-2


First of all, I'll request to not mark my question as duplicate. Because I have googled my problem a lot and didn't find solution of my problem. There is a lot of problem of permission denied on unlink but my problem for this is totally different. So, first read my problem carefully below.

I am creating a user based website. On profile edit, i am updating profile picture. Currently, there is no image on users database, but i am checking in backend that if profile pic exists in user db, then unlink (delete) that first from folder and then update with new one. But i am getting permission denied error on unlink if there is no image. But if there is image, i didn't get any permission denied error. So all i need to call that unlink function only on that condition if user image exists in db. But I've tried to do this a lot. I am failed again and again.
Here is my function code:

public function updateProfilePic($file, $userid) {
        $this->selectImgOnUpdating($userid);

        $filename = $file['user_img']['name'];
        $filetmp = $file['user_img']['tmp_name'];
        $valid_ext = array('png', 'jpeg', 'jpg');
        $location = "user/profilepic/" . $filename;
        $file_extension = pathinfo($location, PATHINFO_EXTENSION);
        $file_extensionstr = strtolower($file_extension);

        if (in_array($file_extensionstr, $valid_ext)) {
            $this->compressImage($filetmp, $location, 60);

            $updateuserpic = $this->updateProfilePicture($filename, $userid);
            return $updateuserpic;
        } else {
            $msg = '<div class="alert alert-danger" role="alert">Invalid file type. You can upload only:-' . implode(', ', $valid_ext) . '<button type="button" class="close" data-dismiss="alert" aria-label="Close"><span aria-hidden="true">&times;</span></button></div>';
            return $msg;
        }
    }

    public function selectImgOnUpdating($userid){
        $query = "SELECT user_img from users WHERE user_id = '$userid'";
        $result = $this->db->select($query);
        if ($result) {
            $deleteImg = $result->fetch_assoc();
            $deleteLink = $deleteImg['user_img'];
            $path = "user/profilepic/$deleteLink";
            unlink($path);
        }
    }

    public function updateProfilePicture($filename, $userid){
        $update = "UPDATE users SET user_img = '$filename' WHERE user_id = '$userid'";
        $result = $this->db->update($update);
        if($result){
            $msg = '<div class="alert alert-success" role="alert">Profile picture uploaded successfully <a href="profile.php">Go back</a><button type="button" class="close" data-dismiss="alert" aria-label="Close"><span aria-hidden="true">&times;</span></button></div>';
            return $msg;
        } else {
            $msg = '<div class="alert alert-danger" role="alert">Error while uploading profile picture. Pleas try again!<button type="button" class="close" data-dismiss="alert" aria-label="Close"><span aria-hidden="true">&times;</span></button></div>';
            return $msg;
        }
    }

Now, i've tried to put check condition first on fetching.

public function selectImgOnUpdating($userid){
        $query = "SELECT user_img from users WHERE user_id = '$userid'";
        $result = $this->db->select($query);
        if ($result) {
            $deleteImg = $result->fetch_assoc();
            $deleteLink = $deleteImg['user_img'];
            $count = $result->num_rows;
            if($count > 0){
                $path = "user/profilepic/$deleteLink";
                unlink($path);
            }
        }
    }

It's also not working, i am still getting that permission denied error. On edit profile, there is one button named "Update profile pic", and new user can upload/update from that.
Currently there is no image in users database row. (So, i am still updating it, because i am doing it with only one function/page. ) On update function, i am first fetching user image, and want to check that if user image exists there then delete/unlink that from folder and then run update function below.

Dharman
  • 30,962
  • 25
  • 85
  • 135
Zain Shabir
  • 79
  • 3
  • 11
  • 4
    Just a side note. Saying: _" I'll request to not mark my question as duplicate"_ doesn't really do anything. If we find a duplicate question/answer, it _should_ be marked as a duplicate. – M. Eriksson Aug 26 '19 at 08:01
  • 1
    what are the permissions to the profilepic folder? – sid Aug 26 '19 at 08:01
  • Sure, but if matched with my problem. So first carefully read my full problem above what i am saying and what I've explained. – Zain Shabir Aug 26 '19 at 08:02
  • 4
    Can't you just check if the file exists before you try and delete it? `if (is_file($path)) { unlink($path); }` – M. Eriksson Aug 26 '19 at 08:02
  • That's how we usually do it. We don't just randomly mark posts as duplicates if they aren't – M. Eriksson Aug 26 '19 at 08:03
  • Brother, It's in the E disc. The problem is, If user_img is not exists in db then it's giving me permission deinied error on unlink, but if user_img exists in folder, then it's not giving me any error. I juts want that when update function runs then first check on fetching image that if image exists or not, if not exists then don't call unlink call, if exists then call unlink function. – Zain Shabir Aug 26 '19 at 08:05
  • 3
    How does that differ from my suggestion about checking if the file exists before trying to delete it? If you try it, it should do just that. `is_file($path)` will check if the path is valid and leads to a file. If `$deleteLink` is empty, then `is_file()` will return false since the path will go to a directory and not a file. – M. Eriksson Aug 26 '19 at 08:06
  • yeah your answer worked @MagnusEriksson. Actually i did it before with `if(file_exists())` but didn't worked. But with your answer `if(is_file())`, it worked now. Thanks a lot – Zain Shabir Aug 26 '19 at 08:11
  • prepare statement means PDO? – Zain Shabir Aug 26 '19 at 08:12
  • 1
    That's because `file_exists()` returns true for folders as well. You need to check if the path is a file, and not a folder (which it will be if `$deleteLink` is empty) which is why `is_file()` works and `file_exists()` doesn't in this case. – M. Eriksson Aug 26 '19 at 08:13
  • _"prepare statement means PDO?"_ - You can use prepared statements with mysqli as well. I would recommend using PDO though since it gives you a way more verbose API than mysqli. But that's more of a preference. – M. Eriksson Aug 26 '19 at 08:14
  • I've posted an answer. Since it helped you, you can accept it and let others know the problem has been resolved. – M. Eriksson Aug 26 '19 at 08:21
  • yeah I've accepted. Thanks a lot – Zain Shabir Aug 26 '19 at 09:14

2 Answers2

2

The problem is that if there is no user image, your $path-variable will just contain the path to the folder, which you then are trying to unlink.

Just check if the file exists before unlinking:

$deleteLink = $deleteImg['user_img'];
$path = "user/profilepic/$deleteLink";

if (is_file($path)) {
    // The path exists and is a file
    unlink($path);    
}

This won't work with file_exists() though since that function returns true even if the path is a folder. Since $path will just contain a folder if the user doesn't have an image name in the DB, you would end up with the exact same problem as before.

is_file() will check if the path exists and if it is a file.

M. Eriksson
  • 13,450
  • 4
  • 29
  • 40
0

You say that when the profile has an image it work but if there is no image it give you permission denied so

first check the privilege in your uploading directory

make it 775 or 777

Never use permission 777 in deploy just for testing

second use is_file it will help you to check if there is an image or not so you can make it like this

if(is_file('your image path')){
   unlink('your image path');
}

and at last use the prepared statement as they say to you in comments to protect you from SQL injection

Joseph
  • 5,644
  • 3
  • 18
  • 44
  • 3
    No need to mess around with the file permissions since they say they _can_ delete the files as long as they exist. Also... **don't use `file_exists()`** since that will return 'true' for folders as well. If the user doesn't have an image, then the `$path`-variable will lead to the folder (and there for return `true`) and it will try and delete the folder, resulting in the exact same problem. – M. Eriksson Aug 26 '19 at 08:09
  • 1
    @Ingus i know it isn't a good idea but for check purpose only – Joseph Aug 26 '19 at 08:10
  • 1
    not worked with `file_exists()` function, but worked with `if(is_file())` – Zain Shabir Aug 26 '19 at 08:14
  • @FavCartoons i fixed it in the answer give me feedback – Joseph Aug 26 '19 at 08:20