mickburkejnr
mickburkejnr

Reputation: 3690

Unable to upload file in CakePHP 2

I'm trying to incorporate an upload function in my CakePHP application. I have built one before for a raw PHP project, and decided to reuse that code because I know it works. The code is as follows:

    $allowed_filetypes = array('.jpg','.gif','.bmp','.png');
    $max_filesize = 1000000; // Maximum filesize in BYTES
    $upload_path = './files/';

    $filename = $_FILES['userfile']['name'];
    $desiredname = $_POST['desiredname'];
    $ext = substr($filename, strpos($filename,'.'), strlen($filename)-1);

    $savedfile = $desiredname.$ext;

    // Check if the filetype is allowed, if not DIE and inform the user.
    if(!in_array($ext,$allowed_filetypes))
        die('The file you attempted to upload is not allowed.');

    // Now check the filesize, if it is too large then DIE and inform the user.
    if(filesize($_FILES['userfile']['tmp_name']) > $max_filesize)
        die('The file you attempted to upload is too large.');

    // Check if we can upload to the specified path, if not DIE and inform the user.
    if(!is_writable($upload_path))
        die('You cannot upload to the specified directory, please CHMOD it to 777.');

    // Upload the file to your specified path.
    if(move_uploaded_file($_FILES['userfile']['tmp_name'],$upload_path . $savedfile))
        echo 'Your file upload was successful, view the file <a href="' . $upload_path . $savedfile . '" title="Your File">here</a>'; // It worked.
    else
        echo 'There was an error during the file upload.  Please try again.'; // It failed :(.

I've put this code in to the Controller of a page that I want to upload. I have used the FormHelper in CakePHP to generate the form, which is as follows:

    <?php 
        echo $this->Form->create('Customer', array(
            'class' => 'form-horizontal',
            'action' => 'add',
            'enctype' => 'multipart/form-data'
        ));

        echo $this->Form->input('filename', array(
            'type' => 'text',
            'label' => 'Filename',
            'class' => 'span5'
        ));
        echo $this->Form->input('file', array(
            'between' => '<br />',
            'type' => 'file'
        ));
        echo $this->Form->end('Save Changes', array(
            'label' => false,
            'type' => 'submit',
            'class' => 'btn btn-primary'
        ));

        echo $this->Form->end();
     ?>

I have changed the any references to the fields in my old code to reflect the change of form being used in this project. However, I get the following errors when I submit the form:

Notice (8): Undefined index: CustomerFile [APP\Controller\CustomersController.php, line 148]

Notice (8): Undefined index: CustomerFilename [APP\Controller\CustomersController.php, line 149]

In the code in the controller, I have changed the form fields (again) to use the following:

$filename = $this->request->data['CustomerFile']['name'];
$desiredname = $this->request->data['CustomerFilename'];

But the error still occurs. I'm guessing that the form fields aren't being referenced to properly, but I thought I had referenced them properly using the $this->request code but obviously it hasn't worked. Has anyone any ideas?

Upvotes: 1

Views: 2916

Answers (2)

user1055293
user1055293

Reputation:

Page Model:

    public function beforeSave() {
    if (!empty($this->data['Page']['image']['name'])) {

        $this->data['Page']['image'] = time() . '-Featured-' . $this->data['Page']['image']['name'];
        $this->data['Page']['alias'] = $this->data['Page']['title'];
        $this->data['Page']['publish'] = date("y.m.d, h:i:s");
        $this->data['Page']['update'] = date("y.m.d, h:i:s");
        $this->data['Page']['posttype'] = 'page';

        return true;
    } else {
        if($this->action == 'edit'){
            $this->data['Page']['image'] = $this->data['Page']['img'];
            $this->data['Page']['alias'] = $this->data['Page']['title'];
            $this->data['Page']['publish'] = date("y.m.d, h:i:s");
            $this->data['Page']['update'] = date("y.m.d, h:i:s");
            $this->data['Page']['posttype'] = 'page';
            return true;
        }
    }

    return true;
}

public function fileExtension ($data) {
    if($this->data['Page']['image']['type'] != 'image/jpeg'){
        $this->invalidate('image','');
        return false;
    }
    return true;
}

Page Controller:

    public function add() {

    if (!empty($this->request->data)) {
        $menus = $this->Page->save($this->request->data);
        if (!empty($menus)) {
            move_uploaded_file($this->data['Page']['image']['tmp_name'], $_SERVER['DOCUMENT_ROOT'] . '/app/webroot/img/test/' . $this->data['Page']['image']['name']);
            $filename = $_SERVER['DOCUMENT_ROOT'] . '/app/webroot/img/test/' . $this->data['Page']['image']['name'];
            list($width,$height) = getimagesize($filename);
            $percent = 20000/$width;
            $newwidth = $width/100*$percent;
            $newheight = $height/100*$percent;
            $thumb = imagecreatetruecolor($newwidth, $newheight);
            $source = imagecreatefromjpeg($filename);
            imagecopyresampled($thumb, $source, 0, 0, 0, 0, $newwidth, $newheight, $width, $height);
            imagejpeg($thumb, $_SERVER['DOCUMENT_ROOT'] . '/app/webroot/img/test/' .  time() . '-Featured-' . $this->data['Page']['image']['name'],100);
            $this->Session->setFlash('Səhifə əlavə olundu', 'default', array('class' => 'alert alert-success'));
        }
        $this->redirect(array('action'=>'add'));
    }
}

Upvotes: 0

Marc B
Marc B

Reputation: 360562

Major non-cake problems:

  1. Rolling your own filename manipulation operation instead of using pathinfo()
  2. Filtering by user-provided filenames to determine upload eligibility. Do not EVER trust anything sent by the user. Use server-side MIME-typing operations, e.g. fileinfo
  3. Assuming the upload succeeded and doing server-side operations on that file before checking for success/failure. Always check the ['error'] code FIRST. Codes are documented here: http://php.net/manual/en/features.file-upload.errors.php
  4. Using post-upload file size limits - it's better to set the limit in php.ini, which will then allow the sever to abort the upload BEFORE it ties up your bandwidth with bytes that are simply going to be ignored later. You can use the ['error'] code to determine if the upload was aborted due to a file size limit violation.
  5. Allowing the user to specify a target filename, with absolutely NO security checks, allowing a malicious user to specify a path in that filename and allowing them to potentially scribble on ANY file on your server.

Upvotes: 3

Related Questions