regex to check for a valid regex pattern in php - php

I am attempting to write a validation class in php and have hit a snag. I am using the following code to check a value against a defined regex pattern but when I try to run the script I receive an error message saying:
"Warning: preg_match() [function.preg-match]: Empty regular expression in C:\wamp\www\valid\Class.Validate.php on line 109"
Can anyone spot my mistake ?
public function is_regex($var, $expression, $msg)
{
if (trim($var) <> "") {
$Valid = (bool)preg_match($expression, $var);
if ($Valid == false) {
return $msg;
}
}
}
and I am using this to call the function
array('Type'=>'Regex','Var'=>$_POST['test'], 'Expression'=>'[A-Za-z]{1,20}$','Msg'=>'Expression does not match')

As far as I see, you need to enclose regexp into enclosure characters, for example |
so your checking array will be like
array('Type'=>'Regex','Var'=>$_POST['test'], 'Expression'=>'|[A-Za-z]{1,20}$|','Msg'=>'Expression does not match')
You can also define character in function, but in this case if you'll have this character in regexp, you'll need to escape it

Related

PHPs strpos does not work as intended with double quoted string

I'm using the following code to return true or false if a string contains a substring in PHP 8.0.
<?php
$username = "mothertrucker"; // This username should NOT be allowed
$banlistFile = file_get_contents("banlist.txt"); //Contains the word "trucker" in it
$banlist = explode("\n", $banlistFile); // Splits $banlistFile into an array, split by line
if (contains($username, $banlist)) {
echo "Username is not allowed!";
} else {
echo "Username is allowed";
}
function contains($str, array $arr)
{
foreach($arr as $a) { // For each word in the banlist
if (stripos($str, $a) !== false) { // If I change $a to 'trucker', it works. "trucker" does not
return true;
}
}
return false;
}
?>
This is to detect if an inappropriate word is used when creating a username. So for example, if someone enters the username "mothertrucker", and "trucker" is included in the ban list, I want it to deny it.
Right now with this code, If I just type in the word "trucker" as a username, it is found and blocks it. Cool. However if there's more to the string than just "trucker", it doesn't detect it. So the username "mothertrucker" is allowed.
I discovered that if I explicitly type in 'trucker' instead of $a in the stripos function, it works perfectly. However, if I explicitly type in "trucker" (with double quotes), it stop working, and only blocks if that's the only thing the user entered.
So what I'm seeing, is it looks like the string $a that I'm passing it is being interpreted by PHP as a double quoted string, when in order for this to detect it properly, it needs to be a single quoted string. But as far as I can tell, I have no control over how php passes passing the variable.
Can I somehow convert it to a single quoted string? Perhaps the explode command I'm using in line 2 is causing it? Is there another way I can pull the data from a txt document and have it be interpreted as a single quote string? Hopefully I'm made sense with my explanation, but you can copy and paste the code and see it for yourself
Thanks for any help!
One potential problem would be any whitespace (which includes things like \r) could stop the word matching, so just trimming the word to compare with can tidy that up...
stripos($str, $a)
to
stripos($str, trim($a))
I do not know what your file actually contains so i dont know what the result of explode is.
Anyways my suggestion is (depending on the speed you want to perform this and also the length of the banlist file also your level of banning) to not explode the file and just look into it as a whole.
<?php
$username = "allow"; // This username should be allowed
$banlist = "trucker\nmotherfucker\n donot\ngoodword";
var_dump(contains($username, $banlist));
function contains($str, $arr)
{
if (stripos($arr, $str) !== false) return true;
else return false;
}
?>
Otherwise if you are going to allow say good which is an allowed word but since it is in the file with goodword it will not (using my example), you should not use stripos but instead use your example and use strcasecmp

Allow no whitespace in required form field

I have a register form which allows users to create usernames and passwords. It requires the username field not be empty, but I need to require that it allow no whitespace at all.
I looked into preg_match() but I can't seem to get that to cooperate with my current code.
if ($_SERVER["REQUEST_METHOD"] == "POST") {
/* Validate Username */
if (empty(trim($_POST["username"]))) {
$username_err = "Username Required";
}
No need to use Regex for something so simple. With strrpos() you can find the last occurence of a substring (space character) in a string (username).
If strrpos doesn't find a match, it will return false. So all you have to do is check if strrpos returns anything else but false:
if (empty(trim($_POST["username"]))) {
$username_err = "Username Required";
} else if (strrpos($_POST["username"], ' ') !== false){
$username_space_err = "Space found in username";
}
Before calling any function on $_POST() I recommend calling isset() on the element to avoid receiving a Notice.
Using isset() will allow for the valid but unlikely username of 0.
Calling trim() on a not-set element will cause a Notice.
I don't see any advantage in checking from the back of the string for spaces with strrpos() so I'll simply call strpos().
If this is a simple pass/fail task (not trying to isolate the cause of the failure), use this:
Code: (Demo)
$_POST['username']="0";
if(isset($_POST['username']) && strlen($_POST['username']) && strpos($_POST['username'],' ')===false){
echo 'pass';
}else{
echo 'fail';
}
Output:
pass
The beauty in this one-liner conditional, is that as soon as one of the conditions fails, the rest are ignored and the fail message will be displayed.
If you want to get a little crazy with micro-optimization, you can remove the strlen() call and just check for the existence of a first character (see if the first "offset" isset).
if(isset($_POST['username'][0]) && strpos($_POST['username'],' ')===false){
echo 'pass';
}else{
echo 'fail';
}
And if we are putting tin-foil hats on, then a check to see that $_POST['username'] is not an array should be included before strpos() is called (in any of the solutions on this page).
if(isset($_POST['username'][0]) && !is_array($_POST['username']) && strpos($_POST['username'],' ')===false){

How to convert random domain names into lowercase consistent urls?

I have this function in a class:
protected $supportedWebsitesUrls = ['www.youtube.com', 'www.vimeo.com', 'www.dailymotion.com'];
protected function isValid($videoUrl)
{
$urlDetails = parse_url($videoUrl);
if (in_array($urlDetails['host'], $this->supportedWebsitesUrls))
{
return true;
} else {
throw new \Exception('This website is not supported yet!');
return false;
}
}
It basically extracts the host name from any random url and then checks if it is in the $supportedWebsitesUrls array to ensure that it is from a supported website. But if I add say: dailymotion.com instead of www.dailymotion.com it won't detect that url. Also if I try to do WWW.DAILYMOTION.COM it still won't work. What can be done? Please help me.
You can use preg_grep function for this. preg_grep supports regex matches against a given array.
Sample use:
$supportedWebsitesUrls = array('www.dailymotion.com', 'www.youtube.com', 'www.vimeo.com');
$s = 'DAILYMOTION.COM';
if ( empty(preg_grep('/' . preg_quote($s, '/') . '/i', $supportedWebsitesUrls)) )
echo 'This website is not supported yet!\n';
else
echo "found a match\n";
Output:
found a match
You can run a few checks on it;
For lower case vs upper case, the php function strtolower() will sort you out.
as for checking with the www. at the beginning vs without it, you can add an extra check to your if clause;
if (in_array($urlDetails['host'], $this->supportedWebsitesUrls) || in_array('www.'.$urlDetails['host'], $this->supportedWebsitesUrls))

Returning a top level domain with a period at the end in php

Basically the problem I am having is I need to write this function that can take a URL like www.stackoverflow.com and just return the "com". But I need to be able to return the same value even if the URL has a period at the end like "www.stackoverflow.com."
This is what I have so far. The if statement is my attempt to return the point in the array before the period but I dont think I am using the if statement correctly. Otherwise the rest of the code does exactly what is supposed to do.
<?php
function getTLD($domain)
{
$domainArray = explode("." , $domain);
$topDomain = end($domainArray);
if ($topDomain == " ")
$changedDomain = prev(end($domainArray));
return $changedDomain;
return $topDomain;
}
?>
Don't use a regex for simple cases like that, it is cpu costly and unreadable. Just remove the final dot if it exists:
function getTLD($domain) {
$domain = rtrim($domain, '.');
return end(explode('.', $domain));
}
The end function is returning an empty string "" (without any spaces). You are comparing $topDomain to single space character so the if is not evaluating to true.
Also prev function requires array input and end($domainArray) is returning a string, so, $changedDomain = prev(end($domainArray)) should throw an E_WARNING.
Since end updates the internal pointer of the array $domainArray, which is already updated when you called $topDomain = end($domainArray), you do not need to call end on $domainArray inside the if block.
Try:
if ($topDomain == "") {
$changedDomain = prev($domainArray);
return $changedDomain; // Will output com
}
Here is the phpfiddle for it.
Use regular expressions for something like this. Try this:
function getTLD($domain) {
return preg_replace("/.*\.([a-z]+)\.?$/i", "$1", $domain );
}
A live example: http://codepad.org/km0vCkLz
Read more about regular expressions and about how to use them: http://www.regular-expressions.info/

Determine if a character is alphabetic

Having problems with this.
Let's say I have a parameter composed of a single character and I only want to accept alphabetic characters. How will I determine that the parameter passed is a member of the latin alphabet (a–z)?
By the way Im using PHP Kohana 3.
Thanks.
http://php.net/manual/en/function.ctype-alpha.php
<?php
$ch = 'a';
if (ctype_alpha($ch)) {
// Accept
} else {
// Reject
}
This also takes locale into account if you set it correctly.
EDIT: To be complete, other posters here seem to think that you need to ensure the parameter is a single character, or else the parameter is invalid. To check the length of a string, you can use strlen(). If strlen() returns any non-1 number, then you can reject the parameter, too.
As it stands, your question at the time of answering, conveys that you have a single character parameter somewhere and you want to check that it is alphabetical. I have provided a general purpose solution that does this, and is locale friendly too.
Use the following guard clause at the top of your method:
if (!preg_match("/^[a-z]$/", $param)) {
// throw an Exception...
}
If you want to allow upper case letters too, change the regular expression accordingly:
if (!preg_match("/^[a-zA-Z]$/", $param)) {
// throw an Exception...
}
Another way to support case insensitivity is to use the /i case insensitivity modifier:
if (!preg_match("/^[a-z]$/i", $param)) {
// throw an Exception...
}
preg_match('/^[a-zA-Z]$/', $var_vhar);
Method will return int value: for no match returns 0 and for matches returns 1.
I'd use ctype, as Nick suggested,since it is not only faster than regex, it is even faster than most of the string functions built into PHP. But you also need to make sure it is a single character:
if (ctype_alpha($ch) && strlen($ch) == 1) {
// Accept
} else {
// Reject
}
You can't use [a-zA-Z] for Unicode.
here are the example working with Unicode,
if ( preg_match('/^\p{L}+$/u', 'my text') ) {
echo 'match';
} else {
echo 'not match';
}
This will help hopefully.This a simple function in php called ctype_alpha
$mystring = 'a'
if (ctype_alpha($mystring))
{
//Then do the code here.
}
You can try:
preg_match('/^[a-zA-Z]$/',$input_char);
The return value of the above function is true if the $input_char contains a single alphabet, else it is false. You can suitably make use of return value.

Categories