Forum Moderators: coopster

Message Too Old, No Replies

Problem with switch

Passing invalid data

         

max4

10:09 pm on May 17, 2009 (gmt 0)

10+ Year Member



Hello,

I'm trying to achieve something very simple. I have a select menu in a form which looks like this:

[fixed]
<select name="y">
<option value="0">valueo</option>
<option value="1">valuea</option>
<option value="2">valueb</option>
<option value="3">valuec</option>
</select>
[/fixed]

I then use switch to define a variable like so:

[fixed]
<?php
$x = array();
switch($_POST['y'])
{
case '1':
case '2':
case '3':
$x['y'] = $_POST['y'];
break;
}
?>
[/fixed]

Finally I check to see if my code is doing what I want it to do:

[fixed]
<?php
$x = array();
switch($_POST['y'])
{
case '1':
case '2':
case '3':
$x['y'] = $_POST['y'];
break;
}
if ($x['y'] = $_POST['y'])
{
Display Success Message
}
else
{
Display Error Message
}
?>
[/fixed]

The problem arises when I select value 0. Even though the switch statement clearly states that only case 1, 2, and 3 define $x['y'] = $_POST['y']; selecting value 0 still returns the success message. Mind you, value 0 is only there to test if the switch statement is working properly.

I have even tried adding default to the switch statement:

[fixed]
switch($_POST['y'])
{
case '1':
case '2':
case '3':
$x['y'] = $_POST['y'];
break;
default:
Display Error Message
}
[/fixed]

What am I doing wrong?

max4

12:14 am on May 18, 2009 (gmt 0)

10+ Year Member



I was wrong; the switch statement is working properly but I don't understand what happens on a misfire. I set up my error displays as follows:
[fixed]
<?php
$x = array();
switch($_POST['y'])
{
case '1':
case '2':
case '3':
$x['y'] = $_POST['y'];
break;
}
if ($x['y'] = $_POST['y'])
{
Display Success Message
}
else
{
if ($x['y'] != $_POST['y'])
{
Display Known Error Message
}
else
{
Display Unknown Error Message
}
}
?>
[/fixed]

I keep receiving the unknown error message, regardless of what I put into the if statement. My goal is to get the 'known error message'. I've tried the following, besides what is posted above:

[fixed]
if (!isset($x['y'])) {
Display known error message
}
[/fixed]

What's interesting about the isset function is if I do this:

[fixed]
if (isset($x['y'])) {
Display known error message
}
[/fixed]

I receive the known error message, meaning $x['y'] is defined. But there is already a check for the success message stating if ($x['y'] = $_POST['y']) then display success message, so I can conclude that $x['y'] is defined but does not equal $_POST['y']. So, it would make sense then that I can simply do this:

[fixed]
if ($x['y'] != $_POST['y']) {
Display known error message
}
[/fixed]

But that still does not display the known error message, it displays the unknown error message.

Any suggestions on what is going on here?

Thanks,
Mohamed

P.S. If I select an option that contains a value within the case parameters then the success message appears. The only difficulty is determining why the correct error message does not display.

idfer

4:21 am on May 18, 2009 (gmt 0)

10+ Year Member



You need to use the double-equal sign for comparisons, so:

if ($x['y'] [b]==[/b] $_POST['y']) { 
Display Success Message
}

The way you have it with a single "=", at the if statement the current value of $_POST['y'] (which is 0) is assigned to $x['y'], then the value of $x['y'] (which is also 0 now) is used to test for true/false, 0 being same as false, it skips over to the else part.

max4

5:17 am on May 18, 2009 (gmt 0)

10+ Year Member



Thank you idfer, that works; however, a problem arises when the user does not provide a value from the select menu. Example:
[fixed]
<select name="y">
<option value="">&nbsp;</option>
<option value="1">valuea</option>
<option value="2">valueb</option>
<option value="3">valuec</option>
</select>
<?php
$x = array();
$z = array();
switch($_POST['y'])
{
case '1':
case '2':
case '3':
$x['y'] = $_POST['y'];
break;
}
if ($x['y'] == $_POST['y'])
{
$z['y'] = mysql_real_escape_string($x['y']);
$sql = "INSERT INTO table (y) VALUES ('{$z['y']}')";
$result = mysql_query($sql);
Display Success Message
}
else
{
if ($x['y'] !== $_POST['y'])
{
Display Known Error Message
}
else
{
Display Unknown Error Message
}
}
?>
[/fixed]

In this case, if the user selects the empty value then the form processes without filtering the select values and outputs a record with no value in the database. If I use ($x['y'] = $_POST['y']) then it skips to the else statement like you pointed out, but gives an unknown error (which you explained) - unless I select one of the cases then it correctly sends the output to the database. I'd like to point out also that if I select one of the cases using the if ($x['y'] == $_POST['y']) statement data still is sent correctly to the database.

Any ideas why my script is allowing the empty non-case value to pass but refusing non-case 'hard' values? The way it should work is to only allow one of the case values through and essentially block out any other value.

enigma1

9:15 am on May 18, 2009 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



use the default case in the switch and handle the error there. eg:

switch($_POST['y'])
{
case '1':
case '2':
case '3':
$x['y'] = $_POST['y'];
break;
default:
// Error handling
}

and the same should go if the $_POST['y'] isn't set which you can place before the switch statement.
if( !isset($_POST['y']) ) {
// Error handling
}
This way you don't need the if ($x['y'] == $_POST['y']) because everything is being validated earlier.

max4

1:53 pm on May 18, 2009 (gmt 0)

10+ Year Member



Thanks for the reply enigma. I've tried that but my script simply skips all errors if I submit with the blank select value. I currently have

if (strlen($_POST['y']) > 0)
{
Display success and other stuff
} else {
if (strlen($_POST['y']) < 0) {
Display blank error
}
Rest
}

It's as though if a user provides a blank value for the select statement, none of the filters work. I know I can be satisfied in the way it works now because malicious content contains characters - but the script is incomplete as blank values are still getting through the filter.

This doesn't work either:


if (!isset($_POST['y'])) {
Display Blank Error
} else {
switch($_POST['y'])
{
case 1:
case 2:
case 3:
$x['y'] = $_POST['y'];
break;
default:
Display Error
}
}

And I think the reason for this is that $_POST['y'] is indeed set with the blank value and I say this because the blank value is entered into the database (replacing the null).

Furthermore, regardless what the value of $_POST['y'] is, the default case is skipped and we end up with the unknown error message; every time. I am baffled by this paradox.

penders

2:05 pm on May 18, 2009 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member Top Contributors Of The Month



<option value="NeedAValueHere">&nbsp;</option>

I think you should always have a value in your option elements.

max4

2:09 pm on May 18, 2009 (gmt 0)

10+ Year Member



Thanks for the reply penders. The script, prior to the addition of the switch statement, would return a blank error message if $_POST['y'] was submitted with value="" The difficulty arises after the inclusion of the switch statement.

I want to be absolutely certain that the only data going into the database is one of the cases in the switch statement.

idfer

5:06 pm on May 18, 2009 (gmt 0)

10+ Year Member



I think you're making this a bit over-complicated, heh. You want to display a form with a select widget, validate the user input, and if valid insert into DB, right?

First, where do you get the list of options for your select? Whether from DB or hard-coded, you should end up with an associative array:

$yValues = array(
'1' => 'valuea',
'2' => 'valueb',
'3' => 'valuec'
);

Use this same array to display the form element and validate the input. Form element:

echo '<select name="y"'>;
echo '<option value="">&nbsp;</option>';
foreach($yValues as $value => $text)
echo '<option value="'.htmlentities($value).'">'.htmlentities($text).'</option>';
echo '</select>';

Validation:

$x['y'] = $_POST['y'];

// Mandatory check
if(!isset($x['y']) ¦¦ trim($x['y']) == '') {
display error "must select a value for y";

// Check input is valid
} elseif(!isset($yValues[$x['y']])) {
display error "invalid value for y";

// All good insert into DB
} else {
$result = mysql_query('INSERT INTO table (y) VALUES ('
."'".mysql_real_escape_string($x['y'])."')"
);
if($result === false) {
display system error;
} else {
display success;
}
}

That's your basic form processing logic (although your real code should be partitioned into separate functions for maintainability). Styling notes:

- Try to test for exceptions first because the code for handling these is usually shorter and your "elseif" and "else" blocks fall closer to the "if" statement.

- Comment your code, it's easier for us to figure out what you're doing, and you'll thank yourself next week when you stare at the code and try to figure out what you were thinking.

max4

1:32 am on May 19, 2009 (gmt 0)

10+ Year Member



Thanks for the reply idfer. The solution you provided would work; but it is not what I aim to accomplish.

I sat down with one of the members of my team and we concluded that it is entering the database because the statement $x['y'] == $_POST['y'] is true if value = "". Because $x is an empty array, and $_POST['y'] is empty, then empty == empty. What still has us baffled is the check we have before that


if ((strlen($_POST['y']) > 0) &&
($x['y'] == $_POST['y']))
{
success
} else {
error
}

The script seems to think $_POST['y'] is greater than zero, even though its value is nothing because it is hard coded in the select menu to be nothing.

Thank you for the styling tips. In my opinion, I find that leaving notes complicates things for me. It's like learning Arabic and leaving English notes everywhere. The pages become a linguistic mess. I enjoy the fluidity of reading just one language.

It does make things easier on others though. Reading another person's work is like listening to dialect, in my opinion :)

max4

4:52 am on May 19, 2009 (gmt 0)

10+ Year Member



I solved the problem. A mistake in my error handling resulted in the unexpected unknown error. I used ¦¦ when I should have used &&. Because of the or statement, errors were passing through my filter and causing unusual behavior.