<?php

/****************************************************************************
 * STATIC RESOURCES MANAGEMENT
 ****************************************************************************/

global $resources;


/** This variable contains the list of resources to be loaded.
 */
$resources = array();


/** This function appends a resource of some type to the list of resources
 * to be loaded.
 */
function addFileResource($type, $path) {
	if (!file_exists($path)) {
		//logText("Resource type '$type': '$path' not found", LOG_DEBUG);
		return false;
	}

	global $resources;
	if (!is_array($resources[$type])) {
		$resources[$type] = array();
	}

	$contents = @file_get_contents($path);
	if ($contents === FALSE) {
		l::notice("Resource type '$type': unable to read '$path'");
		return false;
	}
	$md5 = md5($contents);

	array_push($resources[$type], array($path, $md5, $contents));
	return true;
}


/** This function appends a chunk of raw text to a resource output.
 */
function addRawResource($type, $text) {
	global $resources;
	if (!is_array($resources[$type])) {
		$resources[$type] = array();
	}

	$md5 = md5($text);
	array_push($resources[$type], array(null, $md5, $text));

	return true;
}


/** This function generates the cached output for a set of resources.
 */
function generateResourceCache($type, $md5) {
	if (!is_dir(config::$main['cachedir']) && !@mkdir(config::$main['cachedir'])) {
		return false;
	}

	$f = @fopen(config::$main['cachedir'] . "/$md5.$type", "w");
	if (!$f) {
		return false;
	}

	global $resources;
	$c = count($resources[$type]);
	for ($i=0;$i<$c;$i++) {
		fwrite($f, preg_replace('/__STATICURL__/', config::$main['staticurl'], $resources[$type][$i][2]) . "\n");
	}

	fclose($f);

	return true;
}


/** This function stores a ressource into the database so that it may be used
 * from other scripts.
 */
function storeResource($type, $deleteOld = 0, $write = true) {
	global $resources;
	if (!is_array($resources[$type])) {
//		l::notice("No resource of type $type");
		return null;
	}

	// Delete old entries
	if ($deleteOld > 0) {
		if ($write) {
			$q = dbQuery("SELECT md5 FROM web_cache WHERE unix_timestamp(now())-last_used>$deleteOld AND rtype='$type'");
			while ($r = dbFetchArray($q)) {
				@unlink(config::$main['cachedir'] . "/{$r[0]}.$type");
			}
		}
		dbQuery("DELETE FROM web_cache WHERE unix_timestamp(now())-last_used>$deleteOld AND rtype='$type'");
	}

	// Check for an existing entry
	$md5 = md5(serialize($resources[$type]));
	$q = dbQuery("SELECT id FROM web_cache WHERE rtype='$type' AND md5='$md5' FOR SHARE");
	if ($q && dbCount($q)) {
		list($id) = dbFetchArray($q);
		return $id;
	}

	// Generate the output file
	if ($write && !generateResourceCache($type, $md5)) {
		l::warn("Resource file generation failed (type $type)");
		return null;
	}

	// Add the database entry
	return dbQuery("INSERT INTO web_cache(rtype,md5,last_used) VALUES('$type','$md5'," . time() . ")");
}


/** This function reads a resource, identified by its DB identifier, from the
 * database. If the resource is found in the base, it then tries to send the
 * file's contents.
 */
function displayResource($id, $rtype) {
	$q = dbQuery("SELECT rtype,md5 FROM web_cache WHERE id=$id FOR UPDATE");
	if (!($q && dbCount($q) == 1)) {
		l::warn("Resource ID '$id' not in the database");
		return false;
	}

	list($dbtype,$md5) = dbFetchArray($q);
	if ($rtype != $dbtype) {
		l::warn("Resource ID '$id' has wrong type $dbtype (expected $rtype)");
		return false;
	}

	dbQuery("UPDATE web_cache SET last_used=" . time() . " WHERE id=$id");
	endRequest(false);

	$path = config::$main['cachedir'] . "/$md5.$rtype";
	if (readfile($path) === FALSE) {
		l::warn("File not found for resource '$id': $path");
		return false;
	}
	exit(0);
}


?>