1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40: 41: 42: 43: 44: 45: 46: 47: 48: 49: 50: 51: 52: 53: 54: 55: 56: 57: 58: 59: 60: 61: 62: 63: 64: 65: 66: 67: 68: 69: 70: 71: 72: 73: 74: 75: 76: 77: 78: 79: 80: 81: 82: 83: 84: 85: 86: 87: 88: 89: 90: 91: 92: 93: 94: 95: 96: 97: 98: 99: 100: 101: 102: 103: 104: 105: 106: 107: 108: 109: 110: 111: 112: 113: 114: 115: 116: 117: 118: 119: 120: 121: 122: 123: 124: 125: 126: 127: 128: 129: 130: 131: 132: 133: 134: 135: 136: 137: 138: 139: 140: 141: 142: 143: 144: 145: 146: 147: 148: 149: 150: 151: 152: 153: 154: 155: 156: 157: 158: 159: 160: 161: 162: 163: 164: 165: 166: 167: 168: 169: 170: 171: 172: 173: 174: 175: 176: 177: 178: 179: 180: 181: 182: 183: 184: 185: 186: 187: 188: 189: 190: 191: 192: 193: 194: 195: 196: 197: 198: 199: 200: 201: 202: 203: 204: 205: 206: 207: 208: 209: 210: 211: 212: 213: 214: 215: 216: 217: 218: 219: 220: 221: 222: 223: 224: 225: 226: 227: 228: 229: 230: 231: 232: 233: 234: 235: 236: 237: 238: 239: 240: 241: 242: 243: 244: 245: 246: 247: 248: 249: 250: 251: 252: 253: 254: 255: 256: 257: 258: 259: 260: 261: 262: 263: 264: 265: 266: 267: 268: 269: 270: 271: 272: 273: 274: 275: 276: 277: 278: 279: 280: 281: 282: 283: 284: 285: 286: 287: 288: 289: 290: 291: 292: 293: 294: 295: 296: 297: 298: 299: 300: 301: 302: 303: 304: 305: 306: 307: 308: 309: 310: 311: 312: 313: 314: 315: 316: 317: 318: 319: 320: 321: 322: 323: 324: 325: 326: 327: 328: 329: 330: 331: 332: 333: 334: 335: 336: 337: 338: 339: 340: 341: 342: 343: 344: 345: 346: 347: 348: 349: 350: 351: 352: 353: 354: 355: 356: 357: 358: 359: 360: 361: 362: 363: 364: 365: 366: 367: 368: 369:
<?php
if (!defined('SMF'))
die('No direct access...');
function showAttachment()
{
global $smcFunc, $modSettings, $maintenance, $context, $txt;
$context['character_set'] = empty($modSettings['global_character_set']) ? (empty($txt['lang_character_set']) ? 'ISO-8859-1' : $txt['lang_character_set']) : $modSettings['global_character_set'];
$context['utf8'] = $context['character_set'] === 'UTF-8';
call_integration_hook('integrate_pre_download_request');
ob_end_clean();
if (!empty($modSettings['enableCompressedOutput']) && !headers_sent() && ob_get_length() == 0)
{
if (@ini_get('zlib.output_compression') == '1' || @ini_get('output_handler') == 'ob_gzhandler')
$modSettings['enableCompressedOutput'] = 0;
else
ob_start('ob_gzhandler');
}
if (empty($modSettings['enableCompressedOutput']))
{
ob_start();
header('content-encoding: none');
}
$attachId = isset($_REQUEST['attach']) ? (int) $_REQUEST['attach'] : (int) (isset($_REQUEST['id']) ? (int) $_REQUEST['id'] : 0);
if (empty($attachId))
{
send_http_status(404, 'File Not Found');
die('404 File Not Found');
}
$preview = isset($_REQUEST['preview']) ? $_REQUEST['preview'] : (isset($_REQUEST['type']) && $_REQUEST['type'] == 'preview' ? $_REQUEST['type'] : 0);
$showThumb = isset($_REQUEST['thumb']) || !empty($preview);
$attachTopic = isset($_REQUEST['topic']) ? (int) $_REQUEST['topic'] : 0;
if ((!empty($maintenance) && $maintenance == 2) || !allowedTo('view_attachments'))
{
send_http_status(404, 'File Not Found');
die('404 File Not Found');
}
if (($cache = cache_get_data('attachment_lookup_id-' . $attachId)) != null)
list ($file, $thumbFile) = $cache;
if (empty($file) || empty($thumbFile) && !empty($file['id_thumb']))
{
$attachRequest = null;
call_integration_hook('integrate_download_request', array(&$attachRequest));
if (!is_null($attachRequest) && $smcFunc['db_is_resource']($attachRequest))
$request = $attachRequest;
else
{
$request = $smcFunc['db_query']('', '
SELECT
id_folder, filename, file_hash, fileext, id_attach,
id_thumb, attachment_type, mime_type, approved, id_msg
FROM {db_prefix}attachments
WHERE id_attach = {int:attach}' . (!empty($context['preview_message']) ? '
AND a.id_msg != 0' : '') . '
LIMIT 1',
array(
'attach' => $attachId,
)
);
}
if ($smcFunc['db_num_rows']($request) == 0)
{
send_http_status(404, 'File Not Found');
die('404 File Not Found');
}
$file = $smcFunc['db_fetch_assoc']($request);
$smcFunc['db_free_result']($request);
if (!empty($file['id_msg']) && empty($attachTopic) && empty($preview))
{
send_http_status(404, 'File Not Found');
die('404 File Not Found');
}
if (empty($preview) && is_resource($attachRequest))
{
$request2 = $smcFunc['db_query']('', '
SELECT a.id_msg
FROM {db_prefix}attachments AS a
INNER JOIN {db_prefix}messages AS m ON (m.id_msg = a.id_msg AND m.id_topic = {int:current_topic})
WHERE {query_see_message_board}
AND a.id_attach = {int:attach}
LIMIT 1',
array(
'attach' => $attachId,
'current_topic' => $attachTopic,
)
);
if ($smcFunc['db_num_rows']($request2) == 0)
{
send_http_status(404, 'File Not Found');
die('404 File Not Found');
}
$smcFunc['db_free_result']($request2);
}
$file['filePath'] = getAttachmentFilename($file['filename'], $attachId, $file['id_folder'], false, $file['file_hash']);
$filePath = pathinfo($file['filePath']);
$file['filePath'] = !file_exists($file['filePath']) && isset($filePath['extension']) ? substr($file['filePath'], 0, -(strlen($filePath['extension']) + 1)) : $file['filePath'];
$file['etag'] = '"' . md5_file($file['filePath']) . '"';
$thumbFile = array();
if (!empty($file['id_thumb']))
{
$request = $smcFunc['db_query']('', '
SELECT id_folder, filename, file_hash, fileext, id_attach, attachment_type, mime_type, approved, id_member
FROM {db_prefix}attachments
WHERE id_attach = {int:thumb_id}
LIMIT 1',
array(
'thumb_id' => $file['id_thumb'],
)
);
$thumbFile = $smcFunc['db_fetch_assoc']($request);
$smcFunc['db_free_result']($request);
if ($thumbFile)
{
$attachId = $thumbFile['id_attach'];
$thumbFile['filePath'] = getAttachmentFilename($thumbFile['filename'], $attachId, $thumbFile['id_folder'], false, $thumbFile['file_hash']);
$thumbFile['etag'] = '"' . md5_file($thumbFile['filePath']) . '"';
}
}
if (!empty($file) || !empty($thumbFile))
cache_put_data('attachment_lookup_id-' . $file['id_attach'], array($file, $thumbFile), mt_rand(850, 900));
}
if (!empty($showThumb) && !empty($thumbFile))
$file = $thumbFile;
if (!file_exists($file['filePath']))
{
send_http_status(404);
header('content-type: text/plain; charset=' . (empty($context['character_set']) ? 'ISO-8859-1' : $context['character_set']));
die('File not found.');
}
if (!empty($_SERVER['HTTP_IF_MODIFIED_SINCE']))
{
list($modified_since) = explode(';', $_SERVER['HTTP_IF_MODIFIED_SINCE']);
if (strtotime($modified_since) >= filemtime($file['filePath']))
{
ob_end_clean();
send_http_status(304);
exit;
}
}
$eTag = '"' . substr($_REQUEST['attach'] . $file['filePath'] . filemtime($file['filePath']), 0, 64) . '"';
if (!empty($_SERVER['HTTP_IF_NONE_MATCH']) && strpos($_SERVER['HTTP_IF_NONE_MATCH'], $eTag) !== false)
{
ob_end_clean();
send_http_status(304);
exit;
}
$range = 0;
$size = filesize($file['filePath']);
if (isset($_SERVER['HTTP_RANGE']))
{
list($a, $range) = explode("=", $_SERVER['HTTP_RANGE'], 2);
list($range) = explode(",", $range, 2);
list($range, $range_end) = explode("-", $range);
$range = intval($range);
$range_end = !$range_end ? $size - 1 : intval($range_end);
$new_length = $range_end - $range + 1;
}
if ($file['attachment_type'] != 3 && empty($showThumb) && $range === 0)
$smcFunc['db_query']('', '
UPDATE {db_prefix}attachments
SET downloads = downloads + 1
WHERE id_attach = {int:id_attach}',
array(
'id_attach' => $attachId,
)
);
header('pragma: ');
if (!isBrowser('gecko'))
header('content-transfer-encoding: binary');
header('expires: ' . gmdate('D, d M Y H:i:s', time() + 525600 * 60) . ' GMT');
header('last-modified: ' . gmdate('D, d M Y H:i:s', filemtime($file['filePath'])) . ' GMT');
header('accept-ranges: bytes');
header('connection: close');
header('etag: ' . $eTag);
if (isset($_REQUEST['image']) && !empty($file['mime_type']) && strpos($file['mime_type'], 'image/') !== 0)
unset($_REQUEST['image']);
elseif (!empty($file['mime_type']) && (isset($_REQUEST['image']) || !in_array($file['fileext'], array('jpg', 'gif', 'jpeg', 'x-ms-bmp', 'png', 'psd', 'tiff', 'iff'))))
header('content-type: ' . strtr($file['mime_type'], array('image/bmp' => 'image/x-ms-bmp')));
else
{
header('content-type: ' . (isBrowser('ie') || isBrowser('opera') ? 'application/octetstream' : 'application/octet-stream'));
if (isset($_REQUEST['image']))
unset($_REQUEST['image']);
}
$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']);
if (isset($_REQUEST['image']) || (isBrowser('is_mobile') && (strpos($file['mime_type'], 'audio/') !== 0 || strpos($file['mime_type'], 'video/') !== 0)))
$disposition = 'inline';
else
$disposition = 'attachment';
if (isBrowser('firefox'))
header('content-disposition: ' . $disposition . '; filename*=UTF-8\'\'' . rawurlencode(preg_replace_callback('~&#(\d{3,8});~', 'fixchar__callback', $utf8name)));
elseif (isBrowser('opera'))
header('content-disposition: ' . $disposition . '; filename="' . preg_replace_callback('~&#(\d{3,8});~', 'fixchar__callback', $utf8name) . '"');
elseif (isBrowser('ie'))
header('content-disposition: ' . $disposition . '; filename="' . urlencode(preg_replace_callback('~&#(\d{3,8});~', 'fixchar__callback', $utf8name)) . '"');
else
header('content-disposition: ' . $disposition . '; filename="' . $utf8name . '"');
if (!isset($_REQUEST['image']) && in_array($file['fileext'], array('gif', 'jpg', 'bmp', 'png', 'jpeg', 'tiff')))
header('cache-control: no-cache');
else
header('cache-control: max-age=' . (525600 * 60) . ', private');
if (isset($_SERVER['HTTP_RANGE']))
{
send_http_status(206);
header("content-length: $new_length");
header("content-range: bytes $range-$range_end/$size");
}
else
header("content-length: " . $size);
@set_time_limit(600);
if (isset($_SERVER['HTTP_RANGE']))
{
while (@ob_get_level() > 0)
@ob_end_clean();
$chunksize = 40 * 1024;
$bytes_sent = 0;
$fp = fopen($file['filePath'], 'rb');
fseek($fp, $range);
while (!feof($fp) && (!connection_aborted()) && ($bytes_sent < $new_length))
{
$buffer = fread($fp, $chunksize);
echo($buffer);
flush();
$bytes_sent += strlen($buffer);
}
fclose($fp);
}
elseif ($size > 4194304)
{
while (@ob_get_level() > 0)
@ob_end_clean();
$fp = fopen($file['filePath'], 'rb');
while (!feof($fp))
{
echo fread($fp, 8192);
flush();
}
fclose($fp);
}
elseif (@readfile($file['filePath']) === null)
echo file_get_contents($file['filePath']);
die();
}
?>