Пример #1
0
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);
}
Пример #2
0
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']);
    }
}