Issues (1210)

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.

thumbs/phpThumb.php (4 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
2
//////////////////////////////////////////////////////////////
3
//   phpThumb() by James Heinrich <[email protected]>   //
4
//        available at http://phpthumb.sourceforge.net      //
5
//         and/or https://github.com/JamesHeinrich/phpThumb //
6
//////////////////////////////////////////////////////////////
7
///                                                         //
8
// See: phpthumb.changelog.txt for recent changes           //
9
// See: phpthumb.readme.txt for usage instructions          //
10
//                                                         ///
11
//////////////////////////////////////////////////////////////
12
13
error_reporting(E_ALL);
14
ini_set('display_errors', '1');
15
ini_set('magic_quotes_runtime', '0');
16
if (ini_get('magic_quotes_runtime')) {
17
    die('"magic_quotes_runtime" is set in php.ini, cannot run phpThumb with this enabled');
18
}
19
$starttime = array_sum(explode(' ', microtime())); // could be called as microtime(true) for PHP 5.0.0+
20
21
// this script relies on the superglobal arrays, fake it here for old PHP versions
22
if (PHP_VERSION < '4.1.0') {
23
    $_SERVER = $HTTP_SERVER_VARS;
24
    $_GET    = $HTTP_GET_VARS;
25
}
26
27
/**
28
 * @return bool
29
 */
30
function SendSaveAsFileHeaderIfNeeded()
31
{
32
    if (headers_sent()) {
33
        return false;
34
    }
35
    global $phpThumb;
36
    $downloadfilename = phpthumb_functions::SanitizeFilename(!empty($_GET['sia']) ? $_GET['sia'] : (!empty($_GET['down']) ? $_GET['down'] : 'phpThumb_generated_thumbnail.'
37
                                                                                                                                            . (!empty($_GET['f']) ? $_GET['f'] : 'jpg')));
38
    if (!empty($downloadfilename)) {
39
        $phpThumb->DebugMessage('SendSaveAsFileHeaderIfNeeded() sending header: Content-Disposition: ' . (!empty($_GET['down']) ? 'attachment' : 'inline') . '; filename="' . $downloadfilename . '"',
40
                                __FILE__, __LINE__);
41
        header('Content-Disposition: ' . (!empty($_GET['down']) ? 'attachment' : 'inline') . '; filename="' . $downloadfilename . '"');
42
    }
43
44
    return true;
45
}
46
47
/**
48
 * @return bool
49
 */
50
function RedirectToCachedFile()
51
{
52
    global $phpThumb;
53
54
    $nice_cachefile = str_replace(DIRECTORY_SEPARATOR, '/', $phpThumb->cache_filename);
55
    $nice_docroot   = str_replace(DIRECTORY_SEPARATOR, '/', rtrim($phpThumb->config_document_root, '/\\'));
56
57
    $parsed_url = phpthumb_functions::ParseURLbetter(@$_SERVER['HTTP_REFERER']);
58
59
    $nModified = filemtime($phpThumb->cache_filename);
60
61
    if ($phpThumb->config_nooffsitelink_enabled && !empty($_SERVER['HTTP_REFERER'])
62
        && !in_array(@$parsed_url['host'], $phpThumb->config_nooffsitelink_valid_domains)
63
    ) {
64
        $phpThumb->DebugMessage('Would have used cached (image/'
65
                                . $phpThumb->thumbnailFormat
66
                                . ') file "'
67
                                . $phpThumb->cache_filename
68
                                . '" (Last-Modified: '
69
                                . gmdate('D, d M Y H:i:s', $nModified)
70
                                . ' GMT), but skipping because $_SERVER[HTTP_REFERER] ('
71
                                . @$_SERVER['HTTP_REFERER']
72
                                . ') is not in $phpThumb->config_nooffsitelink_valid_domains ('
73
                                . implode(';', $phpThumb->config_nooffsitelink_valid_domains)
74
                                . ')', __FILE__, __LINE__);
75
    } elseif ($phpThumb->phpThumbDebug) {
76
        $phpThumb->DebugTimingMessage('skipped using cached image', __FILE__, __LINE__);
77
        $phpThumb->DebugMessage('Would have used cached file, but skipping due to phpThumbDebug', __FILE__, __LINE__);
78
        $phpThumb->DebugMessage('* Would have sent headers (1): Last-Modified: ' . gmdate('D, d M Y H:i:s', $nModified) . ' GMT', __FILE__, __LINE__);
79
        if ($getimagesize = @getimagesize($phpThumb->cache_filename)) {
80
            $phpThumb->DebugMessage('* Would have sent headers (2): Content-Type: ' . phpthumb_functions::ImageTypeToMIMEtype($getimagesize[2]), __FILE__, __LINE__);
81
        }
82
        if (preg_match('#^' . preg_quote($nice_docroot) . '(.*)$#', $nice_cachefile, $matches)) {
83
            $phpThumb->DebugMessage('* Would have sent headers (3): Location: ' . dirname($matches[1]) . '/' . urlencode(basename($matches[1])), __FILE__, __LINE__);
84
        } else {
85
            $phpThumb->DebugMessage('* Would have sent data: readfile(' . $phpThumb->cache_filename . ')', __FILE__, __LINE__);
86
        }
87
    } else {
88 View Code Duplication
        if (headers_sent()) {
89
            $phpThumb->ErrorImage('Headers already sent (' . basename(__FILE__) . ' line ' . __LINE__ . ')');
90
            exit;
91
        }
92
        SendSaveAsFileHeaderIfNeeded();
93
94
        header('Cache-Control: private');
95
        header('Pragma: private');
96
        header('Expires: ' . date(DATE_RFC822, strtotime(' 1 day')));
97
        if (!empty($_SERVER['HTTP_IF_MODIFIED_SINCE']) && ($nModified == strtotime($_SERVER['HTTP_IF_MODIFIED_SINCE']))
98
            && !empty($_SERVER['SERVER_PROTOCOL'])
99
        ) {
100
            header('Last-Modified: ' . gmdate('D, d M Y H:i:s', $nModified) . ' GMT');
101
            header($_SERVER['SERVER_PROTOCOL'] . ' 304 Not Modified');
102
            exit;
103
        }
104
        header('Last-Modified: ' . gmdate('D, d M Y H:i:s', $nModified) . ' GMT');
105
        if ($getimagesize = @getimagesize($phpThumb->cache_filename)) {
106
            header('Content-Type: ' . phpthumb_functions::ImageTypeToMIMEtype($getimagesize[2]));
107
        } elseif (preg_match('#\\.ico$#i', $phpThumb->cache_filename)) {
108
            header('Content-Type: image/x-icon');
109
        }
110
        header('Content-Length: ' . filesize($phpThumb->cache_filename));
111
        if (empty($phpThumb->config_cache_force_passthru)
112
            && preg_match('#^' . preg_quote($nice_docroot) . '(.*)$#', $nice_cachefile, $matches)
113
        ) {
114
            header('Location: ' . dirname($matches[1]) . '/' . urlencode(basename($matches[1])));
115
        } else {
116
            @readfile($phpThumb->cache_filename);
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition here. This can introduce security issues, and is generally not recommended.

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...
117
        }
118
        exit;
119
    }
120
121
    return true;
122
}
123
124
// instantiate a new phpThumb() object
125
ob_start();
126 View Code Duplication
if (!require_once __DIR__ . '/phpthumb.class.php') {
127
    ob_end_flush();
128
    die('failed to include_once("' . realpath(__DIR__ . '/phpthumb.class.php') . '")');
129
}
130
ob_end_clean();
131
$phpThumb = new phpThumb();
132
$phpThumb->DebugTimingMessage('phpThumb.php start', __FILE__, __LINE__, $starttime);
133
$phpThumb->SetParameter('config_error_die_on_error', true);
134
135
if (!phpthumb_functions::FunctionIsDisabled('set_time_limit')) {
136
    set_time_limit(60);  // shouldn't take nearly this long in most cases, but with many filters and/or a slow server...
137
}
138
139
// phpThumbDebug[0] used to be here, but may reveal too much
140
// info when high_security_mode should be enabled (not set yet)
141
142
if (file_exists(__DIR__ . '/phpThumb.config.php')) {
143
    ob_start();
144 View Code Duplication
    if (require_once __DIR__ . '/phpThumb.config.php') {
145
        // great
146
    } else {
147
        ob_end_flush();
148
        $phpThumb->config_disable_debug = false; // otherwise error message won't print
149
        $phpThumb->ErrorImage('failed to include_once(' . __DIR__ . '/phpThumb.config.php) - realpath="' . realpath(__DIR__ . '/phpThumb.config.php') . '"');
150
    }
151
    ob_end_clean();
152
} elseif (file_exists(__DIR__ . '/phpThumb.config.php.default')) {
153
    $phpThumb->config_disable_debug = false; // otherwise error message won't print
154
    $phpThumb->ErrorImage('Please rename "phpThumb.config.php.default" to "phpThumb.config.php"');
155 View Code Duplication
} else {
156
    $phpThumb->config_disable_debug = false; // otherwise error message won't print
157
    $phpThumb->ErrorImage('failed to include_once(' . __DIR__ . '/phpThumb.config.php) - realpath="' . realpath(__DIR__ . '/phpThumb.config.php') . '"');
158
}
159
160
if (!empty($PHPTHUMB_CONFIG)) {
161
    foreach ($PHPTHUMB_CONFIG as $key => $value) {
162
        $keyname = 'config_' . $key;
163
        $phpThumb->setParameter($keyname, $value);
164
        if (!preg_match('#(password|mysql)#i', $key)) {
165
            $phpThumb->DebugMessage('setParameter(' . $keyname . ', ' . $phpThumb->phpThumbDebugVarDump($value) . ')', __FILE__, __LINE__);
166
        }
167
    }
168
    if (!$phpThumb->config_disable_debug) {
169
        // if debug mode is enabled, force phpThumbDebug output, do not allow normal thumbnails to be generated
170
        $_GET['phpThumbDebug'] = (!empty($_GET['phpThumbDebug']) ? max(1, (int)$_GET['phpThumbDebug']) : 9);
171
        $phpThumb->setParameter('phpThumbDebug', $_GET['phpThumbDebug']);
172
    }
173
} else {
174
    $phpThumb->DebugMessage('$PHPTHUMB_CONFIG is empty', __FILE__, __LINE__);
175
}
176
177
if (empty($phpThumb->config_disable_pathinfo_parsing) && (empty($_GET) || isset($_GET['phpThumbDebug']))
178
    && !empty($_SERVER['PATH_INFO'])
179
) {
180
    $_SERVER['PHP_SELF'] = str_replace($_SERVER['PATH_INFO'], '', @$_SERVER['PHP_SELF']);
181
182
    $args = explode(';', substr($_SERVER['PATH_INFO'], 1));
183
    $phpThumb->DebugMessage('PATH_INFO.$args set to (' . implode(')(', $args) . ')', __FILE__, __LINE__);
184
    if (!empty($args)) {
185
        $_GET['src'] = @$args[count($args) - 1];
186
        $phpThumb->DebugMessage('PATH_INFO."src" = "' . $_GET['src'] . '"', __FILE__, __LINE__);
187
        if (preg_match('#^new\=([a-z0-9]+)#i', $_GET['src'], $matches)) {
188
            unset($_GET['src']);
189
            $_GET['new'] = $matches[1];
190
        }
191
    }
192
    if (preg_match('#^([0-9]*)x?([0-9]*)$#i', @$args[count($args) - 2], $matches)) {
193
        $_GET['w'] = $matches[1];
194
        $_GET['h'] = $matches[2];
195
        $phpThumb->DebugMessage('PATH_INFO."w"x"h" set to "' . $_GET['w'] . '"x"' . $_GET['h'] . '"', __FILE__, __LINE__);
196
    }
197
    for ($i = 0, $iMax = count($args) - 2; $i < $iMax; $i++) {
198
        @list($key, $value) = explode('=', @$args[$i]);
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition here. This can introduce security issues, and is generally not recommended.

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...
199
        if (substr($key, -2) == '[]') {
200
            $array_key_name          = substr($key, 0, -2);
201
            $_GET[$array_key_name][] = $value;
202
            $phpThumb->DebugMessage('PATH_INFO."' . $array_key_name . '[]" = "' . $value . '"', __FILE__, __LINE__);
203
        } else {
204
            $_GET[$key] = $value;
205
            $phpThumb->DebugMessage('PATH_INFO."' . $key . '" = "' . $value . '"', __FILE__, __LINE__);
206
        }
207
    }
208
}
209
210
if (!empty($phpThumb->config_high_security_enabled)) {
211
    if (empty($_GET['hash'])) {
212
        $phpThumb->config_disable_debug = false; // otherwise error message won't print
213
        $phpThumb->ErrorImage('ERROR: missing hash');
214
    } elseif (phpthumb_functions::PasswordStrength($phpThumb->config_high_security_password) < 20) {
215
        $phpThumb->config_disable_debug = false; // otherwise error message won't print
216
        $phpThumb->ErrorImage('ERROR: $PHPTHUMB_CONFIG[high_security_password] is not complex enough');
217
    } elseif ($_GET['hash'] != md5(str_replace($phpThumb->config_high_security_url_separator . 'hash=' . $_GET['hash'], '', $_SERVER['QUERY_STRING']) . $phpThumb->config_high_security_password)) {
218
        header('HTTP/1.0 403 Forbidden');
219
        sleep(10); // deliberate delay to discourage password-guessing
220
        $phpThumb->ErrorImage('ERROR: invalid hash');
221
    }
222
}
223
224
////////////////////////////////////////////////////////////////
225
// Debug output, to try and help me diagnose problems
226
$phpThumb->DebugTimingMessage('phpThumbDebug[0]', __FILE__, __LINE__);
227
if (isset($_GET['phpThumbDebug']) && ($_GET['phpThumbDebug'] == '0')) {
228
    $phpThumb->phpThumbDebug();
229
}
230
////////////////////////////////////////////////////////////////
231
232
// returned the fixed string if the evil "magic_quotes_gpc" setting is on
233
if (get_magic_quotes_gpc()) {
234
    // deprecated: 'err', 'file', 'goto',
235
    $RequestVarsToStripSlashes = array('src', 'wmf', 'down');
236
    foreach ($RequestVarsToStripSlashes as $key) {
237
        if (isset($_GET[$key])) {
238
            if (is_string($_GET[$key])) {
239
                $_GET[$key] = stripslashes($_GET[$key]);
240
            } else {
241
                unset($_GET[$key]);
242
            }
243
        }
244
    }
245
}
246
247
if (empty($_SERVER['PATH_INFO']) && empty($_SERVER['QUERY_STRING'])) {
248
    $phpThumb->config_disable_debug = false; // otherwise error message won't print
249
    $phpThumb->ErrorImage('ERROR: no parameters specified');
250
}
251
252
if (!empty($_GET['src']) && isset($_GET['md5s']) && empty($_GET['md5s'])) {
253
    if (preg_match('#^([a-z0-9]+)://#i', $_GET['src'], $protocol_matches)) {
254
        if (preg_match('#^(f|ht)tps?://#i', $_GET['src'])) {
255
            if ($rawImageData = phpthumb_functions::SafeURLread($_GET['src'], $error, $phpThumb->config_http_fopen_timeout, $phpThumb->config_http_follow_redirect)) {
256
                $md5s = md5($rawImageData);
257
            }
258
        } else {
259
            $phpThumb->ErrorImage('only FTP and HTTP/HTTPS protocols are allowed, "' . $protocol_matches[1] . '" is not');
260
        }
261
    } else {
262
        $SourceFilename = $phpThumb->ResolveFilenameToAbsolute($_GET['src']);
263
        if (is_readable($SourceFilename)) {
264
            $md5s = phpthumb_functions::md5_file_safe($SourceFilename);
265
        } else {
266
            $phpThumb->ErrorImage('ERROR: "' . $SourceFilename . '" cannot be read');
267
        }
268
    }
269
    if (!empty($_SERVER['HTTP_REFERER'])) {
270
        $phpThumb->ErrorImage('&md5s=' . $md5s);
271
    } else {
272
        die('&md5s=' . $md5s);
273
    }
274
}
275
276
if (!empty($_GET['src']) && empty($phpThumb->config_allow_local_http_src)
277
    && preg_match('#^http://' . @$_SERVER['HTTP_HOST'] . '(.+)#i', $_GET['src'], $matches)
278
) {
279
    $phpThumb->ErrorImage('It is MUCH better to specify the "src" parameter as "'
280
                          . $matches[1]
281
                          . '" instead of "'
282
                          . $matches[0]
283
                          . '".'
284
                          . "\n\n"
285
                          . 'If you really must do it this way, enable "allow_local_http_src" in phpThumb.config.php');
286
}
287
288
////////////////////////////////////////////////////////////////
289
// Debug output, to try and help me diagnose problems
290
$phpThumb->DebugTimingMessage('phpThumbDebug[1]', __FILE__, __LINE__);
291
if (isset($_GET['phpThumbDebug']) && ($_GET['phpThumbDebug'] == '1')) {
292
    $phpThumb->phpThumbDebug();
293
}
294
////////////////////////////////////////////////////////////////
295
296
$parsed_url_referer = phpthumb_functions::ParseURLbetter(@$_SERVER['HTTP_REFERER']);
297
if ($phpThumb->config_nooffsitelink_require_refer
298
    && !in_array(@$parsed_url_referer['host'], $phpThumb->config_nohotlink_valid_domains)
299
) {
300
    $phpThumb->ErrorImage('config_nooffsitelink_require_refer enabled and ' . (@$parsed_url_referer['host'] ? '"'
301
                                                                                                              . $parsed_url_referer['host']
302
                                                                                                              . '" is not an allowed referer' : 'no HTTP_REFERER exists'));
303
}
304
$parsed_url_src = phpthumb_functions::ParseURLbetter(@$_GET['src']);
305
if ($phpThumb->config_nohotlink_enabled
306
    && $phpThumb->config_nohotlink_erase_image
307
    && preg_match('#^(f|ht)tps?://#i', @$_GET['src'])
308
    && !in_array(@$parsed_url_src['host'], $phpThumb->config_nohotlink_valid_domains)
309
) {
310
    $phpThumb->ErrorImage($phpThumb->config_nohotlink_text_message);
311
}
312
313
if ($phpThumb->config_mysql_query) {
314
    if ($phpThumb->config_mysql_extension == 'mysqli') {
315
        $found_missing_function = false;
316
        foreach (array('mysqli_connect') as $required_mysqli_function) {
317
            if (!function_exists($required_mysqli_function)) {
318
                $found_missing_function = $required_mysqli_function;
319
                break;
320
            }
321
        }
322
        if ($found_missing_function) {
323
            $phpThumb->ErrorImage('SQL function unavailable: ' . $found_missing_function);
324
        } else {
325
            $mysqli = new mysqli($phpThumb->config_mysql_hostname, $phpThumb->config_mysql_username, $phpThumb->config_mysql_password, $phpThumb->config_mysql_database);
326
            if ($mysqli->connect_error) {
327
                $phpThumb->ErrorImage('MySQLi connect error (' . $mysqli->connect_errno . ') ' . $mysqli->connect_error);
328
            } else {
329
                if ($result = $mysqli->query($phpThumb->config_mysql_query)) {
330
                    if ($row = $result->fetch_array()) {
331
                        $result->free();
332
                        $mysqli->close();
333
                        $phpThumb->setSourceData($row[0]);
334
                        unset($row);
335
                    } else {
336
                        $result->free();
337
                        $mysqli->close();
338
                        $phpThumb->ErrorImage('no matching data in database.');
339
                    }
340
                } else {
341
                    $mysqli->close();
342
                    $phpThumb->ErrorImage('Error in MySQL query: "' . $mysqli->error . '"');
343
                }
344
            }
345
            unset($_GET['id']);
346
        }
347
    } elseif ($phpThumb->config_mysql_extension == 'mysql') {
348
        $found_missing_function = false;
349
        //foreach (array('mysql_connect', 'mysql_select_db', 'mysql_query', 'mysql_fetch_array', 'mysql_free_result', '$GLOBALS['xoopsDB']->close', 'mysql_error') as $required_mysql_function) {
350
        foreach (array('mysql_connect') as $required_mysql_function) {
351
            if (!function_exists($required_mysql_function)) {
352
                $found_missing_function = $required_mysql_function;
353
                break;
354
            }
355
        }
356
        if ($found_missing_function) {
357
            $phpThumb->ErrorImage('SQL function unavailable: ' . $found_missing_function);
358
        } else {
359
            if ($cid = @mysqli_connect($phpThumb->config_mysql_hostname, $phpThumb->config_mysql_username, $phpThumb->config_mysql_password)) {
360
                if (@mysqli_select_db($GLOBALS['xoopsDB']->conn, $phpThumb->config_mysql_database, $cid)) {
361
                    if ($result = @$GLOBALS['xoopsDB']->queryF($phpThumb->config_mysql_query, $cid)) {
362
                        if ($row = @$GLOBALS['xoopsDB']->fetchBoth($result)) {
363
                            $GLOBALS['xoopsDB']->freeRecordSet($result);
364
                            $GLOBALS['xoopsDB']->close($cid);
365
                            $phpThumb->setSourceData($row[0]);
366
                            unset($row);
367
                        } else {
368
                            $GLOBALS['xoopsDB']->freeRecordSet($result);
369
                            $GLOBALS['xoopsDB']->close($cid);
370
                            $phpThumb->ErrorImage('no matching data in database.');
371
                        }
372 View Code Duplication
                    } else {
373
                        $GLOBALS['xoopsDB']->close($cid);
374
                        $phpThumb->ErrorImage('Error in MySQL query: "' . $GLOBALS['xoopsDB']->error($cid) . '"');
375
                    }
376 View Code Duplication
                } else {
377
                    $GLOBALS['xoopsDB']->close($cid);
378
                    $phpThumb->ErrorImage('cannot select MySQL database: "' . $GLOBALS['xoopsDB']->error($cid) . '"');
379
                }
380
            } else {
381
                $phpThumb->ErrorImage('cannot connect to MySQL server');
382
            }
383
            unset($_GET['id']);
384
        }
385
    } else {
386
        $phpThumb->ErrorImage('config_mysql_extension not supported');
387
    }
388
}
389
390
////////////////////////////////////////////////////////////////
391
// Debug output, to try and help me diagnose problems
392
$phpThumb->DebugTimingMessage('phpThumbDebug[2]', __FILE__, __LINE__);
393
if (isset($_GET['phpThumbDebug']) && ($_GET['phpThumbDebug'] == '2')) {
394
    $phpThumb->phpThumbDebug();
395
}
396
////////////////////////////////////////////////////////////////
397
398
$PHPTHUMB_DEFAULTS_DISABLEGETPARAMS = (bool)($phpThumb->config_cache_default_only_suffix
399
                                             && (strpos($phpThumb->config_cache_default_only_suffix, '*') !== false));
400
401
// deprecated: 'err', 'file', 'goto',
402
$allowedGETparameters = array(
403
    'src',
404
    'new',
405
    'w',
406
    'h',
407
    'wp',
408
    'hp',
409
    'wl',
410
    'hl',
411
    'ws',
412
    'hs',
413
    'f',
414
    'q',
415
    'sx',
416
    'sy',
417
    'sw',
418
    'sh',
419
    'zc',
420
    'bc',
421
    'bg',
422
    'bgt',
423
    'fltr',
424
    'xto',
425
    'ra',
426
    'ar',
427
    'aoe',
428
    'far',
429
    'iar',
430
    'maxb',
431
    'down',
432
    'phpThumbDebug',
433
    'hash',
434
    'md5s',
435
    'sfn',
436
    'dpi',
437
    'sia',
438
    'nocache'
439
);
440
foreach ($_GET as $key => $value) {
441
    if (!empty($PHPTHUMB_DEFAULTS_DISABLEGETPARAMS) && ($key != 'src')) {
442
        // disabled, do not set parameter
443
        $phpThumb->DebugMessage('ignoring $_GET[' . $key . '] because of $PHPTHUMB_DEFAULTS_DISABLEGETPARAMS', __FILE__, __LINE__);
444
    } elseif (in_array($key, $allowedGETparameters)) {
445
        $phpThumb->DebugMessage('setParameter(' . $key . ', ' . $phpThumb->phpThumbDebugVarDump($value) . ')', __FILE__, __LINE__);
446
        $phpThumb->setParameter($key, $value);
447
    } else {
448
        $phpThumb->ErrorImage('Forbidden parameter: ' . $key);
449
    }
450
}
451
452
if (!empty($PHPTHUMB_DEFAULTS) && is_array($PHPTHUMB_DEFAULTS)) {
453
    $phpThumb->DebugMessage('setting $PHPTHUMB_DEFAULTS[' . implode(';', array_keys($PHPTHUMB_DEFAULTS)) . ']', __FILE__, __LINE__);
454
    foreach ($PHPTHUMB_DEFAULTS as $key => $value) {
455
        if (!$PHPTHUMB_DEFAULTS_GETSTRINGOVERRIDE
456
            || !isset($_GET[$key])
457
        ) { // set parameter to default value if config is set to allow _GET to override default, OR if no value is passed via _GET for this parameter
458
            //$_GET[$key] = $value;
459
            //$phpThumb->DebugMessage('PHPTHUMB_DEFAULTS assigning ('.(is_array($value) ? print_r($value, true) : $value).') to $_GET['.$key.']', __FILE__, __LINE__);
460
            $phpThumb->setParameter($key, $value);
461
            $phpThumb->DebugMessage('setParameter(' . $key . ', ' . $phpThumb->phpThumbDebugVarDump($value) . ') from $PHPTHUMB_DEFAULTS', __FILE__, __LINE__);
462
        }
463
    }
464
}
465
466
////////////////////////////////////////////////////////////////
467
// Debug output, to try and help me diagnose problems
468
$phpThumb->DebugTimingMessage('phpThumbDebug[3]', __FILE__, __LINE__);
469
if (isset($_GET['phpThumbDebug']) && ($_GET['phpThumbDebug'] == '3')) {
470
    $phpThumb->phpThumbDebug();
471
}
472
////////////////////////////////////////////////////////////////
473
474
//if (!@$_GET['phpThumbDebug'] && !is_file($phpThumb->sourceFilename) && !phpthumb_functions::gd_version()) {
475
//  if (!headers_sent()) {
476
//      // base64-encoded error image in GIF format
477
//      $ERROR_NOGD = 'R0lGODlhIAAgALMAAAAAABQUFCQkJDY2NkZGRldXV2ZmZnJycoaGhpSUlKWlpbe3t8XFxdXV1eTk5P7+/iwAAAAAIAAgAAAE/vDJSau9WILtTAACUinDNijZtAHfCojS4W5H+qxD8xibIDE9h0OwWaRWDIljJSkUJYsN4bihMB8th3IToAKs1VtYM75cyV8sZ8vygtOE5yMKmGbO4jRdICQCjHdlZzwzNW4qZSQmKDaNjhUMBX4BBAlmMywFSRWEmAI6b5gAlhNxokGhooAIK5o/pi9vEw4Lfj4OLTAUpj6IabMtCwlSFw0DCKBoFqwAB04AjI54PyZ+yY3TD0ss2YcVmN/gvpcu4TOyFivWqYJlbAHPpOntvxNAACcmGHjZzAZqzSzcq5fNjxFmAFw9iFRunD1epU6tsIPmFCAJnWYE0FURk7wJDA0MTKpEzoWAAskiAAA7';
478
//      header('Content-Type: image/gif');
479
//      echo base64_decode($ERROR_NOGD);
480
//  } else {
481
//      echo '*** ERROR: No PHP-GD support available ***';
482
//  }
483
//  exit;
484
//}
485
486
// check to see if file can be output from source with no processing or caching
487
$CanPassThroughDirectly = true;
488
if ($phpThumb->rawImageData) {
489
    // data from SQL, should be fine
490
} elseif (preg_match('#^http\://[^\\?&]+\\.(jpe?g|gif|png)$#i', $phpThumb->src)) {
491
    // assume is ok to passthru if no other parameters specified
492
} elseif (preg_match('#^(f|ht)tp\://#i', $phpThumb->src)) {
493
    $phpThumb->DebugMessage('$CanPassThroughDirectly=false because preg_match("#^(f|ht)tp\://#i", ' . $phpThumb->src . ')', __FILE__, __LINE__);
494
    $CanPassThroughDirectly = false;
495
} elseif (!@is_readable($phpThumb->sourceFilename)) {
496
    $phpThumb->DebugMessage('$CanPassThroughDirectly=false because !@is_readable(' . $phpThumb->sourceFilename . ')', __FILE__, __LINE__);
497
    $CanPassThroughDirectly = false;
498
} elseif (!@is_file($phpThumb->sourceFilename)) {
499
    $phpThumb->DebugMessage('$CanPassThroughDirectly=false because !@is_file(' . $phpThumb->sourceFilename . ')', __FILE__, __LINE__);
500
    $CanPassThroughDirectly = false;
501
}
502
foreach ($_GET as $key => $value) {
503
    switch ($key) {
504
        case 'src':
505
            // allowed
506
            break;
507
508
        case 'w':
509
        case 'h':
510
            // might be OK if exactly matches original
511
            if (preg_match('#^http\://[^\\?&]+\\.(jpe?g|gif|png)$#i', $phpThumb->src)) {
512
                // assume it is not ok for direct-passthru of remote image
513
                $CanPassThroughDirectly = false;
514
            }
515
            break;
516
517
        case 'phpThumbDebug':
518
            // handled in direct-passthru code
519
            break;
520
521
        default:
522
            // all other parameters will cause some processing,
523
            // therefore cannot pass through original image unmodified
524
            $CanPassThroughDirectly = false;
525
            $UnAllowedGET[]         = $key;
526
            break;
527
    }
528
}
529
if (!empty($UnAllowedGET)) {
530
    $phpThumb->DebugMessage('$CanPassThroughDirectly=false because $_GET[' . implode(';', array_unique($UnAllowedGET)) . '] are set', __FILE__, __LINE__);
531
}
532
533
////////////////////////////////////////////////////////////////
534
// Debug output, to try and help me diagnose problems
535
$phpThumb->DebugTimingMessage('phpThumbDebug[4]', __FILE__, __LINE__);
536
if (isset($_GET['phpThumbDebug']) && ($_GET['phpThumbDebug'] == '4')) {
537
    $phpThumb->phpThumbDebug();
538
}
539
////////////////////////////////////////////////////////////////
540
541
$phpThumb->DebugMessage('$CanPassThroughDirectly="' . (int)$CanPassThroughDirectly . '" && $phpThumb->src="' . $phpThumb->src . '"', __FILE__, __LINE__);
542
while ($CanPassThroughDirectly && $phpThumb->src) {
543
    // no parameters set, passthru
544
545
    if (preg_match('#^http\://[^\\?&]+\.(jpe?g|gif|png)$#i', $phpThumb->src)) {
546
        $phpThumb->DebugMessage('Passing HTTP source through directly as Location: redirect (' . $phpThumb->src . ')', __FILE__, __LINE__);
547
        header('Location: ' . $phpThumb->src);
548
        exit;
549
    }
550
551
    $SourceFilename = $phpThumb->ResolveFilenameToAbsolute($phpThumb->src);
552
553
    // security and size checks
554
    if ($phpThumb->getimagesizeinfo = @getimagesize($SourceFilename)) {
555
        $phpThumb->DebugMessage('Direct passthru GetImageSize() returned [w=' . $phpThumb->getimagesizeinfo[0] . ';h=' . $phpThumb->getimagesizeinfo[1] . ';t=' . $phpThumb->getimagesizeinfo[2] . ']',
556
                                __FILE__, __LINE__);
557
558
        if (!@$_GET['w'] && !@$_GET['wp'] && !@$_GET['wl'] && !@$_GET['ws'] && !@$_GET['h'] && !@$_GET['hp']
559
            && !@$_GET['hl']
560
            && !@$_GET['hs']
561
        ) {
562
            // no resizing needed
563
            $phpThumb->DebugMessage('Passing "' . $SourceFilename . '" through directly, no resizing required ("' . $phpThumb->getimagesizeinfo[0] . '"x"' . $phpThumb->getimagesizeinfo[1] . '")',
564
                                    __FILE__, __LINE__);
565
        } elseif (($phpThumb->getimagesizeinfo[0] <= @$_GET['w'])
566
                  && ($phpThumb->getimagesizeinfo[1] <= @$_GET['h'])
567
                  && ((@$_GET['w'] == $phpThumb->getimagesizeinfo[0])
568
                      || (@$_GET['h'] == $phpThumb->getimagesizeinfo[1]))
569
        ) {
570
            // image fits into 'w'x'h' box, and at least one dimension matches exactly, therefore no resizing needed
571
            $phpThumb->DebugMessage('Passing "'
572
                                    . $SourceFilename
573
                                    . '" through directly, no resizing required ("'
574
                                    . $phpThumb->getimagesizeinfo[0]
575
                                    . '"x"'
576
                                    . $phpThumb->getimagesizeinfo[1]
577
                                    . '" fits inside "'
578
                                    . @$_GET['w']
579
                                    . '"x"'
580
                                    . @$_GET['h']
581
                                    . '")', __FILE__, __LINE__);
582
        } else {
583
            $phpThumb->DebugMessage('Not passing "'
584
                                    . $SourceFilename
585
                                    . '" through directly because resizing required (from "'
586
                                    . $phpThumb->getimagesizeinfo[0]
587
                                    . '"x"'
588
                                    . $phpThumb->getimagesizeinfo[1]
589
                                    . '" to "'
590
                                    . @$_GET['w']
591
                                    . '"x"'
592
                                    . @$_GET['h']
593
                                    . '")', __FILE__, __LINE__);
594
            break;
595
        }
596
        switch ($phpThumb->getimagesizeinfo[2]) {
597
            case 1: // GIF
598
            case 2: // JPG
599
            case 3: // PNG
600
                // great, let it through
601
                break;
602
            default:
603
                // browser probably can't handle format, remangle it to JPEG/PNG/GIF
604
                $phpThumb->DebugMessage('Not passing "' . $SourceFilename . '" through directly because $phpThumb->getimagesizeinfo[2] = "' . $phpThumb->getimagesizeinfo[2] . '"', __FILE__, __LINE__);
605
                break 2;
606
        }
607
608
        $ImageCreateFunctions   = array(
609
            1 => 'ImageCreateFromGIF',
610
            2 => 'ImageCreateFromJPEG',
611
            3 => 'ImageCreateFromPNG'
612
        );
613
        $theImageCreateFunction = @$ImageCreateFunctions[$phpThumb->getimagesizeinfo[2]];
614
        if ($phpThumb->config_disable_onlycreateable_passthru
615
            || (function_exists($theImageCreateFunction)
616
                && ($dummyImage = @$theImageCreateFunction($SourceFilename)))
617
        ) {
618
619
            // great
620
            if (@is_resource($dummyImage)) {
621
                unset($dummyImage);
622
            }
623
624 View Code Duplication
            if (headers_sent()) {
625
                $phpThumb->ErrorImage('Headers already sent (' . basename(__FILE__) . ' line ' . __LINE__ . ')');
626
                exit;
627
            }
628
            if (@$_GET['phpThumbDebug']) {
629
                $phpThumb->DebugTimingMessage('skipped direct $SourceFilename passthru', __FILE__, __LINE__);
630
                $phpThumb->DebugMessage('Would have passed "' . $SourceFilename . '" through directly, but skipping due to phpThumbDebug', __FILE__, __LINE__);
631
                break;
632
            }
633
634
            SendSaveAsFileHeaderIfNeeded();
635
            header('Last-Modified: ' . gmdate('D, d M Y H:i:s', @filemtime($SourceFilename)) . ' GMT');
636
            if ($contentType = phpthumb_functions::ImageTypeToMIMEtype(@$phpThumb->getimagesizeinfo[2])) {
637
                header('Content-Type: ' . $contentType);
638
            }
639
            @readfile($SourceFilename);
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition here. This can introduce security issues, and is generally not recommended.

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...
640
            exit;
641
        } else {
642
            $phpThumb->DebugMessage('Not passing "'
643
                                    . $SourceFilename
644
                                    . '" through directly because ($phpThumb->config_disable_onlycreateable_passthru = "'
645
                                    . $phpThumb->config_disable_onlycreateable_passthru
646
                                    . '") and '
647
                                    . $theImageCreateFunction
648
                                    . '() failed', __FILE__, __LINE__);
649
            break;
650
        }
651
    } else {
652
        $phpThumb->DebugMessage('Not passing "' . $SourceFilename . '" through directly because GetImageSize() failed', __FILE__, __LINE__);
653
        break;
654
    }
655
    break;
656
}
657
658
////////////////////////////////////////////////////////////////
659
// Debug output, to try and help me diagnose problems
660
$phpThumb->DebugTimingMessage('phpThumbDebug[5]', __FILE__, __LINE__);
661
if (isset($_GET['phpThumbDebug']) && ($_GET['phpThumbDebug'] == '5')) {
662
    $phpThumb->phpThumbDebug();
663
}
664
////////////////////////////////////////////////////////////////
665
666
// check to see if file already exists in cache, and output it with no processing if it does
667
$phpThumb->SetCacheFilename();
668
if (@is_readable($phpThumb->cache_filename)) {
669
    RedirectToCachedFile();
670
} else {
671
    $phpThumb->DebugMessage('Cached file "' . $phpThumb->cache_filename . '" does not exist, processing as normal', __FILE__, __LINE__);
672
}
673
674
////////////////////////////////////////////////////////////////
675
// Debug output, to try and help me diagnose problems
676
$phpThumb->DebugTimingMessage('phpThumbDebug[6]', __FILE__, __LINE__);
677
if (isset($_GET['phpThumbDebug']) && ($_GET['phpThumbDebug'] == '6')) {
678
    $phpThumb->phpThumbDebug();
679
}
680
////////////////////////////////////////////////////////////////
681
682
if ($phpThumb->rawImageData) {
683
684
    // great
685
} elseif (!empty($_GET['new'])) {
686
687
    // generate a blank image resource of the specified size/background color/opacity
688
    if (($phpThumb->w <= 0) || ($phpThumb->h <= 0)) {
689
        $phpThumb->ErrorImage('"w" and "h" parameters required for "new"');
690
    }
691
    @list($bghexcolor, $opacity) = explode('|', $_GET['new']);
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition here. This can introduce security issues, and is generally not recommended.

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...
692
    if (!phpthumb_functions::IsHexColor($bghexcolor)) {
693
        $phpThumb->ErrorImage('BGcolor parameter for "new" is not valid');
694
    }
695
    $opacity = (strlen($opacity) ? $opacity : 100);
696
    if ($phpThumb->gdimg_source = phpthumb_functions::ImageCreateFunction($phpThumb->w, $phpThumb->h)) {
697
        $alpha = (100 - min(100, max(0, $opacity))) * 1.27;
698
        if ($alpha) {
699
            $phpThumb->setParameter('is_alpha', true);
700
            ImageAlphaBlending($phpThumb->gdimg_source, false);
701
            ImageSaveAlpha($phpThumb->gdimg_source, true);
702
        }
703
        $new_background_color = phpthumb_functions::ImageHexColorAllocate($phpThumb->gdimg_source, $bghexcolor, false, $alpha);
704
        imagefilledrectangle($phpThumb->gdimg_source, 0, 0, $phpThumb->w, $phpThumb->h, $new_background_color);
705
    } else {
706
        $phpThumb->ErrorImage('failed to create "new" image (' . $phpThumb->w . 'x' . $phpThumb->h . ')');
707
    }
708
} elseif (!$phpThumb->src) {
709
    $phpThumb->ErrorImage('Usage: ' . $_SERVER['PHP_SELF'] . '?src=/path/and/filename.jpg' . "\n" . 'read Usage comments for details');
710
} elseif (preg_match('#^([a-z0-9]+)://#i', $_GET['src'], $protocol_matches)) {
711
    if (preg_match('#^(f|ht)tps?://#i', $_GET['src'])) {
712
        $phpThumb->DebugMessage('$phpThumb->src (' . $phpThumb->src . ') is remote image, attempting to download', __FILE__, __LINE__);
713
        if ($phpThumb->config_http_user_agent) {
714
            $phpThumb->DebugMessage('Setting "user_agent" to "' . $phpThumb->config_http_user_agent . '"', __FILE__, __LINE__);
715
            ini_set('user_agent', $phpThumb->config_http_user_agent);
716
        }
717
        $cleanedupurl = phpthumb_functions::CleanUpURLencoding($phpThumb->src);
718
        $phpThumb->DebugMessage('CleanUpURLencoding(' . $phpThumb->src . ') returned "' . $cleanedupurl . '"', __FILE__, __LINE__);
719
        $phpThumb->src = $cleanedupurl;
720
        unset($cleanedupurl);
721
        if ($rawImageData = phpthumb_functions::SafeURLread($phpThumb->src, $error, $phpThumb->config_http_fopen_timeout, $phpThumb->config_http_follow_redirect)) {
722
            $phpThumb->DebugMessage('SafeURLread(' . $phpThumb->src . ') succeeded' . ($error ? ' with messsages: "' . $error . '"' : ''), __FILE__, __LINE__);
723
            $phpThumb->DebugMessage('Setting source data from URL "' . $phpThumb->src . '"', __FILE__, __LINE__);
724
            $phpThumb->setSourceData($rawImageData, urlencode($phpThumb->src));
725
        } else {
726
            $phpThumb->ErrorImage($error);
727
        }
728
    } else {
729
        $phpThumb->ErrorImage('only FTP and HTTP/HTTPS protocols are allowed, "' . $protocol_matches[1] . '" is not');
730
    }
731
}
732
733
////////////////////////////////////////////////////////////////
734
// Debug output, to try and help me diagnose problems
735
$phpThumb->DebugTimingMessage('phpThumbDebug[7]', __FILE__, __LINE__);
736
if (isset($_GET['phpThumbDebug']) && ($_GET['phpThumbDebug'] == '7')) {
737
    $phpThumb->phpThumbDebug();
738
}
739
////////////////////////////////////////////////////////////////
740
741
$phpThumb->GenerateThumbnail();
742
743
////////////////////////////////////////////////////////////////
744
// Debug output, to try and help me diagnose problems
745
$phpThumb->DebugTimingMessage('phpThumbDebug[8]', __FILE__, __LINE__);
746
if (isset($_GET['phpThumbDebug']) && ($_GET['phpThumbDebug'] == '8')) {
747
    $phpThumb->phpThumbDebug();
748
}
749
////////////////////////////////////////////////////////////////
750
751
if (!empty($phpThumb->config_high_security_enabled) && !empty($_GET['nocache'])) {
752
753
    // cache disabled, don't write cachefile
754
} else {
755
    phpthumb_functions::EnsureDirectoryExists(dirname($phpThumb->cache_filename));
756
    if (is_writable(dirname($phpThumb->cache_filename))
757
        || (file_exists($phpThumb->cache_filename)
758
            && is_writable($phpThumb->cache_filename))
759
    ) {
760
        $phpThumb->CleanUpCacheDirectory();
761
        if ($phpThumb->RenderToFile($phpThumb->cache_filename) && is_readable($phpThumb->cache_filename)) {
762
            chmod($phpThumb->cache_filename, 0644);
763
            RedirectToCachedFile();
764
        } else {
765
            $phpThumb->DebugMessage('Failed: RenderToFile(' . $phpThumb->cache_filename . ')', __FILE__, __LINE__);
766
        }
767
    } else {
768
        $phpThumb->DebugMessage('Cannot write to $phpThumb->cache_filename (' . $phpThumb->cache_filename . ') because that directory (' . dirname($phpThumb->cache_filename) . ') is not writable',
769
                                __FILE__, __LINE__);
770
    }
771
}
772
773
////////////////////////////////////////////////////////////////
774
// Debug output, to try and help me diagnose problems
775
$phpThumb->DebugTimingMessage('phpThumbDebug[9]', __FILE__, __LINE__);
776
if (isset($_GET['phpThumbDebug']) && ($_GET['phpThumbDebug'] == '9')) {
777
    $phpThumb->phpThumbDebug();
778
}
779
////////////////////////////////////////////////////////////////
780
781
if (!$phpThumb->OutputThumbnail()) {
782
    $phpThumb->ErrorImage('Error in OutputThumbnail():' . "\n" . $phpThumb->debugmessages[count($phpThumb->debugmessages) - 1]);
783
}
784
785
////////////////////////////////////////////////////////////////
786
// Debug output, to try and help me diagnose problems
787
$phpThumb->DebugTimingMessage('phpThumbDebug[10]', __FILE__, __LINE__);
788
if (isset($_GET['phpThumbDebug']) && ($_GET['phpThumbDebug'] == '10')) {
789
    $phpThumb->phpThumbDebug();
790
}
791
////////////////////////////////////////////////////////////////
792