Completed
Push — master ( b871dd...c32ae6 )
by Mikael
07:45 queued 05:18
created

webroot/img.php (19 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
0 ignored issues
show
Coding Style Compatibility introduced by
For compatibility and reusability of your code, PSR1 recommends that a file should introduce either new symbols (like classes, functions, etc.) or have side-effects (like outputting something, or including other files), but not both at the same time. The first symbol is defined on line 23 and the first side effect is on line 11.

The PSR-1: Basic Coding Standard recommends that a file should either introduce new symbols, that is classes, functions, constants or similar, or have side effects. Side effects are anything that executes logic, like for example printing output, changing ini settings or writing to a file.

The idea behind this recommendation is that merely auto-loading a class should not change the state of an application. It also promotes a cleaner style of programming and makes your code less prone to errors, because the logic is not spread out all over the place.

To learn more about the PSR-1, please see the PHP-FIG site on the PSR-1.

Loading history...
2
/**
3
 * Resize and crop images on the fly, store generated images in a cache.
4
 *
5
 * @author  Mikael Roos [email protected]
6
 * @example http://dbwebb.se/opensource/cimage
7
 * @link    https://github.com/mosbth/cimage
8
 *
9
 */
10
11
$version = "v0.7.8 (2015-12-06)";
12
13
14
15
/**
16
 * Display error message.
17
 *
18
 * @param string $msg to display.
19
 * @param int $type of HTTP error to display.
20
 *
21
 * @return void
22
 */
23
function errorPage($msg, $type = 500)
24
{
25
    global $mode;
26
27
    switch ($type) {
28
        case 403:
29
            $header = "403 Forbidden";
30
        break;
31
        case 404:
32
            $header = "404 Not Found";
33
        break;
34
        default:
35
            $header = "500 Internal Server Error";
36
    }
37
38
    header("HTTP/1.0 $header");
39
40
    if ($mode == 'development') {
41
        die("[img.php] $msg");
42
    }
43
44
    error_log("[img.php] $msg");
45
    die("HTTP/1.0 $header");
0 ignored issues
show
Coding Style Compatibility introduced by
The function errorPage() contains an exit expression.

An exit expression should only be used in rare cases. For example, if you write a short command line script.

In most cases however, using an exit expression makes the code untestable and often causes incompatibilities with other libraries. Thus, unless you are absolutely sure it is required here, we recommend to refactor your code to avoid its usage.

Loading history...
46
}
47
48
49
50
/**
51
 * Custom exception handler.
52
 */
53
set_exception_handler(function ($exception) {
54
    errorPage(
55
        "<p><b>img.php: Uncaught exception:</b> <p>"
56
        . $exception->getMessage()
57
        . "</p><pre>"
58
        . $exception->getTraceAsString()
59
        . "</pre>"
60
    , 500);
61
});
62
63
64
65
/**
66
 * Get input from query string or return default value if not set.
67
 *
68
 * @param mixed $key     as string or array of string values to look for in $_GET.
69
 * @param mixed $default value to return when $key is not set in $_GET.
70
 *
71
 * @return mixed value from $_GET or default value.
72
 */
73
function get($key, $default = null)
74
{
75
    if (is_array($key)) {
76
        foreach ($key as $val) {
77
            if (isset($_GET[$val])) {
78
                return $_GET[$val];
79
            }
80
        }
81
    } elseif (isset($_GET[$key])) {
82
        return $_GET[$key];
83
    }
84
    return $default;
85
}
86
87
88
89
/**
90
 * Get input from query string and set to $defined if defined or else $undefined.
91
 *
92
 * @param mixed $key       as string or array of string values to look for in $_GET.
93
 * @param mixed $defined   value to return when $key is set in $_GET.
94
 * @param mixed $undefined value to return when $key is not set in $_GET.
95
 *
96
 * @return mixed value as $defined or $undefined.
97
 */
98
function getDefined($key, $defined, $undefined)
99
{
100
    return get($key) === null ? $undefined : $defined;
101
}
102
103
104
105
/**
106
 * Get value from config array or default if key is not set in config array.
107
 *
108
 * @param string $key    the key in the config array.
109
 * @param mixed $default value to be default if $key is not set in config.
110
 *
111
 * @return mixed value as $config[$key] or $default.
112
 */
113
function getConfig($key, $default)
114
{
115
    global $config;
116
    return isset($config[$key])
117
        ? $config[$key]
118
        : $default;
119
}
120
121
122
123
/**
124
 * Log when verbose mode, when used without argument it returns the result.
125
 *
126
 * @param string $msg to log.
127
 *
128
 * @return void or array.
129
 */
130
function verbose($msg = null)
131
{
132
    global $verbose, $verboseFile;
133
    static $log = array();
134
135
    if (!($verbose || $verboseFile)) {
136
        return;
137
    }
138
139
    if (is_null($msg)) {
140
        return $log;
141
    }
142
143
    $log[] = $msg;
144
}
145
146
147
148
/**
149
 * Get configuration options from file, if the file exists, else use $config
150
 * if its defined or create an empty $config.
151
 */
152
$configFile = __DIR__.'/'.basename(__FILE__, '.php').'_config.php';
153
154
if (is_file($configFile)) {
155
    $config = require $configFile;
156
} elseif (!isset($config)) {
157
    $config = array();
158
}
159
160
161
162
/**
163
* verbose, v - do a verbose dump of what happens
164
* vf - do verbose dump to file
165
*/
166
$verbose = getDefined(array('verbose', 'v'), true, false);
167
$verboseFile = getDefined('vf', true, false);
168
verbose("img.php version = $version");
169
170
171
172
/**
173
* status - do a verbose dump of the configuration
174
*/
175
$status = getDefined('status', true, false);
176
177
178
179
/**
180
 * Set mode as strict, production or development.
181
 * Default is production environment.
182
 */
183
$mode = getConfig('mode', 'production');
184
185
// Settings for any mode
186
set_time_limit(20);
187
ini_set('gd.jpeg_ignore_warning', 1);
188
189
if (!extension_loaded('gd')) {
190
    errorPage("Extension gd is not loaded.", 500);
191
}
192
193
// Specific settings for each mode
194
if ($mode == 'strict') {
195
196
    error_reporting(0);
197
    ini_set('display_errors', 0);
198
    ini_set('log_errors', 1);
199
    $verbose = false;
200
    $status = false;
201
    $verboseFile = false;
202
203
} elseif ($mode == 'production') {
204
205
    error_reporting(-1);
206
    ini_set('display_errors', 0);
207
    ini_set('log_errors', 1);
208
    $verbose = false;
209
    $status = false;
210
    $verboseFile = false;
211
212
} elseif ($mode == 'development') {
213
214
    error_reporting(-1);
215
    ini_set('display_errors', 1);
216
    ini_set('log_errors', 0);
217
    $verboseFile = false;
218
219
} elseif ($mode == 'test') {
220
221
    error_reporting(-1);
222
    ini_set('display_errors', 1);
223
    ini_set('log_errors', 0);
224
225
} else {
226
    errorPage("Unknown mode: $mode", 500);
227
}
228
229
verbose("mode = $mode");
230
verbose("error log = " . ini_get('error_log'));
231
232
233
234
/**
235
 * Set default timezone if not set or if its set in the config-file.
236
 */
237
$defaultTimezone = getConfig('default_timezone', null);
238
239
if ($defaultTimezone) {
240
    date_default_timezone_set($defaultTimezone);
241
} elseif (!ini_get('default_timezone')) {
242
    date_default_timezone_set('UTC');
243
}
244
245
246
247
/**
248
 * Check if passwords are configured, used and match.
249
 * Options decide themself if they require passwords to be used.
250
 */
251
$pwdConfig   = getConfig('password', false);
252
$pwdAlways   = getConfig('password_always', false);
253
$pwdType     = getConfig('password_type', 'text');
254
$pwd         = get(array('password', 'pwd'), null);
255
256
// Check if passwords match, if configured to use passwords
257
$passwordMatch = null;
258
if ($pwd) {
259
    switch($pwdType) {
260
        case 'md5':
261
            $passwordMatch = ($pwdConfig === md5($pwd));
262
            break;
263
        case 'hash':
264
            $passwordMatch = password_verify($pwd, $pwdConfig);
265
            break;
266
        case 'text':
267
            $passwordMatch = ($pwdConfig === $pwd);
268
            break;
269
        default:
270
            $passwordMatch = false;
271
    }
272
}
273
274
if ($pwdAlways && $passwordMatch !== true) {
275
    errorPage("Password required and does not match or exists.", 403);
276
}
277
278
verbose("password match = $passwordMatch");
279
280
281
282
/**
283
 * Prevent hotlinking, leeching, of images by controlling who access them
284
 * from where.
285
 *
286
 */
287
$allowHotlinking = getConfig('allow_hotlinking', true);
288
$hotlinkingWhitelist = getConfig('hotlinking_whitelist', array());
289
290
$serverName  = isset($_SERVER['SERVER_NAME']) ? $_SERVER['SERVER_NAME'] : null;
291
$referer     = isset($_SERVER['HTTP_REFERER']) ? $_SERVER['HTTP_REFERER'] : null;
292
$refererHost = parse_url($referer, PHP_URL_HOST);
293
294
if (!$allowHotlinking) {
295
    if ($passwordMatch) {
296
        ; // Always allow when password match
297
        verbose("Hotlinking since passwordmatch");
298
    } elseif ($passwordMatch === false) {
299
        errorPage("Hotlinking/leeching not allowed when password missmatch.", 403);
300
    } elseif (!$referer) {
301
        errorPage("Hotlinking/leeching not allowed and referer is missing.", 403);
302
    } elseif (strcmp($serverName, $refererHost) == 0) {
303
        ; // Allow when serverName matches refererHost
304
        verbose("Hotlinking disallowed but serverName matches refererHost.");
305
    } elseif (!empty($hotlinkingWhitelist)) {
306
        $whitelist = new CWhitelist();
307
        $allowedByWhitelist = $whitelist->check($refererHost, $hotlinkingWhitelist);
0 ignored issues
show
It seems like $refererHost defined by parse_url($referer, PHP_URL_HOST) on line 292 can also be of type false; however, CWhitelist::check() does only seem to accept string, did you maybe forget to handle an error condition?

This check looks for type mismatches where the missing type is false. This is usually indicative of an error condtion.

Consider the follow example

<?php

function getDate($date)
{
    if ($date !== null) {
        return new DateTime($date);
    }

    return false;
}

This function either returns a new DateTime object or false, if there was an error. This is a typical pattern in PHP programming to show that an error has occurred without raising an exception. The calling code should check for this returned false before passing on the value to another function or method that may not be able to handle a false.

Loading history...
308
309
        if ($allowedByWhitelist) {
310
            verbose("Hotlinking/leeching allowed by whitelist.");
311
        } else {
312
            errorPage("Hotlinking/leeching not allowed by whitelist. Referer: $referer.", 403);
313
        }
314
315
    } else {
316
        errorPage("Hotlinking/leeching not allowed.", 403);
317
    }
318
}
319
320
verbose("allow_hotlinking = $allowHotlinking");
321
verbose("referer = $referer");
322
verbose("referer host = $refererHost");
323
324
325
326
/**
327
 * Get the source files.
328
 */
329
$autoloader  = getConfig('autoloader', false);
330
$cimageClass = getConfig('cimage_class', false);
331
332
if ($autoloader) {
333
    require $autoloader;
334
} elseif ($cimageClass) {
335
    require $cimageClass;
336
}
337
338
339
340
/**
341
 * Create the class for the image.
342
 */
343
$img = new CImage();
344
$img->setVerbose($verbose || $verboseFile);
345
346
347
348
/**
349
 * Allow or disallow remote download of images from other servers.
350
 * Passwords apply if used.
351
 *
352
 */
353
$allowRemote = getConfig('remote_allow', false);
354
355
if ($allowRemote && $passwordMatch !== false) {
356
    $pattern = getConfig('remote_pattern', null);
357
    $img->setRemoteDownload($allowRemote, $pattern);
358
359
    $whitelist = getConfig('remote_whitelist', null);
360
    $img->setRemoteHostWhitelist($whitelist);
361
}
362
363
364
365
/**
366
 * shortcut, sc - extend arguments with a constant value, defined
367
 * in config-file.
368
 */
369
$shortcut       = get(array('shortcut', 'sc'), null);
370
$shortcutConfig = getConfig('shortcut', array(
371
    'sepia' => "&f=grayscale&f0=brightness,-10&f1=contrast,-20&f2=colorize,120,60,0,0&sharpen",
372
));
373
374
verbose("shortcut = $shortcut");
375
376
if (isset($shortcut)
377
    && isset($shortcutConfig[$shortcut])) {
378
379
    parse_str($shortcutConfig[$shortcut], $get);
380
    verbose("shortcut-constant = {$shortcutConfig[$shortcut]}");
381
    $_GET = array_merge($_GET, $get);
382
}
383
384
385
386
/**
387
 * src - the source image file.
388
 */
389
$srcImage = urldecode(get('src'))
390
    or errorPage('Must set src-attribute.', 404);
0 ignored issues
show
Comprehensibility Best Practice introduced by
Using logical operators such as or instead of || is generally not recommended.

PHP has two types of connecting operators (logical operators, and boolean operators):

  Logical Operators Boolean Operator
AND - meaning and &&
OR - meaning or ||

The difference between these is the order in which they are executed. In most cases, you would want to use a boolean operator like &&, or ||.

Let’s take a look at a few examples:

// Logical operators have lower precedence:
$f = false or true;

// is executed like this:
($f = false) or true;


// Boolean operators have higher precedence:
$f = false || true;

// is executed like this:
$f = (false || true);

Logical Operators are used for Control-Flow

One case where you explicitly want to use logical operators is for control-flow such as this:

$x === 5
    or die('$x must be 5.');

// Instead of
if ($x !== 5) {
    die('$x must be 5.');
}

Since die introduces problems of its own, f.e. it makes our code hardly testable, and prevents any kind of more sophisticated error handling; you probably do not want to use this in real-world code. Unfortunately, logical operators cannot be combined with throw at this point:

// The following is currently a parse error.
$x === 5
    or throw new RuntimeException('$x must be 5.');

These limitations lead to logical operators rarely being of use in current PHP code.

Loading history...
391
392
// Check for valid/invalid characters
393
$imagePath           = getConfig('image_path', __DIR__ . '/img/');
394
$imagePathConstraint = getConfig('image_path_constraint', true);
395
$validFilename       = getConfig('valid_filename', '#^[a-z0-9A-Z-/_ \.:]+$#');
396
397
// Dummy image feature
398
$dummyEnabled  = getConfig('dummy_enabled', true);
399
$dummyFilename = getConfig('dummy_filename', 'dummy');
400
$dummyImage = false;
401
402
preg_match($validFilename, $srcImage)
403
    or errorPage('Filename contains invalid characters.', 404);
0 ignored issues
show
Comprehensibility Best Practice introduced by
Using logical operators such as or instead of || is generally not recommended.

PHP has two types of connecting operators (logical operators, and boolean operators):

  Logical Operators Boolean Operator
AND - meaning and &&
OR - meaning or ||

The difference between these is the order in which they are executed. In most cases, you would want to use a boolean operator like &&, or ||.

Let’s take a look at a few examples:

// Logical operators have lower precedence:
$f = false or true;

// is executed like this:
($f = false) or true;


// Boolean operators have higher precedence:
$f = false || true;

// is executed like this:
$f = (false || true);

Logical Operators are used for Control-Flow

One case where you explicitly want to use logical operators is for control-flow such as this:

$x === 5
    or die('$x must be 5.');

// Instead of
if ($x !== 5) {
    die('$x must be 5.');
}

Since die introduces problems of its own, f.e. it makes our code hardly testable, and prevents any kind of more sophisticated error handling; you probably do not want to use this in real-world code. Unfortunately, logical operators cannot be combined with throw at this point:

// The following is currently a parse error.
$x === 5
    or throw new RuntimeException('$x must be 5.');

These limitations lead to logical operators rarely being of use in current PHP code.

Loading history...
404
405
if ($dummyEnabled && $srcImage === $dummyFilename) {
406
407
    // Prepare to create a dummy image and use it as the source image.
408
    $dummyImage = true;
409
410
} elseif ($allowRemote && $img->isRemoteSource($srcImage)) {
411
412
    // If source is a remote file, ignore local file checks.
413
414
} elseif ($imagePathConstraint) {
415
416
    // Check that the image is a file below the directory 'image_path'.
417
    $pathToImage = realpath($imagePath . $srcImage);
418
    $imageDir    = realpath($imagePath);
419
420
    is_file($pathToImage)
421
        or errorPage(
0 ignored issues
show
Comprehensibility Best Practice introduced by
Using logical operators such as or instead of || is generally not recommended.

PHP has two types of connecting operators (logical operators, and boolean operators):

  Logical Operators Boolean Operator
AND - meaning and &&
OR - meaning or ||

The difference between these is the order in which they are executed. In most cases, you would want to use a boolean operator like &&, or ||.

Let’s take a look at a few examples:

// Logical operators have lower precedence:
$f = false or true;

// is executed like this:
($f = false) or true;


// Boolean operators have higher precedence:
$f = false || true;

// is executed like this:
$f = (false || true);

Logical Operators are used for Control-Flow

One case where you explicitly want to use logical operators is for control-flow such as this:

$x === 5
    or die('$x must be 5.');

// Instead of
if ($x !== 5) {
    die('$x must be 5.');
}

Since die introduces problems of its own, f.e. it makes our code hardly testable, and prevents any kind of more sophisticated error handling; you probably do not want to use this in real-world code. Unfortunately, logical operators cannot be combined with throw at this point:

// The following is currently a parse error.
$x === 5
    or throw new RuntimeException('$x must be 5.');

These limitations lead to logical operators rarely being of use in current PHP code.

Loading history...
422
            'Source image is not a valid file, check the filename and that a
423
            matching file exists on the filesystem.'
424
        , 404);
425
426
    substr_compare($imageDir, $pathToImage, 0, strlen($imageDir)) == 0
427
        or errorPage(
0 ignored issues
show
Comprehensibility Best Practice introduced by
Using logical operators such as or instead of || is generally not recommended.

PHP has two types of connecting operators (logical operators, and boolean operators):

  Logical Operators Boolean Operator
AND - meaning and &&
OR - meaning or ||

The difference between these is the order in which they are executed. In most cases, you would want to use a boolean operator like &&, or ||.

Let’s take a look at a few examples:

// Logical operators have lower precedence:
$f = false or true;

// is executed like this:
($f = false) or true;


// Boolean operators have higher precedence:
$f = false || true;

// is executed like this:
$f = (false || true);

Logical Operators are used for Control-Flow

One case where you explicitly want to use logical operators is for control-flow such as this:

$x === 5
    or die('$x must be 5.');

// Instead of
if ($x !== 5) {
    die('$x must be 5.');
}

Since die introduces problems of its own, f.e. it makes our code hardly testable, and prevents any kind of more sophisticated error handling; you probably do not want to use this in real-world code. Unfortunately, logical operators cannot be combined with throw at this point:

// The following is currently a parse error.
$x === 5
    or throw new RuntimeException('$x must be 5.');

These limitations lead to logical operators rarely being of use in current PHP code.

Loading history...
428
            'Security constraint: Source image is not below the directory "image_path"
429
            as specified in the config file img_config.php.'
430
        , 404);
431
}
432
433
verbose("src = $srcImage");
434
435
436
437
/**
438
 * Manage size constants from config file, use constants to replace values
439
 * for width and height.
440
 */
441
$sizeConstant = getConfig('size_constant', function () {
442
443
    // Set sizes to map constant to value, easier to use with width or height
444
    $sizes = array(
445
        'w1' => 613,
446
        'w2' => 630,
447
    );
448
449
    // Add grid column width, useful for use as predefined size for width (or height).
450
    $gridColumnWidth = 30;
451
    $gridGutterWidth = 10;
452
    $gridColumns     = 24;
453
454
    for ($i = 1; $i <= $gridColumns; $i++) {
455
        $sizes['c' . $i] = ($gridColumnWidth + $gridGutterWidth) * $i - $gridGutterWidth;
456
    }
457
458
    return $sizes;
459
});
460
461
$sizes = call_user_func($sizeConstant);
462
463
464
465
/**
466
 * width, w - set target width, affecting the resulting image width, height and resize options
467
 */
468
$newWidth     = get(array('width', 'w'));
469
$maxWidth     = getConfig('max_width', 2000);
470
471
// Check to replace predefined size
472
if (isset($sizes[$newWidth])) {
473
    $newWidth = $sizes[$newWidth];
474
}
475
476
// Support width as % of original width
477
if ($newWidth[strlen($newWidth)-1] == '%') {
478
    is_numeric(substr($newWidth, 0, -1))
479
        or errorPage('Width % not numeric.', 404);
0 ignored issues
show
Comprehensibility Best Practice introduced by
Using logical operators such as or instead of || is generally not recommended.

PHP has two types of connecting operators (logical operators, and boolean operators):

  Logical Operators Boolean Operator
AND - meaning and &&
OR - meaning or ||

The difference between these is the order in which they are executed. In most cases, you would want to use a boolean operator like &&, or ||.

Let’s take a look at a few examples:

// Logical operators have lower precedence:
$f = false or true;

// is executed like this:
($f = false) or true;


// Boolean operators have higher precedence:
$f = false || true;

// is executed like this:
$f = (false || true);

Logical Operators are used for Control-Flow

One case where you explicitly want to use logical operators is for control-flow such as this:

$x === 5
    or die('$x must be 5.');

// Instead of
if ($x !== 5) {
    die('$x must be 5.');
}

Since die introduces problems of its own, f.e. it makes our code hardly testable, and prevents any kind of more sophisticated error handling; you probably do not want to use this in real-world code. Unfortunately, logical operators cannot be combined with throw at this point:

// The following is currently a parse error.
$x === 5
    or throw new RuntimeException('$x must be 5.');

These limitations lead to logical operators rarely being of use in current PHP code.

Loading history...
480
} else {
481
    is_null($newWidth)
482
        or ($newWidth > 10 && $newWidth <= $maxWidth)
483
        or errorPage('Width out of range.', 404);
0 ignored issues
show
Comprehensibility Best Practice introduced by
Using logical operators such as or instead of || is generally not recommended.

PHP has two types of connecting operators (logical operators, and boolean operators):

  Logical Operators Boolean Operator
AND - meaning and &&
OR - meaning or ||

The difference between these is the order in which they are executed. In most cases, you would want to use a boolean operator like &&, or ||.

Let’s take a look at a few examples:

// Logical operators have lower precedence:
$f = false or true;

// is executed like this:
($f = false) or true;


// Boolean operators have higher precedence:
$f = false || true;

// is executed like this:
$f = (false || true);

Logical Operators are used for Control-Flow

One case where you explicitly want to use logical operators is for control-flow such as this:

$x === 5
    or die('$x must be 5.');

// Instead of
if ($x !== 5) {
    die('$x must be 5.');
}

Since die introduces problems of its own, f.e. it makes our code hardly testable, and prevents any kind of more sophisticated error handling; you probably do not want to use this in real-world code. Unfortunately, logical operators cannot be combined with throw at this point:

// The following is currently a parse error.
$x === 5
    or throw new RuntimeException('$x must be 5.');

These limitations lead to logical operators rarely being of use in current PHP code.

Loading history...
484
}
485
486
verbose("new width = $newWidth");
487
488
489
490
/**
491
 * height, h - set target height, affecting the resulting image width, height and resize options
492
 */
493
$newHeight = get(array('height', 'h'));
494
$maxHeight = getConfig('max_height', 2000);
495
496
// Check to replace predefined size
497
if (isset($sizes[$newHeight])) {
498
    $newHeight = $sizes[$newHeight];
499
}
500
501
// height
502
if ($newHeight[strlen($newHeight)-1] == '%') {
503
    is_numeric(substr($newHeight, 0, -1))
504
        or errorPage('Height % out of range.', 404);
0 ignored issues
show
Comprehensibility Best Practice introduced by
Using logical operators such as or instead of || is generally not recommended.

PHP has two types of connecting operators (logical operators, and boolean operators):

  Logical Operators Boolean Operator
AND - meaning and &&
OR - meaning or ||

The difference between these is the order in which they are executed. In most cases, you would want to use a boolean operator like &&, or ||.

Let’s take a look at a few examples:

// Logical operators have lower precedence:
$f = false or true;

// is executed like this:
($f = false) or true;


// Boolean operators have higher precedence:
$f = false || true;

// is executed like this:
$f = (false || true);

Logical Operators are used for Control-Flow

One case where you explicitly want to use logical operators is for control-flow such as this:

$x === 5
    or die('$x must be 5.');

// Instead of
if ($x !== 5) {
    die('$x must be 5.');
}

Since die introduces problems of its own, f.e. it makes our code hardly testable, and prevents any kind of more sophisticated error handling; you probably do not want to use this in real-world code. Unfortunately, logical operators cannot be combined with throw at this point:

// The following is currently a parse error.
$x === 5
    or throw new RuntimeException('$x must be 5.');

These limitations lead to logical operators rarely being of use in current PHP code.

Loading history...
505
} else {
506
    is_null($newHeight)
507
        or ($newHeight > 10 && $newHeight <= $maxHeight)
508
        or errorPage('Height out of range.', 404);
0 ignored issues
show
Comprehensibility Best Practice introduced by
Using logical operators such as or instead of || is generally not recommended.

PHP has two types of connecting operators (logical operators, and boolean operators):

  Logical Operators Boolean Operator
AND - meaning and &&
OR - meaning or ||

The difference between these is the order in which they are executed. In most cases, you would want to use a boolean operator like &&, or ||.

Let’s take a look at a few examples:

// Logical operators have lower precedence:
$f = false or true;

// is executed like this:
($f = false) or true;


// Boolean operators have higher precedence:
$f = false || true;

// is executed like this:
$f = (false || true);

Logical Operators are used for Control-Flow

One case where you explicitly want to use logical operators is for control-flow such as this:

$x === 5
    or die('$x must be 5.');

// Instead of
if ($x !== 5) {
    die('$x must be 5.');
}

Since die introduces problems of its own, f.e. it makes our code hardly testable, and prevents any kind of more sophisticated error handling; you probably do not want to use this in real-world code. Unfortunately, logical operators cannot be combined with throw at this point:

// The following is currently a parse error.
$x === 5
    or throw new RuntimeException('$x must be 5.');

These limitations lead to logical operators rarely being of use in current PHP code.

Loading history...
509
}
510
511
verbose("new height = $newHeight");
512
513
514
515
/**
516
 * aspect-ratio, ar - affecting the resulting image width, height and resize options
517
 */
518
$aspectRatio         = get(array('aspect-ratio', 'ar'));
519
$aspectRatioConstant = getConfig('aspect_ratio_constant', function () {
520
    return array(
521
        '3:1'    => 3/1,
522
        '3:2'    => 3/2,
523
        '4:3'    => 4/3,
524
        '8:5'    => 8/5,
525
        '16:10'  => 16/10,
526
        '16:9'   => 16/9,
527
        'golden' => 1.618,
528
    );
529
});
530
531
// Check to replace predefined aspect ratio
532
$aspectRatios = call_user_func($aspectRatioConstant);
533
$negateAspectRatio = ($aspectRatio[0] == '!') ? true : false;
534
$aspectRatio = $negateAspectRatio ? substr($aspectRatio, 1) : $aspectRatio;
535
536
if (isset($aspectRatios[$aspectRatio])) {
537
    $aspectRatio = $aspectRatios[$aspectRatio];
538
}
539
540
if ($negateAspectRatio) {
541
    $aspectRatio = 1 / $aspectRatio;
542
}
543
544
is_null($aspectRatio)
545
    or is_numeric($aspectRatio)
546
    or errorPage('Aspect ratio out of range', 404);
0 ignored issues
show
Comprehensibility Best Practice introduced by
Using logical operators such as or instead of || is generally not recommended.

PHP has two types of connecting operators (logical operators, and boolean operators):

  Logical Operators Boolean Operator
AND - meaning and &&
OR - meaning or ||

The difference between these is the order in which they are executed. In most cases, you would want to use a boolean operator like &&, or ||.

Let’s take a look at a few examples:

// Logical operators have lower precedence:
$f = false or true;

// is executed like this:
($f = false) or true;


// Boolean operators have higher precedence:
$f = false || true;

// is executed like this:
$f = (false || true);

Logical Operators are used for Control-Flow

One case where you explicitly want to use logical operators is for control-flow such as this:

$x === 5
    or die('$x must be 5.');

// Instead of
if ($x !== 5) {
    die('$x must be 5.');
}

Since die introduces problems of its own, f.e. it makes our code hardly testable, and prevents any kind of more sophisticated error handling; you probably do not want to use this in real-world code. Unfortunately, logical operators cannot be combined with throw at this point:

// The following is currently a parse error.
$x === 5
    or throw new RuntimeException('$x must be 5.');

These limitations lead to logical operators rarely being of use in current PHP code.

Loading history...
547
548
verbose("aspect ratio = $aspectRatio");
549
550
551
552
/**
553
 * crop-to-fit, cf - affecting the resulting image width, height and resize options
554
 */
555
$cropToFit = getDefined(array('crop-to-fit', 'cf'), true, false);
556
557
verbose("crop to fit = $cropToFit");
558
559
560
561
/**
562
 * Set default background color from config file.
563
 */
564
$backgroundColor = getConfig('background_color', null);
565
566
if ($backgroundColor) {
567
    $img->setDefaultBackgroundColor($backgroundColor);
568
    verbose("Using default background_color = $backgroundColor");
569
}
570
571
572
573
/**
574
 * bgColor - Default background color to use
575
 */
576
$bgColor = get(array('bgColor', 'bg-color', 'bgc'), null);
577
578
verbose("bgColor = $bgColor");
579
580
581
582
/**
583
 * Do or do not resample image when resizing.
584
 */
585
$resizeStrategy = getDefined(array('no-resample'), true, false);
586
587
if ($resizeStrategy) {
588
    $img->setCopyResizeStrategy($img::RESIZE);
589
    verbose("Setting = Resize instead of resample");
590
}
591
592
593
594
595
/**
596
 * fill-to-fit, ff - affecting the resulting image width, height and resize options
597
 */
598
$fillToFit = get(array('fill-to-fit', 'ff'), null);
599
600
verbose("fill-to-fit = $fillToFit");
601
602
if ($fillToFit !== null) {
603
604
    if (!empty($fillToFit)) {
605
        $bgColor   = $fillToFit;
606
        verbose("fillToFit changed bgColor to = $bgColor");
607
    }
608
609
    $fillToFit = true;
610
    verbose("fill-to-fit (fixed) = $fillToFit");
611
}
612
613
614
615
/**
616
 * no-ratio, nr, stretch - affecting the resulting image width, height and resize options
617
 */
618
$keepRatio = getDefined(array('no-ratio', 'nr', 'stretch'), false, true);
619
620
verbose("keep ratio = $keepRatio");
621
622
623
624
/**
625
 * crop, c - affecting the resulting image width, height and resize options
626
 */
627
$crop = get(array('crop', 'c'));
628
629
verbose("crop = $crop");
630
631
632
633
/**
634
 * area, a - affecting the resulting image width, height and resize options
635
 */
636
$area = get(array('area', 'a'));
637
638
verbose("area = $area");
639
640
641
642
/**
643
 * skip-original, so - skip the original image and always process a new image
644
 */
645
$useOriginal = getDefined(array('skip-original', 'so'), false, true);
646
647
verbose("use original = $useOriginal");
648
649
650
651
/**
652
 * no-cache, nc - skip the cached version and process and create a new version in cache.
653
 */
654
$useCache = getDefined(array('no-cache', 'nc'), false, true);
655
656
verbose("use cache = $useCache");
657
658
659
660
/**
661
 * quality, q - set level of quality for jpeg images
662
 */
663
$quality = get(array('quality', 'q'));
664
$qualityDefault = getConfig('jpg_quality', null);
665
666
is_null($quality)
667
    or ($quality > 0 and $quality <= 100)
668
    or errorPage('Quality out of range', 404);
0 ignored issues
show
Comprehensibility Best Practice introduced by
Using logical operators such as or instead of || is generally not recommended.

PHP has two types of connecting operators (logical operators, and boolean operators):

  Logical Operators Boolean Operator
AND - meaning and &&
OR - meaning or ||

The difference between these is the order in which they are executed. In most cases, you would want to use a boolean operator like &&, or ||.

Let’s take a look at a few examples:

// Logical operators have lower precedence:
$f = false or true;

// is executed like this:
($f = false) or true;


// Boolean operators have higher precedence:
$f = false || true;

// is executed like this:
$f = (false || true);

Logical Operators are used for Control-Flow

One case where you explicitly want to use logical operators is for control-flow such as this:

$x === 5
    or die('$x must be 5.');

// Instead of
if ($x !== 5) {
    die('$x must be 5.');
}

Since die introduces problems of its own, f.e. it makes our code hardly testable, and prevents any kind of more sophisticated error handling; you probably do not want to use this in real-world code. Unfortunately, logical operators cannot be combined with throw at this point:

// The following is currently a parse error.
$x === 5
    or throw new RuntimeException('$x must be 5.');

These limitations lead to logical operators rarely being of use in current PHP code.

Loading history...
669
670
if (is_null($quality) && !is_null($qualityDefault)) {
671
    $quality = $qualityDefault;
672
}
673
674
verbose("quality = $quality");
675
676
677
678
/**
679
 * compress, co - what strategy to use when compressing png images
680
 */
681
$compress = get(array('compress', 'co'));
682
$compressDefault = getConfig('png_compression', null);
683
684
is_null($compress)
685
    or ($compress > 0 and $compress <= 9)
686
    or errorPage('Compress out of range', 404);
0 ignored issues
show
Comprehensibility Best Practice introduced by
Using logical operators such as or instead of || is generally not recommended.

PHP has two types of connecting operators (logical operators, and boolean operators):

  Logical Operators Boolean Operator
AND - meaning and &&
OR - meaning or ||

The difference between these is the order in which they are executed. In most cases, you would want to use a boolean operator like &&, or ||.

Let’s take a look at a few examples:

// Logical operators have lower precedence:
$f = false or true;

// is executed like this:
($f = false) or true;


// Boolean operators have higher precedence:
$f = false || true;

// is executed like this:
$f = (false || true);

Logical Operators are used for Control-Flow

One case where you explicitly want to use logical operators is for control-flow such as this:

$x === 5
    or die('$x must be 5.');

// Instead of
if ($x !== 5) {
    die('$x must be 5.');
}

Since die introduces problems of its own, f.e. it makes our code hardly testable, and prevents any kind of more sophisticated error handling; you probably do not want to use this in real-world code. Unfortunately, logical operators cannot be combined with throw at this point:

// The following is currently a parse error.
$x === 5
    or throw new RuntimeException('$x must be 5.');

These limitations lead to logical operators rarely being of use in current PHP code.

Loading history...
687
688
if (is_null($compress) && !is_null($compressDefault)) {
689
    $compress = $compressDefault;
690
}
691
692
verbose("compress = $compress");
693
694
695
696
/**
697
 * save-as, sa - what type of image to save
698
 */
699
$saveAs = get(array('save-as', 'sa'));
700
701
verbose("save as = $saveAs");
702
703
704
705
/**
706
 * scale, s - Processing option, scale up or down the image prior actual resize
707
 */
708
$scale = get(array('scale', 's'));
709
710
is_null($scale)
711
    or ($scale >= 0 and $scale <= 400)
712
    or errorPage('Scale out of range', 404);
0 ignored issues
show
Comprehensibility Best Practice introduced by
Using logical operators such as or instead of || is generally not recommended.

PHP has two types of connecting operators (logical operators, and boolean operators):

  Logical Operators Boolean Operator
AND - meaning and &&
OR - meaning or ||

The difference between these is the order in which they are executed. In most cases, you would want to use a boolean operator like &&, or ||.

Let’s take a look at a few examples:

// Logical operators have lower precedence:
$f = false or true;

// is executed like this:
($f = false) or true;


// Boolean operators have higher precedence:
$f = false || true;

// is executed like this:
$f = (false || true);

Logical Operators are used for Control-Flow

One case where you explicitly want to use logical operators is for control-flow such as this:

$x === 5
    or die('$x must be 5.');

// Instead of
if ($x !== 5) {
    die('$x must be 5.');
}

Since die introduces problems of its own, f.e. it makes our code hardly testable, and prevents any kind of more sophisticated error handling; you probably do not want to use this in real-world code. Unfortunately, logical operators cannot be combined with throw at this point:

// The following is currently a parse error.
$x === 5
    or throw new RuntimeException('$x must be 5.');

These limitations lead to logical operators rarely being of use in current PHP code.

Loading history...
713
714
verbose("scale = $scale");
715
716
717
718
/**
719
 * palette, p - Processing option, create a palette version of the image
720
 */
721
$palette = getDefined(array('palette', 'p'), true, false);
722
723
verbose("palette = $palette");
724
725
726
727
/**
728
 * sharpen - Processing option, post filter for sharpen effect
729
 */
730
$sharpen = getDefined('sharpen', true, null);
731
732
verbose("sharpen = $sharpen");
733
734
735
736
/**
737
 * emboss - Processing option, post filter for emboss effect
738
 */
739
$emboss = getDefined('emboss', true, null);
740
741
verbose("emboss = $emboss");
742
743
744
745
/**
746
 * blur - Processing option, post filter for blur effect
747
 */
748
$blur = getDefined('blur', true, null);
749
750
verbose("blur = $blur");
751
752
753
754
/**
755
 * rotateBefore - Rotate the image with an angle, before processing
756
 */
757
$rotateBefore = get(array('rotateBefore', 'rotate-before', 'rb'));
758
759
is_null($rotateBefore)
760
    or ($rotateBefore >= -360 and $rotateBefore <= 360)
761
    or errorPage('RotateBefore out of range', 404);
0 ignored issues
show
Comprehensibility Best Practice introduced by
Using logical operators such as or instead of || is generally not recommended.

PHP has two types of connecting operators (logical operators, and boolean operators):

  Logical Operators Boolean Operator
AND - meaning and &&
OR - meaning or ||

The difference between these is the order in which they are executed. In most cases, you would want to use a boolean operator like &&, or ||.

Let’s take a look at a few examples:

// Logical operators have lower precedence:
$f = false or true;

// is executed like this:
($f = false) or true;


// Boolean operators have higher precedence:
$f = false || true;

// is executed like this:
$f = (false || true);

Logical Operators are used for Control-Flow

One case where you explicitly want to use logical operators is for control-flow such as this:

$x === 5
    or die('$x must be 5.');

// Instead of
if ($x !== 5) {
    die('$x must be 5.');
}

Since die introduces problems of its own, f.e. it makes our code hardly testable, and prevents any kind of more sophisticated error handling; you probably do not want to use this in real-world code. Unfortunately, logical operators cannot be combined with throw at this point:

// The following is currently a parse error.
$x === 5
    or throw new RuntimeException('$x must be 5.');

These limitations lead to logical operators rarely being of use in current PHP code.

Loading history...
762
763
verbose("rotateBefore = $rotateBefore");
764
765
766
767
/**
768
 * rotateAfter - Rotate the image with an angle, before processing
769
 */
770
$rotateAfter = get(array('rotateAfter', 'rotate-after', 'ra', 'rotate', 'r'));
771
772
is_null($rotateAfter)
773
    or ($rotateAfter >= -360 and $rotateAfter <= 360)
774
    or errorPage('RotateBefore out of range', 404);
0 ignored issues
show
Comprehensibility Best Practice introduced by
Using logical operators such as or instead of || is generally not recommended.

PHP has two types of connecting operators (logical operators, and boolean operators):

  Logical Operators Boolean Operator
AND - meaning and &&
OR - meaning or ||

The difference between these is the order in which they are executed. In most cases, you would want to use a boolean operator like &&, or ||.

Let’s take a look at a few examples:

// Logical operators have lower precedence:
$f = false or true;

// is executed like this:
($f = false) or true;


// Boolean operators have higher precedence:
$f = false || true;

// is executed like this:
$f = (false || true);

Logical Operators are used for Control-Flow

One case where you explicitly want to use logical operators is for control-flow such as this:

$x === 5
    or die('$x must be 5.');

// Instead of
if ($x !== 5) {
    die('$x must be 5.');
}

Since die introduces problems of its own, f.e. it makes our code hardly testable, and prevents any kind of more sophisticated error handling; you probably do not want to use this in real-world code. Unfortunately, logical operators cannot be combined with throw at this point:

// The following is currently a parse error.
$x === 5
    or throw new RuntimeException('$x must be 5.');

These limitations lead to logical operators rarely being of use in current PHP code.

Loading history...
775
776
verbose("rotateAfter = $rotateAfter");
777
778
779
780
/**
781
 * autoRotate - Auto rotate based on EXIF information
782
 */
783
$autoRotate = getDefined(array('autoRotate', 'auto-rotate', 'aro'), true, false);
784
785
verbose("autoRotate = $autoRotate");
786
787
788
789
/**
790
 * filter, f, f0-f9 - Processing option, post filter for various effects using imagefilter()
791
 */
792
$filters = array();
793
$filter = get(array('filter', 'f'));
794
if ($filter) {
795
    $filters[] = $filter;
796
}
797
798
for ($i = 0; $i < 10; $i++) {
799
    $filter = get(array("filter{$i}", "f{$i}"));
800
    if ($filter) {
801
        $filters[] = $filter;
802
    }
803
}
804
805
verbose("filters = " . print_r($filters, 1));
806
807
808
809
/**
810
* json -  output the image as a JSON object with details on the image.
811
* ascii - output the image as ASCII art.
812
 */
813
$outputFormat = getDefined('json', 'json', null);
814
$outputFormat = getDefined('ascii', 'ascii', $outputFormat);
815
816
verbose("outputformat = $outputFormat");
817
818
if ($outputFormat == 'ascii') {
819
    $defaultOptions = getConfig(
820
        'ascii-options',
821
        array(
822
            "characterSet" => 'two',
823
            "scale" => 14,
824
            "luminanceStrategy" => 3,
825
            "customCharacterSet" => null,
826
        )
827
    );
828
    $options = get('ascii');
829
    $options = explode(',', $options);
830
831
    if (isset($options[0]) && !empty($options[0])) {
832
        $defaultOptions['characterSet'] = $options[0];
833
    }
834
835
    if (isset($options[1]) && !empty($options[1])) {
836
        $defaultOptions['scale'] = $options[1];
837
    }
838
839
    if (isset($options[2]) && !empty($options[2])) {
840
        $defaultOptions['luminanceStrategy'] = $options[2];
841
    }
842
843
    if (count($options) > 3) {
844
        // Last option is custom character string
845
        unset($options[0]);
846
        unset($options[1]);
847
        unset($options[2]);
848
        $characterString = implode($options);
849
        $defaultOptions['customCharacterSet'] = $characterString;
850
    }
851
852
    $img->setAsciiOptions($defaultOptions);
853
}
854
855
856
857
858
/**
859
 * dpr - change to get larger image to easier support larger dpr, such as retina.
860
 */
861
$dpr = get(array('ppi', 'dpr', 'device-pixel-ratio'), 1);
862
863
verbose("dpr = $dpr");
864
865
866
867
/**
868
 * convolve - image convolution as in http://php.net/manual/en/function.imageconvolution.php
869
 */
870
$convolve = get('convolve', null);
871
$convolutionConstant = getConfig('convolution_constant', array());
872
873
// Check if the convolve is matching an existing constant
874
if ($convolve && isset($convolutionConstant)) {
875
    $img->addConvolveExpressions($convolutionConstant);
876
    verbose("convolve constant = " . print_r($convolutionConstant, 1));
877
}
878
879
verbose("convolve = " . print_r($convolve, 1));
880
881
882
883
/**
884
 * no-upscale, nu - Do not upscale smaller image to larger dimension.
885
 */
886
$upscale = getDefined(array('no-upscale', 'nu'), false, true);
887
888
verbose("upscale = $upscale");
889
890
891
892
/**
893
 * Get details for post processing
894
 */
895
$postProcessing = getConfig('postprocessing', array(
896
    'png_filter'        => false,
897
    'png_filter_cmd'    => '/usr/local/bin/optipng -q',
898
899
    'png_deflate'       => false,
900
    'png_deflate_cmd'   => '/usr/local/bin/pngout -q',
901
902
    'jpeg_optimize'     => false,
903
    'jpeg_optimize_cmd' => '/usr/local/bin/jpegtran -copy none -optimize',
904
));
905
906
907
908
/**
909
 * alias - Save resulting image to another alias name.
910
 * Password always apply, must be defined.
911
 */
912
$alias          = get('alias', null);
913
$aliasPath      = getConfig('alias_path', null);
914
$validAliasname = getConfig('valid_aliasname', '#^[a-z0-9A-Z-_]+$#');
915
$aliasTarget    = null;
916
917
if ($alias && $aliasPath && $passwordMatch) {
918
919
    $aliasTarget = $aliasPath . $alias;
920
    $useCache    = false;
921
922
    is_writable($aliasPath)
923
        or errorPage("Directory for alias is not writable.", 403);
0 ignored issues
show
Comprehensibility Best Practice introduced by
Using logical operators such as or instead of || is generally not recommended.

PHP has two types of connecting operators (logical operators, and boolean operators):

  Logical Operators Boolean Operator
AND - meaning and &&
OR - meaning or ||

The difference between these is the order in which they are executed. In most cases, you would want to use a boolean operator like &&, or ||.

Let’s take a look at a few examples:

// Logical operators have lower precedence:
$f = false or true;

// is executed like this:
($f = false) or true;


// Boolean operators have higher precedence:
$f = false || true;

// is executed like this:
$f = (false || true);

Logical Operators are used for Control-Flow

One case where you explicitly want to use logical operators is for control-flow such as this:

$x === 5
    or die('$x must be 5.');

// Instead of
if ($x !== 5) {
    die('$x must be 5.');
}

Since die introduces problems of its own, f.e. it makes our code hardly testable, and prevents any kind of more sophisticated error handling; you probably do not want to use this in real-world code. Unfortunately, logical operators cannot be combined with throw at this point:

// The following is currently a parse error.
$x === 5
    or throw new RuntimeException('$x must be 5.');

These limitations lead to logical operators rarely being of use in current PHP code.

Loading history...
924
925
    preg_match($validAliasname, $alias)
926
        or errorPage('Filename for alias contains invalid characters. Do not add extension.', 404);
0 ignored issues
show
Comprehensibility Best Practice introduced by
Using logical operators such as or instead of || is generally not recommended.

PHP has two types of connecting operators (logical operators, and boolean operators):

  Logical Operators Boolean Operator
AND - meaning and &&
OR - meaning or ||

The difference between these is the order in which they are executed. In most cases, you would want to use a boolean operator like &&, or ||.

Let’s take a look at a few examples:

// Logical operators have lower precedence:
$f = false or true;

// is executed like this:
($f = false) or true;


// Boolean operators have higher precedence:
$f = false || true;

// is executed like this:
$f = (false || true);

Logical Operators are used for Control-Flow

One case where you explicitly want to use logical operators is for control-flow such as this:

$x === 5
    or die('$x must be 5.');

// Instead of
if ($x !== 5) {
    die('$x must be 5.');
}

Since die introduces problems of its own, f.e. it makes our code hardly testable, and prevents any kind of more sophisticated error handling; you probably do not want to use this in real-world code. Unfortunately, logical operators cannot be combined with throw at this point:

// The following is currently a parse error.
$x === 5
    or throw new RuntimeException('$x must be 5.');

These limitations lead to logical operators rarely being of use in current PHP code.

Loading history...
927
928
} elseif ($alias) {
929
    errorPage('Alias is not enabled in the config file or password not matching.', 403);
930
}
931
932
verbose("alias = $alias");
933
934
935
936
/**
937
 * Get the cachepath from config.
938
 */
939
$cachePath = getConfig('cache_path', __DIR__ . '/../cache/');
940
941
942
943
/**
944
 * Get the cachepath from config.
945
 */
946
$cacheControl = getConfig('cache_control', null);
947
948
if ($cacheControl) {
949
    verbose("cacheControl = $cacheControl");
950
    $img->addHTTPHeader("Cache-Control", $cacheControl);
951
}
952
953
954
955
/**
956
 * Prepare a dummy image and use it as source image.
957
 */
958
$dummyDir = getConfig('dummy_dir', $cachePath. "/" . $dummyFilename);
959
960
if ($dummyImage === true) {
961
    is_writable($dummyDir)
962
        or verbose("dummy dir not writable = $dummyDir");
963
964
    $img->setSaveFolder($dummyDir)
965
        ->setSource($dummyFilename, $dummyDir)
966
        ->setOptions(
967
            array(
968
                'newWidth'  => $newWidth,
969
                'newHeight' => $newHeight,
970
                'bgColor'   => $bgColor,
971
            )
972
        )
973
        ->setJpegQuality($quality)
974
        ->setPngCompression($compress)
975
        ->createDummyImage()
976
        ->generateFilename(null, false)
977
        ->save(null, null, false);
978
979
    $srcImage = $img->getTarget();
980
    $imagePath = null;
981
982
    verbose("src (updated) = $srcImage");
983
}
984
985
986
987
/**
988
 * Display status
989
 */
990
if ($status) {
991
    $text  = "img.php version = $version\n";
992
    $text .= "PHP version = " . PHP_VERSION . "\n";
993
    $text .= "Running on: " . $_SERVER['SERVER_SOFTWARE'] . "\n";
994
    $text .= "Allow remote images = $allowRemote\n";
995
    $text .= "Cache writable = " . is_writable($cachePath) . "\n";
996
    $text .= "Cache dummy writable = " . is_writable($dummyDir) . "\n";
997
    $text .= "Alias path writable = " . is_writable($aliasPath) . "\n";
998
999
    $no = extension_loaded('exif') ? null : 'NOT';
1000
    $text .= "Extension exif is $no loaded.<br>";
1001
1002
    $no = extension_loaded('curl') ? null : 'NOT';
1003
    $text .= "Extension curl is $no loaded.<br>";
1004
1005
    $no = extension_loaded('gd') ? null : 'NOT';
1006
    $text .= "Extension gd is $no loaded.<br>";
1007
1008
    if (!$no) {
1009
        $text .= print_r(gd_info(), 1);
1010
    }
1011
1012
    echo <<<EOD
1013
<!doctype html>
1014
<html lang=en>
1015
<meta charset=utf-8>
1016
<title>CImage status</title>
1017
<pre>$text</pre>
1018
EOD;
1019
    exit;
1020
}
1021
1022
1023
1024
/**
1025
 * Log verbose details to file
1026
 */
1027
if ($verboseFile) {
1028
    $img->setVerboseToFile("$cachePath/log.txt");
1029
}
1030
1031
1032
1033
/**
1034
 * Hook after img.php configuration and before processing with CImage
1035
 */
1036
$hookBeforeCImage = getConfig('hook_before_CImage', null);
1037
1038
if (is_callable($hookBeforeCImage)) {
1039
    verbose("hookBeforeCImage activated");
1040
1041
    $allConfig = $hookBeforeCImage($img, array(
1042
            // Options for calculate dimensions
1043
            'newWidth'  => $newWidth,
1044
            'newHeight' => $newHeight,
1045
            'aspectRatio' => $aspectRatio,
1046
            'keepRatio' => $keepRatio,
1047
            'cropToFit' => $cropToFit,
1048
            'fillToFit' => $fillToFit,
1049
            'crop'      => $crop,
1050
            'area'      => $area,
1051
            'upscale'   => $upscale,
1052
1053
            // Pre-processing, before resizing is done
1054
            'scale'        => $scale,
1055
            'rotateBefore' => $rotateBefore,
1056
            'autoRotate'   => $autoRotate,
1057
1058
            // General processing options
1059
            'bgColor'    => $bgColor,
1060
1061
            // Post-processing, after resizing is done
1062
            'palette'   => $palette,
1063
            'filters'   => $filters,
1064
            'sharpen'   => $sharpen,
1065
            'emboss'    => $emboss,
1066
            'blur'      => $blur,
1067
            'convolve'  => $convolve,
1068
            'rotateAfter' => $rotateAfter,
1069
1070
            // Output format
1071
            'outputFormat' => $outputFormat,
1072
            'dpr'          => $dpr,
1073
1074
            // Other
1075
            'postProcessing' => $postProcessing,
1076
    ));
1077
    verbose(print_r($allConfig, 1));
1078
    extract($allConfig);
1079
}
1080
1081
1082
1083
/**
1084
 * Display image if verbose mode
1085
 */
1086
if ($verbose) {
1087
    $query = array();
1088
    parse_str($_SERVER['QUERY_STRING'], $query);
1089
    unset($query['verbose']);
1090
    unset($query['v']);
1091
    unset($query['nocache']);
1092
    unset($query['nc']);
1093
    unset($query['json']);
1094
    $url1 = '?' . htmlentities(urldecode(http_build_query($query)));
1095
    $url2 = '?' . urldecode(http_build_query($query));
1096
    echo <<<EOD
1097
<!doctype html>
1098
<html lang=en>
1099
<meta charset=utf-8>
1100
<title>CImage verbose output</title>
1101
<style>body{background-color: #ddd}</style>
1102
<a href=$url1><code>$url1</code></a><br>
1103
<img src='{$url1}' />
1104
<pre id="json"></pre>
1105
<script src="https://code.jquery.com/jquery-2.1.1.min.js"></script>
1106
<script type="text/javascript">
1107
window.getDetails = function (url, id) {
1108
  $.getJSON(url, function(data) {
1109
    element = document.getElementById(id);
1110
    element.innerHTML = "filename: " + data.filename + "\\nmime type: " + data.mimeType + "\\ncolors: " + data.colors + "\\nsize: " + data.size + "\\nwidth: " + data.width + "\\nheigh: " + data.height + "\\naspect-ratio: " + data.aspectRatio + ( data.pngType ? "\\npng-type: " + data.pngType : '');
1111
  });
1112
}
1113
</script>
1114
<script type="text/javascript">window.getDetails("{$url2}&json", "json")</script>
1115
EOD;
1116
}
1117
1118
1119
1120
/**
1121
 * Load, process and output the image
1122
 */
1123
$img->log("Incoming arguments: " . print_r(verbose(), 1))
1124
    ->setSaveFolder($cachePath)
1125
    ->useCache($useCache)
1126
    ->setSource($srcImage, $imagePath)
1127
    ->setOptions(
1128
        array(
1129
            // Options for calculate dimensions
1130
            'newWidth'  => $newWidth,
1131
            'newHeight' => $newHeight,
1132
            'aspectRatio' => $aspectRatio,
1133
            'keepRatio' => $keepRatio,
1134
            'cropToFit' => $cropToFit,
1135
            'fillToFit' => $fillToFit,
1136
            'crop'      => $crop,
1137
            'area'      => $area,
1138
            'upscale'   => $upscale,
1139
1140
            // Pre-processing, before resizing is done
1141
            'scale'        => $scale,
1142
            'rotateBefore' => $rotateBefore,
1143
            'autoRotate'   => $autoRotate,
1144
1145
            // General processing options
1146
            'bgColor'    => $bgColor,
1147
1148
            // Post-processing, after resizing is done
1149
            'palette'   => $palette,
1150
            'filters'   => $filters,
1151
            'sharpen'   => $sharpen,
1152
            'emboss'    => $emboss,
1153
            'blur'      => $blur,
1154
            'convolve'  => $convolve,
1155
            'rotateAfter' => $rotateAfter,
1156
1157
            // Output format
1158
            'outputFormat' => $outputFormat,
1159
            'dpr'          => $dpr,
1160
        )
1161
    )
1162
    ->loadImageDetails()
1163
    ->initDimensions()
1164
    ->calculateNewWidthAndHeight()
1165
    ->setSaveAsExtension($saveAs)
1166
    ->setJpegQuality($quality)
1167
    ->setPngCompression($compress)
1168
    ->useOriginalIfPossible($useOriginal)
1169
    ->generateFilename($cachePath)
1170
    ->useCacheIfPossible($useCache)
1171
    ->load()
1172
    ->preResize()
1173
    ->resize()
1174
    ->postResize()
1175
    ->setPostProcessingOptions($postProcessing)
1176
    ->save()
1177
    ->linkToCacheFile($aliasTarget)
1178
    ->output();
1179