0

I'm implementing a script which to validate an image for upload using php. Actually, the php script is working well with gif, png, and jpg image file, but when i have one condition that:

  1. I took an image theFileName.bmp and renamed its extension to theFileName.jpg.
  2. Then I select the renamed one to upload.

I renamed the image file name manually on my computer and then I selected the file to upload.

The uploading process tooks around 2 or 3 seconds then nothing showed up (not even an error), only the default message from browser displayed:

The connection to localhost was interrupted.

How can I prevent the user from selecting an image file (and any other file for that matter) which is not an actual valid image?

Solutions here

Finally, I managed to come up with my own solutions. It's a bit long but at least it can get the work done! Hope it might help someone.

  1. It helps prevent from user upload not wanted mime-type
  2. Prevent from user uses text file and renamed its extension and so on.
  3. Prevent from user uses text file and changes its mime-type
  4. Prevent from the file is unreadale
  5. Prevent from the file contains error
  6. Prevent from upload not an http
  7. Prevent from the image file size width: 0, height: 0
  8. There are still more things to validate and check in order to make sure it's safe by this means.

    # CHECK & TRY READ IMAGE FILE
    function is_readable_image( $theTmpFileloc ){
        try {
            if ( !getimagesize( $theTmpFileloc ) ){
                # THE IMAGE IS UNREADABLE
                return false;
            }
            # THE IMAGE IS READABLE
            return true;
    
        }catch( Exception $e ){
            # THE IMAGE IS OTHER FILE
            return false;
        }
    }
    # READ AND RETURN AN ARRAY OF IMAGE SIZES
    function get_image_size( $theTmpFileloc ){
        $imageSizes = array();
        $tmpResults = getimagesize( $theTmpFileloc );
        $imageSizes['width']  = $tmpResults[0];
        $imageSizes['height'] = $tmpResults[1];
    
        # IF EITHER WIDTH OR HEIGHT = 0, RETURN FALSE
        if ( $tmpResults[0] == 0 || $tmpResults[1] == 0 ) {
            return false;
        }
    
        return $imageSizes;
    }
    # READ AND RETURN AN IMAGE ACTUAL MIMETYPE
    function get_image_mime( $theTmpFileloc ){
        $imageMime  = '';
        $tmpResults = getimagesize( $theTmpFileloc );
        $imageMime  = $tmpResults['mime'];
    
        return $imageMime;
    }
    
    # START OF PHP TO VALIDATE IMAGE FILE
    if ( isset($_FILES['postImage']) && !empty($_FILES['postImage']['name']) ) {
        $tmpFileLoc      = $_FILES['postImage']['tmp_name'];
        $array_file_type = array('image/gif', 'image/png', 'image/x-png', 'image/jpeg', 'image/pjpeg');
    
        if ( $_FILES['postImage']['error'] == 1 ) {
            # THE IMAGE FILE CONTAINS ERROR
            $resMessage['Error']        = true;
    
        }elseif ( !is_uploaded_file( $tmpFileLoc ) ) {
            # PREVENT FROM UPLOADING FROM EXTERNAL SOURCE NOT HTTP
            $resMessage['Error']        = true;
    
        }elseif ( !is_readable_image( $tmpFileLoc ) ) {
            # PREVENT FROM IMAGE IS INVALID OR OTHER MIMETYPE
            $resMessage['Error']        = true;
    
        }elseif ( !get_image_size( $tmpFileLoc ) ) {
            # PREVENT FROM IMAGE SIZE 0, 0 OR INVALID ACTUAL MIMETYPE
            $resMessage['Error']        = true;
    
        }elseif ( !in_array( get_image_mime( $tmpFileLoc ), $array_file_type) ) {
            # LEVEL 2 OF CHECKING AN IMAGE MIMETYPE
            $resMessage['Error']        = true;
    
        }else {
            # other checks with file extension, max_size, 
            # dir is_writable and so on then move to move_uploaded_file
        }   
    }
    
Nathan
  • 11,814
  • 11
  • 50
  • 93
Thavarith
  • 287
  • 1
  • 3
  • 13
  • 1
    You can't, because you (the PHP script) don't have the image data yet. If the user is dumb enough to change the extension on an image, then they deserve to wait before being told it wont work. – Jonathon Reinhart Mar 29 '12 at 05:18
  • @Jonathon Reinhart: thanks for info. I can't really believe that the PHP cannot do that for image file. – Thavarith Mar 29 '12 at 05:22
  • @Dagon: thanks but the PHP script don't know why cannot detect that at all...it simply skips all the validation codes and browser detects and shows error instead. – Thavarith Mar 29 '12 at 05:25
  • @Thavarith, skips the validation code, what code, are we expected to guess –  Mar 29 '12 at 05:32
  • @Dagon, oops! forgot to mention that. i mean after i've done the changing image file extension then process to the uploading, php seems unable to validate the image file. – Thavarith Mar 29 '12 at 05:37
  • @Jonathon Reinhart, you're right, no matter how i use PHP script to detect that, it won't success...only browser detects and shows error. – Thavarith Mar 29 '12 at 06:07
  • Finally, i managed to get the answer working well for me now. Thanks to all :) – Thavarith Mar 29 '12 at 07:55

2 Answers2

2

To give more security to your php script you should Use getimagesize(). If it returns FALSE it is not an image. Try also to make sure that the file is not too small. In addition you can use GD library.

Sorry for delaying you. you should give us a good example next time LOL.

  • thanks, i've updated my question. I renamed the image extension from my pc then i selected the file to upload. I din't use PHP script to do that. The purpose is to detect if php able to detect the image file is not a valid image type allowed or actual one. – Thavarith Mar 29 '12 at 05:30
  • so do you want to make the user only choose .jpg files from his computer ? – Othman Abahossain Mar 29 '12 at 05:34
  • partially, yes. The fact is that i want to upload .gif, .png, .jpg | .jpeg file. My php script works well but it fails when as i mentioned in the question. – Thavarith Mar 29 '12 at 05:41
  • Thanks, but it won't work somehow. Maybe you don't fully understand my purpose. My php script is working well with the 3 types of images except after i renamed an extension of a file which is not applicable for actual image. For instance: i renamed theFilename.doc to theFilename.jpg then click upload. It fails! – Thavarith Mar 29 '12 at 06:04
  • check my answer again. sorry :D – Othman Abahossain Mar 29 '12 at 06:13
0

Try this code

<?php
if (isset($_FILES['photo']))
{
    $mimetype = mime_content_type($_FILES['photo']['tmp_name']);
    if(in_array($mimetype, array('image/jpeg', 'image/gif', 'image/png'))) {
      move_uploaded_file($_FILES['photo']['tmp_name'],
      '/images/' . $_FILES['photo']['name']);
      echo 'OK';
    } else {
         echo 'Not an image file!';
    }
}
Naveen Kumar
  • 4,543
  • 1
  • 18
  • 36
  • php script, the function mime_content_type is processed only after the selected file was uploaded into somewhere in tmp directory (only after is_uploaded_file is called). In my case, the file is unable to process since its actual mime type is invalid, as i mentioned in my question. Thanks anyway! – Thavarith Mar 29 '12 at 06:00