diff --git a/core/Url.php b/core/Url.php
index 1ed77f5fa5033a9e38f449fffbad36d16f867b26..c27805305d7d660e1efa6490d24366e0f66bd880 100644
--- a/core/Url.php
+++ b/core/Url.php
@@ -67,6 +67,7 @@ class Url
         return self::getCurrentScheme() . '://'
         . self::getCurrentHost()
         . self::getCurrentScriptName()
+        . self::getCurrentPathInfo()
         . self::getCurrentQueryString();
     }
 
@@ -83,7 +84,8 @@ class Url
     {
         return self::getCurrentScheme() . '://'
         . self::getCurrentHost($default = 'unknown', $checkTrustedHost)
-        . self::getCurrentScriptName();
+        . self::getCurrentScriptName()
+        . self::getCurrentPathInfo();
     }
 
     /**
@@ -173,6 +175,24 @@ class Url
         return $url;
     }
 
+    /**
+     * Returns the current PATH_INFO from the request.
+     *
+     * Contains any client-provided pathname information trailing the actual
+     * script filename but preceding the query string, if available.
+     *
+     * For instance, if the current script was accessed via the URL
+     * http://www.example.com/php/path_info.php/some/stuff?foo=bar
+     * then getCurrentPathInfo() would return "/some/stuff".
+     *
+     * @return string
+     * @api
+     */
+    public static function getCurrentPathInfo()
+    {
+        return isset($_SERVER['PATH_INFO']) ? $_SERVER['PATH_INFO'] : '';
+    }
+
     /**
      * Returns the current URL's protocol.
      *
diff --git a/tests/PHPUnit/Unit/UrlTest.php b/tests/PHPUnit/Unit/UrlTest.php
index c77907ee046d0a10cc6a43f3013f5cfcd367c0bc..888e6c8c9d71cc64f1d44d30b64c73083fca8e0b 100644
--- a/tests/PHPUnit/Unit/UrlTest.php
+++ b/tests/PHPUnit/Unit/UrlTest.php
@@ -159,11 +159,7 @@ class UrlTest extends PHPUnit_Framework_TestCase
      */
     public function testGetCurrentUrlWithoutFilename($expected, $https, $host, $path)
     {
-        $names = array('PATH_INFO', 'REQUEST_URI', 'SCRIPT_NAME', 'SCRIPT_FILENAME', 'argv', 'HTTPS', 'HTTP_HOST', 'QUERY_STRING', 'HTTP_REFERER');
-
-        foreach ($names as $name) {
-            unset($_SERVER[$name]);
-        }
+        $this->resetGlobalVariables();
 
         if ($https) {
             $_SERVER['HTTPS'] = $https;
@@ -185,11 +181,7 @@ class UrlTest extends PHPUnit_Framework_TestCase
      */
     public function test_getCurrentScriptName()
     {
-        $names = array('PATH_INFO', 'REQUEST_URI', 'SCRIPT_NAME', 'SCRIPT_FILENAME', 'argv', 'HTTPS', 'HTTP_HOST', 'QUERY_STRING', 'HTTP_REFERER');
-
-        foreach ($names as $name) {
-            unset($_SERVER[$name]);
-        }
+        $this->resetGlobalVariables();
 
         $tests = array(
             array('/', 'http://example.com/', null),
@@ -335,4 +327,85 @@ class UrlTest extends PHPUnit_Framework_TestCase
         );
     }
 
+    public function urlProvider()
+    {
+        return array(
+            array('http://example.com/'),
+            array('https://example.com/'),
+            array('http://example.com/piwik/'),
+            array('http://example.com/index.php'),
+            array('http://example.com/index.php?foo=bar'),
+            array('http://example.com/index.php/.html?foo=bar', '/.html'),
+        );
+    }
+
+    /**
+     * @dataProvider urlProvider
+     */
+    public function testGetCurrentUrl($url, $pathInfo = null)
+    {
+        $this->resetGlobalVariables();
+        $this->setGlobalVariablesFromUrl($url, $pathInfo);
+
+        $this->assertEquals($url, Url::getCurrentUrl());
+    }
+
+    public function urlWithoutQueryStringProvider()
+    {
+        return array(
+            array('http://example.com/', 'http://example.com/'),
+            array('https://example.com/', 'https://example.com/'),
+            array('http://example.com/piwik/', 'http://example.com/piwik/'),
+            array('http://example.com/index.php', 'http://example.com/index.php'),
+            array('http://example.com/index.php?foo=bar', 'http://example.com/index.php'),
+            array('http://example.com/index.php/.html?foo=bar', 'http://example.com/index.php/.html', '/.html'),
+        );
+    }
+
+    /**
+     * @dataProvider urlWithoutQueryStringProvider
+     */
+    public function testGetCurrentUrlWithoutQueryString($url, $expected, $pathInfo = null)
+    {
+        $this->resetGlobalVariables();
+        $this->setGlobalVariablesFromUrl($url, $pathInfo);
+
+        $this->assertEquals($expected, Url::getCurrentUrlWithoutQueryString());
+    }
+
+    private function resetGlobalVariables()
+    {
+        $names = array('PATH_INFO', 'REQUEST_URI', 'SCRIPT_NAME', 'SCRIPT_FILENAME', 'argv', 'HTTPS',
+            'HTTP_HOST', 'QUERY_STRING', 'HTTP_REFERER');
+
+        foreach ($names as $name) {
+            unset($_SERVER[$name]);
+        }
+
+        Config::getInstance()->General['enable_trusted_host_check'] = 0;
+    }
+
+    /**
+     * @param string $url
+     * @param string $pathInfo The PATH_INFO has to be provided because parse_url() doesn't parse that
+     */
+    private function setGlobalVariablesFromUrl($url, $pathInfo)
+    {
+        if (parse_url($url, PHP_URL_SCHEME) === 'https') {
+            $_SERVER['HTTPS'] = true;
+        }
+
+        $_SERVER['HTTP_HOST'] = parse_url($url, PHP_URL_HOST);
+        $_SERVER['REQUEST_URI'] = parse_url($url, PHP_URL_PATH);
+
+        $queryString = parse_url($url, PHP_URL_QUERY);
+        if ($queryString) {
+            $_SERVER['REQUEST_URI'] .= '?' . $queryString;
+            $_SERVER['QUERY_STRING'] = $queryString;
+        }
+
+        if ($pathInfo) {
+            $_SERVER['PATH_INFO'] = $pathInfo;
+        }
+    }
 }