CakePHP – Uploaded File Validation in Models

1st June, 2008 – 3:56 pm

Allowing uploaded files from users in PHP is fraught with danger, however by using CakePHP 1.2 and a little bit of Validation magic we can make things a little safer.

First, lets start by creating a simple upload form where the users will be uploading their files

<?php
# /app/views/story/create.ctp
echo $form->create(‘Story’, array(‘action’ => ‘create’, ‘type’ => ‘file’));
echo $form->input(‘Story.title’);
echo $form->input(‘Story.contents’);
echo $form->input(‘Artwork.uploaded_image’, array(‘type’ => ‘file’, ‘label’ => ‘Front Artwork’));
echo $form->end(‘Create Story’);
?>
 

Nothing particularly special here, just to note that we are specifying “type” => “file” in the $form::create method – this makes cake inset the correct ‘enc-type’ value in the generated

tag.

So when the user submits this form, they will be pointed towards the create() action in the StoryController, lets have a look at that:

<?php
# /app/controllers/story_controller.php
uses(’sanitize’);
class StoryController extends AppController {
        var $name = ‘Story’;
       
        /**
         * Allows users to create a story with an attached image.
        */

        function create() {
                // Always sanitize user input, except for the filename (which will get borked on Win32 systems)
                $uploaded_image = $this->data[‘Artwork’][‘uploaded_image’];
                $this->data = Sanitize::clean($this->data);
                $this->data[‘Artwork’][‘uploaded_image’] = $uploaded_image

                if ($this->Story->save()) {
                        // redirect to the new story.
                        $this->Session->setFlash(‘Your story was created!’);
                        $insert_id = $this->Story->getInsertID();
                        $this->redirect(‘/stories/view/’ . $insert_id);
                } else {
                        $this->Session->setFlash(‘Please correct the errors below’);
                }
        }
}
?>
 

Again, nothing unusual here, however, without any data validation we would be opening the application up to attack from malicious users – they could upload PHP code that could later be executed; for more general reading on the woes of File uploads, see what Chris Shiftlett, author of Essential PHP Security has to say.

So, in order to add some security to Image uploads, we are going to add some simple custom validation rules to the Artwork Model:

<?php
# /app/models/artwork.php
Class Artwork extends AppModel {
        var $name = ‘Artwork’;
        var $validate = array (
                ‘uploaded_image’ => array (
                        ‘valid_upload’ => array (
                                ‘rule’ => array(‘validateUploadedFile’, false)
                                ‘message’ => ‘An error occurred whilst uploading’,
                        ),
                ),
        );

        /**
         * Custom validation rule for uploaded files.
         *
         *  @param Array $data CakePHP File info.
         *  @param Boolean $required Is this field required?
         *  @return Boolean
        */

        function validateUploadedFile($data, $required = false) {
                // Remove first level of Array ($data['Artwork']['size'] becomes $data['size'])
                $upload_info = array_shift($data);

                // No file uploaded.
                if ($required && $upload_info[’size’] == 0) {
                        return false;
                }

                // Check for Basic PHP file errors.
                if ($upload_info[‘error’] !== 0) {
                        return false;
                }

                // Finally, use PHP’s own file validation method.
                return is_uploaded_file($upload_info[‘tmp_name’]);
        }
}
?>
 

Now, before the Data from the form is saved, it will be passed through the custom validation above – any invalid, or potentially malicious files will be rejected. This could easily be split into separate validation methods to provide more understandable error messages for your users.

  1. 3 Trackback(s)

  2. Jun 3, 2008: links for 2008-06-03 « Richard@Home
  3. Jun 16, 2008: Validing Image Uploades in CakePHP - JonnyReeves.co.uk
  4. Dec 30, 2008: CakePHP: Validating file uploads » Justkez

Post a Comment