views:

272

answers:

2

First my code:

class ProfileController extends Zend_Controller_Action {

private function getUploadAvatarForm()
{
    $form = new Zend_Form;
    $form->setAttrib('enctype', 'multipart/form-data');
    $form->setAction($this->view->baseUrl('/profile/upload-avatar'))
         ->setName('uploadAvatarForm')
         ->setMethod('POST');

    $element = new Zend_Form_Element_File('avatar');
    $element->setLabel('Upload an image:')
            ->addFilter('Rename',
                array('target' => '/path/toimages/directory/' . $this->userId . '.png',
                      'overwrite' => true)
            );

    $element->addValidator('Count', false, 1);
    $element->addValidator('Size', false, 102400);
    $element->addValidator('Extension', false, 'png');
    $form->addElement($element, 'avatar')
         ->addElement('submit', 'submit_upload', array('label' => 'upload'));
    return $form;
} 

public function uploadAvatarAction()
{
    $form = $this->getUploadAvatarForm();
    $this->view->form = $form;
    if (!$this->getRequest()->isPost() || !$form->isValid($_POST)) {
        return;
    }                
    if (!$form->avatar->receive()) {
        ... error...
    }
    ... ok ...
}

}

The question is: part of buissiness logic is placed into Rename filter. In my vision it worth it, but may be I'm wrong.

I'm trying to test it:

public function testUploadFile()
{
    $this->_doLogin('user', 'password');
    $this->getRequest()
         ->setMethod('POST'));
    $this->mockFileUpload();

    $this->dispatch('profile/upload-avatar');
    var_dump($this->getResponse()->getBody());
}

private function mockFileUpload()
{
    $_FILES = array(
        'avatar' => array(
            'name' => 'test.png',
            'type' => 'image/png',
            'tmp_name' => '/tmp/test.png',
            'error' => 0,
            'size' => 10127));
}

but got:

The file 'avatar' was illegal uploaded, possible attack

Could you please suggest me how to test this situation? (With filesystem everything will be ok - I'm going to use vfsStream for that, so the problem is only to emulate post upload)

A: 

In your test class, set your form to use an extended class of Zend_File_Transfer_Adapter_Http and override the isValid() method. You will obviously need to change the scope of your form function to public in your ProfileController. This is to be used with PHPUnit. I am not sure how to integrate it with Zend_Test_PHPUnit_ControllerTestCase just yet, but I will need to figure it out at some point and will update.

$class = new ProfileController();
$form = $class->getUploadAvatarForm();
$form->getElement('avatar')->setTransferAdapter(new MockAdapter());

MockAdapter.php

class MockAdapter extends Zend_File_Transfer_Adapter_Http
{
    public function isValid($files = null)
    {
        return true;
    }
}
mbelanger
A: 

I had a similar problem.

After some code reading and experimenting I discovered that my problem was caused by calling the isValid function of my form twice (caused by a minor code glitch).

Not exactly sure how but the double isValid was causing my tmp file (the uploaded file) to be deleted before the second isValid function was run, this made line 183 of Zend_Validate_File_Upload think that it wasn't a proper file upload (because the second time it looked for it it was already deleted):

If you want to check if your temp file isn't there for some reason modify line 183 of Zend_Validate_File_Upload: case 0: var_dump(file_exists($content['tmp_name'])); if (!is_uploaded_file($content['tmp_name'])) { $this->_throw($file, self::ATTACK); } break;

Perhaps your rename filter is moving or renaming the file?

Will