проверьте, существует ли файл в папке - PullRequest
5 голосов
/ 08 января 2012

Мой скрипт:

$secret = check_input($_GET['secret']);
if(isset($_POST['register'])) {
    if (isset($secret) || !empty($secret)) {
        if (file_exists(ROOT . '/intl/codes/' . $secret)) {
            unlink(ROOT . '/intl/codes/' . $secret);
            $trusted = 'yes';
        } else {
            $trusted = 'no';
        }
    }
//$_POST['register'] register details...
}
  1. Есть ли другой способ сделать это (проще и т. Д.)?
  2. Если $secret не существует в папке /codes/, выдается Warning: unlink Is a directory Как избавиться от этого?
  3. Почему $trusted всегда дает yes, даже если файл не существует?

Ответы [ 5 ]

6 голосов
/ 08 января 2012

Чтобы удалить каталог, вы должны использовать rmdir() вместо unlink().

$secret = check_input($_GET['secret']);
if(isset($_POST['register'])) {
    if (!empty($secret)) {
        if(file_exists(ROOT . '/intl/codes/' . $secret)) {
            rmdir(ROOT . '/intl/codes/' . $secret);
            $trusted = 'yes';
        } else {
            $trusted = 'no';
        }
    }
    //$_POST['register'] register details...
}

Хотя здесь существует серьезная угроза безопасности! Если ваш check_input() неправильно очищает $secret, вы можете rmdir('/intl/codes/../'), что аналогично удалению / intl /. Попробуйте что-то вроде этого:

$allowed = ROOT. '/intl/codes/';
$path = realpath($allowed . check_input($_GET['secret']));

if(strpos($path, $allowed) === 0) {  //Check that $path is within allowed directory
    if(is_dir($path)) {
        rmdir($path);
    } else if(file_exists($path)) {
        unlink($path);
    } else {
        echo "File/folder not found";
    }
} else {
    echo "Untrusted user tried to delete outside of allowed directory";
}
1 голос
/ 08 января 2012

как указано в документации php о file_exists():

Checks whether a file or directory exists

Мое единственное предположение для вашего вопроса № 3: Вы проверяете, существует ли файл, и он существует. Только это не файл, это каталог.

Что касается # 2, также, как указано в сообщении об ошибке, вы можете сделать что-то вроде этого:

$ file_to_check = ROOT. '/ intl / codes /'. $ Секрет;

if (file_exists($file_to_check)) {
    if( !is_dir( $file_to_check ) )
        unlink($file_to_check);
    else
        rmdir( $file_to_check );
    $trusted = 'yes';
}

и для вашего вопроса №1 вы можете сделать что-то вроде этого:

$secret = input_get($_GET['secret']);
if(isset($_POST['register']) && !empty($secret)) {

    $file_to_check = ROOT . '/intl/codes/' . $secret;
    if (file_exists($file_to_check)) {
        if( !is_dir( $file_to_check ) )
            unlink($file_to_check);
        else
            rmdir( $file_to_check );
        $trusted = 'yes';
    } else {
        $trusted = 'no';
    }
}

function input_get($key, $default = ""){

    if(!isset($_GET[$key])){
        return $default;
    } else {
        //do input cleanup first, if you want
        return $_GET[$key];
    }
}

Немного объяснений:

  1. Я не знаю, что делает check_input(), поэтому я создал функцию-обертку для $_GET[], которая называется input_get(). Это избавляет от необходимости делать isset(), а также заполнять значение по умолчанию.
  2. Я положил ROOT . '/intl/codes/' . $secret; в переменную $file_to_check, чтобы вам не приходилось вводить ее снова и снова.
1 голос
/ 08 января 2012

Очевидно, что $secret - пустая строка, но она проходит ваш isset() тест. Таким образом, каталог ROOT . '/intl/codes/' существует (таким образом, проходя проверку file_exists()), но вы не можете unlink() каталог (и это не ваше намерение здесь).

Убедитесь, что в $_GET['secret'] есть что-то непустое, и проверьте check_input() функцию.

P.S. Вы, вероятно, должны удалить isset($secret) часть условия. !empty($secret) здесь достаточно, и это исправит ваш сценарий.

1 голос
/ 08 января 2012
    if (file_exists(ROOT . '/intl/codes/' . $secret)) {
        unlink(ROOT . '/intl/codes/' . $secret);
        $trusted = 'yes';
    } else {
        $trusted = 'no';
    }

Есть ли другой способ сделать это (проще и т. Д.)?

Нет, единственный способ использовать file_exists

Если $ secret не существует в папке / codes /, выдается предупреждение: unlink Является ли каталог Как избавиться от этого?

Кажется, $secret указывает на каталог. Путь выполнения достигает unlink, поскольку if part возвращает true. Так оно и есть. Чтобы удалить каталог, используйте rmdir()

Почему $ trust всегда дает да, даже если файл не существует?

Потому что unlink удаляет его и устанавливает $trusted на yes. При поиске после удаления вы видите, что он не существует, но $trusted содержит yes

1 голос
/ 08 января 2012
  1. Вы можете использовать только if (!empty($secret)) - empty() и TRUE возвращает значение NULL.

  2. Используйте if (file_exists(ROOT . '/intl/codes/' . $secret) && !is_dir(ROOT . '/intl/codes/' . $secret)), чтобы проверить, не является ли ваш файл каталогом, и избавьтесь от этого предупреждения. Если вы все еще хотите удалить каталог, используйте функцию rmdir().

  3. file_exists() возвращает TRUE также для каталогов. Итак, вы также должны проверить, является ли аргумент каталогом с is_dir(), как я уже говорил.

...