TYPO3CMS  8
 All Classes Namespaces Files Functions Variables Pages
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 
22 
27 {
33  protected $logFile = '';
34 
40  protected $defaultLogFileTemplate = 'typo3temp/var/logs/typo3_%s.log';
41 
51  protected static $logFileHandles = [];
52 
59  public function __construct(array $options = [])
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  // create .htaccess file if log file is within the site path
195  if (PathUtility::getCommonPrefix([PATH_site, $logFileDirectory]) === PATH_site) {
196  // only create .htaccess, if we created the directory on our own
197  $this->createHtaccessFile($logFileDirectory . '/.htaccess');
198  }
199  }
200  // create the log file
201  GeneralUtility::writeFile($this->logFile, '');
202  }
203 
210  protected function createHtaccessFile($htaccessFile)
211  {
212  // write .htaccess file to protect the log file
213  if (!empty($GLOBALS['TYPO3_CONF_VARS']['SYS']['generateApacheHtaccess']) && !file_exists($htaccessFile)) {
214  $htaccessContent = '
215 # Apache < 2.3
216 <IfModule !mod_authz_core.c>
217  Order allow,deny
218  Deny from all
219  Satisfy All
220 </IfModule>
221 
222 # Apache ≥ 2.3
223 <IfModule mod_authz_core.c>
224  Require all denied
225 </IfModule>
226  ';
227  GeneralUtility::writeFile($htaccessFile, $htaccessContent);
228  }
229  }
230 
239  protected function getDefaultLogFileName()
240  {
241  return sprintf($this->defaultLogFileTemplate, substr(GeneralUtility::hmac($this->defaultLogFileTemplate, 'defaultLogFile'), 0, 10));
242  }
243 }
static mkdir_deep($directory, $deepDirectory= '')
static writeFile($file, $content, $changePermissions=false)
static getName($level)
Definition: LogLevel.php:118
if(TYPO3_MODE=== 'BE') $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_tsfebeuserauth.php']['frontendEditingController']['default']
static getFileAbsFileName($filename, $_=null, $_2=null)
static hmac($input, $additionalSecret= '')
static getCommonPrefix(array $paths)