Simple if() not working as expected - php

I am sure that I am simply overlooking something, and I spent a few days working on this and cant seem to figure it out.
after logging in on the previous page I get the username and password,
$username = mysql_escape_string($_POST['adminusername']);
$password = mysql_escape_string($_POST['adminpassword']);
and then I go to the database to pull the username and password from the database,
$sql = "SELECT username, password FROM `weaponsadmin`";
$rows = $db->query($sql); while ($record = $db->fetch_array($rows)) {
now here is the part that is confusing me, if i have the following, no matter what I use for the username or password, it will NOT allow for me to login,
if ( ($record[username]==$username) && ($record[password]==$adminpassword) ){
$_SESSION['loggedin'] = true;
$_SESSION['username'] = $adminusername;
header( "Location: admin.php" ) ;
}
else {
header( "Location: index.php?login=error" ) ;
}
however if I use the following, it will allow me to login in if the username is correct, but it allows for me to input anything for password and it works,
$adminusername = $record[username];
$adminpassword = $record[password];
if ( ($adminusername==$username) && ($adminpassword==$adminpassword) ) {
$_SESSION['loggedin'] = true;
$_SESSION['username'] = $adminusername;
header( "Location: admin.php" ) ;
}
else {
header( "Location: index.php?login=error" ) ;
}
So in summary for some reason the && part doesn't seem to work correctly and if somebody could help me with the code and let me know where my code could be improved for better security and how to make this work correctly, thanks

what is the point here $adminpassword==$adminpassword :
i think it should be:
if ( ($adminusername==$username) && ($adminpassword==$password) ){

$record[username] should be $record["username"] (and so on). indexes are strings or int

You're using arrays wrong.
You expect: $record[username]; //retrieve contains of key "username"
What really happens:
$record[username];
/*
retrieves a key in the record array under the key which is a value of a
constant named "username" (if it's defined) and an empty string with
E_WARNING if it's not.
*/
You need to either single or double quote the index names, for example $records['username'].
However, you can use unquoted array indexes inside of a string (and these will work as you expect) -> $someString = "Blahblahblah, ergo $record[username] is a donkey.";.

You can use === instead of ==. Read this.
strcmp() isn't necesarry here.

To add to Michael's answer, the reason why you should not use == for string comparison (hopefully this will help you navigate similar difficulties in the future) is that when you call a simple == on an object (such as a string, or really anything other than an int, double, float, char, long, short, or boolean, in most languages), what you're really comparing is the address in memory of each object, that is, the pointer value.
This is useful if you want to know if two variables are referencing the same object, but not so useful if you want to know if two objects are identical. So this is true:
$string_a = $some_string;
$string_b = $some_string;
$string_a == $string_b;
but this is not:
$string_a = getUserInput(); # user types in "hello"
$string_b = getUserInput(); # user types in "hello"
$string_a == $string_b;
and this may be true depending on the language you're in, if it stores string literals in memory independently of the user-defined variables to which they are attached:
$string_a = "hello";
$string_b = "hello";
$string_a = $string_b;
So unless you're checking to see if two objects are in fact the same object, and not merely identical, use, as those before me suggested, a function to compare the two. Such a function usually goes down to the level of primitive types, which can be compared using == as you would expect, and returns true if all of those comparisons do.

Don't use == for string comparison. Instead, use strcmp() or === to match strings.

Related

PHP: most efficient way of structuring IF clauses

I'm looking at a way of structuring if clauses using the DRY principles of Don't Repeat Yourself.
This is work involving scripts that are ~15 years old and poorly coded with globals etc., and I'm asked to drag this script/site into the 21st Century - but due to time and cost constraints, I can not facilitate a complete site rewrite from scratch, although I know that would be far better.
I have a value that is formerly a global value and I do not know where it comes from and it may come from different places from different pages.
I have some activity that is checking an input value in $_POST or $_GET data, if the input value is empty (or invalid), then check if the value is in fact sat in a $_SESSION. If the input value is still empty (or invalid) then boot to another page.
My code as it stands:
$userId = $_REQUEST['userid'];
if (empty($userId)) {
$userId = $_SESSION['userid'];
}
if(empty($userId) || !is_numeric($userId))
{
header("Location:contactdetails.php");
die();
}
I repeat the empty() function twice, I could wrap both IF's into one line but then would need an IF to pass the value from the REQUEST or the SESSION into the $userId variable.
Is there a (better) way that I can check the two possible inputs to see where this [formerly global] '['userid']' variable is coming from and applying that value to the page-local userId variable?
You can use the ternary operator. The first expression will be used if it evaluates to true, otherwise the latter one. The $_REQUEST superglobal takes precedence in this case, like the code in the question:
$userId = $_REQUEST['userid'] ?: $_SESSION['userid'];
if (empty($userId) || !is_numeric($userId)) {
header("Location:contactdetails.php");
exit;
}
However as Havenard stated in a comment above, blindly trusting request data could be a security issue.
Also note that the condition will be true if any user IDs are 0, in that case a null check would be better:
$userId = $_REQUEST['userid'] ?: $_SESSION['userid'];
if ($userId === null || !is_numeric($userId)) {
header("Location:contactdetails.php");
exit;
}
Of course this is assuming that you do not store falsy values in the $_SESSION as a non-null value.
If $_SESSION['userid'] is guaranteed to be set, rink.attendant.6's answer seem like a clean approach. Otherwise, you will have to perform the necessary checks for both $_REQUEST and $_SESSION to guarantee that $userId is set properly:
if (isset($_REQUEST['userid']) && is_numeric($_REQUEST['userid']))
$userId = $_REQUEST['userid'];
else if (isset($_SESSION['userid']) && is_numeric($_SESSION['userid']))
$userId = $_SESSION['userid'];
else // no acceptable value for $userId in sight
{
header("Location: contactdetails.php");
exit;
}
You might want to reconsider using is_numeric() also, since it validates as true for numeric representations in any format, not just positive integers as you might expect.
There are two different problems you're solving here. First is the problem of defaulting and second is filtering. Take each in turn.
For defaulting, you can implement a simple "get from array if it exists otherwise default" helper:
function array_get(array $a, $key, $default = null) {
return (array_key_exists($key, $a) ? $a[$key] : $default);
}
You can then use this helper to provide default chaining:
$userId = array_get($_REQUEST, 'userid', $_SESSION['userid']);
For filtering, you know from this chain that you've got either a null or a value from one of the two arrays. Since you're looking for ostensibly a database ID, I like a function like this:
function is_id_like($it) {
$rc = filter_var($it, FILTER_VALIDATE_INT, array ('options' => array (
'default' => false, 'min_range' => 1,
)));
return (false === $rc ? false : true);
}
This ensures that the number you give it looks like an int, is 1 or higher, and will return false if not. So all these pass: 1, "1", and "1.0" but these all fail: 0 and "1.1".
Combining these, and allowing for the session to not have a user ID:
$userId = array_get($_REQUEST, 'userid', array_get($_SESSION, 'userid'));
if (! is_id_like($userId)) {
header('Location: contactdetails.php');
die();
}
The total number of checks has changed to one array_key_exists and one filter_var, but the code is substantially more readable and these methods can be reused throughout your code base.
If the value will only ever be set in either the request or session then concat the possible values and validate once.
You should be using if-else for two-way statements and using a switch for n-way statements.
swicth($myVar){
case 1: doX();break;
case 'a': doY();break;
case 2: doZ();break;
default: doA();
}

E_NOTICE : type 8 -- Undefined variable

I'm pretty new with PHP and I'm trying to learn all by myself.
I tried to create a simple form with a simple calc to incorporate on my website but I got this E_Notice. And don't know how to echo the result in the html too.
Someone can help?
Link here: PHPfiddle
Your code checks to see if $_POST['valor-finan'] is set -- if it is, it sets the variable $valor_finan. If it IS NOT set, then the variable $valor_finan is never created. Then, your code checks to see if it is empty -- it isn't empty, it doesn't even exist.
Instead, you should set the variable to something no matter what, that way it exists in the code. If you get some $_POST data, use that data, otherwise provide a default value like false.
empty is not the best function to check numeric values. Use is_numeric -- a 0 might be acceptable for your application, but empty will consider 0 to be... empty. Not good for financial calculations.
Also, you are using globals where you don't need to. The global keyword is always bad practice. The switch was unnecessary, too.
Here is your code with the corrections in place:
$valor_finan = (
isset($_POST['valor-finan']) ?
$_POST['valor-finan'] : false
);
$valor_entrada = (
isset($_POST['valor-entrada']) ?
$_POST['valor-entrada'] : false
);
$numero_parcela = (
isset($_POST['numero-parcela']) ?
$_POST['numero-parcela'] : false
);
function calculaFinanciamento ($valor_finan, $valor_entrada, $numero_parcela) {
if(
is_numeric($valor_finan) &&
is_numeric($valor_entrada) &&
is_numeric($numero_parcela)
){
$taxa_percent = 5;
$valor_parcela_bruto = ($valor_finan - $valor_entrada) / $numero_parcela;
$valor_percent = ($taxa_percent / 100) * $valor_parcela_bruto;
$valor_parcela = $valor_parcela_bruto + $valor_percent;
return $valor_parcela;
} else {
return "Por favor preencha os campos, todos são requeridos";
}
}
echo calculaFinanciamento($valor_finan, $valor_entrada, $numero_parcela);
Your variables valor_finan , valor_entrada, numero_parcela have not been set.
Use isset($valor_finan) etc to check if they contain records/have been set or not.

Understanding XOR PHP

I am writing section in my program to update a user, and there is password and confirm passwords. I dont want to do anything to the password field in the DB unless they have filled the fields in.
So I have error checking for:
if(($sql['password']!="") && ($sql['cpassword']!=""))
{
if($sql['password'] == $sql['cpassword'])
{
//update
}
}
However I want to write a quick line to throw an error message if they only filled out one of the password fields. So I figured:
if($sql['password'] ^ $sql['cpassword'])
{
echo You must fill out <i>both</i> password fields and they <i>must</i> match.";
}
Would do it, but It doesnt seem to. Then I added a NOT operator, !, and that seemed to work well, however if both fields have nothing in them, I still get the error message :(
From the logic I can see from this answer, It would seem that simple XOR would work. But
But it doesnt, Can someone explain to me why?
XOR certainly is not what you want here.
As David states, XOR will return a "true" result if the values are different, however when you XOR two strings the XOR operation is only done up to the point of the shortest string.
Examples
'AAAA' ^ 'AAAA' This returns an empty string (false-equivalent value) as the values are the same.
'AAAA' ^ 'bbbb' This returns an non-empty string (true-equivalent value)..
'AAAA' ^ 'AAAAbbbb' This returns an empty string (false-equivalent value), even though the strings are different. This is because the result of the operation only considers the first 4 characters.
In Sandy Lee's example (bool)$string does not really help.
(bool)'0' = false
(bool)'1' = true
This does not tell you if the string is empty or not. It simply gives you the boolean-equivalent value of the string.
There is no need to use XOR here at all. It's not the right tool for the job. There is no need to try and do anything fancy either, the simple tools work perfectly.
$password = trim($password);
$confirm = trim($confirm);
if (!$password || !$confirm) {
// One of the fields was not completed.
}
elseif ($password !== $confirm) {
// Fields did not match
}
else {
// Update password
}

What is the proper way to initialize empty strings in PHP?

In C#, I've come to adopt the following method of initializing empty strings:
string account = string.empty;
rather than
string account = "";
According to my mentor and other C# developers I've talked to, the first method is the better practice.
That said, is there a better way to initialize empty strings in PHP? Currently, I see the following widely used:
$account = '';
Thanks.
What you're doing is correct. Not much more to say about it.
Example:
$account = '';
if ($condition) $account .= 'Some text';
echo $account;
You could get silly and do something like this:
$str = (string) NULL;
..but that's utterly pointless, and it's exactly the same thing - an empty string.
You're doing it right.
For the most part this is irrelevant. Unlike many languages, in PHP it (usually) doesn't matter whether you initialize a variable. PHP will automatically cast an uninitialized (or even undeclared) variable as appropriate for the immediate use. For example, the following are all correct:
$a;
$a + 7; // Evaluates to 7
$a . "This is a test."; // Evaluates to "This is a test."
if (! $a) {} // Evaluates as true
The one caveat is that select functions check for variable type (as does strict equality checking, ===). For example, the following fails:
$a;
if (is_string($a)) {
print 'success';
}
else {
print 'fail';
}
This convenience comes at a heavy cost, though. Unlike strictly typed (or, at least, "more strictly" typed) languages, there is nothing in the core language itself to help you catch common programmer errors. For example, the following will happily execute, but probably not as expected:
$isLoggedIn = getLoginStatus($user);
if ($isLogedIn) {
// Will never run
showOrder($user);
}
else {
showLoginForm();
}
If you choose to initialize all your variables, do it just as you did. But then enable PHP notices (E_NOTICE) to get run-time warnings about uninitialized variables. If you don't, you're basically wasting time and keystrokes initializing your own variable.
Here are some other things to consider when working with strings in PHP:
// Localize based of possible existence
$account = (array_key_exists('account', $results)) ? $results['account'] : null;
// Check to see if string was actually initialized
return (isset($account)) ? $account : null
// If a function is passed an arg which is REQUIRED then validate it
if (empty($arg1)) {
throw new Exception('Invalid $arg1');
}
echo $arg;
// If you are looking to append to string, then initialize it as you described
$account = null;
if (!empty($firstName)) {
$account .= $firstName;
}
echo $account;
// Also, it's better to initialize as null, so you an do simple check constructs
if (is_null($account)) {
// Do something
}
// Versus these types of checks
if ($account == '') {
// Do something
}
Normally I try to avoid initializing vars like this. Instead I localize, or check for existence throughout the code, otherwise you end up maintaining a laundry list of variables which may not actually reflect usage throughout the code following initialization.
chr(32) represents ASCII space (i.e. string of 1 byte length).
If you want to avoid mistakes like $myEmpty = " " vs. $myEmpty = " " vs. $myEmpty = ""
Sometimes it's hard to tell when there are two spaces or one or none by human eyes. Using chr function that is solved for sure.
And for really empty string (zero bytes), there's no other way but to simply define it with (single) quotation marks like $nothing = '';

two equal signs in php when NOT comparing

What do the two equal signs mean when not being used to compare?
$saveOrder = $listOrder == 'a.ordering';
I've never seen anything like this in php.... I am looking at the weblinks Joomla 1.7 admin component.
Thanks
It is used for comparing. Except the result of the comparison is assigned to $saveOrder.
The following code:
<?php
list($listOrder1, $listOrder2) = array('a.ordering', 'a.something_else');
$saveOrder1 = $listOrder1 == 'a.ordering';
$saveOrder2 = $listOrder2 == 'a.ordering';
assigns true to the $saveOrder1 variable and false to the $saveOrder2 variable. If you do not believe, check for yourself here.
They are comparing. It's just not wrapped in parenthesis (like a comparison expression with if/while/etc).
$saveOrder will be assigned either true or false (the result of the condition).
I guess it is the same as $saveOrder = ($listOrder == 'a.ordering');
In your statement also the double equal sign(==) used for the comparison purpose only. Actually your statement contains both the 'assignment'(=) and 'comparison'(==) operators which leads to your confusion.
That is equivalent to $saveOrder = ($listOrder == 'a.ordering');, so first compares the $listOrder with 'a.ordering' and assign the result(true or false) to $saveOrder.
Hope this clear you confusion, if not let me know once.
$listOrder1='a.ordering';
$listOrder1='wrong'
$saveOrder1 = $listOrder1 == 'a.ordering';//1
$saveOrder2 = $listOrder2 == 'a.ordering';//
You can see the output when printing the first will be 1 whereas the second will return: (i.e. nothing)

Categories