<?php
// fixes windows paths...
// (windows accepts forward slashes and backwards slashes, so why does PHP use backwards?
function fix_path($path) {
return str_replace('\\','/',$path);
}
// takes two absolute paths and determines if one is a subdirectory of the other
// it doesn't care if it is an immediate child or 10 subdirectories deep...
// use absolute paths for both for best results
function is_child($parent, $child) {
if(false !== ($parent = realpath($parent))) {
$parent = fix_path($parent);
if(false !== ($child = realpath($child))) {
$child = fix_path($child);
if(substr($child, 0, strlen($parent)) == $parent)
return true;
}
}
return false;
}
?>
realpath
(PHP 4, PHP 5)
realpath — Retorna o path absoluto canonicalizado
Descrição
realpath() expande todos os links simbólicos e resolve referências para '/./', '/../' e extra caracteres '/' na entrada pelo path , e retorna o path absoluto canonicalizado.
Parâmetros
- path
-
O caminho a ser verificado.
Valor Retornado
Retorna o path absoluto em sucesso. O path resultante não conterá nenhum link simbólico ou componentes '/./' e '/../'.
realpath() retorna FALSE em caso de falha, por exemplo, se o caminho não existir. Em sistemas BSD realpath() não falha se somente o último componente do path não existe, quando em outro sistema irá retornar FALSE.
Exemplos
Exemplo #1 Exemplo da realpath()
<?php
chdir('/var/www/');
echo realpath('./../../etc/passwd');
?>
O exemplo acima irá imprimir:
/etc/passwd
Exemplo #2 realpath() em Windows
Em Windows, realpath() modificará o estilo unix de diretórios para o estilo Windows.
<?php
echo realpath('/windows/system32');
?>
O exemplo acima irá imprimir:
C:\WINDOWS\System32
Veja Também
- basename() - Retorna a parte nome do arquivo do caminho/path
- dirname() - Retorna o componente diretório de um caminho/path
- pathinfo() - Retorna informações sobre um caminho de arquivo
realpath
29-Jul-2009 05:36
16-Apr-2009 06:57
<?php
Class RealPath
{
private $ServerPath;
private $ScriptPath;
private $AddSlashEnd;
function __construct()
{
$this->AddSlashEnd = "";
$this->ServerPath = $_SERVER['DOCUMENT_ROOT'];
$this->ScriptPath = substr(dirname($_SERVER['SCRIPT_FILENAME']), strlen($this->ServerPath));
}
private function Server($adress)
{
$ThisPath = @realpath($adress);
$ThisPathLength = strlen($ThisPath);
return substr($ThisPath, strlen($this->ServerPath), $ThisPathLength);
}
public function Absolute($adress)
{
return $_SERVER['SERVER_NAME'] . $this->Server($adress) . $this->AddSlashEnd;
}
public function RelativeServer($adress)
{
return $this->Server($adress) . $this->AddSlashEnd;
}
public function RelativeScript($adress)
{
$ScriptExplode = explode("/", $this->ScriptPath);
$ServerExplode = explode("/", $this->Server($adress));
$TmpCount = $ScriptCount = count($ScriptExplode);
$ServerCount = count($ServerExplode);
$ReturnPath = "";
for($i = 1; $i < $TmpCount; $i++)
{
if($ScriptExplode[$i] == $ServerExplode[$i])
--$ScriptCount;
else
break;
}
for($i = 1; $i < $ScriptCount; $i++)
$ReturnPath .= "/..";
for($i = $TmpCount - $ScriptCount + 1; $i < $ServerCount; $i++)
$ReturnPath .= "/" . $ServerExplode[$i];
return $ReturnPath . $this->AddSlashEnd;
}
public function AddSlash($value)
{
if(is_bool($value))
{
$this->AddSlashEnd = ($value)? "/" : "";
return true;
}
else
return false;
}
}
example:
$ObjectPath = new RealPath;
$ObjectPath->RelativeScript("../a/b../c/d/f../g../h");
15-Feb-2009 08:13
for those who want to start realpath on windows platform and looking for example.
OR
for those who want to run zend framework on windows platform using the quick start guide
<?php
define( "_CUR_OS", substr( php_uname( ), 0, 7 ) == "Windows" ? "Win" : "_Nix" );
function checkCurrentOS( $_OS )
{
if ( strcmp( $_OS, _CUR_OS ) == 0 ) {
return true;
}
return false;
}
// public/index.php
//
// Step 1: APPLICATION_PATH is a constant pointing to our
// application/subdirectory. We use this to add our "library" directory
// to the include_path, so that PHP can find our Zend Framework classes.
if ( checkCurrentOS( "Win" ) ) {
$mappath = '/' . str_replace( "\\", "/", str_replace( "C:\\","", dirname(__FILE__) ) );
}
else {
$mappath = dirname(__FILE__);
}
define('APPLICATION_PATH', realpath( $mappath . '/../_privateadico/application/') );
set_include_path(
APPLICATION_PATH . '/../library'
. PATH_SEPARATOR . get_include_path()
);
?>
I took the index.php for zend which is was written for unix and ported it to windows.
The porting problem was with realpath function not understanding dirname(__FILE__) syntex on windows
28-Aug-2008 12:02
If you need to resolve a url against a base url, as the browser does with anchor tags, then realpath won't help, because it's not on your file system.
This function does that:
<?php
function resolve_href ($base, $href) {
// href="" ==> current url.
if (!$href) {
return $base;
}
// href="http://..." ==> href isn't relative
$rel_parsed = parse_url($href);
if (array_key_exists('scheme', $rel_parsed)) {
return $href;
}
// add an extra character so that, if it ends in a /, we don't lose the last piece.
$base_parsed = parse_url("$base ");
// if it's just server.com and no path, then put a / there.
if (!array_key_exists('path', $base_parsed)) {
$base_parsed = parse_url("$base/ ");
}
// href="/ ==> throw away current path.
if ($href{0} === "/") {
$path = $href;
} else {
$path = dirname($base_parsed['path']) . "/$href";
}
// bla/./bloo ==> bla/bloo
$path = preg_replace('~/\./~', '/', $path);
// resolve /../
// loop through all the parts, popping whenever there's a .., pushing otherwise.
$parts = array();
foreach (
explode('/', preg_replace('~/+~', '/', $path)) as $part
) if ($part === "..") {
array_pop($parts);
} elseif ($part!="") {
$parts[] = $part;
}
return (
(array_key_exists('scheme', $base_parsed)) ?
$base_parsed['scheme'] . '://' . $base_parsed['host'] : ""
) . "/" . implode("/", $parts);
}
?>
[EDIT BY danbrown AT php DOT net: Code contains a bugfix supplied by (Zhenya DOT Morozov AT gmail DOT com) on 23-JAN-09, to address the following issue:
'If your path contains "0" (or any "false" string) directory name, the function removes that directory from the path.']
23-Jun-2008 08:43
Because realpath() does not work on files that do not
exist, I wrote a function that does.
It replaces (consecutive) occurences of / and \\ with
whatever is in DIRECTORY_SEPARATOR, and processes /. and /.. fine.
Paths returned by get_absolute_path() contain no
(back)slash at position 0 (beginning of the string) or
position -1 (ending)
<?php
function get_absolute_path($path) {
$path = str_replace(array('/', '\\'), DIRECTORY_SEPARATOR, $path);
$parts = array_filter(explode(DIRECTORY_SEPARATOR, $path), 'strlen');
$absolutes = array();
foreach ($parts as $part) {
if ('.' == $part) continue;
if ('..' == $part) {
array_pop($absolutes);
} else {
$absolutes[] = $part;
}
}
return implode(DIRECTORY_SEPARATOR, $absolutes);
}
?>
A test:
<?php
var_dump(get_absolute_path('this/is/../a/./test/.///is'));
?>
Returns: string(14) "this/a/test/is"
As you can so, it also produces Yoda-speak. :)
08-Jun-2008 01:49
I made this function so that I could see if a user was trying to go above the current directory.
My top dir:
/var/www/dir/
User wanted
/var/www/
This comes in handy when you're making a php explorer/filemanager and you want your files in the directory above to be private.
Here it is
<?php
//usage
//$dir is the dir you are in
//$dir_top is the highest dir allowed.
//example
/*
if(above_dir('../', '/var/www/filemgr'))
die('Not allowed. Please stick to your directories');
*/
function above_dir($dir, $dir_top){
if($dir == $dir_top)
return false;
$dir = realpath($dir);
$dir_top = realpath($dir_top);
$dir = count(explode('/', $dir));
$dir_top = count(explode('/', $dir_top));
if($dir <= $dir_top){
return true;
}else{
return false;
}
}
?>
24-Apr-2008 08:21
Some users will notice that PHP applications malfunction when they upgrade to PHP 5.2.4 (included in Ubuntu 8.04 LTS) because realpath returns true for files that don't exist.
This is due to the inclusion of the Hardened-PHP Project's Suhosin Patch in many distributions by default. This patch replaces PHPs realpath function with the BSD implementation, which ignores the last path component.
The workaround is to use the file_exists function to verify that the file exists before using realpath to get its real path string.
e.g: instead of:
<?php
if (realpath($path)) {
$path = realpath($path);
} else {
throw new Exception('Path not found!');
}
?>
Do this:
<?php
if (file_exists($path)) {
$path = realpath($path);
} else {
throw new Exception('Path not found!');
}
?>
See http://www.hardened-php.net/suhosin/a_feature_list:realpath.html
19-Mar-2008 11:34
<?php
//rp like, working with absolute/relative path & a little bit shorter :p
function rp($path) {
$out=array();
foreach(explode('/', $path) as $i=>$fold){
if ($fold=='' || $fold=='.') continue;
if ($fold=='..' && $i>0 && end($out)!='..') array_pop($out);
else $out[]= $fold;
} return ($path{0}=='/'?'/':'').join('/', $out);
}
?>
03-Oct-2007 01:25
Sometimes it is helpful to check for the existance of a file
which might be found by using the include_path like in
<?php
include("file_from_include_path.php");
?>
A simple function iterates the include_path and tries all
possibilites, returns translated_local_path on success or false
if not found.
<?php
function mappath($path_to_translate){
$IncludePath=explode(PATH_SEPARATOR,get_include_path());
foreach($IncludePath as $prefix){
if(substr($prefix,-1)==DIRECTORY_SEPARATOR)
$prefix=substr($prefix,0,-1);
$try_path=sprintf("%s%s%s"
,$prefix,DIRECTORY_SEPARATOR,$path_to_translate);
if(file_exists($try_path))return($try_path);
}
return false;
}
?>
21-Sep-2007 05:15
Here's a little function to return the shortest relative path between dest folder and current folder (you can be replace $_SERVER['PHP_SEFL'] by your variable folder) :
<?php
// if you run in /var/www/
echo UnRealPath ('./'); // return "./"
echo UnRealPath ('./ajax-browser/AJAX-B/scripts/'); // return "./ajax-browser/AJAX-B/scripts/"
echo UnRealPath ('/var/'); // return "./../"
echo UnRealPath ('/opt/picasa/wine/'); // return "./../../opt/picasa/wine/"
function UnRealPath ($dest)
{
$Ahere = explode ('/', realpath($_SERVER['PHP_SEFL']));
$Adest = explode ('/', realpath($dest));
$result = '.'; // le chemin retouné dois forcement commancé par ./ c'est le but
while (implode ('/', $Adest) != implode ('/', $Ahere))// && count ($Adest)>0 && count($Ahere)>0 )
{
if (count($Ahere)>count($Adest))
{
array_pop($Ahere);
$result .= '/..';
}
else
{
array_pop($Adest);
}
}
return str_replace('//', '/', $result.str_replace(implode ('/', $Adest), '', realpath($dest)).(@is_dir(realpath($dest))?'/':''));
}
?>
21-Aug-2007 03:50
Beware that the use of a NULL value for the $path argument will give different results depending on the platform:
On Windows, realpath(null) will return the current path (same as realpath(".")).
On Linux (tested on Kernel 2.6) it will return FALSE.
20-Aug-2007 07:52
Given real paths of two files, this function finds the relative path of one ($dest) with respect to the other ($root).
<?php
echo rel_path('a/b/c', 'd/e'); // './../../a/b/c'
echo rel_path('a/b/c', 'a/b/c/d/e'); // './../..'
echo rel_path('a/b/c/d/e', 'a/b/c'); // './d/e'
function rel_path($dest, $root = '', $dir_sep = '/')
{
$root = explode($dir_sep, $root);
$dest = explode($dir_sep, $dest);
$path = '.';
$fix = '';
$diff = 0;
for($i = -1; ++$i < max(($rC = count($root)), ($dC = count($dest)));)
{
if(isset($root[$i]) and isset($dest[$i]))
{
if($diff)
{
$path .= $dir_sep. '..';
$fix .= $dir_sep. $dest[$i];
continue;
}
if($root[$i] != $dest[$i])
{
$diff = 1;
$path .= $dir_sep. '..';
$fix .= $dir_sep. $dest[$i];
continue;
}
}
elseif(!isset($root[$i]) and isset($dest[$i]))
{
for($j = $i-1; ++$j < $dC;)
{
$fix .= $dir_sep. $dest[$j];
}
break;
}
elseif(isset($root[$i]) and !isset($dest[$i]))
{
for($j = $i-1; ++$j < $rC;)
{
$fix = $dir_sep. '..'. $fix;
}
break;
}
}
return $path. $fix;
}
?>
24-Jul-2007 12:22
There might be other solutions like mine in here,
but here is one more.
This function converts Virtual Paths into Relative Paths.
I needed that at one time, and I did'nt have much luck finding a solution amongst the PHP Functions in the manual.
<?php
function GetPath($RedPath) {
if(substr($RedPath, 0, 1) == "/") {
$SysPath = dirname($_SERVER['PHP_SELF']);
if(substr($RedPath, -1) == "/") $RedPath = substr($RedPath, 0, -1);
if(strlen($SysPath) == 1)
return ".".$RedPath;
elseif(strcmp($SysPath,$RedPath) == 0)
return "./";
else {
$s_tmp = split("/", $SysPath);
$r_tmp = split("/", $RedPath);
while(($r_tmp[$i] == $s_tmp[$i]) && $i < 10)
$i++;
$t_RedPath = end(split("/", $RedPath, ($i+1)));
if($i == count($s_tmp))
return "./".$t_RedPath;
else
return str_repeat("../", count($s_tmp)-$i).$t_RedPath;
}
}
else
return $RedPath;
}
?>
16-Jul-2007 04:49
Here's a little function to return the relative path between two urls:
<?php
function get_relative_path($start_dir, $final_dir){
//
$firstPathParts = explode(DIRECTORY_SEPARATOR, $start_dir);
$secondPathParts = explode(DIRECTORY_SEPARATOR, $final_dir);
//
$sameCounter = 0;
for($i = 0; $i < min( count($firstPathParts), count($secondPathParts) ); $i++) {
if( strtolower($firstPathParts[$i]) !== strtolower($secondPathParts[$i]) ) {
break;
}
$sameCounter++;
}
if( $sameCounter == 0 ) {
return $final_dir;
}
//
$newPath = '';
for($i = $sameCounter; $i < count($firstPathParts); $i++) {
if( $i > $sameCounter ) {
$newPath .= DIRECTORY_SEPARATOR;
}
$newPath .= "..";
}
if( count($newPath) == 0 ) {
$newPath = ".";
}
for($i = $sameCounter; $i < count($secondPathParts); $i++) {
$newPath .= DIRECTORY_SEPARATOR;
$newPath .= $secondPathParts[$i];
}
//
return $newPath;
}
?>
26-Jun-2007 04:55
This is my attempt at writing a realpath replacement. I needed to to run some Adobe code on a server with realpath disabled and this seemed to do the job. It is written for a unix server, I suppose it could be made cross platform using DIRECTORY_SEPARATOR. (With thanks to Marc Noirot for his code).
<?php
function myRealPath($path) {
// check if path begins with "/" ie. is absolute
// if it isnt concat with script path
if (strpos($path,"/") !== 0) {
$base=dirname($_SERVER['SCRIPT_FILENAME']);
$path=$base."/".$path;
}
// canonicalize
$path=explode('/', $path);
$newpath=array();
for ($i=0; $i<sizeof($path); $i++) {
if ($path[$i]==='' || $path[$i]==='.') continue;
if ($path[$i]==='..') {
array_pop($newpath);
continue;
}
array_push($newpath, $path[$i]);
}
$finalpath="/".implode('/', $newpath);
// check then return valid path or filename
if (file_exists($finalpath)) {
return ($finalpath);
}
else return FALSE;
}
?>
23-Nov-2006 01:38
Here's a function to canonicalize a URL containing relative paths. Ran into the problem when pulling links from a remote page.
<?php
function canonicalize($address)
{
$address = explode('/', $address);
$keys = array_keys($address, '..');
foreach($keys AS $keypos => $key)
{
array_splice($address, $key - ($keypos * 2 + 1), 2);
}
$address = implode('/', $address);
$address = str_replace('./', '', $address);
}
$url = 'http://www.example.com/something/../else';
echo canonicalize($url); //http://www.example.com/else
?>
21-Sep-2005 04:31
Here's another function that resolves references to '/./', '/../' and extra '/' characters in the input path and returns the canonicalized pathname.
<?php
function cleanPath($path) {
$result = array();
// $pathA = preg_split('/[\/\\\]/', $path);
$pathA = explode('/', $path);
if (!$pathA[0])
$result[] = '';
foreach ($pathA AS $key => $dir) {
if ($dir == '..') {
if (end($result) == '..') {
$result[] = '..';
} elseif (!array_pop($result)) {
$result[] = '..';
}
} elseif ($dir && $dir != '.') {
$result[] = $dir;
}
}
if (!end($pathA))
$result[] = '';
return implode('/', $result);
}
echo 'input: ', $path = '..//./../dir4//./dir5/dir6/..//dir7/', '<br />';
echo 'output: ', cleanPath($path), '<br />';
?>
Will return:
input: ..//./../dir4//./dir5/dir6/..//dir7/
output: ../../dir4/dir5/dir7/
20-Jul-2005 01:55
You have a realpath.
Now you want a htmlpath.
First Suggestion:
<?php
function htmlpath($relative_path) {
$realpath=realpath($relative_path);
$htmlpath=str_replace($_SERVER['DOCUMENT_ROOT'],'',$realpath);
return $htmlpath;
}
?>
But this does not work on some servers.
Second Suggestion:
<?php
function htmlpath($realpath) {
$i = substr_count($_ENV["SCRIPT_URL"],'/')."<br>";
$baserealpath=realpath(str_repeat('../',$i-1));
$htmlpath=str_replace($baserealpath,'',$realpath);
return $htmlpath;
}
?>
08-Jun-2005 03:44
This function is also nice to test for security-breaches. You can forbid the script to access files below a certain directory to prevent "../../../etc/shadow" and similar attacks:
<?php
// declare the basic directory for security reasons
// Please do NOT attach a "/"-suffix !
$basedir = '/var/www/cgi-bin/scriptfolder';
// compare the entered path with the basedir
$path_parts = pathinfo($_REQUEST['file_to_get']);
if (realpath($path_parts['dirname']) != $basedir) {
/* appropriate action against crack-attempt*/
die ('coding good - h4x1ng bad!');
}
?>
The url "script.php?file_to_get=../../../etc/shadow" will now result in an error.
20-Dec-2004 07:43
Sometimes you may need to refer to the absolute path of a file in your website instead of a relative path, but the realpath() function returns the path relative to the server's filesystem, not a path relative to your website root directory.
For example, realpath() may return something like this:
/home/yoursite/public_html/dir1/file.ext
You can't use this in an HTML document, because the web server will not find the file. To do so, you can use:
<?php
function htmlpath($relative_path) {
$realpath=realpath($relative_path);
$htmlpath=str_replace($_SERVER['DOCUMENT_ROOT'],'',$realpath);
return $htmlpath;
}
echo '<img src="',htmlpath('../../relative/path/to/file.ext'),'" border=1>';
?>
It will return something like:
<img src="/dir1/relative/path/to/file.ext" border=1>
17-Jul-2002 11:15
note that realpath() will chop any trailing delimiter like \ or / ...don't forget to add it back on if you need it.
Eric Mueller - themepark.com
05-Jul-2001 08:38
realpath() seems to be equivalent to ASP's Server.MapPath. On my Win2k box I have successfully used realpath() to give me the full path for a file outside of the document_root. This will be very useful in conjunction with is_dir and/or is_file, which require a full path.
28-Aug-2000 05:03
mkdir (and realpath) did not work because i'd used virtual() function to replace server side include in my file.
And i've just seen that virtual() function changes the current directory ... that's why !
jerome ;)
