PHP username validation - php

I am working on writing a PHP login system. I have everything that I need working, but I would like to verify that a username entered during the registration only contains alphanumeric characters. So how could I take a variable, say $username, and ensure that it contained only alphanumeric characters?

if(preg_match('/^\w{5,}$/', $username)) { // \w equals "[0-9A-Za-z_]"
// valid username, alphanumeric & longer than or equals 5 chars
}
OR
if(preg_match('/^[a-zA-Z0-9]{5,}$/', $username)) { // for english chars + numbers only
// valid username, alphanumeric & longer than or equals 5 chars
}

The Best way I recommend is this :-
$str = "";
function validate_username($str)
{
$allowed = array(".", "-", "_"); // you can add here more value, you want to allow.
if(ctype_alnum(str_replace($allowed, '', $str ))) {
return $str;
} else {
$str = "Invalid Username";
return $str;
}
}

If you don't care about the length, you can use:
if (ctype_alnum($username)) {
// Username is valid
}
http://www.php.net/manual/en/function.ctype-alnum.php

try this
function filterName ($name, $filter = "[^a-zA-Z0-9\-\_\.]"){
return preg_match("~" . $filter . "~iU", $name) ? false : true;
}
if ( !filterName ($name) ){
print "Not a valid name";
}

A little bit late but I am using the following function to test usernames or other types of alphanum-like strings. It tests alphanum chars only by default but you can add more characters such as . (dot), - (dash) or _ (underscore) to the whitelist.
It will also prevent consecutive chars for the chars specified as $more_chars.
function valid_alphanum_string($str, $more_chars = '') {
# check type
if (!is_string($str)) return false;
# handle allowed chars
if (mb_strlen($more_chars) > 0) {
# don't allow ^, ] and \ in allowed chars
$more_chars = str_replace(array('^', ']', '\\'), '', $more_chars);
# escape dash
$escaped_chars = strpos($more_chars, '-') !== false
? str_replace('-', '\-', $more_chars)
: $more_chars;
# allowed chars must be non-consecutive
for ($i=0; $i < mb_strlen($more_chars); $i++) {
$consecutive_test = preg_match('/[' . $more_chars[$i] . '][' . $escaped_chars . ']/', $str);
if ($consecutive_test === 1) return false;
}
# allowed chars shouldn't be at the start and the end of the string
if (strpos($more_chars, $str[0]) !== false) return false;
if (strpos($more_chars, $str[mb_strlen($str) - 1])) return false;
}
else $escaped_chars = $more_chars;
$result = preg_match('/^[a-zA-Z0-9' . $escaped_chars . ']{4,}$/', $str);
return $result === 1 ? true : false;
}

If you are allowing the basic alpha-numeric username, You can check alphanumeric value with a predefined template like this:
preg_match([[:alnum:]],$username)&&!preg_match([[:space:]],$username)
The second part returns false if the string contains any spaces.

Related

mask mail with Alternative words using php

Mentioned below is a dummy Email ID say,
abcdefghij#gmail.com
How to mask this email ID partially using PHP?
Output i need as
a*c*e*g*i*#gmail.com
I have tried the below code, But it not works for below requirement
$prop=3;
$domain = substr(strrchr($Member_Email, "#"), 1);
$mailname=str_replace($domain,'',$Member_Email);
$name_l=strlen($mailname);
$domain_l=strlen($domain);
for($i=0;$i<=$name_l/$prop-1;$i++)
{
$start.='*';
}
for($i=0;$i<=$domain_l/$prop-1;$i++)
{
$end.='*';
}
$MaskMail = substr_replace($mailname, $start,2, $name_l/$prop).substr_replace($domain, $end, 2, $domain_l/$prop);
Give a try like this.
$delimeter = '#';
$mail_id = 'abcdefghij#gmail.com';
$domain = substr(strrchr($mail_id, $delimeter), 1);
$user_id = substr($mail_id,0,strpos($mail_id, $delimeter));
$string_array = str_split($user_id);
$partial_id = NULL;
foreach($string_array as $key => $val){
if($key % 2 == 0){
$partial_id .=$val;
}else{
$partial_id .='*' ;
}
}
echo $partial_id.$delimeter.$domain;
Here's a no loop approach to replace every second character of an email username with a mask.
Custom PHP function using native functions split, preg_replace with regex /(.)./, and implode:
echo email_mask('abcdefghi#gmail.com');
// a*c*e*g*i*k*#gmail.com
function email_mask($email) {
list($email_username, $email_domain) = split('#', $email);
$masked_email_username = preg_replace('/(.)./', "$1*", $email_username);
return implode('#', array($masked_email_username, $email_domain));
}
Regex Explanation:
The regular expression starts at the beginning of the string, matches 2 characters and captures the first of those two, replaces the match with the first character followed by an asterisk *. preg_replace repeats this throughout the remaining string until it can no longer match a pair of characters.
$mail='abcdefghij#gmail.com';
$mail_first=explode('#',$mail);
$arr=str_split($mail_first[0]);
$mask=array();
for($i=0;$i<count($arr);$i++) {
if($i%2!=0) {
$arr[$i]='*';
}
$mask[]=$arr[$i];
}
$mask=join($mask).'#'.$mail_first[1];
echo $mask;
Result is :
a*c*e*g*i*#gmail.com
Does it need to have that many asterisks?
It's so hard to read that way.
I will suggest you keep things simple.
Maybe something like this is enough
https://github.com/fedmich/PHP_Codes/blob/master/mask_email.php
Masks an email to show first 3 characters and then the last character before the # sign
ABCDEFZ#gmail.com becomes
A*****Z#gmail.com
Here is the full code that is also in that Github link
function mask_email( $email ) {
/*
Author: Fed
Simple way of masking emails
*/
$char_shown = 3;
$mail_parts = explode("#", $email);
$username = $mail_parts[0];
$len = strlen( $username );
if( $len <= $char_shown ){
return implode("#", $mail_parts );
}
//Logic: show asterisk in middle, but also show the last character before #
$mail_parts[0] = substr( $username, 0 , $char_shown )
. str_repeat("*", $len - $char_shown - 1 )
. substr( $username, $len - $char_shown + 2 , 1 )
;
return implode("#", $mail_parts );
}

how to detect some "$#%#*&$!" type characters from the String in php?

I have an Username input filed . if i want to detect some characters which is in an array like this $array = array('#','%','^') so Is there any built in function in php for that ? which will Take an Array and return true or false .
The easiest way would be:
if (str_replace($array, '', $username) != $username) {
do something;
}
You can write your own function of course:
function contains_unallowed($array = ['#', '%', '^']) {
return str_replace($array, '', $username) != $username;
}
It takes an array of characters as optional parameter and returns true or false. If it doesn't work, please replace the square braces [] with array().
array_intersect may help you - e.g.
$array = array('#','%','^');
if(array_intersect(str_split($username), $array)) {
echo "Found";
} else {
echo "Not Found";
}

How i can check with preg_match contain my string any digits or not?

I need to check in a string of digits, ie all other characters such as ~; & * ^ # & ^ Should not fall under check. I need it to form validation. Now i use that construction:
return ( ! preg_match("/^([0-9])+$/i", $str)) ? FALSE : TRUE;
I have a form for edeiting firstname and lastname of users. Also when someone try to add name with characters somth like that: "kickman!##$%^&())))(&^%$##$%" my form should complete validation without errors. But if i have there any digit i should get an error, somth like : "123kickman!##$%^&())))(&^%$##$%".
Try this:
if (!preg_match("#^[a-zA-Z0-9]+$#", $text)){
echo 'String also contains other characters.';
} else {
echo 'String only contains numbers and letters.';
}
or this:
function countDigits($str)
{
return preg_match_all( "/[0-9]/", $str );
}
If you are trying to see if all characters are digits, just create a function and pass the string to it:
$x = match("01234");
echo $x."<br>";
$x = match("0$#21234");
echo $x."<br>";
function match($str)
{
return ( ! preg_match("/^([0-9])+$/i", $str)) ? 0 : 1;
}
How about:
Edit according to question update:
if (preg_match('/\d/', $string)) {
echo "KO, at least one digit\n";
} else {
echo "OK, no digits found\n";
}
Or, in a function:
return !preg_match('/d/', $string);

How to allow underscore and dash with ctype_alnum()?

How can I add the exception of _ and - as valid characters when using ctype_alnum() ?
I have the following code:
if ( ctype_alnum ($username) ) {
return TRUE;
} elseif (!ctype_alnum ($username)) {
$this->form_validation->set_message(
'_check_username',
'Invalid username! Alphanumerics only.'
);
return FALSE;
}
Since ctype_alnum only validates alpha numeric character,
Try this:
$sUser = 'my_username01';
$aValid = array('-', '_');
if(!ctype_alnum(str_replace($aValid, '', $sUser))) {
echo 'Your username is not properly formatted.';
}
Use preg_match instead, maybe?
if(preg_match("/^[a-zA-Z0-9_\-]+$/", $username)) {
return true;
} else {
$this->form_validation->set_message('_check_username', 'Invalid username! Alphanumerics only.');
}
Here is how to use ctype_alnum AND have exceptions, in this case I also allow hyphens ( OR statement).
$oldString = $input_code;
$newString = '';
$strLen = mb_strlen($oldString);
for ($x = 0; $x < $strLen; $x++)
{
$singleChar = mb_substr($oldString, $x, 1);
if (ctype_alnum($singleChar) OR ($singleChar == '-'))
{
$newString = $newString . $singleChar;
}
}
$input_code = strtoupper($newString);
The regex equivalent is very brief and easy to read.
~^[\w-]+$~ This pattern requires the whole string to be comprised of one or more letters, numbers, underscores, or hyphens.
Regex allows you to skip the data preparation step and directly access the evaluation -- resulting in cleaner, leaner, more direct, professional-looking code.
if (preg_match('~^[\w-]+$~', $username)) {
return true;
} else {
$this->form_validation->set_message(
'_check_username',
'Invalid username! Alphanumerics, underscores, and hyphens only.'
);
return false;
}

How to check if a string is base64 valid in PHP

I have a string and want to test using PHP if it's a valid base64 encoded or not.
I realise that this is an old topic, but using the strict parameter isn't necessarily going to help.
Running base64_decode on a string such as "I am not base 64 encoded" will not return false.
If however you try decoding the string with strict and re-encode it with base64_encode, you can compare the result with the original data to determine if it's a valid bas64 encoded value:
if ( base64_encode(base64_decode($data, true)) === $data){
echo '$data is valid';
} else {
echo '$data is NOT valid';
}
You can use this function:
function is_base64($s)
{
return (bool) preg_match('/^[a-zA-Z0-9\/\r\n+]*={0,2}$/', $s);
}
Just for strings, you could use this function, that checks several base64 properties before returning true:
function is_base64($s){
// Check if there are valid base64 characters
if (!preg_match('/^[a-zA-Z0-9\/\r\n+]*={0,2}$/', $s)) return false;
// Decode the string in strict mode and check the results
$decoded = base64_decode($s, true);
if(false === $decoded) return false;
// Encode the string again
if(base64_encode($decoded) != $s) return false;
return true;
}
This code should work, as the decode function returns FALSE if the string is not valid:
if (base64_decode($mystring, true)) {
// is valid
} else {
// not valid
}
You can read more about the base64_decode function in the documentation.
I think the only way to do that is to do a base64_decode() with the $strict parameter set to true, and see whether it returns false.
I write this method is working perfectly on my projects. When you pass the base64 Image to this method, If it valid return true else return false. Let's try and let me know any wrong. I will edit and learn in the feature.
/**
* #param $str
* #return bool
*/
private function isValid64base($str){
if (base64_decode($str, true) !== false){
return true;
} else {
return false;
}
}
This is a really old question, but I found the following approach to be practically bullet proof. It also takes into account those weird strings with invalid characters that would cause an exception when validating.
public static function isBase64Encoded($str)
{
try
{
$decoded = base64_decode($str, true);
if ( base64_encode($decoded) === $str ) {
return true;
}
else {
return false;
}
}
catch(Exception $e)
{
// If exception is caught, then it is not a base64 encoded string
return false;
}
}
I got the idea from this page and adapted it to PHP.
I tried the following:
base64 decode the string with strict parameter set to true.
base64 encode the result of previous step. if the result is not same as the original string, then original string is not base64 encoded
if the result is same as previous string, then check if the decoded string contains printable characters. I used the php function ctype_print to check for non printable characters. The function returns false if the input string contains one or more non printable characters.
The following code implements the above steps:
public function IsBase64($data) {
$decoded_data = base64_decode($data, true);
$encoded_data = base64_encode($decoded_data);
if ($encoded_data != $data) return false;
else if (!ctype_print($decoded_data)) return false;
return true;
}
The above code will may return unexpected results. For e.g for the string "json" it will return false. "json" may be a valid base64 encoded string since the number of characters it has is a multiple of 4 and all characters are in the allowed range for base64 encoded strings. It seems we must know the range of allowed characters of the original string and then check if the decoded data has those characters.
Alright guys... finally I have found a bullet proof solution for this problem. Use this below function to check if the string is base64 encoded or not -
private function is_base64_encoded($str) {
$decoded_str = base64_decode($str);
$Str1 = preg_replace('/[\x00-\x1F\x7F-\xFF]/', '', $decoded_str);
if ($Str1!=$decoded_str || $Str1 == '') {
return false;
}
return true;
}
if u are doing api calls using js for image/file upload to the back end this might help
function is_base64_string($string) //check base 64 encode
{
// Check if there is no invalid character in string
if (!preg_match('/^(?:[data]{4}:(text|image|application)\/[a-z]*)/', $string)){
return false;
}else{
return true;
}
}
Old topic, but I've found this function and It's working:
function checkBase64Encoded($encodedString) {
$length = strlen($encodedString);
// Check every character.
for ($i = 0; $i < $length; ++$i) {
$c = $encodedString[$i];
if (
($c < '0' || $c > '9')
&& ($c < 'a' || $c > 'z')
&& ($c < 'A' || $c > 'Z')
&& ($c != '+')
&& ($c != '/')
&& ($c != '=')
) {
// Bad character found.
return false;
}
}
// Only good characters found.
return true;
}
I code a solution to validate images checking the sintaxy
$image = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAMAAABEpIrGAAABfVBMVEUAAAAxMhQAoIpFLCTimAE2IRs0IBodEg4OJyEAnYcAmoUAjnoALyn5rgNJLydEKyM5lWFFLCTuogI/JyBAKCHZnQoAlIAAkn48JR6fYgCIVACDUACPbAsAW06IWgAaDw0jFQscEQ4Am4XIfQDGewDhlwHelQEAi3gAe2oAd2cAXE8gFBAeEg8AVEgAtJwAsZn/vhMAuJ//xyMAu6BfQTf/wxv9wRlcPjVhQjj/vBBdQDb/xR9oSD1iRDlWOjH9xSL/uQr+twhkRTplRjxZPDPZpydILydAQD+pezNjRTNQNS3tuCZGLSX4sQn/tQTllgDhkgAArZUAqJFvTUD/wRgGtpp2m0aPaTl+azOIcjGkhS6OaS1ONCvNnirHmSrnsifHnSfFjyemfCfcqSa/jyLwuR/ptB/MmRxiPhnpqRX1sxHzqwnCfgb+tQTYjALnmQH2qQDzpQDejgAnsYQnsYNwTkBlRTtfQi9eQS+1kCy2kSuFYSuEYSvkpRfrqxQPeVhkAAAALnRSTlMADPz0qnhzNBPry5kH/vr36ubKxLy4sKmifVVNQT84Ih4Y2aWloqKMgHdJPDwse8ZSvQAAAbVJREFUOMuV0uVzggAYx3Gsbca6u3vDqSDqBigD25nrLrvX+bfvMSeId9vnBXD3+97zCuQ/ZhUDvV1dvQOKWfFdIWOZHfDMyhRi+4ibZHZLwS5Dukea97YzzAQFYEgTdtYm3DtkhAUKkmFI0mTCCFmH8ICbsEBRhmEWwi080U+xBNwApZlgqX7+rummWJcLEkAQLhdLdWt4wbSXOqX1Hu784uKc8+jpU8o7zQva7RSnb8BR9nZesGF/oelLT2X1XNL0q31dcOGDPnwKO7eBMxw+pD8FF2a8N9vcyfttKbh9O+HwG+8MLxiL3+FXDsc9Du4djiv8Lj7GC0bTMTx6dGzEgfH4KIrH0qO8YDyQjESMvyLJwDjCs5DaKsvlzOV3ah4RkFcCM+wlckRoymcG107ntRn4ppAmSzar9Tvh830lrFbbItJM0meDBcCzT4KIFfLOzB7IdMphFzUxWMjnC4MToqNkbWVY1RPw+wM9quHVSY1gnhyShlCd4aHo9xcfDTptSKnebPxjh0Kooewgmz2ofKFStaS+z2l1Nfv79c+gqlaog6io4HI1UKItKKuBVNuCFPmDH12fd4lDaGbkAAAAAElFTkSuQmCC';
$allowedExtensions = ['png', 'jpg', 'jpeg'];
// check if the data is empty
if (empty($image)) {
echo "Empty data";
}
// check base64 format
$explode = explode(',', $image);
if(count($explode) !== 2){
echo "This string isn't sintaxed as base64";
}
//https://stackoverflow.com/a/11154248/4830771
if (!preg_match('%^[a-zA-Z0-9/+]*={0,2}$%', $explode[1])) {
echo "This string isn't sintaxed as base64";
}
// check if type is allowed
$format = str_replace(
['data:image/', ';', 'base64'],
['', '', '',],
$explode[0]
);
if (!in_array($format, $allowedExtensions)) {
echo "Image type isn't allowed";
}
echo "This image is base64";
But a safe way is using Intervention
use Intervention\Image\ImageManagerStatic;
try {
ImageManagerStatic::make($value);
return true;
} catch (Exception $e) {
return false;
}
You can just send the string through base64_decode (with $strict set to TRUE), it will return FALSE if the input is invalid.
You can also use f.i. regular expressions see whether the string contains any characters outside the base64 alphabet, and check whether it contains the right amount of padding at the end (= characters). But just using base64_decode is much easier, and there shouldn't be a risk of a malformed string causing any harm.
base64_decode() should return false if your base64 encoded data is not valid.
i know that i resort a very old question, and i tried all of the methods proposed; i finally end up with this regex that cover almost all of my cases:
$decoded = base64_decode($string, true);
if (0 < preg_match('/((?![[:graph:]])(?!\s)(?!\p{L}))./', $decoded, $matched)) return false;
basically i check for every character that is not printable (:graph:) is not a space or tab (\s) and is not a unicode letter (all accent ex: èéùìà etc.)
i still get false positive with this chars: £§° but i never use them in a string and for me is perfectly fine to invalidate them.
I aggregate this check with the function proposed by #merlucin
so the result:
function is_base64($s)
{
// Check if there are valid base64 characters
if (!preg_match('/^[a-zA-Z0-9\/\r\n+]*={0,2}$/', $s)) return false;
// Decode the string in strict mode and check the results
$decoded = base64_decode($s, true);
if(false === $decoded) return false;
// if string returned contains not printable chars
if (0 < preg_match('/((?![[:graph:]])(?!\s)(?!\p{L}))./', $decoded, $matched)) return false;
// Encode the string again
if(base64_encode($decoded) != $s) return false;
return true;
}
MOST ANSWERS HERE ARE NOT RELIABLE
In fact, there is no reliable answer, as many non-base64-encoded text will be readable as base64-encoded, so there's no default way to know for sure.
Further, it's worth noting that base64_decode will decode many invalid strings
For exmaple, and is not valid base64 encoding, but base64_decode WILL decode it. As jw specifically. (I learned this the hard way)
That said, your most reliable method is, if you control the input, to add an identifier to the string after you encode it that is unique and not base64, and include it along with other checks. It's not bullet-proof, but it's a lot more bullet resistant than any other solution I've seen. For example:
function my_base64_encode($string){
$prefix = 'z64ENCODEDz_';
$suffix = '_z64ENCODEDz';
return $prefix . base64_encode($string) . $suffix;
}
function my_base64_decode($string){
$prefix = 'z64ENCODEDz_';
$suffix = '_z64ENCODEDz';
if (substr($string, 0, strlen($prefix)) == $prefix) {
$string = substr($string, strlen($prefix));
}
if (substr($string, (0-(strlen($suffix)))) == $suffix) {
$string = substr($string, 0, (0-(strlen($suffix))));
}
return base64_decode($string);
}
function is_my_base64_encoded($string){
$prefix = 'z64ENCODEDz_';
$suffix = '_z64ENCODEDz';
if (strpos($string, 0, 12) == $prefix && strpos($string, -1, 12) == $suffix && my_base64_encode(my_base64_decode($string)) == $string && strlen($string)%4 == 0){
return true;
} else {
return false;
}
}
I have found my solution by accident.
For those who use base64_encode(base64_decode('xxx')) to check may found that some time it is not able to check for string like test, 5555.
If the invalid base 64 string was base64_decode() without return false, it will be dead when you try to json_encode() anyway. This because the decoded string is invalid.
So, I use this method to check for valid base 64 encoded string.
Here is the code.
/**
* Check if the given string is valid base 64 encoded.
*
* #param string $string The string to check.
* #return bool Return `true` if valid, `false` for otherwise.
*/
function isBase64Encoded($string): bool
{
if (!is_string($string)) {
// if check value is not string.
// base64_decode require this argument to be string, if not then just return `false`.
// don't use type hint because `false` value will be converted to empty string.
return false;
}
$decoded = base64_decode($string, true);
if (false === $decoded) {
return false;
}
if (json_encode([$decoded]) === false) {
return false;
}
return true;
}// isBase64Encoded
And here is tests code.
// each tests value must be 'original string' => 'base 64 encoded string'
$testValues = [
555 => 'NTU1',
5555 => 'NTU1NQ==',
'hello' => 'aGVsbG8=',
'สวัสดี' => '4Liq4Lin4Lix4Liq4LiU4Li1',
'test' => 'dGVzdA==',
];
foreach ($testValues as $invalid => $valid) {
if (isBase64Encoded($invalid) === false) {
echo '<strong>' . $invalid . '</strong> is invalid base 64<br>';
} else {
echo '<strong style="color:red;">Error:</strong>';
echo '<strong>' . $invalid . '</strong> should not be valid base 64<br>';
}
if (isBase64Encoded($valid) === true) {
echo '<strong>' . $valid . '</strong> is valid base 64<br>';
} else {
echo '<strong style="color:red;">Error:</strong>';
echo '<strong>' . $valid . '</strong> should not be invalid base 64<br>';
}
echo '<br>';
}
Tests result:
555 is invalid base 64 NTU1 is valid base 64
5555 is invalid base 64 NTU1NQ== is valid base 64
hello is invalid base 64 aGVsbG8= is valid base 64
สวัสดี is invalid base 64 4Liq4Lin4Lix4Liq4LiU4Li1 is valid base
64
test is invalid base 64 dGVzdA== is valid base 64
To validate without errors that someone sends a clipped base64 or that it is not an image, use this function to check the base64 and then if it is really an image
function check_base64_image($base64) {
try {
if (base64_encode(base64_decode($base64, true)) === $base64) {
$img = imagecreatefromstring(base64_decode($base64, true));
if (!$img) {
return false;
}
imagepng($img, 'tmp.png');
$info = getimagesize('tmp.png');
unlink('tmp.png');
if ($info[0] > 0 && $info[1] > 0 && $info['mime']) {
return true;
}
}
} catch (Exception $ex) {
return false;
} }
I am using this approach. It expects the last 2 characters to be ==
substr($buff, -2, 1) == '=' && substr($buff, -1, 1) == '=')
Update: I ended up doing another check if the one above fails
base64_decode($buff, true)
If data is not valid base64 then function base64_decode($string, true) will return FALSE.

Categories