From 2515cb17be18da4aee32167259ee75fdc7a5a56b Mon Sep 17 00:00:00 2001
From: Lukas Reschke <lukas@owncloud.com>
Date: Wed, 11 Feb 2015 01:10:03 +0100
Subject: [PATCH] Support pretty URLs

This changeset allows ownCloud to run with pretty URLs, they will be used if mod_rewrite and mod_env are available. This means basically that the `index.php` in the URL is not shown to the user anymore.

Also the not deprecated functions to generate URLs have been modified to support this behaviour, old functions such as `filePath` will still behave as before for compatibility reasons.

Examples:
http://localhost/owncloud/index.php/s/AIDyKbxiRZWAAjP => http://localhost/owncloud/s/AIDyKbxiRZWAAjP
http://localhost/owncloud/index.php/apps/files/ => http://localhost/owncloud/apps/files/

Due to the way our CSS and JS is structured the .htaccess uses some hacks for the final result but could be worse... And I was just annoyed by all that users crying for the removal of `index.php` ;-)
---
 .htaccess                    | 15 +++++++++++++++
 config/config.sample.php     |  1 -
 core/js/config.php           |  1 +
 core/js/js.js                |  6 +++++-
 lib/private/route/router.php |  8 +++++++-
 lib/private/setup.php        |  6 ++++++
 lib/private/urlgenerator.php |  2 +-
 lib/private/util.php         |  7 ++++++-
 tests/lib/util.php           | 20 ++++++++++++++++++++
 9 files changed, 61 insertions(+), 5 deletions(-)

diff --git a/.htaccess b/.htaccess
index 615f5e7fc96..5c11eff9f37 100644
--- a/.htaccess
+++ b/.htaccess
@@ -43,6 +43,21 @@
   RewriteRule ^remote/(.*) remote.php [QSA,L]
   RewriteRule ^(build|tests|config|lib|3rdparty|templates)/.* - [R=404,L]
   RewriteRule ^(\.|autotest|occ|issue|indie|db_|console).* - [R=404,L]
+
+  <IfModule mod_env.c>
+    SetEnv front_controller_active true
+    RewriteRule ^core/js/oc.js$ index.php [PT,E=PATH_INFO:$1]
+    RewriteRule ^core/preview.png$ index.php [PT,E=PATH_INFO:$1]
+    RewriteCond %{REQUEST_FILENAME} !\.(css|js|svg|gif|png|html|ttf|woff)$
+    RewriteCond %{REQUEST_FILENAME} !/remote.php
+    RewriteCond %{REQUEST_FILENAME} !/public.php
+    RewriteCond %{REQUEST_FILENAME} !/cron.php
+    RewriteCond %{REQUEST_FILENAME} !/status.php
+    RewriteCond %{REQUEST_FILENAME} !/ocs/v1.php
+    RewriteCond %{REQUEST_FILENAME} !/ocs/v2.php
+    RewriteRule .* index.php [PT,E=PATH_INFO:$1]
+  </IfModule>
+
 </IfModule>
 <IfModule mod_mime.c>
   AddType image/svg+xml svg svgz
diff --git a/config/config.sample.php b/config/config.sample.php
index 02e5aba3e94..034a1ebddbf 100644
--- a/config/config.sample.php
+++ b/config/config.sample.php
@@ -213,7 +213,6 @@ $CONFIG = array(
 	)
 ),
 
-
 /**
  * Mail Parameters
  *
diff --git a/core/js/config.php b/core/js/config.php
index 953bd2ede45..463e334ef26 100644
--- a/core/js/config.php
+++ b/core/js/config.php
@@ -141,6 +141,7 @@ $array = array(
 			'version'			=> implode('.', OC_Util::getVersion()),
 			'versionstring'		=> OC_Util::getVersionString(),
 			'enable_avatars'	=> \OC::$server->getConfig()->getSystemValue('enable_avatars', true),
+			'modRewriteWorking'	=> (getenv('front_controller_active') === 'true'),
 		)
 	),
 	"oc_appconfig" => json_encode(
diff --git a/core/js/js.js b/core/js/js.js
index ce552bb8ea2..cbdffd0f016 100644
--- a/core/js/js.js
+++ b/core/js/js.js
@@ -160,7 +160,11 @@ var OC={
 			url = '/' + url;
 
 		}
-		// TODO save somewhere whether the webserver is able to skip the index.php to have shorter links (e.g. for sharing)
+
+		if(oc_config.modRewriteWorking == true) {
+			return OC.webroot + _build(url, params);
+		}
+
 		return OC.webroot + '/index.php' + _build(url, params);
 	},
 
diff --git a/lib/private/route/router.php b/lib/private/route/router.php
index 6d3b7c742bb..25860ee46bf 100644
--- a/lib/private/route/router.php
+++ b/lib/private/route/router.php
@@ -85,9 +85,15 @@ class Router implements IRouter {
 	 */
 	protected $logger;
 
+	/**
+	 * @param ILogger $logger
+	 */
 	public function __construct(ILogger $logger) {
 		$this->logger = $logger;
-		$baseUrl = \OC_Helper::linkTo('', 'index.php');
+		$baseUrl = \OC::$WEBROOT;
+		if(!(getenv('front_controller_active') === 'true')) {
+			$baseUrl = \OC_Helper::linkTo('', 'index.php');
+		}
 		if (!\OC::$CLI) {
 			$method = $_SERVER['REQUEST_METHOD'];
 		} else {
diff --git a/lib/private/setup.php b/lib/private/setup.php
index 8f1ae389e45..1f91240e9da 100644
--- a/lib/private/setup.php
+++ b/lib/private/setup.php
@@ -432,6 +432,12 @@ class Setup {
 			//custom 404 error page
 			$content.= "\nErrorDocument 404 ".\OC::$WEBROOT."/core/templates/404.php";
 		}
+
+		// Add rewrite base
+		$content.="\n<IfModule mod_rewrite.c>";
+		$content.="\n  RewriteBase ".\OC::$WEBROOT;
+		$content.="\n</IfModule>";
+
 		if ($content !== '') {
 			//suppress errors in case we don't have permissions for it
 			@file_put_contents($setupHelper->pathToHtaccess(), $content . "\n", FILE_APPEND);
diff --git a/lib/private/urlgenerator.php b/lib/private/urlgenerator.php
index 428a222f9c7..fb1ea737ef4 100644
--- a/lib/private/urlgenerator.php
+++ b/lib/private/urlgenerator.php
@@ -90,7 +90,7 @@ class URLGenerator implements IURLGenerator {
 	 * Returns a url to the given app and file.
 	 */
 	public function linkTo( $app, $file, $args = array() ) {
-		$frontControllerActive=($this->config->getSystemValue('front_controller_active', 'false') == 'true');
+		$frontControllerActive = (getenv('front_controller_active') === 'true');
 
 		if( $app != '' ) {
 			$app_path = \OC_App::getAppPath($app);
diff --git a/lib/private/util.php b/lib/private/util.php
index 84a8c49c383..5466082d030 100644
--- a/lib/private/util.php
+++ b/lib/private/util.php
@@ -1073,7 +1073,12 @@ class OC_Util {
 						break;
 					}
 				}
-				$location = $urlGenerator->getAbsoluteURL('/index.php/apps/' . $appId . '/');
+
+				if(getenv('front_controller_active') === 'true') {
+					$location = $urlGenerator->getAbsoluteURL('/apps/' . $appId . '/');
+				} else {
+					$location = $urlGenerator->getAbsoluteURL('/index.php/apps/' . $appId . '/');
+				}
 			}
 		}
 		return $location;
diff --git a/tests/lib/util.php b/tests/lib/util.php
index 608c5f0c501..032ede74a81 100644
--- a/tests/lib/util.php
+++ b/tests/lib/util.php
@@ -338,6 +338,26 @@ class Test_Util extends \Test\TestCase {
 		);
 	}
 
+	public function testGetDefaultPageUrlWithRedirectUrlWithoutFrontController() {
+		putenv('front_controller_active=false');
+
+		$_REQUEST['redirect_url'] = 'myRedirectUrl.com';
+		$this->assertSame('http://localhost'.\OC::$WEBROOT.'/myRedirectUrl.com', OC_Util::getDefaultPageUrl());
+	}
+
+	public function testGetDefaultPageUrlWithRedirectUrlRedirectBypassWithoutFrontController() {
+		putenv('front_controller_active=false');
+
+		$_REQUEST['redirect_url'] = 'myRedirectUrl.com@foo.com:a';
+		$this->assertSame('http://localhost'.\OC::$WEBROOT.'/index.php/apps/files/', OC_Util::getDefaultPageUrl());
+	}
+
+	public function testGetDefaultPageUrlWithRedirectUrlRedirectBypassWithFrontController() {
+		putenv('front_controller_active=true');
+		$_REQUEST['redirect_url'] = 'myRedirectUrl.com@foo.com:a';
+		$this->assertSame('http://localhost'.\OC::$WEBROOT.'/apps/files/', OC_Util::getDefaultPageUrl());
+	}
+
 	/**
 	 * Test needUpgrade() when the core version is increased
 	 */
-- 
GitLab