From 35b88e29bf4748af7de0107c75f400d019f9c803 Mon Sep 17 00:00:00 2001
From: Olav Morken <olav.morken@uninett.no>
Date: Mon, 9 Jun 2008 08:04:58 +0000
Subject: [PATCH] Utilities: add resolveURL to resolve (possibly) relative
 URLs.

git-svn-id: https://simplesamlphp.googlecode.com/svn/trunk@618 44740490-163a-0410-bde0-09ae8108e29a
---
 lib/SimpleSAML/Utilities.php | 82 ++++++++++++++++++++++++++++++++++++
 1 file changed, 82 insertions(+)

diff --git a/lib/SimpleSAML/Utilities.php b/lib/SimpleSAML/Utilities.php
index 17a344591..a46f31171 100644
--- a/lib/SimpleSAML/Utilities.php
+++ b/lib/SimpleSAML/Utilities.php
@@ -974,6 +974,88 @@ class SimpleSAML_Utilities {
 		return $ret;
 	}
 
+
+	/**
+	 * Resolve a (possibly) relative URL relative to a given base URL.
+	 *
+	 * This function supports these forms of relative URLs:
+	 *  ^\w+: Absolute URL
+	 *  ^// Same protocol.
+	 *  ^/ Same protocol and host.
+	 *  ^? Same protocol, host and path, replace query string & fragment
+	 *  ^# Same protocol, host, path and query, replace fragment
+	 *  The rest: Relative to the base path.
+	 *
+	 * @param $url  The relative URL.
+	 * @param $base  The base URL. Defaults to the base URL of this installation of simpleSAMLphp.
+	 * @return An absolute URL for the given relative URL.
+	 */
+	public static function resolveURL($url, $base = NULL) {
+		if($base === NULL) {
+			$config = SimpleSAML_Configuration::getInstance();
+			$base = self::selfURLhost() . '/' . $config->getBaseURL();
+		}
+
+
+		if(!preg_match('$^((((\w+:)//[^/]+)(/[^?#]*))(?:\?[^#]*)?)(?:#.*)?$', $base, $baseParsed)) {
+			throw new Exception('Unable to parse base url: ' . $base);
+		}
+
+		$baseDir = dirname($baseParsed[5] . 'filename');
+		$baseScheme = $baseParsed[4];
+		$baseHost = $baseParsed[3];
+		$basePath = $baseParsed[2];
+		$baseQuery = $baseParsed[1];
+
+		if(preg_match('$^\w+:$', $url)) {
+			return $url;
+		}
+
+		if(substr($url, 0, 2) === '//') {
+			return $baseScheme . $url;
+		}
+
+		$firstChar = substr($url, 0, 1);
+
+		if($firstChar === '/') {
+			return $baseHost . $url;
+		}
+
+		if($firstChar === '?') {
+			return $basePath . $url;
+		}
+
+		if($firstChar === '#') {
+			return $baseQuery . $url;
+		}
+
+
+		/* We have a relative path. Remove query string/fragment and save it as $tail. */
+		$queryPos = strpos($url, '?');
+		$fragmentPos = strpos($url, '#');
+		if($queryPos !== FALSE || $fragmentPos !== FALSE) {
+			if($queryPos === FALSE) {
+				$tailPos = $fragmentPos;
+			} elseif($fragmentPos === FALSE) {
+				$tailPos = $queryPos;
+			} elseif($queryPos < $fragmentPos) {
+				$tailPos = $queryPos;
+			} else {
+				$tailPos = $fragmentPos;
+			}
+
+			$tail = substr($url, $tailPos);
+			$dir = substr($url, 0, $tailPos);
+		} else {
+			$dir = $url;
+			$tail = '';
+		}
+
+		$dir = self::resolvePath($dir, $baseDir);
+
+		return $baseHost . $dir . $tail;
+	}
+
 }
 
 ?>
\ No newline at end of file
-- 
GitLab