Accessible Guestbook Script With SPAM Protection

Diese Seite auf Deutsch lesen.

Version

Current version: V4.0 (2013/08/14) - gb_v4.0.zip (205 KB)

News

The code is now written in object-oriented style. This means that the script's integration now works a little bit different. See the example file gb.php for more information. Furthermore you can set a timezone for the script since PHP5 requires a timezone setting which might not be set in all PHP environments.

See change log for more information.

Features

Installer

Should you run into trouble with the installer script you may also manually decompress "gb.zip" which is enclosed in the downloaded ZIP file and FTP its contents up to the server.

Since version 3.0 an installer script is shipped with the guestbook script. You can install the guestbook after uploading two files ("gb.zip" and "gb-install.php") to your webspace. Depending on which (sub-)directory the guestbook is supposed to get installed in the installer will create a new sub directory for the installation.

Should the installer script find an installation of an already existing version of this script it will offer you to download a backup file (in ZIP format) with the current installation inside. After that the installer will try to upgrade the data file to the new version.

If you upload the two mentioned files into your domain's documentRoot file can execute the installer from there directly (e.g. http://example.org/gb-install.php). The script will then create a new subdirectory while extracting the "gb.zip" file called "gb", in which the guestbook script will be be installed. You can then navigate to your guestbook under http://example.org/gb/gb.php.

After the installation process the installer script will delete "gb.zip" and itself from your webspace.

Integration

The script should be easy to integrate into an existing website. There are two sensible approaches to accomplish that:

  1. Simply use the enclosed gb.php script, which will output a complete HTML file to the browser. This script uses an HTML document (gb-template.html) as a template file, which can get customized completely. Since version 3.0 this file can be found in the base directory (usually "/gb") of the guestbook script. This way it is easier to verify any link destinations or image file references.
  2. If your website is already script-driven anyways you might want to include the guestbook script from within an already existing script which generates the HTML output instead of using the HTML template file. Then you won't need the script gb.php. You need to include the "core script" gb.script.inc which simply generates a <div> element with all the guestbook-related stuff inside.
    Since version 3.0 you can define a variable "$gb_no_direct_echo" (contains Boolean true or false) right before including the guestbook script so nothing gets echo-ed to the browser right away. Instead the HTML output gets stored in $GLOBALS['gb-script']['output'] which you can then send to the browser whenever your script sends data.
    Since version 4.0 the core script (gb.script.inc) no longer outputs anything but provides a class with which you can create an object which in turn provides the guestbook output. When you instantiate the object you can set an encoding with which the guestbook script's output will be created.

Everything can get styled using CSS. The basic code structure of the guestbook output looks like this:

<div id="guestbook">
<p class="menue"><a href="?gb_task=new_entry" class="new-entry">Sign guestbook</a> | entries 1 - 4 (von 4) | newer | older </p>
<dl>
    <dt><span>visitor</span> on 11/09/2008 at 12:15 o'clock</dt>
    <dd>My GB entry...</dd>
</dl>
</div>

The CSS file for the layout of this output is heavily commented, so customizing should be relatively easy - provided you do have some knowledge about CSS.

Admin Panel

Some of the most used functions can get configured inside the included admin panel. Until version 2.8 this was accessible via a subdirectory "edit" but now with version 3.0 this has been changed. Now you simply need to add a URL parameter "gb_admin" in order to get to the admin panel.

Let's say you want to access your admin panel and type "http://example.org/gb/gb.php?gb_admin" into your browser: a login form will appear where you can log into the admin panel.

You need to configure your guestbook via this admin panels first! Especially the login credentials must get changed!

You can also configure which words you don't want to read in your guestbook. This feature requires some knowledge about so-called regular expressions - but if you don't know what that is you can simply enter all the words (one per line) and that's OK, too.

For the automatic e-mail notification you can set the very address the notification is supposed to be ent to. There also is a switch to turn this feature on or off independently.

The moderated mode can be enabled in the admin panel. Using this mode means that new entries won't get displayed until they have been explicitely been approved of by an administrator.

The form where you can change the login data is new in the admin panel.

You can also define which language is supposed to be used as default (for all messages and captions). There also is the possibility to define some custom texts for some of these messages. At the moment only English and German are supported (support for Spanish is work in progress).

SPAM Protection

Since the user is forced to a first preview before the new entry gets accepted most automated entries get blocked because these "bots" simply don't understand this concept. This mechanism has been refined using sessions.

Installation

The ZIP file contains an archived directory called "put_these_online". The two files in this directory can be uploaded into any subdirectory of documentRoot but not in /cgi-bin/ oder any subdirectory of it!

The installer needs read and write access for the ZIP file so you might need to set the read/write permissions accordingly (your FTP client program will know more).

By calling the script "gb-install.php" via your browser you start the installation process. If you have uploaded the two files into "/main/pages/" then the installation can get started by typing the following URL into the address field of your browser: "http://example.org/main/pages/gb-install.php". After the installation the guestbook can be found under this URL: "http://example.org/main/pages/gb/gb.php".

After the installation you really must access the admin panel using the URL parameter "gb_admin" (so the complete URL looks like "http://example.org/main/pages/gb/gb.php?gb_admin") and enter new login data!!

If the installer script fails to successfully install the guestbook you can also do things manually. Unzip the contents of the downloaded ZIP file "gb_v30.zip", unzip the contained ZIP file "gb.zip" and upload this ZIP file's contents into a directory on your server (but not "cgi-bin" or a subdirectory of it!). You will need to set all read/write permissions of all XML files so the PHP script(s) can access them.

Demo

This website makes use of this very guestbook script. Try it out yourself if you'd like to send me some greetings: Sign my guestbook.

"Other Stuff"

Some first-aid hints if customization fails

Most e-mails I received were about a problem with an error message which looked somewhat like this:

Warning: session_start(): Cannot send session cache limiter - headers already sent...

Now how can this get fixed? You'll need to know a little more about PHP's session mechanism in order to fix this problem.

Understanding the problem

PHP's session mechanism is a means to identify a visitor when he or she "comes back". Just imagine a user who has entered some stuff into the form in order to leave a message in the guestbook. The server needs to show this user at least a first preview before the message gets accepted. Now how is the server supposed to know which user has already had a preview (and now wants his or her entry to get accepted) or not? Therefore PHP starts a session. If the user's browser is set to accept cookies the session ID gets stored in a cookie. If the user's browser doesn't accept any cookies then the session ID gets appended to the URL string (the part with "PHPSESSID=aRftGh8s2Lxw9...").

Using cookies is part of the HTTP protocol. When the user's browser sends a request to the server it will include any possible cookie data in the header of its request. The same goes for the server in the response. If cookie data is to be sent back to the browser it must happen in the HTTP header. This means that no HTML data must be sent prior to any HTTP header data.

If a PHP script has already sent any HTML data to the browser then the server will have sent any HTTP header data before this data automatically. If a script then wants to send session-related data to the browser this is no longer possible, because the data stream has already begun and the header has already been sent. This is the reason for the above error message.

Solution

So how can the problem get fixed after all? If you use scripts that make use of sessions then you need to hold back all possible output to the browser until everything is really ready to go! There is the possibility to use PHP's output buffering or simply make sure that no data gets sent to the browser until your script is ready to do so.

In some cases data still gets sent to the browser before the script is supposed to do so. The reasons for this seem dubious because according to the script's logic nothing should have been sent so far. In these cases make sure that in all your PHP files the first characters are in fact the ones to start a PHP script ("<php?") without any whitespace characters (or even HTML code!) before that. If you use UTF-8 encoding (like this guestbook script does) also make sure that you leave out the BOM (byte order mark) because this gets sent to the browser before the script can start any buffering.

Examples how in some cases "HTML data" gets send to the browser so even beginners of writing PHP scripts should see the problem:

------script.php------
<html>
<?php
include "head_script.php";
?>
...
</html>
----------------------

Now an approach with a less obvious problem:

------script.php------
 
<?php
include "head_script.php";
include "body_script.php";
include "gb.script.inc"; // GB script
include "footer_script.php";
?>
----------------------

Mind the empty line at the beginning of the second example! This line break character already gets interpreted and treated like "HTML data"! Here the HTTP header gets sent to the browser before the following script can get processed. So when the GB script finally gets included it can't set any HTTP headers anymore because they have already been sent.

Was my script useful to you?

Of course I'm happy if my script is useful not only for myself but for others, too. I appreciate feedback in e-mails especially if it gives me new ideas or ideas for improvements. Please try to solve your problems with my script(s) on your own as hard as you can first before you send me an e-mail for help.