]> git.mxchange.org Git - friendica.git/commitdiff
Add checks & realpath() usage
authorPhilipp Holzer <admin+github@philipp.info>
Tue, 22 Oct 2019 20:47:37 +0000 (22:47 +0200)
committerPhilipp Holzer <admin+github@philipp.info>
Tue, 22 Oct 2019 20:47:37 +0000 (22:47 +0200)
- New util class "FileSystem"
- Add check in admin summary too

src/Factory/LoggerFactory.php
src/Module/Admin/Summary.php
src/Util/FileSystem.php [new file with mode: 0644]
src/Util/Logger/StreamLogger.php
tests/src/Util/Logger/StreamLoggerTest.php

index b25d358387a9ce0342f04bf77e0527741383d19f..d177faf7a93081941ba99998d6ec9d36516bd31b 100644 (file)
@@ -6,6 +6,7 @@ use Friendica\Core\Config\Configuration;
 use Friendica\Core\Logger;
 use Friendica\Database\Database;
 use Friendica\Network\HTTPException\InternalServerErrorException;
+use Friendica\Util\FileSystem;
 use Friendica\Util\Introspection;
 use Friendica\Util\Logger\Monolog\DevelopHandler;
 use Friendica\Util\Logger\Monolog\IntrospectionProcessor;
@@ -51,10 +52,11 @@ class LoggerFactory
         * @param Database      $database The Friendica Database instance
         * @param Configuration $config   The config
         * @param Profiler      $profiler The profiler of the app
+        * @param FileSystem    $fileSystem FileSystem utils
         *
         * @return LoggerInterface The PSR-3 compliant logger instance
         */
-       public function create( Database $database, Configuration $config, Profiler $profiler)
+       public function create(Database $database, Configuration $config, Profiler $profiler, FileSystem $fileSystem)
        {
                if (empty($config->get('system', 'debugging', false))) {
                        $logger = new VoidLogger();
@@ -105,7 +107,7 @@ class LoggerFactory
                                // just add a stream in case it's either writable or not file
                                if (!is_file($stream) || is_writable($stream)) {
                                        try {
-                                               $logger = new StreamLogger($this->channel, $stream, $introspection, $loglevel);
+                                               $logger = new StreamLogger($this->channel, $stream, $introspection, $fileSystem, $loglevel);
                                        } catch (\Throwable $t) {
                                                // No logger ...
                                                $logger = new VoidLogger();
@@ -137,13 +139,14 @@ class LoggerFactory
         *
         * @param Configuration $config   The config
         * @param Profiler      $profiler The profiler of the app
+        * @param FileSystem    $fileSystem FileSystem utils
         *
         * @return LoggerInterface The PSR-3 compliant logger instance
         *
         * @throws InternalServerErrorException
         * @throws \Exception
         */
-       public static function createDev(Configuration $config, Profiler $profiler)
+       public static function createDev(Configuration $config, Profiler $profiler, FileSystem $fileSystem)
        {
                $debugging   = $config->get('system', 'debugging');
                $stream      = $config->get('system', 'dlogfile');
@@ -183,7 +186,7 @@ class LoggerFactory
 
                        case 'stream':
                        default:
-                               $logger = new StreamLogger(self::DEV_CHANNEL, $stream, $introspection, LogLevel::DEBUG);
+                               $logger = new StreamLogger(self::DEV_CHANNEL, $stream, $introspection, $fileSystem, LogLevel::DEBUG);
                                break;
                }
 
@@ -225,7 +228,7 @@ class LoggerFactory
                        case "5":
                        // legacy ALL
                        case "4":
-                       return LogLevel::DEBUG;
+                               return LogLevel::DEBUG;
                        // default if nothing set
                        default:
                                return $level;
index d0bb4347a17ae016a6596e84b1112858bd941893..e1952f294b0207b7a98ad1b62878e88d8c5a9b9e 100644 (file)
@@ -14,6 +14,7 @@ use Friendica\Model\Register;
 use Friendica\Module\BaseAdminModule;
 use Friendica\Util\ConfigFileLoader;
 use Friendica\Util\DateTimeFormat;
+use Friendica\Util\FileSystem;
 use Friendica\Util\Network;
 
 class Summary extends BaseAdminModule
@@ -76,11 +77,21 @@ class Summary extends BaseAdminModule
 
                // Check logfile permission
                if (Config::get('system', 'debugging')) {
-                       $stream = Config::get('system', 'logfile');
+                       $file = Config::get('system', 'logfile');
 
-                       if (is_file($stream) &&
-                           !is_writeable($stream)) {
-                               $warningtext[] = L10n::t('The logfile \'%s\' is not writable. No logging possible', $stream);
+                       /** @var FileSystem $fileSystem */
+                       $fileSystem = self::getClass(FileSystem::class);
+
+                       try {
+                               $stream = $fileSystem->createStream($file);
+
+                               if (is_file($stream) &&
+                                   !is_writeable($stream)) {
+                                       $warningtext[] = L10n::t('The logfile \'%s\' is not writable. No logging possible', $stream);
+                               }
+
+                       } catch (\Throwable $exception) {
+                               $warningtext[] = L10n::t('The logfile \'%s\' is not usable. No logging possible (error: \'%s\')', $file, $exception->getMessage());
                        }
 
                        $stream = Config::get('system', 'dlogfile');
diff --git a/src/Util/FileSystem.php b/src/Util/FileSystem.php
new file mode 100644 (file)
index 0000000..33e0478
--- /dev/null
@@ -0,0 +1,64 @@
+<?php
+
+namespace Friendica\Util;
+
+final class FileSystem
+{
+       /**
+        * @var string a error message
+        */
+       private $errorMessage;
+
+       public function createDir(string $file)
+       {
+               $dirname = null;
+               $pos = strpos($file, '://');
+
+               if (!$pos) {
+                       $dirname = realpath(dirname($file));
+               }
+
+               if (substr($file, 0, 7) === 'file://') {
+                       $dirname = realpath(dirname(substr($file, 7)));
+               }
+
+               if (isset($dirname) && !is_dir($dirname)) {
+                       set_error_handler([$this, 'customErrorHandler']);
+                       $status = mkdir($dirname, 0777, true);
+                       restore_error_handler();
+
+                       if (!$status && !is_dir($dirname)) {
+                               throw new \UnexpectedValueException(sprintf('Directory "%s" cannot get created: ' . $this->errorMessage, $dirname));
+                       }
+
+                       return $dirname;
+               } elseif (isset($dirname) && is_dir($dirname)) {
+                       return $dirname;
+               } else {
+                       return '';
+               }
+       }
+
+       public function createStream(string $url)
+       {
+               $directory = $this->createDir($url);
+               set_error_handler([$this, 'customErrorHandler']);
+               if (!empty($directory)) {
+                       $url = $directory . DIRECTORY_SEPARATOR . pathinfo($url, PATHINFO_BASENAME);
+               }
+
+               $stream = fopen($url, 'ab');
+               restore_error_handler();
+
+               if (!is_resource($stream)) {
+                       throw new \UnexpectedValueException(sprintf('The stream or file "%s" could not be opened: ' . $this->errorMessage, $url));
+               }
+
+               return $stream;
+       }
+
+       private function customErrorHandler($code, $msg)
+       {
+               $this->errorMessage = preg_replace('{^(fopen|mkdir)\(.*?\): }', '', $msg);
+       }
+}
index c9c245d63b352364ae94dc8e06e2ae7377cf9350..600da14fc26a24b3eb7bb7c6c1cded6cec74ed70 100644 (file)
@@ -3,6 +3,7 @@
 namespace Friendica\Util\Logger;
 
 use Friendica\Util\DateTimeFormat;
+use Friendica\Util\FileSystem;
 use Friendica\Util\Introspection;
 use Psr\Log\LogLevel;
 
@@ -35,11 +36,11 @@ class StreamLogger extends AbstractLogger
         */
        private $pid;
 
+
        /**
-        * An error message
-        * @var string
+        * @var FileSystem
         */
-       private $errorMessage;
+       private $fileSystem;
 
        /**
         * Translates LogLevel log levels to integer values
@@ -63,8 +64,10 @@ class StreamLogger extends AbstractLogger
         *
         * @throws \Exception
         */
-       public function __construct($channel, $stream, Introspection $introspection, $level = LogLevel::DEBUG)
+       public function __construct($channel, $stream, Introspection $introspection, FileSystem $fileSystem, $level = LogLevel::DEBUG)
        {
+               $this->fileSystem = $fileSystem;
+
                parent::__construct($channel, $introspection);
 
                if (is_resource($stream)) {
@@ -157,43 +160,6 @@ class StreamLogger extends AbstractLogger
                        throw new \LogicException('Missing stream URL.');
                }
 
-               $this->createDir();
-               set_error_handler([$this, 'customErrorHandler']);
-               $this->stream = fopen($this->url, 'ab');
-               restore_error_handler();
-
-               if (!is_resource($this->stream)) {
-                       $this->stream = null;
-
-                       throw new \UnexpectedValueException(sprintf('The stream or file "%s" could not be opened: ' . $this->errorMessage, $this->url));
-               }
-       }
-
-       private function createDir()
-       {
-               $dirname = null;
-               $pos = strpos($this->url, '://');
-               if (!$pos) {
-                       $dirname = dirname($this->url);
-               }
-
-               if (substr($this->url, 0, 7) === 'file://') {
-                       $dirname = dirname(substr($this->url, 7));
-               }
-
-               if (isset($dirname) && !is_dir($dirname)) {
-                       set_error_handler([$this, 'customErrorHandler']);
-                       $status = mkdir($dirname, 0777, true);
-                       restore_error_handler();
-
-                       if (!$status && !is_dir($dirname)) {
-                               throw new \UnexpectedValueException(sprintf('Directory "%s" cannot get created: ' . $this->errorMessage, $dirname));
-                       }
-               }
-       }
-
-       private function customErrorHandler($code, $msg)
-       {
-               $this->errorMessage = preg_replace('{^(fopen|mkdir)\(.*?\): }', '', $msg);
+               $this->stream = $this->fileSystem->createStream($this->url);
        }
 }
index d42ba1d914c2cfd36344de72f4bc3b1ecfbbddbc..7dcb08ba6df956dee79c951c3daa682df5e77d48 100644 (file)
@@ -2,6 +2,7 @@
 
 namespace Friendica\Test\src\Util\Logger;
 
+use Friendica\Util\FileSystem;
 use Friendica\Test\Util\VFSTrait;
 use Friendica\Util\Logger\StreamLogger;
 use org\bovigo\vfs\vfsStream;
@@ -22,11 +23,18 @@ class StreamLoggerTest extends AbstractLoggerTest
         */
        private $logfile;
 
+       /**
+        * @var Filesystem
+        */
+       private $fileSystem;
+
        protected function setUp()
        {
                parent::setUp();
 
                $this->setUpVfsDir();
+
+               $this->fileSystem = new Filesystem();
        }
 
        /**
@@ -37,7 +45,7 @@ class StreamLoggerTest extends AbstractLoggerTest
                $this->logfile = vfsStream::newFile('friendica.log')
                        ->at($this->root);
 
-               $this->logger = new StreamLogger('test', $this->logfile->url(), $this->introspection, $level);
+               $this->logger = new StreamLogger('test', $this->logfile->url(), $this->introspection, $this->fileSystem, $level);
 
                return $this->logger;
        }
@@ -60,7 +68,7 @@ class StreamLoggerTest extends AbstractLoggerTest
 
                $filehandler = fopen($logfile->url(), 'ab');
 
-               $logger = new StreamLogger('test', $filehandler, $this->introspection);
+               $logger = new StreamLogger('test', $filehandler, $this->introspection, $this->fileSystem);
                $logger->emergency('working');
 
                $text = $logfile->getContent();
@@ -76,7 +84,7 @@ class StreamLoggerTest extends AbstractLoggerTest
                $logfile = vfsStream::newFile('friendica.log')
                        ->at($this->root);
 
-               $logger = new StreamLogger('test', $logfile->url(), $this->introspection);
+               $logger = new StreamLogger('test', $logfile->url(), $this->introspection, $this->fileSystem);
                $logger->emergency('working');
                $logger->close();
                // close doesn't affect
@@ -94,7 +102,7 @@ class StreamLoggerTest extends AbstractLoggerTest
         */
        public function testNoUrl()
        {
-               $logger = new StreamLogger('test', '', $this->introspection);
+               $logger = new StreamLogger('test', '', $this->introspection, $this->fileSystem);
 
                $logger->emergency('not working');
        }
@@ -109,7 +117,7 @@ class StreamLoggerTest extends AbstractLoggerTest
                $logfile = vfsStream::newFile('friendica.log')
                        ->at($this->root)->chmod(0);
 
-               $logger = new StreamLogger('test', $logfile->url(), $this->introspection);
+               $logger = new StreamLogger('test', $logfile->url(), $this->introspection, $this->fileSystem);
 
                $logger->emergency('not working');
        }
@@ -123,7 +131,7 @@ class StreamLoggerTest extends AbstractLoggerTest
        {
                $this->markTestIncomplete('We need a platform independent way to set directory to readonly');
 
-               $logger = new StreamLogger('test', '/$%/wrong/directory/file.txt', $this->introspection);
+               $logger = new StreamLogger('test', '/$%/wrong/directory/file.txt', $this->introspection, $this->fileSystem);
 
                $logger->emergency('not working');
        }
@@ -135,7 +143,7 @@ class StreamLoggerTest extends AbstractLoggerTest
         */
        public function testWrongMinimumLevel()
        {
-               $logger = new StreamLogger('test', 'file.text', $this->introspection, 'NOPE');
+               $logger = new StreamLogger('test', 'file.text', $this->introspection, $this->fileSystem, 'NOPE');
        }
 
        /**
@@ -148,7 +156,7 @@ class StreamLoggerTest extends AbstractLoggerTest
                $logfile = vfsStream::newFile('friendica.log')
                        ->at($this->root);
 
-               $logger = new StreamLogger('test', $logfile->url(), $this->introspection);
+               $logger = new StreamLogger('test', $logfile->url(), $this->introspection, $this->fileSystem);
 
                $logger->log('NOPE', 'a test');
        }
@@ -160,6 +168,23 @@ class StreamLoggerTest extends AbstractLoggerTest
         */
        public function testWrongFile()
        {
-               $logger = new StreamLogger('test', null, $this->introspection);
+               $logger = new StreamLogger('test', null, $this->introspection, $this->fileSystem);
+       }
+
+       /**
+        * Test a relative path
+        */
+       public function testRealPath()
+       {
+               $this->markTestSkipped('vfsStream isn\'t compatible with chdir, so not testable.');
+
+               $logfile = vfsStream::newFile('friendica.log')
+                                   ->at($this->root);
+
+               chdir($this->root->getChild('logs')->url());
+
+               $logger = new StreamLogger('test', '../friendica.log' , $this->introspection, $this->fileSystem);
+
+               $logger->info('Test');
        }
 }