?
Referenced as Pull Request for: # 6454
avatar Fedik
Fedik
11 Mar 2015

I have complex form with multiple files upload, in diferent groups,
and in call $app->input->files j3.4 produce 100 warnings:

Warning: strstr() expects parameter 1 to be string, array given in libraries/joomla/filter/input.php on line 433
Warning: explode() expects parameter 2 to be string, array given in libraries/joomla/filter/input.php on line 442
Warning: array_reverse() expects parameter 1 to be array, null given in libraries/joomla/filter/input.php on line 443
Warning: array_pop() expects parameter 1 to be array, null given in libraries/joomla/filter/input.php on line 444
Warning: array_map(): Argument #2 should be an array in libraries/joomla/filter/input.php on line 445
Warning: in_array() expects parameter 2 to be array, null given in libraries/joomla/filter/input.php on line 453
Warning: in_array() expects parameter 2 to be array, null given in libraries/joomla/filter/input.php on line 453
Warning: in_array() expects parameter 2 to be array, null given in libraries/joomla/filter/input.php on line 453
Warning: in_array() expects parameter 2 to be array, null given in libraries/joomla/filter/input.php on line 453
Warning: in_array() expects parameter 2 to be array, null given in libraries/joomla/filter/input.php on line 453

all these related how JFilterInput::isSafeFile() works.

how to reproduce
it a bit tricky :smile:
simplest way, make fake _FILES, in way how _FILES looks in my form.:

$_FILES = array(
    'jform' => array(
        'name' => array(
            'document' => '',
            'files' => array(
                'files0' => array(
                    'file' => ''
                ),
                'files1' => array(
                    'file' => ''
                ),
                'files2' => array(
                    'file' => ''
                ),
                'files3' => array(
                    'file' => ''
                )
            ),
            'images' => array(
                'images0' => array(
                    'file' => ''
                ),
                'images1' => array(
                    'file' => ''
                )
            )
        ),
        'type' => array(
            'document' => '',
            'files' => array(
                'files0' => array(
                    'file' => ''
                ),
                'files1' => array(
                    'file' => ''
                ),
                'files2' => array(
                    'file' => ''
                ),
                'files3' => array(
                    'file' => ''
                )
            ),
            'images' => array(
                'images0' => array(
                    'file' => ''
                ),
                'images1' => array(
                    'file' => ''
                )
            )
        ),
        'tmp_name' => array(
            'document' => '',
            'files' => array(
                'files0' => array(
                    'file' => ''
                ),
                'files1' => array(
                    'file' => ''
                ),
                'files2' => array(
                    'file' => ''
                ),
                'files3' => array(
                    'file' => ''
                )
            ),
            'images' => array(
                'images0' => array(
                    'file' => ''
                ),
                'images1' => array(
                    'file' => ''
                )
            )
        ),
        'error' => array(
            'document' => 4,
            'files' => array(
                'files0' => array(
                    'file' => 4
                ),
                'files1' => array(
                    'file' => 4
                ),
                'files2' => array(
                    'file' => 4
                ),
                'files3' => array(
                    'file' => 4
                )
            ),
            'images' => array(
                'images0' => array(
                    'file' => 4
                ),
                'images1' => array(
                    'file' => 4
                )
            )
        ),
        'size' => array(
            'document' => 0,
            'files' => array(
                'files0' => array(
                    'file' => 0
                ),
                'files1' => array(
                    'file' => 0
                ),
                'files2' => array(
                    'file' => 0
                ),
                'files3' => array(
                    'file' => 0
                )
            ),
            'images' => array(
                'images0' => array(
                    'file' => 0
                ),
                'images1' => array(
                    'file' => 0
                )
            )
        ),
    )
);
$app = JFactory::getApplication();
$files = $app->input->files->get('jform');
echo '<pre>';
print_r($files['document']);
echo '</pre>';

expected result
just output from print_r $files['document']

Array
(
    [name] => 
    [type] => 
    [tmp_name] => 
    [error] => 4
    [size] => 0
)

actual result
1000 PHP warnings
and only then output from print_r

avatar Fedik Fedik - open - 11 Mar 2015
avatar joomla-cms-bot joomla-cms-bot - change - 11 Mar 2015
Labels Added: ?
avatar Fedik
Fedik - comment - 11 Mar 2015

quick thought,
maybe better move

// Scan the files in the array
if (!empty($this->data))
{
    foreach ($this->data as $name => &$descriptor)
    {
        $descriptor['safe'] = JFilterInput::isSafeFile($descriptor);
    }
}

from JInputFiles::__construct(), to JInputFiles::get(), and test only requested files?

avatar zero-24 zero-24 - change - 12 Mar 2015
Category Libraries
avatar wilsonge
wilsonge - comment - 14 Mar 2015

@nikosdion can you take a look please :)

avatar nikosdion
nikosdion - comment - 15 Mar 2015

This code cannot be moved into get() for obvious reasons. If it's not obvious: get() would be called every single time you access the files descriptors which could be several dozen times in a page load. Calling a very slow operation dozens of times will lead into problems. Moreover, moving the code around doesn't change much, does it?

That said, I want to know exactly what your form looks like. The code you gave above doesn't help me at all in replicating the issue, let alone fixing it :(

avatar Fedik
Fedik - comment - 15 Mar 2015

ok, here is the form that anyone can use for test:

<?xml version="1.0" encoding="utf-8"?>
<form>
  <field type="text" name="title" label="JGLOBAL_TITLE"  />
  <field type="textarea" name="text" label="Text" />
  <field type="file" name="document"  label="Document" />
  <fields name="files">
    <fields name="files0">
        <field type="file" name="file"  label="File 1" />
    </fields>
    <fields name="files1">
        <field type="file" name="file"  label="File 2" />
    </fields>
    <fields name="files2">
        <field type="file" name="file"  label="File 3" />
    </fields>
  </fields>
  <fields name="images">
    <fields name="images0">
        <field type="file" name="file"  label="Images 1" />
    </fields>
    <fields name="images1">
        <field type="file" name="file"  label="Images 2" />
    </fields>
  </fields>
</form>
avatar nikosdion
nikosdion - comment - 16 Mar 2015

Do you have an installable extension where I can test this behaviour? I can’t put this XML in any core component’s XML file and have it actually render the fields (the core components’ code is a bloody mess…).

avatar Fedik
Fedik - comment - 16 Mar 2015

unfortunately I cannot send original,
I will try think something, need some time

but if you just run the code from my first comment (somewhere in template :smile: ), you will see everything :wink:

Other thing, I saw in the code, when you call $app->input->files you have no chance to pass options to JFilterInput::isSafeFile that called in JInputFiles::__construct() as JFilterInput::isSafeFile($descriptor)

that can force some extension developer use $_FILES directly, instead of $app->input->files and use JFilterInput::isSafeFile($_FILES, $options) one more time,
In theory move this to JInputFiles::get() could fix this problem also, we could try use some static caching, or something, for improve performance (a bit)

avatar Devportobello
Devportobello - comment - 16 Mar 2015

You can use 'raw' as filter to let you pass if unsafe then apply your filter (about your second point)
$input->files->get(name, default, filter);

Moreover, in backend, i got some issue when installing custom component wich contain some class (in dir: eg: admin/class) so filter on '<?php' break install, did i need to use a dir 'package' or some other thing?


This comment was created with the J!Tracker Application at issues.joomla.org/joomla-cms/6397.
avatar nikosdion nikosdion - reference | - 16 Mar 15
avatar nikosdion
nikosdion - comment - 16 Mar 2015

I was able to reproduce this issue by modifying the com_helloworld example component from the Joomla! developers' documentation. I have now made the Pull Request gh-6454 which solves this issue, along with testing instructions.

@Fedik can you please test my patch with your component as well?

avatar Fedik
Fedik - comment - 16 Mar 2015

@nikosdion :+1: yes, I will

avatar brianteeman
brianteeman - comment - 16 Mar 2015

Closing in favour of #6454


This comment was created with the J!Tracker Application at issues.joomla.org/joomla-cms/6397.
avatar brianteeman brianteeman - close - 16 Mar 2015
avatar brianteeman brianteeman - change - 16 Mar 2015
Status New Closed
Closed_Date 0000-00-00 00:00:00 2015-03-16 10:26:48
Closed_By brianteeman
avatar brianteeman brianteeman - change - 16 Mar 2015
Closed_Date 2015-03-16 10:26:48 2015-03-16 10:26:49
avatar brianteeman brianteeman - close - 16 Mar 2015
avatar wilsonge wilsonge - reference | - 16 Mar 15
avatar cheesegrits
cheesegrits - comment - 19 Mar 2015

This fix breaks simple usage of ...

<input type="file" name="foo[]" />
<input type="file" name="foo[]" />

See my comment on the PR

Add a Comment

Login with GitHub to post a comment