diff --git a/src/Monolog/Handler/RotatingFileHandler.php b/src/Monolog/Handler/RotatingFileHandler.php index ae2309f8..b8253ba0 100644 --- a/src/Monolog/Handler/RotatingFileHandler.php +++ b/src/Monolog/Handler/RotatingFileHandler.php @@ -12,6 +12,7 @@ namespace Monolog\Handler; use Monolog\Logger; +use Monolog\Utils; /** * Stores logs to files that are rotated every day and a limited number of files are kept. @@ -45,7 +46,7 @@ class RotatingFileHandler extends StreamHandler */ public function __construct($filename, $maxFiles = 0, $level = Logger::DEBUG, $bubble = true, $filePermission = null, $useLocking = false) { - $this->filename = $filename; + $this->filename = Utils::canonicalizePath($filename); $this->maxFiles = (int) $maxFiles; $this->nextRotation = new \DateTime('tomorrow'); $this->filenameFormat = '{filename}-{date}'; diff --git a/src/Monolog/Handler/StreamHandler.php b/src/Monolog/Handler/StreamHandler.php index 27d90e06..7c0dfd22 100644 --- a/src/Monolog/Handler/StreamHandler.php +++ b/src/Monolog/Handler/StreamHandler.php @@ -12,6 +12,7 @@ namespace Monolog\Handler; use Monolog\Logger; +use Monolog\Utils; /** * Stores to any stream resource @@ -45,7 +46,7 @@ class StreamHandler extends AbstractProcessingHandler if (is_resource($stream)) { $this->stream = $stream; } elseif (is_string($stream)) { - $this->url = $stream; + $this->url = Utils::canonicalizePath($stream); } else { throw new \InvalidArgumentException('A stream must either be a resource or a string.'); } diff --git a/src/Monolog/Utils.php b/src/Monolog/Utils.php index 180a159d..712b1969 100644 --- a/src/Monolog/Utils.php +++ b/src/Monolog/Utils.php @@ -23,6 +23,36 @@ class Utils return 'c' === $class[0] && 0 === strpos($class, "class@anonymous\0") ? get_parent_class($class).'@anonymous' : $class; } + /** + * Makes sure if a relative path is passed in it is turned into an absolute path + * + * @param string $streamUrl stream URL or path without protocol + * + * @return string + */ + public static function canonicalizePath($streamUrl) + { + $prefix = ''; + if ('file://' === substr($streamUrl, 0, 7)) { + $streamUrl = substr($streamUrl, 7); + $prefix = 'file://'; + } + + // other type of stream, not supported + if (false !== strpos($streamUrl, '://')) { + return $streamUrl; + } + + // already absolute + if (substr($streamUrl, 0, 1) === '/' || substr($streamUrl, 1, 1) === ':' || substr($streamUrl, 0, 2) === '\\\\') { + return $prefix.$streamUrl; + } + + $streamUrl = getcwd() . '/' . $streamUrl; + + return $prefix.$streamUrl; + } + /** * Return the JSON representation of a value * diff --git a/tests/Monolog/UtilsTest.php b/tests/Monolog/UtilsTest.php index 1ffcc74b..428e02cc 100644 --- a/tests/Monolog/UtilsTest.php +++ b/tests/Monolog/UtilsTest.php @@ -13,6 +13,29 @@ namespace Monolog; class UtilsTest extends \PHPUnit_Framework_TestCase { + /** + * @param string $expected + * @param string $input + * @dataProvider providePathsToCanonicalize + */ + public function testCanonicalizePath($expected, $input) + { + $this->assertSame($expected, Utils::canonicalizePath($input)); + } + + public function providePathsToCanonicalize() + { + return array( + array('/foo/bar', '/foo/bar'), + array('file://'.getcwd().'/bla', 'file://bla'), + array(getcwd().'/bla', 'bla'), + array(getcwd().'/./bla', './bla'), + array('file:///foo/bar', 'file:///foo/bar'), + array('any://foo', 'any://foo'), + array('\\\\network\path', '\\\\network\path'), + ); + } + /** * @param int $code * @param string $msg