You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
595 lines
15 KiB
595 lines
15 KiB
<?php
|
|
|
|
/**
|
|
* Mit der Funktion printCachedPage kann ein Script/Modul seinen dynamisch
|
|
* erzeugten HTML-Inhalt cachen und als statisches HTML einbinden. Die
|
|
* erzeugten HTML-Dateien liegen unter CACHEDIR/<subclientid>/<script-path>/
|
|
* <scriptname>?md5(<request-parameter-liste>).html
|
|
*
|
|
* Es wird für jede Seite und jeden Request-Parameter-Kombination, der in
|
|
* $allowed_req_params angegeben ist, eine Seite im Cache angelegt.
|
|
*
|
|
* Parameter:
|
|
* - $auto_update: erzeugt bei Scriptaufruf eine neue Cache-Datei, wenn:
|
|
* a) die Cachedatei älter ist als die Scriptdatei oder
|
|
* b) die Cachedatei älter ist als eine per include/require eingebunden
|
|
* Scriptdatei
|
|
* - $update_interval: eine Erneuerung der Cachedatei wird vorgenommen, wenn
|
|
* die Cachedatei älter als $update_interval ist.
|
|
* - $script-file: das Script, dessen Inhalt gecached werden soll, i.d.R
|
|
* __FILE__
|
|
* - $allowed_req_params: Liste der erlaubten Request-Parameter, dient zur
|
|
* Bildung des Cachedateinamens
|
|
* - $debug: erzeugt Debug-Ausgaben
|
|
*
|
|
* Die Einbindung in ein Script erfolgt nach Einbindung per include/require
|
|
* der zusätzlich erforderlichen Bibliothen mit:
|
|
*
|
|
* if (printCachedPage($auto_update,$update_interval,__FILE__))
|
|
* return;
|
|
*
|
|
* Der mit printCachedPage erzeugte HTML-Bereich wird mit HTML-Kommentaren
|
|
* umrandet und kann so im Gesamt-Quelltext identifiziert werden.
|
|
*/
|
|
|
|
define ('MAX_CACHE_WAIT_SECS',1);
|
|
|
|
function printCachedPage (
|
|
$script_file,
|
|
$auto_update = true,
|
|
$update_interval = 86400,
|
|
$allowed_req_params = -1,
|
|
$debug = 0)
|
|
{
|
|
if (USE_SCRIPT_CACHE == 0)
|
|
return 0;
|
|
|
|
$em_parameter = "";
|
|
if (isset ($_REQUEST["em_parameter"]))
|
|
$em_parameter = $_REQUEST["em_parameter"];
|
|
if (!empty($em_parameter))
|
|
$GLOBALS["em_parameter"] = $em_parameter;
|
|
if (!empty($GLOBALS["em_parameter"]))
|
|
$em_parameter = $GLOBALS["em_parameter"];
|
|
|
|
$content = "";
|
|
if (isset($_REQUEST["NOCACHE"]))
|
|
{
|
|
if (isset($_REQUEST["PHP_SELF"]))
|
|
{
|
|
$_SERVER["PHP_SELF"]=$_REQUEST["PHP_SELF"];
|
|
|
|
// --- DEBUG OUTPUT -------
|
|
if ($debug)
|
|
echo "<br />PHP_SELF wurde gesetzt: " . $_SERVER["PHP_SELF"];
|
|
// --- END DEBUG OUTPUT ---
|
|
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
// --- DEBUG OUTPUT -------
|
|
$t1 = NULL;
|
|
|
|
if ($debug)
|
|
$t1 = getMilliSeconds ();
|
|
|
|
if ($debug)
|
|
{
|
|
echo "<br />Startzeit: ".strftime("%H:%M:%S");
|
|
echo "<br />Script-Datei: ".$script_file;
|
|
echo "<br />PHP_SELF: ".$_SERVER["PHP_SELF"];
|
|
echo "<br />Erlaubte Cache-Dateien pro Verzeichnis: " .
|
|
MAX_FILES_IN_CACHE_DIR;
|
|
}
|
|
// --- END DEBUG OUTPUT ---
|
|
|
|
$subclient_id = getSubclientIDByUrl();
|
|
|
|
$len = strlen ($_SERVER["DOCUMENT_ROOT"]);
|
|
$script_name = substr ($script_file, $len);
|
|
|
|
// --- DEBUG OUTPUT -------
|
|
if ($debug)
|
|
echo "<br>DOCUMENT ROOT: " . $_SERVER["DOCUMENT_ROOT"];
|
|
|
|
if ($debug)
|
|
echo "<br />Script-Name: $script_name";
|
|
// --- END DEBUG OUTPUT ---
|
|
|
|
$cache_file = realpath (CACHEDIR) . "/" . $subclient_id . "/" .
|
|
substr(dirname($script_name),1) . "/" . basename($script_name) . "/" .
|
|
basename($script_name,".php");
|
|
|
|
$params = "";
|
|
$query_string = "";
|
|
|
|
foreach ($_REQUEST as $key => $val)
|
|
{
|
|
if (is_array ($allowed_req_params) &&
|
|
in_array ($key,$allowed_req_params))
|
|
{
|
|
$val = urlencode (trim($val));
|
|
$key = urlencode (trim($key));
|
|
|
|
// --- DEBUG OUTPUT -------
|
|
if ($debug)
|
|
echo "<br />Hänge Request-Parameter an: _$key-$val";
|
|
// --- END DEBUG OUTPUT ---
|
|
|
|
$params .= "_". $key . "-" . $val;
|
|
$query_string .= $key . "=" . $val . "&";
|
|
}
|
|
}
|
|
|
|
if (!empty ($em_parameter))
|
|
{
|
|
$params .= "_" . $em_parameter;
|
|
$query_string .= "em_parameter=" . $em_parameter;
|
|
}
|
|
|
|
if (!empty ($params))
|
|
$cache_file = $cache_file . "_" . md5($params) . ".html";
|
|
else
|
|
$cache_file = $cache_file . ".html";
|
|
|
|
$url = getProtocol () . "://" . $_SERVER["SERVER_NAME"] . $script_name .
|
|
"?" . $query_string;
|
|
$cached_dir = dirname($cache_file);
|
|
|
|
// --- DEBUG OUTPUT -------
|
|
if ($debug)
|
|
{
|
|
echo "<br />Cache-Datei: $cache_file";
|
|
echo "<br />Script-Datei: $script_file";
|
|
echo "<br />URL: ".htmlspecialchars($url);
|
|
echo "<br />Cache Dir: $cached_dir";
|
|
}
|
|
// --- END DEBUG OUTPUT ---
|
|
|
|
if (!is_dir ($cached_dir))
|
|
{
|
|
if (!is_dir (CACHEDIR . $subclient_id))
|
|
mkdir (CACHEDIR . $subclient_id);
|
|
$cachedir = CACHEDIR . $subclient_id;
|
|
|
|
$dir_arr = explode ("/", dirname($script_name) . "/" .
|
|
basename($script_name));
|
|
|
|
foreach ($dir_arr as $dir)
|
|
{
|
|
if (!is_dir($cachedir . "/" . $dir))
|
|
{
|
|
mkdir ($cachedir. "/" . $dir);
|
|
chmod ($cachedir. "/" . $dir, 0777);
|
|
|
|
// --- DEBUG OUTPUT -------
|
|
if ($debug)
|
|
echo "<br />Erzeuge Verzeichnis: $cachedir/$dir";
|
|
// --- END DEBUG OUTPUT ---
|
|
}
|
|
$cachedir .= "/" . $dir;
|
|
}
|
|
}
|
|
|
|
$is_updated = 0;
|
|
if (!file_exists ($cache_file))
|
|
{
|
|
$file_count = count (scandir ($cached_dir)) - 2;
|
|
|
|
// --- DEBUG OUTPUT -------
|
|
if ($debug)
|
|
echo "<br />Es sind $file_count im Cacheverzeichnis. " .
|
|
"Erlaubt sind " . MAX_FILES_IN_CACHE_DIR. ".";
|
|
// --- END DEBUG OUTPUT ---
|
|
|
|
if ($file_count <= MAX_FILES_IN_CACHE_DIR)
|
|
{
|
|
$content = makeCacheFile ($cache_file, $url, $debug);
|
|
$is_updated = 1;
|
|
|
|
// --- DEBUG OUTPUT -------
|
|
if ($debug)
|
|
echo "<br />Cache-Datei wurde erzeugt, " .
|
|
"weil diese nicht existierte.";
|
|
// --- END DEBUG OUTPUT ---
|
|
}
|
|
else
|
|
{
|
|
// --- DEBUG OUTPUT -------
|
|
if ($debug)
|
|
{
|
|
echo "<br />Es sind mehr Dateien im Cacheverzeichnis als " .
|
|
"erlaubt: " . $file_count .
|
|
"<br />Die Seite kann daher nicht gecached werden.";
|
|
}
|
|
// --- END DEBUG OUTPUT ---
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if ($auto_update)
|
|
{
|
|
$do_update=0;
|
|
|
|
if (filemtime($cache_file) < filemtime($script_file))
|
|
{
|
|
$do_update = 1;
|
|
|
|
// --- DEBUG OUTPUT -------
|
|
if ($debug)
|
|
echo "<br />Cache-Datei wird erzeugt, weil die Cache-Datei " .
|
|
"älter als die Script-Datei ist.";
|
|
// --- END DEBUG OUTPUT ---
|
|
}
|
|
else
|
|
{
|
|
$includes = get_included_files ();
|
|
|
|
foreach($includes as $inc)
|
|
{
|
|
if (strstr ($inc, realpath (HOME . "/../")))
|
|
{
|
|
// --- DEBUG OUTPUT -------
|
|
if ($debug)
|
|
echo "<br />Untersuche Abhängigkeiten von $inc";
|
|
// --- END DEBUG OUTPUT ---
|
|
|
|
if (filemtime($inc) > filemtime($cache_file))
|
|
{
|
|
$do_update=1;
|
|
|
|
// --- DEBUG OUTPUT -------
|
|
if ($debug)
|
|
echo "<br />Cache-Datei wird erzeugt, weil " .
|
|
$inc . "verändert wurde.";
|
|
// --- END DEBUG OUTPUT ---
|
|
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (!$do_update)
|
|
{
|
|
$content = getCacheContent ($cache_file, $debug);
|
|
}
|
|
else
|
|
{
|
|
$content = makeCacheFile ($cache_file, $url, $debug);
|
|
$is_updated = 1;
|
|
|
|
// --- DEBUG OUTPUT -------
|
|
if ($debug)
|
|
echo "<br />Cache-Datei wurde erzeugt: Auto-Update";
|
|
// --- END DEBUG OUTPUT ---
|
|
}
|
|
}
|
|
|
|
if ($update_interval >= 10 && !$is_updated)
|
|
{
|
|
$diff = time() - filemtime($cache_file);
|
|
|
|
// --- DEBUG OUTPUT -------
|
|
if ($debug)
|
|
echo "<br />Noch " . $update_interval - $diff .
|
|
" Sekunden bis zum nächsten Interval-Update";
|
|
// --- END DEBUG OUTPUT ---
|
|
|
|
if ($diff > $update_interval)
|
|
{
|
|
$content = makeCacheFile($cache_file, $url, $debug);
|
|
$is_updated=1;
|
|
|
|
// --- DEBUG OUTPUT -------
|
|
if ($debug)
|
|
echo "<br />Cache-Datei wurde erzeugt: Interval-Update";
|
|
// --- END DEBUG OUTPUT ---
|
|
}
|
|
else
|
|
{
|
|
$content = getCacheContent($cache_file, $debug);
|
|
}
|
|
}
|
|
}
|
|
|
|
// --- DEBUG OUTPUT -------
|
|
if ($debug)
|
|
echo "<hr />";
|
|
// --- END DEBUG OUTPUT ---
|
|
|
|
if (!empty($content))
|
|
echo "\n<!-- Cache-Bereich Anfang: ".basename($script_name)." -->\n";
|
|
echo $content;
|
|
if (!empty($content))
|
|
echo "\n<!-- Cache-Bereich Ende: ".basename($script_name)." -->\n";
|
|
|
|
// --- DEBUG OUTPUT -------
|
|
if ($debug)
|
|
echo "<hr /><p />Gecachter Content wurde ausgeliefert.";
|
|
if ($debug)
|
|
echo "<br />Verarbeitungsdauer (in ms): ".(intval(getMilliSeconds()-$t1));
|
|
// --- END DEBUG OUTPUT ---
|
|
|
|
if (empty($content))
|
|
return 0;
|
|
else
|
|
return 1;
|
|
}
|
|
|
|
function makeCacheFile($cache_file, $url, $debug)
|
|
{
|
|
if (preg_match("/^http.*\?.*/",$url))
|
|
$url = $url."&NOCACHE=1&PHP_SELF=".urlencode($_SERVER["PHP_SELF"]);
|
|
else
|
|
$url = $url."?NOCACHE=1&PHP_SELF=".urlencode($_SERVER["PHP_SELF"]);
|
|
|
|
if ($debug)
|
|
echo "<br />Encoded URL: $url";
|
|
|
|
// --- DEBUG OUTPUT -------
|
|
$t1 = '';
|
|
if ($debug)
|
|
$t1=getMilliSeconds();
|
|
// --- END DEBUG OUTPUT ---
|
|
|
|
$content = file_get_contents($url);
|
|
|
|
// --- DEBUG OUTPUT -------
|
|
if ($debug)
|
|
echo "<br />Laden der Seite ohne Cache dauerte: " .
|
|
getMilliSeconds() - $t1 . " ms";
|
|
flush();
|
|
|
|
if ($debug)
|
|
{
|
|
echo "<br />Cache-Datei ist gesperrt: ";
|
|
var_dump (is_file ($cache_file.".LCK"));
|
|
}
|
|
// --- END DEBUG OUTPUT ---
|
|
|
|
$ctr = 0;
|
|
while (cacheFileIsLocked ($cache_file))
|
|
{
|
|
usleep (100000);
|
|
$ctr++;
|
|
if ($debug)
|
|
{
|
|
echo "<br />Cache-Datei ist gesperrt ...";
|
|
flush();
|
|
}
|
|
if ($ctr>(MAX_CACHE_WAIT_SECS*10))
|
|
return $content;
|
|
clearstatcache();
|
|
}
|
|
$is_locked = lockCacheFile($cache_file);
|
|
if ($is_locked)
|
|
{
|
|
$fp = fopen($cache_file, "w");
|
|
if ($fp)
|
|
{
|
|
fwrite($fp,$content);
|
|
|
|
// for ($x=0;$x<25;$x++)
|
|
// {
|
|
// echo "<br />Test sleep ... $x";
|
|
// flush();
|
|
// sleep(1);
|
|
// }
|
|
|
|
fclose($fp);
|
|
chmod($cache_file,0777);
|
|
}
|
|
} else
|
|
if ($debug)
|
|
echo "<br />Cache-Datei konnte nicht geschrieben werden, " .
|
|
"weil die Lock-Datei nicht gesperrt werden konnte";
|
|
if ($is_locked)
|
|
unlockCacheFile($cache_file);
|
|
return $content;
|
|
}
|
|
|
|
function lockCacheFile($cache_file)
|
|
{
|
|
$lock_file = $cache_file.".LCK";
|
|
if (is_file($lock_file))
|
|
{
|
|
if (is_writable($lock_file))
|
|
{
|
|
chmod($lock_file,0555);
|
|
clearstatcache();
|
|
return 1;
|
|
}
|
|
else
|
|
return 0;
|
|
} else
|
|
{
|
|
$fp = fopen($lock_file,'w');
|
|
if ($fp)
|
|
{
|
|
fclose($fp);
|
|
chmod($lock_file,0555);
|
|
clearstatcache();
|
|
return 1;
|
|
} else
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
function unlockCacheFile($cache_file)
|
|
{
|
|
$lock_file = $cache_file.".LCK";
|
|
chmod($lock_file,0777);
|
|
if (is_file($lock_file))
|
|
{
|
|
unlink($lock_file);
|
|
clearstatcache();
|
|
}
|
|
}
|
|
|
|
function cacheFileIsLocked($cache_file)
|
|
{
|
|
$lock_file = $cache_file.".LCK";
|
|
$is_locked = is_file($lock_file);
|
|
|
|
if ($is_locked)
|
|
return 1;
|
|
return 0;
|
|
}
|
|
|
|
function getProtocol()
|
|
{
|
|
$proto = $_SERVER["SERVER_PROTOCOL"];
|
|
if (preg_match("/^HTTP\/.*$/",$proto))
|
|
return 'http';
|
|
if (preg_match("/^HTTPS\/.*$/",$proto))
|
|
return 'https';
|
|
}
|
|
|
|
function getCacheContent($cache_file, $debug)
|
|
{
|
|
$ctr = 0;
|
|
while (cacheFileIsLocked($cache_file))
|
|
{
|
|
usleep(100000);
|
|
$ctr++;
|
|
if ($debug)
|
|
{
|
|
echo "<br />Kann Content nicht ausliefern, da Cache-Datei gesperrt ist ...";
|
|
flush();
|
|
}
|
|
if ($ctr>(MAX_CACHE_WAIT_SECS*10))
|
|
return "";
|
|
clearstatcache();
|
|
}
|
|
return file_get_contents($cache_file);
|
|
}
|
|
|
|
function cleanupCache()
|
|
{
|
|
$log = "<h3>Cleanup Cache Script</h3>\n<ul>";
|
|
$def_vars = get_defined_constants();
|
|
|
|
if (!array_key_exists('CACHE_CLEANUP_TIME',$def_vars))
|
|
{
|
|
$log .= "<li>Konstante CACHE_CLEANUP_TIME ist nicht definiert - breche Cleanup-Skript ab.</li></ul>";
|
|
return $log;
|
|
} else if (!array_key_exists('CACHECLEANUPFILE',$def_vars))
|
|
{
|
|
$log .= "<li>Konstante CACHECLEANUPFILE ist nicht definiert - breche Cleanup-Skript ab.</li></ul>";
|
|
return $log;
|
|
} else
|
|
if (!preg_match("/^([0-9][0-9]:[0-9][0-9],{0,1})*$/",CACHE_CLEANUP_TIME))
|
|
{
|
|
$log .= "<li>Konstante CACHE_CLEANUP_TIME '".CACHE_CLEANUP_TIME."' ist im falschen Format - breche Cleanup-Skript ab.</li></ul>";
|
|
return $log;
|
|
}
|
|
|
|
$cachecleanup_file = CACHEDIR.CACHECLEANUPFILE;
|
|
$cleanup = 0;
|
|
$err_reporting = ini_get("error_reporting");
|
|
ini_set("error_reporting",0);
|
|
|
|
if (file_exists($cachecleanup_file))
|
|
{
|
|
$lastmodified = filemtime($cachecleanup_file);
|
|
$cachecleanup_file = realpath($cachecleanup_file);
|
|
$log .= "<li>Cache-Cleanup-Datei $cachecleanup_file existiert.</li>";
|
|
$log .= "<li>Cache-Cleanup-Datei $cachecleanup_file wurde letzmals aktualisiert am: ".strftime("%d.%m.%Y %H:%M:%S",$lastmodified)." Uhr</li>";
|
|
|
|
}
|
|
else
|
|
$lastmodified = -1;
|
|
$cleanuptime_arr = explode(",",CACHE_CLEANUP_TIME);
|
|
foreach($cleanuptime_arr as $cleanup_time)
|
|
{
|
|
$log .= "<li><b>Checke Cleanup-Time $cleanup_time Uhr</b><ul>";
|
|
$ct_arr = explode(":",$cleanup_time);
|
|
if (count($ct_arr)>=2)
|
|
{
|
|
$hour = $ct_arr[0];
|
|
$minute = $ct_arr[1];
|
|
$today = getdate();
|
|
$cleanup_timestamp = mktime($hour,$minute,0,$today["mon"],$today["mday"],$today["year"]);
|
|
$now = time();
|
|
$diff1 = $now-$cleanup_timestamp;
|
|
$log .= "<li>Untersuche Differenz: now()-$cleanup_time=$diff1 Sekunden</li>";
|
|
if ($diff1>0)
|
|
{
|
|
$log .= "<li>Cleanup-Zeitpunkt ist überschritten</li>";
|
|
if ($cleanup_timestamp>$lastmodified)
|
|
{
|
|
$cleanup=1;
|
|
$log .= "<li>Cleanup-Zeitpunkt muss durchgeführt werden.</li>";
|
|
} else
|
|
$log .= "<li>Kein Cleanup erforderlich, weil ".basename($cachecleanup_file)." nach der Cleanup-Zeit" .
|
|
" $cleanup_time Uhr verändert wurde.";
|
|
} else
|
|
$log .= "<li>Kein Cleanup erforderlich. Es dauert noch ".(-$diff1)." Sekunden bis zum nächsten Cleanup.</li>";
|
|
}
|
|
$log .= "</ul></li>";
|
|
}
|
|
|
|
if ($cleanup)
|
|
{
|
|
$log .= "<li><b>Führe jetzt Cleanup durch ...</b>";
|
|
$files = scandir(CACHEDIR);
|
|
|
|
foreach($files as $key=>$file)
|
|
{
|
|
if ($file=='.' ||
|
|
$file=='..' ||
|
|
$file=='.svn' ||
|
|
$file==LASTLOGFILE ||
|
|
$file==CACHECLEANUPFILE)
|
|
unset($files[$key]);
|
|
}
|
|
|
|
if (count($files)==0)
|
|
$log .= "<li>Cache ist leer.</li>";
|
|
foreach($files as $file)
|
|
{
|
|
$file = realpath(CACHEDIR.$file);
|
|
$success = 0;
|
|
if (is_file($file))
|
|
{
|
|
$log .= "<li>lösche Datei $file : ";
|
|
$success = unlink($file);
|
|
} else if (is_dir($file))
|
|
{
|
|
$log .= "<li>lösche Verzeichnis $file : ";
|
|
|
|
delTree($file);
|
|
if (!is_dir($file))
|
|
$success = 1;
|
|
}
|
|
|
|
if ($success)
|
|
$log .= " gelöscht.</li>";
|
|
else
|
|
$log .= " <b style=\"color:red\">Löschen fehlgeschlagen.</b></li>";
|
|
}
|
|
$fp = fopen($cachecleanup_file,"w");
|
|
fclose($fp);
|
|
}
|
|
$log .= "\n</ul>\nCleanup beendet.";
|
|
ini_set($err_reporting);
|
|
return $log;
|
|
}
|
|
|
|
function delTree($path) {
|
|
if (is_dir($path)) {
|
|
$entries = scandir($path);
|
|
foreach ($entries as $entry) {
|
|
if ($entry != '.' && $entry != '..') {
|
|
deltree($path.DIRECTORY_SEPARATOR.$entry);
|
|
}
|
|
}
|
|
rmdir($path);
|
|
} else {
|
|
unlink($path);
|
|
}
|
|
}
|
|
|
|
?>
|