migrate therinaldos.com data
Build & Deploy to DigitalOcean Space / build (push) Failing after 2m38s

This commit is contained in:
2024-05-05 15:50:45 -04:00
commit ef1ff240d4
23182 changed files with 3801898 additions and 0 deletions
@@ -0,0 +1,103 @@
<?php
declare(strict_types=1);
/**
* @copyright Copyright (c) 2016, ownCloud, Inc.
*
* @author Bart Visscher <bartv@thisnet.nl>
* @author Björn Schießle <bjoern@schiessle.org>
* @author Christoph Wurst <christoph@winzerhof-wurst.at>
* @author Joas Schilling <coding@schilljs.com>
* @author Julius Härtl <jus@bitgrid.net>
* @author Morris Jobke <hey@morrisjobke.de>
* @author Thomas Müller <thomas.mueller@tmit.eu>
*
* @license AGPL-3.0
*
* This code is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License, version 3,
* as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License, version 3,
* along with this program. If not, see <http://www.gnu.org/licenses/>
*
*/
namespace OC\Log;
use Error;
use OCP\ILogger;
use Psr\Log\LoggerInterface;
use Throwable;
class ErrorHandler {
public function __construct(
private LoggerInterface $logger,
) {
}
/**
* Remove password in URLs
*/
private static function removePassword(string $msg): string {
return preg_replace('#//(.*):(.*)@#', '//xxx:xxx@', $msg);
}
/**
* Fatal errors handler
*/
public function onShutdown(): void {
$error = error_get_last();
if ($error) {
$msg = $error['message'] . ' at ' . $error['file'] . '#' . $error['line'];
$this->logger->critical(self::removePassword($msg), ['app' => 'PHP']);
}
}
/**
* Uncaught exception handler
*/
public function onException(Throwable $exception): void {
$class = get_class($exception);
$msg = $exception->getMessage();
$msg = "$class: $msg at " . $exception->getFile() . '#' . $exception->getLine();
$this->logger->critical(self::removePassword($msg), ['app' => 'PHP']);
}
/**
* Recoverable errors handler
*/
public function onError(int $number, string $message, string $file, int $line): bool {
if (!(error_reporting() & $number)) {
return true;
}
$msg = $message . ' at ' . $file . '#' . $line;
$e = new Error(self::removePassword($msg));
$this->logger->log(self::errnoToLogLevel($number), $e->getMessage(), ['app' => 'PHP']);
return true;
}
/**
* Recoverable handler which catch all errors, warnings and notices
*/
public function onAll(int $number, string $message, string $file, int $line): bool {
$msg = $message . ' at ' . $file . '#' . $line;
$e = new Error(self::removePassword($msg));
$this->logger->log(self::errnoToLogLevel($number), $e->getMessage(), ['app' => 'PHP']);
return true;
}
private static function errnoToLogLevel(int $errno): int {
return match ($errno) {
E_USER_WARNING => ILogger::WARN,
E_DEPRECATED, E_USER_DEPRECATED => ILogger::DEBUG,
E_USER_NOTICE => ILogger::INFO,
default => ILogger::ERROR,
};
}
}
+50
View File
@@ -0,0 +1,50 @@
<?php
declare(strict_types=1);
/**
* The MIT License (MIT)
*
* Copyright (c) 2014 Christian Kampka <christian@kampka.net>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
namespace OC\Log;
use OC\SystemConfig;
use OCP\Log\IWriter;
class Errorlog extends LogDetails implements IWriter {
public function __construct(
SystemConfig $config,
protected string $tag = 'nextcloud',
) {
parent::__construct($config);
}
/**
* Write a message in the log
*
* @param string|array $message
*/
public function write(string $app, $message, int $level): void {
error_log('[' . $this->tag . ']['.$app.']['.$level.'] '.$this->logDetailsAsJSON($app, $message, $level));
}
}
@@ -0,0 +1,307 @@
<?php
/**
* @copyright Copyright (c) 2018 Robin Appelman <robin@icewind.nl>
*
* @author Arthur Schiwon <blizzz@arthur-schiwon.de>
* @author Christoph Wurst <christoph@winzerhof-wurst.at>
* @author Joas Schilling <coding@schilljs.com>
* @author Morris Jobke <hey@morrisjobke.de>
* @author Robin Appelman <robin@icewind.nl>
* @author Roeland Jago Douma <roeland@famdouma.nl>
* @author Vincent Petry <vincent@nextcloud.com>
*
* @license GNU AGPL version 3 or any later version
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
namespace OC\Log;
use OC\Core\Controller\SetupController;
use OC\Security\IdentityProof\Key;
use OC\Setup;
use OC\SystemConfig;
use OCA\Encryption\Controller\RecoveryController;
use OCA\Encryption\Controller\SettingsController;
use OCA\Encryption\Crypto\Crypt;
use OCA\Encryption\Crypto\Encryption;
use OCA\Encryption\Hooks\UserHooks;
use OCA\Encryption\KeyManager;
use OCA\Encryption\Session;
use OCP\HintException;
class ExceptionSerializer {
public const SENSITIVE_VALUE_PLACEHOLDER = '*** sensitive parameters replaced ***';
public const methodsWithSensitiveParameters = [
// Session/User
'completeLogin',
'login',
'checkPassword',
'checkPasswordNoLogging',
'loginWithPassword',
'updatePrivateKeyPassword',
'validateUserPass',
'loginWithToken',
'{closure}',
'createSessionToken',
// Provisioning
'addUser',
// TokenProvider
'getToken',
'isTokenPassword',
'getPassword',
'decryptPassword',
'logClientIn',
'generateToken',
'validateToken',
// TwoFactorAuth
'solveChallenge',
'verifyChallenge',
// ICrypto
'calculateHMAC',
'encrypt',
'decrypt',
// LoginController
'tryLogin',
'confirmPassword',
// LDAP
'bind',
'areCredentialsValid',
'invokeLDAPMethod',
// Encryption
'storeKeyPair',
'setupUser',
'checkSignature',
// files_external: OCA\Files_External\MountConfig
'getBackendStatus',
// files_external: UserStoragesController
'update',
// Preview providers, don't log big data strings
'imagecreatefromstring',
// text: PublicSessionController, SessionController and ApiService
'create',
'close',
'push',
'sync',
'updateSession',
'mention',
'loginSessionUser',
];
public function __construct(
private SystemConfig $systemConfig,
) {
}
protected array $methodsWithSensitiveParametersByClass = [
SetupController::class => [
'run',
'display',
'loadAutoConfig',
],
Setup::class => [
'install'
],
Key::class => [
'__construct'
],
\Redis::class => [
'auth'
],
\RedisCluster::class => [
'__construct'
],
Crypt::class => [
'symmetricEncryptFileContent',
'encrypt',
'generatePasswordHash',
'encryptPrivateKey',
'decryptPrivateKey',
'isValidPrivateKey',
'symmetricDecryptFileContent',
'checkSignature',
'createSignature',
'decrypt',
'multiKeyDecrypt',
'multiKeyEncrypt',
],
RecoveryController::class => [
'adminRecovery',
'changeRecoveryPassword'
],
SettingsController::class => [
'updatePrivateKeyPassword',
],
Encryption::class => [
'encrypt',
'decrypt',
],
KeyManager::class => [
'checkRecoveryPassword',
'storeKeyPair',
'setRecoveryKey',
'setPrivateKey',
'setFileKey',
'setAllFileKeys',
],
Session::class => [
'setPrivateKey',
'prepareDecryptAll',
],
\OCA\Encryption\Users\Setup::class => [
'setupUser',
],
UserHooks::class => [
'login',
'postCreateUser',
'postDeleteUser',
'prePasswordReset',
'postPasswordReset',
'preSetPassphrase',
'setPassphrase',
],
];
private function editTrace(array &$sensitiveValues, array $traceLine): array {
if (isset($traceLine['args'])) {
$sensitiveValues = array_merge($sensitiveValues, $traceLine['args']);
}
$traceLine['args'] = [self::SENSITIVE_VALUE_PLACEHOLDER];
return $traceLine;
}
private function filterTrace(array $trace) {
$sensitiveValues = [];
$trace = array_map(function (array $traceLine) use (&$sensitiveValues) {
$className = $traceLine['class'] ?? '';
if ($className && isset($this->methodsWithSensitiveParametersByClass[$className])
&& in_array($traceLine['function'], $this->methodsWithSensitiveParametersByClass[$className], true)) {
return $this->editTrace($sensitiveValues, $traceLine);
}
foreach (self::methodsWithSensitiveParameters as $sensitiveMethod) {
if (str_contains($traceLine['function'], $sensitiveMethod)) {
return $this->editTrace($sensitiveValues, $traceLine);
}
}
return $traceLine;
}, $trace);
return array_map(function (array $traceLine) use ($sensitiveValues) {
if (isset($traceLine['args'])) {
$traceLine['args'] = $this->removeValuesFromArgs($traceLine['args'], $sensitiveValues);
}
return $traceLine;
}, $trace);
}
private function removeValuesFromArgs($args, $values): array {
$workArgs = [];
foreach ($args as $arg) {
if (in_array($arg, $values, true)) {
$arg = self::SENSITIVE_VALUE_PLACEHOLDER;
} elseif (is_array($arg)) {
$arg = $this->removeValuesFromArgs($arg, $values);
}
$workArgs[] = $arg;
}
return $workArgs;
}
private function encodeTrace($trace) {
$trace = array_map(function (array $line) {
if (isset($line['args'])) {
$line['args'] = array_map([$this, 'encodeArg'], $line['args']);
}
return $line;
}, $trace);
return $this->filterTrace($trace);
}
private function encodeArg($arg, $nestingLevel = 5) {
if (is_object($arg)) {
if ($nestingLevel === 0) {
return [
'__class__' => get_class($arg),
'__properties__' => 'Encoding skipped as the maximum nesting level was reached',
];
}
$objectInfo = [ '__class__' => get_class($arg) ];
$objectVars = get_object_vars($arg);
return array_map(function ($arg) use ($nestingLevel) {
return $this->encodeArg($arg, $nestingLevel - 1);
}, array_merge($objectInfo, $objectVars));
}
if (is_array($arg)) {
if ($nestingLevel === 0) {
return ['Encoding skipped as the maximum nesting level was reached'];
}
// Only log the first 5 elements of an array unless we are on debug
if ((int)$this->systemConfig->getValue('loglevel', 2) !== 0) {
$elemCount = count($arg);
if ($elemCount > 5) {
$arg = array_slice($arg, 0, 5);
$arg[] = 'And ' . ($elemCount - 5) . ' more entries, set log level to debug to see all entries';
}
}
return array_map(function ($e) use ($nestingLevel) {
return $this->encodeArg($e, $nestingLevel - 1);
}, $arg);
}
return $arg;
}
public function serializeException(\Throwable $exception): array {
$data = [
'Exception' => get_class($exception),
'Message' => $exception->getMessage(),
'Code' => $exception->getCode(),
'Trace' => $this->encodeTrace($exception->getTrace()),
'File' => $exception->getFile(),
'Line' => $exception->getLine(),
];
if ($exception instanceof HintException) {
$data['Hint'] = $exception->getHint();
}
if ($exception->getPrevious()) {
$data['Previous'] = $this->serializeException($exception->getPrevious());
}
return $data;
}
public function enlistSensitiveMethods(string $class, array $methods): void {
if (!isset($this->methodsWithSensitiveParametersByClass[$class])) {
$this->methodsWithSensitiveParametersByClass[$class] = [];
}
$this->methodsWithSensitiveParametersByClass[$class] = array_merge($this->methodsWithSensitiveParametersByClass[$class], $methods);
}
}
+149
View File
@@ -0,0 +1,149 @@
<?php
/**
* @copyright Copyright (c) 2016, ownCloud, Inc.
*
* @author Arthur Schiwon <blizzz@arthur-schiwon.de>
* @author Bart Visscher <bartv@thisnet.nl>
* @author Christoph Wurst <christoph@winzerhof-wurst.at>
* @author duritong <peter.meier+github@immerda.ch>
* @author Georg Ehrke <oc.list@georgehrke.com>
* @author J0WI <J0WI@users.noreply.github.com>
* @author Joas Schilling <coding@schilljs.com>
* @author Julius Härtl <jus@bitgrid.net>
* @author Lukas Reschke <lukas@statuscode.ch>
* @author Michael Gapczynski <GapczynskiM@gmail.com>
* @author Morris Jobke <hey@morrisjobke.de>
* @author Robin Appelman <robin@icewind.nl>
* @author Roeland Jago Douma <roeland@famdouma.nl>
* @author Roland Tapken <roland@bitarbeiter.net>
* @author Thomas Müller <thomas.mueller@tmit.eu>
* @author Thomas Pulzer <t.pulzer@kniel.de>
*
* @license AGPL-3.0
*
* This code is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License, version 3,
* as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License, version 3,
* along with this program. If not, see <http://www.gnu.org/licenses/>
*
*/
namespace OC\Log;
use OC\SystemConfig;
use OCP\ILogger;
use OCP\Log\IFileBased;
use OCP\Log\IWriter;
/**
* logging utilities
*
* Log is saved at data/nextcloud.log (on default)
*/
class File extends LogDetails implements IWriter, IFileBased {
protected string $logFile;
protected int $logFileMode;
public function __construct(
string $path,
string $fallbackPath,
private SystemConfig $config,
) {
parent::__construct($config);
$this->logFile = $path;
if (!file_exists($this->logFile)) {
if (
(
!is_writable(dirname($this->logFile))
|| !touch($this->logFile)
)
&& $fallbackPath !== ''
) {
$this->logFile = $fallbackPath;
}
}
$this->logFileMode = $config->getValue('logfilemode', 0640);
}
/**
* write a message in the log
* @param string|array $message
*/
public function write(string $app, $message, int $level): void {
$entry = $this->logDetailsAsJSON($app, $message, $level);
$handle = @fopen($this->logFile, 'a');
if ($this->logFileMode > 0 && is_file($this->logFile) && (fileperms($this->logFile) & 0777) != $this->logFileMode) {
@chmod($this->logFile, $this->logFileMode);
}
if ($handle) {
fwrite($handle, $entry."\n");
fclose($handle);
} else {
// Fall back to error_log
error_log($entry);
}
if (php_sapi_name() === 'cli-server') {
if (!\is_string($message)) {
$message = json_encode($message);
}
error_log($message, 4);
}
}
/**
* get entries from the log in reverse chronological order
*/
public function getEntries(int $limit = 50, int $offset = 0): array {
$minLevel = $this->config->getValue("loglevel", ILogger::WARN);
$entries = [];
$handle = @fopen($this->logFile, 'rb');
if ($handle) {
fseek($handle, 0, SEEK_END);
$pos = ftell($handle);
$line = '';
$entriesCount = 0;
$lines = 0;
// Loop through each character of the file looking for new lines
while ($pos >= 0 && ($limit === null || $entriesCount < $limit)) {
fseek($handle, $pos);
$ch = fgetc($handle);
if ($ch == "\n" || $pos == 0) {
if ($line != '') {
// Add the first character if at the start of the file,
// because it doesn't hit the else in the loop
if ($pos == 0) {
$line = $ch.$line;
}
$entry = json_decode($line);
// Add the line as an entry if it is passed the offset and is equal or above the log level
if ($entry->level >= $minLevel) {
$lines++;
if ($lines > $offset) {
$entries[] = $entry;
$entriesCount++;
}
}
$line = '';
}
} else {
$line = $ch.$line;
}
$pos--;
}
fclose($handle);
}
return $entries;
}
public function getLogFilePath():string {
return $this->logFile;
}
}
+115
View File
@@ -0,0 +1,115 @@
<?php
/**
* @copyright Copyright (c) 2019 Julius Härtl <jus@bitgrid.net>
*
* @author Arthur Schiwon <blizzz@arthur-schiwon.de>
* @author Christoph Wurst <christoph@winzerhof-wurst.at>
* @author Julius Härtl <jus@bitgrid.net>
* @author Thomas Citharel <nextcloud@tcit.fr>
*
* @license GNU AGPL version 3 or any later version
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
namespace OC\Log;
use OC\SystemConfig;
abstract class LogDetails {
public function __construct(
private SystemConfig $config,
) {
}
public function logDetails(string $app, $message, int $level): array {
// default to ISO8601
$format = $this->config->getValue('logdateformat', \DateTimeInterface::ATOM);
$logTimeZone = $this->config->getValue('logtimezone', 'UTC');
try {
$timezone = new \DateTimeZone($logTimeZone);
} catch (\Exception $e) {
$timezone = new \DateTimeZone('UTC');
}
$time = \DateTime::createFromFormat("U.u", number_format(microtime(true), 4, ".", ""));
if ($time === false) {
$time = new \DateTime('now', $timezone);
} else {
// apply timezone if $time is created from UNIX timestamp
$time->setTimezone($timezone);
}
$request = \OC::$server->getRequest();
$reqId = $request->getId();
$remoteAddr = $request->getRemoteAddress();
// remove username/passwords from URLs before writing the to the log file
$time = $time->format($format);
$url = ($request->getRequestUri() !== '') ? $request->getRequestUri() : '--';
$method = is_string($request->getMethod()) ? $request->getMethod() : '--';
if ($this->config->getValue('installed', false)) {
$user = \OC_User::getUser() ? \OC_User::getUser() : '--';
} else {
$user = '--';
}
$userAgent = $request->getHeader('User-Agent');
if ($userAgent === '') {
$userAgent = '--';
}
$version = $this->config->getValue('version', '');
$entry = compact(
'reqId',
'level',
'time',
'remoteAddr',
'user',
'app',
'method',
'url',
'message',
'userAgent',
'version'
);
if (is_array($message)) {
// Exception messages are extracted and the exception is put into a separate field
// anything else modern is split to 'message' (string) and
// data (array) fields
if (array_key_exists('Exception', $message)) {
$entry['exception'] = $message;
$entry['message'] = $message['CustomMessage'] !== '--' ? $message['CustomMessage'] : $message['Message'];
} else {
$entry['message'] = $message['message'] ?? '(no message provided)';
unset($message['message']);
$entry['data'] = $message;
}
}
return $entry;
}
public function logDetailsAsJSON(string $app, $message, int $level): string {
$entry = $this->logDetails($app, $message, $level);
// PHP's json_encode only accept proper UTF-8 strings, loop over all
// elements to ensure that they are properly UTF-8 compliant or convert
// them manually.
foreach ($entry as $key => $value) {
if (is_string($value)) {
$testEncode = json_encode($value, JSON_UNESCAPED_SLASHES);
if ($testEncode === false) {
$entry[$key] = mb_convert_encoding($value, 'UTF-8', mb_detect_encoding($value));
}
}
}
return json_encode($entry, JSON_PARTIAL_OUTPUT_ON_ERROR | JSON_UNESCAPED_SLASHES);
}
}
@@ -0,0 +1,85 @@
<?php
/**
* @copyright Copyright (c) 2018 Arthur Schiwon <blizzz@arthur-schiwon.de>
*
* @author Arthur Schiwon <blizzz@arthur-schiwon.de>
* @author Christoph Wurst <christoph@winzerhof-wurst.at>
* @author Johannes Ernst <jernst@indiecomputing.com>
*
* @license GNU AGPL version 3 or any later version
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
namespace OC\Log;
use OC\Log;
use OC\SystemConfig;
use OCP\ILogger;
use OCP\IServerContainer;
use OCP\Log\ILogFactory;
use OCP\Log\IWriter;
use Psr\Log\LoggerInterface;
class LogFactory implements ILogFactory {
public function __construct(
private IServerContainer $c,
private SystemConfig $systemConfig,
) {
}
/**
* @throws \OCP\AppFramework\QueryException
*/
public function get(string $type):IWriter {
return match (strtolower($type)) {
'errorlog' => new Errorlog($this->systemConfig),
'syslog' => $this->c->resolve(Syslog::class),
'systemd' => $this->c->resolve(Systemdlog::class),
'file' => $this->buildLogFile(),
default => $this->buildLogFile(),
};
}
public function getCustomLogger(string $path): ILogger {
$log = $this->buildLogFile($path);
return new Log($log, $this->systemConfig);
}
protected function createNewLogger(string $type, string $tag, string $path): IWriter {
return match (strtolower($type)) {
'errorlog' => new Errorlog($this->systemConfig, $tag),
'syslog' => new Syslog($this->systemConfig, $tag),
'systemd' => new Systemdlog($this->systemConfig, $tag),
default => $this->buildLogFile($path),
};
}
public function getCustomPsrLogger(string $path, string $type = 'file', string $tag = 'Nextcloud'): LoggerInterface {
$log = $this->createNewLogger($type, $tag, $path);
return new PsrLoggerAdapter(
new Log($log, $this->systemConfig)
);
}
protected function buildLogFile(string $logFile = ''): File {
$defaultLogFile = $this->systemConfig->getValue('datadirectory', \OC::$SERVERROOT.'/data').'/nextcloud.log';
if ($logFile === '') {
$logFile = $this->systemConfig->getValue('logfile', $defaultLogFile);
}
$fallback = $defaultLogFile !== $logFile ? $defaultLogFile : '';
return new File($logFile, $fallback, $this->systemConfig);
}
}
@@ -0,0 +1,243 @@
<?php
declare(strict_types=1);
/**
* @copyright 2020 Christoph Wurst <christoph@winzerhof-wurst.at>
*
* @author Christoph Wurst <christoph@winzerhof-wurst.at>
*
* @license GNU AGPL version 3 or any later version
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
namespace OC\Log;
use OC\Log;
use OCP\EventDispatcher\IEventDispatcher;
use OCP\ILogger;
use OCP\Log\IDataLogger;
use Psr\Log\InvalidArgumentException;
use Psr\Log\LoggerInterface;
use Throwable;
use function array_key_exists;
use function array_merge;
final class PsrLoggerAdapter implements LoggerInterface, IDataLogger {
public function __construct(
private Log $logger,
) {
}
public function setEventDispatcher(IEventDispatcher $eventDispatcher): void {
$this->logger->setEventDispatcher($eventDispatcher);
}
private function containsThrowable(array $context): bool {
return array_key_exists('exception', $context) && $context['exception'] instanceof Throwable;
}
/**
* System is unusable.
*
* @param string $message
*/
public function emergency($message, array $context = []): void {
if ($this->containsThrowable($context)) {
$this->logger->logException($context['exception'], array_merge(
[
'message' => $message,
'level' => ILogger::FATAL,
],
$context
));
} else {
$this->logger->emergency($message, $context);
}
}
/**
* Action must be taken immediately.
*
* Example: Entire website down, database unavailable, etc. This should
* trigger the SMS alerts and wake you up.
*
* @param string $message
*/
public function alert($message, array $context = []): void {
if ($this->containsThrowable($context)) {
$this->logger->logException($context['exception'], array_merge(
[
'message' => $message,
'level' => ILogger::ERROR,
],
$context
));
} else {
$this->logger->alert($message, $context);
}
}
/**
* Critical conditions.
*
* Example: Application component unavailable, unexpected exception.
*
* @param string $message
*/
public function critical($message, array $context = []): void {
if ($this->containsThrowable($context)) {
$this->logger->logException($context['exception'], array_merge(
[
'message' => $message,
'level' => ILogger::ERROR,
],
$context
));
} else {
$this->logger->critical($message, $context);
}
}
/**
* Runtime errors that do not require immediate action but should typically
* be logged and monitored.
*
* @param string $message
*/
public function error($message, array $context = []): void {
if ($this->containsThrowable($context)) {
$this->logger->logException($context['exception'], array_merge(
[
'message' => $message,
'level' => ILogger::ERROR,
],
$context
));
} else {
$this->logger->error($message, $context);
}
}
/**
* Exceptional occurrences that are not errors.
*
* Example: Use of deprecated APIs, poor use of an API, undesirable things
* that are not necessarily wrong.
*
* @param string $message
*/
public function warning($message, array $context = []): void {
if ($this->containsThrowable($context)) {
$this->logger->logException($context['exception'], array_merge(
[
'message' => $message,
'level' => ILogger::WARN,
],
$context
));
} else {
$this->logger->warning($message, $context);
}
}
/**
* Normal but significant events.
*
* @param string $message
*/
public function notice($message, array $context = []): void {
if ($this->containsThrowable($context)) {
$this->logger->logException($context['exception'], array_merge(
[
'message' => $message,
'level' => ILogger::INFO,
],
$context
));
} else {
$this->logger->notice($message, $context);
}
}
/**
* Interesting events.
*
* Example: User logs in, SQL logs.
*
* @param string $message
*/
public function info($message, array $context = []): void {
if ($this->containsThrowable($context)) {
$this->logger->logException($context['exception'], array_merge(
[
'message' => $message,
'level' => ILogger::INFO,
],
$context
));
} else {
$this->logger->info($message, $context);
}
}
/**
* Detailed debug information.
*
* @param string $message
*/
public function debug($message, array $context = []): void {
if ($this->containsThrowable($context)) {
$this->logger->logException($context['exception'], array_merge(
[
'message' => $message,
'level' => ILogger::DEBUG,
],
$context
));
} else {
$this->logger->debug($message, $context);
}
}
/**
* Logs with an arbitrary level.
*
* @param mixed $level
* @param string $message
*
* @throws InvalidArgumentException
*/
public function log($level, $message, array $context = []): void {
if (!is_int($level) || $level < ILogger::DEBUG || $level > ILogger::FATAL) {
throw new InvalidArgumentException('Nextcloud allows only integer log levels');
}
if ($this->containsThrowable($context)) {
$this->logger->logException($context['exception'], array_merge(
[
'message' => $message,
'level' => $level,
],
$context
));
} else {
$this->logger->log($level, $message, $context);
}
}
public function logData(string $message, array $data, array $context = []): void {
$this->logger->logData($message, $data, $context);
}
}
+49
View File
@@ -0,0 +1,49 @@
<?php
/**
* @copyright Copyright (c) 2016, ownCloud, Inc.
*
* @author Arthur Schiwon <blizzz@arthur-schiwon.de>
* @author Bart Visscher <bartv@thisnet.nl>
* @author Christoph Wurst <christoph@winzerhof-wurst.at>
* @author Robin Appelman <robin@icewind.nl>
*
* @license AGPL-3.0
*
* This code is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License, version 3,
* as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License, version 3,
* along with this program. If not, see <http://www.gnu.org/licenses/>
*
*/
namespace OC\Log;
use OCP\Log\RotationTrait;
/**
* This rotates the current logfile to a new name, this way the total log usage
* will stay limited and older entries are available for a while longer.
* For more professional log management set the 'logfile' config to a different
* location and manage that with your own tools.
*/
class Rotate extends \OCP\BackgroundJob\Job {
use RotationTrait;
public function run($dummy): void {
$systemConfig = \OC::$server->getSystemConfig();
$this->filePath = $systemConfig->getValue('logfile', $systemConfig->getValue('datadirectory', \OC::$SERVERROOT . '/data') . '/nextcloud.log');
$this->maxSize = \OC::$server->getConfig()->getSystemValueInt('log_rotate_size', 100 * 1024 * 1024);
if ($this->shouldRotateBySize()) {
$rotatedFile = $this->rotate();
$msg = 'Log file "'.$this->filePath.'" was over '.$this->maxSize.' bytes, moved to "'.$rotatedFile.'"';
\OC::$server->getLogger()->info($msg, ['app' => Rotate::class]);
}
}
}
+64
View File
@@ -0,0 +1,64 @@
<?php
/**
* @copyright Copyright (c) 2016, ownCloud, Inc.
*
* @author Arthur Schiwon <blizzz@arthur-schiwon.de>
* @author Bart Visscher <bartv@thisnet.nl>
* @author Julius Härtl <jus@bitgrid.net>
* @author Roeland Jago Douma <roeland@famdouma.nl>
* @author Thomas Müller <thomas.mueller@tmit.eu>
*
* @license AGPL-3.0
*
* This code is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License, version 3,
* as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License, version 3,
* along with this program. If not, see <http://www.gnu.org/licenses/>
*
*/
namespace OC\Log;
use OC\SystemConfig;
use OCP\ILogger;
use OCP\Log\IWriter;
class Syslog extends LogDetails implements IWriter {
protected array $levels = [
ILogger::DEBUG => LOG_DEBUG,
ILogger::INFO => LOG_INFO,
ILogger::WARN => LOG_WARNING,
ILogger::ERROR => LOG_ERR,
ILogger::FATAL => LOG_CRIT,
];
public function __construct(
SystemConfig $config,
?string $tag = null,
) {
parent::__construct($config);
if ($tag === null) {
$tag = $config->getValue('syslog_tag', 'Nextcloud');
}
openlog($tag, LOG_PID | LOG_CONS, LOG_USER);
}
public function __destruct() {
closelog();
}
/**
* write a message in the log
* @param string|array $message
*/
public function write(string $app, $message, int $level): void {
$syslog_level = $this->levels[$level];
syslog($syslog_level, $this->logDetailsAsJSON($app, $message, $level));
}
}
@@ -0,0 +1,85 @@
<?php
/**
* @copyright Copyright (c) 2018, Johannes Ernst
*
* @author Christoph Wurst <christoph@winzerhof-wurst.at>
* @author Johannes Ernst <jernst@indiecomputing.com>
* @author Julius Härtl <jus@bitgrid.net>
* @author Roeland Jago Douma <roeland@famdouma.nl>
*
* @license GNU AGPL version 3 or any later version
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
namespace OC\Log;
use OC\SystemConfig;
use OCP\HintException;
use OCP\ILogger;
use OCP\Log\IWriter;
// The following fields are understood by systemd/journald, see
// man systemd.journal-fields. All are optional:
// MESSAGE=
// The human-readable message string for this entry.
// MESSAGE_ID=
// A 128-bit message identifier ID
// PRIORITY=
// A priority value between 0 ("emerg") and 7 ("debug")
// CODE_FILE=, CODE_LINE=, CODE_FUNC=
// The code location generating this message, if known
// ERRNO=
// The low-level Unix error number causing this entry, if any.
// SYSLOG_FACILITY=, SYSLOG_IDENTIFIER=, SYSLOG_PID=
// Syslog compatibility fields
class Systemdlog extends LogDetails implements IWriter {
protected array $levels = [
ILogger::DEBUG => 7,
ILogger::INFO => 6,
ILogger::WARN => 4,
ILogger::ERROR => 3,
ILogger::FATAL => 2,
];
protected string $syslogId;
public function __construct(
SystemConfig $config,
?string $tag = null,
) {
parent::__construct($config);
if (!function_exists('sd_journal_send')) {
throw new HintException(
'PHP extension php-systemd is not available.',
'Please install and enable PHP extension systemd if you wish to log to the Systemd journal.');
}
if ($tag === null) {
$tag = $config->getValue('syslog_tag', 'Nextcloud');
}
$this->syslogId = $tag;
}
/**
* Write a message to the log.
* @param string|array $message
*/
public function write(string $app, $message, int $level): void {
$journal_level = $this->levels[$level];
sd_journal_send('PRIORITY='.$journal_level,
'SYSLOG_IDENTIFIER='.$this->syslogId,
'MESSAGE=' . $this->logDetailsAsJSON($app, $message, $level));
}
}