Issues (807)

Security Analysis    not enabled

This project does not seem to handle request data directly as such no vulnerable execution paths were found.

  File Inclusion
File Inclusion enables an attacker to inject custom files into PHP's file loading mechanism, either explicitly passed to include, or for example via PHP's auto-loading mechanism.
  Regex Injection
Regex Injection enables an attacker to execute arbitrary code in your PHP process.
  SQL Injection
SQL Injection enables an attacker to execute arbitrary SQL code on your database server gaining access to user data, or manipulating user data.
  Response Splitting
Response Splitting can be used to send arbitrary responses.
  File Manipulation
File Manipulation enables an attacker to write custom data to files. This potentially leads to injection of arbitrary code on the server.
  Object Injection
Object Injection enables an attacker to inject an object into PHP code, and can lead to arbitrary code execution, file exposure, or file manipulation attacks.
  File Exposure
File Exposure allows an attacker to gain access to local files that he should not be able to access. These files can for example include database credentials, or other configuration files.
  XML Injection
XML Injection enables an attacker to read files on your local filesystem including configuration files, or can be abused to freeze your web-server process.
  Code Injection
Code Injection enables an attacker to execute arbitrary code on the server.
  Variable Injection
Variable Injection enables an attacker to overwrite program variables with custom data, and can lead to further vulnerabilities.
  XPath Injection
XPath Injection enables an attacker to modify the parts of XML document that are read. If that XML document is for example used for authentication, this can lead to further vulnerabilities similar to SQL Injection.
  Other Vulnerability
This category comprises other attack vectors such as manipulating the PHP runtime, loading custom extensions, freezing the runtime, or similar.
  Command Injection
Command Injection enables an attacker to inject a shell command that is execute with the privileges of the web-server. This can be used to expose sensitive data, or gain access of your server.
  LDAP Injection
LDAP Injection enables an attacker to inject LDAP statements potentially granting permission to run unauthorized queries, or modify content inside the LDAP tree.
  Cross-Site Scripting
Cross-Site Scripting enables an attacker to inject code into the response of a web-request that is viewed by other users. It can for example be used to bypass access controls, or even to take over other users' accounts.
  Header Injection
Unfortunately, the security analysis is currently not available for your project. If you are a non-commercial open-source project, please contact support to gain access.

phpthumb/phpthumb.functions.php (21 issues)

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
// phpthumb.functions.php - general support functions       //
9
//                                                         ///
10
//////////////////////////////////////////////////////////////
11
12
class phpthumb_functions
13
{
14
    public static function is_windows()
15
    {
16
        return (strtoupper(substr(PHP_OS, 0, 3)) == 'WIN');
17
    }
18
19
    public static function user_function_exists($functionname)
20
    {
21
        if (function_exists('get_defined_functions')) {
22
            static $get_defined_functions = [];
23
            if (empty($get_defined_functions)) {
24
                $get_defined_functions = get_defined_functions();
25
            }
26
            return in_array(strtolower($functionname), $get_defined_functions['user']);
27
        }
28
        return function_exists($functionname);
29
    }
30
31
    public static function builtin_function_exists($functionname)
32
    {
33
        if (function_exists('get_defined_functions')) {
34
            static $get_defined_functions = [];
35
            if (empty($get_defined_functions)) {
36
                $get_defined_functions = get_defined_functions();
37
            }
38
            return in_array(strtolower($functionname), $get_defined_functions['internal']);
39
        }
40
        return function_exists($functionname);
41
    }
42
43
    public static function version_compare_replacement_sub($version1, $version2, $operator = '')
44
    {
45
        // If you specify the third optional operator argument, you can test for a particular relationship.
46
        // The possible operators are: <, lt, <=, le, >, gt, >=, ge, ==, =, eq, !=, <>, ne respectively.
47
        // Using this argument, the function will return 1 if the relationship is the one specified by the operator, 0 otherwise.
48
49
        // If a part contains special version strings these are handled in the following order:
50
        // (any string not found in this list) < (dev) < (alpha = a) < (beta = b) < (RC = rc) < (#) < (pl = p)
51
        static $versiontype_lookup = [];
52
        if (empty($versiontype_lookup)) {
53
            $versiontype_lookup['dev']   = 10001;
54
            $versiontype_lookup['a']     = 10002;
55
            $versiontype_lookup['alpha'] = 10002;
56
            $versiontype_lookup['b']     = 10003;
57
            $versiontype_lookup['beta']  = 10003;
58
            $versiontype_lookup['RC']    = 10004;
59
            $versiontype_lookup['rc']    = 10004;
60
            $versiontype_lookup['#']     = 10005;
61
            $versiontype_lookup['pl']    = 10006;
62
            $versiontype_lookup['p']     = 10006;
63
        }
64
        $version1 = (isset($versiontype_lookup[$version1]) ? $versiontype_lookup[$version1] : $version1);
65
        $version2 = (isset($versiontype_lookup[$version2]) ? $versiontype_lookup[$version2] : $version2);
66
67
        switch ($operator) {
68
            case '<':
69
            case 'lt':
70
                return (int)($version1 < $version2);
71
                break;
0 ignored issues
show
break is not strictly necessary here and could be removed.

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

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

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

Loading history...
72
            case '<=':
73
            case 'le':
74
                return (int)($version1 <= $version2);
75
                break;
76
            case '>':
77
            case 'gt':
78
                return (int)($version1 > $version2);
79
                break;
80
            case '>=':
81
            case 'ge':
82
                return (int)($version1 >= $version2);
83
                break;
84
            case '==':
85
            case '=':
86
            case 'eq':
87
                return (int)($version1 == $version2);
88
                break;
89
            case '!=':
90
            case '<>':
91
            case 'ne':
92
                return (int)($version1 != $version2);
93
                break;
94
        }
95
        if ($version1 == $version2) {
96
            return 0;
97
        } elseif ($version1 < $version2) {
98
            return -1;
99
        }
100
        return 1;
101
    }
102
103
    public static function version_compare_replacement($version1, $version2, $operator = '')
104
    {
105
        if (function_exists('version_compare')) {
106
            // built into PHP v4.1.0+
107
            return version_compare($version1, $version2, $operator);
108
        }
109
110
        // The function first replaces _, - and + with a dot . in the version strings
111
        $version1 = strtr($version1, '_-+', '...');
112
        $version2 = strtr($version2, '_-+', '...');
113
114
        // and also inserts dots . before and after any non number so that for example '4.3.2RC1' becomes '4.3.2.RC.1'.
115
        // Then it splits the results like if you were using explode('.',$ver). Then it compares the parts starting from left to right.
116
        $version1 = preg_replace('#([\d]+)([A-Z]+)([\d]+)#i', '$1.$2.$3', $version1);
117
        $version2 = preg_replace('#([\d]+)([A-Z]+)([\d]+)#i', '$1.$2.$3', $version2);
118
119
        $parts1      = explode('.', $version1);
120
        $parts2      = explode('.', $version1);
121
        $parts_count = max(count($parts1), count($parts2));
122
        for ($i = 0; $i < $parts_count; $i++) {
123
            $comparison = self::version_compare_replacement_sub($version1, $version2, $operator);
124
            if ($comparison != 0) {
125
                return $comparison;
126
            }
127
        }
128
        return 0;
129
    }
130
131
    public static function escapeshellarg_replacement($arg)
132
    {
133
        if (function_exists('escapeshellarg') && !self::FunctionIsDisabled('escapeshellarg')) {
134
            return escapeshellarg($arg);
135
        }
136
        return '\'' . str_replace('\'', '\\\'', $arg) . '\'';
137
    }
138
139
    public static function phpinfo_array()
140
    {
141
        static $phpinfo_array = [];
142
        if (empty($phpinfo_array)) {
143
            ob_start();
144
            phpinfo();
145
            $phpinfo = ob_get_contents();
146
            ob_end_clean();
147
            $phpinfo_array = explode("\n", $phpinfo);
148
        }
149
        return $phpinfo_array;
150
    }
151
152
    public static function exif_info()
153
    {
154
        static $exif_info = [];
155
        if (empty($exif_info)) {
156
            // based on code by johnschaefer at gmx dot de
157
            // from PHP help on gd_info()
158
            $exif_info     = [
159
                'EXIF Support'           => '',
160
                'EXIF Version'           => '',
161
                'Supported EXIF Version' => '',
162
                'Supported filetypes'    => '',
163
            ];
164
            $phpinfo_array = self::phpinfo_array();
165
            foreach ($phpinfo_array as $line) {
166
                $line = trim(strip_tags($line));
167
                foreach ($exif_info as $key => $value) {
168
                    if (strpos($line, $key) === 0) {
169
                        $newvalue        = trim(str_replace($key, '', $line));
170
                        $exif_info[$key] = $newvalue;
171
                    }
172
                }
173
            }
174
        }
175
        return $exif_info;
176
    }
177
178
    public static function ImageTypeToMIMEtype($imagetype)
179
    {
180
        if (function_exists('image_type_to_mime_type') && ($imagetype >= 1) && ($imagetype <= 18)) {
181
            // PHP v4.3.0+
182
            return image_type_to_mime_type($imagetype);
183
        }
184
        static $image_type_to_mime_type = [
185
            1  => 'image/gif',                     // IMAGETYPE_GIF
186
            2  => 'image/jpeg',                    // IMAGETYPE_JPEG
187
            3  => 'image/png',                     // IMAGETYPE_PNG
188
            4  => 'application/x-shockwave-flash', // IMAGETYPE_SWF
189
            5  => 'image/psd',                     // IMAGETYPE_PSD
190
            6  => 'image/bmp',                     // IMAGETYPE_BMP
191
            7  => 'image/tiff',                    // IMAGETYPE_TIFF_II (intel byte order)
192
            8  => 'image/tiff',                    // IMAGETYPE_TIFF_MM (motorola byte order)
193
            9  => 'application/octet-stream',      // IMAGETYPE_JPC
194
            10 => 'image/jp2',                     // IMAGETYPE_JP2
195
            11 => 'application/octet-stream',      // IMAGETYPE_JPX
196
            12 => 'application/octet-stream',      // IMAGETYPE_JB2
197
            13 => 'application/x-shockwave-flash', // IMAGETYPE_SWC
198
            14 => 'image/iff',                     // IMAGETYPE_IFF
199
            15 => 'image/vnd.wap.wbmp',            // IMAGETYPE_WBMP
200
            16 => 'image/xbm',                     // IMAGETYPE_XBM
201
            17 => 'image/x-icon',                  // IMAGETYPE_ICO
202
            18 => 'image/webp',                    // IMAGETYPE_WEBP
203
204
            'gif'  => 'image/gif',                 // IMAGETYPE_GIF
205
            'jpg'  => 'image/jpeg',                // IMAGETYPE_JPEG
206
            'jpeg' => 'image/jpeg',                // IMAGETYPE_JPEG
207
            'png'  => 'image/png',                 // IMAGETYPE_PNG
208
            'bmp'  => 'image/bmp',                 // IMAGETYPE_BMP
209
            'ico'  => 'image/x-icon',              // IMAGETYPE_ICO
210
            'webp' => 'image/webp',                // IMAGETYPE_WEBP
211
        ];
212
213
        return (isset($image_type_to_mime_type[$imagetype]) ? $image_type_to_mime_type[$imagetype] : false);
214
    }
215
216
    public static function TranslateWHbyAngle($width, $height, $angle)
217
    {
218
        if (($angle % 180) == 0) {
219
            return [$width, $height];
220
        }
221
        $newwidth  = (abs(sin(deg2rad($angle))) * $height) + (abs(cos(deg2rad($angle))) * $width);
222
        $newheight = (abs(sin(deg2rad($angle))) * $width) + (abs(cos(deg2rad($angle))) * $height);
223
        return [$newwidth, $newheight];
224
    }
225
226
    public static function HexCharDisplay($string)
227
    {
228
        $len    = strlen($string);
229
        $output = '';
230
        for ($i = 0; $i < $len; $i++) {
231
            $output .= ' 0x' . str_pad(dechex(ord($string[$i])), 2, '0', STR_PAD_LEFT);
232
        }
233
        return $output;
234
    }
235
236
    public static function IsHexColor($HexColorString)
237
    {
238
        return preg_match('#^[0-9A-F]{6}$#i', $HexColorString);
239
    }
240
241
    public static function ImageColorAllocateAlphaSafe(&$gdimg_hexcolorallocate, $R, $G, $B, $alpha = false)
242
    {
243
        if (self::version_compare_replacement(PHP_VERSION, '4.3.2', '>=') && ($alpha !== false)) {
244
            return imagecolorallocatealpha($gdimg_hexcolorallocate, $R, $G, $B, (int)$alpha);
245
        } else {
246
            return imagecolorallocate($gdimg_hexcolorallocate, $R, $G, $B);
247
        }
248
    }
249
250
    public static function ImageHexColorAllocate(&$gdimg_hexcolorallocate, $HexColorString, $dieOnInvalid = false, $alpha = false)
251
    {
252
        if (!is_resource($gdimg_hexcolorallocate) && !(is_object($gdimg_hexcolorallocate) && $gdimg_hexcolorallocate instanceof \GdImage)) {
253
            die('$gdimg_hexcolorallocate is not a GD resource in ImageHexColorAllocate()');
0 ignored issues
show
Using exit here is not recommended.

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

Loading history...
254
        }
255
        if (self::IsHexColor($HexColorString)) {
256
            $R = hexdec(substr($HexColorString, 0, 2));
257
            $G = hexdec(substr($HexColorString, 2, 2));
258
            $B = hexdec(substr($HexColorString, 4, 2));
259
            return self::ImageColorAllocateAlphaSafe($gdimg_hexcolorallocate, $R, $G, $B, $alpha);
260
        }
261
        if ($dieOnInvalid) {
262
            die('Invalid hex color string: "' . $HexColorString . '"');
0 ignored issues
show
Using exit here is not recommended.

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

Loading history...
263
        }
264
        return imagecolorallocate($gdimg_hexcolorallocate, 0x00, 0x00, 0x00);
265
    }
266
267
    public static function HexColorXOR($hexcolor)
268
    {
269
        return strtoupper(str_pad(dechex(~hexdec($hexcolor) & 0xFFFFFF), 6, '0', STR_PAD_LEFT));
270
    }
271
272
    public static function GetPixelColor(&$img, $x, $y)
273
    {
274
        if (!is_resource($img) && !(is_object($img) && $img instanceof \GdImage)) {
275
            return false;
276
        }
277
        return @imagecolorsforindex($img, @imagecolorat($img, $x, $y));
278
    }
279
280
    public static function PixelColorDifferencePercent($currentPixel, $targetPixel)
281
    {
282
        $diff = 0;
283
        foreach ($targetPixel as $channel => $currentvalue) {
284
            $diff = max($diff, (max($currentPixel[$channel], $targetPixel[$channel]) - min($currentPixel[$channel], $targetPixel[$channel])) / 255);
285
        }
286
        return $diff * 100;
287
    }
288
289
    public static function GrayscaleValue($r, $g, $b)
290
    {
291
        return round(($r * 0.30) + ($g * 0.59) + ($b * 0.11));
292
    }
293
294
    public static function GrayscalePixel($OriginalPixel)
295
    {
296
        $gray = self::GrayscaleValue($OriginalPixel['red'], $OriginalPixel['green'], $OriginalPixel['blue']);
297
        return ['red' => $gray, 'green' => $gray, 'blue' => $gray];
298
    }
299
300
    public static function GrayscalePixelRGB($rgb)
301
    {
302
        $r = ($rgb >> 16) & 0xFF;
303
        $g = ($rgb >> 8) & 0xFF;
304
        $b = $rgb & 0xFF;
305
        return ($r * 0.299) + ($g * 0.587) + ($b * 0.114);
306
    }
307
308
    public static function ScaleToFitInBox($width, $height, $maxwidth = null, $maxheight = null, $allow_enlarge = true, $allow_reduce = true)
309
    {
310
        $maxwidth  = (null === $maxwidth ? $width : $maxwidth);
311
        $maxheight = (null === $maxheight ? $height : $maxheight);
312
        $scale_x   = 1;
313
        $scale_y   = 1;
314
        if (($width > $maxwidth) || ($width < $maxwidth)) {
315
            $scale_x = ($maxwidth / $width);
316
        }
317
        if (($height > $maxheight) || ($height < $maxheight)) {
318
            $scale_y = ($maxheight / $height);
319
        }
320
        $scale = min($scale_x, $scale_y);
321
        if (!$allow_enlarge) {
322
            $scale = min($scale, 1);
323
        }
324
        if (!$allow_reduce) {
325
            $scale = max($scale, 1);
326
        }
327
        return $scale;
328
    }
329
330
    public static function ImageCopyResampleBicubic($dst_img, $src_img, $dst_x, $dst_y, $src_x, $src_y, $dst_w, $dst_h, $src_w, $src_h)
331
    {
332
        // ron at korving dot demon dot nl
333
        // http://www.php.net/imagecopyresampled
334
335
        $scaleX = ($src_w - 1) / $dst_w;
336
        $scaleY = ($src_h - 1) / $dst_h;
337
338
        $scaleX2 = $scaleX / 2.0;
339
        $scaleY2 = $scaleY / 2.0;
340
341
        $isTrueColor = imageistruecolor($src_img);
342
343
        for ($y = $src_y; $y < $src_y + $dst_h; $y++) {
344
            $sY   = $y * $scaleY;
345
            $siY  = (int)$sY;
346
            $siY2 = (int)$sY + $scaleY2;
347
348
            for ($x = $src_x; $x < $src_x + $dst_w; $x++) {
349
                $sX   = $x * $scaleX;
350
                $siX  = (int)$sX;
351
                $siX2 = (int)$sX + $scaleX2;
352
353
                if ($isTrueColor) {
354
                    $c1 = imagecolorat($src_img, $siX, $siY2);
355
                    $c2 = imagecolorat($src_img, $siX, $siY);
356
                    $c3 = imagecolorat($src_img, $siX2, $siY2);
357
                    $c4 = imagecolorat($src_img, $siX2, $siY);
358
359
                    $r = (($c1 + $c2 + $c3 + $c4) >> 2) & 0xFF0000;
360
                    $g = ((($c1 & 0x00FF00) + ($c2 & 0x00FF00) + ($c3 & 0x00FF00) + ($c4 & 0x00FF00)) >> 2) & 0x00FF00;
361
                    $b = ((($c1 & 0x0000FF) + ($c2 & 0x0000FF) + ($c3 & 0x0000FF) + ($c4 & 0x0000FF)) >> 2);
362
                } else {
363
                    $c1 = imagecolorsforindex($src_img, imagecolorat($src_img, $siX, $siY2));
364
                    $c2 = imagecolorsforindex($src_img, imagecolorat($src_img, $siX, $siY));
365
                    $c3 = imagecolorsforindex($src_img, imagecolorat($src_img, $siX2, $siY2));
366
                    $c4 = imagecolorsforindex($src_img, imagecolorat($src_img, $siX2, $siY));
367
368
                    $r = ($c1['red'] + $c2['red'] + $c3['red'] + $c4['red']) << 14;
369
                    $g = ($c1['green'] + $c2['green'] + $c3['green'] + $c4['green']) << 6;
370
                    $b = ($c1['blue'] + $c2['blue'] + $c3['blue'] + $c4['blue']) >> 2;
371
                }
372
                imagesetpixel($dst_img, $dst_x + $x - $src_x, $dst_y + $y - $src_y, $r + $g + $b);
373
            }
374
        }
375
        return true;
376
    }
377
378
    public static function ImageCreateFunction($x_size, $y_size)
379
    {
380
        $ImageCreateFunction = 'imagecreate';
381
        if (self::gd_version() >= 2.0) {
382
            $ImageCreateFunction = 'imagecreatetruecolor';
383
        }
384
        if (!function_exists($ImageCreateFunction)) {
385
            return phpthumb::ErrorImage($ImageCreateFunction . '() does not exist - no GD support?');
0 ignored issues
show
Bug Best Practice introduced by
The method phpthumb::ErrorImage() is not static, but was called statically. ( Ignorable by Annotation )

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

385
            return phpthumb::/** @scrutinizer ignore-call */ ErrorImage($ImageCreateFunction . '() does not exist - no GD support?');
Loading history...
386
        }
387
        if (($x_size <= 0) || ($y_size <= 0)) {
388
            return phpthumb::ErrorImage('Invalid image dimensions: ' . $ImageCreateFunction . '(' . $x_size . ', ' . $y_size . ')');
389
        }
390
        return $ImageCreateFunction(round($x_size), round($y_size));
391
    }
392
393
    public static function ImageCopyRespectAlpha(&$dst_im, &$src_im, $dst_x, $dst_y, $src_x, $src_y, $src_w, $src_h, $opacity_pct = 100)
394
    {
395
        $opacipct = $opacity_pct / 100;
396
        for ($x = $src_x; $x < $src_w; $x++) {
397
            for ($y = $src_y; $y < $src_h; $y++) {
398
                $RealPixel    = self::GetPixelColor($dst_im, $dst_x + $x, $dst_y + $y);
399
                $OverlayPixel = self::GetPixelColor($src_im, $x, $y);
400
                $alphapct     = $OverlayPixel['alpha'] / 127;
401
                $overlaypct   = (1 - $alphapct) * $opacipct;
402
403
                $newcolor = self::ImageColorAllocateAlphaSafe(
404
                    $dst_im,
405
                    $RealPixel['alpha'] == 127 ? $OverlayPixel['red'] : ($OverlayPixel['alpha'] == 127 ? $RealPixel['red'] : (round($RealPixel['red'] * (1 - $overlaypct)) + ($OverlayPixel['red'] * $overlaypct))),
406
                    $RealPixel['alpha'] == 127 ? $OverlayPixel['green'] : ($OverlayPixel['alpha'] == 127 ? $RealPixel['green'] : (round($RealPixel['green'] * (1 - $overlaypct)) + ($OverlayPixel['green'] * $overlaypct))),
407
                    $RealPixel['alpha'] == 127 ? $OverlayPixel['blue'] : ($OverlayPixel['alpha'] == 127 ? $RealPixel['blue'] : (round($RealPixel['blue'] * (1 - $overlaypct)) + ($OverlayPixel['blue'] * $overlaypct))),
408
                    //					0);
409
                    min([$RealPixel['alpha'], floor($OverlayPixel['alpha'] * $opacipct)])
410
                );
411
412
                imagesetpixel($dst_im, $dst_x + $x, $dst_y + $y, $newcolor);
413
            }
414
        }
415
        return true;
416
    }
417
418
    public static function ProportionalResize($old_width, $old_height, $new_width = false, $new_height = false)
419
    {
420
        $old_aspect_ratio = $old_width / $old_height;
421
        if (($new_width === false) && ($new_height === false)) {
422
            return false;
423
        } elseif ($new_width === false) {
424
            $new_width = $new_height * $old_aspect_ratio;
425
        } elseif ($new_height === false) {
426
            $new_height = $new_width / $old_aspect_ratio;
427
        }
428
        $new_aspect_ratio = $new_width / $new_height;
429
        if ($new_aspect_ratio == $old_aspect_ratio) {
430
            // great, done
431
        } elseif ($new_aspect_ratio < $old_aspect_ratio) {
432
            // limited by width
433
            $new_height = $new_width / $old_aspect_ratio;
434
        } elseif ($new_aspect_ratio > $old_aspect_ratio) {
435
            // limited by height
436
            $new_width = $new_height * $old_aspect_ratio;
437
        }
438
        return [
439
            (int)round($new_width),
440
            (int)round($new_height),
441
        ];
442
    }
443
444
    public static function FunctionIsDisabled($function)
445
    {
446
        static $DisabledFunctions = null;
447
        if (null === $DisabledFunctions) {
448
            $disable_functions_local  = explode(',', strtolower(@ini_get('disable_functions')));
0 ignored issues
show
It seems like @ini_get('disable_functions') can also be of type false; however, parameter $string of strtolower() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

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

448
            $disable_functions_local  = explode(',', strtolower(/** @scrutinizer ignore-type */ @ini_get('disable_functions')));
Loading history...
449
            $disable_functions_global = explode(',', strtolower(@get_cfg_var('disable_functions')));
450
            foreach ($disable_functions_local as $key => $value) {
451
                $DisabledFunctions[trim($value)] = 'local';
452
            }
453
            foreach ($disable_functions_global as $key => $value) {
454
                $DisabledFunctions[trim($value)] = 'global';
455
            }
456
            if (@ini_get('safe_mode')) {
457
                $DisabledFunctions['shell_exec']     = 'local';
458
                $DisabledFunctions['set_time_limit'] = 'local';
459
            }
460
        }
461
        return isset($DisabledFunctions[strtolower($function)]);
462
    }
463
464
    public static function SafeExec($command)
465
    {
466
        static $AllowedExecFunctions = [];
467
        if (empty($AllowedExecFunctions)) {
468
            $AllowedExecFunctions = ['shell_exec' => true, 'passthru' => true, 'system' => true, 'exec' => true];
469
            foreach ($AllowedExecFunctions as $key => $value) {
470
                $AllowedExecFunctions[$key] = !self::FunctionIsDisabled($key);
471
            }
472
        }
473
        $command .= ' 2>&1'; // force redirect stderr to stdout
474
        foreach ($AllowedExecFunctions as $execfunction => $is_allowed) {
475
            if (!$is_allowed) {
476
                continue;
477
            }
478
            $returnvalue = false;
479
            switch ($execfunction) {
480
                case 'passthru':
481
                case 'system':
482
                    ob_start();
483
                    $execfunction($command);
484
                    $returnvalue = ob_get_contents();
485
                    ob_end_clean();
486
                    break;
487
488
                case 'exec':
489
                    $output      = [];
490
                    $lastline    = $execfunction($command, $output);
0 ignored issues
show
The assignment to $lastline is dead and can be removed.
Loading history...
491
                    $returnvalue = implode("\n", $output);
492
                    break;
493
494
                case 'shell_exec':
495
                    ob_start();
496
                    $returnvalue = $execfunction($command);
497
                    ob_end_clean();
498
                    break;
499
            }
500
            return $returnvalue;
501
        }
502
        return false;
503
    }
504
505
    public static function ApacheLookupURIarray($filename)
506
    {
507
        // apache_lookup_uri() only works when PHP is installed as an Apache module.
508
        if (PHP_SAPI == 'apache') {
509
            //$property_exists_exists = function_exists('property_exists');
510
            $keys = ['status', 'the_request', 'status_line', 'method', 'content_type', 'handler', 'uri', 'filename', 'path_info', 'args', 'boundary', 'no_cache', 'no_local_copy', 'allowed', 'send_bodyct', 'bytes_sent', 'byterange', 'clength', 'unparsed_uri', 'mtime', 'request_time'];
511
            if ($apacheLookupURIobject = @apache_lookup_uri($filename)) {
512
                $apacheLookupURIarray = [];
513
                foreach ($keys as $key) {
514
                    $apacheLookupURIarray[$key] = @$apacheLookupURIobject->$key;
515
                }
516
                return $apacheLookupURIarray;
517
            }
518
        }
519
        return false;
520
    }
521
522
    public static function gd_is_bundled()
523
    {
524
        static $isbundled = null;
525
        if (null === $isbundled) {
526
            $gd_info   = gd_info();
527
            $isbundled = (strpos($gd_info['GD Version'], 'bundled') !== false);
528
        }
529
        return $isbundled;
530
    }
531
532
    public static function gd_version($fullstring = false)
533
    {
534
        static $cache_gd_version = [];
535
        if (empty($cache_gd_version)) {
536
            $gd_info = gd_info();
537
            if (preg_match('#bundled \((.+)\)$#i', $gd_info['GD Version'], $matches)) {
538
                $cache_gd_version[1] = $gd_info['GD Version'];  // e.g. "bundled (2.0.15 compatible)"
539
                $cache_gd_version[0] = (float)$matches[1];     // e.g. "2.0" (not "bundled (2.0.15 compatible)")
540
            } else {
541
                $cache_gd_version[1] = $gd_info['GD Version'];                       // e.g. "1.6.2 or higher"
542
                $cache_gd_version[0] = (float)substr($gd_info['GD Version'], 0, 3); // e.g. "1.6" (not "1.6.2 or higher")
543
            }
544
        }
545
        return $cache_gd_version[(int)$fullstring];
546
    }
547
548
    public static function filesize_remote($remotefile, $timeout = 10)
549
    {
550
        $size       = false;
551
        $parsed_url = self::ParseURLbetter($remotefile);
552
        if ($fp = @fsockopen($parsed_url['host'], $parsed_url['port'], $errno, $errstr, $timeout)) {
553
            fwrite($fp, 'HEAD ' . $parsed_url['path'] . $parsed_url['query'] . ' HTTP/1.0' . "\r\n" . 'Host: ' . $parsed_url['host'] . "\r\n\r\n");
554
            if (self::version_compare_replacement(PHP_VERSION, '4.3.0', '>=')) {
555
                stream_set_timeout($fp, $timeout);
556
            }
557
            while (!feof($fp)) {
558
                $headerline = fgets($fp, 4096);
559
                if (preg_match('#^Content-Length: (.*)#i', $headerline, $matches)) {
560
                    $size = (int)$matches[1];
561
                    break;
562
                }
563
            }
564
            fclose($fp);
565
        }
566
        return $size;
567
    }
568
569
    public static function filedate_remote($remotefile, $timeout = 10)
570
    {
571
        $date       = false;
572
        $parsed_url = self::ParseURLbetter($remotefile);
573
        if ($fp = @fsockopen($parsed_url['host'], $parsed_url['port'], $errno, $errstr, $timeout)) {
574
            fwrite($fp, 'HEAD ' . $parsed_url['path'] . $parsed_url['query'] . ' HTTP/1.0' . "\r\n" . 'Host: ' . $parsed_url['host'] . "\r\n\r\n");
575
            if (self::version_compare_replacement(PHP_VERSION, '4.3.0', '>=')) {
576
                stream_set_timeout($fp, $timeout);
577
            }
578
            while (!feof($fp)) {
579
                $headerline = fgets($fp, 4096);
580
                if (preg_match('#^Last-Modified: (.*)#i', $headerline, $matches)) {
581
                    $date = strtotime($matches[1]) - date('Z');
582
                    break;
583
                }
584
            }
585
            fclose($fp);
586
        }
587
        return $date;
588
    }
589
590
    public static function md5_file_safe($filename)
591
    {
592
        // md5_file() doesn't exist in PHP < 4.2.0
593
        if (function_exists('md5_file')) {
594
            return md5_file($filename);
595
        }
596
        if ($fp = @fopen($filename, 'rb')) {
597
            $rawData = '';
598
            do {
599
                $buffer  = fread($fp, 8192);
600
                $rawData .= $buffer;
601
            } while (strlen($buffer) > 0);
602
            fclose($fp);
603
            return md5($rawData);
604
        }
605
        return false;
606
    }
607
608
    public static function nonempty_min()
609
    {
610
        $arg_list   = func_get_args();
611
        $acceptable = [];
612
        foreach ($arg_list as $arg) {
613
            if ($arg) {
614
                $acceptable[] = $arg;
615
            }
616
        }
617
        return min($acceptable);
618
    }
619
620
    public static function LittleEndian2String($number, $minbytes = 1)
621
    {
622
        $intstring = '';
623
        while ($number > 0) {
624
            $intstring .= chr($number & 255);
625
            $number    >>= 8;
626
        }
627
        return str_pad($intstring, $minbytes, "\x00", STR_PAD_RIGHT);
628
    }
629
630
    public static function OneOfThese()
631
    {
632
        // return the first useful (non-empty/non-zero/non-false) value from those passed
633
        $arg_list = func_get_args();
634
        foreach ($arg_list as $key => $value) {
635
            if ($value) {
636
                return $value;
637
            }
638
        }
639
        return false;
640
    }
641
642
    public static function CaseInsensitiveInArray($needle, $haystack)
643
    {
644
        $needle = strtolower($needle);
645
        foreach ($haystack as $key => $value) {
646
            if (is_array($value)) {
647
                // skip?
648
            } elseif ($needle == strtolower($value)) {
649
                return true;
650
            }
651
        }
652
        return false;
653
    }
654
655
    public static function URLreadFsock($host, $file, &$errstr, $successonly = true, $port = -1, $timeout = 10)
656
    {
657
        if (!function_exists('fsockopen') || self::FunctionIsDisabled('fsockopen')) {
658
            $errstr = 'URLreadFsock says: function fsockopen() unavailable';
659
            return false;
660
        }
661
        $port = (int)($port ? $port : -1); // passing anything as the $port parameter (even empty values like null, false, 0, "") will override the default -1. fsockopen uses -1 as the default port value.
662
        //if ($fp = @fsockopen($host, $port, $errno, $errstr, $timeout)) {
663
        if ($fp = @fsockopen((($port == 443) ? 'ssl://' : '') . $host, $port, $errno, $errstr, $timeout)) { // https://github.com/JamesHeinrich/phpThumb/issues/39
664
            $out = 'GET ' . $file . ' HTTP/1.0' . "\r\n";
665
            $out .= 'Host: ' . $host . "\r\n";
666
            $out .= 'Connection: Close' . "\r\n\r\n";
667
            fwrite($fp, $out);
668
669
            $isHeader           = true;
670
            $data_header        = '';
671
            $data_body          = '';
672
            $header_newlocation = '';
673
            while (!feof($fp)) {
674
                $line = fgets($fp, 1024);
675
                if ($isHeader) {
676
                    $data_header .= $line;
677
                } else {
678
                    $data_body .= $line;
679
                }
680
                if (preg_match('#^HTTP/[\\.\d]+ ([\d]+)\s*(.+)?$#i', rtrim($line), $matches)) {
681
                    [, $errno, $errstr] = $matches;
682
                    $errno = (int)$errno;
683
                } elseif (preg_match('#^Location: (.*)$#i', rtrim($line), $matches)) {
684
                    $header_newlocation = $matches[1];
685
                }
686
                if ($isHeader && ($line == "\r\n")) {
687
                    $isHeader = false;
688
                    if ($successonly) {
689
                        switch ($errno) {
690
                            case 200:
691
                                // great, continue
692
                                break;
693
694
                            default:
695
                                $errstr = $errno . ' ' . $errstr . ($header_newlocation ? '; Location: ' . $header_newlocation : '');
696
                                fclose($fp);
697
                                return false;
698
                                break;
0 ignored issues
show
break is not strictly necessary here and could be removed.

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

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

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

Loading history...
699
                        }
700
                    }
701
                }
702
            }
703
            fclose($fp);
704
            return $data_body;
705
        }
706
        return null;
707
    }
708
709
    public static function CleanUpURLencoding($url, $queryseperator = '&')
710
    {
711
        if (!0 === stripos($url, "http")) {
712
            return $url;
713
        }
714
        $parsed_url        = self::ParseURLbetter($url);
715
        $pathelements      = explode('/', $parsed_url['path']);
716
        $CleanPathElements = [];
717
        $TranslationMatrix = [' ' => '%20'];
718
        foreach ($pathelements as $key => $pathelement) {
719
            $CleanPathElements[] = strtr($pathelement, $TranslationMatrix);
720
        }
721
        foreach ($CleanPathElements as $key => $value) {
722
            if ($value === '') {
723
                unset($CleanPathElements[$key]);
724
            }
725
        }
726
727
        $queries      = explode($queryseperator, $parsed_url['query']);
728
        $CleanQueries = [];
729
        foreach ($queries as $key => $query) {
730
            @list($param, $value) = explode('=', $query);
731
            $CleanQueries[] = strtr($param, $TranslationMatrix) . ($value ? '=' . strtr($value, $TranslationMatrix) : '');
732
        }
733
        foreach ($CleanQueries as $key => $value) {
734
            if ($value === '') {
735
                unset($CleanQueries[$key]);
736
            }
737
        }
738
739
        $cleaned_url = $parsed_url['scheme'] . '://';
740
        $cleaned_url .= ($parsed_url['user'] ? $parsed_url['user'] . ($parsed_url['pass'] ? ':' . $parsed_url['pass'] : '') . '@' : '');
741
        $cleaned_url .= $parsed_url['host'];
742
        $cleaned_url .= (($parsed_url['port'] && ($parsed_url['port'] != self::URLschemeDefaultPort($parsed_url['scheme']))) ? ':' . $parsed_url['port'] : '');
743
        $cleaned_url .= '/' . implode('/', $CleanPathElements);
744
        $cleaned_url .= (!empty($CleanQueries) ? '?' . implode($queryseperator, $CleanQueries) : '');
745
        return $cleaned_url;
746
    }
747
748
    public static function URLschemeDefaultPort($scheme)
749
    {
750
        static $schemePort = [
751
            'ftp'   => 21,
752
            'http'  => 80,
753
            'https' => 443,
754
        ];
755
        return (isset($schemePort[strtolower($scheme)]) ? $schemePort[strtolower($scheme)] : null);
756
    }
757
758
    public static function ParseURLbetter($url)
759
    {
760
        $parsedURL = @parse_url($url);
761
        foreach (['scheme', 'host', 'port', 'user', 'pass', 'path', 'query', 'fragment'] as $key) { // ensure all possible array keys are always returned
762
            if (!array_key_exists($key, $parsedURL)) {
763
                $parsedURL[$key] = null;
764
            }
765
        }
766
        $parsedURL['port'] = ($parsedURL['port'] ? $parsedURL['port'] : self::URLschemeDefaultPort($parsedURL['scheme']));
767
        return $parsedURL;
768
    }
769
770
    public static function SafeURLread($url, &$error, $timeout = 10, $followredirects = true)
771
    {
772
        $error   = '';
773
        $errstr  = '';
774
        $rawData = '';
775
776
        $parsed_url                      = self::ParseURLbetter($url);
777
        $alreadyLookedAtURLs[trim($url)] = true;
0 ignored issues
show
Comprehensibility Best Practice introduced by
$alreadyLookedAtURLs was never initialized. Although not strictly required by PHP, it is generally a good practice to add $alreadyLookedAtURLs = array(); before regardless.
Loading history...
778
779
        while (true) {
780
            $tryagain = false;
781
            $rawData  = self::URLreadFsock($parsed_url['host'], $parsed_url['path'] . '?' . $parsed_url['query'], $errstr, true, $parsed_url['port'], $timeout);
782
            if ($followredirects && preg_match('#302 [a-z ]+; Location\\: (http.*)#i', $errstr, $matches)) {
783
                $matches[1] = trim(@$matches[1]);
784
                if (!@$alreadyLookedAtURLs[$matches[1]]) {
785
                    // loop through and examine new URL
786
                    $error .= 'URL "' . $url . '" redirected to "' . $matches[1] . '"';
787
788
                    $tryagain                         = true;
789
                    $alreadyLookedAtURLs[$matches[1]] = true;
790
                    $parsed_url                       = self::ParseURLbetter($matches[1]);
791
                }
792
            }
793
            if (!$tryagain) {
794
                break;
795
            }
796
        }
797
798
        if ($rawData === false) {
799
            $error .= 'Error opening "' . $url . '":' . "\n\n" . $errstr;
800
            return false;
801
        } elseif ($rawData === null) {
0 ignored issues
show
The condition $rawData === null is always false.
Loading history...
802
            // fall through
803
            $error .= 'Error opening "' . $url . '":' . "\n\n" . $errstr;
804
        } else {
805
            return $rawData;
806
        }
807
808
        if (function_exists('curl_version') && !self::FunctionIsDisabled('curl_exec')) {
809
            $ch = curl_init();
810
            curl_setopt($ch, CURLOPT_URL, $url);
811
            curl_setopt($ch, CURLOPT_HEADER, false);
812
            curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
813
            curl_setopt($ch, CURLOPT_BINARYTRANSFER, true);
0 ignored issues
show
The constant CURLOPT_BINARYTRANSFER has been deprecated: 5.1.3 ( Ignorable by Annotation )

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

813
            curl_setopt($ch, /** @scrutinizer ignore-deprecated */ CURLOPT_BINARYTRANSFER, true);
Loading history...
814
            curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 2);
815
            curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, true);
816
            curl_setopt($ch, CURLOPT_FOLLOWLOCATION, (bool)$followredirects);
817
            curl_setopt($ch, CURLOPT_TIMEOUT, $timeout);
818
            $rawData = curl_exec($ch);
819
            curl_close($ch);
820
            if (strlen($rawData) > 0) {
821
                $error .= 'CURL succeeded (' . strlen($rawData) . ' bytes); ';
822
                return $rawData;
823
            }
824
            $error .= 'CURL available but returned no data; ';
825
        } else {
826
            $error .= 'CURL unavailable; ';
827
        }
828
829
        $BrokenURLfopenPHPversions = ['4.4.2'];
830
        if (in_array(PHP_VERSION, $BrokenURLfopenPHPversions)) {
831
            $error .= 'fopen(URL) broken in PHP v' . PHP_VERSION . '; ';
832
        } elseif (@ini_get('allow_url_fopen')) {
833
            $rawData     = '';
834
            $error_fopen = '';
835
            ob_start();
836
            if ($fp = fopen($url, 'rb')) {
837
                do {
838
                    $buffer  = fread($fp, 8192);
839
                    $rawData .= $buffer;
840
                } while (strlen($buffer) > 0);
841
                fclose($fp);
842
            } else {
843
                $error_fopen .= trim(strip_tags(ob_get_contents()));
844
            }
845
            ob_end_clean();
846
            $error .= $error_fopen;
847
            if (!$error_fopen) {
848
                $error .= '; "allow_url_fopen" succeeded (' . strlen($rawData) . ' bytes); ';
849
                return $rawData;
850
            }
851
            $error .= '; "allow_url_fopen" enabled but returned no data (' . $error_fopen . '); ';
852
        } else {
853
            $error .= '"allow_url_fopen" disabled; ';
854
        }
855
856
        return false;
857
    }
858
859
    public static function EnsureDirectoryExists($dirname, $mask = 0755)
860
    {
861
        // https://www.php.net/manual/en/ini.core.php#ini.open-basedir says:
862
        // "Under Windows, separate the directories with a semicolon. On all other systems, separate the directories with a colon."
863
        $config_open_basedir = ini_get('open_basedir');
864
        $startoffset         = 2; // 1-based counting, first element to left of first directory separator will either be drive letter (Windows) or blank (unix). May be overridden below.
865
        if (self::is_windows()) {
866
            $delimiter                 = ';';
867
            $case_insensitive_pathname = true;
868
            // unix OSs will always use "/", some Windows configurations you may find "/" used interchangeably with the OS-correct "\", so standardize for ease of comparison
869
            $dirname             = str_replace('/', DIRECTORY_SEPARATOR, $dirname);
870
            $config_open_basedir = str_replace('/', DIRECTORY_SEPARATOR, $config_open_basedir);
871
        } else {
872
            $delimiter                 = ':';
873
            $case_insensitive_pathname = false;
874
        }
875
        $open_basedirs = explode($delimiter, $config_open_basedir);
876
        foreach ($open_basedirs as $key => $open_basedir) {
877
            if (preg_match('#^' . preg_quote($open_basedir) . '#' . ($case_insensitive_pathname ? 'i' : ''), $dirname) && (strlen($dirname) > strlen($open_basedir))) {
878
                $startoffset = substr_count($open_basedir, DIRECTORY_SEPARATOR) + 1;
879
                break;
880
            }
881
        }
882
883
        $directory_elements = explode(DIRECTORY_SEPARATOR, $dirname);
884
        $endoffset          = count($directory_elements);
885
        for ($i = $startoffset; $i <= $endoffset; $i++) {
886
            $test_directory = implode(DIRECTORY_SEPARATOR, array_slice($directory_elements, 0, $i));
887
            if (!$test_directory) {
888
                continue;
889
            }
890
            if (!@is_dir($test_directory)) {
891
                if (@file_exists($test_directory)) {
892
                    // directory name already exists as a file
893
                    return false;
894
                }
895
                @mkdir($test_directory, $mask);
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition for mkdir(). This can introduce security issues, and is generally not recommended. ( Ignorable by Annotation )

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

895
                /** @scrutinizer ignore-unhandled */ @mkdir($test_directory, $mask);

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

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

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

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

896
                /** @scrutinizer ignore-unhandled */ @chmod($test_directory, $mask);

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

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

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
897
                if (!@is_dir($test_directory) || !@is_writable($test_directory)) {
898
                    return false;
899
                }
900
            }
901
        }
902
        return true;
903
    }
904
905
    public static function GetAllFilesInSubfolders($dirname)
906
    {
907
        $AllFiles = [];
908
        $dirname  = rtrim(realpath($dirname), '/\\');
909
        if ($dirhandle = @opendir($dirname)) {
910
            while (($file = readdir($dirhandle)) !== false) {
911
                $fullfilename = $dirname . DIRECTORY_SEPARATOR . $file;
912
                if (is_file($fullfilename)) {
913
                    $AllFiles[] = $fullfilename;
914
                } elseif (is_dir($fullfilename)) {
915
                    switch ($file) {
916
                        case '.':
917
                        case '..':
918
                            break;
919
920
                        default:
921
                            $AllFiles[] = $fullfilename;
922
                            $subfiles   = self::GetAllFilesInSubfolders($fullfilename);
923
                            foreach ($subfiles as $filename) {
924
                                $AllFiles[] = $filename;
925
                            }
926
                            break;
927
                    }
928
                } else {
929
                    // ignore?
930
                }
931
            }
932
            closedir($dirhandle);
933
        }
934
        sort($AllFiles);
935
        return array_unique($AllFiles);
936
    }
937
938
    public static function SanitizeFilename($filename)
939
    {
940
        $filename = preg_replace('/[^' . preg_quote(' !#$%^()+,-.;<>=@[]_{}') . 'a-zA-Z0-9]/', '_', $filename);
941
        if (self::version_compare_replacement(PHP_VERSION, '4.1.0', '>=')) {
942
            $filename = trim($filename, '.');
943
        }
944
        return $filename;
945
    }
946
947
    public static function PasswordStrength($password)
948
    {
949
        $strength = 0;
950
        $strength += strlen(preg_replace('#[^a-z]#', '', $password)) * 0.5; // lowercase characters are weak
951
        $strength += strlen(preg_replace('#[^A-Z]#', '', $password)) * 0.8; // uppercase characters are somewhat better
952
        $strength += strlen(preg_replace('#[^0-9]#', '', $password)) * 1.0; // numbers are somewhat better
953
        $strength += strlen(preg_replace('#[a-zA-Z0-9]#', '', $password)) * 2.0; // other non-alphanumeric characters are best
954
        return $strength;
955
    }
956
}
957
958
////////////// END: class phpthumb_functions //////////////
959
960
if (!function_exists('gd_info')) {
961
    // built into PHP v4.3.0+ (with bundled GD2 library)
962
    function gd_info()
963
    {
964
        static $gd_info = [];
965
        if (empty($gd_info)) {
966
            // based on code by johnschaefer at gmx dot de
967
            // from PHP help on gd_info()
968
            $gd_info       = [
969
                'GD Version'         => '',
970
                'FreeType Support'   => false,
971
                'FreeType Linkage'   => '',
972
                'T1Lib Support'      => false,
973
                'GIF Read Support'   => false,
974
                'GIF Create Support' => false,
975
                'JPG Support'        => false,
976
                'PNG Support'        => false,
977
                'WBMP Support'       => false,
978
                'XBM Support'        => false,
979
            ];
980
            $phpinfo_array = phpthumb_functions::phpinfo_array();
981
            foreach ($phpinfo_array as $line) {
982
                $line = trim(strip_tags($line));
983
                foreach ($gd_info as $key => $value) {
984
                    //if (strpos($line, $key) !== false) {
985
                    if (strpos($line, $key) === 0) {
986
                        $newvalue      = trim(str_replace($key, '', $line));
987
                        $gd_info[$key] = $newvalue;
988
                    }
989
                }
990
            }
991
            if (empty($gd_info['GD Version'])) {
992
                // probable cause: "phpinfo() disabled for security reasons"
993
                if (function_exists('imagetypes')) {
994
                    $imagetypes = imagetypes();
995
                    if ($imagetypes & IMG_PNG) {
996
                        $gd_info['PNG Support'] = true;
997
                    }
998
                    if ($imagetypes & IMG_GIF) {
999
                        $gd_info['GIF Create Support'] = true;
1000
                    }
1001
                    if ($imagetypes & IMG_JPG) {
1002
                        $gd_info['JPG Support'] = true;
1003
                    }
1004
                    if ($imagetypes & IMG_WBMP) {
1005
                        $gd_info['WBMP Support'] = true;
1006
                    }
1007
                }
1008
                // to determine capability of GIF creation, try to use imagecreatefromgif on a 1px GIF
1009
                if (function_exists('imagecreatefromgif')) {
1010
                    if ($tempfilename = phpthumb::phpThumb_tempnam()) {
0 ignored issues
show
Bug Best Practice introduced by
The method phpthumb::phpThumb_tempnam() is not static, but was called statically. ( Ignorable by Annotation )

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

1010
                    if ($tempfilename = phpthumb::/** @scrutinizer ignore-call */ phpThumb_tempnam()) {
Loading history...
1011
                        if ($fp_tempfile = @fopen($tempfilename, 'wb')) {
1012
                            fwrite($fp_tempfile, base64_decode('R0lGODlhAQABAIAAAH//AP///ywAAAAAAQABAAACAUQAOw==')); // very simple 1px GIF file base64-encoded as string
1013
                            fclose($fp_tempfile);
1014
                            $phpthumb_temp = new phpthumb();
1015
                            @chmod($tempfilename, $phpthumb_temp->getParameter('config_file_create_mask'));
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition for chmod(). This can introduce security issues, and is generally not recommended. ( Ignorable by Annotation )

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

1015
                            /** @scrutinizer ignore-unhandled */ @chmod($tempfilename, $phpthumb_temp->getParameter('config_file_create_mask'));

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

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

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
1016
1017
                            // if we can convert the GIF file to a GD image then GIF create support must be enabled, otherwise it's not
1018
                            $gd_info['GIF Read Support'] = (bool)@imagecreatefromgif($tempfilename);
1019
                        }
1020
                        unlink($tempfilename);
1021
                    }
1022
                }
1023
                if (function_exists('imagecreatetruecolor') && @imagecreatetruecolor(1, 1)) {
1024
                    $gd_info['GD Version'] = '2.0.1 or higher (assumed)';
1025
                } elseif (function_exists('imagecreate') && @imagecreate(1, 1)) {
1026
                    $gd_info['GD Version'] = '1.6.0 or higher (assumed)';
1027
                }
1028
            }
1029
        }
1030
        return $gd_info;
1031
    }
1032
}
1033
1034
if (!function_exists('is_executable')) {
1035
    // in PHP v3+, but v5.0+ for Windows
1036
    function is_executable($filename)
1037
    {
1038
        // poor substitute, but better than nothing
1039
        return file_exists($filename);
1040
    }
1041
}
1042
1043
if (!function_exists('preg_quote')) {
1044
    // included in PHP v3.0.9+, but may be unavailable if not compiled in
1045
    function preg_quote($string, $delimiter = '\\')
1046
    {
1047
        static $preg_quote_array = [];
1048
        if (empty($preg_quote_array)) {
1049
            $escapeables = '.\\+*?[^]$(){}=!<>|:';
1050
            for ($i = 0, $iMax = strlen($escapeables); $i < $iMax; $i++) {
1051
                $strtr_preg_quote[$escapeables[$i]] = $delimiter . $escapeables[$i];
1052
            }
1053
        }
1054
        return strtr($string, $strtr_preg_quote);
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $strtr_preg_quote does not seem to be defined for all execution paths leading up to this point.
Loading history...
1055
    }
1056
}
1057
1058
if (!function_exists('file_get_contents')) {
1059
    // included in PHP v4.3.0+
1060
    function file_get_contents($filename)
1061
    {
1062
        if (preg_match('#^(f|ht)tp\://#i', $filename)) {
1063
            return SafeURLread($filename, $error);
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $error seems to be never defined.
Loading history...
The function SafeURLread was not found. Maybe you did not declare it correctly or list all dependencies? ( Ignorable by Annotation )

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

1063
            return /** @scrutinizer ignore-call */ SafeURLread($filename, $error);
Loading history...
1064
        }
1065
        if ($fp = @fopen($filename, 'rb')) {
1066
            $rawData = '';
1067
            do {
1068
                $buffer  = fread($fp, 8192);
1069
                $rawData .= $buffer;
1070
            } while (strlen($buffer) > 0);
1071
            fclose($fp);
1072
            return $rawData;
1073
        }
1074
        return false;
1075
    }
1076
}
1077
1078
if (!function_exists('file_put_contents')) {
1079
    // included in PHP v5.0.0+
1080
    function file_put_contents($filename, $filedata)
1081
    {
1082
        if ($fp = @fopen($filename, 'wb')) {
1083
            fwrite($fp, $filedata);
1084
            fclose($fp);
1085
            return true;
1086
        }
1087
        return false;
1088
    }
1089
}
1090
1091
if (!function_exists('imagealphablending')) {
1092
    // built-in function requires PHP v4.0.6+ *and* GD v2.0.1+
1093
    function imagealphablending(&$img, $blendmode = true)
0 ignored issues
show
The parameter $img is not used and could be removed. ( Ignorable by Annotation )

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

1093
    function imagealphablending(/** @scrutinizer ignore-unused */ &$img, $blendmode = true)

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
The parameter $blendmode is not used and could be removed. ( Ignorable by Annotation )

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

1093
    function imagealphablending(&$img, /** @scrutinizer ignore-unused */ $blendmode = true)

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
1094
    {
1095
        // do nothing, this function is declared here just to
1096
        // prevent runtime errors if GD2 is not available
1097
        return true;
1098
    }
1099
}
1100
1101
if (!function_exists('imagesavealpha')) {
1102
    // built-in function requires PHP v4.3.2+ *and* GD v2.0.1+
1103
    function imagesavealpha(&$img, $blendmode = true)
0 ignored issues
show
The parameter $blendmode is not used and could be removed. ( Ignorable by Annotation )

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

1103
    function imagesavealpha(&$img, /** @scrutinizer ignore-unused */ $blendmode = true)

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
The parameter $img is not used and could be removed. ( Ignorable by Annotation )

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

1103
    function imagesavealpha(/** @scrutinizer ignore-unused */ &$img, $blendmode = true)

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
1104
    {
1105
        // do nothing, this function is declared here just to
1106
        // prevent runtime errors if GD2 is not available
1107
        return true;
1108
    }
1109
}
1110