Category Archives: Web Site Dev

Posts concerning web site design and development. Examples of php, xhtml, and javascript code. Wordpress-related posts may be cross-categorized here, but also have their own category.

A little over a year ago, I wrote a post about a PHP script I had created for protecting a download using a unique URL. The post turned out to be pretty popular, and many of the comments included requests to extend the script in useful ways. So, I’ve finally gotten around to updating the script to generate multiple URLs (up to 20) at a time, to allow different files to be associated with different keys, and to allow brief notes to be attached to the download key.

I’ve also added a simple page that prints out a list of all of the keys generated the date and time that each key was created, the filename of the download on the server that the key accesses, the number of times the key was used, and any attached note. This should make it easier to generate gobs of keys, drop them into an Excel spreadsheet, and help the files’ owner keep track of who’s getting which file, and how often.

The scripts themselves are a little more involved this time around, but the general idea is the same. A unique key is generated and combined with a URL that allows access to a single file on the server. Share the URL/key instead of the URL to the file itself to allow a visitor to download the file, but not to know the location of the file. The key will be valid for a certain length of time and number of downloads, and will stop working once the first limiting condition is met. This should prevent unauthorized downloading due to people sharing the keys.

How it works

There are six main components to this system:

  1. the MySQL database that holds each key, the key creation date and time, the maximum age of the key, the number of times the key has been used, the maximum times the key may be used, the file associated with the key, and the note attached to the key, if any
  2. a generatekey.php page that generates the keys and outputs the corresponding unique URLs
  3. a download.php page that accepts the key, checks its validity, and either initiates the download or rejects the key as invalid
  4. a report.php page that returns all of the data in the database
  5. a config.php file that contains variables such as number of downloads allowed, the maximum allowable age of the key, and the filenames of the downloads, along with the database connection information
  6. the .zip file(s) to be protected

The files

The files, along with two example downloads, are available for download as a .zip file.

Download the protecting multiple downloads PHP script

The MySQL database

Using whatever method you’re comfortable with, create a new MySQL database named “download” and add the following table:

CREATE TABLE `downloadkeys` (
  `uniqueid` varchar(12) NOT NULL default '',
  `timestamp` INT UNSIGNED,
  `lifetime` INT UNSIGNED,
  `maxdownloads` SMALLINT UNSIGNED, 
  `downloads` SMALLINT UNSIGNED default '0',
  `filename` varchar(60) NOT NULL default '',
  `note` varchar(255) NOT NULL default '',
  PRIMARY KEY (uniqueid)
);

How to use the scripts

The scripts require a little setup before they’re ready to be used, so open config.php in your text editor of choice.

Change the values for $db_host, $db_username, $db_password, $db_name to point to your database.

Set the variable $maxdownloads equal to the maximum number of downloads (actually, the number of page loads).

Set the variable $lifetime equal to the keys’ viable duration in seconds (86400 seconds = 24 hours).

Set the variable $realfilenames to the real names of actual download files on the server as a comma-separated list (this is optional; you can also use a single filename or just leave it as empty double-quotes: “”). If you have more than one file to protect, enter the names as a comma-separated list and the script will create a drop-down menu as the Filename field. If you leave the variable blank, the form will display an empty input box as the Filename field.

Set the variable $fakefilename to anything – this is what the visitor’s file will be named when the download is initiated.

I would strongly recommend renaming generatekey.php, as anyone who can view it will be able to create unlimited numbers of keys, and worse, they’ll be able to see the filenames (if you set them in config.php). I would also recommend that the directory you put these files into, and each directory on your site (/images, /css, /js, etc.), contain an index.html file. This is a simple security measure that will prevent visitors from snooping around a directory and viewing its contents (though access to the directory contents is usually prohibited by a setting on the server).

Place all the PHP scripts and your .zip file(s) into the same directory on your server.

That’s all there is to it. Whenever you want to give someone access to the download, visit the generatekey.php page and fill out the form. It will generate a key code, save it to a database, and print out a unique link that you can copy and paste into an email or whatever. The page that the unique link points to checks to see if the key code is legitimate, then checks to see if the code is less than X hours old, then checks to see if it has been used less than X times. The visitor will get a descriptive message for the first unmet condition and the script will terminate. If all three conditions are met, the download starts automatically.

Errors and issues

Note: The download will not initiate automatically, and will actually be output as text on the page, if the download.php page is changed to send headers or any output to the browser. Be careful when making modifications or incorporating this script into another page.

Check the HTTP headers (Google for an online service that does this, or install the LiveHTTPHeaders Firefox plugin) of the download link. If the script is working correctly, you should see Content-Transfer-Encoding: binary and Content-Type: application/octet-stream in the headers. If you’re getting a page of text instead of the zip file, you’ll probably see Content-Type: text/html.

Example HTTP headers for a correctly working download

If the script is working correctly, the HTTP headers will look something like this:

HTTP/1.1 200 OK
Date: Sun, 20 Jun 2010 13:31:50 GMT
Server: Apache
Cache-Control: must-revalidate, post-check=0, pre-check=0, private
Content-Disposition: attachment; filename="bogus_download_name.zip"
Content-Transfer-Encoding: binary
Pragma: public
Content-Length: 132
Keep-Alive: timeout=15, max=100
Connection: Keep-Alive
Content-Type: application/octet-stream

I’ve finally opened a Twitter account, so you can follow me at http://twitter.com/ardamis. As a social experiment, it’s interesting to watch and discuss, but I haven’t really participated much. On the other hand, I’m very interested in the phenomenon of URL shortening. So, without too much trouble, I put together yet another URL shortening service: Minifi.de (‘minified’, in the jargon). It does pretty much the same thing as tinyurl.com, bit.ly and is.gd – you enter a long URL and it returns a shorter one. I’m about 50% done with the API (it works, so long as the URL valid), so if anyone knows of any clients that allow the user to specify a shortening service, I’d like to test that functionality. I have plans to make it account-based, so that you can track usage statistics and such, but that will only happen after I’m confident that the thing will survive in the wild.

So, feel free to give it a whirl, but know that it’s still in development and that I’ll probably have to wipe the database a few more times before I get it just right.

Well, I’ve been sitting on this adaptation of my Broadway Plogger theme for too long. It hasn’t been fully tested, but it seems to work. It’s a dark theme that uses the popular Lightbox 2 JavaScript script to open medium-sized images over the thumbnails page. This means that there is no getting to the full-sized image.

Plogger 3 theme: Broadway screenshot

Anyway, if you’ve been looking for a Lightbox 2 supporting Plogger theme, please give this one a try.

Download the “Broadway 2 + Lightbox” Plogger theme

Update 12/19/09: I’ve updated the theme to be compatible with the recently-released Plogger v.1.0. If you’re running an earlier version, I would recommend that you update to the current stable release.

I was installing PHP 5 on an IIS 6 server when I ran into what turns out to be a pretty common problem. PHP appeared to be installed correctly, but browsing to any page with a .php extension returned a 404 Page Not Found error. While the steps below fixed this for me, I had to piece them together from a few different sources, and a number of other suggestions (like copying the php.ini file to C:/WINDOWS/) didn’t work and were not necessary.

Open your IIS management console at C:\WINDOWS\system32\inetsrv\iis.msc.
Drill down to your web site, right-click and select Properties.
Select the Home Directory tab, then click on the Configuration button.
Select the Mappings tab. If you don’t see a .php extension listed, click the Add button. Browse to the PHP 5 DLL (which may be at C:\Program Files\PHP\php5isapi.dll). Type .php into the Extension field and leave everything else at the default values. Click OK. The extension and executable path will be filled out and under Verbs you should see “All”.

I should point out that I didn’t have anything listed under the ISAPI Filters tab.

Stop and restart your IIS server and browse to a .php file. (To restart your IIS server, open the IIS management console, right-click the local computer in the left pane, hover on All Tasks and choose Restart IIS.) Chances are, you’re no longer getting the 404 error, but are now seeing a 403.1 message, like:

The page cannot be displayed
You have attempted to execute a CGI, ISAPI, or other executable program from a directory that does not allow programs to be executed.

Please try the following:

* Contact the Web site administrator if you believe this directory should allow execute access.

HTTP Error 403.1 – Forbidden: Execute access is denied.
Internet Information Services (IIS)

Open iis.msc again, go back to the Home Directory tab, and select the “Scripts only” option from the Execute Permissions menu. Restart the server.

The server should now be correctly processing .php files.

A client wanted me to implement a drop down contact form that was triggered when the cursor hovered over a button in the site’s navigation. This was no problem, and I delivered some code using script.aculo.us‘s blind effect. A few hours later, the client contacted me and said that as he moved his cursor around the screen, he kept accidently triggering the contact form as the cursor moved through the element, and couldn’t I find a way to make the action a little more deliberate.

As far as I can tell, there is a way to delay a blind effect in script.aculo.us, but no way to stop the effect once the delay’s countdown has begun.

I searched around and came upon a w3schools JavaScript tutorial about timing events and the setTimeout() and clearTimeout() methods. This was exactly what I needed. By calling a function that started a countdown to the event rather than the event itself, and later calling a function that cancelled the countdown, it is possible to abort the drop down action if the mouse was moved out of the element within a specified time interval.

The code snippet below assumes you have links to the script.aculo.us and prototype libraries in place already. As the cursor enters the link, the startForm() function is called and a 500 ms timer begins. If the cursor moves out of the link, the stopForm() function is called, and the timer is cancelled. If stopForm() is called before the timer finishes counting, the effect never happens.

The client’s happy and I learned something useful.

The Code

<script type="text/javascript"><!--//--><![CDATA[//><!--
var t
function startForm() {
	t=setTimeout("Effect.toggle('contactform','blind')",500);
}
function stopForm() {
	clearTimeout(t);
}
//--><!]]></script>

A simple demonstration of how to implement this using inline JavaScript (a no-no).

<ul id="nav">
	<li><a href="#">a link</a></li>
	<li><a href="#">a link</a></li>
	<li><a href="#" onmouseover="startForm()" onmouseout="stopForm()">Contact Us</a></li>
</ul>
<div id="contactform">
        <!-- the form goes here -->
</div>

This post explains how to set up an IIS 5.1 server on your home network for serving web pages, and then add it to your Workgroup so you can edit those pages from a different PC without the need for an FTP server and client.

You’ll need a PC running Windows 2000, XP Professional, or 2003. The different operating systems offer different versions of IIS, with 5.0 and 6.0 being much more full-featured than the 5.1 version that ships with XP Professional. But if all you want to do is test ASP pages and serve them to computers on your home network, 5.1 should suffice.

I’m using an ancient Compaq Armada laptop with a 700 MHz Intel Pentium III and 192 MB RAM. I did a clean install of XP, and it works surprisingly smoothly. I’m serious.

If you want your server to be accessible from outside the LAN, you’ll have to look elsewhere for instructions. I’m not comfortable advising anyone on the security risks of doing that.

Install IIS

Find your Windows XP Professional installation CD and pop it in. Open your Control Panel -> Add or Remove Programs -> Add/Remove Windows Components. Check the box next to Internet Information Services (IIS) and click Next to install. The default settings for the components should be fine.

Open a browser and enter “http://localhost/localstart.asp” into the address bar to confirm the server is running. You’ll likely be prompted for your username and password. You don’t need to go any further if you don’t want to.

Add the PC to your Workgroup

Right click My Computer -> Properties -> Computer Name tab. Click the Change button and enter the name of your Workgroup. Click Ok to save the change and then reboot.

Share the web folders

Open Windows Explorer and navigate to “C:\”. Right-click on the “Inetpub” folder and select “Sharing and security…” Either run through the Network Setup Wizard, or just start sharing the folder. (If you run through the wizard, you’ll be asked how your computer connects to the Internet. Chances are you’ll want to select “Other” at the first opportunity. It’s head-slappingly annoying that there are only five possible choices, yet Microsoft decided to spread them across two pages of options, and then put the two most likely choices on the second page.)

Navigate to “C:\Inetpub” and share the “wwwroot” folder. For some reason, this needs to be shared specifically, while the other folders at this level inherit sharing from the “Inetpub” folder.

Confirm you can access the folders from your primary PC. In Windows Explorer, navigate to My Network Places -> Entire Network -> Microsoft Windows Network -> Workgroup -> <your_server> -> Inetpub -> wwwroot.

Turn on the server

If the server isn’t running automatically after the reboot, open your Control Panel -> Administrative Tools -> Internet Information Services. You might want to right-click and drag this to make a shortcut on the desktop. (The IIS control panel is located at “%SystemRoot%\system32\inetsrv\iis.msc”.)

Drill down to “Web Sites” -> “Default Web Site”, right-click and select Start.

You can also create Virtual Directories, if you like, from the right-click menu.

Add a test folder (optional)

I’d recommend creating a folder in “C:\Inetpub\wwwroot\” called “test” or something and throwing a simple index.html file into it. If you browse to http://localhost on the server, you’ll be prompted for a username and password, but if you browse to a subfolder, such as http://localhost/test/index.html, you’ll get right in. This makes testing your setup from another PC easier.

Once you can get to http://localhost/test/index.html from the server, continue.

Open the Windows Firewall port

Open your Control Panel -> Windows Firewall -> Exceptions tab. Click on “Add Port”, name it HTTP, enter “80” as the port number and leave “TCP” selected. Click OK.

The web server can now act like one and respond to non-local port 80 requests.

Get the IP address

Start -> Run. Type “CMD” and click OK. Type “ipconfig” and press Enter. Jot down the IP address.

You will probably want to make this IP address static. I’ve found that doing it from the router’s admin panel is better than doing it from that connection’s properties.

Browse to the site from another PC on the LAN

Open a browser and enter http://192.168.x.x/test/index.html

You should be looking at your test page. You should also be able to connect using the server’s name instead of the IP address.

Update 6/25/09: I’ve updated the script to include a number of suggestions made in the comments. The new script supports multiple files, up to 20 URLs can be created at a time, and a brief note can be attached to each key. If these features sound useful, please check out the new post at:

Protecting multiple downloads using unique URLs.

A client asked me to develop a simple method for protecting a download (or digital product) by generating a unique URL that can be distributed to authorized users via email. The URL would contain a key that would be valid for a certain amount of time and number of downloads. The key will become invalid once the first of those conditions is exceeded. The idea is that distributing the unique URL will limit unauthorized downloads resulting from the sharing of legitimate download links.

In addition, once the key has been validated, the download starts immediately, preventing the visitor from seeing the actual location of the download file. What’s more, the file name of the download in the “Save as” dialogue box isn’t necessarily the same as the file name of the file on the server, making the file itself pretty much undiscoverable.

How it works

There are five main components to this system:

  1. the MySQL database that holds each key, the key creation time, and the number of times the key has been used
  2. the downloadkey.php page that generates the unique keys and corresponding URLs
  3. the download.php page that accepts the key, verifies its validity, and either initiates the download or rejects the key as invalid
  4. a dbconnect.php file that contains the link to the database and which is included into both of the other PHP files
  5. the download .zip file that is to be protected

Place all three PHP scripts and the .zip file into the same directory on your server.

The MySQL database

Using whatever method you’re comfortable with, create a new MySQL database named “download” and add the following table:

CREATE TABLE `downloadkey` (
  `uniqueid` varchar(255) NOT NULL default '',
  `timestamp` varchar(255) NOT NULL default '',
  `downloads` varchar(255) NOT NULL default '0',
  PRIMARY KEY (uniqueid)
);

The downloadkey.php page

This page generates the key, creates a URL containing the key, and writes the key to the database. Never give out the location of this page – this is for only you to access.

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<title>Download Key Generator</title>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
<meta name="author" content="//ardamis.com/" />
<style type="text/css">
#wrapper {
	font: 15px Verdana, Arial, Helvetica, sans-serif;
	margin: 40px 100px 0 100px;
}
.box {
	border: 1px solid #e5e5e5;
	padding: 6px;
	background: #f5f5f5;
}
</style>
</head>

<body>
<div id="wrapper">

<h2>Download Key Generator</h2>

<?php
// A script to generate unique download keys for the purpose of protecting downloadable goods

require ('dbconnect.php');

	if(empty($_SERVER['REQUEST_URI'])) {
    	$_SERVER['REQUEST_URI'] = $_SERVER['SCRIPT_NAME'];
	}

	// Strip off query string so dirname() doesn't get confused
	$url = preg_replace('/\?.*$/', '', $_SERVER['REQUEST_URI']);
	$folderpath = 'http://'.$_SERVER['HTTP_HOST'].'/'.ltrim(dirname($url), '/').'/';


// Generate the unique download key
	$key = uniqid(md5(rand()));
//	echo "key: " . $key . "<br />";
	
// Get the activation time
	$time = date('U');
//	echo "time: " . $time . "<br />";
	
// Generate the link
	echo "<p>Here's a new download link:</p>";
	echo "<p><span class=\"box\">" . $folderpath . "download.php?id=" . $key . "</span></p>";

	
// Write the key and activation time to the database as a new row
	$registerid = mysql_query("INSERT INTO downloadkey (uniqueid,timestamp) VALUES(\"$key\",\"$time\")") or die(mysql_error());
?>

<p>&nbsp;</p>
<p>Each time you refresh this page, a unique download key is generated and saved to a database.  Copy and paste the download link into an email to allow the recipient access to the download.</p>
<p>This key will be valid for a certain amount of time and number of downloads, which can be set in the download.php script.  The key will expire and no longer be usable when the first of these conditions is exceeded.</p>
<p>The download page has been written to force the browser to begin the download immediately.  This will  prevent the recipient of the email from discovering the location of the actual download file.</p>

</div>
</body>
</html> 

The download.php page

The URL generated by downloadkey.php points to this page. It contains the key validation script and then forces the browser to begin the download if it finds the key is valid.

<?php
// Set the maximum number of downloads (actually, the number of page loads)
$maxdownloads = "2";
// Set the key's viable duration in seconds (86400 seconds = 24 hours)
$maxtime = "86400";

require ('dbconnect.php');

	if(get_magic_quotes_gpc()) {
        $id = stripslashes($_GET['id']);
	}else{
		$id = $_GET['id'];
	}

	// Get the key, timestamp, and number of downloads from the database
	$query = sprintf("SELECT * FROM downloadkey WHERE uniqueid= '%s'",
	mysql_real_escape_string($id, $link));
	$result = mysql_query($query) or die(mysql_error());
	$row = mysql_fetch_array($result);
	if (!$row) { 
		echo "The download key you are using is invalid.";
	}else{
		$timecheck = date('U') - $row['timestamp'];
		
		if ($timecheck >= $maxtime) {
			echo "This key has expired (exceeded time allotted).<br />";
		}else{
			$downloads = $row['downloads'];
			$downloads += 1;
			if ($downloads > $maxdownloads) {
				echo "This key has expired (exceeded allowed downloads).<br />";
			}else{
				$sql = sprintf("UPDATE downloadkey SET downloads = '".$downloads."' WHERE uniqueid= '%s'",
	mysql_real_escape_string($id, $link));
				$incrementdownloads = mysql_query($sql) or die(mysql_error());
				
// Debug		echo "Key validated.";

// Force the browser to start the download automatically

/*
	Variables: 
		$file = real name of actual download file on the server
		$filename = new name of local download file - this is what the visitor's file will actually be called when he/she saves it
*/

   ob_start();
   $mm_type="application/octet-stream";
   $file = "actual_download.zip";
   $filename = "bogus_download_name.zip";
 
   header("Cache-Control: public, must-revalidate");
   header("Pragma: no-cache");
   header("Content-Type: " . $mm_type);
   header("Content-Length: " .(string)(filesize($file)) );
   header('Content-Disposition: attachment; filename="'.$filename.'"');
   header("Content-Transfer-Encoding: binary\n");
 
   ob_end_clean();
   readfile($file);

			}
		}
	}
?>

The dbconnect.php script (database connection)

This is the PHP include referenced by both scripts that contains the database link.

<?php
// Connect to database "download" using: dbname , username , password 
    $link = mysql_connect('localhost', 'root', '') or die("Could not connect: " . mysql_error());
    mysql_select_db("download") or die(mysql_error());
?>

This file will almost certainly require some editing. You will need to specify a host name for your MySQL server and a MySQL username and password in that file at mysql_connect('localhost', 'root', '') so that you can connect to the database you’ve set up. It’s extremely unlikely that your production MySQL database will be installed on localhost with a user “root” and no password.

That’s all there is to it. Whenever you want to give someone access to the download, visit the downloadkey.php page. It will generate a unique key code, save it to a database, and print out a URL that you can copy and paste into an email or whatever. The page at that URL checks to see if the key code is legit, then checks to see if the code is less than X hours old, then checks to see if it has been used less than X times. The visitor will get a descriptive message for the first unmet condition and the script will terminate. If all three conditions are met, the download starts automatically.

Security Note:
As the commenter Bruno Ng points out, submitting information via the form fields when using this script sends your database connection info in plain text, and that’s a bad thing.

Therefore, the form field method should only be used for testing local databases.

If you need to test production databases, your database connection info should be hard coded in the PHP script (which isn’t hard to do – look around lines 72-75).

A simple page for testing and troubleshooting a connection to a MySQL database. The PHP script will test the server address, username and password. If the database field is left empty, it will return a list of available databases. Testing a specific database is optional, but if a database name is supplied, it will return a list of the tables in that database (if any exist).

Due to problems with the Syntax Highlighter plugin producing invalid code when copying and pasting, here is a link to the code in plain text. The code below is just for reference.

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<title>MySQL Connection Test</title>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
<style type="text/css">
#wrapper {
	width: 600px;
	margin: 20px auto 0;
	font: 1.2em Verdana, Arial, sans-serif;
}
input {
	font-size: 1em;
}
#submit {
	padding: 4px 8px;
}
</style>
</head>

<body>

<div id="wrapper">

<?php
	$action = htmlspecialchars($_GET['action'], ENT_QUOTES);
?>

<?php if (!$action) { ?>

	<h1>MySQL connection test</h1>

<form action="<?php echo $_SERVER['PHP_SELF']; ?>?action=test" id="mail" method="post">

	<table cellpadding="2">
		<tr>
			<td>Hostname</td>
			<td><input type="text" name="hostname" id="hostname" value="" size="30" tabindex="1" /></td>
			<td>(usually "localhost")</td>
		</tr>
		<tr>
			<td>Username</td>
			<td><input type="text" name="username" id="username" value="" size="30" tabindex="2" /></td>
			<td></td>
		</tr>
		<tr>
			<td>Password</td>
			<td><input type="text" name="password" id="password" value="" size="30" tabindex="3" /></td>
			<td></td>
		</tr>
		<tr>
			<td>Database</td>
			<td><input type="text" name="database" id="database" value="" size="30" tabindex="4" /></td>
			<td>(optional)</td>
		</tr>
		<tr>
			<td></td>
			<td><input type="submit" id="submit" value="Test Connection" tabindex="5" /></td>
			<td></td>
		</tr>
	</table>

</form>

<?php } ?>

<?php if ($action == "test") {

// The variables have not been adequately sanitized to protect against SQL Injection attacks: http://us3.php.net/mysql_real_escape_string

	$hostname = trim($_POST['hostname']);
	$username = trim($_POST['username']);
	$password = trim($_POST['password']);
	$database = trim($_POST['database']);

	$link = mysql_connect("$hostname", "$username", "$password");
		if (!$link) {
			echo "<p>Could not connect to the server '" . $hostname . "'</p>\n";
        	echo mysql_error();
		}else{
			echo "<p>Successfully connected to the server '" . $hostname . "'</p>\n";
//			printf("MySQL client info: %s\n", mysql_get_client_info());
//			printf("MySQL host info: %s\n", mysql_get_host_info());
//			printf("MySQL server version: %s\n", mysql_get_server_info());
//			printf("MySQL protocol version: %s\n", mysql_get_proto_info());
		}
	if ($link && !$database) {
		echo "<p>No database name was given. Available databases:</p>\n";
		$db_list = mysql_list_dbs($link);
		echo "<pre>\n";
		while ($row = mysql_fetch_array($db_list)) {
     		echo $row['Database'] . "\n";
		}
		echo "</pre>\n";
	}
	if ($database) {
    $dbcheck = mysql_select_db("$database");
		if (!$dbcheck) {
        	echo mysql_error();
		}else{
			echo "<p>Successfully connected to the database '" . $database . "'</p>\n";
			// Check tables
			$sql = "SHOW TABLES FROM `$database`";
			$result = mysql_query($sql);
			if (mysql_num_rows($result) > 0) {
				echo "<p>Available tables:</p>\n";
				echo "<pre>\n";
				while ($row = mysql_fetch_row($result)) {
					echo "{$row[0]}\n";
				}
				echo "</pre>\n";
			} else {
				echo "<p>The database '" . $database . "' contains no tables.</p>\n";
				echo mysql_error();
			}
		}
	}
}
?>

</div><!-- end #wrapper -->
</body>
</html>