2011-06-29 15 views
5

¿Existe alguna forma en PHP de determinar una ruta absoluta dada una ruta relativa sin resolver realmente los enlaces simbólicos? Algo así como la función realpath pero sin resolución de enlace simbólico.Ruta absoluta sin resolución de enlace simbólico/Mantener al usuario en el directorio de inicio

O bien, ¿hay alguna manera fácil de comprobar si el usuario (que utiliza mi script PHP de exploración para ver archivos) no salió accidentalmente del directorio de inicio del host virtual Apache? (o no permitir que use lo desagradable ... y ... en las rutas)

¡Gracias!

Respuesta

2

No sé solución nativa de PHP para esto, pero una buena aplicación ruta absoluta está aquí: http://www.php.net/manual/en/function.realpath.php#84012

+0

¿Cómo se evita la resolución del enlace simbólico? – LeMike

+0

@MikePretzlaw A diferencia de 'realpath', esta función no hace nada en el nivel del sistema de archivos, ya que solo funciona en la modificación de cadenas. ¡Y este es el punto! :-) – Karolis

0

Puede usar open_basedir configuración ini php.ini o en declaración de host virtual (como directiva php_admin_value).

0

Aquí está mi enfoque imitando el original realpath() que también:

  1. agrega/quita de Windows letras de unidad como en c:.
  2. Elimina barras inclinadas.
  3. Prepara el directorio de trabajo actual para las rutas relativas.
  4. Opcionalmente verifica la existencia del archivo. En el caso de un archivo no existente A) no haga nada, B) devuelva un valor FALSO o C) arroje un error.
  5. Opcionalmente sigue los enlaces simbólicos.

NB: Este enfoque utiliza expresiones regulares que se sabe que son costosas para la CPU, por lo que me gusta el método utilizando matrices de http://www.php.net/manual/en/function.realpath.php#84012.

// Set constants for when a file does not exist. 
// 0: Check file existence, set FALSE when file not exists. 
define('FILE_EXISTENCE_CHECK', 0); 
// 1: Require file existence, throw error when file not exists. 
define('FILE_EXISTENCE_CHECK_REQUIRE_FILE', 1); 
// 2: Do not check file existence. 
define('FILE_EXISTENCE_CHECK_SKIP', 2); 
// Windows flag. 
define('IS_WINDOWS', preg_match('#WIN(DOWS|\d+|_?NT)#i', PHP_OS)); 
// Directory separator shortcuts. 
define('DIR_SEP', DIRECTORY_SEPARATOR); 
define('PREG_DIR_SEP', preg_quote(DIR_SEP)); 

/** 
* The original realpath() follows symbolic links which makes it harder to check 
* their paths. 
* 
* Options 
* file_existence_check: 
* - FILE_EXISTENCE_CHECK_REQUIRE_FILE: Script will break if the checked 
*  file does not exist (default). 
* - FILE_EXISTENCE_CHECK: If a file does not exist, a FALSE value will be 
*  returned. 
* - FILE_EXISTENCE_CHECK_SKIP: File existence will not be checked at all. 
* 
* follow_link: Resolve a symbolic link or not (default: FALSE). 
*/ 
function _realpath($path = NULL, $options = array()) { 
    // Merge default options with user options. 
    $options = array_merge(array(
    'file_existence_check' => FILE_EXISTENCE_CHECK_REQUIRE_FILE, 
    'follow_link' => FALSE, 
), $options); 

    // Use current working directory if path has not been defined. 
    $path = $path ? $path : getcwd(); 
    // Replace slashes with OS specific slashes. 
    $path = preg_replace('#[\\\/]#', DIR_SEP, $path); 

    // Handle `./`. Another great approach using arrays can be found at: 
    // @link p://php.net/manual/en/function.realpath.php#84012 
    $path = preg_replace('#' . PREG_DIR_SEP . '(\.?' . PREG_DIR_SEP . ')+#', DIR_SEP, $path); 
    // Handle `../`. 
    while (preg_match('#^(.*?)' . PREG_DIR_SEP . '[^' . PREG_DIR_SEP . ']+' . PREG_DIR_SEP . '\.\.($|' . PREG_DIR_SEP . '.*)#', $path, $m)) { 
    $path = $m[1] . $m[2]; 
    } 
    // Remove trailing slash. 
    $path = rtrim($path, DIR_SEP); 

    // If we are on Windows. 
    if (IS_WINDOWS) { 
    // If path starts with a lowercase drive letter. 
    if (preg_match('#^([a-z]:)(.*)#', $path, $m)) { 
     $path = strtoupper($m[1]) . $m[2]; 
    } 
    // If path starts with a slash instead of a drive letter. 
    elseif ($path[0] === DIR_SEP) { 
     // Add current working directory's drive letter, ie. "D:". 
     $path = substr(getcwd(), 0, 2) . $path; 
    } 
    } 
    else { 
    // Remove drive letter. 
    if (preg_match('#^[A-Z]:(' . PREG_DIR_SEP . '.*)#i', $path, $m)) { 
     $path = $m[1]; 
    } 
    } 

    // If path is relative. 
    if (!preg_match('#^([A-Z]:)?' . PREG_DIR_SEP . '#', $path)) { 
    // Add current working directory to path. 
    $path = getcwd() . DIR_SEP . $path; 
    } 

    // If file existence has to be checked and file does not exist. 
    if ($options['file_existence_check'] !== DSC_FILE_EXISTENCE_CHECK_SKIP && !file_exists($path)) { 
    // Return FALSE value. 
    if ($options['file_existence_check'] === DSC_FILE_EXISTENCE_CHECK) { 
     return FALSE; 
    } 
    // Or throw error. 
    else { 
     dsc_print_error('File does not exist: ' . $path); 
    } 
    } 

    // Follow sybmolic links, but only if the file exists. 
    if (!empty($options['follow_link']) && file_exists($path)) { 
    $path = readlink($path); 
    } 

    return $path; 
} 
Cuestiones relacionadas