Ejemplo n.º 1
0
/**
 * Send javascript file content with as much caching as possible
 * @param string $jspath
 * @param string $etag
 * @param string $filename
 */
function js_send_cached($jspath, $etag, $filename = 'javascript.php') {
    require(__DIR__ . '/xsendfilelib.php');

    $lifetime = 60*60*24*60; // 60 days only - the revision may get incremented quite often

    header('Etag: "'.$etag.'"');
    header('Content-Disposition: inline; filename="'.$filename.'"');
    header('Last-Modified: '. gmdate('D, d M Y H:i:s', filemtime($jspath)) .' GMT');
    header('Expires: '. gmdate('D, d M Y H:i:s', time() + $lifetime) .' GMT');
    header('Pragma: ');
    header('Cache-Control: public, max-age='.$lifetime);
    header('Accept-Ranges: none');
    header('Content-Type: application/javascript; charset=utf-8');

    if (xsendfile($jspath)) {
        die;
    }

    if (!min_enable_zlib_compression()) {
        header('Content-Length: '.filesize($jspath));
    }

    readfile($jspath);
    die;
}
Ejemplo n.º 2
0
/**
 * Enhanced readfile() with optional acceleration.
 * @param string|stored_file $file
 * @param string $mimetype
 * @param bool $accelerate
 * @return void
 */
function readfile_accel($file, $mimetype, $accelerate)
{
    global $CFG;
    if ($mimetype === 'text/plain') {
        // there is no encoding specified in text files, we need something consistent
        header('Content-Type: text/plain; charset=utf-8');
    } else {
        header('Content-Type: ' . $mimetype);
    }
    $lastmodified = is_object($file) ? $file->get_timemodified() : filemtime($file);
    header('Last-Modified: ' . gmdate('D, d M Y H:i:s', $lastmodified) . ' GMT');
    if (is_object($file)) {
        header('Etag: "' . $file->get_contenthash() . '"');
        if (isset($_SERVER['HTTP_IF_NONE_MATCH']) and trim($_SERVER['HTTP_IF_NONE_MATCH'], '"') === $file->get_contenthash()) {
            header('HTTP/1.1 304 Not Modified');
            return;
        }
    }
    // if etag present for stored file rely on it exclusively
    if (!empty($_SERVER['HTTP_IF_MODIFIED_SINCE']) and (empty($_SERVER['HTTP_IF_NONE_MATCH']) or !is_object($file))) {
        // get unixtime of request header; clip extra junk off first
        $since = strtotime(preg_replace('/;.*$/', '', $_SERVER["HTTP_IF_MODIFIED_SINCE"]));
        if ($since && $since >= $lastmodified) {
            header('HTTP/1.1 304 Not Modified');
            return;
        }
    }
    if ($accelerate and !empty($CFG->xsendfile)) {
        if (empty($CFG->disablebyteserving) and $mimetype !== 'text/plain') {
            header('Accept-Ranges: bytes');
        } else {
            header('Accept-Ranges: none');
        }
        if (is_object($file)) {
            $fs = get_file_storage();
            if ($fs->xsendfile($file->get_contenthash())) {
                return;
            }
        } else {
            require_once "{$CFG->libdir}/xsendfilelib.php";
            if (xsendfile($file)) {
                return;
            }
        }
    }
    $filesize = is_object($file) ? $file->get_filesize() : filesize($file);
    header('Last-Modified: ' . gmdate('D, d M Y H:i:s', $lastmodified) . ' GMT');
    if ($accelerate and empty($CFG->disablebyteserving) and $mimetype !== 'text/plain') {
        header('Accept-Ranges: bytes');
        if (!empty($_SERVER['HTTP_RANGE']) and strpos($_SERVER['HTTP_RANGE'], 'bytes=') !== FALSE) {
            // byteserving stuff - for acrobat reader and download accelerators
            // see: http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.35
            // inspired by: http://www.coneural.org/florian/papers/04_byteserving.php
            $ranges = false;
            if (preg_match_all('/(\\d*)-(\\d*)/', $_SERVER['HTTP_RANGE'], $ranges, PREG_SET_ORDER)) {
                foreach ($ranges as $key => $value) {
                    if ($ranges[$key][1] == '') {
                        //suffix case
                        $ranges[$key][1] = $filesize - $ranges[$key][2];
                        $ranges[$key][2] = $filesize - 1;
                    } else {
                        if ($ranges[$key][2] == '' || $ranges[$key][2] > $filesize - 1) {
                            //fix range length
                            $ranges[$key][2] = $filesize - 1;
                        }
                    }
                    if ($ranges[$key][2] != '' && $ranges[$key][2] < $ranges[$key][1]) {
                        //invalid byte-range ==> ignore header
                        $ranges = false;
                        break;
                    }
                    //prepare multipart header
                    $ranges[$key][0] = "\r\n--" . BYTESERVING_BOUNDARY . "\r\nContent-Type: {$mimetype}\r\n";
                    $ranges[$key][0] .= "Content-Range: bytes {$ranges[$key][1]}-{$ranges[$key][2]}/{$filesize}\r\n\r\n";
                }
            } else {
                $ranges = false;
            }
            if ($ranges) {
                if (is_object($file)) {
                    $handle = $file->get_content_file_handle();
                } else {
                    $handle = fopen($file, 'rb');
                }
                byteserving_send_file($handle, $mimetype, $ranges, $filesize);
            }
        }
    } else {
        // Do not byteserve
        header('Accept-Ranges: none');
    }
    header('Content-Length: ' . $filesize);
    if ($filesize > 10000000) {
        // for large files try to flush and close all buffers to conserve memory
        while (@ob_get_level()) {
            if (!@ob_end_flush()) {
                break;
            }
        }
    }
    // send the whole file content
    if (is_object($file)) {
        $file->readfile();
    } else {
        readfile_allow_large($file, $filesize);
    }
}
Ejemplo n.º 3
0
function yui_image_cached($imagepath, $imagename, $mimetype, $etag) {
    global $CFG;
    require("$CFG->dirroot/lib/xsendfilelib.php");

    $lifetime = 60*60*24*360; // 1 year, we do not change YUI versions often, there are a few custom yui modules

    header('Content-Disposition: inline; filename="'.$imagename.'"');
    header('Last-Modified: '. gmdate('D, d M Y H:i:s', filemtime($imagepath)) .' GMT');
    header('Expires: '. gmdate('D, d M Y H:i:s', time() + $lifetime) .' GMT');
    header('Pragma: ');
    header('Cache-Control: public, max-age=315360000, no-transform');
    header('Accept-Ranges: none');
    header('Content-Type: '.$mimetype);
    header('Content-Length: '.filesize($imagepath));
    header('Etag: "'.$etag.'"');

    if (xsendfile($imagepath)) {
        die;
    }

    // no need to gzip already compressed images ;-)

    readfile($imagepath);
    die;
}
Ejemplo n.º 4
0
 /**
  * Serve file content using X-Sendfile header.
  * Please make sure that all headers are already sent
  * and the all access control checks passed.
  *
  * @param string $contenthash sah1 hash of the file content to be served
  * @return bool success
  */
 public function xsendfile($contenthash)
 {
     global $CFG;
     require_once "{$CFG->libdir}/xsendfilelib.php";
     $hashpath = $this->path_from_hash($contenthash);
     return xsendfile("{$hashpath}/{$contenthash}");
 }
Ejemplo n.º 5
0
    header('Etag: '.$etag);
    die;
}

require_once("$CFG->dirroot/lib/xsendfilelib.php");

header('Etag: '.$etag);
header('Content-Disposition: inline; filename="'.$filename.'"');
header('Last-Modified: '. gmdate('D, d M Y H:i:s', filemtime($file)) .' GMT');
header('Expires: '. gmdate('D, d M Y H:i:s', time() + $lifetime) .' GMT');
header('Pragma: ');
header('Cache-Control: public, max-age='.$lifetime);
header('Accept-Ranges: none');
header('Content-Type: '.$mimetype);

if (xsendfile($file)) {
    die;
}

if ($mimetype === 'text/css' or $mimetype === 'application/javascript') {
    if (!min_enable_zlib_compression()) {
        header('Content-Length: '.filesize($file));
    }
} else {
    // No need to compress images.
    header('Content-Length: '.filesize($file));
}

readfile($file);
die;
Ejemplo n.º 6
0
function send_cached_font($fontpath, $etag, $font, $mimetype)
{
    global $CFG;
    require "{$CFG->dirroot}/lib/xsendfilelib.php";
    $lifetime = 60 * 60 * 24 * 60;
    // 60 days only - the revision may get incremented quite often.
    header('Etag: "' . $etag . '"');
    header('Content-Disposition: inline; filename="' . $font . '"');
    header('Last-Modified: ' . gmdate('D, d M Y H:i:s', filemtime($fontpath)) . ' GMT');
    header('Expires: ' . gmdate('D, d M Y H:i:s', time() + $lifetime) . ' GMT');
    header('Pragma: ');
    header('Cache-Control: public, max-age=' . $lifetime);
    header('Accept-Ranges: none');
    header('Content-Type: ' . $mimetype);
    header('Content-Length: ' . filesize($fontpath));
    if (xsendfile($fontpath)) {
        die;
    }
    // No need to gzip already compressed fonts.
    readfile($fontpath);
    die;
}
Ejemplo n.º 7
0
function send_cached_image($imagepath, $etag)
{
    global $CFG;
    require "{$CFG->dirroot}/lib/xsendfilelib.php";
    $lifetime = 60 * 60 * 24 * 60;
    // 60 days only - the revision may get incremented quite often
    $pathinfo = pathinfo($imagepath);
    $imagename = $pathinfo['filename'] . '.' . $pathinfo['extension'];
    $mimetype = get_contenttype_from_ext($pathinfo['extension']);
    header('Etag: "' . $etag . '"');
    header('Content-Disposition: inline; filename="' . $imagename . '"');
    header('Last-Modified: ' . gmdate('D, d M Y H:i:s', filemtime($imagepath)) . ' GMT');
    header('Expires: ' . gmdate('D, d M Y H:i:s', time() + $lifetime) . ' GMT');
    header('Pragma: ');
    header('Cache-Control: public, max-age=' . $lifetime);
    header('Accept-Ranges: none');
    header('Content-Type: ' . $mimetype);
    header('Content-Length: ' . filesize($imagepath));
    if (xsendfile($imagepath)) {
        die;
    }
    // no need to gzip already compressed images ;-)
    readfile($imagepath);
    die;
}
Ejemplo n.º 8
0
    /**
     * Serve file content using X-Sendfile header.
     * Please make sure that all headers are already sent
     * and the all access control checks passed.
     *
     * @param string $contenthash sah1 hash of the file content to be served
     * @return bool success
     */
    public function xsendfile($contenthash) {
        global $CFG;
        require_once("$CFG->libdir/xsendfilelib.php");

        $hashpath = $this->path_from_hash($contenthash);
        return xsendfile("$hashpath/$contenthash");
    }