Jump to content
Larry Ullman's Book Forums

Server-Side Processing


Recommended Posts

Have done some reading and for starters when if($_SERVER['REQUEST_METHOD'] == 'POST') is used the form data arrives at PHP as strings.  Sanitize filters only seem to remove tags, and validate filters only seem to validate.  Since white space is not good it seems like you'd always use trim() first on everything.  Then the filter functions convert the value to the required type or null if invalid.  Some programs create variables right away like $name = trim($_POST['name']).  Then there's filter_input(INPUT_POST, 'name', FILTER_SANITIZE_STRING) which returns and creates a variable.  It doesn't need one previously defined which saves a statement and seems to provide better documentation than filter_var.  Also maybe SANITIZE can replace htmlentities() due to FILTER_SANITIZE_SPECIAL_CHARS.  There must be a straightforward approach to all this so each step isn't "it seemed like a good idea at the time."

Link to comment
Share on other sites

Came across an example for a string:

 

$name = trim($_POST['name']);

$set = isset($name);

if($set)  {

    if(strlen($name) == 0  {

        $name = "";

        }

}  else   $name = "";

 

So this would be a pattern for every string.  First determine if there is form data for it and get rid of white space at the same time.  Then if it is there see if it has characters by calculating its length (and allowing a zero even if its a required field).  If nothing qualifies create an error message.  The field has been converted so you work with the variable.  You would treat every string field the same way and not have to recode it differently each time because all the important bases would be covered by the pattern instead of having to reinvent one every time.

Link to comment
Share on other sites

The previous template is for strings so this would be one for integers.  Since it is form processing my assumption would be that since you know it's a form the coding made especially for it should be used instead of a more generic pattern.  An example would be:

 

$age = filter_input(INPUT_POST, 'age', FILTER_VALIDATE_INT);

if(is_null($age) || $age === false))  {

    $error = 'error';

}

A more convenient variable is created to work with.  No trim() is necessary because the function probably doesn't care about white space.  The variable content exists if it is a valid integer.  A null result means there is nothing there at all.  If it tests as false it means it is an invalid integer.  It doesn't seem necessary to sanitize anything since passing the test means it is okay.  This pattern would work for numbers but emails or passwords in strings would require more sophisticated processing.  Here filter_var wasn't used at all because of filter_input.  My original post wondered whether there were so many ways of doing it that only a lot of trial and error and experimentation would be required to get to the point of making it easier.  These two examples seem straightforward such that a person wouldn't have to buy more books just to find out the right way of doing it from the experts.

Link to comment
Share on other sites

The string example is not great for a couple of reasons:

  • You'll get a notice if $_POST['name'] isn't set
  • The $set variable really isn't necessary
  • Instead of strlen(), you can just use empty()
  • $name ends up being an empty string, which may not be ideal

In the most terse way, you could do this:

$name = (isset($_POST['name']) && !empty(trim($_POST['name']))) ? trim($_POST['name']) : false;

So $name is either assigned the trimmed version of $_POST['name'] or false (if $_POST['name'] doesn't exist or it does exist but is empty).

 

Of course, depending upon how $name might be used later in the script, it may be preferable for it to have an empty string value, in which case that isn't the best solution. 

 

There are so many ways of validating data for a few reasons:

  • PHP has evolved (e.g., the Filter extension is still relatively new)
  • One form--and its data--differs from another
  • How a script uses form data differs, one from another
  • Coding habits differ

It sounds like you're trying to find one simple universal answer here, but, unfortunately, books or no books, there are very few situations in programming where there is one clear right way to do something. 

Link to comment
Share on other sites

My web host uses PHP v.5.4.9 so I can't use isset($_POST['name']) directly and have to create a variable for the test.  One person said that its best to create variables to work with at the start for every form field anyway instead of using the POST input field itself.

 

Writers say that client-side validation is for the client's benefit and the required attribute of HTML5 or jQuery is useful.  But they say that server-side checking is crucial because JavaScript is easily circumvented by malicious activity.  One writer said you should allow a zero or space in a required field to say that something has been typed in avoiding an error message.  He said that strlen() would detect that and pass it up as an error.  However, empty() reports that a zero is a missing value, but it recognizes that a space makes it not empty.  So if trim() was used purging a white space, the filler to satisfy a requirement would be removed and the purpose would be defeated.  Maybe its a bad idea to give the client tricks to use.

 

One writer showed where "malicious JavaScript code" could be placed in an entry creating a SQL injection attack.  He used htmlentities() to produce named entity replacements but then said they were placed as "output to the client browser not being considered part of the markup."  Does that mean that the malicious code in <script> tags became neutralized by htmlentities()?

Link to comment
Share on other sites

My web host uses PHP v.5.4.9 so I can't use isset($_POST['name']) directly and have to create a variable for the test.

I hate to tell you this, but that doesn't make any sense. PHP 5 and later most definitely support using that construct. 

 

Yes, malicious code in script tags is neutralized via htmlentities(). 

Link to comment
Share on other sites

  • 1 month later...

I'm testing the following code on my Web provider's platform:

 

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

 

   $name = filter_input(INPUT_POST, 'name', FILTER_SANITIZE_STRING);

 

   if($name === null)  {

      $name = "No name entered";

 

   }  elseif (empty($name))  {

      $name = "Valid name required";

 

   }  elseif ($name === false  {

      $name = "Invalid name";

 

   }  else  {

      $name = stripslashes($name);

      $name = htmlentities($name, ENT_QUOTES); }

 

With testing it recognizes a valid name and a non-existent (empty) one.  But I cannot create an input which should be recognized as null or invalid.  The filter is supposed to return false if it is an invalid string or null if no entry has been created.  Either the coding for the test results is incorrect or the function is no working correctly.  Thanks for the help in ironing this out.

Link to comment
Share on other sites

No entry in the input field is recognized as being set (but empty) which doesn't seem logical.

 

if (isset($_POST['name']))  {

   echo "name set to " . $POST['name']; }

if (empty($POST['name']))  {

   echo " empty name"; }

 

$name = filter_input(INPUT_POST, 'name', FILTER_SANITIZE_STRING);

 

if (is_null($name)) {

   echo "name variable is NULL";

 

The function is supposed to return NULL if not set but it doesn't happen even with no entry whatsovever.  Empty() is true with the digit 0 entered but a space is a valid string and not an empty string (maybe you couldn't even enter an empty string yourself because that's impossible using data entry).

 

Link to comment
Share on other sites

Right, that makes sense if you understand how PHP handles HTML form inputs. filter_input() returns NULL if the variable is not set. However, an empty form input creates a variable with an empty string value which in PHP means a variable that is set by definition. 

 

Conversely--if I recall correctly--a SELECT menu or radio button group without a selection would result in variables that are not set. The same goes for file. But textarea, email, password, text, and similar inputs create set but empty variables. 

Link to comment
Share on other sites

FILTER_SANITIZE_ STRING strips tags so a browser won't run malicious code.  An internet reference said stripslashes is also important.  That would mean a backslash would be deleted leaving the character being escaped which wouldn't erase the whole combination.  Maybe it would also remove slashes in a malicious directory entry (but then leave unnecessary text).  The reference also said to use htmlentities().  If there are cases remaining there would be entities like &abc; created afterwards corrupting the data which is to be stored in a database.  Should a regular expression be used to delete any entities (&123;) after running htmlentities()?

Link to comment
Share on other sites

  • 3 weeks later...

Two questions:

(1)  I activated PHP on a site I have at godaddy.com and they said PHP was "vulnerable" and they asked if I wanted to purchase locking software to protect myself when using PHP.  I don't need it for testing but I guess a user should know why PHP is vulnerable.

 

(2)  I have this code and added MySQL to it.  Its probably overkill but for learning it makes sense.

 

$name = filter_input(INPUT_POST, 'name', FILTER_SANITIZE_STRING);

 

if(is_null($name)) {

     $name = "No name entered";

} elseif ($name === false)   {

     $name = "Invalid name";

} elseif (empty($name))  {

     $name = "Valid name required";

} else  {

     $query = "SELECT shopname FROM shopper WHERE shopname = '".$name."'";

     $name = mysqli_real_escape_string($db, $name);

}

 

The sanitize and mysqli environments are probably separate so maybe it takes both to cover all the bases.  I don't think someone starting out like myself should make assumptions on what the PHP code actually does until he asks someone does know.  Thanks for the feedback.

Link to comment
Share on other sites

Saying PHP is "vulnerable" is just silly. They're trying to sell you something. Your name handling looks fine except that you're running $name through mysqli_real_escape_string() _after_ using it in a query, which is backwards. 

Link to comment
Share on other sites

I was just defining the query variable to document it for learning purposes and it won't be executed in code until later.  Printing $name in the HTML for "sticky" purposes works easily and putting error messages in it for testing now is expedient whereas later the errors should probably be put in an array and listed.  My guess is that filter sanitizing and mysqli escaping probably do the same thing, but using both is extra insurance unless obviously redundant.  Also the multiline testing of the variable should probably be put in a function to make it less wordy when there are lots of variables to test.

Link to comment
Share on other sites

I see what you were saying.  I was trying to figure out the syntax of a PHP SELECT statement and thinking parameters.  So I looked in a book and came up with:

 

$query = "SELECT shopname FROM shopper WHERE shopname = ?";

 

$stmt = $db -> prepare($query);

$stmt -> bind_param('s', $name);

$stmt -> execute();

$stmt -> bind_result($name);

 

However, I haven't tested it yet on the website so it might not be right yet.

Link to comment
Share on other sites

The MySQL code worked just fine.  Thought I'd experiment by putting some basic PHP code on an aspx (ASP.Net) page to see if that engine would recognize it.  Apparently it's apples and oranges so it's not the same as including it on a html page.  Thought using some PHP validation routines on an aspx page might be possible but those two aren't meant to work together.

Link to comment
Share on other sites

The extension of a file tells the web server how to handle it. So, conventionally, a .html file gets no additional processing; a .php file gets run through the PHP executable; and a .aspx file gets run through a ASP.NET executable. So putting, for example, PHP code in a .aspx file or ASP.NET code in a .php file won't have any effect. 

Link to comment
Share on other sites

 Share

×
×
  • Create New...