BUGFIX Fixed Director::makeRelative() to accept https:// protocol

BUGFIX Fixed GET-parameter replacement in Director::is_absolute_url()
ENHANCEMENT Added Director::is_relative_url() and Director::is_site_url()
BUGFIX Validating $_FILES array in Director::direct()

(Merged from r73250)

git-svn-id: svn://svn.silverstripe.com/silverstripe/open/modules/sapphire/branches/2.2@73272 467b73ca-7a2a-4603-9d3b-597d59a354a9
This commit is contained in:
Sean Harvey 2009-03-18 02:38:41 +00:00 committed by Sam Minnee
parent f69463a107
commit 19ceaa905a

View File

@ -89,7 +89,14 @@ class Director {
* @uses getControllerForURL() rule-lookup logic is handled by this. * @uses getControllerForURL() rule-lookup logic is handled by this.
* @uses Controller::run() Controller::run() handles the page logic for a Director::direct() call. * @uses Controller::run() Controller::run() handles the page logic for a Director::direct() call.
*/ */
function direct($url) { static function direct($url) {
// Validate $_FILES array before merging it with $_POST
foreach($_FILES as $k => $v) {
if($v['tmp_name'] && !is_uploaded_file($v['tmp_name'])) {
user_error("File upoad '$k' doesn't appear to be a valid upload", E_USER_ERROR);
}
}
if(isset($_GET['debug_profile'])) Profiler::mark("Director","direct"); if(isset($_GET['debug_profile'])) Profiler::mark("Director","direct");
$controllerObj = Director::getControllerForURL($url); $controllerObj = Director::getControllerForURL($url);
@ -311,7 +318,11 @@ class Director {
$url = $_SERVER['HTTP_REFERER']; $url = $_SERVER['HTTP_REFERER'];
} }
Director::redirect($url); if(self::is_site_url($url)) {
Director::redirect($url);
} else {
return false;
}
} }
static function currentURLSegment() { static function currentURLSegment() {
@ -350,15 +361,40 @@ class Director {
self::$alternateBaseFolder = $baseFolder; self::$alternateBaseFolder = $baseFolder;
} }
/**
* Turns an absolute URL or folder into one that's relative to the root of the site.
* This is useful when turning a URL into a filesystem reference, or vice versa.
*
* @todo Implement checking across http/https protocols
*
* @param string $url Accepts both a URL or a filesystem path
* @return string Either a relative URL if the checks succeeded, or the original (possibly absolute) URL.
*/
static function makeRelative($url) { static function makeRelative($url) {
$base1 = self::absoluteBaseURL(); $base1 = self::absoluteBaseURL();
$base2 = self::baseFolder(); $base2 = self::baseFolder();
// Allow for the accidental inclusion of a // in the URL // Allow for the accidental inclusion of a // in the URL
$url = ereg_replace('([^:])//','\\1/',$url); $url = ereg_replace('([^:])//','\\1/',$url);
$url = trim($url);
if(substr($url,0,strlen($base1)) == $base1) return substr($url,strlen($base1)); if(substr($url,0,strlen($base1)) == $base1) return substr($url,strlen($base1));
// Only bother comparing the URL to the absolute version if $url looks like a URL.
if(preg_match('/^https?[^:]*:\/\//',$url)) {
$base1 = self::absoluteBaseURL();
if(substr($url,0,strlen($base1)) == $base1) return substr($url,strlen($base1));
}
// test for base folder, e.g. /var/www
$base2 = self::baseFolder();
if(substr($url,0,strlen($base2)) == $base2) return substr($url,strlen($base2)); if(substr($url,0,strlen($base2)) == $base2) return substr($url,strlen($base2));
// Test for relative base url, e.g. mywebsite/ if the full URL is http://localhost/mywebsite/
$base3 = self::baseURL();
if(substr($url,0,strlen($base3)) == $base3) return substr($url,strlen($base3));
// Nothing matched, fall back to returning the original URL
return $url; return $url;
} }
@ -371,6 +407,50 @@ class Director {
return Director::baseFolder() . '/' . $file; return Director::baseFolder() . '/' . $file;
} }
/**
* Checks if a given URL is absolute (e.g. starts with 'http://' etc.).
*
* @param string $url
* @return boolean
*/
public static function is_absolute_url($url) {
$url = trim($url);
// remove all query strings to avoid parse_url choking on URLs like 'test.com?url=http://test.com'
$url = preg_replace('/(.*)\?.*/', '$1', $url);
$parsed = parse_url($url);
return (isset($parsed['scheme']));
}
/**
* Checks if a given URL is relative by checking
* {@link is_absolute_url()}.
*
* @param string $url
* @return boolean
*/
public static function is_relative_url($url) {
return (!Director::is_absolute_url($url));
}
/**
* Checks if the given URL is belonging to this "site",
* as defined by {@link makeRelative()} and {@link absoluteBaseUrl()}.
* Useful to check before redirecting based on a URL from user submissions
* through $_GET or $_POST, and avoid phishing attacks by redirecting
* to an attackers server.
*
* @param string $url
* @return boolean
*/
public static function is_site_url($url) {
$relativeUrl = Director::makeRelative($url);
return (bool)self::is_relative_url($relativeUrl);
}
/**
* Returns true if the given file exists.
* @param $file Filename specified relative to the site root
*/
static function fileExists($file) { static function fileExists($file) {
return file_exists(Director::getAbsFile($file)); return file_exists(Director::getAbsFile($file));
} }