public function testParameterRetrievalDefaultValue() { $request = new Request(); $p = new \Zend\Stdlib\Parameters(array('foo' => 'bar')); $request->setQuery($p); $request->setPost($p); $request->setFiles($p); $default = 15; $this->assertSame($default, $request->getQuery('baz', $default)); $this->assertSame($default, $request->getPost('baz', $default)); $this->assertSame($default, $request->getFiles('baz', $default)); $this->assertSame($default, $request->getHeaders('baz', $default)); $this->assertSame($default, $request->getHeader('baz', $default)); }
/** * Parse upload content from a content stream * * @param resource $stream * @return array * @throws Exception\InvalidMultipartContentException */ protected function parseFromStream($stream) { $data = new Parameters(); $files = new Parameters(); $partInProgress = false; $inHeader = false; $headers = []; $header = false; $name = false; $content = ''; $file = []; $filename = false; $mimeType = false; $tmpFile = false; $partBoundaryPatternStart = '/^--' . $this->boundary . '(--)?/'; $partBoundaryPatternEnd = '/^--' . $this->boundary . '--$/'; while (false !== ($line = fgets($stream))) { $trimmedLine = rtrim($line); if (preg_match($partBoundaryPatternStart, $trimmedLine)) { if ($partInProgress) { // Time to handle the data we've already parsed! // Data if (!$filename) { $data->set($name, rtrim($content, "\r\n")); } // File (successful upload so far) if ($filename && $tmpFile) { // Write the last line, stripping the EOL characters if (false === fwrite($tmpFile, rtrim($lastline, "\r\n"))) { // Ooops! error writing the very last line! $file['error'] = UPLOAD_ERR_CANT_WRITE; fclose($tmpFile); } else { // Success! Let's try and guess the MIME type based on the file written fclose($tmpFile); if ($mimeType === 'application/octet-stream' && function_exists('finfo_open')) { $finfo = finfo_open(FILEINFO_MIME_TYPE); $type = finfo_file($finfo, $file['tmp_name']); if (false !== $type) { $file['type'] = $type; } } // Finally, set the filesize $file['size'] = filesize($file['tmp_name']); } } if ($filename) { // At this point, we can add the file entry, regardless of error condition $files->set($name, $file); } } // Is this a boundary end? If so, we're done if (preg_match($partBoundaryPatternEnd, $trimmedLine)) { // Met the "end" boundary; time to stop! break; } // New part to parse! $partInProgress = true; $inHeader = true; $headers = []; $header = ''; continue; } if (!$partInProgress) { // We're not inside a part, so do nothing. continue; } if ($inHeader) { if (preg_match('/^\\s*$/s', $line)) { // Headers are done; cleanup $inHeader = false; $content = ''; $file = ['error' => UPLOAD_ERR_OK]; $tmpFile = false; $lastline = null; // Parse headers $name = $this->getNameFromHeaders($headers); if (!$name) { throw new Exception\InvalidMultipartContentException('Missing Content-Disposition header, or Content-Disposition header does not ' . 'contain a "name" field'); } $filename = $this->getFilenameFromHeaders($headers); $mimeType = $this->getMimeTypeFromHeaders($headers); continue; } if (preg_match('/^(?P<header>[a-z]+[a-z0-9_-]+):\\s*(?P<value>.*)$/i', $trimmedLine, $matches)) { $header = strtoupper($matches['header']); $headers[$header] = $matches['value']; continue; } if (!$header) { throw new Exception\InvalidMultipartContentException('Malformed or missing MIME part header for multipart content'); } $headers[$header] .= $trimmedLine; continue; } // In the body content... // Data only; aggregate. if (!$filename) { $content .= $line; continue; } // If we've had an error already with the upload, continue parsing // to the end of the MIME part if ($file['error'] !== UPLOAD_ERR_OK) { continue; } // Create a temporary file handle if we haven't already if (!$tmpFile) { // Sets the file entry $file['name'] = $filename; $file['type'] = $mimeType; $tmpDir = $this->getUploadTempDir(); if (empty($tmpDir)) { // Cannot ascertain temporary directory; this is an error $file['error'] = UPLOAD_ERR_NO_TMP_DIR; continue; } $file['tmp_name'] = tempnam($tmpDir, 'zfc'); $tmpFile = fopen($file['tmp_name'], 'wb'); if (false === $tmpFile) { // Cannot open the temporary file for writing; this is an error $file['error'] = UPLOAD_ERR_CANT_WRITE; continue; } } // Off-by-one operation. Last line must be trimmed, so we'll write // the lines one iteration behind. if (null === $lastline) { $lastline = $line; continue; } if (false === fwrite($tmpFile, $lastline)) { $file['error'] = UPLOAD_ERR_CANT_WRITE; fclose($tmpFile); continue; } $lastline = $line; } fclose($stream); if ($files->count()) { $this->request->setFiles($files); } return $data->toArray(); }
public function testOnFinishDoesNotRemoveUploadFilesThatHaveBeenMoved() { $tmpDir = sys_get_temp_dir() . '/' . str_replace('\\', '_', __CLASS__); mkdir($tmpDir); $tmpFile = tempnam($tmpDir, 'zfc'); $files = new Parameters(array('test' => array('error' => UPLOAD_ERR_OK, 'name' => 'test.txt', 'type' => 'text/plain', 'tmp_name' => $tmpFile))); $request = new Request(); $request->setFiles($files); $event = new MvcEvent(); $event->setRequest($request); $this->listener->onFinish($event); $this->assertTrue(file_exists($tmpFile)); unlink($tmpFile); rmdir($tmpDir); }
public function testMergesFilesArrayIntoDataPriorToValidationWhenFilesArrayIsPopulated() { $validator = $this->getMock('Zend\InputFilter\InputFilterInterface'); $services = new ServiceManager(); $services->setService('FooValidator', $validator); $listener = new ContentValidationListener(array( 'Foo' => array('input_filter' => 'FooValidator'), ), $services); $files = new Parameters(array( 'foo' => array( 'name' => 'foo.txt', 'type' => 'text/plain', 'size' => 1, 'tmp_name' => '/tmp/foo.txt', 'error' => UPLOAD_ERR_OK, ), )); $data = array( 'bar' => 'baz', 'quz' => 'quuz', ); $dataContainer = new ParameterDataContainer(); $dataContainer->setBodyParams($data); $request = new HttpRequest(); $request->setMethod('POST'); $request->setFiles($files); $matches = new RouteMatch(array('controller' => 'Foo')); $event = new MvcEvent(); $event->setRequest($request); $event->setRouteMatch($matches); $event->setParam('ZFContentNegotiationParameterData', $dataContainer); $validator->expects($this->any()) ->method('has') ->with($this->equalTo('FooValidator')) ->will($this->returnValue(true)); $validator->expects($this->once()) ->method('setData') ->with($this->equalTo(array_merge_recursive($data, $files->toArray()))); $validator->expects($this->once()) ->method('isValid') ->will($this->returnValue(true)); $this->assertNull($listener->onRoute($event)); }