Jump to content

Recognizing an input stream


ginerjm

Recommended Posts

The topic title is sure to get some attention and that's what I'm looking for.

 

I have seen a couple of posts from one of this forum's members concerning recognizing valid input. It is a different method that he says is a better approach than simply looking for an existing element of the $_POST array. Here's the code he suggests we should all be using:

if ($_SERVER['REQUEST_METHOD'] == 'POST')

 

So - is this true? We should check the REQUEST_METHOD rather than simply look for the existence of a submit button's name attribute in the $_POST array? I have been only coding in PHP for 4-5 years now and have seen this line used but have only recently seen anyone say it is a better approach. In my mind it seems accurate to check for the 'expected' named elements of my html in the proper incoming array, so long as it is the 'expected' POST or GET or even REQUEST (rarely) array.

 

Contributions? Validation?

Edited by ginerjm
Link to comment
Share on other sites

"Should" is debatable. IIRC $_POST will only be filled for POST methods, so if the button is present then you know the form was POSTed.

 

What I think he's getting at is that you can not check for buttons (which requires naming the button) and look for a POST method instead. It's also possible to AJAX a form without including a submit button, so testing the request method is immediately compatible with that.

Link to comment
Share on other sites

I personally would say "It depends".  The complexity of validation is directly proportional to the paranoia of the writer sensitivity of the data.

 

It depends on what you really want to validate: checking the method is quick and easy if you don't care about valid form field values being passed along with it.  If you want to make sure that one or more fields have valid data, then you're just as well to check against relevant $_POST superglobal entry, since you are going to be running validation against the contents anyway as part of your existing validation.

 

Just my opinion.

Link to comment
Share on other sites

So it is simply a matter of how one codes? Personally I learned from my initial readings that one designs a form with expected inputs (and names) and to use a submit button to cause the script to perform what you want it to do. So if I output a form that has several fields in it and a couple of buttons, say a Save and a Cancel button, I know what to expect in my script and to act accordingly. If I don't see either a Save element of a Cancel element in the post array then the form was not submitted properly and I dispose of the input and re-send my form to the user.

 

To me checking the request method is a needless operation if one has designed their script properly to only look for and accept the 'expected' things. And as for those who write about accepting elements from the $_REQUEST array, those people are entirely too loose in their acceptance of input. If one designs a form to do a post, then only accept input from the $_POST array. Same for a GET.

 

In my design style a check for request_method would still necessitate the check for the button name attribute and then the proper input names for the data that I expect. So why check for it? Same goes for those that do a check for $_POST and acting on the True/False condition that they get. Your script should EXPECT certain things and only act upon those same things and anything else should be rejected, just like expected but invalid inputs are rejected.

 

Am I way off-base here?

Link to comment
Share on other sites

No, I don't think you are, but what you are doing is coming across as though you are assuming that the style that fits your way of coding and your requirements is always going to be better than any other, regardless of the situation or individual. Which isn't really true.  Sometimes, for example when information is sent by ajax request as @requenix already suggested, there may not be a requirement to check specific values in the $_POST array, but still having a requirement to check that the $_POST method was called and reacting appropriately.  I personally check against field values - never buttons admittedly - to make sure they are valid (that they are not empty and contain appropriate data for the field context), but I can envisage scenarios that I don't currently program for where that wouldn't necessarily be the best way to handle things, particularly when consuming data from a mobile app for example.

 

I would say it really depends on both how comfortable the coder is with the validity of the POST data before it gets to the script and the context of the interaction between client side and server side. That's just my opinion on the matter however, and I have been proven to be quite wrong with that on numerous occasions  :happy-04:

Link to comment
Share on other sites

It's mostly an issue of how style and how you want your script to behave. For example, what do you want to happen if someone crafted a special POST request with no data / random data?

 

Assuming your code for handing both the initial form GET request and the submission POST request are in the same file, only checking for the expected field would likely result in the malformed POST being treated as if it were a GET, returning the form with no errors.

 

On the other hand if you check for the POST request method, you'd trigger your submission logic which should then check for expected data and return the form again with errors showing.

 

For simple scripts I tend to just check for the expected form data since that's ultimately what I'm interested in. If the form only has one submit button I check for some field that is guaranteed to be submitted, like a text field. If there are multiple buttons, I check for individual buttons as it's necessary to know which was clicked.

 

For bigger things I'm usually using a framework which will have it's own way of handling things.

Link to comment
Share on other sites

It's not just a coding style issue. isset($_POST["button"]) and $_SERVER["REQUEST_METHOD"] == "POST" do two different things: one checks for the presence of a field/button in POSTed data, and the other checks simply that the request was sent using the POST method (which means it likely contains a request body). There's some overlap as to which is more appropriate for a given situation, but neither one nor the other is strictly "better".

 

In the case of a form with only one action, you know logically that if the form was submitted then it is supposed to perform that one action. The presence of a button tells you that the form was submitted using that button, but technically speaking you don't need to require that the button was used. If the form was submitted via AJAX then the button is likely not present, yet the form should still be processed normally because you care that the form was submitted at all.

 

In the case of a form with multiple actions, such as Save or Cancel (and you choose to handle Cancel as an action rather than implement it using, eg, a link back to the previous page), then obviously you need some way to determine which action was requested. Looking at the REQUEST_METHOD will not be enough for that, and named buttons are the easiest solution. You can still do the former as a sort of sanity check, but like I said before I believe $_POST is only filled for POST methods so the presence of a button automatically implies a POST action; missing both buttons means you can't tell what action to perform and you're free to do whatever you want (like redisplay the form).

 

The REQUEST_METHOD matters a lot more with a RESTful API design. It's quite likely, and arguably it should be, that a particular URI will receive multiple actions determined according to the REQUEST_METHOD. For example, a POST to /user/1234 is a different action than a PUT to /user/1234 and most certainly different from a GET. Here there is no submit button, but the "multiple actions" thing still applies: the "page" can perform multiple actions and you determine which by looking at the REQUEST_METHOD, and simply testing for a $_POST field is not appropriate.

 

That overlaps with regular webpages, where you have one serving both as the location of the form as well as the code that processes the form. If you don't look for a submit button then you definitely need to know whether you're supposed to display the form (GET) or process data (POST).

 

Your "design style" argument raises a good point too: if you need to test for a field in $_POST then there's no need for an additional check of the REQUEST_METHOD. It goes towards reducing code complexity.

 

if ($_SERVER["REQUEST_METHOD"] == "POST") {
	if (isset($_POST["save"])) {
		// ...
	} else if (isset($_POST["cancel"])) {
		// ...
	} else {
		// redisplay form
	}
} else {
	// redisplay form
}
Given that "$_POST is only populated for POST requests", the code can be reduced to

 

if (isset($_POST["save"]) /* which implies REQUEST_METHOD=POST */) {
	// ...
} else if (isset($_POST["cancel"]) /* which implies REQUEST_METHOD=POST */) {
	// ...
} else if ($_SERVER["REQUEST_METHOD"] == "POST") {
	// redisplay form
} else {
	// redisplay form
}
and then to the obvious conclusion of

 

if (isset($_POST["save"]) /* which implies REQUEST_METHOD=POST */) {
	// ...
} else if (isset($_POST["cancel"]) /* which implies REQUEST_METHOD=POST */) {
	// ...
} else {
	// redisplay form
}
Thus there is no need to test the REQUEST_METHOD.
Link to comment
Share on other sites

Pretty sure he is referring to me. After many back and forth with @Jaques1 and actual testing, it is a fact that using request method is the correct and failproof way to go.

 

At this point I am pretty burned out on explaining the whys. Perhaps @Jaques1 will do it. One particular instance counting on a button to be submitted that will completely fail is with IE8. I don't want to hear about how its older or not many people use it. It is the default version for windows 7 and unless someone does an upgrade, that is what they have. If you don't care that your script will completely fail for all those users, then so be it.

 

As Jaques1 would tell you, "It is naive to expect that every user is going to use YOUR form to submit data". And in the case of a user using cURL, they are not going to be submitting your button in the request and will have no way of even knowing you are expecting it for the script to work. You have to make way too many assumptions doing anything other than the foolproof 

 

if ($_SERVER['REQUEST_METHOD'] == 'POST')

 

Do your own testing or ask @Jaques1 to explain it in detail. I was previously a if ($POST){} coder before @Jaques1 undisputedly schooled me.

Edited by benanamen
Link to comment
Share on other sites

If the incoming data stream doesn't match EXACTLY what my script was written to expect, then I don't care at all what the input is, nor do I care that the user is doing something different. My script; my rules. If you are using my appl then you use it as I designed it. If I use post only then I will expect only post values; likewise if I only use Get. Should I have a script that takes advantage of both at separate times, again my script will expect things exactly as designed.

 

A pretty simple approach IMHO.

Link to comment
Share on other sites

I have no idea what IE8 would do with my scripts. Are you saying that the following

if (isset($_POST['Return']))

 

would not return a true value if my users clicked on a type=submit element with that name attribute?

Edited by ginerjm
Link to comment
Share on other sites

To answer your questions:

1 - never had to use ie8

2 - just tried it with the IE emulation mode set to 8

3 - my test properly recognized the submit buttons that I clicked on and acted accordingly.

4 - there is no reference to REQUEST_METHOD in my code.

 

I will say that the js code sure popped up with a lot of errors! And not even my js code.

Link to comment
Share on other sites

Back in the day browsers would vary with regard to submit buttons and whether it would be sent or not when the form was submitted by pressing Enter in a text field. Google used to actually detect if the button was sent and if so show a little tip about submitting with the enter key. It seems like these days they are more consistent, but I've not done any exhaustive testing on that.

 

Checking for fields to determine if the form was submitted is ok, checking for buttons could be problematic. I would always make my submit check one of either if ($_POST) or if (isset($_POST['someTextField'])). The first version checks if something exists in the $_POST array, the second checks for a specific text field. Since text fields are always submitted the test is reliable.

 

Also as ginerjm says, if someone isn't submitted the data my script expects, then I don't care. If the data isn't correct then the script can't do it's job. So long as the script doesn't throw a bunch of undefined index/variable errors or similar on such requests it's fine.

 

There are reasons for wanting to check what REQUEST_METHOD is, but it's not necessary for basic form processing.

Edited by kicken
Link to comment
Share on other sites

Kicken,

Thanks for your reasonable response. It appears that I am not doing anything wrong in my current style, although I have yet to experience any 'missing button' phenomena. Should the future alter the current behavior of browsers, I am in a load of trouble!

Link to comment
Share on other sites

I've not done any exhaustive testing on that.

 

I have done pretty exhaustive testing. I wasn't going to say something is the correct way to do it just because @Jaques1 said so or anyone else for that matter. I want to know, by code if something is wrong or not.

 

Although I preach the request method on forums, I still use if ($_POSTin apps that I am the sole coder and are not public access.

 

 

Checking for fields to determine if the form was submitted is ok, checking for buttons could be problematic.

 

Your right. The IE8 issue is specific to how it handles submit and will completely fail with notice of any kind that it did.

 

 

 I would always make my submit check one of either if ($_POST) or if (isset($_POST['someTextField']))

 

Either of those will work. Checking for submit will not.

 

 

Also as ginerjm says, if someone isn't submitted the data my script expects, then I don't care. If the data isn't correct then the script can't do it's job. 

 

On this issue, it doesn't matter one bit if all the data is correct. IE8 behaves exactly the same as if you didn't click the submit button. The script cannot "Do it's job" if it never runs.

Edited by benanamen
Link to comment
Share on other sites

If you're only working alone on small projects where you can come up with your own “rules”, do whatever you want. It's pointless to argue about personal convictions.

 

But outside of this special case, your approach doesn't work at all and is actually harmful:

  • On a multilingual site, the label is likely to depend on the language. Are you saying that everybody should maintain a long list of translations in their code only to “validate” the silly submit label?
  • In many projects, the templates are maintained by a separate team of designers. If the whole code breaks whenever somebody merely changes the label text, that's just unacceptable.
  • It's perfectly normal to submit data without clicking on any buttons (e. g. user scripts, cURL, Ajax, ...). If you reject those requests based on arbitrary “rules”, you may actually lose users. Many sites cannot afford this.

A submit button and its label is just a trivial GUI element. It should have no effect on the business logic whatsoever. If your entire backend breaks just because the stupid label is missing or “wrong”, that's clearly bad code.

 

How do you even react to a missing label? Do you silently assume that you received a GET request even when that's definitely wrong? Without checking the request method, you have no idea what's going on.

 

It just makes no sense. Even when you need to distinguish between two submit buttons, a much better approach is to have two button where the value is completely independend from the graphical label:

<?php

if ($_SERVER['REQUEST_METHOD'] == 'POST')
{
    if (isset($_POST['action']))
    {
        echo 'Action: '.htmlspecialchars($_POST['action'], ENT_QUOTES | ENT_SUBSTITUTE | ENT_HTML5, 'UTF-8');
    }
    else
    {
        echo 'Missing POST parameter: action';
    }
}

?>
<!DOCTYPE HTML>
<html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    </head>
    <body>
        <form method="post">
            <button type="submit" name="action" value="add">A random label for the “add” action</button>
            <button type="submit" name="action" value="delete">A random label for the “delete” action</button>
        </form>
    </body>
</html>
Link to comment
Share on other sites

Am I wrong in thinking I read somewhere that it's pretty easy to spoof the request method header? I'm assuming now that I am, but I've always avoided checking it for that very reason.

 

What I will typically do is insert a hidden value in the form (which can easily be changed, but there are stops to avoid that) and check for that hidden value in the superglobal of choice. For instance,

<?php
public method handleIt(){
	if(isset($_POST['axn']) && isset($_POST['nonce'])){
		$method = "action".ucfirst($_POST['axn']);
		if(method_exists($this, $method)){
			$this->_something = $this->$method($_POST);
		}
	}
}

private function actionAnAction(array $vars){
	if(!$this->_nonceObject->checkNonce($vars['nonce'])){
		return false;
	}
        return $this->doStuff();
}
?>

<form name='doIt' method='post'>
	<input type='hidden' name='axn' value='anAction' />
	<input type='hidden' name='nonce' value='generatedNonce' />
	<input type='text' name='lah' value='deDah' />
	<button type='submit' name='whatever' value='Do It' />
</form>

Please excuse the obviously inane code (it's been a rather long day), but hopefully it's enough to illustrate the point, and it seems to me this is safe and thorough enough to make sure you're dealing with a legit form submission, exactly how you intended the form to be submitted.

 

Either way, $_REQUEST needs to be retired immediately. Then we can all just sit back and watch WordPress burn.

Link to comment
Share on other sites

I don't write for nor expect to appeal to international users. If you want to use my apps learn English.

 

My apps are designed to work just like all of the code I have written for the last 40 years. Yes - the web environment is newest to me, but that doesn't mean that the same principles can't apply. Furthermore this learning process has taught me that you need to be careful about what you get from the user. Well - if I don't get the exact input that I am expecting then all is suspect. How can you dispel my logic on this point Jacques? If someone wants to somehow, someway send me input via ajax when I didn't design for that - it is their problem to deal with and not mine.

 

Yes my browser and other experiences have been limited by what I have tried in a few different environments. Yes - I have experienced problems with my code for some older browsers but that has only been with the JS portions - and never with the PHP. Despite some people's research results, I have not had a problem with testing for a submit button value in IE8, nor in the later versions of that as well as Safari and Chrome.

Link to comment
Share on other sites

If you want to use my apps learn English.

 

For those of us who work on any bigger project, that's not an option.

 

 

 

Furthermore this learning process has taught me that you need to be careful about what you get from the user. Well - if I don't get the exact input that I am expecting then all is suspect. How can you dispel my logic on this point Jacques? If someone wants to somehow, someway send me input via ajax when I didn't design for that - it is their problem to deal with and not mine.

 

So using the WWW means clicking on fancy buttons in web browsers, and anything below that is evil? C'mon.

 

Have you never made a raw HTTP request? Have you never written a user script or browser extension? GUIs are just tools. A well-written application can be accessed in many different ways and lets the user decide. The programmer's preferences are irrelevant.

 

Sure, in your private projects you can try to ban everybody who doesn't speak English or dares to understand HTTP. But how exactly does that help you? This only hurts legitimate users. Even the dumbest script kiddie knows how to send a submit button value, but legitimate clients have to jump through hoops to make your friggin' validator happy. It must be the other way around.

Link to comment
Share on other sites

This thread is more than a year old. Please don't revive it unless you have something important to add.

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • 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.