Powered by Blogger.

Contact

Popular Posts

Sunday, 8 September 2013

Enterprise Resource Planning Tutorial : Download Here








[ Decoding PHP ]
There are many ways to encode and decode PHP code. From the perspective of site security, there are three PHP functions —str_rot13()base64_encode(), and gzinflate — that are frequently used to obfuscate malicious strings of PHP code. For those involved in the securing of websites, understanding how these functions are used to encode and decode encrypted chunks of PHP data is critical to accurate monitoring and expedient attack recovery.

For those already familiar with the concept, but could use a quick reference with examples, I put together a concise summary of this article. The article here is intended as a “behind-the-scenes” look at the decoding and encoding happening on the examples page. Here’s the quick-jump menu:

Encoding and decoding with str_rot13()

As explained in the PHP documentationstr_rot13() is a simple function used for rotating everyletter “13 places in the alphabet” while ignoring non-alphanumeric characters. This type of encoding is called ROT13 encoding and it’s very straightforward using the str_rot13() function. Let’s look at an example..
Let’s say we want to ROT13-encode the following string:
<?php $string = 'Encoding and Decoding Encrypted PHP Code'; ?>
We run this string through str_rot13() and set it as a variable named $encoded like so:
<?php $encoded = str_rot13($string); ?>
Echoing the $encoded variable to the browser, we get this string of gibberish:
Rapbqvat naq Qrpbqvat Rapelcgrq CUC Pbqr
To decode a string encoded with str_rot13(), we simply run it back through the function to restore the original string. Here is an example that returns the original string to a variable named$decoded:
$decoded = str_rot13(str_rot13($string))
Echoing $decoded, we see the original string as expected:
Encoding and Decoding Encrypted PHP Code
Copy/paste example (try it for yourself):
<?php // str_rot13() example
$string = 'Encoding and Decoding Encrypted PHP Code';
$encoded = str_rot13($string);
$decoded = str_rot13(str_rot13($string));
echo $encoded ."\n";
echo $decoded;
?>

Encode and decode with base64_encode() & base64_decode()

Also explained in the PHP documentation, the base64_encode() function “encodes the given data with base64.” Rather than get into the mechanics of encoding with base64, I’ll repeat the enigmatic haiku given in the docs:
This encoding is designed to make binary data survive transport through transport layers that are not 8-bit clean, such as mail bodies.
Ahh, I love taking stuff out of context, but I digress.. Let’s get back on track with a quick example showing how base64_encode() works its magic. Let’s say we want to encode the following string with base64:
<?php $string = 'Encoding and Decoding Encrypted PHP Code'; ?>
We run this string through base64_encode() and set it as a variable named $encoded like so:
<?php $encoded = base64_encode($string); ?>
Echoing the $encoded variable to the browser, we get this string of gibberish:
RW5jb2RpbmcgYW5kIERlY29kaW5nIEVuY3J5cHRlZCBQSFAgQ29kZQ==
As you may count, the base64-encoded string contains around 33% more data than the original. Now to decode a string encoded with base64_encode, we use the converse function,base64_decode. Here is an example that returns the original string to a variable named $decoded:
<?php $decoded = base64_decode(base64_encode($string)); ?>
Echoing $decoded, we see the original string as expected:
Encoding and Decoding Encrypted PHP Code
Copy/paste example (try for yourself):
<?php // base64_encode()/base64_decode() example
$string = 'Encoding and Decoding Encrypted PHP Code';
$encoded = base64_decode($string);
$decoded = base64_decode(base64_encode($string));
echo $encoded ."\n";
echo $decoded;
?>

Deflate and inflate with gzdeflate() & gzinflate()

A third visit to the PHP docs gives us our third function, gzdeflate() is used to “compress the given string using the DEFLATE data format.” Again, not gonna veer off — let’s stay focused with a quick example.
Let’s say we want to “gzdeflate” the following string:
<?php $string = 'Encoding and Decoding Encrypted PHP Code'; ?>
We run this string through gzdeflate() and set it as a variable named $compressed:
<?php $compressed = gzdeflate($string); ?>
Echoing the $compressed variable to the browser, we get this bizarre-looking gibberish:
s�K�O��KWH�KQpI�r\���* JRS < ��SR
To “decode” this alien-speak, we inflate it with the converse function, gzinflate(), to restore the original string. Here is an example that returns the original string to a variable named$uncompressed:
$uncompressed = gzinflate(gzdeflate($string));
Echoing $uncompressed, we see the original string as expected:
Encoding and Decoding Encrypted PHP Code
Copy/paste example:
<?php // gzinflate()/gzdeflate() example
$string = 'Encoding and Decoding Encrypted PHP Code';
$compressed = gzdeflate($string);
$uncompressed = gzinflate($compressed);
echo $compressed ."\n";
echo $uncompressed;
?>

Parameters

Also worth mentioning: whereas the first two functions — str_rot13() and base64_encode() — accept only one parameter (the input $string), the inflate/deflate functions accept twoparameters. Perhaps surprisingly, these second parameters are different between the two functions:
  • gzdeflate() — level = the level of compression (0 to 9)
  • gzinflate() — length = the maximum length of data to decode
Returning to our example, let’s employ these second parameters to help visualize:
<?php // example using second parameters
$string = 'Encoding and Decoding Encrypted PHP Code';
$compressed = gzdeflate($string, 9); // compression level set to 9 = maximum
$uncompressed = gzinflate($compressed, strlen($string)); // length set to same as $string
echo $compressed ."\n";
echo $uncompressed;
?>
And the result as displayed in a browser:
s�K�O��KWH�KQpI�r\���* JRS < ��SR
Encoding and Decoding Encrypted PHP Code

Combined example: gzinflate(str_rot13(base64_decode()))

Malicious scripts often combine multiple encoding methods to further obfuscate data strings. Using the numerous PHP encoding-type functions (and their various parameters), it’s possible to scramble data with many layers of obfuscation. For example, on common technique for encrypting malicious scripts combines all three of the functions described in this article. The structure of such technique looks like this:
$gibberish = eval(gzinflate(str_rot13(base64_decode($string))));
The concept is straightforward, however decoding the $gibberish can be tricky. The easiest way to decode such a string is to use an online decoding tool. And that’s my slick segue into the next section..

Online tools for decoding/encoding PHP code

To further contribute to the cause, I’ve created some online decoding tools to simplify the process. Here are some tools for encoding/decoding with some common PHP functions:

Additional resources

Into this decoding/ecoding stuff? You may also enjoy these fine functions..

Saturday, 7 September 2013




.htaccess made easy

If you want to block tough proxies like hidemyass.com, my previously posted .htaccess methods won’t work. Those methods will block quite a bit of proxy visits to your site, but won’t work on the stealthier proxies. Fortunately, we can use a bit of PHP to keep them out.

Block Tough Proxies with PHP

To stop tough proxy visits from sites like hidemyass.com, add the following slice of finely craftedPHP to the top of your header.php file:
<?php if(@fsockopen($_SERVER['REMOTE_ADDR'], 80, $errstr, $errno, 1))
die("Proxy access not allowed"); ?>
If you’re not using WordPress, just place the code at the top of your web page(s). No editing is necessary, so just add the code, upload the file, and done. You can check that it works by visiting your site via your favorite proxy service. If it works, access will be denied.
This method works for me on a Linux server running Apache 2.2.3, MySQL 5.0, and PHP 5.2.6. It should work on similar setups as well, but your results may vary depending on your server configuration.

Block Other Proxies with .htaccess

If for whatever reason you aren’t using the above PHP method, you can still block a majority of the “lesser” proxies by adding the following block of HTAccess code to your site’s root .htaccess file:
# BLOCK PROXY VISITS
# PerishablePress.com: http://bit.ly/12k6Uo
<ifModule mod_rewrite.c>
RewriteEngine on
RewriteCond %{HTTP:VIA} !^$ [OR]
RewriteCond %{HTTP:FORWARDED} !^$ [OR]
RewriteCond %{HTTP:USERAGENT_VIA} !^$ [OR]
RewriteCond %{HTTP:X_FORWARDED_FOR} !^$ [OR]
RewriteCond %{HTTP:PROXY_CONNECTION} !^$ [OR]
RewriteCond %{HTTP:XPROXY_CONNECTION} !^$ [OR]
RewriteCond %{HTTP:HTTP_PC_REMOTE_ADDR} !^$ [OR]
RewriteCond %{HTTP:HTTP_CLIENT_IP} !^$
RewriteRule .* - [F]
</ifModule>
This proxy-blocking technique is less-effective than the PHP method, but should help reduce overall proxy traffic to your site. Using HTAccess to filter proxies requires fewer system resources than the PHP method. So if you get tons of traffic or have lots of pages, you’re better off sticking with the HTAccess technique. It’s sort of a trade-off between effective proxy-blocking and optimum performance, which will vary depending on your needs and server configuration.

Web Developing - Computer Engineering: 60+ Awesome New WordPress Themes: 60+ Awesome New WordPress Themes Blog Post In: http://www.webdesignerdepot.com It seems like every time you go looking for a ne...

Friday, 6 September 2013






.htaccess made easyI recently spent some time wrestling with various e-commerce/shopping-cart/membership plugins. One of them was of course the popular WP e-Commerce plugin, which uses a directory named “downloadables” to store your precious goods. I had some large files that needed to go into this folder, but the server’s upload limit stopped me from using the plugin’s built-in file uploader to do so.

On most servers, there are limits to how much data you can upload. When dealing with PHP scripts, the upload, download, and similar limits are set in the php.ini file. If you have access to this file, or can create a localized version in the target directory, then increasing the upload limit for large files is as simple as adding these two lines:
upload_max_filesize = 10M
post_max_size = 10M
Unfortunately, there are many hosting/server scenarios where access to php.ini is unavailable. Fortunately, .htaccess provides an alternate method of increasing upload limits. If you have access to .htaccess files, then raising the upload limit is done with these two lines:
php_value upload_max_filesize 10M
php_value post_max_size 10M
With either or perhaps both of these methods in place, you should have no problem uploading large files to your server. But some servers require more advanced configuration to increase upload limits. Such was the case for my WP e-Commerce experiment: hosted on another server, and neither the php.ini nor the .htaccess method were going to work. So I gave up on the built-in uploader and tried just uploading the large files directly via FTP.
Sounds simple enough, and FTP usually works great, but NOT this time. Somehow the WP e-Commerce plugin had locked the downloadables directory via deadly combination of restrictive file permissions and mod_authz_host via .htaccess.
So now I needed a way to bypass both of these measures. Starting with the .htaccess file in thedownloadables directory, I logged into my server control panel to take a look. It contains three lines:
order deny,allow
deny from all
allow from none
Unfortunately, this file was created with @chmod($file_handle,0665);, which means its permissions prevent any non-root editing, such as via Plesk or FTP. Looking then at the downloadables directory, the permissions were 775 – less restrictive, but owned by apache, so no editing of that file either. Here it is visually:
[ Screenshot: Editable and non-editable file permissions in Plesk ]In Plesk, you’re not root, so you’re not modifying files owned by apache
[ CHMOD 665 File Permissions ]Translating 665 chmod values into plain english (for the .htaccess file)
[ CHMOD 775 File Permissions ]Translating 775 chmod values into plain english (for the /downloadables/ directory)
When it gets to this point, where everything is locked down and nothing seems to work, there are two ways forward, depending on your host/server setup:
  • On servers without access to SSH, you’ll need to have your host help you
  • On servers with SSH access, you can do it yourself
If you’ve got access, SSH provides numerous ways to get the job done. In this situation, the end-goal is uploading some large files to a locked-down downloadables directory. The easiest way is to log into your server as the root user via SSH, and then use the scp command to upload the file directly. Here is the general syntax:
scp /usr/dir/large.zip user@11.22.33.44:/usr/dir/
And here is a breakdown of what it means:
[ SSH scp Command ]How to upload a file via SSH
Here is the scp command as it looks entered in Mac Terminal:
[ SSH scp via Terminal ]What the SSH scp command looks like in Terminal
So, using this technique to upload a large file to our locked-down downloadables directory, the scpcommand looks like this:
scp /usr/dir/large.zip user@11.22.33.44:/usr/downloadables/
If we needed to upload an entire directory, we would modify the command like this:
scp -r /usr/directory/ user@11.22.33.44:/usr/downloadables/
Using one of these commands, it’s possible to upload files and directories of just about any size. If, however, you would rather FTP your content, you can use SSH to change the permissions of restrictive directories, which in my case was the downloadables folder.
To change file permissions via chmod, navigate to the parent directory of your target folder and enter the following command via SSH:
chmod -v 777 target-directory
If the target directory is also protected via .htaccess, as is the case with the downloadablesdirectory, then use chmod to change its permissions as well, and then edit the file as needed to allow access. For example, our target directory is protected by the following .htaccess directives:
order deny,allow
deny from all
allow from none
So to allow access, we could grab our IP and modify the .htaccess code like so:
Order Allow,Deny
Deny from all
Allow from none
Allow from 123.456.789.0
And that’s going to give you all the access you need to upload anything you want. Just remember to restore the original .htaccess rules and file permissions once you’ve finished uploading those precious goods.
Publish By:http://perishablepress.com

Thursday, 5 September 2013

Computer Engineering: HTTP Headers for ZIP File Downloads: HTTP Headers for ZIP File Downloads You know when you you’re working on a project and get stuck on something, so you scour the Web for s...

Tuesday, 3 September 2013



Ajax-Powered Error Logs


Update: Check out the new and improved Ajax Error Log Version 2.0!

[ Ajax Error Log - File Structure ]
As an obsessive website administrator, I like to keep a keen eye on my error logs. Once a week, I download my PHP, 404, and other error logs, and analyze them as closely as time allows. Monitoring site errors and other traffic patterns leads to many of the security-related articles I post here atPerishable Press, including resources such as the 5G Blacklist, Ultimate HTAccess Blacklist, and the Blacklist Candidate Series. Easily, one of the best ways to protect your site is to understand the different types of errors that are happening behind the scenes. This is why monitoring your error logs is so important. In this article, you’ll learn how to make it a little easier and more dynamic with MySQLPHP, and the magic of Ajax.

Overview

I tend to over-explain things, so here is an overview of this tutorial:
  • What we’re doing
  • How is this useful?
  • Demonstration
  • Implementation
    • Step 1: Create the database table
    • Step 2: Create the custom error page
    • Step 3: Setup the 404 redirect
    • Step 4: Verify functionality
    • Step 5: Create the dynamic log script
    • Step 6: Create the dynamic log page
  • Download the files
  • Thrilling conclusion

Dynamic Error Monitoring with Ajax

For the past couple of years, I have wanted to develop a way to easily monitor my sites’ errors in “real time.” My idea is to use Ajax and jQuery to display different types of errors dynamically on the web page. If you think of a typical Ajax chat script, where the page is refreshed at short intervals to display new entries, you’ve got a good idea of what I’m doing here. The process goes something like this:
  1. 404 errors are redirected to a custom PHP script
  2. The script then logs the different errors into a database
  3. The contents of the database are displayed on a web page
  4. jQuery/Ajax is used to refresh the page at short intervals
Is this for everyone? Probably not, but if you’re into logging visitor information, recording errors in a database, and keeping an eye on your site in general, you’ll probably benefit from the technique. Keep in mind that the tutorial focuses on setting up and putting things together, so I don’t spend a lot of time getting into the technical aspects of what the actual code is doing. There’s actually a lot of neat stuff happening behind the scenes, such as looking up geographical IP data, encoding image content for the database, and displaying results dynamically with Ajax.

How is this useful?


[ Ajax: Asynchronous Javascript and XML ]
By examining static error logs, we’re catching problemsafter they happen. In my mind, it would be better to have the ability to keep an eye on things in real time and resolve issues as they happen. For example, Perishable Press isfrequently scanned for vulnerabilities by teh evil scriptz, but the Ajax Error Log enables me to take immediate action and protect my site. Plus, catching 404 errors helps you spotlegitimate errors for things that should exist, enabling a more responsive maintenance strategy.
I honestly don’t think any of this is really necessary, but more like an enhancement over boring static log files.
Sure, you can’t sit there and just watch your error log all day, but you can keep a tab open and keep an eye on things while you’re working online. For many of us, that’s nearly all the time, but even if you’re only watching your errors for a few minutes a day, you’re still going to benefit from observing errors as they happen. Even that much will help you better understand what’s happening (or not happening) on your server, which is the key to good security.
Now that I’ve got this script working for Perishable Press, I like to open a browser window, resize it so it fits in the corner of my screen, and then just sort of keep an eye on things as I work. It’s extremely satisfying stopping the bad guys dead in their tracks. It’s good times ;)

Demonstration

This may all sound rather abstract, so here is a Live Demo of my Ajax Error Log technique. The Demo displays the 404 errors just moments after they occur at my test site, bluefeed.net. The site gets very little traffic, so if no new errors are appearing, try the following to watch the Dynamic Error Log do its thing:
  1. Open the Demo in new window (not tab), and position it next to the current window (so you can see both at the same time).
  2. Then trigger a 404 error by clicking on this link: http://bluefeed.net/404 *
  3. Watch the 404 error automagically appear on the Demo page!
Note: Please only click the error link once or twice. Obviously, I’m heavy into monitoring things, so if you don’t want to get banned, please click only a few times to get the idea. Then if you like the technique and want to continue experimenting, follow the tutorial and set it up at your own site. Thanks in advance for being cool :)
While we’re on the subject, it’s also important to note that you SHOULD NOT display your error log to the general public. This technique is designed for use by a single user from a secure andprivate web page. Making it public reveals potentially sensitive information and increases the load on your server.

Implementation

Here are the three files you will need to implement your own dynamic error log:
  • 404.php – contains the PHP script that logs the errors
  • AjaxErrorLog.php – connects to the database and displays its contents
  • AjaxErrorLog.html – contains the HTML & jQuery used to display the results
We’ll create and configure each of these files in this tutorial, but you can also just download the files and follow along that way.
In addition to these 3 files, you’ll need to create a table in your MySQL database. This can either be an existing database or a new one.

Step 1: Create the database table

Once you’ve got the database in place, execute the following SQL query (via phpMyAdmin or similar):
CREATE TABLE `error_log` (
`id` int(10) unsigned NOT NULL auto_increment,
`logtime` varchar(200) NOT NULL default '',
`request` varchar(200) NOT NULL default '',
`referer` varchar(200) NOT NULL default '',
`qstring` varchar(200) NOT NULL default '',
`address` varchar(200) NOT NULL default '',
`agent` varchar(200) NOT NULL default '',
`error` varchar(200) NOT NULL default '',
PRIMARY KEY (`id`),
cur_timestamp TIMESTAMP(8)
) AUTO_INCREMENT = 1
That should create a table named “error_log” in your database. This is where we will be storing the data collected from our 404.php file, which serves as our site’s actual “404-Error” page that also logs each 404 error into the database.

Step 2: Create the custom error page

Create a blank file named 404.php, and fill it with the following PHP code:
<?php
/*
Dynamic Error Logging by Jeff Starr @ Perishable Press
Project URL: http://perishablepress.com/ajax-error-log/
License: GNU General Public License
Version: 1.1
*/

// database credentials
$hostname = "hostname";
$database = "database";
$username = "username";
$password = "password";

// site URL (no trailing slash!)
$website = "http://example.com";

// send proper headers for 404
header("HTTP/1.1 404 Not Found");
header("Status: 404 Not Found");

// set some server variables
$logtime = date("F jS Y, h:ia", time() - 10800);
$request = $site . $_SERVER['REQUEST_URI'];
$referer = $_SERVER['HTTP_REFERER'];
$qstring = $_SERVER['QUERY_STRING'];
$address = $_SERVER['REMOTE_ADDR'];
$agent = $_SERVER['HTTP_USER_AGENT'];
$error = "404"; // for other errors

// connect to database
$dbcon = mysql_connect($hostname, $username, $password)
or die("Couldn't connect to SQL Server on $dbhost");
$selected = mysql_select_db($database, $dbcon)
or die("Couldn't open database $database");

// sanitize server variables
$logtime_esc = mysql_real_escape_string($logtime);
$request_esc = mysql_real_escape_string($request);
$referer_esc = mysql_real_escape_string($referer);
$qstring_esc = mysql_real_escape_string($qstring);
$address_esc = mysql_real_escape_string($address);
$agent_esc = mysql_real_escape_string($agent);

// insert record and close database
$query = "INSERT INTO `error_log` (logtime,request,referer,qstring,address,agent,error) ";
$query .= "VALUES ('$logtime_esc','$request_esc','$referer_esc','$qstring_esc','$address_esc','$agent_esc','$error')";
mysql_query($query);
mysql_close($dbcon);

// and finally output the html
?><html>
<head><title>404 - Not Found</title></head>
<body id="error-404">
<div class="left">
<div class="post">
<h1>Error 404 &mdash; Not Found</h1>
<p>The requested resource was not found on this server.</p>
<div class="content">
<p><?php echo "Requested URL: " . $website . $request_esc; ?></p>
</div>
</div>
</div>
</body>
</html>
This script basically declares some server variables and then sanitizes them before recording them in the database. It also send the correct headers and performs a Geographical IP Lookup to capture key attributes of the request. Thanks to hostip.info for their awesome lookup service, and also to this forum thread for the help with forwarded URLs.
For the 404.php file to work, you’ll need to edit the first four variables – $hostname$database,$username, and $password – to enable the script to connect to your database. Once the file is configured and in place, the server needs to know to use it when responding to 404 errors. We set this up in the next step..

Step 3: Setup the 404 redirect

The next step is to instruct the server to use the custom 404.php file instead of the default error page. With Apache, this is possible with a single line added to your site’s root .htaccess file:
ErrorDocument 404 /ajax-error-log/404.php
..and then edit the path to match the file’s actual location on your server. Once that’s in place on your server, it’s time to check that things are working.

Step 4: Verify functionality

Once you get the 404.php file uploaded and the redirect set up, trigger a few 404 errors on your site and check the results. For each error, you should see the custom 404 page displayed in your browser and a recorded entry in your error_log table. Give it a few spins and ensure that everything is working. You will probably want to customize the appearance of your new error page to fit your site’s design (or not). It’s pretty basic by default, but there’s a ton of cool things you can do. To help with customizing, check out my post on pimping out your 404 error page.

Step 5: Create the dynamic log script

At this point, you have something very useful: a custom 404 page that records all 404 errors in the database. Now let’s get dynamic with it and display the information in “real-time” on a web page. Create a file called AjaxErrorLog.php and insert the following PHP code:
<?php
/*
Dynamic Error Logging by Jeff Starr @ Perishable Press
Project URL: http://perishablepress.com/ajax-error-log/
License: GNU General Public License
Version: 1.1
*/

// database credentials
$hostname = "hostname";
$database = "database";
$username = "username";
$password = "password";

// site URL (no trailing slash!)
$website = "http://example.com";

// connect to server
$dbhandle = mysql_connect($hostname, $username, $password)
or die('Could not connect to SQL Server on $hostname');

// select the database
$selected = mysql_select_db($database, $dbhandle)
or die('Could not open database $database');

// create the sql query
$query = 'SELECT id,logtime,request,referer,qstring,address,agent,error
FROM error_log ORDER BY id DESC LIMIT 50'; // defaults to 50 entries

// execute query and return records
$result = mysql_query($query);
$number = mysql_num_rows($result);

// display the results
while($row = mysql_fetch_array($result)) {
echo '<div class="log-entry"><pre>';
echo 'Error: '.htmlspecialchars($row['error']);
echo ' - '.htmlspecialchars($row['logtime'])."\n";
echo 'Request: '.$website.htmlspecialchars($row['request'])."\n";
echo 'User Agent: '.htmlspecialchars($row['agent'])."\n";
echo 'IP Address: '.htmlspecialchars($row['address']);
echo '</pre></div>';
}

//close db connection
mysql_close($dbhandle);
?>
Let’s see what’s happening with this script. First we specify our database credentials, which should be the same as those specified in the 404.php file. Using this information, the script then connects to the server (or dies trying) and selects the specified database. From there, it creates and executes an SQL query and returns the newest ten results (configurable). It then uses that information to output chunks of HTML markup to the web page. Finally, the database connection is closed.
After configuring the AjaxErrorLog.php file, it’s time to bring it all together by including the output in an actual web page and displaying the log results dynamically via jQuery-flavored Ajax.

Step 6: Create the dynamic log page

Finally, create a file named “AjaxErrorLog.html” and insert the following code:
<!DOCTYPE HTML>
<html>
<head>
<title>Ajax Error Log</title>
<!-- Ajax Error Log @ http://perishablepress.com/ajax-error-log/ -->
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
<style>
pre {
font: 10px/1.5 Courier, "Courier New", mono;
background-color: #efefef; border: 1px solid #ccc;
width: 700px; margin: 7px; padding: 10px;
white-space: pre-wrap;
}
</style>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.3.0/jquery.min.js"></script>
<script>
$(document).ready(function() {
$("#results").load("AjaxErrorLog.php");
var refreshId = setInterval(function() {
$("#results").load("AjaxErrorLog.php").fadeIn("slow");
}, 2000); // refresh time (default = 2000 ms = 2 seconds)
});
</script>
</head>
<body>
<noscript><div id="response"><h1>JavaScript is required for this demo.</h1></div></noscript>
<div id="results"></div>
</body>
</html>
This is the page that will display the results dynamically in a browser. It’s a basic web page that uses a little jQuery/Ajax magic to load the output of the AjaxErrorLog.php file and refresh the results every two seconds (as specified in the code as “2000”). Feel free to use any refresh interval you wish, just keep in mind that these are server requests, so don’t go too crazy. ;)
We’re also using some CSS to add a little style to the markup. Currently, the styling is pretty minimal, so you’ll probably want to customize things to suit your own design. Also note that, for the sake of simplicity, we are using Google’s ajax.googleapis.com for the jQuery script.
Once you get all the files configured and in place, open the AjaxErrorLog.html file in your browser and watch the results scroll across your screen. If the database doesn’t contain any errors yet, go ahead and make up some crazy URLs and request them in another tab. Things should be working quite beautifully.

Download the files

Ajax Error Log – Version 2.0 (4 kB zip)
Changelog:
  • v1.1: Replaced mysql_escape_string with mysql_real_escape_string
  • v1.1: Added htmlspecialchars to escape output SQL
  • v1.1: Added $website variable for better accuracy
  • v1.1: Changed the default number of displayed results to 50

With a glass eye on you..

So that’s how to build a Dynamic Error Log using PHPHTMLCSS, and jQuery. The Ajax Error Log that we build in this tutorial is pretty basic, but it’s also fairly easy to customize once you understand how everything works. To see an example of the possibilities, check out my highly customized version.
I would eventually like to expand the functionality of this Dynamic Error Log and translate it into a WordPress plugin. Until then, I want to share the technique and get as much feedback as possible. If you have any ideas for improving the security, functionality, or usefulness of the technique, please let me know, either in the comments or via email. As always, Thank you for reading Perishable Press =)