/usr/share/php/Nette/Tracy/Logger.php is in php-nette 2.4-20160731-1.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 | <?php
/**
* This file is part of the Tracy (https://tracy.nette.org)
* Copyright (c) 2004 David Grudl (https://davidgrudl.com)
*/
namespace Tracy;
/**
* Logger.
*/
class Logger implements ILogger
{
/** @var string name of the directory where errors should be logged */
public $directory;
/** @var string|array email or emails to which send error notifications */
public $email;
/** @var string sender of email notifications */
public $fromEmail;
/** @var mixed interval for sending email is 2 days */
public $emailSnooze = '2 days';
/** @var callable handler for sending emails */
public $mailer;
/** @var BlueScreen */
private $blueScreen;
public function __construct($directory, $email = NULL, BlueScreen $blueScreen = NULL)
{
$this->directory = $directory;
$this->email = $email;
$this->blueScreen = $blueScreen;
$this->mailer = [$this, 'defaultMailer'];
}
/**
* Logs message or exception to file and sends email notification.
* @param string|\Exception|\Throwable
* @param int one of constant ILogger::INFO, WARNING, ERROR (sends email), EXCEPTION (sends email), CRITICAL (sends email)
* @return string logged error filename
*/
public function log($message, $priority = self::INFO)
{
if (!$this->directory) {
throw new \LogicException('Directory is not specified.');
} elseif (!is_dir($this->directory)) {
throw new \RuntimeException("Directory '$this->directory' is not found or is not directory.");
}
$exceptionFile = $message instanceof \Exception || $message instanceof \Throwable
? $this->getExceptionFile($message)
: NULL;
$line = $this->formatLogLine($message, $exceptionFile);
$file = $this->directory . '/' . strtolower($priority ?: self::INFO) . '.log';
if (!@file_put_contents($file, $line . PHP_EOL, FILE_APPEND | LOCK_EX)) { // @ is escalated to exception
throw new \RuntimeException("Unable to write to log file '$file'. Is directory writable?");
}
if ($exceptionFile) {
$this->logException($message, $exceptionFile);
}
if (in_array($priority, [self::ERROR, self::EXCEPTION, self::CRITICAL], TRUE)) {
$this->sendEmail($message);
}
return $exceptionFile;
}
/**
* @param string|\Exception|\Throwable
* @return string
*/
protected function formatMessage($message)
{
if ($message instanceof \Exception || $message instanceof \Throwable) {
while ($message) {
$tmp[] = ($message instanceof \ErrorException
? Helpers::errorTypeToString($message->getSeverity()) . ': ' . $message->getMessage()
: Helpers::getClass($message) . ': ' . $message->getMessage()
) . ' in ' . $message->getFile() . ':' . $message->getLine();
$message = $message->getPrevious();
}
$message = implode($tmp, "\ncaused by ");
} elseif (!is_string($message)) {
$message = Dumper::toText($message);
}
return trim($message);
}
/**
* @param string|\Exception|\Throwable
* @return string
*/
protected function formatLogLine($message, $exceptionFile = NULL)
{
return implode(' ', [
@date('[Y-m-d H-i-s]'), // @ timezone may not be set
preg_replace('#\s*\r?\n\s*#', ' ', $this->formatMessage($message)),
' @ ' . Helpers::getSource(),
$exceptionFile ? ' @@ ' . basename($exceptionFile) : NULL,
]);
}
/**
* @param \Exception|\Throwable
* @return string
*/
public function getExceptionFile($exception)
{
$dir = strtr($this->directory . '/', '\\/', DIRECTORY_SEPARATOR . DIRECTORY_SEPARATOR);
$hash = substr(md5(preg_replace('~(Resource id #)\d+~', '$1', $exception)), 0, 10);
foreach (new \DirectoryIterator($this->directory) as $file) {
if (strpos($file, $hash)) {
return $dir . $file;
}
}
return $dir . 'exception--' . @date('Y-m-d--H-i') . "--$hash.html"; // @ timezone may not be set
}
/**
* Logs exception to the file if file doesn't exist.
* @param \Exception|\Throwable
* @return string logged error filename
*/
protected function logException($exception, $file = NULL)
{
$file = $file ?: $this->getExceptionFile($exception);
$bs = $this->blueScreen ?: new BlueScreen;
$bs->renderToFile($exception, $file);
return $file;
}
/**
* @param string|\Exception|\Throwable
* @return void
*/
protected function sendEmail($message)
{
$snooze = is_numeric($this->emailSnooze)
? $this->emailSnooze
: @strtotime($this->emailSnooze) - time(); // @ timezone may not be set
if ($this->email && $this->mailer
&& @filemtime($this->directory . '/email-sent') + $snooze < time() // @ file may not exist
&& @file_put_contents($this->directory . '/email-sent', 'sent') // @ file may not be writable
) {
call_user_func($this->mailer, $message, implode(', ', (array) $this->email));
}
}
/**
* Default mailer.
* @param string|\Exception|\Throwable
* @param string
* @return void
* @internal
*/
public function defaultMailer($message, $email)
{
$host = preg_replace('#[^\w.-]+#', '', isset($_SERVER['HTTP_HOST']) ? $_SERVER['HTTP_HOST'] : php_uname('n'));
$parts = str_replace(
["\r\n", "\n"],
["\n", PHP_EOL],
[
'headers' => implode("\n", [
'From: ' . ($this->fromEmail ?: "noreply@$host"),
'X-Mailer: Tracy',
'Content-Type: text/plain; charset=UTF-8',
'Content-Transfer-Encoding: 8bit',
]) . "\n",
'subject' => "PHP: An error occurred on the server $host",
'body' => $this->formatMessage($message) . "\n\nsource: " . Helpers::getSource(),
]
);
mail($email, $parts['subject'], $parts['body'], $parts['headers']);
}
}
|