tags:

views:

334

answers:

7

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?

+9  A: 

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
}
Ant P.
gives me Fatal error: Can't use function return value in write context in C:\WAMP\www\add-thread.php on line 13
You can't use a function call inside empty(). Do it separately, then check the input length is > 0.
Ant P.
A quick way to apply trim to all post elements: $_POST = array_map( 'trim', $_POST ).
Nick Presta
A: 

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.');    
}

}

Ólafur Waage
now you can post without even writing anything
You have to switch the logic around.
Ólafur Waage
I updated it to clarify
Ólafur Waage
empty() doesn't return true for strings consisting of whitespace, which is what the questioner is attempting to deal with.
Rob
Ólafur Waage
A: 

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.

Trevor Bramble
that didnt work but this did: foreach($_POST as $key => $value) $_POST[$key] = trim($value);
also - entries in $_GET and $_POST can be arrays so u have to go thru recurssively
arin sarkissian
Good call, Arin. Definitely not a drop-in solution for any occasion.
Trevor Bramble
+1  A: 

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).

Rob
thanks. didnt know that.
A: 

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);
}
arin sarkissian
+1  A: 

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

$_POST = array_map('trim', $_POST);
Mark Biek
+3  A: 

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.

Alan Storm