Skip to content

Commit 45725b8

Browse files
committed
Fix $_FILES parsing
The old tests were just straight up wrong. I built them wrong when converting the code from 2.x to now. In 2.x all files were preceded by the `data` name which made files parsing much simpler as we had already stripped off the first name element. The new method feels better to me as well. It doesn't use reference arguments and I think is a tiny bit simpler. Refs #3999
1 parent 96a1f36 commit 45725b8

File tree

2 files changed

+85
-243
lines changed

2 files changed

+85
-243
lines changed

src/Network/Request.php

Lines changed: 20 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -402,10 +402,10 @@ protected static function _base() {
402402
protected function _processFiles($post, $files) {
403403
if (is_array($files)) {
404404
foreach ($files as $key => $data) {
405-
if (!is_numeric($key)) {
406-
$this->_processFileData($post, '', $data, $key);
407-
} else {
405+
if (isset($data['tmp_name']) && is_string($data['tmp_name'])) {
408406
$post[$key] = $data;
407+
} else {
408+
$post[$key] = $this->_processFileData([], $data);
409409
}
410410
}
411411
}
@@ -414,31 +414,32 @@ protected function _processFiles($post, $files) {
414414

415415
/**
416416
* Recursively walks the FILES array restructuring the data
417-
* into something sane and useable.
417+
* into something sane and usable.
418418
*
419-
* @param array &$post The post data having files inserted into
419+
* @param array $data The data being built
420+
* @param array $post The post data being traversed
420421
* @param string $path The dot separated path to insert $data into.
421-
* @param array $data The data to traverse/insert.
422-
* @param string $field The terminal field name, which is the top level key in $_FILES.
422+
* @param string $field The terminal field in the path. This is one of the
423+
* $_FILES properties e.g. name, tmp_name, size, error
423424
* @return void
424425
*/
425-
protected function _processFileData(&$post, $path, $data, $field) {
426-
foreach ($data as $key => $fields) {
427-
$newPath = $key;
428-
if (!empty($path)) {
429-
$newPath = $path . '.' . $key;
426+
protected function _processFileData($data, $post, $path = '', $field = '') {
427+
foreach ($post as $key => $fields) {
428+
$newField = $field;
429+
if ($path === '' && $newField === '') {
430+
$newField = $key;
431+
}
432+
if ($field === $newField) {
433+
$path .= '.' . $key;
430434
}
431435
if (is_array($fields)) {
432-
$this->_processFileData($post, $newPath, $fields, $field);
436+
$data = $this->_processFileData($data, $fields, $path, $newField);
433437
} else {
434-
if (strpos($newPath, '.') === false) {
435-
$newPath = $field . '.' . $key;
436-
} else {
437-
$newPath .= '.' . $field;
438-
}
439-
$post = Hash::insert($post, $newPath, $fields);
438+
$path = trim($path . '.' . $field, '.');
439+
$data = Hash::insert($data, $path, $fields);
440440
}
441441
}
442+
return $data;
442443
}
443444

444445
/**

tests/TestCase/Network/RequestTest.php

Lines changed: 65 additions & 224 deletions
Original file line numberDiff line numberDiff line change
@@ -259,235 +259,76 @@ public function testPutParsingJSON() {
259259
}
260260

261261
/**
262-
* Test parsing of FILES array
262+
* Test processing files with `file` field names.
263263
*
264264
* @return void
265265
*/
266-
public function testFilesParsing() {
267-
$files = array(
268-
'name' => array(
269-
'File' => array(
270-
array('data' => 'cake_sqlserver_patch.patch'),
271-
array('data' => 'controller.diff'),
272-
array('data' => ''),
273-
array('data' => ''),
274-
),
275-
'Post' => array('attachment' => 'jquery-1.2.1.js'),
276-
),
277-
'type' => array(
278-
'File' => array(
279-
array('data' => ''),
280-
array('data' => ''),
281-
array('data' => ''),
282-
array('data' => ''),
283-
),
284-
'Post' => array('attachment' => 'application/x-javascript'),
285-
),
286-
'tmp_name' => array(
287-
'File' => array(
288-
array('data' => '/private/var/tmp/phpy05Ywj'),
289-
array('data' => '/private/var/tmp/php7MBztY'),
290-
array('data' => ''),
291-
array('data' => ''),
292-
),
293-
'Post' => array('attachment' => '/private/var/tmp/phpEwlrIo'),
294-
),
295-
'error' => array(
296-
'File' => array(
297-
array('data' => 0),
298-
array('data' => 0),
299-
array('data' => 4),
300-
array('data' => 4)
301-
),
302-
'Post' => array('attachment' => 0)
303-
),
304-
'size' => array(
305-
'File' => array(
306-
array('data' => 6271),
307-
array('data' => 350),
308-
array('data' => 0),
309-
array('data' => 0),
310-
),
311-
'Post' => array('attachment' => 80469)
312-
),
313-
);
314-
266+
public function testProcessFilesNested() {
267+
$files = [
268+
'image_main' => [
269+
'name' => ['file' => 'born on.txt'],
270+
'type' => ['file' => 'text/plain'],
271+
'tmp_name' => ['file' => '/private/var/tmp/php'],
272+
'error' => ['file' => 0],
273+
'size' => ['file' => 17178]
274+
],
275+
0 => [
276+
'name' => ['image' => 'scratch.text'],
277+
'type' => ['image' => 'text/plain'],
278+
'tmp_name' => ['image' => '/private/var/tmp/phpChIZPb'],
279+
'error' => ['image' => 0],
280+
'size' => ['image' => 1490]
281+
],
282+
'pictures' => [
283+
'name' => [
284+
0 => ['file' => 'a-file.png']
285+
],
286+
'type' => [
287+
0 => ['file' => 'image/png']
288+
],
289+
'tmp_name' => [
290+
0 => ['file' => '/tmp/file123']
291+
],
292+
'error' => [
293+
0 => ['file' => '0']
294+
],
295+
'size' => [
296+
0 => ['file' => 17188]
297+
],
298+
]
299+
];
315300
$request = new Request(compact('files'));
316-
$expected = array(
317-
'File' => array(
318-
array(
319-
'data' => array(
320-
'name' => 'cake_sqlserver_patch.patch',
321-
'type' => '',
322-
'tmp_name' => '/private/var/tmp/phpy05Ywj',
323-
'error' => 0,
324-
'size' => 6271,
325-
)
326-
),
327-
array(
328-
'data' => array(
329-
'name' => 'controller.diff',
330-
'type' => '',
331-
'tmp_name' => '/private/var/tmp/php7MBztY',
332-
'error' => 0,
333-
'size' => 350,
334-
)
335-
),
336-
array(
337-
'data' => array(
338-
'name' => '',
339-
'type' => '',
340-
'tmp_name' => '',
341-
'error' => 4,
342-
'size' => 0,
343-
)
344-
),
345-
array(
346-
'data' => array(
347-
'name' => '',
348-
'type' => '',
349-
'tmp_name' => '',
350-
'error' => 4,
351-
'size' => 0,
352-
)
353-
),
354-
),
355-
'Post' => array(
356-
'attachment' => array(
357-
'name' => 'jquery-1.2.1.js',
358-
'type' => 'application/x-javascript',
359-
'tmp_name' => '/private/var/tmp/phpEwlrIo',
301+
$expected = [
302+
'image_main' => [
303+
'file' => [
304+
'name' => 'born on.txt',
305+
'type' => 'text/plain',
306+
'tmp_name' => '/private/var/tmp/php',
360307
'error' => 0,
361-
'size' => 80469,
362-
)
363-
)
364-
);
365-
$this->assertEquals($expected, $request->data);
366-
367-
$files = array(
368-
'name' => array(
369-
'Document' => array(
370-
1 => array(
371-
'birth_cert' => 'born on.txt',
372-
'passport' => 'passport.txt',
373-
'drivers_license' => 'ugly pic.jpg'
374-
),
375-
2 => array(
376-
'birth_cert' => 'aunt betty.txt',
377-
'passport' => 'betty-passport.txt',
378-
'drivers_license' => 'betty-photo.jpg'
379-
),
380-
),
381-
),
382-
'type' => array(
383-
'Document' => array(
384-
1 => array(
385-
'birth_cert' => 'application/octet-stream',
386-
'passport' => 'application/octet-stream',
387-
'drivers_license' => 'application/octet-stream',
388-
),
389-
2 => array(
390-
'birth_cert' => 'application/octet-stream',
391-
'passport' => 'application/octet-stream',
392-
'drivers_license' => 'application/octet-stream',
393-
)
394-
)
395-
),
396-
'tmp_name' => array(
397-
'Document' => array(
398-
1 => array(
399-
'birth_cert' => '/private/var/tmp/phpbsUWfH',
400-
'passport' => '/private/var/tmp/php7f5zLt',
401-
'drivers_license' => '/private/var/tmp/phpMXpZgT',
402-
),
403-
2 => array(
404-
'birth_cert' => '/private/var/tmp/php5kHZt0',
405-
'passport' => '/private/var/tmp/phpnYkOuM',
406-
'drivers_license' => '/private/var/tmp/php9Rq0P3',
407-
)
408-
)
409-
),
410-
'error' => array(
411-
'Document' => array(
412-
1 => array(
413-
'birth_cert' => 0,
414-
'passport' => 0,
415-
'drivers_license' => 0,
416-
),
417-
2 => array(
418-
'birth_cert' => 0,
419-
'passport' => 0,
420-
'drivers_license' => 0,
421-
)
422-
)
423-
),
424-
'size' => array(
425-
'Document' => array(
426-
1 => array(
427-
'birth_cert' => 123,
428-
'passport' => 458,
429-
'drivers_license' => 875,
430-
),
431-
2 => array(
432-
'birth_cert' => 876,
433-
'passport' => 976,
434-
'drivers_license' => 9783,
435-
)
436-
)
437-
)
438-
);
439-
440-
$request = new Request(compact('files'));
441-
$expected = array(
442-
'Document' => array(
443-
1 => array(
444-
'birth_cert' => array(
445-
'name' => 'born on.txt',
446-
'tmp_name' => '/private/var/tmp/phpbsUWfH',
447-
'error' => 0,
448-
'size' => 123,
449-
'type' => 'application/octet-stream',
450-
),
451-
'passport' => array(
452-
'name' => 'passport.txt',
453-
'tmp_name' => '/private/var/tmp/php7f5zLt',
454-
'error' => 0,
455-
'size' => 458,
456-
'type' => 'application/octet-stream',
457-
),
458-
'drivers_license' => array(
459-
'name' => 'ugly pic.jpg',
460-
'tmp_name' => '/private/var/tmp/phpMXpZgT',
461-
'error' => 0,
462-
'size' => 875,
463-
'type' => 'application/octet-stream',
464-
),
465-
),
466-
2 => array(
467-
'birth_cert' => array(
468-
'name' => 'aunt betty.txt',
469-
'tmp_name' => '/private/var/tmp/php5kHZt0',
470-
'error' => 0,
471-
'size' => 876,
472-
'type' => 'application/octet-stream',
473-
),
474-
'passport' => array(
475-
'name' => 'betty-passport.txt',
476-
'tmp_name' => '/private/var/tmp/phpnYkOuM',
477-
'error' => 0,
478-
'size' => 976,
479-
'type' => 'application/octet-stream',
480-
),
481-
'drivers_license' => array(
482-
'name' => 'betty-photo.jpg',
483-
'tmp_name' => '/private/var/tmp/php9Rq0P3',
484-
'error' => 0,
485-
'size' => 9783,
486-
'type' => 'application/octet-stream',
487-
),
488-
),
489-
)
490-
);
308+
'size' => 17178,
309+
]
310+
],
311+
'pictures' => [
312+
0 => [
313+
'file' => [
314+
'name' => 'a-file.png',
315+
'type' => 'image/png',
316+
'tmp_name' => '/tmp/file123',
317+
'error' => '0',
318+
'size' => 17188,
319+
]
320+
]
321+
],
322+
0 => [
323+
'image' => [
324+
'name' => 'scratch.text',
325+
'type' => 'text/plain',
326+
'tmp_name' => '/private/var/tmp/phpChIZPb',
327+
'error' => 0,
328+
'size' => 1490
329+
]
330+
]
331+
];
491332
$this->assertEquals($expected, $request->data);
492333
}
493334

0 commit comments

Comments
 (0)