TYPO3  7.6
FileWriter.php
Go to the documentation of this file.
1 <?php
2 namespace TYPO3\CMS\Core\Log\Writer;
3 
4 /*
5  * This file is part of the TYPO3 CMS project.
6  *
7  * It is free software; you can redistribute it and/or modify it under
8  * the terms of the GNU General Public License, either version 2
9  * of the License, or any later version.
10  *
11  * For the full copyright and license information, please read the
12  * LICENSE.txt file that was distributed with this source code.
13  *
14  * The TYPO3 project - inspiring people to share!
15  */
16 
17 use TYPO3\CMS\Core\Log\Exception\InvalidLogWriterConfigurationException;
22 
27 {
33  protected $logFile = '';
34 
40  protected $defaultLogFileTemplate = 'typo3temp/logs/typo3_%s.log';
41 
51  protected static $logFileHandles = array();
52 
59  public function __construct(array $options = array())
60  {
61  // the parent constructor reads $options and sets them
62  parent::__construct($options);
63  if (empty($options['logFile'])) {
64  $this->setLogFile($this->getDefaultLogFileName());
65  }
66  }
67 
71  public function __destruct()
72  {
73  $this->closeLogFile();
74  }
75 
83  public function setLogFile($relativeLogFile)
84  {
85  $logFile = $relativeLogFile;
86  // Skip handling if logFile is a stream resource. This is used by unit tests with vfs:// directories
87  if (false === strpos($logFile, '://') && !PathUtility::isAbsolutePath($logFile)) {
89  if ($logFile === NULL) {
90  throw new InvalidLogWriterConfigurationException('Log file path "' . $relativeLogFile . '" is not valid!', 1444374805);
91  }
92  }
93  $this->logFile = $logFile;
94  $this->openLogFile();
95 
96  return $this;
97  }
98 
104  public function getLogFile()
105  {
106  return $this->logFile;
107  }
108 
116  public function writeLog(LogRecord $record)
117  {
118  $timestamp = date('r', (int)$record->getCreated());
119  $levelName = LogLevel::getName($record->getLevel());
120  $data = '';
121  $recordData = $record->getData();
122  if (!empty($recordData)) {
123  // According to PSR3 the exception-key may hold an \Exception
124  // Since json_encode() does not encode an exception, we run the _toString() here
125  if (isset($recordData['exception']) && $recordData['exception'] instanceof \Exception) {
126  $recordData['exception'] = (string)$recordData['exception'];
127  }
128  $data = '- ' . json_encode($recordData);
129  }
130 
131  $message = sprintf(
132  '%s [%s] request="%s" component="%s": %s %s',
133  $timestamp,
134  $levelName,
135  $record->getRequestId(),
136  $record->getComponent(),
137  $record->getMessage(),
138  $data
139  );
140 
141  if (false === fwrite(self::$logFileHandles[$this->logFile], $message . LF)) {
142  throw new \RuntimeException('Could not write log record to log file', 1345036335);
143  }
144 
145  return $this;
146  }
147 
154  protected function openLogFile()
155  {
156  if (is_resource(self::$logFileHandles[$this->logFile])) {
157  return;
158  }
159 
160  $this->createLogFile();
161  self::$logFileHandles[$this->logFile] = fopen($this->logFile, 'a');
162  if (!is_resource(self::$logFileHandles[$this->logFile])) {
163  throw new \RuntimeException('Could not open log file "' . $this->logFile . '"', 1321804422);
164  }
165  }
166 
172  protected function closeLogFile()
173  {
174  if (is_resource(self::$logFileHandles[$this->logFile])) {
175  fclose(self::$logFileHandles[$this->logFile]);
176  unset(self::$logFileHandles[$this->logFile]);
177  }
178  }
179 
186  protected function createLogFile()
187  {
188  if (file_exists($this->logFile)) {
189  return;
190  }
191  $logFileDirectory = dirname($this->logFile);
192  if (!@is_dir($logFileDirectory)) {
193  GeneralUtility::mkdir_deep($logFileDirectory);
194  // only create .htaccess, if we created the directory on our own
195  $this->createHtaccessFile($logFileDirectory . '/.htaccess');
196  }
197  // create the log file
198  GeneralUtility::writeFile($this->logFile, '');
199  }
200 
207  protected function createHtaccessFile($htaccessFile)
208  {
209  // write .htaccess file to protect the log file
210  if (!empty($GLOBALS['TYPO3_CONF_VARS']['SYS']['generateApacheHtaccess']) && !file_exists($htaccessFile)) {
211  $htaccessContent = '
212 # Apache < 2.3
213 <IfModule !mod_authz_core.c>
214  Order allow,deny
215  Deny from all
216  Satisfy All
217 </IfModule>
218 
219 # Apache ≥ 2.3
220 <IfModule mod_authz_core.c>
221  Require all denied
222 </IfModule>
223  ';
224  GeneralUtility::writeFile($htaccessFile, $htaccessContent);
225  }
226  }
227 
236  protected function getDefaultLogFileName()
237  {
238  return sprintf($this->defaultLogFileTemplate, substr(GeneralUtility::hmac($this->defaultLogFileTemplate, 'defaultLogFile'), 0, 10));
239  }
240 }