Passed
Push — master ( 89a4a6...169298 )
by Michael
04:31
created

phpthumb_functions::EnsureDirectoryExists()   C

Complexity

Conditions 13
Paths 42

Size

Total Lines 35
Code Lines 23

Duplication

Lines 0
Ratio 0 %

Importance

Changes 4
Bugs 0 Features 0
Metric Value
cc 13
eloc 23
c 4
b 0
f 0
nc 42
nop 1
dl 0
loc 35
rs 6.6166

How to fix   Complexity   

Long Method

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

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

Commonly applied refactorings include:

1
<?php
2
//////////////////////////////////////////////////////////////
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
/**
13
 * Class phpthumb_functions
14
 */
15
class phpthumb_functions
0 ignored issues
show
Coding Style Compatibility introduced by
PSR1 recommends that each class must be in a namespace of at least one level to avoid collisions.

You can fix this by adding a namespace to your class:

namespace YourVendor;

class YourClass { }

When choosing a vendor namespace, try to pick something that is not too generic to avoid conflicts with other libraries.

Loading history...
16
{
17
    /**
18
     * @param $functionname
19
     * @return bool
20
     */
21
    public static function user_function_exists($functionname)
22
    {
23
        if (function_exists('get_defined_functions')) {
24
            static $get_defined_functions = [];
25
            if (empty($get_defined_functions)) {
26
                $get_defined_functions = get_defined_functions();
27
            }
28
29
            return in_array(strtolower($functionname), $get_defined_functions['user']);
30
        }
31
32
        return function_exists($functionname);
33
    }
34
35
    /**
36
     * @param $functionname
37
     * @return bool
38
     */
39
    public static function builtin_function_exists($functionname)
40
    {
41
        if (function_exists('get_defined_functions')) {
42
            static $get_defined_functions = [];
43
            if (empty($get_defined_functions)) {
44
                $get_defined_functions = get_defined_functions();
45
            }
46
47
            return in_array(strtolower($functionname), $get_defined_functions['internal']);
48
        }
49
50
        return function_exists($functionname);
51
    }
52
53
    /**
54
     * @param        $version1
55
     * @param        $version2
56
     * @param string $operator
57
     * @return int
58
     */
59
    public static function version_compare_replacement_sub($version1, $version2, $operator = '')
60
    {
61
        // If you specify the third optional operator argument, you can test for a particular relationship.
62
        // The possible operators are: <, lt, <=, le, >, gt, >=, ge, ==, =, eq, !=, <>, ne respectively.
63
        // Using this argument, the function will return 1 if the relationship is the one specified by the operator, 0 otherwise.
64
65
        // If a part contains special version strings these are handled in the following order:
66
        // (any string not found in this list) < (dev) < (alpha = a) < (beta = b) < (RC = rc) < (#) < (pl = p)
67
        static $versiontype_lookup = [];
68
        if (empty($versiontype_lookup)) {
69
            $versiontype_lookup['dev']   = 10001;
70
            $versiontype_lookup['a']     = 10002;
71
            $versiontype_lookup['alpha'] = 10002;
72
            $versiontype_lookup['b']     = 10003;
73
            $versiontype_lookup['beta']  = 10003;
74
            $versiontype_lookup['RC']    = 10004;
75
            $versiontype_lookup['rc']    = 10004;
76
            $versiontype_lookup['#']     = 10005;
77
            $versiontype_lookup['pl']    = 10006;
78
            $versiontype_lookup['p']     = 10006;
79
        }
80
        $version1 = (isset($versiontype_lookup[$version1]) ? $versiontype_lookup[$version1] : $version1);
81
        $version2 = (isset($versiontype_lookup[$version2]) ? $versiontype_lookup[$version2] : $version2);
82
83
        switch ($operator) {
84
            case '<':
85
            case 'lt':
86
                return (int)($version1 < $version2);
87
                break;
0 ignored issues
show
Unused Code introduced by
break is not strictly necessary here and could be removed.

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

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

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

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

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

Loading history...
327
        }
328
        if (self::IsHexColor($HexColorString)) {
329
            $R = hexdec(substr($HexColorString, 0, 2));
330
            $G = hexdec(substr($HexColorString, 2, 2));
331
            $B = hexdec(substr($HexColorString, 4, 2));
332
333
            return self::ImageColorAllocateAlphaSafe($gdimg_hexcolorallocate, $R, $G, $B, $alpha);
334
        }
335
        if ($dieOnInvalid) {
336
            die('Invalid hex color string: "' . $HexColorString . '"');
0 ignored issues
show
Best Practice introduced by
Using exit here is not recommended.

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

Loading history...
337
        }
338
339
        return imagecolorallocate($gdimg_hexcolorallocate, 0x00, 0x00, 0x00);
340
    }
341
342
    /**
343
     * @param $hexcolor
344
     * @return string
345
     */
346
    public static function HexColorXOR($hexcolor)
347
    {
348
        return strtoupper(str_pad(dechex(~hexdec($hexcolor) & 0xFFFFFF), 6, '0', STR_PAD_LEFT));
349
    }
350
351
    /**
352
     * @param $img
353
     * @param $x
354
     * @param $y
355
     * @return array|bool
356
     */
357
    public static function GetPixelColor(&$img, $x, $y)
358
    {
359
        if (!is_resource($img)) {
360
            return false;
361
        }
362
363
        return @imagecolorsforindex($img, @imagecolorat($img, $x, $y));
364
    }
365
366
    /**
367
     * @param $currentPixel
368
     * @param $targetPixel
369
     * @return float|int
370
     */
371
    public static function PixelColorDifferencePercent($currentPixel, $targetPixel)
372
    {
373
        $diff = 0;
374
        foreach ($targetPixel as $channel => $currentvalue) {
375
            $diff = max($diff, (max($currentPixel[$channel], $targetPixel[$channel]) - min($currentPixel[$channel], $targetPixel[$channel])) / 255);
376
        }
377
378
        return $diff * 100;
379
    }
380
381
    /**
382
     * @param $r
383
     * @param $g
384
     * @param $b
385
     * @return float
386
     */
387
    public static function GrayscaleValue($r, $g, $b)
388
    {
389
        return round(($r * 0.30) + ($g * 0.59) + ($b * 0.11));
390
    }
391
392
    /**
393
     * @param $OriginalPixel
394
     * @return array
395
     */
396
    public static function GrayscalePixel($OriginalPixel)
397
    {
398
        $gray = self::GrayscaleValue($OriginalPixel['red'], $OriginalPixel['green'], $OriginalPixel['blue']);
399
400
        return ['red' => $gray, 'green' => $gray, 'blue' => $gray];
401
    }
402
403
    /**
404
     * @param $rgb
405
     * @return float
406
     */
407
    public static function GrayscalePixelRGB($rgb)
408
    {
409
        $r = ($rgb >> 16) & 0xFF;
410
        $g = ($rgb >> 8) & 0xFF;
411
        $b = $rgb & 0xFF;
412
413
        return ($r * 0.299) + ($g * 0.587) + ($b * 0.114);
414
    }
415
416
    /**
417
     * @param      $width
418
     * @param      $height
419
     * @param null $maxwidth
0 ignored issues
show
Documentation Bug introduced by
Are you sure the doc-type for parameter $maxwidth is correct as it would always require null to be passed?
Loading history...
420
     * @param null $maxheight
0 ignored issues
show
Documentation Bug introduced by
Are you sure the doc-type for parameter $maxheight is correct as it would always require null to be passed?
Loading history...
421
     * @param bool $allow_enlarge
422
     * @param bool $allow_reduce
423
     * @return mixed
424
     */
425
    public static function ScaleToFitInBox(
426
        $width,
427
        $height,
428
        $maxwidth = null,
429
        $maxheight = null,
430
        $allow_enlarge = true,
431
        $allow_reduce = true
432
    ) {
433
        $maxwidth  = (null === $maxwidth ? $width : $maxwidth);
0 ignored issues
show
introduced by
The condition null === $maxwidth is always true.
Loading history...
434
        $maxheight = (null === $maxheight ? $height : $maxheight);
0 ignored issues
show
introduced by
The condition null === $maxheight is always true.
Loading history...
435
        $scale_x   = 1;
436
        $scale_y   = 1;
437
        if (($width > $maxwidth) || ($width < $maxwidth)) {
438
            $scale_x = ($maxwidth / $width);
439
        }
440
        if (($height > $maxheight) || ($height < $maxheight)) {
441
            $scale_y = ($maxheight / $height);
442
        }
443
        $scale = min($scale_x, $scale_y);
444
        if (!$allow_enlarge) {
445
            $scale = min($scale, 1);
446
        }
447
        if (!$allow_reduce) {
448
            $scale = max($scale, 1);
449
        }
450
451
        return $scale;
452
    }
453
454
    /**
455
     * @param $dst_img
456
     * @param $src_img
457
     * @param $dst_x
458
     * @param $dst_y
459
     * @param $src_x
460
     * @param $src_y
461
     * @param $dst_w
462
     * @param $dst_h
463
     * @param $src_w
464
     * @param $src_h
465
     * @return bool
466
     */
467
    public static function ImageCopyResampleBicubic(
468
        $dst_img,
469
        $src_img,
470
        $dst_x,
471
        $dst_y,
472
        $src_x,
473
        $src_y,
474
        $dst_w,
475
        $dst_h,
476
        $src_w,
477
        $src_h
478
    ) {
479
        // ron at korving dot demon dot nl
480
        // http://www.php.net/imagecopyresampled
481
482
        $scaleX = ($src_w - 1) / $dst_w;
483
        $scaleY = ($src_h - 1) / $dst_h;
484
485
        $scaleX2 = $scaleX / 2.0;
486
        $scaleY2 = $scaleY / 2.0;
487
488
        $isTrueColor = imageistruecolor($src_img);
489
490
        for ($y = $src_y; $y < $src_y + $dst_h; $y++) {
491
            $sY   = $y * $scaleY;
492
            $siY  = (int)$sY;
493
            $siY2 = (int)$sY + $scaleY2;
494
495
            for ($x = $src_x; $x < $src_x + $dst_w; $x++) {
496
                $sX   = $x * $scaleX;
497
                $siX  = (int)$sX;
498
                $siX2 = (int)$sX + $scaleX2;
499
500
                if ($isTrueColor) {
501
                    $c1 = imagecolorat($src_img, $siX, $siY2);
502
                    $c2 = imagecolorat($src_img, $siX, $siY);
503
                    $c3 = imagecolorat($src_img, $siX2, $siY2);
504
                    $c4 = imagecolorat($src_img, $siX2, $siY);
505
506
                    $r = (($c1 + $c2 + $c3 + $c4) >> 2) & 0xFF0000;
507
                    $g = ((($c1 & 0x00FF00) + ($c2 & 0x00FF00) + ($c3 & 0x00FF00) + ($c4 & 0x00FF00)) >> 2) & 0x00FF00;
508
                    $b = ((($c1 & 0x0000FF) + ($c2 & 0x0000FF) + ($c3 & 0x0000FF) + ($c4 & 0x0000FF)) >> 2);
509
                } else {
510
                    $c1 = imagecolorsforindex($src_img, imagecolorat($src_img, $siX, $siY2));
511
                    $c2 = imagecolorsforindex($src_img, imagecolorat($src_img, $siX, $siY));
512
                    $c3 = imagecolorsforindex($src_img, imagecolorat($src_img, $siX2, $siY2));
513
                    $c4 = imagecolorsforindex($src_img, imagecolorat($src_img, $siX2, $siY));
514
515
                    $r = ($c1['red'] + $c2['red'] + $c3['red'] + $c4['red']) << 14;
516
                    $g = ($c1['green'] + $c2['green'] + $c3['green'] + $c4['green']) << 6;
517
                    $b = ($c1['blue'] + $c2['blue'] + $c3['blue'] + $c4['blue']) >> 2;
518
                }
519
                imagesetpixel($dst_img, $dst_x + $x - $src_x, $dst_y + $y - $src_y, $r + $g + $b);
520
            }
521
        }
522
523
        return true;
524
    }
525
526
    /**
527
     * @param $x_size
528
     * @param $y_size
529
     * @return bool
530
     */
531
    public static function ImageCreateFunction($x_size, $y_size)
532
    {
533
        $ImageCreateFunction = 'imagecreate';
534
        if (self::gd_version() >= 2.0) {
535
            $ImageCreateFunction = 'imagecreatetruecolor';
536
        }
537
        if (!function_exists($ImageCreateFunction)) {
538
            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

538
            return phpthumb::/** @scrutinizer ignore-call */ ErrorImage($ImageCreateFunction . '() does not exist - no GD support?');
Loading history...
539
        }
540
        if (($x_size <= 0) || ($y_size <= 0)) {
541
            return phpthumb::ErrorImage('Invalid image dimensions: ' . $ImageCreateFunction . '(' . $x_size . ', ' . $y_size . ')');
542
        }
543
544
        return $ImageCreateFunction(round($x_size), round($y_size));
545
    }
546
547
    /**
548
     * @param     $dst_im
549
     * @param     $src_im
550
     * @param     $dst_x
551
     * @param     $dst_y
552
     * @param     $src_x
553
     * @param     $src_y
554
     * @param     $src_w
555
     * @param     $src_h
556
     * @param int $opacity_pct
557
     * @return bool
558
     */
559
    public static function ImageCopyRespectAlpha(
560
        &$dst_im,
561
        &$src_im,
562
        $dst_x,
563
        $dst_y,
564
        $src_x,
565
        $src_y,
566
        $src_w,
567
        $src_h,
568
        $opacity_pct = 100
569
    ) {
570
        $opacipct = $opacity_pct / 100;
571
        for ($x = $src_x; $x < $src_w; $x++) {
572
            for ($y = $src_y; $y < $src_h; $y++) {
573
                $RealPixel    = self::GetPixelColor($dst_im, $dst_x + $x, $dst_y + $y);
574
                $OverlayPixel = self::GetPixelColor($src_im, $x, $y);
575
                $alphapct     = $OverlayPixel['alpha'] / 127;
576
                $overlaypct   = (1 - $alphapct) * $opacipct;
577
578
                $newcolor = self::ImageColorAllocateAlphaSafe(
579
                    $dst_im,
580
                    round($RealPixel['red'] * (1 - $overlaypct)) + ($OverlayPixel['red'] * $overlaypct),
581
                    round($RealPixel['green'] * (1 - $overlaypct)) + ($OverlayPixel['green'] * $overlaypct),
582
                                                                            round($RealPixel['blue'] * (1 - $overlaypct)) + ($OverlayPixel['blue'] * $overlaypct), //$RealPixel['alpha']);
0 ignored issues
show
Unused Code Comprehensibility introduced by
100% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
583
                                                                            0
584
                );
585
586
                imagesetpixel($dst_im, $dst_x + $x, $dst_y + $y, $newcolor);
587
            }
588
        }
589
590
        return true;
591
    }
592
593
    /**
594
     * @param      $old_width
595
     * @param      $old_height
596
     * @param bool $new_width
597
     * @param bool $new_height
598
     * @return array|bool
599
     */
600
    public static function ProportionalResize($old_width, $old_height, $new_width = false, $new_height = false)
601
    {
602
        $old_aspect_ratio = $old_width / $old_height;
603
        if ((false === $new_width) && (false === $new_height)) {
604
            return false;
605
        } elseif (false === $new_width) {
606
            $new_width = $new_height * $old_aspect_ratio;
607
        } elseif (false === $new_height) {
608
            $new_height = $new_width / $old_aspect_ratio;
609
        }
610
        $new_aspect_ratio = $new_width / $new_height;
611
        if ($new_aspect_ratio == $old_aspect_ratio) {
0 ignored issues
show
Unused Code introduced by
This if statement is empty and can be removed.

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

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

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

could be turned into

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

This is much more concise to read.

Loading history...
612
            // great, done
613
        } elseif ($new_aspect_ratio < $old_aspect_ratio) {
614
            // limited by width
615
            $new_height = $new_width / $old_aspect_ratio;
616
        } elseif ($new_aspect_ratio > $old_aspect_ratio) {
617
            // limited by height
618
            $new_width = $new_height * $old_aspect_ratio;
619
        }
620
621
        return [(int)round($new_width), (int)round($new_height)];
0 ignored issues
show
Bug introduced by
It seems like $new_height can also be of type boolean; however, parameter $val of round() does only seem to accept double, 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

621
        return [(int)round($new_width), (int)round(/** @scrutinizer ignore-type */ $new_height)];
Loading history...
Bug introduced by
It seems like $new_width can also be of type true; however, parameter $val of round() does only seem to accept double, 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

621
        return [(int)round(/** @scrutinizer ignore-type */ $new_width), (int)round($new_height)];
Loading history...
622
    }
623
624
    /**
625
     * @param $function
626
     * @return bool
627
     */
628
    public static function FunctionIsDisabled($function)
629
    {
630
        static $DisabledFunctions = null;
631
        if (null === $DisabledFunctions) {
632
            $disable_functions_local  = explode(',', strtolower(@ini_get('disable_functions')));
633
            $disable_functions_global = explode(',', strtolower(@get_cfg_var('disable_functions')));
634
            foreach ($disable_functions_local as $key => $value) {
635
                $DisabledFunctions[trim($value)] = 'local';
636
            }
637
            foreach ($disable_functions_global as $key => $value) {
638
                $DisabledFunctions[trim($value)] = 'global';
639
            }
640
            if (@ini_get('safe_mode')) {
641
                $DisabledFunctions['shell_exec']     = 'local';
642
                $DisabledFunctions['set_time_limit'] = 'local';
643
            }
644
        }
645
646
        return isset($DisabledFunctions[strtolower($function)]);
647
    }
648
649
    /**
650
     * @param $command
651
     * @return bool|string
652
     */
653
    public static function SafeExec($command)
654
    {
655
        static $AllowedExecFunctions = [];
656
        if (empty($AllowedExecFunctions)) {
657
            $AllowedExecFunctions = ['shell_exec' => true, 'passthru' => true, 'system' => true, 'exec' => true];
658
            foreach ($AllowedExecFunctions as $key => $value) {
659
                $AllowedExecFunctions[$key] = !self::FunctionIsDisabled($key);
660
            }
661
        }
662
        $command .= ' 2>&1'; // force redirect stderr to stdout
663
        foreach ($AllowedExecFunctions as $execfunction => $is_allowed) {
664
            if (!$is_allowed) {
665
                continue;
666
            }
667
            $returnvalue = false;
668
            switch ($execfunction) {
669
                case 'passthru':
670
                case 'system':
671
                    ob_start();
672
                    $execfunction($command);
673
                    $returnvalue = ob_get_contents();
674
                    ob_end_clean();
675
                    break;
676
677
                case 'exec':
678
                    $output      = [];
679
                    $lastline    = $execfunction($command, $output);
0 ignored issues
show
Unused Code introduced by
The assignment to $lastline is dead and can be removed.
Loading history...
680
                    $returnvalue = implode("\n", $output);
681
                    break;
682
683
                case 'shell_exec':
684
                    ob_start();
685
                    $returnvalue = $execfunction($command);
686
                    ob_end_clean();
687
                    break;
688
            }
689
690
            return $returnvalue;
691
        }
692
693
        return false;
694
    }
695
696
    /**
697
     * @param $filename
698
     * @return array|bool
699
     */
700
    public static function ApacheLookupURIarray($filename)
701
    {
702
        // apache_lookup_uri() only works when PHP is installed as an Apache module.
703
        if ('apache' === php_sapi_name()) {
704
            //$property_exists_exists = function_exists('property_exists');
0 ignored issues
show
Unused Code Comprehensibility introduced by
56% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
705
            $keys = [
706
                'status',
707
                'the_request',
708
                'status_line',
709
                'method',
710
                'content_type',
711
                'handler',
712
                'uri',
713
                'filename',
714
                'path_info',
715
                'args',
716
                'boundary',
717
                'no_cache',
718
                'no_local_copy',
719
                'allowed',
720
                'send_bodyct',
721
                'bytes_sent',
722
                'byterange',
723
                'clength',
724
                'unparsed_uri',
725
                'mtime',
726
                'request_time'
727
            ];
728
            if ($apacheLookupURIobject = @apache_lookup_uri($filename)) {
729
                $apacheLookupURIarray = [];
730
                foreach ($keys as $key) {
731
                    $apacheLookupURIarray[$key] = @$apacheLookupURIobject->$key;
732
                }
733
734
                return $apacheLookupURIarray;
735
            }
736
        }
737
738
        return false;
739
    }
740
741
    /**
742
     * @return bool|null
743
     */
744
    public static function gd_is_bundled()
745
    {
746
        static $isbundled = null;
747
        if (null === $isbundled) {
748
            $gd_info   = gd_info();
749
            $isbundled = (false !== strpos($gd_info['GD Version'], 'bundled'));
750
        }
751
752
        return $isbundled;
753
    }
754
755
    /**
756
     * @param bool $fullstring
757
     * @return mixed
758
     */
759
    public static function gd_version($fullstring = false)
760
    {
761
        static $cache_gd_version = [];
762
        if (empty($cache_gd_version)) {
763
            $gd_info = gd_info();
764
            if (preg_match('#bundled \((.+)\)$#i', $gd_info['GD Version'], $matches)) {
765
                $cache_gd_version[1] = $gd_info['GD Version'];  // e.g. "bundled (2.0.15 compatible)"
766
                $cache_gd_version[0] = (float)$matches[1];     // e.g. "2.0" (not "bundled (2.0.15 compatible)")
767
            } else {
768
                $cache_gd_version[1] = $gd_info['GD Version'];                       // e.g. "1.6.2 or higher"
769
                $cache_gd_version[0] = (float)substr($gd_info['GD Version'], 0, 3); // e.g. "1.6" (not "1.6.2 or higher")
770
            }
771
        }
772
773
        return $cache_gd_version[(int)$fullstring];
774
    }
775
776
    /**
777
     * @param     $remotefile
778
     * @param int $timeout
779
     * @return bool|int
780
     */
781
    public static function filesize_remote($remotefile, $timeout = 10)
782
    {
783
        $size = false;
784
        $url  = self::ParseURLbetter($remotefile);
785
        if ($fp = @fsockopen($url['host'], ($url['port'] ?: 80), $errno, $errstr, $timeout)) {
786
            fwrite($fp, 'HEAD ' . @$url['path'] . @$url['query'] . ' HTTP/1.0' . "\r\n" . 'Host: ' . @$url['host'] . "\r\n\r\n");
787
            if (self::version_compare_replacement(PHP_VERSION, '4.3.0', '>=')) {
788
                stream_set_timeout($fp, $timeout);
789
            }
790
            while (!feof($fp)) {
791
                $headerline = fgets($fp, 4096);
792
                if (preg_match('#^Content-Length: (.*)#i', $headerline, $matches)) {
793
                    $size = (int)$matches[1];
794
                    break;
795
                }
796
            }
797
            fclose($fp);
798
        }
799
800
        return $size;
801
    }
802
803
    /**
804
     * @param     $remotefile
805
     * @param int $timeout
806
     * @return bool|false|int|string
807
     */
808
    public static function filedate_remote($remotefile, $timeout = 10)
809
    {
810
        $date = false;
811
        $url  = self::ParseURLbetter($remotefile);
812
        if ($fp = @fsockopen($url['host'], ($url['port'] ?: 80), $errno, $errstr, $timeout)) {
813
            fwrite($fp, 'HEAD ' . @$url['path'] . @$url['query'] . ' HTTP/1.0' . "\r\n" . 'Host: ' . @$url['host'] . "\r\n\r\n");
814
            if (self::version_compare_replacement(PHP_VERSION, '4.3.0', '>=')) {
815
                stream_set_timeout($fp, $timeout);
816
            }
817
            while (!feof($fp)) {
818
                $headerline = fgets($fp, 4096);
819
                if (preg_match('#^Last-Modified: (.*)#i', $headerline, $matches)) {
820
                    $date = strtotime($matches[1]) - date('Z');
821
                    break;
822
                }
823
            }
824
            fclose($fp);
825
        }
826
827
        return $date;
828
    }
829
830
    /**
831
     * @param $filename
832
     * @return bool|string
833
     */
834
    public static function md5_file_safe($filename)
835
    {
836
        // md5_file() doesn't exist in PHP < 4.2.0
837
        if (function_exists('md5_file')) {
838
            return md5_file($filename);
839
        }
840
        if ($fp = @fopen($filename, 'rb')) {
841
            $rawData = '';
842
            do {
843
                $buffer  = fread($fp, 8192);
844
                $rawData .= $buffer;
845
            } while (strlen($buffer) > 0);
846
            fclose($fp);
847
848
            return md5($rawData);
849
        }
850
851
        return false;
852
    }
853
854
    /**
855
     * @return mixed
856
     */
857
    public static function nonempty_min()
858
    {
859
        $arg_list   = func_get_args();
860
        $acceptable = [];
861
        foreach ($arg_list as $arg) {
862
            if ($arg) {
863
                $acceptable[] = $arg;
864
            }
865
        }
866
867
        return min($acceptable);
868
    }
869
870
    /**
871
     * @param     $number
872
     * @param int $minbytes
873
     * @return string
874
     */
875
    public static function LittleEndian2String($number, $minbytes = 1)
876
    {
877
        $intstring = '';
878
        while ($number > 0) {
879
            $intstring = $intstring . chr($number & 255);
880
            $number    >>= 8;
881
        }
882
883
        return str_pad($intstring, $minbytes, "\x00", STR_PAD_RIGHT);
884
    }
885
886
    /**
887
     * @return bool
888
     */
889
    public static function OneOfThese()
890
    {
891
        // return the first useful (non-empty/non-zero/non-false) value from those passed
892
        $arg_list = func_get_args();
893
        foreach ($arg_list as $key => $value) {
894
            if ($value) {
895
                return $value;
896
            }
897
        }
898
899
        return false;
900
    }
901
902
    /**
903
     * @param $needle
904
     * @param $haystack
905
     * @return bool
906
     */
907
    public static function CaseInsensitiveInArray($needle, $haystack)
908
    {
909
        $needle = strtolower($needle);
910
        foreach ($haystack as $key => $value) {
911
            if (is_array($value)) {
0 ignored issues
show
Unused Code introduced by
This if statement is empty and can be removed.

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

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

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

could be turned into

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

This is much more concise to read.

Loading history...
912
                // skip?
913
            } elseif ($needle == strtolower($value)) {
914
                return true;
915
            }
916
        }
917
918
        return false;
919
    }
920
921
    /**
922
     * @param      $host
923
     * @param      $file
924
     * @param      $errstr
925
     * @param bool $successonly
926
     * @param int  $port
927
     * @param int  $timeout
928
     * @return bool|null|string
929
     */
930
    public static function URLreadFsock($host, $file, &$errstr, $successonly = true, $port = 80, $timeout = 10)
931
    {
932
        if (!function_exists('fsockopen') || self::FunctionIsDisabled('fsockopen')) {
933
            $errstr = 'fsockopen() unavailable';
934
935
            return false;
936
        }
937
        //if ($fp = @fsockopen($host, $port, $errno, $errstr, $timeout)) {
0 ignored issues
show
Unused Code Comprehensibility introduced by
63% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
938
        if ($fp = @fsockopen(((443 == $port) ? 'ssl://' : '') . $host, $port, $errno, $errstr, $timeout)) { // https://github.com/JamesHeinrich/phpThumb/issues/39
939
            $out = 'GET ' . $file . ' HTTP/1.0' . "\r\n";
940
            $out .= 'Host: ' . $host . "\r\n";
941
            $out .= 'Connection: Close' . "\r\n\r\n";
942
            fwrite($fp, $out);
943
944
            $isHeader           = true;
945
            $Data_header        = '';
946
            $Data_body          = '';
947
            $header_newlocation = '';
948
            while (!feof($fp)) {
949
                $line = fgets($fp, 1024);
950
                if ($isHeader) {
951
                    $Data_header .= $line;
952
                } else {
953
                    $Data_body .= $line;
954
                }
955
                if (preg_match('#^HTTP/[\\.0-9]+ ([0-9]+) (.+)$#i', rtrim($line), $matches)) {
956
                    list(, $errno, $errstr) = $matches;
957
                    $errno = (int)$errno;
958
                } elseif (preg_match('#^Location: (.*)$#i', rtrim($line), $matches)) {
959
                    $header_newlocation = $matches[1];
960
                }
961
                if ($isHeader && ("\r\n" === $line)) {
962
                    $isHeader = false;
963
                    if ($successonly) {
964
                        switch ($errno) {
965
                            case 200:
966
                                // great, continue
0 ignored issues
show
Unused Code Comprehensibility introduced by
40% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
967
                                break;
968
969
                            default:
970
                                $errstr = $errno . ' ' . $errstr . ($header_newlocation ? '; Location: ' . $header_newlocation : '');
971
                                fclose($fp);
972
973
                                return false;
974
                                break;
0 ignored issues
show
Unused Code introduced by
break is not strictly necessary here and could be removed.

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

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

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

Loading history...
975
                        }
976
                    }
977
                }
978
            }
979
            fclose($fp);
980
981
            return $Data_body;
982
        }
983
984
        return null;
985
    }
986
987
    /**
988
     * @param        $url
989
     * @param string $queryseperator
990
     * @return string
991
     */
992
    public static function CleanUpURLencoding($url, $queryseperator = '&')
993
    {
994
        if (!preg_match('#^http#i', $url)) {
995
            return $url;
996
        }
997
        $parse_url         = self::ParseURLbetter($url);
998
        $pathelements      = explode('/', $parse_url['path']);
999
        $CleanPathElements = [];
1000
        $TranslationMatrix = [' ' => '%20'];
1001
        foreach ($pathelements as $key => $pathelement) {
1002
            $CleanPathElements[] = strtr($pathelement, $TranslationMatrix);
1003
        }
1004
        foreach ($CleanPathElements as $key => $value) {
1005
            if ('' === $value) {
1006
                unset($CleanPathElements[$key]);
1007
            }
1008
        }
1009
1010
        $queries      = explode($queryseperator, (isset($parse_url['query']) ? $parse_url['query'] : ''));
1011
        $CleanQueries = [];
1012
        foreach ($queries as $key => $query) {
1013
            @list($param, $value) = explode('=', $query);
1014
            $CleanQueries[] = strtr($param, $TranslationMatrix) . ($value ? '=' . strtr($value, $TranslationMatrix) : '');
1015
        }
1016
        foreach ($CleanQueries as $key => $value) {
1017
            if ('' === $value) {
1018
                unset($CleanQueries[$key]);
1019
            }
1020
        }
1021
1022
        $cleaned_url = $parse_url['scheme'] . '://';
1023
        $cleaned_url .= (@$parse_url['username'] ? $parse_url['host'] . (@$parse_url['password'] ? ':' . $parse_url['password'] : '') . '@' : '');
1024
        $cleaned_url .= $parse_url['host'];
1025
        $cleaned_url .= ((!empty($parse_url['port']) && (80 != $parse_url['port'])) ? ':' . $parse_url['port'] : '');
1026
        $cleaned_url .= '/' . implode('/', $CleanPathElements);
1027
        $cleaned_url .= (@$CleanQueries ? '?' . implode($queryseperator, $CleanQueries) : '');
1028
1029
        return $cleaned_url;
1030
    }
1031
1032
    /**
1033
     * @param $url
1034
     * @return mixed
1035
     */
1036
    public static function ParseURLbetter($url)
1037
    {
1038
        $parsedURL = @parse_url($url);
1039
        if (!@$parsedURL['port']) {
1040
            switch (strtolower(@$parsedURL['scheme'])) {
1041
                case 'ftp':
1042
                    $parsedURL['port'] = 21;
1043
                    break;
1044
                case 'https':
1045
                    $parsedURL['port'] = 443;
1046
                    break;
1047
                case 'http':
1048
                    $parsedURL['port'] = 80;
1049
                    break;
1050
            }
1051
        }
1052
1053
        return $parsedURL;
1054
    }
1055
1056
    /**
1057
     * @param      $url
1058
     * @param      $error
1059
     * @param int  $timeout
1060
     * @param bool $followredirects
1061
     * @return bool|mixed|null|string
1062
     */
1063
    public static function SafeURLread($url, &$error, $timeout = 10, $followredirects = true)
1064
    {
1065
        $error   = '';
1066
        $errstr  = '';
1067
        $rawData = '';
1068
1069
        $parsed_url                      = self::ParseURLbetter($url);
1070
        $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...
1071
1072
        while (true) {
1073
            $tryagain = false;
1074
            $rawData  = self::URLreadFsock(@$parsed_url['host'], @$parsed_url['path'] . '?' . @$parsed_url['query'], $errstr, true, (@$parsed_url['port'] ?: 80), $timeout);
1075
            if ($followredirects && preg_match('#302 [a-z ]+; Location\\: (http.*)#i', $errstr, $matches)) {
1076
                $matches[1] = trim(@$matches[1]);
1077
                if (!@$alreadyLookedAtURLs[$matches[1]]) {
1078
                    // loop through and examine new URL
1079
                    $error .= 'URL "' . $url . '" redirected to "' . $matches[1] . '"';
1080
1081
                    $tryagain                         = true;
1082
                    $alreadyLookedAtURLs[$matches[1]] = true;
1083
                    $parsed_url                       = self::ParseURLbetter($matches[1]);
1084
                }
1085
            }
1086
            if (!$tryagain) {
1087
                break;
1088
            }
1089
        }
1090
1091
        if (false === $rawData) {
1092
            $error .= 'Error opening "' . $url . '":' . "\n\n" . $errstr;
1093
1094
            return false;
1095
        } elseif (null === $rawData) {
0 ignored issues
show
introduced by
The condition null === $rawData is always false.
Loading history...
1096
            // fall through
1097
            $error .= 'Error opening "' . $url . '":' . "\n\n" . $errstr;
1098
        } else {
1099
            return $rawData;
1100
        }
1101
1102
        if (function_exists('curl_version') && !self::FunctionIsDisabled('curl_exec')) {
1103
            $ch = curl_init();
1104
            curl_setopt($ch, CURLOPT_URL, $url);
1105
            curl_setopt($ch, CURLOPT_HEADER, false);
1106
            curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
1107
            curl_setopt($ch, CURLOPT_BINARYTRANSFER, true);
1108
            curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 2);    // changed for XOOPS
1109
            curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, true); // changed for XOOPS
1110
            curl_setopt($ch, CURLOPT_FOLLOWLOCATION, (bool)$followredirects);
1111
            curl_setopt($ch, CURLOPT_TIMEOUT, $timeout);
1112
            $rawData = curl_exec($ch);
1113
            curl_close($ch);
1114
            if (strlen($rawData) > 0) {
1115
                $error .= 'CURL succeeded (' . strlen($rawData) . ' bytes); ';
1116
1117
                return $rawData;
1118
            }
1119
            $error .= 'CURL available but returned no data; ';
1120
        } else {
1121
            $error .= 'CURL unavailable; ';
1122
        }
1123
1124
        $BrokenURLfopenPHPversions = ['4.4.2'];
1125
        if (in_array(PHP_VERSION, $BrokenURLfopenPHPversions)) {
1126
            $error .= 'fopen(URL) broken in PHP v' . PHP_VERSION . '; ';
1127
        } elseif (@ini_get('allow_url_fopen')) {
1128
            $rawData     = '';
1129
            $error_fopen = '';
1130
            ob_start();
1131
            if ($fp = fopen($url, 'rb')) {
1132
                do {
1133
                    $buffer  = fread($fp, 8192);
1134
                    $rawData .= $buffer;
1135
                } while (strlen($buffer) > 0);
1136
                fclose($fp);
1137
            } else {
1138
                $error_fopen .= trim(strip_tags(ob_get_contents()));
1139
            }
1140
            ob_end_clean();
1141
            $error .= $error_fopen;
1142
            if (!$error_fopen) {
1143
                $error .= '; "allow_url_fopen" succeeded (' . strlen($rawData) . ' bytes); ';
1144
1145
                return $rawData;
1146
            }
1147
            $error .= '; "allow_url_fopen" enabled but returned no data (' . $error_fopen . '); ';
1148
        } else {
1149
            $error .= '"allow_url_fopen" disabled; ';
1150
        }
1151
1152
        return false;
1153
    }
1154
1155
    /**
1156
     * @param $dirname
1157
     * @return bool
1158
     */
1159
    public static function EnsureDirectoryExists($dirname)
1160
    {
1161
        $directory_elements = explode(DIRECTORY_SEPARATOR, $dirname);
1162
        $startoffset        = (!$directory_elements[0] ? 2 : 1);  // unix with leading "/" then start with 2nd element; Windows with leading "c:\" then start with 1st element
1163
        $open_basedirs      = preg_split('#[;:]#', ini_get('open_basedir'));
1164
        foreach ($open_basedirs as $key => $open_basedir) {
1165
            if (preg_match('#^' . preg_quote($open_basedir) . '#', $dirname)
1166
                && (strlen($dirname) > strlen($open_basedir))) {
1167
                $startoffset = substr_count($open_basedir, DIRECTORY_SEPARATOR) + 1;
1168
                break;
1169
            }
1170
        }
1171
        $i         = $startoffset;
0 ignored issues
show
Unused Code introduced by
The assignment to $i is dead and can be removed.
Loading history...
1172
        $endoffset = count($directory_elements);
1173
        for ($i = $startoffset; $i <= $endoffset; $i++) {
1174
            $test_directory = implode(DIRECTORY_SEPARATOR, array_slice($directory_elements, 0, $i));
1175
            if (!$test_directory) {
1176
                continue;
1177
            }
1178
            if (!@is_dir($test_directory)) {
1179
                if (@file_exists($test_directory)) {
1180
                    // directory name already exists as a file
1181
                    return false;
1182
                }
1183
                if (!mkdir($test_directory, 0755) && !is_dir($test_directory)) {
1184
                    throw new \RuntimeException(sprintf('Directory "%s" was not created', $test_directory));
1185
                }
1186
                @chmod($test_directory, 0755);
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

1186
                /** @scrutinizer ignore-unhandled */ @chmod($test_directory, 0755);

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...
1187
                if (!@is_dir($test_directory) || !@is_writable($test_directory)) {
1188
                    return false;
1189
                }
1190
            }
1191
        }
1192
1193
        return true;
1194
    }
1195
1196
    /**
1197
     * @param $dirname
1198
     * @return array
1199
     */
1200
    public static function GetAllFilesInSubfolders($dirname)
1201
    {
1202
        $AllFiles = [];
1203
        $dirname  = rtrim(realpath($dirname), '/\\');
1204
        if ($dirhandle = @opendir($dirname)) {
1205
            while (false !== ($file = readdir($dirhandle))) {
1206
                $fullfilename = $dirname . DIRECTORY_SEPARATOR . $file;
1207
                if (is_file($fullfilename)) {
1208
                    $AllFiles[] = $fullfilename;
1209
                } elseif (is_dir($fullfilename)) {
1210
                    switch ($file) {
1211
                        case '.':
1212
                        case '..':
1213
                            break;
1214
1215
                        default:
1216
                            $AllFiles[] = $fullfilename;
1217
                            $subfiles   = self::GetAllFilesInSubfolders($fullfilename);
1218
                            foreach ($subfiles as $filename) {
1219
                                $AllFiles[] = $filename;
1220
                            }
1221
                            break;
1222
                    }
1223
                } else {
0 ignored issues
show
Unused Code introduced by
This else statement is empty and can be removed.

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

These else branches can be removed.

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

could be turned into

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

This is much more concise to read.

Loading history...
1224
                    // ignore?
1225
                }
1226
            }
1227
            closedir($dirhandle);
1228
        }
1229
        sort($AllFiles);
1230
1231
        return array_unique($AllFiles);
1232
    }
1233
1234
    /**
1235
     * @param $filename
1236
     * @return null|string|string[]
1237
     */
1238
    public static function SanitizeFilename($filename)
1239
    {
1240
        $filename = preg_replace('/[^' . preg_quote(' !#$%^()+,-.;<>=@[]_{}') . 'a-zA-Z0-9]/', '_', $filename);
1241
        if (self::version_compare_replacement(PHP_VERSION, '4.1.0', '>=')) {
1242
            $filename = trim($filename, '.');
1243
        }
1244
1245
        return $filename;
1246
    }
1247
1248
    /**
1249
     * @param $password
1250
     * @return float|int
1251
     */
1252
    public static function PasswordStrength($password)
1253
    {
1254
        $strength = 0;
1255
        $strength += strlen(preg_replace('#[^a-z]#', '', $password)) * 0.5; // lowercase characters are weak
1256
        $strength += strlen(preg_replace('#[^A-Z]#', '', $password)) * 0.8; // uppercase characters are somewhat better
1257
        $strength += strlen(preg_replace('#[^0-9]#', '', $password)) * 1.0; // numbers are somewhat better
1258
        $strength += strlen(preg_replace('#[a-zA-Z0-9]#', '', $password)) * 2.0; // other non-alphanumeric characters are best
1259
1260
        return $strength;
1261
    }
1262
}
1263
1264
////////////// END: class phpthumb_functions //////////////
1265
1266
if (!function_exists('gd_info')) {
1267
    // built into PHP v4.3.0+ (with bundled GD2 library)
1268
    /**
1269
     * @return array
1270
     */
1271
    function gd_info()
1272
    {
1273
        static $gd_info = [];
1274
        if (empty($gd_info)) {
1275
            // based on code by johnschaefer at gmx dot de
1276
            // from PHP help on gd_info()
1277
            $gd_info       = [
1278
                'GD Version'         => '',
1279
                'FreeType Support'   => false,
1280
                'FreeType Linkage'   => '',
1281
                'T1Lib Support'      => false,
1282
                'GIF Read Support'   => false,
1283
                'GIF Create Support' => false,
1284
                'JPG Support'        => false,
1285
                'PNG Support'        => false,
1286
                'WBMP Support'       => false,
1287
                'XBM Support'        => false
1288
            ];
1289
            $phpinfo_array = phpthumb_functions::phpinfo_array();
1290
            foreach ($phpinfo_array as $line) {
1291
                $line = trim(strip_tags($line));
1292
                foreach ($gd_info as $key => $value) {
1293
                    //if (strpos($line, $key) !== false) {
0 ignored issues
show
Unused Code Comprehensibility introduced by
62% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
1294
                    if (0 === strpos($line, $key)) {
1295
                        $newvalue      = trim(str_replace($key, '', $line));
1296
                        $gd_info[$key] = $newvalue;
1297
                    }
1298
                }
1299
            }
1300
            if (empty($gd_info['GD Version'])) {
1301
                // probable cause: "phpinfo() disabled for security reasons"
1302
                if (function_exists('imagetypes')) {
1303
                    $imagetypes = imagetypes();
1304
                    if ($imagetypes & IMG_PNG) {
1305
                        $gd_info['PNG Support'] = true;
1306
                    }
1307
                    if ($imagetypes & IMG_GIF) {
1308
                        $gd_info['GIF Create Support'] = true;
1309
                    }
1310
                    if ($imagetypes & IMG_JPG) {
1311
                        $gd_info['JPG Support'] = true;
1312
                    }
1313
                    if ($imagetypes & IMG_WBMP) {
1314
                        $gd_info['WBMP Support'] = true;
1315
                    }
1316
                }
1317
                // to determine capability of GIF creation, try to use imagecreatefromgif on a 1px GIF
1318
                if (function_exists('imagecreatefromgif')) {
1319
                    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

1319
                    if ($tempfilename = phpthumb::/** @scrutinizer ignore-call */ phpThumb_tempnam()) {
Loading history...
1320
                        if ($fp_tempfile = @fopen($tempfilename, 'wb')) {
1321
                            fwrite($fp_tempfile, base64_decode('R0lGODlhAQABAIAAAH//AP///ywAAAAAAQABAAACAUQAOw==')); // very simple 1px GIF file base64-encoded as string
1322
                            fclose($fp_tempfile);
1323
1324
                            // if we can convert the GIF file to a GD image then GIF create support must be enabled, otherwise it's not
1325
                            $gd_info['GIF Read Support'] = (bool)@imagecreatefromgif($tempfilename);
1326
                        }
1327
                        unlink($tempfilename);
1328
                    }
1329
                }
1330
                if (function_exists('imagecreatetruecolor') && @imagecreatetruecolor(1, 1)) {
1331
                    $gd_info['GD Version'] = '2.0.1 or higher (assumed)';
1332
                } elseif (function_exists('imagecreate') && @imagecreate(1, 1)) {
1333
                    $gd_info['GD Version'] = '1.6.0 or higher (assumed)';
1334
                }
1335
            }
1336
        }
1337
1338
        return $gd_info;
1339
    }
1340
}
1341
1342
if (!function_exists('is_executable')) {
1343
    // in PHP v3+, but v5.0+ for Windows
1344
    /**
1345
     * @param $filename
1346
     * @return bool
1347
     */
1348
    function is_executable($filename)
1349
    {
1350
        // poor substitute, but better than nothing
1351
        return file_exists($filename);
1352
    }
1353
}
1354
1355
if (!function_exists('preg_quote')) {
1356
    // included in PHP v3.0.9+, but may be unavailable if not compiled in
1357
    /**
1358
     * @param        $string
1359
     * @param string $delimiter
1360
     * @return string
1361
     */
1362
    function preg_quote($string, $delimiter = '\\')
1363
    {
1364
        static $preg_quote_array = [];
1365
        if (empty($preg_quote_array)) {
1366
            $escapeables = '.\\+*?[^]$(){}=!<>|:';
1367
            for ($i = 0; $i < strlen($escapeables); $i++) {
1368
                $strtr_preg_quote[$escapeables{$i}] = $delimiter . $escapeables{$i};
1369
            }
1370
        }
1371
1372
        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...
1373
    }
1374
}
1375
1376
if (!function_exists('file_get_contents')) {
1377
    // included in PHP v4.3.0+
1378
    /**
1379
     * @param $filename
1380
     * @return bool|string
1381
     */
1382
    function file_get_contents($filename)
1383
    {
1384
        if (preg_match('#^(f|ht)tp\://#i', $filename)) {
1385
            return SafeURLread($filename, $error);
0 ignored issues
show
Bug introduced by
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

1385
            return /** @scrutinizer ignore-call */ SafeURLread($filename, $error);
Loading history...
Comprehensibility Best Practice introduced by
The variable $error seems to be never defined.
Loading history...
1386
        }
1387
        if ($fp = @fopen($filename, 'rb')) {
1388
            $rawData = '';
1389
            do {
1390
                $buffer  = fread($fp, 8192);
1391
                $rawData .= $buffer;
1392
            } while (strlen($buffer) > 0);
1393
            fclose($fp);
1394
1395
            return $rawData;
1396
        }
1397
1398
        return false;
1399
    }
1400
}
1401
1402
if (!function_exists('file_put_contents')) {
1403
    // included in PHP v5.0.0+
1404
    /**
1405
     * @param $filename
1406
     * @param $filedata
1407
     * @return bool
1408
     */
1409
    function file_put_contents($filename, $filedata)
1410
    {
1411
        if ($fp = @fopen($filename, 'wb')) {
1412
            fwrite($fp, $filedata);
1413
            fclose($fp);
1414
1415
            return true;
1416
        }
1417
1418
        return false;
1419
    }
1420
}
1421
1422
if (!function_exists('imagealphablending')) {
1423
    // built-in function requires PHP v4.0.6+ *and* GD v2.0.1+
1424
    /**
1425
     * @param      $img
1426
     * @param bool $blendmode
1427
     * @return bool
1428
     */
1429
    function imagealphablending(&$img, $blendmode = true)
0 ignored issues
show
Unused Code introduced by
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

1429
    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...
Unused Code introduced by
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

1429
    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...
1430
    {
1431
        // do nothing, this function is declared here just to
1432
        // prevent runtime errors if GD2 is not available
1433
        return true;
1434
    }
1435
}
1436
1437
if (!function_exists('imagesavealpha')) {
1438
    // built-in function requires PHP v4.3.2+ *and* GD v2.0.1+
1439
    /**
1440
     * @param      $img
1441
     * @param bool $blendmode
1442
     * @return bool
1443
     */
1444
    function imagesavealpha(&$img, $blendmode = true)
0 ignored issues
show
Unused Code introduced by
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

1444
    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...
Unused Code introduced by
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

1444
    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...
1445
    {
1446
        // do nothing, this function is declared here just to
1447
        // prevent runtime errors if GD2 is not available
1448
        return true;
1449
    }
1450
}
1451