Validating files on nodes with FileField and CCK

Fri, Dec 4, 2009 by Afraaz

Recently I was working on a project where users were able to upload videos, the format in our case didn't matter since we were uploading to Youtube anyway. Allowing users to upload videos was easily done with the Video Upload module and the CCK module. This module allowed us to upload videos directly to our Youtube account. From here, we waited for the next cron run and the video's would be processed, published and viewable by users of the site. Fast, simple, and all done without any custom coding, sweet!

Only a few issues, first we couldn't really verify that the file being uploaded was actually a video file, since we could just manipulate the extension. The big issue was after we ran the initial security scans, we found that we forgot to scan these uploaded files. Turns out that the files were being stored in an S3 bucket for backup purposes, and we had an htaccess file so users would not be able to actually download the video files. But we still needed to solve these glaring issues. So off I went searching for another module that could solve these errors, and I ran in to the File Framework module. This module allowed for scanning the file, but I found it could be overkill, so I decided to use a custom module.

What we basically did in this module was check the mime type of the file and scan it via an antivirus. The code looked similar to this:


/**
 * Implementation of hook_form_alter
 */
function MODULENAME_form_alter(&$form, $form_state, $form_id) {
   if ($form_id == FORM_ID) {
     $form[FIELD_NAME][0]['#upload_validators'][FUNCTION_NAME] = array();
  }
}
function FUNCTION_NAME($field) {
  //Do some processing
}

In the code above MODULENAME can be replaced with your module name. The FORM_ID can be replaced with the form id you're altering. The FIELD_NAME is replaced by the internal name you have given your file field. Finally the FUNCTION_NAME will be replaced by the validating functions name.

So, basically, what I needed to do first was the mime type check. In order to do this I used this snippet:


exec(escapeshellcmd('file --mime-type -b') .' '. escapeshellarg($field->filepath), $mimes);

What this code does is run the shell command file found on servers running *nix, and returns the output in an array. I basically iterated through the matches and checked to see if the file was of an acceptable type. If not, we return an array of errors like so:


if (condition is not met) {
  $errors[] = t('Your error message');
}
return $errors;

Alright, one down, one more to go. I needed to run an antivirus scan on this file before it was uploaded. For this I first installed ClamAV. I'm using Ubuntu 9.10 (Karmic Koala), so in order to install ClamAV I needed to do the following:

Now, after that installation I added the following lines to my validating function:


if (exec(escapeshellcmd(CLAM_AV_PATH) .' '. escapeshellarg($field->filepath), $output)) {
   if (preg_match('/FOUND$/', $output[0])) {
      $result = preg_replace('/^.* (\\S+) FOUND$/', '$1', $output[0]);
      $errors[] = t('Please upload an appropriate file.');
  }
}

This bit of code was taken from the antivirus portion of the File Framework module.

That was all I needed to do to make sure the mime type was correct and the file was safe. The rest was contributed modules. Gotta love the Drupal community. If anyone has a simpler way of doing this leave in the comments, perhaps a hook implementation from Filefield.

The interweb my ~ away from ~

jcmarco posted on December 5, 2009 8:42 am

And using the getid3 module that already do all that and it is integrated with the filefield module?

Post new comment

The content of this field is kept private and will not be shown publicly.
  • Web page addresses and e-mail addresses turn into links automatically.
  • Allowed HTML tags: <a> <em> <strong> <cite> <code> <ul> <ol> <li> <dl> <dt> <dd> <img> <h2>
  • Lines and paragraphs break automatically.

More information about formatting options