Validating files on nodes with FileField and CCK
Posted on: Friday, December 4th 2009 by Afraaz Ali

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 ~

Comments

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

The above process now makes us easy to upload video in YouTube and other video upload site. The video upload module and CSK module is the key feature of the process. This module allowed us to upload videos directly to our Youtube account.
Lewis - Rolex submariner watches for sale

Post new comment

The content of this field is kept private and will not be shown publicly.
Type the characters you see in this picture. (verify using audio)
Type the characters you see in the picture above; if you can't read them, submit the form and a new image will be generated. Not case sensitive.