From ab2b79cda682a697baba2128a21d3a9b5e90853c Mon Sep 17 00:00:00 2001
From: Stefan Herbrechtsmeier <stefan@herbrechtsmeier.net>
Date: Sun, 9 Sep 2012 12:54:47 +0200
Subject: [PATCH] add multiple domains reverse proxy support

Add support for a reverse proxy that handles multiple domains via different
web roots (http[s]://proxy.tld/domain.tld/owncloud).

As the reverse proxy web root is transparent for the web server the
REQUEST_URI and SCRIPT_NAME need manual adjustments. This patch replace
the direct use of this _SERVER variables with function calls and extend
this functions to overwrite the web root. Additionally it adds a Sabre
request backend that extends the Sabre_HTTP_Request to use the same
functions.
---
 apps/files/appinfo/remote.php   |  2 ++
 apps/files/index.php            |  2 +-
 config/config.sample.php        |  3 ++
 lib/app.php                     |  2 +-
 lib/base.php                    |  6 ++--
 lib/connector/sabre/request.php | 50 +++++++++++++++++++++++++++++++++
 lib/public/util.php             | 22 +++++++++++++++
 lib/request.php                 | 32 +++++++++++++++++++++
 lib/util.php                    |  2 +-
 ocs/providers.php               |  2 +-
 10 files changed, 116 insertions(+), 7 deletions(-)
 create mode 100644 lib/connector/sabre/request.php

diff --git a/apps/files/appinfo/remote.php b/apps/files/appinfo/remote.php
index 6a78a1e0d75..6c92cc80b69 100644
--- a/apps/files/appinfo/remote.php
+++ b/apps/files/appinfo/remote.php
@@ -32,12 +32,14 @@ OC_Util::obEnd();
 // Backends
 $authBackend = new OC_Connector_Sabre_Auth();
 $lockBackend = new OC_Connector_Sabre_Locks();
+$requestBackend = new OC_Connector_Sabre_Request();
 
 // Create ownCloud Dir
 $publicDir = new OC_Connector_Sabre_Directory('');
 
 // Fire up server
 $server = new Sabre_DAV_Server($publicDir);
+$server->httpRequest = $requestBackend;
 $server->setBaseUri($baseuri);
 
 // Load plugins
diff --git a/apps/files/index.php b/apps/files/index.php
index 7e767cc8a4f..104cf1a55d3 100644
--- a/apps/files/index.php
+++ b/apps/files/index.php
@@ -36,7 +36,7 @@ OCP\App::setActiveNavigationEntry('files_index');
 $dir = isset($_GET['dir']) ? stripslashes($_GET['dir']) : '';
 // Redirect if directory does not exist
 if (!\OC\Files\Filesystem::is_dir($dir . '/')) {
-	header('Location: ' . $_SERVER['SCRIPT_NAME'] . '');
+	header('Location: ' . OCP\Util::getScriptName() . '');
 	exit();
 }
 
diff --git a/config/config.sample.php b/config/config.sample.php
index 05663a09a46..ebe73fbec7b 100644
--- a/config/config.sample.php
+++ b/config/config.sample.php
@@ -38,6 +38,9 @@ $CONFIG = array(
 /* The automatic protocol detection of ownCloud can fail in certain reverse proxy situations. This option allows to manually override the protocol detection. For example "https" */
 "overwriteprotocol" => "",
 
+/* The automatic webroot detection of ownCloud can fail in certain reverse proxy situations. This option allows to manually override the automatic detection. For example "/domain.tld/ownCloud" */
+"overwritewebroot" => "",
+
 /* A proxy to use to connect to the internet. For example "myproxy.org:88" */
 "proxy" => "",
 
diff --git a/lib/app.php b/lib/app.php
index 7aafeb36295..fa3e14ce4d2 100644
--- a/lib/app.php
+++ b/lib/app.php
@@ -506,7 +506,7 @@ class OC_App{
 	 * @return string
 	 */
 	public static function getCurrentApp() {
-		$script=substr($_SERVER["SCRIPT_NAME"], strlen(OC::$WEBROOT)+1);
+		$script=substr(OC_Request::scriptName(), strlen(OC::$WEBROOT)+1);
 		$topFolder=substr($script, 0, strpos($script, '/'));
 		if (empty($topFolder)) {
 			$path_info = OC_Request::getPathInfo();
diff --git a/lib/base.php b/lib/base.php
index ea5c939cd80..232350b59e2 100644
--- a/lib/base.php
+++ b/lib/base.php
@@ -129,7 +129,7 @@ class OC
 		// calculate the root directories
 		OC::$SERVERROOT = str_replace("\\", '/', substr(__DIR__, 0, -4));
 		OC::$SUBURI = str_replace("\\", "/", substr(realpath($_SERVER["SCRIPT_FILENAME"]), strlen(OC::$SERVERROOT)));
-		$scriptName = $_SERVER["SCRIPT_NAME"];
+		$scriptName = OC_Request::scriptName();
 		if (substr($scriptName, -1) == '/') {
 			$scriptName .= 'index.php';
 			//make sure suburi follows the same rules as scriptName
@@ -230,7 +230,7 @@ class OC
 			header('Strict-Transport-Security: max-age=31536000');
 			ini_set("session.cookie_secure", "on");
 			if (OC_Request::serverProtocol() <> 'https' and !OC::$CLI) {
-				$url = "https://" . OC_Request::serverHost() . $_SERVER['REQUEST_URI'];
+				$url = "https://" . OC_Request::serverHost() . OC_Request::requestUri();
 				header("Location: $url");
 				exit();
 			}
@@ -764,7 +764,7 @@ class OC
 		if (OC_User::login($_SERVER["PHP_AUTH_USER"], $_SERVER["PHP_AUTH_PW"])) {
 			//OC_Log::write('core',"Logged in with HTTP Authentication", OC_Log::DEBUG);
 			OC_User::unsetMagicInCookie();
-			$_REQUEST['redirect_url'] = (isset($_SERVER['REQUEST_URI']) ? $_SERVER['REQUEST_URI'] : '');
+			$_REQUEST['redirect_url'] = OC_Request::requestUri();
 			OC_Util::redirectToDefaultPage();
 		}
 		return true;
diff --git a/lib/connector/sabre/request.php b/lib/connector/sabre/request.php
new file mode 100644
index 00000000000..97a27996bf3
--- /dev/null
+++ b/lib/connector/sabre/request.php
@@ -0,0 +1,50 @@
+<?php
+
+/**
+ * ownCloud
+ *
+ * @author Stefan Herbrechtsmeier
+ * @copyright 2012 Stefan Herbrechtsmeier <stefan@herbrechtsmeier.net>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or any later version.
+ *
+ * This library 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 library.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+class OC_Connector_Sabre_Request extends Sabre_HTTP_Request {
+	/**
+	 * Returns the requested uri
+	 *
+	 * @return string
+	 */
+	public function getUri() {
+		return OC_Request::requestUri();
+	}
+
+	/**
+	 * Returns a specific item from the _SERVER array.
+	 *
+	 * Do not rely on this feature, it is for internal use only.
+	 *
+	 * @param string $field
+	 * @return string
+	 */
+	public function getRawServerValue($field) {
+		if($field == 'REQUEST_URI'){
+			return $this->getUri();
+		}
+		else{
+			return isset($this->_SERVER[$field])?$this->_SERVER[$field]:null;
+		}
+	}
+}
diff --git a/lib/public/util.php b/lib/public/util.php
index 413dbcccd28..a78a52f326e 100644
--- a/lib/public/util.php
+++ b/lib/public/util.php
@@ -218,6 +218,28 @@ class Util {
 		return(\OC_Request::serverProtocol());
 	}
 
+	/**
+	 * @brief Returns the request uri
+	 * @returns the request uri
+	 *
+	 * Returns the request uri, even if the website uses one or more
+	 * reverse proxies
+	 */
+	public static function getRequestUri() {
+		return(\OC_Request::requestUri());
+	}
+
+	/**
+	 * @brief Returns the script name
+	 * @returns the script name
+	 *
+	 * Returns the script name, even if the website uses one or more
+	 * reverse proxies
+	 */
+	public static function getScriptName() {
+		return(\OC_Request::scriptName());
+	}
+
 	/**
 	 * @brief Creates path to an image
 	 * @param string $app app
diff --git a/lib/request.php b/lib/request.php
index f2f15c21103..4c056ce9b2f 100755
--- a/lib/request.php
+++ b/lib/request.php
@@ -58,6 +58,38 @@ class OC_Request {
 		return $proto;
 	}
 
+	/**
+	 * @brief Returns the request uri
+	 * @returns the request uri
+	 *
+	 * Returns the request uri, even if the website uses one or more
+	 * reverse proxies
+	 */
+	public static function requestUri() {
+		$uri = isset($_SERVER['REQUEST_URI']) ? $_SERVER['REQUEST_URI'] : '';
+		if (OC_Config::getValue('overwritewebroot', '') <> '') {
+			$uri = self::scriptName() . substr($uri, strlen($_SERVER['SCRIPT_NAME']));
+		}
+		return $uri;
+	}
+
+	/**
+	 * @brief Returns the script name
+	 * @returns the script name
+	 *
+	 * Returns the script name, even if the website uses one or more
+	 * reverse proxies
+	 */
+	public static function scriptName() {
+		$name = $_SERVER['SCRIPT_NAME'];
+		if (OC_Config::getValue('overwritewebroot', '') <> '') {
+			$serverroot = str_replace("\\", '/', substr(__DIR__, 0, -4));
+			$suburi = str_replace("\\", "/", substr(realpath($_SERVER["SCRIPT_FILENAME"]), strlen($serverroot)));
+			$name = OC_Config::getValue('overwritewebroot', '') . $suburi;
+		}
+		return $name;
+	}
+
 	/**
 	 * @brief get Path info from request
 	 * @returns string Path info or false when not found
diff --git a/lib/util.php b/lib/util.php
index e8057abe9ae..809f6a88be7 100755
--- a/lib/util.php
+++ b/lib/util.php
@@ -312,7 +312,7 @@ class OC_Util {
 	public static function checkLoggedIn() {
 		// Check if we are a user
 		if( !OC_User::isLoggedIn()) {
-			header( 'Location: '.OC_Helper::linkToAbsolute( '', 'index.php', array('redirect_url' => $_SERVER["REQUEST_URI"])));
+			header( 'Location: '.OC_Helper::linkToAbsolute( '', 'index.php', array('redirect_url' => OC_Request::requestUri())));
 			exit();
 		}
 	}
diff --git a/ocs/providers.php b/ocs/providers.php
index 0c7cbaeff08..bf94b85dcfb 100644
--- a/ocs/providers.php
+++ b/ocs/providers.php
@@ -23,7 +23,7 @@
 
 require_once '../lib/base.php';
 
-$url=OCP\Util::getServerProtocol().'://'.substr(OCP\Util::getServerHost().$_SERVER['REQUEST_URI'], 0, -17).'ocs/v1.php/';
+$url=OCP\Util::getServerProtocol().'://'.substr(OCP\Util::getServerHost().OCP\Util::getRequestUri(), 0, -17).'ocs/v1.php/';
 
 echo('
 <providers>
-- 
GitLab