2011-06-29 15 views
5

Czy istnieje sposób w PHP, jak określić bezwzględną ścieżkę, biorąc pod uwagę ścieżkę względną, bez faktycznego rozdzielania dowiązań symbolicznych? Coś w rodzaju funkcji realpath, ale bez rozdzielczości łącza symlink.Bezwzględna ścieżka bez rozdzielczości symlink/Zachowaj użytkownika w katalogu domowym

A może istnieje prosty sposób sprawdzenia, czy użytkownik (który przegląda pliki za pomocą mojego skryptu PHP) nie usunął przypadkowo katalogu domowego serwera wirtualnego Apache? (lub zabronić mu używania brzydkich i ... ścieżek)

Dzięki!

Odpowiedz

2

nie wiem PHP natywne rozwiązanie tego problemu, ale jeden ładny ścieżka bezwzględna realizacja jest tutaj: http://www.php.net/manual/en/function.realpath.php#84012

+0

W jaki sposób unika się rozwiązania problemu z odsyłaczami? – LeMike

+0

@MikePretzlaw W przeciwieństwie do 'realpath', ta funkcja nie robi niczego na poziomie systemu plików, ponieważ działa tylko na modyfikacji napisów. I o to chodzi! :-) – Karolis

0

Możesz użyć ustawienia open_basedir ini php.ini lub w deklaracji hosta wirtualnego (jako dyrektywa php_admin_value).

0

Tu jest moje podejście naśladując oryginalną realpath() który również:

  1. Dodaje/Usuwa systemu Windows litery dysku, jak w c:.
  2. Usuwa ukośne ukośniki.
  3. Dodaje bieżący katalog roboczy do ścieżek względnych.
  4. Opcjonalnie sprawdza istnienie pliku. W przypadku nieistniejącego pliku A) nic nie rób, B) zwracaj wartość FALSE lub C) zgłaszaj błąd.
  5. Opcjonalnie podąża za dowiązaniami symbolicznymi.

NB: W tym podejściu używane są wyrażenia regularne, które są znane z dużej ilości procesora, więc podoba mi się metoda z wykorzystaniem tablic z 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; 
} 
Powiązane problemy