Browse Source

merged branch vicb/kernel/client-ini-max-size (PR #1544)

Commits
-------

3df5ec3 [HttpKernel] Add support for 'upload_max_filesize' ini directive in the Client

Discussion
----------

[HttpKernel] Add support for 'upload_max_filesize' ini directive

[HttpKernel] Add support for 'upload_max_filesize' ini directive in the Client

__This PR depends on #1542__

This PR prevent the SW Client from uploading files larger than the limit set in php.ini to closer mimic a real browser usage.

If both PR eventually gets merge `static protected function getMaxUploadFilesize()` should probably be factorized to the UploadedFile class.

---------------------------------------------------------------------------

by stloyd at 2011/07/05 13:35:06 -0700

+1 for both, I just have found similar "wtf" issues with "empty" `upload_max_filesize`.

---------------------------------------------------------------------------

by oscarballadares at 2011/07/05 15:13:23 -0700

I have opened an issue related to UPLOAD_ERR_INI_SIZE. There was no way to handle this exception.
Can you confirm please?

 If this is the case I will close the issue I opened.

---------------------------------------------------------------------------

by vicb at 2011/07/05 23:04:08 -0700

@oscarballadares the PR you are looking for is most probably #1542 - which you should see in the message thread of your submitted issue.

The best would be for you to verify that PR #1542 fixes your issue and provide some feedback so that the issue can be close but only when the PR gets merged (if it fixes the issue).
Fabien Potencier 14 years ago
parent
commit
d49eaa6a41

+ 51 - 11
src/Symfony/Component/HttpKernel/Client.php

@@ -106,8 +106,13 @@ EOF;
     /**
      * Filters an array of files.
      *
-     * This method marks all uploaded files as already moved thus avoiding
-     * UploadedFile's call to move_uploaded_file(), which would otherwise fail.
+     * This method created test instances of UploadedFile so that the move()
+     * method can be called on those instances.
+     *
+     * If the size of a file is greater than the allowed size (from php.ini) then
+     * an invalid UploadedFile is returned with an error set to UPLOAD_ERR_INI_SIZE.
+     *
+     * @see Symfony\Component\HttpFoundation\File\UploadedFile
      *
      * @param array $files An array of files
      *
@@ -120,15 +125,25 @@ EOF;
             if (is_array($value)) {
                 $filtered[$key] = $this->filterFiles($value);
             } elseif ($value instanceof UploadedFile) {
-                // Create a test mode UploadedFile
-                $filtered[$key] = new UploadedFile(
-                    $value->getPathname(),
-                    $value->getClientOriginalName(),
-                    $value->getClientMimeType(),
-                    $value->getClientSize(),
-                    $value->getError(),
-                    true
-                );
+                if ($value->isValid() && $value->getSize() > static::getMaxUploadFilesize()) {
+                    $filtered[$key] = new UploadedFile(
+                        '',
+                        $value->getClientOriginalName(),
+                        $value->getClientMimeType(),
+                        0,
+                        UPLOAD_ERR_INI_SIZE,
+                        true
+                    );
+                } else {
+                    $filtered[$key] = new UploadedFile(
+                        $value->getPathname(),
+                        $value->getClientOriginalName(),
+                        $value->getClientMimeType(),
+                        $value->getClientSize(),
+                        $value->getError(),
+                        true
+                    );
+                }
             } else {
                 $filtered[$key] = $value;
             }
@@ -157,4 +172,29 @@ EOF;
 
         return new DomResponse($response->getContent(), $response->getStatusCode(), $headers);
     }
+
+    /**
+     * Returns the maximum size of an uploaded file
+     *
+     * @return type The maximum size of an uploaded file in bytes
+     */
+    static protected function getMaxUploadFilesize()
+    {
+        $max = trim(ini_get('upload_max_filesize'));
+
+        if ('' === $max) {
+            return PHP_INT_MAX;
+        }
+
+        switch (strtolower(substr($max, -1))) {
+            case 'g':
+                $max *= 1024;
+            case 'm':
+                $max *= 1024;
+            case 'k':
+                $max *= 1024;
+        }
+
+        return (integer) $max;
+    }
 }

+ 38 - 0
tests/Symfony/Tests/Component/HttpKernel/ClientTest.php

@@ -105,4 +105,42 @@ class ClientTest extends \PHPUnit_Framework_TestCase
         $this->assertFileExists($target);
         unlink($target);
     }
+
+    public function testUploadedFileWhenSizeExceedsUploadMaxFileSize()
+    {
+        $source = tempnam(sys_get_temp_dir(), 'source');
+
+        file_put_contents($source, 'foo');
+
+        $kernel = new TestHttpKernel();
+
+        $client = $this
+            ->getMockBuilder('Symfony\Component\HttpKernel\Client')
+            ->setConstructorArgs(array($kernel))
+            ->setMethods(array('getMaxUploadFilesize'))
+            ->getMock()
+        ;
+
+        $client
+            ->staticExpects($this->once())
+            ->method('getMaxUploadFilesize')
+            ->will($this->returnValue(1))
+        ;
+
+        $client->request('POST', '/', array(), array(new UploadedFile($source, 'original', 'mime/original', 123, UPLOAD_ERR_OK)));
+
+        $files = $kernel->request->files->all();
+
+        $this->assertEquals(1, count($files));
+
+        $file = $files[0];
+
+        $this->assertFalse($file->isValid());
+        $this->assertEquals(UPLOAD_ERR_INI_SIZE, $file->getError());
+        $this->assertEquals('mime/original', $file->getClientMimeType());
+        $this->assertEquals('original', $file->getClientOriginalName());
+        $this->assertEquals(0, $file->getClientSize());
+
+        unlink($source);
+    }
 }