uploader::__get()   A
last analyzed

Complexity

Conditions 2
Paths 2

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 1 Features 0
Metric Value
cc 2
eloc 1
c 1
b 1
f 0
nc 2
nop 1
dl 0
loc 3
rs 10
1
<?php
2
3
/** This file is part of KCFinder project
4
 *
5
 * @desc      Uploader class
6
 * @package   KCFinder
7
 * @version   3.12
8
 * @author    Pavel Tzonkov <[email protected]>
9
 * @copyright 2010-2014 KCFinder Project
10
 * @license   http://opensource.org/licenses/GPL-3.0 GPLv3
11
 * @license   http://opensource.org/licenses/LGPL-3.0 LGPLv3
12
 * @link      http://kcfinder.sunhater.com
13
 */
14
15
namespace kcfinder;
16
17
class uploader
18
{
19
20
    /** Release version */
21
    const VERSION = '3.20-test2';
22
23
    /** Config session-overrided settings
24
     * @var array
25
     */
26
    protected $config = [];
27
28
    /** Default image driver
29
     * @var string
30
     */
31
    protected $imageDriver = 'gd';
32
33
    /** Opener applocation properties
34
     * @var array
35
     */
36
    protected $opener = [];
37
38
    /** Got from $_GET['type'] or first one $config['types'] array key, if inexistant
39
     * @var string
40
     */
41
    protected $type;
42
43
    /** Helper property. Local filesystem path to the Type Directory
44
     * Equivalent: $config['uploadDir'] . "/" . $type
45
     * @var string
46
     */
47
    protected $typeDir;
48
49
    /** Helper property. Web URL to the Type Directory
50
     * Equivalent: $config['uploadURL'] . "/" . $type
51
     * @var string
52
     */
53
    protected $typeURL;
54
55
    /** Linked to $config['types']
56
     * @var array
57
     */
58
    protected $types = [];
59
60
    /** Settings which can override default settings if exists as keys in $config['types'][$type] array
61
     * @var array
62
     */
63
    protected $typeSettings = ['disabled', 'theme', 'dirPerms', 'filePerms', 'denyZipDownload', 'maxImageWidth', 'maxImageHeight', 'thumbWidth', 'thumbHeight', 'jpegQuality', 'access', 'filenameChangeChars', 'dirnameChangeChars', 'denyExtensionRename', 'deniedExts', 'watermark'];
64
65
    /** Got from language file
66
     * @var string
67
     */
68
    protected $charset;
69
70
    /** The language got from $_GET['lng'] or $_GET['lang'] or... Please see next property
71
     * @var string
72
     */
73
    protected $lang = 'en';
74
75
    /** Possible language $_GET keys
76
     * @var array
77
     */
78
    protected $langInputNames = ['lang', 'langCode', 'lng', 'language', 'lang_code'];
79
80
    /** Uploaded file(s) info. Linked to first $_FILES element
81
     * @var array
82
     */
83
    protected $file;
84
85
    /** Next three properties are got from the current language file
86
     * @var string
87
     */
88
    protected $dateTimeFull;   // Currently not used
89
    protected $dateTimeMid;    // Currently not used
90
    protected $dateTimeSmall;
91
92
    /** Contain Specified language labels
93
     * @var array
94
     */
95
    protected $labels = [];
96
97
    /** Session array. Please use this property instead of $_SESSION
98
     * @var array
99
     */
100
    protected $session;
101
102
    /** CMS integration property (got from $_GET['cms'])
103
     * @var string
104
     */
105
    protected $cms = '';
106
107
    /** Magic method which allows read-only access to protected or private class properties
108
     * @param string $property
109
     * @return mixed
110
     */
111
    public function __get($property)
112
    {
113
        return property_exists($this, $property) ? $this->$property : null;
114
    }
115
116
    public function __construct()
117
    {
118
        // SET CMS INTEGRATION PROPERTY
119
        if (isset($_GET['cms']) && $this->checkFilename($_GET['cms']) && is_file("integration/{$_GET['cms']}.php")) {
120
            $this->cms = $_GET['cms'];
121
        }
122
123
        // LINKING UPLOADED FILE
124
        if (count($_FILES)) {
125
            $this->file = &$_FILES[key($_FILES)];
126
        }
127
128
        // CONFIG & SESSION SETUP
129
        $session       = new session('conf/config.php');
130
        $this->config  = $session->getConfig();
131
        $this->session = &$session->values;
132
133
        // IMAGE DRIVER INIT
134
        if (isset($this->config['imageDriversPriority'])) {
135
            $this->config['imageDriversPriority'] = text::clearWhitespaces($this->config['imageDriversPriority']);
136
            $driver                               = image::getDriver(explode(' ', $this->config['imageDriversPriority']));
137
            if (false !== $driver) {
0 ignored issues
show
introduced by
The condition false !== $driver is always true.
Loading history...
138
                $this->imageDriver = $driver;
139
            }
140
        }
141
        if ((!isset($driver) || (false === $driver)) && (false === image::getDriver([$this->imageDriver]))) {
0 ignored issues
show
introduced by
The condition false === kcfinder\image...ay($this->imageDriver)) is always false.
Loading history...
142
            $this->backMsg('Cannot find any of the supported PHP image extensions!');
143
        }
144
145
        // WATERMARK INIT
146
        if (isset($this->config['watermark']) && is_string($this->config['watermark'])) {
147
            $this->config['watermark'] = ['file' => $this->config['watermark']];
148
        }
149
150
        // GET TYPE DIRECTORY
151
        $this->types = &$this->config['types'];
152
        $firstType   = array_keys($this->types);
153
        $firstType   = $firstType[0];
154
        $this->type  = (isset($_GET['type']) && isset($this->types[$_GET['type']])) ? $_GET['type'] : $firstType;
155
156
        // LOAD TYPE DIRECTORY SPECIFIC CONFIGURATION IF EXISTS
157
        if (is_array($this->types[$this->type])) {
158
            foreach ($this->types[$this->type] as $key => $val) {
159
                if (in_array($key, $this->typeSettings)) {
160
                    $this->config[$key] = $val;
161
                }
162
            }
163
            $this->types[$this->type] = isset($this->types[$this->type]['type']) ? $this->types[$this->type]['type'] : '';
164
        }
165
166
        // COOKIES INIT
167
        $ip = '(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)';
168
        $ip = '/^' . implode('\.', [$ip, $ip, $ip, $ip]) . '$/';
169
        if (preg_match($ip, $_SERVER['HTTP_HOST']) || preg_match('/^[^\.]+$/', $_SERVER['HTTP_HOST'])) {
170
            $this->config['cookieDomain'] = '';
171
        } elseif (!strlen($this->config['cookieDomain'])) {
172
            $this->config['cookieDomain'] = $_SERVER['HTTP_HOST'];
173
        }
174
        if (!strlen($this->config['cookiePath'])) {
175
            $this->config['cookiePath'] = '/';
176
        }
177
178
        // UPLOAD FOLDER INIT
179
180
        // FULL URL
181
        if (preg_match(
182
            '/^([a-z]+)\:\/\/([^\/^\:]+)(\:(\d+))?\/(.+)\/?$/',
183
            $this->config['uploadURL'],
184
            $patt
185
        )) {
186
            list($unused, $protocol, $domain, $unused, $port, $path) = $patt;
187
            $path                      = path::normalize($path);
188
            $this->config['uploadURL'] = "$protocol://$domain" . (strlen($port) ? ":$port" : '') . "/$path";
189
            $this->config['uploadDir'] = strlen($this->config['uploadDir']) ? path::normalize($this->config['uploadDir']) : path::url2fullPath("/$path");
190
            $this->typeDir             = "{$this->config['uploadDir']}/{$this->type}";
191
            $this->typeURL             = "{$this->config['uploadURL']}/{$this->type}";
192
            // SITE ROOT
193
        } elseif ('/' == $this->config['uploadURL']) {
194
            $this->config['uploadDir'] = strlen($this->config['uploadDir']) ? path::normalize($this->config['uploadDir']) : path::normalize(realpath($_SERVER['DOCUMENT_ROOT']));
195
            $this->typeDir             = "{$this->config['uploadDir']}/{$this->type}";
196
            $this->typeURL             = "/{$this->type}";
197
            // ABSOLUTE & RELATIVE
198
        } else {
199
            $this->config['uploadURL'] = ('/' === substr($this->config['uploadURL'], 0, 1)) ? path::normalize($this->config['uploadURL']) : path::rel2abs_url($this->config['uploadURL']);
200
            $this->config['uploadDir'] = strlen($this->config['uploadDir']) ? path::normalize($this->config['uploadDir']) : path::url2fullPath($this->config['uploadURL']);
201
            $this->typeDir             = "{$this->config['uploadDir']}/{$this->type}";
202
            $this->typeURL             = "{$this->config['uploadURL']}/{$this->type}";
203
        }
204
205
        // HOST APPLICATIONS INIT
206
        if (isset($_GET['CKEditorFuncNum'])) {
207
            $this->opener['name']     = 'ckeditor';
208
            $this->opener['CKEditor'] = ['funcNum' => $_GET['CKEditorFuncNum']];
209
        } elseif (isset($_GET['opener'])) {
210
            $this->opener['name'] = $_GET['opener'];
211
212
            if ('tinymce' == $_GET['opener']) {
213
                if (!isset($this->config['_tinyMCEPath']) || !strlen($this->config['_tinyMCEPath'])) {
214
                    $this->opener['name'] = false;
215
                }
216
            } elseif ('tinymce4' == $_GET['opener']) {
217
                if (!isset($_GET['field'])) {
218
                    $this->opener['name'] = false;
219
                } else {
220
                    $this->opener['TinyMCE'] = ['field' => $_GET['field']];
221
                }
222
            }
223
        } else {
224
            $this->opener['name'] = false;
225
        }
226
227
        // LOCALIZATION
228
        foreach ($this->langInputNames as $key) {
229
            if (isset($_GET[$key]) && preg_match('/^[a-z][a-z\._\-]*$/i', $_GET[$key]) && file_exists('lang/' . strtolower($_GET[$key]) . '.php')) {
230
                $this->lang = $_GET[$key];
231
                break;
232
            }
233
        }
234
        $this->localize($this->lang);
235
236
        // IF BROWSER IS ENABLED
237
        if (!$this->config['disabled']) {
238
            // TRY TO CREATE UPLOAD DIRECTORY IF NOT EXISTS
239
            if (!$this->config['disabled'] && !is_dir($this->config['uploadDir'])) {
240
                @mkdir($this->config['uploadDir'], $this->config['dirPerms']);
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

240
                /** @scrutinizer ignore-unhandled */ @mkdir($this->config['uploadDir'], $this->config['dirPerms']);

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...
241
            }
242
243
            // CHECK & MAKE DEFAULT .htaccess
244
            if (isset($this->config['_check4htaccess']) && $this->config['_check4htaccess']) {
245
                $htaccess = "{$this->config['uploadDir']}/.htaccess";
246
                $original = $this->get_htaccess();
247
                if (!file_exists($htaccess)) {
248
                    if (!@file_put_contents($htaccess, $original)) {
249
                        $this->backMsg("Cannot write to upload folder. {$this->config['uploadDir']}");
250
                    }
251
                } else {
252
                    if (false === ($data = @file_get_contents($htaccess))) {
253
                        $this->backMsg('Cannot read .htaccess');
254
                    }
255
                    if (($data != $original) && !@file_put_contents($htaccess, $original)) {
256
                        $this->backMsg('Incorrect .htaccess file. Cannot rewrite it!');
257
                    }
258
                }
259
            }
260
261
            // CHECK & CREATE UPLOAD FOLDER
262
            if (!is_dir($this->typeDir)) {
263
                if (!mkdir($this->typeDir, $this->config['dirPerms'])) {
264
                    $this->backMsg('Cannot create {dir} folder.', ['dir' => $this->type]);
265
                }
266
            } elseif (!is_readable($this->typeDir)) {
267
                $this->backMsg('Cannot read upload folder.');
268
            }
269
        }
270
    }
271
272
    public function upload()
273
    {
274
        $config = &$this->config;
275
        $file   = &$this->file;
276
        $url    = $message = '';
277
278
        if ($config['disabled'] || !$config['access']['files']['upload']) {
279
            if (isset($file['tmp_name'])) {
280
                @unlink($file['tmp_name']);
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition for unlink(). This can introduce security issues, and is generally not recommended. ( Ignorable by Annotation )

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

280
                /** @scrutinizer ignore-unhandled */ @unlink($file['tmp_name']);

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...
281
            }
282
            $message = $this->label("You don't have permissions to upload files.");
283
        } elseif (true === ($message = $this->checkUploadedFile())) {
284
            $message = '';
285
286
            $dir = "{$this->typeDir}/";
287
            if (isset($_GET['dir']) && (false !== ($gdir = $this->checkInputDir($_GET['dir'])))) {
288
                $udir = path::normalize("$dir$gdir");
289
                if (substr($udir, 0, strlen($dir)) !== $dir) {
290
                    $message = $this->label('Unknown error.');
291
                } else {
292
                    $l    = strlen($dir);
293
                    $dir  = "$udir/";
294
                    $udir = substr($udir, $l);
295
                }
296
            }
297
298
            if (!strlen($message)) {
299
                if (!is_dir(path::normalize($dir))) {
300
                    @mkdir(path::normalize($dir), $this->config['dirPerms'], true);
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

300
                    /** @scrutinizer ignore-unhandled */ @mkdir(path::normalize($dir), $this->config['dirPerms'], true);

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...
301
                }
302
303
                $filename = $this->normalizeFilename($file['name']);
304
                $target   = file::getInexistantFilename($dir . $filename);
305
306
                if (!@move_uploaded_file($file['tmp_name'], $target) && !@rename($file['tmp_name'], $target) && !@copy($file['tmp_name'], $target)) {
307
                    $message = $this->label('Cannot move uploaded file to target folder.');
308
                } else {
309
                    if (function_exists('chmod')) {
310
                        @chmod($target, $this->config['filePerms']);
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

310
                        /** @scrutinizer ignore-unhandled */ @chmod($target, $this->config['filePerms']);

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...
311
                    }
312
                    $this->makeThumb($target);
313
                    $url = $this->typeURL;
314
                    if (isset($udir)) {
315
                        $url .= "/$udir";
316
                    }
317
                    $url .= '/' . basename($target);
318
                    if (preg_match('/^([a-z]+)\:\/\/([^\/^\:]+)(\:(\d+))?\/(.+)$/', $url, $patt)) {
319
                        list($unused, $protocol, $domain, $unused, $port, $path) = $patt;
320
                        $base = "$protocol://$domain" . (strlen($port) ? ":$port" : '') . '/';
321
                        $url  = $base . path::urlPathEncode($path);
322
                    } else {
323
                        $url = path::urlPathEncode($url);
324
                    }
325
                }
326
            }
327
        }
328
329
        if (strlen($message) && isset($this->file['tmp_name']) && file_exists($this->file['tmp_name'])) {
330
            @unlink($this->file['tmp_name']);
331
        }
332
333
        if (strlen($message) && method_exists($this, 'errorMsg')) {
334
            $this->errorMsg($message);
335
        } else {
336
            $this->callBack($url, $message);
337
        }
338
    }
339
340
    protected function normalizeFilename($filename)
341
    {
342
        if (isset($this->config['filenameChangeChars']) && is_array($this->config['filenameChangeChars'])) {
343
            $filename = strtr($filename, $this->config['filenameChangeChars']);
344
        }
345
346
        if (isset($this->config['_normalizeFilenames']) && $this->config['_normalizeFilenames']) {
347
            $filename = file::normalizeFilename($filename);
348
        }
349
350
        return $filename;
351
    }
352
353
    protected function normalizeDirname($dirname)
354
    {
355
        if (isset($this->config['dirnameChangeChars']) && is_array($this->config['dirnameChangeChars'])) {
356
            $dirname = strtr($dirname, $this->config['dirnameChangeChars']);
357
        }
358
359
        if (isset($this->config['_normalizeFilenames']) && $this->config['_normalizeFilenames']) {
360
            $dirname = file::normalizeFilename($dirname);
361
        }
362
363
        return $dirname;
364
    }
365
366
    protected function checkFilePath($file)
367
    {
368
        $rPath = realpath($file);
369
        if ('WIN' == strtoupper(substr(PHP_OS, 0, 3))) {
370
            $rPath = str_replace("\\", '/', $rPath);
371
        }
372
        return (substr($rPath, 0, strlen($this->typeDir)) === $this->typeDir);
373
    }
374
375
    protected function checkFilename($file)
376
    {
377
        if ((basename($file) !== $file) || (isset($this->config['_normalizeFilenames']) && $this->config['_normalizeFilenames'] && preg_match('/[^0-9a-z\.\- _]/si', $file))) {
378
            return false;
379
        }
380
381
        return true;
382
    }
383
384
    protected function checkUploadedFile(array $aFile = null)
385
    {
386
        $config = &$this->config;
387
        $file   = (null === $aFile) ? $this->file : $aFile;
388
389
        if (!is_array($file) || !isset($file['name'])) {
0 ignored issues
show
introduced by
The condition is_array($file) is always true.
Loading history...
390
            return $this->label('Unknown error');
391
        }
392
393
        if (is_array($file['name'])) {
394
            foreach ($file['name'] as $i => $name) {
395
                $return = $this->checkUploadedFile(
396
                    [
397
                        'name'     => $name,
398
                        'tmp_name' => $file['tmp_name'][$i],
399
                        'error'    => $file['error'][$i]
400
                    ]
401
                );
402
                if (true !== $return) {
403
                    return "$name: $return";
404
                }
405
            }
406
            return true;
407
        }
408
409
        $extension = file::getExtension($file['name']);
410
        $typePatt  = strtolower(text::clearWhitespaces($this->types[$this->type]));
411
412
        // CHECK FOR UPLOAD ERRORS
413
        if ($file['error']) {
414
            return (UPLOAD_ERR_INI_SIZE == $file['error']) ? $this->label(
415
                'The uploaded file exceeds {size} bytes.',
416
                ['size' => ini_get('upload_max_filesize')]
417
            ) : ((UPLOAD_ERR_FORM_SIZE == $file['error']) ? $this->label(
418
                'The uploaded file exceeds {size} bytes.',
419
                ['size' => $_GET['MAX_FILE_SIZE']]
420
            ) : ((UPLOAD_ERR_PARTIAL == $file['error']) ? $this->label('The uploaded file was only partially uploaded.') : ((UPLOAD_ERR_NO_FILE == $file['error']) ? $this->label('No file was uploaded.') : ((UPLOAD_ERR_NO_TMP_DIR == $file['error']) ? $this->label(
421
                'Missing a temporary folder.'
422
            ) : ((UPLOAD_ERR_CANT_WRITE == $file['error']) ? $this->label('Failed to write file.') : $this->label('Unknown error.'))))));
423
        } // HIDDEN FILENAMES CHECK
424
        elseif ('.' == substr($file['name'], 0, 1)) {
425
            return $this->label("File name shouldn't begins with '.'");
426
        } // EXTENSION CHECK
427
        elseif (('.' == substr($file['name'], -1)) || !$this->validateExtension($extension, $this->type)) {
428
            return $this->label('Denied file extension.');
429
        } // SPECIAL DIRECTORY TYPES CHECK (e.g. *img)
430
        elseif (preg_match('/^\*([^ ]+)(.*)?$/s', $typePatt, $patt)) {
431
            list($typePatt, $type, $params) = $patt;
432
            $class = __NAMESPACE__ . "\\type_$type";
433
            if (class_exists($class)) {
434
                $type            = new $class();
435
                $cfg             = $config;
436
                $cfg['filename'] = $file['name'];
437
                if (strlen($params)) {
438
                    $cfg['params'] = trim($params);
439
                }
440
                $response = $type->checkFile($file['tmp_name'], $cfg);
441
                if (true !== $response) {
442
                    return $this->label($response);
443
                }
444
            } else {
445
                return $this->label('Non-existing directory type.');
446
            }
447
        }
448
449
        // IMAGE RESIZE
450
        $img = image::factory($this->imageDriver, $file['tmp_name']);
451
        if (!$img->initError && !$this->imageResize($img, $file['tmp_name'])) {
452
            return $this->label('The image is too big and/or cannot be resized.');
453
        }
454
455
        return true;
456
    }
457
458
    protected function checkInputDir($dir, $inclType = true, $existing = true)
459
    {
460
        $dir = path::normalize($dir);
461
        if ('/' == substr($dir, 0, 1)) {
462
            $dir = substr($dir, 1);
463
        }
464
465
        if (('.' == substr($dir, 0, 1)) || ('.' == substr(basename($dir), 0, 1))) {
466
            return false;
467
        }
468
469
        if ($inclType) {
470
            $first = explode('/', $dir);
471
            $first = $first[0];
472
            if ($first != $this->type) {
473
                return false;
474
            }
475
            $return = $this->removeTypeFromPath($dir);
476
        } else {
477
            $return = $dir;
478
            $dir    = "{$this->type}/$dir";
479
        }
480
481
        if (!$existing) {
482
            return $return;
483
        }
484
485
        $path = "{$this->config['uploadDir']}/$dir";
486
        return (is_dir($path) && is_readable($path)) ? $return : false;
487
    }
488
489
    protected function validateExtension($ext, $type)
490
    {
491
        $ext = trim(strtolower($ext));
492
        if (!isset($this->types[$type])) {
493
            return false;
494
        }
495
496
        $exts = strtolower(text::clearWhitespaces($this->config['deniedExts']));
497
        if (strlen($exts)) {
498
            $exts = explode(' ', $exts);
499
            if (in_array($ext, $exts)) {
500
                return false;
501
            }
502
        }
503
504
        $exts = trim($this->types[$type]);
505
        if (!strlen($exts) || '*' == substr($exts, 0, 1)) {
506
            return true;
507
        }
508
509
        if ('!' == substr($exts, 0, 1)) {
510
            $exts = explode(' ', trim(strtolower(substr($exts, 1))));
511
            return !in_array($ext, $exts);
512
        }
513
514
        $exts = explode(' ', trim(strtolower($exts)));
515
        return in_array($ext, $exts);
516
    }
517
518
    protected function getTypeFromPath($path)
519
    {
520
        return preg_match('/^([^\/]*)\/.*$/', $path, $patt) ? $patt[1] : $path;
521
    }
522
523
    protected function removeTypeFromPath($path)
524
    {
525
        return preg_match('/^[^\/]*\/(.*)$/', $path, $patt) ? $patt[1] : '';
526
    }
527
528
    protected function imageResize($image, $file = null)
529
    {
530
        if (!($image instanceof image)) {
531
            $img = image::factory($this->imageDriver, $image);
532
            if ($img->initError) {
533
                return false;
534
            }
535
            $file = $image;
536
        } elseif (null === $file) {
537
            return false;
538
        } else {
539
            $img = $image;
540
        }
541
542
        $orientation = 1;
543
        if (function_exists('exif_read_data')) {
544
            $orientation = @exif_read_data($file);
545
            $orientation = isset($orientation['Orientation']) ? $orientation['Orientation'] : 1;
546
        }
547
548
        // IMAGE WILL NOT BE RESIZED WHEN NO WATERMARK AND SIZE IS ACCEPTABLE
549
        if ((!isset($this->config['watermark']['file']) || (!strlen(trim($this->config['watermark']['file']))))
550
            && ((!$this->config['maxImageWidth'] && !$this->config['maxImageHeight']) || (($img->width <= $this->config['maxImageWidth']) && ($img->height <= $this->config['maxImageHeight'])))
0 ignored issues
show
Bug Best Practice introduced by
The property $height is declared protected in kcfinder\image. Since you implement __get, consider adding a @property or @property-read.
Loading history...
Bug Best Practice introduced by
The property $width is declared protected in kcfinder\image. Since you implement __get, consider adding a @property or @property-read.
Loading history...
551
            && (1 == $orientation)) {
552
            return true;
553
        }
554
555
        // PROPORTIONAL RESIZE
556
        if ((!$this->config['maxImageWidth'] || !$this->config['maxImageHeight'])) {
557
            if ($this->config['maxImageWidth'] && ($this->config['maxImageWidth'] < $img->width)) {
558
                $width  = $this->config['maxImageWidth'];
559
                $height = $img->getPropHeight($width);
560
            } elseif ($this->config['maxImageHeight'] && ($this->config['maxImageHeight'] < $img->height)) {
561
                $height = $this->config['maxImageHeight'];
562
                $width  = $img->getPropWidth($height);
563
            }
564
565
            if (isset($width) && isset($height) && !$img->resize($width, $height)) {
566
                return false;
567
            }
568
            // RESIZE TO FIT
569
        } elseif ($this->config['maxImageWidth'] && $this->config['maxImageHeight'] && !$img->resizeFit($this->config['maxImageWidth'], $this->config['maxImageHeight'])) {
570
            return false;
571
        }
572
573
        // AUTO FLIP AND ROTATE FROM EXIF
574
        if (((2 == $orientation) && !$img->flipHorizontal()) || ((3 == $orientation) && !$img->rotate(180)) || ((4 == $orientation) && !$img->flipVertical()) || ((5 == $orientation) && (!$img->flipVertical() || !$img->rotate(90))) || ((6 == $orientation) && !$img->rotate(90))
575
            || ((7 == $orientation)
576
                && (!$img->flipHorizontal()
577
                    || !$img->rotate(
578
                        90
579
                    )))
580
            || ((8 == $orientation) && !$img->rotate(270))) {
581
            return false;
582
        }
583
        if (($orientation >= 2) && ($orientation <= 8) && ('imagick' == $this->imageDriver)) {
584
            try {
585
                $img->image->setImageProperty('exif:Orientation', '1');
0 ignored issues
show
Bug Best Practice introduced by
The property $image is declared protected in kcfinder\image. Since you implement __get, consider adding a @property or @property-read.
Loading history...
586
            } catch (\Exception $e) {
0 ignored issues
show
Coding Style Comprehensibility introduced by
Consider adding a comment why this CATCH block is empty.
Loading history...
587
            }
588
        }
589
590
        // WATERMARK
591
        if (isset($this->config['watermark']['file']) && is_file($this->config['watermark']['file'])) {
592
            $left = isset($this->config['watermark']['left']) ? $this->config['watermark']['left'] : false;
593
            $top  = isset($this->config['watermark']['top']) ? $this->config['watermark']['top'] : false;
594
            $img->watermark($this->config['watermark']['file'], $left, $top);
595
        }
596
597
        // WRITE TO FILE
598
        return $img->output(
599
            'jpeg',
600
            [
601
                'file'    => $file,
602
                'quality' => $this->config['jpegQuality']
603
            ]
604
        );
605
    }
606
607
    protected function makeThumb($file, $overwrite = true)
608
    {
609
        $img = image::factory($this->imageDriver, $file);
610
611
        // Drop files which are not images
612
        if ($img->initError) {
613
            return true;
614
        }
615
616
        $fimg = new fastImage($file);
617
        $type = $fimg->getType();
618
        $fimg->close();
619
620
        if (false === $type) {
621
            return true;
622
        }
623
624
        $thumb    = substr($file, strlen($this->config['uploadDir']));
625
        $thumb    = $this->config['uploadDir'] . '/' . $this->config['thumbsDir'] . '/' . $thumb;
626
        $thumb    = path::normalize($thumb);
627
        $thumbDir = dirname($thumb);
628
        if (!is_dir($thumbDir) && !@mkdir($thumbDir, $this->config['dirPerms'], true)) {
629
            return false;
630
        }
631
632
        if (!$overwrite && is_file($thumb)) {
633
            return true;
634
        }
635
636
        // Images with smaller resolutions than thumbnails
637
        if (($img->width <= $this->config['thumbWidth']) && ($img->height <= $this->config['thumbHeight'])) {
638
            // Drop only browsable types
639
            if (in_array($type, ['gif', 'jpeg', 'png'])) {
640
                return true;
641
            }
642
            // Resize image
643
        } elseif (!$img->resizeFit($this->config['thumbWidth'], $this->config['thumbHeight'])) {
644
            return false;
645
        }
646
647
        // Save thumbnail
648
        $options = ['file' => $thumb];
649
        if ('gif' == $type) {
650
            $type = 'jpeg';
651
        }
652
        if ('jpeg' == $type) {
653
            $options['quality'] = $this->config['jpegQuality'];
654
        }
655
        return $img->output($type, $options);
656
    }
657
658
    protected function localize($langCode)
659
    {
660
        require "lang/{$langCode}.php";
661
        setlocale(LC_ALL, $lang['_locale']);
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $lang seems to be never defined.
Loading history...
662
        $this->charset       = $lang['_charset'];
663
        $this->dateTimeFull  = $lang['_dateTimeFull'];
664
        $this->dateTimeMid   = $lang['_dateTimeMid'];
665
        $this->dateTimeSmall = $lang['_dateTimeSmall'];
666
        unset($lang['_locale']);
667
        unset($lang['_charset']);
668
        unset($lang['_dateTimeFull']);
669
        unset($lang['_dateTimeMid']);
670
        unset($lang['_dateTimeSmall']);
671
        $this->labels = $lang;
672
    }
673
674
    protected function label($string, array $data = null)
675
    {
676
        $return = isset($this->labels[$string]) ? $this->labels[$string] : $string;
677
        if (is_array($data)) {
678
            foreach ($data as $key => $val) {
679
                $return = str_replace("{{$key}}", $val, $return);
680
            }
681
        }
682
        return $return;
683
    }
684
685
    protected function backMsg($message, array $data = null)
686
    {
687
        $message  = $this->label($message, $data);
688
        $tmp_name = isset($this->file['tmp_name']) ? $this->file['tmp_name'] : false;
689
690
        if ($tmp_name) {
691
            $tmp_name = (is_array($tmp_name) && isset($tmp_name[0])) ? $tmp_name[0] : $tmp_name;
692
693
            if (file_exists($tmp_name)) {
694
                @unlink($tmp_name);
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition for unlink(). This can introduce security issues, and is generally not recommended. ( Ignorable by Annotation )

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

694
                /** @scrutinizer ignore-unhandled */ @unlink($tmp_name);

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...
695
            }
696
        }
697
        $this->callBack('', $message);
698
        die;
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...
699
    }
700
701
    protected function callBack($url, $message = '')
702
    {
703
        $message = text::jsValue($message);
704
705
        if (("kcfinder\\browser" == get_class($this)) && ('browser' != $this->action)) {
0 ignored issues
show
Bug Best Practice introduced by
The property action does not exist on kcfinder\uploader. Since you implemented __get, consider adding a @property annotation.
Loading history...
706
            return;
707
        }
708
709
        if (isset($this->opener['name'])) {
710
            $method = "callBack_{$this->opener['name']}";
711
            if (method_exists($this, $method)) {
712
                $js = $this->$method($url, $message);
713
            }
714
        }
715
716
        if (!isset($js)) {
717
            $js = $this->callBack_default($url, $message);
718
        }
719
720
        header("Content-Type: text/html; charset={$this->charset}");
721
        echo "<html><body>$js</body></html>";
722
    }
723
724
    protected function callBack_ckeditor($url, $message)
725
    {
726
        $CKfuncNum = isset($this->opener['CKEditor']['funcNum']) ? $this->opener['CKEditor']['funcNum'] : 0;
727
        if (!$CKfuncNum) {
728
            $CKfuncNum = 0;
729
        }
730
        return "<script type='text/javascript'>
731
var par = window.parent,
732
    op = window.opener,
733
    o = (par && par.CKEDITOR) ? par : ((op && op.CKEDITOR) ? op : false);
734
if (o !== false) {
735
    if (op) window.close();
736
    o.CKEDITOR.tools.callFunction($CKfuncNum, '$url', '$message');
737
} else {
738
    alert('$message');
739
    if (op) window.close();
740
}
741
</script>";
742
    }
743
744
    protected function callBack_fckeditor($url, $message)
745
    {
746
        $n = strlen($message) ? 1 : 0;
747
        return "<script type='text/javascript'>
748
var par = window.parent,
749
    op = window.opener,
750
    o = (op && op.OnUploadCompleted) ? op.OnUploadCompleted : ((par && par.OnUploadCompleted) ? par.OnUploadCompleted : false);
751
if (o !== false) {
752
    if (op) window.close();
753
    o($n, '$url', '', '$message');
754
} else {
755
    alert('$message');
756
    if (op) window.close();
757
}
758
</script>";
759
    }
760
761
    protected function callBack_tinymce($url, $message)
762
    {
763
        return $this->callBack_default($url, $message);
764
    }
765
766
    protected function callBack_tinymce4($url, $message)
767
    {
768
        return $this->callBack_default($url, $message);
769
    }
770
771
    protected function callBack_default($url, $message)
772
    {
773
        return "<script type='text/javascript'>
774
alert('$message');
775
if (window.opener) window.close();
776
</script>";
777
    }
778
779
    protected function get_htaccess()
780
    {
781
        return file_get_contents('conf/upload.htaccess');
782
    }
783
}
784