2

I have a plugin that I am working on which uses Email Piping. When an email is processed I want all the attachments from the email to be added to the WordPress Media Library.

Currently I am using wp_insert_attachment, wp_generate_attachment_metadata and wp_update_attachment_metadata which is working fine, however, using these functions allows for any file which is attached to an email to be added to the WP Media Library. The thing that worries me about this is that it could open up the ability for people to attach malicious files which could then be readily accessed and used for nasty purposes.

As such, what I would like to do is when handling attachments be able to identify if the attachment is a supported file type. I have investigated wp_check_filetype, wp_check_filetype_and_ext and get_allowed_mime_types which I can use to confirm the security of a file, but unless I have missed something I cannot see how to pass a file through a function to confirm if it is a supported file type.

If I can identify the files that aren't supported then I can create a zip file of these files to be uploaded rather that the raw file, which in my book should close the security hole that I can see. I am doing this for files uploaded via a form, supported files upload with media_handle_upload and unsupported are processed via PHP, added to a zip file and then attached using wp_insert_attachment, wp_generate_attachment_metadata and wp_update_attachment_metadata.

Any help would be greatly appreciated.

$upload_dir = wp_upload_dir();
$tmp_pathfile = '/home/user/public_html/wp-content/uploads/tmp_file.js';
$tmp_filename = 'tmp_file.js';
$filetype = wp_check_filetype( $tmp_pathfile );
if ( is file allowed for WordPress Media Library ) { // This is where I want to check if the file is supported by the WordPress Media Library
    $data = array(
        'guid' => $upload_dir['url'] . '/' . $tmp_filename,
        'post_title' => $tmp_filename,
        'post_content' => '',
        'post_status' => 'inherit',
        'post_mime_type' => $filetype['type']
    );
    $theID = wp_insert_attachment( $data, $tmp_pathfile );
    $attach_data = wp_generate_attachment_metadata( $theID, $tmp_pathfile );
    wp_update_attachment_metadata( $theID, $attach_data );
} else { // File not supported by the WordPress Media Library
    $zip_pathfile = $tmp_pathfile . '.zip';
    while ( file_exists( $zip_file ) ) {
        $zip_file = $tmp_pathfile . '_' . time() . '.zip';
    }
    $zip = new ZipArchive();
    if ( $zip->open( $zip_file, ZipArchive::CREATE ) ) {
        $zip->addFile( $tmp_pathfile, $tmp_filename );
        $zip->close();
        $filetype = wp_check_filetype( $zip_file );
        $data = array(
            'guid'           => $zip_file, 
            'post_mime_type' => $filetype['type'],
            'post_title'     => basename( $zip_file ),
            'post_content'   => '',
            'post_status'    => 'inherit'
        );
        $theID = wp_insert_attachment( $data, $zip_file );
        $attach_data = wp_generate_attachment_metadata( $theID, $zip_file );
        wp_update_attachment_metadata( $theID, $attach_data );
        unlink( $tmp_pathfile);
    }
}
  • Without your code it is going to be hard to give much of an answer. – s_ha_dum Jan 10 '16 at 3:44
  • Code added... all I need is to identify a function to check if a file is supported by WordPress Media Library (ie, if I tried to upload a file to the WordPress Media Library via the admin interface would it be allowed to be uploaded or rejected because the file type is not supported?) – David Clough Jan 10 '16 at 6:36
1

Ok, seems I was on the right track... I still haven't found a WordPress function that achieves what I need, but the closest I have found is to use the get_allowed_mime_types function.

I created the following function which checks if the file is within the get_allowed_mime_types array and if so returns true (file processed using wp_insert_attachment, wp_generate_attachment_metadata and wp_update_attachment_metadata) or false (file zipped and then processed using wp_insert_attachment, wp_generate_attachment_metadata and wp_update_attachment_metadata)

function is_upload_allowed( $file ) {
    $filetype = wp_check_filetype( $file );
    $file_ext = $filetype['ext'];
    $mimes = get_allowed_mime_types();
    foreach ( $mimes as $type => $mime ) {
        if ( strpos( $type, $file_ext ) !== false ) {
            return true;
        }
    }
    return false;
}

So my updated code looks like this:

$upload_dir = wp_upload_dir();
$tmp_pathfile = '/home/user/public_html/wp-content/uploads/tmp_file.js';
$tmp_filename = 'tmp_file.js';
$filetype = wp_check_filetype( $tmp_pathfile );
if ( is_upload_allowed( tmp_pathfile ) ) { // This is where I want to check if the file is supported by the WordPress Media Library
    $data = array(
        'guid' => $upload_dir['url'] . '/' . $tmp_filename,
        'post_title' => $tmp_filename,
        'post_content' => '',
        'post_status' => 'inherit',
        'post_mime_type' => $filetype['type']
    );
    $theID = wp_insert_attachment( $data, $tmp_pathfile );
    $attach_data = wp_generate_attachment_metadata( $theID, $tmp_pathfile );
    wp_update_attachment_metadata( $theID, $attach_data );
} else { // File not supported by the WordPress Media Library
    $zip_pathfile = $tmp_pathfile . '.zip';
    while ( file_exists( $zip_file ) ) {
        $zip_file = $tmp_pathfile . '_' . time() . '.zip';
    }
    $zip = new ZipArchive();
    if ( $zip->open( $zip_file, ZipArchive::CREATE ) ) {
        $zip->addFile( $tmp_pathfile, $tmp_filename );
        $zip->close();
        $filetype = wp_check_filetype( $zip_file );
        $data = array(
            'guid'           => $zip_file, 
            'post_mime_type' => $filetype['type'],
            'post_title'     => basename( $zip_file ),
            'post_content'   => '',
            'post_status'    => 'inherit'
        );
        $theID = wp_insert_attachment( $data, $zip_file );
        $attach_data = wp_generate_attachment_metadata( $theID, $zip_file );
        wp_update_attachment_metadata( $theID, $attach_data );
        unlink( $tmp_pathfile);
    }
}

It works, would still be happy to hear if there is a builtin WordPress function that achieves the same as the is_upload_allowed function I created.

  • Please accept your own answer as the best solution to the issue. This way, when someone visits this post with the same issue, they can immediatelly see that your answer solved the issue ;-) – Pieter Goosen May 11 '16 at 5:26

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.