GitHub Access Token became invalid

It seems like the GitHub access token used for retrieving details about this repository from GitHub became invalid. This might prevent certain types of inspections from being run (in particular, everything related to pull requests).
Please ask an admin of your repository to re-new the access token on this website.
Completed
Pull Request — develop (#1930)
by
unknown
13:51
created

FileHandler::readDir()   D

Complexity

Conditions 10
Paths 22

Size

Total Lines 43
Code Lines 19

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 10
eloc 19
nc 22
nop 4
dl 0
loc 43
rs 4.8196
c 0
b 0
f 0

How to fix   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
/* Copyright (C) NAVER <http://www.navercorp.com> */
3
4
/**
5
 * Contains methods for accessing file system
6
 *
7
 * @author NAVER ([email protected])
8
 */
9
class FileHandler
10
{
11
12
	/**
13
	 * Changes path of target file, directory into absolute path
14
	 *
15
	 * @param string $source path to change into absolute path
16
	 * @return string Absolute path
17
	 */
18
	function getRealPath($source)
19
	{
20
		if(strlen($source) >= 2 && substr_compare($source, './', 0, 2) === 0)
21
		{
22
			return _XE_PATH_ . substr($source, 2);
23
		}
24
25
		return $source;
26
	}
27
28
	/**
29
	 * Copy a directory to target
30
	 *
31
	 * If target directory does not exist, this function creates it
32
	 *
33
	 * @param string $source_dir Path of source directory
34
	 * @param string $target_dir Path of target dir
35
	 * @param string $filter Regex to filter files. If file matches this regex, the file is not copied.
36
	 * @param string $type If set as 'force'. Even if the file exists in target, the file is copied.
37
	 * @return void
38
	 */
39
	function copyDir($source_dir, $target_dir, $filter = null, $type = null)
40
	{
41
		$source_dir = self::getRealPath($source_dir);
42
		$target_dir = self::getRealPath($target_dir);
43
		if(!is_dir($source_dir))
44
		{
45
			return FALSE;
46
		}
47
48
		// generate when no target exists
49
		self::makeDir($target_dir);
50
51
		if(substr($source_dir, -1) != DIRECTORY_SEPARATOR)
52
		{
53
			$source_dir .= DIRECTORY_SEPARATOR;
54
		}
55
56
		if(substr($target_dir, -1) != DIRECTORY_SEPARATOR)
57
		{
58
			$target_dir .= DIRECTORY_SEPARATOR;
59
		}
60
61
		$oDir = dir($source_dir);
62
		while($file = $oDir->read())
63
		{
64
			if($file{0} == '.')
65
			{
66
				continue;
67
			}
68
69
			if($filter && preg_match($filter, $file))
0 ignored issues
show
Bug Best Practice introduced by
The expression $filter of type string|null is loosely compared to true; this is ambiguous if the string can be empty. You might want to explicitly use !== null instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
70
			{
71
				continue;
72
			}
73
74
			if(is_dir($source_dir . $file))
75
			{
76
				self::copyDir($source_dir . $file, $target_dir . $file, $type);
77
			}
78
			else
79
			{
80
				if($type == 'force')
81
				{
82
					@unlink($target_dir . $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...
83
				}
84
				else
85
				{
86
					if(!file_exists($target_dir . $file))
87
					{
88
						@copy($source_dir . $file, $target_dir . $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...
89
					}
90
				}
91
			}
92
		}
93
		$oDir->close();
94
	}
95
96
	/**
97
	 * Copy a file to target
98
	 *
99
	 * @param string $source Path of source file
100
	 * @param string $target Path of target file
101
	 * @param string $force Y: overwrite
102
	 * @return void
103
	 */
104
	function copyFile($source, $target, $force = 'Y')
105
	{
106
		setlocale(LC_CTYPE, 'en_US.UTF8', 'ko_KR.UTF8');
107
		$source = self::getRealPath($source);
108
		$target_dir = self::getRealPath(dirname($target));
109
		$target = basename($target);
110
111
		self::makeDir($target_dir);
112
113
		if($force == 'Y')
114
		{
115
			@unlink($target_dir . DIRECTORY_SEPARATOR . $target);
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...
116
		}
117
118
		@copy($source, $target_dir . DIRECTORY_SEPARATOR . $target);
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...
119
	}
120
121
	/**
122
	 * Returns the content of the file
123
	 *
124
	 * @param string $filename Path of target file
125
	 * @return string The content of the file. If target file does not exist, this function returns nothing.
126
	 */
127
	function readFile($filename)
128
	{
129
		if(($filename = self::exists($filename)) === FALSE || filesize($filename) < 1)
130
		{
131
			return;
132
		}
133
134
		return @file_get_contents($filename);
135
	}
136
137
	/**
138
	 * Write $buff into the specified file
139
	 *
140
	 * @param string $filename Path of target file
141
	 * @param string $buff Content to be written
142
	 * @param string $mode a(append) / w(write)
143
	 * @return void
144
	 */
145
	function writeFile($filename, $buff, $mode = "w")
146
	{
147
		$filename = self::getRealPath($filename);
148
		$pathinfo = pathinfo($filename);
149
		self::makeDir($pathinfo['dirname']);
150
151
		$flags = 0;
152
		if(strtolower($mode) == 'a')
153
		{
154
			$flags = FILE_APPEND;
155
		}
156
157
		@file_put_contents($filename, $buff, $flags|LOCK_EX);
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...
158
		@chmod($filename, 0644);
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...
159
	}
160
161
	/**
162
	 * Remove a file
163
	 *
164
	 * @param string $filename path of target file
165
	 * @return bool Returns TRUE on success or FALSE on failure.
166
	 */
167
	function removeFile($filename)
168
	{
169
		return (($filename = self::exists($filename)) !== FALSE) && @unlink($filename);
170
	}
171
172
	/**
173
	 * Rename a file
174
	 *
175
	 * In order to move a file, use this function.
176
	 *
177
	 * @param string $source Path of source file
178
	 * @param string $target Path of target file
179
	 * @return bool Returns TRUE on success or FALSE on failure.
180
	 */
181
	function rename($source, $target)
182
	{
183
		return @rename(self::getRealPath($source), self::getRealPath($target));
184
	}
185
186
	/**
187
	 * Move a file
188
	 *
189
	 * @param string $source Path of source file
190
	 * @param string $target Path of target file
191
	 * @return bool Returns TRUE on success or FALSE on failure.
192
	 */
193
	function moveFile($source, $target)
194
	{
195
		if(($source = self::exists($source)) !== FALSE)
196
		{
197
			self::removeFile($target);
198
			return self::rename($source, $target);
199
		}
200
		return FALSE;
201
	}
202
203
	/**
204
	 * Move a directory
205
	 *
206
	 * This function just wraps rename function.
207
	 *
208
	 * @param string $source_dir Path of source directory
209
	 * @param string $target_dir Path of target directory
210
	 * @return void
211
	 */
212
	function moveDir($source_dir, $target_dir)
213
	{
214
		self::rename($source_dir, $target_dir);
215
	}
216
217
	/**
218
	 * Return list of the files in the path
219
	 *
220
	 * The array does not contain files, such as '.', '..', and files starting with '.'
221
	 *
222
	 * @param string $path Path of target directory
223
	 * @param string $filter If specified, return only files matching with the filter
224
	 * @param bool $to_lower If TRUE, file names will be changed into lower case.
225
	 * @param bool $concat_prefix If TRUE, return file name as absolute path
226
	 * @return string[] Array of the filenames in the path
227
	 */
228
	function readDir($path, $filter = '', $to_lower = FALSE, $concat_prefix = FALSE)
229
	{
230
		$path = self::getRealPath($path);
231
		$output = array();
232
233
		if(substr($path, -1) != '/')
234
		{
235
			$path .= '/';
236
		}
237
238
		if(!is_dir($path))
239
		{
240
			return $output;
241
		}
242
243
		$files = scandir($path);
244
		foreach($files as $file)
245
		{
246
			if($file{0} == '.' || ($filter && !preg_match($filter, $file)))
247
			{
248
				continue;
249
			}
250
251
			if($to_lower)
252
			{
253
				$file = strtolower($file);
254
			}
255
256
			if($filter)
257
			{
258
				$file = preg_replace($filter, '$1', $file);
259
			}
260
261
			if($concat_prefix)
262
			{
263
				$file = sprintf('%s%s', str_replace(_XE_PATH_, '', $path), $file);
264
			}
265
266
			$output[] = str_replace(array('/\\', '//'), '/', $file);
267
		}
268
269
		return $output;
270
	}
271
272
	/**
273
	 * Creates a directory
274
	 *
275
	 * This function creates directories recursively, which means that if ancestors of the target directory does not exist, they will be created too.
276
	 *
277
	 * @param string $path_string Path of target directory
278
	 * @return bool TRUE if success. It might return nothing when ftp is used and connection to the ftp address failed.
279
	 */
280
	function makeDir($path_string)
281
	{
282
		if(self::exists($path_string) !== FALSE)
283
		{
284
			return TRUE;
285
		}
286
287
		if(!ini_get('safe_mode'))
288
		{
289
			@mkdir($path_string, 0755, TRUE);
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...
290
			@chmod($path_string, 0755);
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...
291
		}
292
		// if safe_mode is on, use FTP
293
		else
294
		{
295
			static $oFtp = NULL;
296
297
			$ftp_info = Context::getFTPInfo();
298
			if($oFtp == NULL)
299
			{
300
				if(!Context::isFTPRegisted())
301
				{
302
					return;
303
				}
304
305
				require_once(_XE_PATH_ . 'libs/ftp.class.php');
306
				$oFtp = new ftp();
307
				if(!$ftp_info->ftp_host)
308
				{
309
					$ftp_info->ftp_host = "127.0.0.1";
310
				}
311
				if(!$ftp_info->ftp_port)
312
				{
313
					$ftp_info->ftp_port = 21;
314
				}
315
				if(!$oFtp->ftp_connect($ftp_info->ftp_host, $ftp_info->ftp_port))
316
				{
317
					return;
318
				}
319
				if(!$oFtp->ftp_login($ftp_info->ftp_user, $ftp_info->ftp_password))
320
				{
321
					$oFtp->ftp_quit();
322
					return;
323
				}
324
			}
325
326
			if(!($ftp_path = $ftp_info->ftp_root_path))
327
			{
328
				$ftp_path = DIRECTORY_SEPARATOR;
329
			}
330
331
			$path_string = str_replace(_XE_PATH_, '', $path_string);
332
			$path_list = explode(DIRECTORY_SEPARATOR, $path_string);
333
334
			$path = _XE_PATH_;
335
			for($i = 0, $c = count($path_list); $i < $c; $i++)
336
			{
337
				if(!$path_list[$i])
338
				{
339
					continue;
340
				}
341
342
				$path .= $path_list[$i] . DIRECTORY_SEPARATOR;
343
				$ftp_path .= $path_list[$i] . DIRECTORY_SEPARATOR;
344
				if(!is_dir($path))
345
				{
346
					$oFtp->ftp_mkdir($ftp_path);
347
					$oFtp->ftp_site("CHMOD 777 " . $ftp_path);
348
				}
349
			}
350
		}
351
352
		return is_dir($path_string);
353
	}
354
355
	/**
356
	 * Remove all files under the path
357
	 *
358
	 * @param string $path Path of the target directory
359
	 * @return void
360
	 */
361 View Code Duplication
	function removeDir($path)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in 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...
362
	{
363
		if(($path = self::isDir($path)) === FALSE)
364
		{
365
			return;
366
		}
367
368
		if(self::isDir($path))
0 ignored issues
show
Bug Best Practice introduced by
The expression self::isDir($path) of type string|false is loosely compared to true; this is ambiguous if the string can be empty. You might want to explicitly use !== false instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
369
		{
370
			$files = array_diff(scandir($path), array('..', '.'));
371
372
			foreach($files as $file)
373
			{
374
				if(($target = self::getRealPath($path . DIRECTORY_SEPARATOR . $file)) === FALSE)
375
				{
376
					continue;
377
				}
378
379
				if(is_dir($target))
380
				{
381
					self::removeDir($target);
382
				}
383
				else
384
				{
385
					unlink($target);
386
				}
387
			}
388
			rmdir($path);
389
		}
390
		else
391
		{
392
			unlink($path);
393
		}
394
	}
395
396
	/**
397
	 * Remove a directory only if it is empty
398
	 *
399
	 * @param string $path Path of the target directory
400
	 * @return void
401
	 */
402
	function removeBlankDir($path)
403
	{
404
		if(($path = self::isDir($path)) === FALSE)
405
		{
406
			return;
407
		}
408
409
		$files = array_diff(scandir($path), array('..', '.'));
410
411
		if(count($files) < 1)
412
		{
413
			rmdir($path);
414
			return;
415
		}
416
417
		foreach($files as $file)
418
		{
419
			if(($target = self::isDir($path . DIRECTORY_SEPARATOR . $file)) === FALSE)
420
			{
421
				continue;
422
			}
423
424
			self::removeBlankDir($target);
425
		}
426
	}
427
428
	/**
429
	 * Remove files in the target directory
430
	 *
431
	 * This function keeps the directory structure.
432
	 *
433
	 * @param string $path Path of the target directory
434
	 * @return void
435
	 */
436 View Code Duplication
	function removeFilesInDir($path)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in 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...
437
	{
438
		if(($path = self::getRealPath($path)) === FALSE)
439
		{
440
			return;
441
		}
442
443
		if(is_dir($path))
444
		{
445
			$files = array_diff(scandir($path), array('..', '.'));
446
447
			foreach($files as $file)
448
			{
449
				if(($target = self::getRealPath($path . DIRECTORY_SEPARATOR . $file)) === FALSE)
450
				{
451
					continue;
452
				}
453
454
				if(is_dir($target))
455
				{
456
					self::removeFilesInDir($target);
457
				}
458
				else
459
				{
460
					unlink($target);
461
				}
462
			}
463
		}
464
		else
465
		{
466
			if(self::exists($path)) unlink($path);
0 ignored issues
show
Bug Best Practice introduced by
The expression self::exists($path) of type string|false is loosely compared to true; this is ambiguous if the string can be empty. You might want to explicitly use !== false instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
467
		}
468
469
	}
470
471
	/**
472
	 * Makes file size byte into KB, MB according to the size
473
	 *
474
	 * @see self::returnBytes()
475
	 * @param int $size Number of the size
476
	 * @return string File size string
477
	 */
478
	function filesize($size)
479
	{
480
		if(!$size)
481
		{
482
			return '0Byte';
483
		}
484
485
		if($size === 1)
486
		{
487
			return '1Byte';
488
		}
489
490
		if($size < 1024)
491
		{
492
			return $size . 'Bytes';
493
		}
494
495
		if($size >= 1024 && $size < 1024 * 1024)
496
		{
497
			return sprintf("%0.1fKB", $size / 1024);
498
		}
499
500
		return sprintf("%0.2fMB", $size / (1024 * 1024));
501
	}
502
503
	/**
504
	 * Return remote file's content via HTTP
505
	 *
506
	 * If the target is moved (when return code is 300~399), this function follows the location specified response header.
507
	 *
508
	 * @param string $url The address of the target file
509
	 * @param string $body HTTP request body
510
	 * @param int $timeout Connection timeout
511
	 * @param string $method GET/POST
512
	 * @param string $content_type Content type header of HTTP request
513
	 * @param string[] $headers Headers key value array.
514
	 * @param string[] $cookies Cookies key value array.
515
	 * @param string $post_data Request arguments array for POST method
516
	 * @return string If success, the content of the target file. Otherwise: none
517
	 */
518
	function getRemoteResource($url, $body = null, $timeout = 3, $method = 'GET', $content_type = null, $headers = array(), $cookies = array(), $post_data = array(), $request_config = array())
519
	{
520
		require_once(_XE_PATH_ . 'libs/idna_convert/idna_convert.class.php');
521
		$IDN = new idna_convert(array('idn_version' => 2008));
522
		$url = $IDN->encode($url);
523
524
		try
525
		{
526
			requirePear();
527
			require_once('HTTP/Request.php');
528
529
			$parsed_url = parse_url(__PROXY_SERVER__);
530
			if($parsed_url["host"])
531
			{
532
				$oRequest = new HTTP_Request(__PROXY_SERVER__);
533
				$oRequest->setMethod('POST');
534
				$oRequest->addPostData('arg', serialize(array('Destination' => $url, 'method' => $method, 'body' => $body, 'content_type' => $content_type, "headers" => $headers, "post_data" => $post_data)));
535
			}
536
			else
537
			{
538
				$oRequest = new HTTP_Request($url);
0 ignored issues
show
Security Bug introduced by
It seems like $url defined by $IDN->encode($url) on line 522 can also be of type false; however, HTTP_Request2::__construct() does only seem to accept string|object<Net_URL2>|null, did you maybe forget to handle an error condition?

This check looks for type mismatches where the missing type is false. This is usually indicative of an error condtion.

Consider the follow example

<?php

function getDate($date)
{
    if ($date !== null) {
        return new DateTime($date);
    }

    return false;
}

This function either returns a new DateTime object or false, if there was an error. This is a typical pattern in PHP programming to show that an error has occurred without raising an exception. The calling code should check for this returned false before passing on the value to another function or method that may not be able to handle a false.

Loading history...
539
540
				if(count($request_config) && method_exists($oRequest, 'setConfig'))
541
				{
542
					foreach($request_config as $key=>$val)
543
					{
544
						if($key === 'observers')
545
						{
546
							foreach($val as $observer)
547
							{
548
								$oRequest->attach($observer);
549
							}
550
						}
551
						else
552
						{
553
							$oRequest->setConfig($key, $val);
554
						}
555
					}
556
				}
557
558
				if(count($headers) > 0)
559
				{
560
					foreach($headers as $key => $val)
561
					{
562
						$oRequest->addHeader($key, $val);
563
					}
564
				}
565
				if($cookies[$host])
566
				{
567
					foreach($cookies[$host] as $key => $val)
0 ignored issues
show
Bug introduced by
The variable $host does not exist. Did you forget to declare it?

This check marks access to variables or properties that have not been declared yet. While PHP has no explicit notion of declaring a variable, accessing it before a value is assigned to it is most likely a bug.

Loading history...
Bug introduced by
The expression $cookies[$host] of type string is not traversable.
Loading history...
568
					{
569
						$oRequest->addCookie($key, $val);
570
					}
571
				}
572
				if(count($post_data) > 0)
573
				{
574
					foreach($post_data as $key => $val)
0 ignored issues
show
Bug introduced by
The expression $post_data of type string|array is not guaranteed to be traversable. How about adding an additional type check?

There are different options of fixing this problem.

  1. If you want to be on the safe side, you can add an additional type-check:

    $collection = json_decode($data, true);
    if ( ! is_array($collection)) {
        throw new \RuntimeException('$collection must be an array.');
    }
    
    foreach ($collection as $item) { /** ... */ }
    
  2. If you are sure that the expression is traversable, you might want to add a doc comment cast to improve IDE auto-completion and static analysis:

    /** @var array $collection */
    $collection = json_decode($data, true);
    
    foreach ($collection as $item) { /** .. */ }
    
  3. Mark the issue as a false-positive: Just hover the remove button, in the top-right corner of this issue for more options.

Loading history...
575
					{
576
						$oRequest->addPostData($key, $val);
577
					}
578
				}
579
				if(!$content_type)
0 ignored issues
show
Bug Best Practice introduced by
The expression $content_type of type string|null is loosely compared to false; this is ambiguous if the string can be empty. You might want to explicitly use === null instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
580
					$oRequest->addHeader('Content-Type', 'text/html');
581
				else
582
					$oRequest->addHeader('Content-Type', $content_type);
583
				$oRequest->setMethod($method);
584
				if($body)
0 ignored issues
show
Bug Best Practice introduced by
The expression $body of type string|null is loosely compared to true; this is ambiguous if the string can be empty. You might want to explicitly use !== null instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
585
					$oRequest->setBody($body);
586
			}
587
			
588
			if(method_exists($oRequest, 'setConfig'))
589
			{
590
				$oRequest->setConfig('timeout', $timeout);
591
			}
592
			elseif(property_exists($oRequest, '_timeout'))
593
			{
594
				$oRequest->_timeout = $timeout;
0 ignored issues
show
Bug introduced by
The property _timeout does not seem to exist in HTTP_Request.

An attempt at access to an undefined property has been detected. This may either be a typographical error or the property has been renamed but there are still references to its old name.

If you really want to allow access to undefined properties, you can define magic methods to allow access. See the php core documentation on Overloading.

Loading history...
595
			}
596
597
			$oResponse = $oRequest->sendRequest();
0 ignored issues
show
Unused Code introduced by
$oResponse 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...
598
599
			$code = $oRequest->getResponseCode();
600
			$header = $oRequest->getResponseHeader();
601
			$response = $oRequest->getResponseBody();
602
			if($c = $oRequest->getResponseCookies())
603
			{
604
				foreach($c as $k => $v)
605
				{
606
					$cookies[$host][$v['name']] = $v['value'];
607
				}
608
			}
609
610
			if($code > 300 && $code < 399 && $header['location'])
611
			{
612
				return self::getRemoteResource($header['location'], $body, $timeout, $method, $content_type, $headers, $cookies, $post_data);
613
			}
614
615
			if($code != 200)
616
			{
617
				return;
618
			}
619
620
			if(isset($request_config['store_body']) && !$request_config['store_body'])
621
			{
622
				return TRUE;
0 ignored issues
show
Bug Best Practice introduced by
The return type of return TRUE; (boolean) is incompatible with the return type documented by FileHandler::getRemoteResource of type string.

If you return a value from a function or method, it should be a sub-type of the type that is given by the parent type f.e. an interface, or abstract method. This is more formally defined by the Lizkov substitution principle, and guarantees that classes that depend on the parent type can use any instance of a child type interchangably. This principle also belongs to the SOLID principles for object oriented design.

Let’s take a look at an example:

class Author {
    private $name;

    public function __construct($name) {
        $this->name = $name;
    }

    public function getName() {
        return $this->name;
    }
}

abstract class Post {
    public function getAuthor() {
        return 'Johannes';
    }
}

class BlogPost extends Post {
    public function getAuthor() {
        return new Author('Johannes');
    }
}

class ForumPost extends Post { /* ... */ }

function my_function(Post $post) {
    echo strtoupper($post->getAuthor());
}

Our function my_function expects a Post object, and outputs the author of the post. The base class Post returns a simple string and outputting a simple string will work just fine. However, the child class BlogPost which is a sub-type of Post instead decided to return an object, and is therefore violating the SOLID principles. If a BlogPost were passed to my_function, PHP would not complain, but ultimately fail when executing the strtoupper call in its body.

Loading history...
623
			}
624
			else
625
			{
626
				return $response;
627
			}
628
		}
629
		catch(Exception $e)
630
		{
631
			return NULL;
632
		}
633
	}
634
635
	/**
636
	 * Retrieves remote file, then stores it into target path.
637
	 *
638
	 * @param string $url The address of the target file
639
	 * @param string $target_filename The location to store
640
	 * @param string $body HTTP request body
641
	 * @param string $timeout Connection timeout
642
	 * @param string $method GET/POST
643
	 * @param string $content_type Content type header of HTTP request
644
	 * @param string[] $headers Headers key value array.
645
	 * @return bool TRUE: success, FALSE: failed
646
	 */
647
	function getRemoteFile($url, $target_filename, $body = null, $timeout = 3, $method = 'GET', $content_type = null, $headers = array(), $cookies = array(), $post_data = array(), $request_config = array())
648
	{
649
		$target_filename = self::getRealPath($target_filename);
650
		self::writeFile($target_filename, '');
651
		
652
		requirePear();
653
		require_once('HTTP/Request2/Observer/Download.php');
654
		
655
		$request_config['store_body'] = false;
656
		$request_config['observers'][] = new HTTP_Request2_Observer_Download($target_filename);
657
		try
658
		{
659
			$result = self::getRemoteResource($url, $body, $timeout, $method, $content_type, $headers, $cookies, $post_data, $request_config);
660
		}
661
		catch(Exception $e)
662
		{
663
			return FALSE;
664
		}
665
		return $result ? TRUE : FALSE;
666
	}
667
668
	/**
669
	 * Convert size in string into numeric value
670
	 *
671
	 * @see self::filesize()
672
	 * @param $val Size in string (ex., 10, 10K, 10M, 10G )
673
	 * @return int converted size
674
	 */
675
	function returnBytes($val)
676
	{
677
		$unit = strtoupper(substr($val, -1));
678
		$val = (float)$val;
679
680
		switch ($unit)
681
		{
682
			case 'G': $val *= 1024;
683
			case 'M': $val *= 1024;
684
			case 'K': $val *= 1024;
685
		}
686
687
		return round($val);
688
	}
689
690
	/**
691
	 * Check available memory to load image file
692
	 *
693
	 * @param array $imageInfo Image info retrieved by getimagesize function
694
	 * @return bool TRUE: it's ok, FALSE: otherwise
695
	 */
696
	function checkMemoryLoadImage(&$imageInfo)
697
	{
698
		$K64 = 65536;
699
		$TWEAKFACTOR = 2.0;
700
		$channels = $imageInfo['channels'];
701
		if(!$channels)
702
		{
703
			$channels = 6; //for png
704
		}
705
		$memoryNeeded = round(($imageInfo[0] * $imageInfo[1] * $imageInfo['bits'] * $channels / 8 + $K64 ) * $TWEAKFACTOR);
706
		$availableMemory = self::returnBytes(ini_get('memory_limit')) - memory_get_usage();
707
		if($availableMemory < $memoryNeeded)
708
		{
709
			return FALSE;
710
		}
711
		return TRUE;
712
	}
713
714
	/**
715
	 * Moves an image file (resizing is possible)
716
	 *
717
	 * @param string $source_file Path of the source file
718
	 * @param string $target_file Path of the target file
719
	 * @param int $resize_width Width to resize
720
	 * @param int $resize_height Height to resize
721
	 * @param string $target_type If $target_type is set (gif, jpg, png, bmp), result image will be saved as target type
722
	 * @param string $thumbnail_type Thumbnail type(crop, ratio)
723
	 * @return bool TRUE: success, FALSE: failed
724
	 */
725
	function createImageFile($source_file, $target_file, $resize_width = 0, $resize_height = 0, $target_type = '', $thumbnail_type = 'crop')
726
	{
727
		// check params
728
		if (($source_file = self::exists($source_file)) === FALSE)
729
		{
730
			return;
731
		}
732
733
		$target_file = self::getRealPath($target_file);
734
		if(!$resize_width)
735
		{
736
			$resize_width = 100;
737
		}
738
739
		if(!$resize_height)
740
		{
741
			$resize_height = $resize_width;
742
		}
743
744
		// retrieve source image's information
745
		$imageInfo = getimagesize($source_file);
746
		if(!self::checkMemoryLoadImage($imageInfo))
747
		{
748
			return FALSE;
749
		}
750
751
		list($width, $height, $type, $attrs) = $imageInfo;
0 ignored issues
show
Unused Code introduced by
The assignment to $attrs is unused. Consider omitting it like so list($first,,$third).

This checks looks for assignemnts to variables using the list(...) function, where not all assigned variables are subsequently used.

Consider the following code example.

<?php

function returnThreeValues() {
    return array('a', 'b', 'c');
}

list($a, $b, $c) = returnThreeValues();

print $a . " - " . $c;

Only the variables $a and $c are used. There was no need to assign $b.

Instead, the list call could have been.

list($a,, $c) = returnThreeValues();
Loading history...
752
		if($width < 1 || $height < 1)
753
		{
754
			return;
755
		}
756
757
		switch($type)
758
		{
759
			case '1' :
760
				$type = 'gif';
761
				break;
762
			case '2' :
763
				$type = 'jpg';
764
				break;
765
			case '3' :
766
				$type = 'png';
767
				break;
768
			case '6' :
769
				$type = 'bmp';
770
				break;
771
			default :
772
				return;
773
		}
774
775
		if(!$target_type)
776
		{
777
			$target_type = $type;
778
		}
779
		$target_type = strtolower($target_type);
780
781
		// if original image is larger than specified size to resize, calculate the ratio
782
		$width_per = ($resize_width > 0 && $width >= $resize_width) ? $resize_width / $width : 1;
783
		$height_per = ($resize_height > 0 && $height >= $resize_height) ? $resize_height / $height : 1;
784
785
		$per = NULL;
0 ignored issues
show
Unused Code introduced by
$per 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...
786
		if($thumbnail_type == 'ratio')
787
		{
788
			$per = ($width_per > $height_per) ? $height_per : $width_per;
789
			$resize_width = $width * $per;
790
			$resize_height = $height * $per;
791
		}
792
		else
793
		{
794
			$per = ($width_per < $height_per) ? $height_per : $width_per;
795
		}
796
797
		// create temporary image with target size
798
		$thumb = NULL;
799
		if(function_exists('imagecreateTRUEcolor'))
800
		{
801
			$thumb = imagecreateTRUEcolor($resize_width, $resize_height);
802
		}
803
		else if(function_exists('imagecreate'))
804
		{
805
			$thumb = imagecreate($resize_width, $resize_height);
806
		}
807
808
		if(!$thumb)
809
		{
810
			return FALSE;
811
		}
812
813
		imagefilledrectangle($thumb, 0, 0, $resize_width - 1, $resize_height - 1, imagecolorallocate($thumb, 255, 255, 255));
814
815
		// create temporary image having original type
816
		$source = NULL;
817
		switch($type)
818
		{
819
			case 'gif' :
820
				if(function_exists('imagecreatefromgif'))
821
				{
822
					$source = @imagecreatefromgif($source_file);
823
				}
824
				break;
825
			case 'jpeg' :
826
			case 'jpg' :
827
				if(function_exists('imagecreatefromjpeg'))
828
				{
829
					$source = @imagecreatefromjpeg($source_file);
830
				}
831
				break;
832
			case 'png' :
833
				if(function_exists('imagecreatefrompng'))
834
				{
835
					$source = @imagecreatefrompng($source_file);
836
				}
837
				break;
838
			case 'wbmp' :
839
			case 'bmp' :
840
				if(function_exists('imagecreatefromwbmp'))
841
				{
842
					$source = @imagecreatefromwbmp($source_file);
843
				}
844
				break;
845
		}
846
847
		if(!$source)
848
		{
849
			imagedestroy($thumb);
850
			return FALSE;
851
		}
852
853
		// resize original image and put it into temporary image
854
		$new_width = (int) ($width * $per);
855
		$new_height = (int) ($height * $per);
856
857
		$x = 0;
858
		$y = 0;
859
		if($thumbnail_type == 'crop')
860
		{
861
			$x = (int) ($resize_width / 2 - $new_width / 2);
862
			$y = (int) ($resize_height / 2 - $new_height / 2);
863
		}
864
865
		if(function_exists('imagecopyresampled'))
866
		{
867
			imagecopyresampled($thumb, $source, $x, $y, 0, 0, $new_width, $new_height, $width, $height);
868
		}
869
		else
870
		{
871
			imagecopyresized($thumb, $source, $x, $y, 0, 0, $new_width, $new_height, $width, $height);
872
		}
873
874
		// create directory
875
		self::makeDir(dirname($target_file));
876
877
		// write into the file
878
		$output = NULL;
879
		switch($target_type)
880
		{
881
			case 'gif' :
882
				if(function_exists('imagegif'))
883
				{
884
					$output = imagegif($thumb, $target_file);
885
				}
886
				break;
887
			case 'jpeg' :
888
			case 'jpg' :
889
				if(function_exists('imagejpeg'))
890
				{
891
					$output = imagejpeg($thumb, $target_file, 100);
892
				}
893
				break;
894
			case 'png' :
895
				if(function_exists('imagepng'))
896
				{
897
					$output = imagepng($thumb, $target_file, 9);
898
				}
899
				break;
900
			case 'wbmp' :
901
			case 'bmp' :
902
				if(function_exists('imagewbmp'))
903
				{
904
					$output = imagewbmp($thumb, $target_file, 100);
905
				}
906
				break;
907
		}
908
909
		imagedestroy($thumb);
910
		imagedestroy($source);
911
912
		if(!$output)
0 ignored issues
show
Bug Best Practice introduced by
The expression $output of type boolean|null is loosely compared to false; this is ambiguous if the boolean can be false. You might want to explicitly use !== null instead.

If an expression can have both false, and null as possible values. It is generally a good practice to always use strict comparison to clearly distinguish between those two values.

$a = canBeFalseAndNull();

// Instead of
if ( ! $a) { }

// Better use one of the explicit versions:
if ($a !== null) { }
if ($a !== false) { }
if ($a !== null && $a !== false) { }
Loading history...
913
		{
914
			return FALSE;
915
		}
916
		@chmod($target_file, 0644);
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...
917
918
		return TRUE;
919
	}
920
921
	/**
922
	 * Reads ini file, and puts result into array
923
	 *
924
	 * @see self::writeIniFile()
925
	 * @param string $filename Path of the ini file
926
	 * @return array ini array (if the target file does not exist, it returns FALSE)
927
	 */
928
	function readIniFile($filename)
929
	{
930
		if(($filename = self::exists($filename)) === FALSE)
931
		{
932
			return FALSE;
933
		}
934
		$arr = parse_ini_file($filename, TRUE);
935
		if(is_array($arr) && count($arr) > 0)
936
		{
937
			return $arr;
938
		}
939
		else
940
		{
941
			return array();
942
		}
943
	}
944
945
	/**
946
	 * Write array into ini file
947
	 *
948
	 * 	$ini['key1'] = 'value1';<br/>
949
	 * 	$ini['key2'] = 'value2';<br/>
950
	 * 	$ini['section']['key1_in_section'] = 'value1_in_section';<br/>
951
	 * 	$ini['section']['key2_in_section'] = 'value2_in_section';<br/>
952
	 * 	self::writeIniFile('exmple.ini', $ini);
953
	 *
954
	 * @see self::readIniFile()
955
	 * @param string $filename Target ini file name
956
	 * @param array $arr Array
957
	 * @return bool if array contains nothing it returns FALSE, otherwise TRUE
958
	 */
959
	function writeIniFile($filename, $arr)
960
	{
961
		if(!is_array($arr) || count($arr) == 0)
962
		{
963
			return FALSE;
964
		}
965
		self::writeFile($filename, self::_makeIniBuff($arr));
966
		return TRUE;
967
	}
968
969
	/**
970
	 * Make array to ini string
971
	 *
972
	 * @param array $arr Array
973
	 * @return string
974
	 */
975
	function _makeIniBuff($arr)
976
	{
977
		$return = array();
978
		foreach($arr as $key => $val)
979
		{
980
			// section
981
			if(is_array($val))
982
			{
983
				$return[] = sprintf("[%s]", $key);
984
				foreach($val as $k => $v)
985
				{
986
					$return[] = sprintf("%s=\"%s\"", $k, $v);
987
				}
988
				// value
989
			}
990
			else if(is_object($val))
991
			{
992
				continue;
993
			}
994
			else
995
			{
996
				$return[] = sprintf("%s=\"%s\"", $key, $val);
997
			}
998
		}
999
1000
		return join("\n", $return);
1001
	}
1002
1003
	/**
1004
	 * Returns a file object
1005
	 *
1006
	 * If the directory of the file does not exist, create it.
1007
	 *
1008
	 * @param string $filename Target file name
1009
	 * @param string $mode File mode for fopen
1010
	 * @return FileObject File object
1011
	 */
1012
	function openFile($filename, $mode)
1013
	{
1014
		$pathinfo = pathinfo($filename);
1015
		self::makeDir($pathinfo['dirname']);
1016
1017
		require_once("FileObject.class.php");
1018
		return  new FileObject($filename, $mode);
1019
	}
1020
1021
	/**
1022
	 * Check whether the given file has the content.
1023
	 *
1024
	 * @param string $filename Target file name
1025
	 * @return bool Returns TRUE if the file exists and contains something.
1026
	 */
1027
	function hasContent($filename)
1028
	{
1029
		return (is_readable($filename) && (filesize($filename) > 0));
1030
	}
1031
1032
	/**
1033
	 * Check file exists.
1034
	 *
1035
	 * @param string $filename Target file name
1036
	 * @return bool Returns FALSE if the file does not exists, or Returns full path file(string).
1037
	 */
1038
	function exists($filename)
1039
	{
1040
		$filename = self::getRealPath($filename);
1041
		return file_exists($filename) ? $filename : FALSE;
1042
	}
1043
1044
	/**
1045
	 * Check it is dir
1046
	 *
1047
	 * @param string $dir Target dir path
0 ignored issues
show
Bug introduced by
There is no parameter named $dir. Was it maybe removed?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function.

Consider the following example. The parameter $italy is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $island
 * @param array $italy
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was removed, but the annotation was not.

Loading history...
1048
	 * @return bool Returns FALSE if the dir is not dir, or Returns full path of dir(string).
1049
	 */
1050
	function isDir($path)
1051
	{
1052
		$path = self::getRealPath($path);
1053
		return is_dir($path) ? $path : FALSE;
1054
	}
1055
1056
	/**
1057
	 * Check is writable dir
1058
	 *
1059
	 * @param string $path Target dir path
1060
	 * @return bool
1061
	 */
1062
	function isWritableDir($path)
1063
	{
1064
		$path = self::getRealPath($path);
1065
		if(is_dir($path)==FALSE)
0 ignored issues
show
Coding Style Best Practice introduced by
It seems like you are loosely comparing two booleans. Considering using the strict comparison === instead.

When comparing two booleans, it is generally considered safer to use the strict comparison operator.

Loading history...
1066
		{
1067
			return FALSE;
1068
		}
1069
1070
		$checkFile = $path . '/_CheckWritableDir';
1071
1072
		$fp = fopen($checkFile, 'w');
1073
		if(!is_resource($fp))
1074
		{
1075
			return FALSE;
1076
		}
1077
		fclose($fp);
1078
1079
		self::removeFile($checkFile);
1080
		return TRUE;
1081
	}
1082
}
1083
1084
/* End of file FileHandler.class.php */
1085
/* Location: ./classes/file/FileHandler.class.php */
1086