<?php
// Modified-Stempel (der aktuellen Datei) ermitteln & Last-Modified-Header senden
$aModifiedStamps=http_modified(TRUE);
// Modified-Status abgleichen, 304-Header senden & Script beenden
$bModifiedState=http_not_modified($aModifiedStamps['Last-Modified']);
// Dieser Script-Teil wird nur ausgefuehrt, wenn der Browser neue Daten braucht
header('Content-Type: text/html');
echo '<title>Conditional Request - Last-Modified-Header</title>';
echo 'Last-Modified: '.gmdate('D, d M Y H:i:s',$aModifiedStamps['Last-Modified']).' GMT'.'<br>';
echo 'Actual Time: '.date('D, d M Y H:i:s').'<br>';
// ===========================================================================
/**
* Ermitteln und ggf. Senden eines Last-Modified- und/oder ETag-Headers.
*
* <i>array http_modified(mixed time [, string data [, bool header_flag]])</i>
*
* @version 080807
* @since 060201
* @author Cybaer <cybaer@binon.net>
* @copyright Copyright (c) 2006 Cybaer
*
* @category HTTP_LIBRARY
* @access public
*
* @param mixed $mLastModified Ein Timestamp (int), ein Datum oder Dateiname (string) oder ein Flag (bool)
* @param string $sETag Eine fertige Checksumme (Laenge <= 34 Bytes) oder Daten, ueber die ein MD5-Hash gebildet wird (Laenge > 34 Bytes)
* @param bool $bSendHeader Wenn HTTP-Header gesendet werden soll TRUE (Default), sonst FALSE
* @return array Assoz. Array mit den ermittelten Werten 'Last-Modified' und 'ETag'
* Example: <code><?php
* $modifiedStamps=http_modified(TRUE); // Last-Modified-Header mit Timestamp der angeforderten Resource
* $modifiedStamps=http_modified(__FILE__); // Last-Modified-Header mit Timestamp des aktuellen Scripts
* $modifiedStamps=http_modified('now'); // Last-Modified-Header mit aktuellem Timestamp
* $modifiedStamps=http_modified(time()); // Last-Modified-Header mit aktuellem Timestamp
* $modifiedStamps=http_modified(FALSE,'5415d-cb5-b780780'); // ETag-Header mit vorgegebener Checksumme "5415d-cb5-b780780"
* $modifiedStamps=http_modified(FALSE,'12345678901234567890123456789012345'); // ETag-Header mit MD5-Hash "cbe8cefc44dad51f7257da79c686df97"
* $modifiedStamps=http_modified(TRUE,NULL,FALSE); // Timestamp der angeforderten Resource ermitteln, aber keinen Header senden
* ?></code>
*/
function http_modified($mLastModified=NULL,$sETag=NULL,$bSendHeader=TRUE) {
$bSendHeader=($bSendHeader && !headers_sent());
// Last-Modified-Angabe vorhanden (Angabe: z.B. Timestamp)
if($mLastModified!==NULL && $mLastModified!==FALSE) {
if($mLastModified===TRUE) {
// Angabe: TRUE -> Timestamp der angeforderten Resource bzw. (falls keine passende Datei vorhanden) des ausfuehrenden Scripts
$file=$_SERVER['DOCUMENT_ROOT'].((!empty($_SERVER['REQUEST_URI']) && file_exists($_SERVER['DOCUMENT_ROOT'].$_SERVER['REQUEST_URI']))?$_SERVER['REQUEST_URI']:$_SERVER['PHP_SELF']);
$mLastModified=(file_exists($file) && @filemtime($file))?filemtime($file):time();
} else if(is_string($mLastModified)) {
// Angabe: String -> Dateiname oder Datum (Dateiname: PHP 4 -> FALSE, PHP 5 -> -1)
if(($iTimestamp=strtotime($mLastModified))>0) {
// String mit Datum im englischen Format ("now"/"10 December 2005"/"-1 week 2 days 4 hours 2 seconds"/"last Monday"/...)
$mLastModified=$iTimestamp;
} else if(realpath($mLastModified)) {
// String mit Dateiname
$mLastModified=filemtime(realpath($mLastModified));
}
}
// Ausgabe des Headers
if($bSendHeader) { header('Last-Modified: '.gmdate('D, d M Y H:i:s',$mLastModified).' GMT'); }
}
// ETag-Angabe vorhanden
if($sETag) {
// Wenn Kennung groesser als 34 Bytes:
if(strlen($sETag)>34) {
// MD5-Hash ermitteln und verwenden
$sETag=md5($sETag);
}
// Ggf. uebliche Anfuehrungszeichen ergaenzen
if($sETag[0]!='"') { $sETag='"'.$sETag.'"'; }
// Ausgabe des Headers
if($bSendHeader) { header('ETag: '.$sETag); }
}
// Rueckgabe der verwendeten Werte
return array('Last-Modified' => $mLastModified, 'ETag' => $sETag);
}
// ---------------------------------------------------------------------------
/**
* Ueberpruefung auf NOT_MODIFIED-Status und ggf. HTTP-Status "304" senden.
*
* <i>bool http_not_modified(mixed time [, string checksum [, bool exit_flag [, bool header_flag]]])</i>
*
* @version 060516
* @since 060201
* @author Cybaer <cybaer@binon.net>
* @copyright Copyright (c) 2006 Cybaer
*
* @category HTTP_LIBRARY
* @access public
*
* @param mixed $mLastModified Ein Timestamp (int) oder ein Datum (string)
* @param string $sETag Ein ETag-Wert
* @param bool $bExitScript Wenn Script bei Not-Modified beendet werden soll TRUE (Default), sonst FALSE
* @param bool $bSendHeader Wenn HTTP-Header gesendet werden soll TRUE (Default), sonst FALSE
* @return bool Wenn Datei nicht veraendert wurde TRUE, sonst FALSE
* Example: <code><?php
* http_not_modified($timestamp); // Sendet einen 304-Header und bricht das Script ab, wenn $ts einen aelteren Timestamp beeinhaltet, als im Request-Header angefragt
* http_not_modified("last Monday"); // Sendet einen 304-Header und bricht das Script ab, wenn Timestamp im Request-Header frischer ist als "letzter Montag"
* http_not_modified("now"); // Sendet keinen 304-Header und faehrt mit dem Script fort (Timestamp ist ueblicherweise aktueller, als der im Request-Header angefragte)
* http_not_modified(NULL,'"5415d-cb5-b780780"'); // Sendet einen 304-Header und bricht das Script ab, wenn Checksumme mit der im Request-Header uebereinstimmt
* http_not_modified(NULL,'"5415d-cb5-b780780"',FALSE); // Sendet einen 304-Header, wenn Checksumme mit der im Request-Header uebereinstimmt - das Script wird nicht abgebrochen
* $notModified=http_not_modified(NULL,'"5415d-cb5-b780780"',FALSE,FALSE); // Wenn Checksumme mit der im Request-Header uebereinstimmt, ist $notModified TRUE - weder wird das Script abgebrochen, noch wird ein Header gesendet
* ?></code>
*/
function http_not_modified($mLastModified=NULL,$sETag=NULL,$bExitScript=TRUE,$bSendHeader=TRUE) {
$bSendHeader=($bSendHeader && !headers_sent());
// Statusvariablen initialisieren
$bLastModifiedChanged=NULL;
$bETagChanged=NULL;
// Last-Modified auswerten
if($mLastModified && !empty($_SERVER['HTTP_IF_MODIFIED_SINCE'])) {
// Ggf. Pruefdatum-String in Timestamp umwandeln
if(is_string($mLastModified)) { $mLastModified=(($iTimestamp=strtotime($mLastModified))===-1)?time():$iTimestamp; }
// Changed-Status ist wahr, wenn Originalzeit aelter als Pruefzeit ist
$bLastModifiedChanged=(strtotime($_SERVER['HTTP_IF_MODIFIED_SINCE'])>=$mLastModified)?FALSE:TRUE;
}
// ETag auswerten
if($sETag && !empty($_SERVER['HTTP_IF_NONE_MATCH'])) {
// Changed-Status ist wahr, wenn Checksummen unterschiedlich sind
$bETagChanged=($_SERVER['HTTP_IF_NONE_MATCH']==(get_magic_quotes_gpc())?addslashes($sETag):$sETag)?FALSE:TRUE;
}
// Status zusammenfassen
$bNotModified=!($bLastModifiedChanged || $bETagChanged);
// Wenn Aenderungsstatus und Response-Header erwuenscht
if($bNotModified && $bSendHeader) {
header('Status: 304 Not Modified');
header($_SERVER['SERVER_PROTOCOL'].' 304 Not Modified');
header('Connection: close');
// Auf Wunsch Script beenden
if($bExitScript) { die(); }
}
// NOT-MODIFIED-Status zurueckgeben
return $bNotModified;
}
?>