function AdkDownloadFile() { global $modSettings, $txt, $context, $smcFunc, $user_info, $boarddir, $adkFolder; if (!empty($_REQUEST['id'])) { $id = (int) $_REQUEST['id']; } else { fatal_lang_error('adkfatal_require_id_file', false); } $sql = $smcFunc['db_query']('', ' SELECT a.id_file, a.id_attach, a.filename, a.orginalfilename, d.id_cat, d.id_file, d.id_member, d.approved FROM {db_prefix}adk_down_attachs AS a, {db_prefix}adk_down_file AS d INNER JOIN {db_prefix}members AS m ON (m.id_member = d.id_member) WHERE id_attach = {int:a} AND a.id_file = d.id_file', array('a' => $id)); $row = $smcFunc['db_fetch_assoc']($sql); //Empty file? if ($smcFunc['db_num_rows']($sql) == 0) { fatal_lang_error('adkfatal_require_id_file', false); } $smcFunc['db_free_result']($sql); if ($row['approved'] == 0 && $user_info['id'] != $row['id_member'] && !allowedTo('adk_downloads_manage')) { fatal_lang_error('adkfatal_this_download_not_approved', false); } verifyCatPermissions('view', $row['id_cat']); $last = time(); $smcFunc['db_query']('', "UPDATE {db_prefix}adk_down_file\n\t\tSET totaldownloads = totaldownloads + 1, lastdownload = {int:l} WHERE id_file = {int:id} LIMIT 1", array('id' => $row['id_file'], 'l' => $last)); $real_filename = $row['orginalfilename']; $filename = $adkFolder['eds'] . '/' . $row['filename']; $ext = explode('.', $real_filename); $file_ext = $ext[count($ext) - 1]; // This is done to clear any output that was made before now. (would use ob_clean(), but that's PHP 4.2.0+...) ob_end_clean(); if (!empty($modSettings['enableCompressedOutput']) && @version_compare(PHP_VERSION, '4.2.0') >= 0 && @filesize($filename) <= 4194304 && in_array($file_ext, array('txt', 'html', 'htm', 'js', 'doc', 'pdf', 'docx', 'rtf', 'css', 'php', 'log', 'xml', 'sql', 'c', 'java'))) { @ob_start('ob_gzhandler'); } else { ob_start(); header('Content-Encoding: none'); } // No point in a nicer message, because this is supposed to be an attachment anyway... if (!file_exists($filename)) { adkLanguage('Errors'); header('HTTP/1.0 404 ' . $txt['attachment_not_found']); header('Content-Type: text/plain; charset=' . (empty($context['character_set']) ? 'ISO-8859-1' : $context['character_set'])); // We need to die like this *before* we send any anti-caching headers as below. die('404 - ' . $txt['attachment_not_found']); } // If it hasn't been modified since the last time this attachement was retrieved, there's no need to display it again. if (!empty($_SERVER['HTTP_IF_MODIFIED_SINCE'])) { list($modified_since) = explode(';', $_SERVER['HTTP_IF_MODIFIED_SINCE']); if (strtotime($modified_since) >= filemtime($filename)) { ob_end_clean(); // Answer the question - no, it hasn't been modified ;). header('HTTP/1.1 304 Not Modified'); exit; } } // Check whether the ETag was sent back, and cache based on that... $eTag = '"' . substr($_REQUEST['id'] . $real_filename . filemtime($filename), 0, 64) . '"'; if (!empty($_SERVER['HTTP_IF_NONE_MATCH']) && strpos($_SERVER['HTTP_IF_NONE_MATCH'], $eTag) !== false) { ob_end_clean(); header('HTTP/1.1 304 Not Modified'); exit; } // Send the attachment headers. header('Pragma: '); if (!$context['browser']['is_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($filename)) . ' GMT'); header('Accept-Ranges: bytes'); header('Connection: close'); header('ETag: ' . $eTag); // IE 6 just doesn't play nice. As dirty as this seems, it works. if ($context['browser']['is_ie6'] && isset($_REQUEST['image'])) { unset($_REQUEST['image']); } elseif (isset($_REQUEST['image']) && !empty($mime_type) && strpos($mime_type, 'image/') !== 0) { unset($_REQUEST['image']); } elseif (!empty($mime_type) && (isset($_REQUEST['image']) || !in_array($file_ext, array('jpg', 'gif', 'jpeg', 'x-ms-bmp', 'png', 'psd', 'tiff', 'iff')))) { header('Content-Type: ' . strtr($mime_type, array('image/bmp' => 'image/x-ms-bmp'))); } else { header('Content-Type: ' . ($context['browser']['is_ie'] || $context['browser']['is_opera'] ? 'application/octetstream' : 'application/octet-stream')); if (isset($_REQUEST['image'])) { unset($_REQUEST['image']); } } // Convert the file to UTF-8, cuz most browsers dig that. $utf8name = !$context['utf8'] && function_exists('iconv') ? iconv($context['character_set'], 'UTF-8', $real_filename) : (!$context['utf8'] && function_exists('mb_convert_encoding') ? mb_convert_encoding($real_filename, 'UTF-8', $context['character_set']) : $real_filename); $fixchar = create_function('$n', ' if ($n < 32) return \'\'; elseif ($n < 128) return chr($n); elseif ($n < 2048) return chr(192 | $n >> 6) . chr(128 | $n & 63); elseif ($n < 65536) return chr(224 | $n >> 12) . chr(128 | $n >> 6 & 63) . chr(128 | $n & 63); else return chr(240 | $n >> 18) . chr(128 | $n >> 12 & 63) . chr(128 | $n >> 6 & 63) . chr(128 | $n & 63);'); $disposition = !isset($_REQUEST['image']) ? 'attachment' : 'inline'; // Different browsers like different standards... if ($context['browser']['is_firefox']) { header('Content-Disposition: ' . $disposition . '; filename*=UTF-8\'\'' . rawurlencode(preg_replace_callback('~&#(\\d{3,8});~', 'fixchar__callback', $utf8name))); } elseif ($context['browser']['is_opera']) { header('Content-Disposition: ' . $disposition . '; filename="' . preg_replace_callback('~&#(\\d{3,8});~', 'fixchar__callback', $utf8name) . '"'); } elseif ($context['browser']['is_ie']) { header('Content-Disposition: ' . $disposition . '; filename="' . urlencode(preg_replace_callback('~&#(\\d{3,8});~', 'fixchar__callback', $utf8name)) . '"'); } else { header('Content-Disposition: ' . $disposition . '; filename="' . $utf8name . '"'); } // If this has an "image extension" - but isn't actually an image - then ensure it isn't cached cause of silly IE. if (!isset($_REQUEST['image']) && in_array($file_ext, array('gif', 'jpg', 'bmp', 'png', 'jpeg', 'tiff'))) { header('Cache-Control: no-cache'); } else { header('Cache-Control: max-age=' . 525600 * 60 . ', private'); } if (empty($modSettings['enableCompressedOutput']) || filesize($filename) > 4194304) { header('Content-Length: ' . filesize($filename)); } // Try to buy some time... @set_time_limit(600); // Recode line endings for text files, if enabled. if (!empty($modSettings['attachmentRecodeLineEndings']) && !isset($_REQUEST['image']) && in_array($file_ext, array('txt', 'css', 'htm', 'html', 'php', 'xml'))) { if (strpos($_SERVER['HTTP_USER_AGENT'], 'Windows') !== false) { $callback = create_function('$buffer', 'return preg_replace(\'~[\\r]?\\n~\', "\\r\\n", $buffer);'); } elseif (strpos($_SERVER['HTTP_USER_AGENT'], 'Mac') !== false) { $callback = create_function('$buffer', 'return preg_replace(\'~[\\r]?\\n~\', "\\r", $buffer);'); } else { $callback = create_function('$buffer', 'return preg_replace(\'~[\\r]?\\n~\', "\\n", $buffer);'); } } // Since we don't do output compression for files this large... if (filesize($filename) > 4194304) { // Forcibly end any output buffering going on. if (function_exists('ob_get_level')) { while (@ob_get_level() > 0) { @ob_end_clean(); } } else { @ob_end_clean(); @ob_end_clean(); @ob_end_clean(); } $fp = fopen($filename, 'rb'); while (!feof($fp)) { if (isset($callback)) { echo $callback(fread($fp, 8192)); } else { echo fread($fp, 8192); } flush(); } fclose($fp); } elseif (isset($callback) || @readfile($filename) == null) { echo isset($callback) ? $callback(file_get_contents($filename)) : file_get_contents($filename); } obExit(false); }
function verifyCatPermissions($permission, $cat, $return = false) { global $user_info, $smcFunc; //Load Cat Info $sql = $smcFunc['db_query']('', ' SELECT groups_can_view, groups_can_add, id_parent FROM {db_prefix}adk_down_cat WHERE id_cat = {int:cat}', array('cat' => $cat)); $row = $smcFunc['db_fetch_assoc']($sql); $smcFunc['db_free_result']($sql); //Check what permission we're trying to verify if ($permission == 'view') { $y = $row['groups_can_view']; } else { $y = $row['groups_can_add']; } $x = !empty($y) || $y == "0" ? explode(',', $y) : array(); $valid_permission = false; //Check if this user has not permiossion if (!empty($x)) { foreach ($x as $i => $v) { if (in_array($v, $user_info['groups'])) { $valid_permission = true; } } //Guest if ($user_info['is_guest'] && in_array(-1, $x)) { $valid_permission = true; } } if ($user_info['is_admin'] || allowedTo('adk_downloads_manage')) { $valid_permission = true; } //.... lier if ($return) { return $valid_permission; } elseif (!$valid_permission) { fatal_lang_error('adkfatal_cannot_view', false); } //Check if permissions of previous categories if ($row['id_parent'] != 0) { verifyCatPermissions($permission, $row['id_parent']); } }