943,545 Members | Top Members by Rank

Ad:
  • PHP Discussion Thread
  • Unsolved
  • Views: 7991
  • PHP RSS
Jul 23rd, 2007
0

PHP Badword Filter (Intermediate)

Expand Post »
Yes, there are many posts out there about badword filters, and most seem to fall short of something you'd want to turn loose on a corporate website. I've created a fairly elegant badword solution, and I wish to share it with the development community. I'm looking to optimize it a bit more, because as the list of badwords I use grows, the process time could get pretty ugly.

A little more explanation about this particular script - One of my clients has a fairly complex comment form on their website that allows the option to comment, get the newsletter, etc - and then emails the necessary details to their person who handles such things. Recently, the emails were coming fast and furious with spam for lewd websites, prescription medications, and such. Of course, this needed to stop.

As there is no message board to check, and no obvious verification to see if the message was indeed sent or received (just a static thank-you splash page) - there was no need to try and replace bad words with characters, or warn the offending user/bot that anything was amiss - the messages just needed to be sent to the circular bin. As we weren't interested in keeping the messages around, a little delicacy was needed to keep partial matches from flagging the messages. This was the first feature of my script that I noticed most do not contain - many will display words like class as cl***. As the message would then be flagged as containing bad words, this approach wouldn't work.

So, a little wrangling with regular expressions later, I have a script that only matches whole words from my badwords list. Now, the occasional swear isn't going to matter, so if a couple masked words or swears next to tags make it through, it's ok. If you need to further filter for those instances, then by all means replace tags with whitespace before doing the string comparison.

Other features that are in this script that may or may not be included in other examples bouncing around the web:

* bad words are loaded from a text file
* additional block for [url] tags implemented
* result is transparent - offender doesn't know he's blocked.

And here's the script. If there are ideas on how to tidy some things up, I'll happily give them a shot. I'm currently considering switching from preg_match() to eregi(), and also creating the badwords expression from the entire badwords file, using the | operator and a loop. This way there's only one preg_match() call needed, instead of looping it. I'm also sure some of my control expressions could be a little more elegant, but this is a good first crack, I believe. If I make any major changes, I'll post them as replies.


php Syntax (Toggle Plain Text)
  1. // Filtering Function
  2.  
  3. function filterBadWords($str,$badWordsFile) {
  4. $badFlag = 0;
  5. if(!is_file($badWordsFile)) {
  6. echo "ERROR: file missing: ".$badWordsFile;
  7. exit;
  8. }
  9. else {
  10. $badWordsFH = fopen($badWordsFile,"r");
  11. $badWordsArray = explode("\n", fread($badWordsFH, filesize($badWordsFile)));
  12. fclose($badWordsFH);
  13. }
  14. foreach ($badWordsArray as $badWord) {
  15. if(!$badWord) continue;
  16. else {
  17. $regexp = "/\b".$badWord."\b/i";
  18. if(preg_match($regexp,$str)) $badFlag = 1;
  19. }
  20. }
  21. if(preg_match("/\[url/",$str)) $badFlag = 1;
  22. return $badFlag;
  23. }

php Syntax (Toggle Plain Text)
  1. // Function Call/Usage
  2. if (filterBadWords($message,"badwords.txt") == 0) {
  3. mail("mail@destination.com", $subject, $message, $from);
  4. }
  5. header("Location: http://www.siteurl.com/index.php?p=Thank_You");


PHP Syntax (Toggle Plain Text)
  1. // badwords.txt
  2. word1
  3. word2
  4. word3
Similar Threads
Reputation Points: 10
Solved Threads: 0
Newbie Poster
esp68 is offline Offline
1 posts
since Jul 2007
Jul 24th, 2007
0

Re: PHP Badword Filter (Intermediate)

A better solution for yourself would be just to mask the bad words (unless you really don't want to send the email).

Just do a preg_replace of *@!>&^ (or however many characters are in the badword).

Nothing much wrong with your code though, just a few logic changes might benefit yourself.

You are not validating your mail() function either. I suggest wrapping it in an IF statement or use the @ character eg: @mail(..);

Cheers
Reputation Points: 35
Solved Threads: 5
Junior Poster
dr4g is offline Offline
136 posts
since Apr 2007
Jun 21st, 2009
-1

Re: PHP Badword Filter (Intermediate)

Click to Expand / Collapse  Quote originally posted by esp68 ...
Yes, there are many posts out there about badword filters, and most seem to fall short of something you'd want to turn loose on a corporate website. I've created a fairly elegant badword solution, and I wish to share it with the development community. I'm looking to optimize it a bit more, because as the list of badwords I use grows, the process time could get pretty ugly.

A little more explanation about this particular script - One of my clients has a fairly complex comment form on their website that allows the option to comment, get the newsletter, etc - and then emails the necessary details to their person who handles such things. Recently, the emails were coming fast and furious with spam for lewd websites, prescription medications, and such. Of course, this needed to stop.

As there is no message board to check, and no obvious verification to see if the message was indeed sent or received (just a static thank-you splash page) - there was no need to try and replace bad words with characters, or warn the offending user/bot that anything was amiss - the messages just needed to be sent to the circular bin. As we weren't interested in keeping the messages around, a little delicacy was needed to keep partial matches from flagging the messages. This was the first feature of my script that I noticed most do not contain - many will display words like class as cl***. As the message would then be flagged as containing bad words, this approach wouldn't work.

So, a little wrangling with regular expressions later, I have a script that only matches whole words from my badwords list. Now, the occasional swear isn't going to matter, so if a couple masked words or swears next to tags make it through, it's ok. If you need to further filter for those instances, then by all means replace tags with whitespace before doing the string comparison.

Other features that are in this script that may or may not be included in other examples bouncing around the web:

* bad words are loaded from a text file
* additional block for [url] tags implemented
* result is transparent - offender doesn't know he's blocked.

And here's the script. If there are ideas on how to tidy some things up, I'll happily give them a shot. I'm currently considering switching from preg_match() to eregi(), and also creating the badwords expression from the entire badwords file, using the | operator and a loop. This way there's only one preg_match() call needed, instead of looping it. I'm also sure some of my control expressions could be a little more elegant, but this is a good first crack, I believe. If I make any major changes, I'll post them as replies.


php Syntax (Toggle Plain Text)
  1. // Filtering Function
  2.  
  3. function filterBadWords($str,$badWordsFile) {
  4. $badFlag = 0;
  5. if(!is_file($badWordsFile)) {
  6. echo "ERROR: file missing: ".$badWordsFile;
  7. exit;
  8. }
  9. else {
  10. $badWordsFH = fopen($badWordsFile,"r");
  11. $badWordsArray = explode("\n", fread($badWordsFH, filesize($badWordsFile)));
  12. fclose($badWordsFH);
  13. }
  14. foreach ($badWordsArray as $badWord) {
  15. if(!$badWord) continue;
  16. else {
  17. $regexp = "/\b".$badWord."\b/i";
  18. if(preg_match($regexp,$str)) $badFlag = 1;
  19. }
  20. }
  21. if(preg_match("/\[url/",$str)) $badFlag = 1;
  22. return $badFlag;
  23. }

php Syntax (Toggle Plain Text)
  1. // Function Call/Usage
  2. if (filterBadWords($message,"badwords.txt") == 0) {
  3. mail("mail@destination.com", $subject, $message, $from);
  4. }
  5. header("Location: http://www.siteurl.com/index.php?p=Thank_You");


PHP Syntax (Toggle Plain Text)
  1. // badwords.txt
  2. word1
  3. word2
  4. word3
I tried the above mentioned code but it does not work, only the last bad word in the txt file would be filtered

my additional code in front is this
PHP Syntax (Toggle Plain Text)
  1. $badWordsFile="badwords.txt";
in addition, i replace all $str with $message but it does not work, I am currently rushing a project and i need an urgent reply, thanks!
Last edited by jiawei456123; Jun 21st, 2009 at 2:09 am. Reason: Spelling error
Reputation Points: 9
Solved Threads: 0
Newbie Poster
jiawei456123 is offline Offline
1 posts
since Jun 2009

This thread is more than three months old

No one has posted to this discussion for at least three months. Please let old threads die and do not reply to them unless you feel you have something new and valuable to contribute that absolutely must be added to make the discussion complete. Otherwise, please start a new thread in this forum instead.
Message:
Previous Thread in PHP Forum Timeline: Passing & displaying text array from form
Next Thread in PHP Forum Timeline: Populating form with existing MySQL data





About Us | Contact Us | Advertise | Acceptable Use Policy
Forum Index | Build Custom RSS Feed


Follow us on Twitter


© 2011 DaniWeb® LLC