Return to my home page
This would be really funny if it wasn't happening to me.

Welcome Guest!
Login: 
Pass: 
Remember: 
Home
Why become a Member?
Become a Member
Privacy Policy
Random Joke
One-Liners
What's an Extradisambiguator?
View Guestbook
Sign Guestbook
Spammers List
Sudoku Solver
Write a Guestbook!
Threaded Blog
Links Page
Progenitor Page
Offer pages function
View HJTS MDO list
Search HJTS MDO list
  Write a Guestbook!

Introduction
OK, so there are many free providers of guestbooks out there, so why on earth would you want to write your own?
Well, there are a number of reasons, including:-
  • It's a good, relatively simple project that will introduce you to the concept of server-side coding using PHP and MySQL.
  • It means you can say that you wrote that part of your website yourself!
  • You can have your guestbook look exactly as you want it - no advertising, no undesirable links back to the hosting site, no learning how to customise that particular guestbook, and the like.
  • If you decide to use frames for your site, you can specify in the coding here that you want linked sites to open fresh windows, or throw away your frameset totally. It is usually considered bad form to "frame" someone's site in your frameset, but I have seen some guestbooks do exactly that when linking to external sites.
  • You can obfuscate people's e-mail addresses but still make them contactable through a clickable link. This is very important in this day and age when there are programs out there harvesting millions and millions of e-mail addresses for spamming purposes. You can shield your visitors from being harvested from your site. Please see my article about spam (new window) for more information regarding this problem.

You can probably think of more reasons than I have outlined here. In this article, I have been fairly basic in terms of what I have implemented, so be creative! Put something in that will make your guestbook yours, and not a clone of mine! You'll soon get a feel for what can and cannot be done.

This tutorial is intended for those who already have a working knowledge of HTML, although I am going to prefer XHTML. One day I'll write an article on converting from HTML 4.0 Transitional to XHTML 1.0 Transitional - it really is not too difficult. Having said that, those having a good working knowledge of HTML will see that the main differences are that code must be well-formed, i.e. all tags must be closed in the correct order, and that all tags must be closed, even those that do not have closing tags in HTML. This is why some of the tags (such as <br> becomes <br /> - the space follwed by '/' is used to denote the end tag.

Although some elements and tags will be explained, it will be generally assumed that you are able to write a simple page of HTML yourself.

So, with no further ado, let's get on with it!

Decide what you want
Before you even turn your computer on to start coding, think about how you want your guestbook to look. Think about how you want it to feel to the users who will use it. Scribble a layout out on paper, play with different backgrounds and colours, font styles and the like.
This step is very important as it will affect the design phase, and if you don't know what your end result is going to be like how can you write the code for it?
There is very little I can say here because everyone will want something slightly different; I'm not here to tell you what to do, instead I'm here to give you some technical guidelines on how to do it.

Design the user input form
This will be a standard HTML form that the user will fill out when he or she clicks on your "Sign my Guestbook" form. Basically, what we will do here is to have a basic form that will ask for the information we require, and then eventually this data will be sent to the guestbook database.
Let's say that we want to collect the following data:
  • Name
  • E-mail address
  • Website address
  • Verdict - radio buttons giving a general impression of the site
  • Comments

It is important to decide this information now for two reasons: firstly it will affect the form we are about to build, and secondly it will affect the fields, or columns, that we store in the database table.
Let's design a form that will look like this as far as the user input goes:-

Guestbook image 1

I'm only showing the user interface area as everything else will be dependent on your site - the header, the footer, the navigation etc. Remember that everything here will form a complete working project within the framework of your own site (i.e. HTML document type lines, document headers, and styling are all omitted), but it is still only an example of what you can do. You can see an example of what this can look like on this site by signing my guestbook.

You'll notice that some letters are underlined in the prompts. This is because I will be using "accelerator" keys - keys you can press with the ALT key to move the cursor directly to the field. There is an HTML element that permits this, and we'll see it in a little while. Note that this functionality does not work in certain older browsers though, such as Netscape Navigator 4.

Here is the code that produces the form layout above; this code can be placed into a file called feedback.php (remember that the HTML document type, header tags, etc. are not included):

<div align="center"><center>
<form method="post" action="gbookin.php">

<table border="1" cellpadding="5" bgcolor="#ffffcc"><tbody>
 <tr>
  <td><u>N</u>ame</td>
  <td><input type="text" name="guestname" size="60" maxlength="60" accesskey="N" /></td>
 </tr>
 <tr>
  <td>E-ma<u>i</u>l</td>
  <td><input type="text" name="guestemail" size="60" maxlength="60" accesskey="I" /></td>
 </tr>
 <tr>
  <td><u>W</u>ebsite</td>
  <td>
   <input type="text" name="guestsite" size="60" maxlength="60" value="" accesskey="W" />
  </td>
 </tr>
 <tr>
  <td colspan="2">
   <div align="center"><center>
    <table border="1" cellpadding="5" bgcolor="#ffff99"><tbody>
     <tr>
      <td align="center">What do you think<br />of this website?</td>
      <td align="center">
       <input type="radio" name="verdict" value="U" accesskey="u" />It s<u>u</u>cks
      </td>
      <td align="center">
       <input type="radio" name="verdict" value="O" checked="checked" accesskey="O" />
       It's <u>O</u>K
      </td>
      <td align="center">
       <input type="radio" name="verdict" value="C" accesskey="c" />It ro<u>c</u>ks</td>
      </tr>
    </tbody></table>
   </center></div>
  </td>
 </tr>
 <tr>
  <td colspan="2">
   <center>Please enter any co<u>m</u>ments in the box below<br />
    <textarea name="comments" rows="5" cols="56" accesskey="m"></textarea>
   </center>
  </td>
 </tr>
 <tr>
  <td colspan="2">
   <center>
    <input type="submit" name="submit" value="Sign it!" />
    &nbsp;&nbsp;
    <input type="reset" name="reset" value="Clear it!" />
   </center>
  </td>
 </tr>
</tbody>
</table>

</form>
</center></div>


This code is valid XHTML 1.0 Transitional, so if you are building your site to conform to that standard you should have no problems in copying and pasting that code directly.
Just one or two things to point out here:
  1. It is the "accesskey" attribute that lets you use the accelerator keys. The actual letters on the form must be underlined by way of <u> and </u> tags; just because they are specified as access keys does not make them display underlined automatically.
  2. The form has 'method="post"'; there are two main ways of passing information from page to page in PHP, one is called Get and the other is called Post. Get is beyond the scope of this article, as is an explanation of how Get and Post both work. But in your form it must be post, as in this example.
  3. The 'action="gbookin.php"' section specifies what will happen once the user has pressed the Send It button. It will take you to the page named - in this case gbookin.php held in the same path (directory) as this feedback form page (unless explicitly otherwise specified by giving the path in full).
  4. The names of the enterable fields are passed through as the variable names in PHP when the guestbook entry is added. For example, the name field is entered via a field called guestname, and when we come to pick this up for adding to the guestbook it will be called $guestname. This happens because we are using the 'post' method outlined earlier - more of that later.
Creating the Guestbook database table
OK, really you should design the data layout before anything else, but I wanted to build the form up first for two reasons: firstly (in this case) it defines the data that we want to store anyway, and secondly so we could begin to see some fruits of our labours before getting very far!

You can probably use some kind of graphical user interface to create the table, depending on how your hosting service works here. This will not be put into a webpage - this is something you will do once when you set the system up.

Almost certainly there will be provision to create the database table using MySQL syntax, so here is a create statement you might want to use, after any appropriate modifications:



CREATE TABLE  guestbook
(guestid      INT(6)         UNSIGNED NOT NULL AUTO_INCREMENT,
 guestname    VARCHAR(60),
 guestemail   VARCHAR(60),
 guestsite    VARCHAR(60),
 verdict      VARCHAR(1),
 comments     TEXT,
 visitdate    DATETIME       NOT NULL,
 PRIMARY KEY (guestid),
 UNIQUE INDEX guestbook_ux1 (guestid));


Basically, we want to create a table called 'guestbook', and it will have a total of seven fields, or columns in it. The first one is a special unique sequence number that will uniquely identify any record (row) that is created. We are specifiying that it must always have something in it (i.e. never be null (NOT NULL)), and that it will be automatically incremented every time a new row is added.

The other columns are the data we are going to store, as per the form we have just designed, plus the date / time of the user's visit.

Finally, the guestid column has been specified as the primary and unique key. Every MySQL database table needs a primary key, and it will usually be a unique key. It is my considered opinion that every database table you create should have at least one unique key so any given row can be individually identified as required - failing to do this may result in problems in more complex applications where it is simply not possible to guarantee that exactly one row will be returned where required, and complex work-around code then gets written to compensate for this lack of design thought.

In this case, we only have this one table, and it's a very simple application so no problems should arise ... we hope!

If you enter syntax directly to create the table, it's a good idea to save what you did into a text file for future reference. This way, if you need to check what columns you defined and how you defined them, you have the source text available at hand, and also if there is a problem and you mistakenly drop (delete) the table, you can at least easily recreate it (even though all your data will be lost).

Picking up your user input
The variables are passed through directly from the form (provided the PHP server setting REGISTER_GLOBALS is set). Thus a field entered called "guestname" can be referenced by the variable name $guestname, and so on. If REGISTER_GLOBALS is not set, you must access the variables using the construct


$guestname = $_POST['guestname'];


This second method will always work, whereas the first method will only work with REGISTER_GLOBALS set. Therefore, the second method is preferrable.

Inserting the data into the Guestbook and displaying it
Now we have the database table and the input form. When the user clicks the 'Sign it!' button, it would be really nice if the data entered was put into the guestbook table, and the user transferred to a page where he/she can see their own entry, placed above the other entries that are already there. So, how do we do this?

We have already seen that as soon as the Sign It button is clicked, the next thing that will happen is that the page specified in the form's action will be loaded. In this case it's guestin.php. It's this page that will do the insertion of the guestbook entry into the database table and display the guestbook's contents.

So, in guestin.php, here is what we need to do (remember that all PHP scripting must be enclosed in <?php and ?> tags):-

  1. Connect to the database.
    We can use the following piece of PHP script to do this:-


    mysql_connect(localhost,"username","password");
    @mysql_select_db("dbname") or die( "Unable to select database");
    


    The dbname is the name of your database; when you first set up your database you'll need to give it a name. Typically it must not have the same name as any other database hosted on that server, and any attempt to create a database with the same name as another will fail. If this happens, choose another database name. Once you've set up the database and given it a name, that's the name you use here.

    The username and password are a username and password that you have set up for this database; any username and password that have the required permissions is acceptable here. When you first set your database up, you will have created at least one user, and you may use that user. Don't worry about the password being in plain text here because this script is held in a file with a .php extension, thus will always be executed on the server - you cannot see the source code if you try to download it from the server because it will execute instead!

  2. Insert the guestbook entry.
    This is the 'guts' of what we are about here. The following statement will insert a new row into the guestbook table, the table we created earlier.


    // Get current date and time and plug into a variable
    $result = mysql_query("select now() visitdate");
    $visitdate = mysql_result($result, 0, "visitdate");
    // Insert the values into the guestbook
    $guestname = $_POST['guestname'];
    $guestemail = $_POST['guestemail'];
    $guestsite = $_POST['guestsite'];
    $verdict = $_POST['verdict'];
    $comments = $_POST['comments'];
    $query = "INSERT INTO guestbook VALUES
              ('', '$guestname', '$guestemail',
               '$guestsite', '$verdict',
               '$comments', '$visitdate')";
    mysql_query($query); // Insert values into the database
    


    Hopefully, that's fairly self-explanatory. However, just to point out a few things:

    Firstly, we want to get the date and time of the visitor's entry. We do this by way of 'SELECT now() visitdate'.

    The SELECT statement is passed to MySQL by way of the mysql_query function, and the result of the function is returned to the PHP variable $result.

    The name visitdate is a column alias - I've chosen to use this to keep variable names and the like consistent throughout the application. Note that there is not a comma between the now() and the visitdate - it is this which tells MySQL that visitdate is a column alias (another name by which another column is to be referred to on a temporary basis) and not a column in its own right.

    The variables themselves are picked up from the form by way of $_POST[...] ... note that the names given in the brackets are the same as those used on the form.

    On that, please note that I have chosen to use the same names on the form, as the variables, and on the database. This is not essential, but it makes tracking what's going where much easier when it comes to debugging!

    The INSERT statement breaks down as follows:-
    • You tell it to INSERT INTO the required table, in this case guestbook.
    • You can specify which columns you will be inserting if you are not inserting every column. In this case, we want to put something into each and every column so there is no need to do this.
    • You specify the VALUES you want to insert. The actual values themselves come as a set specified in round brackets, as in the example.
    • The actual values themselves come next, in the order specified when the table was created or in the order given in the second bullet point above, if present. The single quotes around the values are just that - text - and will serve to place the data from the variables into those quote marks. All string values in MySQL must be enclosed within single quote marks, and this is precisely what this is doing.
    • Note the '' for the first column ... what's that all about?
      It's because that first column was specified to be an auto-incremented column that will therefore be set up automatically by MySQL when new rows are added. We do not need to put anything in it, in fact must not put anything in it, but it is required.


  3. Display the guestbook contents.
    The following code can be used to display the guestbook. It is not yet finished, but it will do for now:-

    <div align="center"><center>
    <font color="ff0000" size="4">Guestbook</font>
    <br /><br />
    <?php
    /*
    // Get the guestbook data in so it can be
    // presented as an XHTML table
    */
    $result = mysql_query("select guestname, guestemail, guestsite
                                  verdict, comments, visitdate
                           from   guestbook
                           order by guestid desc");
    $numrows = mysql_numrows($result);
    for ($i = 0; $i < $numrows; $i ++)
    {
    	$guestname = mysql_result($result, $i, "guestname");
    	$guestemail = mysql_result($result, $i, "guestemail");
    	$guestsite = mysql_result($result, $i, "guestsite");
    	$verdict = mysql_result($result, $i, "verdict");
    	$comments = mysql_result($result, $i, "comments");
    	$visitdate = mysql_result($result, $i, "visitdate");
    	?>
    	<table border="1" cellpadding="5" bgcolor="#ffffcc">
    	<tr>
    	<td width="50%" bgcolor="#ffff99">
              <?php echo "$visitdate\n"; ?>
            </td>
    	<td width="50%" bgcolor="#ffff99">
    	<?php
    	if ($guestsite == "")
    	{
    		echo "No website supplied";
    	}
    	else
    	{
    		echo nl2br(htmlspecialchars(stripslashes($guestsite), ENT_QUOTES));
    	}
    	?>
    	</td>
    	</tr>
    	<tr>
    	<td width="50%" bgcolor="#ffff99">
             <?php
             echo nl2br(htmlspecialchars(stripslashes($guestname), ENT_QUOTES));
             ?>
             &nbsp;
            </td>
    	<td width="50%" bgcolor="#ffff99">
    	<?php
    	if ($verdict == "U" || $verdict == "u")
    	{
    		echo "It sucks\n";
    	}
    	else if ($verdict == "C" || $verdict == "c")
    	{
    		echo "It rocks\n";
    	}
    	else
    	{
    		echo "It's OK\n";
    	}
    	?>
    	</td>
    	</tr>
    	<tr>
    	<td colspan="2">
    	<p align="center">
    	<?php
    	if ($comments == "")
    	{
    		echo "(No comment made)";
    	}
    	else
    	{
    		echo nl2br(htmlspecialchars(stripslashes($comments), ENT_QUOTES));
    	}
    	?>
    	</p>
    	</td>
    	</tr>
    	</table>
    	<br /><br />
    	<?php
    }
    ?>
    </center></div>
    


    Note that this code is always dipping in and out of PHP, with static XHTML embedded within it.

  4. Disconnect from the database.
    This is very important, as it can clog the server up to leave database connections open all over the place. It's also very easy to do:-


    mysql_close(); /* Close connection to database! Very important! */
    


    That's all there is to it!

So we can put all that together into a complete document, and when the guestbook is signed, the new entry is entered and all the entries displayed in reverse chronological order (i.e. most recent first).

Displaying the Guestbook without Signing It
So far, the guestook can only be viewed immediately after it has been signed. That's not much good, is it?! We need to be able to view it without forcing it to be signed at the same time.

This one is easy to solve. Just have another page, for example called gbook.php, and let it only contain the code to connect to the database, display the guestbook, and disconnect from the database afterwards. In other words, it's a copy of the page that you get after signing the guestbook but without the code to insert a new entry.

That's simple enough to do, but there's a drawback. Supposing you want to change the display code, perhaps to make a change, an improvement, or fix a bug? You now have to make the change in two places! Not nice, and if there's one thing that most programmers hate intensely is having to make their changes more than once! So, how do we get round this?

The answer lies in "include files". We can take the piece of PHP that we want to re-use, and place it into a separate file all by itself. We then include it at the relevant points.

So, in this example, we can take the code that displays the guestbook and place it into a new file, called gbookvu.php for example. This code therefore resides in a file by itself, with nothing else in it at all:-

<?php ?>
<div align="center"><center>
<font color="ff0000" size="4">Guestbook</font>
<br /><br />

<?php
/*
// Get the guestbook data in so it can be
// presented as an XHTML table
*/
$result = mysql_query("select guestname, guestemail, guestsite,
                              verdict, comments, visitdate
                       from   guestbook
                       order by guestid desc");
$numrows = mysql_numrows($result);
for ($i = 0; $i < $numrows; $i ++)
{
	$guestname = mysql_result($result, $i, "guestname");
	$guestemail = mysql_result($result, $i, "guestemail");
	$guestsite = mysql_result($result, $i, "guestsite");
	$verdict = mysql_result($result, $i, "verdict");
	$comments = mysql_result($result, $i, "comments");
	$visitdate = mysql_result($result, $i, "visitdate");
	?>
	<table border="1" cellpadding="5" bgcolor="#ffffcc">
	<tr>
	<td width="50%" bgcolor="#ffff99">
         <?php echo "$visitdate\n"; ?>
        </td>
	<td width="50%" bgcolor="#ffff99">
	<?php
	if ($guestsite == "")
	{
		echo "No website supplied";
	}
	else
	{
		echo nl2br(htmlspecialchars(stripslashes($guestsite), ENT_QUOTES));
	}
	?>
	</td>
	</tr>
	<tr>
	<td width="50%" bgcolor="#ffff99">
         <?php
         echo nl2br(htmlspecialchars(stripslashes($guestname), ENT_QUOTES));
         ?>
         &nbsp;
        </td>
	<td width="50%" bgcolor="#ffff99">
	<?php
	if ($verdict == "U" || $verdict == "u")
	{
		echo "It sucks\n";
	}
	else if ($verdict == "C" || $verdict == "c")
	{
		echo "It rocks\n";
	}
	else
	{
		echo "It's OK\n";
	}
	?>
	</td>
	</tr>
	<tr>
	<td colspan="2">
	<p align="center">
	<?php
	if ($comments == "")
	{
		echo "(No comment made)";
	}
	else
	{
		echo nl2br(htmlspecialchars(stripslashes($comments), ENT_QUOTES));
	}
	?>
	</p>
	</td>
	</tr>
	</table>
	<br /><br />
	<?php
}
?>
</center></div>
<?php ?>


Now we replace that selfsame code in the gbookin.php file with the following:-

<?php
include("gbookvu.php");
?>


Now it's a good idea to copy gbookin.php to gbook.php (view-only version) and remove the insert code.

So at this stage we have a working guestbook! It is spread out across 4 files and one MySQL database. The files are: feedback.php (to collect the guestbook data), gbookin.php (to insert the entry and display the guestbook), gbook.php (to view the guestbook only), and gbookvu.php (the actual code to display guestbook entries).

We have got the complete file for gbookvu.php listed above, so for completeness here is the code for gbookin.php:-


/* Connect to the database */
mysql_connect(localhost,"username","password");
@mysql_select_db("dbname") or die( "Unable to select database");

/* Insert guestbook entry */
// Get current date and time
$result = mysql_query("select now() visitdate");
// Plug it into a variable
$visitdate = mysql_result($result, 0, "visitdate");
$guestname = $_POST['guestname'];
$guestemail = $_POST['guestemail'];
$guestsite = $_POST['guestsite'];
$verdict = $_POST['verdict'];
$comments = $_POST['comments'];
$query = "INSERT INTO guestbook VALUES
          ('', '$guestname', '$guestemail', '$guestsite',
           '$verdict', '$comments', '$visitdate')";
mysql_query($query); // Insert values into the database

/* Display the guestbook by way of include file */
include("gbookvu.php");

/* Disconnect from the database */
mysql_close(); /* Close connection to database! Very important! */


gbook.php will be identical to this except that there will be no code to insert values into the guestbook.

Making the Website Links Work
Note that the website URLs, if given, are not displayed as links. This means that they are not clickable. Fat lot of good having links to websites that are not links at all! What we need to do is modify the code that outputs them to make them into hyperlinks.
Find the following code in the view guestbook include file:


if ($guestsite == "")
{
	echo "No website supplied";
}
else
{
	echo nl2br(htmlspecialchars(stripslashes($guestsite), ENT_QUOTES));
}



and replace it with this:-


if ($guestsite == "")
{
	echo "No website supplied";
}
else
{
	echo "<a href=\"$guestsite\" target=\"_top\">";
	echo nl2br(htmlspecialchars(stripslashes($guestsite), ENT_QUOTES));
	echo "</a>";
}



That's all there is to it! Just a one line change! Test it out, and you'll see that the websites now become links. The 'target="_top"' will force the site to use the full browser window when opened, i.e. escape any frameset that your site might be using. You can use _blank instead of _top to cause the website to open in a new window. Doing one or the other is highly recommended, even if you are not using frames, because you may well make a future modification to your site that does involve frames, and you'll never know you've got the error until you discover it by mistake!

Making the Date and Time of visit look better
MySQL outputs dates and times in the following format:-
2003-07-21 08:45:39
That is, year-month-day, hours, minutes, and seconds. What would be nicer is a display such as the following:
21st July 2003 08:45
We don't want to see 21/07/2003 because it depends on which side of the Atlantic you are as to what it means. In the UK it means the 21st of the 7th month, 2003, whereas in the USA is means the 21st month, 7th day, 2003. OK, in this example it's obvious because there is no such thing as month 21. But supposing the date was 06/07/2003? Is that the sixth of July 2003 or June the 7th 2003? That's going to be mighty ambiguous, and as this site specialises in extradisambiguation, we need to ensure that that dates are fully disambiguated. So, let's modify the code to do it!
Find the line that outputs the date and time:


<td width="50%" bgcolor="#ffff99"><?php echo "$visitdate\n"; ?></td>


...and replace it with code such as the following:


<td width="50%" bgcolor="#ffff99">
<?php
$vyear = substr($visitdate, 0, 4); /* Visit year */
$vmonth = substr($visitdate, 5, 2); /* Visit month */
$vday = substr($visitdate, 8, 2); /* Visit day of month */
$vtime = substr($visitdate, 11, 5); /* Visit time */
$vday *= 1; /* Convert to number */
$vmonth *= 1; /* Convert to number */
$stndrd = "th"; /* Assume Nth */
if ($vday == 1 || $vday == 21 || $vday == 31)
{
	$stndrd = "st"; /* 1st, 21st, 31st */
}
if ($vday == 2 || $vday == 22)
{
	$stndrd = "nd"; /* 2nd, 22nd */
}
if ($vday == 3 || $vday == 23)
{
	$stndrd = "rd"; /* 3rd, 23rd */
}
if ($vmonth == 1) $dmonth = "January";
if ($vmonth == 2) $dmonth = "February";
if ($vmonth == 3) $dmonth = "March";
if ($vmonth == 4) $dmonth = "April";
if ($vmonth == 5) $dmonth = "May";
if ($vmonth == 6) $dmonth = "June";
if ($vmonth == 7) $dmonth = "July";
if ($vmonth == 8) $dmonth = "August";
if ($vmonth == 9) $dmonth = "September";
if ($vmonth == 10) $dmonth = "October";
if ($vmonth == 11) $dmonth = "November";
if ($vmonth == 12) $dmonth = "December";
echo "$vday$stndrd $dmonth $vyear $vtime\n";
?>
</td>


Hopefully there are enough comments in that to help you understand what is going on; I know the months conversion table is somewhat clumsy so maybe it would have been better to have used an array instead of this straight-line code!

Permitting visitors to be e-mailed
Now this one is interesting. Instead of making each name into a mailto link so you can click on them to send an e-mail, we're going to use an e-mail form instead.

Why do this? Well, two reasons. Firstly, not everybody uses e-mail software, thus clicking on a mailto link will have no effect or will attempt to fire up a program that is not used on that machine, and secondly (far more serious) is having e-mail addresses posted for all and sundry to see makes them available to spambots, programs that scour the Web looking for e-mail addresses to which they can send spam, or junk e-mail.

Everybody hates spam, except for the people who send it and the few who actually encourage the practice by purchasing from spammers, so this is a good trick to hide e-mail addresses away such that they can never be harvested in this manner. Nice, eh?

Where an e-mail address has been given, the name will be clickable. A form will then open up that lets you send e-mail. The guestid of the person to whom you are sending mail will be passed over using the GET method so the form knows which e-mail address to use.

In the guestbook view code, locate the following code fragment:-


$result = mysql_query("select guestname, guestemail, guestsite,
                              verdict, comments, visitdate
                       from   guestbook
                       order by guestid desc");
$numrows = mysql_numrows($result);
for ($i = 0; $i < $numrows; $i ++)
{
	$guestname = mysql_result($result, $i, "guestname");


and replace it with the following:-


$result = mysql_query("select guestid, guestname, guestemail,
                              guestsite, verdict, comments,
                              visitdate
                       from   guestbook
                       order by guestid desc");
$numrows = mysql_numrows($result);
for ($i = 0; $i < $numrows; $i ++)
{
	$guestid = mysql_result($result, $i, "guestid");
	$guestname = mysql_result($result, $i, "guestname");


This merely includes the guest ID in the select statement so it's available for use as a link from the guest's name.
Secondly, find the code that displays the guest's name:


<td width="50%" bgcolor="#ffff99">
 <?php
 echo nl2br(htmlspecialchars(stripslashes($guestname), ENT_QUOTES));
 ?>
 &nbsp;
</td>


and replace it with something such as this:


<td width="50%" bgcolor="#ffff99">
<?php
if ($guestemail != "")
{
	/* E-mail address given. Make a link using guestid, NOT e-mail address! */
	echo "<a href=\"email.php?guestid=$guestid\" target=\"_top\">";
	echo nl2br(htmlspecialchars(stripslashes($guestname), ENT_QUOTES));
	echo "</a>\n";
}
else
{
	/* No e-mail address supplied */
	echo nl2br(htmlspecialchars(stripslashes($guestname), ENT_QUOTES));
}
?>
 
</td>


Where no e-mail address has been given, the name is displayed as plain text. Where an e-mail address has been given, the name is made into a link to a page called email.php. Note the '?guestid=$guestid' after it - it is this that forms the "GET" method that will pass the guest ID through to the e-mail form page (email.php).

That's great .... terrific! Now we need to write the code in email.php to pick this up, allow a message to be entered, and an e-mail to be sent!

Handling the e-mail form
This is probably the trickiest part of the whole project. I'm going to have a new page, email.php, that will display the form and process the input entered thereon. Here is the entire active piece of code:


<div align="center"><center>
<?php

$gcount = count($_GET);  // Non-zero if come from guestbook
$pcount = count($_POST); // Non-zero if come from this same page
if ($gcount > 0)
{
	$guestid=$_GET['guestid']; /* Get the guestID from the URL */
	$questid *= 1; // Make sure it's a number
}
else
{
	$guestid = 0; // POST method used, or an error has occurred
}
if ($guestid > 0)
{
	$query = "select guestname, guestemail
                  from   guestbook
                  where guestid=".$guestid;
	$result = mysql_query($query); // Get required Guestbook entry
	$numrows = mysql_numrows($result); // Ensure sensible result
	if ($numrows >= 1)
	{
		// We have a row: get its details
		$guestname = mysql_result($result, 0, "guestname");
		$guestemail = mysql_result($result, 0, "guestemail");
	}
	else
	{
		$guestid = 0; // Use guestid as a flag to indicate duff
	}
}
if ($guestid > 0)
{
	// Have a sensible result - build form to send e-mail from
	?>
	<font color="ff0000" size="4">Send e-mail to
         <?php
         echo htmlspecialchars(stripslashes($guestname), ENT_QUOTES);
         ?>
        </font><br /><br />
	<form method="post" action="<?php echo "$php_self"; ?>">
	<table border="1" cellpadding="5" bgcolor="#ffffcc"><tbody>
	 <tr>
	  <td>Your <u>N</u>ame</td>
	  <td><input type="text" name="yourname" size="60" maxlength="60" accesskey="N" /></td>
	 </tr>
	 <tr>
	  <td>Your E-ma<u>i</u>l</td>
	  <td><input type="text" name="youremail" size="60" maxlength="60" accesskey="I" /></td>
	 </tr>
	 <tr>
	  <td colspan="2">
	   <center>Please enter your <u>M</u>essage here<br />
	    <textarea name="message" rows="5" cols="56" accesskey="m">
            </textarea>
	   </center>
	   <input type="hidden" name="guestid" value="<?php echo "$guestid"; ?>" />
	  </td>
	 </tr>
	 <tr>
	  <td colspan="2">
	   <center>
	    <input type="submit" name="submit" value="Send it!" />
	    &nbsp;&nbsp;
	    <input type="reset" name="reset" value="Clear it!" />
	   </center>
	  </td>
	 </tr>
	</tbody>
	</table>
	</form>
	<?php
}
else
{
	// No rows returned;
	// either we have an error or it's the POST route
	if ($pcount > 0)
	{
		// POST used; send the e-mail
		$numrows = 1; /* Assume it will be good */
		$yourname = $_POST['yourname'];
		if ($yourname == "")
		{
			echo "You have not given your name!  No e-mail will be sent<br />\n";
			$numrows = 0; /* Bu hao */
		}
		$youremail = $_POST['youremail'];
		if ($youremail == "")
		{
			echo "You have not given your e-mail address!  No e-mail will be sent<br />\n";
			$numrows = 0; /* Bu hao */
		}
		else
		{
			if (!eregi("^[_a-z0-9-]+(\.[_a-z0-9-]+)*@[a-z0-9-]+(\.[a-z0-9-]+)*(\.[a-z]{2,3})$", $youremail))
			{
				echo "Your e-mail address is not valid!  No e-mail wil be sent<br />\n";
				$numrows = 0; /* Bu hao */
			}
		}
		$message = $_POST['message'];
		if ($message == "")
		{
			echo "No message has been entered.  No e-mail will be sent<br />\n";
			$numrows = 0; /* Bu hao */
		}
		if ($numrows == 1)
		{
			$guestid = $_POST['guestid'];
			$query = "select guestname, guestemail from guestbook where guestid=".$guestid;
			$result = mysql_query($query); // Get the required Guestbook entry
			$numrows = mysql_numrows($result); // Ensure we have a sensible result
		}
		if ($numrows >= 1)
		{
			// We have a row: get its details
			$guestname =  mysql_result($result, 0, "guestname");
			$guestemail = mysql_result($result, 0, "guestemail");
			$from = "From: \"".$yourname."\" <".$youremail.">\n";
			$sendit = mail($guestemail, "Contact from Extradisambiguator guestbook", $message, $from);
			if ($sendit)
			{
				echo "Message sent successfully!\n";
			}
			else
			{
				echo "Your message was not sent. ";
				echo "Error code $sendit returned\n";
			}
		}
		else
		{
			echo "Unfortunately an error occurred; the e-mail could not be sent.\n";
		}

	}
	else
	{
		// No rows returned; we have an error
		echo "Unfortunately an error has occured, and no e-mail can be sent.\n";
	}
	?>
	<br /><br />
	Please <a href="gbook.php">click here</a>
        to return to the Guestbook
	<br /><br />
	<?php
}
?>
</center></div>


I'm not going to give a blow-by-blow account of what each line is doing, but rather give an overview of what is going on so you can gain an understanding.

Firstly, we need to see how many _GET and _POST entries there are. Either one or the other will be non-zero; they will not both be zero or both non-zero. If the number of _GETs is non-zero, this indicates we have come in from the guestbook, whereas if the number of _POSTs is non-zero, this implies that the Send e-mail button has been clicked. The required behaviour is entirely different for each path.

If we have come in from the guestbook (number of _GETs is greater than zero), then we need to get the guestid from the addressbar (the page will have been called with "?guestid=99" - that numeric value represented by 99 will come in via $_GET['guestid'].

This can then be used to pick up details for the person to whom an e-mail is to be sent from the database - guestid is a unique key so we should get one, and only one, row when the database is queried. If there is an error, set the variables to indicate the fact and drop out.

Normal HTML (XHTML) can then be used to display the e-mail form; there is nothing new here except for the action of the form. Here, I want to come back to the selfsame page once the "Send It" button is clicked, and we can either do this by explicitly giving the name of this page again or by echoing the server variable $SERVER['PHP_SELF'], which contains the name of the current page. This is preferrable because if the name of this page is changed, you don't have to hunt for this to change it also.

When the "Send It" button is clicked, the page is re-entered but this time the number of _POST entries will be greater than zero, while the number of _GET entries will be zero. This can be used to indicate that the page has been re-entered. Clever, no?

Now some variables are set up that will enable us to send the required e-mail: $_POST['yourname'] will contain the name of the person sending the mail, $_POST['youremail'] will contain that person's e-mail address, and so on. These have come in from the e-mail form that was just filled in, and is exactly the same technique that was used for picking up the guestbook entry details for insertion into the guestbook.

There is a degree of validation going on to make sure the person filling up the form provides a name and e-mail address as well as a message. It is thus possible to prevent someone from sending silly empty e-mails. Furthermore, a modicum of e-mail address validation is performed (see that horrendous line using the PHP eregi() function - it is well beyond the scope of this article to provide a discussion on 'regular expressions'). However, the manner in which the validation is performed here is not ideal as it does not allow the user to go back and correct mistakes. This will be left, as they say, as an exercise for the reader; it involves a degree of re-arranging the code and judicious setting of the flags to get this to work properly.

Finally, once all the data has been collected, we can use the PHP mail() command to send the message itself!

The mail() command takes 4 parameters:
  1. The e-mail address of the person to whom the message is to be sent
  2. The subject of the e-mail. In this case we're using fixed text
  3. The actual message body itself
  4. The headers, usually the name and e-mail address of the sender. Note the "\n" at the end of this field; it is essential that this is included. I've used the format 'From: "NAME" <EMAILADDR>\n' here. If you omit the "\n" at the end, your message will fail.
The result is tested, and an appropriate message output to indicate whether the message was sent successfully or not.

Finally, we have a clickable link to let the visitor return to the guestbook. Hardly rocket science!

Validating the Guestbook Data
We need to carry out some basic validity checks on the Guestbook data input. Basically this means making sure the user has entered a name, some comments, and if an e-mail address has been entered that it looks valid. If anything is missing or considered to be duff, then we ought to re-present the form to the user so appropriate modifications can be made.

Unfortunately, this is going to be a bit tricky. This is partly because of the way the project has been designed so-far, so this will have to be shoehorned in using the cleanest methods possible. Let's tackle it this way:
The file feedback.php contains the XHTML to input the form and send it off for processing. This is the page that contains the following XHTML code:

<div align="center"><center>
<form method="post" action="gbookin.php">
...
...
</form>
</center></div>


The two main changes we need to make to the form are (a) pre-prompt any values that have already been entered and (b) display a one-line error message explaining what was wrong.

To this end, let's modify the whole form as follows:

<div align="center"><center>

<?php
$selected = "selected=\"selected\"";
if (!isset($guestname)) $guestname = "";
if (!isset($guestemail)) $guestemail = "";
if (!isset($guestsite)) $guestsite = "";
if (!isset($verdict)) $verdict = "O";
if (!isset($comments)) $comments = "";
if (!isset($errmes)) $errmes = "";
if ($errmes != "") echo "$errmes<br />"; // Output any error message present
?>

<form method="post" action="gbookin.php">
<table border="1" cellpadding="5" bgcolor="#ffffcc"><tbody>
 <tr>
  <td><u>N</u>ame</td>
  <td><input type="text" name="guestname" size="60" maxlength="60" accesskey="N" value="<?php echo "$guestname"; ?>" /></td>
 </tr>
 <tr>
  <td>E-ma<u>i</u>l</td>
  <td><input type="text" name="guestemail" size="60" maxlength="60" accesskey="I" value="<?php echo "$guestemail"; ?>" /></td>
 </tr>
 <tr>
  <td><u>W</u>ebsite</td>
  <td>
   <input type="text" name="guestsite" size="60" maxlength="60" value="" accesskey="W" value="<?php echo "$guestsite"; ?>" />
  </td>
 </tr>
 <tr>
  <td colspan="2" >
   <div align="center"><center>
    <table border="1" cellpadding="5" bgcolor="#ffff99"><tbody>
     <tr>
      <td align="center">What do you think<br />of this website?</td>
      <td align="center">
       <input type="radio" name="verdict" value="U" accesskey="u" <?php if ($verdict == "U") echo "$selected"; ?> />It s<u>u</u>cks
      </td>
      <td align="center">
       <input type="radio" name="verdict" value="O" checked="checked" accesskey="O" <?php if ($verdict == "O") echo "$selected"; ?> />
       It's <u>O</u>K
      </td>
      <td align="center">
       <input type="radio" name="verdict" value="C" accesskey="c" <?php if ($verdict == "C") echo "$selected"; ?> />It ro<u>c</u>ks</td>
      </tr>
    </tbody></table>
   </center></div>
  </td>
 </tr>
 <tr>
  <td colspan="2">
   <center>Please enter any co<u>m</u>ments in the box below<br />
    <textarea name="comments" rows="5" cols="56" accesskey="m"><?php echo "$comments"; ?></textarea>
   </center>
  </td>
 </tr>
 <tr>
  <td colspan="2">
   <center>
    <input type="submit" name="submit" value="Sign it!" />
    &nbsp;&nbsp;
    <input type="reset" name="reset" value="Clear it!" />
   </center>
  </td>
 </tr>
</tbody>
</table>

</form>
</center></div>


The differences between this and the original version is the presence of some embedded PHP within the table. Note the use of a potentially non-existent variable, $errmes. If this exists and has something in it then it will contain an error message advising the user what the problem is. The code to set this up is now about to be written.

In the file gbookin.php, the page that is called when the form is submitted, changes need to be made to ascertain whether the input is valid, and if not, send the user back to the form to make corrections. To do this, we need to pick up ans validate the user's entry BEFORE the HTML headers are sent to the browser - this means even before the document type is declared. Here's one way this may be achieved:



$errmes = ""; // Let's assume there will be no problems
$guestname = (isset($_POST['guestname'])) ? $_POST['guestname'] : "";
if ($guestname == "") $errmes = "You didn't enter your name!<br />\n";
$guestemail = (isset($_POST['guestemail'])) ? $_POST['guestemail'] : "";
if ($guestemail != "")
{
 if (!eregi("^[_a-z0-9-]+(\.[_a-z0-9-]+)*@[a-z0-9-]+(\.[a-z0-9-]+)*(\.[a-z]{2,3})$", $guestemail))
 {
  $errmes = "Your e-mail address is not valid!<br />";
 }
}
$guestsite = (isset($_POST['guestsite'])) ? $_POST['guestsite'] : "";
$verdict = (isset($_POST['verdict'])) ? $_POST['verdict'] : "O";
$comments = (isset($_POST['comments'])) ? $_POST['comments'] : "";
if ($comments == "") $errmes = "You didn't enter any comments!<br />\n";

if ($errmes != "")
{
 include ("feedback.php");
}
else
{
 // Send the document type, and HTML headers here
 ...
 
 // Now insert the Guestbook entry and display it
 mysql_connect(localhost,"username","password");
 @mysql_select_db("dbname") or die( "Unable to select database");
 // Get current date and time and plug into a variable
 $result = mysql_query("select now() visitdate");
 $visitdate = mysql_result($result, 0, "visitdate");
 // Insert the values into the guestbook
 $query = "INSERT INTO guestbook VALUES
           ('', '$guestname', '$guestemail',
            '$guestsite', '$verdict',
            '$comments', '$visitdate')";
 mysql_query($query); // Insert values into the database
 include("gbookvu.php");
 mysql_close(); /* Close connection to database! Very important! */

 // Send the end tags for the HTML body section here
 ...
}


Basically, we're picking up the user's input and validating it before committing ourselves to anything. If the input is invalid, we re-prompt for the missing data by including the form (now the variable $errmes which was missing before is now present) whereas if the data was valid, we proceed as before.



Known Issues
There are a couple of problems I have yet to find a way round. As and when I discover a solution, this tutorial will be updated to take them into account. These are as follows:
  • On the page that inserts your guestbook entry and displays the entire guestbook, using the browser's "refresh" button can cause you to double-post. You may get a question asking you to re-send the data, and if you click yes you'll get your guestbook entry posted twice! This needs to be prevented.
  • Once an e-mail has been sent, it is possible to keep clicking on the browser's refresh button and re-sending the e-mail. Prevent this if possible.

Top of this page      Extradisambiguator home      Check out my Original Website
* Page built in 9 milliseconds *
  • clit

  • ,
  • pregnant women porn

  • ,
  • 16 year old sluts

  • ,
  • tanned

  • ,
  • facial

  • ,
  • swap top hobby saw

  • ,
  • navy blue schoolgirl knickers

  • ,
  • in the ass

  • ,
  • masterbating housewives

  • ,
  • female masturbation with dildo

  • ,
  • nylon stocking fetish nylon fetish

  • ,
  • silicone breast implant approval

  • ,
  • hot lingerie plus size

  • ,
  • beautiful shaved pussy

  • ,
  • fat naked chicks

  • ,
  • female elf

  • ,
  • free female celebs nude

  • ,
  • forced to fuck

  • ,
  • youth at risk bakersfield

  • ,
  • free cfnm pics and vids

  • ,
  • Maid

  • ,
  • dating direct

  • ,
  • ffx hentai

  • ,
  • no smoking ads

  • ,
  • ebony mature

  • ,
  • teens feet

  • ,
  • throat

  • ,
  • adult cartoons

  • ,
  • xxx

  • ,
  • ass bitches

  • ,
  • shemale clips

  • ,
  • uniform

  • ,
  • amateur sex tape

  • ,
  • porn oral sex

  • ,
  • Asshole

  • ,
  • dad daughter xxx

  • ,
  • wiccan tattoo designs

  • ,
  • grouality porn

  • ,
  • low voltage outdoor lights

  • ,
  • huge mature bbw

  • ,
  • men wearing panties groups

  • ,
  • bbw cum facial

  • ,
  • gay male escort

  • ,
  • fat ass in a thong

  • ,
  • asian femdom

  • ,
  • chubby chick porn

  • ,
  • latina handjobs

  • ,
  • free sample hentai movies

  • ,
  • kinky nurse fetish

  • ,
  • free patterns doll clothes toys

  • ,
  • sylvia plath reads

  • ,
  • denise richards porn

  • ,
  • bouncy boob

  • ,
  • free fat women porn

  • ,
  • model a head stud

  • ,
  • maid lesbian

  • ,
  • outdoor xxx

  • ,
  • paparazzi picture of naked celebrity

  • ,
  • adult home party

  • ,
  • female masturbation cam

  • ,
  • disposable speculum vaginal

  • ,
  • bleeding pussy

  • ,
  • young boys in speedos

  • ,
  • gothic bondage

  • ,
  • close-up shaved pussy

  • ,
  • herbal remedy for strep throat

  • ,
  • lindsey lohan nude

  • ,
  • ejaculate skin youth treatment face

  • ,
  • gay redhead porn

  • ,
  • cum on her face rikki

  • ,
  • dirty dozen brass band

  • ,
  • natural saggy tits

  • ,
  • female feet on tv

  • ,
  • female circumcision

  • ,
  • secretaries lesbian

  • ,
  • bbw search engine

  • ,
  • pussy with dildo

  • ,
  • naughty office girls

  • ,
  • reality european sex

  • ,
  • free picture galleries of ffm threesomes

  • ,
  • bisexual jacksonville

  • ,
  • appleton wisconsin realty offices

  • ,
  • japanese nurse sluts

  • ,
  • fat and skinny lesbian sex

  • ,
  • upskirt mania

  • ,
  • sims virtual dating

  • ,
  • casey cam nude

  • ,
  • adult dvd and vista

  • ,
  • wa

  • ,
  • body stocking lingerie

  • ,
  • low cut thongs g strings

  • ,
  • big clit cunt free

  • ,
  • best scat sites

  • ,
  • Stocking

  • ,
  • sunshine socal coeds

  • ,
  • spanking fetish

  • ,
  • natural melons movies

  • ,
  • download ebony sex

  • ,
  • hot latin chicks

  • ,
  • tanned naked women

  • ,
  • naked on beach

  • ,
  • old fisting

  • ,
  • simpsons cartoon porn free

  • ,
  • black gay chat

  • ,
  • adult video game

  • ,
  • celebrety anal

  • ,
  • brazil sex girls

  • ,
  • swallow blowjobs

  • ,
  • news audio clips

  • ,
  • big jizz tit

  • ,
  • cast of desperate housewifes

  • ,
  • young

  • ,
  • milf group sex

  • ,
  • clit free pic pierced

  • ,
  • brunettes blowjob

  • ,
  • female military and clipart

  • ,
  • hustler lawn tractors

  • ,
  • 6 forced

  • ,
  • lowered quality sample movies gangbang

  • ,
  • nude pool party

  • ,
  • college reality sex sites

  • ,
  • jizz huge

  • ,
  • sexy redhead pics

  • ,
  • ethnic men fuck

  • ,
  • nude male video

  • ,
  • animal and xxx and brazil

  • ,
  • lip nipples pierced pussy w woman

  • ,
  • german schoolgirl

  • ,
  • bone my wife

  • ,
  • shemale maids

  • ,
  • free disney xxx

  • ,
  • dick sucking

  • ,
  • child ass

  • ,
  • fat woman sex

  • ,
  • free gospel video clips

  • ,
  • xxx slut

  • ,
  • enormous natural boob

  • ,
  • teenage porn

  • ,
  • free asshole licking pics

  • ,
  • split toe nail cause

  • ,
  • paris hilton blowjob movie

  • ,
  • chick trans

  • ,
  • nude ladies

  • ,
  • huge gay black cocks

  • ,
  • scat bus

  • ,
  • forever live and die

  • ,
  • hentai manga xxx hard adult

  • ,
  • military men fucking

  • ,
  • femdom nurse

  • ,
  • tit gigantic melon jugs

  • ,
  • ffm amateur 3

  • ,
  • sex amateur

  • ,
  • japanese lesbians

  • ,
  • orgasm mpeg

  • ,
  • self anal masturbation

  • ,
  • female hard nipples

  • ,
  • erotica gallery toons

  • ,
  • mom daughter nude

  • ,
  • football jock studs

  • ,
  • deep throat dvd