c7a948e12abbfc5dd7d8e1443a3d520612a91036
[Packages/TYPO3.CMS.git] / typo3 / sysext / core / Classes / Log / Writer / FileWriter.php
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;
18 use TYPO3\CMS\Core\Utility\GeneralUtility;
19
20 /**
21 * Log writer that writes the log records into a file.
22 *
23 * @author Steffen Gebert <steffen.gebert@typo3.org>
24 * @author Steffen Müller <typo3@t3node.com>
25 * @author Ingo Renner <ingo@typo3.org>
26 */
27 class FileWriter extends AbstractWriter {
28
29 /**
30 * Log file path, relative to PATH_site
31 *
32 * @var string
33 */
34 protected $logFile = '';
35
36 /**
37 * Default log file path
38 *
39 * @var string
40 */
41 protected $defaultLogFile = 'typo3temp/logs/typo3.log';
42
43 /**
44 * Log file handle storage
45 *
46 * To avoid concurrent file handles on a the same file when using several FileWriter instances,
47 * we share the file handles in a static class variable
48 *
49 * @static
50 * @var array
51 */
52 static protected $logFileHandles = array();
53
54 /**
55 * Constructor, opens the log file handle
56 *
57 * @param array $options
58 * @return \TYPO3\CMS\Core\Log\Writer\FileWriter
59 */
60 public function __construct(array $options = array()) {
61 // the parent constructor reads $options and sets them
62 parent::__construct($options);
63 if (empty($options['logFile'])) {
64 $this->setLogFile($this->defaultLogFile);
65 }
66 }
67
68 /**
69 * Destructor, closes the log file handle
70 */
71 public function __destruct() {
72 $this->closeLogFile();
73 }
74
75 /**
76 * Sets the path to the log file.
77 *
78 * @param string $logFile path to the log file, relative to PATH_site
79 * @return \TYPO3\CMS\Core\Log\Writer\WriterInterface
80 * @throws \TYPO3\CMS\Core\Log\Exception\InvalidLogWriterConfigurationException
81 */
82 public function setLogFile($logFile) {
83
84 // Skip handling if logFile is a stream resource. This is used by unit tests with vfs:// directories
85 if (FALSE === strpos($logFile, '://')) {
86 if (!GeneralUtility::isAllowedAbsPath((PATH_site . $logFile))) {
87 throw new InvalidLogWriterConfigurationException('Log file path "' . $logFile . '" is not valid!', 1326411176);
88 }
89 $logFile = GeneralUtility::getFileAbsFileName($logFile);
90 }
91 $this->logFile = $logFile;
92 $this->openLogFile();
93
94 return $this;
95 }
96
97 /**
98 * Gets the path to the log file.
99 *
100 * @return string Path to the log file.
101 */
102 public function getLogFile() {
103 return $this->logFile;
104 }
105
106 /**
107 * Writes the log record
108 *
109 * @param \TYPO3\CMS\Core\Log\LogRecord $record Log record
110 * @return \TYPO3\CMS\Core\Log\Writer\WriterInterface $this
111 * @throws \RuntimeException
112 */
113 public function writeLog(\TYPO3\CMS\Core\Log\LogRecord $record) {
114 if (FALSE === fwrite(self::$logFileHandles[$this->logFile], $record . LF)) {
115 throw new \RuntimeException('Could not write log record to log file', 1345036335);
116 }
117
118 return $this;
119 }
120
121 /**
122 * Opens the log file handle
123 *
124 * @return void
125 * @throws \RuntimeException if the log file can't be opened.
126 */
127 protected function openLogFile() {
128 if (is_resource(self::$logFileHandles[$this->logFile])) {
129 return;
130 }
131
132 $this->createLogFile();
133 self::$logFileHandles[$this->logFile] = fopen($this->logFile, 'a');
134 if (!is_resource(self::$logFileHandles[$this->logFile])) {
135 throw new \RuntimeException('Could not open log file "' . $this->logFile . '"', 1321804422);
136 }
137 }
138
139 /**
140 * Closes the log file handle.
141 *
142 * @return void
143 */
144 protected function closeLogFile() {
145 if (is_resource(self::$logFileHandles[$this->logFile])) {
146 fclose(self::$logFileHandles[$this->logFile]);
147 unset(self::$logFileHandles[$this->logFile]);
148 }
149 }
150
151 /**
152 * Creates the log file with correct permissions
153 * and parent directories, if needed
154 *
155 * @return void
156 */
157 protected function createLogFile() {
158 if (file_exists($this->logFile)) {
159 return;
160 }
161 $logFileDirectory = dirname($this->logFile);
162 if (!@is_dir($logFileDirectory)) {
163 GeneralUtility::mkdir_deep($logFileDirectory);
164 // only create .htaccess, if we created the directory on our own
165 $this->createHtaccessFile($logFileDirectory . '/.htaccess');
166 }
167 // create the log file
168 GeneralUtility::writeFile($this->logFile, '');
169 }
170
171 /**
172 * Creates .htaccess file inside a new directory to access protect it
173 *
174 * @param string $htaccessFile Path of .htaccess file
175 * @return void
176 */
177 protected function createHtaccessFile($htaccessFile) {
178 // write .htaccess file to protect the log file
179 if (!empty($GLOBALS['TYPO3_CONF_VARS']['SYS']['generateApacheHtaccess']) && !file_exists($htaccessFile)) {
180 GeneralUtility::writeFile($htaccessFile, 'Deny From All');
181 }
182 }
183
184 }