Test Failed
Branch master (206474)
by Fabio
18:24
created

TTarFileExtractor::_extractList()   F

Complexity

Conditions 53
Paths > 20000

Size

Total Lines 218
Code Lines 138

Duplication

Lines 17
Ratio 7.8 %

Importance

Changes 0
Metric Value
cc 53
eloc 138
nc 52948
nop 5
dl 17
loc 218
rs 2
c 0
b 0
f 0

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
/**
3
 * TTarFileExtractor class file
4
 *
5
 * @author Vincent Blavet <[email protected]>
6
 * @copyright Copyright &copy; 1997-2003 The PHP Group
7
 * @package Prado\IO
8
 */
9
10
namespace Prado\IO;
11
12
/* vim: set ts=4 sw=4: */
13
// +----------------------------------------------------------------------+
14
// | PHP Version 4                                                        |
15
// +----------------------------------------------------------------------+
16
// | Copyright (c) 1997-2003 The PHP Group                                |
17
// +----------------------------------------------------------------------+
18
// | This source file is subject to version 3.0 of the PHP license,       |
19
// | that is bundled with this package in the file LICENSE, and is        |
20
// | available through the world-wide-web at the following url:           |
21
// | http://www.php.net/license/3_0.txt.                                  |
22
// | If you did not receive a copy of the PHP license and are unable to   |
23
// | obtain it through the world-wide-web, please send a note to          |
24
// | [email protected] so we can mail you a copy immediately.               |
25
// +----------------------------------------------------------------------+
26
// | Author: Vincent Blavet <[email protected]>                      |
27
// +----------------------------------------------------------------------+
28
//
29
// $Id: TTarFileExtractor.php 3188 2012-07-12 12:13:23Z ctrlaltca $
30
31
/**
32
 * TTarFileExtractor class
33
 *
34
 * @author Vincent Blavet <[email protected]>
35
 * @package Prado\IO
36
 * @since 3.0
37
 */
38
class TTarFileExtractor
39
{
40
	/**
41
	 * @var string Name of the Tar
42
	 */
43
	private $_tarname = '';
44
45
	/**
46
	 * @var file descriptor
47
	 */
48
	private $_file = 0;
49
50
	/**
51
	 * @var string Local Tar name of a remote Tar (http:// or ftp://)
52
	 */
53
	private $_temp_tarname = '';
54
55
	/**
56
	 * Archive_Tar Class constructor. This flavour of the constructor only
57
	 * declare a new Archive_Tar object, identifying it by the name of the
58
	 * tar file.
59
	 *
60
	 * @param    string $p_tarname $p_tarname  The name of the tar archive to create
61
	 * @access public
62
	 */
63
	public function __construct($p_tarname)
64
	{
65
		$this->_tarname = $p_tarname;
66
	}
67
68
	public function __destruct()
69
	{
70
		$this->_close();
71
		// ----- Look for a local copy to delete
72
		if ($this->_temp_tarname != '') {
73
			@unlink($this->_temp_tarname);
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition here. This can introduce security issues, and is generally not recommended.

If you suppress an error, we recommend checking for the error condition explicitly:

// For example instead of
@mkdir($dir);

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
74
		}
75
	}
76
77
	public function extract($p_path = '')
78
	{
79
		return $this->extractModify($p_path, '');
80
	}
81
82
	/**
83
	 * This method extract all the content of the archive in the directory
84
	 * indicated by $p_path. When relevant the memorized path of the
85
	 * files/dir can be modified by removing the $p_remove_path path at the
86
	 * beginning of the file/dir path.
87
	 * While extracting a file, if the directory path does not exists it is
88
	 * created.
89
	 * While extracting a file, if the file already exists it is replaced
90
	 * without looking for last modification date.
91
	 * While extracting a file, if the file already exists and is write
92
	 * protected, the extraction is aborted.
93
	 * While extracting a file, if a directory with the same name already
94
	 * exists, the extraction is aborted.
95
	 * While extracting a directory, if a file with the same name already
96
	 * exists, the extraction is aborted.
97
	 * While extracting a file/directory if the destination directory exist
98
	 * and is write protected, or does not exist but can not be created,
99
	 * the extraction is aborted.
100
	 * If after extraction an extracted file does not show the correct
101
	 * stored file size, the extraction is aborted.
102
	 * When the extraction is aborted, a PEAR error text is set and false
103
	 * is returned. However the result can be a partial extraction that may
104
	 * need to be manually cleaned.
105
	 *
106
	 * @param string $p_path         The path of the directory where the
107
	 *                               files/dir need to by extracted.
108
	 * @param string $p_remove_path  Part of the memorized path that can be
109
	 *                               removed if present at the beginning of
110
	 *                               the file/dir path.
111
	 * @return bool               true on success, false on error.
112
	 * @access public
113
	 */
114
	protected function extractModify($p_path, $p_remove_path)
115
	{
116
		$v_result = true;
0 ignored issues
show
Unused Code introduced by
$v_result is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
117
		$v_list_detail = [];
118
119
		if ($v_result = $this->_openRead()) {
120
			$v_result = $this->_extractList(
121
				$p_path,
122
				$v_list_detail,
123
											"complete",
124
				0,
125
				$p_remove_path
126
			);
127
			$this->_close();
128
		}
129
130
		return $v_result;
131
	}
132
133
	protected function _error($p_message)
134
	{
135
		throw new \Exception($p_message);
136
	}
137
138
	private function _isArchive($p_filename = null)
139
	{
140
		if ($p_filename == null) {
141
			$p_filename = $this->_tarname;
142
		}
143
		clearstatcache();
144
		return @is_file($p_filename);
145
	}
146
147
	private function _openRead()
148
	{
149
		if (strtolower(substr($this->_tarname, 0, 7)) == 'http://') {
150
151
		  // ----- Look if a local copy need to be done
152
			if ($this->_temp_tarname == '') {
153
				$this->_temp_tarname = uniqid('tar') . '.tmp';
154 View Code Duplication
				if (!$v_file_from = @fopen($this->_tarname, 'rb')) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

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.

Loading history...
155
					$this->_error('Unable to open in read mode \''
156
							  . $this->_tarname . '\'');
157
					$this->_temp_tarname = '';
158
					return false;
159
				}
160 View Code Duplication
				if (!$v_file_to = @fopen($this->_temp_tarname, 'wb')) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

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.

Loading history...
161
					$this->_error('Unable to open in write mode \''
162
							  . $this->_temp_tarname . '\'');
163
					$this->_temp_tarname = '';
164
					return false;
165
				}
166
				while ($v_data = @fread($v_file_from, 1024)) {
167
					@fwrite($v_file_to, $v_data);
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition here. This can introduce security issues, and is generally not recommended.

If you suppress an error, we recommend checking for the error condition explicitly:

// For example instead of
@mkdir($dir);

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
168
				}
169
				@fclose($v_file_from);
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition here. This can introduce security issues, and is generally not recommended.

If you suppress an error, we recommend checking for the error condition explicitly:

// For example instead of
@mkdir($dir);

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
170
				@fclose($v_file_to);
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition here. This can introduce security issues, and is generally not recommended.

If you suppress an error, we recommend checking for the error condition explicitly:

// For example instead of
@mkdir($dir);

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
171
			}
172
173
			// ----- File to open if the local copy
174
			$v_filename = $this->_temp_tarname;
175
		} else {
176
			// ----- File to open if the normal Tar file
177
			$v_filename = $this->_tarname;
178
		}
179
180
		$this->_file = @fopen($v_filename, "rb");
181
182
		if ($this->_file == 0) {
183
			$this->_error('Unable to open in read mode \'' . $v_filename . '\'');
184
			return false;
185
		}
186
187
		return true;
188
	}
189
190
	private function _close()
191
	{
192
		//if (isset($this->_file)) {
193
		if (is_resource($this->_file)) {
194
			@fclose($this->_file);
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition here. This can introduce security issues, and is generally not recommended.

If you suppress an error, we recommend checking for the error condition explicitly:

// For example instead of
@mkdir($dir);

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
195
			$this->_file = 0;
0 ignored issues
show
Documentation Bug introduced by
It seems like 0 of type integer is incompatible with the declared type object<Prado\IO\file> of property $_file.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
196
		}
197
198
		// ----- Look if a local copy need to be erase
199
		// Note that it might be interesting to keep the url for a time : ToDo
200
		if ($this->_temp_tarname != '') {
201
			@unlink($this->_temp_tarname);
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition here. This can introduce security issues, and is generally not recommended.

If you suppress an error, we recommend checking for the error condition explicitly:

// For example instead of
@mkdir($dir);

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
202
			$this->_temp_tarname = '';
203
		}
204
205
		return true;
206
	}
207
208
	private function _cleanFile()
0 ignored issues
show
Unused Code introduced by
This method is not used, and could be removed.
Loading history...
209
	{
210
		$this->_close();
211
212
		// ----- Look for a local copy
213
		if ($this->_temp_tarname != '') {
214
			// ----- Remove the local copy but not the remote tarname
215
			@unlink($this->_temp_tarname);
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition here. This can introduce security issues, and is generally not recommended.

If you suppress an error, we recommend checking for the error condition explicitly:

// For example instead of
@mkdir($dir);

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
216
			$this->_temp_tarname = '';
217
		} else {
218
			// ----- Remove the local tarname file
219
			@unlink($this->_tarname);
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition here. This can introduce security issues, and is generally not recommended.

If you suppress an error, we recommend checking for the error condition explicitly:

// For example instead of
@mkdir($dir);

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
220
		}
221
		$this->_tarname = '';
222
223
		return true;
224
	}
225
226
	private function _readBlock()
227
	{
228
		$v_block = null;
229
		if (is_resource($this->_file)) {
230
			$v_block = @fread($this->_file, 512);
231
		}
232
		return $v_block;
233
	}
234
235
	private function _jumpBlock($p_len = null)
236
	{
237
		if (is_resource($this->_file)) {
238
			if ($p_len === null) {
239
				$p_len = 1;
240
			}
241
242
			@fseek($this->_file, @ftell($this->_file) + ($p_len * 512));
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition here. This can introduce security issues, and is generally not recommended.

If you suppress an error, we recommend checking for the error condition explicitly:

// For example instead of
@mkdir($dir);

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
243
		}
244
		return true;
245
	}
246
247
	private function _readHeader($v_binary_data, &$v_header)
248
	{
249
		if (strlen($v_binary_data) == 0) {
250
			$v_header['filename'] = '';
251
			return true;
252
		}
253
254 View Code Duplication
		if (strlen($v_binary_data) != 512) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

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.

Loading history...
255
			$v_header['filename'] = '';
256
			$this->_error('Invalid block size : ' . strlen($v_binary_data));
257
			return false;
258
		}
259
260
		// ----- Calculate the checksum
261
		$v_checksum = 0;
262
		// ..... First part of the header
263 View Code Duplication
		for ($i = 0; $i < 148; $i++) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

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.

Loading history...
264
			$v_checksum += ord(substr($v_binary_data, $i, 1));
265
		}
266
		// ..... Ignore the checksum value and replace it by ' ' (space)
267
		for ($i = 148; $i < 156; $i++) {
268
			$v_checksum += ord(' ');
269
		}
270
		// ..... Last part of the header
271 View Code Duplication
		for ($i = 156; $i < 512; $i++) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

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.

Loading history...
272
			$v_checksum += ord(substr($v_binary_data, $i, 1));
273
		}
274
275
		$v_data = unpack(
276
			"a100filename/a8mode/a8uid/a8gid/a12size/a12mtime/"
277
						 . "a8checksum/a1typeflag/a100link/a6magic/a2version/"
278
						 . "a32uname/a32gname/a8devmajor/a8devminor",
279
						 $v_binary_data
280
		);
281
282
		// ----- Extract the checksum
283
		$v_header['checksum'] = OctDec(trim($v_data['checksum']));
284
		if ($v_header['checksum'] != $v_checksum) {
285
			$v_header['filename'] = '';
286
287
			// ----- Look for last block (empty block)
288
			if (($v_checksum == 256) && ($v_header['checksum'] == 0)) {
289
				return true;
290
			}
291
292
			$this->_error('Invalid checksum for file "' . $v_data['filename']
293
						  . '" : ' . $v_checksum . ' calculated, '
294
						  . $v_header['checksum'] . ' expected');
295
			return false;
296
		}
297
298
		// ----- Extract the properties
299
		$v_header['filename'] = trim($v_data['filename']);
300
		$v_header['mode'] = OctDec(trim($v_data['mode']));
301
		$v_header['uid'] = OctDec(trim($v_data['uid']));
302
		$v_header['gid'] = OctDec(trim($v_data['gid']));
303
		$v_header['size'] = OctDec(trim($v_data['size']));
304
		$v_header['mtime'] = OctDec(trim($v_data['mtime']));
305
		if (($v_header['typeflag'] = $v_data['typeflag']) == "5") {
306
			$v_header['size'] = 0;
307
		}
308
		return true;
309
	}
310
311
	private function _readLongHeader(&$v_header)
312
	{
313
		$v_filename = '';
314
		$n = floor($v_header['size'] / 512);
315
		for ($i = 0; $i < $n; $i++) {
316
			$v_content = $this->_readBlock();
317
			$v_filename .= $v_content;
318
		}
319
		if (($v_header['size'] % 512) != 0) {
320
			$v_content = $this->_readBlock();
321
			$v_filename .= $v_content;
322
		}
323
324
		// ----- Read the next header
325
		$v_binary_data = $this->_readBlock();
326
327
		if (!$this->_readHeader($v_binary_data, $v_header)) {
328
			return false;
329
		}
330
331
		$v_header['filename'] = $v_filename;
332
333
		return true;
334
	}
335
336
	protected function _extractList(
337
		$p_path,
338
		&$p_list_detail,
339
		$p_mode,
340
						  $p_file_list,
341
		$p_remove_path
342
	) {
343
		$v_result = true;
0 ignored issues
show
Unused Code introduced by
$v_result is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
344
		$v_nb = 0;
345
		$v_extract_all = true;
0 ignored issues
show
Unused Code introduced by
$v_extract_all is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
346
		$v_listing = false;
0 ignored issues
show
Unused Code introduced by
$v_listing is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
347
348
		$p_path = $this->_translateWinPath($p_path, false);
349
		if ($p_path == '' || (substr($p_path, 0, 1) != '/'
350
		&& substr($p_path, 0, 3) != "../" && !strpos($p_path, ':'))) {
351
			$p_path = "./" . $p_path;
352
		}
353
		$p_remove_path = $this->_translateWinPath($p_remove_path);
354
355
		// ----- Look for path to remove format (should end by /)
356
		if (($p_remove_path != '') && (substr($p_remove_path, -1) != '/')) {
357
			$p_remove_path .= '/';
358
		}
359
		$p_remove_path_size = strlen($p_remove_path);
360
361
		switch ($p_mode) {
362
	  case "complete":
363
		$v_extract_all = true;
364
		$v_listing = false;
365
	  break;
366
	  case "partial":
367
		  $v_extract_all = false;
368
		  $v_listing = false;
369
	  break;
370
	  case "list":
371
		  $v_extract_all = false;
372
		  $v_listing = true;
373
	  break;
374
	  default:
375
		$this->_error('Invalid extract mode (' . $p_mode . ')');
376
		return false;
377
	}
378
379
		clearstatcache();
380
381
		while (strlen($v_binary_data = $this->_readBlock()) != 0) {
382
			$v_extract_file = false;
0 ignored issues
show
Unused Code introduced by
$v_extract_file is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
383
			$v_extraction_stopped = 0;
384
385
			if (!$this->_readHeader($v_binary_data, $v_header)) {
386
				return false;
387
			}
388
389
			if ($v_header['filename'] == '') {
390
				continue;
391
			}
392
393
			// ----- Look for long filename
394
			if ($v_header['typeflag'] == 'L') {
395
				if (!$this->_readLongHeader($v_header)) {
396
					return false;
397
				}
398
			}
399
400
			if ((!$v_extract_all) && (is_array($p_file_list))) {
401
				// ----- By default no unzip if the file is not found
402
				$v_extract_file = false;
403
404
				for ($i = 0; $i < count($p_file_list); $i++) {
0 ignored issues
show
Performance Best Practice introduced by
It seems like you are calling the size function count() as part of the test condition. You might want to compute the size beforehand, and not on each iteration.

If the size of the collection does not change during the iteration, it is generally a good practice to compute it beforehand, and not on each iteration:

for ($i=0; $i<count($array); $i++) { // calls count() on each iteration
}

// Better
for ($i=0, $c=count($array); $i<$c; $i++) { // calls count() just once
}
Loading history...
405
					// ----- Look if it is a directory
406
					if (substr($p_file_list[$i], -1) == '/') {
407
						// ----- Look if the directory is in the filename path
408
						if ((strlen($v_header['filename']) > strlen($p_file_list[$i]))
409
				&& (substr($v_header['filename'], 0, strlen($p_file_list[$i]))
410
					== $p_file_list[$i])) {
411
							$v_extract_file = true;
412
							break;
413
						}
414
					}
415
416
					// ----- It is a file, so compare the file names
417
					elseif ($p_file_list[$i] == $v_header['filename']) {
418
						$v_extract_file = true;
419
						break;
420
					}
421
				}
422
			} else {
423
				$v_extract_file = true;
424
			}
425
426
			// ----- Look if this file need to be extracted
427
			if (($v_extract_file) && (!$v_listing)) {
428
				if (($p_remove_path != '')
429
			&& (substr($v_header['filename'], 0, $p_remove_path_size)
430
				== $p_remove_path)) {
431
					$v_header['filename'] = substr(
432
			$v_header['filename'],
433
										 $p_remove_path_size
434
		  );
435
				}
436
				if (($p_path != './') && ($p_path != '/')) {
437
					while (substr($p_path, -1) == '/') {
438
						$p_path = substr($p_path, 0, strlen($p_path) - 1);
439
					}
440
441
					if (substr($v_header['filename'], 0, 1) == '/') {
442
						$v_header['filename'] = $p_path . $v_header['filename'];
443
					} else {
444
						$v_header['filename'] = $p_path . '/' . $v_header['filename'];
445
					}
446
				}
447
				if (file_exists($v_header['filename'])) {
448 View Code Duplication
					if ((@is_dir($v_header['filename']))
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

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.

Loading history...
449
			  && ($v_header['typeflag'] == '')) {
450
						$this->_error('File ' . $v_header['filename']
451
						  . ' already exists as a directory');
452
						return false;
453
					}
454 View Code Duplication
					if (($this->_isArchive($v_header['filename']))
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

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.

Loading history...
455
			  && ($v_header['typeflag'] == "5")) {
456
						$this->_error('Directory ' . $v_header['filename']
457
						  . ' already exists as a file');
458
						return false;
459
					}
460
					if (!is_writable($v_header['filename'])) {
461
						$this->_error('File ' . $v_header['filename']
462
						  . ' already exists and is write protected');
463
						return false;
464
					}
465
					if (filemtime($v_header['filename']) > $v_header['mtime']) {
0 ignored issues
show
Unused Code introduced by
This if statement is empty and can be removed.

This check looks for the bodies of if statements that have no statements or where all statements have been commented out. This may be the result of changes for debugging or the code may simply be obsolete.

These if bodies can be removed. If you have an empty if but statements in the else branch, consider inverting the condition.

if (rand(1, 6) > 3) {
//print "Check failed";
} else {
    print "Check succeeded";
}

could be turned into

if (rand(1, 6) <= 3) {
    print "Check succeeded";
}

This is much more concise to read.

Loading history...
466
						// To be completed : An error or silent no replace ?
467
					}
468
				}
469
470
				// ----- Check the directory availability and create it if necessary
471
				elseif (($v_result
472
				 = $this->_dirCheck(($v_header['typeflag'] == "5"
473
									? $v_header['filename']
474
									: dirname($v_header['filename'])))) != 1) {
475
					$this->_error('Unable to create path for ' . $v_header['filename']);
476
					return false;
477
				}
478
479
				if ($v_extract_file) {
480
					if ($v_header['typeflag'] == "5") {
481
						if (!@file_exists($v_header['filename'])) {
482 View Code Duplication
							if (!@mkdir($v_header['filename'], PRADO_CHMOD)) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

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.

Loading history...
483
								$this->_error('Unable to create directory {'
484
								  . $v_header['filename'] . '}');
485
								return false;
486
							}
487
							chmod($v_header['filename'], PRADO_CHMOD);
488
						}
489
					} else {
490
						if (($v_dest_file = @fopen($v_header['filename'], "wb")) == 0) {
491
							$this->_error('Error while opening {' . $v_header['filename']
492
								. '} in write binary mode');
493
							return false;
494
						} else {
495
							$n = floor($v_header['size'] / 512);
496
							for ($i = 0; $i < $n; $i++) {
497
								$v_content = $this->_readBlock();
498
								fwrite($v_dest_file, $v_content, 512);
499
							}
500
							if (($v_header['size'] % 512) != 0) {
501
								$v_content = $this->_readBlock();
502
								fwrite($v_dest_file, $v_content, ($v_header['size'] % 512));
503
							}
504
505
							@fclose($v_dest_file);
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition here. This can introduce security issues, and is generally not recommended.

If you suppress an error, we recommend checking for the error condition explicitly:

// For example instead of
@mkdir($dir);

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
506
507
							// ----- Change the file mode, mtime
508
							@touch($v_header['filename'], $v_header['mtime']);
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition here. This can introduce security issues, and is generally not recommended.

If you suppress an error, we recommend checking for the error condition explicitly:

// For example instead of
@mkdir($dir);

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
509
							// To be completed
510
			//chmod($v_header[filename], DecOct($v_header[mode]));
511
						}
512
513
						// ----- Check the file size
514
						clearstatcache();
515
						if (filesize($v_header['filename']) != $v_header['size']) {
516
							$this->_error('Extracted file ' . $v_header['filename']
517
							. ' does not have the correct file size \''
518
							. filesize($v_header['filename'])
519
							. '\' (' . $v_header['size']
520
							. ' expected). Archive may be corrupted.');
521
							return false;
522
						}
523
					}
524
				} else {
525
					$this->_jumpBlock(ceil(($v_header['size'] / 512)));
526
				}
527
			} else {
528
				$this->_jumpBlock(ceil(($v_header['size'] / 512)));
529
			}
530
531
			/* TBC : Seems to be unused ...
532
			if ($this->_compress)
533
		$v_end_of_file = @gzeof($this->_file);
534
			else
535
		$v_end_of_file = @feof($this->_file);
536
		*/
537
538
			if ($v_listing || $v_extract_file || $v_extraction_stopped) {
539
				// ----- Log extracted files
540
				if (($v_file_dir = dirname($v_header['filename']))
541
			== $v_header['filename']) {
542
					$v_file_dir = '';
543
				}
544
				if ((substr($v_header['filename'], 0, 1) == '/') && ($v_file_dir == '')) {
545
					$v_file_dir = '/';
0 ignored issues
show
Unused Code introduced by
$v_file_dir is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
546
				}
547
548
				$p_list_detail[$v_nb++] = $v_header;
549
			}
550
		}
551
552
		return true;
553
	}
554
555
	/**
556
	 * Check if a directory exists and create it (including parent
557
	 * dirs) if not.
558
	 *
559
	 * @param string $p_dir directory to check
560
	 *
561
	 * @return bool true if the directory exists or was created
562
	 */
563
	protected function _dirCheck($p_dir)
564
	{
565
		if ((@is_dir($p_dir)) || ($p_dir == '')) {
566
			return true;
567
		}
568
569
		$p_parent_dir = dirname($p_dir);
570
571
		if (($p_parent_dir != $p_dir) &&
572
			($p_parent_dir != '') &&
573
			(!$this->_dirCheck($p_parent_dir))) {
574
			return false;
575
		}
576
577
		if (!@mkdir($p_dir, PRADO_CHMOD)) {
578
			$this->_error("Unable to create directory '$p_dir'");
579
			return false;
580
		}
581
		chmod($p_dir, PRADO_CHMOD);
582
583
		return true;
584
	}
585
586
	protected function _translateWinPath($p_path, $p_remove_disk_letter = true)
587
	{
588
		if (substr(PHP_OS, 0, 3) == 'WIN') {
589
			// ----- Look for potential disk letter
590
			if (($p_remove_disk_letter)
591
			  && (($v_position = strpos($p_path, ':')) != false)) {
0 ignored issues
show
Bug Best Practice introduced by
It seems like you are loosely comparing $v_position = strpos($p_path, ':') of type integer to the boolean false. If you are specifically checking for non-zero, consider using something more explicit like > 0 or !== 0 instead.
Loading history...
592
				$p_path = substr($p_path, $v_position + 1);
593
			}
594
			// ----- Change potential windows directory separator
595
			if ((strpos($p_path, '\\') > 0) || (substr($p_path, 0, 1) == '\\')) {
596
				$p_path = strtr($p_path, '\\', '/');
597
			}
598
		}
599
		return $p_path;
600
	}
601
}
602