From 8b73bd28d81b4fd08a44ed6cc46ebedcab65f0b2 Mon Sep 17 00:00:00 2001 From: Andrew Dolgov Date: Sun, 8 Oct 2017 17:10:05 +0300 Subject: [PATCH] remove apache-specific x-sendfile stuff implement a hook (HOOK_SEND_LOCAL_FILE) which plugins may use to send files via httpd-specific implementation to increase performance typically on larger files --- classes/handler/public.php | 21 +++---------------- classes/pluginhost.php | 1 + include/functions.php | 30 +++++++++++++++++++++++++++ plugins/af_zz_imgproxy/init.php | 6 +----- plugins/cache_starred_images/init.php | 18 +--------------- 5 files changed, 36 insertions(+), 40 deletions(-) diff --git a/classes/handler/public.php b/classes/handler/public.php index 7282adfd..317bc64d 100644 --- a/classes/handler/public.php +++ b/classes/handler/public.php @@ -969,24 +969,9 @@ class Handler_Public extends Handler { if (file_exists($filename)) { header("Content-Disposition: inline; filename=\"$hash\""); - $mimetype = mime_content_type($filename); - - /* See if we can use X-Sendfile */ - $xsendfile = false; - if (function_exists('apache_get_modules') && - array_search('mod_xsendfile', apache_get_modules())) - $xsendfile = true; - - if ($xsendfile) { - header("X-Sendfile: $filename"); - header("Content-type: $mimetype"); - header('Content-Disposition: inline; filename="' . basename($filename) . '"'); - } else { - header("Content-type: $mimetype"); - $stamp = gmdate("D, d M Y H:i:s", filemtime($filename)). " GMT"; - header("Last-Modified: $stamp", true); - readfile($filename); - } + + send_local_file($filename); + } else { header($_SERVER["SERVER_PROTOCOL"]." 404 Not Found"); echo "File not found."; diff --git a/classes/pluginhost.php b/classes/pluginhost.php index 571c30fb..533e7ee9 100644 --- a/classes/pluginhost.php +++ b/classes/pluginhost.php @@ -55,6 +55,7 @@ class PluginHost { const HOOK_FORMAT_ARTICLE = 34; const HOOK_FORMAT_ARTICLE_CDM = 35; const HOOK_FEED_BASIC_INFO = 36; + const HOOK_SEND_LOCAL_FILE = 37; const KIND_ALL = 1; const KIND_SYSTEM = 2; diff --git a/include/functions.php b/include/functions.php index 20345474..392042b9 100644 --- a/include/functions.php +++ b/include/functions.php @@ -2514,3 +2514,33 @@ } } + /* this is essentially a wrapper for readfile() which allows plugins to hook + output with httpd-specific "fast" implementation i.e. X-Sendfile or whatever else + + hook function should return true if request was handled (or at least attempted to) + + note that this can be called without user context so the plugin to handle this + should be loaded systemwide in config.php */ + function send_local_file($filename) { + if (file_exists($filename)) { + $tmppluginhost = new PluginHost(); + + $tmppluginhost->load(PLUGINS, PluginHost::KIND_SYSTEM); + $tmppluginhost->load_data(); + + foreach ($tmppluginhost->get_hooks(PluginHost::HOOK_SEND_LOCAL_FILE) as $plugin) { + if ($plugin->hook_send_local_file($filename)) return true; + } + + $mimetype = mime_content_type($filename); + header("Content-type: $mimetype"); + + $stamp = gmdate("D, d M Y H:i:s", filemtime($filename)) . " GMT"; + header("Last-Modified: $stamp", true); + + return readfile($filename); + } else { + return false; + } + } + diff --git a/plugins/af_zz_imgproxy/init.php b/plugins/af_zz_imgproxy/init.php index 41fec4ac..4cfca418 100644 --- a/plugins/af_zz_imgproxy/init.php +++ b/plugins/af_zz_imgproxy/init.php @@ -55,13 +55,9 @@ class Af_Zz_ImgProxy extends Plugin { header("Content-Disposition: inline; filename=\"".basename($local_filename)."\""); if (file_exists($local_filename)) { - $mimetype = mime_content_type($local_filename); - header("Content-type: $mimetype"); - $stamp = gmdate("D, d M Y H:i:s", filemtime($local_filename)). " GMT"; - header("Last-Modified: $stamp", true); + send_local_file($local_filename); - readfile($local_filename); } else { $data = fetch_file_contents(array("url" => $url)); diff --git a/plugins/cache_starred_images/init.php b/plugins/cache_starred_images/init.php index 527e088d..82e7d1fb 100644 --- a/plugins/cache_starred_images/init.php +++ b/plugins/cache_starred_images/init.php @@ -66,27 +66,11 @@ class Cache_Starred_Images extends Plugin implements IHandler { if ($hash) { $filename = $this->cache_dir . "/" . basename($hash); - $is_video = strpos($filename, ".mp4") !== FALSE; if (file_exists($filename)) { header("Content-Disposition: attachment; filename=\"$hash\""); - /* See if we can use X-Sendfile */ - $xsendfile = false; - if (function_exists('apache_get_modules') && - array_search('mod_xsendfile', apache_get_modules())) - $xsendfile = true; - - if ($xsendfile) { - header("X-Sendfile: $filename"); - header("Content-type: application/octet-stream"); - header('Content-Disposition: attachment; filename="' . basename($filename) . '"'); - } else { - header("Content-type: " . ($is_video ? "video/mp4" : "image/png")); - $stamp = gmdate("D, d M Y H:i:s", filemtime($filename)). " GMT"; - header("Last-Modified: $stamp", true); - readfile($filename); - } + send_local_file($filename); } else { header($_SERVER["SERVER_PROTOCOL"]." 404 Not Found"); echo "File not found."; -- 2.39.2