Passed
Branch master (038e9c)
by Michael
12:17 queued 06:21
created

phpthumb::applyPathSegment()   D

Complexity

Conditions 10
Paths 10

Size

Total Lines 35
Code Lines 29

Duplication

Lines 20
Ratio 57.14 %

Importance

Changes 0
Metric Value
cc 10
eloc 29
nc 10
nop 2
dl 20
loc 35
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
0 ignored issues
show
Coding Style Compatibility introduced by
For compatibility and reusability of your code, PSR1 recommends that a file should introduce either new symbols (like classes, functions, etc.) or have side-effects (like outputting something, or including other files), but not both at the same time. The first symbol is defined on line 19 and the first side effect is on line 12.

The PSR-1: Basic Coding Standard recommends that a file should either introduce new symbols, that is classes, functions, constants or similar, or have side effects. Side effects are anything that executes logic, like for example printing output, changing ini settings or writing to a file.

The idea behind this recommendation is that merely auto-loading a class should not change the state of an application. It also promotes a cleaner style of programming and makes your code less prone to errors, because the logic is not spread out all over the place.

To learn more about the PSR-1, please see the PHP-FIG site on the PSR-1.

Loading history...
2
//////////////////////////////////////////////////////////////
3
//   phpThumb() by James Heinrich <[email protected]>   //
4
//        available at http://phpthumb.sourceforge.net      //
5
//         and/or https://github.com/JamesHeinrich/phpThumb //
6
//////////////////////////////////////////////////////////////
7
///                                                         //
8
// See: phpthumb.readme.txt for usage instructions          //
9
//                                                         ///
10
//////////////////////////////////////////////////////////////
11
12
ob_start();
13 View Code Duplication
if (!include_once(dirname(__FILE__).'/phpthumb.functions.php')) {
14
	ob_end_flush();
15
	die('failed to include_once("'.dirname(__FILE__).'/phpthumb.functions.php")');
16
}
17
ob_end_clean();
18
19
class phpthumb {
20
21
	// public:
22
	// START PARAMETERS (for object mode and phpThumb.php)
23
	// See phpthumb.readme.txt for descriptions of what each of these values are
24
	var $src  = null;     // SouRCe filename
25
	var $new  = null;     // NEW image (phpThumb.php only)
26
	var $w    = null;     // Width
27
	var $h    = null;     // Height
28
	var $wp   = null;     // Width  (Portrait Images Only)
29
	var $hp   = null;     // Height (Portrait Images Only)
30
	var $wl   = null;     // Width  (Landscape Images Only)
31
	var $hl   = null;     // Height (Landscape Images Only)
32
	var $ws   = null;     // Width  (Square Images Only)
33
	var $hs   = null;     // Height (Square Images Only)
34
	var $f    = null;     // output image Format
35
	var $q    = 75;       // jpeg output Quality
36
	var $sx   = null;     // Source crop top-left X position
37
	var $sy   = null;     // Source crop top-left Y position
38
	var $sw   = null;     // Source crop Width
39
	var $sh   = null;     // Source crop Height
40
	var $zc   = null;     // Zoom Crop
41
	var $bc   = null;     // Border Color
42
	var $bg   = null;     // BackGround color
43
	var $fltr = array();  // FiLTeRs
44
	var $goto = null;     // GO TO url after processing
45
	var $err  = null;     // default ERRor image filename
46
	var $xto  = null;     // extract eXif Thumbnail Only
47
	var $ra   = null;     // Rotate by Angle
48
	var $ar   = null;     // Auto Rotate
49
	var $aoe  = null;     // Allow Output Enlargement
50
	var $far  = null;     // Fixed Aspect Ratio
51
	var $iar  = null;     // Ignore Aspect Ratio
52
	var $maxb = null;     // MAXimum Bytes
53
	var $down = null;     // DOWNload thumbnail filename
54
	var $md5s = null;     // MD5 hash of Source image
55
	var $sfn  = 0;        // Source Frame Number
56
	var $dpi  = 150;      // Dots Per Inch for vector source formats
57
	var $sia  = null;     // Save Image As filename
58
59
	var $file = null;     // >>>deprecated, DO NOT USE, will be removed in future versions<<<
60
61
	var $phpThumbDebug = null;
62
	// END PARAMETERS
63
64
65
	// public:
66
	// START CONFIGURATION OPTIONS (for object mode only)
67
	// See phpThumb.config.php for descriptions of what each of these settings do
68
69
	// * Directory Configuration
70
	var $config_cache_directory                      = null;
71
	var $config_cache_directory_depth                = 0;
72
	var $config_cache_disable_warning                = true;
73
	var $config_cache_source_enabled                 = false;
74
	var $config_cache_source_directory               = null;
75
	var $config_temp_directory                       = null;
76
	var $config_document_root                        = null;
77
78
	// * Default output configuration:
79
	var $config_output_format                        = 'jpeg';
80
	var $config_output_maxwidth                      = 0;
81
	var $config_output_maxheight                     = 0;
82
	var $config_output_interlace                     = true;
83
84
	// * Error message configuration
85
	var $config_error_image_width                    = 400;
86
	var $config_error_image_height                   = 100;
87
	var $config_error_message_image_default          = '';
88
	var $config_error_bgcolor                        = 'CCCCFF';
89
	var $config_error_textcolor                      = 'FF0000';
90
	var $config_error_fontsize                       = 1;
91
	var $config_error_die_on_error                   = false;
92
	var $config_error_silent_die_on_error            = false;
93
	var $config_error_die_on_source_failure          = true;
94
95
	// * Anti-Hotlink Configuration:
96
	var $config_nohotlink_enabled                    = true;
97
	var $config_nohotlink_valid_domains              = array();
98
	var $config_nohotlink_erase_image                = true;
99
	var $config_nohotlink_text_message               = 'Off-server thumbnailing is not allowed';
100
	// * Off-server Linking Configuration:
101
	var $config_nooffsitelink_enabled                = false;
102
	var $config_nooffsitelink_valid_domains          = array();
103
	var $config_nooffsitelink_require_refer          = false;
104
	var $config_nooffsitelink_erase_image            = true;
105
	var $config_nooffsitelink_watermark_src          = '';
106
	var $config_nooffsitelink_text_message           = 'Off-server linking is not allowed';
107
108
	// * Border & Background default colors
109
	var $config_border_hexcolor                      = '000000';
110
	var $config_background_hexcolor                  = 'FFFFFF';
111
112
	// * TrueType Fonts
113
	var $config_ttf_directory                        = './fonts';
114
115
	var $config_max_source_pixels                    = null;
116
	var $config_use_exif_thumbnail_for_speed         = false;
117
	var $allow_local_http_src                        = false;
118
119
	var $config_imagemagick_path                     = null;
120
	var $config_prefer_imagemagick                   = true;
121
	var $config_imagemagick_use_thumbnail            = true;
122
123
	var $config_cache_maxage                         = null;
124
	var $config_cache_maxsize                        = null;
125
	var $config_cache_maxfiles                       = null;
126
	var $config_cache_source_filemtime_ignore_local  = false;
127
	var $config_cache_source_filemtime_ignore_remote = true;
128
	var $config_cache_default_only_suffix            = false;
129
	var $config_cache_force_passthru                 = true;
130
	var $config_cache_prefix                         = '';    // default value set in the constructor below
131
132
	// * MySQL
133
	var $config_mysql_extension                      = null;
134
	var $config_mysql_query                          = null;
135
	var $config_mysql_hostname                       = null;
136
	var $config_mysql_username                       = null;
137
	var $config_mysql_password                       = null;
138
	var $config_mysql_database                       = null;
139
140
	// * Security
141
	var $config_high_security_enabled                = true;
142
	var $config_high_security_password               = null;
143
	var $config_high_security_url_separator          = '&';
144
	var $config_disable_debug                        = true;
145
	var $config_allow_src_above_docroot              = false;
146
	var $config_allow_src_above_phpthumb             = true;
147
	var $config_auto_allow_symlinks                  = true;    // allow symlink target directories without explicitly whitelisting them
148
	var $config_additional_allowed_dirs              = array(); // additional directories to allow source images to be read from
149
	var $config_file_create_mask                     = 0755;
150
	var $config_dir_create_mask                      = 0755;
151
152
	// * HTTP fopen
153
	var $config_http_fopen_timeout                   = 10;
154
	var $config_http_follow_redirect                 = true;
155
156
	// * Compatability
157
	var $config_disable_pathinfo_parsing             = false;
158
	var $config_disable_imagecopyresampled           = false;
159
	var $config_disable_onlycreateable_passthru      = false;
160
	var $config_disable_realpath                     = false;
161
162
	var $config_http_user_agent                      = 'Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7.12) Gecko/20050915 Firefox/1.0.7';
163
164
	// END CONFIGURATION OPTIONS
165
166
167
	// public: error messages (read-only; persistant)
168
	var $debugmessages = array();
169
	var $debugtiming   = array();
170
	var $fatalerror    = null;
171
172
173
	// private: (should not be modified directly)
174
	var $thumbnailQuality = 75;
175
	var $thumbnailFormat  = null;
176
177
	var $sourceFilename   = null;
178
	var $rawImageData     = null;
179
	var $IMresizedData    = null;
180
	var $outputImageData  = null;
181
182
	var $useRawIMoutput   = false;
183
184
	var $gdimg_output     = null;
185
	var $gdimg_source     = null;
186
187
	var $getimagesizeinfo = null;
188
189
	var $source_width  = null;
190
	var $source_height = null;
191
192
	var $thumbnailCropX = null;
193
	var $thumbnailCropY = null;
194
	var $thumbnailCropW = null;
195
	var $thumbnailCropH = null;
196
197
	var $exif_thumbnail_width  = null;
198
	var $exif_thumbnail_height = null;
199
	var $exif_thumbnail_type   = null;
200
	var $exif_thumbnail_data   = null;
201
	var $exif_raw_data         = null;
202
203
	var $thumbnail_width        = null;
204
	var $thumbnail_height       = null;
205
	var $thumbnail_image_width  = null;
206
	var $thumbnail_image_height = null;
207
208
	var $tempFilesToDelete = array();
209
	var $cache_filename    = null;
210
211
	var $AlphaCapableFormats = array('png', 'ico', 'gif');
212
	var $is_alpha = false;
213
214
	var $iswindows        = null;
215
	var $issafemode       = null;
216
	var $php_memory_limit = null;
217
218
	var $phpthumb_version = '1.7.14-201608101311';
219
220
	//////////////////////////////////////////////////////////////////////
221
222
	// public: constructor
223
	function __construct() {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
224
		$this->phpThumb();
225
	}
226
227
	function phpThumb() {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
228
		$this->DebugTimingMessage('phpThumb() constructor', __FILE__, __LINE__);
229
		$this->DebugMessage('phpThumb() v'.$this->phpthumb_version, __FILE__, __LINE__);
230
231
		foreach (array(ini_get('memory_limit'), get_cfg_var('memory_limit')) as $php_config_memory_limit) {
232
			if (strlen($php_config_memory_limit)) {
233
				if (substr($php_config_memory_limit, -1, 1) == 'G') { // PHP memory limit expressed in Gigabytes
234
					$php_config_memory_limit = intval(substr($php_config_memory_limit, 0, -1)) * 1073741824;
235
				} elseif (substr($php_config_memory_limit, -1, 1) == 'M') { // PHP memory limit expressed in Megabytes
236
					$php_config_memory_limit = intval(substr($php_config_memory_limit, 0, -1)) * 1048576;
237
				}
238
				$this->php_memory_limit = max($this->php_memory_limit, $php_config_memory_limit);
239
			}
240
		}
241
		if ($this->php_memory_limit > 0) { // could be "-1" for "no limit"
242
			$this->config_max_source_pixels = round($this->php_memory_limit * 0.20); // 20% of memory_limit
243
		}
244
245
		$this->iswindows  = (bool) (strtoupper(substr(PHP_OS, 0, 3)) == 'WIN');
246
		$this->issafemode = (bool) preg_match('#(1|ON)#i', ini_get('safe_mode'));
247
		$this->config_document_root = (!empty($_SERVER['DOCUMENT_ROOT']) ? $_SERVER['DOCUMENT_ROOT']   : $this->config_document_root);
248
		$this->config_cache_prefix  = ( isset($_SERVER['SERVER_NAME'])   ? $_SERVER['SERVER_NAME'].'_' : '');
249
250
		$this->purgeTempFiles(); // purge existing temp files if re-initializing object
251
252
		$php_sapi_name = strtolower(function_exists('php_sapi_name') ? php_sapi_name() : '');
253
		if ($php_sapi_name == 'cli') {
254
			$this->config_allow_src_above_docroot = true;
255
		}
256
257
		if (!$this->config_disable_debug) {
258
			// if debug mode is enabled, force phpThumbDebug output, do not allow normal thumbnails to be generated
259
			$this->phpThumbDebug = (is_null($this->phpThumbDebug) ? 9 : max(1, intval($this->phpThumbDebug)));
260
		}
261
	}
262
263
	function __destruct() {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
264
		$this->purgeTempFiles();
265
	}
266
267
	// public:
268
	function purgeTempFiles() {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
269
		foreach ($this->tempFilesToDelete as $tempFileToDelete) {
270
			if (file_exists($tempFileToDelete)) {
271
				$this->DebugMessage('Deleting temp file "'.$tempFileToDelete.'"', __FILE__, __LINE__);
272
				@unlink($tempFileToDelete);
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition for unlink(). This can introduce security issues, and is generally not recommended. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unhandled  annotation

272
				/** @scrutinizer ignore-unhandled */ @unlink($tempFileToDelete);

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...
273
			}
274
		}
275
		$this->tempFilesToDelete = array();
276
		return true;
277
	}
278
279
	// public:
280
	function setSourceFilename($sourceFilename) {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
281
		//$this->resetObject();
282
		//$this->rawImageData   = null;
283
		$this->sourceFilename = $sourceFilename;
284
		$this->src            = $sourceFilename;
285
		if (is_null($this->config_output_format)) {
286
			$sourceFileExtension = strtolower(substr(strrchr($sourceFilename, '.'), 1));
287
			if (preg_match('#^[a-z]{3,4}$#', $sourceFileExtension)) {
288
				$this->config_output_format = $sourceFileExtension;
289
				$this->DebugMessage('setSourceFilename('.$sourceFilename.') set $this->config_output_format to "'.$sourceFileExtension.'"', __FILE__, __LINE__);
290
			} else {
291
				$this->DebugMessage('setSourceFilename('.$sourceFilename.') did NOT set $this->config_output_format to "'.$sourceFileExtension.'" because it did not seem like an appropriate image format', __FILE__, __LINE__);
292
			}
293
		}
294
		$this->DebugMessage('setSourceFilename('.$sourceFilename.') set $this->sourceFilename to "'.$this->sourceFilename.'"', __FILE__, __LINE__);
295
		return true;
296
	}
297
298
	// public:
299
	function setSourceData($rawImageData, $sourceFilename='') {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
300
		//$this->resetObject();
301
		//$this->sourceFilename = null;
302
		$this->rawImageData   = $rawImageData;
303
		$this->DebugMessage('setSourceData() setting $this->rawImageData ('.strlen($this->rawImageData).' bytes; magic="'.substr($this->rawImageData, 0, 4).'" ('.phpthumb_functions::HexCharDisplay(substr($this->rawImageData, 0, 4)).'))', __FILE__, __LINE__);
304
		if ($this->config_cache_source_enabled) {
305
			$sourceFilename = ($sourceFilename ? $sourceFilename : md5($rawImageData));
306
			if (!is_dir($this->config_cache_source_directory)) {
307
				$this->ErrorImage('$this->config_cache_source_directory ('.$this->config_cache_source_directory.') is not a directory');
308
			} elseif (!@is_writable($this->config_cache_source_directory)) {
309
				$this->ErrorImage('$this->config_cache_source_directory ('.$this->config_cache_source_directory.') is not writable');
310
			}
311
			$this->DebugMessage('setSourceData() attempting to save source image to "'.$this->config_cache_source_directory.DIRECTORY_SEPARATOR.urlencode($sourceFilename).'"', __FILE__, __LINE__);
312
			if ($fp = @fopen($this->config_cache_source_directory.DIRECTORY_SEPARATOR.urlencode($sourceFilename), 'wb')) {
313
				fwrite($fp, $rawImageData);
314
				fclose($fp);
315
			} elseif (!$this->phpThumbDebug) {
316
				$this->ErrorImage('setSourceData() failed to write to source cache ('.$this->config_cache_source_directory.DIRECTORY_SEPARATOR.urlencode($sourceFilename).')');
317
			}
318
		}
319
		return true;
320
	}
321
322
	// public:
323
	function setSourceImageResource($gdimg) {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
324
		//$this->resetObject();
325
		$this->gdimg_source = $gdimg;
326
		return true;
327
	}
328
329
	// public:
330
	function setParameter($param, $value) {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
331
		if ($param == 'src') {
332
			$this->setSourceFilename($this->ResolveFilenameToAbsolute($value));
333
		} elseif (@is_array($this->$param)) {
334
			if (is_array($value)) {
335
				foreach ($value as $arraykey => $arrayvalue) {
336
					array_push($this->$param, $arrayvalue);
337
				}
338
			} else {
339
				array_push($this->$param, $value);
340
			}
341
		} else {
342
			$this->$param = $value;
343
		}
344
		return true;
345
	}
346
347
	// public:
348
	function getParameter($param) {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
349
		//if (property_exists('phpThumb', $param)) {
350
			return $this->$param;
351
		//}
352
		//$this->DebugMessage('setParameter() attempting to get non-existant parameter "'.$param.'"', __FILE__, __LINE__);
353
		//return false;
354
	}
355
356
357
	// public:
358
	function GenerateThumbnail() {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
359
360
		$this->setOutputFormat();
361
			$this->phpThumbDebug('8a');
362
		$this->ResolveSource();
363
			$this->phpThumbDebug('8b');
364
		$this->SetCacheFilename();
365
			$this->phpThumbDebug('8c');
366
		$this->ExtractEXIFgetImageSize();
367
			$this->phpThumbDebug('8d');
368
		if ($this->useRawIMoutput) {
369
			$this->DebugMessage('Skipping rest of GenerateThumbnail() because ($this->useRawIMoutput == true)', __FILE__, __LINE__);
370
			return true;
371
		}
372
			$this->phpThumbDebug('8e');
373
		if (!$this->SourceImageToGD()) {
374
			$this->DebugMessage('SourceImageToGD() failed', __FILE__, __LINE__);
375
			return false;
376
		}
377
			$this->phpThumbDebug('8f');
378
		$this->Rotate();
379
			$this->phpThumbDebug('8g');
380
		$this->CreateGDoutput();
381
			$this->phpThumbDebug('8h');
382
383
		// default values, also applicable for far="C"
384
		$destination_offset_x = round(($this->thumbnail_width  - $this->thumbnail_image_width)  / 2);
385
		$destination_offset_y = round(($this->thumbnail_height - $this->thumbnail_image_height) / 2);
386
		if (($this->far == 'L') || ($this->far == 'TL') || ($this->far == 'BL')) {
387
			$destination_offset_x = 0;
388
		}
389
		if (($this->far == 'R') || ($this->far == 'TR') || ($this->far == 'BR')) {
390
			$destination_offset_x =  round($this->thumbnail_width  - $this->thumbnail_image_width);
391
		}
392
		if (($this->far == 'T') || ($this->far == 'TL') || ($this->far == 'TR')) {
393
			$destination_offset_y = 0;
394
		}
395
		if (($this->far == 'B') || ($this->far == 'BL') || ($this->far == 'BR')) {
396
			$destination_offset_y =  round($this->thumbnail_height - $this->thumbnail_image_height);
397
		}
398
399
//		// copy/resize image to appropriate dimensions
400
//		$borderThickness = 0;
401
//		if (!empty($this->fltr)) {
402
//			foreach ($this->fltr as $key => $value) {
403
//				if (preg_match('#^bord\|([0-9]+)#', $value, $matches)) {
404
//					$borderThickness = $matches[1];
405
//					break;
406
//				}
407
//			}
408
//		}
409
//		if ($borderThickness > 0) {
410
//			//$this->DebugMessage('Skipping ImageResizeFunction() because BorderThickness="'.$borderThickness.'"', __FILE__, __LINE__);
411
//			$this->thumbnail_image_height /= 2;
412
//		}
413
		$this->ImageResizeFunction(
414
			$this->gdimg_output,
415
			$this->gdimg_source,
416
			$destination_offset_x,
417
			$destination_offset_y,
418
			$this->thumbnailCropX,
419
			$this->thumbnailCropY,
420
			$this->thumbnail_image_width,
421
			$this->thumbnail_image_height,
422
			$this->thumbnailCropW,
423
			$this->thumbnailCropH
424
		);
425
426
		$this->DebugMessage('memory_get_usage() after copy-resize = '.(function_exists('memory_get_usage') ? @memory_get_usage() : 'n/a'), __FILE__, __LINE__);
427
		imagedestroy($this->gdimg_source);
0 ignored issues
show
Bug introduced by
It seems like $this->gdimg_source can also be of type false; however, parameter $image of imagedestroy() does only seem to accept resource, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

427
		imagedestroy(/** @scrutinizer ignore-type */ $this->gdimg_source);
Loading history...
428
		$this->DebugMessage('memory_get_usage() after imagedestroy = '.(function_exists('memory_get_usage') ? @memory_get_usage() : 'n/a'), __FILE__, __LINE__);
429
430
			$this->phpThumbDebug('8i');
431
		$this->AntiOffsiteLinking();
432
			$this->phpThumbDebug('8j');
433
		$this->ApplyFilters();
434
			$this->phpThumbDebug('8k');
435
		$this->AlphaChannelFlatten();
436
			$this->phpThumbDebug('8l');
437
		$this->MaxFileSize();
438
			$this->phpThumbDebug('8m');
439
440
		$this->DebugMessage('GenerateThumbnail() completed successfully', __FILE__, __LINE__);
441
		return true;
442
	}
443
444
445
	// public:
446
	function RenderOutput() {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
447 View Code Duplication
		if (!$this->useRawIMoutput && !is_resource($this->gdimg_output)) {
448
			$this->DebugMessage('RenderOutput() failed because !is_resource($this->gdimg_output)', __FILE__, __LINE__);
449
			return false;
450
		}
451
		if (!$this->thumbnailFormat) {
452
			$this->DebugMessage('RenderOutput() failed because $this->thumbnailFormat is empty', __FILE__, __LINE__);
453
			return false;
454
		}
455
		if ($this->useRawIMoutput) {
456
			$this->DebugMessage('RenderOutput copying $this->IMresizedData ('.strlen($this->IMresizedData).' bytes) to $this->outputImage', __FILE__, __LINE__);
457
			$this->outputImageData = $this->IMresizedData;
458
			return true;
459
		}
460
461
		$builtin_formats = array();
462
		if (function_exists('imagetypes')) {
463
			$imagetypes = imagetypes();
464
			$builtin_formats['wbmp'] = (bool) ($imagetypes & IMG_WBMP);
465
			$builtin_formats['jpg']  = (bool) ($imagetypes & IMG_JPG);
466
			$builtin_formats['gif']  = (bool) ($imagetypes & IMG_GIF);
467
			$builtin_formats['png']  = (bool) ($imagetypes & IMG_PNG);
468
		}
469
470
		$this->DebugMessage('imageinterlace($this->gdimg_output, '.intval($this->config_output_interlace).')', __FILE__, __LINE__);
471
		imageinterlace($this->gdimg_output, intval($this->config_output_interlace));
472
473
		$this->DebugMessage('RenderOutput() attempting image'.strtolower(@$this->thumbnailFormat).'($this->gdimg_output)', __FILE__, __LINE__);
474
		ob_start();
475
		switch ($this->thumbnailFormat) {
476 View Code Duplication
			case 'wbmp':
477
				if (empty($builtin_formats['wbmp'])) {
478
					$this->DebugMessage('GD does not have required built-in support for WBMP output', __FILE__, __LINE__);
479
					ob_end_clean();
480
					return false;
481
				}
482
				imagejpeg($this->gdimg_output, null, $this->thumbnailQuality);
483
				$this->outputImageData = ob_get_contents();
484
				break;
485
486
			case 'jpeg':
487 View Code Duplication
			case 'jpg':  // should be "jpeg" not "jpg" but just in case...
488
				if (empty($builtin_formats['jpg'])) {
489
					$this->DebugMessage('GD does not have required built-in support for JPEG output', __FILE__, __LINE__);
490
					ob_end_clean();
491
					return false;
492
				}
493
				imagejpeg($this->gdimg_output, null, $this->thumbnailQuality);
494
				$this->outputImageData = ob_get_contents();
495
				break;
496
497
			case 'png':
498
				if (empty($builtin_formats['png'])) {
499
					$this->DebugMessage('GD does not have required built-in support for PNG output', __FILE__, __LINE__);
500
					ob_end_clean();
501
					return false;
502
				}
503
				if (phpthumb_functions::version_compare_replacement(phpversion(), '5.1.2', '>=')) {
504
					// https://github.com/JamesHeinrich/phpThumb/issues/24
505
506
					/* http://php.net/manual/en/function.imagepng.php:
507
					from php source (gd.h):
508
					2.0.12: Compression level: 0-9 or -1, where 0 is NO COMPRESSION at all,
509
					:: 1 is FASTEST but produces larger files, 9 provides the best
510
					:: compression (smallest files) but takes a long time to compress, and
511
					:: -1 selects the default compiled into the zlib library.
512
					Conclusion: Based on the Zlib manual (http://www.zlib.net/manual.html) the default compression level is set to 6.
513
					*/
514
					if (($this->thumbnailQuality >= -1) && ($this->thumbnailQuality <= 9)) {
515
						$PNGquality = $this->thumbnailQuality;
516
					} else {
517
						$this->DebugMessage('Specified thumbnailQuality "'.$this->thumbnailQuality.'" is outside the accepted range (0-9, or -1). Using 6 as default value.', __FILE__, __LINE__);
518
						$PNGquality = 6;
519
					}
520
					imagepng($this->gdimg_output, null, $PNGquality);
521
				} else {
522
					imagepng($this->gdimg_output);
523
				}
524
				$this->outputImageData = ob_get_contents();
525
				break;
526
527
			case 'gif':
528
				if (empty($builtin_formats['gif'])) {
529
					$this->DebugMessage('GD does not have required built-in support for GIF output', __FILE__, __LINE__);
530
					ob_end_clean();
531
					return false;
532
				}
533
				imagegif($this->gdimg_output);
534
				$this->outputImageData = ob_get_contents();
535
				break;
536
537 View Code Duplication
			case 'bmp':
538
				if (!@include_once(dirname(__FILE__).'/phpthumb.bmp.php')) {
539
					$this->DebugMessage('Error including "'.dirname(__FILE__).'/phpthumb.bmp.php" which is required for BMP format output', __FILE__, __LINE__);
540
					ob_end_clean();
541
					return false;
542
				}
543
				$phpthumb_bmp = new phpthumb_bmp();
544
				$this->outputImageData = $phpthumb_bmp->GD2BMPstring($this->gdimg_output);
545
				unset($phpthumb_bmp);
546
				break;
547
548 View Code Duplication
			case 'ico':
549
				if (!@include_once(dirname(__FILE__).'/phpthumb.ico.php')) {
550
					$this->DebugMessage('Error including "'.dirname(__FILE__).'/phpthumb.ico.php" which is required for ICO format output', __FILE__, __LINE__);
551
					ob_end_clean();
552
					return false;
553
				}
554
				$phpthumb_ico = new phpthumb_ico();
555
				$arrayOfOutputImages = array($this->gdimg_output);
556
				$this->outputImageData = $phpthumb_ico->GD2ICOstring($arrayOfOutputImages);
557
				unset($phpthumb_ico);
558
				break;
559
560 View Code Duplication
			default:
561
				$this->DebugMessage('RenderOutput failed because $this->thumbnailFormat "'.$this->thumbnailFormat.'" is not valid', __FILE__, __LINE__);
562
				ob_end_clean();
563
				return false;
564
		}
565
		ob_end_clean();
566
		if (!$this->outputImageData) {
567
			$this->DebugMessage('RenderOutput() for "'.$this->thumbnailFormat.'" failed', __FILE__, __LINE__);
568
			ob_end_clean();
569
			return false;
570
		}
571
		$this->DebugMessage('RenderOutput() completing with $this->outputImageData = '.strlen($this->outputImageData).' bytes', __FILE__, __LINE__);
572
		return true;
573
	}
574
575
576
	// public:
577
	function RenderToFile($filename) {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
578
		if (preg_match('#^[a-z0-9]+://#i', $filename)) {
579
			$this->DebugMessage('RenderToFile() failed because $filename ('.$filename.') is a URL', __FILE__, __LINE__);
580
			return false;
581
		}
582
		// render thumbnail to this file only, do not cache, do not output to browser
583
		//$renderfilename = $this->ResolveFilenameToAbsolute(dirname($filename)).DIRECTORY_SEPARATOR.basename($filename);
584
		$renderfilename = $filename;
585
		if (($filename{0} != '/') && ($filename{0} != '\\') && ($filename{1} != ':')) {
586
			$renderfilename = $this->ResolveFilenameToAbsolute($renderfilename);
587
		}
588 View Code Duplication
		if (!@is_writable(dirname($renderfilename))) {
0 ignored issues
show
Bug introduced by
It seems like $renderfilename can also be of type false; however, parameter $path of dirname() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

588
		if (!@is_writable(dirname(/** @scrutinizer ignore-type */ $renderfilename))) {
Loading history...
589
			$this->DebugMessage('RenderToFile() failed because "'.dirname($renderfilename).'/" is not writable', __FILE__, __LINE__);
590
			return false;
591
		}
592 View Code Duplication
		if (@is_file($renderfilename) && !@is_writable($renderfilename)) {
0 ignored issues
show
Bug introduced by
It seems like $renderfilename can also be of type false; however, parameter $filename of is_writable() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

592
		if (@is_file($renderfilename) && !@is_writable(/** @scrutinizer ignore-type */ $renderfilename)) {
Loading history...
Bug introduced by
It seems like $renderfilename can also be of type false; however, parameter $filename of is_file() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

592
		if (@is_file(/** @scrutinizer ignore-type */ $renderfilename) && !@is_writable($renderfilename)) {
Loading history...
593
			$this->DebugMessage('RenderToFile() failed because "'.$renderfilename.'" is not writable', __FILE__, __LINE__);
594
			return false;
595
		}
596
597
		if ($this->RenderOutput()) {
598
			if (file_put_contents($renderfilename, $this->outputImageData)) {
0 ignored issues
show
Bug introduced by
It seems like $renderfilename can also be of type false; however, parameter $filename of file_put_contents() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

598
			if (file_put_contents(/** @scrutinizer ignore-type */ $renderfilename, $this->outputImageData)) {
Loading history...
599
				@chmod($renderfilename, $this->getParameter('config_file_create_mask'));
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition for chmod(). This can introduce security issues, and is generally not recommended. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unhandled  annotation

599
				/** @scrutinizer ignore-unhandled */ @chmod($renderfilename, $this->getParameter('config_file_create_mask'));

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...
Bug introduced by
It seems like $renderfilename can also be of type false; however, parameter $filename of chmod() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

599
				@chmod(/** @scrutinizer ignore-type */ $renderfilename, $this->getParameter('config_file_create_mask'));
Loading history...
600
				$this->DebugMessage('RenderToFile('.$renderfilename.') succeeded', __FILE__, __LINE__);
601
				return true;
602
			}
603
			if (!@file_exists($renderfilename)) {
0 ignored issues
show
Bug introduced by
It seems like $renderfilename can also be of type false; however, parameter $filename of file_exists() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

603
			if (!@file_exists(/** @scrutinizer ignore-type */ $renderfilename)) {
Loading history...
604
				$this->DebugMessage('RenderOutput ['.$this->thumbnailFormat.'('.$renderfilename.')] did not appear to fail, but the output image does not exist either...', __FILE__, __LINE__);
605
			}
606
		} else {
607
			$this->DebugMessage('RenderOutput ['.$this->thumbnailFormat.'('.$renderfilename.')] failed', __FILE__, __LINE__);
608
		}
609
		return false;
610
	}
611
612
613
	// public:
614
	function OutputThumbnail() {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
615
		$this->purgeTempFiles();
616
617 View Code Duplication
		if (!$this->useRawIMoutput && !is_resource($this->gdimg_output)) {
618
			$this->DebugMessage('OutputThumbnail() failed because !is_resource($this->gdimg_output)', __FILE__, __LINE__);
619
			return false;
620
		}
621
		if (headers_sent()) {
622
			return $this->ErrorImage('OutputThumbnail() failed - headers already sent');
623
		}
624
625
		$downloadfilename = phpthumb_functions::SanitizeFilename(is_string($this->sia) ? $this->sia : ($this->down ? $this->down : 'phpThumb_generated_thumbnail'.'.'.$this->thumbnailFormat));
626
		$this->DebugMessage('Content-Disposition header filename set to "'.$downloadfilename.'"', __FILE__, __LINE__);
627
		if ($downloadfilename) {
628
			header('Content-Disposition: '.($this->down ? 'attachment' : 'inline').'; filename="'.$downloadfilename.'"');
629
		} else {
630
			$this->DebugMessage('failed to send Content-Disposition header because $downloadfilename is empty', __FILE__, __LINE__);
631
		}
632
633
		if ($this->useRawIMoutput) {
634
635
			header('Content-Type: '.phpthumb_functions::ImageTypeToMIMEtype($this->thumbnailFormat));
0 ignored issues
show
Bug introduced by
Are you sure phpthumb_functions::Imag...$this->thumbnailFormat) of type mixed|false|string can be used in concatenation? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

635
			header('Content-Type: './** @scrutinizer ignore-type */ phpthumb_functions::ImageTypeToMIMEtype($this->thumbnailFormat));
Loading history...
636
			echo $this->IMresizedData;
637
638
		} else {
639
640
			$this->DebugMessage('imageinterlace($this->gdimg_output, '.intval($this->config_output_interlace).')', __FILE__, __LINE__);
641
			imageinterlace($this->gdimg_output, intval($this->config_output_interlace));
642
			switch ($this->thumbnailFormat) {
643 View Code Duplication
				case 'jpeg':
644
					header('Content-Type: '.phpthumb_functions::ImageTypeToMIMEtype($this->thumbnailFormat));
645
					$ImageOutFunction = 'image'.$this->thumbnailFormat;
646
					@$ImageOutFunction($this->gdimg_output, null, $this->thumbnailQuality);
647
					break;
648
649
				case 'png':
650 View Code Duplication
				case 'gif':
651
					header('Content-Type: '.phpthumb_functions::ImageTypeToMIMEtype($this->thumbnailFormat));
652
					$ImageOutFunction = 'image'.$this->thumbnailFormat;
653
					@$ImageOutFunction($this->gdimg_output);
654
					break;
655
656 View Code Duplication
				case 'bmp':
657
					if (!@include_once(dirname(__FILE__).'/phpthumb.bmp.php')) {
658
						$this->DebugMessage('Error including "'.dirname(__FILE__).'/phpthumb.bmp.php" which is required for BMP format output', __FILE__, __LINE__);
659
						return false;
660
					}
661
					$phpthumb_bmp = new phpthumb_bmp();
662
					if (is_object($phpthumb_bmp)) {
663
						$bmp_data = $phpthumb_bmp->GD2BMPstring($this->gdimg_output);
664
						unset($phpthumb_bmp);
665
						if (!$bmp_data) {
666
							$this->DebugMessage('$phpthumb_bmp->GD2BMPstring() failed', __FILE__, __LINE__);
667
							return false;
668
						}
669
						header('Content-Type: '.phpthumb_functions::ImageTypeToMIMEtype($this->thumbnailFormat));
670
						echo $bmp_data;
671
					} else {
672
						$this->DebugMessage('new phpthumb_bmp() failed', __FILE__, __LINE__);
673
						return false;
674
					}
675
					break;
676
677 View Code Duplication
				case 'ico':
678
					if (!@include_once(dirname(__FILE__).'/phpthumb.ico.php')) {
679
						$this->DebugMessage('Error including "'.dirname(__FILE__).'/phpthumb.ico.php" which is required for ICO format output', __FILE__, __LINE__);
680
						return false;
681
					}
682
					$phpthumb_ico = new phpthumb_ico();
683
					if (is_object($phpthumb_ico)) {
684
						$arrayOfOutputImages = array($this->gdimg_output);
685
						$ico_data = $phpthumb_ico->GD2ICOstring($arrayOfOutputImages);
686
						unset($phpthumb_ico);
687
						if (!$ico_data) {
688
							$this->DebugMessage('$phpthumb_ico->GD2ICOstring() failed', __FILE__, __LINE__);
689
							return false;
690
						}
691
						header('Content-Type: '.phpthumb_functions::ImageTypeToMIMEtype($this->thumbnailFormat));
692
						echo $ico_data;
693
					} else {
694
						$this->DebugMessage('new phpthumb_ico() failed', __FILE__, __LINE__);
695
						return false;
696
					}
697
					break;
698
699
				default:
700
					$this->DebugMessage('OutputThumbnail failed because $this->thumbnailFormat "'.$this->thumbnailFormat.'" is not valid', __FILE__, __LINE__);
701
					return false;
702
					break;
0 ignored issues
show
Unused Code introduced by
break is not strictly necessary here and could be removed.

The break statement is not necessary if it is preceded for example by a return statement:

switch ($x) {
    case 1:
        return 'foo';
        break; // This break is not necessary and can be left off.
}

If you would like to keep this construct to be consistent with other case statements, you can safely mark this issue as a false-positive.

Loading history...
703
			}
704
705
		}
706
		return true;
707
	}
708
709
710
	// public:
711
	function CleanUpCacheDirectory() {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
712
		$this->DebugMessage('CleanUpCacheDirectory() set to purge ('.(is_null($this->config_cache_maxage) ? 'NULL' : number_format($this->config_cache_maxage / 86400, 1)).' days; '.(is_null($this->config_cache_maxsize) ? 'NULL' : number_format($this->config_cache_maxsize / 1048576, 2)).' MB; '.(is_null($this->config_cache_maxfiles) ? 'NULL' : number_format($this->config_cache_maxfiles)).' files)', __FILE__, __LINE__);
713
714 View Code Duplication
		if (!is_writable($this->config_cache_directory)) {
715
			$this->DebugMessage('CleanUpCacheDirectory() skipped because "'.$this->config_cache_directory.'" is not writable', __FILE__, __LINE__);
716
			return true;
717
		}
718
719
		// cache status of cache directory for 1 hour to avoid hammering the filesystem functions
720
		$phpThumbCacheStats_filename = $this->config_cache_directory.DIRECTORY_SEPARATOR.'phpThumbCacheStats.txt';
721
		if (file_exists($phpThumbCacheStats_filename) && is_readable($phpThumbCacheStats_filename) && (filemtime($phpThumbCacheStats_filename) >= (time() - 3600))) {
722
			$this->DebugMessage('CleanUpCacheDirectory() skipped because "'.$phpThumbCacheStats_filename.'" is recently modified', __FILE__, __LINE__);
723
			return true;
724
		}
725
		if (!@touch($phpThumbCacheStats_filename)) {
726
			$this->DebugMessage('touch('.$phpThumbCacheStats_filename.') failed', __FILE__, __LINE__);
727
		}
728
729
		$DeletedKeys = array();
730
		$AllFilesInCacheDirectory = array();
731
		if (($this->config_cache_maxage > 0) || ($this->config_cache_maxsize > 0) || ($this->config_cache_maxfiles > 0)) {
732
			$CacheDirOldFilesAge  = array();
733
			$CacheDirOldFilesSize = array();
734
			$AllFilesInCacheDirectory = phpthumb_functions::GetAllFilesInSubfolders($this->config_cache_directory);
735
			foreach ($AllFilesInCacheDirectory as $fullfilename) {
736
				if (preg_match('#'.preg_quote($this->config_cache_prefix).'#i', $fullfilename) && file_exists($fullfilename)) {
737
					$CacheDirOldFilesAge[$fullfilename] = @fileatime($fullfilename);
738
					if ($CacheDirOldFilesAge[$fullfilename] == 0) {
739
						$CacheDirOldFilesAge[$fullfilename] = @filemtime($fullfilename);
740
					}
741
					$CacheDirOldFilesSize[$fullfilename] = @filesize($fullfilename);
742
				}
743
			}
744
			if (empty($CacheDirOldFilesSize)) {
745
				$this->DebugMessage('CleanUpCacheDirectory() skipped because $CacheDirOldFilesSize is empty (phpthumb_functions::GetAllFilesInSubfolders('.$this->config_cache_directory.') found no files)', __FILE__, __LINE__);
746
				return true;
747
			}
748
			$DeletedKeys['zerobyte'] = array();
749
			foreach ($CacheDirOldFilesSize as $fullfilename => $filesize) {
750
				// purge all zero-size files more than an hour old (to prevent trying to delete just-created and/or in-use files)
751
				$cutofftime = time() - 3600;
752
				if (($filesize == 0) && ($CacheDirOldFilesAge[$fullfilename] < $cutofftime)) {
753
					$this->DebugMessage('deleting "'.$fullfilename.'"', __FILE__, __LINE__);
754
					if (@unlink($fullfilename)) {
755
						$DeletedKeys['zerobyte'][] = $fullfilename;
756
						unset($CacheDirOldFilesSize[$fullfilename]);
757
						unset($CacheDirOldFilesAge[$fullfilename]);
758
					}
759
				}
760
			}
761
			$this->DebugMessage('CleanUpCacheDirectory() purged '.count($DeletedKeys['zerobyte']).' zero-byte files', __FILE__, __LINE__);
762
			asort($CacheDirOldFilesAge);
763
764 View Code Duplication
			if ($this->config_cache_maxfiles > 0) {
765
				$TotalCachedFiles = count($CacheDirOldFilesAge);
766
				$DeletedKeys['maxfiles'] = array();
767
				foreach ($CacheDirOldFilesAge as $fullfilename => $filedate) {
768
					if ($TotalCachedFiles > $this->config_cache_maxfiles) {
769
						$this->DebugMessage('deleting "'.$fullfilename.'"', __FILE__, __LINE__);
770
						if (@unlink($fullfilename)) {
771
							$TotalCachedFiles--;
772
							$DeletedKeys['maxfiles'][] = $fullfilename;
773
						}
774
					} else {
775
						// there are few enough files to keep the rest
776
						break;
777
					}
778
				}
779
				$this->DebugMessage('CleanUpCacheDirectory() purged '.count($DeletedKeys['maxfiles']).' files based on (config_cache_maxfiles='.$this->config_cache_maxfiles.')', __FILE__, __LINE__);
780
				foreach ($DeletedKeys['maxfiles'] as $fullfilename) {
781
					unset($CacheDirOldFilesAge[$fullfilename]);
782
					unset($CacheDirOldFilesSize[$fullfilename]);
783
				}
784
			}
785
786 View Code Duplication
			if ($this->config_cache_maxage > 0) {
787
				$mindate = time() - $this->config_cache_maxage;
788
				$DeletedKeys['maxage'] = array();
789
				foreach ($CacheDirOldFilesAge as $fullfilename => $filedate) {
790
					if ($filedate > 0) {
791
						if ($filedate < $mindate) {
792
							$this->DebugMessage('deleting "'.$fullfilename.'"', __FILE__, __LINE__);
793
							if (@unlink($fullfilename)) {
794
								$DeletedKeys['maxage'][] = $fullfilename;
795
							}
796
						} else {
797
							// the rest of the files are new enough to keep
798
							break;
799
						}
800
					}
801
				}
802
				$this->DebugMessage('CleanUpCacheDirectory() purged '.count($DeletedKeys['maxage']).' files based on (config_cache_maxage='.$this->config_cache_maxage.')', __FILE__, __LINE__);
803
				foreach ($DeletedKeys['maxage'] as $fullfilename) {
804
					unset($CacheDirOldFilesAge[$fullfilename]);
805
					unset($CacheDirOldFilesSize[$fullfilename]);
806
				}
807
			}
808
809
			if ($this->config_cache_maxsize > 0) {
810
				$TotalCachedFileSize = array_sum($CacheDirOldFilesSize);
811
				$DeletedKeys['maxsize'] = array();
812
				foreach ($CacheDirOldFilesAge as $fullfilename => $filedate) {
813
					if ($TotalCachedFileSize > $this->config_cache_maxsize) {
814
						$this->DebugMessage('deleting "'.$fullfilename.'"', __FILE__, __LINE__);
815
						if (@unlink($fullfilename)) {
816
							$TotalCachedFileSize -= $CacheDirOldFilesSize[$fullfilename];
817
							$DeletedKeys['maxsize'][] = $fullfilename;
818
						}
819
					} else {
820
						// the total filesizes are small enough to keep the rest of the files
821
						break;
822
					}
823
				}
824
				$this->DebugMessage('CleanUpCacheDirectory() purged '.count($DeletedKeys['maxsize']).' files based on (config_cache_maxsize='.$this->config_cache_maxsize.')', __FILE__, __LINE__);
825
				foreach ($DeletedKeys['maxsize'] as $fullfilename) {
826
					unset($CacheDirOldFilesAge[$fullfilename]);
827
					unset($CacheDirOldFilesSize[$fullfilename]);
828
				}
829
			}
830
831
		} else {
832
			$this->DebugMessage('skipping CleanUpCacheDirectory() because config set to not use it', __FILE__, __LINE__);
833
		}
834
		$totalpurged = 0;
835
		foreach ($DeletedKeys as $key => $value) {
836
			$totalpurged += count($value);
837
		}
838
		$this->DebugMessage('CleanUpCacheDirectory() purged '.$totalpurged.' files (from '.count($AllFilesInCacheDirectory).') based on config settings', __FILE__, __LINE__);
839
		if ($totalpurged > 0) {
840
			$empty_dirs = array();
841
			foreach ($AllFilesInCacheDirectory as $fullfilename) {
842
				if (is_dir($fullfilename)) {
843
					$empty_dirs[$this->realPathSafe($fullfilename)] = 1;
844
				} else {
845
					unset($empty_dirs[$this->realPathSafe(dirname($fullfilename))]);
846
				}
847
			}
848
			krsort($empty_dirs);
849
			$totalpurgeddirs = 0;
850
			foreach ($empty_dirs as $empty_dir => $dummy) {
851
				if ($empty_dir == $this->config_cache_directory) {
852
					// shouldn't happen, but just in case, don't let it delete actual cache directory
853
					continue;
854
				} elseif (@rmdir($empty_dir)) {
855
					$totalpurgeddirs++;
856
				} else {
857
					$this->DebugMessage('failed to rmdir('.$empty_dir.')', __FILE__, __LINE__);
858
				}
859
			}
860
			$this->DebugMessage('purged '.$totalpurgeddirs.' empty directories', __FILE__, __LINE__);
861
		}
862
		return true;
863
	}
864
865
	//////////////////////////////////////////////////////////////////////
866
867
	// private: re-initializator (call between rendering multiple images with one object)
868
	function resetObject() {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
869
		$class_vars = get_class_vars(get_class($this));
870
		foreach ($class_vars as $key => $value) {
871
			// do not clobber debug or config info
872
			if (!preg_match('#^(config_|debug|fatalerror)#i', $key)) {
873
				$this->$key = $value;
874
			}
875
		}
876
		$this->phpThumb(); // re-initialize some class variables
877
		return true;
878
	}
879
880
	//////////////////////////////////////////////////////////////////////
881
882
	function ResolveSource() {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
883
		if (is_resource($this->gdimg_source)) {
884
			$this->DebugMessage('ResolveSource() exiting because is_resource($this->gdimg_source)', __FILE__, __LINE__);
885
			return true;
886
		}
887
		if ($this->rawImageData) {
888
			$this->sourceFilename = null;
889
			$this->DebugMessage('ResolveSource() exiting because $this->rawImageData is set ('.number_format(strlen($this->rawImageData)).' bytes)', __FILE__, __LINE__);
890
			return true;
891
		}
892
		if ($this->sourceFilename) {
893
			$this->sourceFilename = $this->ResolveFilenameToAbsolute($this->sourceFilename);
894
			$this->DebugMessage('$this->sourceFilename set to "'.$this->sourceFilename.'"', __FILE__, __LINE__);
895
		} elseif ($this->src) {
896
			$this->sourceFilename = $this->ResolveFilenameToAbsolute($this->src);
897
			$this->DebugMessage('$this->sourceFilename set to "'.$this->sourceFilename.'" from $this->src ('.$this->src.')', __FILE__, __LINE__);
898
		} else {
899
			return $this->ErrorImage('$this->sourceFilename and $this->src are both empty');
900
		}
901
		if ($this->iswindows && ((substr($this->sourceFilename, 0, 2) == '//') || (substr($this->sourceFilename, 0, 2) == '\\\\'))) {
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...
Bug introduced by
It seems like $this->sourceFilename can also be of type false; however, parameter $string of substr() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

901
		if ($this->iswindows && ((substr(/** @scrutinizer ignore-type */ $this->sourceFilename, 0, 2) == '//') || (substr($this->sourceFilename, 0, 2) == '\\\\'))) {
Loading history...
902
			// Windows \\share\filename.ext
903
		} elseif (preg_match('#^[a-z0-9]+://#i', $this->sourceFilename, $protocol_matches)) {
0 ignored issues
show
Bug introduced by
It seems like $this->sourceFilename can also be of type false; however, parameter $subject of preg_match() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

903
		} elseif (preg_match('#^[a-z0-9]+://#i', /** @scrutinizer ignore-type */ $this->sourceFilename, $protocol_matches)) {
Loading history...
904
			if (preg_match('#^(f|ht)tps?\://#i', $this->sourceFilename)) {
905
				// URL
906
				if ($this->config_http_user_agent) {
907
					ini_set('user_agent', $this->config_http_user_agent);
908
				}
909
			} else {
910
				return $this->ErrorImage('only FTP and HTTP/HTTPS protocols are allowed, "'.$protocol_matches[1].'" is not');
911
		}
912
		} elseif (!@file_exists($this->sourceFilename)) {
0 ignored issues
show
Bug introduced by
It seems like $this->sourceFilename can also be of type false; however, parameter $filename of file_exists() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

912
		} elseif (!@file_exists(/** @scrutinizer ignore-type */ $this->sourceFilename)) {
Loading history...
913
			return $this->ErrorImage('"'.$this->sourceFilename.'" does not exist');
914
		} elseif (!@is_file($this->sourceFilename)) {
0 ignored issues
show
Bug introduced by
It seems like $this->sourceFilename can also be of type false; however, parameter $filename of is_file() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

914
		} elseif (!@is_file(/** @scrutinizer ignore-type */ $this->sourceFilename)) {
Loading history...
915
			return $this->ErrorImage('"'.$this->sourceFilename.'" is not a file');
916
		}
917
		return true;
918
	}
919
920
921
	function setOutputFormat() {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
922
		static $alreadyCalled = false;
923
		if ($this->thumbnailFormat && $alreadyCalled) {
924
			return true;
925
		}
926
		$alreadyCalled = true;
927
928
		$AvailableImageOutputFormats = array();
929
		$AvailableImageOutputFormats[] = 'text';
930
		if (@is_readable(dirname(__FILE__).'/phpthumb.ico.php')) {
931
			$AvailableImageOutputFormats[] = 'ico';
932
		}
933
		if (@is_readable(dirname(__FILE__).'/phpthumb.bmp.php')) {
934
			$AvailableImageOutputFormats[] = 'bmp';
935
		}
936
937
		$this->thumbnailFormat = 'ico';
938
939
		// Set default output format based on what image types are available
940
		if (function_exists('imagetypes')) {
941
			$imagetypes = imagetypes();
942
			if ($imagetypes & IMG_WBMP) {
943
				$this->thumbnailFormat         = 'wbmp';
944
				$AvailableImageOutputFormats[] = 'wbmp';
945
			}
946
			if ($imagetypes & IMG_GIF) {
947
				$this->thumbnailFormat         = 'gif';
948
				$AvailableImageOutputFormats[] = 'gif';
949
			}
950
			if ($imagetypes & IMG_PNG) {
951
				$this->thumbnailFormat         = 'png';
952
				$AvailableImageOutputFormats[] = 'png';
953
			}
954
			if ($imagetypes & IMG_JPG) {
955
				$this->thumbnailFormat         = 'jpeg';
956
				$AvailableImageOutputFormats[] = 'jpeg';
957
			}
958
		} else {
959
			$this->DebugMessage('imagetypes() does not exist - GD support might not be enabled?',  __FILE__, __LINE__);
960
		}
961
		if ($this->ImageMagickVersion()) {
962
			$IMformats = array('jpeg', 'png', 'gif', 'bmp', 'ico', 'wbmp');
963
			$this->DebugMessage('Addding ImageMagick formats to $AvailableImageOutputFormats ('.implode(';', $AvailableImageOutputFormats).')', __FILE__, __LINE__);
964
			foreach ($IMformats as $key => $format) {
965
				$AvailableImageOutputFormats[] = $format;
966
			}
967
		}
968
		$AvailableImageOutputFormats = array_unique($AvailableImageOutputFormats);
969
		$this->DebugMessage('$AvailableImageOutputFormats = array('.implode(';', $AvailableImageOutputFormats).')', __FILE__, __LINE__);
970
971
		$this->f = preg_replace('#[^a-z]#', '', strtolower($this->f));
972
		if (strtolower($this->config_output_format) == 'jpg') {
973
			$this->config_output_format = 'jpeg';
974
		}
975
		if (strtolower($this->f) == 'jpg') {
976
			$this->f = 'jpeg';
977
		}
978 View Code Duplication
		if (phpthumb_functions::CaseInsensitiveInArray($this->config_output_format, $AvailableImageOutputFormats)) {
979
			// set output format to config default if that format is available
980
			$this->DebugMessage('$this->thumbnailFormat set to $this->config_output_format "'.strtolower($this->config_output_format).'"', __FILE__, __LINE__);
981
			$this->thumbnailFormat = strtolower($this->config_output_format);
982
		} elseif ($this->config_output_format) {
983
			$this->DebugMessage('$this->thumbnailFormat staying as "'.$this->thumbnailFormat.'" because $this->config_output_format ('.strtolower($this->config_output_format).') is not in $AvailableImageOutputFormats', __FILE__, __LINE__);
984
		}
985 View Code Duplication
		if ($this->f && (phpthumb_functions::CaseInsensitiveInArray($this->f, $AvailableImageOutputFormats))) {
986
			// override output format if $this->f is set and that format is available
987
			$this->DebugMessage('$this->thumbnailFormat set to $this->f "'.strtolower($this->f).'"', __FILE__, __LINE__);
988
			$this->thumbnailFormat = strtolower($this->f);
989
		} elseif ($this->f) {
990
			$this->DebugMessage('$this->thumbnailFormat staying as "'.$this->thumbnailFormat.'" because $this->f ('.strtolower($this->f).') is not in $AvailableImageOutputFormats', __FILE__, __LINE__);
991
		}
992
993
		// for JPEG images, quality 1 (worst) to 99 (best)
994
		// quality < 25 is nasty, with not much size savings - not recommended
995
		// problems with 100 - invalid JPEG?
996
		$this->thumbnailQuality = max(1, min(99, ($this->q ? intval($this->q) : 75)));
997
		$this->DebugMessage('$this->thumbnailQuality set to "'.$this->thumbnailQuality.'"', __FILE__, __LINE__);
998
999
		return true;
1000
	}
1001
1002
1003
	function setCacheDirectory() {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
1004
		// resolve cache directory to absolute pathname
1005
		$this->DebugMessage('setCacheDirectory() starting with config_cache_directory = "'.$this->config_cache_directory.'"', __FILE__, __LINE__);
1006
		if (substr($this->config_cache_directory, 0, 1) == '.') {
1007
			if (preg_match('#^(f|ht)tps?\://#i', $this->src)) {
1008
				if (!$this->config_cache_disable_warning) {
1009
					$this->ErrorImage('$this->config_cache_directory ('.$this->config_cache_directory.') cannot be used for remote images. Adjust "cache_directory" or "cache_disable_warning" in phpThumb.config.php');
1010
				}
1011
			} elseif ($this->src) {
1012
				// resolve relative cache directory to source image
1013
				$this->config_cache_directory = dirname($this->ResolveFilenameToAbsolute($this->src)).DIRECTORY_SEPARATOR.$this->config_cache_directory;
0 ignored issues
show
Bug introduced by
It seems like $this->ResolveFilenameToAbsolute($this->src) can also be of type false; however, parameter $path of dirname() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

1013
				$this->config_cache_directory = dirname(/** @scrutinizer ignore-type */ $this->ResolveFilenameToAbsolute($this->src)).DIRECTORY_SEPARATOR.$this->config_cache_directory;
Loading history...
1014
			} else {
0 ignored issues
show
Unused Code introduced by
This else statement is empty and can be removed.

This check looks for the else branches 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 else branches can be removed.

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

could be turned into

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

This is much more concise to read.

Loading history...
1015
				// $this->new is probably set
1016
			}
1017
		}
1018
		if (substr($this->config_cache_directory, -1) == '/') {
1019
			$this->config_cache_directory = substr($this->config_cache_directory, 0, -1);
1020
		}
1021
		if ($this->iswindows) {
1022
			$this->config_cache_directory = str_replace('/', DIRECTORY_SEPARATOR, $this->config_cache_directory);
1023
		}
1024
		if ($this->config_cache_directory) {
1025
			$real_cache_path = $this->realPathSafe($this->config_cache_directory);
1026
			if (!$real_cache_path) {
1027
				$this->DebugMessage('$this->realPathSafe($this->config_cache_directory) failed for "'.$this->config_cache_directory.'"', __FILE__, __LINE__);
1028
				if (!is_dir($this->config_cache_directory)) {
1029
					$this->DebugMessage('!is_dir('.$this->config_cache_directory.')', __FILE__, __LINE__);
1030
				}
1031
			}
1032
			if ($real_cache_path) {
1033
				$this->DebugMessage('setting config_cache_directory to $this->realPathSafe('.$this->config_cache_directory.') = "'.$real_cache_path.'"', __FILE__, __LINE__);
1034
				$this->config_cache_directory = $real_cache_path;
1035
			}
1036
		}
1037
		if (!is_dir($this->config_cache_directory)) {
1038
			if (!$this->config_cache_disable_warning) {
1039
				$this->ErrorImage('$this->config_cache_directory ('.$this->config_cache_directory.') does not exist. Adjust "cache_directory" or "cache_disable_warning" in phpThumb.config.php');
1040
			}
1041
			$this->DebugMessage('$this->config_cache_directory ('.$this->config_cache_directory.') is not a directory', __FILE__, __LINE__);
1042
			$this->config_cache_directory = null;
1043 View Code Duplication
		} elseif (!@is_writable($this->config_cache_directory)) {
1044
			$this->DebugMessage('$this->config_cache_directory is not writable ('.$this->config_cache_directory.')', __FILE__, __LINE__);
1045
		}
1046
1047
		$this->InitializeTempDirSetting();
1048
		if (!@is_dir($this->config_temp_directory) && !@is_writable($this->config_temp_directory) && @is_dir($this->config_cache_directory) && @is_writable($this->config_cache_directory)) {
1049
			$this->DebugMessage('setting $this->config_temp_directory = $this->config_cache_directory ('.$this->config_cache_directory.')', __FILE__, __LINE__);
1050
			$this->config_temp_directory = $this->config_cache_directory;
1051
		}
1052
		return true;
1053
	}
1054
1055
	/* Takes the array of path segments up to now, and the next segment (maybe a modifier: empty, . or ..)
1056
	   Applies it, adding or removing from $segments as a result. Returns nothing. */
1057
	// http://support.silisoftware.com/phpBB3/viewtopic.php?t=961
1058
	function applyPathSegment(&$segments, $segment) {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
1059
		if ($segment == '.') {
1060
			return; // always remove
1061
		}
1062
		if ($segment == '') {
1063
			$test = array_pop($segments);
1064
			if (is_null($test)) {
1065
				$segments[] = $segment; // keep the first empty block
1066 View Code Duplication
			} elseif ($test == '') {
1067
				$test = array_pop($segments);
1068
				if (is_null($test)) {
1069
					$segments[] = $test;
1070
					$segments[] = $segment; // keep the second one too
1071
				} else { // put both back and ignore segment
1072
					$segments[] = $test;
1073
					$segments[] = $test;
1074
				}
1075
			} else {
1076
				$segments[] = $test; // ignore empty blocks
1077
			}
1078
		} else {
1079
			if ($segment == '..') {
1080
				$test = array_pop($segments);
1081 View Code Duplication
				if (is_null($test)) {
1082
					$segments[] = $segment;
1083
				} elseif ($test == '..') {
1084
					$segments[] = $test;
1085
					$segments[] = $segment;
1086
				} else {
1087
					if ($test == '') {
1088
						$segments[] = $test;
1089
					} // else nothing, remove both
1090
				}
1091
			} else {
1092
				$segments[] = $segment;
1093
			}
1094
		}
1095
	}
1096
1097
	/* Takes array of path components, normalizes it: removes empty slots and '.', collapses '..' and folder names.  Returns array. */
1098
	// http://support.silisoftware.com/phpBB3/viewtopic.php?t=961
1099
	function normalizePath($segments) {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
1100
		$parts = array();
1101
		foreach ($segments as $segment) {
1102
			$this->applyPathSegment($parts, $segment);
1103
		}
1104
		return $parts;
1105
	}
1106
1107
	/* True if the provided path points (without resolving symbolic links) into one of the allowed directories. */
1108
	// http://support.silisoftware.com/phpBB3/viewtopic.php?t=961
1109
	function matchPath($path, $allowed_dirs) {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
1110
		if (!empty($allowed_dirs)) {
1111
			foreach ($allowed_dirs as $one_dir) {
1112
				if (preg_match('#^'.preg_quote(str_replace(DIRECTORY_SEPARATOR, '/', $this->realPathSafe($one_dir))).'#', $path)) {
1113
					return true;
1114
				}
1115
			}
1116
		}
1117
		return false;
1118
	}
1119
1120
	/* True if the provided path points inside one of open_basedirs (or if open_basedirs are disabled) */
1121
	// http://support.silisoftware.com/phpBB3/viewtopic.php?t=961
1122
	function isInOpenBasedir($path) {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
1123
		static $open_basedirs = null;
1124
		if (is_null($open_basedirs)) {
1125
			$ini_text = ini_get('open_basedir');
1126
			$this->DebugMessage('open_basedir: "'.$ini_text.'"', __FILE__, __LINE__);
1127
			$open_basedirs = array();
1128
			if (strlen($ini_text) > 0) {
1129
				foreach (preg_split('#[;:]#', $ini_text) as $key => $value) {
1130
					$open_basedirs[$key] = $this->realPathSafe($value);
1131
				}
1132
			}
1133
		}
1134
		return (empty($open_basedirs) || $this->matchPath($path, $open_basedirs));
1135
	}
1136
1137
	/* Resolves all symlinks in $path, checking that each continuous part ends in an allowed zone. Returns null, if any component leads outside of allowed zone. */
1138
	// http://support.silisoftware.com/phpBB3/viewtopic.php?t=961
1139
	function resolvePath($path, $allowed_dirs) {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
1140
		$this->DebugMessage('resolvePath: '.$path.' (allowed_dirs: '.print_r($allowed_dirs, true).')', __FILE__, __LINE__);
1141
1142
		// add base path to the top of the list
1143
		if (!$this->config_allow_src_above_docroot) {
1144
			array_unshift($allowed_dirs, $this->realPathSafe($this->config_document_root));
1145
		} else {
1146
			if (!$this->config_allow_src_above_phpthumb) {
1147
				array_unshift($allowed_dirs, $this->realPathSafe(dirname(__FILE__)));
1148
			} else {
1149
				// no checks are needed, offload the work to realpath and forget about it
1150
				$this->DebugMessage('resolvePath: checks disabled, returning '.$this->realPathSafe($path), __FILE__, __LINE__);
1151
				return $this->realPathSafe($path);
1152
			}
1153
		}
1154
		if ($path == '') {
1155
			return null; // save us trouble
1156
		}
1157
1158
		do {
1159
			$this->DebugMessage('resolvePath: iteration, path='.$path.', base path = '.$allowed_dirs[0], __FILE__, __LINE__);
1160
1161
			$parts = array();
1162
			// do not use "cleaner" foreach version of this loop as later code relies on both $segments and $i
1163
			// http://support.silisoftware.com/phpBB3/viewtopic.php?t=964
1164
			$segments = explode(DIRECTORY_SEPARATOR, $path);
1165
			for ($i = 0; $i < count($segments); $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...
1166
				$this->applyPathSegment($parts, $segments[$i]);
1167
				$thispart = implode(DIRECTORY_SEPARATOR, $parts);
1168
				if ($this->isInOpenBasedir($thispart)) {
1169
					if (is_link($thispart)) {
1170
						break;
1171
					}
1172
				}
1173
			}
1174
1175
			$this->DebugMessage('resolvePath: stop at component '.$i, __FILE__, __LINE__);
1176
			// test the part up to here
1177
			$path = implode(DIRECTORY_SEPARATOR, $parts);
1178
			$this->DebugMessage('resolvePath: stop at path='.$path, __FILE__, __LINE__);
1179
			if (!$this->matchPath($path, $allowed_dirs)) {
1180
				$this->DebugMessage('resolvePath: no match, returning null', __FILE__, __LINE__);
1181
				return null;
1182
			}
1183
			if ($i >= count($segments)) { // reached end
1184
				$this->DebugMessage('resolvePath: path parsed, over', __FILE__, __LINE__);
1185
				break;
1186
			}
1187
			// else it's symlink, rewrite path
1188
			$path = readlink($path);
1189
			$this->DebugMessage('resolvePath: symlink matched, target='.$path, __FILE__, __LINE__);
1190
1191
			/*
1192
			Replace base path with symlink target.
1193
			Assuming:
1194
			  /www/img/external -> /external
1195
			This is allowed:
1196
			  GET /www/img/external/../external/test/pic.jpg
1197
			This isn't:
1198
			  GET /www/img/external/../www/img/pic.jpg
1199
			So there's only one base path which is the last symlink target, but any number of stable whitelisted paths.
1200
			*/
1201
			if ($this->config_auto_allow_symlinks) {
1202
				$allowed_dirs[0] = $path;
1203
			}
1204
			$path = $path.DIRECTORY_SEPARATOR.implode(DIRECTORY_SEPARATOR, array_slice($segments,$i + 1));
1205
		} while (true);
1206
		return $path;
1207
	}
1208
1209
1210
	function realPathSafe($filename) {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
1211
		// http://php.net/manual/en/function.realpath.php -- "Note: The running script must have executable permissions on all directories in the hierarchy, otherwise realpath() will return FALSE"
1212
		// realPathSafe() provides a reasonable facsimile of realpath() but does not resolve symbolic links, nor does it check that the file/path actually exists
1213
		if (!$this->config_disable_realpath) {
1214
			return realpath($filename);
1215
		}
1216
1217
		// http://stackoverflow.com/questions/21421569
1218
		$newfilename = preg_replace('#[\\/]+#', DIRECTORY_SEPARATOR, $filename);
1219
		if (!preg_match('#^'.DIRECTORY_SEPARATOR.'#', $newfilename)) {
1220
			$newfilename = dirname(__FILE__).DIRECTORY_SEPARATOR.$newfilename;
1221
		}
1222
		do {
1223
			$beforeloop = $newfilename;
1224
1225
			// Replace all sequences of more than one / with a single one [[ If you're working on a system that treats // at the start of a path as special, make sure you replace multiple / characters at the start with two of them. This is the only place where POSIX allows (but does not mandate) special handling for multiples, in all other cases, multiple / characters are equivalent to a single one.]]
1226
			$newfilename = preg_replace('#'.DIRECTORY_SEPARATOR.'+#', DIRECTORY_SEPARATOR, $newfilename);
1227
1228
			// Replace all occurrences of /./ with /
1229
			$newfilename = preg_replace('#'.DIRECTORY_SEPARATOR.'\\.'.DIRECTORY_SEPARATOR.'#', DIRECTORY_SEPARATOR, $newfilename);
1230
1231
			// Remove ./ if at the start
1232
			$newfilename = preg_replace('#^\\.'.DIRECTORY_SEPARATOR.'#', '', $newfilename);
1233
1234
			// Remove /. if at the end
1235
			$newfilename = preg_replace('#'.DIRECTORY_SEPARATOR.'\\.$#', '', $newfilename);
1236
1237
			// Replace /anything/../ with /
1238
			$newfilename = preg_replace('#'.DIRECTORY_SEPARATOR.'[^'.DIRECTORY_SEPARATOR.']+'.DIRECTORY_SEPARATOR.'\\.\\.'.DIRECTORY_SEPARATOR.'#', DIRECTORY_SEPARATOR, $newfilename);
1239
1240
			// Remove /anything/.. if at the end
1241
			$newfilename = preg_replace('#'.DIRECTORY_SEPARATOR.'[^'.DIRECTORY_SEPARATOR.']+'.DIRECTORY_SEPARATOR.'\\.\\.$#', '', $newfilename);
1242
1243
		} while ($newfilename != $beforeloop);
1244
		return $newfilename;
1245
	}
1246
1247
1248
	function ResolveFilenameToAbsolute($filename) {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
1249
		if (empty($filename)) {
1250
			return false;
1251
		}
1252
1253
		if (preg_match('#^[a-z0-9]+\:/{1,2}#i', $filename)) {
1254
			// eg: http://host/path/file.jpg (HTTP URL)
1255
			// eg: ftp://host/path/file.jpg  (FTP URL)
1256
			// eg: data1:/path/file.jpg      (Netware path)
1257
1258
			//$AbsoluteFilename = $filename;
1259
			return $filename;
1260
1261
		} elseif ($this->iswindows && isset($filename{1}) && ($filename{1} == ':')) {
1262
1263
			// absolute pathname (Windows)
1264
			$AbsoluteFilename = $filename;
1265
1266
		} elseif ($this->iswindows && ((substr($filename, 0, 2) == '//') || (substr($filename, 0, 2) == '\\\\'))) {
1267
1268
			// absolute pathname (Windows)
1269
			$AbsoluteFilename = $filename;
1270
1271
		} elseif ($filename{0} == '/') {
1272
1273
			if (@is_readable($filename) && !@is_readable($this->config_document_root.$filename)) {
1274
1275
				// absolute filename (*nix)
1276
				$AbsoluteFilename = $filename;
1277
1278
			} elseif (isset($filename{1}) && ($filename{1} == '~')) {
1279
1280
				// /~user/path
1281
				if ($ApacheLookupURIarray = phpthumb_functions::ApacheLookupURIarray($filename)) {
1282
					$AbsoluteFilename = $ApacheLookupURIarray['filename'];
1283
				} else {
1284
					$AbsoluteFilename = $this->realPathSafe($filename);
1285
					if (@is_readable($AbsoluteFilename)) {
1286
						$this->DebugMessage('phpthumb_functions::ApacheLookupURIarray() failed for "'.$filename.'", but the correct filename ('.$AbsoluteFilename.') seems to have been resolved with $this->realPathSafe($filename)', __FILE__, __LINE__);
1287 View Code Duplication
					} elseif (is_dir(dirname($AbsoluteFilename))) {
1288
						$this->DebugMessage('phpthumb_functions::ApacheLookupURIarray() failed for "'.dirname($filename).'", but the correct directory ('.dirname($AbsoluteFilename).') seems to have been resolved with $this->realPathSafe(.)', __FILE__, __LINE__);
1289
					} else {
1290
						return $this->ErrorImage('phpthumb_functions::ApacheLookupURIarray() failed for "'.$filename.'". This has been known to fail on Apache2 - try using the absolute filename for the source image (ex: "/home/user/httpdocs/image.jpg" instead of "/~user/image.jpg")');
1291
					}
1292
				}
1293
1294
			} else {
1295
1296
				// relative filename (any OS)
1297
				if (preg_match('#^'.preg_quote($this->config_document_root).'#', $filename)) {
1298
					$AbsoluteFilename = $filename;
1299
					$this->DebugMessage('ResolveFilenameToAbsolute() NOT prepending $this->config_document_root ('.$this->config_document_root.') to $filename ('.$filename.') resulting in ($AbsoluteFilename = "'.$AbsoluteFilename.'")', __FILE__, __LINE__);
1300
				} else {
1301
					$AbsoluteFilename = $this->config_document_root.$filename;
1302
					$this->DebugMessage('ResolveFilenameToAbsolute() prepending $this->config_document_root ('.$this->config_document_root.') to $filename ('.$filename.') resulting in ($AbsoluteFilename = "'.$AbsoluteFilename.'")', __FILE__, __LINE__);
1303
				}
1304
1305
			}
1306
1307
		} else {
1308
1309
			// relative to current directory (any OS)
1310
			$AbsoluteFilename = dirname(__FILE__).DIRECTORY_SEPARATOR.preg_replace('#[/\\\\]#', DIRECTORY_SEPARATOR, $filename);
1311
1312
			if (substr(dirname(@$_SERVER['PHP_SELF']), 0, 2) == '/~') {
1313
				if ($ApacheLookupURIarray = phpthumb_functions::ApacheLookupURIarray(dirname(@$_SERVER['PHP_SELF']))) {
1314
					$AbsoluteFilename = $ApacheLookupURIarray['filename'].DIRECTORY_SEPARATOR.$filename;
1315
				} else {
1316
					$AbsoluteFilename = $this->realPathSafe('.').DIRECTORY_SEPARATOR.$filename;
1317
					if (@is_readable($AbsoluteFilename)) {
1318
						$this->DebugMessage('phpthumb_functions::ApacheLookupURIarray() failed for "'.dirname(@$_SERVER['PHP_SELF']).'", but the correct filename ('.$AbsoluteFilename.') seems to have been resolved with $this->realPathSafe(.)/$filename', __FILE__, __LINE__);
1319 View Code Duplication
					} elseif (is_dir(dirname($AbsoluteFilename))) {
1320
						$this->DebugMessage('phpthumb_functions::ApacheLookupURIarray() failed for "'.dirname(@$_SERVER['PHP_SELF']).'", but the correct directory ('.dirname($AbsoluteFilename).') seems to have been resolved with $this->realPathSafe(.)', __FILE__, __LINE__);
1321
					} else {
1322
						return $this->ErrorImage('phpthumb_functions::ApacheLookupURIarray() failed for "'.dirname(@$_SERVER['PHP_SELF']).'". This has been known to fail on Apache2 - try using the absolute filename for the source image');
1323
					}
1324
				}
1325
			}
1326
1327
		}
1328
		/*
1329
		// removed 2014-May-30: http://support.silisoftware.com/phpBB3/viewtopic.php?t=961
1330
		if (is_link($AbsoluteFilename)) {
1331
			$this->DebugMessage('is_link()==true, changing "'.$AbsoluteFilename.'" to "'.readlink($AbsoluteFilename).'"', __FILE__, __LINE__);
1332
			$AbsoluteFilename = readlink($AbsoluteFilename);
1333
		}
1334
		if ($this->realPathSafe($AbsoluteFilename)) {
1335
			$AbsoluteFilename = $this->realPathSafe($AbsoluteFilename);
1336
		}
1337
		*/
1338
		if ($this->iswindows) {
1339
			$AbsoluteFilename = preg_replace('#^'.preg_quote($this->realPathSafe($this->config_document_root)).'#i', str_replace('\\', '\\\\', $this->realPathSafe($this->config_document_root)), $AbsoluteFilename);
1340
			$AbsoluteFilename = str_replace(DIRECTORY_SEPARATOR, '/', $AbsoluteFilename);
1341
		}
1342
		$AbsoluteFilename = $this->resolvePath($AbsoluteFilename, $this->config_additional_allowed_dirs);
1343
		if (!$this->config_allow_src_above_docroot && !preg_match('#^'.preg_quote(str_replace(DIRECTORY_SEPARATOR, '/', $this->realPathSafe($this->config_document_root))).'#', $AbsoluteFilename)) {
1344
			$this->DebugMessage('!$this->config_allow_src_above_docroot therefore setting "'.$AbsoluteFilename.'" (outside "'.$this->realPathSafe($this->config_document_root).'") to null', __FILE__, __LINE__);
1345
			return false;
1346
		}
1347
		if (!$this->config_allow_src_above_phpthumb && !preg_match('#^'.preg_quote(str_replace(DIRECTORY_SEPARATOR, '/', dirname(__FILE__))).'#', $AbsoluteFilename)) {
1348
			$this->DebugMessage('!$this->config_allow_src_above_phpthumb therefore setting "'.$AbsoluteFilename.'" (outside "'.dirname(__FILE__).'") to null', __FILE__, __LINE__);
1349
			return false;
1350
		}
1351
		return $AbsoluteFilename;
1352
	}
1353
1354
1355
	function file_exists_ignoreopenbasedir($filename, $cached=true) {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
1356
		static $open_basedirs = null;
1357
		static $file_exists_cache = array();
1358
		if (!$cached || !isset($file_exists_cache[$filename])) {
1359
			if (is_null($open_basedirs)) {
1360
				$open_basedirs = preg_split('#[;:]#', ini_get('open_basedir'));
1361
			}
1362
			if (empty($open_basedirs) || in_array(dirname($filename), $open_basedirs)) {
1363
				$file_exists_cache[$filename] = file_exists($filename);
1364
			} elseif ($this->iswindows) {
1365
				$ls_filename = trim(phpthumb_functions::SafeExec('dir /b '.phpthumb_functions::escapeshellarg_replacement($filename)));
0 ignored issues
show
Bug introduced by
It seems like phpthumb_functions::Safe...replacement($filename)) can also be of type false; however, parameter $str of trim() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

1365
				$ls_filename = trim(/** @scrutinizer ignore-type */ phpthumb_functions::SafeExec('dir /b '.phpthumb_functions::escapeshellarg_replacement($filename)));
Loading history...
1366
				$file_exists_cache[$filename] = ($ls_filename == basename($filename));  // command dir /b return only filename without path
1367
			} else {
1368
				$ls_filename = trim(phpthumb_functions::SafeExec('ls '.phpthumb_functions::escapeshellarg_replacement($filename)));
1369
				$file_exists_cache[$filename] = ($ls_filename == $filename);
1370
			}
1371
		}
1372
		return $file_exists_cache[$filename];
1373
	}
1374
1375
1376
	function ImageMagickWhichConvert() {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
1377
		static $WhichConvert = null;
1378
		if (is_null($WhichConvert)) {
1379
			if ($this->iswindows) {
1380
				$WhichConvert = false;
1381
			} else {
1382
				$IMwhichConvertCacheFilename = $this->config_cache_directory.DIRECTORY_SEPARATOR.'phpThumbCacheIMwhichConvert.txt';
1383
				if (($cachedwhichconvertstring = @file_get_contents($IMwhichConvertCacheFilename)) !== false) {
1384
					$WhichConvert = $cachedwhichconvertstring;
1385
				} else {
1386
					$WhichConvert = trim(phpthumb_functions::SafeExec('which convert'));
1387
					@file_put_contents($IMwhichConvertCacheFilename, $WhichConvert);
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition for file_put_contents(). This can introduce security issues, and is generally not recommended. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unhandled  annotation

1387
					/** @scrutinizer ignore-unhandled */ @file_put_contents($IMwhichConvertCacheFilename, $WhichConvert);

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...
1388
					@chmod($IMwhichConvertCacheFilename, $this->getParameter('config_file_create_mask'));
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition for chmod(). This can introduce security issues, and is generally not recommended. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unhandled  annotation

1388
					/** @scrutinizer ignore-unhandled */ @chmod($IMwhichConvertCacheFilename, $this->getParameter('config_file_create_mask'));

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...
1389
				}
1390
			}
1391
		}
1392
		return $WhichConvert;
1393
	}
1394
1395
1396
	function ImageMagickCommandlineBase() {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
1397
		static $commandline = null;
1398
		if (is_null($commandline)) {
1399
			if ($this->issafemode) {
1400
				$commandline = '';
1401
				return $commandline;
1402
			}
1403
1404
			$IMcommandlineBaseCacheFilename = $this->config_cache_directory.DIRECTORY_SEPARATOR.'phpThumbCacheIMcommandlineBase.txt';
1405
			if (($commandline = @file_get_contents($IMcommandlineBaseCacheFilename)) !== false) {
1406
				return $commandline;
1407
			}
1408
1409
			$commandline = (!is_null($this->config_imagemagick_path) ? $this->config_imagemagick_path : '');
0 ignored issues
show
Unused Code introduced by
The assignment to $commandline is dead and can be removed.
Loading history...
1410
1411
			if ($this->config_imagemagick_path && ($this->config_imagemagick_path != $this->realPathSafe($this->config_imagemagick_path))) {
1412
				if (@is_executable($this->realPathSafe($this->config_imagemagick_path))) {
1413
					$this->DebugMessage('Changing $this->config_imagemagick_path ('.$this->config_imagemagick_path.') to $this->realPathSafe($this->config_imagemagick_path) ('.$this->realPathSafe($this->config_imagemagick_path).')', __FILE__, __LINE__);
1414
					$this->config_imagemagick_path = $this->realPathSafe($this->config_imagemagick_path);
1415
				} else {
1416
					$this->DebugMessage('Leaving $this->config_imagemagick_path as ('.$this->config_imagemagick_path.') because !is_execuatable($this->realPathSafe($this->config_imagemagick_path)) ('.$this->realPathSafe($this->config_imagemagick_path).')', __FILE__, __LINE__);
1417
				}
1418
			}
1419
			$this->DebugMessage('                  file_exists('.$this->config_imagemagick_path.') = '.intval(                        @file_exists($this->config_imagemagick_path)), __FILE__, __LINE__);
1420
			$this->DebugMessage('file_exists_ignoreopenbasedir('.$this->config_imagemagick_path.') = '.intval($this->file_exists_ignoreopenbasedir($this->config_imagemagick_path)), __FILE__, __LINE__);
1421
			$this->DebugMessage('                      is_file('.$this->config_imagemagick_path.') = '.intval(                            @is_file($this->config_imagemagick_path)), __FILE__, __LINE__);
1422
			$this->DebugMessage('                is_executable('.$this->config_imagemagick_path.') = '.intval(                      @is_executable($this->config_imagemagick_path)), __FILE__, __LINE__);
1423
1424
			if ($this->file_exists_ignoreopenbasedir($this->config_imagemagick_path)) {
1425
1426
				$this->DebugMessage('using ImageMagick path from $this->config_imagemagick_path ('.$this->config_imagemagick_path.')', __FILE__, __LINE__);
1427
				if ($this->iswindows) {
1428
					$commandline = substr($this->config_imagemagick_path, 0, 2).' && cd '.phpthumb_functions::escapeshellarg_replacement(str_replace('/', DIRECTORY_SEPARATOR, substr(dirname($this->config_imagemagick_path), 2))).' && '.phpthumb_functions::escapeshellarg_replacement(basename($this->config_imagemagick_path));
1429
				} else {
1430
					$commandline = phpthumb_functions::escapeshellarg_replacement($this->config_imagemagick_path);
1431
				}
1432
1433
			} else {
1434
1435
				$which_convert = $this->ImageMagickWhichConvert();
1436
				$IMversion     = $this->ImageMagickVersion();
1437
1438
				if ($which_convert && ($which_convert{0} == '/') && $this->file_exists_ignoreopenbasedir($which_convert)) {
1439
1440
					// `which convert` *should* return the path if "convert" exist, or nothing if it doesn't
1441
					// other things *may* get returned, like "sh: convert: not found" or "no convert in /usr/local/bin /usr/sbin /usr/bin /usr/ccs/bin"
1442
					// so only do this if the value returned exists as a file
1443
					$this->DebugMessage('using ImageMagick path from `which convert` ('.$which_convert.')', __FILE__, __LINE__);
1444
					$commandline = 'convert';
1445
1446
				} elseif ($IMversion) {
1447
1448
					$this->DebugMessage('setting ImageMagick path to $this->config_imagemagick_path ('.$this->config_imagemagick_path.') ['.$IMversion.']', __FILE__, __LINE__);
1449
					$commandline = $this->config_imagemagick_path;
1450
1451
				} else {
1452
1453
					$this->DebugMessage('ImageMagickThumbnailToGD() aborting because cannot find convert in $this->config_imagemagick_path ('.$this->config_imagemagick_path.'), and `which convert` returned ('.$which_convert.')', __FILE__, __LINE__);
1454
					$commandline = '';
1455
1456
				}
1457
1458
			}
1459
1460
			@file_put_contents($IMcommandlineBaseCacheFilename, $commandline);
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition for file_put_contents(). This can introduce security issues, and is generally not recommended. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unhandled  annotation

1460
			/** @scrutinizer ignore-unhandled */ @file_put_contents($IMcommandlineBaseCacheFilename, $commandline);

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...
1461
			@chmod($IMcommandlineBaseCacheFilename, $this->getParameter('config_file_create_mask'));
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition for chmod(). This can introduce security issues, and is generally not recommended. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unhandled  annotation

1461
			/** @scrutinizer ignore-unhandled */ @chmod($IMcommandlineBaseCacheFilename, $this->getParameter('config_file_create_mask'));

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...
1462
		}
1463
		return $commandline;
1464
	}
1465
1466
1467
	function ImageMagickVersion($returnRAW=false) {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
1468
		static $versionstring = null;
1469
		if (is_null($versionstring)) {
1470
			$versionstring = array(0=>false, 1=>false);
1471
1472
			$IMversionCacheFilename = $this->config_cache_directory.DIRECTORY_SEPARATOR.'phpThumbCacheIMversion.txt';
1473
			if ($cachedversionstring = @file_get_contents($IMversionCacheFilename)) {
1474
1475
				$versionstring = explode("\n", $cachedversionstring, 2);
1476
				$versionstring[0] = ($versionstring[0] ? $versionstring[0] : false); // "false" is stored as an empty string in the cache file
1477
				$versionstring[1] = ($versionstring[1] ? $versionstring[1] : false); // "false" is stored as an empty string in the cache file
1478
1479
			} else {
1480
1481
				$commandline = $this->ImageMagickCommandlineBase();
1482
				$commandline = (!is_null($commandline) ? $commandline : '');
1483
				if ($commandline) {
1484
					$commandline .= ' --version';
1485
					$this->DebugMessage('ImageMagick version checked with "'.$commandline.'"', __FILE__, __LINE__);
1486
					$versionstring[1] = trim(phpthumb_functions::SafeExec($commandline));
0 ignored issues
show
Bug introduced by
It seems like phpthumb_functions::SafeExec($commandline) can also be of type false; however, parameter $str of trim() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

1486
					$versionstring[1] = trim(/** @scrutinizer ignore-type */ phpthumb_functions::SafeExec($commandline));
Loading history...
1487
					if (preg_match('#^Version: [^0-9]*([ 0-9\\.\\:Q/\\-]+)#i', $versionstring[1], $matches)) {
1488
						$versionstring[0] = trim($matches[1]);
1489
					} else {
1490
						$versionstring[0] = false;
1491
						$this->DebugMessage('ImageMagick did not return recognized version string ('.$versionstring[1].')', __FILE__, __LINE__);
1492
					}
1493
					$this->DebugMessage('ImageMagick convert --version says "'.@$matches[0].'"', __FILE__, __LINE__);
1494
				}
1495
1496
				@file_put_contents($IMversionCacheFilename, $versionstring[0]."\n".$versionstring[1]);
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition for file_put_contents(). This can introduce security issues, and is generally not recommended. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unhandled  annotation

1496
				/** @scrutinizer ignore-unhandled */ @file_put_contents($IMversionCacheFilename, $versionstring[0]."\n".$versionstring[1]);

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...
1497
				@chmod($IMversionCacheFilename, $this->getParameter('config_file_create_mask'));
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition for chmod(). This can introduce security issues, and is generally not recommended. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unhandled  annotation

1497
				/** @scrutinizer ignore-unhandled */ @chmod($IMversionCacheFilename, $this->getParameter('config_file_create_mask'));

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...
1498
1499
			}
1500
		}
1501
		return $versionstring[intval($returnRAW)];
1502
	}
1503
1504
1505
	function ImageMagickSwitchAvailable($switchname) {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
1506
		static $IMoptions = null;
1507
		if (is_null($IMoptions)) {
1508
			$IMoptions = array();
1509
			$commandline = $this->ImageMagickCommandlineBase();
1510
			if (!is_null($commandline)) {
1511
				$commandline .= ' -help';
1512
				$IMhelp_lines = explode("\n", phpthumb_functions::SafeExec($commandline));
0 ignored issues
show
Bug introduced by
It seems like phpthumb_functions::SafeExec($commandline) can also be of type false; however, parameter $string of explode() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

1512
				$IMhelp_lines = explode("\n", /** @scrutinizer ignore-type */ phpthumb_functions::SafeExec($commandline));
Loading history...
1513
				foreach ($IMhelp_lines as $line) {
1514
					if (preg_match('#^[\\+\\-]([a-z\\-]+) #', trim($line), $matches)) {
1515
						$IMoptions[$matches[1]] = true;
1516
					}
1517
				}
1518
			}
1519
		}
1520
		if (is_array($switchname)) {
1521
			$allOK = true;
1522
			foreach ($switchname as $key => $value) {
1523
				if (!isset($IMoptions[$value])) {
1524
					$allOK = false;
1525
					break;
1526
				}
1527
			}
1528
			$this->DebugMessage('ImageMagickSwitchAvailable('.implode(';', $switchname).') = '.intval($allOK).'', __FILE__, __LINE__);
1529
		} else {
1530
			$allOK = isset($IMoptions[$switchname]);
1531
			$this->DebugMessage('ImageMagickSwitchAvailable('.$switchname.') = '.intval($allOK).'', __FILE__, __LINE__);
1532
		}
1533
		return $allOK;
1534
	}
1535
1536
1537
	function ImageMagickFormatsList() {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
1538
		static $IMformatsList = null;
1539
		if (is_null($IMformatsList)) {
1540
			$IMformatsList = '';
1541
			$commandline = $this->ImageMagickCommandlineBase();
1542
			if (!is_null($commandline)) {
1543
				$commandline = dirname($commandline).DIRECTORY_SEPARATOR.str_replace('convert', 'identify', basename($commandline));
1544
				$commandline .= ' -list format';
1545
				$IMformatsList = phpthumb_functions::SafeExec($commandline);
1546
			}
1547
		}
1548
		return $IMformatsList;
1549
	}
1550
1551
1552
	function SourceDataToTempFile() {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
1553
		if ($IMtempSourceFilename = $this->phpThumb_tempnam()) {
1554
			$IMtempSourceFilename = $this->realPathSafe($IMtempSourceFilename);
1555
			ob_start();
1556
			$fp_tempfile = fopen($IMtempSourceFilename, 'wb');
1557
			$tempfile_open_error  = ob_get_contents();
1558
			ob_end_clean();
1559
			if ($fp_tempfile) {
1560
				fwrite($fp_tempfile, $this->rawImageData);
1561
				fclose($fp_tempfile);
1562
				@chmod($IMtempSourceFilename, $this->getParameter('config_file_create_mask'));
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition for chmod(). This can introduce security issues, and is generally not recommended. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unhandled  annotation

1562
				/** @scrutinizer ignore-unhandled */ @chmod($IMtempSourceFilename, $this->getParameter('config_file_create_mask'));

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...
1563
				$this->sourceFilename = $IMtempSourceFilename;
1564
				$this->DebugMessage('ImageMagickThumbnailToGD() setting $this->sourceFilename to "'.$IMtempSourceFilename.'" from $this->rawImageData ('.strlen($this->rawImageData).' bytes)', __FILE__, __LINE__);
1565
			} else {
1566
				$this->DebugMessage('ImageMagickThumbnailToGD() FAILED setting $this->sourceFilename to "'.$IMtempSourceFilename.'" (failed to open for writing: "'.$tempfile_open_error.'")', __FILE__, __LINE__);
1567
			}
1568
			unset($tempfile_open_error, $IMtempSourceFilename);
1569
			return true;
1570
		}
1571
		$this->DebugMessage('SourceDataToTempFile() FAILED because $this->phpThumb_tempnam() failed', __FILE__, __LINE__);
1572
		return false;
1573
	}
1574
1575
1576
	function ImageMagickThumbnailToGD() {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
1577
		// http://www.imagemagick.org/script/command-line-options.php
1578
1579
		$this->useRawIMoutput = true;
1580
		if (phpthumb_functions::gd_version()) {
1581
			// if GD is not available, must use whatever ImageMagick can output
1582
1583
			// $UnAllowedParameters contains options that can only be processed in GD, not ImageMagick
1584
			// note: 'fltr' *may* need to be processed by GD, but we'll check that in more detail below
1585
			$UnAllowedParameters = array('xto', 'ar', 'bg', 'bc');
1586
			// 'ra' may be part of this list, if not a multiple of 90 degrees
1587
			foreach ($UnAllowedParameters as $parameter) {
1588
				if (isset($this->$parameter)) {
1589
					$this->DebugMessage('$this->useRawIMoutput=false because "'.$parameter.'" is set', __FILE__, __LINE__);
1590
					$this->useRawIMoutput = false;
1591
					break;
1592
				}
1593
			}
1594
		}
1595
		$this->DebugMessage('$this->useRawIMoutput='.($this->useRawIMoutput ? 'true' : 'false').' after checking $UnAllowedParameters', __FILE__, __LINE__);
1596
		$ImageCreateFunction = '';
1597
		$outputFormat = $this->thumbnailFormat;
1598
		if (phpthumb_functions::gd_version()) {
1599
			if ($this->useRawIMoutput) {
1600
				switch ($this->thumbnailFormat) {
1601
					case 'gif':
1602
						$ImageCreateFunction = 'imagecreatefromgif';
1603
						$this->is_alpha = true;
1604
						break;
1605
					case 'png':
1606
						$ImageCreateFunction = 'imagecreatefrompng';
1607
						$this->is_alpha = true;
1608
						break;
1609
					case 'jpg':
1610
					case 'jpeg':
1611
						$ImageCreateFunction = 'imagecreatefromjpeg';
1612
						break;
1613
					default:
1614
						$this->DebugMessage('Forcing output to PNG because $this->thumbnailFormat ('.$this->thumbnailFormat.' is not a GD-supported format)', __FILE__, __LINE__);
1615
						$outputFormat = 'png';
1616
						$ImageCreateFunction = 'imagecreatefrompng';
1617
						$this->is_alpha = true;
1618
						$this->useRawIMoutput = false;
1619
						break;
1620
				}
1621
				if (!function_exists(@$ImageCreateFunction)) {
1622
					// ImageMagickThumbnailToGD() depends on imagecreatefrompng/imagecreatefromgif
1623
					//$this->DebugMessage('ImageMagickThumbnailToGD() aborting because '.@$ImageCreateFunction.'() is not available', __FILE__, __LINE__);
1624
					$this->useRawIMoutput = true;
1625
					//return false;
1626
				}
1627
			} else {
1628
				$outputFormat = 'png';
1629
				$ImageCreateFunction = 'imagecreatefrompng';
1630
				$this->is_alpha = true;
1631
				$this->useRawIMoutput = false;
1632
			}
1633
		}
1634
1635
		// http://freealter.org/doc_distrib/ImageMagick-5.1.1/www/convert.html
1636
		if (!$this->sourceFilename && $this->rawImageData) {
1637
			$this->SourceDataToTempFile();
1638
		}
1639
		if (!$this->sourceFilename) {
1640
			$this->DebugMessage('ImageMagickThumbnailToGD() aborting because $this->sourceFilename is empty', __FILE__, __LINE__);
1641
			$this->useRawIMoutput = false;
1642
			return false;
1643
		}
1644
		if ($this->issafemode) {
1645
			$this->DebugMessage('ImageMagickThumbnailToGD() aborting because safe_mode is enabled', __FILE__, __LINE__);
1646
			$this->useRawIMoutput = false;
1647
			return false;
1648
		}
1649
// TO BE FIXED
1650
//if (true) {
1651
//	$this->DebugMessage('ImageMagickThumbnailToGD() aborting it is broken right now', __FILE__, __LINE__);
1652
//	$this->useRawIMoutput = false;
1653
//	return false;
1654
//}
1655
1656
		$commandline = $this->ImageMagickCommandlineBase();
1657
		if ($commandline) {
1658
			if ($IMtempfilename = $this->phpThumb_tempnam()) {
1659
				$IMtempfilename = $this->realPathSafe($IMtempfilename);
1660
1661
				$IMuseExplicitImageOutputDimensions = false;
1662
				if ($this->ImageMagickSwitchAvailable('thumbnail') && $this->config_imagemagick_use_thumbnail) {
1663
					$IMresizeParameter = 'thumbnail';
1664
				} else {
1665
					$IMresizeParameter = 'resize';
1666
1667
					// some (older? around 2002) versions of IM won't accept "-resize 100x" but require "-resize 100x100"
1668
					$commandline_test = $this->ImageMagickCommandlineBase().' logo: -resize 1x '.phpthumb_functions::escapeshellarg_replacement($IMtempfilename).' 2>&1';
1669
					$IMresult_test = phpthumb_functions::SafeExec($commandline_test);
1670
					$IMuseExplicitImageOutputDimensions = preg_match('#image dimensions are zero#i', $IMresult_test);
0 ignored issues
show
Bug introduced by
It seems like $IMresult_test can also be of type false; however, parameter $subject of preg_match() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

1670
					$IMuseExplicitImageOutputDimensions = preg_match('#image dimensions are zero#i', /** @scrutinizer ignore-type */ $IMresult_test);
Loading history...
1671
					$this->DebugMessage('IMuseExplicitImageOutputDimensions = '.intval($IMuseExplicitImageOutputDimensions), __FILE__, __LINE__);
1672
					if ($fp_im_temp = @fopen($IMtempfilename, 'wb')) {
1673
						// erase temp image so ImageMagick logo doesn't get output if other processing fails
1674
						fclose($fp_im_temp);
1675
						@chmod($IMtempfilename, $this->getParameter('config_file_create_mask'));
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition for chmod(). This can introduce security issues, and is generally not recommended. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unhandled  annotation

1675
						/** @scrutinizer ignore-unhandled */ @chmod($IMtempfilename, $this->getParameter('config_file_create_mask'));

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...
1676
					}
1677
				}
1678
1679
1680
				if (!is_null($this->dpi) && $this->ImageMagickSwitchAvailable('density')) {
1681
					// for vector source formats only (WMF, PDF, etc)
1682
					$commandline .= ' -flatten';
1683
					$commandline .= ' -density '.phpthumb_functions::escapeshellarg_replacement($this->dpi);
1684
				}
1685
				ob_start();
1686
				$getimagesize = getimagesize($this->sourceFilename);
1687
				$GetImageSizeError = ob_get_contents();
1688
				ob_end_clean();
1689
				if (is_array($getimagesize)) {
1690
					$this->DebugMessage('getimagesize('.$this->sourceFilename.') SUCCEEDED: '.print_r($getimagesize, true), __FILE__, __LINE__);
1691
				} else {
1692
					$this->DebugMessage('getimagesize('.$this->sourceFilename.') FAILED with error "'.$GetImageSizeError.'"', __FILE__, __LINE__);
1693
				}
1694
				if (is_array($getimagesize)) {
1695
					$this->DebugMessage('getimagesize('.$this->sourceFilename.') returned [w='.$getimagesize[0].';h='.$getimagesize[1].';f='.$getimagesize[2].']', __FILE__, __LINE__);
1696
					$this->source_width  = $getimagesize[0];
1697
					$this->source_height = $getimagesize[1];
1698
					$this->DebugMessage('source dimensions set to '.$this->source_width.'x'.$this->source_height, __FILE__, __LINE__);
1699
					$this->SetOrientationDependantWidthHeight();
1700
1701 View Code Duplication
					if (!preg_match('#('.implode('|', $this->AlphaCapableFormats).')#i', $outputFormat)) {
1702
						// not a transparency-capable format
1703
						$commandline .= ' -background '.phpthumb_functions::escapeshellarg_replacement('#'.($this->bg ? $this->bg : 'FFFFFF'));
1704
						if ($getimagesize[2] == IMAGETYPE_GIF) {
1705
							$commandline .= ' -flatten';
1706
						}
1707
					}
1708
					if ($getimagesize[2] == IMAGETYPE_GIF) {
1709
						$commandline .= ' -coalesce'; // may be needed for animated GIFs
1710
					}
1711
					if ($this->source_width || $this->source_height) {
1712
						if ($this->zc) {
1713
1714
							$borderThickness = 0;
1715
							if (!empty($this->fltr)) {
1716
								foreach ($this->fltr as $key => $value) {
1717
									if (preg_match('#^bord\|([0-9]+)#', $value, $matches)) {
1718
										$borderThickness = $matches[1];
1719
										break;
1720
									}
1721
								}
1722
							}
1723
							$wAll = intval(max($this->w, $this->wp, $this->wl, $this->ws)) - (2 * $borderThickness);
1724
							$hAll = intval(max($this->h, $this->hp, $this->hl, $this->hs)) - (2 * $borderThickness);
1725
							$imAR = $this->source_width / $this->source_height;
1726
							$zcAR = (($wAll && $hAll) ? $wAll / $hAll : 1);
1727
							$side  = phpthumb_functions::nonempty_min($this->source_width, $this->source_height, max($wAll, $hAll));
1728
							$sideX = phpthumb_functions::nonempty_min($this->source_width,                       $wAll, round($hAll * $zcAR));
0 ignored issues
show
Unused Code introduced by
The assignment to $sideX is dead and can be removed.
Loading history...
1729
							$sideY = phpthumb_functions::nonempty_min(                     $this->source_height, $hAll, round($wAll / $zcAR));
1730
1731
							$thumbnailH = round(max($sideY, ($sideY * $zcAR) / $imAR));
1732
							$commandline .= ' -'.$IMresizeParameter.' '.phpthumb_functions::escapeshellarg_replacement(($IMuseExplicitImageOutputDimensions ? $thumbnailH : '').'x'.$thumbnailH);
1733
1734
							switch (strtoupper($this->zc)) {
1735
								case 'T':
1736
									$commandline .= ' -gravity north';
1737
									break;
1738
								case 'B':
1739
									$commandline .= ' -gravity south';
1740
									break;
1741
								case 'L':
1742
									$commandline .= ' -gravity west';
1743
									break;
1744
								case 'R':
1745
									$commandline .= ' -gravity east';
1746
									break;
1747
								case 'TL':
1748
									$commandline .= ' -gravity northwest';
1749
									break;
1750
								case 'TR':
1751
									$commandline .= ' -gravity northeast';
1752
									break;
1753
								case 'BL':
1754
									$commandline .= ' -gravity southwest';
1755
									break;
1756
								case 'BR':
1757
									$commandline .= ' -gravity southeast';
1758
									break;
1759
								case '1':
1760
								case 'C':
1761
								default:
1762
									$commandline .= ' -gravity center';
1763
									break;
1764
							}
1765
1766
							if (($wAll > 0) && ($hAll > 0)) {
1767
								$commandline .= ' -crop '.phpthumb_functions::escapeshellarg_replacement($wAll.'x'.$hAll.'+0+0');
1768
							} else {
1769
								$commandline .= ' -crop '.phpthumb_functions::escapeshellarg_replacement($side.'x'.$side.'+0+0');
1770
							}
1771
							if ($this->ImageMagickSwitchAvailable('repage')) {
1772
								$commandline .= ' +repage';
1773
							} else {
1774
								$this->DebugMessage('Skipping "+repage" because ImageMagick (v'.$this->ImageMagickVersion().') does not support it', __FILE__, __LINE__);
1775
							}
1776
1777
						} elseif ($this->sw || $this->sh || $this->sx || $this->sy) {
1778
1779
							$crop_param   = '';
1780
							$crop_param  .=     ($this->sw ? (($this->sw < 2) ? round($this->sw * $this->source_width)  : $this->sw) : $this->source_width);
1781
							$crop_param  .= 'x'.($this->sh ? (($this->sh < 2) ? round($this->sh * $this->source_height) : $this->sh) : $this->source_height);
1782
							$crop_param  .= '+'.(($this->sx < 2) ? round($this->sx * $this->source_width)  : $this->sx);
1783
							$crop_param  .= '+'.(($this->sy < 2) ? round($this->sy * $this->source_height) : $this->sy);
1784
// TO BE FIXED
1785
// makes 1x1 output
1786
// http://trainspotted.com/phpThumb/phpThumb.php?src=/content/CNR/47/CNR-4728-LD-L-20110723-898.jpg&w=100&h=100&far=1&f=png&fltr[]=lvl&sx=0.05&sy=0.25&sw=0.92&sh=0.42
1787
// '/usr/bin/convert' -density 150 -thumbnail 100x100 -contrast-stretch '0.1%' '/var/www/vhosts/trainspotted.com/httpdocs/content/CNR/47/CNR-4728-LD-L-20110723-898.jpg[0]' png:'/var/www/vhosts/trainspotted.com/httpdocs/phpThumb/_cache/pThumbIIUlvj'
1788
							$commandline .= ' -crop '.phpthumb_functions::escapeshellarg_replacement($crop_param);
1789
1790
							// this is broken for aoe=1, but unsure how to fix. Send advice to [email protected]
1791
							if ($this->w || $this->h) {
1792
								//if ($this->ImageMagickSwitchAvailable('repage')) {
1793
if (false) {
0 ignored issues
show
Bug introduced by
Avoid IF statements that are always true or false
Loading history...
1794
// TO BE FIXED
1795
// newer versions of ImageMagick require -repage <geometry>
1796
									$commandline .= ' -repage';
1797
								} else {
1798
									$this->DebugMessage('Skipping "-repage" because ImageMagick (v'.$this->ImageMagickVersion().') does not support it', __FILE__, __LINE__);
1799
								}
1800 View Code Duplication
								if ($IMuseExplicitImageOutputDimensions) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $IMuseExplicitImageOutputDimensions of type integer|false is loosely compared to true; this is ambiguous if the integer can be 0. 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 integer values, zero is a special case, in particular the following results might be unexpected:

0   == false // true
0   == null  // true
123 == false // false
123 == null  // false

// It is often better to use strict comparison
0 === false // false
0 === null  // false
Loading history...
1801
									if ($this->w && !$this->h) {
1802
										$this->h = ceil($this->w / ($this->source_width / $this->source_height));
1803
									} elseif ($this->h && !$this->w) {
1804
										$this->w = ceil($this->h * ($this->source_width / $this->source_height));
1805
									}
1806
								}
1807
								$commandline .= ' -'.$IMresizeParameter.' '.phpthumb_functions::escapeshellarg_replacement($this->w.'x'.$this->h);
1808
							}
1809
1810
						} else {
1811
1812
							if ($this->iar && (intval($this->w) > 0) && (intval($this->h) > 0)) {
1813
								list($nw, $nh) = phpthumb_functions::TranslateWHbyAngle($this->w, $this->h, $this->ra);
1814
								$nw = ((round($nw) != 0) ? round($nw) : '');
1815
								$nh = ((round($nh) != 0) ? round($nh) : '');
1816
								$commandline .= ' -'.$IMresizeParameter.' '.phpthumb_functions::escapeshellarg_replacement($nw.'x'.$nh.'!');
1817
							} else {
1818
								$this->w = ((($this->aoe || $this->far) && $this->w) ? $this->w : ($this->w ? phpthumb_functions::nonempty_min($this->w, $getimagesize[0]) : ''));
1819
								$this->h = ((($this->aoe || $this->far) && $this->h) ? $this->h : ($this->h ? phpthumb_functions::nonempty_min($this->h, $getimagesize[1]) : ''));
1820
								if ($this->w || $this->h) {
1821 View Code Duplication
									if ($IMuseExplicitImageOutputDimensions) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $IMuseExplicitImageOutputDimensions of type integer|false is loosely compared to true; this is ambiguous if the integer can be 0. 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 integer values, zero is a special case, in particular the following results might be unexpected:

0   == false // true
0   == null  // true
123 == false // false
123 == null  // false

// It is often better to use strict comparison
0 === false // false
0 === null  // false
Loading history...
1822
										if ($this->w && !$this->h) {
1823
											$this->h = ceil($this->w / ($this->source_width / $this->source_height));
1824
										} elseif ($this->h && !$this->w) {
1825
											$this->w = ceil($this->h * ($this->source_width / $this->source_height));
1826
										}
1827
									}
1828
									list($nw, $nh) = phpthumb_functions::TranslateWHbyAngle($this->w, $this->h, $this->ra);
1829
									$nw = ((round($nw) != 0) ? round($nw) : '');
1830
									$nh = ((round($nh) != 0) ? round($nh) : '');
1831
									$commandline .= ' -'.$IMresizeParameter.' '.phpthumb_functions::escapeshellarg_replacement($nw.'x'.$nh);
1832
								}
1833
							}
1834
						}
1835
					}
1836
1837
				} else {
1838
1839
					$this->DebugMessage('getimagesize('.$this->sourceFilename.') failed', __FILE__, __LINE__);
1840
					if ($this->w || $this->h) {
1841
						$exactDimensionsBang = (($this->iar && (intval($this->w) > 0) && (intval($this->h) > 0)) ? '!' : '');
1842
						if ($IMuseExplicitImageOutputDimensions) {
1843
							// unknown source aspect ratio, just put large number and hope IM figures it out
1844
							$commandline .= ' -'.$IMresizeParameter.' '.phpthumb_functions::escapeshellarg_replacement(($this->w ? $this->w : '9999').'x'.($this->h ? $this->h : '9999').$exactDimensionsBang);
1845
						} else {
1846
							$commandline .= ' -'.$IMresizeParameter.' '.phpthumb_functions::escapeshellarg_replacement($this->w.'x'.$this->h.$exactDimensionsBang);
1847
						}
1848
					}
1849
1850
				}
1851
1852
				if ($this->ra) {
1853
					$this->ra = intval($this->ra);
1854
					if ($this->ImageMagickSwitchAvailable('rotate')) {
1855
						if (!preg_match('#('.implode('|', $this->AlphaCapableFormats).')#i', $outputFormat) || phpthumb_functions::version_compare_replacement($this->ImageMagickVersion(), '6.3.7', '>=')) {
1856
							$this->DebugMessage('Using ImageMagick rotate', __FILE__, __LINE__);
1857
							$commandline .= ' -rotate '.phpthumb_functions::escapeshellarg_replacement($this->ra);
1858
							if (($this->ra % 90) != 0) {
1859 View Code Duplication
								if (preg_match('#('.implode('|', $this->AlphaCapableFormats).')#i', $outputFormat)) {
1860
									// alpha-capable format
1861
									$commandline .= ' -background rgba(255,255,255,0)';
1862
								} else {
1863
									$commandline .= ' -background '.phpthumb_functions::escapeshellarg_replacement('#'.($this->bg ? $this->bg : 'FFFFFF'));
1864
								}
1865
							}
1866
							$this->ra = 0;
1867
						} else {
1868
							$this->DebugMessage('Not using ImageMagick rotate because alpha background buggy before v6.3.7', __FILE__, __LINE__);
1869
						}
1870
					} else {
1871
						$this->DebugMessage('Not using ImageMagick rotate because not supported', __FILE__, __LINE__);
1872
					}
1873
				}
1874
1875
				$successfullyProcessedFilters = array();
1876
				foreach ($this->fltr as $filterkey => $filtercommand) {
1877
					@list($command, $parameter) = explode('|', $filtercommand, 2);
1878
					switch ($command) {
1879
						case 'brit':
1880
							if ($this->ImageMagickSwitchAvailable('modulate')) {
1881
								$commandline .= ' -modulate '.phpthumb_functions::escapeshellarg_replacement((100 + intval($parameter)).',100,100');
1882
								$successfullyProcessedFilters[] = $filterkey;
1883
							}
1884
							break;
1885
1886
						case 'cont':
1887
							if ($this->ImageMagickSwitchAvailable('contrast')) {
1888
								$contDiv10 = round(intval($parameter) / 10);
1889
								if ($contDiv10 > 0) {
1890
									$contDiv10 = min($contDiv10, 100);
1891
									for ($i = 0; $i < $contDiv10; $i++) {
1892
										$commandline .= ' -contrast'; // increase contrast by 10%
1893
									}
1894
								} elseif ($contDiv10 < 0) {
1895
									$contDiv10 = max($contDiv10, -100);
1896
									for ($i = $contDiv10; $i < 0; $i++) {
1897
										$commandline .= ' +contrast'; // decrease contrast by 10%
1898
									}
1899
								} else {
0 ignored issues
show
Unused Code introduced by
This else statement is empty and can be removed.

This check looks for the else branches 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 else branches can be removed.

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

could be turned into

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

This is much more concise to read.

Loading history...
1900
									// do nothing
1901
								}
1902
								$successfullyProcessedFilters[] = $filterkey;
1903
							}
1904
							break;
1905
1906 View Code Duplication
						case 'ds':
1907
							if ($this->ImageMagickSwitchAvailable(array('colorspace', 'modulate'))) {
1908
								if ($parameter == 100) {
1909
									$commandline .= ' -colorspace GRAY';
1910
									$commandline .= ' -modulate 100,0,100';
1911
								} else {
1912
									$commandline .= ' -modulate '.phpthumb_functions::escapeshellarg_replacement('100,'.(100 - intval($parameter)).',100');
1913
								}
1914
								$successfullyProcessedFilters[] = $filterkey;
1915
							}
1916
							break;
1917
1918 View Code Duplication
						case 'sat':
1919
							if ($this->ImageMagickSwitchAvailable(array('colorspace', 'modulate'))) {
1920
								if ($parameter == -100) {
1921
									$commandline .= ' -colorspace GRAY';
1922
									$commandline .= ' -modulate 100,0,100';
1923
								} else {
1924
									$commandline .= ' -modulate '.phpthumb_functions::escapeshellarg_replacement('100,'.(100 + intval($parameter)).',100');
1925
								}
1926
								$successfullyProcessedFilters[] = $filterkey;
1927
							}
1928
							break;
1929
1930
						case 'gray':
1931
							if ($this->ImageMagickSwitchAvailable(array('colorspace', 'modulate'))) {
1932
								$commandline .= ' -colorspace GRAY';
1933
								$commandline .= ' -modulate 100,0,100';
1934
								$successfullyProcessedFilters[] = $filterkey;
1935
							}
1936
							break;
1937
1938
						case 'clr':
1939
							if ($this->ImageMagickSwitchAvailable(array('fill', 'colorize'))) {
1940
								@list($amount, $color) = explode('|', $parameter);
1941
								$commandline .= ' -fill '.phpthumb_functions::escapeshellarg_replacement('#'.preg_replace('#[^0-9A-F]#i', '', $color));
1942
								$commandline .= ' -colorize '.phpthumb_functions::escapeshellarg_replacement(min(max(intval($amount), 0), 100));
1943
							}
1944
							break;
1945
1946
						case 'sep':
1947
							if ($this->ImageMagickSwitchAvailable('sepia-tone')) {
1948
								@list($amount, $color) = explode('|', $parameter);
1949
								$amount = ($amount ? $amount : 80);
1950
								if (!$color) {
1951
									$commandline .= ' -sepia-tone '.phpthumb_functions::escapeshellarg_replacement(min(max(intval($amount), 0), 100).'%');
1952
									$successfullyProcessedFilters[] = $filterkey;
1953
								}
1954
							}
1955
							break;
1956
1957 View Code Duplication
						case 'gam':
1958
							@list($amount) = explode('|', $parameter);
1959
							$amount = min(max(floatval($amount), 0.001), 10);
1960
							if (number_format($amount, 3) != '1.000') {
1961
								if ($this->ImageMagickSwitchAvailable('gamma')) {
1962
									$commandline .= ' -gamma '.phpthumb_functions::escapeshellarg_replacement($amount);
1963
									$successfullyProcessedFilters[] = $filterkey;
1964
								}
1965
							}
1966
							break;
1967
1968
						case 'neg':
1969
							if ($this->ImageMagickSwitchAvailable('negate')) {
1970
								$commandline .= ' -negate';
1971
								$successfullyProcessedFilters[] = $filterkey;
1972
							}
1973
							break;
1974
1975
						case 'th':
1976
							@list($amount) = explode('|', $parameter);
1977
							if ($this->ImageMagickSwitchAvailable(array('threshold', 'dither', 'monochrome'))) {
1978
								$commandline .= ' -threshold '.phpthumb_functions::escapeshellarg_replacement(round(min(max(intval($amount), 0), 255) / 2.55).'%');
1979
								$commandline .= ' -dither';
1980
								$commandline .= ' -monochrome';
1981
								$successfullyProcessedFilters[] = $filterkey;
1982
							}
1983
							break;
1984
1985
						case 'rcd':
1986
							if ($this->ImageMagickSwitchAvailable(array('colors', 'dither'))) {
1987
								@list($colors, $dither) = explode('|', $parameter);
1988
								$colors = ($colors                ?  (int) $colors : 256);
1989
								$dither  = ((strlen($dither) > 0) ? (bool) $dither : true);
1990
								$commandline .= ' -colors '.phpthumb_functions::escapeshellarg_replacement(max($colors, 8)); // ImageMagick will otherwise fail with "cannot quantize to fewer than 8 colors"
1991
								$commandline .= ($dither ? ' -dither' : ' +dither');
1992
								$successfullyProcessedFilters[] = $filterkey;
1993
							}
1994
							break;
1995
1996
						case 'flip':
1997
							if ($this->ImageMagickSwitchAvailable(array('flip', 'flop'))) {
1998
								if (strpos(strtolower($parameter), 'x') !== false) {
1999
									$commandline .= ' -flop';
2000
								}
2001
								if (strpos(strtolower($parameter), 'y') !== false) {
2002
									$commandline .= ' -flip';
2003
								}
2004
								$successfullyProcessedFilters[] = $filterkey;
2005
							}
2006
							break;
2007
2008
						case 'edge':
2009
							if ($this->ImageMagickSwitchAvailable('edge')) {
2010
								$parameter = (!empty($parameter) ? $parameter : 2);
2011
								$commandline .= ' -edge '.phpthumb_functions::escapeshellarg_replacement(!empty($parameter) ? intval($parameter) : 1);
2012
								$successfullyProcessedFilters[] = $filterkey;
2013
							}
2014
							break;
2015
2016
						case 'emb':
2017
							if ($this->ImageMagickSwitchAvailable(array('emboss', 'negate'))) {
2018
								$parameter = (!empty($parameter) ? $parameter : 2);
2019
								$commandline .= ' -emboss '.phpthumb_functions::escapeshellarg_replacement(intval($parameter));
2020
								if ($parameter < 2) {
2021
									$commandline .= ' -negate'; // ImageMagick negates the image for some reason with '-emboss 1';
2022
								}
2023
								$successfullyProcessedFilters[] = $filterkey;
2024
							}
2025
							break;
2026
2027
						case 'lvl':
2028
							@list($band, $method, $threshold) = explode('|', $parameter);
2029
							$band      = ($band ? preg_replace('#[^RGBA\\*]#', '', strtoupper($band))       : '*');
2030
							$method    = ((strlen($method) > 0)    ? intval($method)                        :   2);
2031
							$threshold = ((strlen($threshold) > 0) ? min(max(floatval($threshold), 0), 100) : 0.1);
2032
2033
							$band = preg_replace('#[^RGBA\\*]#', '', strtoupper($band));
2034
2035
							if (($method > 1) && !$this->ImageMagickSwitchAvailable(array('channel', 'contrast-stretch'))) {
2036
								// Because ImageMagick processing happens before PHP-GD filters, and because some
2037
								// clipping is involved in the "lvl" filter, if "lvl" happens before "wb" then the
2038
								// "wb" filter will have (almost) no effect. Therefore, if "wb" is enabled then
2039
								// force the "lvl" filter to be processed by GD, not ImageMagick.
2040
								foreach ($this->fltr as $fltr_key => $fltr_value) {
2041
									list($fltr_cmd) = explode('|', $fltr_value);
2042
									if ($fltr_cmd == 'wb') {
2043
										$this->DebugMessage('Setting "lvl" filter method to "0" (from "'.$method.'") because white-balance filter also enabled', __FILE__, __LINE__);
2044
										$method = 0;
2045
									}
2046
								}
2047
							}
2048
2049
							switch ($method) {
2050
								case 0: // internal RGB
2051
								case 1: // internal grayscale
2052
									break;
2053
								case 2: // ImageMagick "contrast-stretch"
2054
									if ($this->ImageMagickSwitchAvailable('contrast-stretch')) {
2055
										if ($band != '*') {
2056
											$commandline .= ' -channel '.phpthumb_functions::escapeshellarg_replacement(strtoupper($band));
2057
										}
2058
										$threshold = preg_replace('#[^0-9\\.]#', '', $threshold); // should be unneccesary, but just to be double-sure
2059
										//$commandline .= ' -contrast-stretch '.phpthumb_functions::escapeshellarg_replacement($threshold.'%');
2060
										$commandline .= ' -contrast-stretch \''.$threshold.'%\'';
2061
										if ($band != '*') {
2062
											$commandline .= ' +channel';
2063
										}
2064
										$successfullyProcessedFilters[] = $filterkey;
2065
									}
2066
									break;
2067
								case 3: // ImageMagick "normalize"
2068
									if ($this->ImageMagickSwitchAvailable('normalize')) {
2069
										if ($band != '*') {
2070
											$commandline .= ' -channel '.phpthumb_functions::escapeshellarg_replacement(strtoupper($band));
2071
										}
2072
										$commandline .= ' -normalize';
2073
										if ($band != '*') {
2074
											$commandline .= ' +channel';
2075
										}
2076
										$successfullyProcessedFilters[] = $filterkey;
2077
									}
2078
									break;
2079
								default:
2080
									$this->DebugMessage('unsupported method ('.$method.') for "lvl" filter', __FILE__, __LINE__);
2081
									break;
2082
							}
2083
							if (isset($this->fltr[$filterkey]) && ($method > 1)) {
2084
								$this->fltr[$filterkey] = $command.'|'.$band.'|0|'.$threshold;
2085
								$this->DebugMessage('filter "lvl" remapped from method "'.$method.'" to method "0" because ImageMagick support is missing', __FILE__, __LINE__);
2086
							}
2087
							break;
2088
2089
						case 'wb':
2090
							if ($this->ImageMagickSwitchAvailable(array('channel', 'contrast-stretch'))) {
2091
								@list($threshold) = explode('|', $parameter);
2092
								$threshold = (!empty($threshold) ? min(max(floatval($threshold), 0), 100) : 0.1);
2093
								$threshold = preg_replace('#[^0-9\\.]#', '', $threshold); // should be unneccesary, but just to be double-sure
2094
								//$commandline .= ' -channel R -contrast-stretch '.phpthumb_functions::escapeshellarg_replacement($threshold.'%'); // doesn't work on Windows because most versions of PHP do not properly
2095
								//$commandline .= ' -channel G -contrast-stretch '.phpthumb_functions::escapeshellarg_replacement($threshold.'%'); // escape special characters (such as %) and just replace them with spaces
2096
								//$commandline .= ' -channel B -contrast-stretch '.phpthumb_functions::escapeshellarg_replacement($threshold.'%'); // https://bugs.php.net/bug.php?id=43261
2097
								$commandline .= ' -channel R -contrast-stretch \''.$threshold.'%\'';
2098
								$commandline .= ' -channel G -contrast-stretch \''.$threshold.'%\'';
2099
								$commandline .= ' -channel B -contrast-stretch \''.$threshold.'%\'';
2100
								$commandline .= ' +channel';
2101
								$successfullyProcessedFilters[] = $filterkey;
2102
							}
2103
							break;
2104
2105 View Code Duplication
						case 'blur':
2106
							if ($this->ImageMagickSwitchAvailable('blur')) {
2107
								@list($radius) = explode('|', $parameter);
2108
								$radius = (!empty($radius) ? min(max(intval($radius), 0), 25) : 1);
2109
								$commandline .= ' -blur '.phpthumb_functions::escapeshellarg_replacement($radius);
2110
								$successfullyProcessedFilters[] = $filterkey;
2111
							}
2112
							break;
2113
2114
						case 'gblr':
2115
							@list($radius) = explode('|', $parameter);
2116
							$radius = (!empty($radius) ? min(max(intval($radius), 0), 25) : 1);
2117
							// "-gaussian" changed to "-gaussian-blur" sometime around 2009
2118
							if ($this->ImageMagickSwitchAvailable('gaussian-blur')) {
2119
								$commandline .= ' -gaussian-blur '.phpthumb_functions::escapeshellarg_replacement($radius);
2120
								$successfullyProcessedFilters[] = $filterkey;
2121
							} elseif ($this->ImageMagickSwitchAvailable('gaussian')) {
2122
								$commandline .= ' -gaussian '.phpthumb_functions::escapeshellarg_replacement($radius);
2123
								$successfullyProcessedFilters[] = $filterkey;
2124
							}
2125
							break;
2126
2127
						case 'usm':
2128
							if ($this->ImageMagickSwitchAvailable('unsharp')) {
2129
								@list($amount, $radius, $threshold) = explode('|', $parameter);
2130
								$amount    = ($amount            ? min(max(intval($radius), 0), 255) : 80);
2131
								$radius    = ($radius            ? min(max(intval($radius), 0), 10)  : 0.5);
2132
								$threshold = (strlen($threshold) ? min(max(intval($radius), 0), 50)  : 3);
2133
								$commandline .= ' -unsharp '.phpthumb_functions::escapeshellarg_replacement(number_format(($radius * 2) - 1, 2, '.', '').'x1+'.number_format($amount / 100, 2, '.', '').'+'.number_format($threshold / 100, 2, '.', ''));
2134
								$successfullyProcessedFilters[] = $filterkey;
2135
							}
2136
							break;
2137
2138
						case 'bord':
2139
							if ($this->ImageMagickSwitchAvailable(array('border', 'bordercolor', 'thumbnail', 'crop'))) {
2140
								if (!$this->zc) {
2141
									@list($width, $rX, $rY, $color) = explode('|', $parameter);
2142
									$width = intval($width);
2143
									$rX    = intval($rX);
2144
									$rY    = intval($rY);
2145
									if ($width && !$rX && !$rY) {
2146
										if (!phpthumb_functions::IsHexColor($color)) {
2147
											$color = ((!empty($this->bc) && phpthumb_functions::IsHexColor($this->bc)) ? $this->bc : '000000');
2148
										}
2149
										$commandline .= ' -border '.phpthumb_functions::escapeshellarg_replacement(intval($width));
2150
										$commandline .= ' -bordercolor '.phpthumb_functions::escapeshellarg_replacement('#'.$color);
2151
2152
										if (preg_match('# \\-crop "([0-9]+)x([0-9]+)\\+0\\+0" #', $commandline, $matches)) {
2153
											$commandline = str_replace(' -crop "'.$matches[1].'x'.$matches[2].'+0+0" ', ' -crop '.phpthumb_functions::escapeshellarg_replacement(($matches[1] - (2 * $width)).'x'.($matches[2] - (2 * $width)).'+0+0').' ', $commandline);
2154
										} elseif (preg_match('# \\-'.$IMresizeParameter.' "([0-9]+)x([0-9]+)" #', $commandline, $matches)) {
2155
											$commandline = str_replace(' -'.$IMresizeParameter.' "'.$matches[1].'x'.$matches[2].'" ', ' -'.$IMresizeParameter.' '.phpthumb_functions::escapeshellarg_replacement(($matches[1] - (2 * $width)).'x'.($matches[2] - (2 * $width))).' ', $commandline);
2156
										}
2157
										$successfullyProcessedFilters[] = $filterkey;
2158
									}
2159
								}
2160
							}
2161
							break;
2162
2163
						case 'crop':
2164
							break;
2165
2166
						case 'sblr':
2167
							break;
2168
2169
						case 'mean':
2170
							break;
2171
2172
						case 'smth':
2173
							break;
2174
2175
						case 'bvl':
2176
							break;
2177
2178
						case 'wmi':
2179
							break;
2180
2181
						case 'wmt':
2182
							break;
2183
2184
						case 'over':
2185
							break;
2186
2187
						case 'hist':
2188
							break;
2189
2190
						case 'fram':
2191
							break;
2192
2193
						case 'drop':
2194
							break;
2195
2196
						case 'mask':
2197
							break;
2198
2199
						case 'elip':
2200
							break;
2201
2202
						case 'ric':
2203
							break;
2204
2205
						case 'stc':
2206
							break;
2207
2208
						case 'size':
2209
							break;
2210
2211
						default:
2212
							$this->DebugMessage('Unknown $this->fltr['.$filterkey.'] ('.$filtercommand.') -- deleting filter command', __FILE__, __LINE__);
2213
							$successfullyProcessedFilters[] = $filterkey;
2214
							break;
2215
					}
2216
					if (!isset($this->fltr[$filterkey])) {
2217
						$this->DebugMessage('Processed $this->fltr['.$filterkey.'] ('.$filtercommand.') with ImageMagick', __FILE__, __LINE__);
2218
					} else {
2219
						$this->DebugMessage('Skipping $this->fltr['.$filterkey.'] ('.$filtercommand.') with ImageMagick', __FILE__, __LINE__);
2220
					}
2221
				}
2222
				$this->DebugMessage('Remaining $this->fltr after ImageMagick: ('.$this->phpThumbDebugVarDump($this->fltr).')', __FILE__, __LINE__);
2223
				if (count($this->fltr) > 0) {
2224
					$this->useRawIMoutput = false;
2225
				}
2226
2227
				if (preg_match('#jpe?g#i', $outputFormat) && $this->q) {
2228
					if ($this->ImageMagickSwitchAvailable(array('quality', 'interlace'))) {
2229
						$commandline .= ' -quality '.phpthumb_functions::escapeshellarg_replacement($this->thumbnailQuality);
2230
						if ($this->config_output_interlace) {
2231
							// causes weird things with animated GIF... leave for JPEG only
2232
							$commandline .= ' -interlace line '; // Use Line or Plane to create an interlaced PNG or GIF or progressive JPEG image
2233
						}
2234
					}
2235
				}
2236
				$commandline .= ' '.phpthumb_functions::escapeshellarg_replacement(preg_replace('#[/\\\\]#', DIRECTORY_SEPARATOR, $this->sourceFilename).(($outputFormat == 'gif') ? '' : '['.intval($this->sfn).']')); // [0] means first frame of (GIF) animation, can be ignored
2237
				$commandline .= ' '.$outputFormat.':'.phpthumb_functions::escapeshellarg_replacement($IMtempfilename);
2238
				if (!$this->iswindows) {
2239
					$commandline .= ' 2>&1';
2240
				}
2241
				$this->DebugMessage('ImageMagick called as ('.$commandline.')', __FILE__, __LINE__);
2242
				$IMresult = phpthumb_functions::SafeExec($commandline);
2243
				clearstatcache();
2244
				if (!@file_exists($IMtempfilename) || !@filesize($IMtempfilename)) {
2245
					$this->FatalError('ImageMagick failed with message ('.trim($IMresult).')');
0 ignored issues
show
Bug introduced by
It seems like $IMresult can also be of type false; however, parameter $str of trim() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

2245
					$this->FatalError('ImageMagick failed with message ('.trim(/** @scrutinizer ignore-type */ $IMresult).')');
Loading history...
2246
					$this->DebugMessage('ImageMagick failed with message ('.trim($IMresult).')', __FILE__, __LINE__);
2247
					if ($this->iswindows && !$IMresult) {
2248
						$this->DebugMessage('Check to make sure that PHP has read+write permissions to "'.dirname($IMtempfilename).'"', __FILE__, __LINE__);
2249
					}
2250
2251
				} else {
2252
2253
					foreach ($successfullyProcessedFilters as $dummy => $filterkey) {
2254
						unset($this->fltr[$filterkey]);
2255
					}
2256
					$this->IMresizedData = file_get_contents($IMtempfilename);
2257
					$getimagesize_imresized = @getimagesize($IMtempfilename);
2258
					$this->DebugMessage('getimagesize('.$IMtempfilename.') returned [w='.$getimagesize_imresized[0].';h='.$getimagesize_imresized[1].';f='.$getimagesize_imresized[2].']', __FILE__, __LINE__);
2259
					if (($this->config_max_source_pixels > 0) && (($getimagesize_imresized[0] * $getimagesize_imresized[1]) > $this->config_max_source_pixels)) {
2260
						$this->DebugMessage('skipping ImageMagickThumbnailToGD::'.$ImageCreateFunction.'() because IM output is too large ('.$getimagesize_imresized[0].'x'.$getimagesize_imresized[0].' = '.($getimagesize_imresized[0] * $getimagesize_imresized[1]).' > '.$this->config_max_source_pixels.')', __FILE__, __LINE__);
2261
					} elseif (function_exists(@$ImageCreateFunction) && ($this->gdimg_source = @$ImageCreateFunction($IMtempfilename))) {
2262
						$this->source_width  = imagesx($this->gdimg_source);
2263
						$this->source_height = imagesy($this->gdimg_source);
2264
						$this->DebugMessage('ImageMagickThumbnailToGD::'.$ImageCreateFunction.'() succeeded, $this->gdimg_source is now ('.$this->source_width.'x'.$this->source_height.')', __FILE__, __LINE__);
2265
						$this->DebugMessage('ImageMagickThumbnailToGD() returning $this->IMresizedData ('.strlen($this->IMresizedData).' bytes)', __FILE__, __LINE__);
2266
					} else {
2267
						$this->useRawIMoutput = true;
2268
						$this->DebugMessage('$this->useRawIMoutput set to TRUE because '.@$ImageCreateFunction.'('.$IMtempfilename.') failed', __FILE__, __LINE__);
2269
					}
2270 View Code Duplication
					if (file_exists($IMtempfilename)) {
2271
						$this->DebugMessage('deleting "'.$IMtempfilename.'"', __FILE__, __LINE__);
2272
						@unlink($IMtempfilename);
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition for unlink(). This can introduce security issues, and is generally not recommended. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unhandled  annotation

2272
						/** @scrutinizer ignore-unhandled */ @unlink($IMtempfilename);

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...
2273
					}
2274
					return true;
2275
2276
				}
2277 View Code Duplication
				if (file_exists($IMtempfilename)) {
2278
					$this->DebugMessage('deleting "'.$IMtempfilename.'"', __FILE__, __LINE__);
2279
					@unlink($IMtempfilename);
2280
				}
2281
2282
			} elseif ($this->issafemode) {
2283
				$this->DebugMessage('ImageMagickThumbnailToGD() aborting because PHP safe_mode is enabled and phpThumb_tempnam() failed', __FILE__, __LINE__);
2284
				$this->useRawIMoutput = false;
2285
			} else {
2286 View Code Duplication
				if (file_exists($IMtempfilename)) {
2287
					$this->DebugMessage('deleting "'.$IMtempfilename.'"', __FILE__, __LINE__);
2288
					@unlink($IMtempfilename);
2289
				}
2290
				$this->DebugMessage('ImageMagickThumbnailToGD() aborting, phpThumb_tempnam() failed', __FILE__, __LINE__);
2291
			}
2292
		} else {
2293
			$this->DebugMessage('ImageMagickThumbnailToGD() aborting because ImageMagickCommandlineBase() failed', __FILE__, __LINE__);
2294
		}
2295
		$this->useRawIMoutput = false;
2296
		return false;
2297
	}
2298
2299
2300
	function Rotate() {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
2301
		if ($this->ra || $this->ar) {
2302
			if (!function_exists('imagerotate')) {
2303
				$this->DebugMessage('!function_exists(imagerotate)', __FILE__, __LINE__);
2304
				return false;
2305
			}
2306 View Code Duplication
			if (!include_once(dirname(__FILE__).'/phpthumb.filters.php')) {
2307
				$this->DebugMessage('Error including "'.dirname(__FILE__).'/phpthumb.filters.php" which is required for applying filters ('.implode(';', $this->fltr).')', __FILE__, __LINE__);
2308
				return false;
2309
			}
2310
2311
			$this->config_background_hexcolor = ($this->bg ? $this->bg : $this->config_background_hexcolor);
2312
			if (!phpthumb_functions::IsHexColor($this->config_background_hexcolor)) {
2313
				return $this->ErrorImage('Invalid hex color string "'.$this->config_background_hexcolor.'" for parameter "bg"');
2314
			}
2315
2316
			$rotate_angle = 0;
2317
			if ($this->ra) {
2318
2319
				$rotate_angle = floatval($this->ra);
2320
2321
			} else {
2322
2323
				if ($this->ar == 'x') {
2324
					if (phpthumb_functions::version_compare_replacement(phpversion(), '4.2.0', '>=')) {
2325
						if ($this->sourceFilename) {
2326
							if (function_exists('exif_read_data')) {
2327
								if ($exif_data = @exif_read_data($this->sourceFilename, 'IFD0')) {
2328
									// http://sylvana.net/jpegcrop/exif_orientation.html
2329
									switch (@$exif_data['Orientation']) {
2330
										case 1:
2331
											$rotate_angle = 0;
2332
											break;
2333
										case 3:
2334
											$rotate_angle = 180;
2335
											break;
2336
										case 6:
2337
											$rotate_angle = 270;
2338
											break;
2339
										case 8:
2340
											$rotate_angle = 90;
2341
											break;
2342
2343
										default:
2344
											$this->DebugMessage('EXIF auto-rotate failed because unknown $exif_data[Orientation] "'.@$exif_data['Orientation'].'"', __FILE__, __LINE__);
2345
											return false;
2346
											break;
0 ignored issues
show
Unused Code introduced by
break is not strictly necessary here and could be removed.

The break statement is not necessary if it is preceded for example by a return statement:

switch ($x) {
    case 1:
        return 'foo';
        break; // This break is not necessary and can be left off.
}

If you would like to keep this construct to be consistent with other case statements, you can safely mark this issue as a false-positive.

Loading history...
2347
									}
2348
									$this->DebugMessage('EXIF auto-rotate set to '.$rotate_angle.' degrees ($exif_data[Orientation] = "'.@$exif_data['Orientation'].'")', __FILE__, __LINE__);
2349
								} else {
2350
									$this->DebugMessage('failed: exif_read_data('.$this->sourceFilename.')', __FILE__, __LINE__);
2351
									return false;
2352
								}
2353
							} else {
2354
								$this->DebugMessage('!function_exists(exif_read_data)', __FILE__, __LINE__);
2355
								return false;
2356
							}
2357
						} else {
2358
							$this->DebugMessage('Cannot auto-rotate from EXIF data because $this->sourceFilename is empty', __FILE__, __LINE__);
2359
							return false;
2360
						}
2361
					} else {
2362
						$this->DebugMessage('Cannot auto-rotate from EXIF data because PHP is less than v4.2.0 ('.phpversion().')', __FILE__, __LINE__);
2363
						return false;
2364
					}
2365
				} elseif (($this->ar == 'l') && ($this->source_height > $this->source_width)) {
2366
					$rotate_angle = 270;
2367
				} elseif (($this->ar == 'L') && ($this->source_height > $this->source_width)) {
2368
					$rotate_angle = 90;
2369
				} elseif (($this->ar == 'p') && ($this->source_width > $this->source_height)) {
2370
					$rotate_angle = 90;
2371
				} elseif (($this->ar == 'P') && ($this->source_width > $this->source_height)) {
2372
					$rotate_angle = 270;
2373
				}
2374
2375
			}
2376
			if ($rotate_angle % 90) {
2377
				$this->is_alpha = true;
2378
			}
2379
			phpthumb_filters::ImprovedImageRotate($this->gdimg_source, $rotate_angle, $this->config_background_hexcolor, $this->bg, $this);
2380
			$this->source_width  = imagesx($this->gdimg_source);
2381
			$this->source_height = imagesy($this->gdimg_source);
2382
		}
2383
		return true;
2384
	}
2385
2386
2387
	function FixedAspectRatio() {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
2388
		// optional fixed-dimension images (regardless of aspect ratio)
2389
2390
		if (!$this->far) {
2391
			// do nothing
2392
			return true;
2393
		}
2394
2395
		if (!$this->w || !$this->h) {
2396
			return false;
2397
		}
2398
		$this->thumbnail_width  = $this->w;
2399
		$this->thumbnail_height = $this->h;
2400
		$this->is_alpha = true;
2401
		if ($this->thumbnail_image_width >= $this->thumbnail_width) {
2402
2403
			$aspectratio = $this->thumbnail_image_height / $this->thumbnail_image_width;
2404
			if ($this->w) {
2405
				$this->thumbnail_image_height = round($this->thumbnail_image_width * $aspectratio);
2406
				$this->thumbnail_height = ($this->h ? $this->h : $this->thumbnail_image_height);
2407 View Code Duplication
			} elseif ($this->thumbnail_image_height < $this->thumbnail_height) {
2408
				$this->thumbnail_image_height = $this->thumbnail_height;
2409
				$this->thumbnail_image_width  = round($this->thumbnail_image_height / $aspectratio);
2410
			}
2411
2412
		} else {
2413
2414
			$aspectratio = $this->thumbnail_image_width / $this->thumbnail_image_height;
2415
			if ($this->h) {
2416
				$this->thumbnail_image_width = round($this->thumbnail_image_height * $aspectratio);
2417 View Code Duplication
			} elseif ($this->thumbnail_image_width < $this->thumbnail_width) {
2418
				$this->thumbnail_image_width = $this->thumbnail_width;
2419
				$this->thumbnail_image_height  = round($this->thumbnail_image_width / $aspectratio);
2420
			}
2421
2422
		}
2423
		return true;
2424
	}
2425
2426
2427
	function OffsiteDomainIsAllowed($hostname, $allowed_domains) {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
2428
		static $domain_is_allowed = array();
2429
		$hostname = strtolower($hostname);
2430
		if (!isset($domain_is_allowed[$hostname])) {
2431
			$domain_is_allowed[$hostname] = false;
2432
			foreach ($allowed_domains as $valid_domain) {
2433
				$starpos = strpos($valid_domain, '*');
2434
				if ($starpos !== false) {
2435
					$valid_domain = substr($valid_domain, $starpos + 1);
2436
					if (preg_match('#'.preg_quote($valid_domain).'$#', $hostname)) {
2437
						$domain_is_allowed[$hostname] = true;
2438
						break;
2439
					}
2440
				} else {
2441
					if (strtolower($valid_domain) === $hostname) {
2442
						$domain_is_allowed[$hostname] = true;
2443
						break;
2444
					}
2445
				}
2446
			}
2447
		}
2448
		return $domain_is_allowed[$hostname];
2449
	}
2450
2451
2452
	function AntiOffsiteLinking() {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
2453
		// Optional anti-offsite hijacking of the thumbnail script
2454
		$allow   = true;
2455
		if ($allow && $this->config_nooffsitelink_enabled && (@$_SERVER['HTTP_REFERER'] || $this->config_nooffsitelink_require_refer)) {
2456
			$this->DebugMessage('AntiOffsiteLinking() checking $_SERVER[HTTP_REFERER] "'.@$_SERVER['HTTP_REFERER'].'"', __FILE__, __LINE__);
2457
			foreach ($this->config_nooffsitelink_valid_domains as $key => $valid_domain) {
2458
				// $_SERVER['HTTP_HOST'] contains the port number, so strip it out here to make default configuration work
2459
				list($clean_domain) = explode(':', $valid_domain);
2460
				$this->config_nooffsitelink_valid_domains[$key] = $clean_domain;
2461
			}
2462
			$parsed_url = phpthumb_functions::ParseURLbetter(@$_SERVER['HTTP_REFERER']);
2463 View Code Duplication
			if (!$this->OffsiteDomainIsAllowed(@$parsed_url['host'], $this->config_nooffsitelink_valid_domains)) {
2464
				$allow   = false;
2465
				//$this->DebugMessage('AntiOffsiteLinking() - "'.@$parsed_url['host'].'" is NOT in $this->config_nooffsitelink_valid_domains ('.implode(';', $this->config_nooffsitelink_valid_domains).')', __FILE__, __LINE__);
2466
				$this->ErrorImage('AntiOffsiteLinking() - "'.@$parsed_url['host'].'" is NOT in $this->config_nooffsitelink_valid_domains ('.implode(';', $this->config_nooffsitelink_valid_domains).')');
2467
			} else {
2468
				$this->DebugMessage('AntiOffsiteLinking() - "'.@$parsed_url['host'].'" is in $this->config_nooffsitelink_valid_domains ('.implode(';', $this->config_nooffsitelink_valid_domains).')', __FILE__, __LINE__);
2469
			}
2470
		}
2471
2472
		if ($allow && $this->config_nohotlink_enabled && preg_match('#^(f|ht)tps?\://#i', $this->src)) {
2473
			$parsed_url = phpthumb_functions::ParseURLbetter($this->src);
2474
			//if (!phpthumb_functions::CaseInsensitiveInArray(@$parsed_url['host'], $this->config_nohotlink_valid_domains)) {
2475 View Code Duplication
			if (!$this->OffsiteDomainIsAllowed(@$parsed_url['host'], $this->config_nohotlink_valid_domains)) {
2476
				// This domain is not allowed
2477
				$allow = false;
2478
				$this->DebugMessage('AntiOffsiteLinking() - "'.$parsed_url['host'].'" is NOT in $this->config_nohotlink_valid_domains ('.implode(';', $this->config_nohotlink_valid_domains).')', __FILE__, __LINE__);
2479
			} else {
2480
				$this->DebugMessage('AntiOffsiteLinking() - "'.$parsed_url['host'].'" is in $this->config_nohotlink_valid_domains ('.implode(';', $this->config_nohotlink_valid_domains).')', __FILE__, __LINE__);
2481
			}
2482
		}
2483
2484
		if ($allow) {
2485
			$this->DebugMessage('AntiOffsiteLinking() says this is allowed', __FILE__, __LINE__);
2486
			return true;
2487
		}
2488
2489
		if (!phpthumb_functions::IsHexColor($this->config_error_bgcolor)) {
2490
			return $this->ErrorImage('Invalid hex color string "'.$this->config_error_bgcolor.'" for $this->config_error_bgcolor');
2491
		}
2492
		if (!phpthumb_functions::IsHexColor($this->config_error_textcolor)) {
2493
			return $this->ErrorImage('Invalid hex color string "'.$this->config_error_textcolor.'" for $this->config_error_textcolor');
2494
		}
2495
		if ($this->config_nooffsitelink_erase_image) {
2496
2497
			return $this->ErrorImage($this->config_nooffsitelink_text_message, $this->thumbnail_width, $this->thumbnail_height);
2498
2499
		} else {
2500
2501
			$this->config_nooffsitelink_watermark_src = $this->ResolveFilenameToAbsolute($this->config_nooffsitelink_watermark_src);
2502
			if (is_file($this->config_nooffsitelink_watermark_src)) {
0 ignored issues
show
Bug introduced by
It seems like $this->config_nooffsitelink_watermark_src can also be of type false; however, parameter $filename of is_file() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

2502
			if (is_file(/** @scrutinizer ignore-type */ $this->config_nooffsitelink_watermark_src)) {
Loading history...
2503
2504
				if (!include_once(dirname(__FILE__).'/phpthumb.filters.php')) {
2505
					$this->DebugMessage('Error including "'.dirname(__FILE__).'/phpthumb.filters.php" which is required for applying watermark', __FILE__, __LINE__);
2506
					return false;
2507
				}
2508
				$watermark_img = $this->ImageCreateFromStringReplacement(file_get_contents($this->config_nooffsitelink_watermark_src));
0 ignored issues
show
Bug introduced by
It seems like $this->config_nooffsitelink_watermark_src can also be of type false; however, parameter $filename of file_get_contents() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

2508
				$watermark_img = $this->ImageCreateFromStringReplacement(file_get_contents(/** @scrutinizer ignore-type */ $this->config_nooffsitelink_watermark_src));
Loading history...
Bug introduced by
file_get_contents($this-...sitelink_watermark_src) cannot be passed to phpthumb::ImageCreateFromStringReplacement() as the parameter $RawImageData expects a reference. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

2508
				$watermark_img = $this->ImageCreateFromStringReplacement(/** @scrutinizer ignore-type */ file_get_contents($this->config_nooffsitelink_watermark_src));
Loading history...
2509
				$phpthumbFilters = new phpthumb_filters();
2510
				$phpthumbFilters->phpThumbObject = &$this;
2511
				$opacity = 50;
2512
				$margin  = 5;
2513
				$phpthumbFilters->WatermarkOverlay($this->gdimg_output, $watermark_img, '*', $opacity, $margin);
2514
				imagedestroy($watermark_img);
0 ignored issues
show
Bug introduced by
It seems like $watermark_img can also be of type false; however, parameter $image of imagedestroy() does only seem to accept resource, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

2514
				imagedestroy(/** @scrutinizer ignore-type */ $watermark_img);
Loading history...
2515
				unset($phpthumbFilters);
2516
2517
			} else {
2518
2519
				$nohotlink_text_array = explode("\n", wordwrap($this->config_nooffsitelink_text_message, floor($this->thumbnail_width / imagefontwidth($this->config_error_fontsize)), "\n"));
0 ignored issues
show
Bug introduced by
floor($this->thumbnail_w...config_error_fontsize)) of type double is incompatible with the type integer expected by parameter $width of wordwrap(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

2519
				$nohotlink_text_array = explode("\n", wordwrap($this->config_nooffsitelink_text_message, /** @scrutinizer ignore-type */ floor($this->thumbnail_width / imagefontwidth($this->config_error_fontsize)), "\n"));
Loading history...
2520
				$nohotlink_text_color = phpthumb_functions::ImageHexColorAllocate($this->gdimg_output, $this->config_error_textcolor);
2521
2522
				$topoffset = round(($this->thumbnail_height - (count($nohotlink_text_array) * imagefontheight($this->config_error_fontsize))) / 2);
2523
2524
				$rowcounter = 0;
2525
				$this->DebugMessage('AntiOffsiteLinking() writing '.count($nohotlink_text_array).' lines of text "'.$this->config_nooffsitelink_text_message.'" (in #'.$this->config_error_textcolor.') on top of image', __FILE__, __LINE__);
2526
				foreach ($nohotlink_text_array as $textline) {
2527
					$leftoffset = max(0, round(($this->thumbnail_width - (strlen($textline) * imagefontwidth($this->config_error_fontsize))) / 2));
2528
					imagestring($this->gdimg_output, $this->config_error_fontsize, $leftoffset, $topoffset + ($rowcounter++ * imagefontheight($this->config_error_fontsize)), $textline, $nohotlink_text_color);
0 ignored issues
show
Bug introduced by
$topoffset + PostIncNode...>config_error_fontsize) of type double is incompatible with the type integer expected by parameter $y of imagestring(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

2528
					imagestring($this->gdimg_output, $this->config_error_fontsize, $leftoffset, /** @scrutinizer ignore-type */ $topoffset + ($rowcounter++ * imagefontheight($this->config_error_fontsize)), $textline, $nohotlink_text_color);
Loading history...
2529
				}
2530
2531
			}
2532
2533
		}
2534
		return true;
2535
	}
2536
2537
2538
	function AlphaChannelFlatten() {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
2539
		if (!$this->is_alpha) {
2540
			// image doesn't have alpha transparency, no need to flatten
2541
			$this->DebugMessage('skipping AlphaChannelFlatten() because !$this->is_alpha', __FILE__, __LINE__);
2542
			return false;
2543
		}
2544
		switch ($this->thumbnailFormat) {
2545
			case 'png':
2546 View Code Duplication
			case 'ico':
2547
				// image has alpha transparency, but output as PNG or ICO which can handle it
2548
				$this->DebugMessage('skipping AlphaChannelFlatten() because ($this->thumbnailFormat == "'.$this->thumbnailFormat.'")', __FILE__, __LINE__);
2549
				return false;
2550
				break;
0 ignored issues
show
Unused Code introduced by
break is not strictly necessary here and could be removed.

The break statement is not necessary if it is preceded for example by a return statement:

switch ($x) {
    case 1:
        return 'foo';
        break; // This break is not necessary and can be left off.
}

If you would like to keep this construct to be consistent with other case statements, you can safely mark this issue as a false-positive.

Loading history...
2551
2552
			case 'gif':
2553
				// image has alpha transparency, but output as GIF which can handle only single-color transparency
2554
				$CurrentImageColorTransparent = imagecolortransparent($this->gdimg_output);
2555
				if ($CurrentImageColorTransparent == -1) {
2556
					// no transparent color defined
2557
2558
					if (phpthumb_functions::gd_version() < 2.0) {
2559
						$this->DebugMessage('AlphaChannelFlatten() failed because GD version is "'.phpthumb_functions::gd_version().'"', __FILE__, __LINE__);
2560
						return false;
2561
					}
2562
2563
					if ($img_alpha_mixdown_dither = @imagecreatetruecolor(imagesx($this->gdimg_output), imagesy($this->gdimg_output))) {
2564
2565
						$dither_color = array();
2566
						for ($i = 0; $i <= 255; $i++) {
2567
							$dither_color[$i] = imagecolorallocate($img_alpha_mixdown_dither, $i, $i, $i);
2568
						}
2569
2570
						// scan through current truecolor image copy alpha channel to temp image as grayscale
2571 View Code Duplication
						for ($x = 0; $x < $this->thumbnail_width; $x++) {
2572
							for ($y = 0; $y < $this->thumbnail_height; $y++) {
2573
								$PixelColor = phpthumb_functions::GetPixelColor($this->gdimg_output, $x, $y);
2574
								imagesetpixel($img_alpha_mixdown_dither, $x, $y, $dither_color[($PixelColor['alpha'] * 2)]);
2575
							}
2576
						}
2577
2578
						// dither alpha channel grayscale version down to 2 colors
2579
						imagetruecolortopalette($img_alpha_mixdown_dither, true, 2);
2580
2581
						// reduce color palette to 256-1 colors (leave one palette position for transparent color)
2582
						imagetruecolortopalette($this->gdimg_output, true, 255);
2583
2584
						// allocate a new color for transparent color index
2585
						$TransparentColor = imagecolorallocate($this->gdimg_output, 1, 254, 253);
2586
						imagecolortransparent($this->gdimg_output, $TransparentColor);
2587
2588
						// scan through alpha channel image and note pixels with >50% transparency
2589 View Code Duplication
						for ($x = 0; $x < $this->thumbnail_width; $x++) {
2590
							for ($y = 0; $y < $this->thumbnail_height; $y++) {
2591
								$AlphaChannelPixel = phpthumb_functions::GetPixelColor($img_alpha_mixdown_dither, $x, $y);
2592
								if ($AlphaChannelPixel['red'] > 127) {
2593
									imagesetpixel($this->gdimg_output, $x, $y, $TransparentColor);
2594
								}
2595
							}
2596
						}
2597
						imagedestroy($img_alpha_mixdown_dither);
2598
2599
						$this->DebugMessage('AlphaChannelFlatten() set image to 255+1 colors with transparency for GIF output', __FILE__, __LINE__);
2600
						return true;
2601
2602 View Code Duplication
					} else {
2603
						$this->DebugMessage('AlphaChannelFlatten() failed imagecreate('.imagesx($this->gdimg_output).', '.imagesy($this->gdimg_output).')', __FILE__, __LINE__);
2604
						return false;
2605
					}
2606
2607
				} else {
2608
					// a single transparent color already defined, leave as-is
2609
					$this->DebugMessage('skipping AlphaChannelFlatten() because ($this->thumbnailFormat == "'.$this->thumbnailFormat.'") and imagecolortransparent() returned "'.$CurrentImageColorTransparent.'"', __FILE__, __LINE__);
2610
					return true;
2611
				}
2612
				break;
2613
		}
2614
		$this->DebugMessage('continuing AlphaChannelFlatten() for output format "'.$this->thumbnailFormat.'"', __FILE__, __LINE__);
2615
		// image has alpha transparency, and is being output in a format that doesn't support it -- flatten
2616
		if ($gdimg_flatten_temp = phpthumb_functions::ImageCreateFunction($this->thumbnail_width, $this->thumbnail_height)) {
2617
2618
			$this->config_background_hexcolor = ($this->bg ? $this->bg : $this->config_background_hexcolor);
2619
			if (!phpthumb_functions::IsHexColor($this->config_background_hexcolor)) {
2620
				return $this->ErrorImage('Invalid hex color string "'.$this->config_background_hexcolor.'" for parameter "bg"');
2621
			}
2622
			$background_color = phpthumb_functions::ImageHexColorAllocate($this->gdimg_output, $this->config_background_hexcolor);
2623
			imagefilledrectangle($gdimg_flatten_temp, 0, 0, $this->thumbnail_width, $this->thumbnail_height, $background_color);
2624
			imagecopy($gdimg_flatten_temp, $this->gdimg_output, 0, 0, 0, 0, $this->thumbnail_width, $this->thumbnail_height);
2625
2626
			imagealphablending($this->gdimg_output, true);
2627
			imagesavealpha($this->gdimg_output, false);
2628
			imagecolortransparent($this->gdimg_output, -1);
2629
			imagecopy($this->gdimg_output, $gdimg_flatten_temp, 0, 0, 0, 0, $this->thumbnail_width, $this->thumbnail_height);
2630
2631
			imagedestroy($gdimg_flatten_temp);
2632
			return true;
2633
2634
		} else {
2635
			$this->DebugMessage('ImageCreateFunction() failed', __FILE__, __LINE__);
2636
		}
2637
		return false;
2638
	}
2639
2640
2641
	function ApplyFilters() {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
2642
		if ($this->fltr && is_array($this->fltr)) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $this->fltr of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using ! empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
2643 View Code Duplication
			if (!include_once(dirname(__FILE__).'/phpthumb.filters.php')) {
2644
				$this->DebugMessage('Error including "'.dirname(__FILE__).'/phpthumb.filters.php" which is required for applying filters ('.implode(';', $this->fltr).')', __FILE__, __LINE__);
2645
				return false;
2646
			}
2647
			$phpthumbFilters = new phpthumb_filters();
2648
			$phpthumbFilters->phpThumbObject = &$this;
2649
			foreach ($this->fltr as $filtercommand) {
2650
				@list($command, $parameter) = explode('|', $filtercommand, 2);
2651
				$this->DebugMessage('Attempting to process filter command "'.$command.'('.$parameter.')"', __FILE__, __LINE__);
2652
				switch ($command) {
2653
					case 'brit': // Brightness
2654
						$phpthumbFilters->Brightness($this->gdimg_output, $parameter);
2655
						break;
2656
2657
					case 'cont': // Contrast
2658
						$phpthumbFilters->Contrast($this->gdimg_output, $parameter);
2659
						break;
2660
2661
					case 'ds': // Desaturation
2662
						$phpthumbFilters->Desaturate($this->gdimg_output, $parameter, '');
2663
						break;
2664
2665
					case 'sat': // Saturation
2666
						$phpthumbFilters->Saturation($this->gdimg_output, $parameter, '');
2667
						break;
2668
2669
					case 'gray': // Grayscale
2670
						$phpthumbFilters->Grayscale($this->gdimg_output);
2671
						break;
2672
2673 View Code Duplication
					case 'clr': // Colorize
2674
						if (phpthumb_functions::gd_version() < 2) {
2675
							$this->DebugMessage('Skipping Colorize() because gd_version is "'.phpthumb_functions::gd_version().'"', __FILE__, __LINE__);
2676
							break;
2677
						}
2678
						@list($amount, $color) = explode('|', $parameter, 2);
2679
						$phpthumbFilters->Colorize($this->gdimg_output, $amount, $color);
2680
						break;
2681
2682 View Code Duplication
					case 'sep': // Sepia
2683
						if (phpthumb_functions::gd_version() < 2) {
2684
							$this->DebugMessage('Skipping Sepia() because gd_version is "'.phpthumb_functions::gd_version().'"', __FILE__, __LINE__);
2685
							break;
2686
						}
2687
						@list($amount, $color) = explode('|', $parameter, 2);
2688
						$phpthumbFilters->Sepia($this->gdimg_output, $amount, $color);
2689
						break;
2690
2691
					case 'gam': // Gamma correction
2692
						$phpthumbFilters->Gamma($this->gdimg_output, $parameter);
2693
						break;
2694
2695
					case 'neg': // Negative colors
2696
						$phpthumbFilters->Negative($this->gdimg_output);
2697
						break;
2698
2699
					case 'th': // Threshold
2700
						$phpthumbFilters->Threshold($this->gdimg_output, $parameter);
2701
						break;
2702
2703
					case 'rcd': // ReduceColorDepth
2704
						if (phpthumb_functions::gd_version() < 2) {
2705
							$this->DebugMessage('Skipping ReduceColorDepth() because gd_version is "'.phpthumb_functions::gd_version().'"', __FILE__, __LINE__);
2706
							break;
2707
						}
2708
						@list($colors, $dither) = explode('|', $parameter, 2);
2709
						$colors = ($colors                ?  (int) $colors : 256);
2710
						$dither  = ((strlen($dither) > 0) ? (bool) $dither : true);
2711
						$phpthumbFilters->ReduceColorDepth($this->gdimg_output, $colors, $dither);
2712
						break;
2713
2714
					case 'flip': // Flip
2715
						$phpthumbFilters->Flip($this->gdimg_output, (strpos(strtolower($parameter), 'x') !== false), (strpos(strtolower($parameter), 'y') !== false));
2716
						break;
2717
2718
					case 'edge': // EdgeDetect
2719
						$phpthumbFilters->EdgeDetect($this->gdimg_output);
2720
						break;
2721
2722
					case 'emb': // Emboss
2723
						$phpthumbFilters->Emboss($this->gdimg_output);
2724
						break;
2725
2726
					case 'bvl': // Bevel
2727
						@list($width, $color1, $color2) = explode('|', $parameter, 3);
2728
						$phpthumbFilters->Bevel($this->gdimg_output, $width, $color1, $color2);
2729
						break;
2730
2731
					case 'lvl': // autoLevels
2732
						@list($band, $method, $threshold) = explode('|', $parameter, 3);
2733
						$band      = ($band ? preg_replace('#[^RGBA\\*]#', '', strtoupper($band)) : '*');
2734
						$method    = ((strlen($method) > 0)    ? intval($method)                  :   2);
2735
						$threshold = ((strlen($threshold) > 0) ? floatval($threshold)             : 0.1);
2736
2737
						$phpthumbFilters->HistogramStretch($this->gdimg_output, $band, $method, $threshold);
2738
						break;
2739
2740
					case 'wb': // WhiteBalance
2741
						$phpthumbFilters->WhiteBalance($this->gdimg_output, $parameter);
2742
						break;
2743
2744
					case 'hist': // Histogram overlay
2745
						if (phpthumb_functions::gd_version() < 2) {
2746
							$this->DebugMessage('Skipping HistogramOverlay() because gd_version is "'.phpthumb_functions::gd_version().'"', __FILE__, __LINE__);
2747
							break;
2748
						}
2749
						@list($bands, $colors, $width, $height, $alignment, $opacity, $margin_x, $margin_y) = explode('|', $parameter, 8);
2750
						$bands     = ($bands     ? $bands     :  '*');
2751
						$colors    = ($colors    ? $colors    :   '');
2752
						$width     = ($width     ? $width     : 0.25);
2753
						$height    = ($height    ? $height    : 0.25);
2754
						$alignment = ($alignment ? $alignment : 'BR');
2755
						$opacity   = ($opacity   ? $opacity   :   50);
2756
						$margin_x  = ($margin_x  ? $margin_x  :    5);
2757
						// $margin_y -- it wasn't forgotten, let the value always pass unchanged
2758
						$phpthumbFilters->HistogramOverlay($this->gdimg_output, $bands, $colors, $width, $height, $alignment, $opacity, $margin_x, $margin_y);
2759
						break;
2760
2761
					case 'fram': // Frame
2762
						@list($frame_width, $edge_width, $color_frame, $color1, $color2) = explode('|', $parameter, 5);
2763
						$phpthumbFilters->Frame($this->gdimg_output, $frame_width, $edge_width, $color_frame, $color1, $color2);
2764
						break;
2765
2766
					case 'drop': // DropShadow
2767
						if (phpthumb_functions::gd_version() < 2) {
2768
							$this->DebugMessage('Skipping DropShadow() because gd_version is "'.phpthumb_functions::gd_version().'"', __FILE__, __LINE__);
2769
							return false;
2770
						}
2771
						$this->is_alpha = true;
2772
						@list($distance, $width, $color, $angle, $fade) = explode('|', $parameter, 5);
2773
						$phpthumbFilters->DropShadow($this->gdimg_output, $distance, $width, $color, $angle, $fade);
2774
						break;
2775
2776
					case 'mask': // Mask cropping
2777
						if (phpthumb_functions::gd_version() < 2) {
2778
							$this->DebugMessage('Skipping Mask() because gd_version is "'.phpthumb_functions::gd_version().'"', __FILE__, __LINE__);
2779
							return false;
2780
						}
2781
						@list($mask_filename, $invert) = explode('|', $parameter, 2);
2782
						$mask_filename = $this->ResolveFilenameToAbsolute($mask_filename);
2783
						if (@is_readable($mask_filename) && ($fp_mask = @fopen($mask_filename, 'rb'))) {
0 ignored issues
show
Bug introduced by
It seems like $mask_filename can also be of type false; however, parameter $filename of fopen() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

2783
						if (@is_readable($mask_filename) && ($fp_mask = @fopen(/** @scrutinizer ignore-type */ $mask_filename, 'rb'))) {
Loading history...
Bug introduced by
It seems like $mask_filename can also be of type false; however, parameter $filename of is_readable() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

2783
						if (@is_readable(/** @scrutinizer ignore-type */ $mask_filename) && ($fp_mask = @fopen($mask_filename, 'rb'))) {
Loading history...
2784
							$MaskImageData = '';
2785
							do {
2786
								$buffer = fread($fp_mask, 8192);
2787
								$MaskImageData .= $buffer;
2788
							} while (strlen($buffer) > 0);
2789
							fclose($fp_mask);
2790
							if ($gdimg_mask = $this->ImageCreateFromStringReplacement($MaskImageData)) {
2791
								if ($invert && phpthumb_functions::version_compare_replacement(phpversion(), '5.0.0', '>=') && phpthumb_functions::gd_is_bundled()) {
2792
									imagefilter($gdimg_mask, IMG_FILTER_NEGATE);
2793
								}
2794
								$this->is_alpha = true;
2795
								$phpthumbFilters->ApplyMask($gdimg_mask, $this->gdimg_output);
2796
								imagedestroy($gdimg_mask);
2797
							} else {
2798
								$this->DebugMessage('ImageCreateFromStringReplacement() failed for "'.$mask_filename.'"', __FILE__, __LINE__);
2799
							}
2800
						} else {
2801
							$this->DebugMessage('Cannot open mask file "'.$mask_filename.'"', __FILE__, __LINE__);
2802
						}
2803
						break;
2804
2805
					case 'elip': // Ellipse cropping
2806
						if (phpthumb_functions::gd_version() < 2) {
2807
							$this->DebugMessage('Skipping Ellipse() because gd_version is "'.phpthumb_functions::gd_version().'"', __FILE__, __LINE__);
2808
							return false;
2809
						}
2810
						$this->is_alpha = true;
2811
						$phpthumbFilters->Ellipse($this->gdimg_output);
2812
						break;
2813
2814
					case 'ric': // RoundedImageCorners
2815
						if (phpthumb_functions::gd_version() < 2) {
2816
							$this->DebugMessage('Skipping RoundedImageCorners() because gd_version is "'.phpthumb_functions::gd_version().'"', __FILE__, __LINE__);
2817
							return false;
2818
						}
2819
						@list($radius_x, $radius_y) = explode('|', $parameter, 2);
2820
						if (($radius_x < 1) || ($radius_y < 1)) {
2821
							$this->DebugMessage('Skipping RoundedImageCorners('.$radius_x.', '.$radius_y.') because x/y radius is less than 1', __FILE__, __LINE__);
2822
							break;
2823
						}
2824
						$this->is_alpha = true;
2825
						$phpthumbFilters->RoundedImageCorners($this->gdimg_output, $radius_x, $radius_y);
2826
						break;
2827
2828
					case 'crop': // Crop
2829
						@list($left, $right, $top, $bottom) = explode('|', $parameter, 4);
2830
						$phpthumbFilters->Crop($this->gdimg_output, $left, $right, $top, $bottom);
2831
						break;
2832
2833
					case 'bord': // Border
2834
						@list($border_width, $radius_x, $radius_y, $hexcolor_border) = explode('|', $parameter, 4);
2835
						$this->is_alpha = true;
2836
						$phpthumbFilters->ImageBorder($this->gdimg_output, $border_width, $radius_x, $radius_y, $hexcolor_border);
2837
						break;
2838
2839
					case 'over': // Overlay
2840
						@list($filename, $underlay, $margin, $opacity) = explode('|', $parameter, 4);
2841
						$underlay = (bool) ($underlay              ? $underlay : false);
2842
						$margin   =        ((strlen($margin)  > 0) ? $margin   : ($underlay ? 0.1 : 0.0));
2843
						$opacity  =        ((strlen($opacity) > 0) ? $opacity  : 100);
2844
						if (($margin > 0) && ($margin < 1)) {
2845
							$margin = min(0.499, $margin);
2846
						} elseif (($margin > -1) && ($margin < 0)) {
2847
							$margin = max(-0.499, $margin);
2848
						}
2849
2850
						$filename = $this->ResolveFilenameToAbsolute($filename);
2851
						if (@is_readable($filename) && ($fp_watermark = @fopen($filename, 'rb'))) {
2852
							$WatermarkImageData = '';
2853
							do {
2854
								$buffer = fread($fp_watermark, 8192);
2855
								$WatermarkImageData .= $buffer;
2856
							} while (strlen($buffer) > 0);
2857
							fclose($fp_watermark);
2858
							if ($img_watermark = $this->ImageCreateFromStringReplacement($WatermarkImageData)) {
2859
								if (($margin > 0) && ($margin < 1)) {
2860
									$resized_x = max(1, imagesx($this->gdimg_output) - round(2 * (imagesx($this->gdimg_output) * $margin)));
0 ignored issues
show
Bug introduced by
It seems like $this->gdimg_output can also be of type false; however, parameter $image of imagesx() does only seem to accept resource, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

2860
									$resized_x = max(1, imagesx(/** @scrutinizer ignore-type */ $this->gdimg_output) - round(2 * (imagesx($this->gdimg_output) * $margin)));
Loading history...
2861
									$resized_y = max(1, imagesy($this->gdimg_output) - round(2 * (imagesy($this->gdimg_output) * $margin)));
0 ignored issues
show
Bug introduced by
It seems like $this->gdimg_output can also be of type false; however, parameter $image of imagesy() does only seem to accept resource, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

2861
									$resized_y = max(1, imagesy(/** @scrutinizer ignore-type */ $this->gdimg_output) - round(2 * (imagesy($this->gdimg_output) * $margin)));
Loading history...
2862
								} else {
2863
									$resized_x = max(1, imagesx($this->gdimg_output) - round(2 * $margin));
2864
									$resized_y = max(1, imagesy($this->gdimg_output) - round(2 * $margin));
2865
								}
2866
2867
								if ($underlay) {
2868
2869
									if ($img_watermark_resized = phpthumb_functions::ImageCreateFunction(imagesx($this->gdimg_output), imagesy($this->gdimg_output))) {
2870
										imagealphablending($img_watermark_resized, false);
2871
										imagesavealpha($img_watermark_resized, true);
2872
										$this->ImageResizeFunction($img_watermark_resized, $img_watermark, 0, 0, 0, 0, imagesx($img_watermark_resized), imagesy($img_watermark_resized), imagesx($img_watermark), imagesy($img_watermark));
2873
										if ($img_source_resized = phpthumb_functions::ImageCreateFunction($resized_x, $resized_y)) {
2874
											imagealphablending($img_source_resized, false);
2875
											imagesavealpha($img_source_resized, true);
2876
											$this->ImageResizeFunction($img_source_resized, $this->gdimg_output, 0, 0, 0, 0, imagesx($img_source_resized), imagesy($img_source_resized), imagesx($this->gdimg_output), imagesy($this->gdimg_output));
2877
											$phpthumbFilters->WatermarkOverlay($img_watermark_resized, $img_source_resized, 'C', $opacity, $margin);
2878
											imagecopy($this->gdimg_output, $img_watermark_resized, 0, 0, 0, 0, imagesx($this->gdimg_output), imagesy($this->gdimg_output));
0 ignored issues
show
Bug introduced by
It seems like $this->gdimg_output can also be of type false; however, parameter $dst_im of imagecopy() does only seem to accept resource, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

2878
											imagecopy(/** @scrutinizer ignore-type */ $this->gdimg_output, $img_watermark_resized, 0, 0, 0, 0, imagesx($this->gdimg_output), imagesy($this->gdimg_output));
Loading history...
2879
										} else {
2880
											$this->DebugMessage('phpthumb_functions::ImageCreateFunction('.$resized_x.', '.$resized_y.')', __FILE__, __LINE__);
2881
										}
2882
										imagedestroy($img_watermark_resized);
2883 View Code Duplication
									} else {
2884
										$this->DebugMessage('phpthumb_functions::ImageCreateFunction('.imagesx($this->gdimg_output).', '.imagesy($this->gdimg_output).')', __FILE__, __LINE__);
2885
									}
2886
2887
								} else { // overlay
2888
2889
									if ($img_watermark_resized = phpthumb_functions::ImageCreateFunction($resized_x, $resized_y)) {
2890
										imagealphablending($img_watermark_resized, false);
2891
										imagesavealpha($img_watermark_resized, true);
2892
										$this->ImageResizeFunction($img_watermark_resized, $img_watermark, 0, 0, 0, 0, imagesx($img_watermark_resized), imagesy($img_watermark_resized), imagesx($img_watermark), imagesy($img_watermark));
2893
										$phpthumbFilters->WatermarkOverlay($this->gdimg_output, $img_watermark_resized, 'C', $opacity, $margin);
2894
										imagedestroy($img_watermark_resized);
2895
									} else {
2896
										$this->DebugMessage('phpthumb_functions::ImageCreateFunction('.$resized_x.', '.$resized_y.')', __FILE__, __LINE__);
2897
									}
2898
2899
								}
2900
								imagedestroy($img_watermark);
2901
2902
							} else {
2903
								$this->DebugMessage('ImageCreateFromStringReplacement() failed for "'.$filename.'"', __FILE__, __LINE__);
2904
							}
2905
						} else {
2906
							$this->DebugMessage('Cannot open overlay file "'.$filename.'"', __FILE__, __LINE__);
2907
						}
2908
						break;
2909
2910
					case 'wmi': // WaterMarkImage
2911
						@list($filename, $alignment, $opacity, $margin['x'], $margin['y'], $rotate_angle) = explode('|', $parameter, 6);
2912
						// $margin can be pixel margin or percent margin if $alignment is text, or max width/height if $alignment is position like "50x75"
2913
						$alignment    = ($alignment            ? $alignment            : 'BR');
2914
						$opacity      = (strlen($opacity)      ? intval($opacity)      : 50);
2915
						$rotate_angle = (strlen($rotate_angle) ? intval($rotate_angle) : 0);
2916
						if (!preg_match('#^([0-9\\.\\-]*)x([0-9\\.\\-]*)$#i', $alignment, $matches)) {
2917
							$margins = array('x', 'y');
2918
							foreach ($margins as $xy) {
2919
								$margin[$xy] = (strlen($margin[$xy]) ? $margin[$xy] : 5);
2920
								if (($margin[$xy] > 0) && ($margin[$xy] < 1)) {
2921
									$margin[$xy] = min(0.499, $margin[$xy]);
2922
								} elseif (($margin[$xy] > -1) && ($margin[$xy] < 0)) {
2923
									$margin[$xy] = max(-0.499, $margin[$xy]);
2924
								}
2925
							}
2926
						}
2927
2928
						$filename = $this->ResolveFilenameToAbsolute($filename);
2929
						if (@is_readable($filename)) {
2930
							if ($img_watermark = $this->ImageCreateFromFilename($filename)) {
2931
								if ($rotate_angle !== 0) {
2932
									$phpthumbFilters->ImprovedImageRotate($img_watermark, $rotate_angle, 'FFFFFF', null, $this);
2933
								}
2934
								if (preg_match('#^([0-9\\.\\-]*)x([0-9\\.\\-]*)$#i', $alignment, $matches)) {
2935
									$watermark_max_width  = intval($margin['x'] ? $margin['x'] : imagesx($img_watermark));
2936
									$watermark_max_height = intval($margin['y'] ? $margin['y'] : imagesy($img_watermark));
2937
									$scale = phpthumb_functions::ScaleToFitInBox(imagesx($img_watermark), imagesy($img_watermark), $watermark_max_width, $watermark_max_height, true, true);
2938
									$this->DebugMessage('Scaling watermark by a factor of '.number_format($scale, 4), __FILE__, __LINE__);
2939
									if (($scale > 1) || ($scale < 1)) {
2940
										if ($img_watermark2 = phpthumb_functions::ImageCreateFunction($scale * imagesx($img_watermark), $scale * imagesy($img_watermark))) {
2941
											imagealphablending($img_watermark2, false);
2942
											imagesavealpha($img_watermark2, true);
2943
											$this->ImageResizeFunction($img_watermark2, $img_watermark, 0, 0, 0, 0, imagesx($img_watermark2), imagesy($img_watermark2), imagesx($img_watermark), imagesy($img_watermark));
2944
											$img_watermark = $img_watermark2;
2945
										} else {
2946
											$this->DebugMessage('ImageCreateFunction('.($scale * imagesx($img_watermark)).', '.($scale * imagesx($img_watermark)).') failed', __FILE__, __LINE__);
2947
										}
2948
									}
2949
									$watermark_dest_x = round($matches[1] - (imagesx($img_watermark) / 2));
2950
									$watermark_dest_y = round($matches[2] - (imagesy($img_watermark) / 2));
2951
									$alignment = $watermark_dest_x.'x'.$watermark_dest_y;
2952
								}
2953
								$phpthumbFilters->WatermarkOverlay($this->gdimg_output, $img_watermark, $alignment, $opacity, $margin['x'], $margin['y']);
2954
								imagedestroy($img_watermark);
2955
								if (isset($img_watermark2) && is_resource($img_watermark2)) {
2956
									imagedestroy($img_watermark2);
2957
								}
2958
							} else {
2959
								$this->DebugMessage('ImageCreateFromFilename() failed for "'.$filename.'"', __FILE__, __LINE__);
2960
							}
2961
						} else {
2962
							$this->DebugMessage('!is_readable('.$filename.')', __FILE__, __LINE__);
2963
						}
2964
						break;
2965
2966
					case 'wmt': // WaterMarkText
2967
						@list($text, $size, $alignment, $hex_color, $ttffont, $opacity, $margin, $angle, $bg_color, $bg_opacity, $fillextend) = explode('|', $parameter, 11);
2968
						$text       = ($text            ? $text       : '');
2969
						$size       = ($size            ? $size       : 3);
2970
						$alignment  = ($alignment       ? $alignment  : 'BR');
2971
						$hex_color  = ($hex_color       ? $hex_color  : '000000');
2972
						$ttffont    = ($ttffont         ? $ttffont    : '');
2973
						$opacity    = (strlen($opacity) ? $opacity    : 50);
2974
						$margin     = (strlen($margin)  ? $margin     : 5);
2975
						$angle      = (strlen($angle)   ? $angle      : 0);
2976
						$bg_color   = ($bg_color        ? $bg_color   : false);
2977
						$bg_opacity = ($bg_opacity      ? $bg_opacity : 0);
2978
						$fillextend = ($fillextend      ? $fillextend : '');
2979
2980
						if (basename($ttffont) == $ttffont) {
2981
							$ttffont = $this->realPathSafe($this->config_ttf_directory.DIRECTORY_SEPARATOR.$ttffont);
2982
						} else {
2983
							$ttffont = $this->ResolveFilenameToAbsolute($ttffont);
2984
						}
2985
						$phpthumbFilters->WatermarkText($this->gdimg_output, $text, $size, $alignment, $hex_color, $ttffont, $opacity, $margin, $angle, $bg_color, $bg_opacity, $fillextend);
2986
						break;
2987
2988 View Code Duplication
					case 'blur': // Blur
2989
						@list($radius) = explode('|', $parameter, 1);
2990
						$radius = ($radius ? $radius : 1);
2991
						if (phpthumb_functions::gd_version() >= 2) {
2992
							$phpthumbFilters->Blur($this->gdimg_output, $radius);
2993
						} else {
2994
							$this->DebugMessage('Skipping Blur() because gd_version is "'.phpthumb_functions::gd_version().'"', __FILE__, __LINE__);
2995
						}
2996
						break;
2997
2998
					case 'gblr': // Gaussian Blur
2999
						$phpthumbFilters->BlurGaussian($this->gdimg_output);
3000
						break;
3001
3002
					case 'sblr': // Selective Blur
3003
						$phpthumbFilters->BlurSelective($this->gdimg_output);
3004
						break;
3005
3006
					case 'mean': // MeanRemoval blur
3007
						$phpthumbFilters->MeanRemoval($this->gdimg_output);
3008
						break;
3009
3010
					case 'smth': // Smooth blur
3011
						$phpthumbFilters->Smooth($this->gdimg_output, $parameter);
3012
						break;
3013
3014
					case 'usm': // UnSharpMask sharpening
3015
						@list($amount, $radius, $threshold) = explode('|', $parameter, 3);
3016
						$amount    = ($amount            ? $amount    : 80);
3017
						$radius    = ($radius            ? $radius    : 0.5);
3018
						$threshold = (strlen($threshold) ? $threshold : 3);
3019
						if (phpthumb_functions::gd_version() >= 2.0) {
3020
							ob_start();
3021
							if (!@include_once(dirname(__FILE__).'/phpthumb.unsharp.php')) {
3022
								$include_error = ob_get_contents();
3023
								if ($include_error) {
3024
									$this->DebugMessage('include_once("'.dirname(__FILE__).'/phpthumb.unsharp.php") generated message: "'.$include_error.'"', __FILE__, __LINE__);
3025
								}
3026
								$this->DebugMessage('Error including "'.dirname(__FILE__).'/phpthumb.unsharp.php" which is required for unsharp masking', __FILE__, __LINE__);
3027
								ob_end_clean();
3028
								return false;
3029
							}
3030
							ob_end_clean();
3031
							phpUnsharpMask::applyUnsharpMask($this->gdimg_output, $amount, $radius, $threshold);
3032
						} else {
3033
							$this->DebugMessage('Skipping unsharp mask because gd_version is "'.phpthumb_functions::gd_version().'"', __FILE__, __LINE__);
3034
							return false;
3035
						}
3036
						break;
3037
3038
					case 'size': // Resize
3039
						@list($newwidth, $newheight, $stretch) = explode('|', $parameter);
3040
						$newwidth  = (!$newwidth  ? imagesx($this->gdimg_output) : ((($newwidth  > 0) && ($newwidth  < 1)) ? round($newwidth  * imagesx($this->gdimg_output)) : round($newwidth)));
3041
						$newheight = (!$newheight ? imagesy($this->gdimg_output) : ((($newheight > 0) && ($newheight < 1)) ? round($newheight * imagesy($this->gdimg_output)) : round($newheight)));
3042
						$stretch   = ($stretch ? true : false);
3043
						if ($stretch) {
3044
							$scale_x = phpthumb_functions::ScaleToFitInBox(imagesx($this->gdimg_output), imagesx($this->gdimg_output), $newwidth,  $newwidth,  true, true);
3045
							$scale_y = phpthumb_functions::ScaleToFitInBox(imagesy($this->gdimg_output), imagesy($this->gdimg_output), $newheight, $newheight, true, true);
3046
						} else {
3047
							$scale_x = phpthumb_functions::ScaleToFitInBox(imagesx($this->gdimg_output), imagesy($this->gdimg_output), $newwidth, $newheight, true, true);
3048
							$scale_y = $scale_x;
3049
						}
3050
						$this->DebugMessage('Scaling watermark ('.($stretch ? 'with' : 'without').' stretch) by a factor of "'.number_format($scale_x, 4).' x '.number_format($scale_y, 4).'"', __FILE__, __LINE__);
3051
						if (($scale_x > 1) || ($scale_x < 1) || ($scale_y > 1) || ($scale_y < 1)) {
3052
							if ($img_temp = phpthumb_functions::ImageCreateFunction(imagesx($this->gdimg_output), imagesy($this->gdimg_output))) {
3053
								imagecopy($img_temp, $this->gdimg_output, 0, 0, 0, 0, imagesx($this->gdimg_output), imagesy($this->gdimg_output));
0 ignored issues
show
Bug introduced by
It seems like $this->gdimg_output can also be of type false; however, parameter $src_im of imagecopy() does only seem to accept resource, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

3053
								imagecopy($img_temp, /** @scrutinizer ignore-type */ $this->gdimg_output, 0, 0, 0, 0, imagesx($this->gdimg_output), imagesy($this->gdimg_output));
Loading history...
3054
								if ($this->gdimg_output = phpthumb_functions::ImageCreateFunction($scale_x * imagesx($img_temp), $scale_y * imagesy($img_temp))) {
3055
									imagealphablending($this->gdimg_output, false);
3056
									imagesavealpha($this->gdimg_output, true);
3057
									$this->ImageResizeFunction($this->gdimg_output, $img_temp, 0, 0, 0, 0, imagesx($this->gdimg_output), imagesy($this->gdimg_output), imagesx($img_temp), imagesy($img_temp));
3058
								} else {
3059
									$this->DebugMessage('ImageCreateFunction('.($scale_x * imagesx($img_temp)).', '.($scale_y * imagesy($img_temp)).') failed', __FILE__, __LINE__);
3060
								}
3061
								imagedestroy($img_temp);
3062 View Code Duplication
							} else {
3063
								$this->DebugMessage('ImageCreateFunction('.imagesx($this->gdimg_output).', '.imagesy($this->gdimg_output).') failed', __FILE__, __LINE__);
3064
							}
3065
						}
3066
						break;
3067
3068
					case 'rot': // ROTate
3069
						@list($angle, $bgcolor) = explode('|', $parameter, 2);
3070
						$phpthumbFilters->ImprovedImageRotate($this->gdimg_output, $angle, $bgcolor, null, $this);
3071
						break;
3072
3073
					case 'stc': // Source Transparent Color
3074
						@list($hexcolor, $min_limit, $max_limit) = explode('|', $parameter, 3);
3075
						if (!phpthumb_functions::IsHexColor($hexcolor)) {
3076
							$this->DebugMessage('Skipping SourceTransparentColor hex color is invalid ('.$hexcolor.')', __FILE__, __LINE__);
3077
							return false;
3078
						}
3079
						$min_limit = (strlen($min_limit) ? $min_limit :  5);
3080
						$max_limit = (strlen($max_limit) ? $max_limit : 10);
3081
						if ($gdimg_mask = $phpthumbFilters->SourceTransparentColorMask($this->gdimg_output, $hexcolor, $min_limit, $max_limit)) {
3082
							$this->is_alpha = true;
3083
							$phpthumbFilters->ApplyMask($gdimg_mask, $this->gdimg_output);
3084
							imagedestroy($gdimg_mask);
3085
						} else {
3086
							$this->DebugMessage('SourceTransparentColorMask() failed for "'.$hexcolor.','.$min_limit.','.$max_limit.'"', __FILE__, __LINE__);
3087
						}
3088
						break;
3089
				}
3090
				$this->DebugMessage('Finished processing filter command "'.$command.'('.$parameter.')"', __FILE__, __LINE__);
3091
			}
3092
		}
3093
		return true;
3094
	}
3095
3096
3097
	function MaxFileSize() {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
3098
		if (phpthumb_functions::gd_version() < 2) {
3099
			$this->DebugMessage('Skipping MaxFileSize() because gd_version is "'.phpthumb_functions::gd_version().'"', __FILE__, __LINE__);
3100
			return false;
3101
		}
3102
		if ($this->maxb > 0) {
3103
			switch ($this->thumbnailFormat) {
3104
				case 'png':
3105
				case 'gif':
3106
					$imgRenderFunction = 'image'.$this->thumbnailFormat;
3107
3108
					ob_start();
3109
					$imgRenderFunction($this->gdimg_output);
3110
					$imgdata = ob_get_contents();
3111
					ob_end_clean();
3112
3113
					if (strlen($imgdata) > $this->maxb) {
3114
						for ($i = 8; $i >= 1; $i--) {
3115
							$tempIMG = imagecreatetruecolor(imagesx($this->gdimg_output), imagesy($this->gdimg_output));
3116
							imagecopy($tempIMG, $this->gdimg_output, 0, 0, 0, 0, imagesx($this->gdimg_output), imagesy($this->gdimg_output));
3117
							imagetruecolortopalette($tempIMG, true, pow(2, $i));
3118
							ob_start();
3119
							$imgRenderFunction($tempIMG);
3120
							$imgdata = ob_get_contents();
3121
							ob_end_clean();
3122
3123
							if (strlen($imgdata) <= $this->maxb) {
3124
								imagetruecolortopalette($this->gdimg_output, true, pow(2, $i));
3125
								break;
3126
							}
3127
						}
3128
					}
3129
					break;
3130
3131
				case 'jpeg':
3132
					ob_start();
3133
					imagejpeg($this->gdimg_output);
3134
					$imgdata = ob_get_contents();
3135
					ob_end_clean();
3136
3137
					if (strlen($imgdata) > $this->maxb) {
3138
						for ($i = 3; $i < 20; $i++) {
3139
							$q = round(100 * (1 - log10($i / 2)));
3140
							ob_start();
3141
							imagejpeg($this->gdimg_output, null, $q);
0 ignored issues
show
Bug introduced by
$q of type double is incompatible with the type integer expected by parameter $quality of imagejpeg(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

3141
							imagejpeg($this->gdimg_output, null, /** @scrutinizer ignore-type */ $q);
Loading history...
3142
							$imgdata = ob_get_contents();
3143
							ob_end_clean();
3144
3145
							$this->thumbnailQuality = $q;
3146
							if (strlen($imgdata) <= $this->maxb) {
3147
								break;
3148
							}
3149
						}
3150
					}
3151
					if (strlen($imgdata) > $this->maxb) {
3152
						return false;
3153
					}
3154
					break;
3155
3156
				default:
3157
					return false;
3158
			}
3159
		}
3160
		return true;
3161
	}
3162
3163
3164
	function CalculateThumbnailDimensions() {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
3165
		$this->DebugMessage('CalculateThumbnailDimensions() starting with [W,H,sx,sy,sw,sh] initially set to ['.$this->source_width.','.$this->source_height.','.$this->sx.','.$this->sy.','.$this->sw.','.$this->sh.']', __FILE__, __LINE__);
3166
//echo $this->source_width.'x'.$this->source_height.'<hr>';
3167
		$this->thumbnailCropX = ($this->sx ? (($this->sx >= 2) ? $this->sx : round($this->sx * $this->source_width))  : 0);
3168
//echo $this->thumbnailCropX.'<br>';
3169
		$this->thumbnailCropY = ($this->sy ? (($this->sy >= 2) ? $this->sy : round($this->sy * $this->source_height)) : 0);
3170
//echo $this->thumbnailCropY.'<br>';
3171
		$this->thumbnailCropW = ($this->sw ? (($this->sw >= 2) ? $this->sw : round($this->sw * $this->source_width))  : $this->source_width);
3172
//echo $this->thumbnailCropW.'<br>';
3173
		$this->thumbnailCropH = ($this->sh ? (($this->sh >= 2) ? $this->sh : round($this->sh * $this->source_height)) : $this->source_height);
3174
//echo $this->thumbnailCropH.'<hr>';
3175
3176
		// limit source area to original image area
3177
		$this->thumbnailCropW = max(1, min($this->thumbnailCropW, $this->source_width  - $this->thumbnailCropX));
3178
		$this->thumbnailCropH = max(1, min($this->thumbnailCropH, $this->source_height - $this->thumbnailCropY));
3179
3180
		$this->DebugMessage('CalculateThumbnailDimensions() starting with [x,y,w,h] initially set to ['.$this->thumbnailCropX.','.$this->thumbnailCropY.','.$this->thumbnailCropW.','.$this->thumbnailCropH.']', __FILE__, __LINE__);
3181
3182
3183
		if ($this->zc && $this->w && $this->h) {
3184
			// Zoom Crop
3185
			// retain proportional resizing we did above, but crop off larger dimension so smaller
3186
			// dimension fully fits available space
3187
3188
			$scaling_X = $this->source_width  / $this->w;
3189
			$scaling_Y = $this->source_height / $this->h;
3190
			if ($scaling_X > $scaling_Y) {
3191
				// some of the width will need to be cropped
3192
				$allowable_width = $this->source_width / $scaling_X * $scaling_Y;
3193
				$this->thumbnailCropW = round($allowable_width);
3194
				$this->thumbnailCropX = round(($this->source_width - $allowable_width) / 2);
3195
3196
			} elseif ($scaling_Y > $scaling_X) {
3197
				// some of the height will need to be cropped
3198
				$allowable_height = $this->source_height / $scaling_Y * $scaling_X;
3199
				$this->thumbnailCropH = round($allowable_height);
3200
				$this->thumbnailCropY = round(($this->source_height - $allowable_height) / 2);
3201
3202
			} else {
0 ignored issues
show
Unused Code introduced by
This else statement is empty and can be removed.

This check looks for the else branches 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 else branches can be removed.

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

could be turned into

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

This is much more concise to read.

Loading history...
3203
				// image fits perfectly, no cropping needed
3204
			}
3205
			$this->thumbnail_width  = $this->w;
3206
			$this->thumbnail_height = $this->h;
3207
			$this->thumbnail_image_width  = $this->thumbnail_width;
3208
			$this->thumbnail_image_height = $this->thumbnail_height;
3209
3210
		} elseif ($this->iar && $this->w && $this->h) {
3211
3212
			// Ignore Aspect Ratio
3213
			// stretch image to fit exactly 'w' x 'h'
3214
			$this->thumbnail_width  = $this->w;
3215
			$this->thumbnail_height = $this->h;
3216
			$this->thumbnail_image_width  = $this->thumbnail_width;
3217
			$this->thumbnail_image_height = $this->thumbnail_height;
3218
3219
		} else {
3220
3221
			$original_aspect_ratio = $this->thumbnailCropW / $this->thumbnailCropH;
3222
			if ($this->aoe) {
3223
				if ($this->w && $this->h) {
3224
					$maxwidth  = min($this->w, $this->h * $original_aspect_ratio);
3225
					$maxheight = min($this->h, $this->w / $original_aspect_ratio);
3226
				} elseif ($this->w) {
3227
					$maxwidth  = $this->w;
3228
					$maxheight = $this->w / $original_aspect_ratio;
3229
				} elseif ($this->h) {
3230
					$maxwidth  = $this->h * $original_aspect_ratio;
3231
					$maxheight = $this->h;
3232
				} else {
3233
					$maxwidth  = $this->thumbnailCropW;
3234
					$maxheight = $this->thumbnailCropH;
3235
				}
3236
			} else {
3237
				$maxwidth  = phpthumb_functions::nonempty_min($this->w, $this->thumbnailCropW, $this->config_output_maxwidth);
3238
				$maxheight = phpthumb_functions::nonempty_min($this->h, $this->thumbnailCropH, $this->config_output_maxheight);
3239
//echo $maxwidth.'x'.$maxheight.'<br>';
3240
				$maxwidth  = min($maxwidth, $maxheight * $original_aspect_ratio);
3241
				$maxheight = min($maxheight, $maxwidth / $original_aspect_ratio);
3242
//echo $maxwidth.'x'.$maxheight.'<hr>';
3243
			}
3244
3245
			$this->thumbnail_image_width  = $maxwidth;
3246
			$this->thumbnail_image_height = $maxheight;
3247
			$this->thumbnail_width  = $maxwidth;
3248
			$this->thumbnail_height = $maxheight;
3249
3250
			$this->FixedAspectRatio();
3251
		}
3252
3253
		$this->thumbnail_width  = max(1, floor($this->thumbnail_width));
3254
		$this->thumbnail_height = max(1, floor($this->thumbnail_height));
3255
		return true;
3256
	}
3257
3258
3259
	function CreateGDoutput() {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
3260
		$this->CalculateThumbnailDimensions();
3261
3262
		// create the GD image (either true-color or 256-color, depending on GD version)
3263
		$this->gdimg_output = phpthumb_functions::ImageCreateFunction($this->thumbnail_width, $this->thumbnail_height);
3264
3265
		// images that have transparency must have the background filled with the configured 'bg' color otherwise the transparent color will appear as black
3266
		imagesavealpha($this->gdimg_output, true);
0 ignored issues
show
Bug introduced by
It seems like $this->gdimg_output can also be of type false; however, parameter $image of imagesavealpha() does only seem to accept resource, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

3266
		imagesavealpha(/** @scrutinizer ignore-type */ $this->gdimg_output, true);
Loading history...
3267
		if ($this->is_alpha && phpthumb_functions::gd_version() >= 2) {
3268
3269
			imagealphablending($this->gdimg_output, false);
0 ignored issues
show
Bug introduced by
It seems like $this->gdimg_output can also be of type false; however, parameter $image of imagealphablending() does only seem to accept resource, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

3269
			imagealphablending(/** @scrutinizer ignore-type */ $this->gdimg_output, false);
Loading history...
3270
			$output_full_alpha = phpthumb_functions::ImageColorAllocateAlphaSafe($this->gdimg_output, 255, 255, 255, 127);
3271
			imagefilledrectangle($this->gdimg_output, 0, 0, $this->thumbnail_width, $this->thumbnail_height, $output_full_alpha);
0 ignored issues
show
Bug introduced by
It seems like $this->gdimg_output can also be of type false; however, parameter $image of imagefilledrectangle() does only seem to accept resource, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

3271
			imagefilledrectangle(/** @scrutinizer ignore-type */ $this->gdimg_output, 0, 0, $this->thumbnail_width, $this->thumbnail_height, $output_full_alpha);
Loading history...
3272
3273
		} else {
3274
3275
			$current_transparent_color = imagecolortransparent($this->gdimg_source);
3276
			if ($this->bg || (@$current_transparent_color >= 0)) {
3277
3278
				$this->config_background_hexcolor = ($this->bg ? $this->bg : $this->config_background_hexcolor);
3279
				if (!phpthumb_functions::IsHexColor($this->config_background_hexcolor)) {
3280
					return $this->ErrorImage('Invalid hex color string "'.$this->config_background_hexcolor.'" for parameter "bg"');
3281
				}
3282
				$background_color = phpthumb_functions::ImageHexColorAllocate($this->gdimg_output, $this->config_background_hexcolor);
3283
				imagefilledrectangle($this->gdimg_output, 0, 0, $this->thumbnail_width, $this->thumbnail_height, $background_color);
3284
3285
			}
3286
3287
		}
3288
		$this->DebugMessage('CreateGDoutput() returning canvas "'.$this->thumbnail_width.'x'.$this->thumbnail_height.'"', __FILE__, __LINE__);
3289
		return true;
3290
	}
3291
3292
	function SetOrientationDependantWidthHeight() {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
3293
		$this->DebugMessage('SetOrientationDependantWidthHeight() starting with "'.$this->source_width.'"x"'.$this->source_height.'"', __FILE__, __LINE__);
3294
		if ($this->source_height > $this->source_width) {
3295
			// portrait
3296
			$this->w = phpthumb_functions::OneOfThese($this->wp, $this->w, $this->ws, $this->wl);
3297
			$this->h = phpthumb_functions::OneOfThese($this->hp, $this->h, $this->hs, $this->hl);
3298
		} elseif ($this->source_height < $this->source_width) {
3299
			// landscape
3300
			$this->w = phpthumb_functions::OneOfThese($this->wl, $this->w, $this->ws, $this->wp);
3301
			$this->h = phpthumb_functions::OneOfThese($this->hl, $this->h, $this->hs, $this->hp);
3302
		} else {
3303
			// square
3304
			$this->w = phpthumb_functions::OneOfThese($this->ws, $this->w, $this->wl, $this->wp);
3305
			$this->h = phpthumb_functions::OneOfThese($this->hs, $this->h, $this->hl, $this->hp);
3306
		}
3307
		//$this->w = round($this->w ? $this->w : (($this->h && $this->source_height) ? $this->h * $this->source_width  / $this->source_height : $this->w));
3308
		//$this->h = round($this->h ? $this->h : (($this->w && $this->source_width)  ? $this->w * $this->source_height / $this->source_width  : $this->h));
3309
		$this->DebugMessage('SetOrientationDependantWidthHeight() setting w="'.intval($this->w).'", h="'.intval($this->h).'"', __FILE__, __LINE__);
3310
		return true;
3311
	}
3312
3313
	function ExtractEXIFgetImageSize() {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
3314
		$this->DebugMessage('starting ExtractEXIFgetImageSize()', __FILE__, __LINE__);
3315
3316
		if (preg_match('#^http:#i', $this->src) && !$this->sourceFilename && $this->rawImageData) {
3317
			$this->SourceDataToTempFile();
3318
		}
3319
		if (is_null($this->getimagesizeinfo)) {
3320
			if ($this->sourceFilename) {
3321
				$this->getimagesizeinfo = @getimagesize($this->sourceFilename);
3322
				$this->source_width  = $this->getimagesizeinfo[0];
3323
				$this->source_height = $this->getimagesizeinfo[1];
3324
				$this->DebugMessage('getimagesize('.$this->sourceFilename.') says image is '.$this->source_width.'x'.$this->source_height, __FILE__, __LINE__);
3325
			} else {
3326
				$this->DebugMessage('skipping getimagesize() because $this->sourceFilename is empty', __FILE__, __LINE__);
3327
			}
3328
		} else {
3329
			$this->DebugMessage('skipping getimagesize() because !is_null($this->getimagesizeinfo)', __FILE__, __LINE__);
3330
		}
3331
3332
		if (is_resource($this->gdimg_source)) {
3333
3334
			$this->source_width  = imagesx($this->gdimg_source);
3335
			$this->source_height = imagesy($this->gdimg_source);
3336
3337
			$this->SetOrientationDependantWidthHeight();
3338
3339
		} elseif ($this->rawImageData && !$this->sourceFilename) {
3340
3341
			if ($this->SourceImageIsTooLarge($this->source_width, $this->source_height)) {
3342
				$this->DebugMessage('NOT bypassing EXIF and getimagesize sections because source image is too large for GD ('.$this->source_width.'x'.$this->source_width.'='.($this->source_width * $this->source_height * 5).'MB)', __FILE__, __LINE__);
3343
			} else {
3344
				$this->DebugMessage('bypassing EXIF and getimagesize sections because $this->rawImageData is set, and $this->sourceFilename is not set, and source image is not too large for GD ('.$this->source_width.'x'.$this->source_width.'='.($this->source_width * $this->source_height * 5).'MB)', __FILE__, __LINE__);
3345
			}
3346
3347
		}
3348
3349
		if (is_null($this->getimagesizeinfo)) {
3350
			$this->getimagesizeinfo = @getimagesize($this->sourceFilename);
3351
		}
3352
3353
		if (!empty($this->getimagesizeinfo)) {
3354
			// great
3355
			$this->getimagesizeinfo['filesize'] = @filesize($this->sourceFilename);
3356
		} elseif (!$this->rawImageData) {
3357
			$this->DebugMessage('getimagesize("'.$this->sourceFilename.'") failed', __FILE__, __LINE__);
3358
		}
3359
3360
		if ($this->config_prefer_imagemagick) {
3361
			if ($this->ImageMagickThumbnailToGD()) {
3362
				return true;
3363
			}
3364
			$this->DebugMessage('ImageMagickThumbnailToGD() failed', __FILE__, __LINE__);
3365
		}
3366
3367
		$this->source_width  = $this->getimagesizeinfo[0];
3368
		$this->source_height = $this->getimagesizeinfo[1];
3369
3370
		$this->SetOrientationDependantWidthHeight();
3371
3372
		if (phpthumb_functions::version_compare_replacement(phpversion(), '4.2.0', '>=') && function_exists('exif_read_data')) {
3373
			switch ($this->getimagesizeinfo[2]) {
3374
				case IMAGETYPE_JPEG:
3375
				case IMAGETYPE_TIFF_II:
3376
				case IMAGETYPE_TIFF_MM:
3377
					$this->exif_raw_data = @exif_read_data($this->sourceFilename, 0, true);
3378
					break;
3379
			}
3380
		}
3381
		if (function_exists('exif_thumbnail') && ($this->getimagesizeinfo[2] == IMAGETYPE_JPEG)) {
3382
			// Extract EXIF info from JPEGs
3383
3384
			$this->exif_thumbnail_width  = '';
3385
			$this->exif_thumbnail_height = '';
3386
			$this->exif_thumbnail_type   = '';
3387
3388
			// The parameters width, height and imagetype are available since PHP v4.3.0
3389
			if (phpthumb_functions::version_compare_replacement(phpversion(), '4.3.0', '>=')) {
3390
3391
				$this->exif_thumbnail_data = @exif_thumbnail($this->sourceFilename, $this->exif_thumbnail_width, $this->exif_thumbnail_height, $this->exif_thumbnail_type);
0 ignored issues
show
Bug introduced by
$this->exif_thumbnail_height of type string is incompatible with the type integer expected by parameter $height of exif_thumbnail(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

3391
				$this->exif_thumbnail_data = @exif_thumbnail($this->sourceFilename, $this->exif_thumbnail_width, /** @scrutinizer ignore-type */ $this->exif_thumbnail_height, $this->exif_thumbnail_type);
Loading history...
Bug introduced by
$this->exif_thumbnail_type of type string is incompatible with the type integer expected by parameter $imagetype of exif_thumbnail(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

3391
				$this->exif_thumbnail_data = @exif_thumbnail($this->sourceFilename, $this->exif_thumbnail_width, $this->exif_thumbnail_height, /** @scrutinizer ignore-type */ $this->exif_thumbnail_type);
Loading history...
Bug introduced by
$this->exif_thumbnail_width of type string is incompatible with the type integer expected by parameter $width of exif_thumbnail(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

3391
				$this->exif_thumbnail_data = @exif_thumbnail($this->sourceFilename, /** @scrutinizer ignore-type */ $this->exif_thumbnail_width, $this->exif_thumbnail_height, $this->exif_thumbnail_type);
Loading history...
3392
3393
			} else {
3394
3395
				// older versions of exif_thumbnail output an error message but NOT return false on failure
3396
				ob_start();
3397
				$this->exif_thumbnail_data = exif_thumbnail($this->sourceFilename);
3398
				$exit_thumbnail_error = ob_get_contents();
3399
				ob_end_clean();
3400
				if (!$exit_thumbnail_error && $this->exif_thumbnail_data) {
3401
3402
					if ($gdimg_exif_temp = $this->ImageCreateFromStringReplacement($this->exif_thumbnail_data, false)) {
3403
						$this->exif_thumbnail_width  = imagesx($gdimg_exif_temp);
3404
						$this->exif_thumbnail_height = imagesy($gdimg_exif_temp);
3405
						$this->exif_thumbnail_type   = 2; // (2 == JPEG) before PHP v4.3.0 only JPEG format EXIF thumbnails are returned
3406
						unset($gdimg_exif_temp);
3407
					} else {
3408
						return $this->ErrorImage('Failed - $this->ImageCreateFromStringReplacement($this->exif_thumbnail_data) in '.__FILE__.' on line '.__LINE__);
3409
					}
3410
3411
				}
3412
3413
			}
3414
3415
		} elseif (!function_exists('exif_thumbnail')) {
3416
3417
			$this->DebugMessage('exif_thumbnail() does not exist, cannot extract EXIF thumbnail', __FILE__, __LINE__);
3418
3419
		}
3420
3421
		$this->DebugMessage('EXIF thumbnail extraction: (size='.strlen($this->exif_thumbnail_data).'; type="'.$this->exif_thumbnail_type.'"; '.intval($this->exif_thumbnail_width).'x'.intval($this->exif_thumbnail_height).')', __FILE__, __LINE__);
3422
3423
		// see if EXIF thumbnail can be used directly with no processing
3424
		if ($this->config_use_exif_thumbnail_for_speed && $this->exif_thumbnail_data) {
3425
			while (true) {
3426
				if (!$this->xto) {
3427
					$source_ar = $this->source_width / $this->source_height;
3428
					$exif_ar = $this->exif_thumbnail_width / $this->exif_thumbnail_height;
3429 View Code Duplication
					if (number_format($source_ar, 2) != number_format($exif_ar, 2)) {
3430
						$this->DebugMessage('not using EXIF thumbnail because $source_ar != $exif_ar ('.$source_ar.' != '.$exif_ar.')', __FILE__, __LINE__);
3431
						break;
3432
					}
3433
					if ($this->w && ($this->w != $this->exif_thumbnail_width)) {
3434
						$this->DebugMessage('not using EXIF thumbnail because $this->w != $this->exif_thumbnail_width ('.$this->w.' != '.$this->exif_thumbnail_width.')', __FILE__, __LINE__);
3435
						break;
3436
					}
3437
					if ($this->h && ($this->h != $this->exif_thumbnail_height)) {
3438
						$this->DebugMessage('not using EXIF thumbnail because $this->h != $this->exif_thumbnail_height ('.$this->h.' != '.$this->exif_thumbnail_height.')', __FILE__, __LINE__);
3439
						break;
3440
					}
3441
					$CannotBeSetParameters = array('sx', 'sy', 'sh', 'sw', 'far', 'bg', 'bc', 'fltr', 'phpThumbDebug');
3442
					foreach ($CannotBeSetParameters as $parameter) {
3443
						if ($this->$parameter) {
3444
							break 2;
3445
						}
3446
					}
3447
				}
3448
3449
				$this->DebugMessage('setting $this->gdimg_source = $this->ImageCreateFromStringReplacement($this->exif_thumbnail_data)', __FILE__, __LINE__);
3450
				$this->gdimg_source = $this->ImageCreateFromStringReplacement($this->exif_thumbnail_data);
3451
				$this->source_width  = imagesx($this->gdimg_source);
0 ignored issues
show
Bug introduced by
It seems like $this->gdimg_source can also be of type false; however, parameter $image of imagesx() does only seem to accept resource, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

3451
				$this->source_width  = imagesx(/** @scrutinizer ignore-type */ $this->gdimg_source);
Loading history...
3452
				$this->source_height = imagesy($this->gdimg_source);
0 ignored issues
show
Bug introduced by
It seems like $this->gdimg_source can also be of type false; however, parameter $image of imagesy() does only seem to accept resource, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

3452
				$this->source_height = imagesy(/** @scrutinizer ignore-type */ $this->gdimg_source);
Loading history...
3453
				return true;
3454
			}
3455
		}
3456
3457
		if (($this->config_max_source_pixels > 0) && (($this->source_width * $this->source_height) > $this->config_max_source_pixels)) {
3458
3459
			// Source image is larger than would fit in available PHP memory.
3460
			// If ImageMagick is installed, use it to generate the thumbnail.
3461
			// Else, if an EXIF thumbnail is available, use that as the source image.
3462
			// Otherwise, no choice but to fail with an error message
3463
			$this->DebugMessage('image is '.$this->source_width.'x'.$this->source_height.' and therefore contains more pixels ('.($this->source_width * $this->source_height).') than $this->config_max_source_pixels setting ('.$this->config_max_source_pixels.')', __FILE__, __LINE__);
3464
			if (!$this->config_prefer_imagemagick && $this->ImageMagickThumbnailToGD()) {
3465
				// excellent, we have a thumbnailed source image
3466
				return true;
3467
			}
3468
3469
		}
3470
		return true;
3471
	}
3472
3473
3474
	function SetCacheFilename() {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
3475
		if (!is_null($this->cache_filename)) {
3476
			$this->DebugMessage('$this->cache_filename already set, skipping SetCacheFilename()', __FILE__, __LINE__);
3477
			return true;
3478
		}
3479
		if (is_null($this->config_cache_directory)) {
3480
			$this->setCacheDirectory();
3481
			if (!$this->config_cache_directory) {
3482
				$this->DebugMessage('SetCacheFilename() failed because $this->config_cache_directory is empty', __FILE__, __LINE__);
3483
				return false;
3484
			}
3485
		}
3486
		$this->setOutputFormat();
3487
3488
		if (!$this->sourceFilename && !$this->rawImageData && $this->src) {
3489
			$this->sourceFilename = $this->ResolveFilenameToAbsolute($this->src);
3490
		}
3491
3492
		if ($this->config_cache_default_only_suffix && $this->sourceFilename) {
3493
			// simplified cache filenames:
3494
			// only use default parameters in phpThumb.config.php
3495
			// substitute source filename into * in $this->config_cache_default_only_suffix
3496
			// (eg: '*_thumb' becomes 'picture_thumb.jpg')
3497
			if (strpos($this->config_cache_default_only_suffix, '*') === false) {
0 ignored issues
show
Bug introduced by
$this->config_cache_default_only_suffix of type true is incompatible with the type string expected by parameter $haystack of strpos(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

3497
			if (strpos(/** @scrutinizer ignore-type */ $this->config_cache_default_only_suffix, '*') === false) {
Loading history...
3498
				$this->DebugMessage('aborting simplified caching filename because no * in "'.$this->config_cache_default_only_suffix.'"', __FILE__, __LINE__);
3499
			} else {
3500
				preg_match('#(.+)(\\.[a-z0-9]+)?$#i', basename($this->sourceFilename), $matches);
3501
				$this->cache_filename = $this->config_cache_directory.DIRECTORY_SEPARATOR.rawurlencode(str_replace('*', @$matches[1], $this->config_cache_default_only_suffix)).'.'.strtolower($this->thumbnailFormat);
3502
				return true;
3503
			}
3504
		}
3505
3506
		$this->cache_filename = '';
3507
		if ($this->new) {
3508
			$broad_directory_name = strtolower(md5($this->new));
3509
			$this->cache_filename .= '_new'.$broad_directory_name;
3510
		} elseif ($this->md5s) {
3511
			// source image MD5 hash provided
3512
			$this->DebugMessage('SetCacheFilename() _raw set from $this->md5s = "'.$this->md5s.'"', __FILE__, __LINE__);
3513
			$broad_directory_name = $this->md5s;
3514
			$this->cache_filename .= '_raw'.$this->md5s;
3515
		} elseif (!$this->src && $this->rawImageData) {
3516
			$this->DebugMessage('SetCacheFilename() _raw set from md5($this->rawImageData) = "'.md5($this->rawImageData).'"', __FILE__, __LINE__);
3517
			$broad_directory_name = strtolower(md5($this->rawImageData));
3518
			$this->cache_filename .= '_raw'.$broad_directory_name;
3519
		} else {
3520
			$this->DebugMessage('SetCacheFilename() _src set from md5($this->sourceFilename) "'.$this->sourceFilename.'" = "'.md5($this->sourceFilename).'"', __FILE__, __LINE__);
0 ignored issues
show
Bug introduced by
It seems like $this->sourceFilename can also be of type false; however, parameter $str of md5() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

3520
			$this->DebugMessage('SetCacheFilename() _src set from md5($this->sourceFilename) "'.$this->sourceFilename.'" = "'.md5(/** @scrutinizer ignore-type */ $this->sourceFilename).'"', __FILE__, __LINE__);
Loading history...
3521
			$broad_directory_name = strtolower(md5($this->sourceFilename));
3522
			$this->cache_filename .= '_src'.$broad_directory_name;
3523
		}
3524
		if (!empty($_SERVER['HTTP_REFERER']) && $this->config_nooffsitelink_enabled) {
3525
			$parsed_url1 = @phpthumb_functions::ParseURLbetter(@$_SERVER['HTTP_REFERER']);
3526
			$parsed_url2 = @phpthumb_functions::ParseURLbetter('http://'.@$_SERVER['HTTP_HOST']);
3527
			if (@$parsed_url1['host'] && @$parsed_url2['host'] && ($parsed_url1['host'] != $parsed_url2['host'])) {
3528
				// include "_offsite" only if nooffsitelink_enabled and if referrer doesn't match the domain of the current server
3529
				$this->cache_filename .= '_offsite';
3530
			}
3531
		}
3532
3533
		$ParametersString = '';
3534
		if ($this->fltr && is_array($this->fltr)) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $this->fltr of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using ! empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
3535
			$ParametersString .= '_fltr'.implode('_fltr', $this->fltr);
3536
		}
3537
		$FilenameParameters1 = array('ar', 'bg', 'bc', 'far', 'sx', 'sy', 'sw', 'sh', 'zc');
3538
		foreach ($FilenameParameters1 as $key) {
3539
			if ($this->$key) {
3540
				$ParametersString .= '_'.$key.$this->$key;
3541
			}
3542
		}
3543
		$FilenameParameters2 = array('h', 'w', 'wl', 'wp', 'ws', 'hp', 'hs', 'xto', 'ra', 'iar', 'aoe', 'maxb', 'sfn', 'dpi');
3544
		foreach ($FilenameParameters2 as $key) {
3545
			if ($this->$key) {
3546
				$ParametersString .= '_'.$key.intval($this->$key);
3547
			}
3548
		}
3549
		if ($this->thumbnailFormat == 'jpeg') {
3550
			// only JPEG output has variable quality option
3551
			$ParametersString .= '_q'.intval($this->thumbnailQuality);
3552
		}
3553
		$this->DebugMessage('SetCacheFilename() _par set from md5('.$ParametersString.')', __FILE__, __LINE__);
3554
		$this->cache_filename .= '_par'.strtolower(md5($ParametersString));
3555
3556
		if ($this->md5s) {
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...
3557
			// source image MD5 hash provided
3558
			// do not source image modification date --
3559
			// cached image will be used even if file was modified or removed
3560
		} elseif (!$this->config_cache_source_filemtime_ignore_remote && preg_match('#^(f|ht)tps?\://#i', $this->src)) {
3561
			$this->cache_filename .= '_dat'.intval(phpthumb_functions::filedate_remote($this->src));
3562
		} elseif (!$this->config_cache_source_filemtime_ignore_local && $this->src && !$this->rawImageData) {
3563
			$this->cache_filename .= '_dat'.intval(@filemtime($this->sourceFilename));
0 ignored issues
show
Bug introduced by
It seems like $this->sourceFilename can also be of type false; however, parameter $filename of filemtime() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

3563
			$this->cache_filename .= '_dat'.intval(@filemtime(/** @scrutinizer ignore-type */ $this->sourceFilename));
Loading history...
3564
		}
3565
3566
		$this->cache_filename .= '.'.strtolower($this->thumbnailFormat);
3567
		$broad_directories = '';
3568
		for ($i = 0; $i < $this->config_cache_directory_depth; $i++) {
3569
			$broad_directories .= DIRECTORY_SEPARATOR.substr($broad_directory_name, 0, $i + 1);
3570
		}
3571
3572
		$this->cache_filename = $this->config_cache_directory.$broad_directories.DIRECTORY_SEPARATOR.$this->config_cache_prefix.rawurlencode($this->cache_filename);
3573
		return true;
3574
	}
3575
3576
3577
	function SourceImageIsTooLarge($width, $height) {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
3578
		if (!$this->config_max_source_pixels) {
3579
			return false;
3580
		}
3581
		if ($this->php_memory_limit && function_exists('memory_get_usage')) {
3582
			$available_memory = $this->php_memory_limit - memory_get_usage();
3583
			return (bool) (($width * $height * 5) > $available_memory);
3584
		}
3585
		return (bool) (($width * $height) > $this->config_max_source_pixels);
3586
	}
3587
3588
	function ImageCreateFromFilename($filename) {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
3589
		// try to create GD image source directly via GD, if possible,
3590
		// rather than buffering to memory and creating with imagecreatefromstring
3591
		$ImageCreateWasAttempted = false;
3592
		$gd_image = false;
3593
3594
		$this->DebugMessage('starting ImageCreateFromFilename('.$filename.')', __FILE__, __LINE__);
3595
		if ($filename && ($getimagesizeinfo = @getimagesize($filename))) {
3596
			if (!$this->SourceImageIsTooLarge($getimagesizeinfo[0], $getimagesizeinfo[1])) {
3597
				$ImageCreateFromFunction = array(
3598
					1  => 'imagecreatefromgif',
3599
					2  => 'imagecreatefromjpeg',
3600
					3  => 'imagecreatefrompng',
3601
					15 => 'imagecreatefromwbmp',
3602
				);
3603
				$this->DebugMessage('ImageCreateFromFilename found ($getimagesizeinfo[2]=='.@$getimagesizeinfo[2].')', __FILE__, __LINE__);
3604
				switch (@$getimagesizeinfo[2]) {
3605
					case 1:  // GIF
3606
					case 2:  // JPEG
3607
					case 3:  // PNG
3608
					case 15: // WBMP
3609
						$ImageCreateFromFunctionName = $ImageCreateFromFunction[$getimagesizeinfo[2]];
3610
						if (function_exists($ImageCreateFromFunctionName)) {
3611
							$this->DebugMessage('Calling '.$ImageCreateFromFunctionName.'('.$filename.')', __FILE__, __LINE__);
3612
							$ImageCreateWasAttempted = true;
3613
							$gd_image = $ImageCreateFromFunctionName($filename);
3614
						} else {
3615
							$this->DebugMessage('NOT calling '.$ImageCreateFromFunctionName.'('.$filename.') because !function_exists('.$ImageCreateFromFunctionName.')', __FILE__, __LINE__);
3616
						}
3617
						break;
3618
3619
					case 4:  // SWF
3620
					case 5:  // PSD
3621
					case 6:  // BMP
3622
					case 7:  // TIFF (LE)
3623
					case 8:  // TIFF (BE)
3624
					case 9:  // JPC
3625
					case 10: // JP2
3626
					case 11: // JPX
3627
					case 12: // JB2
3628
					case 13: // SWC
3629
					case 14: // IFF
3630
					case 16: // XBM
3631
						$this->DebugMessage('No built-in image creation function for image type "'.@$getimagesizeinfo[2].'" ($getimagesizeinfo[2])', __FILE__, __LINE__);
3632
						break;
3633
3634
					default:
3635
						$this->DebugMessage('Unknown value for $getimagesizeinfo[2]: "'.@$getimagesizeinfo[2].'"', __FILE__, __LINE__);
3636
						break;
3637
				}
3638
			} else {
3639
				$this->DebugMessage('image is '.$getimagesizeinfo[0].'x'.$getimagesizeinfo[1].' and therefore contains more pixels ('.($getimagesizeinfo[0] * $getimagesizeinfo[1]).') than $this->config_max_source_pixels setting ('.$this->config_max_source_pixels.')', __FILE__, __LINE__);
3640
				return false;
3641
			}
3642
		} else {
3643
			$this->DebugMessage('empty $filename or getimagesize('.$filename.') failed', __FILE__, __LINE__);
3644
		}
3645
3646
		if (!$gd_image) {
3647
			// cannot create from filename, attempt to create source image with imagecreatefromstring, if possible
3648
			if ($ImageCreateWasAttempted) {
3649
				$this->DebugMessage($ImageCreateFromFunctionName.'() was attempted but FAILED', __FILE__, __LINE__);
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $ImageCreateFromFunctionName does not seem to be defined for all execution paths leading up to this point.
Loading history...
3650
			}
3651
			$this->DebugMessage('Populating $rawimagedata', __FILE__, __LINE__);
3652
			$rawimagedata = '';
3653
			if ($fp = @fopen($filename, 'rb')) {
3654
				$filesize = filesize($filename);
3655
				$blocksize = 8192;
3656
				$blockreads = ceil($filesize / $blocksize);
3657
				for ($i = 0; $i < $blockreads; $i++) {
3658
					$rawimagedata .= fread($fp, $blocksize);
3659
				}
3660
				fclose($fp);
3661
			} else {
3662
				$this->DebugMessage('cannot fopen('.$filename.')', __FILE__, __LINE__);
3663
			}
3664
			if ($rawimagedata) {
3665
				$this->DebugMessage('attempting ImageCreateFromStringReplacement($rawimagedata ('.strlen($rawimagedata).' bytes), true)', __FILE__, __LINE__);
3666
				$gd_image = $this->ImageCreateFromStringReplacement($rawimagedata, true);
3667
			}
3668
		}
3669
		return $gd_image;
3670
	}
3671
3672
	function SourceImageToGD() {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
3673
		if (is_resource($this->gdimg_source)) {
3674
			$this->source_width  = imagesx($this->gdimg_source);
3675
			$this->source_height = imagesy($this->gdimg_source);
3676
			$this->DebugMessage('skipping SourceImageToGD() because $this->gdimg_source is already a resource ('.$this->source_width.'x'.$this->source_height.')', __FILE__, __LINE__);
3677
			return true;
3678
		}
3679
		$this->DebugMessage('starting SourceImageToGD()', __FILE__, __LINE__);
3680
3681
		if ($this->config_prefer_imagemagick) {
3682
			if (empty($this->sourceFilename) && !empty($this->rawImageData)) {
3683
				$this->DebugMessage('Copying raw image data to temp file and trying again with ImageMagick', __FILE__, __LINE__);
3684
				if ($tempnam = $this->phpThumb_tempnam()) {
3685
					if (file_put_contents($tempnam, $this->rawImageData)) {
3686
						$this->sourceFilename = $tempnam;
3687
						if ($this->ImageMagickThumbnailToGD()) {
3688
							// excellent, we have a thumbnailed source image
3689
							$this->DebugMessage('ImageMagickThumbnailToGD() succeeded', __FILE__, __LINE__);
3690
						} else {
3691
							$this->DebugMessage('ImageMagickThumbnailToGD() failed', __FILE__, __LINE__);
3692
						}
3693
						@chmod($tempnam, $this->getParameter('config_file_create_mask'));
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition for chmod(). This can introduce security issues, and is generally not recommended. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unhandled  annotation

3693
						/** @scrutinizer ignore-unhandled */ @chmod($tempnam, $this->getParameter('config_file_create_mask'));

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...
3694
					} else {
3695
						$this->DebugMessage('failed to put $this->rawImageData into temp file "'.$tempnam.'"', __FILE__, __LINE__);
3696
					}
3697
				} else {
3698
					$this->DebugMessage('failed to generate temp file name', __FILE__, __LINE__);
3699
				}
3700
			}
3701
		}
3702
		if (!$this->gdimg_source && $this->rawImageData) {
3703
3704
			if ($this->SourceImageIsTooLarge($this->source_width, $this->source_height)) {
3705
				$memory_get_usage = (function_exists('memory_get_usage') ? memory_get_usage() : 0);
3706
				return $this->ErrorImage('Source image is too large ('.$this->source_width.'x'.$this->source_height.' = '.number_format($this->source_width * $this->source_height / 1000000, 1).'Mpx, max='.number_format($this->config_max_source_pixels / 1000000, 1).'Mpx) for GD creation (either install ImageMagick or increase PHP memory_limit to at least '.ceil(($memory_get_usage + (5 * $this->source_width * $this->source_height)) / 1048576).'M).');
3707
			}
3708 View Code Duplication
			if ($this->md5s && ($this->md5s != md5($this->rawImageData))) {
3709
				return $this->ErrorImage('$this->md5s != md5($this->rawImageData)'."\n".'"'.$this->md5s.'" != '."\n".'"'.md5($this->rawImageData).'"');
3710
			}
3711
			//if ($this->issafemode) {
3712
			//	return $this->ErrorImage('Cannot generate thumbnails from raw image data when PHP SAFE_MODE enabled');
3713
			//}
3714
			$this->gdimg_source = $this->ImageCreateFromStringReplacement($this->rawImageData);
3715
			if (!$this->gdimg_source) {
3716
				if (substr($this->rawImageData, 0, 2) === 'BM') {
3717
					$this->getimagesizeinfo[2] = 6; // BMP
3718
				} elseif (substr($this->rawImageData, 0, 4) === 'II'."\x2A\x00") {
3719
					$this->getimagesizeinfo[2] = 7; // TIFF (littlendian)
3720
				} elseif (substr($this->rawImageData, 0, 4) === 'MM'."\x00\x2A") {
3721
					$this->getimagesizeinfo[2] = 8; // TIFF (bigendian)
3722
				}
3723
				$this->DebugMessage('SourceImageToGD.ImageCreateFromStringReplacement() failed with unknown image type "'.substr($this->rawImageData, 0, 4).'" ('.phpthumb_functions::HexCharDisplay(substr($this->rawImageData, 0, 4)).')', __FILE__, __LINE__);
3724
//				return $this->ErrorImage('Unknown image type identified by "'.substr($this->rawImageData, 0, 4).'" ('.phpthumb_functions::HexCharDisplay(substr($this->rawImageData, 0, 4)).') in SourceImageToGD()['.__LINE__.']');
3725
			}
3726
3727
		} elseif (!$this->gdimg_source && $this->sourceFilename) {
3728
3729 View Code Duplication
			if ($this->md5s && ($this->md5s != phpthumb_functions::md5_file_safe($this->sourceFilename))) {
3730
				return $this->ErrorImage('$this->md5s != md5(sourceFilename)'."\n".'"'.$this->md5s.'" != '."\n".'"'.phpthumb_functions::md5_file_safe($this->sourceFilename).'"');
0 ignored issues
show
Bug introduced by
Are you sure phpthumb_functions::md5_...($this->sourceFilename) of type false|string can be used in concatenation? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

3730
				return $this->ErrorImage('$this->md5s != md5(sourceFilename)'."\n".'"'.$this->md5s.'" != '."\n".'"'./** @scrutinizer ignore-type */ phpthumb_functions::md5_file_safe($this->sourceFilename).'"');
Loading history...
3731
			}
3732
			switch (@$this->getimagesizeinfo[2]) {
3733
				case 1:
3734
				case 3:
3735
					// GIF or PNG input file may have transparency
3736
					$this->is_alpha = true;
3737
					break;
3738
			}
3739
			if (!$this->SourceImageIsTooLarge($this->source_width, $this->source_height)) {
3740
				$this->gdimg_source = $this->ImageCreateFromFilename($this->sourceFilename);
3741
			}
3742
3743
		}
3744
3745
		while (true) {
3746
			if ($this->gdimg_source) {
3747
				$this->DebugMessage('Not using EXIF thumbnail data because $this->gdimg_source is already set', __FILE__, __LINE__);
3748
				break;
3749
			}
3750
			if (!$this->exif_thumbnail_data) {
3751
				$this->DebugMessage('Not using EXIF thumbnail data because $this->exif_thumbnail_data is empty', __FILE__, __LINE__);
3752
				break;
3753
			}
3754
			if (ini_get('safe_mode')) {
3755
				if (!$this->SourceImageIsTooLarge($this->source_width, $this->source_height)) {
3756
					$this->DebugMessage('Using EXIF thumbnail data because source image too large and safe_mode enabled', __FILE__, __LINE__);
3757
					$this->aoe = true;
3758
				} else {
3759
					break;
3760
				}
3761
			} else {
3762
				if (!$this->config_use_exif_thumbnail_for_speed) {
3763
					$this->DebugMessage('Not using EXIF thumbnail data because $this->config_use_exif_thumbnail_for_speed is FALSE', __FILE__, __LINE__);
3764
					break;
3765
				}
3766
				if (($this->thumbnailCropX != 0) || ($this->thumbnailCropY != 0)) {
3767
					$this->DebugMessage('Not using EXIF thumbnail data because source cropping is enabled ('.$this->thumbnailCropX.','.$this->thumbnailCropY.')', __FILE__, __LINE__);
3768
					break;
3769
				}
3770
				if (($this->w > $this->exif_thumbnail_width) || ($this->h > $this->exif_thumbnail_height)) {
3771
					$this->DebugMessage('Not using EXIF thumbnail data because EXIF thumbnail is too small ('.$this->exif_thumbnail_width.'x'.$this->exif_thumbnail_height.' vs '.$this->w.'x'.$this->h.')', __FILE__, __LINE__);
3772
					break;
3773
				}
3774
				$source_ar = $this->source_width / $this->source_height;
3775
				$exif_ar   = $this->exif_thumbnail_width / $this->exif_thumbnail_height;
3776 View Code Duplication
				if (number_format($source_ar, 2) != number_format($exif_ar, 2)) {
3777
					$this->DebugMessage('not using EXIF thumbnail because $source_ar != $exif_ar ('.$source_ar.' != '.$exif_ar.')', __FILE__, __LINE__);
3778
					break;
3779
				}
3780
			}
3781
3782
			// EXIF thumbnail exists, and is equal to or larger than destination thumbnail, and will be use as source image
3783
			$this->DebugMessage('Trying to use EXIF thumbnail as source image', __FILE__, __LINE__);
3784
3785
			if ($gdimg_exif_temp = $this->ImageCreateFromStringReplacement($this->exif_thumbnail_data, false)) {
3786
3787
				$this->DebugMessage('Successfully using EXIF thumbnail as source image', __FILE__, __LINE__);
3788
				$this->gdimg_source   = $gdimg_exif_temp;
3789
				$this->source_width   = $this->exif_thumbnail_width;
3790
				$this->source_height  = $this->exif_thumbnail_height;
3791
				$this->thumbnailCropW = $this->source_width;
3792
				$this->thumbnailCropH = $this->source_height;
3793
				return true;
3794
3795
			} else {
3796
				$this->DebugMessage('$this->ImageCreateFromStringReplacement($this->exif_thumbnail_data, false) failed', __FILE__, __LINE__);
3797
			}
3798
3799
			break;
3800
		}
3801
3802
		if (!$this->gdimg_source) {
3803
			$this->DebugMessage('$this->gdimg_source is still empty', __FILE__, __LINE__);
3804
3805
			$this->DebugMessage('ImageMagickThumbnailToGD() failed', __FILE__, __LINE__);
3806
3807
			$imageHeader = '';
3808
			$gd_info = gd_info();
3809
			$GDreadSupport = false;
3810
			switch (@$this->getimagesizeinfo[2]) {
3811
				case 1:
3812
					$imageHeader = 'Content-Type: image/gif';
3813
					$GDreadSupport = (bool) @$gd_info['GIF Read Support'];
3814
					break;
3815
				case 2:
3816
					$imageHeader = 'Content-Type: image/jpeg';
3817
					$GDreadSupport = (bool) @$gd_info['JPEG Support'] || (bool) @$gd_info['JPG Support']; // changed for XOOPS
3818
					break;
3819
				case 3:
3820
					$imageHeader = 'Content-Type: image/png';
3821
					$GDreadSupport = (bool) @$gd_info['PNG Support'];
3822
					break;
3823
			}
3824
			if ($imageHeader) {
3825
				// cannot create image for whatever reason (maybe imagecreatefromjpeg et al are not available?)
3826
				// and ImageMagick is not available either, no choice but to output original (not resized/modified) data and exit
3827
				if ($this->config_error_die_on_source_failure) {
3828
					$errormessages = array();
3829
					$errormessages[] = 'All attempts to create GD image source failed.';
3830
					if ($this->fatalerror) {
3831
						$errormessages[] = $this->fatalerror;
3832
					}
3833
					if ($this->issafemode) {
3834
						$errormessages[] = 'Safe Mode enabled, therefore ImageMagick is unavailable. (disable Safe Mode if possible)';
3835
					} elseif (!$this->ImageMagickVersion()) {
3836
						$errormessages[] = 'ImageMagick is not installed (it is highly recommended that you install it).';
3837
					}
3838
					if ($this->SourceImageIsTooLarge($this->getimagesizeinfo[0], $this->getimagesizeinfo[1])) {
3839
						$memory_get_usage = (function_exists('memory_get_usage') ? memory_get_usage() : 0);
3840
						$errormessages[] = 'Source image is too large ('.$this->getimagesizeinfo[0].'x'.$this->getimagesizeinfo[1].' = '.number_format($this->getimagesizeinfo[0] * $this->getimagesizeinfo[1] / 1000000, 1).'Mpx, max='.number_format($this->config_max_source_pixels / 1000000, 1).'Mpx) for GD creation (either install ImageMagick or increase PHP memory_limit to at least '.ceil(($memory_get_usage + (5 * $this->getimagesizeinfo[0] * $this->getimagesizeinfo[1])) / 1048576).'M).';
3841
					} elseif (!$GDreadSupport) {
3842
						$errormessages[] = 'GD does not have read support for "'.$imageHeader.'".';
3843
					} else {
3844
						$errormessages[] = 'Source image probably corrupt.';
3845
					}
3846
					$this->ErrorImage(implode("\n", $errormessages));
3847
3848
				} else {
3849
					$this->DebugMessage('All attempts to create GD image source failed ('.(ini_get('safe_mode') ? 'Safe Mode enabled, ImageMagick unavailable and source image probably too large for GD': ($GDreadSupport ? 'source image probably corrupt' : 'GD does not have read support for "'.$imageHeader.'"')).'), cannot generate thumbnail');
3850
					//$this->DebugMessage('All attempts to create GD image source failed ('.($GDreadSupport ? 'source image probably corrupt' : 'GD does not have read support for "'.$imageHeader.'"').'), outputing raw image', __FILE__, __LINE__);
3851
					//if (!$this->phpThumbDebug) {
3852
					//	header($imageHeader);
3853
					//	echo $this->rawImageData;
3854
					//	exit;
3855
					//}
3856
					return false;
3857
				}
3858
			}
3859
3860
			//switch (substr($this->rawImageData, 0, 2)) {
3861
			//	case 'BM':
3862
			switch (@$this->getimagesizeinfo[2]) {
3863
				case 6:
3864
					ob_start();
3865
					if (!@include_once(dirname(__FILE__).'/phpthumb.bmp.php')) {
3866
						ob_end_clean();
3867
						return $this->ErrorImage('include_once('.dirname(__FILE__).'/phpthumb.bmp.php) failed');
3868
					}
3869
					ob_end_clean();
3870
					if ($fp = @fopen($this->sourceFilename, 'rb')) {
3871
						$this->rawImageData = '';
3872
						while (!feof($fp)) {
3873
							$this->rawImageData .= fread($fp, 32768);
3874
						}
3875
						fclose($fp);
3876
					}
3877
					$phpthumb_bmp = new phpthumb_bmp();
3878
					$this->gdimg_source = $phpthumb_bmp->phpthumb_bmp2gd($this->rawImageData, (phpthumb_functions::gd_version() >= 2.0));
3879
					unset($phpthumb_bmp);
3880
					if ($this->gdimg_source) {
3881
						$this->DebugMessage('$phpthumb_bmp->phpthumb_bmp2gd() succeeded', __FILE__, __LINE__);
3882
					} else {
3883
						return $this->ErrorImage($this->ImageMagickVersion() ? 'ImageMagick failed on BMP source conversion' : 'phpthumb_bmp2gd() failed');
3884
					}
3885
					break;
3886
			//}
3887
			//switch (substr($this->rawImageData, 0, 4)) {
3888
			//	case 'II'."\x2A\x00":
3889
			//	case 'MM'."\x00\x2A":
3890
				case 7:
3891
				case 8:
3892
					return $this->ErrorImage($this->ImageMagickVersion() ? 'ImageMagick failed on TIFF source conversion' : 'ImageMagick is unavailable and phpThumb() does not support TIFF source images without it');
3893
					break;
0 ignored issues
show
Unused Code introduced by
break is not strictly necessary here and could be removed.

The break statement is not necessary if it is preceded for example by a return statement:

switch ($x) {
    case 1:
        return 'foo';
        break; // This break is not necessary and can be left off.
}

If you would like to keep this construct to be consistent with other case statements, you can safely mark this issue as a false-positive.

Loading history...
3894
3895
				//case "\xD7\xCD\xC6\x9A":
3896
				//	return $this->ErrorImage($this->ImageMagickVersion() ? 'ImageMagick failed on WMF source conversion' : 'ImageMagick is unavailable and phpThumb() does not support WMF source images without it');
3897
				//	break;
3898
			}
3899
3900
			if (!$this->gdimg_source) {
3901
				if ($this->rawImageData) {
3902
					$HeaderFourBytes = substr($this->rawImageData, 0, 4);
3903
				} elseif ($this->sourceFilename) {
3904
					if ($fp = @fopen($this->sourceFilename, 'rb')) {
3905
						$HeaderFourBytes = fread($fp, 4);
3906
						fclose($fp);
3907
					} else {
3908
						return $this->ErrorImage('failed to open "'.$this->sourceFilename.'" SourceImageToGD() ['.__LINE__.']');
3909
					}
3910
				} else {
3911
					return $this->ErrorImage('Unable to create image, neither filename nor image data suppplied in SourceImageToGD() ['.__LINE__.']');
3912
				}
3913
				if (!$this->ImageMagickVersion() && !phpthumb_functions::gd_version()) {
3914
					return $this->ErrorImage('Neither GD nor ImageMagick seem to be installed on this server. At least one (preferably GD), or better both, MUST be installed for phpThumb to work.');
3915
				} elseif ($HeaderFourBytes == "\xD7\xCD\xC6\x9A") { // WMF
3916
					return $this->ErrorImage($this->ImageMagickVersion() ? 'ImageMagick failed on WMF source conversion' : 'ImageMagick is unavailable and phpThumb() does not support WMF source images without it');
3917
				} elseif ($HeaderFourBytes == '%PDF') { // "%PDF"
3918
					return $this->ErrorImage($this->ImageMagickVersion() ? 'ImageMagick and GhostScript are both required for PDF source images; GhostScript may not be properly configured' : 'ImageMagick and/or GhostScript are unavailable and phpThumb() does not support PDF source images without them');
3919
				} elseif (substr($HeaderFourBytes, 0, 3) == "\xFF\xD8\xFF") { // JPEG
3920
					return $this->ErrorImage('Image (JPEG) is too large for PHP-GD memory_limit, please install ImageMagick or increase php.ini memory_limit setting');
3921
				} elseif ($HeaderFourBytes == '%PNG') { // "%PNG"
3922
					return $this->ErrorImage('Image (PNG) is too large for PHP-GD memory_limit, please install ImageMagick or increase php.ini memory_limit setting');
3923
				} elseif (substr($HeaderFourBytes, 0, 3) == 'GIF') { // GIF
3924
					return $this->ErrorImage('Image (GIF) is too large for PHP-GD memory_limit, please install ImageMagick or increase php.ini memory_limit setting');
3925
				}
3926
				return $this->ErrorImage('Unknown image type identified by "'.$HeaderFourBytes.'" ('.phpthumb_functions::HexCharDisplay($HeaderFourBytes).') in SourceImageToGD() ['.__LINE__.']');
3927
			}
3928
		}
3929
3930
		if (!$this->gdimg_source) {
3931
			if ($gdimg_exif_temp = $this->ImageCreateFromStringReplacement($this->exif_thumbnail_data, false)) {
3932
				$this->DebugMessage('All other attempts failed, but successfully using EXIF thumbnail as source image', __FILE__, __LINE__);
3933
				$this->gdimg_source = $gdimg_exif_temp;
3934
				// override allow-enlarging setting if EXIF thumbnail is the only source available
3935
				// otherwise thumbnails larger than the EXIF thumbnail will be created at EXIF size
3936
				$this->aoe = true;
3937
				return true;
3938
			}
3939
			return false;
3940
		}
3941
3942
		$this->source_width  = imagesx($this->gdimg_source);
3943
		$this->source_height = imagesy($this->gdimg_source);
3944
		return true;
3945
	}
3946
3947
3948
	function phpThumbDebugVarDump($var) {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
3949
		if (is_null($var)) {
3950
			return 'NULL';
3951
		} elseif (is_bool($var)) {
3952
			return ($var ? 'TRUE' : 'FALSE');
3953
		} elseif (is_string($var)) {
3954
			return 'string('.strlen($var).')'.str_repeat(' ', max(0, 3 - strlen(strlen($var)))).' "'.$var.'"';
3955
		} elseif (is_int($var)) {
3956
			return 'integer     '.$var;
3957
		} elseif (is_float($var)) {
3958
			return 'float       '.$var;
3959
		} elseif (is_array($var)) {
3960
			ob_start();
3961
			var_dump($var);
0 ignored issues
show
Security Debugging Code introduced by
var_dump($var) looks like debug code. Are you sure you do not want to remove it?
Loading history...
3962
			$vardumpoutput = ob_get_contents();
3963
			ob_end_clean();
3964
			return strtr($vardumpoutput, "\n\r\t", '   ');
3965
		}
3966
		return gettype($var);
3967
	}
3968
3969
	function phpThumbDebug($level='') {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
3970
		if ($level && ($this->phpThumbDebug !== $level)) {
3971
			return true;
3972
		}
3973
		if ($this->config_disable_debug) {
3974
			return $this->ErrorImage('phpThumbDebug disabled');
3975
		}
3976
3977
		$FunctionsExistance  = array('exif_thumbnail', 'gd_info', 'image_type_to_mime_type', 'getimagesize', 'imagecopyresampled', 'imagecopyresized', 'imagecreate', 'imagecreatefromstring', 'imagecreatetruecolor', 'imageistruecolor', 'imagerotate', 'imagetypes', 'version_compare', 'imagecreatefromgif', 'imagecreatefromjpeg', 'imagecreatefrompng', 'imagecreatefromwbmp', 'imagecreatefromxbm', 'imagecreatefromxpm', 'imagecreatefromstring', 'imagecreatefromgd', 'imagecreatefromgd2', 'imagecreatefromgd2part', 'imagejpeg', 'imagegif', 'imagepng', 'imagewbmp');
3978
		$ParameterNames      = array('src', 'new', 'w', 'h', 'f', 'q', 'sx', 'sy', 'sw', 'sh', 'far', 'bg', 'bc', 'file', 'goto', 'err', 'xto', 'ra', 'ar', 'aoe', 'iar', 'maxb');
3979
		$ConfigVariableNames = array('document_root', 'temp_directory', 'output_format', 'output_maxwidth', 'output_maxheight', 'error_message_image_default', 'error_bgcolor', 'error_textcolor', 'error_fontsize', 'error_die_on_error', 'error_silent_die_on_error', 'error_die_on_source_failure', 'nohotlink_enabled', 'nohotlink_valid_domains', 'nohotlink_erase_image', 'nohotlink_text_message', 'nooffsitelink_enabled', 'nooffsitelink_valid_domains', 'nooffsitelink_require_refer', 'nooffsitelink_erase_image', 'nooffsitelink_text_message', 'high_security_enabled', 'allow_src_above_docroot', 'allow_src_above_phpthumb', 'max_source_pixels', 'use_exif_thumbnail_for_speed', 'border_hexcolor', 'background_hexcolor', 'ttf_directory', 'disable_pathinfo_parsing', 'disable_imagecopyresampled');
3980
		$OtherVariableNames  = array('phpThumbDebug', 'thumbnailQuality', 'thumbnailFormat', 'gdimg_output', 'gdimg_source', 'sourceFilename', 'source_width', 'source_height', 'thumbnailCropX', 'thumbnailCropY', 'thumbnailCropW', 'thumbnailCropH', 'exif_thumbnail_width', 'exif_thumbnail_height', 'exif_thumbnail_type', 'thumbnail_width', 'thumbnail_height', 'thumbnail_image_width', 'thumbnail_image_height');
3981
3982
		$DebugOutput = array();
3983
		$DebugOutput[] = 'phpThumb() version          = '.$this->phpthumb_version;
3984
		$DebugOutput[] = 'phpversion()                = '.@phpversion();
3985
		$DebugOutput[] = 'PHP_OS                      = '.PHP_OS;
3986
		$DebugOutput[] = '$_SERVER[SERVER_SOFTWARE]   = '.@$_SERVER['SERVER_SOFTWARE'];
3987
		$DebugOutput[] = '__FILE__                    = '.__FILE__;
3988
		$DebugOutput[] = 'realpath(.)                 = '.@realpath('.');
3989
		$DebugOutput[] = '$_SERVER[PHP_SELF]          = '.@$_SERVER['PHP_SELF'];
3990
		$DebugOutput[] = '$_SERVER[HOST_NAME]         = '.@$_SERVER['HOST_NAME'];
3991
		$DebugOutput[] = '$_SERVER[HTTP_REFERER]      = '.@$_SERVER['HTTP_REFERER'];
3992
		$DebugOutput[] = '$_SERVER[QUERY_STRING]      = '.@$_SERVER['QUERY_STRING'];
3993
		$DebugOutput[] = '$_SERVER[PATH_INFO]         = '.@$_SERVER['PATH_INFO'];
3994
		$DebugOutput[] = '$_SERVER[DOCUMENT_ROOT]     = '.@$_SERVER['DOCUMENT_ROOT'];
3995
		$DebugOutput[] = 'getenv(DOCUMENT_ROOT)       = '.@getenv('DOCUMENT_ROOT');
3996
		$DebugOutput[] = '';
3997
3998
		$DebugOutput[] = 'get_magic_quotes_gpc()         = '.$this->phpThumbDebugVarDump(@get_magic_quotes_gpc());
3999
		$DebugOutput[] = 'get_magic_quotes_runtime()     = '.$this->phpThumbDebugVarDump(@get_magic_quotes_runtime());
4000
		$DebugOutput[] = 'error_reporting()              = '.$this->phpThumbDebugVarDump(error_reporting());
4001
		$DebugOutput[] = 'ini_get(error_reporting)       = '.$this->phpThumbDebugVarDump(@ini_get('error_reporting'));
4002
		$DebugOutput[] = 'ini_get(display_errors)        = '.$this->phpThumbDebugVarDump(@ini_get('display_errors'));
4003
		$DebugOutput[] = 'ini_get(allow_url_fopen)       = '.$this->phpThumbDebugVarDump(@ini_get('allow_url_fopen'));
4004
		$DebugOutput[] = 'ini_get(disable_functions)     = '.$this->phpThumbDebugVarDump(@ini_get('disable_functions'));
4005
		$DebugOutput[] = 'get_cfg_var(disable_functions) = '.$this->phpThumbDebugVarDump(@get_cfg_var('disable_functions'));
4006
		$DebugOutput[] = 'ini_get(safe_mode)             = '.$this->phpThumbDebugVarDump(@ini_get('safe_mode'));
4007
		$DebugOutput[] = 'ini_get(open_basedir)          = '.$this->phpThumbDebugVarDump(@ini_get('open_basedir'));
4008
		$DebugOutput[] = 'ini_get(max_execution_time)    = '.$this->phpThumbDebugVarDump(@ini_get('max_execution_time'));
4009
		$DebugOutput[] = 'ini_get(memory_limit)          = '.$this->phpThumbDebugVarDump(@ini_get('memory_limit'));
4010
		$DebugOutput[] = 'get_cfg_var(memory_limit)      = '.$this->phpThumbDebugVarDump(@get_cfg_var('memory_limit'));
4011
		$DebugOutput[] = 'memory_get_usage()             = '.(function_exists('memory_get_usage') ? $this->phpThumbDebugVarDump(@memory_get_usage()) : 'n/a');
4012
		$DebugOutput[] = '';
4013
4014
		$DebugOutput[] = '$this->config_prefer_imagemagick            = '.$this->phpThumbDebugVarDump($this->config_prefer_imagemagick);
4015
		$DebugOutput[] = '$this->config_imagemagick_path              = '.$this->phpThumbDebugVarDump($this->config_imagemagick_path);
4016
		$DebugOutput[] = '$this->ImageMagickWhichConvert()            = '.$this->ImageMagickWhichConvert();
0 ignored issues
show
Bug introduced by
Are you sure $this->ImageMagickWhichConvert() of type false|string can be used in concatenation? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

4016
		$DebugOutput[] = '$this->ImageMagickWhichConvert()            = './** @scrutinizer ignore-type */ $this->ImageMagickWhichConvert();
Loading history...
4017
		$IMpathUsed = ($this->config_imagemagick_path ? $this->config_imagemagick_path : $this->ImageMagickWhichConvert());
4018
		$DebugOutput[] = '[actual ImageMagick path used]              = '.$this->phpThumbDebugVarDump($IMpathUsed);
4019
		$DebugOutput[] = 'file_exists([actual ImageMagick path used]) = '.$this->phpThumbDebugVarDump(@file_exists($IMpathUsed));
0 ignored issues
show
Bug introduced by
It seems like $IMpathUsed can also be of type false; however, parameter $filename of file_exists() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

4019
		$DebugOutput[] = 'file_exists([actual ImageMagick path used]) = '.$this->phpThumbDebugVarDump(@file_exists(/** @scrutinizer ignore-type */ $IMpathUsed));
Loading history...
4020
		$DebugOutput[] = 'ImageMagickVersion(false)                   = '.$this->ImageMagickVersion(false);
4021
		$DebugOutput[] = 'ImageMagickVersion(true)                    = '.$this->ImageMagickVersion(true);
4022
		$DebugOutput[] = '';
4023
4024
		$DebugOutput[] = '$this->config_cache_directory               = '.$this->phpThumbDebugVarDump($this->config_cache_directory);
4025
		$DebugOutput[] = '$this->config_cache_directory_depth         = '.$this->phpThumbDebugVarDump($this->config_cache_directory_depth);
4026
		$DebugOutput[] = '$this->config_cache_disable_warning         = '.$this->phpThumbDebugVarDump($this->config_cache_disable_warning);
4027
		$DebugOutput[] = '$this->config_cache_maxage                  = '.$this->phpThumbDebugVarDump($this->config_cache_maxage);
4028
		$DebugOutput[] = '$this->config_cache_maxsize                 = '.$this->phpThumbDebugVarDump($this->config_cache_maxsize);
4029
		$DebugOutput[] = '$this->config_cache_maxfiles                = '.$this->phpThumbDebugVarDump($this->config_cache_maxfiles);
4030
		$DebugOutput[] = '$this->config_cache_force_passthru          = '.$this->phpThumbDebugVarDump($this->config_cache_force_passthru);
4031
		$DebugOutput[] = '$this->cache_filename                       = '.$this->phpThumbDebugVarDump($this->cache_filename);
4032
		$DebugOutput[] = 'is_readable($this->config_cache_directory)  = '.$this->phpThumbDebugVarDump(@is_readable($this->config_cache_directory));
4033
		$DebugOutput[] = 'is_writable($this->config_cache_directory)  = '.$this->phpThumbDebugVarDump(@is_writable($this->config_cache_directory));
4034
		$DebugOutput[] = 'is_readable($this->cache_filename)          = '.$this->phpThumbDebugVarDump(@is_readable($this->cache_filename));
4035
		$DebugOutput[] = 'is_writable($this->cache_filename)          = '.(@file_exists($this->cache_filename) ? $this->phpThumbDebugVarDump(@is_writable($this->cache_filename)) : 'n/a');
4036
		$DebugOutput[] = '';
4037
4038
		foreach ($ConfigVariableNames as $varname) {
4039
			$varname = 'config_'.$varname;
4040
			$value = $this->$varname;
4041
			$DebugOutput[] = '$this->'.str_pad($varname, 37, ' ', STR_PAD_RIGHT).' = '.$this->phpThumbDebugVarDump($value);
4042
		}
4043
		$DebugOutput[] = '';
4044 View Code Duplication
		foreach ($OtherVariableNames as $varname) {
4045
			$value = $this->$varname;
4046
			$DebugOutput[] = '$this->'.str_pad($varname, 27, ' ', STR_PAD_RIGHT).' = '.$this->phpThumbDebugVarDump($value);
4047
		}
4048
		$DebugOutput[] = 'strlen($this->rawImageData)        = '.strlen(@$this->rawImageData);
4049
		$DebugOutput[] = 'strlen($this->exif_thumbnail_data) = '.strlen(@$this->exif_thumbnail_data);
4050
		$DebugOutput[] = '';
4051
4052 View Code Duplication
		foreach ($ParameterNames as $varname) {
4053
			$value = $this->$varname;
4054
			$DebugOutput[] = '$this->'.str_pad($varname, 4, ' ', STR_PAD_RIGHT).' = '.$this->phpThumbDebugVarDump($value);
4055
		}
4056
		$DebugOutput[] = '';
4057
4058
		foreach ($FunctionsExistance as $functionname) {
4059
			$DebugOutput[] = 'builtin_function_exists('.$functionname.')'.str_repeat(' ', 23 - strlen($functionname)).' = '.$this->phpThumbDebugVarDump(phpthumb_functions::builtin_function_exists($functionname));
4060
		}
4061
		$DebugOutput[] = '';
4062
4063
		$gd_info = gd_info();
4064 View Code Duplication
		foreach ($gd_info as $key => $value) {
4065
			$DebugOutput[] = 'gd_info.'.str_pad($key, 34, ' ', STR_PAD_RIGHT).' = '.$this->phpThumbDebugVarDump($value);
4066
		}
4067
		$DebugOutput[] = '';
4068
4069
		$exif_info = phpthumb_functions::exif_info();
4070 View Code Duplication
		foreach ($exif_info as $key => $value) {
4071
			$DebugOutput[] = 'exif_info.'.str_pad($key, 26, ' ', STR_PAD_RIGHT).' = '.$this->phpThumbDebugVarDump($value);
4072
		}
4073
		$DebugOutput[] = '';
4074
4075
		if ($ApacheLookupURIarray = phpthumb_functions::ApacheLookupURIarray(dirname(@$_SERVER['PHP_SELF']))) {
4076 View Code Duplication
			foreach ($ApacheLookupURIarray as $key => $value) {
4077
				$DebugOutput[] = 'ApacheLookupURIarray.'.str_pad($key, 15, ' ', STR_PAD_RIGHT).' = '.$this->phpThumbDebugVarDump($value);
4078
			}
4079
		} else {
4080
				$DebugOutput[] = 'ApacheLookupURIarray() -- FAILED';
4081
		}
4082
		$DebugOutput[] = '';
4083
4084 View Code Duplication
		if (isset($_GET) && is_array($_GET)) {
4085
			foreach ($_GET as $key => $value) {
4086
				$DebugOutput[] = '$_GET['.$key.']'.str_repeat(' ', 30 - strlen($key)).'= '.$this->phpThumbDebugVarDump($value);
4087
			}
4088
		}
4089 View Code Duplication
		if (isset($_POST) && is_array($_POST)) {
4090
			foreach ($_POST as $key => $value) {
4091
				$DebugOutput[] = '$_POST['.$key.']'.str_repeat(' ', 29 - strlen($key)).'= '.$this->phpThumbDebugVarDump($value);
4092
			}
4093
		}
4094
		$DebugOutput[] = '';
4095
4096
		$DebugOutput[] = '$this->debugmessages:';
4097
		foreach ($this->debugmessages as $errorstring) {
4098
			$DebugOutput[] = '  * '.$errorstring;
4099
		}
4100
		$DebugOutput[] = '';
4101
4102
		$DebugOutput[] = '$this->debugtiming:';
4103
		foreach ($this->debugtiming as $timestamp => $timingstring) {
4104
			$DebugOutput[] = '  * '.$timestamp.' '.$timingstring;
4105
		}
4106
		$DebugOutput[] = '  * Total processing time: '.number_format(max(array_keys($this->debugtiming)) - min(array_keys($this->debugtiming)), 6);
4107
4108
		$this->f = (isset($_GET['f']) ? $_GET['f'] : $this->f); // debug modes 0-2 don't recognize text mode otherwise
4109
		return $this->ErrorImage(implode("\n", $DebugOutput), 700, 500, true);
4110
	}
4111
4112
	function FatalError($text) {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
4113
		if (is_null($this->fatalerror)) {
4114
			$this->fatalerror = $text;
4115
		}
4116
		return true;
4117
	}
4118
4119
	function ErrorImage($text, $width=0, $height=0, $forcedisplay=false) {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
4120
		$width  = ($width  ? $width  : $this->config_error_image_width);
4121
		$height = ($height ? $height : $this->config_error_image_height);
4122
4123
		$text = 'phpThumb() v'.$this->phpthumb_version."\n".'http://phpthumb.sourceforge.net'."\n\n".($this->config_disable_debug ? 'Error messages disabled.'."\n\n".'edit phpThumb.config.php and (temporarily) set'."\n".'$PHPTHUMB_CONFIG[\'disable_debug\'] = false;'."\n".'to view the details of this error' : $text);
4124
4125
		$this->FatalError($text);
4126
		$this->DebugMessage($text, __FILE__, __LINE__);
4127
		$this->purgeTempFiles();
4128
		if ($this->config_error_silent_die_on_error) {
4129
			exit;
0 ignored issues
show
Best Practice introduced by
Using exit here is not recommended.

In general, usage of exit should be done with care and only when running in a scripting context like a CLI script.

Loading history...
4130
		}
4131
		if ($this->phpThumbDebug && !$forcedisplay) {
4132
			return false;
4133
		}
4134
		if (!$this->config_error_die_on_error && !$forcedisplay) {
4135
			return false;
4136
		}
4137
		if ($this->err || $this->config_error_message_image_default) {
4138
			// Show generic custom error image instead of error message
4139
			// for use on production sites where you don't want debug messages
4140
			if (($this->err == 'showerror') || $this->phpThumbDebug) {
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...
4141
				// fall through and actually show error message even if default error image is set
4142
			} else {
4143
				header('Location: '.($this->err ? $this->err : $this->config_error_message_image_default));
4144
				exit;
0 ignored issues
show
Best Practice introduced by
Using exit here is not recommended.

In general, usage of exit should be done with care and only when running in a scripting context like a CLI script.

Loading history...
4145
			}
4146
		}
4147
		$this->setOutputFormat();
4148
		if (!$this->thumbnailFormat || !$this->config_disable_debug || (phpthumb_functions::gd_version() < 1)) {
4149
			$this->thumbnailFormat = 'text';
4150
		}
4151
		if (@$this->thumbnailFormat == 'text') {
4152
			// bypass all GD functions and output text error message
4153
			if (!headers_sent()) {
4154
				header('Content-type: text/plain');
4155
				echo $text;
4156
			} else {
4157
				echo '<pre>'.htmlspecialchars($text).'</pre>';
4158
			}
4159
			exit;
0 ignored issues
show
Best Practice introduced by
Using exit here is not recommended.

In general, usage of exit should be done with care and only when running in a scripting context like a CLI script.

Loading history...
4160
		}
4161
4162
		$FontWidth  = imagefontwidth($this->config_error_fontsize);
4163
		$FontHeight = imagefontheight($this->config_error_fontsize);
4164
4165
		$LinesOfText = explode("\n", @wordwrap($text, floor($width / $FontWidth), "\n", true));
0 ignored issues
show
Bug introduced by
floor($width / $FontWidth) of type double is incompatible with the type integer expected by parameter $width of wordwrap(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

4165
		$LinesOfText = explode("\n", @wordwrap($text, /** @scrutinizer ignore-type */ floor($width / $FontWidth), "\n", true));
Loading history...
4166
		$height = max($height, count($LinesOfText) * $FontHeight);
4167
4168
		$headers_file = '';
4169
		$headers_line = '';
4170
		if (phpthumb_functions::version_compare_replacement(phpversion(), '4.3.0', '>=') && headers_sent($headers_file, $headers_line)) {
0 ignored issues
show
Bug introduced by
$headers_line of type string is incompatible with the type integer expected by parameter $line of headers_sent(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

4170
		if (phpthumb_functions::version_compare_replacement(phpversion(), '4.3.0', '>=') && headers_sent($headers_file, /** @scrutinizer ignore-type */ $headers_line)) {
Loading history...
4171
4172
			echo "\n".'**Headers already sent in file "'.$headers_file.'" on line "'.$headers_line.'", dumping error message as text:**<br><pre>'."\n\n".$text."\n".'</pre>';
4173
4174
		} elseif (headers_sent()) {
4175
4176
			echo "\n".'**Headers already sent, dumping error message as text:**<br><pre>'."\n\n".$text."\n".'</pre>';
4177
4178
		} elseif ($gdimg_error = imagecreate($width, $height)) {
4179
4180
			$background_color = phpthumb_functions::ImageHexColorAllocate($gdimg_error, $this->config_error_bgcolor,   true);
4181
			$text_color       = phpthumb_functions::ImageHexColorAllocate($gdimg_error, $this->config_error_textcolor, true);
4182
			imagefilledrectangle($gdimg_error, 0, 0, $width, $height, $background_color);
4183
			$lineYoffset = 0;
4184
			foreach ($LinesOfText as $line) {
4185
				imagestring($gdimg_error, $this->config_error_fontsize, 2, $lineYoffset, $line, $text_color);
4186
				$lineYoffset += $FontHeight;
4187
			}
4188
			if (function_exists('imagetypes')) {
4189
				$imagetypes = imagetypes();
4190
				if ($imagetypes & IMG_PNG) {
4191
					header('Content-Type: image/png');
4192
					imagepng($gdimg_error);
4193
				} elseif ($imagetypes & IMG_GIF) {
4194
					header('Content-Type: image/gif');
4195
					imagegif($gdimg_error);
4196
				} elseif ($imagetypes & IMG_JPG) {
4197
					header('Content-Type: image/jpeg');
4198
					imagejpeg($gdimg_error);
4199
				} elseif ($imagetypes & IMG_WBMP) {
4200
					header('Content-Type: image/vnd.wap.wbmp');
4201
					imagewbmp($gdimg_error);
4202
				}
4203
			}
4204
			imagedestroy($gdimg_error);
4205
4206
		}
4207
		if (!headers_sent()) {
4208
			echo "\n".'**Failed to send graphical error image, dumping error message as text:**<br>'."\n\n".$text;
4209
		}
4210
		exit;
0 ignored issues
show
Best Practice introduced by
Using exit here is not recommended.

In general, usage of exit should be done with care and only when running in a scripting context like a CLI script.

Loading history...
4211
	}
4212
4213
	function ImageCreateFromStringReplacement(&$RawImageData, $DieOnErrors=false) {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
4214
		// there are serious bugs in the non-bundled versions of GD which may cause
4215
		// PHP to segfault when calling imagecreatefromstring() - avoid if at all possible
4216
		// when not using a bundled version of GD2
4217
		if (!phpthumb_functions::gd_version()) {
4218
			if ($DieOnErrors) {
4219
				if (!headers_sent()) {
4220
					// base64-encoded error image in GIF format
4221
					$ERROR_NOGD = 'R0lGODlhIAAgALMAAAAAABQUFCQkJDY2NkZGRldXV2ZmZnJycoaGhpSUlKWlpbe3t8XFxdXV1eTk5P7+/iwAAAAAIAAgAAAE/vDJSau9WILtTAACUinDNijZtAHfCojS4W5H+qxD8xibIDE9h0OwWaRWDIljJSkUJYsN4bihMB8th3IToAKs1VtYM75cyV8sZ8vygtOE5yMKmGbO4jRdICQCjHdlZzwzNW4qZSQmKDaNjhUMBX4BBAlmMywFSRWEmAI6b5gAlhNxokGhooAIK5o/pi9vEw4Lfj4OLTAUpj6IabMtCwlSFw0DCKBoFqwAB04AjI54PyZ+yY3TD0ss2YcVmN/gvpcu4TOyFivWqYJlbAHPpOntvxNAACcmGHjZzAZqzSzcq5fNjxFmAFw9iFRunD1epU6tsIPmFCAJnWYE0FURk7wJDA0MTKpEzoWAAskiAAA7';
4222
					header('Content-Type: image/gif');
4223
					echo base64_decode($ERROR_NOGD);
4224
				} else {
4225
					echo '*** ERROR: No PHP-GD support available ***';
4226
				}
4227
				exit;
0 ignored issues
show
Best Practice introduced by
Using exit here is not recommended.

In general, usage of exit should be done with care and only when running in a scripting context like a CLI script.

Loading history...
4228
			} else {
4229
				$this->DebugMessage('ImageCreateFromStringReplacement() failed: gd_version says "'.phpthumb_functions::gd_version().'"', __FILE__, __LINE__);
4230
				return false;
4231
			}
4232
		}
4233
		if (phpthumb_functions::gd_is_bundled()) {
4234
			$this->DebugMessage('ImageCreateFromStringReplacement() calling built-in imagecreatefromstring()', __FILE__, __LINE__);
4235
			return @imagecreatefromstring($RawImageData);
4236
		}
4237
		if ($this->issafemode) {
4238
			$this->DebugMessage('ImageCreateFromStringReplacement() failed: cannot create temp file in SAFE_MODE', __FILE__, __LINE__);
4239
			return false;
4240
		}
4241
4242
		switch (substr($RawImageData, 0, 3)) {
4243
			case 'GIF':
4244
				$ICFSreplacementFunctionName = 'imagecreatefromgif';
4245
				break;
4246
			case "\xFF\xD8\xFF":
4247
				$ICFSreplacementFunctionName = 'imagecreatefromjpeg';
4248
				break;
4249
			case "\x89".'PN':
4250
				$ICFSreplacementFunctionName = 'imagecreatefrompng';
4251
				break;
4252
			default:
4253
				$this->DebugMessage('ImageCreateFromStringReplacement() failed: unknown fileformat signature "'.phpthumb_functions::HexCharDisplay(substr($RawImageData, 0, 3)).'"', __FILE__, __LINE__);
4254
				return false;
4255
				break;
0 ignored issues
show
Unused Code introduced by
break is not strictly necessary here and could be removed.

The break statement is not necessary if it is preceded for example by a return statement:

switch ($x) {
    case 1:
        return 'foo';
        break; // This break is not necessary and can be left off.
}

If you would like to keep this construct to be consistent with other case statements, you can safely mark this issue as a false-positive.

Loading history...
4256
		}
4257
		$ErrorMessage = '';
4258
		if ($tempnam = $this->phpThumb_tempnam()) {
4259
			if ($fp_tempnam = @fopen($tempnam, 'wb')) {
4260
				fwrite($fp_tempnam, $RawImageData);
4261
				fclose($fp_tempnam);
4262
				@chmod($tempnam, $this->getParameter('config_file_create_mask'));
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition for chmod(). This can introduce security issues, and is generally not recommended. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unhandled  annotation

4262
				/** @scrutinizer ignore-unhandled */ @chmod($tempnam, $this->getParameter('config_file_create_mask'));

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...
4263
				if (($ICFSreplacementFunctionName == 'imagecreatefromgif') && !function_exists($ICFSreplacementFunctionName)) {
4264
4265
					// Need to create from GIF file, but imagecreatefromgif does not exist
4266
					ob_start();
4267
					if (!@include_once(dirname(__FILE__).'/phpthumb.gif.php')) {
4268
						$ErrorMessage = 'Failed to include required file "'.dirname(__FILE__).'/phpthumb.gif.php" in '.__FILE__.' on line '.__LINE__;
4269
						$this->DebugMessage($ErrorMessage, __FILE__, __LINE__);
4270
					}
4271
					ob_end_clean();
4272
					// gif_loadFileToGDimageResource() cannot read from raw data, write to file first
4273
					if ($tempfilename = $this->phpThumb_tempnam()) {
4274
						if ($fp_tempfile = @fopen($tempfilename, 'wb')) {
4275
							fwrite($fp_tempfile, $RawImageData);
4276
							fclose($fp_tempfile);
4277
							$gdimg_source = gif_loadFileToGDimageResource($tempfilename);
4278
							$this->DebugMessage('gif_loadFileToGDimageResource('.$tempfilename.') completed', __FILE__, __LINE__);
4279
							$this->DebugMessage('deleting "'.$tempfilename.'"', __FILE__, __LINE__);
4280
							unlink($tempfilename);
4281
							return $gdimg_source;
4282
						} else {
4283
							$ErrorMessage = 'Failed to open tempfile in '.__FILE__.' on line '.__LINE__;
4284
							$this->DebugMessage($ErrorMessage, __FILE__, __LINE__);
4285
						}
4286
					} else {
4287
						$ErrorMessage = 'Failed to open generate tempfile name in '.__FILE__.' on line '.__LINE__;
4288
						$this->DebugMessage($ErrorMessage, __FILE__, __LINE__);
4289
					}
4290
4291
				} elseif (function_exists($ICFSreplacementFunctionName) && ($gdimg_source = @$ICFSreplacementFunctionName($tempnam))) {
4292
4293
					// great
4294
					$this->DebugMessage($ICFSreplacementFunctionName.'('.$tempnam.') succeeded', __FILE__, __LINE__);
4295
					$this->DebugMessage('deleting "'.$tempnam.'"', __FILE__, __LINE__);
4296
					unlink($tempnam);
4297
					return $gdimg_source;
4298
4299
				} else {
4300
4301
					// GD functions not available, or failed to create image
4302
					$this->DebugMessage($ICFSreplacementFunctionName.'('.$tempnam.') '.(function_exists($ICFSreplacementFunctionName) ? 'failed' : 'does not exist'), __FILE__, __LINE__);
4303
					if (isset($_GET['phpThumbDebug'])) {
4304
						$this->phpThumbDebug();
4305
					}
4306
4307
				}
4308
			} else {
4309
				$ErrorMessage = 'Failed to fopen('.$tempnam.', "wb") in '.__FILE__.' on line '.__LINE__."\n".'You may need to set $PHPTHUMB_CONFIG[temp_directory] in phpThumb.config.php';
4310
				if ($this->issafemode) {
4311
					$ErrorMessage = 'ImageCreateFromStringReplacement() failed in '.__FILE__.' on line '.__LINE__.': cannot create temp file in SAFE_MODE';
4312
				}
4313
				$this->DebugMessage($ErrorMessage, __FILE__, __LINE__);
4314
			}
4315
			$this->DebugMessage('deleting "'.$tempnam.'"', __FILE__, __LINE__);
4316
			@unlink($tempnam);
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition for unlink(). This can introduce security issues, and is generally not recommended. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unhandled  annotation

4316
			/** @scrutinizer ignore-unhandled */ @unlink($tempnam);

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...
4317
		} else {
4318
			$ErrorMessage = 'Failed to generate phpThumb_tempnam() in '.__FILE__.' on line '.__LINE__."\n".'You may need to set $PHPTHUMB_CONFIG[temp_directory] in phpThumb.config.php';
4319
			if ($this->issafemode) {
4320
				$ErrorMessage = 'ImageCreateFromStringReplacement() failed in '.__FILE__.' on line '.__LINE__.': cannot create temp file in SAFE_MODE';
4321
			}
4322
		}
4323
		if ($DieOnErrors && $ErrorMessage) {
4324
			return $this->ErrorImage($ErrorMessage);
4325
		}
4326
		return false;
4327
	}
4328
4329
	function ImageResizeFunction(&$dst_im, &$src_im, $dstX, $dstY, $srcX, $srcY, $dstW, $dstH, $srcW, $srcH) {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
4330
		$this->DebugMessage('ImageResizeFunction($o, $s, '.$dstX.', '.$dstY.', '.$srcX.', '.$srcY.', '.$dstW.', '.$dstH.', '.$srcW.', '.$srcH.')', __FILE__, __LINE__);
4331
		if (($dstW == $srcW) && ($dstH == $srcH)) {
4332
			return imagecopy($dst_im, $src_im, $dstX, $dstY, $srcX, $srcY, $srcW, $srcH);
4333
		}
4334
		if (phpthumb_functions::gd_version() >= 2.0) {
4335
			if ($this->config_disable_imagecopyresampled) {
4336
				return phpthumb_functions::ImageCopyResampleBicubic($dst_im, $src_im, $dstX, $dstY, $srcX, $srcY, $dstW, $dstH, $srcW, $srcH);
4337
			}
4338
			return imagecopyresampled($dst_im, $src_im, $dstX, $dstY, $srcX, $srcY, $dstW, $dstH, $srcW, $srcH);
4339
		}
4340
		return imagecopyresized($dst_im, $src_im, $dstX, $dstY, $srcX, $srcY, $dstW, $dstH, $srcW, $srcH);
4341
	}
4342
4343
	function InitializeTempDirSetting() {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
4344
		$this->config_temp_directory = ($this->config_temp_directory ? $this->config_temp_directory : (function_exists('sys_get_temp_dir') ? sys_get_temp_dir() : '')); // sys_get_temp_dir added in PHP v5.2.1
4345
		$this->config_temp_directory = ($this->config_temp_directory ? $this->config_temp_directory : getenv('TMPDIR'));
4346
		$this->config_temp_directory = ($this->config_temp_directory ? $this->config_temp_directory : getenv('TMP'));
4347
		$this->config_temp_directory = ($this->config_temp_directory ? $this->config_temp_directory : ini_get('upload_tmp_dir'));
4348
		$this->config_temp_directory = $this->realPathSafe($this->config_temp_directory);
4349
		return true;
4350
	}
4351
4352
	function phpThumb_tempnam() {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
4353
		$this->InitializeTempDirSetting();
4354
		$tempnam = $this->realPathSafe(tempnam($this->config_temp_directory, 'pThumb'));
4355
		$this->tempFilesToDelete[$tempnam] = $tempnam;
4356
		$this->DebugMessage('phpThumb_tempnam() returning "'.$tempnam.'"', __FILE__, __LINE__);
4357
		return $tempnam;
4358
	}
4359
4360
	function DebugMessage($message, $file='', $line='') {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
4361
		$this->debugmessages[] = $message.($file ? ' in file "'.(basename($file) ? basename($file) : $file).'"' : '').($line ? ' on line '.$line : '');
4362
		return true;
4363
	}
4364
4365
	function DebugTimingMessage($message, $file='', $line='', $timestamp=0) {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
4366
		if (!$timestamp) {
4367
			$timestamp = array_sum(explode(' ', microtime()));
4368
		}
4369
		$this->debugtiming[number_format($timestamp, 6, '.', '')] = ': '.$message.($file ? ' in file "'.(basename($file) ? basename($file) : $file).'"' : '').($line ? ' on line '.$line : '');
4370
		return true;
4371
	}
4372
4373
}
4374