Issues (1240)

Security Analysis    not enabled

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

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

system/libraries/Image.php (9 issues)

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

1
<?php defined('SYSPATH') or die('No direct access allowed.');
2
/**
3
 * Manipulate images using standard methods such as resize, crop, rotate, etc.
4
 * This class must be re-initialized for every image you wish to manipulate.
5
 *
6
 * $Id: Image.php 4072 2009-03-13 17:20:38Z jheathco $
7
 *
8
 * @package    Image
9
 * @author     Kohana Team
10
 * @copyright  (c) 2007-2008 Kohana Team
11
 * @license    http://kohanaphp.com/license.html
12
 */
13
class Image_Core
14
{
15
16
    // Master Dimension
17
    const NONE = 1;
18
    const AUTO = 2;
19
    const HEIGHT = 3;
20
    const WIDTH = 4;
21
    // Flip Directions
22
    const HORIZONTAL = 5;
23
    const VERTICAL = 6;
24
25
    // Allowed image types
26
    public static $allowed_types = array(
27
        IMAGETYPE_GIF => 'gif',
28
        IMAGETYPE_JPEG => 'jpg',
29
        IMAGETYPE_PNG => 'png',
30
        IMAGETYPE_TIFF_II => 'tiff',
31
        IMAGETYPE_TIFF_MM => 'tiff',
32
    );
33
34
    // Driver instance
35
    protected $driver;
36
37
    // Driver actions
38
    protected $actions = array();
39
40
    // Reference to the current image filename
41
    protected $image = '';
42
43
    /**
44
     * Creates a new Image instance and returns it.
45
     *
46
     * @param   string   filename of image
47
     * @param   array    non-default configurations
48
     * @return  object
0 ignored issues
show
Consider making the return type a bit more specific; maybe use Image.

This check looks for the generic type array as a return type and suggests a more specific type. This type is inferred from the actual code.

Loading history...
49
     */
50
    public static function factory($image, $config = null)
51
    {
52
        return new Image($image, $config);
53
    }
54
55
    /**
56
     * Creates a new image editor instance.
57
     *
58
     * @throws  Kohana_Exception
59
     * @param   string   filename of image
60
     * @param   array    non-default configurations
61
     * @return  void
0 ignored issues
show
Comprehensibility Best Practice introduced by
Adding a @return annotation to constructors is generally not recommended as a constructor does not have a meaningful return value.

Adding a @return annotation to a constructor is not recommended, since a constructor does not have a meaningful return value.

Please refer to the PHP core documentation on constructors.

Loading history...
62
     */
63
    public function __construct($image, $config = null)
64
    {
65
        static $check;
66
67
        // Make the check exactly once
68
        ($check === null) and $check = function_exists('getimagesize');
69
70
        if ($check === false) {
71
            throw new Kohana_Exception('image.getimagesize_missing');
72
        }
73
74
        // Check to make sure the image exists
75
        if (! is_file($image)) {
76
            throw new Kohana_Exception('image.file_not_found', $image);
77
        }
78
79
        // Disable error reporting, to prevent PHP warnings
80
        $ER = error_reporting(0);
0 ignored issues
show
Comprehensibility introduced by
Avoid variables with short names like $ER. Configured minimum length is 3.

Short variable names may make your code harder to understand. Variable names should be self-descriptive. This check looks for variable names who are shorter than a configured minimum.

Loading history...
81
82
        // Fetch the image size and mime type
83
        $image_info = getimagesize($image);
84
85
        // Turn on error reporting again
86
        error_reporting($ER);
87
88
        // Make sure that the image is readable and valid
89
        if (! is_array($image_info) or count($image_info) < 3) {
90
            throw new Kohana_Exception('image.file_unreadable', $image);
91
        }
92
93
        // Check to make sure the image type is allowed
94
        if (! isset(Image::$allowed_types[$image_info[2]])) {
95
            throw new Kohana_Exception('image.type_not_allowed', $image);
96
        }
97
98
        // Image has been validated, load it
99
        $this->image = array(
0 ignored issues
show
Documentation Bug introduced by
It seems like array('file' => str_repl...=> $image_info['mime']) of type array<string,?,{"file":"...,"ext":"?","mime":"?"}> is incompatible with the declared type string of property $image.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
100
            'file' => str_replace('\\', '/', realpath($image)),
101
            'width' => $image_info[0],
102
            'height' => $image_info[1],
103
            'type' => $image_info[2],
104
            'ext' => Image::$allowed_types[$image_info[2]],
105
            'mime' => $image_info['mime']
106
        );
107
108
        // Load configuration
109
        $this->config = (array) $config + Kohana::config('image');
0 ignored issues
show
The property config does not exist. Did you maybe forget to declare it?

In PHP it is possible to write to properties without declaring them. For example, the following is perfectly valid PHP code:

class MyClass { }

$x = new MyClass();
$x->foo = true;

Generally, it is a good practice to explictly declare properties to avoid accidental typos and provide IDE auto-completion:

class MyClass {
    public $foo;
}

$x = new MyClass();
$x->foo = true;
Loading history...
110
111
        // Set driver class name
112
        $driver = 'Image_'.ucfirst($this->config['driver']).'_Driver';
113
114
        // Load the driver
115 View Code Duplication
        if (! Kohana::auto_load($driver)) {
0 ignored issues
show
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
116
            throw new Kohana_Exception('core.driver_not_found', $this->config['driver'], get_class($this));
117
        }
118
119
        // Initialize the driver
120
        $this->driver = new $driver($this->config['params']);
121
122
        // Validate the driver
123 View Code Duplication
        if (! ($this->driver instanceof Image_Driver)) {
0 ignored issues
show
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
124
            throw new Kohana_Exception('core.driver_implements', $this->config['driver'], get_class($this), 'Image_Driver');
125
        }
126
    }
127
128
    /**
129
     * Handles retrieval of pre-save image properties
130
     *
131
     * @param   string  property name
132
     * @return  string
133
     */
134
    public function __get($property)
135
    {
136
        if (isset($this->image[$property])) {
137
            return $this->image[$property];
138
        } else {
139
            throw new Kohana_Exception('core.invalid_property', $property, get_class($this));
140
        }
141
    }
142
143
    /**
144
     * Resize an image to a specific width and height. By default, Kohana will
145
     * maintain the aspect ratio using the width as the master dimension. If you
146
     * wish to use height as master dim, set $image->master_dim = Image::HEIGHT
147
     * This method is chainable.
148
     *
149
     * @throws  Kohana_Exception
150
     * @param   integer  width
151
     * @param   integer  height
152
     * @param   integer  one of: Image::NONE, Image::AUTO, Image::WIDTH, Image::HEIGHT
153
     * @return  Image_Core
154
     */
155
    public function resize($width, $height, $master = null)
156
    {
157
        if (! $this->valid_size('width', $width)) {
158
            throw new Kohana_Exception('image.invalid_width', $width);
159
        }
160
161
        if (! $this->valid_size('height', $height)) {
162
            throw new Kohana_Exception('image.invalid_height', $height);
163
        }
164
165
        if (empty($width) and empty($height)) {
166
            throw new Kohana_Exception('image.invalid_dimensions', __FUNCTION__);
167
        }
168
169
        if ($master === null) {
170
            // Maintain the aspect ratio by default
171
            $master = Image::AUTO;
172
        } elseif (! $this->valid_size('master', $master)) {
173
            throw new Kohana_Exception('image.invalid_master');
174
        }
175
176
        $this->actions['resize'] = array(
177
            'width'  => $width,
178
            'height' => $height,
179
            'master' => $master,
180
        );
181
182
        return $this;
183
    }
184
185
    /**
186
     * Crop an image to a specific width and height. You may also set the top
187
     * and left offset.
188
     * This method is chainable.
189
     *
190
     * @throws  Kohana_Exception
191
     * @param   integer  width
192
     * @param   integer  height
193
     * @param   integer  top offset, pixel value or one of: top, center, bottom
194
     * @param   integer  left offset, pixel value or one of: left, center, right
195
     * @return  Image_Core
196
     */
197
    public function crop($width, $height, $top = 'center', $left = 'center')
198
    {
199
        if (! $this->valid_size('width', $width)) {
200
            throw new Kohana_Exception('image.invalid_width', $width);
201
        }
202
203
        if (! $this->valid_size('height', $height)) {
204
            throw new Kohana_Exception('image.invalid_height', $height);
205
        }
206
207
        if (! $this->valid_size('top', $top)) {
208
            throw new Kohana_Exception('image.invalid_top', $top);
209
        }
210
211
        if (! $this->valid_size('left', $left)) {
212
            throw new Kohana_Exception('image.invalid_left', $left);
213
        }
214
215
        if (empty($width) and empty($height)) {
216
            throw new Kohana_Exception('image.invalid_dimensions', __FUNCTION__);
217
        }
218
219
        $this->actions['crop'] = array(
220
            'width'  => $width,
221
            'height' => $height,
222
            'top'    => $top,
223
            'left'   => $left,
224
        );
225
226
        return $this;
227
    }
228
229
    /**
230
     * Allows rotation of an image by 180 degrees clockwise or counter clockwise.
231
     *
232
     * @param   integer  degrees
233
     * @return  Image_Core
234
     */
235
    public function rotate($degrees)
236
    {
237
        $degrees = (int) $degrees;
238
239
        if ($degrees > 180) {
240
            do {
241
                // Keep subtracting full circles until the degrees have normalized
242
                $degrees -= 360;
243
            } while ($degrees > 180);
244
        }
245
246
        if ($degrees < -180) {
247
            do {
248
                // Keep adding full circles until the degrees have normalized
249
                $degrees += 360;
250
            } while ($degrees < -180);
251
        }
252
253
        $this->actions['rotate'] = $degrees;
254
255
        return $this;
256
    }
257
258
    /**
259
     * Flip an image horizontally or vertically.
260
     *
261
     * @throws  Kohana_Exception
262
     * @param   integer  direction
263
     * @return  Image_Core
264
     */
265
    public function flip($direction)
266
    {
267
        if ($direction !== Image::HORIZONTAL and $direction !== Image::VERTICAL) {
268
            throw new Kohana_Exception('image.invalid_flip');
269
        }
270
271
        $this->actions['flip'] = $direction;
272
273
        return $this;
274
    }
275
276
    /**
277
     * Change the quality of an image.
278
     *
279
     * @param   integer  quality as a percentage
280
     * @return  Image_Core
281
     */
282
    public function quality($amount)
283
    {
284
        $this->actions['quality'] = max(1, min($amount, 100));
285
286
        return $this;
287
    }
288
289
    /**
290
     * Sharpen an image.
291
     *
292
     * @param   integer  amount to sharpen, usually ~20 is ideal
293
     * @return  Image_Core
294
     */
295
    public function sharpen($amount)
296
    {
297
        $this->actions['sharpen'] = max(1, min($amount, 100));
298
299
        return $this;
300
    }
301
302
    /**
303
     * Save the image to a new image or overwrite this image.
304
     *
305
     * @throws  Kohana_Exception
306
     * @param   string   new image filename
307
     * @param   integer  permissions for new image
308
     * @param   boolean  keep or discard image process actions
309
     * @return  object
310
     */
311
    public function save($new_image = false, $chmod = 0644, $keep_actions = false)
312
    {
313
        // If no new image is defined, use the current image
314
        empty($new_image) and $new_image = $this->image['file'];
315
316
        // Separate the directory and filename
317
        $dir  = pathinfo($new_image, PATHINFO_DIRNAME);
318
        $file = pathinfo($new_image, PATHINFO_BASENAME);
319
320
        // Normalize the path
321
        $dir = str_replace('\\', '/', realpath($dir)).'/';
322
323
        if (! is_writable($dir)) {
324
            throw new Kohana_Exception('image.directory_unwritable', $dir);
325
        }
326
327
        if ($status = $this->driver->process($this->image, $this->actions, $dir, $file)) {
328
            if ($chmod !== false) {
329
                // Set permissions
330
                chmod($new_image, $chmod);
331
            }
332
        }
333
334
        // Reset actions. Subsequent save() or render() will not apply previous actions.
335
        if ($keep_actions === false) {
336
            $this->actions = array();
337
        }
338
339
        return $status;
340
    }
341
342
    /**
343
     * Output the image to the browser.
344
     *
345
     * @param   boolean  keep or discard image process actions
346
     * @return	object
347
     */
348
    public function render($keep_actions = false)
349
    {
350
        $new_image = $this->image['file'];
351
352
        // Separate the directory and filename
353
        $dir  = pathinfo($new_image, PATHINFO_DIRNAME);
354
        $file = pathinfo($new_image, PATHINFO_BASENAME);
355
356
        // Normalize the path
357
        $dir = str_replace('\\', '/', realpath($dir)).'/';
358
359
        // Process the image with the driver
360
        $status = $this->driver->process($this->image, $this->actions, $dir, $file, $render = true);
361
362
        // Reset actions. Subsequent save() or render() will not apply previous actions.
363
        if ($keep_actions === false) {
364
            $this->actions = array();
365
        }
366
367
        return $status;
368
    }
369
370
    /**
371
     * Sanitize a given value type.
372
     *
373
     * @param   string   type of property
374
     * @param   mixed    property value
375
     * @param string $type
376
     * @return  boolean
377
     */
378
    protected function valid_size($type, & $value)
379
    {
380
        if (is_null($value)) {
381
            return true;
382
        }
383
384
        if (! is_scalar($value)) {
385
            return false;
386
        }
387
388
        switch ($type) {
389
            case 'width':
390
            case 'height':
391
                if (is_string($value) and ! ctype_digit($value)) {
392
                    // Only numbers and percent signs
393
                    if (! preg_match('/^[0-9]++%$/D', $value)) {
394
                        return false;
395
                    }
396
                } else {
397
                    $value = (int) $value;
398
                }
399
            break;
400 View Code Duplication
            case 'top':
0 ignored issues
show
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
401
                if (is_string($value) and ! ctype_digit($value)) {
402
                    if (! in_array($value, array('top', 'bottom', 'center'))) {
403
                        return false;
404
                    }
405
                } else {
406
                    $value = (int) $value;
407
                }
408
            break;
409 View Code Duplication
            case 'left':
0 ignored issues
show
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
410
                if (is_string($value) and ! ctype_digit($value)) {
411
                    if (! in_array($value, array('left', 'right', 'center'))) {
412
                        return false;
413
                    }
414
                } else {
415
                    $value = (int) $value;
416
                }
417
            break;
418
            case 'master':
419
                if ($value !== Image::NONE and
420
                    $value !== Image::AUTO and
421
                    $value !== Image::WIDTH and
422
                    $value !== Image::HEIGHT) {
423
                    return false;
424
                }
425
            break;
426
        }
427
428
        return true;
429
    }
430
} // End Image
431