PHP Trim function not removing whitespaces - php

I'm doing some tests with learning purpose. I have a PHP script in which I used some functions to see how they work:
First I used isset to make sure a var exist
Then empty to make sure if a var has some value
Finally I used trim to remove whitespaces
After some testing I realized that trim function is not working properly.
For example I can still write whitespaceCHARwhitespace, then I used strlen function and I get a 3 as a result. What's wrong with my script?
Btw I would like to know how acceptable is this form validation I would like to avoid some sqlinjection.
Thanks in advance.
<span><?php echo $msg;?></span>
<form method="POST">
<label for="name" class="white-headers">NAME</label>
<input type="text" name="name" id="name" class="form-control">
<label for="last_name" class="white-headers">LAST NAME</label>
<input type="text" name="last_name" id="last_name" class="form-control">
<input type="submit" class="btn btn-success" name="submit">
</form>
$msg="";
if(isset($_POST["submit"])){
$name = $_POST["name"];
$last_name = $_POST["last_name"];
if(!empty(trim($name)) && !empty(trim($last_name))){
$name_len=strlen($name);
$last_name_len=strlen($name);
$msg="<div class='alert alert-success'>
both fields are set and have some value name =".$name." with ".$name_len." chars and last_name =".$last_name."
with ".$last_name_len. "chars</div>";
}
else{
$msg="<div class='alert alert-danger'>
both fields are set but one or both are empty name =".$name." and last_name =".$last_name."</div>";
}
}

The only times you're using trim there are when you check whether or not there's anything left after you trim the variables:
if(!empty(trim($name)) && !empty(trim($last_name))) {
That doesn't affect $name and $last_name.
trim returns a string with the whitespace removed, but it doesn't change the value of the variable given as an argument. If you want those to be trimmed for later use in your code, you need to set them to their trimmed values, like $name = trim($name), etc.
In your case, you could probably trim them when you set them from $_POST initially.
$name = trim($_POST["name"]);
$last_name = trim($_POST["last_name"]);
Then you can check if there's anything left more simply:
if ($name && $last_name) {
empty isn't necessary because you know they're set, and zero-length strings evaluate to false.

As specified in the documentation, trim only removes whitespaces at the beginning or at the end of a string. Whitespaces in the middle are not affected (using _ to mark a whitespace):
__string will become string
string__ will become string
s_t_r_i_n_g will remain s_t_r_i_n_g
Plus, as pointed in Don't Panic's answer, you are checking the strings after the trim, not its return value.
About the form validation: if you want to clean your inputs before using them in your application, simply trimming them isn't enough. There are many ways to sanitize inputs, every framework offers some options, but since you specifically spoke of sqlinjections, my suggestion is to start by reading PHP's mysqli.real_escape_string

Related

PHP function echoes unexpected HTML value

I have a piece of php code inside html tag which is supposed to change the tag's style in accordance with the contents of the URL.
There is an html login form which looks like this:
<form class="userdata" action="login.php" method="post">
<input type="text" name="email" placeholder="E-mail" <?php fillin('email'); enlight_unfilled('email');?>><br>
<input type="password" name="pwd" placeholder="Password"><br>
<button type="submit" name="login-submit">Login</button>
</form>
Here are the functions fillin and enlight_unfilled:
<?php
function fillin($key) {
if (isset($_GET[$key])) echo "value=".$_GET[$key];
else echo NULL;
}
function enlight_unfilled($key) {
if (isset($_GET['error']))
if (isset($_GET[$key]) and $_GET[$key] !== "") echo NULL;
else echo "style='border-color: red'";
else echo NULL;
}
?>
If I only apply one of the functions within the tag, they both do what they are expected to – either save the email in the field if it has been already typed in or enlighten the email field if it has been left empty. But if I apply them together, when the field is empty, php assigns the field value 'style='border-color:. I also tried to use functions like print and printf, but the result is the same:
I am a beginner at php coding and mixing it with html, so the question may appear to be dumb, but I did not manage to find any sort of a solution to this issue, so thanks for help and patience in advance!
It looks like you don't properly encase value in quotes, so it just renders the 'style='border-color:.
Let's assume that $_GET[$key] has a value of hello#hello.com. What your PHP & HTML renders is the following:
value=hello#hello.com
See the problem? There are no quotes. That's why the renderer goes forward searching for a valid value. To fix the issue you must add quotes around your $_GET[$key] in the fillin function. Something like this should do the job:
if (isset($_GET[$key])) echo "value='".$_GET[$key] . "'";
It works when ran alone because it reaches the end > and just assumes the value to be hello#hello.com

Using preg_match to detect special characters not working

I'm trying to stop users from being able to put any characters in the username box apart from a-z(A-Z), 0-9 and spaces. Here's the HTML to start off with:
<form action='register.php' method='post'>
<div class="field-wrap">
<label>
Username<span class="req">*</span>
</label>
<input type="text" name="username" required autocomplete="nope" />
</div>
<div class="field-wrap">
<label>
Email Address<span class="req">*</span>
</label>
<input type="email" name="email" required autocomplete="nope" />
</div>
<div class="field-wrap">
<label>
Set A Password<span class="req">*</span>
</label>
<input type="password" name="password" required autocomplete="nope" />
</div>
<button type="submit" class="button button-block" />
REGISTER</button>
</form>
Pretty self explanatory, right?
Here's the PHP on register.php:
$username = $_POST['username'];
$password = $_POST['password'];
if(preg_match('/[^a-zA-Z0-9[:space:]]+$/', $username)){
//pass
}
else{
$message = "Your username may only contain letters, numbers and spaces";
$_SESSION['error'] = $message;
header("Location:auth.php");
}
// do all the other stuff like add user to database etc
header("Location:index.php");
When I try to create a user with a username such as "test##!?*^'/"()", the preg_match function doesn't work. Instead of redirecting back to the login/register page (auth.php), it adds the user to the database and redirects me to the homepage (index.php).
I have also tried /^[a-z0-9 .-]+$/i for the parameters in preg_match but that doesn't work either.
Just a side note, I'm not using this for security reasons, I use stripslashes and mysql_real_escape_string AFTER the preg_match.
Any ideas, or a better way to only allow a-z(A-Z), 0-9 and spaces? I have been trying to solve this for hours now and to no avail. Thanks!
Use this preg_match code to only allow Letters (including uppercase), Numbers, and Spaces:
$Passed = 0;
$username = $_POST['username'];
$password = $_POST['password'];
if(!preg_match("/[^a-z0-9 ]/i", $username)){
$Passed = 1;
//stop header location here.
}
else{
$message = "Your username may only contain letters, numbers and spaces";
$_SESSION['error'] = $message;
header("Location:auth.php");
}
if ($Passed == 0){
header("Location:index.php");
}
About your original question:
This regular expression doesn't work properly due to caret (^) position:
/[^a-zA-Z0-9[:space:]]+$/
↑
In this position, caret negate following pattern inside square brackets. In fact, your pattern search for any not a-zA-Z0-9....
To match a string with only alphanumeric characters and spaces you have to move the caret at start of pattern. In this position the caret means “start of string”:
/^[a-zA-Z0-9[:space:]]+$/
↑
But you can also simplify your pattern, and replace [:space:] with a real blank space ([:space:] and \s match also newline, tab, etc...1). Try this regular expression:
/^[A-z0-9 ]+$/
Your script still not working:
The solution is die().
If the string doesn't match the pattern, you execute this code:
$message = "Your username may only contain letters, numbers and spaces";
$_SESSION['error'] = $message;
header("Location:auth.php");
Sending headers doesn't interrupt the script, so the remaining code is executed and the last sent header (Location:index.php) is loaded.
Force script termination after sending header:
header("Location:auth.php");
die();
1 From PHP documentation: “The "whitespace" characters are HT (9), LF (10), FF (12), CR (13), and space (32). However, if locale-specific matching is happening, characters with code points in the range 128-255 may also be considered as whitespace characters, for instance, NBSP (A0).”
Change your regex to:
/^[\d\w\s]+?$/
You can easy test with http://regexr.com/
Solved this now thanks to Ghulam... his logic was great although the code he wrote was wrong so I've updated it.
Also updated my answer with fusion3k's die(); approach just to make sure the code is completely finished.
$username = $_POST['username'];
$password = $_POST['password'];
$passed = 0;
if(preg_match("/^[A-Za-z0-9 ]+?$/", $username)){
//pass
$passed = 1;
}
if($passed == 0){
$message = "Your username may only contain letters, numbers and spaces";
$_SESSION['error'] = $message;
header("Location:auth.php");
die();
}
if($passed == 1){
//add user to database
header("Location:index.php");
}
We set $passed as 0 to begin with.
If $username only contains letters a-z(A-Z), 0-9 and spaces then we set $passed to 1 as it has passed the preg_match check.
If $username contains any other characters apart from these, (#, %, ^ etc) then we leave the $passed variable as 0.
If $passed is 0 then the username is invalid, so return the user to the register/login page (auth.php) and give them an error message.
If $passed is 1 then the username is valid so we can add the user to the database and return them to the homepage.
die(); is used to make sure the code stops reading/running after the header redirect has been sent. The page might redirect but the user could still be added to the database!
This is a good example for a short security tutorial.
The original code presented by OP allows access if $username does not contains characters from list, at least one of them:
if(preg_match('/[^a-zA-Z0-9[:space:]]+$/', $username)){
//pass
}
The updated code posted here is doing the job:
if(preg_match("/^[A-Za-z0-9 ]+?$/", $username)){
//pass
$passed = 1;
}
However, correctly is to refuse access if $username contains ANY characters outside from the allowed set:
if(!preg_match("/[^A-Za-z0-9 ]/", $username)){
//allows access
$passed = 1;
} else {
//refuse access
$passed = 0;
}
This will cover and refuse anything outside from the allowed character set.
The caret sign "^", usually is a metacharacter that assert start of subject (or line, in multiline mode), like in /^(A sentence).*$/, but when used in a character class, like [^abc] it means "NOT the characters inside the brackets" (reference).

Date entry for first_name, lastname, and job title should be in camel case format even if the user enters all capitalized letters

So this is my code for the first_name. I have no clue why it does not work whenever I add an entry.
First Name: <input type="text" name="first_name" value="<?php function convertString($first_name){
$first_name=htmlentities(strip_tags($first_name));
$lowercaseFName = strtolower($first_name);
$ucFName = ucwords($lowercaseFName);
return $ucFName;} ?>"/> // I changed it with echo but nothing changed.
My code doesn't change the format of the text.I tried inputting in all caps and it will show as is. Am I missing something or doing it wrong?
The inputted text if all in capital must still be shown as Camel Case format in the table, like this:
First Name: MARIA YLONA (in the form)
First Name: Maria Ylona (in the table) - this is another .php file for viewing of the data entries
Seeing you didn't post your html form or how it's used, am submitting the following as a successful piece of code and using !empty() against a POST array with form tags and an isset() for the submit input.
Btw, functions and variables assignments should be used seperately than in inputs/form elements.
Create a function, then pass it inside the input with the parameter.
<?php
function convertString($first_name){
$first_name=htmlentities(strip_tags($first_name));
$lowercaseFName = strtolower($first_name);
$ucFName = ucwords($lowercaseFName);
return $ucFName;
}
if(isset($_POST['submit'])){
if(!empty($_POST['first_name'])){
$first_name = $_POST['first_name'];
}
}
// here initialize $first_name to something meaningful
?>
<form method="post">
First Name: <input type="text" name="first_name" value="<?php echo(convertString($first_name)) ?>"/>
<input type="submit" name="submit" value="Submit">
</form>
Footnotes:
In regards to what Marc mentioned about McDonald's -> mcdonald's -> Mcdonald's and my MacDonald in comments...
Consult the following here on Stack which may prove to be useful:
Given upper case names transform to Proper Case, handling "O'Hara", "McDonald" "van der Sloot" etc
Data Cleanup, post conversion from ALLCAPS to Title Case
You mention the use of a database, but haven't posted relative code and would be beyond the scope of the question.
To clarify what aynber meant in the comments:
<?php
function convertString($first_name){
$first_name=htmlentities(strip_tags($first_name));
$lowercaseFName = strtolower($first_name);
$ucFName = ucwords($lowercaseFName);
return $ucFName;
}
// here initialize $first_name to something meaningful
?>
First Name: <input type="text" name="first_name" value="<?php echo(convertString($first_name)) ?>"/>

How $_POST variable/operation is managed in PHP?

When I do something like:
foreach($_POST as $post_key => $post_value){
/* Any code here*/
}
So, something like:
$varSomething = $_POST['anything'];
$varSomethingElse = $_POST['somethingElse'];
Is it possible? When I catch a $_POST[' '], isn't that variable already consumed?
The main reason why I would do this is because after a form submission, I want to check wether some items of some type got certain value or not.
Is there aything else more appropiate?
Firstly the html code don't use variable types, for example, if you have
<input id="check" type="checkbox" />
without a established value, after that you have echo $_POST['chek'], you could think that the result would be a boolean value (false or true), but the correct result will be "on" or "off", you can coding this case. Also, if you want to know the type of your data, you can use regular expression on server side, for example:
<input type="text" id="number" value="1350" />
.....
PHP code
$data = $_POST['number'];
$regularExpression = "/^\d{1,10}$/";
if (preg_match($regularExpression, $data)) {
echo "Is numeric";
}
Good lucky.
if you don't know what is the name of element which is sending the data. the first method is ohk . but if know the name like password or username you can use second one
in html
<input type="password" name ="password" />
in php
$pass_recvd=$_POST['password'];
there is no way to check the type i.e. text/password/checkbox/select etc. you have to do it on client side BEST WAY IS USING Jquery
if you wanna check whether a variable is set or not simple check by using isset method
if( isset($_POST['someVariableName'])) {}else{}

Prevent empty form input array from being posted?

Sorry if this has been answered somewhere; I'm not quite sure how to phrase the problem to even look for help.
Anyway, I have a form with three text input boxes, where the user will input three song titles. I have simple PHP set up to treat those input boxes as an array (because I may want, say, 100 song titles in the future) and write the song titles to another document.
<form method="post">
<input type="text" name="songs[]" value="" />
<input type="text" name="songs[]" value="" />
<input type="text" name="songs[]" value="" />
<button type="submit" name="submit" value="submit">Submit</button>
</form>
<?php
if (isset($_POST['submit'])) {
$open = fopen("test.html", "w");
if(empty($_POST['songs'])) { }
else {
$songs = $_POST['songs'];
foreach($songs as $song) {
fwrite($open, $song."<br />");
};
};
};
?>
This correctly writes the song titles to an external file. However, even when the input boxes are empty, the external file will still be written to (just with the <br />'s). I'd assumed that the if statement would ensure nothing would happen if the boxes were blank, but that's obviously not the case.
I guess the array's not really empty like I thought it was, but I'm not really sure what implications that comes with. Any idea what I'm doing wrong?
(And again, I am clueless when it comes to PHP, so forgive me if this has been answered a million times before, if I described it horribly, etc.)
you should check each entry:
<?php
if (isset($_POST['submit'])) {
$open = fopen("test.html", "w");
foreach($_POST['songs'] as $song) {
if(!empty($song)) {
fwrite($open, $song."<br />");
};
};
};
?>
Indeed $_POST['songs'] is not an empty array, it's an array of 3 empty strings.
You can use the following to clear out all the empty values:
$song_titles = array_filter($_POST['songs'], function($title) {return (bool) trim($title);});
You could also put some other checks into that callback function (whitelist only alphanumerics and some other characters (spaces, dashes etc)).
If you have a version of PHP older than 5.3 you'll have to define the callback function separately, see http://us2.php.net/manual/en/function.array-filter.php

Categories