Merging in changes from stable
authorDan
Fri, 07 Dec 2007 16:42:22 -0500
changeset 313 854eecfada20
parent 310 199b9708f4a2 (current diff)
parent 312 6c7060d36a23 (diff)
child 314 474f8be55943
Merging in changes from stable
ajax.php
includes/common.php
includes/dbal.php
includes/debugger/debugConsole.class.php
includes/debugger/debugConsole.config.php
includes/debugger/debugConsole.functions.php
includes/debugger/debugConsole.php
includes/functions.php
includes/pageprocess.php
includes/paths.php
includes/render.php
includes/sessions.php
includes/template.php
index.php
--- a/ajax.php	Sun Dec 02 16:00:56 2007 -0500
+++ b/ajax.php	Fri Dec 07 16:42:22 2007 -0500
@@ -12,6 +12,8 @@
  * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for details.
  */
  
+  define('ENANO_INTERFACE_AJAX', '');
+ 
   // fillusername should be done without the help of the rest of Enano - all we need is the DBAL
   if ( isset($_GET['_mode']) && $_GET['_mode'] == 'fillusername' )
   {
--- a/cache/index.php	Sun Dec 02 16:00:56 2007 -0500
+++ b/cache/index.php	Fri Dec 07 16:42:22 2007 -0500
@@ -1,13 +1,10 @@
 <?php
 
-$_GET['title'] = 'Enano:Access_denied';
+$title = 'Access denied';
 require('../includes/common.php');
 header('HTTP/1.1 403 Forbidden');
-$session->perms['edit_page'] = AUTH_DENY;
-$session->perms['view_source'] = AUTH_DENY;
-$template->tpl_strings['PAGE_NAME'] = 'Access denied';
 
 $template->header();
-echo '<p>The administrator has flagged the page "' . $_SERVER['REQUEST_URI'] . '" so that it cannot be accessed from the web. Perhaps this is because this is a cache or includes directory and only needs to be accessed by scripts.</p><p>HTTP error: 403 Forbidden</p>';
+echo '<p>The administrator has flagged the page "' . htmlspecialchars($_SERVER['REQUEST_URI']) . '" so that it cannot be accessed from the web. Perhaps this is because this is a cache or includes directory and only needs to be accessed by scripts.</p><p>HTTP error: 403 Forbidden</p>';
 $template->footer();
-$db->close();
+
--- a/files/index.php	Sun Dec 02 16:00:56 2007 -0500
+++ b/files/index.php	Fri Dec 07 16:42:22 2007 -0500
@@ -1,13 +1,10 @@
 <?php
 
-$_GET['title'] = 'Enano:Access_denied';
+$title = 'Access denied';
 require('../includes/common.php');
 header('HTTP/1.1 403 Forbidden');
-$session->perms['edit_page'] = AUTH_DENY;
-$session->perms['view_source'] = AUTH_DENY;
-$template->tpl_strings['PAGE_NAME'] = 'Access denied';
 
 $template->header();
-echo '<p>The administrator has flagged the page "' . $_SERVER['REQUEST_URI'] . '" so that it cannot be accessed from the web. Perhaps this is because this is a cache or includes directory and only needs to be accessed by scripts.</p><p>HTTP error: 403 Forbidden</p>';
+echo '<p>The administrator has flagged the page "' . htmlspecialchars($_SERVER['REQUEST_URI']) . '" so that it cannot be accessed from the web. Perhaps this is because this is a cache or includes directory and only needs to be accessed by scripts.</p><p>HTTP error: 403 Forbidden</p>';
 $template->footer();
-$db->close();
+
--- a/images/index.php	Sun Dec 02 16:00:56 2007 -0500
+++ b/images/index.php	Fri Dec 07 16:42:22 2007 -0500
@@ -1,13 +1,10 @@
 <?php
 
-$_GET['title'] = 'Enano:Access_denied';
+$title = 'Access denied';
 require('../includes/common.php');
 header('HTTP/1.1 403 Forbidden');
-$session->perms['edit_page'] = AUTH_DENY;
-$session->perms['view_source'] = AUTH_DENY;
-$template->tpl_strings['PAGE_NAME'] = 'Access denied';
 
 $template->header();
-echo '<p>The administrator has flagged the page "' . $_SERVER['REQUEST_URI'] . '" so that it cannot be accessed from the web. Perhaps this is because this is a cache or includes directory and only needs to be accessed by scripts.</p><p>HTTP error: 403 Forbidden</p>';
+echo '<p>The administrator has flagged the page "' . htmlspecialchars($_SERVER['REQUEST_URI']) . '" so that it cannot be accessed from the web. Perhaps this is because this is a cache or includes directory and only needs to be accessed by scripts.</p><p>HTTP error: 403 Forbidden</p>';
 $template->footer();
-$db->close();
+
--- a/includes/common.php	Sun Dec 02 16:00:56 2007 -0500
+++ b/includes/common.php	Fri Dec 07 16:42:22 2007 -0500
@@ -11,8 +11,17 @@
  * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied
  * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for details.
  */
+ 
+/**
+ * The main loader script that initializes everything about Enano in the proper order. Prepare to get
+ * redirected if you don't have $_GET['title'] or $_SERVER['PATH_INFO'] set up.
+ * @package Enano
+ * @subpackage Core
+ * @copyright See header block
+ */
 
-if(isset($_REQUEST['GLOBALS']))
+// Make sure we don't have an attempt to inject globals (register_globals on)
+if ( isset($_REQUEST['GLOBALS']) )
 {
   ?>
   <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd"><html><head><title>Hacking Attempt</title><meta http-equiv="Content-type" content="text/html; charset=utf-8" /></head><style type="text/css">body{background-color:#000;color:#CCC;font-family:trebuchet ms,sans-serif;font-size:9pt;}a{color:#FFF;}</style><body><p>Hacking attempt using <a href="http://www.hardened-php.net/index.76.html">PHP $GLOBALS overwrite vulnerability</a> detected, reported to admin</p><p>You're worse than this guy! Unless you are this guy...</p><p id="billp"><img alt=" " src="about:blank" id="billi" /></p><script type="text/javascript">// <![CDATA[
@@ -23,60 +32,73 @@
   exit;
 }
 
+// Our version number
+// This needs to match the version number in the database. This number should
+// be the expected output of enano_version(), which will always be in the
+// format of 1.0.2, 1.0.2a1, 1.0.2b1, 1.0.2RC1
+// You'll want to change this for custom distributions.
 $version = '1.1.1';
 
+/**
+ * Returns a floating-point number with the current UNIX timestamp in microseconds. Defined very early because we gotta call it
+ * from very early on in the script to measure the starting time of Enano.
+ * @return float
+ */
+
 function microtime_float()
 {
   list($usec, $sec) = explode(" ", microtime());
   return ((float)$usec + (float)$sec);
 }
 
+// Determine starting time
 global $_starttime;
 $_starttime = microtime_float();
 
+// Verbose error reporting
 error_reporting(E_ALL);
 
-// Determine directory (special case for development servers)
+//
+// Determine the location of Enano as an absolute path.
+//
+
+// We need to see if this is a specially marked Enano development server. You can create an Enano
+// development server by cloning the Mercurial repository into a directory named repo, and then
+// using symlinks to reference the original files so as to segregate unique files from non-unique
+// and distribution-standard ones. Enano will pivot its root directory accordingly if the file
+// .enanodev is found in the Enano root (not /repo/).
 if ( strpos(__FILE__, '/repo/') && ( file_exists('.enanodev') || file_exists('../.enanodev') ) )
 {
+  // We have a development directory. Remove /repo/ from the picture.
   $filename = str_replace('/repo/', '/', __FILE__);
 }
 else
 {
+  // Standard Enano installation
   $filename = __FILE__;
 }
 
-if(!defined('ENANO_ROOT')) // ENANO_ROOT is sometimes defined by plugins like AjIM that need the constant before the Enano API is initialized
+// ENANO_ROOT is sometimes defined by plugins like AjIM that need the constant before the Enano API is initialized
+if ( !defined('ENANO_ROOT') )
   define('ENANO_ROOT', dirname(dirname($filename)));
 
-if(defined('ENANO_DEBUG') && version_compare(PHP_VERSION, '5.0.0') < 0)
+// Debugging features are PHP5-specifid
+if ( defined('ENANO_DEBUG') && version_compare(PHP_VERSION, '5.0.0') < 0 )
 {
   die(__FILE__.':'.__LINE__.': The debugConsole requires PHP 5.x.x or greater. Please comment out the ENANO_DEBUG constant in your index.php.');
 }
 
-/*
-if(defined('ENANO_DEBUG'))
-{
-  require_once(ENANO_ROOT.'/includes/debugger/debugConsole.php');
-} else {
-*/
-  function dc_here($m)     { return false; }
-  function dc_dump($a, $g) { return false; }
-  function dc_watch($n)    { return false; }
-  function dc_start_timer($u) { return false; }
-  function dc_stop_timer($m) { return false; }
-//}
+// We deprecated debugConsole in 1.0.2 because it was never used and there were a lot of unneeded debugging points in the code.
 
+// _nightly.php is used to tag non-Mercurial-generated nightly builds
 if ( file_exists( ENANO_ROOT . '/_nightly.php') )
   require(ENANO_ROOT.'/_nightly.php');
 
-// List of scheduled tasks
+// List of scheduled tasks (don't change this manually, use register_cron_task())
 $cron_tasks = array();
 
 // Start including files. LOTS of files. Yeah!
 require_once(ENANO_ROOT.'/includes/constants.php');
-dc_here('Enano CMS '.$version.' (dev) - debug window<br />Powered by debugConsole');
-dc_here('common: including files');
 require_once(ENANO_ROOT.'/includes/functions.php');
 require_once(ENANO_ROOT.'/includes/dbal.php');
 require_once(ENANO_ROOT.'/includes/paths.php');
@@ -101,28 +123,50 @@
 
 strip_magic_quotes_gpc();
 
-// Enano has five parts: the database abstraction layer (DBAL), the session manager, the path/URL manager, the template engine, and the plugin manager.
-// Each part has its own class and a global var; nearly all Enano functions are handled by one of these five components.
+// Enano has five main components: the database abstraction layer (DBAL), the session manager,
+// the path/URL manager, the template engine, and the plugin manager.
+// Each part has its own class and a global object; nearly all Enano functions are handled by one of these five components.
+// All of these classes are singletons and are designed to carry as much data as possible within the object
+// to make data access and function calling easy.
 
 global $db, $session, $paths, $template, $plugins; // Common objects
 global $enano_config; // A global used to cache config information without making loads of queries ;-)
                       // In addition, $enano_config is used to fetch config information if die_semicritical() is called.
-                      
+
+// Jim Tucek's e-mail encryption code                      
 global $email;
+
+// Language object
 global $lang;
 
-if(!isset($_SERVER['HTTP_HOST'])) grinding_halt('Cannot get hostname', '<p>Your web browser did not provide the HTTP Host: field. This site requires a modern browser that supports the HTTP 1.1 standard.</p>');
-                     
+// Because Enano sends out complete URLs in several occasions, we need to know what hostname the user is requesting the page from.
+// In future versions we may include a fallback "safety" host to use, but that's too much to worry about now
+if ( !isset($_SERVER['HTTP_HOST']) )
+  grinding_halt('Cannot get hostname', '<p>Your web browser did not provide the HTTP Host: field. This site requires a modern browser that supports the HTTP 1.1 standard.</p>');
+
+//
+// END BACKGROUND AND ENVIRONMENT CHECKS
+//
+
+//
+// MAIN API INITIALIZATION
+//
+
+// The first thing we need to do is start the database connection. At this point, for all we know, Enano might not
+// even be installed. If this connection attempt fails and it's because of a missing or corrupt config file, the
+// user will be redirected (intelligently) to install.php.
 $db = new mysql();
-dc_here('common: calling $db->connect();');
-$db->connect(); // Redirects to install.php if an installation is not detected
+$db->connect();
 
-if(strstr(contentPath, '?')) $sep = '&';
-else $sep = '?';
+// The URL separator is the character appended to contentPath + url_title type strings.
+// If the contentPath has a ? in it, this should be an ampersand; else, it should be a
+// question mark.
+$sep = ( strstr(contentPath, '?') ) ? '&' : '?';
 define('urlSeparator', $sep);
 unset($sep); // save 10 bytes of memory...
 
-// See if any diagnostic actions have been requested
+// Sometimes there are critical failures triggered by initialization functions in the Enano API that are recurring
+// and cannot be fixed except for manual intervention. This is where that code should go.
 if ( isset($_GET['do']) && $_GET['do'] == 'diag' && isset($_GET['sub']) )
 {
   switch($_GET['sub'])
@@ -137,12 +181,15 @@
 }
 
 // Select and fetch the site configuration
-dc_here('common: selecting global config data');
 $e = $db->sql_query('SELECT config_name, config_value FROM '.table_prefix.'config;');
-if(!$e) $db->_die('Some critical configuration information could not be selected.');
-else define('ENANO_CONFIG_FETCHED', ''); // Used in die_semicritical to figure out whether to call getConfig() or not
+if ( !$e )
+{
+  $db->_die('Some critical configuration information could not be selected.');
+}
+// Used in die_semicritical to figure out whether to call getConfig() or not
+define('ENANO_CONFIG_FETCHED', '');
 
-dc_here('common: fetching $enano_config');
+// Initialize and fetch the site configuration array, which is used to cache the config
 $enano_config = Array();
 while($r = $db->fetchrow())
 {
@@ -151,7 +198,8 @@
 
 $db->free_result();
 
-if(enano_version(false, true) != $version)
+// Now that we have the config, check the Enano version.
+if ( enano_version(false, true) != $version )
 {
   grinding_halt('Version mismatch', '<p>It seems that the Enano release we\'re trying to run ('.$version.') is different from the version specified in your database ('.enano_version().'). Perhaps you need to <a href="'.scriptPath.'/upgrade.php">upgrade</a>?</p>');
 }
@@ -234,32 +282,49 @@
     table_prefix.'tags'
   );
 
-dc_here('common: initializing base classes');
+// Load plugin manager
 $plugins = new pluginLoader();
 
-// So where does the majority of Enano get executed? How about the next nine lines of code :)
-dc_here('common: ok, we\'re set up, starting mainstream execution');
+//
+// Mainstream API boot-up
+//
 
+// Obtain list of plugins
 $plugins->loadAll();
-dc_here('common: loading plugins');
-  global $plugins;
-  foreach($plugins->load_list as $f) { include_once $f; } // Can't be in object context when this is done
+
+global $plugins;
 
+// Load plugins from common because we can't give plugins full abilities in object context
+foreach ( $plugins->load_list as $f )
+{
+  include_once $f;
+}
+
+// Three fifths of the Enano API gets the breath of life right here.
 $session = new sessionManager();
 $paths = new pathManager();
 $template = new template();
 $email = new EmailEncryptor();
 
+// We've got the five main objects - flick on the switch so if a problem occurs, we can have a "friendly" UI
 define('ENANO_BASE_CLASSES_INITIALIZED', '');
 
+// From here on out, none of this functionality is needed during the installer stage.
+// Once $paths->init() is called, we could be redirected to the main page, so we don't want
+// that if the installer's running. Don't just go and define IN_ENANO_INSTALL from your
+// script though, because that will make the DBAL look in the wrong place for the config file.
 if ( !defined('IN_ENANO_INSTALL') )
 {
+  // And here you have it, the de facto way to place a hook. Plugins can place hooks and hook
+  // into other plugins. You just never know.
   $code = $plugins->setHook('base_classes_initted');
   foreach ( $code as $cmd )
   {
     eval($cmd);
   }
-    
+  
+  // For special and administration pages, sometimes there is a "preloader" function that must be run
+  // before the session manager and/or path manager get the init signal. Call it here.  
   $p = RenderMan::strToPageId($paths->get_pageid_from_url());
   if( ( $p[1] == 'Admin' || $p[1] == 'Special' ) && function_exists('page_'.$p[1].'_'.$p[0].'_preloader'))
   {
@@ -271,10 +336,12 @@
   {
     die('SECURITY: spoofed IP address');
   }
-  
+
+  // All checks passed! Start the main components up.  
   $session->start();
   $paths->init();
   
+  // We're ready for whatever life throws us now.
   define('ENANO_MAINSTREAM', '');
   
   // If the site is disabled, bail out, unless we're trying to log in or administer the site
@@ -299,18 +366,26 @@
       die_semicritical('Site disabled', $text);
     }
   }
-  else if(getConfig('site_disabled') == '1' && $session->user_level >= USER_LEVEL_ADMIN)
+  else if ( getConfig('site_disabled') == '1' && $session->user_level >= USER_LEVEL_ADMIN )
   {
+    // If the site is disabled but the user has admin rights, allow browsing
+    // and stuff, but display the orange box notifying the admin.
     $template->site_disabled = true;
   }
   
+  // A better name for this hook would be common_post. At this point
+  // all of Enano is fully initialized and running and you're ready
+  // to do whatever you want.
   $code = $plugins->setHook('session_started');
   foreach ( $code as $cmd )
   {
     eval($cmd);
   }
   
-  if(isset($_GET['noheaders'])) $template->no_headers = true;
+  if ( isset($_GET['noheaders']) )
+    $template->no_headers = true;
 }
 
+// That's the end. Enano should be loaded now :-)
+
 ?>
--- a/includes/dbal.php	Sun Dec 02 16:00:56 2007 -0500
+++ b/includes/dbal.php	Fri Dec 07 16:42:22 2007 -0500
@@ -124,8 +124,6 @@
   {
     $this->enable_errorhandler();
     
-    dc_here('dbal: trying to connect....');
-    
     if ( defined('IN_ENANO_INSTALL') && !defined('IN_ENANO_UPGRADE') )
     {
       @include(ENANO_ROOT.'/config.new.php');
@@ -140,7 +138,6 @@
     
     if ( !defined('ENANO_INSTALLED') && !defined('MIDGET_INSTALLED') && !defined('IN_ENANO_INSTALL') )
     {
-      dc_here('dbal: oops, looks like Enano isn\'t set up. Constants ENANO_INSTALLED, MIDGET_INSTALLED, and IN_ENANO_INSTALL are all undefined.');
       // scriptPath isn't set yet - we need to autodetect it to avoid infinite redirects
       if ( !defined('scriptPath') )
       {
@@ -169,7 +166,6 @@
     
     if ( !$this->_conn )
     {
-      dc_here('dbal: uhoh!<br />'.mysql_error());
       grinding_halt('Enano is having a problem', '<p>Error: couldn\'t connect to MySQL.<br />'.mysql_error().'</p>');
     }
     
@@ -181,15 +177,12 @@
     
     $this->debug = ( defined('ENANO_DEBUG') );
     
-    dc_here('dbal: we\'re in, selecting database...');
     $q = $this->sql_query('USE `'.$dbname.'`;');
     
     if ( !$q )
       $this->_die('The database could not be selected.');
     
     // We're in!
-    dc_here('dbal: connected to MySQL');
-    
     $this->disable_errorhandler();
     return true;
   }
@@ -219,7 +212,6 @@
     $this->num_queries++;
     $this->query_backtrace[] = $q;
     $this->latest_query = $q;
-    dc_here('dbal: making SQL query:<br /><tt>'.$q.'</tt>');
     // First make sure we have a connection
     if ( !$this->_conn )
     {
@@ -247,7 +239,6 @@
     $this->num_queries++;
     $this->query_backtrace[] = '(UNBUFFERED) ' . $q;
     $this->latest_query = $q;
-    dc_here('dbal: making SQL query:<br /><tt>'.$q.'</tt>');
     // First make sure we have a connection
     if ( !$this->_conn )
     {
@@ -454,7 +445,6 @@
   }
   
   function close() {
-    dc_here('dbal: closing MySQL connection');
     mysql_close($this->_conn);
     unset($this->_conn);
   }
--- a/includes/debugger/debugConsole.class.php	Sun Dec 02 16:00:56 2007 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,479 +0,0 @@
-<?php
-/**
- * debugConsole class
- *
- * This class allows opening an external JavaScript
- * window for debugging purposes.
- *
- * @author Andreas Demmer <info@debugconsole.de>
- * @see <http://www.debugconsole.de>
- * @version 1.2.1
- * @package debugConsole_1.2.1
- */
-class debugConsole {
-	/**
-	 * events which are shown in debug console
-	 *
-	 * @var array
-	 */
-	protected $filters;
-	
-	/**
-	 * all watched variables with their current content
-	 *
-	 * @var array
-	 */
-	protected $watches;
-	
-	/**
-	 * debugConsole configuration values
-	 *
-	 * @var array
-	 */
-	protected $config;
-	
-	/**
-	 * URL where template can be found
-	 *
-	 * @var string
-	 */
-	protected $template;
-
-	/**
-	 * javascripts to control popup
-	 *
-	 * @var array
-	 */
-	protected $javascripts;
-
-	/**
-	 * html for popup
-	 *
-	 * @var array
-	 */
-	protected $html;
-
-	/**
-	 * time of debugrun start in milliseconds
-	 *
-	 * @var string
-	 */
-	protected $starttime;
-
-	/**
-	 * time of timer start in milliseconds
-	 *
-	 * @var array
-	 */
-	protected $timers;
-
-	/**
-	 * constructor, opens popup window
-	 */
-	public function __construct () {
-		/* initialize class vars */
-		$this->starttime = $this->getMicrotime();
-		$this->watches = array ();
-		$this->config = $GLOBALS['_debugConsoleConfig'];
-		$this->html = $this->config['html'];
-		$this->html['header'] = str_replace("\n\r", NULL, $this->html['header']);
-		$this->html['header'] = str_replace("\n", NULL, $this->html['header']);
-		$this->javascripts = $this->config['javascripts'];
-		
-		/* replace PHP's errorhandler */
-		$errorhandler = array (
-			$this,
-			'errorHandlerCallback'
-		);
-		
-		set_error_handler($errorhandler);
-		
-		/* open popup */
-		$popupOptions = "', 'debugConsole', 'width=" . $this->config['dimensions']['width'] . ",height=" . $this->config['dimensions']['height'] . ',scrollbars=yes';
-		
-		$this->sendCommand('openPopup', $popupOptions);
-		$this->sendCommand('write', $this->html['header']);
-		
-		$this->startDebugRun();
-	}
-	
-	/**
-	 * destructor, shows runtime and finishes html document in popup window
-	 */
-	public function __destruct () {
-		$runtime = $this->getMicrotime() - $this->starttime;
-		$runtime = number_format((float)$runtime, 4, '.', NULL);
-		
-		$info = '<p class="runtime">This debug-run took ' . $runtime . ' seconds to complete.</p>';
-
-		$this->sendCommand('write', $info);
-		$this->sendCommand('write', '</div>');
-		$this->sendCommand('scroll', "0','100000");
-		$this->sendCommand('write', $this->html['footer']);
-		
-		if ($this->config['focus']) {
-			$this->sendCommand('focus');
-		}
-	}
-	
-	/**
-	 * show new debug run header in console
-	 */
-	
-	protected function startDebugRun () {
-		$info = '<h1>new debug-run (' . date('H:i') . ' hours)</h1>';
-		$this->sendCommand('write', '<div>');
-		$this->sendCommand('write', $info);
-	}
-
-	/**
-	 * adds a variable to the watchlist
-	 * 
-	 * Watched variables must be in a declare(ticks=n)
-	 * block so that every n ticks the watched variables
-	 * are checked for changes. If any changes were made,
-	 * the new value of the variable is shown in the
-	 * debugConsole with additional information where the
-	 * changes happened.
-	 *
-	 * @param string $variableName
-	 */
-	public function watchVariable ($variableName) {
-		if (count($this->watches) === 0) {
-			$watchMethod = array (
-				$this,
-				'watchesCallback'
-			);
-			
-			register_tick_function($watchMethod);
-		}
-		
-		if (isset($GLOBALS[$variableName])) {
-			$this->watches[$variableName] = $GLOBALS[$variableName];
-		} else {
-			$this->watches[$variableName] = NULL;
-		}
-	}
-	
-	/**
-	 * tick callback: process watches and show changes
-	 */
-	public function watchesCallback () {
-		if ($this->config['filters']['watches']) {
-			foreach ($this->watches as $variableName => $variableValue) {
-				if ($GLOBALS[$variableName] !== $this->watches[$variableName]) {
-					$info = '<p class="watch"><strong>$' . $variableName;
-					$info .= '</strong> changed from "';
-					$info .= $this->watches[$variableName];
-					$info .= '" (' . gettype($this->watches[$variableName]) . ')';
-					$info .= ' to "' . $GLOBALS[$variableName] . '" (';
-					$info .= gettype($GLOBALS[$variableName]) . ')';
-					$info .= $this->getTraceback() . '</p>';
-					
-					$this->watches[$variableName] = $GLOBALS[$variableName];
-					$this->sendCommand('write', $info);
-				}
-			}
-		}
-	}
-	
-	/**
-	 * sends a javascript command to browser
-	 *
-	 * @param string $command
-	 * @param string $value
-	 */
-	protected function sendCommand ($command, $value = FALSE) {
-    if($command == 'write') $value = '\'+unescape(\''.rawurlencode($value).'\')+\'';
-		$value = str_replace('\\', '\\\\', $value);
-    $value = nl2br($value);
-		
-		if ((bool)$value) { 
-			/* write optionally logfile */
-			$this->writeLogfileEntry($command, $value);
-			
-			$command = $this->javascripts[$command] . "('" . $value . "');";
-		} else {
-			$command = $this->javascripts[$command] . ';';
-		}
-		
-		$command = str_replace("\n\r", NULL, $command);
-		$command = str_replace("\n", NULL, $command);
-		
-		if (!$this->config['logfile']['disablePopup']) {
-			echo $this->javascripts['openTag'], "\n";
-			echo $command, "\n";
-			echo $this->javascripts['closeTag'], "\n";
-		}
-		
-		flush();
-	}
-	
-	/**
-	 * writes html output as text entry into logfile
-	 *
-	 * @param string $command
-	 * @param string $value
-	 */
-	protected function writeLogfileEntry ($command, $value) {
-		if ($this->config['logfile']['enable']) {
-			$logfile = $this->config['logfile']['path'] . $this->config['logfile']['filename'];
-			/* log only useful entries, no html header and footer */
-			if (
-				$command === 'write'
-				&& !strpos($value, '<html>')
-				&&  !strpos($value, '</html>')
-			) {
-				/* convert html to text */
-				$value = html_entity_decode($value);
-				$value = str_replace('>', '> ', $value);
-				$value = strip_tags($value);
-				
-				$fp = fopen($logfile, 'a+');
-				fputs($fp, $value . "\n\n");
-				fclose($fp);
-			} elseif (strpos($value, '</html>')) {
-				$fp = fopen($logfile, 'a+');
-				fputs($fp, "-----------\n");
-				fclose($fp);
-			}
-		}
-	}
-
-	/**
-	 * shows in console that a checkpoint has been passed,
-	 * additional info is the file and line which triggered
-	 * the output
-	 *
-	 * @param string $message
-	 */	
-	public function passedCheckpoint ($message = NULL) {
-		if ($this->config['filters']['checkpoints']) {
-			$message = (bool)$message ? $message : 'Checkpoint passed!';
-	
-			$info = '<p class="checkpoint"><strong>' . $message . '</strong>';
-			$info .= $this->getTraceback() . '</p>';
-			
-			$this->sendCommand('write', $info);
-		}
-	}
-	
-	/**
-	 * returns microtime as float value
-	 *
-	 * @return float
-	 */
-	protected function getMicrotime () {
-		list($usec, $sec) = explode(' ', microtime()); 
-    	return ((float)$usec + (float)$sec);
-	}
-	
-	/**
-	 * returns all possible filter events for debugConsole::setFilter() method
-	 *
-	 * @return array
-	 */
-	public function getFilters () {
-		$filters = array_keys($this->config['filters']);
-		
-		ksort($filters);
-		reset($filters);
-		
-		return $filters; 
-	}
-	
-	/**
-	 * shows or hides an event-type in debugConsole,
-	 * returns previous setting of the given event-type
-	 *
-	 * @param string $event
-	 * @param bool $isShown
-	 * @return bool
-	 */
-	public function setFilter ($event, $isShown) {
-		if (array_key_exists($event, $this->config['filters'])) {
-			$oldValue = $this->config['filters'][$event];
-			$this->config['filters'][$event] = $isShown;
-		} else {
-			throw new Exception ('debugConsole: unknown event "' . $event . '" in debugConsole::filter()');
-		}
-		
-		return $oldValue;
-	}
-	
-	/**
-	 * show debug info for variable in debugConsole,
-	 * added by custom text for documentation and hints
-	 *
-	 * @param mixed $variable
-	 * @param string $text
-	 */
-	public function dump ($variable, $text) {
-		if ($this->config['filters']['debug']) {
-			@ob_start();
-			
-			/* grab current ob content */
-			$obContents = ob_get_contents();
-			ob_clean();
-			
-			/* grap var dump from ob */
-			var_dump($variable);
-			$variableDebug = ob_get_contents();
-			ob_end_clean();
-			
-			/* restore previous ob content */
-			if ((bool)$obContents) echo $obContents;
-			
-			/* render debug */
-			$variableDebug = htmlspecialchars($variableDebug);			
-			$infos = '<p class="dump">' . $text . '<br />';
-			
-			if (is_array($variable)) {
-				$variableDebug = str_replace(' ', '&nbsp;', $variableDebug);
-				$infos .= '<span class="source">' . $variableDebug . '</span>';
-			} else {
-				$infos .= '<strong>' . $variableDebug . '</strong>';
-			}
-			
-			$infos .= $this->getTraceback() . '</p>';
-			$this->sendCommand('write', $infos);
-		}
-	}
-	
-	/**
-	 * callback method for PHP errorhandling
-	 * 
-	 * @todo implement more errorlevels
-	 */
-	public function errorHandlerCallback () {
-		$details = func_get_args();
-		$details[1] = str_replace("'", '"', $details[1]);
-		$details[1] = str_replace('href="function.', 'target="_blank" href="http://www.php.net/', $details[1]);
-		
-		
-		/* determine error level */
-		switch ($details[0]) {
-			case 2:
-				if (!$this->config['filters']['php_warnings']) return;
-				$errorlevel = 'warning';
-				break;
-			case 8:
-				if (!$this->config['filters']['php_notices']) return;
-				$errorlevel = 'notice';
-				break;
-			case 2048:
-				if (!$this->config['filters']['php_suggestions']) return;
-				$errorlevel = 'suggestion';
-				break;
-		}
-
-		$file = $this->cropScriptPath($details[2]);
-		
-		$infos = '<p class="' . $errorlevel . '"><strong>';
-		$infos .= 'PHP ' . strtoupper($errorlevel) . '</strong>';
-		$infos .= $details[1] . '<span class="backtrace">';
-		$infos .= $file . ' on line ';
-		$infos .= $details[3] . '</span></p>';		
-		
-		$this->sendCommand('write', $infos);
-	}
-	
-	/**
-	 * start timer clock, returns timer handle
-	 * 
-	 * @return mixed
-	 * @param string $comment
-	 */
-	public function startTimer ($comment) {
-		if ($this->config['filters']['timers']) {
-			$timerHandle = md5(microtime());
-			
-			$this->timers[$timerHandle] = array (
-				'starttime' => $this->getMicrotime(),
-				'comment' => $comment
-			);
-		} else {		
-			$timerHandle = FALSE;		
-		}
-		
-		return $timerHandle;
-	}
-	
-	/**
-	 * stop timer clock
-	 * 
-	 * @return bool
-	 * @param string $timerHandle
-	 */
-	public function stopTimer ($timerHandle) {
-		if ($this->config['filters']['timers']) {
-			if (array_key_exists($timerHandle, $this->timers)) {
-				$timerExists = TRUE;
-				$timespan = $this->getMicrotime() - $this->timers[$timerHandle]['starttime'];
-			
-				$info = '<p class="timer"><strong>' . $this->timers[$timerHandle]['comment'];
-				$info .= '</strong><br />The timer ran ';
-				$info .= '<strong>' . number_format ($timespan, 4, '.', NULL) . '</strong>';
-				$info .= ' seconds.' . $this->getTraceback() . '</p>';
-			
-				$this->sendCommand('write', $info);
-			} else {
-				$timerExists = FALSE;
-			}
-		} else {
-			$timerExists = FALSE;
-		}
-		
-		return $timerExists;
-	}
-	
-	/**
-	 * returns a formatted traceback string
-	 *
-	 * @return string
-	 */
-	public function getTraceback () {
-		$callStack = debug_backtrace();
-
-		$debugConsoleFiles = array(
-			'debugConsole.class.php',
-			'debugConsole.functions.php'
-		);
-		
-		$call = array (
-			'file' => 'debugConsole.class.php'
-		);
-		
-		while(in_array(basename($call['file']), $debugConsoleFiles)) {
-			$call = array_shift($callStack);
-		}
-
-		$call['file'] = $this->cropScriptPath($call['file']);
-		
-		$traceback = '<span class="backtrace">';
-		$traceback .= $call['file'] . ' on line ';
-		$traceback .= $call['line'] . '</span>';
-		
-		return $traceback;
-	}
-	
-	/**
-	 * crops long script path, shows only the last $maxLength chars
-	 *
-	 * @param string $path
-	 * @param int $maxLength
-	 * @return string
-	 */
-	protected function cropScriptPath ($path, $maxLength = 30) {
-		if (strlen($path) > $maxLength) {
-			$startPos = strlen($path) - $maxLength - 2;
-			
-			if ($startPos > 0) {
-				$path = '...' . substr($path, $startPos);
-			}
-		}
-
-		return $path;
-	}
-}
-?>
\ No newline at end of file
--- a/includes/debugger/debugConsole.config.php	Sun Dec 02 16:00:56 2007 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,196 +0,0 @@
-<?php
-/**
- * debugConsole configuration
- *
- * @author Andreas Demmer <info@debugconsole.de>
- * @see <http://www.debugconsole.de>
- * @version 1.2.1
- * @package debugConsole_1.2.1
- */
-
-/**
- * config container for debugConsole
- *
- * @var array
- */
-$_debugConsoleConfig = array();
-
-/**
- * use debugConsole
- */
-$_debugConsoleConfig['active'] = TRUE;
-
-/**
- * restrict access
- */
-$_debugConsoleConfig['restrictions'] = array (
-	'restrictAccess' => FALSE,
-	'allowedClientAdresses' => array('127.0.0.1')
-);
-
-/**
- * set timezone, used for PHP >= 5.1.x
- */
-putenv ('TZ=America/New_York');
-
-/**
- * focus debugConsole at end of debug-run
- */
-$_debugConsoleConfig['focus'] = TRUE;
-
-
-/**
- * logfile configuration
- */
-$_debugConsoleConfig['logfile'] = array (
-	'enable' => FALSE,
-	'path' => './',
-	'filename' => 'log.txt',
-	'disablePopup' => FALSE
-);
-
-/**
- * show or hide certain events
- */
-$_debugConsoleConfig['filters'] = array (
-	'debug' => TRUE,
-	'watches' => TRUE,
-	'checkpoints' => TRUE,
-	'timers' => TRUE,
-	'php_notices' => TRUE,
-	'php_warnings' => TRUE,
-	'php_errors' => TRUE,
-	'php_suggestions' => FALSE
-);
-
-/**
- * popup dimensions in px
- */
-$_debugConsoleConfig['dimensions'] = array (
-	'width' => 300,
-	'height' => 525
-);
-
-/**
- * javascript snippets, do not touch!
- */
-$_debugConsoleConfig['javascripts'] = array (
-	'openTag' => '<script language="JavaScript" type="text/javascript">',
-	'closeTag' => '</script>',
-	'openPopup' => 'debugConsole = window.open',
-	'closePopup' => 'debugConsole.close()',
-	'write' => 'debugConsole.document.write',
-	'scroll' => 'debugConsole.scrollBy',
-	'focus' => 'debugConsole.focus()'
-);
-
-/**
- * html snippets, do not touch!
- */
-$_debugConsoleConfig['html'] = array (
-	'header' => '
-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
-  <html>
-    <head>
-      <title>debugConsole</title>
-      <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
-      <meta name="language" content="en" />
-      <style type="text/css">
-        * {
-        	margin: 0px; 
-        	padding: 0px;
-        }
-        
-        body {
-        	font-family: arial, sans-serif;
-        	font-size: 0.7em;
-        	color: black;
-        	background-color: white;
-        	padding: 5px;
-        }
-        
-        h1 {
-        	background-color: #888;
-        	color: white;
-        	font-size: 100%;
-        	padding: 3px;
-        	margin: 0px 0px 5px 0px;
-        	border: 0px;
-        	border-bottom: 4px solid #ccc;
-        }
-        
-        p {
-        	border: 1px solid #888;
-        	border-left: 5px solid #888;
-        	background-color: white;
-        	padding: 3px;
-        	margin: 5px 3px;
-        }
-        
-        div {
-            background-color: #eee;
-            border: 1px solid #888;
-            margin: 0px 0px 25px 0px;
-        }
-        
-        .dump {
-        }
-        
-        .dump .source {
-            font-family: courier, sans-serif;
-        }
-                
-        .backtrace {
-        	display: block;
-			color: #aaa;
-        }
-        
-        .watch {
-        	border-color: #BF1CBF;
-        }
-
-        .checkpoint {
-        	border-color: #00E600;
-        } 
-        
-        .timer {
-        	border-color: blue;
-        } 
-        
-        .notice, .suggestion {
-        	border-color: orange;
-        }
-        
-        .warning {
-        	border-color: red;
-        }
-
-        .notice strong, .warning strong, .suggestion strong {
-        	font-weight: bold;
-        	display: block;
-        }
-    
-        .notice strong, .suggestion strong {
-        	color: orange;
-        }
-    
-        .warning strong {
-        	color: red;
-        }
-        
-        .runtime {
-            margin: 0px;
-            padding: 0px;
-            border: 0px;
-            width: 100%;
-            text-align: center;
-            background-color: transparent;
-            color: #666;
-        }
-               
-      </style>
-    </head>
-  <body>',
-	'footer' => '</body></html>'
-);
-?>
\ No newline at end of file
--- a/includes/debugger/debugConsole.functions.php	Sun Dec 02 16:00:56 2007 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,126 +0,0 @@
-<?php
-/**
- * debugConsole functions
- *
- * @author Andreas Demmer <info@debugconsole.de>
- * @see <http://www.debugconsole.de>
- * @version 1.0.0
- * @package debugConsole_1.2.1
- */
-
-/**
- * show debug info of a variable in debugConsole,
- * add own text for documentation or hints
- * 
- * @param mixed $variable
- * @param string $text
- */
-function dc_dump($variable, $text) {
-  if(!defined('ENANO_DEBUG')) return false;
-	$debugConsole = debugConsoleLoader();
-	
-	if (is_object($debugConsole)) {
-		$debugConsole->dump($variable, $text);
-	}
-}
-
-/**
- * watch value changes of a variable in debugConsole
- *
- * @param string $variableName
- */
-function dc_watch($variableName) {
-  if(!defined('ENANO_DEBUG')) return false;
-	$debugConsole = debugConsoleLoader();
-	
-	if (is_object($debugConsole)) {
-		$debugConsole->watchVariable($variableName);
-	}
-}
-
-/**
- * show checkpoint info in debugConsole to make sure
- * that a certain program line has been passed
- *
- * @param string $message
- */
-function dc_here($message = NULL) {
-  if(!defined('ENANO_DEBUG')) return false;
-	$debugConsole = debugConsoleLoader();
-	
-	if (is_object($debugConsole)) {
-		(bool)$message ? $debugConsole->passedCheckpoint($message) : $debugConsole->passedCheckpoint();
-	}
-}
-
-/**
- * starts a new timer clock and returns its handle
- *
- * @return mixed
- * @param string $comment
- */
-function dc_start_timer($comment) {
-  if(!defined('ENANO_DEBUG')) return false;
-	$debugConsole = debugConsoleLoader();
-	
-	if (is_object($debugConsole)) {
-		return $debugConsole->startTimer($comment);
-	}
-}
-
-/**
- * stops and shows a certain timer clock in debugConsole
- *
- * @return bool
- * @param string $timerHandle
- */
-function dc_stop_timer($timerHandle) {
-  if(!defined('ENANO_DEBUG')) return false;
-	$debugConsole = debugConsoleLoader();
-	
-	if (is_object($debugConsole)) {
-		return $debugConsole->stopTimer($timerHandle);
-	}
-}
-
-/**
- * singleton loader for debugConsole
- * DO NOT USE, private to debugConsole functions
- *
- * @return mixed
- */
-function debugConsoleLoader() {
-	static $debugConsole;
-	static $access = 'unset';
-
-	$config = $GLOBALS['_debugConsoleConfig'];
-	
-	/* obey access restrictions */
-	if (gettype($access) != 'bool') {
-		if ($config['active']) {
-			if ($config['restrictions']['restrictAccess']) {
-				if (in_array($_SERVER['REMOTE_ADDR'], $config['restrictions']['allowedClientAdresses'])) {
-					$access = TRUE;
-				} else {
-					$access = FALSE;
-				}
-			} else {
-				$access = TRUE;
-			}
-		} else {
-			$access = FALSE;
-		}
-	}
-	
-	/* access granted */
-	if ($access) {
-		if (!is_object($debugConsole)) {
-			$debugConsole = new debugConsole();
-		}
-	} else {
-		$debugConsole = FALSE;
-	}
-	
-	return $debugConsole;
-}
-?>
\ No newline at end of file
--- a/includes/debugger/debugConsole.php	Sun Dec 02 16:00:56 2007 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,16 +0,0 @@
-<?php
-/**
- * debugConsole includes
- *
- * @author Andreas Demmer <info@debugconsole.de>
- * @see <http://www.debugconsole.de>
- * @version 1.0.0
- * @package debugConsole_1.2.1
- */
-
-$path = dirname(__FILE__) . '/';
-
-require_once $path . 'debugConsole.config.php';
-require_once $path . 'debugConsole.class.php';
-require_once $path . 'debugConsole.functions.php';
-?>
\ No newline at end of file
--- a/includes/functions.php	Sun Dec 02 16:00:56 2007 -0500
+++ b/includes/functions.php	Fri Dec 07 16:42:22 2007 -0500
@@ -485,8 +485,6 @@
   if ( ob_get_status() )
     ob_end_clean();
 
-  dc_here('functions: <span style="color: red">calling die_semicritical</span>');
-
   $tpl = new template_nodb();
   $tpl->load_theme('oxygen', 'bleu');
   $tpl->tpl_strings['SITE_NAME'] = getConfig('site_name');
@@ -513,7 +511,6 @@
   if ( ob_get_status() )
     ob_end_clean();
 
-  dc_here('functions: <span style="color: red">calling die_friendly</span>');
   $paths->cpage['name'] = $t;
   $template->tpl_strings['PAGE_NAME'] = $t;
   $template->header();
@@ -543,7 +540,6 @@
   if ( ob_get_status() )
     ob_end_clean();
 
-  dc_here('functions: <span style="color: red">calling grinding_halt</span>');
   $tpl = new template_nodb();
   $tpl->load_theme('oxygen', 'bleu');
   $tpl->tpl_strings['SITE_NAME'] = 'Critical error';
--- a/includes/index.php	Sun Dec 02 16:00:56 2007 -0500
+++ b/includes/index.php	Fri Dec 07 16:42:22 2007 -0500
@@ -1,13 +1,10 @@
 <?php
 
-$_GET['title'] = 'Enano:Access_denied';
+$title = 'Access denied';
 require('../includes/common.php');
 header('HTTP/1.1 403 Forbidden');
-$session->perms['edit_page'] = AUTH_DENY;
-$session->perms['view_source'] = AUTH_DENY;
-$template->tpl_strings['PAGE_NAME'] = 'Access denied';
 
 $template->header();
-echo '<p>The administrator has flagged the page "' . $_SERVER['REQUEST_URI'] . '" so that it cannot be accessed from the web. Perhaps this is because this is a cache or includes directory and only needs to be accessed by scripts.</p><p>HTTP error: 403 Forbidden</p>';
+echo '<p>The administrator has flagged the page "' . htmlspecialchars($_SERVER['REQUEST_URI']) . '" so that it cannot be accessed from the web. Perhaps this is because this is a cache or includes directory and only needs to be accessed by scripts.</p><p>HTTP error: 403 Forbidden</p>';
 $template->footer();
-$db->close();
+
--- a/includes/pageprocess.php	Sun Dec 02 16:00:56 2007 -0500
+++ b/includes/pageprocess.php	Fri Dec 07 16:42:22 2007 -0500
@@ -232,7 +232,16 @@
       echo $text;
       
       $this->footer();
-      
+    }
+    else if ( $this->namespace == 'Anonymous' )
+    {
+      $uri = scriptPath . '/' . $this->page_id;
+      if ( !$this->send_headers )
+      {
+        $sep = ( strstr($uri, '?') ) ? '&' : '?';
+        $uri .= "{$sep}noheaders";
+      }
+      redirect( $uri, '', '', 0 );
     }
     else if ( !$this->page_exists )
     {
--- a/includes/paths.php	Sun Dec 02 16:00:56 2007 -0500
+++ b/includes/paths.php	Fri Dec 07 16:42:22 2007 -0500
@@ -18,7 +18,7 @@
  */
  
 class pathManager {
-  var $pages, $custom_page, $cpage, $page, $fullpage, $page_exists, $namespace, $nslist, $admin_tree, $wiki_mode, $page_protected, $template_cache;
+  var $pages, $custom_page, $cpage, $page, $fullpage, $page_exists, $namespace, $nslist, $admin_tree, $wiki_mode, $page_protected, $template_cache, $anonymous_page;
   function __construct()
   {
     global $db, $session, $paths, $template, $plugins; // Common objects
@@ -26,8 +26,6 @@
     $GLOBALS['paths'] =& $this;
     $this->pages = Array();
     
-    dc_here('paths: setting up namespaces, admin nodes');
-    
     // DEFINE NAMESPACES HERE
     // The key names should NOT EVER be changed, or Enano will be very broken
     $this->nslist = Array(
@@ -40,6 +38,7 @@
       'System'  =>'Enano:',
       'Template'=>'Template:',
       'Category'=>'Category:',
+      'Anonymous'=>'PhysicalRedirect:',
       'Project' =>sanitize_page_id(getConfig('site_name')).':',
       );
     
@@ -110,8 +109,6 @@
   {
     global $db, $session, $paths, $template, $plugins; // Common objects
     
-    dc_here('paths: selecting master page data');
-    
     $code = $plugins->setHook('paths_init_before');
     foreach ( $code as $cmd )
     {
@@ -152,115 +149,148 @@
       
     }
     $db->free_result();
-    dc_here('paths: determining page ID');
-    if( isset($_GET['title']) )
+    if ( defined('ENANO_INTERFACE_INDEX') || defined('ENANO_INTERFACE_AJAX') || defined('IN_ENANO_INSTALL') || defined('IN_ENANO_UPGRADE') )
     {
-      if ( $_GET['title'] == '' && getConfig('main_page') != '' )
-      {
-        $this->main_page();
-      }
-      if(strstr($_GET['title'], ' '))
+      if( isset($_GET['title']) )
       {
-        $loc = urldecode(rawurldecode($_SERVER['REQUEST_URI']));
-        $loc = str_replace(' ', '_', $loc);
-        $loc = str_replace('+', '_', $loc);
-        $loc = str_replace('%20', '_', $loc);
-        redirect($loc, 'Redirecting...', 'Space detected in the URL, please wait whilst you are redirected', 0);
-        exit;
+        if ( $_GET['title'] == '' && getConfig('main_page') != '' )
+        {
+          $this->main_page();
+        }
+        if(strstr($_GET['title'], ' '))
+        {
+          $loc = urldecode(rawurldecode($_SERVER['REQUEST_URI']));
+          $loc = str_replace(' ', '_', $loc);
+          $loc = str_replace('+', '_', $loc);
+          $loc = str_replace('%20', '_', $loc);
+          redirect($loc, 'Redirecting...', 'Space detected in the URL, please wait whilst you are redirected', 0);
+          exit;
+        }
+        $url_namespace_special = substr($_GET['title'], 0, strlen($this->nslist['Special']) );
+        $url_namespace_template = substr($_GET['title'], 0, strlen($this->nslist['Template']) );
+        if($url_namespace_special == $this->nslist['Special'] || $url_namespace_template == $this->nslist['Template'] )
+        {
+          $ex = explode('/', $_GET['title']);
+          $this->page = $ex[0];
+        }
+        else
+        {
+          $this->page = $_GET['title'];
+        }
+        $this->fullpage = $_GET['title'];
       }
-      $url_namespace_special = substr($_GET['title'], 0, strlen($this->nslist['Special']) );
-      $url_namespace_template = substr($_GET['title'], 0, strlen($this->nslist['Template']) );
-      if($url_namespace_special == $this->nslist['Special'] || $url_namespace_template == $this->nslist['Template'] )
+      elseif( isset($_SERVER['PATH_INFO']) )
       {
-        $ex = explode('/', $_GET['title']);
-        $this->page = $ex[0];
+        $pi = explode('/', $_SERVER['PATH_INFO']);
+        
+        if( !isset($pi[1]) || (isset($pi[1]) && $pi[1] == '' && getConfig('main_page') != '') )
+        {
+          $this->main_page();
+        }
+        if( strstr($pi[1], ' ') )
+        {
+          $loc = str_replace(' ', '_', urldecode(rawurldecode($_SERVER['REQUEST_URI'])));
+          $loc = str_replace('+', '_', $loc);
+          $loc = str_replace('%20', '_', $loc);
+          redirect($loc, 'Redirecting...', 'Please wait whilst you are redirected', 3);
+          exit;
+        }
+        unset($pi[0]);
+        if( substr($pi[1], 0, strlen($this->nslist['Special'])) == $this->nslist['Special'] || substr($pi[1], 0, strlen($this->nslist['Template'])) == $this->nslist['Template'] )
+        {
+          $pi2 = $pi[1];
+        }
+        else
+        {
+          $pi2 = implode('/', $pi);
+        }
+        $this->page = $pi2;
+        $this->fullpage = implode('/', $pi);
       }
       else
       {
-        $this->page = $_GET['title'];
-      }
-      $this->fullpage = $_GET['title'];
-    }
-    elseif( isset($_SERVER['PATH_INFO']) )
-    {
-      $pi = explode('/', $_SERVER['PATH_INFO']);
-      
-      if( !isset($pi[1]) || (isset($pi[1]) && $pi[1] == '' && getConfig('main_page') != '') )
-      {
-        $this->main_page();
+        $k = array_keys($_GET);
+        foreach($k as $c)
+        {
+          if(substr($c, 0, 1) == '/')
+          {
+            $this->page = substr($c, 1, strlen($c));
+            
+            // Bugfix for apache somehow passing dots as underscores
+            global $mime_types;
+            
+            $exts = array_keys($mime_types);
+            $exts = '(' . implode('|', $exts) . ')';
+            
+            if ( preg_match( '#_'.$exts.'#i', $this->page ) )
+            {
+              $this->page = preg_replace( '#_'.$exts.'#i', '.\\1', $this->page );
+            }
+            
+            $this->fullpage = $this->page;
+            
+            if(substr($this->page, 0, strlen($this->nslist['Special']))==$this->nslist['Special'] || substr($this->page, 0, strlen($this->nslist['Template']))==$this->nslist['Template'])
+            {
+              $ex = explode('/', $this->page);
+              $this->page = $ex[0];
+            }
+            if(strstr($this->page, ' '))
+            {
+              $loc = str_replace(' ', '_', urldecode(rawurldecode($_SERVER['REQUEST_URI'])));
+              $loc = str_replace('+', '_', $loc);
+              $loc = str_replace('%20', '_', $loc);
+              redirect($loc, 'Redirecting...', 'Space in the URL detected, please wait whilst you are redirected', 0);
+              exit;
+            }
+            break;
+          }
+        }
+        if(!$this->page && !($this->page == '' && getConfig('main_page') == ''))
+        {
+          $this->main_page();
+        }
       }
-      if( strstr($pi[1], ' ') )
-      {
-        $loc = str_replace(' ', '_', urldecode(rawurldecode($_SERVER['REQUEST_URI'])));
-        $loc = str_replace('+', '_', $loc);
-        $loc = str_replace('%20', '_', $loc);
-        redirect($loc, 'Redirecting...', 'Please wait whilst you are redirected', 3);
-        exit;
-      }
-      unset($pi[0]);
-      if( substr($pi[1], 0, strlen($this->nslist['Special'])) == $this->nslist['Special'] || substr($pi[1], 0, strlen($this->nslist['Template'])) == $this->nslist['Template'] )
-      {
-        $pi2 = $pi[1];
-      }
-      else
-      {
-        $pi2 = implode('/', $pi);
-      }
-      $this->page = $pi2;
-      $this->fullpage = implode('/', $pi);
     }
     else
     {
-      $k = array_keys($_GET);
-      foreach($k as $c)
+      // Starting up Enano with the API from a page that wants to do its own thing. Generate
+      // metadata for an anonymous page and avoid redirection at all costs.
+      if ( isset($GLOBALS['title']) )
+      {
+        $title =& $GLOBALS['title'];
+      }
+      else
       {
-        if(substr($c, 0, 1) == '/')
-        {
-          $this->page = substr($c, 1, strlen($c));
-          
-          // Bugfix for apache somehow passing dots as underscores
-          global $mime_types;
-          
-          $exts = array_keys($mime_types);
-          $exts = '(' . implode('|', $exts) . ')';
-          
-          if ( preg_match( '#_'.$exts.'#i', $this->page ) )
-          {
-            $this->page = preg_replace( '#_'.$exts.'#i', '.\\1', $this->page );
-          }
-          
-          $this->fullpage = $this->page;
-          
-          if(substr($this->page, 0, strlen($this->nslist['Special']))==$this->nslist['Special'] || substr($this->page, 0, strlen($this->nslist['Template']))==$this->nslist['Template'])
-          {
-            $ex = explode('/', $this->page);
-            $this->page = $ex[0];
-          }
-          if(strstr($this->page, ' '))
-          {
-            $loc = str_replace(' ', '_', urldecode(rawurldecode($_SERVER['REQUEST_URI'])));
-            $loc = str_replace('+', '_', $loc);
-            $loc = str_replace('%20', '_', $loc);
-            redirect($loc, 'Redirecting...', 'Space in the URL detected, please wait whilst you are redirected', 0);
-            exit;
-          }
-          break;
-        }
+        $title = basename($_SERVER['SCRIPT_NAME']);
       }
-      if(!$this->page && !($this->page == '' && getConfig('main_page') == ''))
+      $base_uri = str_replace( scriptPath . '/', '', $_SERVER['SCRIPT_NAME'] );
+      $this->page = $this->nslist['Anonymous'] . sanitize_page_id($base_uri);
+      $this->fullpage = $this->nslist['Anonymous'] . sanitize_page_id($base_uri);
+      $this->namespace = 'Anonymous';
+      $this->cpage = array(
+          'name' => $title,
+          'urlname' => sanitize_page_id($base_uri),
+          'namespace' => 'Anonymous',
+          'special' => 1,
+          'visible' => 1,
+          'comments_on' => 1,
+          'protected' => 1,
+          'delvotes' => 0,
+          'delvote_ips' => ''
+        );
+      $this->anonymous_page = true;
+      $code = $plugins->setHook('paths_anonymous_page');
+      foreach ( $code as $cmd )
       {
-        $this->main_page();
+        eval($cmd);
       }
     }
     
     $this->page = sanitize_page_id($this->page);
     $this->fullpage = sanitize_page_id($this->fullpage);
     
-    dc_here('paths: setting $paths->cpage');
-    
     if(isset($this->pages[$this->page]))
     {
-      dc_here('paths: page existence verified, our page ID is: '.$this->page);
       $this->page_exists = true;
       $this->cpage = $this->pages[$this->page];
       $this->namespace = $this->cpage['namespace'];
@@ -304,7 +334,6 @@
     }
     else
     {
-      dc_here('paths: page doesn\'t exist, creating new page in memory<br />our page ID is: '.$this->page);
       $this->page_exists = false;
       $page_name = dirtify_page_id($this->page);
       $page_name = str_replace('_', ' ', $page_name);
@@ -315,18 +344,21 @@
         redirect($pid_cleaned, 'Sanitizer message', 'page id sanitized', 0);
       }
       
-      $this->cpage = Array(
-        'name'=>$page_name,
-        'urlname'=>$this->page,
-        'namespace'=>'Article',
-        'special'=>0,
-        'visible'=>0,
-        'comments_on'=>1,
-        'protected'=>0,
-        'delvotes'=>0,
-        'delvote_ips'=>'',
-        'wiki_mode'=>2,
-        );
+      if ( !is_array($this->cpage) )
+      {
+        $this->cpage = Array(
+          'name'=>$page_name,
+          'urlname'=>$this->page,
+          'namespace'=>'Article',
+          'special'=>0,
+          'visible'=>0,
+          'comments_on'=>1,
+          'protected'=>0,
+          'delvotes'=>0,
+          'delvote_ips'=>'',
+          'wiki_mode'=>2,
+          );
+      }
       // Look for a namespace prefix in the urlname, and assign a different namespace, if necessary
       $k = array_keys($this->nslist);
       for($i=0;$i<sizeof($this->nslist);$i++)
@@ -348,7 +380,7 @@
       {
         $this->cpage['protected'] = 1;
       }
-      if($this->namespace == 'Special')
+      if($this->namespace == 'Special' && !$this->anonymous_page)
       {
         // Can't load nonexistent pages
         if( is_string(getConfig('main_page')) )
@@ -384,7 +416,6 @@
   
   function add_page($flags)
   {
-    //dc_dump($flags, 'paths: page added by plugin:');
     $flags['urlname_nons'] = $flags['urlname'];
     $flags['urlname'] = $this->nslist[$flags['namespace']] . $flags['urlname']; // Applies the User:/File:/etc prefixes to the URL names
     $pages_len = sizeof($this->pages)/2;
@@ -409,7 +440,6 @@
   function sysmsg($n)
   {
     global $db, $session, $paths, $template, $plugins; // Common objects
-    dc_here('paths: system message requested: '.$n);
     $q = $db->sql_query('SELECT page_text, char_tag FROM '.table_prefix.'page_text WHERE page_id=\''.$db->escape($n).'\' AND namespace=\'System\'');
     if( !$q )
     {
--- a/includes/plugins.php	Sun Dec 02 16:00:56 2007 -0500
+++ b/includes/plugins.php	Fri Dec 07 16:42:22 2007 -0500
@@ -19,8 +19,6 @@
   var $system_plugins = Array('SpecialUserFuncs.php','SpecialUserPrefs.php','SpecialPageFuncs.php','SpecialAdmin.php','SpecialCSS.php','SpecialUpdownload.php','SpecialSearch.php','PrivateMessages.php','SpecialGroups.php');
   function loadAll() 
   {
-    dc_here('plugins: building file list');
-    
     $dir = ENANO_ROOT.'/plugins/';
     
     $this->load_list = Array();
@@ -67,7 +65,6 @@
     //die('<pre>'.htmlspecialchars(print_r($plugins, true)).'</pre>');
   }
   function setHook($name, $opts = Array()) {
-    dc_dump($name, 'plugins: hook added: ');
     /*
     $r = Array();
     if(isset($this->hook_list[$name])) {
@@ -89,7 +86,6 @@
     }
   }
   function attachHook($name, $code) {
-    dc_dump($code, 'plugins: hook attached: '.$name.'<br />code:');
     if(!isset($this->hook_list[$name]))
     {
       $this->hook_list[$name] = Array();
--- a/includes/render.php	Sun Dec 02 16:00:56 2007 -0500
+++ b/includes/render.php	Fri Dec 07 16:42:22 2007 -0500
@@ -41,7 +41,6 @@
   function getPage($page_id, $namespace, $wiki = 1, $smilies = true, $filter_links = true, $redir = true, $render = true)
   {
     global $db, $session, $paths, $template, $plugins; // Common objects
-    dc_here('render: page requested<br />ID/namespace: '."$page_id, $namespace<br />Wiki mode: $wiki<br />Smilies: ".(string)$smilies."<br />Allow redirects: ".(string)$redir);
     
     $perms =& $session;
     
@@ -81,7 +80,6 @@
     
     if ( preg_match("#^\#redirect \[\[([^\]\r\n\a\t]+?)\]\]#", $message, $m) && $redir && ( !isset($_GET['redirect']) || ( isset($_GET['redirect']) && $_GET['redirect'] != 'no' ) ) )
     {
-      dc_here('render: looks like a redirect page to me...');
       $old = $paths->cpage;
       $a = RenderMan::strToPageID($m[1]);
       $a[0] = str_replace(' ', '_', $a[0]);
@@ -91,8 +89,6 @@
       $paths->cpage = $paths->pages[$pageid];
       //die('<pre>'.print_r($paths->cpage,true).'</pre>');
       
-      dc_here('render: wreckin\' $template, and reloading the theme vars to match the new page<br />This might get messy!');
-      
       unset($template);
       unset($GLOBALS['template']);
       
@@ -108,21 +104,17 @@
     }
     else if(preg_match('#^\#redirect \[\[(.+?)\]\]#', $message, $m) && isset($_GET['redirect']) && $_GET['redirect'] == 'no')
     {
-      dc_here('render: looks like a redirect page to me...');
-      dc_here('render: skipping redirect as requested on URI');
       preg_match('#^\#redirect \[\[(.+)\]\]#', $message, $m);
       $m[1] = str_replace(' ', '_', $m[1]);
       $message = preg_replace('#\#redirect \[\[(.+)\]\]#', '<nowiki><div class="mdg-infobox"><table border="0" width="100%" cellspacing="0" cellpadding="0"><tr><td valign="top"><img alt="Cute wet-floor icon" src="'.scriptPath.'/images/redirector.png" /></td><td valign="top" style="padding-left: 10px;"><b>This page is a <i>redirector</i>.</b><br />This means that this page will not show its own content by default. Instead it will display the contents of the page it redirects to.<br /><br />To create a redirect page, make the <i>first characters</i> in the page content <tt>#redirect [[Page_ID]]</tt>. For more information, see the Enano <a href="http://enanocms.org/Help:Wiki_formatting">Wiki formatting guide</a>.<br /><br />This page redirects to <a href="'.makeUrl($m[1]).'">'.$paths->pages[$m[1]]['name'].'</a>.</td></tr></table></div><br /><hr style="margin-left: 1em; width: 200px;" /></nowiki>', $message);
     }
     $session->disallow_password_grab();
-    dc_here('render: alright, got the text, formatting...');
     return ($render) ? RenderMan::render($message, $wiki, $smilies, $filter_links) : $message;
   }
   
   function getTemplate($id, $parms)
   {
     global $db, $session, $paths, $template, $plugins; // Common objects
-    dc_here('render: template requested: '.$id);
     if(!isset($paths->pages[$paths->nslist['Template'].$id])) 
     {
       return '[['.$paths->nslist['Template'].$id.']]';
@@ -161,7 +153,6 @@
   function fetch_template_text($id)
   {
     global $db, $session, $paths, $template, $plugins; // Common objects
-    dc_here('render: template raw data requested: '.$id);
     if(!isset($paths->pages[$paths->nslist['Template'].$id])) 
     {
       return '[['.$paths->nslist['Template'].$id.']]';
--- a/includes/sessions.php	Sun Dec 02 16:00:56 2007 -0500
+++ b/includes/sessions.php	Fri Dec 07 16:42:22 2007 -0500
@@ -1849,7 +1849,6 @@
     $message .= "$prot://".$_SERVER['HTTP_HOST'].$p.$aklink;
       $message .= "\n\nSincerely yours, \n$admin_user and the ".$_SERVER['HTTP_HOST']." administration team";
     error_reporting(E_ALL);
-    dc_dump($r, 'session: about to send activation e-mail to '.$r['email']);
     if(getConfig('smtp_enabled') == '1')
     {
       $result = smtp_send_email($r['email'], getConfig('site_name').' website account activation', preg_replace("#(?<!\r)\n#s", "\n", $message), getConfig('contact_email'));
@@ -1924,7 +1923,6 @@
     
     error_reporting(E_ALL);
     
-    dc_dump($r, 'session: about to send COPPA e-mail to '.$r['email']);
     if(getConfig('smtp_enabled') == '1')
     {
       $result = smtp_send_email($r['email'], getConfig('site_name').' website account activation', preg_replace("#(?<!\r)\n#s", "\n", $message), getConfig('contact_email'));
--- a/includes/template.php	Sun Dec 02 16:00:56 2007 -0500
+++ b/includes/template.php	Fri Dec 07 16:42:22 2007 -0500
@@ -33,7 +33,6 @@
   function __construct()
   {
     global $db, $session, $paths, $template, $plugins; // Common objects
-    dc_here('template: initializing all class variables');
     $this->tpl_bool    = Array();
     $this->tpl_strings = Array();
     $this->sidebar_extra = '';
@@ -137,8 +136,6 @@
     global $email;
     global $lang;
     
-    dc_here("template: initializing all variables");
-    
     if(!$this->theme || !$this->style)
     {
       $this->load_theme();
@@ -146,7 +143,6 @@
     
     if(defined('ENANO_TEMPLATE_LOADED'))
     {
-      dc_here('template: access denied to call template::init_vars(), bailing out');
       die_semicritical('Illegal call', '<p>$template->load_theme was called multiple times, this is not supposed to happen. Exiting with fatal error.</p>');
     }
     
@@ -154,8 +150,6 @@
     
     $tplvars = $this->extract_vars('elements.tpl');
     
-    dc_here('template: setting all template vars');
-    
     if(isset($_SERVER['HTTP_USER_AGENT']) && strstr($_SERVER['HTTP_USER_AGENT'], 'MSIE'))
     {
       $this->add_header('
@@ -227,6 +221,9 @@
       case "Category":
         $ns = $lang->get('onpage_lbl_page_category');
         break;
+      case "Anonymous":
+        $ns = 'external page';
+        break;
     }
     $this->namespace_string = $ns;
     unset($ns);
@@ -245,14 +242,17 @@
     $btn_selected = ( isset($tplvars['toolbar_button_selected'])) ? $tplvars['toolbar_button_selected'] : $tplvars['toolbar_button'];
     $parser = $this->makeParserText($btn_selected);
     
-    $parser->assign_vars(array(
-        'FLAGS' => 'onclick="if ( !KILL_SWITCH ) { void(ajaxReset()); return false; }" title="' . $lang->get('onpage_tip_article') . '" accesskey="a"',
-        'PARENTFLAGS' => 'id="mdgToolbar_article"',
-        'HREF' => makeUrl($paths->page, null, true),
-        'TEXT' => $this->namespace_string
-      ));
-    
-    $tb .= $parser->run();
+    if ( true || !$paths->anonymous_page )
+    {
+      $parser->assign_vars(array(
+          'FLAGS' => 'onclick="if ( !KILL_SWITCH ) { void(ajaxReset()); return false; }" title="' . $lang->get('onpage_tip_article') . '" accesskey="a"',
+          'PARENTFLAGS' => 'id="mdgToolbar_article"',
+          'HREF' => makeUrl($paths->page, null, true),
+          'TEXT' => $this->namespace_string
+        ));
+      
+      $tb .= $parser->run();
+    }
     
     $button = $this->makeParserText($tplvars['toolbar_button']);
     
@@ -577,7 +577,7 @@
     }
     
     // Manage ACLs button
-    if($session->get_permissions('edit_acl') || $session->user_level >= USER_LEVEL_ADMIN)
+    if ( !$paths->anonymous_page && ( $session->get_permissions('edit_acl') || $session->user_level >= USER_LEVEL_ADMIN ) )
     {
       $menubtn->assign_vars(array(
           'FLAGS' => 'onclick="if ( !KILL_SWITCH ) { return ajaxOpenACLManager(); }" title="' . $lang->get('onpage_tip_aclmanager') . '" accesskey="m"',
@@ -810,7 +810,6 @@
     }
     
     $headers_sent = true;
-    dc_here('template: generating and sending the page header');
     if(!defined('ENANO_HEADERS_SENT'))
       define('ENANO_HEADERS_SENT', '');
     if ( !$this->no_headers )
@@ -842,7 +841,6 @@
   function footer($simple = false)
   {
     global $db, $session, $paths, $template, $plugins; // Common objects
-    dc_here('template: generating and sending the page footer');
     if(!$this->no_headers) {
       
       if(!defined('ENANO_HEADERS_SENT'))
@@ -873,7 +871,6 @@
   function getHeader()
   {
     $headers_sent = true;
-    dc_here('template: generating and sending the page header');
     if(!defined('ENANO_HEADERS_SENT'))
       define('ENANO_HEADERS_SENT', '');
     if(!$this->no_headers) return $this->process_template('header.tpl');
@@ -881,7 +878,6 @@
   function getFooter()
   {
     global $db, $session, $paths, $template, $plugins; // Common objects
-    dc_here('template: generating and sending the page footer');
     if(!$this->no_headers) {
       global $_starttime;
       $t = '';
--- a/index.php	Sun Dec 02 16:00:56 2007 -0500
+++ b/index.php	Fri Dec 07 16:42:22 2007 -0500
@@ -16,6 +16,8 @@
  *
  */
  
+  define('ENANO_INTERFACE_INDEX', '');
+ 
   // Set up gzip encoding before any output is sent
   
   $aggressive_optimize_html = false;
--- a/plugins/index.php	Sun Dec 02 16:00:56 2007 -0500
+++ b/plugins/index.php	Fri Dec 07 16:42:22 2007 -0500
@@ -1,21 +1,10 @@
 <?php
-/*
-Plugin Name:
-Plugin URI:
-Description: 
-Author:
-Version:
-Author URI:
-*/
 
-$_GET['title'] = 'Enano:Access_denied';
+$title = 'Access denied';
 require('../includes/common.php');
 header('HTTP/1.1 403 Forbidden');
-$session->perms['edit_page'] = AUTH_DENY;
-$session->perms['view_source'] = AUTH_DENY;
-$template->tpl_strings['PAGE_NAME'] = 'Access denied';
 
 $template->header();
-echo '<p>The administrator has flagged the page "' . $_SERVER['REQUEST_URI'] . '" so that it cannot be accessed from the web. Perhaps this is because this is a cache or includes directory and only needs to be accessed by scripts.</p><p>HTTP error: 403 Forbidden</p>';
+echo '<p>The administrator has flagged the page "' . htmlspecialchars($_SERVER['REQUEST_URI']) . '" so that it cannot be accessed from the web. Perhaps this is because this is a cache or includes directory and only needs to be accessed by scripts.</p><p>HTTP error: 403 Forbidden</p>';
 $template->footer();
-$db->close();
+
--- a/themes/index.php	Sun Dec 02 16:00:56 2007 -0500
+++ b/themes/index.php	Fri Dec 07 16:42:22 2007 -0500
@@ -1,13 +1,10 @@
 <?php
 
-$_GET['title'] = 'Enano:Access_denied';
+$title = 'Access denied';
 require('../includes/common.php');
 header('HTTP/1.1 403 Forbidden');
-$session->perms['edit_page'] = AUTH_DENY;
-$session->perms['view_source'] = AUTH_DENY;
-$template->tpl_strings['PAGE_NAME'] = 'Access denied';
 
 $template->header();
-echo '<p>The administrator has flagged the page "' . $_SERVER['REQUEST_URI'] . '" so that it cannot be accessed from the web. Perhaps this is because this is a cache or includes directory and only needs to be accessed by scripts.</p><p>HTTP error: 403 Forbidden</p>';
+echo '<p>The administrator has flagged the page "' . htmlspecialchars($_SERVER['REQUEST_URI']) . '" so that it cannot be accessed from the web. Perhaps this is because this is a cache or includes directory and only needs to be accessed by scripts.</p><p>HTTP error: 403 Forbidden</p>';
 $template->footer();
-$db->close();
+
--- a/themes/oxygen/css/bleu.css	Sun Dec 02 16:00:56 2007 -0500
+++ b/themes/oxygen/css/bleu.css	Fri Dec 07 16:42:22 2007 -0500
@@ -26,7 +26,7 @@
 div.rectbot                        { width: 140px; height: 12px; margin: 0; padding: 0; }  
 td.rectbottop                      { width: 100%;  height: 12px; background-image: url(../images/bleu/border-btm.gif); background-repeat: repeat-x;  margin: 0; padding: 0; }
 div.slideblock, .dbx-content       { overflow: hidden; background-color: #DDD; }
-div.slideblock2                    { overflow: hidden; background-color: #DDD; margin: 0px 1px 0px 1px; }
+div.slideblock2                    { overflow: hidden; background-color: #DDD; margin: 0px 1px 0px 1px; border-bottom: 1px solid #FFF; }
 .dbx-handle                        { cursor: move !important; }
 
 /* The credits thingy at the bottom */
--- a/themes/oxygen/css/mint.css	Sun Dec 02 16:00:56 2007 -0500
+++ b/themes/oxygen/css/mint.css	Fri Dec 07 16:42:22 2007 -0500
@@ -26,7 +26,7 @@
 div.rectbot                        { width: 140px; height: 12px; margin: 0; padding: 0; }  
 td.rectbottop                      { width: 100%;  height: 12px; background-image: url(../images/mint/border-btm.gif); background-repeat: repeat-x;  margin: 0; padding: 0; }
 div.slideblock, .dbx-content       { overflow: hidden; background-color: #DDD; }
-div.slideblock2                    { overflow: hidden; background-color: #DDD; margin: 0px 1px 0px 1px; }
+div.slideblock2                    { overflow: hidden; background-color: #DDD; margin: 0px 1px 0px 1px; border-bottom: 1px solid #FFF; }
 .dbx-handle                        { cursor: move !important; }
 
 /* The credits thingy at the bottom */