Failed Conditions
Branch release-2.1 (4e22cf)
by Rick
06:39
created

ShowAttachments.php ➔ showAttachment()   F

Complexity

Conditions 81
Paths > 20000

Size

Total Lines 334
Code Lines 160

Duplication

Lines 62
Ratio 18.56 %

Importance

Changes 0
Metric Value
cc 81
eloc 160
nc 429496.7295
nop 0
dl 62
loc 334
rs 2
c 0
b 0
f 0

How to fix   Long Method    Complexity   

Long Method

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

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

Commonly applied refactorings include:

1
<?php
2
3
/**
4
 * This file handles avatar and attachment preview requests. The whole point of this file is to reduce the loaded stuff to show an image.
5
 *
6
 * Simple Machines Forum (SMF)
7
 *
8
 * @package SMF
9
 * @author Simple Machines http://www.simplemachines.org
10
 * @copyright 2017 Simple Machines and individual contributors
11
 * @license http://www.simplemachines.org/about/smf/license.php BSD
12
 *
13
 * @version 2.1 Beta 4
14
 */
15
16
if (!defined('SMF'))
17
	die('No direct access...');
18
19
/**
20
 * Shows an avatar based on $_GET['attach']
21
 */
22
function showAttachment()
23
{
24
	global $smcFunc, $modSettings, $maintenance, $context;
25
26
	// Some defaults that we need.
27
	$context['character_set'] = empty($modSettings['global_character_set']) ? (empty($txt['lang_character_set']) ? 'ISO-8859-1' : $txt['lang_character_set']) : $modSettings['global_character_set'];
0 ignored issues
show
Bug introduced by
The variable $txt seems to never exist, and therefore empty should always return true. Did you maybe rename this variable?

This check looks for calls to isset(...) or empty() on variables that are yet undefined. These calls will always produce the same result and can be removed.

This is most likely caused by the renaming of a variable or the removal of a function/method parameter.

Loading history...
28
	$context['utf8'] = $context['character_set'] === 'UTF-8';
29
30
	// An early hook to set up global vars, clean cache and other early process.
31
	call_integration_hook('integrate_pre_download_request');
32
33
	// This is done to clear any output that was made before now.
34
	ob_end_clean();
35
36
	if (!empty($modSettings['enableCompressedOutput']) && !headers_sent() && ob_get_length() == 0)
37
	{
38 View Code Duplication
		if (@ini_get('zlib.output_compression') == '1' || @ini_get('output_handler') == 'ob_gzhandler')
39
			$modSettings['enableCompressedOutput'] = 0;
40
41
		else
42
			ob_start('ob_gzhandler');
43
	}
44
45
	if (empty($modSettings['enableCompressedOutput']))
46
	{
47
		ob_start();
48
		header('Content-Encoding: none');
49
	}
50
51
	// Better handling.
52
	$attachId = isset($_REQUEST['attach']) ? (int) $_REQUEST['attach'] : (int) (isset($_REQUEST['id']) ? (int) $_REQUEST['id'] : 0);
53
54
	// We need a valid ID.
55
	if (empty($attachId))
56
	{
57
		header('HTTP/1.0 404 File Not Found');
58
		die('404 File Not Found');
59
	}
60
61
	// A thumbnail has been requested? madness! madness I say!
62
	$preview = isset($_REQUEST['preview']) ? $_REQUEST['preview'] : (isset($_REQUEST['type']) && $_REQUEST['type'] == 'preview' ? $_REQUEST['type'] : 0);
63
	$showThumb = isset($_REQUEST['thumb']) || !empty($preview);
64
	$attachTopic = isset($_REQUEST['topic']) ? (int) $_REQUEST['topic'] : 0;
65
66
	// No access in strict maintenance mode or you don't have permission to see attachments.
67
	if ((!empty($maintenance) && $maintenance == 2) || !allowedTo('view_attachments'))
68
	{
69
		header('HTTP/1.0 404 File Not Found');
70
		die('404 File Not Found');
71
	}
72
73
	// Use cache when possible.
74
	if (($cache = cache_get_data('attachment_lookup_id-' . $attachId)) != null)
75
		list($file, $thumbFile) = $cache;
76
77
	// Get the info from the DB.
78
	if (empty($file) || empty($thumbFile) && !empty($file['id_thumb']))
79
	{
80
		// Do we have a hook wanting to use our attachment system? We use $attachRequest to prevent accidental usage of $request.
81
		$attachRequest = null;
82
		call_integration_hook('integrate_download_request', array(&$attachRequest));
83
		if (!is_null($attachRequest) && $smcFunc['db_is_resource']($attachRequest))
84
			$request = $attachRequest;
85
86
		else
87
		{
88
			// Make sure this attachment is on this board and load its info while we are at it.
89
			$request = $smcFunc['db_query']('', '
90
				SELECT id_folder, filename, file_hash, fileext, id_attach, id_thumb, attachment_type, mime_type, approved, id_msg
91
				FROM {db_prefix}attachments
92
				WHERE id_attach = {int:attach}
93
				LIMIT 1',
94
				array(
95
					'attach' => $attachId,
96
				)
97
			);
98
		}
99
100
		// No attachment has been found.
101
		if ($smcFunc['db_num_rows']($request) == 0)
102
		{
103
			header('HTTP/1.0 404 File Not Found');
104
			die('404 File Not Found');
105
		}
106
107
		$file = $smcFunc['db_fetch_assoc']($request);
108
		$smcFunc['db_free_result']($request);
109
110
		// If theres a message ID stored, we NEED a topic ID.
111
		if (!empty($file['id_msg']) && empty($attachTopic) && empty($preview))
112
		{
113
			header('HTTP/1.0 404 File Not Found');
114
			die('404 File Not Found');
115
		}
116
117
		// Previews doesn't have this info.
118
		if (empty($preview))
119
		{
120
			$request2 = $smcFunc['db_query']('', '
121
				SELECT a.id_msg
122
				FROM {db_prefix}attachments AS a
123
					INNER JOIN {db_prefix}messages AS m ON (m.id_msg = a.id_msg AND m.id_topic = {int:current_topic})
124
					INNER JOIN {db_prefix}boards AS b ON (b.id_board = m.id_board AND {query_see_board})
125
				WHERE a.id_attach = {int:attach}
126
				LIMIT 1',
127
				array(
128
					'attach' => $attachId,
129
					'current_topic' => $attachTopic,
130
				)
131
			);
132
133
			// The provided topic must match the one stored in the DB for this particular attachment, also.
134
			if ($smcFunc['db_num_rows']($request2) == 0)
135
			{
136
				header('HTTP/1.0 404 File Not Found');
137
				die('404 File Not Found');
138
			}
139
140
			$smcFunc['db_free_result']($request2);
141
		}
142
143
		// set filePath and ETag time
144
		$file['filePath'] = getAttachmentFilename($file['filename'], $attachId, $file['id_folder'], false, $file['file_hash']);
145
		// ensure variant attachment compatibility
146
		$filePath = pathinfo($file['filePath']);
147
		$file['filePath'] = !file_exists($file['filePath']) ? substr($file['filePath'], 0, -(strlen($filePath['extension']) + 1)) : $file['filePath'];
148
		$file['etag'] = '"' . md5_file($file['filePath']) . '"';
149
150
		// now get the thumbfile!
151
		$thumbFile = array();
152
		if (!empty($file['id_thumb']))
153
		{
154
			$request = $smcFunc['db_query']('', '
155
				SELECT id_folder, filename, file_hash, fileext, id_attach, attachment_type, mime_type, approved, id_member
156
				FROM {db_prefix}attachments
157
				WHERE id_attach = {int:thumb_id}
158
				LIMIT 1',
159
				array(
160
					'thumb_id' => $file['id_thumb'],
161
				)
162
			);
163
164
			$thumbFile = $smcFunc['db_fetch_assoc']($request);
165
			$smcFunc['db_free_result']($request);
166
167
			// Got something! replace the $file var with the thumbnail info.
168 View Code Duplication
			if ($thumbFile)
169
			{
170
				$attachId = $thumbFile['id_attach'];
171
172
				// set filePath and ETag time
173
				$thumbFile['filePath'] = getAttachmentFilename($thumbFile['filename'], $attachId, $thumbFile['id_folder'], false, $thumbFile['file_hash']);
174
				$thumbFile['etag'] = '"' . md5_file($thumbFile['filePath']) . '"';
175
			}
176
		}
177
178
		// Cache it.
179
		if (!empty($file) || !empty($thumbFile))
180
			cache_put_data('attachment_lookup_id-' . $file['id_attach'], array($file, $thumbFile), mt_rand(850, 900));
181
	}
182
183
	// Replace the normal file with its thumbnail if it has one!
184
	if (!empty($showThumb) && !empty($thumbFile))
185
		$file = $thumbFile;
186
187
	// No point in a nicer message, because this is supposed to be an attachment anyway...
188 View Code Duplication
	if (!file_exists($file['filePath']))
189
	{
190
		header((preg_match('~HTTP/1\.[01]~i', $_SERVER['SERVER_PROTOCOL']) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0') . ' 404 Not Found');
191
		header('Content-Type: text/plain; charset=' . (empty($context['character_set']) ? 'ISO-8859-1' : $context['character_set']));
192
193
		// We need to die like this *before* we send any anti-caching headers as below.
194
		die('File not found.');
195
	}
196
197
	// If it hasn't been modified since the last time this attachment was retrieved, there's no need to display it again.
198 View Code Duplication
	if (!empty($_SERVER['HTTP_IF_MODIFIED_SINCE']))
199
	{
200
		list($modified_since) = explode(';', $_SERVER['HTTP_IF_MODIFIED_SINCE']);
201
		if (strtotime($modified_since) >= filemtime($file['filePath']))
202
		{
203
			ob_end_clean();
204
205
			// Answer the question - no, it hasn't been modified ;).
206
			header('HTTP/1.1 304 Not Modified');
207
			exit;
208
		}
209
	}
210
211
	// Check whether the ETag was sent back, and cache based on that...
212
	$eTag = '"' . substr($_REQUEST['attach'] . $file['filePath'] . filemtime($file['filePath']), 0, 64) . '"';
213 View Code Duplication
	if (!empty($_SERVER['HTTP_IF_NONE_MATCH']) && strpos($_SERVER['HTTP_IF_NONE_MATCH'], $eTag) !== false)
214
	{
215
		ob_end_clean();
216
217
		header('HTTP/1.1 304 Not Modified');
218
		exit;
219
	}
220
221
	// If this is a partial download, we need to determine what data range to send
222
	$range = 0;
223
	$size = filesize($file['filePath']);
224
	if (isset($_SERVER['HTTP_RANGE']))
225
	{
226
		list($a, $range) = explode("=", $_SERVER['HTTP_RANGE'], 2);
0 ignored issues
show
Unused Code introduced by
The assignment to $a is unused. Consider omitting it like so list($first,,$third).

This checks looks for assignemnts to variables using the list(...) function, where not all assigned variables are subsequently used.

Consider the following code example.

<?php

function returnThreeValues() {
    return array('a', 'b', 'c');
}

list($a, $b, $c) = returnThreeValues();

print $a . " - " . $c;

Only the variables $a and $c are used. There was no need to assign $b.

Instead, the list call could have been.

list($a,, $c) = returnThreeValues();
Loading history...
Comprehensibility introduced by
Avoid variables with short names like $a. Configured minimum length is 3.

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

Loading history...
Coding Style Comprehensibility introduced by
The string literal = does not require double quotes, as per coding-style, please use single quotes.

PHP provides two ways to mark string literals. Either with single quotes 'literal' or with double quotes "literal". The difference between these is that string literals in double quotes may contain variables with are evaluated at run-time as well as escape sequences.

String literals in single quotes on the other hand are evaluated very literally and the only two characters that needs escaping in the literal are the single quote itself (\') and the backslash (\\). Every other character is displayed as is.

Double quoted string literals may contain other variables or more complex escape sequences.

<?php

$singleQuoted = 'Value';
$doubleQuoted = "\tSingle is $singleQuoted";

print $doubleQuoted;

will print an indented: Single is Value

If your string literal does not contain variables or escape sequences, it should be defined using single quotes to make that fact clear.

For more information on PHP string literals and available escape sequences see the PHP core documentation.

Loading history...
227
		list($range) = explode(",", $range, 2);
0 ignored issues
show
Coding Style Comprehensibility introduced by
The string literal , does not require double quotes, as per coding-style, please use single quotes.

PHP provides two ways to mark string literals. Either with single quotes 'literal' or with double quotes "literal". The difference between these is that string literals in double quotes may contain variables with are evaluated at run-time as well as escape sequences.

String literals in single quotes on the other hand are evaluated very literally and the only two characters that needs escaping in the literal are the single quote itself (\') and the backslash (\\). Every other character is displayed as is.

Double quoted string literals may contain other variables or more complex escape sequences.

<?php

$singleQuoted = 'Value';
$doubleQuoted = "\tSingle is $singleQuoted";

print $doubleQuoted;

will print an indented: Single is Value

If your string literal does not contain variables or escape sequences, it should be defined using single quotes to make that fact clear.

For more information on PHP string literals and available escape sequences see the PHP core documentation.

Loading history...
228
		list($range, $range_end) = explode("-", $range);
0 ignored issues
show
Coding Style Comprehensibility introduced by
The string literal - does not require double quotes, as per coding-style, please use single quotes.

PHP provides two ways to mark string literals. Either with single quotes 'literal' or with double quotes "literal". The difference between these is that string literals in double quotes may contain variables with are evaluated at run-time as well as escape sequences.

String literals in single quotes on the other hand are evaluated very literally and the only two characters that needs escaping in the literal are the single quote itself (\') and the backslash (\\). Every other character is displayed as is.

Double quoted string literals may contain other variables or more complex escape sequences.

<?php

$singleQuoted = 'Value';
$doubleQuoted = "\tSingle is $singleQuoted";

print $doubleQuoted;

will print an indented: Single is Value

If your string literal does not contain variables or escape sequences, it should be defined using single quotes to make that fact clear.

For more information on PHP string literals and available escape sequences see the PHP core documentation.

Loading history...
229
		$range = intval($range);
230
		$range_end = !$range_end ? $size - 1 : intval($range_end);
231
		$new_length = $range_end - $range + 1;
232
	}
233
234
	// Update the download counter (unless it's a thumbnail or resuming an incomplete download).
235
	if ($file['attachment_type'] != 3 && empty($showThumb) && $range === 0)
236
		$smcFunc['db_query']('attach_download_increase', '
237
			UPDATE LOW_PRIORITY {db_prefix}attachments
238
			SET downloads = downloads + 1
239
			WHERE id_attach = {int:id_attach}',
240
			array(
241
				'id_attach' => $attachId,
242
			)
243
		);
244
245
	// Send the attachment headers.
246
	header('Pragma: ');
247
248
	if (!isBrowser('gecko'))
249
		header('Content-Transfer-Encoding: binary');
250
251
	header('Expires: ' . gmdate('D, d M Y H:i:s', time() + 525600 * 60) . ' GMT');
252
	header('Last-Modified: ' . gmdate('D, d M Y H:i:s', filemtime($file['filePath'])) . ' GMT');
253
	header('Accept-Ranges: bytes');
254
	header('Connection: close');
255
	header('ETag: ' . $eTag);
256
257
	// Make sure the mime type warrants an inline display.
258
	if (isset($_REQUEST['image']) && !empty($file['mime_type']) && strpos($file['mime_type'], 'image/') !== 0)
259
		unset($_REQUEST['image']);
260
261
	// Does this have a mime type?
262
	elseif (!empty($file['mime_type']) && (isset($_REQUEST['image']) || !in_array($file['fileext'], array('jpg', 'gif', 'jpeg', 'x-ms-bmp', 'png', 'psd', 'tiff', 'iff'))))
263
		header('Content-Type: ' . strtr($file['mime_type'], array('image/bmp' => 'image/x-ms-bmp')));
264
265 View Code Duplication
	else
266
	{
267
		header('Content-Type: ' . (isBrowser('ie') || isBrowser('opera') ? 'application/octetstream' : 'application/octet-stream'));
268
		if (isset($_REQUEST['image']))
269
			unset($_REQUEST['image']);
270
	}
271
272
	// Convert the file to UTF-8, cuz most browsers dig that.
273
	$utf8name = !$context['utf8'] && function_exists('iconv') ? iconv($context['character_set'], 'UTF-8', $file['filename']) : (!$context['utf8'] && function_exists('mb_convert_encoding') ? mb_convert_encoding($file['filename'], 'UTF-8', $context['character_set']) : $file['filename']);
274
	$disposition = !isset($_REQUEST['image']) ? 'attachment' : 'inline';
275
276
	// Different browsers like different standards...
277 View Code Duplication
	if (isBrowser('firefox'))
278
		header('Content-Disposition: ' . $disposition . '; filename*=UTF-8\'\'' . rawurlencode(preg_replace_callback('~&#(\d{3,8});~', 'fixchar__callback', $utf8name)));
279
280
	elseif (isBrowser('opera'))
281
		header('Content-Disposition: ' . $disposition . '; filename="' . preg_replace_callback('~&#(\d{3,8});~', 'fixchar__callback', $utf8name) . '"');
282
283
	elseif (isBrowser('ie'))
284
		header('Content-Disposition: ' . $disposition . '; filename="' . urlencode(preg_replace_callback('~&#(\d{3,8});~', 'fixchar__callback', $utf8name)) . '"');
285
286
	else
287
		header('Content-Disposition: ' . $disposition . '; filename="' . $utf8name . '"');
288
289
	// If this has an "image extension" - but isn't actually an image - then ensure it isn't cached cause of silly IE.
290 View Code Duplication
	if (!isset($_REQUEST['image']) && in_array($file['fileext'], array('gif', 'jpg', 'bmp', 'png', 'jpeg', 'tiff')))
291
		header('Cache-Control: no-cache');
292
293
	else
294
		header('Cache-Control: max-age=' . (525600 * 60) . ', private');
295
296
	// Multipart and resuming support
297
	if (isset($_SERVER['HTTP_RANGE']))
298
	{
299
		header("HTTP/1.1 206 Partial Content");
0 ignored issues
show
Coding Style Comprehensibility introduced by
The string literal HTTP/1.1 206 Partial Content does not require double quotes, as per coding-style, please use single quotes.

PHP provides two ways to mark string literals. Either with single quotes 'literal' or with double quotes "literal". The difference between these is that string literals in double quotes may contain variables with are evaluated at run-time as well as escape sequences.

String literals in single quotes on the other hand are evaluated very literally and the only two characters that needs escaping in the literal are the single quote itself (\') and the backslash (\\). Every other character is displayed as is.

Double quoted string literals may contain other variables or more complex escape sequences.

<?php

$singleQuoted = 'Value';
$doubleQuoted = "\tSingle is $singleQuoted";

print $doubleQuoted;

will print an indented: Single is Value

If your string literal does not contain variables or escape sequences, it should be defined using single quotes to make that fact clear.

For more information on PHP string literals and available escape sequences see the PHP core documentation.

Loading history...
300
		header("Content-Length: $new_length");
0 ignored issues
show
Bug introduced by
The variable $new_length does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
Coding Style Best Practice introduced by
As per coding-style, please use concatenation or sprintf for the variable $new_length instead of interpolation.

It is generally a best practice as it is often more readable to use concatenation instead of interpolation for variables inside strings.

// Instead of
$x = "foo $bar $baz";

// Better use either
$x = "foo " . $bar . " " . $baz;
$x = sprintf("foo %s %s", $bar, $baz);
Loading history...
301
		header("Content-Range: bytes $range-$range_end/$size");
0 ignored issues
show
Bug introduced by
The variable $range_end does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
Coding Style Best Practice introduced by
As per coding-style, please use concatenation or sprintf for the variable $range instead of interpolation.

It is generally a best practice as it is often more readable to use concatenation instead of interpolation for variables inside strings.

// Instead of
$x = "foo $bar $baz";

// Better use either
$x = "foo " . $bar . " " . $baz;
$x = sprintf("foo %s %s", $bar, $baz);
Loading history...
Coding Style Best Practice introduced by
As per coding-style, please use concatenation or sprintf for the variable $range_end instead of interpolation.

It is generally a best practice as it is often more readable to use concatenation instead of interpolation for variables inside strings.

// Instead of
$x = "foo $bar $baz";

// Better use either
$x = "foo " . $bar . " " . $baz;
$x = sprintf("foo %s %s", $bar, $baz);
Loading history...
Coding Style Best Practice introduced by
As per coding-style, please use concatenation or sprintf for the variable $size instead of interpolation.

It is generally a best practice as it is often more readable to use concatenation instead of interpolation for variables inside strings.

// Instead of
$x = "foo $bar $baz";

// Better use either
$x = "foo " . $bar . " " . $baz;
$x = sprintf("foo %s %s", $bar, $baz);
Loading history...
302
	}
303
	else
304
		header("Content-Length: " . $size);
0 ignored issues
show
Coding Style Comprehensibility introduced by
The string literal Content-Length: does not require double quotes, as per coding-style, please use single quotes.

PHP provides two ways to mark string literals. Either with single quotes 'literal' or with double quotes "literal". The difference between these is that string literals in double quotes may contain variables with are evaluated at run-time as well as escape sequences.

String literals in single quotes on the other hand are evaluated very literally and the only two characters that needs escaping in the literal are the single quote itself (\') and the backslash (\\). Every other character is displayed as is.

Double quoted string literals may contain other variables or more complex escape sequences.

<?php

$singleQuoted = 'Value';
$doubleQuoted = "\tSingle is $singleQuoted";

print $doubleQuoted;

will print an indented: Single is Value

If your string literal does not contain variables or escape sequences, it should be defined using single quotes to make that fact clear.

For more information on PHP string literals and available escape sequences see the PHP core documentation.

Loading history...
305
306
307
	// Try to buy some time...
308
	@set_time_limit(600);
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...
309
310
	// For multipart/resumable downloads, send the requested chunk(s) of the file
311
	if (isset($_SERVER['HTTP_RANGE']))
312
	{
313
		while (@ob_get_level() > 0)
314
			@ob_end_clean();
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...
315
316
		// 40 kilobytes is a good-ish amount
317
		$chunksize = 40 * 1024;
318
		$bytes_sent = 0;
319
320
		$fp = fopen($file['filePath'], 'rb');
0 ignored issues
show
Comprehensibility introduced by
Avoid variables with short names like $fp. Configured minimum length is 3.

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

Loading history...
321
322
		fseek($fp, $range);
323
324
		while (!feof($fp) && (!connection_aborted()) && ($bytes_sent < $new_length))
325
		{
326
			$buffer = fread($fp, $chunksize);
327
			echo($buffer);
328
			flush();
329
			$bytes_sent += strlen($buffer);
330
		}
331
		fclose($fp);
332
	}
333
334
	// Since we don't do output compression for files this large...
335
	elseif ($size > 4194304)
336
	{
337
		// Forcibly end any output buffering going on.
338
		while (@ob_get_level() > 0)
339
			@ob_end_clean();
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...
340
341
		$fp = fopen($file['filePath'], 'rb');
342
		while (!feof($fp))
343
		{
344
			echo fread($fp, 8192);
345
			flush();
346
		}
347
		fclose($fp);
348
	}
349
350
	// On some of the less-bright hosts, readfile() is disabled.  It's just a faster, more byte safe, version of what's in the if.
351
	elseif (@readfile($file['filePath']) === null)
352
		echo file_get_contents($file['filePath']);
353
354
	die();
355
}
356
357
?>