Как проверить функцию загрузки файла с логикой, помещенной в фильтр переименования (Zend_Form_Element_File)? - PullRequest
0 голосов
/ 12 октября 2009

Первый мой код:

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 ...
}

}

Вопрос в том, что часть бизнес-логики помещается в фильтр переименования. На мой взгляд, оно того стоит, но, может быть, я ошибаюсь.

Я пытаюсь проверить это:

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));
}

но получил:

Файл "Аватар" загружен незаконно, возможна атака

Не могли бы вы предложить мне, как проверить эту ситуацию? (С файловой системой все будет хорошо - я собираюсь использовать для этого vfsStream, поэтому проблема заключается только в эмуляции загрузки после)

Ответы [ 2 ]

0 голосов
/ 17 сентября 2010

У меня была похожая проблема.

После некоторого чтения кода и экспериментов я обнаружил, что моя проблема была вызвана двойным вызовом функции isValid моей формы (вызванной незначительным сбоями кода).

Не совсем уверен, как, но двойной isValid вызывал удаление моего tmp-файла (загруженного файла) перед запуском второй функции isValid. Это заставило строку 183 Zend_Validate_File_Upload подумать, что загрузка файла была неправильной (потому что во второй раз его искали уже удалили):

Если вы хотите по какой-то причине проверить, не существует ли ваш временный файл, измените строку 183 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;

Возможно, ваш фильтр переименования перемещает или переименовывает файл?

0 голосов
/ 15 июля 2010

В своем тестовом классе настройте свою форму на использование расширенного класса Zend_File_Transfer_Adapter_Http и переопределите метод isValid (). Вам, очевидно, нужно будет изменить область вашей функции формы на public в вашем ProfileController. Это должно использоваться с PHPUnit. Я пока не уверен, как интегрировать его с Zend_Test_PHPUnit_ControllerTestCase, но мне нужно будет это выяснить в какой-то момент и он обновится.

$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;
    }
}
...