Zend Framework

Form_Element_File->addValidator('Extension', true, 'txt') doesn't work

Details

  • Type: Bug Bug
  • Status: Resolved Resolved
  • Priority: Major Major
  • Resolution: Fixed
  • Affects Version/s: None
  • Fix Version/s: 1.7.0
  • Labels:
    None

Description

$subForm->createElement('file', 'txt')
->setDestination($options['tmp'])
->addFilter('Rename', $options['tmp'] . '/' . md5(microtime(true)))
->setRequired(true)
->addValidator('Count', false, 1) // ensure only 1 file
->setMaxFileSize(10 * 1024 * 1024) // limit to 10M
//->addValidator('FilesSize', true, '1MB')
->addValidator('Extension', true, 'txt'), // only JPEG, PNG, and GIFs

Every upload has error ($form->getErrors('txt')) like this:
"The file 'readme.txt' was not found"

'FilesSize' Validator seems to doesn't work too

If I uncomment above validator, I've got:

  • One or more files can not be read
  • The file 'readme.txt' was not found

Why I've got 2 errors, while I've true in $breakChainOnFailure? Why I've errros?

Activity

Hide
Thomas Weidner added a comment -

Please do not double enter issues.

Please try out trunk r12267 and not 1.7pre when you have issues.
There has been much changed in the last 4 weeks.

Show
Thomas Weidner added a comment - Please do not double enter issues. Please try out trunk r12267 and not 1.7pre when you have issues. There has been much changed in the last 4 weeks.
Hide
Adam Kusmierz added a comment -

As I said in other issue, I've using newest trunk. Sorry for mistake in bug description.

Show
Adam Kusmierz added a comment - As I said in other issue, I've using newest trunk. Sorry for mistake in bug description.
Hide
Thomas Weidner added a comment -

So which does not work... the header declares Extension does not work.
But in your description you declare that FilesSize valdiator does not work as also in your code example.

Which validator does not work ?
Please give the $_FILES array after submittion.

Related to breakchain... it does only break the chain for the single file element, but not for other elements.
So when you validate two elements by calling $form->isValid() you will get one error for each element.

And please give the code you use afterwards for validation and retrievment of the files.

Show
Thomas Weidner added a comment - So which does not work... the header declares Extension does not work. But in your description you declare that FilesSize valdiator does not work as also in your code example. Which validator does not work ? Please give the $_FILES array after submittion. Related to breakchain... it does only break the chain for the single file element, but not for other elements. So when you validate two elements by calling $form->isValid() you will get one error for each element. And please give the code you use afterwards for validation and retrievment of the files.
Hide
Adam Kusmierz added a comment -

Doesn't work 'FilesSize' and 'Extension' too.

Related to breakchain... it does only break the chain for the single file element, but not for other elements.
So when you validate two elements by calling $form->isValid() you will get one error for each element.

This is for one element...

  • One or more files can not be read
  • The file 'readme.txt' was not found

validation code, only:

$postValues = $this->getRequest()->getPost();
if (!empty($postValues)) {
              // some commented code here
	if ($form->isValid($postValues)) {
                  // some commented code here
              }
              // some commented code here
}

Dumps after validation code
$_FILES:

array(2) {
  ["file1"]=>
  array(5) {
    ["name"]=>
    string(10) "movies.txt"
    ["type"]=>
    string(10) "text/plain"
    ["tmp_name"]=>
    string(37) "C:\Program Files\wamp\tmp\php76A2.tmp"
    ["error"]=>
    int(0)
    ["size"]=>
    int(303)
  }
  ["file2"]=>
  array(5) {
    ["name"]=>
    string(8) "todo.txt"
    ["type"]=>
    string(10) "text/plain"
    ["tmp_name"]=>
    string(37) "C:\Program Files\wamp\tmp\php76A3.tmp"
    ["error"]=>
    int(0)
    ["size"]=>
    int(98)
  }
}

form->getErrors()

array(4) {
  ["file1"]=>
  array(2) {
    [0]=>
    string(24) "fileFilesSizeNotReadable"
    [1]=>
    string(21) "fileExtensionNotFound"
  }
  ["file2"]=>
  array(0) {
  }
  ["submit"]=>
  array(0) {
  }
}

$form->getValues()

array(4) {
  ["file1"]=>
  NULL
  ["file2"]=>
  string(32) "b55377db56f87f64bf6d6f68962eed63"
  ["submit"]=>
  string(5) "Submit"
}
Show
Adam Kusmierz added a comment - Doesn't work 'FilesSize' and 'Extension' too.
Related to breakchain... it does only break the chain for the single file element, but not for other elements. So when you validate two elements by calling $form->isValid() you will get one error for each element.
This is for one element...
  • One or more files can not be read
  • The file 'readme.txt' was not found
validation code, only:
$postValues = $this->getRequest()->getPost();
if (!empty($postValues)) {
              // some commented code here
	if ($form->isValid($postValues)) {
                  // some commented code here
              }
              // some commented code here
}
Dumps after validation code $_FILES:
array(2) {
  ["file1"]=>
  array(5) {
    ["name"]=>
    string(10) "movies.txt"
    ["type"]=>
    string(10) "text/plain"
    ["tmp_name"]=>
    string(37) "C:\Program Files\wamp\tmp\php76A2.tmp"
    ["error"]=>
    int(0)
    ["size"]=>
    int(303)
  }
  ["file2"]=>
  array(5) {
    ["name"]=>
    string(8) "todo.txt"
    ["type"]=>
    string(10) "text/plain"
    ["tmp_name"]=>
    string(37) "C:\Program Files\wamp\tmp\php76A3.tmp"
    ["error"]=>
    int(0)
    ["size"]=>
    int(98)
  }
}
form->getErrors()
array(4) {
  ["file1"]=>
  array(2) {
    [0]=>
    string(24) "fileFilesSizeNotReadable"
    [1]=>
    string(21) "fileExtensionNotFound"
  }
  ["file2"]=>
  array(0) {
  }
  ["submit"]=>
  array(0) {
  }
}
$form->getValues()
array(4) {
  ["file1"]=>
  NULL
  ["file2"]=>
  string(32) "b55377db56f87f64bf6d6f68962eed63"
  ["submit"]=>
  string(5) "Submit"
}
Hide
Thomas Weidner added a comment -

There is something wrong...

Your first code creates a file element named "txt".
But your $_FILES array declares that the elements are named "file1" and "file2".

This does not match... eighter the first code you gave is wrong, or the $_FILES array is not from the above code.

Please give the correct code and $_FILES array for investigation.

Show
Thomas Weidner added a comment - There is something wrong... Your first code creates a file element named "txt". But your $_FILES array declares that the elements are named "file1" and "file2". This does not match... eighter the first code you gave is wrong, or the $_FILES array is not from the above code. Please give the correct code and $_FILES array for investigation.
Hide
Adam Kusmierz added a comment -

Huh, what difference? I've changed form element names... Full code, perfect simply:

public function indexAction()
	{
		$form = new Zend_Form();
		$form
			->setAction('/admin/')
			->setMethod(Zend_Form::METHOD_POST)
			->setAttrib('enctype', 'multipart/form-data')
			->addElements(array(
				$form->createElement('file', 'txt')
					->setDestination('../tmp')
					->addFilter('Rename', '../tmp/' . md5(microtime(true)))
					->setRequired(true)
					->addValidator('Count', false, 1) // ensure only 1 file
					->setMaxFileSize(10 * 1024 * 1024) // limit to 10M
					->addValidator('FilesSize', true, '10MB')
					->addValidator('Extension', true, 'mp3'), // only JPEG, PNG, and GIFs
				$form->createElement('submit', 'submit')
		));

		$postValues = $this->getRequest()->getPost();
		if (!empty($postValues) && $form->isValid($postValues)) {
		}
		var_dump($_FILES, $form->getErrors(), $form->getValues());
		$this->view->form = $form;
	}

output of var_dump:

array(1) {
  ["txt"]=>
  array(5) {
    ["name"]=>
    string(8) "todo.txt"
    ["type"]=>
    string(10) "text/plain"
    ["tmp_name"]=>
    string(37) "C:\Program Files\wamp\tmp\phpA427.tmp"
    ["error"]=>
    int(0)
    ["size"]=>
    int(98)
  }
}
array(2) {
  ["txt"]=>
  array(2) {
    [0]=>
    string(24) "fileFilesSizeNotReadable"
    [1]=>
    string(21) "fileExtensionNotFound"
  }
  ["submit"]=>
  array(0) {
  }
}
array(2) {
  ["txt"]=>
  NULL
  ["submit"]=>
  string(6) "submit"
}
Show
Adam Kusmierz added a comment - Huh, what difference? I've changed form element names... Full code, perfect simply:
public function indexAction()
	{
		$form = new Zend_Form();
		$form
			->setAction('/admin/')
			->setMethod(Zend_Form::METHOD_POST)
			->setAttrib('enctype', 'multipart/form-data')
			->addElements(array(
				$form->createElement('file', 'txt')
					->setDestination('../tmp')
					->addFilter('Rename', '../tmp/' . md5(microtime(true)))
					->setRequired(true)
					->addValidator('Count', false, 1) // ensure only 1 file
					->setMaxFileSize(10 * 1024 * 1024) // limit to 10M
					->addValidator('FilesSize', true, '10MB')
					->addValidator('Extension', true, 'mp3'), // only JPEG, PNG, and GIFs
				$form->createElement('submit', 'submit')
		));

		$postValues = $this->getRequest()->getPost();
		if (!empty($postValues) && $form->isValid($postValues)) {
		}
		var_dump($_FILES, $form->getErrors(), $form->getValues());
		$this->view->form = $form;
	}
output of var_dump:
array(1) {
  ["txt"]=>
  array(5) {
    ["name"]=>
    string(8) "todo.txt"
    ["type"]=>
    string(10) "text/plain"
    ["tmp_name"]=>
    string(37) "C:\Program Files\wamp\tmp\phpA427.tmp"
    ["error"]=>
    int(0)
    ["size"]=>
    int(98)
  }
}
array(2) {
  ["txt"]=>
  array(2) {
    [0]=>
    string(24) "fileFilesSizeNotReadable"
    [1]=>
    string(21) "fileExtensionNotFound"
  }
  ["submit"]=>
  array(0) {
  }
}
array(2) {
  ["txt"]=>
  NULL
  ["submit"]=>
  string(6) "submit"
}
Hide
Thomas Weidner added a comment -

For example the difference that in your code you only declare one single file element and in your returned $_FILES array there are 2 file elements ?

Show
Thomas Weidner added a comment - For example the difference that in your code you only declare one single file element and in your returned $_FILES array there are 2 file elements ?
Hide
Thomas Weidner added a comment -

So there is one problem with your code...

You can not getPost() and then validate the elements when there has nothing be posted.
According to manual you have previously to check with isPost().

This has nothing to do with the file element but with generic form handling. I am no forms expert as this is not my component but even I can say that validation on empty elements will ALWAYS FAIL.

Show
Thomas Weidner added a comment - So there is one problem with your code... You can not getPost() and then validate the elements when there has nothing be posted. According to manual you have previously to check with isPost(). This has nothing to do with the file element but with generic form handling. I am no forms expert as this is not my component but even I can say that validation on empty elements will ALWAYS FAIL.
Hide
Adam Kusmierz added a comment -

But it doesn't matter.
Additionaly I've got Notice, when I trying to get $form->getValues(); in my form (see code below) without submit data (just GET).

Notice: Undefined index: name in C:\Program Files\wamp\www\public_html\karaoke\library\Zend\File\Transfer\Adapter\Abstract.php on line 1224

I've form, deeply inserted in my application and I should copy you half of my files. So to simpliest this, I change some of fields to copy you point. Here you are 2 files, but bug is same, and there isn't difference, that you add 1, 2 or 50 files.

public function indexAction()
	{
		$form = new Zend_Form();
		$form
			->setAction('/admin/')
			->setMethod(Zend_Form::METHOD_POST)
			->setAttrib('enctype', 'multipart/form-data')
			->addElements(array(
				$form->createElement('file', 'txt')
					->setDestination('../tmp')
					->addFilter('Rename', '../tmp/' . md5(microtime(true)))
					->setRequired(true)
					->addValidator('Count', false, 1) // ensure only 1 file
					->setMaxFileSize(10 * 1024 * 1024) // limit to 10M
					->addValidator('FilesSize', true, '10MB')
					->addValidator('Extension', true, 'mp3'), // only JPEG, PNG, and GIFs
					$form->createElement('file', 'doc')
						->setLabel('Plik kar')
						->setDestination('../tmp')
						->addFilter('Rename', '../tmp/' . md5(microtime(true)))
						->setRequired(true)
						->addValidator('Count', false, 1),
				$form->createElement('submit', 'submit')
		));

		$postValues = $this->getRequest()->getPost();
		if (!empty($postValues) && $form->isValid($postValues)) {
		}
		var_dump($_FILES, $form->getErrors(), $form->getValues());
		$this->view->form = $form;
	}
array(2) {
  ["txt"]=>
  array(5) {
    ["name"]=>
    string(8) "todo.txt"
    ["type"]=>
    string(10) "text/plain"
    ["tmp_name"]=>
    string(37) "C:\Program Files\wamp\tmp\phpAFBE.tmp"
    ["error"]=>
    int(0)
    ["size"]=>
    int(98)
  }
  ["doc"]=>
  array(5) {
    ["name"]=>
    string(13) "formularz.doc"
    ["type"]=>
    string(18) "application/msword"
    ["tmp_name"]=>
    string(37) "C:\Program Files\wamp\tmp\phpAFBF.tmp"
    ["error"]=>
    int(0)
    ["size"]=>
    int(64512)
  }
}
array(3) {
  ["txt"]=>
  array(2) {
    [0]=>
    string(24) "fileFilesSizeNotReadable"
    [1]=>
    string(21) "fileExtensionNotFound"
  }
  ["doc"]=>
  array(0) {
  }
  ["submit"]=>
  array(0) {
  }
}
array(3) {
  ["txt"]=>
  NULL
  ["doc"]=>
  string(32) "83b62560437c8b21f1614892f1a027af"
  ["submit"]=>
  string(6) "submit"
}
Show
Adam Kusmierz added a comment - But it doesn't matter. Additionaly I've got Notice, when I trying to get $form->getValues(); in my form (see code below) without submit data (just GET).
Notice: Undefined index: name in C:\Program Files\wamp\www\public_html\karaoke\library\Zend\File\Transfer\Adapter\Abstract.php on line 1224
I've form, deeply inserted in my application and I should copy you half of my files. So to simpliest this, I change some of fields to copy you point. Here you are 2 files, but bug is same, and there isn't difference, that you add 1, 2 or 50 files.
public function indexAction()
	{
		$form = new Zend_Form();
		$form
			->setAction('/admin/')
			->setMethod(Zend_Form::METHOD_POST)
			->setAttrib('enctype', 'multipart/form-data')
			->addElements(array(
				$form->createElement('file', 'txt')
					->setDestination('../tmp')
					->addFilter('Rename', '../tmp/' . md5(microtime(true)))
					->setRequired(true)
					->addValidator('Count', false, 1) // ensure only 1 file
					->setMaxFileSize(10 * 1024 * 1024) // limit to 10M
					->addValidator('FilesSize', true, '10MB')
					->addValidator('Extension', true, 'mp3'), // only JPEG, PNG, and GIFs
					$form->createElement('file', 'doc')
						->setLabel('Plik kar')
						->setDestination('../tmp')
						->addFilter('Rename', '../tmp/' . md5(microtime(true)))
						->setRequired(true)
						->addValidator('Count', false, 1),
				$form->createElement('submit', 'submit')
		));

		$postValues = $this->getRequest()->getPost();
		if (!empty($postValues) && $form->isValid($postValues)) {
		}
		var_dump($_FILES, $form->getErrors(), $form->getValues());
		$this->view->form = $form;
	}
array(2) {
  ["txt"]=>
  array(5) {
    ["name"]=>
    string(8) "todo.txt"
    ["type"]=>
    string(10) "text/plain"
    ["tmp_name"]=>
    string(37) "C:\Program Files\wamp\tmp\phpAFBE.tmp"
    ["error"]=>
    int(0)
    ["size"]=>
    int(98)
  }
  ["doc"]=>
  array(5) {
    ["name"]=>
    string(13) "formularz.doc"
    ["type"]=>
    string(18) "application/msword"
    ["tmp_name"]=>
    string(37) "C:\Program Files\wamp\tmp\phpAFBF.tmp"
    ["error"]=>
    int(0)
    ["size"]=>
    int(64512)
  }
}
array(3) {
  ["txt"]=>
  array(2) {
    [0]=>
    string(24) "fileFilesSizeNotReadable"
    [1]=>
    string(21) "fileExtensionNotFound"
  }
  ["doc"]=>
  array(0) {
  }
  ["submit"]=>
  array(0) {
  }
}
array(3) {
  ["txt"]=>
  NULL
  ["doc"]=>
  string(32) "83b62560437c8b21f1614892f1a027af"
  ["submit"]=>
  string(6) "submit"
}
Hide
Adam Kusmierz added a comment -

You can not getPost() and then validate the elements when there has nothing be posted.
According to manual you have previously to check with isPost().

I don't understand.
you mean

$postValues = $this->getRequest()->getPost();
		if (!empty($postValues) && $form->isValid($postValues)) {
		}

as what?

if ($this->getRequest()->isPost()) {
		if ($form->isValid($this->getRequest()->getPost())) {
		}
}

? Is it not the same?

Show
Adam Kusmierz added a comment -
You can not getPost() and then validate the elements when there has nothing be posted. According to manual you have previously to check with isPost().
I don't understand. you mean
$postValues = $this->getRequest()->getPost();
		if (!empty($postValues) && $form->isValid($postValues)) {
		}
as what?
if ($this->getRequest()->isPost()) {
		if ($form->isValid($this->getRequest()->getPost())) {
		}
}
? Is it not the same?
Hide
Thomas Weidner added a comment -

When there were no difference I would not have asked...
Still you can not validating non existing input... this will always fail as I already wrote.

Show
Thomas Weidner added a comment - When there were no difference I would not have asked... Still you can not validating non existing input... this will always fail as I already wrote.
Hide
Adam Kusmierz added a comment -
if (!empty($postValues) && $form->isValid($postValues)) {

empty($postValues) - ok, this could be not the same as $this->getRequest()->isPost(), but in this example is.

And, as you know, if first element in tuple, ie. a & b is false, so php leave it (see Boolean algebra), even NOT check second element. I can't find differences, or I'm blind. Could you tell me, where it is?

PS
Code above doesn't work too. It has same dump output as main.

Show
Adam Kusmierz added a comment -
if (!empty($postValues) && $form->isValid($postValues)) {
empty($postValues) - ok, this could be not the same as $this->getRequest()->isPost(), but in this example is. And, as you know, if first element in tuple, ie. a & b is false, so php leave it (see Boolean algebra), even NOT check second element. I can't find differences, or I'm blind. Could you tell me, where it is? PS Code above doesn't work too. It has same dump output as main.
Hide
Thomas Weidner added a comment -

I rewrote your code to run independently:

<?php
error_reporting(E_ALL|E_STRICT);
ini_set('include_path',ini_get('include_path').PATH_SEPARATOR.'../library');
require_once('Zend/Loader.php');
Zend_Loader::registerAutoload();

$request = new Zend_Controller_Request_Http();

// setup the form
        $form = new Zend_Form();
        $form
            ->setMethod(Zend_Form::METHOD_POST)
            ->setAttrib('enctype', 'multipart/form-data')
            ->addElements(array(
                $form->createElement('file', 'txt')
                    ->setDestination('C:/temp')
                    ->addFilter('Rename', 'C:/temp/' . md5(microtime(true)))
                    ->setRequired(true)
                    ->addValidator('Count', false, 1) // ensure only 1 file
                    ->setMaxFileSize(10 * 1024 * 1024) // limit to 10M
                    ->addValidator('FilesSize', true, '10MB')
                    ->addValidator('Extension', true, 'mp3'), // only JPEG, PNG, and GIFs
                $form->createElement('submit', 'submit')
        ));

        if ($request->isPost()) {
        $postValues = $request->getPost();
        if (!empty($postValues) && $form->isValid($postValues)) {
        }
        var_dump($_FILES, $form->getErrors(), $form->getValues());
        }

?>
<html>
<head>
<title>Test</title>
</head>
<body>
<?php echo $form->render(new Zend_View());?>
</body>
</html>

I have no notices, no warnings... only one validation failure when a false file was transferred.
From what I see there are no problems.

Can you please check this in your environment ?
Also you should update to latest trunk to be sure we both use the same codebase.

Show
Thomas Weidner added a comment - I rewrote your code to run independently:
<?php
error_reporting(E_ALL|E_STRICT);
ini_set('include_path',ini_get('include_path').PATH_SEPARATOR.'../library');
require_once('Zend/Loader.php');
Zend_Loader::registerAutoload();

$request = new Zend_Controller_Request_Http();

// setup the form
        $form = new Zend_Form();
        $form
            ->setMethod(Zend_Form::METHOD_POST)
            ->setAttrib('enctype', 'multipart/form-data')
            ->addElements(array(
                $form->createElement('file', 'txt')
                    ->setDestination('C:/temp')
                    ->addFilter('Rename', 'C:/temp/' . md5(microtime(true)))
                    ->setRequired(true)
                    ->addValidator('Count', false, 1) // ensure only 1 file
                    ->setMaxFileSize(10 * 1024 * 1024) // limit to 10M
                    ->addValidator('FilesSize', true, '10MB')
                    ->addValidator('Extension', true, 'mp3'), // only JPEG, PNG, and GIFs
                $form->createElement('submit', 'submit')
        ));

        if ($request->isPost()) {
        $postValues = $request->getPost();
        if (!empty($postValues) && $form->isValid($postValues)) {
        }
        var_dump($_FILES, $form->getErrors(), $form->getValues());
        }

?>
<html>
<head>
<title>Test</title>
</head>
<body>
<?php echo $form->render(new Zend_View());?>
</body>
</html>
I have no notices, no warnings... only one validation failure when a false file was transferred. From what I see there are no problems. Can you please check this in your environment ? Also you should update to latest trunk to be sure we both use the same codebase.
Hide
Adam Kusmierz added a comment -

It works both with newest trunk.

Show
Adam Kusmierz added a comment - It works both with newest trunk.
Hide
Thomas Weidner added a comment -

Fixed within trunk >r12272

Show
Thomas Weidner added a comment - Fixed within trunk >r12272
Hide
Wil Sinclair added a comment -

Changing issues in preparation for the 1.7.0 release.

Show
Wil Sinclair added a comment - Changing issues in preparation for the 1.7.0 release.

People

Vote (0)
Watch (1)

Dates

  • Created:
    Updated:
    Resolved: