This project does not seem to handle request data directly as such no vulnerable execution paths were found.
include
, or for example
via PHP's auto-loading mechanism.
These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more
1 | <?php |
||
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 | if (!require_once __DIR__ . '/phpthumb.functions.php') { |
||
14 | ob_end_flush(); |
||
15 | die('failed to include_once("' . __DIR__ . '/phpthumb.functions.php")'); |
||
16 | } |
||
17 | ob_end_clean(); |
||
18 | |||
19 | /** |
||
20 | * Class phpthumb |
||
21 | */ |
||
22 | class phpthumb |
||
23 | { |
||
24 | |||
25 | // public: |
||
26 | // START PARAMETERS (for object mode and phpThumb.php) |
||
27 | // See phpthumb.readme.txt for descriptions of what each of these values are |
||
28 | public $src = null; // SouRCe filename |
||
29 | public $new = null; // NEW image (phpThumb.php only) |
||
30 | public $w = null; // Width |
||
31 | public $h = null; // Height |
||
32 | public $wp = null; // Width (Portrait Images Only) |
||
33 | public $hp = null; // Height (Portrait Images Only) |
||
34 | public $wl = null; // Width (Landscape Images Only) |
||
35 | public $hl = null; // Height (Landscape Images Only) |
||
36 | public $ws = null; // Width (Square Images Only) |
||
37 | public $hs = null; // Height (Square Images Only) |
||
38 | public $f = null; // output image Format |
||
39 | public $q = 75; // jpeg output Quality |
||
40 | public $sx = null; // Source crop top-left X position |
||
41 | public $sy = null; // Source crop top-left Y position |
||
42 | public $sw = null; // Source crop Width |
||
43 | public $sh = null; // Source crop Height |
||
44 | public $zc = null; // Zoom Crop |
||
45 | public $bc = null; // Border Color |
||
46 | public $bg = null; // BackGround color |
||
47 | public $fltr = array(); // FiLTeRs |
||
48 | public $goto = null; // GO TO url after processing |
||
49 | public $err = null; // default ERRor image filename |
||
50 | public $xto = null; // extract eXif Thumbnail Only |
||
51 | public $ra = null; // Rotate by Angle |
||
52 | public $ar = null; // Auto Rotate |
||
53 | public $aoe = null; // Allow Output Enlargement |
||
54 | public $far = null; // Fixed Aspect Ratio |
||
55 | public $iar = null; // Ignore Aspect Ratio |
||
56 | public $maxb = null; // MAXimum Bytes |
||
57 | public $down = null; // DOWNload thumbnail filename |
||
58 | public $md5s = null; // MD5 hash of Source image |
||
59 | public $sfn = 0; // Source Frame Number |
||
60 | public $dpi = 150; // Dots Per Inch for vector source formats |
||
61 | public $sia = null; // Save Image As filename |
||
62 | |||
63 | public $file = null; // >>>deprecated, DO NOT USE, will be removed in future versions<<< |
||
64 | |||
65 | public $phpThumbDebug = null; |
||
66 | // END PARAMETERS |
||
67 | |||
68 | // public: |
||
69 | // START CONFIGURATION OPTIONS (for object mode only) |
||
70 | // See phpThumb.config.php for descriptions of what each of these settings do |
||
71 | |||
72 | // * Directory Configuration |
||
73 | public $config_cache_directory = null; |
||
74 | public $config_cache_directory_depth = 0; |
||
75 | public $config_cache_disable_warning = true; |
||
76 | public $config_cache_source_enabled = false; |
||
77 | public $config_cache_source_directory = null; |
||
78 | public $config_temp_directory = null; |
||
79 | public $config_document_root = null; |
||
80 | |||
81 | // * Default output configuration: |
||
82 | public $config_output_format = 'jpeg'; |
||
83 | public $config_output_maxwidth = 0; |
||
84 | public $config_output_maxheight = 0; |
||
85 | public $config_output_interlace = true; |
||
86 | |||
87 | // * Error message configuration |
||
88 | public $config_error_image_width = 400; |
||
89 | public $config_error_image_height = 100; |
||
90 | public $config_error_message_image_default = ''; |
||
91 | public $config_error_bgcolor = 'CCCCFF'; |
||
92 | public $config_error_textcolor = 'FF0000'; |
||
93 | public $config_error_fontsize = 1; |
||
94 | public $config_error_die_on_error = false; |
||
95 | public $config_error_silent_die_on_error = false; |
||
96 | public $config_error_die_on_source_failure = true; |
||
97 | |||
98 | // * Anti-Hotlink Configuration: |
||
99 | public $config_nohotlink_enabled = true; |
||
100 | public $config_nohotlink_valid_domains = array(); |
||
101 | public $config_nohotlink_erase_image = true; |
||
102 | public $config_nohotlink_text_message = 'Off-server thumbnailing is not allowed'; |
||
103 | // * Off-server Linking Configuration: |
||
104 | public $config_nooffsitelink_enabled = false; |
||
105 | public $config_nooffsitelink_valid_domains = array(); |
||
106 | public $config_nooffsitelink_require_refer = false; |
||
107 | public $config_nooffsitelink_erase_image = true; |
||
108 | public $config_nooffsitelink_watermark_src = ''; |
||
109 | public $config_nooffsitelink_text_message = 'Off-server linking is not allowed'; |
||
110 | |||
111 | // * Border & Background default colors |
||
112 | public $config_border_hexcolor = '000000'; |
||
113 | public $config_background_hexcolor = 'FFFFFF'; |
||
114 | |||
115 | // * TrueType Fonts |
||
116 | public $config_ttf_directory = './fonts'; |
||
117 | |||
118 | public $config_max_source_pixels = null; |
||
119 | public $config_use_exif_thumbnail_for_speed = false; |
||
120 | public $allow_local_http_src = false; |
||
121 | |||
122 | public $config_imagemagick_path = null; |
||
123 | public $config_prefer_imagemagick = true; |
||
124 | public $config_imagemagick_use_thumbnail = true; |
||
125 | |||
126 | public $config_cache_maxage = null; |
||
127 | public $config_cache_maxsize = null; |
||
128 | public $config_cache_maxfiles = null; |
||
129 | public $config_cache_source_filemtime_ignore_local = false; |
||
130 | public $config_cache_source_filemtime_ignore_remote = true; |
||
131 | public $config_cache_default_only_suffix = false; |
||
132 | public $config_cache_force_passthru = true; |
||
133 | public $config_cache_prefix = ''; // default value set in the constructor below |
||
134 | |||
135 | // * MySQL |
||
136 | public $config_mysql_extension = null; |
||
137 | public $config_mysql_query = null; |
||
138 | public $config_mysql_hostname = null; |
||
139 | public $config_mysql_username = null; |
||
140 | public $config_mysql_password = null; |
||
141 | public $config_mysql_database = null; |
||
142 | |||
143 | // * Security |
||
144 | public $config_high_security_enabled = true; |
||
145 | public $config_high_security_password = null; |
||
146 | public $config_high_security_url_separator = '&'; |
||
147 | public $config_disable_debug = true; |
||
148 | public $config_allow_src_above_docroot = false; |
||
149 | public $config_allow_src_above_phpthumb = true; |
||
150 | public $config_auto_allow_symlinks = true; // allow symlink target directories without explicitly whitelisting them |
||
151 | public $config_additional_allowed_dirs = array(); // additional directories to allow source images to be read from |
||
152 | |||
153 | // * HTTP fopen |
||
154 | public $config_http_fopen_timeout = 10; |
||
155 | public $config_http_follow_redirect = true; |
||
156 | |||
157 | // * Compatability |
||
158 | public $config_disable_pathinfo_parsing = false; |
||
159 | public $config_disable_imagecopyresampled = false; |
||
160 | public $config_disable_onlycreateable_passthru = false; |
||
161 | public $config_disable_realpath = false; |
||
162 | |||
163 | public $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'; |
||
164 | |||
165 | // END CONFIGURATION OPTIONS |
||
166 | |||
167 | // public: error messages (read-only; persistant) |
||
168 | public $debugmessages = array(); |
||
169 | public $debugtiming = array(); |
||
170 | public $fatalerror = null; |
||
171 | |||
172 | // private: (should not be modified directly) |
||
173 | public $thumbnailQuality = 75; |
||
174 | public $thumbnailFormat = null; |
||
175 | |||
176 | public $sourceFilename = null; |
||
177 | public $rawImageData = null; |
||
178 | public $IMresizedData = null; |
||
179 | public $outputImageData = null; |
||
180 | |||
181 | public $useRawIMoutput = false; |
||
182 | |||
183 | public $gdimg_output = null; |
||
184 | public $gdimg_source = null; |
||
185 | |||
186 | public $getimagesizeinfo = null; |
||
187 | |||
188 | public $source_width = null; |
||
189 | public $source_height = null; |
||
190 | |||
191 | public $thumbnailCropX = null; |
||
192 | public $thumbnailCropY = null; |
||
193 | public $thumbnailCropW = null; |
||
194 | public $thumbnailCropH = null; |
||
195 | |||
196 | public $exif_thumbnail_width = null; |
||
197 | public $exif_thumbnail_height = null; |
||
198 | public $exif_thumbnail_type = null; |
||
199 | public $exif_thumbnail_data = null; |
||
200 | public $exif_raw_data = null; |
||
201 | |||
202 | public $thumbnail_width = null; |
||
203 | public $thumbnail_height = null; |
||
204 | public $thumbnail_image_width = null; |
||
205 | public $thumbnail_image_height = null; |
||
206 | |||
207 | public $tempFilesToDelete = array(); |
||
208 | public $cache_filename = null; |
||
209 | |||
210 | public $AlphaCapableFormats = array('png', 'ico', 'gif'); |
||
211 | public $is_alpha = false; |
||
212 | |||
213 | public $iswindows = null; |
||
214 | public $issafemode = null; |
||
215 | public $php_memory_limit = null; |
||
216 | |||
217 | public $phpthumb_version = '1.7.14-201603240806'; |
||
218 | |||
219 | ////////////////////////////////////////////////////////////////////// |
||
220 | |||
221 | // public: constructor |
||
222 | /** |
||
223 | * phpthumb constructor. |
||
224 | */ |
||
225 | public function __construct() |
||
226 | { |
||
227 | $this->phpThumb(); |
||
228 | } |
||
229 | |||
230 | public function phpThumb() |
||
231 | { |
||
232 | $this->DebugTimingMessage('phpThumb() constructor', __FILE__, __LINE__); |
||
233 | $this->DebugMessage('phpThumb() v' . $this->phpthumb_version, __FILE__, __LINE__); |
||
234 | |||
235 | foreach (array(ini_get('memory_limit'), get_cfg_var('memory_limit')) as $php_config_memory_limit) { |
||
236 | if (strlen($php_config_memory_limit)) { |
||
237 | if (substr($php_config_memory_limit, -1, 1) == 'G') { // PHP memory limit expressed in Gigabytes |
||
238 | $php_config_memory_limit = (int)substr($php_config_memory_limit, 0, -1) * 1073741824; |
||
239 | } elseif (substr($php_config_memory_limit, -1, 1) == 'M') { // PHP memory limit expressed in Megabytes |
||
240 | $php_config_memory_limit = (int)substr($php_config_memory_limit, 0, -1) * 1048576; |
||
241 | } |
||
242 | $this->php_memory_limit = max($this->php_memory_limit, $php_config_memory_limit); |
||
243 | } |
||
244 | } |
||
245 | if ($this->php_memory_limit > 0) { // could be "-1" for "no limit" |
||
246 | $this->config_max_source_pixels = round($this->php_memory_limit * 0.20); // 20% of memory_limit |
||
247 | } |
||
248 | |||
249 | $this->iswindows = (bool)(strtoupper(substr(PHP_OS, 0, 3)) == 'WIN'); |
||
250 | $this->issafemode = (bool)preg_match('#(1|ON)#i', ini_get('safe_mode')); |
||
251 | $this->config_document_root = (!empty($_SERVER['DOCUMENT_ROOT']) ? $_SERVER['DOCUMENT_ROOT'] : $this->config_document_root); |
||
252 | $this->config_cache_prefix = (isset($_SERVER['SERVER_NAME']) ? $_SERVER['SERVER_NAME'] . '_' : ''); |
||
253 | |||
254 | $this->purgeTempFiles(); // purge existing temp files if re-initializing object |
||
255 | |||
256 | $php_sapi_name = strtolower(function_exists('php_sapi_name') ? php_sapi_name() : ''); |
||
257 | if ($php_sapi_name == 'cli') { |
||
258 | $this->config_allow_src_above_docroot = true; |
||
259 | } |
||
260 | |||
261 | if (!$this->config_disable_debug) { |
||
262 | // if debug mode is enabled, force phpThumbDebug output, do not allow normal thumbnails to be generated |
||
263 | $this->phpThumbDebug = (is_null($this->phpThumbDebug) ? 9 : max(1, (int)$this->phpThumbDebug)); |
||
264 | } |
||
265 | } |
||
266 | |||
267 | public function __destruct() |
||
268 | { |
||
269 | $this->purgeTempFiles(); |
||
270 | } |
||
271 | |||
272 | // public: |
||
273 | |||
274 | /** |
||
275 | * @return bool |
||
276 | */ |
||
277 | public function purgeTempFiles() |
||
278 | { |
||
279 | foreach ($this->tempFilesToDelete as $tempFileToDelete) { |
||
280 | if (file_exists($tempFileToDelete)) { |
||
281 | $this->DebugMessage('Deleting temp file "' . $tempFileToDelete . '"', __FILE__, __LINE__); |
||
282 | @unlink($tempFileToDelete); |
||
0 ignored issues
–
show
|
|||
283 | } |
||
284 | } |
||
285 | $this->tempFilesToDelete = array(); |
||
286 | |||
287 | return true; |
||
288 | } |
||
289 | |||
290 | // public: |
||
291 | |||
292 | /** |
||
293 | * @param $sourceFilename |
||
294 | * @return bool |
||
295 | */ |
||
296 | public function setSourceFilename($sourceFilename) |
||
297 | { |
||
298 | //$this->resetObject(); |
||
299 | //$this->rawImageData = null; |
||
300 | $this->sourceFilename = $sourceFilename; |
||
301 | $this->src = $sourceFilename; |
||
302 | if (is_null($this->config_output_format)) { |
||
303 | $sourceFileExtension = strtolower(substr(strrchr($sourceFilename, '.'), 1)); |
||
304 | if (preg_match('#^[a-z]{3,4}$#', $sourceFileExtension)) { |
||
305 | $this->config_output_format = $sourceFileExtension; |
||
306 | $this->DebugMessage('setSourceFilename(' . $sourceFilename . ') set $this->config_output_format to "' . $sourceFileExtension . '"', __FILE__, __LINE__); |
||
307 | } else { |
||
308 | $this->DebugMessage('setSourceFilename(' |
||
309 | . $sourceFilename |
||
310 | . ') did NOT set $this->config_output_format to "' |
||
311 | . $sourceFileExtension |
||
312 | . '" because it did not seem like an appropriate image format', __FILE__, __LINE__); |
||
313 | } |
||
314 | } |
||
315 | $this->DebugMessage('setSourceFilename(' . $sourceFilename . ') set $this->sourceFilename to "' . $this->sourceFilename . '"', __FILE__, __LINE__); |
||
316 | |||
317 | return true; |
||
318 | } |
||
319 | |||
320 | // public: |
||
321 | |||
322 | /** |
||
323 | * @param $rawImageData |
||
324 | * @param string $sourceFilename |
||
325 | * @return bool |
||
326 | */ |
||
327 | public function setSourceData($rawImageData, $sourceFilename = '') |
||
328 | { |
||
329 | //$this->resetObject(); |
||
330 | //$this->sourceFilename = null; |
||
331 | $this->rawImageData = $rawImageData; |
||
332 | $this->DebugMessage('setSourceData() setting $this->rawImageData (' |
||
333 | . strlen($this->rawImageData) |
||
334 | . ' bytes; magic="' |
||
335 | . substr($this->rawImageData, 0, 4) |
||
336 | . '" (' |
||
337 | . phpthumb_functions::HexCharDisplay(substr($this->rawImageData, 0, 4)) |
||
338 | . '))', __FILE__, __LINE__); |
||
339 | if ($this->config_cache_source_enabled) { |
||
340 | $sourceFilename = ($sourceFilename ?: md5($rawImageData)); |
||
341 | if (!is_dir($this->config_cache_source_directory)) { |
||
342 | $this->ErrorImage('$this->config_cache_source_directory (' . $this->config_cache_source_directory . ') is not a directory'); |
||
343 | } elseif (!@is_writable($this->config_cache_source_directory)) { |
||
344 | $this->ErrorImage('$this->config_cache_source_directory (' . $this->config_cache_source_directory . ') is not writable'); |
||
345 | } |
||
346 | $this->DebugMessage('setSourceData() attempting to save source image to "' . $this->config_cache_source_directory . DIRECTORY_SEPARATOR . urlencode($sourceFilename) . '"', __FILE__, |
||
347 | __LINE__); |
||
348 | if ($fp = @fopen($this->config_cache_source_directory . DIRECTORY_SEPARATOR . urlencode($sourceFilename), 'wb')) { |
||
349 | fwrite($fp, $rawImageData); |
||
350 | fclose($fp); |
||
351 | } elseif (!$this->phpThumbDebug) { |
||
352 | $this->ErrorImage('setSourceData() failed to write to source cache (' . $this->config_cache_source_directory . DIRECTORY_SEPARATOR . urlencode($sourceFilename) . ')'); |
||
353 | } |
||
354 | } |
||
355 | |||
356 | return true; |
||
357 | } |
||
358 | |||
359 | // public: |
||
360 | |||
361 | /** |
||
362 | * @param $gdimg |
||
363 | * @return bool |
||
364 | */ |
||
365 | public function setSourceImageResource($gdimg) |
||
366 | { |
||
367 | //$this->resetObject(); |
||
368 | $this->gdimg_source = $gdimg; |
||
369 | |||
370 | return true; |
||
371 | } |
||
372 | |||
373 | // public: |
||
374 | |||
375 | /** |
||
376 | * @param $param |
||
377 | * @param $value |
||
378 | * @return bool |
||
379 | */ |
||
380 | public function setParameter($param, $value) |
||
381 | { |
||
382 | if ($param == 'src') { |
||
383 | $this->setSourceFilename($this->ResolveFilenameToAbsolute($value)); |
||
384 | } elseif (@is_array($this->$param)) { |
||
385 | if (is_array($value)) { |
||
386 | foreach ($value as $arraykey => $arrayvalue) { |
||
387 | array_push($this->$param, $arrayvalue); |
||
388 | } |
||
389 | } else { |
||
390 | array_push($this->$param, $value); |
||
391 | } |
||
392 | } else { |
||
393 | $this->$param = $value; |
||
394 | } |
||
395 | |||
396 | return true; |
||
397 | } |
||
398 | |||
399 | // public: |
||
400 | |||
401 | /** |
||
402 | * @param $param |
||
403 | * @return mixed |
||
404 | */ |
||
405 | public function getParameter($param) |
||
406 | { |
||
407 | //if (property_exists('phpThumb', $param)) { |
||
408 | return $this->$param; |
||
409 | //} |
||
410 | //$this->DebugMessage('setParameter() attempting to get non-existant parameter "'.$param.'"', __FILE__, __LINE__); |
||
411 | //return false; |
||
412 | } |
||
413 | |||
414 | // public: |
||
415 | |||
416 | /** |
||
417 | * @return bool |
||
418 | */ |
||
419 | public function GenerateThumbnail() |
||
420 | { |
||
421 | $this->setOutputFormat(); |
||
422 | $this->phpThumbDebug('8a'); |
||
423 | $this->ResolveSource(); |
||
424 | $this->phpThumbDebug('8b'); |
||
425 | $this->SetCacheFilename(); |
||
426 | $this->phpThumbDebug('8c'); |
||
427 | $this->ExtractEXIFgetImageSize(); |
||
428 | $this->phpThumbDebug('8d'); |
||
429 | if ($this->useRawIMoutput) { |
||
430 | $this->DebugMessage('Skipping rest of GenerateThumbnail() because ($this->useRawIMoutput === true)', __FILE__, __LINE__); |
||
431 | |||
432 | return true; |
||
433 | } |
||
434 | $this->phpThumbDebug('8e'); |
||
435 | if (!$this->SourceImageToGD()) { |
||
436 | $this->DebugMessage('SourceImageToGD() failed', __FILE__, __LINE__); |
||
437 | |||
438 | return false; |
||
439 | } |
||
440 | $this->phpThumbDebug('8f'); |
||
441 | $this->Rotate(); |
||
442 | $this->phpThumbDebug('8g'); |
||
443 | $this->CreateGDoutput(); |
||
444 | $this->phpThumbDebug('8h'); |
||
445 | |||
446 | // default values, also applicable for far="C" |
||
447 | $destination_offset_x = round(($this->thumbnail_width - $this->thumbnail_image_width) / 2); |
||
448 | $destination_offset_y = round(($this->thumbnail_height - $this->thumbnail_image_height) / 2); |
||
449 | if (($this->far == 'L') || ($this->far == 'TL') || ($this->far == 'BL')) { |
||
450 | $destination_offset_x = 0; |
||
451 | } |
||
452 | if (($this->far == 'R') || ($this->far == 'TR') || ($this->far == 'BR')) { |
||
453 | $destination_offset_x = round($this->thumbnail_width - $this->thumbnail_image_width); |
||
454 | } |
||
455 | if (($this->far == 'T') || ($this->far == 'TL') || ($this->far == 'TR')) { |
||
456 | $destination_offset_y = 0; |
||
457 | } |
||
458 | if (($this->far == 'B') || ($this->far == 'BL') || ($this->far == 'BR')) { |
||
459 | $destination_offset_y = round($this->thumbnail_height - $this->thumbnail_image_height); |
||
460 | } |
||
461 | |||
462 | // // copy/resize image to appropriate dimensions |
||
463 | // $borderThickness = 0; |
||
464 | // if (!empty($this->fltr)) { |
||
465 | // foreach ($this->fltr as $key => $value) { |
||
466 | // if (preg_match('#^bord\|([0-9]+)#', $value, $matches)) { |
||
467 | // $borderThickness = $matches[1]; |
||
468 | // break; |
||
469 | // } |
||
470 | // } |
||
471 | // } |
||
472 | // if ($borderThickness > 0) { |
||
473 | // //$this->DebugMessage('Skipping ImageResizeFunction() because BorderThickness="'.$borderThickness.'"', __FILE__, __LINE__); |
||
474 | // $this->thumbnail_image_height /= 2; |
||
475 | // } |
||
476 | $this->ImageResizeFunction($this->gdimg_output, $this->gdimg_source, $destination_offset_x, $destination_offset_y, $this->thumbnailCropX, $this->thumbnailCropY, $this->thumbnail_image_width, |
||
477 | $this->thumbnail_image_height, $this->thumbnailCropW, $this->thumbnailCropH); |
||
478 | |||
479 | $this->DebugMessage('memory_get_usage() after copy-resize = ' . (function_exists('memory_get_usage') ? @memory_get_usage() : 'n/a'), __FILE__, __LINE__); |
||
480 | imagedestroy($this->gdimg_source); |
||
481 | $this->DebugMessage('memory_get_usage() after ImageDestroy = ' . (function_exists('memory_get_usage') ? @memory_get_usage() : 'n/a'), __FILE__, __LINE__); |
||
482 | |||
483 | $this->phpThumbDebug('8i'); |
||
484 | $this->AntiOffsiteLinking(); |
||
485 | $this->phpThumbDebug('8j'); |
||
486 | $this->ApplyFilters(); |
||
487 | $this->phpThumbDebug('8k'); |
||
488 | $this->AlphaChannelFlatten(); |
||
489 | $this->phpThumbDebug('8l'); |
||
490 | $this->MaxFileSize(); |
||
491 | $this->phpThumbDebug('8m'); |
||
492 | |||
493 | $this->DebugMessage('GenerateThumbnail() completed successfully', __FILE__, __LINE__); |
||
494 | |||
495 | return true; |
||
496 | } |
||
497 | |||
498 | // public: |
||
499 | |||
500 | /** |
||
501 | * @return bool |
||
502 | */ |
||
503 | public function RenderOutput() |
||
504 | { |
||
505 | View Code Duplication | if (!$this->useRawIMoutput && !is_resource($this->gdimg_output)) { |
|
506 | $this->DebugMessage('RenderOutput() failed because !is_resource($this->gdimg_output)', __FILE__, __LINE__); |
||
507 | |||
508 | return false; |
||
509 | } |
||
510 | if (!$this->thumbnailFormat) { |
||
511 | $this->DebugMessage('RenderOutput() failed because $this->thumbnailFormat is empty', __FILE__, __LINE__); |
||
512 | |||
513 | return false; |
||
514 | } |
||
515 | if ($this->useRawIMoutput) { |
||
516 | $this->DebugMessage('RenderOutput copying $this->IMresizedData (' . strlen($this->IMresizedData) . ' bytes) to $this->outputImage', __FILE__, __LINE__); |
||
517 | $this->outputImageData = $this->IMresizedData; |
||
518 | |||
519 | return true; |
||
520 | } |
||
521 | |||
522 | $builtin_formats = array(); |
||
523 | if (function_exists('ImageTypes')) { |
||
524 | $imagetypes = imagetypes(); |
||
525 | $builtin_formats['wbmp'] = (bool)($imagetypes & IMG_WBMP); |
||
526 | $builtin_formats['jpg'] = (bool)($imagetypes & IMG_JPG); |
||
527 | $builtin_formats['gif'] = (bool)($imagetypes & IMG_GIF); |
||
528 | $builtin_formats['png'] = (bool)($imagetypes & IMG_PNG); |
||
529 | } |
||
530 | |||
531 | $this->DebugMessage('ImageInterlace($this->gdimg_output, ' . (int)$this->config_output_interlace . ')', __FILE__, __LINE__); |
||
532 | imageinterlace($this->gdimg_output, (int)$this->config_output_interlace); |
||
533 | |||
534 | $this->DebugMessage('RenderOutput() attempting Image' . strtoupper(@$this->thumbnailFormat) . '($this->gdimg_output)', __FILE__, __LINE__); |
||
535 | ob_start(); |
||
536 | switch ($this->thumbnailFormat) { |
||
537 | View Code Duplication | case 'wbmp': |
|
538 | if (empty($builtin_formats['wbmp'])) { |
||
539 | $this->DebugMessage('GD does not have required built-in support for WBMP output', __FILE__, __LINE__); |
||
540 | ob_end_clean(); |
||
541 | |||
542 | return false; |
||
543 | } |
||
544 | imagejpeg($this->gdimg_output, null, $this->thumbnailQuality); |
||
545 | $this->outputImageData = ob_get_contents(); |
||
546 | break; |
||
547 | |||
548 | case 'jpeg': |
||
549 | View Code Duplication | case 'jpg': // should be "jpeg" not "jpg" but just in case... |
|
550 | if (empty($builtin_formats['jpg'])) { |
||
551 | $this->DebugMessage('GD does not have required built-in support for JPEG output', __FILE__, __LINE__); |
||
552 | ob_end_clean(); |
||
553 | |||
554 | return false; |
||
555 | } |
||
556 | imagejpeg($this->gdimg_output, null, $this->thumbnailQuality); |
||
557 | $this->outputImageData = ob_get_contents(); |
||
558 | break; |
||
559 | |||
560 | case 'png': |
||
561 | if (empty($builtin_formats['png'])) { |
||
562 | $this->DebugMessage('GD does not have required built-in support for PNG output', __FILE__, __LINE__); |
||
563 | ob_end_clean(); |
||
564 | |||
565 | return false; |
||
566 | } |
||
567 | if (phpthumb_functions::version_compare_replacement(PHP_VERSION, '5.1.2', '>=')) { |
||
568 | // https://github.com/JamesHeinrich/phpThumb/issues/24 |
||
569 | |||
570 | /* http://php.net/manual/en/function.imagepng.php: |
||
571 | from php source (gd.h): |
||
572 | 2.0.12: Compression level: 0-9 or -1, where 0 is NO COMPRESSION at all, |
||
573 | :: 1 is FASTEST but produces larger files, 9 provides the best |
||
574 | :: compression (smallest files) but takes a long time to compress, and |
||
575 | :: -1 selects the default compiled into the zlib library. |
||
576 | Conclusion: Based on the Zlib manual (http://www.zlib.net/manual.html) the default compression level is set to 6. |
||
577 | */ |
||
578 | if (($this->thumbnailQuality >= -1) && ($this->thumbnailQuality <= 9)) { |
||
579 | $PNGquality = $this->thumbnailQuality; |
||
580 | } else { |
||
581 | $this->DebugMessage('Specified thumbnailQuality "' . $this->thumbnailQuality . '" is outside the accepted range (0-9, or -1). Using 6 as default value.', __FILE__, __LINE__); |
||
582 | $PNGquality = 6; |
||
583 | } |
||
584 | imagepng($this->gdimg_output, null, $PNGquality); |
||
585 | } else { |
||
586 | imagepng($this->gdimg_output); |
||
587 | } |
||
588 | $this->outputImageData = ob_get_contents(); |
||
589 | break; |
||
590 | |||
591 | case 'gif': |
||
592 | if (empty($builtin_formats['gif'])) { |
||
593 | $this->DebugMessage('GD does not have required built-in support for GIF output', __FILE__, __LINE__); |
||
594 | ob_end_clean(); |
||
595 | |||
596 | return false; |
||
597 | } |
||
598 | imagegif($this->gdimg_output); |
||
599 | $this->outputImageData = ob_get_contents(); |
||
600 | break; |
||
601 | |||
602 | View Code Duplication | case 'bmp': |
|
603 | $ImageOutFunction = '"builtin BMP output"'; |
||
604 | if (!@require_once __DIR__ . '/phpthumb.bmp.php') { |
||
605 | $this->DebugMessage('Error including "' . __DIR__ . '/phpthumb.bmp.php" which is required for BMP format output', __FILE__, __LINE__); |
||
606 | ob_end_clean(); |
||
607 | |||
608 | return false; |
||
609 | } |
||
610 | $phpthumb_bmp = new phpthumb_bmp(); |
||
611 | $this->outputImageData = $phpthumb_bmp->GD2BMPstring($this->gdimg_output); |
||
612 | unset($phpthumb_bmp); |
||
613 | break; |
||
614 | |||
615 | View Code Duplication | case 'ico': |
|
616 | $ImageOutFunction = '"builtin ICO output"'; |
||
617 | if (!@require_once __DIR__ . '/phpthumb.ico.php') { |
||
618 | $this->DebugMessage('Error including "' . __DIR__ . '/phpthumb.ico.php" which is required for ICO format output', __FILE__, __LINE__); |
||
619 | ob_end_clean(); |
||
620 | |||
621 | return false; |
||
622 | } |
||
623 | $phpthumb_ico = new phpthumb_ico(); |
||
624 | $arrayOfOutputImages = array($this->gdimg_output); |
||
625 | $this->outputImageData = $phpthumb_ico->GD2ICOstring($arrayOfOutputImages); |
||
626 | unset($phpthumb_ico); |
||
627 | break; |
||
628 | |||
629 | View Code Duplication | default: |
|
630 | $this->DebugMessage('RenderOutput failed because $this->thumbnailFormat "' . $this->thumbnailFormat . '" is not valid', __FILE__, __LINE__); |
||
631 | ob_end_clean(); |
||
632 | |||
633 | return false; |
||
634 | } |
||
635 | ob_end_clean(); |
||
636 | if (!$this->outputImageData) { |
||
637 | $this->DebugMessage('RenderOutput() for "' . $this->thumbnailFormat . '" failed', __FILE__, __LINE__); |
||
638 | ob_end_clean(); |
||
639 | |||
640 | return false; |
||
641 | } |
||
642 | $this->DebugMessage('RenderOutput() completing with $this->outputImageData = ' . strlen($this->outputImageData) . ' bytes', __FILE__, __LINE__); |
||
643 | |||
644 | return true; |
||
645 | } |
||
646 | |||
647 | // public: |
||
648 | |||
649 | /** |
||
650 | * @param $filename |
||
651 | * @return bool |
||
652 | */ |
||
653 | public function RenderToFile($filename) |
||
654 | { |
||
655 | if (preg_match('#^[a-z0-9]+://#i', $filename)) { |
||
656 | $this->DebugMessage('RenderToFile() failed because $filename (' . $filename . ') is a URL', __FILE__, __LINE__); |
||
657 | |||
658 | return false; |
||
659 | } |
||
660 | // render thumbnail to this file only, do not cache, do not output to browser |
||
661 | //$renderfilename = $this->ResolveFilenameToAbsolute(dirname($filename)).DIRECTORY_SEPARATOR.basename($filename); |
||
662 | $renderfilename = $filename; |
||
663 | if (($filename{0} != '/') && ($filename{0} != '\\') && ($filename{1} != ':')) { |
||
664 | $renderfilename = $this->ResolveFilenameToAbsolute($renderfilename); |
||
665 | } |
||
666 | View Code Duplication | if (!@is_writable(dirname($renderfilename))) { |
|
667 | $this->DebugMessage('RenderToFile() failed because "' . dirname($renderfilename) . '/" is not writable', __FILE__, __LINE__); |
||
668 | |||
669 | return false; |
||
670 | } |
||
671 | View Code Duplication | if (@is_file($renderfilename) && !@is_writable($renderfilename)) { |
|
672 | $this->DebugMessage('RenderToFile() failed because "' . $renderfilename . '" is not writable', __FILE__, __LINE__); |
||
673 | |||
674 | return false; |
||
675 | } |
||
676 | |||
677 | if ($this->RenderOutput()) { |
||
678 | if (file_put_contents($renderfilename, $this->outputImageData)) { |
||
679 | $this->DebugMessage('RenderToFile(' . $renderfilename . ') succeeded', __FILE__, __LINE__); |
||
680 | |||
681 | return true; |
||
682 | } |
||
683 | if (!@file_exists($renderfilename)) { |
||
684 | $this->DebugMessage('RenderOutput [' . $this->thumbnailFormat . '(' . $renderfilename . ')] did not appear to fail, but the output image does not exist either...', __FILE__, __LINE__); |
||
685 | } |
||
686 | } else { |
||
687 | $this->DebugMessage('RenderOutput [' . $this->thumbnailFormat . '(' . $renderfilename . ')] failed', __FILE__, __LINE__); |
||
688 | } |
||
689 | |||
690 | return false; |
||
691 | } |
||
692 | |||
693 | // public: |
||
694 | |||
695 | /** |
||
696 | * @return bool |
||
697 | */ |
||
698 | public function OutputThumbnail() |
||
699 | { |
||
700 | $this->purgeTempFiles(); |
||
701 | |||
702 | View Code Duplication | if (!$this->useRawIMoutput && !is_resource($this->gdimg_output)) { |
|
703 | $this->DebugMessage('OutputThumbnail() failed because !is_resource($this->gdimg_output)', __FILE__, __LINE__); |
||
704 | |||
705 | return false; |
||
706 | } |
||
707 | if (headers_sent()) { |
||
708 | return $this->ErrorImage('OutputThumbnail() failed - headers already sent'); |
||
709 | exit; |
||
710 | } |
||
711 | |||
712 | $downloadfilename = phpthumb_functions::SanitizeFilename(is_string($this->sia) ? $this->sia : ($this->down ?: 'phpThumb_generated_thumbnail' . '.' . $this->thumbnailFormat)); |
||
713 | $this->DebugMessage('Content-Disposition header filename set to "' . $downloadfilename . '"', __FILE__, __LINE__); |
||
714 | if ($downloadfilename) { |
||
715 | header('Content-Disposition: ' . ($this->down ? 'attachment' : 'inline') . '; filename="' . $downloadfilename . '"'); |
||
716 | } else { |
||
717 | $this->DebugMessage('failed to send Content-Disposition header because $downloadfilename is empty', __FILE__, __LINE__); |
||
718 | } |
||
719 | |||
720 | if ($this->useRawIMoutput) { |
||
721 | header('Content-Type: ' . phpthumb_functions::ImageTypeToMIMEtype($this->thumbnailFormat)); |
||
722 | echo $this->IMresizedData; |
||
723 | } else { |
||
724 | $this->DebugMessage('ImageInterlace($this->gdimg_output, ' . (int)$this->config_output_interlace . ')', __FILE__, __LINE__); |
||
725 | imageinterlace($this->gdimg_output, (int)$this->config_output_interlace); |
||
726 | switch ($this->thumbnailFormat) { |
||
727 | View Code Duplication | case 'jpeg': |
|
728 | header('Content-Type: ' . phpthumb_functions::ImageTypeToMIMEtype($this->thumbnailFormat)); |
||
729 | $ImageOutFunction = 'image' . $this->thumbnailFormat; |
||
730 | @$ImageOutFunction($this->gdimg_output, null, $this->thumbnailQuality); |
||
0 ignored issues
–
show
It seems like you do not handle an error condition here. This can introduce security issues, and is generally not recommended.
If you suppress an error, we recommend checking for the error condition explicitly: // For example instead of
@mkdir($dir);
// Better use
if (@mkdir($dir) === false) {
throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
![]() |
|||
731 | break; |
||
732 | |||
733 | case 'png': |
||
734 | View Code Duplication | case 'gif': |
|
735 | header('Content-Type: ' . phpthumb_functions::ImageTypeToMIMEtype($this->thumbnailFormat)); |
||
736 | $ImageOutFunction = 'image' . $this->thumbnailFormat; |
||
737 | @$ImageOutFunction($this->gdimg_output); |
||
0 ignored issues
–
show
It seems like you do not handle an error condition here. This can introduce security issues, and is generally not recommended.
If you suppress an error, we recommend checking for the error condition explicitly: // For example instead of
@mkdir($dir);
// Better use
if (@mkdir($dir) === false) {
throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
![]() |
|||
738 | break; |
||
739 | |||
740 | View Code Duplication | case 'bmp': |
|
741 | if (!@require_once __DIR__ . '/phpthumb.bmp.php') { |
||
742 | $this->DebugMessage('Error including "' . __DIR__ . '/phpthumb.bmp.php" which is required for BMP format output', __FILE__, __LINE__); |
||
743 | |||
744 | return false; |
||
745 | } |
||
746 | $phpthumb_bmp = new phpthumb_bmp(); |
||
747 | if (is_object($phpthumb_bmp)) { |
||
748 | $bmp_data = $phpthumb_bmp->GD2BMPstring($this->gdimg_output); |
||
749 | unset($phpthumb_bmp); |
||
750 | if (!$bmp_data) { |
||
751 | $this->DebugMessage('$phpthumb_bmp->GD2BMPstring() failed', __FILE__, __LINE__); |
||
752 | |||
753 | return false; |
||
754 | } |
||
755 | header('Content-Type: ' . phpthumb_functions::ImageTypeToMIMEtype($this->thumbnailFormat)); |
||
756 | echo $bmp_data; |
||
757 | } else { |
||
758 | $this->DebugMessage('new phpthumb_bmp() failed', __FILE__, __LINE__); |
||
759 | |||
760 | return false; |
||
761 | } |
||
762 | break; |
||
763 | |||
764 | View Code Duplication | case 'ico': |
|
765 | if (!@require_once __DIR__ . '/phpthumb.ico.php') { |
||
766 | $this->DebugMessage('Error including "' . __DIR__ . '/phpthumb.ico.php" which is required for ICO format output', __FILE__, __LINE__); |
||
767 | |||
768 | return false; |
||
769 | } |
||
770 | $phpthumb_ico = new phpthumb_ico(); |
||
771 | if (is_object($phpthumb_ico)) { |
||
772 | $arrayOfOutputImages = array($this->gdimg_output); |
||
773 | $ico_data = $phpthumb_ico->GD2ICOstring($arrayOfOutputImages); |
||
774 | unset($phpthumb_ico); |
||
775 | if (!$ico_data) { |
||
776 | $this->DebugMessage('$phpthumb_ico->GD2ICOstring() failed', __FILE__, __LINE__); |
||
777 | |||
778 | return false; |
||
779 | } |
||
780 | header('Content-Type: ' . phpthumb_functions::ImageTypeToMIMEtype($this->thumbnailFormat)); |
||
781 | echo $ico_data; |
||
782 | } else { |
||
783 | $this->DebugMessage('new phpthumb_ico() failed', __FILE__, __LINE__); |
||
784 | |||
785 | return false; |
||
786 | } |
||
787 | break; |
||
788 | |||
789 | default: |
||
790 | $this->DebugMessage('OutputThumbnail failed because $this->thumbnailFormat "' . $this->thumbnailFormat . '" is not valid', __FILE__, __LINE__); |
||
791 | |||
792 | return false; |
||
793 | break; |
||
794 | } |
||
795 | } |
||
796 | |||
797 | return true; |
||
798 | } |
||
799 | |||
800 | // public: |
||
801 | |||
802 | /** |
||
803 | * @return bool |
||
804 | */ |
||
805 | public function CleanUpCacheDirectory() |
||
806 | { |
||
807 | $this->DebugMessage('CleanUpCacheDirectory() set to purge (' |
||
808 | . (is_null($this->config_cache_maxage) ? 'NULL' : number_format($this->config_cache_maxage / 86400, 1)) |
||
809 | . ' days; ' |
||
810 | . (is_null($this->config_cache_maxsize) ? 'NULL' : number_format($this->config_cache_maxsize / 1048576, 2)) |
||
811 | . ' MB; ' |
||
812 | . (is_null($this->config_cache_maxfiles) ? 'NULL' : number_format($this->config_cache_maxfiles)) |
||
813 | . ' files)', __FILE__, __LINE__); |
||
814 | |||
815 | View Code Duplication | if (!is_writable($this->config_cache_directory)) { |
|
816 | $this->DebugMessage('CleanUpCacheDirectory() skipped because "' . $this->config_cache_directory . '" is not writable', __FILE__, __LINE__); |
||
817 | |||
818 | return true; |
||
819 | } |
||
820 | |||
821 | // cache status of cache directory for 1 hour to avoid hammering the filesystem functions |
||
822 | $phpThumbCacheStats_filename = $this->config_cache_directory . DIRECTORY_SEPARATOR . 'phpThumbCacheStats.txt'; |
||
823 | if (file_exists($phpThumbCacheStats_filename) && is_readable($phpThumbCacheStats_filename) |
||
824 | && (filemtime($phpThumbCacheStats_filename) >= (time() - 3600)) |
||
825 | ) { |
||
826 | $this->DebugMessage('CleanUpCacheDirectory() skipped because "' . $phpThumbCacheStats_filename . '" is recently modified', __FILE__, __LINE__); |
||
827 | |||
828 | return true; |
||
829 | } |
||
830 | if (!@touch($phpThumbCacheStats_filename)) { |
||
831 | $this->DebugMessage('touch(' . $phpThumbCacheStats_filename . ') failed', __FILE__, __LINE__); |
||
832 | } |
||
833 | |||
834 | $DeletedKeys = array(); |
||
835 | $AllFilesInCacheDirectory = array(); |
||
836 | if (($this->config_cache_maxage > 0) || ($this->config_cache_maxsize > 0) |
||
837 | || ($this->config_cache_maxfiles > 0) |
||
838 | ) { |
||
839 | $CacheDirOldFilesAge = array(); |
||
840 | $CacheDirOldFilesSize = array(); |
||
841 | $AllFilesInCacheDirectory = phpthumb_functions::GetAllFilesInSubfolders($this->config_cache_directory); |
||
842 | foreach ($AllFilesInCacheDirectory as $fullfilename) { |
||
843 | if (preg_match('#' . preg_quote($this->config_cache_prefix) . '#i', $fullfilename) |
||
844 | && file_exists($fullfilename) |
||
845 | ) { |
||
846 | $CacheDirOldFilesAge[$fullfilename] = @fileatime($fullfilename); |
||
847 | if ($CacheDirOldFilesAge[$fullfilename] == 0) { |
||
848 | $CacheDirOldFilesAge[$fullfilename] = @filemtime($fullfilename); |
||
849 | } |
||
850 | $CacheDirOldFilesSize[$fullfilename] = @filesize($fullfilename); |
||
851 | } |
||
852 | } |
||
853 | if (empty($CacheDirOldFilesSize)) { |
||
854 | $this->DebugMessage('CleanUpCacheDirectory() skipped because $CacheDirOldFilesSize is empty (phpthumb_functions::GetAllFilesInSubfolders(' |
||
855 | . $this->config_cache_directory |
||
856 | . ') found no files)', __FILE__, __LINE__); |
||
857 | |||
858 | return true; |
||
859 | } |
||
860 | $DeletedKeys['zerobyte'] = array(); |
||
861 | foreach ($CacheDirOldFilesSize as $fullfilename => $filesize) { |
||
862 | // purge all zero-size files more than an hour old (to prevent trying to delete just-created and/or in-use files) |
||
863 | $cutofftime = time() - 3600; |
||
864 | if (($filesize == 0) && ($CacheDirOldFilesAge[$fullfilename] < $cutofftime)) { |
||
865 | $this->DebugMessage('deleting "' . $fullfilename . '"', __FILE__, __LINE__); |
||
866 | if (@unlink($fullfilename)) { |
||
867 | $DeletedKeys['zerobyte'][] = $fullfilename; |
||
868 | unset($CacheDirOldFilesSize[$fullfilename]); |
||
869 | unset($CacheDirOldFilesAge[$fullfilename]); |
||
870 | } |
||
871 | } |
||
872 | } |
||
873 | $this->DebugMessage('CleanUpCacheDirectory() purged ' . count($DeletedKeys['zerobyte']) . ' zero-byte files', __FILE__, __LINE__); |
||
874 | asort($CacheDirOldFilesAge); |
||
875 | |||
876 | View Code Duplication | if ($this->config_cache_maxfiles > 0) { |
|
877 | $TotalCachedFiles = count($CacheDirOldFilesAge); |
||
878 | $DeletedKeys['maxfiles'] = array(); |
||
879 | foreach ($CacheDirOldFilesAge as $fullfilename => $filedate) { |
||
880 | if ($TotalCachedFiles > $this->config_cache_maxfiles) { |
||
881 | $this->DebugMessage('deleting "' . $fullfilename . '"', __FILE__, __LINE__); |
||
882 | if (@unlink($fullfilename)) { |
||
883 | $TotalCachedFiles--; |
||
884 | $DeletedKeys['maxfiles'][] = $fullfilename; |
||
885 | } |
||
886 | } else { |
||
887 | // there are few enough files to keep the rest |
||
888 | break; |
||
889 | } |
||
890 | } |
||
891 | $this->DebugMessage('CleanUpCacheDirectory() purged ' . count($DeletedKeys['maxfiles']) . ' files based on (config_cache_maxfiles=' . $this->config_cache_maxfiles . ')', __FILE__, |
||
892 | __LINE__); |
||
893 | foreach ($DeletedKeys['maxfiles'] as $fullfilename) { |
||
894 | unset($CacheDirOldFilesAge[$fullfilename]); |
||
895 | unset($CacheDirOldFilesSize[$fullfilename]); |
||
896 | } |
||
897 | } |
||
898 | |||
899 | View Code Duplication | if ($this->config_cache_maxage > 0) { |
|
900 | $mindate = time() - $this->config_cache_maxage; |
||
901 | $DeletedKeys['maxage'] = array(); |
||
902 | foreach ($CacheDirOldFilesAge as $fullfilename => $filedate) { |
||
903 | if ($filedate > 0) { |
||
904 | if ($filedate < $mindate) { |
||
905 | $this->DebugMessage('deleting "' . $fullfilename . '"', __FILE__, __LINE__); |
||
906 | if (@unlink($fullfilename)) { |
||
907 | $DeletedKeys['maxage'][] = $fullfilename; |
||
908 | } |
||
909 | } else { |
||
910 | // the rest of the files are new enough to keep |
||
911 | break; |
||
912 | } |
||
913 | } |
||
914 | } |
||
915 | $this->DebugMessage('CleanUpCacheDirectory() purged ' . count($DeletedKeys['maxage']) . ' files based on (config_cache_maxage=' . $this->config_cache_maxage . ')', __FILE__, __LINE__); |
||
916 | foreach ($DeletedKeys['maxage'] as $fullfilename) { |
||
917 | unset($CacheDirOldFilesAge[$fullfilename]); |
||
918 | unset($CacheDirOldFilesSize[$fullfilename]); |
||
919 | } |
||
920 | } |
||
921 | |||
922 | if ($this->config_cache_maxsize > 0) { |
||
923 | $TotalCachedFileSize = array_sum($CacheDirOldFilesSize); |
||
924 | $DeletedKeys['maxsize'] = array(); |
||
925 | foreach ($CacheDirOldFilesAge as $fullfilename => $filedate) { |
||
926 | if ($TotalCachedFileSize > $this->config_cache_maxsize) { |
||
927 | $this->DebugMessage('deleting "' . $fullfilename . '"', __FILE__, __LINE__); |
||
928 | if (@unlink($fullfilename)) { |
||
929 | $TotalCachedFileSize -= $CacheDirOldFilesSize[$fullfilename]; |
||
930 | $DeletedKeys['maxsize'][] = $fullfilename; |
||
931 | } |
||
932 | } else { |
||
933 | // the total filesizes are small enough to keep the rest of the files |
||
934 | break; |
||
935 | } |
||
936 | } |
||
937 | $this->DebugMessage('CleanUpCacheDirectory() purged ' . count($DeletedKeys['maxsize']) . ' files based on (config_cache_maxsize=' . $this->config_cache_maxsize . ')', __FILE__, |
||
938 | __LINE__); |
||
939 | foreach ($DeletedKeys['maxsize'] as $fullfilename) { |
||
940 | unset($CacheDirOldFilesAge[$fullfilename]); |
||
941 | unset($CacheDirOldFilesSize[$fullfilename]); |
||
942 | } |
||
943 | } |
||
944 | } else { |
||
945 | $this->DebugMessage('skipping CleanUpCacheDirectory() because config set to not use it', __FILE__, __LINE__); |
||
946 | } |
||
947 | $totalpurged = 0; |
||
948 | foreach ($DeletedKeys as $key => $value) { |
||
949 | $totalpurged += count($value); |
||
950 | } |
||
951 | $this->DebugMessage('CleanUpCacheDirectory() purged ' . $totalpurged . ' files (from ' . count($AllFilesInCacheDirectory) . ') based on config settings', __FILE__, __LINE__); |
||
952 | if ($totalpurged > 0) { |
||
953 | $empty_dirs = array(); |
||
954 | foreach ($AllFilesInCacheDirectory as $fullfilename) { |
||
955 | if (is_dir($fullfilename)) { |
||
956 | $empty_dirs[$this->realPathSafe($fullfilename)] = 1; |
||
957 | } else { |
||
958 | unset($empty_dirs[$this->realPathSafe(dirname($fullfilename))]); |
||
959 | } |
||
960 | } |
||
961 | krsort($empty_dirs); |
||
962 | $totalpurgeddirs = 0; |
||
963 | foreach ($empty_dirs as $empty_dir => $dummy) { |
||
964 | if ($empty_dir == $this->config_cache_directory) { |
||
965 | // shouldn't happen, but just in case, don't let it delete actual cache directory |
||
966 | continue; |
||
967 | } elseif (@rmdir($empty_dir)) { |
||
968 | $totalpurgeddirs++; |
||
969 | } else { |
||
970 | $this->DebugMessage('failed to rmdir(' . $empty_dir . ')', __FILE__, __LINE__); |
||
971 | } |
||
972 | } |
||
973 | $this->DebugMessage('purged ' . $totalpurgeddirs . ' empty directories', __FILE__, __LINE__); |
||
974 | } |
||
975 | |||
976 | return true; |
||
977 | } |
||
978 | |||
979 | ////////////////////////////////////////////////////////////////////// |
||
980 | |||
981 | // private: re-initializator (call between rendering multiple images with one object) |
||
982 | /** |
||
983 | * @return bool |
||
984 | */ |
||
985 | public function resetObject() |
||
986 | { |
||
987 | $class_vars = get_class_vars(get_class($this)); |
||
988 | foreach ($class_vars as $key => $value) { |
||
989 | // do not clobber debug or config info |
||
990 | if (!preg_match('#^(config_|debug|fatalerror)#i', $key)) { |
||
991 | $this->$key = $value; |
||
992 | } |
||
993 | } |
||
994 | $this->phpThumb(); // re-initialize some class variables |
||
995 | return true; |
||
996 | } |
||
997 | |||
998 | ////////////////////////////////////////////////////////////////////// |
||
999 | |||
1000 | /** |
||
1001 | * @return bool |
||
1002 | */ |
||
1003 | public function ResolveSource() |
||
1004 | { |
||
1005 | if (is_resource($this->gdimg_source)) { |
||
1006 | $this->DebugMessage('ResolveSource() exiting because is_resource($this->gdimg_source)', __FILE__, __LINE__); |
||
1007 | |||
1008 | return true; |
||
1009 | } |
||
1010 | if ($this->rawImageData) { |
||
1011 | $this->sourceFilename = null; |
||
1012 | $this->DebugMessage('ResolveSource() exiting because $this->rawImageData is set (' . number_format(strlen($this->rawImageData)) . ' bytes)', __FILE__, __LINE__); |
||
1013 | |||
1014 | return true; |
||
1015 | } |
||
1016 | if ($this->sourceFilename) { |
||
1017 | $this->sourceFilename = $this->ResolveFilenameToAbsolute($this->sourceFilename); |
||
1018 | $this->DebugMessage('$this->sourceFilename set to "' . $this->sourceFilename . '"', __FILE__, __LINE__); |
||
1019 | } elseif ($this->src) { |
||
1020 | $this->sourceFilename = $this->ResolveFilenameToAbsolute($this->src); |
||
1021 | $this->DebugMessage('$this->sourceFilename set to "' . $this->sourceFilename . '" from $this->src (' . $this->src . ')', __FILE__, __LINE__); |
||
1022 | } else { |
||
1023 | return $this->ErrorImage('$this->sourceFilename and $this->src are both empty'); |
||
1024 | } |
||
1025 | if ($this->iswindows |
||
1026 | && ((substr($this->sourceFilename, 0, 2) == '//') |
||
1027 | || (substr($this->sourceFilename, 0, 2) == '\\\\')) |
||
1028 | ) { |
||
1029 | // Windows \\share\filename.ext |
||
1030 | } elseif (preg_match('#^[a-z0-9]+://#i', $this->sourceFilename, $protocol_matches)) { |
||
1031 | if (preg_match('#^(f|ht)tps?\://#i', $this->sourceFilename)) { |
||
1032 | // URL |
||
1033 | if ($this->config_http_user_agent) { |
||
1034 | ini_set('user_agent', $this->config_http_user_agent); |
||
1035 | } |
||
1036 | } else { |
||
1037 | return $this->ErrorImage('only FTP and HTTP/HTTPS protocols are allowed, "' . $protocol_matches[1] . '" is not'); |
||
1038 | } |
||
1039 | } elseif (!@file_exists($this->sourceFilename)) { |
||
1040 | return $this->ErrorImage('"' . $this->sourceFilename . '" does not exist'); |
||
1041 | } elseif (!@is_file($this->sourceFilename)) { |
||
1042 | return $this->ErrorImage('"' . $this->sourceFilename . '" is not a file'); |
||
1043 | } |
||
1044 | |||
1045 | return true; |
||
1046 | } |
||
1047 | |||
1048 | /** |
||
1049 | * @return bool |
||
1050 | */ |
||
1051 | public function setOutputFormat() |
||
1052 | { |
||
1053 | static $alreadyCalled = false; |
||
1054 | if ($this->thumbnailFormat && $alreadyCalled) { |
||
1055 | return true; |
||
1056 | } |
||
1057 | $alreadyCalled = true; |
||
1058 | |||
1059 | $AvailableImageOutputFormats = array(); |
||
1060 | $AvailableImageOutputFormats[] = 'text'; |
||
1061 | if (@is_readable(__DIR__ . '/phpthumb.ico.php')) { |
||
1062 | $AvailableImageOutputFormats[] = 'ico'; |
||
1063 | } |
||
1064 | if (@is_readable(__DIR__ . '/phpthumb.bmp.php')) { |
||
1065 | $AvailableImageOutputFormats[] = 'bmp'; |
||
1066 | } |
||
1067 | |||
1068 | $this->thumbnailFormat = 'ico'; |
||
1069 | |||
1070 | // Set default output format based on what image types are available |
||
1071 | if (function_exists('ImageTypes')) { |
||
1072 | $imagetypes = imagetypes(); |
||
1073 | if ($imagetypes & IMG_WBMP) { |
||
1074 | $this->thumbnailFormat = 'wbmp'; |
||
1075 | $AvailableImageOutputFormats[] = 'wbmp'; |
||
1076 | } |
||
1077 | if ($imagetypes & IMG_GIF) { |
||
1078 | $this->thumbnailFormat = 'gif'; |
||
1079 | $AvailableImageOutputFormats[] = 'gif'; |
||
1080 | } |
||
1081 | if ($imagetypes & IMG_PNG) { |
||
1082 | $this->thumbnailFormat = 'png'; |
||
1083 | $AvailableImageOutputFormats[] = 'png'; |
||
1084 | } |
||
1085 | if ($imagetypes & IMG_JPG) { |
||
1086 | $this->thumbnailFormat = 'jpeg'; |
||
1087 | $AvailableImageOutputFormats[] = 'jpeg'; |
||
1088 | } |
||
1089 | } else { |
||
1090 | //return $this->ErrorImage('ImageTypes() does not exist - GD support might not be enabled?'); |
||
1091 | $this->DebugMessage('ImageTypes() does not exist - GD support might not be enabled?', __FILE__, __LINE__); |
||
1092 | } |
||
1093 | if ($this->ImageMagickVersion()) { |
||
1094 | $IMformats = array('jpeg', 'png', 'gif', 'bmp', 'ico', 'wbmp'); |
||
1095 | $this->DebugMessage('Addding ImageMagick formats to $AvailableImageOutputFormats (' . implode(';', $AvailableImageOutputFormats) . ')', __FILE__, __LINE__); |
||
1096 | foreach ($IMformats as $key => $format) { |
||
1097 | $AvailableImageOutputFormats[] = $format; |
||
1098 | } |
||
1099 | } |
||
1100 | $AvailableImageOutputFormats = array_unique($AvailableImageOutputFormats); |
||
1101 | $this->DebugMessage('$AvailableImageOutputFormats = array(' . implode(';', $AvailableImageOutputFormats) . ')', __FILE__, __LINE__); |
||
1102 | |||
1103 | $this->f = preg_replace('#[^a-z]#', '', strtolower($this->f)); |
||
1104 | if (strtolower($this->config_output_format) == 'jpg') { |
||
1105 | $this->config_output_format = 'jpeg'; |
||
1106 | } |
||
1107 | if (strtolower($this->f) == 'jpg') { |
||
1108 | $this->f = 'jpeg'; |
||
1109 | } |
||
1110 | View Code Duplication | if (phpthumb_functions::CaseInsensitiveInArray($this->config_output_format, $AvailableImageOutputFormats)) { |
|
1111 | // set output format to config default if that format is available |
||
1112 | $this->DebugMessage('$this->thumbnailFormat set to $this->config_output_format "' . strtolower($this->config_output_format) . '"', __FILE__, __LINE__); |
||
1113 | $this->thumbnailFormat = strtolower($this->config_output_format); |
||
1114 | } elseif ($this->config_output_format) { |
||
1115 | $this->DebugMessage('$this->thumbnailFormat staying as "' |
||
1116 | . $this->thumbnailFormat |
||
1117 | . '" because $this->config_output_format (' |
||
1118 | . strtolower($this->config_output_format) |
||
1119 | . ') is not in $AvailableImageOutputFormats', __FILE__, __LINE__); |
||
1120 | } |
||
1121 | View Code Duplication | if ($this->f && phpthumb_functions::CaseInsensitiveInArray($this->f, $AvailableImageOutputFormats)) { |
|
1122 | // override output format if $this->f is set and that format is available |
||
1123 | $this->DebugMessage('$this->thumbnailFormat set to $this->f "' . strtolower($this->f) . '"', __FILE__, __LINE__); |
||
1124 | $this->thumbnailFormat = strtolower($this->f); |
||
1125 | } elseif ($this->f) { |
||
1126 | $this->DebugMessage('$this->thumbnailFormat staying as "' . $this->thumbnailFormat . '" because $this->f (' . strtolower($this->f) . ') is not in $AvailableImageOutputFormats', __FILE__, |
||
1127 | __LINE__); |
||
1128 | } |
||
1129 | |||
1130 | // for JPEG images, quality 1 (worst) to 99 (best) |
||
1131 | // quality < 25 is nasty, with not much size savings - not recommended |
||
1132 | // problems with 100 - invalid JPEG? |
||
1133 | $this->thumbnailQuality = max(1, min(99, ($this->q ? (int)$this->q : 75))); |
||
1134 | $this->DebugMessage('$this->thumbnailQuality set to "' . $this->thumbnailQuality . '"', __FILE__, __LINE__); |
||
1135 | |||
1136 | return true; |
||
1137 | } |
||
1138 | |||
1139 | /** |
||
1140 | * @return bool |
||
1141 | */ |
||
1142 | public function setCacheDirectory() |
||
1143 | { |
||
1144 | // resolve cache directory to absolute pathname |
||
1145 | $this->DebugMessage('setCacheDirectory() starting with config_cache_directory = "' . $this->config_cache_directory . '"', __FILE__, __LINE__); |
||
1146 | if (substr($this->config_cache_directory, 0, 1) == '.') { |
||
1147 | if (preg_match('#^(f|ht)tps?\://#i', $this->src)) { |
||
1148 | if (!$this->config_cache_disable_warning) { |
||
1149 | $this->ErrorImage('$this->config_cache_directory (' |
||
1150 | . $this->config_cache_directory |
||
1151 | . ') cannot be used for remote images. Adjust "cache_directory" or "cache_disable_warning" in phpThumb.config.php'); |
||
1152 | } |
||
1153 | } elseif ($this->src) { |
||
1154 | // resolve relative cache directory to source image |
||
1155 | $this->config_cache_directory = dirname($this->ResolveFilenameToAbsolute($this->src)) . DIRECTORY_SEPARATOR . $this->config_cache_directory; |
||
1156 | } else { |
||
1157 | // $this->new is probably set |
||
1158 | } |
||
1159 | } |
||
1160 | if (substr($this->config_cache_directory, -1) == '/') { |
||
1161 | $this->config_cache_directory = substr($this->config_cache_directory, 0, -1); |
||
1162 | } |
||
1163 | if ($this->iswindows) { |
||
1164 | $this->config_cache_directory = str_replace('/', DIRECTORY_SEPARATOR, $this->config_cache_directory); |
||
1165 | } |
||
1166 | if ($this->config_cache_directory) { |
||
1167 | $real_cache_path = $this->realPathSafe($this->config_cache_directory); |
||
1168 | if (!$real_cache_path) { |
||
1169 | $this->DebugMessage('$this->realPathSafe($this->config_cache_directory) failed for "' . $this->config_cache_directory . '"', __FILE__, __LINE__); |
||
1170 | if (!is_dir($this->config_cache_directory)) { |
||
1171 | $this->DebugMessage('!is_dir(' . $this->config_cache_directory . ')', __FILE__, __LINE__); |
||
1172 | } |
||
1173 | } |
||
1174 | if ($real_cache_path) { |
||
1175 | $this->DebugMessage('setting config_cache_directory to $this->realPathSafe(' . $this->config_cache_directory . ') = "' . $real_cache_path . '"', __FILE__, __LINE__); |
||
1176 | $this->config_cache_directory = $real_cache_path; |
||
1177 | } |
||
1178 | } |
||
1179 | if (!is_dir($this->config_cache_directory)) { |
||
1180 | if (!$this->config_cache_disable_warning) { |
||
1181 | $this->ErrorImage('$this->config_cache_directory (' . $this->config_cache_directory . ') does not exist. Adjust "cache_directory" or "cache_disable_warning" in phpThumb.config.php'); |
||
1182 | } |
||
1183 | $this->DebugMessage('$this->config_cache_directory (' . $this->config_cache_directory . ') is not a directory', __FILE__, __LINE__); |
||
1184 | $this->config_cache_directory = null; |
||
1185 | View Code Duplication | } elseif (!@is_writable($this->config_cache_directory)) { |
|
1186 | $this->DebugMessage('$this->config_cache_directory is not writable (' . $this->config_cache_directory . ')', __FILE__, __LINE__); |
||
1187 | } |
||
1188 | |||
1189 | $this->InitializeTempDirSetting(); |
||
1190 | if (!@is_dir($this->config_temp_directory) && !@is_writable($this->config_temp_directory) |
||
1191 | && @is_dir($this->config_cache_directory) |
||
1192 | && @is_writable($this->config_cache_directory) |
||
1193 | ) { |
||
1194 | $this->DebugMessage('setting $this->config_temp_directory = $this->config_cache_directory (' . $this->config_cache_directory . ')', __FILE__, __LINE__); |
||
1195 | $this->config_temp_directory = $this->config_cache_directory; |
||
1196 | } |
||
1197 | |||
1198 | return true; |
||
1199 | } |
||
1200 | |||
1201 | /* Takes the array of path segments up to now, and the next segment (maybe a modifier: empty, . or ..) |
||
1202 | Applies it, adding or removing from $segments as a result. Returns nothing. */ |
||
1203 | // http://support.silisoftware.com/phpBB3/viewtopic.php?t=961 |
||
1204 | /** |
||
1205 | * @param $segments |
||
1206 | * @param $segment |
||
1207 | */ |
||
1208 | public function applyPathSegment(&$segments, $segment) |
||
1209 | { |
||
1210 | if ($segment == '.') { |
||
1211 | return; // always remove |
||
1212 | } |
||
1213 | if ($segment == '') { |
||
1214 | $test = array_pop($segments); |
||
1215 | if (is_null($test)) { |
||
1216 | $segments[] = $segment; // keep the first empty block |
||
1217 | View Code Duplication | } elseif ($test == '') { |
|
1218 | $test = array_pop($segments); |
||
1219 | if (is_null($test)) { |
||
1220 | $segments[] = $test; |
||
1221 | $segments[] = $segment; // keep the second one too |
||
1222 | } else { // put both back and ignore segment |
||
1223 | $segments[] = $test; |
||
1224 | $segments[] = $test; |
||
1225 | } |
||
1226 | } else { |
||
1227 | $segments[] = $test; // ignore empty blocks |
||
1228 | } |
||
1229 | } else { |
||
1230 | if ($segment == '..') { |
||
1231 | $test = array_pop($segments); |
||
1232 | View Code Duplication | if (is_null($test)) { |
|
1233 | $segments[] = $segment; |
||
1234 | } elseif ($test == '..') { |
||
1235 | $segments[] = $test; |
||
1236 | $segments[] = $segment; |
||
1237 | } else { |
||
1238 | if ($test == '') { |
||
1239 | $segments[] = $test; |
||
1240 | } // else nothing, remove both |
||
1241 | } |
||
1242 | } else { |
||
1243 | $segments[] = $segment; |
||
1244 | } |
||
1245 | } |
||
1246 | } |
||
1247 | |||
1248 | /* Takes array of path components, normalizes it: removes empty slots and '.', collapses '..' and folder names. Returns array. */ |
||
1249 | // http://support.silisoftware.com/phpBB3/viewtopic.php?t=961 |
||
1250 | /** |
||
1251 | * @param $segments |
||
1252 | * @return array |
||
1253 | */ |
||
1254 | public function normalizePath($segments) |
||
1255 | { |
||
1256 | $parts = array(); |
||
1257 | foreach ($segments as $segment) { |
||
1258 | $this->applyPathSegment($parts, $segment); |
||
1259 | } |
||
1260 | |||
1261 | return $parts; |
||
1262 | } |
||
1263 | |||
1264 | /* True if the provided path points (without resolving symbolic links) into one of the allowed directories. */ |
||
1265 | // http://support.silisoftware.com/phpBB3/viewtopic.php?t=961 |
||
1266 | /** |
||
1267 | * @param $path |
||
1268 | * @param $allowed_dirs |
||
1269 | * @return bool |
||
1270 | */ |
||
1271 | public function matchPath($path, $allowed_dirs) |
||
1272 | { |
||
1273 | if (!empty($allowed_dirs)) { |
||
1274 | foreach ($allowed_dirs as $one_dir) { |
||
1275 | if (preg_match('#^' . preg_quote(str_replace(DIRECTORY_SEPARATOR, '/', $this->realPathSafe($one_dir))) . '#', $path)) { |
||
1276 | return true; |
||
1277 | } |
||
1278 | } |
||
1279 | } |
||
1280 | |||
1281 | return false; |
||
1282 | } |
||
1283 | |||
1284 | /* True if the provided path points inside one of open_basedirs (or if open_basedirs are disabled) */ |
||
1285 | // http://support.silisoftware.com/phpBB3/viewtopic.php?t=961 |
||
1286 | /** |
||
1287 | * @param $path |
||
1288 | * @return bool |
||
1289 | */ |
||
1290 | public function isInOpenBasedir($path) |
||
1291 | { |
||
1292 | static $open_basedirs = null; |
||
1293 | if (is_null($open_basedirs)) { |
||
1294 | $ini_text = ini_get('open_basedir'); |
||
1295 | $this->DebugMessage('open_basedir: "' . $ini_text . '"', __FILE__, __LINE__); |
||
1296 | $open_basedirs = array(); |
||
1297 | if (strlen($ini_text) > 0) { |
||
1298 | foreach (preg_split('#[;:]#', $ini_text) as $key => $value) { |
||
1299 | $open_basedirs[$key] = $this->realPathSafe($value); |
||
1300 | } |
||
1301 | } |
||
1302 | } |
||
1303 | |||
1304 | return (empty($open_basedirs) || $this->matchPath($path, $open_basedirs)); |
||
1305 | } |
||
1306 | |||
1307 | /* 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. */ |
||
1308 | // http://support.silisoftware.com/phpBB3/viewtopic.php?t=961 |
||
1309 | /** |
||
1310 | * @param $path |
||
1311 | * @param $allowed_dirs |
||
1312 | * @return null|string |
||
1313 | */ |
||
1314 | public function resolvePath($path, $allowed_dirs) |
||
1315 | { |
||
1316 | $this->DebugMessage('resolvePath: ' . $path . ' (allowed_dirs: ' . print_r($allowed_dirs, true) . ')', __FILE__, __LINE__); |
||
1317 | |||
1318 | // add base path to the top of the list |
||
1319 | if (!$this->config_allow_src_above_docroot) { |
||
1320 | array_unshift($allowed_dirs, $this->realPathSafe($this->config_document_root)); |
||
1321 | } else { |
||
1322 | if (!$this->config_allow_src_above_phpthumb) { |
||
1323 | array_unshift($allowed_dirs, $this->realPathSafe(__DIR__)); |
||
1324 | } else { |
||
1325 | // no checks are needed, offload the work to realpath and forget about it |
||
1326 | $this->DebugMessage('resolvePath: checks disabled, returning ' . $this->realPathSafe($path), __FILE__, __LINE__); |
||
1327 | |||
1328 | return $this->realPathSafe($path); |
||
1329 | } |
||
1330 | } |
||
1331 | if ($path == '') { |
||
1332 | return null; // save us trouble |
||
1333 | } |
||
1334 | |||
1335 | do { |
||
1336 | $this->DebugMessage('resolvePath: iteration, path=' . $path . ', base path = ' . $allowed_dirs[0], __FILE__, __LINE__); |
||
1337 | |||
1338 | $parts = array(); |
||
1339 | // do not use "cleaner" foreach version of this loop as later code relies on both $segments and $i |
||
1340 | // http://support.silisoftware.com/phpBB3/viewtopic.php?t=964 |
||
1341 | $segments = explode(DIRECTORY_SEPARATOR, $path); |
||
1342 | for ($i = 0, $iMax = count($segments); $i < $iMax; ++$i) { |
||
1343 | $this->applyPathSegment($parts, $segments[$i]); |
||
1344 | $thispart = implode(DIRECTORY_SEPARATOR, $parts); |
||
1345 | if ($this->isInOpenBasedir($thispart)) { |
||
1346 | if (is_link($thispart)) { |
||
1347 | break; |
||
1348 | } |
||
1349 | } |
||
1350 | } |
||
1351 | |||
1352 | $this->DebugMessage('resolvePath: stop at component ' . $i, __FILE__, __LINE__); |
||
1353 | // test the part up to here |
||
1354 | $path = implode(DIRECTORY_SEPARATOR, $parts); |
||
1355 | $this->DebugMessage('resolvePath: stop at path=' . $path, __FILE__, __LINE__); |
||
1356 | if (!$this->matchPath($path, $allowed_dirs)) { |
||
1357 | $this->DebugMessage('resolvePath: no match, returning null', __FILE__, __LINE__); |
||
1358 | |||
1359 | return null; |
||
1360 | } |
||
1361 | if ($i >= count($segments)) { // reached end |
||
1362 | $this->DebugMessage('resolvePath: path parsed, over', __FILE__, __LINE__); |
||
1363 | break; |
||
1364 | } |
||
1365 | // else it's symlink, rewrite path |
||
1366 | $path = readlink($path); |
||
1367 | $this->DebugMessage('resolvePath: symlink matched, target=' . $path, __FILE__, __LINE__); |
||
1368 | |||
1369 | /* |
||
1370 | Replace base path with symlink target. |
||
1371 | Assuming: |
||
1372 | /www/img/external -> /external |
||
1373 | This is allowed: |
||
1374 | GET /www/img/external/../external/test/pic.jpg |
||
1375 | This isn't: |
||
1376 | GET /www/img/external/../www/img/pic.jpg |
||
1377 | So there's only one base path which is the last symlink target, but any number of stable whitelisted paths. |
||
1378 | */ |
||
1379 | if ($this->config_auto_allow_symlinks) { |
||
1380 | $allowed_dirs[0] = $path; |
||
1381 | } |
||
1382 | $path = $path . DIRECTORY_SEPARATOR . implode(DIRECTORY_SEPARATOR, array_slice($segments, $i + 1)); |
||
1383 | } while (true); |
||
1384 | |||
1385 | return $path; |
||
1386 | } |
||
1387 | |||
1388 | /** |
||
1389 | * @param $filename |
||
1390 | * @return mixed|string |
||
1391 | */ |
||
1392 | public function realPathSafe($filename) |
||
1393 | { |
||
1394 | // 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" |
||
1395 | // realPathSafe() provides a reasonable facsimile of realpath() but does not resolve symbolic links, nor does it check that the file/path actually exists |
||
1396 | if (!$this->config_disable_realpath) { |
||
1397 | return realpath($filename); |
||
1398 | } |
||
1399 | |||
1400 | // http://stackoverflow.com/questions/21421569 |
||
1401 | $newfilename = preg_replace('#[\\/]+#', DIRECTORY_SEPARATOR, $filename); |
||
1402 | if (!preg_match('#^' . DIRECTORY_SEPARATOR . '#', $newfilename)) { |
||
1403 | $newfilename = __DIR__ . DIRECTORY_SEPARATOR . $newfilename; |
||
1404 | } |
||
1405 | do { |
||
1406 | $beforeloop = $newfilename; |
||
1407 | |||
1408 | // 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.]] |
||
1409 | $newfilename = preg_replace('#' . DIRECTORY_SEPARATOR . '+#', DIRECTORY_SEPARATOR, $newfilename); |
||
1410 | |||
1411 | // Replace all occurrences of /./ with / |
||
1412 | $newfilename = preg_replace('#' . DIRECTORY_SEPARATOR . '\\.' . DIRECTORY_SEPARATOR . '#', DIRECTORY_SEPARATOR, $newfilename); |
||
1413 | |||
1414 | // Remove ./ if at the start |
||
1415 | $newfilename = preg_replace('#^\\.' . DIRECTORY_SEPARATOR . '#', '', $newfilename); |
||
1416 | |||
1417 | // Remove /. if at the end |
||
1418 | $newfilename = preg_replace('#' . DIRECTORY_SEPARATOR . '\\.$#', '', $newfilename); |
||
1419 | |||
1420 | // Replace /anything/../ with / |
||
1421 | $newfilename = preg_replace('#' . DIRECTORY_SEPARATOR . '[^' . DIRECTORY_SEPARATOR . ']+' . DIRECTORY_SEPARATOR . '\\.\\.' . DIRECTORY_SEPARATOR . '#', DIRECTORY_SEPARATOR, $newfilename); |
||
1422 | |||
1423 | // Remove /anything/.. if at the end |
||
1424 | $newfilename = preg_replace('#' . DIRECTORY_SEPARATOR . '[^' . DIRECTORY_SEPARATOR . ']+' . DIRECTORY_SEPARATOR . '\\.\\.$#', '', $newfilename); |
||
1425 | } while ($newfilename != $beforeloop); |
||
1426 | |||
1427 | return $newfilename; |
||
1428 | } |
||
1429 | |||
1430 | /** |
||
1431 | * @param $filename |
||
1432 | * @return bool|mixed|string |
||
1433 | */ |
||
1434 | public function ResolveFilenameToAbsolute($filename) |
||
1435 | { |
||
1436 | if (empty($filename)) { |
||
1437 | return false; |
||
1438 | } |
||
1439 | |||
1440 | if (preg_match('#^[a-z0-9]+\:/{1,2}#i', $filename)) { |
||
1441 | // eg: http://host/path/file.jpg (HTTP URL) |
||
1442 | // eg: ftp://host/path/file.jpg (FTP URL) |
||
1443 | // eg: data1:/path/file.jpg (Netware path) |
||
1444 | |||
1445 | //$AbsoluteFilename = $filename; |
||
1446 | return $filename; |
||
1447 | } elseif ($this->iswindows && isset($filename{1}) && ($filename{1} == ':')) { |
||
1448 | |||
1449 | // absolute pathname (Windows) |
||
1450 | $AbsoluteFilename = $filename; |
||
1451 | } elseif ($this->iswindows && ((substr($filename, 0, 2) == '//') || (substr($filename, 0, 2) == '\\\\'))) { |
||
1452 | |||
1453 | // absolute pathname (Windows) |
||
1454 | $AbsoluteFilename = $filename; |
||
1455 | } elseif ($filename{0} == '/') { |
||
1456 | if (@is_readable($filename) && !@is_readable($this->config_document_root . $filename)) { |
||
1457 | |||
1458 | // absolute filename (*nix) |
||
1459 | $AbsoluteFilename = $filename; |
||
1460 | } elseif (isset($filename{1}) && ($filename{1} == '~')) { |
||
1461 | |||
1462 | // /~user/path |
||
1463 | if ($ApacheLookupURIarray = phpthumb_functions::ApacheLookupURIarray($filename)) { |
||
1464 | $AbsoluteFilename = $ApacheLookupURIarray['filename']; |
||
1465 | } else { |
||
1466 | $AbsoluteFilename = $this->realPathSafe($filename); |
||
1467 | if (@is_readable($AbsoluteFilename)) { |
||
1468 | $this->DebugMessage('phpthumb_functions::ApacheLookupURIarray() failed for "' |
||
1469 | . $filename |
||
1470 | . '", but the correct filename (' |
||
1471 | . $AbsoluteFilename |
||
1472 | . ') seems to have been resolved with $this->realPathSafe($filename)', __FILE__, __LINE__); |
||
1473 | View Code Duplication | } elseif (is_dir(dirname($AbsoluteFilename))) { |
|
1474 | $this->DebugMessage('phpthumb_functions::ApacheLookupURIarray() failed for "' |
||
1475 | . dirname($filename) |
||
1476 | . '", but the correct directory (' |
||
1477 | . dirname($AbsoluteFilename) |
||
1478 | . ') seems to have been resolved with $this->realPathSafe(.)', __FILE__, __LINE__); |
||
1479 | } else { |
||
1480 | return $this->ErrorImage('phpthumb_functions::ApacheLookupURIarray() failed for "' |
||
1481 | . $filename |
||
1482 | . '". 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")'); |
||
1483 | } |
||
1484 | } |
||
1485 | } else { |
||
1486 | |||
1487 | // relative filename (any OS) |
||
1488 | if (preg_match('#^' . preg_quote($this->config_document_root) . '#', $filename)) { |
||
1489 | $AbsoluteFilename = $filename; |
||
1490 | $this->DebugMessage('ResolveFilenameToAbsolute() NOT prepending $this->config_document_root (' |
||
1491 | . $this->config_document_root |
||
1492 | . ') to $filename (' |
||
1493 | . $filename |
||
1494 | . ') resulting in ($AbsoluteFilename = "' |
||
1495 | . $AbsoluteFilename |
||
1496 | . '")', __FILE__, __LINE__); |
||
1497 | } else { |
||
1498 | $AbsoluteFilename = $this->config_document_root . $filename; |
||
1499 | $this->DebugMessage('ResolveFilenameToAbsolute() prepending $this->config_document_root (' |
||
1500 | . $this->config_document_root |
||
1501 | . ') to $filename (' |
||
1502 | . $filename |
||
1503 | . ') resulting in ($AbsoluteFilename = "' |
||
1504 | . $AbsoluteFilename |
||
1505 | . '")', __FILE__, __LINE__); |
||
1506 | } |
||
1507 | } |
||
1508 | } else { |
||
1509 | |||
1510 | // relative to current directory (any OS) |
||
1511 | $AbsoluteFilename = __DIR__ . DIRECTORY_SEPARATOR . preg_replace('#[/\\\\]#', DIRECTORY_SEPARATOR, $filename); |
||
1512 | |||
1513 | if (substr(dirname(@$_SERVER['PHP_SELF']), 0, 2) == '/~') { |
||
1514 | if ($ApacheLookupURIarray = phpthumb_functions::ApacheLookupURIarray(dirname(@$_SERVER['PHP_SELF']))) { |
||
1515 | $AbsoluteFilename = $ApacheLookupURIarray['filename'] . DIRECTORY_SEPARATOR . $filename; |
||
1516 | } else { |
||
1517 | $AbsoluteFilename = $this->realPathSafe('.') . DIRECTORY_SEPARATOR . $filename; |
||
1518 | if (@is_readable($AbsoluteFilename)) { |
||
1519 | $this->DebugMessage('phpthumb_functions::ApacheLookupURIarray() failed for "' |
||
1520 | . dirname(@$_SERVER['PHP_SELF']) |
||
1521 | . '", but the correct filename (' |
||
1522 | . $AbsoluteFilename |
||
1523 | . ') seems to have been resolved with $this->realPathSafe(.)/$filename', __FILE__, __LINE__); |
||
1524 | View Code Duplication | } elseif (is_dir(dirname($AbsoluteFilename))) { |
|
1525 | $this->DebugMessage('phpthumb_functions::ApacheLookupURIarray() failed for "' |
||
1526 | . dirname(@$_SERVER['PHP_SELF']) |
||
1527 | . '", but the correct directory (' |
||
1528 | . dirname($AbsoluteFilename) |
||
1529 | . ') seems to have been resolved with $this->realPathSafe(.)', __FILE__, __LINE__); |
||
1530 | } else { |
||
1531 | return $this->ErrorImage('phpthumb_functions::ApacheLookupURIarray() failed for "' |
||
1532 | . dirname(@$_SERVER['PHP_SELF']) |
||
1533 | . '". This has been known to fail on Apache2 - try using the absolute filename for the source image'); |
||
1534 | } |
||
1535 | } |
||
1536 | } |
||
1537 | } |
||
1538 | /* |
||
1539 | // removed 2014-May-30: http://support.silisoftware.com/phpBB3/viewtopic.php?t=961 |
||
1540 | if (is_link($AbsoluteFilename)) { |
||
1541 | $this->DebugMessage('is_link()==true, changing "'.$AbsoluteFilename.'" to "'.readlink($AbsoluteFilename).'"', __FILE__, __LINE__); |
||
1542 | $AbsoluteFilename = readlink($AbsoluteFilename); |
||
1543 | } |
||
1544 | if ($this->realPathSafe($AbsoluteFilename)) { |
||
1545 | $AbsoluteFilename = $this->realPathSafe($AbsoluteFilename); |
||
1546 | } |
||
1547 | */ |
||
1548 | if ($this->iswindows) { |
||
1549 | $AbsoluteFilename = preg_replace('#^' . preg_quote($this->realPathSafe($this->config_document_root)) . '#i', $this->realPathSafe($this->config_document_root), $AbsoluteFilename); |
||
1550 | $AbsoluteFilename = str_replace(DIRECTORY_SEPARATOR, '/', $AbsoluteFilename); |
||
1551 | } |
||
1552 | $AbsoluteFilename = $this->resolvePath($AbsoluteFilename, $this->config_additional_allowed_dirs); |
||
1553 | if (!$this->config_allow_src_above_docroot |
||
1554 | && !preg_match('#^' . preg_quote(str_replace(DIRECTORY_SEPARATOR, '/', $this->realPathSafe($this->config_document_root))) . '#', $AbsoluteFilename) |
||
1555 | ) { |
||
1556 | $this->DebugMessage('!$this->config_allow_src_above_docroot therefore setting "' . $AbsoluteFilename . '" (outside "' . $this->realPathSafe($this->config_document_root) . '") to null', |
||
1557 | __FILE__, __LINE__); |
||
1558 | |||
1559 | return false; |
||
1560 | } |
||
1561 | if (!$this->config_allow_src_above_phpthumb |
||
1562 | && !preg_match('#^' . preg_quote(str_replace(DIRECTORY_SEPARATOR, '/', __DIR__)) . '#', $AbsoluteFilename) |
||
1563 | ) { |
||
1564 | $this->DebugMessage('!$this->config_allow_src_above_phpthumb therefore setting "' . $AbsoluteFilename . '" (outside "' . __DIR__ . '") to null', __FILE__, __LINE__); |
||
1565 | |||
1566 | return false; |
||
1567 | } |
||
1568 | |||
1569 | return $AbsoluteFilename; |
||
1570 | } |
||
1571 | |||
1572 | /** |
||
1573 | * @param $filename |
||
1574 | * @param bool $cached |
||
1575 | * @return mixed |
||
1576 | */ |
||
1577 | public function file_exists_ignoreopenbasedir($filename, $cached = true) |
||
1578 | { |
||
1579 | static $open_basedirs = null; |
||
1580 | static $file_exists_cache = array(); |
||
1581 | if (!$cached || !isset($file_exists_cache[$filename])) { |
||
1582 | if (is_null($open_basedirs)) { |
||
1583 | $open_basedirs = preg_split('#[;:]#', ini_get('open_basedir')); |
||
1584 | } |
||
1585 | if (empty($open_basedirs) || in_array(dirname($filename), $open_basedirs)) { |
||
1586 | $file_exists_cache[$filename] = file_exists($filename); |
||
1587 | } elseif ($this->iswindows) { |
||
1588 | $ls_filename = trim(phpthumb_functions::SafeExec('dir /b ' . phpthumb_functions::escapeshellarg_replacement($filename))); |
||
1589 | $file_exists_cache[$filename] = ($ls_filename == basename($filename)); // command dir /b return only filename without path |
||
1590 | } else { |
||
1591 | $ls_filename = trim(phpthumb_functions::SafeExec('ls ' . phpthumb_functions::escapeshellarg_replacement($filename))); |
||
1592 | $file_exists_cache[$filename] = ($ls_filename == $filename); |
||
1593 | } |
||
1594 | } |
||
1595 | |||
1596 | return $file_exists_cache[$filename]; |
||
1597 | } |
||
1598 | |||
1599 | /** |
||
1600 | * @return bool|null|string |
||
1601 | */ |
||
1602 | public function ImageMagickWhichConvert() |
||
1603 | { |
||
1604 | static $WhichConvert = null; |
||
1605 | if (is_null($WhichConvert)) { |
||
1606 | if ($this->iswindows) { |
||
1607 | $WhichConvert = false; |
||
1608 | } else { |
||
1609 | $IMwhichConvertCacheFilename = $this->config_cache_directory . DIRECTORY_SEPARATOR . 'phpThumbCacheIMwhichConvert.txt'; |
||
1610 | if (($cachedwhichconvertstring = @file_get_contents($IMwhichConvertCacheFilename)) !== false) { |
||
1611 | $WhichConvert = $cachedwhichconvertstring; |
||
1612 | } else { |
||
1613 | $WhichConvert = trim(phpthumb_functions::SafeExec('which convert')); |
||
1614 | @file_put_contents($IMwhichConvertCacheFilename, $WhichConvert); |
||
0 ignored issues
–
show
It seems like you do not handle an error condition here. This can introduce security issues, and is generally not recommended.
If you suppress an error, we recommend checking for the error condition explicitly: // For example instead of
@mkdir($dir);
// Better use
if (@mkdir($dir) === false) {
throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
![]() |
|||
1615 | } |
||
1616 | } |
||
1617 | } |
||
1618 | |||
1619 | return $WhichConvert; |
||
1620 | } |
||
1621 | |||
1622 | /** |
||
1623 | * @return bool|null|string |
||
1624 | */ |
||
1625 | public function ImageMagickCommandlineBase() |
||
1626 | { |
||
1627 | static $commandline = null; |
||
1628 | if (is_null($commandline)) { |
||
1629 | if ($this->issafemode) { |
||
1630 | $commandline = ''; |
||
1631 | |||
1632 | return $commandline; |
||
1633 | } |
||
1634 | |||
1635 | $IMcommandlineBaseCacheFilename = $this->config_cache_directory . DIRECTORY_SEPARATOR . 'phpThumbCacheIMcommandlineBase.txt'; |
||
1636 | if (($commandline = @file_get_contents($IMcommandlineBaseCacheFilename)) !== false) { |
||
1637 | return $commandline; |
||
1638 | } |
||
1639 | |||
1640 | $commandline = (!is_null($this->config_imagemagick_path) ? $this->config_imagemagick_path : ''); |
||
1641 | |||
1642 | if ($this->config_imagemagick_path |
||
1643 | && ($this->config_imagemagick_path != $this->realPathSafe($this->config_imagemagick_path)) |
||
1644 | ) { |
||
1645 | if (@is_executable($this->realPathSafe($this->config_imagemagick_path))) { |
||
1646 | $this->DebugMessage('Changing $this->config_imagemagick_path (' |
||
1647 | . $this->config_imagemagick_path |
||
1648 | . ') to $this->realPathSafe($this->config_imagemagick_path) (' |
||
1649 | . $this->realPathSafe($this->config_imagemagick_path) |
||
1650 | . ')', __FILE__, __LINE__); |
||
1651 | $this->config_imagemagick_path = $this->realPathSafe($this->config_imagemagick_path); |
||
1652 | } else { |
||
1653 | $this->DebugMessage('Leaving $this->config_imagemagick_path as (' |
||
1654 | . $this->config_imagemagick_path |
||
1655 | . ') because !is_execuatable($this->realPathSafe($this->config_imagemagick_path)) (' |
||
1656 | . $this->realPathSafe($this->config_imagemagick_path) |
||
1657 | . ')', __FILE__, __LINE__); |
||
1658 | } |
||
1659 | } |
||
1660 | $this->DebugMessage(' file_exists(' . $this->config_imagemagick_path . ') = ' . (int)(@file_exists($this->config_imagemagick_path)), __FILE__, __LINE__); |
||
1661 | $this->DebugMessage('file_exists_ignoreopenbasedir(' . $this->config_imagemagick_path . ') = ' . (int)$this->file_exists_ignoreopenbasedir($this->config_imagemagick_path), __FILE__, |
||
1662 | __LINE__); |
||
1663 | $this->DebugMessage(' is_file(' . $this->config_imagemagick_path . ') = ' . (int)(@is_file($this->config_imagemagick_path)), __FILE__, __LINE__); |
||
1664 | $this->DebugMessage(' is_executable(' . $this->config_imagemagick_path . ') = ' . (int)(@is_executable($this->config_imagemagick_path)), __FILE__, __LINE__); |
||
1665 | |||
1666 | if ($this->file_exists_ignoreopenbasedir($this->config_imagemagick_path)) { |
||
1667 | $this->DebugMessage('using ImageMagick path from $this->config_imagemagick_path (' . $this->config_imagemagick_path . ')', __FILE__, __LINE__); |
||
1668 | if ($this->iswindows) { |
||
1669 | $commandline = substr($this->config_imagemagick_path, 0, 2) |
||
1670 | . ' && cd ' |
||
1671 | . phpthumb_functions::escapeshellarg_replacement(str_replace('/', DIRECTORY_SEPARATOR, substr(dirname($this->config_imagemagick_path), 2))) |
||
1672 | . ' && ' |
||
1673 | . phpthumb_functions::escapeshellarg_replacement(basename($this->config_imagemagick_path)); |
||
1674 | } else { |
||
1675 | $commandline = phpthumb_functions::escapeshellarg_replacement($this->config_imagemagick_path); |
||
1676 | } |
||
1677 | } else { |
||
1678 | $which_convert = $this->ImageMagickWhichConvert(); |
||
1679 | $IMversion = $this->ImageMagickVersion(); |
||
1680 | |||
1681 | if ($which_convert && ($which_convert{0} == '/') |
||
1682 | && $this->file_exists_ignoreopenbasedir($which_convert) |
||
1683 | ) { |
||
1684 | |||
1685 | // `which convert` *should* return the path if "convert" exist, or nothing if it doesn't |
||
1686 | // other things *may* get returned, like "sh: convert: not found" or "no convert in /usr/local/bin /usr/sbin /usr/bin /usr/ccs/bin" |
||
1687 | // so only do this if the value returned exists as a file |
||
1688 | $this->DebugMessage('using ImageMagick path from `which convert` (' . $which_convert . ')', __FILE__, __LINE__); |
||
1689 | $commandline = 'convert'; |
||
1690 | } elseif ($IMversion) { |
||
1691 | $this->DebugMessage('setting ImageMagick path to $this->config_imagemagick_path (' . $this->config_imagemagick_path . ') [' . $IMversion . ']', __FILE__, __LINE__); |
||
1692 | $commandline = $this->config_imagemagick_path; |
||
1693 | } else { |
||
1694 | $this->DebugMessage('ImageMagickThumbnailToGD() aborting because cannot find convert in $this->config_imagemagick_path (' |
||
1695 | . $this->config_imagemagick_path |
||
1696 | . '), and `which convert` returned (' |
||
1697 | . $which_convert |
||
1698 | . ')', __FILE__, __LINE__); |
||
1699 | $commandline = ''; |
||
1700 | } |
||
1701 | } |
||
1702 | |||
1703 | @file_put_contents($IMcommandlineBaseCacheFilename, $commandline); |
||
0 ignored issues
–
show
It seems like you do not handle an error condition here. This can introduce security issues, and is generally not recommended.
If you suppress an error, we recommend checking for the error condition explicitly: // For example instead of
@mkdir($dir);
// Better use
if (@mkdir($dir) === false) {
throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
![]() |
|||
1704 | } |
||
1705 | |||
1706 | return $commandline; |
||
1707 | } |
||
1708 | |||
1709 | /** |
||
1710 | * @param bool $returnRAW |
||
1711 | * @return mixed |
||
1712 | */ |
||
1713 | public function ImageMagickVersion($returnRAW = false) |
||
1714 | { |
||
1715 | static $versionstring = null; |
||
1716 | if (is_null($versionstring)) { |
||
1717 | $versionstring = array(0 => false, 1 => false); |
||
1718 | |||
1719 | $IMversionCacheFilename = $this->config_cache_directory . DIRECTORY_SEPARATOR . 'phpThumbCacheIMversion.txt'; |
||
1720 | if ($cachedversionstring = @file_get_contents($IMversionCacheFilename)) { |
||
1721 | $versionstring = explode("\n", $cachedversionstring, 2); |
||
1722 | $versionstring[0] = ($versionstring[0] ?: false); // "false" is stored as an empty string in the cache file |
||
1723 | $versionstring[1] = ($versionstring[1] ?: false); // "false" is stored as an empty string in the cache file |
||
1724 | } else { |
||
1725 | $commandline = $this->ImageMagickCommandlineBase(); |
||
1726 | $commandline = (!is_null($commandline) ? $commandline : ''); |
||
1727 | if ($commandline) { |
||
1728 | $commandline .= ' --version'; |
||
1729 | $this->DebugMessage('ImageMagick version checked with "' . $commandline . '"', __FILE__, __LINE__); |
||
1730 | $versionstring[1] = trim(phpthumb_functions::SafeExec($commandline)); |
||
1731 | if (preg_match('#^Version: [^0-9]*([ 0-9\\.\\:Q/\\-]+)#i', $versionstring[1], $matches)) { |
||
1732 | $versionstring[0] = trim($matches[1]); |
||
1733 | } else { |
||
1734 | $versionstring[0] = false; |
||
1735 | $this->DebugMessage('ImageMagick did not return recognized version string (' . $versionstring[1] . ')', __FILE__, __LINE__); |
||
1736 | } |
||
1737 | $this->DebugMessage('ImageMagick convert --version says "' . @$matches[0] . '"', __FILE__, __LINE__); |
||
1738 | } |
||
1739 | |||
1740 | @file_put_contents($IMversionCacheFilename, $versionstring[0] . "\n" . $versionstring[1]); |
||
0 ignored issues
–
show
It seems like you do not handle an error condition here. This can introduce security issues, and is generally not recommended.
If you suppress an error, we recommend checking for the error condition explicitly: // For example instead of
@mkdir($dir);
// Better use
if (@mkdir($dir) === false) {
throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
![]() |
|||
1741 | } |
||
1742 | } |
||
1743 | |||
1744 | return $versionstring[(int)$returnRAW]; |
||
1745 | } |
||
1746 | |||
1747 | /** |
||
1748 | * @param $switchname |
||
1749 | * @return bool |
||
1750 | */ |
||
1751 | public function ImageMagickSwitchAvailable($switchname) |
||
1752 | { |
||
1753 | static $IMoptions = null; |
||
1754 | if (is_null($IMoptions)) { |
||
1755 | $IMoptions = array(); |
||
1756 | $commandline = $this->ImageMagickCommandlineBase(); |
||
1757 | if (!is_null($commandline)) { |
||
1758 | $commandline .= ' -help'; |
||
1759 | $IMhelp_lines = explode("\n", phpthumb_functions::SafeExec($commandline)); |
||
1760 | foreach ($IMhelp_lines as $line) { |
||
1761 | if (preg_match('#^[\\+\\-]([a-z\\-]+) #', trim($line), $matches)) { |
||
1762 | $IMoptions[$matches[1]] = true; |
||
1763 | } |
||
1764 | } |
||
1765 | } |
||
1766 | } |
||
1767 | if (is_array($switchname)) { |
||
1768 | $allOK = true; |
||
1769 | foreach ($switchname as $key => $value) { |
||
1770 | if (!isset($IMoptions[$value])) { |
||
1771 | $allOK = false; |
||
1772 | break; |
||
1773 | } |
||
1774 | } |
||
1775 | $this->DebugMessage('ImageMagickSwitchAvailable(' . implode(';', $switchname) . ') = ' . (int)$allOK . '', __FILE__, __LINE__); |
||
1776 | } else { |
||
1777 | $allOK = isset($IMoptions[$switchname]); |
||
1778 | $this->DebugMessage('ImageMagickSwitchAvailable(' . $switchname . ') = ' . (int)$allOK . '', __FILE__, __LINE__); |
||
1779 | } |
||
1780 | |||
1781 | return $allOK; |
||
1782 | } |
||
1783 | |||
1784 | /** |
||
1785 | * @return bool|null|string |
||
1786 | */ |
||
1787 | public function ImageMagickFormatsList() |
||
1788 | { |
||
1789 | static $IMformatsList = null; |
||
1790 | if (is_null($IMformatsList)) { |
||
1791 | $IMformatsList = ''; |
||
1792 | $commandline = $this->ImageMagickCommandlineBase(); |
||
1793 | if (!is_null($commandline)) { |
||
1794 | $commandline = dirname($commandline) . DIRECTORY_SEPARATOR . str_replace('convert', 'identify', basename($commandline)); |
||
1795 | $commandline .= ' -list format'; |
||
1796 | $IMformatsList = phpthumb_functions::SafeExec($commandline); |
||
1797 | } |
||
1798 | } |
||
1799 | |||
1800 | return $IMformatsList; |
||
1801 | } |
||
1802 | |||
1803 | /** |
||
1804 | * @return bool |
||
1805 | */ |
||
1806 | public function SourceDataToTempFile() |
||
1807 | { |
||
1808 | if ($IMtempSourceFilename = $this->phpThumb_tempnam()) { |
||
1809 | $IMtempSourceFilename = $this->realPathSafe($IMtempSourceFilename); |
||
1810 | ob_start(); |
||
1811 | $fp_tempfile = fopen($IMtempSourceFilename, 'wb'); |
||
1812 | $tempfile_open_error = ob_get_contents(); |
||
1813 | ob_end_clean(); |
||
1814 | if ($fp_tempfile) { |
||
1815 | fwrite($fp_tempfile, $this->rawImageData); |
||
1816 | fclose($fp_tempfile); |
||
1817 | $this->sourceFilename = $IMtempSourceFilename; |
||
1818 | $this->DebugMessage('ImageMagickThumbnailToGD() setting $this->sourceFilename to "' . $IMtempSourceFilename . '" from $this->rawImageData (' . strlen($this->rawImageData) . ' bytes)', |
||
1819 | __FILE__, __LINE__); |
||
1820 | } else { |
||
1821 | $this->DebugMessage('ImageMagickThumbnailToGD() FAILED setting $this->sourceFilename to "' . $IMtempSourceFilename . '" (failed to open for writing: "' . $tempfile_open_error . '")', |
||
1822 | __FILE__, __LINE__); |
||
1823 | } |
||
1824 | unset($tempfile_open_error, $IMtempSourceFilename); |
||
1825 | |||
1826 | return true; |
||
1827 | } |
||
1828 | $this->DebugMessage('SourceDataToTempFile() FAILED because $this->phpThumb_tempnam() failed', __FILE__, __LINE__); |
||
1829 | |||
1830 | return false; |
||
1831 | } |
||
1832 | |||
1833 | /** |
||
1834 | * @return bool |
||
1835 | */ |
||
1836 | public function ImageMagickThumbnailToGD() |
||
1837 | { |
||
1838 | // http://www.imagemagick.org/script/command-line-options.php |
||
1839 | |||
1840 | $this->useRawIMoutput = true; |
||
1841 | if (phpthumb_functions::gd_version()) { |
||
1842 | // if GD is not available, must use whatever ImageMagick can output |
||
1843 | |||
1844 | // $UnAllowedParameters contains options that can only be processed in GD, not ImageMagick |
||
1845 | // note: 'fltr' *may* need to be processed by GD, but we'll check that in more detail below |
||
1846 | $UnAllowedParameters = array('xto', 'ar', 'bg', 'bc'); |
||
1847 | // 'ra' may be part of this list, if not a multiple of 90 degrees |
||
1848 | foreach ($UnAllowedParameters as $parameter) { |
||
1849 | if (isset($this->$parameter)) { |
||
1850 | $this->DebugMessage('$this->useRawIMoutput=false because "' . $parameter . '" is set', __FILE__, __LINE__); |
||
1851 | $this->useRawIMoutput = false; |
||
1852 | break; |
||
1853 | } |
||
1854 | } |
||
1855 | } |
||
1856 | $this->DebugMessage('$this->useRawIMoutput=' . ($this->useRawIMoutput ? 'true' : 'false') . ' after checking $UnAllowedParameters', __FILE__, __LINE__); |
||
1857 | $outputFormat = $this->thumbnailFormat; |
||
1858 | if (phpthumb_functions::gd_version()) { |
||
1859 | if ($this->useRawIMoutput) { |
||
1860 | switch ($this->thumbnailFormat) { |
||
1861 | case 'gif': |
||
1862 | $ImageCreateFunction = 'ImageCreateFromGIF'; |
||
1863 | $this->is_alpha = true; |
||
1864 | break; |
||
1865 | case 'png': |
||
1866 | $ImageCreateFunction = 'ImageCreateFromPNG'; |
||
1867 | $this->is_alpha = true; |
||
1868 | break; |
||
1869 | case 'jpg': |
||
1870 | case 'jpeg': |
||
1871 | $ImageCreateFunction = 'ImageCreateFromJPEG'; |
||
1872 | break; |
||
1873 | default: |
||
1874 | $this->DebugMessage('Forcing output to PNG because $this->thumbnailFormat (' . $this->thumbnailFormat . ' is not a GD-supported format)', __FILE__, __LINE__); |
||
1875 | $outputFormat = 'png'; |
||
1876 | $ImageCreateFunction = 'ImageCreateFromPNG'; |
||
1877 | $this->is_alpha = true; |
||
1878 | $this->useRawIMoutput = false; |
||
1879 | break; |
||
1880 | } |
||
1881 | if (!function_exists(@$ImageCreateFunction)) { |
||
1882 | // ImageMagickThumbnailToGD() depends on ImageCreateFromPNG/ImageCreateFromGIF |
||
1883 | //$this->DebugMessage('ImageMagickThumbnailToGD() aborting because '.@$ImageCreateFunction.'() is not available', __FILE__, __LINE__); |
||
1884 | $this->useRawIMoutput = true; |
||
1885 | //return false; |
||
1886 | } |
||
1887 | } else { |
||
1888 | $outputFormat = 'png'; |
||
1889 | $ImageCreateFunction = 'ImageCreateFromPNG'; |
||
1890 | $this->is_alpha = true; |
||
1891 | $this->useRawIMoutput = false; |
||
1892 | } |
||
1893 | } |
||
1894 | |||
1895 | // http://freealter.org/doc_distrib/ImageMagick-5.1.1/www/convert.html |
||
1896 | if (!$this->sourceFilename && $this->rawImageData) { |
||
1897 | $this->SourceDataToTempFile(); |
||
1898 | } |
||
1899 | if (!$this->sourceFilename) { |
||
1900 | $this->DebugMessage('ImageMagickThumbnailToGD() aborting because $this->sourceFilename is empty', __FILE__, __LINE__); |
||
1901 | $this->useRawIMoutput = false; |
||
1902 | |||
1903 | return false; |
||
1904 | } |
||
1905 | if ($this->issafemode) { |
||
1906 | $this->DebugMessage('ImageMagickThumbnailToGD() aborting because safe_mode is enabled', __FILE__, __LINE__); |
||
1907 | $this->useRawIMoutput = false; |
||
1908 | |||
1909 | return false; |
||
1910 | } |
||
1911 | // TO BE FIXED |
||
1912 | //if (true) { |
||
1913 | // $this->DebugMessage('ImageMagickThumbnailToGD() aborting it is broken right now', __FILE__, __LINE__); |
||
1914 | // $this->useRawIMoutput = false; |
||
1915 | // return false; |
||
1916 | //} |
||
1917 | |||
1918 | $commandline = $this->ImageMagickCommandlineBase(); |
||
1919 | if ($commandline) { |
||
1920 | if ($IMtempfilename = $this->phpThumb_tempnam()) { |
||
1921 | $IMtempfilename = $this->realPathSafe($IMtempfilename); |
||
1922 | |||
1923 | $IMuseExplicitImageOutputDimensions = false; |
||
1924 | if ($this->ImageMagickSwitchAvailable('thumbnail') && $this->config_imagemagick_use_thumbnail) { |
||
1925 | $IMresizeParameter = 'thumbnail'; |
||
1926 | } else { |
||
1927 | $IMresizeParameter = 'resize'; |
||
1928 | |||
1929 | // some (older? around 2002) versions of IM won't accept "-resize 100x" but require "-resize 100x100" |
||
1930 | $commandline_test = $this->ImageMagickCommandlineBase() . ' logo: -resize 1x ' . phpthumb_functions::escapeshellarg_replacement($IMtempfilename) . ' 2>&1'; |
||
1931 | $IMresult_test = phpthumb_functions::SafeExec($commandline_test); |
||
1932 | $IMuseExplicitImageOutputDimensions = preg_match('#image dimensions are zero#i', $IMresult_test); |
||
1933 | $this->DebugMessage('IMuseExplicitImageOutputDimensions = ' . (int)$IMuseExplicitImageOutputDimensions, __FILE__, __LINE__); |
||
1934 | if ($fp_im_temp = @fopen($IMtempfilename, 'wb')) { |
||
1935 | // erase temp image so ImageMagick logo doesn't get output if other processing fails |
||
1936 | fclose($fp_im_temp); |
||
1937 | } |
||
1938 | } |
||
1939 | |||
1940 | if (!is_null($this->dpi) && $this->ImageMagickSwitchAvailable('density')) { |
||
1941 | // for raster source formats only (WMF, PDF, etc) |
||
1942 | $commandline .= ' -density ' . phpthumb_functions::escapeshellarg_replacement($this->dpi); |
||
1943 | } |
||
1944 | ob_start(); |
||
1945 | $getimagesize = getimagesize($this->sourceFilename); |
||
1946 | $GetImageSizeError = ob_get_contents(); |
||
1947 | ob_end_clean(); |
||
1948 | if (is_array($getimagesize)) { |
||
1949 | $this->DebugMessage('GetImageSize(' . $this->sourceFilename . ') SUCCEEDED: ' . print_r($getimagesize, true), __FILE__, __LINE__); |
||
1950 | } else { |
||
1951 | $this->DebugMessage('GetImageSize(' . $this->sourceFilename . ') FAILED with error "' . $GetImageSizeError . '"', __FILE__, __LINE__); |
||
1952 | } |
||
1953 | if (is_array($getimagesize)) { |
||
1954 | $this->DebugMessage('GetImageSize(' . $this->sourceFilename . ') returned [w=' . $getimagesize[0] . ';h=' . $getimagesize[1] . ';f=' . $getimagesize[2] . ']', __FILE__, __LINE__); |
||
1955 | $this->source_width = $getimagesize[0]; |
||
1956 | $this->source_height = $getimagesize[1]; |
||
1957 | $this->DebugMessage('source dimensions set to ' . $this->source_width . 'x' . $this->source_height, __FILE__, __LINE__); |
||
1958 | $this->SetOrientationDependantWidthHeight(); |
||
1959 | |||
1960 | View Code Duplication | if (!preg_match('#(' . implode('|', $this->AlphaCapableFormats) . ')#i', $outputFormat)) { |
|
1961 | // not a transparency-capable format |
||
1962 | $commandline .= ' -background ' . phpthumb_functions::escapeshellarg_replacement('#' . ($this->bg ?: 'FFFFFF')); |
||
1963 | if ($getimagesize[2] == IMAGETYPE_GIF) { |
||
1964 | $commandline .= ' -flatten'; |
||
1965 | } |
||
1966 | } |
||
1967 | if ($getimagesize[2] == IMAGETYPE_GIF) { |
||
1968 | $commandline .= ' -coalesce'; // may be needed for animated GIFs |
||
1969 | } |
||
1970 | if ($this->source_width || $this->source_height) { |
||
1971 | if ($this->zc) { |
||
1972 | $borderThickness = 0; |
||
1973 | if (!empty($this->fltr)) { |
||
1974 | foreach ($this->fltr as $key => $value) { |
||
1975 | if (preg_match('#^bord\|([0-9]+)#', $value, $matches)) { |
||
1976 | $borderThickness = $matches[1]; |
||
1977 | break; |
||
1978 | } |
||
1979 | } |
||
1980 | } |
||
1981 | $wAll = (int)max($this->w, $this->wp, $this->wl, $this->ws) - (2 * $borderThickness); |
||
1982 | $hAll = (int)max($this->h, $this->hp, $this->hl, $this->hs) - (2 * $borderThickness); |
||
1983 | $imAR = $this->source_width / $this->source_height; |
||
1984 | $zcAR = (($wAll && $hAll) ? $wAll / $hAll : 1); |
||
1985 | $side = phpthumb_functions::nonempty_min($this->source_width, $this->source_height, max($wAll, $hAll)); |
||
1986 | $sideX = phpthumb_functions::nonempty_min($this->source_width, $wAll, round($hAll * $zcAR)); |
||
1987 | $sideY = phpthumb_functions::nonempty_min($this->source_height, $hAll, round($wAll / $zcAR)); |
||
1988 | |||
1989 | $thumbnailH = round(max($sideY, ($sideY * $zcAR) / $imAR)); |
||
1990 | $commandline .= ' -' . $IMresizeParameter . ' ' . phpthumb_functions::escapeshellarg_replacement(($IMuseExplicitImageOutputDimensions ? $thumbnailH : '') |
||
1991 | . 'x' |
||
1992 | . $thumbnailH); |
||
1993 | |||
1994 | switch (strtoupper($this->zc)) { |
||
1995 | case 'T': |
||
1996 | $commandline .= ' -gravity north'; |
||
1997 | break; |
||
1998 | case 'B': |
||
1999 | $commandline .= ' -gravity south'; |
||
2000 | break; |
||
2001 | case 'L': |
||
2002 | $commandline .= ' -gravity west'; |
||
2003 | break; |
||
2004 | case 'R': |
||
2005 | $commandline .= ' -gravity east'; |
||
2006 | break; |
||
2007 | case 'TL': |
||
2008 | $commandline .= ' -gravity northwest'; |
||
2009 | break; |
||
2010 | case 'TR': |
||
2011 | $commandline .= ' -gravity northeast'; |
||
2012 | break; |
||
2013 | case 'BL': |
||
2014 | $commandline .= ' -gravity southwest'; |
||
2015 | break; |
||
2016 | case 'BR': |
||
2017 | $commandline .= ' -gravity southeast'; |
||
2018 | break; |
||
2019 | case '1': |
||
2020 | case 'C': |
||
2021 | default: |
||
2022 | $commandline .= ' -gravity center'; |
||
2023 | break; |
||
2024 | } |
||
2025 | |||
2026 | if (($wAll > 0) && ($hAll > 0)) { |
||
2027 | $commandline .= ' -crop ' . phpthumb_functions::escapeshellarg_replacement($wAll . 'x' . $hAll . '+0+0'); |
||
2028 | } else { |
||
2029 | $commandline .= ' -crop ' . phpthumb_functions::escapeshellarg_replacement($side . 'x' . $side . '+0+0'); |
||
2030 | } |
||
2031 | if ($this->ImageMagickSwitchAvailable('repage')) { |
||
2032 | $commandline .= ' +repage'; |
||
2033 | } else { |
||
2034 | $this->DebugMessage('Skipping "+repage" because ImageMagick (v' . $this->ImageMagickVersion() . ') does not support it', __FILE__, __LINE__); |
||
2035 | } |
||
2036 | } elseif ($this->sw || $this->sh || $this->sx || $this->sy) { |
||
2037 | $crop_param = ''; |
||
2038 | $crop_param .= ($this->sw ? (($this->sw < 2) ? round($this->sw * $this->source_width) : $this->sw) : $this->source_width); |
||
2039 | $crop_param .= 'x' . ($this->sh ? (($this->sh < 2) ? round($this->sh * $this->source_height) : $this->sh) : $this->source_height); |
||
2040 | $crop_param .= '+' . (($this->sx < 2) ? round($this->sx * $this->source_width) : $this->sx); |
||
2041 | $crop_param .= '+' . (($this->sy < 2) ? round($this->sy * $this->source_height) : $this->sy); |
||
2042 | // TO BE FIXED |
||
2043 | // makes 1x1 output |
||
2044 | // 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 |
||
2045 | // '/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' |
||
2046 | $commandline .= ' -crop ' . phpthumb_functions::escapeshellarg_replacement($crop_param); |
||
2047 | |||
2048 | // this is broken for aoe=1, but unsure how to fix. Send advice to [email protected] |
||
2049 | if ($this->w || $this->h) { |
||
2050 | //if ($this->ImageMagickSwitchAvailable('repage')) { |
||
2051 | if (false) { |
||
2052 | // TO BE FIXED |
||
2053 | // newer versions of ImageMagick require -repage <geometry> |
||
2054 | $commandline .= ' -repage'; |
||
2055 | } else { |
||
2056 | $this->DebugMessage('Skipping "-repage" because ImageMagick (v' . $this->ImageMagickVersion() . ') does not support it', __FILE__, __LINE__); |
||
2057 | } |
||
2058 | View Code Duplication | if ($IMuseExplicitImageOutputDimensions) { |
|
2059 | if ($this->w && !$this->h) { |
||
2060 | $this->h = ceil($this->w / ($this->source_width / $this->source_height)); |
||
2061 | } elseif ($this->h && !$this->w) { |
||
2062 | $this->w = ceil($this->h * ($this->source_width / $this->source_height)); |
||
2063 | } |
||
2064 | } |
||
2065 | $commandline .= ' -' . $IMresizeParameter . ' ' . phpthumb_functions::escapeshellarg_replacement($this->w . 'x' . $this->h); |
||
2066 | } |
||
2067 | } else { |
||
2068 | if ($this->iar && ((int)$this->w > 0) && ((int)$this->h > 0)) { |
||
2069 | list($nw, $nh) = phpthumb_functions::TranslateWHbyAngle($this->w, $this->h, $this->ra); |
||
2070 | $nw = ((round($nw) != 0) ? round($nw) : ''); |
||
2071 | $nh = ((round($nh) != 0) ? round($nh) : ''); |
||
2072 | $commandline .= ' -' . $IMresizeParameter . ' ' . phpthumb_functions::escapeshellarg_replacement($nw . 'x' . $nh . '!'); |
||
2073 | } else { |
||
2074 | $this->w = ((($this->aoe || $this->far) |
||
2075 | && $this->w) ? $this->w : ($this->w ? phpthumb_functions::nonempty_min($this->w, $getimagesize[0]) : '')); |
||
2076 | $this->h = ((($this->aoe || $this->far) |
||
2077 | && $this->h) ? $this->h : ($this->h ? phpthumb_functions::nonempty_min($this->h, $getimagesize[1]) : '')); |
||
2078 | if ($this->w || $this->h) { |
||
2079 | View Code Duplication | if ($IMuseExplicitImageOutputDimensions) { |
|
2080 | if ($this->w && !$this->h) { |
||
2081 | $this->h = ceil($this->w / ($this->source_width / $this->source_height)); |
||
2082 | } elseif ($this->h && !$this->w) { |
||
2083 | $this->w = ceil($this->h * ($this->source_width / $this->source_height)); |
||
2084 | } |
||
2085 | } |
||
2086 | list($nw, $nh) = phpthumb_functions::TranslateWHbyAngle($this->w, $this->h, $this->ra); |
||
2087 | $nw = ((round($nw) != 0) ? round($nw) : ''); |
||
2088 | $nh = ((round($nh) != 0) ? round($nh) : ''); |
||
2089 | $commandline .= ' -' . $IMresizeParameter . ' ' . phpthumb_functions::escapeshellarg_replacement($nw . 'x' . $nh); |
||
2090 | } |
||
2091 | } |
||
2092 | } |
||
2093 | } |
||
2094 | } else { |
||
2095 | $this->DebugMessage('GetImageSize(' . $this->sourceFilename . ') failed', __FILE__, __LINE__); |
||
2096 | if ($this->w || $this->h) { |
||
2097 | $exactDimensionsBang = (($this->iar && ((int)$this->w > 0) |
||
2098 | && ((int)$this->h > 0)) ? '!' : ''); |
||
2099 | if ($IMuseExplicitImageOutputDimensions) { |
||
2100 | // unknown source aspect ratio, just put large number and hope IM figures it out |
||
2101 | $commandline .= ' -' . $IMresizeParameter . ' ' . phpthumb_functions::escapeshellarg_replacement(($this->w ?: '9999') |
||
2102 | . 'x' |
||
2103 | . ($this->h ? $this->h : '9999') |
||
2104 | . $exactDimensionsBang); |
||
2105 | } else { |
||
2106 | $commandline .= ' -' . $IMresizeParameter . ' ' . phpthumb_functions::escapeshellarg_replacement($this->w . 'x' . $this->h . $exactDimensionsBang); |
||
2107 | } |
||
2108 | } |
||
2109 | } |
||
2110 | |||
2111 | if ($this->ra) { |
||
2112 | $this->ra = (int)$this->ra; |
||
2113 | if ($this->ImageMagickSwitchAvailable('rotate')) { |
||
2114 | if (!preg_match('#(' . implode('|', $this->AlphaCapableFormats) . ')#i', $outputFormat) |
||
2115 | || phpthumb_functions::version_compare_replacement($this->ImageMagickVersion(), '6.3.7', '>=') |
||
2116 | ) { |
||
2117 | $this->DebugMessage('Using ImageMagick rotate', __FILE__, __LINE__); |
||
2118 | $commandline .= ' -rotate ' . phpthumb_functions::escapeshellarg_replacement($this->ra); |
||
2119 | if (($this->ra % 90) != 0) { |
||
2120 | View Code Duplication | if (preg_match('#(' . implode('|', $this->AlphaCapableFormats) . ')#i', $outputFormat)) { |
|
2121 | // alpha-capable format |
||
2122 | $commandline .= ' -background rgba(255,255,255,0)'; |
||
2123 | } else { |
||
2124 | $commandline .= ' -background ' . phpthumb_functions::escapeshellarg_replacement('#' . ($this->bg ?: 'FFFFFF')); |
||
2125 | } |
||
2126 | } |
||
2127 | $this->ra = 0; |
||
2128 | } else { |
||
2129 | $this->DebugMessage('Not using ImageMagick rotate because alpha background buggy before v6.3.7', __FILE__, __LINE__); |
||
2130 | } |
||
2131 | } else { |
||
2132 | $this->DebugMessage('Not using ImageMagick rotate because not supported', __FILE__, __LINE__); |
||
2133 | } |
||
2134 | } |
||
2135 | |||
2136 | $successfullyProcessedFilters = array(); |
||
2137 | foreach ($this->fltr as $filterkey => $filtercommand) { |
||
2138 | @list($command, $parameter) = explode('|', $filtercommand, 2); |
||
0 ignored issues
–
show
It seems like you do not handle an error condition here. This can introduce security issues, and is generally not recommended.
If you suppress an error, we recommend checking for the error condition explicitly: // For example instead of
@mkdir($dir);
// Better use
if (@mkdir($dir) === false) {
throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
![]() |
|||
2139 | switch ($command) { |
||
2140 | case 'brit': |
||
2141 | if ($this->ImageMagickSwitchAvailable('modulate')) { |
||
2142 | $commandline .= ' -modulate ' . phpthumb_functions::escapeshellarg_replacement((100 + (int)$parameter) . ',100,100'); |
||
2143 | $successfullyProcessedFilters[] = $filterkey; |
||
2144 | } |
||
2145 | break; |
||
2146 | |||
2147 | case 'cont': |
||
2148 | if ($this->ImageMagickSwitchAvailable('contrast')) { |
||
2149 | $contDiv10 = round((int)$parameter / 10); |
||
2150 | if ($contDiv10 > 0) { |
||
2151 | $contDiv10 = min($contDiv10, 100); |
||
2152 | for ($i = 0; $i < $contDiv10; $i++) { |
||
2153 | $commandline .= ' -contrast'; // increase contrast by 10% |
||
2154 | } |
||
2155 | } elseif ($contDiv10 < 0) { |
||
2156 | $contDiv10 = max($contDiv10, -100); |
||
2157 | for ($i = $contDiv10; $i < 0; $i++) { |
||
2158 | $commandline .= ' +contrast'; // decrease contrast by 10% |
||
2159 | } |
||
2160 | } else { |
||
2161 | // do nothing |
||
2162 | } |
||
2163 | $successfullyProcessedFilters[] = $filterkey; |
||
2164 | } |
||
2165 | break; |
||
2166 | |||
2167 | View Code Duplication | case 'ds': |
|
2168 | if ($this->ImageMagickSwitchAvailable(array('colorspace', 'modulate'))) { |
||
2169 | if ($parameter == 100) { |
||
2170 | $commandline .= ' -colorspace GRAY'; |
||
2171 | $commandline .= ' -modulate 100,0,100'; |
||
2172 | } else { |
||
2173 | $commandline .= ' -modulate ' . phpthumb_functions::escapeshellarg_replacement('100,' . (100 - (int)$parameter) . ',100'); |
||
2174 | } |
||
2175 | $successfullyProcessedFilters[] = $filterkey; |
||
2176 | } |
||
2177 | break; |
||
2178 | |||
2179 | View Code Duplication | case 'sat': |
|
2180 | if ($this->ImageMagickSwitchAvailable(array('colorspace', 'modulate'))) { |
||
2181 | if ($parameter == -100) { |
||
2182 | $commandline .= ' -colorspace GRAY'; |
||
2183 | $commandline .= ' -modulate 100,0,100'; |
||
2184 | } else { |
||
2185 | $commandline .= ' -modulate ' . phpthumb_functions::escapeshellarg_replacement('100,' . (100 + (int)$parameter) . ',100'); |
||
2186 | } |
||
2187 | $successfullyProcessedFilters[] = $filterkey; |
||
2188 | } |
||
2189 | break; |
||
2190 | |||
2191 | case 'gray': |
||
2192 | if ($this->ImageMagickSwitchAvailable(array('colorspace', 'modulate'))) { |
||
2193 | $commandline .= ' -colorspace GRAY'; |
||
2194 | $commandline .= ' -modulate 100,0,100'; |
||
2195 | $successfullyProcessedFilters[] = $filterkey; |
||
2196 | } |
||
2197 | break; |
||
2198 | |||
2199 | case 'clr': |
||
2200 | if ($this->ImageMagickSwitchAvailable(array('fill', 'colorize'))) { |
||
2201 | @list($amount, $color) = explode('|', $parameter); |
||
0 ignored issues
–
show
It seems like you do not handle an error condition here. This can introduce security issues, and is generally not recommended.
If you suppress an error, we recommend checking for the error condition explicitly: // For example instead of
@mkdir($dir);
// Better use
if (@mkdir($dir) === false) {
throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
![]() |
|||
2202 | $commandline .= ' -fill ' . phpthumb_functions::escapeshellarg_replacement('#' . preg_replace('#[^0-9A-F]#i', '', $color)); |
||
2203 | $commandline .= ' -colorize ' . phpthumb_functions::escapeshellarg_replacement(min(max((int)$amount, 0), 100)); |
||
2204 | } |
||
2205 | break; |
||
2206 | |||
2207 | View Code Duplication | case 'sep': |
|
2208 | if ($this->ImageMagickSwitchAvailable('sepia-tone')) { |
||
2209 | @list($amount, $color) = explode('|', $parameter); |
||
0 ignored issues
–
show
It seems like you do not handle an error condition here. This can introduce security issues, and is generally not recommended.
If you suppress an error, we recommend checking for the error condition explicitly: // For example instead of
@mkdir($dir);
// Better use
if (@mkdir($dir) === false) {
throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
![]() |
|||
2210 | $amount = ($amount ?: 80); |
||
2211 | if (!$color) { |
||
2212 | $commandline .= ' -sepia-tone ' . phpthumb_functions::escapeshellarg_replacement(min(max((int)$amount, 0), 100) . '%'); |
||
2213 | $successfullyProcessedFilters[] = $filterkey; |
||
2214 | } |
||
2215 | } |
||
2216 | break; |
||
2217 | |||
2218 | View Code Duplication | case 'gam': |
|
2219 | @list($amount) = explode('|', $parameter); |
||
0 ignored issues
–
show
It seems like you do not handle an error condition here. This can introduce security issues, and is generally not recommended.
If you suppress an error, we recommend checking for the error condition explicitly: // For example instead of
@mkdir($dir);
// Better use
if (@mkdir($dir) === false) {
throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
![]() |
|||
2220 | $amount = min(max((float)$amount, 0.001), 10); |
||
2221 | if (number_format($amount, 3) != '1.000') { |
||
2222 | if ($this->ImageMagickSwitchAvailable('gamma')) { |
||
2223 | $commandline .= ' -gamma ' . phpthumb_functions::escapeshellarg_replacement($amount); |
||
2224 | $successfullyProcessedFilters[] = $filterkey; |
||
2225 | } |
||
2226 | } |
||
2227 | break; |
||
2228 | |||
2229 | case 'neg': |
||
2230 | if ($this->ImageMagickSwitchAvailable('negate')) { |
||
2231 | $commandline .= ' -negate'; |
||
2232 | $successfullyProcessedFilters[] = $filterkey; |
||
2233 | } |
||
2234 | break; |
||
2235 | |||
2236 | case 'th': |
||
2237 | @list($amount) = explode('|', $parameter); |
||
0 ignored issues
–
show
It seems like you do not handle an error condition here. This can introduce security issues, and is generally not recommended.
If you suppress an error, we recommend checking for the error condition explicitly: // For example instead of
@mkdir($dir);
// Better use
if (@mkdir($dir) === false) {
throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
![]() |
|||
2238 | if ($this->ImageMagickSwitchAvailable(array('threshold', 'dither', 'monochrome'))) { |
||
2239 | $commandline .= ' -threshold ' . phpthumb_functions::escapeshellarg_replacement(round(min(max((int)$amount, 0), 255) / 2.55) . '%'); |
||
2240 | $commandline .= ' -dither'; |
||
2241 | $commandline .= ' -monochrome'; |
||
2242 | $successfullyProcessedFilters[] = $filterkey; |
||
2243 | } |
||
2244 | break; |
||
2245 | |||
2246 | case 'rcd': |
||
2247 | if ($this->ImageMagickSwitchAvailable(array('colors', 'dither'))) { |
||
2248 | @list($colors, $dither) = explode('|', $parameter); |
||
0 ignored issues
–
show
It seems like you do not handle an error condition here. This can introduce security issues, and is generally not recommended.
If you suppress an error, we recommend checking for the error condition explicitly: // For example instead of
@mkdir($dir);
// Better use
if (@mkdir($dir) === false) {
throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
![]() |
|||
2249 | $colors = ($colors ? (int)$colors : 256); |
||
2250 | $dither = ((strlen($dither) > 0) ? (bool)$dither : true); |
||
2251 | $commandline .= ' -colors ' . phpthumb_functions::escapeshellarg_replacement(max($colors, |
||
2252 | 8)); // ImageMagick will otherwise fail with "cannot quantize to fewer than 8 colors" |
||
2253 | $commandline .= ($dither ? ' -dither' : ' +dither'); |
||
2254 | $successfullyProcessedFilters[] = $filterkey; |
||
2255 | } |
||
2256 | break; |
||
2257 | |||
2258 | case 'flip': |
||
2259 | if ($this->ImageMagickSwitchAvailable(array('flip', 'flop'))) { |
||
2260 | if (strpos(strtolower($parameter), 'x') !== false) { |
||
2261 | $commandline .= ' -flop'; |
||
2262 | } |
||
2263 | if (strpos(strtolower($parameter), 'y') !== false) { |
||
2264 | $commandline .= ' -flip'; |
||
2265 | } |
||
2266 | $successfullyProcessedFilters[] = $filterkey; |
||
2267 | } |
||
2268 | break; |
||
2269 | |||
2270 | case 'edge': |
||
2271 | if ($this->ImageMagickSwitchAvailable('edge')) { |
||
2272 | $parameter = (!empty($parameter) ? $parameter : 2); |
||
2273 | $commandline .= ' -edge ' . phpthumb_functions::escapeshellarg_replacement(!empty($parameter) ? (int)$parameter : 1); |
||
2274 | $successfullyProcessedFilters[] = $filterkey; |
||
2275 | } |
||
2276 | break; |
||
2277 | |||
2278 | case 'emb': |
||
2279 | if ($this->ImageMagickSwitchAvailable(array('emboss', 'negate'))) { |
||
2280 | $parameter = (!empty($parameter) ? $parameter : 2); |
||
2281 | $commandline .= ' -emboss ' . phpthumb_functions::escapeshellarg_replacement((int)$parameter); |
||
2282 | if ($parameter < 2) { |
||
2283 | $commandline .= ' -negate'; // ImageMagick negates the image for some reason with '-emboss 1'; |
||
2284 | } |
||
2285 | $successfullyProcessedFilters[] = $filterkey; |
||
2286 | } |
||
2287 | break; |
||
2288 | |||
2289 | case 'lvl': |
||
2290 | @list($band, $method, $threshold) = explode('|', $parameter); |
||
0 ignored issues
–
show
It seems like you do not handle an error condition here. This can introduce security issues, and is generally not recommended.
If you suppress an error, we recommend checking for the error condition explicitly: // For example instead of
@mkdir($dir);
// Better use
if (@mkdir($dir) === false) {
throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
![]() |
|||
2291 | $band = ($band ? preg_replace('#[^RGBA\\*]#', '', strtoupper($band)) : '*'); |
||
2292 | $method = ((strlen($method) > 0) ? (int)$method : 2); |
||
2293 | $threshold = ((strlen($threshold) > 0) ? min(max((float)$threshold, 0), 100) : 0.1); |
||
2294 | |||
2295 | $band = preg_replace('#[^RGBA\\*]#', '', strtoupper($band)); |
||
2296 | |||
2297 | if (($method > 1) |
||
2298 | && !$this->ImageMagickSwitchAvailable(array( |
||
2299 | 'channel', |
||
2300 | 'contrast-stretch' |
||
2301 | )) |
||
2302 | ) { |
||
2303 | // Because ImageMagick processing happens before PHP-GD filters, and because some |
||
2304 | // clipping is involved in the "lvl" filter, if "lvl" happens before "wb" then the |
||
2305 | // "wb" filter will have (almost) no effect. Therefore, if "wb" is enabled then |
||
2306 | // force the "lvl" filter to be processed by GD, not ImageMagick. |
||
2307 | foreach ($this->fltr as $fltr_key => $fltr_value) { |
||
2308 | list($fltr_cmd) = explode('|', $fltr_value); |
||
2309 | if ($fltr_cmd == 'wb') { |
||
2310 | $this->DebugMessage('Setting "lvl" filter method to "0" (from "' . $method . '") because white-balance filter also enabled', __FILE__, __LINE__); |
||
2311 | $method = 0; |
||
2312 | } |
||
2313 | } |
||
2314 | } |
||
2315 | |||
2316 | switch ($method) { |
||
2317 | case 0: // internal RGB |
||
2318 | case 1: // internal grayscale |
||
2319 | break; |
||
2320 | case 2: // ImageMagick "contrast-stretch" |
||
2321 | if ($this->ImageMagickSwitchAvailable('contrast-stretch')) { |
||
2322 | if ($band != '*') { |
||
2323 | $commandline .= ' -channel ' . phpthumb_functions::escapeshellarg_replacement(strtoupper($band)); |
||
2324 | } |
||
2325 | $threshold = preg_replace('#[^0-9\\.]#', '', $threshold); // should be unneccesary, but just to be double-sure |
||
2326 | //$commandline .= ' -contrast-stretch '.phpthumb_functions::escapeshellarg_replacement($threshold.'%'); |
||
2327 | $commandline .= ' -contrast-stretch \'' . $threshold . '%\''; |
||
2328 | if ($band != '*') { |
||
2329 | $commandline .= ' +channel'; |
||
2330 | } |
||
2331 | $successfullyProcessedFilters[] = $filterkey; |
||
2332 | } |
||
2333 | break; |
||
2334 | case 3: // ImageMagick "normalize" |
||
2335 | if ($this->ImageMagickSwitchAvailable('normalize')) { |
||
2336 | if ($band != '*') { |
||
2337 | $commandline .= ' -channel ' . phpthumb_functions::escapeshellarg_replacement(strtoupper($band)); |
||
2338 | } |
||
2339 | $commandline .= ' -normalize'; |
||
2340 | if ($band != '*') { |
||
2341 | $commandline .= ' +channel'; |
||
2342 | } |
||
2343 | $successfullyProcessedFilters[] = $filterkey; |
||
2344 | } |
||
2345 | break; |
||
2346 | default: |
||
2347 | $this->DebugMessage('unsupported method (' . $method . ') for "lvl" filter', __FILE__, __LINE__); |
||
2348 | break; |
||
2349 | } |
||
2350 | if (isset($this->fltr[$filterkey]) && ($method > 1)) { |
||
2351 | $this->fltr[$filterkey] = $command . '|' . $band . '|0|' . $threshold; |
||
2352 | $this->DebugMessage('filter "lvl" remapped from method "' . $method . '" to method "0" because ImageMagick support is missing', __FILE__, __LINE__); |
||
2353 | } |
||
2354 | break; |
||
2355 | |||
2356 | case 'wb': |
||
2357 | if ($this->ImageMagickSwitchAvailable(array('channel', 'contrast-stretch'))) { |
||
2358 | @list($threshold) = explode('|', $parameter); |
||
0 ignored issues
–
show
It seems like you do not handle an error condition here. This can introduce security issues, and is generally not recommended.
If you suppress an error, we recommend checking for the error condition explicitly: // For example instead of
@mkdir($dir);
// Better use
if (@mkdir($dir) === false) {
throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
![]() |
|||
2359 | $threshold = (!empty($threshold) ? min(max((float)$threshold, 0), 100) : 0.1); |
||
2360 | $threshold = preg_replace('#[^0-9\\.]#', '', $threshold); // should be unneccesary, but just to be double-sure |
||
2361 | //$commandline .= ' -channel R -contrast-stretch '.phpthumb_functions::escapeshellarg_replacement($threshold.'%'); // doesn't work on Windows because most versions of PHP do not properly |
||
2362 | //$commandline .= ' -channel G -contrast-stretch '.phpthumb_functions::escapeshellarg_replacement($threshold.'%'); // escape special characters (such as %) and just replace them with spaces |
||
2363 | //$commandline .= ' -channel B -contrast-stretch '.phpthumb_functions::escapeshellarg_replacement($threshold.'%'); // https://bugs.php.net/bug.php?id=43261 |
||
2364 | $commandline .= ' -channel R -contrast-stretch \'' . $threshold . '%\''; |
||
2365 | $commandline .= ' -channel G -contrast-stretch \'' . $threshold . '%\''; |
||
2366 | $commandline .= ' -channel B -contrast-stretch \'' . $threshold . '%\''; |
||
2367 | $commandline .= ' +channel'; |
||
2368 | $successfullyProcessedFilters[] = $filterkey; |
||
2369 | } |
||
2370 | break; |
||
2371 | |||
2372 | View Code Duplication | case 'blur': |
|
2373 | if ($this->ImageMagickSwitchAvailable('blur')) { |
||
2374 | @list($radius) = explode('|', $parameter); |
||
0 ignored issues
–
show
It seems like you do not handle an error condition here. This can introduce security issues, and is generally not recommended.
If you suppress an error, we recommend checking for the error condition explicitly: // For example instead of
@mkdir($dir);
// Better use
if (@mkdir($dir) === false) {
throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
![]() |
|||
2375 | $radius = (!empty($radius) ? min(max((int)$radius, 0), 25) : 1); |
||
2376 | $commandline .= ' -blur ' . phpthumb_functions::escapeshellarg_replacement($radius); |
||
2377 | $successfullyProcessedFilters[] = $filterkey; |
||
2378 | } |
||
2379 | break; |
||
2380 | |||
2381 | case 'gblr': |
||
2382 | @list($radius) = explode('|', $parameter); |
||
0 ignored issues
–
show
It seems like you do not handle an error condition here. This can introduce security issues, and is generally not recommended.
If you suppress an error, we recommend checking for the error condition explicitly: // For example instead of
@mkdir($dir);
// Better use
if (@mkdir($dir) === false) {
throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
![]() |
|||
2383 | $radius = (!empty($radius) ? min(max((int)$radius, 0), 25) : 1); |
||
2384 | // "-gaussian" changed to "-gaussian-blur" sometime around 2009 |
||
2385 | if ($this->ImageMagickSwitchAvailable('gaussian-blur')) { |
||
2386 | $commandline .= ' -gaussian-blur ' . phpthumb_functions::escapeshellarg_replacement($radius); |
||
2387 | $successfullyProcessedFilters[] = $filterkey; |
||
2388 | } elseif ($this->ImageMagickSwitchAvailable('gaussian')) { |
||
2389 | $commandline .= ' -gaussian ' . phpthumb_functions::escapeshellarg_replacement($radius); |
||
2390 | $successfullyProcessedFilters[] = $filterkey; |
||
2391 | } |
||
2392 | break; |
||
2393 | |||
2394 | case 'usm': |
||
2395 | if ($this->ImageMagickSwitchAvailable('unsharp')) { |
||
2396 | @list($amount, $radius, $threshold) = explode('|', $parameter); |
||
0 ignored issues
–
show
It seems like you do not handle an error condition here. This can introduce security issues, and is generally not recommended.
If you suppress an error, we recommend checking for the error condition explicitly: // For example instead of
@mkdir($dir);
// Better use
if (@mkdir($dir) === false) {
throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
![]() |
|||
2397 | $amount = ($amount ? min(max((int)$radius, 0), 255) : 80); |
||
2398 | $radius = ($radius ? min(max((int)$radius, 0), 10) : 0.5); |
||
2399 | $threshold = (strlen($threshold) ? min(max((int)$radius, 0), 50) : 3); |
||
2400 | $commandline .= ' -unsharp ' . phpthumb_functions::escapeshellarg_replacement(number_format(($radius * 2) - 1, 2, '.', '') |
||
2401 | . 'x1+' |
||
2402 | . number_format($amount / 100, 2, '.', '') |
||
2403 | . '+' |
||
2404 | . number_format($threshold / 100, 2, '.', '')); |
||
2405 | $successfullyProcessedFilters[] = $filterkey; |
||
2406 | } |
||
2407 | break; |
||
2408 | |||
2409 | case 'bord': |
||
2410 | if ($this->ImageMagickSwitchAvailable(array( |
||
2411 | 'border', |
||
2412 | 'bordercolor', |
||
2413 | 'thumbnail', |
||
2414 | 'crop' |
||
2415 | )) |
||
2416 | ) { |
||
2417 | if (!$this->zc) { |
||
2418 | @list($width, $rX, $rY, $color) = explode('|', $parameter); |
||
0 ignored issues
–
show
It seems like you do not handle an error condition here. This can introduce security issues, and is generally not recommended.
If you suppress an error, we recommend checking for the error condition explicitly: // For example instead of
@mkdir($dir);
// Better use
if (@mkdir($dir) === false) {
throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
![]() |
|||
2419 | $width = (int)$width; |
||
2420 | $rX = (int)$rX; |
||
2421 | $rY = (int)$rY; |
||
2422 | if ($width && !$rX && !$rY) { |
||
2423 | if (!phpthumb_functions::IsHexColor($color)) { |
||
2424 | $color = ((!empty($this->bc) |
||
2425 | && phpthumb_functions::IsHexColor($this->bc)) ? $this->bc : '000000'); |
||
2426 | } |
||
2427 | $commandline .= ' -border ' . phpthumb_functions::escapeshellarg_replacement((int)$width); |
||
2428 | $commandline .= ' -bordercolor ' . phpthumb_functions::escapeshellarg_replacement('#' . $color); |
||
2429 | |||
2430 | if (preg_match('# \\-crop "([0-9]+)x([0-9]+)\\+0\\+0" #', $commandline, $matches)) { |
||
2431 | $commandline = str_replace(' -crop "' . $matches[1] . 'x' . $matches[2] . '+0+0" ', |
||
2432 | ' -crop ' . phpthumb_functions::escapeshellarg_replacement(($matches[1] - (2 * $width)) |
||
2433 | . 'x' |
||
2434 | . ($matches[2] - (2 * $width)) |
||
2435 | . '+0+0') . ' ', $commandline); |
||
2436 | } elseif (preg_match('# \\-' . $IMresizeParameter . ' "([0-9]+)x([0-9]+)" #', $commandline, $matches)) { |
||
2437 | $commandline = str_replace(' -' . $IMresizeParameter . ' "' . $matches[1] . 'x' . $matches[2] . '" ', |
||
2438 | ' -' . $IMresizeParameter . ' ' . phpthumb_functions::escapeshellarg_replacement(($matches[1] - (2 * $width)) |
||
2439 | . 'x' |
||
2440 | . ($matches[2] - (2 * $width))) . ' ', |
||
2441 | $commandline); |
||
2442 | } |
||
2443 | $successfullyProcessedFilters[] = $filterkey; |
||
2444 | } |
||
2445 | } |
||
2446 | } |
||
2447 | break; |
||
2448 | |||
2449 | case 'crop': |
||
2450 | break; |
||
2451 | |||
2452 | case 'sblr': |
||
2453 | break; |
||
2454 | |||
2455 | case 'mean': |
||
2456 | break; |
||
2457 | |||
2458 | case 'smth': |
||
2459 | break; |
||
2460 | |||
2461 | case 'bvl': |
||
2462 | break; |
||
2463 | |||
2464 | case 'wmi': |
||
2465 | break; |
||
2466 | |||
2467 | case 'wmt': |
||
2468 | break; |
||
2469 | |||
2470 | case 'over': |
||
2471 | break; |
||
2472 | |||
2473 | case 'hist': |
||
2474 | break; |
||
2475 | |||
2476 | case 'fram': |
||
2477 | break; |
||
2478 | |||
2479 | case 'drop': |
||
2480 | break; |
||
2481 | |||
2482 | case 'mask': |
||
2483 | break; |
||
2484 | |||
2485 | case 'elip': |
||
2486 | break; |
||
2487 | |||
2488 | case 'ric': |
||
2489 | break; |
||
2490 | |||
2491 | case 'stc': |
||
2492 | break; |
||
2493 | |||
2494 | case 'size': |
||
2495 | break; |
||
2496 | |||
2497 | default: |
||
2498 | $this->DebugMessage('Unknown $this->fltr[' . $filterkey . '] (' . $filtercommand . ') -- deleting filter command', __FILE__, __LINE__); |
||
2499 | $successfullyProcessedFilters[] = $filterkey; |
||
2500 | break; |
||
2501 | } |
||
2502 | if (!isset($this->fltr[$filterkey])) { |
||
2503 | $this->DebugMessage('Processed $this->fltr[' . $filterkey . '] (' . $filtercommand . ') with ImageMagick', __FILE__, __LINE__); |
||
2504 | } else { |
||
2505 | $this->DebugMessage('Skipping $this->fltr[' . $filterkey . '] (' . $filtercommand . ') with ImageMagick', __FILE__, __LINE__); |
||
2506 | } |
||
2507 | } |
||
2508 | $this->DebugMessage('Remaining $this->fltr after ImageMagick: (' . $this->phpThumbDebugVarDump($this->fltr) . ')', __FILE__, __LINE__); |
||
2509 | if (count($this->fltr) > 0) { |
||
2510 | $this->useRawIMoutput = false; |
||
2511 | } |
||
2512 | |||
2513 | if (preg_match('#jpe?g#i', $outputFormat) && $this->q) { |
||
2514 | if ($this->ImageMagickSwitchAvailable(array('quality', 'interlace'))) { |
||
2515 | $commandline .= ' -quality ' . phpthumb_functions::escapeshellarg_replacement($this->thumbnailQuality); |
||
2516 | if ($this->config_output_interlace) { |
||
2517 | // causes weird things with animated GIF... leave for JPEG only |
||
2518 | $commandline .= ' -interlace line '; // Use Line or Plane to create an interlaced PNG or GIF or progressive JPEG image |
||
2519 | } |
||
2520 | } |
||
2521 | } |
||
2522 | $commandline .= ' ' . phpthumb_functions::escapeshellarg_replacement(preg_replace('#[/\\\\]#', DIRECTORY_SEPARATOR, $this->sourceFilename) . (($outputFormat == 'gif') ? '' : '[' |
||
2523 | . (int)$this->sfn |
||
2524 | . ']')); // [0] means first frame of (GIF) animation, can be ignored |
||
2525 | $commandline .= ' ' . $outputFormat . ':' . phpthumb_functions::escapeshellarg_replacement($IMtempfilename); |
||
2526 | if (!$this->iswindows) { |
||
2527 | $commandline .= ' 2>&1'; |
||
2528 | } |
||
2529 | $this->DebugMessage('ImageMagick called as (' . $commandline . ')', __FILE__, __LINE__); |
||
2530 | $IMresult = phpthumb_functions::SafeExec($commandline); |
||
2531 | clearstatcache(); |
||
2532 | if (!@file_exists($IMtempfilename) || !@filesize($IMtempfilename)) { |
||
2533 | $this->FatalError('ImageMagick failed with message (' . trim($IMresult) . ')'); |
||
2534 | $this->DebugMessage('ImageMagick failed with message (' . trim($IMresult) . ')', __FILE__, __LINE__); |
||
2535 | if ($this->iswindows && !$IMresult) { |
||
2536 | $this->DebugMessage('Check to make sure that PHP has read+write permissions to "' . dirname($IMtempfilename) . '"', __FILE__, __LINE__); |
||
2537 | } |
||
2538 | } else { |
||
2539 | foreach ($successfullyProcessedFilters as $dummy => $filterkey) { |
||
2540 | unset($this->fltr[$filterkey]); |
||
2541 | } |
||
2542 | $this->IMresizedData = file_get_contents($IMtempfilename); |
||
2543 | $getimagesize_imresized = @getimagesize($IMtempfilename); |
||
2544 | $this->DebugMessage('GetImageSize(' |
||
2545 | . $IMtempfilename |
||
2546 | . ') returned [w=' |
||
2547 | . $getimagesize_imresized[0] |
||
2548 | . ';h=' |
||
2549 | . $getimagesize_imresized[1] |
||
2550 | . ';f=' |
||
2551 | . $getimagesize_imresized[2] |
||
2552 | . ']', __FILE__, __LINE__); |
||
2553 | if (($this->config_max_source_pixels > 0) |
||
2554 | && (($getimagesize_imresized[0] * $getimagesize_imresized[1]) > $this->config_max_source_pixels) |
||
2555 | ) { |
||
2556 | $this->DebugMessage('skipping ImageMagickThumbnailToGD::' |
||
2557 | . $ImageCreateFunction |
||
2558 | . '() because IM output is too large (' |
||
2559 | . $getimagesize_imresized[0] |
||
2560 | . 'x' |
||
2561 | . $getimagesize_imresized[0] |
||
2562 | . ' = ' |
||
2563 | . ($getimagesize_imresized[0] * $getimagesize_imresized[1]) |
||
2564 | . ' > ' |
||
2565 | . $this->config_max_source_pixels |
||
2566 | . ')', __FILE__, __LINE__); |
||
2567 | } elseif (function_exists(@$ImageCreateFunction) |
||
2568 | && ($this->gdimg_source = @$ImageCreateFunction($IMtempfilename)) |
||
2569 | ) { |
||
2570 | $this->source_width = imagesx($this->gdimg_source); |
||
2571 | $this->source_height = imagesy($this->gdimg_source); |
||
2572 | $this->DebugMessage('ImageMagickThumbnailToGD::' . $ImageCreateFunction . '() succeeded, $this->gdimg_source is now (' . $this->source_width . 'x' . $this->source_height . ')', |
||
2573 | __FILE__, __LINE__); |
||
2574 | $this->DebugMessage('ImageMagickThumbnailToGD() returning $this->IMresizedData (' . strlen($this->IMresizedData) . ' bytes)', __FILE__, __LINE__); |
||
2575 | } else { |
||
2576 | $this->useRawIMoutput = true; |
||
2577 | $this->DebugMessage('$this->useRawIMoutput set to TRUE because ' . @$ImageCreateFunction . '(' . $IMtempfilename . ') failed', __FILE__, __LINE__); |
||
2578 | } |
||
2579 | View Code Duplication | if (file_exists($IMtempfilename)) { |
|
2580 | $this->DebugMessage('deleting "' . $IMtempfilename . '"', __FILE__, __LINE__); |
||
2581 | @unlink($IMtempfilename); |
||
0 ignored issues
–
show
It seems like you do not handle an error condition here. This can introduce security issues, and is generally not recommended.
If you suppress an error, we recommend checking for the error condition explicitly: // For example instead of
@mkdir($dir);
// Better use
if (@mkdir($dir) === false) {
throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
![]() |
|||
2582 | } |
||
2583 | |||
2584 | return true; |
||
2585 | } |
||
2586 | View Code Duplication | if (file_exists($IMtempfilename)) { |
|
2587 | $this->DebugMessage('deleting "' . $IMtempfilename . '"', __FILE__, __LINE__); |
||
2588 | @unlink($IMtempfilename); |
||
0 ignored issues
–
show
It seems like you do not handle an error condition here. This can introduce security issues, and is generally not recommended.
If you suppress an error, we recommend checking for the error condition explicitly: // For example instead of
@mkdir($dir);
// Better use
if (@mkdir($dir) === false) {
throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
![]() |
|||
2589 | } |
||
2590 | } elseif ($this->issafemode) { |
||
2591 | $this->DebugMessage('ImageMagickThumbnailToGD() aborting because PHP safe_mode is enabled and phpThumb_tempnam() failed', __FILE__, __LINE__); |
||
2592 | $this->useRawIMoutput = false; |
||
2593 | } else { |
||
2594 | View Code Duplication | if (file_exists($IMtempfilename)) { |
|
2595 | $this->DebugMessage('deleting "' . $IMtempfilename . '"', __FILE__, __LINE__); |
||
2596 | @unlink($IMtempfilename); |
||
0 ignored issues
–
show
It seems like you do not handle an error condition here. This can introduce security issues, and is generally not recommended.
If you suppress an error, we recommend checking for the error condition explicitly: // For example instead of
@mkdir($dir);
// Better use
if (@mkdir($dir) === false) {
throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
![]() |
|||
2597 | } |
||
2598 | $this->DebugMessage('ImageMagickThumbnailToGD() aborting, phpThumb_tempnam() failed', __FILE__, __LINE__); |
||
2599 | } |
||
2600 | } else { |
||
2601 | $this->DebugMessage('ImageMagickThumbnailToGD() aborting because ImageMagickCommandlineBase() failed', __FILE__, __LINE__); |
||
2602 | } |
||
2603 | $this->useRawIMoutput = false; |
||
2604 | |||
2605 | return false; |
||
2606 | } |
||
2607 | |||
2608 | /** |
||
2609 | * @return bool |
||
2610 | */ |
||
2611 | public function Rotate() |
||
2612 | { |
||
2613 | if ($this->ra || $this->ar) { |
||
2614 | if (!function_exists('ImageRotate')) { |
||
2615 | $this->DebugMessage('!function_exists(ImageRotate)', __FILE__, __LINE__); |
||
2616 | |||
2617 | return false; |
||
2618 | } |
||
2619 | View Code Duplication | if (!require_once __DIR__ . '/phpthumb.filters.php') { |
|
2620 | $this->DebugMessage('Error including "' . __DIR__ . '/phpthumb.filters.php" which is required for applying filters (' . implode(';', $this->fltr) . ')', __FILE__, __LINE__); |
||
2621 | |||
2622 | return false; |
||
2623 | } |
||
2624 | |||
2625 | $this->config_background_hexcolor = ($this->bg ?: $this->config_background_hexcolor); |
||
2626 | if (!phpthumb_functions::IsHexColor($this->config_background_hexcolor)) { |
||
2627 | return $this->ErrorImage('Invalid hex color string "' . $this->config_background_hexcolor . '" for parameter "bg"'); |
||
2628 | } |
||
2629 | |||
2630 | $rotate_angle = 0; |
||
2631 | if ($this->ra) { |
||
2632 | $rotate_angle = (float)$this->ra; |
||
2633 | } else { |
||
2634 | if ($this->ar == 'x') { |
||
2635 | if (phpthumb_functions::version_compare_replacement(PHP_VERSION, '4.2.0', '>=')) { |
||
2636 | if ($this->sourceFilename) { |
||
2637 | if (function_exists('exif_read_data')) { |
||
2638 | if ($exif_data = @exif_read_data($this->sourceFilename, 'IFD0')) { |
||
2639 | // http://sylvana.net/jpegcrop/exif_orientation.html |
||
2640 | switch (@$exif_data['Orientation']) { |
||
2641 | case 1: |
||
2642 | $rotate_angle = 0; |
||
2643 | break; |
||
2644 | case 3: |
||
2645 | $rotate_angle = 180; |
||
2646 | break; |
||
2647 | case 6: |
||
2648 | $rotate_angle = 270; |
||
2649 | break; |
||
2650 | case 8: |
||
2651 | $rotate_angle = 90; |
||
2652 | break; |
||
2653 | |||
2654 | default: |
||
2655 | $this->DebugMessage('EXIF auto-rotate failed because unknown $exif_data[Orientation] "' . @$exif_data['Orientation'] . '"', __FILE__, __LINE__); |
||
2656 | |||
2657 | return false; |
||
2658 | break; |
||
2659 | } |
||
2660 | $this->DebugMessage('EXIF auto-rotate set to ' . $rotate_angle . ' degrees ($exif_data[Orientation] = "' . @$exif_data['Orientation'] . '")', __FILE__, __LINE__); |
||
2661 | } else { |
||
2662 | $this->DebugMessage('failed: exif_read_data(' . $this->sourceFilename . ')', __FILE__, __LINE__); |
||
2663 | |||
2664 | return false; |
||
2665 | } |
||
2666 | } else { |
||
2667 | $this->DebugMessage('!function_exists(exif_read_data)', __FILE__, __LINE__); |
||
2668 | |||
2669 | return false; |
||
2670 | } |
||
2671 | } else { |
||
2672 | $this->DebugMessage('Cannot auto-rotate from EXIF data because $this->sourceFilename is empty', __FILE__, __LINE__); |
||
2673 | |||
2674 | return false; |
||
2675 | } |
||
2676 | } else { |
||
2677 | $this->DebugMessage('Cannot auto-rotate from EXIF data because PHP is less than v4.2.0 (' . PHP_VERSION . ')', __FILE__, __LINE__); |
||
2678 | |||
2679 | return false; |
||
2680 | } |
||
2681 | } elseif (($this->ar == 'l') && ($this->source_height > $this->source_width)) { |
||
2682 | $rotate_angle = 270; |
||
2683 | } elseif (($this->ar == 'L') && ($this->source_height > $this->source_width)) { |
||
2684 | $rotate_angle = 90; |
||
2685 | } elseif (($this->ar == 'p') && ($this->source_width > $this->source_height)) { |
||
2686 | $rotate_angle = 90; |
||
2687 | } elseif (($this->ar == 'P') && ($this->source_width > $this->source_height)) { |
||
2688 | $rotate_angle = 270; |
||
2689 | } |
||
2690 | } |
||
2691 | if ($rotate_angle % 90) { |
||
2692 | $this->is_alpha = true; |
||
2693 | } |
||
2694 | phpthumb_filters::ImprovedImageRotate($this->gdimg_source, $rotate_angle, $this->config_background_hexcolor, $this->bg, $this); |
||
2695 | $this->source_width = imagesx($this->gdimg_source); |
||
2696 | $this->source_height = imagesy($this->gdimg_source); |
||
2697 | } |
||
2698 | |||
2699 | return true; |
||
2700 | } |
||
2701 | |||
2702 | /** |
||
2703 | * @return bool |
||
2704 | */ |
||
2705 | public function FixedAspectRatio() |
||
2706 | { |
||
2707 | // optional fixed-dimension images (regardless of aspect ratio) |
||
2708 | |||
2709 | if (!$this->far) { |
||
2710 | // do nothing |
||
2711 | return true; |
||
2712 | } |
||
2713 | |||
2714 | if (!$this->w || !$this->h) { |
||
2715 | return false; |
||
2716 | } |
||
2717 | $this->thumbnail_width = $this->w; |
||
2718 | $this->thumbnail_height = $this->h; |
||
2719 | $this->is_alpha = true; |
||
2720 | if ($this->thumbnail_image_width >= $this->thumbnail_width) { |
||
2721 | $aspectratio = $this->thumbnail_image_height / $this->thumbnail_image_width; |
||
2722 | View Code Duplication | if ($this->w) { |
|
2723 | $this->thumbnail_image_height = round($this->thumbnail_image_width * $aspectratio); |
||
2724 | $this->thumbnail_height = ($this->h ?: $this->thumbnail_image_height); |
||
2725 | } elseif ($this->thumbnail_image_height < $this->thumbnail_height) { |
||
2726 | $this->thumbnail_image_height = $this->thumbnail_height; |
||
2727 | $this->thumbnail_image_width = round($this->thumbnail_image_height / $aspectratio); |
||
2728 | } |
||
2729 | View Code Duplication | } else { |
|
2730 | $aspectratio = $this->thumbnail_image_width / $this->thumbnail_image_height; |
||
2731 | if ($this->h) { |
||
2732 | $this->thumbnail_image_width = round($this->thumbnail_image_height * $aspectratio); |
||
2733 | } elseif ($this->thumbnail_image_width < $this->thumbnail_width) { |
||
2734 | $this->thumbnail_image_width = $this->thumbnail_width; |
||
2735 | $this->thumbnail_image_height = round($this->thumbnail_image_width / $aspectratio); |
||
2736 | } |
||
2737 | } |
||
2738 | |||
2739 | return true; |
||
2740 | } |
||
2741 | |||
2742 | /** |
||
2743 | * @param $hostname |
||
2744 | * @param $allowed_domains |
||
2745 | * @return mixed |
||
2746 | */ |
||
2747 | public function OffsiteDomainIsAllowed($hostname, $allowed_domains) |
||
2748 | { |
||
2749 | static $domain_is_allowed = array(); |
||
2750 | $hostname = strtolower($hostname); |
||
2751 | if (!isset($domain_is_allowed[$hostname])) { |
||
2752 | $domain_is_allowed[$hostname] = false; |
||
2753 | foreach ($allowed_domains as $valid_domain) { |
||
2754 | $starpos = strpos($valid_domain, '*'); |
||
2755 | if ($starpos !== false) { |
||
2756 | $valid_domain = substr($valid_domain, $starpos + 1); |
||
2757 | if (preg_match('#' . preg_quote($valid_domain) . '$#', $hostname)) { |
||
2758 | $domain_is_allowed[$hostname] = true; |
||
2759 | break; |
||
2760 | } |
||
2761 | } else { |
||
2762 | if (strtolower($valid_domain) === $hostname) { |
||
2763 | $domain_is_allowed[$hostname] = true; |
||
2764 | break; |
||
2765 | } |
||
2766 | } |
||
2767 | } |
||
2768 | } |
||
2769 | |||
2770 | return $domain_is_allowed[$hostname]; |
||
2771 | } |
||
2772 | |||
2773 | /** |
||
2774 | * @return bool |
||
2775 | */ |
||
2776 | public function AntiOffsiteLinking() |
||
2777 | { |
||
2778 | // Optional anti-offsite hijacking of the thumbnail script |
||
2779 | $allow = true; |
||
2780 | if ($allow && $this->config_nooffsitelink_enabled |
||
2781 | && (@$_SERVER['HTTP_REFERER'] |
||
2782 | || $this->config_nooffsitelink_require_refer) |
||
2783 | ) { |
||
2784 | $this->DebugMessage('AntiOffsiteLinking() checking $_SERVER[HTTP_REFERER] "' . @$_SERVER['HTTP_REFERER'] . '"', __FILE__, __LINE__); |
||
2785 | foreach ($this->config_nooffsitelink_valid_domains as $key => $valid_domain) { |
||
2786 | // $_SERVER['HTTP_HOST'] contains the port number, so strip it out here to make default configuration work |
||
2787 | list($clean_domain) = explode(':', $valid_domain); |
||
2788 | $this->config_nooffsitelink_valid_domains[$key] = $clean_domain; |
||
2789 | } |
||
2790 | $parsed_url = phpthumb_functions::ParseURLbetter(@$_SERVER['HTTP_REFERER']); |
||
2791 | View Code Duplication | if (!$this->OffsiteDomainIsAllowed(@$parsed_url['host'], $this->config_nooffsitelink_valid_domains)) { |
|
2792 | $allow = false; |
||
2793 | $erase = $this->config_nooffsitelink_erase_image; |
||
2794 | $message = $this->config_nooffsitelink_text_message; |
||
2795 | //$this->DebugMessage('AntiOffsiteLinking() - "'.@$parsed_url['host'].'" is NOT in $this->config_nooffsitelink_valid_domains ('.implode(';', $this->config_nooffsitelink_valid_domains).')', __FILE__, __LINE__); |
||
2796 | $this->ErrorImage('AntiOffsiteLinking() - "' |
||
2797 | . @$parsed_url['host'] |
||
2798 | . '" is NOT in $this->config_nooffsitelink_valid_domains (' |
||
2799 | . implode(';', $this->config_nooffsitelink_valid_domains) |
||
2800 | . ')'); |
||
2801 | } else { |
||
2802 | $this->DebugMessage('AntiOffsiteLinking() - "' |
||
2803 | . @$parsed_url['host'] |
||
2804 | . '" is in $this->config_nooffsitelink_valid_domains (' |
||
2805 | . implode(';', $this->config_nooffsitelink_valid_domains) |
||
2806 | . ')', __FILE__, __LINE__); |
||
2807 | } |
||
2808 | } |
||
2809 | |||
2810 | if ($allow && $this->config_nohotlink_enabled && preg_match('#^(f|ht)tps?\://#i', $this->src)) { |
||
2811 | $parsed_url = phpthumb_functions::ParseURLbetter($this->src); |
||
2812 | //if (!phpthumb_functions::CaseInsensitiveInArray(@$parsed_url['host'], $this->config_nohotlink_valid_domains)) { |
||
2813 | View Code Duplication | if (!$this->OffsiteDomainIsAllowed(@$parsed_url['host'], $this->config_nohotlink_valid_domains)) { |
|
2814 | // This domain is not allowed |
||
2815 | $allow = false; |
||
2816 | $erase = $this->config_nohotlink_erase_image; |
||
2817 | $message = $this->config_nohotlink_text_message; |
||
2818 | $this->DebugMessage('AntiOffsiteLinking() - "' |
||
2819 | . $parsed_url['host'] |
||
2820 | . '" is NOT in $this->config_nohotlink_valid_domains (' |
||
2821 | . implode(';', $this->config_nohotlink_valid_domains) |
||
2822 | . ')', __FILE__, __LINE__); |
||
2823 | } else { |
||
2824 | $this->DebugMessage('AntiOffsiteLinking() - "' . $parsed_url['host'] . '" is in $this->config_nohotlink_valid_domains (' . implode(';', $this->config_nohotlink_valid_domains) . ')', |
||
2825 | __FILE__, __LINE__); |
||
2826 | } |
||
2827 | } |
||
2828 | |||
2829 | if ($allow) { |
||
2830 | $this->DebugMessage('AntiOffsiteLinking() says this is allowed', __FILE__, __LINE__); |
||
2831 | |||
2832 | return true; |
||
2833 | } |
||
2834 | |||
2835 | if (!phpthumb_functions::IsHexColor($this->config_error_bgcolor)) { |
||
2836 | return $this->ErrorImage('Invalid hex color string "' . $this->config_error_bgcolor . '" for $this->config_error_bgcolor'); |
||
2837 | } |
||
2838 | if (!phpthumb_functions::IsHexColor($this->config_error_textcolor)) { |
||
2839 | return $this->ErrorImage('Invalid hex color string "' . $this->config_error_textcolor . '" for $this->config_error_textcolor'); |
||
2840 | } |
||
2841 | if ($erase) { |
||
2842 | return $this->ErrorImage($message, $this->thumbnail_width, $this->thumbnail_height, $this->config_error_bgcolor, $this->config_error_textcolor, $this->config_error_fontsize); |
||
2843 | } else { |
||
2844 | $this->config_nooffsitelink_watermark_src = $this->ResolveFilenameToAbsolute($this->config_nooffsitelink_watermark_src); |
||
2845 | if (is_file($this->config_nooffsitelink_watermark_src)) { |
||
2846 | if (!require_once __DIR__ . '/phpthumb.filters.php') { |
||
2847 | $this->DebugMessage('Error including "' . __DIR__ . '/phpthumb.filters.php" which is required for applying watermark', __FILE__, __LINE__); |
||
2848 | |||
2849 | return false; |
||
2850 | } |
||
2851 | $watermark_img = $this->ImageCreateFromStringReplacement(file_get_contents($this->config_nooffsitelink_watermark_src)); |
||
2852 | $phpthumbFilters = new phpthumb_filters(); |
||
2853 | $phpthumbFilters->phpThumbObject = &$this; |
||
2854 | $opacity = 50; |
||
2855 | $margin = 5; |
||
2856 | $phpthumbFilters->WatermarkOverlay($this->gdimg_output, $watermark_img, '*', $opacity, $margin); |
||
2857 | imagedestroy($watermark_img); |
||
2858 | unset($phpthumbFilters); |
||
2859 | } else { |
||
2860 | $nohotlink_text_array = explode("\n", wordwrap($message, floor($this->thumbnail_width / imagefontwidth($this->config_error_fontsize)), "\n")); |
||
2861 | $nohotlink_text_color = phpthumb_functions::ImageHexColorAllocate($this->gdimg_output, $this->config_error_textcolor); |
||
2862 | |||
2863 | $topoffset = round(($this->thumbnail_height - (count($nohotlink_text_array) * imagefontheight($this->config_error_fontsize))) / 2); |
||
2864 | |||
2865 | $rowcounter = 0; |
||
2866 | $this->DebugMessage('AntiOffsiteLinking() writing ' . count($nohotlink_text_array) . ' lines of text "' . $message . '" (in #' . $this->config_error_textcolor . ') on top of image', |
||
2867 | __FILE__, __LINE__); |
||
2868 | foreach ($nohotlink_text_array as $textline) { |
||
2869 | $leftoffset = max(0, round(($this->thumbnail_width - (strlen($textline) * imagefontwidth($this->config_error_fontsize))) / 2)); |
||
2870 | imagestring($this->gdimg_output, $this->config_error_fontsize, $leftoffset, $topoffset + ($rowcounter++ * imagefontheight($this->config_error_fontsize)), $textline, |
||
2871 | $nohotlink_text_color); |
||
2872 | } |
||
2873 | } |
||
2874 | } |
||
2875 | |||
2876 | return true; |
||
2877 | } |
||
2878 | |||
2879 | /** |
||
2880 | * @return bool |
||
2881 | */ |
||
2882 | public function AlphaChannelFlatten() |
||
2883 | { |
||
2884 | if (!$this->is_alpha) { |
||
2885 | // image doesn't have alpha transparency, no need to flatten |
||
2886 | $this->DebugMessage('skipping AlphaChannelFlatten() because !$this->is_alpha', __FILE__, __LINE__); |
||
2887 | |||
2888 | return false; |
||
2889 | } |
||
2890 | switch ($this->thumbnailFormat) { |
||
2891 | case 'png': |
||
2892 | View Code Duplication | case 'ico': |
|
2893 | // image has alpha transparency, but output as PNG or ICO which can handle it |
||
2894 | $this->DebugMessage('skipping AlphaChannelFlatten() because ($this->thumbnailFormat == "' . $this->thumbnailFormat . '")', __FILE__, __LINE__); |
||
2895 | |||
2896 | return false; |
||
2897 | break; |
||
2898 | |||
2899 | case 'gif': |
||
2900 | // image has alpha transparency, but output as GIF which can handle only single-color transparency |
||
2901 | $CurrentImageColorTransparent = imagecolortransparent($this->gdimg_output); |
||
2902 | if ($CurrentImageColorTransparent == -1) { |
||
2903 | // no transparent color defined |
||
2904 | |||
2905 | if (phpthumb_functions::gd_version() < 2.0) { |
||
2906 | $this->DebugMessage('AlphaChannelFlatten() failed because GD version is "' . phpthumb_functions::gd_version() . '"', __FILE__, __LINE__); |
||
2907 | |||
2908 | return false; |
||
2909 | } |
||
2910 | |||
2911 | if ($img_alpha_mixdown_dither = @imagecreatetruecolor(imagesx($this->gdimg_output), imagesy($this->gdimg_output))) { |
||
2912 | for ($i = 0; $i <= 255; $i++) { |
||
2913 | $dither_color[$i] = imagecolorallocate($img_alpha_mixdown_dither, $i, $i, $i); |
||
2914 | } |
||
2915 | |||
2916 | // scan through current truecolor image copy alpha channel to temp image as grayscale |
||
2917 | View Code Duplication | for ($x = 0; $x < $this->thumbnail_width; $x++) { |
|
2918 | for ($y = 0; $y < $this->thumbnail_height; $y++) { |
||
2919 | $PixelColor = phpthumb_functions::GetPixelColor($this->gdimg_output, $x, $y); |
||
2920 | imagesetpixel($img_alpha_mixdown_dither, $x, $y, $dither_color[$PixelColor['alpha'] * 2]); |
||
2921 | } |
||
2922 | } |
||
2923 | |||
2924 | // dither alpha channel grayscale version down to 2 colors |
||
2925 | imagetruecolortopalette($img_alpha_mixdown_dither, true, 2); |
||
2926 | |||
2927 | // reduce color palette to 256-1 colors (leave one palette position for transparent color) |
||
2928 | imagetruecolortopalette($this->gdimg_output, true, 255); |
||
2929 | |||
2930 | // allocate a new color for transparent color index |
||
2931 | $TransparentColor = imagecolorallocate($this->gdimg_output, 1, 254, 253); |
||
2932 | imagecolortransparent($this->gdimg_output, $TransparentColor); |
||
2933 | |||
2934 | // scan through alpha channel image and note pixels with >50% transparency |
||
2935 | $TransparentPixels = array(); |
||
2936 | View Code Duplication | for ($x = 0; $x < $this->thumbnail_width; $x++) { |
|
2937 | for ($y = 0; $y < $this->thumbnail_height; $y++) { |
||
2938 | $AlphaChannelPixel = phpthumb_functions::GetPixelColor($img_alpha_mixdown_dither, $x, $y); |
||
2939 | if ($AlphaChannelPixel['red'] > 127) { |
||
2940 | imagesetpixel($this->gdimg_output, $x, $y, $TransparentColor); |
||
2941 | } |
||
2942 | } |
||
2943 | } |
||
2944 | imagedestroy($img_alpha_mixdown_dither); |
||
2945 | |||
2946 | $this->DebugMessage('AlphaChannelFlatten() set image to 255+1 colors with transparency for GIF output', __FILE__, __LINE__); |
||
2947 | |||
2948 | return true; |
||
2949 | View Code Duplication | } else { |
|
2950 | $this->DebugMessage('AlphaChannelFlatten() failed ImageCreate(' . imagesx($this->gdimg_output) . ', ' . imagesy($this->gdimg_output) . ')', __FILE__, __LINE__); |
||
2951 | |||
2952 | return false; |
||
2953 | } |
||
2954 | } else { |
||
2955 | // a single transparent color already defined, leave as-is |
||
2956 | $this->DebugMessage('skipping AlphaChannelFlatten() because ($this->thumbnailFormat == "' |
||
2957 | . $this->thumbnailFormat |
||
2958 | . '") and ImageColorTransparent returned "' |
||
2959 | . $CurrentImageColorTransparent |
||
2960 | . '"', __FILE__, __LINE__); |
||
2961 | |||
2962 | return true; |
||
2963 | } |
||
2964 | break; |
||
2965 | } |
||
2966 | $this->DebugMessage('continuing AlphaChannelFlatten() for output format "' . $this->thumbnailFormat . '"', __FILE__, __LINE__); |
||
2967 | // image has alpha transparency, and is being output in a format that doesn't support it -- flatten |
||
2968 | if ($gdimg_flatten_temp = phpthumb_functions::ImageCreateFunction($this->thumbnail_width, $this->thumbnail_height)) { |
||
2969 | $this->config_background_hexcolor = ($this->bg ?: $this->config_background_hexcolor); |
||
2970 | if (!phpthumb_functions::IsHexColor($this->config_background_hexcolor)) { |
||
2971 | return $this->ErrorImage('Invalid hex color string "' . $this->config_background_hexcolor . '" for parameter "bg"'); |
||
2972 | } |
||
2973 | $background_color = phpthumb_functions::ImageHexColorAllocate($this->gdimg_output, $this->config_background_hexcolor); |
||
2974 | imagefilledrectangle($gdimg_flatten_temp, 0, 0, $this->thumbnail_width, $this->thumbnail_height, $background_color); |
||
2975 | imagecopy($gdimg_flatten_temp, $this->gdimg_output, 0, 0, 0, 0, $this->thumbnail_width, $this->thumbnail_height); |
||
2976 | |||
2977 | ImageAlphaBlending($this->gdimg_output, true); |
||
2978 | ImageSaveAlpha($this->gdimg_output, false); |
||
2979 | imagecolortransparent($this->gdimg_output, -1); |
||
2980 | imagecopy($this->gdimg_output, $gdimg_flatten_temp, 0, 0, 0, 0, $this->thumbnail_width, $this->thumbnail_height); |
||
2981 | |||
2982 | imagedestroy($gdimg_flatten_temp); |
||
2983 | |||
2984 | return true; |
||
2985 | } else { |
||
2986 | $this->DebugMessage('ImageCreateFunction() failed', __FILE__, __LINE__); |
||
2987 | } |
||
2988 | |||
2989 | return false; |
||
2990 | } |
||
2991 | |||
2992 | /** |
||
2993 | * @return bool |
||
2994 | */ |
||
2995 | public function ApplyFilters() |
||
2996 | { |
||
2997 | if ($this->fltr && is_array($this->fltr)) { |
||
2998 | View Code Duplication | if (!require_once __DIR__ . '/phpthumb.filters.php') { |
|
2999 | $this->DebugMessage('Error including "' . __DIR__ . '/phpthumb.filters.php" which is required for applying filters (' . implode(';', $this->fltr) . ')', __FILE__, __LINE__); |
||
3000 | |||
3001 | return false; |
||
3002 | } |
||
3003 | $phpthumbFilters = new phpthumb_filters(); |
||
3004 | $phpthumbFilters->phpThumbObject = &$this; |
||
3005 | foreach ($this->fltr as $filtercommand) { |
||
3006 | @list($command, $parameter) = explode('|', $filtercommand, 2); |
||
0 ignored issues
–
show
It seems like you do not handle an error condition here. This can introduce security issues, and is generally not recommended.
If you suppress an error, we recommend checking for the error condition explicitly: // For example instead of
@mkdir($dir);
// Better use
if (@mkdir($dir) === false) {
throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
![]() |
|||
3007 | $this->DebugMessage('Attempting to process filter command "' . $command . '(' . $parameter . ')"', __FILE__, __LINE__); |
||
3008 | switch ($command) { |
||
3009 | case 'brit': // Brightness |
||
3010 | $phpthumbFilters->Brightness($this->gdimg_output, $parameter); |
||
3011 | break; |
||
3012 | |||
3013 | case 'cont': // Contrast |
||
3014 | $phpthumbFilters->Contrast($this->gdimg_output, $parameter); |
||
3015 | break; |
||
3016 | |||
3017 | case 'ds': // Desaturation |
||
3018 | $phpthumbFilters->Desaturate($this->gdimg_output, $parameter, ''); |
||
3019 | break; |
||
3020 | |||
3021 | case 'sat': // Saturation |
||
3022 | $phpthumbFilters->Saturation($this->gdimg_output, $parameter, ''); |
||
3023 | break; |
||
3024 | |||
3025 | case 'gray': // Grayscale |
||
3026 | $phpthumbFilters->Grayscale($this->gdimg_output); |
||
3027 | break; |
||
3028 | |||
3029 | View Code Duplication | case 'clr': // Colorize |
|
3030 | if (phpthumb_functions::gd_version() < 2) { |
||
3031 | $this->DebugMessage('Skipping Colorize() because gd_version is "' . phpthumb_functions::gd_version() . '"', __FILE__, __LINE__); |
||
3032 | break; |
||
3033 | } |
||
3034 | @list($amount, $color) = explode('|', $parameter, 2); |
||
0 ignored issues
–
show
It seems like you do not handle an error condition here. This can introduce security issues, and is generally not recommended.
If you suppress an error, we recommend checking for the error condition explicitly: // For example instead of
@mkdir($dir);
// Better use
if (@mkdir($dir) === false) {
throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
![]() |
|||
3035 | $phpthumbFilters->Colorize($this->gdimg_output, $amount, $color); |
||
3036 | break; |
||
3037 | |||
3038 | View Code Duplication | case 'sep': // Sepia |
|
3039 | if (phpthumb_functions::gd_version() < 2) { |
||
3040 | $this->DebugMessage('Skipping Sepia() because gd_version is "' . phpthumb_functions::gd_version() . '"', __FILE__, __LINE__); |
||
3041 | break; |
||
3042 | } |
||
3043 | @list($amount, $color) = explode('|', $parameter, 2); |
||
0 ignored issues
–
show
It seems like you do not handle an error condition here. This can introduce security issues, and is generally not recommended.
If you suppress an error, we recommend checking for the error condition explicitly: // For example instead of
@mkdir($dir);
// Better use
if (@mkdir($dir) === false) {
throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
![]() |
|||
3044 | $phpthumbFilters->Sepia($this->gdimg_output, $amount, $color); |
||
3045 | break; |
||
3046 | |||
3047 | case 'gam': // Gamma correction |
||
3048 | $phpthumbFilters->Gamma($this->gdimg_output, $parameter); |
||
3049 | break; |
||
3050 | |||
3051 | case 'neg': // Negative colors |
||
3052 | $phpthumbFilters->Negative($this->gdimg_output); |
||
3053 | break; |
||
3054 | |||
3055 | case 'th': // Threshold |
||
3056 | $phpthumbFilters->Threshold($this->gdimg_output, $parameter); |
||
3057 | break; |
||
3058 | |||
3059 | case 'rcd': // ReduceColorDepth |
||
3060 | if (phpthumb_functions::gd_version() < 2) { |
||
3061 | $this->DebugMessage('Skipping ReduceColorDepth() because gd_version is "' . phpthumb_functions::gd_version() . '"', __FILE__, __LINE__); |
||
3062 | break; |
||
3063 | } |
||
3064 | @list($colors, $dither) = explode('|', $parameter, 2); |
||
0 ignored issues
–
show
It seems like you do not handle an error condition here. This can introduce security issues, and is generally not recommended.
If you suppress an error, we recommend checking for the error condition explicitly: // For example instead of
@mkdir($dir);
// Better use
if (@mkdir($dir) === false) {
throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
![]() |
|||
3065 | $colors = ($colors ? (int)$colors : 256); |
||
3066 | $dither = ((strlen($dither) > 0) ? (bool)$dither : true); |
||
3067 | $phpthumbFilters->ReduceColorDepth($this->gdimg_output, $colors, $dither); |
||
3068 | break; |
||
3069 | |||
3070 | case 'flip': // Flip |
||
3071 | $phpthumbFilters->Flip($this->gdimg_output, strpos(strtolower($parameter), 'x') !== false, strpos(strtolower($parameter), 'y') !== false); |
||
3072 | break; |
||
3073 | |||
3074 | case 'edge': // EdgeDetect |
||
3075 | $phpthumbFilters->EdgeDetect($this->gdimg_output); |
||
3076 | break; |
||
3077 | |||
3078 | case 'emb': // Emboss |
||
3079 | $phpthumbFilters->Emboss($this->gdimg_output); |
||
3080 | break; |
||
3081 | |||
3082 | case 'bvl': // Bevel |
||
3083 | @list($width, $color1, $color2) = explode('|', $parameter, 3); |
||
0 ignored issues
–
show
It seems like you do not handle an error condition here. This can introduce security issues, and is generally not recommended.
If you suppress an error, we recommend checking for the error condition explicitly: // For example instead of
@mkdir($dir);
// Better use
if (@mkdir($dir) === false) {
throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
![]() |
|||
3084 | $phpthumbFilters->Bevel($this->gdimg_output, $width, $color1, $color2); |
||
3085 | break; |
||
3086 | |||
3087 | case 'lvl': // autoLevels |
||
3088 | @list($band, $method, $threshold) = explode('|', $parameter, 3); |
||
0 ignored issues
–
show
It seems like you do not handle an error condition here. This can introduce security issues, and is generally not recommended.
If you suppress an error, we recommend checking for the error condition explicitly: // For example instead of
@mkdir($dir);
// Better use
if (@mkdir($dir) === false) {
throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
![]() |
|||
3089 | $band = ($band ? preg_replace('#[^RGBA\\*]#', '', strtoupper($band)) : '*'); |
||
3090 | $method = ((strlen($method) > 0) ? (int)$method : 2); |
||
3091 | $threshold = ((strlen($threshold) > 0) ? (float)$threshold : 0.1); |
||
3092 | |||
3093 | $phpthumbFilters->HistogramStretch($this->gdimg_output, $band, $method, $threshold); |
||
3094 | break; |
||
3095 | |||
3096 | case 'wb': // WhiteBalance |
||
3097 | $phpthumbFilters->WhiteBalance($this->gdimg_output, $parameter); |
||
3098 | break; |
||
3099 | |||
3100 | case 'hist': // Histogram overlay |
||
3101 | if (phpthumb_functions::gd_version() < 2) { |
||
3102 | $this->DebugMessage('Skipping HistogramOverlay() because gd_version is "' . phpthumb_functions::gd_version() . '"', __FILE__, __LINE__); |
||
3103 | break; |
||
3104 | } |
||
3105 | @list($bands, $colors, $width, $height, $alignment, $opacity, $margin_x, $margin_y) = explode('|', $parameter, 8); |
||
0 ignored issues
–
show
It seems like you do not handle an error condition here. This can introduce security issues, and is generally not recommended.
If you suppress an error, we recommend checking for the error condition explicitly: // For example instead of
@mkdir($dir);
// Better use
if (@mkdir($dir) === false) {
throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
![]() |
|||
3106 | $bands = ($bands ?: '*'); |
||
3107 | $colors = ($colors ?: ''); |
||
3108 | $width = ($width ?: 0.25); |
||
3109 | $height = ($height ?: 0.25); |
||
3110 | $alignment = ($alignment ?: 'BR'); |
||
3111 | $opacity = ($opacity ?: 50); |
||
3112 | $margin_x = ($margin_x ?: 5); |
||
3113 | $margin_y = $margin_y; // just to note it wasn't forgotten, but let the value always pass unchanged |
||
3114 | $phpthumbFilters->HistogramOverlay($this->gdimg_output, $bands, $colors, $width, $height, $alignment, $opacity, $margin_x, $margin_y); |
||
3115 | break; |
||
3116 | |||
3117 | case 'fram': // Frame |
||
3118 | @list($frame_width, $edge_width, $color_frame, $color1, $color2) = explode('|', $parameter, 5); |
||
0 ignored issues
–
show
It seems like you do not handle an error condition here. This can introduce security issues, and is generally not recommended.
If you suppress an error, we recommend checking for the error condition explicitly: // For example instead of
@mkdir($dir);
// Better use
if (@mkdir($dir) === false) {
throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
![]() |
|||
3119 | $phpthumbFilters->Frame($this->gdimg_output, $frame_width, $edge_width, $color_frame, $color1, $color2); |
||
3120 | break; |
||
3121 | |||
3122 | case 'drop': // DropShadow |
||
3123 | if (phpthumb_functions::gd_version() < 2) { |
||
3124 | $this->DebugMessage('Skipping DropShadow() because gd_version is "' . phpthumb_functions::gd_version() . '"', __FILE__, __LINE__); |
||
3125 | |||
3126 | return false; |
||
3127 | } |
||
3128 | $this->is_alpha = true; |
||
3129 | @list($distance, $width, $color, $angle, $fade) = explode('|', $parameter, 5); |
||
0 ignored issues
–
show
It seems like you do not handle an error condition here. This can introduce security issues, and is generally not recommended.
If you suppress an error, we recommend checking for the error condition explicitly: // For example instead of
@mkdir($dir);
// Better use
if (@mkdir($dir) === false) {
throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
![]() |
|||
3130 | $phpthumbFilters->DropShadow($this->gdimg_output, $distance, $width, $color, $angle, $fade); |
||
3131 | break; |
||
3132 | |||
3133 | case 'mask': // Mask cropping |
||
3134 | if (phpthumb_functions::gd_version() < 2) { |
||
3135 | $this->DebugMessage('Skipping Mask() because gd_version is "' . phpthumb_functions::gd_version() . '"', __FILE__, __LINE__); |
||
3136 | |||
3137 | return false; |
||
3138 | } |
||
3139 | @list($mask_filename, $invert) = explode('|', $parameter, 2); |
||
0 ignored issues
–
show
It seems like you do not handle an error condition here. This can introduce security issues, and is generally not recommended.
If you suppress an error, we recommend checking for the error condition explicitly: // For example instead of
@mkdir($dir);
// Better use
if (@mkdir($dir) === false) {
throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
![]() |
|||
3140 | $mask_filename = $this->ResolveFilenameToAbsolute($mask_filename); |
||
3141 | if (@is_readable($mask_filename) && ($fp_mask = @fopen($mask_filename, 'rb'))) { |
||
3142 | $MaskImageData = ''; |
||
3143 | do { |
||
3144 | $buffer = fread($fp_mask, 8192); |
||
3145 | $MaskImageData .= $buffer; |
||
3146 | } while (strlen($buffer) > 0); |
||
3147 | fclose($fp_mask); |
||
3148 | if ($gdimg_mask = $this->ImageCreateFromStringReplacement($MaskImageData)) { |
||
3149 | if ($invert |
||
3150 | && phpthumb_functions::version_compare_replacement(PHP_VERSION, '5.0.0', '>=') |
||
3151 | && phpthumb_functions::gd_is_bundled() |
||
3152 | ) { |
||
3153 | imagefilter($gdimg_mask, IMG_FILTER_NEGATE); |
||
3154 | } |
||
3155 | $this->is_alpha = true; |
||
3156 | $phpthumbFilters->ApplyMask($gdimg_mask, $this->gdimg_output); |
||
3157 | imagedestroy($gdimg_mask); |
||
3158 | } else { |
||
3159 | $this->DebugMessage('ImageCreateFromStringReplacement() failed for "' . $mask_filename . '"', __FILE__, __LINE__); |
||
3160 | } |
||
3161 | } else { |
||
3162 | $this->DebugMessage('Cannot open mask file "' . $mask_filename . '"', __FILE__, __LINE__); |
||
3163 | } |
||
3164 | break; |
||
3165 | |||
3166 | case 'elip': // Ellipse cropping |
||
3167 | if (phpthumb_functions::gd_version() < 2) { |
||
3168 | $this->DebugMessage('Skipping Ellipse() because gd_version is "' . phpthumb_functions::gd_version() . '"', __FILE__, __LINE__); |
||
3169 | |||
3170 | return false; |
||
3171 | } |
||
3172 | $this->is_alpha = true; |
||
3173 | $phpthumbFilters->Ellipse($this->gdimg_output); |
||
3174 | break; |
||
3175 | |||
3176 | case 'ric': // RoundedImageCorners |
||
3177 | if (phpthumb_functions::gd_version() < 2) { |
||
3178 | $this->DebugMessage('Skipping RoundedImageCorners() because gd_version is "' . phpthumb_functions::gd_version() . '"', __FILE__, __LINE__); |
||
3179 | |||
3180 | return false; |
||
3181 | } |
||
3182 | @list($radius_x, $radius_y) = explode('|', $parameter, 2); |
||
0 ignored issues
–
show
It seems like you do not handle an error condition here. This can introduce security issues, and is generally not recommended.
If you suppress an error, we recommend checking for the error condition explicitly: // For example instead of
@mkdir($dir);
// Better use
if (@mkdir($dir) === false) {
throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
![]() |
|||
3183 | if (($radius_x < 1) || ($radius_y < 1)) { |
||
3184 | $this->DebugMessage('Skipping RoundedImageCorners(' . $radius_x . ', ' . $radius_y . ') because x/y radius is less than 1', __FILE__, __LINE__); |
||
3185 | break; |
||
3186 | } |
||
3187 | $this->is_alpha = true; |
||
3188 | $phpthumbFilters->RoundedImageCorners($this->gdimg_output, $radius_x, $radius_y); |
||
3189 | break; |
||
3190 | |||
3191 | case 'crop': // Crop |
||
3192 | @list($left, $right, $top, $bottom) = explode('|', $parameter, 4); |
||
0 ignored issues
–
show
It seems like you do not handle an error condition here. This can introduce security issues, and is generally not recommended.
If you suppress an error, we recommend checking for the error condition explicitly: // For example instead of
@mkdir($dir);
// Better use
if (@mkdir($dir) === false) {
throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
![]() |
|||
3193 | $phpthumbFilters->Crop($this->gdimg_output, $left, $right, $top, $bottom); |
||
3194 | break; |
||
3195 | |||
3196 | case 'bord': // Border |
||
3197 | @list($border_width, $radius_x, $radius_y, $hexcolor_border) = explode('|', $parameter, 4); |
||
0 ignored issues
–
show
It seems like you do not handle an error condition here. This can introduce security issues, and is generally not recommended.
If you suppress an error, we recommend checking for the error condition explicitly: // For example instead of
@mkdir($dir);
// Better use
if (@mkdir($dir) === false) {
throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
![]() |
|||
3198 | $this->is_alpha = true; |
||
3199 | $phpthumbFilters->ImageBorder($this->gdimg_output, $border_width, $radius_x, $radius_y, $hexcolor_border); |
||
3200 | break; |
||
3201 | |||
3202 | case 'over': // Overlay |
||
3203 | @list($filename, $underlay, $margin, $opacity) = explode('|', $parameter, 4); |
||
0 ignored issues
–
show
It seems like you do not handle an error condition here. This can introduce security issues, and is generally not recommended.
If you suppress an error, we recommend checking for the error condition explicitly: // For example instead of
@mkdir($dir);
// Better use
if (@mkdir($dir) === false) {
throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
![]() |
|||
3204 | $underlay = (bool)($underlay ?: false); |
||
3205 | $margin = ((strlen($margin) > 0) ? $margin : ($underlay ? 0.1 : 0.0)); |
||
3206 | $opacity = ((strlen($opacity) > 0) ? $opacity : 100); |
||
3207 | if (($margin > 0) && ($margin < 1)) { |
||
3208 | $margin = min(0.499, $margin); |
||
3209 | } elseif (($margin > -1) && ($margin < 0)) { |
||
3210 | $margin = max(-0.499, $margin); |
||
3211 | } |
||
3212 | |||
3213 | $filename = $this->ResolveFilenameToAbsolute($filename); |
||
3214 | if (@is_readable($filename) && ($fp_watermark = @fopen($filename, 'rb'))) { |
||
3215 | $WatermarkImageData = ''; |
||
3216 | do { |
||
3217 | $buffer = fread($fp_watermark, 8192); |
||
3218 | $WatermarkImageData .= $buffer; |
||
3219 | } while (strlen($buffer) > 0); |
||
3220 | fclose($fp_watermark); |
||
3221 | if ($img_watermark = $this->ImageCreateFromStringReplacement($WatermarkImageData)) { |
||
3222 | if ($margin < 1) { |
||
3223 | $resized_x = max(1, imagesx($this->gdimg_output) - round(2 * (imagesx($this->gdimg_output) * $margin))); |
||
3224 | $resized_y = max(1, imagesy($this->gdimg_output) - round(2 * (imagesy($this->gdimg_output) * $margin))); |
||
3225 | } else { |
||
3226 | $resized_x = max(1, imagesx($this->gdimg_output) - round(2 * $margin)); |
||
3227 | $resized_y = max(1, imagesy($this->gdimg_output) - round(2 * $margin)); |
||
3228 | } |
||
3229 | |||
3230 | if ($underlay) { |
||
3231 | if ($img_watermark_resized = phpthumb_functions::ImageCreateFunction(imagesx($this->gdimg_output), imagesy($this->gdimg_output))) { |
||
3232 | ImageAlphaBlending($img_watermark_resized, false); |
||
3233 | ImageSaveAlpha($img_watermark_resized, true); |
||
3234 | $this->ImageResizeFunction($img_watermark_resized, $img_watermark, 0, 0, 0, 0, imagesx($img_watermark_resized), imagesy($img_watermark_resized), |
||
3235 | imagesx($img_watermark), imagesy($img_watermark)); |
||
3236 | if ($img_source_resized = phpthumb_functions::ImageCreateFunction($resized_x, $resized_y)) { |
||
3237 | ImageAlphaBlending($img_source_resized, false); |
||
3238 | ImageSaveAlpha($img_source_resized, true); |
||
3239 | $this->ImageResizeFunction($img_source_resized, $this->gdimg_output, 0, 0, 0, 0, imagesx($img_source_resized), imagesy($img_source_resized), |
||
3240 | imagesx($this->gdimg_output), imagesy($this->gdimg_output)); |
||
3241 | $phpthumbFilters->WatermarkOverlay($img_watermark_resized, $img_source_resized, 'C', $opacity, $margin); |
||
3242 | imagecopy($this->gdimg_output, $img_watermark_resized, 0, 0, 0, 0, imagesx($this->gdimg_output), imagesy($this->gdimg_output)); |
||
3243 | } else { |
||
3244 | $this->DebugMessage('phpthumb_functions::ImageCreateFunction(' . $resized_x . ', ' . $resized_y . ')', __FILE__, __LINE__); |
||
3245 | } |
||
3246 | imagedestroy($img_watermark_resized); |
||
3247 | View Code Duplication | } else { |
|
3248 | $this->DebugMessage('phpthumb_functions::ImageCreateFunction(' . imagesx($this->gdimg_output) . ', ' . imagesy($this->gdimg_output) . ')', __FILE__, __LINE__); |
||
3249 | } |
||
3250 | } else { // overlay |
||
3251 | |||
3252 | if ($img_watermark_resized = phpthumb_functions::ImageCreateFunction($resized_x, $resized_y)) { |
||
3253 | ImageAlphaBlending($img_watermark_resized, false); |
||
3254 | ImageSaveAlpha($img_watermark_resized, true); |
||
3255 | $this->ImageResizeFunction($img_watermark_resized, $img_watermark, 0, 0, 0, 0, imagesx($img_watermark_resized), imagesy($img_watermark_resized), |
||
3256 | imagesx($img_watermark), imagesy($img_watermark)); |
||
3257 | $phpthumbFilters->WatermarkOverlay($this->gdimg_output, $img_watermark_resized, 'C', $opacity, $margin); |
||
3258 | imagedestroy($img_watermark_resized); |
||
3259 | } else { |
||
3260 | $this->DebugMessage('phpthumb_functions::ImageCreateFunction(' . $resized_x . ', ' . $resized_y . ')', __FILE__, __LINE__); |
||
3261 | } |
||
3262 | } |
||
3263 | imagedestroy($img_watermark); |
||
3264 | } else { |
||
3265 | $this->DebugMessage('ImageCreateFromStringReplacement() failed for "' . $filename . '"', __FILE__, __LINE__); |
||
3266 | } |
||
3267 | } else { |
||
3268 | $this->DebugMessage('Cannot open overlay file "' . $filename . '"', __FILE__, __LINE__); |
||
3269 | } |
||
3270 | break; |
||
3271 | |||
3272 | case 'wmi': // WaterMarkImage |
||
3273 | @list($filename, $alignment, $opacity, $margin['x'], $margin['y'], $rotate_angle) = explode('|', $parameter, 6); |
||
0 ignored issues
–
show
It seems like you do not handle an error condition here. This can introduce security issues, and is generally not recommended.
If you suppress an error, we recommend checking for the error condition explicitly: // For example instead of
@mkdir($dir);
// Better use
if (@mkdir($dir) === false) {
throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
![]() |
|||
3274 | // $margin can be pixel margin or percent margin if $alignment is text, or max width/height if $alignment is position like "50x75" |
||
3275 | $alignment = ($alignment ?: 'BR'); |
||
3276 | $opacity = (strlen($opacity) ? (int)$opacity : 50); |
||
3277 | $rotate_angle = (strlen($rotate_angle) ? (int)$rotate_angle : 0); |
||
3278 | if (!preg_match('#^([0-9\\.\\-]*)x([0-9\\.\\-]*)$#i', $alignment, $matches)) { |
||
3279 | $margins = array('x', 'y'); |
||
3280 | foreach ($margins as $xy) { |
||
3281 | $margin[$xy] = (strlen($margin[$xy]) ? $margin[$xy] : 5); |
||
3282 | if (($margin[$xy] > 0) && ($margin[$xy] < 1)) { |
||
3283 | $margin[$xy] = min(0.499, $margin[$xy]); |
||
3284 | } elseif (($margin[$xy] > -1) && ($margin[$xy] < 0)) { |
||
3285 | $margin[$xy] = max(-0.499, $margin[$xy]); |
||
3286 | } |
||
3287 | } |
||
3288 | } |
||
3289 | |||
3290 | $filename = $this->ResolveFilenameToAbsolute($filename); |
||
3291 | if (@is_readable($filename)) { |
||
3292 | if ($img_watermark = $this->ImageCreateFromFilename($filename)) { |
||
3293 | if ($rotate_angle !== 0) { |
||
3294 | $phpthumbFilters->ImprovedImageRotate($img_watermark, $rotate_angle, 'FFFFFF', null, $this); |
||
3295 | } |
||
3296 | if (preg_match('#^([0-9\\.\\-]*)x([0-9\\.\\-]*)$#i', $alignment, $matches)) { |
||
3297 | $watermark_max_width = (int)($margin['x'] ?: imagesx($img_watermark)); |
||
3298 | $watermark_max_height = (int)($margin['y'] ?: imagesy($img_watermark)); |
||
3299 | $scale = phpthumb_functions::ScaleToFitInBox(imagesx($img_watermark), imagesy($img_watermark), $watermark_max_width, $watermark_max_height, true, |
||
3300 | true); |
||
3301 | $this->DebugMessage('Scaling watermark by a factor of ' . number_format($scale, 4), __FILE__, __LINE__); |
||
3302 | if (($scale > 1) || ($scale < 1)) { |
||
3303 | if ($img_watermark2 = phpthumb_functions::ImageCreateFunction($scale * imagesx($img_watermark), $scale * imagesy($img_watermark))) { |
||
3304 | ImageAlphaBlending($img_watermark2, false); |
||
3305 | ImageSaveAlpha($img_watermark2, true); |
||
3306 | $this->ImageResizeFunction($img_watermark2, $img_watermark, 0, 0, 0, 0, imagesx($img_watermark2), imagesy($img_watermark2), imagesx($img_watermark), |
||
3307 | imagesy($img_watermark)); |
||
3308 | $img_watermark = $img_watermark2; |
||
3309 | } else { |
||
3310 | $this->DebugMessage('ImageCreateFunction(' . ($scale * imagesx($img_watermark)) . ', ' . ($scale * imagesx($img_watermark)) . ') failed', __FILE__, |
||
3311 | __LINE__); |
||
3312 | } |
||
3313 | } |
||
3314 | $watermark_dest_x = round($matches[1] - (imagesx($img_watermark) / 2)); |
||
3315 | $watermark_dest_y = round($matches[2] - (imagesy($img_watermark) / 2)); |
||
3316 | $alignment = $watermark_dest_x . 'x' . $watermark_dest_y; |
||
3317 | } |
||
3318 | $phpthumbFilters->WatermarkOverlay($this->gdimg_output, $img_watermark, $alignment, $opacity, $margin['x'], $margin['y']); |
||
3319 | imagedestroy($img_watermark); |
||
3320 | if (isset($img_watermark2) && is_resource($img_watermark2)) { |
||
3321 | imagedestroy($img_watermark2); |
||
3322 | } |
||
3323 | } else { |
||
3324 | $this->DebugMessage('ImageCreateFromFilename() failed for "' . $filename . '"', __FILE__, __LINE__); |
||
3325 | } |
||
3326 | } else { |
||
3327 | $this->DebugMessage('!is_readable(' . $filename . ')', __FILE__, __LINE__); |
||
3328 | } |
||
3329 | break; |
||
3330 | |||
3331 | case 'wmt': // WaterMarkText |
||
3332 | @list($text, $size, $alignment, $hex_color, $ttffont, $opacity, $margin, $angle, $bg_color, $bg_opacity, $fillextend) = explode('|', $parameter, 11); |
||
0 ignored issues
–
show
It seems like you do not handle an error condition here. This can introduce security issues, and is generally not recommended.
If you suppress an error, we recommend checking for the error condition explicitly: // For example instead of
@mkdir($dir);
// Better use
if (@mkdir($dir) === false) {
throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
![]() |
|||
3333 | $text = ($text ?: ''); |
||
3334 | $size = ($size ?: 3); |
||
3335 | $alignment = ($alignment ?: 'BR'); |
||
3336 | $hex_color = ($hex_color ?: '000000'); |
||
3337 | $ttffont = ($ttffont ?: ''); |
||
3338 | $opacity = (strlen($opacity) ? $opacity : 50); |
||
3339 | $margin = (strlen($margin) ? $margin : 5); |
||
3340 | $angle = (strlen($angle) ? $angle : 0); |
||
3341 | $bg_color = ($bg_color ?: false); |
||
3342 | $bg_opacity = ($bg_opacity ?: 0); |
||
3343 | $fillextend = ($fillextend ?: ''); |
||
3344 | |||
3345 | if (basename($ttffont) == $ttffont) { |
||
3346 | $ttffont = $this->realPathSafe($this->config_ttf_directory . DIRECTORY_SEPARATOR . $ttffont); |
||
3347 | } else { |
||
3348 | $ttffont = $this->ResolveFilenameToAbsolute($ttffont); |
||
3349 | } |
||
3350 | $phpthumbFilters->WatermarkText($this->gdimg_output, $text, $size, $alignment, $hex_color, $ttffont, $opacity, $margin, $angle, $bg_color, $bg_opacity, $fillextend); |
||
3351 | break; |
||
3352 | |||
3353 | View Code Duplication | case 'blur': // Blur |
|
3354 | @list($radius) = explode('|', $parameter, 1); |
||
0 ignored issues
–
show
It seems like you do not handle an error condition here. This can introduce security issues, and is generally not recommended.
If you suppress an error, we recommend checking for the error condition explicitly: // For example instead of
@mkdir($dir);
// Better use
if (@mkdir($dir) === false) {
throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
![]() |
|||
3355 | $radius = ($radius ?: 1); |
||
3356 | if (phpthumb_functions::gd_version() >= 2) { |
||
3357 | $phpthumbFilters->Blur($this->gdimg_output, $radius); |
||
3358 | } else { |
||
3359 | $this->DebugMessage('Skipping Blur() because gd_version is "' . phpthumb_functions::gd_version() . '"', __FILE__, __LINE__); |
||
3360 | } |
||
3361 | break; |
||
3362 | |||
3363 | case 'gblr': // Gaussian Blur |
||
3364 | $phpthumbFilters->BlurGaussian($this->gdimg_output); |
||
3365 | break; |
||
3366 | |||
3367 | case 'sblr': // Selective Blur |
||
3368 | $phpthumbFilters->BlurSelective($this->gdimg_output); |
||
3369 | break; |
||
3370 | |||
3371 | case 'mean': // MeanRemoval blur |
||
3372 | $phpthumbFilters->MeanRemoval($this->gdimg_output); |
||
3373 | break; |
||
3374 | |||
3375 | case 'smth': // Smooth blur |
||
3376 | $phpthumbFilters->Smooth($this->gdimg_output, $parameter); |
||
3377 | break; |
||
3378 | |||
3379 | case 'usm': // UnSharpMask sharpening |
||
3380 | @list($amount, $radius, $threshold) = explode('|', $parameter, 3); |
||
0 ignored issues
–
show
It seems like you do not handle an error condition here. This can introduce security issues, and is generally not recommended.
If you suppress an error, we recommend checking for the error condition explicitly: // For example instead of
@mkdir($dir);
// Better use
if (@mkdir($dir) === false) {
throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
![]() |
|||
3381 | $amount = ($amount ?: 80); |
||
3382 | $radius = ($radius ?: 0.5); |
||
3383 | $threshold = (strlen($threshold) ? $threshold : 3); |
||
3384 | if (phpthumb_functions::gd_version() >= 2.0) { |
||
3385 | ob_start(); |
||
3386 | if (!@require_once __DIR__ . '/phpthumb.unsharp.php') { |
||
3387 | $include_error = ob_get_contents(); |
||
3388 | if ($include_error) { |
||
3389 | $this->DebugMessage('include_once("' . __DIR__ . '/phpthumb.unsharp.php") generated message: "' . $include_error . '"', __FILE__, __LINE__); |
||
3390 | } |
||
3391 | $this->DebugMessage('Error including "' . __DIR__ . '/phpthumb.unsharp.php" which is required for unsharp masking', __FILE__, __LINE__); |
||
3392 | ob_end_clean(); |
||
3393 | |||
3394 | return false; |
||
3395 | } |
||
3396 | ob_end_clean(); |
||
3397 | phpUnsharpMask::applyUnsharpMask($this->gdimg_output, $amount, $radius, $threshold); |
||
3398 | } else { |
||
3399 | $this->DebugMessage('Skipping unsharp mask because gd_version is "' . phpthumb_functions::gd_version() . '"', __FILE__, __LINE__); |
||
3400 | |||
3401 | return false; |
||
3402 | } |
||
3403 | break; |
||
3404 | |||
3405 | case 'size': // Resize |
||
3406 | @list($newwidth, $newheight, $stretch) = explode('|', $parameter); |
||
0 ignored issues
–
show
It seems like you do not handle an error condition here. This can introduce security issues, and is generally not recommended.
If you suppress an error, we recommend checking for the error condition explicitly: // For example instead of
@mkdir($dir);
// Better use
if (@mkdir($dir) === false) {
throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
![]() |
|||
3407 | $newwidth = (!$newwidth ? imagesx($this->gdimg_output) : ((($newwidth > 0) |
||
3408 | && ($newwidth < 1)) ? round($newwidth * imagesx($this->gdimg_output)) : round($newwidth))); |
||
3409 | $newheight = (!$newheight ? imagesy($this->gdimg_output) : ((($newheight > 0) |
||
3410 | && ($newheight < 1)) ? round($newheight * imagesy($this->gdimg_output)) : round($newheight))); |
||
3411 | $stretch = ($stretch ? true : false); |
||
3412 | if ($stretch) { |
||
3413 | $scale_x = phpthumb_functions::ScaleToFitInBox(imagesx($this->gdimg_output), imagesx($this->gdimg_output), $newwidth, $newwidth, true, true); |
||
3414 | $scale_y = phpthumb_functions::ScaleToFitInBox(imagesy($this->gdimg_output), imagesy($this->gdimg_output), $newheight, $newheight, true, true); |
||
3415 | } else { |
||
3416 | $scale_x = phpthumb_functions::ScaleToFitInBox(imagesx($this->gdimg_output), imagesy($this->gdimg_output), $newwidth, $newheight, true, true); |
||
3417 | $scale_y = $scale_x; |
||
3418 | } |
||
3419 | $this->DebugMessage('Scaling watermark (' |
||
3420 | . ($stretch ? 'with' : 'without') |
||
3421 | . ' stretch) by a factor of "' |
||
3422 | . number_format($scale_x, 4) |
||
3423 | . ' x ' |
||
3424 | . number_format($scale_y, 4) |
||
3425 | . '"', __FILE__, __LINE__); |
||
3426 | if (($scale_x > 1) || ($scale_x < 1) || ($scale_y > 1) || ($scale_y < 1)) { |
||
3427 | if ($img_temp = phpthumb_functions::ImageCreateFunction(imagesx($this->gdimg_output), imagesy($this->gdimg_output))) { |
||
3428 | imagecopy($img_temp, $this->gdimg_output, 0, 0, 0, 0, imagesx($this->gdimg_output), imagesy($this->gdimg_output)); |
||
3429 | //ImageDestroy($this->gdimg_output); |
||
3430 | if ($this->gdimg_output = phpthumb_functions::ImageCreateFunction($scale_x * imagesx($img_temp), $scale_y * imagesy($img_temp))) { |
||
3431 | ImageAlphaBlending($this->gdimg_output, false); |
||
3432 | ImageSaveAlpha($this->gdimg_output, true); |
||
3433 | $this->ImageResizeFunction($this->gdimg_output, $img_temp, 0, 0, 0, 0, imagesx($this->gdimg_output), imagesy($this->gdimg_output), imagesx($img_temp), |
||
3434 | imagesy($img_temp)); |
||
3435 | } else { |
||
3436 | $this->DebugMessage('ImageCreateFunction(' . ($scale_x * imagesx($img_temp)) . ', ' . ($scale_y * imagesy($img_temp)) . ') failed', __FILE__, __LINE__); |
||
3437 | } |
||
3438 | imagedestroy($img_temp); |
||
3439 | View Code Duplication | } else { |
|
3440 | $this->DebugMessage('ImageCreateFunction(' . imagesx($this->gdimg_output) . ', ' . imagesy($this->gdimg_output) . ') failed', __FILE__, __LINE__); |
||
3441 | } |
||
3442 | } |
||
3443 | break; |
||
3444 | |||
3445 | case 'rot': // ROTate |
||
3446 | @list($angle, $bgcolor) = explode('|', $parameter, 2); |
||
0 ignored issues
–
show
It seems like you do not handle an error condition here. This can introduce security issues, and is generally not recommended.
If you suppress an error, we recommend checking for the error condition explicitly: // For example instead of
@mkdir($dir);
// Better use
if (@mkdir($dir) === false) {
throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
![]() |
|||
3447 | $phpthumbFilters->ImprovedImageRotate($this->gdimg_output, $angle, $bgcolor, null, $this); |
||
3448 | break; |
||
3449 | |||
3450 | case 'stc': // Source Transparent Color |
||
3451 | @list($hexcolor, $min_limit, $max_limit) = explode('|', $parameter, 3); |
||
0 ignored issues
–
show
It seems like you do not handle an error condition here. This can introduce security issues, and is generally not recommended.
If you suppress an error, we recommend checking for the error condition explicitly: // For example instead of
@mkdir($dir);
// Better use
if (@mkdir($dir) === false) {
throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
![]() |
|||
3452 | if (!phpthumb_functions::IsHexColor($hexcolor)) { |
||
3453 | $this->DebugMessage('Skipping SourceTransparentColor hex color is invalid (' . $hexcolor . ')', __FILE__, __LINE__); |
||
3454 | |||
3455 | return false; |
||
3456 | } |
||
3457 | $min_limit = (strlen($min_limit) ? $min_limit : 5); |
||
3458 | $max_limit = (strlen($max_limit) ? $max_limit : 10); |
||
3459 | if ($gdimg_mask = $phpthumbFilters->SourceTransparentColorMask($this->gdimg_output, $hexcolor, $min_limit, $max_limit)) { |
||
3460 | $this->is_alpha = true; |
||
3461 | $phpthumbFilters->ApplyMask($gdimg_mask, $this->gdimg_output); |
||
3462 | imagedestroy($gdimg_mask); |
||
3463 | } else { |
||
3464 | $this->DebugMessage('SourceTransparentColorMask() failed for "' . $mask_filename . '"', __FILE__, __LINE__); |
||
3465 | } |
||
3466 | break; |
||
3467 | } |
||
3468 | $this->DebugMessage('Finished processing filter command "' . $command . '(' . $parameter . ')"', __FILE__, __LINE__); |
||
3469 | } |
||
3470 | } |
||
3471 | |||
3472 | return true; |
||
3473 | } |
||
3474 | |||
3475 | /** |
||
3476 | * @return bool |
||
3477 | */ |
||
3478 | public function MaxFileSize() |
||
3479 | { |
||
3480 | if (phpthumb_functions::gd_version() < 2) { |
||
3481 | $this->DebugMessage('Skipping MaxFileSize() because gd_version is "' . phpthumb_functions::gd_version() . '"', __FILE__, __LINE__); |
||
3482 | |||
3483 | return false; |
||
3484 | } |
||
3485 | if ($this->maxb > 0) { |
||
3486 | switch ($this->thumbnailFormat) { |
||
3487 | case 'png': |
||
3488 | case 'gif': |
||
3489 | $imgRenderFunction = 'image' . $this->thumbnailFormat; |
||
3490 | |||
3491 | ob_start(); |
||
3492 | $imgRenderFunction($this->gdimg_output); |
||
3493 | $imgdata = ob_get_contents(); |
||
3494 | ob_end_clean(); |
||
3495 | |||
3496 | if (strlen($imgdata) > $this->maxb) { |
||
3497 | for ($i = 8; $i >= 1; $i--) { |
||
3498 | $tempIMG = imagecreatetruecolor(imagesx($this->gdimg_output), imagesy($this->gdimg_output)); |
||
3499 | imagecopy($tempIMG, $this->gdimg_output, 0, 0, 0, 0, imagesx($this->gdimg_output), imagesy($this->gdimg_output)); |
||
3500 | imagetruecolortopalette($tempIMG, true, pow(2, $i)); |
||
3501 | ob_start(); |
||
3502 | $imgRenderFunction($tempIMG); |
||
3503 | $imgdata = ob_get_contents(); |
||
3504 | ob_end_clean(); |
||
3505 | |||
3506 | View Code Duplication | if (strlen($imgdata) <= $this->maxb) { |
|
3507 | imagetruecolortopalette($this->gdimg_output, true, pow(2, $i)); |
||
3508 | break; |
||
3509 | } |
||
3510 | } |
||
3511 | } |
||
3512 | View Code Duplication | if (strlen($imgdata) > $this->maxb) { |
|
3513 | imagetruecolortopalette($this->gdimg_output, true, pow(2, $i)); |
||
3514 | |||
3515 | return false; |
||
3516 | } |
||
3517 | break; |
||
3518 | |||
3519 | case 'jpeg': |
||
3520 | ob_start(); |
||
3521 | imagejpeg($this->gdimg_output); |
||
3522 | $imgdata = ob_get_contents(); |
||
3523 | ob_end_clean(); |
||
3524 | |||
3525 | $OriginalJPEGquality = $this->thumbnailQuality; |
||
3526 | if (strlen($imgdata) > $this->maxb) { |
||
3527 | for ($i = 3; $i < 20; $i++) { |
||
3528 | $q = round(100 * (1 - log10($i / 2))); |
||
3529 | ob_start(); |
||
3530 | imagejpeg($this->gdimg_output, null, $q); |
||
3531 | $imgdata = ob_get_contents(); |
||
3532 | ob_end_clean(); |
||
3533 | |||
3534 | $this->thumbnailQuality = $q; |
||
3535 | if (strlen($imgdata) <= $this->maxb) { |
||
3536 | break; |
||
3537 | } |
||
3538 | } |
||
3539 | } |
||
3540 | if (strlen($imgdata) > $this->maxb) { |
||
3541 | return false; |
||
3542 | } |
||
3543 | break; |
||
3544 | |||
3545 | default: |
||
3546 | return false; |
||
3547 | break; |
||
3548 | } |
||
3549 | } |
||
3550 | |||
3551 | return true; |
||
3552 | } |
||
3553 | |||
3554 | /** |
||
3555 | * @return bool |
||
3556 | */ |
||
3557 | public function CalculateThumbnailDimensions() |
||
3558 | { |
||
3559 | $this->DebugMessage('CalculateThumbnailDimensions() starting with [W,H,sx,sy,sw,sh] initially set to [' |
||
3560 | . $this->source_width |
||
3561 | . ',' |
||
3562 | . $this->source_height |
||
3563 | . ',' |
||
3564 | . $this->sx |
||
3565 | . ',' |
||
3566 | . $this->sy |
||
3567 | . ',' |
||
3568 | . $this->sw |
||
3569 | . ',' |
||
3570 | . $this->sh |
||
3571 | . ']', __FILE__, __LINE__); |
||
3572 | //echo $this->source_width.'x'.$this->source_height.'<hr>'; |
||
3573 | $this->thumbnailCropX = ($this->sx ? (($this->sx >= 2) ? $this->sx : round($this->sx * $this->source_width)) : 0); |
||
3574 | //echo $this->thumbnailCropX.'<br>'; |
||
3575 | $this->thumbnailCropY = ($this->sy ? (($this->sy >= 2) ? $this->sy : round($this->sy * $this->source_height)) : 0); |
||
3576 | //echo $this->thumbnailCropY.'<br>'; |
||
3577 | $this->thumbnailCropW = ($this->sw ? (($this->sw >= 2) ? $this->sw : round($this->sw * $this->source_width)) : $this->source_width); |
||
3578 | //echo $this->thumbnailCropW.'<br>'; |
||
3579 | $this->thumbnailCropH = ($this->sh ? (($this->sh >= 2) ? $this->sh : round($this->sh * $this->source_height)) : $this->source_height); |
||
3580 | //echo $this->thumbnailCropH.'<hr>'; |
||
3581 | |||
3582 | // limit source area to original image area |
||
3583 | $this->thumbnailCropW = max(1, min($this->thumbnailCropW, $this->source_width - $this->thumbnailCropX)); |
||
3584 | $this->thumbnailCropH = max(1, min($this->thumbnailCropH, $this->source_height - $this->thumbnailCropY)); |
||
3585 | |||
3586 | $this->DebugMessage('CalculateThumbnailDimensions() starting with [x,y,w,h] initially set to [' |
||
3587 | . $this->thumbnailCropX |
||
3588 | . ',' |
||
3589 | . $this->thumbnailCropY |
||
3590 | . ',' |
||
3591 | . $this->thumbnailCropW |
||
3592 | . ',' |
||
3593 | . $this->thumbnailCropH |
||
3594 | . ']', __FILE__, __LINE__); |
||
3595 | |||
3596 | if ($this->zc && $this->w && $this->h) { |
||
3597 | // Zoom Crop |
||
3598 | // retain proportional resizing we did above, but crop off larger dimension so smaller |
||
3599 | // dimension fully fits available space |
||
3600 | |||
3601 | $scaling_X = $this->source_width / $this->w; |
||
3602 | $scaling_Y = $this->source_height / $this->h; |
||
3603 | if ($scaling_X > $scaling_Y) { |
||
3604 | // some of the width will need to be cropped |
||
3605 | $allowable_width = $this->source_width / $scaling_X * $scaling_Y; |
||
3606 | $this->thumbnailCropW = round($allowable_width); |
||
3607 | $this->thumbnailCropX = round(($this->source_width - $allowable_width) / 2); |
||
3608 | } elseif ($scaling_Y > $scaling_X) { |
||
3609 | // some of the height will need to be cropped |
||
3610 | $allowable_height = $this->source_height / $scaling_Y * $scaling_X; |
||
3611 | $this->thumbnailCropH = round($allowable_height); |
||
3612 | $this->thumbnailCropY = round(($this->source_height - $allowable_height) / 2); |
||
3613 | } else { |
||
3614 | // image fits perfectly, no cropping needed |
||
3615 | } |
||
3616 | $this->thumbnail_width = $this->w; |
||
3617 | $this->thumbnail_height = $this->h; |
||
3618 | $this->thumbnail_image_width = $this->thumbnail_width; |
||
3619 | $this->thumbnail_image_height = $this->thumbnail_height; |
||
3620 | } elseif ($this->iar && $this->w && $this->h) { |
||
3621 | |||
3622 | // Ignore Aspect Ratio |
||
3623 | // stretch image to fit exactly 'w' x 'h' |
||
3624 | $this->thumbnail_width = $this->w; |
||
3625 | $this->thumbnail_height = $this->h; |
||
3626 | $this->thumbnail_image_width = $this->thumbnail_width; |
||
3627 | $this->thumbnail_image_height = $this->thumbnail_height; |
||
3628 | } else { |
||
3629 | $original_aspect_ratio = $this->thumbnailCropW / $this->thumbnailCropH; |
||
3630 | if ($this->aoe) { |
||
3631 | if ($this->w && $this->h) { |
||
3632 | $maxwidth = min($this->w, $this->h * $original_aspect_ratio); |
||
3633 | $maxheight = min($this->h, $this->w / $original_aspect_ratio); |
||
3634 | } elseif ($this->w) { |
||
3635 | $maxwidth = $this->w; |
||
3636 | $maxheight = $this->w / $original_aspect_ratio; |
||
3637 | } elseif ($this->h) { |
||
3638 | $maxwidth = $this->h * $original_aspect_ratio; |
||
3639 | $maxheight = $this->h; |
||
3640 | } else { |
||
3641 | $maxwidth = $this->thumbnailCropW; |
||
3642 | $maxheight = $this->thumbnailCropH; |
||
3643 | } |
||
3644 | } else { |
||
3645 | $maxwidth = phpthumb_functions::nonempty_min($this->w, $this->thumbnailCropW, $this->config_output_maxwidth); |
||
3646 | $maxheight = phpthumb_functions::nonempty_min($this->h, $this->thumbnailCropH, $this->config_output_maxheight); |
||
3647 | //echo $maxwidth.'x'.$maxheight.'<br>'; |
||
3648 | $maxwidth = min($maxwidth, $maxheight * $original_aspect_ratio); |
||
3649 | $maxheight = min($maxheight, $maxwidth / $original_aspect_ratio); |
||
3650 | //echo $maxwidth.'x'.$maxheight.'<hr>'; |
||
3651 | } |
||
3652 | |||
3653 | $this->thumbnail_image_width = $maxwidth; |
||
3654 | $this->thumbnail_image_height = $maxheight; |
||
3655 | $this->thumbnail_width = $maxwidth; |
||
3656 | $this->thumbnail_height = $maxheight; |
||
3657 | |||
3658 | $this->FixedAspectRatio(); |
||
3659 | } |
||
3660 | |||
3661 | $this->thumbnail_width = max(1, floor($this->thumbnail_width)); |
||
3662 | $this->thumbnail_height = max(1, floor($this->thumbnail_height)); |
||
3663 | |||
3664 | return true; |
||
3665 | } |
||
3666 | |||
3667 | /** |
||
3668 | * @return bool |
||
3669 | */ |
||
3670 | public function CreateGDoutput() |
||
3671 | { |
||
3672 | $this->CalculateThumbnailDimensions(); |
||
3673 | |||
3674 | // Create the GD image (either true-color or 256-color, depending on GD version) |
||
3675 | $this->gdimg_output = phpthumb_functions::ImageCreateFunction($this->thumbnail_width, $this->thumbnail_height); |
||
3676 | |||
3677 | // Images that have transparency must have the background filled with the configured 'bg' color |
||
3678 | // otherwise the transparent color will appear as black |
||
3679 | ImageSaveAlpha($this->gdimg_output, true); |
||
3680 | if ($this->is_alpha && phpthumb_functions::gd_version() >= 2) { |
||
3681 | ImageAlphaBlending($this->gdimg_output, false); |
||
3682 | $output_full_alpha = phpthumb_functions::ImageColorAllocateAlphaSafe($this->gdimg_output, 255, 255, 255, 127); |
||
3683 | imagefilledrectangle($this->gdimg_output, 0, 0, $this->thumbnail_width, $this->thumbnail_height, $output_full_alpha); |
||
3684 | } else { |
||
3685 | $current_transparent_color = imagecolortransparent($this->gdimg_source); |
||
3686 | if ($this->bg || (@$current_transparent_color >= 0)) { |
||
3687 | $this->config_background_hexcolor = ($this->bg ?: $this->config_background_hexcolor); |
||
3688 | if (!phpthumb_functions::IsHexColor($this->config_background_hexcolor)) { |
||
3689 | return $this->ErrorImage('Invalid hex color string "' . $this->config_background_hexcolor . '" for parameter "bg"'); |
||
3690 | } |
||
3691 | $background_color = phpthumb_functions::ImageHexColorAllocate($this->gdimg_output, $this->config_background_hexcolor); |
||
3692 | imagefilledrectangle($this->gdimg_output, 0, 0, $this->thumbnail_width, $this->thumbnail_height, $background_color); |
||
3693 | } |
||
3694 | } |
||
3695 | $this->DebugMessage('CreateGDoutput() returning canvas "' . $this->thumbnail_width . 'x' . $this->thumbnail_height . '"', __FILE__, __LINE__); |
||
3696 | |||
3697 | return true; |
||
3698 | } |
||
3699 | |||
3700 | /** |
||
3701 | * @return bool |
||
3702 | */ |
||
3703 | public function SetOrientationDependantWidthHeight() |
||
3704 | { |
||
3705 | $this->DebugMessage('SetOrientationDependantWidthHeight() starting with "' . $this->source_width . '"x"' . $this->source_height . '"', __FILE__, __LINE__); |
||
3706 | if ($this->source_height > $this->source_width) { |
||
3707 | // portrait |
||
3708 | $this->w = phpthumb_functions::OneOfThese($this->wp, $this->w, $this->ws, $this->wl); |
||
3709 | $this->h = phpthumb_functions::OneOfThese($this->hp, $this->h, $this->hs, $this->hl); |
||
3710 | } elseif ($this->source_height < $this->source_width) { |
||
3711 | // landscape |
||
3712 | $this->w = phpthumb_functions::OneOfThese($this->wl, $this->w, $this->ws, $this->wp); |
||
3713 | $this->h = phpthumb_functions::OneOfThese($this->hl, $this->h, $this->hs, $this->hp); |
||
3714 | } else { |
||
3715 | // square |
||
3716 | $this->w = phpthumb_functions::OneOfThese($this->ws, $this->w, $this->wl, $this->wp); |
||
3717 | $this->h = phpthumb_functions::OneOfThese($this->hs, $this->h, $this->hl, $this->hp); |
||
3718 | } |
||
3719 | //$this->w = round($this->w ? $this->w : (($this->h && $this->source_height) ? $this->h * $this->source_width / $this->source_height : $this->w)); |
||
3720 | //$this->h = round($this->h ? $this->h : (($this->w && $this->source_width) ? $this->w * $this->source_height / $this->source_width : $this->h)); |
||
3721 | $this->DebugMessage('SetOrientationDependantWidthHeight() setting w="' . (int)$this->w . '", h="' . (int)$this->h . '"', __FILE__, __LINE__); |
||
3722 | |||
3723 | return true; |
||
3724 | } |
||
3725 | |||
3726 | /** |
||
3727 | * @return bool |
||
3728 | */ |
||
3729 | public function ExtractEXIFgetImageSize() |
||
3730 | { |
||
3731 | $this->DebugMessage('starting ExtractEXIFgetImageSize()', __FILE__, __LINE__); |
||
3732 | |||
3733 | if (preg_match('#^http:#i', $this->src) && !$this->sourceFilename && $this->rawImageData) { |
||
3734 | !$this->SourceDataToTempFile(); |
||
3735 | } |
||
3736 | if (is_null($this->getimagesizeinfo)) { |
||
3737 | if ($this->sourceFilename) { |
||
3738 | $this->getimagesizeinfo = @getimagesize($this->sourceFilename); |
||
3739 | $this->source_width = $this->getimagesizeinfo[0]; |
||
3740 | $this->source_height = $this->getimagesizeinfo[1]; |
||
3741 | $this->DebugMessage('GetImageSize(' . $this->sourceFilename . ') says image is ' . $this->source_width . 'x' . $this->source_height, __FILE__, __LINE__); |
||
3742 | } else { |
||
3743 | $this->DebugMessage('skipping GetImageSize() because $this->sourceFilename is empty', __FILE__, __LINE__); |
||
3744 | } |
||
3745 | } else { |
||
3746 | $this->DebugMessage('skipping GetImageSize() because !is_null($this->getimagesizeinfo)', __FILE__, __LINE__); |
||
3747 | } |
||
3748 | |||
3749 | if (is_resource($this->gdimg_source)) { |
||
3750 | $this->source_width = imagesx($this->gdimg_source); |
||
3751 | $this->source_height = imagesy($this->gdimg_source); |
||
3752 | |||
3753 | $this->SetOrientationDependantWidthHeight(); |
||
3754 | } elseif ($this->rawImageData && !$this->sourceFilename) { |
||
3755 | if ($this->SourceImageIsTooLarge($this->source_width, $this->source_height)) { |
||
3756 | $this->DebugMessage('NOT bypassing EXIF and GetImageSize sections because source image is too large for GD (' |
||
3757 | . $this->source_width |
||
3758 | . 'x' |
||
3759 | . $this->source_width |
||
3760 | . '=' |
||
3761 | . ($this->source_width * $this->source_height * 5) |
||
3762 | . 'MB)', __FILE__, __LINE__); |
||
3763 | } else { |
||
3764 | $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 (' |
||
3765 | . $this->source_width |
||
3766 | . 'x' |
||
3767 | . $this->source_width |
||
3768 | . '=' |
||
3769 | . ($this->source_width * $this->source_height * 5) |
||
3770 | . 'MB)', __FILE__, __LINE__); |
||
3771 | } |
||
3772 | } |
||
3773 | |||
3774 | if (is_null($this->getimagesizeinfo)) { |
||
3775 | $this->getimagesizeinfo = @getimagesize($this->sourceFilename); |
||
3776 | } |
||
3777 | |||
3778 | if (!empty($this->getimagesizeinfo)) { |
||
3779 | // great |
||
3780 | $this->getimagesizeinfo['filesize'] = @filesize($this->sourceFilename); |
||
3781 | } elseif (!$this->rawImageData) { |
||
3782 | $this->DebugMessage('GetImageSize("' . $this->sourceFilename . '") failed', __FILE__, __LINE__); |
||
3783 | } |
||
3784 | |||
3785 | if ($this->config_prefer_imagemagick) { |
||
3786 | if ($this->ImageMagickThumbnailToGD()) { |
||
3787 | return true; |
||
3788 | } |
||
3789 | $this->DebugMessage('ImageMagickThumbnailToGD() failed', __FILE__, __LINE__); |
||
3790 | } |
||
3791 | |||
3792 | $this->source_width = $this->getimagesizeinfo[0]; |
||
3793 | $this->source_height = $this->getimagesizeinfo[1]; |
||
3794 | |||
3795 | $this->SetOrientationDependantWidthHeight(); |
||
3796 | |||
3797 | if (phpthumb_functions::version_compare_replacement(PHP_VERSION, '4.2.0', '>=') |
||
3798 | && function_exists('exif_read_data') |
||
3799 | ) { |
||
3800 | switch ($this->getimagesizeinfo[2]) { |
||
3801 | case IMAGETYPE_JPEG: |
||
3802 | case IMAGETYPE_TIFF_II: |
||
3803 | case IMAGETYPE_TIFF_MM: |
||
3804 | $this->exif_raw_data = @exif_read_data($this->sourceFilename, 0, true); |
||
3805 | break; |
||
3806 | } |
||
3807 | } |
||
3808 | if (function_exists('exif_thumbnail') && ($this->getimagesizeinfo[2] == IMAGETYPE_JPEG)) { |
||
3809 | // Extract EXIF info from JPEGs |
||
3810 | |||
3811 | $this->exif_thumbnail_width = ''; |
||
3812 | $this->exif_thumbnail_height = ''; |
||
3813 | $this->exif_thumbnail_type = ''; |
||
3814 | |||
3815 | // The parameters width, height and imagetype are available since PHP v4.3.0 |
||
3816 | if (phpthumb_functions::version_compare_replacement(PHP_VERSION, '4.3.0', '>=')) { |
||
3817 | $this->exif_thumbnail_data = @exif_thumbnail($this->sourceFilename, $this->exif_thumbnail_width, $this->exif_thumbnail_height, $this->exif_thumbnail_type); |
||
3818 | } else { |
||
3819 | |||
3820 | // older versions of exif_thumbnail output an error message but NOT return false on failure |
||
3821 | ob_start(); |
||
3822 | $this->exif_thumbnail_data = exif_thumbnail($this->sourceFilename); |
||
3823 | $exit_thumbnail_error = ob_get_contents(); |
||
3824 | ob_end_clean(); |
||
3825 | if (!$exit_thumbnail_error && $this->exif_thumbnail_data) { |
||
3826 | if ($gdimg_exif_temp = $this->ImageCreateFromStringReplacement($this->exif_thumbnail_data, false)) { |
||
3827 | $this->exif_thumbnail_width = imagesx($gdimg_exif_temp); |
||
3828 | $this->exif_thumbnail_height = imagesy($gdimg_exif_temp); |
||
3829 | $this->exif_thumbnail_type = 2; // (2 == JPEG) before PHP v4.3.0 only JPEG format EXIF thumbnails are returned |
||
3830 | unset($gdimg_exif_temp); |
||
3831 | } else { |
||
3832 | return $this->ErrorImage('Failed - $this->ImageCreateFromStringReplacement($this->exif_thumbnail_data) in ' . __FILE__ . ' on line ' . __LINE__); |
||
3833 | } |
||
3834 | } |
||
3835 | } |
||
3836 | } elseif (!function_exists('exif_thumbnail')) { |
||
3837 | $this->DebugMessage('exif_thumbnail() does not exist, cannot extract EXIF thumbnail', __FILE__, __LINE__); |
||
3838 | } |
||
3839 | |||
3840 | $this->DebugMessage('EXIF thumbnail extraction: (size=' |
||
3841 | . strlen($this->exif_thumbnail_data) |
||
3842 | . '; type="' |
||
3843 | . $this->exif_thumbnail_type |
||
3844 | . '"; ' |
||
3845 | . (int)$this->exif_thumbnail_width |
||
3846 | . 'x' |
||
3847 | . (int)$this->exif_thumbnail_height |
||
3848 | . ')', __FILE__, __LINE__); |
||
3849 | |||
3850 | // see if EXIF thumbnail can be used directly with no processing |
||
3851 | if ($this->config_use_exif_thumbnail_for_speed && $this->exif_thumbnail_data) { |
||
3852 | while (true) { |
||
3853 | if (!$this->xto) { |
||
3854 | $source_ar = $this->source_width / $this->source_height; |
||
3855 | $exif_ar = $this->exif_thumbnail_width / $this->exif_thumbnail_height; |
||
3856 | View Code Duplication | if (number_format($source_ar, 2) != number_format($exif_ar, 2)) { |
|
3857 | $this->DebugMessage('not using EXIF thumbnail because $source_ar != $exif_ar (' . $source_ar . ' != ' . $exif_ar . ')', __FILE__, __LINE__); |
||
3858 | break; |
||
3859 | } |
||
3860 | if ($this->w && ($this->w != $this->exif_thumbnail_width)) { |
||
3861 | $this->DebugMessage('not using EXIF thumbnail because $this->w != $this->exif_thumbnail_width (' . $this->w . ' != ' . $this->exif_thumbnail_width . ')', __FILE__, __LINE__); |
||
3862 | break; |
||
3863 | } |
||
3864 | if ($this->h && ($this->h != $this->exif_thumbnail_height)) { |
||
3865 | $this->DebugMessage('not using EXIF thumbnail because $this->h != $this->exif_thumbnail_height (' . $this->h . ' != ' . $this->exif_thumbnail_height . ')', __FILE__, __LINE__); |
||
3866 | break; |
||
3867 | } |
||
3868 | $CannotBeSetParameters = array('sx', 'sy', 'sh', 'sw', 'far', 'bg', 'bc', 'fltr', 'phpThumbDebug'); |
||
3869 | foreach ($CannotBeSetParameters as $parameter) { |
||
3870 | if ($this->$parameter) { |
||
3871 | break 2; |
||
3872 | } |
||
3873 | } |
||
3874 | } |
||
3875 | |||
3876 | $this->DebugMessage('setting $this->gdimg_source = $this->ImageCreateFromStringReplacement($this->exif_thumbnail_data)', __FILE__, __LINE__); |
||
3877 | $this->gdimg_source = $this->ImageCreateFromStringReplacement($this->exif_thumbnail_data); |
||
3878 | $this->source_width = imagesx($this->gdimg_source); |
||
3879 | $this->source_height = imagesy($this->gdimg_source); |
||
3880 | |||
3881 | return true; |
||
3882 | } |
||
3883 | } |
||
3884 | |||
3885 | if (($this->config_max_source_pixels > 0) |
||
3886 | && (($this->source_width * $this->source_height) > $this->config_max_source_pixels) |
||
3887 | ) { |
||
3888 | |||
3889 | // Source image is larger than would fit in available PHP memory. |
||
3890 | // If ImageMagick is installed, use it to generate the thumbnail. |
||
3891 | // Else, if an EXIF thumbnail is available, use that as the source image. |
||
3892 | // Otherwise, no choice but to fail with an error message |
||
3893 | $this->DebugMessage('image is ' |
||
3894 | . $this->source_width |
||
3895 | . 'x' |
||
3896 | . $this->source_height |
||
3897 | . ' and therefore contains more pixels (' |
||
3898 | . ($this->source_width * $this->source_height) |
||
3899 | . ') than $this->config_max_source_pixels setting (' |
||
3900 | . $this->config_max_source_pixels |
||
3901 | . ')', __FILE__, __LINE__); |
||
3902 | if (!$this->config_prefer_imagemagick && $this->ImageMagickThumbnailToGD()) { |
||
3903 | // excellent, we have a thumbnailed source image |
||
3904 | return true; |
||
3905 | } |
||
3906 | } |
||
3907 | |||
3908 | return true; |
||
3909 | } |
||
3910 | |||
3911 | /** |
||
3912 | * @return bool |
||
3913 | */ |
||
3914 | public function SetCacheFilename() |
||
3915 | { |
||
3916 | if (!is_null($this->cache_filename)) { |
||
3917 | $this->DebugMessage('$this->cache_filename already set, skipping SetCacheFilename()', __FILE__, __LINE__); |
||
3918 | |||
3919 | return true; |
||
3920 | } |
||
3921 | if (is_null($this->config_cache_directory)) { |
||
3922 | $this->setCacheDirectory(); |
||
3923 | if (!$this->config_cache_directory) { |
||
3924 | $this->DebugMessage('SetCacheFilename() failed because $this->config_cache_directory is empty', __FILE__, __LINE__); |
||
3925 | |||
3926 | return false; |
||
3927 | } |
||
3928 | } |
||
3929 | $this->setOutputFormat(); |
||
3930 | |||
3931 | if (!$this->sourceFilename && !$this->rawImageData && $this->src) { |
||
3932 | $this->sourceFilename = $this->ResolveFilenameToAbsolute($this->src); |
||
3933 | } |
||
3934 | |||
3935 | if ($this->config_cache_default_only_suffix && $this->sourceFilename) { |
||
3936 | // simplified cache filenames: |
||
3937 | // only use default parameters in phpThumb.config.php |
||
3938 | // substitute source filename into * in $this->config_cache_default_only_suffix |
||
3939 | // (eg: '*_thumb' becomes 'picture_thumb.jpg') |
||
3940 | if (strpos($this->config_cache_default_only_suffix, '*') === false) { |
||
3941 | $this->DebugMessage('aborting simplified caching filename because no * in "' . $this->config_cache_default_only_suffix . '"', __FILE__, __LINE__); |
||
3942 | } else { |
||
3943 | preg_match('#(.+)(\\.[a-z0-9]+)?$#i', basename($this->sourceFilename), $matches); |
||
3944 | $this->cache_filename = $this->config_cache_directory |
||
3945 | . DIRECTORY_SEPARATOR |
||
3946 | . rawurlencode(str_replace('*', @$matches[1], $this->config_cache_default_only_suffix)) |
||
3947 | . '.' |
||
3948 | . strtolower($this->thumbnailFormat); |
||
3949 | |||
3950 | return true; |
||
3951 | } |
||
3952 | } |
||
3953 | |||
3954 | $this->cache_filename = ''; |
||
3955 | $broad_directory_name = ''; |
||
3956 | if ($this->new) { |
||
3957 | $broad_directory_name = strtolower(md5($this->new)); |
||
3958 | $this->cache_filename .= '_new' . $broad_directory_name; |
||
3959 | } elseif ($this->md5s) { |
||
3960 | // source image MD5 hash provided |
||
3961 | $this->DebugMessage('SetCacheFilename() _raw set from $this->md5s = "' . $this->md5s . '"', __FILE__, __LINE__); |
||
3962 | $broad_directory_name = $this->md5s; |
||
3963 | $this->cache_filename .= '_raw' . $this->md5s; |
||
3964 | } elseif (!$this->src && $this->rawImageData) { |
||
3965 | $this->DebugMessage('SetCacheFilename() _raw set from md5($this->rawImageData) = "' . md5($this->rawImageData) . '"', __FILE__, __LINE__); |
||
3966 | $broad_directory_name = strtolower(md5($this->rawImageData)); |
||
3967 | $this->cache_filename .= '_raw' . $broad_directory_name; |
||
3968 | } else { |
||
3969 | $this->DebugMessage('SetCacheFilename() _src set from md5($this->sourceFilename) "' . $this->sourceFilename . '" = "' . md5($this->sourceFilename) . '"', __FILE__, __LINE__); |
||
3970 | $broad_directory_name = strtolower(md5($this->sourceFilename)); |
||
3971 | $this->cache_filename .= '_src' . $broad_directory_name; |
||
3972 | } |
||
3973 | if (!empty($_SERVER['HTTP_REFERER']) && $this->config_nooffsitelink_enabled) { |
||
3974 | $parsed_url1 = @phpthumb_functions::ParseURLbetter(@$_SERVER['HTTP_REFERER']); |
||
3975 | $parsed_url2 = @phpthumb_functions::ParseURLbetter('http://' . @$_SERVER['HTTP_HOST']); |
||
3976 | if (@$parsed_url1['host'] && @$parsed_url2['host'] && ($parsed_url1['host'] != $parsed_url2['host'])) { |
||
3977 | // include "_offsite" only if nooffsitelink_enabled and if referrer doesn't match the domain of the current server |
||
3978 | $this->cache_filename .= '_offsite'; |
||
3979 | } |
||
3980 | } |
||
3981 | |||
3982 | $ParametersString = ''; |
||
3983 | if ($this->fltr && is_array($this->fltr)) { |
||
3984 | $ParametersString .= '_fltr' . implode('_fltr', $this->fltr); |
||
3985 | } |
||
3986 | $FilenameParameters1 = array('ar', 'bg', 'bc', 'far', 'sx', 'sy', 'sw', 'sh', 'zc'); |
||
3987 | foreach ($FilenameParameters1 as $key) { |
||
3988 | if ($this->$key) { |
||
3989 | $ParametersString .= '_' . $key . $this->$key; |
||
3990 | } |
||
3991 | } |
||
3992 | $FilenameParameters2 = array( |
||
3993 | 'h', |
||
3994 | 'w', |
||
3995 | 'wl', |
||
3996 | 'wp', |
||
3997 | 'ws', |
||
3998 | 'hp', |
||
3999 | 'hs', |
||
4000 | 'xto', |
||
4001 | 'ra', |
||
4002 | 'iar', |
||
4003 | 'aoe', |
||
4004 | 'maxb', |
||
4005 | 'sfn', |
||
4006 | 'dpi' |
||
4007 | ); |
||
4008 | foreach ($FilenameParameters2 as $key) { |
||
4009 | if ($this->$key) { |
||
4010 | $ParametersString .= '_' . $key . (int)$this->$key; |
||
4011 | } |
||
4012 | } |
||
4013 | if ($this->thumbnailFormat == 'jpeg') { |
||
4014 | // only JPEG output has variable quality option |
||
4015 | $ParametersString .= '_q' . (int)$this->thumbnailQuality; |
||
4016 | } |
||
4017 | $this->DebugMessage('SetCacheFilename() _par set from md5(' . $ParametersString . ')', __FILE__, __LINE__); |
||
4018 | $this->cache_filename .= '_par' . strtolower(md5($ParametersString)); |
||
4019 | |||
4020 | if ($this->md5s) { |
||
4021 | // source image MD5 hash provided |
||
4022 | // do not source image modification date -- |
||
4023 | // cached image will be used even if file was modified or removed |
||
4024 | } elseif (!$this->config_cache_source_filemtime_ignore_remote && preg_match('#^(f|ht)tps?\://#i', $this->src)) { |
||
4025 | $this->cache_filename .= '_dat' . (int)phpthumb_functions::filedate_remote($this->src); |
||
4026 | } elseif (!$this->config_cache_source_filemtime_ignore_local && $this->src && !$this->rawImageData) { |
||
4027 | $this->cache_filename .= '_dat' . (int)(@filemtime($this->sourceFilename)); |
||
4028 | } |
||
4029 | |||
4030 | $this->cache_filename .= '.' . strtolower($this->thumbnailFormat); |
||
4031 | $broad_directories = ''; |
||
4032 | for ($i = 0; $i < $this->config_cache_directory_depth; $i++) { |
||
4033 | $broad_directories .= DIRECTORY_SEPARATOR . substr($broad_directory_name, 0, $i + 1); |
||
4034 | } |
||
4035 | |||
4036 | $this->cache_filename = $this->config_cache_directory . $broad_directories . DIRECTORY_SEPARATOR . $this->config_cache_prefix . rawurlencode($this->cache_filename); |
||
4037 | |||
4038 | return true; |
||
4039 | } |
||
4040 | |||
4041 | /** |
||
4042 | * @param $width |
||
4043 | * @param $height |
||
4044 | * @return bool |
||
4045 | */ |
||
4046 | public function SourceImageIsTooLarge($width, $height) |
||
4047 | { |
||
4048 | if (!$this->config_max_source_pixels) { |
||
4049 | return false; |
||
4050 | } |
||
4051 | if ($this->php_memory_limit && function_exists('memory_get_usage')) { |
||
4052 | $available_memory = $this->php_memory_limit - memory_get_usage(); |
||
4053 | |||
4054 | return (bool)(($width * $height * 5) > $available_memory); |
||
4055 | } |
||
4056 | |||
4057 | return (bool)(($width * $height) > $this->config_max_source_pixels); |
||
4058 | } |
||
4059 | |||
4060 | /** |
||
4061 | * @param $filename |
||
4062 | * @return bool|resource |
||
4063 | */ |
||
4064 | public function ImageCreateFromFilename($filename) |
||
4065 | { |
||
4066 | // try to create GD image source directly via GD, if possible, |
||
4067 | // rather than buffering to memory and creating with ImageCreateFromString |
||
4068 | $ImageCreateWasAttempted = false; |
||
4069 | $gd_image = false; |
||
4070 | |||
4071 | $this->DebugMessage('starting ImageCreateFromFilename(' . $filename . ')', __FILE__, __LINE__); |
||
4072 | if ($filename && ($getimagesizeinfo = @getimagesize($filename))) { |
||
4073 | if (!$this->SourceImageIsTooLarge($getimagesizeinfo[0], $getimagesizeinfo[1])) { |
||
4074 | $ImageCreateFromFunction = array( |
||
4075 | 1 => 'ImageCreateFromGIF', |
||
4076 | 2 => 'ImageCreateFromJPEG', |
||
4077 | 3 => 'ImageCreateFromPNG', |
||
4078 | 15 => 'ImageCreateFromWBMP' |
||
4079 | ); |
||
4080 | $this->DebugMessage('ImageCreateFromFilename found ($getimagesizeinfo[2]==' . @$getimagesizeinfo[2] . ')', __FILE__, __LINE__); |
||
4081 | switch (@$getimagesizeinfo[2]) { |
||
4082 | case 1: // GIF |
||
4083 | case 2: // JPEG |
||
4084 | case 3: // PNG |
||
4085 | case 15: // WBMP |
||
4086 | $ImageCreateFromFunctionName = $ImageCreateFromFunction[$getimagesizeinfo[2]]; |
||
4087 | if (function_exists($ImageCreateFromFunctionName)) { |
||
4088 | $this->DebugMessage('Calling ' . $ImageCreateFromFunctionName . '(' . $filename . ')', __FILE__, __LINE__); |
||
4089 | $ImageCreateWasAttempted = true; |
||
4090 | $gd_image = $ImageCreateFromFunctionName($filename); |
||
4091 | } else { |
||
4092 | $this->DebugMessage('NOT calling ' . $ImageCreateFromFunctionName . '(' . $filename . ') because !function_exists(' . $ImageCreateFromFunctionName . ')', __FILE__, |
||
4093 | __LINE__); |
||
4094 | } |
||
4095 | break; |
||
4096 | |||
4097 | case 4: // SWF |
||
4098 | case 5: // PSD |
||
4099 | case 6: // BMP |
||
4100 | case 7: // TIFF (LE) |
||
4101 | case 8: // TIFF (BE) |
||
4102 | case 9: // JPC |
||
4103 | case 10: // JP2 |
||
4104 | case 11: // JPX |
||
4105 | case 12: // JB2 |
||
4106 | case 13: // SWC |
||
4107 | case 14: // IFF |
||
4108 | case 16: // XBM |
||
4109 | $this->DebugMessage('No built-in image creation function for image type "' . @$getimagesizeinfo[2] . '" ($getimagesizeinfo[2])', __FILE__, __LINE__); |
||
4110 | break; |
||
4111 | |||
4112 | default: |
||
4113 | $this->DebugMessage('Unknown value for $getimagesizeinfo[2]: "' . @$getimagesizeinfo[2] . '"', __FILE__, __LINE__); |
||
4114 | break; |
||
4115 | } |
||
4116 | } else { |
||
4117 | $this->DebugMessage('image is ' |
||
4118 | . $getimagesizeinfo[0] |
||
4119 | . 'x' |
||
4120 | . $getimagesizeinfo[1] |
||
4121 | . ' and therefore contains more pixels (' |
||
4122 | . ($getimagesizeinfo[0] * $getimagesizeinfo[1]) |
||
4123 | . ') than $this->config_max_source_pixels setting (' |
||
4124 | . $this->config_max_source_pixels |
||
4125 | . ')', __FILE__, __LINE__); |
||
4126 | |||
4127 | return false; |
||
4128 | } |
||
4129 | } else { |
||
4130 | $this->DebugMessage('empty $filename or GetImageSize(' . $filename . ') failed', __FILE__, __LINE__); |
||
4131 | } |
||
4132 | |||
4133 | if (!$gd_image) { |
||
4134 | // cannot create from filename, attempt to create source image with ImageCreateFromString, if possible |
||
4135 | if ($ImageCreateWasAttempted) { |
||
4136 | $this->DebugMessage(@$ImageCreateFromFunctionName . '() was attempted but FAILED', __FILE__, __LINE__); |
||
4137 | } |
||
4138 | $this->DebugMessage('Populating $rawimagedata', __FILE__, __LINE__); |
||
4139 | $rawimagedata = ''; |
||
4140 | if ($fp = @fopen($filename, 'rb')) { |
||
4141 | $filesize = filesize($filename); |
||
4142 | $blocksize = 8192; |
||
4143 | $blockreads = ceil($filesize / $blocksize); |
||
4144 | for ($i = 0; $i < $blockreads; $i++) { |
||
4145 | $rawimagedata .= fread($fp, $blocksize); |
||
4146 | } |
||
4147 | fclose($fp); |
||
4148 | } else { |
||
4149 | $this->DebugMessage('cannot fopen(' . $filename . ')', __FILE__, __LINE__); |
||
4150 | } |
||
4151 | if ($rawimagedata) { |
||
4152 | $this->DebugMessage('attempting ImageCreateFromStringReplacement($rawimagedata (' . strlen($rawimagedata) . ' bytes), true)', __FILE__, __LINE__); |
||
4153 | $gd_image = $this->ImageCreateFromStringReplacement($rawimagedata, true); |
||
4154 | } |
||
4155 | } |
||
4156 | |||
4157 | return $gd_image; |
||
4158 | } |
||
4159 | |||
4160 | /** |
||
4161 | * @return bool |
||
4162 | */ |
||
4163 | public function SourceImageToGD() |
||
4164 | { |
||
4165 | if (is_resource($this->gdimg_source)) { |
||
4166 | $this->source_width = imagesx($this->gdimg_source); |
||
4167 | $this->source_height = imagesy($this->gdimg_source); |
||
4168 | $this->DebugMessage('skipping SourceImageToGD() because $this->gdimg_source is already a resource (' . $this->source_width . 'x' . $this->source_height . ')', __FILE__, __LINE__); |
||
4169 | |||
4170 | return true; |
||
4171 | } |
||
4172 | $this->DebugMessage('starting SourceImageToGD()', __FILE__, __LINE__); |
||
4173 | |||
4174 | if ($this->config_prefer_imagemagick) { |
||
4175 | if (empty($this->sourceFilename) && !empty($this->rawImageData)) { |
||
4176 | $this->DebugMessage('Copying raw image data to temp file and trying again with ImageMagick', __FILE__, __LINE__); |
||
4177 | if ($tempnam = $this->phpThumb_tempnam()) { |
||
4178 | if (file_put_contents($tempnam, $this->rawImageData)) { |
||
4179 | $this->sourceFilename = $tempnam; |
||
4180 | if ($this->ImageMagickThumbnailToGD()) { |
||
4181 | // excellent, we have a thumbnailed source image |
||
4182 | $this->DebugMessage('ImageMagickThumbnailToGD() succeeded', __FILE__, __LINE__); |
||
4183 | } else { |
||
4184 | $this->DebugMessage('ImageMagickThumbnailToGD() failed', __FILE__, __LINE__); |
||
4185 | } |
||
4186 | } else { |
||
4187 | $this->DebugMessage('failed to put $this->rawImageData into temp file "' . $tempnam . '"', __FILE__, __LINE__); |
||
4188 | } |
||
4189 | } else { |
||
4190 | $this->DebugMessage('failed to generate temp file name', __FILE__, __LINE__); |
||
4191 | } |
||
4192 | } |
||
4193 | } |
||
4194 | if (!$this->gdimg_source && $this->rawImageData) { |
||
4195 | if ($this->SourceImageIsTooLarge($this->source_width, $this->source_height)) { |
||
4196 | $memory_get_usage = (function_exists('memory_get_usage') ? memory_get_usage() : 0); |
||
4197 | |||
4198 | return $this->ErrorImage('Source image is too large (' |
||
4199 | . $this->source_width |
||
4200 | . 'x' |
||
4201 | . $this->source_height |
||
4202 | . ' = ' |
||
4203 | . number_format($this->source_width * $this->source_height / 1000000, 1) |
||
4204 | . 'Mpx, max=' |
||
4205 | . number_format($this->config_max_source_pixels / 1000000, 1) |
||
4206 | . 'Mpx) for GD creation (either install ImageMagick or increase PHP memory_limit to at least ' |
||
4207 | . ceil(($memory_get_usage + (5 * $this->source_width * $this->source_height)) / 1048576) |
||
4208 | . 'M).'); |
||
4209 | } |
||
4210 | View Code Duplication | if ($this->md5s && ($this->md5s != md5($this->rawImageData))) { |
|
4211 | return $this->ErrorImage('$this->md5s != md5($this->rawImageData)' . "\n" . '"' . $this->md5s . '" != ' . "\n" . '"' . md5($this->rawImageData) . '"'); |
||
4212 | } |
||
4213 | //if ($this->issafemode) { |
||
4214 | // return $this->ErrorImage('Cannot generate thumbnails from raw image data when PHP SAFE_MODE enabled'); |
||
4215 | //} |
||
4216 | $this->gdimg_source = $this->ImageCreateFromStringReplacement($this->rawImageData); |
||
4217 | if (!$this->gdimg_source) { |
||
4218 | if (substr($this->rawImageData, 0, 2) === 'BM') { |
||
4219 | $this->getimagesizeinfo[2] = 6; // BMP |
||
4220 | } elseif (substr($this->rawImageData, 0, 4) === 'II' . "\x2A\x00") { |
||
4221 | $this->getimagesizeinfo[2] = 7; // TIFF (littlendian) |
||
4222 | } elseif (substr($this->rawImageData, 0, 4) === 'MM' . "\x00\x2A") { |
||
4223 | $this->getimagesizeinfo[2] = 8; // TIFF (bigendian) |
||
4224 | } |
||
4225 | $this->DebugMessage('SourceImageToGD.ImageCreateFromStringReplacement() failed with unknown image type "' |
||
4226 | . substr($this->rawImageData, 0, 4) |
||
4227 | . '" (' |
||
4228 | . phpthumb_functions::HexCharDisplay(substr($this->rawImageData, 0, 4)) |
||
4229 | . ')', __FILE__, __LINE__); |
||
4230 | // return $this->ErrorImage('Unknown image type identified by "'.substr($this->rawImageData, 0, 4).'" ('.phpthumb_functions::HexCharDisplay(substr($this->rawImageData, 0, 4)).') in SourceImageToGD()['.__LINE__.']'); |
||
4231 | } |
||
4232 | } elseif (!$this->gdimg_source && $this->sourceFilename) { |
||
4233 | View Code Duplication | if ($this->md5s && ($this->md5s != phpthumb_functions::md5_file_safe($this->sourceFilename))) { |
|
4234 | return $this->ErrorImage('$this->md5s != md5(sourceFilename)' . "\n" . '"' . $this->md5s . '" != ' . "\n" . '"' . phpthumb_functions::md5_file_safe($this->sourceFilename) . '"'); |
||
4235 | } |
||
4236 | switch (@$this->getimagesizeinfo[2]) { |
||
4237 | case 1: |
||
4238 | case 3: |
||
4239 | // GIF or PNG input file may have transparency |
||
4240 | $this->is_alpha = true; |
||
4241 | break; |
||
4242 | } |
||
4243 | if (!$this->SourceImageIsTooLarge($this->source_width, $this->source_height)) { |
||
4244 | $this->gdimg_source = $this->ImageCreateFromFilename($this->sourceFilename); |
||
4245 | } |
||
4246 | } |
||
4247 | |||
4248 | while (true) { |
||
4249 | if ($this->gdimg_source) { |
||
4250 | $this->DebugMessage('Not using EXIF thumbnail data because $this->gdimg_source is already set', __FILE__, __LINE__); |
||
4251 | break; |
||
4252 | } |
||
4253 | if (!$this->exif_thumbnail_data) { |
||
4254 | $this->DebugMessage('Not using EXIF thumbnail data because $this->exif_thumbnail_data is empty', __FILE__, __LINE__); |
||
4255 | break; |
||
4256 | } |
||
4257 | if (ini_get('safe_mode')) { |
||
4258 | if (!$this->SourceImageIsTooLarge($this->source_width, $this->source_height)) { |
||
4259 | $this->DebugMessage('Using EXIF thumbnail data because source image too large and safe_mode enabled', __FILE__, __LINE__); |
||
4260 | $this->aoe = true; |
||
4261 | } else { |
||
4262 | break; |
||
4263 | } |
||
4264 | } else { |
||
4265 | if (!$this->config_use_exif_thumbnail_for_speed) { |
||
4266 | $this->DebugMessage('Not using EXIF thumbnail data because $this->config_use_exif_thumbnail_for_speed is FALSE', __FILE__, __LINE__); |
||
4267 | break; |
||
4268 | } |
||
4269 | if (($this->thumbnailCropX != 0) || ($this->thumbnailCropY != 0)) { |
||
4270 | $this->DebugMessage('Not using EXIF thumbnail data because source cropping is enabled (' . $this->thumbnailCropX . ',' . $this->thumbnailCropY . ')', __FILE__, __LINE__); |
||
4271 | break; |
||
4272 | } |
||
4273 | if (($this->w > $this->exif_thumbnail_width) || ($this->h > $this->exif_thumbnail_height)) { |
||
4274 | $this->DebugMessage('Not using EXIF thumbnail data because EXIF thumbnail is too small (' |
||
4275 | . $this->exif_thumbnail_width |
||
4276 | . 'x' |
||
4277 | . $this->exif_thumbnail_height |
||
4278 | . ' vs ' |
||
4279 | . $this->w |
||
4280 | . 'x' |
||
4281 | . $this->h |
||
4282 | . ')', __FILE__, __LINE__); |
||
4283 | break; |
||
4284 | } |
||
4285 | $source_ar = $this->source_width / $this->source_height; |
||
4286 | $exif_ar = $this->exif_thumbnail_width / $this->exif_thumbnail_height; |
||
4287 | View Code Duplication | if (number_format($source_ar, 2) != number_format($exif_ar, 2)) { |
|
4288 | $this->DebugMessage('not using EXIF thumbnail because $source_ar != $exif_ar (' . $source_ar . ' != ' . $exif_ar . ')', __FILE__, __LINE__); |
||
4289 | break; |
||
4290 | } |
||
4291 | } |
||
4292 | |||
4293 | // EXIF thumbnail exists, and is equal to or larger than destination thumbnail, and will be use as source image |
||
4294 | $this->DebugMessage('Trying to use EXIF thumbnail as source image', __FILE__, __LINE__); |
||
4295 | |||
4296 | if ($gdimg_exif_temp = $this->ImageCreateFromStringReplacement($this->exif_thumbnail_data, false)) { |
||
4297 | $this->DebugMessage('Successfully using EXIF thumbnail as source image', __FILE__, __LINE__); |
||
4298 | $this->gdimg_source = $gdimg_exif_temp; |
||
4299 | $this->source_width = $this->exif_thumbnail_width; |
||
4300 | $this->source_height = $this->exif_thumbnail_height; |
||
4301 | $this->thumbnailCropW = $this->source_width; |
||
4302 | $this->thumbnailCropH = $this->source_height; |
||
4303 | |||
4304 | return true; |
||
4305 | } else { |
||
4306 | $this->DebugMessage('$this->ImageCreateFromStringReplacement($this->exif_thumbnail_data, false) failed', __FILE__, __LINE__); |
||
4307 | } |
||
4308 | |||
4309 | break; |
||
4310 | } |
||
4311 | |||
4312 | if (!$this->gdimg_source) { |
||
4313 | $this->DebugMessage('$this->gdimg_source is still empty', __FILE__, __LINE__); |
||
4314 | |||
4315 | $this->DebugMessage('ImageMagickThumbnailToGD() failed', __FILE__, __LINE__); |
||
4316 | |||
4317 | $imageHeader = ''; |
||
4318 | $gd_info = gd_info(); |
||
4319 | $GDreadSupport = false; |
||
4320 | switch (@$this->getimagesizeinfo[2]) { |
||
4321 | case 1: |
||
4322 | $imageHeader = 'Content-Type: image/gif'; |
||
4323 | $GDreadSupport = (bool)@$gd_info['GIF Read Support']; |
||
4324 | break; |
||
4325 | case 2: |
||
4326 | $imageHeader = 'Content-Type: image/jpeg'; |
||
4327 | $GDreadSupport = (bool)@$gd_info['JPG Support']; |
||
4328 | break; |
||
4329 | case 3: |
||
4330 | $imageHeader = 'Content-Type: image/png'; |
||
4331 | $GDreadSupport = (bool)@$gd_info['PNG Support']; |
||
4332 | break; |
||
4333 | } |
||
4334 | if ($imageHeader) { |
||
4335 | // cannot create image for whatever reason (maybe ImageCreateFromJPEG et al are not available?) |
||
4336 | // and ImageMagick is not available either, no choice but to output original (not resized/modified) data and exit |
||
4337 | if ($this->config_error_die_on_source_failure) { |
||
4338 | $errormessages = array(); |
||
4339 | $errormessages[] = 'All attempts to create GD image source failed.'; |
||
4340 | if ($this->fatalerror) { |
||
4341 | $errormessages[] = $this->fatalerror; |
||
4342 | } |
||
4343 | if ($this->issafemode) { |
||
4344 | $errormessages[] = 'Safe Mode enabled, therefore ImageMagick is unavailable. (disable Safe Mode if possible)'; |
||
4345 | } elseif (!$this->ImageMagickVersion()) { |
||
4346 | $errormessages[] = 'ImageMagick is not installed (it is highly recommended that you install it).'; |
||
4347 | } |
||
4348 | if ($this->SourceImageIsTooLarge($this->getimagesizeinfo[0], $this->getimagesizeinfo[1])) { |
||
4349 | $memory_get_usage = (function_exists('memory_get_usage') ? memory_get_usage() : 0); |
||
4350 | $errormessages[] = 'Source image is too large (' |
||
4351 | . $this->getimagesizeinfo[0] |
||
4352 | . 'x' |
||
4353 | . $this->getimagesizeinfo[1] |
||
4354 | . ' = ' |
||
4355 | . number_format($this->getimagesizeinfo[0] |
||
4356 | * $this->getimagesizeinfo[1] |
||
4357 | / 1000000, 1) |
||
4358 | . 'Mpx, max=' |
||
4359 | . number_format($this->config_max_source_pixels / 1000000, 1) |
||
4360 | . 'Mpx) for GD creation (either install ImageMagick or increase PHP memory_limit to at least ' |
||
4361 | . ceil(($memory_get_usage + (5 * $this->getimagesizeinfo[0] * $this->getimagesizeinfo[1])) / 1048576) |
||
4362 | . 'M).'; |
||
4363 | } elseif (!$GDreadSupport) { |
||
4364 | $errormessages[] = 'GD does not have read support for "' . $imageHeader . '".'; |
||
4365 | } else { |
||
4366 | $errormessages[] = 'Source image probably corrupt.'; |
||
4367 | } |
||
4368 | $this->ErrorImage(implode("\n", $errormessages)); |
||
4369 | } else { |
||
4370 | $this->DebugMessage('All attempts to create GD image source failed (' |
||
4371 | . (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 "' |
||
4372 | . $imageHeader |
||
4373 | . '"')) |
||
4374 | . '), cannot generate thumbnail'); |
||
4375 | //$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__); |
||
4376 | //if (!$this->phpThumbDebug) { |
||
4377 | // header($imageHeader); |
||
4378 | // echo $this->rawImageData; |
||
4379 | // exit; |
||
4380 | //} |
||
4381 | return false; |
||
4382 | } |
||
4383 | } |
||
4384 | |||
4385 | //switch (substr($this->rawImageData, 0, 2)) { |
||
4386 | // case 'BM': |
||
4387 | switch (@$this->getimagesizeinfo[2]) { |
||
4388 | case 6: |
||
4389 | ob_start(); |
||
4390 | if (!@require_once __DIR__ . '/phpthumb.bmp.php') { |
||
4391 | ob_end_clean(); |
||
4392 | |||
4393 | return $this->ErrorImage('include_once(' . __DIR__ . '/phpthumb.bmp.php) failed'); |
||
4394 | } |
||
4395 | ob_end_clean(); |
||
4396 | if ($fp = @fopen($this->sourceFilename, 'rb')) { |
||
4397 | $this->rawImageData = ''; |
||
4398 | while (!feof($fp)) { |
||
4399 | $this->rawImageData .= fread($fp, 32768); |
||
4400 | } |
||
4401 | fclose($fp); |
||
4402 | } |
||
4403 | $phpthumb_bmp = new phpthumb_bmp(); |
||
4404 | $this->gdimg_source = $phpthumb_bmp->phpthumb_bmp2gd($this->rawImageData, phpthumb_functions::gd_version() >= 2.0); |
||
4405 | unset($phpthumb_bmp); |
||
4406 | if ($this->gdimg_source) { |
||
4407 | $this->DebugMessage('$phpthumb_bmp->phpthumb_bmp2gd() succeeded', __FILE__, __LINE__); |
||
4408 | } else { |
||
4409 | return $this->ErrorImage($this->ImageMagickVersion() ? 'ImageMagick failed on BMP source conversion' : 'phpthumb_bmp2gd() failed'); |
||
4410 | } |
||
4411 | break; |
||
4412 | //} |
||
4413 | //switch (substr($this->rawImageData, 0, 4)) { |
||
4414 | // case 'II'."\x2A\x00": |
||
4415 | // case 'MM'."\x00\x2A": |
||
4416 | case 7: |
||
4417 | case 8: |
||
4418 | return $this->ErrorImage($this->ImageMagickVersion() ? 'ImageMagick failed on TIFF source conversion' : 'ImageMagick is unavailable and phpThumb() does not support TIFF source images without it'); |
||
4419 | break; |
||
4420 | |||
4421 | //case "\xD7\xCD\xC6\x9A": |
||
4422 | // return $this->ErrorImage($this->ImageMagickVersion() ? 'ImageMagick failed on WMF source conversion' : 'ImageMagick is unavailable and phpThumb() does not support WMF source images without it'); |
||
4423 | // break; |
||
4424 | } |
||
4425 | |||
4426 | if (!$this->gdimg_source) { |
||
4427 | $HeaderFourBytes = ''; |
||
4428 | if ($this->rawImageData) { |
||
4429 | $HeaderFourBytes = substr($this->rawImageData, 0, 4); |
||
4430 | } elseif ($this->sourceFilename) { |
||
4431 | if ($fp = @fopen($this->sourceFilename, 'rb')) { |
||
4432 | $HeaderFourBytes = fread($fp, 4); |
||
4433 | fclose($fp); |
||
4434 | } else { |
||
4435 | return $this->ErrorImage('failed to open "' . $this->sourceFilename . '" SourceImageToGD() [' . __LINE__ . ']'); |
||
4436 | } |
||
4437 | } else { |
||
4438 | return $this->ErrorImage('Unable to create image, neither filename nor image data suppplied in SourceImageToGD() [' . __LINE__ . ']'); |
||
4439 | } |
||
4440 | if (!$this->ImageMagickVersion() && !phpthumb_functions::gd_version()) { |
||
4441 | 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.'); |
||
4442 | } elseif ($HeaderFourBytes == "\xD7\xCD\xC6\x9A") { // WMF |
||
4443 | return $this->ErrorImage($this->ImageMagickVersion() ? 'ImageMagick failed on WMF source conversion' : 'ImageMagick is unavailable and phpThumb() does not support WMF source images without it'); |
||
4444 | } elseif ($HeaderFourBytes == '%PDF') { // "%PDF" |
||
4445 | 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'); |
||
4446 | } elseif (substr($HeaderFourBytes, 0, 3) == "\xFF\xD8\xFF") { // JPEG |
||
4447 | return $this->ErrorImage('Image (JPEG) is too large for PHP-GD memory_limit, please install ImageMagick or increase php.ini memory_limit setting'); |
||
4448 | } elseif ($HeaderFourBytes == '%PNG') { // "%PNG" |
||
4449 | return $this->ErrorImage('Image (PNG) is too large for PHP-GD memory_limit, please install ImageMagick or increase php.ini memory_limit setting'); |
||
4450 | } elseif (substr($HeaderFourBytes, 0, 3) == 'GIF') { // GIF |
||
4451 | return $this->ErrorImage('Image (GIF) is too large for PHP-GD memory_limit, please install ImageMagick or increase php.ini memory_limit setting'); |
||
4452 | } |
||
4453 | |||
4454 | return $this->ErrorImage('Unknown image type identified by "' |
||
4455 | . $HeaderFourBytes |
||
4456 | . '" (' |
||
4457 | . phpthumb_functions::HexCharDisplay($HeaderFourBytes) |
||
4458 | . ') in SourceImageToGD() [' |
||
4459 | . __LINE__ |
||
4460 | . ']'); |
||
4461 | } |
||
4462 | } |
||
4463 | |||
4464 | if (!$this->gdimg_source) { |
||
4465 | if ($gdimg_exif_temp = $this->ImageCreateFromStringReplacement($this->exif_thumbnail_data, false)) { |
||
4466 | $this->DebugMessage('All other attempts failed, but successfully using EXIF thumbnail as source image', __FILE__, __LINE__); |
||
4467 | $this->gdimg_source = $gdimg_exif_temp; |
||
4468 | // override allow-enlarging setting if EXIF thumbnail is the only source available |
||
4469 | // otherwise thumbnails larger than the EXIF thumbnail will be created at EXIF size |
||
4470 | $this->aoe = true; |
||
4471 | |||
4472 | return true; |
||
4473 | } |
||
4474 | |||
4475 | return false; |
||
4476 | } |
||
4477 | |||
4478 | $this->source_width = imagesx($this->gdimg_source); |
||
4479 | $this->source_height = imagesy($this->gdimg_source); |
||
4480 | |||
4481 | return true; |
||
4482 | } |
||
4483 | |||
4484 | /** |
||
4485 | * @param $var |
||
4486 | * @return string |
||
4487 | */ |
||
4488 | public function phpThumbDebugVarDump($var) |
||
4489 | { |
||
4490 | if (is_null($var)) { |
||
4491 | return 'NULL'; |
||
4492 | } elseif (is_bool($var)) { |
||
4493 | return ($var ? 'TRUE' : 'FALSE'); |
||
4494 | } elseif (is_string($var)) { |
||
4495 | return 'string(' . strlen($var) . ')' . str_repeat(' ', max(0, 3 - strlen(strlen($var)))) . ' "' . $var . '"'; |
||
4496 | } elseif (is_int($var)) { |
||
4497 | return 'integer ' . $var; |
||
4498 | } elseif (is_float($var)) { |
||
4499 | return 'float ' . $var; |
||
4500 | } elseif (is_array($var)) { |
||
4501 | ob_start(); |
||
4502 | var_dump($var); |
||
0 ignored issues
–
show
|
|||
4503 | $vardumpoutput = ob_get_contents(); |
||
4504 | ob_end_clean(); |
||
4505 | |||
4506 | return strtr($vardumpoutput, "\n\r\t", ' '); |
||
4507 | } |
||
4508 | |||
4509 | return gettype($var); |
||
4510 | } |
||
4511 | |||
4512 | /** |
||
4513 | * @param string $level |
||
4514 | * @return bool |
||
4515 | */ |
||
4516 | public function phpThumbDebug($level = '') |
||
4517 | { |
||
4518 | if ($level && ($this->phpThumbDebug !== $level)) { |
||
4519 | return true; |
||
4520 | } |
||
4521 | if ($this->config_disable_debug) { |
||
4522 | return $this->ErrorImage('phpThumbDebug disabled'); |
||
4523 | } |
||
4524 | |||
4525 | $FunctionsExistance = array( |
||
4526 | 'exif_thumbnail', |
||
4527 | 'gd_info', |
||
4528 | 'image_type_to_mime_type', |
||
4529 | 'GetImageSize', |
||
4530 | 'ImageCopyResampled', |
||
4531 | 'ImageCopyResized', |
||
4532 | 'ImageCreate', |
||
4533 | 'ImageCreateFromString', |
||
4534 | 'ImageCreateTrueColor', |
||
4535 | 'ImageIsTrueColor', |
||
4536 | 'ImageRotate', |
||
4537 | 'ImageTypes', |
||
4538 | 'version_compare', |
||
4539 | 'ImageCreateFromGIF', |
||
4540 | 'ImageCreateFromJPEG', |
||
4541 | 'ImageCreateFromPNG', |
||
4542 | 'ImageCreateFromWBMP', |
||
4543 | 'ImageCreateFromXBM', |
||
4544 | 'ImageCreateFromXPM', |
||
4545 | 'ImageCreateFromString', |
||
4546 | 'ImageCreateFromGD', |
||
4547 | 'ImageCreateFromGD2', |
||
4548 | 'ImageCreateFromGD2Part', |
||
4549 | 'ImageJPEG', |
||
4550 | 'ImageGIF', |
||
4551 | 'ImagePNG', |
||
4552 | 'ImageWBMP' |
||
4553 | ); |
||
4554 | $ParameterNames = array( |
||
4555 | 'src', |
||
4556 | 'new', |
||
4557 | 'w', |
||
4558 | 'h', |
||
4559 | 'f', |
||
4560 | 'q', |
||
4561 | 'sx', |
||
4562 | 'sy', |
||
4563 | 'sw', |
||
4564 | 'sh', |
||
4565 | 'far', |
||
4566 | 'bg', |
||
4567 | 'bc', |
||
4568 | 'file', |
||
4569 | 'goto', |
||
4570 | 'err', |
||
4571 | 'xto', |
||
4572 | 'ra', |
||
4573 | 'ar', |
||
4574 | 'aoe', |
||
4575 | 'iar', |
||
4576 | 'maxb' |
||
4577 | ); |
||
4578 | $ConfigVariableNames = array( |
||
4579 | 'document_root', |
||
4580 | 'temp_directory', |
||
4581 | 'output_format', |
||
4582 | 'output_maxwidth', |
||
4583 | 'output_maxheight', |
||
4584 | 'error_message_image_default', |
||
4585 | 'error_bgcolor', |
||
4586 | 'error_textcolor', |
||
4587 | 'error_fontsize', |
||
4588 | 'error_die_on_error', |
||
4589 | 'error_silent_die_on_error', |
||
4590 | 'error_die_on_source_failure', |
||
4591 | 'nohotlink_enabled', |
||
4592 | 'nohotlink_valid_domains', |
||
4593 | 'nohotlink_erase_image', |
||
4594 | 'nohotlink_text_message', |
||
4595 | 'nooffsitelink_enabled', |
||
4596 | 'nooffsitelink_valid_domains', |
||
4597 | 'nooffsitelink_require_refer', |
||
4598 | 'nooffsitelink_erase_image', |
||
4599 | 'nooffsitelink_text_message', |
||
4600 | 'high_security_enabled', |
||
4601 | 'allow_src_above_docroot', |
||
4602 | 'allow_src_above_phpthumb', |
||
4603 | 'max_source_pixels', |
||
4604 | 'use_exif_thumbnail_for_speed', |
||
4605 | 'border_hexcolor', |
||
4606 | 'background_hexcolor', |
||
4607 | 'ttf_directory', |
||
4608 | 'disable_pathinfo_parsing', |
||
4609 | 'disable_imagecopyresampled' |
||
4610 | ); |
||
4611 | $OtherVariableNames = array( |
||
4612 | 'phpThumbDebug', |
||
4613 | 'thumbnailQuality', |
||
4614 | 'thumbnailFormat', |
||
4615 | 'gdimg_output', |
||
4616 | 'gdimg_source', |
||
4617 | 'sourceFilename', |
||
4618 | 'source_width', |
||
4619 | 'source_height', |
||
4620 | 'thumbnailCropX', |
||
4621 | 'thumbnailCropY', |
||
4622 | 'thumbnailCropW', |
||
4623 | 'thumbnailCropH', |
||
4624 | 'exif_thumbnail_width', |
||
4625 | 'exif_thumbnail_height', |
||
4626 | 'exif_thumbnail_type', |
||
4627 | 'thumbnail_width', |
||
4628 | 'thumbnail_height', |
||
4629 | 'thumbnail_image_width', |
||
4630 | 'thumbnail_image_height' |
||
4631 | ); |
||
4632 | |||
4633 | $DebugOutput = array(); |
||
4634 | $DebugOutput[] = 'phpThumb() version = ' . $this->phpthumb_version; |
||
4635 | $DebugOutput[] = 'PHP_VERSION = ' . @PHP_VERSION; |
||
4636 | $DebugOutput[] = 'PHP_OS = ' . PHP_OS; |
||
4637 | $DebugOutput[] = '$_SERVER[SERVER_SOFTWARE] = ' . @$_SERVER['SERVER_SOFTWARE']; |
||
4638 | $DebugOutput[] = '__FILE__ = ' . __FILE__; |
||
4639 | $DebugOutput[] = 'realpath(.) = ' . @realpath('.'); |
||
4640 | $DebugOutput[] = '$_SERVER[PHP_SELF] = ' . @$_SERVER['PHP_SELF']; |
||
4641 | $DebugOutput[] = '$_SERVER[HOST_NAME] = ' . @$_SERVER['HOST_NAME']; |
||
4642 | $DebugOutput[] = '$_SERVER[HTTP_REFERER] = ' . @$_SERVER['HTTP_REFERER']; |
||
4643 | $DebugOutput[] = '$_SERVER[QUERY_STRING] = ' . @$_SERVER['QUERY_STRING']; |
||
4644 | $DebugOutput[] = '$_SERVER[PATH_INFO] = ' . @$_SERVER['PATH_INFO']; |
||
4645 | $DebugOutput[] = '$_SERVER[DOCUMENT_ROOT] = ' . @$_SERVER['DOCUMENT_ROOT']; |
||
4646 | $DebugOutput[] = 'getenv(DOCUMENT_ROOT) = ' . @getenv('DOCUMENT_ROOT'); |
||
4647 | $DebugOutput[] = ''; |
||
4648 | |||
4649 | $DebugOutput[] = 'get_magic_quotes_gpc() = ' . $this->phpThumbDebugVarDump(@get_magic_quotes_gpc()); |
||
4650 | $DebugOutput[] = 'get_magic_quotes_runtime() = ' . $this->phpThumbDebugVarDump(@get_magic_quotes_runtime()); |
||
4651 | $DebugOutput[] = 'error_reporting() = ' . $this->phpThumbDebugVarDump(error_reporting()); |
||
4652 | $DebugOutput[] = 'ini_get(error_reporting) = ' . $this->phpThumbDebugVarDump(@ini_get('error_reporting')); |
||
4653 | $DebugOutput[] = 'ini_get(display_errors) = ' . $this->phpThumbDebugVarDump(@ini_get('display_errors')); |
||
4654 | $DebugOutput[] = 'ini_get(allow_url_fopen) = ' . $this->phpThumbDebugVarDump(@ini_get('allow_url_fopen')); |
||
4655 | $DebugOutput[] = 'ini_get(disable_functions) = ' . $this->phpThumbDebugVarDump(@ini_get('disable_functions')); |
||
4656 | $DebugOutput[] = 'get_cfg_var(disable_functions) = ' . $this->phpThumbDebugVarDump(@get_cfg_var('disable_functions')); |
||
4657 | $DebugOutput[] = 'ini_get(safe_mode) = ' . $this->phpThumbDebugVarDump(@ini_get('safe_mode')); |
||
4658 | $DebugOutput[] = 'ini_get(open_basedir) = ' . $this->phpThumbDebugVarDump(@ini_get('open_basedir')); |
||
4659 | $DebugOutput[] = 'ini_get(max_execution_time) = ' . $this->phpThumbDebugVarDump(@ini_get('max_execution_time')); |
||
4660 | $DebugOutput[] = 'ini_get(memory_limit) = ' . $this->phpThumbDebugVarDump(@ini_get('memory_limit')); |
||
4661 | $DebugOutput[] = 'get_cfg_var(memory_limit) = ' . $this->phpThumbDebugVarDump(@get_cfg_var('memory_limit')); |
||
4662 | $DebugOutput[] = 'memory_get_usage() = ' . (function_exists('memory_get_usage') ? $this->phpThumbDebugVarDump(@memory_get_usage()) : 'n/a'); |
||
4663 | $DebugOutput[] = ''; |
||
4664 | |||
4665 | $DebugOutput[] = '$this->config_prefer_imagemagick = ' . $this->phpThumbDebugVarDump($this->config_prefer_imagemagick); |
||
4666 | $DebugOutput[] = '$this->config_imagemagick_path = ' . $this->phpThumbDebugVarDump($this->config_imagemagick_path); |
||
4667 | $DebugOutput[] = '$this->ImageMagickWhichConvert() = ' . $this->ImageMagickWhichConvert(); |
||
4668 | $IMpathUsed = ($this->config_imagemagick_path ?: $this->ImageMagickWhichConvert()); |
||
4669 | $DebugOutput[] = '[actual ImageMagick path used] = ' . $this->phpThumbDebugVarDump($IMpathUsed); |
||
4670 | $DebugOutput[] = 'file_exists([actual ImageMagick path used]) = ' . $this->phpThumbDebugVarDump(@file_exists($IMpathUsed)); |
||
4671 | $DebugOutput[] = 'ImageMagickVersion(false) = ' . $this->ImageMagickVersion(false); |
||
4672 | $DebugOutput[] = 'ImageMagickVersion(true) = ' . $this->ImageMagickVersion(true); |
||
4673 | $DebugOutput[] = ''; |
||
4674 | |||
4675 | $DebugOutput[] = '$this->config_cache_directory = ' . $this->phpThumbDebugVarDump($this->config_cache_directory); |
||
4676 | $DebugOutput[] = '$this->config_cache_directory_depth = ' . $this->phpThumbDebugVarDump($this->config_cache_directory_depth); |
||
4677 | $DebugOutput[] = '$this->config_cache_disable_warning = ' . $this->phpThumbDebugVarDump($this->config_cache_disable_warning); |
||
4678 | $DebugOutput[] = '$this->config_cache_maxage = ' . $this->phpThumbDebugVarDump($this->config_cache_maxage); |
||
4679 | $DebugOutput[] = '$this->config_cache_maxsize = ' . $this->phpThumbDebugVarDump($this->config_cache_maxsize); |
||
4680 | $DebugOutput[] = '$this->config_cache_maxfiles = ' . $this->phpThumbDebugVarDump($this->config_cache_maxfiles); |
||
4681 | $DebugOutput[] = '$this->config_cache_force_passthru = ' . $this->phpThumbDebugVarDump($this->config_cache_force_passthru); |
||
4682 | $DebugOutput[] = '$this->cache_filename = ' . $this->phpThumbDebugVarDump($this->cache_filename); |
||
4683 | $DebugOutput[] = 'is_readable($this->config_cache_directory) = ' . $this->phpThumbDebugVarDump(@is_readable($this->config_cache_directory)); |
||
4684 | $DebugOutput[] = 'is_writable($this->config_cache_directory) = ' . $this->phpThumbDebugVarDump(@is_writable($this->config_cache_directory)); |
||
4685 | $DebugOutput[] = 'is_readable($this->cache_filename) = ' . $this->phpThumbDebugVarDump(@is_readable($this->cache_filename)); |
||
4686 | $DebugOutput[] = 'is_writable($this->cache_filename) = ' . (@file_exists($this->cache_filename) ? $this->phpThumbDebugVarDump(@is_writable($this->cache_filename)) : 'n/a'); |
||
4687 | $DebugOutput[] = ''; |
||
4688 | |||
4689 | foreach ($ConfigVariableNames as $varname) { |
||
4690 | $varname = 'config_' . $varname; |
||
4691 | $value = $this->$varname; |
||
4692 | $DebugOutput[] = '$this->' . str_pad($varname, 37, ' ', STR_PAD_RIGHT) . ' = ' . $this->phpThumbDebugVarDump($value); |
||
4693 | } |
||
4694 | $DebugOutput[] = ''; |
||
4695 | View Code Duplication | foreach ($OtherVariableNames as $varname) { |
|
4696 | $value = $this->$varname; |
||
4697 | $DebugOutput[] = '$this->' . str_pad($varname, 27, ' ', STR_PAD_RIGHT) . ' = ' . $this->phpThumbDebugVarDump($value); |
||
4698 | } |
||
4699 | $DebugOutput[] = 'strlen($this->rawImageData) = ' . strlen(@$this->rawImageData); |
||
4700 | $DebugOutput[] = 'strlen($this->exif_thumbnail_data) = ' . strlen(@$this->exif_thumbnail_data); |
||
4701 | $DebugOutput[] = ''; |
||
4702 | |||
4703 | View Code Duplication | foreach ($ParameterNames as $varname) { |
|
4704 | $value = $this->$varname; |
||
4705 | $DebugOutput[] = '$this->' . str_pad($varname, 4, ' ', STR_PAD_RIGHT) . ' = ' . $this->phpThumbDebugVarDump($value); |
||
4706 | } |
||
4707 | $DebugOutput[] = ''; |
||
4708 | |||
4709 | foreach ($FunctionsExistance as $functionname) { |
||
4710 | $DebugOutput[] = 'builtin_function_exists(' |
||
4711 | . $functionname |
||
4712 | . ')' |
||
4713 | . str_repeat(' ', 23 - strlen($functionname)) |
||
4714 | . ' = ' |
||
4715 | . $this->phpThumbDebugVarDump(phpthumb_functions::builtin_function_exists($functionname)); |
||
4716 | } |
||
4717 | $DebugOutput[] = ''; |
||
4718 | |||
4719 | $gd_info = gd_info(); |
||
4720 | View Code Duplication | foreach ($gd_info as $key => $value) { |
|
4721 | $DebugOutput[] = 'gd_info.' . str_pad($key, 34, ' ', STR_PAD_RIGHT) . ' = ' . $this->phpThumbDebugVarDump($value); |
||
4722 | } |
||
4723 | $DebugOutput[] = ''; |
||
4724 | |||
4725 | $exif_info = phpthumb_functions::exif_info(); |
||
4726 | View Code Duplication | foreach ($exif_info as $key => $value) { |
|
4727 | $DebugOutput[] = 'exif_info.' . str_pad($key, 26, ' ', STR_PAD_RIGHT) . ' = ' . $this->phpThumbDebugVarDump($value); |
||
4728 | } |
||
4729 | $DebugOutput[] = ''; |
||
4730 | |||
4731 | if ($ApacheLookupURIarray = phpthumb_functions::ApacheLookupURIarray(dirname(@$_SERVER['PHP_SELF']))) { |
||
4732 | View Code Duplication | foreach ($ApacheLookupURIarray as $key => $value) { |
|
4733 | $DebugOutput[] = 'ApacheLookupURIarray.' . str_pad($key, 15, ' ', STR_PAD_RIGHT) . ' = ' . $this->phpThumbDebugVarDump($value); |
||
4734 | } |
||
4735 | } else { |
||
4736 | $DebugOutput[] = 'ApacheLookupURIarray() -- FAILED'; |
||
4737 | } |
||
4738 | $DebugOutput[] = ''; |
||
4739 | |||
4740 | View Code Duplication | if (isset($_GET) && is_array($_GET)) { |
|
4741 | foreach ($_GET as $key => $value) { |
||
4742 | $DebugOutput[] = '$_GET[' . $key . ']' . str_repeat(' ', 30 - strlen($key)) . '= ' . $this->phpThumbDebugVarDump($value); |
||
4743 | } |
||
4744 | } |
||
4745 | View Code Duplication | if (isset($_POST) && is_array($_POST)) { |
|
4746 | foreach ($_POST as $key => $value) { |
||
4747 | $DebugOutput[] = '$_POST[' . $key . ']' . str_repeat(' ', 29 - strlen($key)) . '= ' . $this->phpThumbDebugVarDump($value); |
||
4748 | } |
||
4749 | } |
||
4750 | $DebugOutput[] = ''; |
||
4751 | |||
4752 | $DebugOutput[] = '$this->debugmessages:'; |
||
4753 | foreach ($this->debugmessages as $errorstring) { |
||
4754 | $DebugOutput[] = ' * ' . $errorstring; |
||
4755 | } |
||
4756 | $DebugOutput[] = ''; |
||
4757 | |||
4758 | $DebugOutput[] = '$this->debugtiming:'; |
||
4759 | foreach ($this->debugtiming as $timestamp => $timingstring) { |
||
4760 | $DebugOutput[] = ' * ' . $timestamp . ' ' . $timingstring; |
||
4761 | } |
||
4762 | $DebugOutput[] = ' * Total processing time: ' . number_format(max(array_keys($this->debugtiming)) - min(array_keys($this->debugtiming)), 6); |
||
4763 | |||
4764 | $this->f = (isset($_GET['f']) ? $_GET['f'] : $this->f); // debug modes 0-2 don't recognize text mode otherwise |
||
4765 | return $this->ErrorImage(implode("\n", $DebugOutput), 700, 500, true); |
||
4766 | } |
||
4767 | |||
4768 | /** |
||
4769 | * @param $text |
||
4770 | * @return bool |
||
4771 | */ |
||
4772 | public function FatalError($text) |
||
4773 | { |
||
4774 | if (is_null($this->fatalerror)) { |
||
4775 | $this->fatalerror = $text; |
||
4776 | } |
||
4777 | |||
4778 | return true; |
||
4779 | } |
||
4780 | |||
4781 | /** |
||
4782 | * @param $text |
||
4783 | * @param int $width |
||
4784 | * @param int $height |
||
4785 | * @param bool $forcedisplay |
||
4786 | * @return bool |
||
4787 | */ |
||
4788 | public function ErrorImage($text, $width = 0, $height = 0, $forcedisplay = false) |
||
4789 | { |
||
4790 | $width = ($width ?: $this->config_error_image_width); |
||
4791 | $height = ($height ?: $this->config_error_image_height); |
||
4792 | |||
4793 | $text = 'phpThumb() v' . $this->phpthumb_version . "\n" . 'http://phpthumb.sourceforge.net' . "\n\n" . ($this->config_disable_debug ? 'Error messages disabled.' |
||
4794 | . "\n\n" |
||
4795 | . 'edit phpThumb.config.php and (temporarily) set' |
||
4796 | . "\n" |
||
4797 | . '$PHPTHUMB_CONFIG[\'disable_debug\'] = false;' |
||
4798 | . "\n" |
||
4799 | . 'to view the details of this error' : $text); |
||
4800 | |||
4801 | $this->FatalError($text); |
||
4802 | $this->DebugMessage($text, __FILE__, __LINE__); |
||
4803 | $this->purgeTempFiles(); |
||
4804 | if ($this->config_error_silent_die_on_error) { |
||
4805 | exit; |
||
4806 | } |
||
4807 | if ($this->phpThumbDebug && !$forcedisplay) { |
||
4808 | return false; |
||
4809 | } |
||
4810 | if (!$this->config_error_die_on_error && !$forcedisplay) { |
||
4811 | return false; |
||
4812 | } |
||
4813 | if ($this->err || $this->config_error_message_image_default) { |
||
4814 | // Show generic custom error image instead of error message |
||
4815 | // for use on production sites where you don't want debug messages |
||
4816 | if (($this->err == 'showerror') || $this->phpThumbDebug) { |
||
4817 | // fall through and actually show error message even if default error image is set |
||
4818 | } else { |
||
4819 | header('Location: ' . ($this->err ?: $this->config_error_message_image_default)); |
||
4820 | exit; |
||
4821 | } |
||
4822 | } |
||
4823 | $this->setOutputFormat(); |
||
4824 | if (!$this->thumbnailFormat || !$this->config_disable_debug || (phpthumb_functions::gd_version() < 1)) { |
||
4825 | $this->thumbnailFormat = 'text'; |
||
4826 | } |
||
4827 | if (@$this->thumbnailFormat == 'text') { |
||
4828 | // bypass all GD functions and output text error message |
||
4829 | if (!headers_sent()) { |
||
4830 | header('Content-type: text/plain'); |
||
4831 | echo $text; |
||
4832 | } else { |
||
4833 | echo '<pre>' . htmlspecialchars($text) . '</pre>'; |
||
4834 | } |
||
4835 | exit; |
||
4836 | } |
||
4837 | |||
4838 | $FontWidth = imagefontwidth($this->config_error_fontsize); |
||
4839 | $FontHeight = imagefontheight($this->config_error_fontsize); |
||
4840 | |||
4841 | $LinesOfText = explode("\n", @wordwrap($text, floor($width / $FontWidth), "\n", true)); |
||
4842 | $height = max($height, count($LinesOfText) * $FontHeight); |
||
4843 | |||
4844 | $headers_file = ''; |
||
4845 | $headers_line = ''; |
||
4846 | if (phpthumb_functions::version_compare_replacement(PHP_VERSION, '4.3.0', '>=') |
||
4847 | && headers_sent($headers_file, $headers_line) |
||
4848 | ) { |
||
4849 | 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>'; |
||
4850 | } elseif (headers_sent()) { |
||
4851 | echo "\n" . '**Headers already sent, dumping error message as text:**<br><pre>' . "\n\n" . $text . "\n" . '</pre>'; |
||
4852 | } elseif ($gdimg_error = imagecreate($width, $height)) { |
||
4853 | $background_color = phpthumb_functions::ImageHexColorAllocate($gdimg_error, $this->config_error_bgcolor, true); |
||
4854 | $text_color = phpthumb_functions::ImageHexColorAllocate($gdimg_error, $this->config_error_textcolor, true); |
||
4855 | imagefilledrectangle($gdimg_error, 0, 0, $width, $height, $background_color); |
||
4856 | $lineYoffset = 0; |
||
4857 | foreach ($LinesOfText as $line) { |
||
4858 | imagestring($gdimg_error, $this->config_error_fontsize, 2, $lineYoffset, $line, $text_color); |
||
4859 | $lineYoffset += $FontHeight; |
||
4860 | } |
||
4861 | if (function_exists('ImageTypes')) { |
||
4862 | $imagetypes = imagetypes(); |
||
4863 | if ($imagetypes & IMG_PNG) { |
||
4864 | header('Content-Type: image/png'); |
||
4865 | imagepng($gdimg_error); |
||
4866 | } elseif ($imagetypes & IMG_GIF) { |
||
4867 | header('Content-Type: image/gif'); |
||
4868 | imagegif($gdimg_error); |
||
4869 | } elseif ($imagetypes & IMG_JPG) { |
||
4870 | header('Content-Type: image/jpeg'); |
||
4871 | imagejpeg($gdimg_error); |
||
4872 | } elseif ($imagetypes & IMG_WBMP) { |
||
4873 | header('Content-Type: image/vnd.wap.wbmp'); |
||
4874 | imagewbmp($gdimg_error); |
||
4875 | } |
||
4876 | } |
||
4877 | imagedestroy($gdimg_error); |
||
4878 | } |
||
4879 | if (!headers_sent()) { |
||
4880 | echo "\n" . '**Failed to send graphical error image, dumping error message as text:**<br>' . "\n\n" . $text; |
||
4881 | } |
||
4882 | exit; |
||
4883 | |||
4884 | return true; |
||
4885 | } |
||
4886 | |||
4887 | /** |
||
4888 | * @param $RawImageData |
||
4889 | * @param bool $DieOnErrors |
||
4890 | * @return bool|resource |
||
4891 | */ |
||
4892 | public function ImageCreateFromStringReplacement(&$RawImageData, $DieOnErrors = false) |
||
4893 | { |
||
4894 | // there are serious bugs in the non-bundled versions of GD which may cause |
||
4895 | // PHP to segfault when calling ImageCreateFromString() - avoid if at all possible |
||
4896 | // when not using a bundled version of GD2 |
||
4897 | if (!phpthumb_functions::gd_version()) { |
||
4898 | if ($DieOnErrors) { |
||
4899 | if (!headers_sent()) { |
||
4900 | // base64-encoded error image in GIF format |
||
4901 | $ERROR_NOGD = 'R0lGODlhIAAgALMAAAAAABQUFCQkJDY2NkZGRldXV2ZmZnJycoaGhpSUlKWlpbe3t8XFxdXV1eTk5P7+/iwAAAAAIAAgAAAE/vDJSau9WILtTAACUinDNijZtAHfCojS4W5H+qxD8xibIDE9h0OwWaRWDIljJSkUJYsN4bihMB8th3IToAKs1VtYM75cyV8sZ8vygtOE5yMKmGbO4jRdICQCjHdlZzwzNW4qZSQmKDaNjhUMBX4BBAlmMywFSRWEmAI6b5gAlhNxokGhooAIK5o/pi9vEw4Lfj4OLTAUpj6IabMtCwlSFw0DCKBoFqwAB04AjI54PyZ+yY3TD0ss2YcVmN/gvpcu4TOyFivWqYJlbAHPpOntvxNAACcmGHjZzAZqzSzcq5fNjxFmAFw9iFRunD1epU6tsIPmFCAJnWYE0FURk7wJDA0MTKpEzoWAAskiAAA7'; |
||
4902 | header('Content-Type: image/gif'); |
||
4903 | echo base64_decode($ERROR_NOGD); |
||
4904 | } else { |
||
4905 | echo '*** ERROR: No PHP-GD support available ***'; |
||
4906 | } |
||
4907 | exit; |
||
4908 | } else { |
||
4909 | $this->DebugMessage('ImageCreateFromStringReplacement() failed: gd_version says "' . phpthumb_functions::gd_version() . '"', __FILE__, __LINE__); |
||
4910 | |||
4911 | return false; |
||
4912 | } |
||
4913 | } |
||
4914 | if (phpthumb_functions::gd_is_bundled()) { |
||
4915 | $this->DebugMessage('ImageCreateFromStringReplacement() calling built-in ImageCreateFromString()', __FILE__, __LINE__); |
||
4916 | |||
4917 | return @imagecreatefromstring($RawImageData); |
||
4918 | } |
||
4919 | if ($this->issafemode) { |
||
4920 | $this->DebugMessage('ImageCreateFromStringReplacement() failed: cannot create temp file in SAFE_MODE', __FILE__, __LINE__); |
||
4921 | |||
4922 | return false; |
||
4923 | } |
||
4924 | |||
4925 | switch (substr($RawImageData, 0, 3)) { |
||
4926 | case 'GIF': |
||
4927 | $ICFSreplacementFunctionName = 'ImageCreateFromGIF'; |
||
4928 | break; |
||
4929 | case "\xFF\xD8\xFF": |
||
4930 | $ICFSreplacementFunctionName = 'ImageCreateFromJPEG'; |
||
4931 | break; |
||
4932 | case "\x89" . 'PN': |
||
4933 | $ICFSreplacementFunctionName = 'ImageCreateFromPNG'; |
||
4934 | break; |
||
4935 | default: |
||
4936 | $this->DebugMessage('ImageCreateFromStringReplacement() failed: unknown fileformat signature "' . phpthumb_functions::HexCharDisplay(substr($RawImageData, 0, 3)) . '"', __FILE__, |
||
4937 | __LINE__); |
||
4938 | |||
4939 | return false; |
||
4940 | break; |
||
4941 | } |
||
4942 | if ($tempnam = $this->phpThumb_tempnam()) { |
||
4943 | if ($fp_tempnam = @fopen($tempnam, 'wb')) { |
||
4944 | fwrite($fp_tempnam, $RawImageData); |
||
4945 | fclose($fp_tempnam); |
||
4946 | if (($ICFSreplacementFunctionName == 'ImageCreateFromGIF') |
||
4947 | && !function_exists($ICFSreplacementFunctionName) |
||
4948 | ) { |
||
4949 | |||
4950 | // Need to create from GIF file, but ImageCreateFromGIF does not exist |
||
4951 | ob_start(); |
||
4952 | if (!@require_once __DIR__ . '/phpthumb.gif.php') { |
||
4953 | $ErrorMessage = 'Failed to include required file "' . __DIR__ . '/phpthumb.gif.php" in ' . __FILE__ . ' on line ' . __LINE__; |
||
4954 | $this->DebugMessage($ErrorMessage, __FILE__, __LINE__); |
||
4955 | } |
||
4956 | ob_end_clean(); |
||
4957 | // gif_loadFileToGDimageResource() cannot read from raw data, write to file first |
||
4958 | if ($tempfilename = $this->phpThumb_tempnam()) { |
||
4959 | if ($fp_tempfile = @fopen($tempfilename, 'wb')) { |
||
4960 | fwrite($fp_tempfile, $RawImageData); |
||
4961 | fclose($fp_tempfile); |
||
4962 | $gdimg_source = gif_loadFileToGDimageResource($tempfilename); |
||
4963 | $this->DebugMessage('gif_loadFileToGDimageResource(' . $tempfilename . ') completed', __FILE__, __LINE__); |
||
4964 | $this->DebugMessage('deleting "' . $tempfilename . '"', __FILE__, __LINE__); |
||
4965 | unlink($tempfilename); |
||
4966 | |||
4967 | return $gdimg_source; |
||
4968 | } else { |
||
4969 | $ErrorMessage = 'Failed to open tempfile in ' . __FILE__ . ' on line ' . __LINE__; |
||
4970 | $this->DebugMessage($ErrorMessage, __FILE__, __LINE__); |
||
4971 | } |
||
4972 | } else { |
||
4973 | $ErrorMessage = 'Failed to open generate tempfile name in ' . __FILE__ . ' on line ' . __LINE__; |
||
4974 | $this->DebugMessage($ErrorMessage, __FILE__, __LINE__); |
||
4975 | } |
||
4976 | } elseif (function_exists($ICFSreplacementFunctionName) |
||
4977 | && ($gdimg_source = @$ICFSreplacementFunctionName($tempnam)) |
||
4978 | ) { |
||
4979 | |||
4980 | // great |
||
4981 | $this->DebugMessage($ICFSreplacementFunctionName . '(' . $tempnam . ') succeeded', __FILE__, __LINE__); |
||
4982 | $this->DebugMessage('deleting "' . $tempnam . '"', __FILE__, __LINE__); |
||
4983 | unlink($tempnam); |
||
4984 | |||
4985 | return $gdimg_source; |
||
4986 | } else { |
||
4987 | |||
4988 | // GD functions not available, or failed to create image |
||
4989 | $this->DebugMessage($ICFSreplacementFunctionName . '(' . $tempnam . ') ' . (function_exists($ICFSreplacementFunctionName) ? 'failed' : 'does not exist'), __FILE__, __LINE__); |
||
4990 | if (isset($_GET['phpThumbDebug'])) { |
||
4991 | $this->phpThumbDebug(); |
||
4992 | } |
||
4993 | } |
||
4994 | } else { |
||
4995 | $ErrorMessage = 'Failed to fopen(' |
||
4996 | . $tempnam |
||
4997 | . ', "wb") in ' |
||
4998 | . __FILE__ |
||
4999 | . ' on line ' |
||
5000 | . __LINE__ |
||
5001 | . "\n" |
||
5002 | . 'You may need to set $PHPTHUMB_CONFIG[temp_directory] in phpThumb.config.php'; |
||
5003 | if ($this->issafemode) { |
||
5004 | $ErrorMessage = 'ImageCreateFromStringReplacement() failed in ' . __FILE__ . ' on line ' . __LINE__ . ': cannot create temp file in SAFE_MODE'; |
||
5005 | } |
||
5006 | $this->DebugMessage($ErrorMessage, __FILE__, __LINE__); |
||
5007 | } |
||
5008 | $this->DebugMessage('deleting "' . $tempnam . '"', __FILE__, __LINE__); |
||
5009 | @unlink($tempnam); |
||
0 ignored issues
–
show
It seems like you do not handle an error condition here. This can introduce security issues, and is generally not recommended.
If you suppress an error, we recommend checking for the error condition explicitly: // For example instead of
@mkdir($dir);
// Better use
if (@mkdir($dir) === false) {
throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
![]() |
|||
5010 | } else { |
||
5011 | $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'; |
||
5012 | if ($this->issafemode) { |
||
5013 | $ErrorMessage = 'ImageCreateFromStringReplacement() failed in ' . __FILE__ . ' on line ' . __LINE__ . ': cannot create temp file in SAFE_MODE'; |
||
5014 | } |
||
5015 | } |
||
5016 | if ($DieOnErrors && $ErrorMessage) { |
||
5017 | return $this->ErrorImage($ErrorMessage); |
||
5018 | } |
||
5019 | |||
5020 | return false; |
||
5021 | } |
||
5022 | |||
5023 | /** |
||
5024 | * @param $dst_im |
||
5025 | * @param $src_im |
||
5026 | * @param $dstX |
||
5027 | * @param $dstY |
||
5028 | * @param $srcX |
||
5029 | * @param $srcY |
||
5030 | * @param $dstW |
||
5031 | * @param $dstH |
||
5032 | * @param $srcW |
||
5033 | * @param $srcH |
||
5034 | * @return bool |
||
5035 | */ |
||
5036 | public function ImageResizeFunction(&$dst_im, &$src_im, $dstX, $dstY, $srcX, $srcY, $dstW, $dstH, $srcW, $srcH) |
||
5037 | { |
||
5038 | $this->DebugMessage('ImageResizeFunction($o, $s, ' . $dstX . ', ' . $dstY . ', ' . $srcX . ', ' . $srcY . ', ' . $dstW . ', ' . $dstH . ', ' . $srcW . ', ' . $srcH . ')', __FILE__, __LINE__); |
||
5039 | if (($dstW == $srcW) && ($dstH == $srcH)) { |
||
5040 | return imagecopy($dst_im, $src_im, $dstX, $dstY, $srcX, $srcY, $srcW, $srcH); |
||
5041 | } |
||
5042 | if (phpthumb_functions::gd_version() >= 2.0) { |
||
5043 | if ($this->config_disable_imagecopyresampled) { |
||
5044 | return phpthumb_functions::ImageCopyResampleBicubic($dst_im, $src_im, $dstX, $dstY, $srcX, $srcY, $dstW, $dstH, $srcW, $srcH); |
||
5045 | } |
||
5046 | |||
5047 | return imagecopyresampled($dst_im, $src_im, $dstX, $dstY, $srcX, $srcY, $dstW, $dstH, $srcW, $srcH); |
||
5048 | } |
||
5049 | |||
5050 | return imagecopyresized($dst_im, $src_im, $dstX, $dstY, $srcX, $srcY, $dstW, $dstH, $srcW, $srcH); |
||
5051 | } |
||
5052 | |||
5053 | /** |
||
5054 | * @return bool |
||
5055 | */ |
||
5056 | public function InitializeTempDirSetting() |
||
5057 | { |
||
5058 | $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 |
||
5059 | $this->config_temp_directory = ($this->config_temp_directory ?: getenv('TMPDIR')); |
||
5060 | $this->config_temp_directory = ($this->config_temp_directory ?: getenv('TMP')); |
||
5061 | $this->config_temp_directory = ($this->config_temp_directory ?: ini_get('upload_tmp_dir')); |
||
5062 | $this->config_temp_directory = $this->realPathSafe($this->config_temp_directory); |
||
5063 | |||
5064 | return true; |
||
5065 | } |
||
5066 | |||
5067 | /** |
||
5068 | * @return mixed|string |
||
5069 | */ |
||
5070 | public function phpThumb_tempnam() |
||
5071 | { |
||
5072 | $this->InitializeTempDirSetting(); |
||
5073 | $tempnam = $this->realPathSafe(tempnam($this->config_temp_directory, 'pThumb')); |
||
5074 | $this->tempFilesToDelete[$tempnam] = $tempnam; |
||
5075 | $this->DebugMessage('phpThumb_tempnam() returning "' . $tempnam . '"', __FILE__, __LINE__); |
||
5076 | |||
5077 | return $tempnam; |
||
5078 | } |
||
5079 | |||
5080 | /** |
||
5081 | * @param $message |
||
5082 | * @param string $file |
||
5083 | * @param string $line |
||
5084 | * @return bool |
||
5085 | */ |
||
5086 | public function DebugMessage($message, $file = '', $line = '') |
||
5087 | { |
||
5088 | $this->debugmessages[] = $message . ($file ? ' in file "' . (basename($file) ?: $file) . '"' : '') . ($line ? ' on line ' . $line : ''); |
||
5089 | |||
5090 | return true; |
||
5091 | } |
||
5092 | |||
5093 | /** |
||
5094 | * @param $message |
||
5095 | * @param string $file |
||
5096 | * @param string $line |
||
5097 | * @param int $timestamp |
||
5098 | * @return bool |
||
5099 | */ |
||
5100 | public function DebugTimingMessage($message, $file = '', $line = '', $timestamp = 0) |
||
5101 | { |
||
5102 | if (!$timestamp) { |
||
5103 | $timestamp = array_sum(explode(' ', microtime())); |
||
5104 | } |
||
5105 | $this->debugtiming[number_format($timestamp, 6, '.', '')] = ': ' . $message . ($file ? ' in file "' . (basename($file) ?: $file) . '"' : '') . ($line ? ' on line ' . $line : ''); |
||
5106 | |||
5107 | return true; |
||
5108 | } |
||
5109 | } |
||
5110 |
If you suppress an error, we recommend checking for the error condition explicitly: