Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

check if file exist in folder

My script:

$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. Is there another way to do it (simplier, etc.)?
  2. If $secret doesn't exist in the /codes/ folder, it produces Warning: unlink Is a directory How to get rid of that?
  3. Why $trusted always gives yes even if the file doesn't exist ?
like image 318
ZeroSuf3r Avatar asked Jan 08 '12 08:01

ZeroSuf3r


5 Answers

To delete a directory, you should be using rmdir() instead of 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...
}

Although, there is a serious security risk here! If your check_input() does not properly sanitize $secret, you could rmdir('/intl/codes/../') which is the same as deleting /intl/. Try something like this:

$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";
}
like image 69
Bailey Parker Avatar answered Nov 02 '22 09:11

Bailey Parker


  1. You can use just if (!empty($secret)) - empty() returns TRUE for NULL value as well.

  2. Use if (file_exists(ROOT . '/intl/codes/' . $secret) && !is_dir(ROOT . '/intl/codes/' . $secret)) to check if your file is not a directory and get rid of that warning. If you still wanna remove the directory, use rmdir() function.

  3. file_exists() returns TRUE for directories as well. So, you should also check if the argument is a directory with is_dir() , as i said before.

like image 24
shybovycha Avatar answered Nov 02 '22 10:11

shybovycha


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

Is there another way to do it (more simplier, etc.)?

No, Only way is to use file_exists

If $secret doesn't exist in /codes/ folder, it produce Warning: unlink Is a directory How get rid of of that?

It seems $secret points to a directory. The execution path reaches to unlink because if part returns true. So it exists. To delete a directory use rmdir()

Why $trusted always give's yes even if file doesn't exist ?

Because unlink deletes it and sets $trusted to yes. When you search after deletion you see it doesn't exist but $trusted contains yes

like image 39
Shiplu Mokaddim Avatar answered Nov 02 '22 11:11

Shiplu Mokaddim


Obviously your $secret is an empty string, but it's passing your isset() test. So the directory ROOT . '/intl/codes/' does exist (thus passing file_exists() check), but you can't unlink() the directory (neither is it your intention here).

Make sure that you have something non-empty in $_GET['secret'] and verify your check_input() function.

P.S. You probably should remove isset($secret) part of the condition. !empty($secret) is enough here and it will fix your script.

like image 1
ash108 Avatar answered Nov 02 '22 09:11

ash108


as stated by php documentation about file_exists():

Checks whether a file or directory exists

My only guess for your question #3 is: You check if file exists and it does. Only, it's not file, it's directory.

as for #2, also as stated by the error message, you can do something like this:

$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';
}

and for your #1 question, you might one to do something like this:

$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];
    }
}

A little bit of explanation:

  1. I don't know what check_input() does, so I created wrapper function for $_GET[] called input_get(). It removes the need to do isset() and also fill in the default value.
  2. I put ROOT . '/intl/codes/' . $secret; into variable $file_to_check so that you don't have to type it again and again.
like image 1
ariefbayu Avatar answered Nov 02 '22 09:11

ariefbayu