Remy
Remy

Reputation:

Catch blank (including all-whitespace) form submissions

If have a problem on my site that users can post empty messages if they use space.

Code:

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

  // check for empty fields
  if (empty($_POST['headline']) || empty($_POST['text']) ||
      empty($_POST['forum_id'])) {
      header("Refresh: 2; url=/add-thread"); 
      die('You must fill out every field.');
  }

// No errors? Save.
else {
$headline = mysql_real_escape_string($_POST['headline']);
$text = mysql_real_escape_string($_POST['text']);

mysql_query("INSERT INTO threads (headline, text, date, forum_id, user_id)
             VALUES ('$headline', '$text', NOW(), '$_POST[forum_id]', '$user[id]')");

header("Location: /thread/".mysql_insert_id()."");
}

}

How can I fix this?

Upvotes: 1

Views: 1606

Answers (7)

user42092
user42092

Reputation:

trim() the text inputs. You can do that easily like this:

// get input vars and trim space
$callback = array('filter' => FILTER_CALLBACK, 'options' => 'trim');
$fields = filter_input_array(INPUT_POST, array(
    'headline' => $callback,
    'text'     => $callback,
    'forum_id' => $callback,
));

// check for empty fields by counting how many are set
if ( count($fields) != count(array_filter($fields)) ) {
    // something was unset
}

Upvotes: 9

Trevor Bramble
Trevor Bramble

Reputation: 8813

Right after checking for a submission:

foreach ( $_POST as $key => &$value ) $value = trim($value);

edit in response to asker's comment:

Odd that it didn't work as above. Here was my exercise to confirm it would.

tbramble@wayfarer:~$ php -a
Interactive shell

php > $arr = array('one',' two', ' three ');
php > print_r($arr);
Array
(
    [0] => one
    [1] =>  two
    [2] =>  three 
)
php > foreach ( $arr as $key => &$value ) $value = trim($value);
php > print_r($arr);
Array
(
    [0] => one
    [1] => two
    [2] => three
)    

Must have something to do with working on a superglobal instead of a normal array.

Upvotes: -1

Alana Storm
Alana Storm

Reputation: 166076

The empty function checks for variables that meet a set criteria, from the manual

Returns FALSE if var has a non-empty and non-zero value.

The following things are considered to be empty:

  • "" (an empty string)

  • 0 (0 as an integer)

  • "0" (0 as a string)

  • NULL

  • FALSE

  • array() (an empty array)

  • var $var; (a variable declared, but without a value in a class)

Your $_POST fields actually contain something like this

"   "; 

This isn't and empty string, but a string that's filled with whitespace characters.

Before using empty(), trim() the white-space from your POSTed values

$trimmed_post = array();
foreach($_POST as $key=>$value){
    $trimmed_post[$key] = $value;
}
if(!empty($trimmed_post['headline'])){
    //...
}

You don't need to put the new values into a new array, but I'm not a big fan of changing what's in the auto-generated superglobals.

One final note, you can't do something like this

if(!empty(trim($_POST['headline']))){
   //...
}

because the empty function expects to be passed an actual variable. You could do something like this instead

if('' != trim($_POST['headline'])){
//...
}

This is probably the best approach to take. You reduce the number of functions that you need to call, users can post entries with a value of 0, and the code is more explicit about what it does. Another form you'll see is

if(trim($_POST['headline'])){

}

This works because PHP evaluates an empty string ('') as false, and a non empty string as true. I tend to avoid this form because I've found a lot of PHP bugs crop up around misunderstandings on how the equality operators get boolean values out of certain types. Being explicit helps reduce occurrences of these types of bugs.

Upvotes: 3

Mark Biek
Mark Biek

Reputation: 150789

I agree that trimming is the way to go. Here's a much easier way to go about it:

$_POST = array_map('trim', $_POST);

Upvotes: 1

phatduckk
phatduckk

Reputation: 1795

I trim every $_GET & $_POST variable as soon as the app starts. try something like this:

function trimArray(&$array) {
    if (empty($array)) {
        return;
    }

    foreach ($array as $k => $v) {
        if (! is_array($v)) {
            $array[$k] = trim($v);
        } else {
            trimArray($v);
        }
    }
}

if (! empty($_GET)) {
    trimArray($_GET);
}
if (! empty($_POST)) {
    trimArray($_POST);
}

Upvotes: -1

Rob
Rob

Reputation: 48369

Just a quick note: You're injecting the value of $_POST['forum_id'] into the SQL; that's not a good idea, since a user could manipulate that value as desired, even if it is coming from a hidden field. It would be wise to escape the value, or at least pass it through intval() and ensure it's an integer (assuming integral post identifiers).

Upvotes: 1

Ólafur Waage
Ólafur Waage

Reputation: 70001

Try

if (!empty($_POST['headline']) && !empty($_POST['text']) &&
!empty($_POST['forum_id']))

For the logic.

You'd have to switch it around though.

UPDATE to clarify:

if (isset($_POST['submit']) && !empty($_POST['headline']) && 
!empty($_POST['text']) && !empty($_POST['forum_id'])) {

    $headline = mysql_real_escape_string($_POST['headline']);
    $text = mysql_real_escape_string($_POST['text']);

    mysql_query("INSERT INTO threads (headline, text, date, forum_id, user_id)
         VALUES ('$headline', '$text', NOW(), '$_POST[forum_id]', '$user[id]')");

    header("Location: /thread/".mysql_insert_id()."");
}
else
{
  header("Refresh: 2; url=/add-thread"); 
  die('You must fill out every field.');    
}

}

Upvotes: 0

Related Questions