Jump to content

URI to file path


boen_robot

Recommended Posts

I need a function that would take any URI as argument and will return an absolute file path on the server to represent it. Is there such a function, or should I try to create one myself? I'm mostly worried about performance in this case.This function must find the document root of the server, respect relative paths, etc.... for example, if my document root is at

D:/htdocs

and the php file is at

D:/htdocs/sub1/sub2/file1.php

then the URI

../file2.php

placed inside file1.php, should make this function return

D:/htdocs/sub1/file2.php

while

/file3.php

would make it return

D:/htdocs/file3.php

Last but not least. When a file:// path is used, the result should still be convertable, so that

file:///D|/dir2/file.php

Would result in:

D:/dir2/file.php

Link to comment
Share on other sites

There's not one function that can do all of that, specifically the file:// requirement. That's an absolute URL, so it wouldn't need to be converted.Anyway, you'll probably have to do most of this yourself, such as checking if the path starts with a slash, but there are several variables in PHP to at least let you know the base path. You can do this to get the filesystem path to the currently executing file:dirname(__FILE__);You would use that path if you could verify that the filename were a relative URI. I think you can even just do a straight concatenation. I think this would be valid; confusing, but valid:D:/htdocs/sub1/sub2/../file2.phpwould point to:D:/htdocs/sub1/file2.phpIf you can verify that the link is relative to the base path of the web server, you can use this to get that path:$_SERVER['DOCUMENT_ROOT'];e.g. c:\inetpub\wwwrootThe $_SERVER['REQUEST_URI'] variable holds the URI relative to the document root.So yeah, you've got that information available to you, but I think it's still up to you to detect if the path is absolute or relative, using a scheme or not. You might also find this helpful, I didn't look at it too much though so it might be totally useless:

Convert a URL to the local file path and vice versa, convert a local file path to a URL.// this sets the sytem / or \ :strstr( PHP_OS, "WIN") ? $slash = "\\" : $slash = "/";// This is the location of the php file that contains this// function. Usually this request is made to files/folders // down the directory structure, so the php file that // contains these functions is a good "where am i" // reference point:$WIMPY_BASE['path']['physical'] = getcwd();$WIMPY_BASE['path']['www'] = "http://".$_SERVER['HTTP_HOST'];function url2filepath($theURL){	global $WIMPY_BASE, $slash;	$AtheFile = explode ("/", $theURL);	$theFileName = array_pop($AtheFile);	$AwimpyPathWWW = explode ("/", $WIMPY_BASE['path']['www']);	$AtheFilePath = array_values (array_diff ($AtheFile, $AwimpyPathWWW));	if($AtheFilePath){		$theFilePath = $slash.implode($slash, $AtheFilePath).$slash.$theFileName;	} else {		$theFilePath = implode($slash, $AtheFilePath).$slash.$theFileName;	}	return ($WIMPY_BASE['path']['physical'].$theFilePath);}function filepath2url ($theFilepath){	global $WIMPY_BASE, $slash;	$AtheFile = explode ($slash, $theFilepath);	$theFileName = array_pop($AtheFile);	$AwimpyPathFILE = explode ($slash, $WIMPY_BASE['path']['physical']);	$AtheFilePath = array_values (array_diff ($AtheFile, $AwimpyPathFILE));	$thFileURL = implode("/", $AtheFilePath)."/".$theFileName;	return ($WIMPY_BASE['path']['www']."$thFileURL");}

hey look at that, theres a getcwd function. i guess i can hang up dirname(__FILE__).actually no, they still return different results for included files. dirname is still my boy

Link to comment
Share on other sites

Wow. This code sample looks a little too literal for my taste. I'm certanly not using it :) .Concatenating the path? Now there's something interesting. Things just got a whole lot simpler. I can already think the complete function, including the file:// requrement. Now if I just go home and try writing it and testing it :) .Thanks for everything.

Link to comment
Share on other sites

Hmm... dirname(__FILE__) doesn't work on PHP 5.2.2. At least not on my computer anyway. No matter, I found another way, which however doesn't work for versions prior to 5.2, because it uses pathinfo() with DIRNAME, which was added there. Here it is:

function current_folder() {	return pathinfo($_SERVER["SCRIPT_FILENAME"],PATHINFO_DIRNAME);}function url2filepath($url) {	$durl = urldecode($url);	if (ereg('^\/',$durl)) {//If it's a relative to the document root path		return $_SERVER['DOCUMENT_ROOT'] . $durl;	}elseif (ereg('^file\:\/\/\/',$durl)) {//If it uses the file protocol		return strtr(substr($durl,8),'|',':');	}else {//Everything else is (assumed to be) a relative path		return current_folder(). '/' . $durl;	}}

I know it returns the paths with forward slashes. That's intended.Any suggestestions for supporting older PHP 5's (I don't need PHP4 support)? Any situation I haven't anticipated?

Link to comment
Share on other sites

Hmm.. dirname should be fine, assuming that PHP is not running in safe mode and the dirname function is not listed as a disabled function. You can try using the getcwd function, that should work fine. But keep in mind that if you use getcwd in an included file, it will return the working directory for the base script, not the included script. dirname(__FILE__) would return the path for whatever file is currently executing.

Link to comment
Share on other sites

Actually getcwd() is perfect, as I plan to include this function in a file containing functions I need to use frequently. Relative paths would need to be relative to the document which calls the url2filepath() function, not the file that defines it.But, there's one problem... getcwd() returns the path with backward slashes. That is fine for now, but if I upload my files on a UNIX host, I might have problems. I'd need a path with forward slashes. Yet on my development machine(s) I'd need backward slashes. Is there a way I can apply a slash replacement (with strtr() I guess) depending on the OS? Or should I say - how can I detect the OS the script is running on?

Link to comment
Share on other sites

Still, I need to return the rest of the path with proper slashes. So the matter of detecting OS remains.

Link to comment
Share on other sites

Tip (this should work):use getcwd() and take the first character from the string it returns, if that character is / it's *nix, if it's not (C, D, E etc) then it's win..

Link to comment
Share on other sites

Good idea. Here's my new version, based on your suggestion:

function url2filepath($url) {	$durl = urldecode($url);	$fs = '/';	$fsr = '\/';	if (ereg('^' . $fsr, $durl)) {//If it's a path relative to the document root		$result = $_SERVER['DOCUMENT_ROOT'] . $durl;	}elseif (ereg('^file\:\/\/\/', $durl)) {//If it uses the file protocol to target the current machine		$result = strtr(substr($durl,8),'|',':');	}else {//Everything else is (assumed to be) a relative path		$result = getcwd() . $fs . $durl;	}	//Return the filepath with the proper OS slashes	return (ereg($fsr,getcwd()) ? $result : strtr($result,$fs,'\\'));}

Now there's only one minor problem I personally won't have troubles with... not for the time being anyway. I was thinking "what if I start to accept foreign data as input?". It currently seems this is very fault tolerant function. If I write "file:///D:\test.file" I still get "D:\test.file" and if I write "/spaces are not allowed in URLs" I still get "D:\htdocs\spaces are not allowed in URLs" which isn't exactly right, cause as the statement says "spaces are not allowed in URLs". The same goes for backward slashes.Is there any way I could check if the input is a valid URL and decline it (return false) altogether if it's invalid? Ideally, I would want a second argument to determine whether this strict check should be applied or not.I would like to avoid usage of regular expressions for this one, cause I doubht there's a good enough one to catch absolutely every URL (absolute and relative with all URL rules) without also having a flaw of it's own. If there is... well... if it's the only way... fine... but what?[edit] One solution I've come across is detecting whether the file at the URL exist. While this sounds nice, it doesn't fease all situations I plan to use this function for. Any other approaches?[/edit]

Link to comment
Share on other sites

Is there any way I could check if the input is a valid URL and decline it (return false) altogether if it's invalid?
What characteristics are you looking for to make it valid or invalid?
Link to comment
Share on other sites

Archived

This topic is now archived and is closed to further replies.

×
×
  • Create New...