From 4ddd5dc8c078a61238a874278cf81e0040adf689 Mon Sep 17 00:00:00 2001 From: David Lee Lambert Date: Sun, 10 Jul 2005 02:22:21 +0000 Subject: [PATCH] Send last modified information for images so the browser can use the cached version instead of re-downloading images each page refresh. --- appimage.php | 63 +++++++++++++++++++++++++++++++++++++++++++++--- include/incl.php | 19 +++++++++++++++ 2 files changed, 79 insertions(+), 3 deletions(-) diff --git a/appimage.php b/appimage.php index 4962836..bf441b5 100644 --- a/appimage.php +++ b/appimage.php @@ -6,14 +6,71 @@ include("path.php"); require(BASE."include/"."incl.php"); require(BASE."include/"."screenshot.php"); + + /* an image doesn't have a link, so a cookie makes no sense */ +header("Set-Cookie: "); +header("Pragma: "); + if(!$_SESSION['current']->hasPriv("admin") && $_REQUEST['queued']) { - errorpage("Insufficient privileges."); - exit; + errorpage("Insufficient privileges."); + exit; +} +if ($_REQUEST['REQUEST_METHOD']='HEAD') +{ + /* WARNING! optimization of logic in include/screenshots.php */ + if (sscanf($_REQUEST['id'],"%d", &$iId) < 1) { + errorpage("Bad parameter"); + exit; + } + $sQuery = "SELECT id FROM appData + WHERE id = ".$iId." + AND type = 'image' LIMIT 1"; + if (!($hResult = query_appdb($sQuery) && + $fImage = fopen($_SERVER['DOCUMENT_ROOT']."/data/screenshots/".$iId))) + { + header("404 No such image"); + exit; + } + $iModTime = fstat($fImage)['mtime']; + $sMagic = fread($fImage,8); + fclose($fImage); + if (strcmp("\x89PNG\r\n\x1A\n",$sMagic)==0) + { + header("Content-Type: image/png"); + } else if (preg_match("^\xFF\xD8..(JFIF|Exif)",$sMagic)) { + header("Content-Type: image/jpeg"); + } else { + header("500 Bad image format"); + exit; + } + header("Cache-Control: public"); + header("Expires: "); + header("Last-Modified: ".fHttpDate($iModTime)); + exit; } $oScreenshot = new screenshot($_REQUEST['id'],$_REQUEST['queued']); + + /* at this point, we know that .../screenshots/$id and + * .../screenshots/thumbnails/$id both exist; normally + * they would both be created at the same time. */ +$iModTime = stat($_SERVER['DOCUMENT_ROOT'] + ."/data/screenshots/".$_REQUEST['id'])['mtime']; + +header("Cache-Control: public"); +header("Expires: "); + +if (isset($_SERVER['HTTP_IF_MODIFIED_SINCE']) && + $iModTime == pHttpDate($_SERVER['HTTP_IF_MODIFIED_SINCE'])) { + header("HTTP/1.0 304 Not Modified"); + exit; +} + +header("Last-Modified: ".fHttpDate($iModTime)); + if(!$_REQUEST['thumbnail']) $oScreenshot->oScreenshotImage->output_to_browser(1); else $oScreenshot->oThumbnailImage->output_to_browser(1); -?> + +?> \ No newline at end of file diff --git a/include/incl.php b/include/incl.php index d351663..68138db 100644 --- a/include/incl.php +++ b/include/incl.php @@ -147,6 +147,7 @@ function errorpage($text = null, $message = null) if (!$text) { $text = "You must be logged in to perform that operation."; } + header("HTTP/1.0 404 Object not found or user is not logged in"); apidb_header("Oops"); echo "
$text
\n"; echo "

$message

\n"; @@ -176,6 +177,24 @@ function redirectref($url = null) redirect($url); } +/** + * format a date as required for HTTP by RFC 2068 sec 3.3.1 + */ +function fHttpDate($iDate) { + return gmdate("D, d M Y H:i:s",$iDate)." GMT"; +} + +/** + * parse all the date formats required by HTTP 1.1 into PHP time values + */ +function pHttpDate($sDate) { + $iDate = strtotime($sDate); + if ($iDate != -1) return $iDate; + /* the RFC also requires asctime() format... */ + $aTs = strptime($sDate,"%a %b %e %H:%M:%S %Y"); + $iDate = gmmktime($aTs[2],$aTs[1],$aTs[0],$aTs[4],$aTs[3],$aTs[5],0); + return $iDate; +} /** * msgs will be displayed on the Next page view of the same user