File.php 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229
  1. <?php
  2. /**
  3. * PHPIDS
  4. *
  5. * Requirements: PHP5, SimpleXML
  6. *
  7. * Copyright (c) 2008 PHPIDS group (https://phpids.org)
  8. *
  9. * PHPIDS is free software; you can redistribute it and/or modify
  10. * it under the terms of the GNU Lesser General Public License as published by
  11. * the Free Software Foundation, version 3 of the License, or
  12. * (at your option) any later version.
  13. *
  14. * PHPIDS is distributed in the hope that it will be useful,
  15. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  16. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  17. * GNU Lesser General Public License for more details.
  18. *
  19. * You should have received a copy of the GNU Lesser General Public License
  20. * along with PHPIDS. If not, see <http://www.gnu.org/licenses/>.
  21. *
  22. * PHP version 5.1.6+
  23. *
  24. * @category Security
  25. * @package PHPIDS
  26. * @author Mario Heiderich <mario.heiderich@gmail.com>
  27. * @author Christian Matthies <ch0012@gmail.com>
  28. * @author Lars Strojny <lars@strojny.net>
  29. * @license http://www.gnu.org/licenses/lgpl.html LGPL
  30. * @link http://php-ids.org/
  31. */
  32. require_once 'IDS/Log/Interface.php';
  33. /**
  34. * File logging wrapper
  35. *
  36. * The file wrapper is designed to store data into a flatfile. It implements the
  37. * singleton pattern.
  38. *
  39. * @category Security
  40. * @package PHPIDS
  41. * @author Christian Matthies <ch0012@gmail.com>
  42. * @author Mario Heiderich <mario.heiderich@gmail.com>
  43. * @author Lars Strojny <lars@strojny.net>
  44. * @copyright 2007-2009 The PHPIDS Group
  45. * @license http://www.gnu.org/licenses/lgpl.html LGPL
  46. * @version Release: $Id:File.php 517 2007-09-15 15:04:13Z mario $
  47. * @link http://php-ids.org/
  48. */
  49. class IDS_Log_File implements IDS_Log_Interface
  50. {
  51. /**
  52. * Path to the log file
  53. *
  54. * @var string
  55. */
  56. private $logfile = null;
  57. /**
  58. * Instance container
  59. *
  60. * Due to the singleton pattern this class allows to initiate only one
  61. * instance for each file.
  62. *
  63. * @var array
  64. */
  65. private static $instances = array();
  66. /**
  67. * Holds current remote address
  68. *
  69. * @var string
  70. */
  71. private $ip = 'local/unknown';
  72. /**
  73. * Constructor
  74. *
  75. * @param string $logfile path to the log file
  76. *
  77. * @return void
  78. */
  79. protected function __construct($logfile)
  80. {
  81. // determine correct IP address and concat them if necessary
  82. $this->ip = $_SERVER['REMOTE_ADDR'] .
  83. (isset($_SERVER['HTTP_X_FORWARDED_FOR']) ?
  84. ' (' . $_SERVER['HTTP_X_FORWARDED_FOR'] . ')' : '');
  85. $this->logfile = $logfile;
  86. }
  87. /**
  88. * Returns an instance of this class
  89. *
  90. * This method allows the passed argument to be either an instance of
  91. * IDS_Init or a path to a log file. Due to the singleton pattern only one
  92. * instance for each file can be initiated.
  93. *
  94. * @param mixed $config IDS_Init or path to a file
  95. * @param string $classname the class name to use
  96. *
  97. * @return object $this
  98. */
  99. public static function getInstance($config, $classname = 'IDS_Log_File')
  100. {
  101. if ($config instanceof IDS_Init) {
  102. $logfile = $config->getBasePath() . $config->config['Logging']['path'];
  103. } elseif (is_string($config)) {
  104. $logfile = $config;
  105. }
  106. if (!isset(self::$instances[$logfile])) {
  107. self::$instances[$logfile] = new $classname($logfile);
  108. }
  109. return self::$instances[$logfile];
  110. }
  111. /**
  112. * Permitting to clone this object
  113. *
  114. * For the sake of correctness of a singleton pattern, this is necessary
  115. *
  116. * @return void
  117. */
  118. private function __clone()
  119. {
  120. }
  121. /**
  122. * Prepares data
  123. *
  124. * Converts given data into a format that can be stored into a file.
  125. * You might edit this method to your requirements.
  126. *
  127. * @param mixed $data incoming report data
  128. *
  129. * @return string
  130. */
  131. protected function prepareData($data)
  132. {
  133. $format = '"%s",%s,%d,"%s","%s","%s","%s"';
  134. $attackedParameters = '';
  135. foreach ($data as $event) {
  136. $attackedParameters .= $event->getName() . '=' .
  137. rawurlencode($event->getValue()) . ' ';
  138. }
  139. $dataString = sprintf($format,
  140. urlencode($this->ip),
  141. date('c'),
  142. $data->getImpact(),
  143. join(' ', $data->getTags()),
  144. urlencode(trim($attackedParameters)),
  145. urlencode($_SERVER['REQUEST_URI']),
  146. $_SERVER['SERVER_ADDR']
  147. );
  148. return $dataString;
  149. }
  150. /**
  151. * Stores given data into a file
  152. *
  153. * @param object $data IDS_Report
  154. *
  155. * @throws Exception if the logfile isn't writeable
  156. * @return boolean
  157. */
  158. public function execute(IDS_Report $data)
  159. {
  160. /*
  161. * In case the data has been modified before it might be necessary
  162. * to convert it to string since we can't store array or object
  163. * into a file
  164. */
  165. $data = $this->prepareData($data);
  166. if (is_string($data)) {
  167. if (file_exists($this->logfile)) {
  168. $data = trim($data);
  169. if (!empty($data)) {
  170. if (is_writable($this->logfile)) {
  171. $handle = fopen($this->logfile, 'a');
  172. fwrite($handle, trim($data) . "\n");
  173. fclose($handle);
  174. } else {
  175. throw new Exception(
  176. 'Please make sure that ' . $this->logfile .
  177. ' is writeable.'
  178. );
  179. }
  180. }
  181. } else {
  182. throw new Exception(
  183. 'Given file does not exist. Please make sure the
  184. logfile is present in the given directory.'
  185. );
  186. }
  187. } else {
  188. throw new Exception(
  189. 'Please make sure that data returned by
  190. IDS_Log_File::prepareData() is a string.'
  191. );
  192. }
  193. return true;
  194. }
  195. }
  196. /**
  197. * Local variables:
  198. * tab-width: 4
  199. * c-basic-offset: 4
  200. * End:
  201. * vim600: sw=4 ts=4 expandtab
  202. */