This question has been asked before about strings, however *none of the questions I've reviewed (not mods do not remove or tell us this is a duplicate please) actually answer my question.
I have a landing page with a simple signup via email box. Recently people have been abusing it by entering foreign characters such as *, #, $, % and also using profanity on purpose (you can always tell). I have an array of banned characters and words I'm using as follows
$banned = array("f**k", "f******", "blah", "*", "#", "$", "%");
I can tell for sure someone has been purposely trying again and again to get through it because I've missed out some characters and suddenly a bunch of addresses have been entered making no sense at all. I need to know how to use a For loop to go through and find if the following contains any of the banned words in the array
$email = $_POST['email'];
I have tried using
$arrlen = count($banned);
for($i=0; $i < $arrlen; $i++) {
if(stripos($email, $banned[$i] !== false) {
echo 'Banned word or character!';
}
else {
echo 'Email signed up!';
}
}
This did not work at all! I tried an old function is_str_contain but the error of function does not exist came back.
I tried the normal strpos as well, still no joy.
I've been tinkering at the idea since I didn't have a ready-made piece of code to help out.
The following works:
$banned = array("badword1", "badword2", "blah", "*", "#", "$", "%");
$_POST['email'] = "emailbadword1#example.com";
$email = $_POST['email'];
foreach ($banned as $ban) {
if (stripos($email, $ban) !== FALSE) {
echo "Match found.";
return true;
}
}
echo "No match found.";
return false;
Plus, as I mentioned in comments; you should be using a confirmation method sent via email if you're not already doing so. If that person does not confirm their email address, then "stop the presses".
Using regular expressions ?
if( !preg_match( '/(\b' . implode( '\b|\b', $banned ) . '\b)/i',
$_POST['email'] )) {
echo "Match found";
}
try like this
$banned = array("****", "*******", "blah", "*", "#", "$", "%");
$email = $_POST['email'];
foreach ($email as $em) {
//if (strstr($em, $banned)) { // mine version
if (strpos($em, $banned) !== FALSE) { // Yoshi version
echo "Match found";
return true;
}
}
echo "Not found!";
return false;
You can use stripos as
foreach ($banned as $v) {
if (stripos($email,$v) > -1){
echo 'Banned word or character!';
}else{
echo 'Email signed up!';
}
}
You will need to iterate through each banned word and look if your email contains any of the banned word/character.
$banned = array("****", "*******", "blah", "*", "#", "$", "%");
$email = $_POST['email'];
$banned = false;
for($i=0; $i < count($banned); $i++) {
if(strrpos($email, $banned[$i]) != FALSE ) {
$banned = true;
break;
}
}
echo $banned ? 'Banned word or character!' : 'Email signed up!'
Related
I have the below code for matching an email address using regular expression rules.
It works well, but I've recently noticed that it seems to match a "Blank" email address.
if (preg_match("/.* <.*#.*\..*>/i",$this->to,$matches)) {
$this->email_to = preg_replace("/.*<(.*)>.*/","$1",$this->to);
} else {
$this->email_to = $this->to;
}
My understanding of the preg_match is:-
Looks for any character, except a line break
< anycharacter#anything.anything >
Case-insensitive?
Following those rules, I can't quite work out why it matches a blank / no email address if someone can give some guidance.
Thank you.
No needs for preg_match + preg_replace.
if (empty($this->to)) {
$this->email_to = 'Is empty'; # assign what you want
} elseif (preg_match("/<(.+?#.+?\..+?)>/", $this->to, $matches)) {
$this->email_to = $matches[1];
} else {
$this->email_to = $this->to;
}
I don't know why it behaves like that but an easy solution is to ask if the string is blank
if (preg_match("/.* <.*#.*\..*>/i",$this->to,$matches)) {
if ($matches != ""){
$this->email_to = preg_replace("/.*<(.*)>.*/","$1",$this->to);
} else { $this->email_to = $this->to; }
} else {
$this->email_to = $this->to;
}
So, i've been working on making a search engine without the use of a database. What it's supposed to do is find the word searched for in the webpage and automatically give it's link. Here's it's code:
<?php
session_start();
$searchInput = $_POST['search'];
$inputPage1 = $_SESSION['pOneText'];
$inputPage2 = isset($_SESSION['pTwoText']) ? $_SESSION['pTwoText'] : "";
$inputPage3 = isset($_SESSION['pThreeText']) ? $_SESSION['pThreeText'] : "";
$fUrl = file_get_contents("mDummyP.php");
$sUrl = file_get_contents("sDummyP.php");
$tUrl = file_get_contents("tDummyP.php");
if (substr_count($fUrl, $searchInput) !== false) {
echo "All results for <strong> $searchInput </strong> : <br>" ;
} elseif (substr_count($sUrl, $searchInput) !== false) {
echo "All results for <strong> $searchInput </strong> : <br>";
} elseif (substr_count($tUrl, $searchInput) !== false) {
echo "All results for <strong> $searchInput </strong> : <br>";
} else {
echo "No resulst for <strong> $searchInput </strong>! ";
}
?>
However, it never checks if the word actually exists or not, it always returns "all results for". So, i was wondering if anyone knew why or had suggestions to improve it. Keep in mind that it will never be used professionally, it's just to test my abilities. Thanks in advance!
You need to look at the php manual for substr_count
Return Values
This function returns an integer.
Thus it will ALWAYS go into this first if block:
if (substr_count($fUrl, $searchInput) !== false) {
because the return value of substr_count is only ever an integer and is NEVER going to be false - your code is checking for the exact value and type of false.
Furthermore, apart from the else block, all of the statements are just echo'ing the exact same string so you will not see any differentiation of output if execution did go into the if or elseif blocks. See below to get you on the right track:
$searchInput = 'some';
$fUrl = 'this is test file text';
$sUrl = 'this is some other text';
$tUrl = 'extra text';
if (substr_count($fUrl, $searchInput) !== 0) {
echo "a";
} elseif (substr_count($sUrl, $searchInput) !== 0) {
echo "b";
} elseif (substr_count($tUrl, $searchInput) !== 0) {
echo "c";
} else {
echo "No resulst for <strong> $searchInput </strong>! ";
}
I am trying to read all lines from a file and than see if a given string contains any of these lines.
My code
$mails = file('blacklist.txt');
$email = "hendrik#anonbox.net";
$fail = false;
foreach($mails as $mail) {
if(strpos($email, $mail) > 0) {
$fail = true;
}
}
if($fail) {
echo "Fail";
} else {
echo "you can use that";
}
The blacklist.txt can be found here http://pastebin.com/aJyVkcNx.
I would expect strpos return a position for at least one string in the blacklist, but it does not. I am guessing that somehow I am generating not the kind of values within the $mails as I am expecting.
EDIT this is print_r($mails) http://pastebin.com/83ZqVwHx
EDIT2 some clarification: I want to see if a domain is within an email, even if the mail contains subdomain.domain.tld. And I tried to use !== false instead of my > 0 which yielded the same result.
You need to parse the email well since you're checking the domain of the email address if its inside the blacklist. Example:
$email = "hendrik#foo.anonbox.net";
if(filter_var($email, FILTER_VALIDATE_EMAIL)) {
preg_match('/#.*?([^.]+[.]\w{3}|[^.])$/', $email, $matches);
if(!empty($matches) && isset($matches[1])) {
$domain = $matches[1];
} else {
// not good email
exit;
}
// THIS IS FOR SAMPLES SAKE, i know youre using file()
$blacklist = explode("\n", file_get_contents('http://pastebin.com/raw.php?i=aJyVkcNx'));
foreach($blacklist as $email) {
if(stripos($email, $domain) !== false) {
echo 'you are blacklisted';
exit;
}
}
}
// his/her email is ok continue
strpos returns FALSE if the string was not found.'
Simply use this :
$fail = false;
foreach($mails as $mail) {
if(strpos($email, $mail) === false) {
$fail = true;
}
}
Or even better use this:
$blacklist = file_get_contents('blacklist.txt');
$email = "hendrik#anonbox.net";
if(strpos($email, $blacklist) === false){
echo "fail";
} else {
echo "This email is not blacklisted";
}
You have found the common pitfall with the strpos function. The return value of the strpos function refers to the position at which it found the string. In this instance, if the string begins at the first character, it will return 0. Note that 0 !== false.
The correct way to use the function is:
if(strpos($email, $mail) !== false){
// the string was found, potentially at position 0
}
However, this function may not be necessary at all; if you are simply checking if $mail is the same as $email, instead of seeing if the string exists within a larger string, then just use:
if($mail == $email){
// they are the same
}
Though you might still use foreach, that’s array reduce pattern:
function check_against($carry, $mail, $blacklisted) {
return $carry ||= strpos($mail, $blacklisted) !== false;
};
var_dump(array_reduce($mails, "check_against", $email_to_check));
Hope it helps.
Yet another way to solve this. Works fine:
$blacklist = file_get_contents('blacklist.txt');
$email = "hendrik#x.ip6.li";
$domain = substr(trim($email), strpos($email, '#')+1);
if(strpos($blacklist, $domain)){
echo "Your email has been blacklisted!";
}else{
echo "You are all good to go! not blacklisted :-)";
}
Goodluck!
This question already has answers here:
How to validate an Email in PHP?
(7 answers)
How to validate an email address in PHP
(15 answers)
Closed 9 years ago.
I want to validate the e-mail domain but I don't want to worry about any possible subdomain that may appears.
For example:
#abc.com
#a.abc.com
#b.abc.com
...
These should all be valid.
Also, I have a list of domains to validate, such as abc.com, xyz.com... how is the best way to validate e-mail domains from a list, including subdomains?
Thanks.
I decided to rewrite this to be more friendly so that you aren't restricted on what type of domain scheme you whitelist.
$whitelist = array("abc.com", "xyz.com", "specific.subdomain.com", "really.specific.subdomain.com"); //You can add basically whatever you want here because it checks for one of these strings to be at the end of the $email string.
$email = "#d.xyz.com";
function validateEmailDomain($email, $domains) {
foreach ($domains as $domain) {
$pos = strpos($email, $domain, strlen($email) - strlen($domain));
if ($pos === false)
continue;
if ($pos == 0 || $email[(int) $pos - 1] == "#" || $email[(int) $pos - 1] == ".")
return true;
}
return false;
}
So, you'd use this like:
if (validateEmailDomain($email, $whitelist))
//Do something.
You can also validate the domain using dns:
function validEmail($email)
{
$allowedDomains = array('abc.com');
list($user, $domain) = explode('#', $email);
if (checkdnsrr($domain, 'MX') && in_array($domain, $allowedDomains))
{
return true;
}
return false;
}
I wrote this function a while back. It may fill the requirements on what you're looking for. It does two things, validates the email address is a valid address and then validates if the domain name is a valid name against it's MX record in DNS.
function validate_email($email) {
// Check email syntax
if(preg_match('/^([a-zA-Z0-9\._\+-]+)\#((\[?)[a-zA-Z0-9\-\.]+\.([a-zA-Z]{2,7}|[0-9]{1,3})(\]?))$/', $email, $matches)) {
$user = $matches[1];
$domain = $matches[2];
// Check availability of DNS MX records
if(getmxrr($domain, $mxhosts, $mxweight)) {
for($i=0;$i<count($mxhosts);$i++){
$mxs[$mxhosts[$i]] = $mxweight[$i];
}
// Sort the records
asort($mxs);
$mailers = array_keys($mxs);
} elseif(checkdnsrr($domain, 'A')) {
$mailers[0] = gethostbyname($domain);
} else {
$mailers = array();
}
$total = count($mailers);
// Added to still catch domains with no MX records
if($total == 0 || !$total) {
$error = "No MX record found for the domain.";
}
} else {
$error = "Address syntax not correct.";
}
return ($error ? $error : TRUE);
}
I wrote a simple example of the regular expression with the ability to check the list of domain.
<?php
$email = 'shagtv#a.xyz.com';
$domains = array('abc.com', 'xyz.com');
$pattern = "/^[a-z0-9._%+-]+#[a-z0-9.-]*(" . implode('|', $domains) . ")$/i";
if (preg_match($pattern, $email)) {
echo 'valid';
} else {
echo 'not valid';
}
?>
Well you should use some code like this:
<?php
$subject = "abcdef";
$pattern = '/^def/';
preg_match($pattern, substr($subject,3), $matches, PREG_OFFSET_CAPTURE);
print_r($matches);
?>
or this:
<?php
$email = "someone#exa mple.com";
if(!filter_var($email, FILTER_VALIDATE_EMAIL))
{
echo "E-mail is not valid";
}
else
{
echo "E-mail is valid";
}
?>
or this that you have to do a little modify with this page.
Hope it helps!
Very similar to this post: PHP Check domain of email being registered is a 'school.edu' address
However, you need to take it one step further. Once you have that split, look at parse_url
http://php.net/manual/en/function.parse-url.php and grab the HOST part.
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Regular Expression matching for entire string
On my form page, I am trying to make it only accept alphanumeric characters for my username and password and require that they be from 6 to 15 characters. When I type in invalid data, it will insert it into the database rather than throw the user error that I defined in my CheckAlNum function.
functions.php
function checkAlNum($whichField)
{
if (preg_match('/[A-Za-z0-9]+/', $_POST[$whichField])){
if ( (!count(strlen($whichField) >= 6)) OR (!count(strlen($whichField) <= 15 ))) {
$message1 = '<p> Username and password must be between 6 and 15 characters </p>';
return user_error($message1);
}
else{
return true;
}
}
else {
$message = '<p>Username and password can only be numbers or letters</p>';
return user_error($message);
}
}
Form.php
if (count($_POST) > 0) {
//Validate the inputs
$errorMessages = array();
//Validate the username
$item5 = checkAlNum('username');
if($item5 !== true) {
$errorMessages[] = $item5;
}
//Validate the password
$item6 = checkAlNum('password');
if($item6 !== true) {
$errorMessages[] = $item6;
}
//Validate the firstName and lastName
$item1 = checkNameChars('firstName');
if ($item1 !== true) {
$errorMessages[] = $item1;
}
$item2 = checkNameChars('lastName');
if ($item2 !== true) {
$errorMessages[] = $item2;
}
//Validate the office name
$item3 = checkOfficeChars('office');
if ($item3 !== true) {
$errorMessages[] = $item3;
}
//Validate the phone number
$item4 = validate_phone_number('phoneNumber');
if($item4 !== true) {
$errorMessages[] = $item4;
}
//Check to see if anything failed
if (count($errorMessages) == 0) {
$newEmployee = new Person;
$newEmployee -> insert();
}
else { //Else, reprint the form along with some error messages
echo "<h2><span>Error</span>: </h2>";
foreach($errorMessages as $msg) {
echo "<p>" . $msg . "</p>";
}
}
}
?>
I've tried playing around with the nesting of the if-else statements of the checkAlNum function and also the regex (although I'm pretty sure the regex is right). Maybe I'm just missing something really silly?
function checkAlNum($whichField)
{
if (preg_match('/^[a-z0-9]{6,15}$/i', $_POST[$whichField])) {
return true;
}
else {
$message = '<p>Username and password can only be numbers or letters, 6-15 characters long</p>';
return user_error($message);
}
}
Without the ^ and $ anchors, your regex only checks whether there are alphanumerics anywhere in the field, not that the whole thing is alphanumeric. And changing + to {6,15} implements the length check here, so you can remove that extra check in your code.
I think the second if statement is incorrect. It should be like this:
if ( !( (!count(strlen($whichField) >= 6)) OR (!count(strlen($whichField) <= 15 )) ) ) {
// ... do something
}
This is due to De Morgan Rule which states
A AND B = !( !A OR !B )
In any case, I would not do my checks this way, strucurally you will end up with too many nested if statements that are hard to maintain and make your code look unpretty. Try avoiding nested conditions in your code.
Barmar's answer is the best. But if you want to keep your if statement to check string length, you need to remove the count() as you are already checking the length using strlen().
if ( (!(strlen($whichField) >= 6)) OR (!(strlen($whichField) <= 15 ))) {