Category: PHP Programming

Online Contact Forms

I’ve had online contact forms for a while on my websites, and one thing common from site to site is that spammers will get hold of them and start trying to use them to spam me with my own tool. It’s ridiculous. I’ve tried everything to remedy the problem, from making dynamic buttons that move to different locations on the page to the use of CAPTCHA. I’ve made the forms so hard that even a person reasonably intelligent couldn’t figure it out. Everything I tried failed. Yes, even blocking ip addresses and referers because all those can be spoofed reasonably easy.

I monitored, over several years, how these guys operate. I looked at it statistically and learned that spammers are fairly predictable with phrases and word use. Using CAPTCHA, or some other type of determent will not work. Spammers have bot scripts for just about every event and can crack most determents. Heck, they have even figured out Google’s silly text CAPTCHA. Spammers are extremely good at what they do.

Because we know that spammers, for the most part, use the same keywords and terminology from message to message it becomes apparent and quite reasonable that we should be able to block them, or at least, slow them down by triggering the keywords and phrases within our code. After testing several methods, the code I devised is the simplest and has been the most effective against spammers hitting my contact forms, and guestbooks.

Form Code:

<?php

//This is the usage of the function
//Always scrub your post variables
$msg = htmlspecialchars($_POST['fmrmsg'], ENT_QUOTES);

if(msgok($msg) == "GOOD"){

     //Do your form code here
      echo "No bad words, you're good to go!";
}else{
     //Failed the test, send them on a vacation.
     header('Location: http://www.disney.com');
     exit();
}

function msgok($usermsg) {
	include("includes/badwords.inc");

	$usermsg = strtoupper($usermsg);
	$tmpbad = strtoupper($badwords);
	$badwords = explode(",",$tmpbad);
	$ding = "GOOD";
	$i = 0;

	while (($ding == "GOOD") && ($i <= count($badwords)-1)){
		if (strpos($usermsg, $badwords[$i]) !== FALSE) {
			$ding = "BAD";
		}
		$i++;
	}
	return $ding;
}
?>

badwords.inc Code

<?php

//add words, separated by a comma and no spaces between the commas
//If the check returns true, the email or message will not be delivered
//so be very careful what you put in here.  The words are not case sensitive.

     $badwords = 'enter,bad,words,or bad phrases,here';

?>

With this code I get about 1 or 2 spam messages in a month from my online forms which isn’t bad when I see about 300 of those guys using the form multiple times a month. Email me for my dictionary to enter into the $badwords variable. This may not be the best way, but it is pretty effective.

Indexes - Rolling your own Unique

I am working on a rather large database for work and I came upon a dilemma that I just could figure out. I had 3 tables, one was a user info table whose id was an auto increment and unique. The second table was a list of groups that the users would be put into. The third table was the group mapping where it would pair the user id with the group id.

The thought is that if the user was already present then inserting into the table with the group pairs wouldn’t be a big problem. The auto id would already be made and could easily be inserted into the group pair table. What would happen if the user didn’t exist? How would I then insert it into the group pair table without the id existing for the user. Auto increment only increments after the record is added.

I tried many methods starting with @@IDENTITY but that didn’t work, then I came across SCOPE_IDENTITY() and thought, okay, problem solved. Well, it was short lived. When I inserted the user record with my INSERT query and then immediately ran scope_identity I got the ID I would get the last inserted id. Was real cool.

I thought that scope_identity worked off the last session, but soon found that it didn’t work very well with multiple users on a non persistent data connection…ugh. Alrighty then, even though all the sql db admins I asked said it should work, my testing showed otherwise. It wasn’t consistent enough for me.

After some consideration I decided to roll my own index, so I asked around and got some ideas. Some of the ideas seemed a little bloated others were just so complex that they were hard to understand. I believe that in many cases the simple solution might be the best. This is the code I came up with.

Generate the random ID

$rID = md5(mt_rand(1, 2048));
$id = md5($rID . microtime());

Then do a select to see if it is unique

$result = mysql_query("SELECT UID FROM members WHERE UID = '" . $id . "' LIMIT 1");
$cnt = mysql_num_rows;

With this in mind, I created a class that would check the db for duplicates and then release a new ID if there were no dupes.

<?php

include('dbconnect.php');
$Basic = new r_id;

echo $Basic->Getcnt();

class r_id{
     var $mid;
     var $cnt = 1;

     function Getid(){
          $rID = md5(mt_rand(1, 2048));
          $id = md5($rID . microtime());
          return $id;
     }

     function Getcnt(){
          while ($this->cnt > 0){
               $this->mid = $this->Getid();
               $result = mysql_query("SELECT UID FROM members WHERE UID = '" . $this->mid . "' LIMIT 1");
               $this->cnt = mysql_num_rows($result);
          }
          return $this->mid;
     }
}
?>

The ID will be a huge alphanumeric entry in this fashion - 47e509c01d97f7ee1df29ecf2b0a0e07; the chances of it ever being duplicated are slim. I’m sure someone could quantify its chance of being duplicated; don’t look at me to do it.

Simple PHP Image Upload

I consider myself a fairly descent programmer, not great by any means, but ok; anyway I spent the last three days struggling over a form that would upload a picture to mysql. It shouldn’t be a problem because it’s pretty basic, but I couldn’t get it to work. Why?!!! Gawd, it was frustrating the hell out of me. The form kept passing an empty array…over and over and over I worked with it making the simplest of script and still nothing. Then this morning it dawned on me. I had an epiphany…the harps and trumpets played in tandem at the back of my frustrated mind. *sigh* I was using $_POST and not $_FILES.

Anyhow, here is some simple code for anyone that wants it.

form.php

<?php

     if (!empty($_FILES['imgfile'])){
          echo '<form action="form.php" method="post" enctype="multipart/form-data" >
               <input type="file" name="imgfile">
               <input type="hidden" name="MAX_FILE_SIZE" value="1000000">
          </form>';
     }else{
          $image = $_FILES['imgfile'];
          //make sure this folder is writeable 666
          $path = '/home/user/public_html/images/';
          copy($image['tmp_name'], $path.$image['name']);
     }
?>

This simple script uploads a file, and then copies it from the temporary php upload directory to your permanent directory with its original name.

If you wanted to insert the object into a mysql database, then, to save space one would encode it - basically turn it into a text file - and insert the image into a field with type longtext. The code would look something like this. Again, this is pretty simple code and no error capture. Code takes off from above.

     copy($image['tmp_name'], $path.$image['name']);

     //open file for reading
     $fp = fopen($path.$image['name'], "r");

          //measure the file contents
          $contents = fread($fp, filesize($path.$image['name']));

     //close the file
     fclose($fp);

     //encode the file to save space in the db
     $encoded = chunk_split(base64_encode($contents));

     //my assumption is that you already have a db setup with a longtext field.
     mysql_query("INSERT INTO images (ID, IMAGE) VALUES (" . $id . ",'" . $encoded . "')");

     //since it's inserted into mysql, you can delete the existing file
     unlink($path.$image['name']);

So now, how do we view the file? Good question and I don’t know….

Nah, here you go

image.php

     <?php

     //My assumption is that you already have connected to the database somewhere
     //and the db has an id field
     $result=mysql_query("SELECT * FROM images WHERE ID='".$_GET['img']."'");

     //fetch data from database
     $data=mysql_fetch_array($result);

     $encoded=$data['data'];

     //close connection
     mysql_close($connection);

     //decode and echo the image data
     echo base64_decode($encoded);

?>

This is a simple usage of it.
<img src=”image.php?img=32″ border=”0″>