|
 |
realpath (PHP 4, PHP 5) realpath -- Возвращает канонизированный абсолютный путь к файлу Описаниеstring realpath ( string path )
realpath() раскрывает все символические ссылки,
переходы типа '/./', '/../' и лишние символы '/' в
пути path, возвращая канонизированный абсолютный
путь к файлу. В этом пути не будет символических ссылок и компонентов типа
'/./' или '/../'.
realpath() возвращает FALSE при неудаче, например
если файл не существует.
Пример 1. Пример использования функции realpath()
<?php
$real_path = realpath("../../index.php");
?>
|
|
См. также описание функций basename(),
dirname() и
pathinfo().
realpath
14-Jul-2006 09:21
realpath() needs to be given a second argument that would permit use of the function on non-existent files. It is frequently required that extra path data (., ./, ../, etc.) be removed from data, but in cases where the file doesn't exist on the machine.
Would be nice to do <? realpath('/usr/rbin/../', true) ?> and have it give '/usr' as the return value, even if /usr/rbin (or even /usr) does not exist.
nospam at savvior dot com
03-Oct-2005 11:36
Hello, I was having problems getting realpath to work on a windows shared hosting machine and used this function to resolve it... hope this helps someone
Code:
<?
function realpath2($path)
{
if (strlen(realpath($path))>0)
return realpath($path);
$p=getenv("PATH_TRANSLATED");
$p=str_replace("\\","/",$p);
$p=str_replace(basename(getenv("PATH_INFO")),"",$p);
$p.="/";
if ($path==".")
return $p;
$p=$p.$path;
$dirs=split("/",$p);
foreach($dirs as $k => $v)
{
if ($v=="..")
{
$dirs[$k]="";
$dirs[$k-2]="";
}
}
$p="";
foreach($dirs as $k => $v)
{
if (strlen($v)>0)
$p.=$v."/";
}
$p=substr($p,0,strlen($p)-1);
if (is_dir($p))
return $p;
if (is_file($p))
return $p;
return false;
}
?>
bart at mediawave dot nl
21-Sep-2005 11: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 = 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/
Jonny Rylands
14-Sep-2005 03:19
Having problems with includes within include files,
particularly when the include files are in different directories?
This syntax allows:
* relative paths to be used in include strings.
* include files to include other files in different directories.
without getting file not found errors.
<?
include_once realpath(dirname(__FILE__)."/relative/path/to/include.inc.php");
?>
Tyron Madlener
14-Aug-2005 12:53
None of the functions provided here worked for me. All of them somehow had the problem with pathes like '../../downloads/bar/../foo/..' or didn't provide relative paths.
So I coded my one that justs removes '.'-dirs from the paths and simplifies stuff like 'dir/..'
function SimplifyPath($path) {
$dirs = explode('/',$path);
for($i=0; $i<count($dirs);$i++) {
if($dirs[$i]=="." || $dirs[$i]=="") {
array_splice($dirs,$i,1);
$i--;
}
if($dirs[$i]=="..") {
$cnt = count($dirs);
$dirs=Simplify($dirs, $i);
$i-= $cnt-count($dirs);
}
}
return implode('/',$dirs);
}
function Simplify($dirs, $idx) {
if($idx==0) return $dirs;
if($dirs[$idx-1]=="..") Simplify($dirs, $idx-1);
else array_splice($dirs,$idx-1,2);
return $dirs;
}
I just wonder why all the other solutions are so complex and that mine so simple, because in general the problem of simplifieng isn't that hard to solve. Well, I hope that there aren't any cases on which my solution fails. Otherwise, feel free to improve :D
phpnote at web-milk dot co dot uk
22-Jul-2005 07:01
I have written this function so that it does not matter whether the folder exists on the system. It simply traverses the given path moving up directories at every "/.." that it encounters. Though this can be used with a file at the end I would be cautious about using it with a query attached as any "/.." in the query will remove the text proir until the previous "/".
<?php
function htmlpath($relative_path)
{
$realpath = '';
$q = 0;
$relative_path = str_replace('/./', '/', $relative_path);
if ($relative_path[strlen($relative_path)-1] == '/')
{
$relative_path = substr($relative_path, 0, -1);
}
$p = strpos($relative_path, '/..', $q);
while ($p !== false)
{
if ($p != $q) $realpath .= substr($relative_path, $q, $p);
$i = strrpos($realpath, '/');
if ($i === false)
{
return false; }
$realpath = substr($realpath, 0, $i);
$relative_path = substr($relative_path, 0, $p) . substr($relative_path, $p+3);
$q = $p;
$p = strpos($relative_path, '/..', $q);
}
$realpath .= substr($relative_path, $q);
return $realpath;
}
?>
php.netatjulian-lemburg.de
20-Jul-2005 08: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;
}
?>
Lars Scheithauer <l dot scheithauer at gmx dot de>
08-Jun-2005 10: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
$basedir = '/var/www/cgi-bin/scriptfolder';
$path_parts = pathinfo($_REQUEST['file_to_get']);
if (realpath($path_parts['dirname']) != $basedir) {
die ('coding good - h4x1ng bad!');
}
?>
The url "script.php?file_to_get=../../../etc/shadow" will now result in an error.
pulstar at ig dot com dot br
20-Dec-2004 01: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>
carlosreche at yahoo dot com
16-Dec-2004 03:52
In my last function, it will always discard "../" if there are no more parent dirs to go back. But it's a mistake! For example, relative paths like "../../downloads" returns "downloads/", and it should return exactly the same entry (because parent directories for "downloads" may exist in this case). Well, I've corrected this bug. Now:
"C:/downloads/../../../" returns "C:/"
"downloads/../../../" returns "../../"
<?php
function real_path($path)
{
if ($path == "")
{
return false;
}
$path = trim(preg_replace("/\\\\/", "/", (string)$path));
if (!preg_match("/(\.\w{1,4})$/", $path) &&
!preg_match("/\?[^\\/]+$/", $path) &&
!preg_match("/\\/$/", $path))
{
$path .= '/';
}
$pattern = "/^(\\/|\w:\\/|https?:\\/\\/[^\\/]+\\/)?(.*)$/i";
preg_match_all($pattern, $path, $matches, PREG_SET_ORDER);
$path_tok_1 = $matches[0][1];
$path_tok_2 = $matches[0][2];
$path_tok_2 = preg_replace(
array("/^\\/+/", "/\\/+/"),
array("", "/"),
$path_tok_2);
$path_parts = explode("/", $path_tok_2);
$real_path_parts = array();
for ($i = 0, $real_path_parts = array(); $i < count($path_parts); $i++)
{
if ($path_parts[$i] == '.')
{
continue;
}
else if ($path_parts[$i] == '..')
{
if ( (isset($real_path_parts[0]) && $real_path_parts[0] != '..')
|| ($path_tok_1 != "") )
{
array_pop($real_path_parts);
continue;
}
}
array_push($real_path_parts, $path_parts[$i]);
}
return $path_tok_1 . implode('/', $real_path_parts);
}
?>
ash at spamless dot theleys dot net
19-Nov-2004 09:37
sarizmendi is right, and this is very frustrating. I'm trying to use a script with a different virtual root, which process folders/contents. This works perfectly with asp's server.mappath() but realpath() fails, because it's mapping to the same doc root (C:\inetpub\wwwroot) when it should be from a different virtual path (i.e. D:\content). Although I could force this to the static path, I'm trying to use it with a $_GET, and this could point to any of a number of virtual roots.
ilgarm -at- azeronline.com
11-Mar-2004 11:43
I've tested several examples given by other ppls but none were working, at least on windows. so I spent time and wrote my own function for realpath( ) replacement that will work with non-existing paths also.
Here it is. Please, check it, if you have time and let me know about the results. Thanks.
<?php
define( "_PL_OS_SEP", "/" );
define( "_CUR_OS", substr( php_uname( ), 0, 7 ) == "Windows" ? "Win" : "_Nix" );
function checkCurrentOS( $_OS )
{
if ( strcmp( $_OS, _CUR_OS ) == 0 ) {
return true;
}
return false;
}
function isRelative( $_dir )
{
if ( checkCurrentOS( "Win" ) ) {
return ( preg_match( "/^\w+:/", $_dir ) <= 0 );
}
else {
return ( preg_match( "/^\//", $_dir ) <= 0 );
}
}
function unifyPath( $_path )
{
if ( checkCurrentOS( "Win" ) ) {
return str_replace( "\\", _PL_OS_SEP, $_path );
}
return $_path;
}
function getRealpath( $_path )
{
$__path = $_path;
if ( isRelative( $_path ) ) {
$__curdir = unifyPath( realpath( "." ) . _PL_OS_SEP );
$__path = $__curdir . $__path;
}
$__startPoint = "";
if ( checkCurrentOS( "Win" ) ) {
list( $__startPoint, $__path ) = explode( ":", $__path, 2 );
$__startPoint .= ":";
}
$__realparts = array( );
$__parts = explode( _PL_OS_SEP, $__path );
for ( $i = 0; $i < count( $__parts ); $i++ ) {
if ( strlen( $__parts[ $i ] ) == 0 || $__parts[ $i ] == "." ) {
continue;
}
if ( $__parts[ $i ] == ".." ) {
if ( count( $__realparts ) > 0 ) {
array_pop( $__realparts );
}
}
else {
array_push( $__realparts, $__parts[ $i ] );
}
}
return $__startPoint . _PL_OS_SEP . implode( _PL_OS_SEP, $__realparts );
}
echo "getRealpath ../../x: ". getRealpath( "../../x" ) . "<BR>\n";
echo "getRealpath ./../x: ". getRealpath( "./../x" ) . "<BR>\n";
echo "getRealpath x: ". getRealpath( "x" ) . "<BR>\n";
echo "getRealpath /../x: ". getRealpath( "/../x" ) . "<BR>\n";
echo "getRealpath d:/../../x: ". getRealpath( "d:/../../x" ) . "<BR>\n";
echo "getRealpath ./../xx/xxx/.////../yyy: ". getRealpath( "./../xx/xxx/.////../yyy" ) . "<BR>\n";
?>
eric at themepark dot com
17-Jul-2002 06: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
jemptyg at rwmc dot net
05-Jul-2001 03: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.
jerome at dot451 dot com
28-Aug-2000 12: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 ;)
| |