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