Jump to content

String will not create an array


rick.emmet

Recommended Posts

Hello Everyone,
This ought to be straightforward, I want to retrieve the entire “type” array out of the $_FILES array, so that I can run a test to determine what uploaded files are images. Everything I've looked at in the Manual and at various forums hasn't worked.

Since there are a number of image types, I tried to use preg_grep to find any image files uploaded in the “type” array, and all I could retrieve was, “array.” I tried several other approaches and the most I could retrieve was, “[userfile] => array.” Since this is a multi-dimensional array, I had previously attempted to loop through the array and could only print out the proper keys and values, but couldn't contain them in a variable outside of the loop.

I then tried a foreach loop with a key and value and have been able to grab the values for each upload, image/jpeg, text/plane, or even ' ' (which is really important – I want to unset these.)

But when I attempted to create a mono-dimensional array, I'm having all kinds of trouble. I'm not getting any error message, just garbage output. I created a variable and assigned the formatted data values with single quotations and a comma. Then I removed the last comma and space and even used settype to make sure that the variable contains a string. When I run the code, I get an array with one index [0] and all my values, see webPage.jpg:

Once I have this data as an array, I can use preg_grep to find all the non-images and unset them, as the indices will be exactly the same as the ones in the $_FILES array.

Get this, in order to create the last array in webPage.jpg, I copied and pasted the string from the HTML output, “The string in the Values Var is: ” (in red) into the array() for the variable $cantSayOnTV, and then it can output that to the page as a proper array.

Here's my code. At this point, the insert page simply calls this function:

function forUpload() {

    // Try a different approach
    foreach ($_FILES['userfile']['type'] as $key => $value) {
        
        $values .= "'".$value."', ";
        
    }
   // remove the last two characters
    $values = rtrim($values,', ');
    
    // set the type for the variable
    settype($values, "string");
    
    echo "The string in the Values Var is: ".$values."<br />";
    echo gettype($values)."<br />";
    
    // TRY to make this an array
    $newArray = array($values);
    
    // Try to echo out the simple array here
    echo '<pre>';
    print_r($newArray);
    echo '</pre>';
    "<br />";
    
    // force the output to become an array
    $cantSayOnTV = array('image/tiff', 'image/png', 'image/gif', '', 'image/jpeg', 'text/plain');
    
    echo '<pre>';
    print_r($cantSayOnTV);
    echo '</pre>';
    "<br />";
    
    echo "Exiting Data Validation on line 218";
    exit; 
}

So, is there a straightforward way to grab all of the “type” array from the $_ FILES array – or is there some way to force the string to be converted into a proper array? Thanks in advance for you assistance!

Cheers,

Rick

 

post-124625-0-67377400-1492642497_thumb.jpg

Link to comment
Share on other sites

I want to retrieve the entire “type” array out of the $_FILES array, so that I can run a test to determine what uploaded files are images.

Don't. The "type" is not reliable: the browser is the one deciding what the file is, not PHP, so that means a malicious user could send you a PHP file and claim that it's an image.

 

You need to do three things:

1. Do some quick checks on the uploaded file itself to decide whether it looks like an image. You cannot be 100% certain that is it, and it's possible someone will upload a file that is a hybrid of an image and something else, but you can be reasonably sure that the file looks and acts like an image.

2. If you put the file somewhere on your server then make sure it has the right extension to match the type of image it is. 99% of the time the extension dictates what the file acts like (while the other 1% is actually covered in the previous step) so if you detect that an image is a JPEG, for example, then you need to make sure it ends up with a .jpg/jpeg extension.

3. If that file is also going to be directly accessible by a user, meaning you use direct URLs to the file as opposed to it being "downloaded" or something through a PHP script, then you should also take quick steps to make absolutely sure your server doesn't somehow get thoroughly confused and decide that it should try to execute a file. This is incredibly unlikely to ever happen, given the other two steps, but the precautions are easy so you might as well add that layer of protection.

 

For images PHP has an easy way to detect all the normal image types.

$image = @getimagesize($path_to_file); // one of the *very* few times @ is okay to use
if ($image) {
	// file is an image, $image is an array of useful data
} else {
	// file is not an image
}
I don't think it can do TIFFs though - do you need to support those?

 

It'll probably be easier to demonstrate. Your code is... troubling... but mostly I'm just not sure what you're trying to accomplish with it. What is the end goal for that function?

Link to comment
Share on other sites

Besides the upload-specific problems, you seem to deeply misunderstand how programming languages work. A string of comma-separated values within an array() expression is still a string. It doesn't magically become an array. This is like painting a face on a stone and assuming it's now a human.

 

I also wonder what on earth those “grabbing” gymnastics are even supposed to do. $_FILES['userfile']['type'] already is an array of the user-supplied types. A real, actual array. Extracting the values and putting them into another array doesn't achieve anything (just a lot of bugs in your case).

Link to comment
Share on other sites

Hello Requinex and Jacques1,

Thanks for responding. I have a series of functions that strip tags, check for upload errors, mime type or anything that's black listed. The code creates a new image and destroys the old one. Anyone can copy an HTML form and add userfile buttons to send any number of files to the server. I found that if there's a whole in the userfile type array (such as ' ') the code processes all the subsequent images and places them in the upload folder.

I want to unset these from the $_FILES array and then hand off the remaining files to the functions that filter the input. I would like to use preg_grep() to find all the cases in the userfile array that are not ( ^ ) images. I attempted to use preg_grep on $_FILES, but can't retrieve anything other than “array” so I wanted to create a mono-dimensional array, use preg_grep on it and then unset the corresponding files in the $_FILES array.

The $_ FILES array can then be processed with a limit on the number of photos. The idea is that I won't process thirty or fifty photos, and then limit the number moved to the upload folder. I don't want the processing overhead if I can avoid it.

The text book shows the use of the array construct like this:

$products = array('tires', 'oil', 'spark plugs');

and that worked. A variable is supposed to be exactly what is inside of it, so:

$newArray = array($values);

for instance, should be the same as:

$ newArray = array('image/tiff', 'image/png', 'image/gif', '', 'image/jpeg', 'text/plain');

I just looked up array() in the Manual and it show that one can use the key and value pair or just the values. I tried to create an array with the key value pair in this manner:

$values .=  $key." => '".$value."', ";

And I get the output:

Array
(
    [0] => 0 => 'image/tiff', 1 => 'image/png', 2 => 'image/gif', 3 => '', 4 => 'image/jpeg', 5 => 'image/jpeg'
)
And again if I cut and past the output in red into the line of code (within the parenthesis):

$cantSayOnTV = array(0 => 'image/tiff', 1 => 'image/png', 2 => 'image/gif', 3 => '', 4 => 'image/jpeg', 5 => 'image/jpeg');

I get a proper array like this:

Array
(
    [0] => image/tiff
    [1] => image/png
    [2] => image/gif
    [3] =>
    [4] => image/jpeg
    [5] => image/jpeg
)


instead of one that has a single index of [0]. The fact that the code can output a duplicate of the userfile type array makes its failure when using a variable seem odd to me. Any help with this is very much appreciated.
Cheers,
Rick

Link to comment
Share on other sites

Stop banging your head against the wall and read the replies.

 

No, referencing a variable is not the same as putting its content into the code. This is a fundamental misunderstanding. The expression array($some_var) creates an array with a single element, no matter what $some_var looks like. If you put a string with comma-separated values into an array, you can an array with a string; the comma-separated values aren't magically “unpacked”.

 

Your strip_tags() and blacklists don't help you. Read what requinix said about secure uploads, then implement it. But before that, I strongly recommend you learn the basics of PHP.

Link to comment
Share on other sites

Hello Jacques1,

Here's what I was attempting to do...

// Create an array of only the file type
$types = array();
foreach ($_FILES as $filename => $arrayofvalues) {
    $types['type'] = $arrayofvalues['type'];
}

// Create a sub-array of types
foreach ($types as $subArray) {
    foreach ($subArray as $val) {
        $simple[] = $val;
    }
}

// Get the key & value of just image files
$images = preg_grep('/\image\b/', $simple);

// Use the differenc array function to find the indices I want
$dif = array_diff($simple, $images);

// Loop through the difference array and uset non-photos
foreach ($dif as $key => $value) {
    unset($_FILES['userfile']['name'][$key]);
    unset($_FILES['userfile']['type'][$key]);
    unset($_FILES['userfile']['tmp_name'][$key]);
    unset($_FILES['userfile']['error'][$key]);
    unset($_FILES['userfile']['size'][$key]);
}

And the output was:

Full FILES array:

Array
(
    [userfile] => Array
        (
            [name] => Array
                (
                    [0] => text.txt
                    [1] => 
                    [2] => Home Page.tiff
                    [3] => video_icon.png
                    [4] => watersports.gif
                    [5] => IMG_20170325_130533573_HDR.jpg
                )

            [type] => Array
                (
                    [0] => text/plain
                    [1] => 
                    [2] => image/tiff
                    [3] => image/png
                    [4] => image/gif
                    [5] => image/jpeg
                ) 
// MORE OF THE $_FILES ARRAY BELOW

All the 'type' array:

Array
(
    [type] => Array
        (
            [0] => text/plain
            [1] => 
            [2] => image/tiff
            [3] => image/png
            [4] => image/gif
            [5] => image/jpeg
        )

)

Simple images array:

Array
(
    [0] => text/plain
    [1] => 
    [2] => image/tiff
    [3] => image/png
    [4] => image/gif
    [5] => image/jpeg
)

the elements to remove:

Array
(
    [0] => text/plain
    [1] => 
)

FILES array after unsetting:

Array
(
    [userfile] => Array
        (
            [name] => Array
                (
                    [2] => Home Page.tiff
                    [3] => video_icon.png
                    [4] => watersports.gif
                    [5] => IMG_20170325_130533573_HDR.jpg
                )

            [type] => Array
                (
                    [2] => image/tiff
                    [3] => image/png
                    [4] => image/gif
                    [5] => image/jpeg
                )
// MORE OF THE $_FILES ARRAY BELOW

Thanks for your assistance,

Rick

Link to comment
Share on other sites

Rick. I understand what you're trying to do. I'm telling you it doesn't make any sense.

 

You need to learn how arrays work. All those loops are useless. Copying items from one array to another array and then again to another array is useless. You already have an array of all types.

 

Then you need to read what requinix told you above. The user-provided types don't tell you anything about the actual file types. The user can lie. They can give you a PHP script and claim it's an image. If you want a proper upload, you need more robust checks.

Link to comment
Share on other sites

Archived

This topic is now archived and is closed to further replies.

×
×
  • Create New...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.