per1os Posted June 12, 2007 Share Posted June 12, 2007 What I am seeing is that your "string to test" is blank and the exploding of the variables is not working like expected to. Post the file contents of the word file. Also check and make sure the $_POST['comments'] is the correct variable name on the form, maybe even post the comment form code. Quote Link to comment Share on other sites More sharing options...
wildteen88 Posted June 12, 2007 Share Posted June 12, 2007 mysql_real_escape is not a known (builtin) function and thus PHP kicks up the fatal error: to called to undefined function xxx in xyz on line 123 error message. I guess you mean to call mysql_real_escape_string function not mysql_real_escape (which doesn't exist) Also I would change your error checking to this: <?php foreach($_POST as $key => $value) { $POST[$field] = trim($value); } $err = ''; // input error checking if(isset($_POST['name']) || empty($_POST['name'])) { $err[] = 'Please enter your name.'; } if(isset($_POST['phone']) || empty($_POST['phone']) && !is_numeric($_POST['phone'])) { $err[] = 'Please enter a valid phone number. Phone numbers must only contain digits'; } // input error checking if(isset($_POST['email']) || empty($_POST['email'])) { $err[] = 'Please enter your email address.'; } elseif(!eregi("^[_a-z0-9-]+(\.[_a-z0-9-]+)*@[a-z0-9-]+(\.[a-z0-9-]+)*(\.[a-z]{2,3})$", $_POST['email'])) { $err[] = $email . ' is not a valid email address.'; } if(is_array($err)) { echo 'Please correct the following errors thank you:<br />'; echo '<ul><li>' . implode('</li><li>', $err) . '</li></ul>'; } else { // post our variables from the registration form $name = mysql_real_escape_string($_POST['name']); $phone = mysql_real_escape_string($_POST['phone']); $email = mysql_real_escape_string($_POST['email']); $facing_foreclosure = $name; $referred_by = mysql_real_escape_string($_POST['referred_by']); $comments = mysql_real_escape_string($comments); $today = date("F j, Y, g:i a"); // make database connection db_conn(); // mail the results to admin send_ebook_mail(); // run the query ebook_insert(); } } ?> Always validate raw $_POST data do not do $var = $_POST['var']; if($var=='') Revamped code: <?php // ebook registration and database insertion include 'db_config.inc'; if (isset($_POST['Submit'])) { // our attempt to stop spammers $keywords_list = file_get_contents('words.txt'); $banned_keywords = explode(',', $keywords_list); $comments = $_POST['comments']; foreach ($banned_keywords as $keyword) { if(preg_match('/' . trim($keyword) . '/i', $comments)) { header("location: reject.htm"); exit; } else { foreach($_POST as $key => $value) { $POST[$field] = trim($value); } $err = ''; // input error checking if(isset($_POST['name']) || empty($_POST['name'])) { $err[] = 'Please enter your name.'; } if(isset($_POST['phone']) || empty($_POST['phone']) && !is_numeric($_POST['phone'])) { $err[] = 'Please enter a valid phone number. Phone numbers must only contain digits'; } // input error checking if(isset($_POST['email']) || empty($_POST['email'])) { $err[] = 'Please enter your email address.'; } elseif(!eregi("^[_a-z0-9-]+(\.[_a-z0-9-]+)*@[a-z0-9-]+(\.[a-z0-9-]+)*(\.[a-z]{2,3})$", $_POST['email'])) { $err[] = $email . ' is not a valid email address.'; } if(is_array($err)) { echo 'Please correct the following errors thank you:<br />'; echo '<ul><li>' . implode('</li><li>', $err) . '</li></ul>'; } else { // post our variables from the registration form $name = mysql_real_escape_string($_POST['name']); $phone = mysql_real_escape_string($_POST['phone']); $email = mysql_real_escape_string($_POST['email']); $facing_foreclosure = $name; $referred_by = mysql_real_escape_string($_POST['referred_by']); $comments = mysql_real_escape_string($comments); $today = date("F j, Y, g:i a"); // make database connection db_conn(); // mail the results to admin send_ebook_mail(); // run the query ebook_insert(); } } } } ?> Quote Link to comment Share on other sites More sharing options...
simcoweb Posted June 12, 2007 Author Share Posted June 12, 2007 *ahem*...the contents of the 'words.txt' file are not appropriate for young eyes. So, i'll post the 'edited' version generic viagra cialis levitra soma propecia phentermine adipex tramadol Cheap Order Adipex url http msg JADAVIS Soma fioricet pantyhose sex free gallery teen voyeur upskirt privatevoyeur projectvoyeur Fioricet Regarding the form, dohhhhhh.. honestly i'm not that dumb. The $_POST['comments'] form field was mislabeled. I corrected it and resubmitted. Here's the new message: String to Test against: viagra cialis Keyword: generic Warning: Cannot modify header information - headers already sent by (output started at /home/content/C/o/r/Corbaley8076/html/ebook.php:12) in /home/content/C/o/r/website/html/ebook.php on line 93 So, it appears it's testing now but the Keyword: generic just shows the first line of the words.txt file. viagra is the 2nd line and cialis is the 3rd. Quote Link to comment Share on other sites More sharing options...
wildteen88 Posted June 12, 2007 Share Posted June 12, 2007 comment out the header part for now. it is causing your script to not work correctly chane this: if(preg_match('/'.$keyword.'/i',$str)) { header("location: reject.htm");exit; //Or whatever the logout url is } else { to this: if(preg_match('/'.$keyword.'/i',$str)) { //header("location: reject.htm");exit; //Or whatever the logout url is } else { Now you can continue debugging your script. Quote Link to comment Share on other sites More sharing options...
simcoweb Posted June 12, 2007 Author Share Posted June 12, 2007 wildteen, I tried that and it go t the same error message since there's another header function later in the code: String to Test against: cialis viagra Keyword: generic Warning: Cannot modify header information - headers already sent by (output started at /home/content/C/o/r/Corbaley8076/html/ebook.php:12) in /home/content/C/o/r/Corbaley8076/html/ebook.php on line 93 Quote Link to comment Share on other sites More sharing options...
The Little Guy Posted June 12, 2007 Share Posted June 12, 2007 I would suggest that you have a filter, and if it finds a word within the post that is in your filter, than you deny the post from taking place, untill the words are removed. Quote Link to comment Share on other sites More sharing options...
simcoweb Posted June 12, 2007 Author Share Posted June 12, 2007 That's pretty much what we're trying to do. But, the way it figures, I don't want to let someone keep trying if they typed in viagra, cialis, phentermine, etc. in their first attempt. That's a spammer. The goal is to get rid of them on the first try so they don't figure out a way to modify the spelling and get it through (ex: c1alis, c*i*a*l*i*s, etc. instead of cialis). The site is about foreclosure proceedings. Viagra has no place in that conversation (Hi, Mr. Realtor, I was taking some viagra today and remembered my house was in foreclosure...). I really want it to check/filter against the restricted words and if found it bounces their asses outta there before it submits the data to the database and emails the site owner with the results. We're close but need a tweak or two to get it there. Any ideas? Quote Link to comment Share on other sites More sharing options...
simcoweb Posted June 13, 2007 Author Share Posted June 13, 2007 Still looking for a fix on this As an experiment I submitted the form with the word 'generic' in the comments box (previous tests all used 'viagra' and 'cialis'). What happened that was different than previous tests is the keyword display showed two lines instead of one. Check it out: String to Test against: generic Keyword: generic Keyword: viagra The 'debug' code is set to loop through all the keywords but for some reason that's not working: if (isset($_POST['Submit'])) { // our attempt to stop spammers $wordfile = file_get_contents('words.txt'); $notallowed = explode(",",$wordfile); $str = strip_tags(trim($_POST['comments'])); echo "String to Test against: " . $str . "<br />"; foreach ($notallowed as $keyword) { echo "Keyword: " . $keyword . "<Br />"; $keyword = trim($keyword); if(preg_match('/'.$keyword.'/i',$str)) { //header("location: reject.htm");exit; //Or whatever the logout url is } else { As another experiment I changed the 'words.txt' file to a comma delimited format. This is supposed to check against the banned words and, if found, exit the script. Quote Link to comment Share on other sites More sharing options...
per1os Posted June 13, 2007 Share Posted June 13, 2007 Still looking for a fix on this As an experiment I submitted the form with the word 'generic' in the comments box (previous tests all used 'viagra' and 'cialis'). What happened that was different than previous tests is the keyword display showed two lines instead of one. Check it out: String to Test against: generic Keyword: generic Keyword: viagra The 'debug' code is set to loop through all the keywords but for some reason that's not working: if (isset($_POST['Submit'])) { // our attempt to stop spammers $wordfile = file_get_contents('words.txt'); $notallowed = explode(",",$wordfile); $str = strip_tags(trim($_POST['comments'])); echo "String to Test against: " . $str . "<br />"; foreach ($notallowed as $keyword) { echo "Keyword: " . $keyword . "<Br />"; $keyword = trim($keyword); if(preg_match('/'.$keyword.'/i',$str)) { //header("location: reject.htm");exit; //Or whatever the logout url is } else { As another experiment I changed the 'words.txt' file to a comma delimited format. This is supposed to check against the banned words and, if found, exit the script. The reason it showed 2 is that the loop actually ran threw, before you were testing it against a string of "viagra" instead of "Generic viagra" so it hit viagra and ended there. Basically it means it is working. Quote Link to comment Share on other sites More sharing options...
simcoweb Posted June 13, 2007 Author Share Posted June 13, 2007 Hi frost. But I didn't use 'Generic viagra' in the test. Just the word 'generic'. In the previous tests I used two words, 'viagra' and 'cialis'. So based upon those shouldn't it have displayed as follows?: generic viagra cialis levitra And, the golden question, why isn't it flagging the banned words and exiting? It's obviously matching up. But what happens is it continues with the 'else' code which is to add it to the database and send the emails. Quote Link to comment Share on other sites More sharing options...
thefortrees Posted June 13, 2007 Share Posted June 13, 2007 man. Quote Link to comment Share on other sites More sharing options...
Yesideez Posted June 13, 2007 Share Posted June 13, 2007 If you want to block emails sent by bots trawling through your site why not just add a verification code that needs to be entered? You can make your own quite easily, something like this that I use on my site: As well as asking the user for their details you can also ask them to enter what they see in the image. The code to produce this is like this: <?php session_start(); $imgWidth=130; $imgHeight=34; $chars='abcdefghijkmnqrstuvwxyz0123456789ABCDEFGHIJKLMNPQRSTUVWXYZ'; $strText=''; for ($i=1;$i<7;$i++) {$strText.=substr($chars,mt_rand(0,strlen($chars)-1),1);} $_SESSION['code']=md5($strText); header("Content-type: image/png"); $img=imagecreatefrompng('gfx/codebg.png'); for ($i=0;$i<strlen($strText);$i++) { $colFG=imagecolorallocate($img,mt_rand(50,255),mt_rand(50,255),mt_rand(50,255)); imagettftext($img,20,mt_rand(-40,40),10+($i*20),27,$colFG,'times.ttf',substr($strText,$i,1)); } imagepng($img); imagedestroy($img); ?> Just take the code they enter, use md5() on it and check if it matches the session variable 'code'. If you use the above method you'll have to upload a TrueType font file (times.ttf in above example) onto the server and have GD library installed to be able to make the images. The file 'gfx/codebg.png' is the cloud background I made using Photoshop. The script builds a random string using the specified allowed characters and uses GD library to draw them on the cloud image. Note I've removed some of the characters from the "allowed" list to prevent confusion between like a lower case "L" and a number "1" EDIT: Removed superfluous code Quote Link to comment Share on other sites More sharing options...
Yesideez Posted June 13, 2007 Share Posted June 13, 2007 btw, I've used a different method on the guestbook on my website http://www.pictureinthesky.net If you just want to search for various words in the message or subject string then there's no need to search for every variation on a word. Just convert to the same case before checking! Quote Link to comment Share on other sites More sharing options...
per1os Posted June 13, 2007 Share Posted June 13, 2007 Hi frost. But I didn't use 'Generic viagra' in the test. Just the word 'generic'. In the previous tests I used two words, 'viagra' and 'cialis'. So based upon those shouldn't it have displayed as follows?: generic viagra cialis levitra And, the golden question, why isn't it flagging the banned words and exiting? It's obviously matching up. But what happens is it continues with the 'else' code which is to add it to the database and send the emails. To be honest, I have no clue. I have my own filter setup that works differently than yours, but similar. Try this out: <?php $words = "cialis,viagra, levitor"; $wordList = explode(",", $words); $check[] = "The best part off waking up is wondering if you will wake up!"; $check[] = "The best part off waking up is having Cialis in your CUP!!"; $check[] = "The best part off waking up is having EverytHing in your CUP!!"; $check[] = "The best part off waking up is having ViagrA in your CUP!!"; $check[] = "The best part off waking up is having LevItOR in your CUP!!"; $check[] = "The best part off waking up is having NOTHING in your CUP!!"; function is_spam($check, $wordlist) { if (!is_array($wordlist)) { $wordlist = explode(",", $words); } foreach ($wordlist as $word) { $word = trim($word); // for good measure if (eregi($word, $check)) { return true; // this is spam } } return false; // must not be spam } // Run our unit test foreach ($check as $test) { if (is_spam($test, $wordList)) { echo $test . " has been flagged as spam<br />"; }else { echo $test . " has <b>NOT</b> been flagged as spam<br />"; } } ?> pending there are no syntax errors that has always worked for me. Quote Link to comment Share on other sites More sharing options...
simcoweb Posted June 13, 2007 Author Share Posted June 13, 2007 The CAPTCHA can prevent the bots but most of these are humans going right past it, unfortunately. A better way to discourage them is to see the look on their face when the form boots 'em out. After a dozen more tries they'll probably give up and go bug someone else. I'm trying to figure out why the code is not matching the words and executing properly. I'm not getting any errors but it's not working either in regards to comparing the entries in the form field with the banned words and exiting if found. Quote Link to comment Share on other sites More sharing options...
per1os Posted June 13, 2007 Share Posted June 13, 2007 form boots 'em out. After a dozen more tries they'll probably give up and go bug someone else. You would think so, but that is generally not the case. Trust me, it does not discourage anyone, they simply find new ways or you get new spammers that come in. One suggestion would be to limit the number of urls that could be posted in the comments. Generally spammers like to use alot > 3 but yea, some do not even use urls. At any rate, try the function I posted above and see if that works for you. Maybe easier to go with something that works than fix something that doesn't. Quote Link to comment Share on other sites More sharing options...
Yesideez Posted June 13, 2007 Share Posted June 13, 2007 The CAPTCHA can prevent the bots but most of these are humans going right past it I think you'll find MOST are actually bots! There are even bots that can read the capcha images. Some are pretty intelligent which can give the impression that a human sent the message. Quote Link to comment Share on other sites More sharing options...
per1os Posted June 13, 2007 Share Posted June 13, 2007 The CAPTCHA can prevent the bots but most of these are humans going right past it I think you'll find MOST are actually bots! There are even bots that can read the capcha images. Exactly some are too intelligent that it is easy to read captcha, so why implement a "fix" that will not work or will be depreciated in a few months in the first place ??? http://ploum.frimouvy.org/?150-the-invisible-captcha-mechanism-icm-against-form-spam A great article on how to prevent most bots without having that lame image interfere with real people trying to comment. If captcha is the way you also want to go. But I would implement the word filter either way, just be wary that someone could be talking about viagra legitimately depending on the article etc. Quote Link to comment Share on other sites More sharing options...
Yesideez Posted June 13, 2007 Share Posted June 13, 2007 The bottom rule is that no method will be 100% safe. If you make your method unique (like my guestbook) then you'll prevent most of them. Since adding the verification code in my guestbook I've had ZERO spam (I did gets loads!) I think calling the captcha image method "lame" going a bit far. The characters can overlap in my image which makes it extremely difficult for bots to read the image data especially when mixed with a background image. The contact form on my website is currently being attacked by bots (on average 10 emails a day) and when I added the same code that I used on my gueastbook the email spam went down to NIL. The argument of copy-protection on games can also be applied to spam-protection on guestbooks and contact forms. Go too extreme and users can't use the product. Quote Link to comment Share on other sites More sharing options...
per1os Posted June 13, 2007 Share Posted June 13, 2007 I think calling the captcha image method "lame" going a bit far. My opinions are educated with many bad experiences due to captcha. Namely, the amount of time it can take if someone implemented it wrong and if you guess the word wrong than you have to fill out forms again. Or they made the image insanely hard to read/see so that it is nearly impossible to get it right in the first 20 tries, hence "lame". It sucks filling out a form two or even three times, it sucks even worse trying to get the image correct and still failing after 20 tries because of how the creator setup the captcha. Captcha does work for the most part, for the most part. But there are other solutions, and there will need to be other solutions too as it was stated, bots get smarter every day and it is just a matter of time before captcha is rendered completely useless. It may be good to pioneer a new way which is less of hassle to the user. I still stand by my original comment, Captcha's are definitely lame. Quote Link to comment Share on other sites More sharing options...
simcoweb Posted June 13, 2007 Author Share Posted June 13, 2007 Heh, well I figured i'd spent enough time on this so I just integrated a CAPTCHA setup into the form. Works fine and we'll see if it stops the bulk of the spammers. I'm sure it'll have an impact. Honestly it's not my preferred method but I needed something in the interim until the real method is debugged. Once I get through with it the spammers will get biatch-slapped. frost, I didn't just disregard your 'spam' checker. I'm looking at that as well and how I can adapt it. What it was missing was the rejection I want ( IF spam GETTHEBOOT ) which is what I was trying to work out in my original code but couldn't seem to get it to work. In regards to a 100% solution, there may be one today. But by tomorrow those spamjerks will have it figured out and a way to bypass it I would, though, like to continue to create the banned word functionality and when I do i'll post back here. Based on the number of views and the sheer number of sites having forms affected by spammers (one of our clients has a shopping cart with customer product reviews which we had to turn off due to spammers) it could be a nice bit of code to share. Any ideas are welcome. Thanks to all that posted! You guys rock! Quote Link to comment Share on other sites More sharing options...
per1os Posted June 13, 2007 Share Posted June 13, 2007 Missing the rejection part...ummm that is the great thing about a function...check this out. <?php $words = "cialis,viagra, levitor"; $wordList = explode(",", $words); $check = "The best part off waking up is having Cialis in your CUP!!"; if (is_spam($test, $wordList)) { //header('location: bootspammer.html'); // Note the header code inside the if.. echo $test . " has been flagged as spam<br />"; echo "To boot them out place header code here!!!"; } function is_spam($check, $wordlist) { if (!is_array($wordlist)) { $wordlist = explode(",", $words); } foreach ($wordlist as $word) { $word = trim($word); // for good measure if (eregi($word, $check)) { return true; // this is spam } } return false; // must not be spam } ?> Either way man, good luck trying to debug that other function, especially when the one presented above does the same thing, except it actually works. Quote Link to comment Share on other sites More sharing options...
simcoweb Posted June 13, 2007 Author Share Posted June 13, 2007 frost, you rock, dude. Ok, couple of questions. Because there's SOOOOOOOO many words that need to be checked and the prospect that the list would grow weekly I felt it best to utilize an external file or possibly even a database for your $words variable/array. 2nd, the string to check is unknown until they post. So, my original snippet had: $check = trim($_POST['comments']); Can that method work... and... would it be wise to take the 'comments' posted content and also explode it and compare the $words with the $check? Quote Link to comment Share on other sites More sharing options...
per1os Posted June 13, 2007 Share Posted June 13, 2007 frost, you rock, dude. Ok, couple of questions. Because there's SOOOOOOOO many words that need to be checked and the prospect that the list would grow weekly I felt it best to utilize an external file or possibly even a database for your $words variable/array. 2nd, the string to check is unknown until they post. So, my original snippet had: $check = trim($_POST['comments']); Can that method work... and... would it be wise to take the 'comments' posted content and also explode it and compare the $words with the $check? Yes, I know I rock. You can create a table of words, but is unnecessary as all you would needs is one row with a LONGTEXT column type, and just house all the words there comma separated. Would probably run faster than pulling each word separately, whichever you want to go is your choice just as long as each individual word is an array. I do not call the word file inside the function due to that if you use it 2 or 3 times you are already less efficient, having them read into memory first and than running it 2 or 3 times is a lot more efficient. #2, see code below: <?php $words = "cialis,viagra, levitor"; $wordList = explode(",", $words); if (is_spam($_POST['comments'], $wordList)) { //header('location: bootspammer.html'); // Note the header code inside the if.. echo $test . " has been flagged as spam<br />"; echo "To boot them out place header code here!!!"; } function is_spam($check, $wordlist) { $check = trim($check); if ($check == "" || empty($check)) { return false; // nothing to check against } if (!is_array($wordlist)) { $wordlist = explode(",", $words); } foreach ($wordlist as $word) { $word = trim($word); // for good measure if (eregi($word, $check)) { return true; // this is spam } } return false; // must not be spam } ?> #3: It is not wise to explode it into it's own words as that would be less efficient and unnecessary as you would be running 2 loops when only 1 loop is required. As you can see this function works great with the string as a whole, no need to explode it at all, especially since user input can vary so much that anyone could easily defeat that if you use the explode feature. Hope that helps. Quote Link to comment Share on other sites More sharing options...
simcoweb Posted June 13, 2007 Author Share Posted June 13, 2007 I love that you're modest, too! :) Ok, I had to make a couple of tweaks (dare I say corrections?) to your snippet but got this to work: <?php $words = "cialis,viagra,phentermine"; $wordList = explode(",", $words); $check = trim($_POST['comments']); if (is_spam($check, $wordList)) { header("Location: reject.htm"); // Note the header code inside the if.. echo $check . " has been flagged as spam<br />"; // echo "To boot them out place header code here!!!"; exit; } else { ?> where you had the 'echo "To boot them out place header code here!!!"; had to be moved up or deleted since it caused a header error. I also had to change this: echo $test . " has been flagged as spam<br />"; as $test wasn't used anywhere but $check was. I may just turn this into an $error that would be displayed on the reject page. Not sure, though, since giving the spammer a clue as to what the word(s) was may not be a good idea. Anyway, with the 'tweaks' and your simple function I tested it and was able to successfully get redirected if using the wrong words in the comments box (even though they've used the name field for that as well but primarily the comments box is the one they flood) and also was able to get the spam error message to echo but at the expense of not having it redirect. That's why i'll probably turn it into an error that would display on the next page. Quote Link to comment Share on other sites More sharing options...
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.