PHP5 foreach $_POST throwing error? - php

I'm getting this error:
Warning: stristr() expects parameter 1 to be string, array given in
/nfs/c09/h03/mnt/12345/domains/mydomainname.com/html/inyoni/fabrics.php
on line 385
from this code:
foreach ($_POST as $field => $value) {
if ($value && (stristr($value,"Content-Type: "))){
header("Location: error.php");
exit;
}
}
and I have no idea why. In fact, I don't see the error, but my client does. My understanding is that this happens when an image file was included in the form (however, this error didn't appear before, only now).
The site is hosted on Mediatemple and a PHP notification had been sent out to customers about the time this started about PHP5 being used across the board on their servers--is this a PHP5 conflict or something?
A bit puzzled--any help appreciated!

The error is pretty clear. It's saying that the first parameter of stristr() has to be a string. However, you're supplying an array instead which is why the code produces an error. To fix it, simply make sure you're just checking for string values.
if (is_string($value))
{
if (stristr(...))
}

Well the $value contains an array, not a string. This can happen when you have a form something like this:
<input type="text" name="form[foo]"/>
<input type="text" name="form[bar]"/>
The $_POST['form'] will hold an array of those two variables. Check if something like this occurs.
It can also happen with file uploads, multiple checkboxes, etc.
As Kemal Fadillah suggested, make a simple type check of the $value variable.

Do a var_dump($value) in the loop. If any of the forms contains an array, such as an uploaded file http://www.php.net/manual/en/features.file-upload.post-method.php or a bunch of checkboxes, then $value would be an array, instead of a string.

Related

Illegal string offset PHP 5.6

We have an old version of CakePHP that we've moved to a new server running PHP 5.6 and we've started to recieve this error when adding a product to the basket:
Warning (2): Illegal string offset 'AddBasketData'
[APP/controllers/personalisation_controller.php, line 848]
Here is line 848 within the file:
if (is_array($this->data['AddBasketData'])) {
$personalisation_data['Personalise'] = $this->data['AddBasketData'];
}else {
$personalisation_data['Personalise'] = array();
}
Could anyone shed any light on this, I think it's down to the specific PHP version we're running now but any help would be great.
Thanks
Transforming my comments into an answer :
The problem here seems to be that $this->data is a string and not an array.
You should test this first, then check if the offset AddBasketData exists, and finally if the offset AddBasketData is an array :
if (is_array($this->data) && isset($this->data['AddBasketData']) && is_array($this->data['AddBasketData'])) {
$personalisation_data['Personalise'] = $this->data['AddBasketData'];
} else {
$personalisation_data['Personalise'] = array();
}
Of course, that will only correct the symptoms (which is the raised warning), you might have some code debugging to do to find out why $this->data is a string instead of an array.
As noted by #roberto06 in the comments to your question, the reason you're getting the error is because you're trying to treat a string value as an array.
The reason for that specific error message is because you can use the array-offset notation to fetch a single character from the string. Just like you'd do in C's string arrays. But this only support numerical indices, and not a string index as shown in the code you posted.
Now, the easy way to stop the error from occurring is to simply test the type of the data, and whether or not the given index actually exists.Like so:
if (is_array ($this->data) && !empty ($this->data['AddBasketData'])) {
$personalisation_data['Personalise'] = $this->data['AddBasketData'];
} else {
$personalisation_data['Personalise'] = array();
}
However, seeing as you're not suddenly getting this error after update hints towards something else being the issue. Especially since the code you posted expects the value stored in the Personalise index to be an array. I'd trace where the $this->data member gets set, and changed, to see if you can find the underlying reason for why this apparent change in behavior. This might be the side-effect of a more nefarious subtle bug, after all.

Should you use htmlspecialchars() before isset() and empty(), or after?

I was wondering what is the correct procedure when it comes to security and practicality. Should you use htmlspecialchars() on a variable before you check if it's set and empty?
Examples:
Use htmlspecialchars() on use or storage of post data:
$field = $_POST['field'];
if(isset($field)){
//store or use: htmlspecialchars($field);
}
Or should you use htmlspecialchars() on retrieval of the post data:
$field = htmlspecialchars($_POST['field']);
if(isset($field)){
//store or use: $field
}
This is probably a silly question, but I wanted to know which is correct.
Well, think about it this way. Why do we use isset in the first place? The answer is to protect our code from trying to do things with something that doesn't exist.
For example, using php -a in your console, you can see:
php > $temp
php > echo htmlspecialchars($temp);
Parse error: parse error in php shell code on line 2
php >
Clearly you don't want your code throwing parse errors. So, you need to check that the value exists first (using isset), then do things with that value.
You should use both isset and empty if you want to make your condition fully secure, Because isset checks that variable is defined or not and empty checks for the value of variable is empty or not.
So you should use your if condition like this,
$field = $_POST['field'];
if(isset($field) && !empty($field)){
//store or use: htmlspecialchars($field);
}

PHP not reading $_POST variables

I set up a new AMP stack on a laptop so I could do some work locally. I am no expert in the mechanics of Apache or PHP behind the scenes, so I have a problem. I have a form which collects information and posts it to be processed by a php file. The html form and php processor both work fine on my live server, but on the laptop, the php script doesn't appear to be seeing the posted variables.
Here is how I define the processor program
<form method='POST' action='myprogram.php'>
Here is an example of how I am populating the variables
<input type='text' name='gw' size='8' value='65000'>Gross Weight
here is how I am submitting them
<input type='submit' value='Submit' name='B1'>
in the php, here is how I am defining them locally
$gw=$_POST[gw];
and finally, here is the error message I get for every single variable:
"Notice: Use of undefined constant gw - assumed 'gw' in C:\Apache\htdocs\myprogram\myprogram.php on line 21"
Since the code works perfectly on my apache 2.2 server and not on the 2.4 that I just installed, I'm pretty sure that the problem is in either my apache or php configuration. I've looked everywhere I can think of and can't find a directive that "turns on" this feature. I'd sure love some help on this one, thanks in advance.
Jim
$_POST values are stored in an associative array, that is to say the values are indexed by some type of string 'key'. To access an element, you must use the appropriate string:
$value = $_POST['gw']; // a string using single quotes
$key = 'gw';
$value = $_POST[$key]; // this is also acceptable
In your code, you did not include quotes around your string, so PHP interpreted it as a constant.
What you are missing are the quotes around $gw=$_POST['gw'] It thinks that you are using a constant gw. Here is the specific article with regards to this error: Why is $foo[bar] wrong?
For better code that doesn't produce errors I recommend using:
$gw = ( empty($_POST['gw']) ) ? $_POST['gw'] : false;
This is PHP's ternary operator. This code checks that there is in fact a value before assigning it to the variable.

How can I get all submitted form values in PHP and automatically assign them to variables?

I'm trying to migrate a website from one host to another. On the first host, when you submit a form, all of the form values are automatically stuck into variables with the input name (this is PHP). On the new host, these values are all null unless I do this:
$data = $_GET['data'];
Is there a PHP configuration setting that is causing this? If there isn't, is there an easy way to loop through all of the $_GET variables and automatically assign their values to a variable with the same name?
Thanks!
The setting is register_globals, but it is now deprecated and strongly advised against using it because it is a security risk. Anyone can set variables in your script which might interact in a negative or unexpected way with your code.
If you absolutely must, you can do it like this:
foreach ($_GET as $key=>$value) {
$$key = $value;
}
or, more simply:
import_request_variables("g");
or, to make it a little safer:
import_request_variables("g", "myprefix_"); // This way forces you to use "myprefix_"
// in front of the variables, better ensuring you are not unaware
// of the fact that this can come from a user
extract($_GET) could also work, as someone else pointed out, and it also allows specification (via extra arguments) of adding a prefix or what to do if your extraction conflicts with an already existing variable (e.g., if you extracted after you defined some other variables).
Look at the extract function : http://www.php.net/manual/en/function.extract.php
You could do something like this:
foreach ($_GET["data"] as $name => $value){
$$name = $value;
}
The issue with this is that it makes it easy for people to fiddle with the variables in your script. I could visit http://yoursite.com/?sql=DELETE+FROM...
I'd advise against doing this and just sticking to using $_GET.
Your question infers you are not doing any filtering or validation when assigning $_GET['data'] to $data, unless you are doing these kind of checks further down your script.
From what I have seen most programmers would do this first, in an effort to fail early if expected data did not match expectations, so that the above assignment in the case of expecting a positive int would become something like:
if( isset($_GET['data']) && (int)$_GET['data'] === 0){
//fail
}else{
$data = $_GET['data'];
}
So seeing just plain
$data = $_GET['data']
makes me wince.

Easiest and most efficient way to get data from URL using php?

Solution?
Apparently there isn't a faster way, I'm okay with that.
I am just learning php and I am trying to figure out some good tips and tricks so I don't get into a bad habit and waste time.
I am passing in values into a php script. I am using $_GET so the URL looks like this:
/poll_results.php?Sports=tennis&cat=Sports&question=Pick+your+favorite+sports
Now I know how to accept those values and place them into variables like so:
$sports = $_GET['Sports'];
$cat = $_GET['cat'];
$question = $_GET['question'];
Super simple yet if I am passing 5 - 6 things it can get bothersome and I don't like typing things out for every single variable, that's the only reason. I know there is a better way of doing this. I have tried list($var, $var, $var) = $_GET but that doesn't work with an associative array just indexed ones (i think).
I also tried variable variables like so:
foreach($_GET as $value) {
$$values = $value;
echo $$values;
}
But that gave me a Notice: Undefined variable: values in poll_results.php on line 14. Line 14 is the $$values = $value. I don't know if that's a big deal or not... but I'm not turning off error reporting as I am still in the process of building the script. It does do what I want it to do though...
Any answers will be copied and pasted into my question so the next person knows :D
Thanks guys!
Your second bit of code is wrong. It ought to be like
foreach ($_GET as $key => $value) {
$$key = $value;
}
if i understand your intent. However, you're basically reinventing register_globals, which....eh. That'll get ya hacked.
If you have certain variables you want to get, you could do like
foreach (array('Sports', 'cat', 'question') as $key)
{
$$key = $_GET[$key];
}
which is less likely to overwrite some important variable (whether by accident or because someone was messing around with URLs).
Use parse_url() to extract the query string from a URL you've got in a string, then parse_str() to extract the individual arguments of the query string.
If you want to pollute your script with the contents of the superglobals, then you can use extract(). however, be aware that this is basically replicating the hideous monstrosity known as "register_globals", and opens all kinds of security vulnerabilities.
For instant, what if one of the original query arguments was _GET=haha. You've now trashed the $_GET superglobal by overwriting it via extract().
I am just learning php and I am trying to figure out some good tips and tricks so I don't get into a bad habit and waste time.
If I am passing 5 - 6 things it can get bothersome and I don't like typing things out for every single variable, that's the only reason.
What you are trying to do will, unless curbed, become a bad habit and even before then is a waste of time.
Type out the variables: your digits like exercise and your brain can take it easy when it doesn't have to figure out which variables are available (or not, or maybe; which would be the case when you use variable variables).
You can use
foreach($_GET as $key => $value)
To preserve the key and value associativity.
Variable variables (the $$value) are a bad idea. With your loop above say you had a variable named $password that is already defined from some other source. Now I can send $_GET['password'] and overwrite your variable! All sorts of nastiness can result from this. It's the same reason why PHP abandoned register_globals which essentially does the same thing.
My advice: use $_POST when possible. It keeps your URLs much cleaner for one thing. Secondly there's no real reason to assign the array to variables anyway, just use them where you need them in the program.
One good reason for this, especially in a large program, is that you'll instantly know where they came from, and that their data should not be trusted.

Categories