In php I have open a .php file and want to evaluate certain lines. Specifically when the $table_id and $line variables are assigned a value.
Within the text file I have:
...
$table_id = 'crs_class'; // table name
$screen = 'crs_class.detail.screen.inc'; // file identifying screen structure
...
amongst other lines. The if statement below never detects the occurance of $table_id or $screen (even without the $ prepended). I can't understand why it won't work as the strpos statement below looking for 'require' works fine.
So, why isn't this if statement getting a hit?
while ($line=fgets($fh)) {
//echo "Evaluating... $line <br>";
**if ((($pos = stripos($line, '$table_id')) === true) || (($pos = stripos($line, '$screen'))===true))**
{
// TODO: Not evaluating tableid and screen lines correctly fix.
// Set $table_id and $screen variables from task scripts
eval($line);
}
if (($pos=stripos($line, 'require')) === true) {
$controller = $line;
}
}
use !==false instead of ===true
stripos returns the position as an integer if the needle is found. And that's never ===bool.
You might also be interested in PHP's tokenizer module or the lexer package in the pear repository.
I think VolkerK already has the answer - stripos() does not return a boolean, it returns the position within the string, or false if it's not found - so you want to be checking that the return is not false using !== (not != as you want to check the type as well).
Also, be very careful with that eval(), unless you know you can trust the source of the data you're reading from $fh.
Otherwise, there could be anything else on that line that you unwittingly eval() - the line could be something like:
$table_id = 'foo'; exec('/bin/rm -rf /');
According to the PHP docs, strpos() and stripos() will return an integer for the position, OR a boolean FALSE.
Since 0 (zero) is a valid, and very expect-able index, this function should be used with extreme caution.
Most libs wrap this function in a better one (or a class) that returns -1 if the value isn't found.
e.g. like Javascript's
String.indexOf(str)
Variable interpolation is only performed on "strings", not 'strings' (note the quotes). i.e.
<?php
$foo = "bar";
print '$foo';
print "$foo";
?>
prints $foobar. Change your quotes, and all should be well.
Why are you using the === Argument?
If it is anywhere in the line, it will be an integer. You're comparing the type also by using ====
From my understand you're asking it "If the position is equal and of the same type as true" which will never work.
Related
I want to check if a numeric variable has a value (including '0') and is not empty. Empty meaning EMPTY (''), not '0'.
Is this really the best I can do with PHP?
if (isset($variable) && $variable !== '') { ... }
I'd like to do this with one check without writing a function for it...
What you are trying to check is string length, not "empty". This can easily be done using strlen().
if (isset($variable) && strlen($variable) > 0) {
// Do something
}
If you want to exclude whitespace as invalid, you can add a trim() in there as well (generally recommended).
if (isset($variable) && strlen(trim($variable)) > 0 } {
// ...
}
The best thing you could do, is making your own custom function. The point is to pass the variables by reference to not trigger a warning, when you pass an undefined variable. As posted as comment, I'd use something along the line isset($variable) AND !empty($variable) AND !is_numeric($variable) AND $variable !== false to cover all cases.
Your custom function could look like this (improved version):
function is_blank(&$variable) {
return (bool) !(isset($variable) AND (!empty($variable) OR is_numeric($variable) OR $variable === false));
}
https://3v4l.org/ZcCDu
Yes, your way is the best (most efficient) way to:
insure the variable has been set (so you don't get an warning checking a variable that's not been set)
it's not the empty string ''
But, could be '0', 0,false, null, or [] which all count as empty in php, but you wish to consider as non-empty as indicated by your OP
your !== will ensure only exactly the string '' is compared (no casting/conversion)
The use of strlen works as well, but if you look at the opcode generated you'll see direct comparison is more 3 times computationally more efficient (assuming all operations are equally weighted, even more efficient if operations like DO_FCALL take significantly more cycles to execute than a basic IS_NOT_IDENTICAL check)
The !== ''version bytecode:
IS_NOT_IDENTICAL ~1 !0, ''
The strlen() > 0 version bytecode:
SEND_VAR !0
DO_FCALL 1 $1 'strlen'
IS_SMALLER ~2 $1, 0
(The answer has been edited. Consult the additionals further down under "ternary operations").
Why go through the trouble of using all that?
Just use an "not empty" if(!empty($var)){...}
However, if you're using this with a GET array, then yes; it would be best to use an isset() and empty() on a conditional statement.
I want to check if a variable has a value (including '0') and is not empty
That to me interprets as:
Check if a value has a value and is not empty (as you wrote) and stands to contain a 0 (zero).
Therefore:
if(!empty($var) && $var='0'){...}
I'd like to do this with one check without writing a function for it...
Use a ternary operator then.
However "without a function"... right well you can't. You still need "some type of function".
About that "ternary operator" I mentioned above. You can reference what are called "nested ternary operations" in both these Q&A's on Stack:
How to concatenate multiple ternary operator in PHP?
nested php ternary trouble: ternary output != if - else
That way you won't need a custom function.
Sidenote: I am by far not taking away or trying to take away from (Charlotte's) accepted answer (which should remain as accepted). This is just an additional method of achieving your (ultimate) goal.
I am taking over the maintenance of an old web site and came across this confusing syntax for processing a form that I have never seen before, and I am not exactly certain what it does:
foreach (array('address','comments','country','email','mail_content','name','title') as $vuln)
{
isset($_REQUEST[$vuln]) and $_REQUEST[$vuln] = htmlentities($_REQUEST[$vuln]);
isset($_GET[$vuln]) and $_GET[$vuln] = htmlentities($_GET[$vuln]);
isset($_POST[$vuln]) and $_POST[$vuln] = htmlentities($_POST[$vuln]);
isset($$vuln) and $$vuln = htmlentities($$vuln);
}
It's the "and" that is throwing me - I read it as "if variable is set convert it to htmlentities, but why is there an "and" in there?
Finally what does the last line do?
isset($$vuln) and $$vuln = htmlentities($$vuln);
It's using the operator precedence rules of PHP in an unusual way.
If you have an and statement, PHP will stop processing it if the left side is false - there's no need to check the right hand side, because it won't make a difference to the end result. (The converse is also true for an or statement if the left hand side is true.)
So the coder that wrote this is using it as a shorthand for:
if (isset($_REQUEST[$vuln])) {
$_REQUEST[$vuln] = htmlentities($_REQUEST[$vuln]);
}
They've save a small amount of typing, at the cost of making the code slightly harder to read. It's good practice to use isset to make sure that your array values are set before you use them, which is why the check is there.
As to the last line; logically, it's doing the same as the above, but with a variable variable. The first time through, $vuln will be set to the first item in your array, which is address - the final line of code is checking to see if there's a variable called $address, and if so, set its value to htmlentities($address).
That's what the code is doing. Why it's checking REQUEST, GET, and POST is beyond me.
Hi These are the nothing but the shortend form.
isset($_REQUEST[$vuln]) and $_REQUEST[$vuln] = htmlentities($_REQUEST[$vuln]);
above line means
if(isset($_REQUEST[$vuln])){
$_REQUEST[$vuln] = htmlentities($_REQUEST[$vuln]);
}
Also the $$vuln is a reference variable its checking the same that if reference variable is set then assign it value
isset($var) and <statement goes here that uses $var>;
This basically only executes the <statement ...> if the statement preceding and (in this case isset($var)) evaluates to true. This happens because if anything is false before a and, there's no need to evaluate (or execute) the rest. This works similarly to:
if (false && condition) { ... }
The condition will never be evaluated, since no matter what its value evaluates to, the if condition will always evaluate to false.
A more readable alternative for the first example:
if (isset($var)) {
<statement goes here that uses $var>;
}
As pointed out in the comments by #chris85, see $$variable.
An example of a variable variable:
$vuln = 'abc'; /* Regular variable assignment */
$$vuln = 'def'; /* This is "equivalent" to $abc = 'def'
* because $$vuln expands to $<contents of $vuln>,
* therefore $abc is assigned with 'def'.
*/
/* $abc is now a variable with 'def' as its value */
It might be easier to comprehend as the following, for the first iteration through the array:
<?php
if(isset($_REQUEST['address'])) {
$_REQUEST['address'] = htmlentities($_REQUEST['address']);
}
if(isset($_GET['address'])) {
$_GET['address'] = htmlentities($_GET['address']);
}
if(isset($_POST['address'])) {
$_POST['address'] = htmlentities($_POST['address']);
}
if(isset($address)) {
$address = htmlentities($address);
}
It looks to me like legacy code that probably was a replacement for (or perhaps in addition to) 'magic quoting' when 'register globals' was turned on. Probably so they could do some pseudo escaping of variables before database inserts and or page echos.
I have seen programming practices where a string or a boolean can be returned from a function. In such cases, is it recommended to check for empty() and isset() in the if loops, or will just doing a check like if($returnvar) will work or not.
Here's a piece of code I am playing around with. What do you think should be the output and are the checks correct in the if condition?
Thanks,
<?php
function testMe()
{
try
{
$returnText = 'John King Rocks';
return $returnText;
}
catch (Exception $e)
{
return false;
}
}
$str = testMe();
if ($str)
{
echo $str;
}
?>
This code should work (for this specific example of $str), but checking for Boolean in PHP is risky, as you suggested, and should be done with caution, I would suggest (in general) to check it as follows:
if ($str !== false)
{
echo $str;
}
What will happen is $str will be type casted to a boolean. So, the string will evaluate to false when it is:
The empty string
The string "0"
Every other value is considered true, which may not be the behavior you desire. So, to answer your questions:
What do you think should be the output?
Well, the return string doesn't match either of the two conditions, so the if statement will evaluate to true and the $str will be echo()'d. (Not to mention that the above code can never produce an Exception).
Are the checks correct in the if?
That depends on the functionality you're looking for. If you want to consider all strings (including "" and "0") to be valid, and to skip the echo() only when the function returns false, then you should check if the return value's equality with !== false. Otherwise, if those two conditions above are acceptable as false, you should be fine.
if is not a loop. It's a conditional. echo false will be coerced to echo '0', so the if check is only necessary if you don't want to print a zero. However, echo null will not print anything at all. Even better would be to return empty string. You should avoid mixing return types. Many other languages don't even allow it.
By the way your exception handling does nothing .. the contents of the try cannot throw an exception. Swallowing exceptions is also bad, and you need a $ before the e.
In answer to your question, there is a phrase "paranoid programming is professional programming." That is, you should do as many checks as possible if you want your application to work consistently (and the if check is good in this case), but it's also important to know what methods you are working with and the expected result. Do you want some other handling if testMe is false? Or do you want to just not print anything?
How can you search a partial string when typing (not to use MySQL) like the LIKE function in MySQL but using PHP when searching a string, e.g.
<?php
$string = "Stackoverflow";
$find = "overfl";
if($find == $string)
{
return true;
}
else
{
return false
}
?>
But that will obviously work won't, but is there a function where you can search partially of a string? That would be great :)
EDIT:
What if it was in an array?
if i use the strpos, it does the echo, If I use it, it goes like truetruetruetruetrue.
I tend to use strpos
$needle='appy';
$haystack='I\'m feeling flappy, and you?';
if(strpos($haystack,$needle)!==false){
//then it was found
}
If you want it to ignore case, use stripos.
Note that a subtlety about this is that if the needle is at the very start of the haystack, in position 0, integer 0 is returned. This means you must compare to false, using strict comparison, or it can produce a false negative.
As noted in the manual, linked above
Warning
This function may return Boolean
FALSE, but may also return a
non-Boolean value which evaluates to
FALSE, such as 0 or "". Please read
the section on Booleans for more
information. Use the === operator for
testing the return value of this
function.
As far as using arrays, strpos is meant to take two strings. Using an array will produce Warning: strpos() expects parameter 1 to be string, array given or 1Warning: strpos(): needle is not a string or an integer`.
Okay, let's say you have an array of strings for which to search.
You can
$needles=array('hose','fribb','pancake');
$haystack='Where are those pancakes??';
foreach($needles as $ndl){
if(strpos($haystack,$ndl)!==false){ echo "'$ndl': found<br>\n"; }
else{ echo "'$ndl' : not found<br>\n"; }
}
Another way of searching for multiple strings in one string, without using an array... This only tells you whether at least one match was found.
$haystack='Where are those pancakes??';
$match=preg_match('#(hose|fribb|pancake)#',$haystack);
//$match is now int(1)
Or, use preg_match_all to see how many matches there are, total.
$all_matches=preg_match_all('#(hose|fribb|pancake)#',$haystack,$results);
//all_matches is int(2). Note you also have $results, which stores which needles matched.
In that, the search term is a regular expression. () groups the terms together, and | means 'or'. # denotes the beginning and end of the pattern. Regexes can get pretty complicated quickly, but of course, they work! They are often avoided for performance reasons, but if you're testing multiple strings, this might be more efficient than they array looping method described above. I'm sure there are also other ways to do this.
strstr() / stristr() (the latter being case-insensitive)
if(strstr($string,$find)!==false){
//true
}
strpos() can do that.
if(strpos($string, $find) !== false)
. . .
Note that it may return 0, so do use the type-equals operator.
I am using the PHP in_array() function in order to authenticate (with sessions) if a user can access a particular page. For some reason, it is not working...
PHP PAGE
session_start();
require_once('../scripts/functions.php');
$role_auth = #$_SESSION['role_auth'];
access($role_auth, array(0,1,2,3,4));
access FUNCTION
function access($role_auth, $array){
if(!(in_array($role_auth, $array))){
header("Location: ../index.html");
}
}
If I insert print statements in the function, I can see that all of the correct values are being passed into the function. The problem is, if the function is called without a session variable set, for some reason it is considered as being in the array, and it authenticates.
Any ideas?
you may want to enable strict type checks by using:
in_array($role_auth, $array, true)
as what is likely happening is that $role_auth is being eval'd as false and that could match 0 in your in_array statement.
what you SHOULD be doing is this:
session_start();
require_once('../scripts/functions.php');
$role_auth = (isset($_SESSION['role_auth']))?$_SESSION['role_auth']:-1;
access($role_auth, array(0,1,2,3,4));
or something similiar. nothing good ever comes of using the # operator
I would check to see if $_SESSION['role_auth'] is actually set (with isset) instead of using # to suppress warnings (which is bad practice IMHO)
I think what's happening is that false == 0 ... so in_array returns true when nothing is in $role_auth because it sees it as 0 and 0 is in your array
$role_auth = #$_SESSION['role_auth'];
The # sign is suppressing any warnings you might get here, like index is not in array. How about something like this instead:
if(isset($_SESSION['role_auth']))
$role_auth = $_SESSION['role_auth'];
else
$role_auth = -1;//(or whatever an invalid role is)
In php, the number zero is considered equal to most non-numeric things, for example:
null == 0
false == 0
"" == 0
"asdf" == 0
You probably need to make sure that $_SESSION actually contains the 'role_auth' key beforehand and convert it to the appropriate type, also passing the $strict parameter to in_array, thus guaranteeing a type check as well as a value check (=== vs. ==). Removing zero from your array might also be a good idea.