2014-01-15 3 views
0

В рамках проекта у меня есть возможность создавать каталоги и файлы, а также редактировать эти файлы. Но теперь я добавляю функцию удаления для удаления каталогов и всего содержимого внутри. Я провел некоторое исследование и нашел ответ переполнения стека с 2009 года, который имел два варианта. Мне любопытно, какой из них лучше, и были ли какие-либо обновления безопасности этих двух (просто убедитесь, что я использую безопасный метод). Ниже приведена копия и вставка ответа.PHP: Удалить каталог и содержимое - самый безопасный, самый надежный метод

Stack Overflow Answer:

Эта функция позволит удалить любую папку (до тех пор, как он доступен для записи), и это файлы и подкаталоги.

function Delete($path) 
{ 
    if (is_dir($path) === true) 
    { 
     $files = array_diff(scandir($path), array('.', '..')); 

     foreach ($files as $file) 
     { 
      Delete(realpath($path) . '/' . $file); 
     } 

     return rmdir($path); 
    } 

else if (is_file($path) === true) 
{ 
    return unlink($path); 
} 

return false; 
} 

Или без рекурсии с помощью RecursiveDirectoryIterator:

function Delete($path) 
{ 
    if (is_dir($path) === true) 
    { 
     $files = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($path), RecursiveIteratorIterator::CHILD_FIRST); 

     foreach ($files as $file) 
     { 
      if (in_array($file->getBasename(), array('.', '..')) !== true) 
      { 
       if ($file->isDir() === true) 
       { 
        rmdir($file->getPathName()); 
       } 

       else if (($file->isFile() === true) || ($file->isLink() === true)) 
       { 
        unlink($file->getPathname()); 
       } 
      } 
     } 

     return rmdir($path); 
    } 

    else if ((is_file($path) === true) || (is_link($path) === true)) 
    { 
     return unlink($path); 
    } 

    return false; 
    } 
+1

Я не вижу, что вы имеют значение * secure *. Оба могут нанести ущерб, если вы не знаете, что делаете. –

+0

как в уязвимостях в коде, так и в известных небезопасных методах. Я знаю, что есть определенные вещи, которые не рекомендуются из-за известных уязвимостей, и просто хотели убедиться, что они не содержат никаких. – kdjernigan

+0

^так что вы спрашиваете - это обзор кода? если да, то это может быть OT – reikyoushin

ответ

2

Вы можете также использовать базовую ОС команды, чтобы сделать это:

if(is_dir($path)) { 
    $path_escaped = escapeshellcmd(realpath($path)); 
    $output = shell_exec('rm -fR ' . $path_escaped); 
} 

Следует отметить, что вы определенно хотите, чтобы иметь возможность чтобы убедиться, что предоставленное значение $ path (если оно введено из ненадежного источника) попадает в любую директорию или набор каталогов, для которых вы хотите разрешить такую ​​функциональность.

Например, вы могли бы сделать что-то вроде:

$allowable_delete_dirs = array(
    '/var/www/some_dir/', 
    '/var/www/some_other_dir/' 
); 

if(is_dir($path)) { 
    $real_path = realpath($path); 
    $result_array = array_filter($allowable_delete_dirs, function($value) use ($real_path) { 
     return (str_pos($real_path, $value) === 0 && $real_path !== $value); 
    } 
    if (count($result_array) > 0) { 
     // the path provided matches one or more of the allowable directories 
     $output = shell_exec('rm -fR ' . escapeshellcmd($real_path)); 
    } 
} 
+2

Итак, что произойдет, если '$ path' окажется'/'? –

+0

@cryptic ツ Ну, вероятно, если он работает от имени root, PHP не будет иметь возможности выполнить. Серьезно, хотя, вероятно, было бы желательно ограничить область каталогов, которые можно было бы удалить таким образом, но это действительно не рассматривается в примерах в исходном вопросе. Для меня это может быть достигнуто путем обеспечения того, что путь, который будет использоваться, попадает в известную структуру каталогов. Я добавлю комментарий к ответу. –

+0

Как я могу убедиться, что путь попадает в определенную структуру каталогов? – kdjernigan

0

Используйте это методы для удаления любого файла или каталога, даже если каталог имеет подкаталоги:

<?php 

function list_files_dirs($dir) { 
    if (!is_dir($dir)) 
     return ('Directory ' . $dir . ' doesn\'t exists.'); 
    $files = scandir($dir); 
    unset($files[array_search('.', $files)]); 
    unset($files[array_search('..', $files)]); 
    return $files; 
} 

function delete_files($dir) { 
    if (substr($dir, -1) == '/') 
     $dir = substr($dir, 0, strlen($dir) - 1); 
    if (!is_dir($dir) && !file_exists($dir)) 
     return $dir . ' doesn\'t exists.'; 

    function rmdir_recursive($dir, $instance) { 
     foreach (list_files_dirs($dir) as $file) { 
      if (is_dir("$dir/$file")) 
       rmdir_recursive($dir . "/" . $file, $instance); 
      else 
       unlink($dir . "/" . $file); 
     } 
     rmdir($dir); 
    } 

    rmdir_recursive($dir, $this); 
    return true; 
} 
echo delete_files("directory/or/file"); 
?> 
+0

было бы трудно изменить, чтобы ограничить функцию определенным каталогом? Например, он может удалять файлы/папки только в папке '$ _SERVER ['DOCUMENT_ROOT']. '/ Directory /'. – kdjernigan

+1

просто введите 'if' в начало и проверьте, не разрешен ли каталог, затем' die ('not allowed') ' –

Смежные вопросы