<?php
/**
 * @version		$Id: log.php 9764 2007-12-30 07:48:11Z ircmaxell $
 * @package		Joomla.Framework
 * @subpackage	Error
 * @copyright	Copyright (C) 2005 - 2008 Open Source Matters. All rights reserved.
 * @license		GNU/GPL, see LICENSE.php
 * Joomla! is free software. This version may have been modified pursuant
 * to the GNU General Public License, and as distributed it includes or
 * is derivative of works licensed under the GNU General Public License or
 * other free or open source software licenses.
 * See COPYRIGHT.php for copyright notices and details.
 */

// Check to ensure this file is within the rest of the framework
defined('JPATH_BASE') or die();

/**
 * Joomla! Logging class
 *
 * This class is designed to build log files based on the
 * W3C specification at: http://www.w3.org/TR/WD-logfile.html
 *
 * @author		Louis Landry <louis.landry@joomla.org>
 * @package 	Joomla.Framework
 * @subpackage	Error
 * @since		1.5
 */
class JLog extends JObject
{
	/**
	 * Log File Pointer
	 * @var	resource
	 */
	var $_file;

	/**
	 * Log File Path
	 * @var	string
	 */
	var $_path;

	/**
	 * Log Format
	 * @var	string
	 */
	var $_format = "{DATE}\t{TIME}\t{LEVEL}\t{C-IP}\t{STATUS}\t{COMMENT}";

	/**
	 * Constructor
	 *
	 * @access	protected
	 * @param	string	$path		Log file path
	 * @param	array	$options	Log file options
	 * @since	1.5
	 */
	function __construct($path, $options)
	{
		// Set default values
		$this->_path = $path;
		$this->setOptions($options);
	}

	/**
	 * Returns a reference to the global log object, only creating it
	 * if it doesn't already exist.
	 *
	 * This method must be invoked as:
	 * 		<pre>  $log = & JLog::getInstance();</pre>
	 *
	 * @access	public
	 * @static
	 * @return	object	The JLog object.
	 * @since	1.5
	 */
	function & getInstance($file = 'error.php', $options = null, $path = null)
	{
		static $instances;

		// Set default path if not set
		if (!$path)
		{
			$config =& JFactory::getConfig();
			$path = $config->getValue('config.log_path');
		}

		jimport('joomla.filesystem.path');
		$path = JPath :: clean($path . DS . $file);
		$sig = md5($path);

		if (!isset ($instances)) {
			$instances = array ();
		}

		if (empty ($instances[$sig])) {
			$instances[$sig] = new JLog($path, $options);
		}

		return $instances[$sig];
	}

	/**
	 * Set log file options
	 *
	 * @access	public
	 * @param	array	$options	Associative array of options to set
	 * @return	boolean				True if successful
	 * @since	1.5
	 */
	function setOptions($options) {

		if (isset ($options['format'])) {
			$this->_format = $options['format'];
		}
		return true;
	}

	function addEntry($entry)
	{
		// Set some default field values if not already set.
		if (!isset ($entry['date'])) {
			// TODO: Should this be JDate?
			$entry['date'] = date("Y-m-d");
		}
		if (!isset ($entry['time'])) {
			// TODO: Should this be JDate?
			$entry['time'] = date("H:i:s");
		}
		if (!isset ($entry['c-ip'])) {
			$entry['c-ip'] = $_SERVER['REMOTE_ADDR'];
		}

		// Ensure that the log entry keys are all uppercase
		$entry = array_change_key_case($entry, CASE_UPPER);

		// Find all fields in the format string
		$fields = array ();
		$regex = "/{(.*?)}/i";
		preg_match_all($regex, $this->_format, $fields);

		// Fill in the field data
		$line = $this->_format;
		for ($i = 0; $i < count($fields[0]); $i++)
		{
			$line = str_replace($fields[0][$i], (isset ($entry[$fields[1][$i]])) ? $entry[$fields[1][$i]] : "-", $line);
		}

		// Write the log entry line
		if ($this->_openLog())
		{
			if (!fputs($this->_file, "\n" . $line)) {
				return false;
			}
		} else {
			return false;
		}
		return true;
	}

	/**
	 * Open the log file pointer and create the file if it doesn't exist
	 *
	 * @access 	public
	 * @return 	boolean	True on success
	 * @since	1.5
	 */
	function _openLog()
	{
		// Only open if not already opened...
		if (is_resource($this->_file)) {
			return true;
		}
		// TODO: Should this be JDate?
		$date = date("Y-m-d");
		$time = date("H:i:s");
		if (!file_exists($this->_path))
		{
			jimport("joomla.filesystem.folder");
			if (!JFolder :: create(dirname($this->_path))) {
				return false;
			}
			$header[] = "#<?php die('Direct Access To Log Files Not Permitted'); ?>";
			$header[] = "#Version: 1.0";
			$header[] = "#Date: " . $date . " " . $time;

			// Prepare the fields string
			$fields = str_replace("{", "", $this->_format);
			$fields = str_replace("}", "", $fields);
			$fields = strtolower($fields);
			$header[] = "#Fields: " . $fields;

			// Prepare the software string
			$version = new JVersion();
			$header[] = "#Software: " . $version->getLongVersion();

			$head = implode("\n", $header);
		} else {
			$head = false;
		}

		if (!$this->_file = fopen($this->_path, "a")) {
			return false;
		}
		if ($head)
		{
			if (!fputs($this->_file, $head)) {
				return false;
			}
		}

		// If we opened the file lets make sure we close it
		register_shutdown_function(array(&$this,'_closeLog'));
		return true;
	}

	/**
	 * Close the log file pointer
	 *
	 * @access 	public
	 * @return 	boolean	True on success
	 * @since	1.5
	 */
	function _closeLog()
	{
		if (is_resource($this->_file)) {
			fclose($this->_file);
		}
		return true;
	}
}