<?php
$CACHE_FILE="/home/evilkittie/.xonotic/urlcache.serial";// create this file and be make sure www-data has write access (you can place this in /var/cache if you prefer)
$data="/home/evilkittie/.xonotic/data";// Path to Xonotic's data folder
$servers=(object)array(// Game server is used as last resort (pay attention to commas at the end of lines in here)
// true means use a HTTPS connection
// false means use a HTTP connection
"dl.xonotic.co"=>false,
"xonotic.devfull.de/packages"=>true
);
function checkRemoteFile($path,$file,$https){
// based on answer here
// https://stackoverflow.com/questions/1363925/check-whether-image-exists-on-remote-url
$cache=(object)$GLOBALS["cache"];
if(isset($cache->{$path}) && isset($cache->{$path}->{$file})){// Is this cached?
return $cache->{$path}->{$file};// looks like it
}
else{// not cached, lets cache it!
/* Caching method is not perfect, there is a chance we could
* delete a small amount of cache doing this (no file lock)
* however it is only a cache we will get it sooner or later.
*/
$ch=curl_init();
curl_setopt($ch, CURLOPT_URL,"http".($https?'s':'')."://$path/$file");
// don't download content
curl_setopt($ch, CURLOPT_NOBODY, 1);
curl_setopt($ch, CURLOPT_FAILONERROR, 1);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
$result=curl_exec($ch)!==FALSE;
curl_close($ch);
if($GLOBALS["cacheTime"]!=filemtime($GLOBALS["CACHE_FILE"]))// did the cache change on us?
$cache=loadCache();// refresh it
if(!isset($cache->{$path}))
$cache->{$path}=(object)array();
$cache->{$path}->{$file}=$result;
saveCache($cache);
$GLOBALS["cache"]=$cache;//export cache
return $cache->{$path}->{$file};// is the file there?
}
}
function loadCache(){
$CACHE_FILE=$GLOBALS["CACHE_FILE"];
$cache=file_get_contents($CACHE_FILE);
if(filesize($CACHE_FILE)==0)// Assume file exist (*points at line 2*)
$cache=(object)array();
else{
$cache=false;
$ct=0;// safety
while($cache===false){
if($cache===false){// did it work?
if($ct!==0)
usleep(10000);// wait 0.01 seconds
$cache=file_get_contents($CACHE_FILE);// must have opened while data was being written
}
$cache=@unserialize($cache);// vastly faster than json_parse
$ct++;
if($ct>100){
// cache appears to be broken
$cache=(object)array();
break;
}
}
$GLOBALS["cacheTime"]=filemtime($CACHE_FILE);
}
return $cache;
}
function saveCache($cache){
$f=fopen($GLOBALS["CACHE_FILE"],"w");// open cache
fwrite($f, serialize($cache));//write cache
fclose($f);//save cache
}
if(isset($argv)){// cli management
foreach($argv as $key => $val){
if($val=="--dump"){
var_dump(unserialize(file_get_contents($CACHE_FILE)));
}
if($val=="--truncate"){
file_put_contents($CACHE_FILE, "");
}
if($val=="--delete"){
if(!isset($argv[$key+1]))
echo "--delete requires a file name";
else{
$del=$argv[$key+1];
$cache=loadCache();
foreach($cache as $s => $f){
if(isset($cache->{$s}->{$del}))
unset($cache->{$s}->{$del});
}
saveCache($cache);
}
}
if($val=="--drop"){
if(!isset($argv[$key+1]))
echo "--drop requires a path name";
else{
$del=$argv[$key+1];
$cache=loadCache();
if(isset($cache->{$del}))
unset($cache->{$del});
saveCache($cache);
}
}
if($val=="--help"){
echo "Options:\n\t".
"--dump\n\t\tDump cache in a readable format\n\t".
"--truncate\n\t\tDelete cache file content\n\t".
"--delete\n\t\tDelete a file from cache\n\t".
"--drop\n\t\tRemove a entire server's folder from cache\n\t".
"--help\n\t\tShow this help info";
}
}
die("\n");
}
if(!isset($_GET['file']))
die("file parameter is required!");
$file=$_GET['file'];
$file=substr($file,strrpos($file,'/'));// SECURITY MEASURE: DO NOT DELETE!
$cache=loadCache();
foreach($servers as $key => $val){
if(checkRemoteFile($key,$file,$val))
exit(header("Location: http".($val?'s':'')."://$key/$file"));
}
if(file_exists("$data/$file")){// guess we better send them our local copy
if(strtolower(substr(strrpos($file,".")))!='.pk3'){// are you trying to get server.cfg?
header('HTTP/1.0 403 Forbidden');// denied
header("Content-Type: text/plain");
die("Where did you get that file name anyway?");
}
header("Content-Type: application/zip");
header("Content-Disposition: attachment; filename=$file");
$file="$data/$file";
header("Content-Length: ".filesize($file));
include("$file");
}
else{
header("HTTP/1.0 404 Not Found");
header("Content-Type: text/plain");
echo "Xonotic Server: You need to download $file\n".
"Client: Web server I need you to give me $file\n".
"Web Server: $file does not even exist on this server\n".
"Client: Why would you tell me I need a file you don't have?\n".
"Web Server: The Xonotic Server must be experiencing an ID10T error.";
}
?>