|
1
|
|
|
<?php |
|
2
|
|
|
/* vim: set ts=4 sw=4: */ |
|
3
|
|
|
// +----------------------------------------------------------------------+ |
|
4
|
|
|
// | PHP Version 4 | |
|
5
|
|
|
// +----------------------------------------------------------------------+ |
|
6
|
|
|
// | Copyright (c) 1997-2003 The PHP Group | |
|
7
|
|
|
// +----------------------------------------------------------------------+ |
|
8
|
|
|
// | This library is free software; you can redistribute it and/or | |
|
9
|
|
|
// | modify it under the terms of the GNU Lesser General Public | |
|
10
|
|
|
// | License as published by the Free Software Foundation; either | |
|
11
|
|
|
// | version 2.1 of the License, or (at your option) any later version. | |
|
12
|
|
|
// | | |
|
13
|
|
|
// | This library is distributed in the hope that it will be useful, | |
|
14
|
|
|
// | but WITHOUT ANY WARRANTY; without even the implied warranty of | |
|
15
|
|
|
// | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
|
16
|
|
|
// | Lesser General Public License for more details. | |
|
17
|
|
|
// | | |
|
18
|
|
|
// | You should have received a copy of the GNU Lesser General Public | |
|
19
|
|
|
// | License along with this library; if not, write to the Free Software | |
|
20
|
|
|
// | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, | |
|
21
|
|
|
// | MA 02110-1301 USA | |
|
22
|
|
|
// +----------------------------------------------------------------------+ |
|
23
|
|
|
// | Author: Vincent Blavet <[email protected]> | |
|
24
|
|
|
// +----------------------------------------------------------------------+ |
|
25
|
|
|
// |
|
26
|
|
|
// $Id: Zip.php,v 1.2 2005/11/21 06:51:57 vblavet Exp $ |
|
27
|
|
|
|
|
28
|
|
|
// require_once 'PEAR.php'; // GIJ |
|
29
|
|
|
|
|
30
|
|
|
// ----- Constants |
|
31
|
|
|
define('ARCHIVE_ZIP_READ_BLOCK_SIZE', 2048); |
|
32
|
|
|
|
|
33
|
|
|
// ----- File list separator |
|
34
|
|
|
define('ARCHIVE_ZIP_SEPARATOR', ','); |
|
35
|
|
|
|
|
36
|
|
|
// ----- Optional static temporary directory |
|
37
|
|
|
// By default temporary files are generated in the script current |
|
38
|
|
|
// path. |
|
39
|
|
|
// If defined : |
|
40
|
|
|
// - MUST BE terminated by a '/'. |
|
41
|
|
|
// - MUST be a valid, already created directory |
|
42
|
|
|
// Samples : |
|
43
|
|
|
// define('ARCHIVE_ZIP_TEMPORARY_DIR', '/temp/' ); |
|
44
|
|
|
// define('ARCHIVE_ZIP_TEMPORARY_DIR', 'C:/Temp/' ); |
|
45
|
|
|
define('ARCHIVE_ZIP_TEMPORARY_DIR', ''); |
|
46
|
|
|
|
|
47
|
|
|
// ----- Error codes |
|
48
|
|
|
define('ARCHIVE_ZIP_ERR_NO_ERROR', 0); |
|
49
|
|
|
define('ARCHIVE_ZIP_ERR_WRITE_OPEN_FAIL', -1); |
|
50
|
|
|
define('ARCHIVE_ZIP_ERR_READ_OPEN_FAIL', -2); |
|
51
|
|
|
define('ARCHIVE_ZIP_ERR_INVALID_PARAMETER', -3); |
|
52
|
|
|
define('ARCHIVE_ZIP_ERR_MISSING_FILE', -4); |
|
53
|
|
|
define('ARCHIVE_ZIP_ERR_FILENAME_TOO_LONG', -5); |
|
54
|
|
|
define('ARCHIVE_ZIP_ERR_INVALID_ZIP', -6); |
|
55
|
|
|
define('ARCHIVE_ZIP_ERR_BAD_EXTRACTED_FILE', -7); |
|
56
|
|
|
define('ARCHIVE_ZIP_ERR_DIR_CREATE_FAIL', -8); |
|
57
|
|
|
define('ARCHIVE_ZIP_ERR_BAD_EXTENSION', -9); |
|
58
|
|
|
define('ARCHIVE_ZIP_ERR_BAD_FORMAT', -10); |
|
59
|
|
|
define('ARCHIVE_ZIP_ERR_DELETE_FILE_FAIL', -11); |
|
60
|
|
|
define('ARCHIVE_ZIP_ERR_RENAME_FILE_FAIL', -12); |
|
61
|
|
|
define('ARCHIVE_ZIP_ERR_BAD_CHECKSUM', -13); |
|
62
|
|
|
define('ARCHIVE_ZIP_ERR_INVALID_ARCHIVE_ZIP', -14); |
|
63
|
|
|
define('ARCHIVE_ZIP_ERR_MISSING_OPTION_VALUE', -15); |
|
64
|
|
|
define('ARCHIVE_ZIP_ERR_INVALID_PARAM_VALUE', -16); |
|
65
|
|
|
|
|
66
|
|
|
// ----- Warning codes |
|
67
|
|
|
define('ARCHIVE_ZIP_WARN_NO_WARNING', 0); |
|
68
|
|
|
define('ARCHIVE_ZIP_WARN_FILE_EXIST', 1); |
|
69
|
|
|
|
|
70
|
|
|
// ----- Methods parameters |
|
71
|
|
|
define('ARCHIVE_ZIP_PARAM_PATH', 'path'); |
|
72
|
|
|
define('ARCHIVE_ZIP_PARAM_ADD_PATH', 'add_path'); |
|
73
|
|
|
define('ARCHIVE_ZIP_PARAM_REMOVE_PATH', 'remove_path'); |
|
74
|
|
|
define('ARCHIVE_ZIP_PARAM_REMOVE_ALL_PATH', 'remove_all_path'); |
|
75
|
|
|
define('ARCHIVE_ZIP_PARAM_SET_CHMOD', 'set_chmod'); |
|
76
|
|
|
define('ARCHIVE_ZIP_PARAM_EXTRACT_AS_STRING', 'extract_as_string'); |
|
77
|
|
|
define('ARCHIVE_ZIP_PARAM_NO_COMPRESSION', 'no_compression'); |
|
78
|
|
|
define('ARCHIVE_ZIP_PARAM_BY_NAME', 'by_name'); |
|
79
|
|
|
define('ARCHIVE_ZIP_PARAM_BY_INDEX', 'by_index'); |
|
80
|
|
|
define('ARCHIVE_ZIP_PARAM_BY_EREG', 'by_ereg'); |
|
81
|
|
|
define('ARCHIVE_ZIP_PARAM_BY_PREG', 'by_preg'); |
|
82
|
|
|
|
|
83
|
|
|
define('ARCHIVE_ZIP_PARAM_PRE_EXTRACT', 'callback_pre_extract'); |
|
84
|
|
|
define('ARCHIVE_ZIP_PARAM_POST_EXTRACT', 'callback_post_extract'); |
|
85
|
|
|
define('ARCHIVE_ZIP_PARAM_PRE_ADD', 'callback_pre_add'); |
|
86
|
|
|
define('ARCHIVE_ZIP_PARAM_POST_ADD', 'callback_post_add'); |
|
87
|
|
|
|
|
88
|
|
|
/** |
|
89
|
|
|
* Class for manipulating zip archive files |
|
90
|
|
|
* |
|
91
|
|
|
* A class which provided common methods to manipulate ZIP formatted |
|
92
|
|
|
* archive files. |
|
93
|
|
|
* It provides creation, extraction, deletion and add features. |
|
94
|
|
|
* |
|
95
|
|
|
* @author Vincent Blavet <[email protected]> |
|
96
|
|
|
* @version $Revision: 1.2 $ |
|
97
|
|
|
* @package Archive_Zip |
|
98
|
|
|
* @category Archive |
|
99
|
|
|
*/ |
|
100
|
|
|
class Archive_Zip |
|
101
|
|
|
{ |
|
102
|
|
|
/** |
|
103
|
|
|
* The filename of the zip archive. |
|
104
|
|
|
* |
|
105
|
|
|
* @var string Name of the Zip file |
|
106
|
|
|
*/ |
|
107
|
|
|
public $_zipname = ''; |
|
108
|
|
|
|
|
109
|
|
|
/** |
|
110
|
|
|
* File descriptor of the opened Zip file. |
|
111
|
|
|
* |
|
112
|
|
|
* @var int Internal zip file descriptor |
|
113
|
|
|
*/ |
|
114
|
|
|
public $_zip_fd = 0; |
|
115
|
|
|
|
|
116
|
|
|
/** |
|
117
|
|
|
* @var int last error code |
|
118
|
|
|
*/ |
|
119
|
|
|
public $_error_code = 1; |
|
120
|
|
|
|
|
121
|
|
|
/** |
|
122
|
|
|
* @var string Last error description |
|
123
|
|
|
*/ |
|
124
|
|
|
public $_error_string = ''; |
|
125
|
|
|
|
|
126
|
|
|
// {{{ constructor |
|
127
|
|
|
/** |
|
128
|
|
|
* Archive_Zip Class constructor. This flavour of the constructor only |
|
129
|
|
|
* declare a new Archive_Zip object, identifying it by the name of the |
|
130
|
|
|
* zip file. |
|
131
|
|
|
* |
|
132
|
|
|
* @param string $p_zipname The name of the zip archive to create |
|
133
|
|
|
* @access public |
|
134
|
|
|
*/ |
|
135
|
|
|
public function __construct($p_zipname) |
|
136
|
|
|
{ |
|
137
|
|
|
|
|
138
|
|
|
// ----- Check the zlib |
|
139
|
|
|
/* if (!extension_loaded('zlib')) { |
|
140
|
|
|
PEAR::loadExtension('zlib'); |
|
141
|
|
|
}*/ // GIJ |
|
142
|
|
|
if (!extension_loaded('zlib')) { |
|
143
|
|
|
die("The extension 'zlib' couldn't be found.\n" . 'Please make sure your version of PHP was built ' . "with 'zlib' support.\n"); |
|
144
|
|
|
} |
|
145
|
|
|
|
|
146
|
|
|
// ----- Set the attributes |
|
147
|
|
|
$this->_zipname = $p_zipname; |
|
148
|
|
|
$this->_zip_fd = 0; |
|
149
|
|
|
} |
|
150
|
|
|
// }}} |
|
151
|
|
|
|
|
152
|
|
|
// {{{ create() |
|
153
|
|
|
/** |
|
154
|
|
|
* This method creates a Zip Archive with the filename set with |
|
155
|
|
|
* the constructor. |
|
156
|
|
|
* The files and directories indicated in $p_filelist |
|
157
|
|
|
* are added in the archive. |
|
158
|
|
|
* When a directory is in the list, the directory and its content is added |
|
159
|
|
|
* in the archive. |
|
160
|
|
|
* The methods takes a variable list of parameters in $p_params. |
|
161
|
|
|
* The supported parameters for this method are : |
|
162
|
|
|
* 'add_path' : Add a path to the archived files. |
|
163
|
|
|
* 'remove_path' : Remove the specified 'root' path of the archived files. |
|
164
|
|
|
* 'remove_all_path' : Remove all the path of the archived files. |
|
165
|
|
|
* 'no_compression' : The archived files will not be compressed. |
|
166
|
|
|
* |
|
167
|
|
|
* @access public |
|
168
|
|
|
* @param mixed $p_filelist The list of the files or folders to add. |
|
169
|
|
|
* It can be a string with filenames separated |
|
170
|
|
|
* by a comma, or an array of filenames. |
|
171
|
|
|
* @param mixed $p_params An array of variable parameters and values. |
|
172
|
|
|
* @return mixed An array of file description on success, |
|
173
|
|
|
* an error code on error |
|
174
|
|
|
*/ |
|
175
|
|
|
public function create($p_filelist, $p_params = 0) |
|
176
|
|
|
{ |
|
177
|
|
|
$this->_errorReset(); |
|
178
|
|
|
|
|
179
|
|
|
// ----- Set default values |
|
180
|
|
|
if ($p_params === 0) { |
|
181
|
|
|
$p_params = array(); |
|
182
|
|
|
} |
|
183
|
|
|
if ($this->_check_parameters($p_params, array( |
|
184
|
|
|
'no_compression' => false, |
|
185
|
|
|
'add_path' => '', |
|
186
|
|
|
'remove_path' => '', |
|
187
|
|
|
'remove_all_path' => false |
|
188
|
|
|
)) != 1 |
|
189
|
|
|
) { |
|
190
|
|
|
return 0; |
|
191
|
|
|
} |
|
192
|
|
|
|
|
193
|
|
|
// ----- Look if the $p_filelist is really an array |
|
194
|
|
|
$p_result_list = array(); |
|
195
|
|
View Code Duplication |
if (is_array($p_filelist)) { |
|
|
|
|
|
|
196
|
|
|
$v_result = $this->_create($p_filelist, $p_result_list, $p_params); |
|
197
|
|
|
} // ----- Look if the $p_filelist is a string |
|
198
|
|
|
elseif (is_string($p_filelist)) { |
|
199
|
|
|
// ----- Create a list with the elements from the string |
|
200
|
|
|
$v_list = explode(ARCHIVE_ZIP_SEPARATOR, $p_filelist); |
|
201
|
|
|
|
|
202
|
|
|
$v_result = $this->_create($v_list, $p_result_list, $p_params); |
|
203
|
|
|
} // ----- Invalid variable |
|
204
|
|
|
else { |
|
205
|
|
|
$this->_errorLog(ARCHIVE_ZIP_ERR_INVALID_PARAMETER, 'Invalid variable type p_filelist'); |
|
206
|
|
|
$v_result = ARCHIVE_ZIP_ERR_INVALID_PARAMETER; |
|
207
|
|
|
} |
|
208
|
|
|
|
|
209
|
|
|
if ($v_result != 1) { |
|
210
|
|
|
return 0; |
|
211
|
|
|
} |
|
212
|
|
|
|
|
213
|
|
|
return $p_result_list; |
|
214
|
|
|
} |
|
215
|
|
|
// }}} |
|
216
|
|
|
|
|
217
|
|
|
// {{{ add() |
|
218
|
|
|
/** |
|
219
|
|
|
* This method add files or directory in an existing Zip Archive. |
|
220
|
|
|
* If the Zip Archive does not exist it is created. |
|
221
|
|
|
* The files and directories to add are indicated in $p_filelist. |
|
222
|
|
|
* When a directory is in the list, the directory and its content is added |
|
223
|
|
|
* in the archive. |
|
224
|
|
|
* The methods takes a variable list of parameters in $p_params. |
|
225
|
|
|
* The supported parameters for this method are : |
|
226
|
|
|
* 'add_path' : Add a path to the archived files. |
|
227
|
|
|
* 'remove_path' : Remove the specified 'root' path of the archived files. |
|
228
|
|
|
* 'remove_all_path' : Remove all the path of the archived files. |
|
229
|
|
|
* 'no_compression' : The archived files will not be compressed. |
|
230
|
|
|
* 'callback_pre_add' : A callback function that will be called before |
|
231
|
|
|
* each entry archiving. |
|
232
|
|
|
* 'callback_post_add' : A callback function that will be called after |
|
233
|
|
|
* each entry archiving. |
|
234
|
|
|
* |
|
235
|
|
|
* @access public |
|
236
|
|
|
* @param mixed $p_filelist The list of the files or folders to add. |
|
237
|
|
|
* It can be a string with filenames separated |
|
238
|
|
|
* by a comma, or an array of filenames. |
|
239
|
|
|
* @param mixed $p_params An array of variable parameters and values. |
|
240
|
|
|
* @return mixed An array of file description on success, |
|
241
|
|
|
* 0 on an unrecoverable failure, an error code is logged. |
|
242
|
|
|
*/ |
|
243
|
|
|
public function add($p_filelist, $p_params = 0) |
|
244
|
|
|
{ |
|
245
|
|
|
$this->_errorReset(); |
|
246
|
|
|
|
|
247
|
|
|
// ----- Set default values |
|
248
|
|
|
if ($p_params === 0) { |
|
249
|
|
|
$p_params = array(); |
|
250
|
|
|
} |
|
251
|
|
|
if ($this->_check_parameters($p_params, array( |
|
252
|
|
|
'no_compression' => false, |
|
253
|
|
|
'add_path' => '', |
|
254
|
|
|
'remove_path' => '', |
|
255
|
|
|
'remove_all_path' => false, |
|
256
|
|
|
'callback_pre_add' => '', |
|
257
|
|
|
'callback_post_add' => '' |
|
258
|
|
|
)) != 1 |
|
259
|
|
|
) { |
|
260
|
|
|
return 0; |
|
261
|
|
|
} |
|
262
|
|
|
|
|
263
|
|
|
// ----- Look if the $p_filelist is really an array |
|
264
|
|
|
$p_result_list = array(); |
|
265
|
|
View Code Duplication |
if (is_array($p_filelist)) { |
|
|
|
|
|
|
266
|
|
|
// ----- Call the create fct |
|
267
|
|
|
$v_result = $this->_add($p_filelist, $p_result_list, $p_params); |
|
268
|
|
|
} // ----- Look if the $p_filelist is a string |
|
269
|
|
|
elseif (is_string($p_filelist)) { |
|
270
|
|
|
// ----- Create a list with the elements from the string |
|
271
|
|
|
$v_list = explode(ARCHIVE_ZIP_SEPARATOR, $p_filelist); |
|
272
|
|
|
|
|
273
|
|
|
// ----- Call the create fct |
|
274
|
|
|
$v_result = $this->_add($v_list, $p_result_list, $p_params); |
|
275
|
|
|
} // ----- Invalid variable |
|
276
|
|
|
else { |
|
277
|
|
|
$this->_errorLog(ARCHIVE_ZIP_ERR_INVALID_PARAMETER, 'add() : Invalid variable type p_filelist'); |
|
278
|
|
|
$v_result = ARCHIVE_ZIP_ERR_INVALID_PARAMETER; |
|
279
|
|
|
} |
|
280
|
|
|
|
|
281
|
|
|
if ($v_result != 1) { |
|
282
|
|
|
return 0; |
|
283
|
|
|
} |
|
284
|
|
|
|
|
285
|
|
|
// ----- Return the result list |
|
286
|
|
|
return $p_result_list; |
|
287
|
|
|
} |
|
288
|
|
|
// }}} |
|
289
|
|
|
|
|
290
|
|
|
// {{{ listContent() |
|
291
|
|
|
/** |
|
292
|
|
|
* This method gives the names and properties of the files and directories |
|
293
|
|
|
* which are present in the zip archive. |
|
294
|
|
|
* The properties of each entries in the list are : |
|
295
|
|
|
* filename : Name of the file. |
|
296
|
|
|
* For create() or add() it's the filename given by the user. |
|
297
|
|
|
* For an extract() it's the filename of the extracted file. |
|
298
|
|
|
* stored_filename : Name of the file / directory stored in the archive. |
|
299
|
|
|
* size : Size of the stored file. |
|
300
|
|
|
* compressed_size : Size of the file's data compressed in the archive |
|
301
|
|
|
* (without the zip headers overhead) |
|
302
|
|
|
* mtime : Last known modification date of the file (UNIX timestamp) |
|
303
|
|
|
* comment : Comment associated with the file |
|
304
|
|
|
* folder : true | false (indicates if the entry is a folder) |
|
305
|
|
|
* index : index of the file in the archive (-1 when not available) |
|
306
|
|
|
* status : status of the action on the entry (depending of the action) : |
|
307
|
|
|
* Values are : |
|
308
|
|
|
* ok : OK ! |
|
309
|
|
|
* filtered : the file/dir was not extracted (filtered by user) |
|
310
|
|
|
* already_a_directory : the file can't be extracted because a |
|
311
|
|
|
* directory with the same name already |
|
312
|
|
|
* exists |
|
313
|
|
|
* write_protected : the file can't be extracted because a file |
|
314
|
|
|
* with the same name already exists and is |
|
315
|
|
|
* write protected |
|
316
|
|
|
* newer_exist : the file was not extracted because a newer |
|
317
|
|
|
* file already exists |
|
318
|
|
|
* path_creation_fail : the file is not extracted because the |
|
319
|
|
|
* folder does not exists and can't be |
|
320
|
|
|
* created |
|
321
|
|
|
* write_error : the file was not extracted because there was a |
|
322
|
|
|
* error while writing the file |
|
323
|
|
|
* read_error : the file was not extracted because there was a |
|
324
|
|
|
* error while reading the file |
|
325
|
|
|
* invalid_header : the file was not extracted because of an |
|
326
|
|
|
* archive format error (bad file header) |
|
327
|
|
|
* Note that each time a method can continue operating when there |
|
328
|
|
|
* is an error on a single file, the error is only logged in the file status. |
|
329
|
|
|
* |
|
330
|
|
|
* @access public |
|
331
|
|
|
* @return mixed An array of file description on success, |
|
332
|
|
|
* 0 on an unrecoverable failure, an error code is logged. |
|
333
|
|
|
*/ |
|
334
|
|
|
public function listContent() |
|
335
|
|
|
{ |
|
336
|
|
|
$this->_errorReset(); |
|
337
|
|
|
|
|
338
|
|
|
// ----- Check archive |
|
339
|
|
|
if (!$this->_checkFormat()) { |
|
340
|
|
|
return 0; |
|
341
|
|
|
} |
|
342
|
|
|
|
|
343
|
|
|
$v_list = array(); |
|
344
|
|
|
if ($this->_list($v_list) != 1) { |
|
345
|
|
|
unset($v_list); |
|
346
|
|
|
|
|
347
|
|
|
return 0; |
|
348
|
|
|
} |
|
349
|
|
|
|
|
350
|
|
|
return $v_list; |
|
351
|
|
|
} |
|
352
|
|
|
// }}} |
|
353
|
|
|
|
|
354
|
|
|
// {{{ extract() |
|
355
|
|
|
/** |
|
356
|
|
|
* This method extract the files and folders which are in the zip archive. |
|
357
|
|
|
* It can extract all the archive or a part of the archive by using filter |
|
358
|
|
|
* feature (extract by name, by index, by ereg, by preg). The extraction |
|
359
|
|
|
* can occur in the current path or an other path. |
|
360
|
|
|
* All the advanced features are activated by the use of variable |
|
361
|
|
|
* parameters. |
|
362
|
|
|
* The return value is an array of entry descriptions which gives |
|
363
|
|
|
* information on extracted files (See listContent()). |
|
364
|
|
|
* The method may return a success value (an array) even if some files |
|
365
|
|
|
* are not correctly extracted (see the file status in listContent()). |
|
366
|
|
|
* The supported variable parameters for this method are : |
|
367
|
|
|
* 'add_path' : Path where the files and directories are to be extracted |
|
368
|
|
|
* 'remove_path' : First part ('root' part) of the memorized path |
|
369
|
|
|
* (if similar) to remove while extracting. |
|
370
|
|
|
* 'remove_all_path' : Remove all the memorized path while extracting. |
|
371
|
|
|
* 'extract_as_string' : |
|
372
|
|
|
* 'set_chmod' : After the extraction of the file the indicated mode |
|
373
|
|
|
* will be set. |
|
374
|
|
|
* 'by_name' : It can be a string with file/dir names separated by ',', |
|
375
|
|
|
* or an array of file/dir names to extract from the archive. |
|
376
|
|
|
* 'by_index' : A string with range of indexes separated by ',', |
|
377
|
|
|
* (sample "1,3-5,12"). |
|
378
|
|
|
* 'by_ereg' : A regular expression (ereg) that must match the extracted |
|
379
|
|
|
* filename. |
|
380
|
|
|
* 'by_preg' : A regular expression (preg) that must match the extracted |
|
381
|
|
|
* filename. |
|
382
|
|
|
* 'callback_pre_extract' : A callback function that will be called before |
|
383
|
|
|
* each entry extraction. |
|
384
|
|
|
* 'callback_post_extract' : A callback function that will be called after |
|
385
|
|
|
* each entry extraction. |
|
386
|
|
|
* |
|
387
|
|
|
* @access public |
|
388
|
|
|
* @param mixed $p_params An array of variable parameters and values. |
|
389
|
|
|
* @return mixed An array of file description on success, |
|
390
|
|
|
* 0 on an unrecoverable failure, an error code is logged. |
|
391
|
|
|
*/ |
|
392
|
|
|
public function extract($p_params = 0) |
|
393
|
|
|
{ |
|
394
|
|
|
$this->_errorReset(); |
|
395
|
|
|
|
|
396
|
|
|
// ----- Check archive |
|
397
|
|
|
if (!$this->_checkFormat()) { |
|
398
|
|
|
return 0; |
|
399
|
|
|
} |
|
400
|
|
|
|
|
401
|
|
|
// ----- Set default values |
|
402
|
|
|
if ($p_params === 0) { |
|
403
|
|
|
$p_params = array(); |
|
404
|
|
|
} |
|
405
|
|
|
if ($this->_check_parameters($p_params, array( |
|
406
|
|
|
'extract_as_string' => false, |
|
407
|
|
|
'add_path' => '', |
|
408
|
|
|
'remove_path' => '', |
|
409
|
|
|
'remove_all_path' => false, |
|
410
|
|
|
'callback_pre_extract' => '', |
|
411
|
|
|
'callback_post_extract' => '', |
|
412
|
|
|
'set_chmod' => 0, |
|
413
|
|
|
'by_name' => '', |
|
414
|
|
|
'by_index' => '', |
|
415
|
|
|
'by_ereg' => '', |
|
416
|
|
|
'by_preg' => '' |
|
417
|
|
|
)) != 1 |
|
418
|
|
|
) { |
|
419
|
|
|
return 0; |
|
420
|
|
|
} |
|
421
|
|
|
|
|
422
|
|
|
// ----- Call the extracting fct |
|
423
|
|
|
$v_list = array(); |
|
424
|
|
|
if ($this->_extractByRule($v_list, $p_params) != 1) { |
|
425
|
|
|
unset($v_list); |
|
426
|
|
|
|
|
427
|
|
|
return 0; |
|
428
|
|
|
} |
|
429
|
|
|
|
|
430
|
|
|
return $v_list; |
|
431
|
|
|
} |
|
432
|
|
|
// }}} |
|
433
|
|
|
|
|
434
|
|
|
// {{{ delete() |
|
435
|
|
|
/** |
|
436
|
|
|
* This methods delete archive entries in the zip archive. |
|
437
|
|
|
* Notice that at least one filtering rule (set by the variable parameter |
|
438
|
|
|
* list) must be set. |
|
439
|
|
|
* Also notice that if you delete a folder entry, only the folder entry |
|
440
|
|
|
* is deleted, not all the files bellonging to this folder. |
|
441
|
|
|
* The supported variable parameters for this method are : |
|
442
|
|
|
* 'by_name' : It can be a string with file/dir names separated by ',', |
|
443
|
|
|
* or an array of file/dir names to delete from the archive. |
|
444
|
|
|
* 'by_index' : A string with range of indexes separated by ',', |
|
445
|
|
|
* (sample "1,3-5,12"). |
|
446
|
|
|
* 'by_ereg' : A regular expression (ereg) that must match the extracted |
|
447
|
|
|
* filename. |
|
448
|
|
|
* 'by_preg' : A regular expression (preg) that must match the extracted |
|
449
|
|
|
* filename. |
|
450
|
|
|
* |
|
451
|
|
|
* @access public |
|
452
|
|
|
* @param mixed $p_params An array of variable parameters and values. |
|
453
|
|
|
* @return mixed An array of file description on success, |
|
454
|
|
|
* 0 on an unrecoverable failure, an error code is logged. |
|
455
|
|
|
*/ |
|
456
|
|
|
public function delete($p_params) |
|
457
|
|
|
{ |
|
458
|
|
|
$this->_errorReset(); |
|
459
|
|
|
|
|
460
|
|
|
// ----- Check archive |
|
461
|
|
|
if (!$this->_checkFormat()) { |
|
462
|
|
|
return 0; |
|
463
|
|
|
} |
|
464
|
|
|
|
|
465
|
|
|
// ----- Set default values |
|
466
|
|
|
if ($this->_check_parameters($p_params, array( |
|
467
|
|
|
'by_name' => '', |
|
468
|
|
|
'by_index' => '', |
|
469
|
|
|
'by_ereg' => '', |
|
470
|
|
|
'by_preg' => '' |
|
471
|
|
|
)) != 1 |
|
472
|
|
|
) { |
|
473
|
|
|
return 0; |
|
474
|
|
|
} |
|
475
|
|
|
|
|
476
|
|
|
// ----- Check that at least one rule is set |
|
477
|
|
|
if (($p_params['by_name'] == '') && ($p_params['by_index'] == '') && ($p_params['by_ereg'] == '') && ($p_params['by_preg'] == '')) { |
|
478
|
|
|
$this->_errorLog(ARCHIVE_ZIP_ERR_INVALID_PARAMETER, 'At least one filtering rule must' . ' be set as parameter'); |
|
479
|
|
|
|
|
480
|
|
|
return 0; |
|
481
|
|
|
} |
|
482
|
|
|
|
|
483
|
|
|
// ----- Call the delete fct |
|
484
|
|
|
$v_list = array(); |
|
485
|
|
|
if ($this->_deleteByRule($v_list, $p_params) != 1) { |
|
486
|
|
|
unset($v_list); |
|
487
|
|
|
|
|
488
|
|
|
return 0; |
|
489
|
|
|
} |
|
490
|
|
|
|
|
491
|
|
|
return $v_list; |
|
492
|
|
|
} |
|
493
|
|
|
// }}} |
|
494
|
|
|
|
|
495
|
|
|
// {{{ properties() |
|
496
|
|
|
/** |
|
497
|
|
|
* This method gives the global properties of the archive. |
|
498
|
|
|
* The properties are : |
|
499
|
|
|
* nb : Number of files in the archive |
|
500
|
|
|
* comment : Comment associated with the archive file |
|
501
|
|
|
* status : not_exist, ok |
|
502
|
|
|
* |
|
503
|
|
|
* @access public |
|
504
|
|
|
* @return mixed An array with the global properties or 0 on error. |
|
505
|
|
|
* @internal param mixed $p_params {Description} |
|
506
|
|
|
*/ |
|
507
|
|
|
public function properties() |
|
508
|
|
|
{ |
|
509
|
|
|
$this->_errorReset(); |
|
510
|
|
|
|
|
511
|
|
|
// ----- Check archive |
|
512
|
|
|
if (!$this->_checkFormat()) { |
|
513
|
|
|
return 0; |
|
514
|
|
|
} |
|
515
|
|
|
|
|
516
|
|
|
// ----- Default properties |
|
517
|
|
|
$v_prop = array(); |
|
518
|
|
|
$v_prop['comment'] = ''; |
|
519
|
|
|
$v_prop['nb'] = 0; |
|
520
|
|
|
$v_prop['status'] = 'not_exist'; |
|
521
|
|
|
|
|
522
|
|
|
// ----- Look if file exists |
|
523
|
|
|
if (@is_file($this->_zipname)) { |
|
524
|
|
|
// ----- Open the zip file |
|
525
|
|
|
if (($this->_zip_fd = @fopen($this->_zipname, 'rb')) == 0) { |
|
526
|
|
|
$this->_errorLog(ARCHIVE_ZIP_ERR_READ_OPEN_FAIL, 'Unable to open archive \'' . $this->_zipname . '\' in binary read mode'); |
|
527
|
|
|
|
|
528
|
|
|
return 0; |
|
529
|
|
|
} |
|
530
|
|
|
|
|
531
|
|
|
// ----- Read the central directory informations |
|
532
|
|
|
$v_central_dir = array(); |
|
533
|
|
|
if (($v_result = $this->_readEndCentralDir($v_central_dir)) != 1) { |
|
534
|
|
|
return 0; |
|
535
|
|
|
} |
|
536
|
|
|
|
|
537
|
|
|
$this->_closeFd(); |
|
538
|
|
|
|
|
539
|
|
|
// ----- Set the user attributes |
|
540
|
|
|
$v_prop['comment'] = $v_central_dir['comment']; |
|
541
|
|
|
$v_prop['nb'] = $v_central_dir['entries']; |
|
542
|
|
|
$v_prop['status'] = 'ok'; |
|
543
|
|
|
} |
|
544
|
|
|
|
|
545
|
|
|
return $v_prop; |
|
546
|
|
|
} |
|
547
|
|
|
// }}} |
|
548
|
|
|
|
|
549
|
|
|
// {{{ duplicate() |
|
550
|
|
|
/** |
|
551
|
|
|
* This method creates an archive by copying the content of an other one. |
|
552
|
|
|
* If the archive already exist, it is replaced by the new one without |
|
553
|
|
|
* any warning. |
|
554
|
|
|
* |
|
555
|
|
|
* @access public |
|
556
|
|
|
* @param mixed $p_archive It can be a valid Archive_Zip object or |
|
557
|
|
|
* the filename of a valid zip archive. |
|
558
|
|
|
* @return integer 1 on success, 0 on failure. |
|
559
|
|
|
*/ |
|
560
|
|
|
public function duplicate($p_archive) |
|
561
|
|
|
{ |
|
562
|
|
|
$this->_errorReset(); |
|
563
|
|
|
|
|
564
|
|
|
// ----- Look if the $p_archive is a Archive_Zip object |
|
565
|
|
|
if (is_object($p_archive) && (strtolower(get_class($p_archive)) === 'archive_zip')) { |
|
566
|
|
|
$v_result = $this->_duplicate($p_archive->_zipname); |
|
567
|
|
|
} // ----- Look if the $p_archive is a string (so a filename) |
|
568
|
|
|
elseif (is_string($p_archive)) { |
|
569
|
|
|
// ----- Check that $p_archive is a valid zip file |
|
570
|
|
|
// TBC : Should also check the archive format |
|
571
|
|
|
if (!is_file($p_archive)) { |
|
572
|
|
|
$this->_errorLog(ARCHIVE_ZIP_ERR_MISSING_FILE, "No file with filename '" . $p_archive . "'"); |
|
573
|
|
|
$v_result = ARCHIVE_ZIP_ERR_MISSING_FILE; |
|
574
|
|
|
} else { |
|
575
|
|
|
$v_result = $this->_duplicate($p_archive); |
|
576
|
|
|
} |
|
577
|
|
|
} // ----- Invalid variable |
|
578
|
|
|
else { |
|
579
|
|
|
$this->_errorLog(ARCHIVE_ZIP_ERR_INVALID_PARAMETER, 'Invalid variable type p_archive_to_add'); |
|
580
|
|
|
$v_result = ARCHIVE_ZIP_ERR_INVALID_PARAMETER; |
|
581
|
|
|
} |
|
582
|
|
|
|
|
583
|
|
|
return $v_result; |
|
584
|
|
|
} |
|
585
|
|
|
// }}} |
|
586
|
|
|
|
|
587
|
|
|
// {{{ merge() |
|
588
|
|
|
/** |
|
589
|
|
|
* This method merge a valid zip archive at the end of the |
|
590
|
|
|
* archive identified by the Archive_Zip object. |
|
591
|
|
|
* If the archive ($this) does not exist, the merge becomes a duplicate. |
|
592
|
|
|
* If the archive to add does not exist, the merge is a success. |
|
593
|
|
|
* |
|
594
|
|
|
* @access public |
|
595
|
|
|
* @param mixed $p_archive_to_add It can be a valid Archive_Zip object or |
|
596
|
|
|
* the filename of a valid zip archive. |
|
597
|
|
|
* @return integer 1 on success, 0 on failure. |
|
598
|
|
|
*/ |
|
599
|
|
|
public function merge($p_archive_to_add) |
|
600
|
|
|
{ |
|
601
|
|
|
$v_result = 1; |
|
|
|
|
|
|
602
|
|
|
$this->_errorReset(); |
|
603
|
|
|
|
|
604
|
|
|
// ----- Check archive |
|
605
|
|
|
if (!$this->_checkFormat()) { |
|
606
|
|
|
return 0; |
|
607
|
|
|
} |
|
608
|
|
|
|
|
609
|
|
|
// ----- Look if the $p_archive_to_add is a Archive_Zip object |
|
610
|
|
|
if (is_object($p_archive_to_add) && (strtolower(get_class($p_archive_to_add)) === 'archive_zip')) { |
|
611
|
|
|
$v_result = $this->_merge($p_archive_to_add); |
|
612
|
|
|
} // ----- Look if the $p_archive_to_add is a string (so a filename) |
|
613
|
|
|
elseif (is_string($p_archive_to_add)) { |
|
614
|
|
|
// ----- Create a temporary archive |
|
615
|
|
|
$v_object_archive = new Archive_Zip($p_archive_to_add); |
|
616
|
|
|
|
|
617
|
|
|
// ----- Merge the archive |
|
618
|
|
|
$v_result = $this->_merge($v_object_archive); |
|
619
|
|
|
} // ----- Invalid variable |
|
620
|
|
|
else { |
|
621
|
|
|
$this->_errorLog(ARCHIVE_ZIP_ERR_INVALID_PARAMETER, 'Invalid variable type p_archive_to_add'); |
|
622
|
|
|
$v_result = ARCHIVE_ZIP_ERR_INVALID_PARAMETER; |
|
623
|
|
|
} |
|
624
|
|
|
|
|
625
|
|
|
return $v_result; |
|
626
|
|
|
} |
|
627
|
|
|
// }}} |
|
628
|
|
|
|
|
629
|
|
|
// {{{ errorCode() |
|
630
|
|
|
/** |
|
631
|
|
|
* Method that gives the lastest error code. |
|
632
|
|
|
* |
|
633
|
|
|
* @access public |
|
634
|
|
|
* @return integer The error code value. |
|
635
|
|
|
*/ |
|
636
|
|
|
public function errorCode() |
|
637
|
|
|
{ |
|
638
|
|
|
return $this->_error_code; |
|
639
|
|
|
} |
|
640
|
|
|
// }}} |
|
641
|
|
|
|
|
642
|
|
|
// {{{ errorName() |
|
643
|
|
|
/** |
|
644
|
|
|
* This method gives the latest error code name. |
|
645
|
|
|
* |
|
646
|
|
|
* @access public |
|
647
|
|
|
* @param boolean $p_with_code If true, gives the name and the int value. |
|
648
|
|
|
* @return string The error name. |
|
649
|
|
|
*/ |
|
650
|
|
|
public function errorName($p_with_code = false) |
|
651
|
|
|
{ |
|
652
|
|
|
$v_const_list = get_defined_constants(); |
|
653
|
|
|
|
|
654
|
|
|
// ----- Extract error constants from all const. |
|
655
|
|
|
for (reset($v_const_list); list($v_key, $v_value) = each($v_const_list);) { |
|
656
|
|
|
if (0 === strpos($v_key, 'ARCHIVE_ZIP_ERR_')) { |
|
657
|
|
|
$v_error_list[$v_key] = $v_value; |
|
|
|
|
|
|
658
|
|
|
} |
|
659
|
|
|
} |
|
660
|
|
|
|
|
661
|
|
|
// ----- Search the name form the code value |
|
662
|
|
|
$v_key = array_search($this->_error_code, $v_error_list, true); |
|
|
|
|
|
|
663
|
|
|
$v_value = 'NoName'; |
|
664
|
|
|
if ($v_key != false) { |
|
665
|
|
|
$v_value = $v_key; |
|
666
|
|
|
} |
|
667
|
|
|
|
|
668
|
|
|
if ($p_with_code) { |
|
669
|
|
|
return ($v_value . ' (' . $this->_error_code . ')'); |
|
670
|
|
|
} else { |
|
671
|
|
|
return $v_value; |
|
672
|
|
|
} |
|
673
|
|
|
} |
|
674
|
|
|
// }}} |
|
675
|
|
|
|
|
676
|
|
|
// {{{ errorInfo() |
|
677
|
|
|
/** |
|
678
|
|
|
* This method returns the description associated with the latest error. |
|
679
|
|
|
* |
|
680
|
|
|
* @access public |
|
681
|
|
|
* @param boolean $p_full If set to true gives the description with the |
|
682
|
|
|
* error code, the name and the description. |
|
683
|
|
|
* If set to false gives only the description |
|
684
|
|
|
* and the error code. |
|
685
|
|
|
* @return string The error description. |
|
686
|
|
|
*/ |
|
687
|
|
|
public function errorInfo($p_full = false) |
|
688
|
|
|
{ |
|
689
|
|
|
if ($p_full) { |
|
690
|
|
|
return ($this->errorName(true) . ' : ' . $this->_error_string); |
|
691
|
|
|
} else { |
|
692
|
|
|
return ($this->_error_string . ' [code ' . $this->_error_code . ']'); |
|
693
|
|
|
} |
|
694
|
|
|
} |
|
695
|
|
|
// }}} |
|
696
|
|
|
|
|
697
|
|
|
// ----------------------------------------------------------------------------- |
|
698
|
|
|
// ***** UNDER THIS LINE ARE DEFINED PRIVATE INTERNAL FUNCTIONS ***** |
|
699
|
|
|
// ***** ***** |
|
700
|
|
|
// ***** THESES FUNCTIONS MUST NOT BE USED DIRECTLY ***** |
|
701
|
|
|
// ----------------------------------------------------------------------------- |
|
702
|
|
|
|
|
703
|
|
|
// --------------------------------------------------------------------------- |
|
704
|
|
|
// Function : _checkFormat() |
|
705
|
|
|
// Description : |
|
706
|
|
|
// This method check that the archive exists and is a valid zip archive. |
|
707
|
|
|
// Several level of check exists. (futur) |
|
708
|
|
|
// Parameters : |
|
709
|
|
|
// $p_level : Level of check. Default 0. |
|
710
|
|
|
// 0 : Check the first bytes (magic codes) (default value)) |
|
711
|
|
|
// 1 : 0 + Check the central directory (futur) |
|
712
|
|
|
// 2 : 1 + Check each file header (futur) |
|
713
|
|
|
// Return Values : |
|
714
|
|
|
// true on success, |
|
715
|
|
|
// false on error, the error code is set. |
|
716
|
|
|
// --------------------------------------------------------------------------- |
|
717
|
|
|
/** |
|
718
|
|
|
* Archive_Zip::_checkFormat() |
|
719
|
|
|
* |
|
720
|
|
|
* { Description } |
|
721
|
|
|
* |
|
722
|
|
|
* @param integer $p_level |
|
723
|
|
|
* @return bool |
|
724
|
|
|
*/ |
|
725
|
|
|
public function _checkFormat($p_level = 0) |
|
|
|
|
|
|
726
|
|
|
{ |
|
727
|
|
|
$v_result = true; |
|
728
|
|
|
|
|
729
|
|
|
// ----- Reset the error handler |
|
730
|
|
|
$this->_errorReset(); |
|
731
|
|
|
|
|
732
|
|
|
// ----- Look if the file exits |
|
733
|
|
|
if (!is_file($this->_zipname)) { |
|
734
|
|
|
// ----- Error log |
|
735
|
|
|
$this->_errorLog(ARCHIVE_ZIP_ERR_MISSING_FILE, "Missing archive file '" . $this->_zipname . "'"); |
|
736
|
|
|
|
|
737
|
|
|
return false; |
|
738
|
|
|
} |
|
739
|
|
|
|
|
740
|
|
|
// ----- Check that the file is readeable |
|
741
|
|
|
if (!is_readable($this->_zipname)) { |
|
742
|
|
|
// ----- Error log |
|
743
|
|
|
$this->_errorLog(ARCHIVE_ZIP_ERR_READ_OPEN_FAIL, "Unable to read archive '" . $this->_zipname . "'"); |
|
744
|
|
|
|
|
745
|
|
|
return false; |
|
746
|
|
|
} |
|
747
|
|
|
|
|
748
|
|
|
// ----- Check the magic code |
|
749
|
|
|
// TBC |
|
750
|
|
|
|
|
751
|
|
|
// ----- Check the central header |
|
752
|
|
|
// TBC |
|
753
|
|
|
|
|
754
|
|
|
// ----- Check each file header |
|
755
|
|
|
// TBC |
|
756
|
|
|
|
|
757
|
|
|
// ----- Return |
|
758
|
|
|
return $v_result; |
|
759
|
|
|
} |
|
760
|
|
|
// --------------------------------------------------------------------------- |
|
761
|
|
|
|
|
762
|
|
|
// --------------------------------------------------------------------------- |
|
763
|
|
|
// Function : _create() |
|
764
|
|
|
// Description : |
|
765
|
|
|
// Parameters : |
|
766
|
|
|
// Return Values : |
|
767
|
|
|
// --------------------------------------------------------------------------- |
|
768
|
|
|
/** |
|
769
|
|
|
* Archive_Zip::_create() |
|
770
|
|
|
* |
|
771
|
|
|
* { Description } |
|
772
|
|
|
* @param $p_list |
|
773
|
|
|
* @param $p_result_list |
|
774
|
|
|
* @param $p_params |
|
775
|
|
|
* @return int |
|
776
|
|
|
*/ |
|
777
|
|
|
public function _create($p_list, &$p_result_list, &$p_params) |
|
778
|
|
|
{ |
|
779
|
|
|
$v_result = 1; |
|
|
|
|
|
|
780
|
|
|
$v_list_detail = array(); |
|
|
|
|
|
|
781
|
|
|
|
|
782
|
|
|
$p_add_dir = $p_params['add_path']; |
|
783
|
|
|
$p_remove_dir = $p_params['remove_path']; |
|
784
|
|
|
$p_remove_all_dir = $p_params['remove_all_path']; |
|
785
|
|
|
|
|
786
|
|
|
// ----- Open the file in write mode |
|
787
|
|
|
if (($v_result = $this->_openFd('wb')) != 1) { |
|
788
|
|
|
// ----- Return |
|
789
|
|
|
return $v_result; |
|
790
|
|
|
} |
|
791
|
|
|
|
|
792
|
|
|
// ----- Add the list of files |
|
793
|
|
|
$v_result = $this->_addList($p_list, $p_result_list, $p_add_dir, $p_remove_dir, $p_remove_all_dir, $p_params); |
|
794
|
|
|
|
|
795
|
|
|
// ----- Close |
|
796
|
|
|
$this->_closeFd(); |
|
797
|
|
|
|
|
798
|
|
|
// ----- Return |
|
799
|
|
|
return $v_result; |
|
800
|
|
|
} |
|
801
|
|
|
// --------------------------------------------------------------------------- |
|
802
|
|
|
|
|
803
|
|
|
// --------------------------------------------------------------------------- |
|
804
|
|
|
// Function : _add() |
|
805
|
|
|
// Description : |
|
806
|
|
|
// Parameters : |
|
807
|
|
|
// Return Values : |
|
808
|
|
|
// --------------------------------------------------------------------------- |
|
809
|
|
|
/** |
|
810
|
|
|
* Archive_Zip::_add() |
|
811
|
|
|
* |
|
812
|
|
|
* { Description } |
|
813
|
|
|
* @param $p_list |
|
814
|
|
|
* @param $p_result_list |
|
815
|
|
|
* @param $p_params |
|
816
|
|
|
* @return int |
|
817
|
|
|
*/ |
|
818
|
|
|
public function _add($p_list, &$p_result_list, &$p_params) |
|
819
|
|
|
{ |
|
820
|
|
|
$v_result = 1; |
|
|
|
|
|
|
821
|
|
|
$v_list_detail = array(); |
|
|
|
|
|
|
822
|
|
|
|
|
823
|
|
|
$p_add_dir = $p_params['add_path']; |
|
824
|
|
|
$p_remove_dir = $p_params['remove_path']; |
|
825
|
|
|
$p_remove_all_dir = $p_params['remove_all_path']; |
|
826
|
|
|
|
|
827
|
|
|
// ----- Look if the archive exists or is empty and need to be created |
|
828
|
|
|
if ((!is_file($this->_zipname)) || (filesize($this->_zipname) == 0)) { |
|
829
|
|
|
$v_result = $this->_create($p_list, $p_result_list, $p_params); |
|
830
|
|
|
|
|
831
|
|
|
return $v_result; |
|
832
|
|
|
} |
|
833
|
|
|
|
|
834
|
|
|
// ----- Open the zip file |
|
835
|
|
|
if (($v_result = $this->_openFd('rb')) != 1) { |
|
836
|
|
|
return $v_result; |
|
837
|
|
|
} |
|
838
|
|
|
|
|
839
|
|
|
// ----- Read the central directory informations |
|
840
|
|
|
$v_central_dir = array(); |
|
841
|
|
|
if (($v_result = $this->_readEndCentralDir($v_central_dir)) != 1) { |
|
842
|
|
|
$this->_closeFd(); |
|
843
|
|
|
|
|
844
|
|
|
return $v_result; |
|
845
|
|
|
} |
|
846
|
|
|
|
|
847
|
|
|
// ----- Go to beginning of File |
|
848
|
|
|
@rewind($this->_zip_fd); |
|
|
|
|
|
|
849
|
|
|
|
|
850
|
|
|
// ----- Creates a temporay file |
|
851
|
|
|
$v_zip_temp_name = ARCHIVE_ZIP_TEMPORARY_DIR . uniqid('archive_zip-') . '.tmp'; |
|
852
|
|
|
|
|
853
|
|
|
// ----- Open the temporary file in write mode |
|
854
|
|
View Code Duplication |
if (($v_zip_temp_fd = @fopen($v_zip_temp_name, 'wb')) == 0) { |
|
|
|
|
|
|
855
|
|
|
$this->_closeFd(); |
|
856
|
|
|
|
|
857
|
|
|
$this->_errorLog(ARCHIVE_ZIP_ERR_READ_OPEN_FAIL, 'Unable to open temporary file \'' . $v_zip_temp_name . '\' in binary write mode'); |
|
858
|
|
|
|
|
859
|
|
|
return Archive_Zip::errorCode(); |
|
860
|
|
|
} |
|
861
|
|
|
|
|
862
|
|
|
// ----- Copy the files from the archive to the temporary file |
|
863
|
|
|
// TBC : Here I should better append the file and go back to erase the |
|
864
|
|
|
// central dir |
|
865
|
|
|
$v_size = $v_central_dir['offset']; |
|
866
|
|
|
while ($v_size != 0) { |
|
867
|
|
|
$v_read_size = ($v_size < ARCHIVE_ZIP_READ_BLOCK_SIZE ? $v_size : ARCHIVE_ZIP_READ_BLOCK_SIZE); |
|
868
|
|
|
$v_buffer = fread($this->_zip_fd, $v_read_size); |
|
869
|
|
|
@fwrite($v_zip_temp_fd, $v_buffer, $v_read_size); |
|
|
|
|
|
|
870
|
|
|
$v_size -= $v_read_size; |
|
871
|
|
|
} |
|
872
|
|
|
|
|
873
|
|
|
// ----- Swap the file descriptor |
|
874
|
|
|
// Here is a trick : I swap the temporary fd with the zip fd, in order to |
|
875
|
|
|
// use the following methods on the temporary fil and not the real archive |
|
876
|
|
|
$v_swap = $this->_zip_fd; |
|
877
|
|
|
$this->_zip_fd = $v_zip_temp_fd; |
|
878
|
|
|
$v_zip_temp_fd = $v_swap; |
|
879
|
|
|
|
|
880
|
|
|
// ----- Add the files |
|
881
|
|
|
$v_header_list = array(); |
|
882
|
|
|
if (($v_result = $this->_addFileList($p_list, $v_header_list, $p_add_dir, $p_remove_dir, $p_remove_all_dir, $p_params)) != 1) { |
|
883
|
|
|
fclose($v_zip_temp_fd); |
|
884
|
|
|
$this->_closeFd(); |
|
885
|
|
|
@unlink($v_zip_temp_name); |
|
|
|
|
|
|
886
|
|
|
|
|
887
|
|
|
// ----- Return |
|
888
|
|
|
return $v_result; |
|
889
|
|
|
} |
|
890
|
|
|
|
|
891
|
|
|
// ----- Store the offset of the central dir |
|
892
|
|
|
$v_offset = @ftell($this->_zip_fd); |
|
893
|
|
|
|
|
894
|
|
|
// ----- Copy the block of file headers from the old archive |
|
895
|
|
|
$v_size = $v_central_dir['size']; |
|
896
|
|
View Code Duplication |
while ($v_size != 0) { |
|
|
|
|
|
|
897
|
|
|
$v_read_size = ($v_size < ARCHIVE_ZIP_READ_BLOCK_SIZE ? $v_size : ARCHIVE_ZIP_READ_BLOCK_SIZE); |
|
898
|
|
|
$v_buffer = @fread($v_zip_temp_fd, $v_read_size); |
|
899
|
|
|
@fwrite($this->_zip_fd, $v_buffer, $v_read_size); |
|
|
|
|
|
|
900
|
|
|
$v_size -= $v_read_size; |
|
901
|
|
|
} |
|
902
|
|
|
|
|
903
|
|
|
// ----- Create the Central Dir files header |
|
904
|
|
|
for ($i = 0, $iMax = count($v_header_list); $i < $iMax; ++$i) { |
|
905
|
|
|
// ----- Create the file header |
|
906
|
|
|
if ($v_header_list[$i]['status'] === 'ok') { |
|
907
|
|
|
if (($v_result = $this->_writeCentralFileHeader($v_header_list[$i])) != 1) { |
|
908
|
|
|
fclose($v_zip_temp_fd); |
|
909
|
|
|
$this->_closeFd(); |
|
910
|
|
|
@unlink($v_zip_temp_name); |
|
|
|
|
|
|
911
|
|
|
|
|
912
|
|
|
// ----- Return |
|
913
|
|
|
return $v_result; |
|
914
|
|
|
} |
|
915
|
|
|
++$v_count; |
|
|
|
|
|
|
916
|
|
|
} |
|
917
|
|
|
|
|
918
|
|
|
// ----- Transform the header to a 'usable' info |
|
919
|
|
|
$this->_convertHeader2FileInfo($v_header_list[$i], $p_result_list[$i]); |
|
920
|
|
|
} |
|
921
|
|
|
|
|
922
|
|
|
// ----- Zip file comment |
|
923
|
|
|
$v_comment = ''; |
|
924
|
|
|
|
|
925
|
|
|
// ----- Calculate the size of the central header |
|
926
|
|
|
$v_size = @ftell($this->_zip_fd) - $v_offset; |
|
927
|
|
|
|
|
928
|
|
|
// ----- Create the central dir footer |
|
929
|
|
|
if (($v_result = $this->_writeCentralHeader($v_count + $v_central_dir['entries'], $v_size, $v_offset, $v_comment)) != 1) { |
|
930
|
|
|
// ----- Reset the file list |
|
931
|
|
|
unset($v_header_list); |
|
932
|
|
|
|
|
933
|
|
|
// ----- Return |
|
934
|
|
|
return $v_result; |
|
935
|
|
|
} |
|
936
|
|
|
|
|
937
|
|
|
// ----- Swap back the file descriptor |
|
938
|
|
|
$v_swap = $this->_zip_fd; |
|
939
|
|
|
$this->_zip_fd = $v_zip_temp_fd; |
|
940
|
|
|
$v_zip_temp_fd = $v_swap; |
|
941
|
|
|
|
|
942
|
|
|
// ----- Close |
|
943
|
|
|
$this->_closeFd(); |
|
944
|
|
|
|
|
945
|
|
|
// ----- Close the temporary file |
|
946
|
|
|
@fclose($v_zip_temp_fd); |
|
|
|
|
|
|
947
|
|
|
|
|
948
|
|
|
// ----- Delete the zip file |
|
949
|
|
|
// TBC : I should test the result ... |
|
950
|
|
|
@unlink($this->_zipname); |
|
|
|
|
|
|
951
|
|
|
|
|
952
|
|
|
// ----- Rename the temporary file |
|
953
|
|
|
// TBC : I should test the result ... |
|
954
|
|
|
//@rename($v_zip_temp_name, $this->_zipname); |
|
955
|
|
|
$this->_tool_Rename($v_zip_temp_name, $this->_zipname); |
|
956
|
|
|
|
|
957
|
|
|
// ----- Return |
|
958
|
|
|
return $v_result; |
|
959
|
|
|
} |
|
960
|
|
|
// --------------------------------------------------------------------------- |
|
961
|
|
|
|
|
962
|
|
|
// --------------------------------------------------------------------------- |
|
963
|
|
|
// Function : _openFd() |
|
964
|
|
|
// Description : |
|
965
|
|
|
// Parameters : |
|
966
|
|
|
// --------------------------------------------------------------------------- |
|
967
|
|
|
/** |
|
968
|
|
|
* Archive_Zip::_openFd() |
|
969
|
|
|
* |
|
970
|
|
|
* { Description } |
|
971
|
|
|
* @param $p_mode |
|
972
|
|
|
* @return int |
|
973
|
|
|
*/ |
|
974
|
|
|
public function _openFd($p_mode) |
|
975
|
|
|
{ |
|
976
|
|
|
$v_result = 1; |
|
977
|
|
|
|
|
978
|
|
|
// ----- Look if already open |
|
979
|
|
|
if ($this->_zip_fd != 0) { |
|
980
|
|
|
$this->_errorLog(ARCHIVE_ZIP_ERR_READ_OPEN_FAIL, 'Zip file \'' . $this->_zipname . '\' already open'); |
|
981
|
|
|
|
|
982
|
|
|
return Archive_Zip::errorCode(); |
|
983
|
|
|
} |
|
984
|
|
|
|
|
985
|
|
|
// ----- Open the zip file |
|
986
|
|
View Code Duplication |
if (($this->_zip_fd = @fopen($this->_zipname, $p_mode)) == 0) { |
|
|
|
|
|
|
987
|
|
|
$this->_errorLog(ARCHIVE_ZIP_ERR_READ_OPEN_FAIL, 'Unable to open archive \'' . $this->_zipname . '\' in ' . $p_mode . ' mode'); |
|
988
|
|
|
|
|
989
|
|
|
return Archive_Zip::errorCode(); |
|
990
|
|
|
} |
|
991
|
|
|
|
|
992
|
|
|
// ----- Return |
|
993
|
|
|
return $v_result; |
|
994
|
|
|
} |
|
995
|
|
|
// --------------------------------------------------------------------------- |
|
996
|
|
|
|
|
997
|
|
|
// --------------------------------------------------------------------------- |
|
998
|
|
|
// Function : _closeFd() |
|
999
|
|
|
// Description : |
|
1000
|
|
|
// Parameters : |
|
1001
|
|
|
// --------------------------------------------------------------------------- |
|
1002
|
|
|
/** |
|
1003
|
|
|
* Archive_Zip::_closeFd() |
|
1004
|
|
|
* |
|
1005
|
|
|
* { Description } |
|
1006
|
|
|
* |
|
1007
|
|
|
*/ |
|
1008
|
|
|
public function _closeFd() |
|
1009
|
|
|
{ |
|
1010
|
|
|
$v_result = 1; |
|
1011
|
|
|
|
|
1012
|
|
|
if ($this->_zip_fd != 0) { |
|
1013
|
|
|
@fclose($this->_zip_fd); |
|
|
|
|
|
|
1014
|
|
|
} |
|
1015
|
|
|
$this->_zip_fd = 0; |
|
1016
|
|
|
|
|
1017
|
|
|
// ----- Return |
|
1018
|
|
|
return $v_result; |
|
1019
|
|
|
} |
|
1020
|
|
|
// --------------------------------------------------------------------------- |
|
1021
|
|
|
|
|
1022
|
|
|
// --------------------------------------------------------------------------- |
|
1023
|
|
|
// Function : _addList() |
|
1024
|
|
|
// Description : |
|
1025
|
|
|
// $p_add_dir and $p_remove_dir will give the ability to memorize a path which is |
|
1026
|
|
|
// different from the real path of the file. This is usefull if you want to have PclTar |
|
1027
|
|
|
// running in any directory, and memorize relative path from an other directory. |
|
1028
|
|
|
// Parameters : |
|
1029
|
|
|
// $p_list : An array containing the file or directory names to add in the tar |
|
1030
|
|
|
// $p_result_list : list of added files with their properties (specially the status field) |
|
1031
|
|
|
// $p_add_dir : Path to add in the filename path archived |
|
1032
|
|
|
// $p_remove_dir : Path to remove in the filename path archived |
|
1033
|
|
|
// Return Values : |
|
1034
|
|
|
// --------------------------------------------------------------------------- |
|
1035
|
|
|
/** |
|
1036
|
|
|
* Archive_Zip::_addList() |
|
1037
|
|
|
* |
|
1038
|
|
|
* { Description } |
|
1039
|
|
|
* @param $p_list |
|
1040
|
|
|
* @param $p_result_list |
|
1041
|
|
|
* @param $p_add_dir |
|
1042
|
|
|
* @param $p_remove_dir |
|
1043
|
|
|
* @param $p_remove_all_dir |
|
1044
|
|
|
* @param $p_params |
|
1045
|
|
|
* @return int |
|
1046
|
|
|
*/ |
|
1047
|
|
|
public function _addList($p_list, &$p_result_list, $p_add_dir, $p_remove_dir, $p_remove_all_dir, &$p_params) |
|
1048
|
|
|
{ |
|
1049
|
|
|
$v_result = 1; |
|
|
|
|
|
|
1050
|
|
|
|
|
1051
|
|
|
// ----- Add the files |
|
1052
|
|
|
$v_header_list = array(); |
|
1053
|
|
|
if (($v_result = $this->_addFileList($p_list, $v_header_list, $p_add_dir, $p_remove_dir, $p_remove_all_dir, $p_params)) != 1) { |
|
1054
|
|
|
return $v_result; |
|
1055
|
|
|
} |
|
1056
|
|
|
|
|
1057
|
|
|
// ----- Store the offset of the central dir |
|
1058
|
|
|
$v_offset = @ftell($this->_zip_fd); |
|
1059
|
|
|
|
|
1060
|
|
|
// ----- Create the Central Dir files header |
|
1061
|
|
|
for ($i = 0, $iMax = count($v_header_list); $i < $iMax; ++$i) { |
|
1062
|
|
|
// ----- Create the file header |
|
1063
|
|
|
if ($v_header_list[$i]['status'] === 'ok') { |
|
1064
|
|
|
if (($v_result = $this->_writeCentralFileHeader($v_header_list[$i])) != 1) { |
|
1065
|
|
|
return $v_result; |
|
1066
|
|
|
} |
|
1067
|
|
|
++$v_count; |
|
|
|
|
|
|
1068
|
|
|
} |
|
1069
|
|
|
|
|
1070
|
|
|
// ----- Transform the header to a 'usable' info |
|
1071
|
|
|
$this->_convertHeader2FileInfo($v_header_list[$i], $p_result_list[$i]); |
|
1072
|
|
|
} |
|
1073
|
|
|
|
|
1074
|
|
|
// ----- Zip file comment |
|
1075
|
|
|
$v_comment = ''; |
|
1076
|
|
|
|
|
1077
|
|
|
// ----- Calculate the size of the central header |
|
1078
|
|
|
$v_size = @ftell($this->_zip_fd) - $v_offset; |
|
1079
|
|
|
|
|
1080
|
|
|
// ----- Create the central dir footer |
|
1081
|
|
|
if (($v_result = $this->_writeCentralHeader($v_count, $v_size, $v_offset, $v_comment)) != 1) { |
|
1082
|
|
|
// ----- Reset the file list |
|
1083
|
|
|
unset($v_header_list); |
|
1084
|
|
|
|
|
1085
|
|
|
// ----- Return |
|
1086
|
|
|
return $v_result; |
|
1087
|
|
|
} |
|
1088
|
|
|
|
|
1089
|
|
|
// ----- Return |
|
1090
|
|
|
return $v_result; |
|
1091
|
|
|
} |
|
1092
|
|
|
// --------------------------------------------------------------------------- |
|
1093
|
|
|
|
|
1094
|
|
|
// --------------------------------------------------------------------------- |
|
1095
|
|
|
// Function : _addFileList() |
|
1096
|
|
|
// Description : |
|
1097
|
|
|
// $p_add_dir and $p_remove_dir will give the ability to memorize a path which is |
|
1098
|
|
|
// different from the real path of the file. This is usefull if you want to |
|
1099
|
|
|
// run the lib in any directory, and memorize relative path from an other directory. |
|
1100
|
|
|
// Parameters : |
|
1101
|
|
|
// $p_list : An array containing the file or directory names to add in the tar |
|
1102
|
|
|
// $p_result_list : list of added files with their properties (specially the status field) |
|
1103
|
|
|
// $p_add_dir : Path to add in the filename path archived |
|
1104
|
|
|
// $p_remove_dir : Path to remove in the filename path archived |
|
1105
|
|
|
// Return Values : |
|
1106
|
|
|
// --------------------------------------------------------------------------- |
|
1107
|
|
|
/** |
|
1108
|
|
|
* Archive_Zip::_addFileList() |
|
1109
|
|
|
* |
|
1110
|
|
|
* { Description } |
|
1111
|
|
|
* @param $p_list |
|
1112
|
|
|
* @param $p_result_list |
|
1113
|
|
|
* @param $p_add_dir |
|
1114
|
|
|
* @param $p_remove_dir |
|
1115
|
|
|
* @param $p_remove_all_dir |
|
1116
|
|
|
* @param $p_params |
|
1117
|
|
|
* @return int |
|
1118
|
|
|
*/ |
|
1119
|
|
|
public function _addFileList($p_list, &$p_result_list, $p_add_dir, $p_remove_dir, $p_remove_all_dir, &$p_params) |
|
1120
|
|
|
{ |
|
1121
|
|
|
$v_result = 1; |
|
1122
|
|
|
$v_header = array(); |
|
1123
|
|
|
|
|
1124
|
|
|
// ----- Recuperate the current number of elt in list |
|
1125
|
|
|
$v_nb = count($p_result_list); |
|
1126
|
|
|
|
|
1127
|
|
|
// ----- Loop on the files |
|
1128
|
|
|
for ($j = 0; ($j < count($p_list)) && ($v_result == 1); ++$j) { |
|
1129
|
|
|
// ----- Recuperate the filename |
|
1130
|
|
|
$p_filename = $this->_tool_TranslateWinPath($p_list[$j], false); |
|
1131
|
|
|
|
|
1132
|
|
|
// ----- Skip empty file names |
|
1133
|
|
|
if ($p_filename == '') { |
|
1134
|
|
|
continue; |
|
1135
|
|
|
} |
|
1136
|
|
|
|
|
1137
|
|
|
// ----- Check the filename |
|
1138
|
|
|
if (!file_exists($p_filename)) { |
|
1139
|
|
|
$this->_errorLog(ARCHIVE_ZIP_ERR_MISSING_FILE, "File '$p_filename' does not exists"); |
|
1140
|
|
|
|
|
1141
|
|
|
return Archive_Zip::errorCode(); |
|
1142
|
|
|
} |
|
1143
|
|
|
|
|
1144
|
|
|
// ----- Look if it is a file or a dir with no all pathnre move |
|
1145
|
|
|
if (is_file($p_filename) || (is_dir($p_filename) && !$p_remove_all_dir)) { |
|
1146
|
|
|
// ----- Add the file |
|
1147
|
|
|
if (($v_result = $this->_addFile($p_filename, $v_header, $p_add_dir, $p_remove_dir, $p_remove_all_dir, $p_params)) != 1) { |
|
1148
|
|
|
// ----- Return status |
|
1149
|
|
|
return $v_result; |
|
1150
|
|
|
} |
|
1151
|
|
|
|
|
1152
|
|
|
// ----- Store the file infos |
|
1153
|
|
|
$p_result_list[$v_nb++] = $v_header; |
|
1154
|
|
|
} |
|
1155
|
|
|
|
|
1156
|
|
|
// ----- Look for directory |
|
1157
|
|
|
if (is_dir($p_filename)) { |
|
1158
|
|
|
|
|
1159
|
|
|
// ----- Look for path |
|
1160
|
|
|
$v_path = ''; |
|
1161
|
|
|
if ($p_filename !== '.') { |
|
1162
|
|
|
$v_path = $p_filename . '/'; |
|
1163
|
|
|
} |
|
1164
|
|
|
|
|
1165
|
|
|
// ----- Read the directory for files and sub-directories |
|
1166
|
|
|
$p_hdir = opendir($p_filename); |
|
1167
|
|
|
$p_hitem = readdir($p_hdir); // '.' directory |
|
|
|
|
|
|
1168
|
|
|
$p_hitem = readdir($p_hdir); // '..' directory |
|
|
|
|
|
|
1169
|
|
|
while ($p_hitem = readdir($p_hdir)) { |
|
1170
|
|
|
|
|
1171
|
|
|
// ----- Look for a file |
|
1172
|
|
|
if (is_file($v_path . $p_hitem)) { |
|
1173
|
|
|
|
|
1174
|
|
|
// ----- Add the file |
|
1175
|
|
|
if (($v_result = $this->_addFile($v_path . $p_hitem, $v_header, $p_add_dir, $p_remove_dir, $p_remove_all_dir, $p_params)) != 1) { |
|
1176
|
|
|
// ----- Return status |
|
1177
|
|
|
return $v_result; |
|
1178
|
|
|
} |
|
1179
|
|
|
|
|
1180
|
|
|
// ----- Store the file infos |
|
1181
|
|
|
$p_result_list[$v_nb++] = $v_header; |
|
1182
|
|
|
} // ----- Recursive call to _addFileList() |
|
1183
|
|
|
else { |
|
1184
|
|
|
|
|
1185
|
|
|
// ----- Need an array as parameter |
|
1186
|
|
|
$p_temp_list[0] = $v_path . $p_hitem; |
|
|
|
|
|
|
1187
|
|
|
$v_result = $this->_addFileList($p_temp_list, $p_result_list, $p_add_dir, $p_remove_dir, $p_remove_all_dir, $p_params); |
|
|
|
|
|
|
1188
|
|
|
|
|
1189
|
|
|
// ----- Update the number of elements of the list |
|
1190
|
|
|
$v_nb = count($p_result_list); |
|
1191
|
|
|
} |
|
1192
|
|
|
} |
|
1193
|
|
|
|
|
1194
|
|
|
// ----- Free memory for the recursive loop |
|
1195
|
|
|
unset($p_temp_list, $p_hdir, $p_hitem); |
|
1196
|
|
|
} |
|
1197
|
|
|
} |
|
1198
|
|
|
|
|
1199
|
|
|
return $v_result; |
|
1200
|
|
|
} |
|
1201
|
|
|
// --------------------------------------------------------------------------- |
|
1202
|
|
|
|
|
1203
|
|
|
// --------------------------------------------------------------------------- |
|
1204
|
|
|
// Function : _addFile() |
|
1205
|
|
|
// Description : |
|
1206
|
|
|
// Parameters : |
|
1207
|
|
|
// Return Values : |
|
1208
|
|
|
// --------------------------------------------------------------------------- |
|
1209
|
|
|
/** |
|
1210
|
|
|
* Archive_Zip::_addFile() |
|
1211
|
|
|
* |
|
1212
|
|
|
* { Description } |
|
1213
|
|
|
* @param $p_filename |
|
1214
|
|
|
* @param $p_header |
|
1215
|
|
|
* @param $p_add_dir |
|
1216
|
|
|
* @param $p_remove_dir |
|
1217
|
|
|
* @param $p_remove_all_dir |
|
1218
|
|
|
* @param $p_params |
|
1219
|
|
|
* @return int |
|
1220
|
|
|
*/ |
|
1221
|
|
|
public function _addFile($p_filename, &$p_header, $p_add_dir, $p_remove_dir, $p_remove_all_dir, &$p_params) |
|
1222
|
|
|
{ |
|
1223
|
|
|
$v_result = 1; |
|
1224
|
|
|
|
|
1225
|
|
|
if ($p_filename == '') { |
|
1226
|
|
|
// ----- Error log |
|
1227
|
|
|
$this->_errorLog(ARCHIVE_ZIP_ERR_INVALID_PARAMETER, 'Invalid file list parameter (invalid or empty list)'); |
|
1228
|
|
|
|
|
1229
|
|
|
// ----- Return |
|
1230
|
|
|
return Archive_Zip::errorCode(); |
|
1231
|
|
|
} |
|
1232
|
|
|
|
|
1233
|
|
|
// ----- Calculate the stored filename |
|
1234
|
|
|
$v_stored_filename = $p_filename; |
|
1235
|
|
|
|
|
1236
|
|
|
// ----- Look for all path to remove |
|
1237
|
|
|
if ($p_remove_all_dir) { |
|
1238
|
|
|
$v_stored_filename = basename($p_filename); |
|
1239
|
|
|
} // ----- Look for partial path remove |
|
1240
|
|
|
elseif ($p_remove_dir != '') { |
|
1241
|
|
|
if (substr($p_remove_dir, -1) !== '/') { |
|
1242
|
|
|
$p_remove_dir .= '/'; |
|
1243
|
|
|
} |
|
1244
|
|
|
|
|
1245
|
|
|
if ((substr($p_filename, 0, 2) === './') || (substr($p_remove_dir, 0, 2) === './')) { |
|
1246
|
|
View Code Duplication |
if ((substr($p_filename, 0, 2) === './') && (substr($p_remove_dir, 0, 2) !== './')) { |
|
|
|
|
|
|
1247
|
|
|
$p_remove_dir = './' . $p_remove_dir; |
|
1248
|
|
|
} |
|
1249
|
|
View Code Duplication |
if ((substr($p_filename, 0, 2) !== './') && (substr($p_remove_dir, 0, 2) === './')) { |
|
|
|
|
|
|
1250
|
|
|
$p_remove_dir = substr($p_remove_dir, 2); |
|
1251
|
|
|
} |
|
1252
|
|
|
} |
|
1253
|
|
|
|
|
1254
|
|
|
$v_compare = $this->_tool_PathInclusion($p_remove_dir, $p_filename); |
|
1255
|
|
|
if ($v_compare > 0) { |
|
1256
|
|
|
// if (substr($p_filename, 0, strlen($p_remove_dir)) == $p_remove_dir) { |
|
1257
|
|
|
|
|
1258
|
|
|
if ($v_compare == 2) { |
|
1259
|
|
|
$v_stored_filename = ''; |
|
1260
|
|
|
} else { |
|
1261
|
|
|
$v_stored_filename = substr($p_filename, strlen($p_remove_dir)); |
|
1262
|
|
|
} |
|
1263
|
|
|
} |
|
1264
|
|
|
} |
|
1265
|
|
|
|
|
1266
|
|
|
// ----- Look for path to add |
|
1267
|
|
|
if ($p_add_dir != '') { |
|
1268
|
|
|
if (substr($p_add_dir, -1) === '/') { |
|
1269
|
|
|
$v_stored_filename = $p_add_dir . $v_stored_filename; |
|
1270
|
|
|
} else { |
|
1271
|
|
|
$v_stored_filename = $p_add_dir . '/' . $v_stored_filename; |
|
1272
|
|
|
} |
|
1273
|
|
|
} |
|
1274
|
|
|
|
|
1275
|
|
|
// ----- Filename (reduce the path of stored name) |
|
1276
|
|
|
$v_stored_filename = $this->_tool_PathReduction($v_stored_filename); |
|
1277
|
|
|
|
|
1278
|
|
|
/* filename length moved after call-back in release 1.3 |
|
1279
|
|
|
// ----- Check the path length |
|
1280
|
|
|
if (strlen($v_stored_filename) > 0xFF) { |
|
1281
|
|
|
// ----- Error log |
|
1282
|
|
|
$this->_errorLog(-5, "Stored file name is too long (max. 255) : '$v_stored_filename'"); |
|
1283
|
|
|
|
|
1284
|
|
|
// ----- Return |
|
1285
|
|
|
return Archive_Zip::errorCode(); |
|
1286
|
|
|
} |
|
1287
|
|
|
*/ |
|
1288
|
|
|
|
|
1289
|
|
|
// ----- Set the file properties |
|
1290
|
|
|
clearstatcache(); |
|
1291
|
|
|
$p_header['version'] = 20; |
|
1292
|
|
|
$p_header['version_extracted'] = 10; |
|
1293
|
|
|
$p_header['flag'] = 0; |
|
1294
|
|
|
$p_header['compression'] = 0; |
|
1295
|
|
|
$p_header['mtime'] = filemtime($p_filename); |
|
1296
|
|
|
$p_header['crc'] = 0; |
|
1297
|
|
|
$p_header['compressed_size'] = 0; |
|
1298
|
|
|
$p_header['size'] = filesize($p_filename); |
|
1299
|
|
|
$p_header['filename_len'] = strlen($p_filename); |
|
1300
|
|
|
$p_header['extra_len'] = 0; |
|
1301
|
|
|
$p_header['comment_len'] = 0; |
|
1302
|
|
|
$p_header['disk'] = 0; |
|
1303
|
|
|
$p_header['internal'] = 0; |
|
1304
|
|
|
$p_header['external'] = (is_file($p_filename) ? 0xFE49FFE0 : 0x41FF0010); |
|
1305
|
|
|
$p_header['offset'] = 0; |
|
1306
|
|
|
$p_header['filename'] = $p_filename; |
|
1307
|
|
|
$p_header['stored_filename'] = $v_stored_filename; |
|
1308
|
|
|
$p_header['extra'] = ''; |
|
1309
|
|
|
$p_header['comment'] = ''; |
|
1310
|
|
|
$p_header['status'] = 'ok'; |
|
1311
|
|
|
$p_header['index'] = -1; |
|
1312
|
|
|
|
|
1313
|
|
|
// ----- Look for pre-add callback |
|
1314
|
|
|
if (isset($p_params[ARCHIVE_ZIP_PARAM_PRE_ADD]) && ($p_params[ARCHIVE_ZIP_PARAM_PRE_ADD] != '')) { |
|
1315
|
|
|
|
|
1316
|
|
|
// ----- Generate a local information |
|
1317
|
|
|
$v_local_header = array(); |
|
1318
|
|
|
$this->_convertHeader2FileInfo($p_header, $v_local_header); |
|
1319
|
|
|
|
|
1320
|
|
|
// ----- Call the callback |
|
1321
|
|
|
// Here I do not use call_user_func() because I need to send a reference to the |
|
1322
|
|
|
// header. |
|
1323
|
|
|
eval('$v_result = ' . $p_params[ARCHIVE_ZIP_PARAM_PRE_ADD] . '(ARCHIVE_ZIP_PARAM_PRE_ADD, $v_local_header);'); |
|
1324
|
|
|
if ($v_result == 0) { |
|
1325
|
|
|
// ----- Change the file status |
|
1326
|
|
|
$p_header['status'] = 'skipped'; |
|
1327
|
|
|
$v_result = 1; |
|
1328
|
|
|
} |
|
1329
|
|
|
|
|
1330
|
|
|
// ----- Update the informations |
|
1331
|
|
|
// Only some fields can be modified |
|
1332
|
|
|
if ($p_header['stored_filename'] != $v_local_header['stored_filename']) { |
|
1333
|
|
|
$p_header['stored_filename'] = $this->_tool_PathReduction($v_local_header['stored_filename']); |
|
1334
|
|
|
} |
|
1335
|
|
|
} |
|
1336
|
|
|
|
|
1337
|
|
|
// ----- Look for empty stored filename |
|
1338
|
|
|
if ($p_header['stored_filename'] == '') { |
|
1339
|
|
|
$p_header['status'] = 'filtered'; |
|
1340
|
|
|
} |
|
1341
|
|
|
|
|
1342
|
|
|
// ----- Check the path length |
|
1343
|
|
|
if (strlen($p_header['stored_filename']) > 0xFF) { |
|
1344
|
|
|
$p_header['status'] = 'filename_too_long'; |
|
1345
|
|
|
} |
|
1346
|
|
|
|
|
1347
|
|
|
// ----- Look if no error, or file not skipped |
|
1348
|
|
|
if ($p_header['status'] === 'ok') { |
|
1349
|
|
|
|
|
1350
|
|
|
// ----- Look for a file |
|
1351
|
|
|
if (is_file($p_filename)) { |
|
1352
|
|
|
// ----- Open the source file |
|
1353
|
|
View Code Duplication |
if (($v_file = @fopen($p_filename, 'rb')) == 0) { |
|
|
|
|
|
|
1354
|
|
|
$this->_errorLog(ARCHIVE_ZIP_ERR_READ_OPEN_FAIL, "Unable to open file '$p_filename' in binary read mode"); |
|
1355
|
|
|
|
|
1356
|
|
|
return Archive_Zip::errorCode(); |
|
1357
|
|
|
} |
|
1358
|
|
|
|
|
1359
|
|
|
if ($p_params['no_compression']) { |
|
1360
|
|
|
// ----- Read the file content |
|
1361
|
|
|
$v_content_compressed = @fread($v_file, $p_header['size']); |
|
1362
|
|
|
|
|
1363
|
|
|
// ----- Calculate the CRC |
|
1364
|
|
|
$p_header['crc'] = crc32($v_content_compressed); |
|
1365
|
|
|
} else { |
|
1366
|
|
|
// ----- Read the file content |
|
1367
|
|
|
$v_content = @fread($v_file, $p_header['size']); |
|
1368
|
|
|
|
|
1369
|
|
|
// ----- Calculate the CRC |
|
1370
|
|
|
$p_header['crc'] = crc32($v_content); |
|
1371
|
|
|
|
|
1372
|
|
|
// ----- Compress the file |
|
1373
|
|
|
$v_content_compressed = gzdeflate($v_content); |
|
1374
|
|
|
} |
|
1375
|
|
|
|
|
1376
|
|
|
// ----- Set header parameters |
|
1377
|
|
|
$p_header['compressed_size'] = strlen($v_content_compressed); |
|
1378
|
|
|
$p_header['compression'] = 8; |
|
1379
|
|
|
|
|
1380
|
|
|
// ----- Call the header generation |
|
1381
|
|
|
if (($v_result = $this->_writeFileHeader($p_header)) != 1) { |
|
1382
|
|
|
@fclose($v_file); |
|
|
|
|
|
|
1383
|
|
|
|
|
1384
|
|
|
return $v_result; |
|
1385
|
|
|
} |
|
1386
|
|
|
|
|
1387
|
|
|
// ----- Write the compressed content |
|
1388
|
|
|
$v_binary_data = pack('a' . $p_header['compressed_size'], $v_content_compressed); |
|
1389
|
|
|
@fwrite($this->_zip_fd, $v_binary_data, $p_header['compressed_size']); |
|
|
|
|
|
|
1390
|
|
|
|
|
1391
|
|
|
// ----- Close the file |
|
1392
|
|
|
@fclose($v_file); |
|
|
|
|
|
|
1393
|
|
|
} // ----- Look for a directory |
|
1394
|
|
|
else { |
|
1395
|
|
|
// ----- Set the file properties |
|
1396
|
|
|
$p_header['filename'] .= '/'; |
|
1397
|
|
|
$p_header['filename_len']++; |
|
1398
|
|
|
$p_header['size'] = 0; |
|
1399
|
|
|
$p_header['external'] = 0x41FF0010; // Value for a folder : to be checked |
|
1400
|
|
|
|
|
1401
|
|
|
// ----- Call the header generation |
|
1402
|
|
|
if (($v_result = $this->_writeFileHeader($p_header)) != 1) { |
|
1403
|
|
|
return $v_result; |
|
1404
|
|
|
} |
|
1405
|
|
|
} |
|
1406
|
|
|
} |
|
1407
|
|
|
|
|
1408
|
|
|
// ----- Look for pre-add callback |
|
1409
|
|
|
if (isset($p_params[ARCHIVE_ZIP_PARAM_POST_ADD]) && ($p_params[ARCHIVE_ZIP_PARAM_POST_ADD] != '')) { |
|
1410
|
|
|
|
|
1411
|
|
|
// ----- Generate a local information |
|
1412
|
|
|
$v_local_header = array(); |
|
1413
|
|
|
$this->_convertHeader2FileInfo($p_header, $v_local_header); |
|
1414
|
|
|
|
|
1415
|
|
|
// ----- Call the callback |
|
1416
|
|
|
// Here I do not use call_user_func() because I need to send a reference to the |
|
1417
|
|
|
// header. |
|
1418
|
|
|
eval('$v_result = ' . $p_params[ARCHIVE_ZIP_PARAM_POST_ADD] . '(ARCHIVE_ZIP_PARAM_POST_ADD, $v_local_header);'); |
|
1419
|
|
|
if ($v_result == 0) { |
|
1420
|
|
|
// ----- Ignored |
|
1421
|
|
|
$v_result = 1; |
|
1422
|
|
|
} |
|
1423
|
|
|
|
|
1424
|
|
|
// ----- Update the informations |
|
1425
|
|
|
// Nothing can be modified |
|
1426
|
|
|
} |
|
1427
|
|
|
|
|
1428
|
|
|
// ----- Return |
|
1429
|
|
|
return $v_result; |
|
1430
|
|
|
} |
|
1431
|
|
|
// --------------------------------------------------------------------------- |
|
1432
|
|
|
|
|
1433
|
|
|
// --------------------------------------------------------------------------- |
|
1434
|
|
|
// Function : _writeFileHeader() |
|
1435
|
|
|
// Description : |
|
1436
|
|
|
// Parameters : |
|
1437
|
|
|
// Return Values : |
|
1438
|
|
|
// --------------------------------------------------------------------------- |
|
1439
|
|
|
/** |
|
1440
|
|
|
* Archive_Zip::_writeFileHeader() |
|
1441
|
|
|
* |
|
1442
|
|
|
* { Description } |
|
1443
|
|
|
* @param $p_header |
|
1444
|
|
|
* @return int |
|
1445
|
|
|
*/ |
|
1446
|
|
|
public function _writeFileHeader(&$p_header) |
|
1447
|
|
|
{ |
|
1448
|
|
|
$v_result = 1; |
|
1449
|
|
|
|
|
1450
|
|
|
// TBC |
|
1451
|
|
|
//for (reset($p_header); $key = key($p_header); next($p_header)) { |
|
1452
|
|
|
//} |
|
1453
|
|
|
|
|
1454
|
|
|
// ----- Store the offset position of the file |
|
1455
|
|
|
$p_header['offset'] = ftell($this->_zip_fd); |
|
1456
|
|
|
|
|
1457
|
|
|
// ----- Transform UNIX mtime to DOS format mdate/mtime |
|
1458
|
|
|
$v_date = getdate($p_header['mtime']); |
|
1459
|
|
|
$v_mtime = ($v_date['hours'] << 11) + ($v_date['minutes'] << 5) + $v_date['seconds'] / 2; |
|
1460
|
|
|
$v_mdate = (($v_date['year'] - 1980) << 9) + ($v_date['mon'] << 5) + $v_date['mday']; |
|
1461
|
|
|
|
|
1462
|
|
|
// ----- Packed data |
|
1463
|
|
|
$v_binary_data = pack('VvvvvvVVVvv', 0x04034b50, $p_header['version'], $p_header['flag'], $p_header['compression'], $v_mtime, $v_mdate, $p_header['crc'], $p_header['compressed_size'], $p_header['size'], strlen($p_header['stored_filename']), $p_header['extra_len']); |
|
1464
|
|
|
|
|
1465
|
|
|
// ----- Write the first 148 bytes of the header in the archive |
|
1466
|
|
|
fwrite($this->_zip_fd, $v_binary_data, 30); |
|
1467
|
|
|
|
|
1468
|
|
|
// ----- Write the variable fields |
|
1469
|
|
View Code Duplication |
if ($p_header['stored_filename'] != 0) { |
|
|
|
|
|
|
1470
|
|
|
fwrite($this->_zip_fd, $p_header['stored_filename'], strlen($p_header['stored_filename'])); |
|
1471
|
|
|
} |
|
1472
|
|
View Code Duplication |
if ($p_header['extra_len'] != 0) { |
|
|
|
|
|
|
1473
|
|
|
fwrite($this->_zip_fd, $p_header['extra'], $p_header['extra_len']); |
|
1474
|
|
|
} |
|
1475
|
|
|
|
|
1476
|
|
|
// ----- Return |
|
1477
|
|
|
return $v_result; |
|
1478
|
|
|
} |
|
1479
|
|
|
|
|
1480
|
|
|
// --------------------------------------------------------------------------- |
|
1481
|
|
|
|
|
1482
|
|
|
// --------------------------------------------------------------------------- |
|
1483
|
|
|
// Function : _writeCentralFileHeader() |
|
1484
|
|
|
// Description : |
|
1485
|
|
|
// Parameters : |
|
1486
|
|
|
// Return Values : |
|
1487
|
|
|
// --------------------------------------------------------------------------- |
|
1488
|
|
|
/** |
|
1489
|
|
|
* Archive_Zip::_writeCentralFileHeader() |
|
1490
|
|
|
* |
|
1491
|
|
|
* { Description } |
|
1492
|
|
|
* @param $p_header |
|
1493
|
|
|
* @return int |
|
1494
|
|
|
*/ |
|
1495
|
|
|
public function _writeCentralFileHeader(&$p_header) |
|
1496
|
|
|
{ |
|
1497
|
|
|
$v_result = 1; |
|
1498
|
|
|
|
|
1499
|
|
|
// TBC |
|
1500
|
|
|
//for (reset($p_header); $key = key($p_header); next($p_header)) { |
|
1501
|
|
|
//} |
|
1502
|
|
|
|
|
1503
|
|
|
// ----- Transform UNIX mtime to DOS format mdate/mtime |
|
1504
|
|
|
$v_date = getdate($p_header['mtime']); |
|
1505
|
|
|
$v_mtime = ($v_date['hours'] << 11) + ($v_date['minutes'] << 5) + $v_date['seconds'] / 2; |
|
1506
|
|
|
$v_mdate = (($v_date['year'] - 1980) << 9) + ($v_date['mon'] << 5) + $v_date['mday']; |
|
1507
|
|
|
|
|
1508
|
|
|
// ----- Packed data |
|
1509
|
|
|
$v_binary_data = |
|
1510
|
|
|
pack('VvvvvvvVVVvvvvvVV', 0x02014b50, $p_header['version'], $p_header['version_extracted'], $p_header['flag'], $p_header['compression'], $v_mtime, $v_mdate, $p_header['crc'], $p_header['compressed_size'], $p_header['size'], strlen($p_header['stored_filename']), $p_header['extra_len'], |
|
1511
|
|
|
$p_header['comment_len'], $p_header['disk'], $p_header['internal'], $p_header['external'], $p_header['offset']); |
|
1512
|
|
|
|
|
1513
|
|
|
// ----- Write the 42 bytes of the header in the zip file |
|
1514
|
|
|
fwrite($this->_zip_fd, $v_binary_data, 46); |
|
1515
|
|
|
|
|
1516
|
|
|
// ----- Write the variable fields |
|
1517
|
|
View Code Duplication |
if ('' !== $p_header['stored_filename']) { |
|
|
|
|
|
|
1518
|
|
|
fwrite($this->_zip_fd, $p_header['stored_filename'], strlen($p_header['stored_filename'])); |
|
1519
|
|
|
} |
|
1520
|
|
View Code Duplication |
if ($p_header['extra_len'] != 0) { |
|
|
|
|
|
|
1521
|
|
|
fwrite($this->_zip_fd, $p_header['extra'], $p_header['extra_len']); |
|
1522
|
|
|
} |
|
1523
|
|
|
if ($p_header['comment_len'] != 0) { |
|
1524
|
|
|
fwrite($this->_zip_fd, $p_header['comment'], $p_header['comment_len']); |
|
1525
|
|
|
} |
|
1526
|
|
|
|
|
1527
|
|
|
// ----- Return |
|
1528
|
|
|
return $v_result; |
|
1529
|
|
|
} |
|
1530
|
|
|
|
|
1531
|
|
|
// --------------------------------------------------------------------------- |
|
1532
|
|
|
|
|
1533
|
|
|
// --------------------------------------------------------------------------- |
|
1534
|
|
|
// Function : _writeCentralHeader() |
|
1535
|
|
|
// Description : |
|
1536
|
|
|
// Parameters : |
|
1537
|
|
|
// Return Values : |
|
1538
|
|
|
// --------------------------------------------------------------------------- |
|
1539
|
|
|
/** |
|
1540
|
|
|
* Archive_Zip::_writeCentralHeader() |
|
1541
|
|
|
* |
|
1542
|
|
|
* { Description } |
|
1543
|
|
|
* @param $p_nb_entries |
|
1544
|
|
|
* @param $p_size |
|
1545
|
|
|
* @param $p_offset |
|
1546
|
|
|
* @param $p_comment |
|
1547
|
|
|
* @return int |
|
1548
|
|
|
*/ |
|
1549
|
|
|
public function _writeCentralHeader($p_nb_entries, $p_size, $p_offset, $p_comment) |
|
1550
|
|
|
{ |
|
1551
|
|
|
$v_result = 1; |
|
1552
|
|
|
|
|
1553
|
|
|
// ----- Packed data |
|
1554
|
|
|
$v_binary_data = pack('VvvvvVVv', 0x06054b50, 0, 0, $p_nb_entries, $p_nb_entries, $p_size, $p_offset, strlen($p_comment)); |
|
1555
|
|
|
|
|
1556
|
|
|
// ----- Write the 22 bytes of the header in the zip file |
|
1557
|
|
|
fwrite($this->_zip_fd, $v_binary_data, 22); |
|
1558
|
|
|
|
|
1559
|
|
|
// ----- Write the variable fields |
|
1560
|
|
|
if ('' !== $p_comment) { |
|
1561
|
|
|
fwrite($this->_zip_fd, $p_comment, strlen($p_comment)); |
|
1562
|
|
|
} |
|
1563
|
|
|
|
|
1564
|
|
|
// ----- Return |
|
1565
|
|
|
return $v_result; |
|
1566
|
|
|
} |
|
1567
|
|
|
|
|
1568
|
|
|
// --------------------------------------------------------------------------- |
|
1569
|
|
|
|
|
1570
|
|
|
// --------------------------------------------------------------------------- |
|
1571
|
|
|
// Function : _list() |
|
1572
|
|
|
// Description : |
|
1573
|
|
|
// Parameters : |
|
1574
|
|
|
// Return Values : |
|
1575
|
|
|
// --------------------------------------------------------------------------- |
|
1576
|
|
|
/** |
|
1577
|
|
|
* Archive_Zip::_list() |
|
1578
|
|
|
* |
|
1579
|
|
|
* { Description } |
|
1580
|
|
|
* @param $p_list |
|
1581
|
|
|
* @return int |
|
1582
|
|
|
*/ |
|
1583
|
|
|
public function _list(&$p_list) |
|
1584
|
|
|
{ |
|
1585
|
|
|
$v_result = 1; |
|
|
|
|
|
|
1586
|
|
|
|
|
1587
|
|
|
// ----- Open the zip file |
|
1588
|
|
View Code Duplication |
if (($this->_zip_fd = @fopen($this->_zipname, 'rb')) == 0) { |
|
|
|
|
|
|
1589
|
|
|
// ----- Error log |
|
1590
|
|
|
$this->_errorLog(ARCHIVE_ZIP_ERR_READ_OPEN_FAIL, 'Unable to open archive \'' . $this->_zipname . '\' in binary read mode'); |
|
1591
|
|
|
|
|
1592
|
|
|
// ----- Return |
|
1593
|
|
|
return Archive_Zip::errorCode(); |
|
1594
|
|
|
} |
|
1595
|
|
|
|
|
1596
|
|
|
// ----- Read the central directory informations |
|
1597
|
|
|
$v_central_dir = array(); |
|
1598
|
|
|
if (($v_result = $this->_readEndCentralDir($v_central_dir)) != 1) { |
|
1599
|
|
|
return $v_result; |
|
1600
|
|
|
} |
|
1601
|
|
|
|
|
1602
|
|
|
// ----- Go to beginning of Central Dir |
|
1603
|
|
|
@rewind($this->_zip_fd); |
|
|
|
|
|
|
1604
|
|
View Code Duplication |
if (@fseek($this->_zip_fd, $v_central_dir['offset'])) { |
|
|
|
|
|
|
1605
|
|
|
// ----- Error log |
|
1606
|
|
|
$this->_errorLog(ARCHIVE_ZIP_ERR_INVALID_ARCHIVE_ZIP, 'Invalid archive size'); |
|
1607
|
|
|
|
|
1608
|
|
|
// ----- Return |
|
1609
|
|
|
return Archive_Zip::errorCode(); |
|
1610
|
|
|
} |
|
1611
|
|
|
|
|
1612
|
|
|
// ----- Read each entry |
|
1613
|
|
|
for ($i = 0; $i < $v_central_dir['entries']; ++$i) { |
|
1614
|
|
|
// ----- Read the file header |
|
1615
|
|
|
if (($v_result = $this->_readCentralFileHeader($v_header)) != 1) { |
|
1616
|
|
|
return $v_result; |
|
1617
|
|
|
} |
|
1618
|
|
|
$v_header['index'] = $i; |
|
1619
|
|
|
|
|
1620
|
|
|
// ----- Get the only interesting attributes |
|
1621
|
|
|
$this->_convertHeader2FileInfo($v_header, $p_list[$i]); |
|
1622
|
|
|
unset($v_header); |
|
1623
|
|
|
} |
|
1624
|
|
|
|
|
1625
|
|
|
// ----- Close the zip file |
|
1626
|
|
|
$this->_closeFd(); |
|
1627
|
|
|
|
|
1628
|
|
|
// ----- Return |
|
1629
|
|
|
return $v_result; |
|
1630
|
|
|
} |
|
1631
|
|
|
|
|
1632
|
|
|
// --------------------------------------------------------------------------- |
|
1633
|
|
|
|
|
1634
|
|
|
// --------------------------------------------------------------------------- |
|
1635
|
|
|
// Function : _convertHeader2FileInfo() |
|
1636
|
|
|
// Description : |
|
1637
|
|
|
// This function takes the file informations from the central directory |
|
1638
|
|
|
// entries and extract the interesting parameters that will be given back. |
|
1639
|
|
|
// The resulting file infos are set in the array $p_info |
|
1640
|
|
|
// $p_info['filename'] : Filename with full path. Given by user (add), |
|
1641
|
|
|
// extracted in the filesystem (extract). |
|
1642
|
|
|
// $p_info['stored_filename'] : Stored filename in the archive. |
|
1643
|
|
|
// $p_info['size'] = Size of the file. |
|
1644
|
|
|
// $p_info['compressed_size'] = Compressed size of the file. |
|
1645
|
|
|
// $p_info['mtime'] = Last modification date of the file. |
|
1646
|
|
|
// $p_info['comment'] = Comment associated with the file. |
|
1647
|
|
|
// $p_info['folder'] = true/false : indicates if the entry is a folder or not. |
|
1648
|
|
|
// $p_info['status'] = status of the action on the file. |
|
1649
|
|
|
// Parameters : |
|
1650
|
|
|
// Return Values : |
|
1651
|
|
|
// --------------------------------------------------------------------------- |
|
1652
|
|
|
/** |
|
1653
|
|
|
* Archive_Zip::_convertHeader2FileInfo() |
|
1654
|
|
|
* |
|
1655
|
|
|
* { Description } |
|
1656
|
|
|
* @param $p_header |
|
1657
|
|
|
* @param $p_info |
|
1658
|
|
|
* @return int |
|
1659
|
|
|
*/ |
|
1660
|
|
|
public function _convertHeader2FileInfo($p_header, &$p_info) |
|
1661
|
|
|
{ |
|
1662
|
|
|
$v_result = 1; |
|
1663
|
|
|
|
|
1664
|
|
|
// ----- Get the interesting attributes |
|
1665
|
|
|
$p_info['filename'] = $p_header['filename']; |
|
1666
|
|
|
$p_info['stored_filename'] = $p_header['stored_filename']; |
|
1667
|
|
|
$p_info['size'] = $p_header['size']; |
|
1668
|
|
|
$p_info['compressed_size'] = $p_header['compressed_size']; |
|
1669
|
|
|
$p_info['mtime'] = $p_header['mtime']; |
|
1670
|
|
|
$p_info['comment'] = $p_header['comment']; |
|
1671
|
|
|
$p_info['folder'] = (($p_header['external'] & 0x00000010) == 0x00000010); |
|
1672
|
|
|
$p_info['index'] = $p_header['index']; |
|
1673
|
|
|
$p_info['status'] = $p_header['status']; |
|
1674
|
|
|
|
|
1675
|
|
|
// ----- Return |
|
1676
|
|
|
return $v_result; |
|
1677
|
|
|
} |
|
1678
|
|
|
|
|
1679
|
|
|
// --------------------------------------------------------------------------- |
|
1680
|
|
|
|
|
1681
|
|
|
// --------------------------------------------------------------------------- |
|
1682
|
|
|
// Function : _extractByRule() |
|
1683
|
|
|
// Description : |
|
1684
|
|
|
// Extract a file or directory depending of rules (by index, by name, ...) |
|
1685
|
|
|
// Parameters : |
|
1686
|
|
|
// $p_file_list : An array where will be placed the properties of each |
|
1687
|
|
|
// extracted file |
|
1688
|
|
|
// $p_path : Path to add while writing the extracted files |
|
1689
|
|
|
// $p_remove_path : Path to remove (from the file memorized path) while writing the |
|
1690
|
|
|
// extracted files. If the path does not match the file path, |
|
1691
|
|
|
// the file is extracted with its memorized path. |
|
1692
|
|
|
// $p_remove_path does not apply to 'list' mode. |
|
1693
|
|
|
// $p_path and $p_remove_path are commulative. |
|
1694
|
|
|
// Return Values : |
|
1695
|
|
|
// 1 on success,0 or less on error (see error code list) |
|
1696
|
|
|
// --------------------------------------------------------------------------- |
|
1697
|
|
|
/** |
|
1698
|
|
|
* Archive_Zip::_extractByRule() |
|
1699
|
|
|
* |
|
1700
|
|
|
* { Description } |
|
1701
|
|
|
* @param $p_file_list |
|
1702
|
|
|
* @param $p_params |
|
1703
|
|
|
* @return int |
|
1704
|
|
|
*/ |
|
1705
|
|
|
public function _extractByRule(&$p_file_list, &$p_params) |
|
1706
|
|
|
{ |
|
1707
|
|
|
$v_result = 1; |
|
|
|
|
|
|
1708
|
|
|
|
|
1709
|
|
|
$p_path = $p_params['add_path']; |
|
1710
|
|
|
$p_remove_path = $p_params['remove_path']; |
|
1711
|
|
|
$p_remove_all_path = $p_params['remove_all_path']; |
|
1712
|
|
|
|
|
1713
|
|
|
// ----- Check the path |
|
1714
|
|
|
if (($p_path == '') || ((substr($p_path, 0, 1) !== '/') && (substr($p_path, 0, 3) !== '../') && (substr($p_path, 1, 2) !== ':/'))) { |
|
1715
|
|
|
$p_path = './' . $p_path; |
|
1716
|
|
|
} |
|
1717
|
|
|
|
|
1718
|
|
|
// ----- Reduce the path last (and duplicated) '/' |
|
1719
|
|
|
if (($p_path !== './') && ($p_path !== '/')) { |
|
1720
|
|
|
// ----- Look for the path end '/' |
|
1721
|
|
|
while (substr($p_path, -1) === '/') { |
|
1722
|
|
|
$p_path = substr($p_path, 0, -1); |
|
1723
|
|
|
} |
|
1724
|
|
|
} |
|
1725
|
|
|
|
|
1726
|
|
|
// ----- Look for path to remove format (should end by /) |
|
1727
|
|
|
if (($p_remove_path != '') && (substr($p_remove_path, -1) !== '/')) { |
|
1728
|
|
|
$p_remove_path .= '/'; |
|
1729
|
|
|
} |
|
1730
|
|
|
$p_remove_path_size = strlen($p_remove_path); |
|
|
|
|
|
|
1731
|
|
|
|
|
1732
|
|
|
// ----- Open the zip file |
|
1733
|
|
|
if (($v_result = $this->_openFd('rb')) != 1) { |
|
1734
|
|
|
return $v_result; |
|
1735
|
|
|
} |
|
1736
|
|
|
|
|
1737
|
|
|
// ----- Read the central directory informations |
|
1738
|
|
|
$v_central_dir = array(); |
|
1739
|
|
|
if (($v_result = $this->_readEndCentralDir($v_central_dir)) != 1) { |
|
1740
|
|
|
// ----- Close the zip file |
|
1741
|
|
|
$this->_closeFd(); |
|
1742
|
|
|
|
|
1743
|
|
|
return $v_result; |
|
1744
|
|
|
} |
|
1745
|
|
|
|
|
1746
|
|
|
// ----- Start at beginning of Central Dir |
|
1747
|
|
|
$v_pos_entry = $v_central_dir['offset']; |
|
1748
|
|
|
|
|
1749
|
|
|
// ----- Read each entry |
|
1750
|
|
|
$j_start = 0; |
|
1751
|
|
|
for ($i = 0, $v_nb_extracted = 0; $i < $v_central_dir['entries']; ++$i) { |
|
1752
|
|
|
// ----- Read next Central dir entry |
|
1753
|
|
|
@rewind($this->_zip_fd); |
|
|
|
|
|
|
1754
|
|
View Code Duplication |
if (@fseek($this->_zip_fd, $v_pos_entry)) { |
|
|
|
|
|
|
1755
|
|
|
$this->_closeFd(); |
|
1756
|
|
|
|
|
1757
|
|
|
$this->_errorLog(ARCHIVE_ZIP_ERR_INVALID_ARCHIVE_ZIP, 'Invalid archive size'); |
|
1758
|
|
|
|
|
1759
|
|
|
return Archive_Zip::errorCode(); |
|
1760
|
|
|
} |
|
1761
|
|
|
|
|
1762
|
|
|
// ----- Read the file header |
|
1763
|
|
|
$v_header = array(); |
|
1764
|
|
|
if (($v_result = $this->_readCentralFileHeader($v_header)) != 1) { |
|
1765
|
|
|
$this->_closeFd(); |
|
1766
|
|
|
|
|
1767
|
|
|
return $v_result; |
|
1768
|
|
|
} |
|
1769
|
|
|
|
|
1770
|
|
|
// ----- Store the index |
|
1771
|
|
|
$v_header['index'] = $i; |
|
1772
|
|
|
|
|
1773
|
|
|
// ----- Store the file position |
|
1774
|
|
|
$v_pos_entry = ftell($this->_zip_fd); |
|
1775
|
|
|
|
|
1776
|
|
|
// ----- Look for the specific extract rules |
|
1777
|
|
|
$v_extract = false; |
|
1778
|
|
|
|
|
1779
|
|
|
// ----- Look for extract by name rule |
|
1780
|
|
|
if (isset($p_params[ARCHIVE_ZIP_PARAM_BY_NAME]) && ($p_params[ARCHIVE_ZIP_PARAM_BY_NAME] != 0)) { |
|
1781
|
|
|
|
|
1782
|
|
|
// ----- Look if the filename is in the list |
|
1783
|
|
|
for ($j = 0; ($j < count($p_params[ARCHIVE_ZIP_PARAM_BY_NAME])) && (!$v_extract); ++$j) { |
|
1784
|
|
|
|
|
1785
|
|
|
// ----- Look for a directory |
|
1786
|
|
|
if (substr($p_params[ARCHIVE_ZIP_PARAM_BY_NAME][$j], -1) === '/') { |
|
1787
|
|
|
|
|
1788
|
|
|
// ----- Look if the directory is in the filename path |
|
1789
|
|
|
if ((strlen($v_header['stored_filename']) > strlen($p_params[ARCHIVE_ZIP_PARAM_BY_NAME][$j])) |
|
1790
|
|
|
&& (substr($v_header['stored_filename'], 0, strlen($p_params[ARCHIVE_ZIP_PARAM_BY_NAME][$j])) == $p_params[ARCHIVE_ZIP_PARAM_BY_NAME][$j]) |
|
1791
|
|
|
) { |
|
1792
|
|
|
$v_extract = true; |
|
1793
|
|
|
} |
|
1794
|
|
|
} // ----- Look for a filename |
|
1795
|
|
|
elseif ($v_header['stored_filename'] == $p_params[ARCHIVE_ZIP_PARAM_BY_NAME][$j]) { |
|
1796
|
|
|
$v_extract = true; |
|
1797
|
|
|
} |
|
1798
|
|
|
} |
|
1799
|
|
|
} // ----- Look for extract by ereg rule |
|
1800
|
|
View Code Duplication |
elseif (isset($p_params[ARCHIVE_ZIP_PARAM_BY_EREG]) && ($p_params[ARCHIVE_ZIP_PARAM_BY_EREG] != '')) { |
|
|
|
|
|
|
1801
|
|
|
if (preg_match('/' . $p_params[ARCHIVE_ZIP_PARAM_BY_EREG] . '/', $v_header['stored_filename'])) { |
|
1802
|
|
|
$v_extract = true; |
|
1803
|
|
|
} |
|
1804
|
|
|
} // ----- Look for extract by preg rule |
|
1805
|
|
|
elseif (isset($p_params[ARCHIVE_ZIP_PARAM_BY_PREG]) && ($p_params[ARCHIVE_ZIP_PARAM_BY_PREG] != '')) { |
|
1806
|
|
|
if (preg_match($p_params[ARCHIVE_ZIP_PARAM_BY_PREG], $v_header['stored_filename'])) { |
|
1807
|
|
|
$v_extract = true; |
|
1808
|
|
|
} |
|
1809
|
|
|
} // ----- Look for extract by index rule |
|
1810
|
|
View Code Duplication |
elseif (isset($p_params[ARCHIVE_ZIP_PARAM_BY_INDEX]) && ($p_params[ARCHIVE_ZIP_PARAM_BY_INDEX] != 0)) { |
|
|
|
|
|
|
1811
|
|
|
|
|
1812
|
|
|
// ----- Look if the index is in the list |
|
1813
|
|
|
for ($j = $j_start; ($j < count($p_params[ARCHIVE_ZIP_PARAM_BY_INDEX])) && (!$v_extract); ++$j) { |
|
1814
|
|
|
if (($i >= $p_params[ARCHIVE_ZIP_PARAM_BY_INDEX][$j]['start']) && ($i <= $p_params[ARCHIVE_ZIP_PARAM_BY_INDEX][$j]['end'])) { |
|
1815
|
|
|
$v_extract = true; |
|
1816
|
|
|
} |
|
1817
|
|
|
if ($i >= $p_params[ARCHIVE_ZIP_PARAM_BY_INDEX][$j]['end']) { |
|
1818
|
|
|
$j_start = $j + 1; |
|
1819
|
|
|
} |
|
1820
|
|
|
|
|
1821
|
|
|
if ($p_params[ARCHIVE_ZIP_PARAM_BY_INDEX][$j]['start'] > $i) { |
|
1822
|
|
|
break; |
|
1823
|
|
|
} |
|
1824
|
|
|
} |
|
1825
|
|
|
} // ----- Look for no rule, which means extract all the archive |
|
1826
|
|
|
else { |
|
1827
|
|
|
$v_extract = true; |
|
1828
|
|
|
} |
|
1829
|
|
|
|
|
1830
|
|
|
// ----- Look for real extraction |
|
1831
|
|
|
if ($v_extract) { |
|
1832
|
|
|
|
|
1833
|
|
|
// ----- Go to the file position |
|
1834
|
|
|
@rewind($this->_zip_fd); |
|
|
|
|
|
|
1835
|
|
View Code Duplication |
if (@fseek($this->_zip_fd, $v_header['offset'])) { |
|
|
|
|
|
|
1836
|
|
|
// ----- Close the zip file |
|
1837
|
|
|
$this->_closeFd(); |
|
1838
|
|
|
|
|
1839
|
|
|
// ----- Error log |
|
1840
|
|
|
$this->_errorLog(ARCHIVE_ZIP_ERR_INVALID_ARCHIVE_ZIP, 'Invalid archive size'); |
|
1841
|
|
|
|
|
1842
|
|
|
// ----- Return |
|
1843
|
|
|
return Archive_Zip::errorCode(); |
|
1844
|
|
|
} |
|
1845
|
|
|
|
|
1846
|
|
|
// ----- Look for extraction as string |
|
1847
|
|
|
if ($p_params[ARCHIVE_ZIP_PARAM_EXTRACT_AS_STRING]) { |
|
1848
|
|
|
|
|
1849
|
|
|
// ----- Extracting the file |
|
1850
|
|
|
if (($v_result = $this->_extractFileAsString($v_header, $v_string)) != 1) { |
|
1851
|
|
|
// ----- Close the zip file |
|
1852
|
|
|
$this->_closeFd(); |
|
1853
|
|
|
|
|
1854
|
|
|
return $v_result; |
|
1855
|
|
|
} |
|
1856
|
|
|
|
|
1857
|
|
|
// ----- Get the only interesting attributes |
|
1858
|
|
|
if (($v_result = $this->_convertHeader2FileInfo($v_header, $p_file_list[$v_nb_extracted])) != 1) { |
|
1859
|
|
|
// ----- Close the zip file |
|
1860
|
|
|
$this->_closeFd(); |
|
1861
|
|
|
|
|
1862
|
|
|
return $v_result; |
|
1863
|
|
|
} |
|
1864
|
|
|
|
|
1865
|
|
|
// ----- Set the file content |
|
1866
|
|
|
$p_file_list[$v_nb_extracted]['content'] = $v_string; |
|
1867
|
|
|
|
|
1868
|
|
|
// ----- Next extracted file |
|
1869
|
|
|
++$v_nb_extracted; |
|
1870
|
|
|
} else { |
|
1871
|
|
|
// ----- Extracting the file |
|
1872
|
|
|
if (($v_result = $this->_extractFile($v_header, $p_path, $p_remove_path, $p_remove_all_path, $p_params)) != 1) { |
|
1873
|
|
|
// ----- Close the zip file |
|
1874
|
|
|
$this->_closeFd(); |
|
1875
|
|
|
|
|
1876
|
|
|
return $v_result; |
|
1877
|
|
|
} |
|
1878
|
|
|
|
|
1879
|
|
|
// ----- Get the only interesting attributes |
|
1880
|
|
|
if (($v_result = $this->_convertHeader2FileInfo($v_header, $p_file_list[$v_nb_extracted++])) != 1) { |
|
1881
|
|
|
// ----- Close the zip file |
|
1882
|
|
|
$this->_closeFd(); |
|
1883
|
|
|
|
|
1884
|
|
|
return $v_result; |
|
1885
|
|
|
} |
|
1886
|
|
|
} |
|
1887
|
|
|
} |
|
1888
|
|
|
} |
|
1889
|
|
|
|
|
1890
|
|
|
// ----- Close the zip file |
|
1891
|
|
|
$this->_closeFd(); |
|
1892
|
|
|
|
|
1893
|
|
|
// ----- Return |
|
1894
|
|
|
return $v_result; |
|
1895
|
|
|
} |
|
1896
|
|
|
|
|
1897
|
|
|
// --------------------------------------------------------------------------- |
|
1898
|
|
|
|
|
1899
|
|
|
// --------------------------------------------------------------------------- |
|
1900
|
|
|
// Function : _extractFile() |
|
1901
|
|
|
// Description : |
|
1902
|
|
|
// Parameters : |
|
1903
|
|
|
// Return Values : |
|
1904
|
|
|
// --------------------------------------------------------------------------- |
|
1905
|
|
|
/** |
|
1906
|
|
|
* Archive_Zip::_extractFile() |
|
1907
|
|
|
* |
|
1908
|
|
|
* { Description } |
|
1909
|
|
|
* @param $p_entry |
|
1910
|
|
|
* @param $p_path |
|
1911
|
|
|
* @param $p_remove_path |
|
1912
|
|
|
* @param $p_remove_all_path |
|
1913
|
|
|
* @param $p_params |
|
1914
|
|
|
* @return int |
|
1915
|
|
|
*/ |
|
1916
|
|
|
public function _extractFile(&$p_entry, $p_path, $p_remove_path, $p_remove_all_path, &$p_params) |
|
1917
|
|
|
{ |
|
1918
|
|
|
$v_result = 1; |
|
|
|
|
|
|
1919
|
|
|
|
|
1920
|
|
|
// ----- Read the file header |
|
1921
|
|
|
if (($v_result = $this->_readFileHeader($v_header)) != 1) { |
|
1922
|
|
|
// ----- Return |
|
1923
|
|
|
return $v_result; |
|
1924
|
|
|
} |
|
1925
|
|
|
|
|
1926
|
|
|
// ----- Check that the file header is coherent with $p_entry info |
|
1927
|
|
|
// TBC |
|
1928
|
|
|
|
|
1929
|
|
|
// ----- Look for all path to remove |
|
1930
|
|
|
if ($p_remove_all_path == true) { |
|
1931
|
|
|
// ----- Get the basename of the path |
|
1932
|
|
|
$p_entry['filename'] = basename($p_entry['filename']); |
|
1933
|
|
|
} // ----- Look for path to remove |
|
1934
|
|
|
elseif ($p_remove_path != '') { |
|
1935
|
|
|
//if (strcmp($p_remove_path, $p_entry['filename'])==0) |
|
1936
|
|
|
if ($this->_tool_PathInclusion($p_remove_path, $p_entry['filename']) == 2) { |
|
1937
|
|
|
|
|
1938
|
|
|
// ----- Change the file status |
|
1939
|
|
|
$p_entry['status'] = 'filtered'; |
|
1940
|
|
|
|
|
1941
|
|
|
// ----- Return |
|
1942
|
|
|
return $v_result; |
|
1943
|
|
|
} |
|
1944
|
|
|
|
|
1945
|
|
|
$p_remove_path_size = strlen($p_remove_path); |
|
1946
|
|
|
if (substr($p_entry['filename'], 0, $p_remove_path_size) == $p_remove_path) { |
|
1947
|
|
|
|
|
1948
|
|
|
// ----- Remove the path |
|
1949
|
|
|
$p_entry['filename'] = substr($p_entry['filename'], $p_remove_path_size); |
|
1950
|
|
|
} |
|
1951
|
|
|
} |
|
1952
|
|
|
|
|
1953
|
|
|
// ----- Add the path |
|
1954
|
|
|
if ($p_path != '') { |
|
1955
|
|
|
$p_entry['filename'] = $p_path . '/' . $p_entry['filename']; |
|
1956
|
|
|
} |
|
1957
|
|
|
|
|
1958
|
|
|
// ----- Look for pre-extract callback |
|
1959
|
|
|
if (isset($p_params[ARCHIVE_ZIP_PARAM_PRE_EXTRACT]) && ($p_params[ARCHIVE_ZIP_PARAM_PRE_EXTRACT] != '')) { |
|
1960
|
|
|
|
|
1961
|
|
|
// ----- Generate a local information |
|
1962
|
|
|
$v_local_header = array(); |
|
1963
|
|
|
$this->_convertHeader2FileInfo($p_entry, $v_local_header); |
|
1964
|
|
|
|
|
1965
|
|
|
// ----- Call the callback |
|
1966
|
|
|
// Here I do not use call_user_func() because I need to send a reference to the |
|
1967
|
|
|
// header. |
|
1968
|
|
|
eval('$v_result = ' . $p_params[ARCHIVE_ZIP_PARAM_PRE_EXTRACT] . '(ARCHIVE_ZIP_PARAM_PRE_EXTRACT, $v_local_header);'); |
|
1969
|
|
|
if ($v_result == 0) { |
|
1970
|
|
|
// ----- Change the file status |
|
1971
|
|
|
$p_entry['status'] = 'skipped'; |
|
1972
|
|
|
$v_result = 1; |
|
1973
|
|
|
} |
|
1974
|
|
|
|
|
1975
|
|
|
// ----- Update the informations |
|
1976
|
|
|
// Only some fields can be modified |
|
1977
|
|
|
$p_entry['filename'] = $v_local_header['filename']; |
|
1978
|
|
|
} |
|
1979
|
|
|
|
|
1980
|
|
|
// ----- Trace |
|
1981
|
|
|
|
|
1982
|
|
|
// ----- Look if extraction should be done |
|
1983
|
|
|
if ($p_entry['status'] === 'ok') { |
|
1984
|
|
|
|
|
1985
|
|
|
// ----- Look for specific actions while the file exist |
|
1986
|
|
|
if (file_exists($p_entry['filename'])) { |
|
1987
|
|
|
|
|
1988
|
|
|
// ----- Look if file is a directory |
|
1989
|
|
|
if (is_dir($p_entry['filename'])) { |
|
1990
|
|
|
|
|
1991
|
|
|
// ----- Change the file status |
|
1992
|
|
|
$p_entry['status'] = 'already_a_directory'; |
|
1993
|
|
|
|
|
1994
|
|
|
// ----- Return |
|
1995
|
|
|
//return $v_result; |
|
1996
|
|
|
} // ----- Look if file is write protected |
|
1997
|
|
|
elseif (!is_writable($p_entry['filename'])) { |
|
1998
|
|
|
|
|
1999
|
|
|
// ----- Change the file status |
|
2000
|
|
|
$p_entry['status'] = 'write_protected'; |
|
2001
|
|
|
|
|
2002
|
|
|
// ----- Return |
|
2003
|
|
|
//return $v_result; |
|
2004
|
|
|
} // ----- Look if the extracted file is older |
|
2005
|
|
|
elseif (filemtime($p_entry['filename']) > $p_entry['mtime']) { |
|
2006
|
|
|
|
|
2007
|
|
|
// ----- Change the file status |
|
2008
|
|
|
$p_entry['status'] = 'newer_exist'; |
|
2009
|
|
|
|
|
2010
|
|
|
// ----- Return |
|
2011
|
|
|
//return $v_result; |
|
2012
|
|
|
} |
|
2013
|
|
|
} // ----- Check the directory availability and create it if necessary |
|
2014
|
|
|
else { |
|
2015
|
|
|
if ((($p_entry['external'] & 0x00000010) == 0x00000010) || (substr($p_entry['filename'], -1) === '/')) { |
|
2016
|
|
|
$v_dir_to_check = $p_entry['filename']; |
|
2017
|
|
|
} elseif (false === strpos($p_entry['filename'], '/')) { |
|
2018
|
|
|
$v_dir_to_check = ''; |
|
2019
|
|
|
} else { |
|
2020
|
|
|
$v_dir_to_check = dirname($p_entry['filename']); |
|
2021
|
|
|
} |
|
2022
|
|
|
|
|
2023
|
|
|
if (($v_result = $this->_dirCheck($v_dir_to_check, ($p_entry['external'] & 0x00000010) == 0x00000010)) != 1) { |
|
2024
|
|
|
|
|
2025
|
|
|
// ----- Change the file status |
|
2026
|
|
|
$p_entry['status'] = 'path_creation_fail'; |
|
2027
|
|
|
|
|
2028
|
|
|
// ----- Return |
|
2029
|
|
|
//return $v_result; |
|
2030
|
|
|
$v_result = 1; |
|
2031
|
|
|
} |
|
2032
|
|
|
} |
|
2033
|
|
|
} |
|
2034
|
|
|
|
|
2035
|
|
|
// ----- Look if extraction should be done |
|
2036
|
|
|
if ($p_entry['status'] === 'ok') { |
|
2037
|
|
|
|
|
2038
|
|
|
// ----- Do the extraction (if not a folder) |
|
2039
|
|
|
if (!(($p_entry['external'] & 0x00000010) == 0x00000010)) { |
|
2040
|
|
|
|
|
2041
|
|
|
// ----- Look for not compressed file |
|
2042
|
|
|
if ($p_entry['compressed_size'] == $p_entry['size']) { |
|
2043
|
|
|
|
|
2044
|
|
|
// ----- Opening destination file |
|
2045
|
|
View Code Duplication |
if (($v_dest_file = @fopen($p_entry['filename'], 'wb')) == 0) { |
|
|
|
|
|
|
2046
|
|
|
|
|
2047
|
|
|
// ----- Change the file status |
|
2048
|
|
|
$p_entry['status'] = 'write_error'; |
|
2049
|
|
|
|
|
2050
|
|
|
// ----- Return |
|
2051
|
|
|
return $v_result; |
|
2052
|
|
|
} |
|
2053
|
|
|
|
|
2054
|
|
|
// ----- Read the file by ARCHIVE_ZIP_READ_BLOCK_SIZE octets blocks |
|
2055
|
|
|
$v_size = $p_entry['compressed_size']; |
|
2056
|
|
|
while ($v_size != 0) { |
|
2057
|
|
|
$v_read_size = ($v_size < ARCHIVE_ZIP_READ_BLOCK_SIZE ? $v_size : ARCHIVE_ZIP_READ_BLOCK_SIZE); |
|
2058
|
|
|
$v_buffer = fread($this->_zip_fd, $v_read_size); |
|
2059
|
|
|
$v_binary_data = pack('a' . $v_read_size, $v_buffer); |
|
2060
|
|
|
@fwrite($v_dest_file, $v_binary_data, $v_read_size); |
|
|
|
|
|
|
2061
|
|
|
$v_size -= $v_read_size; |
|
2062
|
|
|
} |
|
2063
|
|
|
|
|
2064
|
|
|
// ----- Closing the destination file |
|
2065
|
|
|
fclose($v_dest_file); |
|
2066
|
|
|
|
|
2067
|
|
|
// ----- Change the file mtime |
|
2068
|
|
|
touch($p_entry['filename'], $p_entry['mtime']); |
|
2069
|
|
|
} else { |
|
2070
|
|
|
// ----- Trace |
|
2071
|
|
|
|
|
2072
|
|
|
// ----- Opening destination file |
|
2073
|
|
View Code Duplication |
if (($v_dest_file = @fopen($p_entry['filename'], 'wb')) == 0) { |
|
|
|
|
|
|
2074
|
|
|
|
|
2075
|
|
|
// ----- Change the file status |
|
2076
|
|
|
$p_entry['status'] = 'write_error'; |
|
2077
|
|
|
|
|
2078
|
|
|
return $v_result; |
|
2079
|
|
|
} |
|
2080
|
|
|
|
|
2081
|
|
|
// ----- Read the compressed file in a buffer (one shot) |
|
2082
|
|
|
$v_buffer = @fread($this->_zip_fd, $p_entry['compressed_size']); |
|
2083
|
|
|
|
|
2084
|
|
|
// ----- Decompress the file |
|
2085
|
|
|
$v_file_content = gzinflate($v_buffer); |
|
2086
|
|
|
unset($v_buffer); |
|
2087
|
|
|
|
|
2088
|
|
|
// ----- Write the uncompressed data |
|
2089
|
|
|
@fwrite($v_dest_file, $v_file_content, $p_entry['size']); |
|
|
|
|
|
|
2090
|
|
|
unset($v_file_content); |
|
2091
|
|
|
|
|
2092
|
|
|
// ----- Closing the destination file |
|
2093
|
|
|
@fclose($v_dest_file); |
|
|
|
|
|
|
2094
|
|
|
|
|
2095
|
|
|
// ----- Change the file mtime |
|
2096
|
|
|
touch($p_entry['filename'], $p_entry['mtime']); |
|
2097
|
|
|
} |
|
2098
|
|
|
|
|
2099
|
|
|
// ----- Look for chmod option |
|
2100
|
|
|
if (isset($p_params[ARCHIVE_ZIP_PARAM_SET_CHMOD]) && ($p_params[ARCHIVE_ZIP_PARAM_SET_CHMOD] != 0)) { |
|
2101
|
|
|
|
|
2102
|
|
|
// ----- Change the mode of the file |
|
2103
|
|
|
chmod($p_entry['filename'], $p_params[ARCHIVE_ZIP_PARAM_SET_CHMOD]); |
|
2104
|
|
|
} |
|
2105
|
|
|
} |
|
2106
|
|
|
} |
|
2107
|
|
|
|
|
2108
|
|
|
// ----- Look for post-extract callback |
|
2109
|
|
|
if (isset($p_params[ARCHIVE_ZIP_PARAM_POST_EXTRACT]) && ($p_params[ARCHIVE_ZIP_PARAM_POST_EXTRACT] != '')) { |
|
2110
|
|
|
|
|
2111
|
|
|
// ----- Generate a local information |
|
2112
|
|
|
$v_local_header = array(); |
|
2113
|
|
|
$this->_convertHeader2FileInfo($p_entry, $v_local_header); |
|
2114
|
|
|
|
|
2115
|
|
|
// ----- Call the callback |
|
2116
|
|
|
// Here I do not use call_user_func() because I need to send a reference to the |
|
2117
|
|
|
// header. |
|
2118
|
|
|
eval('$v_result = ' . $p_params[ARCHIVE_ZIP_PARAM_POST_EXTRACT] . '(ARCHIVE_ZIP_PARAM_POST_EXTRACT, $v_local_header);'); |
|
2119
|
|
|
} |
|
2120
|
|
|
|
|
2121
|
|
|
// ----- Return |
|
2122
|
|
|
return $v_result; |
|
2123
|
|
|
} |
|
2124
|
|
|
|
|
2125
|
|
|
// --------------------------------------------------------------------------- |
|
2126
|
|
|
|
|
2127
|
|
|
// --------------------------------------------------------------------------- |
|
2128
|
|
|
// Function : _extractFileAsString() |
|
2129
|
|
|
// Description : |
|
2130
|
|
|
// Parameters : |
|
2131
|
|
|
// Return Values : |
|
2132
|
|
|
// --------------------------------------------------------------------------- |
|
2133
|
|
|
/** |
|
2134
|
|
|
* Archive_Zip::_extractFileAsString() |
|
2135
|
|
|
* |
|
2136
|
|
|
* { Description } |
|
2137
|
|
|
* @param $p_entry |
|
2138
|
|
|
* @param $p_string |
|
2139
|
|
|
* @return int |
|
2140
|
|
|
*/ |
|
2141
|
|
|
public function _extractFileAsString(&$p_entry, &$p_string) |
|
2142
|
|
|
{ |
|
2143
|
|
|
$v_result = 1; |
|
|
|
|
|
|
2144
|
|
|
|
|
2145
|
|
|
// ----- Read the file header |
|
2146
|
|
|
$v_header = array(); |
|
2147
|
|
|
if (($v_result = $this->_readFileHeader($v_header)) != 1) { |
|
2148
|
|
|
// ----- Return |
|
2149
|
|
|
return $v_result; |
|
2150
|
|
|
} |
|
2151
|
|
|
|
|
2152
|
|
|
// ----- Check that the file header is coherent with $p_entry info |
|
2153
|
|
|
// TBC |
|
2154
|
|
|
|
|
2155
|
|
|
// ----- Trace |
|
2156
|
|
|
|
|
2157
|
|
|
// ----- Do the extraction (if not a folder) |
|
2158
|
|
|
if (!(($p_entry['external'] & 0x00000010) == 0x00000010)) { |
|
2159
|
|
|
// ----- Look for not compressed file |
|
2160
|
|
|
if ($p_entry['compressed_size'] == $p_entry['size']) { |
|
2161
|
|
|
// ----- Trace |
|
2162
|
|
|
|
|
2163
|
|
|
// ----- Reading the file |
|
2164
|
|
|
$p_string = fread($this->_zip_fd, $p_entry['compressed_size']); |
|
2165
|
|
|
} else { |
|
2166
|
|
|
// ----- Trace |
|
2167
|
|
|
|
|
2168
|
|
|
// ----- Reading the file |
|
2169
|
|
|
$v_data = fread($this->_zip_fd, $p_entry['compressed_size']); |
|
2170
|
|
|
|
|
2171
|
|
|
// ----- Decompress the file |
|
2172
|
|
|
$p_string = gzinflate($v_data); |
|
2173
|
|
|
} |
|
2174
|
|
|
|
|
2175
|
|
|
// ----- Trace |
|
2176
|
|
|
} else { |
|
2177
|
|
|
// TBC : error : can not extract a folder in a string |
|
2178
|
|
|
} |
|
2179
|
|
|
|
|
2180
|
|
|
// ----- Return |
|
2181
|
|
|
return $v_result; |
|
2182
|
|
|
} |
|
2183
|
|
|
|
|
2184
|
|
|
// --------------------------------------------------------------------------- |
|
2185
|
|
|
|
|
2186
|
|
|
// --------------------------------------------------------------------------- |
|
2187
|
|
|
// Function : _readFileHeader() |
|
2188
|
|
|
// Description : |
|
2189
|
|
|
// Parameters : |
|
2190
|
|
|
// Return Values : |
|
2191
|
|
|
// --------------------------------------------------------------------------- |
|
2192
|
|
|
/** |
|
2193
|
|
|
* Archive_Zip::_readFileHeader() |
|
2194
|
|
|
* |
|
2195
|
|
|
* { Description } |
|
2196
|
|
|
* @param $p_header |
|
2197
|
|
|
* @return int |
|
2198
|
|
|
*/ |
|
2199
|
|
|
public function _readFileHeader(&$p_header) |
|
2200
|
|
|
{ |
|
2201
|
|
|
$v_result = 1; |
|
2202
|
|
|
|
|
2203
|
|
|
// ----- Read the 4 bytes signature |
|
2204
|
|
|
$v_binary_data = @fread($this->_zip_fd, 4); |
|
2205
|
|
|
$v_data = unpack('Vid', $v_binary_data); |
|
2206
|
|
|
|
|
2207
|
|
|
// ----- Check signature |
|
2208
|
|
|
if ($v_data['id'] != 0x04034b50) { |
|
2209
|
|
|
|
|
2210
|
|
|
// ----- Error log |
|
2211
|
|
|
$this->_errorLog(ARCHIVE_ZIP_ERR_BAD_FORMAT, 'Invalid archive structure'); |
|
2212
|
|
|
|
|
2213
|
|
|
// ----- Return |
|
2214
|
|
|
return Archive_Zip::errorCode(); |
|
2215
|
|
|
} |
|
2216
|
|
|
|
|
2217
|
|
|
// ----- Read the first 42 bytes of the header |
|
2218
|
|
|
$v_binary_data = fread($this->_zip_fd, 26); |
|
2219
|
|
|
|
|
2220
|
|
|
// ----- Look for invalid block size |
|
2221
|
|
View Code Duplication |
if (strlen($v_binary_data) != 26) { |
|
|
|
|
|
|
2222
|
|
|
$p_header['filename'] = ''; |
|
2223
|
|
|
$p_header['status'] = 'invalid_header'; |
|
2224
|
|
|
|
|
2225
|
|
|
// ----- Error log |
|
2226
|
|
|
$this->_errorLog(ARCHIVE_ZIP_ERR_BAD_FORMAT, 'Invalid block size : ' . strlen($v_binary_data)); |
|
2227
|
|
|
|
|
2228
|
|
|
// ----- Return |
|
2229
|
|
|
return Archive_Zip::errorCode(); |
|
2230
|
|
|
} |
|
2231
|
|
|
|
|
2232
|
|
|
// ----- Extract the values |
|
2233
|
|
|
$v_data = unpack('vversion/vflag/vcompression/vmtime/vmdate/Vcrc/Vcompressed_size/Vsize/vfilename_len/vextra_len', $v_binary_data); |
|
2234
|
|
|
|
|
2235
|
|
|
// ----- Get filename |
|
2236
|
|
|
$p_header['filename'] = fread($this->_zip_fd, $v_data['filename_len']); |
|
2237
|
|
|
|
|
2238
|
|
|
// ----- Get extra_fields |
|
2239
|
|
|
if ($v_data['extra_len'] != 0) { |
|
2240
|
|
|
$p_header['extra'] = fread($this->_zip_fd, $v_data['extra_len']); |
|
2241
|
|
|
} else { |
|
2242
|
|
|
$p_header['extra'] = ''; |
|
2243
|
|
|
} |
|
2244
|
|
|
|
|
2245
|
|
|
// ----- Extract properties |
|
2246
|
|
|
$p_header['compression'] = $v_data['compression']; |
|
2247
|
|
|
$p_header['size'] = $v_data['size']; |
|
2248
|
|
|
$p_header['compressed_size'] = $v_data['compressed_size']; |
|
2249
|
|
|
$p_header['crc'] = $v_data['crc']; |
|
2250
|
|
|
$p_header['flag'] = $v_data['flag']; |
|
2251
|
|
|
|
|
2252
|
|
|
// ----- Recuperate date in UNIX format |
|
2253
|
|
|
$p_header['mdate'] = $v_data['mdate']; |
|
2254
|
|
|
$p_header['mtime'] = $v_data['mtime']; |
|
2255
|
|
View Code Duplication |
if ($p_header['mdate'] && $p_header['mtime']) { |
|
|
|
|
|
|
2256
|
|
|
// ----- Extract time |
|
2257
|
|
|
$v_hour = ($p_header['mtime'] & 0xF800) >> 11; |
|
2258
|
|
|
$v_minute = ($p_header['mtime'] & 0x07E0) >> 5; |
|
2259
|
|
|
$v_seconde = ($p_header['mtime'] & 0x001F) * 2; |
|
2260
|
|
|
|
|
2261
|
|
|
// ----- Extract date |
|
2262
|
|
|
$v_year = (($p_header['mdate'] & 0xFE00) >> 9) + 1980; |
|
2263
|
|
|
$v_month = ($p_header['mdate'] & 0x01E0) >> 5; |
|
2264
|
|
|
$v_day = $p_header['mdate'] & 0x001F; |
|
2265
|
|
|
|
|
2266
|
|
|
// ----- Get UNIX date format |
|
2267
|
|
|
$p_header['mtime'] = mktime($v_hour, $v_minute, $v_seconde, $v_month, $v_day, $v_year); |
|
2268
|
|
|
} else { |
|
2269
|
|
|
$p_header['mtime'] = time(); |
|
2270
|
|
|
} |
|
2271
|
|
|
|
|
2272
|
|
|
// ----- Other informations |
|
2273
|
|
|
|
|
2274
|
|
|
// TBC |
|
2275
|
|
|
//for (reset($v_data); $key = key($v_data); next($v_data)) { |
|
2276
|
|
|
//} |
|
2277
|
|
|
|
|
2278
|
|
|
// ----- Set the stored filename |
|
2279
|
|
|
$p_header['stored_filename'] = $p_header['filename']; |
|
2280
|
|
|
|
|
2281
|
|
|
// ----- Set the status field |
|
2282
|
|
|
$p_header['status'] = 'ok'; |
|
2283
|
|
|
|
|
2284
|
|
|
// ----- Return |
|
2285
|
|
|
return $v_result; |
|
2286
|
|
|
} |
|
2287
|
|
|
|
|
2288
|
|
|
// --------------------------------------------------------------------------- |
|
2289
|
|
|
|
|
2290
|
|
|
// --------------------------------------------------------------------------- |
|
2291
|
|
|
// Function : _readCentralFileHeader() |
|
2292
|
|
|
// Description : |
|
2293
|
|
|
// Parameters : |
|
2294
|
|
|
// Return Values : |
|
2295
|
|
|
// --------------------------------------------------------------------------- |
|
2296
|
|
|
/** |
|
2297
|
|
|
* Archive_Zip::_readCentralFileHeader() |
|
2298
|
|
|
* |
|
2299
|
|
|
* { Description } |
|
2300
|
|
|
* @param $p_header |
|
2301
|
|
|
* @return int |
|
2302
|
|
|
*/ |
|
2303
|
|
|
public function _readCentralFileHeader(&$p_header) |
|
2304
|
|
|
{ |
|
2305
|
|
|
$v_result = 1; |
|
2306
|
|
|
|
|
2307
|
|
|
// ----- Read the 4 bytes signature |
|
2308
|
|
|
$v_binary_data = @fread($this->_zip_fd, 4); |
|
2309
|
|
|
$v_data = unpack('Vid', $v_binary_data); |
|
2310
|
|
|
|
|
2311
|
|
|
// ----- Check signature |
|
2312
|
|
|
if ($v_data['id'] != 0x02014b50) { |
|
2313
|
|
|
|
|
2314
|
|
|
// ----- Error log |
|
2315
|
|
|
$this->_errorLog(ARCHIVE_ZIP_ERR_BAD_FORMAT, 'Invalid archive structure'); |
|
2316
|
|
|
|
|
2317
|
|
|
// ----- Return |
|
2318
|
|
|
return Archive_Zip::errorCode(); |
|
2319
|
|
|
} |
|
2320
|
|
|
|
|
2321
|
|
|
// ----- Read the first 42 bytes of the header |
|
2322
|
|
|
$v_binary_data = fread($this->_zip_fd, 42); |
|
2323
|
|
|
|
|
2324
|
|
|
// ----- Look for invalid block size |
|
2325
|
|
View Code Duplication |
if (strlen($v_binary_data) != 42) { |
|
|
|
|
|
|
2326
|
|
|
$p_header['filename'] = ''; |
|
2327
|
|
|
$p_header['status'] = 'invalid_header'; |
|
2328
|
|
|
|
|
2329
|
|
|
// ----- Error log |
|
2330
|
|
|
$this->_errorLog(ARCHIVE_ZIP_ERR_BAD_FORMAT, 'Invalid block size : ' . strlen($v_binary_data)); |
|
2331
|
|
|
|
|
2332
|
|
|
// ----- Return |
|
2333
|
|
|
return Archive_Zip::errorCode(); |
|
2334
|
|
|
} |
|
2335
|
|
|
|
|
2336
|
|
|
// ----- Extract the values |
|
2337
|
|
|
$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); |
|
2338
|
|
|
|
|
2339
|
|
|
// ----- Get filename |
|
2340
|
|
View Code Duplication |
if ($p_header['filename_len'] != 0) { |
|
|
|
|
|
|
2341
|
|
|
$p_header['filename'] = fread($this->_zip_fd, $p_header['filename_len']); |
|
2342
|
|
|
} else { |
|
2343
|
|
|
$p_header['filename'] = ''; |
|
2344
|
|
|
} |
|
2345
|
|
|
|
|
2346
|
|
|
// ----- Get extra |
|
2347
|
|
View Code Duplication |
if ($p_header['extra_len'] != 0) { |
|
|
|
|
|
|
2348
|
|
|
$p_header['extra'] = fread($this->_zip_fd, $p_header['extra_len']); |
|
2349
|
|
|
} else { |
|
2350
|
|
|
$p_header['extra'] = ''; |
|
2351
|
|
|
} |
|
2352
|
|
|
|
|
2353
|
|
|
// ----- Get comment |
|
2354
|
|
View Code Duplication |
if ($p_header['comment_len'] != 0) { |
|
|
|
|
|
|
2355
|
|
|
$p_header['comment'] = fread($this->_zip_fd, $p_header['comment_len']); |
|
2356
|
|
|
} else { |
|
2357
|
|
|
$p_header['comment'] = ''; |
|
2358
|
|
|
} |
|
2359
|
|
|
|
|
2360
|
|
|
// ----- Extract properties |
|
2361
|
|
|
|
|
2362
|
|
|
// ----- Recuperate date in UNIX format |
|
2363
|
|
View Code Duplication |
if ($p_header['mdate'] && $p_header['mtime']) { |
|
|
|
|
|
|
2364
|
|
|
// ----- Extract time |
|
2365
|
|
|
$v_hour = ($p_header['mtime'] & 0xF800) >> 11; |
|
2366
|
|
|
$v_minute = ($p_header['mtime'] & 0x07E0) >> 5; |
|
2367
|
|
|
$v_seconde = ($p_header['mtime'] & 0x001F) * 2; |
|
2368
|
|
|
|
|
2369
|
|
|
// ----- Extract date |
|
2370
|
|
|
$v_year = (($p_header['mdate'] & 0xFE00) >> 9) + 1980; |
|
2371
|
|
|
$v_month = ($p_header['mdate'] & 0x01E0) >> 5; |
|
2372
|
|
|
$v_day = $p_header['mdate'] & 0x001F; |
|
2373
|
|
|
|
|
2374
|
|
|
// ----- Get UNIX date format |
|
2375
|
|
|
$p_header['mtime'] = mktime($v_hour, $v_minute, $v_seconde, $v_month, $v_day, $v_year); |
|
2376
|
|
|
} else { |
|
2377
|
|
|
$p_header['mtime'] = time(); |
|
2378
|
|
|
} |
|
2379
|
|
|
|
|
2380
|
|
|
// ----- Set the stored filename |
|
2381
|
|
|
$p_header['stored_filename'] = $p_header['filename']; |
|
2382
|
|
|
|
|
2383
|
|
|
// ----- Set default status to ok |
|
2384
|
|
|
$p_header['status'] = 'ok'; |
|
2385
|
|
|
|
|
2386
|
|
|
// ----- Look if it is a directory |
|
2387
|
|
|
if (substr($p_header['filename'], -1) === '/') { |
|
2388
|
|
|
$p_header['external'] = 0x41FF0010; |
|
2389
|
|
|
} |
|
2390
|
|
|
|
|
2391
|
|
|
// ----- Return |
|
2392
|
|
|
return $v_result; |
|
2393
|
|
|
} |
|
2394
|
|
|
|
|
2395
|
|
|
// --------------------------------------------------------------------------- |
|
2396
|
|
|
|
|
2397
|
|
|
// --------------------------------------------------------------------------- |
|
2398
|
|
|
// Function : _readEndCentralDir() |
|
2399
|
|
|
// Description : |
|
2400
|
|
|
// Parameters : |
|
2401
|
|
|
// Return Values : |
|
2402
|
|
|
// --------------------------------------------------------------------------- |
|
2403
|
|
|
/** |
|
2404
|
|
|
* Archive_Zip::_readEndCentralDir() |
|
2405
|
|
|
* |
|
2406
|
|
|
* { Description } |
|
2407
|
|
|
* @param $p_central_dir |
|
2408
|
|
|
* @return int |
|
2409
|
|
|
*/ |
|
2410
|
|
|
public function _readEndCentralDir(&$p_central_dir) |
|
2411
|
|
|
{ |
|
2412
|
|
|
$v_result = 1; |
|
2413
|
|
|
|
|
2414
|
|
|
// ----- Go to the end of the zip file |
|
2415
|
|
|
$v_size = filesize($this->_zipname); |
|
2416
|
|
|
@fseek($this->_zip_fd, $v_size); |
|
|
|
|
|
|
2417
|
|
View Code Duplication |
if (@ftell($this->_zip_fd) != $v_size) { |
|
|
|
|
|
|
2418
|
|
|
$this->_errorLog(ARCHIVE_ZIP_ERR_BAD_FORMAT, 'Unable to go to the end of the archive \'' . $this->_zipname . '\''); |
|
2419
|
|
|
|
|
2420
|
|
|
return Archive_Zip::errorCode(); |
|
2421
|
|
|
} |
|
2422
|
|
|
|
|
2423
|
|
|
// ----- First try : look if this is an archive with no commentaries |
|
2424
|
|
|
// (most of the time) |
|
2425
|
|
|
// in this case the end of central dir is at 22 bytes of the file end |
|
2426
|
|
|
$v_found = 0; |
|
2427
|
|
|
if ($v_size > 26) { |
|
2428
|
|
|
@fseek($this->_zip_fd, $v_size - 22); |
|
|
|
|
|
|
2429
|
|
View Code Duplication |
if (($v_pos = @ftell($this->_zip_fd)) != ($v_size - 22)) { |
|
|
|
|
|
|
2430
|
|
|
$this->_errorLog(ARCHIVE_ZIP_ERR_BAD_FORMAT, 'Unable to seek back to the middle of the archive \'' . $this->_zipname . '\''); |
|
2431
|
|
|
|
|
2432
|
|
|
return Archive_Zip::errorCode(); |
|
2433
|
|
|
} |
|
2434
|
|
|
|
|
2435
|
|
|
// ----- Read for bytes |
|
2436
|
|
|
$v_binary_data = @fread($this->_zip_fd, 4); |
|
2437
|
|
|
$v_data = unpack('Vid', $v_binary_data); |
|
2438
|
|
|
|
|
2439
|
|
|
// ----- Check signature |
|
2440
|
|
|
if ($v_data['id'] == 0x06054b50) { |
|
2441
|
|
|
$v_found = 1; |
|
2442
|
|
|
} |
|
2443
|
|
|
|
|
2444
|
|
|
$v_pos = ftell($this->_zip_fd); |
|
2445
|
|
|
} |
|
2446
|
|
|
|
|
2447
|
|
|
// ----- Go back to the maximum possible size of the Central Dir End Record |
|
2448
|
|
|
if (!$v_found) { |
|
2449
|
|
|
$v_maximum_size = 65557; // 0xFFFF + 22; |
|
2450
|
|
|
if ($v_maximum_size > $v_size) { |
|
2451
|
|
|
$v_maximum_size = $v_size; |
|
2452
|
|
|
} |
|
2453
|
|
|
@fseek($this->_zip_fd, $v_size - $v_maximum_size); |
|
|
|
|
|
|
2454
|
|
View Code Duplication |
if (@ftell($this->_zip_fd) != ($v_size - $v_maximum_size)) { |
|
|
|
|
|
|
2455
|
|
|
$this->_errorLog(ARCHIVE_ZIP_ERR_BAD_FORMAT, 'Unable to seek back to the middle of the archive \'' . $this->_zipname . '\''); |
|
2456
|
|
|
|
|
2457
|
|
|
return Archive_Zip::errorCode(); |
|
2458
|
|
|
} |
|
2459
|
|
|
|
|
2460
|
|
|
// ----- Read byte per byte in order to find the signature |
|
2461
|
|
|
$v_pos = ftell($this->_zip_fd); |
|
2462
|
|
|
$v_bytes = 0x00000000; |
|
2463
|
|
|
while ($v_pos < $v_size) { |
|
2464
|
|
|
// ----- Read a byte |
|
2465
|
|
|
$v_byte = @fread($this->_zip_fd, 1); |
|
2466
|
|
|
|
|
2467
|
|
|
// ----- Add the byte |
|
2468
|
|
|
$v_bytes = ($v_bytes << 8) | ord($v_byte); |
|
2469
|
|
|
|
|
2470
|
|
|
// ----- Compare the bytes |
|
2471
|
|
|
if ($v_bytes == 0x504b0506) { |
|
2472
|
|
|
++$v_pos; |
|
2473
|
|
|
break; |
|
2474
|
|
|
} |
|
2475
|
|
|
|
|
2476
|
|
|
++$v_pos; |
|
2477
|
|
|
} |
|
2478
|
|
|
|
|
2479
|
|
|
// ----- Look if not found end of central dir |
|
2480
|
|
|
if ($v_pos == $v_size) { |
|
2481
|
|
|
$this->_errorLog(ARCHIVE_ZIP_ERR_BAD_FORMAT, 'Unable to find End of Central Dir Record signature'); |
|
2482
|
|
|
|
|
2483
|
|
|
return Archive_Zip::errorCode(); |
|
2484
|
|
|
} |
|
2485
|
|
|
} |
|
2486
|
|
|
|
|
2487
|
|
|
// ----- Read the first 18 bytes of the header |
|
2488
|
|
|
$v_binary_data = fread($this->_zip_fd, 18); |
|
2489
|
|
|
|
|
2490
|
|
|
// ----- Look for invalid block size |
|
2491
|
|
|
if (strlen($v_binary_data) != 18) { |
|
2492
|
|
|
$this->_errorLog(ARCHIVE_ZIP_ERR_BAD_FORMAT, 'Invalid End of Central Dir Record size : ' . strlen($v_binary_data)); |
|
2493
|
|
|
|
|
2494
|
|
|
return Archive_Zip::errorCode(); |
|
2495
|
|
|
} |
|
2496
|
|
|
|
|
2497
|
|
|
// ----- Extract the values |
|
2498
|
|
|
$v_data = unpack('vdisk/vdisk_start/vdisk_entries/ventries/Vsize/Voffset/vcomment_size', $v_binary_data); |
|
2499
|
|
|
|
|
2500
|
|
|
// ----- Check the global size |
|
2501
|
|
|
if (($v_pos + $v_data['comment_size'] + 18) != $v_size) { |
|
|
|
|
|
|
2502
|
|
|
$this->_errorLog(ARCHIVE_ZIP_ERR_BAD_FORMAT, 'Fail to find the right signature'); |
|
2503
|
|
|
|
|
2504
|
|
|
return Archive_Zip::errorCode(); |
|
2505
|
|
|
} |
|
2506
|
|
|
|
|
2507
|
|
|
// ----- Get comment |
|
2508
|
|
|
if ($v_data['comment_size'] != 0) { |
|
2509
|
|
|
$p_central_dir['comment'] = fread($this->_zip_fd, $v_data['comment_size']); |
|
2510
|
|
|
} else { |
|
2511
|
|
|
$p_central_dir['comment'] = ''; |
|
2512
|
|
|
} |
|
2513
|
|
|
|
|
2514
|
|
|
$p_central_dir['entries'] = $v_data['entries']; |
|
2515
|
|
|
$p_central_dir['disk_entries'] = $v_data['disk_entries']; |
|
2516
|
|
|
$p_central_dir['offset'] = $v_data['offset']; |
|
2517
|
|
|
$p_central_dir['size'] = $v_data['size']; |
|
2518
|
|
|
$p_central_dir['disk'] = $v_data['disk']; |
|
2519
|
|
|
$p_central_dir['disk_start'] = $v_data['disk_start']; |
|
2520
|
|
|
|
|
2521
|
|
|
// ----- Return |
|
2522
|
|
|
return $v_result; |
|
2523
|
|
|
} |
|
2524
|
|
|
|
|
2525
|
|
|
// --------------------------------------------------------------------------- |
|
2526
|
|
|
|
|
2527
|
|
|
// --------------------------------------------------------------------------- |
|
2528
|
|
|
// Function : _deleteByRule() |
|
2529
|
|
|
// Description : |
|
2530
|
|
|
// Parameters : |
|
2531
|
|
|
// Return Values : |
|
2532
|
|
|
// --------------------------------------------------------------------------- |
|
2533
|
|
|
/** |
|
2534
|
|
|
* Archive_Zip::_deleteByRule() |
|
2535
|
|
|
* |
|
2536
|
|
|
* { Description } |
|
2537
|
|
|
* @param $p_result_list |
|
2538
|
|
|
* @param $p_params |
|
2539
|
|
|
* @return int |
|
2540
|
|
|
*/ |
|
2541
|
|
|
public function _deleteByRule(&$p_result_list, &$p_params) |
|
2542
|
|
|
{ |
|
2543
|
|
|
$v_result = 1; |
|
|
|
|
|
|
2544
|
|
|
$v_list_detail = array(); |
|
|
|
|
|
|
2545
|
|
|
|
|
2546
|
|
|
// ----- Open the zip file |
|
2547
|
|
|
if (($v_result = $this->_openFd('rb')) != 1) { |
|
2548
|
|
|
// ----- Return |
|
2549
|
|
|
return $v_result; |
|
2550
|
|
|
} |
|
2551
|
|
|
|
|
2552
|
|
|
// ----- Read the central directory informations |
|
2553
|
|
|
$v_central_dir = array(); |
|
2554
|
|
|
if (($v_result = $this->_readEndCentralDir($v_central_dir)) != 1) { |
|
2555
|
|
|
$this->_closeFd(); |
|
2556
|
|
|
|
|
2557
|
|
|
return $v_result; |
|
2558
|
|
|
} |
|
2559
|
|
|
|
|
2560
|
|
|
// ----- Go to beginning of File |
|
2561
|
|
|
@rewind($this->_zip_fd); |
|
|
|
|
|
|
2562
|
|
|
|
|
2563
|
|
|
// ----- Scan all the files |
|
2564
|
|
|
// ----- Start at beginning of Central Dir |
|
2565
|
|
|
$v_pos_entry = $v_central_dir['offset']; |
|
2566
|
|
|
@rewind($this->_zip_fd); |
|
|
|
|
|
|
2567
|
|
View Code Duplication |
if (@fseek($this->_zip_fd, $v_pos_entry)) { |
|
|
|
|
|
|
2568
|
|
|
// ----- Clean |
|
2569
|
|
|
$this->_closeFd(); |
|
2570
|
|
|
|
|
2571
|
|
|
$this->_errorLog(ARCHIVE_ZIP_ERR_INVALID_ARCHIVE_ZIP, 'Invalid archive size'); |
|
2572
|
|
|
|
|
2573
|
|
|
return Archive_Zip::errorCode(); |
|
2574
|
|
|
} |
|
2575
|
|
|
|
|
2576
|
|
|
// ----- Read each entry |
|
2577
|
|
|
$v_header_list = array(); |
|
2578
|
|
|
$j_start = 0; |
|
2579
|
|
|
for ($i = 0, $v_nb_extracted = 0; $i < $v_central_dir['entries']; ++$i) { |
|
2580
|
|
|
|
|
2581
|
|
|
// ----- Read the file header |
|
2582
|
|
|
$v_header_list[$v_nb_extracted] = array(); |
|
2583
|
|
|
$v_result = $this->_readCentralFileHeader($v_header_list[$v_nb_extracted]); |
|
2584
|
|
|
if ($v_result != 1) { |
|
2585
|
|
|
// ----- Clean |
|
2586
|
|
|
$this->_closeFd(); |
|
2587
|
|
|
|
|
2588
|
|
|
return $v_result; |
|
2589
|
|
|
} |
|
2590
|
|
|
|
|
2591
|
|
|
// ----- Store the index |
|
2592
|
|
|
$v_header_list[$v_nb_extracted]['index'] = $i; |
|
2593
|
|
|
|
|
2594
|
|
|
// ----- Look for the specific extract rules |
|
2595
|
|
|
$v_found = false; |
|
2596
|
|
|
|
|
2597
|
|
|
// ----- Look for extract by name rule |
|
2598
|
|
|
if (isset($p_params[ARCHIVE_ZIP_PARAM_BY_NAME]) && ($p_params[ARCHIVE_ZIP_PARAM_BY_NAME] != 0)) { |
|
2599
|
|
|
|
|
2600
|
|
|
// ----- Look if the filename is in the list |
|
2601
|
|
|
for ($j = 0; ($j < count($p_params[ARCHIVE_ZIP_PARAM_BY_NAME])) && (!$v_found); ++$j) { |
|
2602
|
|
|
|
|
2603
|
|
|
// ----- Look for a directory |
|
2604
|
|
|
if (substr($p_params[ARCHIVE_ZIP_PARAM_BY_NAME][$j], -1) === '/') { |
|
2605
|
|
|
|
|
2606
|
|
|
// ----- Look if the directory is in the filename path |
|
2607
|
|
|
if ((strlen($v_header_list[$v_nb_extracted]['stored_filename']) > strlen($p_params[ARCHIVE_ZIP_PARAM_BY_NAME][$j])) |
|
2608
|
|
|
&& (substr($v_header_list[$v_nb_extracted]['stored_filename'], 0, strlen($p_params[ARCHIVE_ZIP_PARAM_BY_NAME][$j])) == $p_params[ARCHIVE_ZIP_PARAM_BY_NAME][$j]) |
|
2609
|
|
|
) { |
|
2610
|
|
|
$v_found = true; |
|
2611
|
|
|
} elseif ((($v_header_list[$v_nb_extracted]['external'] & 0x00000010) == 0x00000010) /* Indicates a folder */ |
|
2612
|
|
|
&& ($v_header_list[$v_nb_extracted]['stored_filename'] . '/' == $p_params[ARCHIVE_ZIP_PARAM_BY_NAME][$j]) |
|
2613
|
|
|
) { |
|
2614
|
|
|
$v_found = true; |
|
2615
|
|
|
} |
|
2616
|
|
|
} // ----- Look for a filename |
|
2617
|
|
|
elseif ($v_header_list[$v_nb_extracted]['stored_filename'] == $p_params[ARCHIVE_ZIP_PARAM_BY_NAME][$j]) { |
|
2618
|
|
|
$v_found = true; |
|
2619
|
|
|
} |
|
2620
|
|
|
} |
|
2621
|
|
|
} // ----- Look for extract by ereg rule |
|
2622
|
|
View Code Duplication |
elseif (isset($p_params[ARCHIVE_ZIP_PARAM_BY_EREG]) && ($p_params[ARCHIVE_ZIP_PARAM_BY_EREG] != '')) { |
|
|
|
|
|
|
2623
|
|
|
if (preg_match('/' . $p_params[ARCHIVE_ZIP_PARAM_BY_EREG] . '/', $v_header_list[$v_nb_extracted]['stored_filename'])) { |
|
2624
|
|
|
$v_found = true; |
|
2625
|
|
|
} |
|
2626
|
|
|
} // ----- Look for extract by preg rule |
|
2627
|
|
|
elseif (isset($p_params[ARCHIVE_ZIP_PARAM_BY_PREG]) && ($p_params[ARCHIVE_ZIP_PARAM_BY_PREG] != '')) { |
|
2628
|
|
|
if (preg_match($p_params[ARCHIVE_ZIP_PARAM_BY_PREG], $v_header_list[$v_nb_extracted]['stored_filename'])) { |
|
2629
|
|
|
$v_found = true; |
|
2630
|
|
|
} |
|
2631
|
|
|
} // ----- Look for extract by index rule |
|
2632
|
|
View Code Duplication |
elseif (isset($p_params[ARCHIVE_ZIP_PARAM_BY_INDEX]) && ($p_params[ARCHIVE_ZIP_PARAM_BY_INDEX] != 0)) { |
|
|
|
|
|
|
2633
|
|
|
|
|
2634
|
|
|
// ----- Look if the index is in the list |
|
2635
|
|
|
for ($j = $j_start; ($j < count($p_params[ARCHIVE_ZIP_PARAM_BY_INDEX])) && (!$v_found); ++$j) { |
|
2636
|
|
|
if (($i >= $p_params[ARCHIVE_ZIP_PARAM_BY_INDEX][$j]['start']) && ($i <= $p_params[ARCHIVE_ZIP_PARAM_BY_INDEX][$j]['end'])) { |
|
2637
|
|
|
$v_found = true; |
|
2638
|
|
|
} |
|
2639
|
|
|
if ($i >= $p_params[ARCHIVE_ZIP_PARAM_BY_INDEX][$j]['end']) { |
|
2640
|
|
|
$j_start = $j + 1; |
|
2641
|
|
|
} |
|
2642
|
|
|
|
|
2643
|
|
|
if ($p_params[ARCHIVE_ZIP_PARAM_BY_INDEX][$j]['start'] > $i) { |
|
2644
|
|
|
break; |
|
2645
|
|
|
} |
|
2646
|
|
|
} |
|
2647
|
|
|
} |
|
2648
|
|
|
|
|
2649
|
|
|
// ----- Look for deletion |
|
2650
|
|
|
if ($v_found) { |
|
2651
|
|
|
unset($v_header_list[$v_nb_extracted]); |
|
2652
|
|
|
} else { |
|
2653
|
|
|
++$v_nb_extracted; |
|
2654
|
|
|
} |
|
2655
|
|
|
} |
|
2656
|
|
|
|
|
2657
|
|
|
// ----- Look if something need to be deleted |
|
2658
|
|
|
if ($v_nb_extracted > 0) { |
|
2659
|
|
|
|
|
2660
|
|
|
// ----- Creates a temporay file |
|
2661
|
|
|
$v_zip_temp_name = ARCHIVE_ZIP_TEMPORARY_DIR . uniqid('archive_zip-') . '.tmp'; |
|
2662
|
|
|
|
|
2663
|
|
|
// ----- Creates a temporary zip archive |
|
2664
|
|
|
$v_temp_zip = new Archive_Zip($v_zip_temp_name); |
|
2665
|
|
|
|
|
2666
|
|
|
// ----- Open the temporary zip file in write mode |
|
2667
|
|
|
if (($v_result = $v_temp_zip->_openFd('wb')) != 1) { |
|
2668
|
|
|
$this->_closeFd(); |
|
2669
|
|
|
|
|
2670
|
|
|
// ----- Return |
|
2671
|
|
|
return $v_result; |
|
2672
|
|
|
} |
|
2673
|
|
|
|
|
2674
|
|
|
// ----- Look which file need to be kept |
|
2675
|
|
|
for ($i = 0, $iMax = count($v_header_list); $i < $iMax; ++$i) { |
|
2676
|
|
|
|
|
2677
|
|
|
// ----- Calculate the position of the header |
|
2678
|
|
|
@rewind($this->_zip_fd); |
|
|
|
|
|
|
2679
|
|
|
if (@fseek($this->_zip_fd, $v_header_list[$i]['offset'])) { |
|
2680
|
|
|
// ----- Clean |
|
2681
|
|
|
$this->_closeFd(); |
|
2682
|
|
|
$v_temp_zip->_closeFd(); |
|
2683
|
|
|
@unlink($v_zip_temp_name); |
|
|
|
|
|
|
2684
|
|
|
|
|
2685
|
|
|
$this->_errorLog(ARCHIVE_ZIP_ERR_INVALID_ARCHIVE_ZIP, 'Invalid archive size'); |
|
2686
|
|
|
|
|
2687
|
|
|
return Archive_Zip::errorCode(); |
|
2688
|
|
|
} |
|
2689
|
|
|
|
|
2690
|
|
|
// ----- Read the file header |
|
2691
|
|
View Code Duplication |
if (($v_result = $this->_readFileHeader($v_header_list[$i])) != 1) { |
|
|
|
|
|
|
2692
|
|
|
// ----- Clean |
|
2693
|
|
|
$this->_closeFd(); |
|
2694
|
|
|
$v_temp_zip->_closeFd(); |
|
2695
|
|
|
@unlink($v_zip_temp_name); |
|
|
|
|
|
|
2696
|
|
|
|
|
2697
|
|
|
return $v_result; |
|
2698
|
|
|
} |
|
2699
|
|
|
|
|
2700
|
|
|
// ----- Write the file header |
|
2701
|
|
|
$v_result = $v_temp_zip->_writeFileHeader($v_header_list[$i]); |
|
2702
|
|
|
if ($v_result != 1) { |
|
2703
|
|
|
// ----- Clean |
|
2704
|
|
|
$this->_closeFd(); |
|
2705
|
|
|
$v_temp_zip->_closeFd(); |
|
2706
|
|
|
@unlink($v_zip_temp_name); |
|
|
|
|
|
|
2707
|
|
|
|
|
2708
|
|
|
return $v_result; |
|
2709
|
|
|
} |
|
2710
|
|
|
|
|
2711
|
|
|
// ----- Read/write the data block |
|
2712
|
|
|
$v_result = $this->_tool_CopyBlock($this->_zip_fd, $v_temp_zip->_zip_fd, $v_header_list[$i]['compressed_size']); |
|
2713
|
|
|
if ($v_result != 1) { |
|
2714
|
|
|
// ----- Clean |
|
2715
|
|
|
$this->_closeFd(); |
|
2716
|
|
|
$v_temp_zip->_closeFd(); |
|
2717
|
|
|
@unlink($v_zip_temp_name); |
|
|
|
|
|
|
2718
|
|
|
|
|
2719
|
|
|
return $v_result; |
|
2720
|
|
|
} |
|
2721
|
|
|
} |
|
2722
|
|
|
|
|
2723
|
|
|
// ----- Store the offset of the central dir |
|
2724
|
|
|
$v_offset = @ftell($v_temp_zip->_zip_fd); |
|
2725
|
|
|
|
|
2726
|
|
|
// ----- Re-Create the Central Dir files header |
|
2727
|
|
|
for ($i = 0, $iMax = count($v_header_list); $i < $iMax; ++$i) { |
|
2728
|
|
|
// ----- Create the file header |
|
2729
|
|
|
$v_result = $v_temp_zip->_writeCentralFileHeader($v_header_list[$i]); |
|
2730
|
|
|
if ($v_result != 1) { |
|
2731
|
|
|
// ----- Clean |
|
2732
|
|
|
$v_temp_zip->_closeFd(); |
|
2733
|
|
|
$this->_closeFd(); |
|
2734
|
|
|
@unlink($v_zip_temp_name); |
|
|
|
|
|
|
2735
|
|
|
|
|
2736
|
|
|
return $v_result; |
|
2737
|
|
|
} |
|
2738
|
|
|
|
|
2739
|
|
|
// ----- Transform the header to a 'usable' info |
|
2740
|
|
|
$v_temp_zip->_convertHeader2FileInfo($v_header_list[$i], $p_result_list[$i]); |
|
2741
|
|
|
} |
|
2742
|
|
|
|
|
2743
|
|
|
// ----- Zip file comment |
|
2744
|
|
|
$v_comment = ''; |
|
2745
|
|
|
|
|
2746
|
|
|
// ----- Calculate the size of the central header |
|
2747
|
|
|
$v_size = @ftell($v_temp_zip->_zip_fd) - $v_offset; |
|
2748
|
|
|
|
|
2749
|
|
|
// ----- Create the central dir footer |
|
2750
|
|
|
$v_result = $v_temp_zip->_writeCentralHeader(count($v_header_list), $v_size, $v_offset, $v_comment); |
|
2751
|
|
View Code Duplication |
if ($v_result != 1) { |
|
|
|
|
|
|
2752
|
|
|
// ----- Clean |
|
2753
|
|
|
unset($v_header_list); |
|
2754
|
|
|
$v_temp_zip->_closeFd(); |
|
2755
|
|
|
$this->_closeFd(); |
|
2756
|
|
|
@unlink($v_zip_temp_name); |
|
|
|
|
|
|
2757
|
|
|
|
|
2758
|
|
|
return $v_result; |
|
2759
|
|
|
} |
|
2760
|
|
|
|
|
2761
|
|
|
// ----- Close |
|
2762
|
|
|
$v_temp_zip->_closeFd(); |
|
2763
|
|
|
$this->_closeFd(); |
|
2764
|
|
|
|
|
2765
|
|
|
// ----- Delete the zip file |
|
2766
|
|
|
// TBC : I should test the result ... |
|
2767
|
|
|
@unlink($this->_zipname); |
|
|
|
|
|
|
2768
|
|
|
|
|
2769
|
|
|
// ----- Rename the temporary file |
|
2770
|
|
|
// TBC : I should test the result ... |
|
2771
|
|
|
//@rename($v_zip_temp_name, $this->_zipname); |
|
2772
|
|
|
$this->_tool_Rename($v_zip_temp_name, $this->_zipname); |
|
2773
|
|
|
|
|
2774
|
|
|
// ----- Destroy the temporary archive |
|
2775
|
|
|
unset($v_temp_zip); |
|
2776
|
|
|
} |
|
2777
|
|
|
|
|
2778
|
|
|
// ----- Return |
|
2779
|
|
|
return $v_result; |
|
2780
|
|
|
} |
|
2781
|
|
|
|
|
2782
|
|
|
// --------------------------------------------------------------------------- |
|
2783
|
|
|
|
|
2784
|
|
|
// --------------------------------------------------------------------------- |
|
2785
|
|
|
// Function : _dirCheck() |
|
2786
|
|
|
// Description : |
|
2787
|
|
|
// Check if a directory exists, if not it creates it and all the parents directory |
|
2788
|
|
|
// which may be useful. |
|
2789
|
|
|
// Parameters : |
|
2790
|
|
|
// $p_dir : Directory path to check. |
|
2791
|
|
|
// Return Values : |
|
2792
|
|
|
// 1 : OK |
|
2793
|
|
|
// -1 : Unable to create directory |
|
2794
|
|
|
// --------------------------------------------------------------------------- |
|
2795
|
|
|
/** |
|
2796
|
|
|
* Archive_Zip::_dirCheck() |
|
2797
|
|
|
* |
|
2798
|
|
|
* { Description } |
|
2799
|
|
|
* |
|
2800
|
|
|
* @param [type] $p_is_dir |
|
|
|
|
|
|
2801
|
|
|
* @param bool $p_is_dir |
|
2802
|
|
|
* @return int |
|
2803
|
|
|
*/ |
|
2804
|
|
|
public function _dirCheck($p_dir, $p_is_dir = false) |
|
2805
|
|
|
{ |
|
2806
|
|
|
$v_result = 1; |
|
2807
|
|
|
|
|
2808
|
|
|
// ----- Remove the final '/' |
|
2809
|
|
|
if ($p_is_dir && (substr($p_dir, -1) === '/')) { |
|
2810
|
|
|
$p_dir = substr($p_dir, 0, -1); |
|
2811
|
|
|
} |
|
2812
|
|
|
|
|
2813
|
|
|
// ----- Check the directory availability |
|
2814
|
|
|
if (is_dir($p_dir) || ($p_dir == '')) { |
|
2815
|
|
|
return 1; |
|
2816
|
|
|
} |
|
2817
|
|
|
|
|
2818
|
|
|
// ----- Extract parent directory |
|
2819
|
|
|
$p_parent_dir = dirname($p_dir); |
|
2820
|
|
|
|
|
2821
|
|
|
// ----- Just a check |
|
2822
|
|
|
if ($p_parent_dir != $p_dir) { |
|
2823
|
|
|
// ----- Look for parent directory |
|
2824
|
|
|
if ($p_parent_dir != '') { |
|
2825
|
|
|
if (($v_result = $this->_dirCheck($p_parent_dir)) != 1) { |
|
2826
|
|
|
return $v_result; |
|
2827
|
|
|
} |
|
2828
|
|
|
} |
|
2829
|
|
|
} |
|
2830
|
|
|
|
|
2831
|
|
|
// ----- Create the directory |
|
2832
|
|
|
if (!@mkdir($p_dir, 0777)) { |
|
2833
|
|
|
$this->_errorLog(ARCHIVE_ZIP_ERR_DIR_CREATE_FAIL, "Unable to create directory '$p_dir'"); |
|
2834
|
|
|
|
|
2835
|
|
|
return Archive_Zip::errorCode(); |
|
2836
|
|
|
} |
|
2837
|
|
|
|
|
2838
|
|
|
// ----- Return |
|
2839
|
|
|
return $v_result; |
|
2840
|
|
|
} |
|
2841
|
|
|
|
|
2842
|
|
|
// --------------------------------------------------------------------------- |
|
2843
|
|
|
|
|
2844
|
|
|
// --------------------------------------------------------------------------- |
|
2845
|
|
|
// Function : _merge() |
|
2846
|
|
|
// Description : |
|
2847
|
|
|
// If $p_archive_to_add does not exist, the function exit with a success result. |
|
2848
|
|
|
// Parameters : |
|
2849
|
|
|
// Return Values : |
|
2850
|
|
|
// --------------------------------------------------------------------------- |
|
2851
|
|
|
/** |
|
2852
|
|
|
* Archive_Zip::_merge() |
|
2853
|
|
|
* |
|
2854
|
|
|
* { Description } |
|
2855
|
|
|
* @param $p_archive_to_add |
|
2856
|
|
|
* @return int |
|
2857
|
|
|
*/ |
|
2858
|
|
|
public function _merge(&$p_archive_to_add) |
|
2859
|
|
|
{ |
|
2860
|
|
|
$v_result = 1; |
|
|
|
|
|
|
2861
|
|
|
|
|
2862
|
|
|
// ----- Look if the archive_to_add exists |
|
2863
|
|
|
if (!is_file($p_archive_to_add->_zipname)) { |
|
2864
|
|
|
// ----- Nothing to merge, so merge is a success |
|
2865
|
|
|
return 1; |
|
2866
|
|
|
} |
|
2867
|
|
|
|
|
2868
|
|
|
// ----- Look if the archive exists |
|
2869
|
|
|
if (!is_file($this->_zipname)) { |
|
2870
|
|
|
// ----- Do a duplicate |
|
2871
|
|
|
$v_result = $this->_duplicate($p_archive_to_add->_zipname); |
|
2872
|
|
|
|
|
2873
|
|
|
return $v_result; |
|
2874
|
|
|
} |
|
2875
|
|
|
|
|
2876
|
|
|
// ----- Open the zip file |
|
2877
|
|
|
if (($v_result = $this->_openFd('rb')) != 1) { |
|
2878
|
|
|
return $v_result; |
|
2879
|
|
|
} |
|
2880
|
|
|
|
|
2881
|
|
|
// ----- Read the central directory informations |
|
2882
|
|
|
$v_central_dir = array(); |
|
2883
|
|
|
if (($v_result = $this->_readEndCentralDir($v_central_dir)) != 1) { |
|
2884
|
|
|
$this->_closeFd(); |
|
2885
|
|
|
|
|
2886
|
|
|
return $v_result; |
|
2887
|
|
|
} |
|
2888
|
|
|
|
|
2889
|
|
|
// ----- Go to beginning of File |
|
2890
|
|
|
@rewind($this->_zip_fd); |
|
|
|
|
|
|
2891
|
|
|
|
|
2892
|
|
|
// ----- Open the archive_to_add file |
|
2893
|
|
|
if (($v_result = $p_archive_to_add->_openFd('rb')) != 1) { |
|
2894
|
|
|
$this->_closeFd(); |
|
2895
|
|
|
|
|
2896
|
|
|
return $v_result; |
|
2897
|
|
|
} |
|
2898
|
|
|
|
|
2899
|
|
|
// ----- Read the central directory informations |
|
2900
|
|
|
$v_central_dir_to_add = array(); |
|
2901
|
|
|
$v_result = $p_archive_to_add->_readEndCentralDir($v_central_dir_to_add); |
|
2902
|
|
|
if ($v_result != 1) { |
|
2903
|
|
|
$this->_closeFd(); |
|
2904
|
|
|
$p_archive_to_add->_closeFd(); |
|
2905
|
|
|
|
|
2906
|
|
|
return $v_result; |
|
2907
|
|
|
} |
|
2908
|
|
|
|
|
2909
|
|
|
// ----- Go to beginning of File |
|
2910
|
|
|
@rewind($p_archive_to_add->_zip_fd); |
|
|
|
|
|
|
2911
|
|
|
|
|
2912
|
|
|
// ----- Creates a temporay file |
|
2913
|
|
|
$v_zip_temp_name = ARCHIVE_ZIP_TEMPORARY_DIR . uniqid('archive_zip-') . '.tmp'; |
|
2914
|
|
|
|
|
2915
|
|
|
// ----- Open the temporary file in write mode |
|
2916
|
|
View Code Duplication |
if (($v_zip_temp_fd = @fopen($v_zip_temp_name, 'wb')) == 0) { |
|
|
|
|
|
|
2917
|
|
|
$this->_closeFd(); |
|
2918
|
|
|
$p_archive_to_add->_closeFd(); |
|
2919
|
|
|
$this->_errorLog(ARCHIVE_ZIP_ERR_READ_OPEN_FAIL, 'Unable to open temporary file \'' . $v_zip_temp_name . '\' in binary write mode'); |
|
2920
|
|
|
|
|
2921
|
|
|
return Archive_Zip::errorCode(); |
|
2922
|
|
|
} |
|
2923
|
|
|
|
|
2924
|
|
|
// ----- Copy the files from the archive to the temporary file |
|
2925
|
|
|
// TBC : Here I should better append the file and go back to erase the |
|
2926
|
|
|
// central dir |
|
2927
|
|
|
$v_size = $v_central_dir['offset']; |
|
2928
|
|
|
while ($v_size != 0) { |
|
2929
|
|
|
$v_read_size = ($v_size < ARCHIVE_ZIP_READ_BLOCK_SIZE ? $v_size : ARCHIVE_ZIP_READ_BLOCK_SIZE); |
|
2930
|
|
|
$v_buffer = fread($this->_zip_fd, $v_read_size); |
|
2931
|
|
|
@fwrite($v_zip_temp_fd, $v_buffer, $v_read_size); |
|
|
|
|
|
|
2932
|
|
|
$v_size -= $v_read_size; |
|
2933
|
|
|
} |
|
2934
|
|
|
|
|
2935
|
|
|
// ----- Copy the files from the archive_to_add into the temporary file |
|
2936
|
|
|
$v_size = $v_central_dir_to_add['offset']; |
|
2937
|
|
|
while ($v_size != 0) { |
|
2938
|
|
|
$v_read_size = ($v_size < ARCHIVE_ZIP_READ_BLOCK_SIZE ? $v_size : ARCHIVE_ZIP_READ_BLOCK_SIZE); |
|
2939
|
|
|
$v_buffer = fread($p_archive_to_add->_zip_fd, $v_read_size); |
|
2940
|
|
|
@fwrite($v_zip_temp_fd, $v_buffer, $v_read_size); |
|
|
|
|
|
|
2941
|
|
|
$v_size -= $v_read_size; |
|
2942
|
|
|
} |
|
2943
|
|
|
|
|
2944
|
|
|
// ----- Store the offset of the central dir |
|
2945
|
|
|
$v_offset = @ftell($v_zip_temp_fd); |
|
2946
|
|
|
|
|
2947
|
|
|
// ----- Copy the block of file headers from the old archive |
|
2948
|
|
|
$v_size = $v_central_dir['size']; |
|
2949
|
|
View Code Duplication |
while ($v_size != 0) { |
|
|
|
|
|
|
2950
|
|
|
$v_read_size = ($v_size < ARCHIVE_ZIP_READ_BLOCK_SIZE ? $v_size : ARCHIVE_ZIP_READ_BLOCK_SIZE); |
|
2951
|
|
|
$v_buffer = @fread($this->_zip_fd, $v_read_size); |
|
2952
|
|
|
@fwrite($v_zip_temp_fd, $v_buffer, $v_read_size); |
|
|
|
|
|
|
2953
|
|
|
$v_size -= $v_read_size; |
|
2954
|
|
|
} |
|
2955
|
|
|
|
|
2956
|
|
|
// ----- Copy the block of file headers from the archive_to_add |
|
2957
|
|
|
$v_size = $v_central_dir_to_add['size']; |
|
2958
|
|
View Code Duplication |
while ($v_size != 0) { |
|
|
|
|
|
|
2959
|
|
|
$v_read_size = ($v_size < ARCHIVE_ZIP_READ_BLOCK_SIZE ? $v_size : ARCHIVE_ZIP_READ_BLOCK_SIZE); |
|
2960
|
|
|
$v_buffer = @fread($p_archive_to_add->_zip_fd, $v_read_size); |
|
2961
|
|
|
@fwrite($v_zip_temp_fd, $v_buffer, $v_read_size); |
|
|
|
|
|
|
2962
|
|
|
$v_size -= $v_read_size; |
|
2963
|
|
|
} |
|
2964
|
|
|
|
|
2965
|
|
|
// ----- Zip file comment |
|
2966
|
|
|
// TBC : I should merge the two comments |
|
2967
|
|
|
$v_comment = ''; |
|
2968
|
|
|
|
|
2969
|
|
|
// ----- Calculate the size of the (new) central header |
|
2970
|
|
|
$v_size = @ftell($v_zip_temp_fd) - $v_offset; |
|
2971
|
|
|
|
|
2972
|
|
|
// ----- Swap the file descriptor |
|
2973
|
|
|
// Here is a trick : I swap the temporary fd with the zip fd, in order to use |
|
2974
|
|
|
// the following methods on the temporary fil and not the real archive fd |
|
2975
|
|
|
$v_swap = $this->_zip_fd; |
|
2976
|
|
|
$this->_zip_fd = $v_zip_temp_fd; |
|
2977
|
|
|
$v_zip_temp_fd = $v_swap; |
|
2978
|
|
|
|
|
2979
|
|
|
// ----- Create the central dir footer |
|
2980
|
|
|
if (($v_result = $this->_writeCentralHeader($v_central_dir['entries'] + $v_central_dir_to_add['entries'], $v_size, $v_offset, $v_comment)) != 1) { |
|
2981
|
|
|
$this->_closeFd(); |
|
2982
|
|
|
$p_archive_to_add->_closeFd(); |
|
2983
|
|
|
@fclose($v_zip_temp_fd); |
|
|
|
|
|
|
2984
|
|
|
$this->_zip_fd = null; |
|
2985
|
|
|
|
|
2986
|
|
|
// ----- Reset the file list |
|
2987
|
|
|
unset($v_header_list); |
|
2988
|
|
|
|
|
2989
|
|
|
// ----- Return |
|
2990
|
|
|
return $v_result; |
|
2991
|
|
|
} |
|
2992
|
|
|
|
|
2993
|
|
|
// ----- Swap back the file descriptor |
|
2994
|
|
|
$v_swap = $this->_zip_fd; |
|
2995
|
|
|
$this->_zip_fd = $v_zip_temp_fd; |
|
2996
|
|
|
$v_zip_temp_fd = $v_swap; |
|
2997
|
|
|
|
|
2998
|
|
|
// ----- Close |
|
2999
|
|
|
$this->_closeFd(); |
|
3000
|
|
|
$p_archive_to_add->_closeFd(); |
|
3001
|
|
|
|
|
3002
|
|
|
// ----- Close the temporary file |
|
3003
|
|
|
@fclose($v_zip_temp_fd); |
|
|
|
|
|
|
3004
|
|
|
|
|
3005
|
|
|
// ----- Delete the zip file |
|
3006
|
|
|
// TBC : I should test the result ... |
|
3007
|
|
|
@unlink($this->_zipname); |
|
|
|
|
|
|
3008
|
|
|
|
|
3009
|
|
|
// ----- Rename the temporary file |
|
3010
|
|
|
// TBC : I should test the result ... |
|
3011
|
|
|
//@rename($v_zip_temp_name, $this->_zipname); |
|
3012
|
|
|
$this->_tool_Rename($v_zip_temp_name, $this->_zipname); |
|
3013
|
|
|
|
|
3014
|
|
|
// ----- Return |
|
3015
|
|
|
return $v_result; |
|
3016
|
|
|
} |
|
3017
|
|
|
|
|
3018
|
|
|
// --------------------------------------------------------------------------- |
|
3019
|
|
|
|
|
3020
|
|
|
// --------------------------------------------------------------------------- |
|
3021
|
|
|
// Function : _duplicate() |
|
3022
|
|
|
// Description : |
|
3023
|
|
|
// Parameters : |
|
3024
|
|
|
// Return Values : |
|
3025
|
|
|
// --------------------------------------------------------------------------- |
|
3026
|
|
|
/** |
|
3027
|
|
|
* Archive_Zip::_duplicate() |
|
3028
|
|
|
* |
|
3029
|
|
|
* { Description } |
|
3030
|
|
|
* @param $p_archive_filename |
|
3031
|
|
|
* @return int |
|
3032
|
|
|
*/ |
|
3033
|
|
|
public function _duplicate($p_archive_filename) |
|
3034
|
|
|
{ |
|
3035
|
|
|
$v_result = 1; |
|
|
|
|
|
|
3036
|
|
|
|
|
3037
|
|
|
// ----- Look if the $p_archive_filename exists |
|
3038
|
|
|
if (!is_file($p_archive_filename)) { |
|
3039
|
|
|
|
|
3040
|
|
|
// ----- Nothing to duplicate, so duplicate is a success. |
|
3041
|
|
|
$v_result = 1; |
|
3042
|
|
|
|
|
3043
|
|
|
// ----- Return |
|
3044
|
|
|
return $v_result; |
|
3045
|
|
|
} |
|
3046
|
|
|
|
|
3047
|
|
|
// ----- Open the zip file |
|
3048
|
|
|
if (($v_result = $this->_openFd('wb')) != 1) { |
|
3049
|
|
|
// ----- Return |
|
3050
|
|
|
return $v_result; |
|
3051
|
|
|
} |
|
3052
|
|
|
|
|
3053
|
|
|
// ----- Open the temporary file in write mode |
|
3054
|
|
View Code Duplication |
if (($v_zip_temp_fd = @fopen($p_archive_filename, 'rb')) == 0) { |
|
|
|
|
|
|
3055
|
|
|
$this->_closeFd(); |
|
3056
|
|
|
$this->_errorLog(ARCHIVE_ZIP_ERR_READ_OPEN_FAIL, 'Unable to open archive file \'' . $p_archive_filename . '\' in binary write mode'); |
|
3057
|
|
|
|
|
3058
|
|
|
return Archive_Zip::errorCode(); |
|
3059
|
|
|
} |
|
3060
|
|
|
|
|
3061
|
|
|
// ----- Copy the files from the archive to the temporary file |
|
3062
|
|
|
// TBC : Here I should better append the file and go back to erase the |
|
3063
|
|
|
// central dir |
|
3064
|
|
|
$v_size = filesize($p_archive_filename); |
|
3065
|
|
|
while ($v_size != 0) { |
|
3066
|
|
|
$v_read_size = ($v_size < ARCHIVE_ZIP_READ_BLOCK_SIZE ? $v_size : ARCHIVE_ZIP_READ_BLOCK_SIZE); |
|
3067
|
|
|
$v_buffer = fread($v_zip_temp_fd, $v_read_size); |
|
3068
|
|
|
@fwrite($this->_zip_fd, $v_buffer, $v_read_size); |
|
|
|
|
|
|
3069
|
|
|
$v_size -= $v_read_size; |
|
3070
|
|
|
} |
|
3071
|
|
|
|
|
3072
|
|
|
// ----- Close |
|
3073
|
|
|
$this->_closeFd(); |
|
3074
|
|
|
|
|
3075
|
|
|
// ----- Close the temporary file |
|
3076
|
|
|
@fclose($v_zip_temp_fd); |
|
|
|
|
|
|
3077
|
|
|
|
|
3078
|
|
|
return $v_result; |
|
3079
|
|
|
} |
|
3080
|
|
|
|
|
3081
|
|
|
// --------------------------------------------------------------------------- |
|
3082
|
|
|
|
|
3083
|
|
|
/** |
|
3084
|
|
|
* Archive_Zip::_check_parameters() |
|
3085
|
|
|
* |
|
3086
|
|
|
* { Description } |
|
3087
|
|
|
* |
|
3088
|
|
|
* @param $p_params |
|
3089
|
|
|
* @param $p_default |
|
3090
|
|
|
* @return int |
|
3091
|
|
|
* @internal param int $p_error_code |
|
3092
|
|
|
* @internal param string $p_error_string |
|
3093
|
|
|
*/ |
|
3094
|
|
|
public function _check_parameters(&$p_params, $p_default) |
|
3095
|
|
|
{ |
|
3096
|
|
|
|
|
3097
|
|
|
// ----- Check that param is an array |
|
3098
|
|
|
if (!is_array($p_params)) { |
|
3099
|
|
|
$this->_errorLog(ARCHIVE_ZIP_ERR_INVALID_PARAMETER, 'Unsupported parameter, waiting for an array'); |
|
3100
|
|
|
|
|
3101
|
|
|
return Archive_Zip::errorCode(); |
|
3102
|
|
|
} |
|
3103
|
|
|
|
|
3104
|
|
|
// ----- Check that all the params are valid |
|
3105
|
|
|
for (reset($p_params); list($v_key, $v_value) = each($p_params);) { |
|
|
|
|
|
|
3106
|
|
|
if (!isset($p_default[$v_key])) { |
|
3107
|
|
|
$this->_errorLog(ARCHIVE_ZIP_ERR_INVALID_PARAMETER, 'Unsupported parameter with key \'' . $v_key . '\''); |
|
3108
|
|
|
|
|
3109
|
|
|
return Archive_Zip::errorCode(); |
|
3110
|
|
|
} |
|
3111
|
|
|
} |
|
3112
|
|
|
|
|
3113
|
|
|
// ----- Set the default values |
|
3114
|
|
|
for (reset($p_default); list($v_key, $v_value) = each($p_default);) { |
|
|
|
|
|
|
3115
|
|
|
if (!isset($p_params[$v_key])) { |
|
3116
|
|
|
$p_params[$v_key] = $p_default[$v_key]; |
|
3117
|
|
|
} |
|
3118
|
|
|
} |
|
3119
|
|
|
|
|
3120
|
|
|
// ----- Check specific parameters |
|
3121
|
|
|
$v_callback_list = array( |
|
3122
|
|
|
'callback_pre_add', |
|
3123
|
|
|
'callback_post_add', |
|
3124
|
|
|
'callback_pre_extract', |
|
3125
|
|
|
'callback_post_extract' |
|
3126
|
|
|
); |
|
3127
|
|
|
for ($i = 0, $iMax = count($v_callback_list); $i < $iMax; ++$i) { |
|
3128
|
|
|
$v_key = $v_callback_list[$i]; |
|
3129
|
|
|
if (isset($p_params[$v_key]) && ($p_params[$v_key] != '')) { |
|
3130
|
|
|
if (!function_exists($p_params[$v_key])) { |
|
3131
|
|
|
$this->_errorLog(ARCHIVE_ZIP_ERR_INVALID_PARAM_VALUE, "Callback '" . $p_params[$v_key] . "()' is not an existing function for " . "parameter '" . $v_key . "'"); |
|
3132
|
|
|
|
|
3133
|
|
|
return Archive_Zip::errorCode(); |
|
3134
|
|
|
} |
|
3135
|
|
|
} |
|
3136
|
|
|
} |
|
3137
|
|
|
|
|
3138
|
|
|
return 1; |
|
3139
|
|
|
} |
|
3140
|
|
|
|
|
3141
|
|
|
// --------------------------------------------------------------------------- |
|
3142
|
|
|
|
|
3143
|
|
|
// --------------------------------------------------------------------------- |
|
3144
|
|
|
// Function : _errorLog() |
|
3145
|
|
|
// Description : |
|
3146
|
|
|
// Parameters : |
|
3147
|
|
|
// --------------------------------------------------------------------------- |
|
3148
|
|
|
/** |
|
3149
|
|
|
* Archive_Zip::_errorLog() |
|
3150
|
|
|
* |
|
3151
|
|
|
* { Description } |
|
3152
|
|
|
* |
|
3153
|
|
|
* @param integer $p_error_code |
|
3154
|
|
|
* @param string $p_error_string |
|
3155
|
|
|
*/ |
|
3156
|
|
|
public function _errorLog($p_error_code = 0, $p_error_string = '') |
|
3157
|
|
|
{ |
|
3158
|
|
|
$this->_error_code = $p_error_code; |
|
3159
|
|
|
$this->_error_string = $p_error_string; |
|
3160
|
|
|
} |
|
3161
|
|
|
|
|
3162
|
|
|
// --------------------------------------------------------------------------- |
|
3163
|
|
|
|
|
3164
|
|
|
// --------------------------------------------------------------------------- |
|
3165
|
|
|
// Function : _errorReset() |
|
3166
|
|
|
// Description : |
|
3167
|
|
|
// Parameters : |
|
3168
|
|
|
// --------------------------------------------------------------------------- |
|
3169
|
|
|
/** |
|
3170
|
|
|
* Archive_Zip::_errorReset() |
|
3171
|
|
|
* |
|
3172
|
|
|
* { Description } |
|
3173
|
|
|
* |
|
3174
|
|
|
*/ |
|
3175
|
|
|
public function _errorReset() |
|
3176
|
|
|
{ |
|
3177
|
|
|
$this->_error_code = 1; |
|
3178
|
|
|
$this->_error_string = ''; |
|
3179
|
|
|
} |
|
3180
|
|
|
|
|
3181
|
|
|
// --------------------------------------------------------------------------- |
|
3182
|
|
|
|
|
3183
|
|
|
// --------------------------------------------------------------------------- |
|
3184
|
|
|
// Function : $this->_tool_PathReduction() |
|
3185
|
|
|
// Description : |
|
3186
|
|
|
// Parameters : |
|
3187
|
|
|
// Return Values : |
|
3188
|
|
|
// --------------------------------------------------------------------------- |
|
3189
|
|
|
/** |
|
3190
|
|
|
* _tool_PathReduction() |
|
3191
|
|
|
* |
|
3192
|
|
|
* { Description } |
|
3193
|
|
|
* @param $p_dir |
|
3194
|
|
|
* @return string |
|
3195
|
|
|
*/ |
|
3196
|
|
|
public function _tool_PathReduction($p_dir) |
|
3197
|
|
|
{ |
|
3198
|
|
|
$v_result = ''; |
|
3199
|
|
|
|
|
3200
|
|
|
// ----- Look for not empty path |
|
3201
|
|
|
if ($p_dir != '') { |
|
3202
|
|
|
// ----- Explode path by directory names |
|
3203
|
|
|
$v_list = explode('/', $p_dir); |
|
3204
|
|
|
|
|
3205
|
|
|
// ----- Study directories from last to first |
|
3206
|
|
|
for ($i = count($v_list) - 1; $i >= 0; $i--) { |
|
3207
|
|
|
// ----- Look for current path |
|
3208
|
|
|
if ($v_list[$i] === '.') { |
|
3209
|
|
|
// ----- Ignore this directory |
|
3210
|
|
|
// Should be the first $i=0, but no check is done |
|
3211
|
|
|
} elseif ($v_list[$i] === '..') { |
|
3212
|
|
|
// ----- Ignore it and ignore the $i-1 |
|
3213
|
|
|
$i--; |
|
3214
|
|
|
} elseif (($v_list[$i] == '') && ($i != (count($v_list) - 1)) && ($i != 0)) { |
|
3215
|
|
|
// ----- Ignore only the double '//' in path, |
|
3216
|
|
|
// but not the first and last '/' |
|
3217
|
|
|
} else { |
|
3218
|
|
|
$v_result = $v_list[$i] . ($i != (count($v_list) - 1) ? '/' . $v_result : ''); |
|
3219
|
|
|
} |
|
3220
|
|
|
} |
|
3221
|
|
|
} |
|
3222
|
|
|
|
|
3223
|
|
|
// ----- Return |
|
3224
|
|
|
return $v_result; |
|
3225
|
|
|
} |
|
3226
|
|
|
|
|
3227
|
|
|
// --------------------------------------------------------------------------- |
|
3228
|
|
|
|
|
3229
|
|
|
// --------------------------------------------------------------------------- |
|
3230
|
|
|
// Function : $this->_tool_PathInclusion() |
|
3231
|
|
|
// Description : |
|
3232
|
|
|
// This function indicates if the path $p_path is under the $p_dir tree. Or, |
|
3233
|
|
|
// said in an other way, if the file or sub-dir $p_path is inside the dir |
|
3234
|
|
|
// $p_dir. |
|
3235
|
|
|
// The function indicates also if the path is exactly the same as the dir. |
|
3236
|
|
|
// This function supports path with duplicated '/' like '//', but does not |
|
3237
|
|
|
// support '.' or '..' statements. |
|
3238
|
|
|
// Parameters : |
|
3239
|
|
|
// Return Values : |
|
3240
|
|
|
// 0 if $p_path is not inside directory $p_dir |
|
3241
|
|
|
// 1 if $p_path is inside directory $p_dir |
|
3242
|
|
|
// 2 if $p_path is exactly the same as $p_dir |
|
3243
|
|
|
// --------------------------------------------------------------------------- |
|
3244
|
|
|
/** |
|
3245
|
|
|
* _tool_PathInclusion() |
|
3246
|
|
|
* |
|
3247
|
|
|
* { Description } |
|
3248
|
|
|
* @param $p_dir |
|
3249
|
|
|
* @param $p_path |
|
3250
|
|
|
* @return int |
|
3251
|
|
|
*/ |
|
3252
|
|
|
public function _tool_PathInclusion($p_dir, $p_path) |
|
3253
|
|
|
{ |
|
3254
|
|
|
$v_result = 1; |
|
3255
|
|
|
|
|
3256
|
|
|
// ----- Explode dir and path by directory separator |
|
3257
|
|
|
$v_list_dir = explode('/', $p_dir); |
|
3258
|
|
|
$v_list_dir_size = count($v_list_dir); |
|
3259
|
|
|
$v_list_path = explode('/', $p_path); |
|
3260
|
|
|
$v_list_path_size = count($v_list_path); |
|
3261
|
|
|
|
|
3262
|
|
|
// ----- Study directories paths |
|
3263
|
|
|
$i = 0; |
|
3264
|
|
|
$j = 0; |
|
3265
|
|
|
while (($i < $v_list_dir_size) && ($j < $v_list_path_size) && $v_result) { |
|
3266
|
|
|
|
|
3267
|
|
|
// ----- Look for empty dir (path reduction) |
|
3268
|
|
|
if ($v_list_dir[$i] == '') { |
|
3269
|
|
|
++$i; |
|
3270
|
|
|
continue; |
|
3271
|
|
|
} |
|
3272
|
|
|
if ($v_list_path[$j] == '') { |
|
3273
|
|
|
++$j; |
|
3274
|
|
|
continue; |
|
3275
|
|
|
} |
|
3276
|
|
|
|
|
3277
|
|
|
// ----- Compare the items |
|
3278
|
|
|
if (($v_list_dir[$i] != $v_list_path[$j]) && ($v_list_dir[$i] != '') && ($v_list_path[$j] != '')) { |
|
3279
|
|
|
$v_result = 0; |
|
3280
|
|
|
} |
|
3281
|
|
|
|
|
3282
|
|
|
// ----- Next items |
|
3283
|
|
|
++$i; |
|
3284
|
|
|
++$j; |
|
3285
|
|
|
} |
|
3286
|
|
|
|
|
3287
|
|
|
// ----- Look if everything seems to be the same |
|
3288
|
|
|
if ($v_result) { |
|
3289
|
|
|
// ----- Skip all the empty items |
|
3290
|
|
|
while (($j < $v_list_path_size) && ($v_list_path[$j] == '')) { |
|
3291
|
|
|
++$j; |
|
3292
|
|
|
} |
|
3293
|
|
|
while (($i < $v_list_dir_size) && ($v_list_dir[$i] == '')) { |
|
3294
|
|
|
++$i; |
|
3295
|
|
|
} |
|
3296
|
|
|
|
|
3297
|
|
|
if (($i >= $v_list_dir_size) && ($j >= $v_list_path_size)) { |
|
3298
|
|
|
// ----- There are exactly the same |
|
3299
|
|
|
$v_result = 2; |
|
3300
|
|
|
} elseif ($i < $v_list_dir_size) { |
|
3301
|
|
|
// ----- The path is shorter than the dir |
|
3302
|
|
|
$v_result = 0; |
|
3303
|
|
|
} |
|
3304
|
|
|
} |
|
3305
|
|
|
|
|
3306
|
|
|
// ----- Return |
|
3307
|
|
|
return $v_result; |
|
3308
|
|
|
} |
|
3309
|
|
|
|
|
3310
|
|
|
// --------------------------------------------------------------------------- |
|
3311
|
|
|
|
|
3312
|
|
|
// --------------------------------------------------------------------------- |
|
3313
|
|
|
// Function : $this->_tool_CopyBlock() |
|
3314
|
|
|
// Description : |
|
3315
|
|
|
// Parameters : |
|
3316
|
|
|
// $p_mode : read/write compression mode |
|
3317
|
|
|
// 0 : src & dest normal |
|
3318
|
|
|
// 1 : src gzip, dest normal |
|
3319
|
|
|
// 2 : src normal, dest gzip |
|
3320
|
|
|
// 3 : src & dest gzip |
|
3321
|
|
|
// Return Values : |
|
3322
|
|
|
// --------------------------------------------------------------------------- |
|
3323
|
|
|
/** |
|
3324
|
|
|
* _tool_CopyBlock() |
|
3325
|
|
|
* |
|
3326
|
|
|
* { Description } |
|
3327
|
|
|
* |
|
3328
|
|
|
* @param $p_src |
|
3329
|
|
|
* @param $p_dest |
|
3330
|
|
|
* @param $p_size |
|
3331
|
|
|
* @param integer $p_mode |
|
3332
|
|
|
* @return int |
|
3333
|
|
|
*/ |
|
3334
|
|
|
public function _tool_CopyBlock($p_src, $p_dest, $p_size, $p_mode = 0) |
|
3335
|
|
|
{ |
|
3336
|
|
|
$v_result = 1; |
|
3337
|
|
|
|
|
3338
|
|
|
if ($p_mode == 0) { |
|
3339
|
|
|
while ($p_size != 0) { |
|
3340
|
|
|
$v_read_size = ($p_size < ARCHIVE_ZIP_READ_BLOCK_SIZE ? $p_size : ARCHIVE_ZIP_READ_BLOCK_SIZE); |
|
3341
|
|
|
$v_buffer = @fread($p_src, $v_read_size); |
|
3342
|
|
|
@fwrite($p_dest, $v_buffer, $v_read_size); |
|
|
|
|
|
|
3343
|
|
|
$p_size -= $v_read_size; |
|
3344
|
|
|
} |
|
3345
|
|
View Code Duplication |
} elseif ($p_mode == 1) { |
|
|
|
|
|
|
3346
|
|
|
while ($p_size != 0) { |
|
3347
|
|
|
$v_read_size = ($p_size < ARCHIVE_ZIP_READ_BLOCK_SIZE ? $p_size : ARCHIVE_ZIP_READ_BLOCK_SIZE); |
|
3348
|
|
|
$v_buffer = @gzread($p_src, $v_read_size); |
|
3349
|
|
|
@fwrite($p_dest, $v_buffer, $v_read_size); |
|
|
|
|
|
|
3350
|
|
|
$p_size -= $v_read_size; |
|
3351
|
|
|
} |
|
3352
|
|
|
} elseif ($p_mode == 2) { |
|
3353
|
|
|
while ($p_size != 0) { |
|
3354
|
|
|
$v_read_size = ($p_size < ARCHIVE_ZIP_READ_BLOCK_SIZE ? $p_size : ARCHIVE_ZIP_READ_BLOCK_SIZE); |
|
3355
|
|
|
$v_buffer = @fread($p_src, $v_read_size); |
|
3356
|
|
|
@gzwrite($p_dest, $v_buffer, $v_read_size); |
|
|
|
|
|
|
3357
|
|
|
$p_size -= $v_read_size; |
|
3358
|
|
|
} |
|
3359
|
|
View Code Duplication |
} elseif ($p_mode == 3) { |
|
|
|
|
|
|
3360
|
|
|
while ($p_size != 0) { |
|
3361
|
|
|
$v_read_size = ($p_size < ARCHIVE_ZIP_READ_BLOCK_SIZE ? $p_size : ARCHIVE_ZIP_READ_BLOCK_SIZE); |
|
3362
|
|
|
$v_buffer = @gzread($p_src, $v_read_size); |
|
3363
|
|
|
@gzwrite($p_dest, $v_buffer, $v_read_size); |
|
|
|
|
|
|
3364
|
|
|
$p_size -= $v_read_size; |
|
3365
|
|
|
} |
|
3366
|
|
|
} |
|
3367
|
|
|
|
|
3368
|
|
|
// ----- Return |
|
3369
|
|
|
return $v_result; |
|
3370
|
|
|
} |
|
3371
|
|
|
|
|
3372
|
|
|
// --------------------------------------------------------------------------- |
|
3373
|
|
|
|
|
3374
|
|
|
// --------------------------------------------------------------------------- |
|
3375
|
|
|
// Function : $this->_tool_Rename() |
|
3376
|
|
|
// Description : |
|
3377
|
|
|
// This function tries to do a simple rename() function. If it fails, it |
|
3378
|
|
|
// tries to copy the $p_src file in a new $p_dest file and then unlink the |
|
3379
|
|
|
// first one. |
|
3380
|
|
|
// Parameters : |
|
3381
|
|
|
// $p_src : Old filename |
|
3382
|
|
|
// $p_dest : New filename |
|
3383
|
|
|
// Return Values : |
|
3384
|
|
|
// 1 on success, 0 on failure. |
|
3385
|
|
|
// --------------------------------------------------------------------------- |
|
3386
|
|
|
/** |
|
3387
|
|
|
* _tool_Rename() |
|
3388
|
|
|
* |
|
3389
|
|
|
* { Description } |
|
3390
|
|
|
* @param $p_src |
|
3391
|
|
|
* @param $p_dest |
|
3392
|
|
|
* @return int |
|
3393
|
|
|
*/ |
|
3394
|
|
|
public function _tool_Rename($p_src, $p_dest) |
|
3395
|
|
|
{ |
|
3396
|
|
|
$v_result = 1; |
|
3397
|
|
|
|
|
3398
|
|
|
// ----- Try to rename the files |
|
3399
|
|
|
if (!@rename($p_src, $p_dest)) { |
|
3400
|
|
|
|
|
3401
|
|
|
// ----- Try to copy & unlink the src |
|
3402
|
|
|
if (!@copy($p_src, $p_dest)) { |
|
3403
|
|
|
$v_result = 0; |
|
3404
|
|
|
} elseif (!@unlink($p_src)) { |
|
3405
|
|
|
$v_result = 0; |
|
3406
|
|
|
} |
|
3407
|
|
|
} |
|
3408
|
|
|
|
|
3409
|
|
|
// ----- Return |
|
3410
|
|
|
return $v_result; |
|
3411
|
|
|
} |
|
3412
|
|
|
|
|
3413
|
|
|
// --------------------------------------------------------------------------- |
|
3414
|
|
|
|
|
3415
|
|
|
// --------------------------------------------------------------------------- |
|
3416
|
|
|
// Function : $this->_tool_TranslateWinPath() |
|
3417
|
|
|
// Description : |
|
3418
|
|
|
// Translate windows path by replacing '\' by '/' and optionally removing |
|
3419
|
|
|
// drive letter. |
|
3420
|
|
|
// Parameters : |
|
3421
|
|
|
// $p_path : path to translate. |
|
3422
|
|
|
// $p_remove_disk_letter : true | false |
|
3423
|
|
|
// Return Values : |
|
3424
|
|
|
// The path translated. |
|
3425
|
|
|
// --------------------------------------------------------------------------- |
|
3426
|
|
|
/** |
|
3427
|
|
|
* _tool_TranslateWinPath() |
|
3428
|
|
|
* |
|
3429
|
|
|
* { Description } |
|
3430
|
|
|
* |
|
3431
|
|
|
* @param [type] $p_remove_disk_letter |
|
|
|
|
|
|
3432
|
|
|
* @param bool $p_remove_disk_letter |
|
3433
|
|
|
* @return string |
|
3434
|
|
|
*/ |
|
3435
|
|
|
public function _tool_TranslateWinPath($p_path, $p_remove_disk_letter = true) |
|
3436
|
|
|
{ |
|
3437
|
|
|
if (false !== stripos(php_uname(), 'windows')) { |
|
3438
|
|
|
// ----- Look for potential disk letter |
|
3439
|
|
|
if ($p_remove_disk_letter && (($v_position = strpos($p_path, ':')) != false)) { |
|
|
|
|
|
|
3440
|
|
|
$p_path = substr($p_path, $v_position + 1); |
|
3441
|
|
|
} |
|
3442
|
|
|
// ----- Change potential windows directory separator |
|
3443
|
|
|
if ((strpos($p_path, '\\') > 0) || (substr($p_path, 0, 1) === '\\')) { |
|
3444
|
|
|
$p_path = strtr($p_path, '\\', '/'); |
|
3445
|
|
|
} |
|
3446
|
|
|
} |
|
3447
|
|
|
|
|
3448
|
|
|
return $p_path; |
|
3449
|
|
|
} |
|
3450
|
|
|
// --------------------------------------------------------------------------- |
|
3451
|
|
|
} |
|
3452
|
|
|
// End of class |
|
3453
|
|
|
|
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.
You can also find more detailed suggestions in the “Code” section of your repository.