How to Sanitize Image Upload?

Today I updated my plugin f(x) Favicon (no longer available, WordPress now have “Site Icon” feature), and I would like to share in how I sanitize image URL in the plugin uploader.

favicon-settingsWhy sanitize image upload?
Basically what we need is to make sure that the input is an image URL. So, we don’t want user to input other file such as document file, video file, mp3 file, etc.

And this is to make sure our plugin/theme working correctly. We also need to do this check before loading the file.

Wanted result:

<link rel="shortcut icon" href="http://siteurl.com/path/favicon.png"/>

Unwanted Result:

<link rel="shortcut icon" href="http://siteurl.com/path/some-random-file.doc"/>

 

WordPress have a neat function to check file type, wp_check_filetype() and it will return file extension and file type (mime type).

esc_url() and esc_url_raw()

WordPress also have function to make sure an input/data is an URL. Use esc_url() for general use, but if it’s for database queries and redirects use esc_url_raw().

How to use the functions

So what I did is to create a helper function to sanitize image, and we can also use this to validate the data:

/**
 * Check Image
 * @since 0.1.0
 */
function my_sanitize_image( $input ){

    /* default output */
    $output = '';

    /* check file type */
    $filetype = wp_check_filetype( $input );
    $mime_type = $filetype['type'];

    /* only mime type "image" allowed */
    if ( strpos( $mime_type, 'image' ) !== false ){
        $output = $input;
    }

    return $output
}

And we can use this function in our sanitization callback function, such as in post meta/custom fields or in our settings page. Example:

/* Register Settings */
register_setting(
    'some_option_group',
    'some_option_name', 
    'my_sanitize_callback'
);
function my_sanitize_callback( $input ){
    $new_input = array();
    if( isset( $input['image_url'] ) ){
        $new_input['image_url'] = esc_url_raw( my_sanitize_image( $input['image_url'] ) );
    }
    return $new_input;
}

and we can also use it in template/loading our function. Example:

<?php if( my_sanitize_image( $image_url ) ){ ?>
    <img src="<?php echo esc_url_raw( my_sanitize_image( $image_url ) ); ?>"/>
<?php } // end check image file ?>