PageRenderTime 52ms CodeModel.GetById 24ms RepoModel.GetById 0ms app.codeStats 0ms

/libraries/joomla/log/logger/formattedtext.php

http://github.com/joomla/joomla-platform
PHP | 267 lines | 126 code | 36 blank | 105 comment | 17 complexity | 1f4d8e62efb0cb9f93e5790e14bbca30 MD5 | raw file
Possible License(s): GPL-2.0, LGPL-2.1
  1. <?php
  2. /**
  3. * @package Joomla.Platform
  4. * @subpackage Log
  5. *
  6. * @copyright Copyright (C) 2005 - 2013 Open Source Matters, Inc. All rights reserved.
  7. * @license GNU General Public License version 2 or later; see LICENSE
  8. */
  9. defined('JPATH_PLATFORM') or die;
  10. jimport('joomla.filesystem.folder');
  11. /**
  12. * Joomla! Formatted Text File Log class
  13. *
  14. * This class is designed to use as a base for building formatted text files for output. By
  15. * default it emulates the Syslog style format output. This is a disk based output format.
  16. *
  17. * @package Joomla.Platform
  18. * @subpackage Log
  19. * @since 11.1
  20. */
  21. class JLogLoggerFormattedtext extends JLogLogger
  22. {
  23. /**
  24. * @var resource The file pointer for the log file.
  25. * @since 11.1
  26. */
  27. protected $file;
  28. /**
  29. * @var string The format for which each entry follows in the log file. All fields must be named
  30. * in all caps and be within curly brackets eg. {FOOBAR}.
  31. * @since 11.1
  32. */
  33. protected $format = '{DATETIME} {PRIORITY} {CATEGORY} {MESSAGE}';
  34. /**
  35. * @var array The parsed fields from the format string.
  36. * @since 11.1
  37. */
  38. protected $fields = array();
  39. /**
  40. * @var string The full filesystem path for the log file.
  41. * @since 11.1
  42. */
  43. protected $path;
  44. /**
  45. * Constructor.
  46. *
  47. * @param array &$options Log object options.
  48. *
  49. * @since 11.1
  50. */
  51. public function __construct(array &$options)
  52. {
  53. // Call the parent constructor.
  54. parent::__construct($options);
  55. // The name of the text file defaults to 'error.php' if not explicitly given.
  56. if (empty($this->options['text_file']))
  57. {
  58. $this->options['text_file'] = 'error.php';
  59. }
  60. // The name of the text file path defaults to that which is set in configuration if not explicitly given.
  61. if (empty($this->options['text_file_path']))
  62. {
  63. $this->options['text_file_path'] = JFactory::getConfig()->get('log_path');
  64. }
  65. // False to treat the log file as a php file.
  66. if (empty($this->options['text_file_no_php']))
  67. {
  68. $this->options['text_file_no_php'] = false;
  69. }
  70. // Build the full path to the log file.
  71. $this->path = $this->options['text_file_path'] . '/' . $this->options['text_file'];
  72. // Use the default entry format unless explicitly set otherwise.
  73. if (!empty($this->options['text_entry_format']))
  74. {
  75. $this->format = (string) $this->options['text_entry_format'];
  76. }
  77. // Build the fields array based on the format string.
  78. $this->parseFields();
  79. }
  80. /**
  81. * Destructor.
  82. *
  83. * @since 11.1
  84. */
  85. public function __destruct()
  86. {
  87. if (is_resource($this->file))
  88. {
  89. fclose($this->file);
  90. }
  91. }
  92. /**
  93. * Method to add an entry to the log.
  94. *
  95. * @param JLogEntry $entry The log entry object to add to the log.
  96. *
  97. * @return boolean True on success.
  98. *
  99. * @since 11.1
  100. * @throws RuntimeException
  101. */
  102. public function addEntry(JLogEntry $entry)
  103. {
  104. // Initialise the file if not already done.
  105. if (!is_resource($this->file))
  106. {
  107. $this->initFile();
  108. }
  109. // Set some default field values if not already set.
  110. if (!isset($entry->clientIP))
  111. {
  112. // Check for proxies as well.
  113. if (isset($_SERVER['REMOTE_ADDR']))
  114. {
  115. $entry->clientIP = $_SERVER['REMOTE_ADDR'];
  116. }
  117. elseif (isset($_SERVER['HTTP_X_FORWARDED_FOR']))
  118. {
  119. $entry->clientIP = $_SERVER['HTTP_X_FORWARDED_FOR'];
  120. }
  121. elseif (isset($_SERVER['HTTP_CLIENT_IP']))
  122. {
  123. $entry->clientIP = $_SERVER['HTTP_CLIENT_IP'];
  124. }
  125. }
  126. // If the time field is missing or the date field isn't only the date we need to rework it.
  127. if ((strlen($entry->date) != 10) || !isset($entry->time))
  128. {
  129. // Get the date and time strings in GMT.
  130. $entry->datetime = $entry->date->toISO8601();
  131. $entry->time = $entry->date->format('H:i:s', false);
  132. $entry->date = $entry->date->format('Y-m-d', false);
  133. }
  134. // Get a list of all the entry keys and make sure they are upper case.
  135. $tmp = array_change_key_case(get_object_vars($entry), CASE_UPPER);
  136. // Decode the entry priority into an English string.
  137. $tmp['PRIORITY'] = $this->priorities[$entry->priority];
  138. // Fill in field data for the line.
  139. $line = $this->format;
  140. foreach ($this->fields as $field)
  141. {
  142. $line = str_replace('{' . $field . '}', (isset($tmp[$field])) ? $tmp[$field] : '-', $line);
  143. }
  144. // Write the new entry to the file.
  145. if (!fwrite($this->file, $line . "\n"))
  146. {
  147. throw new RuntimeException('Cannot write to log file.');
  148. }
  149. }
  150. /**
  151. * Method to generate the log file header.
  152. *
  153. * @return string The log file header
  154. *
  155. * @since 11.1
  156. */
  157. protected function generateFileHeader()
  158. {
  159. $head = array();
  160. // Build the log file header.
  161. // If the no php flag is not set add the php die statement.
  162. if (empty($this->options['text_file_no_php']))
  163. {
  164. // Blank line to prevent information disclose: https://bugs.php.net/bug.php?id=60677
  165. $head[] = '#';
  166. $head[] = '#<?php die(\'Forbidden.\'); ?>';
  167. }
  168. $head[] = '#Date: ' . gmdate('Y-m-d H:i:s') . ' UTC';
  169. $head[] = '#Software: ' . JPlatform::getLongVersion();
  170. $head[] = '';
  171. // Prepare the fields string
  172. $head[] = '#Fields: ' . strtolower(str_replace('}', '', str_replace('{', '', $this->format)));
  173. $head[] = '';
  174. return implode("\n", $head);
  175. }
  176. /**
  177. * Method to initialise the log file. This will create the folder path to the file if it doesn't already
  178. * exist and also get a new file header if the file doesn't already exist. If the file already exists it
  179. * will simply open it for writing.
  180. *
  181. * @return void
  182. *
  183. * @since 11.1
  184. */
  185. protected function initFile()
  186. {
  187. // If the file doesn't already exist we need to create it and generate the file header.
  188. if (!is_file($this->path))
  189. {
  190. // Make sure the folder exists in which to create the log file.
  191. JFolder::create(dirname($this->path));
  192. // Build the log file header.
  193. $head = $this->generateFileHeader();
  194. }
  195. else
  196. {
  197. $head = false;
  198. }
  199. // Open the file for writing (append mode).
  200. if (!$this->file = fopen($this->path, 'a'))
  201. {
  202. throw new RuntimeException('Cannot open file for writing log');
  203. }
  204. if ($head)
  205. {
  206. if (!fwrite($this->file, $head))
  207. {
  208. throw new RuntimeException('Cannot fput file for log');
  209. }
  210. }
  211. }
  212. /**
  213. * Method to parse the format string into an array of fields.
  214. *
  215. * @return void
  216. *
  217. * @since 11.1
  218. */
  219. protected function parseFields()
  220. {
  221. $this->fields = array();
  222. $matches = array();
  223. // Get all of the available fields in the format string.
  224. preg_match_all("/{(.*?)}/i", $this->format, $matches);
  225. // Build the parsed fields list based on the found fields.
  226. foreach ($matches[1] as $match)
  227. {
  228. $this->fields[] = strtoupper($match);
  229. }
  230. }
  231. }