Merging fixes and updates from stable branch
authorDan
Fri, 22 Feb 2008 12:51:53 -0500
changeset 458 c433348f3628
parent 439 d9dd2b2134c4 (diff)
parent 457 d823e49e2e4e (current diff)
child 459 31c23016ab62
Merging fixes and updates from stable branch
includes/clientside/static/misc.js
includes/comment.php
includes/common.php
includes/functions.php
includes/pageprocess.php
includes/pageutils.php
includes/paths.php
includes/render.php
includes/rijndael.php
includes/sessions.php
includes/template.php
includes/wikiengine/Tables.php
licenses/cc-by-2.0.html
plugins/SpecialAdmin.php
plugins/SpecialGroups.php
plugins/SpecialUpdownload.php
plugins/SpecialUserFuncs.php
--- a/.hgtags	Fri Feb 22 12:46:51 2008 -0500
+++ b/.hgtags	Fri Feb 22 12:51:53 2008 -0500
@@ -11,3 +11,6 @@
 95dc632bf0846b5a7d7d841a4fe9518964a1cc9a release
 f8356d9c3481b7ebb88dbf70637d8f5d2cca4528 rebrand
 d409d7fcf6f8bc638e0282101fb823ccf3e29e59 release
+3395ecddd831ee2f0229ab3b4a1c9d69f0ab73d7 release
+d1a95497b68f765f6ca4ed816d07b20b13cee692 rebrand
+ceff43bbc3d3bc18d7679f88ef6fec2e070bc704 release
--- a/README	Fri Feb 22 12:46:51 2008 -0500
+++ b/README	Fri Feb 22 12:51:53 2008 -0500
@@ -1,5 +1,5 @@
 Enano CMS
-Version 1.0.3
+Version 1.1.2
 -----------------------------
 
 Thanks for downloading Enano! If you're looking for an installation guide,
@@ -9,7 +9,7 @@
 -----------------------------
 
 Enano CMS
-Copyright (C) 2006-2007 Dan Fuhry. All rights except those explicitly granted
+Copyright (C) 2006-2008 Dan Fuhry. All rights except those explicitly granted
 by the included license agreement reserved.
 
 PHILOSOPHY
@@ -74,16 +74,30 @@
 CHANGES IN THIS RELEASE
 -----------------------------
 
-Please see <http://enanocms.org/Release_notes/1.0.3> for a list of changes in
+Please see <http://enanocms.org/Release_notes/1.1.2> for a list of changes in
 this release.
 
 UPGRADING FROM PREVIOUS RELEASES
 -----------------------------
 
-This tarball includes an upgrade script that can migrate any previous version
-of Enano to this one. Before you upload the contents of this tarball to your
-server, you might want to delete the files config.new.php and .htaccess.new,
-neither of which are needed if you are performing an upgrade.
+This tarball includes a very basic migration script that you can use to change
+a 1.0.x installation into a 1.1.x one. Make sure you're using the latest 1.0.x
+release (1.0.3 at the time of this writing) BEFORE you run the migration
+script. DO NOT UPGRADE A PRODUCTION SITE.
+
+As of 1.1.2, basic upgrade functionality is included and is considered highly
+experimental. Back up your entire database and Enano root before upgrading.
+
+TRANSLATING ENANO
+-----------------------------
+
+This is the only the second formal release of Enano that is localized. Right
+now since this is an alpha, you probably don't want to do any translation
+because you'll be doing a TON more strings at every release. HOWEVER, we're
+looking for people to sign up and volunteer for translation efforts later on.
+If you have a native or very good knowledge of a language, drop us an e-mail
+and we'll get you onto the translator list and eventually onto a mailing list
+specifically for l10n.
 
 EXPANDING YOUR SITE'S CAPABILITIES
 -----------------------------
@@ -91,7 +105,10 @@
 There is a gallery of plugins for Enano at
 <http://enanocms.org/Category:Plugins>. It's not very full right now because
 not every plugin has a page on the website yet, and some plugins still have
-yet to be ported to work with some of the newer API changes.
+yet to be ported to work with some of the newer API changes. Being an alpha
+release you'll probably need to look in the Mercurial repositories at
+<http://hg.enanocms.org/> for the latest versions of plugins that are designed
+to work under both 1.0.x and 1.1.x.
 
 GIVING YOUR SITE A NEW LOOK
 -----------------------------
@@ -100,20 +117,19 @@
 Again, we're still working on packaging up themes and creating pages for them,
 so try to be patient. We have quite a few themes in the works. You can create
 your own themes too; for more information, see Chapter V of the Enano
-Administrator's handbook, at <http://docs.enanocms.org/Help:5>.
+Administrator's handbook, at <http://docs.enanocms.org/Help:5>. Unless
+specifically marked, themes on the Enano website are compatible with 1.0.x.
+While you can use 1.0.x themes under 1.1.x, some features (namely viewing IPs
+on comments and the default "Inherit" option in the ACL editor) will be missing
+unless you copy over comment.tpl and acledit.tpl respectively from Oxygen or
+one of the other themes included with this 1.1.x package.
 
 GETTING SUPPORT
 -----------------------------
 
-Before contacting support, have a look at the Enano Documentation at
-<http://docs.enanocms.org/>. Most of Enano's features are documented with
-step-by-step guides at this site; if you encounter a problem, then please
-contact the Enano team as instructed below.
-
-Support for Enano is available via the Enano forums at
-<http://forum.enanocms.org>. You can also use our IRC channel
-(irc.freenode.net #enano) or purchase paid one-on-one support via instant
-messaging for US$20 an hour.
+This is an alpha release. No support of any kind will be provided, but proper
+bug reports are appreciated. See the Enano forums at
+<http://forum.enanocms.org/> for more information.
 
 Have fun with Enano!
 
--- a/ajax.php	Fri Feb 22 12:46:51 2008 -0500
+++ b/ajax.php	Fri Feb 22 12:51:53 2008 -0500
@@ -2,7 +2,7 @@
 
 /*
  * Enano - an open-source CMS capable of wiki functions, Drupal-like sidebar blocks, and everything in between
- * Version 1.0.3 (Dyrad)
+ * Version 1.1.1
  * Copyright (C) 2006-2007 Dan Fuhry
  *
  * This program is Free Software; you can redistribute and/or modify it under the terms of the GNU General Public License
@@ -35,7 +35,7 @@
     define('ENANO_ROOT', dirname($filename));
     require(ENANO_ROOT.'/includes/functions.php');
     require(ENANO_ROOT.'/includes/dbal.php');
-    require(ENANO_ROOT.'/includes/json.php');
+    require(ENANO_ROOT.'/includes/json2.php');
     
     require(ENANO_ROOT . '/config.php');
     unset($dbuser, $dbpasswd);
@@ -47,7 +47,6 @@
     $db->connect();
     
     // result is sent using JSON
-    $json = new Services_JSON(SERVICES_JSON_LOOSE_TYPE);
     $return = Array(
         'mode' => 'success',
         'users_real' => Array()
@@ -61,7 +60,7 @@
         'mode' => 'error',
         'error' => 'Invalid URI'
       );
-      die( $json->encode($return) );
+      die( enano_json_encode($return) );
     }
     $allowanon = ( isset($_GET['allowanon']) && $_GET['allowanon'] == '1' ) ? '' : ' AND user_id > 1';
     $q = $db->sql_query('SELECT username FROM '.table_prefix.'users WHERE ' . ENANO_SQLFUNC_LOWERCASE . '(username) LIKE ' . ENANO_SQLFUNC_LOWERCASE . '(\'%'.$name.'%\')' . $allowanon . ' ORDER BY username ASC;');
@@ -80,7 +79,7 @@
     // all done! :-)
     $db->close();
     
-    echo $json->encode( $return );
+    echo enano_json_encode( $return );
     
     exit;
   }
@@ -97,21 +96,116 @@
       echo PageUtils::checkusername($_GET['name']);
       break;
     case "getsource":
+      header('Content-type: text/plain');
       $password = ( isset($_GET['pagepass']) ) ? $_GET['pagepass'] : false;
-      $page = new PageProcessor($paths->page_id, $paths->namespace);
+      $revid = ( isset($_GET['revid']) ) ? intval($_GET['revid']) : 0;
+      $page = new PageProcessor($paths->page_id, $paths->namespace, $revid);
       $page->password = $password;
+      $have_draft = false;
       if ( $src = $page->fetch_source() )
       {
-        echo $src;
+        $allowed = true;
+        $q = $db->sql_query('SELECT author, time_id, page_text, edit_summary FROM ' . table_prefix . 'logs WHERE log_type = \'page\' AND action = \'edit\'
+                               AND page_id = \'' . $db->escape($paths->page_id) . '\'
+                               AND namespace = \'' . $db->escape($paths->namespace) . '\'
+                               AND is_draft = 1;');
+        if ( !$q )
+          $db->die_json();
+        
+        if ( $db->numrows() > 0 )
+        {
+          $have_draft = true;
+          $draft_row = $db->fetchrow($q);
+        }
       }
       else if ( $src !== false )
       {
-        echo '';
+        $allowed = true;
+        $src = '';
       }
       else
       {
-        echo 'err_access_denied';
+        $allowed = false;
+        $src = '';
+      }
+      
+      $auth_edit = ( $session->get_permissions('edit_page') && ( $session->get_permissions('even_when_protected') || !$paths->page_protected ) );
+      $auth_wysiwyg = ( $session->get_permissions('edit_wysiwyg') );
+      
+      $return = array(
+          'mode' => 'editor',
+          'src' => $src,
+          'auth_view_source' => $allowed,
+          'auth_edit' => $auth_edit,
+          'time' => time(),
+          'require_captcha' => false,
+          'allow_wysiwyg' => $auth_wysiwyg,
+          'revid' => $revid,
+          'have_draft' => false
+        );
+      
+      if ( $have_draft )
+      {
+        $row =& $draft_row;
+        $return['have_draft'] = true;
+        $return['draft_author'] = $row['author'];
+        $return['draft_time'] = enano_date('d M Y h:i a', intval($row['time_id']));
+        if ( isset($_GET['get_draft']) && @$_GET['get_draft'] === '1' )
+        {
+          $return['src'] = $row['page_text'];
+          $return['edit_summary'] = $row['edit_summary'];
+        }
       }
+      
+      if ( $revid > 0 )
+      {
+        // Retrieve information about this revision and the current one
+        $q = $db->sql_query('SELECT l1.author AS currentrev_author, l2.author AS oldrev_author FROM ' . table_prefix . 'logs AS l1
+  LEFT JOIN ' . table_prefix . 'logs AS l2
+    ON ( l2.time_id = ' . $revid . '
+         AND l2.log_type  = \'page\'
+         AND l2.action    = \'edit\'
+         AND l2.page_id   = \'' . $db->escape($paths->page_id)   . '\'
+         AND l2.namespace = \'' . $db->escape($paths->namespace) . '\'
+        )
+  WHERE l1.log_type  = \'page\'
+    AND l1.action    = \'edit\'
+    AND l1.page_id   = \'' . $db->escape($paths->page_id)   . '\'
+    AND l1.namespace = \'' . $db->escape($paths->namespace) . '\'
+    AND l1.time_id >= ' . $revid . '
+  ORDER BY l1.time_id DESC;');
+        if ( !$q )
+          $db->die_json();
+        
+        $rev_count = $db->numrows() - 1;
+        if ( $rev_count == -1 )
+        {
+          $return = array(
+              'mode' => 'error',
+              'error' => '[Internal] No rows returned by revision info query. SQL:<pre>' . $db->latest_query . '</pre>'
+            );
+        }
+        else
+        {
+          $row = $db->fetchrow();
+          $return['undo_info'] = array(
+            'old_author'     => $row['oldrev_author'],
+            'current_author' => $row['currentrev_author'],
+            'undo_count'     => $rev_count
+          );
+        }
+      }
+      
+      if ( $auth_edit && !$session->user_logged_in && getConfig('guest_edit_require_captcha') == '1' )
+      {
+        $return['require_captcha'] = true;
+        $return['captcha_id'] = $session->make_captcha();
+      }
+      
+      $template->load_theme();
+      $return['toolbar_templates'] = $template->extract_vars('toolbar.tpl');
+      
+      echo enano_json_encode($return);
       break;
     case "getpage":
       // echo PageUtils::getpage($paths->page, false, ( (isset($_GET['oldid'])) ? $_GET['oldid'] : false ));
@@ -127,7 +221,7 @@
       $summ = ( isset($_POST['summary']) ) ? $_POST['summary'] : '';
       $minor = isset($_POST['minor']);
       $e = PageUtils::savepage($paths->page_id, $paths->namespace, $_POST['text'], $summ, $minor);
-      if($e=='good')
+      if ( $e == 'good' )
       {
         $page = new PageProcessor($paths->page_id, $paths->namespace);
         $page->send();
@@ -137,6 +231,159 @@
         echo '<p>Error saving the page: '.$e.'</p>';
       }
       break;
+    case "savepage_json":
+      header('Content-type: application/json');
+      if ( !isset($_POST['r']) )
+        die('Invalid request [1]');
+      
+      $request = enano_json_decode($_POST['r']);
+      if ( !isset($request['src']) || !isset($request['summary']) || !isset($request['minor_edit']) || !isset($request['time']) || !isset($request['draft']) )
+        die('Invalid request [2]<pre>' . htmlspecialchars(print_r($request, true)) . '</pre>');
+      
+      $time = intval($request['time']);
+      
+      if ( $request['draft'] )
+      {
+        //
+        // The user wants to save a draft version of the page.
+        //
+        
+        // Delete any draft copies if they exist
+        $q = $db->sql_query('DELETE FROM ' . table_prefix . 'logs WHERE log_type = \'page\' AND action = \'edit\'
+                               AND page_id = \'' . $db->escape($paths->page_id) . '\'
+                               AND namespace = \'' . $db->escape($paths->namespace) . '\'
+                               AND is_draft = 1;');
+        if ( !$q )
+          $db->die_json();
+        
+        $src = RenderMan::preprocess_text($request['src'], false, false);
+        
+        // Save the draft
+        $q = $db->sql_query('INSERT INTO ' . table_prefix . 'logs ( log_type, action, page_id, namespace, author, edit_summary, page_text, is_draft, time_id )
+                               VALUES (
+                                 \'page\',
+                                 \'edit\',
+                                 \'' . $db->escape($paths->page_id) . '\',
+                                 \'' . $db->escape($paths->namespace) . '\',
+                                 \'' . $db->escape($session->username) . '\',
+                                 \'' . $db->escape($request['summary']) . '\',
+                                 \'' . $db->escape($src) . '\',
+                                 1,
+                                 ' . time() . '
+                               );');
+        
+        // Done!
+        $return = array(
+            'mode' => 'success',
+            'is_draft' => true
+          );
+      }
+      else
+      {
+        // Verify that no edits have been made since the editor was requested
+        $q = $db->sql_query('SELECT time_id, author FROM ' . table_prefix . "logs WHERE log_type = 'page' AND action = 'edit' AND page_id = '{$paths->page_id}' AND namespace = '{$paths->namespace}' AND is_draft != 1 ORDER BY time_id DESC LIMIT 1;");
+        if ( !$q )
+          $db->die_json();
+        
+        $row = $db->fetchrow();
+        $db->free_result();
+        
+        if ( $row['time_id'] > $time )
+        {
+          $return = array(
+            'mode' => 'obsolete',
+            'author' => $row['author'],
+            'date_string' => enano_date('d M Y h:i a', $row['time_id']),
+            'time' => $row['time_id'] // time() ???
+            );
+          echo enano_json_encode($return);
+          break;
+        }
+        
+        // Verify captcha, if needed
+        if ( !$session->user_logged_in && getConfig('guest_edit_require_captcha') == '1' )
+        {
+          if ( !isset($request['captcha_id']) || !isset($request['captcha_code']) )
+          {
+            die('Invalid request, need captcha metadata');
+          }
+          $code_correct = strtolower($session->get_captcha($request['captcha_id']));
+          $code_input = strtolower($request['captcha_code']);
+          if ( $code_correct !== $code_input )
+          {
+            $return = array(
+              'mode' => 'errors',
+              'errors' => array($lang->get('editor_err_captcha_wrong')),
+              'new_captcha' => $session->make_captcha()
+            );
+            echo enano_json_encode($return);
+            break;
+          }
+        }
+        
+        // Verification complete. Start the PageProcessor and let it do the dirty work for us.
+        $page = new PageProcessor($paths->page_id, $paths->namespace);
+        if ( $page->update_page($request['src'], $request['summary'], ( $request['minor_edit'] == 1 )) )
+        {
+          $return = array(
+              'mode' => 'success',
+              'is_draft' => false
+            );
+        }
+        else
+        {
+          $errors = array();
+          while ( $err = $page->pop_error() )
+          {
+            $errors[] = $err;
+          }
+          $return = array(
+            'mode' => 'errors',
+            'errors' => array_values($errors)
+            );
+          if ( !$session->user_logged_in && getConfig('guest_edit_require_captcha') == '1' )
+          {
+            $return['new_captcha'] = $session->make_captcha();
+          }
+        }
+        
+        // If this is based on a draft version, delete the draft - we no longer need it.
+        if ( @$request['used_draft'] )
+        {
+          $q = $db->sql_query('DELETE FROM ' . table_prefix . 'logs WHERE log_type = \'page\' AND action = \'edit\'
+                                 AND page_id = \'' . $db->escape($paths->page_id) . '\'
+                                 AND namespace = \'' . $db->escape($paths->namespace) . '\'
+                                 AND is_draft = 1;');
+        }
+      }
+      
+      echo enano_json_encode($return);
+      
+      break;
+    case "diff_cur":
+      
+      // Lie about our content type to fool ad scripts
+      header('Content-type: application/xhtml+xml');
+      
+      if ( !isset($_POST['text']) )
+        die('Invalid request');
+      
+      $page = new PageProcessor($paths->page_id, $paths->namespace);
+      if ( !($src = $page->fetch_source()) )
+      {
+        die('Access denied');
+      }
+      
+      $diff = RenderMan::diff($src, $_POST['text']);
+      if ( $diff == '<table class="diff"></table>' )
+      {
+        $diff = '<p>' . $lang->get('editor_msg_diff_empty') . '</p>';
+      }
+      
+      echo '<div class="info-box">' . $lang->get('editor_msg_diff') . '</div>';
+      echo $diff;
+      
+      break;
     case "protect":
       echo PageUtils::protect($paths->page_id, $paths->namespace, (int)$_POST['level'], $_POST['reason']);
       break;
@@ -166,7 +413,7 @@
     case "deletepage":
       $reason = ( isset($_POST['reason']) ) ? $_POST['reason'] : false;
       if ( empty($reason) )
-        die('Please enter a reason for deleting this page.');
+        die($lang->get('page_err_need_reason'));
       echo PageUtils::deletepage($paths->page_id, $paths->namespace, $reason);
       break;
     case "delvote":
@@ -285,7 +532,6 @@
       die('GOOD');
       break;
     case 'get_tags':
-      $json = new Services_JSON(SERVICES_JSON_LOOSE_TYPE);
       
       $ret = array('tags' => array(), 'user_level' => $session->user_level, 'can_add' => $session->get_permissions('tag_create'));
       $q = $db->sql_query('SELECT t.tag_id, t.tag_name, pg.pg_target IS NOT NULL AS used_in_acl, t.user_id FROM '.table_prefix.'tags AS t
@@ -321,11 +567,10 @@
         );
       }
       
-      echo $json->encode($ret);
+      echo enano_json_encode($ret);
       
       break;
     case 'addtag':
-      $json = new Services_JSON(SERVICES_JSON_LOOSE_TYPE);
       $resp = array(
           'success' => false,
           'error' => 'No error',
@@ -337,7 +582,7 @@
       if ( !$session->get_permissions('tag_create') )
       {
         $resp['error'] = 'You are not permitted to tag pages.';
-        die($json->encode($resp));
+        die(enano_json_encode($resp));
       }
       
       // sanitize the tag name
@@ -347,7 +592,7 @@
       if ( strlen($tag) < 2 )
       {
         $resp['error'] = 'Tags must consist of at least 2 alphanumeric characters.';
-        die($json->encode($resp));
+        die(enano_json_encode($resp));
       }
       
       // check if tag is already on page
@@ -357,7 +602,7 @@
       if ( $db->numrows() > 0 )
       {
         $resp['error'] = 'This page already has this tag.';
-        die($json->encode($resp));
+        die(enano_json_encode($resp));
       }
       $db->free_result();
       
@@ -369,7 +614,7 @@
       if ( $db->numrows() > 0 && !$can_edit_acl )
       {
         $resp['error'] = 'This tag is used in an ACL page group, and thus can\'t be added to a page by people without administrator privileges.';
-        die($json->encode($resp));
+        die(enano_json_encode($resp));
       }
       $resp['in_acl'] = ( $db->numrows() > 0 );
       $db->free_result();
@@ -383,7 +628,7 @@
       $resp['tag'] = $tag;
       $resp['tag_id'] = $db->insert_id();
       
-      echo $json->encode($resp);
+      echo enano_json_encode($resp);
       break;
     case 'deltag':
       
--- a/cron.php	Fri Feb 22 12:46:51 2008 -0500
+++ b/cron.php	Fri Feb 22 12:51:53 2008 -0500
@@ -2,7 +2,7 @@
 
 /*
  * Enano - an open-source CMS capable of wiki functions, Drupal-like sidebar blocks, and everything in between
- * Version 1.0.3 (Dyrad)
+ * Version 1.1.2 (Caoineag alpha 2)
  * Copyright (C) 2006-2007 Dan Fuhry
  *
  * This program is Free Software; you can redistribute and/or modify it under the terms of the GNU General Public License
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/files/avatars/.htaccess	Fri Feb 22 12:51:53 2008 -0500
@@ -0,0 +1,1 @@
+Allow from all
Binary file images/about-powered-pgsql.png has changed
Binary file images/check.png has changed
Binary file images/checkbad.png has changed
Binary file images/checkunk.png has changed
Binary file images/editor/diff.gif has changed
Binary file images/editor/discard.gif has changed
Binary file images/editor/preview.gif has changed
Binary file images/editor/revert.gif has changed
Binary file images/editor/save.gif has changed
Binary file images/editor/savedraft.gif has changed
--- a/images/enano-artwork/README	Fri Feb 22 12:46:51 2008 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,8 +0,0 @@
-The images in this directory are copyright (C) 2007 Dan Fuhry. Except
-as permitted by applicable law, they may not be used in any way other
-than to promote the unmodified Enano CMS. You also may not modify and
-then distribute the images in this directory, or distribute them sep-
-arately from the Enano packages. The goal here is to establish a uni-
-que identity for  Enano through the use of  a logo, and that identity
-would be confused if this  logo is used for unofficial Enano distros.
-
Binary file images/enano-artwork/installer-greeting-blue.png has changed
Binary file images/enano-artwork/installer-greeting-green.png has changed
Binary file images/pm_ajax.gif has changed
Binary file images/pm_star_off.png has changed
Binary file images/pm_star_on.png has changed
--- a/includes/captcha.php	Fri Feb 22 12:46:51 2008 -0500
+++ b/includes/captcha.php	Fri Feb 22 12:51:53 2008 -0500
@@ -2,7 +2,7 @@
 
 /*
  * Enano - an open-source CMS capable of wiki functions, Drupal-like sidebar blocks, and everything in between
- * Version 1.0.3 (Dyrad)
+ * Version 1.1.2 (Caoineag alpha 2)
  * Copyright (C) 2006-2007 Dan Fuhry
  * captcha.php - visual confirmation system used during registration
  *
@@ -11,738 +11,178 @@
  *
  * 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.
- *
- * This file contains code written by Paul Sohier (www.paulscripts.nl). The CAPTCHA code was ported from the phpBB Better
- * Captcha mod, and has been released under the GPLv2 by the original author.
- *
- * This file contains code written by the phpBB team (www.phpbb.com). phpBB is licensed under the GPLv2.
+ */
+
+/**
+ * The base class for CAPTCHA engines.
+ * @package Enano
+ * @subpackage User management
+ * @copyright 2008 Dan Fuhry
  */
  
-class captcha
+class captcha_base
 {
-  var $chars, $confirm_id, $compat, $code, $captcha_config;
-  function __construct($code)
+  
+  /**
+   * Our session ID
+   * @var string
+   */
+  
+  private $session_id;
+  
+  /**
+   * Our saved session data
+   * @var array
+   */
+  
+  private $session_data;
+  
+  /**
+   * The confirmation code we're generating.
+   * @var string
+   */
+  
+  private $code = '';
+  
+  /**
+   * Numerical ID (primary key) for our session
+   * @var int
+   */
+  
+  private $id = 0;
+  
+  /**
+   * Constructor.
+   * @param string Session ID for captcha
+   */
+  
+  function __construct($session_id, $row = false)
   {
     global $db, $session, $paths, $template, $plugins; // Common objects
-    
-    // Check if GD exists, otherwise we will use the fallback phpBB confirm image
-    $this->compat = false;
-    if(!extension_loaded("gd")){
-      $this->compat = true;
+    if ( !preg_match('/^[a-f0-9]{32}([a-z0-9]{8})?$/', $session_id) )
+    {
+      throw new Exception('Invalid session ID');
     }
-    if(!function_exists("gd_info") || !function_exists('imagettftext')){
-      $this->compat = true;
+    $this->session_id = $session_id;
+    // If we weren't supplied with session info, retreive it
+    if ( !is_array($row) )
+    {
+      $q = $db->sql_query('SELECT code_id, code, session_data FROM ' . table_prefix . "captcha WHERE session_id = '$session_id';");
+      if ( !$q )
+        $db->_die();
+      $row = $db->fetchrow();
+      $row['code_id'] = intval($row['code_id']);
+      $db->free_result();
     }
-    $this->code = $code;
-    
-    $hex = Array('0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F');
-    $latticecolor = '#';
-    for($i=0;$i<6;$i++) $latticecolor .= $hex[mt_rand(0, 15)];
+    if ( !isset($row['code']) || !isset($row['session_data']) || !is_int(@$row['code_id']) )
+    {
+      throw new Exception('Row doesn\'t contain what we need (code and session_data)');
+    }
+    $this->session_data = ( is_array($x = @unserialize($row['session_data'])) ) ? $x : array();
+    $this->code = $row['code'];
+    $this->id = $row['code_id'];
     
-    $this->captcha_config = array (
-      'width' => '350',
-      'height' => '90',
-      'background_color' => '#E5ECF9',
-      'jpeg' => '0',
-      'jpeg_quality' => '95',
-      'pre_letters' => '1',
-      'pre_letters_great' => '0',
-      'font' => '1',
-      'chess' => '2',
-      'ellipses' => '2',
-      'arcs' => '2',
-      'lines' => '2',
-      'image' => '0',
-      'gammacorrect' => '0.8',
-      'foreground_lattice_x' => (string)mt_rand(25, 30),
-      'foreground_lattice_y' => (string)mt_rand(25, 30),
-      'lattice_color' => $latticecolor,
-    );
+    // run any custom init functions
+    if ( function_exists(array($this, 'construct_hook')) )
+      $this->construct_hook();
   }
-  function captcha($code)
-  {
-    $this->__construct($code);    
-  }
-  function dss_rand()
+  
+  /**
+   * Retrieves a key from the session data set
+   * @param int|string Key to fetch
+   * @param mixed Default value for key
+   * @return mixed
+   */
+   
+  function session_fetch($key, $default = false)
   {
-    global $db;
-    
-    $val = microtime() .  mt_rand();
-    $val = md5($val . 'a');
-    return substr($val, 4, 16);
+    return ( isset($this->session_data[$key]) ) ? $this->session_data[$key] : $default;
   }
   
-  function make_image()
+  /**
+   * Stores a value in the session's data set. Change must be committed using $captcha->session_commit()
+   * @param int|string Name of key
+   * @param mixed Value - can be an array, string, int, or double, but probably not objects :-)
+   */
+  
+  function session_store($key, $value)
   {
-    $code=$this->code;
-    if($this->compat)
-    {
-      // We can we will generate a single filtered png 
-      // Thanks to DavidMJ for emulating zlib within the code :)
-      $_png = $this->define_filtered_pngs();
-      
-      $total_width = 320;
-      $total_height = 50;
-      $img_height = 40;
-      $img_width = 0;
-      $l = 0;
-      
-      list($usec, $sec) = explode(' ', microtime()); 
-      mt_srand($sec * $usec); 
-      
-      $char_widths = array();
-      for ($i = 0; $i < strlen($code); $i++)
-      {
-        $char = $code{$i};
-      
-        $width = mt_rand(0, 4);
-        $char_widths[] = $width;
-        $img_width += $_png[$char]['width'] - $width;
-      }
-      
-      $offset_x = mt_rand(0, $total_width - $img_width);
-      $offset_y = mt_rand(0, $total_height - $img_height);
-      
-      $image = '';
-      $hold_chars = array();
-      for ($i = 0; $i < $total_height; $i++)
-      {
-        $image .= chr(0);
-      
-        if ($i > $offset_y && $i < $offset_y + $img_height)
-        {
-          $j = 0;
-      
-          for ($k = 0; $k < $offset_x; $k++)
-          {
-            $image .= chr(mt_rand(140, 255));
-          }
-      
-          for ($k = 0; $k < strlen($code); $k++)
-          {
-            $char = $code{$k};
-      
-            if (empty($hold_chars[$char]))
-            {
-              $hold_chars[$char] = explode("\n", chunk_split(base64_decode($_png[$char]['data']), $_png[$char]['width'] + 1, "\n"));
-            }
-            $image .= $this->randomise(substr($hold_chars[$char][$l], 1), $char_widths[$j]);
-            $j++;
-          }
-      
-          for ($k = $offset_x + $img_width; $k < $total_width; $k++)
-          {
-            $image .= chr(mt_rand(140, 255));
-          }
-      
-          $l++;
-        }
-        else
-        {
-          for ($k = 0; $k < $total_width; $k++)
-          {
-            $image .= chr(mt_rand(140, 255));
-          }
-        }
-      
-      }
-      unset($hold);
-      
-      $image = $this->create_png($image, $total_width, $total_height);
+    $this->session_data[$key] = $value;
+  }
+  
+  /**
+   * Commits changes to the session data set to the database.
+   */
+  
+  function session_commit()
+  {
+    global $db, $session, $paths, $template, $plugins; // Common objects
+    $session_data = serialize($this->session_data);
+    $session_data = $db->escape($session_data);
+    $code = $db->escape($this->code);
+    
+    $q = $db->sql_query('UPDATE ' . table_prefix . "captcha SET code = '$code', session_data = '$session_data' WHERE code_id = {$this->id};");
+    if ( !$q )
+      $db->_die();
+  }
+  
+  /**
+   * Changes the confirmation code
+   * @param string New string
+   */
   
-      // Output image
-      header('Content-Type: image/png');
-      header('Cache-control: no-cache, no-store');
-      echo $image;
-      
-      unset($image);
-      unset($_png);
-    } elseif(defined('ENANO_CAPTCHA_BIGNFAT')) {
-      // Prefs
-      $total_width = $this->captcha_config['width'];
-      $total_height = $this->captcha_config['height'];
-      
-      $hex_bg_color = $this->get_rgb($this->captcha_config['background_color']);
-      $bg_color = array();
-      $bg_color = explode(",", $hex_bg_color);
-      
-      $jpeg = $this->captcha_config['jpeg'];
-      $img_quality = $this->captcha_config['jpeg_quality'];
-      // Max quality is 95
-      
-      $pre_letters = $this->captcha_config['pre_letters'];
-      $pre_letter_great = $this->captcha_config['pre_letters_great'];
-      $rnd_font = $this->captcha_config['font'];
-      $chess = $this->captcha_config['chess'];
-      $ellipses = $this->captcha_config['ellipses'];
-      $arcs = $this->captcha_config['arcs'];
-      $lines = $this->captcha_config['lines'];
-      $image = $this->captcha_config['image'];
-      
-      $gammacorrect = $this->captcha_config['gammacorrect'];
-      
-      $foreground_lattice_y = $this->captcha_config['foreground_lattice_y'];
-      $foreground_lattice_x = $this->captcha_config['foreground_lattice_x'];
-      $hex_lattice_color = $this->get_rgb($this->captcha_config['lattice_color']);
-      $rgb_lattice_color = array();
-      $rgb_lattice_color = explode(",", $hex_lattice_color);
-      
-      $font_debug = false;
-      
-      // Fonts and images init
-      if ($image)
-      {
-        $bg_imgs = array();
-        if ($img_dir = opendir(ENANO_ROOT.'/includes/captcha/pics/'))
-        {
-          while (true == ($file = @readdir($img_dir))) 
-          { 
-            if ((substr(strtolower($file), -3) == 'jpg') || (substr(strtolower($file), -3) == 'gif'))    
-            {         
-              $bg_imgs[] = $file; 
-            }     
-          }
-          closedir($img_dir);
-        }
-        // Grab a random Background Image or set FALSE if none was found
-        $bg_img = ( count($bg_imgs) ) ? rand(0, (count($bg_imgs)-1)) : false;
-      }
-      
-      $fonts = array();
-      if ($fonts_dir = opendir(ENANO_ROOT.'/includes/captcha/fonts/'))
-      {
-        while (true == ($file = @readdir($fonts_dir))) 
-        { 
-          if ((substr(strtolower($file), strlen($file)-3, strlen($file)) == 'ttf'))
-          {         
-            $fonts[] = $file; 
-          }     
-        }
-        closedir($fonts_dir);
-      } else {
-        die('Error reading directory: '.ENANO_ROOT.'/includes/captcha/fonts/');
-      }
-      $font = rand(0, (count($fonts)-1));
-      
-      // Generate
-      $image = ($this->gdVersion() >= 2) ? imagecreatetruecolor($total_width, $total_height) : imagecreate($total_width, $total_height);
-      $background_color = imagecolorallocate($image, $bg_color[0], $bg_color[1], $bg_color[2]);
-      imagefill($image, 0, 0, $background_color);
-      
-      // Generate backgrund
-      if ($chess == '1' || $chess == '2' && rand(0,1))
-      {
-        // Draw rectangles
-        for($i = 0; $i <= 8; $i++)
-        {
-          $rectanglecolor = imagecolorallocate($image, rand(100,200),rand(100,200),rand(100,200));
-          imagefilledrectangle($image, 0, 0, round($total_width-($total_width/8*$i)), round($total_height), $rectanglecolor);
-          $rectanglecolor = imagecolorallocate($image, rand(100,200),rand(100,200),rand(100,200));
-          imagefilledrectangle($image, 0, 0, round($total_width-($total_width/8*$i)), round($total_height/2), $rectanglecolor);
-        }
-      }
-      if ($ellipses == '1' || $ellipses == '2' && rand(0,1))
-      {
-        // Draw random ellipses
-        for ($i = 1; $i <= 60; $i++)
-        {
-          $ellipsecolor = imagecolorallocate($image, rand(100,250),rand(100,250),rand(100,250));
-          imagefilledellipse($image, round(rand(0, $total_width)), round(rand(0, $total_height)), round(rand(0, $total_width/8)), round(rand(0, $total_height/4)), $ellipsecolor);	
-        }
-      }
-      if ($arcs == '1' || $arcs == '2' && rand(0,1))
-      {
-        // Draw random partial ellipses
-        for ($i = 0; $i <= 30; $i++)
-        {
-          $linecolor = imagecolorallocate($image, rand(120,255),rand(120,255),rand(120,255));
-          $cx = round(rand(1, $total_width));
-          $cy = round(rand(1, $total_height));
-          $int_w = round(rand(1, $total_width/2));
-          $int_h = round(rand(1, $total_height));
-          imagearc($image, $cx, $cy, $int_w, $int_h, round(rand(0, 190)), round(rand(191, 360)), $linecolor);
-          imagearc($image, $cx-1, $cy-1, $int_w, $int_h, round(rand(0, 190)), round(rand(191, 360)), $linecolor);
-        }
-      }
-      if ($lines == '1' || $lines == '2' && rand(0,1))
-      {
-        // Draw random lines
-        for ($i = 0; $i <= 50; $i++)
-        {
-          $linecolor = imagecolorallocate($image, rand(120,255),rand(120,255),rand(120,255));
-          imageline($image, round(rand(1, $total_width*3)), round(rand(1, $total_height*5)), round(rand(1, $total_width/2)), round(rand(1, $total_height*2)), $linecolor);
-        }
-      }
-      
-      $text_color_array = array('255,51,0', '51,77,255', '204,51,102', '0,153,0', '255,166,2', '255,0,255', '255,0,0', '0,255,0', '0,0,255', '0,255,255');
-      shuffle($text_color_array);
-      $pre_text_color_array = array('255,71,20', '71,20,224', '224,71,122', '20,173,20', '255,186,22', '25,25,25');
-      shuffle($pre_text_color_array);
-      $white = imagecolorallocate($image, 255, 255, 255);
-      $gray = imagecolorallocate($image, 100, 100, 100);
-      $black = imagecolorallocate($image, 0, 0, 0);
-      $lattice_color = imagecolorallocate($image, $rgb_lattice_color[0], $rgb_lattice_color[1], $rgb_lattice_color[2]);
-      
-      $x_char_position = (round(($total_width - 12) / strlen($code)) + mt_rand(-3, 5));
-      
-      for ($i = 0; $i < strlen($code); $i++)
-      {
-        mt_srand((double)microtime()*1000000);
-      
-        $char = $code{$i};
-        $size = mt_rand(floor($total_height / 3.5), ceil($total_height / 2.8));
-        $font = ($rnd_font) ? rand(0, (count($fonts)-1)) : $font;
-        $angle = mt_rand(-30, 30);
-      
-        $char_pos = array();
-        $char_pos = imagettfbbox($size, $angle, ENANO_ROOT.'/includes/captcha/fonts/'.$fonts[$font], $char);
-        $letter_width = abs($char_pos[0]) + abs($char_pos[4]);
-        $letter_height = abs($char_pos[1]) + abs($char_pos[5]);
-      
-        $x_pos = ($x_char_position / 4) + ($i * $x_char_position);
-        ($i == strlen($code)-1 && $x_pos >= ($total_width - ($letter_width + 5))) ? $x_pos = ($total_width - ($letter_width + 5)) : '';
-        $y_pos = mt_rand(($size * 1.4 ), $total_height - ($size * 0.4));
-      
-      //	Pre letters
-        $size = ($pre_letter_great) ? $size + (2 * $pre_letters) : $size - (2 * $pre_letters);
-        for ($count = 1; $count <= $pre_letters; $count++)
-        {
-          $pre_angle = $angle + mt_rand(-20, 20);
-      
-          $text_color = $pre_text_color_array[mt_rand(0,count($pre_text_color_array)-1)];
-          $text_color = explode(",", $text_color);
-          $textcolor = imagecolorallocate($image, $text_color[0], $text_color[1], $text_color[2]);
-      
-          imagettftext($image, $size, $pre_angle, $x_pos, $y_pos-2, $white, ENANO_ROOT.'/includes/captcha/fonts/'.$fonts[$font], $char);
-          imagettftext($image, $size, $pre_angle, $x_pos+2, $y_pos, $black, ENANO_ROOT.'/includes/captcha/fonts/'.$fonts[$font], $char);
-          imagettftext($image, $size, $pre_angle, $x_pos+1, $y_pos-1, $textcolor, ENANO_ROOT.'/includes/captcha/fonts/'.$fonts[$font], $char);
-      
-          $size = ($pre_letter_great) ? $size - 2 : $size + 2;
-        }
-      
-      //	Final letters
-        $text_color = $text_color_array[mt_rand(0,count($text_color_array)-1)];
-        $text_color = explode(",", $text_color);
-        $textcolor = imagecolorallocate($image, $text_color[0], $text_color[1], $text_color[2]);
-      
-        imagettftext($image, $size, $angle, $x_pos, $y_pos-2, $white, ENANO_ROOT.'/includes/captcha/fonts/'.$fonts[$font], $char);
-        imagettftext($image, $size, $angle, $x_pos+2, $y_pos, $black, ENANO_ROOT.'/includes/captcha/fonts/'.$fonts[$font], $char);
-        imagettftext($image, $size, $angle, $x_pos+1, $y_pos-1, $textcolor, ENANO_ROOT.'/includes/captcha/fonts/'.$fonts[$font], $char);
-      }
-      
-      
-      ($gammacorrect) ? imagegammacorrect($image, 1.0, $gammacorrect) : '';
-      
-      // Generate a white lattice in foreground
-      if ($foreground_lattice_y)
-      {
-        // x lines
-        $ih = round($total_height / $foreground_lattice_y);
-        for ($i = 0; $i <= $ih; $i++)
-        {
-          imageline($image, 0, $i*$foreground_lattice_y, $total_width, $i*$foreground_lattice_y, $lattice_color);
-        }
-      }
-      if ($foreground_lattice_x)
-      {
-        // y lines
-        $iw = round($total_width / $foreground_lattice_x);
-        for ($i = 0; $i <= $iw; $i++)
-        {
-          imageline($image, $i*$foreground_lattice_x, 0, $i*$foreground_lattice_x, $total_height, $lattice_color);
-        }
-      }
-      
-      // Font debug
-      if ($font_debug && !$rnd_font)
-      {
-        imagestring($image, 5, 2, 0, $fonts[$font], $white);
-        imagestring($image, 5, 5, 0, $fonts[$font], $white);
-        imagestring($image, 5, 4, 2, $fonts[$font], $gray);
-        imagestring($image, 5, 3, 1, $fonts[$font], $black);
-      }
-      
-      // Display
-      header("Last-Modified: " . gmdate("D, d M Y H:i:s") ." GMT"); 
-      header("Pragma: no-cache"); 
-      header("Cache-Control: no-store, no-cache, max-age=0, must-revalidate");
-      (!$jpeg) ? header("Content-Type: image/png") : header("Content-Type: image/jpeg");
-      
-      (!$jpeg) ? imagepng($image) : imagejpeg($image, '', $img_quality);
-      imagedestroy($image);
-    } else {
-      /**
-        * The next part is orginnaly written by ted from mastercode.nl and modified for use in Enano.
-        **/
-      header("content-type:image/png");
-      header('Cache-control: no-cache, no-store');
-      $breedte = 320;
-      $hoogte = 60;
-      $img = imagecreatetruecolor($breedte,$hoogte);
-      $achtergrond = imagecolorallocate($img, $this->color("bg"), $this->color("bg"), $this->color("bg"));
-      
-      imagefilledrectangle($img, 0, 0, $breedte-1, $hoogte-1, $achtergrond);
-      for($g = 0;$g < 30; $g++)
-      {
-        $t = $this->dss_rand();
-        $t = $t[0];
-            
-        $ypos = rand(0,$hoogte);
-        $xpos = rand(0,$breedte);
-            
-        $kleur = imagecolorallocate($img, $this->color("bgtekst"), $this->color("bgtekst"), $this->color("bgtekst"));
-            
-        imagettftext($img, $this->size(), $this->move(), $xpos, $ypos, $kleur, $this->font(), $t);
-      } 			
-      $stukje = $breedte / (strlen($code) + 3);
-      
-      for($j = 0;$j < strlen($code); $j++)
-      {
-        
-        
-        $tek = $code[$j];
-        $ypos = rand(33,43);
-        $xpos = $stukje * ($j+1);
-            
-        $kleur2 = imagecolorallocate($img, $this->color("tekst"), $this->color("tekst"), $this->color("tekst"));
-        
-        imagettftext($img, $this->size(), $this->move(), $xpos, $ypos, $kleur2, $this->font() , $tek);
-      }
-        
-      imagepng($img);
+  function set_code($code)
+  {
+    if ( !is_string($code) )
+      return false;
+    
+    $this->code = $code;
+  }
+  
+  /**
+   * Returns the confirmation code
+   * @return string
+   */
+  
+  function get_code()
+  {
+    return $this->code;
+  }
+  
+}
+
+/**
+ * Returns a new captcha object
+ * @param string Session ID
+ * @param string Optional - engine to load
+ * @param array Optional row to send to the captcha engine
+ */
+
+function captcha_object($session_id, $engine = false, $row = false)
+{
+  static $singletons = array();
+  if ( !$engine )
+  {
+    $engine = getConfig('captcha_engine');
+    if ( !$engine )
+    {
+      $engine = 'bc';
     }
   }
-  /**
-    * Some functions :)
-    * Also orginally written by mastercode.nl
-    **/
-  /**
-    * Function to create a random color
-    * @param $type string Mode for the color
-    * @return int
-    **/
-  function color($type)
-  {
-    switch($type)
-    {
-      case "bg": 
-        $kleur = rand(224,255); 
-      break;
-      case "tekst": 
-        $kleur = rand(0,127); 
-      break;
-      case "bgtekst": 
-        $kleur = rand(200,224); 
-      break;
-      default: 
-        $kleur = rand(0,255); 
-      break;
-    }
-    return $kleur;
-  }
-  /**
-    * Function to ranom the size
-    * @return int
-    **/
-  function size()
-  {
-    $grootte = rand(14,30);
-    return $grootte;
-  }
-  /**
-    * Function to random the posistion
-    * @return int
-    **/
-  function move()
-  {
-    $draai = rand(-25,25);
-    return $draai;
-  }
-  /**
-    * Function to return a ttf file from fonts map
-    * @return string
-    **/
-  function font()
+  if( !extension_loaded("gd") || !function_exists("gd_info") || !function_exists('imagettftext') )
   {
-    $f = @opendir(ENANO_ROOT . '/includes/captcha/fonts/');
-    if(!$f) die('Can\'t open '.ENANO_ROOT.'/includes/captcha/fonts/ for reading');
-    $ar = array();
-    while(($file = @readdir($f)) !== false)
-    {
-      if(!in_array($file, array('.','..')) && strstr($file, '.ttf'))
-      {
-        $ar[] = $file;
-      }
-    }
-    if(count($ar))
-    {
-      shuffle($ar);
-      $i = rand(0,(count($ar) - 1));
-      return ENANO_ROOT . '/includes/captcha/fonts/' . $ar[$i];
-    }
+    $engine = 'failsafe';
   }
-  
-  // This is designed to randomise the pixels of the image data within
-  // certain limits so as to keep it readable. It also varies the image
-  // width a little
-  function randomise($scanline, $width)
-  {
-    $new_line = '';
-    $start = floor($width/2);
-    $end = strlen($scanline) - ceil($width/2);
-  
-    for ($i = $start; $i < $end; $i++)
-    {
-      $pixel = ord($scanline{$i});
-  
-      if ($pixel < 190)
-      {
-        $new_line .= chr(mt_rand(0, 205));
-      }
-      else if ($pixel > 190)
-      {
-        $new_line .= chr(mt_rand(145, 255));
-      }
-      else
-      {
-        $new_line .= $scanline{$i};
-      }
-    }
-  
-    return $new_line;
-  }
-  
-  // This creates a chunk of the given type, with the given data
-  // of the given length adding the relevant crc
-  function png_chunk($length, $type, $data)
-  {
-    $raw = $type;
-    $raw .= $data;
-    $crc = crc32($raw);
-    $raw .= pack('C4', $crc >> 24, $crc >> 16, $crc >> 8, $crc);
-  
-    return pack('C4', $length >> 24, $length >> 16, $length >> 8, $length) . $raw;
-  }
-  
-  // Creates greyscale 8bit png - The PNG spec can be found at
-  // http://www.libpng.org/pub/png/spec/PNG-Contents.html we use
-  // png because it's a fully recognised open standard and supported
-  // by practically all modern browsers and OSs
-  function create_png($raw_image, $width, $height)
-  
+  if ( !class_exists("captcha_engine_$engine") )
   {
-    // SIG
-    $image = pack('C8', 137, 80, 78, 71, 13, 10, 26, 10);
-    // IHDR
-    $raw = pack('C4', $width >> 24, $width >> 16, $width >> 8, $width);
-    $raw .= pack('C4', $height >> 24, $height >> 16, $height >> 8, $height);
-    $raw .= pack('C5', 8, 0, 0, 0, 0);
-    $image .= $this->png_chunk(13, 'IHDR', $raw);
-  
-    if (@extension_loaded('zlib'))
-    {
-      $raw_image = gzcompress($raw_image);
-      $length = strlen($raw_image);
-    }
-    else
-    {
-      // The total length of this image, uncompressed, is just a calculation of pixels
-      $length = ($width + 1) * $height;
-  
-      // Adler-32 hash generation
-      // Optimized Adler-32 loop ported from the GNU Classpath project
-      $temp_length = $length;
-      $s1 = 1;
-      $s2 = $index = 0;
-  
-      while ($temp_length > 0)
-      {
-        // We can defer the modulo operation:
-        // s1 maximally grows from 65521 to 65521 + 255 * 3800
-        // s2 maximally grows by 3800 * median(s1) = 2090079800 < 2^31
-        $substract_value = ($temp_length < 3800) ? $temp_length : 3800;
-        $temp_length -= $substract_value;
-  
-        while (--$substract_value >= 0)
-        {
-          $s1 += ord($raw_image[$index]);
-          $s2 += $s1;
-  
-          $index++;
-        }
-  
-        $s1 %= 65521;
-        $s2 %= 65521;
-      }
-      $adler_hash = pack('N', ($s2 << 16) | $s1);
-  
-      // This is the same thing as gzcompress($raw_image, 0) but does not need zlib
-      $raw_image = pack('C3v2', 0x78, 0x01, 0x01, $length, ~$length) . $raw_image . $adler_hash;
-  
-      // The Zlib header + Adler hash make us add on 11
-      $length += 11;
-    }
-  
-    // IDAT
-    $image .= $this->png_chunk($length, 'IDAT', $raw_image);
-  
-    // IEND
-    $image .= $this->png_chunk(0, 'IEND', '');
-  
-    return $image;
+    require_once ENANO_ROOT . "/includes/captcha/engine_{$engine}.php";
   }
-  
-  // Each 'data' element is base64_encoded uncompressed IDAT
-  // png image data
-  function define_filtered_pngs()
+  if ( !class_exists("captcha_engine_$engine") )
   {
-    $_png = array(
-      '0' => array('data' => 'AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A///////////////////olFAkBAAAGDyA4P///M31/////////////wD////////////////0dAgAAAAAAAAAAAAEcPipFGHn////////////AP//////////////6DAAAAAAAAAAAAAAAAAALSEAN+T///////////8A//////////////xAAAAAAAAAAAAAAAAAAAAAACPA/////////////wD/////////////oAAAAAAAAAAAAAAAAAAAAAAAev//////////////AP////////////8oAAAAAAAAPNj/zDAAAAAAAABD//////////////8A////////////1AAAAAAAABjw////5BAAAAAAAADo/////////////wD///////////+QAAAAAAAAbP//////QgAAAAAAAKj/////////////AP///////////1wAAAAAAACs/////8AXAAAAAAAAcP////////////8A////////////OAAAAAAAAND////dNwAAAAAAAABI/////////////wD///////////8gAAAAAAAA4P//7koACwAAAAAAACT/////////////AP///////////wgAAAAAAAD///VqAwaPAAAAAAAAEP////////////8A////////////AAAAAAAAAP/8kQYDavUAAAAAAAAA/////////////wD///////////8AAAAAAAAA/6kNAEru/wAAAAAAAAD/////////////AP///////////wAAAAAAAADAIwA33f//AAAAAAAAAP////////////8A////////////FAAAAAAAADYAI8D///8AAAAAAAAQ/////////////wD///////////8kAAAAAAAAAA2p////5AAAAAAAACD/////////////AP///////////0gAAAAAAAAFkfz////UAAAAAAAAQP////////////8A////////////cAAAAAAAAET1/////7AAAAAAAABo/////////////wD///////////+oAAAAAAAAXfX/////sAAAAAAAAGj/////////////AAAAALgAAAAAAAAwAAAAAAAAAAAAAAD////////////oAAAAAAAACOT////oEAAAAAAAAOD/////////////AP////////////8+AAAAAAAAKMz/zDQAAAAAAAA0//////////////8A////////////7jgAAAAAAAAAAAAAAAAAAAAAAKT//////////////wD///////////VqAwIAAAAAAAAAAAAAAAAAAAA8////////////////AP//////////rQcDaVEAAAAAAAAAAAAAAAAAKOj///////////////8A///////////nblnu/IAIAAAAAAAAAAAAAFzw/////////////////wD////////////79////+iITCAAAAAgSITg////////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////w==','width' => 40), 
-      '1' => array('data' => 'AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////8BAAAAAAAP//////////////////AP////////////////////////9sAAAAAAAA//////////////////8A////////////////////////pAAAAAAAAAD//////////////////wD//////////////////////6wEAAAAAAAAAP//////////////////AP////////////////////h4AAAAAAAAAAAA//////////////////8A//////////////////ygJAAAAAAAAAAAAAD//////////////////wD//////////////9x8HAAAAAAAAAAAAAAAAP//////////////////AP//////////////AAAAAAAAAAAAAAAAAAAA//////////////////8A//////////////8AAAAAAAAAAAAAAAAAAAD//////////////////wD//////////////wAAAAAAAAR4AAAAAAAAAP//////////////////AP//////////////AAAAAAA4zP8AAAAAAAAA//////////////////8A//////////////8AAAA4sP///wAAAAAAAAD//////////////////wD//////////////yR80P//////AAAAAAAAAP//////////////////AP////////////////////////8AAAAAAAAA//////////////////8A/////////////////////////wAAAAAAAAD//////////////////wD/////////////////////////AAAAAAAAAP//////////////////AP////////////////////////8AAAAAAAAA//////////////////8A/////////////////////////wAAAAAAAAD//////////////////wD/////////////////////////AAAAAAAAAP//////////////////AP////////////////////////8AAAAAAAAA//////////////////8A/////////////////////////wAAAAAAAAD//////////////////wD/////////////////////////AAAAAAAAAP//////////////////AP////////////////////////8AAAAAAAAA//////////////////8A/////////////////////////wAAAAAAAAD//////////////////wD/////////////////////////AAAAAAAAAP//////////////////AP////////////////////////8AAAAAAAAA//////////////////8A/////////////////////////wAAAAAAAAD//////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8=','width' => 40), 
-      '2' => array('data' => 'AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP/////////////////okFAkCAAABCBIfNT///////////////////8A///////////////8hAgAAAAAAAAAAAAAAFTo/////////////////wD//////////////1QAAAAAAAAAAAAAAAAAACjo////////////////AP////////////+MAAAAAAAAAAAAAAAAAAAAADj///////////////8A////////////9BAAAAAAAAAAAAAAAAAAAAAAALD//////////////wD///////////+gAAAAAAAAAHjs+KwMAAAAAAAAVP//////////////AP///////////1gAAAAAAABM/////6QAAAAAAAAU//////////////8A////////////KAAAAAAAALj/////+AAAAAAAAAD//////////////wD///////////+MfGBMOCAI8P/////wAAAAAAAACP//////////////AP///////////////////////////5wAAAAAAAAw//////////////8A///////////////////////////oFAAAAAAAAHz//////////////wD/////////////////////////6CgAAAAAAAAE3P//////////////AP///////////////////////9ggAAAAAAAAAHT///////////////8A//////////////////////+0DAAAAAAAAAA8+P///////////////wD/////////////////////gAAAAAAAAAAAKOj/////////////////AP//////////////////9FAAAAAAAAAAADzw//////////////////8A/////////////////+g4AAAAAAAAAABk/P///////////////////wD////////////////oKAAAAAAAAAAMqP//////////////////////AP//////////////6CgAAAAAAAAAMNz///////////////////////8A//////////////g4AAAAAAAAAFT0/////////////////////////wD/////////////bAAAAAAAAABU/P//////////////////////////AP///////////8wAAAAAAAAAAAAAAAAAAAAAAAAA//////////////8A////////////SAAAAAAAAAAAAAAAAAAAAAAAAAD//////////////wD//////////9wAAAAAAAAAAAAAAAAAAAAAAAAAAP//////////////AP//////////hAAAAAAAAAAAAAAAAAAAAAAAAAAA//////////////8A//////////9AAAAAAAAAAAAAAAAAAAAAAAAAAAD//////////////wD//////////xAAAAAAAAAAAAAAAAAAAAAAAAAAAP//////////////AP////////////////////////////////////////////////////8=','width' => 40), 
-      '3' => array('data' => 'AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD////////////////8sGg0FAAAACA4cLz8////////////////////AP//////////////rBgAAAAAAAAAAAAAACTA//////////////////8A/////////////3QAAAAAAAAAAAAAAAAAAASs/////////////////wD///////////+YAAAAAAAAAAAAAAAAAAAAAAjc////////////////AP//////////6AwAAAAAAAAAAAAAAAAAAAAAAGT///////////////8A//////////94AAAAAAAABJDw/8g4AAAAAAAAHP///////////////wD//////////yAAAAAAAACE/////9gAAAAAAAAA////////////////AP///////////NSwiGQ4FOT//////AAAAAAAABD///////////////8A//////////////////////////+YAAAAAAAAVP///////////////wD//////////////////////P/ggAQAAAAAAATM////////////////AP////////////////////9gAAAAAAAAAAAElP////////////////8A/////////////////////0AAAAAAAAAAHLj//////////////////wD/////////////////////OAAAAAAAAAAwkPj/////////////////AP////////////////////8gAAAAAAAAAAAAINj///////////////8A/////////////////////xAAAAAAAAAAAAAAIPD//////////////wD/////////////////////uOz/4HgEAAAAAAAAhP//////////////AP///////////////////////////3wAAAAAAAAw//////////////8A////////////////////////////6AAAAAAAAAj//////////////wD/////////////////////////////AAAAAAAAAP//////////////AP//////////tJh8YEQoDNz//////+AAAAAAAAAY//////////////8A//////////88AAAAAAAAaP//////dAAAAAAAAEz//////////////wD//////////6QAAAAAAAAAdOD/5HQAAAAAAAAApP//////////////AP///////////CgAAAAAAAAAAAAAAAAAAAAAACD4//////////////8A////////////yAQAAAAAAAAAAAAAAAAAAAAEuP///////////////wD/////////////rAQAAAAAAAAAAAAAAAAABJD/////////////////AP//////////////zDQAAAAAAAAAAAAAACTA//////////////////8A/////////////////8BwOCAAAAAUNGi0/P///////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8=','width' => 40), 
-      '4' => array('data' => 'AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP//////////////////////////nAAAAAAAAAD///////////////8A/////////////////////////8AEAAAAAAAAAP///////////////wD////////////////////////gGAAAAAAAAAAA////////////////AP//////////////////////9DAAAAAAAAAAAAD///////////////8A//////////////////////9UAAAAAAAAAAAAAP///////////////wD/////////////////////hAAAAAAAAAAAAAAA////////////////AP///////////////////7QAAAAAAAAAAAAAAAD///////////////8A///////////////////UDAAAAAAUAAAAAAAAAP///////////////wD/////////////////7CQAAAAABMAAAAAAAAAA////////////////AP////////////////xEAAAAAACU/wAAAAAAAAD///////////////8A////////////////cAAAAAAAZP//AAAAAAAAAP///////////////wD//////////////6AAAAAAADz8//8AAAAAAAAA////////////////AP/////////////IBAAAAAAc6P///wAAAAAAAAD///////////////8A////////////5BgAAAAADMz/////AAAAAAAAAP///////////////wD///////////g0AAAAAACk//////8AAAAAAAAA////////////////AP//////////XAAAAAAAfP///////wAAAAAAAAD///////////////8A//////////8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP///////////wD//////////wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA////////////AP//////////AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD///////////8A//////////8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP///////////wD//////////wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA////////////AP//////////AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD///////////8A////////////////////////////AAAAAAAAAP///////////////wD///////////////////////////8AAAAAAAAA////////////////AP///////////////////////////wAAAAAAAAD///////////////8A////////////////////////////AAAAAAAAAP///////////////wD///////////////////////////8AAAAAAAAA////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8=','width' => 40), 
-      '5' => array('data' => 'AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP//////////////8AAAAAAAAAAAAAAAAAAAAAAA//////////////8A///////////////MAAAAAAAAAAAAAAAAAAAAAAD//////////////wD//////////////6wAAAAAAAAAAAAAAAAAAAAAAP//////////////AP//////////////iAAAAAAAAAAAAAAAAAAAAAAA//////////////8A//////////////9kAAAAAAAAAAAAAAAAAAAAAAD//////////////wD//////////////0QAAAAAAAAAAAAAAAAAAAAAAP//////////////AP//////////////IAAAAAAAYP////////////////////////////8A//////////////wAAAAAAAB8/////////////////////////////wD/////////////3AAAAAAAAIj/////////////////////////////AP////////////+4AAAAAAAAoLRYHAAEKGTE//////////////////8A/////////////5QAAAAAAAAQAAAAAAAAAABY9P///////////////wD/////////////dAAAAAAAAAAAAAAAAAAAAAA89P//////////////AP////////////9QAAAAAAAAAAAAAAAAAAAAAABg//////////////8A/////////////zAAAAAAAAAAAAAAAAAAAAAAAADQ/////////////wD/////////////IAAAAAAAAGjY/+h4BAAAAAAAAGz/////////////AP//////////////9NS0lHSc//////90AAAAAAAALP////////////8A/////////////////////////////9QAAAAAAAAE/////////////wD//////////////////////////////wAAAAAAAAD/////////////AP/////////////////////////////8AAAAAAAAEP////////////8A////////////pIRwWEAgDOD//////8wAAAAAAAA8/////////////wD///////////9EAAAAAAAAaP//////ZAAAAAAAAHz/////////////AP///////////6QAAAAAAAAAaOD/4GQAAAAAAAAE4P////////////8A/////////////CQAAAAAAAAAAAAAAAAAAAAAAGD//////////////wD/////////////yAQAAAAAAAAAAAAAAAAAAAAc7P//////////////AP//////////////rAwAAAAAAAAAAAAAAAAAGNj///////////////8A////////////////0EAAAAAAAAAAAAAAAFTo/////////////////wD//////////////////8h4QCAAAAAcQHzU////////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8=','width' => 40), 
-      '6' => array('data' => 'AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD///////////////////+0ZCwMAAAUNGjI////////////////////AP/////////////////EMAAAAAAAAAAAAABM6P////////////////8A////////////////lAQAAAAAAAAAAAAAAAAo6P///////////////wD//////////////6wAAAAAAAAAAAAAAAAAAABI////////////////AP/////////////oEAAAAAAAAAAAAAAAAAAAAACw//////////////8A/////////////3AAAAAAAAAoxP/YPAAAAAAAAEj//////////////wD////////////4EAAAAAAACOD////YDCBAVGiAoP//////////////AP///////////7gAAAAAAABY//////////////////////////////8A////////////eAAAAAAAAJT//////////////////////////////wD///////////9MAAAAAAAAvP/IXBgABCx03P//////////////////AP///////////ygAAAAAAADcdAAAAAAAAAAEiP////////////////8A////////////FAAAAAAAAFAAAAAAAAAAAAAAcP///////////////wD///////////8AAAAAAAAAAAAAAAAAAAAAAAAAlP//////////////AP///////////wAAAAAAAAAAAAAAAAAAAAAAAAAQ8P////////////8A////////////AAAAAAAAAABAyP/kZAAAAAAAAACQ/////////////wD///////////8MAAAAAAAALPj/////WAAAAAAAAET/////////////AP///////////yQAAAAAAACY///////MAAAAAAAAFP////////////8A////////////SAAAAAAAAMD///////wAAAAAAAAA/////////////wD///////////9wAAAAAAAAvP///////wAAAAAAAAD/////////////AP///////////7QAAAAAAACI///////UAAAAAAAAJP////////////8A////////////+AwAAAAAACDw/////2wAAAAAAABY/////////////wD/////////////cAAAAAAAADC8/Ox4AAAAAAAAAKj/////////////AP/////////////oEAAAAAAAAAAAAAAAAAAAAAAk/P////////////8A//////////////+oAAAAAAAAAAAAAAAAAAAABLj//////////////wD///////////////+QAAAAAAAAAAAAAAAAAACQ////////////////AP////////////////+0JAAAAAAAAAAAAAAkuP////////////////8A///////////////////8sGg0FAAADCxgqPz//////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8=','width' => 40), 
-      '7' => array('data' => 'AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD///////////8AAAAAAAAAAAAAAAAAAAAAAAAAAAD/////////////AP///////////wAAAAAAAAAAAAAAAAAAAAAAAAAAAP////////////8A////////////AAAAAAAAAAAAAAAAAAAAAAAAAAAA/////////////wD///////////8AAAAAAAAAAAAAAAAAAAAAAAAAAAD/////////////AP///////////wAAAAAAAAAAAAAAAAAAAAAAAAAABP////////////8A////////////AAAAAAAAAAAAAAAAAAAAAAAAAAy4/////////////wD//////////////////////////+QUAAAAAAAEuP//////////////AP/////////////////////////8QAAAAAAAAKT///////////////8A/////////////////////////4wAAAAAAAB0/////////////////wD////////////////////////cCAAAAAAANPz/////////////////AP///////////////////////0QAAAAAAATY//////////////////8A//////////////////////+0AAAAAAAAeP///////////////////wD//////////////////////CQAAAAAABTw////////////////////AP////////////////////+gAAAAAAAAkP////////////////////8A/////////////////////ywAAAAAABDw/////////////////////wD///////////////////+4AAAAAAAAbP//////////////////////AP///////////////////1wAAAAAAADQ//////////////////////8A///////////////////4DAAAAAAAMP///////////////////////wD//////////////////7QAAAAAAAB8////////////////////////AP//////////////////aAAAAAAAAMj///////////////////////8A//////////////////8oAAAAAAAM/P///////////////////////wD/////////////////8AAAAAAAAET/////////////////////////AP////////////////+0AAAAAAAAcP////////////////////////8A/////////////////4wAAAAAAACY/////////////////////////wD/////////////////WAAAAAAAAMD/////////////////////////AP////////////////80AAAAAAAA4P////////////////////////8A/////////////////xAAAAAAAAD4/////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8=','width' => 40), 
-      '8' => array('data' => 'AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD////////////////////IdDQUAAAEIEiA1P//////////////////AP/////////////////gRAAAAAAAAAAAAAAAROD///////////////8A////////////////0BgAAAAAAAAAAAAAAAAAEMj//////////////wD///////////////AcAAAAAAAAAAAAAAAAAAAAHPD/////////////AP//////////////hAAAAAAAAAAAAAAAAAAAAAAAhP////////////8A//////////////8sAAAAAAAAKMz/zCgAAAAAAAAs/////////////wD//////////////wAAAAAAAADM////zAAAAAAAAAD/////////////AP//////////////BAAAAAAAAP//////AAAAAAAABP////////////8A//////////////8sAAAAAAAAzP///9QAAAAAAAAw/////////////wD//////////////3wAAAAAAAAoyP/YNAAAAAAAAIT/////////////AP//////////////7BgAAAAAAAAAAAAAAAAAAAAc8P////////////8A////////////////xBgAAAAAAAAAAAAAAAAAGNj//////////////wD/////////////////tAQAAAAAAAAAAAAAAACo////////////////AP///////////////HAAAAAAAAAAAAAAAAAAAAB8//////////////8A//////////////9gAAAAAAAAAAAAAAAAAAAAAAB8/////////////wD/////////////wAAAAAAAAABk4P/UWAAAAAAAAATQ////////////AP////////////9UAAAAAAAAaP//////XAAAAAAAAGT///////////8A/////////////xgAAAAAAADg///////cAAAAAAAAJP///////////wD/////////////AAAAAAAAAP////////8AAAAAAAAA////////////AP////////////8AAAAAAAAA4P//////3AAAAAAAAAT///////////8A/////////////ygAAAAAAABg//////9cAAAAAAAALP///////////wD/////////////ZAAAAAAAAABY1P/cXAAAAAAAAABw////////////AP/////////////QAAAAAAAAAAAAAAAAAAAAAAAABNz///////////8A//////////////9gAAAAAAAAAAAAAAAAAAAAAAB0/////////////wD///////////////Q8AAAAAAAAAAAAAAAAAAAAUPz/////////////AP////////////////x4CAAAAAAAAAAAAAAAEIT8//////////////8A///////////////////smFQwGAAAABg0ZKT0/////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8=','width' => 40), 
-      '9' => array('data' => 'AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD///////////////////ysYCwMAAAUNGiw/P//////////////////AP////////////////+4JAAAAAAAAAAAAAAkuP////////////////8A////////////////lAQAAAAAAAAAAAAAAAAAkP///////////////wD//////////////8AEAAAAAAAAAAAAAAAAAAAAqP//////////////AP/////////////8JAAAAAAAAAAAAAAAAAAAAAAQ7P////////////8A/////////////6wAAAAAAAAAfOz8vCwAAAAAAABw/////////////wD/////////////WAAAAAAAAHD/////7BgAAAAAAAz4////////////AP////////////8kAAAAAAAA1P//////hAAAAAAAALT///////////8A/////////////wAAAAAAAAD///////+4AAAAAAAAcP///////////wD/////////////AAAAAAAAAPz//////8AAAAAAAABI////////////AP////////////8UAAAAAAAAzP//////lAAAAAAAACT///////////8A/////////////0QAAAAAAABY//////gsAAAAAAAADP///////////wD/////////////kAAAAAAAAABw5P/IPAAAAAAAAAAA////////////AP/////////////wEAAAAAAAAAAAAAAAAAAAAAAAAAD///////////8A//////////////+UAAAAAAAAAAAAAAAAAAAAAAAAAP///////////wD///////////////9wAAAAAAAAAAAAAFAAAAAAAAAU////////////AP////////////////+IBAAAAAAAAABw3AAAAAAAACj///////////8A///////////////////cdCwEABhcxP+8AAAAAAAATP///////////wD//////////////////////////////5AAAAAAAAB4////////////AP//////////////////////////////UAAAAAAAALj///////////8A//////////////+kgGxUQCAM2P///+AIAAAAAAAQ+P///////////wD//////////////0gAAAAAAAA42P/EKAAAAAAAAHD/////////////AP//////////////sAAAAAAAAAAAAAAAAAAAAAAQ6P////////////8A////////////////TAAAAAAAAAAAAAAAAAAAAKz//////////////wD////////////////oKAAAAAAAAAAAAAAAAASU////////////////AP/////////////////sUAAAAAAAAAAAAAAwxP////////////////8A////////////////////yHA0FAAADCxktP///////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8=','width' => 40), 
-      'A' => array('data' => 'AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD//////////////////+QAAAAAAAAAAAAAAOT/////////////////AP//////////////////kAAAAAAAAAAAAAAAkP////////////////8A//////////////////88AAAAAAAAAAAAAAA8/////////////////wD/////////////////5AAAAAAAAAAAAAAAAADk////////////////AP////////////////+QAAAAAAAAAAAAAAAAAJD///////////////8A/////////////////zwAAAAAAAAAAAAAAAAAPP///////////////wD////////////////kAAAAAAAAAAgAAAAAAAAA5P//////////////AP///////////////5AAAAAAAAAAgAAAAAAAAACQ//////////////8A////////////////PAAAAAAAAAz8HAAAAAAAADz//////////////wD//////////////+QAAAAAAAAAWP9kAAAAAAAAANz/////////////AP//////////////kAAAAAAAAACk/7wAAAAAAAAAhP////////////8A//////////////88AAAAAAAABOz//BQAAAAAAAAw/////////////wD/////////////4AAAAAAAAAA8////ZAAAAAAAAADc////////////AP////////////+EAAAAAAAAAIj///+8AAAAAAAAAIT///////////8A/////////////zAAAAAAAAAA2P////wQAAAAAAAAMP///////////wD////////////cAAAAAAAAACT//////1wAAAAAAAAA3P//////////AP///////////4QAAAAAAAAAAAAAAAAAAAAAAAAAAACE//////////8A////////////MAAAAAAAAAAAAAAAAAAAAAAAAAAAADD//////////wD//////////9wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAANz/////////AP//////////hAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAhP////////8A//////////8wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAw/////////wD/////////3AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADc////////AP////////+EAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIT///////8A/////////zAAAAAAAAAAhP///////////2QAAAAAAAAAMP///////wD////////cAAAAAAAAAADM////////////vAAAAAAAAAAA3P//////AP///////4QAAAAAAAAAHP/////////////4DAAAAAAAAACE//////8A////////MAAAAAAAAABk//////////////9cAAAAAAAAADD//////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8=','width' => 40), 
-      'B' => array('data' => 'AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A//////////8AAAAAAAAAAAAAAAAAAAAAEDh83P///////////////wD//////////wAAAAAAAAAAAAAAAAAAAAAAAAAEhP//////////////AP//////////AAAAAAAAAAAAAAAAAAAAAAAAAAAAeP////////////8A//////////8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAxP///////////wD//////////wAAAAAAAAAAAAAAAAAAAAAAAAAAAABY////////////AP//////////AAAAAAAAAAAAAAAAAAAAAAAAAAAAABT///////////8A//////////8AAAAAAAAAAP/////4zEwAAAAAAAAAAP///////////wD//////////wAAAAAAAAAA////////7AAAAAAAAAAQ////////////AP//////////AAAAAAAAAAD////////sAAAAAAAAAEj///////////8A//////////8AAAAAAAAAAP/////4zEQAAAAAAAAAtP///////////wD//////////wAAAAAAAAAAAAAAAAAAAAAAAAAAAFz/////////////AP//////////AAAAAAAAAAAAAAAAAAAAAAAAAAiA/P////////////8A//////////8AAAAAAAAAAAAAAAAAAAAAAAAIjPj//////////////wD//////////wAAAAAAAAAAAAAAAAAAAAAAAAAAGKz/////////////AP//////////AAAAAAAAAAAAAAAAAAAAAAAAAAAAAJT///////////8A//////////8AAAAAAAAAAAAAAAAAAAAAAAAAAAAABNz//////////wD//////////wAAAAAAAAAA///////sqCAAAAAAAAAAbP//////////AP//////////AAAAAAAAAAD/////////yAAAAAAAAAAs//////////8A//////////8AAAAAAAAAAP//////////AAAAAAAAAAT//////////wD//////////wAAAAAAAAAA/////////7wAAAAAAAAAAP//////////AP//////////AAAAAAAAAAD//////+ikGAAAAAAAAAAY//////////8A//////////8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFT//////////wD//////////wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAsP//////////AP//////////AAAAAAAAAAAAAAAAAAAAAAAAAAAAADj///////////8A//////////8AAAAAAAAAAAAAAAAAAAAAAAAAAAAc6P///////////wD//////////wAAAAAAAAAAAAAAAAAAAAAAAAAATOj/////////////AP//////////AAAAAAAAAAAAAAAAAAAEIEBkkNj///////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8=','width' => 40), 
-      'C' => array('data' => 'AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP//////////////////5JRULBAAAAgkTIDQ//////////////////8A////////////////1FAAAAAAAAAAAAAAAABAyP///////////////wD//////////////4gEAAAAAAAAAAAAAAAAAAAElP//////////////AP////////////9wAAAAAAAAAAAAAAAAAAAAAAAAlP////////////8A////////////kAAAAAAAAAAAAAAAAAAAAAAAAAAEyP///////////wD//////////9wIAAAAAAAAAAAAAAAAAAAAAAAAAAAw////////////AP//////////WAAAAAAAAAAAWMz/8JwQAAAAAAAAAACw//////////8A/////////+wEAAAAAAAAAID//////9QMAAAAAAAAAET//////////wD/////////nAAAAAAAAAAo/P///////3wAAAAABDBspP//////////AP////////9gAAAAAAAAAIz/////////3BxQjMT0//////////////8A/////////zQAAAAAAAAAzP///////////////////////////////wD/////////GAAAAAAAAADo////////////////////////////////AP////////8AAAAAAAAAAP////////////////////////////////8A/////////wAAAAAAAAAA/////////////////////////////////wD/////////AAAAAAAAAAD/////////////////////////////////AP////////8cAAAAAAAAAOj///////////////////////////////8A/////////zgAAAAAAAAA0P/////////kIGio7P///////////////wD/////////bAAAAAAAAACg/////////5wAAAAAMHS49P//////////AP////////+oAAAAAAAAAEz/////////PAAAAAAAAAAc//////////8A//////////QIAAAAAAAAALz//////6QAAAAAAAAAAGT//////////wD//////////3AAAAAAAAAADIzo/+SEBAAAAAAAAAAAyP//////////AP//////////7BAAAAAAAAAAAAAAAAAAAAAAAAAAAED///////////8A////////////rAAAAAAAAAAAAAAAAAAAAAAAAAAE0P///////////wD/////////////fAAAAAAAAAAAAAAAAAAAAAAAAJz/////////////AP//////////////iAQAAAAAAAAAAAAAAAAAAASY//////////////8A////////////////yEAAAAAAAAAAAAAAAAA8yP///////////////wD//////////////////9yIUCwQAAAAIEB4yP//////////////////AP////////////////////////////////////////////////////8=','width' => 40), 
-      'D' => array('data' => 'AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD///////////8AAAAAAAAAAAAAAAAADChQkOT/////////////////AP///////////wAAAAAAAAAAAAAAAAAAAAAABGjw//////////////8A////////////AAAAAAAAAAAAAAAAAAAAAAAAACDY/////////////wD///////////8AAAAAAAAAAAAAAAAAAAAAAAAAABjk////////////AP///////////wAAAAAAAAAAAAAAAAAAAAAAAAAAAED///////////8A////////////AAAAAAAAAAAAAAAAAAAAAAAAAAAAAKj//////////wD///////////8AAAAAAAAAAP///+isSAAAAAAAAAAANP//////////AP///////////wAAAAAAAAAA////////hAAAAAAAAAAA2P////////8A////////////AAAAAAAAAAD/////////MAAAAAAAAACQ/////////wD///////////8AAAAAAAAAAP////////+MAAAAAAAAAFj/////////AP///////////wAAAAAAAAAA/////////8gAAAAAAAAAMP////////8A////////////AAAAAAAAAAD/////////5AAAAAAAAAAY/////////wD///////////8AAAAAAAAAAP//////////AAAAAAAAAAD/////////AP///////////wAAAAAAAAAA//////////8AAAAAAAAAAP////////8A////////////AAAAAAAAAAD//////////wAAAAAAAAAA/////////wD///////////8AAAAAAAAAAP/////////wAAAAAAAAABD/////////AP///////////wAAAAAAAAAA/////////9QAAAAAAAAAJP////////8A////////////AAAAAAAAAAD/////////qAAAAAAAAABI/////////wD///////////8AAAAAAAAAAP////////9QAAAAAAAAAHj/////////AP///////////wAAAAAAAAAA////////uAAAAAAAAAAAvP////////8A////////////AAAAAAAAAAD////w0HwEAAAAAAAAACT8/////////wD///////////8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAoP//////////AP///////////wAAAAAAAAAAAAAAAAAAAAAAAAAAADz8//////////8A////////////AAAAAAAAAAAAAAAAAAAAAAAAAAAY6P///////////wD///////////8AAAAAAAAAAAAAAAAAAAAAAAAAKNz/////////////AP///////////wAAAAAAAAAAAAAAAAAAAAAACHT0//////////////8A////////////AAAAAAAAAAAAAAAAABg4bKj0/////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8=','width' => 40), 
-      'E' => array('data' => 'AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP//////////AAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////////////8A//////////8AAAAAAAAAAAAAAAAAAAAAAAAAAAAA/////////////wD//////////wAAAAAAAAAAAAAAAAAAAAAAAAAAAAD/////////////AP//////////AAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////////////8A//////////8AAAAAAAAAAAAAAAAAAAAAAAAAAAAA/////////////wD//////////wAAAAAAAAAAAAAAAAAAAAAAAAAAAAD/////////////AP//////////AAAAAAAAAAD///////////////////////////////8A//////////8AAAAAAAAAAP///////////////////////////////wD//////////wAAAAAAAAAA////////////////////////////////AP//////////AAAAAAAAAAD///////////////////////////////8A//////////8AAAAAAAAAAAAAAAAAAAAAAAAAAAD//////////////wD//////////wAAAAAAAAAAAAAAAAAAAAAAAAAAAP//////////////AP//////////AAAAAAAAAAAAAAAAAAAAAAAAAAAA//////////////8A//////////8AAAAAAAAAAAAAAAAAAAAAAAAAAAD//////////////wD//////////wAAAAAAAAAAAAAAAAAAAAAAAAAAAP//////////////AP//////////AAAAAAAAAAAAAAAAAAAAAAAAAAAA//////////////8A//////////8AAAAAAAAAAP///////////////////////////////wD//////////wAAAAAAAAAA////////////////////////////////AP//////////AAAAAAAAAAD///////////////////////////////8A//////////8AAAAAAAAAAP///////////////////////////////wD//////////wAAAAAAAAAA////////////////////////////////AP//////////AAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////////////8A//////////8AAAAAAAAAAAAAAAAAAAAAAAAAAAAA/////////////wD//////////wAAAAAAAAAAAAAAAAAAAAAAAAAAAAD/////////////AP//////////AAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////////////8A//////////8AAAAAAAAAAAAAAAAAAAAAAAAAAAAA/////////////wD//////////wAAAAAAAAAAAAAAAAAAAAAAAAAAAAD/////////////AP////////////////////////////////////////////////////8=','width' => 40),
-      'F' => array('data' => 'AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A/////////////wAAAAAAAAAAAAAAAAAAAAAAAAAA/////////////wD/////////////AAAAAAAAAAAAAAAAAAAAAAAAAAD/////////////AP////////////8AAAAAAAAAAAAAAAAAAAAAAAAAAP////////////8A/////////////wAAAAAAAAAAAAAAAAAAAAAAAAAA/////////////wD/////////////AAAAAAAAAAAAAAAAAAAAAAAAAAD/////////////AP////////////8AAAAAAAAAAAAAAAAAAAAAAAAAAP////////////8A/////////////wAAAAAAAAAA/////////////////////////////wD/////////////AAAAAAAAAAD/////////////////////////////AP////////////8AAAAAAAAAAP////////////////////////////8A/////////////wAAAAAAAAAA/////////////////////////////wD/////////////AAAAAAAAAAAAAAAAAAAAAAAA////////////////AP////////////8AAAAAAAAAAAAAAAAAAAAAAAD///////////////8A/////////////wAAAAAAAAAAAAAAAAAAAAAAAP///////////////wD/////////////AAAAAAAAAAAAAAAAAAAAAAAA////////////////AP////////////8AAAAAAAAAAAAAAAAAAAAAAAD///////////////8A/////////////wAAAAAAAAAAAAAAAAAAAAAAAP///////////////wD/////////////AAAAAAAAAAD/////////////////////////////AP////////////8AAAAAAAAAAP////////////////////////////8A/////////////wAAAAAAAAAA/////////////////////////////wD/////////////AAAAAAAAAAD/////////////////////////////AP////////////8AAAAAAAAAAP////////////////////////////8A/////////////wAAAAAAAAAA/////////////////////////////wD/////////////AAAAAAAAAAD/////////////////////////////AP////////////8AAAAAAAAAAP////////////////////////////8A/////////////wAAAAAAAAAA/////////////////////////////wD/////////////AAAAAAAAAAD/////////////////////////////AP////////////8AAAAAAAAAAP////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8=','width' => 40), 
-      'G' => array('data' => 'AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD//////////////////MB8TCgQAAAACCA4YJzs////////////////AP///////////////JQcAAAAAAAAAAAAAAAAAAhw8P////////////8A/////////////9gwAAAAAAAAAAAAAAAAAAAAAAAk2P///////////wD////////////EDAAAAAAAAAAAAAAAAAAAAAAAAAAc7P//////////AP//////////2AwAAAAAAAAAAAAAAAAAAAAAAAAAAABY//////////8A//////////wwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADQ/////////wD/////////kAAAAAAAAAAAEHzQ/P/gmCAAAAAAAAAAAFz/////////AP////////wcAAAAAAAAACjg////////8CwAAAAAAAAgWP////////8A////////vAAAAAAAAAAI2P//////////yBRAcJjI8P///////////wD///////94AAAAAAAAAGD/////////////////////////////////AP///////0AAAAAAAAAAsP////////////////////////////////8A////////IAAAAAAAAADc/////////////////////////////////wD///////8AAAAAAAAAAP///////wAAAAAAAAAAAAAAAAD/////////AP///////wAAAAAAAAAA////////AAAAAAAAAAAAAAAAAP////////8A////////AAAAAAAAAAD///////8AAAAAAAAAAAAAAAAA/////////wD///////8gAAAAAAAAAOD//////wAAAAAAAAAAAAAAAAD/////////AP///////0AAAAAAAAAAtP//////AAAAAAAAAAAAAAAAAP////////8A////////cAAAAAAAAABw//////8AAAAAAAAAAAAAAAAA/////////wD///////+8AAAAAAAAABDs////////////AAAAAAAAAAD/////////AP////////wYAAAAAAAAADz0//////////AAAAAAAAAAAP////////8A/////////5AAAAAAAAAAACCY4P//3KhcCAAAAAAAAAAA/////////wD/////////+CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD/////////AP//////////xAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIP////////8A////////////rAQAAAAAAAAAAAAAAAAAAAAAAAAAAGTw/////////wD/////////////vBQAAAAAAAAAAAAAAAAAAAAAADjI////////////AP//////////////8HAQAAAAAAAAAAAAAAAAAEiw//////////////8A//////////////////iwcEAgBAAABCA4aKDk/////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8=','width' => 40), 
-      'H' => array('data' => 'AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////8AAAAAAAAAAP///////////wAAAAAAAAAA//////////8A/////////wAAAAAAAAAA////////////AAAAAAAAAAD//////////wD/////////AAAAAAAAAAD///////////8AAAAAAAAAAP//////////AP////////8AAAAAAAAAAP///////////wAAAAAAAAAA//////////8A/////////wAAAAAAAAAA////////////AAAAAAAAAAD//////////wD/////////AAAAAAAAAAD///////////8AAAAAAAAAAP//////////AP////////8AAAAAAAAAAP///////////wAAAAAAAAAA//////////8A/////////wAAAAAAAAAA////////////AAAAAAAAAAD//////////wD/////////AAAAAAAAAAD///////////8AAAAAAAAAAP//////////AP////////8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA//////////8A/////////wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD//////////wD/////////AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP//////////AP////////8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA//////////8A/////////wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD//////////wD/////////AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP//////////AP////////8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA//////////8A/////////wAAAAAAAAAA////////////AAAAAAAAAAD//////////wD/////////AAAAAAAAAAD///////////8AAAAAAAAAAP//////////AP////////8AAAAAAAAAAP///////////wAAAAAAAAAA//////////8A/////////wAAAAAAAAAA////////////AAAAAAAAAAD//////////wD/////////AAAAAAAAAAD///////////8AAAAAAAAAAP//////////AP////////8AAAAAAAAAAP///////////wAAAAAAAAAA//////////8A/////////wAAAAAAAAAA////////////AAAAAAAAAAD//////////wD/////////AAAAAAAAAAD///////////8AAAAAAAAAAP//////////AP////////8AAAAAAAAAAP///////////wAAAAAAAAAA//////////8A/////////wAAAAAAAAAA////////////AAAAAAAAAAD//////////wD/////////AAAAAAAAAAD///////////8AAAAAAAAAAP//////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8=','width' => 40), 
-      'I' => array('data' => 'AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////AAAAAAAAAAAAAAAAAAAAAAAA////////////////AP////////////8AAAAAAAAAAAAAAAAAAAAAAAD///////////////8A/////////////wAAAAAAAAAAAAAAAAAAAAAAAP///////////////wD/////////////AAAAAAAAAAAAAAAAAAAAAAAA////////////////AP////////////8AAAAAAAAAAAAAAAAAAAAAAAD///////////////8A/////////////wAAAAAAAAAAAAAAAAAAAAAAAP///////////////wD/////////////AAAAAAAAAAAAAAAAAAAAAAAA////////////////AP///////////////////wAAAAAAAAAA//////////////////////8A////////////////////AAAAAAAAAAD//////////////////////wD///////////////////8AAAAAAAAAAP//////////////////////AP///////////////////wAAAAAAAAAA//////////////////////8A////////////////////AAAAAAAAAAD//////////////////////wD///////////////////8AAAAAAAAAAP//////////////////////AP///////////////////wAAAAAAAAAA//////////////////////8A////////////////////AAAAAAAAAAD//////////////////////wD///////////////////8AAAAAAAAAAP//////////////////////AP///////////////////wAAAAAAAAAA//////////////////////8A////////////////////AAAAAAAAAAD//////////////////////wD///////////////////8AAAAAAAAAAP//////////////////////AP///////////////////wAAAAAAAAAA//////////////////////8A////////////////////AAAAAAAAAAD//////////////////////wD///////////////////8AAAAAAAAAAP//////////////////////AP////////////8AAAAAAAAAAAAAAAAAAAAAAAD///////////////8A/////////////wAAAAAAAAAAAAAAAAAAAAAAAP///////////////wD/////////////AAAAAAAAAAAAAAAAAAAAAAAA////////////////AP////////////8AAAAAAAAAAAAAAAAAAAAAAAD///////////////8A/////////////wAAAAAAAAAAAAAAAAAAAAAAAP///////////////wD/////////////AAAAAAAAAAAAAAAAAAAAAAAA////////////////AP////////////8AAAAAAAAAAAAAAAAAAAAAAAD///////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8=','width' => 40),
-      'J' => array('data' => 'AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP///////////////////////////wAAAAAAAAAA//////////////8A////////////////////////////AAAAAAAAAAD//////////////wD///////////////////////////8AAAAAAAAAAP//////////////AP///////////////////////////wAAAAAAAAAA//////////////8A////////////////////////////AAAAAAAAAAD//////////////wD///////////////////////////8AAAAAAAAAAP//////////////AP///////////////////////////wAAAAAAAAAA//////////////8A////////////////////////////AAAAAAAAAAD//////////////wD///////////////////////////8AAAAAAAAAAP//////////////AP///////////////////////////wAAAAAAAAAA//////////////8A////////////////////////////AAAAAAAAAAD//////////////wD///////////////////////////8AAAAAAAAAAP//////////////AP///////////////////////////wAAAAAAAAAA//////////////8A////////////////////////////AAAAAAAAAAD//////////////wD///////////////////////////8AAAAAAAAAAP//////////////AP///////////////////////////wAAAAAAAAAA//////////////8A////////////////////////////AAAAAAAAAAj//////////////wD//////////+zMrIxwUDAQ//////wAAAAAAAAAIP//////////////AP//////////DAAAAAAAAADo////2AAAAAAAAAA0//////////////8A//////////8wAAAAAAAAAKj///+YAAAAAAAAAFj//////////////wD//////////2gAAAAAAAAAIND/yBgAAAAAAAAAkP//////////////AP//////////vAAAAAAAAAAAAAAAAAAAAAAAAADc//////////////8A////////////MAAAAAAAAAAAAAAAAAAAAAAAUP///////////////wD////////////EBAAAAAAAAAAAAAAAAAAAABjk////////////////AP////////////+sBAAAAAAAAAAAAAAAAAAY2P////////////////8A///////////////EMAAAAAAAAAAAAAAAVOj//////////////////wD/////////////////vHBAIAAAABg8fNT/////////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8=','width' => 40),
-      'K' => array('data' => 'AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD///////8AAAAAAAAAAP//////////wAQAAAAAAAAAAABw////////AP///////wAAAAAAAAAA/////////9AMAAAAAAAAAAAAcP////////8A////////AAAAAAAAAAD////////cGAAAAAAAAAAAAHD//////////wD///////8AAAAAAAAAAP//////6CgAAAAAAAAAAABs////////////AP///////wAAAAAAAAAA//////Q0AAAAAAAAAAAAVPz///////////8A////////AAAAAAAAAAD////8RAAAAAAAAAAAAFT8/////////////wD///////8AAAAAAAAAAP///1gAAAAAAAAAAABU/P//////////////AP///////wAAAAAAAAAA//9wAAAAAAAAAAAASPz///////////////8A////////AAAAAAAAAAD/jAAAAAAAAAAAADz0/////////////////wD///////8AAAAAAAAAAKQAAAAAAAAAAAA89P//////////////////AP///////wAAAAAAAAAABAAAAAAAAAAAFPT///////////////////8A////////AAAAAAAAAAAAAAAAAAAAAAAApP///////////////////wD///////8AAAAAAAAAAAAAAAAAAAAAAAAU8P//////////////////AP///////wAAAAAAAAAAAAAAAAAAAAAAAABk//////////////////8A////////AAAAAAAAAAAAAAAAAAAAAAAAAADE/////////////////wD///////8AAAAAAAAAAAAAAAAoEAAAAAAAACz8////////////////AP///////wAAAAAAAAAAAAAAGNiAAAAAAAAAAIj///////////////8A////////AAAAAAAAAAAAABjY//gYAAAAAAAACOD//////////////wD///////8AAAAAAAAAAAAY2P///5wAAAAAAAAASP//////////////AP///////wAAAAAAAAAAGNj//////CgAAAAAAAAAqP////////////8A////////AAAAAAAAAADI////////sAAAAAAAAAAc8P///////////wD///////8AAAAAAAAAAP//////////QAAAAAAAAABs////////////AP///////wAAAAAAAAAA///////////IAAAAAAAAAATI//////////8A////////AAAAAAAAAAD///////////9YAAAAAAAAADD8/////////wD///////8AAAAAAAAAAP///////////9wEAAAAAAAAAJD/////////AP///////wAAAAAAAAAA/////////////3AAAAAAAAAADOT///////8A////////AAAAAAAAAAD/////////////7BAAAAAAAAAAUP///////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8=','width' => 40), 
-      'L' => array('data' => 'AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////8AAAAAAAAAAP////////////////////////////8A/////////////wAAAAAAAAAA/////////////////////////////wD/////////////AAAAAAAAAAD/////////////////////////////AP////////////8AAAAAAAAAAP////////////////////////////8A/////////////wAAAAAAAAAA/////////////////////////////wD/////////////AAAAAAAAAAD/////////////////////////////AP////////////8AAAAAAAAAAP////////////////////////////8A/////////////wAAAAAAAAAA/////////////////////////////wD/////////////AAAAAAAAAAD/////////////////////////////AP////////////8AAAAAAAAAAP////////////////////////////8A/////////////wAAAAAAAAAA/////////////////////////////wD/////////////AAAAAAAAAAD/////////////////////////////AP////////////8AAAAAAAAAAP////////////////////////////8A/////////////wAAAAAAAAAA/////////////////////////////wD/////////////AAAAAAAAAAD/////////////////////////////AP////////////8AAAAAAAAAAP////////////////////////////8A/////////////wAAAAAAAAAA/////////////////////////////wD/////////////AAAAAAAAAAD/////////////////////////////AP////////////8AAAAAAAAAAP////////////////////////////8A/////////////wAAAAAAAAAA/////////////////////////////wD/////////////AAAAAAAAAAAAAAAAAAAAAAAAAAD/////////////AP////////////8AAAAAAAAAAAAAAAAAAAAAAAAAAP////////////8A/////////////wAAAAAAAAAAAAAAAAAAAAAAAAAA/////////////wD/////////////AAAAAAAAAAAAAAAAAAAAAAAAAAD/////////////AP////////////8AAAAAAAAAAAAAAAAAAAAAAAAAAP////////////8A/////////////wAAAAAAAAAAAAAAAAAAAAAAAAAA/////////////wD/////////////AAAAAAAAAAAAAAAAAAAAAAAAAAD/////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8=','width' => 40), 
-      'M' => array('data' => 'AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A//////8AAAAAAAAAAAAAAHz//////3wAAAAAAAAAAAAAAP///////wD//////wAAAAAAAAAAAAAATP//////UAAAAAAAAAAAAAAA////////AP//////AAAAAAAAAAAAAAAc//////8cAAAAAAAAAAAAAAD///////8A//////8AAAAAAAAAAAAAAADw////8AAAAAAAAAAAAAAAAP///////wD//////wAAAAAAAAAAAAAAALz////AAAAAAAAAAAAAAAAA////////AP//////AAAAAAAAAAAAAAAAkP///5AAAAAAAAAAAAAAAAD///////8A//////8AAAAAAAAAAAAAAABc////ZAAAAAAAAAAAAAAAAP///////wD//////wAAAAAAAAAoAAAAADD///8wAAAAACQAAAAAAAAA////////AP//////AAAAAAAAAFwAAAAABPz//AgAAAAAXAAAAAAAAAD///////8A//////8AAAAAAAAAkAAAAAAA0P/UAAAAAACQAAAAAAAAAP///////wD//////wAAAAAAAADMAAAAAACg/6gAAAAAAMQAAAAAAAAA////////AP//////AAAAAAAAAPgEAAAAAHD/dAAAAAAE+AAAAAAAAAD///////8A//////8AAAAAAAAA/zQAAAAAQP9IAAAAADD/AAAAAAAAAP///////wD//////wAAAAAAAAD/bAAAAAAQ/xQAAAAAaP8AAAAAAAAA////////AP//////AAAAAAAAAP+gAAAAAADQAAAAAACc/wAAAAAAAAD///////8A//////8AAAAAAAAA/9QAAAAAAGgAAAAAAND/AAAAAAAAAP///////wD//////wAAAAAAAAD//wwAAAAAFAAAAAAM/P8AAAAAAAAA////////AP//////AAAAAAAAAP//RAAAAAAAAAAAADz//wAAAAAAAAD///////8A//////8AAAAAAAAA//94AAAAAAAAAAAAcP//AAAAAAAAAP///////wD//////wAAAAAAAAD//7AAAAAAAAAAAACo//8AAAAAAAAA////////AP//////AAAAAAAAAP//5AAAAAAAAAAAANz//wAAAAAAAAD///////8A//////8AAAAAAAAA////HAAAAAAAAAAQ////AAAAAAAAAP///////wD//////wAAAAAAAAD///9QAAAAAAAAAEz///8AAAAAAAAA////////AP//////AAAAAAAAAP///4gAAAAAAAAAfP///wAAAAAAAAD///////8A//////8AAAAAAAAA////vAAAAAAAAACw////AAAAAAAAAP///////wD//////wAAAAAAAAD////wAAAAAAAAAOz///8AAAAAAAAA////////AP//////AAAAAAAAAP////8sAAAAAAAc/////wAAAAAAAAD///////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8=','width' => 40), 
-      'N' => array('data' => 'AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////AAAAAAAAALD/////////////AAAAAAAAAP//////////AP////////8AAAAAAAAAFOj///////////8AAAAAAAAA//////////8A/////////wAAAAAAAAAASP///////////wAAAAAAAAD//////////wD/////////AAAAAAAAAAAAkP//////////AAAAAAAAAP//////////AP////////8AAAAAAAAAAAAI1P////////8AAAAAAAAA//////////8A/////////wAAAAAAAAAAAAAw+P///////wAAAAAAAAD//////////wD/////////AAAAAAAAAAAAAABw////////AAAAAAAAAP//////////AP////////8AAAAAAAAAAAAAAAC8//////8AAAAAAAAA//////////8A/////////wAAAAAAAAAAAAAAABzs/////wAAAAAAAAD//////////wD/////////AAAAAAAAAAAAAAAAAFD/////AAAAAAAAAP//////////AP////////8AAAAAAAAAAAAAAAAAAJz///8AAAAAAAAA//////////8A/////////wAAAAAAAAAUAAAAAAAADNz//wAAAAAAAAD//////////wD/////////AAAAAAAAALQAAAAAAAAANPz/AAAAAAAAAP//////////AP////////8AAAAAAAAA/2wAAAAAAAAAfP8AAAAAAAAA//////////8A/////////wAAAAAAAAD/+CwAAAAAAAAExAAAAAAAAAD//////////wD/////////AAAAAAAAAP//0AQAAAAAAAAgAAAAAAAAAP//////////AP////////8AAAAAAAAA////jAAAAAAAAAAAAAAAAAAA//////////8A/////////wAAAAAAAAD/////RAAAAAAAAAAAAAAAAAD//////////wD/////////AAAAAAAAAP/////kFAAAAAAAAAAAAAAAAP//////////AP////////8AAAAAAAAA//////+sAAAAAAAAAAAAAAAA//////////8A/////////wAAAAAAAAD///////9kAAAAAAAAAAAAAAD//////////wD/////////AAAAAAAAAP////////QkAAAAAAAAAAAAAP//////////AP////////8AAAAAAAAA/////////8wEAAAAAAAAAAAA//////////8A/////////wAAAAAAAAD//////////4QAAAAAAAAAAAD//////////wD/////////AAAAAAAAAP///////////DwAAAAAAAAAAP//////////AP////////8AAAAAAAAA////////////4BAAAAAAAAAA//////////8A/////////wAAAAAAAAD/////////////qAAAAAAAAAD//////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8=','width' => 40), 
-      'O' => array('data' => 'AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A///////////////////0qGw4HAAAABw4aKT0/////////////////wD////////////////wcAwAAAAAAAAAAAAAAAho6P//////////////AP//////////////uBQAAAAAAAAAAAAAAAAAAAAMoP////////////8A/////////////6AEAAAAAAAAAAAAAAAAAAAAAAAAkP///////////wD///////////+4BAAAAAAAAAAAAAAAAAAAAAAAAAAAoP//////////AP//////////8BQAAAAAAAAAAAAAAAAAAAAAAAAAAAAM5P////////8A//////////9wAAAAAAAAAAAsrPD/7KQsAAAAAAAAAABg/////////wD/////////+BAAAAAAAAAAUPj///////hQAAAAAAAAAAjs////////AP////////+sAAAAAAAAABDw//////////AYAAAAAAAAAKD///////8A/////////2wAAAAAAAAAdP///////////3wAAAAAAAAAYP///////wD/////////OAAAAAAAAAC4////////////xAAAAAAAAAAw////////AP////////8cAAAAAAAAAOD////////////oAAAAAAAAABT///////8A/////////wAAAAAAAAAA//////////////8AAAAAAAAAAP///////wD/////////AAAAAAAAAAD//////////////wAAAAAAAAAA////////AP////////8AAAAAAAAAAP/////////////8AAAAAAAAAAD///////8A/////////xwAAAAAAAAA5P///////////+AAAAAAAAAAHP///////wD/////////NAAAAAAAAAC8////////////uAAAAAAAAAA4////////AP////////9oAAAAAAAAAHj///////////98AAAAAAAAAGT///////8A/////////6gAAAAAAAAAGPD/////////+BgAAAAAAAAApP///////wD/////////9AwAAAAAAAAAUPz///////xcAAAAAAAAAAjs////////AP//////////cAAAAAAAAAAALKjs//CwOAAAAAAAAAAAYP////////8A///////////wFAAAAAAAAAAAAAAAAAAAAAAAAAAAAAzk/////////wD///////////+4BAAAAAAAAAAAAAAAAAAAAAAAAAAAoP//////////AP////////////+QAAAAAAAAAAAAAAAAAAAAAAAAAJD///////////8A//////////////+sEAAAAAAAAAAAAAAAAAAAAAyg/////////////wD////////////////oZAgAAAAAAAAAAAAAAARg4P//////////////AP//////////////////9KhsOCAAAAAUMFyc7P////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8=','width' => 40), 
-      'P' => array('data' => 'AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP///////////wAAAAAAAAAAAAAAAAAACCxguP////////////////8A////////////AAAAAAAAAAAAAAAAAAAAAAAAOOD//////////////wD///////////8AAAAAAAAAAAAAAAAAAAAAAAAAGOD/////////////AP///////////wAAAAAAAAAAAAAAAAAAAAAAAAAARP////////////8A////////////AAAAAAAAAAAAAAAAAAAAAAAAAAAAxP///////////wD///////////8AAAAAAAAAAAAAAAAAAAAAAAAAAABo////////////AP///////////wAAAAAAAAAA////6JwMAAAAAAAAADD///////////8A////////////AAAAAAAAAAD//////6AAAAAAAAAADP///////////wD///////////8AAAAAAAAAAP//////9AAAAAAAAAAA////////////AP///////////wAAAAAAAAAA///////0AAAAAAAAAAD///////////8A////////////AAAAAAAAAAD//////5gAAAAAAAAAHP///////////wD///////////8AAAAAAAAAAP///9iICAAAAAAAAABI////////////AP///////////wAAAAAAAAAAAAAAAAAAAAAAAAAAAJD///////////8A////////////AAAAAAAAAAAAAAAAAAAAAAAAAAAI6P///////////wD///////////8AAAAAAAAAAAAAAAAAAAAAAAAAAIT/////////////AP///////////wAAAAAAAAAAAAAAAAAAAAAAAABU/P////////////8A////////////AAAAAAAAAAAAAAAAAAAAAAAIhPz//////////////wD///////////8AAAAAAAAAAAAAAAAABCRMkOz/////////////////AP///////////wAAAAAAAAAA//////////////////////////////8A////////////AAAAAAAAAAD//////////////////////////////wD///////////8AAAAAAAAAAP//////////////////////////////AP///////////wAAAAAAAAAA//////////////////////////////8A////////////AAAAAAAAAAD//////////////////////////////wD///////////8AAAAAAAAAAP//////////////////////////////AP///////////wAAAAAAAAAA//////////////////////////////8A////////////AAAAAAAAAAD//////////////////////////////wD///////////8AAAAAAAAAAP//////////////////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8=','width' => 40), 
-      'Q' => array('data' => 'AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////SoaDQcAAAAHDhoqPT///////////////////8A//////////////BwDAAAAAAAAAAAAAAACHDo/////////////////wD///////////+4FAAAAAAAAAAAAAAAAAAAABCo////////////////AP//////////nAQAAAAAAAAAAAAAAAAAAAAAAACQ//////////////8A/////////7gEAAAAAAAAAAAAAAAAAAAAAAAAAACg/////////////wD////////wFAAAAAAAAAAAAAAAAAAAAAAAAAAAAAzo////////////AP///////3AAAAAAAAAAACyo8P/sqCwAAAAAAAAAAGT///////////8A///////4EAAAAAAAAABM+P///////FQAAAAAAAAACPT//////////wD//////7AAAAAAAAAAFPD/////////9BgAAAAAAAAApP//////////AP//////bAAAAAAAAAB4////////////fAAAAAAAAABk//////////8A//////84AAAAAAAAALz///////////+8AAAAAAAAADT//////////wD//////xwAAAAAAAAA6P///////////+QAAAAAAAAAHP//////////AP//////AAAAAAAAAAD//////////////wAAAAAAAAAA//////////8A//////8AAAAAAAAAAP//////////////AAAAAAAAAAD//////////wD//////wAAAAAAAAAA/P////////////8AAAAAAAAAAP//////////AP//////GAAAAAAAAADg////////////4AAAAAAAAAAc//////////8A//////84AAAAAAAAALT////MJHTo//+8AAAAAAAAADT//////////wD//////2wAAAAAAAAAdP///2AAABCg/3wAAAAAAAAAZP//////////AP//////rAAAAAAAAAAY9P/sCAAAAABMGAAAAAAAAACk//////////8A///////4EAAAAAAAAABU/P+0OAAAAAAAAAAAAAAACPT//////////wD///////94AAAAAAAAAAA4sPD/gAAAAAAAAAAAAABk////////////AP////////AcAAAAAAAAAAAAAAAAAAAAAAAAAAAADOT///////////8A/////////7wEAAAAAAAAAAAAAAAAAAAAAAAAAACQ/////////////wD//////////6wEAAAAAAAAAAAAAAAAAAAAAAAAABSs////////////AP///////////7gUAAAAAAAAAAAAAAAAAAAAAAAAAABAwP////////8A//////////////BwDAAAAAAAAAAAAAAABAgAAAAAAAA8/////////wD////////////////0qGg0GAAAABgwXJjkxBgAAAAAALD/////////AP//////////////////////////////////5DQAAAAk/P////////8A////////////////////////////////////+GwAAJD//////////wD//////////////////////////////////////8A49P//////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8=','width' => 40), 
-      'R' => array('data' => 'AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A/////////wAAAAAAAAAAAAAAAAAAAAQgOGSk+P///////////////wD/////////AAAAAAAAAAAAAAAAAAAAAAAAAAAcuP//////////////AP////////8AAAAAAAAAAAAAAAAAAAAAAAAAAAAEsP////////////8A/////////wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQ6P///////////wD/////////AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB8////////////AP////////8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAADD///////////8A/////////wAAAAAAAAAA///////svDgAAAAAAAAACP///////////wD/////////AAAAAAAAAAD/////////7AAAAAAAAAAA////////////AP////////8AAAAAAAAAAP/////////cAAAAAAAAABD///////////8A/////////wAAAAAAAAAA//////DQoCQAAAAAAAAAQP///////////wD/////////AAAAAAAAAAAAAAAAAAAAAAAAAAAAAACU////////////AP////////8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAIPj///////////8A/////////wAAAAAAAAAAAAAAAAAAAAAAAAAAAAzU/////////////wD/////////AAAAAAAAAAAAAAAAAAAAAAAAAAA02P//////////////AP////////8AAAAAAAAAAAAAAAAAAAAAAAxctPz///////////////8A/////////wAAAAAAAAAAAAAAAAAAAAAAAEDY/////////////////wD/////////AAAAAAAAAAD/9LAsAAAAAAAAAAzc////////////////AP////////8AAAAAAAAAAP///+wkAAAAAAAAADD8//////////////8A/////////wAAAAAAAAAA/////8QAAAAAAAAAAJD//////////////wD/////////AAAAAAAAAAD//////1QAAAAAAAAAFPD/////////////AP////////8AAAAAAAAAAP//////3AQAAAAAAAAAgP////////////8A/////////wAAAAAAAAAA////////aAAAAAAAAAAM6P///////////wD/////////AAAAAAAAAAD////////oCAAAAAAAAABs////////////AP////////8AAAAAAAAAAP////////+AAAAAAAAAAATc//////////8A/////////wAAAAAAAAAA//////////AUAAAAAAAAAFj//////////wD/////////AAAAAAAAAAD//////////5AAAAAAAAAAAND/////////AP////////8AAAAAAAAAAP//////////+CQAAAAAAAAAQP////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8=','width' => 40), 
-      'S' => array('data' => 'AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP/////////////////8vHBEIAgAAAQgQHC8/P////////////////8A////////////////pCQAAAAAAAAAAAAAAAAcoP///////////////wD//////////////FwAAAAAAAAAAAAAAAAAAAAAXP//////////////AP////////////9oAAAAAAAAAAAAAAAAAAAAAAAAhP////////////8A////////////zAAAAAAAAAAAAAAAAAAAAAAAAAAI6P///////////wD///////////9cAAAAAAAAAAAAAAAAAAAAAAAAAACA////////////AP///////////xgAAAAAAAAAUOD/8KwkAAAAAAAAADj///////////8A////////////AAAAAAAAAAD0/////8wABCAgICxASP///////////wD///////////8MAAAAAAAAAMz/////////////////////////////AP///////////0AAAAAAAAAACFiQxPT///////////////////////8A////////////oAAAAAAAAAAAAAAAADBwtPT//////////////////wD////////////8QAAAAAAAAAAAAAAAAAAACFTA////////////////AP/////////////oOAAAAAAAAAAAAAAAAAAAAABM6P////////////8A///////////////4fAgAAAAAAAAAAAAAAAAAAAAY2P///////////wD/////////////////7IwwAAAAAAAAAAAAAAAAAAAo+P//////////AP/////////////////////koGw0BAAAAAAAAAAAAACU//////////8A///////////////////////////4uFgAAAAAAAAAADz//////////wD//////////2BgSEA0IBwA6P///////5QAAAAAAAAADP//////////AP//////////JAAAAAAAAACc/////////AAAAAAAAAAA//////////8A//////////9YAAAAAAAAACDo///////AAAAAAAAAABT//////////wD//////////6QAAAAAAAAAACCk7P/snBQAAAAAAAAAUP//////////AP//////////+BAAAAAAAAAAAAAAAAAAAAAAAAAAAACs//////////8A////////////kAAAAAAAAAAAAAAAAAAAAAAAAAAAOP///////////wD////////////8RAAAAAAAAAAAAAAAAAAAAAAAABjc////////////AP/////////////0PAAAAAAAAAAAAAAAAAAAAAAg2P////////////8A///////////////8hBQAAAAAAAAAAAAAAAAMdPT//////////////wD/////////////////+LRwSCAMAAAAHDhoqPT/////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8=','width' => 40), 
-      'T' => array('data' => 'AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA////////////AP////////8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD///////////8A/////////wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP///////////wD/////////AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA////////////AP////////8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD///////////8A/////////wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP///////////wD///////////////////8AAAAAAAAAAP//////////////////////AP///////////////////wAAAAAAAAAA//////////////////////8A////////////////////AAAAAAAAAAD//////////////////////wD///////////////////8AAAAAAAAAAP//////////////////////AP///////////////////wAAAAAAAAAA//////////////////////8A////////////////////AAAAAAAAAAD//////////////////////wD///////////////////8AAAAAAAAAAP//////////////////////AP///////////////////wAAAAAAAAAA//////////////////////8A////////////////////AAAAAAAAAAD//////////////////////wD///////////////////8AAAAAAAAAAP//////////////////////AP///////////////////wAAAAAAAAAA//////////////////////8A////////////////////AAAAAAAAAAD//////////////////////wD///////////////////8AAAAAAAAAAP//////////////////////AP///////////////////wAAAAAAAAAA//////////////////////8A////////////////////AAAAAAAAAAD//////////////////////wD///////////////////8AAAAAAAAAAP//////////////////////AP///////////////////wAAAAAAAAAA//////////////////////8A////////////////////AAAAAAAAAAD//////////////////////wD///////////////////8AAAAAAAAAAP//////////////////////AP///////////////////wAAAAAAAAAA//////////////////////8A////////////////////AAAAAAAAAAD//////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8=','width' => 40), 
-      'U' => array('data' => 'AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////8AAAAAAAAAAP///////////wAAAAAAAAAA//////////8A/////////wAAAAAAAAAA////////////AAAAAAAAAAD//////////wD/////////AAAAAAAAAAD///////////8AAAAAAAAAAP//////////AP////////8AAAAAAAAAAP///////////wAAAAAAAAAA//////////8A/////////wAAAAAAAAAA////////////AAAAAAAAAAD//////////wD/////////AAAAAAAAAAD///////////8AAAAAAAAAAP//////////AP////////8AAAAAAAAAAP///////////wAAAAAAAAAA//////////8A/////////wAAAAAAAAAA////////////AAAAAAAAAAD//////////wD/////////AAAAAAAAAAD///////////8AAAAAAAAAAP//////////AP////////8AAAAAAAAAAP///////////wAAAAAAAAAA//////////8A/////////wAAAAAAAAAA////////////AAAAAAAAAAD//////////wD/////////AAAAAAAAAAD///////////8AAAAAAAAAAP//////////AP////////8AAAAAAAAAAP///////////wAAAAAAAAAA//////////8A/////////wAAAAAAAAAA////////////AAAAAAAAAAD//////////wD/////////AAAAAAAAAAD///////////8AAAAAAAAAAP//////////AP////////8AAAAAAAAAAP///////////wAAAAAAAAAA//////////8A/////////wAAAAAAAAAA////////////AAAAAAAAAAD//////////wD/////////JAAAAAAAAADk/////////+gAAAAAAAAAHP//////////AP////////9MAAAAAAAAAJz/////////nAAAAAAAAABE//////////8A/////////4gAAAAAAAAAHOj//////+ggAAAAAAAAAHz//////////wD/////////0AAAAAAAAAAAIJzs/+ykIAAAAAAAAAAA0P//////////AP//////////QAAAAAAAAAAAAAAAAAAAAAAAAAAAAED///////////8A///////////IBAAAAAAAAAAAAAAAAAAAAAAAAAAE0P///////////wD///////////+YAAAAAAAAAAAAAAAAAAAAAAAAAJj/////////////AP////////////+UBAAAAAAAAAAAAAAAAAAAAASU//////////////8A///////////////IPAAAAAAAAAAAAAAAAAAwyP///////////////wD/////////////////0IxYOCAIAAAEIEiAyP//////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8=','width' => 40), 
-      'V' => array('data' => 'AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD//////zAAAAAAAAAAYP//////////////ZAAAAAAAAAAw////////AP//////kAAAAAAAAAAU/P////////////8UAAAAAAAAAJD///////8A///////oBAAAAAAAAADE////////////xAAAAAAAAAAE7P///////wD///////9MAAAAAAAAAHD///////////94AAAAAAAAAEz/////////AP///////6gAAAAAAAAAJP///////////yQAAAAAAAAArP////////8A////////+BAAAAAAAAAA1P/////////YAAAAAAAAABT4/////////wD/////////aAAAAAAAAACE/////////4QAAAAAAAAAbP//////////AP/////////EAAAAAAAAADT/////////OAAAAAAAAADM//////////8A//////////8kAAAAAAAAAOT//////+QAAAAAAAAAKP///////////wD//////////4QAAAAAAAAAmP//////nAAAAAAAAACI////////////AP//////////5AAAAAAAAABE//////9EAAAAAAAABOT///////////8A////////////QAAAAAAAAAT0////9AgAAAAAAABI/////////////wD///////////+gAAAAAAAAAKT///+kAAAAAAAAAKj/////////////AP////////////QIAAAAAAAAXP///1wAAAAAAAAM+P////////////8A/////////////1wAAAAAAAAM+P/8DAAAAAAAAGT//////////////wD/////////////vAAAAAAAAAC8/7wAAAAAAAAAxP//////////////AP//////////////HAAAAAAAAGj/aAAAAAAAACT///////////////8A//////////////94AAAAAAAAHP8cAAAAAAAAhP///////////////wD//////////////9gAAAAAAAAAkAAAAAAAAADk////////////////AP///////////////zgAAAAAAAAQAAAAAAAAQP////////////////8A////////////////lAAAAAAAAAAAAAAAAACg/////////////////wD////////////////sCAAAAAAAAAAAAAAADPT/////////////////AP////////////////9QAAAAAAAAAAAAAABg//////////////////8A/////////////////7AAAAAAAAAAAAAAAMD//////////////////wD//////////////////BQAAAAAAAAAAAAc////////////////////AP//////////////////cAAAAAAAAAAAAHz///////////////////8A///////////////////MAAAAAAAAAAAA3P///////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8=','width' => 40), 
-      'W' => array('data' => 'AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A//8cAAAAAAAAALz/////4AAAAAAAAAAA6P////+8AAAAAAAAABz//wD//1QAAAAAAAAAjP////+gAAAAAAAAAACo/////4wAAAAAAAAAUP//AP//jAAAAAAAAABU/////2AAAAAAAAAAAGj/////VAAAAAAAAACM//8A///EAAAAAAAAACT/////IAAAAAAAAAAAKP////8kAAAAAAAAAMT//wD///gEAAAAAAAAAPD//+AAAAAAAAAAAAAA6P//8AAAAAAAAAAE9P//AP///zAAAAAAAAAAvP//oAAAAAAAAAAAAACo//+8AAAAAAAAADD///8A////bAAAAAAAAACM//9gAAAAAAAAAAAAAGT//4wAAAAAAAAAaP///wD///+kAAAAAAAAAFT//yAAAAAAAAAAAAAAIP//VAAAAAAAAACc////AP///9gAAAAAAAAAJP/gAAAAAAAAAAAAAAAA4P8kAAAAAAAAANT///8A/////xAAAAAAAAAA8KAAAAAAAAAAAAAAAACg8AAAAAAAAAAQ/////wD/////TAAAAAAAAAC8YAAAAAAAAAAAAAAAAGC8AAAAAAAAAET/////AP////+AAAAAAAAAAIwgAAAAAAAAAAAAAAAAIIwAAAAAAAAAfP////8A/////7gAAAAAAAAANAAAAAAAACwwAAAAAAAANAAAAAAAAACw/////wD/////8AAAAAAAAAAAAAAAAAAAdHgAAAAAAAAAAAAAAAAAAOz/////AP//////KAAAAAAAAAAAAAAAAAC4vAAAAAAAAAAAAAAAAAAg//////8A//////9gAAAAAAAAAAAAAAAACPj4CAAAAAAAAAAAAAAAAFj//////wD//////5QAAAAAAAAAAAAAAABE//9IAAAAAAAAAAAAAAAAkP//////AP//////0AAAAAAAAAAAAAAAAIj//4wAAAAAAAAAAAAAAADI//////8A///////8DAAAAAAAAAAAAAAAzP//1AAAAAAAAAAAAAAABPj//////wD///////88AAAAAAAAAAAAABT/////GAAAAAAAAAAAAAA0////////AP///////3QAAAAAAAAAAAAAWP////9gAAAAAAAAAAAAAHD///////8A////////sAAAAAAAAAAAAACg/////6QAAAAAAAAAAAAApP///////wD////////kAAAAAAAAAAAAAOT/////6AAAAAAAAAAAAADc////////AP////////8cAAAAAAAAAAAo////////MAAAAAAAAAAAEP////////8A/////////1QAAAAAAAAAAHD///////94AAAAAAAAAABM/////////wD/////////jAAAAAAAAAAAtP///////7wAAAAAAAAAAID/////////AP/////////EAAAAAAAAAAT0////////+AgAAAAAAAAAuP////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8=','width' => 40), 
-      'X' => array('data' => 'AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD///////9UAAAAAAAAAKz///////////+sAAAAAAAAAFD/////////AP///////+QQAAAAAAAAFOT/////////8BwAAAAAAAAM5P////////8A/////////5gAAAAAAAAATP////////9kAAAAAAAAAJD//////////wD//////////0AAAAAAAAAAoP//////wAAAAAAAAAA0/P//////////AP//////////2AgAAAAAAAAQ4P////gkAAAAAAAABMz///////////8A////////////iAAAAAAAAABA////dAAAAAAAAABw/////////////wD////////////8MAAAAAAAAACU/9AEAAAAAAAAHPD/////////////AP/////////////IBAAAAAAAAAzYMAAAAAAAAACs//////////////8A//////////////90AAAAAAAAABAAAAAAAAAATP///////////////wD///////////////QgAAAAAAAAAAAAAAAAAAzg////////////////AP///////////////7wAAAAAAAAAAAAAAAAAjP////////////////8A/////////////////2AAAAAAAAAAAAAAADD8/////////////////wD/////////////////7BQAAAAAAAAAAAAEyP//////////////////AP/////////////////gDAAAAAAAAAAAAAjY//////////////////8A/////////////////0AAAAAAAAAAAAAAADj8/////////////////wD///////////////+UAAAAAAAAAAAAAAAAAJD/////////////////AP//////////////4AwAAAAAAAAAAAAAAAAADOD///////////////8A//////////////9AAAAAAAAAAAAAAAAAAAAAQP///////////////wD/////////////nAAAAAAAAAAAWAAAAAAAAAAAlP//////////////AP///////////+QQAAAAAAAAAGD/YAAAAAAAAAAM4P////////////8A////////////TAAAAAAAAAAs9P/0LAAAAAAAAABM/////////////wD//////////6AAAAAAAAAADNT////UDAAAAAAAAACg////////////AP/////////kEAAAAAAAAACg//////+gAAAAAAAAABDk//////////8A/////////0wAAAAAAAAAYP////////9gAAAAAAAAAEz//////////wD///////+oAAAAAAAAACz0//////////QsAAAAAAAAAKT/////////AP//////7BQAAAAAAAAM1P///////////9QMAAAAAAAAFOz///////8A//////9UAAAAAAAAAKD//////////////6AAAAAAAAAAVP///////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8=','width' => 40), 
-      'Y' => array('data' => 'AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP///////1QAAAAAAAAAAGj//////////2gAAAAAAAAAAFT///////8A////////5BAAAAAAAAAAAMT////////EAAAAAAAAAAAQ5P///////wD/////////mAAAAAAAAAAAKPj/////+CgAAAAAAAAAAJj/////////AP//////////PAAAAAAAAAAAgP////+AAAAAAAAAAAA8//////////8A///////////YCAAAAAAAAAAE2P//2AQAAAAAAAAACNj//////////wD///////////+AAAAAAAAAAAA4//84AAAAAAAAAACA////////////AP////////////woAAAAAAAAAACUlAAAAAAAAAAAKPz///////////8A/////////////8gAAAAAAAAAABAQAAAAAAAAAADI/////////////wD//////////////2wAAAAAAAAAAAAAAAAAAAAAbP//////////////AP//////////////8BwAAAAAAAAAAAAAAAAAABzw//////////////8A////////////////tAAAAAAAAAAAAAAAAAAAtP///////////////wD/////////////////VAAAAAAAAAAAAAAAAFT/////////////////AP/////////////////oEAAAAAAAAAAAAAAQ6P////////////////8A//////////////////+cAAAAAAAAAAAAAJz//////////////////wD///////////////////9AAAAAAAAAAABA////////////////////AP///////////////////9gAAAAAAAAAANj///////////////////8A/////////////////////wAAAAAAAAAA/////////////////////wD/////////////////////AAAAAAAAAAD/////////////////////AP////////////////////8AAAAAAAAAAP////////////////////8A/////////////////////wAAAAAAAAAA/////////////////////wD/////////////////////AAAAAAAAAAD/////////////////////AP////////////////////8AAAAAAAAAAP////////////////////8A/////////////////////wAAAAAAAAAA/////////////////////wD/////////////////////AAAAAAAAAAD/////////////////////AP////////////////////8AAAAAAAAAAP////////////////////8A/////////////////////wAAAAAAAAAA/////////////////////wD/////////////////////AAAAAAAAAAD/////////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8=','width' => 40), 
-      'Z' => array('data' => 'AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A//////////8AAAAAAAAAAAAAAAAAAAAAAAAAAAD//////////////wD//////////wAAAAAAAAAAAAAAAAAAAAAAAAAAAP//////////////AP//////////AAAAAAAAAAAAAAAAAAAAAAAAAAAA//////////////8A//////////8AAAAAAAAAAAAAAAAAAAAAAAAAAAD//////////////wD//////////wAAAAAAAAAAAAAAAAAAAAAAAAAAAP//////////////AP//////////AAAAAAAAAAAAAAAAAAAAAAAAAAAQ//////////////8A/////////////////////////1AAAAAAAAAABLz//////////////wD///////////////////////98AAAAAAAAAACY////////////////AP//////////////////////pAAAAAAAAAAAaP////////////////8A/////////////////////8QIAAAAAAAAAET8/////////////////wD////////////////////gGAAAAAAAAAAo9P//////////////////AP//////////////////9CwAAAAAAAAAFNz///////////////////8A//////////////////xMAAAAAAAAAATA/////////////////////wD/////////////////eAAAAAAAAAAAnP//////////////////////AP///////////////5wAAAAAAAAAAHT///////////////////////8A///////////////ABAAAAAAAAABM/P///////////////////////wD/////////////3BQAAAAAAAAALPT/////////////////////////AP////////////QoAAAAAAAAABjg//////////////////////////8A///////////8SAAAAAAAAAAExP///////////////////////////wD//////////2wAAAAAAAAAAKD/////////////////////////////AP////////+YAAAAAAAAAAB8//////////////////////////////8A/////////wQAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/////////////wD/////////AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD/////////////AP////////8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////////////8A/////////wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/////////////wD/////////AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD/////////////AP////////8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8=','width' => 40), 
-    );
-  
-    return $_png;
+    throw new Exception("Expected but couldn't find class for captcha engine: captcha_engine_$engine");
   }
-  
-  // These define base64_encoded raw png image data used
-  // when we cannot generate our own single png image
-  function define_raw_pngs()
-  {
-    $_png = array(
-      '0' => 'iVBORw0KGgoAAAANSUhEUgAAACgAAAAoCAAAAACpleexAAAAFXRFWHRDcmVhdGlvbiBUaW1lAAfTBQ4QKCNGXKO6AAAAB3RJTUUH0wUOEDQ6EUG1VwAAAAlwSFlzAAALEgAACxIB0t1+/AAAAXNJREFUeNpj/M9AHGAiUt2wVvhyaqAqKyOjpG3jQwaGv+e+IUn9RwJfSjjg4iwFP1aKJD6HyyErfGGAYrquIoP5E2wK/zigu0v5wH9sChdgeKDqP1aFGhBZmxv/z0Dd4IxV4RWIpMQHIPuJAITzAqEQETx7IFQIP5CQNoJwDmALxzMQCuyjg1chnBPYwtECwr8AZN41h0p6YHOjAkTuwf//77wYuCEcFWwKOWA2fM1iZuuHcASwKYQ55c9ENuasrxgRjKlwJS+D17v/hBUeUGYwv/sfn0IRiJQZJIbxuFEFagjvSlDUQNgK2GIGqpC1JRhIfoAqxBYz0DRhn8IMJO+giKEqhMaMJBeI3AHhIKdkRPqG8DlAifqFADyasKRHO6h1Z/6fMYEwTbCmx3cWGCl8CTaFwBhGz+M2/7EpXMvOnBmIok7jBVaFz/Mi3/1pQORrhpgPyOr+M8IL0j9/gKpeLjhy5QEwoDVsYuRR3cE4IktcAJNx8cJaZBeQAAAAAElFTkSuQmCC', 
-      '1' => 'iVBORw0KGgoAAAANSUhEUgAAACgAAAAoCAAAAACpleexAAAAFXRFWHRDcmVhdGlvbiBUaW1lAAfTBQ4QMi//xxVKAAAAB3RJTUUH0wUOEDYLcqnX7wAAAAlwSFlzAAALEgAACxIB0t1+/AAAAHpJREFUeNpj/M9AHGAiUh1WhR8FGUGAsMKaD9iM/I8BlmCVwVS4hoUohT8qcNiFyv2zQIWBCIV3amRwu54RKcDRAgQ1KigIcJYK7CqR3QsCFmf+Y8qgeQakbANMAz6FKjUXECbj8zWa76nm61GFw1UhI10KqVGFNFQIADdK9Zj7PsV9AAAAAElFTkSuQmCC', 
-      '2' => 'iVBORw0KGgoAAAANSUhEUgAAACgAAAAoCAAAAACpleexAAAAFXRFWHRDcmVhdGlvbiBUaW1lAAfTBQ4QMwPUBEjoAAAAB3RJTUUH0wUOEDUqFe2UcgAAAAlwSFlzAAALEgAACxIB0t1+/AAAAQxJREFUeNpj/M9AHGAiUt2owkGrkAWF93LFgStPfjCwyGiYRGijqfyPAH9aOJAkQl78RwbICkNQjdB4gUNhD7qzLLAr/CKA4YENSAoRvl7zAUJXvPmxhgfCXILVMxEQvg+IDVUhgtVqDYjkDhD7B2aQIMIx5cOTN29evLAAsaEKObBajQzmQOQMcIQjHLwQgSisIaDwBdS5LHfwK7yhAHVVyX+8CrdAA5HB5gdehQ3Yoxpd4ZcAmDqbD//xKISEIjhU//zHoxDmXQaeFRhOZ8CmzuDOf3wKf8DsDfnyH6/CHJi6P//xKjyDJethVehBpMI7DPgVwrPCCgb8AK5wDwGFcNMF8EkCASOx1QcAGUxu1untnFIAAAAASUVORK5CYII=', 
-      '3' => 'iVBORw0KGgoAAAANSUhEUgAAACgAAAAoCAAAAACpleexAAAAFXRFWHRDcmVhdGlvbiBUaW1lAAfTBQ4QMxBQugk2AAAAB3RJTUUH0wUOEDU3duv4qwAAAAlwSFlzAAALEgAACxIB0t1+/AAAATdJREFUeNpj/M9AHGAiUt0IVciCzPm7ZceZB28YGBQkLHwcmNFU/keANRJI4ioH/qMAJIUlaHatwaFwBrqrOO5gVfiCB8P9KVgVVkAtnPDh/wkLCFsGq0IFiGQLiH0D06P/GWHJ7O+NOzfuXLlzQRrEhgSawHscwYPurxAcwQMBf/4/aIAYyHIGr8IEeDhO+Y9XoQNUncwOVHGMRPEDSovc+IkzrpGDCQgUbuC1WgBhhsIHfAp3vPn/oIIFKfRxKQSDGohCA4IKX0DTD7YoRAWMUJ9iyQpbn4DBBWUQ5yFEDDnFw622gXAzwBxoYvfB5sYlUI0lD/4/gWWKJdgU/tHAcKjCD6y+PsGCpo4FJbaRgmcNqkqWCThTzxkTJHXo+Ro1HA9uOPHiATDlKJj4eKCVFIzDqWgGAK7GW/haPS+zAAAAAElFTkSuQmCC', 
-      '4' => 'iVBORw0KGgoAAAANSUhEUgAAACgAAAAoCAAAAACpleexAAAAFXRFWHRDcmVhdGlvbiBUaW1lAAfTBQ4QMyqWttCEAAAAB3RJTUUH0wUOEDUxn4hdngAAAAlwSFlzAAALEgAACxIB0t1+/AAAAKBJREFUeNpj/M9AHGAiUh2FCucyQgCK4H9McIAFixwWhQ8kGIhS+MWAgTiFIQzEKWxhIE7hFgbiFF7hASkQIajwjQpInuUAIYV/XMDyU/4TUlgAlk75T0jhArCszR9CCk+AY07mxX8CCp+AY47nzH8CCn+YgOWW/CekMAYsVfMfl0JGmCBq4kNEDp2zAn0UMmItABjRvDykPTO43DgyFQIANP6pTFLWAdoAAAAASUVORK5CYII=', 
-      '5' => 'iVBORw0KGgoAAAANSUhEUgAAACgAAAAoCAAAAACpleexAAAAFXRFWHRDcmVhdGlvbiBUaW1lAAfTBQ4QMzPy3XhEAAAAB3RJTUUH0wUOEDUk8lW5dQAAAAlwSFlzAAALEgAACxIB0t1+/AAAAQpJREFUeNpj/M9AHGAiUt2oQuIVfmREBzgU3iHWxAfEKiTaRFpZnfAfAbAr/AsxUYagiVCbeQgqhPpFYmukLCOrZupRNJUIB02BCAjAZCK+/Ed2LoJZgm6bzRfsCgMw3JWAXaEBpg8uIGSRPPMBQmXc+P+iggXCnoOQZUQK1K8PgEAjGcQs7QGL6FzG5mtkcAUiyYIQYcRRUkDTLEIWR1b4ixamQMPhrKUP3rx48eDNFXmwdyFiOthixgXqaTAnBcKpwRaOS6A6Mx78fwBVx/IAm8I/KsTGzAkWNHUyb7Ar/L8GNSlK3MCRev7/v+CApC7kBUoUoAX4yQ0nHjwAWqpiE6GNFgNDoAwHAKC2Q2lMNcCmAAAAAElFTkSuQmCC', 
-      '6' => 'iVBORw0KGgoAAAANSUhEUgAAACgAAAAoCAAAAACpleexAAAAFXRFWHRDcmVhdGlvbiBUaW1lAAfTBQ4QNAObRd4vAAAAB3RJTUUH0wUOEDUc2lcB6wAAAAlwSFlzAAALEgAACxIB0t1+/AAAATtJREFUeNpj/M9AHGAiUh2Gwq2puryMjKKmmSfRVf5HBkcMEBI+L1CkUBROYUE2QuMFLoVr0CzzwKHwhQC6szZgV1gAtfHI/xs2mEYywsPxp8QHEMVxQ56B4aaJiIKIiIRCPDZf74DwI/5jB4hwPAChbAgG+BWoExlOxkoysuqW3sUV4BoQ/p0SqARLB44AF4HIByDMKMCuEIu7phCrUOADNl/DgMOJ/09SIMwPC7B5hgfC1/kB4kRAOC7YrFaByM0Ac85AOCLYrFaBhSMIQNPlG2wBDg3HP2CSGU/MuEAoiKVXUWxB9cwPiG8UwEGSg5FCMNOjwZ4/byqgpqwgMoWr/MGeZ1agqWPZgSNz/Z+AqnDCf1wK/29B8qbKDhQpRtTE8HfLjjMP3jDwKJh4hKCGJSPNC6lRhTRWCABWpdoxd/bZ4QAAAABJRU5ErkJggg==', 
-      '7' => 'iVBORw0KGgoAAAANSUhEUgAAACgAAAAoCAAAAACpleexAAAAFXRFWHRDcmVhdGlvbiBUaW1lAAfTBQ4QNA18/fMoAAAAB3RJTUUH0wUOEDUVo4u5TwAAAAlwSFlzAAALEgAACxIB0t1+/AAAAM9JREFUeNpj/M9AHGAiUt2oQnorZIGzGLFJIyJ40HqGhUiFPFuQ/YUFPBGBmLcDSQybwj8OEDOW/CegsAeiruQ/AYV3OMDqTP4QUugCceCN/wQUQn1a8Z+Awj8qYHUiHwgpXAAxcMJ/Qgp1wOoEPhBSuANiYM5/QgpjIAovEFL4gweszgAz0NASxZ4vYMqHYDKDBiIWhWhWa0CS1x9CVn+8AaYsmAlZfQRC6RDMChADGTQIKjxDrMI7EEoBi0JGlMJe8AOY+sFOSCEeQHQBAABCZ7xyT9fJhwAAAABJRU5ErkJggg==', 
-      '8' => 'iVBORw0KGgoAAAANSUhEUgAAACgAAAAoCAAAAACpleexAAAAFXRFWHRDcmVhdGlvbiBUaW1lAAfTBQ4QNBeBnwpSAAAAB3RJTUUH0wUOEDUOKe5wowAAAAlwSFlzAAALEgAACxIB0t1+/AAAATVJREFUeNpj/M9AHGAiUt1AKmRB459cc+DBGwYWGQ2LEG1Umf/I4IELkozLA2QpFIUXJFDMEDiBQ+EHGTR3yHzArrAFwwct2BXqQGQ1zvw/owFh6mBXCDXmDJB5BsOrjEhxzfoHIgkiGCGB9xtrgEPtOwvEV6FWY4+ZAAgVc5LhZgKEGYI9wN+gBiPu4Pl/BFWlxA1cMfN/C0rUr8AVhX8K0KyuwaEwASNmarAqPACVTXnw/0oENBFewKYQGhYZYE4MVBM2hVAvQ1LhHQhHBVsUMjIgYhCdhy3PPASTd6GOxBYz0KhOQHajDjY3pkC1Rlz5fweqjqEAm8ILGK5gYLlDZICXYI+ZLzZo6gL+4EgUfyo4kJQJtCCpQ8kKQPB2zZ47L14AU5iMgUMAN7IM43AqHwdQIQAhMPz6Gz5V/wAAAABJRU5ErkJggg==', 
-      '9' => 'iVBORw0KGgoAAAANSUhEUgAAACgAAAAoCAAAAACpleexAAAAFXRFWHRDcmVhdGlvbiBUaW1lAAfTBQ4QNCQ+T2tEAAAAB3RJTUUH0wUOEDUHUDLIBwAAAAlwSFlzAAALEgAACxIB0t1+/AAAAUZJREFUeNpj/M9AHGAiUh26wr9rE3V5GRlFTTM3/kVT+R8Z7FBBSKjsQJFCUTiFBcWMCbgUHmBBs20FdoV/VNDUMQi8wapwDVS65s2fPToQZgFWhRFIkm8kwGyeH9gUQm2+Aua0QDhb4LJI4XgHQmmDSRMIZw+emIEENAeEcwObQhEIdQHiABRbUGPGBSIQAWL/gHqbB5tnJkC1Fjz5f8IGwxwkhR8EsCQarFE4hViF/wsQCgKgHsSu8H8HLFkUQL2rgUPh/zslOiwMEjFH/kND2geXQvQgqMAWhSjgAIRygAswIuXCpXfevHjz4M0ZdQaGhxo/wAnyBTuWmPnvARGxuPH/iAa+9Ph/A7r9Ai+wK/zvg6ZwzX8cCl9oICtjmfIfl8L/bwIQ6gyO/Met8P//EwUmwHTJo5OyBU2CkdaF1KhCWisEAM/sJxmZkdWnAAAAAElFTkSuQmCC', 
-      'A' => 'iVBORw0KGgoAAAANSUhEUgAAACgAAAAoCAAAAACpleexAAAAFXRFWHRDcmVhdGlvbiBUaW1lAAfTBQ4QFwy1U7TfAAAAB3RJTUUH0wUOEC0ZKCZtPQAAAAlwSFlzAAALEgAACxIB0t1+/AAAAO1JREFUeNrt1LERwiAUBuAHZ2GRwsIypQMwQEZwgBQpM4QDZBSLFI7gCA5gQWGRdA5gkTuMSh48eMTUnq96wH98B+QiDCwruTD3D76qF676ueAp0Y9lSBXeSkFWaLAje3T+kkzK4SgpBzZw8pqxJWcdOJuRsyGPbWDk0tS20zw9SXsobdfytJVXdzNsP61i6Zt3K7Ht0UeUgbPdjsrOXMd+2IS2C2qb271HVWi7YANcNXFQsUEVBTXwNdl46jYRxPl52dnwRUZbhkLSDmS8DnxFRWiULxg8UxvobefuRR8ZQYDKtffVVcQWv/RrfgJC4bd0upw4MQAAAABJRU5ErkJggg==', 
-      'B' => 'iVBORw0KGgoAAAANSUhEUgAAACgAAAAoCAAAAACpleexAAAAFXRFWHRDcmVhdGlvbiBUaW1lAAfTBQ4QGAusrz2zAAAAB3RJTUUH0wUOEC01Gv4B3gAAAAlwSFlzAAALEgAACxIB0t1+/AAAANJJREFUeNpj/M9AHGAiUh0tFTKiAUHL2rsoKv9DARZDWFr+IwA+hQwMFcQqZDhCrMIIYhWK4FYIYv8444PuV+wK//9/A+UJwBUSCHAL3OEIsdoFyttCpGdiiAtHjoY/RCnk6PlBbBRKrCE6CqcQq5DlDs5whIT3CgUI788EvOEIBCegXB2YPCNMBSNMISqf5TeUjysK90LpP/itfrFEAhZCMHkWdKMYUbk2MAah7BqD02pUYEFkgMu8IE6hD0IdpmegwSejoKLjoY7syaFU7A0HhQA2e4cJytImvAAAAABJRU5ErkJggg==', 
-      'C' => 'iVBORw0KGgoAAAANSUhEUgAAACgAAAAoCAAAAACpleexAAAAFXRFWHRDcmVhdGlvbiBUaW1lAAfTBQ4QGBbPqVFqAAAAB3RJTUUH0wUOEC4BEGemqAAAAAlwSFlzAAALEgAACxIB0t1+/AAAASlJREFUeNpj/M9AHGAiUt2owkGrkAWV+3TDgRtPPjBwyGiYBOijSv1HAlcCkGUcTiDLISvsQDOeZQp2hQWYDpuCTeEEbD44ganwDgc2vxpgKoyAyUWc+f9hjgCMtwFd4RuYRxog/ueBcl3QFc6BSmj8gfBrwE40yFmCrjABqrAH5mSZgJ4jX7AEjwlU4Zn/OAAsrp9AaRlccc0IzdeMsBilOPWQrBDmtpfEKnwBpZ8qZq58i6IS6vscKHcBcgQYlOz4gh6OK6AKfaB8G5hN6Aq/wBLPHjB3CczCFIzUA0u2PD0v/j9pgaf1ExgK3wgwYAEOWFL4GizqWC5gyzM1mArnEJkLZ2DPhf//n3BAVmeDkq8ZUZPL3TUn7gBLCgYFBYsAcxQZRmKrDwABNsv9SJSDwwAAAABJRU5ErkJggg==', 
-      'D' => 'iVBORw0KGgoAAAANSUhEUgAAACgAAAAoCAAAAACpleexAAAAFXRFWHRDcmVhdGlvbiBUaW1lAAfTBQ4QGC1+orhOAAAAB3RJTUUH0wUOEC4yr7fHvgAAAAlwSFlzAAALEgAACxIB0t1+/AAAAM9JREFUeNpj/M9AHGAiUt1AKmSBsxiRhXlkNBxCpFFU/ocBTDMyPvxHADwKGRgUbhCpkEHiCZEKGRyIVciwArdCIPPFGg8YzwSvQiBogXFvEFD43wDKnQDl44yZGCh9glAU2sCsJqRQBkq/gMUw3G2wuP6PnU/H9PgRSgsQUvgESosQUngFSqsQUrgCSsNiCFcU7oBx9+CL6w8XamB5SeUPkelxAZEJ1+YPcQolXhCXFTTuEJULOUq+IOVrFgasQELBxMaHG1mEcTiVjwOoEADAIkCnGpmJKgAAAABJRU5ErkJggg==', 
-      'E' => 'iVBORw0KGgoAAAANSUhEUgAAACgAAAAoCAAAAACpleexAAAAFXRFWHRDcmVhdGlvbiBUaW1lAAfTBQ4QGDeDwEE0AAAAB3RJTUUH0wUOEC8CkHXGUwAAAAlwSFlzAAALEgAACxIB0t1+/AAAAD5JREFUeNpj/M9AHGAiUt2owkGrkAXGYMQqjUgJQ8EzpPsa05+D140oMYTk4KEQ4MMqZqgUhcM1czESW30AABfqB1XDnLzcAAAAAElFTkSuQmCC', 
-      'F' => 'iVBORw0KGgoAAAANSUhEUgAAACgAAAAoCAAAAACpleexAAAAFXRFWHRDcmVhdGlvbiBUaW1lAAfTBQ4QGQe8AkDZAAAAB3RJTUUH0wUOEC8JB6cf2wAAAAlwSFlzAAALEgAACxIB0t1+/AAAADlJREFUeNpj/M9AHGAiUt3wUsiCYDJikUYE3lDwDDm+xvTp4HUjIoaQXTsUAnxYxcyoQryAcUSWuAAW/gZTg/yEMAAAAABJRU5ErkJggg==', 
-      'G' => 'iVBORw0KGgoAAAANSUhEUgAAACgAAAAoCAAAAACpleexAAAAFXRFWHRDcmVhdGlvbiBUaW1lAAfTBQ4QGRFI1vWIAAAAB3RJTUUH0wUOEC8QY8y3GwAAAAlwSFlzAAALEgAACxIB0t1+/AAAASZJREFUeNpj/M9AHGAiUt0IVciCwvt7ZM+FOy8+MDBwSEho2AQII8v9R4A/U2RQtHEUfEBIIim8YYBhn8oNLAqP8GBxmcwbDIU3sKljYIhAV/jHgAE7uICmcAJMQqDmwp//D2YowPgxqAr/wPyr8QAi8EEHwleIQFW4BxYicG+eEHEomHECET5QhRVQhQn/cQFoFJ6AKgwgFNcPoFwdnAoZIXmGERahKDwkIdqlR1j4PiRW4RVCCmExvQenQrSYEXiDiAoUBfC4loAK23yBSnzArhCRehRmAJPFnRUxHDgU/lDA7zZECj/Cgl2dAkaeWYNVZcoHDIX/94hgKLM4gS27/v9QIICizGMDkiQjSon7c8eBCw+e/GFgkZEwsHCRRpZiHE5FMwCa2YE+WcAOUwAAAABJRU5ErkJggg==', 
-      'H' => 'iVBORw0KGgoAAAANSUhEUgAAACgAAAAoCAAAAACpleexAAAAFXRFWHRDcmVhdGlvbiBUaW1lAAfTBQ4QGRw2Z4k1AAAAB3RJTUUH0wUOEC8agxleBQAAAAlwSFlzAAALEgAACxIB0t1+/AAAAD1JREFUeNpj/M9AHGAiUt2oQvyABUozQml4+KMLDAXPDAWFLGh8RlwKh4JnaB88GOlxELhxVCFewDgEynAAN2sFVHAvevkAAAAASUVORK5CYII=', 
-      'I' => 'iVBORw0KGgoAAAANSUhEUgAAACgAAAAoCAAAAACpleexAAAAFXRFWHRDcmVhdGlvbiBUaW1lAAfTBQ4QGSlg1E0WAAAAB3RJTUUH0wUOEC86uHd+zQAAAAlwSFlzAAALEgAACxIB0t1+/AAAAD5JREFUeNpj/M9AHGAiUt1AKmRBMBkxJJE9OhQ8Q32FjGhxDQsjjCQwFDwzqnCwKkRKZqO5EBMwDqcSl2iFAMMeB0s/kLo2AAAAAElFTkSuQmCC', 
-      'J' => 'iVBORw0KGgoAAAANSUhEUgAAACgAAAAoCAAAAACpleexAAAAFXRFWHRDcmVhdGlvbiBUaW1lAAfTBQ4QGywiiNsbAAAAB3RJTUUH0wUOEDAFw0tdbgAAAAlwSFlzAAALEgAACxIB0t1+/AAAAKdJREFUeNpj/M9AHGAiUh3xClmwijJCaSR3Ud/qUYWjCklTyIHEhifctw8ePHgCxO+B7L9QMQlsChW+QOiX4gwMd6BiItisVoHSB6AYWQwM/kNBBszkC/9PwKyc8B8B4Ar3YPHMHWwK/xtgqAv4j1XhEfScK/EEu8L/a1BVStz4j0Ph/yPItoe8QFH3nxGlkNq75cKDB0DDVBwitNEcwjhwpdmoQrwAAN6ioiFapgUdAAAAAElFTkSuQmCC', 
-      'K' => 'iVBORw0KGgoAAAANSUhEUgAAACgAAAAoCAAAAACpleexAAAAFXRFWHRDcmVhdGlvbiBUaW1lAAfTBQ4QHAEoFhGpAAAAB3RJTUUH0wUOEDANzZDVXAAAAAlwSFlzAAALEgAACxIB0t1+/AAAAPZJREFUeNpj/M9AHGAiUt2owgFSyAgFMOGDrDARxkKo0H8wYEDh/b/AAzepACqEVeEdCQx1WBW+0ICry/mPR+EXE7i6kD94FP5xwaYOi8IIrOowFRbA1Xkgq8NQ2ANXZ/PlPx6FS3CpQ1fIAmOIoKn7jxbXf2CMNxvQIxvVRAQQ+YDXaiSQQqxChiOEFGoIQGidP/gVStxogLI68CqUuPH/BzSVcTzAoxCo7v//ObBIxK0QrO7/H1iCXIFT4QkIFxbaMh9wKYQJO0D5OYQUnoDF/QkCCuHJ1+APAYV3YOloAgGF8JTO84SAwjfQiGQIgPAZqV4rAACnKSarzdlc4gAAAABJRU5ErkJggg==', 
-      'L' => 'iVBORw0KGgoAAAANSUhEUgAAACgAAAAoCAAAAACpleexAAAAFXRFWHRDcmVhdGlvbiBUaW1lAAfTBQ4QHA64qQw4AAAAB3RJTUUH0wUOEDAXMPIsJgAAAAlwSFlzAAALEgAACxIB0t1+/AAAADlJREFUeNpj/M9AHGAiUt2QUMiCYDJCaezhMBQ8M6pwVCEdFLJgCjEisRH5Zyh4hvoKGUdkQUq0QgARaARRV9jUFQAAAABJRU5ErkJggg==', 
-      'M' => 'iVBORw0KGgoAAAANSUhEUgAAACgAAAAoCAAAAACpleexAAAAFXRFWHRDcmVhdGlvbiBUaW1lAAfTBQ4QHBhMfblpAAAAB3RJTUUH0wUOEDAqaJpgNwAAAAlwSFlzAAALEgAACxIB0t1+/AAAAPNJREFUeNrdlK0OgzAUhS8bCQYxMYmcmEAgEAgejQfZQyG2pAIxOYlATkAu691o2tvSYia2iv7lyzn3NG0jhG1tt5H7Aggom7ZuaKPhBFqKV+pFWDGjjcxStEAYXuvBkrKtoVX+gdRiK9i6sxjgeVGUMJzWwZLACaZOTqoAOAronmrlBuvPkQsIgHn8BqnE2AMmhaaYJ57jqTRFMwsDyW249XaJLhAujizm7UFM5XCUXTqiTvBLQYWRc7H3WWt+3NmlyGbOGh9q/45mjQxUb+CA6A2jSqu5MweX0ooQWLJxLYx6fz0GwmBOsww5GP3At/dX4Ayb7qpFI9y5ygAAAABJRU5ErkJggg==', 
-      'N' => 'iVBORw0KGgoAAAANSUhEUgAAACgAAAAoCAAAAACpleexAAAAFXRFWHRDcmVhdGlvbiBUaW1lAAfTBQ4QHC6DxyzwAAAAB3RJTUUH0wUOEDAye/b4YQAAAAlwSFlzAAALEgAACxIB0t1+/AAAALRJREFUeNpj/M9AHGAiUt0IV8gIARsRMlAROP8/BEB5Ii/+/0cVgXNRhRk8iFXIMIFYhRxXiFTIYPCDSIUMBcQqZNhDrEKZN0QqZAggViHDHIIKRSAUzx1CCrdAaZM/BBT+z4Eyaggp/KEDYbAcIaDw/wUWCEuBkML/PagBgFvhfxdiFT4RIVLh/zXEKvyfQqzCLypEKvx/hoVIhf9biFX4x4ZIhf8fCBCp8P8KNBHG4VQ0AwDEOyeZhO5p1AAAAABJRU5ErkJggg==', 
-      'O' => 'iVBORw0KGgoAAAANSUhEUgAAACgAAAAoCAAAAACpleexAAAAFXRFWHRDcmVhdGlvbiBUaW1lAAfTBQ4QHQExDSDoAAAAB3RJTUUH0wUOEDA4myMRfwAAAAlwSFlzAAALEgAACxIB0t1+/AAAATtJREFUeNpj/M9AHGAiUt3wUsiCyv265ciZJ08YGGRkDGwCuFGk/iOBDwU8SDIcGS+Q5JAV7hBBs45nAVaFC1gwXTYBi8IdWNQxMCzAUPhBBJs6Bp4n6AoLYFI6az78f7NEB8ZNQFP4QwAqEfADwg+A+f0NqsI1UHGBDzCnSKC6EhYzB6B0Cj+UwZ+CKgNTeAZKu8C94QGlL6DGjAyU+wAeXC+gIiIQLiM0KzDC9CFCBlWICsnsL3aFMDc+hcs8QZWBKYSF2g24whvYFZpA6T1whUegNCwyoYGxAmYyLGZ+wOxYghqFX2BpO+APmP8nBspHj2uk1LPizf8PGyxgXPTUQ3x6JDqF//8/AYs6bHkGmCYF0O3FnguBCSaFA0kZS8IDJDlG1IIUVFK8eABMWzI6DgHCyDKMI7LEBQCD5YgI9wbKGgAAAABJRU5ErkJggg==', 
-      'P' => 'iVBORw0KGgoAAAANSUhEUgAAACgAAAAoCAAAAACpleexAAAAFXRFWHRDcmVhdGlvbiBUaW1lAAfTBQ4QHQvR2Mn2AAAAB3RJTUUH0wUOEDEDMzPJGgAAAAlwSFlzAAALEgAACxIB0t1+/AAAAKVJREFUeNpj/M9AHGAiUh05ChlRAKdu4k5Ulf9hANMQiwf/EQCfQgaJB0QqZHAhViHDEbg0AV8vwRM8QN0v5vBAOSfw+BrMWQDl8MClGeEKGGEKQcRXHmQemTGD1RMy+N14o4MDyvGAS7NgGMaIzPHAYyIy4HhBZMy0EBmFIX+IUsjRgqQOi2fAgEVBwyVGGEUEQw2O3EbLzDWSFDIOhtJsVCEWAAC/Yt2X+2PYcgAAAABJRU5ErkJggg==', 
-      'Q' => 'iVBORw0KGgoAAAANSUhEUgAAACgAAAAoCAAAAACpleexAAAAFXRFWHRDcmVhdGlvbiBUaW1lAAfTBQ4QHRxSC0wxAAAAB3RJTUUH0wUOEDEKSu9xvgAAAAlwSFlzAAALEgAACxIB0t1+/AAAAW1JREFUeNpj/M9AHGAiUt2QUMiCzPm65cCZF08YGGRkDBx8uNFU/oeDDwU8SOIcBS/+IwOEwh0iaEYIrMCqcA4LprsmYFG4A4s6BoYFGAo/iGBTx8DzAl1hAUxKZ8WH/29W6MC4KWgKfwhAJXx+gPl/QmB+/4KqcANUXOQDVPiLBFRkCUwhJGb2wGzihzK4U6CMA6hReAbKc4F7wwFKX0CNGRkoB+HJJ1ARGZgAIziFM8J0IUIGXYjMZPaXkEJYYDyBiz+EuRFVoQKUdwWIz6qWvmRguAMVkUBVaIIUalPu9GgshIefAWrwrIHp//L/DQc4KjFiBi2uQ/7832KB5AX0uP5fAZOx2PDhfwNCIXrq+f9BhgEb4HmCkcL3YE3hSHkBnmfWYFMpsoaYXAgGDgcwFKLlaxYOCG2DqRCYrldkmIACUMIgZsaTI5Cg3IBNISp4AoovlT+EFf7/kYPkb3wK//8/YAGPGcYhUIYDAHBC9Yak1w7iAAAAAElFTkSuQmCC', 
-      'R' => 'iVBORw0KGgoAAAANSUhEUgAAACgAAAAoCAAAAACpleexAAAAFXRFWHRDcmVhdGlvbiBUaW1lAAfTBQ4QHSkEuIgSAAAAB3RJTUUH0wUOEDEUsOBM3QAAAAlwSFlzAAALEgAACxIB0t1+/AAAAOZJREFUeNpj/M9AHGAiUh0NFLJAaUY0YRkJHYcQdmSh/xCAzRCZHf8RAJ9CBpYNRCpkEHgBV4jfMx+mEOVGIDDAaTWY82aPBZTLgV8hUCkaH6cbP8B8gxHgyODjgwstMDfiVIgWQyFE+lrhB3EBznOFuJgxuUFMXPPEbPmDpA53FH55osKMIoAe4F826MDMvPMfj9WgWFGBBeIf/Ar/H4FxJhBQ+B8WzCIfCCi8A4uvBgIK/2fA/POCgMIXHFBuDqH02ABLM3cIKPwgAuVHEFD4fwJM4AIBhT9goe4AFWAcAsXesFIIAEvJyZHTCSiTAAAAAElFTkSuQmCC', 
-      'S' => 'iVBORw0KGgoAAAANSUhEUgAAACgAAAAoCAAAAACpleexAAAAFXRFWHRDcmVhdGlvbiBUaW1lAAfTBQ4QHTRnvuTLAAAAB3RJTUUH0wUOEDEbIF9RTAAAAAlwSFlzAAALEgAACxIB0t1+/AAAAVZJREFUeNpj/M9AHGAiUt2oQvyABYX398CWK3de/GBgkVEw8HFgRpH7jwSWqCDLyCxAlkNS+CcG3boY7AozMB3Wgk3hGSw+4HgBl0b4egIWhT9mYPGMBFQg4MH/D2tgvrKASzPC0yMjlP7CDSTOmrDIMDDwiHBsxzSRBypw5j9WgFDoAPNAxIQjX/ApXIDsC4OCLV9wKfzjwIACOEIO4IiZFxbooePzAqvC/z9qONBUStzAqvD//zc9BqgqNX5gVwgETxbkmCClvSk4FYLdsCMCptAGI2YSGV78+PLmz5MX4mDu1ByIMM9n9JiBxe4caGChy8MZMMsUIEFyAMoVwVC4BGaEwpI3/9/MEYGlJQyFPwQYsIE1mL7GlnCR0iNSXLtgqpO4gy1mvtigq1NAxCBKgP9pEUFWxlOCnNIYUYrmn3v23Ljx5gsw88sYOPhwI0sxDoEyHAABtSc836a1EQAAAABJRU5ErkJggg==', 
-      'T' => 'iVBORw0KGgoAAAANSUhEUgAAACgAAAAoCAAAAACpleexAAAAFXRFWHRDcmVhdGlvbiBUaW1lAAfTBQ4QHgUdTbcyAAAAB3RJTUUH0wUOEDEgkVS4aAAAAAlwSFlzAAALEgAACxIB0t1+/AAAADdJREFUeNpj/M9AHGAiUt0IVcgCpRlxyMODeSh4hmiFjGipB+Z7jEQ1FDwzqnBU4WBSyDicimYAb/AFTaJpyH8AAAAASUVORK5CYII=', 
-      'U' => 'iVBORw0KGgoAAAANSUhEUgAAACgAAAAoCAAAAACpleexAAAAFXRFWHRDcmVhdGlvbiBUaW1lAAfTBQ4QHhEHl2NPAAAAB3RJTUUH0wUOEDEon48wWgAAAAlwSFlzAAALEgAACxIB0t1+/AAAAKlJREFUeNpj/M9AHGAiUh3xClmgNCOUhrsEXYD6Vo8qHFVIuUIVKP0USr+E0jLoCjWg9A4ovQVNHJjUIaADZsILMPeFApRfA5X/D1N4AaZRYc6b/2+WwNQxXEBX+N8Bqxcc/mMoPMGCRR3LBUyF/2dgUTjjPxaF/6egm8ky5T9Whf9P2KCoMziBJPefEaWQurjnzIMXL34wsMhoWHiYo2hjHLjSbFQhXgAAKzejCLAOcVMAAAAASUVORK5CYII=', 
-      'V' => 'iVBORw0KGgoAAAANSUhEUgAAACgAAAAoCAAAAACpleexAAAAFXRFWHRDcmVhdGlvbiBUaW1lAAfTBQ4QHh/gL05IAAAAB3RJTUUH0wUOEDEuduyVbwAAAAlwSFlzAAALEgAACxIB0t1+/AAAAVNJREFUeNpj/M9AHGAiUt2owoFRaMgIAYlIMqlQMUMo/z8ITIByRP78hwMRqNgECBei8AULVPQIXN0RqAjLGwgfYrW4B1R4DdzmLVDaQxjZ6v8roDwVuIkqMK3/ka3+/0MAKn4FKn4D5uof/5GtZmCPgEpsQHNDBDsDitVwt5tA+RZQ/pn/qFYj3PQEzHsC5WnA3QyPmQQU3+5AE0VYDTfDBcxzgQbik/8YVv93gMp9AbK/cEAD8T+m1TBb/oD8veEHhs0IE2GmxADZMRAmz4//WKxGkv3DA2Gm/MeqcA/Ujj1w1hHsCv/LQKQz/megRzyawgqIvAxMRwsuhbCEAEvGT3AphEUwNCU5IEv9R8lcUH9/wAxE5HAEgjccSBI8X3CbKOyBxAnhxm3i/w1IEgdQZFA98/+PCFydDKo6VKsZmGPQ0wgOq/+fgYvfQTORkeq1AgCIAvD7+THsDgAAAABJRU5ErkJggg==', 
-      'W' => 'iVBORw0KGgoAAAANSUhEUgAAACgAAAAoCAAAAACpleexAAAAFXRFWHRDcmVhdGlvbiBUaW1lAAfTBQ4QFhZRKnzkAAAAB3RJTUUH0wUOEDIR66frkQAAAAlwSFlzAAALEgAACxIB0t1+/AAAAXNJREFUeNrtlK1ywkAUhZdMZsJMKyIqKhAIBAKBiEBEVCDyCJV9iIo+Do9QGRERgUBEVCAqKhAIREVERURnTvfn3t27xSA6g+kOQ/ZkP/aec5NlBHXZSC7k/sE/AhUwoVkDPQ58/2RUQ2IC6B1XpN7MV8tg62/pUdjSDO7OwR2J0pbekpqZYlMG50bNSGwBDQ4pyV5YtCZ7mqZf1mO2IN2Jynba0XRx49pThjQCbEKWFfVRpIlBzlK4PuLdpxEWlTr4LHvYMEDOaTYS3HCW3DAJt8mmaSXYchZbOfEzkyYGZRbrEbX8qe7GMpLqFeyxV9F4fon1pwcxjxbqJpJTBPBJLoyHYSz1I3xq78aOMssepHZZHFjKhbX9/AZd6e9bsdABeyHTQXiE2PLO6PugCwiP/r1QVLYSlpXwKE1Wno7b7jY+hoWj0aegPyA9+jPrzgqwZJ0j8hhMVtElmDoD19FFPAvamc+sOXBm+KdYEzC63p/9D7Tr72kj/8qjAAAAAElFTkSuQmCC', 
-      'X' => 'iVBORw0KGgoAAAANSUhEUgAAACgAAAAoCAAAAACpleexAAAAFXRFWHRDcmVhdGlvbiBUaW1lAAfTBQ4QHi/G9n7kAAAAB3RJTUUH0wUOEDIXAsROpAAAAAlwSFlzAAALEgAACxIB0t1+/AAAAT9JREFUeNpj/M9AHGAiUt3IVhjKCAFr4RJroSKBMIH/YPBEAMITeQLh//8gAxHggQlAFf6fAdXnA+WnQPkT/qMp/O8AlVkA5h2A8kz+YCi8wQGREngA5PxQgXBYzvzHUPi/A2qIA5BdAmUX/Mei8I8BVHbK/wssEJbMB2wK/5+ASvPcgGlZ8x+rQriFAmghgKHwiwJKXPA8wKXw/x4UhT3/cSr8n4CkzuAPHoVvRODqWE6gyPxHTT1ffiAUCjCgAhRtDkgSFnisnoJixAScCh/wEBk8DmiucsChcA5MQQSMMQWrQlgiZ0iAByey5QiFPlBZnS//v+hgxjZc4QKYKVeAnCswby3AUAi3eAGKNoEn6Ap94A5EjXUfNIUrEA6EALgzl6AohCUGsAMhAOZMkTfICkMw3I5wZgiEyzicimYAFRFkVwgDfJ0AAAAASUVORK5CYII=', 
-      'Y' => 'iVBORw0KGgoAAAANSUhEUgAAACgAAAAoCAAAAACpleexAAAAFXRFWHRDcmVhdGlvbiBUaW1lAAfTBQ4QHjkyIsu1AAAAB3RJTUUH0wUOEDIkvRQvsgAAAAlwSFlzAAALEgAACxIB0t1+/AAAANJJREFUeNrt1L0NgzAQBWAcUVB6AAZgBAoKhmAICoZgCAoKxmAECkbwABSUlBRILwF8duwYhFJEihJ37+6T5T9g8K6N20X3FdDDNjKKOeTIqZLtWcKBU73bCx1lPhgQNTWieY1zRLmGCZFQp1xTSSmBDUUgW754BF+GQLxAPUkMxMb0FlzUsqpKLXhxQPRqo+oIerggCvuMC7jhFJounA4gWhO2OIL6Jp/uzglHrh0fTyAaDRucQaTkUpxDQVBYDWZ/hYze6bsv/A8/DNlP/kgvwzuer4kCMGPZDgAAAABJRU5ErkJggg==', 
-      'Z' => 'iVBORw0KGgoAAAANSUhEUgAAACgAAAAoCAAAAACpleexAAAAFXRFWHRDcmVhdGlvbiBUaW1lAAfTBQ4QHwfqWOdfAAAAB3RJTUUH0wUOEDIrLasyIwAAAAlwSFlzAAALEgAACxIB0t1+/AAAAL5JREFUeNrl1C0OwkAQBWCWQIJEVPQIFT0GAlHBMRBIBKIHqahAIDlERY9R0UOs3ORh5qVLunmp5GfUZvczbzKzDqtltV7ofgtueHCp16h33xBGwn0KYqoTO/J868Csaj418e0cPujOkLDfmTsECcfcXOGhoC/NZQMUDBUDd5DwxiAtJGzprpCw48xVQcIhM1d6KOgLc/kIBcORgXtIeGGQOyRs6Oq0g7P92YbkRE7bRZhcwhh+6nLF5f7yx30B8Z7FgxzMWtEAAAAASUVORK5CYII=', 
-    );
-  
-    return $_png;
-  }
-  
-  // Function get_rgb by Frank Burian
-  // http://www.phpfuncs.org/?content=show&id=46
-  function get_rgb($hex) { 
-    $hex_array = array(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 
-        'A' => 10, 'B' => 11, 'C' => 12, 'D' => 13, 'E' => 14, 
-        'F' => 15); 
-    $hex = str_replace('#', '', strtoupper($hex)); 
-    if (($length = strlen($hex)) == 3) { 
-        $hex = $hex{0}.$hex{0}.$hex{1}.$hex{1}.$hex{2}.$hex{2}; 
-        $length = 6; 
-    } 
-    if ($length != 6 or strlen(str_replace(array_keys($hex_array), '', $hex))) 
-        return NULL; 
-    $rgb['r'] = $hex_array[$hex{0}] * 16 + $hex_array[$hex{1}]; 
-    $rgb['g'] = $hex_array[$hex{2}] * 16 + $hex_array[$hex{3}]; 
-    $rgb['b']= $hex_array[$hex{4}] * 16 + $hex_array[$hex{5}]; 
-    return $rgb['r'].','.$rgb['g'].','.$rgb['b']; 
-  }
-  
-  // Function  gdVersion by Hagan Fox
-  // http://de3.php.net/manual/en/function.gd-info.php#52481
-  function gdVersion($user_ver = 0)
-  {
-     if (! extension_loaded('gd')) { return; }
-     static $gd_ver = 0;
-     // Just accept the specified setting if it's 1.
-     if ($user_ver == 1) { $gd_ver = 1; return 1; }
-     // Use the static variable if function was called previously.
-     if ($user_ver !=2 && $gd_ver > 0 ) { return $gd_ver; }
-     // Use the gd_info() function if possible.
-     if (function_exists('gd_info')) {
-         $ver_info = gd_info();
-         preg_match('/\d/', $ver_info['GD Version'], $match);
-         $gd_ver = $match[0];
-         return $match[0];
-     }
-     // If phpinfo() is disabled use a specified / fail-safe choice...
-     if (preg_match('/phpinfo/', ini_get('disable_functions'))) {
-         if ($user_ver == 2) {
-             $gd_ver = 2;
-             return 2;
-         } else {
-             $gd_ver = 1;
-             return 1;
-         }
-     }
-     // ...otherwise use phpinfo().
-     ob_start();
-     phpinfo(8);
-     $info = ob_get_contents();
-     ob_end_clean();
-     $info = stristr($info, 'gd version');
-     preg_match('/\d/', $info, $match);
-     $gd_ver = $match[0];
-     return $match[0];
-  }
-    
+  $class = "captcha_engine_$engine";
+  return new $class($session_id, $row);
 }
 
-// define('ENANO_CAPTCHA_BIGNFAT', '');
-  
 ?>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/includes/captcha/dicts/default.php	Fri Feb 22 12:51:53 2008 -0500
@@ -0,0 +1,6690 @@
+<?php
+$dict = array(
+'aback',
+'abacus',
+'abaft',
+'abase',
+'abaser',
+'abate',
+'abated',
+'abater',
+'abbess',
+'abbey',
+'abbot',
+'abduct',
+'abeam',
+'abhor',
+'abider',
+'abject',
+'abjure',
+'ablate',
+'ablaze',
+'abler',
+'abloom',
+'aboard',
+'abode',
+'abound',
+'about',
+'above',
+'abroad',
+'abrupt',
+'abseil',
+'absent',
+'absurd',
+'abused',
+'abuses',
+'abuzz',
+'abyss',
+'acacia',
+'accede',
+'accent',
+'accept',
+'access',
+'accost',
+'accrue',
+'accuse',
+'acetic',
+'ached',
+'achene',
+'aches',
+'aching',
+'acorn',
+'acquit',
+'acrid',
+'across',
+'acting',
+'active',
+'actual',
+'acuity',
+'acumen',
+'acute',
+'adage',
+'adagio',
+'adapt',
+'addend',
+'addle',
+'adduct',
+'adept',
+'adhere',
+'adieu',
+'adjoin',
+'adjust',
+'adman',
+'admen',
+'admit',
+'adobe',
+'adopts',
+'adore',
+'adorn',
+'adrift',
+'adroit',
+'adult',
+'advent',
+'advert',
+'advice',
+'aegis',
+'aerial',
+'aether',
+'affair',
+'affine',
+'affix',
+'afford',
+'affray',
+'afield',
+'afire',
+'aflame',
+'afloat',
+'afoot',
+'afore',
+'afoul',
+'afraid',
+'afresh',
+'after',
+'afters',
+'again',
+'agape',
+'agate',
+'agave',
+'ageing',
+'ageism',
+'ageist',
+'agency',
+'agenda',
+'agent',
+'agents',
+'aghast',
+'agile',
+'agleam',
+'aglow',
+'agony',
+'agouti',
+'agreer',
+'ahead',
+'aided',
+'airing',
+'airway',
+'aisle',
+'aitch',
+'alack',
+'albeit',
+'albino',
+'album',
+'alcove',
+'aleph',
+'algae',
+'algal',
+'alias',
+'alibi',
+'alight',
+'align',
+'aligns',
+'alike',
+'alive',
+'alkali',
+'alkyd',
+'alkyl',
+'allay',
+'allele',
+'alley',
+'allier',
+'allies',
+'allot',
+'allots',
+'allow',
+'allows',
+'alloy',
+'almond',
+'almost',
+'alnico',
+'aloft',
+'aloha',
+'alone',
+'along',
+'aloof',
+'aloud',
+'alpaca',
+'alpha',
+'altar',
+'alter',
+'alumna',
+'alumni',
+'always',
+'amass',
+'amaze',
+'amber',
+'ambit',
+'amble',
+'ambles',
+'ambush',
+'amends',
+'amener',
+'amerce',
+'amide',
+'amidst',
+'amigo',
+'amine',
+'amino',
+'amiss',
+'amity',
+'amnion',
+'amoeba',
+'among',
+'amoral',
+'amount',
+'amour',
+'ampere',
+'ample',
+'amulet',
+'amused',
+'anders',
+'angle',
+'angora',
+'angry',
+'angst',
+'animal',
+'animus',
+'anion',
+'anise',
+'ankle',
+'anklet',
+'annal',
+'anneal',
+'annex',
+'annexe',
+'annoy',
+'annual',
+'annul',
+'annuli',
+'annum',
+'anode',
+'anoint',
+'anomic',
+'anomie',
+'anorak',
+'anther',
+'antic',
+'antler',
+'antral',
+'anvil',
+'anyhow',
+'anyone',
+'anyway',
+'aorist',
+'aorta',
+'apace',
+'apart',
+'apathy',
+'aphid',
+'apical',
+'apiece',
+'apish',
+'aplomb',
+'apogee',
+'apolar',
+'appeal',
+'appear',
+'append',
+'apple',
+'applet',
+'approx',
+'apron',
+'apter',
+'aptest',
+'arable',
+'arbour',
+'arcade',
+'arcana',
+'arcane',
+'ardent',
+'ardour',
+'areal',
+'arena',
+'areola',
+'argent',
+'argon',
+'argosy',
+'argot',
+'argue',
+'argued',
+'argues',
+'aright',
+'arise',
+'arisen',
+'ariser',
+'armada',
+'armed',
+'armer',
+'armful',
+'arming',
+'armlet',
+'armour',
+'armpit',
+'aroma',
+'arose',
+'around',
+'arrack',
+'arrant',
+'arras',
+'array',
+'arrive',
+'arrow',
+'arroyo',
+'arsine',
+'arson',
+'artful',
+'artist',
+'ascend',
+'ascent',
+'ashen',
+'asher',
+'ashlar',
+'ashore',
+'ashram',
+'aside',
+'asked',
+'askew',
+'aslant',
+'asleep',
+'aspect',
+'aspen',
+'aspic',
+'assay',
+'assen',
+'assent',
+'asses',
+'assess',
+'asset',
+'assign',
+'assist',
+'assize',
+'assort',
+'assume',
+'aster',
+'astern',
+'asthma',
+'astir',
+'astral',
+'astray',
+'astute',
+'asylum',
+'ataxia',
+'ataxic',
+'atilt',
+'atlas',
+'atoll',
+'atomic',
+'atonal',
+'atria',
+'atrial',
+'atrium',
+'attach',
+'attain',
+'attar',
+'attend',
+'attic',
+'attire',
+'attune',
+'auburn',
+'audio',
+'audit',
+'auger',
+'aught',
+'augite',
+'augur',
+'augury',
+'august',
+'auntie',
+'aunty',
+'aural',
+'aurora',
+'auteur',
+'author',
+'autumn',
+'auxin',
+'avant',
+'avast',
+'avatar',
+'avaunt',
+'avenge',
+'avenue',
+'averse',
+'avert',
+'avian',
+'aviary',
+'avouch',
+'avowal',
+'avowed',
+'avower',
+'avows',
+'await',
+'awake',
+'award',
+'aware',
+'awash',
+'aweigh',
+'awful',
+'awhile',
+'awing',
+'awning',
+'awoke',
+'awoken',
+'axial',
+'azalea',
+'azure',
+'babble',
+'babel',
+'baboon',
+'backer',
+'backup',
+'bacon',
+'baddie',
+'badge',
+'badger',
+'badman',
+'badmen',
+'bagel',
+'bagful',
+'bagged',
+'baggy',
+'bailee',
+'bailer',
+'bailey',
+'bails',
+'bairn',
+'baiter',
+'baize',
+'baked',
+'bakery',
+'baking',
+'balboa',
+'balder',
+'baleen',
+'ballet',
+'balls',
+'ballsy',
+'balmy',
+'balsa',
+'balun',
+'bamboo',
+'banal',
+'banana',
+'banded',
+'bander',
+'bandit',
+'bands',
+'bandy',
+'bangle',
+'banish',
+'banjo',
+'banner',
+'banns',
+'bantam',
+'banter',
+'banyan',
+'banzai',
+'baobab',
+'barbel',
+'barber',
+'barfly',
+'bargy',
+'barium',
+'barker',
+'barley',
+'baron',
+'barony',
+'barque',
+'barre',
+'barred',
+'barrel',
+'barren',
+'barrio',
+'barrow',
+'barter',
+'baryon',
+'basal',
+'basalt',
+'based',
+'baser',
+'bases',
+'basher',
+'basic',
+'basil',
+'basing',
+'basis',
+'basset',
+'basso',
+'baste',
+'batch',
+'bated',
+'bater',
+'bathe',
+'bathos',
+'batik',
+'bating',
+'batman',
+'batmen',
+'baton',
+'battle',
+'batty',
+'bauble',
+'baulky',
+'bawdy',
+'bawler',
+'bayou',
+'bazaar',
+'beach',
+'beadle',
+'beady',
+'beagle',
+'beanie',
+'beano',
+'bears',
+'beast',
+'beaten',
+'beaut',
+'beaux',
+'bebop',
+'becalm',
+'became',
+'beckon',
+'become',
+'bedaub',
+'bedbug',
+'bedeck',
+'bedim',
+'bedlam',
+'bedpan',
+'bedsit',
+'beech',
+'beefy',
+'beery',
+'beetle',
+'beeves',
+'befall',
+'befell',
+'befit',
+'befog',
+'before',
+'befoul',
+'began',
+'beggar',
+'begin',
+'begone',
+'begot',
+'begum',
+'begun',
+'behalf',
+'behead',
+'beheld',
+'behest',
+'behind',
+'behold',
+'behove',
+'beige',
+'being',
+'belate',
+'belay',
+'belch',
+'belfry',
+'belie',
+'belief',
+'belier',
+'belle',
+'bellow',
+'belly',
+'belong',
+'below',
+'belted',
+'beluga',
+'beman',
+'bemire',
+'bemoan',
+'bemuse',
+'bench',
+'bends',
+'benign',
+'benumb',
+'berate',
+'bereft',
+'beret',
+'berry',
+'berth',
+'beryl',
+'beseem',
+'beset',
+'beside',
+'besot',
+'bester',
+'bestir',
+'bestow',
+'betake',
+'betcha',
+'betel',
+'bethel',
+'betide',
+'betook',
+'betray',
+'bevel',
+'bewail',
+'beware',
+'beyond',
+'bezel',
+'biased',
+'bicarb',
+'biceps',
+'bicker',
+'bidden',
+'bidder',
+'biddy',
+'bider',
+'bidet',
+'bigamy',
+'biggie',
+'bight',
+'bigot',
+'bigwig',
+'bijou',
+'bijoux',
+'bikini',
+'bilge',
+'billow',
+'billy',
+'bimbo',
+'binary',
+'binder',
+'bindle',
+'binge',
+'bingen',
+'bingo',
+'bionic',
+'biopic',
+'biopsy',
+'biota',
+'biotin',
+'biped',
+'birch',
+'birdie',
+'birth',
+'births',
+'bisect',
+'bishop',
+'bison',
+'bisque',
+'bistro',
+'bitchy',
+'biting',
+'bitser',
+'bitten',
+'bitty',
+'bizzes',
+'black',
+'blade',
+'blame',
+'blanc',
+'blanch',
+'bland',
+'blank',
+'blare',
+'blast',
+'blazon',
+'bleach',
+'bleak',
+'bleary',
+'bleat',
+'bleed',
+'bleep',
+'blench',
+'blend',
+'blight',
+'blimey',
+'blimp',
+'blink',
+'blinks',
+'bliss',
+'blithe',
+'blitz',
+'bloat',
+'block',
+'bloke',
+'blond',
+'blonde',
+'bloody',
+'bloom',
+'bloop',
+'blotch',
+'blotto',
+'blouse',
+'blown',
+'blowy',
+'blowzy',
+'bluer',
+'bluest',
+'bluesy',
+'bluff',
+'bluing',
+'bluish',
+'blunt',
+'blurb',
+'blurry',
+'blurt',
+'board',
+'boards',
+'boasts',
+'bobbin',
+'bobble',
+'bobby',
+'bobcat',
+'boccie',
+'bodega',
+'bodice',
+'bodied',
+'boding',
+'bodkin',
+'boffin',
+'boggle',
+'boggy',
+'bogus',
+'boiled',
+'boiler',
+'bolero',
+'bolted',
+'bolter',
+'bolts',
+'bolus',
+'bonbon',
+'bongo',
+'bonito',
+'bonnet',
+'bonnie',
+'bonny',
+'bonsai',
+'bonus',
+'bonzes',
+'booby',
+'boodle',
+'boogie',
+'boohoo',
+'booked',
+'bookie',
+'books',
+'boomer',
+'boost',
+'bootee',
+'booth',
+'booty',
+'booze',
+'boozy',
+'borate',
+'borax',
+'boring',
+'borne',
+'boron',
+'borzoi',
+'bosomy',
+'boson',
+'bosser',
+'bossy',
+'bosun',
+'botch',
+'botfly',
+'bother',
+'bothy',
+'bottle',
+'bough',
+'bought',
+'bouncy',
+'bovine',
+'bowed',
+'bowel',
+'bower',
+'bowing',
+'bowser',
+'bowwow',
+'bowyer',
+'boxcar',
+'boxful',
+'boxing',
+'boyer',
+'boyish',
+'bracer',
+'bract',
+'braid',
+'brainy',
+'braise',
+'brake',
+'branch',
+'brand',
+'brands',
+'brandy',
+'brash',
+'brass',
+'brassy',
+'bratty',
+'brave',
+'bravo',
+'brawl',
+'brawn',
+'brawny',
+'brayer',
+'braze',
+'brazen',
+'breach',
+'bread',
+'bream',
+'breech',
+'breed',
+'breeze',
+'breezy',
+'breve',
+'brevet',
+'brewer',
+'briar',
+'brick',
+'bridal',
+'bride',
+'bridge',
+'bridle',
+'brief',
+'brier',
+'bright',
+'brine',
+'briner',
+'bring',
+'brink',
+'briny',
+'brisk',
+'broach',
+'broad',
+'brogue',
+'broil',
+'broke',
+'broken',
+'broker',
+'bronc',
+'bronco',
+'bronze',
+'brooch',
+'broody',
+'brook',
+'broom',
+'brose',
+'broth',
+'brown',
+'brows',
+'browse',
+'bruin',
+'bruise',
+'bruit',
+'brunch',
+'brunet',
+'brunt',
+'brush',
+'bruter',
+'bubble',
+'bubbly',
+'buboes',
+'bucker',
+'buckle',
+'buddy',
+'budge',
+'budgie',
+'buffet',
+'bugger',
+'buggy',
+'bugle',
+'build',
+'builds',
+'bulgy',
+'bulker',
+'bulky',
+'bullet',
+'bully',
+'bummed',
+'bumper',
+'bumpy',
+'bunch',
+'bunchy',
+'bundle',
+'bungee',
+'bunker',
+'bunkum',
+'bunny',
+'burble',
+'burbs',
+'burden',
+'bureau',
+'burgh',
+'burgle',
+'burial',
+'buried',
+'burier',
+'burlap',
+'burler',
+'burly',
+'burned',
+'burnt',
+'burrow',
+'bursa',
+'bursae',
+'bursar',
+'burst',
+'bursts',
+'bushel',
+'busher',
+'bushy',
+'buskin',
+'busman',
+'busmen',
+'busted',
+'butane',
+'butene',
+'butler',
+'butter',
+'butyl',
+'buying',
+'buyout',
+'byers',
+'bygone',
+'byline',
+'byname',
+'bypass',
+'bypath',
+'byplay',
+'byroad',
+'byway',
+'byword',
+'cabal',
+'cabala',
+'cabana',
+'caber',
+'cable',
+'cacao',
+'cache',
+'cacher',
+'cackle',
+'cacti',
+'cactus',
+'caddie',
+'caddy',
+'cadent',
+'cadet',
+'cadge',
+'cadre',
+'caeca',
+'caecal',
+'caecum',
+'caftan',
+'cagey',
+'cagier',
+'cahoot',
+'cairn',
+'calico',
+'caliph',
+'calla',
+'callee',
+'callow',
+'calls',
+'calve',
+'calves',
+'calyx',
+'camel',
+'cameo',
+'camion',
+'camped',
+'camps',
+'campus',
+'campy',
+'canal',
+'canard',
+'canary',
+'cancan',
+'cancel',
+'candid',
+'candle',
+'candy',
+'canine',
+'caning',
+'canker',
+'cannon',
+'cannot',
+'canny',
+'canopy',
+'canst',
+'canted',
+'canter',
+'canto',
+'canton',
+'cantor',
+'cants',
+'canvas',
+'canyon',
+'caper',
+'capita',
+'capon',
+'capped',
+'captor',
+'carafe',
+'carat',
+'carboy',
+'cared',
+'careen',
+'career',
+'cares',
+'caress',
+'caret',
+'cargo',
+'caries',
+'caring',
+'carnal',
+'carny',
+'carob',
+'carol',
+'carom',
+'carpal',
+'carpel',
+'carpi',
+'carpus',
+'carrel',
+'carrot',
+'carte',
+'cartel',
+'carven',
+'casaba',
+'casbah',
+'cased',
+'casein',
+'cashew',
+'casing',
+'casino',
+'cassia',
+'caste',
+'castle',
+'castor',
+'casual',
+'catchy',
+'cater',
+'catgut',
+'cation',
+'catkin',
+'catnap',
+'catnip',
+'cattle',
+'catty',
+'caucus',
+'caudal',
+'caught',
+'caulk',
+'causal',
+'caused',
+'caveat',
+'caver',
+'cavern',
+'caves',
+'cavil',
+'caving',
+'cavity',
+'cavort',
+'cayman',
+'cease',
+'cedar',
+'celery',
+'cellar',
+'cement',
+'censer',
+'cereal',
+'cerise',
+'cerium',
+'cermet',
+'chador',
+'chafe',
+'chafer',
+'chaff',
+'chain',
+'chaise',
+'chalet',
+'chalky',
+'champ',
+'chancy',
+'chant',
+'chaos',
+'chapel',
+'chard',
+'charge',
+'chary',
+'chase',
+'chasm',
+'chaste',
+'chatty',
+'cheap',
+'cheat',
+'check',
+'checks',
+'cheek',
+'cheeky',
+'cheep',
+'cheer',
+'cheery',
+'cheese',
+'cheesy',
+'cheque',
+'cherry',
+'chert',
+'cherub',
+'chest',
+'chesty',
+'chewy',
+'chicer',
+'chichi',
+'chick',
+'chicle',
+'chide',
+'child',
+'chilli',
+'chilly',
+'chime',
+'chimp',
+'china',
+'chine',
+'chink',
+'chino',
+'chintz',
+'chippy',
+'chiral',
+'chirp',
+'chirpy',
+'chisel',
+'chitin',
+'chive',
+'chivvy',
+'chock',
+'choice',
+'choir',
+'chokes',
+'choler',
+'chomp',
+'choose',
+'choosy',
+'choppy',
+'choral',
+'chord',
+'chorea',
+'chorus',
+'chose',
+'chosen',
+'chrism',
+'chroma',
+'chrome',
+'chubby',
+'chuck',
+'chuff',
+'chukka',
+'chummy',
+'chump',
+'chunky',
+'churl',
+'churn',
+'chute',
+'chyme',
+'cicada',
+'cider',
+'cigar',
+'cilia',
+'cilium',
+'cinch',
+'cinema',
+'circa',
+'circle',
+'circus',
+'cirque',
+'cirri',
+'cirrus',
+'cissy',
+'citron',
+'citrus',
+'civet',
+'civic',
+'civics',
+'civil',
+'clack',
+'claim',
+'clammy',
+'clamp',
+'clang',
+'claque',
+'clash',
+'clasp',
+'classy',
+'clause',
+'clave',
+'claver',
+'clawer',
+'clean',
+'cleans',
+'clear',
+'cleat',
+'cleave',
+'cleft',
+'clench',
+'cleric',
+'clerk',
+'clever',
+'clevis',
+'click',
+'client',
+'cliff',
+'climax',
+'climb',
+'clime',
+'cling',
+'clingy',
+'clinic',
+'clink',
+'clique',
+'cloaca',
+'cloak',
+'cloche',
+'clock',
+'clomp',
+'clonal',
+'clone',
+'clonk',
+'close',
+'closed',
+'closer',
+'closes',
+'cloth',
+'clothe',
+'clouds',
+'cloudy',
+'clout',
+'clove',
+'cloven',
+'clown',
+'cluck',
+'clump',
+'clumpy',
+'clumsy',
+'clung',
+'clunky',
+'clutch',
+'coaler',
+'coarse',
+'coast',
+'coated',
+'coater',
+'coats',
+'cobalt',
+'cobble',
+'coble',
+'cobra',
+'cobweb',
+'cocci',
+'coccus',
+'coccyx',
+'cockle',
+'cocky',
+'cocoa',
+'cocoon',
+'coddle',
+'codec',
+'coded',
+'coder',
+'codex',
+'codger',
+'coding',
+'codon',
+'coeval',
+'coffee',
+'cogent',
+'cognac',
+'cohere',
+'cohort',
+'cokey',
+'coleus',
+'colic',
+'collar',
+'colony',
+'colter',
+'comae',
+'combed',
+'combo',
+'comedy',
+'comely',
+'comer',
+'comes',
+'comet',
+'cometh',
+'comfit',
+'comfy',
+'comic',
+'coming',
+'comity',
+'commie',
+'commit',
+'common',
+'comply',
+'conch',
+'conchs',
+'concur',
+'condo',
+'condor',
+'confab',
+'conga',
+'conger',
+'conic',
+'conics',
+'conman',
+'conmen',
+'conner',
+'consul',
+'contd',
+'convex',
+'convoy',
+'cooked',
+'cooker',
+'cookie',
+'cooled',
+'coolie',
+'cooper',
+'cootie',
+'copay',
+'coper',
+'copied',
+'copies',
+'coping',
+'copper',
+'copra',
+'copse',
+'copter',
+'coral',
+'corbel',
+'corder',
+'cords',
+'corgi',
+'coring',
+'corked',
+'corks',
+'cornea',
+'corner',
+'cornet',
+'corny',
+'corona',
+'corps',
+'corpse',
+'corpus',
+'corral',
+'corset',
+'cortex',
+'corves',
+'cosign',
+'cosine',
+'cosmic',
+'cosmos',
+'costly',
+'cotton',
+'couch',
+'cougar',
+'cough',
+'could',
+'counts',
+'county',
+'couple',
+'coupon',
+'course',
+'court',
+'cousin',
+'covary',
+'coven',
+'covers',
+'covert',
+'covet',
+'covey',
+'coward',
+'cowboy',
+'cowpox',
+'cowrie',
+'coyed',
+'coyote',
+'coypu',
+'cozen',
+'crabby',
+'cradle',
+'crafty',
+'craggy',
+'cramp',
+'crane',
+'cranky',
+'cranny',
+'crape',
+'crass',
+'crate',
+'crater',
+'cravat',
+'crave',
+'craver',
+'crawl',
+'crawly',
+'craze',
+'crazy',
+'creak',
+'creaky',
+'creamy',
+'crease',
+'create',
+'credo',
+'creed',
+'creeds',
+'creek',
+'creel',
+'creepy',
+'creme',
+'creole',
+'crepe',
+'crept',
+'cress',
+'crest',
+'cretin',
+'crewel',
+'crick',
+'cries',
+'crime',
+'crimp',
+'cringe',
+'crises',
+'crisis',
+'crispy',
+'criss',
+'croak',
+'croaky',
+'crock',
+'crocus',
+'croft',
+'crone',
+'crony',
+'crook',
+'croon',
+'crops',
+'crouch',
+'croup',
+'croupy',
+'crowds',
+'crown',
+'cruddy',
+'crude',
+'cruel',
+'cruet',
+'cruise',
+'crumb',
+'crumby',
+'crummy',
+'crump',
+'crunch',
+'cruse',
+'crusty',
+'crutch',
+'crypt',
+'cuber',
+'cubic',
+'cubism',
+'cubit',
+'cuboid',
+'cuckoo',
+'cuddly',
+'cudgel',
+'cueing',
+'culler',
+'culpa',
+'cumber',
+'cumin',
+'cumuli',
+'cupful',
+'cupid',
+'cupola',
+'cupric',
+'curacy',
+'curare',
+'curate',
+'curdle',
+'curfew',
+'curia',
+'curiae',
+'curial',
+'curie',
+'curio',
+'curium',
+'curled',
+'curlew',
+'curls',
+'curly',
+'curry',
+'curse',
+'cursed',
+'cursor',
+'curtsy',
+'curve',
+'curved',
+'curvy',
+'cushy',
+'cussed',
+'cusser',
+'cusses',
+'cutesy',
+'cutler',
+'cutlet',
+'cuttle',
+'cutup',
+'cyborg',
+'cycad',
+'cycled',
+'cycler',
+'cycles',
+'cyder',
+'cygnet',
+'cynic',
+'cypher',
+'dabber',
+'dabble',
+'dacha',
+'dactyl',
+'daddy',
+'daemon',
+'daffy',
+'dahlia',
+'daily',
+'dainty',
+'daisy',
+'daleth',
+'dally',
+'damask',
+'dammit',
+'damner',
+'dampen',
+'damsel',
+'damson',
+'dance',
+'dandle',
+'dandy',
+'danger',
+'dapper',
+'dapple',
+'daring',
+'darken',
+'darkly',
+'dative',
+'datum',
+'davit',
+'dawdle',
+'daybed',
+'deaden',
+'deadly',
+'deafen',
+'deals',
+'dealt',
+'dearth',
+'deary',
+'debar',
+'debark',
+'debase',
+'debate',
+'debit',
+'debris',
+'debtor',
+'debug',
+'decade',
+'decaf',
+'decal',
+'decay',
+'deceit',
+'decent',
+'decile',
+'decoy',
+'decree',
+'deduct',
+'deeds',
+'deejay',
+'deepen',
+'deface',
+'defame',
+'defeat',
+'defend',
+'defer',
+'defile',
+'define',
+'defog',
+'deform',
+'defuse',
+'degas',
+'degree',
+'deign',
+'deist',
+'deity',
+'delay',
+'delft',
+'delta',
+'deluge',
+'deluxe',
+'delve',
+'demean',
+'demise',
+'demit',
+'demob',
+'demon',
+'demote',
+'demur',
+'demure',
+'dengue',
+'denial',
+'denim',
+'dense',
+'denser',
+'dental',
+'dented',
+'dents',
+'denude',
+'depart',
+'depict',
+'deploy',
+'depot',
+'depth',
+'deputy',
+'derail',
+'derby',
+'derive',
+'dermal',
+'dermis',
+'desalt',
+'descry',
+'desert',
+'desist',
+'despot',
+'detain',
+'deter',
+'detest',
+'detox',
+'detune',
+'devise',
+'devote',
+'devour',
+'devout',
+'dewar',
+'dexes',
+'dexter',
+'dhoti',
+'dials',
+'diaper',
+'diatom',
+'dibble',
+'dicer',
+'dices',
+'dicey',
+'dicier',
+'dicing',
+'dickey',
+'dicta',
+'dictum',
+'diddle',
+'didst',
+'diesel',
+'differ',
+'digit',
+'digram',
+'diker',
+'diktat',
+'dilate',
+'dilute',
+'dimity',
+'dimmed',
+'dimple',
+'dimply',
+'dimwit',
+'dinar',
+'dinghy',
+'dingle',
+'dingo',
+'dingy',
+'dinky',
+'diode',
+'dioxin',
+'dipole',
+'dippy',
+'dirge',
+'dirty',
+'disant',
+'disarm',
+'disbar',
+'disco',
+'discus',
+'dismal',
+'dismay',
+'dispel',
+'distal',
+'distil',
+'disuse',
+'ditch',
+'dither',
+'ditto',
+'ditty',
+'divan',
+'dived',
+'divers',
+'divert',
+'divest',
+'divot',
+'divvy',
+'dobbin',
+'docile',
+'dodder',
+'dodge',
+'dodgem',
+'dodgy',
+'dogged',
+'doggo',
+'doggy',
+'dogleg',
+'dogma',
+'doily',
+'doing',
+'doings',
+'doled',
+'doles',
+'doling',
+'dollar',
+'dolly',
+'dolmen',
+'dolour',
+'domain',
+'domes',
+'domino',
+'donate',
+'dongle',
+'donkey',
+'donor',
+'doodle',
+'dooper',
+'dopant',
+'dopey',
+'dopier',
+'dorky',
+'dorsal',
+'dosage',
+'dotage',
+'dotard',
+'dotty',
+'double',
+'doubts',
+'douche',
+'dough',
+'doughy',
+'douse',
+'douser',
+'dowdy',
+'dowel',
+'downy',
+'dowry',
+'dowse',
+'doyen',
+'dozen',
+'dozer',
+'draggy',
+'dragon',
+'drain',
+'drake',
+'drama',
+'drank',
+'drawee',
+'draws',
+'dreamt',
+'dreamy',
+'drear',
+'dreary',
+'dredge',
+'drench',
+'dressy',
+'drill',
+'drippy',
+'drive',
+'drivel',
+'driven',
+'drives',
+'drogue',
+'droll',
+'droner',
+'drool',
+'droop',
+'droopy',
+'drops',
+'dropsy',
+'dross',
+'drove',
+'drown',
+'drowse',
+'drowsy',
+'drudge',
+'druid',
+'drunk',
+'drupe',
+'dryad',
+'dryer',
+'dryish',
+'dryly',
+'dubbed',
+'dubbin',
+'ducal',
+'ducat',
+'duchy',
+'ducker',
+'ducky',
+'ducted',
+'ducts',
+'duenna',
+'duffel',
+'dugout',
+'dulcet',
+'dumdum',
+'dummy',
+'dumpy',
+'dunce',
+'dunker',
+'dunno',
+'dupion',
+'duple',
+'duplex',
+'duress',
+'during',
+'durst',
+'durum',
+'dusky',
+'dusty',
+'duvet',
+'duxes',
+'dwarf',
+'dwell',
+'dwells',
+'dwelt',
+'dybbuk',
+'dyeing',
+'dying',
+'dynamo',
+'eagle',
+'eaglet',
+'earful',
+'early',
+'earned',
+'earthy',
+'earwax',
+'earwig',
+'eased',
+'easel',
+'easer',
+'eases',
+'easily',
+'easing',
+'eater',
+'eatery',
+'eating',
+'ebony',
+'echoes',
+'echoic',
+'eczema',
+'edging',
+'edible',
+'edict',
+'edited',
+'editor',
+'edits',
+'eerie',
+'eerily',
+'efface',
+'effete',
+'effigy',
+'efflux',
+'eggcup',
+'egger',
+'eggnog',
+'egoism',
+'egress',
+'egret',
+'eider',
+'eight',
+'eighty',
+'either',
+'eject',
+'ejecta',
+'eland',
+'elans',
+'elapse',
+'elate',
+'elated',
+'elater',
+'elbow',
+'elder',
+'eldest',
+'elects',
+'elegy',
+'eleven',
+'elfin',
+'elfish',
+'elicit',
+'elide',
+'elite',
+'elixir',
+'elodea',
+'elope',
+'eloper',
+'eluate',
+'elute',
+'elven',
+'elver',
+'elves',
+'elvish',
+'email',
+'embalm',
+'embank',
+'embark',
+'embed',
+'ember',
+'emblem',
+'embody',
+'emboss',
+'embryo',
+'emcee',
+'emend',
+'emerge',
+'emery',
+'emetic',
+'emote',
+'employ',
+'emptor',
+'empty',
+'enable',
+'enact',
+'enacts',
+'enamel',
+'encamp',
+'encase',
+'encode',
+'encore',
+'encyst',
+'ending',
+'endive',
+'endow',
+'endue',
+'enema',
+'enemy',
+'enfold',
+'engage',
+'engine',
+'engram',
+'engulf',
+'enigma',
+'enjoin',
+'enlist',
+'enmesh',
+'enmity',
+'ennui',
+'enough',
+'enrage',
+'enrich',
+'enrol',
+'ensign',
+'ensue',
+'ensure',
+'entail',
+'enters',
+'entire',
+'entity',
+'entomb',
+'entrap',
+'entry',
+'envied',
+'envoy',
+'enzyme',
+'eolith',
+'epoch',
+'epochs',
+'epoxy',
+'equal',
+'equine',
+'equip',
+'equips',
+'equity',
+'equiv',
+'erase',
+'erbium',
+'erect',
+'ergot',
+'ermine',
+'erode',
+'erotic',
+'errand',
+'errant',
+'errata',
+'erring',
+'error',
+'ersatz',
+'eschew',
+'escort',
+'escrow',
+'escudo',
+'esprit',
+'estate',
+'esteem',
+'etalon',
+'ethane',
+'ether',
+'ethic',
+'ethnic',
+'ethos',
+'ethyl',
+'euchre',
+'eunuch',
+'eureka',
+'evener',
+'evenly',
+'event',
+'evict',
+'evince',
+'evoke',
+'evolve',
+'exact',
+'exacts',
+'excel',
+'excise',
+'exempt',
+'exeunt',
+'exhume',
+'exile',
+'exist',
+'exodus',
+'exotic',
+'expect',
+'expend',
+'expert',
+'expiry',
+'expose',
+'extant',
+'extend',
+'extent',
+'extol',
+'extort',
+'extra',
+'exude',
+'exurb',
+'eyeful',
+'eyelet',
+'eyelid',
+'fable',
+'fabled',
+'fabler',
+'fables',
+'fabric',
+'facer',
+'facial',
+'facile',
+'facing',
+'facto',
+'factor',
+'fading',
+'faerie',
+'faint',
+'faire',
+'fairly',
+'fairy',
+'fakir',
+'falcon',
+'fallen',
+'fallow',
+'falls',
+'false',
+'falter',
+'family',
+'famine',
+'famish',
+'famous',
+'fanout',
+'farad',
+'farce',
+'farer',
+'farina',
+'farrow',
+'fascia',
+'fasten',
+'fatale',
+'fatso',
+'fatten',
+'fatty',
+'fatwa',
+'fault',
+'faulty',
+'fauna',
+'fealty',
+'feast',
+'fedora',
+'feeble',
+'feeds',
+'feign',
+'feint',
+'feisty',
+'feline',
+'fellah',
+'fellow',
+'felon',
+'felony',
+'female',
+'femme',
+'femur',
+'fence',
+'fenced',
+'fencer',
+'fennel',
+'feral',
+'ferny',
+'ferret',
+'ferro',
+'ferule',
+'fervid',
+'fesses',
+'festal',
+'fester',
+'fetter',
+'fettle',
+'feudal',
+'fiasco',
+'fibre',
+'fibrin',
+'fibula',
+'fiche',
+'fichu',
+'fickle',
+'ficus',
+'fiddle',
+'fidget',
+'fiend',
+'fierce',
+'fiery',
+'fiesta',
+'fifth',
+'fifty',
+'fight',
+'filch',
+'filial',
+'filing',
+'fills',
+'filly',
+'filmy',
+'filthy',
+'finale',
+'finch',
+'finely',
+'finer',
+'finery',
+'finest',
+'finger',
+'finial',
+'fining',
+'finis',
+'finish',
+'finite',
+'finny',
+'fiord',
+'fires',
+'firing',
+'firkin',
+'firmer',
+'firmly',
+'first',
+'firth',
+'fiscal',
+'fished',
+'fisher',
+'fishy',
+'fitful',
+'fitted',
+'fitter',
+'fiver',
+'fixate',
+'fixed',
+'fixes',
+'fixing',
+'fixity',
+'fizzer',
+'fizzle',
+'fizzy',
+'fjord',
+'flabby',
+'flack',
+'flagon',
+'flail',
+'flair',
+'flake',
+'flaker',
+'flaky',
+'flamed',
+'flamen',
+'flamer',
+'flames',
+'flange',
+'flank',
+'flanks',
+'flaps',
+'flashy',
+'flask',
+'flatus',
+'flaxen',
+'fleck',
+'fledge',
+'fleece',
+'fleecy',
+'fleer',
+'fleet',
+'fleshy',
+'flews',
+'flexes',
+'flick',
+'flier',
+'fliest',
+'flimsy',
+'flinch',
+'fling',
+'flinty',
+'flirt',
+'float',
+'flock',
+'flood',
+'floor',
+'floozy',
+'floppy',
+'floral',
+'floret',
+'florid',
+'florin',
+'floss',
+'flossy',
+'flour',
+'floury',
+'flout',
+'flowed',
+'flown',
+'fluent',
+'fluffy',
+'fluke',
+'fluky',
+'flume',
+'flung',
+'flunk',
+'flunky',
+'flurry',
+'flush',
+'flute',
+'fluxes',
+'flyby',
+'flybys',
+'flyer',
+'flying',
+'foamer',
+'foamy',
+'fogey',
+'foggy',
+'foible',
+'foist',
+'folder',
+'foliar',
+'folio',
+'folks',
+'folksy',
+'folly',
+'foment',
+'fondue',
+'foodie',
+'forage',
+'foray',
+'forbid',
+'force',
+'forced',
+'forcer',
+'forego',
+'forged',
+'forges',
+'forget',
+'forgo',
+'forgot',
+'forker',
+'format',
+'formed',
+'former',
+'formic',
+'forms',
+'forte',
+'forth',
+'forty',
+'forum',
+'fought',
+'fouls',
+'found',
+'founds',
+'fount',
+'fourth',
+'fovea',
+'foveae',
+'foveal',
+'fowler',
+'foxed',
+'foxes',
+'foxing',
+'foyer',
+'fracas',
+'frail',
+'frame',
+'framed',
+'franc',
+'frank',
+'fraud',
+'freak',
+'freaky',
+'freeze',
+'freon',
+'fresco',
+'friar',
+'friary',
+'fridge',
+'fried',
+'fries',
+'frieze',
+'frigid',
+'frill',
+'frilly',
+'fringe',
+'frisky',
+'frizz',
+'frizzy',
+'frock',
+'froid',
+'frolic',
+'frond',
+'front',
+'frosts',
+'frosty',
+'froth',
+'frothy',
+'frowzy',
+'froze',
+'frozen',
+'frugal',
+'fruit',
+'fruity',
+'frump',
+'frumpy',
+'fryer',
+'fuddle',
+'fudge',
+'fugal',
+'fugue',
+'fuhrer',
+'fulfil',
+'fuller',
+'funds',
+'fungal',
+'fungi',
+'fungus',
+'funky',
+'funnel',
+'funny',
+'furore',
+'furrow',
+'furry',
+'furze',
+'fused',
+'fusee',
+'fuses',
+'fusing',
+'fusion',
+'fusser',
+'fussy',
+'fusty',
+'futile',
+'futon',
+'future',
+'fuzzy',
+'gabble',
+'gabby',
+'gable',
+'gabler',
+'gadfly',
+'gaffe',
+'gaggle',
+'gaiety',
+'gaily',
+'gained',
+'gains',
+'galaxy',
+'galen',
+'galena',
+'galley',
+'gallon',
+'gallop',
+'galoot',
+'galore',
+'galosh',
+'gambit',
+'gamble',
+'gambol',
+'gamest',
+'gamete',
+'gamin',
+'gamine',
+'gaming',
+'gamma',
+'gamut',
+'gander',
+'ganger',
+'gannet',
+'gantry',
+'gaper',
+'garage',
+'garble',
+'garde',
+'garden',
+'gargle',
+'garish',
+'garlic',
+'garner',
+'garnet',
+'garret',
+'gasbag',
+'gasket',
+'gasses',
+'gassy',
+'gateau',
+'gauche',
+'gaucho',
+'gaudy',
+'gauger',
+'gaunt',
+'gauss',
+'gauze',
+'gauzy',
+'gavel',
+'gawker',
+'gawky',
+'gazebo',
+'gecko',
+'geese',
+'geezer',
+'geisha',
+'gelcap',
+'gelid',
+'genial',
+'genii',
+'genius',
+'genome',
+'genre',
+'gentry',
+'genus',
+'geode',
+'gerbil',
+'gerund',
+'getup',
+'gewgaw',
+'ghetto',
+'ghost',
+'ghoul',
+'giant',
+'gibber',
+'gibbon',
+'giber',
+'giddy',
+'gifted',
+'giggly',
+'giller',
+'gillie',
+'gimlet',
+'gimpy',
+'ginkgo',
+'gipsy',
+'girdle',
+'girlie',
+'girth',
+'given',
+'giveth',
+'giving',
+'glade',
+'gladly',
+'gland',
+'glans',
+'glassy',
+'glaze',
+'glazed',
+'gleam',
+'glean',
+'glide',
+'glint',
+'glitch',
+'glitz',
+'glitzy',
+'global',
+'globe',
+'gloomy',
+'glory',
+'glossy',
+'glower',
+'glued',
+'gluier',
+'gluon',
+'glutei',
+'gluten',
+'glycol',
+'glyph',
+'gnarl',
+'gnash',
+'gnawer',
+'gneiss',
+'gnome',
+'gnomic',
+'goalie',
+'goatee',
+'gobbet',
+'gobble',
+'goblet',
+'goblin',
+'godly',
+'godson',
+'goggle',
+'going',
+'goitre',
+'golden',
+'golly',
+'gonad',
+'gooder',
+'goodly',
+'goody',
+'goofy',
+'googly',
+'gooier',
+'goose',
+'gopher',
+'gorge',
+'gorger',
+'gorgon',
+'goring',
+'gorse',
+'gospel',
+'gotta',
+'gotten',
+'gouge',
+'gourd',
+'gouty',
+'graded',
+'grades',
+'graft',
+'grail',
+'grain',
+'grainy',
+'gramme',
+'grand',
+'grange',
+'granny',
+'grant',
+'grape',
+'graph',
+'grass',
+'grassy',
+'grates',
+'gratis',
+'grave',
+'gravel',
+'graven',
+'gravid',
+'gravy',
+'grazer',
+'grease',
+'greasy',
+'great',
+'grebe',
+'greedy',
+'green',
+'greet',
+'greyer',
+'grief',
+'grill',
+'grille',
+'grilse',
+'grime',
+'grimy',
+'grinds',
+'gringo',
+'gripe',
+'grisly',
+'grist',
+'gritty',
+'groan',
+'groat',
+'grocer',
+'groggy',
+'groom',
+'groove',
+'groovy',
+'gross',
+'grotto',
+'ground',
+'group',
+'groups',
+'grouse',
+'grout',
+'grove',
+'grovel',
+'grows',
+'grubby',
+'gruff',
+'grumpy',
+'grunge',
+'grungy',
+'grunt',
+'guano',
+'guard',
+'guava',
+'guest',
+'guffaw',
+'guide',
+'guider',
+'guides',
+'guild',
+'guile',
+'guilty',
+'guinea',
+'guise',
+'gulden',
+'gullet',
+'gulley',
+'gully',
+'gummy',
+'gunky',
+'gunman',
+'gunmen',
+'gunny',
+'guppy',
+'gurgle',
+'gushy',
+'gusset',
+'gusto',
+'gusty',
+'gutsy',
+'gutta',
+'gutter',
+'guzzle',
+'gypped',
+'gypsum',
+'gypsy',
+'habeas',
+'habits',
+'hackle',
+'hades',
+'hadron',
+'hadst',
+'haggis',
+'haggle',
+'haiku',
+'hairdo',
+'hairy',
+'hajjes',
+'hajji',
+'halal',
+'haled',
+'haler',
+'hales',
+'halide',
+'haling',
+'halite',
+'hallo',
+'hallow',
+'haloes',
+'halon',
+'halter',
+'halve',
+'halves',
+'hamlet',
+'hammer',
+'hammy',
+'hamper',
+'handed',
+'handle',
+'hands',
+'hangar',
+'hangs',
+'hangup',
+'hankie',
+'hanky',
+'hansom',
+'happen',
+'happy',
+'harass',
+'harden',
+'hardy',
+'harem',
+'harken',
+'harmed',
+'harmer',
+'harpy',
+'harrow',
+'harry',
+'harsh',
+'hasher',
+'hassle',
+'haste',
+'hasten',
+'hasty',
+'hatred',
+'hauled',
+'hauler',
+'hauls',
+'haunch',
+'haven',
+'haver',
+'havoc',
+'hayer',
+'haymow',
+'hazard',
+'hazel',
+'hazing',
+'hdqrs',
+'heads',
+'heady',
+'healed',
+'health',
+'heard',
+'hearer',
+'hears',
+'hearse',
+'hearth',
+'hearty',
+'heave',
+'heaven',
+'heaves',
+'heavy',
+'heckle',
+'hectic',
+'hector',
+'heeded',
+'heehaw',
+'hefty',
+'hegira',
+'heifer',
+'heigh',
+'height',
+'helium',
+'helix',
+'hello',
+'helmet',
+'helot',
+'helter',
+'helve',
+'hempen',
+'hence',
+'henge',
+'henna',
+'henry',
+'herbal',
+'hereat',
+'hereby',
+'herein',
+'hereof',
+'heresy',
+'hereto',
+'hermit',
+'heroes',
+'heroic',
+'heroin',
+'heron',
+'herpes',
+'hertz',
+'hexane',
+'hexer',
+'heyday',
+'hiatus',
+'hicks',
+'hidden',
+'hidey',
+'hiding',
+'hieing',
+'hight',
+'hijack',
+'hilly',
+'hinder',
+'hinge',
+'hinged',
+'hinger',
+'hinges',
+'hippie',
+'hippo',
+'hippy',
+'hired',
+'hires',
+'hiring',
+'hisser',
+'hitch',
+'hither',
+'hoard',
+'hoarse',
+'hoary',
+'hobbit',
+'hobble',
+'hobby',
+'hobnob',
+'hockey',
+'hocus',
+'hodge',
+'hogan',
+'hogger',
+'hoist',
+'hoity',
+'hokey',
+'holder',
+'holds',
+'holey',
+'hollow',
+'holly',
+'homage',
+'homely',
+'homey',
+'homier',
+'homily',
+'homing',
+'honer',
+'honest',
+'honey',
+'hooded',
+'hoodoo',
+'hooey',
+'hoofer',
+'hookah',
+'hooker',
+'hookup',
+'hooper',
+'hoopla',
+'hooray',
+'hoover',
+'hooves',
+'hoper',
+'horde',
+'horned',
+'horner',
+'hornet',
+'horrid',
+'horror',
+'horsey',
+'hosier',
+'hotbed',
+'hotbox',
+'hotel',
+'hotpot',
+'hotrod',
+'hough',
+'hound',
+'houri',
+'hourly',
+'housed',
+'houser',
+'hovel',
+'howdah',
+'hoyden',
+'hubbub',
+'hubby',
+'hubris',
+'huddle',
+'huffy',
+'hullo',
+'humane',
+'humble',
+'humbug',
+'humeri',
+'humid',
+'hummus',
+'humph',
+'humus',
+'hunch',
+'hunger',
+'hungry',
+'hunky',
+'hurdle',
+'hurrah',
+'hurray',
+'hurter',
+'hurtle',
+'husky',
+'hussar',
+'hussy',
+'hustle',
+'hutch',
+'hyaena',
+'hydra',
+'hydro',
+'hyena',
+'hymnal',
+'hyper',
+'hyrax',
+'hyssop',
+'iambi',
+'iambic',
+'iambus',
+'ibidem',
+'icebox',
+'icecap',
+'icicle',
+'icing',
+'ictus',
+'ideate',
+'idiocy',
+'idiom',
+'igloo',
+'ignite',
+'ignore',
+'iguana',
+'ileum',
+'iliac',
+'ilium',
+'illume',
+'imago',
+'imbibe',
+'imbue',
+'immure',
+'impact',
+'impair',
+'impala',
+'impale',
+'impart',
+'imped',
+'impede',
+'impend',
+'imping',
+'impish',
+'imply',
+'import',
+'impose',
+'impugn',
+'impute',
+'inane',
+'inborn',
+'inbred',
+'incest',
+'incite',
+'income',
+'incurs',
+'indeed',
+'indict',
+'indigo',
+'indite',
+'indium',
+'indoor',
+'induct',
+'inept',
+'inert',
+'infamy',
+'infant',
+'infect',
+'infill',
+'infirm',
+'infix',
+'inflow',
+'influx',
+'inform',
+'infra',
+'ingot',
+'inhere',
+'inject',
+'injure',
+'inlaid',
+'inland',
+'inlay',
+'inlet',
+'inlier',
+'inmate',
+'inmost',
+'innate',
+'inner',
+'input',
+'inroad',
+'inrush',
+'insane',
+'insert',
+'inset',
+'inside',
+'instal',
+'insure',
+'intact',
+'intake',
+'intend',
+'intent',
+'inter',
+'intern',
+'inters',
+'intone',
+'intra',
+'intro',
+'intuit',
+'inure',
+'invent',
+'invest',
+'inward',
+'iodate',
+'iodide',
+'iodine',
+'iodise',
+'iodize',
+'ionic',
+'ionise',
+'ionize',
+'ipecac',
+'irate',
+'irenic',
+'ironer',
+'irony',
+'irrupt',
+'island',
+'islet',
+'isobar',
+'isomer',
+'ispell',
+'issued',
+'issues',
+'italic',
+'itchy',
+'itself',
+'ivory',
+'jabber',
+'jabot',
+'jackal',
+'jaded',
+'jagged',
+'jaggy',
+'jaguar',
+'jalopy',
+'jangle',
+'jarful',
+'jargon',
+'jasper',
+'jaunty',
+'jazzy',
+'jeans',
+'jeerer',
+'jejuna',
+'jejune',
+'jelly',
+'jemmy',
+'jennet',
+'jenny',
+'jerker',
+'jerkin',
+'jerky',
+'jerry',
+'jersey',
+'jetsam',
+'jetty',
+'jewel',
+'jiffy',
+'jigger',
+'jiggle',
+'jiggly',
+'jigsaw',
+'jihad',
+'jilter',
+'jingle',
+'jingly',
+'jingo',
+'jinked',
+'jitsu',
+'jitter',
+'jobber',
+'jockey',
+'jocose',
+'jocund',
+'joggle',
+'johnny',
+'joined',
+'joiner',
+'joins',
+'joint',
+'joints',
+'joist',
+'jokey',
+'jolly',
+'jongg',
+'jostle',
+'joule',
+'jounce',
+'joust',
+'jovial',
+'jowly',
+'joyed',
+'joyful',
+'joyous',
+'judder',
+'judger',
+'jugful',
+'juice',
+'juicy',
+'jujube',
+'jumble',
+'jumbo',
+'jumpy',
+'junco',
+'jungle',
+'junior',
+'junket',
+'junkie',
+'junky',
+'junta',
+'juries',
+'jurist',
+'juror',
+'juster',
+'justly',
+'kaboom',
+'kabuki',
+'kaftan',
+'kaiser',
+'kaolin',
+'kapok',
+'kappa',
+'kaput',
+'karate',
+'karma',
+'karmic',
+'kayak',
+'kazoo',
+'kebab',
+'keeler',
+'keener',
+'kelvin',
+'kennel',
+'kerned',
+'kernel',
+'ketch',
+'ketone',
+'kettle',
+'keypad',
+'khaki',
+'kibble',
+'kibosh',
+'kicky',
+'kiddie',
+'kiddo',
+'kidnap',
+'kidney',
+'killer',
+'kilohm',
+'kilter',
+'kimono',
+'kinda',
+'kindle',
+'kindly',
+'kingly',
+'kinked',
+'kinky',
+'kiosk',
+'kipper',
+'kirsch',
+'kismet',
+'kitbag',
+'kitsch',
+'kitty',
+'klaxon',
+'kludge',
+'knack',
+'knead',
+'kneel',
+'knell',
+'knelt',
+'knick',
+'knife',
+'knight',
+'knish',
+'knives',
+'knobby',
+'knock',
+'knoll',
+'knotty',
+'knower',
+'known',
+'knurl',
+'koala',
+'kooky',
+'kopeck',
+'kopeks',
+'kosher',
+'kowtow',
+'kraal',
+'kraft',
+'krill',
+'krona',
+'krone',
+'kroner',
+'kronor',
+'kronur',
+'kudos',
+'kudzu',
+'kulaks',
+'label',
+'labia',
+'labial',
+'labile',
+'labium',
+'labour',
+'laced',
+'lacer',
+'laces',
+'lacier',
+'lacing',
+'lackey',
+'lactic',
+'lacuna',
+'ladder',
+'laddie',
+'laden',
+'lading',
+'ladle',
+'lagoon',
+'laird',
+'laity',
+'lambda',
+'lamber',
+'lamed',
+'lament',
+'lamina',
+'lamper',
+'lance',
+'lancet',
+'landau',
+'lander',
+'lanky',
+'lapdog',
+'lapel',
+'lapin',
+'lappet',
+'lapse',
+'lapser',
+'laptop',
+'larch',
+'lards',
+'lardy',
+'large',
+'largo',
+'lariat',
+'larker',
+'larva',
+'larvae',
+'larval',
+'larynx',
+'lashed',
+'lasher',
+'lassie',
+'lasso',
+'lasted',
+'lasts',
+'latch',
+'latent',
+'later',
+'latest',
+'latex',
+'lathe',
+'lather',
+'latish',
+'latte',
+'latter',
+'lauder',
+'lauds',
+'launch',
+'laurel',
+'lavage',
+'lavish',
+'lawful',
+'lawyer',
+'laxes',
+'laxity',
+'layer',
+'laying',
+'layman',
+'laymen',
+'layout',
+'layup',
+'lazuli',
+'leach',
+'leaded',
+'leaden',
+'leader',
+'leafy',
+'league',
+'leaker',
+'leaky',
+'leaner',
+'leant',
+'leaper',
+'leapt',
+'learn',
+'learns',
+'learnt',
+'lease',
+'leash',
+'least',
+'leave',
+'leaves',
+'lecher',
+'ledge',
+'leech',
+'leery',
+'leeway',
+'legacy',
+'legal',
+'legato',
+'legend',
+'leggy',
+'legit',
+'legume',
+'lemma',
+'lemme',
+'lemon',
+'lemony',
+'lemur',
+'length',
+'lenser',
+'lentil',
+'lento',
+'leper',
+'lepta',
+'lepton',
+'lesion',
+'lessee',
+'lesser',
+'lessor',
+'lethal',
+'letter',
+'letup',
+'level',
+'levity',
+'lewis',
+'lexeme',
+'liable',
+'liaise',
+'libel',
+'libero',
+'lichee',
+'lichen',
+'licit',
+'licker',
+'lieder',
+'liege',
+'lieut',
+'lieux',
+'ligand',
+'light',
+'lignum',
+'likely',
+'liken',
+'liker',
+'likest',
+'liking',
+'lilac',
+'lilly',
+'limbo',
+'limper',
+'limpet',
+'limpid',
+'linage',
+'linden',
+'lineal',
+'linear',
+'lined',
+'linen',
+'lines',
+'linger',
+'lingo',
+'lining',
+'linked',
+'links',
+'linnet',
+'lintel',
+'linty',
+'lipase',
+'lipid',
+'lippy',
+'liquid',
+'liquor',
+'lisle',
+'lissom',
+'listed',
+'listen',
+'litany',
+'lithe',
+'litmus',
+'litre',
+'litter',
+'little',
+'lived',
+'lively',
+'liven',
+'lives',
+'livest',
+'livid',
+'living',
+'lizard',
+'llama',
+'loads',
+'loamy',
+'loath',
+'loathe',
+'loaves',
+'lobar',
+'lobule',
+'local',
+'locale',
+'lochs',
+'locked',
+'locket',
+'locks',
+'locus',
+'locust',
+'lodge',
+'lodged',
+'lodges',
+'lofter',
+'lofty',
+'loggia',
+'logia',
+'logic',
+'login',
+'logjam',
+'logout',
+'loiter',
+'loller',
+'lolly',
+'lonely',
+'loofah',
+'looked',
+'looks',
+'lookup',
+'loony',
+'looper',
+'loopy',
+'loose',
+'loosed',
+'looses',
+'loper',
+'lordly',
+'loris',
+'lorry',
+'lossy',
+'lotion',
+'lotto',
+'lotus',
+'louden',
+'lounge',
+'loupe',
+'louse',
+'lousy',
+'louvre',
+'loved',
+'lovely',
+'loving',
+'lowish',
+'lowly',
+'loyal',
+'lubber',
+'lucent',
+'lucid',
+'lucky',
+'lucre',
+'luger',
+'lumbar',
+'lumber',
+'lumen',
+'lumpen',
+'lumper',
+'lumpy',
+'lunacy',
+'lunar',
+'lunate',
+'lunch',
+'lunge',
+'lunger',
+'lupin',
+'lupine',
+'lupus',
+'lurch',
+'lurer',
+'lurex',
+'lurid',
+'lustre',
+'lusty',
+'luting',
+'luxury',
+'lyceum',
+'lychee',
+'lying',
+'lymph',
+'lynch',
+'lyric',
+'lyrist',
+'lysine',
+'macaw',
+'macer',
+'macho',
+'macro',
+'macron',
+'madam',
+'madame',
+'madcap',
+'madden',
+'madman',
+'madmen',
+'madras',
+'maggot',
+'magic',
+'magma',
+'magnum',
+'magpie',
+'mahout',
+'maiden',
+'mainly',
+'mains',
+'maize',
+'major',
+'makes',
+'making',
+'malady',
+'malice',
+'malign',
+'mallet',
+'mallow',
+'malted',
+'malty',
+'mamba',
+'mambo',
+'mammal',
+'mammy',
+'manage',
+'mangle',
+'mango',
+'mangy',
+'mania',
+'maniac',
+'manic',
+'manioc',
+'manly',
+'manna',
+'manned',
+'manner',
+'manor',
+'manse',
+'manta',
+'mantel',
+'mantis',
+'mantle',
+'mantra',
+'manual',
+'manure',
+'maple',
+'mapped',
+'maraca',
+'maraud',
+'marble',
+'march',
+'margin',
+'maria',
+'marine',
+'marked',
+'market',
+'markka',
+'marks',
+'marlin',
+'marmot',
+'maroon',
+'marque',
+'marred',
+'marrow',
+'marry',
+'marshy',
+'marten',
+'martin',
+'martyr',
+'marvel',
+'mascot',
+'masked',
+'masks',
+'mason',
+'masque',
+'massif',
+'master',
+'maths',
+'mating',
+'matins',
+'matrix',
+'matron',
+'matte',
+'matter',
+'mature',
+'matzo',
+'mauve',
+'maxim',
+'maxima',
+'maxing',
+'maybe',
+'mayday',
+'mayfly',
+'mayhap',
+'mayhem',
+'mayor',
+'mayst',
+'mazer',
+'meadow',
+'meagre',
+'mealy',
+'meaner',
+'meanie',
+'meanly',
+'meant',
+'measly',
+'meaty',
+'medal',
+'meddle',
+'media',
+'medial',
+'median',
+'medico',
+'medium',
+'medley',
+'meeter',
+'megohm',
+'mellow',
+'melon',
+'melted',
+'melter',
+'melts',
+'member',
+'memoir',
+'memory',
+'mender',
+'menial',
+'meninx',
+'mental',
+'mentor',
+'mercer',
+'merge',
+'merino',
+'merlin',
+'merry',
+'mescal',
+'meshed',
+'meson',
+'messy',
+'metal',
+'meter',
+'method',
+'methyl',
+'metier',
+'metro',
+'mettle',
+'mezzo',
+'miasma',
+'mickey',
+'midday',
+'midden',
+'middle',
+'middy',
+'midge',
+'midget',
+'midrib',
+'midst',
+'midway',
+'mighty',
+'mikado',
+'milady',
+'milch',
+'milden',
+'mildew',
+'miler',
+'milieu',
+'milky',
+'millet',
+'mimer',
+'mimosa',
+'minded',
+'minder',
+'mined',
+'mines',
+'mingle',
+'minim',
+'minima',
+'mining',
+'minion',
+'minke',
+'minnow',
+'minor',
+'minty',
+'minuet',
+'minus',
+'minute',
+'mirage',
+'misery',
+'misfit',
+'mishap',
+'mislay',
+'misled',
+'missal',
+'misses',
+'missus',
+'misty',
+'misuse',
+'mitre',
+'mitten',
+'mixed',
+'mixes',
+'mixing',
+'mizzen',
+'mobber',
+'mocha',
+'mocker',
+'modal',
+'model',
+'modem',
+'modern',
+'modest',
+'modish',
+'moduli',
+'modulo',
+'modus',
+'moggie',
+'mogul',
+'mohair',
+'moiety',
+'moire',
+'moist',
+'molal',
+'molar',
+'molly',
+'molten',
+'moment',
+'momma',
+'monad',
+'money',
+'monger',
+'monies',
+'monism',
+'monkey',
+'monody',
+'month',
+'mooch',
+'moody',
+'moose',
+'mooter',
+'moped',
+'mopish',
+'moppet',
+'moral',
+'morass',
+'moray',
+'morbid',
+'morel',
+'morgue',
+'morose',
+'morph',
+'morris',
+'morrow',
+'morsel',
+'mortal',
+'mortar',
+'mortem',
+'mosaic',
+'mosey',
+'mosque',
+'mossy',
+'motel',
+'motet',
+'mother',
+'motif',
+'motile',
+'motion',
+'motive',
+'motley',
+'mottle',
+'motto',
+'mould',
+'moulds',
+'mouldy',
+'moult',
+'mound',
+'mounts',
+'mouse',
+'mousey',
+'mousse',
+'mousy',
+'mouthy',
+'moved',
+'mover',
+'moves',
+'moving',
+'mowing',
+'mucker',
+'mucky',
+'mucosa',
+'mucous',
+'mucus',
+'muddle',
+'muddy',
+'muesli',
+'muffin',
+'muffle',
+'mufti',
+'muggy',
+'mulch',
+'mulct',
+'mulish',
+'mullah',
+'mullet',
+'multi',
+'mumble',
+'mumbo',
+'mummer',
+'mummy',
+'mumps',
+'munch',
+'munge',
+'mural',
+'murder',
+'murky',
+'murmur',
+'muscat',
+'muscle',
+'muser',
+'museum',
+'mushy',
+'music',
+'muskeg',
+'musky',
+'muslin',
+'mussel',
+'muster',
+'musty',
+'mutant',
+'mutate',
+'muted',
+'mutely',
+'muter',
+'mutest',
+'mutiny',
+'mutter',
+'mutton',
+'mutual',
+'muumuu',
+'muzzle',
+'mynah',
+'myopia',
+'myopic',
+'myriad',
+'myrrh',
+'myself',
+'mystic',
+'nabob',
+'nacho',
+'nacre',
+'nadir',
+'naffer',
+'naiad',
+'naifs',
+'nailer',
+'naive',
+'naked',
+'namby',
+'named',
+'namely',
+'namer',
+'nanny',
+'napalm',
+'napkin',
+'nappy',
+'narky',
+'narrow',
+'nasty',
+'natal',
+'natch',
+'nation',
+'native',
+'natter',
+'natty',
+'nature',
+'nausea',
+'naval',
+'navel',
+'navvy',
+'nearby',
+'neaten',
+'nebula',
+'necker',
+'nectar',
+'needed',
+'needer',
+'needy',
+'negate',
+'neigh',
+'nelson',
+'nephew',
+'nerdy',
+'nerve',
+'nervy',
+'nester',
+'nestle',
+'nether',
+'netter',
+'nettle',
+'neural',
+'neuron',
+'never',
+'newbie',
+'newel',
+'newish',
+'newsy',
+'newton',
+'nexus',
+'niacin',
+'nibble',
+'nicety',
+'niche',
+'nickel',
+'niece',
+'nifty',
+'night',
+'nights',
+'nimbi',
+'nimble',
+'nimbus',
+'ninety',
+'ninja',
+'ninny',
+'nippy',
+'nitwit',
+'nobody',
+'nodal',
+'noddle',
+'noddy',
+'nodule',
+'noggin',
+'nohow',
+'noire',
+'noisy',
+'nomad',
+'nonage',
+'nonce',
+'nones',
+'noodle',
+'noose',
+'normal',
+'north',
+'nosey',
+'nosing',
+'notary',
+'notch',
+'notify',
+'notion',
+'nougat',
+'nought',
+'nounal',
+'novae',
+'novena',
+'novice',
+'noway',
+'nozzle',
+'nuance',
+'nubby',
+'nubile',
+'nuclei',
+'nuder',
+'nudes',
+'nudge',
+'nudger',
+'nugget',
+'number',
+'nuncio',
+'nurse',
+'nurser',
+'nutate',
+'nutmeg',
+'nutria',
+'nutty',
+'nuzzle',
+'nylon',
+'nymph',
+'oafish',
+'oaken',
+'oakum',
+'oases',
+'oasis',
+'oaten',
+'obese',
+'obeyer',
+'oblate',
+'oblige',
+'oblong',
+'oboist',
+'obtuse',
+'occult',
+'occur',
+'ocean',
+'ocelot',
+'ochre',
+'octal',
+'octane',
+'octant',
+'octave',
+'octavo',
+'octet',
+'octile',
+'ocular',
+'oddity',
+'odious',
+'odium',
+'odour',
+'oedema',
+'oeuvre',
+'offal',
+'offer',
+'offing',
+'offish',
+'offset',
+'often',
+'ogive',
+'ogress',
+'ogrish',
+'okapi',
+'olden',
+'oldie',
+'oldish',
+'olefin',
+'olive',
+'omega',
+'omelet',
+'oncer',
+'onion',
+'onrush',
+'onset',
+'onside',
+'onward',
+'oodles',
+'opaque',
+'opened',
+'opens',
+'opiate',
+'opine',
+'opioid',
+'opium',
+'oppose',
+'optic',
+'optics',
+'optima',
+'option',
+'oracle',
+'orang',
+'orate',
+'orator',
+'orchid',
+'ordain',
+'ordeal',
+'ordure',
+'oriel',
+'origin',
+'oriole',
+'orison',
+'ormolu',
+'ornate',
+'orphan',
+'orris',
+'osier',
+'osmium',
+'osprey',
+'ossify',
+'ostler',
+'other',
+'otiose',
+'otter',
+'ought',
+'ounce',
+'outang',
+'outcry',
+'outdo',
+'outer',
+'outfit',
+'outfox',
+'outgo',
+'outing',
+'outlay',
+'output',
+'overdo',
+'overly',
+'overt',
+'owlet',
+'owlish',
+'owned',
+'owner',
+'oxalic',
+'oxbow',
+'oxide',
+'oxtail',
+'oyster',
+'ozone',
+'pacer',
+'paces',
+'pacey',
+'packed',
+'packs',
+'padded',
+'paddle',
+'paddy',
+'padre',
+'paean',
+'paella',
+'paeony',
+'pagan',
+'paged',
+'pagoda',
+'paint',
+'paired',
+'palace',
+'palate',
+'palely',
+'paler',
+'palest',
+'paling',
+'palish',
+'pallid',
+'pallor',
+'palmer',
+'palmy',
+'palsy',
+'paltry',
+'pamby',
+'pampas',
+'panama',
+'panda',
+'pander',
+'panel',
+'panic',
+'panky',
+'pansy',
+'pantry',
+'panzer',
+'papacy',
+'papal',
+'papaw',
+'papaya',
+'papers',
+'papery',
+'papist',
+'papyri',
+'parade',
+'parcel',
+'parch',
+'pardon',
+'parer',
+'parers',
+'pares',
+'pariah',
+'paring',
+'parish',
+'parity',
+'parka',
+'parky',
+'parley',
+'parody',
+'parole',
+'parry',
+'parse',
+'parsec',
+'parsed',
+'parson',
+'parter',
+'partly',
+'parts',
+'party',
+'pascal',
+'pasha',
+'passim',
+'pasta',
+'paste',
+'pastel',
+'paster',
+'pastis',
+'pastor',
+'pastry',
+'pasts',
+'pasty',
+'patch',
+'patchy',
+'paten',
+'patent',
+'pater',
+'pathos',
+'patina',
+'patio',
+'patois',
+'patrol',
+'patten',
+'patter',
+'patty',
+'paunch',
+'pause',
+'paved',
+'paver',
+'paves',
+'paving',
+'pawner',
+'paxes',
+'payee',
+'payer',
+'payout',
+'peace',
+'peach',
+'peachy',
+'peahen',
+'peaky',
+'pealed',
+'peals',
+'peanut',
+'pearl',
+'pearly',
+'peats',
+'peaty',
+'pebble',
+'pebbly',
+'pecan',
+'pectic',
+'pectin',
+'pedal',
+'peddle',
+'pedlar',
+'peeled',
+'peeler',
+'peeve',
+'peewee',
+'pekoe',
+'pelmet',
+'pelter',
+'pelvic',
+'pelvis',
+'penal',
+'pence',
+'pencil',
+'penman',
+'penmen',
+'pennon',
+'penury',
+'peony',
+'people',
+'pepper',
+'peppy',
+'pepsin',
+'peptic',
+'perch',
+'percha',
+'peril',
+'perky',
+'permit',
+'peruke',
+'peruse',
+'peseta',
+'pesky',
+'pestle',
+'pesto',
+'petal',
+'petard',
+'petite',
+'petrel',
+'petrol',
+'petty',
+'pewee',
+'pewit',
+'pewter',
+'peyote',
+'phage',
+'phalli',
+'phase',
+'phenol',
+'phenyl',
+'phial',
+'phlegm',
+'phloem',
+'phlox',
+'phobia',
+'phobic',
+'phoebe',
+'phoney',
+'phonic',
+'phonon',
+'phony',
+'phooey',
+'photo',
+'photon',
+'phrase',
+'phyla',
+'phylum',
+'physic',
+'piano',
+'piazza',
+'picked',
+'picket',
+'pickle',
+'picky',
+'picnic',
+'picot',
+'piddle',
+'pidgin',
+'piece',
+'piecer',
+'pieing',
+'piety',
+'piffle',
+'piggy',
+'piglet',
+'pigsty',
+'pilaf',
+'pilers',
+'pileup',
+'pilfer',
+'piling',
+'pillar',
+'pillow',
+'pimple',
+'pimply',
+'pince',
+'pincer',
+'pinch',
+'pineal',
+'pinged',
+'pinger',
+'pinion',
+'pinkie',
+'pinky',
+'pinna',
+'pinnae',
+'pinned',
+'pious',
+'piping',
+'pipit',
+'pippin',
+'pique',
+'piracy',
+'pisser',
+'piste',
+'pistil',
+'pistol',
+'piston',
+'pitch',
+'pithy',
+'pitman',
+'piton',
+'pixel',
+'pixie',
+'pixmap',
+'pizazz',
+'pizza',
+'placed',
+'placer',
+'placid',
+'plague',
+'plaice',
+'plaid',
+'plains',
+'plaint',
+'plait',
+'planar',
+'plane',
+'planet',
+'plank',
+'plant',
+'plaque',
+'plash',
+'plasm',
+'plasma',
+'plate',
+'platen',
+'played',
+'plays',
+'plaza',
+'please',
+'pleat',
+'pledge',
+'plenty',
+'plenum',
+'pleura',
+'plexus',
+'pliant',
+'pliers',
+'plight',
+'plinth',
+'plover',
+'plucky',
+'plugs',
+'plumb',
+'plume',
+'plummy',
+'plump',
+'plunge',
+'plunk',
+'plural',
+'plush',
+'plushy',
+'poach',
+'pocket',
+'pocus',
+'podgy',
+'podium',
+'poesy',
+'poetic',
+'poetry',
+'pogrom',
+'point',
+'pointy',
+'poise',
+'poison',
+'polar',
+'poler',
+'policy',
+'polio',
+'polish',
+'polite',
+'polka',
+'pollen',
+'poller',
+'pomade',
+'pommel',
+'pompom',
+'ponce',
+'poncho',
+'ponder',
+'pongee',
+'pooch',
+'poodle',
+'popgun',
+'poplar',
+'poplin',
+'poppet',
+'poppy',
+'porch',
+'porky',
+'porous',
+'portal',
+'porter',
+'portly',
+'poser',
+'poseur',
+'posing',
+'posses',
+'possum',
+'postal',
+'posted',
+'poster',
+'posts',
+'potage',
+'potash',
+'potato',
+'potent',
+'potful',
+'potion',
+'potty',
+'pouch',
+'pouffe',
+'pounce',
+'pound',
+'pourri',
+'powder',
+'power',
+'powwow',
+'praise',
+'prank',
+'prawn',
+'praxes',
+'praxis',
+'prayer',
+'preach',
+'precut',
+'preen',
+'prefab',
+'prefix',
+'premed',
+'premix',
+'press',
+'presto',
+'pretty',
+'price',
+'priced',
+'pricer',
+'pricey',
+'priest',
+'primal',
+'prime',
+'primp',
+'prince',
+'print',
+'prints',
+'prions',
+'prior',
+'priori',
+'priory',
+'prise',
+'priser',
+'prism',
+'prissy',
+'privet',
+'privy',
+'prize',
+'prober',
+'prolix',
+'promo',
+'prompt',
+'prone',
+'prong',
+'pronto',
+'proof',
+'proper',
+'prose',
+'proser',
+'prosy',
+'protea',
+'proton',
+'proud',
+'prove',
+'proved',
+'proven',
+'proves',
+'prowl',
+'proxy',
+'prune',
+'pseudo',
+'pshaw',
+'psych',
+'psyche',
+'psycho',
+'psychs',
+'puddle',
+'pudgy',
+'pueblo',
+'puffer',
+'puffin',
+'puffy',
+'pukka',
+'pullet',
+'pulley',
+'pulper',
+'pulpit',
+'pulpy',
+'pulsar',
+'pulse',
+'pulsed',
+'pulser',
+'pulses',
+'pumice',
+'pummel',
+'pumper',
+'punchy',
+'pundit',
+'punky',
+'punnet',
+'pupae',
+'pupal',
+'pupate',
+'pupil',
+'puppy',
+'purdah',
+'purge',
+'purine',
+'purism',
+'purist',
+'purity',
+'purple',
+'purse',
+'pursue',
+'purvey',
+'pushy',
+'putrid',
+'putsch',
+'puttee',
+'putter',
+'putty',
+'pygmy',
+'pyjama',
+'pyknic',
+'pylon',
+'pylori',
+'pyrite',
+'python',
+'pyxis',
+'quack',
+'quaff',
+'quail',
+'quaint',
+'quake',
+'quaky',
+'qualm',
+'quango',
+'quanta',
+'quark',
+'quarry',
+'quart',
+'quarto',
+'quartz',
+'quasar',
+'quash',
+'quasi',
+'quaver',
+'queasy',
+'queen',
+'queer',
+'quell',
+'quench',
+'quern',
+'query',
+'quest',
+'quests',
+'queue',
+'queuer',
+'quiche',
+'quick',
+'quiet',
+'quiff',
+'quill',
+'quilt',
+'quince',
+'quinsy',
+'quint',
+'quire',
+'quirk',
+'quirky',
+'quirt',
+'quite',
+'quiver',
+'quizzy',
+'quoin',
+'quoit',
+'quorum',
+'quoted',
+'quoter',
+'quoth',
+'qwerty',
+'rabbi',
+'rabble',
+'rabid',
+'rabies',
+'raceme',
+'racism',
+'racket',
+'radar',
+'radial',
+'radian',
+'radii',
+'radish',
+'radium',
+'radius',
+'radix',
+'radon',
+'raffia',
+'raffle',
+'ragbag',
+'ragged',
+'raglan',
+'ragout',
+'ragtag',
+'railer',
+'rainy',
+'raise',
+'raisin',
+'raison',
+'rajah',
+'raker',
+'rakish',
+'rally',
+'ramie',
+'ramjet',
+'ranch',
+'rancid',
+'ranee',
+'range',
+'rangy',
+'ranked',
+'ranker',
+'rankle',
+'rapid',
+'rapier',
+'rapine',
+'rappel',
+'rarefy',
+'rarity',
+'rascal',
+'rasper',
+'raspy',
+'raster',
+'rather',
+'rating',
+'ratio',
+'ration',
+'rattan',
+'rattle',
+'rattly',
+'ratty',
+'ravage',
+'ravel',
+'raven',
+'ravine',
+'rayon',
+'razor',
+'reach',
+'react',
+'reacts',
+'reader',
+'reads',
+'ready',
+'realm',
+'rebate',
+'rebel',
+'rebook',
+'rebut',
+'recall',
+'recap',
+'recent',
+'recipe',
+'recite',
+'reckon',
+'recoil',
+'recopy',
+'record',
+'recoup',
+'rector',
+'recur',
+'recurs',
+'redact',
+'redbud',
+'redcap',
+'redden',
+'redeem',
+'redial',
+'redraw',
+'reedy',
+'reeve',
+'refile',
+'refill',
+'refine',
+'refit',
+'reflex',
+'refuge',
+'refund',
+'refuse',
+'regain',
+'regale',
+'regard',
+'reggae',
+'regime',
+'regrow',
+'rehab',
+'rehang',
+'rehear',
+'reheat',
+'rehire',
+'reign',
+'reject',
+'rejoin',
+'reknit',
+'relax',
+'relay',
+'relic',
+'relict',
+'relief',
+'reline',
+'relish',
+'relit',
+'reload',
+'relock',
+'remain',
+'remake',
+'remand',
+'remap',
+'remark',
+'remelt',
+'remind',
+'remiss',
+'remit',
+'remix',
+'remote',
+'remove',
+'render',
+'renege',
+'rennet',
+'rennin',
+'renown',
+'rental',
+'reopen',
+'repack',
+'repair',
+'repast',
+'repave',
+'repeal',
+'repel',
+'repent',
+'replay',
+'reply',
+'report',
+'repose',
+'repost',
+'reread',
+'resat',
+'rescue',
+'resent',
+'reset',
+'reship',
+'resift',
+'resign',
+'resin',
+'resiny',
+'resole',
+'result',
+'resume',
+'retail',
+'retain',
+'retch',
+'retest',
+'retina',
+'retool',
+'retort',
+'retro',
+'retry',
+'retune',
+'revamp',
+'revere',
+'revet',
+'revile',
+'revise',
+'revive',
+'revue',
+'rewash',
+'rewed',
+'rewind',
+'rhesus',
+'rheum',
+'rheumy',
+'rhino',
+'rhyme',
+'ribald',
+'ribbon',
+'richen',
+'ridden',
+'riddle',
+'rider',
+'riders',
+'ridge',
+'ridgy',
+'riding',
+'riffle',
+'rifled',
+'rigger',
+'right',
+'rights',
+'rigid',
+'rigour',
+'rinse',
+'rinser',
+'ripely',
+'riper',
+'ripple',
+'ripply',
+'ripsaw',
+'risen',
+'risky',
+'ritual',
+'ritzy',
+'riven',
+'river',
+'riyal',
+'roach',
+'roadie',
+'roast',
+'robber',
+'robed',
+'robin',
+'robot',
+'robust',
+'rocker',
+'rocky',
+'rococo',
+'rodent',
+'rodeo',
+'roger',
+'rogue',
+'roller',
+'rondo',
+'rookie',
+'roomy',
+'roost',
+'ropey',
+'rosary',
+'roster',
+'rotary',
+'rotate',
+'rotor',
+'rotten',
+'rotter',
+'rotund',
+'rouble',
+'rouge',
+'rough',
+'rouse',
+'rouser',
+'roust',
+'route',
+'rowdy',
+'rowel',
+'royal',
+'rubati',
+'rubato',
+'rubber',
+'rubble',
+'rubout',
+'rubric',
+'ruddy',
+'ruffle',
+'rugby',
+'ruled',
+'ruler',
+'ruling',
+'rumba',
+'rumble',
+'rumen',
+'rummer',
+'rummy',
+'rumour',
+'rumple',
+'rumply',
+'rumpus',
+'runlet',
+'runnel',
+'runner',
+'runny',
+'runty',
+'runway',
+'rupee',
+'rupiah',
+'rural',
+'rushy',
+'russet',
+'rustic',
+'rustle',
+'rustre',
+'rutty',
+'sable',
+'sabot',
+'sabra',
+'sabre',
+'sachem',
+'sachet',
+'sacker',
+'sacra',
+'sacral',
+'sacred',
+'sacrum',
+'sadden',
+'saddle',
+'safari',
+'safely',
+'safety',
+'sagely',
+'saggy',
+'sahib',
+'sailor',
+'saint',
+'saker',
+'salaam',
+'salad',
+'salami',
+'salary',
+'saline',
+'sallow',
+'sally',
+'salmon',
+'salon',
+'saloon',
+'salsa',
+'salted',
+'salts',
+'salty',
+'salvo',
+'samba',
+'sampan',
+'sample',
+'sandal',
+'sander',
+'sandy',
+'sanely',
+'sappy',
+'sarong',
+'sateen',
+'satin',
+'satiny',
+'satori',
+'satrap',
+'satyr',
+'saucer',
+'saucy',
+'sauna',
+'savant',
+'saved',
+'savour',
+'savoy',
+'sawfly',
+'sawyer',
+'saying',
+'scabby',
+'scalar',
+'scald',
+'scale',
+'scaled',
+'scales',
+'scalp',
+'scaly',
+'scamp',
+'scampi',
+'scans',
+'scanty',
+'scape',
+'scarab',
+'scarce',
+'scarer',
+'scarf',
+'scarp',
+'scary',
+'scathe',
+'scent',
+'schema',
+'scheme',
+'schism',
+'schist',
+'schizo',
+'school',
+'schuss',
+'schwa',
+'scion',
+'scoff',
+'scold',
+'sconce',
+'scone',
+'scoot',
+'scope',
+'scored',
+'scores',
+'scotch',
+'scour',
+'scout',
+'scowl',
+'scrag',
+'scram',
+'scrap',
+'scrape',
+'scrawl',
+'scree',
+'screed',
+'screen',
+'screw',
+'screwy',
+'scribe',
+'scrim',
+'scrimp',
+'scrip',
+'script',
+'scroll',
+'scrub',
+'scrum',
+'scuba',
+'scuff',
+'scull',
+'sculpt',
+'scummy',
+'scurf',
+'scurfy',
+'scurry',
+'scurvy',
+'scythe',
+'seabed',
+'sealer',
+'seaman',
+'seamer',
+'seance',
+'season',
+'seater',
+'seaway',
+'secant',
+'secede',
+'second',
+'secret',
+'sector',
+'sects',
+'secure',
+'sedan',
+'sedge',
+'sedgy',
+'seeded',
+'seeder',
+'seedy',
+'seeing',
+'seemly',
+'seethe',
+'segue',
+'seine',
+'seisin',
+'seize',
+'seldom',
+'select',
+'seller',
+'selves',
+'sempre',
+'senate',
+'sender',
+'senile',
+'senior',
+'senna',
+'sense',
+'sensor',
+'sentry',
+'sepal',
+'sepia',
+'sepoy',
+'sepses',
+'sepsis',
+'septa',
+'septet',
+'septum',
+'sequel',
+'sequin',
+'serape',
+'serene',
+'serge',
+'series',
+'serif',
+'sermon',
+'serous',
+'serum',
+'serve',
+'served',
+'server',
+'serves',
+'servo',
+'sesame',
+'settee',
+'settle',
+'seven',
+'severe',
+'sewage',
+'sewer',
+'sexpot',
+'sextet',
+'sexton',
+'shabby',
+'shack',
+'shaded',
+'shady',
+'shaft',
+'shaggy',
+'shake',
+'shaken',
+'shaky',
+'shale',
+'shall',
+'shalom',
+'shaman',
+'shandy',
+'shank',
+'shanty',
+'shaped',
+'shapes',
+'shard',
+'share',
+'shared',
+'shark',
+'sharp',
+'shave',
+'shaven',
+'shawl',
+'shawm',
+'shchi',
+'sheaf',
+'shear',
+'sheath',
+'sheave',
+'sheen',
+'sheeny',
+'sheep',
+'sheer',
+'sheet',
+'sheik',
+'sheikh',
+'shekel',
+'shelf',
+'shell',
+'shelve',
+'sherds',
+'sherry',
+'shield',
+'shifty',
+'shimmy',
+'shine',
+'shiny',
+'ships',
+'shire',
+'shirk',
+'shirr',
+'shirt',
+'shiver',
+'shoal',
+'shoat',
+'shoddy',
+'shogun',
+'shone',
+'shook',
+'shoot',
+'shoots',
+'shore',
+'shorn',
+'short',
+'shorty',
+'shots',
+'should',
+'shout',
+'shouts',
+'shove',
+'showed',
+'shower',
+'shown',
+'shows',
+'showy',
+'shrank',
+'shred',
+'shrew',
+'shrewd',
+'shriek',
+'shrift',
+'shrike',
+'shrill',
+'shrimp',
+'shrine',
+'shrink',
+'shrive',
+'shroud',
+'shrub',
+'shrug',
+'shrunk',
+'shtick',
+'shunt',
+'shush',
+'shyer',
+'shyest',
+'shyly',
+'sicken',
+'sickie',
+'sickly',
+'sided',
+'sides',
+'siding',
+'sidle',
+'siege',
+'sienna',
+'sierra',
+'siesta',
+'sieve',
+'sifted',
+'sifts',
+'sigma',
+'signet',
+'signor',
+'signs',
+'silage',
+'silent',
+'silica',
+'silken',
+'silky',
+'silly',
+'silty',
+'simian',
+'simile',
+'simmer',
+'simon',
+'simony',
+'simoom',
+'simper',
+'simple',
+'since',
+'sinew',
+'sinful',
+'singe',
+'single',
+'sinter',
+'sinus',
+'siphon',
+'siren',
+'sisal',
+'sissy',
+'sister',
+'sitcom',
+'sitter',
+'sixer',
+'sixth',
+'sixty',
+'sized',
+'sizes',
+'sizing',
+'sizzle',
+'skate',
+'skeet',
+'skein',
+'skewer',
+'skiff',
+'skill',
+'skimpy',
+'skinny',
+'skirt',
+'skirts',
+'skivvy',
+'skulk',
+'skull',
+'skunk',
+'skyway',
+'slack',
+'slain',
+'slake',
+'slalom',
+'slang',
+'slangy',
+'slant',
+'slash',
+'slate',
+'slaver',
+'sledge',
+'sleek',
+'sleeps',
+'sleepy',
+'sleet',
+'sleety',
+'sleeve',
+'sleigh',
+'slept',
+'sleuth',
+'slice',
+'slick',
+'slide',
+'slime',
+'slimy',
+'sling',
+'slink',
+'slinky',
+'sliver',
+'slogan',
+'sloop',
+'slope',
+'sloppy',
+'slosh',
+'slouch',
+'slough',
+'sloven',
+'sludge',
+'sludgy',
+'sluice',
+'slummy',
+'slump',
+'slung',
+'slunk',
+'slurp',
+'slurry',
+'slushy',
+'slyly',
+'smack',
+'small',
+'smarmy',
+'smart',
+'smarts',
+'smear',
+'smell',
+'smelly',
+'smelt',
+'smiler',
+'smiley',
+'smirch',
+'smirk',
+'smite',
+'smiter',
+'smithy',
+'smock',
+'smoggy',
+'smoke',
+'smoky',
+'smooch',
+'smote',
+'smudgy',
+'snack',
+'snafu',
+'snail',
+'snake',
+'snaky',
+'snappy',
+'snaps',
+'snare',
+'snarer',
+'snarly',
+'snatch',
+'snazzy',
+'sneaky',
+'sneeze',
+'snick',
+'snide',
+'sniff',
+'snipe',
+'snippy',
+'snitch',
+'snivel',
+'snobby',
+'snood',
+'snook',
+'snoop',
+'snoopy',
+'snooty',
+'snooze',
+'snore',
+'snort',
+'snotty',
+'snout',
+'snowy',
+'snuff',
+'soaker',
+'soapy',
+'soarer',
+'soccer',
+'socio',
+'sodden',
+'sodium',
+'soever',
+'soften',
+'softer',
+'softly',
+'softy',
+'soggy',
+'soiled',
+'soiree',
+'solace',
+'solar',
+'solder',
+'soled',
+'solely',
+'soles',
+'solid',
+'soling',
+'solute',
+'solve',
+'solved',
+'sombre',
+'sonar',
+'sonata',
+'sonnet',
+'sonny',
+'soothe',
+'sooty',
+'soppy',
+'sorbet',
+'sordid',
+'sorrel',
+'sorrow',
+'sorry',
+'sorted',
+'sorter',
+'sortie',
+'sough',
+'sought',
+'sound',
+'soupy',
+'source',
+'souse',
+'south',
+'soviet',
+'sower',
+'spacey',
+'spadix',
+'spank',
+'spare',
+'spark',
+'sparky',
+'spars',
+'sparse',
+'spasm',
+'spate',
+'spathe',
+'spatio',
+'spavin',
+'spawn',
+'speak',
+'speaks',
+'spear',
+'specie',
+'speck',
+'speedy',
+'spell',
+'spelt',
+'spend',
+'spent',
+'sphinx',
+'spice',
+'spicy',
+'spider',
+'spiel',
+'spiffy',
+'spigot',
+'spike',
+'spiky',
+'spill',
+'spilt',
+'spinal',
+'spinet',
+'spiny',
+'spiral',
+'spire',
+'spired',
+'spires',
+'spirit',
+'spiry',
+'spite',
+'splat',
+'splay',
+'spleen',
+'splice',
+'spline',
+'splint',
+'split',
+'spoil',
+'spoilt',
+'spoken',
+'spongy',
+'spoof',
+'spook',
+'spooky',
+'spool',
+'spoor',
+'spore',
+'sporty',
+'spots',
+'spotty',
+'spouse',
+'spout',
+'sprain',
+'sprang',
+'sprat',
+'sprawl',
+'spray',
+'spree',
+'sprig',
+'sprint',
+'sprite',
+'sprout',
+'spruce',
+'sprue',
+'sprung',
+'spryer',
+'spryly',
+'spume',
+'spumy',
+'spurge',
+'spurn',
+'spurt',
+'sputa',
+'squab',
+'squad',
+'squall',
+'square',
+'squash',
+'squat',
+'squaw',
+'squawk',
+'squeal',
+'squib',
+'squid',
+'squint',
+'squire',
+'squirl',
+'squirm',
+'squirt',
+'stably',
+'stadia',
+'staff',
+'stager',
+'stagy',
+'staid',
+'stair',
+'stake',
+'stale',
+'stalk',
+'stall',
+'stamen',
+'stamp',
+'stance',
+'stank',
+'stanza',
+'staple',
+'stare',
+'stark',
+'starry',
+'start',
+'starts',
+'starve',
+'stash',
+'stasis',
+'state',
+'stated',
+'stater',
+'states',
+'static',
+'stator',
+'statue',
+'status',
+'stave',
+'stayer',
+'stead',
+'steady',
+'steak',
+'steal',
+'steamy',
+'steed',
+'steel',
+'steely',
+'steep',
+'steers',
+'stein',
+'stench',
+'steno',
+'steppe',
+'stereo',
+'stern',
+'sticky',
+'stiff',
+'stigma',
+'stile',
+'still',
+'stingy',
+'stink',
+'stinky',
+'stint',
+'stitch',
+'stoat',
+'stock',
+'stodgy',
+'stoic',
+'stoke',
+'stole',
+'stolen',
+'stolid',
+'stolon',
+'stoma',
+'stomal',
+'stomp',
+'stoner',
+'stony',
+'stood',
+'stooge',
+'stool',
+'stoop',
+'store',
+'storer',
+'storey',
+'stork',
+'stormy',
+'story',
+'stoup',
+'stout',
+'stove',
+'strafe',
+'strain',
+'strait',
+'strand',
+'strap',
+'strata',
+'strati',
+'straw',
+'stray',
+'streak',
+'stream',
+'street',
+'strew',
+'strewn',
+'stria',
+'striae',
+'stride',
+'strife',
+'strim',
+'string',
+'strip',
+'stripe',
+'strive',
+'strobe',
+'strode',
+'stroke',
+'stroll',
+'strop',
+'strove',
+'struck',
+'strum',
+'strung',
+'strut',
+'stubby',
+'stucco',
+'stuck',
+'studio',
+'stuff',
+'stuffs',
+'stuffy',
+'stump',
+'stumpy',
+'stung',
+'stunk',
+'stupid',
+'stupor',
+'sturdy',
+'style',
+'styler',
+'styli',
+'stylus',
+'stymie',
+'suave',
+'subdue',
+'sublet',
+'submit',
+'subnet',
+'suborn',
+'subset',
+'subtle',
+'subtly',
+'suburb',
+'subway',
+'sucker',
+'suckle',
+'sudden',
+'sudsy',
+'suede',
+'sugar',
+'sugary',
+'suite',
+'suited',
+'suitor',
+'sulky',
+'sullen',
+'sully',
+'sultan',
+'sultry',
+'sumac',
+'summon',
+'sundae',
+'sunder',
+'sundry',
+'sunken',
+'sunlit',
+'sunny',
+'sunset',
+'suntan',
+'super',
+'superb',
+'supine',
+'supple',
+'supply',
+'supra',
+'surer',
+'surety',
+'surge',
+'surly',
+'surtax',
+'survey',
+'sushi',
+'sutler',
+'suture',
+'svelte',
+'swain',
+'swami',
+'swampy',
+'swanky',
+'sward',
+'swarm',
+'swart',
+'swash',
+'swatch',
+'swath',
+'swathe',
+'swear',
+'sweaty',
+'swede',
+'sweet',
+'swell',
+'swept',
+'swerve',
+'swift',
+'swill',
+'swine',
+'swipe',
+'swirl',
+'swirly',
+'swish',
+'switch',
+'swivel',
+'swizz',
+'swoon',
+'swoop',
+'swoosh',
+'swore',
+'sworn',
+'swung',
+'sylph',
+'sylvan',
+'synch',
+'syndic',
+'synod',
+'syntax',
+'syphon',
+'syrup',
+'syrupy',
+'syzygy',
+'tabby',
+'tabla',
+'table',
+'tablet',
+'taboo',
+'tabor',
+'tacit',
+'tackle',
+'tacky',
+'tactic',
+'tagged',
+'taiga',
+'taint',
+'taken',
+'taker',
+'talcum',
+'talkie',
+'talky',
+'tallow',
+'tally',
+'talon',
+'talus',
+'tamale',
+'tamed',
+'tamper',
+'tandem',
+'tangle',
+'tango',
+'tangy',
+'tanned',
+'tannin',
+'tansy',
+'tantra',
+'taper',
+'tapir',
+'tapped',
+'tappet',
+'tardy',
+'target',
+'tariff',
+'tarmac',
+'tarot',
+'tarpon',
+'tarry',
+'tarsal',
+'tarsi',
+'tarsus',
+'tartan',
+'tartar',
+'tassel',
+'tastes',
+'tasty',
+'tatter',
+'tattle',
+'tattoo',
+'taught',
+'taupe',
+'tavern',
+'tawdry',
+'tawny',
+'taxer',
+'taxies',
+'taxing',
+'teabag',
+'teapot',
+'tease',
+'teasel',
+'teazel',
+'teazle',
+'techs',
+'teddy',
+'tedium',
+'teens',
+'teeny',
+'teepee',
+'teeter',
+'teeth',
+'teethe',
+'telex',
+'teller',
+'telly',
+'temper',
+'tempi',
+'temple',
+'tempo',
+'tempt',
+'tenant',
+'tench',
+'tended',
+'tendon',
+'tends',
+'tenet',
+'tenner',
+'tennis',
+'tenon',
+'tenor',
+'tenpin',
+'tense',
+'tensor',
+'tenter',
+'tenth',
+'tents',
+'tenure',
+'tepee',
+'tepid',
+'tercel',
+'terns',
+'terry',
+'terse',
+'tested',
+'tests',
+'testy',
+'tetchy',
+'tether',
+'tetra',
+'thane',
+'thatch',
+'theft',
+'their',
+'theism',
+'theist',
+'theme',
+'thence',
+'there',
+'therm',
+'these',
+'thesis',
+'theta',
+'thick',
+'thief',
+'thieve',
+'thigh',
+'thine',
+'thing',
+'think',
+'third',
+'thirst',
+'thirty',
+'thole',
+'thorax',
+'thorny',
+'those',
+'though',
+'thrall',
+'thrash',
+'thread',
+'threat',
+'three',
+'thresh',
+'threw',
+'thrice',
+'throb',
+'throe',
+'throne',
+'throng',
+'throw',
+'thrown',
+'thrum',
+'thrush',
+'thrust',
+'thumb',
+'thump',
+'thunk',
+'thwack',
+'thwart',
+'thyme',
+'thymus',
+'tiara',
+'tibia',
+'tibiae',
+'tickle',
+'tidal',
+'tiger',
+'tight',
+'tilde',
+'tiled',
+'tilled',
+'tiller',
+'tilth',
+'timber',
+'timbre',
+'timed',
+'timely',
+'timer',
+'timid',
+'timing',
+'tinder',
+'tinge',
+'tingle',
+'tingly',
+'tinker',
+'tinkle',
+'tinny',
+'tinpot',
+'tinsel',
+'tippet',
+'tipple',
+'tipsy',
+'tiptoe',
+'tiptop',
+'tirade',
+'tired',
+'tiring',
+'tissue',
+'titan',
+'titbit',
+'tithe',
+'title',
+'titled',
+'titre',
+'titter',
+'tittle',
+'tizzy',
+'toady',
+'toast',
+'toasty',
+'tocsin',
+'today',
+'toddle',
+'toddy',
+'toecap',
+'toffee',
+'toggle',
+'toilet',
+'toity',
+'token',
+'tomato',
+'tomboy',
+'tomcat',
+'tomtit',
+'tonal',
+'toned',
+'toner',
+'tongue',
+'tonic',
+'toning',
+'tonne',
+'tonsil',
+'tooled',
+'tools',
+'tooth',
+'toothy',
+'tootle',
+'toots',
+'tootsy',
+'topaz',
+'toper',
+'topic',
+'topple',
+'toque',
+'torch',
+'toroid',
+'torpid',
+'torpor',
+'torque',
+'torrid',
+'torso',
+'torte',
+'torus',
+'total',
+'totem',
+'totter',
+'toucan',
+'touch',
+'touchy',
+'tough',
+'toupee',
+'tourer',
+'tousle',
+'toward',
+'towbar',
+'towel',
+'tower',
+'townee',
+'townie',
+'toxic',
+'toxin',
+'trace',
+'traced',
+'traces',
+'tracts',
+'tragic',
+'trail',
+'trails',
+'train',
+'trains',
+'trait',
+'traits',
+'tramp',
+'trance',
+'trashy',
+'trauma',
+'travel',
+'trawl',
+'tread',
+'treat',
+'treats',
+'treaty',
+'treble',
+'tremor',
+'trench',
+'trendy',
+'trews',
+'triad',
+'triage',
+'tribal',
+'trice',
+'tricky',
+'tried',
+'tries',
+'trifle',
+'trike',
+'trilby',
+'trill',
+'triode',
+'tripe',
+'triple',
+'triply',
+'tripod',
+'tripos',
+'trite',
+'triune',
+'trivet',
+'trivia',
+'troika',
+'troll',
+'tromp',
+'troop',
+'trophy',
+'tropic',
+'troth',
+'trough',
+'troupe',
+'trout',
+'trove',
+'trowel',
+'truant',
+'truce',
+'truck',
+'trudge',
+'truism',
+'truly',
+'trump',
+'trunk',
+'truss',
+'trusty',
+'truth',
+'tryst',
+'tsetse',
+'tubby',
+'tubing',
+'tubule',
+'tucker',
+'tulip',
+'tulle',
+'tumble',
+'tumid',
+'tummy',
+'tumour',
+'tumult',
+'tundra',
+'tuned',
+'tunes',
+'tunic',
+'tuning',
+'tunnel',
+'tunny',
+'tupelo',
+'turban',
+'turbid',
+'turbo',
+'turbot',
+'tureen',
+'turfy',
+'turgid',
+'turkey',
+'turned',
+'turner',
+'turnip',
+'turret',
+'turtle',
+'turvy',
+'tussle',
+'tutor',
+'tutti',
+'tuxedo',
+'twain',
+'twang',
+'twangy',
+'tweak',
+'tweed',
+'tweedy',
+'tweet',
+'tweeze',
+'twelve',
+'twenty',
+'twerp',
+'twice',
+'twiggy',
+'twilit',
+'twill',
+'twine',
+'twinge',
+'twirl',
+'twist',
+'twisty',
+'twitch',
+'tycoon',
+'typed',
+'typhus',
+'typify',
+'tyrant',
+'tyred',
+'ukase',
+'ulcer',
+'ulnae',
+'ulnar',
+'ulster',
+'ultimo',
+'ultra',
+'umbel',
+'umber',
+'umbra',
+'umbrae',
+'umlaut',
+'umpire',
+'unable',
+'unary',
+'unban',
+'unbar',
+'unbend',
+'unbolt',
+'uncial',
+'unclad',
+'uncle',
+'uncool',
+'uncork',
+'uncurl',
+'uncut',
+'under',
+'undue',
+'unease',
+'uneven',
+'unfair',
+'unfelt',
+'unfit',
+'unfix',
+'unhand',
+'unholy',
+'unhurt',
+'union',
+'unique',
+'unisex',
+'unison',
+'unite',
+'unity',
+'unjust',
+'unkind',
+'unkink',
+'unlace',
+'unlap',
+'unlike',
+'unlink',
+'unlit',
+'unload',
+'unlock',
+'unmake',
+'unmask',
+'unmesh',
+'unmet',
+'unpack',
+'unpick',
+'unpin',
+'unplug',
+'unread',
+'unreal',
+'unrest',
+'unruly',
+'unsafe',
+'unset',
+'unshod',
+'unsnap',
+'unsure',
+'unties',
+'until',
+'untrue',
+'unwind',
+'unwire',
+'unyoke',
+'upbeat',
+'update',
+'upend',
+'upheld',
+'uphill',
+'uphold',
+'upkeep',
+'upland',
+'uplift',
+'uplink',
+'upload',
+'upped',
+'upper',
+'upping',
+'uppish',
+'uppity',
+'uprate',
+'uproar',
+'uproot',
+'upset',
+'upshot',
+'upside',
+'uptake',
+'uptime',
+'uptown',
+'upturn',
+'upward',
+'upwind',
+'uracil',
+'urban',
+'urbane',
+'urchin',
+'ureter',
+'urgent',
+'urinal',
+'ursine',
+'usable',
+'usage',
+'useful',
+'using',
+'usual',
+'usurer',
+'usury',
+'utile',
+'utmost',
+'utopia',
+'utter',
+'uvula',
+'uvular',
+'vacant',
+'vacate',
+'vacua',
+'vacuum',
+'vagary',
+'vague',
+'valet',
+'valise',
+'valley',
+'valour',
+'valued',
+'valuer',
+'values',
+'vamped',
+'vamps',
+'vandal',
+'vanity',
+'vapid',
+'vapour',
+'varied',
+'varlet',
+'vassal',
+'vault',
+'vaunt',
+'vector',
+'vegan',
+'veggie',
+'velar',
+'veldt',
+'vellum',
+'velour',
+'velum',
+'velvet',
+'vendor',
+'venial',
+'venom',
+'venous',
+'vented',
+'venue',
+'verbal',
+'verge',
+'verger',
+'verify',
+'verity',
+'vermin',
+'vernal',
+'versa',
+'verse',
+'versed',
+'verso',
+'versus',
+'vertex',
+'verve',
+'vesper',
+'vessel',
+'vestal',
+'vetch',
+'vetoes',
+'viable',
+'viand',
+'vicar',
+'victor',
+'video',
+'views',
+'vigil',
+'vigour',
+'viking',
+'viler',
+'vilify',
+'villa',
+'villi',
+'villus',
+'vinous',
+'vinyl',
+'violet',
+'violin',
+'viper',
+'virago',
+'viral',
+'vireo',
+'virus',
+'visage',
+'viscid',
+'viscus',
+'vision',
+'visit',
+'visits',
+'visor',
+'vista',
+'visual',
+'vitae',
+'vitro',
+'vivace',
+'vivid',
+'vivify',
+'vixen',
+'vizier',
+'vocab',
+'vodka',
+'vogue',
+'voice',
+'voiced',
+'voices',
+'voided',
+'voids',
+'voile',
+'volley',
+'volte',
+'volume',
+'volute',
+'voodoo',
+'vortex',
+'votary',
+'vouch',
+'vowel',
+'voyage',
+'vulgar',
+'wacky',
+'waddle',
+'wafer',
+'waffle',
+'wager',
+'waggle',
+'wagon',
+'wailer',
+'waist',
+'waive',
+'waken',
+'wakeup',
+'walkie',
+'wallet',
+'wallop',
+'wallow',
+'walnut',
+'walrus',
+'waltz',
+'wampum',
+'wander',
+'wangle',
+'wanted',
+'wanton',
+'wapiti',
+'warble',
+'warded',
+'warden',
+'warder',
+'warier',
+'warmer',
+'warmly',
+'warmth',
+'warren',
+'washed',
+'washes',
+'waste',
+'watery',
+'wattle',
+'waver',
+'waxen',
+'waylay',
+'weaken',
+'wealth',
+'wearer',
+'wears',
+'weasel',
+'weave',
+'weaves',
+'wedded',
+'wedge',
+'weedy',
+'weekly',
+'weenie',
+'weensy',
+'weeny',
+'weepy',
+'weevil',
+'weigh',
+'weight',
+'weird',
+'welled',
+'wells',
+'welsh',
+'welter',
+'wench',
+'whack',
+'whale',
+'wharf',
+'wheal',
+'wheat',
+'wheel',
+'wheeze',
+'wheezy',
+'whelk',
+'whelm',
+'whelp',
+'whence',
+'where',
+'which',
+'whiff',
+'while',
+'whilom',
+'whilst',
+'whims',
+'whimsy',
+'whinny',
+'whiny',
+'whirl',
+'whirr',
+'whisk',
+'whisky',
+'whist',
+'white',
+'whiten',
+'whitey',
+'whole',
+'wholly',
+'whoop',
+'whoosh',
+'whorl',
+'whose',
+'whoso',
+'wicked',
+'wicket',
+'widen',
+'widget',
+'widow',
+'width',
+'wield',
+'wifely',
+'wiggle',
+'wiggly',
+'wigwag',
+'wigwam',
+'wilder',
+'wilful',
+'willed',
+'willow',
+'wimple',
+'wimpy',
+'wince',
+'winch',
+'winds',
+'windy',
+'winery',
+'winkle',
+'winnow',
+'winter',
+'wintry',
+'wired',
+'wirer',
+'wiring',
+'wisdom',
+'wised',
+'wiser',
+'wises',
+'wisest',
+'wising',
+'wispy',
+'withal',
+'wither',
+'within',
+'witty',
+'wives',
+'wizen',
+'wobbly',
+'woken',
+'wolves',
+'woman',
+'wombat',
+'women',
+'wonky',
+'wooden',
+'woods',
+'woody',
+'woolly',
+'woozy',
+'wordy',
+'worker',
+'wormer',
+'wormy',
+'worse',
+'worsen',
+'worst',
+'worthy',
+'would',
+'wound',
+'wounds',
+'woven',
+'wrack',
+'wraith',
+'wrasse',
+'wreak',
+'wreath',
+'wreck',
+'wrest',
+'wring',
+'write',
+'writes',
+'writhe',
+'wrong',
+'wroth',
+'wrung',
+'wryer',
+'wryest',
+'wryly',
+'wurzel',
+'xenon',
+'xylem',
+'xylol',
+'yammer',
+'yarrow',
+'yeasty',
+'yellow',
+'yeoman',
+'yeomen',
+'yield',
+'yikes',
+'yippee',
+'yobbo',
+'yodel',
+'yoked',
+'yokel',
+'yokes',
+'yoking',
+'yonder',
+'young',
+'youth',
+'yucca',
+'yucky',
+'yummy',
+'yuppie',
+'zealot',
+'zebra',
+'zenith',
+'zephyr',
+'zeroes',
+'zeugma',
+'zigzag',
+'zilch',
+'zinnia',
+'zippy',
+'zither',
+'zloty',
+'zodiac',
+'zombie',
+'zonked',
+'zygote'
+);
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/includes/captcha/engine_default.php	Fri Feb 22 12:51:53 2008 -0500
@@ -0,0 +1,150 @@
+<?php
+
+/*
+ * Enano - an open-source CMS capable of wiki functions, Drupal-like sidebar blocks, and everything in between
+ * Version 1.1.2 (Caoineag alpha 2)
+ * Copyright (C) 2006-2007 Dan Fuhry
+ * captcha.php - visual confirmation system used during registration
+ *
+ * This program is Free Software; you can redistribute and/or modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.
+ *
+ * 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.
+ *
+ * This file contains code written by Paul Sohier (www.paulscripts.nl). The CAPTCHA code was ported from the phpBB Better
+ * Captcha mod, and has been released under the GPLv2 by the original author.
+ */
+
+/**
+ * The default CAPTCHA engine. Generates medium-strength captchas with very good performance.
+ * @package Enano
+ * @subpackage User management
+ * @copyright 2007-2008 Dan Fuhry
+ * @copyright Paul Sohier
+ */
+ 
+class captcha_engine_default extends captcha_base
+{
+  function make_image()
+  {
+    $code =& strtoupper($this->get_code());
+    
+    /**
+      * The next part is orginnaly written by ted from mastercode.nl and modified for use in Enano.
+      **/
+    header("content-type:image/png");
+    header('Cache-control: no-cache, no-store');
+    $breedte = 320;
+    $hoogte = 60;
+    $img = imagecreatetruecolor($breedte,$hoogte);
+    $achtergrond = imagecolorallocate($img, $this->color("bg"), $this->color("bg"), $this->color("bg"));
+    
+    imagefilledrectangle($img, 0, 0, $breedte-1, $hoogte-1, $achtergrond);
+    for($g = 0;$g < 30; $g++)
+    {
+      $t = $this->dss_rand();
+      $t = $t[0];
+          
+      $ypos = rand(0,$hoogte);
+      $xpos = rand(0,$breedte);
+          
+      $kleur = imagecolorallocate($img, $this->color("bgtekst"), $this->color("bgtekst"), $this->color("bgtekst"));
+          
+      imagettftext($img, $this->size(), $this->move(), $xpos, $ypos, $kleur, $this->font(), $t);
+    } 			
+    $stukje = $breedte / (strlen($code) + 3);
+    
+    for($j = 0;$j < strlen($code); $j++)
+    {
+      
+      
+      $tek = $code[$j];
+      $ypos = rand(33,43);
+      $xpos = $stukje * ($j+1);
+          
+      $kleur2 = imagecolorallocate($img, $this->color("tekst"), $this->color("tekst"), $this->color("tekst"));
+      
+      imagettftext($img, $this->size(), $this->move(), $xpos, $ypos, $kleur2, $this->font() , $tek);
+    }
+      
+    imagepng($img);
+  }
+  
+  /**
+    * Some functions :)
+    * Also orginally written by mastercode.nl
+    **/
+  /**
+    * Function to create a random color
+    * @param $type string Mode for the color
+    * @return int
+    **/
+  function color($type)
+  {
+    switch($type)
+    {
+      case "bg": 
+        $kleur = rand(224,255); 
+      break;
+      case "tekst": 
+        $kleur = rand(0,127); 
+      break;
+      case "bgtekst": 
+        $kleur = rand(200,224); 
+      break;
+      default: 
+        $kleur = rand(0,255); 
+      break;
+    }
+    return $kleur;
+  }
+  /**
+    * Function to ranom the size
+    * @return int
+    **/
+  function size()
+  {
+    $grootte = rand(14,30);
+    return $grootte;
+  }
+  /**
+    * Function to random the posistion
+    * @return int
+    **/
+  function move()
+  {
+    $draai = rand(-25,25);
+    return $draai;
+  }
+  
+  /**
+    * Function to return a ttf file from fonts map
+    * @return string
+    **/
+  function font()
+  {
+    $f = @opendir(ENANO_ROOT . '/includes/captcha/fonts/');
+    if(!$f) die('Can\'t open includes/captcha/fonts/ for reading');
+    $ar = array();
+    while(($file = @readdir($f)) !== false)
+    {
+      if(!in_array($file, array('.','..')) && strstr($file, '.ttf'))
+      {
+        $ar[] = $file;
+      }
+    }
+    if(count($ar))
+    {
+      shuffle($ar);
+      $i = rand(0,(count($ar) - 1));
+      return ENANO_ROOT . '/includes/captcha/fonts/' . $ar[$i];
+    }
+  }
+  function dss_rand()
+  {
+    $val = microtime() .  mt_rand();
+    $val = md5($val . 'a');
+    return substr($val, 4, 16);
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/includes/captcha/engine_failsafe.php	Fri Feb 22 12:51:53 2008 -0500
@@ -0,0 +1,313 @@
+<?php
+
+/*
+ * Enano - an open-source CMS capable of wiki functions, Drupal-like sidebar blocks, and everything in between
+ * Version 1.1.2 (Caoineag alpha 2)
+ * Copyright (C) 2006-2007 Dan Fuhry
+ * captcha.php - visual confirmation system used during registration
+ *
+ * This program is Free Software; you can redistribute and/or modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.
+ *
+ * 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.
+ *
+ * This file contains code written by the phpBB team (www.phpbb.com). phpBB is licensed under the GPLv2.
+ */
+
+/**
+ * Failsafe (no-GD) captcha engine.
+ * @package Enano
+ * @subpackage User management
+ * @copyright 2007-2008 Dan Fuhry
+ * @copyright 2002-2008 phpBB Group
+ */
+ 
+class captcha_engine_failsafe extends captcha_base
+{
+  function make_image()
+  {
+    $code =& strtoupper($this->get_code());
+    // We can we will generate a single filtered png 
+    // Thanks to DavidMJ for emulating zlib within the code :)
+    $_png = $this->define_filtered_pngs();
+    
+    $total_width = 320;
+    $total_height = 50;
+    $img_height = 40;
+    $img_width = 0;
+    $l = 0;
+    
+    list($usec, $sec) = explode(' ', microtime()); 
+    mt_srand($sec * $usec); 
+    
+    $char_widths = array();
+    for ($i = 0; $i < strlen($code); $i++)
+    {
+      $char = $code{$i};
+    
+      $width = mt_rand(0, 4);
+      $char_widths[] = $width;
+      $img_width += $_png[$char]['width'] - $width;
+    }
+    
+    $offset_x = mt_rand(0, $total_width - $img_width);
+    $offset_y = mt_rand(0, $total_height - $img_height);
+    
+    $image = '';
+    $hold_chars = array();
+    for ($i = 0; $i < $total_height; $i++)
+    {
+      $image .= chr(0);
+    
+      if ($i > $offset_y && $i < $offset_y + $img_height)
+      {
+        $j = 0;
+    
+        for ($k = 0; $k < $offset_x; $k++)
+        {
+          $image .= chr(mt_rand(140, 255));
+        }
+    
+        for ($k = 0; $k < strlen($code); $k++)
+        {
+          $char = $code{$k};
+    
+          if (empty($hold_chars[$char]))
+          {
+            $hold_chars[$char] = explode("\n", chunk_split(base64_decode($_png[$char]['data']), $_png[$char]['width'] + 1, "\n"));
+          }
+          $image .= $this->randomise(substr($hold_chars[$char][$l], 1), $char_widths[$j]);
+          $j++;
+        }
+    
+        for ($k = $offset_x + $img_width; $k < $total_width; $k++)
+        {
+          $image .= chr(mt_rand(140, 255));
+        }
+    
+        $l++;
+      }
+      else
+      {
+        for ($k = 0; $k < $total_width; $k++)
+        {
+          $image .= chr(mt_rand(140, 255));
+        }
+      }
+    
+    }
+    unset($hold);
+    
+    $image = $this->create_png($image, $total_width, $total_height);
+
+    // Output image
+    header('Content-Type: image/png');
+    header('Cache-control: no-cache, no-store');
+    echo $image;
+    
+    unset($image);
+    unset($_png);
+  }
+  // This creates a chunk of the given type, with the given data
+  // of the given length adding the relevant crc
+  function png_chunk($length, $type, $data)
+  {
+    $raw = $type;
+    $raw .= $data;
+    $crc = crc32($raw);
+    $raw .= pack('C4', $crc >> 24, $crc >> 16, $crc >> 8, $crc);
+  
+    return pack('C4', $length >> 24, $length >> 16, $length >> 8, $length) . $raw;
+  }
+  
+  // Creates greyscale 8bit png - The PNG spec can be found at
+  // http://www.libpng.org/pub/png/spec/PNG-Contents.html we use
+  // png because it's a fully recognised open standard and supported
+  // by practically all modern browsers and OSs
+  function create_png($raw_image, $width, $height)
+  
+  {
+    // SIG
+    $image = pack('C8', 137, 80, 78, 71, 13, 10, 26, 10);
+    // IHDR
+    $raw = pack('C4', $width >> 24, $width >> 16, $width >> 8, $width);
+    $raw .= pack('C4', $height >> 24, $height >> 16, $height >> 8, $height);
+    $raw .= pack('C5', 8, 0, 0, 0, 0);
+    $image .= $this->png_chunk(13, 'IHDR', $raw);
+  
+    if (@extension_loaded('zlib'))
+    {
+      $raw_image = gzcompress($raw_image);
+      $length = strlen($raw_image);
+    }
+    else
+    {
+      // The total length of this image, uncompressed, is just a calculation of pixels
+      $length = ($width + 1) * $height;
+  
+      // Adler-32 hash generation
+      // Optimized Adler-32 loop ported from the GNU Classpath project
+      $temp_length = $length;
+      $s1 = 1;
+      $s2 = $index = 0;
+  
+      while ($temp_length > 0)
+      {
+        // We can defer the modulo operation:
+        // s1 maximally grows from 65521 to 65521 + 255 * 3800
+        // s2 maximally grows by 3800 * median(s1) = 2090079800 < 2^31
+        $substract_value = ($temp_length < 3800) ? $temp_length : 3800;
+        $temp_length -= $substract_value;
+  
+        while (--$substract_value >= 0)
+        {
+          $s1 += ord($raw_image[$index]);
+          $s2 += $s1;
+  
+          $index++;
+        }
+  
+        $s1 %= 65521;
+        $s2 %= 65521;
+      }
+      $adler_hash = pack('N', ($s2 << 16) | $s1);
+  
+      // This is the same thing as gzcompress($raw_image, 0) but does not need zlib
+      $raw_image = pack('C3v2', 0x78, 0x01, 0x01, $length, ~$length) . $raw_image . $adler_hash;
+  
+      // The Zlib header + Adler hash make us add on 11
+      $length += 11;
+    }
+  
+    // IDAT
+    $image .= $this->png_chunk($length, 'IDAT', $raw_image);
+  
+    // IEND
+    $image .= $this->png_chunk(0, 'IEND', '');
+  
+    return $image;
+  }
+  
+  // Each 'data' element is base64_encoded uncompressed IDAT
+  // png image data
+  function define_filtered_pngs()
+  {
+    $_png = array(
+      '0' => array('data' => 'AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A///////////////////olFAkBAAAGDyA4P///M31/////////////wD////////////////0dAgAAAAAAAAAAAAEcPipFGHn////////////AP//////////////6DAAAAAAAAAAAAAAAAAALSEAN+T///////////8A//////////////xAAAAAAAAAAAAAAAAAAAAAACPA/////////////wD/////////////oAAAAAAAAAAAAAAAAAAAAAAAev//////////////AP////////////8oAAAAAAAAPNj/zDAAAAAAAABD//////////////8A////////////1AAAAAAAABjw////5BAAAAAAAADo/////////////wD///////////+QAAAAAAAAbP//////QgAAAAAAAKj/////////////AP///////////1wAAAAAAACs/////8AXAAAAAAAAcP////////////8A////////////OAAAAAAAAND////dNwAAAAAAAABI/////////////wD///////////8gAAAAAAAA4P//7koACwAAAAAAACT/////////////AP///////////wgAAAAAAAD///VqAwaPAAAAAAAAEP////////////8A////////////AAAAAAAAAP/8kQYDavUAAAAAAAAA/////////////wD///////////8AAAAAAAAA/6kNAEru/wAAAAAAAAD/////////////AP///////////wAAAAAAAADAIwA33f//AAAAAAAAAP////////////8A////////////FAAAAAAAADYAI8D///8AAAAAAAAQ/////////////wD///////////8kAAAAAAAAAA2p////5AAAAAAAACD/////////////AP///////////0gAAAAAAAAFkfz////UAAAAAAAAQP////////////8A////////////cAAAAAAAAET1/////7AAAAAAAABo/////////////wD///////////+oAAAAAAAAXfX/////sAAAAAAAAGj/////////////AAAAALgAAAAAAAAwAAAAAAAAAAAAAAD////////////oAAAAAAAACOT////oEAAAAAAAAOD/////////////AP////////////8+AAAAAAAAKMz/zDQAAAAAAAA0//////////////8A////////////7jgAAAAAAAAAAAAAAAAAAAAAAKT//////////////wD///////////VqAwIAAAAAAAAAAAAAAAAAAAA8////////////////AP//////////rQcDaVEAAAAAAAAAAAAAAAAAKOj///////////////8A///////////nblnu/IAIAAAAAAAAAAAAAFzw/////////////////wD////////////79////+iITCAAAAAgSITg////////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////w==','width' => 40), 
+      '1' => array('data' => 'AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////8BAAAAAAAP//////////////////AP////////////////////////9sAAAAAAAA//////////////////8A////////////////////////pAAAAAAAAAD//////////////////wD//////////////////////6wEAAAAAAAAAP//////////////////AP////////////////////h4AAAAAAAAAAAA//////////////////8A//////////////////ygJAAAAAAAAAAAAAD//////////////////wD//////////////9x8HAAAAAAAAAAAAAAAAP//////////////////AP//////////////AAAAAAAAAAAAAAAAAAAA//////////////////8A//////////////8AAAAAAAAAAAAAAAAAAAD//////////////////wD//////////////wAAAAAAAAR4AAAAAAAAAP//////////////////AP//////////////AAAAAAA4zP8AAAAAAAAA//////////////////8A//////////////8AAAA4sP///wAAAAAAAAD//////////////////wD//////////////yR80P//////AAAAAAAAAP//////////////////AP////////////////////////8AAAAAAAAA//////////////////8A/////////////////////////wAAAAAAAAD//////////////////wD/////////////////////////AAAAAAAAAP//////////////////AP////////////////////////8AAAAAAAAA//////////////////8A/////////////////////////wAAAAAAAAD//////////////////wD/////////////////////////AAAAAAAAAP//////////////////AP////////////////////////8AAAAAAAAA//////////////////8A/////////////////////////wAAAAAAAAD//////////////////wD/////////////////////////AAAAAAAAAP//////////////////AP////////////////////////8AAAAAAAAA//////////////////8A/////////////////////////wAAAAAAAAD//////////////////wD/////////////////////////AAAAAAAAAP//////////////////AP////////////////////////8AAAAAAAAA//////////////////8A/////////////////////////wAAAAAAAAD//////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8=','width' => 40), 
+      '2' => array('data' => 'AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP/////////////////okFAkCAAABCBIfNT///////////////////8A///////////////8hAgAAAAAAAAAAAAAAFTo/////////////////wD//////////////1QAAAAAAAAAAAAAAAAAACjo////////////////AP////////////+MAAAAAAAAAAAAAAAAAAAAADj///////////////8A////////////9BAAAAAAAAAAAAAAAAAAAAAAALD//////////////wD///////////+gAAAAAAAAAHjs+KwMAAAAAAAAVP//////////////AP///////////1gAAAAAAABM/////6QAAAAAAAAU//////////////8A////////////KAAAAAAAALj/////+AAAAAAAAAD//////////////wD///////////+MfGBMOCAI8P/////wAAAAAAAACP//////////////AP///////////////////////////5wAAAAAAAAw//////////////8A///////////////////////////oFAAAAAAAAHz//////////////wD/////////////////////////6CgAAAAAAAAE3P//////////////AP///////////////////////9ggAAAAAAAAAHT///////////////8A//////////////////////+0DAAAAAAAAAA8+P///////////////wD/////////////////////gAAAAAAAAAAAKOj/////////////////AP//////////////////9FAAAAAAAAAAADzw//////////////////8A/////////////////+g4AAAAAAAAAABk/P///////////////////wD////////////////oKAAAAAAAAAAMqP//////////////////////AP//////////////6CgAAAAAAAAAMNz///////////////////////8A//////////////g4AAAAAAAAAFT0/////////////////////////wD/////////////bAAAAAAAAABU/P//////////////////////////AP///////////8wAAAAAAAAAAAAAAAAAAAAAAAAA//////////////8A////////////SAAAAAAAAAAAAAAAAAAAAAAAAAD//////////////wD//////////9wAAAAAAAAAAAAAAAAAAAAAAAAAAP//////////////AP//////////hAAAAAAAAAAAAAAAAAAAAAAAAAAA//////////////8A//////////9AAAAAAAAAAAAAAAAAAAAAAAAAAAD//////////////wD//////////xAAAAAAAAAAAAAAAAAAAAAAAAAAAP//////////////AP////////////////////////////////////////////////////8=','width' => 40), 
+      '3' => array('data' => 'AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD////////////////8sGg0FAAAACA4cLz8////////////////////AP//////////////rBgAAAAAAAAAAAAAACTA//////////////////8A/////////////3QAAAAAAAAAAAAAAAAAAASs/////////////////wD///////////+YAAAAAAAAAAAAAAAAAAAAAAjc////////////////AP//////////6AwAAAAAAAAAAAAAAAAAAAAAAGT///////////////8A//////////94AAAAAAAABJDw/8g4AAAAAAAAHP///////////////wD//////////yAAAAAAAACE/////9gAAAAAAAAA////////////////AP///////////NSwiGQ4FOT//////AAAAAAAABD///////////////8A//////////////////////////+YAAAAAAAAVP///////////////wD//////////////////////P/ggAQAAAAAAATM////////////////AP////////////////////9gAAAAAAAAAAAElP////////////////8A/////////////////////0AAAAAAAAAAHLj//////////////////wD/////////////////////OAAAAAAAAAAwkPj/////////////////AP////////////////////8gAAAAAAAAAAAAINj///////////////8A/////////////////////xAAAAAAAAAAAAAAIPD//////////////wD/////////////////////uOz/4HgEAAAAAAAAhP//////////////AP///////////////////////////3wAAAAAAAAw//////////////8A////////////////////////////6AAAAAAAAAj//////////////wD/////////////////////////////AAAAAAAAAP//////////////AP//////////tJh8YEQoDNz//////+AAAAAAAAAY//////////////8A//////////88AAAAAAAAaP//////dAAAAAAAAEz//////////////wD//////////6QAAAAAAAAAdOD/5HQAAAAAAAAApP//////////////AP///////////CgAAAAAAAAAAAAAAAAAAAAAACD4//////////////8A////////////yAQAAAAAAAAAAAAAAAAAAAAEuP///////////////wD/////////////rAQAAAAAAAAAAAAAAAAABJD/////////////////AP//////////////zDQAAAAAAAAAAAAAACTA//////////////////8A/////////////////8BwOCAAAAAUNGi0/P///////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8=','width' => 40), 
+      '4' => array('data' => 'AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP//////////////////////////nAAAAAAAAAD///////////////8A/////////////////////////8AEAAAAAAAAAP///////////////wD////////////////////////gGAAAAAAAAAAA////////////////AP//////////////////////9DAAAAAAAAAAAAD///////////////8A//////////////////////9UAAAAAAAAAAAAAP///////////////wD/////////////////////hAAAAAAAAAAAAAAA////////////////AP///////////////////7QAAAAAAAAAAAAAAAD///////////////8A///////////////////UDAAAAAAUAAAAAAAAAP///////////////wD/////////////////7CQAAAAABMAAAAAAAAAA////////////////AP////////////////xEAAAAAACU/wAAAAAAAAD///////////////8A////////////////cAAAAAAAZP//AAAAAAAAAP///////////////wD//////////////6AAAAAAADz8//8AAAAAAAAA////////////////AP/////////////IBAAAAAAc6P///wAAAAAAAAD///////////////8A////////////5BgAAAAADMz/////AAAAAAAAAP///////////////wD///////////g0AAAAAACk//////8AAAAAAAAA////////////////AP//////////XAAAAAAAfP///////wAAAAAAAAD///////////////8A//////////8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP///////////wD//////////wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA////////////AP//////////AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD///////////8A//////////8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP///////////wD//////////wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA////////////AP//////////AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD///////////8A////////////////////////////AAAAAAAAAP///////////////wD///////////////////////////8AAAAAAAAA////////////////AP///////////////////////////wAAAAAAAAD///////////////8A////////////////////////////AAAAAAAAAP///////////////wD///////////////////////////8AAAAAAAAA////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8=','width' => 40), 
+      '5' => array('data' => 'AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP//////////////8AAAAAAAAAAAAAAAAAAAAAAA//////////////8A///////////////MAAAAAAAAAAAAAAAAAAAAAAD//////////////wD//////////////6wAAAAAAAAAAAAAAAAAAAAAAP//////////////AP//////////////iAAAAAAAAAAAAAAAAAAAAAAA//////////////8A//////////////9kAAAAAAAAAAAAAAAAAAAAAAD//////////////wD//////////////0QAAAAAAAAAAAAAAAAAAAAAAP//////////////AP//////////////IAAAAAAAYP////////////////////////////8A//////////////wAAAAAAAB8/////////////////////////////wD/////////////3AAAAAAAAIj/////////////////////////////AP////////////+4AAAAAAAAoLRYHAAEKGTE//////////////////8A/////////////5QAAAAAAAAQAAAAAAAAAABY9P///////////////wD/////////////dAAAAAAAAAAAAAAAAAAAAAA89P//////////////AP////////////9QAAAAAAAAAAAAAAAAAAAAAABg//////////////8A/////////////zAAAAAAAAAAAAAAAAAAAAAAAADQ/////////////wD/////////////IAAAAAAAAGjY/+h4BAAAAAAAAGz/////////////AP//////////////9NS0lHSc//////90AAAAAAAALP////////////8A/////////////////////////////9QAAAAAAAAE/////////////wD//////////////////////////////wAAAAAAAAD/////////////AP/////////////////////////////8AAAAAAAAEP////////////8A////////////pIRwWEAgDOD//////8wAAAAAAAA8/////////////wD///////////9EAAAAAAAAaP//////ZAAAAAAAAHz/////////////AP///////////6QAAAAAAAAAaOD/4GQAAAAAAAAE4P////////////8A/////////////CQAAAAAAAAAAAAAAAAAAAAAAGD//////////////wD/////////////yAQAAAAAAAAAAAAAAAAAAAAc7P//////////////AP//////////////rAwAAAAAAAAAAAAAAAAAGNj///////////////8A////////////////0EAAAAAAAAAAAAAAAFTo/////////////////wD//////////////////8h4QCAAAAAcQHzU////////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8=','width' => 40), 
+      '6' => array('data' => 'AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD///////////////////+0ZCwMAAAUNGjI////////////////////AP/////////////////EMAAAAAAAAAAAAABM6P////////////////8A////////////////lAQAAAAAAAAAAAAAAAAo6P///////////////wD//////////////6wAAAAAAAAAAAAAAAAAAABI////////////////AP/////////////oEAAAAAAAAAAAAAAAAAAAAACw//////////////8A/////////////3AAAAAAAAAoxP/YPAAAAAAAAEj//////////////wD////////////4EAAAAAAACOD////YDCBAVGiAoP//////////////AP///////////7gAAAAAAABY//////////////////////////////8A////////////eAAAAAAAAJT//////////////////////////////wD///////////9MAAAAAAAAvP/IXBgABCx03P//////////////////AP///////////ygAAAAAAADcdAAAAAAAAAAEiP////////////////8A////////////FAAAAAAAAFAAAAAAAAAAAAAAcP///////////////wD///////////8AAAAAAAAAAAAAAAAAAAAAAAAAlP//////////////AP///////////wAAAAAAAAAAAAAAAAAAAAAAAAAQ8P////////////8A////////////AAAAAAAAAABAyP/kZAAAAAAAAACQ/////////////wD///////////8MAAAAAAAALPj/////WAAAAAAAAET/////////////AP///////////yQAAAAAAACY///////MAAAAAAAAFP////////////8A////////////SAAAAAAAAMD///////wAAAAAAAAA/////////////wD///////////9wAAAAAAAAvP///////wAAAAAAAAD/////////////AP///////////7QAAAAAAACI///////UAAAAAAAAJP////////////8A////////////+AwAAAAAACDw/////2wAAAAAAABY/////////////wD/////////////cAAAAAAAADC8/Ox4AAAAAAAAAKj/////////////AP/////////////oEAAAAAAAAAAAAAAAAAAAAAAk/P////////////8A//////////////+oAAAAAAAAAAAAAAAAAAAABLj//////////////wD///////////////+QAAAAAAAAAAAAAAAAAACQ////////////////AP////////////////+0JAAAAAAAAAAAAAAkuP////////////////8A///////////////////8sGg0FAAADCxgqPz//////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8=','width' => 40), 
+      '7' => array('data' => 'AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD///////////8AAAAAAAAAAAAAAAAAAAAAAAAAAAD/////////////AP///////////wAAAAAAAAAAAAAAAAAAAAAAAAAAAP////////////8A////////////AAAAAAAAAAAAAAAAAAAAAAAAAAAA/////////////wD///////////8AAAAAAAAAAAAAAAAAAAAAAAAAAAD/////////////AP///////////wAAAAAAAAAAAAAAAAAAAAAAAAAABP////////////8A////////////AAAAAAAAAAAAAAAAAAAAAAAAAAy4/////////////wD//////////////////////////+QUAAAAAAAEuP//////////////AP/////////////////////////8QAAAAAAAAKT///////////////8A/////////////////////////4wAAAAAAAB0/////////////////wD////////////////////////cCAAAAAAANPz/////////////////AP///////////////////////0QAAAAAAATY//////////////////8A//////////////////////+0AAAAAAAAeP///////////////////wD//////////////////////CQAAAAAABTw////////////////////AP////////////////////+gAAAAAAAAkP////////////////////8A/////////////////////ywAAAAAABDw/////////////////////wD///////////////////+4AAAAAAAAbP//////////////////////AP///////////////////1wAAAAAAADQ//////////////////////8A///////////////////4DAAAAAAAMP///////////////////////wD//////////////////7QAAAAAAAB8////////////////////////AP//////////////////aAAAAAAAAMj///////////////////////8A//////////////////8oAAAAAAAM/P///////////////////////wD/////////////////8AAAAAAAAET/////////////////////////AP////////////////+0AAAAAAAAcP////////////////////////8A/////////////////4wAAAAAAACY/////////////////////////wD/////////////////WAAAAAAAAMD/////////////////////////AP////////////////80AAAAAAAA4P////////////////////////8A/////////////////xAAAAAAAAD4/////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8=','width' => 40), 
+      '8' => array('data' => 'AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD////////////////////IdDQUAAAEIEiA1P//////////////////AP/////////////////gRAAAAAAAAAAAAAAAROD///////////////8A////////////////0BgAAAAAAAAAAAAAAAAAEMj//////////////wD///////////////AcAAAAAAAAAAAAAAAAAAAAHPD/////////////AP//////////////hAAAAAAAAAAAAAAAAAAAAAAAhP////////////8A//////////////8sAAAAAAAAKMz/zCgAAAAAAAAs/////////////wD//////////////wAAAAAAAADM////zAAAAAAAAAD/////////////AP//////////////BAAAAAAAAP//////AAAAAAAABP////////////8A//////////////8sAAAAAAAAzP///9QAAAAAAAAw/////////////wD//////////////3wAAAAAAAAoyP/YNAAAAAAAAIT/////////////AP//////////////7BgAAAAAAAAAAAAAAAAAAAAc8P////////////8A////////////////xBgAAAAAAAAAAAAAAAAAGNj//////////////wD/////////////////tAQAAAAAAAAAAAAAAACo////////////////AP///////////////HAAAAAAAAAAAAAAAAAAAAB8//////////////8A//////////////9gAAAAAAAAAAAAAAAAAAAAAAB8/////////////wD/////////////wAAAAAAAAABk4P/UWAAAAAAAAATQ////////////AP////////////9UAAAAAAAAaP//////XAAAAAAAAGT///////////8A/////////////xgAAAAAAADg///////cAAAAAAAAJP///////////wD/////////////AAAAAAAAAP////////8AAAAAAAAA////////////AP////////////8AAAAAAAAA4P//////3AAAAAAAAAT///////////8A/////////////ygAAAAAAABg//////9cAAAAAAAALP///////////wD/////////////ZAAAAAAAAABY1P/cXAAAAAAAAABw////////////AP/////////////QAAAAAAAAAAAAAAAAAAAAAAAABNz///////////8A//////////////9gAAAAAAAAAAAAAAAAAAAAAAB0/////////////wD///////////////Q8AAAAAAAAAAAAAAAAAAAAUPz/////////////AP////////////////x4CAAAAAAAAAAAAAAAEIT8//////////////8A///////////////////smFQwGAAAABg0ZKT0/////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8=','width' => 40), 
+      '9' => array('data' => 'AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD///////////////////ysYCwMAAAUNGiw/P//////////////////AP////////////////+4JAAAAAAAAAAAAAAkuP////////////////8A////////////////lAQAAAAAAAAAAAAAAAAAkP///////////////wD//////////////8AEAAAAAAAAAAAAAAAAAAAAqP//////////////AP/////////////8JAAAAAAAAAAAAAAAAAAAAAAQ7P////////////8A/////////////6wAAAAAAAAAfOz8vCwAAAAAAABw/////////////wD/////////////WAAAAAAAAHD/////7BgAAAAAAAz4////////////AP////////////8kAAAAAAAA1P//////hAAAAAAAALT///////////8A/////////////wAAAAAAAAD///////+4AAAAAAAAcP///////////wD/////////////AAAAAAAAAPz//////8AAAAAAAABI////////////AP////////////8UAAAAAAAAzP//////lAAAAAAAACT///////////8A/////////////0QAAAAAAABY//////gsAAAAAAAADP///////////wD/////////////kAAAAAAAAABw5P/IPAAAAAAAAAAA////////////AP/////////////wEAAAAAAAAAAAAAAAAAAAAAAAAAD///////////8A//////////////+UAAAAAAAAAAAAAAAAAAAAAAAAAP///////////wD///////////////9wAAAAAAAAAAAAAFAAAAAAAAAU////////////AP////////////////+IBAAAAAAAAABw3AAAAAAAACj///////////8A///////////////////cdCwEABhcxP+8AAAAAAAATP///////////wD//////////////////////////////5AAAAAAAAB4////////////AP//////////////////////////////UAAAAAAAALj///////////8A//////////////+kgGxUQCAM2P///+AIAAAAAAAQ+P///////////wD//////////////0gAAAAAAAA42P/EKAAAAAAAAHD/////////////AP//////////////sAAAAAAAAAAAAAAAAAAAAAAQ6P////////////8A////////////////TAAAAAAAAAAAAAAAAAAAAKz//////////////wD////////////////oKAAAAAAAAAAAAAAAAASU////////////////AP/////////////////sUAAAAAAAAAAAAAAwxP////////////////8A////////////////////yHA0FAAADCxktP///////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8=','width' => 40), 
+      'A' => array('data' => 'AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD//////////////////+QAAAAAAAAAAAAAAOT/////////////////AP//////////////////kAAAAAAAAAAAAAAAkP////////////////8A//////////////////88AAAAAAAAAAAAAAA8/////////////////wD/////////////////5AAAAAAAAAAAAAAAAADk////////////////AP////////////////+QAAAAAAAAAAAAAAAAAJD///////////////8A/////////////////zwAAAAAAAAAAAAAAAAAPP///////////////wD////////////////kAAAAAAAAAAgAAAAAAAAA5P//////////////AP///////////////5AAAAAAAAAAgAAAAAAAAACQ//////////////8A////////////////PAAAAAAAAAz8HAAAAAAAADz//////////////wD//////////////+QAAAAAAAAAWP9kAAAAAAAAANz/////////////AP//////////////kAAAAAAAAACk/7wAAAAAAAAAhP////////////8A//////////////88AAAAAAAABOz//BQAAAAAAAAw/////////////wD/////////////4AAAAAAAAAA8////ZAAAAAAAAADc////////////AP////////////+EAAAAAAAAAIj///+8AAAAAAAAAIT///////////8A/////////////zAAAAAAAAAA2P////wQAAAAAAAAMP///////////wD////////////cAAAAAAAAACT//////1wAAAAAAAAA3P//////////AP///////////4QAAAAAAAAAAAAAAAAAAAAAAAAAAACE//////////8A////////////MAAAAAAAAAAAAAAAAAAAAAAAAAAAADD//////////wD//////////9wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAANz/////////AP//////////hAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAhP////////8A//////////8wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAw/////////wD/////////3AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADc////////AP////////+EAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIT///////8A/////////zAAAAAAAAAAhP///////////2QAAAAAAAAAMP///////wD////////cAAAAAAAAAADM////////////vAAAAAAAAAAA3P//////AP///////4QAAAAAAAAAHP/////////////4DAAAAAAAAACE//////8A////////MAAAAAAAAABk//////////////9cAAAAAAAAADD//////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8=','width' => 40), 
+      'B' => array('data' => 'AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A//////////8AAAAAAAAAAAAAAAAAAAAAEDh83P///////////////wD//////////wAAAAAAAAAAAAAAAAAAAAAAAAAEhP//////////////AP//////////AAAAAAAAAAAAAAAAAAAAAAAAAAAAeP////////////8A//////////8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAxP///////////wD//////////wAAAAAAAAAAAAAAAAAAAAAAAAAAAABY////////////AP//////////AAAAAAAAAAAAAAAAAAAAAAAAAAAAABT///////////8A//////////8AAAAAAAAAAP/////4zEwAAAAAAAAAAP///////////wD//////////wAAAAAAAAAA////////7AAAAAAAAAAQ////////////AP//////////AAAAAAAAAAD////////sAAAAAAAAAEj///////////8A//////////8AAAAAAAAAAP/////4zEQAAAAAAAAAtP///////////wD//////////wAAAAAAAAAAAAAAAAAAAAAAAAAAAFz/////////////AP//////////AAAAAAAAAAAAAAAAAAAAAAAAAAiA/P////////////8A//////////8AAAAAAAAAAAAAAAAAAAAAAAAIjPj//////////////wD//////////wAAAAAAAAAAAAAAAAAAAAAAAAAAGKz/////////////AP//////////AAAAAAAAAAAAAAAAAAAAAAAAAAAAAJT///////////8A//////////8AAAAAAAAAAAAAAAAAAAAAAAAAAAAABNz//////////wD//////////wAAAAAAAAAA///////sqCAAAAAAAAAAbP//////////AP//////////AAAAAAAAAAD/////////yAAAAAAAAAAs//////////8A//////////8AAAAAAAAAAP//////////AAAAAAAAAAT//////////wD//////////wAAAAAAAAAA/////////7wAAAAAAAAAAP//////////AP//////////AAAAAAAAAAD//////+ikGAAAAAAAAAAY//////////8A//////////8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFT//////////wD//////////wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAsP//////////AP//////////AAAAAAAAAAAAAAAAAAAAAAAAAAAAADj///////////8A//////////8AAAAAAAAAAAAAAAAAAAAAAAAAAAAc6P///////////wD//////////wAAAAAAAAAAAAAAAAAAAAAAAAAATOj/////////////AP//////////AAAAAAAAAAAAAAAAAAAEIEBkkNj///////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8=','width' => 40), 
+      'C' => array('data' => 'AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP//////////////////5JRULBAAAAgkTIDQ//////////////////8A////////////////1FAAAAAAAAAAAAAAAABAyP///////////////wD//////////////4gEAAAAAAAAAAAAAAAAAAAElP//////////////AP////////////9wAAAAAAAAAAAAAAAAAAAAAAAAlP////////////8A////////////kAAAAAAAAAAAAAAAAAAAAAAAAAAEyP///////////wD//////////9wIAAAAAAAAAAAAAAAAAAAAAAAAAAAw////////////AP//////////WAAAAAAAAAAAWMz/8JwQAAAAAAAAAACw//////////8A/////////+wEAAAAAAAAAID//////9QMAAAAAAAAAET//////////wD/////////nAAAAAAAAAAo/P///////3wAAAAABDBspP//////////AP////////9gAAAAAAAAAIz/////////3BxQjMT0//////////////8A/////////zQAAAAAAAAAzP///////////////////////////////wD/////////GAAAAAAAAADo////////////////////////////////AP////////8AAAAAAAAAAP////////////////////////////////8A/////////wAAAAAAAAAA/////////////////////////////////wD/////////AAAAAAAAAAD/////////////////////////////////AP////////8cAAAAAAAAAOj///////////////////////////////8A/////////zgAAAAAAAAA0P/////////kIGio7P///////////////wD/////////bAAAAAAAAACg/////////5wAAAAAMHS49P//////////AP////////+oAAAAAAAAAEz/////////PAAAAAAAAAAc//////////8A//////////QIAAAAAAAAALz//////6QAAAAAAAAAAGT//////////wD//////////3AAAAAAAAAADIzo/+SEBAAAAAAAAAAAyP//////////AP//////////7BAAAAAAAAAAAAAAAAAAAAAAAAAAAED///////////8A////////////rAAAAAAAAAAAAAAAAAAAAAAAAAAE0P///////////wD/////////////fAAAAAAAAAAAAAAAAAAAAAAAAJz/////////////AP//////////////iAQAAAAAAAAAAAAAAAAAAASY//////////////8A////////////////yEAAAAAAAAAAAAAAAAA8yP///////////////wD//////////////////9yIUCwQAAAAIEB4yP//////////////////AP////////////////////////////////////////////////////8=','width' => 40), 
+      'D' => array('data' => 'AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD///////////8AAAAAAAAAAAAAAAAADChQkOT/////////////////AP///////////wAAAAAAAAAAAAAAAAAAAAAABGjw//////////////8A////////////AAAAAAAAAAAAAAAAAAAAAAAAACDY/////////////wD///////////8AAAAAAAAAAAAAAAAAAAAAAAAAABjk////////////AP///////////wAAAAAAAAAAAAAAAAAAAAAAAAAAAED///////////8A////////////AAAAAAAAAAAAAAAAAAAAAAAAAAAAAKj//////////wD///////////8AAAAAAAAAAP///+isSAAAAAAAAAAANP//////////AP///////////wAAAAAAAAAA////////hAAAAAAAAAAA2P////////8A////////////AAAAAAAAAAD/////////MAAAAAAAAACQ/////////wD///////////8AAAAAAAAAAP////////+MAAAAAAAAAFj/////////AP///////////wAAAAAAAAAA/////////8gAAAAAAAAAMP////////8A////////////AAAAAAAAAAD/////////5AAAAAAAAAAY/////////wD///////////8AAAAAAAAAAP//////////AAAAAAAAAAD/////////AP///////////wAAAAAAAAAA//////////8AAAAAAAAAAP////////8A////////////AAAAAAAAAAD//////////wAAAAAAAAAA/////////wD///////////8AAAAAAAAAAP/////////wAAAAAAAAABD/////////AP///////////wAAAAAAAAAA/////////9QAAAAAAAAAJP////////8A////////////AAAAAAAAAAD/////////qAAAAAAAAABI/////////wD///////////8AAAAAAAAAAP////////9QAAAAAAAAAHj/////////AP///////////wAAAAAAAAAA////////uAAAAAAAAAAAvP////////8A////////////AAAAAAAAAAD////w0HwEAAAAAAAAACT8/////////wD///////////8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAoP//////////AP///////////wAAAAAAAAAAAAAAAAAAAAAAAAAAADz8//////////8A////////////AAAAAAAAAAAAAAAAAAAAAAAAAAAY6P///////////wD///////////8AAAAAAAAAAAAAAAAAAAAAAAAAKNz/////////////AP///////////wAAAAAAAAAAAAAAAAAAAAAACHT0//////////////8A////////////AAAAAAAAAAAAAAAAABg4bKj0/////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8=','width' => 40), 
+      'E' => array('data' => 'AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP//////////AAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////////////8A//////////8AAAAAAAAAAAAAAAAAAAAAAAAAAAAA/////////////wD//////////wAAAAAAAAAAAAAAAAAAAAAAAAAAAAD/////////////AP//////////AAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////////////8A//////////8AAAAAAAAAAAAAAAAAAAAAAAAAAAAA/////////////wD//////////wAAAAAAAAAAAAAAAAAAAAAAAAAAAAD/////////////AP//////////AAAAAAAAAAD///////////////////////////////8A//////////8AAAAAAAAAAP///////////////////////////////wD//////////wAAAAAAAAAA////////////////////////////////AP//////////AAAAAAAAAAD///////////////////////////////8A//////////8AAAAAAAAAAAAAAAAAAAAAAAAAAAD//////////////wD//////////wAAAAAAAAAAAAAAAAAAAAAAAAAAAP//////////////AP//////////AAAAAAAAAAAAAAAAAAAAAAAAAAAA//////////////8A//////////8AAAAAAAAAAAAAAAAAAAAAAAAAAAD//////////////wD//////////wAAAAAAAAAAAAAAAAAAAAAAAAAAAP//////////////AP//////////AAAAAAAAAAAAAAAAAAAAAAAAAAAA//////////////8A//////////8AAAAAAAAAAP///////////////////////////////wD//////////wAAAAAAAAAA////////////////////////////////AP//////////AAAAAAAAAAD///////////////////////////////8A//////////8AAAAAAAAAAP///////////////////////////////wD//////////wAAAAAAAAAA////////////////////////////////AP//////////AAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////////////8A//////////8AAAAAAAAAAAAAAAAAAAAAAAAAAAAA/////////////wD//////////wAAAAAAAAAAAAAAAAAAAAAAAAAAAAD/////////////AP//////////AAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////////////8A//////////8AAAAAAAAAAAAAAAAAAAAAAAAAAAAA/////////////wD//////////wAAAAAAAAAAAAAAAAAAAAAAAAAAAAD/////////////AP////////////////////////////////////////////////////8=','width' => 40),
+      'F' => array('data' => 'AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A/////////////wAAAAAAAAAAAAAAAAAAAAAAAAAA/////////////wD/////////////AAAAAAAAAAAAAAAAAAAAAAAAAAD/////////////AP////////////8AAAAAAAAAAAAAAAAAAAAAAAAAAP////////////8A/////////////wAAAAAAAAAAAAAAAAAAAAAAAAAA/////////////wD/////////////AAAAAAAAAAAAAAAAAAAAAAAAAAD/////////////AP////////////8AAAAAAAAAAAAAAAAAAAAAAAAAAP////////////8A/////////////wAAAAAAAAAA/////////////////////////////wD/////////////AAAAAAAAAAD/////////////////////////////AP////////////8AAAAAAAAAAP////////////////////////////8A/////////////wAAAAAAAAAA/////////////////////////////wD/////////////AAAAAAAAAAAAAAAAAAAAAAAA////////////////AP////////////8AAAAAAAAAAAAAAAAAAAAAAAD///////////////8A/////////////wAAAAAAAAAAAAAAAAAAAAAAAP///////////////wD/////////////AAAAAAAAAAAAAAAAAAAAAAAA////////////////AP////////////8AAAAAAAAAAAAAAAAAAAAAAAD///////////////8A/////////////wAAAAAAAAAAAAAAAAAAAAAAAP///////////////wD/////////////AAAAAAAAAAD/////////////////////////////AP////////////8AAAAAAAAAAP////////////////////////////8A/////////////wAAAAAAAAAA/////////////////////////////wD/////////////AAAAAAAAAAD/////////////////////////////AP////////////8AAAAAAAAAAP////////////////////////////8A/////////////wAAAAAAAAAA/////////////////////////////wD/////////////AAAAAAAAAAD/////////////////////////////AP////////////8AAAAAAAAAAP////////////////////////////8A/////////////wAAAAAAAAAA/////////////////////////////wD/////////////AAAAAAAAAAD/////////////////////////////AP////////////8AAAAAAAAAAP////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8=','width' => 40), 
+      'G' => array('data' => 'AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD//////////////////MB8TCgQAAAACCA4YJzs////////////////AP///////////////JQcAAAAAAAAAAAAAAAAAAhw8P////////////8A/////////////9gwAAAAAAAAAAAAAAAAAAAAAAAk2P///////////wD////////////EDAAAAAAAAAAAAAAAAAAAAAAAAAAc7P//////////AP//////////2AwAAAAAAAAAAAAAAAAAAAAAAAAAAABY//////////8A//////////wwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADQ/////////wD/////////kAAAAAAAAAAAEHzQ/P/gmCAAAAAAAAAAAFz/////////AP////////wcAAAAAAAAACjg////////8CwAAAAAAAAgWP////////8A////////vAAAAAAAAAAI2P//////////yBRAcJjI8P///////////wD///////94AAAAAAAAAGD/////////////////////////////////AP///////0AAAAAAAAAAsP////////////////////////////////8A////////IAAAAAAAAADc/////////////////////////////////wD///////8AAAAAAAAAAP///////wAAAAAAAAAAAAAAAAD/////////AP///////wAAAAAAAAAA////////AAAAAAAAAAAAAAAAAP////////8A////////AAAAAAAAAAD///////8AAAAAAAAAAAAAAAAA/////////wD///////8gAAAAAAAAAOD//////wAAAAAAAAAAAAAAAAD/////////AP///////0AAAAAAAAAAtP//////AAAAAAAAAAAAAAAAAP////////8A////////cAAAAAAAAABw//////8AAAAAAAAAAAAAAAAA/////////wD///////+8AAAAAAAAABDs////////////AAAAAAAAAAD/////////AP////////wYAAAAAAAAADz0//////////AAAAAAAAAAAP////////8A/////////5AAAAAAAAAAACCY4P//3KhcCAAAAAAAAAAA/////////wD/////////+CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD/////////AP//////////xAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIP////////8A////////////rAQAAAAAAAAAAAAAAAAAAAAAAAAAAGTw/////////wD/////////////vBQAAAAAAAAAAAAAAAAAAAAAADjI////////////AP//////////////8HAQAAAAAAAAAAAAAAAAAEiw//////////////8A//////////////////iwcEAgBAAABCA4aKDk/////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8=','width' => 40), 
+      'H' => array('data' => 'AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////8AAAAAAAAAAP///////////wAAAAAAAAAA//////////8A/////////wAAAAAAAAAA////////////AAAAAAAAAAD//////////wD/////////AAAAAAAAAAD///////////8AAAAAAAAAAP//////////AP////////8AAAAAAAAAAP///////////wAAAAAAAAAA//////////8A/////////wAAAAAAAAAA////////////AAAAAAAAAAD//////////wD/////////AAAAAAAAAAD///////////8AAAAAAAAAAP//////////AP////////8AAAAAAAAAAP///////////wAAAAAAAAAA//////////8A/////////wAAAAAAAAAA////////////AAAAAAAAAAD//////////wD/////////AAAAAAAAAAD///////////8AAAAAAAAAAP//////////AP////////8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA//////////8A/////////wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD//////////wD/////////AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP//////////AP////////8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA//////////8A/////////wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD//////////wD/////////AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP//////////AP////////8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA//////////8A/////////wAAAAAAAAAA////////////AAAAAAAAAAD//////////wD/////////AAAAAAAAAAD///////////8AAAAAAAAAAP//////////AP////////8AAAAAAAAAAP///////////wAAAAAAAAAA//////////8A/////////wAAAAAAAAAA////////////AAAAAAAAAAD//////////wD/////////AAAAAAAAAAD///////////8AAAAAAAAAAP//////////AP////////8AAAAAAAAAAP///////////wAAAAAAAAAA//////////8A/////////wAAAAAAAAAA////////////AAAAAAAAAAD//////////wD/////////AAAAAAAAAAD///////////8AAAAAAAAAAP//////////AP////////8AAAAAAAAAAP///////////wAAAAAAAAAA//////////8A/////////wAAAAAAAAAA////////////AAAAAAAAAAD//////////wD/////////AAAAAAAAAAD///////////8AAAAAAAAAAP//////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8=','width' => 40), 
+      'I' => array('data' => 'AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////AAAAAAAAAAAAAAAAAAAAAAAA////////////////AP////////////8AAAAAAAAAAAAAAAAAAAAAAAD///////////////8A/////////////wAAAAAAAAAAAAAAAAAAAAAAAP///////////////wD/////////////AAAAAAAAAAAAAAAAAAAAAAAA////////////////AP////////////8AAAAAAAAAAAAAAAAAAAAAAAD///////////////8A/////////////wAAAAAAAAAAAAAAAAAAAAAAAP///////////////wD/////////////AAAAAAAAAAAAAAAAAAAAAAAA////////////////AP///////////////////wAAAAAAAAAA//////////////////////8A////////////////////AAAAAAAAAAD//////////////////////wD///////////////////8AAAAAAAAAAP//////////////////////AP///////////////////wAAAAAAAAAA//////////////////////8A////////////////////AAAAAAAAAAD//////////////////////wD///////////////////8AAAAAAAAAAP//////////////////////AP///////////////////wAAAAAAAAAA//////////////////////8A////////////////////AAAAAAAAAAD//////////////////////wD///////////////////8AAAAAAAAAAP//////////////////////AP///////////////////wAAAAAAAAAA//////////////////////8A////////////////////AAAAAAAAAAD//////////////////////wD///////////////////8AAAAAAAAAAP//////////////////////AP///////////////////wAAAAAAAAAA//////////////////////8A////////////////////AAAAAAAAAAD//////////////////////wD///////////////////8AAAAAAAAAAP//////////////////////AP////////////8AAAAAAAAAAAAAAAAAAAAAAAD///////////////8A/////////////wAAAAAAAAAAAAAAAAAAAAAAAP///////////////wD/////////////AAAAAAAAAAAAAAAAAAAAAAAA////////////////AP////////////8AAAAAAAAAAAAAAAAAAAAAAAD///////////////8A/////////////wAAAAAAAAAAAAAAAAAAAAAAAP///////////////wD/////////////AAAAAAAAAAAAAAAAAAAAAAAA////////////////AP////////////8AAAAAAAAAAAAAAAAAAAAAAAD///////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8=','width' => 40),
+      'J' => array('data' => 'AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP///////////////////////////wAAAAAAAAAA//////////////8A////////////////////////////AAAAAAAAAAD//////////////wD///////////////////////////8AAAAAAAAAAP//////////////AP///////////////////////////wAAAAAAAAAA//////////////8A////////////////////////////AAAAAAAAAAD//////////////wD///////////////////////////8AAAAAAAAAAP//////////////AP///////////////////////////wAAAAAAAAAA//////////////8A////////////////////////////AAAAAAAAAAD//////////////wD///////////////////////////8AAAAAAAAAAP//////////////AP///////////////////////////wAAAAAAAAAA//////////////8A////////////////////////////AAAAAAAAAAD//////////////wD///////////////////////////8AAAAAAAAAAP//////////////AP///////////////////////////wAAAAAAAAAA//////////////8A////////////////////////////AAAAAAAAAAD//////////////wD///////////////////////////8AAAAAAAAAAP//////////////AP///////////////////////////wAAAAAAAAAA//////////////8A////////////////////////////AAAAAAAAAAj//////////////wD//////////+zMrIxwUDAQ//////wAAAAAAAAAIP//////////////AP//////////DAAAAAAAAADo////2AAAAAAAAAA0//////////////8A//////////8wAAAAAAAAAKj///+YAAAAAAAAAFj//////////////wD//////////2gAAAAAAAAAIND/yBgAAAAAAAAAkP//////////////AP//////////vAAAAAAAAAAAAAAAAAAAAAAAAADc//////////////8A////////////MAAAAAAAAAAAAAAAAAAAAAAAUP///////////////wD////////////EBAAAAAAAAAAAAAAAAAAAABjk////////////////AP////////////+sBAAAAAAAAAAAAAAAAAAY2P////////////////8A///////////////EMAAAAAAAAAAAAAAAVOj//////////////////wD/////////////////vHBAIAAAABg8fNT/////////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8=','width' => 40),
+      'K' => array('data' => 'AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD///////8AAAAAAAAAAP//////////wAQAAAAAAAAAAABw////////AP///////wAAAAAAAAAA/////////9AMAAAAAAAAAAAAcP////////8A////////AAAAAAAAAAD////////cGAAAAAAAAAAAAHD//////////wD///////8AAAAAAAAAAP//////6CgAAAAAAAAAAABs////////////AP///////wAAAAAAAAAA//////Q0AAAAAAAAAAAAVPz///////////8A////////AAAAAAAAAAD////8RAAAAAAAAAAAAFT8/////////////wD///////8AAAAAAAAAAP///1gAAAAAAAAAAABU/P//////////////AP///////wAAAAAAAAAA//9wAAAAAAAAAAAASPz///////////////8A////////AAAAAAAAAAD/jAAAAAAAAAAAADz0/////////////////wD///////8AAAAAAAAAAKQAAAAAAAAAAAA89P//////////////////AP///////wAAAAAAAAAABAAAAAAAAAAAFPT///////////////////8A////////AAAAAAAAAAAAAAAAAAAAAAAApP///////////////////wD///////8AAAAAAAAAAAAAAAAAAAAAAAAU8P//////////////////AP///////wAAAAAAAAAAAAAAAAAAAAAAAABk//////////////////8A////////AAAAAAAAAAAAAAAAAAAAAAAAAADE/////////////////wD///////8AAAAAAAAAAAAAAAAoEAAAAAAAACz8////////////////AP///////wAAAAAAAAAAAAAAGNiAAAAAAAAAAIj///////////////8A////////AAAAAAAAAAAAABjY//gYAAAAAAAACOD//////////////wD///////8AAAAAAAAAAAAY2P///5wAAAAAAAAASP//////////////AP///////wAAAAAAAAAAGNj//////CgAAAAAAAAAqP////////////8A////////AAAAAAAAAADI////////sAAAAAAAAAAc8P///////////wD///////8AAAAAAAAAAP//////////QAAAAAAAAABs////////////AP///////wAAAAAAAAAA///////////IAAAAAAAAAATI//////////8A////////AAAAAAAAAAD///////////9YAAAAAAAAADD8/////////wD///////8AAAAAAAAAAP///////////9wEAAAAAAAAAJD/////////AP///////wAAAAAAAAAA/////////////3AAAAAAAAAADOT///////8A////////AAAAAAAAAAD/////////////7BAAAAAAAAAAUP///////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8=','width' => 40), 
+      'L' => array('data' => 'AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////8AAAAAAAAAAP////////////////////////////8A/////////////wAAAAAAAAAA/////////////////////////////wD/////////////AAAAAAAAAAD/////////////////////////////AP////////////8AAAAAAAAAAP////////////////////////////8A/////////////wAAAAAAAAAA/////////////////////////////wD/////////////AAAAAAAAAAD/////////////////////////////AP////////////8AAAAAAAAAAP////////////////////////////8A/////////////wAAAAAAAAAA/////////////////////////////wD/////////////AAAAAAAAAAD/////////////////////////////AP////////////8AAAAAAAAAAP////////////////////////////8A/////////////wAAAAAAAAAA/////////////////////////////wD/////////////AAAAAAAAAAD/////////////////////////////AP////////////8AAAAAAAAAAP////////////////////////////8A/////////////wAAAAAAAAAA/////////////////////////////wD/////////////AAAAAAAAAAD/////////////////////////////AP////////////8AAAAAAAAAAP////////////////////////////8A/////////////wAAAAAAAAAA/////////////////////////////wD/////////////AAAAAAAAAAD/////////////////////////////AP////////////8AAAAAAAAAAP////////////////////////////8A/////////////wAAAAAAAAAA/////////////////////////////wD/////////////AAAAAAAAAAAAAAAAAAAAAAAAAAD/////////////AP////////////8AAAAAAAAAAAAAAAAAAAAAAAAAAP////////////8A/////////////wAAAAAAAAAAAAAAAAAAAAAAAAAA/////////////wD/////////////AAAAAAAAAAAAAAAAAAAAAAAAAAD/////////////AP////////////8AAAAAAAAAAAAAAAAAAAAAAAAAAP////////////8A/////////////wAAAAAAAAAAAAAAAAAAAAAAAAAA/////////////wD/////////////AAAAAAAAAAAAAAAAAAAAAAAAAAD/////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8=','width' => 40), 
+      'M' => array('data' => 'AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A//////8AAAAAAAAAAAAAAHz//////3wAAAAAAAAAAAAAAP///////wD//////wAAAAAAAAAAAAAATP//////UAAAAAAAAAAAAAAA////////AP//////AAAAAAAAAAAAAAAc//////8cAAAAAAAAAAAAAAD///////8A//////8AAAAAAAAAAAAAAADw////8AAAAAAAAAAAAAAAAP///////wD//////wAAAAAAAAAAAAAAALz////AAAAAAAAAAAAAAAAA////////AP//////AAAAAAAAAAAAAAAAkP///5AAAAAAAAAAAAAAAAD///////8A//////8AAAAAAAAAAAAAAABc////ZAAAAAAAAAAAAAAAAP///////wD//////wAAAAAAAAAoAAAAADD///8wAAAAACQAAAAAAAAA////////AP//////AAAAAAAAAFwAAAAABPz//AgAAAAAXAAAAAAAAAD///////8A//////8AAAAAAAAAkAAAAAAA0P/UAAAAAACQAAAAAAAAAP///////wD//////wAAAAAAAADMAAAAAACg/6gAAAAAAMQAAAAAAAAA////////AP//////AAAAAAAAAPgEAAAAAHD/dAAAAAAE+AAAAAAAAAD///////8A//////8AAAAAAAAA/zQAAAAAQP9IAAAAADD/AAAAAAAAAP///////wD//////wAAAAAAAAD/bAAAAAAQ/xQAAAAAaP8AAAAAAAAA////////AP//////AAAAAAAAAP+gAAAAAADQAAAAAACc/wAAAAAAAAD///////8A//////8AAAAAAAAA/9QAAAAAAGgAAAAAAND/AAAAAAAAAP///////wD//////wAAAAAAAAD//wwAAAAAFAAAAAAM/P8AAAAAAAAA////////AP//////AAAAAAAAAP//RAAAAAAAAAAAADz//wAAAAAAAAD///////8A//////8AAAAAAAAA//94AAAAAAAAAAAAcP//AAAAAAAAAP///////wD//////wAAAAAAAAD//7AAAAAAAAAAAACo//8AAAAAAAAA////////AP//////AAAAAAAAAP//5AAAAAAAAAAAANz//wAAAAAAAAD///////8A//////8AAAAAAAAA////HAAAAAAAAAAQ////AAAAAAAAAP///////wD//////wAAAAAAAAD///9QAAAAAAAAAEz///8AAAAAAAAA////////AP//////AAAAAAAAAP///4gAAAAAAAAAfP///wAAAAAAAAD///////8A//////8AAAAAAAAA////vAAAAAAAAACw////AAAAAAAAAP///////wD//////wAAAAAAAAD////wAAAAAAAAAOz///8AAAAAAAAA////////AP//////AAAAAAAAAP////8sAAAAAAAc/////wAAAAAAAAD///////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8=','width' => 40), 
+      'N' => array('data' => 'AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////AAAAAAAAALD/////////////AAAAAAAAAP//////////AP////////8AAAAAAAAAFOj///////////8AAAAAAAAA//////////8A/////////wAAAAAAAAAASP///////////wAAAAAAAAD//////////wD/////////AAAAAAAAAAAAkP//////////AAAAAAAAAP//////////AP////////8AAAAAAAAAAAAI1P////////8AAAAAAAAA//////////8A/////////wAAAAAAAAAAAAAw+P///////wAAAAAAAAD//////////wD/////////AAAAAAAAAAAAAABw////////AAAAAAAAAP//////////AP////////8AAAAAAAAAAAAAAAC8//////8AAAAAAAAA//////////8A/////////wAAAAAAAAAAAAAAABzs/////wAAAAAAAAD//////////wD/////////AAAAAAAAAAAAAAAAAFD/////AAAAAAAAAP//////////AP////////8AAAAAAAAAAAAAAAAAAJz///8AAAAAAAAA//////////8A/////////wAAAAAAAAAUAAAAAAAADNz//wAAAAAAAAD//////////wD/////////AAAAAAAAALQAAAAAAAAANPz/AAAAAAAAAP//////////AP////////8AAAAAAAAA/2wAAAAAAAAAfP8AAAAAAAAA//////////8A/////////wAAAAAAAAD/+CwAAAAAAAAExAAAAAAAAAD//////////wD/////////AAAAAAAAAP//0AQAAAAAAAAgAAAAAAAAAP//////////AP////////8AAAAAAAAA////jAAAAAAAAAAAAAAAAAAA//////////8A/////////wAAAAAAAAD/////RAAAAAAAAAAAAAAAAAD//////////wD/////////AAAAAAAAAP/////kFAAAAAAAAAAAAAAAAP//////////AP////////8AAAAAAAAA//////+sAAAAAAAAAAAAAAAA//////////8A/////////wAAAAAAAAD///////9kAAAAAAAAAAAAAAD//////////wD/////////AAAAAAAAAP////////QkAAAAAAAAAAAAAP//////////AP////////8AAAAAAAAA/////////8wEAAAAAAAAAAAA//////////8A/////////wAAAAAAAAD//////////4QAAAAAAAAAAAD//////////wD/////////AAAAAAAAAP///////////DwAAAAAAAAAAP//////////AP////////8AAAAAAAAA////////////4BAAAAAAAAAA//////////8A/////////wAAAAAAAAD/////////////qAAAAAAAAAD//////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8=','width' => 40), 
+      'O' => array('data' => 'AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A///////////////////0qGw4HAAAABw4aKT0/////////////////wD////////////////wcAwAAAAAAAAAAAAAAAho6P//////////////AP//////////////uBQAAAAAAAAAAAAAAAAAAAAMoP////////////8A/////////////6AEAAAAAAAAAAAAAAAAAAAAAAAAkP///////////wD///////////+4BAAAAAAAAAAAAAAAAAAAAAAAAAAAoP//////////AP//////////8BQAAAAAAAAAAAAAAAAAAAAAAAAAAAAM5P////////8A//////////9wAAAAAAAAAAAsrPD/7KQsAAAAAAAAAABg/////////wD/////////+BAAAAAAAAAAUPj///////hQAAAAAAAAAAjs////////AP////////+sAAAAAAAAABDw//////////AYAAAAAAAAAKD///////8A/////////2wAAAAAAAAAdP///////////3wAAAAAAAAAYP///////wD/////////OAAAAAAAAAC4////////////xAAAAAAAAAAw////////AP////////8cAAAAAAAAAOD////////////oAAAAAAAAABT///////8A/////////wAAAAAAAAAA//////////////8AAAAAAAAAAP///////wD/////////AAAAAAAAAAD//////////////wAAAAAAAAAA////////AP////////8AAAAAAAAAAP/////////////8AAAAAAAAAAD///////8A/////////xwAAAAAAAAA5P///////////+AAAAAAAAAAHP///////wD/////////NAAAAAAAAAC8////////////uAAAAAAAAAA4////////AP////////9oAAAAAAAAAHj///////////98AAAAAAAAAGT///////8A/////////6gAAAAAAAAAGPD/////////+BgAAAAAAAAApP///////wD/////////9AwAAAAAAAAAUPz///////xcAAAAAAAAAAjs////////AP//////////cAAAAAAAAAAALKjs//CwOAAAAAAAAAAAYP////////8A///////////wFAAAAAAAAAAAAAAAAAAAAAAAAAAAAAzk/////////wD///////////+4BAAAAAAAAAAAAAAAAAAAAAAAAAAAoP//////////AP////////////+QAAAAAAAAAAAAAAAAAAAAAAAAAJD///////////8A//////////////+sEAAAAAAAAAAAAAAAAAAAAAyg/////////////wD////////////////oZAgAAAAAAAAAAAAAAARg4P//////////////AP//////////////////9KhsOCAAAAAUMFyc7P////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8=','width' => 40), 
+      'P' => array('data' => 'AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP///////////wAAAAAAAAAAAAAAAAAACCxguP////////////////8A////////////AAAAAAAAAAAAAAAAAAAAAAAAOOD//////////////wD///////////8AAAAAAAAAAAAAAAAAAAAAAAAAGOD/////////////AP///////////wAAAAAAAAAAAAAAAAAAAAAAAAAARP////////////8A////////////AAAAAAAAAAAAAAAAAAAAAAAAAAAAxP///////////wD///////////8AAAAAAAAAAAAAAAAAAAAAAAAAAABo////////////AP///////////wAAAAAAAAAA////6JwMAAAAAAAAADD///////////8A////////////AAAAAAAAAAD//////6AAAAAAAAAADP///////////wD///////////8AAAAAAAAAAP//////9AAAAAAAAAAA////////////AP///////////wAAAAAAAAAA///////0AAAAAAAAAAD///////////8A////////////AAAAAAAAAAD//////5gAAAAAAAAAHP///////////wD///////////8AAAAAAAAAAP///9iICAAAAAAAAABI////////////AP///////////wAAAAAAAAAAAAAAAAAAAAAAAAAAAJD///////////8A////////////AAAAAAAAAAAAAAAAAAAAAAAAAAAI6P///////////wD///////////8AAAAAAAAAAAAAAAAAAAAAAAAAAIT/////////////AP///////////wAAAAAAAAAAAAAAAAAAAAAAAABU/P////////////8A////////////AAAAAAAAAAAAAAAAAAAAAAAIhPz//////////////wD///////////8AAAAAAAAAAAAAAAAABCRMkOz/////////////////AP///////////wAAAAAAAAAA//////////////////////////////8A////////////AAAAAAAAAAD//////////////////////////////wD///////////8AAAAAAAAAAP//////////////////////////////AP///////////wAAAAAAAAAA//////////////////////////////8A////////////AAAAAAAAAAD//////////////////////////////wD///////////8AAAAAAAAAAP//////////////////////////////AP///////////wAAAAAAAAAA//////////////////////////////8A////////////AAAAAAAAAAD//////////////////////////////wD///////////8AAAAAAAAAAP//////////////////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8=','width' => 40), 
+      'Q' => array('data' => 'AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////SoaDQcAAAAHDhoqPT///////////////////8A//////////////BwDAAAAAAAAAAAAAAACHDo/////////////////wD///////////+4FAAAAAAAAAAAAAAAAAAAABCo////////////////AP//////////nAQAAAAAAAAAAAAAAAAAAAAAAACQ//////////////8A/////////7gEAAAAAAAAAAAAAAAAAAAAAAAAAACg/////////////wD////////wFAAAAAAAAAAAAAAAAAAAAAAAAAAAAAzo////////////AP///////3AAAAAAAAAAACyo8P/sqCwAAAAAAAAAAGT///////////8A///////4EAAAAAAAAABM+P///////FQAAAAAAAAACPT//////////wD//////7AAAAAAAAAAFPD/////////9BgAAAAAAAAApP//////////AP//////bAAAAAAAAAB4////////////fAAAAAAAAABk//////////8A//////84AAAAAAAAALz///////////+8AAAAAAAAADT//////////wD//////xwAAAAAAAAA6P///////////+QAAAAAAAAAHP//////////AP//////AAAAAAAAAAD//////////////wAAAAAAAAAA//////////8A//////8AAAAAAAAAAP//////////////AAAAAAAAAAD//////////wD//////wAAAAAAAAAA/P////////////8AAAAAAAAAAP//////////AP//////GAAAAAAAAADg////////////4AAAAAAAAAAc//////////8A//////84AAAAAAAAALT////MJHTo//+8AAAAAAAAADT//////////wD//////2wAAAAAAAAAdP///2AAABCg/3wAAAAAAAAAZP//////////AP//////rAAAAAAAAAAY9P/sCAAAAABMGAAAAAAAAACk//////////8A///////4EAAAAAAAAABU/P+0OAAAAAAAAAAAAAAACPT//////////wD///////94AAAAAAAAAAA4sPD/gAAAAAAAAAAAAABk////////////AP////////AcAAAAAAAAAAAAAAAAAAAAAAAAAAAADOT///////////8A/////////7wEAAAAAAAAAAAAAAAAAAAAAAAAAACQ/////////////wD//////////6wEAAAAAAAAAAAAAAAAAAAAAAAAABSs////////////AP///////////7gUAAAAAAAAAAAAAAAAAAAAAAAAAABAwP////////8A//////////////BwDAAAAAAAAAAAAAAABAgAAAAAAAA8/////////wD////////////////0qGg0GAAAABgwXJjkxBgAAAAAALD/////////AP//////////////////////////////////5DQAAAAk/P////////8A////////////////////////////////////+GwAAJD//////////wD//////////////////////////////////////8A49P//////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8=','width' => 40), 
+      'R' => array('data' => 'AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A/////////wAAAAAAAAAAAAAAAAAAAAQgOGSk+P///////////////wD/////////AAAAAAAAAAAAAAAAAAAAAAAAAAAcuP//////////////AP////////8AAAAAAAAAAAAAAAAAAAAAAAAAAAAEsP////////////8A/////////wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQ6P///////////wD/////////AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB8////////////AP////////8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAADD///////////8A/////////wAAAAAAAAAA///////svDgAAAAAAAAACP///////////wD/////////AAAAAAAAAAD/////////7AAAAAAAAAAA////////////AP////////8AAAAAAAAAAP/////////cAAAAAAAAABD///////////8A/////////wAAAAAAAAAA//////DQoCQAAAAAAAAAQP///////////wD/////////AAAAAAAAAAAAAAAAAAAAAAAAAAAAAACU////////////AP////////8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAIPj///////////8A/////////wAAAAAAAAAAAAAAAAAAAAAAAAAAAAzU/////////////wD/////////AAAAAAAAAAAAAAAAAAAAAAAAAAA02P//////////////AP////////8AAAAAAAAAAAAAAAAAAAAAAAxctPz///////////////8A/////////wAAAAAAAAAAAAAAAAAAAAAAAEDY/////////////////wD/////////AAAAAAAAAAD/9LAsAAAAAAAAAAzc////////////////AP////////8AAAAAAAAAAP///+wkAAAAAAAAADD8//////////////8A/////////wAAAAAAAAAA/////8QAAAAAAAAAAJD//////////////wD/////////AAAAAAAAAAD//////1QAAAAAAAAAFPD/////////////AP////////8AAAAAAAAAAP//////3AQAAAAAAAAAgP////////////8A/////////wAAAAAAAAAA////////aAAAAAAAAAAM6P///////////wD/////////AAAAAAAAAAD////////oCAAAAAAAAABs////////////AP////////8AAAAAAAAAAP////////+AAAAAAAAAAATc//////////8A/////////wAAAAAAAAAA//////////AUAAAAAAAAAFj//////////wD/////////AAAAAAAAAAD//////////5AAAAAAAAAAAND/////////AP////////8AAAAAAAAAAP//////////+CQAAAAAAAAAQP////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8=','width' => 40), 
+      'S' => array('data' => 'AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP/////////////////8vHBEIAgAAAQgQHC8/P////////////////8A////////////////pCQAAAAAAAAAAAAAAAAcoP///////////////wD//////////////FwAAAAAAAAAAAAAAAAAAAAAXP//////////////AP////////////9oAAAAAAAAAAAAAAAAAAAAAAAAhP////////////8A////////////zAAAAAAAAAAAAAAAAAAAAAAAAAAI6P///////////wD///////////9cAAAAAAAAAAAAAAAAAAAAAAAAAACA////////////AP///////////xgAAAAAAAAAUOD/8KwkAAAAAAAAADj///////////8A////////////AAAAAAAAAAD0/////8wABCAgICxASP///////////wD///////////8MAAAAAAAAAMz/////////////////////////////AP///////////0AAAAAAAAAACFiQxPT///////////////////////8A////////////oAAAAAAAAAAAAAAAADBwtPT//////////////////wD////////////8QAAAAAAAAAAAAAAAAAAACFTA////////////////AP/////////////oOAAAAAAAAAAAAAAAAAAAAABM6P////////////8A///////////////4fAgAAAAAAAAAAAAAAAAAAAAY2P///////////wD/////////////////7IwwAAAAAAAAAAAAAAAAAAAo+P//////////AP/////////////////////koGw0BAAAAAAAAAAAAACU//////////8A///////////////////////////4uFgAAAAAAAAAADz//////////wD//////////2BgSEA0IBwA6P///////5QAAAAAAAAADP//////////AP//////////JAAAAAAAAACc/////////AAAAAAAAAAA//////////8A//////////9YAAAAAAAAACDo///////AAAAAAAAAABT//////////wD//////////6QAAAAAAAAAACCk7P/snBQAAAAAAAAAUP//////////AP//////////+BAAAAAAAAAAAAAAAAAAAAAAAAAAAACs//////////8A////////////kAAAAAAAAAAAAAAAAAAAAAAAAAAAOP///////////wD////////////8RAAAAAAAAAAAAAAAAAAAAAAAABjc////////////AP/////////////0PAAAAAAAAAAAAAAAAAAAAAAg2P////////////8A///////////////8hBQAAAAAAAAAAAAAAAAMdPT//////////////wD/////////////////+LRwSCAMAAAAHDhoqPT/////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8=','width' => 40), 
+      'T' => array('data' => 'AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA////////////AP////////8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD///////////8A/////////wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP///////////wD/////////AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA////////////AP////////8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD///////////8A/////////wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP///////////wD///////////////////8AAAAAAAAAAP//////////////////////AP///////////////////wAAAAAAAAAA//////////////////////8A////////////////////AAAAAAAAAAD//////////////////////wD///////////////////8AAAAAAAAAAP//////////////////////AP///////////////////wAAAAAAAAAA//////////////////////8A////////////////////AAAAAAAAAAD//////////////////////wD///////////////////8AAAAAAAAAAP//////////////////////AP///////////////////wAAAAAAAAAA//////////////////////8A////////////////////AAAAAAAAAAD//////////////////////wD///////////////////8AAAAAAAAAAP//////////////////////AP///////////////////wAAAAAAAAAA//////////////////////8A////////////////////AAAAAAAAAAD//////////////////////wD///////////////////8AAAAAAAAAAP//////////////////////AP///////////////////wAAAAAAAAAA//////////////////////8A////////////////////AAAAAAAAAAD//////////////////////wD///////////////////8AAAAAAAAAAP//////////////////////AP///////////////////wAAAAAAAAAA//////////////////////8A////////////////////AAAAAAAAAAD//////////////////////wD///////////////////8AAAAAAAAAAP//////////////////////AP///////////////////wAAAAAAAAAA//////////////////////8A////////////////////AAAAAAAAAAD//////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8=','width' => 40), 
+      'U' => array('data' => 'AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////8AAAAAAAAAAP///////////wAAAAAAAAAA//////////8A/////////wAAAAAAAAAA////////////AAAAAAAAAAD//////////wD/////////AAAAAAAAAAD///////////8AAAAAAAAAAP//////////AP////////8AAAAAAAAAAP///////////wAAAAAAAAAA//////////8A/////////wAAAAAAAAAA////////////AAAAAAAAAAD//////////wD/////////AAAAAAAAAAD///////////8AAAAAAAAAAP//////////AP////////8AAAAAAAAAAP///////////wAAAAAAAAAA//////////8A/////////wAAAAAAAAAA////////////AAAAAAAAAAD//////////wD/////////AAAAAAAAAAD///////////8AAAAAAAAAAP//////////AP////////8AAAAAAAAAAP///////////wAAAAAAAAAA//////////8A/////////wAAAAAAAAAA////////////AAAAAAAAAAD//////////wD/////////AAAAAAAAAAD///////////8AAAAAAAAAAP//////////AP////////8AAAAAAAAAAP///////////wAAAAAAAAAA//////////8A/////////wAAAAAAAAAA////////////AAAAAAAAAAD//////////wD/////////AAAAAAAAAAD///////////8AAAAAAAAAAP//////////AP////////8AAAAAAAAAAP///////////wAAAAAAAAAA//////////8A/////////wAAAAAAAAAA////////////AAAAAAAAAAD//////////wD/////////JAAAAAAAAADk/////////+gAAAAAAAAAHP//////////AP////////9MAAAAAAAAAJz/////////nAAAAAAAAABE//////////8A/////////4gAAAAAAAAAHOj//////+ggAAAAAAAAAHz//////////wD/////////0AAAAAAAAAAAIJzs/+ykIAAAAAAAAAAA0P//////////AP//////////QAAAAAAAAAAAAAAAAAAAAAAAAAAAAED///////////8A///////////IBAAAAAAAAAAAAAAAAAAAAAAAAAAE0P///////////wD///////////+YAAAAAAAAAAAAAAAAAAAAAAAAAJj/////////////AP////////////+UBAAAAAAAAAAAAAAAAAAAAASU//////////////8A///////////////IPAAAAAAAAAAAAAAAAAAwyP///////////////wD/////////////////0IxYOCAIAAAEIEiAyP//////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8=','width' => 40), 
+      'V' => array('data' => 'AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD//////zAAAAAAAAAAYP//////////////ZAAAAAAAAAAw////////AP//////kAAAAAAAAAAU/P////////////8UAAAAAAAAAJD///////8A///////oBAAAAAAAAADE////////////xAAAAAAAAAAE7P///////wD///////9MAAAAAAAAAHD///////////94AAAAAAAAAEz/////////AP///////6gAAAAAAAAAJP///////////yQAAAAAAAAArP////////8A////////+BAAAAAAAAAA1P/////////YAAAAAAAAABT4/////////wD/////////aAAAAAAAAACE/////////4QAAAAAAAAAbP//////////AP/////////EAAAAAAAAADT/////////OAAAAAAAAADM//////////8A//////////8kAAAAAAAAAOT//////+QAAAAAAAAAKP///////////wD//////////4QAAAAAAAAAmP//////nAAAAAAAAACI////////////AP//////////5AAAAAAAAABE//////9EAAAAAAAABOT///////////8A////////////QAAAAAAAAAT0////9AgAAAAAAABI/////////////wD///////////+gAAAAAAAAAKT///+kAAAAAAAAAKj/////////////AP////////////QIAAAAAAAAXP///1wAAAAAAAAM+P////////////8A/////////////1wAAAAAAAAM+P/8DAAAAAAAAGT//////////////wD/////////////vAAAAAAAAAC8/7wAAAAAAAAAxP//////////////AP//////////////HAAAAAAAAGj/aAAAAAAAACT///////////////8A//////////////94AAAAAAAAHP8cAAAAAAAAhP///////////////wD//////////////9gAAAAAAAAAkAAAAAAAAADk////////////////AP///////////////zgAAAAAAAAQAAAAAAAAQP////////////////8A////////////////lAAAAAAAAAAAAAAAAACg/////////////////wD////////////////sCAAAAAAAAAAAAAAADPT/////////////////AP////////////////9QAAAAAAAAAAAAAABg//////////////////8A/////////////////7AAAAAAAAAAAAAAAMD//////////////////wD//////////////////BQAAAAAAAAAAAAc////////////////////AP//////////////////cAAAAAAAAAAAAHz///////////////////8A///////////////////MAAAAAAAAAAAA3P///////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8=','width' => 40), 
+      'W' => array('data' => 'AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A//8cAAAAAAAAALz/////4AAAAAAAAAAA6P////+8AAAAAAAAABz//wD//1QAAAAAAAAAjP////+gAAAAAAAAAACo/////4wAAAAAAAAAUP//AP//jAAAAAAAAABU/////2AAAAAAAAAAAGj/////VAAAAAAAAACM//8A///EAAAAAAAAACT/////IAAAAAAAAAAAKP////8kAAAAAAAAAMT//wD///gEAAAAAAAAAPD//+AAAAAAAAAAAAAA6P//8AAAAAAAAAAE9P//AP///zAAAAAAAAAAvP//oAAAAAAAAAAAAACo//+8AAAAAAAAADD///8A////bAAAAAAAAACM//9gAAAAAAAAAAAAAGT//4wAAAAAAAAAaP///wD///+kAAAAAAAAAFT//yAAAAAAAAAAAAAAIP//VAAAAAAAAACc////AP///9gAAAAAAAAAJP/gAAAAAAAAAAAAAAAA4P8kAAAAAAAAANT///8A/////xAAAAAAAAAA8KAAAAAAAAAAAAAAAACg8AAAAAAAAAAQ/////wD/////TAAAAAAAAAC8YAAAAAAAAAAAAAAAAGC8AAAAAAAAAET/////AP////+AAAAAAAAAAIwgAAAAAAAAAAAAAAAAIIwAAAAAAAAAfP////8A/////7gAAAAAAAAANAAAAAAAACwwAAAAAAAANAAAAAAAAACw/////wD/////8AAAAAAAAAAAAAAAAAAAdHgAAAAAAAAAAAAAAAAAAOz/////AP//////KAAAAAAAAAAAAAAAAAC4vAAAAAAAAAAAAAAAAAAg//////8A//////9gAAAAAAAAAAAAAAAACPj4CAAAAAAAAAAAAAAAAFj//////wD//////5QAAAAAAAAAAAAAAABE//9IAAAAAAAAAAAAAAAAkP//////AP//////0AAAAAAAAAAAAAAAAIj//4wAAAAAAAAAAAAAAADI//////8A///////8DAAAAAAAAAAAAAAAzP//1AAAAAAAAAAAAAAABPj//////wD///////88AAAAAAAAAAAAABT/////GAAAAAAAAAAAAAA0////////AP///////3QAAAAAAAAAAAAAWP////9gAAAAAAAAAAAAAHD///////8A////////sAAAAAAAAAAAAACg/////6QAAAAAAAAAAAAApP///////wD////////kAAAAAAAAAAAAAOT/////6AAAAAAAAAAAAADc////////AP////////8cAAAAAAAAAAAo////////MAAAAAAAAAAAEP////////8A/////////1QAAAAAAAAAAHD///////94AAAAAAAAAABM/////////wD/////////jAAAAAAAAAAAtP///////7wAAAAAAAAAAID/////////AP/////////EAAAAAAAAAAT0////////+AgAAAAAAAAAuP////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8=','width' => 40), 
+      'X' => array('data' => 'AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD///////9UAAAAAAAAAKz///////////+sAAAAAAAAAFD/////////AP///////+QQAAAAAAAAFOT/////////8BwAAAAAAAAM5P////////8A/////////5gAAAAAAAAATP////////9kAAAAAAAAAJD//////////wD//////////0AAAAAAAAAAoP//////wAAAAAAAAAA0/P//////////AP//////////2AgAAAAAAAAQ4P////gkAAAAAAAABMz///////////8A////////////iAAAAAAAAABA////dAAAAAAAAABw/////////////wD////////////8MAAAAAAAAACU/9AEAAAAAAAAHPD/////////////AP/////////////IBAAAAAAAAAzYMAAAAAAAAACs//////////////8A//////////////90AAAAAAAAABAAAAAAAAAATP///////////////wD///////////////QgAAAAAAAAAAAAAAAAAAzg////////////////AP///////////////7wAAAAAAAAAAAAAAAAAjP////////////////8A/////////////////2AAAAAAAAAAAAAAADD8/////////////////wD/////////////////7BQAAAAAAAAAAAAEyP//////////////////AP/////////////////gDAAAAAAAAAAAAAjY//////////////////8A/////////////////0AAAAAAAAAAAAAAADj8/////////////////wD///////////////+UAAAAAAAAAAAAAAAAAJD/////////////////AP//////////////4AwAAAAAAAAAAAAAAAAADOD///////////////8A//////////////9AAAAAAAAAAAAAAAAAAAAAQP///////////////wD/////////////nAAAAAAAAAAAWAAAAAAAAAAAlP//////////////AP///////////+QQAAAAAAAAAGD/YAAAAAAAAAAM4P////////////8A////////////TAAAAAAAAAAs9P/0LAAAAAAAAABM/////////////wD//////////6AAAAAAAAAADNT////UDAAAAAAAAACg////////////AP/////////kEAAAAAAAAACg//////+gAAAAAAAAABDk//////////8A/////////0wAAAAAAAAAYP////////9gAAAAAAAAAEz//////////wD///////+oAAAAAAAAACz0//////////QsAAAAAAAAAKT/////////AP//////7BQAAAAAAAAM1P///////////9QMAAAAAAAAFOz///////8A//////9UAAAAAAAAAKD//////////////6AAAAAAAAAAVP///////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8=','width' => 40), 
+      'Y' => array('data' => 'AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP///////1QAAAAAAAAAAGj//////////2gAAAAAAAAAAFT///////8A////////5BAAAAAAAAAAAMT////////EAAAAAAAAAAAQ5P///////wD/////////mAAAAAAAAAAAKPj/////+CgAAAAAAAAAAJj/////////AP//////////PAAAAAAAAAAAgP////+AAAAAAAAAAAA8//////////8A///////////YCAAAAAAAAAAE2P//2AQAAAAAAAAACNj//////////wD///////////+AAAAAAAAAAAA4//84AAAAAAAAAACA////////////AP////////////woAAAAAAAAAACUlAAAAAAAAAAAKPz///////////8A/////////////8gAAAAAAAAAABAQAAAAAAAAAADI/////////////wD//////////////2wAAAAAAAAAAAAAAAAAAAAAbP//////////////AP//////////////8BwAAAAAAAAAAAAAAAAAABzw//////////////8A////////////////tAAAAAAAAAAAAAAAAAAAtP///////////////wD/////////////////VAAAAAAAAAAAAAAAAFT/////////////////AP/////////////////oEAAAAAAAAAAAAAAQ6P////////////////8A//////////////////+cAAAAAAAAAAAAAJz//////////////////wD///////////////////9AAAAAAAAAAABA////////////////////AP///////////////////9gAAAAAAAAAANj///////////////////8A/////////////////////wAAAAAAAAAA/////////////////////wD/////////////////////AAAAAAAAAAD/////////////////////AP////////////////////8AAAAAAAAAAP////////////////////8A/////////////////////wAAAAAAAAAA/////////////////////wD/////////////////////AAAAAAAAAAD/////////////////////AP////////////////////8AAAAAAAAAAP////////////////////8A/////////////////////wAAAAAAAAAA/////////////////////wD/////////////////////AAAAAAAAAAD/////////////////////AP////////////////////8AAAAAAAAAAP////////////////////8A/////////////////////wAAAAAAAAAA/////////////////////wD/////////////////////AAAAAAAAAAD/////////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8=','width' => 40), 
+      'Z' => array('data' => 'AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A//////////8AAAAAAAAAAAAAAAAAAAAAAAAAAAD//////////////wD//////////wAAAAAAAAAAAAAAAAAAAAAAAAAAAP//////////////AP//////////AAAAAAAAAAAAAAAAAAAAAAAAAAAA//////////////8A//////////8AAAAAAAAAAAAAAAAAAAAAAAAAAAD//////////////wD//////////wAAAAAAAAAAAAAAAAAAAAAAAAAAAP//////////////AP//////////AAAAAAAAAAAAAAAAAAAAAAAAAAAQ//////////////8A/////////////////////////1AAAAAAAAAABLz//////////////wD///////////////////////98AAAAAAAAAACY////////////////AP//////////////////////pAAAAAAAAAAAaP////////////////8A/////////////////////8QIAAAAAAAAAET8/////////////////wD////////////////////gGAAAAAAAAAAo9P//////////////////AP//////////////////9CwAAAAAAAAAFNz///////////////////8A//////////////////xMAAAAAAAAAATA/////////////////////wD/////////////////eAAAAAAAAAAAnP//////////////////////AP///////////////5wAAAAAAAAAAHT///////////////////////8A///////////////ABAAAAAAAAABM/P///////////////////////wD/////////////3BQAAAAAAAAALPT/////////////////////////AP////////////QoAAAAAAAAABjg//////////////////////////8A///////////8SAAAAAAAAAAExP///////////////////////////wD//////////2wAAAAAAAAAAKD/////////////////////////////AP////////+YAAAAAAAAAAB8//////////////////////////////8A/////////wQAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/////////////wD/////////AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD/////////////AP////////8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////////////8A/////////wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/////////////wD/////////AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD/////////////AP////////8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8=','width' => 40), 
+    );
+  
+    return $_png;
+  }
+  
+  // These define base64_encoded raw png image data used
+  // when we cannot generate our own single png image
+  function define_raw_pngs()
+  {
+    $_png = array(
+      '0' => 'iVBORw0KGgoAAAANSUhEUgAAACgAAAAoCAAAAACpleexAAAAFXRFWHRDcmVhdGlvbiBUaW1lAAfTBQ4QKCNGXKO6AAAAB3RJTUUH0wUOEDQ6EUG1VwAAAAlwSFlzAAALEgAACxIB0t1+/AAAAXNJREFUeNpj/M9AHGAiUt2wVvhyaqAqKyOjpG3jQwaGv+e+IUn9RwJfSjjg4iwFP1aKJD6HyyErfGGAYrquIoP5E2wK/zigu0v5wH9sChdgeKDqP1aFGhBZmxv/z0Dd4IxV4RWIpMQHIPuJAITzAqEQETx7IFQIP5CQNoJwDmALxzMQCuyjg1chnBPYwtECwr8AZN41h0p6YHOjAkTuwf//77wYuCEcFWwKOWA2fM1iZuuHcASwKYQ55c9ENuasrxgRjKlwJS+D17v/hBUeUGYwv/sfn0IRiJQZJIbxuFEFagjvSlDUQNgK2GIGqpC1JRhIfoAqxBYz0DRhn8IMJO+giKEqhMaMJBeI3AHhIKdkRPqG8DlAifqFADyasKRHO6h1Z/6fMYEwTbCmx3cWGCl8CTaFwBhGz+M2/7EpXMvOnBmIok7jBVaFz/Mi3/1pQORrhpgPyOr+M8IL0j9/gKpeLjhy5QEwoDVsYuRR3cE4IktcAJNx8cJaZBeQAAAAAElFTkSuQmCC', 
+      '1' => 'iVBORw0KGgoAAAANSUhEUgAAACgAAAAoCAAAAACpleexAAAAFXRFWHRDcmVhdGlvbiBUaW1lAAfTBQ4QMi//xxVKAAAAB3RJTUUH0wUOEDYLcqnX7wAAAAlwSFlzAAALEgAACxIB0t1+/AAAAHpJREFUeNpj/M9AHGAiUh1WhR8FGUGAsMKaD9iM/I8BlmCVwVS4hoUohT8qcNiFyv2zQIWBCIV3amRwu54RKcDRAgQ1KigIcJYK7CqR3QsCFmf+Y8qgeQakbANMAz6FKjUXECbj8zWa76nm61GFw1UhI10KqVGFNFQIADdK9Zj7PsV9AAAAAElFTkSuQmCC', 
+      '2' => 'iVBORw0KGgoAAAANSUhEUgAAACgAAAAoCAAAAACpleexAAAAFXRFWHRDcmVhdGlvbiBUaW1lAAfTBQ4QMwPUBEjoAAAAB3RJTUUH0wUOEDUqFe2UcgAAAAlwSFlzAAALEgAACxIB0t1+/AAAAQxJREFUeNpj/M9AHGAiUt2owkGrkAWF93LFgStPfjCwyGiYRGijqfyPAH9aOJAkQl78RwbICkNQjdB4gUNhD7qzLLAr/CKA4YENSAoRvl7zAUJXvPmxhgfCXILVMxEQvg+IDVUhgtVqDYjkDhD7B2aQIMIx5cOTN29evLAAsaEKObBajQzmQOQMcIQjHLwQgSisIaDwBdS5LHfwK7yhAHVVyX+8CrdAA5HB5gdehQ3Yoxpd4ZcAmDqbD//xKISEIjhU//zHoxDmXQaeFRhOZ8CmzuDOf3wKf8DsDfnyH6/CHJi6P//xKjyDJethVehBpMI7DPgVwrPCCgb8AK5wDwGFcNMF8EkCASOx1QcAGUxu1untnFIAAAAASUVORK5CYII=', 
+      '3' => 'iVBORw0KGgoAAAANSUhEUgAAACgAAAAoCAAAAACpleexAAAAFXRFWHRDcmVhdGlvbiBUaW1lAAfTBQ4QMxBQugk2AAAAB3RJTUUH0wUOEDU3duv4qwAAAAlwSFlzAAALEgAACxIB0t1+/AAAATdJREFUeNpj/M9AHGAiUt0IVciCzPm7ZceZB28YGBQkLHwcmNFU/keANRJI4ioH/qMAJIUlaHatwaFwBrqrOO5gVfiCB8P9KVgVVkAtnPDh/wkLCFsGq0IFiGQLiH0D06P/GWHJ7O+NOzfuXLlzQRrEhgSawHscwYPurxAcwQMBf/4/aIAYyHIGr8IEeDhO+Y9XoQNUncwOVHGMRPEDSovc+IkzrpGDCQgUbuC1WgBhhsIHfAp3vPn/oIIFKfRxKQSDGohCA4IKX0DTD7YoRAWMUJ9iyQpbn4DBBWUQ5yFEDDnFw622gXAzwBxoYvfB5sYlUI0lD/4/gWWKJdgU/tHAcKjCD6y+PsGCpo4FJbaRgmcNqkqWCThTzxkTJHXo+Ro1HA9uOPHiATDlKJj4eKCVFIzDqWgGAK7GW/haPS+zAAAAAElFTkSuQmCC', 
+      '4' => 'iVBORw0KGgoAAAANSUhEUgAAACgAAAAoCAAAAACpleexAAAAFXRFWHRDcmVhdGlvbiBUaW1lAAfTBQ4QMyqWttCEAAAAB3RJTUUH0wUOEDUxn4hdngAAAAlwSFlzAAALEgAACxIB0t1+/AAAAKBJREFUeNpj/M9AHGAiUh2FCucyQgCK4H9McIAFixwWhQ8kGIhS+MWAgTiFIQzEKWxhIE7hFgbiFF7hASkQIajwjQpInuUAIYV/XMDyU/4TUlgAlk75T0jhArCszR9CCk+AY07mxX8CCp+AY47nzH8CCn+YgOWW/CekMAYsVfMfl0JGmCBq4kNEDp2zAn0UMmItABjRvDykPTO43DgyFQIANP6pTFLWAdoAAAAASUVORK5CYII=', 
+      '5' => 'iVBORw0KGgoAAAANSUhEUgAAACgAAAAoCAAAAACpleexAAAAFXRFWHRDcmVhdGlvbiBUaW1lAAfTBQ4QMzPy3XhEAAAAB3RJTUUH0wUOEDUk8lW5dQAAAAlwSFlzAAALEgAACxIB0t1+/AAAAQpJREFUeNpj/M9AHGAiUt2oQuIVfmREBzgU3iHWxAfEKiTaRFpZnfAfAbAr/AsxUYagiVCbeQgqhPpFYmukLCOrZupRNJUIB02BCAjAZCK+/Ed2LoJZgm6bzRfsCgMw3JWAXaEBpg8uIGSRPPMBQmXc+P+iggXCnoOQZUQK1K8PgEAjGcQs7QGL6FzG5mtkcAUiyYIQYcRRUkDTLEIWR1b4ixamQMPhrKUP3rx48eDNFXmwdyFiOthixgXqaTAnBcKpwRaOS6A6Mx78fwBVx/IAm8I/KsTGzAkWNHUyb7Ar/L8GNSlK3MCRev7/v+CApC7kBUoUoAX4yQ0nHjwAWqpiE6GNFgNDoAwHAKC2Q2lMNcCmAAAAAElFTkSuQmCC', 
+      '6' => 'iVBORw0KGgoAAAANSUhEUgAAACgAAAAoCAAAAACpleexAAAAFXRFWHRDcmVhdGlvbiBUaW1lAAfTBQ4QNAObRd4vAAAAB3RJTUUH0wUOEDUc2lcB6wAAAAlwSFlzAAALEgAACxIB0t1+/AAAATtJREFUeNpj/M9AHGAiUh2Gwq2puryMjKKmmSfRVf5HBkcMEBI+L1CkUBROYUE2QuMFLoVr0CzzwKHwhQC6szZgV1gAtfHI/xs2mEYywsPxp8QHEMVxQ56B4aaJiIKIiIRCPDZf74DwI/5jB4hwPAChbAgG+BWoExlOxkoysuqW3sUV4BoQ/p0SqARLB44AF4HIByDMKMCuEIu7phCrUOADNl/DgMOJ/09SIMwPC7B5hgfC1/kB4kRAOC7YrFaByM0Ac85AOCLYrFaBhSMIQNPlG2wBDg3HP2CSGU/MuEAoiKVXUWxB9cwPiG8UwEGSg5FCMNOjwZ4/byqgpqwgMoWr/MGeZ1agqWPZgSNz/Z+AqnDCf1wK/29B8qbKDhQpRtTE8HfLjjMP3jDwKJh4hKCGJSPNC6lRhTRWCABWpdoxd/bZ4QAAAABJRU5ErkJggg==', 
+      '7' => 'iVBORw0KGgoAAAANSUhEUgAAACgAAAAoCAAAAACpleexAAAAFXRFWHRDcmVhdGlvbiBUaW1lAAfTBQ4QNA18/fMoAAAAB3RJTUUH0wUOEDUVo4u5TwAAAAlwSFlzAAALEgAACxIB0t1+/AAAAM9JREFUeNpj/M9AHGAiUt2oQnorZIGzGLFJIyJ40HqGhUiFPFuQ/YUFPBGBmLcDSQybwj8OEDOW/CegsAeiruQ/AYV3OMDqTP4QUugCceCN/wQUQn1a8Z+Awj8qYHUiHwgpXAAxcMJ/Qgp1wOoEPhBSuANiYM5/QgpjIAovEFL4gweszgAz0NASxZ4vYMqHYDKDBiIWhWhWa0CS1x9CVn+8AaYsmAlZfQRC6RDMChADGTQIKjxDrMI7EEoBi0JGlMJe8AOY+sFOSCEeQHQBAABCZ7xyT9fJhwAAAABJRU5ErkJggg==', 
+      '8' => 'iVBORw0KGgoAAAANSUhEUgAAACgAAAAoCAAAAACpleexAAAAFXRFWHRDcmVhdGlvbiBUaW1lAAfTBQ4QNBeBnwpSAAAAB3RJTUUH0wUOEDUOKe5wowAAAAlwSFlzAAALEgAACxIB0t1+/AAAATVJREFUeNpj/M9AHGAiUt1AKmRB459cc+DBGwYWGQ2LEG1Umf/I4IELkozLA2QpFIUXJFDMEDiBQ+EHGTR3yHzArrAFwwct2BXqQGQ1zvw/owFh6mBXCDXmDJB5BsOrjEhxzfoHIgkiGCGB9xtrgEPtOwvEV6FWY4+ZAAgVc5LhZgKEGYI9wN+gBiPu4Pl/BFWlxA1cMfN/C0rUr8AVhX8K0KyuwaEwASNmarAqPACVTXnw/0oENBFewKYQGhYZYE4MVBM2hVAvQ1LhHQhHBVsUMjIgYhCdhy3PPASTd6GOxBYz0KhOQHajDjY3pkC1Rlz5fweqjqEAm8ILGK5gYLlDZICXYI+ZLzZo6gL+4EgUfyo4kJQJtCCpQ8kKQPB2zZ47L14AU5iMgUMAN7IM43AqHwdQIQAhMPz6Gz5V/wAAAABJRU5ErkJggg==', 
+      '9' => 'iVBORw0KGgoAAAANSUhEUgAAACgAAAAoCAAAAACpleexAAAAFXRFWHRDcmVhdGlvbiBUaW1lAAfTBQ4QNCQ+T2tEAAAAB3RJTUUH0wUOEDUHUDLIBwAAAAlwSFlzAAALEgAACxIB0t1+/AAAAUZJREFUeNpj/M9AHGAiUh26wr9rE3V5GRlFTTM3/kVT+R8Z7FBBSKjsQJFCUTiFBcWMCbgUHmBBs20FdoV/VNDUMQi8wapwDVS65s2fPToQZgFWhRFIkm8kwGyeH9gUQm2+Aua0QDhb4LJI4XgHQmmDSRMIZw+emIEENAeEcwObQhEIdQHiABRbUGPGBSIQAWL/gHqbB5tnJkC1Fjz5f8IGwxwkhR8EsCQarFE4hViF/wsQCgKgHsSu8H8HLFkUQL2rgUPh/zslOiwMEjFH/kND2geXQvQgqMAWhSjgAIRygAswIuXCpXfevHjz4M0ZdQaGhxo/wAnyBTuWmPnvARGxuPH/iAa+9Ph/A7r9Ai+wK/zvg6ZwzX8cCl9oICtjmfIfl8L/bwIQ6gyO/Met8P//EwUmwHTJo5OyBU2CkdaF1KhCWisEAM/sJxmZkdWnAAAAAElFTkSuQmCC', 
+      'A' => 'iVBORw0KGgoAAAANSUhEUgAAACgAAAAoCAAAAACpleexAAAAFXRFWHRDcmVhdGlvbiBUaW1lAAfTBQ4QFwy1U7TfAAAAB3RJTUUH0wUOEC0ZKCZtPQAAAAlwSFlzAAALEgAACxIB0t1+/AAAAO1JREFUeNrt1LERwiAUBuAHZ2GRwsIypQMwQEZwgBQpM4QDZBSLFI7gCA5gQWGRdA5gkTuMSh48eMTUnq96wH98B+QiDCwruTD3D76qF676ueAp0Y9lSBXeSkFWaLAje3T+kkzK4SgpBzZw8pqxJWcdOJuRsyGPbWDk0tS20zw9SXsobdfytJVXdzNsP61i6Zt3K7Ht0UeUgbPdjsrOXMd+2IS2C2qb271HVWi7YANcNXFQsUEVBTXwNdl46jYRxPl52dnwRUZbhkLSDmS8DnxFRWiULxg8UxvobefuRR8ZQYDKtffVVcQWv/RrfgJC4bd0upw4MQAAAABJRU5ErkJggg==', 
+      'B' => 'iVBORw0KGgoAAAANSUhEUgAAACgAAAAoCAAAAACpleexAAAAFXRFWHRDcmVhdGlvbiBUaW1lAAfTBQ4QGAusrz2zAAAAB3RJTUUH0wUOEC01Gv4B3gAAAAlwSFlzAAALEgAACxIB0t1+/AAAANJJREFUeNpj/M9AHGAiUh0tFTKiAUHL2rsoKv9DARZDWFr+IwA+hQwMFcQqZDhCrMIIYhWK4FYIYv8444PuV+wK//9/A+UJwBUSCHAL3OEIsdoFyttCpGdiiAtHjoY/RCnk6PlBbBRKrCE6CqcQq5DlDs5whIT3CgUI788EvOEIBCegXB2YPCNMBSNMISqf5TeUjysK90LpP/itfrFEAhZCMHkWdKMYUbk2MAah7BqD02pUYEFkgMu8IE6hD0IdpmegwSejoKLjoY7syaFU7A0HhQA2e4cJytImvAAAAABJRU5ErkJggg==', 
+      'C' => 'iVBORw0KGgoAAAANSUhEUgAAACgAAAAoCAAAAACpleexAAAAFXRFWHRDcmVhdGlvbiBUaW1lAAfTBQ4QGBbPqVFqAAAAB3RJTUUH0wUOEC4BEGemqAAAAAlwSFlzAAALEgAACxIB0t1+/AAAASlJREFUeNpj/M9AHGAiUt2owkGrkAWV+3TDgRtPPjBwyGiYBOijSv1HAlcCkGUcTiDLISvsQDOeZQp2hQWYDpuCTeEEbD44ganwDgc2vxpgKoyAyUWc+f9hjgCMtwFd4RuYRxog/ueBcl3QFc6BSmj8gfBrwE40yFmCrjABqrAH5mSZgJ4jX7AEjwlU4Zn/OAAsrp9AaRlccc0IzdeMsBilOPWQrBDmtpfEKnwBpZ8qZq58i6IS6vscKHcBcgQYlOz4gh6OK6AKfaB8G5hN6Aq/wBLPHjB3CczCFIzUA0u2PD0v/j9pgaf1ExgK3wgwYAEOWFL4GizqWC5gyzM1mArnEJkLZ2DPhf//n3BAVmeDkq8ZUZPL3TUn7gBLCgYFBYsAcxQZRmKrDwABNsv9SJSDwwAAAABJRU5ErkJggg==', 
+      'D' => 'iVBORw0KGgoAAAANSUhEUgAAACgAAAAoCAAAAACpleexAAAAFXRFWHRDcmVhdGlvbiBUaW1lAAfTBQ4QGC1+orhOAAAAB3RJTUUH0wUOEC4yr7fHvgAAAAlwSFlzAAALEgAACxIB0t1+/AAAAM9JREFUeNpj/M9AHGAiUt1AKmSBsxiRhXlkNBxCpFFU/ocBTDMyPvxHADwKGRgUbhCpkEHiCZEKGRyIVciwArdCIPPFGg8YzwSvQiBogXFvEFD43wDKnQDl44yZGCh9glAU2sCsJqRQBkq/gMUw3G2wuP6PnU/H9PgRSgsQUvgESosQUngFSqsQUrgCSsNiCFcU7oBx9+CL6w8XamB5SeUPkelxAZEJ1+YPcQolXhCXFTTuEJULOUq+IOVrFgasQELBxMaHG1mEcTiVjwOoEADAIkCnGpmJKgAAAABJRU5ErkJggg==', 
+      'E' => 'iVBORw0KGgoAAAANSUhEUgAAACgAAAAoCAAAAACpleexAAAAFXRFWHRDcmVhdGlvbiBUaW1lAAfTBQ4QGDeDwEE0AAAAB3RJTUUH0wUOEC8CkHXGUwAAAAlwSFlzAAALEgAACxIB0t1+/AAAAD5JREFUeNpj/M9AHGAiUt2owkGrkAXGYMQqjUgJQ8EzpPsa05+D140oMYTk4KEQ4MMqZqgUhcM1czESW30AABfqB1XDnLzcAAAAAElFTkSuQmCC', 
+      'F' => 'iVBORw0KGgoAAAANSUhEUgAAACgAAAAoCAAAAACpleexAAAAFXRFWHRDcmVhdGlvbiBUaW1lAAfTBQ4QGQe8AkDZAAAAB3RJTUUH0wUOEC8JB6cf2wAAAAlwSFlzAAALEgAACxIB0t1+/AAAADlJREFUeNpj/M9AHGAiUt3wUsiCYDJikUYE3lDwDDm+xvTp4HUjIoaQXTsUAnxYxcyoQryAcUSWuAAW/gZTg/yEMAAAAABJRU5ErkJggg==', 
+      'G' => 'iVBORw0KGgoAAAANSUhEUgAAACgAAAAoCAAAAACpleexAAAAFXRFWHRDcmVhdGlvbiBUaW1lAAfTBQ4QGRFI1vWIAAAAB3RJTUUH0wUOEC8QY8y3GwAAAAlwSFlzAAALEgAACxIB0t1+/AAAASZJREFUeNpj/M9AHGAiUt0IVciCwvt7ZM+FOy8+MDBwSEho2AQII8v9R4A/U2RQtHEUfEBIIim8YYBhn8oNLAqP8GBxmcwbDIU3sKljYIhAV/jHgAE7uICmcAJMQqDmwp//D2YowPgxqAr/wPyr8QAi8EEHwleIQFW4BxYicG+eEHEomHECET5QhRVQhQn/cQFoFJ6AKgwgFNcPoFwdnAoZIXmGERahKDwkIdqlR1j4PiRW4RVCCmExvQenQrSYEXiDiAoUBfC4loAK23yBSnzArhCRehRmAJPFnRUxHDgU/lDA7zZECj/Cgl2dAkaeWYNVZcoHDIX/94hgKLM4gS27/v9QIICizGMDkiQjSon7c8eBCw+e/GFgkZEwsHCRRpZiHE5FMwCa2YE+WcAOUwAAAABJRU5ErkJggg==', 
+      'H' => 'iVBORw0KGgoAAAANSUhEUgAAACgAAAAoCAAAAACpleexAAAAFXRFWHRDcmVhdGlvbiBUaW1lAAfTBQ4QGRw2Z4k1AAAAB3RJTUUH0wUOEC8agxleBQAAAAlwSFlzAAALEgAACxIB0t1+/AAAAD1JREFUeNpj/M9AHGAiUt2oQvyABUozQml4+KMLDAXPDAWFLGh8RlwKh4JnaB88GOlxELhxVCFewDgEynAAN2sFVHAvevkAAAAASUVORK5CYII=', 
+      'I' => 'iVBORw0KGgoAAAANSUhEUgAAACgAAAAoCAAAAACpleexAAAAFXRFWHRDcmVhdGlvbiBUaW1lAAfTBQ4QGSlg1E0WAAAAB3RJTUUH0wUOEC86uHd+zQAAAAlwSFlzAAALEgAACxIB0t1+/AAAAD5JREFUeNpj/M9AHGAiUt1AKmRBMBkxJJE9OhQ8Q32FjGhxDQsjjCQwFDwzqnCwKkRKZqO5EBMwDqcSl2iFAMMeB0s/kLo2AAAAAElFTkSuQmCC', 
+      'J' => 'iVBORw0KGgoAAAANSUhEUgAAACgAAAAoCAAAAACpleexAAAAFXRFWHRDcmVhdGlvbiBUaW1lAAfTBQ4QGywiiNsbAAAAB3RJTUUH0wUOEDAFw0tdbgAAAAlwSFlzAAALEgAACxIB0t1+/AAAAKdJREFUeNpj/M9AHGAiUh3xClmwijJCaSR3Ud/qUYWjCklTyIHEhifctw8ePHgCxO+B7L9QMQlsChW+QOiX4gwMd6BiItisVoHSB6AYWQwM/kNBBszkC/9PwKyc8B8B4Ar3YPHMHWwK/xtgqAv4j1XhEfScK/EEu8L/a1BVStz4j0Ph/yPItoe8QFH3nxGlkNq75cKDB0DDVBwitNEcwjhwpdmoQrwAAN6ioiFapgUdAAAAAElFTkSuQmCC', 
+      'K' => 'iVBORw0KGgoAAAANSUhEUgAAACgAAAAoCAAAAACpleexAAAAFXRFWHRDcmVhdGlvbiBUaW1lAAfTBQ4QHAEoFhGpAAAAB3RJTUUH0wUOEDANzZDVXAAAAAlwSFlzAAALEgAACxIB0t1+/AAAAPZJREFUeNpj/M9AHGAiUt2owgFSyAgFMOGDrDARxkKo0H8wYEDh/b/AAzepACqEVeEdCQx1WBW+0ICry/mPR+EXE7i6kD94FP5xwaYOi8IIrOowFRbA1Xkgq8NQ2ANXZ/PlPx6FS3CpQ1fIAmOIoKn7jxbXf2CMNxvQIxvVRAQQ+YDXaiSQQqxChiOEFGoIQGidP/gVStxogLI68CqUuPH/BzSVcTzAoxCo7v//ObBIxK0QrO7/H1iCXIFT4QkIFxbaMh9wKYQJO0D5OYQUnoDF/QkCCuHJ1+APAYV3YOloAgGF8JTO84SAwjfQiGQIgPAZqV4rAACnKSarzdlc4gAAAABJRU5ErkJggg==', 
+      'L' => 'iVBORw0KGgoAAAANSUhEUgAAACgAAAAoCAAAAACpleexAAAAFXRFWHRDcmVhdGlvbiBUaW1lAAfTBQ4QHA64qQw4AAAAB3RJTUUH0wUOEDAXMPIsJgAAAAlwSFlzAAALEgAACxIB0t1+/AAAADlJREFUeNpj/M9AHGAiUt2QUMiCYDJCaezhMBQ8M6pwVCEdFLJgCjEisRH5Zyh4hvoKGUdkQUq0QgARaARRV9jUFQAAAABJRU5ErkJggg==', 
+      'M' => 'iVBORw0KGgoAAAANSUhEUgAAACgAAAAoCAAAAACpleexAAAAFXRFWHRDcmVhdGlvbiBUaW1lAAfTBQ4QHBhMfblpAAAAB3RJTUUH0wUOEDAqaJpgNwAAAAlwSFlzAAALEgAACxIB0t1+/AAAAPNJREFUeNrdlK0OgzAUhS8bCQYxMYmcmEAgEAgejQfZQyG2pAIxOYlATkAu691o2tvSYia2iv7lyzn3NG0jhG1tt5H7Aggom7ZuaKPhBFqKV+pFWDGjjcxStEAYXuvBkrKtoVX+gdRiK9i6sxjgeVGUMJzWwZLACaZOTqoAOAronmrlBuvPkQsIgHn8BqnE2AMmhaaYJ57jqTRFMwsDyW249XaJLhAujizm7UFM5XCUXTqiTvBLQYWRc7H3WWt+3NmlyGbOGh9q/45mjQxUb+CA6A2jSqu5MweX0ooQWLJxLYx6fz0GwmBOsww5GP3At/dX4Ayb7qpFI9y5ygAAAABJRU5ErkJggg==', 
+      'N' => 'iVBORw0KGgoAAAANSUhEUgAAACgAAAAoCAAAAACpleexAAAAFXRFWHRDcmVhdGlvbiBUaW1lAAfTBQ4QHC6DxyzwAAAAB3RJTUUH0wUOEDAye/b4YQAAAAlwSFlzAAALEgAACxIB0t1+/AAAALRJREFUeNpj/M9AHGAiUt0IV8gIARsRMlAROP8/BEB5Ii/+/0cVgXNRhRk8iFXIMIFYhRxXiFTIYPCDSIUMBcQqZNhDrEKZN0QqZAggViHDHIIKRSAUzx1CCrdAaZM/BBT+z4Eyaggp/KEDYbAcIaDw/wUWCEuBkML/PagBgFvhfxdiFT4RIVLh/zXEKvyfQqzCLypEKvx/hoVIhf9biFX4x4ZIhf8fCBCp8P8KNBHG4VQ0AwDEOyeZhO5p1AAAAABJRU5ErkJggg==', 
+      'O' => 'iVBORw0KGgoAAAANSUhEUgAAACgAAAAoCAAAAACpleexAAAAFXRFWHRDcmVhdGlvbiBUaW1lAAfTBQ4QHQExDSDoAAAAB3RJTUUH0wUOEDA4myMRfwAAAAlwSFlzAAALEgAACxIB0t1+/AAAATtJREFUeNpj/M9AHGAiUt3wUsiCyv265ciZJ08YGGRkDGwCuFGk/iOBDwU8SDIcGS+Q5JAV7hBBs45nAVaFC1gwXTYBi8IdWNQxMCzAUPhBBJs6Bp4n6AoLYFI6az78f7NEB8ZNQFP4QwAqEfADwg+A+f0NqsI1UHGBDzCnSKC6EhYzB6B0Cj+UwZ+CKgNTeAZKu8C94QGlL6DGjAyU+wAeXC+gIiIQLiM0KzDC9CFCBlWICsnsL3aFMDc+hcs8QZWBKYSF2g24whvYFZpA6T1whUegNCwyoYGxAmYyLGZ+wOxYghqFX2BpO+APmP8nBspHj2uk1LPizf8PGyxgXPTUQ3x6JDqF//8/AYs6bHkGmCYF0O3FnguBCSaFA0kZS8IDJDlG1IIUVFK8eABMWzI6DgHCyDKMI7LEBQCD5YgI9wbKGgAAAABJRU5ErkJggg==', 
+      'P' => 'iVBORw0KGgoAAAANSUhEUgAAACgAAAAoCAAAAACpleexAAAAFXRFWHRDcmVhdGlvbiBUaW1lAAfTBQ4QHQvR2Mn2AAAAB3RJTUUH0wUOEDEDMzPJGgAAAAlwSFlzAAALEgAACxIB0t1+/AAAAKVJREFUeNpj/M9AHGAiUh05ChlRAKdu4k5Ulf9hANMQiwf/EQCfQgaJB0QqZHAhViHDEbg0AV8vwRM8QN0v5vBAOSfw+BrMWQDl8MClGeEKGGEKQcRXHmQemTGD1RMy+N14o4MDyvGAS7NgGMaIzPHAYyIy4HhBZMy0EBmFIX+IUsjRgqQOi2fAgEVBwyVGGEUEQw2O3EbLzDWSFDIOhtJsVCEWAAC/Yt2X+2PYcgAAAABJRU5ErkJggg==', 
+      'Q' => 'iVBORw0KGgoAAAANSUhEUgAAACgAAAAoCAAAAACpleexAAAAFXRFWHRDcmVhdGlvbiBUaW1lAAfTBQ4QHRxSC0wxAAAAB3RJTUUH0wUOEDEKSu9xvgAAAAlwSFlzAAALEgAACxIB0t1+/AAAAW1JREFUeNpj/M9AHGAiUt2QUMiCzPm65cCZF08YGGRkDBx8uNFU/oeDDwU8SOIcBS/+IwOEwh0iaEYIrMCqcA4LprsmYFG4A4s6BoYFGAo/iGBTx8DzAl1hAUxKZ8WH/29W6MC4KWgKfwhAJXx+gPl/QmB+/4KqcANUXOQDVPiLBFRkCUwhJGb2wGzihzK4U6CMA6hReAbKc4F7wwFKX0CNGRkoB+HJJ1ARGZgAIziFM8J0IUIGXYjMZPaXkEJYYDyBiz+EuRFVoQKUdwWIz6qWvmRguAMVkUBVaIIUalPu9GgshIefAWrwrIHp//L/DQc4KjFiBi2uQ/7832KB5AX0uP5fAZOx2PDhfwNCIXrq+f9BhgEb4HmCkcL3YE3hSHkBnmfWYFMpsoaYXAgGDgcwFKLlaxYOCG2DqRCYrldkmIACUMIgZsaTI5Cg3IBNISp4AoovlT+EFf7/kYPkb3wK//8/YAGPGcYhUIYDAHBC9Yak1w7iAAAAAElFTkSuQmCC', 
+      'R' => 'iVBORw0KGgoAAAANSUhEUgAAACgAAAAoCAAAAACpleexAAAAFXRFWHRDcmVhdGlvbiBUaW1lAAfTBQ4QHSkEuIgSAAAAB3RJTUUH0wUOEDEUsOBM3QAAAAlwSFlzAAALEgAACxIB0t1+/AAAAOZJREFUeNpj/M9AHGAiUh0NFLJAaUY0YRkJHYcQdmSh/xCAzRCZHf8RAJ9CBpYNRCpkEHgBV4jfMx+mEOVGIDDAaTWY82aPBZTLgV8hUCkaH6cbP8B8gxHgyODjgwstMDfiVIgWQyFE+lrhB3EBznOFuJgxuUFMXPPEbPmDpA53FH55osKMIoAe4F826MDMvPMfj9WgWFGBBeIf/Ar/H4FxJhBQ+B8WzCIfCCi8A4uvBgIK/2fA/POCgMIXHFBuDqH02ABLM3cIKPwgAuVHEFD4fwJM4AIBhT9goe4AFWAcAsXesFIIAEvJyZHTCSiTAAAAAElFTkSuQmCC', 
+      'S' => 'iVBORw0KGgoAAAANSUhEUgAAACgAAAAoCAAAAACpleexAAAAFXRFWHRDcmVhdGlvbiBUaW1lAAfTBQ4QHTRnvuTLAAAAB3RJTUUH0wUOEDEbIF9RTAAAAAlwSFlzAAALEgAACxIB0t1+/AAAAVZJREFUeNpj/M9AHGAiUt2oQvyABYX398CWK3de/GBgkVEw8HFgRpH7jwSWqCDLyCxAlkNS+CcG3boY7AozMB3Wgk3hGSw+4HgBl0b4egIWhT9mYPGMBFQg4MH/D2tgvrKASzPC0yMjlP7CDSTOmrDIMDDwiHBsxzSRBypw5j9WgFDoAPNAxIQjX/ApXIDsC4OCLV9wKfzjwIACOEIO4IiZFxbooePzAqvC/z9qONBUStzAqvD//zc9BqgqNX5gVwgETxbkmCClvSk4FYLdsCMCptAGI2YSGV78+PLmz5MX4mDu1ByIMM9n9JiBxe4caGChy8MZMMsUIEFyAMoVwVC4BGaEwpI3/9/MEYGlJQyFPwQYsIE1mL7GlnCR0iNSXLtgqpO4gy1mvtigq1NAxCBKgP9pEUFWxlOCnNIYUYrmn3v23Ljx5gsw88sYOPhwI0sxDoEyHAABtSc836a1EQAAAABJRU5ErkJggg==', 
+      'T' => 'iVBORw0KGgoAAAANSUhEUgAAACgAAAAoCAAAAACpleexAAAAFXRFWHRDcmVhdGlvbiBUaW1lAAfTBQ4QHgUdTbcyAAAAB3RJTUUH0wUOEDEgkVS4aAAAAAlwSFlzAAALEgAACxIB0t1+/AAAADdJREFUeNpj/M9AHGAiUt0IVcgCpRlxyMODeSh4hmiFjGipB+Z7jEQ1FDwzqnBU4WBSyDicimYAb/AFTaJpyH8AAAAASUVORK5CYII=', 
+      'U' => 'iVBORw0KGgoAAAANSUhEUgAAACgAAAAoCAAAAACpleexAAAAFXRFWHRDcmVhdGlvbiBUaW1lAAfTBQ4QHhEHl2NPAAAAB3RJTUUH0wUOEDEon48wWgAAAAlwSFlzAAALEgAACxIB0t1+/AAAAKlJREFUeNpj/M9AHGAiUh3xClmgNCOUhrsEXYD6Vo8qHFVIuUIVKP0USr+E0jLoCjWg9A4ovQVNHJjUIaADZsILMPeFApRfA5X/D1N4AaZRYc6b/2+WwNQxXEBX+N8Bqxcc/mMoPMGCRR3LBUyF/2dgUTjjPxaF/6egm8ky5T9Whf9P2KCoMziBJPefEaWQurjnzIMXL34wsMhoWHiYo2hjHLjSbFQhXgAAKzejCLAOcVMAAAAASUVORK5CYII=', 
+      'V' => 'iVBORw0KGgoAAAANSUhEUgAAACgAAAAoCAAAAACpleexAAAAFXRFWHRDcmVhdGlvbiBUaW1lAAfTBQ4QHh/gL05IAAAAB3RJTUUH0wUOEDEuduyVbwAAAAlwSFlzAAALEgAACxIB0t1+/AAAAVNJREFUeNpj/M9AHGAiUt2owoFRaMgIAYlIMqlQMUMo/z8ITIByRP78hwMRqNgECBei8AULVPQIXN0RqAjLGwgfYrW4B1R4DdzmLVDaQxjZ6v8roDwVuIkqMK3/ka3+/0MAKn4FKn4D5uof/5GtZmCPgEpsQHNDBDsDitVwt5tA+RZQ/pn/qFYj3PQEzHsC5WnA3QyPmQQU3+5AE0VYDTfDBcxzgQbik/8YVv93gMp9AbK/cEAD8T+m1TBb/oD8veEHhs0IE2GmxADZMRAmz4//WKxGkv3DA2Gm/MeqcA/Ujj1w1hHsCv/LQKQz/megRzyawgqIvAxMRwsuhbCEAEvGT3AphEUwNCU5IEv9R8lcUH9/wAxE5HAEgjccSBI8X3CbKOyBxAnhxm3i/w1IEgdQZFA98/+PCFydDKo6VKsZmGPQ0wgOq/+fgYvfQTORkeq1AgCIAvD7+THsDgAAAABJRU5ErkJggg==', 
+      'W' => 'iVBORw0KGgoAAAANSUhEUgAAACgAAAAoCAAAAACpleexAAAAFXRFWHRDcmVhdGlvbiBUaW1lAAfTBQ4QFhZRKnzkAAAAB3RJTUUH0wUOEDIR66frkQAAAAlwSFlzAAALEgAACxIB0t1+/AAAAXNJREFUeNrtlK1ywkAUhZdMZsJMKyIqKhAIBAKBiEBEVCDyCJV9iIo+Do9QGRERgUBEVCAqKhAIREVERURnTvfn3t27xSA6g+kOQ/ZkP/aec5NlBHXZSC7k/sE/AhUwoVkDPQ58/2RUQ2IC6B1XpN7MV8tg62/pUdjSDO7OwR2J0pbekpqZYlMG50bNSGwBDQ4pyV5YtCZ7mqZf1mO2IN2Jynba0XRx49pThjQCbEKWFfVRpIlBzlK4PuLdpxEWlTr4LHvYMEDOaTYS3HCW3DAJt8mmaSXYchZbOfEzkyYGZRbrEbX8qe7GMpLqFeyxV9F4fon1pwcxjxbqJpJTBPBJLoyHYSz1I3xq78aOMssepHZZHFjKhbX9/AZd6e9bsdABeyHTQXiE2PLO6PugCwiP/r1QVLYSlpXwKE1Wno7b7jY+hoWj0aegPyA9+jPrzgqwZJ0j8hhMVtElmDoD19FFPAvamc+sOXBm+KdYEzC63p/9D7Tr72kj/8qjAAAAAElFTkSuQmCC', 
+      'X' => 'iVBORw0KGgoAAAANSUhEUgAAACgAAAAoCAAAAACpleexAAAAFXRFWHRDcmVhdGlvbiBUaW1lAAfTBQ4QHi/G9n7kAAAAB3RJTUUH0wUOEDIXAsROpAAAAAlwSFlzAAALEgAACxIB0t1+/AAAAT9JREFUeNpj/M9AHGAiUt3IVhjKCAFr4RJroSKBMIH/YPBEAMITeQLh//8gAxHggQlAFf6fAdXnA+WnQPkT/qMp/O8AlVkA5h2A8kz+YCi8wQGREngA5PxQgXBYzvzHUPi/A2qIA5BdAmUX/Mei8I8BVHbK/wssEJbMB2wK/5+ASvPcgGlZ8x+rQriFAmghgKHwiwJKXPA8wKXw/x4UhT3/cSr8n4CkzuAPHoVvRODqWE6gyPxHTT1ffiAUCjCgAhRtDkgSFnisnoJixAScCh/wEBk8DmiucsChcA5MQQSMMQWrQlgiZ0iAByey5QiFPlBZnS//v+hgxjZc4QKYKVeAnCswby3AUAi3eAGKNoEn6Ap94A5EjXUfNIUrEA6EALgzl6AohCUGsAMhAOZMkTfICkMw3I5wZgiEyzicimYAFRFkVwgDfJ0AAAAASUVORK5CYII=', 
+      'Y' => 'iVBORw0KGgoAAAANSUhEUgAAACgAAAAoCAAAAACpleexAAAAFXRFWHRDcmVhdGlvbiBUaW1lAAfTBQ4QHjkyIsu1AAAAB3RJTUUH0wUOEDIkvRQvsgAAAAlwSFlzAAALEgAACxIB0t1+/AAAANJJREFUeNrt1L0NgzAQBWAcUVB6AAZgBAoKhmAICoZgCAoKxmAECkbwABSUlBRILwF8duwYhFJEihJ37+6T5T9g8K6N20X3FdDDNjKKOeTIqZLtWcKBU73bCx1lPhgQNTWieY1zRLmGCZFQp1xTSSmBDUUgW754BF+GQLxAPUkMxMb0FlzUsqpKLXhxQPRqo+oIerggCvuMC7jhFJounA4gWhO2OIL6Jp/uzglHrh0fTyAaDRucQaTkUpxDQVBYDWZ/hYze6bsv/A8/DNlP/kgvwzuer4kCMGPZDgAAAABJRU5ErkJggg==', 
+      'Z' => 'iVBORw0KGgoAAAANSUhEUgAAACgAAAAoCAAAAACpleexAAAAFXRFWHRDcmVhdGlvbiBUaW1lAAfTBQ4QHwfqWOdfAAAAB3RJTUUH0wUOEDIrLasyIwAAAAlwSFlzAAALEgAACxIB0t1+/AAAAL5JREFUeNrl1C0OwkAQBWCWQIJEVPQIFT0GAlHBMRBIBKIHqahAIDlERY9R0UOs3ORh5qVLunmp5GfUZvczbzKzDqtltV7ofgtueHCp16h33xBGwn0KYqoTO/J868Csaj418e0cPujOkLDfmTsECcfcXOGhoC/NZQMUDBUDd5DwxiAtJGzprpCw48xVQcIhM1d6KOgLc/kIBcORgXtIeGGQOyRs6Oq0g7P92YbkRE7bRZhcwhh+6nLF5f7yx30B8Z7FgxzMWtEAAAAASUVORK5CYII=', 
+    );
+  
+    return $_png;
+  }
+  
+  // This is designed to randomise the pixels of the image data within
+  // certain limits so as to keep it readable. It also varies the image
+  // width a little
+  function randomise($scanline, $width)
+  {
+    $new_line = '';
+    $start = floor($width/2);
+    $end = strlen($scanline) - ceil($width/2);
+  
+    for ($i = $start; $i < $end; $i++)
+    {
+      $pixel = ord($scanline{$i});
+  
+      if ($pixel < 190)
+      {
+        $new_line .= chr(mt_rand(0, 205));
+      }
+      else if ($pixel > 190)
+      {
+        $new_line .= chr(mt_rand(145, 255));
+      }
+      else
+      {
+        $new_line .= $scanline{$i};
+      }
+    }
+  
+    return $new_line;
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/includes/captcha/engine_freecap.php	Fri Feb 22 12:51:53 2008 -0500
@@ -0,0 +1,810 @@
+<?php
+/************************************************************\
+*
+*		freeCap v1.4.1 Copyright 2005 Howard Yeend
+*		www.puremango.co.uk
+*
+*    This file is part of freeCap.
+*
+*    freeCap is free software; you can redistribute it and/or modify
+*    it under the terms of the GNU General Public License as published by
+*    the Free Software Foundation; either version 2 of the License, or
+*    (at your option) any later version.
+*
+*    freeCap 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 more details.
+*
+*    You should have received a copy of the GNU General Public License
+*    along with freeCap; if not, write to the Free Software
+*    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*
+*
+\************************************************************/
+
+/**
+ * A port of the freeCap captcha engine to Enano.
+ */
+
+class captcha_engine_freecap extends captcha_base
+{
+  
+  var $site_tags = array();
+  var $tag_pos = 0;
+  var $rand_func = "mt_rand";
+  var $seed_func = "mt_srand";
+  var $hash_func = "sha1";
+  var $output = "png";
+  var $use_dict = false;
+  var $dict_location = "";
+  var $max_word_length = 7;
+  var $col_type = 1;
+  var $max_attempts = 20;
+  var $font_locations = Array();
+  var $bg_type = 3;
+  var $blur_bg = false;
+  var $bg_images = Array();
+  var $merge_type = 0;
+  var $morph_bg = true;
+  var $im, $im2, $im3;
+  var $font_size = 36;
+  var $debug = false;
+  
+  function __construct($s, $r = false)
+  {
+    parent::__construct($s, $r);
+    
+    // try to avoid the 'free p*rn' method of CAPTCHA circumvention
+    // see en.wikipedia.org/wiki/CAPTCHA for more info
+    // $this->site_tags[0] = "To avoid spam, please do NOT enter the text if";
+    // $this->site_tags[1] = "this site is not puremango.co.uk";
+    // or more simply:
+    // $site_tags[0] = "for use only on puremango.co.uk";
+    // reword or add lines as you please
+    // or if you don't want any text:
+    $this->site_tags = array();
+    
+    // where to write the above:
+    // 0=top
+    // 1=bottom
+    // 2=both
+    $this->tag_pos = 1;
+    
+    // functions to call for random number generation
+    // mt_rand produces 'better' random numbers
+    // but if your server doesn't support it, it's fine to use rand instead
+    $this->rand_func = "mt_rand";
+    $this->seed_func = "mt_srand";
+    
+    // which type of hash to use?
+    // possible values: "sha1", "md5", "crc32"
+    // sha1 supported by PHP4.3.0+
+    // md5 supported by PHP3+
+    // crc32 supported by PHP4.0.1+
+    $this->hash_func = $this->session_fetch('hash_func', 'sha1');
+    // store in session so can validate in form processor
+    
+    // image type:
+    // possible values: "jpg", "png", "gif"
+    // jpg doesn't support transparency (transparent bg option ends up white)
+    // png isn't supported by old browsers (see http://www.libpng.org/pub/png/pngstatus.html)
+    // gif may not be supported by your GD Lib.
+    $this->output = "png";
+    
+    // 0=generate pseudo-random string, true=use dictionary
+    // dictionary is easier to recognise
+    // - both for humans and computers, so use random string if you're paranoid.
+    $this->use_dict = false;
+    // if your server is NOT set up to deny web access to files beginning ".ht"
+    // then you should ensure the dictionary file is kept outside the web directory
+    // eg: if www.foo.com/index.html points to c:\website\www\index.html
+    // then the dictionary should be placed in c:\website\dict.txt
+    // test your server's config by trying to access the dictionary through a web browser
+    // you should NOT be able to view the contents.
+    // can leave this blank if not using dictionary
+    $this->dict_location = ENANO_ROOT . "/includes/captcha/dicts/default.php";
+    
+    // used to calculate image width, and for non-dictionary word generation
+    $this->max_word_length = 7;
+    
+    // text colour
+    // 0=one random colour for all letters
+    // 1=different random colour for each letter
+    $this->col_type = 1;
+    
+    // maximum times a user can refresh the image
+    // on a 6500 word dictionary, I think 15-50 is enough to not annoy users and make BF unfeasble.
+    // further notes re: BF attacks in "avoid brute force attacks" section, below
+    // on the other hand, those attempting OCR will find the ability to request new images
+    // very useful; if they can't crack one, just grab an easier target...
+    // for the ultra-paranoid, setting it to <5 will still work for most users
+    $this->max_attempts = 20;
+    
+    // list of fonts to use
+    // font size should be around 35 pixels wide for each character.
+    // you can use my GD fontmaker script at www.puremango.co.uk to create your own fonts
+    // There are other programs to can create GD fonts, but my script allows a greater
+    // degree of control over exactly how wide each character is, and is therefore
+    // recommended for 'special' uses. For normal use of GD fonts,
+    // the GDFontGenerator @ http://www.philiplb.de is excellent for convering ttf to GD
+    
+    // the fonts included with freeCap *only* include lowercase alphabetic characters
+    // so are not suitable for most other uses
+    // to increase security, you really should add other fonts
+    $this->font_locations = Array(
+        //ENANO_ROOT . "/includes/captcha/fonts/assimila.ttf",
+        //ENANO_ROOT . "/includes/captcha/fonts/elephant.ttf",
+        //ENANO_ROOT . "/includes/captcha/fonts/swash_normal.ttf",
+        //ENANO_ROOT . "/includes/captcha/fonts/.ttf",
+        //ENANO_ROOT . "/includes/captcha/fonts/trekker_regular.ttf"
+        ENANO_ROOT . "/includes/captcha/fonts/FreeMonoBold.ttf",
+        ENANO_ROOT . "/includes/captcha/fonts/FreeSerifBold.ttf",
+        ENANO_ROOT . "/includes/captcha/fonts/LiberationSans-Bold.ttf",
+      );
+    
+    // background:
+    // 0=transparent (if jpg, white)
+    // 1=white bg with grid
+    // 2=white bg with squiggles
+    // 3=morphed image blocks
+    // 'random' background from v1.3 didn't provide any extra security (according to 2 independent experts)
+    // many thanks to http://ocr-research.org.ua and http://sam.zoy.org/pwntcha/ for testing
+    // for jpgs, 'transparent' is white
+    $this->bg_type = 3;
+    // should we blur the background? (looks nicer, makes text easier to read, takes longer)
+    $this->blur_bg = false;
+    
+    // for bg_type 3, which images should we use?
+    // if you add your own, make sure they're fairly 'busy' images (ie a lot of shapes in them)
+    $this->bg_images = Array(
+        ENANO_ROOT . "/includes/captcha/pics/freecap_im1.jpg",
+        ENANO_ROOT . "/includes/captcha/pics/freecap_im2.jpg",
+        ENANO_ROOT . "/includes/captcha/pics/freecap_im3.jpg",
+        ENANO_ROOT . "/includes/captcha/pics/freecap_im4.jpg",
+        ENANO_ROOT . "/includes/captcha/pics/allyourbase.jpg"
+      );
+    
+    // for non-transparent backgrounds only:
+    // if 0, merges CAPTCHA with bg
+    // if 1, write CAPTCHA over bg
+    $this->merge_type = 0;
+    // should we morph the bg? (recommend yes, but takes a little longer to compute)
+    $this->morph_bg = true;
+    
+    // you shouldn't need to edit anything below this, but it's extensively commented if you do want to play
+    // have fun, and email me with ideas, or improvements to the code (very interested in speed improvements)
+    // hope this script saves some spam :-)
+  }
+  
+  //////////////////////////////////////////////////////
+  ////// Functions:
+  //////////////////////////////////////////////////////
+  function make_seed() {
+  // from http://php.net/srand
+      list($usec, $sec) = explode(' ', microtime());
+      return (float) $sec + ((float) $usec * 100000);
+  }
+  
+  function rand_color() {
+    $rf =& $this->rand_func;
+    if($this->bg_type==3)
+    {
+      // needs darker colour..
+      return $rf(10,100);
+    } else {
+      return $rf(60,170);
+    }
+  }
+  
+  function myImageBlur($im)
+  {
+    // w00t. my very own blur function
+    // in GD2, there's a gaussian blur function. bunch of bloody show-offs... :-)
+  
+    $width = imagesx($im);
+    $height = imagesy($im);
+  
+    $temp_im = ImageCreateTrueColor($width,$height);
+    $bg = ImageColorAllocate($temp_im,150,150,150);
+  
+    // preserves transparency if in orig image
+    ImageColorTransparent($temp_im,$bg);
+  
+    // fill bg
+    ImageFill($temp_im,0,0,$bg);
+  
+    // anything higher than 3 makes it totally unreadable
+    // might be useful in a 'real' blur function, though (ie blurring pictures not text)
+    $distance = 1;
+    // use $distance=30 to have multiple copies of the word. not sure if this is useful.
+  
+    // blur by merging with itself at different x/y offsets:
+    ImageCopyMerge($temp_im, $im, 0, 0, 0, $distance, $width, $height-$distance, 70);
+    ImageCopyMerge($im, $temp_im, 0, 0, $distance, 0, $width-$distance, $height, 70);
+    ImageCopyMerge($temp_im, $im, 0, $distance, 0, 0, $width, $height, 70);
+    ImageCopyMerge($im, $temp_im, $distance, 0, 0, 0, $width, $height, 70);
+    // remove temp image
+    ImageDestroy($temp_im);
+  
+    return $im;
+  }
+  
+  function sendImage($pic)
+  {
+    // output image with appropriate headers
+    global $output,$im,$im2,$im3;
+    // ENANO - obfuscation technique disabled
+    // (this is for ethical reasons - ask dan at enanocms.org for information on why)
+    // Basically it outputs an X-Captcha header showing freeCap version, etc. Unnecessary
+    // header(base64_decode("WC1DYXB0Y2hhOiBmcmVlQ2FwIDEuNCAtIHd3dy5wdXJlbWFuZ28uY28udWs="));
+    
+    if ( $this->debug )
+    {
+      $x = imagesx($pic) - 70;
+      $y = imagesy($pic) - 20;
+      
+      $code = $this->get_code();
+      $red = ImageColorAllocateAlpha($pic, 0xAA, 0, 0, 72);
+      ImageString($pic, 5, $x, $y, $code, $red);
+      ImageString($pic, 5, 5, $y, "[debug mode]", $red);
+    }
+    
+    switch($this->output)
+    {
+      // add other cases as desired
+      case "jpg":
+        header("Content-Type: image/jpeg");
+        ImageJPEG($pic);
+        break;
+      case "gif":
+        header("Content-Type: image/gif");
+        ImageGIF($pic);
+        break;
+      case "png":
+      default:
+        header("Content-Type: image/png");
+        ImagePNG($pic);
+        break;
+    }
+  
+    // kill GD images (removes from memory)
+    ImageDestroy($this->im);
+    ImageDestroy($this->im2);
+    ImageDestroy($pic);
+    if(!empty($this->im3))
+    {
+      ImageDestroy($this->im3);
+    }
+    exit();
+  }
+  
+  function make_image()
+  {
+    //////////////////////////////////////////////////////
+    ////// Create Images + initialise a few things
+    //////////////////////////////////////////////////////
+    
+    // seed random number generator
+    // PHP 4.2.0+ doesn't need this, but lower versions will
+    $this->seed_func($this->make_seed());
+    
+    // how faded should the bg be? (100=totally gone, 0=bright as the day)
+    // to test how much protection the bg noise gives, take a screenshot of the freeCap image
+    // and take it into a photo editor. play with contrast and brightness.
+    // If you can remove most of the bg, then it's not a good enough percentage
+    switch($this->bg_type)
+    {
+      case 0:
+        break;
+      case 1:
+      case 2:
+        $bg_fade_pct = 65;
+        break;
+      case 3:
+        $bg_fade_pct = 50;
+        break;
+    }
+    // slightly randomise the bg fade
+    $bg_fade_pct += $this->rand_func(-2,2);
+    
+    // read each font and get font character widths
+    // $font_widths = Array();
+    // for($i=0 ; $i<sizeof($this->font_locations) ; $i++)
+    // {
+    //   $handle = fopen($this->font_locations[$i],"r");
+    //   // read header of GD font, up to char width
+    //   $c_wid = fread($handle,15);
+    //   $font_widths[$i] = ord($c_wid{8})+ord($c_wid{9})+ord($c_wid{10})+ord($c_wid{11});
+    //   fclose($handle);
+    // }
+    
+    // modify image width depending on maximum possible length of word
+    // you shouldn't need to use words > 6 chars in length really.
+    $width = ($this->max_word_length*($this->font_size+10)+75);
+    $height = 90;
+    
+    $this->im = ImageCreateTrueColor($width, $height);
+    $this->im2 = ImageCreateTrueColor($width, $height);
+    
+    ////////////////////////////////////////////////////////
+    // GENERATE IMAGE                                     //
+    ////////////////////////////////////////////////////////
+    
+    $word = $this->get_code();
+    
+    // save hash of word for comparison
+    // using hash so that if there's an insecurity elsewhere (eg on the form processor),
+    // an attacker could only get the hash
+    // also, shared servers usually give all users access to the session files
+    // echo `ls /tmp`; and echo `more /tmp/someone_elses_session_file`; usually work
+    // so even if your site is 100% secure, someone else's site on your server might not be
+    // hence, even if attackers can read the session file, they can't get the freeCap word
+    // (though most hashes are easy to brute force for simple strings)
+    
+    //////////////////////////////////////////////////////
+    ////// Fill BGs and Allocate Colours:
+    //////////////////////////////////////////////////////
+    
+    // set tag colour
+    // have to do this before any distortion
+    // (otherwise colour allocation fails when bg type is 1)
+    $tag_col = ImageColorAllocate($this->im,10,10,10);
+    $site_tag_col2 = ImageColorAllocate($this->im2,0,0,0);
+    
+    // set debug colours (text colours are set later)
+    $debug = ImageColorAllocate($this->im, 255, 0, 0);
+    $debug2 = ImageColorAllocate($this->im2, 255, 0, 0);
+    
+    // set background colour (can change to any colour not in possible $text_col range)
+    // it doesn't matter as it'll be transparent or coloured over.
+    // if you're using bg_type 3, you might want to try to ensure that the color chosen
+    // below doesn't appear too much in any of your background images.
+    $bg = ImageColorAllocate($this->im, 254, 254, 254);
+    $bg2 = ImageColorAllocate($this->im2, 254, 254, 254);
+    
+    // set transparencies
+    ImageColorTransparent($this->im,$bg);
+    // im2 transparent to allow characters to overlap slightly while morphing
+    ImageColorTransparent($this->im2,$bg2);
+    
+    // fill backgrounds
+    ImageFill($this->im,0,0,$bg);
+    ImageFill($this->im2,0,0,$bg2);
+    
+    if($this->bg_type!=0)
+    {
+      // generate noisy background, to be merged with CAPTCHA later
+      // any suggestions on how best to do this much appreciated
+      // sample code would be even better!
+      // I'm not an OCR expert (hell, I'm not even an image expert; puremango.co.uk was designed in MsPaint)
+      // so the noise models are based around my -guesswork- as to what would make it hard for an OCR prog
+      // ideally, the character obfuscation would be strong enough not to need additional background noise
+      // in any case, I hope at least one of the options given here provide some extra security!
+    
+      $this->im3 = ImageCreateTrueColor($width,$height);
+      $temp_bg = ImageCreateTrueColor($width*1.5,$height*1.5);
+      $bg3 = ImageColorAllocate($this->im3,255,255,255);
+      ImageFill($this->im3,0,0,$bg3);
+      $temp_bg_col = ImageColorAllocate($temp_bg,255,255,255);
+      ImageFill($temp_bg,0,0,$temp_bg_col);
+    
+      // we draw all noise onto temp_bg
+      // then if we're morphing, merge from temp_bg to im3
+      // or if not, just copy a $widthx$height portion of $temp_bg to $this->im3
+      // temp_bg is much larger so that when morphing, the edges retain the noise.
+    
+      if($this->bg_type==1)
+      {
+        // grid bg:
+    
+        // draw grid on x
+        for($i=$this->rand_func(6,20) ; $i<$width*2 ; $i+=$this->rand_func(10,25))
+        {
+          ImageSetThickness($temp_bg,$this->rand_func(2,6));
+          $text_r = $this->rand_func(100,150);
+          $text_g = $this->rand_func(100,150);
+          $text_b = $this->rand_func(100,150);
+          $text_colour3 = ImageColorAllocate($temp_bg, $text_r, $text_g, $text_b);
+    
+          ImageLine($temp_bg,$i,0,$i,$height*2,$text_colour3);
+        }
+        // draw grid on y
+        for($i=$this->rand_func(6,20) ; $i<$height*2 ; $i+=$this->rand_func(10,25))
+        {
+          ImageSetThickness($temp_bg,$this->rand_func(2,6));
+          $text_r = $this->rand_func(100,150);
+          $text_g = $this->rand_func(100,150);
+          $text_b = $this->rand_func(100,150);
+          $text_colour3 = ImageColorAllocate($temp_bg, $text_r, $text_g, $text_b);
+    
+          ImageLine($temp_bg,0,$i,$width*2, $i ,$text_colour3);
+        }
+      } else if($this->bg_type==2) {
+        // draw squiggles!
+    
+        $bg3 = ImageColorAllocate($this->im3,255,255,255);
+        ImageFill($this->im3,0,0,$bg3);
+        ImageSetThickness($temp_bg,4);
+    
+        for($i=0 ; $i<strlen($word)+1 ; $i++)
+        {
+          $text_r = $this->rand_func(100,150);
+          $text_g = $this->rand_func(100,150);
+          $text_b = $this->rand_func(100,150);
+          $text_colour3 = ImageColorAllocate($temp_bg, $text_r, $text_g, $text_b);
+    
+          $points = Array();
+          // draw random squiggle for each character
+          // the longer the loop, the more complex the squiggle
+          // keep random so OCR can't say "if found shape has 10 points, ignore it"
+          // each squiggle will, however, be a closed shape, so OCR could try to find
+          // line terminations and start from there. (I don't think they're that advanced yet..)
+          for($j=1 ; $j<$this->rand_func(5,10) ; $j++)
+          {
+            $points[] = $this->rand_func(1*(20*($i+1)),1*(50*($i+1)));
+            $points[] = $this->rand_func(30,$height+30);
+          }
+    
+          ImagePolygon($temp_bg,$points,intval(sizeof($points)/2),$text_colour3);
+        }
+    
+      } else if($this->bg_type==3) {
+        // take random chunks of $this->bg_images and paste them onto the background
+    
+        for($i=0 ; $i<sizeof($this->bg_images) ; $i++)
+        {
+          // read each image and its size
+          $temp_im[$i] = ImageCreateFromJPEG($this->bg_images[$i]);
+          $temp_width[$i] = imagesx($temp_im[$i]);
+          $temp_height[$i] = imagesy($temp_im[$i]);
+        }
+    
+        $blocksize = $this->rand_func(20,60);
+        for($i=0 ; $i<$width*2 ; $i+=$blocksize)
+        {
+          // could randomise blocksize here... hardly matters
+          for($j=0 ; $j<$height*2 ; $j+=$blocksize)
+          {
+            $this->image_index = $this->rand_func(0,sizeof($temp_im)-1);
+            $cut_x = $this->rand_func(0,$temp_width[$this->image_index]-$blocksize);
+            $cut_y = $this->rand_func(0,$temp_height[$this->image_index]-$blocksize);
+            ImageCopy($temp_bg, $temp_im[$this->image_index], $i, $j, $cut_x, $cut_y, $blocksize, $blocksize);
+          }
+        }
+        for($i=0 ; $i<sizeof($temp_im) ; $i++)
+        {
+          // remove bgs from memory
+          ImageDestroy($temp_im[$i]);
+        }
+    
+        // for debug:
+        //sendImage($temp_bg);
+      }
+    
+      // for debug:
+      //sendImage($this->im3);
+    
+      if($this->morph_bg)
+      {
+        // morph background
+        // we do this separately to the main text morph because:
+        // a) the main text morph is done char-by-char, this is done across whole image
+        // b) if an attacker could un-morph the bg, it would un-morph the CAPTCHA
+        // hence bg is morphed differently to text
+        // why do we morph it at all? it might make it harder for an attacker to remove the background
+        // morph_chunk 1 looks better but takes longer
+    
+        // this is a different and less perfect morph than the one we do on the CAPTCHA
+        // occasonally you get some dark background showing through around the edges
+        // it doesn't need to be perfect as it's only the bg.
+        $morph_chunk = $this->rand_func(1,5);
+        $morph_y = 0;
+        for($x=0 ; $x<$width ; $x+=$morph_chunk)
+        {
+          $morph_chunk = $this->rand_func(1,5);
+          $morph_y += $this->rand_func(-1,1);
+          ImageCopy($this->im3, $temp_bg, $x, 0, $x+30, 30+$morph_y, $morph_chunk, $height*2);
+        }
+    
+        ImageCopy($temp_bg, $this->im3, 0, 0, 0, 0, $width, $height);
+    
+        $morph_x = 0;
+        for($y=0 ; $y<=$height; $y+=$morph_chunk)
+        {
+          $morph_chunk = $this->rand_func(1,5);
+          $morph_x += $this->rand_func(-1,1);
+          ImageCopy($this->im3, $temp_bg, $morph_x, $y, 0, $y, $width, $morph_chunk);
+    
+        }
+      } else {
+        // just copy temp_bg onto im3
+        ImageCopy($this->im3,$temp_bg,0,0,30,30,$width,$height);
+      }
+    
+      ImageDestroy($temp_bg);
+    
+      if($this->blur_bg)
+      {
+        $this->myImageBlur($this->im3);
+      }
+    }
+    // for debug:
+    //sendImage($this->im3);
+    
+    //////////////////////////////////////////////////////
+    ////// Write Word
+    //////////////////////////////////////////////////////
+    
+    // write word in random starting X position
+    $word_start_x = $this->rand_func(5,32);
+    // y positions jiggled about later
+    $word_start_y = 50;
+    
+    // use last pixelwidth
+    $font_pixelwidth = $this->font_size + 10;
+    
+    if($this->col_type==0)
+    {
+      $text_r = $this->rand_color();
+      $text_g = $this->rand_color();
+      $text_b = $this->rand_color();
+      $text_colour2 = ImageColorAllocate($this->im2, $text_r, $text_g, $text_b);
+    }
+    
+    // write each char in different font
+    for($i=0 ; $i<strlen($word) ; $i++)
+    {
+      if($this->col_type==1)
+      {
+        $text_r = $this->rand_color();
+        $text_g = $this->rand_color();
+        $text_b = $this->rand_color();
+        $text_colour2 = ImageColorAllocate($this->im2, $text_r, $text_g, $text_b);
+      }
+    
+      $j = $this->rand_func(0,sizeof($this->font_locations)-1);
+      // $font = ImageLoadFont($this->font_locations[$j]);
+      // ImageString($this->im2, $font, $word_start_x+($font_widths[$j]*$i), $word_start_y, $word{$i}, $text_colour2);
+      ImageTTFText($this->im2, $this->font_size, 0, $word_start_x+(($font_pixelwidth)*$i), $word_start_y, $text_colour2, $this->font_locations[$j], $word{$i});
+    }
+    
+    // for debug:
+    // $this->sendImage($this->im2);
+    
+    //////////////////////////////////////////////////////
+    ////// Morph Image:
+    //////////////////////////////////////////////////////
+    
+    // calculate how big the text is in pixels
+    // (so we only morph what we need to)
+    $word_pix_size = $word_start_x+(strlen($word)*$font_pixelwidth);
+    
+    // firstly move each character up or down a bit:
+    $y_pos = 0;
+    for($i=$word_start_x ; $i<$word_pix_size ; $i+=$font_pixelwidth)
+    {
+      // move on Y axis
+      // deviates at least 4 pixels between each letter
+      $prev_y = $y_pos;
+      do{
+        $y_pos = $this->rand_func(-5,5);
+      } while($y_pos<$prev_y+2 && $y_pos>$prev_y-2);
+      ImageCopy($this->im, $this->im2, $i, $y_pos, $i, 0, $font_pixelwidth, $height);
+    
+      // for debug:
+      // ImageRectangle($this->im,$i,$y_pos+10,$i+$font_pixelwidth,$y_pos+70,$debug);
+    }
+    
+    // for debug:
+    // $this->sendImage($this->im);
+    
+    ImageFilledRectangle($this->im2,0,0,$width,$height,$bg2);
+    
+    // randomly morph each character individually on x-axis
+    // this is where the main distortion happens
+    // massively improved since v1.2
+    $y_chunk = 1;
+    $morph_factor = 1;
+    $morph_x = 0;
+    for($j=0 ; $j<strlen($word) ; $j++)
+    {
+      $y_pos = 0;
+      for($i=0 ; $i<=$height; $i+=$y_chunk)
+      {
+        $orig_x = $word_start_x+($j*$font_pixelwidth);
+        // morph x += so that instead of deviating from orig x each time, we deviate from where we last deviated to
+        // get it? instead of a zig zag, we get more of a sine wave.
+        // I wish we could deviate more but it looks crap if we do.
+        $morph_x += $this->rand_func(-$morph_factor,$morph_factor);
+        // had to change this to ImageCopyMerge when starting using ImageCreateTrueColor
+        // according to the manual; "when (pct is) 100 this function behaves identically to imagecopy()"
+        // but this is NOT true when dealing with transparencies...
+        ImageCopyMerge($this->im2, $this->im, $orig_x+$morph_x, $i+$y_pos, $orig_x, $i, $font_pixelwidth, $y_chunk, 100);
+    
+        // for debug:
+        //ImageLine($this->im2, $orig_x+$morph_x, $i, $orig_x+$morph_x+1, $i+$y_chunk, $debug2);
+        //ImageLine($this->im2, $orig_x+$morph_x+$font_pixelwidth, $i, $orig_x+$morph_x+$font_pixelwidth+1, $i+$y_chunk, $debug2);
+      }
+    }
+    
+    // for debug:
+    //sendImage($this->im2);
+    
+    ImageFilledRectangle($this->im,0,0,$width,$height,$bg);
+    // now do the same on the y-axis
+    // (much easier because we can just do it across the whole image, don't have to do it char-by-char)
+    $y_pos = 0;
+    $x_chunk = 1;
+    for($i=0 ; $i<=$width ; $i+=$x_chunk)
+    {
+      // can result in image going too far off on Y-axis;
+      // not much I can do about that, apart from make image bigger
+      // again, I wish I could do 1.5 pixels
+      $y_pos += $this->rand_func(-1,1);
+      ImageCopy($this->im, $this->im2, $i, $y_pos, $i, 0, $x_chunk, $height);
+    
+      // for debug:
+      //ImageLine($this->im,$i+$x_chunk,0,$i+$x_chunk,100,$debug);
+      //ImageLine($this->im,$i,$y_pos+25,$i+$x_chunk,$y_pos+25,$debug);
+    }
+    
+    // for debug:
+    //sendImage($this->im);
+    
+    // blur edges:
+    // doesn't really add any security, but looks a lot nicer, and renders text a little easier to read
+    // for humans (hopefully not for OCRs, but if you know better, feel free to disable this function)
+    // (and if you do, let me know why)
+    $this->myImageBlur($this->im);
+    
+    // for debug:
+    //sendImage($this->im);
+    
+    if($this->output!="jpg" && $this->bg_type==0)
+    {
+      // make background transparent
+      ImageColorTransparent($this->im,$bg);
+    }
+    
+    
+    
+    
+    
+    //////////////////////////////////////////////////////
+    ////// Try to avoid 'free p*rn' style CAPTCHA re-use
+    //////////////////////////////////////////////////////
+    // ('*'ed to stop my site coming up for certain keyword searches on google)
+    
+    // can obscure CAPTCHA word in some cases..
+    
+    // write site tags 'shining through' the morphed image
+    ImageFilledRectangle($this->im2,0,0,$width,$height,$bg2);
+    if(is_array($this->site_tags))
+    {
+      for($i=0 ; $i<sizeof($this->site_tags) ; $i++)
+      {
+        // ensure tags are centered
+        $tag_width = strlen($this->site_tags[$i])*6;
+        // write tag is chosen position
+        if($this->tag_pos==0 || $this->tag_pos==2)
+        {
+          // write at top
+          ImageString($this->im2, 2, intval($width/2)-intval($tag_width/2), (10*$i), $this->site_tags[$i], $site_tag_col2);
+        }
+        if($this->tag_pos==1 || $this->tag_pos==2)
+        {
+          // write at bottom
+          ImageString($this->im2, 2, intval($width/2)-intval($tag_width/2), ($height-34+($i*10)), $this->site_tags[$i], $site_tag_col2);
+        }
+      }
+    }
+    ImageCopyMerge($this->im2,$this->im,0,0,0,0,$width,$height,80);
+    ImageCopy($this->im,$this->im2,0,0,0,0,$width,$height);
+    // for debug:
+    //sendImage($this->im);
+    
+    
+    
+    
+    //////////////////////////////////////////////////////
+    ////// Merge with obfuscated background
+    //////////////////////////////////////////////////////
+    
+    if($this->bg_type!=0)
+    {
+      // merge bg image with CAPTCHA image to create smooth background
+    
+      // fade bg:
+      if($this->bg_type!=3)
+      {
+        $temp_im = ImageCreateTrueColor($width,$height);
+        $white = ImageColorAllocate($temp_im,255,255,255);
+        ImageFill($temp_im,0,0,$white);
+        ImageCopyMerge($this->im3,$temp_im,0,0,0,0,$width,$height,$bg_fade_pct);
+        // for debug:
+        //sendImage($this->im3);
+        ImageDestroy($temp_im);
+        $c_fade_pct = 50;
+      } else {
+        $c_fade_pct = $bg_fade_pct;
+      }
+    
+      // captcha over bg:
+      // might want to not blur if using this method
+      // otherwise leaves white-ish border around each letter
+      if($this->merge_type==1)
+      {
+        ImageCopyMerge($this->im3,$this->im,0,0,0,0,$width,$height,100);
+        ImageCopy($this->im,$this->im3,0,0,0,0,$width,$height);
+      } else {
+        // bg over captcha:
+        ImageCopyMerge($this->im,$this->im3,0,0,0,0,$width,$height,$c_fade_pct);
+      }
+    }
+    // for debug:
+    //sendImage($this->im);
+    
+    
+    //////////////////////////////////////////////////////
+    ////// Write tags, remove variables and output!
+    //////////////////////////////////////////////////////
+    
+    // tag it
+    // feel free to remove/change
+    // but if it's not essential I'd appreciate you leaving it
+    // after all, I've put a lot of work into this and am giving it away for free
+    // the least you could do is give me credit (or buy me stuff from amazon!)
+    // but I understand that in professional environments, your boss might not like this tag
+    // so that's cool.
+    $tag_str = "";
+    // for debug:
+    //$tag_str = "[".$word."]";
+    
+    // ensure tag is right-aligned
+    $tag_width = strlen($tag_str)*6;
+    // write tag
+    ImageString($this->im, 2, $width-$tag_width, $height-13, $tag_str, $tag_col);
+    
+    // unset all sensetive vars
+    // in case someone include()s this file on a shared server
+    // you might think this unneccessary, as it exit()s
+    // but by using register_shutdown_function
+    // on a -very- insecure shared server, they -might- be able to get the word
+    unset($word);
+    // the below aren't really essential, but might aid an OCR attack if discovered.
+    // so we unset them
+    
+    // output final image :-)
+    $this->sendImage($this->im);
+    // (sendImage also destroys all used images)
+  }
+  
+  function rand_func($s, $m)
+  {
+    global $_starttime;
+    $tn = microtime_float() - $_starttime;
+    if ( $tn > 5 )
+    {
+      echo '<pre>';
+      enano_debug_print_backtrace();
+      echo '</pre>';
+      exit;
+    }
+    $rf =& $this->rand_func;
+    return $rf($s, $m);
+  }
+  
+  function seed_func($s)
+  {
+    $rf =& $this->seed_func;
+    return $rf($s);
+  }
+  
+  function hash_func($s)
+  {
+    $rf =& $this->hash_func;
+    return $rf($s);
+  }
+  
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/includes/captcha/engine_potpourri.php	Fri Feb 22 12:51:53 2008 -0500
@@ -0,0 +1,332 @@
+<?php
+
+/*
+ * Enano - an open-source CMS capable of wiki functions, Drupal-like sidebar blocks, and everything in between
+ * Version 1.1.2 (Caoineag alpha 2)
+ * Copyright (C) 2006-2007 Dan Fuhry
+ * captcha.php - visual confirmation system used during registration
+ *
+ * This program is Free Software; you can redistribute and/or modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.
+ *
+ * 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.
+ */
+
+/**
+ * A more complex captcha engine that relies on GD.
+ * @package Enano
+ * @subpackage User management
+ * @copyright 2007-2008 Dan Fuhry
+ * @copyright 2002-2008 phpBB Group
+ */
+ 
+class captcha_engine_potpourri extends captcha_base
+{
+  var $captcha_config;
+  
+  function __construct($sid, $r = false)
+  {
+    parent::__construct($sid, $r);
+    
+    $hex = Array('0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F');
+    $latticecolor = '#';
+    for ( $i = 0; $i < 6; $i++ )
+      $latticecolor .= $hex[mt_rand(0, 15)];
+    
+    $this->captcha_config = array (
+      'width' => '350',
+      'height' => '90',
+      'background_color' => '#E5ECF9',
+      'jpeg' => '0',
+      'jpeg_quality' => '95',
+      'pre_letters' => '1',
+      'pre_letters_great' => '0',
+      'font' => '1',
+      'chess' => '2',
+      'ellipses' => '2',
+      'arcs' => '2',
+      'lines' => '2',
+      'image' => '0',
+      'gammacorrect' => '0.8',
+      'foreground_lattice_x' => (string)mt_rand(25, 30),
+      'foreground_lattice_y' => (string)mt_rand(25, 30),
+      'lattice_color' => $latticecolor,
+    );
+  }
+  
+  function make_image()
+  {
+    $code = $this->get_code();
+    
+    // Prefs
+    $total_width = $this->captcha_config['width'];
+    $total_height = $this->captcha_config['height'];
+    
+    $hex_bg_color = $this->get_rgb($this->captcha_config['background_color']);
+    $bg_color = array();
+    $bg_color = explode(",", $hex_bg_color);
+    
+    $jpeg = $this->captcha_config['jpeg'];
+    $img_quality = $this->captcha_config['jpeg_quality'];
+    // Max quality is 95
+    
+    $pre_letters = $this->captcha_config['pre_letters'];
+    $pre_letter_great = $this->captcha_config['pre_letters_great'];
+    $rnd_font = $this->captcha_config['font'];
+    $chess = $this->captcha_config['chess'];
+    $ellipses = $this->captcha_config['ellipses'];
+    $arcs = $this->captcha_config['arcs'];
+    $lines = $this->captcha_config['lines'];
+    $image = $this->captcha_config['image'];
+    
+    $gammacorrect = $this->captcha_config['gammacorrect'];
+    
+    $foreground_lattice_y = $this->captcha_config['foreground_lattice_y'];
+    $foreground_lattice_x = $this->captcha_config['foreground_lattice_x'];
+    $hex_lattice_color = $this->get_rgb($this->captcha_config['lattice_color']);
+    $rgb_lattice_color = array();
+    $rgb_lattice_color = explode(",", $hex_lattice_color);
+    
+    $font_debug = false;
+    
+    // Fonts and images init
+    if ($image)
+    {
+      $bg_imgs = array();
+      if ($img_dir = opendir(ENANO_ROOT.'/includes/captcha/pics/'))
+      {
+        while (true == ($file = @readdir($img_dir))) 
+        { 
+          if ((substr(strtolower($file), -3) == 'jpg') || (substr(strtolower($file), -3) == 'gif'))    
+          {         
+            $bg_imgs[] = $file; 
+          }     
+        }
+        closedir($img_dir);
+      }
+      // Grab a random Background Image or set FALSE if none was found
+      $bg_img = ( count($bg_imgs) ) ? rand(0, (count($bg_imgs)-1)) : false;
+    }
+    
+    $fonts = array();
+    if ($fonts_dir = opendir(ENANO_ROOT . '/includes/captcha/fonts/'))
+    {
+      while (true == ($file = @readdir($fonts_dir))) 
+      { 
+        if ((substr(strtolower($file), strlen($file)-3, strlen($file)) == 'ttf'))
+        {
+          $fonts[] = $file; 
+        }     
+      }
+      closedir($fonts_dir);
+    } else {
+      die('Error reading directory: '.ENANO_ROOT.'/includes/captcha/fonts/');
+    }
+    $font = mt_rand(0, (count($fonts)-1));
+    
+    // Generate
+    $image = ($this->gdVersion() >= 2) ? imagecreatetruecolor($total_width, $total_height) : imagecreate($total_width, $total_height);
+    $background_color = imagecolorallocate($image, $bg_color[0], $bg_color[1], $bg_color[2]);
+    imagefill($image, 0, 0, $background_color);
+    
+    // Generate backgrund
+    if ($chess == '1' || $chess == '2' && rand(0,1))
+    {
+      // Draw rectangles
+      for($i = 0; $i <= 8; $i++)
+      {
+        $rectanglecolor = imagecolorallocate($image, rand(100,200),rand(100,200),rand(100,200));
+        imagefilledrectangle($image, 0, 0, round($total_width-($total_width/8*$i)), round($total_height), $rectanglecolor);
+        $rectanglecolor = imagecolorallocate($image, rand(100,200),rand(100,200),rand(100,200));
+        imagefilledrectangle($image, 0, 0, round($total_width-($total_width/8*$i)), round($total_height/2), $rectanglecolor);
+      }
+    }
+    if ($ellipses == '1' || $ellipses == '2' && rand(0,1))
+    {
+      // Draw random ellipses
+      for ($i = 1; $i <= 60; $i++)
+      {
+        $ellipsecolor = imagecolorallocate($image, rand(100,250),rand(100,250),rand(100,250));
+        imagefilledellipse($image, round(rand(0, $total_width)), round(rand(0, $total_height)), round(rand(0, $total_width/8)), round(rand(0, $total_height/4)), $ellipsecolor);	
+      }
+    }
+    if ($arcs == '1' || $arcs == '2' && rand(0,1))
+    {
+      // Draw random partial ellipses
+      for ($i = 0; $i <= 30; $i++)
+      {
+        $linecolor = imagecolorallocate($image, rand(120,255),rand(120,255),rand(120,255));
+        $cx = round(rand(1, $total_width));
+        $cy = round(rand(1, $total_height));
+        $int_w = round(rand(1, $total_width/2));
+        $int_h = round(rand(1, $total_height));
+        imagearc($image, $cx, $cy, $int_w, $int_h, round(rand(0, 190)), round(rand(191, 360)), $linecolor);
+        imagearc($image, $cx-1, $cy-1, $int_w, $int_h, round(rand(0, 190)), round(rand(191, 360)), $linecolor);
+      }
+    }
+    if ($lines == '1' || $lines == '2' && rand(0,1))
+    {
+      // Draw random lines
+      for ($i = 0; $i <= 50; $i++)
+      {
+        $linecolor = imagecolorallocate($image, rand(120,255),rand(120,255),rand(120,255));
+        imageline($image, round(rand(1, $total_width*3)), round(rand(1, $total_height*5)), round(rand(1, $total_width/2)), round(rand(1, $total_height*2)), $linecolor);
+      }
+    }
+    
+    $text_color_array = array('255,51,0', '51,77,255', '204,51,102', '0,153,0', '255,166,2', '255,0,255', '255,0,0', '0,255,0', '0,0,255', '0,255,255');
+    shuffle($text_color_array);
+    $pre_text_color_array = array('255,71,20', '71,20,224', '224,71,122', '20,173,20', '255,186,22', '25,25,25');
+    shuffle($pre_text_color_array);
+    $white = imagecolorallocate($image, 255, 255, 255);
+    $gray = imagecolorallocate($image, 100, 100, 100);
+    $black = imagecolorallocate($image, 0, 0, 0);
+    $lattice_color = imagecolorallocate($image, $rgb_lattice_color[0], $rgb_lattice_color[1], $rgb_lattice_color[2]);
+    
+    $x_char_position = (round(($total_width - 12) / strlen($code)) + mt_rand(-3, 5));
+    
+    for ($i = 0; $i < strlen($code); $i++)
+    {
+      mt_srand((double)microtime()*1000000);
+    
+      $char = $code{$i};
+      $size = mt_rand(floor($total_height / 3.5), ceil($total_height / 2.8));
+      $font = ($rnd_font) ? rand(0, (count($fonts)-1)) : $font;
+      $angle = mt_rand(-30, 30);
+    
+      $char_pos = array();
+      $char_pos = imagettfbbox($size, $angle, ENANO_ROOT.'/includes/captcha/fonts/'.$fonts[$font], $char);
+      $letter_width = abs($char_pos[0]) + abs($char_pos[4]);
+      $letter_height = abs($char_pos[1]) + abs($char_pos[5]);
+    
+      $x_pos = ($x_char_position / 4) + ($i * $x_char_position);
+      ($i == strlen($code)-1 && $x_pos >= ($total_width - ($letter_width + 5))) ? $x_pos = ($total_width - ($letter_width + 5)) : '';
+      $y_pos = mt_rand(($size * 1.4 ), $total_height - ($size * 0.4));
+    
+    //	Pre letters
+      $size = ($pre_letter_great) ? $size + (2 * $pre_letters) : $size - (2 * $pre_letters);
+      for ($count = 1; $count <= $pre_letters; $count++)
+      {
+        $pre_angle = $angle + mt_rand(-20, 20);
+    
+        $text_color = $pre_text_color_array[mt_rand(0,count($pre_text_color_array)-1)];
+        $text_color = explode(",", $text_color);
+        $textcolor = imagecolorallocate($image, $text_color[0], $text_color[1], $text_color[2]);
+    
+        imagettftext($image, $size, $pre_angle, $x_pos, $y_pos-2, $white, ENANO_ROOT.'/includes/captcha/fonts/'.$fonts[$font], $char);
+        imagettftext($image, $size, $pre_angle, $x_pos+2, $y_pos, $black, ENANO_ROOT.'/includes/captcha/fonts/'.$fonts[$font], $char);
+        imagettftext($image, $size, $pre_angle, $x_pos+1, $y_pos-1, $textcolor, ENANO_ROOT.'/includes/captcha/fonts/'.$fonts[$font], $char);
+    
+        $size = ($pre_letter_great) ? $size - 2 : $size + 2;
+      }
+    
+    //	Final letters
+      $text_color = $text_color_array[mt_rand(0,count($text_color_array)-1)];
+      $text_color = explode(",", $text_color);
+      $textcolor = imagecolorallocate($image, $text_color[0], $text_color[1], $text_color[2]);
+    
+      imagettftext($image, $size, $angle, $x_pos, $y_pos-2, $white, ENANO_ROOT.'/includes/captcha/fonts/'.$fonts[$font], $char);
+      imagettftext($image, $size, $angle, $x_pos+2, $y_pos, $black, ENANO_ROOT.'/includes/captcha/fonts/'.$fonts[$font], $char);
+      imagettftext($image, $size, $angle, $x_pos+1, $y_pos-1, $textcolor, ENANO_ROOT.'/includes/captcha/fonts/'.$fonts[$font], $char);
+    }
+    
+    
+    ($gammacorrect) ? imagegammacorrect($image, 1.0, $gammacorrect) : '';
+    
+    // Generate a white lattice in foreground
+    if ($foreground_lattice_y)
+    {
+      // x lines
+      $ih = round($total_height / $foreground_lattice_y);
+      for ($i = 0; $i <= $ih; $i++)
+      {
+        imageline($image, 0, $i*$foreground_lattice_y, $total_width, $i*$foreground_lattice_y, $lattice_color);
+      }
+    }
+    if ($foreground_lattice_x)
+    {
+      // y lines
+      $iw = round($total_width / $foreground_lattice_x);
+      for ($i = 0; $i <= $iw; $i++)
+      {
+        imageline($image, $i*$foreground_lattice_x, 0, $i*$foreground_lattice_x, $total_height, $lattice_color);
+      }
+    }
+    
+    // Font debug
+    if ($font_debug && !$rnd_font)
+    {
+      imagestring($image, 5, 2, 0, $fonts[$font], $white);
+      imagestring($image, 5, 5, 0, $fonts[$font], $white);
+      imagestring($image, 5, 4, 2, $fonts[$font], $gray);
+      imagestring($image, 5, 3, 1, $fonts[$font], $black);
+    }
+    
+    // Display
+    header("Last-Modified: " . gmdate("D, d M Y H:i:s") ." GMT"); 
+    header("Pragma: no-cache"); 
+    header("Cache-Control: no-store, no-cache, max-age=0, must-revalidate");
+    (!$jpeg) ? header("Content-Type: image/png") : header("Content-Type: image/jpeg");
+    
+    (!$jpeg) ? imagepng($image) : imagejpeg($image, '', $img_quality);
+    imagedestroy($image);
+  }
+  
+  // Function get_rgb by Frank Burian
+  // http://www.phpfuncs.org/?content=show&id=46
+  function get_rgb($hex) { 
+    $hex_array = array(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 
+        'A' => 10, 'B' => 11, 'C' => 12, 'D' => 13, 'E' => 14, 
+        'F' => 15); 
+    $hex = str_replace('#', '', strtoupper($hex)); 
+    if (($length = strlen($hex)) == 3) { 
+        $hex = $hex{0}.$hex{0}.$hex{1}.$hex{1}.$hex{2}.$hex{2}; 
+        $length = 6; 
+    } 
+    if ($length != 6 or strlen(str_replace(array_keys($hex_array), '', $hex))) 
+        return NULL; 
+    $rgb['r'] = $hex_array[$hex{0}] * 16 + $hex_array[$hex{1}]; 
+    $rgb['g'] = $hex_array[$hex{2}] * 16 + $hex_array[$hex{3}]; 
+    $rgb['b']= $hex_array[$hex{4}] * 16 + $hex_array[$hex{5}]; 
+    return $rgb['r'].','.$rgb['g'].','.$rgb['b']; 
+  }
+  
+  // Function  gdVersion by Hagan Fox
+  // http://de3.php.net/manual/en/function.gd-info.php#52481
+  function gdVersion($user_ver = 0)
+  {
+     if (! extension_loaded('gd')) { return; }
+     static $gd_ver = 0;
+     // Just accept the specified setting if it's 1.
+     if ($user_ver == 1) { $gd_ver = 1; return 1; }
+     // Use the static variable if function was called previously.
+     if ($user_ver !=2 && $gd_ver > 0 ) { return $gd_ver; }
+     // Use the gd_info() function if possible.
+     if (function_exists('gd_info')) {
+         $ver_info = gd_info();
+         preg_match('/\d/', $ver_info['GD Version'], $match);
+         $gd_ver = $match[0];
+         return $match[0];
+     }
+     // If phpinfo() is disabled use a specified / fail-safe choice...
+     if (preg_match('/phpinfo/', ini_get('disable_functions'))) {
+         if ($user_ver == 2) {
+             $gd_ver = 2;
+             return 2;
+         } else {
+             $gd_ver = 1;
+             return 1;
+         }
+     }
+     // ...otherwise use phpinfo().
+     ob_start();
+     phpinfo(8);
+     $info = ob_get_contents();
+     ob_end_clean();
+     $info = stristr($info, 'gd version');
+     preg_match('/\d/', $info, $match);
+     $gd_ver = $match[0];
+     return $match[0];
+  }
+}
Binary file includes/captcha/fonts/FreeMonoBold.ttf has changed
Binary file includes/captcha/fonts/FreeSerifBold.ttf has changed
Binary file includes/captcha/fonts/LiberationSans-Bold.ttf has changed
Binary file includes/captcha/pics/allyourbase.jpg has changed
Binary file includes/captcha/pics/freecap_im1.jpg has changed
Binary file includes/captcha/pics/freecap_im2.jpg has changed
Binary file includes/captcha/pics/freecap_im3.jpg has changed
Binary file includes/captcha/pics/freecap_im4.jpg has changed
--- a/includes/clientside/css/enano-shared.css	Fri Feb 22 12:46:51 2008 -0500
+++ b/includes/clientside/css/enano-shared.css	Fri Feb 22 12:51:53 2008 -0500
@@ -52,7 +52,7 @@
   opacity: 0.6;
   /*filter: alpha(opacity=60);*/
 }
-div.toolbar a:hover img {
+div.toolbar a:hover img, div.toolbar a:focus img {
   opacity: 1;
   /*filter: alpha(opacity=100);*/
 }
@@ -67,7 +67,7 @@
   max-height: 16px;
   text-decoration: none;
 }
-div.toolbar a:hover {
+div.toolbar a:hover, div.toolbar a:focus {
   border: 1px solid #202090;
   background-color: #ceceed;
   color: #000000;
@@ -163,6 +163,14 @@
 div.tblholder th.subhead          { padding: 4px; background-color: #90A0B0; font-weight: bold; text-align: center; color: #FFFFFF; }
 div.tblholder table               { background-color: #FFFFFF; width: 100%; }
 
+/* Colored table cells */
+div.tblholder td.row1_red         { padding: 4px; background-color: #F8E0E0; }
+div.tblholder td.row2_red         { padding: 4px; background-color: #FFF0F0; }
+div.tblholder td.row3_red         { padding: 4px; background-color: #FFE8E8; }
+div.tblholder td.row1_green       { padding: 4px; background-color: #E0F8E0; }
+div.tblholder td.row2_green       { padding: 4px; background-color: #F0FFF0; }
+div.tblholder td.row3_green       { padding: 4px; background-color: #E8FFE8; }
+
 /* Well, not Midget and not comments (usually), but that's what the class is called ;-). Basically an informational window or used as a wrapper for tables. */
 .mdg-comment, .mdg-infobox        { margin-left: 1em; padding: 7px; border: 1px solid #AAAAAA; background-color: #E8E8E8; }
 
@@ -185,6 +193,7 @@
 div.search-result span.search-result-info { color: #7777CC; }
 div.search-result span.search-result-url  { color: green; }
 div.search-result span.search-term, div.search-result span.title-search-term { background-color: #FFFFC0; font-weight: bold; }
+div.search-result span.url-search-term { font-weight: bold; }
 div.search-result span.search-result-annotation { font-size: 8pt; }
 div.search-hibar       { border-top: 1px solid #3366CC; margin-top: 10px; color: #000; background-color: #D5DFF3; padding: 3px; vertical-align: middle; }
 div.search-lobar       { background-color: #E5EFFF; margin: 0; padding: 5px; }
@@ -416,6 +425,10 @@
 .usermessage a:hover {
   color: #AA5500 !important;
 }
+.usermessage h2 {
+  border-bottom-color: #ef8500 !important;
+  color: black;
+}
 div.thumbnail {
   display: table;
   border: 1px solid #AAAAAA;
@@ -518,3 +531,185 @@
   font-size: 0.7em;
 }
 
+/* Default private message AJAX interface styles (colors and style based on those of Gmail) */
+
+div#privmsgs {
+  /* Neal prefers this border but I personally consider it distasteful because it detracts from the Gmail-ey look.
+  border: 1px solid #c0c0c0; */
+  background-color: white;
+  color: black;
+}
+
+span.pm_link {
+  color: #0000ff;
+  cursor: pointer;
+  text-decoration: underline;
+}
+
+span.pm_link_folder {
+  display: block;
+  text-decoration: none;
+  padding: 3px;
+}
+
+span.pm_link_selected {
+  background-color: #c3d9ff;
+  font-weight: bold;
+  text-decoration: underline;
+}
+
+span.pm_link_selected_trash {
+  background-color: #d9d9db;
+}
+
+div.pm_break {
+  height: 10px;
+}
+
+div.pm_main {
+  background-color: #c3d9ff;
+  padding: 5px 5px 3px 5px;
+  margin-left: 12em;
+  min-height: 16em;
+}
+
+div.pm_main_trash {
+  background-color: #d9d9db;
+}
+
+div.pm_status {
+  display: table;
+  background-color: #cc0000;
+  padding: 3px;
+  margin: 0 auto;
+  color: white;
+}
+
+div.pm_teaser {
+  background-color: white;
+  color: black;
+  text-align: center;
+  padding: 8em 1em 8em 1em;
+}
+
+div.pm_mlist_message {
+  background-color: #e8eef7;
+  color: black;
+  border-bottom: 1px solid #d8d8d8;
+  cursor: pointer;
+}
+
+div.pm_mlist_message span.pm_subject {
+  font-weight: normal;
+  display: inline-block;
+  clip: rect(0px, auto, auto, 0px);
+  overflow: hidden;
+  margin: 0 3px 0 0;
+}
+
+div.pm_mlist_message span.pm_sender {
+  display: inline-block;
+  width: 30%;
+  margin: 0 10px 0% 4px;
+  font-weight: normal;
+  clip: rect(0px, auto, auto, 0px);
+  overflow: hidden;
+}
+
+div.pm_mlist_message span.pm_miniclip {
+  color: #909090;
+  display: inline-block;
+  clip: rect(0px, auto, auto, 0px);
+  overflow: hidden;
+}
+
+div.pm_messagelist_inner {
+  min-height: 12em;
+  background-color: white;
+}
+
+div.pm_mlist_message_unread {
+  background-color: white;
+}
+
+div.pm_mlist_message_unread span.pm_subject {
+  font-weight: bold;
+}
+
+div.pm_mlist_message_unread span.pm_sender {
+  font-weight: bold;
+}
+
+div.pm_mlist_message_selected {
+  background-color: #ffffcc;
+}
+
+span.pm_toolbar_label {
+  color: black;
+  font-weight: bold;
+}
+
+div.noborderbottom * {
+  border-bottom-width: 0px;
+}
+
+div.nobordertop * {
+  border-top-width: 0px;
+}
+
+/* Theme buttons in admin CP */
+
+div.themebutton {
+  width: 216px;
+  float: left;
+  background-position: center center;
+  background-repeat: no-repeat;
+  margin-right: 10px;
+  padding: 5px;
+  border: 1px solid #F0F0F0;
+}
+
+div.themebutton_theme_disabled {
+  background-color: #D84308;
+}
+
+div.themebutton_theme_system {
+  display: none;
+}
+
+div.themebutton a.tb-inner {
+  opacity: 0;
+  filter: alpha(opacity=0);
+  display: block;
+  height: 110px;
+  padding-top: 40px;
+  text-align: center;
+  font-size: 40px;
+  text-decoration: none;
+}
+div.themebutton_theme_system a.tb-inner {
+  font-size: 28px;
+  height: 100px;
+  padding-top: 50px;
+}
+div.themebutton a.tb-inner:hover {
+  opacity: 0.75;
+  filter: alpha(opacity=75);
+  background-color: #ffffff;
+}
+div.themebutton a.tb-inner span.themename {
+  font-size: 8pt;
+  color: #606060;
+  display: block;
+}
+
+div.themebutton div.status {
+  opacity: 0.75;
+  filter: alpha(opacity=75);
+  background-image: url(../../../images/loading-big.gif);
+  background-repeat: no-repeat;
+  background-position: center center;
+  background-color: #ffffff;
+  height: 150px;
+}
+
--- a/includes/clientside/jsres.php	Fri Feb 22 12:46:51 2008 -0500
+++ b/includes/clientside/jsres.php	Fri Feb 22 12:51:53 2008 -0500
@@ -2,7 +2,7 @@
 
 /*
  * Enano - an open-source CMS capable of wiki functions, Drupal-like sidebar blocks, and everything in between
- * Version 1.0.3 (Dyrad)
+ * Version 1.1.2 (Caoineag alpha 2)
  * Copyright (C) 2006-2007 Dan Fuhry
  * jsres.php - the Enano client-side runtime, a.k.a. AJAX on steroids
  *
@@ -13,82 +13,173 @@
  * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for details.
  */
 
-if(!isset($_GET['title'])) $_GET['title'] = 'null';
-require('../common.php');
+// Disable for IE, it causes problems.
+if ( strstr(@$_SERVER['HTTP_USER_AGENT'], 'MSIE') )
+{
+  header('HTTP/1.1 302 Redirect');
+  header('Location: static/enano-lib-basic.js');
+  exit();
+}
 
-define('ENABLE_COMPRESSION', '');
+// Setup Enano
+
+//
+// Determine the location of Enano as an absolute path.
+//
 
-ob_start();
-header('Content-type: text/javascript');
+// 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__;
+}
 
-$file = ( isset($_GET['file']) ) ? $_GET['file'] : 'enano-lib-basic.js';
+// 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(dirname($filename))));
+
+chdir(ENANO_ROOT);
+
+// CONFIG
 
-if(!preg_match('/^([a-z0-9_-]+)\.js$/i', $file))
-  die('// ERROR: Hacking attempt');
+// Files safe to run full (aggressive) compression on
+$full_compress_safe = array(
+  // Sorted by file size, descending (du -b *.js | sort -n)
+  'libbigint.js',
+  'ajax.js',
+  'editor.js',
+  'acl.js',
+  'misc.js',
+  'comments.js',
+  'rijndael.js',
+  'autofill.js',
+  'dropdown.js',
+  'paginate.js',
+  'autocomplete.js',
+  'md5.js',
+  'pwstrength.js',
+  'sha256.js',
+  'flyin.js',
+  'template-compiler.js',
+  'toolbar.js',
+  'diffiehellman.js',
+  'enanomath.js'
+);
 
-$fname = './static/' . $file;
-if ( !file_exists($fname) )
-  die('// ERROR: File not found: ' . $file);
+// Files that should NOT be compressed due to already being compressed, licensing, or invalid produced code
+$compress_unsafe = array('SpryEffects.js', 'json.js', 'fat.js', 'admin-menu.js');
+
+require('includes/functions.php');
+require('includes/json2.php');
+require('includes/js-compressor.php');
 
-$everything = file_get_contents($fname);
+// Output format will always be JS
+header('Content-type: text/javascript');
+$everything = '';
 
-$mtime = filemtime($fname);
-header('Last-Modified: '.date('D, d M Y H:i:s T', $mtime));
-header('Content-disposition: attachment; filename=' . $file);
+// Load and parse enano_lib_basic
+$file = @file_get_contents('includes/clientside/static/enano-lib-basic.js');
+
+$pos_start_includes = strpos($file, '/*!START_INCLUDER*/');
+$pos_end_includes = strpos($file, '/*!END_INCLUDER*/');
 
-if(defined('ENABLE_COMPRESSION'))
+if ( !$pos_start_includes || !$pos_end_includes )
+{
+  die('// Error: enano-lib-basic does not have required metacomments');
+}
+
+$pos_end_includes += strlen('/*!END_INCLUDER*/');
+
+preg_match('/var thefiles = (\[([^\]]+?)\]);/', $file, $match);
+
+if ( empty($match) )
+  die('// Error: could not retrieve file list from enano-lib-basic');
+
+// Decode file list
+try
+{
+  $file_list = enano_json_decode($match[1]);
+}
+catch ( Exception $e )
 {
-  echo "/*
- * Enano - an open-source CMS capable of wiki functions, Drupal-like sidebar blocks, and everything in between
- * Version 1.0.3 (Dyrad)
- * [Aggressively compressed] Javascript client code
- * Copyright (C) 2006-2007 Dan Fuhry
- * Enano is Free Software, licensed under the GNU General Public License; see http://enanocms.org/ for details.
- */
+  die("// Exception caught during file list parsing");
+}
+
+$apex = filemtime('includes/clientside/static/enano-lib-basic.js');
+
+$before_includes = substr($file, 0, $pos_start_includes);
+$after_includes = substr($file, $pos_end_includes);
+
+$everything .= $before_includes;
+$everything .= $after_includes;
 
-";
+foreach ( $file_list as $js_file )
+{
+  $file_contents = file_get_contents("includes/clientside/static/$js_file");
+  $file_md5 = md5($file_contents);
+  $time = filemtime("includes/clientside/static/$js_file");
+  if ( $time > $apex )
+    $apex = $time;
+  // Is this file cached?
+  $cache_path = ENANO_ROOT . "/cache/jsres_$js_file.json";
+  $loaded_cache = false;
   
-  $cache_file = ENANO_ROOT . '/cache/jsres-' . $file . '.php';
-  
-  if ( file_exists($cache_file) )
+  if ( file_exists($cache_path) )
   {
-    $cached = file_get_contents ( $cache_file );
-    $data = unserialize ( $cached );
-    if ( $data['md5'] == md5 ( $everything ) )
+    // Load the cache file and parse it.
+    $cache_file = file_get_contents($cache_path);
+    try
+    {
+      $cache_file = enano_json_decode($cache_file);
+    }
+    catch ( Exception $e )
+    {
+      // Don't do anything - let our fallbacks come into place
+    }
+    if ( is_array($cache_file) && isset($cache_file['md5']) && isset($cache_file['src']) )
     {
-      echo "// The code in this file was fetched from cache\n\n";
-      echo $data['code'];
-      exit;
+      if ( $cache_file['md5'] === $file_md5 )
+      {
+        $loaded_cache = true;
+        $file_contents = $cache_file['src'];
+      }
+    }
+  }
+  if ( !$loaded_cache )
+  {
+    // Try to open the cache file and write to it. If we can't do that, just don't compress the code.
+    $handle = @fopen($cache_path, 'w');
+    if ( $handle )
+    {
+      $aggressive = in_array($js_file, $full_compress_safe);
+      if ( !in_array($js_file, $compress_unsafe) )
+        $file_contents = perform_js_compress($file_contents, $aggressive);
+      
+      $payload = enano_json_encode(array(
+          'md5' => $file_md5,
+          'src' => $file_contents
+        ));
+      fwrite($handle, $payload);
+      fclose($handle);
     }
   }
   
-  if ( getConfig('cache_thumbs') == '1' )
-  {
-    $js_compressor = new JavascriptCompressor();
-    $packed = $js_compressor->getPacked($everything);
-    $data = Array(
-      'md5' => md5 ( $everything ),
-      'code' => $packed
-      );
-    echo "// The code in this file was fetched from the static scripts and compressed (packed code cached)\n\n";
-    echo $packed;
-    
-    $fh = @fopen($cache_file, 'w');
-    if (!$fh)
-      die('// ERROR: Can\'t open cache file for writing');
-    fwrite($fh, serialize ( $data ) );
-    fclose($fh);
-    
-    exit;
-  }
-  
-  echo "// The code in this file was not compressed because packed-script caching is disabled\n\n";
-  echo $everything;
-  
+  $everything .= "\n // $js_file\n";
+  $everything .= "\n" . $file_contents;
 }
-else
-{
-  echo "// The code in this file was not compressed because all script compression is disabled\n\n";
-  echo $everything;
-}
-?>
+
+$date = date('r', $apex);
+header("Date: $date");
+header("Last-Modified: $date");
+
+echo $everything;
+
--- a/includes/clientside/sbedit.js	Fri Feb 22 12:46:51 2008 -0500
+++ b/includes/clientside/sbedit.js	Fri Feb 22 12:51:53 2008 -0500
@@ -4,7 +4,7 @@
   disenable_currentBlock = document.getElementById('disabled_'+id);
   ajaxGet(makeUrlNS('Special', 'EditSidebar', 'action=disenable&ajax=true&noheaders&id='+id), function()
     {
-      if(ajax.readyState == 4)
+      if ( ajax.readyState == 4 && ajax.status == 200 )
       {
         if(ajax.responseText == 'GOOD')
         {
@@ -31,7 +31,7 @@
   delete_currentBlock = { 0 : id, 1 : oElm };
   ajaxGet(makeUrlNS('Special', 'EditSidebar', 'action=delete&ajax=true&noheaders&id='+id), function()
     {
-      if(ajax.readyState == 4)
+      if ( ajax.readyState == 4 && ajax.status == 200 )
       {
         if(ajax.responseText == 'GOOD')
         {
@@ -53,7 +53,7 @@
   blockEdit_current = { 0 : id, 1 : oElm };
   ajaxGet(makeUrlNS('Special', 'EditSidebar', 'action=getsource&noheaders&id='+id), function()
     {
-      if(ajax.readyState == 4)
+      if ( ajax.readyState == 4 && ajax.status == 200 )
       {
         id = blockEdit_current[0];
         oElm = blockEdit_current[1];
@@ -71,7 +71,7 @@
         thediv.style.margin = '0';
         if(ajax.responseText == 'HOUSTON_WE_HAVE_A_PLUGIN')
         {
-          thediv.innerHTML = '<h3>This block cannot be edited.</h3><p>This is a plugin block, and cannot be edited.</p><p><a href="#" onclick="this.parentNode.parentNode.parentNode.removeChild(this.parentNode.parentNode); return false;">close</a></p>';
+          thediv.innerHTML = '<h3>' + $lang.get('sbedit_msg_cant_edit_plugin_title') + '</h3><p>' + $lang.get('sbedit_msg_cant_edit_plugin_body', { close_link: 'a href="#" onclick="this.parentNode.parentNode.parentNode.removeChild(this.parentNode.parentNode); return false;"' }) + '</p>';
         }
         else
         {
@@ -82,7 +82,7 @@
           thediv.appendChild(ta);
           b = document.createElement('br');
           thediv.appendChild(b);
-          thediv.innerHTML += '<a href="#" onclick="ajaxSaveBlock(this, \''+id+'\'); return false;">save</a>  |  <a href="#" onclick="if(confirm(\'Do you really want to discard your changes?\')) this.parentNode.parentNode.removeChild(this.parentNode); return false;">cancel</a>';
+          thediv.innerHTML += '<a href="#" onclick="ajaxSaveBlock(this, \''+id+'\'); return false;">' + $lang.get('sbedit_btn_edit_save') + '</a>  |  <a href="#" onclick="if(confirm(\'' + $lang.get('sbedit_msg_discard_confirm') + '\')) this.parentNode.parentNode.removeChild(this.parentNode); return false;">' + $lang.get('sbedit_btn_edit_cancel') + '</a>';
         }
         body = document.getElementsByTagName('body');
         body = body[0];
@@ -100,7 +100,7 @@
   blockSave_current = { 0 : id, 1 : oElm };
   ajaxPost(makeUrlNS('Special', 'EditSidebar', 'noheaders&action=save&id='+id), 'content='+taContent, function()
     {
-      if(ajax.readyState == 4)
+      if ( ajax.readyState == 4 && ajax.status == 200 )
       {
         id   = blockSave_current[0];
         oElm = blockSave_current[1];
@@ -172,7 +172,7 @@
   newname = ajaxEscape(newname);
   ajaxPost(makeUrlNS('Special', 'EditSidebar', 'ajax&noheaders&action=rename&id='+id), 'newname=' +newname, function()
     {
-      if ( ajax.readyState == 4 )
+      if ( ajax.readyState == 4 && ajax.status == 200 )
       {
         parent.removeChild(img);
         if ( ajax.responseText != 'GOOD' )
--- a/includes/clientside/static/acl.js	Fri Feb 22 12:46:51 2008 -0500
+++ b/includes/clientside/static/acl.js	Fri Feb 22 12:51:53 2008 -0500
@@ -25,7 +25,7 @@
   params = toJSONString(params);
   params = ajaxEscape(params);
   ajaxPost(stdAjaxPrefix+'&_mode=acljson', 'acl_params='+params, function() {
-      if(ajax.readyState == 4)
+      if ( ajax.readyState == 4 && ajax.status == 200 )
       {
         var response = String(ajax.responseText + '');
         if ( response.substr(0, 1) != '{' )
@@ -49,7 +49,7 @@
         aclDataCache = groups;
         __aclBuildSelector(groups);
       }
-    });
+    }, true);
   return false;
 }
 
@@ -66,11 +66,11 @@
   params = toJSONString(params);
   params = ajaxEscape(params);
   ajaxPost(stdAjaxPrefix+'&_mode=acljson', 'acl_params='+params, function() {
-      if(ajax.readyState == 4)
+      if ( ajax.readyState == 4 && ajax.status == 200 )
       {
         document.getElementById(aclManagerID+'_main').innerHTML = '';
         document.getElementById(aclManagerID + '_back').style.display = 'none';
-        document.getElementById(aclManagerID + '_next').value = 'Next >';
+        document.getElementById(aclManagerID + '_next').value = $lang.get('etc_wizard_next');
         groups = parseJSON(ajax.responseText);
         if ( groups.mode == 'error' )
         {
@@ -84,7 +84,7 @@
         groups.namespace = thispage[1];
         __aclBuildSelector(groups);
       }
-    });
+    }, true);
 }
 
 function __aclBuildSelector(groups)
@@ -115,13 +115,13 @@
   grpb.onclick = function() { seed = this.className; document.getElementById('enACL_grpbox_'+seed).style.display = 'block'; document.getElementById('enACL_usrbox_'+seed).style.display = 'none'; };
   lbl = document.createElement('label');
   lbl.appendChild(grpb);
-  lbl.appendChild(document.createTextNode('A usergroup'));
+  lbl.appendChild(document.createTextNode($lang.get('acl_radio_usergroup')));
   lbl.style.display = 'block';
   span.appendChild(grpsel);
   
   anoninfo = document.createElement('div');
   anoninfo.className = 'info-box-mini';
-  anoninfo.appendChild(document.createTextNode('To edit permissions for guests, select "a specific user", and enter Anonymous as the username.'));
+  anoninfo.appendChild(document.createTextNode($lang.get('acl_msg_guest_howto')));
   span.appendChild(document.createElement('br'));
   span.appendChild(anoninfo);
   
@@ -133,7 +133,7 @@
   usrb.onclick = function() { seed = this.className; document.getElementById('enACL_grpbox_'+seed).style.display = 'none'; document.getElementById('enACL_usrbox_'+seed).style.display = 'block'; };
   lbl2 = document.createElement('label');
   lbl2.appendChild(usrb);
-  lbl2.appendChild(document.createTextNode('A specific user'));
+  lbl2.appendChild(document.createTextNode($lang.get('acl_radio_user')));
   lbl2.style.display = 'block';
   
   usrsel = document.createElement('input');
@@ -178,21 +178,21 @@
     lblPage = document.createElement('label');
       lblPage.style.display = 'block';
       lblPage.appendChild(scopeRadioPage);
-      lblPage.appendChild(document.createTextNode('Only this page'));
+      lblPage.appendChild(document.createTextNode($lang.get('acl_radio_scope_thispage')));
     lblGlobal = document.createElement('label');
       lblGlobal.style.display = 'block';
       lblGlobal.appendChild(scopeRadioGlobal);
-      lblGlobal.appendChild(document.createTextNode('The entire website'));
+      lblGlobal.appendChild(document.createTextNode($lang.get('acl_radio_scope_wholesite')));
     lblGroup = document.createElement('label');
       lblGroup.style.display = 'block';
       lblGroup.appendChild(scopeRadioGroup);
-      lblGroup.appendChild(document.createTextNode('A group of pages'));
+      lblGroup.appendChild(document.createTextNode($lang.get('acl_radio_scope_pagegroup')));
     scopediv1.appendChild(lblPage);
     scopediv2.appendChild(lblGroup);
     scopediv3.appendChild(lblGlobal);
     
     scopedesc = document.createElement('p');
-    scopedesc.appendChild(document.createTextNode('What should this access rule control?'));
+    scopedesc.appendChild(document.createTextNode($lang.get('acl_lbl_scope')));
     
     scopePGrp = document.createElement('select');
     scopePGrp.style.marginLeft = '13px';
@@ -230,10 +230,10 @@
   container.style.paddingTop = '50px';
   
   head = document.createElement('h2');
-  head.appendChild(document.createTextNode('Manage page access'));
+  head.appendChild(document.createTextNode($lang.get('acl_lbl_welcome_title')));
   
   desc = document.createElement('p');
-  desc.appendChild(document.createTextNode('Please select who should be affected by this access rule.'));
+  desc.appendChild(document.createTextNode($lang.get('acl_lbl_welcome_body')));
   
   container.appendChild(head);
   container.appendChild(desc);
@@ -316,7 +316,7 @@
   params = toJSONString(params);
   params = ajaxEscape(params);
   ajaxPost(stdAjaxPrefix+'&_mode=acljson', 'acl_params='+params, function() {
-      if(ajax.readyState == 4)
+      if ( ajax.readyState == 4 && ajax.status == 200 )
       {
         var response = String(ajax.responseText + '');
         if ( response.substr(0, 1) != '{' )
@@ -336,11 +336,14 @@
             
             // Build the ACL edit form
             // try {
-              act_desc = ( data.type == 'new' ) ? 'Create access rule' : 'Editing permissions';
-              target_type_t = ( data.target_type == 1 ) ? 'group' : 'user';
-              target_name_t = data.target_name;
-              var scope_type = ( data.page_id == false && data.namespace == false ) ? 'this entire site' : ( data.namespace == '__PageGroup' ) ? 'this group of pages' : 'this page';
-              html = '<h2>'+act_desc+'</h2><p>This panel allows you to edit what the '+target_type_t+' "<b>'+target_name_t+'</b>" can do on <b>' + scope_type + '</b>. Unless you set a permission to "Deny", these permissions may be overridden by other rules.</p>';
+            
+              var act_desc = ( data.type == 'new' ) ? $lang.get('acl_lbl_editwin_title_create') : $lang.get('acl_lbl_editwin_title_edit');
+              var target_type_t = ( data.target_type == 1 ) ? $lang.get('acl_target_type_group') : $lang.get('acl_target_type_user');
+              var target_name_t = data.target_name;
+              var scope_type = ( data.page_id == false && data.namespace == false ) ? $lang.get('acl_scope_type_wholesite') : ( data.namespace == '__PageGroup' ) ? $lang.get('acl_scope_type_pagegroup') : $lang.get('acl_scope_type_thispage');
+              
+              html = '<h2>'+act_desc+'</h2>';
+              html += '<p>' + $lang.get('acl_lbl_editwin_body', { target_type: target_type_t, target: target_name_t, scope_type: scope_type }) + '</p>';
               parser = new templateParser(data.template.acl_field_begin);
               html += parser.run();
               
@@ -352,19 +355,34 @@
                   cls = ( cls == 'row1' ) ? 'row2' : 'row1';
                   p = new templateParser(data.template.acl_field_item);
                   vars = new Object();
-                  vars['FIELD_DESC'] = data.acl_descs[i];
+                  if ( data.acl_descs[i].match(/^([a-z0-9_]+)$/) )
+                  {
+                    vars['FIELD_DESC'] = $lang.get(data.acl_descs[i]);
+                  }
+                  else
+                  {
+                    vars['FIELD_DESC'] = data.acl_descs[i];
+                  }
+                  vars['FIELD_INHERIT_CHECKED'] = '';
                   vars['FIELD_DENY_CHECKED'] = '';
                   vars['FIELD_DISALLOW_CHECKED'] = '';
                   vars['FIELD_WIKIMODE_CHECKED'] = '';
                   vars['FIELD_ALLOW_CHECKED'] = '';
                   vars['FIELD_NAME'] = i;
+                  if ( !data.current_perms[i] )
+                  {
+                    data.current_perms[i] = 'i';
+                  }
                   switch(data.current_perms[i])
                   {
+                    case 'i':
+                    default:
+                      vars['FIELD_INHERIT_CHECKED'] = 'checked="checked"';
+                      break;
                     case 1:
                       vars['FIELD_DENY_CHECKED'] = 'checked="checked"';
                       break;
                     case 2:
-                    default:
                       vars['FIELD_DISALLOW_CHECKED'] = 'checked="checked"';
                       break;
                     case 3:
@@ -384,7 +402,7 @@
               html += parser.run();
               
               if(data.type == 'edit')
-                html += '<p id="'+aclManagerID+'_deletelnk" style="text-align: right;"><a href="#delete_acl_rule" onclick="if(confirm(\'Do you really want to delete this rule?\')) __aclDeleteRule(); return false;" style="color: red;">Delete this rule</a></p>';
+                html += '<p id="'+aclManagerID+'_deletelnk" style="text-align: right;"><a href="#delete_acl_rule" onclick="if(confirm(\'' + $lang.get('acl_msg_deleterule_confirm') + '\')) __aclDeleteRule(); return false;" style="color: red;">' + $lang.get('acl_lbl_deleterule') + '</a></p>';
               
               var main = document.getElementById(aclManagerID + '_main');
               main.innerHTML = html;
@@ -400,7 +418,7 @@
               aclPermList = array_keys(data.acl_types);
               
               document.getElementById(aclManagerID + '_back').style.display = 'inline';
-              document.getElementById(aclManagerID + '_next').value = 'Save Changes';
+              document.getElementById(aclManagerID + '_next').value = $lang.get('etc_save_changes');
               
             // } catch(e) { alert(e); aclDebug(ajax.responseText); }
             
@@ -410,27 +428,33 @@
             note.className = 'info-box';
             note.style.marginLeft = '0';
             var b = document.createElement('b');
-            b.appendChild(document.createTextNode('Permissions updated'));
+            b.appendChild(document.createTextNode($lang.get('acl_lbl_save_success_title')));
             note.appendChild(b);
             note.appendChild(document.createElement('br'));
-            note.appendChild(document.createTextNode('The permissions for '+data.target_name+' on this page have been updated successfully. If you changed permissions that affect your user account, you may not see changes until you reload the page.'));
+            note.appendChild(document.createTextNode($lang.get('acl_lbl_save_success_body', { target_name: data.target_name })));
             note.appendChild(document.createElement('br'));
             var a = document.createElement('a');
-            a.href = 'javascript:void(0);';
-            a.onclick = function() { this.parentNode.parentNode.removeChild(this.parentNode); return false; };
-            a.appendChild(document.createTextNode('[ dismiss :'));
+            a.href = '#';
+            a.id = aclManagerID + '_btn_dismiss';
+            a.appendChild(document.createTextNode('[ ' + $lang.get('acl_btn_success_dismiss') + ' :'));
             note.appendChild(a);
             var a2 = document.createElement('a');
-            a2.href = 'javascript:void(0);';
-            a2.onclick = function() { killACLManager(); return false; };
-            a2.appendChild(document.createTextNode(': close manager ]'));
+            a2.href = '#';
+            a.id = aclManagerID + '_btn_close';
+            a2.appendChild(document.createTextNode(': ' + $lang.get('acl_btn_success_close') + ' ]'));
             note.appendChild(a2);
             document.getElementById(aclManagerID + '_main').insertBefore(note, document.getElementById(aclManagerID + '_main').firstChild);
             if(!document.getElementById(aclManagerID+'_deletelnk'))
-              document.getElementById(aclManagerID + '_main').innerHTML += '<p id="'+aclManagerID+'_deletelnk" style="text-align: right;"><a href="#delete_acl_rule" onclick="if(confirm(\'Do you really want to delete this rule?\')) __aclDeleteRule(); return false;" style="color: red;">Delete this rule</a></p>';
+              document.getElementById(aclManagerID + '_main').innerHTML += '<p id="'+aclManagerID+'_deletelnk" style="text-align: right;"><a href="#delete_acl_rule" onclick="if(confirm(\'' + $lang.get('acl_msg_deleterule_confirm') + '\')) __aclDeleteRule(); return false;" style="color: red;">' + $lang.get('acl_lbl_deleterule') + '</a></p>';
             //fadeInfoBoxes();
             document.getElementById(aclManagerID+'_main').scrollTop = 0;
             
+            var a = document.getElementById(aclManagerID + '_btn_dismiss');
+            var a2 = document.getElementById(aclManagerID + '_btn_close');
+            
+            a.setAttribute('onclick', function(e) { this.parentNode.parentNode.removeChild(this.parentNode); return false; });
+            a2.setAttribute('onclick', function(e) { killACLManager(); return false; });
+            
             aclDataCache.mode = 'save_edit';
             break;
           case 'delete':
@@ -441,11 +465,11 @@
           params = toJSONString(params);
           params = ajaxEscape(params);
           ajaxPost(stdAjaxPrefix+'&_mode=acljson', 'acl_params='+params, function() {
-              if(ajax.readyState == 4)
+              if ( ajax.readyState == 4 && ajax.status == 200 )
               {
                 document.getElementById(aclManagerID+'_main').innerHTML = '';
                 document.getElementById(aclManagerID + '_back').style.display = 'none';
-                document.getElementById(aclManagerID + '_next').value = 'Next >';
+                document.getElementById(aclManagerID + '_next').value = $lang.get('etc_wizard_next');
                 var thispage = strToPageID(title);
                 groups.page_id = thispage[0];
                 groups.namespace = thispage[1];
@@ -458,26 +482,26 @@
                 note.style.width = '558px';
                 note.id = 'aclSuccessNotice_' + Math.floor(Math.random() * 100000);
                 b = document.createElement('b');
-                b.appendChild(document.createTextNode('Entry deleted'));
+                b.appendChild(document.createTextNode($lang.get('acl_lbl_delete_success_title')));
                 note.appendChild(b);
                 note.appendChild(document.createElement('br'));
-                note.appendChild(document.createTextNode('The access rules for '+aclDataCache.target_name+' on this page have been deleted.'));
+                note.appendChild(document.createTextNode($lang.get('acl_lbl_delete_success_body', { target_name: aclDataCache.target_name })));
                 note.appendChild(document.createElement('br'));
                 a = document.createElement('a');
                 a.href = '#';
                 a.onclick = function() { opacity(this.parentNode.id, 100, 0, 1000); setTimeout('var div = document.getElementById("' + this.parentNode.id + '"); div.parentNode.removeChild(div);', 1100); return false; };
-                a.appendChild(document.createTextNode('[ dismiss :'));
+                a.appendChild(document.createTextNode('[ ' + $lang.get('acl_btn_success_dismiss') + ' :'));
                 note.appendChild(a);
                 a = document.createElement('a');
                 a.href = '#';
                 a.onclick = function() { killACLManager(); return false; };
-                a.appendChild(document.createTextNode(': close manager ]'));
+                a.appendChild(document.createTextNode(': ' + $lang.get('acl_btn_success_close') + ' ]'));
                 note.appendChild(a);
                 document.getElementById(aclManagerID + '_main').insertBefore(note, document.getElementById(aclManagerID + '_main').firstChild);
                 //fadeInfoBoxes();
                 
               }
-            });
+            }, true);
             
             break;
           case 'error':
@@ -491,7 +515,7 @@
             break;
         }
       }
-    });
+    }, true);
 }
 
 function __aclBuildGroupsHTML(groups)
@@ -559,7 +583,7 @@
   
   back = document.createElement('input');
   back.type = 'button';
-  back.value = '< Back';
+  back.value = $lang.get('etc_wizard_back');
   back.style.fontWeight = 'normal';
   back.onclick = function() { ajaxACLSwitchToSelector(); return false; };
   back.style.display = 'none';
@@ -567,14 +591,14 @@
   
   saver = document.createElement('input');
   saver.type = 'submit';
-  saver.value = 'Next >';
+  saver.value = $lang.get('etc_wizard_next');
   saver.style.fontWeight = 'bold';
   saver.id = aclManagerID + '_next';
   
   closer = document.createElement('input');
   closer.type = 'button';
-  closer.value = 'Cancel Changes';
-  closer.onclick = function() { if(!confirm('Do you really want to close the ACL manager?')) return false; killACLManager(); return false; }
+  closer.value = $lang.get('etc_cancel_changes');
+  closer.onclick = function() { if(!confirm($lang.get('acl_msg_closeacl_confirm'))) return false; killACLManager(); return false; }
   
   spacer1 = document.createTextNode('  ');
   spacer2 = document.createTextNode('  ');
@@ -641,7 +665,7 @@
       var target_type = parseInt(getRadioState(thefrm, 'target_type', ['1', '2']));
       if(isNaN(target_type))
       {
-        alert('Please select a target type.');
+        alert($lang.get('acl_err_pleaseselect_targettype'));
         return false;
       }
       target_id = ( target_type == 1 ) ? parseInt(thefrm.group_id.value) : thefrm.username.value;
@@ -683,7 +707,7 @@
       }
       if(target_id == '')
       {
-        alert('Please enter a username.');
+        alert($lang.get('acl_err_pleaseselect_username'));
         return false;
       }
       __aclJSONSubmitAjaxHandler(obj);
--- a/includes/clientside/static/ajax.js	Fri Feb 22 12:46:51 2008 -0500
+++ b/includes/clientside/static/ajax.js	Fri Feb 22 12:51:53 2008 -0500
@@ -2,7 +2,22 @@
  * AJAX applets
  */
  
-function ajaxGet(uri, f) {
+function ajaxGet(uri, f, call_editor_safe) {
+  // Is the editor open?
+  if ( editor_open && !call_editor_safe )
+  {
+    // Make sure the user is willing to close the editor
+    var conf = confirm($lang.get('editor_msg_confirm_ajax'));
+    if ( !conf )
+    {
+      // Kill off any "loading" windows, etc. and cancel the request
+      unsetAjaxLoading();
+      return false;
+    }
+    // The user allowed the editor to be closed. Reset flags and knock out the on-close confirmation.
+    editor_open = false;
+    enableUnload();
+  }
   if (window.XMLHttpRequest) {
     ajax = new XMLHttpRequest();
   } else {
@@ -19,7 +34,22 @@
   ajax.send(null);
 }
 
-function ajaxPost(uri, parms, f) {
+function ajaxPost(uri, parms, f, call_editor_safe) {
+  // Is the editor open?
+  if ( editor_open && !call_editor_safe )
+  {
+    // Make sure the user is willing to close the editor
+    var conf = confirm($lang.get('editor_msg_confirm_ajax'));
+    if ( !conf )
+    {
+      // Kill off any "loading" windows, etc. and cancel the request
+      unsetAjaxLoading();
+      return false;
+    }
+    // The user allowed the editor to be closed. Reset flags and knock out the on-close confirmation.
+    editor_open = false;
+    enableUnload();
+  }
   if (window.XMLHttpRequest) {
     ajax = new XMLHttpRequest();
   } else {
@@ -50,7 +80,7 @@
 
 function handle_invalid_json(response, customerror)
 {
-  var mainwin = $('ajaxEditContainer').object;
+  var mainwin = $dynano('ajaxEditContainer').object;
   mainwin.innerHTML = '';
   
   // Title
@@ -67,7 +97,7 @@
   else
   {
     customerror  = 'We unexpectedly received the following response from the server. The response should have been in the JSON ';
-    customerror += 'serialization format, but the response wasn\'t composed only of the JSON response. There are three possible triggers';
+    customerror += 'serialization format, but the response wasn\'t composed only of the JSON response. There are three possible triggers ';
     customerror += 'for this problem:';
     var el = document.createElement('p');
     el.appendChild(document.createTextNode(customerror));
@@ -106,7 +136,7 @@
     var mb = new messagebox(MB_YESNO | MB_ICONEXCLAMATION, 'Do you really want to view this response as HTML?', 'If the response was changed during transmission to include malicious code, you may be allowing that malicious code to run by viewing the response as HTML. Only do this if you have reviewed the response text and have found no suspicious code in it.');
     mb.onclick['Yes'] = function()
     {
-      var html = $('invalidjson_link').object._resp;
+      var html = $dynano('invalidjson_link').object._resp;
       var win = window.open('about:blank', 'invalidjson_htmlwin', 'width=550,height=400,status=no,toolbars=no,toolbar=no,address=no,scroll=yes');
       win.document.write(html);
     }
@@ -134,142 +164,12 @@
   return text;
 }
 
-// Page editor
-
-function ajaxEditor()
-{
-  // IE <6 pseudo-compatibility
-  if ( KILL_SWITCH )
-    return true;
-  setAjaxLoading();
-  ajaxGet(stdAjaxPrefix+'&_mode=getsource', function() {
-      if(ajax.readyState == 4) {
-        unsetAjaxLoading();
-        if(edit_open) {
-          c=confirm('Do you really want to revert your changes?');
-          if(!c) return;
-        }
-        edit_open = true;
-        selectButtonMajor('article');
-        selectButtonMinor('edit');
-        if(in_array('ajaxEditArea', grippied_textareas))
-        {
-          // Allow the textarea grippifier to re-create the resizer control on the textarea
-          grippied_textareas.pop(in_array('ajaxEditArea', grippied_textareas));
-        }
-        disableUnload('If you do, any changes that you have made to this page will be lost.');
-        var switcher = ( readCookie('enano_editor_mode') == 'tinymce' ) ?
-                        '<a href="#" onclick="setEditorText(); return false;">wikitext editor</a>  |  graphical editor' :
-                        'wikitext editor  |  <a href="#" onclick="setEditorMCE(); return false;">graphical editor</a>' ;
-        document.getElementById('ajaxEditContainer').innerHTML = '\
-        <div id="mdgPreviewContainer"></div> \
-        <span id="switcher">' + switcher + '</span><br />\
-        <form name="mdgAjaxEditor" method="get" action="#" onsubmit="ajaxSavePage(); return false;">\
-        <textarea id="ajaxEditArea" rows="20" cols="60" style="display: block; margin: 1em 0 1em 1em; width: 96.5%;">'+ajax.responseText+'</textarea><br />\
-          Edit summary: <input id="ajaxEditSummary" size="40" /><br />\
-          <input id="ajaxEditMinor" name="minor" type="checkbox" /> <label for="ajaxEditMinor">This is a minor edit</label><br />\
-          <a href="#" onclick="void(ajaxSavePage()); return false;">save changes</a>  |  <a href="#" onclick="void(ajaxShowPreview()); return false;">preview changes</a>  |  <a href="#" onclick="void(ajaxEditor()); return false;">revert changes</a>  |  <a href="#" onclick="void(ajaxDiscard()); return false;">discard changes</a>\
-          <br />\
-          '+editNotice+'\
-        </form>';
-        // initTextareas();
-        if(readCookie('enano_editor_mode') == 'tinymce')
-        {
-          $('ajaxEditArea').switchToMCE();
-        }
-      }
-  });
-}
-
-function setEditorMCE()
-{
-  $('ajaxEditArea').switchToMCE();
-  createCookie('enano_editor_mode', 'tinymce', 365);
-  $('switcher').object.innerHTML = '<a href="#" onclick="setEditorText(); return false;">wikitext editor</a>  |  graphical editor';
-}
-
-function setEditorText()
-{
-  $('ajaxEditArea').destroyMCE();
-  createCookie('enano_editor_mode', 'text', 365);
-  $('switcher').object.innerHTML = 'wikitext editor  |  <a href="#" onclick="setEditorMCE(); return false;">graphical editor</a>';
-}
-
-function ajaxViewSource()
-{
-  // IE <6 pseudo-compatibility
-  if ( KILL_SWITCH )
-    return true;
-  setAjaxLoading();
-  ajaxGet(stdAjaxPrefix+'&_mode=getsource', function() {
-      if(ajax.readyState == 4) {
-        unsetAjaxLoading();
-        if(edit_open) {
-          c=confirm('Do you really want to revert your changes?');
-          if(!c) return;
-        }
-        edit_open = true;
-        selectButtonMajor('article');
-        selectButtonMinor('edit');
-        if(in_array('ajaxEditArea', grippied_textareas))
-        {
-          // Allow the textarea grippifier to re-create the resizer control on the textarea
-          grippied_textareas.pop(in_array('ajaxEditArea', grippied_textareas));
-        }
-        document.getElementById('ajaxEditContainer').innerHTML = '\
-          <form method="get" action="#" onsubmit="ajaxSavePage(); return false;">\
-            <textarea readonly="readonly" id="ajaxEditArea" rows="20" cols="60" style="display: block; margin: 1em 0 1em 1em; width: 96.5%;">'+ajax.responseText+'</textarea><br />\
-            <a href="#" onclick="void(ajaxReset()); return false;">close viewer</a>\
-          </form>';
-        initTextareas();
-      }
-  });
-}
-
-function ajaxShowPreview()
-{
-  // IE <6 pseudo-compatibility
-  if ( KILL_SWITCH )
-    return true;
-  goBusy('Loading preview...');
-  var text = ajaxEscape($('ajaxEditArea').getContent());
-  if(document.mdgAjaxEditor.minor.checked) minor='&minor';
-  else minor='';
-  ajaxPost(stdAjaxPrefix+'&_mode=preview', 'summary='+document.getElementById('ajaxEditSummary').value+minor+'&text='+text, function() {
-    if(ajax.readyState == 4) {
-      unBusy();
-      edit_open = false;
-      document.getElementById('mdgPreviewContainer').innerHTML = ajax.responseText;
-    }
-  });
-}
-
-function ajaxSavePage()
-{
-  // IE <6 pseudo-compatibility
-  if ( KILL_SWITCH )
-    return true;
-  //goBusy('Saving page...');
-  var text = ajaxEscape($('ajaxEditArea').getContent());
-  if(document.mdgAjaxEditor.minor.checked) minor='&minor';
-  else minor='';
-  ajaxPost(stdAjaxPrefix+'&_mode=savepage', 'summary='+document.getElementById('ajaxEditSummary').value+minor+'&text='+text, function() {
-    if(ajax.readyState == 4) {
-      unBusy();
-      edit_open = false;
-      document.getElementById('ajaxEditContainer').innerHTML = ajax.responseText;
-      enableUnload();
-      unselectAllButtonsMinor();
-    }
-  });
-}
-
 function ajaxDiscard()
 {
   // IE <6 pseudo-compatibility
   if ( KILL_SWITCH )
     return true;
-  c = confirm('Do you really want to discard your changes?');
+  c = confirm($lang.get('editor_msg_discard_confirm'));
   if(!c) return;
   ajaxReset();
 }
@@ -279,12 +179,16 @@
   // IE <6 pseudo-compatibility
   if ( KILL_SWITCH )
     return true;
+  var ns_id = strToPageID(title);
+  if ( ns_id[1] == 'Special' || ns_id[1] == 'Admin' )
+    return false;
   enableUnload();
   setAjaxLoading();
   ajaxGet(stdAjaxPrefix+'&_mode=getpage&noheaders', function() {
-    if(ajax.readyState == 4) {
+    // Allow for 404 here, it's generated by the "page not found" error message
+    // (even with noheaders specified, probably should be fixed)
+    if ( ajax.readyState == 4 && ( ajax.status == 200 || ajax.status == 404 ) ) {
       unsetAjaxLoading();
-      edit_open = false;
       document.getElementById('ajaxEditContainer').innerHTML = ajax.responseText;
       selectButtonMajor('article');
       unselectAllButtonsMinor();
@@ -301,7 +205,7 @@
   if(shift) {
     r = 'NO_REASON';
   } else {
-    r = prompt('Reason for (un)protecting:');
+    r = prompt($lang.get('ajax_protect_prompt_reason'));
     if(!r || r=='') return;
   }
   setAjaxLoading();
@@ -310,12 +214,12 @@
   document.getElementById('protbtn_2').style.textDecoration = 'none';
   document.getElementById('protbtn_'+l).style.textDecoration = 'underline';
   ajaxPost(stdAjaxPrefix+'&_mode=protect', 'reason='+ajaxEscape(r)+'&level='+l, function() {
-    if(ajax.readyState == 4) {
+    if ( ajax.readyState == 4 && ajax.status == 200 ) {
       unsetAjaxLoading();
       if(ajax.responseText != 'good')
         alert(ajax.responseText);
     }
-  });
+  }, true);
 }
 
 function ajaxRename()
@@ -323,15 +227,15 @@
   // IE <6 pseudo-compatibility
   if ( KILL_SWITCH )
     return true;
-  r = prompt('What title should this page be renamed to?\nNote: This does not and will never change the URL of this page, that must be done from the admin panel.');
+  r = prompt($lang.get('ajax_rename_prompt'));
   if(!r || r=='') return;
   setAjaxLoading();
   ajaxPost(stdAjaxPrefix+'&_mode=rename', 'newtitle='+ajaxEscape(r), function() {
-    if(ajax.readyState == 4) {
+    if ( ajax.readyState == 4 && ajax.status == 200 ) {
       unsetAjaxLoading();
       alert(ajax.responseText);
     }
-  });
+  }, true);
 }
 
 function ajaxMakePage()
@@ -341,7 +245,7 @@
     return true;
   setAjaxLoading();
   ajaxPost(ENANO_SPECIAL_CREATEPAGE, ENANO_CREATEPAGE_PARAMS, function() {
-    if(ajax.readyState == 4) {
+    if ( ajax.readyState == 4 && ajax.status == 200 ) {
       unsetAjaxLoading();
       window.location.reload();
     }
@@ -353,19 +257,19 @@
   // IE <6 pseudo-compatibility
   if ( KILL_SWITCH )
     return true;
-  var reason = prompt('Please enter your reason for deleting this page.');
+  var reason = prompt($lang.get('ajax_delete_prompt_reason'));
   if ( !reason || reason == '' )
   {
     return false;
   }
-  c = confirm('You are about to REVERSIBLY delete this page. Do you REALLY want to do this?\n\n(Comments and categorization data, as well as any attached files, will be permanently lost)');
+  c = confirm($lang.get('ajax_delete_confirm'));
   if(!c)
   {
     return;
   }
   setAjaxLoading();
   ajaxPost(stdAjaxPrefix+'&_mode=deletepage', 'reason=' + ajaxEscape(reason), function() {
-    if(ajax.readyState == 4) {
+    if ( ajax.readyState == 4 && ajax.status == 200 ) {
       unsetAjaxLoading();
       alert(ajax.responseText);
       window.location.reload();                                                                           
@@ -378,15 +282,15 @@
   // IE <6 pseudo-compatibility
   if ( KILL_SWITCH )
     return true;
-  c = confirm('Are you sure that you want to vote that this page be deleted?');
+  c = confirm($lang.get('ajax_delvote_confirm'));
   if(!c) return;
   setAjaxLoading();
   ajaxGet(stdAjaxPrefix+'&_mode=delvote', function() {
-    if(ajax.readyState == 4) {
+    if ( ajax.readyState == 4 && ajax.status == 200 ) {
       unsetAjaxLoading();
       alert(ajax.responseText);
     }
-  });
+  }, true);
 }
 
 function ajaxResetDelVotes()
@@ -394,11 +298,11 @@
   // IE <6 pseudo-compatibility
   if ( KILL_SWITCH )
     return true;
-  c = confirm('This will reset the number of votes against this page to zero. Do you really want to do this?');
+  c = confirm($lang.get('ajax_delvote_reset_confirm'));
   if(!c) return;
   setAjaxLoading();
   ajaxGet(stdAjaxPrefix+'&_mode=resetdelvotes', function() {
-    if(ajax.readyState == 4) {
+    if ( ajax.readyState == 4 && ajax.status == 200 ) {
       unsetAjaxLoading();
       alert(ajax.responseText);
       item = document.getElementById('mdgDeleteVoteNoticeBox');
@@ -408,7 +312,7 @@
         setTimeout("document.getElementById('mdgDeleteVoteNoticeBox').style.display = 'none';", 1000);
       }
     }
-  });
+  }, true);
 }
 
 function ajaxSetWikiMode(val) {
@@ -421,7 +325,7 @@
   document.getElementById('wikibtn_2').style.textDecoration = 'none';
   document.getElementById('wikibtn_'+val).style.textDecoration = 'underline';
   ajaxGet(stdAjaxPrefix+'&_mode=setwikimode&mode='+val, function() {
-    if(ajax.readyState == 4) {
+    if ( ajax.readyState == 4 && ajax.status == 200 ) {
       unsetAjaxLoading();
       if(ajax.responseText!='GOOD')
       {
@@ -442,7 +346,7 @@
     return true;
   setAjaxLoading();
   ajaxGet(stdAjaxPrefix+'&_mode=catedit', function() {
-    if(ajax.readyState == 4) {
+    if ( ajax.readyState == 4 && ajax.status == 200 ) {
       unsetAjaxLoading();
       edit_open = false;
       eval(ajax.responseText);
@@ -470,7 +374,7 @@
   setAjaxLoading();
   query = query.substring(1, query.length);
   ajaxPost(stdAjaxPrefix+'&_mode=catsave', query, function() {
-    if(ajax.readyState == 4) {
+    if ( ajax.readyState == 4 && ajax.status == 200 ) {
       unsetAjaxLoading();
       edit_open = false;
       if(ajax.responseText != 'GOOD') alert(ajax.responseText);
@@ -488,7 +392,7 @@
     return true;
   setAjaxLoading();
   ajaxGet(stdAjaxPrefix+'&_mode=histlist', function() {
-    if(ajax.readyState == 4) {
+    if ( ajax.readyState == 4 && ajax.status == 200 ) {
       unsetAjaxLoading();
       edit_open = false;
       selectButtonMajor('article');
@@ -506,7 +410,7 @@
   if(!tit) tit=title;
   setAjaxLoading();
   ajaxGet(append_sid(scriptPath+'/ajax.php?title='+tit+'&_mode=getpage&oldid='+oldid), function() {
-    if(ajax.readyState == 4) {
+    if ( ajax.readyState == 4 && ajax.status == 200 ) {
       unsetAjaxLoading();
       edit_open = false;
       document.getElementById('ajaxEditContainer').innerHTML = ajax.responseText;
@@ -520,7 +424,7 @@
     return true;
   setAjaxLoading();
   ajaxGet(stdAjaxPrefix+'&_mode=rollback&id='+id, function() {
-    if(ajax.readyState == 4) {
+    if ( ajax.readyState == 4 && ajax.status == 200 ) {
       unsetAjaxLoading();
       alert(ajax.responseText);
     }
@@ -532,13 +436,13 @@
   // IE <6 pseudo-compatibility
   if ( KILL_SWITCH )
     return true;
-  c = confirm('You are about to DESTROY all log entries for this page. As opposed to (example) deleting this page, this action is completely IRREVERSIBLE and should not be used except in dire circumstances. Do you REALLY want to do this?');
+  c = confirm($lang.get('ajax_clearlogs_confirm'));
   if(!c) return;
-  c = confirm('You\'re ABSOLUTELY sure???');
+  c = confirm($lang.get('ajax_clearlogs_confirm_nag'));
   if(!c) return;
   setAjaxLoading();
   ajaxGet(stdAjaxPrefix+'&_mode=flushlogs', function() {
-    if(ajax.readyState == 4) {
+    if ( ajax.readyState == 4 && ajax.status == 200 ) {
       unsetAjaxLoading();
       alert(ajax.responseText);
       window.location.reload();
@@ -622,7 +526,7 @@
   setAjaxLoading();
   ajaxGet(stdAjaxPrefix+'&_mode=pagediff&diff1='+id1+'&diff2='+id2, function()
     {
-      if(ajax.readyState==4)
+      if ( ajax.readyState == 4 && ajax.status == 200 )
       {
         unsetAjaxLoading();
         document.getElementById('ajaxEditContainer').innerHTML = ajax.responseText;
@@ -638,13 +542,13 @@
   if ( KILL_SWITCH )
     return true;
   var inner_html = '';
-  inner_html += '<p><label>Theme: ';
+  inner_html += '<p><label>' + $lang.get('ajax_changestyle_lbl_theme') + ' ';
   inner_html += '  <select id="chtheme_sel_theme" onchange="ajaxGetStyles(this.value);">';
-  inner_html += '    <option value="_blank" selected="selected">[Select]</option>';
+  inner_html += '    <option value="_blank" selected="selected">' + $lang.get('ajax_changestyle_select') + '</option>';
   inner_html +=      ENANO_THEME_LIST;
   inner_html += '  </select>';
   inner_html += '</label></p>';
-  var chtheme_mb = new messagebox(MB_OKCANCEL|MB_ICONQUESTION, 'Change your theme', inner_html);
+  var chtheme_mb = new messagebox(MB_OKCANCEL|MB_ICONQUESTION, $lang.get('ajax_changestyle_title'), inner_html);
   chtheme_mb.onbeforeclick['OK'] = ajaxChangeStyleComplete;
 }
 
@@ -663,7 +567,7 @@
     return null;
   }
   ajaxGet(stdAjaxPrefix + '&_mode=getstyles&id=' + id, function() {
-      if ( ajax.readyState == 4 )
+      if ( ajax.readyState == 4 && ajax.status == 200 )
       {
         // IE doesn't like substr() on ajax.responseText
         var response = String(ajax.responseText + ' ');
@@ -689,7 +593,7 @@
         var p_parent = document.createElement('p');
         var label  = document.createElement('label');
         p_parent.id = 'chtheme_sel_style_parent';
-        label.appendChild(document.createTextNode('Style: '));
+        label.appendChild(document.createTextNode($lang.get('ajax_changestyle_lbl_style') + ' '));
         var select = document.createElement('select');
         select.id = 'chtheme_sel_style';
         for ( var i in options )
@@ -706,7 +610,7 @@
         kid.appendChild(p_parent);
         
       }
-    });
+    }, true);
 }
 
 function ajaxChangeStyleComplete()
@@ -714,11 +618,11 @@
   // IE <6 pseudo-compatibility
   if ( KILL_SWITCH )
     return true;
-  var theme = $('chtheme_sel_theme');
-  var style = $('chtheme_sel_style');
+  var theme = $dynano('chtheme_sel_theme');
+  var style = $dynano('chtheme_sel_style');
   if ( !theme.object || !style.object )
   {
-    alert('Please select a theme from the list.');
+    alert($lang.get('ajax_changestyle_pleaseselect_theme'));
     return true;
   }
   var theme_id = theme.object.value;
@@ -738,11 +642,11 @@
   
   ajaxPost(stdAjaxPrefix + '&_mode=change_theme', 'theme_id=' + ajaxEscape(theme_id) + '&style_id=' + ajaxEscape(style_id), function()
     {
-      if ( ajax.readyState == 4 )
+      if ( ajax.readyState == 4 && ajax.status == 200 )
       {
         if ( ajax.responseText == 'GOOD' )
         {
-          var c = confirm('Your theme preference has been changed.\nWould you like to reload the page now to see the changes?');
+          var c = confirm($lang.get('ajax_changestyle_success'));
           if ( c )
             window.location.reload();
         }
@@ -751,7 +655,7 @@
           alert('Error occurred during attempt to change theme:\n' + ajax.responseText);
         }
       }
-    });
+    }, true);
   
   return false;
   
@@ -794,7 +698,7 @@
 function ajaxGetStyles(id) {
   setAjaxLoading();
   ajaxGet(stdAjaxPrefix+'&_mode=getstyles&id='+id, function() {
-    if(ajax.readyState == 4) {
+    if ( ajax.readyState == 4 && ajax.status == 200 ) {
       unsetAjaxLoading();
       eval(ajax.responseText);
       html = '<h3>And a style...</h3><select id="mdgStyleID" name="style">';
@@ -837,22 +741,16 @@
   ajaxPost(stdAjaxPrefix+'&_mode=setpass', 'password='+pass, function()
     {
       unsetAjaxLoading();
-      if(ajax.readyState==4)
+      if ( ajax.readyState == 4 && ajax.status == 200 )
       {
         alert(ajax.responseText);
       }
-    }
-  );
+    }, true);
 }
 
 function ajaxStartLogin()
 {
-  // IE <6 pseudo-compatibility
-  if ( KILL_SWITCH )
-    return true;
-  ajaxPromptAdminAuth(function(k) {
-      window.location.reload();
-    }, USER_LEVEL_MEMBER);
+  ajaxLogonToMember();
 }
 
 function ajaxStartAdminLogin()
@@ -862,7 +760,7 @@
     return true;
   if ( auth_level < USER_LEVEL_ADMIN )
   {
-    ajaxPromptAdminAuth(function(k) {
+    ajaxLoginInit(function(k) {
       ENANO_SID = k;
       auth_level = USER_LEVEL_ADMIN;
       var loc = makeUrlNS('Special', 'Administration');
@@ -951,7 +849,7 @@
   // IE <6 pseudo-compatibility
   if ( KILL_SWITCH )
     return true;
-  if ( !confirm('Are you really sure you want to do this? Some pages might not function if this emergency-only feature is activated.') )
+  if ( !confirm($lang.get('ajax_killphp_confirm')) )
     return false;
   var $killdiv = $dynano('php_killer');
   if ( !$killdiv.object )
@@ -962,7 +860,7 @@
   $killdiv.object.innerHTML = '<img alt="Loading..." src="' + scriptPath + '/images/loading-big.gif" /><br />Making request...';
   var url = makeUrlNS('Admin', 'Home', 'src=ajax');
   ajaxPost(url, 'act=kill_php', function() {
-      if ( ajax.readyState == 4 )
+      if ( ajax.readyState == 4 && ajax.status == 200 )
       {
         if ( ajax.responseText == '1' )
         {
@@ -972,7 +870,7 @@
           var newdiv = document.createElement('div');
           // newdiv.style = $killdiv.object.style;
           newdiv.className = $killdiv.object.className;
-          newdiv.innerHTML = '<img alt="Success" src="' + scriptPath + '/images/error.png" /><br />Embedded PHP in pages has been disabled.';
+          newdiv.innerHTML = '<img alt="Success" src="' + scriptPath + '/images/error.png" /><br />' + $lang.get('ajax_killphp_success');
           $killdiv.object.parentNode.appendChild(newdiv);
           $killdiv.object.parentNode.removeChild($killdiv.object);
         }
@@ -994,7 +892,7 @@
   setAjaxLoading();
   ajaxGet(stdAjaxPrefix + '&_mode=get_tags', function()
     {
-      if ( ajax.readyState == 4 )
+      if ( ajax.readyState == 4 && ajax.status == 200 )
       {
         unsetAjaxLoading();
         var resptext = String(ajax.responseText + ' ');
@@ -1009,14 +907,14 @@
         if ( !catbox )
           return false;
         var linkbox = catbox.parentNode.firstChild.firstChild.nextSibling;
-        linkbox.firstChild.nodeValue = 'show page categorization';
+        linkbox.firstChild.nodeValue = $lang.get('catedit_catbox_link_showcategorization');
         linkbox.onclick = function() { ajaxTagToCat(); return false; };
         catHTMLBuf = catbox.innerHTML;
         catbox.innerHTML = '';
-        catbox.appendChild(document.createTextNode('Page tags: '));
+        catbox.appendChild(document.createTextNode($lang.get('tags_lbl_page_tags')+' '));
         if ( json.tags.length < 1 )
         {
-          catbox.appendChild(document.createTextNode('No tags on this page'));
+          catbox.appendChild(document.createTextNode($lang.get('tags_lbl_no_tags')));
         }
         for ( var i = 0; i < json.tags.length; i++ )
         {
@@ -1040,7 +938,7 @@
           var addlink = document.createElement('a');
           addlink.href = '#';
           addlink.onclick = function() { try { ajaxAddTagStage1(); } catch(e) { }; return false; };
-          addlink.appendChild(document.createTextNode('(add a tag)'));
+          addlink.appendChild(document.createTextNode($lang.get('tags_btn_add_tag')));
           catbox.appendChild(addlink);
         }
       }
@@ -1059,7 +957,7 @@
   var addlink = document.createElement('a');
   addlink.href = '#';
   addlink.onclick = function() { ajaxAddTagStage2(this.parentNode.firstChild.nextSibling.value, this.parentNode); return false; };
-  addlink.appendChild(document.createTextNode('+ Add'));
+  addlink.appendChild(document.createTextNode($lang.get('tags_btn_add')));
   text.type = 'text';
   text.size = '15';
   text.onkeyup = function(e)
@@ -1071,7 +969,7 @@
   }
   
   adddiv.style.margin = '5px 0 0 0';
-  adddiv.appendChild(document.createTextNode('Add a tag: '));
+  adddiv.appendChild(document.createTextNode($lang.get('tags_lbl_add_tag')+' '));
   adddiv.appendChild(text);
   adddiv.appendChild(document.createTextNode(' '));
   adddiv.appendChild(addlink);
@@ -1092,7 +990,7 @@
   setAjaxLoading();
   ajaxPost(stdAjaxPrefix + '&_mode=addtag', 'tag=' + tag, function()
     {
-      if ( ajax.readyState == 4 )
+      if ( ajax.readyState == 4 && ajax.status == 200 )
       {
         unsetAjaxLoading();
         var nukeme = addtag_nukeme;
@@ -1113,7 +1011,7 @@
           var node = parent.childNodes[1];
           var insertafter = false;
           var nukeafter = false;
-          if ( node.nodeValue == 'No tags on this page' )
+          if ( node.nodeValue == $lang.get('tags_lbl_no_tags') )
           {
             nukeafter = true;
           }
@@ -1154,17 +1052,17 @@
   var writeNoTags = false;
   if ( parentobj.previousSibling.previousSibling.previousSibling.nodeValue == ', ' )
     arrDelete.push(parentobj.previousSibling.previousSibling.previousSibling);
-  else if ( parentobj.previousSibling.previousSibling.previousSibling.nodeValue == 'Page tags: ' )
+  else if ( parentobj.previousSibling.previousSibling.previousSibling.nodeValue == $lang.get('tags_lbl_page_tags') + ' ' )
     arrDelete.push(parentobj.nextSibling);
   
-  if ( parentobj.previousSibling.previousSibling.previousSibling.nodeValue == 'Page tags: ' &&
+  if ( parentobj.previousSibling.previousSibling.previousSibling.nodeValue == $lang.get('tags_lbl_page_tags') + ' ' &&
        parentobj.nextSibling.nextSibling.firstChild )
-    if ( parentobj.nextSibling.nextSibling.firstChild.nodeValue == '(add a tag)')
+    if ( parentobj.nextSibling.nextSibling.firstChild.nodeValue == $lang.get('tags_btn_add_tag'))
       writeNoTags = true;
     
   ajaxPost(stdAjaxPrefix + '&_mode=deltag', 'tag_id=' + String(tag_id), function()
     {
-      if ( ajax.readyState == 4 )
+      if ( ajax.readyState == 4 && ajax.status == 200 )
       {
         if ( ajax.responseText == 'success' )
         {
@@ -1177,7 +1075,7 @@
           }
           if ( writeNoTags )
           {
-            var node1 = document.createTextNode('No tags on this page');
+            var node1 = document.createTextNode($lang.get('tags_lbl_no_tags'));
             var node2 = document.createTextNode(' ');
             insertAfter(parent, node1, parent.firstChild);
             insertAfter(parent, node2, node1);
@@ -1200,7 +1098,7 @@
     return false;
   addtag_open = false;
   var linkbox = catbox.parentNode.firstChild.firstChild.nextSibling;
-  linkbox.firstChild.nodeValue = 'show page tags';
+  linkbox.firstChild.nodeValue = $lang.get('tags_catbox_link');
   linkbox.onclick = function() { ajaxCatToTag(); return false; };
   catbox.innerHTML = catHTMLBuf;
   catHTMLBuf = false;
@@ -1223,7 +1121,7 @@
     if ( keepalive_interval )
       clearInterval(keepalive_interval);
     var span = document.getElementById('keepalivestat');
-    span.firstChild.nodeValue = 'Turn on keep-alive';
+    span.firstChild.nodeValue = $lang.get('adm_btn_keepalive_off');
   }
   else
   {
@@ -1231,7 +1129,7 @@
     if ( !keepalive_interval )
       keepalive_interval = setInterval('ajaxPingServer();', 600000);
     var span = document.getElementById('keepalivestat');
-    span.firstChild.nodeValue = 'Turn off keep-alive';
+    span.firstChild.nodeValue = $lang.get('adm_btn_keepalive_on');
     ajaxPingServer();
   }
 }
@@ -1243,19 +1141,221 @@
     if ( !keepalive_interval )
       keepalive_interval = setInterval('ajaxPingServer();', 600000);
     var span = document.getElementById('keepalivestat');
-    span.firstChild.nodeValue = 'Turn off keep-alive';
+    span.firstChild.nodeValue = $lang.get('adm_btn_keepalive_on');
   }
   else
   {
     if ( keepalive_interval )
       clearInterval(keepalive_interval);
     var span = document.getElementById('keepalivestat');
-    span.firstChild.nodeValue = 'Turn on keep-alive';
+    span.firstChild.nodeValue = $lang.get('adm_btn_keepalive_off');
   }
 };
 
 function aboutKeepAlive()
 {
-  new messagebox(MB_OK|MB_ICONINFORMATION, 'About the keep-alive feature', 'Keep-alive is a new Enano feature that keeps your administrative session from timing out while you are using the administration panel. This feature can be useful if you are editing a large page or doing something in the administration interface that will take longer than 15 minutes.<br /><br />For security reasons, Enano mandates that high-privilege logins last only 15 minutes, with the time being reset each time a page is loaded (or, more specifically, each time the session API is started). The consequence of this is that if you are performing an action in the administration panel that takes more than 15 minutes, your session may be terminated. The keep-alive feature attempts to relieve this by sending a "ping" to the server every 10 minutes.<br /><br />Please note that keep-alive state is determined by a cookie. Thus, if you log out and then back in as a different administrator, keep-alive will use the same setting that was used when you were logged in as the first administrative user. In the same way, if you log into the administration panel under your account from another computer, keep-alive will be set to "off".<br /><br /><b>For more information:</b><br /><a href="http://docs.enanocms.org/Help:Appendix_B" onclick="window.open(this.href); return false;">Overview of Enano'+"'"+'s security model');
+  new messagebox(MB_OK|MB_ICONINFORMATION, $lang.get('user_keepalive_info_title'), $lang.get('user_keepalive_info_body'));
+}
+
+function ajaxShowCaptcha(code)
+{
+  var mydiv = document.createElement('div');
+  mydiv.style.backgroundColor = '#FFFFFF';
+  mydiv.style.padding = '10px';
+  mydiv.style.position = 'absolute';
+  mydiv.style.top = '0px';
+  mydiv.id = 'autoCaptcha';
+  mydiv.style.zIndex = String( getHighestZ() + 1 );
+  var img = document.createElement('img');
+  img.onload = function()
+  {
+    if ( this.loaded )
+      return true;
+    var mydiv = document.getElementById('autoCaptcha');
+    var width = getWidth();
+    var divw = $dynano(mydiv).Width();
+    var left = ( width / 2 ) - ( divw / 2 );
+    mydiv.style.left = left + 'px';
+    fly_in_top(mydiv, false, true);
+    this.loaded = true;
+  };
+  img.src = makeUrlNS('Special', 'Captcha/' + code);
+  img.onclick = function() { this.src = this.src + '/a'; };
+  img.style.cursor = 'pointer';
+  mydiv.appendChild(img);
+  domObjChangeOpac(0, mydiv);
+  var body = document.getElementsByTagName('body')[0];
+  body.appendChild(mydiv);
 }
 
+function ajaxUpdateCheck(targetelement)
+{
+  if ( !document.getElementById(targetelement) )
+  {
+    return false;
+  }
+  var target = document.getElementById(targetelement);
+  target.innerHTML = '';
+  var img = document.createElement('img');
+  img.src = scriptPath + '/images/loading.gif';
+  img.alt = 'Loading...';
+  target.appendChild(img);
+  ajaxGet(makeUrlNS('Admin', 'Home/updates.xml'), function()
+    {
+      if ( ajax.readyState == 4 && ajax.status == 200 )
+      {
+        var releases = new Array();
+        var update_available = false;
+        if ( ajax.responseXML == null )
+        {
+          alert("Error fetching updates list:\n" + ajax.responseText);
+          return false;
+        }
+        if ( ajax.responseXML.firstChild.tagName == 'enano' )
+        {
+          var enanotag = ajax.responseXML.firstChild;
+          for ( var i = 0; i < enanotag.childNodes.length; i++ )
+          {
+            if ( enanotag.childNodes[i].tagName == 'error' )
+            {
+              alert(enanotag.childNodes[i].firstChild.nodeValue);
+            }
+            else if ( enanotag.childNodes[i].tagName == 'latest' )
+            {
+              // got <latest>
+              var latesttag = enanotag.childNodes[i];
+              for ( var j = 0; j < latesttag.childNodes.length; j++ )
+              {
+                var node = latesttag.childNodes[j];
+                if ( node.tagName == 'release' )
+                {
+                  var releasedata = new Object();
+                  for ( var k = 0; k < node.attributes.length; k++ )
+                  {
+                    releasedata[node.attributes[k].nodeName] = node.attributes[k].nodeValue;
+                  }
+                  releases.push(releasedata);
+                }
+                else if ( node.tagName == 'haveupdates' )
+                {
+                  update_available = true;
+                }
+              }
+              break;
+            }
+          }
+        }
+        else
+        {
+          return false;
+        }
+        var thediv = document.getElementById(targetelement);
+        thediv.innerHTML = '';
+        if ( !thediv )
+        {
+          return false;
+        }
+        if ( releases.length > 0 )
+        {
+          thediv.className = 'tblholder';
+          if ( update_available )
+          {
+            var infobox = document.createElement('div');
+            infobox.className = 'info-box-mini';
+            infobox.appendChild(document.createTextNode('An update for Enano is available. The newest release is highlighted below.'));
+            infobox.style.borderWidth = '0';
+            infobox.style.margin = '0 0 0 0';
+            thediv.appendChild(infobox);
+          }
+          else
+          {
+            var infobox = document.createElement('div');
+            infobox.className = 'info-box-mini';
+            infobox.appendChild(document.createTextNode('No new updates are available. The latest available releases are shown below.'));
+            infobox.style.borderWidth = '0';
+            infobox.style.margin = '0 0 0 0';
+            thediv.appendChild(infobox);
+          }
+          var table = document.createElement('table');
+          table.setAttribute('border', '0');
+          table.setAttribute('cellspacing', '1');
+          table.setAttribute('cellpadding', '4');
+          
+          var tr = document.createElement('tr');
+          
+          var td1 = document.createElement('th');
+          var td2 = document.createElement('th');
+          var td3 = document.createElement('th');
+          var td4 = document.createElement('th');
+          
+          td1.appendChild( document.createTextNode('Release type') );
+          td2.appendChild( document.createTextNode('Version') );
+          td3.appendChild( document.createTextNode('Code name') );
+          td4.appendChild( document.createTextNode('Release notes') );
+          
+          tr.appendChild(td1);
+          tr.appendChild(td2);
+          tr.appendChild(td3);
+          tr.appendChild(td4);
+            
+          table.appendChild(tr);
+          
+          var cls = 'row2';
+          
+          var j = 0;
+          for ( var i in releases )
+          {
+            j++;
+            if ( j > 5 )
+              break;
+            if ( update_available && j == 1 )
+              cls = 'row1_green';
+            else
+              cls = ( cls == 'row1' ) ? 'row2' : 'row1';
+            var release = releases[i];
+            var tr = document.createElement('tr');
+            
+            var td1 = document.createElement('td');
+            var td2 = document.createElement('td');
+            var td3 = document.createElement('td');
+            var td4 = document.createElement('td');
+            
+            td1.className = cls;
+            td2.className = cls;
+            td3.className = cls;
+            td4.className = cls;
+            
+            if ( release.tag )
+              td1.appendChild( document.createTextNode(release.tag) );
+            
+            if ( release.version )
+              td2.appendChild( document.createTextNode(release.version) );
+            
+            if ( release.codename )
+              td3.appendChild( document.createTextNode(release.codename) );
+            
+            if ( release.relnotes )
+            {
+              var a = document.createElement('a');
+              a.href = release.relnotes;
+              a.appendChild(document.createTextNode('View'));
+              td4.appendChild( a );
+            }
+            
+            tr.appendChild(td1);
+            tr.appendChild(td2);
+            tr.appendChild(td3);
+            tr.appendChild(td4);
+            
+            table.appendChild(tr);
+          }
+          thediv.appendChild(table);
+        }
+        else
+        {
+          thediv.appendChild(document.createTextNode('No releases available.'));
+        }
+      }
+    });
+}
+
--- a/includes/clientside/static/autocomplete.js	Fri Feb 22 12:46:51 2008 -0500
+++ b/includes/clientside/static/autocomplete.js	Fri Feb 22 12:51:53 2008 -0500
@@ -137,7 +137,7 @@
   val = escape(o.value).replace('+', '%2B');
   ajaxGet(stdAjaxPrefix+'&_mode=fillusername&name='+val, function()
     {
-      if(ajax.readyState==4)
+      if ( ajax.readyState == 4 && ajax.status == 200 )
       {
         // Determine the appropriate left/top positions, then create a div to use for the drop-down list
         // The trick here is to be able to make the div dynamically destroy itself depending on how far the user's mouse is from it
@@ -185,7 +185,7 @@
         }
         else
         {
-          html = '<table border="0" cellspacing="1" cellpadding="3" style="width: auto;"><tr><th><small>Username matches</small></th></tr>';
+          html = '<table border="0" cellspacing="1" cellpadding="3" style="width: auto;"><tr><th><small>' + $lang.get('user_autofill_heading_suggestions') + '</small></th></tr>';
           cls = 'row2';
           unObjCurrentSelection = userlist[0];
           for(i=0;i<userlist.length;i++)
@@ -224,7 +224,7 @@
   ajaxGet(stdAjaxPrefix+'&_mode=fillpagename&name='+val, function()
     {
       if(!ajax) return;
-      if(ajax.readyState==4)
+      if ( ajax.readyState == 4 && ajax.status == 200 )
       {
         // Determine the appropriate left/top positions, then create a div to use for the drop-down list
         // The trick here is to be able to make the div dynamically destroy itself depending on how far the user's mouse is from it
@@ -251,7 +251,7 @@
         }
         else
         {
-          html = '<table border="0" cellspacing="1" cellpadding="3" style="width: auto;"><tr><th colspan="2">Page name matches</th></tr><tr><th><small>Page title</small></th><th><small>Page ID</small></th></tr>';
+          html = '<table border="0" cellspacing="1" cellpadding="3" style="width: auto;"><tr><th colspan="2">' + $lang.get('page_autosuggest_heading') + '</th></tr><tr><th><small>' + $lang.get('page_autosuggest_col_name') + '</small></th><th><small>' + $lang.get('page_autosuggest_col_page_id') + '</small></th></tr>';
           cls = 'row2';
           unObjCurrentSelection = userlist[0];
           for(i=0;i<userlist.length;i++)
--- a/includes/clientside/static/autofill.js	Fri Feb 22 12:46:51 2008 -0500
+++ b/includes/clientside/static/autofill.js	Fri Feb 22 12:51:53 2008 -0500
@@ -58,7 +58,7 @@
         if ( autofill.event.keyCode == autofill.KEY_ENTER && autofill.boxes.length < 1 && !autofill.box_id )
         {
           // user hit enter after accepting a suggestion - submit the form
-          var frm = findParentForm($(autofill.field_id).object);
+          var frm = findParentForm($dynano(autofill.field_id).object);
           frm._af_acting = false;
           frm.submit();
           // window.console.info('Submitting form');
@@ -86,7 +86,7 @@
       try
       {
         var user = resp_json.users_real[i].toLowerCase();
-        var inp  = $(autofill.field_id).object.value;
+        var inp  = $dynano(autofill.field_id).object.value;
         inp = inp.toLowerCase();
         if ( user.indexOf(inp) > -1 )
         {
@@ -116,7 +116,7 @@
     
     var tr = document.createElement('tr');
     var th = document.createElement('th');
-    th.appendChild(document.createTextNode('Username suggestions'));
+    th.appendChild(document.createTextNode($lang.get('user_autofill_heading_suggestions')));
     tr.appendChild(th);
     table.appendChild(tr);
     
@@ -125,7 +125,7 @@
       var tr = document.createElement('tr');
       var td = document.createElement('td');
       td.className = 'row1';
-      td.appendChild(document.createTextNode('No suggestions'));
+      td.appendChild(document.createTextNode($lang.get('user_autofill_msg_no_suggestions')));
       td.afobj = autofill;
       tr.appendChild(td);
       table.appendChild(tr);
@@ -150,10 +150,10 @@
       }
       
     // Finalize div
-    var tb_top    = $(autofill.field_id).Top();
-    var tb_height = $(autofill.field_id).Height();
+    var tb_top    = $dynano(autofill.field_id).Top();
+    var tb_height = $dynano(autofill.field_id).Height();
     var af_top    = tb_top + tb_height - 9;
-    var tb_left   = $(autofill.field_id).Left();
+    var tb_left   = $dynano(autofill.field_id).Left();
     var af_left   = tb_left;
     
     div.style.position = 'absolute';
@@ -182,7 +182,7 @@
     af_current = this;
     var processResponse = function()
     {
-      if ( ajax.readyState == 4 )
+      if ( ajax.readyState == 4 && ajax.status == 200 )
       {
         var afobj = af_current;
         af_current = false;
@@ -193,15 +193,15 @@
           new messagebox(MB_OK|MB_ICONSTOP, 'Invalid response', 'Invalid or unexpected JSON response from server:<pre>' + ajax.responseText + '</pre>');
           return false;
         }
-        if ( $(afobj.field_id).object.value.length < 3 )
+        if ( $dynano(afobj.field_id).object.value.length < 3 )
           return false;
         var resp_json = parseJSON(response);
-        var resp_code = $(afobj.field_id).object.value.toLowerCase().substr(0, 3);
+        var resp_code = $dynano(afobj.field_id).object.value.toLowerCase().substr(0, 3);
         afobj.responses[resp_code] = resp_json;
         afobj.process_dataset(resp_json);
       }
     }
-    var usernamefragment = ajaxEscape($(this.field_id).object.value);
+    var usernamefragment = ajaxEscape($dynano(this.field_id).object.value);
     ajaxGet(stdAjaxPrefix + '&_mode=fillusername&name=' + usernamefragment + '&allowanon=' + ( this.allowanon ? '1' : '0' ), processResponse);
   }
   
@@ -216,7 +216,7 @@
     if ( af_current )
       return false;
     
-    var resp_code = $(this.field_id).object.value.toLowerCase().substr(0, 3);
+    var resp_code = $dynano(this.field_id).object.value.toLowerCase().substr(0, 3);
     if ( this.responses.length < 1 || ! this.responses[ resp_code ] )
     {
       // window.console.info('Cannot find dataset ' + resp_code + ' in cache, sending AJAX request');
@@ -261,7 +261,7 @@
     if ( key == this.KEY_ENTER && !this.repeat )
     {
       submitAuthorized = true;
-      var form = findParentForm($(this.field_id).object);
+      var form = findParentForm($dynano(this.field_id).object);
       form._af_acting = false;
       return true;
     }
@@ -284,7 +284,7 @@
         break;
     }
     
-    var form = findParentForm($(this.field_id).object);
+    var form = findParentForm($dynano(this.field_id).object);
       form._af_acting = false;
   }
   
@@ -315,9 +315,9 @@
     if ( state_td.parentNode.nextSibling )
     {
       // Ooh boy, DOM stuff can be so complicated...
-      // <tr>  -->  <tr>
-      // <td>       <td>
-      // user       user
+      //   <tr>   →   <tr>
+      // ↑ <td>       <td> ↓
+      //   user       user
       
       var newstate = state_td.parentNode.nextSibling.firstChild.firstChild.nodeValue;
       if ( !newstate )
@@ -327,19 +327,19 @@
       state_td.parentNode.nextSibling.firstChild.className = 'row2';
       
       // Exception - automatically scroll around if the item is off-screen
-      var height = $(this.box_id).Height();
-      var top = $(this.box_id).object.scrollTop;
+      var height = $dynano(this.box_id).Height();
+      var top = $dynano(this.box_id).object.scrollTop;
       var scroll_bottom = height + top;
       
-      var td_top = $(state_td.parentNode.nextSibling.firstChild).Top() - $(this.box_id).Top();
-      var td_height = $(state_td.parentNode.nextSibling.firstChild).Height();
+      var td_top = $dynano(state_td.parentNode.nextSibling.firstChild).Top() - $dynano(this.box_id).Top();
+      var td_height = $dynano(state_td.parentNode.nextSibling.firstChild).Height();
       var td_bottom = td_top + td_height;
       
       if ( td_bottom > scroll_bottom )
       {
         var scrollY = td_top - height + 2*td_height - 7;
         // window.console.debug(scrollY);
-        $(this.box_id).object.scrollTop = scrollY;
+        $dynano(this.box_id).object.scrollTop = scrollY;
         /*
         var newtd = state_td.parentNode.nextSibling.firstChild;
         var a = document.createElement('a');
@@ -351,7 +351,7 @@
         */
         
         // In firefox, scrolling like that makes the field get unfocused
-        $(this.field_id).object.focus();
+        $dynano(this.field_id).object.focus();
       }
     }
     else
@@ -368,9 +368,9 @@
     if ( state_td.parentNode.previousSibling && state_td.parentNode.previousSibling.firstChild.tagName != 'TH' )
     {
       // Ooh boy, DOM stuff can be so complicated...
-      // <tr>  <--  <tr>
-      // <td>       <td>
-      // user       user
+      //   <tr>   ↠  <tr>
+      // ↓ <td>       <td> ↑
+      //   user       user
       
       var newstate = state_td.parentNode.previousSibling.firstChild.firstChild.nodeValue;
       if ( !newstate )
@@ -382,13 +382,13 @@
       state_td.parentNode.previousSibling.firstChild.className = 'row2';
       
       // Exception - automatically scroll around if the item is off-screen
-      var top = $(this.box_id).object.scrollTop;
+      var top = $dynano(this.box_id).object.scrollTop;
       
-      var td_top = $(state_td.parentNode.previousSibling.firstChild).Top() - $(this.box_id).Top();
+      var td_top = $dynano(state_td.parentNode.previousSibling.firstChild).Top() - $dynano(this.box_id).Top();
       
       if ( td_top < top )
       {
-        $(this.box_id).object.scrollTop = td_top - 10;
+        $dynano(this.box_id).object.scrollTop = td_top - 10;
         /*
         var newtd = state_td.parentNode.previousSibling.firstChild;
         var a = document.createElement('a');
@@ -400,12 +400,12 @@
         */
         
         // In firefox, scrolling like that makes the field get unfocused
-        $(this.field_id).object.focus();
+        $dynano(this.field_id).object.focus();
       }
     }
     else
     {
-      $(this.box_id).object.scrollTop = 0;
+      $dynano(this.box_id).object.scrollTop = 0;
       return false;
     }
   }
@@ -439,7 +439,7 @@
     else if ( this.state )
       ta.value = this.state;
     this.destroy();
-    findParentForm($(this.field_id.object))._af_acting = false;
+    findParentForm($dynano(this.field_id.object))._af_acting = false;
   }
   
   this.sleep = function()
@@ -449,7 +449,7 @@
       var div = document.getElementById(this.box_id);
       div.style.display = 'none';
     }
-    var el = $(this.field_id).object;
+    var el = $dynano(this.field_id).object;
     var fr = findParentForm(el);
     el._af_acting = false;
   }
--- a/includes/clientside/static/comments.js	Fri Feb 22 12:46:51 2008 -0500
+++ b/includes/clientside/static/comments.js	Fri Feb 22 12:51:53 2008 -0500
@@ -19,7 +19,7 @@
     parms.have_template = true;
   parms = ajaxEscape(toJSONString(parms));
   ajaxPost(stdAjaxPrefix+'&_mode=comments', 'data=' + parms, function() {
-    if(ajax.readyState == 4) {
+    if ( ajax.readyState == 4 && ajax.status == 200 ) {
       unsetAjaxLoading();
       selectButtonMajor('discussion');
       unselectAllButtonsMinor();
@@ -48,7 +48,7 @@
           annihiliateComment(response.id);
           break;
         case 'materialize':
-          alert('Your comment has been posted. If it does not appear right away, it is probably awaiting approval.');
+          alert($lang.get('comment_msg_comment_posted'));
           hideCommentForm();
           materializeComment(response);
           break;
@@ -70,36 +70,43 @@
   
   // Header
   
-    html += '<h3>Article Comments</h3>';
+    html += '<h3>' + $lang.get('comment_heading') + '</h3>';
     
-    var ns = ( strToPageID(title)[1]=='Article' ) ? 'article' : ( strToPageID(title)[1].toLowerCase() ) + ' page';
+    var ns = ENANO_PAGE_TYPE;
   
-    // Counters
+  // Counters
     if ( data.auth_mod_comments )
     {
       var cnt = ( data.auth_mod_comments ) ? data.count_total : data.count_appr;
-      if ( cnt == 0 ) cnt = 'no';
-      var s  = ( cnt == 1 ) ? '' : 's';
-      var is = ( cnt == 1 ) ? 'is' : 'are';
-      html += "<p id=\"comment_status\">There "+is+" " + cnt + " comment"+s+" on this "+ns+".";
+      
+      var subst = {
+        num_comments: cnt,
+        page_type: ns
+      }
+      var count_msg = ( cnt == 0 ) ? $lang.get('comment_msg_count_zero', subst) : ( ( cnt == 1 ) ? $lang.get('comment_msg_count_one', subst) : $lang.get('comment_msg_count_plural', subst) );
+      
+      html += "<p id=\"comment_status\"><span>" + count_msg + '</span>';
       if ( data.count_unappr > 0 )
       {
-        html += ' <span style="color: #D84308">' + data.count_unappr + ' of those are unapproved.</span>';
+        html += ' <span style="color: #D84308" id="comment_status_unapp">' + $lang.get('comment_msg_count_unapp_mod', { num_unapp: data.count_unappr }) + '</span>';
       }
       html += '</p>';
     }
     else
     {
       var cnt = data.count_appr;
-      if ( cnt == 0 ) cnt = 'no';
-      var s  = ( cnt == 1 ) ? '' : 's';
-      var is = ( cnt == 1 ) ? 'is' : 'are';
-      html += "<p id=\"comment_status\">There "+is+" " + cnt + " comment"+s+" on this "+ns+".";
+      
+      var subst = {
+        num_comments: cnt,
+        page_type: ns
+      }
+      var count_msg = ( cnt == 0 ) ? $lang.get('comment_msg_count_zero', subst) : ( ( cnt == 1 ) ? $lang.get('comment_msg_count_one', subst) : $lang.get('comment_msg_count_plural', subst) );
+      
+      html += "<p id=\"comment_status\">" + count_msg;
       if ( data.count_unappr > 0 )
       {
-        var s  = ( data.count_unappr == 1 ) ? '' : 's';
-        var is = ( data.count_unappr == 1 ) ? 'is' : 'are';
-        html += ' However, there '+is+' '+data.count_unappr+' additional comment'+s+' awaiting approval.';
+        var unappr_msg  = ( data.count_unappr == 1 ) ? $lang.get('comment_msg_count_unapp_one') : $lang.get('comment_msg_count_unapp_plural', { num_unapp: data.count_unappr });
+        html += ' ' + unappr_msg;
       }
       html += '</p>';
     }
@@ -115,34 +122,32 @@
   
   if ( data.auth_post_comments )
   {
-    
     // Posting form
   
-    html += '<h3>Got something to say?</h3>';
-    html += '<p>If you have comments or suggestions on this article, you can shout it out here.';
+    html += '<h3>' + $lang.get('comment_postform_title') + '</h3>';
+    html += '<p>' + $lang.get('comment_postform_blurb');
     if ( data.approval_needed )
-      html+=' Before your post will be visible to the public, a moderator will have to approve it.';
-    html += ' <a id="leave_comment_button" href="#" onclick="displayCommentForm(); return false;">Leave a comment...</a></p>';
+      html+=' ' + $lang.get('comment_postform_blurb_unapp');
+    html += ' <a id="leave_comment_button" href="#" onclick="displayCommentForm(); return false;">' + $lang.get('comment_postform_blurb_link') + '</a></p>';
     html += '<div id="comment_form" style="display: none;">';
     html += '  <table border="0">';
-    html += '    <tr><td>Your name/screen name:</td><td>';
+    html += '    <tr><td>' + $lang.get('comment_postform_field_name') + '</td><td>';
     if ( data.user_id > 1 ) html += data.username + '<input id="commentform_name" type="hidden" value="'+data.username+'" size="40" />';
     else html += '<input id="commentform_name" type="text" size="40" />';
     html += '    </td></tr>';
-    html += '    <tr><td>Comment subject:</td><td><input id="commentform_subject" type="text" size="40" /></td></tr>';
-    html += '    <tr><td>Comment:</td><td><textarea id="commentform_message" rows="15" cols="50"></textarea></td></tr>';
+    html += '    <tr><td>' + $lang.get('comment_postform_field_subject') + '</td><td><input id="commentform_subject" type="text" size="40" /></td></tr>';
+    html += '    <tr><td>' + $lang.get('comment_postform_field_comment') + '</td><td><textarea id="commentform_message" rows="15" cols="50"></textarea></td></tr>';
     if ( !data.logged_in && data.guest_posting == '1' )
     {
-      html += '  <tr><td>Visual confirmation:<br /><small>Please enter the confirmation code seen in the image on the right into the box. If you cannot read the code, please click on the image to generate a new one. This helps to prevent automated bot posting.</small></td><td>';
+      html += '  <tr><td>' + $lang.get('comment_postform_field_captcha_title') + '<br /><small>' + $lang.get('comment_postform_field_captcha_blurb') + '</small></td><td>';
       html += '  <img alt="CAPTCHA image" src="'+makeUrlNS('Special', 'Captcha/' + data.captcha)+'" onclick="this.src=\''+makeUrlNS('Special', 'Captcha/' + data.captcha)+'/\'+Math.floor(Math.random()*10000000);" style="cursor: pointer;" /><br />';
-      html += '  Confirmation code: <input type="text" size="8" id="commentform_captcha" />';
+      html += '  ' + $lang.get('comment_postform_field_captcha_label') + ' <input type="text" size="8" id="commentform_captcha" />';
       html += '  <!-- This input is used to track the ID of the CAPTCHA image --> <input type="hidden" id="commentform_captcha_id" value="'+data.captcha+'" />';
       html += '  </td></tr>';
     }
-    html += '    <tr><td colspan="2" style="text-align: center;"><input type="button" onclick="submitComment();" value="Submit comment" /></td></tr>';
+    html += '    <tr><td colspan="2" style="text-align: center;"><input type="button" onclick="submitComment();" value="' + $lang.get('comment_postform_btn_submit') + '" /></td></tr>';
     html += '  </table>';
     html += '</div>';
-    
   }
     
   document.getElementById('ajaxEditContainer').innerHTML = html;
@@ -171,37 +176,55 @@
   tplvars.SIGNATURE = this_comment.signature;
   
   if ( this_comment.approved != '1' )
-    tplvars.SUBJECT += ' <span style="color: #D84308">(Unapproved)</span>';
+    tplvars.SUBJECT += ' <span style="color: #D84308">' + $lang.get('comment_msg_note_unapp') + '</span>';
   
   // Name
   tplvars.NAME = this_comment.name;
   if ( this_comment.user_id > 1 )
     tplvars.NAME = '<a href="' + makeUrlNS('User', this_comment.name) + '">' + this_comment.name + '</a>';
   
+  // Avatar
+  if ( this_comment.user_has_avatar == '1' )
+  {
+    tplvars.AVATAR_URL = scriptPath + '/' + data.avatar_directory + '/' + this_comment.user_id + '.' + this_comment.avatar_type;
+    tplvars.USERPAGE_LINK = makeUrlNS('User', this_comment.name);
+    tplvars.AVATAR_ALT = $lang.get('usercp_avatar_image_alt', { username: this_comment.name });
+  }
+  
   // User level
-  tplvars.USER_LEVEL = 'Guest';
-  if ( this_comment.user_level >= data.user_level.member ) tplvars.USER_LEVEL = 'Member';
-  if ( this_comment.user_level >= data.user_level.mod )    tplvars.USER_LEVEL = 'Moderator';
-  if ( this_comment.user_level >= data.user_level.admin )  tplvars.USER_LEVEL = 'Administrator';
-                              
+  tplvars.USER_LEVEL = $lang.get('user_type_guest');
+  if ( this_comment.user_level >= data.user_level.member ) tplvars.USER_LEVEL = $lang.get('user_type_member');
+  if ( this_comment.user_level >= data.user_level.mod ) tplvars.USER_LEVEL = $lang.get('user_type_mod');
+  if ( this_comment.user_level >= data.user_level.admin ) tplvars.USER_LEVEL = $lang.get('user_type_admin');
+  
   // Send PM link
-  tplvars.SEND_PM_LINK=(this_comment.user_id>1 && data.logged_in)?'<a onclick="window.open(this.href); return false;" href="'+ makeUrlNS('Special', 'PrivateMessages/Compose/To/' + ( this_comment.name.replace(/ /g, '_') )) +'">Send private message</a><br />':'';
+  tplvars.SEND_PM_LINK=(this_comment.user_id>1)?'<a onclick="window.open(this.href); return false;" href="'+ makeUrlNS('Special', 'PrivateMessages/Compose/To/' + ( this_comment.name.replace(/ /g, '_') )) +'">' + $lang.get('comment_btn_send_privmsg') + '</a><br />':'';
   
   // Add buddy link
-  tplvars.ADD_BUDDY_LINK=(this_comment.user_id>1 && data.logged_in && this_comment.is_buddy != 1)?'<a onclick="window.open(this.href); return false;" href="'+ makeUrlNS('Special', 'PrivateMessages/FriendList/Add/' + ( this_comment.name.replace(/ /g, '_') )) +'">Add to buddy list</a><br />':'';
+  tplvars.ADD_BUDDY_LINK=(this_comment.user_id>1)?'<a onclick="window.open(this.href); return false;" href="'+ makeUrlNS('Special', 'PrivateMessages/FriendList/Add/' + ( this_comment.name.replace(/ /g, '_') )) +'">' + $lang.get('comment_btn_add_buddy') + '</a><br />':'';
   
   // Edit link
-  tplvars.EDIT_LINK='<a href="#edit_'+i+'" onclick="editComment(\''+i+'\', this); return false;" id="cmteditlink_'+i+'">edit</a>';
+  tplvars.EDIT_LINK='<a href="#edit_'+i+'" onclick="editComment(\''+i+'\', this); return false;" id="cmteditlink_'+i+'">' + $lang.get('comment_btn_edit') + '</a>';
   
   // Delete link
-  tplvars.DELETE_LINK='<a href="#delete_'+i+'" onclick="deleteComment(\''+i+'\'); return false;">delete</a>';
+  tplvars.DELETE_LINK='<a href="#delete_'+i+'" onclick="deleteComment(\''+i+'\'); return false;">' + $lang.get('comment_btn_delete') + '</a>';
   
   // Moderation: (Un)approve link
-  var appr = ( this_comment.approved == 1 ) ? 'Unapprove' : 'Approve';
+  var appr = ( this_comment.approved == 1 ) ? $lang.get('comment_btn_mod_unapprove') : $lang.get('comment_btn_mod_approve');
   tplvars.MOD_APPROVE_LINK='<a href="#approve_'+i+'" id="comment_approve_'+i+'" onclick="approveComment(\''+i+'\'); return false;">'+appr+'</a>';
   
   // Moderation: Delete post link
-  tplvars.MOD_DELETE_LINK='<a href="#mod_del_'+i+'" onclick="deleteComment(\''+i+'\'); return false;">Delete</a>';
+  tplvars.MOD_DELETE_LINK='<a href="#mod_del_'+i+'" onclick="deleteComment(\''+i+'\'); return false;">' + $lang.get('comment_btn_mod_delete') + '</a>';
+  
+  // Moderation: IP address link
+  if ( this_comment.have_ip )
+  {
+    tplvars.MOD_IP_LINK = '<span id="comment_ip_' + i + '"><a href="#mod_ip_' + i + '" onclick="viewCommentIP(' + this_comment.comment_id + ', ' + i + '); return false;">' + $lang.get('comment_btn_mod_ip_logged') + '</a></span>';
+  }
+  else
+  {
+    tplvars.MOD_IP_LINK = $lang.get('comment_btn_mod_ip_missing');
+  }
   
   var tplbool = new Object();
   
@@ -210,16 +233,22 @@
   tplbool.auth_mod = data.auth_mod_comments;
   tplbool.is_friend = ( this_comment.is_buddy == 1 && this_comment.is_friend == 1 );
   tplbool.is_foe = ( this_comment.is_buddy == 1 && this_comment.is_friend == 0 );
+  tplbool.user_has_avatar = ( this_comment.user_has_avatar == '1' );
   
   if ( tplbool.is_friend )
-    tplvars.USER_LEVEL += '<br /><b>On your friend list</b>';
+    tplvars.USER_LEVEL += '<br /><b>' + $lang.get('comment_on_friend_list') + '</b>';
   else if ( tplbool.is_foe )
-    tplvars.USER_LEVEL += '<br /><b>On your foe list</b>';
+    tplvars.USER_LEVEL += '<br /><b>' + $lang.get('comment_on_foe_list') + '</b>';
   
   parser.assign_vars(tplvars);
   parser.assign_bool(tplbool);
   
-  return '<div id="comment_holder_' + i + '"><input type="hidden" value="'+this_comment.comment_id+'" /><input type="hidden" id="comment_source_'+i+'" />' + parser.run() + '</div>';
+  var ret = '<div id="comment_holder_' + i + '">';
+  ret += '<input type="hidden" value="'+this_comment.comment_id+'" />';
+  ret += '<input type="hidden" id="comment_source_'+i+'" />';
+  ret += parser.run();
+  ret += '</div>';
+  return ret;
 }
 
 function displayCommentForm()
@@ -255,7 +284,7 @@
   cmt.appendChild(ta);
   
   link.style.fontWeight = 'bold';
-  link.innerHTML = 'save';
+  link.innerHTML = $lang.get('comment_btn_save');
   link.onclick = function() { var id = this.id.substr(this.id.indexOf('_')+1); saveComment(id, this); return false; };
 }
 
@@ -273,7 +302,7 @@
     'subj' : subj
   };
   link.style.fontWeight = 'normal';
-  link.innerHTML = 'edit';
+  link.innerHTML = $lang.get('comment_btn_edit');
   link.onclick = function() { var id = this.id.substr(this.id.indexOf('_')+1); editComment(id, this); return false; };
   ajaxComments(req);
 }
@@ -282,7 +311,7 @@
 {
   if ( !shift )
   {
-    var c = confirm('Do you really want to delete this comment?');
+    var c = confirm($lang.get('comment_msg_delete_confirm'));
     if(!c)
       return false;
   }
@@ -340,36 +369,17 @@
   }
   if ( data.approved && data.approved != '1' )
   {
-    document.getElementById('subject_' + data.id).innerHTML += ' <span style="color: #D84308">(Unapproved)</span>';
+    document.getElementById('subject_' + data.id).innerHTML += ' <span style="color: #D84308">' + $lang.get('comment_msg_note_unapp') + '</span>';
   }
   if ( data.approved && ( typeof(data.approve_updated) == 'string' && data.approve_updated == 'yes' ) )
   {
-    var appr = ( data.approved == '1' ) ? 'Unapprove' : 'Approve';
+    var appr = ( data.approved == '1' ) ? $lang.get('comment_btn_mod_unapprove') : $lang.get('comment_btn_mod_approve');
     document.getElementById('comment_approve_'+data.id).innerHTML = appr;
     
-    // Update approval status
-    var p = document.getElementById('comment_status');
-    var count = p.firstChild.nodeValue.split(' ')[2];
-    
-    if ( p.firstChild.nextSibling )
-    {
-      var span = p.firstChild.nextSibling;
-      var is = ( data.approved == '1' ) ? -1 : 1;
-      var n_unapp = parseInt(span.firstChild.nodeValue.split(' ')[0]) + is;
-      n_unapp = n_unapp + '';
-    }
+    if ( data.approved == '1' )
+      comment_decrement_unapproval();
     else
-    {
-      var span = document.createElement('span');
-      p.innerHTML += ' ';
-      span.innerHTML = ' ';
-      span.style.color = '#D84308';
-      var n_unapp = '1';
-      p.appendChild(span);
-    }
-    span.innerHTML = n_unapp + ' of those are unapproved.';
-    if ( n_unapp == '0' )
-      p.removeChild(span);
+      comment_increment_unapproval();
   }
   if ( data.text )
   {
@@ -379,6 +389,13 @@
   {
     document.getElementById('comment_source_' + data.id).value = data.src;
   }
+  if ( data.ip_addr )
+  {
+    var span = $dynano('comment_ip_' + data.local_id).object;
+    if ( !span )
+      return false;
+    span.innerHTML = $lang.get('comment_msg_ip_address') + ' <a href="#rdns" onclick="ajaxReverseDNS(this); return false;">' + data.ip_addr + '</a>';
+  }
 }
 
 function approveComment(id)
@@ -396,41 +413,24 @@
 // Does the actual DOM object removal
 function annihiliateComment(id) // Did I spell that right?
 {
-  // Approved?
-  var p = document.getElementById('comment_status');
-  
+  var approved = true;
   if(document.getElementById('comment_approve_'+id))
   {
     var appr = document.getElementById('comment_approve_'+id).firstChild.nodeValue;
-    if ( p.firstChild.nextSibling && appr == 'Approve' )
+    if ( appr == $lang.get('comment_btn_mod_approve') )
     {
-      var span = p.firstChild.nextSibling;
-      var t = span.firstChild.nodeValue;
-      var n_unapp = ( parseInt(t.split(' ')[0]) ) - 1;
-      if ( n_unapp == 0 )
-        p.removeChild(span);
-      else
-        span.firstChild.nodeValue = n_unapp + t.substr(t.indexOf(' '));
+      approved = false;
     }
   }
   
   var div = document.getElementById('comment_holder_'+id);
   div.parentNode.removeChild(div);
-  var t = p.firstChild.nodeValue.split(' ');
-  t[2] = ( parseInt(t[2]) - 1 ) + '';
-  delete(t.toJSONString);
-  if ( t[2] == '1' )
+  
+  // update approval status
+  if ( document.getElementById('comment_count_unapp_inner') && !approved )
   {
-    t[1] = 'is';
-    t[3] = 'comment';
+    comment_decrement_unapproval();
   }
-  else
-  {
-    t[1] = 'are';
-    t[3] = 'comments';
-  }
-  t = implode(' ', t);
-  p.firstChild.nodeValue = t;
 }
 
 function materializeComment(data)
@@ -465,38 +465,50 @@
     tplvars.NAME = '<a href="' + makeUrlNS('User', data.name) + '">' + data.name + '</a>';
   
   if ( data.approved != '1' )
-    tplvars.SUBJECT += ' <span style="color: #D84308">(Unapproved)</span>';
+    tplvars.SUBJECT += ' <span style="color: #D84308">' + $lang.get('comment_msg_note_unapp') + '</span>';
   
   // User level
-  tplvars.USER_LEVEL = 'Guest';
-  if ( data.user_level >= data.user_level_list.member ) tplvars.USER_LEVEL = 'Member';
-  if ( data.user_level >= data.user_level_list.mod ) tplvars.USER_LEVEL = 'Moderator';
-  if ( data.user_level >= data.user_level_list.admin ) tplvars.USER_LEVEL = 'Administrator';
+  tplvars.USER_LEVEL = $lang.get('user_type_guest');
+  if ( data.user_level >= data.user_level_list.member ) tplvars.USER_LEVEL = $lang.get('user_type_member');
+  if ( data.user_level >= data.user_level_list.mod ) tplvars.USER_LEVEL = $lang.get('user_type_mod');
+  if ( data.user_level >= data.user_level_list.admin ) tplvars.USER_LEVEL = $lang.get('user_type_admin');
+  
+  // Avatar
+  if ( data.user_has_avatar == '1' )
+  {
+    tplvars.AVATAR_URL = scriptPath + '/' + data.avatar_directory + '/' + data.user_id + '.' + data.avatar_type;
+    tplvars.USERPAGE_LINK = makeUrlNS('User', data.name);
+    tplvars.AVATAR_ALT = $lang.get('usercp_avatar_image_alt', { username: data.name });
+  }
   
   // Send PM link
-  tplvars.SEND_PM_LINK=(data.user_id>1)?'<a onclick="window.open(this.href); return false;" href="'+ makeUrlNS('Special', 'PrivateMessages/Compose/To/' + ( data.name.replace(/ /g, '_') )) +'">Send private message</a><br />':'';
+  tplvars.SEND_PM_LINK=(data.user_id>1)?'<a onclick="window.open(this.href); return false;" href="'+ makeUrlNS('Special', 'PrivateMessages/Compose/To/' + ( data.name.replace(/ /g, '_') )) +'">' + $lang.get('comment_btn_send_privmsg') + '</a><br />':'';
   
   // Add buddy link
-  tplvars.ADD_BUDDY_LINK=(data.user_id>1)?'<a onclick="window.open(this.href); return false;" href="'+ makeUrlNS('Special', 'PrivateMessages/FriendList/Add/' + ( data.name.replace(/ /g, '_') )) +'">Add to buddy list</a><br />':'';
+  tplvars.ADD_BUDDY_LINK=(data.user_id>1)?'<a onclick="window.open(this.href); return false;" href="'+ makeUrlNS('Special', 'PrivateMessages/FriendList/Add/' + ( data.name.replace(/ /g, '_') )) +'">' + $lang.get('comment_btn_add_buddy') + '</a><br />':'';
   
   // Edit link
-  tplvars.EDIT_LINK='<a href="#edit_'+i+'" onclick="editComment(\''+i+'\', this); return false;" id="cmteditlink_'+i+'">edit</a>';
+  tplvars.EDIT_LINK='<a href="#edit_'+i+'" onclick="editComment(\''+i+'\', this); return false;" id="cmteditlink_'+i+'">' + $lang.get('comment_btn_edit') + '</a>';
   
   // Delete link
-  tplvars.DELETE_LINK='<a href="#delete_'+i+'" onclick="deleteComment(\''+i+'\'); return false;">delete</a>';
+  tplvars.DELETE_LINK='<a href="#delete_'+i+'" onclick="deleteComment(\''+i+'\'); return false;">' + $lang.get('comment_btn_delete') + '</a>';
   
   // Moderation: (Un)approve link
-  var appr = ( data.approved == 1 ) ? 'Unapprove' : 'Approve';
+  var appr = ( data.approved == 1 ) ? $lang.get('comment_btn_mod_unapprove') : $lang.get('comment_btn_mod_approve');
   tplvars.MOD_APPROVE_LINK='<a href="#approve_'+i+'" id="comment_approve_'+i+'" onclick="approveComment(\''+i+'\'); return false;">'+appr+'</a>';
   
   // Moderation: Delete post link
-  tplvars.MOD_DELETE_LINK='<a href="#mod_del_'+i+'" onclick="deleteComment(\''+i+'\'); return false;">Delete</a>';
+  tplvars.MOD_DELETE_LINK='<a href="#mod_del_'+i+'" onclick="deleteComment(\''+i+'\'); return false;">' + $lang.get('comment_btn_mod_delete') + '</a>';
+  
+  // Moderation: IP address link
+  tplvars.MOD_IP_LINK = '<span id="comment_ip_' + i + '"><a href="#mod_ip_' + i + '" onclick="viewCommentIP(' + data.comment_id + ', ' + i + '); return false;">' + $lang.get('comment_btn_mod_ip_logged') + '</a></span>';
   
   var tplbool = new Object();
   
   tplbool.signature = ( data.signature == '' ) ? false : true;
   tplbool.can_edit = ( data.auth_edit_comments && ( ( data.user_id == data.user_id && data.logged_in ) || data.auth_mod_comments ) );
   tplbool.auth_mod = data.auth_mod_comments;
+  tplbool.user_has_avatar = ( data.user_has_avatar == '1' );
   
   parser.assign_vars(tplvars);
   parser.assign_bool(tplbool);
@@ -519,50 +531,96 @@
   
   document.getElementById('comment_source_'+i).value = data.comment_source;
   
-  var p = document.getElementById('comment_status');
-  var t = p.firstChild.nodeValue.split(' ');
-  var n = ( isNaN(parseInt(t[2])) ) ? 0 : parseInt(t[2]);
-  t[2] = ( n + 1 ) + '';
-  delete(t.toJSONString);
-  if ( t[2] == '1' )
-  {
-    t[1] = 'is';
-    t[3] = 'comment';
+  var cnt = document.getElementById('comment_count_inner').innerHTML;
+  cnt = parseInt(cnt);
+  if ( isNaN(cnt) )
+    cnt = 0;
+  
+  var subst = {
+    num_comments: cnt,
+    page_type: ENANO_PAGE_TYPE
   }
-  else
-  {
-    t[1] = 'are';
-    t[3] = 'comments';
-  }
-  t = implode(' ', t);
-  p.firstChild.nodeValue = t;
+  
+  var count_msg = ( cnt == 0 ) ? $lang.get('comment_msg_count_zero', subst) : ( ( cnt == 1 ) ? $lang.get('comment_msg_count_one', subst) : $lang.get('comment_msg_count_plural', subst) );
+  
+  document.getElementById('comment_status').firstChild.innerHTML = count_msg;
   
   if(document.getElementById('comment_approve_'+i))
   {
-    var appr = document.getElementById('comment_approve_'+i).firstChild.nodeValue;
-    if ( p.firstChild.nextSibling && appr == 'Approve' )
+    var is_unappr = document.getElementById('comment_approve_'+i).firstChild.nodeValue;
+    is_unappr = ( is_unappr == $lang.get('comment_btn_mod_approve') );
+    if ( is_unappr )
     {
-      var span = p.firstChild.nextSibling;
-      var t = span.firstChild.nodeValue;
-      var n_unapp = ( parseInt(t.split(' ')[0]) ) - 1;
-      if ( n_unapp == 0 )
-        p.removeChild(span);
-      else
-        span.firstChild.nodeValue = n_unapp + t.substr(t.indexOf(' '));
-    }
-    else if ( appr == 'Approve' && !p.firstChild.nextSibling )
-    {
-      var span = document.createElement('span');
-      p.innerHTML += ' ';
-      span.innerHTML = '1 of those are unapproved.';
-      span.style.color = '#D84308';
-      var n_unapp = '1';
-      p.appendChild(span);
+      comment_increment_unapproval();
     }
   }
   
 }
 
+function comment_decrement_unapproval()
+{
+  if ( document.getElementById('comment_count_unapp_inner') )
+  {
+    var num_unapp = parseInt(document.getElementById('comment_count_unapp_inner').innerHTML);
+    if ( !isNaN(num_unapp) )
+    {
+      num_unapp = num_unapp - 1;
+      if ( num_unapp == 0 )
+      {
+        var p = document.getElementById('comment_status');
+        p.removeChild(p.childNodes[2]);
+        p.removeChild(p.childNodes[1]);
+      }
+      else
+      {
+        var count_msg = $lang.get('comment_msg_count_unapp_mod', { num_unapp: num_unapp });
+        document.getElementById('comment_count_unapp_inner').parentNode.innerHTML = count_msg;
+      }
+    }
+  }
+}
+
+function comment_increment_unapproval()
+{
+  if ( document.getElementById('comment_count_unapp_inner') )
+  {
+    var num_unapp = parseInt(document.getElementById('comment_count_unapp_inner').innerHTML);
+    if ( isNaN(num_unapp) )
+      num_unapp = 0;
+    num_unapp = num_unapp + 1;
+    var count_msg = $lang.get('comment_msg_count_unapp_mod', { num_unapp: num_unapp });
+    document.getElementById('comment_count_unapp_inner').parentNode.innerHTML = count_msg;
+  }
+  else
+  {
+    var count_msg = $lang.get('comment_msg_count_unapp_mod', { num_unapp: 1 });
+    var status = document.getElementById('comment_status');
+    if ( !status.childNodes[1] )
+      status.appendChild(document.createTextNode(' '));
+    var span = document.createElement('span');
+    span.id = 'comment_status_unapp';
+    span.style.color = '#D84308';
+    span.innerHTML = count_msg;
+    status.appendChild(span);
+  }
+}
+
+function viewCommentIP(id, local_id)
+{
+  // set "loading" indicator on IP button
+  var span = $dynano('comment_ip_' + local_id).object;
+  if ( !span )
+    return false;
+  span.innerHTML = '<img alt="..." src="' + ajax_load_icon + '" />';
+  
+  var parms = {
+    mode: 'view_ip',
+    id: id,
+    local_id: local_id
+  }
+  ajaxComments(parms);
+}
+
 function htmlspecialchars(text)
 {
   text = text.replace(/</g, '&lt;');
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/includes/clientside/static/diffiehellman.js	Fri Feb 22 12:51:53 2008 -0500
@@ -0,0 +1,44 @@
+/*
+ * The Diffie-Hellman key exchange protocol.
+ */
+
+// Our prime number as a base for operations.
+var dh_prime = '82818079787776757473727170696867666564636261605958575655545352515049484746454443424140393837363534333231302928272625242322212019181716151413121110987654321';
+
+// g, a primitive root used as an exponent
+// (2 and 5 are acceptable, but BigInt is faster with odd numbers)
+var dh_g = '5';
+
+/**
+ * Generates a Diffie-Hellman private key
+ * @return string(BigInt)
+ */
+
+function dh_gen_private()
+{
+  return EnanoMath.RandomInt(256);
+}
+
+/**
+ * Calculates the public key from the private key
+ * @param string(BigInt)
+ * @return string(BigInt)
+ */
+
+function dh_gen_public(b)
+{
+  return EnanoMath.PowMod(dh_g, b, dh_prime);
+}
+
+/**
+ * Calculates the shared secret.
+ * @param string(BigInt) Our private key
+ * @param string(BigInt) Remote party's public key
+ * @return string(BigInt)
+ */
+
+function dh_gen_shared_secret(b, A)
+{
+  return EnanoMath.PowMod(A, b, dh_prime);
+}
+
--- a/includes/clientside/static/dropdown.js	Fri Feb 22 12:46:51 2008 -0500
+++ b/includes/clientside/static/dropdown.js	Fri Feb 22 12:51:53 2008 -0500
@@ -57,7 +57,7 @@
 // Initializes a div with a jBox menu in it.
 function jBoxSetup(obj)
 {
-  $(obj).addClass('menu');
+  $dynano(obj).addClass('menu');
   removeTextNodes(obj);
   
   for ( var i = 0; i < obj.childNodes.length; i++ )
@@ -123,7 +123,7 @@
     if(typeof(others[i]) == 'object')
     {
       others[i].style.display = 'none';
-      $(others[i].previousSibling).rmClass('liteselected');
+      $dynano(others[i].previousSibling).rmClass('liteselected');
     }
   }
   var others = obj.parentNode.getElementsByTagName('div');
@@ -134,13 +134,13 @@
       if ( others[i].className == 'submenu' )
       {
         others[i].style.display = 'none';
-        $(others[i].previousSibling).rmClass('liteselected');
+        $dynano(others[i].previousSibling).rmClass('liteselected');
       }
     }
   }
   if(obj.nextSibling.tagName.toLowerCase() == 'ul' || ( obj.nextSibling.tagName.toLowerCase() == 'div' && obj.nextSibling.className == 'submenu' ))
   {
-    $(a).addClass('liteselected');
+    $dynano(a).addClass('liteselected');
     //obj.className = 'liteselected';
     var ul = obj.nextSibling;
     var dim = fetch_dimensions(obj);
@@ -198,7 +198,7 @@
   
   if (!isOverObj(a, false, event) && !isOverObj(ul, true, event))
   {
-    $(a).rmClass('liteselected');
+    $dynano(a).rmClass('liteselected');
     
     if ( jBox_slide_enable )
     {
@@ -390,7 +390,7 @@
         {
           if ( !isOverObj(uls[j], false, e) )
           {
-            $(uls[j].previousSibling).rmClass('liteselected');
+            $dynano(uls[j].previousSibling).rmClass('liteselected');
             //uls[j].style.display = 'none';
             slideIn(uls[j]);
           }
@@ -403,7 +403,7 @@
         {
           if ( !isOverObj(uls[j], false, e) )
           {
-            $(uls[j].previousSibling).rmClass('liteselected');
+            $dynano(uls[j].previousSibling).rmClass('liteselected');
             //uls[j].style.display = 'none';
             slideIn(uls[j]);
           }
@@ -530,3 +530,21 @@
     object.filter = "alpha(opacity=" + opacity + ")";
 }
 
+function getScrollOffset()
+{
+  var position;
+  if (self.pageYOffset)
+  {
+    position = self.pageYOffset;
+  }
+  else if (document.documentElement && document.documentElement.scrollTop)
+  {
+    position = document.documentElement.scrollTop;
+  }
+  else if (document.body)
+  {
+    position = document.body.scrollTop;
+  }
+  return position;
+}
+
--- a/includes/clientside/static/dynano.js	Fri Feb 22 12:46:51 2008 -0500
+++ b/includes/clientside/static/dynano.js	Fri Feb 22 12:51:53 2008 -0500
@@ -22,6 +22,7 @@
     this.switchToMCE = DN_switchToMCE;
     this.destroyMCE = DN_destroyMCE;
     this.getContent = DN_mceFetchContent;
+    this.setContent = DN_mceSetContent;
   }
 }
 function __DNObjGetHeight(o) {
@@ -86,7 +87,7 @@
   return left_offset;
 }
 
-function DN_switchToMCE()
+function DN_switchToMCE(performWikiTransform)
 {
   //if ( this.object.dn_is_mce )
   //  return this;
@@ -94,17 +95,38 @@
     this.object.id = 'textarea_' + Math.floor(Math.random() * 1000000);
   if ( !this.object.name )
     this.object.name = 'textarea_' + Math.floor(Math.random() * 1000000);
-  tinyMCE.addMCEControl(this.object, this.object.name, document);
+  // TinyMCE 2.x
+  // tinyMCE.addMCEControl(this.object, this.object.name, document);
+  // TinyMCE 3.x
+  if ( performWikiTransform )
+  {
+    this.object.value = DN_WikitextToXHTML(this.object.value);
+  }
+  tinyMCE.execCommand("mceAddControl", true, this.object.id);
   this.object.dnIsMCE = 'yes';
   return this;
 }
 
-function DN_destroyMCE()
+function DN_destroyMCE(performWikiTransform)
 {
   //if ( !this.object.dn_is_mce )
   //  return this;
-  if ( this.object.name )
-    tinyMCE.removeMCEControl(this.object.name);
+  if ( this.object.id )
+  {
+    // TinyMCE 2.x
+    // tinyMCE.removeMCEControl(this.object.name);
+    // TinyMCE 3.x
+    var ed = tinyMCE.getInstanceById(this.object.id);
+    if ( ed )
+    {
+      if ( !tinyMCE.execCommand("mceRemoveEditor", false, this.object.id) )
+        alert('could not destroy editor');
+      if ( performWikiTransform )
+      {
+        this.object.value = DN_XHTMLToWikitext(this.object.value);
+      }
+    }
+  }
   this.object.dnIsMCE = 'no';
   return this;
 }
@@ -114,8 +136,11 @@
   if ( this.object.name )
   {
     var text = this.object.value;
-    if ( tinyMCE.getInstanceById(this.object.name) )
-      text = tinyMCE.getContent(this.object.name);
+    if ( tinyMCE.get(this.object.id) )
+    {
+      var editor = tinyMCE.get(this.object.id);
+      text = editor.getContent();
+    }
     return text;
   }
   else
@@ -124,6 +149,44 @@
   }
 }
 
+function DN_mceSetContent(text)
+{
+  if ( this.object.name )
+  {
+    this.object.value = text;
+    if ( tinyMCE.get(this.object.id) )
+    {
+      var editor = tinyMCE.get(this.object.id);
+      editor.setContent(text);
+    }
+  }
+  else
+  {
+    this.object.value = text;
+  }
+}
+
+// A basic Wikitext to XHTML converter
+function DN_WikitextToXHTML(text)
+{
+  text = text.replace(/^===[\s]*(.+?)[\s]*===$/g, '<h3>$1</h3>');
+  text = text.replace(/'''(.+?)'''/g, '<b>$1</b>');
+  text = text.replace(/''(.+?)''/g, '<i>$1</i>');
+  text = text.replace(/\[(http|ftp|irc|mailto):([^ \]])+ ([^\]]+?)\]/g, '<a href="$1:$2">$4</a>');
+  return text;
+}
+
+// Inverse of the previous function
+function DN_XHTMLToWikitext(text)
+{
+  text = text.replace(/<h3>(.+?)<\/h3>/g, '=== $1 ===');
+  text = text.replace(/<(b|strong)>(.+?)<\/(b|strong)>/g, "'''$2'''");
+  text = text.replace(/<(i|em)>(.+?)<\/(i|em)>/g, "''$2''");
+  text = text.replace(/<a href="([^" ]+)">(.+?)<\/a>/g, '[$1 $2]');
+  text = text.replace(/<\/?p>/g, '');
+  return text;
+}
+
 DNobj.prototype.addClass = function(clsname) { addClass(this.object, clsname); return this; };
 DNobj.prototype.rmClass  = function(clsname) { rmClass( this.object, clsname); return this; };
 DNobj.prototype.hasClass = function(clsname) { return hasClass(this.object, clsname); };
--- a/includes/clientside/static/editor.js	Fri Feb 22 12:46:51 2008 -0500
+++ b/includes/clientside/static/editor.js	Fri Feb 22 12:51:53 2008 -0500
@@ -1,23 +1,44 @@
 // Javascript routines for the page editor
 
+if ( document.getElementById('mdgCss') )
+{
+  var css_url = document.getElementById('mdgCss').href;
+}
+else
+{
+  var css_url = scriptPath + '/includes/clientside/css/enano_shared.css';
+}
+
+var do_popups = ( is_Safari ) ? '' : ',inlinepopups';
+var _skin = ( typeof(tinymce_skin) == 'string' ) ? tinymce_skin : 'default';
+var editor_img_path = scriptPath + '/images/editor';
+
+// Idle time required for autosave, in seconds
+var AUTOSAVE_TIMEOUT = 15;
+var AutosaveTimeoutObj = null;
+
 var enano_tinymce_options = {
-  mode : "exact",
-  elements : '',
-  plugins : 'table',
+  mode : "none",
+  plugins : 'table,save,safari,pagebreak,style,layer,advhr,insertdatetime,searchreplace,print,contextmenu,paste,directionality,fullscreen,noneditable,visualchars,nonbreaking,xhtmlxtras' + do_popups,
+  theme : 'advanced',
+  skin : _skin,
   theme_advanced_resize_horizontal : false,
   theme_advanced_resizing : true,
   theme_advanced_toolbar_location : "top",
   theme_advanced_toolbar_align : "left",
-  theme_advanced_buttons1_add : "fontselect,fontsizeselect",
+  theme_advanced_buttons1 : "save,|,bold,italic,underline,strikethrough,|,justifyleft,justifycenter,justifyright,justifyfull,|,forecolor,backcolor,|,formatselect,|,fontselect,fontsizeselect",
   theme_advanced_buttons3_add_before : "tablecontrols,separator",
-  theme_advanced_statusbar_location : 'bottom'
+  theme_advanced_buttons3_add_after : "|,fullscreen",
+  theme_advanced_statusbar_location : 'bottom',
+  noneditable_noneditable_class : 'mce_readonly',
+  content_css : css_url
 };
 
 var initTinyMCE = function(e)
 {
   if ( typeof(tinyMCE) == 'object' )
   {
-    if ( !KILL_SWITCH )
+    if ( !KILL_SWITCH && !DISABLE_MCE )
     {
       tinyMCE.init(enano_tinymce_options);
     }
@@ -25,3 +46,891 @@
 }
 addOnloadHook(initTinyMCE);
 
+var editor_open = false;
+
+function ajaxEditor(revid)
+{
+  if ( KILL_SWITCH )
+    return true;
+  if ( editor_open )
+    return true;
+  var rev_id_uri = ( revid ) ? '&revid=' + revid : '';
+  selectButtonMinor('edit');
+  selectButtonMajor('article');
+  setAjaxLoading();
+  ajaxGet(stdAjaxPrefix + '&_mode=getsource' + rev_id_uri, function()
+    {
+      if ( ajax.readyState == 4 && ajax.status == 200 )
+      {
+        unsetAjaxLoading();
+        
+        var response = String(ajax.responseText + '');
+        if ( response.substr(0, 1) != '{' )
+        {
+          handle_invalid_json(response);
+          return false;
+        }
+        
+        response = parseJSON(response);
+        if ( response.mode == 'error' )
+        {
+          unselectAllButtonsMinor();
+          new messagebox(MB_OK | MB_ICONSTOP, $lang.get('editor_err_server'), response.error);
+          return false;
+        }
+        
+        if ( !response.auth_view_source )
+        {
+          unselectAllButtonsMinor();
+          new messagebox(MB_OK | MB_ICONSTOP, $lang.get('editor_err_access_denied_title'), $lang.get('editor_err_access_denied_body'));
+          return false;
+        }
+        
+        // do we need to enter a captcha before saving the page?
+        var captcha_hash = ( response.require_captcha ) ? response.captcha_id : false;
+        
+        ajaxBuildEditor((!response.auth_edit), response.time, response.allow_wysiwyg, captcha_hash, response.revid, response.undo_info, response);
+      }
+    });
+}
+
+function ajaxBuildEditor(readonly, timestamp, allow_wysiwyg, captcha_hash, revid, undo_info, response)
+{
+  // Set flags
+  // We don't want the fancy confirmation framework to trigger if the user is only viewing the page source
+  if ( !readonly )
+  {
+    editor_open = true;
+    disableUnload();
+  }
+  
+  // Destroy existing contents of page container
+  var edcon = document.getElementById('ajaxEditContainer');
+  for ( var i = edcon.childNodes.length - 1; i >= 0; i-- )
+  {
+    edcon.removeChild(edcon.childNodes[i]);
+  }
+  
+  var content = response.src;
+  
+  //
+  // BUILD EDITOR
+  //
+  
+  var heading = document.createElement('h3');
+  heading.style.cssFloat = 'left';
+  heading.style.styleFloat = 'left';
+  heading.style.marginTop = '0px';
+  heading.style.marginBottom = '0px';
+  heading.appendChild(document.createTextNode($lang.get('editor_msg_editor_heading')));
+  
+  // Plaintext/wikitext toggler
+  // Only build the editor if using TinyMCE is allowed. THIS IS WEAK
+  // AND CANNOT BE MADE ANY STRONGER.
+  
+  if ( allow_wysiwyg )
+  {
+    var toggler = document.createElement('p');
+    toggler.style.marginLeft = '0';
+    toggler.style.textAlign = 'right';
+    
+    var span_wiki = document.createElement('span');
+    var span_mce  = document.createElement('span');
+    span_wiki.id  = 'enano_edit_btn_pt';
+    span_mce.id   = 'enano_edit_btn_mce';
+    if ( readCookie('enano_editor_mode') == 'tinymce' )
+    {
+      // Current selection is TinyMCE - make span_wiki have the link and span_mce be plaintext
+      var a = document.createElement('a');
+      a.href = '#';
+      a.appendChild(document.createTextNode($lang.get('editor_btn_wikitext')));
+      span_wiki.appendChild(a);
+      toggler.appendChild(span_wiki);
+      toggler.appendChild(document.createTextNode(' | '));
+      span_mce.appendChild(document.createTextNode($lang.get('editor_btn_graphical')));
+      toggler.appendChild(span_mce);
+    }
+    else
+    {
+      // Current selection is wikitext - set span_wiki to plaintext and span_mce to link
+      span_wiki.appendChild(document.createTextNode($lang.get('editor_btn_wikitext')));
+      toggler.appendChild(span_wiki);
+      toggler.appendChild(document.createTextNode(' | '));
+      var a = document.createElement('a');
+      a.href = '#';
+      a.appendChild(document.createTextNode($lang.get('editor_btn_graphical')));
+      span_mce.appendChild(a);
+      toggler.appendChild(span_mce);
+    }
+  }
+  
+  // Form (to allow submits from MCE to trigger a real save)
+  var form = document.createElement('form');
+  form.action = 'javascript:void(0);';
+  form.onsubmit = function()
+  {
+    ajaxEditorSave();
+    return false;
+  }
+  
+  // Draft notice
+  if ( response.have_draft )
+  {
+    var dn = document.createElement('div');
+    dn.className = 'warning-box';
+    dn.id = 'ajax_edit_draft_notice';
+    dn.innerHTML = '<b>' + $lang.get('editor_msg_have_draft_title') + '</b><br />';
+    dn.innerHTML += $lang.get('editor_msg_have_draft_body', { author: response.draft_author, time: response.draft_time });
+  }
+  
+  // Old-revision notice
+  if ( revid > 0 )
+  {
+    var oldrev_box = document.createElement('div');
+    oldrev_box.className = 'usermessage';
+    oldrev_box.appendChild(document.createTextNode($lang.get('editor_msg_editing_old_revision')));
+  }
+  
+  // Preview holder
+  var preview_anchor = document.createElement('a');
+  preview_anchor.name = 'ajax_preview';
+  preview_anchor.id = 'ajax_preview';
+  var preview_container = document.createElement('div');
+  preview_container.id = 'enano_editor_preview';
+  preview_container.style.clear = 'left';
+  
+  // Textarea containing the content
+  var ta_wrapper = document.createElement('div');
+  ta_wrapper.style.margin = '10px 0';
+  // ta_wrapper.style.clear = 'both';
+  var textarea = document.createElement('textarea');
+  ta_wrapper.appendChild(textarea);
+  
+  textarea.id = 'ajaxEditArea';
+  textarea.rows = '20';
+  textarea.cols = '60';
+  textarea.style.width = '98.7%';
+  
+  // Revision metadata controls
+  var tblholder = document.createElement('div');
+  tblholder.className = 'tblholder';
+  var metatable = document.createElement('table');
+  metatable.setAttribute('border', '0');
+  metatable.setAttribute('cellspacing', '1');
+  metatable.setAttribute('cellpadding', '4');
+  
+  if ( readonly )
+  {
+    // Close Viewer button
+    var toolbar = '';
+    var head = new templateParser(response.toolbar_templates.toolbar_start);
+    var button = new templateParser(response.toolbar_templates.toolbar_button);
+    var tail = new templateParser(response.toolbar_templates.toolbar_end);
+    
+    button.assign_bool({
+        show_title: true
+      });
+    
+    // Button: close
+    button.assign_vars({
+        TITLE: $lang.get('editor_btn_closeviewer'),
+        IMAGE: editor_img_path + '/discard.gif',
+        FLAGS: 'href="#" onclick="ajaxReset(true); return false;"'
+      });
+    toolbar += button.run();
+  }
+  else
+  {
+    // First row: edit summary
+    var tr1 = document.createElement('tr');
+    var td1_1 = document.createElement('td');
+    var td1_2 = document.createElement('td');
+    td1_1.className = 'row2';
+    td1_2.className = 'row1';
+    td1_2.style.width = '70%';
+    td1_1.appendChild(document.createTextNode($lang.get('editor_lbl_edit_summary')));
+    td1_1.appendChild(document.createElement('br'));
+    var small = document.createElement('small');
+    small.appendChild(document.createTextNode($lang.get('editor_lbl_edit_summary_explain')));
+    td1_1.appendChild(small);
+    
+    var field_es = document.createElement('input');
+    field_es.id = 'enano_editor_field_summary';
+    field_es.type = 'text';
+    field_es.size = '40';
+    field_es.style.width = '96%';
+    
+    if ( revid > 0 )
+    {
+      undo_info.last_rev_id = revid;
+      field_es.value = $lang.get('editor_reversion_edit_summary', undo_info);
+    }
+    
+    td1_2.appendChild(field_es);
+    
+    tr1.appendChild(td1_1);
+    tr1.appendChild(td1_2);
+    
+    // Second row: minor edit
+    var tr2 = document.createElement('tr');
+    var td2_1 = document.createElement('td');
+    var td2_2 = document.createElement('td');
+    td2_1.className = 'row2';
+    td2_2.className = 'row1';
+    td2_1.appendChild(document.createTextNode($lang.get('editor_lbl_minor_edit')));
+    td2_1.appendChild(document.createElement('br'));
+    var small = document.createElement('small');
+    small.appendChild(document.createTextNode($lang.get('editor_lbl_minor_edit_explain')));
+    td2_1.appendChild(small);
+    
+    var label = document.createElement('label');
+    var field_mi = document.createElement('input');
+    field_mi.id = 'enano_editor_field_minor';
+    field_mi.type = 'checkbox';
+    label.appendChild(field_mi);
+    label.appendChild(document.createTextNode(' '));
+    label.appendChild(document.createTextNode($lang.get('editor_lbl_minor_edit_field')));
+    td2_2.appendChild(label);
+    
+    tr2.appendChild(td2_1);
+    tr2.appendChild(td2_2);
+    
+    if ( captcha_hash )
+    {
+      // generate captcha field (effectively third row)
+      var tr4 = document.createElement('tr');
+      var td4_1 = document.createElement('td');
+      var td4_2 = document.createElement('td');
+      td4_1.className = 'row2';
+      td4_2.className = 'row1';
+      
+      td4_1.appendChild(document.createTextNode($lang.get('editor_lbl_field_captcha')));
+      td4_1.appendChild(document.createElement('br'));
+      var small2 = document.createElement('small');
+      small2.appendChild(document.createTextNode($lang.get('editor_msg_captcha_pleaseenter')));
+      small2.appendChild(document.createElement('br'));
+      small2.appendChild(document.createElement('br'));
+      small2.appendChild(document.createTextNode($lang.get('editor_msg_captcha_blind')));
+      td4_1.appendChild(small2);
+      
+      var img = document.createElement('img');
+      img.src = makeUrlNS('Special', 'Captcha/' + captcha_hash);
+      img._captchaHash = captcha_hash;
+      img.id = 'enano_editor_captcha_img';
+      img.onclick = function()
+      {
+        this.src = makeUrlNS('Special', 'Captcha/' + this._captchaHash + '/' + Math.floor(Math.random() * 100000));
+      }
+      img.style.cursor = 'pointer';
+      td4_2.appendChild(img);
+      td4_2.appendChild(document.createElement('br'));
+      td4_2.appendChild(document.createTextNode($lang.get('editor_lbl_field_captcha_code') + ' '));
+      var input = document.createElement('input');
+      input.type = 'text';
+      input.id = 'enano_editor_field_captcha';
+      input._captchaHash = captcha_hash;
+      input.size = '9';
+      td4_2.appendChild(input);
+      
+      tr4.appendChild(td4_1);
+      tr4.appendChild(td4_2);
+    }
+    
+    // Third row: controls
+    
+    var toolbar = '';
+    var head = new templateParser(response.toolbar_templates.toolbar_start);
+    var button = new templateParser(response.toolbar_templates.toolbar_button);
+    var label = new templateParser(response.toolbar_templates.toolbar_label);
+    var tail = new templateParser(response.toolbar_templates.toolbar_end);
+    
+    button.assign_bool({
+        show_title: true
+      });
+    
+    toolbar += head.run();
+    
+    // Button: Save
+    button.assign_vars({
+        TITLE: $lang.get('editor_btn_save'),
+        IMAGE: editor_img_path + '/save.gif',
+        FLAGS: 'href="#" onclick="ajaxEditorSave(); return false;"'
+      });
+    toolbar += button.run();
+    
+    // Button: preview
+    button.assign_vars({
+        TITLE: $lang.get('editor_btn_preview'),
+        IMAGE: editor_img_path + '/preview.gif',
+        FLAGS: 'href="#" onclick="ajaxEditorGenPreview(); return false;"'
+      });
+    toolbar += button.run();
+    
+    // Button: revert
+    button.assign_vars({
+        TITLE: $lang.get('editor_btn_revert'),
+          IMAGE: editor_img_path + '/revert.gif',
+        FLAGS: 'href="#" onclick="ajaxEditorRevertToLatest(); return false;"'
+      });
+    toolbar += button.run();
+    
+    // Button: diff
+    button.assign_vars({
+        TITLE: $lang.get('editor_btn_diff'),
+        IMAGE: editor_img_path + '/diff.gif',
+        FLAGS: 'href="#" onclick="ajaxEditorShowDiffs(); return false;"'
+      });
+    toolbar += button.run();
+    
+    // Button: cancel
+    button.assign_vars({
+        TITLE: $lang.get('editor_btn_cancel'),
+        IMAGE: editor_img_path + '/discard.gif',
+        FLAGS: 'href="#" onclick="ajaxEditorCancel(); return false;"'
+      });
+    toolbar += button.run();
+    
+    // Separator
+    label.assign_vars({
+        TITLE: ' '
+      });
+    toolbar += label.run();
+    
+    // Button: Save draft
+    button.assign_vars({
+        TITLE: $lang.get('editor_btn_savedraft'),
+        IMAGE: editor_img_path + '/savedraft.gif',
+        FLAGS: 'href="#" onclick="ajaxPerformAutosave(); return false;" id="ajax_edit_savedraft_btn"'
+      });
+    toolbar += button.run();
+    
+    toolbar += tail.run();
+    
+    metatable.appendChild(tr1);
+    metatable.appendChild(tr2);
+    if ( captcha_hash )
+    {
+      metatable.appendChild(tr4);
+    }
+    // metatable.appendChild(tr3);
+  }
+  tblholder.appendChild(metatable);
+  
+  // Edit disclaimer/notice
+  if ( editNotice ) // This is set globally in {JS_DYNAMIC_VARS}.
+  {
+    var en_div = document.createElement('div');
+    en_div.innerHTML = editNotice;
+    en_div.className = 'usermessage';
+    en_div.style.margin = '10px 0 0 0';
+  }
+  
+  // Put it all together...
+  form.appendChild(heading);
+  if ( allow_wysiwyg )
+    form.appendChild(toggler);
+  
+  if ( dn )
+    form.appendChild(dn);
+  
+  if ( oldrev_box )
+    form.appendChild(oldrev_box);
+  
+  form.appendChild(preview_anchor);
+  form.appendChild(preview_container);
+  form.appendChild(ta_wrapper);
+  form.appendChild(tblholder);
+  form.innerHTML += '<div style="margin: 10px 0 0 0;">' + toolbar + '</div>';
+  edcon.appendChild(form);
+  
+  if ( editNotice && !readonly )
+  {
+    edcon.appendChild(en_div);
+  }
+  
+  // more textarea attribs/init
+  var textarea = document.getElementById('ajaxEditArea');
+  textarea.as_last_save = 0;
+  textarea.content_orig = content;
+  textarea.used_draft = false;
+  textarea.onkeyup = function()
+  {
+    if ( this.needReset )
+    {
+      var img = $dynano('ajax_edit_savedraft_btn').object.getElementsByTagName('img')[0];
+      var lbl = $dynano('ajax_edit_savedraft_btn').object.getElementsByTagName('span')[0];
+      img.src = editor_img_path + '/savedraft.gif';
+      lbl.innerHTML = $lang.get('editor_btn_savedraft');
+    }
+    if ( AutosaveTimeoutObj )
+      clearTimeout(AutosaveTimeoutObj);
+    AutosaveTimeoutObj = setTimeout('ajaxAutosaveDraft();', ( AUTOSAVE_TIMEOUT * 1000 ));
+  }
+  
+  if ( readonly )
+  {
+    textarea.className = 'mce_readonly';
+    textarea.setAttribute('readonly', 'readonly');
+  }
+  
+  // If the editor preference is tinymce, switch the editor to TinyMCE now
+  if ( readCookie('enano_editor_mode') == 'tinymce' && allow_wysiwyg )
+  {
+    $dynano('ajaxEditArea').switchToMCE();
+  }
+  $dynano('ajaxEditArea').object.focus();
+  $dynano('ajaxEditArea').object._edTimestamp = timestamp;
+  $dynano('ajaxEditArea').setContent(content);
+  
+  if ( allow_wysiwyg )
+  {
+    if ( readCookie('enano_editor_mode') == 'tinymce' )
+    {
+      var a = document.getElementById('enano_edit_btn_pt').getElementsByTagName('a')[0];
+      a.onclick = function() {
+        ajaxSetEditorPlain();
+        return false;
+      };
+    }
+    else
+    {
+      var a = document.getElementById('enano_edit_btn_mce').getElementsByTagName('a')[0];
+      a.onclick = function() {
+        ajaxSetEditorMCE();
+        return false;
+      };
+    }
+  }
+  
+  // Autosave every 5 minutes           (m  *  s  *  ms)
+  setInterval('ajaxPerformAutosave();', ( 5 * 60 * 1000 ));
+}
+
+function ajaxEditorSave(is_draft)
+{
+  if ( !is_draft )
+    ajaxSetEditorLoading();
+  var ta_content = $dynano('ajaxEditArea').getContent();
+  
+  if ( !is_draft && ( ta_content == '' || ta_content == '<p></p>' || ta_content == '<p>&nbsp;</p>' ) )
+  {
+    new messagebox(MB_OK|MB_ICONSTOP, $lang.get('editor_err_no_text_title'), $lang.get('editor_err_no_text_body'));
+    ajaxUnSetEditorLoading();
+    return false;
+  }
+  
+  if ( is_draft )
+  {
+    // ajaxSetEditorLoading();
+    var img = $dynano('ajax_edit_savedraft_btn').object.getElementsByTagName('img')[0];
+    var lbl = $dynano('ajax_edit_savedraft_btn').object.getElementsByTagName('span')[0];
+    img.src = scriptPath + '/images/loading.gif';
+    var d = new Date();
+    var m = String(d.getMinutes());
+    if ( m.length < 2 )
+      m = '0' + m;
+    var time = d.getHours() + ':' + m;
+    lbl.innerHTML = $lang.get('editor_msg_draft_saving');
+  }
+  
+  var edit_summ = $dynano('enano_editor_field_summary').object.value;
+  if ( !edit_summ )
+    edit_summ = '';
+  var is_minor = ( $dynano('enano_editor_field_minor').object.checked ) ? 1 : 0;
+  var timestamp = $dynano('ajaxEditArea').object._edTimestamp;
+  var used_draft = $dynano('ajaxEditArea').object.used_draft;
+  
+  var json_packet = {
+    src: ta_content,
+    summary: edit_summ,
+    minor_edit: is_minor,
+    time: timestamp,
+    draft: ( is_draft == true ),
+    used_draft: used_draft
+  };
+  
+  // Do we need to add captcha info?
+  if ( document.getElementById('enano_editor_field_captcha') )
+  {
+    var captcha_field = document.getElementById('enano_editor_field_captcha');
+    if ( captcha_field.value == '' )
+    {
+      new messagebox(MB_OK|MB_ICONSTOP, $lang.get('editor_err_need_captcha_title'), $lang.get('editor_err_need_captcha_body'));
+      ajaxUnSetEditorLoading();
+      return false;
+    }
+    json_packet.captcha_code = captcha_field.value;
+    json_packet.captcha_id = captcha_field._captchaHash;
+  }
+  
+  json_packet = ajaxEscape(toJSONString(json_packet));
+  ajaxPost(stdAjaxPrefix + '&_mode=savepage_json', 'r=' + json_packet, function()
+    {
+      if ( ajax.readyState == 4 && ajax.status == 200 )
+      {
+        var response = String(ajax.responseText + '');
+        if ( response.substr(0, 1) != '{' )
+        {
+          handle_invalid_json(response);
+          return false;
+        }
+        
+        response = parseJSON(response);
+        // This will only be used if there was a lower-level error.
+        if ( response.mode == 'error' )
+        {
+          new messagebox(MB_OK | MB_ICONSTOP, $lang.get('editor_err_server'), response.error);
+          return false;
+        }
+        // This will be used if the PageProcessor generated errors (usually security/permissions related)
+        if ( response.mode == 'errors' )
+        {
+          // This will be true if the user entered a captcha code incorrectly, thus
+          // invalidating the code and requiring a new image to be generated.
+          if ( response.new_captcha )
+          {
+            // Generate the new captcha field
+            var img = document.getElementById('enano_editor_captcha_img');
+            var input = document.getElementById('enano_editor_field_captcha');
+            if ( img && input )
+            {
+              img._captchaHash = response.new_captcha;
+              input._captchaHash = response.new_captcha;
+              img.src = makeUrlNS('Special', 'Captcha/' + response.new_captcha);
+              input.value = '';
+            }
+          }
+          var errors = '<ul><li>' + implode('</li><li>', response.errors) + '</li></ul>';
+          new messagebox(MB_OK | MB_ICONSTOP, $lang.get('editor_err_save_title'), $lang.get('editor_err_save_body') + errors);
+          return false;
+        }
+        // If someone else got to the page first, warn the user
+        if ( response.mode == 'obsolete' )
+        {
+          // Update the local timestamp to allow override
+          $dynano('ajaxEditArea').object._edTimestamp = response.time;
+          new messagebox(MB_OK | MB_ICONEXCLAMATION, $lang.get('editor_err_obsolete_title'), $lang.get('editor_err_obsolete_body', { author: response.author, timestamp: response.date_string, page_url: makeUrl(title, false, true) }));
+          return false;
+        }
+        if ( response.mode == 'success' )
+        {
+          if ( response.is_draft )
+          {
+            document.getElementById('ajaxEditArea').used_draft = true;
+            document.getElementById('ajaxEditArea').needReset = true;
+            var img = $dynano('ajax_edit_savedraft_btn').object.getElementsByTagName('img')[0];
+            var lbl = $dynano('ajax_edit_savedraft_btn').object.getElementsByTagName('span')[0];
+            img.src = scriptPath + '/images/mini-info.png';
+            var d = new Date();
+            var m = String(d.getMinutes());
+            if ( m.length < 2 )
+              m = '0' + m;
+            var time = d.getHours() + ':' + m;
+            lbl.innerHTML = $lang.get('editor_msg_draft_saved', { time: time });
+          }
+          else
+          {
+            // The save was successful; reset flags and make another request for the new page content
+            ajaxUnSetEditorLoading();
+            setAjaxLoading();
+            editor_open = false;
+            enableUnload();
+            changeOpac(0, 'ajaxEditContainer');
+            ajaxGet(stdAjaxPrefix + '&_mode=getpage&noheaders', function()
+              {
+                if ( ajax.readyState == 4 && ajax.status == 200 )
+                {
+                  unsetAjaxLoading();
+                  selectButtonMajor('article');
+                  unselectAllButtonsMinor();
+                  
+                  document.getElementById('ajaxEditContainer').innerHTML = '<div class="usermessage">' + $lang.get('editor_msg_saved') + '</div>' + ajax.responseText;
+                  opacity('ajaxEditContainer', 0, 100, 1000);
+                }
+              });
+          }
+        }
+      }
+    }, true);
+}
+
+function ajaxEditorGenPreview()
+{
+  ajaxSetEditorLoading();
+  var ta_content = $dynano('ajaxEditArea').getContent();
+  ta_content = ajaxEscape(ta_content);
+  if ( $dynano('enano_editor_preview').object.innerHTML != '' )
+  {
+    opacity('enano_editor_preview', 100, 0, 500);
+  }
+  ajaxPost(stdAjaxPrefix + '&_mode=preview', 'text=' + ta_content, function()
+    {
+      if ( ajax.readyState == 4 && ajax.status == 200 )
+      {
+        ajaxUnSetEditorLoading();
+        changeOpac(0, 'enano_editor_preview');
+        $dynano('enano_editor_preview').object.innerHTML = ajax.responseText;
+        window.location.hash = '#ajax_preview';
+        opacity('enano_editor_preview', 0, 100, 500);
+      }
+    }, true);
+}
+
+function ajaxEditorRevertToLatest()
+{
+  var mb = new messagebox(MB_YESNO | MB_ICONQUESTION, $lang.get('editor_msg_revert_confirm_title'), $lang.get('editor_msg_revert_confirm_body'));
+  mb.onclick['Yes'] = function()
+  {
+    setTimeout('ajaxEditorRevertToLatestReal();', 750);
+  }
+}
+
+function ajaxEditorRevertToLatestReal()
+{
+  ajaxSetEditorLoading();
+  ajaxGet(stdAjaxPrefix + '&_mode=getsource', function()
+    {
+      if ( ajax.readyState == 4 && ajax.status == 200 )
+      {
+        ajaxUnSetEditorLoading();
+        
+        var response = String(ajax.responseText + '');
+        if ( response.substr(0, 1) != '{' )
+        {
+          handle_invalid_json(response);
+          return false;
+        }
+        
+        response = parseJSON(response);
+        if ( response.mode == 'error' )
+        {
+          unselectAllButtonsMinor();
+          new messagebox(MB_OK | MB_ICONSTOP, $lang.get('editor_err_server'), response.error);
+          return false;
+        }
+        
+        if ( !response.auth_view_source )
+        {
+          unselectAllButtonsMinor();
+          new messagebox(MB_OK | MB_ICONSTOP, $lang.get('editor_err_access_denied_title'), $lang.get('editor_err_access_denied_body'));
+          return false;
+        }
+        
+        $dynano('ajaxEditArea').setContent(response.src);
+      }
+    }, true);
+}
+
+function ajaxEditorShowDiffs()
+{
+  ajaxSetEditorLoading();
+  var ta_content = $dynano('ajaxEditArea').getContent();
+  ta_content = ajaxEscape(ta_content);
+  if ( $dynano('enano_editor_preview').object.innerHTML != '' )
+  {
+    opacity('enano_editor_preview', 100, 0, 500);
+  }
+  ajaxPost(stdAjaxPrefix + '&_mode=diff_cur', 'text=' + ta_content, function()
+    {
+      if ( ajax.readyState == 4 && ajax.status == 200 )
+      {
+        ajaxUnSetEditorLoading();
+        changeOpac(0, 'enano_editor_preview');
+        $dynano('enano_editor_preview').object.innerHTML = ajax.responseText;
+        window.location.hash = '#ajax_preview';
+        opacity('enano_editor_preview', 0, 100, 500);
+      }
+    }, true);
+}
+
+function ajaxEditorCancel()
+{
+  var mb = new messagebox(MB_YESNO | MB_ICONQUESTION, $lang.get('editor_msg_cancel_confirm_title'), $lang.get('editor_msg_cancel_confirm_body'));
+  mb.onclick['Yes'] = function()
+  {
+    setAjaxLoading();
+    editor_open = false;
+    enableUnload();
+    setTimeout('ajaxReset();', 750);
+  }
+}
+
+function ajaxSetEditorMCE()
+{
+  if ( editor_loading )
+    return false;
+  
+  // Clear out existing buttons
+  var span_wiki = $dynano('enano_edit_btn_pt').object;
+  var span_mce  = $dynano('enano_edit_btn_mce').object;
+  span_wiki.removeChild(span_wiki.firstChild);
+  span_mce.removeChild(span_mce.firstChild);
+  
+  // Rebuild control
+  var a = document.createElement('a');
+  a.href = '#';
+  a.onclick = function() {
+    ajaxSetEditorPlain();
+    return false;
+  };
+  a.appendChild(document.createTextNode($lang.get('editor_btn_wikitext')));
+  span_wiki.appendChild(a);
+  span_mce.appendChild(document.createTextNode($lang.get('editor_btn_graphical')));
+  
+  // Swap editor
+  $dynano('ajaxEditArea').switchToMCE();
+  
+  // Remember the setting
+  createCookie('enano_editor_mode', 'tinymce', 365);
+}
+
+function ajaxSetEditorPlain()
+{
+  if ( editor_loading )
+    return false;
+  
+  // Clear out existing buttons
+  var span_wiki = $dynano('enano_edit_btn_pt').object;
+  var span_mce  = $dynano('enano_edit_btn_mce').object;
+  span_wiki.removeChild(span_wiki.firstChild);
+  span_mce.removeChild(span_mce.firstChild);
+  
+  // Rebuild control
+  span_wiki.appendChild(document.createTextNode($lang.get('editor_btn_wikitext')));
+  var a = document.createElement('a');
+  a.href = '#';
+  a.onclick = function() {
+    ajaxSetEditorMCE();
+    return false;
+  };
+  a.appendChild(document.createTextNode($lang.get('editor_btn_graphical')));
+  span_mce.appendChild(a);
+  
+  // Swap editor
+  $dynano('ajaxEditArea').destroyMCE();
+  
+  // Remember the setting
+  createCookie('enano_editor_mode', 'text', 365);
+}
+
+var editor_loading = false;
+
+function ajaxSetEditorLoading()
+{
+  var ed = tinyMCE.get('ajaxEditArea');
+  editor_loading = true;
+  if ( ed )
+  {
+    ed.setProgressState(1);
+  }
+  else
+  {
+    ed = document.getElementById('ajaxEditArea');
+    var blackout = document.createElement('div');
+    blackout.style.position = 'absolute';
+    blackout.style.top = $dynano('ajaxEditArea').Top() + 'px';
+    blackout.style.left = $dynano('ajaxEditArea').Left() + 'px';
+    blackout.style.width = $dynano('ajaxEditArea').Width() + 'px';
+    blackout.style.height = $dynano('ajaxEditArea').Height() + 'px';
+    blackout.style.backgroundColor = '#FFFFFF';
+    domObjChangeOpac(60, blackout);
+    blackout.style.backgroundImage = 'url(' + scriptPath + '/includes/clientside/tinymce/themes/advanced/skins/default/img/progress.gif)';
+    blackout.style.backgroundPosition = 'center center';
+    blackout.style.backgroundRepeat = 'no-repeat';
+    blackout.id = 'enano_editor_blackout';
+    blackout.style.zIndex = getHighestZ() + 2;
+    
+    var body = document.getElementsByTagName('body')[0];
+    body.appendChild(blackout);
+  }
+}
+
+function ajaxUnSetEditorLoading()
+{
+  editor_loading = false;
+  var ed = tinyMCE.get('ajaxEditArea');
+  if ( ed )
+  {
+    ed.setProgressState(0);
+  }
+  else
+  {
+    var blackout = document.getElementById('enano_editor_blackout');
+    var body = document.getElementsByTagName('body')[0];
+    body.removeChild(blackout);
+  }
+}
+
+function ajaxAutosaveDraft()
+{
+  var aed = document.getElementById('ajaxEditArea');
+  if ( !aed )
+    return false;
+  var last_save = aed.as_last_save;
+  var now = unix_time();
+  if ( ( last_save + 120 ) < now && aed.value != aed.content_orig )
+  {
+    ajaxPerformAutosave();
+  }
+}
+
+function ajaxPerformAutosave()
+{
+  var aed = document.getElementById('ajaxEditArea');
+  if ( !aed )
+    return false;
+  var now = unix_time();
+  aed.as_last_save = now;
+  
+  var ta_content = $dynano('ajaxEditArea').getContent();
+  
+  if ( ta_content == '' || ta_content == '<p></p>' || ta_content == '<p>&nbsp;</p>' )
+  {
+    return false;
+  }
+  
+  ajaxEditorSave(true);
+}
+
+function ajaxEditorUseDraft()
+{
+  var aed = document.getElementById('ajaxEditArea');
+  if ( !aed )
+    return false;
+  ajaxSetEditorLoading();
+  ajaxGet(stdAjaxPrefix + '&_mode=getsource&get_draft=1', function()
+    {
+      if ( ajax.readyState == 4 && ajax.status == 200 )
+      {
+        ajaxUnSetEditorLoading();
+        
+        var response = String(ajax.responseText + '');
+        if ( response.substr(0, 1) != '{' )
+        {
+          handle_invalid_json(response);
+          return false;
+        }
+        
+        response = parseJSON(response);
+        if ( response.mode == 'error' )
+        {
+          unselectAllButtonsMinor();
+          new messagebox(MB_OK | MB_ICONSTOP, $lang.get('editor_err_server'), response.error);
+          return false;
+        }
+        
+        $dynano('ajaxEditArea').setContent(response.src);
+        $dynano('ajaxEditArea').object.used_draft = true;
+        
+        var es = document.getElementById('enano_editor_field_summary');
+        if ( es.value == '' )
+        {
+          es.value = response.edit_summary;
+        }
+        
+        var dn = $dynano('ajax_edit_draft_notice').object;
+        dn.parentNode.removeChild(dn);
+      }
+    }, true);
+}
+
--- a/includes/clientside/static/enano-lib-basic.js	Fri Feb 22 12:46:51 2008 -0500
+++ b/includes/clientside/static/enano-lib-basic.js	Fri Feb 22 12:51:53 2008 -0500
@@ -10,8 +10,9 @@
  * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for details.
  *
  * For more information about Enano, please visit http://enanocms.org/.
- * All of the code in these script files may be used freely so long as the above license block is displayed and your
- * modified code is distributed under the GPL. See the page Special:About_Enano on this website for more information.
+ * Unless otherwise noted, all of the code in these script files may be used freely so long as the above license block
+ * is displayed and your modified code is distributed in compliance with the GPL. See the special page "About Enano" on
+ * this website for more information.
  */
 
 if(typeof title != 'string')
@@ -63,6 +64,11 @@
 // dummy tinyMCE object
 var tinyMCE = new Object();
 
+if ( typeof(DISABLE_MCE) == undefined )
+{
+  var DISABLE_MCE = false;
+}
+
 // Obsolete JSON kill switch
 function disableJSONExts() { };
 
@@ -251,17 +257,23 @@
 }
 
 var head = document.getElementsByTagName('head')[0];
-if ( !KILL_SWITCH )
+if ( !KILL_SWITCH && !DISABLE_MCE )
 {
   var script = document.createElement('script');
   script.type="text/javascript";
-  script.src=scriptPath+"/includes/clientside/tinymce/tiny_mce_src.js";
+  script.src=scriptPath+"/includes/clientside/tinymce/tiny_mce.js";
   head.appendChild(script);
 }
 
+// Do not remove the following comments, they are used by jsres.php.
+/*!START_INCLUDER*/
+
 // Start loading files
+// The string from the [ to the ] needs to be valid JSON, it's parsed by jsres.php.
 var thefiles = [
+  'dynano.js',
   'misc.js',
+  'login.js',
   'admin-menu.js',
   'ajax.js',
   'autocomplete.js',
@@ -273,18 +285,22 @@
   'grippy.js',
   'json.js',
   'md5.js',
+  'libbigint.js',
+  'enanomath.js',
+  'diffiehellman.js',
+  'sha256.js',
   'sliders.js',
   'toolbar.js',
-  'windows.js',
   'rijndael.js',
+  'l10n.js',
   'template-compiler.js',
   'acl.js',
   'comments.js',
   'editor.js',
-  'dynano.js',
   'flyin.js',
   'paginate.js',
   'pwstrength.js',
+  'theme-manager.js',
   'SpryEffects.js',
   'loader.js'
 ];
@@ -309,6 +325,9 @@
   head.appendChild(script);
 }
 
+// Do not remove the following comment, it is used by jsres.php.
+/*!END_INCLUDER*/
+
 addOnloadHook(function() {
   if ( $_REQUEST['do'] )
   {
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/includes/clientside/static/enanomath.js	Fri Feb 22 12:51:53 2008 -0500
@@ -0,0 +1,29 @@
+/*
+ * EnanoMath, an abstraction layer for big-integer (arbitrary precision)
+ * mathematics.
+ */
+
+var EnanoMathLayers = {};
+
+// EnanoMath layer: Leemon (frontend to BigInt library by Leemon Baird)
+
+EnanoMathLayers.Leemon = {
+  Base: 10,
+  PowMod: function(a, b, c)
+  {
+    a = str2bigInt(a, this.Base);
+    b = str2bigInt(b, this.Base);
+    c = str2bigInt(c, this.Base);
+    var result = powMod(a, b, c);
+    result = bigInt2str(result, this.Base);
+    return result;
+  },
+  RandomInt: function(bits)
+  {
+    var result = randBigInt(bits);
+    return bigInt2str(result, this.Base);
+  }
+}
+
+var EnanoMath = EnanoMathLayers.Leemon;
+
--- a/includes/clientside/static/faders.js	Fri Feb 22 12:46:51 2008 -0500
+++ b/includes/clientside/static/faders.js	Fri Feb 22 12:51:53 2008 -0500
@@ -186,7 +186,8 @@
   {
     btn = document.createElement('input');
     btn.type = 'button';
-    btn.value = 'OK';
+    btn.value = $lang.get('etc_ok');
+    btn._GenericName = 'OK';
     btn.onclick = this.clickHandler;
     btn.style.margin = '0 3px';
     buttondiv.appendChild(btn);
@@ -196,14 +197,16 @@
   {
     btn = document.createElement('input');
     btn.type = 'button';
-    btn.value = 'OK';
+    btn.value = $lang.get('etc_ok');
+    btn._GenericName = 'OK';
     btn.onclick = this.clickHandler;
     btn.style.margin = '0 3px';
     buttondiv.appendChild(btn);
     
     btn = document.createElement('input');
     btn.type = 'button';
-    btn.value = 'Cancel';
+    btn.value = $lang.get('etc_cancel');
+    btn._GenericName = 'Cancel';
     btn.onclick = this.clickHandler;
     btn.style.margin = '0 3px';
     buttondiv.appendChild(btn);
@@ -213,14 +216,16 @@
   {
     btn = document.createElement('input');
     btn.type = 'button';
-    btn.value = 'Yes';
+    btn.value = $lang.get('etc_yes');
+    btn._GenericName = 'Yes';
     btn.onclick = this.clickHandler;
     btn.style.margin = '0 3px';
     buttondiv.appendChild(btn);
     
     btn = document.createElement('input');
     btn.type = 'button';
-    btn.value = 'No';
+    btn.value = $lang.get('etc_no');
+    btn._GenericName = 'No';
     btn.onclick = this.clickHandler;
     btn.style.margin = '0 3px';
     buttondiv.appendChild(btn);
@@ -230,21 +235,24 @@
   {
     btn = document.createElement('input');
     btn.type = 'button';
-    btn.value = 'Yes';
+    btn.value = $lang.get('etc_yes');
+    btn._GenericName = 'Yes';
     btn.onclick = this.clickHandler;
     btn.style.margin = '0 3px';
     buttondiv.appendChild(btn);
     
     btn = document.createElement('input');
     btn.type = 'button';
-    btn.value = 'No';
+    btn.value = $lang.get('etc_no');
+    btn._GenericName = 'No';
     btn.onclick = this.clickHandler;
     btn.style.margin = '0 3px';
     buttondiv.appendChild(btn);
     
     btn = document.createElement('input');
     btn.type = 'button';
-    btn.value = 'Cancel';
+    btn.value = $lang.get('etc_cancel');
+    btn._GenericName = 'Cancel';
     btn.onclick = this.clickHandler;
     btn.style.margin = '0 3px';
     buttondiv.appendChild(btn);
@@ -305,7 +313,7 @@
 
 function messagebox_click(obj, mb)
 {
-  val = obj.value;
+  val = ( typeof ( obj._GenericName ) == 'string' ) ? obj._GenericName : obj.value;
   if(typeof mb.onbeforeclick[val] == 'function')
   {
     var o = mb.onbeforeclick[val];
@@ -360,6 +368,8 @@
   j = 0;
   for(var i in d)
   {
+    if ( !d[i] )
+      continue;
     if ( !d[i].tagName )
       continue;
     if(d[i].className=='info-box' || d[i].className=='error-box' || d[i].className=='warning-box' || d[i].className=='question-box')
@@ -451,7 +461,7 @@
 
 function mb_logout()
 {
-  var mb = new messagebox(MB_YESNO|MB_ICONQUESTION, 'Are you sure you want to log out?', 'If you log out, you will no longer be able to access your user preferences, your private messages, or certain areas of this site until you log in again.');
+  var mb = new messagebox(MB_YESNO|MB_ICONQUESTION, $lang.get('user_logout_confirm_title'), $lang.get('user_logout_confirm_body'));
   mb.onclick['Yes'] = function()
     {
       window.location = makeUrlNS('Special', 'Logout/' + title);
--- a/includes/clientside/static/flyin.js	Fri Feb 22 12:46:51 2008 -0500
+++ b/includes/clientside/static/flyin.js	Fri Feb 22 12:51:53 2008 -0500
@@ -83,8 +83,8 @@
   // setup element
   element.style.position = 'absolute';
   
-  dim = [ $(element).Height(), $(element).Width() ];
-  off = [ $(element).Top(), $(element).Left() ];
+  dim = [ $dynano(element).Height(), $dynano(element).Width() ];
+  off = [ $dynano(element).Top(), $dynano(element).Left() ];
   
   if ( height_taken_care_of )
   {
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/includes/clientside/static/l10n.js	Fri Feb 22 12:51:53 2008 -0500
@@ -0,0 +1,69 @@
+/*
+ * Enano client-side localization library
+ */
+
+var Language = function(lang_id)
+{
+  if ( typeof(enano_lang) != 'object' )
+    return false;
+  if ( typeof(enano_lang[lang_id]) != 'object' )
+    return false;
+  this.strings = enano_lang[lang_id];
+  this.lang_id = lang_id;
+  
+  this.get = function(string_id, subst)
+  {
+    if ( window.console )
+    {
+      try {
+        window.console.log('$lang(' + this.lang_id + '): requested string: ' + string_id);
+      }
+      catch(e)
+      {}
+    }
+    var catname = string_id.substr(0, string_id.indexOf('_'));
+    var string_name = string_id.substr(string_id.indexOf('_') + 1);
+    if ( typeof(this.strings[catname]) != 'object' )
+      return string_id;
+    if ( typeof(this.strings[catname][string_name]) != 'string' )
+      return string_id;
+    return this.perform_subst(this.strings[catname][string_name], subst);
+  }
+  
+  this.perform_subst = function(str, subst)
+  {
+    var this_regex = /%this\.([a-z0-9_]+)%/;
+    var match;
+    while ( str.match(this_regex) )
+    {
+      match = str.match(this_regex);
+      str = str.replace(match[0], this.get(match[1]));
+    }
+    // hackish workaround for %config.*%
+    str = str.replace(/%config\.([a-z0-9_]+)%/g, '%$1%');
+    if ( typeof(subst) == 'object' )
+    {
+      for ( var i in subst )
+      {
+        if ( !i.match(/^([a-z0-9_]+)$/) )
+          continue;
+        var regex = new RegExp('%' + i + '%', 'g');
+        str = str.replace(regex, subst[i]);
+      }
+    }
+    return str;
+  }
+  
+}
+
+var $lang;
+
+var language_onload = function()
+{
+  $lang = new Language(ENANO_LANG_ID);
+  // for debugging :-)
+  // alert( $lang.get('user_err_invalid_credentials_lockout_captcha', { lockout_fails: '3', lockout_threshold: '5', lockout_duration: '15' }) );
+}
+
+addOnloadHook(language_onload);
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/includes/clientside/static/libbigint.js	Fri Feb 22 12:51:53 2008 -0500
@@ -0,0 +1,1400 @@
+////////////////////////////////////////////////////////////////////////////////////////
+// Big Integer Library v. 5.1
+// Created 2000, last modified 2007
+// Leemon Baird
+// www.leemon.com
+//
+// Version history:
+//
+// v 5.1  8 Oct 2007 
+//   - renamed inverseModInt_ to inverseModInt since it doesn't change its parameters
+//   - added functions GCD and randBigInt, which call GCD_ and randBigInt_
+//   - fixed a bug found by Rob Visser (see comment with his name below)
+//   - improved comments
+//
+// This file is public domain.   You can use it for any purpose without restriction.
+// I do not guarantee that it is correct, so use it at your own risk.  If you use 
+// it for something interesting, I'd appreciate hearing about it.  If you find 
+// any bugs or make any improvements, I'd appreciate hearing about those too.
+// It would also be nice if my name and address were left in the comments.
+// But none of that is required.
+//
+// This code defines a bigInt library for arbitrary-precision integers.
+// A bigInt is an array of integers storing the value in chunks of bpe bits, 
+// little endian (buff[0] is the least significant word).
+// Negative bigInts are stored two's complement.
+// Some functions assume their parameters have at least one leading zero element.
+// Functions with an underscore at the end of the name have unpredictable behavior in case of overflow, 
+// so the caller must make sure the arrays must be big enough to hold the answer.
+// For each function where a parameter is modified, that same 
+// variable must not be used as another argument too.
+// So, you cannot square x by doing multMod_(x,x,n).  
+// You must use squareMod_(x,n) instead, or do y=dup(x); multMod_(x,y,n).
+//
+// These functions are designed to avoid frequent dynamic memory allocation in the inner loop.
+// For most functions, if it needs a BigInt as a local variable it will actually use
+// a global, and will only allocate to it only when it's not the right size.  This ensures
+// that when a function is called repeatedly with same-sized parameters, it only allocates
+// memory on the first call.
+//
+// Note that for cryptographic purposes, the calls to Math.random() must 
+// be replaced with calls to a better pseudorandom number generator.
+//
+// In the following, "bigInt" means a bigInt with at least one leading zero element,
+// and "integer" means a nonnegative integer less than radix.  In some cases, integer 
+// can be negative.  Negative bigInts are 2s complement.
+// 
+// The following functions do not modify their inputs.
+// Those returning a bigInt, string, or Array will dynamically allocate memory for that value.
+// Those returning a boolean will return the integer 0 (false) or 1 (true).
+// Those returning boolean or int will not allocate memory except possibly on the first time they're called with a given parameter size.
+// 
+// bigInt  add(x,y)               //return (x+y) for bigInts x and y.  
+// bigInt  addInt(x,n)            //return (x+n) where x is a bigInt and n is an integer.
+// string  bigInt2str(x,base)     //return a string form of bigInt x in a given base, with 2 <= base <= 95
+// int     bitSize(x)             //return how many bits long the bigInt x is, not counting leading zeros
+// bigInt  dup(x)                 //return a copy of bigInt x
+// boolean equals(x,y)            //is the bigInt x equal to the bigint y?
+// boolean equalsInt(x,y)         //is bigint x equal to integer y?
+// bigInt  expand(x,n)            //return a copy of x with at least n elements, adding leading zeros if needed
+// Array   findPrimes(n)          //return array of all primes less than integer n
+// bigInt  GCD(x,y)               //return greatest common divisor of bigInts x and y (each with same number of elements).
+// boolean greater(x,y)           //is x>y?  (x and y are nonnegative bigInts)
+// boolean greaterShift(x,y,shift)//is (x <<(shift*bpe)) > y?
+// bigInt  int2bigInt(t,n,m)      //return a bigInt equal to integer t, with at least n bits and m array elements
+// bigInt  inverseMod(x,n)        //return (x**(-1) mod n) for bigInts x and n.  If no inverse exists, it returns null
+// int     inverseModInt(x,n)     //return x**(-1) mod n, for integers x and n.  Return 0 if there is no inverse
+// boolean isZero(x)              //is the bigInt x equal to zero?
+// boolean millerRabin(x,b)       //does one round of Miller-Rabin base integer b say that bigInt x is possibly prime (as opposed to definitely composite)?
+// bigInt  mod(x,n)               //return a new bigInt equal to (x mod n) for bigInts x and n.
+// int     modInt(x,n)            //return x mod n for bigInt x and integer n.
+// bigInt  mult(x,y)              //return x*y for bigInts x and y. This is faster when y<x.
+// bigInt  multMod(x,y,n)         //return (x*y mod n) for bigInts x,y,n.  For greater speed, let y<x.
+// boolean negative(x)            //is bigInt x negative?
+// bigInt  powMod(x,y,n)          //return (x**y mod n) where x,y,n are bigInts and ** is exponentiation.  0**0=1. Faster for odd n.
+// bigInt  randBigInt(n,s)        //return an n-bit random BigInt (n>=1).  If s=1, then the most significant of those n bits is set to 1.
+// bigInt  randTruePrime(k)       //return a new, random, k-bit, true prime bigInt using Maurer's algorithm.
+// bigInt  str2bigInt(s,b,n,m)    //return a bigInt for number represented in string s in base b with at least n bits and m array elements
+// bigInt  sub(x,y)               //return (x-y) for bigInts x and y.  Negative answers will be 2s complement
+// bigInt  bigint_trim(x,k)              //return a copy of x with exactly k leading zero elements
+//
+//
+// The following functions each have a non-underscored version, which most users should call instead.
+// These functions each write to a single parameter, and the caller is responsible for ensuring the array 
+// passed in is large enough to hold the result. 
+//
+// void    addInt_(x,n)          //do x=x+n where x is a bigInt and n is an integer
+// void    add_(x,y)             //do x=x+y for bigInts x and y
+// void    copy_(x,y)            //do x=y on bigInts x and y
+// void    copyInt_(x,n)         //do x=n on bigInt x and integer n
+// void    GCD_(x,y)             //set x to the greatest common divisor of bigInts x and y, (y is destroyed).  (This never overflows its array).
+// boolean inverseMod_(x,n)      //do x=x**(-1) mod n, for bigInts x and n. Returns 1 (0) if inverse does (doesn't) exist
+// void    mod_(x,n)             //do x=x mod n for bigInts x and n. (This never overflows its array).
+// void    mult_(x,y)            //do x=x*y for bigInts x and y.
+// void    multMod_(x,y,n)       //do x=x*y  mod n for bigInts x,y,n.
+// void    powMod_(x,y,n)        //do x=x**y mod n, where x,y,n are bigInts (n is odd) and ** is exponentiation.  0**0=1.
+// void    randBigInt_(b,n,s)    //do b = an n-bit random BigInt. if s=1, then nth bit (most significant bit) is set to 1. n>=1.
+// void    randTruePrime_(ans,k) //do ans = a random k-bit true random prime (not just probable prime) with 1 in the msb.
+// void    sub_(x,y)             //do x=x-y for bigInts x and y. Negative answers will be 2s complement.
+//
+// The following functions do NOT have a non-underscored version. 
+// They each write a bigInt result to one or more parameters.  The caller is responsible for
+// ensuring the arrays passed in are large enough to hold the results. 
+//
+// void addShift_(x,y,ys)       //do x=x+(y<<(ys*bpe))
+// void carry_(x)               //do carries and borrows so each element of the bigInt x fits in bpe bits.
+// void divide_(x,y,q,r)        //divide x by y giving quotient q and remainder r
+// int  divInt_(x,n)            //do x=floor(x/n) for bigInt x and integer n, and return the remainder. (This never overflows its array).
+// int  eGCD_(x,y,d,a,b)        //sets a,b,d to positive bigInts such that d = GCD_(x,y) = a*x-b*y
+// void halve_(x)               //do x=floor(|x|/2)*sgn(x) for bigInt x in 2's complement.  (This never overflows its array).
+// void leftShift_(x,n)         //left shift bigInt x by n bits.  n<bpe.
+// void linComb_(x,y,a,b)       //do x=a*x+b*y for bigInts x and y and integers a and b
+// void linCombShift_(x,y,b,ys) //do x=x+b*(y<<(ys*bpe)) for bigInts x and y, and integers b and ys
+// void mont_(x,y,n,np)         //Montgomery multiplication (see comments where the function is defined)
+// void multInt_(x,n)           //do x=x*n where x is a bigInt and n is an integer.
+// void rightShift_(x,n)        //right shift bigInt x by n bits.  0 <= n < bpe. (This never overflows its array).
+// void squareMod_(x,n)         //do x=x*x  mod n for bigInts x,n
+// void subShift_(x,y,ys)       //do x=x-(y<<(ys*bpe)). Negative answers will be 2s complement.
+//
+// The following functions are based on algorithms from the _Handbook of Applied Cryptography_
+//    powMod_()           = algorithm 14.94, Montgomery exponentiation
+//    eGCD_,inverseMod_() = algorithm 14.61, Binary extended GCD_
+//    GCD_()              = algorothm 14.57, Lehmer's algorithm
+//    mont_()             = algorithm 14.36, Montgomery multiplication
+//    divide_()           = algorithm 14.20  Multiple-precision division
+//    squareMod_()        = algorithm 14.16  Multiple-precision squaring
+//    randTruePrime_()    = algorithm  4.62, Maurer's algorithm
+//    millerRabin()       = algorithm  4.24, Miller-Rabin algorithm
+//
+// Profiling shows:
+//     randTruePrime_() spends:
+//         10% of its time in calls to powMod_()
+//         85% of its time in calls to millerRabin()
+//     millerRabin() spends:
+//         99% of its time in calls to powMod_()   (always with a base of 2)
+//     powMod_() spends:
+//         94% of its time in calls to mont_()  (almost always with x==y)
+//
+// This suggests there are several ways to speed up this library slightly:
+//     - convert powMod_ to use a Montgomery form of k-ary window (or maybe a Montgomery form of sliding window)
+//         -- this should especially focus on being fast when raising 2 to a power mod n
+//     - convert randTruePrime_() to use a minimum r of 1/3 instead of 1/2 with the appropriate change to the test
+//     - tune the parameters in randTruePrime_(), including c, m, and recLimit
+//     - speed up the single loop in mont_() that takes 95% of the runtime, perhaps by reducing checking
+//       within the loop when all the parameters are the same length.
+//
+// There are several ideas that look like they wouldn't help much at all:
+//     - replacing trial division in randTruePrime_() with a sieve (that speeds up something taking almost no time anyway)
+//     - increase bpe from 15 to 30 (that would help if we had a 32*32->64 multiplier, but not with JavaScript's 32*32->32)
+//     - speeding up mont_(x,y,n,np) when x==y by doing a non-modular, non-Montgomery square
+//       followed by a Montgomery reduction.  The intermediate answer will be twice as long as x, so that
+//       method would be slower.  This is unfortunate because the code currently spends almost all of its time
+//       doing mont_(x,x,...), both for randTruePrime_() and powMod_().  A faster method for Montgomery squaring
+//       would have a large impact on the speed of randTruePrime_() and powMod_().  HAC has a couple of poorly-worded
+//       sentences that seem to imply it's faster to do a non-modular square followed by a single
+//       Montgomery reduction, but that's obviously wrong.
+////////////////////////////////////////////////////////////////////////////////////////
+
+//globals
+bpe=0;         //bits stored per array element
+mask=0;        //AND this with an array element to chop it down to bpe bits
+radix=mask+1;  //equals 2^bpe.  A single 1 bit to the left of the last bit of mask.
+
+//the digits for converting to different bases
+digitsStr='0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz_=!@#$%^&*()[]{}|;:,.<>/?`~ \\\'\"+-';
+
+//initialize the global variables
+for (bpe=0; (1<<(bpe+1)) > (1<<bpe); bpe++);  //bpe=number of bits in the mantissa on this platform
+bpe>>=1;                   //bpe=number of bits in one element of the array representing the bigInt
+mask=(1<<bpe)-1;           //AND the mask with an integer to get its bpe least significant bits
+radix=mask+1;              //2^bpe.  a single 1 bit to the left of the first bit of mask
+one=int2bigInt(1,1,1);     //constant used in powMod_()
+
+//the following global variables are scratchpad memory to 
+//reduce dynamic memory allocation in the inner loop
+t=new Array(0);
+ss=t;       //used in mult_()
+s0=t;       //used in multMod_(), squareMod_() 
+s1=t;       //used in powMod_(), multMod_(), squareMod_() 
+s2=t;       //used in powMod_(), multMod_()
+s3=t;       //used in powMod_()
+s4=t; s5=t; //used in mod_()
+s6=t;       //used in bigInt2str()
+s7=t;       //used in powMod_()
+T=t;        //used in GCD_()
+sa=t;       //used in mont_()
+mr_x1=t; mr_r=t; mr_a=t;                                      //used in millerRabin()
+eg_v=t; eg_u=t; eg_A=t; eg_B=t; eg_C=t; eg_D=t;               //used in eGCD_(), inverseMod_()
+md_q1=t; md_q2=t; md_q3=t; md_r=t; md_r1=t; md_r2=t; md_tt=t; //used in mod_()
+
+primes=t; pows=t; s_i=t; s_i2=t; s_R=t; s_rm=t; s_q=t; s_n1=t; 
+  s_a=t; s_r2=t; s_n=t; s_b=t; s_d=t; s_x1=t; s_x2=t, s_aa=t; //used in randTruePrime_()
+
+////////////////////////////////////////////////////////////////////////////////////////
+
+//return array of all primes less than integer n
+function findPrimes(n) {
+  var i,s,p,ans;
+  s=new Array(n);
+  for (i=0;i<n;i++)
+    s[i]=0;
+  s[0]=2;
+  p=0;    //first p elements of s are primes, the rest are a sieve
+  for(;s[p]<n;) {                  //s[p] is the pth prime
+    for(i=s[p]*s[p]; i<n; i+=s[p]) //mark multiples of s[p]
+      s[i]=1;
+    p++;
+    s[p]=s[p-1]+1;
+    for(; s[p]<n && s[s[p]]; s[p]++); //find next prime (where s[p]==0)
+  }
+  ans=new Array(p);
+  for(i=0;i<p;i++)
+    ans[i]=s[i];
+  return ans;
+}
+
+//does a single round of Miller-Rabin base b consider x to be a possible prime?
+//x is a bigInt, and b is an integer
+function millerRabin(x,b) {
+  var i,j,k,s;
+
+  if (mr_x1.length!=x.length) {
+    mr_x1=dup(x);
+    mr_r=dup(x);
+    mr_a=dup(x);
+  }
+
+  copyInt_(mr_a,b);
+  copy_(mr_r,x);
+  copy_(mr_x1,x);
+
+  addInt_(mr_r,-1);
+  addInt_(mr_x1,-1);
+
+  //s=the highest power of two that divides mr_r
+  k=0;
+  for (i=0;i<mr_r.length;i++)
+    for (j=1;j<mask;j<<=1)
+      if (x[i] & j) {
+        s=(k<mr_r.length+bpe ? k : 0); 
+         i=mr_r.length;
+         j=mask;
+      } else
+        k++;
+
+  if (s)                
+    rightShift_(mr_r,s);
+
+  powMod_(mr_a,mr_r,x);
+
+  if (!equalsInt(mr_a,1) && !equals(mr_a,mr_x1)) {
+    j=1;
+    while (j<=s-1 && !equals(mr_a,mr_x1)) {
+      squareMod_(mr_a,x);
+      if (equalsInt(mr_a,1)) {
+        return 0;
+      }
+      j++;
+    }
+    if (!equals(mr_a,mr_x1)) {
+      return 0;
+    }
+  }
+  return 1;  
+}
+
+//returns how many bits long the bigInt is, not counting leading zeros.
+function bitSize(x) {
+  var j,z,w;
+  for (j=x.length-1; (x[j]==0) && (j>0); j--);
+  for (z=0,w=x[j]; w; (w>>=1),z++);
+  z+=bpe*j;
+  return z;
+}
+
+//return a copy of x with at least n elements, adding leading zeros if needed
+function expand(x,n) {
+  var ans=int2bigInt(0,(x.length>n ? x.length : n)*bpe,0);
+  copy_(ans,x);
+  return ans;
+}
+
+//return a k-bit true random prime using Maurer's algorithm.
+function randTruePrime(k) {
+  var ans=int2bigInt(0,k,0);
+  randTruePrime_(ans,k);
+  return bigint_trim(ans,1);
+}
+
+//return a new bigInt equal to (x mod n) for bigInts x and n.
+function mod(x,n) {
+  var ans=dup(x);
+  mod_(ans,n);
+  return bigint_trim(ans,1);
+}
+
+//return (x+n) where x is a bigInt and n is an integer.
+function addInt(x,n) {
+  var ans=expand(x,x.length+1);
+  addInt_(ans,n);
+  return bigint_trim(ans,1);
+}
+
+//return x*y for bigInts x and y. This is faster when y<x.
+function mult(x,y) {
+  var ans=expand(x,x.length+y.length);
+  mult_(ans,y);
+  return bigint_trim(ans,1);
+}
+
+//return (x**y mod n) where x,y,n are bigInts and ** is exponentiation.  0**0=1. Faster for odd n.
+function powMod(x,y,n) {
+  var ans=expand(x,n.length);  
+  powMod_(ans,bigint_trim(y,2),bigint_trim(n,2),0);  //this should work without the trim, but doesn't
+  return bigint_trim(ans,1);
+}
+
+//return (x-y) for bigInts x and y.  Negative answers will be 2s complement
+function sub(x,y) {
+  var ans=expand(x,(x.length>y.length ? x.length+1 : y.length+1)); 
+  sub_(ans,y);
+  return bigint_trim(ans,1);
+}
+
+//return (x+y) for bigInts x and y.  
+function add(x,y) {
+  var ans=expand(x,(x.length>y.length ? x.length+1 : y.length+1)); 
+  add_(ans,y);
+  return bigint_trim(ans,1);
+}
+
+//return (x**(-1) mod n) for bigInts x and n.  If no inverse exists, it returns null
+function inverseMod(x,n) {
+  var ans=expand(x,n.length); 
+  var s;
+  s=inverseMod_(ans,n);
+  return s ? bigint_trim(ans,1) : null;
+}
+
+//return (x*y mod n) for bigInts x,y,n.  For greater speed, let y<x.
+function multMod(x,y,n) {
+  var ans=expand(x,n.length);
+  multMod_(ans,y,n);
+  return bigint_trim(ans,1);
+}
+
+//generate a k-bit true random prime using Maurer's algorithm,
+//and put it into ans.  The bigInt ans must be large enough to hold it.
+function randTruePrime_(ans,k) {
+  var c,m,pm,dd,j,r,B,divisible,z,zz,recSize;
+
+  if (primes.length==0)
+    primes=findPrimes(30000);  //check for divisibility by primes <=30000
+
+  if (pows.length==0) {
+    pows=new Array(512);
+    for (j=0;j<512;j++) {
+      pows[j]=Math.pow(2,j/511.-1.);
+    }
+  }
+
+  //c and m should be tuned for a particular machine and value of k, to maximize speed
+  c=0.1;  //c=0.1 in HAC
+  m=20;   //generate this k-bit number by first recursively generating a number that has between k/2 and k-m bits
+  recLimit=20; //stop recursion when k <=recLimit.  Must have recLimit >= 2
+
+  if (s_i2.length!=ans.length) {
+    s_i2=dup(ans);
+    s_R =dup(ans);
+    s_n1=dup(ans);
+    s_r2=dup(ans);
+    s_d =dup(ans);
+    s_x1=dup(ans);
+    s_x2=dup(ans);
+    s_b =dup(ans);
+    s_n =dup(ans);
+    s_i =dup(ans);
+    s_rm=dup(ans);
+    s_q =dup(ans);
+    s_a =dup(ans);
+    s_aa=dup(ans);
+  }
+
+  if (k <= recLimit) {  //generate small random primes by trial division up to its square root
+    pm=(1<<((k+2)>>1))-1; //pm is binary number with all ones, just over sqrt(2^k)
+    copyInt_(ans,0);
+    for (dd=1;dd;) {
+      dd=0;
+      ans[0]= 1 | (1<<(k-1)) | Math.floor(Math.random()*(1<<k));  //random, k-bit, odd integer, with msb 1
+      for (j=1;(j<primes.length) && ((primes[j]&pm)==primes[j]);j++) { //trial division by all primes 3...sqrt(2^k)
+        if (0==(ans[0]%primes[j])) {
+          dd=1;
+          break;
+        }
+      }
+    }
+    carry_(ans);
+    return;
+  }
+
+  B=c*k*k;    //try small primes up to B (or all the primes[] array if the largest is less than B).
+  if (k>2*m)  //generate this k-bit number by first recursively generating a number that has between k/2 and k-m bits
+    for (r=1; k-k*r<=m; )
+      r=pows[Math.floor(Math.random()*512)];   //r=Math.pow(2,Math.random()-1);
+  else
+    r=.5;
+
+  //simulation suggests the more complex algorithm using r=.333 is only slightly faster.
+
+  recSize=Math.floor(r*k)+1;
+
+  randTruePrime_(s_q,recSize);
+  copyInt_(s_i2,0);
+  s_i2[Math.floor((k-2)/bpe)] |= (1<<((k-2)%bpe));   //s_i2=2^(k-2)
+  divide_(s_i2,s_q,s_i,s_rm);                        //s_i=floor((2^(k-1))/(2q))
+
+  z=bitSize(s_i);
+
+  for (;;) {
+    for (;;) {  //generate z-bit numbers until one falls in the range [0,s_i-1]
+      randBigInt_(s_R,z,0);
+      if (greater(s_i,s_R))
+        break;
+    }                //now s_R is in the range [0,s_i-1]
+    addInt_(s_R,1);  //now s_R is in the range [1,s_i]
+    add_(s_R,s_i);   //now s_R is in the range [s_i+1,2*s_i]
+
+    copy_(s_n,s_q);
+    mult_(s_n,s_R); 
+    multInt_(s_n,2);
+    addInt_(s_n,1);    //s_n=2*s_R*s_q+1
+    
+    copy_(s_r2,s_R);
+    multInt_(s_r2,2);  //s_r2=2*s_R
+
+    //check s_n for divisibility by small primes up to B
+    for (divisible=0,j=0; (j<primes.length) && (primes[j]<B); j++)
+      if (modInt(s_n,primes[j])==0) {
+        divisible=1;
+        break;
+      }      
+
+    if (!divisible)    //if it passes small primes check, then try a single Miller-Rabin base 2
+      if (!millerRabin(s_n,2)) //this line represents 75% of the total runtime for randTruePrime_ 
+        divisible=1;
+
+    if (!divisible) {  //if it passes that test, continue checking s_n
+      addInt_(s_n,-3);
+      for (j=s_n.length-1;(s_n[j]==0) && (j>0); j--);  //strip leading zeros
+      for (zz=0,w=s_n[j]; w; (w>>=1),zz++);
+      zz+=bpe*j;                             //zz=number of bits in s_n, ignoring leading zeros
+      for (;;) {  //generate z-bit numbers until one falls in the range [0,s_n-1]
+        randBigInt_(s_a,zz,0);
+        if (greater(s_n,s_a))
+          break;
+      }                //now s_a is in the range [0,s_n-1]
+      addInt_(s_n,3);  //now s_a is in the range [0,s_n-4]
+      addInt_(s_a,2);  //now s_a is in the range [2,s_n-2]
+      copy_(s_b,s_a);
+      copy_(s_n1,s_n);
+      addInt_(s_n1,-1);
+      powMod_(s_b,s_n1,s_n);   //s_b=s_a^(s_n-1) modulo s_n
+      addInt_(s_b,-1);
+      if (isZero(s_b)) {
+        copy_(s_b,s_a);
+        powMod_(s_b,s_r2,s_n);
+        addInt_(s_b,-1);
+        copy_(s_aa,s_n);
+        copy_(s_d,s_b);
+        GCD_(s_d,s_n);  //if s_b and s_n are relatively prime, then s_n is a prime
+        if (equalsInt(s_d,1)) {
+          copy_(ans,s_aa);
+          return;     //if we've made it this far, then s_n is absolutely guaranteed to be prime
+        }
+      }
+    }
+  }
+}
+
+//Return an n-bit random BigInt (n>=1).  If s=1, then the most significant of those n bits is set to 1.
+function randBigInt(n,s) {
+  var a,b;
+  a=Math.floor((n-1)/bpe)+2; //# array elements to hold the BigInt with a leading 0 element
+  b=int2bigInt(0,0,a);
+  randBigInt_(b,n,s);
+  return b;
+}
+
+//Set b to an n-bit random BigInt.  If s=1, then the most significant of those n bits is set to 1.
+//Array b must be big enough to hold the result. Must have n>=1
+function randBigInt_(b,n,s) {
+  var i,a;
+  for (i=0;i<b.length;i++)
+    b[i]=0;
+  a=Math.floor((n-1)/bpe)+1; //# array elements to hold the BigInt
+  for (i=0;i<a;i++) {
+    b[i]=Math.floor(Math.random()*(1<<(bpe-1)));
+  }
+  b[a-1] &= (2<<((n-1)%bpe))-1;
+  if (s==1)
+    b[a-1] |= (1<<((n-1)%bpe));
+}
+
+//Return the greatest common divisor of bigInts x and y (each with same number of elements).
+function GCD(x,y) {
+  var xc,yc;
+  xc=dup(x);
+  yc=dup(y);
+  GCD_(xc,yc);
+  return xc;
+}
+
+//set x to the greatest common divisor of bigInts x and y (each with same number of elements).
+//y is destroyed.
+function GCD_(x,y) {
+  var i,xp,yp,A,B,C,D,q,sing;
+  if (T.length!=x.length)
+    T=dup(x);
+
+  sing=1;
+  while (sing) { //while y has nonzero elements other than y[0]
+    sing=0;
+    for (i=1;i<y.length;i++) //check if y has nonzero elements other than 0
+      if (y[i]) {
+        sing=1;
+        break;
+      }
+    if (!sing) break; //quit when y all zero elements except possibly y[0]
+
+    for (i=x.length;!x[i] && i>=0;i--);  //find most significant element of x
+    xp=x[i];
+    yp=y[i];
+    A=1; B=0; C=0; D=1;
+    while ((yp+C) && (yp+D)) {
+      q =Math.floor((xp+A)/(yp+C));
+      qp=Math.floor((xp+B)/(yp+D));
+      if (q!=qp)
+        break;
+      t= A-q*C;   A=C;   C=t;    //  do (A,B,xp, C,D,yp) = (C,D,yp, A,B,xp) - q*(0,0,0, C,D,yp)      
+      t= B-q*D;   B=D;   D=t;
+      t=xp-q*yp; xp=yp; yp=t;
+    }
+    if (B) {
+      copy_(T,x);
+      linComb_(x,y,A,B); //x=A*x+B*y
+      linComb_(y,T,D,C); //y=D*y+C*T
+    } else {
+      mod_(x,y);
+      copy_(T,x);
+      copy_(x,y);
+      copy_(y,T);
+    } 
+  }
+  if (y[0]==0)
+    return;
+  t=modInt(x,y[0]);
+  copyInt_(x,y[0]);
+  y[0]=t;
+  while (y[0]) {
+    x[0]%=y[0];
+    t=x[0]; x[0]=y[0]; y[0]=t;
+  }
+}
+
+//do x=x**(-1) mod n, for bigInts x and n.
+//If no inverse exists, it sets x to zero and returns 0, else it returns 1.
+//The x array must be at least as large as the n array.
+function inverseMod_(x,n) {
+  var k=1+2*Math.max(x.length,n.length);
+
+  if(!(x[0]&1)  && !(n[0]&1)) {  //if both inputs are even, then inverse doesn't exist
+    copyInt_(x,0);
+    return 0;
+  }
+
+  if (eg_u.length!=k) {
+    eg_u=new Array(k);
+    eg_v=new Array(k);
+    eg_A=new Array(k);
+    eg_B=new Array(k);
+    eg_C=new Array(k);
+    eg_D=new Array(k);
+  }
+
+  copy_(eg_u,x);
+  copy_(eg_v,n);
+  copyInt_(eg_A,1);
+  copyInt_(eg_B,0);
+  copyInt_(eg_C,0);
+  copyInt_(eg_D,1);
+  for (;;) {
+    while(!(eg_u[0]&1)) {  //while eg_u is even
+      halve_(eg_u);
+      if (!(eg_A[0]&1) && !(eg_B[0]&1)) { //if eg_A==eg_B==0 mod 2
+        halve_(eg_A);
+        halve_(eg_B);      
+      } else {
+        add_(eg_A,n);  halve_(eg_A);
+        sub_(eg_B,x);  halve_(eg_B);
+      }
+    }
+
+    while (!(eg_v[0]&1)) {  //while eg_v is even
+      halve_(eg_v);
+      if (!(eg_C[0]&1) && !(eg_D[0]&1)) { //if eg_C==eg_D==0 mod 2
+        halve_(eg_C);
+        halve_(eg_D);      
+      } else {
+        add_(eg_C,n);  halve_(eg_C);
+        sub_(eg_D,x);  halve_(eg_D);
+      }
+    }
+
+    if (!greater(eg_v,eg_u)) { //eg_v <= eg_u
+      sub_(eg_u,eg_v);
+      sub_(eg_A,eg_C);
+      sub_(eg_B,eg_D);
+    } else {                   //eg_v > eg_u
+      sub_(eg_v,eg_u);
+      sub_(eg_C,eg_A);
+      sub_(eg_D,eg_B);
+    }
+  
+    if (equalsInt(eg_u,0)) {
+      if (negative(eg_C)) //make sure answer is nonnegative
+        add_(eg_C,n);
+      copy_(x,eg_C);
+
+      if (!equalsInt(eg_v,1)) { //if GCD_(x,n)!=1, then there is no inverse
+        copyInt_(x,0);
+        return 0;
+      }
+      return 1;
+    }
+  }
+}
+
+//return x**(-1) mod n, for integers x and n.  Return 0 if there is no inverse
+function inverseModInt(x,n) {
+  var a=1,b=0,t;
+  for (;;) {
+    if (x==1) return a;
+    if (x==0) return 0;
+    b-=a*Math.floor(n/x);
+    n%=x;
+
+    if (n==1) return b; //to avoid negatives, change this b to n-b, and each -= to +=
+    if (n==0) return 0;
+    a-=b*Math.floor(x/n);
+    x%=n;
+  }
+}
+
+//this deprecated function is for backward compatibility only. 
+function inverseModInt_(x,n) {
+   return inverseModInt(x,n);
+}
+
+
+//Given positive bigInts x and y, change the bigints v, a, and b to positive bigInts such that:
+//     v = GCD_(x,y) = a*x-b*y
+//The bigInts v, a, b, must have exactly as many elements as the larger of x and y.
+function eGCD_(x,y,v,a,b) {
+  var g=0;
+  var k=Math.max(x.length,y.length);
+  if (eg_u.length!=k) {
+    eg_u=new Array(k);
+    eg_A=new Array(k);
+    eg_B=new Array(k);
+    eg_C=new Array(k);
+    eg_D=new Array(k);
+  }
+  while(!(x[0]&1)  && !(y[0]&1)) {  //while x and y both even
+    halve_(x);
+    halve_(y);
+    g++;
+  }
+  copy_(eg_u,x);
+  copy_(v,y);
+  copyInt_(eg_A,1);
+  copyInt_(eg_B,0);
+  copyInt_(eg_C,0);
+  copyInt_(eg_D,1);
+  for (;;) {
+    while(!(eg_u[0]&1)) {  //while u is even
+      halve_(eg_u);
+      if (!(eg_A[0]&1) && !(eg_B[0]&1)) { //if A==B==0 mod 2
+        halve_(eg_A);
+        halve_(eg_B);      
+      } else {
+        add_(eg_A,y);  halve_(eg_A);
+        sub_(eg_B,x);  halve_(eg_B);
+      }
+    }
+
+    while (!(v[0]&1)) {  //while v is even
+      halve_(v);
+      if (!(eg_C[0]&1) && !(eg_D[0]&1)) { //if C==D==0 mod 2
+        halve_(eg_C);
+        halve_(eg_D);      
+      } else {
+        add_(eg_C,y);  halve_(eg_C);
+        sub_(eg_D,x);  halve_(eg_D);
+      }
+    }
+
+    if (!greater(v,eg_u)) { //v<=u
+      sub_(eg_u,v);
+      sub_(eg_A,eg_C);
+      sub_(eg_B,eg_D);
+    } else {                //v>u
+      sub_(v,eg_u);
+      sub_(eg_C,eg_A);
+      sub_(eg_D,eg_B);
+    }
+    if (equalsInt(eg_u,0)) {
+      if (negative(eg_C)) {   //make sure a (C)is nonnegative
+        add_(eg_C,y);
+        sub_(eg_D,x);
+      }
+      multInt_(eg_D,-1);  ///make sure b (D) is nonnegative
+      copy_(a,eg_C);
+      copy_(b,eg_D);
+      leftShift_(v,g);
+      return;
+    }
+  }
+}
+
+
+//is bigInt x negative?
+function negative(x) {
+  return ((x[x.length-1]>>(bpe-1))&1);
+}
+
+
+//is (x << (shift*bpe)) > y?
+//x and y are nonnegative bigInts
+//shift is a nonnegative integer
+function greaterShift(x,y,shift) {
+  var kx=x.length, ky=y.length;
+  k=((kx+shift)<ky) ? (kx+shift) : ky;
+  for (i=ky-1-shift; i<kx && i>=0; i++) 
+    if (x[i]>0)
+      return 1; //if there are nonzeros in x to the left of the first column of y, then x is bigger
+  for (i=kx-1+shift; i<ky; i++)
+    if (y[i]>0)
+      return 0; //if there are nonzeros in y to the left of the first column of x, then x is not bigger
+  for (i=k-1; i>=shift; i--)
+    if      (x[i-shift]>y[i]) return 1;
+    else if (x[i-shift]<y[i]) return 0;
+  return 0;
+}
+
+//is x > y? (x and y both nonnegative)
+function greater(x,y) {
+  var i;
+  var k=(x.length<y.length) ? x.length : y.length;
+
+  for (i=x.length;i<y.length;i++)
+    if (y[i])
+      return 0;  //y has more digits
+
+  for (i=y.length;i<x.length;i++)
+    if (x[i])
+      return 1;  //x has more digits
+
+  for (i=k-1;i>=0;i--)
+    if (x[i]>y[i])
+      return 1;
+    else if (x[i]<y[i])
+      return 0;
+  return 0;
+}
+
+//divide x by y giving quotient q and remainder r.  (q=floor(x/y),  r=x mod y).  All 4 are bigints.
+//x must have at least one leading zero element.
+//y must be nonzero.
+//q and r must be arrays that are exactly the same length as x. (Or q can have more).
+//Must have x.length >= y.length >= 2.
+function divide_(x,y,q,r) {
+  var kx, ky;
+  var i,j,y1,y2,c,a,b;
+  copy_(r,x);
+  for (ky=y.length;y[ky-1]==0;ky--); //ky is number of elements in y, not including leading zeros
+
+  //normalize: ensure the most significant element of y has its highest bit set  
+  b=y[ky-1];
+  for (a=0; b; a++)
+    b>>=1;  
+  a=bpe-a;  //a is how many bits to shift so that the high order bit of y is leftmost in its array element
+  leftShift_(y,a);  //multiply both by 1<<a now, then divide both by that at the end
+  leftShift_(r,a);
+
+  //Rob Visser discovered a bug: the following line was originally just before the normalization.
+  for (kx=r.length;r[kx-1]==0 && kx>ky;kx--); //kx is number of elements in normalized x, not including leading zeros
+
+  copyInt_(q,0);                      // q=0
+  while (!greaterShift(y,r,kx-ky)) {  // while (leftShift_(y,kx-ky) <= r) {
+    subShift_(r,y,kx-ky);             //   r=r-leftShift_(y,kx-ky)
+    q[kx-ky]++;                       //   q[kx-ky]++;
+  }                                   // }
+
+  for (i=kx-1; i>=ky; i--) {
+    if (r[i]==y[ky-1])
+      q[i-ky]=mask;
+    else
+      q[i-ky]=Math.floor((r[i]*radix+r[i-1])/y[ky-1]);	
+
+    //The following for(;;) loop is equivalent to the commented while loop, 
+    //except that the uncommented version avoids overflow.
+    //The commented loop comes from HAC, which assumes r[-1]==y[-1]==0
+    //  while (q[i-ky]*(y[ky-1]*radix+y[ky-2]) > r[i]*radix*radix+r[i-1]*radix+r[i-2])
+    //    q[i-ky]--;    
+    for (;;) {
+      y2=(ky>1 ? y[ky-2] : 0)*q[i-ky];
+      c=y2>>bpe;
+      y2=y2 & mask;
+      y1=c+q[i-ky]*y[ky-1];
+      c=y1>>bpe;
+      y1=y1 & mask;
+
+      if (c==r[i] ? y1==r[i-1] ? y2>(i>1 ? r[i-2] : 0) : y1>r[i-1] : c>r[i]) 
+        q[i-ky]--;
+      else
+        break;
+    }
+
+    linCombShift_(r,y,-q[i-ky],i-ky);    //r=r-q[i-ky]*leftShift_(y,i-ky)
+    if (negative(r)) {
+      addShift_(r,y,i-ky);         //r=r+leftShift_(y,i-ky)
+      q[i-ky]--;
+    }
+  }
+
+  rightShift_(y,a);  //undo the normalization step
+  rightShift_(r,a);  //undo the normalization step
+}
+
+//do carries and borrows so each element of the bigInt x fits in bpe bits.
+function carry_(x) {
+  var i,k,c,b;
+  k=x.length;
+  c=0;
+  for (i=0;i<k;i++) {
+    c+=x[i];
+    b=0;
+    if (c<0) {
+      b=-(c>>bpe);
+      c+=b*radix;
+    }
+    x[i]=c & mask;
+    c=(c>>bpe)-b;
+  }
+}
+
+//return x mod n for bigInt x and integer n.
+function modInt(x,n) {
+  var i,c=0;
+  for (i=x.length-1; i>=0; i--)
+    c=(c*radix+x[i])%n;
+  return c;
+}
+
+//convert the integer t into a bigInt with at least the given number of bits.
+//the returned array stores the bigInt in bpe-bit chunks, little endian (buff[0] is least significant word)
+//Pad the array with leading zeros so that it has at least minSize elements.
+//There will always be at least one leading 0 element.
+function int2bigInt(t,bits,minSize) {   
+  var i,k;
+  k=Math.ceil(bits/bpe)+1;
+  k=minSize>k ? minSize : k;
+  buff=new Array(k);
+  copyInt_(buff,t);
+  return buff;
+}
+
+//return the bigInt given a string representation in a given base.  
+//Pad the array with leading zeros so that it has at least minSize elements.
+//If base=-1, then it reads in a space-separated list of array elements in decimal.
+//The array will always have at least one leading zero, unless base=-1.
+function str2bigInt(s,base,minSize) {
+  var d, i, j, x, y, kk;
+  var k=s.length;
+  if (base==-1) { //comma-separated list of array elements in decimal
+    x=new Array(0);
+    for (;;) {
+      y=new Array(x.length+1);
+      for (i=0;i<x.length;i++)
+        y[i+1]=x[i];
+      y[0]=parseInt(s,10);
+      x=y;
+      d=s.indexOf(',',0);
+      if (d<1) 
+        break;
+      s=s.substring(d+1);
+      if (s.length==0)
+        break;
+    }
+    if (x.length<minSize) {
+      y=new Array(minSize);
+      copy_(y,x);
+      return y;
+    }
+    return x;
+  }
+
+  x=int2bigInt(0,base*k,0);
+  for (i=0;i<k;i++) {
+    d=digitsStr.indexOf(s.substring(i,i+1),0);
+    if (base<=36 && d>=36)  //convert lowercase to uppercase if base<=36
+      d-=26;
+    if (d<base && d>=0) {   //ignore illegal characters
+      multInt_(x,base);
+      addInt_(x,d);
+    }
+  }
+
+  for (k=x.length;k>0 && !x[k-1];k--); //strip off leading zeros
+  k=minSize>k+1 ? minSize : k+1;
+  y=new Array(k);
+  kk=k<x.length ? k : x.length;
+  for (i=0;i<kk;i++)
+    y[i]=x[i];
+  for (;i<k;i++)
+    y[i]=0;
+  return y;
+}
+
+//is bigint x equal to integer y?
+//y must have less than bpe bits
+function equalsInt(x,y) {
+  var i;
+  if (x[0]!=y)
+    return 0;
+  for (i=1;i<x.length;i++)
+    if (x[i])
+      return 0;
+  return 1;
+}
+
+//are bigints x and y equal?
+//this works even if x and y are different lengths and have arbitrarily many leading zeros
+function equals(x,y) {
+  var i;
+  var k=x.length<y.length ? x.length : y.length;
+  for (i=0;i<k;i++)
+    if (x[i]!=y[i])
+      return 0;
+  if (x.length>y.length) {
+    for (;i<x.length;i++)
+      if (x[i])
+        return 0;
+  } else {
+    for (;i<y.length;i++)
+      if (y[i])
+        return 0;
+  }
+  return 1;
+}
+
+//is the bigInt x equal to zero?
+function isZero(x) {
+  var i;
+  for (i=0;i<x.length;i++)
+    if (x[i])
+      return 0;
+  return 1;
+}
+
+//convert a bigInt into a string in a given base, from base 2 up to base 95.
+//Base -1 prints the contents of the array representing the number.
+function bigInt2str(x,base) {
+  var i,t,s="";
+
+  if (s6.length!=x.length) 
+    s6=dup(x);
+  else
+    copy_(s6,x);
+
+  if (base==-1) { //return the list of array contents
+    for (i=x.length-1;i>0;i--)
+      s+=x[i]+',';
+    s+=x[0];
+  }
+  else { //return it in the given base
+    while (!isZero(s6)) {
+      t=divInt_(s6,base);  //t=s6 % base; s6=floor(s6/base);
+      s=digitsStr.substring(t,t+1)+s;
+    }
+  }
+  if (s.length==0)
+    s="0";
+  return s;
+}
+
+//returns a duplicate of bigInt x
+function dup(x) {
+  var i;
+  buff=new Array(x.length);
+  copy_(buff,x);
+  return buff;
+}
+
+//do x=y on bigInts x and y.  x must be an array at least as big as y (not counting the leading zeros in y).
+function copy_(x,y) {
+  var i;
+  var k=x.length<y.length ? x.length : y.length;
+  for (i=0;i<k;i++)
+    x[i]=y[i];
+  for (i=k;i<x.length;i++)
+    x[i]=0;
+}
+
+//do x=y on bigInt x and integer y.  
+function copyInt_(x,n) {
+  var i,c;
+  for (c=n,i=0;i<x.length;i++) {
+    x[i]=c & mask;
+    c>>=bpe;
+  }
+}
+
+//do x=x+n where x is a bigInt and n is an integer.
+//x must be large enough to hold the result.
+function addInt_(x,n) {
+  var i,k,c,b;
+  x[0]+=n;
+  k=x.length;
+  c=0;
+  for (i=0;i<k;i++) {
+    c+=x[i];
+    b=0;
+    if (c<0) {
+      b=-(c>>bpe);
+      c+=b*radix;
+    }
+    x[i]=c & mask;
+    c=(c>>bpe)-b;
+    if (!c) return; //stop carrying as soon as the carry_ is zero
+  }
+}
+
+//right shift bigInt x by n bits.  0 <= n < bpe.
+function rightShift_(x,n) {
+  var i;
+  var k=Math.floor(n/bpe);
+  if (k) {
+    for (i=0;i<x.length-k;i++) //right shift x by k elements
+      x[i]=x[i+k];
+    for (;i<x.length;i++)
+      x[i]=0;
+    n%=bpe;
+  }
+  for (i=0;i<x.length-1;i++) {
+    x[i]=mask & ((x[i+1]<<(bpe-n)) | (x[i]>>n));
+  }
+  x[i]>>=n;
+}
+
+//do x=floor(|x|/2)*sgn(x) for bigInt x in 2's complement
+function halve_(x) {
+  var i;
+  for (i=0;i<x.length-1;i++) {
+    x[i]=mask & ((x[i+1]<<(bpe-1)) | (x[i]>>1));
+  }
+  x[i]=(x[i]>>1) | (x[i] & (radix>>1));  //most significant bit stays the same
+}
+
+//left shift bigInt x by n bits.
+function leftShift_(x,n) {
+  var i;
+  var k=Math.floor(n/bpe);
+  if (k) {
+    for (i=x.length; i>=k; i--) //left shift x by k elements
+      x[i]=x[i-k];
+    for (;i>=0;i--)
+      x[i]=0;  
+    n%=bpe;
+  }
+  if (!n)
+    return;
+  for (i=x.length-1;i>0;i--) {
+    x[i]=mask & ((x[i]<<n) | (x[i-1]>>(bpe-n)));
+  }
+  x[i]=mask & (x[i]<<n);
+}
+
+//do x=x*n where x is a bigInt and n is an integer.
+//x must be large enough to hold the result.
+function multInt_(x,n) {
+  var i,k,c,b;
+  if (!n)
+    return;
+  k=x.length;
+  c=0;
+  for (i=0;i<k;i++) {
+    c+=x[i]*n;
+    b=0;
+    if (c<0) {
+      b=-(c>>bpe);
+      c+=b*radix;
+    }
+    x[i]=c & mask;
+    c=(c>>bpe)-b;
+  }
+}
+
+//do x=floor(x/n) for bigInt x and integer n, and return the remainder
+function divInt_(x,n) {
+  var i,r=0,s;
+  for (i=x.length-1;i>=0;i--) {
+    s=r*radix+x[i];
+    x[i]=Math.floor(s/n);
+    r=s%n;
+  }
+  return r;
+}
+
+//do the linear combination x=a*x+b*y for bigInts x and y, and integers a and b.
+//x must be large enough to hold the answer.
+function linComb_(x,y,a,b) {
+  var i,c,k,kk;
+  k=x.length<y.length ? x.length : y.length;
+  kk=x.length;
+  for (c=0,i=0;i<k;i++) {
+    c+=a*x[i]+b*y[i];
+    x[i]=c & mask;
+    c>>=bpe;
+  }
+  for (i=k;i<kk;i++) {
+    c+=a*x[i];
+    x[i]=c & mask;
+    c>>=bpe;
+  }
+}
+
+//do the linear combination x=a*x+b*(y<<(ys*bpe)) for bigInts x and y, and integers a, b and ys.
+//x must be large enough to hold the answer.
+function linCombShift_(x,y,b,ys) {
+  var i,c,k,kk;
+  k=x.length<ys+y.length ? x.length : ys+y.length;
+  kk=x.length;
+  for (c=0,i=ys;i<k;i++) {
+    c+=x[i]+b*y[i-ys];
+    x[i]=c & mask;
+    c>>=bpe;
+  }
+  for (i=k;c && i<kk;i++) {
+    c+=x[i];
+    x[i]=c & mask;
+    c>>=bpe;
+  }
+}
+
+//do x=x+(y<<(ys*bpe)) for bigInts x and y, and integers a,b and ys.
+//x must be large enough to hold the answer.
+function addShift_(x,y,ys) {
+  var i,c,k,kk;
+  k=x.length<ys+y.length ? x.length : ys+y.length;
+  kk=x.length;
+  for (c=0,i=ys;i<k;i++) {
+    c+=x[i]+y[i-ys];
+    x[i]=c & mask;
+    c>>=bpe;
+  }
+  for (i=k;c && i<kk;i++) {
+    c+=x[i];
+    x[i]=c & mask;
+    c>>=bpe;
+  }
+}
+
+//do x=x-(y<<(ys*bpe)) for bigInts x and y, and integers a,b and ys.
+//x must be large enough to hold the answer.
+function subShift_(x,y,ys) {
+  var i,c,k,kk;
+  k=x.length<ys+y.length ? x.length : ys+y.length;
+  kk=x.length;
+  for (c=0,i=ys;i<k;i++) {
+    c+=x[i]-y[i-ys];
+    x[i]=c & mask;
+    c>>=bpe;
+  }
+  for (i=k;c && i<kk;i++) {
+    c+=x[i];
+    x[i]=c & mask;
+    c>>=bpe;
+  }
+}
+
+//do x=x-y for bigInts x and y.
+//x must be large enough to hold the answer.
+//negative answers will be 2s complement
+function sub_(x,y) {
+  var i,c,k,kk;
+  k=x.length<y.length ? x.length : y.length;
+  for (c=0,i=0;i<k;i++) {
+    c+=x[i]-y[i];
+    x[i]=c & mask;
+    c>>=bpe;
+  }
+  for (i=k;c && i<x.length;i++) {
+    c+=x[i];
+    x[i]=c & mask;
+    c>>=bpe;
+  }
+}
+
+//do x=x+y for bigInts x and y.
+//x must be large enough to hold the answer.
+function add_(x,y) {
+  var i,c,k,kk;
+  k=x.length<y.length ? x.length : y.length;
+  for (c=0,i=0;i<k;i++) {
+    c+=x[i]+y[i];
+    x[i]=c & mask;
+    c>>=bpe;
+  }
+  for (i=k;c && i<x.length;i++) {
+    c+=x[i];
+    x[i]=c & mask;
+    c>>=bpe;
+  }
+}
+
+//do x=x*y for bigInts x and y.  This is faster when y<x.
+function mult_(x,y) {
+  var i;
+  if (ss.length!=2*x.length)
+    ss=new Array(2*x.length);
+  copyInt_(ss,0);
+  for (i=0;i<y.length;i++)
+    if (y[i])
+      linCombShift_(ss,x,y[i],i);   //ss=1*ss+y[i]*(x<<(i*bpe))
+  copy_(x,ss);
+}
+
+//do x=x mod n for bigInts x and n.
+function mod_(x,n) {
+  if (s4.length!=x.length)
+    s4=dup(x);
+  else
+    copy_(s4,x);
+  if (s5.length!=x.length)
+    s5=dup(x);  
+  divide_(s4,n,s5,x);  //x = remainder of s4 / n
+}
+
+//do x=x*y mod n for bigInts x,y,n.
+//for greater speed, let y<x.
+function multMod_(x,y,n) {
+  var i;
+  if (s0.length!=2*x.length)
+    s0=new Array(2*x.length);
+  copyInt_(s0,0);
+  for (i=0;i<y.length;i++)
+    if (y[i])
+      linCombShift_(s0,x,y[i],i);   //s0=1*s0+y[i]*(x<<(i*bpe))
+  mod_(s0,n);
+  copy_(x,s0);
+}
+
+//do x=x*x mod n for bigInts x,n.
+function squareMod_(x,n) {
+  var i,j,d,c,kx,kn,k;
+  for (kx=x.length; kx>0 && !x[kx-1]; kx--);  //ignore leading zeros in x
+  k=kx>n.length ? 2*kx : 2*n.length; //k=# elements in the product, which is twice the elements in the larger of x and n
+  if (s0.length!=k) 
+    s0=new Array(k);
+  copyInt_(s0,0);
+  for (i=0;i<kx;i++) {
+    c=s0[2*i]+x[i]*x[i];
+    s0[2*i]=c & mask;
+    c>>=bpe;
+    for (j=i+1;j<kx;j++) {
+      c=s0[i+j]+2*x[i]*x[j]+c;
+      s0[i+j]=(c & mask);
+      c>>=bpe;
+    }
+    s0[i+kx]=c;
+  }
+  mod_(s0,n);
+  copy_(x,s0);
+}
+
+//return x with exactly k leading zero elements
+function bigint_trim(x,k) {
+  var i,y;
+  for (i=x.length; i>0 && !x[i-1]; i--);
+  y=new Array(i+k);
+  copy_(y,x);
+  return y;
+}
+
+//do x=x**y mod n, where x,y,n are bigInts and ** is exponentiation.  0**0=1.
+//this is faster when n is odd.  x usually needs to have as many elements as n.
+function powMod_(x,y,n) {
+  var k1,k2,kn,np;
+  if(s7.length!=n.length)
+    s7=dup(n);
+
+  //for even modulus, use a simple square-and-multiply algorithm,
+  //rather than using the more complex Montgomery algorithm.
+  if ((n[0]&1)==0) {
+    copy_(s7,x);
+    copyInt_(x,1);
+    while(!equalsInt(y,0)) {
+      if (y[0]&1)
+        multMod_(x,s7,n);
+      divInt_(y,2);
+      squareMod_(s7,n); 
+    }
+    return;
+  }
+
+  //calculate np from n for the Montgomery multiplications
+  copyInt_(s7,0);
+  for (kn=n.length;kn>0 && !n[kn-1];kn--);
+  np=radix-inverseModInt(modInt(n,radix),radix);
+  s7[kn]=1;
+  multMod_(x ,s7,n);   // x = x * 2**(kn*bp) mod n
+
+  if (s3.length!=x.length)
+    s3=dup(x);
+  else
+    copy_(s3,x);
+
+  for (k1=y.length-1;k1>0 & !y[k1]; k1--);  //k1=first nonzero element of y
+  if (y[k1]==0) {  //anything to the 0th power is 1
+    copyInt_(x,1);
+    return;
+  }
+  for (k2=1<<(bpe-1);k2 && !(y[k1] & k2); k2>>=1);  //k2=position of first 1 bit in y[k1]
+  for (;;) {
+    if (!(k2>>=1)) {  //look at next bit of y
+      k1--;
+      if (k1<0) {
+        mont_(x,one,n,np);
+        return;
+      }
+      k2=1<<(bpe-1);
+    }    
+    mont_(x,x,n,np);
+
+    if (k2 & y[k1]) //if next bit is a 1
+      mont_(x,s3,n,np);
+  }
+}    
+
+//do x=x*y*Ri mod n for bigInts x,y,n, 
+//  where Ri = 2**(-kn*bpe) mod n, and kn is the 
+//  number of elements in the n array, not 
+//  counting leading zeros.  
+//x must be large enough to hold the answer.
+//It's OK if x and y are the same variable.
+//must have:
+//  x,y < n
+//  n is odd
+//  np = -(n^(-1)) mod radix
+function mont_(x,y,n,np) {
+  var i,j,c,ui,t;
+  var kn=n.length;
+  var ky=y.length;
+
+  if (sa.length!=kn)
+    sa=new Array(kn);
+
+  for (;kn>0 && n[kn-1]==0;kn--); //ignore leading zeros of n
+  //this function sometimes gives wrong answers when the next line is uncommented
+  //for (;ky>0 && y[ky-1]==0;ky--); //ignore leading zeros of y
+
+  copyInt_(sa,0);
+
+  //the following loop consumes 95% of the runtime for randTruePrime_() and powMod_() for large keys
+  for (i=0; i<kn; i++) {
+    t=sa[0]+x[i]*y[0];
+    ui=((t & mask) * np) & mask;  //the inner "& mask" is needed on Macintosh MSIE, but not windows MSIE
+    c=(t+ui*n[0]) >> bpe;
+    t=x[i];
+
+    //do sa=(sa+x[i]*y+ui*n)/b   where b=2**bpe
+    for (j=1;j<ky;j++) { 
+      c+=sa[j]+t*y[j]+ui*n[j];
+      sa[j-1]=c & mask;
+      c>>=bpe;
+    }    
+    for (;j<kn;j++) { 
+      c+=sa[j]+ui*n[j];
+      sa[j-1]=c & mask;
+      c>>=bpe;
+    }    
+    sa[j-1]=c & mask;
+  }
+
+  if (!greater(n,sa))
+    sub_(sa,n);
+  copy_(x,sa);
+}
+
+
--- a/includes/clientside/static/loader.js	Fri Feb 22 12:46:51 2008 -0500
+++ b/includes/clientside/static/loader.js	Fri Feb 22 12:51:53 2008 -0500
@@ -2,7 +2,6 @@
 
 function mdgInnerLoader(e)
 {
-  jws.startup();
   if(window.location.hash == '#comments') ajaxComments();
   window.onkeydown=isKeyPressed;
   window.onkeyup=function(e) { isKeyPressed(e); };
@@ -18,10 +17,14 @@
   initSliders();
   runOnloadHooks(e);
 }
-if(window.onload) var ld = window.onload;
-else var ld = function() {return;};
+var ld;
+if(window.onload) ld = window.onload;
+else ld = function() {return;};
 function enano_init(e) {
-  ld(e);
+  if ( typeof(ld) == 'function' )
+  {
+    ld(e);
+  }
   mdgInnerLoader(e);
 }
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/includes/clientside/static/login.js	Fri Feb 22 12:51:53 2008 -0500
@@ -0,0 +1,778 @@
+/*
+ * AJAX-based intelligent login interface
+ */
+
+/*
+ * FRONTEND
+ */
+
+/**
+ * Performs a logon as a regular member.
+ */
+
+function ajaxLogonToMember()
+{
+  // IE <6 pseudo-compatibility
+  if ( KILL_SWITCH )
+    return true;
+  if ( auth_level >= USER_LEVEL_MEMBER )
+    return true;
+  ajaxLoginInit(function(k)
+    {
+      window.location.reload();
+    }, USER_LEVEL_MEMBER);
+}
+
+/**
+ * Authenticates to the highest level the current user is allowed to go to.
+ */
+
+function ajaxLogonToElev()
+{
+  if ( auth_level == user_level )
+    return true;
+  
+  ajaxLoginInit(function(k)
+    {
+      ENANO_SID = k;
+      var url = String(' ' + window.location).substr(1);
+      url = append_sid(url);
+      window.location = url;
+    }, user_level);
+}
+
+/*
+ * BACKEND
+ */
+
+/**
+ * Holding object for various AJAX authentication information.
+ * @var object
+ */
+
+var logindata = {};
+
+/**
+ * Path to the image used to indicate loading progress
+ * @var string
+ */
+
+if ( !ajax_login_loadimg_path )
+  var ajax_login_loadimg_path = false;
+
+if ( !ajax_login_successimg_path )
+  var ajax_login_successimg_path = false;
+
+/**
+ * Status variables
+ * @var int
+ */
+
+var AJAX_STATUS_LOADING_KEY = 1;
+var AJAX_STATUS_GENERATING_KEY = 2;
+var AJAX_STATUS_LOGGING_IN = 3;
+var AJAX_STATUS_SUCCESS = 4;
+var AJAX_STATUS_DESTROY = 65535;
+
+/**
+ * State constants
+ * @var int
+ */
+
+var AJAX_STATE_EARLY_INIT = 1;
+var AJAX_STATE_LOADING_KEY = 2;
+
+/**
+ * Performs the AJAX request to get an encryption key and from there spawns the login form.
+ * @param function The function that will be called once authentication completes successfully.
+ * @param int The security level to authenticate at - see http://docs.enanocms.org/Help:Appendix_B
+ */
+
+function ajaxLoginInit(call_on_finish, user_level)
+{
+  logindata = {};
+  
+  var title = ( user_level > USER_LEVEL_MEMBER ) ? $lang.get('user_login_ajax_prompt_title_elev') : $lang.get('user_login_ajax_prompt_title');
+  logindata.mb_object = new messagebox(MB_OKCANCEL | MB_ICONLOCK, title, '');
+  
+  logindata.mb_object.onclick['Cancel'] = function()
+  {
+    // Hide the error message and captcha
+    if ( document.getElementById('ajax_login_error_box') )
+    {
+      document.getElementById('ajax_login_error_box').parentNode.removeChild(document.getElementById('ajax_login_error_box'));
+    }
+    if ( document.getElementById('autoCaptcha') )
+    {
+      var to = fly_out_top(document.getElementById('autoCaptcha'), false, true);
+      setTimeout(function() {
+          var d = document.getElementById('autoCaptcha');
+          d.parentNode.removeChild(d);
+        }, to);
+    }
+  };
+  
+  logindata.mb_object.onbeforeclick['OK'] = function()
+  {
+    ajaxLoginSubmitForm();
+    return true;
+  }
+  
+  // Fetch the inner content area
+  logindata.mb_inner = document.getElementById('messageBox').getElementsByTagName('div')[0];
+  
+  // Initialize state
+  logindata.showing_status = false;
+  logindata.user_level = user_level;
+  logindata.successfunc = call_on_finish;
+  
+  // Build the "loading" window
+  ajaxLoginSetStatus(AJAX_STATUS_LOADING_KEY);
+  
+  // Request the key
+  ajaxLoginPerformRequest({ mode: 'getkey' });
+}
+
+/**
+ * Sets the contents of the AJAX login window to the appropriate status message.
+ * @param int One of AJAX_STATUS_*
+ */
+
+function ajaxLoginSetStatus(status)
+{
+  if ( !logindata.mb_inner )
+    return false;
+  if ( logindata.showing_status )
+  {
+    var div = document.getElementById('ajax_login_status');
+    if ( div )
+      logindata.mb_inner.removeChild(div);
+  }
+  switch(status)
+  {
+    case AJAX_STATUS_LOADING_KEY:
+      
+      // Create the status div
+      var div = document.createElement('div');
+      div.id = 'ajax_login_status';
+      div.style.marginTop = '10px';
+      div.style.textAlign = 'center';
+      
+      // The circly ball ajaxy image + status message
+      var status_msg = $lang.get('user_login_ajax_fetching_key');
+      
+      // Insert the status message
+      div.appendChild(document.createTextNode(status_msg));
+      
+      // Append a br or two to space things properly
+      div.appendChild(document.createElement('br'));
+      div.appendChild(document.createElement('br'));
+      
+      var img = document.createElement('img');
+      img.src = ( ajax_login_loadimg_path ) ? ajax_login_loadimg_path : scriptPath + '/images/loading-big.gif';
+      div.appendChild(img);
+      
+      // Another coupla brs
+      div.appendChild(document.createElement('br'));
+      div.appendChild(document.createElement('br'));
+      
+      // The link to the full login form
+      var small = document.createElement('small');
+      small.innerHTML = $lang.get('user_login_ajax_link_fullform', { link_full_form: makeUrlNS('Special', 'Login/' + title) });
+      div.appendChild(small);
+      
+      // Insert the entire message into the login window
+      logindata.mb_inner.innerHTML = '';
+      logindata.mb_inner.appendChild(div);
+      
+      break;
+    case AJAX_STATUS_GENERATING_KEY:
+      
+      // Create the status div
+      var div = document.createElement('div');
+      div.id = 'ajax_login_status';
+      div.style.marginTop = '10px';
+      div.style.textAlign = 'center';
+      
+      // The circly ball ajaxy image + status message
+      var status_msg = $lang.get('user_login_ajax_generating_key');
+      
+      // Insert the status message
+      div.appendChild(document.createTextNode(status_msg));
+      
+      // Append a br or two to space things properly
+      div.appendChild(document.createElement('br'));
+      div.appendChild(document.createElement('br'));
+      
+      var img = document.createElement('img');
+      img.src = ( ajax_login_loadimg_path ) ? ajax_login_loadimg_path : scriptPath + '/images/loading-big.gif';
+      div.appendChild(img);
+      
+      // Another coupla brs
+      div.appendChild(document.createElement('br'));
+      div.appendChild(document.createElement('br'));
+      
+      // The link to the full login form
+      var small = document.createElement('small');
+      small.innerHTML = $lang.get('user_login_ajax_link_fullform_dh', { link_full_form: makeUrlNS('Special', 'Login/' + title) });
+      div.appendChild(small);
+      
+      // Insert the entire message into the login window
+      logindata.mb_inner.innerHTML = '';
+      logindata.mb_inner.appendChild(div);
+      
+      break;
+    case AJAX_STATUS_LOGGING_IN:
+      
+      // Create the status div
+      var div = document.createElement('div');
+      div.id = 'ajax_login_status';
+      div.style.marginTop = '10px';
+      div.style.textAlign = 'center';
+      
+      // The circly ball ajaxy image + status message
+      var status_msg = $lang.get('user_login_ajax_loggingin');
+      
+      // Insert the status message
+      div.appendChild(document.createTextNode(status_msg));
+      
+      // Append a br or two to space things properly
+      div.appendChild(document.createElement('br'));
+      div.appendChild(document.createElement('br'));
+      
+      var img = document.createElement('img');
+      img.src = ( ajax_login_loadimg_path ) ? ajax_login_loadimg_path : scriptPath + '/images/loading-big.gif';
+      div.appendChild(img);
+      
+      // Insert the entire message into the login window
+      logindata.mb_inner.innerHTML = '';
+      logindata.mb_inner.appendChild(div);
+      
+      break;
+    case AJAX_STATUS_SUCCESS:
+      
+      // Create the status div
+      var div = document.createElement('div');
+      div.id = 'ajax_login_status';
+      div.style.marginTop = '10px';
+      div.style.textAlign = 'center';
+      
+      // The circly ball ajaxy image + status message
+      var status_msg = $lang.get('user_login_success_short');
+      
+      // Insert the status message
+      div.appendChild(document.createTextNode(status_msg));
+      
+      // Append a br or two to space things properly
+      div.appendChild(document.createElement('br'));
+      div.appendChild(document.createElement('br'));
+      
+      var img = document.createElement('img');
+      img.src = ( ajax_login_successimg_path ) ? ajax_login_successimg_path : scriptPath + '/images/check.png';
+      div.appendChild(img);
+      
+      // Insert the entire message into the login window
+      logindata.mb_inner.innerHTML = '';
+      logindata.mb_inner.appendChild(div);
+      
+    case AJAX_STATUS_DESTROY:
+    case null:
+    case undefined:
+      logindata.showing_status = false;
+      return null;
+      break;
+  }
+  logindata.showing_status = true;
+}
+
+/**
+ * Performs an AJAX logon request to the server and calls ajaxLoginProcessResponse() on the result.
+ * @param object JSON packet to send
+ */
+
+function ajaxLoginPerformRequest(json)
+{
+  json = toJSONString(json);
+  json = ajaxEscape(json);
+  ajaxPost(makeUrlNS('Special', 'Login/action.json'), 'r=' + json, function()
+    {
+      if ( ajax.readyState == 4 && ajax.status == 200 )
+      {
+        // parse response
+        var response = String(ajax.responseText + '');
+        if ( response.substr(0, 1) != '{' )
+        {
+          handle_invalid_json(response);
+          return false;
+        }
+        response = parseJSON(response);
+        ajaxLoginProcessResponse(response);
+      }
+    }, true);
+}
+
+/**
+ * Processes a response from the login server
+ * @param object JSON response
+ */
+
+function ajaxLoginProcessResponse(response)
+{
+  // Did the server send a plaintext error?
+  if ( response.mode == 'error' )
+  {
+    logindata.mb_object.destroy();
+    new messagebox(MB_ICONSTOP | MB_OK, 'FIXME L10N: There was an error in the login process', 'The following error code came from the server:<br />' + response.error);
+    return false;
+  }
+  // Rid ourselves of any loading windows
+  ajaxLoginSetStatus(AJAX_STATUS_DESTROY);
+  // Main mode switch
+  switch ( response.mode )
+  {
+    case 'build_box':
+      // The server wants us to build the login form, all the information is there
+      ajaxLoginBuildForm(response);
+      break;
+    case 'login_success':
+      ajaxLoginSetStatus(AJAX_STATUS_SUCCESS);
+      logindata.successfunc(response.key);
+      break;
+    case 'login_failure':
+      document.getElementById('messageBox').style.backgroundColor = '#C0C0C0';
+      var mb_parent = document.getElementById('messageBox').parentNode;
+      new Spry.Effect.Shake(mb_parent, {duration: 1500}).start();
+      setTimeout(function()
+        {
+          document.getElementById('messageBox').style.backgroundColor = '#FFF';
+          ajaxLoginBuildForm(response.respawn_info);
+          ajaxLoginShowFriendlyError(response);
+        }, 2500);
+      break;
+  }
+}
+
+/*
+ * RESPONSE HANDLERS
+ */
+
+/**
+ * Builds the login form.
+ * @param object Metadata to build off of
+ */
+
+function ajaxLoginBuildForm(data)
+{
+  // let's hope this effectively preloads the image...
+  var _ = document.createElement('img');
+  _.src = ( ajax_login_successimg_path ) ? ajax_login_successimg_path : scriptPath + '/images/check.png';
+  
+  var div = document.createElement('div');
+  div.id = 'ajax_login_form';
+  
+  var show_captcha = ( data.locked_out && data.lockout_info.lockout_policy == 'captcha' ) ? data.lockout_info.captcha : false;
+  
+  // text displayed on re-auth
+  if ( logindata.user_level > USER_LEVEL_MEMBER )
+  {
+    div.innerHTML += $lang.get('user_login_ajax_prompt_body_elev') + '<br /><br />';
+  }
+  
+  // Create the form
+  var form = document.createElement('form');
+  form.action = 'javascript:void(ajaxLoginSubmitForm());';
+  form.onsubmit = function()
+  {
+    ajaxLoginSubmitForm();
+    return false;
+  }
+  
+  // Using tables to wrap form elements because it results in a
+  // more visually appealing form. Yes, tables suck. I don't really
+  // care - they make forms look good.
+  
+  var table = document.createElement('table');
+  table.style.margin = '0 auto';
+  
+  // Field - username
+  var tr1 = document.createElement('tr');
+  var td1_1 = document.createElement('td');
+  td1_1.appendChild(document.createTextNode($lang.get('user_login_field_username') + ':'));
+  tr1.appendChild(td1_1);
+  var td1_2 = document.createElement('td');
+  var f_username = document.createElement('input');
+  f_username.id = 'ajax_login_field_username';
+  f_username.name = 'ajax_login_field_username';
+  f_username.type = 'text';
+  f_username.size = '25';
+  if ( data.username )
+    f_username.value = data.username;
+  td1_2.appendChild(f_username);
+  tr1.appendChild(td1_2);
+  table.appendChild(tr1);
+  
+  // Field - password
+  var tr2 = document.createElement('tr');
+  var td2_1 = document.createElement('td');
+  td2_1.appendChild(document.createTextNode($lang.get('user_login_field_password') + ':'));
+  tr2.appendChild(td2_1);
+  var td2_2 = document.createElement('td');
+  var f_password = document.createElement('input');
+  f_password.id = 'ajax_login_field_password';
+  f_password.name = 'ajax_login_field_username';
+  f_password.type = 'password';
+  f_password.size = '25';
+  if ( !show_captcha )
+  {
+    f_password.onkeyup = function(e)
+    {
+      if ( !e.keyCode )
+        e = window.event;
+      if ( !e.keyCode )
+        return true;
+      if ( e.keyCode == 13 )
+      {
+        ajaxLoginSubmitForm();
+      }
+    }
+  }
+  td2_2.appendChild(f_password);
+  tr2.appendChild(td2_2);
+  table.appendChild(tr2);
+  
+  // Field - captcha
+  if ( show_captcha )
+  {
+    var tr3 = document.createElement('tr');
+    var td3_1 = document.createElement('td');
+    td3_1.appendChild(document.createTextNode($lang.get('user_login_field_captcha') + ':'));
+    tr3.appendChild(td3_1);
+    var td3_2 = document.createElement('td');
+    var f_captcha = document.createElement('input');
+    f_captcha.id = 'ajax_login_field_captcha';
+    f_captcha.name = 'ajax_login_field_username';
+    f_captcha.type = 'text';
+    f_captcha.size = '25';
+    f_captcha.onkeyup = function(e)
+    {
+      if ( !e )
+        e = window.event;
+      if ( !e.keyCode )
+        return true;
+      if ( e.keyCode == 13 )
+      {
+        ajaxLoginSubmitForm();
+      }
+    }
+    td3_2.appendChild(f_captcha);
+    tr3.appendChild(td3_2);
+    table.appendChild(tr3);
+  }
+  
+  // Done building the main part of the form
+  form.appendChild(table);
+  
+  // Field: enable Diffie Hellman
+  var lbl_dh = document.createElement('label');
+  lbl_dh.style.fontSize = 'smaller';
+  lbl_dh.style.display = 'block';
+  lbl_dh.style.textAlign = 'center';
+  var check_dh = document.createElement('input');
+  check_dh.type = 'checkbox';
+  // this onclick attribute changes the cookie whenever the checkbox or label is clicked
+  check_dh.setAttribute('onclick', 'var ck = ( this.checked ) ? "enable" : "disable"; createCookie("diffiehellman_login", ck, 3650);');
+  if ( readCookie('diffiehellman_login') != 'disable' )
+    check_dh.setAttribute('checked', 'checked');
+  check_dh.id = 'ajax_login_field_dh';
+  lbl_dh.appendChild(check_dh);
+  lbl_dh.innerHTML += $lang.get('user_login_ajax_check_dh');
+  form.appendChild(lbl_dh);
+  
+  div.appendChild(form);
+  
+  // Diagnostic / help links
+  // (only displayed in login, not in re-auth)
+  if ( logindata.user_level == USER_LEVEL_MEMBER )
+  {
+    form.style.marginBottom = '10px';
+    var links = document.createElement('small');
+    links.style.display = 'block';
+    links.style.textAlign = 'center';
+    links.innerHTML = '';
+    if ( !show_captcha )
+      links.innerHTML += $lang.get('user_login_ajax_link_fullform', { link_full_form: makeUrlNS('Special', 'Login/' + title) }) + '<br />';
+    // Always shown
+    links.innerHTML += $lang.get('user_login_ajax_link_forgotpass', { forgotpass_link: makeUrlNS('Special', 'PasswordReset') }) + '<br />';
+    if ( !show_captcha )
+      links.innerHTML += $lang.get('user_login_createaccount_blurb', { reg_link: makeUrlNS('Special', 'Register') });
+    div.appendChild(links);
+  }
+  
+  // Insert the entire form into the login window
+  logindata.mb_inner.innerHTML = '';
+  logindata.mb_inner.appendChild(div);
+  
+  // Post operations: field focus
+  if ( data.username )
+    f_password.focus();
+  else
+    f_username.focus();
+  
+  // Post operations: show captcha window
+  if ( show_captcha )
+    ajaxShowCaptcha(show_captcha);
+  
+  // Post operations: stash encryption keys and All That Jazz(TM)
+  logindata.key_aes = data.aes_key;
+  logindata.key_dh = data.dh_public_key;
+  logindata.captcha_hash = show_captcha;
+  
+  // Are we locked out? If so simulate an error and disable the controls
+  if ( data.lockout_info.lockout_policy == 'lockout' && data.locked_out )
+  {
+    f_username.setAttribute('disabled', 'disabled');
+    f_password.setAttribute('disabled', 'disabled');
+    var fake_packet = {
+      error_code: 'locked_out',
+      respawn_info: data
+    };
+    ajaxLoginShowFriendlyError(fake_packet);
+  }
+}
+
+function ajaxLoginSubmitForm(real, username, password, captcha)
+{
+  // Perform AES test to make sure it's all working
+  if ( !aes_self_test() )
+  {
+    alert('BUG: AES self-test failed');
+    login_cache.mb_object.destroy();
+    return false;
+  }
+  // Hide the error message and captcha
+  if ( document.getElementById('ajax_login_error_box') )
+  {
+    document.getElementById('ajax_login_error_box').parentNode.removeChild(document.getElementById('ajax_login_error_box'));
+  }
+  if ( document.getElementById('autoCaptcha') )
+  {
+    var to = fly_out_top(document.getElementById('autoCaptcha'), false, true);
+    setTimeout(function() {
+        var d = document.getElementById('autoCaptcha');
+        d.parentNode.removeChild(d);
+      }, to);
+  }
+  // Encryption: preprocessor
+  if ( real )
+  {
+    var do_dh = true;
+  }
+  else if ( document.getElementById('ajax_login_field_dh') )
+  {
+    var do_dh = document.getElementById('ajax_login_field_dh').checked;
+  }
+  else
+  {
+    // The user probably clicked ok when the form wasn't in there.
+    return false;
+  }
+  if ( !username )
+  {
+    var username = document.getElementById('ajax_login_field_username').value;
+  }
+  if ( !password )
+  {
+    var password = document.getElementById('ajax_login_field_password').value;
+  }
+  if ( !captcha && document.getElementById('ajax_login_field_captcha') )
+  {
+    var captcha = document.getElementById('ajax_login_field_captcha').value;
+  }
+  
+  if ( do_dh )
+  {
+    ajaxLoginSetStatus(AJAX_STATUS_GENERATING_KEY);
+    if ( !real )
+    {
+      // Wait while the browser updates the login window
+      setTimeout(function()
+        {
+          ajaxLoginSubmitForm(true, username, password, captcha);
+        }, 200);
+      return true;
+    }
+    // Perform Diffie Hellman stuff
+    var dh_priv = dh_gen_private();
+    var dh_pub = dh_gen_public(dh_priv);
+    var secret = dh_gen_shared_secret(dh_priv, logindata.key_dh);
+    // secret_hash is used to verify that the server guesses the correct secret
+    var secret_hash = hex_sha1(secret);
+    // crypt_key is the actual AES key
+    var crypt_key = (hex_sha256(secret)).substr(0, (keySizeInBits / 4));
+  }
+  else
+  {
+    var crypt_key = logindata.key_aes;
+  }
+  
+  ajaxLoginSetStatus(AJAX_STATUS_LOGGING_IN);
+  
+  // Encrypt the password and username
+  var userinfo = toJSONString({
+      username: username,
+      password: password
+    });
+  var crypt_key_ba = hexToByteArray(crypt_key);
+  userinfo = stringToByteArray(userinfo);
+  
+  userinfo = rijndaelEncrypt(userinfo, crypt_key_ba, 'ECB');
+  userinfo = byteArrayToHex(userinfo);
+  // Encrypted username and password (serialized with JSON) are now in the userinfo string
+  
+  // Collect other needed information
+  if ( logindata.captcha_hash )
+  {
+    var captcha_hash = logindata.captcha_hash;
+    var captcha_code = captcha;
+  }
+  else
+  {
+    var captcha_hash = false;
+    var captcha_code = false;
+  }
+  
+  // Ship it across the 'net
+  if ( do_dh )
+  {
+    var json_packet = {
+      mode: 'login_dh',
+      userinfo: userinfo,
+      captcha_code: captcha_code,
+      captcha_hash: captcha_hash,
+      dh_public_key: logindata.key_dh,
+      dh_client_key: dh_pub,
+      dh_secret_hash: secret_hash,
+      level: logindata.user_level
+    }
+  }
+  else
+  {
+    var json_packet = {
+      mode: 'login_aes',
+      userinfo: userinfo,
+      captcha_code: captcha_code,
+      captcha_hash: captcha_hash,
+      key_aes: hex_md5(crypt_key),
+      level: logindata.user_level
+    }
+  }
+  ajaxLoginPerformRequest(json_packet);
+}
+
+function ajaxLoginShowFriendlyError(response)
+{
+  if ( !response.respawn_info )
+    return false;
+  if ( !response.error_code )
+    return false;
+  var text = ajaxLoginGetErrorText(response);
+  if ( document.getElementById('ajax_login_error_box') )
+  {
+    // console.info('Reusing existing error-box');
+    document.getElementById('ajax_login_error_box').innerHTML = text;
+    return true;
+  }
+  
+  // console.info('Drawing new error-box');
+  
+  // calculate position for the top of the box
+  var mb_bottom = $('messageBoxButtons').Top() + $('messageBoxButtons').Height();
+  // if the box isn't done flying in yet, just estimate
+  if ( mb_bottom < ( getHeight() / 2 ) )
+  {
+    mb_bottom = ( getHeight() / 2 ) + 120;
+  }
+  var win_bottom = getHeight() + getScrollOffset();
+  var top = mb_bottom + ( ( win_bottom - mb_bottom ) / 2 ) - 32;
+  // left position = 0.2 * window_width, seeing as the box is 60% width this works hackishly but nice and quick
+  var left = getWidth() * 0.2;
+  
+  // create the div
+  var errbox = document.createElement('div');
+  errbox.className = 'error-box-mini';
+  errbox.style.position = 'absolute';
+  errbox.style.width = '60%';
+  errbox.style.top = top + 'px';
+  errbox.style.left = left + 'px';
+  errbox.innerHTML = text;
+  errbox.id = 'ajax_login_error_box';
+  
+  var body = document.getElementsByTagName('body')[0];
+  body.appendChild(errbox);
+}
+
+function ajaxLoginGetErrorText(response)
+{
+  switch ( response.error_code )
+  {
+    default:
+      return $lang.get('user_err_' + response.error_code);
+      break;
+    case 'locked_out':
+      if ( response.respawn_info.lockout_info.lockout_policy == 'lockout' )
+      {
+        return $lang.get('user_err_locked_out', { 
+                  lockout_threshold: response.respawn_info.lockout_info.lockout_threshold,
+                  lockout_duration: response.respawn_info.lockout_info.lockout_duration,
+                  time_rem: response.respawn_info.lockout_info.time_rem,
+                  plural: ( response.respawn_info.lockout_info.time_rem == 1 ) ? '' : $lang.get('meta_plural'),
+                  captcha_blurb: ''
+                });
+        break;
+      }
+    case 'invalid_credentials':
+      var base = $lang.get('user_err_invalid_credentials');
+      if ( response.respawn_info.locked_out )
+      {
+        base += ' ';
+        var captcha_blurb = '';
+        switch(response.respawn_info.lockout_info.lockout_policy)
+        {
+          case 'captcha':
+            captcha_blurb = $lang.get('user_err_locked_out_captcha_blurb');
+            break;
+          case 'lockout':
+            break;
+          default:
+            base += 'WTF? Shouldn\'t be locked out with lockout policy set to disable.';
+            break;
+        }
+        base += $lang.get('user_err_locked_out', { 
+                  captcha_blurb: captcha_blurb,
+                  lockout_threshold: response.respawn_info.lockout_info.lockout_threshold,
+                  lockout_duration: response.respawn_info.lockout_info.lockout_duration,
+                  time_rem: response.respawn_info.lockout_info.time_rem,
+                  plural: ( response.respawn_info.lockout_info.time_rem == 1 ) ? '' : $lang.get('meta_plural')
+                });
+      }
+      else if ( response.respawn_info.lockout_info.lockout_policy == 'lockout' || response.respawn_info.lockout_info.lockout_policy == 'captcha' )
+      {
+        // if we have a lockout policy of captcha or lockout, then warn the user
+        switch ( response.respawn_info.lockout_info.lockout_policy )
+        {
+          case 'captcha':
+            base += $lang.get('user_err_invalid_credentials_lockout', { 
+                fails: response.respawn_info.lockout_info.lockout_fails,
+                lockout_threshold: response.respawn_info.lockout_info.lockout_threshold,
+                lockout_duration: response.respawn_info.lockout_info.lockout_duration
+              });
+            break;
+          case 'lockout':
+            break;
+        }
+      }
+      return base;
+      break;
+  }
+}
+
--- a/includes/clientside/static/misc.js	Fri Feb 22 12:46:51 2008 -0500
+++ b/includes/clientside/static/misc.js	Fri Feb 22 12:51:53 2008 -0500
@@ -38,7 +38,7 @@
   rDnsObj = o;
   rDnsBannerObj = bannerOn('Retrieving reverse DNS info...');
   ajaxGet(stdAjaxPrefix+'&_mode=rdns&ip='+ipaddr, function() {
-      if(ajax.readyState == 4)
+      if ( ajax.readyState == 4 && ajax.status == 200 )
       {
         off = fetch_offset(rDnsObj);
         dim = fetch_dimensions(rDnsObj);
@@ -299,286 +299,13 @@
 
 /*
  * AJAX login box (experimental)
+ * Moved / rewritten in login.js
  */
 
-var ajax_auth_prompt_cache = false;
-var ajax_auth_mb_cache = false;
-var ajax_auth_level_cache = false;
-var ajax_auth_error_string = false;
-
+// Included only for API-compatibility
 function ajaxPromptAdminAuth(call_on_ok, level)
 {
-  if ( typeof(call_on_ok) == 'function' )
-  {
-    ajax_auth_prompt_cache = call_on_ok;
-  }
-  if ( !level )
-    level = USER_LEVEL_MEMBER;
-  ajax_auth_level_cache = level;
-  var loading_win = '<div align="center" style="text-align: center;"> \
-      <p>Fetching an encryption key...</p> \
-      <p><small>Not working? Use the <a href="'+makeUrlNS('Special', 'Login/' + title)+'">alternate login form</a>.</p> \
-      <p><img alt="Please wait..." src="'+scriptPath+'/images/loading-big.gif" /></p> \
-    </div>';
-  var title = ( level > USER_LEVEL_MEMBER ) ? 'You are requesting a sensitive operation.' : 'Please enter your username and password to continue.';
-  ajax_auth_mb_cache = new messagebox(MB_OKCANCEL|MB_ICONLOCK, title, loading_win);
-  ajax_auth_mb_cache.onbeforeclick['OK'] = ajaxValidateLogin;
-  ajaxAuthLoginInnerSetup();
-}
-
-function ajaxAuthLoginInnerSetup()
-{
-  // let's hope this gets the image cached
-  var _ = new Image(32, 32); 
-  _.src = scriptPath + "/images/good.gif";
-  
-  ajaxGet(makeUrlNS('Special', 'Login', 'act=getkey'), function() {
-      if ( ajax.readyState == 4 )
-      {
-        var response = String(ajax.responseText);
-        if ( response.substr(0,1) != '{' )
-        {
-          handle_invalid_json(response);
-          ajax_auth_mb_cache.destroy();
-          return false;
-        }
-        response = parseJSON(response);
-        var level = ajax_auth_level_cache;
-        var form_html = '';
-        var shown_error = false;
-        if ( ajax_auth_error_string )
-        {
-          shown_error = true;
-          form_html += '<div class="error-box-mini" id="ajax_auth_error">' + ajax_auth_error_string + '</div>';
-          ajax_auth_error_string = false;
-        }
-        else if ( level > USER_LEVEL_MEMBER )
-        {
-          form_html += 'Please re-enter your login details, to verify your identity.<br /><br />';
-        }
-        form_html += ' \
-          <form action="#" onsubmit="ajaxValidateLogin(); return false;" name="ajax_login_form"> \
-            <table border="0" align="center"> \
-              <tr> \
-                <td>Username:</td><td><input name="username" tabindex="1" id="ajaxlogin_user" type="text"     size="25" /> \
-              </tr> \
-              <tr> \
-                <td>Password:</td><td><input name="password" tabindex="2" id="ajaxlogin_pass" type="password" size="25" /> \
-              </tr> \
-              <tr> \
-                <td colspan="2" style="text-align: center;"> \
-                  <br /><small>Trouble logging in? Try the <a href="'+makeUrlNS('Special', 'Login/' + title, 'level=' + level)+'">full login form</a>.<br />';
-       if ( level <= USER_LEVEL_MEMBER )
-       {
-         form_html += ' \
-                  Did you <a href="'+makeUrlNS('Special', 'PasswordReset')+'">forget your password</a>?<br /> \
-                  Maybe you need to <a href="'+makeUrlNS('Special', 'Register')+'">create an account</a>.</small>';
-       }
-       form_html += ' \
-                </td> \
-              </tr> \
-            </table> \
-            <input type="hidden" id="ajaxlogin_crypt_key"       value="' + response.key + '" /> \
-            <input type="hidden" id="ajaxlogin_crypt_challenge" value="' + response.challenge + '" /> \
-          </form>';
-        ajax_auth_mb_cache.updateContent(form_html);
-        $('messageBox').object.nextSibling.firstChild.tabindex = '3';
-        if ( typeof(response.username) == 'string' )
-        {
-          $('ajaxlogin_user').object.value = response.username;
-          if ( IE )
-          {
-            setTimeout("document.forms['ajax_login_form'].password.focus();", 200);
-          }
-          else
-          {
-            $('ajaxlogin_pass').object.focus();
-          }
-        }
-        else
-        {
-          if ( IE )
-          {
-            setTimeout("document.forms['ajax_login_form'].username.focus();", 200);
-          }
-          else
-          {
-            $('ajaxlogin_user').object.focus();
-          }
-        }
-        $('ajaxlogin_pass').object.onblur = function(e) { if ( !shift ) $('messageBox').object.nextSibling.firstChild.focus(); };
-        $('ajaxlogin_pass').object.onkeypress = function(e)
-        {
-          // Trigger a form submit when the password field is focused and the user presses enter
-          
-          // IE doesn't give us an event object when it should - check window.event. If that
-          // still fails, give up.
-          if ( !e )
-          {
-            e = window.event;
-          }
-          if ( !e && IE )
-          {
-            return true;
-          }
-          if ( e.keyCode == 13 )
-          {
-            ajaxValidateLogin();
-          }
-        };
-        /*
-        ## This causes the background image to disappear under Fx 2
-        if ( shown_error )
-        {
-          // fade to #FFF4F4
-          var fader = new Spry.Effect.Highlight('ajax_auth_error', {duration: 1000, from: '#FFF4F4', to: '#805600', restoreColor: '#805600', finish: function()
-              {
-                var fader = new Spry.Effect.Highlight('ajax_auth_error', {duration: 3000, from: '#805600', to: '#FFF4F4', restoreColor: '#FFF4F4'});
-                fader.start();
-          }});
-          fader.start();
-        }
-        */
-      }
-    });
-}
-
-function ajaxValidateLogin()
-{
-  var username,password,auth_enabled,crypt_key,crypt_data,challenge_salt,challenge_data;
-  username = document.getElementById('ajaxlogin_user');
-  if ( !username )
-    return false;
-  username = document.getElementById('ajaxlogin_user').value;
-  password = document.getElementById('ajaxlogin_pass').value;
-  auth_enabled = false;
-  
-  disableJSONExts();
-  
-  //
-  // Encryption test
-  //
-  
-  var str = '';
-  for(i=0;i<keySizeInBits/4;i++)
-  {
-    str+='0';
-  }
-  str = hexToByteArray(str);
-  var ct  = rijndaelEncrypt(str, str, 'ECB');
-  ct      = byteArrayToHex(ct);
-  var v;
-  switch(keySizeInBits)
-  {
-    case 128:
-      v = '66e94bd4ef8a2c3b884cfa59ca342b2e';
-      break;
-    case 192:
-      v = 'aae06992acbf52a3e8f4a96ec9300bd7aae06992acbf52a3e8f4a96ec9300bd7';
-      break;
-    case 256:
-      v = 'dc95c078a2408989ad48a21492842087dc95c078a2408989ad48a21492842087';
-      break;
-  }
-  auth_enabled = ( ct == v && md5_vm_test() );
-  if ( !auth_enabled )
-  {
-    alert('Login error: encryption sanity check failed\n');
-    return true;
-  }
-  
-  crypt_key = document.getElementById('ajaxlogin_crypt_key').value;
-  challenge_salt = document.getElementById('ajaxlogin_crypt_challenge').value;
-  
-  var crypt_key_md5 = hex_md5(crypt_key);
-  
-  challenge_data = hex_md5(password + challenge_salt) + challenge_salt;
-  
-  password = stringToByteArray(password);
-  crypt_key = hexToByteArray(crypt_key);
-  
-  crypt_data = rijndaelEncrypt(password, crypt_key, 'ECB');
-  crypt_data = byteArrayToHex(crypt_data);
-  
-  var json_data = {
-    'username' : username,
-    'crypt_key' : crypt_key_md5,
-    'challenge' : challenge_data,
-    'crypt_data' : crypt_data,
-    'level' : ajax_auth_level_cache
-  };
-  
-  json_data = toJSONString(json_data);
-  json_data = encodeURIComponent(json_data);
-  
-  var loading_win = '<div align="center" style="text-align: center;"> \
-      <p>Logging in...</p> \
-      <p><img alt="Please wait..." src="'+scriptPath+'/images/loading-big.gif" /></p> \
-    </div>';
-    
-  ajax_auth_mb_cache.updateContent(loading_win);
-  
-  ajaxPost(makeUrlNS('Special', 'Login', 'act=ajaxlogin'), 'params=' + json_data, function() {
-      if ( ajax.readyState == 4 )
-      {
-        var response = ajax.responseText;
-        if ( response.substr(0,1) != '{' )
-        {
-          alert('Invalid JSON response from server: ' + response);
-          ajaxAuthLoginInnerSetup();
-          return false;
-        }
-        response = parseJSON(response);
-        switch(response.result)
-        {
-          case 'success':
-            var success_win = '<div align="center" style="text-align: center;"> \
-                  <p>Success.</p> \
-                  <p><img alt=" " src="'+scriptPath+'/images/good.gif" /></p> \
-                </div>';
-            ajax_auth_mb_cache.updateContent(success_win);
-            if ( typeof(ajax_auth_prompt_cache) == 'function' )
-            {
-              ajax_auth_prompt_cache(response.key);
-            }
-            break;
-          case 'success_reset':
-            var conf = confirm('You have logged in using a temporary password. Before you can log in, you must finish resetting your password. Do you want to reset your real password now?');
-            if ( conf )
-            {
-              var url = makeUrlNS('Special', 'PasswordReset/stage2/' + response.user_id + '/' + response.temppass);
-              window.location = url;
-            }
-            else
-            {
-              ajaxAuthLoginInnerSetup();
-            }
-            break;
-          case 'error':
-            if ( response.error == 'The username and/or password is incorrect.' )
-            {
-              ajax_auth_error_string = response.error;
-              mb_current_obj.updateContent('');
-              document.getElementById('messageBox').style.backgroundColor = '#C0C0C0';
-              var mb_parent = document.getElementById('messageBox').parentNode;
-              new Spry.Effect.Shake(mb_parent, {duration: 1500}).start();
-              setTimeout("document.getElementById('messageBox').style.backgroundColor = '#FFF'; ajaxAuthLoginInnerSetup();", 2500);
-            }
-            else
-            {
-              alert(response.error);
-              ajaxAuthLoginInnerSetup();
-            }
-            break;
-          default:
-            alert(ajax.responseText);
-            break;
-        }
-      }
-    });
-  
-  return true;
-  
+  ajaxLogonInit(call_on_ok, level);
 }
 
 // This code is in the public domain. Feel free to link back to http://jan.moesen.nu/
@@ -674,3 +401,181 @@
   return ( email.match(/^(?:[\w\d_-]+\.?)+@((?:(?:[\w\d_-]\-?)+\.)+\w{2,4}|localhost)$/) ) ? true : false;
 }
 
+/**
+ * Validates a username.
+ * @param string Username to test
+ * @return bool
+ */
+
+function validateUsername(username)
+{
+  var regex = new RegExp('^[^<>&\?\'"%\n\r/]+$', '');
+  return ( username.match(regex) ) ? true : false;
+}
+
+/**
+ * Equivalent of PHP's time()
+ * @return int
+ */
+
+function unix_time()
+{
+  return parseInt((new Date()).getTime()/1000);
+}
+
+/*
+ * Utility functions, moved from windows.js
+ */
+ 
+// getElementWidth() and getElementHeight()
+// Source: http://www.aspandjavascript.co.uk/javascript/javascript_api/get_element_width_height.asp
+
+function getElementHeight(Elem) {
+  if (ns4) 
+  {
+    var elem = getObjNN4(document, Elem);
+    return elem.clip.height;
+  } 
+  else
+  {
+    if(document.getElementById) 
+    {
+      var elem = document.getElementById(Elem);
+    }
+    else if (document.all)
+    {
+      var elem = document.all[Elem];
+    }
+    if (op5) 
+    { 
+      xPos = elem.style.pixelHeight;
+    }
+    else
+    {
+      xPos = elem.offsetHeight;
+    }
+    return xPos;
+  } 
+}
+
+function getElementWidth(Elem) {
+  if (ns4) {
+    var elem = getObjNN4(document, Elem);
+    return elem.clip.width;
+  } else {
+    if(document.getElementById) {
+      var elem = document.getElementById(Elem);
+    } else if (document.all){
+      var elem = document.all[Elem];
+    }
+    if (op5) {
+      xPos = elem.style.pixelWidth;
+    } else {
+      xPos = elem.offsetWidth;
+    }
+    return xPos;
+  }
+}
+
+function getHeight() {
+  var myHeight = 0;
+  if( typeof( window.innerWidth ) == 'number' ) {
+    myHeight = window.innerHeight;
+  } else if( document.documentElement &&
+      ( document.documentElement.clientWidth || document.documentElement.clientHeight ) ) {
+    myHeight = document.documentElement.clientHeight;
+  } else if( document.body && ( document.body.clientWidth || document.body.clientHeight ) ) {
+    myHeight = document.body.clientHeight;
+  }
+  return myHeight;
+}
+
+function getWidth() {
+  var myWidth = 0;
+  if( typeof( window.innerWidth ) == 'number' ) {
+    myWidth = window.innerWidth;
+  } else if( document.documentElement &&
+      ( document.documentElement.clientWidth || document.documentElement.clientWidth ) ) {
+    myWidth = document.documentElement.clientWidth;
+  } else if( document.body && ( document.body.clientWidth || document.body.clientWidth ) ) {
+    myWidth = document.body.clientWidth;
+  }
+  return myWidth;
+}
+
+/**
+ * Sanitizes a page URL string so that it can safely be stored in the database.
+ * @param string Page ID to sanitize
+ * @return string Cleaned text
+ */
+
+function sanitize_page_id(page_id)
+{
+  // Remove character escapes
+  page_id = dirtify_page_id(page_id);
+
+  var regex = new RegExp('[A-Za-z0-9\\[\\]\./:;\(\)@_-]', 'g');
+  pid_clean = page_id.replace(regex, 'X');
+  var pid_dirty = [];
+  for ( var i = 0; i < pid_clean.length; i++ )
+    pid_dirty[i] = pid_clean.substr(i, 1);
+
+  for ( var i = 0; i < pid_dirty.length; i++ )
+  {
+    var char = pid_dirty[i];
+    if ( char == 'X' )
+      continue;
+    var cid = char.charCodeAt(0);
+    cid = cid.toString(16).toUpperCase();
+    if ( cid.length < 2 )
+    {
+      cid = '0' + cid;
+    }
+    pid_dirty[i] = "." + cid;
+  }
+  
+  var pid_chars = [];
+  for ( var i = 0; i < page_id.length; i++ )
+    pid_chars[i] = page_id.substr(i, 1);
+  
+  var page_id_cleaned = '';
+
+  for ( var id in pid_chars )
+  {
+    var char = pid_chars[id];
+    if ( pid_dirty[id] == 'X' )
+      page_id_cleaned += char;
+    else
+      page_id_cleaned += pid_dirty[id];
+  }
+  
+  return page_id_cleaned;
+}
+
+/**
+ * Removes character escapes in a page ID string
+ * @param string Page ID string to dirty up
+ * @return string
+ */
+
+function dirtify_page_id(page_id)
+{
+  // First, replace spaces with underscores
+  page_id = page_id.replace(/ /g, '_');
+
+  var matches = page_id.match(/\.[A-Fa-f0-9][A-Fa-f0-9]/g);
+  
+  if ( matches != null )
+  {
+    for ( var i = 0; i < matches.length; i++ )
+    {
+      var match = matches[i];
+      var byt = (match.substr(1)).toUpperCase();
+      var code = eval("0x" + byt);
+      var regex = new RegExp('\\.' + byt, 'g');
+      page_id = page_id.replace(regex, String.fromCharCode(code));
+    }
+  }
+  
+  return page_id;
+}
--- a/includes/clientside/static/paginate.js	Fri Feb 22 12:46:51 2008 -0500
+++ b/includes/clientside/static/paginate.js	Fri Feb 22 12:51:53 2008 -0500
@@ -68,7 +68,7 @@
 function _build_paginator(this_page)
 {
   var div_styling = ( IE ) ? 'width: 1px; margin: 10px auto 10px 0;' : 'display: table; margin: 10px 0 0 auto;';
-  var begin = '<div class="tblholder" style="'+div_styling+'"><table border="0" cellspacing="1" cellpadding="4"><tr><th>Page:</th>';
+  var begin = '<div class="tblholder" style="'+div_styling+'"><table border="0" cellspacing="1" cellpadding="4"><tr><th>' + $lang.get('paginate_lbl_page') + '</th>';
   var block = '<td class="row1" style="text-align: center; white-space: nowrap;">{LINK}</td>';
   var end = '</tr></table></div>';
   var blk = new templateParser(block);
@@ -78,7 +78,7 @@
   if ( this_page > 0 )
   {
     var url = '#page_'+(this_page);
-    var link = "<a href=\""+url+"\" onclick=\"jspaginator_goto('"+this.random_id+"', "+(this_page-1)+"); return false;\" style='text-decoration: none;'>&laquo; Prev</a>";
+    var link = "<a href=\""+url+"\" onclick=\"jspaginator_goto('"+this.random_id+"', "+(this_page-1)+"); return false;\" style='text-decoration: none;'>&laquo; " + $lang.get('paginate_btn_prev') + "</a>";
     cls = ( cls == 'row1' ) ? 'row2' : 'row1';
     blk.assign_vars({
         CLASS: cls,
@@ -126,7 +126,7 @@
       }
     }
     var url = '#page_1';
-    var link = ( 0 == this_page ) ? "<b>First</b>" : "<a href=\""+url+"\" onclick=\"jspaginator_goto('"+this.random_id+"', 0); return false;\" style='text-decoration: none;'>&laquo; First</a>";
+    var link = ( 0 == this_page ) ? "<b>" + $lang.get('paginate_btn_first') + "</b>" : "<a href=\""+url+"\" onclick=\"jspaginator_goto('"+this.random_id+"', 0); return false;\" style='text-decoration: none;'>&laquo; " + $lang.get('paginate_btn_first') + "</a>";
     blk.assign_vars({
         CLASS: cls,
         LINK: link
@@ -164,7 +164,7 @@
 
       cls = ( cls == 'row1' ) ? 'row2' : 'row1';
       var url = '#page_' + String( this.num_pages-1 );
-      var link = ( ( this.num_pages - 1 ) == this_page ) ? "<b>Last</b>" : "<a href=\""+url+"\" onclick=\"jspaginator_goto('"+this.random_id+"', "+(this.num_pages-1)+"); return false;\" style='text-decoration: none;'>Last &raquo;</a>";
+      var link = ( ( this.num_pages - 1 ) == this_page ) ? "<b>" + $lang.get('paginate_btn_last') + "</b>" : "<a href=\""+url+"\" onclick=\"jspaginator_goto('"+this.random_id+"', "+(this.num_pages-1)+"); return false;\" style='text-decoration: none;'>" + $lang.get('paginate_btn_last') + " &raquo;</a>";
       blk.assign_vars({
           CLASS: cls,
           LINK: link
@@ -177,7 +177,7 @@
   if ( this_page < ( this.num_pages - 1 ) )
   {
     var url = '#page_' + String(this_page + 2);
-    var link = "<a href=\""+url+"\" onclick=\"jspaginator_goto('"+this.random_id+"', "+(this_page+1)+"); return false;\" style='text-decoration: none;'>Next &raquo;</a>";
+    var link = "<a href=\""+url+"\" onclick=\"jspaginator_goto('"+this.random_id+"', "+(this_page+1)+"); return false;\" style='text-decoration: none;'>" + $lang.get('paginate_btn_next') + " &raquo;</a>";
     cls = ( cls == 'row1' ) ? 'row2' : 'row1';
     blk.assign_vars({
           CLASS: cls,
@@ -269,10 +269,10 @@
 
 function paginator_goto(parentobj, this_page, num_pages, perpage, url_string)
 {
-  var height = $(parentobj).Height();
-  var width  = $(parentobj).Width();
-  var left   = $(parentobj).Left();
-  var top    = $(parentobj).Top();
+  var height = $dynano(parentobj).Height();
+  var width  = $dynano(parentobj).Width();
+  var left   = $dynano(parentobj).Left();
+  var top    = $dynano(parentobj).Top();
   var left_pos = left + width ;
   var top_pos = height + top;
   var div = document.createElement('div');
@@ -284,14 +284,18 @@
   var regex = new RegExp('\"', 'g');
   var submit_target = ( typeof(url_string) == 'object' ) ? ( toJSONString(url_string) ).replace(regex, '\'') : 'unescape(\'' + escape(url_string) + '\')';
   var onclick = 'paginator_submit(this, '+num_pages+', '+perpage+', '+submit_target+'); return false;';
-  div.innerHTML = 'Go to page:<br /><input type="text" size="2" style="padding: 1px; font-size: 8pt;" value="'+(parseInt(this_page)+1)+'" id="'+vtmp+'" />&emsp;<a href="#" onclick="'+onclick+'" style="font-size: 14pt; text-decoration: none;">&raquo;</a>&emsp;<a href="#" onclick="fly_out_top(this.parentNode, false, true); return false;" style="font-size: 14pt; text-decoration: none;">&times;</a>';
+  div.innerHTML = $lang.get('paginate_lbl_goto_page') + '<br /><input type="text" size="2" style="padding: 1px; font-size: 8pt;" value="'+(parseInt(this_page)+1)+'" id="'+vtmp+'" />&emsp;<a href="#" onclick="'+onclick+'" style="font-size: 14pt; text-decoration: none;">&raquo;</a>&emsp;<a href="#" onclick="var _pn = this.parentNode; setTimeout(function() { _pn.parentNode.removeChild(_pn); }, 2000); fly_out_top(this.parentNode, false, true); return false;" style="font-size: 14pt; text-decoration: none;">&times;</a>';
   
   var body = document.getElementsByTagName('body')[0];
   domObjChangeOpac(0, div);
   
   body.appendChild(div);
   
-  document.getElementById(vtmp).onkeypress = function(e){if(e.keyCode==13)this.nextSibling.nextSibling.onclick();};
+  document.getElementById(vtmp).onkeypress = function(e)
+    {
+      if ( e.keyCode == 13 )
+        this.nextSibling.nextSibling.onclick();
+    };
   document.getElementById(vtmp).focus();
   
   // fade the div
@@ -303,7 +307,7 @@
   
   fly_in_bottom(div, false, true);
   
-  var divh = $(div).Width();
+  var divh = $dynano(div).Width();
   left_pos = left_pos - divh;
   div.style.left = left_pos + 'px';
 }
@@ -315,7 +319,7 @@
   var offset = ( userinput - 1 ) * perpage;
   if ( userinput > max || isNaN(userinput) || userinput < 1 )
   {
-    new messagebox(MB_OK|MB_ICONSTOP, 'Invalid entry', 'Please enter a page number between 1 and ' + max + '.');
+    new messagebox(MB_OK|MB_ICONSTOP, $lang.get('paginate_err_bad_page_title'), $lang.get('paginate_err_bad_page_body', { max: max }));
     return false;
   }
   if ( typeof(formatstring) == 'object' )
--- a/includes/clientside/static/pwstrength.js	Fri Feb 22 12:46:51 2008 -0500
+++ b/includes/clientside/static/pwstrength.js	Fri Feb 22 12:51:53 2008 -0500
@@ -181,9 +181,9 @@
     debug_txt += debug[i] + "\n";
   }
   
-  if ( window.console )
-    window.console.info(debug_txt);
-  else if ( document.getElementById('passdebug') )
+  // For users that really want to know why their password sucks.
+  // Not localized because the feature is really only used for debugging the algorithm.
+  if ( document.getElementById('passdebug') )
     document.getElementById('passdebug').innerHTML = debug_txt;
   
   return score;
@@ -191,36 +191,53 @@
 
 function password_score_draw(score)
 {
+  if ( !$lang )
+  {
+    // $lang isn't initted yet, this happens sometimes on the usercp/emailpassword form.
+    // Try to init it if we have ENANO_LANG_ID and enano_lang; if not, report an error.
+    if ( typeof(enano_lang) == 'object' && typeof(ENANO_LANG_ID) == 'number' )
+    {
+      language_onload();
+    }
+    else
+    {
+      return {
+        color: '#000000',
+        fgcolor: '#666666',
+        str: 'Language init failed',
+      };
+    }
+  }
   // some colors are from the Gmail sign-up form
   if ( score >= 10 )
   {
     var color = '#000000';
     var fgcolor = '#666666';
-    var str = 'Very strong (score: '+score+')';
+    var str = $lang.get('usercp_pwstrength_score_verystrong', { score: score });
   }
   else if ( score > 3 )
   {
     var color = '#008000';
     var fgcolor = '#004000';
-    var str = 'Strong (score: '+score+')';
+    var str = $lang.get('usercp_pwstrength_score_strong', { score: score });
   }
   else if ( score >= 1 )
   {
     var color = '#6699cc';
     var fgcolor = '#4477aa';
-    var str = 'Good (score: '+score+')';
+    var str = $lang.get('usercp_pwstrength_score_good', { score: score });
   }
   else if ( score >= -3 )
   {
     var color = '#f5ac00';
     var fgcolor = '#ffcc33';
-    var str = 'Fair (score: '+score+')';
+    var str = $lang.get('usercp_pwstrength_score_fair', { score: score });
   }
   else
   {
     var color = '#aa0033';
     var fgcolor = '#FF6060';
-    var str = 'Weak (score: '+score+')';
+    var str = $lang.get('usercp_pwstrength_score_weak', { score: score });
   }
   return {
     color: color,
--- a/includes/clientside/static/rijndael.js	Fri Feb 22 12:46:51 2008 -0500
+++ b/includes/clientside/static/rijndael.js	Fri Feb 22 12:51:53 2008 -0500
@@ -577,3 +577,34 @@
   return result;
 }
 
+function aes_self_test()
+{
+  //
+  // Encryption test
+  //
+  
+  var str = '';
+  for(i=0;i<keySizeInBits/4;i++)
+  {
+    str+='0';
+  }
+  str = hexToByteArray(str);
+  var ct  = rijndaelEncrypt(str, str, 'ECB');
+  ct      = byteArrayToHex(ct);
+  var v;
+  switch(keySizeInBits)
+  {
+    // These test vectors are for 128-bit block size.
+    case 128:
+      v = '66e94bd4ef8a2c3b884cfa59ca342b2e';
+      break;
+    case 192:
+      v = 'aae06992acbf52a3e8f4a96ec9300bd7aae06992acbf52a3e8f4a96ec9300bd7';
+      break;
+    case 256:
+      v = 'dc95c078a2408989ad48a21492842087dc95c078a2408989ad48a21492842087';
+      break;
+  }
+  return ( ct == v && md5_vm_test() );
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/includes/clientside/static/sha256.js	Fri Feb 22 12:51:53 2008 -0500
@@ -0,0 +1,84 @@
+/* A JavaScript implementation of the Secure Hash Algorithm, SHA-256
+ * Version 0.3 Copyright Angel Marin 2003-2004 - http://anmar.eu.org/
+ * Distributed under the BSD License
+ * Some bits taken from Paul Johnston's SHA-1 implementation
+ */
+/*
+Copyright (c) 2003-2004, Angel Marin
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice, this
+   list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright notice,
+   this list of conditions and the following disclaimer in the documentation
+   and/or other materials provided with the distribution.
+ * Neither the name of the <ORGANIZATION> nor the names of its contributors may
+   be used to endorse or promote products derived from this software without
+   specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+OF THE POSSIBILITY OF SUCH DAMAGE.
*/
+var chrsz = 8;  /* bits per input character. 8 - ASCII; 16 - Unicode  */
+function safe_add (x, y) {
+  var lsw = (x & 0xFFFF) + (y & 0xFFFF);
+  var msw = (x >> 16) + (y >> 16) + (lsw >> 16);
+  return (msw << 16) | (lsw & 0xFFFF);
+}
+function S (X, n) {return ( X >>> n ) | (X << (32 - n));}
+function R (X, n) {return ( X >>> n );}
+function Ch(x, y, z) {return ((x & y) ^ ((~x) & z));}
+function Maj(x, y, z) {return ((x & y) ^ (x & z) ^ (y & z));}
+function Sigma0256(x) {return (S(x, 2) ^ S(x, 13) ^ S(x, 22));}
+function Sigma1256(x) {return (S(x, 6) ^ S(x, 11) ^ S(x, 25));}
+function Gamma0256(x) {return (S(x, 7) ^ S(x, 18) ^ R(x, 3));}
+function Gamma1256(x) {return (S(x, 17) ^ S(x, 19) ^ R(x, 10));}
+function core_sha256 (m, l) {
+    var K = new Array(0x428A2F98,0x71374491,0xB5C0FBCF,0xE9B5DBA5,0x3956C25B,0x59F111F1,0x923F82A4,0xAB1C5ED5,0xD807AA98,0x12835B01,0x243185BE,0x550C7DC3,0x72BE5D74,0x80DEB1FE,0x9BDC06A7,0xC19BF174,0xE49B69C1,0xEFBE4786,0xFC19DC6,0x240CA1CC,0x2DE92C6F,0x4A7484AA,0x5CB0A9DC,0x76F988DA,0x983E5152,0xA831C66D,0xB00327C8,0xBF597FC7,0xC6E00BF3,0xD5A79147,0x6CA6351,0x14292967,0x27B70A85,0x2E1B2138,0x4D2C6DFC,0x53380D13,0x650A7354,0x766A0ABB,0x81C2C92E,0x92722C85,0xA2BFE8A1,0xA81A664B,0xC24B8B70,0xC76C51A3,0xD192E819,0xD6990624,0xF40E3585,0x106AA070,0x19A4C116,0x1E376C08,0x2748774C,0x34B0BCB5,0x391C0CB3,0x4ED8AA4A,0x5B9CCA4F,0x682E6FF3,0x748F82EE,0x78A5636F,0x84C87814,0x8CC70208,0x90BEFFFA,0xA4506CEB,0xBEF9A3F7,0xC67178F2);
+    var HASH = new Array(0x6A09E667, 0xBB67AE85, 0x3C6EF372, 0xA54FF53A, 0x510E527F, 0x9B05688C, 0x1F83D9AB, 0x5BE0CD19);
+    var W = new Array(64);
+    var a, b, c, d, e, f, g, h, i, j;
+    var T1, T2;
+    /* append padding */
+    m[l >> 5] |= 0x80 << (24 - l % 32);
+    m[((l + 64 >> 9) << 4) + 15] = l;
+    for ( var i = 0; i<m.length; i+=16 ) {
+        a = HASH[0]; b = HASH[1]; c = HASH[2]; d = HASH[3]; e = HASH[4]; f = HASH[5]; g = HASH[6]; h = HASH[7];
+        for ( var j = 0; j<64; j++) {
+            if (j < 16) W[j] = m[j + i];
+            else W[j] = safe_add(safe_add(safe_add(Gamma1256(W[j - 2]), W[j - 7]), Gamma0256(W[j - 15])), W[j - 16]);
+            T1 = safe_add(safe_add(safe_add(safe_add(h, Sigma1256(e)), Ch(e, f, g)), K[j]), W[j]);
+            T2 = safe_add(Sigma0256(a), Maj(a, b, c));
+            h = g; g = f; f = e; e = safe_add(d, T1); d = c; c = b; b = a; a = safe_add(T1, T2);
+        }
+        HASH[0] = safe_add(a, HASH[0]); HASH[1] = safe_add(b, HASH[1]); HASH[2] = safe_add(c, HASH[2]); HASH[3] = safe_add(d, HASH[3]); HASH[4] = safe_add(e, HASH[4]); HASH[5] = safe_add(f, HASH[5]); HASH[6] = safe_add(g, HASH[6]); HASH[7] = safe_add(h, HASH[7]);
+    }
+    return HASH;
+}
+function str2binb (str) {
+  var bin = Array();
+  var mask = (1 << chrsz) - 1;
+  for(var i = 0; i < str.length * chrsz; i += chrsz)
+    bin[i>>5] |= (str.charCodeAt(i / chrsz) & mask) << (24 - i%32);
+  return bin;
+}
+function binb2hex (binarray) {
+  var hexcase = 0; /* hex output format. 0 - lowercase; 1 - uppercase */
+  var hex_tab = hexcase ? "0123456789ABCDEF" : "0123456789abcdef";
+  var str = "";
+  for (var i = 0; i < binarray.length * 4; i++) {
+    str += hex_tab.charAt((binarray[i>>2] >> ((3 - i%4)*8+4)) & 0xF) + hex_tab.charAt((binarray[i>>2] >> ((3 - i%4)*8  )) & 0xF);
+  }
+  return str;
+}
+function hex_sha256(s){return binb2hex(core_sha256(str2binb(s),s.length * chrsz));}
--- a/includes/clientside/static/sliders.js	Fri Feb 22 12:46:51 2008 -0500
+++ b/includes/clientside/static/sliders.js	Fri Feb 22 12:51:53 2008 -0500
@@ -30,6 +30,9 @@
         // use cookies to toggle whether to display it or not
         var id = ( divs[i].parentNode.firstChild.nextSibling ) ? divs[i].parentNode.firstChild.nextSibling.firstChild : divs[i].parentNode.parentNode.firstChild.nextSibling.firstChild;
         
+        if ( !id.nextSibling )
+          return;
+        
         if(id.innerHTML || id.nextSibling.length < 1) id = id.innerHTML;
         else id = id.nextSibling.innerHTML; // Gecko fix
         
--- a/includes/clientside/static/template-compiler.js	Fri Feb 22 12:46:51 2008 -0500
+++ b/includes/clientside/static/template-compiler.js	Fri Feb 22 12:51:53 2008 -0500
@@ -54,6 +54,7 @@
   code = code.replace(new RegExp(unescape('%0A'), 'g'), '\\n');
   code = "'" + code + "'";
   code = code.replace(/\{([A-z0-9_-]+)\}/ig, "' + this.tpl_strings['$1'] + '");
+  code = code.replace(/\{lang:([a-z0-9_]+)\}/g, "' + $lang.get('$1') + '");
   code = code.replace(/\<!-- BEGIN ([A-z0-9_-]+) --\>([\s\S]*?)\<!-- BEGINELSE \1 --\>([\s\S]*?)\<!-- END \1 --\>/ig, "' + ( ( this.tpl_bool['$1'] == true ) ? '$2' : '$3' ) + '");
   code = code.replace(/\<!-- BEGIN ([A-z0-9_-]+) --\>([\s\S]*?)\<!-- END \1 --\>/ig, "' + ( ( this.tpl_bool['$1'] == true ) ? '$2' : '' ) + '");
   return code;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/includes/clientside/static/theme-manager.js	Fri Feb 22 12:51:53 2008 -0500
@@ -0,0 +1,216 @@
+function ajaxToggleSystemThemes()
+{
+  var theme_list = document.getElementById('theme_list_edit');
+  var mode = ( theme_list.sys_shown ) ? 'hide' : 'show';
+  for ( var i = 0; i < theme_list.childNodes.length; i++ )
+  {
+    var child = theme_list.childNodes[i];
+    if ( child.tagName == 'DIV' )
+    {
+      if ( $(child).hasClass('themebutton_theme_system') )
+      {
+        if ( $(child).hasClass('themebutton_theme_disabled') )
+        {
+          $(child).rmClass('themebutton_theme_disabled')
+        }
+        if ( mode == 'show' )
+        {
+          domObjChangeOpac(0, child);
+          child.style.display = 'block';
+          domOpacity(child, 0, 100, 1000);
+        }
+        else
+        {
+          domOpacity(child, 100, 0, 1000);
+          setTimeout("document.getElementById('" + child.id + "').style.display = 'none';", 1050);
+        }
+      }
+    }
+  }
+  theme_list.sys_shown = ( mode == 'show' );
+  document.getElementById('systheme_toggler').innerHTML = ( mode == 'hide' ) ? $lang.get('acptm_btn_system_themes_show') : $lang.get('acptm_btn_system_themes_hide');
+}
+
+function ajaxInstallTheme(theme_id)
+{
+  var thediv = document.getElementById('themebtn_install_' + theme_id);
+  if ( !thediv )
+    return false;
+  thediv.removeChild(thediv.getElementsByTagName('a')[0]);
+  var status = document.createElement('div');
+  status.className = 'status';
+  thediv.appendChild(status);
+  setTimeout(function()
+    {
+      var theme_list = document.getElementById('theme_list_edit');
+      
+      var btn = document.createElement('div');
+      btn.className = 'themebutton';
+      btn.style.backgroundImage = thediv.style.backgroundImage;
+      btn.id = 'themebtn_edit_' + theme_id;
+      
+      var a = document.createElement('a');
+      a.className = 'tb-inner';
+      a.appendChild(document.createTextNode($lang.get('acptm_btn_theme_edit')));
+      a.appendChild(document.createTextNode("\n"));
+      a.theme_id = theme_id;
+      a.onclick = function()
+      {
+        ajaxEditTheme(this.theme_id);
+        return false;
+      }
+      a.href = '#';
+      var span = document.createElement('span');
+      span.className = 'themename';
+      span.appendChild(document.createTextNode(thediv.getAttribute('enano:themename')));
+      a.appendChild(span);
+      btn.appendChild(a);
+      btn.setAttribute('enano:themename', thediv.getAttribute('enano:themename'));
+      theme_list.appendChild(btn);
+      
+      thediv.parentNode.removeChild(thediv);
+    }, 3000);
+}
+
+function ajaxEditTheme(theme_id)
+{
+  // Fade out and subsequently destroy the entire list, then make an
+  // ajax request to the theme manager for the theme info via JSON
+  var theme_list = document.getElementById('theme_list_edit').parentNode;
+  var backgroundImage = document.getElementById('themebtn_edit_' + theme_id).style.backgroundImage;
+  for ( var i = 0; i < theme_list.childNodes.length; i++ )
+  {
+    var el = theme_list.childNodes[i];
+    if ( el.tagName )
+      domOpacity(el, 100, 0, 1000);
+  }
+  setTimeout(function()
+    {
+      theme_list.innerHTML = '';
+      var req = toJSONString({
+          mode: 'fetch_theme',
+          theme_id: theme_id
+        });
+      // we've finished nukeing the existing interface, request editor data
+      ajaxPost(makeUrlNS('Admin', 'ThemeManager/action.json'), 'r=' + ajaxEscape(req), function()
+        {
+          if ( ajax.readyState == 4 && ajax.status == 200 )
+          {
+            var response = String(ajax.responseText + '');
+            if ( response.substr(0, 1) != '{' )
+            {
+              alert(response);
+              return false;
+            }
+            response = parseJSON(response);
+            if ( response.mode == 'error' )
+            {
+              alert(response.error);
+              return false;
+            }
+            response.background_image = backgroundImage;
+            ajaxBuildThemeEditor(response, theme_list);
+          }
+        });
+    }, 1050);
+}
+
+function ajaxBuildThemeEditor(data, target)
+{
+  // Build the theme editor interface
+  // Init opacity
+  domObjChangeOpac(0, target);
+  
+  // Theme preview
+  var preview = document.createElement('div');
+  preview.style.border = '1px solid #F0F0F0';
+  preview.style.padding = '5px';
+  preview.style.width = '216px';
+  preview.style.height = '150px';
+  preview.style.backgroundImage = data.background_image;
+  preview.style.backgroundRepeat = 'no-repeat';
+  preview.style.backgroundPosition = 'center center';
+  preview.style.cssFloat = 'right';
+  preview.style.styleFloat = 'right';
+  
+  target.appendChild(preview);
+  
+  // Heading
+  var h3 = document.createElement('h3');
+  h3.appendChild(document.createTextNode($lang.get('acptm_heading_theme_edit', { theme_name: data.theme_name })));
+  target.appendChild(h3);
+  
+  // Field: Theme name
+  var l_name = document.createElement('label');
+  l_name.appendChild(document.createTextNode($lang.get('acptm_field_theme_name') + ' '));
+  var f_name = document.createElement('input');
+  f_name.type = 'text';
+  f_name.id = 'themeed_field_name';
+  f_name.value = data.theme_name;
+  f_name.size = '40';
+  l_name.appendChild(f_name);
+  target.appendChild(l_name);
+  
+  target.appendChild(document.createElement('br'));
+  
+  // Field: default style
+  var l_style = document.createElement('label');
+  l_style.appendChild(document.createTextNode($lang.get('acptm_field_default_style') + ' '));
+  var f_style = document.createElement('select');
+  f_style.id = 'themeed_field_style';
+  var opts = [];
+  for ( var i = 0; i < data.css.length; i++ )
+  {
+    if ( data.css[i] == '_printable' )
+      continue;
+    
+    opts[i] = document.createElement('option');
+    opts[i].value = data.css[i];
+    opts[i].appendChild(document.createTextNode(data.css[i]));
+    if ( data.default_style == data.css[i] )
+    {
+      opts[i].selected = true;
+    }
+    f_style.appendChild(opts[i]);
+  }
+  l_style.appendChild(f_style);
+  target.appendChild(l_style);
+  
+  target.appendChild(document.createElement('br'));
+  
+  // Default theme
+  target.appendChild(document.createTextNode($lang.get('acptm_field_default_theme') + ' '));
+  if ( data.is_default )
+  {
+    var l_default = document.createElement('b');
+    l_default.appendChild(document.createTextNode($lang.get('acptm_field_default_msg_current')));
+  }
+  else
+  {
+    var l_default = document.createElement('label');
+    var f_default = document.createElement('input');
+    f_default.type = 'checkbox';
+    f_default.id = 'themeed_field_default';
+    l_default.appendChild(f_default);
+    l_default.appendChild(document.createTextNode($lang.get('acptm_field_default_btn_make_default')));
+  }
+  target.appendChild(l_default);
+  
+  // Availability policy
+  var h3 = document.createElement('h3');
+  h3.appendChild(document.createTextNode($lang.get('acptm_heading_theme_groups')));
+  target.appendChild(h3);
+  
+  for ( var i = 0; i < data.group_list.length; i++ )
+  {
+    
+  }
+  
+  var clearer = document.createElement('span');
+  clearer.className = 'menuclear';
+  target.appendChild(clearer);
+  
+  // Fade it all in
+  domOpacity(target, 0, 100, 500);
+  f_name.focus();
+}
--- a/includes/clientside/static/toolbar.js	Fri Feb 22 12:46:51 2008 -0500
+++ b/includes/clientside/static/toolbar.js	Fri Feb 22 12:51:53 2008 -0500
@@ -9,7 +9,7 @@
   {
     if(obj.id == 'mdgToolbar_article' || obj.id == 'mdgToolbar_discussion')
     {
-      $(obj).rmClass('selected');
+      $dynano(obj).rmClass('selected');
     }
     obj = obj.nextSibling;
   }
@@ -22,7 +22,7 @@
   obj = document.getElementById('pagebar_main').firstChild.nextSibling;
   while(obj)
   {
-    if ( !$(obj).hasClass('selected') )
+    if ( !$dynano(obj).hasClass('selected') )
     {
       obj = obj.nextSibling;
       continue;
@@ -30,7 +30,7 @@
     if(obj.id != 'mdgToolbar_article' && obj.id != 'mdgToolbar_discussion')
     {
       if ( obj.className )
-        $(obj).rmClass('selected');
+        $dynano(obj).rmClass('selected');
     }
     obj = obj.nextSibling;
   }
@@ -46,7 +46,7 @@
   if(typeof(dom) == 'object')
   {
     unselectAllButtonsMajor();
-    $('mdgToolbar_'+which).addClass('selected');
+    $dynano('mdgToolbar_'+which).addClass('selected');
   }
 }
 
@@ -57,7 +57,7 @@
   if(typeof(document.getElementById('mdgToolbar_'+which)) == 'object')
   {
     unselectAllButtonsMinor();
-    $('mdgToolbar_'+which).addClass('selected');
+    $dynano('mdgToolbar_'+which).addClass('selected');
   }
 }
 
--- a/includes/clientside/static/windows.js	Fri Feb 22 12:46:51 2008 -0500
+++ b/includes/clientside/static/windows.js	Fri Feb 22 12:51:53 2008 -0500
@@ -6,23 +6,6 @@
  */
 
   var position;
-  function getScrollOffset()
-  {
-    var position;
-    if (self.pageYOffset)
-    {
-      position = self.pageYOffset;
-    }
-    else if (document.documentElement && document.documentElement.scrollTop)
-    {
-      position = document.documentElement.scrollTop;
-    }
-    else if (document.body)
-    {
-      position = document.body.scrollTop;
-    }
-    return position;
-  }
   position = getScrollOffset();
   
   var jws = {
@@ -150,86 +133,6 @@
 
 //window.onscroll=jws['scrollHandler'];
 
-/*
- * Utility functions
- */
- 
-// getElementWidth() and getElementHeight()
-// Source: http://www.aspandjavascript.co.uk/javascript/javascript_api/get_element_width_height.asp
-
-function getElementHeight(Elem) {
-  if (ns4) 
-  {
-    var elem = getObjNN4(document, Elem);
-    return elem.clip.height;
-  } 
-  else
-  {
-    if(document.getElementById) 
-    {
-      var elem = document.getElementById(Elem);
-    }
-    else if (document.all)
-    {
-      var elem = document.all[Elem];
-    }
-    if (op5) 
-    { 
-      xPos = elem.style.pixelHeight;
-    }
-    else
-    {
-      xPos = elem.offsetHeight;
-    }
-    return xPos;
-  } 
-}
-
-function getElementWidth(Elem) {
-  if (ns4) {
-    var elem = getObjNN4(document, Elem);
-    return elem.clip.width;
-  } else {
-    if(document.getElementById) {
-      var elem = document.getElementById(Elem);
-    } else if (document.all){
-      var elem = document.all[Elem];
-    }
-    if (op5) {
-      xPos = elem.style.pixelWidth;
-    } else {
-      xPos = elem.offsetWidth;
-    }
-    return xPos;
-  }
-}
-
-function getHeight() {
-  var myHeight = 0;
-  if( typeof( window.innerWidth ) == 'number' ) {
-    myHeight = window.innerHeight;
-  } else if( document.documentElement &&
-      ( document.documentElement.clientWidth || document.documentElement.clientHeight ) ) {
-    myHeight = document.documentElement.clientHeight;
-  } else if( document.body && ( document.body.clientWidth || document.body.clientHeight ) ) {
-    myHeight = document.body.clientHeight;
-  }
-  return myHeight;
-}
-
-function getWidth() {
-  var myWidth = 0;
-  if( typeof( window.innerWidth ) == 'number' ) {
-    myWidth = window.innerWidth;
-  } else if( document.documentElement &&
-      ( document.documentElement.clientWidth || document.documentElement.clientWidth ) ) {
-    myWidth = document.documentElement.clientWidth;
-  } else if( document.body && ( document.body.clientWidth || document.body.clientWidth ) ) {
-    myWidth = document.body.clientWidth;
-  }
-  return myWidth;
-}
-
 /**************************************************
  * dom-drag.js
  * 09.25.2001
--- a/includes/clientside/tinymce/blank.htm	Fri Feb 22 12:46:51 2008 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,9 +0,0 @@
-<html xmlns="http://www.w3.org/1999/xhtml">
-<head>
-	<title>blank_page</title>
-	<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
-</head>
-<body class="mceContentBody">
-
-</body>
-</html>
--- a/includes/clientside/tinymce/langs/en.js	Fri Feb 22 12:46:51 2008 -0500
+++ b/includes/clientside/tinymce/langs/en.js	Fri Feb 22 12:51:53 2008 -0500
@@ -1,41 +1,154 @@
-// UK lang variables
-
-tinyMCE.addToLang('',{
-bold_desc : 'Bold (Ctrl+B)',
-italic_desc : 'Italic (Ctrl+I)',
-underline_desc : 'Underline (Ctrl+U)',
-striketrough_desc : 'Strikethrough',
-justifyleft_desc : 'Align left',
-justifycenter_desc : 'Align center',
-justifyright_desc : 'Align right',
-justifyfull_desc : 'Align full',
-bullist_desc : 'Unordered list',
-numlist_desc : 'Ordered list',
-outdent_desc : 'Outdent',
-indent_desc : 'Indent',
-undo_desc : 'Undo (Ctrl+Z)',
-redo_desc : 'Redo (Ctrl+Y)',
-link_desc : 'Insert/edit link',
-unlink_desc : 'Unlink',
-image_desc : 'Insert/edit image',
-cleanup_desc : 'Cleanup messy code',
-focus_alert : 'A editor instance must be focused before using this command.',
-edit_confirm : 'Do you want to use the WYSIWYG mode for this textarea?',
-insert_link_title : 'Insert/edit link',
-insert : 'Insert',
-update : 'Update',
-cancel : 'Cancel',
-insert_link_url : 'Link URL',
-insert_link_target : 'Target',
-insert_link_target_same : 'Open link in the same window',
-insert_link_target_blank : 'Open link in a new window',
-insert_image_title : 'Insert/edit image',
-insert_image_src : 'Image URL',
-insert_image_alt : 'Image description',
-help_desc : 'Help',
-bold_img : "bold.gif",
-italic_img : "italic.gif",
-underline_img : "underline.gif",
-clipboard_msg : 'Copy/Cut/Paste is not available in Mozilla and Firefox.\nDo you want more information about this issue?',
-popup_blocked : 'Sorry, but we have noticed that your popup-blocker has disabled a window that provides application functionality. You will need to disable popup blocking on this site in order to fully utilize this tool.'
-});
+tinyMCE.addI18n({en:{
+common:{
+edit_confirm:"Do you want to use the WYSIWYG mode for this textarea?",
+apply:"Apply",
+insert:"Insert",
+update:"Update",
+cancel:"Cancel",
+close:"Close",
+browse:"Browse",
+class_name:"Class",
+not_set:"-- Not set --",
+clipboard_msg:"Copy/Cut/Paste is not available in Mozilla and Firefox.\nDo you want more information about this issue?",
+clipboard_no_support:"Currently not supported by your browser, use keyboard shortcuts instead.",
+popup_blocked:"Sorry, but we have noticed that your popup-blocker has disabled a window that provides application functionality. You will need to disable popup blocking on this site in order to fully utilize this tool.",
+invalid_data:"Error: Invalid values entered, these are marked in red.",
+more_colors:"More colors"
+},
+contextmenu:{
+align:"Alignment",
+left:"Left",
+center:"Center",
+right:"Right",
+full:"Full"
+},
+insertdatetime:{
+date_fmt:"%Y-%m-%d",
+time_fmt:"%H:%M:%S",
+insertdate_desc:"Insert date",
+inserttime_desc:"Insert time",
+months_long:"January,February,March,April,May,June,July,August,September,October,November,December",
+months_short:"Jan,Feb,Mar,Apr,May,Jun,Jul,Aug,Sep,Oct,Nov,Dec",
+day_long:"Sunday,Monday,Tuesday,Wednesday,Thursday,Friday,Saturday,Sunday",
+day_short:"Sun,Mon,Tue,Wed,Thu,Fri,Sat,Sun"
+},
+print:{
+print_desc:"Print"
+},
+preview:{
+preview_desc:"Preview"
+},
+directionality:{
+ltr_desc:"Direction left to right",
+rtl_desc:"Direction right to left"
+},
+layer:{
+insertlayer_desc:"Insert new layer",
+forward_desc:"Move forward",
+backward_desc:"Move backward",
+absolute_desc:"Toggle absolute positioning",
+content:"New layer..."
+},
+save:{
+save_desc:"Save",
+cancel_desc:"Cancel all changes"
+},
+nonbreaking:{
+nonbreaking_desc:"Insert non-breaking space character"
+},
+iespell:{
+iespell_desc:"Run spell checking",
+download:"ieSpell not detected. Do you want to install it now?"
+},
+advhr:{
+advhr_desc:"Horizontale rule"
+},
+emotions:{
+emotions_desc:"Emotions"
+},
+searchreplace:{
+search_desc:"Find",
+replace_desc:"Find/Replace"
+},
+advimage:{
+image_desc:"Insert/edit image"
+},
+advlink:{
+link_desc:"Insert/edit link"
+},
+xhtmlxtras:{
+cite_desc:"Citation",
+abbr_desc:"Abbreviation",
+acronym_desc:"Acronym",
+del_desc:"Deletion",
+ins_desc:"Insertion",
+attribs_desc:"Insert/Edit Attributes"
+},
+style:{
+desc:"Edit CSS Style"
+},
+paste:{
+paste_text_desc:"Paste as Plain Text",
+paste_word_desc:"Paste from Word",
+selectall_desc:"Select All"
+},
+paste_dlg:{
+text_title:"Use CTRL+V on your keyboard to paste the text into the window.",
+text_linebreaks:"Keep linebreaks",
+word_title:"Use CTRL+V on your keyboard to paste the text into the window."
+},
+table:{
+desc:"Inserts a new table",
+row_before_desc:"Insert row before",
+row_after_desc:"Insert row after",
+delete_row_desc:"Delete row",
+col_before_desc:"Insert column before",
+col_after_desc:"Insert column after",
+delete_col_desc:"Remove column",
+split_cells_desc:"Split merged table cells",
+merge_cells_desc:"Merge table cells",
+row_desc:"Table row properties",
+cell_desc:"Table cell properties",
+props_desc:"Table properties",
+paste_row_before_desc:"Paste table row before",
+paste_row_after_desc:"Paste table row after",
+cut_row_desc:"Cut table row",
+copy_row_desc:"Copy table row",
+del:"Delete table",
+row:"Row",
+col:"Column",
+cell:"Cell"
+},
+autosave:{
+unload_msg:"The changes you made will be lost if you navigate away from this page."
+},
+fullscreen:{
+desc:"Toggle fullscreen mode"
+},
+media:{
+desc:"Insert / edit embedded media",
+edit:"Edit embedded media"
+},
+fullpage:{
+desc:"Document properties"
+},
+template:{
+desc:"Insert predefined template content"
+},
+visualchars:{
+desc:"Visual control characters on/off."
+},
+spellchecker:{
+desc:"Toggle spellchecker",
+menu:"Spellchecker settings",
+ignore_word:"Ignore word",
+ignore_words:"Ignore all",
+langs:"Languages",
+wait:"Please wait...",
+sug:"Suggestions",
+no_sug:"No suggestions",
+no_mpell:"No misspellings found."
+},
+pagebreak:{
+desc:"Insert page break."
+}}});
\ No newline at end of file
--- a/includes/clientside/tinymce/langs/readme.txt	Fri Feb 22 12:46:51 2008 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,9 +0,0 @@
-Beginning with version 2.0.5 the language packs are no
-longer included with the core distribution.
-Language packs can be downloaded from the TinyMCE website:
-http://tinymce.moxiecode.com/download.php
-
-The language pack codes are based on ISO-639-1:
-http://www.loc.gov/standards/iso639-2/englangn.html
-
-Plrease try using entities if possible. Like &aring; etc for non a-z characters.
--- a/includes/clientside/tinymce/plugins/advhr/css/advhr.css	Fri Feb 22 12:46:51 2008 -0500
+++ b/includes/clientside/tinymce/plugins/advhr/css/advhr.css	Fri Feb 22 12:51:53 2008 -0500
@@ -1,23 +1,5 @@
-input.radio {
-	border: 1px none #000000;
-	background-color: transparent;
-	vertical-align: middle;
-}
-
-.panel_wrapper div.current {
-	height: 80px;
-}
-
-#width {
-	width: 50px;
-	vertical-align: middle;
-}
-
-#width2 {
-	width: 50px;
-	vertical-align: middle;
-}
-
-#size {
-	width: 100px;
-}
+input.radio {border:1px none #000; background:transparent; vertical-align:middle;}
+.panel_wrapper div.current {height:80px;}
+#width {width:50px; vertical-align:middle;}
+#width2 {width:50px; vertical-align:middle;}
+#size {width:100px;}
--- a/includes/clientside/tinymce/plugins/advhr/editor_plugin.js	Fri Feb 22 12:46:51 2008 -0500
+++ b/includes/clientside/tinymce/plugins/advhr/editor_plugin.js	Fri Feb 22 12:51:53 2008 -0500
@@ -1,1 +1,1 @@
-tinyMCE.importPluginLanguagePack('advhr');var TinyMCE_AdvancedHRPlugin={getInfo:function(){return{longname:'Advanced HR',author:'Moxiecode Systems AB',authorurl:'http://tinymce.moxiecode.com',infourl:'http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/advhr',version:tinyMCE.majorVersion+"."+tinyMCE.minorVersion}},getControlHTML:function(cn){switch(cn){case"advhr":return tinyMCE.getButtonHTML(cn,'lang_insert_advhr_desc','{$pluginurl}/images/advhr.gif','mceAdvancedHr')}return""},execCommand:function(editor_id,element,command,user_interface,value){switch(command){case"mceAdvancedHr":var template=new Array();template['file']='../../plugins/advhr/rule.htm';template['width']=250;template['height']=160;template['width']+=tinyMCE.getLang('lang_advhr_delta_width',0);template['height']+=tinyMCE.getLang('lang_advhr_delta_height',0);var size="",width="",noshade="";if(tinyMCE.selectedElement!=null&&tinyMCE.selectedElement.nodeName.toLowerCase()=="hr"){tinyMCE.hrElement=tinyMCE.selectedElement;if(tinyMCE.hrElement){size=tinyMCE.hrElement.getAttribute('size')?tinyMCE.hrElement.getAttribute('size'):"";width=tinyMCE.hrElement.getAttribute('width')?tinyMCE.hrElement.getAttribute('width'):"";noshade=tinyMCE.hrElement.getAttribute('noshade')?tinyMCE.hrElement.getAttribute('noshade'):""}tinyMCE.openWindow(template,{editor_id:editor_id,size:size,width:width,noshade:noshade,mceDo:'update'})}else{if(tinyMCE.isMSIE){tinyMCE.execInstanceCommand(editor_id,'mceInsertContent',false,'<hr />')}else{tinyMCE.openWindow(template,{editor_id:editor_id,inline:"yes",size:size,width:width,noshade:noshade,mceDo:'insert'})}}return true}return false},handleNodeChange:function(editor_id,node,undo_index,undo_levels,visual_aid,any_selection){if(node==null)return;do{if(node.nodeName=="HR"){tinyMCE.switchClass(editor_id+'_advhr','mceButtonSelected');return true}}while((node=node.parentNode));tinyMCE.switchClass(editor_id+'_advhr','mceButtonNormal');return true}};tinyMCE.addPlugin("advhr",TinyMCE_AdvancedHRPlugin);
\ No newline at end of file
+(function(){tinymce.create('tinymce.plugins.AdvancedHRPlugin',{init:function(ed,url){ed.addCommand('mceAdvancedHr',function(){ed.windowManager.open({file:url+'/rule.htm',width:250+parseInt(ed.getLang('advhr.delta_width',0)),height:160+parseInt(ed.getLang('advhr.delta_height',0)),inline:1},{plugin_url:url});});ed.addButton('advhr',{title:'advhr.advhr_desc',cmd:'mceAdvancedHr'});ed.onNodeChange.add(function(ed,cm,n){cm.setActive('advhr',n.nodeName=='HR');});ed.onClick.add(function(ed,e){e=e.target;if(e.nodeName==='HR')ed.selection.select(e);});},getInfo:function(){return{longname:'Advanced HR',author:'Moxiecode Systems AB',authorurl:'http://tinymce.moxiecode.com',infourl:'http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/advhr',version:tinymce.majorVersion+"."+tinymce.minorVersion};}});tinymce.PluginManager.add('advhr',tinymce.plugins.AdvancedHRPlugin);})();
\ No newline at end of file
--- a/includes/clientside/tinymce/plugins/advhr/editor_plugin_src.js	Fri Feb 22 12:46:51 2008 -0500
+++ b/includes/clientside/tinymce/plugins/advhr/editor_plugin_src.js	Fri Feb 22 12:51:53 2008 -0500
@@ -1,90 +1,54 @@
 /**
- * $Id: editor_plugin_src.js 201 2007-02-12 15:56:56Z spocke $
+ * $Id: editor_plugin_src.js 520 2008-01-07 16:30:32Z spocke $
  *
  * @author Moxiecode
- * @copyright Copyright © 2004-2007, Moxiecode Systems AB, All rights reserved.
+ * @copyright Copyright © 2004-2008, Moxiecode Systems AB, All rights reserved.
  */
 
-/* Import plugin specific language pack */
-tinyMCE.importPluginLanguagePack('advhr');
-
-var TinyMCE_AdvancedHRPlugin = {
-	getInfo : function() {
-		return {
-			longname : 'Advanced HR',
-			author : 'Moxiecode Systems AB',
-			authorurl : 'http://tinymce.moxiecode.com',
-			infourl : 'http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/advhr',
-			version : tinyMCE.majorVersion + "." + tinyMCE.minorVersion
-		}
-	},
+(function() {
+	tinymce.create('tinymce.plugins.AdvancedHRPlugin', {
+		init : function(ed, url) {
+			// Register commands
+			ed.addCommand('mceAdvancedHr', function() {
+				ed.windowManager.open({
+					file : url + '/rule.htm',
+					width : 250 + parseInt(ed.getLang('advhr.delta_width', 0)),
+					height : 160 + parseInt(ed.getLang('advhr.delta_height', 0)),
+					inline : 1
+				}, {
+					plugin_url : url
+				});
+			});
 
-	getControlHTML : function(cn) {
-		switch (cn) {
-			case "advhr":
-				return tinyMCE.getButtonHTML(cn, 'lang_insert_advhr_desc', '{$pluginurl}/images/advhr.gif', 'mceAdvancedHr');
-		}
-
-		return "";
-	},
-
-	/**
-	 * Executes the mceAdvanceHr command.
-	 */
-	execCommand : function(editor_id, element, command, user_interface, value) {
-		// Handle commands
-		switch (command) {
-			case "mceAdvancedHr":
-				var template = new Array();
-
-				template['file']   = '../../plugins/advhr/rule.htm'; // Relative to theme
-				template['width']  = 250;
-				template['height'] = 160;
-
-				template['width']  += tinyMCE.getLang('lang_advhr_delta_width', 0);
-				template['height'] += tinyMCE.getLang('lang_advhr_delta_height', 0);
+			// Register buttons
+			ed.addButton('advhr', {
+				title : 'advhr.advhr_desc',
+				cmd : 'mceAdvancedHr'
+			});
 
-				var size = "", width = "", noshade = "";
-				if (tinyMCE.selectedElement != null && tinyMCE.selectedElement.nodeName.toLowerCase() == "hr") {
-					tinyMCE.hrElement = tinyMCE.selectedElement;
-
-					if (tinyMCE.hrElement) {
-						size    = tinyMCE.hrElement.getAttribute('size') ? tinyMCE.hrElement.getAttribute('size') : "";
-						width   = tinyMCE.hrElement.getAttribute('width') ? tinyMCE.hrElement.getAttribute('width') : "";
-						noshade = tinyMCE.hrElement.getAttribute('noshade') ? tinyMCE.hrElement.getAttribute('noshade') : "";
-					}
+			ed.onNodeChange.add(function(ed, cm, n) {
+				cm.setActive('advhr', n.nodeName == 'HR');
+			});
 
-					tinyMCE.openWindow(template, {editor_id : editor_id, size : size, width : width, noshade : noshade, mceDo : 'update'});
-				} else {
-					if (tinyMCE.isMSIE) {
-						tinyMCE.execInstanceCommand(editor_id, 'mceInsertContent', false,'<hr />');
-					} else {
-						tinyMCE.openWindow(template, {editor_id : editor_id, inline : "yes", size : size, width : width, noshade : noshade, mceDo : 'insert'});
-					}
-				}
+			ed.onClick.add(function(ed, e) {
+				e = e.target;
 
-				return true;
-		}
+				if (e.nodeName === 'HR')
+					ed.selection.select(e);
+			});
+		},
 
-		// Pass to next handler in chain
-		return false;
-	},
-
-	handleNodeChange : function(editor_id, node, undo_index, undo_levels, visual_aid, any_selection) {
-		if (node == null)
-			return;
+		getInfo : function() {
+			return {
+				longname : 'Advanced HR',
+				author : 'Moxiecode Systems AB',
+				authorurl : 'http://tinymce.moxiecode.com',
+				infourl : 'http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/advhr',
+				version : tinymce.majorVersion + "." + tinymce.minorVersion
+			};
+		}
+	});
 
-		do {
-			if (node.nodeName == "HR") {
-				tinyMCE.switchClass(editor_id + '_advhr', 'mceButtonSelected');
-				return true;
-			}
-		} while ((node = node.parentNode));
-
-		tinyMCE.switchClass(editor_id + '_advhr', 'mceButtonNormal');
-
-		return true;
-	}
-};
-
-tinyMCE.addPlugin("advhr", TinyMCE_AdvancedHRPlugin);
+	// Register plugin
+	tinymce.PluginManager.add('advhr', tinymce.plugins.AdvancedHRPlugin);
+})();
\ No newline at end of file
Binary file includes/clientside/tinymce/plugins/advhr/images/advhr.gif has changed
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/includes/clientside/tinymce/plugins/advhr/js/rule.js	Fri Feb 22 12:51:53 2008 -0500
@@ -0,0 +1,34 @@
+var AdvHRDialog = {
+	init : function(ed) {
+		var dom = ed.dom, f = document.forms[0], n = ed.selection.getNode(), w;
+
+		w = dom.getAttrib(n, 'width');
+		f.width.value = w ? parseInt(w) : '';
+		f.size.value = dom.getAttrib(n, 'size');
+		f.noshade.checked = !!dom.getAttrib(n, 'noshade');
+		selectByValue(f, 'width2', w.indexOf('%') != -1 ? '%' : 'px');
+	},
+
+	update : function() {
+		var ed = tinyMCEPopup.editor, h, f = document.forms[0];
+
+		h = '<hr';
+
+		if (f.size.value)
+			h += ' size="' + f.size.value + '"';
+
+		if (f.width.value)
+			h += ' width="' + f.width.value + (f.width2.value == '%' ? '%' : '') + '"';
+
+		if (f.noshade.checked)
+			h += ' noshade="noshade"';
+
+		h += ' />';
+
+		ed.execCommand("mceInsertContent", false, h);
+		tinyMCEPopup.close();
+	}
+};
+
+tinyMCEPopup.requireLangPack();
+tinyMCEPopup.onInit.add(AdvHRDialog.init, AdvHRDialog);
--- a/includes/clientside/tinymce/plugins/advhr/jscripts/rule.js	Fri Feb 22 12:46:51 2008 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,43 +0,0 @@
-function init() {
-	tinyMCEPopup.resizeToInnerSize();
-
-	var formObj = document.forms[0];
-	formObj.width.value  = tinyMCE.getWindowArg('width');
-	formObj.size.value   = tinyMCE.getWindowArg('size');
-	formObj.insert.value = tinyMCE.getLang('lang_' + tinyMCE.getWindowArg('mceDo'),'Insert',true);
-	if (tinyMCE.getWindowArg('noshade')) {
-		formObj.noshade.checked = true;
-	}
-	if (tinyMCE.getWindowArg('width').lastIndexOf('%')!=-1) {
-		formObj.width2.value = "%";
-		formObj.width.value  = formObj.width.value.substring(0,formObj.width.value.length-1);
-	}
-}
-
-function insertHR() {
-	var formObj = document.forms[0];
-	var width   = formObj.width.value;
-	var size    = formObj.size.value;
-	var html = '<hr';
-	if (size!='' && size!=0) {
-		html += ' size="' + size + '"';
-	}
-	if (width!='' && width!=0) {
-		html += ' width="' + width;
-		if (formObj.width2.value=='%') {
-			html += '%';
-		}
-		html += '"';
-	}
-	if (formObj.noshade.checked==true) {
-		html += ' noshade="noshade"';
-	}
-	html += ' />';
-
-	tinyMCEPopup.execCommand("mceInsertContent", true, html);
-	tinyMCEPopup.close();
-}
-
-function cancelAction() {
-	tinyMCEPopup.close();
-}
--- a/includes/clientside/tinymce/plugins/advhr/langs/en.js	Fri Feb 22 12:46:51 2008 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,8 +0,0 @@
-// UK lang variables
-
-tinyMCE.addToLang('',{
-insert_advhr_desc : 'Horizontale rule',
-insert_advhr_width : 'Width',
-insert_advhr_size : 'Height',
-insert_advhr_noshade : 'No shadow'
-});
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/includes/clientside/tinymce/plugins/advhr/langs/en_dlg.js	Fri Feb 22 12:51:53 2008 -0500
@@ -0,0 +1,5 @@
+tinyMCE.addI18n('en.advhr_dlg',{
+width:"Width",
+size:"Height",
+noshade:"No shadow"
+});
\ No newline at end of file
--- a/includes/clientside/tinymce/plugins/advhr/readme.txt	Fri Feb 22 12:46:51 2008 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1 +0,0 @@
-Check the TinyMCE documentation for details on this plugin.
--- a/includes/clientside/tinymce/plugins/advhr/rule.htm	Fri Feb 22 12:46:51 2008 -0500
+++ b/includes/clientside/tinymce/plugins/advhr/rule.htm	Fri Feb 22 12:51:53 2008 -0500
@@ -1,17 +1,19 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
 <html xmlns="http://www.w3.org/1999/xhtml">
 <head>
-	<title>{$lang_insert_advhr_desc}</title>
-	<script language="javascript" type="text/javascript" src="../../tiny_mce_popup.js"></script>
-	<script language="javascript" type="text/javascript" src="jscripts/rule.js"></script>
-	<script language="javascript" type="text/javascript" src="../../utils/mctabs.js"></script>
+	<title>{#advhr.advhr_desc}</title>
+	<script type="text/javascript" src="../../tiny_mce_popup.js"></script>
+	<script type="text/javascript" src="js/rule.js"></script>
+	<script type="text/javascript" src="../../utils/mctabs.js"></script>
+	<script type="text/javascript" src="../../utils/form_utils.js"></script>
 	<link href="css/advhr.css" rel="stylesheet" type="text/css" />
 	<base target="_self" />
 </head>
-<body onload="tinyMCEPopup.executeOnLoad('init();');">
-<form onsubmit="insertHR();return false;" action="#">
+<body>
+<form onsubmit="AdvHRDialog.update();return false;" action="#">
 	<div class="tabs">
 		<ul>
-			<li id="general_tab" class="current"><span><a href="javascript:mcTabs.displayTab('general_tab','general_panel');" onmousedown="return false;">{$lang_insert_advhr_desc}</a></span></li>
+			<li id="general_tab" class="current"><span><a href="javascript:mcTabs.displayTab('general_tab','general_panel');" onmousedown="return false;">{#advhr.advhr_desc}</a></span></li>
 		</ul>
 	</div>
 
@@ -19,7 +21,7 @@
 		<div id="general_panel" class="panel current">
 			<table border="0" cellpadding="4" cellspacing="0">
                     <tr>
-                        <td><label for="width">{$lang_insert_advhr_width}</label></td>
+                        <td><label for="width">{#advhr_dlg.width}</label></td>
                         <td nowrap="nowrap">
                             <input id="width" name="width" type="text" value="" />
                             <select name="width2" id="width2">
@@ -29,7 +31,7 @@
                         </td>
                     </tr>
                     <tr>
-                        <td><label for="size">{$lang_insert_advhr_size}</label></td>
+                        <td><label for="size">{#advhr_dlg.size}</label></td>
                         <td><select id="size" name="size">
                             <option value="">Normal</option>
                             <option value="1">1</option>
@@ -40,7 +42,7 @@
                         </select></td>
                     </tr>
                     <tr>
-                        <td><label for="noshade">{$lang_insert_advhr_noshade}</label></td>
+                        <td><label for="noshade">{#advhr_dlg.noshade}</label></td>
                         <td><input type="checkbox" name="noshade" id="noshade" class="radio" /></td>
                     </tr>
             </table>
@@ -49,11 +51,11 @@
 
 	<div class="mceActionPanel">
 		<div style="float: left">
-			<input type="button" id="insert" name="insert" value="{$lang_insert}" onclick="insertHR();" />
+			<input type="button" id="insert" name="insert" value="{#insert}" onclick="AdvHRDialog.update();" />
 		</div>
 
 		<div style="float: right">
-			<input type="button" id="cancel" name="cancel" value="{$lang_cancel}" onclick="tinyMCEPopup.close();" />
+			<input type="button" id="cancel" name="cancel" value="{#cancel}" onclick="tinyMCEPopup.close();" />
 		</div>
 	</div>
 </form>
--- a/includes/clientside/tinymce/plugins/advimage/css/advimage.css	Fri Feb 22 12:46:51 2008 -0500
+++ b/includes/clientside/tinymce/plugins/advimage/css/advimage.css	Fri Feb 22 12:51:53 2008 -0500
@@ -1,66 +1,13 @@
-/* CSS file for advimage plugin popup */
-
-.mceImageList {
-	width: 280px;
-}
-
-.mceActionPanel {
-	margin-top: 7px;
-}
-
-.alignPreview {
-	border: 1px solid black;
-	width: 140px;
-	height: 140px;
-	overflow: hidden;
-	padding: 5px;
-}
-
-.checkbox {
-	border: 0;
-}
-
-.panel_wrapper div.current {
-	height: 305px;
-}
-
-#prev {
-	margin: 0;
-	border: 1px
-	solid black;
-	width: 99%;
-	height: 150px;
-	overflow: auto;
-}
-
-#align, #classlist {
-	width: 150px;
-}
-
-#width, #height {
-	vertical-align: middle;
-	width: 50px;
-	text-align: center;
-}
-
-#vspace, #hspace, #border {
-	vertical-align: middle;
-	width: 30px;
-	text-align: center;
-}
-
-#classlist {
-	width: 180px;
-}
-
-input {
-	width: 280px;
-}
-
-#constrain, #onmousemovecheck {
-	width: auto;
-}
-
-#id, #dir, #lang, #usemap, #longdesc {
-	width: 200px;
-}
+#src_list, #over_list, #out_list {width:280px;}
+.mceActionPanel {margin-top:7px;}
+.alignPreview {border:1px solid #000; width:140px; height:140px; overflow:hidden; padding:5px;}
+.checkbox {border:0;}
+.panel_wrapper div.current {height:305px;}
+#prev {margin:0; border:1px solid #000; width:99%; height:150px; overflow:auto;}
+#align, #classlist {width:150px;}
+#width, #height {vertical-align:middle; width:50px; text-align:center;}
+#vspace, #hspace, #border {vertical-align:middle; width:30px; text-align:center;}
+#class_list {width:180px;}
+input {width: 280px;}
+#constrain, #onmousemovecheck {width:auto;}
+#id, #dir, #lang, #usemap, #longdesc {width:200px;}
--- a/includes/clientside/tinymce/plugins/advimage/editor_plugin.js	Fri Feb 22 12:46:51 2008 -0500
+++ b/includes/clientside/tinymce/plugins/advimage/editor_plugin.js	Fri Feb 22 12:51:53 2008 -0500
@@ -1,1 +1,1 @@
-tinyMCE.importPluginLanguagePack('advimage');var TinyMCE_AdvancedImagePlugin={getInfo:function(){return{longname:'Advanced image',author:'Moxiecode Systems AB',authorurl:'http://tinymce.moxiecode.com',infourl:'http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/advimage',version:tinyMCE.majorVersion+"."+tinyMCE.minorVersion}},getControlHTML:function(cn){switch(cn){case"image":return tinyMCE.getButtonHTML(cn,'lang_image_desc','{$themeurl}/images/image.gif','mceAdvImage')}return""},execCommand:function(editor_id,element,command,user_interface,value){switch(command){case"mceAdvImage":var template=new Array();template['file']='../../plugins/advimage/image.htm';template['width']=480;template['height']=380;template['width']+=tinyMCE.getLang('lang_advimage_delta_width',0);template['height']+=tinyMCE.getLang('lang_advimage_delta_height',0);var inst=tinyMCE.getInstanceById(editor_id);var elm=inst.getFocusElement();if(elm!=null&&tinyMCE.getAttrib(elm,'class').indexOf('mceItem')!=-1)return true;tinyMCE.openWindow(template,{editor_id:editor_id,inline:"yes"});return true}return false},cleanup:function(type,content){switch(type){case"insert_to_editor_dom":var imgs=content.getElementsByTagName("img"),src,i;for(i=0;i<imgs.length;i++){var onmouseover=tinyMCE.cleanupEventStr(tinyMCE.getAttrib(imgs[i],'onmouseover'));var onmouseout=tinyMCE.cleanupEventStr(tinyMCE.getAttrib(imgs[i],'onmouseout'));if((src=this._getImageSrc(onmouseover))!=""){if(tinyMCE.getParam('convert_urls'))src=tinyMCE.convertRelativeToAbsoluteURL(tinyMCE.settings['base_href'],src);imgs[i].setAttribute('onmouseover',"this.src='"+src+"';")}if((src=this._getImageSrc(onmouseout))!=""){if(tinyMCE.getParam('convert_urls'))src=tinyMCE.convertRelativeToAbsoluteURL(tinyMCE.settings['base_href'],src);imgs[i].setAttribute('onmouseout',"this.src='"+src+"';")}}break;case"get_from_editor_dom":var imgs=content.getElementsByTagName("img");for(var i=0;i<imgs.length;i++){var onmouseover=tinyMCE.cleanupEventStr(tinyMCE.getAttrib(imgs[i],'onmouseover'));var onmouseout=tinyMCE.cleanupEventStr(tinyMCE.getAttrib(imgs[i],'onmouseout'));if((src=this._getImageSrc(onmouseover))!=""){if(tinyMCE.getParam('convert_urls'))src=eval(tinyMCE.settings['urlconverter_callback']+"(src, null, true);");imgs[i].setAttribute('onmouseover',"this.src='"+src+"';")}if((src=this._getImageSrc(onmouseout))!=""){if(tinyMCE.getParam('convert_urls'))src=eval(tinyMCE.settings['urlconverter_callback']+"(src, null, true);");imgs[i].setAttribute('onmouseout',"this.src='"+src+"';")}}break}return content},handleNodeChange:function(editor_id,node,undo_index,undo_levels,visual_aid,any_selection){if(node==null)return;do{if(node.nodeName=="IMG"&&tinyMCE.getAttrib(node,'class').indexOf('mceItem')==-1){tinyMCE.switchClass(editor_id+'_advimage','mceButtonSelected');return true}}while((node=node.parentNode));tinyMCE.switchClass(editor_id+'_advimage','mceButtonNormal');return true},_getImageSrc:function(s){var sr,p=-1;if(!s)return"";if((p=s.indexOf('this.src='))!=-1){sr=s.substring(p+10);sr=sr.substring(0,sr.indexOf('\''));return sr}return""}};tinyMCE.addPlugin("advimage",TinyMCE_AdvancedImagePlugin);
\ No newline at end of file
+(function(){tinymce.create('tinymce.plugins.AdvancedImagePlugin',{init:function(ed,url){ed.addCommand('mceAdvImage',function(){var e=ed.selection.getNode();if(ed.dom.getAttrib(e,'class').indexOf('mceItem')!=-1)return;ed.windowManager.open({file:url+'/image.htm',width:480+parseInt(ed.getLang('advimage.delta_width',0)),height:385+parseInt(ed.getLang('advimage.delta_height',0)),inline:1},{plugin_url:url});});ed.addButton('image',{title:'advimage.image_desc',cmd:'mceAdvImage'});},getInfo:function(){return{longname:'Advanced image',author:'Moxiecode Systems AB',authorurl:'http://tinymce.moxiecode.com',infourl:'http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/advimage',version:tinymce.majorVersion+"."+tinymce.minorVersion};}});tinymce.PluginManager.add('advimage',tinymce.plugins.AdvancedImagePlugin);})();
\ No newline at end of file
--- a/includes/clientside/tinymce/plugins/advimage/editor_plugin_src.js	Fri Feb 22 12:46:51 2008 -0500
+++ b/includes/clientside/tinymce/plugins/advimage/editor_plugin_src.js	Fri Feb 22 12:51:53 2008 -0500
@@ -1,148 +1,49 @@
 /**
- * $Id: editor_plugin_src.js 201 2007-02-12 15:56:56Z spocke $
+ * $Id: editor_plugin_src.js 520 2008-01-07 16:30:32Z spocke $
  *
  * @author Moxiecode
- * @copyright Copyright © 2004-2007, Moxiecode Systems AB, All rights reserved.
+ * @copyright Copyright © 2004-2008, Moxiecode Systems AB, All rights reserved.
  */
 
-/* Import plugin specific language pack */
-tinyMCE.importPluginLanguagePack('advimage');
-
-var TinyMCE_AdvancedImagePlugin = {
-	getInfo : function() {
-		return {
-			longname : 'Advanced image',
-			author : 'Moxiecode Systems AB',
-			authorurl : 'http://tinymce.moxiecode.com',
-			infourl : 'http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/advimage',
-			version : tinyMCE.majorVersion + "." + tinyMCE.minorVersion
-		};
-	},
-
-	getControlHTML : function(cn) {
-		switch (cn) {
-			case "image":
-				return tinyMCE.getButtonHTML(cn, 'lang_image_desc', '{$themeurl}/images/image.gif', 'mceAdvImage');
-		}
-
-		return "";
-	},
-
-	execCommand : function(editor_id, element, command, user_interface, value) {
-		switch (command) {
-			case "mceAdvImage":
-				var template = new Array();
-
-				template['file']   = '../../plugins/advimage/image.htm';
-				template['width']  = 480;
-				template['height'] = 380;
+(function() {
+	tinymce.create('tinymce.plugins.AdvancedImagePlugin', {
+		init : function(ed, url) {
+			// Register commands
+			ed.addCommand('mceAdvImage', function() {
+				var e = ed.selection.getNode();
 
-				// Language specific width and height addons
-				template['width']  += tinyMCE.getLang('lang_advimage_delta_width', 0);
-				template['height'] += tinyMCE.getLang('lang_advimage_delta_height', 0);
-
-				var inst = tinyMCE.getInstanceById(editor_id);
-				var elm = inst.getFocusElement();
-
-				if (elm != null && tinyMCE.getAttrib(elm, 'class').indexOf('mceItem') != -1)
-					return true;
-
-				tinyMCE.openWindow(template, {editor_id : editor_id, inline : "yes"});
-
-				return true;
-		}
-
-		return false;
-	},
+				// Internal image object like a flash placeholder
+				if (ed.dom.getAttrib(e, 'class').indexOf('mceItem') != -1)
+					return;
 
-	cleanup : function(type, content) {
-		switch (type) {
-			case "insert_to_editor_dom":
-				var imgs = content.getElementsByTagName("img"), src, i;
-				for (i=0; i<imgs.length; i++) {
-					var onmouseover = tinyMCE.cleanupEventStr(tinyMCE.getAttrib(imgs[i], 'onmouseover'));
-					var onmouseout = tinyMCE.cleanupEventStr(tinyMCE.getAttrib(imgs[i], 'onmouseout'));
-
-					if ((src = this._getImageSrc(onmouseover)) != "") {
-						if (tinyMCE.getParam('convert_urls'))
-							src = tinyMCE.convertRelativeToAbsoluteURL(tinyMCE.settings['base_href'], src);
-
-						imgs[i].setAttribute('onmouseover', "this.src='" + src + "';");
-					}
-
-					if ((src = this._getImageSrc(onmouseout)) != "") {
-						if (tinyMCE.getParam('convert_urls'))
-							src = tinyMCE.convertRelativeToAbsoluteURL(tinyMCE.settings['base_href'], src);
+				ed.windowManager.open({
+					file : url + '/image.htm',
+					width : 480 + parseInt(ed.getLang('advimage.delta_width', 0)),
+					height : 385 + parseInt(ed.getLang('advimage.delta_height', 0)),
+					inline : 1
+				}, {
+					plugin_url : url
+				});
+			});
 
-						imgs[i].setAttribute('onmouseout', "this.src='" + src + "';");
-					}
-				}
-				break;
-
-			case "get_from_editor_dom":
-				var imgs = content.getElementsByTagName("img");
-				for (var i=0; i<imgs.length; i++) {
-					var onmouseover = tinyMCE.cleanupEventStr(tinyMCE.getAttrib(imgs[i], 'onmouseover'));
-					var onmouseout = tinyMCE.cleanupEventStr(tinyMCE.getAttrib(imgs[i], 'onmouseout'));
-
-					if ((src = this._getImageSrc(onmouseover)) != "") {
-						if (tinyMCE.getParam('convert_urls'))
-							src = eval(tinyMCE.settings['urlconverter_callback'] + "(src, null, true);");
-
-						imgs[i].setAttribute('onmouseover', "this.src='" + src + "';");
-					}
-
-					if ((src = this._getImageSrc(onmouseout)) != "") {
-						if (tinyMCE.getParam('convert_urls'))
-							src = eval(tinyMCE.settings['urlconverter_callback'] + "(src, null, true);");
-
-						imgs[i].setAttribute('onmouseout', "this.src='" + src + "';");
-					}
-				}
-				break;
-		}
-
-		return content;
-	},
-
-	handleNodeChange : function(editor_id, node, undo_index, undo_levels, visual_aid, any_selection) {
-		if (node == null)
-			return;
+			// Register buttons
+			ed.addButton('image', {
+				title : 'advimage.image_desc',
+				cmd : 'mceAdvImage'
+			});
+		},
 
-		do {
-			if (node.nodeName == "IMG" && tinyMCE.getAttrib(node, 'class').indexOf('mceItem') == -1) {
-				tinyMCE.switchClass(editor_id + '_advimage', 'mceButtonSelected');
-				return true;
-			}
-		} while ((node = node.parentNode));
-
-		tinyMCE.switchClass(editor_id + '_advimage', 'mceButtonNormal');
-
-		return true;
-	},
+		getInfo : function() {
+			return {
+				longname : 'Advanced image',
+				author : 'Moxiecode Systems AB',
+				authorurl : 'http://tinymce.moxiecode.com',
+				infourl : 'http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/advimage',
+				version : tinymce.majorVersion + "." + tinymce.minorVersion
+			};
+		}
+	});
 
-	/**
-	 * Returns the image src from a scripted mouse over image str.
-	 *
-	 * @param {string} s String to get real src from.
-	 * @return Image src from a scripted mouse over image str.
-	 * @type string
-	 */
-	_getImageSrc : function(s) {
-		var sr, p = -1;
-
-		if (!s)
-			return "";
-
-		if ((p = s.indexOf('this.src=')) != -1) {
-			sr = s.substring(p + 10);
-			sr = sr.substring(0, sr.indexOf('\''));
-
-			return sr;
-		}
-
-		return "";
-	}
-};
-
-tinyMCE.addPlugin("advimage", TinyMCE_AdvancedImagePlugin);
+	// Register plugin
+	tinymce.PluginManager.add('advimage', tinymce.plugins.AdvancedImagePlugin);
+})();
\ No newline at end of file
--- a/includes/clientside/tinymce/plugins/advimage/image.htm	Fri Feb 22 12:46:51 2008 -0500
+++ b/includes/clientside/tinymce/plugins/advimage/image.htm	Fri Feb 22 12:51:53 2008 -0500
@@ -1,83 +1,83 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
 <html xmlns="http://www.w3.org/1999/xhtml">
 <head>
-	<title>{$lang_insert_image_title}</title>
-	<script language="javascript" type="text/javascript" src="../../tiny_mce_popup.js"></script>
-	<script language="javascript" type="text/javascript" src="../../utils/mctabs.js"></script>
-	<script language="javascript" type="text/javascript" src="../../utils/form_utils.js"></script>
-	<script language="javascript" type="text/javascript" src="../../utils/validate.js"></script>
-	<script language="javascript" type="text/javascript" src="jscripts/functions.js"></script>
+	<title>{#advimage_dlg.dialog_title}</title>
+	<script type="text/javascript" src="../../tiny_mce_popup.js"></script>
+	<script type="text/javascript" src="../../utils/mctabs.js"></script>
+	<script type="text/javascript" src="../../utils/form_utils.js"></script>
+	<script type="text/javascript" src="../../utils/validate.js"></script>
+	<script type="text/javascript" src="js/image.js"></script>
 	<link href="css/advimage.css" rel="stylesheet" type="text/css" />
 	<base target="_self" />
 </head>
-<body id="advimage" onload="tinyMCEPopup.executeOnLoad('init();');" style="display: none">
-    <form onsubmit="insertAction();return false;" action="#"> 
+<body id="advimage" style="display: none">
+    <form onsubmit="ImageDialog.insert();return false;" action="#"> 
 		<div class="tabs">
 			<ul>
-				<li id="general_tab" class="current"><span><a href="javascript:mcTabs.displayTab('general_tab','general_panel');" onmousedown="return false;">{$lang_advimage_tab_general}</a></span></li>
-				<li id="appearance_tab"><span><a href="javascript:mcTabs.displayTab('appearance_tab','appearance_panel');" onmousedown="return false;">{$lang_advimage_tab_appearance}</a></span></li>
-				<li id="advanced_tab"><span><a href="javascript:mcTabs.displayTab('advanced_tab','advanced_panel');" onmousedown="return false;">{$lang_advimage_tab_advanced}</a></span></li>
+				<li id="general_tab" class="current"><span><a href="javascript:mcTabs.displayTab('general_tab','general_panel');" onmousedown="return false;">{#advimage_dlg.tab_general}</a></span></li>
+				<li id="appearance_tab"><span><a href="javascript:mcTabs.displayTab('appearance_tab','appearance_panel');" onmousedown="return false;">{#advimage_dlg.tab_appearance}</a></span></li>
+				<li id="advanced_tab"><span><a href="javascript:mcTabs.displayTab('advanced_tab','advanced_panel');" onmousedown="return false;">{#advimage_dlg.tab_advanced}</a></span></li>
 			</ul>
 		</div>
 
 		<div class="panel_wrapper">
 			<div id="general_panel" class="panel current">
 				<fieldset>
-						<legend>{$lang_advimage_general}</legend>
+						<legend>{#advimage_dlg.general}</legend>
 
 						<table class="properties">
 							<tr>
-								<td class="column1"><label id="srclabel" for="src">{$lang_insert_image_src}</label></td>
+								<td class="column1"><label id="srclabel" for="src">{#advimage_dlg.src}</label></td>
 								<td colspan="2"><table border="0" cellspacing="0" cellpadding="0">
 									<tr> 
-									  <td><input name="src" type="text" id="src" value="" onchange="showPreviewImage(this.value);" /></td> 
+									  <td><input name="src" type="text" id="src" value="" onchange="ImageDialog.showPreviewImage(this.value);" /></td> 
 									  <td id="srcbrowsercontainer">&nbsp;</td>
 									</tr>
 								  </table></td>
 							</tr>
-							<tr id="imagelistsrcrow">
-								<td class="column1"><label for="imagelistsrc">{$lang_image_list}</label></td>
-								<td colspan="2" id="imagelistsrccontainer">&nbsp;</td>
+							<tr>
+								<td><label for="src_list">{#advimage_dlg.image_list}</label></td>
+								<td><select id="src_list" name="src_list" onchange="document.getElementById('src').value=this.options[this.selectedIndex].value;document.getElementById('alt').value=this.options[this.selectedIndex].text;document.getElementById('title').value=this.options[this.selectedIndex].text;ImageDialog.showPreviewImage(this.options[this.selectedIndex].value);"></select></td>
 							</tr>
 							<tr> 
-								<td class="column1"><label id="altlabel" for="alt">{$lang_insert_image_alt}</label></td> 
+								<td class="column1"><label id="altlabel" for="alt">{#advimage_dlg.alt}</label></td> 
 								<td colspan="2"><input id="alt" name="alt" type="text" value="" /></td> 
 							</tr> 
 							<tr> 
-								<td class="column1"><label id="titlelabel" for="title">{$lang_advimage_title}</label></td> 
+								<td class="column1"><label id="titlelabel" for="title">{#advimage_dlg.title}</label></td> 
 								<td colspan="2"><input id="title" name="title" type="text" value="" /></td> 
 							</tr>
 						</table>
 				</fieldset>
 
 				<fieldset>
-					<legend>{$lang_advimage_preview}</legend>
+					<legend>{#advimage_dlg.preview}</legend>
 					<div id="prev"></div>
 				</fieldset>
 			</div>
 
 			<div id="appearance_panel" class="panel">
 				<fieldset>
-					<legend>{$lang_advimage_tab_appearance}</legend>
+					<legend>{#advimage_dlg.tab_appearance}</legend>
 
 					<table border="0" cellpadding="4" cellspacing="0">
 						<tr> 
-							<td class="column1"><label id="alignlabel" for="align">{$lang_insert_image_align}</label></td> 
-							<td><select id="align" name="align" onchange="changeAppearance();"> 
-									<option value="">{$lang_insert_image_align_default}</option> 
-									<option value="baseline">{$lang_insert_image_align_baseline}</option> 
-									<option value="top">{$lang_insert_image_align_top}</option> 
-									<option value="middle">{$lang_insert_image_align_middle}</option> 
-									<option value="bottom">{$lang_insert_image_align_bottom}</option> 
-									<option value="texttop">{$lang_insert_image_align_texttop}</option> 
-									<option value="absmiddle">{$lang_insert_image_align_absmiddle}</option> 
-									<option value="absbottom">{$lang_insert_image_align_absbottom}</option> 
-									<option value="left">{$lang_insert_image_align_left}</option> 
-									<option value="right">{$lang_insert_image_align_right}</option> 
+							<td class="column1"><label id="alignlabel" for="align">{#advimage_dlg.align}</label></td> 
+							<td><select id="align" name="align" onchange="ImageDialog.updateStyle('align');ImageDialog.changeAppearance();"> 
+									<option value="">{#not_set}</option> 
+									<option value="baseline">{#advimage_dlg.align_baseline}</option>
+									<option value="top">{#advimage_dlg.align_top}</option>
+									<option value="middle">{#advimage_dlg.align_middle}</option>
+									<option value="bottom">{#advimage_dlg.align_bottom}</option>
+									<option value="text-top">{#advimage_dlg.align_texttop}</option>
+									<option value="text-bottom">{#advimage_dlg.align_textbottom}</option>
+									<option value="left">{#advimage_dlg.align_left}</option>
+									<option value="right">{#advimage_dlg.align_right}</option>
 								</select> 
 							</td>
 							<td rowspan="6" valign="top">
 								<div class="alignPreview">
-									<img id="alignSampleImg" src="images/sample.gif" alt="{$lang_advimage_example_img}" />
+									<img id="alignSampleImg" src="img/sample.gif" alt="{#advimage_dlg.example_img}" />
 									Lorem ipsum, Dolor sit amet, consectetuer adipiscing loreum ipsum edipiscing elit, sed diam
 									nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat.Loreum ipsum
 									edipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam
@@ -87,10 +87,10 @@
 						</tr>
 
 						<tr>
-							<td class="column1"><label id="widthlabel" for="width">{$lang_insert_image_dimensions}</label></td>
+							<td class="column1"><label id="widthlabel" for="width">{#advimage_dlg.dimensions}</label></td>
 							<td nowrap="nowrap">
-								<input name="width" type="text" id="width" value="" size="5" maxlength="5" class="size" onchange="changeHeight();" /> x 
-								<input name="height" type="text" id="height" value="" size="5" maxlength="5" class="size" onchange="changeWidth();" /> px
+								<input name="width" type="text" id="width" value="" size="5" maxlength="5" class="size" onchange="ImageDialog.changeHeight();" /> x 
+								<input name="height" type="text" id="height" value="" size="5" maxlength="5" class="size" onchange="ImageDialog.changeWidth();" /> px
 							</td>
 						</tr>
 
@@ -99,43 +99,39 @@
 							<td><table border="0" cellpadding="0" cellspacing="0">
 									<tr>
 										<td><input id="constrain" type="checkbox" name="constrain" class="checkbox" /></td>
-										<td><label id="constrainlabel" for="constrain">{$lang_advimage_constrain_proportions}</label></td>
+										<td><label id="constrainlabel" for="constrain">{#advimage_dlg.constrain_proportions}</label></td>
 									</tr>
 								</table></td>
 						</tr>
 
 						<tr>
-							<td class="column1"><label id="vspacelabel" for="vspace">{$lang_insert_image_vspace}</label></td> 
-							<td><input name="vspace" type="text" id="vspace" value="" size="3" maxlength="3" class="number" onchange="changeAppearance();updateStyle();" />
+							<td class="column1"><label id="vspacelabel" for="vspace">{#advimage_dlg.vspace}</label></td> 
+							<td><input name="vspace" type="text" id="vspace" value="" size="3" maxlength="3" class="number" onchange="ImageDialog.updateStyle('vspace');ImageDialog.changeAppearance();" onblur="ImageDialog.updateStyle('vspace');ImageDialog.changeAppearance();" />
 							</td>
 						</tr>
 
 						<tr> 
-							<td class="column1"><label id="hspacelabel" for="hspace">{$lang_insert_image_hspace}</label></td> 
-							<td><input name="hspace" type="text" id="hspace" value="" size="3" maxlength="3" class="number" onchange="changeAppearance();updateStyle();" /></td> 
+							<td class="column1"><label id="hspacelabel" for="hspace">{#advimage_dlg.hspace}</label></td> 
+							<td><input name="hspace" type="text" id="hspace" value="" size="3" maxlength="3" class="number" onchange="ImageDialog.updateStyle('hspace');ImageDialog.changeAppearance();" onblur="ImageDialog.updateStyle('hspace');ImageDialog.changeAppearance();" /></td> 
 						</tr>
 
 						<tr>
-							<td class="column1"><label id="borderlabel" for="border">{$lang_insert_image_border}</label></td> 
-							<td><input id="border" name="border" type="text" value="" size="3" maxlength="3" class="number" onchange="changeAppearance();updateStyle();" /></td> 
+							<td class="column1"><label id="borderlabel" for="border">{#advimage_dlg.border}</label></td> 
+							<td><input id="border" name="border" type="text" value="" size="3" maxlength="3" class="number" onchange="ImageDialog.updateStyle('border');ImageDialog.changeAppearance();" onblur="ImageDialog.updateStyle('border');ImageDialog.changeAppearance();" /></td> 
 						</tr>
 
 						<tr>
-							<td><label id="classlabel" for="classlist">{$lang_class_name}</label></td>
-							<td colspan="2">
-								 <select id="classlist" name="classlist">
-									<option value="" selected>{$lang_not_set}</option>
-								 </select>
-							</td>
+							<td><label for="class_list">{#class_name}</label></td>
+							<td><select id="class_list" name="class_list"></select></td>
 						</tr>
 
 						<tr>
-							<td class="column1"><label id="stylelabel" for="style">{$lang_advimage_style}</label></td> 
-							<td colspan="2"><input id="style" name="style" type="text" value="" onchange="styleUpdated();" /></td> 
+							<td class="column1"><label id="stylelabel" for="style">{#advimage_dlg.style}</label></td> 
+							<td colspan="2"><input id="style" name="style" type="text" value="" onchange="ImageDialog.changeAppearance();" /></td> 
 						</tr>
 
 						<!-- <tr>
-							<td class="column1"><label id="classeslabel" for="classes">{$lang_advimage_classes}</label></td> 
+							<td class="column1"><label id="classeslabel" for="classes">{#advimage_dlg.classes}</label></td> 
 							<td colspan="2"><input id="classes" name="classes" type="text" value="" onchange="selectByValue(this.form,'classlist',this.value,true);" /></td> 
 						</tr> -->
 					</table>
@@ -144,14 +140,14 @@
 
 			<div id="advanced_panel" class="panel">
 				<fieldset>
-					<legend>{$lang_advimage_swap_image}</legend>
+					<legend>{#advimage_dlg.swap_image}</legend>
 
-					<input type="checkbox" id="onmousemovecheck" name="onmousemovecheck" class="checkbox" onclick="changeMouseMove();" />
-					<label id="onmousemovechecklabel" for="onmousemovecheck">{$lang_advimage_alt_image}</label>
+					<input type="checkbox" id="onmousemovecheck" name="onmousemovecheck" class="checkbox" onclick="ImageDialog.setSwapImage(this.checked);" />
+					<label id="onmousemovechecklabel" for="onmousemovecheck">{#advimage_dlg.alt_image}</label>
 
 					<table border="0" cellpadding="4" cellspacing="0" width="100%">
 							<tr>
-								<td class="column1"><label id="onmouseoversrclabel" for="onmouseoversrc">{$lang_advimage_mouseover}</label></td> 
+								<td class="column1"><label id="onmouseoversrclabel" for="onmouseoversrc">{#advimage_dlg.mouseover}</label></td> 
 								<td><table border="0" cellspacing="0" cellpadding="0"> 
 									<tr> 
 									  <td><input id="onmouseoversrc" name="onmouseoversrc" type="text" value="" /></td> 
@@ -159,12 +155,12 @@
 									</tr>
 								  </table></td>
 							</tr>
-							<tr id="imagelistoverrow">
-								<td class="column1"><label for="imagelistover">{$lang_image_list}</label></td>
-								<td id="imagelistovercontainer">&nbsp;</td>
+							<tr>
+								<td><label for="over_list">{#advimage_dlg.image_list}</label></td>
+								<td><select id="over_list" name="over_list" onchange="document.getElementById('onmouseoversrc').value=this.options[this.selectedIndex].value;"></select></td>
 							</tr>
 							<tr> 
-								<td class="column1"><label id="onmouseoutsrclabel" for="onmouseoutsrc">{$lang_advimage_mouseout}</label></td> 
+								<td class="column1"><label id="onmouseoutsrclabel" for="onmouseoutsrc">{#advimage_dlg.mouseout}</label></td> 
 								<td class="column2"><table border="0" cellspacing="0" cellpadding="0"> 
 									<tr> 
 									  <td><input id="onmouseoutsrc" name="onmouseoutsrc" type="text" value="" /></td> 
@@ -172,49 +168,49 @@
 									</tr> 
 								  </table></td> 
 							</tr>
-							<tr id="imagelistoutrow">
-								<td class="column1"><label for="imagelistout">{$lang_image_list}</label></td>
-								<td id="imagelistoutcontainer">&nbsp;</td>
+							<tr>
+								<td><label for="out_list">{#advimage_dlg.image_list}</label></td>
+								<td><select id="out_list" name="out_list" onchange="document.getElementById('onmouseoutsrc').value=this.options[this.selectedIndex].value;"></select></td>
 							</tr>
 					</table>
 				</fieldset>
 
 				<fieldset>
-					<legend>{$lang_advimage_misc}</legend>
+					<legend>{#advimage_dlg.misc}</legend>
 
 					<table border="0" cellpadding="4" cellspacing="0">
 						<tr>
-							<td class="column1"><label id="idlabel" for="id">{$lang_advimage_id}</label></td> 
+							<td class="column1"><label id="idlabel" for="id">{#advimage_dlg.id}</label></td> 
 							<td><input id="id" name="id" type="text" value="" /></td> 
 						</tr>
 
 						<tr>
-							<td class="column1"><label id="dirlabel" for="dir">{$lang_advimage_langdir}</label></td> 
+							<td class="column1"><label id="dirlabel" for="dir">{#advimage_dlg.langdir}</label></td> 
 							<td>
-								<select id="dir" name="dir" onchange="changeAppearance();"> 
-										<option value="">{$lang_not_set}</option> 
-										<option value="ltr">{$lang_advimage_ltr}</option> 
-										<option value="rtl">{$lang_advimage_rtl}</option> 
+								<select id="dir" name="dir" onchange="ImageDialog.changeAppearance();"> 
+										<option value="">{#not_set}</option> 
+										<option value="ltr">{#advimage_dlg.ltr}</option> 
+										<option value="rtl">{#advimage_dlg.rtl}</option> 
 								</select>
 							</td> 
 						</tr>
 
 						<tr>
-							<td class="column1"><label id="langlabel" for="lang">{$lang_advimage_langcode}</label></td> 
+							<td class="column1"><label id="langlabel" for="lang">{#advimage_dlg.langcode}</label></td> 
 							<td>
 								<input id="lang" name="lang" type="text" value="" />
 							</td> 
 						</tr>
 
 						<tr>
-							<td class="column1"><label id="usemaplabel" for="usemap">{$lang_advimage_image_map}</label></td> 
+							<td class="column1"><label id="usemaplabel" for="usemap">{#advimage_dlg.map}</label></td> 
 							<td>
 								<input id="usemap" name="usemap" type="text" value="" />
 							</td> 
 						</tr>
 
 						<tr>
-							<td class="column1"><label id="longdesclabel" for="longdesc">{$lang_advimage_long_desc}</label></td>
+							<td class="column1"><label id="longdesclabel" for="longdesc">{#advimage_dlg.long_desc}</label></td>
 							<td><table border="0" cellspacing="0" cellpadding="0">
 									<tr>
 									  <td><input id="longdesc" name="longdesc" type="text" value="" /></td>
@@ -229,11 +225,11 @@
 
 		<div class="mceActionPanel">
 			<div style="float: left">
-				<input type="button" id="insert" name="insert" value="{$lang_insert}" onclick="insertAction();" />
+				<input type="button" id="insert" name="insert" value="{#insert}" onclick="ImageDialog.insert();" />
 			</div>
 
 			<div style="float: right">
-				<input type="button" id="cancel" name="cancel" value="{$lang_cancel}" onclick="cancelAction();" />
+				<input type="button" id="cancel" name="cancel" value="{#cancel}" onclick="tinyMCEPopup.close();" />
 			</div>
 		</div>
     </form>
Binary file includes/clientside/tinymce/plugins/advimage/images/sample.gif has changed
Binary file includes/clientside/tinymce/plugins/advimage/img/sample.gif has changed
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/includes/clientside/tinymce/plugins/advimage/js/image.js	Fri Feb 22 12:51:53 2008 -0500
@@ -0,0 +1,434 @@
+var ImageDialog = {
+	preInit : function() {
+		var url;
+
+		tinyMCEPopup.requireLangPack();
+
+		if (url = tinyMCEPopup.getParam("external_image_list_url"))
+			document.write('<script language="javascript" type="text/javascript" src="' + tinyMCEPopup.editor.documentBaseURI.toAbsolute(url) + '"></script>');
+	},
+
+	init : function(ed) {
+		var f = document.forms[0], nl = f.elements, ed = tinyMCEPopup.editor, dom = ed.dom, n = ed.selection.getNode();
+
+		tinyMCEPopup.resizeToInnerSize();
+		this.fillClassList('class_list');
+		this.fillFileList('src_list', 'tinyMCEImageList');
+		this.fillFileList('over_list', 'tinyMCEImageList');
+		this.fillFileList('out_list', 'tinyMCEImageList');
+
+		if (n.nodeName == 'IMG') {
+			nl.src.value = dom.getAttrib(n, 'src');
+			nl.width.value = dom.getAttrib(n, 'width');
+			nl.height.value = dom.getAttrib(n, 'height');
+			nl.alt.value = dom.getAttrib(n, 'alt');
+			nl.title.value = dom.getAttrib(n, 'title');
+			nl.vspace.value = this.getAttrib(n, 'vspace');
+			nl.hspace.value = this.getAttrib(n, 'hspace');
+			nl.border.value = this.getAttrib(n, 'border');
+			selectByValue(f, 'align', this.getAttrib(n, 'align'));
+			selectByValue(f, 'class_list', dom.getAttrib(n, 'class'));
+			nl.style.value = dom.getAttrib(n, 'style');
+			nl.id.value = dom.getAttrib(n, 'id');
+			nl.dir.value = dom.getAttrib(n, 'dir');
+			nl.lang.value = dom.getAttrib(n, 'lang');
+			nl.usemap.value = dom.getAttrib(n, 'usemap');
+			nl.longdesc.value = dom.getAttrib(n, 'longdesc');
+			nl.insert.value = ed.getLang('update');
+
+			if (/^\s*this.src\s*=\s*\'([^\']+)\';?\s*$/.test(dom.getAttrib(n, 'onmouseover')))
+				nl.onmouseoversrc.value = dom.getAttrib(n, 'onmouseover').replace(/^\s*this.src\s*=\s*\'([^\']+)\';?\s*$/, '$1');
+
+			if (/^\s*this.src\s*=\s*\'([^\']+)\';?\s*$/.test(dom.getAttrib(n, 'onmouseout')))
+				nl.onmouseoutsrc.value = dom.getAttrib(n, 'onmouseout').replace(/^\s*this.src\s*=\s*\'([^\']+)\';?\s*$/, '$1');
+
+			if (ed.settings.inline_styles) {
+				// Move attribs to styles
+				if (dom.getAttrib(n, 'align'))
+					this.updateStyle('align');
+
+				if (dom.getAttrib(n, 'hspace'))
+					this.updateStyle('hspace');
+
+				if (dom.getAttrib(n, 'border'))
+					this.updateStyle('border');
+
+				if (dom.getAttrib(n, 'vspace'))
+					this.updateStyle('vspace');
+			}
+		}
+
+		// Setup browse button
+		document.getElementById('srcbrowsercontainer').innerHTML = getBrowserHTML('srcbrowser','src','image','theme_advanced_image');
+		if (isVisible('srcbrowser'))
+			document.getElementById('src').style.width = '260px';
+
+		// Setup browse button
+		document.getElementById('onmouseoversrccontainer').innerHTML = getBrowserHTML('overbrowser','onmouseoversrc','image','theme_advanced_image');
+		if (isVisible('overbrowser'))
+			document.getElementById('onmouseoversrc').style.width = '260px';
+
+		// Setup browse button
+		document.getElementById('onmouseoutsrccontainer').innerHTML = getBrowserHTML('outbrowser','onmouseoutsrc','image','theme_advanced_image');
+		if (isVisible('outbrowser'))
+			document.getElementById('onmouseoutsrc').style.width = '260px';
+
+		// If option enabled default contrain proportions to checked
+		if (ed.getParam("advimage_constrain_proportions", true))
+			f.constrain.checked = true;
+
+		// Check swap image if valid data
+		if (nl.onmouseoversrc.value || nl.onmouseoutsrc.value)
+			this.setSwapImage(true);
+		else
+			this.setSwapImage(false);
+
+		this.changeAppearance();
+		this.showPreviewImage(nl.src.value, 1);
+	},
+
+	insert : function(file, title) {
+		var ed = tinyMCEPopup.editor, t = this, f = document.forms[0];
+
+		if (f.src.value === '') {
+			ed.dom.remove(ed.selection.getNode());
+			ed.execCommand('mceRepaint');
+			tinyMCEPopup.close();
+			return;
+		}
+
+		if (tinyMCEPopup.getParam("accessibility_warnings", 1)) {
+			if (!f.alt.value) {
+				tinyMCEPopup.editor.windowManager.confirm(tinyMCEPopup.getLang('advimage_dlg.missing_alt'), function(s) {
+					if (s)
+						t.insertAndClose();
+				});
+
+				return;
+			}
+		}
+
+		t.insertAndClose();
+	},
+
+	insertAndClose : function() {
+		var ed = tinyMCEPopup.editor, f = document.forms[0], nl = f.elements, v, args = {}, el;
+
+		// Fixes crash in Safari
+		if (tinymce.isWebKit)
+			ed.getWin().focus();
+
+		if (!ed.settings.inline_styles) {
+			args = {
+				vspace : nl.vspace.value,
+				hspace : nl.hspace.value,
+				border : nl.border.value,
+				align : getSelectValue(f, 'align')
+			};
+		} else {
+			// Remove deprecated values
+			args = {
+				vspace : '',
+				hspace : '',
+				border : '',
+				align : ''
+			};
+		}
+
+		tinymce.extend(args, {
+			src : nl.src.value,
+			width : nl.width.value,
+			height : nl.height.value,
+			alt : nl.alt.value,
+			title : nl.title.value,
+			'class' : getSelectValue(f, 'class_list'),
+			style : nl.style.value,
+			id : nl.id.value,
+			dir : nl.dir.value,
+			lang : nl.lang.value,
+			usemap : nl.usemap.value,
+			longdesc : nl.longdesc.value
+		});
+
+		args.onmouseover = args.onmouseout = '';
+
+		if (f.onmousemovecheck.checked) {
+			if (nl.onmouseoversrc.value)
+				args.onmouseover = "this.src='" + nl.onmouseoversrc.value + "';";
+
+			if (nl.onmouseoutsrc.value)
+				args.onmouseout = "this.src='" + nl.onmouseoutsrc.value + "';";
+		}
+
+		el = ed.selection.getNode();
+
+		if (el && el.nodeName == 'IMG') {
+			ed.dom.setAttribs(el, args);
+		} else {
+			ed.execCommand('mceInsertContent', false, '<img id="__mce_tmp" src="javascript:;" />');
+			ed.dom.setAttribs('__mce_tmp', args);
+			ed.dom.setAttrib('__mce_tmp', 'id', '');
+		}
+
+		tinyMCEPopup.close();
+	},
+
+	getAttrib : function(e, at) {
+		var ed = tinyMCEPopup.editor, dom = ed.dom, v, v2;
+
+		if (ed.settings.inline_styles) {
+			switch (at) {
+				case 'align':
+					if (v = dom.getStyle(e, 'float'))
+						return v;
+
+					if (v = dom.getStyle(e, 'vertical-align'))
+						return v;
+
+					break;
+
+				case 'hspace':
+					v = dom.getStyle(e, 'margin-left')
+					v2 = dom.getStyle(e, 'margin-right');
+
+					if (v && v == v2)
+						return parseInt(v.replace(/[^0-9]/g, ''));
+
+					break;
+
+				case 'vspace':
+					v = dom.getStyle(e, 'margin-top')
+					v2 = dom.getStyle(e, 'margin-bottom');
+					if (v && v == v2)
+						return parseInt(v.replace(/[^0-9]/g, ''));
+
+					break;
+
+				case 'border':
+					v = 0;
+
+					tinymce.each(['top', 'right', 'bottom', 'left'], function(sv) {
+						sv = dom.getStyle(e, 'border-' + sv + '-width');
+
+						// False or not the same as prev
+						if (!sv || (sv != v && v !== 0)) {
+							v = 0;
+							return false;
+						}
+
+						if (sv)
+							v = sv;
+					});
+
+					if (v)
+						return parseInt(v.replace(/[^0-9]/g, ''));
+
+					break;
+			}
+		}
+
+		if (v = dom.getAttrib(e, at))
+			return v;
+
+		return '';
+	},
+
+	setSwapImage : function(st) {
+		var f = document.forms[0];
+
+		f.onmousemovecheck.checked = st;
+		setBrowserDisabled('overbrowser', !st);
+		setBrowserDisabled('outbrowser', !st);
+
+		if (f.over_list)
+			f.over_list.disabled = !st;
+
+		if (f.out_list)
+			f.out_list.disabled = !st;
+
+		f.onmouseoversrc.disabled = !st;
+		f.onmouseoutsrc.disabled  = !st;
+	},
+
+	fillClassList : function(id) {
+		var dom = tinyMCEPopup.dom, lst = dom.get(id), v, cl;
+
+		if (v = tinyMCEPopup.getParam('theme_advanced_styles')) {
+			cl = [];
+
+			tinymce.each(v.split(';'), function(v) {
+				var p = v.split('=');
+
+				cl.push({'title' : p[0], 'class' : p[1]});
+			});
+		} else
+			cl = tinyMCEPopup.editor.dom.getClasses();
+
+		if (cl.length > 0) {
+			lst.options[lst.options.length] = new Option(tinyMCEPopup.getLang('not_set'), '');
+
+			tinymce.each(cl, function(o) {
+				lst.options[lst.options.length] = new Option(o.title || o['class'], o['class']);
+			});
+		} else
+			dom.remove(dom.getParent(id, 'tr'));
+	},
+
+	fillFileList : function(id, l) {
+		var dom = tinyMCEPopup.dom, lst = dom.get(id), v, cl;
+
+		l = window[l];
+
+		if (l && l.length > 0) {
+			lst.options[lst.options.length] = new Option('', '');
+
+			tinymce.each(l, function(o) {
+				lst.options[lst.options.length] = new Option(o[0], o[1]);
+			});
+		} else
+			dom.remove(dom.getParent(id, 'tr'));
+	},
+
+	resetImageData : function() {
+		var f = document.forms[0];
+
+		f.elements.width.value = f.elements.height.value = '';
+	},
+
+	updateImageData : function(img, st) {
+		var f = document.forms[0];
+
+		if (!st) {
+			f.elements.width.value = img.width;
+			f.elements.height.value = img.height;
+		}
+
+		this.preloadImg = img;
+	},
+
+	changeAppearance : function() {
+		var ed = tinyMCEPopup.editor, f = document.forms[0], img = document.getElementById('alignSampleImg');
+
+		if (img) {
+			if (ed.getParam('inline_styles')) {
+				ed.dom.setAttrib(img, 'style', f.style.value);
+			} else {
+				img.align = f.align.value;
+				img.border = f.border.value;
+				img.hspace = f.hspace.value;
+				img.vspace = f.vspace.value;
+			}
+		}
+	},
+
+	changeHeight : function() {
+		var f = document.forms[0], tp, t = this;
+
+		if (!f.constrain.checked || !t.preloadImg) {
+			return;
+		}
+
+		if (f.width.value == "" || f.height.value == "")
+			return;
+
+		tp = (parseInt(f.width.value) / parseInt(t.preloadImg.width)) * t.preloadImg.height;
+		f.height.value = tp.toFixed(0);
+	},
+
+	changeWidth : function() {
+		var f = document.forms[0], tp, t = this;
+
+		if (!f.constrain.checked || !t.preloadImg) {
+			return;
+		}
+
+		if (f.width.value == "" || f.height.value == "")
+			return;
+
+		tp = (parseInt(f.height.value) / parseInt(t.preloadImg.height)) * t.preloadImg.width;
+		f.width.value = tp.toFixed(0);
+	},
+
+	updateStyle : function(ty) {
+		var dom = tinyMCEPopup.dom, st, v, f = document.forms[0], img = dom.create('img', {style : dom.get('style').value});
+
+		if (tinyMCEPopup.editor.settings.inline_styles) {
+			// Handle align
+			if (ty == 'align') {
+				dom.setStyle(img, 'float', '');
+				dom.setStyle(img, 'vertical-align', '');
+
+				v = getSelectValue(f, 'align');
+				if (v) {
+					if (v == 'left' || v == 'right')
+						dom.setStyle(img, 'float', v);
+					else
+						img.style.verticalAlign = v;
+				}
+			}
+
+			// Handle border
+			if (ty == 'border') {
+				dom.setStyle(img, 'border', '');
+
+				v = f.border.value;
+				if (v || v == '0') {
+					if (v == '0')
+						img.style.border = '';
+					else
+						img.style.border = v + 'px solid black';
+				}
+			}
+
+			// Handle hspace
+			if (ty == 'hspace') {
+				dom.setStyle(img, 'marginLeft', '');
+				dom.setStyle(img, 'marginRight', '');
+
+				v = f.hspace.value;
+				if (v) {
+					img.style.marginLeft = v + 'px';
+					img.style.marginRight = v + 'px';
+				}
+			}
+
+			// Handle vspace
+			if (ty == 'vspace') {
+				dom.setStyle(img, 'marginTop', '');
+				dom.setStyle(img, 'marginBottom', '');
+
+				v = f.vspace.value;
+				if (v) {
+					img.style.marginTop = v + 'px';
+					img.style.marginBottom = v + 'px';
+				}
+			}
+
+			// Merge
+			dom.get('style').value = dom.serializeStyle(dom.parseStyle(img.style.cssText));
+		}
+	},
+
+	changeMouseMove : function() {
+	},
+
+	showPreviewImage : function(u, st) {
+		if (!u) {
+			tinyMCEPopup.dom.setHTML('prev', '');
+			return;
+		}
+
+		if (!st && tinyMCEPopup.getParam("advimage_update_dimensions_onchange", true))
+			this.resetImageData();
+
+		u = tinyMCEPopup.editor.documentBaseURI.toAbsolute(u);
+
+		if (!st)
+			tinyMCEPopup.dom.setHTML('prev', '<img id="previewImg" src="' + u + '" border="0" onload="ImageDialog.updateImageData(this);" onerror="ImageDialog.resetImageData();" />');
+		else
+			tinyMCEPopup.dom.setHTML('prev', '<img id="previewImg" src="' + u + '" border="0" onload="ImageDialog.updateImageData(this, 1);" />');
+	}
+};
+
+ImageDialog.preInit();
+tinyMCEPopup.onInit.add(ImageDialog.init, ImageDialog);
--- a/includes/clientside/tinymce/plugins/advimage/jscripts/functions.js	Fri Feb 22 12:46:51 2008 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,534 +0,0 @@
-/* Functions for the advimage plugin popup */
-
-var preloadImg = null;
-var orgImageWidth, orgImageHeight;
-
-function preinit() {
-	// Initialize
-	tinyMCE.setWindowArg('mce_windowresize', false);
-
-	// Import external list url javascript
-	var url = tinyMCE.getParam("external_image_list_url");
-	if (url != null) {
-		// Fix relative
-		if (url.charAt(0) != '/' && url.indexOf('://') == -1)
-			url = tinyMCE.documentBasePath + "/" + url;
-
-		document.write('<sc'+'ript language="javascript" type="text/javascript" src="' + url + '"></sc'+'ript>');
-	}
-}
-
-function convertURL(url, node, on_save) {
-	return eval("tinyMCEPopup.windowOpener." + tinyMCE.settings['urlconverter_callback'] + "(url, node, on_save);");
-}
-
-function getImageSrc(str) {
-	var pos = -1;
-
-	if (!str)
-		return "";
-
-	if ((pos = str.indexOf('this.src=')) != -1) {
-		var src = str.substring(pos + 10);
-
-		src = src.substring(0, src.indexOf('\''));
-
-		if (tinyMCE.getParam('convert_urls'))
-			src = convertURL(src, null, true);
-
-		return src;
-	}
-
-	return "";
-}
-
-function init() {
-	tinyMCEPopup.resizeToInnerSize();
-
-	var formObj = document.forms[0];
-	var inst = tinyMCE.getInstanceById(tinyMCE.getWindowArg('editor_id'));
-	var elm = inst.getFocusElement();
-	var action = "insert";
-	var html = "";
-
-	// Image list src
-	html = getImageListHTML('imagelistsrc','src','onSelectMainImage');
-	if (html == "")
-		document.getElementById("imagelistsrcrow").style.display = 'none';
-	else
-		document.getElementById("imagelistsrccontainer").innerHTML = html;
-
-	// Image list oversrc
-	html = getImageListHTML('imagelistover','onmouseoversrc');
-	if (html == "")
-		document.getElementById("imagelistoverrow").style.display = 'none';
-	else
-		document.getElementById("imagelistovercontainer").innerHTML = html;
-
-	// Image list outsrc
-	html = getImageListHTML('imagelistout','onmouseoutsrc');
-	if (html == "")
-		document.getElementById("imagelistoutrow").style.display = 'none';
-	else
-		document.getElementById("imagelistoutcontainer").innerHTML = html;
-
-	// Src browser
-	html = getBrowserHTML('srcbrowser','src','image','advimage');
-	document.getElementById("srcbrowsercontainer").innerHTML = html;
-
-	// Over browser
-	html = getBrowserHTML('oversrcbrowser','onmouseoversrc','image','advimage');
-	document.getElementById("onmouseoversrccontainer").innerHTML = html;
-
-	// Out browser
-	html = getBrowserHTML('outsrcbrowser','onmouseoutsrc','image','advimage');
-	document.getElementById("onmouseoutsrccontainer").innerHTML = html;
-
-	// Longdesc browser
-	html = getBrowserHTML('longdescbrowser','longdesc','file','advimage');
-	document.getElementById("longdesccontainer").innerHTML = html;
-
-	// Resize some elements
-	if (isVisible('srcbrowser'))
-		document.getElementById('src').style.width = '260px';
-
-	if (isVisible('oversrcbrowser'))
-		document.getElementById('onmouseoversrc').style.width = '260px';
-
-	if (isVisible('outsrcbrowser'))
-		document.getElementById('onmouseoutsrc').style.width = '260px';
-
-	if (isVisible('longdescbrowser'))
-		document.getElementById('longdesc').style.width = '180px';
-
-	// Check action
-	if (elm != null && elm.nodeName == "IMG")
-		action = "update";
-
-	formObj.insert.value = tinyMCE.getLang('lang_' + action, 'Insert', true); 
-
-	if (action == "update") {
-		var src = tinyMCE.getAttrib(elm, 'src');
-		var onmouseoversrc = getImageSrc(tinyMCE.cleanupEventStr(tinyMCE.getAttrib(elm, 'onmouseover')));
-		var onmouseoutsrc = getImageSrc(tinyMCE.cleanupEventStr(tinyMCE.getAttrib(elm, 'onmouseout')));
-
-		src = convertURL(src, elm, true);
-
-		// Use mce_src if found
-		var mceRealSrc = tinyMCE.getAttrib(elm, 'mce_src');
-		if (mceRealSrc != "") {
-			src = mceRealSrc;
-
-			if (tinyMCE.getParam('convert_urls'))
-				src = convertURL(src, elm, true);
-		}
-
-		if (onmouseoversrc != "" && tinyMCE.getParam('convert_urls'))
-			onmouseoversrc = convertURL(onmouseoversrc, elm, true);
-
-		if (onmouseoutsrc != "" && tinyMCE.getParam('convert_urls'))
-			onmouseoutsrc = convertURL(onmouseoutsrc, elm, true);
-
-		// Setup form data
-		var style = tinyMCE.parseStyle(tinyMCE.getAttrib(elm, "style"));
-
-		// Store away old size
-		orgImageWidth = trimSize(getStyle(elm, 'width'))
-		orgImageHeight = trimSize(getStyle(elm, 'height'));
-
-		formObj.src.value    = src;
-		formObj.alt.value    = tinyMCE.getAttrib(elm, 'alt');
-		formObj.title.value  = tinyMCE.getAttrib(elm, 'title');
-		formObj.border.value = trimSize(getStyle(elm, 'border', 'borderWidth'));
-		formObj.vspace.value = tinyMCE.getAttrib(elm, 'vspace');
-		formObj.hspace.value = tinyMCE.getAttrib(elm, 'hspace');
-		formObj.width.value  = orgImageWidth;
-		formObj.height.value = orgImageHeight;
-		formObj.onmouseoversrc.value = onmouseoversrc;
-		formObj.onmouseoutsrc.value  = onmouseoutsrc;
-		formObj.id.value  = tinyMCE.getAttrib(elm, 'id');
-		formObj.dir.value  = tinyMCE.getAttrib(elm, 'dir');
-		formObj.lang.value  = tinyMCE.getAttrib(elm, 'lang');
-		formObj.longdesc.value  = tinyMCE.getAttrib(elm, 'longdesc');
-		formObj.usemap.value  = tinyMCE.getAttrib(elm, 'usemap');
-		formObj.style.value  = tinyMCE.serializeStyle(style);
-
-		// Select by the values
-		if (tinyMCE.isMSIE)
-			selectByValue(formObj, 'align', getStyle(elm, 'align', 'styleFloat'));
-		else
-			selectByValue(formObj, 'align', getStyle(elm, 'align', 'cssFloat'));
-
-		addClassesToList('classlist', 'advimage_styles');
-
-		selectByValue(formObj, 'classlist', tinyMCE.getAttrib(elm, 'class'));
-		selectByValue(formObj, 'imagelistsrc', src);
-		selectByValue(formObj, 'imagelistover', onmouseoversrc);
-		selectByValue(formObj, 'imagelistout', onmouseoutsrc);
-
-		updateStyle();
-		showPreviewImage(src, true);
-		changeAppearance();
-
-		window.focus();
-	} else
-		addClassesToList('classlist', 'advimage_styles');
-
-	// If option enabled default contrain proportions to checked
-	if (tinyMCE.getParam("advimage_constrain_proportions", true))
-		formObj.constrain.checked = true;
-
-	// Check swap image if valid data
-	if (formObj.onmouseoversrc.value != "" || formObj.onmouseoutsrc.value != "")
-		setSwapImageDisabled(false);
-	else
-		setSwapImageDisabled(true);
-}
-
-function setSwapImageDisabled(state) {
-	var formObj = document.forms[0];
-
-	formObj.onmousemovecheck.checked = !state;
-
-	setBrowserDisabled('overbrowser', state);
-	setBrowserDisabled('outbrowser', state);
-
-	if (formObj.imagelistover)
-		formObj.imagelistover.disabled = state;
-
-	if (formObj.imagelistout)
-		formObj.imagelistout.disabled = state;
-
-	formObj.onmouseoversrc.disabled = state;
-	formObj.onmouseoutsrc.disabled  = state;
-}
-
-function setAttrib(elm, attrib, value) {
-	var formObj = document.forms[0];
-	var valueElm = formObj.elements[attrib];
-
-	if (typeof(value) == "undefined" || value == null) {
-		value = "";
-
-		if (valueElm)
-			value = valueElm.value;
-	}
-
-	if (value != "") {
-		elm.setAttribute(attrib, value);
-
-		if (attrib == "style")
-			attrib = "style.cssText";
-
-		if (attrib == "longdesc")
-			attrib = "longDesc";
-
-		if (attrib == "width") {
-			attrib = "style.width";
-			value = value + "px";
-			value = value.replace(/%px/g, 'px');
-		}
-
-		if (attrib == "height") {
-			attrib = "style.height";
-			value = value + "px";
-			value = value.replace(/%px/g, 'px');
-		}
-
-		if (attrib == "class")
-			attrib = "className";
-
-		eval('elm.' + attrib + "=value;");
-	} else
-		elm.removeAttribute(attrib);
-}
-
-function makeAttrib(attrib, value) {
-	var formObj = document.forms[0];
-	var valueElm = formObj.elements[attrib];
-
-	if (typeof(value) == "undefined" || value == null) {
-		value = "";
-
-		if (valueElm)
-			value = valueElm.value;
-	}
-
-	if (value == "")
-		return "";
-
-	// XML encode it
-	value = value.replace(/&/g, '&amp;');
-	value = value.replace(/\"/g, '&quot;');
-	value = value.replace(/</g, '&lt;');
-	value = value.replace(/>/g, '&gt;');
-
-	return ' ' + attrib + '="' + value + '"';
-}
-
-function insertAction() {
-	var inst = tinyMCE.getInstanceById(tinyMCE.getWindowArg('editor_id'));
-	var elm = inst.getFocusElement();
-	var formObj = document.forms[0];
-	var src = formObj.src.value;
-	var onmouseoversrc = formObj.onmouseoversrc.value;
-	var onmouseoutsrc = formObj.onmouseoutsrc.value;
-
-	if (!AutoValidator.validate(formObj)) {
-		alert(tinyMCE.getLang('lang_invalid_data'));
-		return false;
-	}
-
-	if (tinyMCE.getParam("accessibility_warnings")) {
-		if (formObj.alt.value == "" && !confirm(tinyMCE.getLang('lang_advimage_missing_alt', '', true)))
-			return;
-	}
-
-	if (onmouseoversrc && onmouseoversrc != "")
-		onmouseoversrc = "this.src='" + convertURL(onmouseoversrc, tinyMCE.imgElement) + "';";
-
-	if (onmouseoutsrc && onmouseoutsrc != "")
-		onmouseoutsrc = "this.src='" + convertURL(onmouseoutsrc, tinyMCE.imgElement) + "';";
-
-	if (elm != null && elm.nodeName == "IMG") {
-		setAttrib(elm, 'src', convertURL(src, tinyMCE.imgElement));
-		setAttrib(elm, 'mce_src', src);
-		setAttrib(elm, 'alt');
-		setAttrib(elm, 'title');
-		setAttrib(elm, 'border');
-		setAttrib(elm, 'vspace');
-		setAttrib(elm, 'hspace');
-		setAttrib(elm, 'width');
-		setAttrib(elm, 'height');
-		setAttrib(elm, 'onmouseover', onmouseoversrc);
-		setAttrib(elm, 'onmouseout', onmouseoutsrc);
-		setAttrib(elm, 'id');
-		setAttrib(elm, 'dir');
-		setAttrib(elm, 'lang');
-		setAttrib(elm, 'longdesc');
-		setAttrib(elm, 'usemap');
-		setAttrib(elm, 'style');
-		setAttrib(elm, 'class', getSelectValue(formObj, 'classlist'));
-		setAttrib(elm, 'align', getSelectValue(formObj, 'align'));
-
-		//tinyMCEPopup.execCommand("mceRepaint");
-
-		// Repaint if dimensions changed
-		if (formObj.width.value != orgImageWidth || formObj.height.value != orgImageHeight)
-			inst.repaint();
-
-		// Refresh in old MSIE
-		if (tinyMCE.isMSIE5)
-			elm.outerHTML = elm.outerHTML;
-	} else {
-		var html = "<img";
-
-		html += makeAttrib('src', convertURL(src, tinyMCE.imgElement));
-		html += makeAttrib('mce_src', src);
-		html += makeAttrib('alt');
-		html += makeAttrib('title');
-		html += makeAttrib('border');
-		html += makeAttrib('vspace');
-		html += makeAttrib('hspace');
-		html += makeAttrib('width');
-		html += makeAttrib('height');
-		html += makeAttrib('onmouseover', onmouseoversrc);
-		html += makeAttrib('onmouseout', onmouseoutsrc);
-		html += makeAttrib('id');
-		html += makeAttrib('dir');
-		html += makeAttrib('lang');
-		html += makeAttrib('longdesc');
-		html += makeAttrib('usemap');
-		html += makeAttrib('style');
-		html += makeAttrib('class', getSelectValue(formObj, 'classlist'));
-		html += makeAttrib('align', getSelectValue(formObj, 'align'));
-		html += " />";
-
-		tinyMCEPopup.execCommand("mceInsertContent", false, html);
-	}
-
-	tinyMCE._setEventsEnabled(inst.getBody(), false);
-	tinyMCEPopup.close();
-}
-
-function cancelAction() {
-	tinyMCEPopup.close();
-}
-
-function changeAppearance() {
-	var formObj = document.forms[0];
-	var img = document.getElementById('alignSampleImg');
-
-	if (img) {
-		img.align = formObj.align.value;
-		img.border = formObj.border.value;
-		img.hspace = formObj.hspace.value;
-		img.vspace = formObj.vspace.value;
-	}
-}
-
-function changeMouseMove() {
-	var formObj = document.forms[0];
-
-	setSwapImageDisabled(!formObj.onmousemovecheck.checked);
-}
-
-function updateStyle() {
-	var formObj = document.forms[0];
-	var st = tinyMCE.parseStyle(formObj.style.value);
-
-	if (tinyMCE.getParam('inline_styles', false)) {
-		st['width'] = formObj.width.value == '' ? '' : formObj.width.value + "px";
-		st['height'] = formObj.height.value == '' ? '' : formObj.height.value + "px";
-		st['border-width'] = formObj.border.value == '' ? '' : formObj.border.value + "px";
-		st['margin-top'] = formObj.vspace.value == '' ? '' : formObj.vspace.value + "px";
-		st['margin-bottom'] = formObj.vspace.value == '' ? '' : formObj.vspace.value + "px";
-		st['margin-left'] = formObj.hspace.value == '' ? '' : formObj.hspace.value + "px";
-		st['margin-right'] = formObj.hspace.value == '' ? '' : formObj.hspace.value + "px";
-	} else {
-		st['width'] = st['height'] = st['border-width'] = null;
-
-		if (st['margin-top'] == st['margin-bottom'])
-			st['margin-top'] = st['margin-bottom'] = null;
-
-		if (st['margin-left'] == st['margin-right'])
-			st['margin-left'] = st['margin-right'] = null;
-	}
-
-	formObj.style.value = tinyMCE.serializeStyle(st);
-}
-
-function styleUpdated() {
-	var formObj = document.forms[0];
-	var st = tinyMCE.parseStyle(formObj.style.value);
-
-	if (st['width'])
-		formObj.width.value = st['width'].replace('px', '');
-
-	if (st['height'])
-		formObj.height.value = st['height'].replace('px', '');
-
-	if (st['margin-top'] && st['margin-top'] == st['margin-bottom'])
-		formObj.vspace.value = st['margin-top'].replace('px', '');
-
-	if (st['margin-left'] && st['margin-left'] == st['margin-right'])
-		formObj.hspace.value = st['margin-left'].replace('px', '');
-
-	if (st['border-width'])
-		formObj.border.value = st['border-width'].replace('px', '');
-}
-
-function changeHeight() {
-	var formObj = document.forms[0];
-
-	if (!formObj.constrain.checked || !preloadImg) {
-		updateStyle();
-		return;
-	}
-
-	if (formObj.width.value == "" || formObj.height.value == "")
-		return;
-
-	var temp = (parseInt(formObj.width.value) / parseInt(preloadImg.width)) * preloadImg.height;
-	formObj.height.value = temp.toFixed(0);
-	updateStyle();
-}
-
-function changeWidth() {
-	var formObj = document.forms[0];
-
-	if (!formObj.constrain.checked || !preloadImg) {
-		updateStyle();
-		return;
-	}
-
-	if (formObj.width.value == "" || formObj.height.value == "")
-		return;
-
-	var temp = (parseInt(formObj.height.value) / parseInt(preloadImg.height)) * preloadImg.width;
-	formObj.width.value = temp.toFixed(0);
-	updateStyle();
-}
-
-function onSelectMainImage(target_form_element, name, value) {
-	var formObj = document.forms[0];
-
-	formObj.alt.value = name;
-	formObj.title.value = name;
-
-	resetImageData();
-	showPreviewImage(formObj.elements[target_form_element].value, false);
-}
-
-function showPreviewImage(src, start) {
-	var formObj = document.forms[0];
-
-	selectByValue(document.forms[0], 'imagelistsrc', src);
-
-	var elm = document.getElementById('prev');
-	var src = src == "" ? src : tinyMCE.convertRelativeToAbsoluteURL(tinyMCE.settings['base_href'], src);
-
-	if (!start && tinyMCE.getParam("advimage_update_dimensions_onchange", true))
-		resetImageData();
-
-	if (src == "")
-		elm.innerHTML = "";
-	else
-		elm.innerHTML = '<img id="previewImg" src="' + src + '" border="0" onload="updateImageData();" onerror="resetImageData();" />'
-}
-
-function updateImageData() {
-	var formObj = document.forms[0];
-
-	preloadImg = document.getElementById('previewImg');
-
-	if (formObj.width.value == "")
-		formObj.width.value = preloadImg.width;
-
-	if (formObj.height.value == "")
-		formObj.height.value = preloadImg.height;
-
-	updateStyle();
-}
-
-function resetImageData() {
-	var formObj = document.forms[0];
-	formObj.width.value = formObj.height.value = "";	
-}
-
-function getSelectValue(form_obj, field_name) {
-	var elm = form_obj.elements[field_name];
-
-	if (elm == null || elm.options == null)
-		return "";
-
-	return elm.options[elm.selectedIndex].value;
-}
-
-function getImageListHTML(elm_id, target_form_element, onchange_func) {
-	if (typeof(tinyMCEImageList) == "undefined" || tinyMCEImageList.length == 0)
-		return "";
-
-	var html = "";
-
-	html += '<select id="' + elm_id + '" name="' + elm_id + '"';
-	html += ' class="mceImageList" onfocus="tinyMCE.addSelectAccessibility(event, this, window);" onchange="this.form.' + target_form_element + '.value=';
-	html += 'this.options[this.selectedIndex].value;';
-
-	if (typeof(onchange_func) != "undefined")
-		html += onchange_func + '(\'' + target_form_element + '\',this.options[this.selectedIndex].text,this.options[this.selectedIndex].value);';
-
-	html += '"><option value="">---</option>';
-
-	for (var i=0; i<tinyMCEImageList.length; i++)
-		html += '<option value="' + tinyMCEImageList[i][1] + '">' + tinyMCEImageList[i][0] + '</option>';
-
-	html += '</select>';
-
-	return html;
-
-	// tinyMCE.debug('-- image list start --', html, '-- image list end --');
-}
-
-// While loading
-preinit();
--- a/includes/clientside/tinymce/plugins/advimage/langs/en.js	Fri Feb 22 12:46:51 2008 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,27 +0,0 @@
-// UK lang variables
-
-tinyMCE.addToLang('advimage',{
-tab_general : 'General',
-tab_appearance : 'Appearance',
-tab_advanced : 'Advanced',
-general : 'General',
-title : 'Title',
-preview : 'Preview',
-constrain_proportions : 'Constrain proportions',
-langdir : 'Language direction',
-langcode : 'Language code',
-long_desc : 'Long description link',
-style : 'Style',
-classes : 'Classes',
-ltr : 'Left to right',
-rtl : 'Right to left',
-id : 'Id',
-image_map : 'Image map',
-swap_image : 'Swap image',
-alt_image : 'Alternative image',
-mouseover : 'for mouse over',
-mouseout : 'for mouse out',
-misc : 'Miscellaneous',
-example_img : 'Appearance&nbsp;preview&nbsp;image',
-missing_alt : 'Are you sure you want to continue without including an Image Description? Without  it the image may not be accessible to some users with disabilities, or to those using a text browser, or browsing the Web with images turned off.'
-});
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/includes/clientside/tinymce/plugins/advimage/langs/en_dlg.js	Fri Feb 22 12:51:53 2008 -0500
@@ -0,0 +1,43 @@
+tinyMCE.addI18n('en.advimage_dlg',{
+tab_general:"General",
+tab_appearance:"Appearance",
+tab_advanced:"Advanced",
+general:"General",
+title:"Title",
+preview:"Preview",
+constrain_proportions:"Constrain proportions",
+langdir:"Language direction",
+langcode:"Language code",
+long_desc:"Long description link",
+style:"Style",
+classes:"Classes",
+ltr:"Left to right",
+rtl:"Right to left",
+id:"Id",
+map:"Image map",
+swap_image:"Swap image",
+alt_image:"Alternative image",
+mouseover:"for mouse over",
+mouseout:"for mouse out",
+misc:"Miscellaneous",
+example_img:"Appearance preview image",
+missing_alt:"Are you sure you want to continue without including an Image Description? Without it the image may not be accessible to some users with disabilities, or to those using a text browser, or browsing the Web with images turned off.",
+dialog_title:"Insert/edit image",
+src:"Image URL",
+alt:"Image description",
+list:"Image list",
+border:"Border",
+dimensions:"Dimensions",
+vspace:"Vertical space",
+hspace:"Horizontal space",
+align:"Alignment",
+align_baseline:"Baseline",
+align_top:"Top",
+align_middle:"Middle",
+align_bottom:"Bottom",
+align_texttop:"Text top",
+align_textbottom:"Text bottom",
+align_left:"Left",
+align_right:"Right",
+image_list:"Image list"
+});
\ No newline at end of file
--- a/includes/clientside/tinymce/plugins/advimage/readme.txt	Fri Feb 22 12:46:51 2008 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1 +0,0 @@
-Check the TinyMCE documentation for details on this plugin.
--- a/includes/clientside/tinymce/plugins/advlink/css/advlink.css	Fri Feb 22 12:46:51 2008 -0500
+++ b/includes/clientside/tinymce/plugins/advlink/css/advlink.css	Fri Feb 22 12:51:53 2008 -0500
@@ -1,35 +1,8 @@
-/* CSS file for advimage plugin popup */
-
-.mceLinkList, .mceAnchorList, #targetlist {
-	width: 280px;
-}
-
-.mceActionPanel {
-	margin-top: 7px;
-}
-
-.panel_wrapper div.current {
-	height: 320px;
-}
-
-#classlist, #title, #href {
-	width: 280px;
-}
-
-#popupurl, #popupname {
-	width: 200px;
-}
-
-#popupwidth, #popupheight, #popupleft, #popuptop {
-	width: 30px;
-	vertical-align: middle;
-	text-align: center;
-}
-
-#id, #style, #classes, #target, #dir, #hreflang, #lang, #charset, #type, #rel, #rev, #tabindex, #accesskey {
-	width: 200px;
-}
-
-#events_panel input {
-	width: 200px;
-}
+.mceLinkList, .mceAnchorList, #targetlist {width:280px;}
+.mceActionPanel {margin-top:7px;}
+.panel_wrapper div.current {height:320px;}
+#classlist, #title, #href {width:280px;}
+#popupurl, #popupname {width:200px;}
+#popupwidth, #popupheight, #popupleft, #popuptop {width:30px;vertical-align:middle;text-align:center;}
+#id, #style, #classes, #target, #dir, #hreflang, #lang, #charset, #type, #rel, #rev, #tabindex, #accesskey {width:200px;}
+#events_panel input {width:200px;}
--- a/includes/clientside/tinymce/plugins/advlink/editor_plugin.js	Fri Feb 22 12:46:51 2008 -0500
+++ b/includes/clientside/tinymce/plugins/advlink/editor_plugin.js	Fri Feb 22 12:51:53 2008 -0500
@@ -1,1 +1,1 @@
-tinyMCE.importPluginLanguagePack('advlink');var TinyMCE_AdvancedLinkPlugin={getInfo:function(){return{longname:'Advanced link',author:'Moxiecode Systems AB',authorurl:'http://tinymce.moxiecode.com',infourl:'http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/advlink',version:tinyMCE.majorVersion+"."+tinyMCE.minorVersion}},initInstance:function(inst){inst.addShortcut('ctrl','k','lang_advlink_desc','mceAdvLink')},getControlHTML:function(cn){switch(cn){case"link":return tinyMCE.getButtonHTML(cn,'lang_link_desc','{$themeurl}/images/link.gif','mceAdvLink')}return""},execCommand:function(editor_id,element,command,user_interface,value){switch(command){case"mceAdvLink":var anySelection=false;var inst=tinyMCE.getInstanceById(editor_id);var focusElm=inst.getFocusElement();var selectedText=inst.selection.getSelectedText();if(tinyMCE.selectedElement)anySelection=(tinyMCE.selectedElement.nodeName.toLowerCase()=="img")||(selectedText&&selectedText.length>0);if(anySelection||(focusElm!=null&&focusElm.nodeName=="A")){var template=new Array();template['file']='../../plugins/advlink/link.htm';template['width']=480;template['height']=400;template['width']+=tinyMCE.getLang('lang_advlink_delta_width',0);template['height']+=tinyMCE.getLang('lang_advlink_delta_height',0);tinyMCE.openWindow(template,{editor_id:editor_id,inline:"yes"})}return true}return false},handleNodeChange:function(editor_id,node,undo_index,undo_levels,visual_aid,any_selection){if(node==null)return;do{if(node.nodeName=="A"&&tinyMCE.getAttrib(node,'href')!=""){tinyMCE.switchClass(editor_id+'_advlink','mceButtonSelected');return true}}while((node=node.parentNode));if(any_selection){tinyMCE.switchClass(editor_id+'_advlink','mceButtonNormal');return true}tinyMCE.switchClass(editor_id+'_advlink','mceButtonDisabled');return true}};tinyMCE.addPlugin("advlink",TinyMCE_AdvancedLinkPlugin);
\ No newline at end of file
+(function(){tinymce.create('tinymce.plugins.AdvancedLinkPlugin',{init:function(ed,url){this.editor=ed;ed.addCommand('mceAdvLink',function(){var se=ed.selection;if(se.isCollapsed()&&!ed.dom.getParent(se.getNode(),'A'))return;ed.windowManager.open({file:url+'/link.htm',width:480+parseInt(ed.getLang('advlink.delta_width',0)),height:400+parseInt(ed.getLang('advlink.delta_height',0)),inline:1},{plugin_url:url});});ed.addButton('link',{title:'advlink.link_desc',cmd:'mceAdvLink'});ed.addShortcut('ctrl+k','advlink.advlink_desc','mceAdvLink');ed.onNodeChange.add(function(ed,cm,n,co){cm.setDisabled('link',co&&n.nodeName!='A');cm.setActive('link',n.nodeName=='A'&&!n.name);});},getInfo:function(){return{longname:'Advanced link',author:'Moxiecode Systems AB',authorurl:'http://tinymce.moxiecode.com',infourl:'http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/advlink',version:tinymce.majorVersion+"."+tinymce.minorVersion};}});tinymce.PluginManager.add('advlink',tinymce.plugins.AdvancedLinkPlugin);})();
\ No newline at end of file
--- a/includes/clientside/tinymce/plugins/advlink/editor_plugin_src.js	Fri Feb 22 12:46:51 2008 -0500
+++ b/includes/clientside/tinymce/plugins/advlink/editor_plugin_src.js	Fri Feb 22 12:51:53 2008 -0500
@@ -1,88 +1,58 @@
 /**
- * $Id: editor_plugin_src.js 201 2007-02-12 15:56:56Z spocke $
+ * $Id: editor_plugin_src.js 539 2008-01-14 19:08:58Z spocke $
  *
  * @author Moxiecode
- * @copyright Copyright © 2004-2007, Moxiecode Systems AB, All rights reserved.
+ * @copyright Copyright © 2004-2008, Moxiecode Systems AB, All rights reserved.
  */
 
-/* Import plugin specific language pack */
-tinyMCE.importPluginLanguagePack('advlink');
+(function() {
+	tinymce.create('tinymce.plugins.AdvancedLinkPlugin', {
+		init : function(ed, url) {
+			this.editor = ed;
 
-var TinyMCE_AdvancedLinkPlugin = {
-	getInfo : function() {
-		return {
-			longname : 'Advanced link',
-			author : 'Moxiecode Systems AB',
-			authorurl : 'http://tinymce.moxiecode.com',
-			infourl : 'http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/advlink',
-			version : tinyMCE.majorVersion + "." + tinyMCE.minorVersion
-		};
-	},
-
-	initInstance : function(inst) {
-		inst.addShortcut('ctrl', 'k', 'lang_advlink_desc', 'mceAdvLink');
-	},
+			// Register commands
+			ed.addCommand('mceAdvLink', function() {
+				var se = ed.selection;
 
-	getControlHTML : function(cn) {
-		switch (cn) {
-			case "link":
-				return tinyMCE.getButtonHTML(cn, 'lang_link_desc', '{$themeurl}/images/link.gif', 'mceAdvLink');
-		}
-
-		return "";
-	},
+				// No selection and not in link
+				if (se.isCollapsed() && !ed.dom.getParent(se.getNode(), 'A'))
+					return;
 
-	execCommand : function(editor_id, element, command, user_interface, value) {
-		switch (command) {
-			case "mceAdvLink":
-				var anySelection = false;
-				var inst = tinyMCE.getInstanceById(editor_id);
-				var focusElm = inst.getFocusElement();
-				var selectedText = inst.selection.getSelectedText();
-
-				if (tinyMCE.selectedElement)
-					anySelection = (tinyMCE.selectedElement.nodeName.toLowerCase() == "img") || (selectedText && selectedText.length > 0);
-
-				if (anySelection || (focusElm != null && focusElm.nodeName == "A")) {
-					var template = new Array();
+				ed.windowManager.open({
+					file : url + '/link.htm',
+					width : 480 + parseInt(ed.getLang('advlink.delta_width', 0)),
+					height : 400 + parseInt(ed.getLang('advlink.delta_height', 0)),
+					inline : 1
+				}, {
+					plugin_url : url
+				});
+			});
 
-					template['file']   = '../../plugins/advlink/link.htm';
-					template['width']  = 480;
-					template['height'] = 400;
-
-					// Language specific width and height addons
-					template['width']  += tinyMCE.getLang('lang_advlink_delta_width', 0);
-					template['height'] += tinyMCE.getLang('lang_advlink_delta_height', 0);
+			// Register buttons
+			ed.addButton('link', {
+				title : 'advlink.link_desc',
+				cmd : 'mceAdvLink'
+			});
 
-					tinyMCE.openWindow(template, {editor_id : editor_id, inline : "yes"});
-				}
+			ed.addShortcut('ctrl+k', 'advlink.advlink_desc', 'mceAdvLink');
 
-				return true;
-		}
-
-		return false;
-	},
+			ed.onNodeChange.add(function(ed, cm, n, co) {
+				cm.setDisabled('link', co && n.nodeName != 'A');
+				cm.setActive('link', n.nodeName == 'A' && !n.name);
+			});
+		},
 
-	handleNodeChange : function(editor_id, node, undo_index, undo_levels, visual_aid, any_selection) {
-		if (node == null)
-			return;
-
-		do {
-			if (node.nodeName == "A" && tinyMCE.getAttrib(node, 'href') != "") {
-				tinyMCE.switchClass(editor_id + '_advlink', 'mceButtonSelected');
-				return true;
-			}
-		} while ((node = node.parentNode));
+		getInfo : function() {
+			return {
+				longname : 'Advanced link',
+				author : 'Moxiecode Systems AB',
+				authorurl : 'http://tinymce.moxiecode.com',
+				infourl : 'http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/advlink',
+				version : tinymce.majorVersion + "." + tinymce.minorVersion
+			};
+		}
+	});
 
-		if (any_selection) {
-			tinyMCE.switchClass(editor_id + '_advlink', 'mceButtonNormal');
-			return true;
-		}
-
-		tinyMCE.switchClass(editor_id + '_advlink', 'mceButtonDisabled');
-
-		return true;
-	}
-};
-
-tinyMCE.addPlugin("advlink", TinyMCE_AdvancedLinkPlugin);
+	// Register plugin
+	tinymce.PluginManager.add('advlink', tinymce.plugins.AdvancedLinkPlugin);
+})();
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/includes/clientside/tinymce/plugins/advlink/js/advlink.js	Fri Feb 22 12:51:53 2008 -0500
@@ -0,0 +1,563 @@
+/* Functions for the advlink plugin popup */
+
+tinyMCEPopup.requireLangPack();
+
+var templates = {
+	"window.open" : "window.open('${url}','${target}','${options}')"
+};
+
+function preinit() {
+	var url;
+
+	if (url = tinyMCEPopup.getParam("external_link_list_url"))
+		document.write('<script language="javascript" type="text/javascript" src="' + tinyMCEPopup.editor.documentBaseURI.toAbsolute(url) + '"></script>');
+}
+
+function changeClass() {
+	var formObj = document.forms[0];
+	formObj.classes.value = getSelectValue(formObj, 'classlist');
+}
+
+function init() {
+	tinyMCEPopup.resizeToInnerSize();
+
+	var formObj = document.forms[0];
+	var inst = tinyMCEPopup.editor;
+	var elm = inst.selection.getNode();
+	var action = "insert";
+	var html;
+
+	document.getElementById('hrefbrowsercontainer').innerHTML = getBrowserHTML('hrefbrowser','href','file','advlink');
+	document.getElementById('popupurlbrowsercontainer').innerHTML = getBrowserHTML('popupurlbrowser','popupurl','file','advlink');
+	document.getElementById('linklisthrefcontainer').innerHTML = getLinkListHTML('linklisthref','href');
+	document.getElementById('anchorlistcontainer').innerHTML = getAnchorListHTML('anchorlist','href');
+	document.getElementById('targetlistcontainer').innerHTML = getTargetListHTML('targetlist','target');
+
+	// Link list
+	html = getLinkListHTML('linklisthref','href');
+	if (html == "")
+		document.getElementById("linklisthrefrow").style.display = 'none';
+	else
+		document.getElementById("linklisthrefcontainer").innerHTML = html;
+
+	// Resize some elements
+	if (isVisible('hrefbrowser'))
+		document.getElementById('href').style.width = '260px';
+
+	if (isVisible('popupurlbrowser'))
+		document.getElementById('popupurl').style.width = '180px';
+
+	elm = inst.dom.getParent(elm, "A");
+	if (elm != null && elm.nodeName == "A")
+		action = "update";
+
+	formObj.insert.value = tinyMCEPopup.getLang(action, 'Insert', true); 
+
+	setPopupControlsDisabled(true);
+
+	if (action == "update") {
+		var href = inst.dom.getAttrib(elm, 'href');
+		var onclick = inst.dom.getAttrib(elm, 'onclick');
+
+		// Setup form data
+		setFormValue('href', href);
+		setFormValue('title', inst.dom.getAttrib(elm, 'title'));
+		setFormValue('id', inst.dom.getAttrib(elm, 'id'));
+		setFormValue('style', inst.dom.getAttrib(elm, "style"));
+		setFormValue('rel', inst.dom.getAttrib(elm, 'rel'));
+		setFormValue('rev', inst.dom.getAttrib(elm, 'rev'));
+		setFormValue('charset', inst.dom.getAttrib(elm, 'charset'));
+		setFormValue('hreflang', inst.dom.getAttrib(elm, 'hreflang'));
+		setFormValue('dir', inst.dom.getAttrib(elm, 'dir'));
+		setFormValue('lang', inst.dom.getAttrib(elm, 'lang'));
+		setFormValue('tabindex', inst.dom.getAttrib(elm, 'tabindex', typeof(elm.tabindex) != "undefined" ? elm.tabindex : ""));
+		setFormValue('accesskey', inst.dom.getAttrib(elm, 'accesskey', typeof(elm.accesskey) != "undefined" ? elm.accesskey : ""));
+		setFormValue('type', inst.dom.getAttrib(elm, 'type'));
+		setFormValue('onfocus', inst.dom.getAttrib(elm, 'onfocus'));
+		setFormValue('onblur', inst.dom.getAttrib(elm, 'onblur'));
+		setFormValue('onclick', onclick);
+		setFormValue('ondblclick', inst.dom.getAttrib(elm, 'ondblclick'));
+		setFormValue('onmousedown', inst.dom.getAttrib(elm, 'onmousedown'));
+		setFormValue('onmouseup', inst.dom.getAttrib(elm, 'onmouseup'));
+		setFormValue('onmouseover', inst.dom.getAttrib(elm, 'onmouseover'));
+		setFormValue('onmousemove', inst.dom.getAttrib(elm, 'onmousemove'));
+		setFormValue('onmouseout', inst.dom.getAttrib(elm, 'onmouseout'));
+		setFormValue('onkeypress', inst.dom.getAttrib(elm, 'onkeypress'));
+		setFormValue('onkeydown', inst.dom.getAttrib(elm, 'onkeydown'));
+		setFormValue('onkeyup', inst.dom.getAttrib(elm, 'onkeyup'));
+		setFormValue('target', inst.dom.getAttrib(elm, 'target'));
+		setFormValue('classes', inst.dom.getAttrib(elm, 'class'));
+
+		// Parse onclick data
+		if (onclick != null && onclick.indexOf('window.open') != -1)
+			parseWindowOpen(onclick);
+		else
+			parseFunction(onclick);
+
+		// Select by the values
+		selectByValue(formObj, 'dir', inst.dom.getAttrib(elm, 'dir'));
+		selectByValue(formObj, 'rel', inst.dom.getAttrib(elm, 'rel'));
+		selectByValue(formObj, 'rev', inst.dom.getAttrib(elm, 'rev'));
+		selectByValue(formObj, 'linklisthref', href);
+
+		if (href.charAt(0) == '#')
+			selectByValue(formObj, 'anchorlist', href);
+
+		addClassesToList('classlist', 'advlink_styles');
+
+		selectByValue(formObj, 'classlist', inst.dom.getAttrib(elm, 'class'), true);
+		selectByValue(formObj, 'targetlist', inst.dom.getAttrib(elm, 'target'), true);
+	} else
+		addClassesToList('classlist', 'advlink_styles');
+
+	window.focus();
+}
+
+function checkPrefix(n) {
+	if (n.value && Validator.isEmail(n) && !/^\s*mailto:/i.test(n.value) && confirm(tinyMCEPopup.getLang('advlink_dlg.is_email')))
+		n.value = 'mailto:' + n.value;
+
+	if (/^\s*www./i.test(n.value) && confirm(tinyMCEPopup.getLang('advlink_dlg.is_external')))
+		n.value = 'http://' + n.value;
+}
+
+function setFormValue(name, value) {
+	document.forms[0].elements[name].value = value;
+}
+
+function parseWindowOpen(onclick) {
+	var formObj = document.forms[0];
+
+	// Preprocess center code
+	if (onclick.indexOf('return false;') != -1) {
+		formObj.popupreturn.checked = true;
+		onclick = onclick.replace('return false;', '');
+	} else
+		formObj.popupreturn.checked = false;
+
+	var onClickData = parseLink(onclick);
+
+	if (onClickData != null) {
+		formObj.ispopup.checked = true;
+		setPopupControlsDisabled(false);
+
+		var onClickWindowOptions = parseOptions(onClickData['options']);
+		var url = onClickData['url'];
+
+		formObj.popupname.value = onClickData['target'];
+		formObj.popupurl.value = url;
+		formObj.popupwidth.value = getOption(onClickWindowOptions, 'width');
+		formObj.popupheight.value = getOption(onClickWindowOptions, 'height');
+
+		formObj.popupleft.value = getOption(onClickWindowOptions, 'left');
+		formObj.popuptop.value = getOption(onClickWindowOptions, 'top');
+
+		if (formObj.popupleft.value.indexOf('screen') != -1)
+			formObj.popupleft.value = "c";
+
+		if (formObj.popuptop.value.indexOf('screen') != -1)
+			formObj.popuptop.value = "c";
+
+		formObj.popuplocation.checked = getOption(onClickWindowOptions, 'location') == "yes";
+		formObj.popupscrollbars.checked = getOption(onClickWindowOptions, 'scrollbars') == "yes";
+		formObj.popupmenubar.checked = getOption(onClickWindowOptions, 'menubar') == "yes";
+		formObj.popupresizable.checked = getOption(onClickWindowOptions, 'resizable') == "yes";
+		formObj.popuptoolbar.checked = getOption(onClickWindowOptions, 'toolbar') == "yes";
+		formObj.popupstatus.checked = getOption(onClickWindowOptions, 'status') == "yes";
+		formObj.popupdependent.checked = getOption(onClickWindowOptions, 'dependent') == "yes";
+
+		buildOnClick();
+	}
+}
+
+function parseFunction(onclick) {
+	var formObj = document.forms[0];
+	var onClickData = parseLink(onclick);
+
+	// TODO: Add stuff here
+}
+
+function getOption(opts, name) {
+	return typeof(opts[name]) == "undefined" ? "" : opts[name];
+}
+
+function setPopupControlsDisabled(state) {
+	var formObj = document.forms[0];
+
+	formObj.popupname.disabled = state;
+	formObj.popupurl.disabled = state;
+	formObj.popupwidth.disabled = state;
+	formObj.popupheight.disabled = state;
+	formObj.popupleft.disabled = state;
+	formObj.popuptop.disabled = state;
+	formObj.popuplocation.disabled = state;
+	formObj.popupscrollbars.disabled = state;
+	formObj.popupmenubar.disabled = state;
+	formObj.popupresizable.disabled = state;
+	formObj.popuptoolbar.disabled = state;
+	formObj.popupstatus.disabled = state;
+	formObj.popupreturn.disabled = state;
+	formObj.popupdependent.disabled = state;
+
+	setBrowserDisabled('popupurlbrowser', state);
+}
+
+function parseLink(link) {
+	link = link.replace(new RegExp('&#39;', 'g'), "'");
+
+	var fnName = link.replace(new RegExp("\\s*([A-Za-z0-9\.]*)\\s*\\(.*", "gi"), "$1");
+
+	// Is function name a template function
+	var template = templates[fnName];
+	if (template) {
+		// Build regexp
+		var variableNames = template.match(new RegExp("'?\\$\\{[A-Za-z0-9\.]*\\}'?", "gi"));
+		var regExp = "\\s*[A-Za-z0-9\.]*\\s*\\(";
+		var replaceStr = "";
+		for (var i=0; i<variableNames.length; i++) {
+			// Is string value
+			if (variableNames[i].indexOf("'${") != -1)
+				regExp += "'(.*)'";
+			else // Number value
+				regExp += "([0-9]*)";
+
+			replaceStr += "$" + (i+1);
+
+			// Cleanup variable name
+			variableNames[i] = variableNames[i].replace(new RegExp("[^A-Za-z0-9]", "gi"), "");
+
+			if (i != variableNames.length-1) {
+				regExp += "\\s*,\\s*";
+				replaceStr += "<delim>";
+			} else
+				regExp += ".*";
+		}
+
+		regExp += "\\);?";
+
+		// Build variable array
+		var variables = new Array();
+		variables["_function"] = fnName;
+		var variableValues = link.replace(new RegExp(regExp, "gi"), replaceStr).split('<delim>');
+		for (var i=0; i<variableNames.length; i++)
+			variables[variableNames[i]] = variableValues[i];
+
+		return variables;
+	}
+
+	return null;
+}
+
+function parseOptions(opts) {
+	if (opts == null || opts == "")
+		return new Array();
+
+	// Cleanup the options
+	opts = opts.toLowerCase();
+	opts = opts.replace(/;/g, ",");
+	opts = opts.replace(/[^0-9a-z=,]/g, "");
+
+	var optionChunks = opts.split(',');
+	var options = new Array();
+
+	for (var i=0; i<optionChunks.length; i++) {
+		var parts = optionChunks[i].split('=');
+
+		if (parts.length == 2)
+			options[parts[0]] = parts[1];
+	}
+
+	return options;
+}
+
+function buildOnClick() {
+	var formObj = document.forms[0];
+
+	if (!formObj.ispopup.checked) {
+		formObj.onclick.value = "";
+		return;
+	}
+
+	var onclick = "window.open('";
+	var url = formObj.popupurl.value;
+
+	onclick += url + "','";
+	onclick += formObj.popupname.value + "','";
+
+	if (formObj.popuplocation.checked)
+		onclick += "location=yes,";
+
+	if (formObj.popupscrollbars.checked)
+		onclick += "scrollbars=yes,";
+
+	if (formObj.popupmenubar.checked)
+		onclick += "menubar=yes,";
+
+	if (formObj.popupresizable.checked)
+		onclick += "resizable=yes,";
+
+	if (formObj.popuptoolbar.checked)
+		onclick += "toolbar=yes,";
+
+	if (formObj.popupstatus.checked)
+		onclick += "status=yes,";
+
+	if (formObj.popupdependent.checked)
+		onclick += "dependent=yes,";
+
+	if (formObj.popupwidth.value != "")
+		onclick += "width=" + formObj.popupwidth.value + ",";
+
+	if (formObj.popupheight.value != "")
+		onclick += "height=" + formObj.popupheight.value + ",";
+
+	if (formObj.popupleft.value != "") {
+		if (formObj.popupleft.value != "c")
+			onclick += "left=" + formObj.popupleft.value + ",";
+		else
+			onclick += "left='+(screen.availWidth/2-" + (formObj.popupwidth.value/2) + ")+',";
+	}
+
+	if (formObj.popuptop.value != "") {
+		if (formObj.popuptop.value != "c")
+			onclick += "top=" + formObj.popuptop.value + ",";
+		else
+			onclick += "top='+(screen.availHeight/2-" + (formObj.popupheight.value/2) + ")+',";
+	}
+
+	if (onclick.charAt(onclick.length-1) == ',')
+		onclick = onclick.substring(0, onclick.length-1);
+
+	onclick += "');";
+
+	if (formObj.popupreturn.checked)
+		onclick += "return false;";
+
+	// tinyMCE.debug(onclick);
+
+	formObj.onclick.value = onclick;
+
+	if (formObj.href.value == "")
+		formObj.href.value = url;
+}
+
+function setAttrib(elm, attrib, value) {
+	var formObj = document.forms[0];
+	var valueElm = formObj.elements[attrib.toLowerCase()];
+
+	if (typeof(value) == "undefined" || value == null) {
+		value = "";
+
+		if (valueElm)
+			value = valueElm.value;
+	}
+
+	if (value != "") {
+		elm.setAttribute(attrib.toLowerCase(), value);
+
+		if (attrib == "style")
+			attrib = "style.cssText";
+
+//		if (attrib.substring(0, 2) == 'on')
+//			value = 'return true;' + value;
+
+		if (attrib == "class")
+			attrib = "className";
+
+		elm[attrib] = value;
+	} else
+		elm.removeAttribute(attrib);
+}
+
+function getAnchorListHTML(id, target) {
+	var inst = tinyMCEPopup.editor;
+	var nodes = inst.dom.select('a.mceItemAnchor,img.mceItemAnchor'), name, i;
+	var html = "";
+
+	html += '<select id="' + id + '" name="' + id + '" class="mceAnchorList" o2nfocus="tinyMCE.addSelectAccessibility(event, this, window);" onchange="this.form.' + target + '.value=';
+	html += 'this.options[this.selectedIndex].value;">';
+	html += '<option value="">---</option>';
+
+	for (i=0; i<nodes.length; i++) {
+		if ((name = inst.dom.getAttrib(nodes[i], "name")) != "")
+			html += '<option value="#' + name + '">' + name + '</option>';
+	}
+
+	html += '</select>';
+
+	return html;
+}
+
+function insertAction() {
+	var inst = tinyMCEPopup.editor;
+	var elm, elementArray, i;
+
+	elm = inst.selection.getNode();
+	checkPrefix(document.forms[0].href);
+
+	elm = inst.dom.getParent(elm, "A");
+
+	// Remove element if there is no href
+	if (!document.forms[0].href.value) {
+		tinyMCEPopup.execCommand("mceBeginUndoLevel");
+		i = inst.selection.getBookmark();
+		inst.dom.remove(elm, 1);
+		inst.selection.moveToBookmark(i);
+		tinyMCEPopup.execCommand("mceEndUndoLevel");
+		tinyMCEPopup.close();
+		return;
+	}
+
+	tinyMCEPopup.execCommand("mceBeginUndoLevel");
+
+	// Create new anchor elements
+	if (elm == null) {
+		tinyMCEPopup.execCommand("CreateLink", false, "#mce_temp_url#");
+
+		elementArray = tinymce.grep(inst.dom.select("a"), function(n) {return inst.dom.getAttrib(n, 'href') == '#mce_temp_url#';});
+		for (i=0; i<elementArray.length; i++) {
+			elm = elementArray[i];
+
+			// Move cursor to end
+			try {
+				tinyMCEPopup.editor.selection.collapse(false);
+			} catch (ex) {
+				// Ignore
+			}
+
+			// Move cursor behind the new anchor
+			// Don't remember why this was needed so it's now removed
+			/*
+			if (tinyMCE.isGecko) {
+				var sp = inst.getDoc().createTextNode(" ");
+
+				if (elm.nextSibling)
+					elm.parentNode.insertBefore(sp, elm.nextSibling);
+				else
+					elm.parentNode.appendChild(sp);
+
+				// Set range after link
+				var rng = inst.getDoc().createRange();
+				rng.setStartAfter(elm);
+				rng.setEndAfter(elm);
+
+				// Update selection
+				var sel = inst.getSel();
+				sel.removeAllRanges();
+				sel.addRange(rng);
+			}
+			*/
+
+			setAllAttribs(elm);
+		}
+	} else
+		setAllAttribs(elm);
+
+	tinyMCEPopup.execCommand("mceEndUndoLevel");
+	tinyMCEPopup.close();
+}
+
+function setAllAttribs(elm) {
+	var formObj = document.forms[0];
+	var href = formObj.href.value;
+	var target = getSelectValue(formObj, 'targetlist');
+
+	setAttrib(elm, 'href', href);
+	setAttrib(elm, 'mce_href', href);
+	setAttrib(elm, 'title');
+	setAttrib(elm, 'target', target == '_self' ? '' : target);
+	setAttrib(elm, 'id');
+	setAttrib(elm, 'style');
+	setAttrib(elm, 'class', getSelectValue(formObj, 'classlist'));
+	setAttrib(elm, 'rel');
+	setAttrib(elm, 'rev');
+	setAttrib(elm, 'charset');
+	setAttrib(elm, 'hreflang');
+	setAttrib(elm, 'dir');
+	setAttrib(elm, 'lang');
+	setAttrib(elm, 'tabindex');
+	setAttrib(elm, 'accesskey');
+	setAttrib(elm, 'type');
+	setAttrib(elm, 'onfocus');
+	setAttrib(elm, 'onblur');
+	setAttrib(elm, 'onclick');
+	setAttrib(elm, 'ondblclick');
+	setAttrib(elm, 'onmousedown');
+	setAttrib(elm, 'onmouseup');
+	setAttrib(elm, 'onmouseover');
+	setAttrib(elm, 'onmousemove');
+	setAttrib(elm, 'onmouseout');
+	setAttrib(elm, 'onkeypress');
+	setAttrib(elm, 'onkeydown');
+	setAttrib(elm, 'onkeyup');
+
+	// Refresh in old MSIE
+	if (tinyMCE.isMSIE5)
+		elm.outerHTML = elm.outerHTML;
+}
+
+function getSelectValue(form_obj, field_name) {
+	var elm = form_obj.elements[field_name];
+
+	if (elm == null || elm.options == null)
+		return "";
+
+	return elm.options[elm.selectedIndex].value;
+}
+
+function getLinkListHTML(elm_id, target_form_element, onchange_func) {
+	if (typeof(tinyMCELinkList) == "undefined" || tinyMCELinkList.length == 0)
+		return "";
+
+	var html = "";
+
+	html += '<select id="' + elm_id + '" name="' + elm_id + '"';
+	html += ' class="mceLinkList" onfoc2us="tinyMCE.addSelectAccessibility(event, this, window);" onchange="this.form.' + target_form_element + '.value=';
+	html += 'this.options[this.selectedIndex].value;';
+
+	if (typeof(onchange_func) != "undefined")
+		html += onchange_func + '(\'' + target_form_element + '\',this.options[this.selectedIndex].text,this.options[this.selectedIndex].value);';
+
+	html += '"><option value="">---</option>';
+
+	for (var i=0; i<tinyMCELinkList.length; i++)
+		html += '<option value="' + tinyMCELinkList[i][1] + '">' + tinyMCELinkList[i][0] + '</option>';
+
+	html += '</select>';
+
+	return html;
+
+	// tinyMCE.debug('-- image list start --', html, '-- image list end --');
+}
+
+function getTargetListHTML(elm_id, target_form_element) {
+	var targets = tinyMCEPopup.getParam('theme_advanced_link_targets', '').split(';');
+	var html = '';
+
+	html += '<select id="' + elm_id + '" name="' + elm_id + '" onf2ocus="tinyMCE.addSelectAccessibility(event, this, window);" onchange="this.form.' + target_form_element + '.value=';
+	html += 'this.options[this.selectedIndex].value;">';
+	html += '<option value="_self">' + tinyMCEPopup.getLang('advlink_dlg.target_same') + '</option>';
+	html += '<option value="_blank">' + tinyMCEPopup.getLang('advlink_dlg.target_blank') + ' (_blank)</option>';
+	html += '<option value="_parent">' + tinyMCEPopup.getLang('advlink_dlg.target_parent') + ' (_parent)</option>';
+	html += '<option value="_top">' + tinyMCEPopup.getLang('advlink_dlg.target_top') + ' (_top)</option>';
+
+	for (var i=0; i<targets.length; i++) {
+		var key, value;
+
+		if (targets[i] == "")
+			continue;
+
+		key = targets[i].split('=')[0];
+		value = targets[i].split('=')[1];
+
+		html += '<option value="' + key + '">' + value + ' (' + key + ')</option>';
+	}
+
+	html += '</select>';
+
+	return html;
+}
+
+// While loading
+preinit();
+tinyMCEPopup.onInit.add(init);
--- a/includes/clientside/tinymce/plugins/advlink/jscripts/functions.js	Fri Feb 22 12:46:51 2008 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,568 +0,0 @@
-/* Functions for the advlink plugin popup */
-
-var templates = {
-	"window.open" : "window.open('${url}','${target}','${options}')"
-};
-
-function preinit() {
-	// Initialize
-	tinyMCE.setWindowArg('mce_windowresize', false);
-
-	// Import external list url javascript
-	var url = tinyMCE.getParam("external_link_list_url");
-	if (url != null) {
-		// Fix relative
-		if (url.charAt(0) != '/' && url.indexOf('://') == -1)
-			url = tinyMCE.documentBasePath + "/" + url;
-
-		document.write('<sc'+'ript language="javascript" type="text/javascript" src="' + url + '"></sc'+'ript>');
-	}
-}
-
-function changeClass() {
-	var formObj = document.forms[0];
-	formObj.classes.value = getSelectValue(formObj, 'classlist');
-}
-
-function init() {
-	tinyMCEPopup.resizeToInnerSize();
-
-	var formObj = document.forms[0];
-	var inst = tinyMCE.getInstanceById(tinyMCE.getWindowArg('editor_id'));
-	var elm = inst.getFocusElement();
-	var action = "insert";
-	var html;
-
-	document.getElementById('hrefbrowsercontainer').innerHTML = getBrowserHTML('hrefbrowser','href','file','advlink');
-	document.getElementById('popupurlbrowsercontainer').innerHTML = getBrowserHTML('popupurlbrowser','popupurl','file','advlink');
-	document.getElementById('linklisthrefcontainer').innerHTML = getLinkListHTML('linklisthref','href');
-	document.getElementById('anchorlistcontainer').innerHTML = getAnchorListHTML('anchorlist','href');
-	document.getElementById('targetlistcontainer').innerHTML = getTargetListHTML('targetlist','target');
-
-	// Link list
-	html = getLinkListHTML('linklisthref','href');
-	if (html == "")
-		document.getElementById("linklisthrefrow").style.display = 'none';
-	else
-		document.getElementById("linklisthrefcontainer").innerHTML = html;
-
-	// Resize some elements
-	if (isVisible('hrefbrowser'))
-		document.getElementById('href').style.width = '260px';
-
-	if (isVisible('popupurlbrowser'))
-		document.getElementById('popupurl').style.width = '180px';
-
-	elm = tinyMCE.getParentElement(elm, "a");
-	if (elm != null && elm.nodeName == "A")
-		action = "update";
-
-	formObj.insert.value = tinyMCE.getLang('lang_' + action, 'Insert', true); 
-
-	setPopupControlsDisabled(true);
-
-	if (action == "update") {
-		var href = tinyMCE.getAttrib(elm, 'href');
-
-		href = convertURL(href, elm, true);
-
-		// Use mce_href if found
-		var mceRealHref = tinyMCE.getAttrib(elm, 'mce_href');
-		if (mceRealHref != "") {
-			href = mceRealHref;
-
-			if (tinyMCE.getParam('convert_urls'))
-				href = convertURL(href, elm, true);
-		}
-
-		var onclick = tinyMCE.cleanupEventStr(tinyMCE.getAttrib(elm, 'onclick'));
-
-		// Setup form data
-		setFormValue('href', href);
-		setFormValue('title', tinyMCE.getAttrib(elm, 'title'));
-		setFormValue('id', tinyMCE.getAttrib(elm, 'id'));
-		setFormValue('style', tinyMCE.serializeStyle(tinyMCE.parseStyle(tinyMCE.getAttrib(elm, "style"))));
-		setFormValue('rel', tinyMCE.getAttrib(elm, 'rel'));
-		setFormValue('rev', tinyMCE.getAttrib(elm, 'rev'));
-		setFormValue('charset', tinyMCE.getAttrib(elm, 'charset'));
-		setFormValue('hreflang', tinyMCE.getAttrib(elm, 'hreflang'));
-		setFormValue('dir', tinyMCE.getAttrib(elm, 'dir'));
-		setFormValue('lang', tinyMCE.getAttrib(elm, 'lang'));
-		setFormValue('tabindex', tinyMCE.getAttrib(elm, 'tabindex', typeof(elm.tabindex) != "undefined" ? elm.tabindex : ""));
-		setFormValue('accesskey', tinyMCE.getAttrib(elm, 'accesskey', typeof(elm.accesskey) != "undefined" ? elm.accesskey : ""));
-		setFormValue('type', tinyMCE.getAttrib(elm, 'type'));
-		setFormValue('onfocus', tinyMCE.cleanupEventStr(tinyMCE.getAttrib(elm, 'onfocus')));
-		setFormValue('onblur', tinyMCE.cleanupEventStr(tinyMCE.getAttrib(elm, 'onblur')));
-		setFormValue('onclick', onclick);
-		setFormValue('ondblclick', tinyMCE.cleanupEventStr(tinyMCE.getAttrib(elm, 'ondblclick')));
-		setFormValue('onmousedown', tinyMCE.cleanupEventStr(tinyMCE.getAttrib(elm, 'onmousedown')));
-		setFormValue('onmouseup', tinyMCE.cleanupEventStr(tinyMCE.getAttrib(elm, 'onmouseup')));
-		setFormValue('onmouseover', tinyMCE.cleanupEventStr(tinyMCE.getAttrib(elm, 'onmouseover')));
-		setFormValue('onmousemove', tinyMCE.cleanupEventStr(tinyMCE.getAttrib(elm, 'onmousemove')));
-		setFormValue('onmouseout', tinyMCE.cleanupEventStr(tinyMCE.getAttrib(elm, 'onmouseout')));
-		setFormValue('onkeypress', tinyMCE.cleanupEventStr(tinyMCE.getAttrib(elm, 'onkeypress')));
-		setFormValue('onkeydown', tinyMCE.cleanupEventStr(tinyMCE.getAttrib(elm, 'onkeydown')));
-		setFormValue('onkeyup', tinyMCE.cleanupEventStr(tinyMCE.getAttrib(elm, 'onkeyup')));
-		setFormValue('target', tinyMCE.getAttrib(elm, 'target'));
-		setFormValue('classes', tinyMCE.getAttrib(elm, 'class'));
-
-		// Parse onclick data
-		if (onclick != null && onclick.indexOf('window.open') != -1)
-			parseWindowOpen(onclick);
-		else
-			parseFunction(onclick);
-
-		// Select by the values
-		selectByValue(formObj, 'dir', tinyMCE.getAttrib(elm, 'dir'));
-		selectByValue(formObj, 'rel', tinyMCE.getAttrib(elm, 'rel'));
-		selectByValue(formObj, 'rev', tinyMCE.getAttrib(elm, 'rev'));
-		selectByValue(formObj, 'linklisthref', href);
-
-		if (href.charAt(0) == '#')
-			selectByValue(formObj, 'anchorlist', href);
-
-		addClassesToList('classlist', 'advlink_styles');
-
-		selectByValue(formObj, 'classlist', tinyMCE.getAttrib(elm, 'class'), true);
-		selectByValue(formObj, 'targetlist', tinyMCE.getAttrib(elm, 'target'), true);
-	} else
-		addClassesToList('classlist', 'advlink_styles');
-
-	window.focus();
-}
-
-function setFormValue(name, value) {
-	document.forms[0].elements[name].value = value;
-}
-
-function convertURL(url, node, on_save) {
-	return eval("tinyMCEPopup.windowOpener." + tinyMCE.settings['urlconverter_callback'] + "(url, node, on_save);");
-}
-
-function parseWindowOpen(onclick) {
-	var formObj = document.forms[0];
-
-	// Preprocess center code
-	if (onclick.indexOf('return false;') != -1) {
-		formObj.popupreturn.checked = true;
-		onclick = onclick.replace('return false;', '');
-	} else
-		formObj.popupreturn.checked = false;
-
-	var onClickData = parseLink(onclick);
-
-	if (onClickData != null) {
-		formObj.ispopup.checked = true;
-		setPopupControlsDisabled(false);
-
-		var onClickWindowOptions = parseOptions(onClickData['options']);
-		var url = onClickData['url'];
-
-		if (tinyMCE.getParam('convert_urls'))
-			url = convertURL(url, null, true);
-
-		formObj.popupname.value = onClickData['target'];
-		formObj.popupurl.value = url;
-		formObj.popupwidth.value = getOption(onClickWindowOptions, 'width');
-		formObj.popupheight.value = getOption(onClickWindowOptions, 'height');
-
-		formObj.popupleft.value = getOption(onClickWindowOptions, 'left');
-		formObj.popuptop.value = getOption(onClickWindowOptions, 'top');
-
-		if (formObj.popupleft.value.indexOf('screen') != -1)
-			formObj.popupleft.value = "c";
-
-		if (formObj.popuptop.value.indexOf('screen') != -1)
-			formObj.popuptop.value = "c";
-
-		formObj.popuplocation.checked = getOption(onClickWindowOptions, 'location') == "yes";
-		formObj.popupscrollbars.checked = getOption(onClickWindowOptions, 'scrollbars') == "yes";
-		formObj.popupmenubar.checked = getOption(onClickWindowOptions, 'menubar') == "yes";
-		formObj.popupresizable.checked = getOption(onClickWindowOptions, 'resizable') == "yes";
-		formObj.popuptoolbar.checked = getOption(onClickWindowOptions, 'toolbar') == "yes";
-		formObj.popupstatus.checked = getOption(onClickWindowOptions, 'status') == "yes";
-		formObj.popupdependent.checked = getOption(onClickWindowOptions, 'dependent') == "yes";
-
-		buildOnClick();
-	}
-}
-
-function parseFunction(onclick) {
-	var formObj = document.forms[0];
-	var onClickData = parseLink(onclick);
-
-	// TODO: Add stuff here
-}
-
-function getOption(opts, name) {
-	return typeof(opts[name]) == "undefined" ? "" : opts[name];
-}
-
-function setPopupControlsDisabled(state) {
-	var formObj = document.forms[0];
-
-	formObj.popupname.disabled = state;
-	formObj.popupurl.disabled = state;
-	formObj.popupwidth.disabled = state;
-	formObj.popupheight.disabled = state;
-	formObj.popupleft.disabled = state;
-	formObj.popuptop.disabled = state;
-	formObj.popuplocation.disabled = state;
-	formObj.popupscrollbars.disabled = state;
-	formObj.popupmenubar.disabled = state;
-	formObj.popupresizable.disabled = state;
-	formObj.popuptoolbar.disabled = state;
-	formObj.popupstatus.disabled = state;
-	formObj.popupreturn.disabled = state;
-	formObj.popupdependent.disabled = state;
-
-	setBrowserDisabled('popupurlbrowser', state);
-}
-
-function parseLink(link) {
-	link = link.replace(new RegExp('&#39;', 'g'), "'");
-
-	var fnName = link.replace(new RegExp("\\s*([A-Za-z0-9\.]*)\\s*\\(.*", "gi"), "$1");
-
-	// Is function name a template function
-	var template = templates[fnName];
-	if (template) {
-		// Build regexp
-		var variableNames = template.match(new RegExp("'?\\$\\{[A-Za-z0-9\.]*\\}'?", "gi"));
-		var regExp = "\\s*[A-Za-z0-9\.]*\\s*\\(";
-		var replaceStr = "";
-		for (var i=0; i<variableNames.length; i++) {
-			// Is string value
-			if (variableNames[i].indexOf("'${") != -1)
-				regExp += "'(.*)'";
-			else // Number value
-				regExp += "([0-9]*)";
-
-			replaceStr += "$" + (i+1);
-
-			// Cleanup variable name
-			variableNames[i] = variableNames[i].replace(new RegExp("[^A-Za-z0-9]", "gi"), "");
-
-			if (i != variableNames.length-1) {
-				regExp += "\\s*,\\s*";
-				replaceStr += "<delim>";
-			} else
-				regExp += ".*";
-		}
-
-		regExp += "\\);?";
-
-		// Build variable array
-		var variables = new Array();
-		variables["_function"] = fnName;
-		var variableValues = link.replace(new RegExp(regExp, "gi"), replaceStr).split('<delim>');
-		for (var i=0; i<variableNames.length; i++)
-			variables[variableNames[i]] = variableValues[i];
-
-		return variables;
-	}
-
-	return null;
-}
-
-function parseOptions(opts) {
-	if (opts == null || opts == "")
-		return new Array();
-
-	// Cleanup the options
-	opts = opts.toLowerCase();
-	opts = opts.replace(/;/g, ",");
-	opts = opts.replace(/[^0-9a-z=,]/g, "");
-
-	var optionChunks = opts.split(',');
-	var options = new Array();
-
-	for (var i=0; i<optionChunks.length; i++) {
-		var parts = optionChunks[i].split('=');
-
-		if (parts.length == 2)
-			options[parts[0]] = parts[1];
-	}
-
-	return options;
-}
-
-function buildOnClick() {
-	var formObj = document.forms[0];
-
-	if (!formObj.ispopup.checked) {
-		formObj.onclick.value = "";
-		return;
-	}
-
-	var onclick = "window.open('";
-	var url = formObj.popupurl.value;
-
-	if (tinyMCE.getParam('convert_urls'))
-		url = convertURL(url, null, true);
-
-	onclick += url + "','";
-	onclick += formObj.popupname.value + "','";
-
-	if (formObj.popuplocation.checked)
-		onclick += "location=yes,";
-
-	if (formObj.popupscrollbars.checked)
-		onclick += "scrollbars=yes,";
-
-	if (formObj.popupmenubar.checked)
-		onclick += "menubar=yes,";
-
-	if (formObj.popupresizable.checked)
-		onclick += "resizable=yes,";
-
-	if (formObj.popuptoolbar.checked)
-		onclick += "toolbar=yes,";
-
-	if (formObj.popupstatus.checked)
-		onclick += "status=yes,";
-
-	if (formObj.popupdependent.checked)
-		onclick += "dependent=yes,";
-
-	if (formObj.popupwidth.value != "")
-		onclick += "width=" + formObj.popupwidth.value + ",";
-
-	if (formObj.popupheight.value != "")
-		onclick += "height=" + formObj.popupheight.value + ",";
-
-	if (formObj.popupleft.value != "") {
-		if (formObj.popupleft.value != "c")
-			onclick += "left=" + formObj.popupleft.value + ",";
-		else
-			onclick += "left='+(screen.availWidth/2-" + (formObj.popupwidth.value/2) + ")+',";
-	}
-
-	if (formObj.popuptop.value != "") {
-		if (formObj.popuptop.value != "c")
-			onclick += "top=" + formObj.popuptop.value + ",";
-		else
-			onclick += "top='+(screen.availHeight/2-" + (formObj.popupheight.value/2) + ")+',";
-	}
-
-	if (onclick.charAt(onclick.length-1) == ',')
-		onclick = onclick.substring(0, onclick.length-1);
-
-	onclick += "');";
-
-	if (formObj.popupreturn.checked)
-		onclick += "return false;";
-
-	// tinyMCE.debug(onclick);
-
-	formObj.onclick.value = onclick;
-
-	if (formObj.href.value == "")
-		formObj.href.value = url;
-}
-
-function setAttrib(elm, attrib, value) {
-	var formObj = document.forms[0];
-	var valueElm = formObj.elements[attrib.toLowerCase()];
-
-	if (typeof(value) == "undefined" || value == null) {
-		value = "";
-
-		if (valueElm)
-			value = valueElm.value;
-	}
-
-	if (value != "") {
-		elm.setAttribute(attrib.toLowerCase(), value);
-
-		if (attrib == "style")
-			attrib = "style.cssText";
-
-		if (attrib.substring(0, 2) == 'on')
-			value = 'return true;' + value;
-
-		if (attrib == "class")
-			attrib = "className";
-
-		eval('elm.' + attrib + "=value;");
-	} else
-		elm.removeAttribute(attrib);
-}
-
-function getAnchorListHTML(id, target) {
-	var inst = tinyMCE.getInstanceById(tinyMCE.getWindowArg('editor_id'));
-	var nodes = inst.getBody().getElementsByTagName("a");
-
-	var html = "";
-
-	html += '<select id="' + id + '" name="' + id + '" class="mceAnchorList" onfocus="tinyMCE.addSelectAccessibility(event, this, window);" onchange="this.form.' + target + '.value=';
-	html += 'this.options[this.selectedIndex].value;">';
-	html += '<option value="">---</option>';
-
-	for (var i=0; i<nodes.length; i++) {
-		if ((name = tinyMCE.getAttrib(nodes[i], "name")) != "")
-			html += '<option value="#' + name + '">' + name + '</option>';
-	}
-
-	html += '</select>';
-
-	return html;
-}
-
-function insertAction() {
-	var inst = tinyMCE.getInstanceById(tinyMCE.getWindowArg('editor_id'));
-	var elm = inst.getFocusElement();
-
-	elm = tinyMCE.getParentElement(elm, "a");
-
-	tinyMCEPopup.execCommand("mceBeginUndoLevel");
-
-	// Create new anchor elements
-	if (elm == null) {
-		if (tinyMCE.isSafari)
-			tinyMCEPopup.execCommand("mceInsertContent", false, '<a href="#mce_temp_url#">' + inst.selection.getSelectedHTML() + '</a>');
-		else
-			tinyMCEPopup.execCommand("createlink", false, "#mce_temp_url#");
-
-		var elementArray = tinyMCE.getElementsByAttributeValue(inst.getBody(), "a", "href", "#mce_temp_url#");
-		for (var i=0; i<elementArray.length; i++) {
-			var elm = elementArray[i];
-
-			// Move cursor behind the new anchor
-			if (tinyMCE.isGecko) {
-				var sp = inst.getDoc().createTextNode(" ");
-
-				if (elm.nextSibling)
-					elm.parentNode.insertBefore(sp, elm.nextSibling);
-				else
-					elm.parentNode.appendChild(sp);
-
-				// Set range after link
-				var rng = inst.getDoc().createRange();
-				rng.setStartAfter(elm);
-				rng.setEndAfter(elm);
-
-				// Update selection
-				var sel = inst.getSel();
-				sel.removeAllRanges();
-				sel.addRange(rng);
-			}
-
-			setAllAttribs(elm);
-		}
-	} else
-		setAllAttribs(elm);
-
-	tinyMCE._setEventsEnabled(inst.getBody(), false);
-	tinyMCEPopup.execCommand("mceEndUndoLevel");
-	tinyMCEPopup.close();
-}
-
-function setAllAttribs(elm) {
-	var formObj = document.forms[0];
-	var href = formObj.href.value;
-	var target = getSelectValue(formObj, 'targetlist');
-
-	// Make anchors absolute
-	if (href.charAt(0) != '#')
-		href = convertURL(href, elm);
-
-	setAttrib(elm, 'href', href);
-	setAttrib(elm, 'mce_href', href);
-	setAttrib(elm, 'title');
-	setAttrib(elm, 'target', target == '_self' ? '' : target);
-	setAttrib(elm, 'id');
-	setAttrib(elm, 'style');
-	setAttrib(elm, 'class', getSelectValue(formObj, 'classlist'));
-	setAttrib(elm, 'rel');
-	setAttrib(elm, 'rev');
-	setAttrib(elm, 'charset');
-	setAttrib(elm, 'hreflang');
-	setAttrib(elm, 'dir');
-	setAttrib(elm, 'lang');
-	setAttrib(elm, 'tabindex');
-	setAttrib(elm, 'accesskey');
-	setAttrib(elm, 'type');
-	setAttrib(elm, 'onfocus');
-	setAttrib(elm, 'onblur');
-	setAttrib(elm, 'onclick');
-	setAttrib(elm, 'ondblclick');
-	setAttrib(elm, 'onmousedown');
-	setAttrib(elm, 'onmouseup');
-	setAttrib(elm, 'onmouseover');
-	setAttrib(elm, 'onmousemove');
-	setAttrib(elm, 'onmouseout');
-	setAttrib(elm, 'onkeypress');
-	setAttrib(elm, 'onkeydown');
-	setAttrib(elm, 'onkeyup');
-
-	// Refresh in old MSIE
-	if (tinyMCE.isMSIE5)
-		elm.outerHTML = elm.outerHTML;
-}
-
-function getSelectValue(form_obj, field_name) {
-	var elm = form_obj.elements[field_name];
-
-	if (elm == null || elm.options == null)
-		return "";
-
-	return elm.options[elm.selectedIndex].value;
-}
-
-function getLinkListHTML(elm_id, target_form_element, onchange_func) {
-	if (typeof(tinyMCELinkList) == "undefined" || tinyMCELinkList.length == 0)
-		return "";
-
-	var html = "";
-
-	html += '<select id="' + elm_id + '" name="' + elm_id + '"';
-	html += ' class="mceLinkList" onfocus="tinyMCE.addSelectAccessibility(event, this, window);" onchange="this.form.' + target_form_element + '.value=';
-	html += 'this.options[this.selectedIndex].value;';
-
-	if (typeof(onchange_func) != "undefined")
-		html += onchange_func + '(\'' + target_form_element + '\',this.options[this.selectedIndex].text,this.options[this.selectedIndex].value);';
-
-	html += '"><option value="">---</option>';
-
-	for (var i=0; i<tinyMCELinkList.length; i++)
-		html += '<option value="' + tinyMCELinkList[i][1] + '">' + tinyMCELinkList[i][0] + '</option>';
-
-	html += '</select>';
-
-	return html;
-
-	// tinyMCE.debug('-- image list start --', html, '-- image list end --');
-}
-
-function getTargetListHTML(elm_id, target_form_element) {
-	var targets = tinyMCE.getParam('theme_advanced_link_targets', '').split(';');
-	var html = '';
-
-	html += '<select id="' + elm_id + '" name="' + elm_id + '" onfocus="tinyMCE.addSelectAccessibility(event, this, window);" onchange="this.form.' + target_form_element + '.value=';
-	html += 'this.options[this.selectedIndex].value;">';
-
-	html += '<option value="_self">' + tinyMCE.getLang('lang_advlink_target_same') + '</option>';
-	html += '<option value="_blank">' + tinyMCE.getLang('lang_advlink_target_blank') + ' (_blank)</option>';
-	html += '<option value="_parent">' + tinyMCE.getLang('lang_advlink_target_parent') + ' (_parent)</option>';
-	html += '<option value="_top">' + tinyMCE.getLang('lang_advlink_target_top') + ' (_top)</option>';
-
-	for (var i=0; i<targets.length; i++) {
-		var key, value;
-
-		if (targets[i] == "")
-			continue;
-
-		key = targets[i].split('=')[0];
-		value = targets[i].split('=')[1];
-
-		html += '<option value="' + key + '">' + value + ' (' + key + ')</option>';
-	}
-
-	html += '</select>';
-
-	return html;
-}
-
-// While loading
-preinit();
--- a/includes/clientside/tinymce/plugins/advlink/langs/en.js	Fri Feb 22 12:46:51 2008 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,46 +0,0 @@
-// UK lang variables
-
-tinyMCE.addToLang('advlink',{
-general_tab : 'General',
-popup_tab : 'Popup',
-events_tab : 'Events',
-advanced_tab : 'Advanced',
-general_props : 'General properties',
-popup_props : 'Popup properties',
-event_props : 'Events',
-advanced_props : 'Advanced properties',
-popup_opts : 'Options',
-anchor_names : 'Anchors',
-target_same : 'Open in this window / frame',
-target_parent : 'Open in parent window / frame',
-target_top : 'Open in top frame (replaces all frames)',
-target_blank : 'Open in new window',
-popup : 'Javascript popup',
-popup_url : 'Popup URL',
-popup_name : 'Window name',
-popup_return : 'Insert \'return false\'',
-popup_scrollbars : 'Show scrollbars',
-popup_statusbar : 'Show status bar',
-popup_toolbar : 'Show toolbars',
-popup_menubar : 'Show menu bar',
-popup_location : 'Show location bar',
-popup_resizable : 'Make window resizable',
-popup_dependent : 'Dependent (Mozilla/Firefox only)',
-popup_size : 'Size',
-popup_position : 'Position (X/Y)',
-id : 'Id',
-style: 'Style',
-classes : 'Classes',
-target_name : 'Target name',
-langdir : 'Language direction',
-target_langcode : 'Target language',
-langcode : 'Language code',
-encoding : 'Target character encoding',
-mime : 'Target MIME type',
-rel : 'Relationship page to target',
-rev : 'Relationship target to page',
-tabindex : 'Tabindex',
-accesskey : 'Accesskey',
-ltr : 'Left to right',
-rtl : 'Right to left'
-});
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/includes/clientside/tinymce/plugins/advlink/langs/en_dlg.js	Fri Feb 22 12:51:53 2008 -0500
@@ -0,0 +1,52 @@
+tinyMCE.addI18n('en.advlink_dlg',{
+title:"Insert/edit link",
+url:"Link URL",
+target:"Target",
+titlefield:"Title",
+is_email:"The URL you entered seems to be an email address, do you want to add the required mailto: prefix?",
+is_external:"The URL you entered seems to external link, do you want to add the required http:// prefix?",
+list:"Link list",
+general_tab:"General",
+popup_tab:"Popup",
+events_tab:"Events",
+advanced_tab:"Advanced",
+general_props:"General properties",
+popup_props:"Popup properties",
+event_props:"Events",
+advanced_props:"Advanced properties",
+popup_opts:"Options",
+anchor_names:"Anchors",
+target_same:"Open in this window / frame",
+target_parent:"Open in parent window / frame",
+target_top:"Open in top frame (replaces all frames)",
+target_blank:"Open in new window",
+popup:"Javascript popup",
+popup_url:"Popup URL",
+popup_name:"Window name",
+popup_return:"Insert 'return false'",
+popup_scrollbars:"Show scrollbars",
+popup_statusbar:"Show status bar",
+popup_toolbar:"Show toolbars",
+popup_menubar:"Show menu bar",
+popup_location:"Show location bar",
+popup_resizable:"Make window resizable",
+popup_dependent:"Dependent (Mozilla/Firefox only)",
+popup_size:"Size",
+popup_position:"Position (X/Y)",
+id:"Id",
+style:"Style",
+classes:"Classes",
+target_name:"Target name",
+langdir:"Language direction",
+target_langcode:"Target language",
+langcode:"Language code",
+encoding:"Target character encoding",
+mime:"Target MIME type",
+rel:"Relationship page to target",
+rev:"Relationship target to page",
+tabindex:"Tabindex",
+accesskey:"Accesskey",
+ltr:"Left to right",
+rtl:"Right to left",
+link_list:"Link list"
+});
\ No newline at end of file
--- a/includes/clientside/tinymce/plugins/advlink/link.htm	Fri Feb 22 12:46:51 2008 -0500
+++ b/includes/clientside/tinymce/plugins/advlink/link.htm	Fri Feb 22 12:51:53 2008 -0500
@@ -1,32 +1,34 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
 <html xmlns="http://www.w3.org/1999/xhtml">
 <head>
-	<title>{$lang_insert_link_title}</title>
-	<script language="javascript" type="text/javascript" src="../../tiny_mce_popup.js"></script>
-	<script language="javascript" type="text/javascript" src="../../utils/mctabs.js"></script>
-	<script language="javascript" type="text/javascript" src="../../utils/form_utils.js"></script>
-	<script language="javascript" type="text/javascript" src="jscripts/functions.js"></script>
+	<title>{#advlink_dlg.title}</title>
+	<script type="text/javascript" src="../../tiny_mce_popup.js"></script>
+	<script type="text/javascript" src="../../utils/mctabs.js"></script>
+	<script type="text/javascript" src="../../utils/form_utils.js"></script>
+	<script type="text/javascript" src="../../utils/validate.js"></script>
+	<script type="text/javascript" src="js/advlink.js"></script>
 	<link href="css/advlink.css" rel="stylesheet" type="text/css" />
 	<base target="_self" />
 </head>
-<body id="advlink" onload="tinyMCEPopup.executeOnLoad('init();');" style="display: none">
+<body id="advlink" style="display: none">
     <form onsubmit="insertAction();return false;" action="#">
 		<div class="tabs">
 			<ul>
-				<li id="general_tab" class="current"><span><a href="javascript:mcTabs.displayTab('general_tab','general_panel');" onmousedown="return false;">{$lang_advlink_general_tab}</a></span></li>
-				<li id="popup_tab"><span><a href="javascript:mcTabs.displayTab('popup_tab','popup_panel');" onmousedown="return false;">{$lang_advlink_popup_tab}</a></span></li>
-				<li id="events_tab"><span><a href="javascript:mcTabs.displayTab('events_tab','events_panel');" onmousedown="return false;">{$lang_advlink_events_tab}</a></span></li>
-				<li id="advanced_tab"><span><a href="javascript:mcTabs.displayTab('advanced_tab','advanced_panel');" onmousedown="return false;">{$lang_advlink_advanced_tab}</a></span></li>
+				<li id="general_tab" class="current"><span><a href="javascript:mcTabs.displayTab('general_tab','general_panel');" onmousedown="return false;">{#advlink_dlg.general_tab}</a></span></li>
+				<li id="popup_tab"><span><a href="javascript:mcTabs.displayTab('popup_tab','popup_panel');" onmousedown="return false;">{#advlink_dlg.popup_tab}</a></span></li>
+				<li id="events_tab"><span><a href="javascript:mcTabs.displayTab('events_tab','events_panel');" onmousedown="return false;">{#advlink_dlg.events_tab}</a></span></li>
+				<li id="advanced_tab"><span><a href="javascript:mcTabs.displayTab('advanced_tab','advanced_panel');" onmousedown="return false;">{#advlink_dlg.advanced_tab}</a></span></li>
 			</ul>
 		</div>
 
 		<div class="panel_wrapper">
 			<div id="general_panel" class="panel current">
 				<fieldset>
-					<legend>{$lang_advlink_general_props}</legend>
+					<legend>{#advlink_dlg.general_props}</legend>
 
 					<table border="0" cellpadding="4" cellspacing="0">
 						<tr>
-						  <td nowrap="nowrap"><label id="hreflabel" for="href">{$lang_insert_link_url}</label></td>
+						  <td nowrap="nowrap"><label id="hreflabel" for="href">{#advlink_dlg.url}</label></td>
 						  <td><table border="0" cellspacing="0" cellpadding="0">
 								<tr>
 								  <td><input id="href" name="href" type="text" value="" onchange="selectByValue(this.form,'linklisthref',this.value);" /></td>
@@ -35,26 +37,26 @@
 							  </table></td>
 						</tr>
 						<tr id="linklisthrefrow">
-							<td class="column1"><label for="linklisthref">{$lang_link_list}</label></td>
+							<td class="column1"><label for="linklisthref">{#advlink_dlg.list}</label></td>
 							<td colspan="2" id="linklisthrefcontainer">&nbsp;</td>
 						</tr>
 						<tr>
-							<td class="column1"><label for="anchorlist">{$lang_advlink_anchor_names}</label></td>
+							<td class="column1"><label for="anchorlist">{#advlink_dlg.anchor_names}</label></td>
 							<td colspan="2" id="anchorlistcontainer">&nbsp;</td>
 						</tr>
 						<tr>
-							<td><label id="targetlistlabel" for="targetlist">{$lang_insert_link_target}</label></td>
+							<td><label id="targetlistlabel" for="targetlist">{#advlink_dlg.target}</label></td>
 							<td id="targetlistcontainer">&nbsp;</td>
 						</tr>
 						<tr>
-							<td nowrap="nowrap"><label id="titlelabel" for="title">{$lang_theme_insert_link_titlefield}</label></td>
+							<td nowrap="nowrap"><label id="titlelabel" for="title">{#advlink_dlg.titlefield}</label></td>
 							<td><input id="title" name="title" type="text" value="" /></td>
 						</tr>
 						<tr>
-							<td><label id="classlabel" for="classlist">{$lang_class_name}</label></td>
+							<td><label id="classlabel" for="classlist">{#class_name}</label></td>
 							<td>
 								 <select id="classlist" name="classlist" onchange="changeClass();">
-									<option value="" selected>{$lang_not_set}</option>
+									<option value="" selected>{#not_set}</option>
 								 </select>
 							</td>
 						</tr>
@@ -64,14 +66,14 @@
 
 			<div id="popup_panel" class="panel">
 				<fieldset>
-					<legend>{$lang_advlink_popup_props}</legend>
+					<legend>{#advlink_dlg.popup_props}</legend>
 
 					<input type="checkbox" id="ispopup" name="ispopup" class="radio" onclick="setPopupControlsDisabled(!this.checked);buildOnClick();" />
-					<label id="ispopuplabel" for="ispopup">{$lang_advlink_popup}</label>
+					<label id="ispopuplabel" for="ispopup">{#advlink_dlg.popup}</label>
 
 					<table border="0" cellpadding="0" cellspacing="4">
 						<tr>
-							<td nowrap="nowrap"><label for="popupurl">{$lang_advlink_popup_url}</label>&nbsp;</td>
+							<td nowrap="nowrap"><label for="popupurl">{#advlink_dlg.popup_url}</label>&nbsp;</td>
 							<td>
 								<table border="0" cellspacing="0" cellpadding="0">
 									<tr>
@@ -82,18 +84,18 @@
 							</td>
 						</tr>
 						<tr>
-							<td nowrap="nowrap"><label for="popupname">{$lang_advlink_popup_name}</label>&nbsp;</td>
+							<td nowrap="nowrap"><label for="popupname">{#advlink_dlg.popup_name}</label>&nbsp;</td>
 							<td><input type="text" name="popupname" id="popupname" value="" onchange="buildOnClick();" /></td>
 						</tr>
 						<tr>
-							<td nowrap="nowrap"><label>{$lang_advlink_popup_size}</label>&nbsp;</td>
+							<td nowrap="nowrap"><label>{#advlink_dlg.popup_size}</label>&nbsp;</td>
 							<td nowrap="nowrap">
 								<input type="text" id="popupwidth" name="popupwidth" value="" onchange="buildOnClick();" /> x
 								<input type="text" id="popupheight" name="popupheight" value="" onchange="buildOnClick();" /> px
 							</td>
 						</tr>
 						<tr>
-							<td nowrap="nowrap" id="labelleft"><label>{$lang_advlink_popup_position}</label>&nbsp;</td>
+							<td nowrap="nowrap" id="labelleft"><label>{#advlink_dlg.popup_position}</label>&nbsp;</td>
 							<td nowrap="nowrap">
 								<input type="text" id="popupleft" name="popupleft" value="" onchange="buildOnClick();" /> /                                
 								<input type="text" id="popuptop" name="popuptop" value="" onchange="buildOnClick();" /> (c /c = center)
@@ -102,32 +104,32 @@
 					</table>
 
 					<fieldset>
-						<legend>{$lang_advlink_popup_opts}</legend>
+						<legend>{#advlink_dlg.popup_opts}</legend>
 
 						<table border="0" cellpadding="0" cellspacing="4">
 							<tr>
 								<td><input type="checkbox" id="popuplocation" name="popuplocation" class="checkbox" onchange="buildOnClick();" /></td>
-								<td nowrap="nowrap"><label id="popuplocationlabel" for="popuplocation">{$lang_advlink_popup_location}</label></td>
+								<td nowrap="nowrap"><label id="popuplocationlabel" for="popuplocation">{#advlink_dlg.popup_location}</label></td>
 								<td><input type="checkbox" id="popupscrollbars" name="popupscrollbars" class="checkbox" onchange="buildOnClick();" /></td>
-								<td nowrap="nowrap"><label id="popupscrollbarslabel" for="popupscrollbars">{$lang_advlink_popup_scrollbars}</label></td>
+								<td nowrap="nowrap"><label id="popupscrollbarslabel" for="popupscrollbars">{#advlink_dlg.popup_scrollbars}</label></td>
 							</tr>
 							<tr>
 								<td><input type="checkbox" id="popupmenubar" name="popupmenubar" class="checkbox" onchange="buildOnClick();" /></td>
-								<td nowrap="nowrap"><label id="popupmenubarlabel" for="popupmenubar">{$lang_advlink_popup_menubar}</label></td>
+								<td nowrap="nowrap"><label id="popupmenubarlabel" for="popupmenubar">{#advlink_dlg.popup_menubar}</label></td>
 								<td><input type="checkbox" id="popupresizable" name="popupresizable" class="checkbox" onchange="buildOnClick();" /></td>
-								<td nowrap="nowrap"><label id="popupresizablelabel" for="popupresizable">{$lang_advlink_popup_resizable}</label></td>
+								<td nowrap="nowrap"><label id="popupresizablelabel" for="popupresizable">{#advlink_dlg.popup_resizable}</label></td>
 							</tr>
 							<tr>
 								<td><input type="checkbox" id="popuptoolbar" name="popuptoolbar" class="checkbox" onchange="buildOnClick();" /></td>
-								<td nowrap="nowrap"><label id="popuptoolbarlabel" for="popuptoolbar">{$lang_advlink_popup_toolbar}</label></td>
+								<td nowrap="nowrap"><label id="popuptoolbarlabel" for="popuptoolbar">{#advlink_dlg.popup_toolbar}</label></td>
 								<td><input type="checkbox" id="popupdependent" name="popupdependent" class="checkbox" onchange="buildOnClick();" /></td>
-								<td nowrap="nowrap"><label id="popupdependentlabel" for="popupdependent">{$lang_advlink_popup_dependent}</label></td>
+								<td nowrap="nowrap"><label id="popupdependentlabel" for="popupdependent">{#advlink_dlg.popup_dependent}</label></td>
 							</tr>
 							<tr>
 								<td><input type="checkbox" id="popupstatus" name="popupstatus" class="checkbox" onchange="buildOnClick();" /></td>
-								<td nowrap="nowrap"><label id="popupstatuslabel" for="popupstatus">{$lang_advlink_popup_statusbar}</label></td>
+								<td nowrap="nowrap"><label id="popupstatuslabel" for="popupstatus">{#advlink_dlg.popup_statusbar}</label></td>
 								<td><input type="checkbox" id="popupreturn" name="popupreturn" class="checkbox" onchange="buildOnClick();" checked="checked" /></td>
-								<td nowrap="nowrap"><label id="popupreturnlabel" for="popupreturn">{$lang_advlink_popup_return}</label></td>
+								<td nowrap="nowrap"><label id="popupreturnlabel" for="popupreturn">{#advlink_dlg.popup_return}</label></td>
 							</tr>
 						</table>
 					</fieldset>
@@ -136,66 +138,66 @@
 
 			<div id="advanced_panel" class="panel">
 			<fieldset>
-					<legend>{$lang_advlink_advanced_props}</legend>
+					<legend>{#advlink_dlg.advanced_props}</legend>
 
 					<table border="0" cellpadding="0" cellspacing="4">
 						<tr>
-							<td class="column1"><label id="idlabel" for="id">{$lang_advlink_id}</label></td> 
+							<td class="column1"><label id="idlabel" for="id">{#advlink_dlg.id}</label></td> 
 							<td><input id="id" name="id" type="text" value="" /></td> 
 						</tr>
 
 						<tr>
-							<td><label id="stylelabel" for="style">{$lang_advlink_style}</label></td>
+							<td><label id="stylelabel" for="style">{#advlink_dlg.style}</label></td>
 							<td><input type="text" id="style" name="style" value="" /></td>
 						</tr>
 
 						<tr>
-							<td><label id="classeslabel" for="classes">{$lang_advlink_classes}</label></td>
+							<td><label id="classeslabel" for="classes">{#advlink_dlg.classes}</label></td>
 							<td><input type="text" id="classes" name="classes" value="" onchange="selectByValue(this.form,'classlist',this.value,true);" /></td>
 						</tr>
 
 						<tr>
-							<td><label id="targetlabel" for="target">{$lang_advlink_target_name}</label></td>
+							<td><label id="targetlabel" for="target">{#advlink_dlg.target_name}</label></td>
 							<td><input type="text" id="target" name="target" value="" onchange="selectByValue(this.form,'targetlist',this.value,true);" /></td>
 						</tr>
 
 						<tr>
-							<td class="column1"><label id="dirlabel" for="dir">{$lang_advlink_langdir}</label></td> 
+							<td class="column1"><label id="dirlabel" for="dir">{#advlink_dlg.langdir}</label></td> 
 							<td>
 								<select id="dir" name="dir"> 
-										<option value="">{$lang_not_set}</option> 
-										<option value="ltr">{$lang_advlink_ltr}</option> 
-										<option value="rtl">{$lang_advlink_rtl}</option> 
+										<option value="">{#not_set}</option> 
+										<option value="ltr">{#advlink_dlg.ltr}</option> 
+										<option value="rtl">{#advlink_dlg.rtl}</option> 
 								</select>
 							</td> 
 						</tr>
 
 						<tr>
-							<td><label id="hreflanglabel" for="hreflang">{$lang_advlink_target_langcode}</label></td>
+							<td><label id="hreflanglabel" for="hreflang">{#advlink_dlg.target_langcode}</label></td>
 							<td><input type="text" id="hreflang" name="hreflang" value="" /></td>
 						</tr>
 
 						<tr>
-							<td class="column1"><label id="langlabel" for="lang">{$lang_advlink_langcode}</label></td> 
+							<td class="column1"><label id="langlabel" for="lang">{#advlink_dlg.langcode}</label></td> 
 							<td>
 								<input id="lang" name="lang" type="text" value="" />
 							</td> 
 						</tr>
 
 						<tr>
-							<td><label id="charsetlabel" for="charset">{$lang_advlink_encoding}</label></td>
+							<td><label id="charsetlabel" for="charset">{#advlink_dlg.encoding}</label></td>
 							<td><input type="text" id="charset" name="charset" value="" /></td>
 						</tr>
 
 						<tr>
-							<td><label id="typelabel" for="type">{$lang_advlink_mime}</label></td>
+							<td><label id="typelabel" for="type">{#advlink_dlg.mime}</label></td>
 							<td><input type="text" id="type" name="type" value="" /></td>
 						</tr>
 
 						<tr>
-							<td><label id="rellabel" for="rel">{$lang_advlink_rel}</label></td>
+							<td><label id="rellabel" for="rel">{#advlink_dlg.rel}</label></td>
 							<td><select id="rel" name="rel"> 
-									<option value="">{$lang_not_set}</option> 
+									<option value="">{#not_set}</option> 
 									<option value="lightbox">Lightbox</option> 
 									<option value="alternate">Alternate</option> 
 									<option value="designates">Designates</option> 
@@ -219,9 +221,9 @@
 						</tr>
 
 						<tr>
-							<td><label id="revlabel" for="rev">{$lang_advlink_rev}</label></td>
+							<td><label id="revlabel" for="rev">{#advlink_dlg.rev}</label></td>
 							<td><select id="rev" name="rev"> 
-									<option value="">{$lang_not_set}</option> 
+									<option value="">{#not_set}</option> 
 									<option value="alternate">Alternate</option> 
 									<option value="designates">Designates</option> 
 									<option value="stylesheet">Stylesheet</option> 
@@ -242,12 +244,12 @@
 						</tr>
 
 						<tr>
-							<td><label id="tabindexlabel" for="tabindex">{$lang_advlink_tabindex}</label></td>
+							<td><label id="tabindexlabel" for="tabindex">{#advlink_dlg.tabindex}</label></td>
 							<td><input type="text" id="tabindex" name="tabindex" value="" /></td>
 						</tr>
 
 						<tr>
-							<td><label id="accesskeylabel" for="accesskey">{$lang_advlink_accesskey}</label></td>
+							<td><label id="accesskeylabel" for="accesskey">{#advlink_dlg.accesskey}</label></td>
 							<td><input type="text" id="accesskey" name="accesskey" value="" /></td>
 						</tr>
 					</table>
@@ -256,7 +258,7 @@
 
 			<div id="events_panel" class="panel">
 			<fieldset>
-					<legend>{$lang_advlink_event_props}</legend>
+					<legend>{#advlink_dlg.event_props}</legend>
 
 					<table border="0" cellpadding="0" cellspacing="4">
 						<tr>
@@ -325,11 +327,11 @@
 
 		<div class="mceActionPanel">
 			<div style="float: left">
-				<input type="button" id="insert" name="insert" value="{$lang_insert}" onclick="insertAction();" />
+				<input type="button" id="insert" name="insert" value="{#insert}" onclick="insertAction();" />
 			</div>
 
 			<div style="float: right">
-				<input type="button" id="cancel" name="cancel" value="{$lang_cancel}" onclick="tinyMCEPopup.close();" />
+				<input type="button" id="cancel" name="cancel" value="{#cancel}" onclick="tinyMCEPopup.close();" />
 			</div>
 		</div>
     </form>
--- a/includes/clientside/tinymce/plugins/advlink/readme.txt	Fri Feb 22 12:46:51 2008 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1 +0,0 @@
-Check the TinyMCE documentation for details on this plugin.
--- a/includes/clientside/tinymce/plugins/autosave/editor_plugin.js	Fri Feb 22 12:46:51 2008 -0500
+++ b/includes/clientside/tinymce/plugins/autosave/editor_plugin.js	Fri Feb 22 12:51:53 2008 -0500
@@ -1,1 +1,1 @@
-tinyMCE.importPluginLanguagePack('autosave');var TinyMCE_AutoSavePlugin={getInfo:function(){return{longname:'Auto save',author:'Moxiecode Systems AB',authorurl:'http://tinymce.moxiecode.com',infourl:'http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/autosave',version:tinyMCE.majorVersion+"."+tinyMCE.minorVersion}},_beforeUnloadHandler:function(){var n,inst,anyDirty=false,msg=tinyMCE.getLang("lang_autosave_unload_msg");if(tinyMCE.getParam("fullscreen_is_enabled"))return;for(n in tinyMCE.instances){inst=tinyMCE.instances[n];if(!tinyMCE.isInstance(inst))continue;if(inst.isDirty())return msg}return}};window.onbeforeunload=TinyMCE_AutoSavePlugin._beforeUnloadHandler;tinyMCE.addPlugin("autosave",TinyMCE_AutoSavePlugin);
\ No newline at end of file
+(function(){tinymce.create('tinymce.plugins.AutoSavePlugin',{init:function(ed,url){var t=this;t.editor=ed;window.onbeforeunload=tinymce.plugins.AutoSavePlugin._beforeUnloadHandler;},getInfo:function(){return{longname:'Auto save',author:'Moxiecode Systems AB',authorurl:'http://tinymce.moxiecode.com',infourl:'http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/autosave',version:tinymce.majorVersion+"."+tinymce.minorVersion};},'static':{_beforeUnloadHandler:function(){var msg;tinymce.each(tinyMCE.editors,function(ed){if(ed.getParam("fullscreen_is_enabled"))return;if(ed.isDirty()){msg=ed.getLang("autosave.unload_msg");return false;}});return msg;}}});tinymce.PluginManager.add('autosave',tinymce.plugins.AutoSavePlugin);})();
\ No newline at end of file
--- a/includes/clientside/tinymce/plugins/autosave/editor_plugin_src.js	Fri Feb 22 12:46:51 2008 -0500
+++ b/includes/clientside/tinymce/plugins/autosave/editor_plugin_src.js	Fri Feb 22 12:51:53 2008 -0500
@@ -1,46 +1,51 @@
 /**
- * $Id: editor_plugin_src.js 201 2007-02-12 15:56:56Z spocke $
+ * $Id: editor_plugin_src.js 520 2008-01-07 16:30:32Z spocke $
  *
  * @author Moxiecode
- * @copyright Copyright © 2004-2007, Moxiecode Systems AB, All rights reserved.
+ * @copyright Copyright © 2004-2008, Moxiecode Systems AB, All rights reserved.
  */
 
-/* Import plugin specific language pack */
-tinyMCE.importPluginLanguagePack('autosave');
+(function() {
+	tinymce.create('tinymce.plugins.AutoSavePlugin', {
+		init : function(ed, url) {
+			var t = this;
+
+			t.editor = ed;
+
+			window.onbeforeunload = tinymce.plugins.AutoSavePlugin._beforeUnloadHandler;
+		},
 
-var TinyMCE_AutoSavePlugin = {
-	getInfo : function() {
-		return {
-			longname : 'Auto save',
-			author : 'Moxiecode Systems AB',
-			authorurl : 'http://tinymce.moxiecode.com',
-			infourl : 'http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/autosave',
-			version : tinyMCE.majorVersion + "." + tinyMCE.minorVersion
-		};
-	},
+		getInfo : function() {
+			return {
+				longname : 'Auto save',
+				author : 'Moxiecode Systems AB',
+				authorurl : 'http://tinymce.moxiecode.com',
+				infourl : 'http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/autosave',
+				version : tinymce.majorVersion + "." + tinymce.minorVersion
+			};
+		},
 
-	// Private plugin internal methods
-
-	_beforeUnloadHandler : function() {
-		var n, inst, anyDirty = false, msg = tinyMCE.getLang("lang_autosave_unload_msg");
+		// Private plugin internal methods
 
-		if (tinyMCE.getParam("fullscreen_is_enabled"))
-			return;
+		'static' : {
+			_beforeUnloadHandler : function() {
+				var msg;
 
-		for (n in tinyMCE.instances) {
-			inst = tinyMCE.instances[n];
-
-			if (!tinyMCE.isInstance(inst))
-				continue;
+				tinymce.each(tinyMCE.editors, function(ed) {
+					if (ed.getParam("fullscreen_is_enabled"))
+						return;
 
-			if (inst.isDirty())
-				return msg;
-		}
+					if (ed.isDirty()) {
+						msg = ed.getLang("autosave.unload_msg");
+						return false;
+					}
+				});
 
-		return;
-	}
-};
+				return msg;
+			}
+		}
+	});
 
-window.onbeforeunload = TinyMCE_AutoSavePlugin._beforeUnloadHandler;
-
-tinyMCE.addPlugin("autosave", TinyMCE_AutoSavePlugin);
+	// Register plugin
+	tinymce.PluginManager.add('autosave', tinymce.plugins.AutoSavePlugin);
+})();
\ No newline at end of file
--- a/includes/clientside/tinymce/plugins/autosave/langs/en.js	Fri Feb 22 12:46:51 2008 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,5 +0,0 @@
-// EN lang variables
-
-tinyMCE.addToLang('',{
-autosave_unload_msg : 'The changes you made will be lost if you navigate away from this page.'
-});
--- a/includes/clientside/tinymce/plugins/autosave/readme.txt	Fri Feb 22 12:46:51 2008 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1 +0,0 @@
-Check the TinyMCE documentation for details on this plugin.
--- a/includes/clientside/tinymce/plugins/bbcode/editor_plugin.js	Fri Feb 22 12:46:51 2008 -0500
+++ b/includes/clientside/tinymce/plugins/bbcode/editor_plugin.js	Fri Feb 22 12:51:53 2008 -0500
@@ -1,1 +1,1 @@
-var TinyMCE_BBCodePlugin={getInfo:function(){return{longname:'BBCode Plugin',author:'Moxiecode Systems AB',authorurl:'http://tinymce.moxiecode.com',infourl:'http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/bbcode',version:tinyMCE.majorVersion+"."+tinyMCE.minorVersion}},cleanup:function(type,content){var dialect=tinyMCE.getParam('bbcode_dialect','punbb').toLowerCase();switch(type){case"insert_to_editor":content=this['_'+dialect+'_bbcode2html'](content);break;case"get_from_editor":content=this['_'+dialect+'_html2bbcode'](content);break}return content},_punbb_html2bbcode:function(s){s=tinyMCE.trim(s);function rep(re,str){s=s.replace(re,str)};rep(/<a href=\"(.*?)\".*?>(.*?)<\/a>/gi,"[url]$1[/url]");rep(/<font.*?color=\"(.*?)\".*?class=\"codeStyle\".*?>(.*?)<\/font>/gi,"[code][color=$1]$2[/color][/code]");rep(/<font.*?color=\"(.*?)\".*?class=\"quoteStyle\".*?>(.*?)<\/font>/gi,"[quote][color=$1]$2[/color][/quote]");rep(/<font.*?class=\"codeStyle\".*?color=\"(.*?)\".*?>(.*?)<\/font>/gi,"[code][color=$1]$2[/color][/code]");rep(/<font.*?class=\"quoteStyle\".*?color=\"(.*?)\".*?>(.*?)<\/font>/gi,"[quote][color=$1]$2[/color][/quote]");rep(/<font.*?color=\"(.*?)\".*?>(.*?)<\/font>/gi,"[color=$1]$2[/color]");rep(/<font>(.*?)<\/font>/gi,"$1");rep(/<img.*?src=\"(.*?)\".*?\/>/gi,"[img]$1[/img]");rep(/<span class=\"codeStyle\">(.*?)<\/span>/gi,"[code]$1[/code]");rep(/<span class=\"quoteStyle\">(.*?)<\/span>/gi,"[quote]$1[/quote]");rep(/<strong class=\"codeStyle\">(.*?)<\/strong>/gi,"[code][b]$1[/b][/code]");rep(/<strong class=\"quoteStyle\">(.*?)<\/strong>/gi,"[quote][b]$1[/b][/quote]");rep(/<em class=\"codeStyle\">(.*?)<\/em>/gi,"[code][i]$1[/i][/code]");rep(/<em class=\"quoteStyle\">(.*?)<\/em>/gi,"[quote][i]$1[/i][/quote]");rep(/<u class=\"codeStyle\">(.*?)<\/u>/gi,"[code][u]$1[/u][/code]");rep(/<u class=\"quoteStyle\">(.*?)<\/u>/gi,"[quote][u]$1[/u][/quote]");rep(/<\/(strong|b)>/gi,"[/b]");rep(/<(strong|b)>/gi,"[b]");rep(/<\/(em|i)>/gi,"[/i]");rep(/<(em|i)>/gi,"[i]");rep(/<\/u>/gi,"[/u]");rep(/<u>/gi,"[u]");rep(/<br \/>/gi,"\n");rep(/<br\/>/gi,"\n");rep(/<br>/gi,"\n");rep(/<p>/gi,"");rep(/<\/p>/gi,"\n");rep(/&nbsp;/gi," ");rep(/&quot;/gi,"\"");rep(/&lt;/gi,"<");rep(/&gt;/gi,">");rep(/&amp;/gi,"&");rep(/&undefined;/gi,"'");return s},_punbb_bbcode2html:function(s){s=tinyMCE.trim(s);function rep(re,str){s=s.replace(re,str)};rep(/\n/gi,"<br />");rep(/\[b\]/gi,"<strong>");rep(/\[\/b\]/gi,"</strong>");rep(/\[i\]/gi,"<em>");rep(/\[\/i\]/gi,"</em>");rep(/\[u\]/gi,"<u>");rep(/\[\/u\]/gi,"</u>");rep(/\[url\](.*?)\[\/url\]/gi,"<a href=\"$1\">$1</a>");rep(/\[img\](.*?)\[\/img\]/gi,"<img src=\"$1\" />");rep(/\[color=(.*?)\](.*?)\[\/color\]/gi,"<font color=\"$1\">$2</font>");rep(/\[code\](.*?)\[\/code\]/gi,"<span class=\"codeStyle\">$1</span>&nbsp;");rep(/\[quote.*?\](.*?)\[\/quote\]/gi,"<span class=\"quoteStyle\">$1</span>&nbsp;");return s}};tinyMCE.addPlugin("bbcode",TinyMCE_BBCodePlugin);
\ No newline at end of file
+(function(){tinymce.create('tinymce.plugins.BBCodePlugin',{init:function(ed,url){var t=this,dialect=ed.getParam('bbcode_dialect','punbb').toLowerCase();ed.onBeforeSetContent.add(function(ed,o){o.content=t['_'+dialect+'_bbcode2html'](o.content);});ed.onPostProcess.add(function(ed,o){if(o.set)o.content=t['_'+dialect+'_bbcode2html'](o.content);if(o.get)o.content=t['_'+dialect+'_html2bbcode'](o.content);});},getInfo:function(){return{longname:'BBCode Plugin',author:'Moxiecode Systems AB',authorurl:'http://tinymce.moxiecode.com',infourl:'http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/bbcode',version:tinymce.majorVersion+"."+tinymce.minorVersion};},_punbb_html2bbcode:function(s){s=tinymce.trim(s);function rep(re,str){s=s.replace(re,str);};rep(/<a.*?href=\"(.*?)\".*?>(.*?)<\/a>/gi,"[url=$1]$2[/url]");rep(/<font.*?color=\"(.*?)\".*?class=\"codeStyle\".*?>(.*?)<\/font>/gi,"[code][color=$1]$2[/color][/code]");rep(/<font.*?color=\"(.*?)\".*?class=\"quoteStyle\".*?>(.*?)<\/font>/gi,"[quote][color=$1]$2[/color][/quote]");rep(/<font.*?class=\"codeStyle\".*?color=\"(.*?)\".*?>(.*?)<\/font>/gi,"[code][color=$1]$2[/color][/code]");rep(/<font.*?class=\"quoteStyle\".*?color=\"(.*?)\".*?>(.*?)<\/font>/gi,"[quote][color=$1]$2[/color][/quote]");rep(/<span style=\"color: ?(.*?);\">(.*?)<\/span>/gi,"[color=$1]$2[/color]");rep(/<font.*?color=\"(.*?)\".*?>(.*?)<\/font>/gi,"[color=$1]$2[/color]");rep(/<span style=\"font-size:(.*?);\">(.*?)<\/span>/gi,"[size=$1]$2[/size]");rep(/<font>(.*?)<\/font>/gi,"$1");rep(/<img.*?src=\"(.*?)\".*?\/>/gi,"[img]$1[/img]");rep(/<span class=\"codeStyle\">(.*?)<\/span>/gi,"[code]$1[/code]");rep(/<span class=\"quoteStyle\">(.*?)<\/span>/gi,"[quote]$1[/quote]");rep(/<strong class=\"codeStyle\">(.*?)<\/strong>/gi,"[code][b]$1[/b][/code]");rep(/<strong class=\"quoteStyle\">(.*?)<\/strong>/gi,"[quote][b]$1[/b][/quote]");rep(/<em class=\"codeStyle\">(.*?)<\/em>/gi,"[code][i]$1[/i][/code]");rep(/<em class=\"quoteStyle\">(.*?)<\/em>/gi,"[quote][i]$1[/i][/quote]");rep(/<u class=\"codeStyle\">(.*?)<\/u>/gi,"[code][u]$1[/u][/code]");rep(/<u class=\"quoteStyle\">(.*?)<\/u>/gi,"[quote][u]$1[/u][/quote]");rep(/<\/(strong|b)>/gi,"[/b]");rep(/<(strong|b)>/gi,"[b]");rep(/<\/(em|i)>/gi,"[/i]");rep(/<(em|i)>/gi,"[i]");rep(/<\/u>/gi,"[/u]");rep(/<span style=\"text-decoration: ?underline;\">(.*?)<\/span>/gi,"[u]$1[/u]");rep(/<u>/gi,"[u]");rep(/<br \/>/gi,"\n");rep(/<br\/>/gi,"\n");rep(/<br>/gi,"\n");rep(/<p>/gi,"");rep(/<\/p>/gi,"\n");rep(/&nbsp;/gi," ");rep(/&quot;/gi,"\"");rep(/&lt;/gi,"<");rep(/&gt;/gi,">");rep(/&amp;/gi,"&");return s;},_punbb_bbcode2html:function(s){s=tinymce.trim(s);function rep(re,str){s=s.replace(re,str);};rep(/\n/gi,"<br />");rep(/\[b\]/gi,"<strong>");rep(/\[\/b\]/gi,"</strong>");rep(/\[i\]/gi,"<em>");rep(/\[\/i\]/gi,"</em>");rep(/\[u\]/gi,"<u>");rep(/\[\/u\]/gi,"</u>");rep(/\[url=([^\]]+)\](.*?)\[\/url\]/gi,"<a href=\"$1\">$2</a>");rep(/\[url\](.*?)\[\/url\]/gi,"<a href=\"$1\">$1</a>");rep(/\[img\](.*?)\[\/img\]/gi,"<img src=\"$1\" />");rep(/\[color=(.*?)\](.*?)\[\/color\]/gi,"<font color=\"$1\">$2</font>");rep(/\[code\](.*?)\[\/code\]/gi,"<span class=\"codeStyle\">$1</span>&nbsp;");rep(/\[quote.*?\](.*?)\[\/quote\]/gi,"<span class=\"quoteStyle\">$1</span>&nbsp;");return s;}});tinymce.PluginManager.add('bbcode',tinymce.plugins.BBCodePlugin);})();
\ No newline at end of file
--- a/includes/clientside/tinymce/plugins/bbcode/editor_plugin_src.js	Fri Feb 22 12:46:51 2008 -0500
+++ b/includes/clientside/tinymce/plugins/bbcode/editor_plugin_src.js	Fri Feb 22 12:51:53 2008 -0500
@@ -1,102 +1,115 @@
-var TinyMCE_BBCodePlugin = {
-	getInfo : function() {
-		return {
-			longname : 'BBCode Plugin',
-			author : 'Moxiecode Systems AB',
-			authorurl : 'http://tinymce.moxiecode.com',
-			infourl : 'http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/bbcode',
-			version : tinyMCE.majorVersion + "." + tinyMCE.minorVersion
-		};
-	},
+/**
+ * $Id: editor_plugin_src.js 201 2007-02-12 15:56:56Z spocke $
+ *
+ * @author Moxiecode
+ * @copyright Copyright © 2004-2008, Moxiecode Systems AB, All rights reserved.
+ */
 
-	cleanup : function(type, content) {
-		var dialect = tinyMCE.getParam('bbcode_dialect', 'punbb').toLowerCase();
+(function() {
+	tinymce.create('tinymce.plugins.BBCodePlugin', {
+		init : function(ed, url) {
+			var t = this, dialect = ed.getParam('bbcode_dialect', 'punbb').toLowerCase();
+
+			ed.onBeforeSetContent.add(function(ed, o) {
+				o.content = t['_' + dialect + '_bbcode2html'](o.content);
+			});
+
+			ed.onPostProcess.add(function(ed, o) {
+				if (o.set)
+					o.content = t['_' + dialect + '_bbcode2html'](o.content);
 
-		switch (type) {
-			case "insert_to_editor":
-				content = this['_' + dialect + '_bbcode2html'](content);
-				break;
-
-			case "get_from_editor":
-				content = this['_' + dialect + '_html2bbcode'](content);
-				break;
-		}
+				if (o.get)
+					o.content = t['_' + dialect + '_html2bbcode'](o.content);
+			});
+		},
 
-		return content;
-	},
-
-	// Private methods
+		getInfo : function() {
+			return {
+				longname : 'BBCode Plugin',
+				author : 'Moxiecode Systems AB',
+				authorurl : 'http://tinymce.moxiecode.com',
+				infourl : 'http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/bbcode',
+				version : tinymce.majorVersion + "." + tinymce.minorVersion
+			};
+		},
 
-	// HTML -> BBCode in PunBB dialect
-	_punbb_html2bbcode : function(s) {
-		s = tinyMCE.trim(s);
+		// Private methods
 
-		function rep(re, str) {
-			s = s.replace(re, str);
-		};
+		// HTML -> BBCode in PunBB dialect
+		_punbb_html2bbcode : function(s) {
+			s = tinymce.trim(s);
+
+			function rep(re, str) {
+				s = s.replace(re, str);
+			};
 
-		// example: <strong> to [b]
-		rep(/<a href=\"(.*?)\".*?>(.*?)<\/a>/gi,"[url]$1[/url]");
-		rep(/<font.*?color=\"(.*?)\".*?class=\"codeStyle\".*?>(.*?)<\/font>/gi,"[code][color=$1]$2[/color][/code]");
-		rep(/<font.*?color=\"(.*?)\".*?class=\"quoteStyle\".*?>(.*?)<\/font>/gi,"[quote][color=$1]$2[/color][/quote]");
-		rep(/<font.*?class=\"codeStyle\".*?color=\"(.*?)\".*?>(.*?)<\/font>/gi,"[code][color=$1]$2[/color][/code]");
-		rep(/<font.*?class=\"quoteStyle\".*?color=\"(.*?)\".*?>(.*?)<\/font>/gi,"[quote][color=$1]$2[/color][/quote]");
-		rep(/<font.*?color=\"(.*?)\".*?>(.*?)<\/font>/gi,"[color=$1]$2[/color]");
-		rep(/<font>(.*?)<\/font>/gi,"$1");
-		rep(/<img.*?src=\"(.*?)\".*?\/>/gi,"[img]$1[/img]");
-		rep(/<span class=\"codeStyle\">(.*?)<\/span>/gi,"[code]$1[/code]");
-		rep(/<span class=\"quoteStyle\">(.*?)<\/span>/gi,"[quote]$1[/quote]");
-		rep(/<strong class=\"codeStyle\">(.*?)<\/strong>/gi,"[code][b]$1[/b][/code]");
-		rep(/<strong class=\"quoteStyle\">(.*?)<\/strong>/gi,"[quote][b]$1[/b][/quote]");
-		rep(/<em class=\"codeStyle\">(.*?)<\/em>/gi,"[code][i]$1[/i][/code]");
-		rep(/<em class=\"quoteStyle\">(.*?)<\/em>/gi,"[quote][i]$1[/i][/quote]");
-		rep(/<u class=\"codeStyle\">(.*?)<\/u>/gi,"[code][u]$1[/u][/code]");
-		rep(/<u class=\"quoteStyle\">(.*?)<\/u>/gi,"[quote][u]$1[/u][/quote]");
-		rep(/<\/(strong|b)>/gi,"[/b]");
-		rep(/<(strong|b)>/gi,"[b]");
-		rep(/<\/(em|i)>/gi,"[/i]");
-		rep(/<(em|i)>/gi,"[i]");
-		rep(/<\/u>/gi,"[/u]");
-		rep(/<u>/gi,"[u]");
-		rep(/<br \/>/gi,"\n");
-		rep(/<br\/>/gi,"\n");
-		rep(/<br>/gi,"\n");
-		rep(/<p>/gi,"");
-		rep(/<\/p>/gi,"\n");
-		rep(/&nbsp;/gi," ");
-		rep(/&quot;/gi,"\"");
-		rep(/&lt;/gi,"<");
-		rep(/&gt;/gi,">");
-		rep(/&amp;/gi,"&");
-		rep(/&undefined;/gi,"'"); // quickfix
+			// example: <strong> to [b]
+			rep(/<a.*?href=\"(.*?)\".*?>(.*?)<\/a>/gi,"[url=$1]$2[/url]");
+			rep(/<font.*?color=\"(.*?)\".*?class=\"codeStyle\".*?>(.*?)<\/font>/gi,"[code][color=$1]$2[/color][/code]");
+			rep(/<font.*?color=\"(.*?)\".*?class=\"quoteStyle\".*?>(.*?)<\/font>/gi,"[quote][color=$1]$2[/color][/quote]");
+			rep(/<font.*?class=\"codeStyle\".*?color=\"(.*?)\".*?>(.*?)<\/font>/gi,"[code][color=$1]$2[/color][/code]");
+			rep(/<font.*?class=\"quoteStyle\".*?color=\"(.*?)\".*?>(.*?)<\/font>/gi,"[quote][color=$1]$2[/color][/quote]");
+			rep(/<span style=\"color: ?(.*?);\">(.*?)<\/span>/gi,"[color=$1]$2[/color]");
+			rep(/<font.*?color=\"(.*?)\".*?>(.*?)<\/font>/gi,"[color=$1]$2[/color]");
+			rep(/<span style=\"font-size:(.*?);\">(.*?)<\/span>/gi,"[size=$1]$2[/size]");
+			rep(/<font>(.*?)<\/font>/gi,"$1");
+			rep(/<img.*?src=\"(.*?)\".*?\/>/gi,"[img]$1[/img]");
+			rep(/<span class=\"codeStyle\">(.*?)<\/span>/gi,"[code]$1[/code]");
+			rep(/<span class=\"quoteStyle\">(.*?)<\/span>/gi,"[quote]$1[/quote]");
+			rep(/<strong class=\"codeStyle\">(.*?)<\/strong>/gi,"[code][b]$1[/b][/code]");
+			rep(/<strong class=\"quoteStyle\">(.*?)<\/strong>/gi,"[quote][b]$1[/b][/quote]");
+			rep(/<em class=\"codeStyle\">(.*?)<\/em>/gi,"[code][i]$1[/i][/code]");
+			rep(/<em class=\"quoteStyle\">(.*?)<\/em>/gi,"[quote][i]$1[/i][/quote]");
+			rep(/<u class=\"codeStyle\">(.*?)<\/u>/gi,"[code][u]$1[/u][/code]");
+			rep(/<u class=\"quoteStyle\">(.*?)<\/u>/gi,"[quote][u]$1[/u][/quote]");
+			rep(/<\/(strong|b)>/gi,"[/b]");
+			rep(/<(strong|b)>/gi,"[b]");
+			rep(/<\/(em|i)>/gi,"[/i]");
+			rep(/<(em|i)>/gi,"[i]");
+			rep(/<\/u>/gi,"[/u]");
+			rep(/<span style=\"text-decoration: ?underline;\">(.*?)<\/span>/gi,"[u]$1[/u]");
+			rep(/<u>/gi,"[u]");
+			rep(/<br \/>/gi,"\n");
+			rep(/<br\/>/gi,"\n");
+			rep(/<br>/gi,"\n");
+			rep(/<p>/gi,"");
+			rep(/<\/p>/gi,"\n");
+			rep(/&nbsp;/gi," ");
+			rep(/&quot;/gi,"\"");
+			rep(/&lt;/gi,"<");
+			rep(/&gt;/gi,">");
+			rep(/&amp;/gi,"&");
 
-		return s; 
-	},
+			return s; 
+		},
 
-	// BBCode -> HTML from PunBB dialect
-	_punbb_bbcode2html : function(s) {
-		s = tinyMCE.trim(s);
+		// BBCode -> HTML from PunBB dialect
+		_punbb_bbcode2html : function(s) {
+			s = tinymce.trim(s);
 
-		function rep(re, str) {
-			s = s.replace(re, str);
-		};
+			function rep(re, str) {
+				s = s.replace(re, str);
+			};
 
-		// example: [b] to <strong>
-		rep(/\n/gi,"<br />");
-		rep(/\[b\]/gi,"<strong>");
-		rep(/\[\/b\]/gi,"</strong>");
-		rep(/\[i\]/gi,"<em>");
-		rep(/\[\/i\]/gi,"</em>");
-		rep(/\[u\]/gi,"<u>");
-		rep(/\[\/u\]/gi,"</u>");
-		rep(/\[url\](.*?)\[\/url\]/gi,"<a href=\"$1\">$1</a>");
-		rep(/\[img\](.*?)\[\/img\]/gi,"<img src=\"$1\" />");
-		rep(/\[color=(.*?)\](.*?)\[\/color\]/gi,"<font color=\"$1\">$2</font>");
-		rep(/\[code\](.*?)\[\/code\]/gi,"<span class=\"codeStyle\">$1</span>&nbsp;");
-		rep(/\[quote.*?\](.*?)\[\/quote\]/gi,"<span class=\"quoteStyle\">$1</span>&nbsp;");
+			// example: [b] to <strong>
+			rep(/\n/gi,"<br />");
+			rep(/\[b\]/gi,"<strong>");
+			rep(/\[\/b\]/gi,"</strong>");
+			rep(/\[i\]/gi,"<em>");
+			rep(/\[\/i\]/gi,"</em>");
+			rep(/\[u\]/gi,"<u>");
+			rep(/\[\/u\]/gi,"</u>");
+			rep(/\[url=([^\]]+)\](.*?)\[\/url\]/gi,"<a href=\"$1\">$2</a>");
+			rep(/\[url\](.*?)\[\/url\]/gi,"<a href=\"$1\">$1</a>");
+			rep(/\[img\](.*?)\[\/img\]/gi,"<img src=\"$1\" />");
+			rep(/\[color=(.*?)\](.*?)\[\/color\]/gi,"<font color=\"$1\">$2</font>");
+			rep(/\[code\](.*?)\[\/code\]/gi,"<span class=\"codeStyle\">$1</span>&nbsp;");
+			rep(/\[quote.*?\](.*?)\[\/quote\]/gi,"<span class=\"quoteStyle\">$1</span>&nbsp;");
 
-		return s; 
-	}
-};
+			return s; 
+		}
+	});
 
-tinyMCE.addPlugin("bbcode", TinyMCE_BBCodePlugin);
+	// Register plugin
+	tinymce.PluginManager.add('bbcode', tinymce.plugins.BBCodePlugin);
+})();
\ No newline at end of file
--- a/includes/clientside/tinymce/plugins/cleanup/editor_plugin_src.js	Fri Feb 22 12:46:51 2008 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,10 +0,0 @@
-/**
- * $Id: editor_plugin_src.js 162 2007-01-03 16:16:52Z spocke $
- *
- * Experimental plugin for new Cleanup routine, this logic will be moved into the core ones it's stable enougth.
- *
- * @author Moxiecode
- * @copyright Copyright © 2004-2007, Moxiecode Systems AB, All rights reserved.
- */
-
-/* Dummy file since cleanup is now moved to core */
--- a/includes/clientside/tinymce/plugins/cleanup/readme.txt	Fri Feb 22 12:46:51 2008 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1 +0,0 @@
-Dummy plugin since cleanup is now moved into core.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/includes/clientside/tinymce/plugins/compat2x/editor_plugin.js	Fri Feb 22 12:51:53 2008 -0500
@@ -0,0 +1,1 @@
+(function(){var DOM=tinymce.DOM,Event=tinymce.dom.Event,each=tinymce.each,is=tinymce.is;tinymce.create('tinymce.plugins.Compat2x',{getInfo:function(){return{longname:'Compat2x',author:'Moxiecode Systems AB',authorurl:'http://tinymce.moxiecode.com',infourl:'http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/compat2x',version:tinyMCE.majorVersion+"."+tinyMCE.minorVersion};}});(function(){tinymce.extend(tinyMCE,{addToLang:function(p,l){each(l,function(v,k){tinyMCE.i18n[(tinyMCE.settings.language||'en')+'.'+(p?p+'_':'')+k]=v;});},getInstanceById:function(n){return this.get(n);}});})();(function(){var EditorManager=tinymce.EditorManager;tinyMCE.instances={};tinyMCE.plugins={};tinymce.PluginManager.onAdd.add(function(pm,n,p){tinyMCE.plugins[n]=p;});tinyMCE.majorVersion=tinymce.majorVersion;tinyMCE.minorVersion=tinymce.minorVersion;tinyMCE.releaseDate=tinymce.releaseDate;tinyMCE.baseURL=tinymce.baseURL;tinyMCE.isIE=tinyMCE.isMSIE=tinymce.isIE||tinymce.isOpera;tinyMCE.isMSIE5=tinymce.isIE;tinyMCE.isMSIE5_0=tinymce.isIE;tinyMCE.isMSIE7=tinymce.isIE;tinyMCE.isGecko=tinymce.isGecko;tinyMCE.isSafari=tinymce.isWebKit;tinyMCE.isOpera=tinymce.isOpera;tinyMCE.isMac=false;tinyMCE.isNS7=false;tinyMCE.isNS71=false;tinyMCE.compat=true;TinyMCE_Engine=tinyMCE;tinymce.extend(tinyMCE,{getParam:function(n,dv){return this.activeEditor.getParam(n,dv);},addEvent:function(e,na,f,sc){tinymce.dom.Event.add(e,na,f,sc||this);},getControlHTML:function(n){return EditorManager.activeEditor.controlManager.createControl(n);},loadCSS:function(u){tinymce.DOM.loadCSS(u);},importCSS:function(doc,u){if(doc==document)this.loadCSS(u);else new tinymce.dom.DOMUtils(doc).loadCSS(u);},log:function(){console.debug.apply(console,arguments);},getLang:function(n,dv){var v=EditorManager.activeEditor.getLang(n.replace(/^lang_/g,''),dv);if(/^[0-9\-.]+$/g.test(v))return parseInt(v);return v;},isInstance:function(o){return o!=null&&typeof(o)=="object"&&o.execCommand;},triggerNodeChange:function(){EditorManager.activeEditor.nodeChanged();},regexpReplace:function(in_str,reg_exp,replace_str,opts){var re;if(in_str==null)return in_str;if(typeof(opts)=="undefined")opts='g';re=new RegExp(reg_exp,opts);return in_str.replace(re,replace_str);},trim:function(s){return tinymce.trim(s);},xmlEncode:function(s){return tinymce.DOM.encode(s);},explode:function(s,d){var o=[];tinymce.each(s.split(d),function(v){if(v!='')o.push(v);});return o;},switchClass:function(id,cls){var b;if(/^mceButton/.test(cls)){b=EditorManager.activeEditor.controlManager.get(id);if(!b)return;switch(cls){case"mceButtonNormal":b.setDisabled(false);b.setActive(false);return;case"mceButtonDisabled":b.setDisabled(true);return;case"mceButtonSelected":b.setActive(true);b.setDisabled(false);return;}}},addCSSClass:function(e,n,b){return tinymce.DOM.addClass(e,n,b);},hasCSSClass:function(e,n){return tinymce.DOM.hasClass(e,n);},removeCSSClass:function(e,n){return tinymce.DOM.removeClass(e,n);},getCSSClasses:function(){var cl=EditorManager.activeEditor.dom.getClasses(),o=[];each(cl,function(c){o.push(c['class']);});return o;},setWindowArg:function(n,v){EditorManager.activeEditor.windowManager.params[n]=v;},getWindowArg:function(n,dv){var wm=EditorManager.activeEditor.windowManager,v;v=wm.getParam(n);if(v==='')return'';return v||wm.getFeature(n)||dv;},getParentNode:function(n,f){return this._getDOM().getParent(n,f);},selectElements:function(n,na,f){var i,a=[],nl,x;for(x=0,na=na.split(',');x<na.length;x++)for(i=0,nl=n.getElementsByTagName(na[x]);i<nl.length;i++)(!f||f(nl[i]))&&a.push(nl[i]);return a;},getNodeTree:function(n,na,t,nn){return this.selectNodes(n,function(n){return(!t||n.nodeType==t)&&(!nn||n.nodeName==nn);},na?na:[]);},getAttrib:function(e,n,dv){return this._getDOM().getAttrib(e,n,dv);},setAttrib:function(e,n,v){return this._getDOM().setAttrib(e,n,v);},getElementsByAttributeValue:function(n,e,a,v){var i,nl=n.getElementsByTagName(e),o=[];for(i=0;i<nl.length;i++){if(tinyMCE.getAttrib(nl[i],a).indexOf(v)!=-1)o[o.length]=nl[i];}return o;},selectNodes:function(n,f,a){var i;if(!a)a=[];if(f(n))a[a.length]=n;if(n.hasChildNodes()){for(i=0;i<n.childNodes.length;i++)tinyMCE.selectNodes(n.childNodes[i],f,a);}return a;},getContent:function(){return EditorManager.activeEditor.getContent();},getParentElement:function(n,na,f){if(na)na=new RegExp('^('+na.toUpperCase().replace(/,/g,'|')+')$','g');return this._getDOM().getParent(n,function(n){return n.nodeType==1&&(!na||na.test(n.nodeName))&&(!f||f(n));},this.activeEditor.getBody());},importPluginLanguagePack:function(n){tinymce.PluginManager.requireLangPack(n);},getButtonHTML:function(cn,lang,img,c,u,v){var ed=EditorManager.activeEditor;img=img.replace(/\{\$pluginurl\}/g,tinyMCE.pluginURL);img=img.replace(/\{\$themeurl\}/g,tinyMCE.themeURL);lang=lang.replace(/^lang_/g,'');return ed.controlManager.createButton(cn,{title:lang,command:c,ui:u,value:v,scope:this,'class':'compat',image:img});},addSelectAccessibility:function(e,s,w){if(!s._isAccessible){s.onkeydown=tinyMCE.accessibleEventHandler;s.onblur=tinyMCE.accessibleEventHandler;s._isAccessible=true;s._win=w;}return false;},accessibleEventHandler:function(e){var elm,win=this._win;e=tinymce.isIE?win.event:e;elm=tinymce.isIE?e.srcElement:e.target;if(e.type=="blur"){if(elm.oldonchange){elm.onchange=elm.oldonchange;elm.oldonchange=null;}return true;}if(elm.nodeName=="SELECT"&&!elm.oldonchange){elm.oldonchange=elm.onchange;elm.onchange=null;}if(e.keyCode==13||e.keyCode==32){elm.onchange=elm.oldonchange;elm.onchange();elm.oldonchange=null;tinyMCE.cancelEvent(e);return false;}return true;},cancelEvent:function(e){return tinymce.dom.Event.cancel(e);},handleVisualAid:function(e){EditorManager.activeEditor.addVisual(e);},getAbsPosition:function(n,r){return tinymce.DOM.getPos(n,r);},cleanupEventStr:function(s){s=""+s;s=s.replace('function anonymous()\n{\n','');s=s.replace('\n}','');s=s.replace(/^return true;/gi,'');return s;},getVisualAidClass:function(s){return s;},parseStyle:function(s){return this._getDOM().parseStyle(s);},serializeStyle:function(s){return this._getDOM().serializeStyle(s);},openWindow:function(tpl,args){var ed=EditorManager.activeEditor,o={},n;for(n in tpl)o[n]=tpl[n];tpl=o;args=args||{};tpl.url=new tinymce.util.URI(tinymce.ThemeManager.themeURLs[ed.settings.theme]).toAbsolute(tpl.file);tpl.inline=tpl.inline||args.inline;ed.windowManager.open(tpl,args);},closeWindow:function(win){EditorManager.activeEditor.windowManager.close(win);},getOuterHTML:function(e){return tinymce.DOM.getOuterHTML(e);},setOuterHTML:function(e,h,d){return tinymce.DOM.setOuterHTML(e,h,d);},hasPlugin:function(n){return tinymce.PluginManager.get(n)!=null;},_setEventsEnabled:function(){},addPlugin:function(pn,f){var t=this;function PluginWrapper(ed){tinyMCE.selectedInstance=ed;ed.onInit.add(function(){t.settings=ed.settings;t.settings['base_href']=tinyMCE.documentBasePath;tinyMCE.settings=t.settings;tinyMCE.documentBasePath=ed.documentBasePath;if(f.initInstance)f.initInstance(ed);ed.contentDocument=ed.getDoc();ed.contentWindow=ed.getWin();ed.undoRedo=ed.undoManager;ed.startContent=ed.getContent({format:'raw'});tinyMCE.instances[ed.id]=ed;tinyMCE.loadedFiles=[];});ed.onActivate.add(function(){tinyMCE.settings=ed.settings;tinyMCE.selectedInstance=ed;});if(f.handleNodeChange){ed.onNodeChange.add(function(ed,cm,n){f.handleNodeChange(ed.id,n,0,0,false,!ed.selection.isCollapsed());});}if(f.onChange){ed.onChange.add(function(ed,n){return f.onChange(ed);});}if(f.cleanup){ed.onGetContent.add(function(){});}this.getInfo=function(){return f.getInfo();};this.createControl=function(n){tinyMCE.pluginURL=tinymce.baseURL+'/plugins/'+pn;tinyMCE.themeURL=tinymce.baseURL+'/themes/'+tinyMCE.activeEditor.settings.theme;if(f.getControlHTML)return f.getControlHTML(n);return null;};this.execCommand=function(cmd,ui,val){if(f.execCommand)return f.execCommand(ed.id,ed.getBody(),cmd,ui,val);return false;};};tinymce.PluginManager.add(pn,PluginWrapper);},_getDOM:function(){return tinyMCE.activeEditor?tinyMCE.activeEditor.dom:tinymce.DOM;},convertRelativeToAbsoluteURL:function(b,u){return new tinymce.util.URI(b).toAbsolute(u);},convertAbsoluteURLToRelativeURL:function(b,u){return new tinymce.util.URI(b).toRelative(u);}});tinymce.extend(tinymce.Editor.prototype,{getFocusElement:function(){return this.selection.getNode();},getData:function(n){if(!this.data)this.data=[];if(!this.data[n])this.data[n]=[];return this.data[n];},hasPlugin:function(n){return this.plugins[n]!=null;},getContainerWin:function(){return window;},getHTML:function(raw){return this.getContent({format:raw?'raw':'html'});},setHTML:function(h){this.setContent(h);},getSel:function(){return this.selection.getSel();},getRng:function(){return this.selection.getRng();},isHidden:function(){var s;if(!tinymce.isGecko)return false;s=this.getSel();return(!s||!s.rangeCount||s.rangeCount==0);},translate:function(s){var c=this.settings.language,o;o=tinymce.EditorManager.i18n[c+'.'+s]||s.replace(/{\#([^}]+)\}/g,function(a,b){return tinymce.EditorManager.i18n[c+'.'+b]||'{#'+b+'}';});o=o.replace(/{\$lang_([^}]+)\}/g,function(a,b){return tinymce.EditorManager.i18n[c+'.'+b]||'{$lang_'+b+'}';});return o;},repaint:function(){this.execCommand('mceRepaint');}});tinymce.extend(tinymce.dom.Selection.prototype,{getSelectedText:function(){return this.getContent({format:'text'});},getSelectedHTML:function(){return this.getContent({format:'html'});},getFocusElement:function(){return this.getNode();},selectNode:function(node,collapse,select_text_node,to_start){var t=this;t.select(node,select_text_node||0);if(!is(collapse))collapse=true;if(collapse){if(!is(to_start))to_start=true;t.collapse(to_start);}}});}).call(this);tinymce.PluginManager.add('compat2x',tinymce.plugins.Compat2x);})();
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/includes/clientside/tinymce/plugins/compat2x/editor_plugin_src.js	Fri Feb 22 12:51:53 2008 -0500
@@ -0,0 +1,613 @@
+/**
+ * $Id: editor_plugin_src.js 264 2007-04-26 20:53:09Z spocke $
+ *
+ * @author Moxiecode
+ * @copyright Copyright © 2004-2008, Moxiecode Systems AB, All rights reserved.
+ */
+
+(function() {
+	var DOM = tinymce.DOM, Event = tinymce.dom.Event, each = tinymce.each, is = tinymce.is;
+
+	tinymce.create('tinymce.plugins.Compat2x', {
+		getInfo : function() {
+			return {
+				longname : 'Compat2x',
+				author : 'Moxiecode Systems AB',
+				authorurl : 'http://tinymce.moxiecode.com',
+				infourl : 'http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/compat2x',
+				version : tinyMCE.majorVersion + "." + tinyMCE.minorVersion
+			};
+		}
+	});
+
+	(function() {
+		// Extend tinyMCE/EditorManager
+		tinymce.extend(tinyMCE, {
+			addToLang : function(p, l) {
+				each(l, function(v, k) {
+					tinyMCE.i18n[(tinyMCE.settings.language || 'en') + '.' + (p ? p + '_' : '') + k] = v;
+				});
+			},
+
+			getInstanceById : function(n) {
+				return this.get(n);
+			}
+		});
+	})();
+
+	(function() {
+		var EditorManager = tinymce.EditorManager;
+
+		tinyMCE.instances = {};
+		tinyMCE.plugins = {};
+		tinymce.PluginManager.onAdd.add(function(pm, n, p) {
+			tinyMCE.plugins[n] = p;
+		});
+
+		tinyMCE.majorVersion = tinymce.majorVersion;
+		tinyMCE.minorVersion = tinymce.minorVersion;
+		tinyMCE.releaseDate = tinymce.releaseDate;
+		tinyMCE.baseURL = tinymce.baseURL;
+		tinyMCE.isIE = tinyMCE.isMSIE = tinymce.isIE || tinymce.isOpera;
+		tinyMCE.isMSIE5 = tinymce.isIE;
+		tinyMCE.isMSIE5_0 = tinymce.isIE;
+		tinyMCE.isMSIE7 = tinymce.isIE;
+		tinyMCE.isGecko = tinymce.isGecko;
+		tinyMCE.isSafari = tinymce.isWebKit;
+		tinyMCE.isOpera = tinymce.isOpera;
+		tinyMCE.isMac = false;
+		tinyMCE.isNS7 = false;
+		tinyMCE.isNS71 = false;
+		tinyMCE.compat = true;
+
+		// Extend tinyMCE class
+		TinyMCE_Engine = tinyMCE;
+		tinymce.extend(tinyMCE, {
+			getParam : function(n, dv) {
+				return this.activeEditor.getParam(n, dv);
+			},
+
+			addEvent : function(e, na, f, sc) {
+				tinymce.dom.Event.add(e, na, f, sc || this);
+			},
+
+			getControlHTML : function(n) {
+				return EditorManager.activeEditor.controlManager.createControl(n);
+			},
+
+			loadCSS : function(u) {
+				tinymce.DOM.loadCSS(u);
+			},
+
+			importCSS : function(doc, u) {
+				if (doc == document)
+					this.loadCSS(u);
+				else
+					new tinymce.dom.DOMUtils(doc).loadCSS(u);
+			},
+
+			log : function() {
+				console.debug.apply(console, arguments);
+			},
+
+			getLang : function(n, dv) {
+				var v = EditorManager.activeEditor.getLang(n.replace(/^lang_/g, ''), dv);
+
+				// Is number
+				if (/^[0-9\-.]+$/g.test(v))
+					return parseInt(v);
+
+				return v;
+			},
+
+			isInstance : function(o) {
+				return o != null && typeof(o) == "object" && o.execCommand;
+			},
+
+			triggerNodeChange : function() {
+				EditorManager.activeEditor.nodeChanged();
+			},
+
+			regexpReplace : function(in_str, reg_exp, replace_str, opts) {
+				var re;
+
+				if (in_str == null)
+					return in_str;
+
+				if (typeof(opts) == "undefined")
+					opts = 'g';
+
+				re = new RegExp(reg_exp, opts);
+
+				return in_str.replace(re, replace_str);
+			},
+
+			trim : function(s) {
+				return tinymce.trim(s);
+			},
+
+			xmlEncode : function(s) {
+				return tinymce.DOM.encode(s);
+			},
+
+			explode : function(s, d) {
+				var o = [];
+
+				tinymce.each(s.split(d), function(v) {
+					if (v != '')
+						o.push(v);
+				});
+
+				return o;
+			},
+
+			switchClass : function(id, cls) {
+				var b;
+
+				if (/^mceButton/.test(cls)) {
+					b = EditorManager.activeEditor.controlManager.get(id);
+
+					if (!b)
+						return;
+
+					switch (cls) {
+						case "mceButtonNormal":
+							b.setDisabled(false);
+							b.setActive(false);
+							return;
+
+						case "mceButtonDisabled":
+							b.setDisabled(true);
+							return;
+
+						case "mceButtonSelected":
+							b.setActive(true);
+							b.setDisabled(false);
+							return;
+					}
+				}
+			},
+
+			addCSSClass : function(e, n, b) {
+				return tinymce.DOM.addClass(e, n, b);
+			},
+
+			hasCSSClass : function(e, n) {
+				return tinymce.DOM.hasClass(e, n);
+			},
+
+			removeCSSClass : function(e, n) {
+				return tinymce.DOM.removeClass(e, n);
+			},
+
+			getCSSClasses : function() {
+				var cl = EditorManager.activeEditor.dom.getClasses(), o = [];
+
+				each(cl, function(c) {
+					o.push(c['class']);
+				});
+
+				return o;
+			},
+
+			setWindowArg : function(n, v) {
+				EditorManager.activeEditor.windowManager.params[n] = v;
+			},
+
+			getWindowArg : function(n, dv) {
+				var wm = EditorManager.activeEditor.windowManager, v;
+
+				v = wm.getParam(n);
+				if (v === '')
+					return '';
+
+				return v || wm.getFeature(n) || dv;
+			},
+
+			getParentNode : function(n, f) {
+				return this._getDOM().getParent(n, f);
+			},
+
+			selectElements : function(n, na, f) {
+				var i, a = [], nl, x;
+
+				for (x=0, na = na.split(','); x<na.length; x++)
+					for (i=0, nl = n.getElementsByTagName(na[x]); i<nl.length; i++)
+						(!f || f(nl[i])) && a.push(nl[i]);
+
+				return a;
+			},
+
+			getNodeTree : function(n, na, t, nn) {
+				return this.selectNodes(n, function(n) {
+					return (!t || n.nodeType == t) && (!nn || n.nodeName == nn);
+				}, na ? na : []);
+			},
+
+			getAttrib : function(e, n, dv) {
+				return this._getDOM().getAttrib(e, n, dv);
+			},
+
+			setAttrib : function(e, n, v) {
+				return this._getDOM().setAttrib(e, n, v);
+			},
+
+			getElementsByAttributeValue : function(n, e, a, v) {
+				var i, nl = n.getElementsByTagName(e), o = [];
+
+				for (i=0; i<nl.length; i++) {
+					if (tinyMCE.getAttrib(nl[i], a).indexOf(v) != -1)
+						o[o.length] = nl[i];
+				}
+
+				return o;
+			},
+
+			selectNodes : function(n, f, a) {
+				var i;
+
+				if (!a)
+					a = [];
+
+				if (f(n))
+					a[a.length] = n;
+
+				if (n.hasChildNodes()) {
+					for (i=0; i<n.childNodes.length; i++)
+						tinyMCE.selectNodes(n.childNodes[i], f, a);
+				}
+
+				return a;
+			},
+
+			getContent : function() {
+				return EditorManager.activeEditor.getContent();
+			},
+
+			getParentElement : function(n, na, f) {
+				if (na)
+					na = new RegExp('^(' + na.toUpperCase().replace(/,/g, '|') + ')$', 'g');
+
+				return this._getDOM().getParent(n, function(n) {
+					return n.nodeType == 1 && (!na || na.test(n.nodeName)) && (!f || f(n));
+				}, this.activeEditor.getBody());
+			},
+
+			importPluginLanguagePack : function(n) {
+				tinymce.PluginManager.requireLangPack(n);
+			},
+
+			getButtonHTML : function(cn, lang, img, c, u, v) {
+				var ed = EditorManager.activeEditor;
+
+				img = img.replace(/\{\$pluginurl\}/g, tinyMCE.pluginURL);
+				img = img.replace(/\{\$themeurl\}/g, tinyMCE.themeURL);
+				lang = lang.replace(/^lang_/g, '');
+
+				return ed.controlManager.createButton(cn, {
+					title : lang,
+					command : c,
+					ui : u,
+					value : v,
+					scope : this,
+					'class' : 'compat',
+					image : img
+				});
+			},
+
+			addSelectAccessibility : function(e, s, w) {
+				// Add event handlers 
+				if (!s._isAccessible) {
+					s.onkeydown = tinyMCE.accessibleEventHandler;
+					s.onblur = tinyMCE.accessibleEventHandler;
+					s._isAccessible = true;
+					s._win = w;
+				}
+
+				return false;
+			},
+
+			accessibleEventHandler : function(e) {
+				var elm, win = this._win;
+
+				e = tinymce.isIE ? win.event : e;
+				elm = tinymce.isIE ? e.srcElement : e.target;
+
+				// Unpiggyback onchange on blur
+				if (e.type == "blur") {
+					if (elm.oldonchange) {
+						elm.onchange = elm.oldonchange;
+						elm.oldonchange = null;
+					}
+
+					return true;
+				}
+
+				// Piggyback onchange
+				if (elm.nodeName == "SELECT" && !elm.oldonchange) {
+					elm.oldonchange = elm.onchange;
+					elm.onchange = null;
+				}
+
+				// Execute onchange and remove piggyback
+				if (e.keyCode == 13 || e.keyCode == 32) {
+					elm.onchange = elm.oldonchange;
+					elm.onchange();
+					elm.oldonchange = null;
+
+					tinyMCE.cancelEvent(e);
+					return false;
+				}
+
+				return true;
+			},
+
+			cancelEvent : function(e) {
+				return tinymce.dom.Event.cancel(e);
+			},
+
+			handleVisualAid : function(e) {
+				EditorManager.activeEditor.addVisual(e);
+			},
+
+			getAbsPosition : function(n, r) {
+				return tinymce.DOM.getPos(n, r);
+			},
+
+			cleanupEventStr : function(s) {
+				s = "" + s;
+				s = s.replace('function anonymous()\n{\n', '');
+				s = s.replace('\n}', '');
+				s = s.replace(/^return true;/gi, ''); // Remove event blocker
+
+				return s;
+			},
+
+			getVisualAidClass : function(s) {
+				// TODO: Implement
+				return s;
+			},
+
+			parseStyle : function(s) {
+				return this._getDOM().parseStyle(s);
+			},
+
+			serializeStyle : function(s) {
+				return this._getDOM().serializeStyle(s);
+			},
+
+			openWindow : function(tpl, args) {
+				var ed = EditorManager.activeEditor, o = {}, n;
+
+				// Convert name/value array to object
+				for (n in tpl)
+					o[n] = tpl[n];
+
+				tpl = o;
+
+				args = args || {};
+				tpl.url = new tinymce.util.URI(tinymce.ThemeManager.themeURLs[ed.settings.theme]).toAbsolute(tpl.file);
+				tpl.inline = tpl.inline || args.inline;
+
+				ed.windowManager.open(tpl, args);
+			},
+
+			closeWindow : function(win) {
+				EditorManager.activeEditor.windowManager.close(win);
+			},
+
+			getOuterHTML : function(e) {
+				return tinymce.DOM.getOuterHTML(e);
+			},
+
+			setOuterHTML : function(e, h, d) {
+				return tinymce.DOM.setOuterHTML(e, h, d);
+			},
+
+			hasPlugin : function(n) {
+				return tinymce.PluginManager.get(n) != null;
+			},
+
+			_setEventsEnabled : function() {
+				// Ignore it!!
+			},
+
+			addPlugin : function(pn, f) {
+				var t = this;
+
+				function PluginWrapper(ed) {
+					tinyMCE.selectedInstance = ed;
+
+					ed.onInit.add(function() {
+						t.settings = ed.settings;
+						t.settings['base_href'] = tinyMCE.documentBasePath;
+						tinyMCE.settings = t.settings;
+						tinyMCE.documentBasePath = ed.documentBasePath;
+						//ed.formElement = DOM.get(ed.id);
+
+						if (f.initInstance)
+							f.initInstance(ed);
+
+						ed.contentDocument = ed.getDoc();
+						ed.contentWindow = ed.getWin();
+						ed.undoRedo = ed.undoManager;
+						ed.startContent = ed.getContent({format : 'raw'});
+
+						tinyMCE.instances[ed.id] = ed;
+						tinyMCE.loadedFiles = [];
+					});
+
+					ed.onActivate.add(function() {
+						tinyMCE.settings = ed.settings;
+						tinyMCE.selectedInstance = ed;
+					});
+
+				/*	if (f.removeInstance) {
+						ed.onDestroy.add(function() {
+							return f.removeInstance(ed.id);
+						});
+					}*/
+
+					if (f.handleNodeChange) {
+						ed.onNodeChange.add(function(ed, cm, n) {
+							f.handleNodeChange(ed.id, n, 0, 0, false, !ed.selection.isCollapsed());
+						});
+					}
+
+					if (f.onChange) {
+						ed.onChange.add(function(ed, n) {
+							return f.onChange(ed);
+						});
+					}
+
+					if (f.cleanup) {
+						ed.onGetContent.add(function() {
+							//f.cleanup(type, content, inst);
+						});
+					}
+
+					this.getInfo = function() {
+						return f.getInfo();
+					};
+
+					this.createControl = function(n) {
+						tinyMCE.pluginURL = tinymce.baseURL + '/plugins/' + pn;
+						tinyMCE.themeURL = tinymce.baseURL + '/themes/' + tinyMCE.activeEditor.settings.theme;
+
+						if (f.getControlHTML)
+							return f.getControlHTML(n);
+
+						return null;
+					};
+
+					this.execCommand = function(cmd, ui, val) {
+						if (f.execCommand)
+							return f.execCommand(ed.id, ed.getBody(), cmd, ui, val);
+
+						return false;
+					};
+				};
+
+				tinymce.PluginManager.add(pn, PluginWrapper);
+			},
+
+			_getDOM : function() {
+				return tinyMCE.activeEditor ? tinyMCE.activeEditor.dom : tinymce.DOM;
+			},
+
+			convertRelativeToAbsoluteURL : function(b, u) {
+				return new tinymce.util.URI(b).toAbsolute(u);
+			},
+
+			convertAbsoluteURLToRelativeURL : function(b, u) {
+				return new tinymce.util.URI(b).toRelative(u);
+			}
+		});
+
+		// Extend Editor class
+		tinymce.extend(tinymce.Editor.prototype, {
+			getFocusElement : function() {
+				return this.selection.getNode();
+			},
+
+			getData : function(n) {
+				if (!this.data)
+					this.data = [];
+
+				if (!this.data[n])
+					this.data[n] = [];
+
+				return this.data[n];
+			},
+
+			hasPlugin : function(n) {
+				return this.plugins[n] != null;
+			},
+
+			getContainerWin : function() {
+				return window;
+			},
+
+			getHTML : function(raw) {
+				return this.getContent({ format : raw ? 'raw' : 'html'});
+			},
+
+			setHTML : function(h) {
+				this.setContent(h);
+			},
+
+			getSel : function() {
+				return this.selection.getSel();
+			},
+
+			getRng : function() {
+				return this.selection.getRng();
+			},
+
+			isHidden : function() {
+				var s;
+
+				if (!tinymce.isGecko)
+					return false;
+
+				s = this.getSel();
+
+				// Weird, wheres that cursor selection?
+				return (!s || !s.rangeCount || s.rangeCount == 0);
+			},
+
+			translate : function(s) {
+				var c = this.settings.language, o;
+
+				o = tinymce.EditorManager.i18n[c + '.' + s] || s.replace(/{\#([^}]+)\}/g, function(a, b) {
+					return tinymce.EditorManager.i18n[c + '.' + b] || '{#' + b + '}';
+				});
+
+				o = o.replace(/{\$lang_([^}]+)\}/g, function(a, b) {
+					return tinymce.EditorManager.i18n[c + '.' + b] || '{$lang_' + b + '}';
+				});
+
+				return o;
+			},
+
+			repaint : function() {
+				this.execCommand('mceRepaint');
+			}
+		});
+
+		// Extend selection
+		tinymce.extend(tinymce.dom.Selection.prototype, {
+			getSelectedText : function() {
+				return this.getContent({format : 'text'});
+			},
+
+			getSelectedHTML : function() {
+				return this.getContent({format : 'html'});
+			},
+
+			getFocusElement : function() {
+				return this.getNode();
+			},
+
+			selectNode : function(node, collapse, select_text_node, to_start) {
+				var t = this;
+
+				t.select(node, select_text_node || 0);
+
+				if (!is(collapse))
+					collapse = true;
+
+				if (collapse) {
+					if (!is(to_start))
+						to_start = true;
+
+					t.collapse(to_start);
+				}
+			}
+		});
+	}).call(this);
+
+	// Register plugin
+	tinymce.PluginManager.add('compat2x', tinymce.plugins.Compat2x);
+})();
+
--- a/includes/clientside/tinymce/plugins/contextmenu/css/contextmenu.css	Fri Feb 22 12:46:51 2008 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,74 +0,0 @@
-.contextMenuIEPopup {
-	padding: 0;
-	margin: 0;
-	border: 0;
-	overflow: hidden;
-}
-
-.contextMenu {
-	position: absolute;
-	cursor: default;
-	z-index: 1000;
-	border: 1px solid #D4D0C8;
-	background-color: #FFFFFF;
-}
-
-.contextMenuItem, .contextMenuItemOver {
-}
-
-.contextMenuSeparator {
-	width: 100%;
-	background-color: #D4D0C8;
-	border: 0;
-}
-
-.contextMenuImage, .contextMenuItemDisabled {
-	border: 0;
-}
-
-.contextMenuIcon {
-	background-color: #F0F0EE;
-}
-
-.contextMenuItemOver .contextMenuIcon {
-	background-color: #B6BDD2;
-}
-
-.contextMenuIcon {
-	background-color: #F0F0EE;
-}
-
-.contextMenuItemDisabled img {
-	filter:progid:DXImageTransform.Microsoft.Alpha(opacity=30);
-	-moz-opacity:0.3;
-	opacity: 0.3;
-}
-
-.contextMenuText {
-	font-family: Tahoma, Verdana, Arial, Helvetica;
-	font-size: 11px;
-	line-height: 20px;
-}
-
-.contextMenuItemDisabled {
-	color: #AAAAAA;
-}
-
-.contextMenuText a {
-	display: block;
-	line-height: 20px;
-	width: 100%;
-	text-decoration: none;
-	color: black;
-	font-weight: normal;
-	margin: 0;
-	padding: 0;
-}
-
-.contextMenuText a:hover {
-	background-color: #B6BDD2;
-	text-decoration: none !important;
-	font-weight: normal;
-	margin: 0;
-	padding: 0;
-}
--- a/includes/clientside/tinymce/plugins/contextmenu/editor_plugin.js	Fri Feb 22 12:46:51 2008 -0500
+++ b/includes/clientside/tinymce/plugins/contextmenu/editor_plugin.js	Fri Feb 22 12:51:53 2008 -0500
@@ -1,1 +1,1 @@
-if(!tinyMCE.settings['contextmenu_skip_plugin_css']){tinyMCE.loadCSS(tinyMCE.baseURL+"/plugins/contextmenu/css/contextmenu.css")}var TinyMCE_ContextMenuPlugin={_contextMenu:null,getInfo:function(){return{longname:'Context menus',author:'Moxiecode Systems AB',authorurl:'http://tinymce.moxiecode.com',infourl:'http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/contextmenu',version:tinyMCE.majorVersion+"."+tinyMCE.minorVersion}},initInstance:function(inst){if(tinyMCE.isMSIE5_0&&tinyMCE.isOpera)return;TinyMCE_ContextMenuPlugin._contextMenu=new TinyMCE_ContextMenu({commandhandler:"TinyMCE_ContextMenuPlugin._commandHandler",spacer_image:tinyMCE.baseURL+"/plugins/contextmenu/images/spacer.gif"});tinyMCE.addEvent(inst.getDoc(),"click",TinyMCE_ContextMenuPlugin._hideContextMenu);tinyMCE.addEvent(inst.getDoc(),"keypress",TinyMCE_ContextMenuPlugin._hideContextMenu);tinyMCE.addEvent(inst.getDoc(),"keydown",TinyMCE_ContextMenuPlugin._hideContextMenu);tinyMCE.addEvent(document,"click",TinyMCE_ContextMenuPlugin._hideContextMenu);tinyMCE.addEvent(document,"keypress",TinyMCE_ContextMenuPlugin._hideContextMenu);tinyMCE.addEvent(document,"keydown",TinyMCE_ContextMenuPlugin._hideContextMenu);if(tinyMCE.isGecko){tinyMCE.addEvent(inst.getDoc(),"contextmenu",function(e){TinyMCE_ContextMenuPlugin._showContextMenu(tinyMCE.isMSIE?inst.contentWindow.event:e,inst)})}else tinyMCE.addEvent(inst.getDoc(),"contextmenu",TinyMCE_ContextMenuPlugin._onContextMenu)},_onContextMenu:function(e){var elm=tinyMCE.isMSIE?e.srcElement:e.target;var targetInst,body;if((body=tinyMCE.getParentElement(elm,"body"))!=null){for(var n in tinyMCE.instances){var inst=tinyMCE.instances[n];if(!tinyMCE.isInstance(inst))continue;if(body==inst.getBody()){targetInst=inst;break}}return TinyMCE_ContextMenuPlugin._showContextMenu(tinyMCE.isMSIE?targetInst.contentWindow.event:e,targetInst)}},_showContextMenu:function(e,inst){function getAttrib(elm,name){return elm.getAttribute(name)?elm.getAttribute(name):""}var x,y,elm,contextMenu;var pos=tinyMCE.getAbsPosition(inst.iframeElement);x=tinyMCE.isMSIE?e.screenX:pos.absLeft+(e.pageX-inst.getBody().scrollLeft);y=tinyMCE.isMSIE?e.screenY:pos.absTop+(e.pageY-inst.getBody().scrollTop);elm=tinyMCE.isMSIE?e.srcElement:e.target;contextMenu=this._contextMenu;contextMenu.inst=inst;window.setTimeout(function(){var theme=tinyMCE.getParam("theme");contextMenu.clearAll();var sel=inst.selection.getSelectedText().length!=0||elm.nodeName=="IMG";contextMenu.addItem(tinyMCE.baseURL+"/themes/"+theme+"/images/cut.gif","$lang_cut_desc","Cut","",!sel);contextMenu.addItem(tinyMCE.baseURL+"/themes/"+theme+"/images/copy.gif","$lang_copy_desc","Copy","",!sel);contextMenu.addItem(tinyMCE.baseURL+"/themes/"+theme+"/images/paste.gif","$lang_paste_desc","Paste","",false);if(sel||(elm?(elm.nodeName=='A'&&tinyMCE.getAttrib(elm,'name')=='')||(elm.nodeName=='IMG'):false)){contextMenu.addSeparator();contextMenu.addItem(tinyMCE.baseURL+"/themes/advanced/images/link.gif","$lang_link_desc",inst.hasPlugin("advlink")?"mceAdvLink":"mceLink");contextMenu.addItem(tinyMCE.baseURL+"/themes/advanced/images/unlink.gif","$lang_unlink_desc","unlink","",(elm?(elm.nodeName!='A')&&(elm.nodeName!='IMG'):true))}elm=tinyMCE.getParentElement(elm,"img,table,td"+(inst.hasPlugin("advhr")?',hr':''));if(elm){switch(elm.nodeName){case"IMG":contextMenu.addSeparator();if(tinyMCE.hasPlugin('flash')&&tinyMCE.getAttrib(elm,'class').indexOf('mceItemFlash')!=-1)contextMenu.addItem(tinyMCE.baseURL+"/plugins/flash/images/flash.gif","$lang_flash_props","mceFlash");else if(tinyMCE.hasPlugin('media')&&/mceItem(Flash|ShockWave|WindowsMedia|QuickTime|RealMedia)/.test(tinyMCE.getAttrib(elm,'class')))contextMenu.addItem(tinyMCE.baseURL+"/plugins/flash/images/flash.gif","$lang_media_title","mceMedia");else contextMenu.addItem(tinyMCE.baseURL+"/themes/"+theme+"/images/image.gif","$lang_image_props_desc",inst.hasPlugin("advimage")?"mceAdvImage":"mceImage");break;case"HR":contextMenu.addSeparator();contextMenu.addItem(tinyMCE.baseURL+"/plugins/advhr/images/advhr.gif","$lang_insert_advhr_desc","mceAdvancedHr");break;case"TABLE":case"TD":if(inst.hasPlugin("table")){var colspan=(elm.nodeName=="TABLE")?"":getAttrib(elm,"colspan");var rowspan=(elm.nodeName=="TABLE")?"":getAttrib(elm,"rowspan");colspan=colspan==""?"1":colspan;rowspan=rowspan==""?"1":rowspan;contextMenu.addSeparator();contextMenu.addItem(tinyMCE.baseURL+"/themes/"+theme+"/images/cut.gif","$lang_table_cut_row_desc","mceTableCutRow");contextMenu.addItem(tinyMCE.baseURL+"/themes/"+theme+"/images/copy.gif","$lang_table_copy_row_desc","mceTableCopyRow");contextMenu.addItem(tinyMCE.baseURL+"/themes/"+theme+"/images/paste.gif","$lang_table_paste_row_before_desc","mceTablePasteRowBefore","",inst.tableRowClipboard==null);contextMenu.addItem(tinyMCE.baseURL+"/themes/"+theme+"/images/paste.gif","$lang_table_paste_row_after_desc","mceTablePasteRowAfter","",inst.tableRowClipboard==null);contextMenu.addSeparator();contextMenu.addItem(tinyMCE.baseURL+"/plugins/table/images/table.gif","$lang_table_desc","mceInsertTable","insert");contextMenu.addItem(tinyMCE.baseURL+"/plugins/table/images/table.gif","$lang_table_props_desc","mceInsertTable");contextMenu.addItem(tinyMCE.baseURL+"/plugins/table/images/table_cell_props.gif","$lang_table_cell_desc","mceTableCellProps");contextMenu.addItem(tinyMCE.baseURL+"/plugins/table/images/table_delete.gif","$lang_table_del","mceTableDelete");contextMenu.addSeparator();contextMenu.addItem(tinyMCE.baseURL+"/plugins/table/images/table_row_props.gif","$lang_table_row_desc","mceTableRowProps");contextMenu.addItem(tinyMCE.baseURL+"/plugins/table/images/table_insert_row_before.gif","$lang_table_row_before_desc","mceTableInsertRowBefore");contextMenu.addItem(tinyMCE.baseURL+"/plugins/table/images/table_insert_row_after.gif","$lang_table_row_after_desc","mceTableInsertRowAfter");contextMenu.addItem(tinyMCE.baseURL+"/plugins/table/images/table_delete_row.gif","$lang_table_delete_row_desc","mceTableDeleteRow");contextMenu.addSeparator();contextMenu.addItem(tinyMCE.baseURL+"/plugins/table/images/table_insert_col_before.gif","$lang_table_col_before_desc","mceTableInsertColBefore");contextMenu.addItem(tinyMCE.baseURL+"/plugins/table/images/table_insert_col_after.gif","$lang_table_col_after_desc","mceTableInsertColAfter");contextMenu.addItem(tinyMCE.baseURL+"/plugins/table/images/table_delete_col.gif","$lang_table_delete_col_desc","mceTableDeleteCol");contextMenu.addSeparator();contextMenu.addItem(tinyMCE.baseURL+"/plugins/table/images/table_split_cells.gif","$lang_table_split_cells_desc","mceTableSplitCells","",(colspan=="1"&&rowspan=="1"));contextMenu.addItem(tinyMCE.baseURL+"/plugins/table/images/table_merge_cells.gif","$lang_table_merge_cells_desc","mceTableMergeCells","",false)}break}}else{if(inst.hasPlugin("table")){contextMenu.addSeparator();contextMenu.addItem(tinyMCE.baseURL+"/plugins/table/images/table.gif","$lang_table_desc","mceInsertTable","insert")}}contextMenu.show(x,y)},10);tinyMCE.cancelEvent(e);return false},_hideContextMenu:function(){if(TinyMCE_ContextMenuPlugin._contextMenu)TinyMCE_ContextMenuPlugin._contextMenu.hide()},_commandHandler:function(command,value){var cm=TinyMCE_ContextMenuPlugin._contextMenu;cm.hide();var ui=false;if(command=="mceInsertTable"||command=="mceTableCellProps"||command=="mceTableRowProps"||command=="mceTableMergeCells")ui=true;if(command=="Paste")value=null;if(tinyMCE.getParam("dialog_type")=="modal"&&tinyMCE.isMSIE){window.setTimeout(function(){cm.inst.execCommand(command,ui,value)},100)}else cm.inst.execCommand(command,ui,value)}};tinyMCE.addPlugin("contextmenu",TinyMCE_ContextMenuPlugin);function TinyMCE_ContextMenu(settings){var doc,self=this;function defParam(key,def_val){settings[key]=typeof(settings[key])!="undefined"?settings[key]:def_val}this.isMSIE=(navigator.appName=="Microsoft Internet Explorer");this.contextMenuDiv=document.createElement("div");this.contextMenuDiv.className="contextMenu";this.contextMenuDiv.setAttribute("class","contextMenu");this.contextMenuDiv.style.display="none";this.contextMenuDiv.style.position='absolute';this.contextMenuDiv.style.zindex=1000;this.contextMenuDiv.style.left='0';this.contextMenuDiv.style.top='0';this.contextMenuDiv.unselectable="on";document.body.appendChild(this.contextMenuDiv);defParam("commandhandler","");defParam("spacer_image","images/spacer.gif");this.items=new Array();this.settings=settings;this.html="";if(tinyMCE.isMSIE&&!tinyMCE.isMSIE5_0&&!tinyMCE.isOpera){this.pop=window.createPopup();doc=this.pop.document;doc.open();doc.write('<html><head><link href="'+tinyMCE.baseURL+'/plugins/contextmenu/css/contextmenu.css" rel="stylesheet" type="text/css" /></head><body unselectable="yes" class="contextMenuIEPopup"></body></html>');doc.close()}};TinyMCE_ContextMenu.prototype={clearAll:function(){this.html="";this.contextMenuDiv.innerHTML=""},addSeparator:function(){this.html+='<tr class="contextMenuItem"><td class="contextMenuIcon"><img src="'+this.settings['spacer_image']+'" width="20" height="1" class="contextMenuImage" /></td><td><img class="contextMenuSeparator" width="1" height="1" src="'+this.settings['spacer_image']+'" /></td></tr>'},addItem:function(icon,title,command,value,disabled){if(title.charAt(0)=='$')title=tinyMCE.getLang(title.substring(1));var onMouseDown='';var html='';if(tinyMCE.isMSIE&&!tinyMCE.isMSIE5_0)onMouseDown='contextMenu.execCommand(\''+command+'\', \''+value+'\');return false;';else onMouseDown=this.settings['commandhandler']+'(\''+command+'\', \''+value+'\');return false;';if(icon=="")icon=this.settings['spacer_image'];if(!disabled)html+='<tr class="contextMenuItem">';else html+='<tr class="contextMenuItemDisabled">';html+='<td class="contextMenuIcon"><img src="'+icon+'" width="20" height="20" class="contextMenuImage" /></td>';html+='<td><div class="contextMenuText">';html+='<a href="javascript:void(0);" onclick="'+onMouseDown+'" onmousedown="return false;">&#160;';html+=title;html+='&#160;</a>';html+='</div></td>';html+='</tr>';this.html+=html},show:function(x,y){var vp,width,height,yo;if(this.html=="")return;var html='';html+='<a href="#"></a><table border="0" cellpadding="0" cellspacing="0">';html+=this.html;html+='</table>';this.contextMenuDiv.innerHTML=html;this.contextMenuDiv.style.display="block";width=this.contextMenuDiv.offsetWidth;height=this.contextMenuDiv.offsetHeight;this.contextMenuDiv.style.display="none";if(tinyMCE.isMSIE&&!tinyMCE.isMSIE5_0&&!tinyMCE.isOpera){this.pop.document.body.innerHTML='<div class="contextMenu">'+html+"</div>";this.pop.document.tinyMCE=tinyMCE;this.pop.document.contextMenu=this;this.pop.show(x,y,width,height)}else{vp=this.getViewPort();yo=tinyMCE.isMSIE5_0?document.body.scrollTop:self.pageYOffset;this.contextMenuDiv.style.left=(x>vp.left+vp.width-width?vp.left+vp.width-width:x)+'px';this.contextMenuDiv.style.top=(y>vp.top+vp.height-height?vp.top+vp.height-height:y)+'px';this.contextMenuDiv.style.display="block"}},getViewPort:function(){return{left:self.pageXOffset||self.document.documentElement.scrollLeft||self.document.body.scrollLeft,top:self.pageYOffset||self.document.documentElement.scrollTop||self.document.body.scrollTop,width:document.documentElement.offsetWidth||document.body.offsetWidth,height:self.innerHeight||document.documentElement.clientHeight||document.body.clientHeight}},hide:function(){if(tinyMCE.isMSIE&&!tinyMCE.isMSIE5_0&&!tinyMCE.isOpera)this.pop.hide();else this.contextMenuDiv.style.display="none"},execCommand:function(command,value){eval(this.settings['commandhandler']+"(command, value);")}};
\ No newline at end of file
+(function(){var Event=tinymce.dom.Event,each=tinymce.each,DOM=tinymce.DOM;tinymce.create('tinymce.plugins.ContextMenu',{init:function(ed){var t=this;t.editor=ed;t.onContextMenu=new tinymce.util.Dispatcher(this);ed.onContextMenu.add(function(ed,e){t._getMenu(ed).showMenu(e.clientX,e.clientY);Event.cancel(e);});function hide(){if(t._menu){t._menu.removeAll();t._menu.destroy();}};ed.onMouseDown.add(hide);ed.onKeyDown.add(hide);Event.add(document,'click',hide);},_getMenu:function(ed){var t=this,m=t._menu,se=ed.selection,col=se.isCollapsed(),el=se.getNode()||ed.getBody(),am;if(m){m.removeAll();m.destroy();}p1=DOM.getPos(ed.getContentAreaContainer());p2=DOM.getPos(ed.getContainer());m=ed.controlManager.createDropMenu('contextmenu',{offset_x:p1.x,offset_y:p1.y,constrain:1});t._menu=m;m.add({title:'advanced.cut_desc',icon:'cut',cmd:'Cut'}).setDisabled(col);m.add({title:'advanced.copy_desc',icon:'copy',cmd:'Copy'}).setDisabled(col);m.add({title:'advanced.paste_desc',icon:'paste',cmd:'Paste'});if((el.nodeName=='A'&&!ed.dom.getAttrib(el,'name'))||!col){m.addSeparator();m.add({title:'advanced.link_desc',icon:'link',cmd:ed.plugins.advlink?'mceAdvLink':'mceLink',ui:true});m.add({title:'advanced.unlink_desc',icon:'unlink',cmd:'UnLink'});}m.addSeparator();m.add({title:'advanced.image_desc',icon:'image',cmd:ed.plugins.advimage?'mceAdvImage':'mceImage',ui:true});m.addSeparator();am=m.addMenu({title:'contextmenu.align'});am.add({title:'contextmenu.left',icon:'justifyleft',cmd:'JustifyLeft'});am.add({title:'contextmenu.center',icon:'justifycenter',cmd:'JustifyCenter'});am.add({title:'contextmenu.right',icon:'justifyright',cmd:'JustifyRight'});am.add({title:'contextmenu.full',icon:'justifyfull',cmd:'JustifyFull'});t.onContextMenu.dispatch(t,m,el,col);return m;}});tinymce.PluginManager.add('contextmenu',tinymce.plugins.ContextMenu);})();
\ No newline at end of file
--- a/includes/clientside/tinymce/plugins/contextmenu/editor_plugin_src.js	Fri Feb 22 12:46:51 2008 -0500
+++ b/includes/clientside/tinymce/plugins/contextmenu/editor_plugin_src.js	Fri Feb 22 12:51:53 2008 -0500
@@ -1,357 +1,84 @@
 /**
- * $Id: editor_plugin_src.js 201 2007-02-12 15:56:56Z spocke $
+ * $Id: editor_plugin_src.js 520 2008-01-07 16:30:32Z spocke $
  *
  * @author Moxiecode
- * @copyright Copyright © 2004-2007, Moxiecode Systems AB, All rights reserved.
+ * @copyright Copyright © 2004-2008, Moxiecode Systems AB, All rights reserved.
  */
 
-/* Import plugin specific language pack */
-if (!tinyMCE.settings['contextmenu_skip_plugin_css']) {
-	tinyMCE.loadCSS(tinyMCE.baseURL + "/plugins/contextmenu/css/contextmenu.css");
-}
-
-var TinyMCE_ContextMenuPlugin = {
-	// Private fields
-	_contextMenu : null,
+(function() {
+	var Event = tinymce.dom.Event, each = tinymce.each, DOM = tinymce.DOM;
 
-	getInfo : function() {
-		return {
-			longname : 'Context menus',
-			author : 'Moxiecode Systems AB',
-			authorurl : 'http://tinymce.moxiecode.com',
-			infourl : 'http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/contextmenu',
-			version : tinyMCE.majorVersion + "." + tinyMCE.minorVersion
-		};
-	},
-
-	initInstance : function(inst) {
-		// Is not working on MSIE 5.0 or Opera no contextmenu event
-		if (tinyMCE.isMSIE5_0 && tinyMCE.isOpera)
-			return;
-
-		TinyMCE_ContextMenuPlugin._contextMenu = new TinyMCE_ContextMenu({
-			commandhandler : "TinyMCE_ContextMenuPlugin._commandHandler",
-			spacer_image : tinyMCE.baseURL + "/plugins/contextmenu/images/spacer.gif"
-		});
-
-		// Add hide event handles
-		tinyMCE.addEvent(inst.getDoc(), "click", TinyMCE_ContextMenuPlugin._hideContextMenu);
-		tinyMCE.addEvent(inst.getDoc(), "keypress", TinyMCE_ContextMenuPlugin._hideContextMenu);
-		tinyMCE.addEvent(inst.getDoc(), "keydown", TinyMCE_ContextMenuPlugin._hideContextMenu);
-		tinyMCE.addEvent(document, "click", TinyMCE_ContextMenuPlugin._hideContextMenu);
-		tinyMCE.addEvent(document, "keypress", TinyMCE_ContextMenuPlugin._hideContextMenu);
-		tinyMCE.addEvent(document, "keydown", TinyMCE_ContextMenuPlugin._hideContextMenu);
+	tinymce.create('tinymce.plugins.ContextMenu', {
+		init : function(ed) {
+			var t = this;
 
-		// Attach contextmenu event
-		if (tinyMCE.isGecko) {
-			tinyMCE.addEvent(inst.getDoc(), "contextmenu", function(e) {TinyMCE_ContextMenuPlugin._showContextMenu(tinyMCE.isMSIE ? inst.contentWindow.event : e, inst);});
-		} else
-			tinyMCE.addEvent(inst.getDoc(), "contextmenu", TinyMCE_ContextMenuPlugin._onContextMenu);
-	},
-
-	// Private plugin internal methods
-
-	_onContextMenu : function(e) {
-		var elm = tinyMCE.isMSIE ? e.srcElement : e.target;
-		var targetInst, body;
-
-		// Find instance
-		if ((body = tinyMCE.getParentElement(elm, "body")) != null) {
-			for (var n in tinyMCE.instances) {
-				var inst = tinyMCE.instances[n];
-				if (!tinyMCE.isInstance(inst))
-					continue;
+			t.editor = ed;
+			t.onContextMenu = new tinymce.util.Dispatcher(this);
 
-				if (body == inst.getBody()) {
-					targetInst = inst;
-					break;
-				}
-			}
-
-			return TinyMCE_ContextMenuPlugin._showContextMenu(tinyMCE.isMSIE ? targetInst.contentWindow.event : e, targetInst);
-		}
-	},
-
-	_showContextMenu : function(e, inst) {
-		function getAttrib(elm, name) {
-			return elm.getAttribute(name) ? elm.getAttribute(name) : "";
-		}
-
-		var x, y, elm, contextMenu;
-		var pos = tinyMCE.getAbsPosition(inst.iframeElement);
-
-		x = tinyMCE.isMSIE ? e.screenX : pos.absLeft + (e.pageX - inst.getBody().scrollLeft);
-		y = tinyMCE.isMSIE ? e.screenY : pos.absTop + (e.pageY - inst.getBody().scrollTop);
-		elm = tinyMCE.isMSIE ? e.srcElement : e.target;
-
-		contextMenu = this._contextMenu;
-		contextMenu.inst = inst;
+			ed.onContextMenu.add(function(ed, e) {
+				t._getMenu(ed).showMenu(e.clientX, e.clientY);
+				Event.cancel(e);
+			});
 
-		// Mozilla needs some time
-		window.setTimeout(function () {
-			var theme = tinyMCE.getParam("theme");
-
-			contextMenu.clearAll();
-			var sel = inst.selection.getSelectedText().length != 0 || elm.nodeName == "IMG";
-
-			// Default items
-			contextMenu.addItem(tinyMCE.baseURL + "/themes/" + theme + "/images/cut.gif", "$lang_cut_desc", "Cut", "", !sel);
-			contextMenu.addItem(tinyMCE.baseURL + "/themes/" + theme + "/images/copy.gif", "$lang_copy_desc", "Copy", "", !sel);
-			contextMenu.addItem(tinyMCE.baseURL + "/themes/" + theme + "/images/paste.gif", "$lang_paste_desc", "Paste", "", false);
-
-			if (sel || (elm ? (elm.nodeName == 'A' && tinyMCE.getAttrib(elm, 'name') == '') || (elm.nodeName == 'IMG') : false)) {
-				contextMenu.addSeparator();
-				contextMenu.addItem(tinyMCE.baseURL + "/themes/advanced/images/link.gif", "$lang_link_desc", inst.hasPlugin("advlink") ? "mceAdvLink" : "mceLink");
-				contextMenu.addItem(tinyMCE.baseURL + "/themes/advanced/images/unlink.gif", "$lang_unlink_desc", "unlink", "", (elm ? (elm.nodeName != 'A') && (elm.nodeName != 'IMG') : true));
-			}
-
-			// Get element
-			elm = tinyMCE.getParentElement(elm, "img,table,td" + (inst.hasPlugin("advhr") ? ',hr' : ''));
-			if (elm) {
-				switch (elm.nodeName) {
-					case "IMG":
-						contextMenu.addSeparator();
-
-						// If flash
-						if (tinyMCE.hasPlugin('flash') && tinyMCE.getAttrib(elm, 'class').indexOf('mceItemFlash') != -1)
-							contextMenu.addItem(tinyMCE.baseURL + "/plugins/flash/images/flash.gif", "$lang_flash_props", "mceFlash");
-						else if (tinyMCE.hasPlugin('media') && /mceItem(Flash|ShockWave|WindowsMedia|QuickTime|RealMedia)/.test(tinyMCE.getAttrib(elm, 'class')))
-							contextMenu.addItem(tinyMCE.baseURL + "/plugins/flash/images/flash.gif", "$lang_media_title", "mceMedia");
-						else
-							contextMenu.addItem(tinyMCE.baseURL + "/themes/" + theme + "/images/image.gif", "$lang_image_props_desc", inst.hasPlugin("advimage") ? "mceAdvImage" : "mceImage");
-						break;
-
-					case "HR":
-						contextMenu.addSeparator();
-						contextMenu.addItem(tinyMCE.baseURL + "/plugins/advhr/images/advhr.gif", "$lang_insert_advhr_desc", "mceAdvancedHr");
-						break;
+			function hide() {
+				if (t._menu) {
+					t._menu.removeAll();
+					t._menu.destroy();
+				}
+			};
 
-					case "TABLE":
-					case "TD":
-						// Is table plugin loaded
-						if (inst.hasPlugin("table")) {
-							var colspan = (elm.nodeName == "TABLE") ? "" : getAttrib(elm, "colspan");
-							var rowspan = (elm.nodeName == "TABLE") ? "" : getAttrib(elm, "rowspan");
-
-							colspan = colspan == "" ? "1" : colspan;
-							rowspan = rowspan == "" ? "1" : rowspan;
-
-							contextMenu.addSeparator();
-							contextMenu.addItem(tinyMCE.baseURL + "/themes/" + theme + "/images/cut.gif", "$lang_table_cut_row_desc", "mceTableCutRow");
-							contextMenu.addItem(tinyMCE.baseURL + "/themes/" + theme + "/images/copy.gif", "$lang_table_copy_row_desc", "mceTableCopyRow");
-							contextMenu.addItem(tinyMCE.baseURL + "/themes/" + theme + "/images/paste.gif", "$lang_table_paste_row_before_desc", "mceTablePasteRowBefore", "", inst.tableRowClipboard == null);
-							contextMenu.addItem(tinyMCE.baseURL + "/themes/" + theme + "/images/paste.gif", "$lang_table_paste_row_after_desc", "mceTablePasteRowAfter", "", inst.tableRowClipboard == null);
+			ed.onMouseDown.add(hide);
+			ed.onKeyDown.add(hide);
+			Event.add(document, 'click', hide);
+		},
 
-	/*						contextMenu.addItem(tinyMCE.baseURL + "/themes/" + theme + "/images/justifyleft.gif", "$lang_justifyleft_desc", "JustifyLeft", "", false);
-							contextMenu.addItem(tinyMCE.baseURL + "/themes/" + theme + "/images/justifycenter.gif", "$lang_justifycenter_desc", "JustifyCenter", "", false);
-							contextMenu.addItem(tinyMCE.baseURL + "/themes/" + theme + "/images/justifyright.gif", "$lang_justifyright_desc", "JustifyRight", "", false);
-							contextMenu.addItem(tinyMCE.baseURL + "/themes/" + theme + "/images/justifyfull.gif", "$lang_justifyfull_desc", "JustifyFull", "", false);*/
-							contextMenu.addSeparator();
-							contextMenu.addItem(tinyMCE.baseURL + "/plugins/table/images/table.gif", "$lang_table_desc", "mceInsertTable", "insert");
-							contextMenu.addItem(tinyMCE.baseURL + "/plugins/table/images/table.gif", "$lang_table_props_desc", "mceInsertTable");
-							contextMenu.addItem(tinyMCE.baseURL + "/plugins/table/images/table_cell_props.gif", "$lang_table_cell_desc", "mceTableCellProps");
-							contextMenu.addItem(tinyMCE.baseURL + "/plugins/table/images/table_delete.gif", "$lang_table_del", "mceTableDelete");
-							contextMenu.addSeparator();
-							contextMenu.addItem(tinyMCE.baseURL + "/plugins/table/images/table_row_props.gif", "$lang_table_row_desc", "mceTableRowProps");
-							contextMenu.addItem(tinyMCE.baseURL + "/plugins/table/images/table_insert_row_before.gif", "$lang_table_row_before_desc", "mceTableInsertRowBefore");
-							contextMenu.addItem(tinyMCE.baseURL + "/plugins/table/images/table_insert_row_after.gif", "$lang_table_row_after_desc", "mceTableInsertRowAfter");
-							contextMenu.addItem(tinyMCE.baseURL + "/plugins/table/images/table_delete_row.gif", "$lang_table_delete_row_desc", "mceTableDeleteRow");
-							contextMenu.addSeparator();
-							contextMenu.addItem(tinyMCE.baseURL + "/plugins/table/images/table_insert_col_before.gif", "$lang_table_col_before_desc", "mceTableInsertColBefore");
-							contextMenu.addItem(tinyMCE.baseURL + "/plugins/table/images/table_insert_col_after.gif", "$lang_table_col_after_desc", "mceTableInsertColAfter");
-							contextMenu.addItem(tinyMCE.baseURL + "/plugins/table/images/table_delete_col.gif", "$lang_table_delete_col_desc", "mceTableDeleteCol");
-							contextMenu.addSeparator();
-							contextMenu.addItem(tinyMCE.baseURL + "/plugins/table/images/table_split_cells.gif", "$lang_table_split_cells_desc", "mceTableSplitCells", "", (colspan == "1" && rowspan == "1"));
-							contextMenu.addItem(tinyMCE.baseURL + "/plugins/table/images/table_merge_cells.gif", "$lang_table_merge_cells_desc", "mceTableMergeCells", "", false);
-						}
-						break;
-				}
-			}  else {
-				// Add table specific
-				if (inst.hasPlugin("table")) {
-					contextMenu.addSeparator();
-					contextMenu.addItem(tinyMCE.baseURL + "/plugins/table/images/table.gif", "$lang_table_desc", "mceInsertTable", "insert");
-				}
+		_getMenu : function(ed) {
+			var t = this, m = t._menu, se = ed.selection, col = se.isCollapsed(), el = se.getNode() || ed.getBody(), am;
+
+			if (m) {
+				m.removeAll();
+				m.destroy();
 			}
 
-			contextMenu.show(x, y);
-		}, 10);
-
-		// Cancel default handeling
-		tinyMCE.cancelEvent(e);
-		return false;
-	},
-
-	_hideContextMenu : function() {
-		if (TinyMCE_ContextMenuPlugin._contextMenu)
-			TinyMCE_ContextMenuPlugin._contextMenu.hide();
-	},
-
-	_commandHandler : function(command, value) {
-		var cm = TinyMCE_ContextMenuPlugin._contextMenu;
-
-		cm.hide();
-
-		// UI must be true on these
-		var ui = false;
-		if (command == "mceInsertTable" || command == "mceTableCellProps" || command == "mceTableRowProps" || command == "mceTableMergeCells")
-			ui = true;
-
-		if (command == "Paste")
-			value = null;
-
-		if (tinyMCE.getParam("dialog_type") == "modal" && tinyMCE.isMSIE) {
-			// Cell properties will generate access denied error is this isn't done?!
-			window.setTimeout(function() {
-				cm.inst.execCommand(command, ui, value);
-			}, 100);
-		} else
-			cm.inst.execCommand(command, ui, value);
-	}
-};
-
-tinyMCE.addPlugin("contextmenu", TinyMCE_ContextMenuPlugin);
-
-// Context menu class
-
-function TinyMCE_ContextMenu(settings) {
-	var doc, self = this;
+			p1 = DOM.getPos(ed.getContentAreaContainer());
+			p2 = DOM.getPos(ed.getContainer());
 
-	// Default value function
-	function defParam(key, def_val) {
-		settings[key] = typeof(settings[key]) != "undefined" ? settings[key] : def_val;
-	}
-
-	this.isMSIE = (navigator.appName == "Microsoft Internet Explorer");
-
-	// Setup contextmenu div
-	this.contextMenuDiv = document.createElement("div");
-	this.contextMenuDiv.className = "contextMenu";
-	this.contextMenuDiv.setAttribute("class", "contextMenu");
-	this.contextMenuDiv.style.display = "none";
-	this.contextMenuDiv.style.position = 'absolute';
-	this.contextMenuDiv.style.zindex = 1000;
-	this.contextMenuDiv.style.left = '0';
-	this.contextMenuDiv.style.top = '0';
-	this.contextMenuDiv.unselectable = "on";
-
-	document.body.appendChild(this.contextMenuDiv);
-
-	// Setup default values
-	defParam("commandhandler", "");
-	defParam("spacer_image", "images/spacer.gif");
+			m = ed.controlManager.createDropMenu('contextmenu', {
+				offset_x : p1.x,
+				offset_y : p1.y,
+/*				vp_offset_x : p2.x,
+				vp_offset_y : p2.y,*/
+				constrain : 1
+			});
 
-	this.items = new Array();
-	this.settings = settings;
-	this.html = "";
+			t._menu = m;
 
-	// IE Popup
-	if (tinyMCE.isMSIE && !tinyMCE.isMSIE5_0 && !tinyMCE.isOpera) {
-		this.pop = window.createPopup();
-		doc = this.pop.document;
-		doc.open();
-		doc.write('<html><head><link href="' + tinyMCE.baseURL + '/plugins/contextmenu/css/contextmenu.css" rel="stylesheet" type="text/css" /></head><body unselectable="yes" class="contextMenuIEPopup"></body></html>');
-		doc.close();
-	}
-};
-
-TinyMCE_ContextMenu.prototype = {
-	clearAll : function() {
-		this.html = "";
-		this.contextMenuDiv.innerHTML = "";
-	},
-
-	addSeparator : function() {
-		this.html += '<tr class="contextMenuItem"><td class="contextMenuIcon"><img src="' + this.settings['spacer_image'] + '" width="20" height="1" class="contextMenuImage" /></td><td><img class="contextMenuSeparator" width="1" height="1" src="' + this.settings['spacer_image'] + '" /></td></tr>';
-	},
+			m.add({title : 'advanced.cut_desc', icon : 'cut', cmd : 'Cut'}).setDisabled(col);
+			m.add({title : 'advanced.copy_desc', icon : 'copy', cmd : 'Copy'}).setDisabled(col);
+			m.add({title : 'advanced.paste_desc', icon : 'paste', cmd : 'Paste'});
 
-	addItem : function(icon, title, command, value, disabled) {
-		if (title.charAt(0) == '$')
-			title = tinyMCE.getLang(title.substring(1));
-
-		var onMouseDown = '';
-		var html = '';
-
-		if (tinyMCE.isMSIE && !tinyMCE.isMSIE5_0)
-			onMouseDown = 'contextMenu.execCommand(\'' + command + '\', \'' + value + '\');return false;';
-		else
-			onMouseDown = this.settings['commandhandler'] + '(\'' + command + '\', \'' + value + '\');return false;';
-
-		if (icon == "")
-			icon = this.settings['spacer_image'];
-
-		if (!disabled)
-			html += '<tr class="contextMenuItem">';
-		else
-			html += '<tr class="contextMenuItemDisabled">';
+			if ((el.nodeName == 'A' && !ed.dom.getAttrib(el, 'name')) || !col) {
+				m.addSeparator();
+				m.add({title : 'advanced.link_desc', icon : 'link', cmd : ed.plugins.advlink ? 'mceAdvLink' : 'mceLink', ui : true});
+				m.add({title : 'advanced.unlink_desc', icon : 'unlink', cmd : 'UnLink'});
+			}
 
-		html += '<td class="contextMenuIcon"><img src="' + icon + '" width="20" height="20" class="contextMenuImage" /></td>';
-		html += '<td><div class="contextMenuText">';
-		html += '<a href="javascript:void(0);" onclick="' + onMouseDown + '" onmousedown="return false;">&#160;';
-
-		// Add text
-		html += title;
-
-		html += '&#160;</a>';
-		html += '</div></td>';
-		html += '</tr>';
-
-		// Add to main
-		this.html += html;
-	},
-
-	show : function(x, y) {
-		var vp, width, height, yo;
-
-		if (this.html == "")
-			return;
-
-		var html = '';
+			m.addSeparator();
+			m.add({title : 'advanced.image_desc', icon : 'image', cmd : ed.plugins.advimage ? 'mceAdvImage' : 'mceImage', ui : true});
 
-		html += '<a href="#"></a><table border="0" cellpadding="0" cellspacing="0">';
-		html += this.html;
-		html += '</table>';
-
-		this.contextMenuDiv.innerHTML = html;
-
-		// Get dimensions
-		this.contextMenuDiv.style.display = "block";
-		width = this.contextMenuDiv.offsetWidth;
-		height = this.contextMenuDiv.offsetHeight;
-		this.contextMenuDiv.style.display = "none";
+			m.addSeparator();
+			am = m.addMenu({title : 'contextmenu.align'});
+			am.add({title : 'contextmenu.left', icon : 'justifyleft', cmd : 'JustifyLeft'});
+			am.add({title : 'contextmenu.center', icon : 'justifycenter', cmd : 'JustifyCenter'});
+			am.add({title : 'contextmenu.right', icon : 'justifyright', cmd : 'JustifyRight'});
+			am.add({title : 'contextmenu.full', icon : 'justifyfull', cmd : 'JustifyFull'});
 
-		if (tinyMCE.isMSIE && !tinyMCE.isMSIE5_0 && !tinyMCE.isOpera) {
-			// Setup popup and show
-			this.pop.document.body.innerHTML = '<div class="contextMenu">' + html + "</div>";
-			this.pop.document.tinyMCE = tinyMCE;
-			this.pop.document.contextMenu = this;
-			this.pop.show(x, y, width, height);
-		} else {
-			vp = this.getViewPort();
-			yo = tinyMCE.isMSIE5_0 ? document.body.scrollTop : self.pageYOffset;
-			this.contextMenuDiv.style.left = (x > vp.left + vp.width - width ? vp.left + vp.width - width : x) + 'px';
-			this.contextMenuDiv.style.top = (y > vp.top + vp.height - height ? vp.top + vp.height - height : y) + 'px';
-			this.contextMenuDiv.style.display = "block";
-		}
-	},
+			t.onContextMenu.dispatch(t, m, el, col);
 
-	getViewPort : function() {
-		return {
-			left : self.pageXOffset || self.document.documentElement.scrollLeft || self.document.body.scrollLeft,
-			top: self.pageYOffset || self.document.documentElement.scrollTop || self.document.body.scrollTop,
-			width : document.documentElement.offsetWidth || document.body.offsetWidth,
-			height : self.innerHeight || document.documentElement.clientHeight || document.body.clientHeight
-		};
-	},
+			return m;
+		}
+	});
 
-	hide : function() {
-		if (tinyMCE.isMSIE && !tinyMCE.isMSIE5_0 && !tinyMCE.isOpera)
-			this.pop.hide();
-		else
-			this.contextMenuDiv.style.display = "none";
-	},
-
-	execCommand : function(command, value) {
-		eval(this.settings['commandhandler'] + "(command, value);");
-	}
-};
+	// Register plugin
+	tinymce.PluginManager.add('contextmenu', tinymce.plugins.ContextMenu);
+})();
\ No newline at end of file
Binary file includes/clientside/tinymce/plugins/contextmenu/images/spacer.gif has changed
--- a/includes/clientside/tinymce/plugins/contextmenu/readme.txt	Fri Feb 22 12:46:51 2008 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1 +0,0 @@
-Check the TinyMCE documentation for details on this plugin.
--- a/includes/clientside/tinymce/plugins/devkit/css/devkit.css	Fri Feb 22 12:46:51 2008 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,117 +0,0 @@
-body {
-	overflow: hidden;
-}
-
-h1 {
-	font-size: 14px;
-	margin: 0 0 10px 0;
-}
-
-h2 {
-	font-size: 12px;
-	margin: 3px 0 3px 0;
-}
-
-h3 {
-	font-size: 11px;
-	margin: 3px 0 3px 0;
-}
-
-#log {
-	font-family: Verdana;
-	border: 1px solid gray;
-	width: 100%; height: 240px;
-	overflow: scroll;
-	white-space: nowrap;
-}
-
-#log span {
-	display: block;
-}
-
-#log span.msg {
-	float: left;
-}
-
-#log span.time {
-	float: left;
-}
-
-#log br {
-	clear: both;
-}
-
-#logfilter {
-	width: 350px;
-}
-
-#logenabled {
-	border: 0;
-}
-
-#settings_panel span, #info_panel span, #content_panel span, #command_states_panel span, #undo_redo_panel span {
-	display: block;
-	margin: 5px 0 5px 0;
-}
-
-div.data {
-	width: 100%; height: 240px;
-	overflow: scroll;
-	border: 1px solid gray;
-}
-
-#misc_panel div.data {
-	height: 270px;
-}
-
-.data input {
-	width: 265px;
-	border: 0;
-}
-
-.data h2 {
-	margin-left: 5px;
-}
-
-.data h3 {
-	margin-left: 7px;
-}
-
-.data div {
-	margin-left: 7px;
-}
-
-.data table {
-	margin: 0 0 15px 15px;
-}
-
-.data p {
-	margin: 0; padding: 0;
-	margin-top: 5px;
-	margin-left: 5px;
-}
-
-table, td {
-	border: 1px solid gray;
-	border-collapse: collapse;
-}
-
-#flip {
-	position: absolute;
-	left: 295; top: 384px;
-}
-
-.bspec {
-	color: gray;
-}
-
-.dep {
-	color: #880000;
-}
-
-.col1 {
-	width: 265px;
-}
-
-div.undodata {
-}
--- a/includes/clientside/tinymce/plugins/devkit/css/devkit_ui.css	Fri Feb 22 12:46:51 2008 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,15 +0,0 @@
-#devkit {
-	position: absolute;
-	top: -385px; right: 0;
-	width: 640px; height: 390px;
-	border: 1px solid black;
-	z-index: 10000;
-}
-
-.devkitup {
-	top: -385px !important;
-}
-
-.devkitdown {
-	top: 0 !important;
-}
--- a/includes/clientside/tinymce/plugins/devkit/devkit.htm	Fri Feb 22 12:46:51 2008 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,140 +0,0 @@
-<html xmlns="http://www.w3.org/1999/xhtml">
-<head>
-	<title>{$lang_devkit_title}</title>
-	<script language="javascript" type="text/javascript" src="../../tiny_mce_popup.js"></script>
-	<script language="javascript" type="text/javascript" src="../../utils/mctabs.js"></script>
-	<script language="javascript" type="text/javascript" src="../../utils/form_utils.js"></script>
-	<script language="javascript" type="text/javascript" src="jscripts/devkit.js"></script>
-	<script language="javascript" type="text/javascript" src="jscripts/diff.js"></script>
-	<link href="css/devkit.css" rel="stylesheet" type="text/css" />
-	<base target="_self" />
-</head>
-<body id="devkit" onload="tinyMCEPopup.executeOnLoad('init();');" style="display: none">
-    <form action="#">
-		<h1>{$lang_devkit_title}</h1>
-
-		<div class="tabs">
-			<ul>
-				<li id="log_tab" class="current"><span><a href="javascript:mcTabs.displayTab('log_tab','log_panel');" onmousedown="return false;">{$lang_devkit_log_tab}</a></span></li>
-				<li id="info_tab"><span><a href="javascript:mcTabs.displayTab('info_tab','info_panel');" onmousedown="return false;">{$lang_devkit_info_tab}</a></span></li>
-				<li id="settings_tab"><span><a href="javascript:mcTabs.displayTab('settings_tab','settings_panel');" onmousedown="return false;">{$lang_devkit_settings_tab}</a></span></li>
-				<li id="content_tab"><span><a href="javascript:mcTabs.displayTab('content_tab','content_panel');" onmousedown="return false;">{$lang_devkit_content_tab}</a></span></li>
-				<!-- <li id="command_states_tab"><span><a href="javascript:mcTabs.displayTab('command_states_tab','command_states_panel');" onmousedown="return false;">{$lang_devkit_command_states_tab}</a></span></li> -->
-				<li id="undo_redo_tab"><span><a href="javascript:mcTabs.displayTab('undo_redo_tab','undo_redo_panel');" onmousedown="return false;">{$lang_devkit_undo_redo_tab}</a></span></li>
-				<li id="misc_tab"><span><a href="javascript:mcTabs.displayTab('misc_tab','misc_panel');" onmousedown="return false;">{$lang_devkit_misc_tab}</a></span></li>
-			</ul>
-		</div>
-
-		<div class="panel_wrapper">
-			<div id="log_panel" class="panel current">
-				<fieldset>
-					<legend>{$lang_devkit_log_tab}</legend>
-
-					<div style="float: left">
-						<label>{$lang_devkit_filter} </label><input type="text" id="logfilter" name="logfilter" value="" onchange="changeFilter(this.value);" />
-					</div>
-
-					<div style="float: left">
-						<input type="checkbox" id="logenabled" name="logenabled" value="true" checked="checked" onclick="toggleLog(this.checked);" />
-					</div>
-
-					<div style="float: right">
-						<a href="javascript:clearLog();">[{$lang_devkit_clear_log}]</a>
-					</div>
-
-					<br style="clear: both" />
-
-					<div id="log">
-					</div>
-
-					<input type="checkbox" id="debug_events" name="debug_events" class="checkbox" onclick="toggleDebugEvents(this.checked);" /><label for="debug_events" onclick="toggleDebugEvents(this.form.debug_events.checked);">{$lang_devkit_debug_events}</label>
-				</fieldset>
-			</div>
-
-			<div id="info_panel" class="panel">
-				<fieldset>
-					<legend>{$lang_devkit_info_tab}</legend>
-
-					<span><a href="javascript:renderInfo();">[{$lang_devkit_refresh}]</a></span>
-
-					<div id="info" class="data">
-						<p>{$lang_devkit_info_help}</p>
-					</div>
-				</fieldset>
-			</div>
-
-			<div id="settings_panel" class="panel">
-			<fieldset>
-					<legend>{$lang_devkit_settings_tab}</legend>
-
-					<span><a href="javascript:renderSettings();">[{$lang_devkit_refresh}]</a></span>
-
-					<div id="settings" class="data">
-						<p>{$lang_devkit_settings_help}</p>
-					</div>
-				</fieldset>
-			</div>
-
-			<div id="content_panel" class="panel">
-			<fieldset>
-					<legend>{$lang_devkit_content_tab}</legend>
-
-					<span><a href="javascript:renderContent();">[{$lang_devkit_refresh}]</a></span>
-
-					<div id="content" class="data">
-						<p>{$lang_devkit_content_help}</p>
-					</div>
-				</fieldset>
-			</div>
-
-			<div id="command_states_panel" class="panel">
-			<fieldset>
-					<legend>{$lang_devkit_command_states_tab}</legend>
-
-					<span><a href="javascript:renderCommandStates();">[{$lang_devkit_refresh}]</a></span>
-
-					<div id="command_states" class="data">
-						<p>{$lang_devkit_command_states_help}</p>
-					</div>
-				</fieldset>
-			</div>
-
-			<div id="undo_redo_panel" class="panel">
-				<fieldset>
-					<legend>{$lang_devkit_undo_redo_tab}</legend>
-
-					<span><a href="javascript:renderUndoRedo();">[{$lang_devkit_refresh}]</a></span>
-
-					<div id="undo_redo" class="data">
-						<p>{$lang_devkit_undo_redo_help}</p>
-					</div>
-
-					<input type="checkbox" id="undo_diff" name="undo_diff" class="checkbox" /><label for="undo_diff">{$lang_devkit_undo_diff}</label>
-				</fieldset>
-			</div>
-
-			<div id="misc_panel" class="panel">
-				<fieldset>
-					<legend>{$lang_devkit_misc_tab}</legend>
-
-					<div class="data">
-						<p>{$lang_devkit_misc_help}</p>
-						<hr />
-						<p>Selection: <a href="#" onmousedown="return storeSelection();">[Store selection]</a> <a href="#" onmousedown="return restoreSelection();">[Restore selection]</a></p>
-						<hr />
-						<div><strong>Insert custom HTML content</strong></div>
-						<div><textarea id="htmlcont" name="htmlcont" style="width: 90%" rows="5"></textarea></div>
-						<div><a href="#" onclick="return tinyMCE.execCommand('mceInsertContent',false,document.getElementById('htmlcont').value);">[Insert content]</a></div>
-						<hr />
-						<div><strong>Eval JS:</strong></div>
-						<div><textarea id="jscont" name="jscont" style="width: 90%" rows="5">tinyMCE.execCommand('Bold',false,null);</textarea></div>
-						<div><a href="#" onclick="return parent.window.eval(document.getElementById('jscont').value);">[Evaluate]</a></div>
-					</div>
-				</fieldset>
-			</div>
-		</div>
-    </form>
-
-	<div id="flip"><a href="javascript:toggleFlip();" onmousedown="return false;"><img id="flipbtn" src="images/flip_down.gif" border="0" /></a></div>
-</body>
-</html>
--- a/includes/clientside/tinymce/plugins/devkit/editor_plugin.js	Fri Feb 22 12:46:51 2008 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1 +0,0 @@
-tinyMCE.importPluginLanguagePack('devkit');var TinyMCE_DevKitPlugin={_logFilter:'\\[(importCSS|execCommand|execInstanceCommand|debug)\\]',_logPadding:'',_startTime:null,_benchMark:false,_winLoaded:false,_isDebugEvents:false,getInfo:function(){return{longname:'Development Kit',author:'Moxiecode Systems AB',authorurl:'http://tinymce.moxiecode.com',infourl:'http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/devkit',version:tinyMCE.majorVersion+"."+tinyMCE.minorVersion}},initInstance:function(inst){this._setup()},_setup:function(){if(this._loaded)return;this._loaded=true;document.___TinyMCE=tinyMCE;this._logFilter=tinyMCE.getParam('devkit_log_filter',this._logFilter);this._benchMark=tinyMCE.getParam('devkit_bench_mark',false);var ifr=document.createElement('iframe');ifr.setAttribute("id","devkit");ifr.setAttribute("frameBorder","0");ifr.setAttribute("src",tinyMCE.baseURL+'/plugins/devkit/devkit.htm');document.body.appendChild(ifr);tinyMCE.importCSS(document,tinyMCE.baseURL+'/plugins/devkit/css/devkit_ui.css')},_start:function(){this._logPadding+='\u00a0';return new Date().getTime()},_end:function(st){if(this._logPadding.length>0)this._logPadding=this._logPadding.substring(0,this._logPadding.length-1);if(this._benchMark)this._log("benchmark","Execution time: "+(new Date().getTime()-st))},_log:function(t){var m,a,i,e=document.getElementById('devkit'),now=new Date().getTime();if(!this._startTime)this._startTime=now;m=(this._logPadding.length>1?this._logPadding:'')+'['+(now-this._startTime)+'] ['+t+'] ';a=this._log.arguments;for(i=1;i<a.length;i++){if(typeof(a[i])=='undefined')continue;if(i>1)m+=', ';m+=a[i]}if(!new RegExp(this._logFilter,'gi').test(m)){if(this._logPadding.length>0)this._logPadding=this._logPadding.substring(0,this._logPadding.length-1);return}if(!this._winLoaded)tinyMCE.log[tinyMCE.log.length]=m;else e.contentWindow.debug(m)},_debugEvents:function(s){var i,ld,inst,n,ev=['CheckboxStateChange','DOMAttrModified','DOMMenuItemActive','DOMMenuItemInactive','DOMMouseScroll','DOMNodeInserted','DOMNodeRemoved','RadioStateChange','blur','broadcast','change','click','close','command','commandupdate','contextmenu','dblclick','dragdrop','dragenter','dragexit','draggesture','dragover','focus','input','keydown','keypress','keyup','load','mousedown','mouseout','mouseover','mouseup','overflow','overflowchanged','popuphidden','popuphiding','popupshowing','popupshown','select','syncfrompreference','synctopreference','underflow','unload','abort','activate','afterprint','afterupdate','beforeactivate','beforecopy','beforecut','beforedeactivate','beforeeditfocus','beforepaste','beforeprint','beforeunload','beforeupdate','bounce','cellchange','controlselect','copy','cut','dataavailable','datasetchanged','datasetcomplete','deactivate','dragend','dragleave','dragstart','drop','error','errorupdate','filterchange','finish','focusin','focusout','help','layoutcomplete','losecapture','mouseenter','mouseleave','mousewheel','move','moveend','movestart','paste','propertychange','readystatechange','reset','resize','resizeend','resizestart','rowenter','rowexit','rowsdelete','rowsinserted','scroll','selectionchange','selectstart','start','stop','submit'];if(TinyMCE_DevKitPlugin._isDebugEvents==s)return;TinyMCE_DevKitPlugin._isDebugEvents=s;for(n in tinyMCE.instances){inst=tinyMCE.instances[n];if(!tinyMCE.isInstance(inst)||inst.getDoc()==ld)continue;ld=inst.getDoc();for(i=0;i<ev.length;i++){if(s)tinyMCE.addEvent(ld,ev[i],TinyMCE_DevKitPlugin._debugEvent);else tinyMCE.removeEvent(ld,ev[i],TinyMCE_DevKitPlugin._debugEvent)}}},_debugEvent:function(e){var t;e=e?e:tinyMCE.selectedInstance.getWin().event;t=e.srcElement?e.srcElement:e.target;tinyMCE.debug(e.type,t?t.nodeName:'')},_serialize:function(o){var i,v,s=TinyMCE_DevKitPlugin._serialize;if(o==null)return'null';switch(typeof o){case'string':v='\bb\tt\nn\ff\rr\""\'\'\\\\';return'"'+o.replace(new RegExp('([\u0080-\uFFFF\\x00-\\x1f\\"])','g'),function(a,b){i=v.indexOf(b);if(i+1)return'\\'+v.charAt(i+1);a=b.charCodeAt().toString(16);return'\\u'+'0000'.substring(a.length)+a})+'"';case'object':if(o instanceof Array){for(i=0,v='[';i<o.length;i++)v+=(i>0?',':'')+s(o[i]);return v+']'}v='{';for(i in o)v+=typeof o[i]!='function'?(v.length>1?',"':'"')+i+'":'+s(o[i]):'';return v+'}'}return''+o}};tinyMCE.__debug=tinyMCE.debug;tinyMCE.debug=function(){var a,i,m='',now=new Date().getTime(),start=TinyMCE_DevKitPlugin._startTime;if(!start)TinyMCE_DevKitPlugin._startTime=start=now;a=this.debug.arguments;for(i=0;i<a.length;i++){if(typeof(a[i])=='undefined')continue;if(i>0)m+=', ';m+=a[i]}TinyMCE_DevKitPlugin._log('debug',m)};tinyMCE.dump=function(o){tinyMCE.debug(TinyMCE_DevKitPlugin._serialize(o))};tinyMCE.sleep=function(t){var s=new Date().getTime(),b;while(new Date().getTime()-s<t)b=1};tinyMCE.__execCommand=tinyMCE.execCommand;tinyMCE.execCommand=function(command,user_interface,value){var r,st,dk=TinyMCE_DevKitPlugin;st=dk._start();dk._log('execCommand',command,user_interface,value);r=tinyMCE.__execCommand(command,user_interface,value);dk._end(st);return r};tinyMCE.__execInstanceCommand=tinyMCE.execInstanceCommand;tinyMCE.execInstanceCommand=function(editor_id,command,user_interface,value,focus){var r,st,dk=TinyMCE_DevKitPlugin;st=dk._start();dk._log('execInstanceCommand',editor_id,command,user_interface,value);r=tinyMCE.__execInstanceCommand(editor_id,command,user_interface,value);dk._end(st);return r};TinyMCE_Engine.prototype.__handleEvent=TinyMCE_Engine.prototype.handleEvent;TinyMCE_Engine.prototype.handleEvent=function(e){var r,st,dk=TinyMCE_DevKitPlugin;st=dk._start();dk._log('handleEvent',e.type);r=tinyMCE.__handleEvent(e);dk._end(st);return r};tinyMCE.__importCSS=tinyMCE.importCSS;tinyMCE.importCSS=function(doc,css){var r,st,dk=TinyMCE_DevKitPlugin;st=dk._start();dk._log('importCSS',doc,css);r=tinyMCE.__importCSS(doc,css);dk._end(st);return r};tinyMCE.__triggerNodeChange=tinyMCE.triggerNodeChange;tinyMCE.triggerNodeChange=function(focus,setup_content){var r,st,dk=TinyMCE_DevKitPlugin;st=dk._start();dk._log('triggerNodeChange',focus,setup_content);r=tinyMCE.__triggerNodeChange(focus,setup_content);dk._end(st);return r};tinyMCE.__dispatchCallback=tinyMCE.dispatchCallback;tinyMCE.dispatchCallback=function(i,p,n){var r,st,dk=TinyMCE_DevKitPlugin;st=dk._start();dk._log('dispatchCallback',i,p,n);r=tinyMCE.__dispatchCallback(i,p,n);dk._end(st);return r};tinyMCE.__executeCallback=tinyMCE.executeCallback;tinyMCE.executeCallback=function(i,p,n){var r,st,dk=TinyMCE_DevKitPlugin;st=dk._start();dk._log('executeCallback',i,p,n);r=tinyMCE.__executeCallback(i,p,n);dk._end(st);return r};tinyMCE.__execCommandCallback=tinyMCE.execCommandCallback;tinyMCE.execCommandCallback=function(i,p,n){var r,st,dk=TinyMCE_DevKitPlugin;st=dk._start();dk._log('execCommandCallback',i,p,n);r=tinyMCE.__execCommandCallback(i,p,n);dk._end(st);return r};tinyMCE.addPlugin("devkit",TinyMCE_DevKitPlugin);
\ No newline at end of file
--- a/includes/clientside/tinymce/plugins/devkit/editor_plugin_src.js	Fri Feb 22 12:46:51 2008 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,325 +0,0 @@
-/**
- * $Id: editor_plugin_src.js 42 2006-08-08 14:32:24Z spocke $
- *
- * @author Moxiecode
- * @copyright Copyright © 2004-2007, Moxiecode Systems AB, All rights reserved.
- */
-
-tinyMCE.importPluginLanguagePack('devkit');
-
-var TinyMCE_DevKitPlugin = {
-	_logFilter : '\\[(importCSS|execCommand|execInstanceCommand|debug)\\]',
-	_logPadding : '',
-	_startTime : null,
-	_benchMark : false,
-	_winLoaded : false,
-	_isDebugEvents : false,
-
-	getInfo : function() {
-		return {
-			longname : 'Development Kit',
-			author : 'Moxiecode Systems AB',
-			authorurl : 'http://tinymce.moxiecode.com',
-			infourl : 'http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/devkit',
-			version : tinyMCE.majorVersion + "." + tinyMCE.minorVersion
-		};
-	},
-
-	initInstance : function(inst) {
-		this._setup();
-	},
-
-	_setup : function() {
-		if (this._loaded)
-			return;
-
-		this._loaded = true;
-
-		// Register a document reference for more easy access in the FF DOM inspector
-		document.___TinyMCE = tinyMCE;
-
-		// Setup devkit by settings
-		this._logFilter = tinyMCE.getParam('devkit_log_filter', this._logFilter);
-		this._benchMark = tinyMCE.getParam('devkit_bench_mark', false);
-
-		var ifr = document.createElement('iframe');
-
-		ifr.setAttribute("id", "devkit");
-		ifr.setAttribute("frameBorder", "0");
-		ifr.setAttribute("src", tinyMCE.baseURL + '/plugins/devkit/devkit.htm');
-
-		document.body.appendChild(ifr);
-
-		// Workaround for strange IE reload bug
-		//if (tinyMCE.isRealIE)
-		//	document.getElementById('devkit').outerHTML = document.getElementById('devkit').outerHTML;
-
-		tinyMCE.importCSS(document, tinyMCE.baseURL + '/plugins/devkit/css/devkit_ui.css');
-	},
-
-	_start : function() {
-		this._logPadding += '\u00a0';
-
-		return new Date().getTime();
-	},
-
-	_end : function(st) {
-		if (this._logPadding.length > 0)
-			this._logPadding = this._logPadding.substring(0, this._logPadding.length - 1);
-
-		if (this._benchMark)
-			this._log("benchmark", "Execution time: " + (new Date().getTime() - st));
-	},
-
-	_log : function(t) {
-		var m, a, i, e = document.getElementById('devkit'), now = new Date().getTime();
-
-		if (!this._startTime)
-			this._startTime = now;
-
-		m = (this._logPadding.length > 1 ? this._logPadding : '') + '[' + (now - this._startTime) + '] [' + t + '] ';
-
-		a = this._log.arguments;
-		for (i=1; i<a.length; i++) {
-			if (typeof(a[i]) == 'undefined')
-				continue;
-
-			if (i > 1)
-				m += ', ';
-
-			m += a[i];
-		}
-
-		if (!new RegExp(this._logFilter, 'gi').test(m)) {
-			if (this._logPadding.length > 0)
-				this._logPadding = this._logPadding.substring(0, this._logPadding.length - 1);
-
-			return;
-		}
-
-		if (!this._winLoaded)
-			tinyMCE.log[tinyMCE.log.length] = m;
-		else
-			e.contentWindow.debug(m);
-	},
-
-	_debugEvents : function(s) {
-		var i, ld, inst, n, ev = ['CheckboxStateChange','DOMAttrModified','DOMMenuItemActive',
-				'DOMMenuItemInactive','DOMMouseScroll','DOMNodeInserted','DOMNodeRemoved',
-				'RadioStateChange','blur','broadcast','change','click','close','command',
-				'commandupdate','contextmenu','dblclick','dragdrop','dragenter','dragexit',
-				'draggesture','dragover','focus','input','keydown','keypress','keyup','load',
-				'mousedown','mouseout','mouseover','mouseup','overflow','overflowchanged','popuphidden',
-				'popuphiding','popupshowing','popupshown','select','syncfrompreference','synctopreference',
-				'underflow','unload','abort','activate','afterprint','afterupdate','beforeactivate',
-				'beforecopy','beforecut','beforedeactivate','beforeeditfocus','beforepaste','beforeprint',
-				'beforeunload','beforeupdate','bounce','cellchange','controlselect','copy','cut',
-				'dataavailable','datasetchanged','datasetcomplete','deactivate','dragend','dragleave',
-				'dragstart','drop','error','errorupdate','filterchange','finish','focusin','focusout',
-				'help','layoutcomplete','losecapture','mouseenter','mouseleave','mousewheel',
-				'move','moveend','movestart','paste','propertychange','readystatechange','reset','resize',
-				'resizeend','resizestart','rowenter','rowexit','rowsdelete','rowsinserted','scroll',
-				'selectionchange','selectstart','start','stop','submit'];
-		// mousemove
-
-		if (TinyMCE_DevKitPlugin._isDebugEvents == s)
-			return;
-
-		TinyMCE_DevKitPlugin._isDebugEvents = s;
-
-		for (n in tinyMCE.instances) {
-			inst = tinyMCE.instances[n];
-
-			if (!tinyMCE.isInstance(inst) || inst.getDoc() == ld)
-				continue;
-
-			ld = inst.getDoc();
-
-			for (i=0; i<ev.length; i++) {
-				if (s)
-					tinyMCE.addEvent(ld, ev[i], TinyMCE_DevKitPlugin._debugEvent);
-				else
-					tinyMCE.removeEvent(ld, ev[i], TinyMCE_DevKitPlugin._debugEvent);
-			}
-		}
-	},
-
-	_debugEvent : function(e) {
-		var t;
-
-		e = e ? e : tinyMCE.selectedInstance.getWin().event;
-		t = e.srcElement ? e.srcElement : e.target;
-
-		tinyMCE.debug(e.type, t ? t.nodeName : '');
-	},
-
-	_serialize : function(o) {
-		var i, v, s = TinyMCE_DevKitPlugin._serialize;
-
-		if (o == null)
-			return 'null';
-
-		switch (typeof o) {
-			case 'string':
-				v = '\bb\tt\nn\ff\rr\""\'\'\\\\';
-
-				return '"' + o.replace(new RegExp('([\u0080-\uFFFF\\x00-\\x1f\\"])', 'g'), function(a, b) {
-					i = v.indexOf(b);
-
-					if (i+1)
-						return '\\' + v.charAt(i + 1);
-
-					a = b.charCodeAt().toString(16);
-
-					return '\\u' + '0000'.substring(a.length) + a;
-				}) + '"';
-
-			case 'object':
-				if (o instanceof Array) {
-					for (i=0, v = '['; i<o.length; i++)
-						v += (i > 0 ? ',' : '') + s(o[i]);
-
-					return v + ']';
-				}
-
-				v = '{';
-
-				for (i in o)
-					v += typeof o[i] != 'function' ? (v.length > 1 ? ',"' : '"') + i + '":' + s(o[i]) : '';
-
-				return v + '}';
-		}
-
-		return '' + o;
-	}
-};
-
-// Patch and piggy back functions
-tinyMCE.__debug = tinyMCE.debug;
-tinyMCE.debug = function() {
-	var a, i, m = '', now = new Date().getTime(), start = TinyMCE_DevKitPlugin._startTime;
-
-	if (!start)
-		TinyMCE_DevKitPlugin._startTime = start = now;
-
-	a = this.debug.arguments;
-	for (i=0; i<a.length; i++) {
-		if (typeof(a[i]) == 'undefined')
-			continue;
-
-		if (i > 0)
-			m += ', ';
-
-		m += a[i];
-	}
-
-	TinyMCE_DevKitPlugin._log('debug', m);
-};
-
-tinyMCE.dump = function(o) {
-	tinyMCE.debug(TinyMCE_DevKitPlugin._serialize(o));
-};
-
-tinyMCE.sleep = function(t) {
-	var s = new Date().getTime(), b;
-
-	while (new Date().getTime() - s < t) b=1;
-};
-
-tinyMCE.__execCommand = tinyMCE.execCommand;
-tinyMCE.execCommand = function(command, user_interface, value) {
-	var r, st, dk = TinyMCE_DevKitPlugin;
-
-	st = dk._start();
-	dk._log('execCommand', command, user_interface, value);
-	r = tinyMCE.__execCommand(command, user_interface, value);
-	dk._end(st);
-
-	return r;
-};
-
-tinyMCE.__execInstanceCommand = tinyMCE.execInstanceCommand;
-tinyMCE.execInstanceCommand = function(editor_id, command, user_interface, value, focus) {
-	var r, st, dk = TinyMCE_DevKitPlugin;
-
-	st = dk._start();
-	dk._log('execInstanceCommand', editor_id, command, user_interface, value);
-	r = tinyMCE.__execInstanceCommand(editor_id, command, user_interface, value);
-	dk._end(st);
-
-	return r;
-};
-
-TinyMCE_Engine.prototype.__handleEvent = TinyMCE_Engine.prototype.handleEvent;
-TinyMCE_Engine.prototype.handleEvent = function(e) {
-	var r, st, dk = TinyMCE_DevKitPlugin;
-
-	st = dk._start();
-	dk._log('handleEvent', e.type);
-	r = tinyMCE.__handleEvent(e);
-	dk._end(st);
-
-	return r;
-};
-
-tinyMCE.__importCSS = tinyMCE.importCSS;
-tinyMCE.importCSS = function(doc, css) {
-	var r, st, dk = TinyMCE_DevKitPlugin;
-
-	st = dk._start();
-	dk._log('importCSS', doc, css);
-	r = tinyMCE.__importCSS(doc, css);
-	dk._end(st);
-
-	return r;
-};
-
-tinyMCE.__triggerNodeChange = tinyMCE.triggerNodeChange;
-tinyMCE.triggerNodeChange = function(focus, setup_content) {
-	var r, st, dk = TinyMCE_DevKitPlugin;
-
-	st = dk._start();
-	dk._log('triggerNodeChange', focus, setup_content);
-	r = tinyMCE.__triggerNodeChange(focus, setup_content);
-	dk._end(st);
-
-	return r;
-};
-
-tinyMCE.__dispatchCallback = tinyMCE.dispatchCallback;
-tinyMCE.dispatchCallback = function(i, p, n) {
-	var r, st, dk = TinyMCE_DevKitPlugin;
-
-	st = dk._start();
-	dk._log('dispatchCallback', i, p, n);
-	r = tinyMCE.__dispatchCallback(i, p, n);
-	dk._end(st);
-
-	return r;
-};
-
-tinyMCE.__executeCallback = tinyMCE.executeCallback;
-tinyMCE.executeCallback = function(i, p, n) {
-	var r, st, dk = TinyMCE_DevKitPlugin;
-
-	st = dk._start();
-	dk._log('executeCallback', i, p, n);
-	r = tinyMCE.__executeCallback(i, p, n);
-	dk._end(st);
-
-	return r;
-};
-
-tinyMCE.__execCommandCallback = tinyMCE.execCommandCallback;
-tinyMCE.execCommandCallback = function(i, p, n) {
-	var r, st, dk = TinyMCE_DevKitPlugin;
-
-	st = dk._start();
-	dk._log('execCommandCallback', i, p, n);
-	r = tinyMCE.__execCommandCallback(i, p, n);
-	dk._end(st);
-
-	return r;
-};
-
-tinyMCE.addPlugin("devkit", TinyMCE_DevKitPlugin);
Binary file includes/clientside/tinymce/plugins/devkit/images/flip_down.gif has changed
Binary file includes/clientside/tinymce/plugins/devkit/images/flip_up.gif has changed
--- a/includes/clientside/tinymce/plugins/devkit/jscripts/devkit.js	Fri Feb 22 12:46:51 2008 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,331 +0,0 @@
-var devkit = parent.tinyMCE.plugins['devkit'], logEnabled = true, flip = false, book = null;
-
-function init() {
-	var log, i, f = document.forms[0];
-
-	devkit._winLoaded = true;
-
-	log = tinyMCE.log;
-
-	for (i=0; i<log.length; i++)
-		debug(log[i]);
-
-	f.logfilter.value = devkit._logFilter;
-}
-
-function changeFilter(f) {
-	devkit._logFilter = f;
-}
-
-function toggleLog(s) {
-	logEnabled = s;
-}
-
-function toggleFlip() {
-	document.getElementById('flipbtn').src = flip ? 'images/flip_down.gif' : 'images/flip_up.gif';
-
-	if (flip)
-		parent.document.getElementById('devkit').className = 'devkitup';
-	else
-		parent.document.getElementById('devkit').className = 'devkitdown';
-
-	flip = !flip;
-}
-
-function debug(s) {
-	var d, l, n;
-
-	if (!logEnabled || !new RegExp(devkit._logFilter, 'gi').test(s))
-		return;
-
-	d = document;
-	l = d.getElementById('log');
-	n = d.createElement('span');
-
-	n.innerHTML = tinyMCE.xmlEncode(s);
-
-	l.appendChild(n);
-	l.scrollTop = l.scrollHeight;
-}
-
-function renderInfo() {
-	var se = document.getElementById('info'), n, sn, inst, h = '', sel, rng, instCount = 0, rc;
-
-	h += '<h2>Browser info:</h2>';
-
-	h += '<table border="0" cellpadding="0" cellspacing="0" class="data">';
-	h += addRenderInfo('navigator.userAgent', navigator.userAgent);
-	h += addRenderInfo('navigator.appName', navigator.appName);
-	h += addRenderInfo('navigator.platform', navigator.platform);
-	h += addRenderInfo('navigator.language', navigator.language, 'bspec');
-	h += addRenderInfo('navigator.browserLanguage', navigator.browserLanguage, 'bspec');
-	h += addRenderInfo('navigator.systemLanguage', navigator.systemLanguage, 'bspec');
-	h += addRenderInfo('navigator.userLanguage', navigator.userLanguage, 'bspec');
-	h += addRenderInfo('opera.buildNumber("inconspicuous")', typeof(opera) != 'undefined' && opera.buildNumber ? opera.buildNumber('inconspicuous') : null, 'bspec');
-	h += addRenderInfo('window.innerWidth', parent.window.innerWidth, 'bspec');
-	h += addRenderInfo('window.innerHeight', parent.window.innerHeight, 'bspec');
-	h += addRenderInfo('document.body.offsetWidth', parent.document.body.offsetWidth);
-	h += addRenderInfo('document.body.offsetHeight', parent.document.body.offsetHeight);
-	h += addRenderInfo('screen.width', screen.width);
-	h += addRenderInfo('screen.height', screen.height);
-	h += addRenderInfo('screen.availWidth', screen.availWidth);
-	h += addRenderInfo('screen.availHeight', screen.availHeight);
-	h += addRenderInfo('screen.colorDepth', screen.colorDepth);
-	h += addRenderInfo('screen.pixelDepth', screen.pixelDepth, 'bspec');
-	h += addRenderInfo('document.contentType', document.contentType, 'bspec');
-	h += '</table>';
-
-	h += '<h2>TinyMCE_Engine info:</h2>';
-
-	h += '<table border="0" cellpadding="0" cellspacing="0" class="data">';
-	h += addRenderInfo('baseURL', tinyMCE.baseURL);
-	h += addRenderInfo('selectedInstance.editorId', tinyMCE.selectedInstance ? tinyMCE.selectedInstance.editorId : null);
-	h += addRenderInfo('selectedElement.nodeName', tinyMCE.selectedElement ? tinyMCE.selectedElement.nodeName : null, 'dep');
-	h += addRenderInfo('loadedFiles',tinyMCE.loadedFiles.join(','));
-	h += addRenderInfo('isMSIE', tinyMCE.isMSIE);
-	h += addRenderInfo('isMSIE5', tinyMCE.isMSIE5);
-	h += addRenderInfo('isMSIE5_0', tinyMCE.isMSIE5_0);
-	h += addRenderInfo('isMSIE7', tinyMCE.isMSIE7);
-	h += addRenderInfo('isGecko', tinyMCE.isGecko);
-	h += addRenderInfo('isSafari', tinyMCE.isSafari);
-	h += addRenderInfo('isOpera', tinyMCE.isOpera);
-	h += addRenderInfo('isMac', tinyMCE.isMac);
-	h += addRenderInfo('isNS7', tinyMCE.isNS7);
-	h += addRenderInfo('isNS71', tinyMCE.isNS71);
-	h += addRenderInfo('idCounter', tinyMCE.idCounter);
-	h += addRenderInfo('currentConfig', tinyMCE.currentConfig);
-	h += addRenderInfo('majorVersion', tinyMCE.majorVersion);
-	h += addRenderInfo('minorVersion', tinyMCE.minorVersion);
-	h += addRenderInfo('releaseDate', tinyMCE.releaseDate);
-	h += addRenderInfo('documentBasePath', tinyMCE.documentBasePath);
-	h += addRenderInfo('documentURL', tinyMCE.documentURL);
-	h += '</table>';
-
-	for (n in tinyMCE.instances) {
-		inst = tinyMCE.instances[n];
-
-		if (!tinyMCE.isInstance(inst))
-			continue;
-
-		sel = inst.selection.getSel();
-		rng = inst.selection.getRng();
-
-		h += '<h2>TinyMCE_Control(' + (instCount++) + ') id: ' + inst.editorId + '</h2>';
-		h += '<table border="0" cellpadding="0" cellspacing="0" class="data">';
-
-		h += addRenderInfo('editorId', inst.editorId);
-		h += addRenderInfo('visualAid', inst.visualAid);
-		h += addRenderInfo('foreColor', inst.foreColor);
-		h += addRenderInfo('backColor', inst.backColor);
-		h += addRenderInfo('formTargetElementId', inst.formTargetElementId);
-		h += addRenderInfo('formElement', inst.formElement ? inst.formElement.nodeName : null);
-		h += addRenderInfo('oldTargetElement', inst.oldTargetElement ? inst.oldTargetElement.nodeName : null);
-		h += addRenderInfo('linkElement', inst.linkElement ? inst.linkElement.nodeName : null, 'dep');
-		h += addRenderInfo('imgElement', inst.imgElement ? inst.imgElement.nodeName : null, 'dep');
-		h += addRenderInfo('selectedNode', inst.selectedNode ? inst.selectedNode.nodeName : null, 'dep');
-		h += addRenderInfo('targetElement', inst.targetElement ? inst.targetElement.nodeName : null);
-		h += addRenderInfo('getBody().nodeName', inst.getBody() ? inst.getBody().nodeName : null);
-		h += addRenderInfo('getBody().getAttribute("id")', inst.getBody() ? inst.getBody().getAttribute("id") : null);
-		h += addRenderInfo('getDoc().location', inst.getDoc() ? inst.getDoc().location : null);
-		h += addRenderInfo('startContent', inst.startContent);
-		h += addRenderInfo('isHidden()', inst.isHidden());
-		h += addRenderInfo('isDirty()', inst.isDirty());
-		h += addRenderInfo('undoRedo.undoLevels.length', inst.undoRedo.undoLevels.length);
-		h += addRenderInfo('undoRedo.undoIndex', inst.undoRedo.undoIndex);
-		h += addRenderInfo('selection.getSelectedHTML()', inst.selection.getSelectedHTML());
-		h += addRenderInfo('selection.isCollapsed()', inst.selection.isCollapsed() || 'false');
-		h += addRenderInfo('selection.getSelectedText()', inst.selection.getSelectedText());
-		h += addRenderInfo('selection.getFocusElement().nodeName', inst.selection.getFocusElement().nodeName);
-		h += addRenderInfo('selection.getFocusElement().outerHTML', tinyMCE.getOuterHTML(inst.selection.getFocusElement()));
-
-		if ((tinyMCE.isGecko || tinyMCE.isOpera) && sel && rng) {
-			h += addRenderInfo('selection.getSel().anchorNode.nodeName', sel.anchorNode ? sel.anchorNode.nodeName : null, 'bspec');
-			h += addRenderInfo('selection.getSel().anchorOffset', sel.anchorOffset, 'bspec');
-			h += addRenderInfo('selection.getSel().focusNode.nodeName', sel.focusNode ? sel.focusNode.nodeName : null, 'bspec');
-			h += addRenderInfo('selection.getSel().focusOffset', sel.focusOffset, 'bspec');
-			h += addRenderInfo('selection.getRng().startContainer.nodeName', rng.startContainer ? rng.startContainer.nodeName : null, 'bspec');
-			h += addRenderInfo('selection.getRng().startOffset', rng.startOffset, 'bspec');
-			h += addRenderInfo('selection.getRng().endContainer.nodeName', rng.endContainer ? rng.endContainer.nodeName : null, 'bspec');
-			h += addRenderInfo('selection.getRng().endOffset', rng.endOffset, 'bspec');
-		}
-
-		if (typeof(rng.item) != 'undefined' || typeof(rng.htmlText) != 'undefined') {
-			if (!rng.item) {
-				h += addRenderInfo('selection.getSel().type', sel.type, 'bspec');
-				h += addRenderInfo('selection.getRng().htmlText', rng.htmlText, 'bspec');
-				h += addRenderInfo('selection.getRng().text', rng.text, 'bspec');
-			} else
-				h += addRenderInfo('selection.getRng().item(0).nodeName', rng.item(0).nodeName, 'bspec');
-		}
-
-		h += '</table>';
-	}
-
-	h += '<p>Fields marked in <strong class="bspec">gray</strong> is not cross browser and should be used with care.</p>';
-	h += '<p>Fields marked <strong class="dep">red</strong> are marked deprecated and will be removed in the future.</p><br />';
-
-	se.innerHTML = h;
-}
-
-function addRenderInfo(n, v, c) {
-	return '<tr><td' + (c ? ' class="' + c + '"' : '')+ '>' + n + '</td><td><input type="text" value="' + tinyMCE.xmlEncode(v != null ? ('' + v).replace(/[\r\n]/g, '') : 'null') + '" /></td></tr>';
-}
-
-function renderSettings() {
-	var se = document.getElementById('settings'), n, sn, inst, h = '', v;
-
-	for (n in tinyMCE.instances) {
-		inst = tinyMCE.instances[n];
-
-		if (!tinyMCE.isInstance(inst))
-			continue;
-
-		h += '<h2>Instance id: ' + inst.editorId + '</h2>';
-		h += '<table border="0" cellpadding="0" cellspacing="0" class="data">';
-
-		for (sn in inst.settings) {
-			v = inst.settings[sn];
-
-			h += '<tr><td class="col1">' + tinyMCE.xmlEncode(sn) + '</td><td><input type="text" value="' + tinyMCE.xmlEncode(v) + '" /></td></tr>';
-		}
-
-		h += '</table>';
-	}
-
-	se.innerHTML = h;
-}
-
-function renderContent() {
-	var se = document.getElementById('content'), n, inst, h = '';
-
-	for (n in tinyMCE.instances) {
-		inst = tinyMCE.instances[n];
-
-		if (!tinyMCE.isInstance(inst))
-			continue;
-
-		h += '<h2>Instance id: ' + inst.editorId + '</h2>';
-
-		h += '<h3>Start content - inst.startContent:</h3>';
-		h += '<div>' + tinyMCE.xmlEncode(inst.startContent) + '</div>';
-
-		h += '<h3>Raw content - inst.getBody().innerHTML or inst.getHTML(true):</h3>';
-		h += '<div>' + tinyMCE.xmlEncode(inst.getHTML(true)) + '</div>';
-
-		h += '<h3>Cleaned content - inst.getHTML():</h3>';
-		h += '<div>' + tinyMCE.xmlEncode(inst.getHTML()) + '</div>';
-
-		if (inst.serializedHTML) {
-			h += '<h3>Serialized HTML content - inst.serializedHTML:</h3>';
-			h += '<div>' + tinyMCE.xmlEncode(inst.serializedHTML) + '</div>';
-		}
-	}
-
-	se.innerHTML = h;
-}
-
-function renderCommandStates() {
-	var se = document.getElementById('command_states'), n, inst, h = '', v, ex;
-	var cmds = new Array('2D-Position','AbsolutePosition','BackColor','BlockDirLTR','BlockDirRTL','Bold','BrowseMode','Copy','CreateBookmark','CreateLink','Cut','Delete','DirLTR','DirRTL','EditMode','enableInlineTableEditing','enableObjectResizing','FontName','FontSize','ForeColor','FormatBlock','Indent','InsertButton','InsertFieldset','InsertHorizontalRule','InsertIFrame','InsertImage','InsertInputButton','InsertInputCheckbox','InsertInputFileUpload','InsertInputHidden','InsertInputImage','InsertInputPassword','InsertInputRadio','InsertInputReset','InsertInputSubmit','InsertInputText','InsertMarquee','InsertOrderedList','InsertParagraph','InsertSelectDropdown','InsertSelectListbox','InsertTextArea','InsertUnorderedList','Italic','JustifyCenter','JustifyFull','JustifyLeft','JustifyNone','JustifyRight','LiveResize','MultipleSelection','Open','Outdent','OverWrite','Paste','PlayImage','Redo','Refresh','RemoveFormat','SaveAs','SelectAll','SizeToControl','SizeToControlHeight','SizeToControlWidth','Stop','StopImage','StrikeThrough','styleWithCSS','Subscript','Superscript','UnBookmark','Underline','Undo','Unlink','Unselect'), i;
-
-	for (n in tinyMCE.instances) {
-		inst = tinyMCE.instances[n];
-
-		if (!tinyMCE.isInstance(inst))
-			continue;
-
-		h += '<h2>Instance id: ' + inst.editorId + '</h2>';
-		h += '<table border="0" cellpadding="0" cellspacing="0" class="data">';
-
-		for (i=0; i<cmds.length; i++) {
-			v = null;
-
-			try {
-				v = tinyMCE.isGecko || inst.getDoc().queryCommandSupported(cmds[i]);
-				v = v ? inst.queryCommandState(cmds[i]) : 'Not supported';
-			} catch (ex) {
-				v = 'Not supported';
-			}
-
-			h += '<tr><td><input type="text" value="' + tinyMCE.xmlEncode(cmds[i]) + '" /></td><td><input type="text" value="' + tinyMCE.xmlEncode(v) + '" /></td></tr>';
-		}
-
-		h += '</table>';
-	}
-
-	se.innerHTML = h;
-}
-
-function renderUndoRedo() {
-	var se = document.getElementById('undo_redo'), inst, n, h = '', i, le, id, d, ur;
-	var f = document.forms[0];	
-
-	if (tinyMCE.undoLevels) {
-		le = tinyMCE.undoLevels;
-
-		h += '<h2>Global undo/redo</h2>';
-		h += '<table border="0" cellpadding="0" cellspacing="0" width="50%" class="data">';
-		h += '<tr><td>undoLevels.length</td><td>' + le.length + '</td></tr>';
-		h += '<tr><td>undoIndex</td><td>' + tinyMCE.undoIndex + '</td></tr>';
-		h += '</table>';
-
-		for (i=0; i<le.length; i++)
-			h += '<h3>Level: ' + i + ', Instance: ' + (le[i] ? le[i].editorId : 'null') + '</h3>';
-	}
-
-	for (n in tinyMCE.instances) {
-		inst = tinyMCE.instances[n];
-
-		if (!tinyMCE.isInstance(inst))
-			continue;
-
-		ur = inst.undoRedo;
-		le = ur.undoLevels;
-
-		h += '<hr /><h2>Instance id: ' + inst.editorId + '</h2>';
-		h += '<table border="0" cellpadding="0" cellspacing="0" width="50%" class="data">';
-		h += '<tr><td>undoLevels.length</td><td>' + le.length + '</td></tr>';
-		h += '<tr><td>undoIndex</td><td>' + ur.undoIndex + '</td></tr>';
-		h += '<tr><td>typingUndoIndex</td><td>' + ur.typingUndoIndex + '</td></tr>';
-		h += '<tr><td>undoRedo</td><td>' + ur.undoRedo + '</td></tr>';
-		h += '</table>';
-
-		for (i=0; i<le.length; i++) {
-			h += '<h3>Level: ' + i + (!le[i].bookmark ? "" : " [bookmark]") + '</h3>';
-			h += '<div class="undodata">' + tinyMCE.xmlEncode(le[i].content) + '</div>';
-
-			if (i > 0 && f.undo_diff.checked) {
-				d = diff_main(i > 0 ? le[i-1].content.replace(/[\r\n]+/g, '') : null, le[i].content.replace(/[\r\n]+/g, ''), false);
-				diff_cleanup_semantic(d);
-				h += '<h3>Diff ' + (i-1) + ',' + i + '</h3><div class="undodata">' + diff_prettyhtml(d) + '</div>';
-			}
-		}
-	}
-
-	se.innerHTML = h;
-}
-
-function clearLog() {
-	document.getElementById('log').innerHTML = '';
-	devkit._startTime = null;
-}
-
-function cancelAction() {
-	parent.document.getElementById('devkit').style.display = 'none';
-}
-
-function toggleDebugEvents(s) {
-	devkit._debugEvents(s);
-}
-
-function storeSelection() {
-	book = tinyMCE.selectedInstance.selection.getBookmark();
-
-	return false;
-}
-
-function restoreSelection() {
-	tinyMCE.selectedInstance.selection.moveToBookmark(book);
-
-	return false;
-}
\ No newline at end of file
--- a/includes/clientside/tinymce/plugins/devkit/jscripts/diff.js	Fri Feb 22 12:46:51 2008 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1192 +0,0 @@
-// Diff_Match_Patch v1.3
-// Computes the difference between two texts to create a patch.
-// Applies the patch onto another text, allowing for errors.
-// Copyright (C) 2006 Neil Fraser
-// http://neil.fraser.name/software/diff_match_patch/
-
-// This program is free software; you can redistribute it and/or
-// modify it under the terms of the GNU General Public License
-// as published by the Free Software Foundation.
-
-// 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 (www.gnu.org) for more details.
-
-
-// Constants.
-// Redefine these in your program to override the defaults.
-
-// Number of seconds to map a diff before giving up.  (0 for infinity)
-var DIFF_TIMEOUT = 1.0;
-// Cost of an empty edit operation in terms of edit characters.
-var DIFF_EDIT_COST = 4;
-// Tweak the relative importance (0.0 = accuracy, 1.0 = proximity)
-var MATCH_BALANCE = 0.5;
-// At what point is no match declared (0.0 = perfection, 1.0 = very loose)
-var MATCH_THRESHOLD = 0.5;
-// The min and max cutoffs used when computing text lengths.
-var MATCH_MINLENGTH = 100;
-var MATCH_MAXLENGTH = 1000;
-// Chunk size for context length.
-var PATCH_MARGIN = 4;
-
-
-  //////////////////////////////////////////////////////////////////////
- //  Diff                                                            //
-//////////////////////////////////////////////////////////////////////
-
-// The data structure representing a diff is an array of tuples:
-// [[-1, "Hello"], [1, "Goodbye"], [0, " world."]]
-// which means: delete "Hello", add "Goodbye" and keep " world."
-
-
-function diff_main(text1, text2, checklines) {
-  // Find the differences between two texts.  Return an array of changes.
-  // If checklines is present and false, then don't run a line-level diff first to identify the changed areas.
-  // Check for equality (speedup)
-  if (text1 == text2)
-    return [[0, text1]];
-
-  if (typeof checklines == 'undefined')
-    checklines = true;
-
-  var a;
-  // Trim off common prefix (speedup)
-  a = diff_prefix(text1, text2);
-  text1 = a[0];
-  text2 = a[1];
-  var commonprefix = a[2];
-
-  // Trim off common suffix (speedup)
-  a = diff_suffix(text1, text2);
-  text1 = a[0];
-  text2 = a[1];
-  var commonsuffix = a[2];
-
-  var diff, i;
-  var longtext = text1.length > text2.length ? text1 : text2;
-  var shorttext = text1.length > text2.length ? text2 : text1;
-
-  if (!text1) {  // Just add some text (speedup)
-    diff = [[1, text2]];
-  } else if (!text2) { // Just delete some text (speedup)
-    diff = [[-1, text1]];
-  } else if ((i = longtext.indexOf(shorttext)) != -1) {
-    // Shorter text is inside the longer text (speedup)
-    diff = [[1, longtext.substring(0, i)], [0, shorttext], [1, longtext.substring(i+shorttext.length)]];
-    // Swap insertions for deletions if diff is reversed.
-    if (text1.length > text2.length)
-      diff[0][0] = diff[2][0] = -1;
-  } else {
-    longtext = shorttext = null; // Garbage collect
-    // Check to see if the problem can be split in two.
-    var hm = diff_halfmatch(text1, text2);
-    if (hm) {
-      // A half-match was found, sort out the return data.
-      var text1_a = hm[0];
-      var text1_b = hm[1];
-      var text2_a = hm[2];
-      var text2_b = hm[3];
-      var mid_common = hm[4];
-      // Send both pairs off for separate processing.
-      var diff_a = diff_main(text1_a, text2_a, checklines);
-      var diff_b = diff_main(text1_b, text2_b, checklines);
-      // Merge the results.
-      diff = diff_a.concat([[0, mid_common]], diff_b);
-    } else {
-      // Perform a real diff.
-      if (checklines && text1.length + text2.length < 250)
-        checklines = false; // Too trivial for the overhead.
-      if (checklines) {
-        // Scan the text on a line-by-line basis first.
-        a = diff_lines2chars(text1, text2);
-        text1 = a[0];
-        text2 = a[1];
-        var linearray = a[2];
-      }
-      diff = diff_map(text1, text2);
-      if (!diff) // No acceptable result.
-        diff = [[-1, text1], [1, text2]];
-      if (checklines) {
-        diff_chars2lines(diff, linearray); // Convert the diff back to original text.
-        diff_cleanup_semantic(diff); // Eliminate freak matches (e.g. blank lines)
-
-        // Rediff any replacement blocks, this time on character-by-character basis.
-        diff.push([0, '']);  // Add a dummy entry at the end.
-        var pointer = 0;
-        var count_delete = 0;
-        var count_insert = 0;
-        var text_delete = '';
-        var text_insert = '';
-        while(pointer < diff.length) {
-          if (diff[pointer][0] == 1) {
-            count_insert++;
-            text_insert += diff[pointer][1];
-          } else if (diff[pointer][0] == -1) {
-            count_delete++;
-            text_delete += diff[pointer][1];
-          } else {  // Upon reaching an equality, check for prior redundancies.
-            if (count_delete >= 1 && count_insert >= 1) {
-              // Delete the offending records and add the merged ones.
-              a = diff_main(text_delete, text_insert, false);
-              diff.splice(pointer - count_delete - count_insert, count_delete + count_insert);
-              pointer = pointer - count_delete - count_insert;
-              for (i=a.length-1; i>=0; i--)
-                diff.splice(pointer, 0, a[i]);
-              pointer = pointer + a.length;
-            }
-            count_insert = 0;
-            count_delete = 0;
-            text_delete = '';
-            text_insert = '';
-          }
-          pointer++;
-        }
-        diff.pop();  // Remove the dummy entry at the end.
-
-      }
-    }
-  }
-
-  if (commonprefix)
-    diff.unshift([0, commonprefix]);
-  if (commonsuffix)
-    diff.push([0, commonsuffix]);
-  diff_cleanup_merge(diff);
-  return diff;
-}
-
-
-function diff_lines2chars(text1, text2) {
-  // Split text into an array of strings.
-  // Reduce the texts to a string of hashes where each character represents one line.
-  var linearray = new Array();  // linearray[4] == "Hello\n"
-  var linehash = new Object();  // linehash["Hello\n"] == 4
-
-  // "\x00" is a valid JavaScript character, but the Venkman debugger doesn't like it (bug 335098)
-  // So we'll insert a junk entry to avoid generating a null character.
-  linearray.push('');
-
-  function diff_lines2chars_munge(text) {
-    // My first ever closure!
-    var i, line;
-    var chars = '';
-    while (text) {
-      i = text.indexOf('\n');
-      if (i == -1)
-        i = text.length;
-      line = text.substring(0, i+1);
-      text = text.substring(i+1);
-      if (linehash.hasOwnProperty ? linehash.hasOwnProperty(line) : (linehash[line] !== undefined)) {
-        chars += String.fromCharCode(linehash[line]);
-      } else {
-        linearray.push(line);
-        linehash[line] = linearray.length - 1;
-        chars += String.fromCharCode(linearray.length - 1);
-      }
-    }
-    return chars;
-  }
-
-  var chars1 = diff_lines2chars_munge(text1);
-  var chars2 = diff_lines2chars_munge(text2);
-  return [chars1, chars2, linearray];
-}
-
-
-function diff_chars2lines(diff, linearray) {
-  // Rehydrate the text in a diff from a string of line hashes to real lines of text.
-  var chars, text;
-  for (var x=0; x<diff.length; x++) {
-    chars = diff[x][1];
-    text = '';
-    for (var y=0; y<chars.length; y++)
-      text += linearray[chars.charCodeAt(y)];
-    diff[x][1] = text;
-  }
-}
-
-
-function diff_map(text1, text2) {
-  // Explore the intersection points between the two texts.
-  var now = new Date();
-  var ms_end = now.getTime() + DIFF_TIMEOUT * 1000; // Don't run for too long.
-  var max = (text1.length + text2.length) / 2;
-  var v_map1 = new Array();
-  var v_map2 = new Array();
-  var v1 = new Object();
-  var v2 = new Object();
-  v1[1] = 0;
-  v2[1] = 0;
-  var x, y;
-  var footstep; // Used to track overlapping paths.
-  var footsteps = new Object();
-  var done = false;
-  var hasOwnProperty = !!(footsteps.hasOwnProperty);
-  // If the total number of characters is odd, then the front path will collide with the reverse path.
-  var front = (text1.length + text2.length) % 2;
-  for (var d=0; d<max; d++) {
-    now = new Date();
-    if (DIFF_TIMEOUT > 0 && now.getTime() > ms_end) // Timeout reached
-      return null;
-
-    // Walk the front path one step.
-    v_map1[d] = new Object();
-    for (var k=-d; k<=d; k+=2) {
-      if (k == -d || k != d && v1[k-1] < v1[k+1])
-        x = v1[k+1];
-      else
-        x = v1[k-1]+1;
-      y = x - k;
-      footstep = x+","+y;
-      if (front && (hasOwnProperty ? footsteps.hasOwnProperty(footstep) : (footsteps[footstep] !== undefined)))
-        done = true;
-      if (!front)
-        footsteps[footstep] = d;
-      while (!done && x < text1.length && y < text2.length && text1.charAt(x) == text2.charAt(y)) {
-        x++; y++;
-        footstep = x+","+y;
-        if (front && (hasOwnProperty ? footsteps.hasOwnProperty(footstep) : (footsteps[footstep] !== undefined)))
-          done = true;
-        if (!front)
-          footsteps[footstep] = d;
-      }
-      v1[k] = x;
-      v_map1[d][x+","+y] = true;
-      if (done) {
-        // Front path ran over reverse path.
-        v_map2 = v_map2.slice(0, footsteps[footstep]+1);
-        var a = diff_path1(v_map1, text1.substring(0, x), text2.substring(0, y));
-        return a.concat(diff_path2(v_map2, text1.substring(x), text2.substring(y)));
-      }
-    }
-
-    // Walk the reverse path one step.
-    v_map2[d] = new Object();
-    for (var k=-d; k<=d; k+=2) {
-      if (k == -d || k != d && v2[k-1] < v2[k+1])
-        x = v2[k+1];
-      else
-        x = v2[k-1]+1;
-      y = x - k;
-      footstep = (text1.length-x)+","+(text2.length-y);
-      if (!front && (hasOwnProperty ? footsteps.hasOwnProperty(footstep) : (footsteps[footstep] !== undefined)))
-        done = true;
-      if (front)
-        footsteps[footstep] = d;
-      while (!done && x < text1.length && y < text2.length && text1.charAt(text1.length-x-1) == text2.charAt(text2.length-y-1)) {
-        x++; y++;
-        footstep = (text1.length-x)+","+(text2.length-y);
-        if (!front && (hasOwnProperty ? footsteps.hasOwnProperty(footstep) : (footsteps[footstep] !== undefined)))
-          done = true;
-        if (front)
-          footsteps[footstep] = d;
-      }
-      v2[k] = x;
-      v_map2[d][x+","+y] = true;
-      if (done) {
-        // Reverse path ran over front path.
-        v_map1 = v_map1.slice(0, footsteps[footstep]+1);
-        var a = diff_path1(v_map1, text1.substring(0, text1.length-x), text2.substring(0, text2.length-y));
-        return a.concat(diff_path2(v_map2, text1.substring(text1.length-x), text2.substring(text2.length-y)));
-      }
-    }
-  }
-  // Number of diffs equals number of characters, no commonality at all.
-  return null;
-}
-
-
-function diff_path1(v_map, text1, text2) {
-  // Work from the middle back to the start to determine the path.
-  var path = [];
-  var x = text1.length;
-  var y = text2.length;
-  var last_op = null;
-  for (var d=v_map.length-2; d>=0; d--) {
-    while(1) {
-      if (v_map[d].hasOwnProperty ? v_map[d].hasOwnProperty((x-1)+","+y) : (v_map[d][(x-1)+","+y] !== undefined)) {
-        x--;
-        if (last_op === -1)
-          path[0][1] = text1.charAt(x) + path[0][1];
-        else
-          path.unshift([-1, text1.charAt(x)]);
-        last_op = -1;
-        break;
-      } else if (v_map[d].hasOwnProperty ? v_map[d].hasOwnProperty(x+","+(y-1)) : (v_map[d][x+","+(y-1)] !== undefined)) {
-        y--;
-        if (last_op === 1)
-          path[0][1] = text2.charAt(y) + path[0][1];
-        else
-          path.unshift([1, text2.charAt(y)]);
-        last_op = 1;
-        break;
-      } else {
-        x--;
-        y--;
-        //if (text1.charAt(x) != text2.charAt(y))
-        //  return alert("No diagonal.  Can't happen. (diff_path1)");
-        if (last_op === 0)
-          path[0][1] = text1.charAt(x) + path[0][1];
-        else
-          path.unshift([0, text1.charAt(x)]);
-        last_op = 0;
-      }
-    }
-  }
-  return path;
-}
-
-
-function diff_path2(v_map, text1, text2) {
-  // Work from the middle back to the end to determine the path.
-  var path = [];
-  var x = text1.length;
-  var y = text2.length;
-  var last_op = null;
-  for (var d=v_map.length-2; d>=0; d--) {
-    while(1) {
-      if (v_map[d].hasOwnProperty ? v_map[d].hasOwnProperty((x-1)+","+y) : (v_map[d][(x-1)+","+y] !== undefined)) {
-        x--;
-        if (last_op === -1)
-          path[path.length-1][1] += text1.charAt(text1.length-x-1);
-        else
-          path.push([-1, text1.charAt(text1.length-x-1)]);
-        last_op = -1;
-        break;
-      } else if (v_map[d].hasOwnProperty ? v_map[d].hasOwnProperty(x+","+(y-1)) : (v_map[d][x+","+(y-1)] !== undefined)) {
-        y--;
-        if (last_op === 1)
-          path[path.length-1][1] += text2.charAt(text2.length-y-1);
-        else
-          path.push([1, text2.charAt(text2.length-y-1)]);
-        last_op = 1;
-        break;
-      } else {
-        x--;
-        y--;
-        //if (text1.charAt(text1.length-x-1) != text2.charAt(text2.length-y-1))
-        //  return alert("No diagonal.  Can't happen. (diff_path2)");
-        if (last_op === 0)
-          path[path.length-1][1] += text1.charAt(text1.length-x-1);
-        else
-          path.push([0, text1.charAt(text1.length-x-1)]);
-        last_op = 0;
-      }
-    }
-  }
-  return path;
-}
-
-
-function diff_prefix(text1, text2) {
-  // Trim off common prefix
-  var pointermin = 0;
-  var pointermax = Math.min(text1.length, text2.length);
-  var pointermid = pointermax;
-  while(pointermin < pointermid) {
-    if (text1.substring(0, pointermid) == text2.substring(0, pointermid))
-      pointermin = pointermid;
-    else
-      pointermax = pointermid;
-    pointermid = Math.floor((pointermax - pointermin) / 2 + pointermin);
-  }
-  var commonprefix = text1.substring(0, pointermid);
-  text1 = text1.substring(pointermid);
-  text2 = text2.substring(pointermid);
-  return [text1, text2, commonprefix];
-}
-
-
-function diff_suffix(text1, text2) {
-  // Trim off common suffix
-  var pointermin = 0;
-  var pointermax = Math.min(text1.length, text2.length);
-  var pointermid = pointermax;
-  while(pointermin < pointermid) {
-    if (text1.substring(text1.length-pointermid) == text2.substring(text2.length-pointermid))
-      pointermin = pointermid;
-    else
-      pointermax = pointermid;
-    pointermid = Math.floor((pointermax - pointermin) / 2 + pointermin);
-  }
-  var commonsuffix = text1.substring(text1.length-pointermid);
-  text1 = text1.substring(0, text1.length-pointermid);
-  text2 = text2.substring(0, text2.length-pointermid);
-  return [text1, text2, commonsuffix];
-}
-
-
-function diff_halfmatch(text1, text2) {
-  // Do the two texts share a substring which is at least half the length of the longer text?
-  var longtext = text1.length > text2.length ? text1 : text2;
-  var shorttext = text1.length > text2.length ? text2 : text1;
-  if (longtext.length < 10 || shorttext.length < 1)
-    return null; // Pointless.
-
-  function diff_halfmatch_i(longtext, shorttext, i) {
-    // Start with a 1/4 length substring at position i as a seed.
-    var seed = longtext.substring(i, i+Math.floor(longtext.length/4));
-    var j = -1;
-    var best_common = '';
-    var best_longtext_a, best_longtext_b, best_shorttext_a, best_shorttext_b;
-    while ((j = shorttext.indexOf(seed, j+1)) != -1) {
-      var my_prefix = diff_prefix(longtext.substring(i), shorttext.substring(j));
-      var my_suffix = diff_suffix(longtext.substring(0, i), shorttext.substring(0, j));
-      if (best_common.length < (my_suffix[2] + my_prefix[2]).length) {
-        best_common = my_suffix[2] + my_prefix[2];
-        best_longtext_a = my_suffix[0];
-        best_longtext_b = my_prefix[0];
-        best_shorttext_a = my_suffix[1];
-        best_shorttext_b = my_prefix[1];
-      }
-    }
-    if (best_common.length >= longtext.length/2)
-      return [best_longtext_a, best_longtext_b, best_shorttext_a, best_shorttext_b, best_common];
-    else
-      return null;
-  }
-
-  // First check if the second quarter is the seed for a half-match.
-  var hm1 = diff_halfmatch_i(longtext, shorttext, Math.ceil(longtext.length/4));
-  // Check again based on the third quarter.
-  var hm2 = diff_halfmatch_i(longtext, shorttext, Math.ceil(longtext.length/2));
-  var hm;
-  if (!hm1 && !hm2)
-    return null;
-  else if (!hm2)
-    hm = hm1;
-  else if (!hm1)
-    hm = hm2;
-  else // Both matched.  Select the longest.
-    hm = hm1[4].length > hm2[4].length ? hm1 : hm2;
-
-  // A half-match was found, sort out the return data.
-  if (text1.length > text2.length) {
-    var text1_a = hm[0];
-    var text1_b = hm[1];
-    var text2_a = hm[2];
-    var text2_b = hm[3];
-  } else {
-    var text2_a = hm[0];
-    var text2_b = hm[1];
-    var text1_a = hm[2];
-    var text1_b = hm[3];
-  }
-  var mid_common = hm[4];
-  return [text1_a, text1_b, text2_a, text2_b, mid_common];
-}
-
-
-function diff_cleanup_semantic(diff) {
-  // Reduce the number of edits by eliminating semantically trivial equalities.
-  var changes = false;
-  var equalities = []; // Stack of indices where equalities are found.
-  var lastequality = null; // Always equal to equalities[equalities.length-1][1]
-  var pointer = 0; // Index of current position.
-  var length_changes1 = 0; // Number of characters that changed prior to the equality.
-  var length_changes2 = 0; // Number of characters that changed after the equality.
-  while (pointer < diff.length) {
-    if (diff[pointer][0] == 0) { // equality found
-      equalities.push(pointer);
-      length_changes1 = length_changes2;
-      length_changes2 = 0;
-      lastequality = diff[pointer][1];
-    } else { // an insertion or deletion
-      length_changes2 += diff[pointer][1].length;
-      if (lastequality != null && (lastequality.length <= length_changes1) && (lastequality.length <= length_changes2)) {
-        //alert("Splitting: '"+lastequality+"'");
-        diff.splice(equalities[equalities.length-1], 0, [-1, lastequality]); // Duplicate record
-        diff[equalities[equalities.length-1]+1][0] = 1; // Change second copy to insert.
-        equalities.pop();  // Throw away the equality we just deleted;
-        equalities.pop();  // Throw away the previous equality;
-        pointer = equalities.length ? equalities[equalities.length-1] : -1;
-        length_changes1 = 0; // Reset the counters.
-        length_changes2 = 0;
-        lastequality = null;
-        changes = true;
-      }
-    }
-    pointer++;
-  }
-
-  if (changes)
-    diff_cleanup_merge(diff);
-}
-
-
-function diff_cleanup_efficiency(diff) {
-  // Reduce the number of edits by eliminating operationally trivial equalities.
-  var changes = false;
-  var equalities = []; // Stack of indices where equalities are found.
-  var lastequality = ''; // Always equal to equalities[equalities.length-1][1]
-  var pointer = 0; // Index of current position.
-  var pre_ins = false; // Is there an insertion operation before the last equality.
-  var pre_del = false; // Is there an deletion operation before the last equality.
-  var post_ins = false; // Is there an insertion operation after the last equality.
-  var post_del = false; // Is there an deletion operation after the last equality.
-  while (pointer < diff.length) {
-    if (diff[pointer][0] == 0) { // equality found
-      if (diff[pointer][1].length < DIFF_EDIT_COST && (post_ins || post_del)) {
-        // Candidate found.
-        equalities.push(pointer);
-        pre_ins = post_ins;
-        pre_del = post_del;
-        lastequality = diff[pointer][1];
-      } else {
-        // Not a candidate, and can never become one.
-        equalities = [];
-        lastequality = '';
-      }
-      post_ins = post_del = false;
-    } else { // an insertion or deletion
-      if (diff[pointer][0] == -1)
-        post_del = true;
-      else
-        post_ins = true;
-      // Five types to be split:
-      // <ins>A</ins><del>B</del>XY<ins>C</ins><del>D</del>
-      // <ins>A</ins>X<ins>C</ins><del>D</del>
-      // <ins>A</ins><del>B</del>X<ins>C</ins>
-      // <ins>A</del>X<ins>C</ins><del>D</del>
-      // <ins>A</ins><del>B</del>X<del>C</del>
-      if (lastequality && ((pre_ins && pre_del && post_ins && post_del) || ((lastequality.length < DIFF_EDIT_COST/2) && (pre_ins + pre_del + post_ins + post_del) == 3))) {
-        //alert("Splitting: '"+lastequality+"'");
-        diff.splice(equalities[equalities.length-1], 0, [-1, lastequality]); // Duplicate record
-        diff[equalities[equalities.length-1]+1][0] = 1; // Change second copy to insert.
-        equalities.pop();  // Throw away the equality we just deleted;
-        lastequality = '';
-        if (pre_ins && pre_del) {
-          // No changes made which could affect previous entry, keep going.
-          post_ins = post_del = true;
-          equalities = [];
-        } else {
-          equalities.pop();  // Throw away the previous equality;
-          pointer = equalities.length ? equalities[equalities.length-1] : -1;
-          post_ins = post_del = false;
-        }
-        changes = true;
-      }
-    }
-    pointer++;
-  }
-
-  if (changes)
-    diff_cleanup_merge(diff);
-}
-
-
-function diff_cleanup_merge(diff) {
-  // Reorder and merge like edit sections.  Merge equalities.
-  // Any edit section can move as long as it doesn't cross an equality.
-  diff.push([0, '']);  // Add a dummy entry at the end.
-  var pointer = 0;
-  var count_delete = 0;
-  var count_insert = 0;
-  var text_delete = '';
-  var text_insert = '';
-  var record_insert, record_delete;
-  var my_xfix;
-  while(pointer < diff.length) {
-    if (diff[pointer][0] == 1) {
-      count_insert++;
-      text_insert += diff[pointer][1];
-      pointer++;
-    } else if (diff[pointer][0] == -1) {
-      count_delete++;
-      text_delete += diff[pointer][1];
-      pointer++;
-    } else {  // Upon reaching an equality, check for prior redundancies.
-      if (count_delete > 1 || count_insert > 1) {
-        if (count_delete > 1 && count_insert > 1) {
-          // Factor out any common prefixies.
-          my_xfix = diff_prefix(text_insert, text_delete);
-          if (my_xfix[2] != '') {
-            if ((pointer - count_delete - count_insert) > 0 && diff[pointer - count_delete - count_insert - 1][0] == 0) {
-              text_insert = my_xfix[0];
-              text_delete = my_xfix[1];
-              diff[pointer - count_delete - count_insert - 1][1] += my_xfix[2];
-            }
-          }
-          // Factor out any common suffixies.
-          my_xfix = diff_suffix(text_insert, text_delete);
-          if (my_xfix[2] != '') {
-            text_insert = my_xfix[0];
-            text_delete = my_xfix[1];
-            diff[pointer][1] = my_xfix[2] + diff[pointer][1];
-          }
-        }
-        // Delete the offending records and add the merged ones.
-        if (count_delete == 0)
-          diff.splice(pointer - count_delete - count_insert, count_delete + count_insert, [1, text_insert]);
-        else if (count_insert == 0)
-          diff.splice(pointer - count_delete - count_insert, count_delete + count_insert, [-1, text_delete]);
-        else
-          diff.splice(pointer - count_delete - count_insert, count_delete + count_insert, [-1, text_delete], [1, text_insert]);
-        pointer = pointer - count_delete - count_insert + (count_delete ? 1 : 0) + (count_insert ? 1 : 0) + 1;
-      } else if (pointer != 0 && diff[pointer-1][0] == 0) {
-        // Merge this equality with the previous one.
-        diff[pointer-1][1] += diff[pointer][1];
-        diff.splice(pointer, 1);
-      } else {
-        pointer++;
-      }
-      count_insert = 0;
-      count_delete = 0;
-      text_delete = '';
-      text_insert = '';
-    }
-  }
-  if (diff[diff.length-1][1] == '')
-    diff.pop();  // Remove the dummy entry at the end.
-}
-
-
-function diff_addindex(diff) {
-  // Add an index to each tuple, represents where the tuple is located in text2.
-  // e.g. [[-1, 'h', 0], [1, 'c', 0], [0, 'at', 1]]
-  var i = 0;
-  for (var x=0; x<diff.length; x++) {
-    diff[x].push(i);
-    if (diff[x][0] != -1)
-      i += diff[x][1].length;
-  }
-}
-
-
-function diff_xindex(diff, loc) {
-  // loc is a location in text1, compute and return the equivalent location in text2.
-  // e.g. "The cat" vs "The big cat", 1->1, 5->8
-  var chars1 = 0;
-  var chars2 = 0;
-  var last_chars1 = 0;
-  var last_chars2 = 0;
-  for (var x=0; x<diff.length; x++) {
-    if (diff[x][0] != 1) // Equality or deletion.
-      chars1 += diff[x][1].length;
-    if (diff[x][0] != -1) // Equality or insertion.
-      chars2 += diff[x][1].length;
-    if (chars1 > loc) // Overshot the location.
-      break;
-    last_chars1 = chars1;
-    last_chars2 = chars2;
-  }
-  if (diff.length != x && diff[x][0] == -1) // The location was deleted.
-    return last_chars2;
-  // Add the remaining character length.
-  return last_chars2 + (loc - last_chars1);
-}
-
-
-function diff_prettyhtml(diff) {
-  // Convert a diff array into a pretty HTML report.
-  diff_addindex(diff);
-  var html = '';
-  for (var x=0; x<diff.length; x++) {
-    var m = diff[x][0]; // Mode (-1=delete, 0=copy, 1=add)
-    var t = diff[x][1]; // Text of change.
-    var i = diff[x][2]; // Index of change.
-    t = t.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
-    t = t.replace(/\n/g, "&para;<BR>");
-    if (m == -1)
-      html += "<DEL STYLE='background:#FFE6E6;' TITLE='i="+i+"'>"+t+"</DEL>";
-    else if (m == 1)
-      html += "<INS STYLE='background:#E6FFE6;' TITLE='i="+i+"'>"+t+"</INS>";
-    else
-      html += "<SPAN TITLE='i="+i+"'>"+t+"</SPAN>";
-  }
-  return html;
-}
-
-
-  //////////////////////////////////////////////////////////////////////
- //  Match                                                           //
-//////////////////////////////////////////////////////////////////////
-
-
-function match_getmaxbits() {
-  // Compute the number of bits in an int.
-  // The normal answer for JavaScript is 32.
-  var maxbits = 0;
-  var oldi = 1;
-  var newi = 2;
-  while (oldi != newi) {
-    maxbits++;
-    oldi = newi;
-    newi = newi << 1;
-  }
-  return maxbits;
-}
-var MATCH_MAXBITS = match_getmaxbits();
-
-
-function match_main(text, pattern, loc) {
-  // Locate the best instance of 'pattern' in 'text' near 'loc'.
-  loc = Math.max(0, Math.min(loc, text.length-pattern.length));
-  if (text == pattern) {
-    // Shortcut (potentially not guaranteed by the algorithm)
-    return 0;
-  } else if (text.length == 0) {
-    // Nothing to match.
-    return null;
-  } else if (text.substring(loc, loc + pattern.length) == pattern) {
-    // Perfect match at the perfect spot!  (Includes case of null pattern)
-    return loc;
-  } else {
-    // Do a fuzzy compare.
-    var match = match_bitap(text, pattern, loc);
-    return match;
-  }
-}
-
-
-function match_bitap(text, pattern, loc) {
-  // Locate the best instance of 'pattern' in 'text' near 'loc' using the Bitap algorithm.
-  if (pattern.length > MATCH_MAXBITS)
-    return alert("Pattern too long for this browser.");
-
-  // Initialise the alphabet.
-  var s = match_alphabet(pattern);
-
-  var score_text_length = text.length;
-  // Coerce the text length between reasonable maximums and minimums.
-  score_text_length = Math.max(score_text_length, MATCH_MINLENGTH);
-  score_text_length = Math.min(score_text_length, MATCH_MAXLENGTH);
-
-  function match_bitap_score (e, x) {
-    // Compute and return the score for a match with e errors and x location.
-    var d = Math.abs(loc-x);
-    return (e / pattern.length / MATCH_BALANCE) + (d / score_text_length / (1.0 - MATCH_BALANCE));
-  }
-
-  // Highest score beyond which we give up.
-  var score_threshold = MATCH_THRESHOLD;
-  // Is there a nearby exact match? (speedup)
-  var best_loc = text.indexOf(pattern, loc);
-  if (best_loc != -1)
-    score_threshold = Math.min(match_bitap_score(0, best_loc), score_threshold);
-  // What about in the other direction? (speedup)
-  best_loc = text.lastIndexOf(pattern, loc+pattern.length);
-  if (best_loc != -1)
-    score_threshold = Math.min(match_bitap_score(0, best_loc), score_threshold);
-
-  // Initialise the bit arrays.
-  var r = Array();
-  var d = -1;
-  var matchmask = Math.pow(2, pattern.length-1);
-  best_loc = null;
-
-  var bin_min, bin_mid;
-  var bin_max = Math.max(loc+loc, text.length);
-  var last_rd;
-  for (var d=0; d<pattern.length; d++) {
-    // Scan for the best match; each iteration allows for one more error.
-    var rd = Array(text.length);
-
-    // Run a binary search to determine how far from 'loc' we can stray at this error level.
-    bin_min = loc;
-    bin_mid = bin_max;
-    while(bin_min < bin_mid) {
-      if (match_bitap_score(d, bin_mid) < score_threshold)
-        bin_min = bin_mid;
-      else
-        bin_max = bin_mid;
-      bin_mid = Math.floor((bin_max - bin_min) / 2 + bin_min);
-    }
-    bin_max = bin_mid; // Use the result from this iteration as the maximum for the next.
-    var start = Math.max(0, loc - (bin_mid - loc) - 1);
-    var finish = Math.min(text.length-1, pattern.length + bin_mid);
-
-    if (text.charAt(finish) == pattern.charAt(pattern.length-1))
-      rd[finish] = Math.pow(2, d+1)-1;
-    else
-      rd[finish] = Math.pow(2, d)-1;
-    for (var j=finish-1; j>=start; j--) {
-      // The alphabet (s) is a sparse hash, so the following lines generate warnings.
-      if (d == 0) // First pass: exact match.
-        rd[j] = ((rd[j+1] << 1) | 1) & s[text.charAt(j)];
-      else // Subsequent passes: fuzzy match.
-        rd[j] = ((rd[j+1] << 1) | 1) & s[text.charAt(j)] | ((last_rd[j+1] << 1) | 1) | ((last_rd[j] << 1) | 1) | last_rd[j+1];
-      if (rd[j] & matchmask) {
-        var score = match_bitap_score(d, j);
-        // This match will almost certainly be better than any existing match.  But check anyway.
-        if (score <= score_threshold) {
-          // Told you so.
-          score_threshold = score;
-          best_loc = j;
-          if (j > loc) {
-            // When passing loc, don't exceed our current distance from loc.
-            start = Math.max(0, loc - (j - loc));
-          } else {
-            // Already passed loc, downhill from here on in.
-            break;
-          }
-        }
-      }
-    }
-    if (match_bitap_score(d+1, loc) > score_threshold) // No hope for a (better) match at greater error levels.
-      break;
-    last_rd = rd;
-  }
-  return best_loc;
-}
-
-
-function match_alphabet(pattern) {
-  // Initialise the alphabet for the Bitap algorithm.
-  var s = Object();
-  for (var i=0; i<pattern.length; i++)
-    s[pattern.charAt(i)] = 0;
-  for (var i=0; i<pattern.length; i++)
-    s[pattern.charAt(i)] |= Math.pow(2, pattern.length-i-1);
-  return s;
-}
-
-
-  //////////////////////////////////////////////////////////////////////
- //  Patch                                                           //
-//////////////////////////////////////////////////////////////////////
-
-
-function patch_obj() {
-  // Constructor for a patch object.
-  this.diffs = [];
-  this.start1 = null;
-  this.start2 = null;
-  this.length1 = 0;
-  this.length2 = 0;
-
-  this.toString = function() {
-    // Emmulate GNU diff's format.
-    // Header: @@ -382,8 +481,9 @@
-    // Indicies are printed as 1-based, not 0-based.
-    var coords1, coords2;
-    if (this.length1 == 0)
-      coords1 = this.start1+",0";
-    else if (this.length1 == 1)
-      coords1 = this.start1+1;
-    else
-      coords1 = (this.start1+1)+","+this.length1;
-    if (this.length2 == 0)
-      coords2 = this.start2+",0";
-    else if (this.length2 == 1)
-      coords2 = this.start2+1;
-    else
-      coords2 = (this.start2+1)+","+this.length2;
-    var txt = "@@ -"+coords1+" +"+coords2+" @@\n";
-    // Escape the body of the patch with %xx notation.
-    for (var x=0; x<this.diffs.length; x++)
-      txt += ("- +".charAt(this.diffs[x][0]+1)) + encodeURI(this.diffs[x][1]) + "\n";
-    return txt.replace(/%20/g, ' ');
-  }
-
-  this.text1 = function() {
-    // Compute and return the source text (all equalities and deletions).
-    var txt = '';
-    for (var x=0; x<this.diffs.length; x++)
-      if (this.diffs[x][0] == 0 || this.diffs[x][0] == -1)
-        txt += this.diffs[x][1];
-    return txt;
-  }
-
-  this.text2 = function() {
-    // Compute and return the destination text (all equalities and insertions).
-    var txt = '';
-    for (var x=0; x<this.diffs.length; x++)
-      if (this.diffs[x][0] == 0 || this.diffs[x][0] == 1)
-        txt += this.diffs[x][1];
-    return txt;
-  }
-}
-
-
-function patch_addcontext(patch, text) {
-  var pattern = text.substring(patch.start2, patch.start2+patch.length1);
-  var padding = 0;
-  // Increase the context until we're unique (but don't let the pattern expand beyond MATCH_MAXBITS).
-  while (text.indexOf(pattern) != text.lastIndexOf(pattern) && pattern.length < MATCH_MAXBITS-PATCH_MARGIN-PATCH_MARGIN) {
-    padding += PATCH_MARGIN;
-    pattern = text.substring(patch.start2 - padding, patch.start2+patch.length1 + padding);
-  }
-  // Add one chunk for good luck.
-  padding += PATCH_MARGIN;
-  // Add the prefix.
-  var prefix = text.substring(patch.start2 - padding, patch.start2);
-  if (prefix != '')
-    patch.diffs.unshift([0, prefix]);
-  // Add the suffix
-  var suffix = text.substring(patch.start2+patch.length1, patch.start2+patch.length1 + padding);
-  if (suffix != '')
-    patch.diffs.push([0, suffix]);
-
-  // Roll back the start points.
-  patch.start1 -= prefix.length;
-  patch.start2 -= prefix.length;
-  // Extend the lengths.
-  patch.length1 += prefix.length + suffix.length;
-  patch.length2 += prefix.length + suffix.length;
-}
-
-
-function patch_make(text1, text2, diff) {
-  // Compute a list of patches to turn text1 into text2.
-  // Use diff if provided, otherwise compute it ourselves.
-  if (typeof diff == 'undefined') {
-    diff = diff_main(text1, text2, true);
-    if (diff.length > 2) {
-      diff_cleanup_semantic(diff);
-      diff_cleanup_efficiency(diff);
-    }
-  }
-  if (diff.length == 0)
-    return []; // Get rid of the null case.
-  var patches = [];
-  var patch = new patch_obj();
-  var char_count1 = 0; // Number of characters into the text1 string.
-  var char_count2 = 0; // Number of characters into the text2 string.
-  var last_type = null;
-  var prepatch_text = text1; // Recreate the patches to determine context info.
-  var postpatch_text = text1;
-  for (var x=0; x<diff.length; x++) {
-    var diff_type = diff[x][0];
-    var diff_text = diff[x][1];
-
-    if (patch.diffs.length == 0 && diff_type != 0) {
-      // A new patch starts here.
-      patch.start1 = char_count1;
-      patch.start2 = char_count2;
-    }
-
-    if (diff_type == 1) {
-      // Insertion
-      patch.diffs.push(diff[x]);
-      patch.length2 += diff_text.length;
-      postpatch_text = postpatch_text.substring(0, char_count2) + diff_text + postpatch_text.substring(char_count2);
-    } else if (diff_type == -1) {
-      // Deletion.
-      patch.length1 += diff_text.length;
-      patch.diffs.push(diff[x]);
-      postpatch_text = postpatch_text.substring(0, char_count2) + postpatch_text.substring(char_count2 + diff_text.length);
-    } else if (diff_type == 0 && diff_text.length <= 2*PATCH_MARGIN && patch.diffs.length != 0 && diff.length != x+1) {
-      // Small equality inside a patch.
-      patch.diffs.push(diff[x]);
-      patch.length1 += diff_text.length;
-      patch.length2 += diff_text.length;
-    }
-
-    last_type = diff_type;
-    if (diff_type == 0 && diff_text.length >= 2*PATCH_MARGIN) {
-      // Time for a new patch.
-      if (patch.diffs.length != 0) {
-        patch_addcontext(patch, prepatch_text);
-        patches.push(patch);
-        var patch = new patch_obj();
-        last_type = null;
-        prepatch_text = postpatch_text;
-      }
-    }
-
-    // Update the current character count.
-    if (diff_type != 1)
-      char_count1 += diff_text.length;
-    if (diff_type != -1)
-      char_count2 += diff_text.length;
-  }
-  // Pick up the leftover patch if not empty.
-  if (patch.diffs.length != 0) {
-    patch_addcontext(patch, prepatch_text);
-    patches.push(patch);
-  }
-
-  return patches;
-}
-
-
-function patch_apply(patches, text) {
-  // Merge a set of patches onto the text.
-  // Return a patched text, as well as a list of true/false values indicating which patches were applied.
-  patch_splitmax(patches);
-  var results = [];
-  var delta = 0;
-  var expected_loc, start_loc;
-  var text1, text2;
-  var diff, mod, index1, index2;
-  for (var x=0; x<patches.length; x++) {
-    expected_loc = patches[x].start2 + delta;
-    text1 = patches[x].text1();
-    start_loc = match_main(text, text1, expected_loc);
-    if (start_loc == null) {
-      // No match found.  :(
-      results.push(false);
-    } else {
-      // Found a match.  :)
-      results.push(true);
-      delta = start_loc - expected_loc;
-      text2 = text.substring(start_loc, start_loc + text1.length);
-      if (text1 == text2) {
-        // Perfect match, just shove the replacement text in.
-        text = text.substring(0, start_loc) + patches[x].text2() + text.substring(start_loc + text1.length);
-      } else {
-        // Imperfect match.  Run a diff to get a framework of equivalent indicies.
-        diff = diff_main(text1, text2, false);
-        index1 = 0;
-        for (var y=0; y<patches[x].diffs.length; y++) {
-          mod = patches[x].diffs[y];
-          if (mod[0] != 0)
-            index2 = diff_xindex(diff, index1);
-          if (mod[0] == 1) // Insertion
-            text = text.substring(0, start_loc + index2) + mod[1] + text.substring(start_loc + index2);
-          else if (mod[0] == -1) // Deletion
-            text = text.substring(0, start_loc + index2) + text.substring(start_loc + diff_xindex(diff, index1 + mod[1].length));
-          if (mod[0] != -1)
-            index1 += mod[1].length;
-        }
-      }
-    }
-  }
-  return [text, results];
-}
-
-
-function patch_splitmax(patches) {
-  // Look through the patches and break up any which are longer than the maximum limit of the match algorithm.
-  var bigpatch, patch, patch_size, start1, start2, diff_type, diff_text, precontext, postcontext, empty;
-  for (var x=0; x<patches.length; x++) {
-    if (patches[x].length1 > MATCH_MAXBITS) {
-      bigpatch = patches[x];
-      // Remove the big old patch.
-      patches.splice(x, 1);
-      patch_size = MATCH_MAXBITS;
-      start1 = bigpatch.start1;
-      start2 = bigpatch.start2;
-      precontext = '';
-      while (bigpatch.diffs.length != 0) {
-        // Create one of several smaller patches.
-        patch = new patch_obj();
-        empty = true;
-        patch.start1 = start1 - precontext.length;
-        patch.start2 = start2 - precontext.length;
-        if (precontext  != '') {
-          patch.length1 = patch.length2 = precontext.length;
-          patch.diffs.push([0, precontext]);
-        }
-        while (bigpatch.diffs.length != 0 && patch.length1 < patch_size - PATCH_MARGIN) {
-          diff_type = bigpatch.diffs[0][0];
-          diff_text = bigpatch.diffs[0][1];
-          if (diff_type == 1) {
-            // Insertions are harmless.
-            patch.length2 += diff_text.length;
-            start2 += diff_text.length;
-            patch.diffs.push(bigpatch.diffs.shift());
-            empty = false;
-          } else {
-            // Deletion or equality.  Only take as much as we can stomach.
-            diff_text = diff_text.substring(0, patch_size - patch.length1 - PATCH_MARGIN);
-            patch.length1 += diff_text.length;
-            start1 += diff_text.length;
-            if (diff_type == 0) {
-              patch.length2 += diff_text.length;
-              start2 += diff_text.length;
-            } else {
-              empty = false;
-            }
-            patch.diffs.push([diff_type, diff_text]);
-            if (diff_text == bigpatch.diffs[0][1])
-              bigpatch.diffs.shift();
-            else
-              bigpatch.diffs[0][1] = bigpatch.diffs[0][1].substring(diff_text.length);
-          }
-        }
-        // Compute the head context for the next patch.
-        precontext = patch.text2();
-        precontext = precontext.substring(precontext.length - PATCH_MARGIN);
-        // Append the end context for this patch.
-        postcontext = bigpatch.text1().substring(0, PATCH_MARGIN);
-        if (postcontext  != '') {
-          patch.length1 += postcontext.length;
-          patch.length2 += postcontext.length;
-          if (patch.diffs.length > 0 && patch.diffs[patch.diffs.length-1][0] == 0)
-            patch.diffs[patch.diffs.length-1][1] += postcontext;
-          else
-            patch.diffs.push([0, postcontext]);
-        }
-        if (!empty)
-          patches.splice(x++, 0, patch);
-      }
-    }
-  }
-}
-
-
-function patch_totext(patches) {
-  // Take a list of patches and return a textual representation.
-  var text = '';
-  for (var x=0; x<patches.length; x++)
-    text += patches[x];
-  return text;
-}
-
-
-function patch_fromtext(text) {
-  // Take a textual representation of patches and return a list of patch objects.
-  var patches = [];
-  text = text.split('\n');
-  var patch, m, chars1, chars2, sign, line;
-  while (text.length != 0) {
-    m = text[0].match(/^@@ -(\d+),?(\d*) \+(\d+),?(\d*) @@$/);
-    if (!m)
-      return alert("Invalid patch string:\n"+text[0]);
-    patch = new patch_obj();
-    patches.push(patch);
-    patch.start1 = parseInt(m[1]);
-    if (m[2] == '') {
-      patch.start1--;
-      patch.length1 = 1;
-    } else if (m[2] == '0') {
-      patch.length1 = 0;
-    } else {
-      patch.start1--;
-      patch.length1 = parseInt(m[2]);
-    }
-
-    patch.start2 = parseInt(m[3]);
-    if (m[4] == '') {
-      patch.start2--;
-      patch.length2 = 1;
-    } else if (m[4] == '0') {
-      patch.length2 = 0;
-    } else {
-      patch.start2--;
-      patch.length2 = parseInt(m[4]);
-    }
-    text.shift();
-
-    while (text.length != 0) {
-      sign = text[0].charAt(0);
-      line = decodeURIComponent(text[0].substring(1));
-      if (sign == '-') {
-        // Deletion.
-        patch.diffs.push([-1, line]);
-      } else if (sign == '+') {
-        // Insertion.
-        patch.diffs.push([1, line]);
-      } else if (sign == ' ') {
-        // Minor equality.
-        patch.diffs.push([0, line]);
-      } else if (sign == '@') {
-        // Start of next patch.
-        break;
-      } else if (sign == '') {
-        // Blank line?  Whatever.
-      } else {
-        // WTF?
-        return alert("Invalid patch mode: '"+sign+"'\n"+line);
-      }
-      text.shift();
-    }
-  }
-  return patches;
-}
-
-// EOF
--- a/includes/clientside/tinymce/plugins/devkit/langs/en.js	Fri Feb 22 12:46:51 2008 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,23 +0,0 @@
-// UK lang variables
-
-tinyMCE.addToLang('devkit',{
-title : 'TinyMCE Development Kit',
-info_tab : 'Info',
-settings_tab : 'Settings',
-log_tab : 'Log',
-content_tab : 'Content',
-command_states_tab : 'Commands',
-undo_redo_tab : 'Undo/Redo',
-misc_tab : 'Misc',
-filter : 'Filter:',
-clear_log : 'Clear log',
-refresh : 'Refresh',
-info_help : 'Press Refresh to view info.',
-settings_help : 'Press Refresh to display the settings array for each TinyMCE_Control instance.',
-content_help : 'Press Refresh to display the raw and cleaned HTML content for each TinyMCE_Control instance.',
-command_states_help : 'Press Refresh to display the current command states from inst.queryCommandState. This list will also mark unsupported commands.',
-undo_redo_help : 'Press Refresh to display the global and instance undo/redo levels.',
-misc_help : 'Here are various tools for debugging and development purposes.',
-debug_events : 'Debug events',
-undo_diff : 'Diff undo levels'
-});
--- a/includes/clientside/tinymce/plugins/directionality/editor_plugin.js	Fri Feb 22 12:46:51 2008 -0500
+++ b/includes/clientside/tinymce/plugins/directionality/editor_plugin.js	Fri Feb 22 12:51:53 2008 -0500
@@ -1,1 +1,1 @@
-tinyMCE.importPluginLanguagePack('directionality');var TinyMCE_DirectionalityPlugin={getInfo:function(){return{longname:'Directionality',author:'Moxiecode Systems AB',authorurl:'http://tinymce.moxiecode.com',infourl:'http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/directionality',version:tinyMCE.majorVersion+"."+tinyMCE.minorVersion}},getControlHTML:function(cn){switch(cn){case"ltr":return tinyMCE.getButtonHTML(cn,'lang_directionality_ltr_desc','{$pluginurl}/images/ltr.gif','mceDirectionLTR');case"rtl":return tinyMCE.getButtonHTML(cn,'lang_directionality_rtl_desc','{$pluginurl}/images/rtl.gif','mceDirectionRTL')}return""},execCommand:function(editor_id,element,command,user_interface,value){switch(command){case"mceDirectionLTR":var inst=tinyMCE.getInstanceById(editor_id);var elm=tinyMCE.getParentElement(inst.getFocusElement(),"p,div,td,h1,h2,h3,h4,h5,h6,pre,address");if(elm)elm.setAttribute("dir","ltr");tinyMCE.triggerNodeChange(false);return true;case"mceDirectionRTL":var inst=tinyMCE.getInstanceById(editor_id);var elm=tinyMCE.getParentElement(inst.getFocusElement(),"p,div,td,h1,h2,h3,h4,h5,h6,pre,address");if(elm)elm.setAttribute("dir","rtl");tinyMCE.triggerNodeChange(false);return true}return false},handleNodeChange:function(editor_id,node,undo_index,undo_levels,visual_aid,any_selection){function getAttrib(elm,name){return elm.getAttribute(name)?elm.getAttribute(name):""}if(node==null)return;var elm=tinyMCE.getParentElement(node,"p,div,td,h1,h2,h3,h4,h5,h6,pre,address");if(!elm){tinyMCE.switchClass(editor_id+'_ltr','mceButtonDisabled');tinyMCE.switchClass(editor_id+'_rtl','mceButtonDisabled');return true}tinyMCE.switchClass(editor_id+'_ltr','mceButtonNormal');tinyMCE.switchClass(editor_id+'_rtl','mceButtonNormal');var dir=getAttrib(elm,"dir");if(dir=="ltr"||dir=="")tinyMCE.switchClass(editor_id+'_ltr','mceButtonSelected');else tinyMCE.switchClass(editor_id+'_rtl','mceButtonSelected');return true}};tinyMCE.addPlugin("directionality",TinyMCE_DirectionalityPlugin);
\ No newline at end of file
+(function(){tinymce.create('tinymce.plugins.Directionality',{init:function(ed,url){var t=this;t.editor=ed;ed.addCommand('mceDirectionLTR',function(){var e=ed.dom.getParent(ed.selection.getNode(),ed.dom.isBlock);if(e){if(ed.dom.getAttrib(e,"dir")!="ltr")ed.dom.setAttrib(e,"dir","ltr");else ed.dom.setAttrib(e,"dir","");}ed.nodeChanged();});ed.addCommand('mceDirectionRTL',function(){var e=ed.dom.getParent(ed.selection.getNode(),ed.dom.isBlock);if(e){if(ed.dom.getAttrib(e,"dir")!="rtl")ed.dom.setAttrib(e,"dir","rtl");else ed.dom.setAttrib(e,"dir","");}ed.nodeChanged();});ed.addButton('ltr',{title:'directionality.ltr_desc',cmd:'mceDirectionLTR'});ed.addButton('rtl',{title:'directionality.rtl_desc',cmd:'mceDirectionRTL'});ed.onNodeChange.add(t._nodeChange,t);},getInfo:function(){return{longname:'Directionality',author:'Moxiecode Systems AB',authorurl:'http://tinymce.moxiecode.com',infourl:'http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/directionality',version:tinymce.majorVersion+"."+tinymce.minorVersion};},_nodeChange:function(ed,cm,n){var dom=ed.dom,dir;n=dom.getParent(n,dom.isBlock);if(!n){cm.setDisabled('ltr',1);cm.setDisabled('rtl',1);return;}dir=dom.getAttrib(n,'dir');cm.setActive('ltr',dir=="ltr");cm.setDisabled('ltr',0);cm.setActive('rtl',dir=="rtl");cm.setDisabled('rtl',0);}});tinymce.PluginManager.add('directionality',tinymce.plugins.Directionality);})();
\ No newline at end of file
--- a/includes/clientside/tinymce/plugins/directionality/editor_plugin_src.js	Fri Feb 22 12:46:51 2008 -0500
+++ b/includes/clientside/tinymce/plugins/directionality/editor_plugin_src.js	Fri Feb 22 12:51:53 2008 -0500
@@ -1,90 +1,79 @@
 /**
- * $Id: editor_plugin_src.js 201 2007-02-12 15:56:56Z spocke $
+ * $Id: editor_plugin_src.js 520 2008-01-07 16:30:32Z spocke $
  *
  * @author Moxiecode
- * @copyright Copyright © 2004-2007, Moxiecode Systems AB, All rights reserved.
+ * @copyright Copyright © 2004-2008, Moxiecode Systems AB, All rights reserved.
  */
 
-/* Import plugin specific language pack */
-tinyMCE.importPluginLanguagePack('directionality');
+(function() {
+	tinymce.create('tinymce.plugins.Directionality', {
+		init : function(ed, url) {
+			var t = this;
+
+			t.editor = ed;
 
-var TinyMCE_DirectionalityPlugin = {
-	getInfo : function() {
-		return {
-			longname : 'Directionality',
-			author : 'Moxiecode Systems AB',
-			authorurl : 'http://tinymce.moxiecode.com',
-			infourl : 'http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/directionality',
-			version : tinyMCE.majorVersion + "." + tinyMCE.minorVersion
-		};
-	},
+			ed.addCommand('mceDirectionLTR', function() {
+				var e = ed.dom.getParent(ed.selection.getNode(), ed.dom.isBlock);
 
-	getControlHTML : function(cn) {
-		switch (cn) {
-			case "ltr":
-				return tinyMCE.getButtonHTML(cn, 'lang_directionality_ltr_desc', '{$pluginurl}/images/ltr.gif', 'mceDirectionLTR');
+				if (e) {
+					if (ed.dom.getAttrib(e, "dir") != "ltr")
+						ed.dom.setAttrib(e, "dir", "ltr");
+					else
+						ed.dom.setAttrib(e, "dir", "");
+				}
 
-			case "rtl":
-				return tinyMCE.getButtonHTML(cn, 'lang_directionality_rtl_desc', '{$pluginurl}/images/rtl.gif', 'mceDirectionRTL');
-		}
+				ed.nodeChanged();
+			});
 
-		return "";
-	},
+			ed.addCommand('mceDirectionRTL', function() {
+				var e = ed.dom.getParent(ed.selection.getNode(), ed.dom.isBlock);
 
-	execCommand : function(editor_id, element, command, user_interface, value) {
-		// Handle commands
-		switch (command) {
-			case "mceDirectionLTR":
-				var inst = tinyMCE.getInstanceById(editor_id);
-				var elm = tinyMCE.getParentElement(inst.getFocusElement(), "p,div,td,h1,h2,h3,h4,h5,h6,pre,address");
+				if (e) {
+					if (ed.dom.getAttrib(e, "dir") != "rtl")
+						ed.dom.setAttrib(e, "dir", "rtl");
+					else
+						ed.dom.setAttrib(e, "dir", "");
+				}
 
-				if (elm)
-					elm.setAttribute("dir", "ltr");
+				ed.nodeChanged();
+			});
 
-				tinyMCE.triggerNodeChange(false);
-				return true;
+			ed.addButton('ltr', {title : 'directionality.ltr_desc', cmd : 'mceDirectionLTR'});
+			ed.addButton('rtl', {title : 'directionality.rtl_desc', cmd : 'mceDirectionRTL'});
 
-			case "mceDirectionRTL":
-				var inst = tinyMCE.getInstanceById(editor_id);
-				var elm = tinyMCE.getParentElement(inst.getFocusElement(), "p,div,td,h1,h2,h3,h4,h5,h6,pre,address");
-
-				if (elm)
-					elm.setAttribute("dir", "rtl");
+			ed.onNodeChange.add(t._nodeChange, t);
+		},
 
-				tinyMCE.triggerNodeChange(false);
-				return true;
-		}
+		getInfo : function() {
+			return {
+				longname : 'Directionality',
+				author : 'Moxiecode Systems AB',
+				authorurl : 'http://tinymce.moxiecode.com',
+				infourl : 'http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/directionality',
+				version : tinymce.majorVersion + "." + tinymce.minorVersion
+			};
+		},
 
-		// Pass to next handler in chain
-		return false;
-	},
+		// Private methods
 
-	handleNodeChange : function(editor_id, node, undo_index, undo_levels, visual_aid, any_selection) {
-		function getAttrib(elm, name) {
-			return elm.getAttribute(name) ? elm.getAttribute(name) : "";
-		}
+		_nodeChange : function(ed, cm, n) {
+			var dom = ed.dom, dir;
 
-		if (node == null)
-			return;
-
-		var elm = tinyMCE.getParentElement(node, "p,div,td,h1,h2,h3,h4,h5,h6,pre,address");
-		if (!elm) {
-			tinyMCE.switchClass(editor_id + '_ltr', 'mceButtonDisabled');
-			tinyMCE.switchClass(editor_id + '_rtl', 'mceButtonDisabled');
-			return true;
-		}
+			n = dom.getParent(n, dom.isBlock);
+			if (!n) {
+				cm.setDisabled('ltr', 1);
+				cm.setDisabled('rtl', 1);
+				return;
+			}
 
-		tinyMCE.switchClass(editor_id + '_ltr', 'mceButtonNormal');
-		tinyMCE.switchClass(editor_id + '_rtl', 'mceButtonNormal');
+			dir = dom.getAttrib(n, 'dir');
+			cm.setActive('ltr', dir == "ltr");
+			cm.setDisabled('ltr', 0);
+			cm.setActive('rtl', dir == "rtl");
+			cm.setDisabled('rtl', 0);
+		}
+	});
 
-		var dir = getAttrib(elm, "dir");
-		if (dir == "ltr" || dir == "")
-			tinyMCE.switchClass(editor_id + '_ltr', 'mceButtonSelected');
-		else
-			tinyMCE.switchClass(editor_id + '_rtl', 'mceButtonSelected');
-
-		return true;
-	}
-};
-
-tinyMCE.addPlugin("directionality", TinyMCE_DirectionalityPlugin);
+	// Register plugin
+	tinymce.PluginManager.add('directionality', tinymce.plugins.Directionality);
+})();
\ No newline at end of file
Binary file includes/clientside/tinymce/plugins/directionality/images/ltr.gif has changed
Binary file includes/clientside/tinymce/plugins/directionality/images/rtl.gif has changed
--- a/includes/clientside/tinymce/plugins/directionality/langs/en.js	Fri Feb 22 12:46:51 2008 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,6 +0,0 @@
-// UK lang variables
-
-tinyMCE.addToLang('',{
-directionality_ltr_desc : 'Direction left to right',
-directionality_rtl_desc : 'Direction right to left'
-});
--- a/includes/clientside/tinymce/plugins/directionality/readme.txt	Fri Feb 22 12:46:51 2008 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1 +0,0 @@
-Check the TinyMCE documentation for details on this plugin.
--- a/includes/clientside/tinymce/plugins/emotions/editor_plugin.js	Fri Feb 22 12:46:51 2008 -0500
+++ b/includes/clientside/tinymce/plugins/emotions/editor_plugin.js	Fri Feb 22 12:51:53 2008 -0500
@@ -1,1 +1,1 @@
-tinyMCE.importPluginLanguagePack('emotions');var TinyMCE_EmotionsPlugin={getInfo:function(){return{longname:'Emotions',author:'Moxiecode Systems AB',authorurl:'http://tinymce.moxiecode.com',infourl:'http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/emotions',version:tinyMCE.majorVersion+"."+tinyMCE.minorVersion}},getControlHTML:function(cn){switch(cn){case"emotions":return tinyMCE.getButtonHTML(cn,'lang_emotions_desc','{$pluginurl}/images/emotions.gif','mceEmotion')}return""},execCommand:function(editor_id,element,command,user_interface,value){switch(command){case"mceEmotion":var template=new Array();template['file']='../../plugins/emotions/emotions.htm';template['width']=250;template['height']=160;template['width']+=tinyMCE.getLang('lang_emotions_delta_width',0);template['height']+=tinyMCE.getLang('lang_emotions_delta_height',0);tinyMCE.openWindow(template,{editor_id:editor_id,inline:"yes"});return true}return false}};tinyMCE.addPlugin('emotions',TinyMCE_EmotionsPlugin);
\ No newline at end of file
+(function(){tinymce.create('tinymce.plugins.EmotionsPlugin',{init:function(ed,url){ed.addCommand('mceEmotion',function(){ed.windowManager.open({file:url+'/emotions.htm',width:250+parseInt(ed.getLang('emotions.delta_width',0)),height:160+parseInt(ed.getLang('emotions.delta_height',0)),inline:1},{plugin_url:url});});ed.addButton('emotions',{title:'emotions.emotions_desc',cmd:'mceEmotion'});},getInfo:function(){return{longname:'Emotions',author:'Moxiecode Systems AB',authorurl:'http://tinymce.moxiecode.com',infourl:'http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/emotions',version:tinymce.majorVersion+"."+tinymce.minorVersion};}});tinymce.PluginManager.add('emotions',tinymce.plugins.EmotionsPlugin);})();
\ No newline at end of file
--- a/includes/clientside/tinymce/plugins/emotions/editor_plugin_src.js	Fri Feb 22 12:46:51 2008 -0500
+++ b/includes/clientside/tinymce/plugins/emotions/editor_plugin_src.js	Fri Feb 22 12:51:53 2008 -0500
@@ -1,63 +1,40 @@
 /**
- * $Id: editor_plugin_src.js 201 2007-02-12 15:56:56Z spocke $
+ * $Id: editor_plugin_src.js 520 2008-01-07 16:30:32Z spocke $
  *
  * @author Moxiecode
- * @copyright Copyright © 2004-2007, Moxiecode Systems AB, All rights reserved.
+ * @copyright Copyright © 2004-2008, Moxiecode Systems AB, All rights reserved.
  */
 
-/* Import plugin specific language pack */
-tinyMCE.importPluginLanguagePack('emotions');
-
-// Plucin static class
-var TinyMCE_EmotionsPlugin = {
-	getInfo : function() {
-		return {
-			longname : 'Emotions',
-			author : 'Moxiecode Systems AB',
-			authorurl : 'http://tinymce.moxiecode.com',
-			infourl : 'http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/emotions',
-			version : tinyMCE.majorVersion + "." + tinyMCE.minorVersion
-		};
-	},
-
-	/**
-	 * Returns the HTML contents of the emotions control.
-	 */
-	getControlHTML : function(cn) {
-		switch (cn) {
-			case "emotions":
-				return tinyMCE.getButtonHTML(cn, 'lang_emotions_desc', '{$pluginurl}/images/emotions.gif', 'mceEmotion');
-		}
-
-		return "";
-	},
+(function() {
+	tinymce.create('tinymce.plugins.EmotionsPlugin', {
+		init : function(ed, url) {
+			// Register commands
+			ed.addCommand('mceEmotion', function() {
+				ed.windowManager.open({
+					file : url + '/emotions.htm',
+					width : 250 + parseInt(ed.getLang('emotions.delta_width', 0)),
+					height : 160 + parseInt(ed.getLang('emotions.delta_height', 0)),
+					inline : 1
+				}, {
+					plugin_url : url
+				});
+			});
 
-	/**
-	 * Executes the mceEmotion command.
-	 */
-	execCommand : function(editor_id, element, command, user_interface, value) {
-		// Handle commands
-		switch (command) {
-			case "mceEmotion":
-				var template = new Array();
-
-				template['file'] = '../../plugins/emotions/emotions.htm'; // Relative to theme
-				template['width'] = 250;
-				template['height'] = 160;
+			// Register buttons
+			ed.addButton('emotions', {title : 'emotions.emotions_desc', cmd : 'mceEmotion'});
+		},
 
-				// Language specific width and height addons
-				template['width'] += tinyMCE.getLang('lang_emotions_delta_width', 0);
-				template['height'] += tinyMCE.getLang('lang_emotions_delta_height', 0);
-
-				tinyMCE.openWindow(template, {editor_id : editor_id, inline : "yes"});
-
-				return true;
+		getInfo : function() {
+			return {
+				longname : 'Emotions',
+				author : 'Moxiecode Systems AB',
+				authorurl : 'http://tinymce.moxiecode.com',
+				infourl : 'http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/emotions',
+				version : tinymce.majorVersion + "." + tinymce.minorVersion
+			};
 		}
+	});
 
-		// Pass to next handler in chain
-		return false;
-	}
-};
-
-// Register plugin
-tinyMCE.addPlugin('emotions', TinyMCE_EmotionsPlugin);
+	// Register plugin
+	tinymce.PluginManager.add('emotions', tinymce.plugins.EmotionsPlugin);
+})();
\ No newline at end of file
--- a/includes/clientside/tinymce/plugins/emotions/emotions.htm	Fri Feb 22 12:46:51 2008 -0500
+++ b/includes/clientside/tinymce/plugins/emotions/emotions.htm	Fri Feb 22 12:51:53 2008 -0500
@@ -1,38 +1,39 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
 <html xmlns="http://www.w3.org/1999/xhtml">
 <head>
-	<title>{$lang_emotions_title}</title>
-	<script language="javascript" type="text/javascript" src="../../tiny_mce_popup.js"></script>
-	<script language="javascript" type="text/javascript" src="jscripts/functions.js"></script>
+	<title>{#emotions_dlg.title}</title>
+	<script type="text/javascript" src="../../tiny_mce_popup.js"></script>
+	<script type="text/javascript" src="js/emotions.js"></script>
 	<base target="_self" />
 </head>
-<body onload="tinyMCEPopup.executeOnLoad('init();');" style="display: none">
+<body style="display: none">
 	<div align="center">
-		<div class="title">{$lang_emotions_title}:<br /><br /></div>
+		<div class="title">{#emotions_dlg.title}:<br /><br /></div>
 
 		<table border="0" cellspacing="0" cellpadding="4">
 		  <tr>
-			<td><a href="javascript:insertEmotion('smiley-cool.gif','lang_emotions_cool');"><img src="images/smiley-cool.gif" width="18" height="18" border="0" alt="{$lang_emotions_cool}" title="{$lang_emotions_cool}" /></a></td>
-			<td><a href="javascript:insertEmotion('smiley-cry.gif','lang_emotions_cry');"><img src="images/smiley-cry.gif" width="18" height="18" border="0" alt="{$lang_emotions_cry}" title="{$lang_emotions_cry}" /></a></td>
-			<td><a href="javascript:insertEmotion('smiley-embarassed.gif','lang_emotions_embarassed');"><img src="images/smiley-embarassed.gif" width="18" height="18" border="0" alt="{$lang_emotions_embarassed}" title="{$lang_emotions_embarassed}" /></a></td>
-			<td><a href="javascript:insertEmotion('smiley-foot-in-mouth.gif','lang_emotions_foot_in_mouth');"><img src="images/smiley-foot-in-mouth.gif" width="18" height="18" border="0" alt="{$lang_emotions_foot_in_mouth}" title="{$lang_emotions_foot_in_mouth}" /></a></td>
+			<td><a href="javascript:EmotionsDialog.insert('smiley-cool.gif','emotions_dlg.cool');"><img src="img/smiley-cool.gif" width="18" height="18" border="0" alt="{#emotions_dlg.cool}" title="{#emotions_dlg.cool}" /></a></td>
+			<td><a href="javascript:EmotionsDialog.insert('smiley-cry.gif','emotions_dlg.cry');"><img src="img/smiley-cry.gif" width="18" height="18" border="0" alt="{#emotions_dlg.cry}" title="{#emotions_dlg.cry}" /></a></td>
+			<td><a href="javascript:EmotionsDialog.insert('smiley-embarassed.gif','emotions_dlg.embarassed');"><img src="img/smiley-embarassed.gif" width="18" height="18" border="0" alt="{#emotions_dlg.embarassed}" title="{#emotions_dlg.embarassed}" /></a></td>
+			<td><a href="javascript:EmotionsDialog.insert('smiley-foot-in-mouth.gif','emotions_dlg.foot_in_mouth');"><img src="img/smiley-foot-in-mouth.gif" width="18" height="18" border="0" alt="{#emotions_dlg.foot_in_mouth}" title="{#emotions_dlg.foot_in_mouth}" /></a></td>
 		  </tr>
 		  <tr>
-			<td><a href="javascript:insertEmotion('smiley-frown.gif','lang_emotions_frown');"><img src="images/smiley-frown.gif" width="18" height="18" border="0" alt="{$lang_emotions_frown}" title="{$lang_emotions_frown}" /></a></td>
-			<td><a href="javascript:insertEmotion('smiley-innocent.gif','lang_emotions_innocent');"><img src="images/smiley-innocent.gif" width="18" height="18" border="0" alt="{$lang_emotions_innocent}" title="{$lang_emotions_innocent}" /></a></td>
-			<td><a href="javascript:insertEmotion('smiley-kiss.gif','lang_emotions_kiss');"><img src="images/smiley-kiss.gif" width="18" height="18" border="0" alt="{$lang_emotions_kiss}" title="{$lang_emotions_kiss}" /></a></td>
-			<td><a href="javascript:insertEmotion('smiley-laughing.gif','lang_emotions_laughing');"><img src="images/smiley-laughing.gif" width="18" height="18" border="0" alt="{$lang_emotions_laughing}" title="{$lang_emotions_laughing}" /></a></td>
+			<td><a href="javascript:EmotionsDialog.insert('smiley-frown.gif','emotions_dlg.frown');"><img src="img/smiley-frown.gif" width="18" height="18" border="0" alt="{#emotions_dlg.frown}" title="{#emotions_dlg.frown}" /></a></td>
+			<td><a href="javascript:EmotionsDialog.insert('smiley-innocent.gif','emotions_dlg.innocent');"><img src="img/smiley-innocent.gif" width="18" height="18" border="0" alt="{#emotions_dlg.innocent}" title="{#emotions_dlg.innocent}" /></a></td>
+			<td><a href="javascript:EmotionsDialog.insert('smiley-kiss.gif','emotions_dlg.kiss');"><img src="img/smiley-kiss.gif" width="18" height="18" border="0" alt="{#emotions_dlg.kiss}" title="{#emotions_dlg.kiss}" /></a></td>
+			<td><a href="javascript:EmotionsDialog.insert('smiley-laughing.gif','emotions_dlg.laughing');"><img src="img/smiley-laughing.gif" width="18" height="18" border="0" alt="{#emotions_dlg.laughing}" title="{#emotions_dlg.laughing}" /></a></td>
 		  </tr>
 		  <tr>
-			<td><a href="javascript:insertEmotion('smiley-money-mouth.gif','lang_emotions_money_mouth');"><img src="images/smiley-money-mouth.gif" width="18" height="18" border="0" alt="{$lang_emotions_money_mouth}" title="{$lang_emotions_money_mouth}" /></a></td>
-			<td><a href="javascript:insertEmotion('smiley-sealed.gif','lang_emotions_sealed');"><img src="images/smiley-sealed.gif" width="18" height="18" border="0" alt="{$lang_emotions_sealed}" title="{$lang_emotions_sealed}" /></a></td>
-			<td><a href="javascript:insertEmotion('smiley-smile.gif','lang_emotions_smile');"><img src="images/smiley-smile.gif" width="18" height="18" border="0" alt="{$lang_emotions_smile}" title="{$lang_emotions_smile}" /></a></td>
-			<td><a href="javascript:insertEmotion('smiley-surprised.gif','lang_emotions_surprised');"><img src="images/smiley-surprised.gif" width="18" height="18" border="0" alt="{$lang_emotions_surprised}" title="{$lang_emotions_surprised}" /></a></td>
+			<td><a href="javascript:EmotionsDialog.insert('smiley-money-mouth.gif','emotions_dlg.money_mouth');"><img src="img/smiley-money-mouth.gif" width="18" height="18" border="0" alt="{#emotions_dlg.money_mouth}" title="{#emotions_dlg.money_mouth}" /></a></td>
+			<td><a href="javascript:EmotionsDialog.insert('smiley-sealed.gif','emotions_dlg.sealed');"><img src="img/smiley-sealed.gif" width="18" height="18" border="0" alt="{#emotions_dlg.sealed}" title="{#emotions_dlg.sealed}" /></a></td>
+			<td><a href="javascript:EmotionsDialog.insert('smiley-smile.gif','emotions_dlg.smile');"><img src="img/smiley-smile.gif" width="18" height="18" border="0" alt="{#emotions_dlg.smile}" title="{#emotions_dlg.smile}" /></a></td>
+			<td><a href="javascript:EmotionsDialog.insert('smiley-surprised.gif','emotions_dlg.surprised');"><img src="img/smiley-surprised.gif" width="18" height="18" border="0" alt="{#emotions_dlg.surprised}" title="{#emotions_dlg.surprised}" /></a></td>
 		  </tr>
 		  <tr>
-			<td><a href="javascript:insertEmotion('smiley-tongue-out.gif','lang_emotions_tongue_out');"><img src="images/smiley-tongue-out.gif" width="18" height="18" border="0" alt="{$lang_emotions_tongue-out}" title="{$lang_emotions_tongue_out}" /></a></td>
-			<td><a href="javascript:insertEmotion('smiley-undecided.gif','lang_emotions_undecided');"><img src="images/smiley-undecided.gif" width="18" height="18" border="0" alt="{$lang_emotions_undecided}" title="{$lang_emotions_undecided}" /></a></td>
-			<td><a href="javascript:insertEmotion('smiley-wink.gif','lang_emotions_wink');"><img src="images/smiley-wink.gif" width="18" height="18" border="0" alt="{$lang_emotions_wink}" title="{$lang_emotions_wink}" /></a></td>
-			<td><a href="javascript:insertEmotion('smiley-yell.gif','lang_emotions_yell');"><img src="images/smiley-yell.gif" width="18" height="18" border="0" alt="{$lang_emotions_yell}" title="{$lang_emotions_yell}" /></a></td>
+			<td><a href="javascript:EmotionsDialog.insert('smiley-tongue-out.gif','emotions_dlg.tongue_out');"><img src="img/smiley-tongue-out.gif" width="18" height="18" border="0" alt="{#emotions_dlg.tongue-out}" title="{#emotions_dlg.tongue_out}" /></a></td>
+			<td><a href="javascript:EmotionsDialog.insert('smiley-undecided.gif','emotions_dlg.undecided');"><img src="img/smiley-undecided.gif" width="18" height="18" border="0" alt="{#emotions_dlg.undecided}" title="{#emotions_dlg.undecided}" /></a></td>
+			<td><a href="javascript:EmotionsDialog.insert('smiley-wink.gif','emotions_dlg.wink');"><img src="img/smiley-wink.gif" width="18" height="18" border="0" alt="{#emotions_dlg.wink}" title="{#emotions_dlg.wink}" /></a></td>
+			<td><a href="javascript:EmotionsDialog.insert('smiley-yell.gif','emotions_dlg.yell');"><img src="img/smiley-yell.gif" width="18" height="18" border="0" alt="{#emotions_dlg.yell}" title="{#emotions_dlg.yell}" /></a></td>
 		  </tr>
 		</table>
 	</div>
Binary file includes/clientside/tinymce/plugins/emotions/images/emotions.gif has changed
--- a/includes/clientside/tinymce/plugins/emotions/images/readme.txt	Fri Feb 22 12:46:51 2008 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,2 +0,0 @@
-These emotions where taken from Mozilla Thunderbird.
-I hope they don't get angry if I use them here after all this is a open source project aswell.
Binary file includes/clientside/tinymce/plugins/emotions/images/smiley-cool.gif has changed
Binary file includes/clientside/tinymce/plugins/emotions/images/smiley-cry.gif has changed
Binary file includes/clientside/tinymce/plugins/emotions/images/smiley-embarassed.gif has changed
Binary file includes/clientside/tinymce/plugins/emotions/images/smiley-foot-in-mouth.gif has changed
Binary file includes/clientside/tinymce/plugins/emotions/images/smiley-frown.gif has changed
Binary file includes/clientside/tinymce/plugins/emotions/images/smiley-innocent.gif has changed
Binary file includes/clientside/tinymce/plugins/emotions/images/smiley-kiss.gif has changed
Binary file includes/clientside/tinymce/plugins/emotions/images/smiley-laughing.gif has changed
Binary file includes/clientside/tinymce/plugins/emotions/images/smiley-money-mouth.gif has changed
Binary file includes/clientside/tinymce/plugins/emotions/images/smiley-sealed.gif has changed
Binary file includes/clientside/tinymce/plugins/emotions/images/smiley-smile.gif has changed
Binary file includes/clientside/tinymce/plugins/emotions/images/smiley-surprised.gif has changed
Binary file includes/clientside/tinymce/plugins/emotions/images/smiley-tongue-out.gif has changed
Binary file includes/clientside/tinymce/plugins/emotions/images/smiley-undecided.gif has changed
Binary file includes/clientside/tinymce/plugins/emotions/images/smiley-wink.gif has changed
Binary file includes/clientside/tinymce/plugins/emotions/images/smiley-yell.gif has changed
Binary file includes/clientside/tinymce/plugins/emotions/img/smiley-cool.gif has changed
Binary file includes/clientside/tinymce/plugins/emotions/img/smiley-cry.gif has changed
Binary file includes/clientside/tinymce/plugins/emotions/img/smiley-embarassed.gif has changed
Binary file includes/clientside/tinymce/plugins/emotions/img/smiley-foot-in-mouth.gif has changed
Binary file includes/clientside/tinymce/plugins/emotions/img/smiley-frown.gif has changed
Binary file includes/clientside/tinymce/plugins/emotions/img/smiley-innocent.gif has changed
Binary file includes/clientside/tinymce/plugins/emotions/img/smiley-kiss.gif has changed
Binary file includes/clientside/tinymce/plugins/emotions/img/smiley-laughing.gif has changed
Binary file includes/clientside/tinymce/plugins/emotions/img/smiley-money-mouth.gif has changed
Binary file includes/clientside/tinymce/plugins/emotions/img/smiley-sealed.gif has changed
Binary file includes/clientside/tinymce/plugins/emotions/img/smiley-smile.gif has changed
Binary file includes/clientside/tinymce/plugins/emotions/img/smiley-surprised.gif has changed
Binary file includes/clientside/tinymce/plugins/emotions/img/smiley-tongue-out.gif has changed
Binary file includes/clientside/tinymce/plugins/emotions/img/smiley-undecided.gif has changed
Binary file includes/clientside/tinymce/plugins/emotions/img/smiley-wink.gif has changed
Binary file includes/clientside/tinymce/plugins/emotions/img/smiley-yell.gif has changed
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/includes/clientside/tinymce/plugins/emotions/js/emotions.js	Fri Feb 22 12:51:53 2008 -0500
@@ -0,0 +1,22 @@
+tinyMCEPopup.requireLangPack();
+
+var EmotionsDialog = {
+	init : function(ed) {
+		tinyMCEPopup.resizeToInnerSize();
+	},
+
+	insert : function(file, title) {
+		var ed = tinyMCEPopup.editor, dom = ed.dom;
+
+		tinyMCEPopup.execCommand('mceInsertContent', false, dom.createHTML('img', {
+			src : tinyMCEPopup.getWindowArg('plugin_url') + '/img/' + file,
+			alt : ed.getLang(title),
+			title : ed.getLang(title),
+			border : 0
+		}));
+
+		tinyMCEPopup.close();
+	}
+};
+
+tinyMCEPopup.onInit.add(EmotionsDialog.init, EmotionsDialog);
--- a/includes/clientside/tinymce/plugins/emotions/jscripts/functions.js	Fri Feb 22 12:46:51 2008 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,21 +0,0 @@
-function init() {
-	tinyMCEPopup.resizeToInnerSize();
-}
-
-function insertEmotion(file_name, title) {
-	title = tinyMCE.getLang(title);
-
-	if (title == null)
-		title = "";
-
-	// XML encode
-	title = title.replace(/&/g, '&amp;');
-	title = title.replace(/\"/g, '&quot;');
-	title = title.replace(/</g, '&lt;');
-	title = title.replace(/>/g, '&gt;');
-
-	var html = '<img src="' + tinyMCE.baseURL + "/plugins/emotions/images/" + file_name + '" mce_src="' + tinyMCE.baseURL + "/plugins/emotions/images/" + file_name + '" border="0" alt="' + title + '" title="' + title + '" />';
-
-	tinyMCE.execCommand('mceInsertContent', false, html);
-	tinyMCEPopup.close();
-}
--- a/includes/clientside/tinymce/plugins/emotions/langs/en.js	Fri Feb 22 12:46:51 2008 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,22 +0,0 @@
-// UK lang variables
-
-tinyMCE.addToLang('emotions',{
-title : 'Insert emotion',
-desc : 'Emotions',
-cool : 'Cool',
-cry : 'Cry',
-embarassed : 'Embarassed',
-foot_in_mouth : 'Foot in mouth',
-frown : 'Frown',
-innocent : 'Innocent',
-kiss : 'Kiss',
-laughing : 'Laughing',
-money_mouth : 'Money mouth',
-sealed : 'Sealed',
-smile : 'Smile',
-surprised : 'Surprised',
-tongue_out : 'Tongue out',
-undecided : 'Undecided',
-wink : 'Wink',
-yell : 'Yell'
-});
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/includes/clientside/tinymce/plugins/emotions/langs/en_dlg.js	Fri Feb 22 12:51:53 2008 -0500
@@ -0,0 +1,20 @@
+tinyMCE.addI18n('en.emotions_dlg',{
+title:"Insert emotion",
+desc:"Emotions",
+cool:"Cool",
+cry:"Cry",
+embarassed:"Embarassed",
+foot_in_mouth:"Foot in mouth",
+frown:"Frown",
+innocent:"Innocent",
+kiss:"Kiss",
+laughing:"Laughing",
+money_mouth:"Money mouth",
+sealed:"Sealed",
+smile:"Smile",
+surprised:"Surprised",
+tongue_out:"Tongue out",
+undecided:"Undecided",
+wink:"Wink",
+yell:"Yell"
+});
\ No newline at end of file
--- a/includes/clientside/tinymce/plugins/emotions/readme.txt	Fri Feb 22 12:46:51 2008 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1 +0,0 @@
-Check the TinyMCE documentation for details on this plugin.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/includes/clientside/tinymce/plugins/example/dialog.htm	Fri Feb 22 12:51:53 2008 -0500
@@ -0,0 +1,27 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+	<title>{#example_dlg.title}</title>
+	<script type="text/javascript" src="../../tiny_mce_popup.js"></script>
+	<script type="text/javascript" src="js/dialog.js"></script>
+</head>
+<body>
+
+<form onsubmit="ExampleDialog.insert();return false;" action="#">
+	<p>Here is a example dialog.</p>
+	<p>Selected text: <input id="someval" name="someval" type="text" class="text" /></p>
+	<p>Custom arg: <input id="somearg" name="somearg" type="text" class="text" /></p>
+
+	<div class="mceActionPanel">
+		<div style="float: left">
+			<input type="button" id="insert" name="insert" value="{#insert}" onclick="ExampleDialog.insert();" />
+		</div>
+
+		<div style="float: right">
+			<input type="button" id="cancel" name="cancel" value="{#cancel}" onclick="tinyMCEPopup.close();" />
+		</div>
+	</div>
+</form>
+
+</body>
+</html>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/includes/clientside/tinymce/plugins/example/editor_plugin.js	Fri Feb 22 12:51:53 2008 -0500
@@ -0,0 +1,1 @@
+(function(){tinymce.PluginManager.requireLangPack('example');tinymce.create('tinymce.plugins.ExamplePlugin',{init:function(ed,url){ed.addCommand('mceExample',function(){ed.windowManager.open({file:url+'/dialog.htm',width:320+parseInt(ed.getLang('example.delta_width',0)),height:120+parseInt(ed.getLang('example.delta_height',0)),inline:1},{plugin_url:url,some_custom_arg:'custom arg'});});ed.addButton('example',{title:'example.desc',cmd:'mceExample',image:url+'/img/example.gif'});ed.onNodeChange.add(function(ed,cm,n){cm.setActive('example',n.nodeName=='IMG');});},createControl:function(n,cm){return null;},getInfo:function(){return{longname:'Example plugin',author:'Some author',authorurl:'http://tinymce.moxiecode.com',infourl:'http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/example',version:"1.0"};}});tinymce.PluginManager.add('example',tinymce.plugins.ExamplePlugin);})();
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/includes/clientside/tinymce/plugins/example/editor_plugin_src.js	Fri Feb 22 12:51:53 2008 -0500
@@ -0,0 +1,81 @@
+/**
+ * $Id: editor_plugin_src.js 201 2007-02-12 15:56:56Z spocke $
+ *
+ * @author Moxiecode
+ * @copyright Copyright © 2004-2008, Moxiecode Systems AB, All rights reserved.
+ */
+
+(function() {
+	// Load plugin specific language pack
+	tinymce.PluginManager.requireLangPack('example');
+
+	tinymce.create('tinymce.plugins.ExamplePlugin', {
+		/**
+		 * Initializes the plugin, this will be executed after the plugin has been created.
+		 * This call is done before the editor instance has finished it's initialization so use the onInit event
+		 * of the editor instance to intercept that event.
+		 *
+		 * @param {tinymce.Editor} ed Editor instance that the plugin is initialized in.
+		 * @param {string} url Absolute URL to where the plugin is located.
+		 */
+		init : function(ed, url) {
+			// Register the command so that it can be invoked by using tinyMCE.activeEditor.execCommand('mceExample');
+			ed.addCommand('mceExample', function() {
+				ed.windowManager.open({
+					file : url + '/dialog.htm',
+					width : 320 + parseInt(ed.getLang('example.delta_width', 0)),
+					height : 120 + parseInt(ed.getLang('example.delta_height', 0)),
+					inline : 1
+				}, {
+					plugin_url : url, // Plugin absolute URL
+					some_custom_arg : 'custom arg' // Custom argument
+				});
+			});
+
+			// Register example button
+			ed.addButton('example', {
+				title : 'example.desc',
+				cmd : 'mceExample',
+				image : url + '/img/example.gif'
+			});
+
+			// Add a node change handler, selects the button in the UI when a image is selected
+			ed.onNodeChange.add(function(ed, cm, n) {
+				cm.setActive('example', n.nodeName == 'IMG');
+			});
+		},
+
+		/**
+		 * Creates control instances based in the incomming name. This method is normally not
+		 * needed since the addButton method of the tinymce.Editor class is a more easy way of adding buttons
+		 * but you sometimes need to create more complex controls like listboxes, split buttons etc then this
+		 * method can be used to create those.
+		 *
+		 * @param {String} n Name of the control to create.
+		 * @param {tinymce.ControlManager} cm Control manager to use inorder to create new control.
+		 * @return {tinymce.ui.Control} New control instance or null if no control was created.
+		 */
+		createControl : function(n, cm) {
+			return null;
+		},
+
+		/**
+		 * Returns information about the plugin as a name/value array.
+		 * The current keys are longname, author, authorurl, infourl and version.
+		 *
+		 * @return {Object} Name/value array containing information about the plugin.
+		 */
+		getInfo : function() {
+			return {
+				longname : 'Example plugin',
+				author : 'Some author',
+				authorurl : 'http://tinymce.moxiecode.com',
+				infourl : 'http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/example',
+				version : "1.0"
+			};
+		}
+	});
+
+	// Register plugin
+	tinymce.PluginManager.add('example', tinymce.plugins.ExamplePlugin);
+})();
\ No newline at end of file
Binary file includes/clientside/tinymce/plugins/example/img/example.gif has changed
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/includes/clientside/tinymce/plugins/example/js/dialog.js	Fri Feb 22 12:51:53 2008 -0500
@@ -0,0 +1,19 @@
+tinyMCEPopup.requireLangPack();
+
+var ExampleDialog = {
+	init : function() {
+		var f = document.forms[0];
+
+		// Get the selected contents as text and place it in the input
+		f.someval.value = tinyMCEPopup.editor.selection.getContent({format : 'text'});
+		f.somearg.value = tinyMCEPopup.getWindowArg('some_custom_arg');
+	},
+
+	insert : function() {
+		// Insert the contents from the input into the document
+		tinyMCEPopup.editor.execCommand('mceInsertContent', false, document.forms[0].someval.value);
+		tinyMCEPopup.close();
+	}
+};
+
+tinyMCEPopup.onInit.add(ExampleDialog.init, ExampleDialog);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/includes/clientside/tinymce/plugins/example/langs/en.js	Fri Feb 22 12:51:53 2008 -0500
@@ -0,0 +1,3 @@
+tinyMCE.addI18n('en.example',{
+	desc : 'This is just a template button'
+});
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/includes/clientside/tinymce/plugins/example/langs/en_dlg.js	Fri Feb 22 12:51:53 2008 -0500
@@ -0,0 +1,3 @@
+tinyMCE.addI18n('en.example_dlg',{
+	title : 'This is just a example title'
+});
--- a/includes/clientside/tinymce/plugins/flash/css/content.css	Fri Feb 22 12:46:51 2008 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,7 +0,0 @@
-.mceItemFlash {
-	border: 1px dotted #cc0000;
-	background-image: url('../images/flash.gif');
-	background-position: center;
-	background-repeat: no-repeat;
-	background-color: #ffffcc;
-}
--- a/includes/clientside/tinymce/plugins/flash/css/flash.css	Fri Feb 22 12:46:51 2008 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,11 +0,0 @@
-.panel_wrapper div.current {
-	height: 100px;
-}
-
-#width, #height {
-	width: 50px;
-}
-
-#file {
-	width: 250px;
-}
--- a/includes/clientside/tinymce/plugins/flash/editor_plugin.js	Fri Feb 22 12:46:51 2008 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1 +0,0 @@
-tinyMCE.importPluginLanguagePack('flash');var TinyMCE_FlashPlugin={getInfo:function(){return{longname:'Flash',author:'Moxiecode Systems AB',authorurl:'http://tinymce.moxiecode.com',infourl:'http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/flash',version:tinyMCE.majorVersion+"."+tinyMCE.minorVersion}},initInstance:function(inst){if(!tinyMCE.settings['flash_skip_plugin_css'])tinyMCE.importCSS(inst.getDoc(),tinyMCE.baseURL+"/plugins/flash/css/content.css")},getControlHTML:function(cn){switch(cn){case"flash":return tinyMCE.getButtonHTML(cn,'lang_flash_desc','{$pluginurl}/images/flash.gif','mceFlash')}return""},execCommand:function(editor_id,element,command,user_interface,value){switch(command){case"mceFlash":var name="",swffile="",swfwidth="",swfheight="",action="insert";var template=new Array();var inst=tinyMCE.getInstanceById(editor_id);var focusElm=inst.getFocusElement();template['file']='../../plugins/flash/flash.htm';template['width']=430;template['height']=175;template['width']+=tinyMCE.getLang('lang_flash_delta_width',0);template['height']+=tinyMCE.getLang('lang_flash_delta_height',0);if(focusElm!=null&&focusElm.nodeName.toLowerCase()=="img"){name=tinyMCE.getAttrib(focusElm,'class');if(name.indexOf('mceItemFlash')==-1)return true;swffile=tinyMCE.getAttrib(focusElm,'alt');if(tinyMCE.getParam('convert_urls'))swffile=eval(tinyMCE.settings['urlconverter_callback']+"(swffile, null, true);");swfwidth=tinyMCE.getAttrib(focusElm,'width');swfheight=tinyMCE.getAttrib(focusElm,'height');action="update"}tinyMCE.openWindow(template,{editor_id:editor_id,inline:"yes",swffile:swffile,swfwidth:swfwidth,swfheight:swfheight,action:action});return true}return false},cleanup:function(type,content){switch(type){case"insert_to_editor_dom":if(tinyMCE.getParam('convert_urls')){var imgs=content.getElementsByTagName("img");for(var i=0;i<imgs.length;i++){if(tinyMCE.getAttrib(imgs[i],"class")=="mceItemFlash"){var src=tinyMCE.getAttrib(imgs[i],"alt");if(tinyMCE.getParam('convert_urls'))src=eval(tinyMCE.settings['urlconverter_callback']+"(src, null, true);");imgs[i].setAttribute('alt',src);imgs[i].setAttribute('title',src)}}}break;case"get_from_editor_dom":var imgs=content.getElementsByTagName("img");for(var i=0;i<imgs.length;i++){if(tinyMCE.getAttrib(imgs[i],"class")=="mceItemFlash"){var src=tinyMCE.getAttrib(imgs[i],"alt");if(tinyMCE.getParam('convert_urls'))src=eval(tinyMCE.settings['urlconverter_callback']+"(src, null, true);");imgs[i].setAttribute('alt',src);imgs[i].setAttribute('title',src)}}break;case"insert_to_editor":var startPos=0;var embedList=new Array();content=content.replace(new RegExp('<[ ]*embed','gi'),'<embed');content=content.replace(new RegExp('<[ ]*/embed[ ]*>','gi'),'</embed>');content=content.replace(new RegExp('<[ ]*object','gi'),'<object');content=content.replace(new RegExp('<[ ]*/object[ ]*>','gi'),'</object>');while((startPos=content.indexOf('<embed',startPos+1))!=-1){var endPos=content.indexOf('>',startPos);var attribs=TinyMCE_FlashPlugin._parseAttributes(content.substring(startPos+6,endPos));embedList[embedList.length]=attribs}var index=0;while((startPos=content.indexOf('<object',startPos))!=-1){if(index>=embedList.length)break;var attribs=embedList[index];endPos=content.indexOf('</object>',startPos);endPos+=9;var contentAfter=content.substring(endPos);content=content.substring(0,startPos);content+='<img width="'+attribs["width"]+'" height="'+attribs["height"]+'"';content+=' src="'+(tinyMCE.getParam("theme_href")+'/images/spacer.gif')+'" title="'+attribs["src"]+'"';content+=' alt="'+attribs["src"]+'" class="mceItemFlash" />'+content.substring(endPos);content+=contentAfter;index++;startPos++}var index=0;while((startPos=content.indexOf('<embed',startPos))!=-1){if(index>=embedList.length)break;var attribs=embedList[index];endPos=content.indexOf('>',startPos);endPos+=9;var contentAfter=content.substring(endPos);content=content.substring(0,startPos);content+='<img width="'+attribs["width"]+'" height="'+attribs["height"]+'"';content+=' src="'+(tinyMCE.getParam("theme_href")+'/images/spacer.gif')+'" title="'+attribs["src"]+'"';content+=' alt="'+attribs["src"]+'" class="mceItemFlash" />'+content.substring(endPos);content+=contentAfter;index++;startPos++}break;case"get_from_editor":var startPos=-1;while((startPos=content.indexOf('<img',startPos+1))!=-1){var endPos=content.indexOf('/>',startPos);var attribs=TinyMCE_FlashPlugin._parseAttributes(content.substring(startPos+4,endPos));if(attribs['class']!="mceItemFlash")continue;endPos+=2;var embedHTML='';var wmode=tinyMCE.getParam("flash_wmode","");var quality=tinyMCE.getParam("flash_quality","high");var menu=tinyMCE.getParam("flash_menu","false");embedHTML+='<object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"';embedHTML+=' codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,29,0"';embedHTML+=' width="'+attribs["width"]+'" height="'+attribs["height"]+'">';embedHTML+='<param name="movie" value="'+attribs["title"]+'" />';embedHTML+='<param name="quality" value="'+quality+'" />';embedHTML+='<param name="menu" value="'+menu+'" />';embedHTML+='<param name="wmode" value="'+wmode+'" />';embedHTML+='<embed src="'+attribs["title"]+'" wmode="'+wmode+'" quality="'+quality+'" menu="'+menu+'" pluginspage="http://www.macromedia.com/go/getflashplayer" type="application/x-shockwave-flash" width="'+attribs["width"]+'" height="'+attribs["height"]+'"></embed></object>';chunkBefore=content.substring(0,startPos);chunkAfter=content.substring(endPos);content=chunkBefore+embedHTML+chunkAfter}break}return content},handleNodeChange:function(editor_id,node,undo_index,undo_levels,visual_aid,any_selection){if(node==null)return;do{if(node.nodeName=="IMG"&&tinyMCE.getAttrib(node,'class').indexOf('mceItemFlash')==0){tinyMCE.switchClass(editor_id+'_flash','mceButtonSelected');return true}}while((node=node.parentNode));tinyMCE.switchClass(editor_id+'_flash','mceButtonNormal');return true},_parseAttributes:function(attribute_string){var attributeName="";var attributeValue="";var withInName;var withInValue;var attributes=new Array();var whiteSpaceRegExp=new RegExp('^[ \n\r\t]+','g');if(attribute_string==null||attribute_string.length<2)return null;withInName=withInValue=false;for(var i=0;i<attribute_string.length;i++){var chr=attribute_string.charAt(i);if((chr=='"'||chr=="'")&&!withInValue)withInValue=true;else if((chr=='"'||chr=="'")&&withInValue){withInValue=false;var pos=attributeName.lastIndexOf(' ');if(pos!=-1)attributeName=attributeName.substring(pos+1);attributes[attributeName.toLowerCase()]=attributeValue.substring(1);attributeName="";attributeValue=""}else if(!whiteSpaceRegExp.test(chr)&&!withInName&&!withInValue)withInName=true;if(chr=='='&&withInName)withInName=false;if(withInName)attributeName+=chr;if(withInValue)attributeValue+=chr}return attributes}};tinyMCE.addPlugin("flash",TinyMCE_FlashPlugin);
\ No newline at end of file
--- a/includes/clientside/tinymce/plugins/flash/editor_plugin_src.js	Fri Feb 22 12:46:51 2008 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,285 +0,0 @@
-/**
- * $Id: editor_plugin_src.js 201 2007-02-12 15:56:56Z spocke $
- *
- * @author Moxiecode
- * @copyright Copyright © 2004-2007, Moxiecode Systems AB, All rights reserved.
- */
-
-/* Import plugin specific language pack */
-tinyMCE.importPluginLanguagePack('flash');
-
-var TinyMCE_FlashPlugin = {
-	getInfo : function() {
-		return {
-			longname : 'Flash',
-			author : 'Moxiecode Systems AB',
-			authorurl : 'http://tinymce.moxiecode.com',
-			infourl : 'http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/flash',
-			version : tinyMCE.majorVersion + "." + tinyMCE.minorVersion
-		};
-	},
-
-	initInstance : function(inst) {
-		if (!tinyMCE.settings['flash_skip_plugin_css'])
-			tinyMCE.importCSS(inst.getDoc(), tinyMCE.baseURL + "/plugins/flash/css/content.css");
-	},
-
-	getControlHTML : function(cn) {
-		switch (cn) {
-			case "flash":
-				return tinyMCE.getButtonHTML(cn, 'lang_flash_desc', '{$pluginurl}/images/flash.gif', 'mceFlash');
-		}
-
-		return "";
-	},
-
-	execCommand : function(editor_id, element, command, user_interface, value) {
-		// Handle commands
-		switch (command) {
-			case "mceFlash":
-				var name = "", swffile = "", swfwidth = "", swfheight = "", action = "insert";
-				var template = new Array();
-				var inst = tinyMCE.getInstanceById(editor_id);
-				var focusElm = inst.getFocusElement();
-
-				template['file']   = '../../plugins/flash/flash.htm'; // Relative to theme
-				template['width']  = 430;
-				template['height'] = 175;
-
-				template['width'] += tinyMCE.getLang('lang_flash_delta_width', 0);
-				template['height'] += tinyMCE.getLang('lang_flash_delta_height', 0);
-
-				// Is selection a image
-				if (focusElm != null && focusElm.nodeName.toLowerCase() == "img") {
-					name = tinyMCE.getAttrib(focusElm, 'class');
-
-					if (name.indexOf('mceItemFlash') == -1) // Not a Flash
-						return true;
-
-					// Get rest of Flash items
-					swffile = tinyMCE.getAttrib(focusElm, 'alt');
-
-					if (tinyMCE.getParam('convert_urls'))
-						swffile = eval(tinyMCE.settings['urlconverter_callback'] + "(swffile, null, true);");
-
-					swfwidth = tinyMCE.getAttrib(focusElm, 'width');
-					swfheight = tinyMCE.getAttrib(focusElm, 'height');
-					action = "update";
-				}
-
-				tinyMCE.openWindow(template, {editor_id : editor_id, inline : "yes", swffile : swffile, swfwidth : swfwidth, swfheight : swfheight, action : action});
-			return true;
-	   }
-
-	   // Pass to next handler in chain
-	   return false;
-	},
-
-	cleanup : function(type, content) {
-		switch (type) {
-			case "insert_to_editor_dom":
-				// Force relative/absolute
-				if (tinyMCE.getParam('convert_urls')) {
-					var imgs = content.getElementsByTagName("img");
-					for (var i=0; i<imgs.length; i++) {
-						if (tinyMCE.getAttrib(imgs[i], "class") == "mceItemFlash") {
-							var src = tinyMCE.getAttrib(imgs[i], "alt");
-
-							if (tinyMCE.getParam('convert_urls'))
-								src = eval(tinyMCE.settings['urlconverter_callback'] + "(src, null, true);");
-
-							imgs[i].setAttribute('alt', src);
-							imgs[i].setAttribute('title', src);
-						}
-					}
-				}
-				break;
-
-			case "get_from_editor_dom":
-				var imgs = content.getElementsByTagName("img");
-				for (var i=0; i<imgs.length; i++) {
-					if (tinyMCE.getAttrib(imgs[i], "class") == "mceItemFlash") {
-						var src = tinyMCE.getAttrib(imgs[i], "alt");
-
-						if (tinyMCE.getParam('convert_urls'))
-							src = eval(tinyMCE.settings['urlconverter_callback'] + "(src, null, true);");
-
-						imgs[i].setAttribute('alt', src);
-						imgs[i].setAttribute('title', src);
-					}
-				}
-				break;
-
-			case "insert_to_editor":
-				var startPos = 0;
-				var embedList = new Array();
-
-				// Fix the embed and object elements
-				content = content.replace(new RegExp('<[ ]*embed','gi'),'<embed');
-				content = content.replace(new RegExp('<[ ]*/embed[ ]*>','gi'),'</embed>');
-				content = content.replace(new RegExp('<[ ]*object','gi'),'<object');
-				content = content.replace(new RegExp('<[ ]*/object[ ]*>','gi'),'</object>');
-
-				// Parse all embed tags
-				while ((startPos = content.indexOf('<embed', startPos+1)) != -1) {
-					var endPos = content.indexOf('>', startPos);
-					var attribs = TinyMCE_FlashPlugin._parseAttributes(content.substring(startPos + 6, endPos));
-					embedList[embedList.length] = attribs;
-				}
-
-				// Parse all object tags and replace them with images from the embed data
-				var index = 0;
-				while ((startPos = content.indexOf('<object', startPos)) != -1) {
-					if (index >= embedList.length)
-						break;
-
-					var attribs = embedList[index];
-
-					// Find end of object
-					endPos = content.indexOf('</object>', startPos);
-					endPos += 9;
-
-					// Insert image
-					var contentAfter = content.substring(endPos);
-					content = content.substring(0, startPos);
-					content += '<img width="' + attribs["width"] + '" height="' + attribs["height"] + '"';
-					content += ' src="' + (tinyMCE.getParam("theme_href") + '/images/spacer.gif') + '" title="' + attribs["src"] + '"';
-					content += ' alt="' + attribs["src"] + '" class="mceItemFlash" />' + content.substring(endPos);
-					content += contentAfter;
-					index++;
-
-					startPos++;
-				}
-
-				// Parse all embed tags and replace them with images from the embed data
-				var index = 0;
-				while ((startPos = content.indexOf('<embed', startPos)) != -1) {
-					if (index >= embedList.length)
-						break;
-
-					var attribs = embedList[index];
-
-					// Find end of embed
-					endPos = content.indexOf('>', startPos);
-					endPos += 9;
-
-					// Insert image
-					var contentAfter = content.substring(endPos);
-					content = content.substring(0, startPos);
-					content += '<img width="' + attribs["width"] + '" height="' + attribs["height"] + '"';
-					content += ' src="' + (tinyMCE.getParam("theme_href") + '/images/spacer.gif') + '" title="' + attribs["src"] + '"';
-					content += ' alt="' + attribs["src"] + '" class="mceItemFlash" />' + content.substring(endPos);
-					content += contentAfter;
-					index++;
-
-					startPos++;
-				}
-
-				break;
-
-			case "get_from_editor":
-				// Parse all img tags and replace them with object+embed
-				var startPos = -1;
-
-				while ((startPos = content.indexOf('<img', startPos+1)) != -1) {
-					var endPos = content.indexOf('/>', startPos);
-					var attribs = TinyMCE_FlashPlugin._parseAttributes(content.substring(startPos + 4, endPos));
-
-					// Is not flash, skip it
-					if (attribs['class'] != "mceItemFlash")
-						continue;
-
-					endPos += 2;
-
-					var embedHTML = '';
-					var wmode = tinyMCE.getParam("flash_wmode", "");
-					var quality = tinyMCE.getParam("flash_quality", "high");
-					var menu = tinyMCE.getParam("flash_menu", "false");
-
-					// Insert object + embed
-					embedHTML += '<object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"';
-					embedHTML += ' codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,29,0"';
-					embedHTML += ' width="' + attribs["width"] + '" height="' + attribs["height"] + '">';
-					embedHTML += '<param name="movie" value="' + attribs["title"] + '" />';
-					embedHTML += '<param name="quality" value="' + quality + '" />';
-					embedHTML += '<param name="menu" value="' + menu + '" />';
-					embedHTML += '<param name="wmode" value="' + wmode + '" />';
-					embedHTML += '<embed src="' + attribs["title"] + '" wmode="' + wmode + '" quality="' + quality + '" menu="' + menu + '" pluginspage="http://www.macromedia.com/go/getflashplayer" type="application/x-shockwave-flash" width="' + attribs["width"] + '" height="' + attribs["height"] + '"></embed></object>';
-
-					// Insert embed/object chunk
-					chunkBefore = content.substring(0, startPos);
-					chunkAfter = content.substring(endPos);
-					content = chunkBefore + embedHTML + chunkAfter;
-				}
-				break;
-		}
-
-		// Pass through to next handler in chain
-		return content;
-	},
-
-	handleNodeChange : function(editor_id, node, undo_index, undo_levels, visual_aid, any_selection) {
-		if (node == null)
-			return;
-
-		do {
-			if (node.nodeName == "IMG" && tinyMCE.getAttrib(node, 'class').indexOf('mceItemFlash') == 0) {
-				tinyMCE.switchClass(editor_id + '_flash', 'mceButtonSelected');
-				return true;
-			}
-		} while ((node = node.parentNode));
-
-		tinyMCE.switchClass(editor_id + '_flash', 'mceButtonNormal');
-
-		return true;
-	},
-
-	// Private plugin internal functions
-
-	_parseAttributes : function(attribute_string) {
-		var attributeName = "";
-		var attributeValue = "";
-		var withInName;
-		var withInValue;
-		var attributes = new Array();
-		var whiteSpaceRegExp = new RegExp('^[ \n\r\t]+', 'g');
-
-		if (attribute_string == null || attribute_string.length < 2)
-			return null;
-
-		withInName = withInValue = false;
-
-		for (var i=0; i<attribute_string.length; i++) {
-			var chr = attribute_string.charAt(i);
-
-			if ((chr == '"' || chr == "'") && !withInValue)
-				withInValue = true;
-			else if ((chr == '"' || chr == "'") && withInValue) {
-				withInValue = false;
-
-				var pos = attributeName.lastIndexOf(' ');
-				if (pos != -1)
-					attributeName = attributeName.substring(pos+1);
-
-				attributes[attributeName.toLowerCase()] = attributeValue.substring(1);
-
-				attributeName = "";
-				attributeValue = "";
-			} else if (!whiteSpaceRegExp.test(chr) && !withInName && !withInValue)
-				withInName = true;
-
-			if (chr == '=' && withInName)
-				withInName = false;
-
-			if (withInName)
-				attributeName += chr;
-
-			if (withInValue)
-				attributeValue += chr;
-		}
-
-		return attributes;
-	}
-};
-
-tinyMCE.addPlugin("flash", TinyMCE_FlashPlugin);
--- a/includes/clientside/tinymce/plugins/flash/flash.htm	Fri Feb 22 12:46:51 2008 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,70 +0,0 @@
-<html xmlns="http://www.w3.org/1999/xhtml">
-<head>
-	<title>{$lang_flash_title}</title>
-	<script language="javascript" type="text/javascript" src="../../tiny_mce_popup.js"></script>
-	<script language="javascript" type="text/javascript" src="jscripts/flash.js"></script>
-	<script language="javascript" type="text/javascript" src="../../utils/mctabs.js"></script>
-	<script language="javascript" type="text/javascript" src="../../utils/form_utils.js"></script>
-	<link href="css/flash.css" rel="stylesheet" type="text/css" />
-	<base target="_self" />
-</head>
-<body onload="tinyMCEPopup.executeOnLoad('init();');" style="display: none">
-    <form onsubmit="insertFlash();return false;" action="#">
-		<div class="tabs">
-			<ul>
-				<li id="general_tab" class="current"><span><a href="javascript:mcTabs.displayTab('general_tab','general_panel');" onmousedown="return false;">{$lang_flash_general}</a></span></li>
-			</ul>
-		</div>
-
-		<div class="panel_wrapper">
-			<div id="general_panel" class="panel current">
-				<fieldset>
-					<legend>{$lang_flash_general}</legend>
-
-					<table border="0" cellpadding="4" cellspacing="0">
-							<tr>
-							<td nowrap="nowrap"><label for="file">{$lang_flash_file}</label></td>
-							  <td nowrap="nowrap">
-									<table border="0" cellspacing="0" cellpadding="0">
-									  <tr>
-										<td><input id="file" name="file" type="text" value="" onfocus="this.select();" /></td>
-										<td id="filebrowsercontainer">&nbsp;</td>
-									  </tr>
-									</table>
-								</td>
-							</tr>
-							<tr id="linklistrow">
-								<td><label for="linklist">{$lang_flash_list}</label></td>
-								<td id="linklistcontainer">&nbsp;</td>
-							</tr>
-							<tr>
-								<td nowrap="nowrap"><label>{$lang_flash_size}</label></td>
-								<td nowrap="nowrap">
-									<input type="text" id="width" name="width" value="" onfocus="this.select();" />
-									<select name="width2" id="width2" style="width: 50px">
-										<option value="">px</option>
-										<option value="%">%</option>
-									</select>&nbsp;x&nbsp;<input id="height" name="height" type="text"  value="" onfocus="this.select();" />
-									<select name="height2" id="height2" style="width: 50px">
-										<option value="">px</option>
-										<option value="%">%</option>
-									</select>
-								</td>
-							</tr>
-					</table>
-				</fieldset>
-			</div>
-		</div>
-
-		<div class="mceActionPanel">
-			<div style="float: left">
-				<input type="button" id="insert" name="insert" value="{$lang_insert}" onclick="insertFlash();" />
-			</div>
-
-			<div style="float: right">
-				<input type="button" id="cancel" name="cancel" value="{$lang_cancel}" onclick="tinyMCEPopup.close();" />
-			</div>
-		</div>
-	</form>
-</body>
-</html>
Binary file includes/clientside/tinymce/plugins/flash/images/flash.gif has changed
--- a/includes/clientside/tinymce/plugins/flash/jscripts/flash.js	Fri Feb 22 12:46:51 2008 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,107 +0,0 @@
-var url = tinyMCE.getParam("flash_external_list_url");
-if (url != null) {
-	// Fix relative
-	if (url.charAt(0) != '/' && url.indexOf('://') == -1)
-		url = tinyMCE.documentBasePath + "/" + url;
-
-	document.write('<sc'+'ript language="javascript" type="text/javascript" src="' + url + '"></sc'+'ript>');
-}
-
-function init() {
-	tinyMCEPopup.resizeToInnerSize();
-
-	document.getElementById("filebrowsercontainer").innerHTML = getBrowserHTML('filebrowser','file','flash','flash');
-
-	// Image list outsrc
-	var html = getFlashListHTML('filebrowser','file','flash','flash');
-	if (html == "")
-		document.getElementById("linklistrow").style.display = 'none';
-	else
-		document.getElementById("linklistcontainer").innerHTML = html;
-
-	var formObj = document.forms[0];
-	var swffile   = tinyMCE.getWindowArg('swffile');
-	var swfwidth  = '' + tinyMCE.getWindowArg('swfwidth');
-	var swfheight = '' + tinyMCE.getWindowArg('swfheight');
-
-	if (swfwidth.indexOf('%')!=-1) {
-		formObj.width2.value = "%";
-		formObj.width.value  = swfwidth.substring(0,swfwidth.length-1);
-	} else {
-		formObj.width2.value = "px";
-		formObj.width.value  = swfwidth;
-	}
-
-	if (swfheight.indexOf('%')!=-1) {
-		formObj.height2.value = "%";
-		formObj.height.value  = swfheight.substring(0,swfheight.length-1);
-	} else {
-		formObj.height2.value = "px";
-		formObj.height.value  = swfheight;
-	}
-
-	formObj.file.value = swffile;
-	formObj.insert.value = tinyMCE.getLang('lang_' + tinyMCE.getWindowArg('action'), 'Insert', true);
-
-	selectByValue(formObj, 'linklist', swffile);
-
-	// Handle file browser
-	if (isVisible('filebrowser'))
-		document.getElementById('file').style.width = '230px';
-
-	// Auto select flash in list
-	if (typeof(tinyMCEFlashList) != "undefined" && tinyMCEFlashList.length > 0) {
-		for (var i=0; i<formObj.linklist.length; i++) {
-			if (formObj.linklist.options[i].value == tinyMCE.getWindowArg('swffile'))
-				formObj.linklist.options[i].selected = true;
-		}
-	}
-}
-
-function getFlashListHTML() {
-	if (typeof(tinyMCEFlashList) != "undefined" && tinyMCEFlashList.length > 0) {
-		var html = "";
-
-		html += '<select id="linklist" name="linklist" style="width: 250px" onfocus="tinyMCE.addSelectAccessibility(event, this, window);" onchange="this.form.file.value=this.options[this.selectedIndex].value;">';
-		html += '<option value="">---</option>';
-
-		for (var i=0; i<tinyMCEFlashList.length; i++)
-			html += '<option value="' + tinyMCEFlashList[i][1] + '">' + tinyMCEFlashList[i][0] + '</option>';
-
-		html += '</select>';
-
-		return html;
-	}
-
-	return "";
-}
-
-function insertFlash() {
-	var formObj = document.forms[0];
-	var html      = '';
-	var file      = formObj.file.value;
-	var width     = formObj.width.value;
-	var height    = formObj.height.value;
-	if (formObj.width2.value=='%') {
-		width = width + '%';
-	}
-	if (formObj.height2.value=='%') {
-		height = height + '%';
-	}
-
-	if (width == "")
-		width = 100;
-
-	if (height == "")
-		height = 100;
-
-	html += ''
-		+ '<img src="' + (tinyMCE.getParam("theme_href") + "/images/spacer.gif") + '" mce_src="' + (tinyMCE.getParam("theme_href") + "/images/spacer.gif") + '" '
-		+ 'width="' + width + '" height="' + height + '" '
-		+ 'border="0" alt="' + file + '" title="' + file + '" class="mceItemFlash" />';
-
-	tinyMCEPopup.execCommand("mceInsertContent", true, html);
-	tinyMCE.selectedInstance.repaint();
-
-	tinyMCEPopup.close();
-}
--- a/includes/clientside/tinymce/plugins/flash/langs/en.js	Fri Feb 22 12:46:51 2008 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,11 +0,0 @@
-// UK lang variables
-
-tinyMCE.addToLang('flash',{
-title : 'Insert / edit Flash Movie',
-desc : 'Insert / edit Flash Movie',
-file : 'Flash-File (.swf)',
-size : 'Size',
-list : 'Flash files',
-props : 'Flash properties',
-general : 'General'
-});
--- a/includes/clientside/tinymce/plugins/flash/readme.txt	Fri Feb 22 12:46:51 2008 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1 +0,0 @@
-Check the TinyMCE documentation for details on this plugin.
--- a/includes/clientside/tinymce/plugins/fullpage/blank.htm	Fri Feb 22 12:46:51 2008 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,9 +0,0 @@
-<html xmlns="http://www.w3.org/1999/xhtml">
-<head>
-	<title>blank_page</title>
-	<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
-</head>
-<body onload="parent.setupIframe(document);">
-
-</body>
-</html>
--- a/includes/clientside/tinymce/plugins/fullpage/css/fullpage.css	Fri Feb 22 12:46:51 2008 -0500
+++ b/includes/clientside/tinymce/plugins/fullpage/css/fullpage.css	Fri Feb 22 12:51:53 2008 -0500
@@ -170,3 +170,9 @@
 	width: 22px;
 	height: 22px;
 }
+
+textarea {
+	height: 55px;
+}
+
+.panel_wrapper div.current {height:420px;}
\ No newline at end of file
--- a/includes/clientside/tinymce/plugins/fullpage/editor_plugin.js	Fri Feb 22 12:46:51 2008 -0500
+++ b/includes/clientside/tinymce/plugins/fullpage/editor_plugin.js	Fri Feb 22 12:51:53 2008 -0500
@@ -1,1 +1,1 @@
-tinyMCE.importPluginLanguagePack('fullpage');var TinyMCE_FullPagePlugin={getInfo:function(){return{longname:'Fullpage',author:'Moxiecode Systems AB',authorurl:'http://tinymce.moxiecode.com',infourl:'http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/fullpage',version:tinyMCE.majorVersion+"."+tinyMCE.minorVersion}},getControlHTML:function(cn){switch(cn){case"fullpage":return tinyMCE.getButtonHTML(cn,'lang_fullpage_desc','{$pluginurl}/images/fullpage.gif','mceFullPageProperties')}return""},execCommand:function(editor_id,element,command,user_interface,value){switch(command){case"mceFullPageProperties":var template=new Array();template['file']='../../plugins/fullpage/fullpage.htm';template['width']=430;template['height']=485+(tinyMCE.isOpera?5:0);template['width']+=tinyMCE.getLang('lang_fullpage_delta_width',0);template['height']+=tinyMCE.getLang('lang_fullpage_delta_height',0);tinyMCE.openWindow(template,{editor_id:editor_id,inline:"yes"});return true;case"mceFullPageUpdate":TinyMCE_FullPagePlugin._addToHead(tinyMCE.getInstanceById(editor_id));return true}return false},cleanup:function(type,content,inst){switch(type){case"insert_to_editor":var tmp=content.toLowerCase();var pos=tmp.indexOf('<body'),pos2;if(pos!=-1){pos=tmp.indexOf('>',pos);pos2=tmp.lastIndexOf('</body>');inst.fullpageTopContent=content.substring(0,pos+1);content=content.substring(pos+1,pos2);}else{if(!inst.fullpageTopContent){var docType=tinyMCE.getParam("fullpage_default_doctype",'<!DOCTYPE html PUBLIC "-/'+'/W3C//DTD XHTML 1.0 Transitional/'+'/EN" "http:/'+'/www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">');var enc=tinyMCE.getParam("fullpage_default_encoding",'utf-8');var title=tinyMCE.getParam("fullpage_default_title",'Untitled document');var lang=tinyMCE.getParam("fullpage_default_langcode",'en');var pi=tinyMCE.getParam("fullpage_default_xml_pi",true);var ff=tinyMCE.getParam("fullpage_default_font_family","");var fz=tinyMCE.getParam("fullpage_default_font_size","");var ds=tinyMCE.getParam("fullpage_default_style","");var dtc=tinyMCE.getParam("fullpage_default_text_color","");title=title.replace(/&/g,'&amp;');title=title.replace(/\"/g,'&quot;');title=title.replace(/</g,'&lt;');title=title.replace(/>/g,'&gt;');tmp='';if(pi)tmp+='<?xml version="1.0" encoding="'+enc+'"?>\n';tmp+=docType+'\n';tmp+='<html xmlns="http:/'+'/www.w3.org/1999/xhtml" lang="'+lang+'" xml:lang="'+lang+'">\n';tmp+='<head>\n';tmp+='\t<title>'+title+'</title>\n';tmp+='\t<meta http-equiv="Content-Type" content="text/html; charset='+enc+'" />\n';tmp+='</head>\n';tmp+='<body';if(ff!=''||fz!=''){tmp+=' style="';if(ds!='')tmp+=ds+";";if(ff!='')tmp+='font-family: '+ff+";";if(fz!='')tmp+='font-size: '+fz+";";tmp+='"'}if(dtc!='')tmp+=' text="'+dtc+'"';tmp+='>\n';inst.fullpageTopContent=tmp}}this._addToHead(inst);break;case"get_from_editor":if(inst.fullpageTopContent)content=inst.fullpageTopContent+content+"\n</body>\n</html>";break}return content},_addToHead:function(inst){var doc=inst.getDoc();var head=doc.getElementsByTagName("head")[0];var body=doc.body;var h=inst.fullpageTopContent;var e=doc.createElement("body");var nl,i,le,tmp;h=h.replace(/(\r|\n)/gi,'');h=h.replace(/<\?[^\>]*\>/gi,'');h=h.replace(/<\/?(!DOCTYPE|head|html)[^\>]*\>/gi,'');h=h.replace(/<script(.*?)<\/script>/gi,'');h=h.replace(/<title(.*?)<\/title>/gi,'');h=h.replace(/<(meta|base)[^>]*>/gi,'');h=h.replace(/<link([^>]*)\/>/gi,'<pre mce_type="link" $1></pre>');h=h.replace(/<body/gi,'<div mce_type="body"');h+='</div>';e.innerHTML=h;body.vLink=body.aLink=body.link=body.text='';body.style.cssText='';nl=head.getElementsByTagName('link');for(i=0;i<nl.length;i++){if(tinyMCE.getAttrib(nl[i],'mce_head')=="true")nl[i].parentNode.removeChild(nl[i])}nl=e.getElementsByTagName('pre');for(i=0;i<nl.length;i++){tmp=tinyMCE.getAttrib(nl[i],'media');if(tinyMCE.getAttrib(nl[i],'mce_type')=="link"&&(tmp==""||tmp=="screen"||tmp=="all")&&tinyMCE.getAttrib(nl[i],'rel')=="stylesheet"){le=doc.createElement("link");le.rel="stylesheet";le.href=tinyMCE.getAttrib(nl[i],'href');le.setAttribute("mce_head","true");head.appendChild(le)}}nl=e.getElementsByTagName('div');if(nl.length>0){body.style.cssText=tinyMCE.getAttrib(nl[0],'style');if((tmp=tinyMCE.getAttrib(nl[0],'leftmargin'))!=''&&body.style.marginLeft=='')body.style.marginLeft=tmp+"px";if((tmp=tinyMCE.getAttrib(nl[0],'rightmargin'))!=''&&body.style.marginRight=='')body.style.marginRight=tmp+"px";if((tmp=tinyMCE.getAttrib(nl[0],'topmargin'))!=''&&body.style.marginTop=='')body.style.marginTop=tmp+"px";if((tmp=tinyMCE.getAttrib(nl[0],'bottommargin'))!=''&&body.style.marginBottom=='')body.style.marginBottom=tmp+"px";body.dir=tinyMCE.getAttrib(nl[0],'dir');body.vLink=tinyMCE.getAttrib(nl[0],'vlink');body.aLink=tinyMCE.getAttrib(nl[0],'alink');body.link=tinyMCE.getAttrib(nl[0],'link');body.text=tinyMCE.getAttrib(nl[0],'text');if((tmp=tinyMCE.getAttrib(nl[0],'background'))!='')body.style.backgroundImage="url('"+tmp+"')";if((tmp=tinyMCE.getAttrib(nl[0],'bgcolor'))!='')body.style.backgroundColor=tmp}}};tinyMCE.addPlugin("fullpage",TinyMCE_FullPagePlugin);
\ No newline at end of file
+(function(){tinymce.create('tinymce.plugins.FullPagePlugin',{init:function(ed,url){var t=this;t.editor=ed;ed.addCommand('mceFullPageProperties',function(){ed.windowManager.open({file:url+'/fullpage.htm',width:430+parseInt(ed.getLang('fullpage.delta_width',0)),height:495+parseInt(ed.getLang('fullpage.delta_height',0)),inline:1},{plugin_url:url,head_html:t.head});});ed.addButton('fullpage',{title:'fullpage.desc',cmd:'mceFullPageProperties'});ed.onBeforeSetContent.add(t._setContent,t);ed.onGetContent.add(t._getContent,t);},getInfo:function(){return{longname:'Fullpage',author:'Moxiecode Systems AB',authorurl:'http://tinymce.moxiecode.com',infourl:'http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/fullpage',version:tinymce.majorVersion+"."+tinymce.minorVersion};},_createSerializer:function(){return new tinymce.dom.Serializer({dom:this.editor.dom,apply_source_formatting:true});},_setContent:function(ed,o){var t=this,sp,ep,c=o.content;sp=c.indexOf('<body');if(sp==-1)sp=c.indexOf('<BODY');if(sp!=-1){sp=c.indexOf('>',sp);t.head=c.substring(0,sp+1);ep=c.indexOf('</body',sp);if(ep==-1)ep=c.indexOf('</body',ep);o.content=c.substring(sp+1,ep);t.foot=c.substring(ep);}else{t.head='<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">';t.head+='\n<html>\n<head>\n<title>Untitled document</title>\n</head>\n<body>\n';t.foot='\n</body>\n</html>';}},_getContent:function(ed,o){var t=this;o.content=tinymce.trim(t.head)+'\n'+tinymce.trim(o.content)+'\n'+tinymce.trim(t.foot);}});tinymce.PluginManager.add('fullpage',tinymce.plugins.FullPagePlugin);})();
\ No newline at end of file
--- a/includes/clientside/tinymce/plugins/fullpage/editor_plugin_src.js	Fri Feb 22 12:46:51 2008 -0500
+++ b/includes/clientside/tinymce/plugins/fullpage/editor_plugin_src.js	Fri Feb 22 12:51:53 2008 -0500
@@ -1,227 +1,88 @@
 /**
- * $Id: editor_plugin_src.js 201 2007-02-12 15:56:56Z spocke $
+ * $Id: editor_plugin_src.js 520 2008-01-07 16:30:32Z spocke $
  *
  * @author Moxiecode
- * @copyright Copyright © 2004-2007, Moxiecode Systems AB, All rights reserved.
+ * @copyright Copyright © 2004-2008, Moxiecode Systems AB, All rights reserved.
  */
 
-/* Import plugin specific language pack */
-tinyMCE.importPluginLanguagePack('fullpage');
-
-var TinyMCE_FullPagePlugin = {
-	getInfo : function() {
-		return {
-			longname : 'Fullpage',
-			author : 'Moxiecode Systems AB',
-			authorurl : 'http://tinymce.moxiecode.com',
-			infourl : 'http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/fullpage',
-			version : tinyMCE.majorVersion + "." + tinyMCE.minorVersion
-		};
-	},
-
-	getControlHTML : function(cn) {
-		switch (cn) {
-			case "fullpage":
-				return tinyMCE.getButtonHTML(cn, 'lang_fullpage_desc', '{$pluginurl}/images/fullpage.gif', 'mceFullPageProperties');
-		}
-
-		return "";
-	},
+(function() {
+	tinymce.create('tinymce.plugins.FullPagePlugin', {
+		init : function(ed, url) {
+			var t = this;
 
-	execCommand : function(editor_id, element, command, user_interface, value) {
-		// Handle commands
-		switch (command) {
-			case "mceFullPageProperties":
-				var template = new Array();
-
-				template['file']   = '../../plugins/fullpage/fullpage.htm';
-				template['width']  = 430;
-				template['height'] = 485 + (tinyMCE.isOpera ? 5 : 0);
-
-				template['width'] += tinyMCE.getLang('lang_fullpage_delta_width', 0);
-				template['height'] += tinyMCE.getLang('lang_fullpage_delta_height', 0);
-
-				tinyMCE.openWindow(template, {editor_id : editor_id, inline : "yes"});
-			return true;
-
-			case "mceFullPageUpdate":
-				TinyMCE_FullPagePlugin._addToHead(tinyMCE.getInstanceById(editor_id));
-				return true;
-	   }
-
-	   // Pass to next handler in chain
-	   return false;
-	},
-
-	cleanup : function(type, content, inst) {
-		switch (type) {
-			case "insert_to_editor":
-				var tmp = content.toLowerCase();
-				var pos = tmp.indexOf('<body'), pos2;
+			t.editor = ed;
 
-				// Split page in header and body chunks
-				if (pos != -1) {
-					pos = tmp.indexOf('>', pos);
-					pos2 = tmp.lastIndexOf('</body>');
-					inst.fullpageTopContent = content.substring(0, pos + 1);
-					content = content.substring(pos + 1, pos2);
-					// tinyMCE.debug(inst.fullpageTopContent, content);
-				} else {
-					if (!inst.fullpageTopContent) {
-						var docType = tinyMCE.getParam("fullpage_default_doctype", '<!DOCTYPE html PUBLIC "-/'+'/W3C//DTD XHTML 1.0 Transitional/'+'/EN" "http:/'+'/www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">');
-						var enc = tinyMCE.getParam("fullpage_default_encoding", 'utf-8');
-						var title = tinyMCE.getParam("fullpage_default_title", 'Untitled document');
-						var lang = tinyMCE.getParam("fullpage_default_langcode", 'en');
-						var pi = tinyMCE.getParam("fullpage_default_xml_pi", true);
-						var ff = tinyMCE.getParam("fullpage_default_font_family", "");
-						var fz = tinyMCE.getParam("fullpage_default_font_size", "");
-						var ds = tinyMCE.getParam("fullpage_default_style", "");
-						var dtc = tinyMCE.getParam("fullpage_default_text_color", "");
+			// Register commands
+			ed.addCommand('mceFullPageProperties', function() {
+				ed.windowManager.open({
+					file : url + '/fullpage.htm',
+					width : 430 + parseInt(ed.getLang('fullpage.delta_width', 0)),
+					height : 495 + parseInt(ed.getLang('fullpage.delta_height', 0)),
+					inline : 1
+				}, {
+					plugin_url : url,
+					head_html : t.head
+				});
+			});
 
-						// Xml encode it
-						title = title.replace(/&/g, '&amp;');
-						title = title.replace(/\"/g, '&quot;');
-						title = title.replace(/</g, '&lt;');
-						title = title.replace(/>/g, '&gt;');
-
-						tmp = '';
+			// Register buttons
+			ed.addButton('fullpage', {title : 'fullpage.desc', cmd : 'mceFullPageProperties'});
 
-						// Make default chunk
-						if (pi)
-							tmp += '<?xml version="1.0" encoding="' + enc + '"?>\n';
-
-						tmp += docType + '\n';
-						tmp += '<html xmlns="http:/'+'/www.w3.org/1999/xhtml" lang="' + lang + '" xml:lang="' + lang + '">\n';
-						tmp += '<head>\n';
-						tmp += '\t<title>' + title + '</title>\n';
-						tmp += '\t<meta http-equiv="Content-Type" content="text/html; charset=' + enc + '" />\n';
-						tmp += '</head>\n';
-						tmp += '<body';
+			ed.onBeforeSetContent.add(t._setContent, t);
+			ed.onGetContent.add(t._getContent, t);
+		},
 
-						if (ff != '' || fz != '') {
-							tmp += ' style="';
-
-							if (ds != '')
-								tmp += ds + ";";
+		getInfo : function() {
+			return {
+				longname : 'Fullpage',
+				author : 'Moxiecode Systems AB',
+				authorurl : 'http://tinymce.moxiecode.com',
+				infourl : 'http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/fullpage',
+				version : tinymce.majorVersion + "." + tinymce.minorVersion
+			};
+		},
 
-							if (ff != '')
-								tmp += 'font-family: ' + ff + ";";
-
-							if (fz != '')
-								tmp += 'font-size: ' + fz + ";";
-
-							tmp += '"';
-						}
+		// Private plugin internal methods
 
-						if (dtc != '')
-							tmp += ' text="' + dtc + '"';
-
-						tmp += '>\n';
-
-						inst.fullpageTopContent = tmp;
-					}
-				}
-
-				this._addToHead(inst);
-
-				break;
-
-			case "get_from_editor":
-				if (inst.fullpageTopContent)
-					content = inst.fullpageTopContent + content + "\n</body>\n</html>";
-
-				break;
-		}
-
-		// Pass through to next handler in chain
-		return content;
-	},
-
-	// Private plugin internal methods
+		_createSerializer : function() {
+			return new tinymce.dom.Serializer({
+				dom : this.editor.dom,
+				apply_source_formatting : true
+			});
+		},
 
-	_addToHead : function(inst) {
-		var doc = inst.getDoc();
-		var head = doc.getElementsByTagName("head")[0];
-		var body = doc.body;
-		var h = inst.fullpageTopContent;
-		var e = doc.createElement("body");
-		var nl, i, le, tmp;
+		_setContent : function(ed, o) {
+			var t = this, sp, ep, c = o.content;
 
-		// Remove stuff we don't want
-		h = h.replace(/(\r|\n)/gi, '');
-		h = h.replace(/<\?[^\>]*\>/gi, '');
-		h = h.replace(/<\/?(!DOCTYPE|head|html)[^\>]*\>/gi, '');
-		h = h.replace(/<script(.*?)<\/script>/gi, '');
-		h = h.replace(/<title(.*?)<\/title>/gi, '');
-		h = h.replace(/<(meta|base)[^>]*>/gi, '');
+			// Parse out head, body and footer
+			sp = c.indexOf('<body');
+			if (sp == -1)
+				sp = c.indexOf('<BODY');
 
-		// Make link and style elements into pre
-		h = h.replace(/<link([^>]*)\/>/gi, '<pre mce_type="link" $1></pre>');
-		//h = h.replace(/<style([^>]*)>(.*?)<\/style>/gi, '<pre mce_type="style" $1>$2</pre>');
-
-		// Make body a div
-		h = h.replace(/<body/gi, '<div mce_type="body"');
-		h += '</div>';
-
-		// Now crapy MSIE can parse it
-		e.innerHTML = h;
+			if (sp != -1) {
+				sp = c.indexOf('>', sp);
+				t.head = c.substring(0, sp + 1);
 
-		// Reset all body attributes
-		body.vLink = body.aLink = body.link = body.text = '';
-		body.style.cssText = '';
-
-		// Delete all old links
-		nl = head.getElementsByTagName('link');
-		for (i=0; i<nl.length; i++) {
-			if (tinyMCE.getAttrib(nl[i], 'mce_head') == "true")
-				nl[i].parentNode.removeChild(nl[i]);
-		}
-
-		// Add link elements
-		nl = e.getElementsByTagName('pre');
-		for (i=0; i<nl.length; i++) {
-			tmp = tinyMCE.getAttrib(nl[i], 'media');
-			if (tinyMCE.getAttrib(nl[i], 'mce_type') == "link" && (tmp == "" || tmp == "screen" || tmp == "all") && tinyMCE.getAttrib(nl[i], 'rel') == "stylesheet") {
-				le = doc.createElement("link");
-
-				le.rel = "stylesheet";
-				le.href = tinyMCE.getAttrib(nl[i], 'href');
-				le.setAttribute("mce_head", "true");
-
-				head.appendChild(le);
-			}
-		}
+				ep = c.indexOf('</body', sp);
+				if (ep == -1)
+					ep = c.indexOf('</body', ep);
 
-		// Add body attributes
-		nl = e.getElementsByTagName('div');
-		if (nl.length > 0) {
-			body.style.cssText = tinyMCE.getAttrib(nl[0], 'style');
-
-			if ((tmp = tinyMCE.getAttrib(nl[0], 'leftmargin')) != '' && body.style.marginLeft == '')
-				body.style.marginLeft = tmp + "px";
-
-			if ((tmp = tinyMCE.getAttrib(nl[0], 'rightmargin')) != '' && body.style.marginRight == '')
-				body.style.marginRight = tmp + "px";
-
-			if ((tmp = tinyMCE.getAttrib(nl[0], 'topmargin')) != '' && body.style.marginTop == '')
-				body.style.marginTop = tmp + "px";
-
-			if ((tmp = tinyMCE.getAttrib(nl[0], 'bottommargin')) != '' && body.style.marginBottom == '')
-				body.style.marginBottom = tmp + "px";
+				o.content = c.substring(sp + 1, ep);
+				t.foot = c.substring(ep);
+			} else {
+				t.head = '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">';
+				t.head += '\n<html>\n<head>\n<title>Untitled document</title>\n</head>\n<body>\n';
+				t.foot = '\n</body>\n</html>';
+			}
+		},
 
-			body.dir = tinyMCE.getAttrib(nl[0], 'dir');
-			body.vLink = tinyMCE.getAttrib(nl[0], 'vlink');
-			body.aLink = tinyMCE.getAttrib(nl[0], 'alink');
-			body.link = tinyMCE.getAttrib(nl[0], 'link');
-			body.text = tinyMCE.getAttrib(nl[0], 'text');
+		_getContent : function(ed, o) {
+			var t = this;
 
-			if ((tmp = tinyMCE.getAttrib(nl[0], 'background')) != '')
-				body.style.backgroundImage = "url('" + tmp + "')";
+			o.content = tinymce.trim(t.head) + '\n' + tinymce.trim(o.content) + '\n' + tinymce.trim(t.foot);
+		}
+	});
 
-			if ((tmp = tinyMCE.getAttrib(nl[0], 'bgcolor')) != '')
-				body.style.backgroundColor = tmp;
-		}
-	}
-};
-
-tinyMCE.addPlugin("fullpage", TinyMCE_FullPagePlugin);
+	// Register plugin
+	tinymce.PluginManager.add('fullpage', tinymce.plugins.FullPagePlugin);
+})();
\ No newline at end of file
--- a/includes/clientside/tinymce/plugins/fullpage/fullpage.htm	Fri Feb 22 12:46:51 2008 -0500
+++ b/includes/clientside/tinymce/plugins/fullpage/fullpage.htm	Fri Feb 22 12:51:53 2008 -0500
@@ -1,101 +1,101 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
 <html xmlns="http://www.w3.org/1999/xhtml">
 <head>
-	<title>{$lang_fullpage_title}</title>
-	<script language="javascript" type="text/javascript" src="../../tiny_mce_popup.js"></script>
-	<script language="javascript" type="text/javascript" src="../../utils/mctabs.js"></script>
-	<script language="javascript" type="text/javascript" src="../../utils/mclayer.js"></script>
-	<script language="javascript" type="text/javascript" src="../../utils/form_utils.js"></script>
-	<script language="javascript" type="text/javascript" src="jscripts/fullpage.js"></script>
+	<title>{#fullpage_dlg.title}</title>
+	<script type="text/javascript" src="../../tiny_mce_popup.js"></script>
+	<script type="text/javascript" src="../../utils/mctabs.js"></script>
+	<script type="text/javascript" src="../../utils/form_utils.js"></script>
+	<script type="text/javascript" src="js/fullpage.js"></script>
 	<link href="css/fullpage.css" rel="stylesheet" type="text/css" />
 	<base target="_self" />
 </head>
-<body id="advlink" onload="tinyMCEPopup.executeOnLoad('init();');" style="display: none">
+<body id="advlink" style="display: none">
     <form onsubmit="updateAction();return false;" name="fullpage" action="#">
 		<div class="tabs">
 			<ul>
-				<li id="meta_tab" class="current"><span><a href="javascript:mcTabs.displayTab('meta_tab','meta_panel');" onmousedown="return false;">{$lang_fullpage_meta_tab}</a></span></li>
-				<li id="appearance_tab"><span><a href="javascript:mcTabs.displayTab('appearance_tab','appearance_panel');" onmousedown="return false;">{$lang_fullpage_appearance_tab}</a></span></li>
-				<li id="advanced_tab"><span><a href="javascript:mcTabs.displayTab('advanced_tab','advanced_panel');" onmousedown="return false;">{$lang_fullpage_advanced_tab}</a></span></li>
+				<li id="meta_tab" class="current"><span><a href="javascript:mcTabs.displayTab('meta_tab','meta_panel');" onmousedown="return false;">{#fullpage_dlg.meta_tab}</a></span></li>
+				<li id="appearance_tab"><span><a href="javascript:mcTabs.displayTab('appearance_tab','appearance_panel');" onmousedown="return false;">{#fullpage_dlg.appearance_tab}</a></span></li>
+				<li id="advanced_tab"><span><a href="javascript:mcTabs.displayTab('advanced_tab','advanced_panel');" onmousedown="return false;">{#fullpage_dlg.advanced_tab}</a></span></li>
 			</ul>
 		</div>
 
 		<div class="panel_wrapper">
 			<div id="meta_panel" class="panel current">
 				<fieldset>
-					<legend>{$lang_fullpage_meta_props}</legend>
+					<legend>{#fullpage_dlg.meta_props}</legend>
 
 					<table border="0" cellpadding="4" cellspacing="0">
 						<tr>
-							<td nowrap="nowrap"><label for="metatitle">{$lang_fullpage_meta_title}</label>&nbsp;</td>
+							<td nowrap="nowrap"><label for="metatitle">{#fullpage_dlg.meta_title}</label>&nbsp;</td>
 							<td><input type="text" id="metatitle" name="metatitle" value="" /></td>
 						</tr>
 						<tr>
-							<td nowrap="nowrap"><label for="metakeywords">{$lang_fullpage_meta_keywords}</label>&nbsp;</td>
-							<td><textarea id="metakeywords" name="metakeywords" rows="3"></textarea></td>
+							<td nowrap="nowrap"><label for="metakeywords">{#fullpage_dlg.meta_keywords}</label>&nbsp;</td>
+							<td><textarea id="metakeywords" name="metakeywords" rows="4"></textarea></td>
 						</tr>
 						<tr>
-							<td nowrap="nowrap"><label for="metadescription">{$lang_fullpage_meta_description}</label>&nbsp;</td>
-							<td><textarea id="metadescription" name="metadescription" rows="3"></textarea></td>
+							<td nowrap="nowrap"><label for="metadescription">{#fullpage_dlg.meta_description}</label>&nbsp;</td>
+							<td><textarea id="metadescription" name="metadescription" rows="4"></textarea></td>
 						</tr>
 						<tr>
-							<td nowrap="nowrap"><label for="metaauthor">{$lang_fullpage_author}</label>&nbsp;</td>
+							<td nowrap="nowrap"><label for="metaauthor">{#fullpage_dlg.author}</label>&nbsp;</td>
 							<td><input type="text" id="metaauthor" name="metaauthor" value="" /></td>
 						</tr>
 						<tr>
-							<td nowrap="nowrap"><label for="metacopyright">{$lang_fullpage_copyright}</label>&nbsp;</td>
+							<td nowrap="nowrap"><label for="metacopyright">{#fullpage_dlg.copyright}</label>&nbsp;</td>
 							<td><input type="text" id="metacopyright" name="metacopyright" value="" /></td>
 						</tr>
 						<tr>
-							<td nowrap="nowrap"><label for="metarobots">{$lang_fullpage_meta_robots}</label>&nbsp;</td>
+							<td nowrap="nowrap"><label for="metarobots">{#fullpage_dlg.meta_robots}</label>&nbsp;</td>
 							<td>
-<select id="metarobots" name="metarobots">
-			<option value="">{$lang_not_set}</option> 
-			<option value="index,follow">{$lang_fullpage_meta_index_follow}</option>
-			<option value="index,nofollow">{$lang_fullpage_meta_index_nofollow}</option>
-			<option value="noindex,follow">{$lang_fullpage_meta_noindex_follow}</option>
-			<option value="noindex,nofollow">{$lang_fullpage_meta_noindex_nofollow}</option>
-</select>
+								<select id="metarobots" name="metarobots">
+											<option value="">{#not_set}</option> 
+											<option value="index,follow">{#fullpage_dlg.meta_index_follow}</option>
+											<option value="index,nofollow">{#fullpage_dlg.meta_index_nofollow}</option>
+											<option value="noindex,follow">{#fullpage_dlg.meta_noindex_follow}</option>
+											<option value="noindex,nofollow">{#fullpage_dlg.meta_noindex_nofollow}</option>
+								</select>
 							</td>
 						</tr>
 					</table>
 				</fieldset>
 
 				<fieldset>
-					<legend>{$lang_fullpage_langprops}</legend>
+					<legend>{#fullpage_dlg.langprops}</legend>
 
 					<table border="0" cellpadding="4" cellspacing="0">
 						<tr>
-							<td class="column1"><label for="docencoding">{$lang_fullpage_encoding}</label></td> 
+							<td class="column1"><label for="docencoding">{#fullpage_dlg.encoding}</label></td> 
 							<td>
 								<select id="docencoding" name="docencoding"> 
-										<option value="">{$lang_not_set}</option>
+										<option value="">{#not_set}</option>
 								</select>
 							</td> 
 						</tr>
 						<tr>
-							<td nowrap="nowrap"><label for="doctypes">{$lang_fullpage_doctypes}</label>&nbsp;</td>
+							<td nowrap="nowrap"><label for="doctypes">{#fullpage_dlg.doctypes}</label>&nbsp;</td>
 							<td>
 								<select id="doctypes" name="doctypes">
-										<option value="">{$lang_not_set}</option>
+										<option value="">{#not_set}</option>
 								</select>
 							</td>
 						</tr>
 						<tr>
-							<td nowrap="nowrap"><label for="langcode">{$lang_fullpage_langcode}</label>&nbsp;</td>
+							<td nowrap="nowrap"><label for="langcode">{#fullpage_dlg.langcode}</label>&nbsp;</td>
 							<td><input type="text" id="langcode" name="langcode" value="" /></td>
 						</tr>
 						<tr>
-							<td class="column1"><label for="langdir">{$lang_fullpage_langdir}</label></td> 
+							<td class="column1"><label for="langdir">{#fullpage_dlg.langdir}</label></td> 
 							<td>
 								<select id="langdir" name="langdir"> 
-										<option value="">{$lang_not_set}</option> 
-										<option value="ltr">{$lang_fullpage_ltr}</option> 
-										<option value="rtl">{$lang_fullpage_rtl}</option> 
+										<option value="">{#not_set}</option> 
+										<option value="ltr">{#fullpage_dlg.ltr}</option> 
+										<option value="rtl">{#fullpage_dlg.rtl}</option> 
 								</select>
 							</td> 
 						</tr>
 						<tr>
-							<td nowrap="nowrap"><label for="xml_pi">{$lang_fullpage_xml_pi}</label>&nbsp;</td>
+							<td nowrap="nowrap"><label for="xml_pi">{#fullpage_dlg.xml_pi}</label>&nbsp;</td>
 							<td><input type="checkbox" id="xml_pi" name="xml_pi" class="checkbox" /></td>
 						</tr>
 					</table>
@@ -104,29 +104,29 @@
 
 			<div id="appearance_panel" class="panel">
 				<fieldset>
-					<legend>{$lang_fullpage_appearance_textprops}</legend>
+					<legend>{#fullpage_dlg.appearance_textprops}</legend>
 
 					<table border="0" cellpadding="4" cellspacing="0">
 						<tr>
-							<td class="column1"><label for="fontface">{$lang_fullpage_fontface}</label></td> 
+							<td class="column1"><label for="fontface">{#fullpage_dlg.fontface}</label></td> 
 							<td>
 								<select id="fontface" name="fontface" onchange="changedStyleField(this);">
-										<option value="">{$lang_not_set}</option>
+										<option value="">{#not_set}</option>
 								</select>
 							</td> 
 						</tr>
 
 						<tr>
-							<td class="column1"><label for="fontsize">{$lang_fullpage_fontsize}</label></td> 
+							<td class="column1"><label for="fontsize">{#fullpage_dlg.fontsize}</label></td> 
 							<td>
 								<select id="fontsize" name="fontsize" onchange="changedStyleField(this);">
-										<option value="">{$lang_not_set}</option>
+										<option value="">{#not_set}</option>
 								</select>
 							</td>
 						</tr>
 
 						<tr>
-							<td class="column1"><label for="textcolor">{$lang_fullpage_textcolor}</label></td> 
+							<td class="column1"><label for="textcolor">{#fullpage_dlg.textcolor}</label></td> 
 							<td>
 								<table border="0" cellpadding="0" cellspacing="0">
 									<tr>
@@ -140,11 +140,11 @@
 				</fieldset>
 
 				<fieldset>
-					<legend>{$lang_fullpage_appearance_bgprops}</legend>
+					<legend>{#fullpage_dlg.appearance_bgprops}</legend>
 
 					<table border="0" cellpadding="4" cellspacing="0">
 						<tr>
-							<td class="column1"><label for="bgimage">{$lang_fullpage_bgimage}</label></td> 
+							<td class="column1"><label for="bgimage">{#fullpage_dlg.bgimage}</label></td> 
 							<td>
 								<table border="0" cellpadding="0" cellspacing="0">
 									<tr>
@@ -155,7 +155,7 @@
 							</td>
 						</tr>
 						<tr>
-							<td class="column1"><label for="bgcolor">{$lang_fullpage_bgcolor}</label></td> 
+							<td class="column1"><label for="bgcolor">{#fullpage_dlg.bgcolor}</label></td> 
 							<td>
 								<table border="0" cellpadding="0" cellspacing="0">
 									<tr>
@@ -169,30 +169,30 @@
 				</fieldset>
 
 				<fieldset>
-					<legend>{$lang_fullpage_appearance_marginprops}</legend>
+					<legend>{#fullpage_dlg.appearance_marginprops}</legend>
 
 					<table border="0" cellpadding="4" cellspacing="0">
 						<tr>
-							<td class="column1"><label for="leftmargin">{$lang_fullpage_left_margin}</label></td> 
+							<td class="column1"><label for="leftmargin">{#fullpage_dlg.left_margin}</label></td> 
 							<td><input id="leftmargin" name="leftmargin" type="text" value="" onchange="changedStyleField(this);" /></td>
-							<td class="column1"><label for="rightmargin">{$lang_fullpage_right_margin}</label></td> 
+							<td class="column1"><label for="rightmargin">{#fullpage_dlg.right_margin}</label></td> 
 							<td><input id="rightmargin" name="rightmargin" type="text" value="" onchange="changedStyleField(this);" /></td>
 						</tr>
 						<tr>
-							<td class="column1"><label for="topmargin">{$lang_fullpage_top_margin}</label></td> 
+							<td class="column1"><label for="topmargin">{#fullpage_dlg.top_margin}</label></td> 
 							<td><input id="topmargin" name="topmargin" type="text" value="" onchange="changedStyleField(this);" /></td>
-							<td class="column1"><label for="bottommargin">{$lang_fullpage_bottom_margin}</label></td> 
+							<td class="column1"><label for="bottommargin">{#fullpage_dlg.bottom_margin}</label></td> 
 							<td><input id="bottommargin" name="bottommargin" type="text" value="" onchange="changedStyleField(this);" /></td>
 						</tr>
 					</table>
 				</fieldset>
 
 				<fieldset>
-					<legend>{$lang_fullpage_appearance_linkprops}</legend>
+					<legend>{#fullpage_dlg.appearance_linkprops}</legend>
 
 					<table border="0" cellpadding="4" cellspacing="0">
 						<tr>
-							<td class="column1"><label for="link_color">{$lang_fullpage_link_color}</label></td> 
+							<td class="column1"><label for="link_color">{#fullpage_dlg.link_color}</label></td> 
 							<td>
 								<table border="0" cellpadding="0" cellspacing="0">
 									<tr>
@@ -202,7 +202,7 @@
 								</table>
 							</td>
 
-							<td class="column1"><label for="visited_color">{$lang_fullpage_visited_color}</label></td> 
+							<td class="column1"><label for="visited_color">{#fullpage_dlg.visited_color}</label></td> 
 							<td>
 								<table border="0" cellpadding="0" cellspacing="0">
 									<tr>
@@ -214,7 +214,7 @@
 						</tr>
 
 						<tr>
-							<td class="column1"><label for="active_color">{$lang_fullpage_active_color}</label></td> 
+							<td class="column1"><label for="active_color">{#fullpage_dlg.active_color}</label></td> 
 							<td>
 								<table border="0" cellpadding="0" cellspacing="0">
 									<tr>
@@ -227,7 +227,7 @@
 							<td>&nbsp;</td>
 							<td>&nbsp;</td>
 
-<!--							<td class="column1"><label for="hover_color">{$lang_fullpage_hover_color}</label></td> 
+<!--							<td class="column1"><label for="hover_color">{#fullpage_dlg.hover_color}</label></td> 
 							<td>
 								<table border="0" cellpadding="0" cellspacing="0">
 									<tr>
@@ -241,11 +241,11 @@
 				</fieldset>
 
 				<fieldset>
-					<legend>{$lang_fullpage_appearance_style}</legend>
+					<legend>{#fullpage_dlg.appearance_style}</legend>
 
 					<table border="0" cellpadding="4" cellspacing="0">
 						<tr>
-							<td class="column1"><label for="stylesheet">{$lang_fullpage_stylesheet}</label></td> 
+							<td class="column1"><label for="stylesheet">{#fullpage_dlg.stylesheet}</label></td> 
 							<td><table border="0" cellpadding="0" cellspacing="0">
 									<tr>
 										<td><input id="stylesheet" name="stylesheet" type="text" value="" /></td>
@@ -254,7 +254,7 @@
 								</table></td>
 						</tr>
 						<tr>
-							<td class="column1"><label for="style">{$lang_fullpage_style}</label></td> 
+							<td class="column1"><label for="style">{#fullpage_dlg.style}</label></td> 
 							<td><input id="style" name="style" type="text" value="" onchange="changedStyleField(this);" /></td>
 						</tr>
 					</table>
@@ -264,28 +264,28 @@
 			<div id="advanced_panel" class="panel">
 				<div id="addmenu">
 					<table border="0" cellpadding="0" cellspacing="0">
-						<tr><td><a href="javascript:addHeadElm('title');" onmousedown="return false;"><span>{$lang_fullpage_add_title}</span></a></td></tr>
-						<tr><td><a href="javascript:addHeadElm('meta');" onmousedown="return false;"><span>{$lang_fullpage_add_meta}</span></a></td></tr>
-						<tr><td><a href="javascript:addHeadElm('script');" onmousedown="return false;"><span>{$lang_fullpage_add_script}</span></a></td></tr>
-						<tr><td><a href="javascript:addHeadElm('style');" onmousedown="return false;"><span>{$lang_fullpage_add_style}</span></a></td></tr>
-						<tr><td><a href="javascript:addHeadElm('link');" onmousedown="return false;"><span>{$lang_fullpage_add_link}</span></a></td></tr>
-						<tr><td><a href="javascript:addHeadElm('base');" onmousedown="return false;"><span>{$lang_fullpage_add_base}</span></a></td></tr>
-						<tr><td><a href="javascript:addHeadElm('comment');" onmousedown="return false;"><span>{$lang_fullpage_add_comment}</span></a></td></tr>
+						<tr><td><a href="javascript:addHeadElm('title');" onmousedown="return false;"><span>{#fullpage_dlg.add_title}</span></a></td></tr>
+						<tr><td><a href="javascript:addHeadElm('meta');" onmousedown="return false;"><span>{#fullpage_dlg.add_meta}</span></a></td></tr>
+						<tr><td><a href="javascript:addHeadElm('script');" onmousedown="return false;"><span>{#fullpage_dlg.add_script}</span></a></td></tr>
+						<tr><td><a href="javascript:addHeadElm('style');" onmousedown="return false;"><span>{#fullpage_dlg.add_style}</span></a></td></tr>
+						<tr><td><a href="javascript:addHeadElm('link');" onmousedown="return false;"><span>{#fullpage_dlg.add_link}</span></a></td></tr>
+						<tr><td><a href="javascript:addHeadElm('base');" onmousedown="return false;"><span>{#fullpage_dlg.add_base}</span></a></td></tr>
+						<tr><td><a href="javascript:addHeadElm('comment');" onmousedown="return false;"><span>{#fullpage_dlg.add_comment}</span></a></td></tr>
 					</table>
 				</div>
 
 				<fieldset>
-					<legend>{$lang_fullpage_head_elements}</legend>
+					<legend>{#fullpage_dlg.head_elements}</legend>
 
 					<div class="headlistwrapper">
 						<div class="toolbar">
 							<div style="float: left">
-								<a id="addbutton" href="javascript:showAddMenu();" onmousedown="return false;" class="addbutton" title="{$lang_fullpage_add}"></a>
-								<a href="#" onmousedown="return false;" class="removebutton" title="{$lang_fullpage_remove}"></a>
+								<a id="addbutton" href="javascript:showAddMenu();" onmousedown="return false;" class="addbutton" title="{#fullpage_dlg.add}"></a>
+								<a href="#" onmousedown="return false;" class="removebutton" title="{#fullpage_dlg.remove}"></a>
 							</div>
 							<div style="float: right">
-								<a href="#" onmousedown="return false;" class="moveupbutton" title="{$lang_fullpage_moveup}"></a>
-								<a href="#" onmousedown="return false;" class="movedownbutton" title="{$lang_fullpage_movedown}"></a>
+								<a href="#" onmousedown="return false;" class="moveupbutton" title="{#fullpage_dlg.moveup}"></a>
+								<a href="#" onmousedown="return false;" class="movedownbutton" title="{#fullpage_dlg.movedown}"></a>
 							</div>
 							<br style="clear: both" />
 						</div>
@@ -303,49 +303,49 @@
 				</fieldset>
 
 				<fieldset id="meta_element">
-					<legend>{$lang_fullpage_meta_element}</legend>
+					<legend>{#fullpage_dlg.meta_element}</legend>
 
 					<table border="0" cellpadding="4" cellspacing="0">
 						<tr>
-							<td class="column1"><label for="element_meta_type">{$lang_fullpage_type}</label></td> 
+							<td class="column1"><label for="element_meta_type">{#fullpage_dlg.type}</label></td> 
 							<td><select id="element_meta_type">
 										<option value="name">name</option>
 										<option value="http-equiv">http-equiv</option>
 								</select></td>
 						</tr>
 						<tr>
-							<td class="column1"><label for="element_meta_name">{$lang_fullpage_name}</label></td> 
+							<td class="column1"><label for="element_meta_name">{#fullpage_dlg.name}</label></td> 
 							<td><input id="element_meta_name" name="element_meta_name" type="text" value="" /></td>
 						</tr>
 						<tr>
-							<td class="column1"><label for="element_meta_content">{$lang_fullpage_content}</label></td> 
+							<td class="column1"><label for="element_meta_content">{#fullpage_dlg.content}</label></td> 
 							<td><input id="element_meta_content" name="element_meta_content" type="text" value="" /></td>
 						</tr>
 					</table>
 
-					<input type="button" id="meta_updateelement" class="updateElementButton" name="update" value="{$lang_update}" onclick="updateElement();" />
+					<input type="button" id="meta_updateelement" class="updateElementButton" name="update" value="{#update}" onclick="updateElement();" />
 				</fieldset>
 
 				<fieldset id="title_element">
-					<legend>{$lang_fullpage_title_element}</legend>
+					<legend>{#fullpage_dlg.title_element}</legend>
 
 					<table border="0" cellpadding="4" cellspacing="0">
 						<tr>
-							<td class="column1"><label for="element_title">{$lang_fullpage_meta_title}</label></td> 
+							<td class="column1"><label for="element_title">{#fullpage_dlg.meta_title}</label></td> 
 							<td><input id="element_title" name="element_title" type="text" value="" /></td>
 						</tr>
 					</table>
 
-					<input type="button" id="title_updateelement" class="updateElementButton" name="update" value="{$lang_update}" onclick="updateElement();" />
+					<input type="button" id="title_updateelement" class="updateElementButton" name="update" value="{#update}" onclick="updateElement();" />
 				</fieldset>
 
 				<fieldset id="script_element">
-					<legend>{$lang_fullpage_script_element}</legend>
+					<legend>{#fullpage_dlg.script_element}</legend>
 
 					<div class="tabs">
 						<ul>
-							<li id="script_props_tab" class="current"><span><a href="javascript:mcTabs.displayTab('script_props_tab','script_props_panel');" onmousedown="return false;">{$lang_fullpage_properties}</a></span></li>
-							<li id="script_value_tab"><span><a href="javascript:mcTabs.displayTab('script_value_tab','script_value_panel');" onmousedown="return false;">{$lang_fullpage_value}</a></span></li>
+							<li id="script_props_tab" class="current"><span><a href="javascript:mcTabs.displayTab('script_props_tab','script_props_panel');" onmousedown="return false;">{#fullpage_dlg.properties}</a></span></li>
+							<li id="script_value_tab"><span><a href="javascript:mcTabs.displayTab('script_value_tab','script_value_panel');" onmousedown="return false;">{#fullpage_dlg.value}</a></span></li>
 						</ul>
 					</div>
 
@@ -355,7 +355,7 @@
 						<div id="script_props_panel" class="panel current">
 							<table border="0" cellpadding="4" cellspacing="0">
 								<tr>
-									<td class="column1"><label for="element_script_type">{$lang_fullpage_type}</label></td> 
+									<td class="column1"><label for="element_script_type">{#fullpage_dlg.type}</label></td> 
 									<td><select id="element_script_type">
 										<option value="text/javascript">text/javascript</option>
 										<option value="text/jscript">text/jscript</option>
@@ -366,7 +366,7 @@
 									</select></td>
 								</tr>
 								<tr>
-									<td class="column1"><label for="element_script_src">{$lang_fullpage_src}</label></td> 
+									<td class="column1"><label for="element_script_src">{#fullpage_dlg.src}</label></td> 
 									<td><table border="0" cellpadding="0" cellspacing="0">
 									<tr>
 										<td><input id="element_script_src" name="element_script_src" type="text" value="" /></td>
@@ -375,11 +375,11 @@
 								</table></td>
 								</tr>
 								<tr>
-									<td class="column1"><label for="element_script_charset">{$lang_fullpage_charset}</label></td> 
-									<td><select id="element_script_charset"><option value="">{$lang_not_set}</option></select></td>
+									<td class="column1"><label for="element_script_charset">{#fullpage_dlg.charset}</label></td> 
+									<td><select id="element_script_charset"><option value="">{#not_set}</option></select></td>
 								</tr>
 								<tr>
-									<td class="column1"><label for="element_script_defer">{$lang_fullpage_defer}</label></td> 
+									<td class="column1"><label for="element_script_defer">{#fullpage_dlg.defer}</label></td> 
 									<td><input type="checkbox" id="element_script_defer" name="element_script_defer" class="checkbox" /></td>
 								</tr>
 							</table>
@@ -390,16 +390,16 @@
 						</div>
 					</div>
 
-					<input type="button" id="script_updateelement" class="updateElementButton" name="update" value="{$lang_update}" onclick="updateElement();" />
+					<input type="button" id="script_updateelement" class="updateElementButton" name="update" value="{#update}" onclick="updateElement();" />
 				</fieldset>
 
 				<fieldset id="style_element">
-					<legend>{$lang_fullpage_style_element}</legend>
+					<legend>{#fullpage_dlg.style_element}</legend>
 
 					<div class="tabs">
 						<ul>
-							<li id="style_props_tab" class="current"><span><a href="javascript:mcTabs.displayTab('style_props_tab','style_props_panel');" onmousedown="return false;">{$lang_fullpage_properties}</a></span></li>
-							<li id="style_value_tab"><span><a href="javascript:mcTabs.displayTab('style_value_tab','style_value_panel');" onmousedown="return false;">{$lang_fullpage_value}</a></span></li>
+							<li id="style_props_tab" class="current"><span><a href="javascript:mcTabs.displayTab('style_props_tab','style_props_panel');" onmousedown="return false;">{#fullpage_dlg.properties}</a></span></li>
+							<li id="style_value_tab"><span><a href="javascript:mcTabs.displayTab('style_value_tab','style_value_panel');" onmousedown="return false;">{#fullpage_dlg.value}</a></span></li>
 						</ul>
 					</div>
 
@@ -409,13 +409,13 @@
 						<div id="style_props_panel" class="panel current">
 							<table border="0" cellpadding="4" cellspacing="0">
 								<tr>
-									<td class="column1"><label for="element_style_type">{$lang_fullpage_type}</label></td> 
+									<td class="column1"><label for="element_style_type">{#fullpage_dlg.type}</label></td> 
 									<td><select id="element_style_type">
 										<option value="text/css">text/css</option>
 									</select></td>
 								</tr>
 								<tr>
-									<td class="column1"><label for="element_style_media">{$lang_fullpage_media}</label></td> 
+									<td class="column1"><label for="element_style_media">{#fullpage_dlg.media}</label></td> 
 									<td><select id="element_style_media"></select></td>
 								</tr>
 							</table>
@@ -426,33 +426,33 @@
 						</div>
 					</div>
 
-					<input type="button" id="style_updateelement" class="updateElementButton" name="update" value="{$lang_update}" onclick="updateElement();" />
+					<input type="button" id="style_updateelement" class="updateElementButton" name="update" value="{#update}" onclick="updateElement();" />
 				</fieldset>
 
 				<fieldset id="base_element">
-					<legend>{$lang_fullpage_base_element}</legend>
+					<legend>{#fullpage_dlg.base_element}</legend>
 
 					<table border="0" cellpadding="4" cellspacing="0">
 						<tr>
-							<td class="column1"><label for="element_base_href">{$lang_fullpage_href}</label></td> 
+							<td class="column1"><label for="element_base_href">{#fullpage_dlg.href}</label></td> 
 							<td><input id="element_base_href" name="element_base_href" type="text" value="" /></td>
 						</tr>
 						<tr>
-							<td class="column1"><label for="element_base_target">{$lang_fullpage_target}</label></td> 
+							<td class="column1"><label for="element_base_target">{#fullpage_dlg.target}</label></td> 
 							<td><input id="element_base_target" name="element_base_target" type="text" value="" /></td>
 						</tr>
 					</table>
 
-					<input type="button" id="base_updateelement" class="updateElementButton" name="update" value="{$lang_update}" onclick="updateElement();" />
+					<input type="button" id="base_updateelement" class="updateElementButton" name="update" value="{#update}" onclick="updateElement();" />
 				</fieldset>
 
 				<fieldset id="link_element">
-					<legend>{$lang_fullpage_link_element}</legend>
+					<legend>{#fullpage_dlg.link_element}</legend>
 
 					<div class="tabs">
 						<ul>
-							<li id="link_general_tab" class="current"><span><a href="javascript:mcTabs.displayTab('link_general_tab','link_general_panel');" onmousedown="return false;">{$lang_fullpage_general_props}</a></span></li>
-							<li id="link_advanced_tab"><span><a href="javascript:mcTabs.displayTab('link_advanced_tab','link_advanced_panel');" onmousedown="return false;">{$lang_fullpage_advanced_props}</a></span></li>
+							<li id="link_general_tab" class="current"><span><a href="javascript:mcTabs.displayTab('link_general_tab','link_general_panel');" onmousedown="return false;">{#fullpage_dlg.general_props}</a></span></li>
+							<li id="link_advanced_tab"><span><a href="javascript:mcTabs.displayTab('link_advanced_tab','link_advanced_panel');" onmousedown="return false;">{#fullpage_dlg.advanced_props}</a></span></li>
 						</ul>
 					</div>
 
@@ -462,7 +462,7 @@
 						<div id="link_general_panel" class="panel current">
 							<table border="0" cellpadding="4" cellspacing="0">
 								<tr>
-									<td class="column1"><label for="element_link_href">{$lang_fullpage_href}</label></td> 
+									<td class="column1"><label for="element_link_href">{#fullpage_dlg.href}</label></td> 
 									<td><table border="0" cellpadding="0" cellspacing="0">
 									<tr>
 										<td><input id="element_link_href" name="element_link_href" type="text" value="" /></td>
@@ -471,24 +471,24 @@
 								</table></td>
 								</tr>
 								<tr>
-									<td class="column1"><label for="element_link_title">{$lang_fullpage_meta_title}</label></td> 
+									<td class="column1"><label for="element_link_title">{#fullpage_dlg.meta_title}</label></td> 
 									<td><input id="element_link_title" name="element_link_title" type="text" value="" /></td>
 								</tr>
 								<tr>
-									<td class="column1"><label for="element_link_type">{$lang_fullpage_type}</label></td> 
+									<td class="column1"><label for="element_link_type">{#fullpage_dlg.type}</label></td> 
 									<td><select id="element_link_type" name="element_link_type">
 										<option value="text/css">text/css</option>
 										<option value="text/javascript">text/javascript</option>
 									</select></td>
 								</tr>
 								<tr>
-									<td class="column1"><label for="element_link_media">{$lang_fullpage_media}</label></td> 
+									<td class="column1"><label for="element_link_media">{#fullpage_dlg.media}</label></td> 
 									<td><select id="element_link_media" name="element_link_media"></select></td>
 								</tr>
 								<tr>
-									<td><label for="element_style_rel">{$lang_fullpage_rel}</label></td>
+									<td><label for="element_style_rel">{#fullpage_dlg.rel}</label></td>
 									<td><select id="element_style_rel" name="element_style_rel"> 
-											<option value="">{$lang_not_set}</option> 
+											<option value="">{#not_set}</option> 
 											<option value="stylesheet">Stylesheet</option>
 											<option value="alternate">Alternate</option>
 											<option value="designates">Designates</option>
@@ -513,21 +513,21 @@
 						<div id="link_advanced_panel" class="panel">
 							<table border="0" cellpadding="4" cellspacing="0">
 								<tr>
-									<td class="column1"><label for="element_link_charset">{$lang_fullpage_charset}</label></td> 
-									<td><select id="element_link_charset"><option value="">{$lang_not_set}</option></select></td>
+									<td class="column1"><label for="element_link_charset">{#fullpage_dlg.charset}</label></td> 
+									<td><select id="element_link_charset"><option value="">{#not_set}</option></select></td>
 								</tr>
 								<tr>
-									<td class="column1"><label for="element_link_hreflang">{$lang_fullpage_hreflang}</label></td> 
+									<td class="column1"><label for="element_link_hreflang">{#fullpage_dlg.hreflang}</label></td> 
 									<td><input id="element_link_hreflang" name="element_link_hreflang" type="text" value="" /></td>
 								</tr>
 								<tr>
-									<td class="column1"><label for="element_link_target">{$lang_fullpage_target}</label></td> 
+									<td class="column1"><label for="element_link_target">{#fullpage_dlg.target}</label></td> 
 									<td><input id="element_link_target" name="element_link_target" type="text" value="" /></td>
 								</tr>
 								<tr>
-									<td><label for="element_style_rev">{$lang_fullpage_rev}</label></td>
+									<td><label for="element_style_rev">{#fullpage_dlg.rev}</label></td>
 									<td><select id="element_style_rev" name="element_style_rev"> 
-											<option value="">{$lang_not_set}</option> 
+											<option value="">{#not_set}</option> 
 											<option value="alternate">Alternate</option> 
 											<option value="designates">Designates</option> 
 											<option value="stylesheet">Stylesheet</option> 
@@ -550,26 +550,26 @@
 						</div>
 					</div>
 
-					<input type="button" id="link_updateelement" class="updateElementButton" name="update" value="{$lang_update}" onclick="updateElement();" />
+					<input type="button" id="link_updateelement" class="updateElementButton" name="update" value="{#update}" onclick="updateElement();" />
 				</fieldset>
 
 				<fieldset id="comment_element">
-					<legend>{$lang_fullpage_comment_element}</legend>
+					<legend>{#fullpage_dlg.comment_element}</legend>
 
 					<textarea id="element_comment_value"></textarea>
 
-					<input type="button" id="comment_updateelement" class="updateElementButton" name="update" value="{$lang_update}" onclick="updateElement();" />
+					<input type="button" id="comment_updateelement" class="updateElementButton" name="update" value="{#update}" onclick="updateElement();" />
 				</fieldset>
 			</div>
 		</div>
 
 		<div class="mceActionPanel">
 			<div style="float: left">
-				<input type="button" id="insert" name="update" value="{$lang_update}" onclick="updateAction();" />
+				<input type="button" id="insert" name="update" value="{#update}" onclick="updateAction();" />
 			</div>
 
 			<div style="float: right">
-				<input type="button" id="cancel" name="cancel" value="{$lang_cancel}" onclick="tinyMCEPopup.close();" />
+				<input type="button" id="cancel" name="cancel" value="{#cancel}" onclick="tinyMCEPopup.close();" />
 			</div>
 		</div>
     </form>
Binary file includes/clientside/tinymce/plugins/fullpage/images/add.gif has changed
Binary file includes/clientside/tinymce/plugins/fullpage/images/fullpage.gif has changed
Binary file includes/clientside/tinymce/plugins/fullpage/images/move_down.gif has changed
Binary file includes/clientside/tinymce/plugins/fullpage/images/move_up.gif has changed
Binary file includes/clientside/tinymce/plugins/fullpage/images/remove.gif has changed
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/includes/clientside/tinymce/plugins/fullpage/js/fullpage.js	Fri Feb 22 12:51:53 2008 -0500
@@ -0,0 +1,461 @@
+tinyMCEPopup.requireLangPack();
+
+var doc;
+
+var defaultDocTypes = 
+	'XHTML 1.0 Transitional=<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">,' +
+	'XHTML 1.0 Frameset=<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Frameset//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-frameset.dtd">,' +
+	'XHTML 1.0 Strict=<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">,' +
+	'XHTML 1.1=<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">,' +
+	'HTML 4.01 Transitional=<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">,' +
+	'HTML 4.01 Strict=<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">,' +
+	'HTML 4.01 Frameset=<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Frameset//EN" "http://www.w3.org/TR/html4/frameset.dtd">';
+
+var defaultEncodings = 
+	'Western european (iso-8859-1)=iso-8859-1,' +
+	'Central European (iso-8859-2)=iso-8859-2,' +
+	'Unicode (UTF-8)=utf-8,' +
+	'Chinese traditional (Big5)=big5,' +
+	'Cyrillic (iso-8859-5)=iso-8859-5,' +
+	'Japanese (iso-2022-jp)=iso-2022-jp,' +
+	'Greek (iso-8859-7)=iso-8859-7,' +
+	'Korean (iso-2022-kr)=iso-2022-kr,' +
+	'ASCII (us-ascii)=us-ascii';
+
+var defaultMediaTypes = 
+	'all=all,' +
+	'screen=screen,' +
+	'print=print,' +
+	'tty=tty,' +
+	'tv=tv,' +
+	'projection=projection,' +
+	'handheld=handheld,' +
+	'braille=braille,' +
+	'aural=aural';
+
+var defaultFontNames = 'Arial=arial,helvetica,sans-serif;Courier New=courier new,courier,monospace;Georgia=georgia,times new roman,times,serif;Tahoma=tahoma,arial,helvetica,sans-serif;Times New Roman=times new roman,times,serif;Verdana=verdana,arial,helvetica,sans-serif;Impact=impact;WingDings=wingdings';
+var defaultFontSizes = '10px,11px,12px,13px,14px,15px,16px';
+
+function init() {
+	var f = document.forms['fullpage'], el = f.elements, e, i, p, doctypes, encodings, mediaTypes, fonts, ed = tinyMCEPopup.editor, dom = tinyMCEPopup.dom, style;
+
+	// Setup doctype select box
+	doctypes = ed.getParam("fullpage_doctypes", defaultDocTypes).split(',');
+	for (i=0; i<doctypes.length; i++) {
+		p = doctypes[i].split('=');
+
+		if (p.length > 1)
+			addSelectValue(f, 'doctypes', p[0], p[1]);
+	}
+
+	// Setup fonts select box
+	fonts = ed.getParam("fullpage_fonts", defaultFontNames).split(';');
+	for (i=0; i<fonts.length; i++) {
+		p = fonts[i].split('=');
+
+		if (p.length > 1)
+			addSelectValue(f, 'fontface', p[0], p[1]);
+	}
+
+	// Setup fontsize select box
+	fonts = ed.getParam("fullpage_fontsizes", defaultFontSizes).split(',');
+	for (i=0; i<fonts.length; i++)
+		addSelectValue(f, 'fontsize', fonts[i], fonts[i]);
+
+	// Setup mediatype select boxs
+	mediaTypes = ed.getParam("fullpage_media_types", defaultMediaTypes).split(',');
+	for (i=0; i<mediaTypes.length; i++) {
+		p = mediaTypes[i].split('=');
+
+		if (p.length > 1) {
+			addSelectValue(f, 'element_style_media', p[0], p[1]);
+			addSelectValue(f, 'element_link_media', p[0], p[1]);
+		}
+	}
+
+	// Setup encodings select box
+	encodings = ed.getParam("fullpage_encodings", defaultEncodings).split(',');
+	for (i=0; i<encodings.length; i++) {
+		p = encodings[i].split('=');
+
+		if (p.length > 1) {
+			addSelectValue(f, 'docencoding', p[0], p[1]);
+			addSelectValue(f, 'element_script_charset', p[0], p[1]);
+			addSelectValue(f, 'element_link_charset', p[0], p[1]);
+		}
+	}
+
+	document.getElementById('bgcolor_pickcontainer').innerHTML = getColorPickerHTML('bgcolor_pick','bgcolor');
+	document.getElementById('link_color_pickcontainer').innerHTML = getColorPickerHTML('link_color_pick','link_color');
+	//document.getElementById('hover_color_pickcontainer').innerHTML = getColorPickerHTML('hover_color_pick','hover_color');
+	document.getElementById('visited_color_pickcontainer').innerHTML = getColorPickerHTML('visited_color_pick','visited_color');
+	document.getElementById('active_color_pickcontainer').innerHTML = getColorPickerHTML('active_color_pick','active_color');
+	document.getElementById('textcolor_pickcontainer').innerHTML = getColorPickerHTML('textcolor_pick','textcolor');
+	document.getElementById('stylesheet_browsercontainer').innerHTML = getBrowserHTML('stylesheetbrowser','stylesheet','file','fullpage');
+	document.getElementById('link_href_pickcontainer').innerHTML = getBrowserHTML('link_href_browser','element_link_href','file','fullpage');
+	document.getElementById('script_src_pickcontainer').innerHTML = getBrowserHTML('script_src_browser','element_script_src','file','fullpage');
+	document.getElementById('bgimage_pickcontainer').innerHTML = getBrowserHTML('bgimage_browser','bgimage','image','fullpage');
+
+	// Resize some elements
+	if (isVisible('stylesheetbrowser'))
+		document.getElementById('stylesheet').style.width = '220px';
+
+	if (isVisible('link_href_browser'))
+		document.getElementById('element_link_href').style.width = '230px';
+
+	if (isVisible('bgimage_browser'))
+		document.getElementById('bgimage').style.width = '210px';
+
+	// Add iframe
+	dom.add(document.body, 'iframe', {id : 'documentIframe', src : 'javascript:""', style : {display : 'none'}});
+	doc = dom.get('documentIframe').contentWindow.document;
+	h = tinyMCEPopup.getWindowArg('head_html');
+
+	// Preprocess the HTML disable scripts and urls
+	h = h.replace(/<script>/gi, '<script type="text/javascript">');
+	h = h.replace(/type=([\"\'])?/gi, 'type=$1-mce-');
+	h = h.replace(/(src=|href=)/g, 'mce_$1');
+
+	// Write in the content in the iframe
+	doc.write(h + '</body></html>');
+	doc.close();
+
+	// Parse xml and doctype
+	xmlVer = getReItem(/<\?\s*?xml.*?version\s*?=\s*?"(.*?)".*?\?>/gi, h, 1);
+	xmlEnc = getReItem(/<\?\s*?xml.*?encoding\s*?=\s*?"(.*?)".*?\?>/gi, h, 1);
+	docType = getReItem(/<\!DOCTYPE.*?>/gi, h, 0);
+	f.langcode.value = getReItem(/lang="(.*?)"/gi, h, 1);
+
+	// Parse title
+	if (e = doc.getElementsByTagName('title')[0])
+		el.metatitle.value = e.textContent || e.text;
+
+	// Parse meta
+	tinymce.each(doc.getElementsByTagName('meta'), function(n) {
+		var na = (n.getAttribute('name', 2) || '').toLowerCase(), va = n.getAttribute('content', 2), eq = n.getAttribute('httpEquiv', 2) || '';
+
+		e = el['meta' + na];
+
+		if (na == 'robots') {
+			selectByValue(f, 'metarobots', tinymce.trim(va), true, true);
+			return;
+		}
+
+		switch (eq.toLowerCase()) {
+			case "content-type":
+				tmp = getReItem(/charset\s*=\s*(.*)\s*/gi, value, 1);
+
+				// Override XML encoding
+				if (tmp != "")
+					xmlEnc = tmp;
+
+				return;
+		}
+
+		if (e)
+			e.value = va;
+	});
+
+	selectByValue(f, 'doctypes', docType, true, true);
+	selectByValue(f, 'docencoding', xmlEnc, true, true);
+	selectByValue(f, 'langdir', doc.body.getAttribute('dir', 2) || '', true, true);
+
+	if (xmlVer != '')
+		el.xml_pi.checked = true;
+
+	// Parse appearance
+
+	// Parse primary stylesheet
+	tinymce.each(doc.getElementsByTagName("link"), function(l) {
+		var m = l.getAttribute('media', 2) || '', t = l.getAttribute('type', 2) || '';
+
+		if (t == "-mce-text/css" && (m == "" || m == "screen" || m == "all") && (l.getAttribute('rel', 2) || '') == "stylesheet") {
+			f.stylesheet.value = l.getAttribute('mce_href', 2) || '';
+			return false;
+		}
+	});
+
+	// Get from style elements
+	tinymce.each(doc.getElementsByTagName("style"), function(st) {
+		var tmp = parseStyleElement(st);
+
+		for (x=0; x<tmp.length; x++) {
+			if (tmp[x].rule.indexOf('a:visited') != -1 && tmp[x].data['color'])
+				f.visited_color.value = tmp[x].data['color'];
+
+			if (tmp[x].rule.indexOf('a:link') != -1 && tmp[x].data['color'])
+				f.link_color.value = tmp[x].data['color'];
+
+			if (tmp[x].rule.indexOf('a:active') != -1 && tmp[x].data['color'])
+				f.active_color.value = tmp[x].data['color'];
+		}
+	});
+
+	f.textcolor.value = tinyMCEPopup.dom.getAttrib(doc.body, "text");
+	f.active_color.value = tinyMCEPopup.dom.getAttrib(doc.body, "alink");
+	f.link_color.value = tinyMCEPopup.dom.getAttrib(doc.body, "link");
+	f.visited_color.value = tinyMCEPopup.dom.getAttrib(doc.body, "vlink");
+	f.bgcolor.value = tinyMCEPopup.dom.getAttrib(doc.body, "bgcolor");
+	f.bgimage.value = tinyMCEPopup.dom.getAttrib(doc.body, "background");
+
+	// Get from style info
+	style = tinyMCEPopup.dom.parseStyle(tinyMCEPopup.dom.getAttrib(doc.body, 'style'));
+
+	if (style['font-family'])
+		selectByValue(f, 'fontface', style['font-family'], true, true);
+	else
+		selectByValue(f, 'fontface', ed.getParam("fullpage_default_fontface", ""), true, true);
+
+	if (style['font-size'])
+		selectByValue(f, 'fontsize', style['font-size'], true, true);
+	else
+		selectByValue(f, 'fontsize', ed.getParam("fullpage_default_fontsize", ""), true, true);
+
+	if (style['color'])
+		f.textcolor.value = convertRGBToHex(style['color']);
+
+	if (style['background-image'])
+		f.bgimage.value = style['background-image'].replace(new RegExp("url\\('?([^']*)'?\\)", 'gi'), "$1");
+
+	if (style['background-color'])
+		f.bgcolor.value = style['background-color'];
+
+	if (style['margin']) {
+		tmp = style['margin'].replace(/[^0-9 ]/g, '');
+		tmp = tmp.split(/ +/);
+		f.topmargin.value = tmp.length > 0 ? tmp[0] : '';
+		f.rightmargin.value = tmp.length > 1 ? tmp[1] : tmp[0];
+		f.bottommargin.value = tmp.length > 2 ? tmp[2] : tmp[0];
+		f.leftmargin.value = tmp.length > 3 ? tmp[3] : tmp[0];
+	}
+
+	if (style['margin-left'])
+		f.leftmargin.value = style['margin-left'].replace(/[^0-9]/g, '');
+
+	if (style['margin-right'])
+		f.rightmargin.value = style['margin-right'].replace(/[^0-9]/g, '');
+
+	if (style['margin-top'])
+		f.topmargin.value = style['margin-top'].replace(/[^0-9]/g, '');
+
+	if (style['margin-bottom'])
+		f.bottommargin.value = style['margin-bottom'].replace(/[^0-9]/g, '');
+
+	f.style.value = tinyMCEPopup.dom.serializeStyle(style);
+
+	// Update colors
+	updateColor('textcolor_pick', 'textcolor');
+	updateColor('bgcolor_pick', 'bgcolor');
+	updateColor('visited_color_pick', 'visited_color');
+	updateColor('active_color_pick', 'active_color');
+	updateColor('link_color_pick', 'link_color');
+}
+
+function getReItem(r, s, i) {
+	var c = r.exec(s);
+
+	if (c && c.length > i)
+		return c[i];
+
+	return '';
+}
+
+function updateAction() {
+	var f = document.forms[0], nl, i, h, v, s, head, html, l, tmp, addlink = true, ser;
+
+	head = doc.getElementsByTagName('head')[0];
+
+	// Fix scripts without a type
+	nl = doc.getElementsByTagName('script');
+	for (i=0; i<nl.length; i++) {
+		if (tinyMCEPopup.dom.getAttrib(nl[i], 'mce_type') == '')
+			nl[i].setAttribute('mce_type', 'text/javascript');
+	}
+
+	// Get primary stylesheet
+	nl = doc.getElementsByTagName("link");
+	for (i=0; i<nl.length; i++) {
+		l = nl[i];
+
+		tmp = tinyMCEPopup.dom.getAttrib(l, 'media');
+
+		if (tinyMCEPopup.dom.getAttrib(l, 'mce_type') == "text/css" && (tmp == "" || tmp == "screen" || tmp == "all") && tinyMCEPopup.dom.getAttrib(l, 'rel') == "stylesheet") {
+			addlink = false;
+
+			if (f.stylesheet.value == '')
+				l.parentNode.removeChild(l);
+			else
+				l.setAttribute('mce_href', f.stylesheet.value);
+
+			break;
+		}
+	}
+
+	// Add new link
+	if (f.stylesheet.value != '') {
+		l = doc.createElement('link');
+
+		l.setAttribute('type', 'text/css');
+		l.setAttribute('mce_href', f.stylesheet.value);
+		l.setAttribute('rel', 'stylesheet');
+
+		head.appendChild(l);
+	}
+
+	setMeta(head, 'keywords', f.metakeywords.value);
+	setMeta(head, 'description', f.metadescription.value);
+	setMeta(head, 'author', f.metaauthor.value);
+	setMeta(head, 'copyright', f.metacopyright.value);
+	setMeta(head, 'robots', getSelectValue(f, 'metarobots'));
+	setMeta(head, 'Content-Type', getSelectValue(f, 'docencoding'));
+
+	doc.body.dir = getSelectValue(f, 'langdir');
+	doc.body.style.cssText = f.style.value;
+
+	doc.body.setAttribute('vLink', f.visited_color.value);
+	doc.body.setAttribute('link', f.link_color.value);
+	doc.body.setAttribute('text', f.textcolor.value);
+	doc.body.setAttribute('aLink', f.active_color.value);
+
+	doc.body.style.fontFamily = getSelectValue(f, 'fontface');
+	doc.body.style.fontSize = getSelectValue(f, 'fontsize');
+	doc.body.style.backgroundColor = f.bgcolor.value;
+
+	if (f.leftmargin.value != '')
+		doc.body.style.marginLeft = f.leftmargin.value + 'px';
+
+	if (f.rightmargin.value != '')
+		doc.body.style.marginRight = f.rightmargin.value + 'px';
+
+	if (f.bottommargin.value != '')
+		doc.body.style.marginBottom = f.bottommargin.value + 'px';
+
+	if (f.topmargin.value != '')
+		doc.body.style.marginTop = f.topmargin.value + 'px';
+
+	html = doc.getElementsByTagName('html')[0];
+	html.setAttribute('lang', f.langcode.value);
+	html.setAttribute('xml:lang', f.langcode.value);
+
+	if (f.bgimage.value != '')
+		doc.body.style.backgroundImage = "url('" + f.bgimage.value + "')";
+	else
+		doc.body.style.backgroundImage = '';
+
+	ser = tinyMCEPopup.editor.plugins.fullpage._createSerializer();
+	ser.setRules('-title,meta[http-equiv|name|content],base[href|target],link[href|rel|type|title|media],style[type],script[type|language|src],html[lang|xml::lang|xmlns],body[style|dir|vlink|link|text|alink],head');
+
+	h = ser.serialize(doc.documentElement);
+	h = h.substring(0, h.lastIndexOf('</body>'));
+
+	if (h.indexOf('<title>') == -1)
+		h = h.replace(/<head.*?>/, '$&\n' + '<title>' + tinyMCEPopup.dom.encode(f.metatitle.value) + '</title>');
+	else
+		h = h.replace(/<title>(.*?)<\/title>/, '<title>' + tinyMCEPopup.dom.encode(f.metatitle.value) + '</title>');
+
+	if ((v = getSelectValue(f, 'doctypes')) != '')
+		h = v + '\n' + h;
+
+	if (f.xml_pi.checked) {
+		s = '<?xml version="1.0"';
+
+		if ((v = getSelectValue(f, 'docencoding')) != '')
+			s += ' encoding="' + v + '"';
+
+		s += '?>\n';
+		h = s + h;
+	}
+
+	h = h.replace(/type=\"\-mce\-/gi, 'type="');
+
+	tinyMCEPopup.editor.plugins.fullpage.head = h;
+	tinyMCEPopup.close();
+}
+
+function changedStyleField(field) {
+	//alert(field.id);
+}
+
+function setMeta(he, k, v) {
+	var nl, i, m;
+
+	nl = he.getElementsByTagName('meta');
+	for (i=0; i<nl.length; i++) {
+		if (k == 'Content-Type' && tinyMCEPopup.dom.getAttrib(nl[i], 'http-equiv') == k) {
+			if (v == '')
+				nl[i].parentNode.removeChild(nl[i]);
+			else
+				nl[i].setAttribute('content', "text/html; charset=" + v);
+
+			return;
+		}
+
+		if (tinyMCEPopup.dom.getAttrib(nl[i], 'name') == k) {
+			if (v == '')
+				nl[i].parentNode.removeChild(nl[i]);
+			else
+				nl[i].setAttribute('content', v);
+			return;
+		}
+	}
+
+	if (v == '')
+		return;
+
+	m = doc.createElement('meta');
+
+	if (k == 'Content-Type')
+		m.httpEquiv = k;
+	else
+		m.setAttribute('name', k);
+
+	m.setAttribute('content', v);
+	he.appendChild(m);
+}
+
+function parseStyleElement(e) {
+	var v = e.innerHTML;
+	var p, i, r;
+
+	v = v.replace(/<!--/gi, '');
+	v = v.replace(/-->/gi, '');
+	v = v.replace(/[\n\r]/gi, '');
+	v = v.replace(/\s+/gi, ' ');
+
+	r = [];
+	p = v.split(/{|}/);
+
+	for (i=0; i<p.length; i+=2) {
+		if (p[i] != "")
+			r[r.length] = {rule : tinymce.trim(p[i]), data : tinyMCEPopup.dom.parseStyle(p[i+1])};
+	}
+
+	return r;
+}
+
+function serializeStyleElement(d) {
+	var i, s, st;
+
+	s = '<!--\n';
+
+	for (i=0; i<d.length; i++) {
+		s += d[i].rule + ' {\n';
+
+		st = tinyMCE.serializeStyle(d[i].data);
+
+		if (st != '')
+			st += ';';
+
+		s += st.replace(/;/g, ';\n');
+		s += '}\n';
+
+		if (i != d.length - 1)
+			s += '\n';
+	}
+
+	s += '\n-->';
+
+	return s;
+}
+
+tinyMCEPopup.onInit.add(init);
--- a/includes/clientside/tinymce/plugins/fullpage/jscripts/fullpage.js	Fri Feb 22 12:46:51 2008 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,580 +0,0 @@
-//
-
-var defaultDocTypes = 
-	'XHTML 1.0 Transitional=<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">,' +
-	'XHTML 1.0 Frameset=<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Frameset//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-frameset.dtd">,' +
-	'XHTML 1.0 Strict=<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">,' +
-	'XHTML 1.1=<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">">,' +
-	'HTML 4.01 Transitional=<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">,' +
-	'HTML 4.01 Strict=<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">,' +
-	'HTML 4.01 Frameset=<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Frameset//EN" "http://www.w3.org/TR/html4/frameset.dtd">';
-
-var defaultEncodings = 
-	'Western european (iso-8859-1)=iso-8859-1,' +
-	'Central European (iso-8859-2)=iso-8859-2,' +
-	'Unicode (UTF-8)=utf-8,' +
-	'Chinese traditional (Big5)=big5,' +
-	'Cyrillic (iso-8859-5)=iso-8859-5,' +
-	'Japanese (iso-2022-jp)=iso-2022-jp,' +
-	'Greek (iso-8859-7)=iso-8859-7,' +
-	'Korean (iso-2022-kr)=iso-2022-kr,' +
-	'ASCII (us-ascii)=us-ascii';
-
-var defaultMediaTypes = 
-	'all=all,' +
-	'screen=screen,' +
-	'print=print,' +
-	'tty=tty,' +
-	'tv=tv,' +
-	'projection=projection,' +
-	'handheld=handheld,' +
-	'braille=braille,' +
-	'aural=aural';
-
-var defaultFontNames = 'Arial=arial,helvetica,sans-serif;Courier New=courier new,courier,monospace;Georgia=georgia,times new roman,times,serif;Tahoma=tahoma,arial,helvetica,sans-serif;Times New Roman=times new roman,times,serif;Verdana=verdana,arial,helvetica,sans-serif;Impact=impact;WingDings=wingdings';
-var defaultFontSizes = '10px,11px,12px,13px,14px,15px,16px';
-
-var addMenuLayer = new MCLayer("addmenu");
-var lastElementType = null;
-var topDoc;
-
-function init() {
-	var f = document.forms['fullpage'];
-	var i, p, doctypes, encodings, mediaTypes, fonts;
-	var inst = tinyMCE.getInstanceById(tinyMCE.getWindowArg('editor_id'));
-
-	// Setup doctype select box
-	doctypes = tinyMCE.getParam("fullpage_doctypes", defaultDocTypes).split(',');
-	for (i=0; i<doctypes.length; i++) {
-		p = doctypes[i].split('=');
-
-		if (p.length > 1)
-			addSelectValue(f, 'doctypes', p[0], p[1]);
-	}
-
-	// Setup fonts select box
-	fonts = tinyMCE.getParam("fullpage_fonts", defaultFontNames).split(';');
-	for (i=0; i<fonts.length; i++) {
-		p = fonts[i].split('=');
-
-		if (p.length > 1)
-			addSelectValue(f, 'fontface', p[0], p[1]);
-	}
-
-	// Setup fontsize select box
-	fonts = tinyMCE.getParam("fullpage_fontsizes", defaultFontSizes).split(',');
-	for (i=0; i<fonts.length; i++)
-		addSelectValue(f, 'fontsize', fonts[i], fonts[i]);
-
-	// Setup mediatype select boxs
-	mediaTypes = tinyMCE.getParam("fullpage_media_types", defaultMediaTypes).split(',');
-	for (i=0; i<mediaTypes.length; i++) {
-		p = mediaTypes[i].split('=');
-
-		if (p.length > 1) {
-			addSelectValue(f, 'element_style_media', p[0], p[1]);
-			addSelectValue(f, 'element_link_media', p[0], p[1]);
-		}
-	}
-
-	// Setup encodings select box
-	encodings = tinyMCE.getParam("fullpage_encodings", defaultEncodings).split(',');
-	for (i=0; i<encodings.length; i++) {
-		p = encodings[i].split('=');
-
-		if (p.length > 1) {
-			addSelectValue(f, 'docencoding', p[0], p[1]);
-			addSelectValue(f, 'element_script_charset', p[0], p[1]);
-			addSelectValue(f, 'element_link_charset', p[0], p[1]);
-		}
-	}
-
-	document.getElementById('bgcolor_pickcontainer').innerHTML = getColorPickerHTML('bgcolor_pick','bgcolor');
-	document.getElementById('link_color_pickcontainer').innerHTML = getColorPickerHTML('link_color_pick','link_color');
-	//document.getElementById('hover_color_pickcontainer').innerHTML = getColorPickerHTML('hover_color_pick','hover_color');
-	document.getElementById('visited_color_pickcontainer').innerHTML = getColorPickerHTML('visited_color_pick','visited_color');
-	document.getElementById('active_color_pickcontainer').innerHTML = getColorPickerHTML('active_color_pick','active_color');
-	document.getElementById('textcolor_pickcontainer').innerHTML = getColorPickerHTML('textcolor_pick','textcolor');
-	document.getElementById('stylesheet_browsercontainer').innerHTML = getBrowserHTML('stylesheetbrowser','stylesheet','file','fullpage');
-	document.getElementById('link_href_pickcontainer').innerHTML = getBrowserHTML('link_href_browser','element_link_href','file','fullpage');
-	document.getElementById('script_src_pickcontainer').innerHTML = getBrowserHTML('script_src_browser','element_script_src','file','fullpage');
-	document.getElementById('bgimage_pickcontainer').innerHTML = getBrowserHTML('bgimage_browser','bgimage','image','fullpage');
-
-	// Resize some elements
-	if (isVisible('stylesheetbrowser'))
-		document.getElementById('stylesheet').style.width = '220px';
-
-	if (isVisible('link_href_browser'))
-		document.getElementById('element_link_href').style.width = '230px';
-
-	if (isVisible('bgimage_browser'))
-		document.getElementById('bgimage').style.width = '210px';
-
-	// Create iframe
-	var iframe = document.createElement('iframe');
-
-	iframe.id = 'tempFrame';
-	iframe.style.display = 'none';
-	iframe.src = tinyMCE.baseURL + "/plugins/fullpage/blank.htm";
-
-	document.body.appendChild(iframe);
-
-	tinyMCEPopup.resizeToInnerSize();
-}
-
-function setupIframe(doc) {
-	var inst = tinyMCE.getInstanceById(tinyMCE.getWindowArg('editor_id'));
-	var hc = inst.fullpageTopContent;
-	var f = document.forms[0];
-	var xmlVer, xmlEnc, docType;
-	var nodes, i, x, name, value, tmp, l;
-
-	// Keep it from not loading/executing stuff
-	hc = hc.replace(/<script>/gi, '<script type="text/javascript">');
-	hc = hc.replace(/\ssrc=/gi, " mce_src=");
-	hc = hc.replace(/\shref=/gi, " mce_href=");
-	hc = hc.replace(/\stype=/gi, " mce_type=");
-	hc = hc.replace(/<script/gi, '<script type="text/unknown" ');
-
-	// Add end to make it DOM parseable
-	hc += '</body></html>';
-
-	topDoc = doc;
-	doc.open();
-	doc.write(hc);
-	doc.close();
-
-	// ------- Setup options for genral tab
-
-	// Parse xml and doctype
-	xmlVer = getReItem(/<\?\s*?xml.*?version\s*?=\s*?"(.*?)".*?\?>/gi, hc, 1);
-	xmlEnc = getReItem(/<\?\s*?xml.*?encoding\s*?=\s*?"(.*?)".*?\?>/gi, hc, 1);
-	docType = getReItem(/<\!DOCTYPE.*?>/gi, hc, 0);
-	f.langcode.value = getReItem(/lang="(.*?)"/gi, hc, 1);
-
-	// Get title
-	f.metatitle.value = tinyMCE.entityDecode(getReItem(/<title>(.*?)<\/title>/gi, hc, 1));
-
-	// Check for meta encoding
-	nodes = doc.getElementsByTagName("meta");
-	for (i=0; i<nodes.length; i++) {
-		name = tinyMCE.getAttrib(nodes[i], 'name');
-		value = tinyMCE.getAttrib(nodes[i], 'content');
-		httpEquiv = tinyMCE.getAttrib(nodes[i], 'httpEquiv');
-
-		switch (name.toLowerCase()) {
-			case "keywords":
-				f.metakeywords.value = value;
-				break;
-
-			case "description":
-				f.metadescription.value = value;
-				break;
-
-			case "author":
-				f.metaauthor.value = value;
-				break;
-
-			case "copyright":
-				f.metacopyright.value = value;
-				break;
-
-			case "robots":
-				selectByValue(f, 'metarobots', value, true, true);
-				break;
-		}
-
-		switch (httpEquiv.toLowerCase()) {
-			case "content-type":
-				tmp = getReItem(/charset\s*=\s*(.*)\s*/gi, value, 1);
-
-				// Override XML encoding
-				if (tmp != "")
-					xmlEnc = tmp;
-
-				break;
-		}
-	}
-
-	selectByValue(f, 'doctypes', docType, true, true);
-	selectByValue(f, 'docencoding', xmlEnc, true, true);
-	selectByValue(f, 'langdir', tinyMCE.getAttrib(doc.body, 'dir'), true, true);
-
-	if (xmlVer != '')
-		f.xml_pi.checked = true;
-
-	// ------- Setup options for appearance tab
-
-	// Get primary stylesheet
-	nodes = doc.getElementsByTagName("link");
-	for (i=0; i<nodes.length; i++) {
-		l = nodes[i];
-		tmp = tinyMCE.getAttrib(l, 'media');
-
-		if (tinyMCE.getAttrib(l, 'mce_type') == "text/css" && (tmp == "" || tmp == "screen" || tmp == "all") && tinyMCE.getAttrib(l, 'rel') == "stylesheet") {
-			f.stylesheet.value = tinyMCE.getAttrib(l, 'mce_href');
-			break;
-		}
-	}
-
-	// Get from style elements
-	nodes = doc.getElementsByTagName("style");
-	for (i=0; i<nodes.length; i++) {
-		tmp = parseStyleElement(nodes[i]);
-
-		for (x=0; x<tmp.length; x++) {
-		//	if (tmp[x].rule.indexOf('a:hover') != -1 && tmp[x].data['color'])
-		//		f.hover_color.value = tmp[x].data['color'];
-
-			if (tmp[x].rule.indexOf('a:visited') != -1 && tmp[x].data['color'])
-				f.visited_color.value = tmp[x].data['color'];
-
-			if (tmp[x].rule.indexOf('a:link') != -1 && tmp[x].data['color'])
-				f.link_color.value = tmp[x].data['color'];
-
-			if (tmp[x].rule.indexOf('a:active') != -1 && tmp[x].data['color'])
-				f.active_color.value = tmp[x].data['color'];
-		}
-	}
-
-	// Get from body attribs
-
-/*	f.leftmargin.value = tinyMCE.getAttrib(doc.body, "leftmargin");
-	f.rightmargin.value = tinyMCE.getAttrib(doc.body, "rightmargin");
-	f.topmargin.value = tinyMCE.getAttrib(doc.body, "topmargin");
-	f.bottommargin.value = tinyMCE.getAttrib(doc.body, "bottommargin");*/
-	f.textcolor.value = convertRGBToHex(tinyMCE.getAttrib(doc.body, "text"));
-	f.active_color.value = convertRGBToHex(tinyMCE.getAttrib(doc.body, "alink"));
-	f.link_color.value = convertRGBToHex(tinyMCE.getAttrib(doc.body, "link"));
-	f.visited_color.value = convertRGBToHex(tinyMCE.getAttrib(doc.body, "vlink"));
-	f.bgcolor.value = convertRGBToHex(tinyMCE.getAttrib(doc.body, "bgcolor"));
-	f.bgimage.value = convertRGBToHex(tinyMCE.getAttrib(doc.body, "background"));
-
-	// Get from style info
-	var style = tinyMCE.parseStyle(tinyMCE.getAttrib(doc.body, 'style'));
-
-	if (style['font-family'])
-		selectByValue(f, 'fontface', style['font-family'], true, true);
-	else
-		selectByValue(f, 'fontface', tinyMCE.getParam("fullpage_default_fontface", ""), true, true);
-
-	if (style['font-size'])
-		selectByValue(f, 'fontsize', style['font-size'], true, true);
-	else
-		selectByValue(f, 'fontsize', tinyMCE.getParam("fullpage_default_fontsize", ""), true, true);
-
-	if (style['color'])
-		f.textcolor.value = convertRGBToHex(style['color']);
-
-	if (style['background-image'])
-		f.bgimage.value = style['background-image'].replace(new RegExp("url\\('?([^']*)'?\\)", 'gi'), "$1");
-
-	if (style['background-color'])
-		f.bgcolor.value = convertRGBToHex(style['background-color']);
-
-	if (style['margin']) {
-		tmp = style['margin'].replace(/[^0-9 ]/g, '');
-		tmp = tmp.split(/ +/);
-		f.topmargin.value = tmp.length > 0 ? tmp[0] : '';
-		f.rightmargin.value = tmp.length > 1 ? tmp[1] : tmp[0];
-		f.bottommargin.value = tmp.length > 2 ? tmp[2] : tmp[0];
-		f.leftmargin.value = tmp.length > 3 ? tmp[3] : tmp[0];
-	}
-
-	if (style['margin-left'])
-		f.leftmargin.value = style['margin-left'].replace(/[^0-9]/g, '');
-
-	if (style['margin-right'])
-		f.rightmargin.value = style['margin-right'].replace(/[^0-9]/g, '');
-
-	if (style['margin-top'])
-		f.topmargin.value = style['margin-top'].replace(/[^0-9]/g, '');
-
-	if (style['margin-bottom'])
-		f.bottommargin.value = style['margin-bottom'].replace(/[^0-9]/g, '');
-
-	f.style.value = tinyMCE.serializeStyle(style);
-
-	updateColor('textcolor_pick', 'textcolor');
-	updateColor('bgcolor_pick', 'bgcolor');
-	updateColor('visited_color_pick', 'visited_color');
-	updateColor('active_color_pick', 'active_color');
-	updateColor('link_color_pick', 'link_color');
-	//updateColor('hover_color_pick', 'hover_color');
-}
-
-function updateAction() {
-	var inst = tinyMCE.getInstanceById(tinyMCE.getWindowArg('editor_id'));
-	var f = document.forms[0];
-	var nl, i, h, v, s, head, html, l, tmp, addlink = true;
-
-	head = topDoc.getElementsByTagName('head')[0];
-
-	// Fix scripts without a type
-	nl = topDoc.getElementsByTagName('script');
-	for (i=0; i<nl.length; i++) {
-		if (tinyMCE.getAttrib(nl[i], 'mce_type') == '')
-			nl[i].setAttribute('mce_type', 'text/javascript');
-	}
-
-	// Get primary stylesheet
-	nl = topDoc.getElementsByTagName("link");
-	for (i=0; i<nl.length; i++) {
-		l = nl[i];
-
-		tmp = tinyMCE.getAttrib(l, 'media');
-
-		if (tinyMCE.getAttrib(l, 'mce_type') == "text/css" && (tmp == "" || tmp == "screen" || tmp == "all") && tinyMCE.getAttrib(l, 'rel') == "stylesheet") {
-			addlink = false;
-
-			if (f.stylesheet.value == '')
-				l.parentNode.removeChild(l);
-			else
-				l.setAttribute('mce_href', f.stylesheet.value);
-
-			break;
-		}
-	}
-
-	// Add new link
-	if (f.stylesheet.value != '') {
-		l = topDoc.createElement('link');
-
-		l.setAttribute('mce_type', 'text/css');
-		l.setAttribute('mce_href', f.stylesheet.value);
-		l.setAttribute('rel', 'stylesheet');
-
-		head.appendChild(l);
-	}
-
-	setMeta(head, 'keywords', f.metakeywords.value);
-	setMeta(head, 'description', f.metadescription.value);
-	setMeta(head, 'author', f.metaauthor.value);
-	setMeta(head, 'copyright', f.metacopyright.value);
-	setMeta(head, 'robots', getSelectValue(f, 'metarobots'));
-	setMeta(head, 'Content-Type', getSelectValue(f, 'docencoding'));
-
-	topDoc.body.dir = getSelectValue(f, 'langdir');
-	topDoc.body.style.cssText = f.style.value;
-
-	topDoc.body.setAttribute('vLink', f.visited_color.value);
-	topDoc.body.setAttribute('link', f.link_color.value);
-	topDoc.body.setAttribute('text', f.textcolor.value);
-	topDoc.body.setAttribute('aLink', f.active_color.value);
-
-	topDoc.body.style.fontFamily = getSelectValue(f, 'fontface');
-	topDoc.body.style.fontSize = getSelectValue(f, 'fontsize');
-	topDoc.body.style.backgroundColor = f.bgcolor.value;
-
-	if (f.leftmargin.value != '')
-		topDoc.body.style.marginLeft = f.leftmargin.value + 'px';
-
-	if (f.rightmargin.value != '')
-		topDoc.body.style.marginRight = f.rightmargin.value + 'px';
-
-	if (f.bottommargin.value != '')
-		topDoc.body.style.marginBottom = f.bottommargin.value + 'px';
-
-	if (f.topmargin.value != '')
-		topDoc.body.style.marginTop = f.topmargin.value + 'px';
-
-	html = topDoc.getElementsByTagName('html')[0];
-	html.setAttribute('lang', f.langcode.value);
-	html.setAttribute('xml:lang', f.langcode.value);
-
-	if (f.bgimage.value != '')
-		topDoc.body.style.backgroundImage = "url('" + f.bgimage.value + "')";
-	else
-		topDoc.body.style.backgroundImage = '';
-
-	inst.cleanup.addRuleStr('-title,meta[http-equiv|name|content],base[href|target],link[href|rel|type|title|media],style[type],script[type|language|src],html[lang|xml:lang|xmlns],body[style|dir|vlink|link|text|alink],head');
-
-	h = inst.cleanup.serializeNodeAsHTML(topDoc.documentElement);
-
-	h = h.substring(0, h.lastIndexOf('</body>'));
-
-	if (h.indexOf('<title>') == -1)
-		h = h.replace(/<head.*?>/, '$&\n' + '<title>' + inst.cleanup.xmlEncode(f.metatitle.value) + '</title>');
-	else
-		h = h.replace(/<title>(.*?)<\/title>/, '<title>' + inst.cleanup.xmlEncode(f.metatitle.value) + '</title>');
-
-	if ((v = getSelectValue(f, 'doctypes')) != '')
-		h = v + '\n' + h;
-
-	if (f.xml_pi.checked) {
-		s = '<?xml version="1.0"';
-
-		if ((v = getSelectValue(f, 'docencoding')) != '')
-			s += ' encoding="' + v + '"';
-
-		s += '?>\n';
-		h = s + h;
-	}
-
-	inst.fullpageTopContent = h;
-
-	tinyMCEPopup.execCommand('mceFullPageUpdate', false, '');
-	tinyMCEPopup.close();
-}
-
-function setMeta(he, k, v) {
-	var nl, i, m;
-
-	nl = he.getElementsByTagName('meta');
-	for (i=0; i<nl.length; i++) {
-		if (k == 'Content-Type' && tinyMCE.getAttrib(nl[i], 'http-equiv') == k) {
-			if (v == '')
-				nl[i].parentNode.removeChild(nl[i]);
-			else
-				nl[i].setAttribute('content', "text/html; charset=" + v);
-
-			return;
-		}
-
-		if (tinyMCE.getAttrib(nl[i], 'name') == k) {
-			if (v == '')
-				nl[i].parentNode.removeChild(nl[i]);
-			else
-				nl[i].setAttribute('content', v);
-			return;
-		}
-	}
-
-	if (v == '')
-		return;
-
-	m = topDoc.createElement('meta');
-
-	if (k == 'Content-Type')
-		m.httpEquiv = k;
-	else
-		m.setAttribute('name', k);
-
-	m.setAttribute('content', v);
-	he.appendChild(m);
-}
-
-function parseStyleElement(e) {
-	var v = e.innerHTML;
-	var p, i, r;
-
-	v = v.replace(/<!--/gi, '');
-	v = v.replace(/-->/gi, '');
-	v = v.replace(/[\n\r]/gi, '');
-	v = v.replace(/\s+/gi, ' ');
-
-	r = new Array();
-	p = v.split(/{|}/);
-
-	for (i=0; i<p.length; i+=2) {
-		if (p[i] != "")
-			r[r.length] = {rule : tinyMCE.trim(p[i]), data : tinyMCE.parseStyle(p[i+1])};
-	}
-
-	return r;
-}
-
-function serializeStyleElement(d) {
-	var i, s, st;
-
-	s = '<!--\n';
-
-	for (i=0; i<d.length; i++) {
-		s += d[i].rule + ' {\n';
-
-		st = tinyMCE.serializeStyle(d[i].data);
-
-		if (st != '')
-			st += ';';
-
-		s += st.replace(/;/g, ';\n');
-		s += '}\n';
-
-		if (i != d.length - 1)
-			s += '\n';
-	}
-
-	s += '\n-->';
-
-	return s;
-}
-
-function getReItem(r, s, i) {
-	var c = r.exec(s);
-
-	if (c && c.length > i)
-		return c[i];
-
-	return '';
-}
-
-function changedStyleField(field) {
-	//alert(field.id);
-}
-
-function showAddMenu() {
-	var re = document.getElementById('addbutton');
-
-	addMenuLayer.moveRelativeTo(re, 'tr');
-	if (addMenuLayer.isMSIE)
-		addMenuLayer.moveBy(2, 0);
-
-	addMenuLayer.show();
-	addMenuLayer.setAutoHide(true, hideAddMenu);
-	addMenuLayer.addCSSClass(re, 'selected');
-}
-
-function hideAddMenu(l, e, mx, my) {
-	var re = document.getElementById('addbutton');
-	addMenuLayer.removeCSSClass(re, 'selected');
-}
-
-function addHeadElm(type) {
-	var le = document.getElementById('headlist');
-	var re = document.getElementById('addbutton');
-	var te = document.getElementById(type + '_element');
-
-	if (lastElementType)
-		lastElementType.style.display = 'none';
-
-	te.style.display = 'block';
-
-	lastElementType = te;
-
-	addMenuLayer.hide();
-	addMenuLayer.removeCSSClass(re, 'selected');
-
-	document.getElementById(type + '_updateelement').value = tinyMCE.getLang('lang_insert', 'Insert', true);
-
-	le.size = 10;
-}
-
-function updateHeadElm(item) {
-	var type = item.substring(0, item.indexOf('_'));
-	var le = document.getElementById('headlist');
-	var re = document.getElementById('addbutton');
-	var te = document.getElementById(type + '_element');
-
-	if (lastElementType)
-		lastElementType.style.display = 'none';
-
-	te.style.display = 'block';
-
-	lastElementType = te;
-
-	addMenuLayer.hide();
-	addMenuLayer.removeCSSClass(re, 'selected');
-
-	document.getElementById(type + '_updateelement').value = tinyMCE.getLang('lang_update', 'Update', true);
-
-	le.size = 10;
-}
-
-function cancelElementUpdate() {
-	var le = document.getElementById('headlist');
-
-	if (lastElementType)
-		lastElementType.style.display = 'none';
-
-	le.size = 26;
-}
\ No newline at end of file
--- a/includes/clientside/tinymce/plugins/fullpage/langs/en.js	Fri Feb 22 12:46:51 2008 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,92 +0,0 @@
-// UK lang variables
-
-tinyMCE.addToLang('fullpage',{
-	title : 'Document properties',
-	desc : 'Document properties',
-	meta_tab : 'General',
-	appearance_tab : 'Appearance',
-	advanced_tab : 'Advanced',
-	meta_props : 'Meta information',
-	langprops : 'Language and encoding',
-	meta_title : 'Title',
-	meta_keywords : 'Keywords',
-	meta_description : 'Description',
-	meta_robots : 'Robots',
-	doctypes : 'Doctype',
-	langcode : 'Language code',
-	langdir : 'Language direction',
-	ltr : 'Left to right',
-	rtl : 'Right to left',
-	xml_pi : 'XML declaration',
-	encoding : 'Character encoding',
-	appearance_bgprops : 'Background properties',
-	appearance_marginprops : 'Body margins',
-	appearance_linkprops : 'Link colors',
-	appearance_textprops : 'Text properties',
-	bgcolor : 'Background color',
-	bgimage : 'Background image',
-	left_margin : 'Left margin',
-	right_margin : 'Right margin',
-	top_margin : 'Top margin',
-	bottom_margin : 'Bottom margin',
-	text_color : 'Text color',
-	font_size : 'Font size',
-	font_face : 'Font face',
-	link_color : 'Link color',
-	hover_color : 'Hover color',
-	visited_color : 'Visited color',
-	active_color : 'Active color',
-	textcolor : 'Color',
-	fontsize : 'Font size',
-	fontface : 'Font family',
-	meta_index_follow : 'Index and follow the links',
-	meta_index_nofollow : 'Index and don\'t follow the links',
-	meta_noindex_follow : 'Do not index but follow the links',
-	meta_noindex_nofollow : 'Do not index and don\'t follow the links',
-	appearance_style : 'Stylesheet and style properties',
-	stylesheet : 'Stylesheet',
-	style : 'Style',
-	author : 'Author',
-	copyright : 'Copyright',
-	add : 'Add new element',
-	remove : 'Remove selected element',
-	moveup : 'Move selected element up',
-	movedown : 'Move selected element down',
-	head_elements : 'Head elements',
-	info : 'Information',
-	info_text : '',
-	add_title : 'Title element',
-	add_meta : 'Meta element',
-	add_script : 'Script element',
-	add_style : 'Style element',
-	add_link : 'Link element',
-	add_base : 'Base element',
-	add_comment : 'Comment node',
-	title_element : 'Title element',
-	script_element : 'Script element',
-	style_element : 'Style element',
-	base_element : 'Base element',
-	link_element : 'Link element',
-	meta_element : 'Meta element',
-	comment_element : 'Comment',
-	src : 'Src',
-	language : 'Language',
-	href : 'Href',
-	target : 'Target',
-	rel : 'Rel',
-	type : 'Type',
-	charset : 'Charset',
-	defer : 'Defer',
-	media : 'Media',
-	properties : 'Properties',
-	name : 'Name',
-	value : 'Value',
-	content : 'Content',
-	rel : 'Rel',
-	rev : 'Rev',
-	hreflang : 'Href lang',
-	general_props : 'General',
-	advanced_props : 'Advanced',
-	delta_width : 0,
-	delta_height : 0
-});
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/includes/clientside/tinymce/plugins/fullpage/langs/en_dlg.js	Fri Feb 22 12:51:53 2008 -0500
@@ -0,0 +1,85 @@
+tinyMCE.addI18n('en.fullpage_dlg',{
+title:"Document properties",
+meta_tab:"General",
+appearance_tab:"Appearance",
+advanced_tab:"Advanced",
+meta_props:"Meta information",
+langprops:"Language and encoding",
+meta_title:"Title",
+meta_keywords:"Keywords",
+meta_description:"Description",
+meta_robots:"Robots",
+doctypes:"Doctype",
+langcode:"Language code",
+langdir:"Language direction",
+ltr:"Left to right",
+rtl:"Right to left",
+xml_pi:"XML declaration",
+encoding:"Character encoding",
+appearance_bgprops:"Background properties",
+appearance_marginprops:"Body margins",
+appearance_linkprops:"Link colors",
+appearance_textprops:"Text properties",
+bgcolor:"Background color",
+bgimage:"Background image",
+left_margin:"Left margin",
+right_margin:"Right margin",
+top_margin:"Top margin",
+bottom_margin:"Bottom margin",
+text_color:"Text color",
+font_size:"Font size",
+font_face:"Font face",
+link_color:"Link color",
+hover_color:"Hover color",
+visited_color:"Visited color",
+active_color:"Active color",
+textcolor:"Color",
+fontsize:"Font size",
+fontface:"Font family",
+meta_index_follow:"Index and follow the links",
+meta_index_nofollow:"Index and don't follow the links",
+meta_noindex_follow:"Do not index but follow the links",
+meta_noindex_nofollow:"Do not index and don\'t follow the links",
+appearance_style:"Stylesheet and style properties",
+stylesheet:"Stylesheet",
+style:"Style",
+author:"Author",
+copyright:"Copyright",
+add:"Add new element",
+remove:"Remove selected element",
+moveup:"Move selected element up",
+movedown:"Move selected element down",
+head_elements:"Head elements",
+info:"Information",
+add_title:"Title element",
+add_meta:"Meta element",
+add_script:"Script element",
+add_style:"Style element",
+add_link:"Link element",
+add_base:"Base element",
+add_comment:"Comment node",
+title_element:"Title element",
+script_element:"Script element",
+style_element:"Style element",
+base_element:"Base element",
+link_element:"Link element",
+meta_element:"Meta element",
+comment_element:"Comment",
+src:"Src",
+language:"Language",
+href:"Href",
+target:"Target",
+type:"Type",
+charset:"Charset",
+defer:"Defer",
+media:"Media",
+properties:"Properties",
+name:"Name",
+value:"Value",
+content:"Content",
+rel:"Rel",
+rev:"Rev",
+hreflang:"Href lang",
+general_props:"General",
+advanced_props:"Advanced"
+});
\ No newline at end of file
--- a/includes/clientside/tinymce/plugins/fullscreen/css/page.css	Fri Feb 22 12:46:51 2008 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,21 +0,0 @@
-/* This class restores all CSS properties to that absolute positioning of fullscreen mode is correct */
-.mceFullscreenPos {
-	display: block !important;
-	position: static !important;
-	left: 0 !important;
-	top: 0 !important;
-	bottom: auto !important;
-	right: auto !important;
-	width: auto !important;
-	height: auto !important;
-	margin: 0 !important;
-	padding: 0 !important;
-	border: 0 !important;
-	overflow: visible;
-	z-index: 1 !important;
-	clear: both;
-}
-
-body.mceFullscreen {
-	overflow: hidden !important;
-}
--- a/includes/clientside/tinymce/plugins/fullscreen/editor_plugin.js	Fri Feb 22 12:46:51 2008 -0500
+++ b/includes/clientside/tinymce/plugins/fullscreen/editor_plugin.js	Fri Feb 22 12:51:53 2008 -0500
@@ -1,1 +1,1 @@
-tinyMCE.importPluginLanguagePack('fullscreen');var TinyMCE_FullScreenPlugin={getInfo:function(){return{longname:'Fullscreen',author:'Moxiecode Systems AB',authorurl:'http://tinymce.moxiecode.com',infourl:'http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/fullscreen',version:tinyMCE.majorVersion+"."+tinyMCE.minorVersion}},initInstance:function(inst){if(!tinyMCE.settings['fullscreen_skip_plugin_css'])tinyMCE.importCSS(inst.getContainerWin().document,tinyMCE.baseURL+"/plugins/fullscreen/css/page.css")},getControlHTML:function(cn){switch(cn){case"fullscreen":return tinyMCE.getButtonHTML(cn,'lang_fullscreen_desc','{$pluginurl}/images/fullscreen.gif','mceFullScreen')}return""},execCommand:function(editor_id,element,command,user_interface,value){var inst;switch(command){case"mceFullScreen":inst=tinyMCE.getInstanceById(editor_id);if(tinyMCE.getParam('fullscreen_new_window'))this._toggleFullscreenWin(inst);else this._toggleFullscreen(inst);return true}return false},_toggleFullscreenWin:function(inst){if(tinyMCE.getParam('fullscreen_is_enabled')){window.opener.tinyMCE.execInstanceCommand(tinyMCE.getParam('fullscreen_editor_id'),'mceSetContent',false,tinyMCE.getContent(inst.editorId));top.close()}else{tinyMCE.setWindowArg('editor_id',inst.editorId);var win=window.open(tinyMCE.baseURL+"/plugins/fullscreen/fullscreen.htm","mceFullScreenPopup","fullscreen=yes,menubar=no,toolbar=no,scrollbars=no,resizable=yes,left=0,top=0,width="+screen.availWidth+",height="+screen.availHeight);try{win.resizeTo(screen.availWidth,screen.availHeight)}catch(e){}}},_toggleFullscreen:function(inst){var ds=inst.getData('fullscreen'),editorContainer,tableElm,iframe,vp,cw,cd,re,w,h,si,blo,delta=0,cell,row,fcml,bcml;cw=inst.getContainerWin();cd=cw.document;editorContainer=cd.getElementById(inst.editorId+'_parent');tableElm=editorContainer.firstChild;iframe=inst.iframeElement;re=cd.getElementById(inst.editorId+'_resize');blo=document.getElementById('mce_fullscreen_blocker');fcm=new TinyMCE_Layer(inst.editorId+'_fcMenu');fcml=new TinyMCE_Layer(inst.editorId+'_fcMenu');bcml=new TinyMCE_Layer(inst.editorId+'_bcMenu');if(fcml.exists()&&fcml.isVisible()){tinyMCE.switchClass(inst.editorId+'_forecolor','mceMenuButton');fcml.hide()}if(bcml.exists()&&bcml.isVisible()){tinyMCE.switchClass(inst.editorId+'_backcolor','mceMenuButton');bcml.hide()}if(!ds.enabled){if(inst.toolbarElement){delta+=inst.toolbarElement.offsetHeight;cell=tableElm.tBodies[0].insertRow(0).insertCell(-1);cell.className='mceToolbarTop';cell.nowrap=true;ds.oldToolbarParent=inst.toolbarElement.parentNode;ds.toolbarHolder=document.createTextNode('...');cell.appendChild(ds.oldToolbarParent.replaceChild(ds.toolbarHolder,inst.toolbarElement))}ds.parents=[];vp=tinyMCE.getViewPort(cw);ds.scrollX=vp.left;ds.scrollY=vp.top;if(!tinyMCE.isOpera)tinyMCE.addCSSClass(cd.body,'mceFullscreen');tinyMCE.getParentNode(tableElm.parentNode,function(n){if(n.nodeName=='BODY')return true;if(n.nodeType==1)tinyMCE.addCSSClass(n,'mceFullscreenPos');return false});if(re)re.style.display='none';vp=tinyMCE.getViewPort(cw);ds.oldWidth=iframe.style.width?iframe.style.width:iframe.offsetWidth;ds.oldHeight=iframe.style.height?iframe.style.height:iframe.offsetHeight;ds.oldTWidth=tableElm.style.width?tableElm.style.width:tableElm.offsetWidth;ds.oldTHeight=tableElm.style.height?tableElm.style.height:tableElm.offsetHeight;if(ds.oldWidth&&ds.oldWidth.indexOf)ds.oldTWidth=ds.oldWidth.indexOf('%')!=-1?ds.oldWidth:ds.oldTWidth;if(!blo&&tinyMCE.isRealIE){blo=tinyMCE.createTag(document,'iframe',{id:'mce_fullscreen_blocker',src:'about:blank',frameBorder:0,width:vp.width,height:vp.height,style:'display: block; position: absolute; left: 0; top: 0; z-index: 999; margin: 0; padding: 0;'});document.body.appendChild(blo)}tableElm.style.position='absolute';tableElm.style.zIndex=1000;tableElm.style.left=tableElm.style.top='0';tableElm.style.width=vp.width+'px';tableElm.style.height=vp.height+'px';if(tinyMCE.isRealIE){iframe.style.width=vp.width+'px';iframe.style.height=vp.height+'px';w=iframe.parentNode.clientWidth-(tableElm.offsetWidth-vp.width);h=iframe.parentNode.clientHeight-(tableElm.offsetHeight-vp.height)}else{w=iframe.parentNode.clientWidth;h=iframe.parentNode.clientHeight}iframe.style.width=w+"px";iframe.style.height=(h+delta)+"px";tinyMCE.switchClass(inst.editorId+'_fullscreen','mceButtonSelected');ds.enabled=true;inst.useCSS=false}else{if(inst.toolbarElement){row=inst.toolbarElement.parentNode.parentNode;row.parentNode.removeChild(row);ds.oldToolbarParent.replaceChild(inst.toolbarElement,ds.toolbarHolder);ds.oldToolbarParent=null;ds.toolbarHolder=null}if(blo)blo.parentNode.removeChild(blo);si=0;tinyMCE.getParentNode(tableElm.parentNode,function(n){if(n.nodeName=='BODY')return true;if(n.nodeType==1)tinyMCE.removeCSSClass(n,'mceFullscreenPos')});if(re&&tinyMCE.getParam("theme_advanced_resizing",false))re.style.display='block';tableElm.style.position='static';tableElm.style.zIndex='';tableElm.style.width='';tableElm.style.height='';tableElm.style.width=ds.oldTWidth?ds.oldTWidth:'';tableElm.style.height=ds.oldTHeight?ds.oldTHeight:'';iframe.style.width=ds.oldWidth?ds.oldWidth:'';iframe.style.height=ds.oldHeight?ds.oldHeight:'';tinyMCE.switchClass(inst.editorId+'_fullscreen','mceButtonNormal');ds.enabled=false;tinyMCE.removeCSSClass(cd.body,'mceFullscreen');cw.scrollTo(ds.scrollX,ds.scrollY);inst.useCSS=false}},handleNodeChange:function(editor_id,node,undo_index,undo_levels,visual_aid,any_selection){if(tinyMCE.getParam('fullscreen_is_enabled'))tinyMCE.switchClass(editor_id+'_fullscreen','mceButtonSelected');return true}};tinyMCE.addPlugin("fullscreen",TinyMCE_FullScreenPlugin);
\ No newline at end of file
+(function(){var DOM=tinymce.DOM;tinymce.create('tinymce.plugins.FullScreenPlugin',{init:function(ed,url){var t=this,s={},vp;t.editor=ed;ed.addCommand('mceFullScreen',function(){var win,de=document.documentElement;if(ed.getParam('fullscreen_is_enabled')){if(ed.getParam('fullscreen_new_window'))closeFullscreen();else{window.setTimeout(function(){tinyMCE.get(ed.getParam('fullscreen_editor_id')).setContent(ed.getContent({format:'raw'}),{format:'raw'});tinyMCE.remove(ed);DOM.remove('mce_fullscreen_container');de.style.overflow=ed.getParam('fullscreen_html_overflow');DOM.setStyle(document.body,'overflow',ed.getParam('fullscreen_overflow'));window.scrollTo(ed.getParam('fullscreen_scrollx'),ed.getParam('fullscreen_scrolly'));},10);}return;}if(ed.getParam('fullscreen_new_window')){win=window.open(url+"/fullscreen.htm","mceFullScreenPopup","fullscreen=yes,menubar=no,toolbar=no,scrollbars=no,resizable=no,left=0,top=0,width="+screen.availWidth+",height="+screen.availHeight);try{win.resizeTo(screen.availWidth,screen.availHeight);}catch(e){}}else{s.fullscreen_overflow=DOM.getStyle(document.body,'overflow',1)||'auto';s.fullscreen_html_overflow=DOM.getStyle(de,'overflow',1);vp=DOM.getViewPort();s.fullscreen_scrollx=vp.x;s.fullscreen_scrolly=vp.y;if(tinymce.isOpera&&s.fullscreen_overflow=='visible')s.fullscreen_overflow='auto';if(tinymce.isIE&&s.fullscreen_overflow=='scroll')s.fullscreen_overflow='auto';if(s.fullscreen_overflow=='0px')s.fullscreen_overflow='';DOM.setStyle(document.body,'overflow','hidden');de.style.overflow='hidden';vp=DOM.getViewPort();window.scrollTo(0,0);if(tinymce.isIE)vp.h-=1;n=DOM.add(document.body,'div',{id:'mce_fullscreen_container',style:'position:absolute;top:0;left:0;width:'+vp.w+'px;height:'+vp.h+'px;z-index:150;'});DOM.add(n,'div',{id:'mce_fullscreen'});tinymce.each(ed.settings,function(v,n){s[n]=v;});s.id='mce_fullscreen';s.width=n.clientWidth;s.height=n.clientHeight-15;s.fullscreen_is_enabled=true;s.fullscreen_editor_id=ed.id;s.theme_advanced_resizing=false;tinymce.each(ed.getParam('fullscreen_settings'),function(v,k){s[k]=v;});if(s.theme_advanced_toolbar_location==='external')s.theme_advanced_toolbar_location='top';t.fullscreenEditor=new tinymce.Editor('mce_fullscreen',s);t.fullscreenEditor.onInit.add(function(){t.fullscreenEditor.setContent(ed.getContent({format:'raw',no_events:1}),{format:'raw',no_events:1});});t.fullscreenEditor.render();tinyMCE.add(t.fullscreenEditor);t.fullscreenElement=new tinymce.dom.Element('mce_fullscreen_container');t.fullscreenElement.update();}});ed.addButton('fullscreen',{title:'fullscreen.desc',cmd:'mceFullScreen'});ed.onNodeChange.add(function(ed,cm){cm.setActive('fullscreen',ed.getParam('fullscreen_is_enabled'));});},getInfo:function(){return{longname:'Fullscreen',author:'Moxiecode Systems AB',authorurl:'http://tinymce.moxiecode.com',infourl:'http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/fullscreen',version:tinymce.majorVersion+"."+tinymce.minorVersion};}});tinymce.PluginManager.add('fullscreen',tinymce.plugins.FullScreenPlugin);})();
\ No newline at end of file
--- a/includes/clientside/tinymce/plugins/fullscreen/editor_plugin_src.js	Fri Feb 22 12:46:51 2008 -0500
+++ b/includes/clientside/tinymce/plugins/fullscreen/editor_plugin_src.js	Fri Feb 22 12:51:53 2008 -0500
@@ -1,230 +1,127 @@
 /**
- * $Id: editor_plugin_src.js 201 2007-02-12 15:56:56Z spocke $
+ * $Id: editor_plugin_src.js 544 2008-01-17 13:07:00Z spocke $
  *
  * @author Moxiecode
- * @copyright Copyright © 2004-2007, Moxiecode Systems AB, All rights reserved.
+ * @copyright Copyright © 2004-2008, Moxiecode Systems AB, All rights reserved.
  */
 
-/* Import plugin specific language pack */
-tinyMCE.importPluginLanguagePack('fullscreen');
-
-var TinyMCE_FullScreenPlugin = {
-	getInfo : function() {
-		return {
-			longname : 'Fullscreen',
-			author : 'Moxiecode Systems AB',
-			authorurl : 'http://tinymce.moxiecode.com',
-			infourl : 'http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/fullscreen',
-			version : tinyMCE.majorVersion + "." + tinyMCE.minorVersion
-		};
-	},
+(function() {
+	var DOM = tinymce.DOM;
 
-	initInstance : function(inst) {
-		if (!tinyMCE.settings['fullscreen_skip_plugin_css'])
-			tinyMCE.importCSS(inst.getContainerWin().document, tinyMCE.baseURL + "/plugins/fullscreen/css/page.css");
-	},
+	tinymce.create('tinymce.plugins.FullScreenPlugin', {
+		init : function(ed, url) {
+			var t = this, s = {}, vp;
 
-	getControlHTML : function(cn) {
-		switch (cn) {
-			case "fullscreen":
-				return tinyMCE.getButtonHTML(cn, 'lang_fullscreen_desc', '{$pluginurl}/images/fullscreen.gif', 'mceFullScreen');
-		}
+			t.editor = ed;
 
-		return "";
-	},
+			// Register commands
+			ed.addCommand('mceFullScreen', function() {
+				var win, de = document.documentElement;
 
-	execCommand : function(editor_id, element, command, user_interface, value) {
-		var inst;
+				if (ed.getParam('fullscreen_is_enabled')) {
+					if (ed.getParam('fullscreen_new_window'))
+						closeFullscreen(); // Call to close in new window
+					else {
+						window.setTimeout(function() {
+							tinyMCE.get(ed.getParam('fullscreen_editor_id')).setContent(ed.getContent({format : 'raw'}), {format : 'raw'});
+							tinyMCE.remove(ed);
+							DOM.remove('mce_fullscreen_container');
+							de.style.overflow = ed.getParam('fullscreen_html_overflow');
+							DOM.setStyle(document.body, 'overflow', ed.getParam('fullscreen_overflow'));
+							window.scrollTo(ed.getParam('fullscreen_scrollx'), ed.getParam('fullscreen_scrolly'));
+						}, 10);
+					}
 
-		// Handle commands
-		switch (command) {
-			case "mceFullScreen":
-				inst = tinyMCE.getInstanceById(editor_id);
-
-				if (tinyMCE.getParam('fullscreen_new_window'))
-					this._toggleFullscreenWin(inst);
-				else
-					this._toggleFullscreen(inst);
+					return;
+				}
 
-				return true;
-		}
-
-		// Pass to next handler in chain
-		return false;
-	},
+				if (ed.getParam('fullscreen_new_window')) {
+					win = window.open(url + "/fullscreen.htm", "mceFullScreenPopup", "fullscreen=yes,menubar=no,toolbar=no,scrollbars=no,resizable=no,left=0,top=0,width=" + screen.availWidth + ",height=" + screen.availHeight);
+					try {
+						win.resizeTo(screen.availWidth, screen.availHeight);
+					} catch (e) {
+						// Ignore
+					}
+				} else {
+					s.fullscreen_overflow = DOM.getStyle(document.body, 'overflow', 1) || 'auto';
+					s.fullscreen_html_overflow = DOM.getStyle(de, 'overflow', 1);
+					vp = DOM.getViewPort();
+					s.fullscreen_scrollx = vp.x;
+					s.fullscreen_scrolly = vp.y;
 
-	_toggleFullscreenWin : function(inst) {
-		if (tinyMCE.getParam('fullscreen_is_enabled')) {
-			// In fullscreen mode
-			window.opener.tinyMCE.execInstanceCommand(tinyMCE.getParam('fullscreen_editor_id'), 'mceSetContent', false, tinyMCE.getContent(inst.editorId));
-			top.close();
-		} else {
-			tinyMCE.setWindowArg('editor_id', inst.editorId);
+					// Fixes an Opera bug where the scrollbars doesn't reappear
+					if (tinymce.isOpera && s.fullscreen_overflow == 'visible')
+						s.fullscreen_overflow = 'auto';
 
-			var win = window.open(tinyMCE.baseURL + "/plugins/fullscreen/fullscreen.htm", "mceFullScreenPopup", "fullscreen=yes,menubar=no,toolbar=no,scrollbars=no,resizable=yes,left=0,top=0,width=" + screen.availWidth + ",height=" + screen.availHeight);
-			try { win.resizeTo(screen.availWidth, screen.availHeight); } catch (e) {}
-		}
-	},
+					// Fixes an IE bug where horizontal scrollbars would appear
+					if (tinymce.isIE && s.fullscreen_overflow == 'scroll')
+						s.fullscreen_overflow = 'auto';
 
-	_toggleFullscreen : function(inst) {
-		var ds = inst.getData('fullscreen'), editorContainer, tableElm, iframe, vp, cw, cd, re, w, h, si, blo, delta = 0, cell, row, fcml, bcml;
+					if (s.fullscreen_overflow == '0px')
+						s.fullscreen_overflow = '';
 
-		cw = inst.getContainerWin();
-		cd = cw.document;
-		editorContainer = cd.getElementById(inst.editorId + '_parent');
-		tableElm = editorContainer.firstChild;
-		iframe = inst.iframeElement;
-		re = cd.getElementById(inst.editorId + '_resize');
-		blo = document.getElementById('mce_fullscreen_blocker');
-		fcm = new TinyMCE_Layer(inst.editorId + '_fcMenu');
-		fcml = new TinyMCE_Layer(inst.editorId + '_fcMenu');
-		bcml = new TinyMCE_Layer(inst.editorId + '_bcMenu');
+					DOM.setStyle(document.body, 'overflow', 'hidden');
+					de.style.overflow = 'hidden'; //Fix for IE6/7
+					vp = DOM.getViewPort();
+					window.scrollTo(0, 0);
 
-		if (fcml.exists() && fcml.isVisible()) {
-			tinyMCE.switchClass(inst.editorId + '_forecolor', 'mceMenuButton');
-			fcml.hide();
-		}
+					if (tinymce.isIE)
+						vp.h -= 1;
 
-		if (bcml.exists() && bcml.isVisible()) {
-			tinyMCE.switchClass(inst.editorId + '_backcolor', 'mceMenuButton');
-			bcml.hide();
-		}
+					n = DOM.add(document.body, 'div', {id : 'mce_fullscreen_container', style : 'position:absolute;top:0;left:0;width:' + vp.w + 'px;height:' + vp.h + 'px;z-index:150;'});
+					DOM.add(n, 'div', {id : 'mce_fullscreen'});
+
+					tinymce.each(ed.settings, function(v, n) {
+						s[n] = v;
+					});
 
-		if (!ds.enabled) {
-			// Handle External Toolbar
-			if (inst.toolbarElement) {
-				delta += inst.toolbarElement.offsetHeight;
+					s.id = 'mce_fullscreen';
+					s.width = n.clientWidth;
+					s.height = n.clientHeight - 15;
+					s.fullscreen_is_enabled = true;
+					s.fullscreen_editor_id = ed.id;
+					s.theme_advanced_resizing = false;
 
-				cell = tableElm.tBodies[0].insertRow(0).insertCell(-1);
-				cell.className = 'mceToolbarTop';
-				cell.nowrap = true;
-
-				ds.oldToolbarParent = inst.toolbarElement.parentNode;
-				ds.toolbarHolder = document.createTextNode('...');
-
-				cell.appendChild(ds.oldToolbarParent.replaceChild(ds.toolbarHolder, inst.toolbarElement));
-			}
-
-			ds.parents = [];
+					tinymce.each(ed.getParam('fullscreen_settings'), function(v, k) {
+						s[k] = v;
+					});
 
-			vp = tinyMCE.getViewPort(cw);
-			ds.scrollX = vp.left;
-			ds.scrollY = vp.top;
+					if (s.theme_advanced_toolbar_location === 'external')
+						s.theme_advanced_toolbar_location = 'top';
 
-			// Opera has a bug restoring scrollbars
-			if (!tinyMCE.isOpera)
-				tinyMCE.addCSSClass(cd.body, 'mceFullscreen');
+					t.fullscreenEditor = new tinymce.Editor('mce_fullscreen', s);
+					t.fullscreenEditor.onInit.add(function() {
+						t.fullscreenEditor.setContent(ed.getContent({format : 'raw', no_events : 1}), {format : 'raw', no_events : 1});
+					});
 
-			tinyMCE.getParentNode(tableElm.parentNode, function (n) {
-				if (n.nodeName == 'BODY')
-					return true;
+					t.fullscreenEditor.render();
+					tinyMCE.add(t.fullscreenEditor);
 
-				if (n.nodeType == 1)
-					tinyMCE.addCSSClass(n, 'mceFullscreenPos');
-
-				return false;
+					t.fullscreenElement = new tinymce.dom.Element('mce_fullscreen_container');
+					t.fullscreenElement.update();
+					//document.body.overflow = 'hidden';
+				}
 			});
 
-			if (re)
-				re.style.display = 'none';
-
-			vp = tinyMCE.getViewPort(cw);
-
-			ds.oldWidth = iframe.style.width ? iframe.style.width : iframe.offsetWidth;
-			ds.oldHeight = iframe.style.height ? iframe.style.height : iframe.offsetHeight;
-			ds.oldTWidth = tableElm.style.width ? tableElm.style.width : tableElm.offsetWidth;
-			ds.oldTHeight = tableElm.style.height ? tableElm.style.height : tableElm.offsetHeight;
-
-			// Handle % width
-			if (ds.oldWidth && ds.oldWidth.indexOf)
-				ds.oldTWidth = ds.oldWidth.indexOf('%') != -1 ? ds.oldWidth : ds.oldTWidth;
-
-			if (!blo && tinyMCE.isRealIE) {
-				blo = tinyMCE.createTag(document, 'iframe', {id : 'mce_fullscreen_blocker', src : 'about:blank', frameBorder : 0, width : vp.width, height : vp.height, style : 'display: block; position: absolute; left: 0; top: 0; z-index: 999; margin: 0; padding: 0;'});
-				document.body.appendChild(blo);
-			}
-
-			tableElm.style.position = 'absolute';
-			tableElm.style.zIndex = 1000;
-			tableElm.style.left = tableElm.style.top = '0';
-
-			tableElm.style.width = vp.width + 'px';
-			tableElm.style.height = vp.height + 'px';
+			// Register buttons
+			ed.addButton('fullscreen', {title : 'fullscreen.desc', cmd : 'mceFullScreen'});
 
-			if (tinyMCE.isRealIE) {
-				iframe.style.width = vp.width + 'px';
-				iframe.style.height = vp.height + 'px';
-
-				// Calc new width/height based on overflow
-				w = iframe.parentNode.clientWidth - (tableElm.offsetWidth - vp.width);
-				h = iframe.parentNode.clientHeight - (tableElm.offsetHeight - vp.height);
-			} else {
-				w = iframe.parentNode.clientWidth;
-				h = iframe.parentNode.clientHeight;
-			}
-
-			iframe.style.width = w + "px";
-			iframe.style.height = (h+delta) + "px";
-
-			tinyMCE.switchClass(inst.editorId + '_fullscreen', 'mceButtonSelected');
-			ds.enabled = true;
-
-			inst.useCSS = false;
-		} else {
-			// Handle External Toolbar
-			if (inst.toolbarElement) {
-				row = inst.toolbarElement.parentNode.parentNode;
-
-				row.parentNode.removeChild(row);
+			ed.onNodeChange.add(function(ed, cm) {
+				cm.setActive('fullscreen', ed.getParam('fullscreen_is_enabled'));
+			});
+		},
 
-				ds.oldToolbarParent.replaceChild(inst.toolbarElement, ds.toolbarHolder);
-
-				ds.oldToolbarParent = null;
-				ds.toolbarHolder = null;
-			}
-
-			if (blo)
-				blo.parentNode.removeChild(blo);
-
-			si = 0;
-			tinyMCE.getParentNode(tableElm.parentNode, function (n) {
-				if (n.nodeName == 'BODY')
-					return true;
-
-				if (n.nodeType == 1)
-					tinyMCE.removeCSSClass(n, 'mceFullscreenPos');
-			});
-
-			if (re && tinyMCE.getParam("theme_advanced_resizing", false))
-				re.style.display = 'block';
-
-			tableElm.style.position = 'static';
-			tableElm.style.zIndex = '';
-			tableElm.style.width = '';
-			tableElm.style.height = '';
+		getInfo : function() {
+			return {
+				longname : 'Fullscreen',
+				author : 'Moxiecode Systems AB',
+				authorurl : 'http://tinymce.moxiecode.com',
+				infourl : 'http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/fullscreen',
+				version : tinymce.majorVersion + "." + tinymce.minorVersion
+			};
+		}
+	});
 
-			tableElm.style.width = ds.oldTWidth ? ds.oldTWidth : '';
-			tableElm.style.height = ds.oldTHeight ? ds.oldTHeight : '';
-
-			iframe.style.width = ds.oldWidth ? ds.oldWidth : '';
-			iframe.style.height = ds.oldHeight ? ds.oldHeight : '';
-
-			tinyMCE.switchClass(inst.editorId + '_fullscreen', 'mceButtonNormal');
-			ds.enabled = false;
-
-			tinyMCE.removeCSSClass(cd.body, 'mceFullscreen');
-			cw.scrollTo(ds.scrollX, ds.scrollY);
-
-			inst.useCSS = false;
-		}
-	},
-
-	handleNodeChange : function(editor_id, node, undo_index, undo_levels, visual_aid, any_selection) {
-		if (tinyMCE.getParam('fullscreen_is_enabled'))
-			tinyMCE.switchClass(editor_id + '_fullscreen', 'mceButtonSelected');
-
-		return true;
-	}
-};
-
-tinyMCE.addPlugin("fullscreen", TinyMCE_FullScreenPlugin);
+	// Register plugin
+	tinymce.PluginManager.add('fullscreen', tinymce.plugins.FullScreenPlugin);
+})();
\ No newline at end of file
--- a/includes/clientside/tinymce/plugins/fullscreen/fullscreen.htm	Fri Feb 22 12:46:51 2008 -0500
+++ b/includes/clientside/tinymce/plugins/fullscreen/fullscreen.htm	Fri Feb 22 12:51:53 2008 -0500
@@ -1,23 +1,24 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
 <html xmlns="http://www.w3.org/1999/xhtml">
 <head>
-	<title>{$lang_fullscreen_title}</title>
+	<title></title>
 	<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
-	<script language="javascript" type="text/javascript" src="../../tiny_mce.js"></script>
-	<script language="javascript" type="text/javascript">
+	<script type="text/javascript" src="../../tiny_mce.js"></script>
+	<script type="text/javascript">
 		function patchCallback(settings, key) {
 			if (settings[key])
 				settings[key] = "window.opener." + settings[key];
 		}
 
-		var settings = new Array();
+		var settings = {}, paSe = window.opener.tinyMCE.activeEditor.settings;
 
 		// Clone array
-		for (var name in window.opener.tinyMCE.settings)
-			settings[name] = window.opener.tinyMCE.settings[name];
+		for (var n in paSe)
+			settings[n] = paSe[n];
 
 		// Override options for fullscreen
-		for (var name in window.opener.tinyMCE.settings.fullscreen_settings)
-			settings[name] = window.opener.tinyMCE.settings.fullscreen_settings[name];
+		for (var n in paSe.fullscreen_settings)
+			settings[n] = paSe.fullscreen_settings[n];
 
 		// Patch callbacks, make them point to window.opener
 		patchCallback(settings, 'urlconverter_callback');
@@ -33,42 +34,31 @@
 		patchCallback(settings, 'oninit');
 
 		// Set options
+		delete settings.id;
 		settings['mode'] = 'exact';
 		settings['elements'] = 'fullscreenarea';
+		settings['add_unload_trigger'] = false;
 		settings['ask'] = false;
-		settings['setupcontent_callback'] = 'setupContent';
+		settings['document_base_url'] = window.opener.tinyMCE.activeEditor.documentBaseURI.getURI();
 		settings['fullscreen_is_enabled'] = true;
-		settings['fullscreen_editor_id'] = window.opener.tinyMCE.getWindowArg("editor_id");
+		settings['fullscreen_editor_id'] = window.opener.tinyMCE.activeEditor.id;
 		settings['theme_advanced_resizing'] = false;
 
-		// Init
-		tinyMCE.init(settings);
-		tinyMCE.documentBasePath = window.opener.tinyMCE.documentBasePath;
-
-		function setupContent(editor_id, body, doc) {
-			var inst = tinyMCE.getInstanceById(editor_id);
-			var content = window.opener.tinyMCE.getContent(tinyMCE.getParam('fullscreen_editor_id'));
-
-			// Setup title
-			var divElm = document.createElement("div");
-			divElm.innerHTML = tinyMCELang['lang_fullscreen_title'];
-			document.title = divElm.innerHTML;
-
-			// Get content
-			inst.execCommand('mceSetContent', false, content);
-		}
-
 		function unloadHandler(e) {
 			moveContent();
 		}
 
 		function moveContent() {
-			var doc = tinyMCE.isMSIE ? window.frames['mce_editor_0'].window.document : document.getElementById('mce_editor_0').contentDocument;
-			window.opener.tinyMCE.setInnerHTML(window.opener.tinyMCE.selectedInstance.getBody(), doc.body.innerHTML);
+			window.opener.tinyMCE.activeEditor.setContent(tinyMCE.activeEditor.getContent({format : 'raw'}));
+		}
+
+		function closeFullscreen() {
+			moveContent();
+			window.close();
 		}
 
 		// Add onunload
-		tinyMCE.addEvent(window, "beforeunload", unloadHandler);
+		tinymce.dom.Event.add(window, "beforeunload", unloadHandler);
 
 		function doParentSubmit() {
 			moveContent();
@@ -83,9 +73,18 @@
 	</script>
 	<base target="_self" />
 </head>
-<body style="margin: 0; overflow: hidden; height: 100%" scrolling="no" scroll="no">
-<form onsubmit="doParentSubmit();" style="height: 100%">
-<textarea id="fullscreenarea" style="width: 100%; height: 100%"></textarea>
+<body style="margin:0;overflow:hidden;width:100%;height:100%" scrolling="no" scroll="no">
+<form onsubmit="doParentSubmit();">
+<textarea id="fullscreenarea" style="width:100%; height:100%"></textarea>
 </form>
+
+<script type="text/javascript">
+		var e = document.getElementById('fullscreenarea');
+		e.value = window.opener.tinyMCE.activeEditor.getContent({format : 'raw'});
+		settings['width'] = window.innerWidth || document.body.clientWidth;
+		settings['height'] = (window.innerHeight || document.body.clientHeight) - 18;
+		tinyMCE.init(settings);
+</script>
+
 </body>
 </html>
Binary file includes/clientside/tinymce/plugins/fullscreen/images/fullscreen.gif has changed
--- a/includes/clientside/tinymce/plugins/fullscreen/langs/en.js	Fri Feb 22 12:46:51 2008 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,5 +0,0 @@
-// UK lang variables
-
-tinyMCE.addToLang('',{
-fullscreen_desc : 'Toggle fullscreen mode'
-});
--- a/includes/clientside/tinymce/plugins/fullscreen/readme.txt	Fri Feb 22 12:46:51 2008 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1 +0,0 @@
-Check the TinyMCE documentation for details on this plugin.
--- a/includes/clientside/tinymce/plugins/iespell/editor_plugin.js	Fri Feb 22 12:46:51 2008 -0500
+++ b/includes/clientside/tinymce/plugins/iespell/editor_plugin.js	Fri Feb 22 12:51:53 2008 -0500
@@ -1,1 +1,1 @@
-tinyMCE.importPluginLanguagePack('iespell');var TinyMCE_IESpellPlugin={getInfo:function(){return{longname:'IESpell (MSIE Only)',author:'Moxiecode Systems AB',authorurl:'http://tinymce.moxiecode.com',infourl:'http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/iespell',version:tinyMCE.majorVersion+"."+tinyMCE.minorVersion}},getControlHTML:function(cn){if(cn=="iespell"&&(tinyMCE.isMSIE&&!tinyMCE.isOpera))return tinyMCE.getButtonHTML(cn,'lang_iespell_desc','{$pluginurl}/images/iespell.gif','mceIESpell');return""},execCommand:function(editor_id,element,command,user_interface,value){if(command=="mceIESpell"){try{var ieSpell=new ActiveXObject("ieSpell.ieSpellExtension");ieSpell.CheckDocumentNode(tinyMCE.getInstanceById(editor_id).contentDocument.documentElement)}catch(e){if(e.number==-2146827859){if(confirm(tinyMCE.getLang("lang_iespell_download","",true)))window.open('http://www.iespell.com/download.php','ieSpellDownload','')}else alert("Error Loading ieSpell: Exception "+e.number)}return true}return false}};tinyMCE.addPlugin("iespell",TinyMCE_IESpellPlugin);
\ No newline at end of file
+(function(){tinymce.create('tinymce.plugins.IESpell',{init:function(ed,url){var t=this,sp;if(!tinymce.isIE)return;t.editor=ed;ed.addCommand('mceIESpell',function(){try{sp=new ActiveXObject("ieSpell.ieSpellExtension");sp.CheckDocumentNode(ed.getDoc().documentElement);}catch(e){if(e.number==-2146827859){ed.windowManager.confirm(ed.getLang("iespell.download"),function(s){if(s)window.open('http://www.iespell.com/download.php','ieSpellDownload','');});}else ed.windowManager.alert("Error Loading ieSpell: Exception "+e.number);}});ed.addButton('iespell',{title:'iespell.iespell_desc',cmd:'mceIESpell'});},getInfo:function(){return{longname:'IESpell (IE Only)',author:'Moxiecode Systems AB',authorurl:'http://tinymce.moxiecode.com',infourl:'http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/iespell',version:tinymce.majorVersion+"."+tinymce.minorVersion};}});tinymce.PluginManager.add('iespell',tinymce.plugins.IESpell);})();
\ No newline at end of file
--- a/includes/clientside/tinymce/plugins/iespell/editor_plugin_src.js	Fri Feb 22 12:46:51 2008 -0500
+++ b/includes/clientside/tinymce/plugins/iespell/editor_plugin_src.js	Fri Feb 22 12:51:53 2008 -0500
@@ -1,58 +1,51 @@
 /**
- * $Id: editor_plugin_src.js 201 2007-02-12 15:56:56Z spocke $
+ * $Id: editor_plugin_src.js 520 2008-01-07 16:30:32Z spocke $
  *
  * @author Moxiecode
- * @copyright Copyright © 2004-2007, Moxiecode Systems AB, All rights reserved.
+ * @copyright Copyright © 2004-2008, Moxiecode Systems AB, All rights reserved.
  */
 
-/* Import plugin specific language pack */
-tinyMCE.importPluginLanguagePack('iespell');
+(function() {
+	tinymce.create('tinymce.plugins.IESpell', {
+		init : function(ed, url) {
+			var t = this, sp;
 
-var TinyMCE_IESpellPlugin = {
-	getInfo : function() {
-		return {
-			longname : 'IESpell (MSIE Only)',
-			author : 'Moxiecode Systems AB',
-			authorurl : 'http://tinymce.moxiecode.com',
-			infourl : 'http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/iespell',
-			version : tinyMCE.majorVersion + "." + tinyMCE.minorVersion
-		};
-	},
+			if (!tinymce.isIE)
+				return;
 
-	/**
-	 * Returns the HTML contents of the iespell control.
-	 */
-	getControlHTML : function(cn) {
-		// Is it the iespell control and is the brower MSIE.
-		if (cn == "iespell" && (tinyMCE.isMSIE && !tinyMCE.isOpera))
-			return tinyMCE.getButtonHTML(cn, 'lang_iespell_desc', '{$pluginurl}/images/iespell.gif', 'mceIESpell');
-
-		return "";
-	},
+			t.editor = ed;
 
-	/**
-	 * Executes the mceIESpell command.
-	 */
-	execCommand : function(editor_id, element, command, user_interface, value) {
-		// Handle ieSpellCommand
-		if (command == "mceIESpell") {
-			try {
-				var ieSpell = new ActiveXObject("ieSpell.ieSpellExtension");
-				ieSpell.CheckDocumentNode(tinyMCE.getInstanceById(editor_id).contentDocument.documentElement);
-			} catch (e) {
-				if (e.number == -2146827859) {
-					if (confirm(tinyMCE.getLang("lang_iespell_download", "", true)))
-						window.open('http://www.iespell.com/download.php', 'ieSpellDownload', '');
-				} else
-					alert("Error Loading ieSpell: Exception " + e.number);
-			}
+			// Register commands
+			ed.addCommand('mceIESpell', function() {
+				try {
+					sp = new ActiveXObject("ieSpell.ieSpellExtension");
+					sp.CheckDocumentNode(ed.getDoc().documentElement);
+				} catch (e) {
+					if (e.number == -2146827859) {
+						ed.windowManager.confirm(ed.getLang("iespell.download"), function(s) {
+							if (s)
+								window.open('http://www.iespell.com/download.php', 'ieSpellDownload', '');
+						});
+					} else
+						ed.windowManager.alert("Error Loading ieSpell: Exception " + e.number);
+				}
+			});
 
-			return true;
-		}
+			// Register buttons
+			ed.addButton('iespell', {title : 'iespell.iespell_desc', cmd : 'mceIESpell'});
+		},
 
-		// Pass to next handler in chain
-		return false;
-	}
-};
+		getInfo : function() {
+			return {
+				longname : 'IESpell (IE Only)',
+				author : 'Moxiecode Systems AB',
+				authorurl : 'http://tinymce.moxiecode.com',
+				infourl : 'http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/iespell',
+				version : tinymce.majorVersion + "." + tinymce.minorVersion
+			};
+		}
+	});
 
-tinyMCE.addPlugin("iespell", TinyMCE_IESpellPlugin);
+	// Register plugin
+	tinymce.PluginManager.add('iespell', tinymce.plugins.IESpell);
+})();
\ No newline at end of file
Binary file includes/clientside/tinymce/plugins/iespell/images/iespell.gif has changed
--- a/includes/clientside/tinymce/plugins/iespell/langs/en.js	Fri Feb 22 12:46:51 2008 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,7 +0,0 @@
-// UK lang variables
-
-tinyMCE.addToLang('',{
-iespell_desc : 'Run spell checking',
-iespell_download : "ieSpell not detected. Click OK to go to download page."
-});
-
--- a/includes/clientside/tinymce/plugins/iespell/readme.txt	Fri Feb 22 12:46:51 2008 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1 +0,0 @@
-Check the TinyMCE documentation for details on this plugin.
--- a/includes/clientside/tinymce/plugins/inlinepopups/css/inlinepopup.css	Fri Feb 22 12:46:51 2008 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,69 +0,0 @@
-/* Window classes */
-
-.mceWindow {
-	position: absolute;
-	left: 0;
-	top: 0;
-	border: 1px solid black;
-	background-color: #D4D0C8;
-}
-
-.mceWindowHead {
-	background-color: #334F8D;
-	width: 100%;
-	height: 18px;
-	cursor: move;
-	overflow: hidden;
-}
-
-.mceWindowBody {
-	clear: both;
-	background-color: white;
-}
-
-.mceWindowStatusbar {
-	background-color: #D4D0C8;
-	height: 12px;
-	border-top: 1px solid black;
-}
-
-.mceWindowTitle {
-	float: left;
-	font-family: "MS Sans Serif";
-	font-size: 9pt;
-	font-weight: bold;
-	line-height: 18px;
-	color: white;
-	margin-left: 2px;
-	overflow: hidden;
-}
-
-.mceWindowHeadTools {
-	margin-right: 2px;
-}
-
-.mceWindowClose, .mceWindowMinimize, .mceWindowMaximize {
-	display: block;
-	float: right;
-	overflow: hidden;
-	margin-top: 2px;
-}
-
-.mceWindowClose {
-	margin-left: 2px;
-}
-
-.mceWindowMinimize {
-}
-
-.mceWindowMaximize {
-}
-
-.mceWindowResize {
-	display: block;
-	float: right;
-	overflow: hidden;
-	cursor: se-resize;
-	width: 12px;
-	height: 12px;
-}
--- a/includes/clientside/tinymce/plugins/inlinepopups/editor_plugin.js	Fri Feb 22 12:46:51 2008 -0500
+++ b/includes/clientside/tinymce/plugins/inlinepopups/editor_plugin.js	Fri Feb 22 12:51:53 2008 -0500
@@ -1,1 +1,1 @@
-var TinyMCE_InlinePopupsPlugin={getInfo:function(){return{longname:'Inline Popups',author:'Moxiecode Systems AB',authorurl:'http://tinymce.moxiecode.com',infourl:'http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/inlinepopups',version:tinyMCE.majorVersion+"."+tinyMCE.minorVersion}}};tinyMCE.addPlugin("inlinepopups",TinyMCE_InlinePopupsPlugin);TinyMCE_Engine.prototype.orgOpenWindow=TinyMCE_Engine.prototype.openWindow;TinyMCE_Engine.prototype.orgCloseWindow=TinyMCE_Engine.prototype.closeWindow;TinyMCE_Engine.prototype.openWindow=function(template,args){if(args['inline']!="yes"||tinyMCE.isOpera||tinyMCE.getParam("plugins").indexOf('inlinepopups')==-1){mcWindows.selectedWindow=null;args['mce_inside_iframe']=false;this.orgOpenWindow(template,args);return}var url,resizable,scrollbars;args['mce_inside_iframe']=true;tinyMCE.windowArgs=args;if(template['file'].charAt(0)!='/'&&template['file'].indexOf('://')==-1)url=tinyMCE.baseURL+"/themes/"+tinyMCE.getParam("theme")+"/"+template['file'];else url=template['file'];if(!(width=parseInt(template['width'])))width=320;if(!(height=parseInt(template['height'])))height=200;if(!(minWidth=parseInt(template['minWidth'])))minWidth=100;if(!(minHeight=parseInt(template['minHeight'])))minHeight=100;resizable=(args&&args['resizable'])?args['resizable']:"no";scrollbars=(args&&args['scrollbars'])?args['scrollbars']:"no";height+=18;for(var name in args){if(typeof(args[name])=='function')continue;url=tinyMCE.replaceVar(url,name,escape(args[name]))}var elm=document.getElementById(this.selectedInstance.editorId+'_parent');if(tinyMCE.hasPlugin('fullscreen')&&this.selectedInstance.getData('fullscreen').enabled)pos={absLeft:0,absTop:0};else pos=tinyMCE.getAbsPosition(elm);pos.absLeft+=Math.round((elm.firstChild.clientWidth/ 2) - (width /2));pos.absTop+=Math.round((elm.firstChild.clientHeight/ 2) - (height /2));mcWindows.open(url,mcWindows.idCounter++,"modal=yes,width="+width+",height="+height+",resizable="+resizable+",scrollbars="+scrollbars+",statusbar="+resizable+",left="+pos.absLeft+",top="+pos.absTop+",minWidth="+minWidth+",minHeight="+minHeight)};TinyMCE_Engine.prototype.closeWindow=function(win){var gotit=false,n,w;for(n in mcWindows.windows){w=mcWindows.windows[n];if(typeof(w)=='function')continue;if(win.name==w.id+'_iframe'){w.close();gotit=true}}if(!gotit)this.orgCloseWindow(win);tinyMCE.selectedInstance.getWin().focus()};TinyMCE_Engine.prototype.setWindowTitle=function(win_ref,title){for(var n in mcWindows.windows){var win=mcWindows.windows[n];if(typeof(win)=='function')continue;if(win_ref.name==win.id+"_iframe")window.frames[win.id+"_iframe"].document.getElementById(win.id+'_title').innerHTML=title}};function TinyMCE_Windows(){this.settings=new Array();this.windows=new Array();this.isMSIE=(navigator.appName=="Microsoft Internet Explorer");this.isGecko=navigator.userAgent.indexOf('Gecko')!=-1;this.isSafari=navigator.userAgent.indexOf('Safari')!=-1;this.isMac=navigator.userAgent.indexOf('Mac')!=-1;this.isMSIE5_0=this.isMSIE&&(navigator.userAgent.indexOf('MSIE 5.0')!=-1);this.action="none";this.selectedWindow=null;this.lastSelectedWindow=null;this.zindex=1001;this.mouseDownScreenX=0;this.mouseDownScreenY=0;this.mouseDownLayerX=0;this.mouseDownLayerY=0;this.mouseDownWidth=0;this.mouseDownHeight=0;this.idCounter=0};TinyMCE_Windows.prototype.init=function(settings){this.settings=settings;if(this.isMSIE)this.addEvent(document,"mousemove",mcWindows.eventDispatcher);else this.addEvent(window,"mousemove",mcWindows.eventDispatcher);this.addEvent(document,"mouseup",mcWindows.eventDispatcher);this.addEvent(window,"resize",mcWindows.eventDispatcher);this.addEvent(document,"scroll",mcWindows.eventDispatcher);this.doc=document};TinyMCE_Windows.prototype.getBounds=function(){if(!this.bounds){var vp=tinyMCE.getViewPort(window);var top,left,bottom,right,docEl=this.doc.documentElement;top=vp.top;left=vp.left;bottom=vp.height+top-2;right=vp.width+left-22;this.bounds=[left,top,right,bottom]}return this.bounds};TinyMCE_Windows.prototype.clampBoxPosition=function(x,y,w,h,minW,minH){var bounds=this.getBounds();x=Math.max(bounds[0],Math.min(bounds[2],x+w)-w);y=Math.max(bounds[1],Math.min(bounds[3],y+h)-h);return this.clampBoxSize(x,y,w,h,minW,minH)};TinyMCE_Windows.prototype.clampBoxSize=function(x,y,w,h,minW,minH){var bounds=this.getBounds();return[x,y,Math.max(minW,Math.min(bounds[2],x+w)-x),Math.max(minH,Math.min(bounds[3],y+h)-y)]};TinyMCE_Windows.prototype.getParam=function(name,default_value){var value=null;value=(typeof(this.settings[name])=="undefined")?default_value:this.settings[name];if(value=="true"||value=="false")return(value=="true");return value};TinyMCE_Windows.prototype.eventDispatcher=function(e){e=typeof(e)=="undefined"?window.event:e;if(mcWindows.selectedWindow==null)return;if(mcWindows.isGecko&&e.type=="mousedown"){var elm=e.currentTarget;for(var n in mcWindows.windows){var win=mcWindows.windows[n];if(win.headElement==elm||win.resizeElement==elm){win.focus();break}}}switch(e.type){case"mousemove":mcWindows.selectedWindow.onMouseMove(e);break;case"mouseup":mcWindows.selectedWindow.onMouseUp(e);break;case"mousedown":mcWindows.selectedWindow.onMouseDown(e);break;case"focus":mcWindows.selectedWindow.onFocus(e);break;case"scroll":case"resize":if(mcWindows.clampUpdateTimeout)clearTimeout(mcWindows.clampUpdateTimeout);mcWindows.clampEventType=e.type;mcWindows.clampUpdateTimeout=setTimeout(function(){mcWindows.updateClamping()},100);break}};TinyMCE_Windows.prototype.updateClamping=function(){var clamp,oversize,etype=mcWindows.clampEventType;this.bounds=null;this.clampUpdateTimeout=null;for(var n in this.windows){win=this.windows[n];if(typeof(win)=='function'||!win.winElement)continue;clamp=mcWindows.clampBoxPosition(win.left,win.top,win.winElement.scrollWidth,win.winElement.scrollHeight,win.features.minWidth,win.features.minHeight);oversize=(clamp[2]!=win.winElement.scrollWidth||clamp[3]!=win.winElement.scrollHeight)?true:false;if(!oversize||win.features.resizable=="yes"||etype!="scroll")win.moveTo(clamp[0],clamp[1]);if(oversize&&win.features.resizable=="yes")win.resizeTo(clamp[2],clamp[3])}};TinyMCE_Windows.prototype.addEvent=function(obj,name,handler){if(this.isMSIE)obj.attachEvent("on"+name,handler);else obj.addEventListener(name,handler,false)};TinyMCE_Windows.prototype.cancelEvent=function(e){if(this.isMSIE){e.returnValue=false;e.cancelBubble=true}else e.preventDefault()};TinyMCE_Windows.prototype.parseFeatures=function(opts){opts=opts.toLowerCase();opts=opts.replace(/;/g,",");opts=opts.replace(/[^0-9a-z=,]/g,"");var optionChunks=opts.split(',');var options=new Array();options['left']="10";options['top']="10";options['width']="300";options['height']="300";options['minwidth']="100";options['minheight']="100";options['resizable']="yes";options['minimizable']="yes";options['maximizable']="yes";options['close']="yes";options['movable']="yes";options['statusbar']="yes";options['scrollbars']="auto";options['modal']="no";if(opts=="")return options;for(var i=0;i<optionChunks.length;i++){var parts=optionChunks[i].split('=');if(parts.length==2)options[parts[0]]=parts[1]}options['left']=parseInt(options['left']);options['top']=parseInt(options['top']);options['width']=parseInt(options['width']);options['height']=parseInt(options['height']);options['minWidth']=parseInt(options['minwidth']);options['minHeight']=parseInt(options['minheight']);return options};TinyMCE_Windows.prototype.open=function(url,name,features){this.lastSelectedWindow=this.selectedWindow;var win=new TinyMCE_Window();var winDiv,html="",id;var imgPath=this.getParam("images_path");features=this.parseFeatures(features);var clamp=mcWindows.clampBoxPosition(features['left'],features['top'],features['width'],features['height'],features['minWidth'],features['minHeight']);features['left']=clamp[0];features['top']=clamp[1];if(features['resizable']=="yes"){features['width']=clamp[2];features['height']=clamp[3]}id="mcWindow_"+name;win.deltaHeight=18;if(features['statusbar']=="yes"){win.deltaHeight+=13;if(this.isMSIE)win.deltaHeight+=1}width=parseInt(features['width']);height=parseInt(features['height'])-win.deltaHeight;if(this.isMSIE)width-=2;win.id=id;win.url=url;win.name=name;win.features=features;this.windows[name]=win;iframeWidth=width;iframeHeight=height;html+='<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">';html+='<html>';html+='<head>';html+='<title>Wrapper iframe</title>';html+='<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">';html+='<link href="'+this.getParam("css_file")+'" rel="stylesheet" type="text/css" />';html+='</head>';html+='<body onload="parent.mcWindows.onLoad(\''+name+'\');">';html+='<div id="'+id+'_container" class="mceWindow">';html+='<div id="'+id+'_head" class="mceWindowHead" onmousedown="parent.mcWindows.windows[\''+name+'\'].focus();">';html+='  <div id="'+id+'_title" class="mceWindowTitle"';html+='  onselectstart="return false;" unselectable="on" style="-moz-user-select: none !important;"></div>';html+='    <div class="mceWindowHeadTools">';html+='      <a href="javascript:parent.mcWindows.windows[\''+name+'\'].close();" target="_self" onmousedown="return false;" class="mceWindowClose"><img border="0" src="'+imgPath+'/window_close.gif" /></a>';if(features['resizable']=="yes"&&features['maximizable']=="yes")html+='      <a href="javascript:parent.mcWindows.windows[\''+name+'\'].maximize();" target="_self" onmousedown="return false;" class="mceWindowMaximize"><img border="0" src="'+imgPath+'/window_maximize.gif" /></a>';html+='    </div>';html+='</div><div id="'+id+'_body" class="mceWindowBody" style="width: '+width+'px; height: '+height+'px;">';html+='<iframe id="'+id+'_iframe" name="'+id+'_iframe" frameborder="0" width="'+iframeWidth+'" height="'+iframeHeight+'" src="'+url+'" class="mceWindowBodyIframe" scrolling="'+features['scrollbars']+'"></iframe></div>';if(features['statusbar']=="yes"){html+='<div id="'+id+'_statusbar" class="mceWindowStatusbar" onmousedown="parent.mcWindows.windows[\''+name+'\'].focus();">';if(features['resizable']=="yes"){if(this.isGecko)html+='<div id="'+id+'_resize" class="mceWindowResize"><div style="background-image: url(\''+imgPath+'/window_resize.gif\'); width: 12px; height: 12px;"></div></div>';else html+='<div id="'+id+'_resize" class="mceWindowResize"><img onmousedown="parent.mcWindows.windows[\''+name+'\'].focus();" border="0" src="'+imgPath+'/window_resize.gif" /></div>'}html+='</div>'}html+='</div>';html+='</body>';html+='</html>';this.createFloatingIFrame(id,features['left'],features['top'],features['width'],features['height'],html)};TinyMCE_Windows.prototype.setDocumentLock=function(state){var elm=document.getElementById('mcWindowEventBlocker');if(state){if(elm==null){elm=document.createElement("div");elm.id="mcWindowEventBlocker";elm.style.position="absolute";elm.style.left="0";elm.style.top="0";document.body.appendChild(elm)}elm.style.display="none";var imgPath=this.getParam("images_path");var width=document.body.clientWidth;var height=document.body.clientHeight;elm.style.width=width;elm.style.height=height;elm.innerHTML='<img src="'+imgPath+'/spacer.gif" width="'+width+'" height="'+height+'" />';elm.style.zIndex=mcWindows.zindex-1;elm.style.display="block"}else if(elm!=null){if(mcWindows.windows.length==0)elm.parentNode.removeChild(elm);else elm.style.zIndex=mcWindows.zindex-1}};TinyMCE_Windows.prototype.onLoad=function(name){var win=mcWindows.windows[name];var id="mcWindow_"+name;var wrapperIframe=window.frames[id+"_iframe"].frames[0];var wrapperDoc=window.frames[id+"_iframe"].document;var doc=window.frames[id+"_iframe"].document;var winDiv=document.getElementById("mcWindow_"+name+"_div");var realIframe=window.frames[id+"_iframe"].frames[0];win.id="mcWindow_"+name;win.winElement=winDiv;win.bodyElement=doc.getElementById(id+'_body');win.iframeElement=doc.getElementById(id+'_iframe');win.headElement=doc.getElementById(id+'_head');win.titleElement=doc.getElementById(id+'_title');win.resizeElement=doc.getElementById(id+'_resize');win.containerElement=doc.getElementById(id+'_container');win.left=win.features['left'];win.top=win.features['top'];win.frame=window.frames[id+'_iframe'].frames[0];win.wrapperFrame=window.frames[id+'_iframe'];win.wrapperIFrameElement=document.getElementById(id+"_iframe");mcWindows.addEvent(win.headElement,"mousedown",mcWindows.eventDispatcher);if(win.resizeElement!=null)mcWindows.addEvent(win.resizeElement,"mousedown",mcWindows.eventDispatcher);if(mcWindows.isMSIE){mcWindows.addEvent(realIframe.document,"mousemove",mcWindows.eventDispatcher);mcWindows.addEvent(realIframe.document,"mouseup",mcWindows.eventDispatcher)}else{mcWindows.addEvent(realIframe,"mousemove",mcWindows.eventDispatcher);mcWindows.addEvent(realIframe,"mouseup",mcWindows.eventDispatcher);mcWindows.addEvent(realIframe,"focus",mcWindows.eventDispatcher)}for(var i=0;i<window.frames.length;i++){if(!window.frames[i]._hasMouseHandlers){if(mcWindows.isMSIE){mcWindows.addEvent(window.frames[i].document,"mousemove",mcWindows.eventDispatcher);mcWindows.addEvent(window.frames[i].document,"mouseup",mcWindows.eventDispatcher)}else{mcWindows.addEvent(window.frames[i],"mousemove",mcWindows.eventDispatcher);mcWindows.addEvent(window.frames[i],"mouseup",mcWindows.eventDispatcher)}window.frames[i]._hasMouseHandlers=true}}if(mcWindows.isMSIE){mcWindows.addEvent(win.frame.document,"mousemove",mcWindows.eventDispatcher);mcWindows.addEvent(win.frame.document,"mouseup",mcWindows.eventDispatcher)}else{mcWindows.addEvent(win.frame,"mousemove",mcWindows.eventDispatcher);mcWindows.addEvent(win.frame,"mouseup",mcWindows.eventDispatcher);mcWindows.addEvent(win.frame,"focus",mcWindows.eventDispatcher)}var func=this.getParam("on_open_window","");if(func!="")eval(func+"(win);");win.focus();if(win.features['modal']=="yes")mcWindows.setDocumentLock(true)};TinyMCE_Windows.prototype.createFloatingIFrame=function(id_prefix,left,top,width,height,html){var iframe=document.createElement("iframe");var div=document.createElement("div"),doc;width=parseInt(width);height=parseInt(height)+1;div.setAttribute("id",id_prefix+"_div");div.setAttribute("width",width);div.setAttribute("height",(height));div.style.position="absolute";div.style.left=left+"px";div.style.top=top+"px";div.style.width=width+"px";div.style.height=(height)+"px";div.style.backgroundColor="white";div.style.display="none";if(this.isGecko){iframeWidth=width+2;iframeHeight=height+2}else{iframeWidth=width;iframeHeight=height+1}iframe.setAttribute("id",id_prefix+"_iframe");iframe.setAttribute("name",id_prefix+"_iframe");iframe.setAttribute("border","0");iframe.setAttribute("frameBorder","0");iframe.setAttribute("marginWidth","0");iframe.setAttribute("marginHeight","0");iframe.setAttribute("leftMargin","0");iframe.setAttribute("topMargin","0");iframe.setAttribute("width",iframeWidth);iframe.setAttribute("height",iframeHeight);iframe.setAttribute("scrolling","no");iframe.style.width=iframeWidth+"px";iframe.style.height=iframeHeight+"px";iframe.style.backgroundColor="white";div.appendChild(iframe);document.body.appendChild(div);div.innerHTML=div.innerHTML;if(this.isSafari){window.setTimeout(function(){var doc=window.frames[id_prefix+'_iframe'].document;doc.open();doc.write(html);doc.close()},10)}else{doc=window.frames[id_prefix+'_iframe'].window.document;doc.open();doc.write(html);doc.close()}div.style.display="block";return div};function TinyMCE_Window(){};TinyMCE_Window.prototype.focus=function(){if(this!=mcWindows.selectedWindow){this.winElement.style.zIndex=++mcWindows.zindex;mcWindows.lastSelectedWindow=mcWindows.selectedWindow;mcWindows.selectedWindow=this}};TinyMCE_Window.prototype.minimize=function(){};TinyMCE_Window.prototype.maximize=function(){if(this.restoreSize){this.moveTo(this.restoreSize[0],this.restoreSize[1]);this.resizeTo(this.restoreSize[2],this.restoreSize[3]);this.updateClamping();this.restoreSize=null}else{var bounds=mcWindows.getBounds();this.restoreSize=[this.left,this.top,this.winElement.scrollWidth,this.winElement.scrollHeight];this.moveTo(bounds[0],bounds[1]);this.resizeTo(bounds[2]-bounds[0],bounds[3]-bounds[1])}};TinyMCE_Window.prototype.startResize=function(){mcWindows.action="resize"};TinyMCE_Window.prototype.startMove=function(e){mcWindows.action="move"};TinyMCE_Window.prototype.close=function(){if(this.frame&&this.frame['tinyMCEPopup'])this.frame['tinyMCEPopup'].restoreSelection();if(mcWindows.lastSelectedWindow!=null)mcWindows.lastSelectedWindow.focus();var mcWindowsNew=new Array();for(var n in mcWindows.windows){var win=mcWindows.windows[n];if(typeof(win)=='function')continue;if(win.name!=this.name)mcWindowsNew[n]=win}mcWindows.windows=mcWindowsNew;var e=mcWindows.doc.getElementById(this.id+"_iframe");e.parentNode.removeChild(e);var e=mcWindows.doc.getElementById(this.id+"_div");e.parentNode.removeChild(e);mcWindows.setDocumentLock(false)};TinyMCE_Window.prototype.onMouseMove=function(e){var clamp;var dx=e.screenX-mcWindows.mouseDownScreenX;var dy=e.screenY-mcWindows.mouseDownScreenY;switch(mcWindows.action){case"resize":clamp=mcWindows.clampBoxSize(this.left,this.top,mcWindows.mouseDownWidth+(e.screenX-mcWindows.mouseDownScreenX),mcWindows.mouseDownHeight+(e.screenY-mcWindows.mouseDownScreenY),this.features.minWidth,this.features.minHeight);this.resizeTo(clamp[2],clamp[3]);mcWindows.cancelEvent(e);break;case"move":this.left=mcWindows.mouseDownLayerX+(e.screenX-mcWindows.mouseDownScreenX);this.top=mcWindows.mouseDownLayerY+(e.screenY-mcWindows.mouseDownScreenY);this.updateClamping();mcWindows.cancelEvent(e);break}};TinyMCE_Window.prototype.moveTo=function(x,y){this.left=x;this.top=y;this.winElement.style.left=this.left+"px";this.winElement.style.top=this.top+"px"};TinyMCE_Window.prototype.resizeTo=function(width,height){this.wrapperIFrameElement.style.width=(width+2)+'px';this.wrapperIFrameElement.style.height=(height+2)+'px';this.wrapperIFrameElement.width=width+2;this.wrapperIFrameElement.height=height+2;this.winElement.style.width=width+'px';this.winElement.style.height=height+'px';height=height-this.deltaHeight;this.containerElement.style.width=width+'px';this.iframeElement.style.width=width+'px';this.iframeElement.style.height=height+'px';this.bodyElement.style.width=width+'px';this.bodyElement.style.height=height+'px';this.headElement.style.width=width+'px';};TinyMCE_Window.prototype.updateClamping=function(){var clamp,oversize;clamp=mcWindows.clampBoxPosition(this.left,this.top,this.winElement.scrollWidth,this.winElement.scrollHeight,this.features.minWidth,this.features.minHeight);oversize=(clamp[2]!=this.winElement.scrollWidth||clamp[3]!=this.winElement.scrollHeight)?true:false;this.moveTo(clamp[0],clamp[1]);if(this.features.resizable=="yes"&&oversize)this.resizeTo(clamp[2],clamp[3])};function debug(msg){document.getElementById('debug').value+=msg+"\n"}TinyMCE_Window.prototype.onMouseUp=function(e){mcWindows.action="none"};TinyMCE_Window.prototype.onFocus=function(e){var winRef=e.currentTarget;for(var n in mcWindows.windows){var win=mcWindows.windows[n];if(typeof(win)=='function')continue;if(winRef.name==win.id+"_iframe"){win.focus();return}}};TinyMCE_Window.prototype.onMouseDown=function(e){var elm=mcWindows.isMSIE?this.wrapperFrame.event.srcElement:e.target;mcWindows.mouseDownScreenX=e.screenX;mcWindows.mouseDownScreenY=e.screenY;mcWindows.mouseDownLayerX=this.left;mcWindows.mouseDownLayerY=this.top;mcWindows.mouseDownWidth=parseInt(this.winElement.style.width);mcWindows.mouseDownHeight=parseInt(this.winElement.style.height);if(this.resizeElement!=null&&elm==this.resizeElement.firstChild)this.startResize(e);else this.startMove(e);mcWindows.cancelEvent(e)};var mcWindows=new TinyMCE_Windows();mcWindows.init({images_path:tinyMCE.baseURL+"/plugins/inlinepopups/images",css_file:tinyMCE.baseURL+"/plugins/inlinepopups/css/inlinepopup.css"});
\ No newline at end of file
+(function(){var DOM=tinymce.DOM,Element=tinymce.dom.Element,Event=tinymce.dom.Event,each=tinymce.each,is=tinymce.is;tinymce.create('tinymce.plugins.InlinePopups',{init:function(ed,url){ed.onBeforeRenderUI.add(function(){ed.windowManager=new tinymce.InlineWindowManager(ed);DOM.loadCSS(url+'/skins/'+(ed.settings.inlinepopups_skin||'clearlooks2')+"/window.css");});},getInfo:function(){return{longname:'InlinePopups',author:'Moxiecode Systems AB',authorurl:'http://tinymce.moxiecode.com',infourl:'http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/inlinepopups',version:tinymce.majorVersion+"."+tinymce.minorVersion};}});tinymce.create('tinymce.InlineWindowManager:tinymce.WindowManager',{InlineWindowManager:function(ed){var t=this;t.parent(ed);t.zIndex=1000;},open:function(f,p){var t=this,id,opt='',ed=t.editor,dw=0,dh=0,vp,po,mdf,clf,we,w;f=f||{};p=p||{};if(!f.inline)return t.parent(f,p);t.bookmark=ed.selection.getBookmark('simple');id=DOM.uniqueId();vp=DOM.getViewPort();f.width=parseInt(f.width||320);f.height=parseInt(f.height||240)+(tinymce.isIE?8:0);f.min_width=parseInt(f.min_width||150);f.min_height=parseInt(f.min_height||100);f.max_width=parseInt(f.max_width||2000);f.max_height=parseInt(f.max_height||2000);f.left=f.left||Math.round(Math.max(vp.x,vp.x+(vp.w/ 2.0) - (f.width /2.0)));f.top=f.top||Math.round(Math.max(vp.y,vp.y+(vp.h/ 2.0) - (f.height /2.0)));f.movable=f.resizable=true;p.mce_width=f.width;p.mce_height=f.height;p.mce_inline=true;p.mce_window_id=id;t.features=f;t.params=p;t.onOpen.dispatch(t,f,p);if(f.type){opt+=' modal '+f.type;f.resizable=false;}if(f.statusbar)opt+=' statusbar';if(f.resizable)opt+=' resizable';if(f.minimizable)opt+=' minimizable';if(f.maximizable)opt+=' maximizable';if(f.movable)opt+=' movable';t._addAll(document.body,['div',{id:id,'class':ed.settings.inlinepopups_skin||'clearlooks2',style:'width:100px;height:100px'},['div',{id:id+'_wrapper','class':'wrapper'+opt},['div',{id:id+'_top','class':'top'},['div',{'class':'left'}],['div',{'class':'center'}],['div',{'class':'right'}],['span',{id:id+'_title'},f.title||'']],['div',{id:id+'_middle','class':'middle'},['div',{id:id+'_left','class':'left'}],['span',{id:id+'_content'}],['div',{id:id+'_right','class':'right'}]],['div',{id:id+'_bottom','class':'bottom'},['div',{'class':'left'}],['div',{'class':'center'}],['div',{'class':'right'}],['span',{id:id+'_status'},'Content']],['a',{'class':'move',href:'javascript:;'}],['a',{'class':'min',href:'javascript:;',onmousedown:'return false;'}],['a',{'class':'max',href:'javascript:;',onmousedown:'return false;'}],['a',{'class':'med',href:'javascript:;',onmousedown:'return false;'}],['a',{'class':'close',href:'javascript:;',onmousedown:'return false;'}],['a',{id:id+'_resize_n','class':'resize resize-n',href:'javascript:;'}],['a',{id:id+'_resize_s','class':'resize resize-s',href:'javascript:;'}],['a',{id:id+'_resize_w','class':'resize resize-w',href:'javascript:;'}],['a',{id:id+'_resize_e','class':'resize resize-e',href:'javascript:;'}],['a',{id:id+'_resize_nw','class':'resize resize-nw',href:'javascript:;'}],['a',{id:id+'_resize_ne','class':'resize resize-ne',href:'javascript:;'}],['a',{id:id+'_resize_sw','class':'resize resize-sw',href:'javascript:;'}],['a',{id:id+'_resize_se','class':'resize resize-se',href:'javascript:;'}]]]);DOM.setStyles(id,{top:-10000,left:-10000});if(tinymce.isGecko)DOM.setStyle(id,'overflow','auto');if(!f.type){dw+=DOM.get(id+'_left').clientWidth;dw+=DOM.get(id+'_right').clientWidth;dh+=DOM.get(id+'_top').clientHeight;dh+=DOM.get(id+'_bottom').clientHeight;}DOM.setStyles(id,{top:f.top,left:f.left,width:f.width+dw,height:f.height+dh});if(!f.type){DOM.add(id+'_content','iframe',{id:id+'_ifr',src:'javascript:""',frameBorder:0,style:'border:0;width:10px;height:10px'});DOM.setStyles(id+'_ifr',{width:f.width,height:f.height});DOM.setAttrib(id+'_ifr','src',f.url||f.file);}else{DOM.add(id+'_wrapper','a',{id:id+'_ok','class':'button ok',href:'javascript:;',onmousedown:'return false;'},'Ok');if(f.type=='confirm')DOM.add(id+'_wrapper','a',{'class':'button cancel',href:'javascript:;',onmousedown:'return false;'},'Cancel');DOM.add(id+'_middle','div',{'class':'icon'});DOM.setHTML(id+'_content',f.content.replace('\n','<br />'));}mdf=Event.add(id,'mousedown',function(e){var n=e.target,w,vp;w=t.windows[id];t.focus(id);if(n.nodeName=='A'||n.nodeName=='a'){if(n.className=='max'){w.oldPos=w.element.getXY();w.oldSize=w.element.getSize();vp=DOM.getViewPort();vp.w-=2;vp.h-=2;w.element.moveTo(vp.x,vp.y);w.element.resizeTo(vp.w,vp.h);DOM.setStyles(id+'_ifr',{width:vp.w-w.deltaWidth,height:vp.h-w.deltaHeight});DOM.addClass(id+'_wrapper','maximized');}else if(n.className=='med'){w.element.moveTo(w.oldPos.x,w.oldPos.y);w.element.resizeTo(w.oldSize.w,w.oldSize.h);w.iframeElement.resizeTo(w.oldSize.w-w.deltaWidth,w.oldSize.h-w.deltaHeight);DOM.removeClass(id+'_wrapper','maximized');}else if(n.className=='move')return t._startDrag(id,e,n.className);else if(DOM.hasClass(n,'resize'))return t._startDrag(id,e,n.className.substring(7));}});clf=Event.add(id,'click',function(e){var n=e.target;t.focus(id);if(n.nodeName=='A'||n.nodeName=='a'){switch(n.className){case'close':t.close(null,id);return Event.cancel(e);case'button ok':case'button cancel':f.button_func(n.className=='button ok');return Event.cancel(e);}}});t.windows=t.windows||{};w=t.windows[id]={id:id,mousedown_func:mdf,click_func:clf,element:new Element(id,{blocker:1,container:ed.getContainer()}),iframeElement:new Element(id+'_ifr'),features:f,deltaWidth:dw,deltaHeight:dh};w.iframeElement.on('focus',function(){t.focus(id);});t.focus(id);t._fixIELayout(id,1);return w;},focus:function(id){var t=this,w=t.windows[id];w.zIndex=this.zIndex++;w.element.setStyle('zIndex',w.zIndex);w.element.update();id=id+'_wrapper';DOM.removeClass(t.lastId,'focus');DOM.addClass(id,'focus');t.lastId=id;},_addAll:function(te,ne){var i,n,t=this,dom=tinymce.DOM;if(is(ne,'string'))te.appendChild(dom.doc.createTextNode(ne));else if(ne.length){te=te.appendChild(dom.create(ne[0],ne[1]));for(i=2;i<ne.length;i++)t._addAll(te,ne[i]);}},_startDrag:function(id,se,ac){var t=this,mu,mm,d=document,eb,w=t.windows[id],we=w.element,sp=we.getXY(),p,sz,ph,cp,vp,sx,sy,sex,sey,dx,dy,dw,dh;cp={x:0,y:0};vp=DOM.getViewPort();vp.w-=2;vp.h-=2;sex=se.screenX;sey=se.screenY;dx=dy=dw=dh=0;mu=Event.add(d,'mouseup',function(e){Event.remove(d,'mouseup',mu);Event.remove(d,'mousemove',mm);if(eb)eb.remove();we.moveBy(dx,dy);we.resizeBy(dw,dh);sz=we.getSize();DOM.setStyles(id+'_ifr',{width:sz.w-w.deltaWidth,height:sz.h-w.deltaHeight});t._fixIELayout(id,1);return Event.cancel(e);});if(ac!='move')startMove();function startMove(){if(eb)return;t._fixIELayout(id,0);DOM.add(d.body,'div',{id:'mceEventBlocker','class':'mceEventBlocker '+(t.editor.settings.inlinepopups_skin||'clearlooks2'),style:{left:vp.x,top:vp.y,width:vp.w-20,height:vp.h-20,zIndex:20001}});eb=new Element('mceEventBlocker');eb.update();p=we.getXY();sz=we.getSize();sx=cp.x+p.x-vp.x;sy=cp.y+p.y-vp.y;DOM.add(eb.get(),'div',{id:'mcePlaceHolder','class':'placeholder',style:{left:sx,top:sy,width:sz.w,height:sz.h}});ph=new Element('mcePlaceHolder');};mm=Event.add(d,'mousemove',function(e){var x,y,v;startMove();x=e.screenX-sex;y=e.screenY-sey;switch(ac){case'resize-w':dx=x;dw=0-x;break;case'resize-e':dw=x;break;case'resize-n':case'resize-nw':case'resize-ne':if(ac=="resize-nw"){dx=x;dw=0-x;}else if(ac=="resize-ne")dw=x;dy=y;dh=0-y;break;case'resize-s':case'resize-sw':case'resize-se':if(ac=="resize-sw"){dx=x;dw=0-x;}else if(ac=="resize-se")dw=x;dh=y;break;case'move':dx=x;dy=y;break;}if(dw<(v=w.features.min_width-sz.w)){if(dx!==0)dx+=dw-v;dw=v;}if(dh<(v=w.features.min_height-sz.h)){if(dy!==0)dy+=dh-v;dh=v;}dw=Math.min(dw,w.features.max_width-sz.w);dh=Math.min(dh,w.features.max_height-sz.h);dx=Math.max(dx,vp.x-(sx+vp.x));dy=Math.max(dy,vp.y-(sy+vp.y));dx=Math.min(dx,(vp.w+vp.x)-(sx+sz.w+vp.x));dy=Math.min(dy,(vp.h+vp.y)-(sy+sz.h+vp.y));if(dx+dy!==0){if(sx+dx<0)dx=0;if(sy+dy<0)dy=0;ph.moveTo(sx+dx,sy+dy);}if(dw+dh!==0)ph.resizeTo(sz.w+dw,sz.h+dh);return Event.cancel(e);});return Event.cancel(se);},resizeBy:function(dw,dh,id){var w=this.windows[id];if(w){w.element.resizeBy(dw,dh);w.iframeElement.resizeBy(dw,dh);}},close:function(win,id){var t=this,w,d=document,ix=0,fw;if(!id&&win){t.parent(win);return;}if(w=t.windows[id]){t.onClose.dispatch(t);Event.remove(d,'mousedown',w.mousedownFunc);Event.remove(d,'click',w.clickFunc);DOM.setAttrib(id+'_ifr','src','javascript:""');w.element.remove();delete t.windows[id];each(t.windows,function(w){if(w.zIndex>ix){fw=w;ix=w.zIndex;}});if(fw)t.focus(fw.id);}},setTitle:function(ti,id){DOM.get(id+'_title').innerHTML=DOM.encode(ti);},alert:function(txt,cb,s){var t=this,w;w=t.open({title:t,type:'alert',button_func:function(s){if(cb)cb.call(s||t,s);t.close(null,w.id);},content:DOM.encode(t.editor.getLang(txt,txt)),inline:1,width:400,height:130});},confirm:function(txt,cb,s){var t=this,w;w=t.open({title:t,type:'confirm',button_func:function(s){if(cb)cb.call(s||t,s);t.close(null,w.id);},content:DOM.encode(t.editor.getLang(txt,txt)),inline:1,width:400,height:130});},_fixIELayout:function(id,s){var w,img;if(!tinymce.isIE6)return;each(['n','s','w','e','nw','ne','sw','se'],function(v){var e=DOM.get(id+'_resize_'+v);DOM.setStyles(e,{width:s?e.clientWidth:'',height:s?e.clientHeight:'',cursor:DOM.getStyle(e,'cursor',1)});DOM.setStyle(id+"_bottom",'bottom','-1px');e=0;});if(w=this.windows[id]){w.element.hide();w.element.show();each(DOM.select('div,a',id),function(e,i){if(e.currentStyle.backgroundImage!='none'){img=new Image();img.src=e.currentStyle.backgroundImage.replace(/url\(\"(.+)\"\)/,'$1');}});DOM.get(id).style.filter='';}}});tinymce.PluginManager.add('inlinepopups',tinymce.plugins.InlinePopups);})();
\ No newline at end of file
--- a/includes/clientside/tinymce/plugins/inlinepopups/editor_plugin_src.js	Fri Feb 22 12:46:51 2008 -0500
+++ b/includes/clientside/tinymce/plugins/inlinepopups/editor_plugin_src.js	Fri Feb 22 12:51:53 2008 -0500
@@ -1,814 +1,559 @@
-/**
- * $Id: editor_plugin_src.js 201 2007-02-12 15:56:56Z spocke $
- *
- * Moxiecode DHTML Windows script.
- *
- * @author Moxiecode
- * @copyright Copyright © 2004-2007, Moxiecode Systems AB, All rights reserved.
- */
-
-// Patch openWindow, closeWindow TinyMCE functions
-
-var TinyMCE_InlinePopupsPlugin = {
-	getInfo : function() {
-		return {
-			longname : 'Inline Popups',
-			author : 'Moxiecode Systems AB',
-			authorurl : 'http://tinymce.moxiecode.com',
-			infourl : 'http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/inlinepopups',
-			version : tinyMCE.majorVersion + "." + tinyMCE.minorVersion
-		};
-	}
-};
-
-tinyMCE.addPlugin("inlinepopups", TinyMCE_InlinePopupsPlugin);
-
-// Patch openWindow, closeWindow TinyMCE functions
-
-TinyMCE_Engine.prototype.orgOpenWindow = TinyMCE_Engine.prototype.openWindow;
-TinyMCE_Engine.prototype.orgCloseWindow = TinyMCE_Engine.prototype.closeWindow;
-
-TinyMCE_Engine.prototype.openWindow = function(template, args) {
-	// Does the caller support inline
-	if (args['inline'] != "yes" || tinyMCE.isOpera || tinyMCE.getParam("plugins").indexOf('inlinepopups') == -1) {
-		mcWindows.selectedWindow = null;
-		args['mce_inside_iframe'] = false;
-		this.orgOpenWindow(template, args);
-		return;
-	}
-
-	var url, resizable, scrollbars;
-
-	args['mce_inside_iframe'] = true;
-	tinyMCE.windowArgs = args;
-
-	if (template['file'].charAt(0) != '/' && template['file'].indexOf('://') == -1)
-		url = tinyMCE.baseURL + "/themes/" + tinyMCE.getParam("theme") + "/" + template['file'];
-	else
-		url = template['file'];
-
-	if (!(width = parseInt(template['width'])))
-		width = 320;
-
-	if (!(height = parseInt(template['height'])))
-		height = 200;
-
-	if (!(minWidth = parseInt(template['minWidth'])))
-		minWidth = 100;
-
-	if (!(minHeight = parseInt(template['minHeight'])))
-		minHeight = 100;
-
-	resizable = (args && args['resizable']) ? args['resizable'] : "no";
-	scrollbars = (args && args['scrollbars']) ? args['scrollbars'] : "no";
-
-	height += 18;
-
-	// Replace all args as variables in URL
-	for (var name in args) {
-		if (typeof(args[name]) == 'function')
-			continue;
-
-		url = tinyMCE.replaceVar(url, name, escape(args[name]));
-	}
-
-	var elm = document.getElementById(this.selectedInstance.editorId + '_parent');
-
-	if (tinyMCE.hasPlugin('fullscreen') && this.selectedInstance.getData('fullscreen').enabled)
-		pos = { absLeft: 0, absTop: 0 };
-	else
-		pos = tinyMCE.getAbsPosition(elm);
-
-	// Center div in editor area
-	pos.absLeft += Math.round((elm.firstChild.clientWidth / 2) - (width / 2));
-	pos.absTop += Math.round((elm.firstChild.clientHeight / 2) - (height / 2));
-
-	mcWindows.open(url, mcWindows.idCounter++, "modal=yes,width=" + width+ ",height=" + height + ",resizable=" + resizable + ",scrollbars=" + scrollbars + ",statusbar=" + resizable + ",left=" + pos.absLeft + ",top=" + pos.absTop + ",minWidth=" + minWidth + ",minHeight=" + minHeight );
-};
-
-TinyMCE_Engine.prototype.closeWindow = function(win) {
-	var gotit = false, n, w;
-	for (n in mcWindows.windows) {
-		w = mcWindows.windows[n];
-		if (typeof(w) == 'function') continue;
-		if (win.name == w.id + '_iframe') {
-			w.close();
-			gotit = true;
-		}
-	}
-	if (!gotit)
-		this.orgCloseWindow(win);
-
-	tinyMCE.selectedInstance.getWin().focus(); 
-};
-
-TinyMCE_Engine.prototype.setWindowTitle = function(win_ref, title) {
-	for (var n in mcWindows.windows) {
-		var win = mcWindows.windows[n];
-		if (typeof(win) == 'function')
-			continue;
-
-		if (win_ref.name == win.id + "_iframe")
-			window.frames[win.id + "_iframe"].document.getElementById(win.id + '_title').innerHTML = title;
-	}
-};
-
-// * * * * * TinyMCE_Windows classes below
-
-// Windows handler
-function TinyMCE_Windows() {
-	this.settings = new Array();
-	this.windows = new Array();
-	this.isMSIE = (navigator.appName == "Microsoft Internet Explorer");
-	this.isGecko = navigator.userAgent.indexOf('Gecko') != -1;
-	this.isSafari = navigator.userAgent.indexOf('Safari') != -1;
-	this.isMac = navigator.userAgent.indexOf('Mac') != -1;
-	this.isMSIE5_0 = this.isMSIE && (navigator.userAgent.indexOf('MSIE 5.0') != -1);
-	this.action = "none";
-	this.selectedWindow = null;
-	this.lastSelectedWindow = null;
-	this.zindex = 1001;
-	this.mouseDownScreenX = 0;
-	this.mouseDownScreenY = 0;
-	this.mouseDownLayerX = 0;
-	this.mouseDownLayerY = 0;
-	this.mouseDownWidth = 0;
-	this.mouseDownHeight = 0;
-	this.idCounter = 0;
-};
-
-TinyMCE_Windows.prototype.init = function(settings) {
-	this.settings = settings;
-
-	if (this.isMSIE)
-		this.addEvent(document, "mousemove", mcWindows.eventDispatcher);
-	else
-		this.addEvent(window, "mousemove", mcWindows.eventDispatcher);
-
-	this.addEvent(document, "mouseup", mcWindows.eventDispatcher);
-
-	this.addEvent(window, "resize", mcWindows.eventDispatcher);
-	this.addEvent(document, "scroll", mcWindows.eventDispatcher);
-
-	this.doc = document;
-};
-
-TinyMCE_Windows.prototype.getBounds = function() {
-	if (!this.bounds) {
-		var vp = tinyMCE.getViewPort(window);
-		var top, left, bottom, right, docEl = this.doc.documentElement;
-
-		top    = vp.top;
-		left   = vp.left;
-		bottom = vp.height + top - 2;
-		right  = vp.width  + left - 22; // TODO this number is platform dependant
-		// x1, y1, x2, y2
-		this.bounds = [left, top, right, bottom];
-	}
-	return this.bounds;
-};
-
-TinyMCE_Windows.prototype.clampBoxPosition = function(x, y, w, h, minW, minH) {
-	var bounds = this.getBounds();
-
-	x = Math.max(bounds[0], Math.min(bounds[2], x + w) - w);
-	y = Math.max(bounds[1], Math.min(bounds[3], y + h) - h);
-
-	return this.clampBoxSize(x, y, w, h, minW, minH);
-};
-
-TinyMCE_Windows.prototype.clampBoxSize = function(x, y, w, h, minW, minH) {
-	var bounds = this.getBounds();
-
-	return [
-		x, y,
-		Math.max(minW, Math.min(bounds[2], x + w) - x),
-		Math.max(minH, Math.min(bounds[3], y + h) - y)
-	];
-};
-
-TinyMCE_Windows.prototype.getParam = function(name, default_value) {
-	var value = null;
-
-	value = (typeof(this.settings[name]) == "undefined") ? default_value : this.settings[name];
-
-	// Fix bool values
-	if (value == "true" || value == "false")
-		return (value == "true");
-
-	return value;
-};
-
-TinyMCE_Windows.prototype.eventDispatcher = function(e) {
-	e = typeof(e) == "undefined" ? window.event : e;
-
-	if (mcWindows.selectedWindow == null)
-		return;
-
-	// Switch focus
-	if (mcWindows.isGecko && e.type == "mousedown") {
-		var elm = e.currentTarget;
-
-		for (var n in mcWindows.windows) {
-			var win = mcWindows.windows[n];
-
-			if (win.headElement == elm || win.resizeElement == elm) {
-				win.focus();
-				break;
-			}
-		}
-	}
-
-	switch (e.type) {
-		case "mousemove":
-			mcWindows.selectedWindow.onMouseMove(e);
-			break;
-
-		case "mouseup":
-			mcWindows.selectedWindow.onMouseUp(e);
-			break;
-
-		case "mousedown":
-			mcWindows.selectedWindow.onMouseDown(e);
-			break;
-
-		case "focus":
-			mcWindows.selectedWindow.onFocus(e);
-			break;
-		case "scroll":
-		case "resize":
-			if (mcWindows.clampUpdateTimeout)
-				clearTimeout(mcWindows.clampUpdateTimeout);
-			mcWindows.clampEventType = e.type;
-			mcWindows.clampUpdateTimeout =
-				setTimeout(function () {mcWindows.updateClamping()}, 100);
-			break;
-	}
-};
-
-TinyMCE_Windows.prototype.updateClamping = function () {
-	var clamp, oversize, etype = mcWindows.clampEventType;
-
-	this.bounds = null; // Recalc window bounds on resize/scroll
-	this.clampUpdateTimeout = null;
-
-	for (var n in this.windows) {
-		win = this.windows[n];
-		if (typeof(win) == 'function' || ! win.winElement) continue;
-
-		clamp = mcWindows.clampBoxPosition(
-			win.left, win.top,
-			win.winElement.scrollWidth,
-			win.winElement.scrollHeight,
-			win.features.minWidth,
-			win.features.minHeight
-		);
-		oversize = (
-			clamp[2] != win.winElement.scrollWidth ||
-			clamp[3] != win.winElement.scrollHeight
-		) ? true : false;
-
-		if (!oversize || win.features.resizable == "yes" || etype != "scroll")
-			win.moveTo(clamp[0], clamp[1]);
-		if (oversize && win.features.resizable == "yes")
-			win.resizeTo(clamp[2], clamp[3]);
-	}
-};
-
-TinyMCE_Windows.prototype.addEvent = function(obj, name, handler) {
-	if (this.isMSIE)
-		obj.attachEvent("on" + name, handler);
-	else
-		obj.addEventListener(name, handler, false);
-};
-
-TinyMCE_Windows.prototype.cancelEvent = function(e) {
-	if (this.isMSIE) {
-		e.returnValue = false;
-		e.cancelBubble = true;
-	} else
-		e.preventDefault();
-};
-
-TinyMCE_Windows.prototype.parseFeatures = function(opts) {
-	// Cleanup the options
-	opts = opts.toLowerCase();
-	opts = opts.replace(/;/g, ",");
-	opts = opts.replace(/[^0-9a-z=,]/g, "");
-
-	var optionChunks = opts.split(',');
-	var options = new Array();
-
-	options['left'] = "10";
-	options['top'] = "10";
-	options['width'] = "300";
-	options['height'] = "300";
-	options['minwidth'] = "100";
-	options['minheight'] = "100";
-	options['resizable'] = "yes";
-	options['minimizable'] = "yes";
-	options['maximizable'] = "yes";
-	options['close'] = "yes";
-	options['movable'] = "yes";
-	options['statusbar'] = "yes";
-	options['scrollbars'] = "auto";
-	options['modal'] = "no";
-
-	if (opts == "")
-		return options;
-
-	for (var i=0; i<optionChunks.length; i++) {
-		var parts = optionChunks[i].split('=');
-
-		if (parts.length == 2)
-			options[parts[0]] = parts[1];
-	}
-
-	options['left'] = parseInt(options['left']);
-	options['top'] = parseInt(options['top']);
-	options['width'] = parseInt(options['width']);
-	options['height'] = parseInt(options['height']);
-	options['minWidth'] = parseInt(options['minwidth']);
-	options['minHeight'] = parseInt(options['minheight']);
-
-	return options;
-};
-
-TinyMCE_Windows.prototype.open = function(url, name, features) {
-	this.lastSelectedWindow = this.selectedWindow;
-
-	var win = new TinyMCE_Window();
-	var winDiv, html = "", id;
-	var imgPath = this.getParam("images_path");
-
-	features = this.parseFeatures(features);
-
-	// Clamp specified dimensions
-	var clamp = mcWindows.clampBoxPosition(
-		features['left'], features['top'],
-		features['width'], features['height'],
-		features['minWidth'], features['minHeight']
-	);
-
-	features['left'] = clamp[0];
-	features['top'] = clamp[1];
-
-	if (features['resizable'] == "yes") {
-		features['width'] = clamp[2];
-		features['height'] = clamp[3];
-	}
-
-	// Create div
-	id = "mcWindow_" + name;
-	win.deltaHeight = 18;
-
-	if (features['statusbar'] == "yes") {
-		win.deltaHeight += 13;
-
-		if (this.isMSIE)
-			win.deltaHeight += 1;
-	}
-
-	width = parseInt(features['width']);
-	height = parseInt(features['height'])-win.deltaHeight;
-
-	if (this.isMSIE)
-		width -= 2;
-
-	// Setup first part of window
-	win.id = id;
-	win.url = url;
-	win.name = name;
-	win.features = features;
-	this.windows[name] = win;
-
-	iframeWidth = width;
-	iframeHeight = height;
-
-	// Create inner content
-	html += '<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">';
-	html += '<html>';
-	html += '<head>';
-	html += '<title>Wrapper iframe</title>';
-	html += '<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">';
-	html += '<link href="' + this.getParam("css_file") + '" rel="stylesheet" type="text/css" />';
-	html += '</head>';
-	html += '<body onload="parent.mcWindows.onLoad(\'' + name + '\');">';
-
-	html += '<div id="' + id + '_container" class="mceWindow">';
-	html += '<div id="' + id + '_head" class="mceWindowHead" onmousedown="parent.mcWindows.windows[\'' + name + '\'].focus();">';
-	html += '  <div id="' + id + '_title" class="mceWindowTitle"';
-	html += '  onselectstart="return false;" unselectable="on" style="-moz-user-select: none !important;"></div>';
-	html += '    <div class="mceWindowHeadTools">';
-	html += '      <a href="javascript:parent.mcWindows.windows[\'' + name + '\'].close();" target="_self" onmousedown="return false;" class="mceWindowClose"><img border="0" src="' + imgPath + '/window_close.gif" /></a>';
-	if (features['resizable'] == "yes" && features['maximizable'] == "yes")
-		html += '      <a href="javascript:parent.mcWindows.windows[\'' + name + '\'].maximize();" target="_self" onmousedown="return false;" class="mceWindowMaximize"><img border="0" src="' + imgPath + '/window_maximize.gif" /></a>';
-	// html += '      <a href="javascript:mcWindows.windows[\'' + name + '\'].minimize();" target="_self" onmousedown="return false;" class="mceWindowMinimize"></a>';
-	html += '    </div>';
-	html += '</div><div id="' + id + '_body" class="mceWindowBody" style="width: ' + width + 'px; height: ' + height + 'px;">';
-	html += '<iframe id="' + id + '_iframe" name="' + id + '_iframe" frameborder="0" width="' + iframeWidth + '" height="' + iframeHeight + '" src="' + url + '" class="mceWindowBodyIframe" scrolling="' + features['scrollbars'] + '"></iframe></div>';
-
-	if (features['statusbar'] == "yes") {
-		html += '<div id="' + id + '_statusbar" class="mceWindowStatusbar" onmousedown="parent.mcWindows.windows[\'' + name + '\'].focus();">';
-
-		if (features['resizable'] == "yes") {
-			if (this.isGecko)
-				html += '<div id="' + id + '_resize" class="mceWindowResize"><div style="background-image: url(\'' + imgPath + '/window_resize.gif\'); width: 12px; height: 12px;"></div></div>';
-			else
-				html += '<div id="' + id + '_resize" class="mceWindowResize"><img onmousedown="parent.mcWindows.windows[\'' + name + '\'].focus();" border="0" src="' + imgPath + '/window_resize.gif" /></div>';
-		}
-
-		html += '</div>';
-	}
-
-	html += '</div>';
-
-	html += '</body>';
-	html += '</html>';
-
-	// Create iframe
-	this.createFloatingIFrame(id, features['left'], features['top'], features['width'], features['height'], html);
-};
-
-// Blocks the document events by placing a image over the whole document
-TinyMCE_Windows.prototype.setDocumentLock = function(state) {
-	var elm = document.getElementById('mcWindowEventBlocker');
-
-	if (state) {
-		if (elm == null) {
-			elm = document.createElement("div");
-
-			elm.id = "mcWindowEventBlocker";
-			elm.style.position = "absolute";
-			elm.style.left = "0";
-			elm.style.top = "0";
-
-			document.body.appendChild(elm);
-		}
-
-		elm.style.display = "none";
-
-		var imgPath = this.getParam("images_path");
-		var width = document.body.clientWidth;
-		var height = document.body.clientHeight;
-
-		elm.style.width = width;
-		elm.style.height = height;
-		elm.innerHTML = '<img src="' + imgPath + '/spacer.gif" width="' + width + '" height="' + height + '" />';
-
-		elm.style.zIndex = mcWindows.zindex-1;
-		elm.style.display = "block";
-	} else if (elm != null) {
-		if (mcWindows.windows.length == 0)
-			elm.parentNode.removeChild(elm);
-		else
-			elm.style.zIndex = mcWindows.zindex-1;
-	}
-};
-
-// Gets called when wrapper iframe is initialized
-TinyMCE_Windows.prototype.onLoad = function(name) {
-	var win = mcWindows.windows[name];
-	var id = "mcWindow_" + name;
-	var wrapperIframe = window.frames[id + "_iframe"].frames[0];
-	var wrapperDoc = window.frames[id + "_iframe"].document;
-	var doc = window.frames[id + "_iframe"].document;
-	var winDiv = document.getElementById("mcWindow_" + name + "_div");
-	var realIframe = window.frames[id + "_iframe"].frames[0];
-
-	// Set window data
-	win.id = "mcWindow_" + name;
-	win.winElement = winDiv;
-	win.bodyElement = doc.getElementById(id + '_body');
-	win.iframeElement = doc.getElementById(id + '_iframe');
-	win.headElement = doc.getElementById(id + '_head');
-	win.titleElement = doc.getElementById(id + '_title');
-	win.resizeElement = doc.getElementById(id + '_resize');
-	win.containerElement = doc.getElementById(id + '_container');
-	win.left = win.features['left'];
-	win.top = win.features['top'];
-	win.frame = window.frames[id + '_iframe'].frames[0];
-	win.wrapperFrame = window.frames[id + '_iframe'];
-	win.wrapperIFrameElement = document.getElementById(id + "_iframe");
-
-	// Add event handlers
-	mcWindows.addEvent(win.headElement, "mousedown", mcWindows.eventDispatcher);
-
-	if (win.resizeElement != null)
-		mcWindows.addEvent(win.resizeElement, "mousedown", mcWindows.eventDispatcher);
-
-	if (mcWindows.isMSIE) {
-		mcWindows.addEvent(realIframe.document, "mousemove", mcWindows.eventDispatcher);
-		mcWindows.addEvent(realIframe.document, "mouseup", mcWindows.eventDispatcher);
-	} else {
-		mcWindows.addEvent(realIframe, "mousemove", mcWindows.eventDispatcher);
-		mcWindows.addEvent(realIframe, "mouseup", mcWindows.eventDispatcher);
-		mcWindows.addEvent(realIframe, "focus", mcWindows.eventDispatcher);
-	}
-
-	for (var i=0; i<window.frames.length; i++) {
-		if (!window.frames[i]._hasMouseHandlers) {
-			if (mcWindows.isMSIE) {
-				mcWindows.addEvent(window.frames[i].document, "mousemove", mcWindows.eventDispatcher);
-				mcWindows.addEvent(window.frames[i].document, "mouseup", mcWindows.eventDispatcher);
-			} else {
-				mcWindows.addEvent(window.frames[i], "mousemove", mcWindows.eventDispatcher);
-				mcWindows.addEvent(window.frames[i], "mouseup", mcWindows.eventDispatcher);
-			}
-
-			window.frames[i]._hasMouseHandlers = true;
-		}
-	}
-
-	if (mcWindows.isMSIE) {
-		mcWindows.addEvent(win.frame.document, "mousemove", mcWindows.eventDispatcher);
-		mcWindows.addEvent(win.frame.document, "mouseup", mcWindows.eventDispatcher);
-	} else {
-		mcWindows.addEvent(win.frame, "mousemove", mcWindows.eventDispatcher);
-		mcWindows.addEvent(win.frame, "mouseup", mcWindows.eventDispatcher);
-		mcWindows.addEvent(win.frame, "focus", mcWindows.eventDispatcher);
-	}
-
-	// Dispatch open window event
-	var func = this.getParam("on_open_window", "");
-	if (func != "")
-		eval(func + "(win);");
-
-	win.focus();
-
-	if (win.features['modal'] == "yes")
-		mcWindows.setDocumentLock(true);
-};
-
-TinyMCE_Windows.prototype.createFloatingIFrame = function(id_prefix, left, top, width, height, html) {
-	var iframe = document.createElement("iframe");
-	var div = document.createElement("div"), doc;
-
-	width = parseInt(width);
-	height = parseInt(height)+1;
-
-	// Create wrapper div
-	div.setAttribute("id", id_prefix + "_div");
-	div.setAttribute("width", width);
-	div.setAttribute("height", (height));
-	div.style.position = "absolute";
-
-	div.style.left = left + "px";
-	div.style.top = top + "px";
-	div.style.width = width + "px";
-	div.style.height = (height) + "px";
-	div.style.backgroundColor = "white";
-	div.style.display = "none";
-
-	if (this.isGecko) {
-		iframeWidth = width + 2;
-		iframeHeight = height + 2;
-	} else {
-		iframeWidth = width;
-		iframeHeight = height + 1;
-	}
-
-	// Create iframe
-	iframe.setAttribute("id", id_prefix + "_iframe");
-	iframe.setAttribute("name", id_prefix + "_iframe");
-	iframe.setAttribute("border", "0");
-	iframe.setAttribute("frameBorder", "0");
-	iframe.setAttribute("marginWidth", "0");
-	iframe.setAttribute("marginHeight", "0");
-	iframe.setAttribute("leftMargin", "0");
-	iframe.setAttribute("topMargin", "0");
-	iframe.setAttribute("width", iframeWidth);
-	iframe.setAttribute("height", iframeHeight);
-	// iframe.setAttribute("src", "../jscripts/tiny_mce/blank.htm");
-	// iframe.setAttribute("allowtransparency", "false");
-	iframe.setAttribute("scrolling", "no");
-	iframe.style.width = iframeWidth + "px";
-	iframe.style.height = iframeHeight + "px";
-	iframe.style.backgroundColor = "white";
-	div.appendChild(iframe);
-
-	document.body.appendChild(div);
-
-	// Fixed MSIE 5.0 issue
-	div.innerHTML = div.innerHTML;
-
-	if (this.isSafari) {
-		// Give Safari some time to setup
-		window.setTimeout(function() {
-			var doc = window.frames[id_prefix + '_iframe'].document;
-			doc.open();
-			doc.write(html);
-			doc.close();
-		}, 10);
-	} else {
-		doc = window.frames[id_prefix + '_iframe'].window.document;
-		doc.open();
-		doc.write(html);
-		doc.close();
-	}
-
-	div.style.display = "block";
-
-	return div;
-};
-
-// Window instance
-function TinyMCE_Window() {
-};
-
-TinyMCE_Window.prototype.focus = function() {
-	if (this != mcWindows.selectedWindow) {
-		this.winElement.style.zIndex = ++mcWindows.zindex;
-		mcWindows.lastSelectedWindow = mcWindows.selectedWindow;
-		mcWindows.selectedWindow = this;
-	}
-};
-
-TinyMCE_Window.prototype.minimize = function() {
-};
-
-TinyMCE_Window.prototype.maximize = function() {
-	if (this.restoreSize) {
-		this.moveTo(this.restoreSize[0], this.restoreSize[1]);
-		this.resizeTo(this.restoreSize[2], this.restoreSize[3]);
-		this.updateClamping();
-		this.restoreSize = null;
-	} else {
-		var bounds = mcWindows.getBounds();
-		this.restoreSize = [
-			this.left, this.top,
-			this.winElement.scrollWidth,
-			this.winElement.scrollHeight
-		];
-		this.moveTo(bounds[0], bounds[1]);
-		this.resizeTo(
-			bounds[2] - bounds[0],
-			bounds[3] - bounds[1]
-		);
-	}
-};
-
-TinyMCE_Window.prototype.startResize = function() {
-	mcWindows.action = "resize";
-};
-
-TinyMCE_Window.prototype.startMove = function(e) {
-	mcWindows.action = "move";
-};
-
-TinyMCE_Window.prototype.close = function() {
-	if (this.frame && this.frame['tinyMCEPopup'])
-		this.frame['tinyMCEPopup'].restoreSelection();
-
-	if (mcWindows.lastSelectedWindow != null)
-		mcWindows.lastSelectedWindow.focus();
-
-	var mcWindowsNew = new Array();
-	for (var n in mcWindows.windows) {
-		var win = mcWindows.windows[n];
-		if (typeof(win) == 'function')
-			continue;
-
-		if (win.name != this.name)
-			mcWindowsNew[n] = win;
-	}
-
-	mcWindows.windows = mcWindowsNew;
-
-	// alert(mcWindows.doc.getElementById(this.id + "_iframe"));
-
-	var e = mcWindows.doc.getElementById(this.id + "_iframe");
-	e.parentNode.removeChild(e);
-
-	var e = mcWindows.doc.getElementById(this.id + "_div");
-	e.parentNode.removeChild(e);
-
-	mcWindows.setDocumentLock(false);
-};
-
-TinyMCE_Window.prototype.onMouseMove = function(e) {
-	var clamp;
-	// Calculate real X, Y
-	var dx = e.screenX - mcWindows.mouseDownScreenX;
-	var dy = e.screenY - mcWindows.mouseDownScreenY;
-
-	switch (mcWindows.action) {
-		case "resize":
-			clamp = mcWindows.clampBoxSize(
-				this.left, this.top,
-				mcWindows.mouseDownWidth + (e.screenX - mcWindows.mouseDownScreenX),
-				mcWindows.mouseDownHeight + (e.screenY - mcWindows.mouseDownScreenY),
-				this.features.minWidth, this.features.minHeight
-			);
-
-			this.resizeTo(clamp[2], clamp[3]);
-
-			mcWindows.cancelEvent(e);
-			break;
-
-		case "move":
-			this.left = mcWindows.mouseDownLayerX + (e.screenX - mcWindows.mouseDownScreenX);
-			this.top = mcWindows.mouseDownLayerY + (e.screenY - mcWindows.mouseDownScreenY);
-			this.updateClamping();
-
-			mcWindows.cancelEvent(e);
-			break;
-	}
-};
-
-TinyMCE_Window.prototype.moveTo = function (x, y) {
-	this.left = x;
-	this.top = y;
-
-	this.winElement.style.left = this.left + "px";
-	this.winElement.style.top = this.top + "px";
-};
-
-TinyMCE_Window.prototype.resizeTo = function (width, height) {
-	this.wrapperIFrameElement.style.width = (width+2) + 'px';
-	this.wrapperIFrameElement.style.height = (height+2) + 'px';
-	this.wrapperIFrameElement.width = width+2;
-	this.wrapperIFrameElement.height = height+2;
-	this.winElement.style.width = width + 'px';
-	this.winElement.style.height = height + 'px';
-
-	height = height - this.deltaHeight;
-
-	this.containerElement.style.width = width + 'px';
-	this.iframeElement.style.width = width + 'px';
-	this.iframeElement.style.height = height + 'px';
-	this.bodyElement.style.width = width + 'px';
-	this.bodyElement.style.height = height + 'px';
-	this.headElement.style.width = width + 'px';
-	//this.statusElement.style.width = width + 'px';
-};
-
-TinyMCE_Window.prototype.updateClamping = function () {
-	var clamp, oversize;
-
-	clamp = mcWindows.clampBoxPosition(
-		this.left, this.top,
-		this.winElement.scrollWidth,
-		this.winElement.scrollHeight,
-		this.features.minWidth, this.features.minHeight
-	);
-	oversize = (
-		clamp[2] != this.winElement.scrollWidth ||
-		clamp[3] != this.winElement.scrollHeight
-	) ? true : false;
-
-	this.moveTo(clamp[0], clamp[1]);
-	if (this.features.resizable == "yes" && oversize)
-		this.resizeTo(clamp[2], clamp[3]);
-};
-
-function debug(msg) {
-	document.getElementById('debug').value += msg + "\n";
-}
-
-TinyMCE_Window.prototype.onMouseUp = function(e) {
-	mcWindows.action = "none";
-};
-
-TinyMCE_Window.prototype.onFocus = function(e) {
-	// Gecko only handler
-	var winRef = e.currentTarget;
-
-	for (var n in mcWindows.windows) {
-		var win = mcWindows.windows[n];
-		if (typeof(win) == 'function')
-			continue;
-
-		if (winRef.name == win.id + "_iframe") {
-			win.focus();
-			return;
-		}
-	}
-};
-
-TinyMCE_Window.prototype.onMouseDown = function(e) {
-	var elm = mcWindows.isMSIE ? this.wrapperFrame.event.srcElement : e.target;
-
-	mcWindows.mouseDownScreenX = e.screenX;
-	mcWindows.mouseDownScreenY = e.screenY;
-	mcWindows.mouseDownLayerX = this.left;
-	mcWindows.mouseDownLayerY = this.top;
-	mcWindows.mouseDownWidth = parseInt(this.winElement.style.width);
-	mcWindows.mouseDownHeight = parseInt(this.winElement.style.height);
-
-	if (this.resizeElement != null && elm == this.resizeElement.firstChild)
-		this.startResize(e);
-	else
-		this.startMove(e);
-
-	mcWindows.cancelEvent(e);
-};
-
-// Global instance
-var mcWindows = new TinyMCE_Windows();
-
-// Initialize windows
-mcWindows.init({
-	images_path : tinyMCE.baseURL + "/plugins/inlinepopups/images",
-	css_file : tinyMCE.baseURL + "/plugins/inlinepopups/css/inlinepopup.css"
-});
+/**
+ * $Id: editor_plugin_src.js 520 2008-01-07 16:30:32Z spocke $
+ *
+ * @author Moxiecode
+ * @copyright Copyright © 2004-2008, Moxiecode Systems AB, All rights reserved.
+ */
+
+(function() {
+	var DOM = tinymce.DOM, Element = tinymce.dom.Element, Event = tinymce.dom.Event, each = tinymce.each, is = tinymce.is;
+
+	tinymce.create('tinymce.plugins.InlinePopups', {
+		init : function(ed, url) {
+			// Replace window manager
+			ed.onBeforeRenderUI.add(function() {
+				ed.windowManager = new tinymce.InlineWindowManager(ed);
+				DOM.loadCSS(url + '/skins/' + (ed.settings.inlinepopups_skin || 'clearlooks2') + "/window.css");
+			});
+		},
+
+		getInfo : function() {
+			return {
+				longname : 'InlinePopups',
+				author : 'Moxiecode Systems AB',
+				authorurl : 'http://tinymce.moxiecode.com',
+				infourl : 'http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/inlinepopups',
+				version : tinymce.majorVersion + "." + tinymce.minorVersion
+			};
+		}
+	});
+
+	tinymce.create('tinymce.InlineWindowManager:tinymce.WindowManager', {
+		InlineWindowManager : function(ed) {
+			var t = this;
+
+			t.parent(ed);
+			t.zIndex = 1000;
+		},
+
+		open : function(f, p) {
+			var t = this, id, opt = '', ed = t.editor, dw = 0, dh = 0, vp, po, mdf, clf, we, w;
+
+			f = f || {};
+			p = p || {};
+
+			// Run native windows
+			if (!f.inline)
+				return t.parent(f, p);
+
+			t.bookmark = ed.selection.getBookmark('simple');
+			id = DOM.uniqueId();
+			vp = DOM.getViewPort();
+			f.width = parseInt(f.width || 320);
+			f.height = parseInt(f.height || 240) + (tinymce.isIE ? 8 : 0);
+			f.min_width = parseInt(f.min_width || 150);
+			f.min_height = parseInt(f.min_height || 100);
+			f.max_width = parseInt(f.max_width || 2000);
+			f.max_height = parseInt(f.max_height || 2000);
+			f.left = f.left || Math.round(Math.max(vp.x, vp.x + (vp.w / 2.0) - (f.width / 2.0)));
+			f.top = f.top || Math.round(Math.max(vp.y, vp.y + (vp.h / 2.0) - (f.height / 2.0)));
+			f.movable = f.resizable = true;
+			p.mce_width = f.width;
+			p.mce_height = f.height;
+			p.mce_inline = true;
+			p.mce_window_id = id;
+
+			// Transpose
+//			po = DOM.getPos(ed.getContainer());
+//			f.left -= po.x;
+//			f.top -= po.y;
+
+			t.features = f;
+			t.params = p;
+			t.onOpen.dispatch(t, f, p);
+
+			if (f.type) {
+				opt += ' modal ' + f.type;
+				f.resizable = false;
+			}
+
+			if (f.statusbar)
+				opt += ' statusbar';
+
+			if (f.resizable)
+				opt += ' resizable';
+
+			if (f.minimizable)
+				opt += ' minimizable';
+
+			if (f.maximizable)
+				opt += ' maximizable';
+
+			if (f.movable)
+				opt += ' movable';
+
+			// Create DOM objects
+			t._addAll(document.body, 
+				['div', {id : id, 'class' : ed.settings.inlinepopups_skin || 'clearlooks2', style : 'width:100px;height:100px'}, 
+					['div', {id : id + '_wrapper', 'class' : 'wrapper' + opt},
+						['div', {id : id + '_top', 'class' : 'top'}, 
+							['div', {'class' : 'left'}],
+							['div', {'class' : 'center'}],
+							['div', {'class' : 'right'}],
+							['span', {id : id + '_title'}, f.title || '']
+						],
+
+						['div', {id : id + '_middle', 'class' : 'middle'}, 
+							['div', {id : id + '_left', 'class' : 'left'}],
+							['span', {id : id + '_content'}],
+							['div', {id : id + '_right', 'class' : 'right'}]
+						],
+
+						['div', {id : id + '_bottom', 'class' : 'bottom'},
+							['div', {'class' : 'left'}],
+							['div', {'class' : 'center'}],
+							['div', {'class' : 'right'}],
+							['span', {id : id + '_status'}, 'Content']
+						],
+
+						['a', {'class' : 'move', href : 'javascript:;'}],
+						['a', {'class' : 'min', href : 'javascript:;', onmousedown : 'return false;'}],
+						['a', {'class' : 'max', href : 'javascript:;', onmousedown : 'return false;'}],
+						['a', {'class' : 'med', href : 'javascript:;', onmousedown : 'return false;'}],
+						['a', {'class' : 'close', href : 'javascript:;', onmousedown : 'return false;'}],
+						['a', {id : id + '_resize_n', 'class' : 'resize resize-n', href : 'javascript:;'}],
+						['a', {id : id + '_resize_s', 'class' : 'resize resize-s', href : 'javascript:;'}],
+						['a', {id : id + '_resize_w', 'class' : 'resize resize-w', href : 'javascript:;'}],
+						['a', {id : id + '_resize_e', 'class' : 'resize resize-e', href : 'javascript:;'}],
+						['a', {id : id + '_resize_nw', 'class' : 'resize resize-nw', href : 'javascript:;'}],
+						['a', {id : id + '_resize_ne', 'class' : 'resize resize-ne', href : 'javascript:;'}],
+						['a', {id : id + '_resize_sw', 'class' : 'resize resize-sw', href : 'javascript:;'}],
+						['a', {id : id + '_resize_se', 'class' : 'resize resize-se', href : 'javascript:;'}]
+					]
+				]
+			);
+
+			DOM.setStyles(id, {top : -10000, left : -10000});
+
+			// Fix gecko rendering bug, where the editors iframe messed with window contents
+			if (tinymce.isGecko)
+				DOM.setStyle(id, 'overflow', 'auto');
+
+			// Measure borders
+			if (!f.type) {
+				dw += DOM.get(id + '_left').clientWidth;
+				dw += DOM.get(id + '_right').clientWidth;
+				dh += DOM.get(id + '_top').clientHeight;
+				dh += DOM.get(id + '_bottom').clientHeight;
+			}
+
+			// Resize window
+			DOM.setStyles(id, {top : f.top, left : f.left, width : f.width + dw, height : f.height + dh});
+
+			if (!f.type) {
+				DOM.add(id + '_content', 'iframe', {id : id + '_ifr', src : 'javascript:""', frameBorder : 0, style : 'border:0;width:10px;height:10px'});
+				DOM.setStyles(id + '_ifr', {width : f.width, height : f.height});
+				DOM.setAttrib(id + '_ifr', 'src', f.url || f.file);
+			} else {
+				DOM.add(id + '_wrapper', 'a', {id : id + '_ok', 'class' : 'button ok', href : 'javascript:;', onmousedown : 'return false;'}, 'Ok');
+
+				if (f.type == 'confirm')
+					DOM.add(id + '_wrapper', 'a', {'class' : 'button cancel', href : 'javascript:;', onmousedown : 'return false;'}, 'Cancel');
+
+				DOM.add(id + '_middle', 'div', {'class' : 'icon'});
+				DOM.setHTML(id + '_content', f.content.replace('\n', '<br />'));
+			}
+
+			// Register events
+			mdf = Event.add(id, 'mousedown', function(e) {
+				var n = e.target, w, vp;
+
+				w = t.windows[id];
+				t.focus(id);
+
+				if (n.nodeName == 'A' || n.nodeName == 'a') {
+					if (n.className == 'max') {
+						w.oldPos = w.element.getXY();
+						w.oldSize = w.element.getSize();
+
+						vp = DOM.getViewPort();
+
+						// Reduce viewport size to avoid scrollbars
+						vp.w -= 2;
+						vp.h -= 2;
+
+						w.element.moveTo(vp.x, vp.y);
+						w.element.resizeTo(vp.w, vp.h);
+						DOM.setStyles(id + '_ifr', {width : vp.w - w.deltaWidth, height : vp.h - w.deltaHeight});
+						DOM.addClass(id + '_wrapper', 'maximized');
+					} else if (n.className == 'med') {
+						// Reset to old size
+						w.element.moveTo(w.oldPos.x, w.oldPos.y);
+						w.element.resizeTo(w.oldSize.w, w.oldSize.h);
+						w.iframeElement.resizeTo(w.oldSize.w - w.deltaWidth, w.oldSize.h - w.deltaHeight);
+
+						DOM.removeClass(id + '_wrapper', 'maximized');
+					} else if (n.className == 'move')
+						return t._startDrag(id, e, n.className);
+					else if (DOM.hasClass(n, 'resize'))
+						return t._startDrag(id, e, n.className.substring(7));
+				}
+			});
+
+			clf = Event.add(id, 'click', function(e) {
+				var n = e.target;
+
+				t.focus(id);
+
+				if (n.nodeName == 'A' || n.nodeName == 'a') {
+					switch (n.className) {
+						case 'close':
+							t.close(null, id);
+							return Event.cancel(e);
+
+						case 'button ok':
+						case 'button cancel':
+							f.button_func(n.className == 'button ok');
+							return Event.cancel(e);
+					}
+				}
+			});
+
+			// Add window
+			t.windows = t.windows || {};
+			w = t.windows[id] = {
+				id : id,
+				mousedown_func : mdf,
+				click_func : clf,
+				element : new Element(id, {blocker : 1, container : ed.getContainer()}),
+				iframeElement : new Element(id + '_ifr'),
+				features : f,
+				deltaWidth : dw,
+				deltaHeight : dh
+			};
+
+			w.iframeElement.on('focus', function() {
+				t.focus(id);
+			});
+
+			t.focus(id);
+			t._fixIELayout(id, 1);
+
+//			if (DOM.get(id + '_ok'))
+//				DOM.get(id + '_ok').focus();
+
+			return w;
+		},
+
+		focus : function(id) {
+			var t = this, w = t.windows[id];
+
+			w.zIndex = this.zIndex++;
+			w.element.setStyle('zIndex', w.zIndex);
+			w.element.update();
+
+			id = id + '_wrapper';
+			DOM.removeClass(t.lastId, 'focus');
+			DOM.addClass(id, 'focus');
+			t.lastId = id;
+		},
+
+		_addAll : function(te, ne) {
+			var i, n, t = this, dom = tinymce.DOM;
+
+			if (is(ne, 'string'))
+				te.appendChild(dom.doc.createTextNode(ne));
+			else if (ne.length) {
+				te = te.appendChild(dom.create(ne[0], ne[1]));
+
+				for (i=2; i<ne.length; i++)
+					t._addAll(te, ne[i]);
+			}
+		},
+
+		_startDrag : function(id, se, ac) {
+			var t = this, mu, mm, d = document, eb, w = t.windows[id], we = w.element, sp = we.getXY(), p, sz, ph, cp, vp, sx, sy, sex, sey, dx, dy, dw, dh;
+
+			// Get positons and sizes
+//			cp = DOM.getPos(t.editor.getContainer());
+			cp = {x : 0, y : 0};
+			vp = DOM.getViewPort();
+
+			// Reduce viewport size to avoid scrollbars
+			vp.w -= 2;
+			vp.h -= 2;
+
+			sex = se.screenX;
+			sey = se.screenY;
+			dx = dy = dw = dh = 0;
+
+			// Handle mouse up
+			mu = Event.add(d, 'mouseup', function(e) {
+				Event.remove(d, 'mouseup', mu);
+				Event.remove(d, 'mousemove', mm);
+
+				if (eb)
+					eb.remove();
+
+				we.moveBy(dx, dy);
+				we.resizeBy(dw, dh);
+				sz = we.getSize();
+				DOM.setStyles(id + '_ifr', {width : sz.w - w.deltaWidth, height : sz.h - w.deltaHeight});
+				t._fixIELayout(id, 1);
+
+				return Event.cancel(e);
+			});
+
+			if (ac != 'move')
+				startMove();
+
+			function startMove() {
+				if (eb)
+					return;
+
+				t._fixIELayout(id, 0);
+
+				// Setup event blocker
+				DOM.add(d.body, 'div', {
+					id : 'mceEventBlocker',
+					'class' : 'mceEventBlocker ' + (t.editor.settings.inlinepopups_skin || 'clearlooks2'),
+					style : {left : vp.x, top : vp.y, width : vp.w - 20, height : vp.h - 20, zIndex : 20001}
+				});
+				eb = new Element('mceEventBlocker');
+				eb.update();
+
+				// Setup placeholder
+				p = we.getXY();
+				sz = we.getSize();
+				sx = cp.x + p.x - vp.x;
+				sy = cp.y + p.y - vp.y;
+				DOM.add(eb.get(), 'div', {id : 'mcePlaceHolder', 'class' : 'placeholder', style : {left : sx, top : sy, width : sz.w, height : sz.h}});
+				ph = new Element('mcePlaceHolder');
+			};
+
+			// Handle mouse move/drag
+			mm = Event.add(d, 'mousemove', function(e) {
+				var x, y, v;
+
+				startMove();
+
+				x = e.screenX - sex;
+				y = e.screenY - sey;
+
+				switch (ac) {
+					case 'resize-w':
+						dx = x;
+						dw = 0 - x;
+						break;
+
+					case 'resize-e':
+						dw = x;
+						break;
+
+					case 'resize-n':
+					case 'resize-nw':
+					case 'resize-ne':
+						if (ac == "resize-nw") {
+							dx = x;
+							dw = 0 - x;
+						} else if (ac == "resize-ne")
+							dw = x;
+
+						dy = y;
+						dh = 0 - y;
+						break;
+
+					case 'resize-s':
+					case 'resize-sw':
+					case 'resize-se':
+						if (ac == "resize-sw") {
+							dx = x;
+							dw = 0 - x;
+						} else if (ac == "resize-se")
+							dw = x;
+
+						dh = y;
+						break;
+
+					case 'move':
+						dx = x;
+						dy = y;
+						break;
+				}
+
+				// Boundary check
+				if (dw < (v = w.features.min_width - sz.w)) {
+					if (dx !== 0)
+						dx += dw - v;
+
+					dw = v;
+				}
+	
+				if (dh < (v = w.features.min_height - sz.h)) {
+					if (dy !== 0)
+						dy += dh - v;
+
+					dh = v;
+				}
+
+				dw = Math.min(dw, w.features.max_width - sz.w);
+				dh = Math.min(dh, w.features.max_height - sz.h);
+				dx = Math.max(dx, vp.x - (sx + vp.x));
+				dy = Math.max(dy, vp.y - (sy + vp.y));
+				dx = Math.min(dx, (vp.w + vp.x) - (sx + sz.w + vp.x));
+				dy = Math.min(dy, (vp.h + vp.y) - (sy + sz.h + vp.y));
+
+				// Move if needed
+				if (dx + dy !== 0) {
+					if (sx + dx < 0)
+						dx = 0;
+	
+					if (sy + dy < 0)
+						dy = 0;
+
+					ph.moveTo(sx + dx, sy + dy);
+				}
+
+				// Resize if needed
+				if (dw + dh !== 0)
+					ph.resizeTo(sz.w + dw, sz.h + dh);
+
+				return Event.cancel(e);
+			});
+
+			return Event.cancel(se);
+		},
+
+		resizeBy : function(dw, dh, id) {
+			var w = this.windows[id];
+
+			if (w) {
+				w.element.resizeBy(dw, dh);
+				w.iframeElement.resizeBy(dw, dh);
+			}
+		},
+
+		close : function(win, id) {
+			var t = this, w, d = document, ix = 0, fw;
+
+			// Probably not inline
+			if (!id && win) {
+				t.parent(win);
+				return;
+			}
+
+			if (w = t.windows[id]) {
+				t.onClose.dispatch(t);
+				Event.remove(d, 'mousedown', w.mousedownFunc);
+				Event.remove(d, 'click', w.clickFunc);
+
+				DOM.setAttrib(id + '_ifr', 'src', 'javascript:""'); // Prevent leak
+				w.element.remove();
+				delete t.windows[id];
+
+				// Find front most window and focus that
+				each (t.windows, function(w) {
+					if (w.zIndex > ix) {
+						fw = w;
+						ix = w.zIndex;
+					}
+				});
+
+				if (fw)
+					t.focus(fw.id);
+			}
+		},
+
+		setTitle : function(ti, id) {
+			DOM.get(id + '_title').innerHTML = DOM.encode(ti);
+		},
+
+		alert : function(txt, cb, s) {
+			var t = this, w;
+
+			w = t.open({
+				title : t,
+				type : 'alert',
+				button_func : function(s) {
+					if (cb)
+						cb.call(s || t, s);
+
+					t.close(null, w.id);
+				},
+				content : DOM.encode(t.editor.getLang(txt, txt)),
+				inline : 1,
+				width : 400,
+				height : 130
+			});
+		},
+
+		confirm : function(txt, cb, s) {
+			var t = this, w;
+
+			w = t.open({
+				title : t,
+				type : 'confirm',
+				button_func : function(s) {
+					if (cb)
+						cb.call(s || t, s);
+
+					t.close(null, w.id);
+				},
+				content : DOM.encode(t.editor.getLang(txt, txt)),
+				inline : 1,
+				width : 400,
+				height : 130
+			});
+		},
+
+		// Internal functions
+
+		_fixIELayout : function(id, s) {
+			var w, img;
+
+			if (!tinymce.isIE6)
+				return;
+
+			// Fixes the bug where hover flickers and does odd things in IE6
+			each(['n','s','w','e','nw','ne','sw','se'], function(v) {
+				var e = DOM.get(id + '_resize_' + v);
+
+				DOM.setStyles(e, {
+					width : s ? e.clientWidth : '',
+					height : s ? e.clientHeight : '',
+					cursor : DOM.getStyle(e, 'cursor', 1)
+				});
+
+				DOM.setStyle(id + "_bottom", 'bottom', '-1px');
+
+				e = 0;
+			});
+
+			// Fixes graphics glitch
+			if (w = this.windows[id]) {
+				// Fixes rendering bug after resize
+				w.element.hide();
+				w.element.show();
+
+				// Forced a repaint of the window
+				//DOM.get(id).style.filter = '';
+
+				// IE has a bug where images used in CSS won't get loaded
+				// sometimes when the cache in the browser is disabled
+				// This fix tries to solve it by loading the images using the image object
+				each(DOM.select('div,a', id), function(e, i) {
+					if (e.currentStyle.backgroundImage != 'none') {
+						img = new Image();
+						img.src = e.currentStyle.backgroundImage.replace(/url\(\"(.+)\"\)/, '$1');
+					}
+				});
+
+				DOM.get(id).style.filter = '';
+			}
+		}
+	});
+
+	// Register plugin
+	tinymce.PluginManager.add('inlinepopups', tinymce.plugins.InlinePopups);
+})();
+
Binary file includes/clientside/tinymce/plugins/inlinepopups/images/spacer.gif has changed
Binary file includes/clientside/tinymce/plugins/inlinepopups/images/window_close.gif has changed
Binary file includes/clientside/tinymce/plugins/inlinepopups/images/window_maximize.gif has changed
Binary file includes/clientside/tinymce/plugins/inlinepopups/images/window_minimize.gif has changed
Binary file includes/clientside/tinymce/plugins/inlinepopups/images/window_resize.gif has changed
--- a/includes/clientside/tinymce/plugins/inlinepopups/jscripts/mcwindows.js	Fri Feb 22 12:46:51 2008 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,453 +0,0 @@
-/**
- * $Id: mcwindows.js 18 2006-06-29 14:11:23Z spocke $
- *
- * Moxiecode DHTML Windows script.
- *
- * @author Moxiecode
- * @copyright Copyright © 2004, Moxiecode Systems AB, All rights reserved.
- */
-
-// Windows handler
-function MCWindows() {
-	this.settings = new Array();
-	this.windows = new Array();
-	this.isMSIE = (navigator.appName == "Microsoft Internet Explorer");
-	this.isGecko = navigator.userAgent.indexOf('Gecko') != -1;
-	this.isSafari = navigator.userAgent.indexOf('Safari') != -1;
-	this.isMac = navigator.userAgent.indexOf('Mac') != -1;
-	this.isMSIE5_0 = this.isMSIE && (navigator.userAgent.indexOf('MSIE 5.0') != -1);
-	this.action = "none";
-	this.selectedWindow = null;
-	this.zindex = 100;
-	this.mouseDownScreenX = 0;
-	this.mouseDownScreenY = 0;
-	this.mouseDownLayerX = 0;
-	this.mouseDownLayerY = 0;
-	this.mouseDownWidth = 0;
-	this.mouseDownHeight = 0;
-};
-
-MCWindows.prototype.init = function(settings) {
-	this.settings = settings;
-
-	if (this.isMSIE)
-		this.addEvent(document, "mousemove", mcWindows.eventDispatcher);
-	else
-		this.addEvent(window, "mousemove", mcWindows.eventDispatcher);
-
-	this.addEvent(document, "mouseup", mcWindows.eventDispatcher);
-};
-
-MCWindows.prototype.getParam = function(name, default_value) {
-	var value = null;
-
-	value = (typeof(this.settings[name]) == "undefined") ? default_value : this.settings[name];
-
-	// Fix bool values
-	if (value == "true" || value == "false")
-		return (value == "true");
-
-	return value;
-};
-
-MCWindows.prototype.eventDispatcher = function(e) {
-	e = typeof(e) == "undefined" ? window.event : e;
-
-	if (mcWindows.selectedWindow == null)
-		return;
-
-	// Switch focus
-	if (mcWindows.isGecko && e.type == "mousedown") {
-		var elm = e.currentTarget;
-
-		for (var n in mcWindows.windows) {
-			var win = mcWindows.windows[n];
-			if (typeof(win) == 'function')
-				continue;
-
-			if (win.headElement == elm || win.resizeElement == elm) {
-				win.focus();
-				break;
-			}
-		}
-	}
-
-	switch (e.type) {
-		case "mousemove":
-			mcWindows.selectedWindow.onMouseMove(e);
-			break;
-
-		case "mouseup":
-			mcWindows.selectedWindow.onMouseUp(e);
-			break;
-
-		case "mousedown":
-			mcWindows.selectedWindow.onMouseDown(e);
-			break;
-
-		case "focus":
-			mcWindows.selectedWindow.onFocus(e);
-			break;
-	}
-}
-
-MCWindows.prototype.addEvent = function(obj, name, handler) {
-	if (this.isMSIE)
-		obj.attachEvent("on" + name, handler);
-	else
-		obj.addEventListener(name, handler, true);
-};
-
-MCWindows.prototype.cancelEvent = function(e) {
-	if (this.isMSIE) {
-		e.returnValue = false;
-		e.cancelBubble = true;
-	} else
-		e.preventDefault();
-};
-
-MCWindows.prototype.parseFeatures = function(opts) {
-	// Cleanup the options
-	opts = opts.toLowerCase();
-	opts = opts.replace(/;/g, ",");
-	opts = opts.replace(/[^0-9a-z=,]/g, "");
-
-	var optionChunks = opts.split(',');
-	var options = new Array();
-
-	options['left'] = 10;
-	options['top'] = 10;
-	options['width'] = 300;
-	options['height'] = 300;
-	options['resizable'] = true;
-	options['minimizable'] = true;
-	options['maximizable'] = true;
-	options['close'] = true;
-	options['movable'] = true;
-
-	if (opts == "")
-		return options;
-
-	for (var i=0; i<optionChunks.length; i++) {
-		var parts = optionChunks[i].split('=');
-
-		if (parts.length == 2)
-			options[parts[0]] = parts[1];
-	}
-
-	return options;
-};
-
-MCWindows.prototype.open = function(url, name, features) {
-	var win = new MCWindow();
-	var winDiv, html = "", id;
-
-	features = this.parseFeatures(features);
-
-	// Create div
-	id = "mcWindow_" + name;
-
-	width = parseInt(features['width']);
-	height = parseInt(features['height'])-12-19;
-
-	if (this.isMSIE)
-		width -= 2;
-
-	// Setup first part of window
-	win.id = id;
-	win.url = url;
-	win.name = name;
-	win.features = features;
-	this.windows[name] = win;
-
-	iframeWidth = width;
-	iframeHeight = height;
-
-	// Create inner content
-	html += '<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">';
-	html += '<html>';
-	html += '<head>';
-	html += '<title>Wrapper iframe</title>';
-	html += '<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">';
-	html += '<link href="../jscripts/tiny_mce/themes/advanced/css/editor_ui.css" rel="stylesheet" type="text/css" />';
-	html += '</head>';
-	html += '<body onload="parent.mcWindows.onLoad(\'' + name + '\');">';
-
-	html += '<div id="' + id + '_container" class="mceWindow">';
-	html += '<div id="' + id + '_head" class="mceWindowHead" onmousedown="parent.mcWindows.windows[\'' + name + '\'].focus();">';
-	html += '  <div id="' + id + '_title" class="mceWindowTitle"';
-	html += '  onselectstart="return false;" unselectable="on" style="-moz-user-select: none !important;">No name window</div>';
-	html += '    <div class="mceWindowHeadTools">';
-	html += '      <a href="javascript:parent.mcWindows.windows[\'' + name + '\'].close();" onmousedown="return false;" class="mceWindowClose"><img border="0" src="../jscripts/tiny_mce/themes/advanced/images/window_close.gif" /></a>';
-//	html += '      <a href="javascript:mcWindows.windows[\'' + name + '\'].maximize();" onmousedown="return false;" class="mceWindowMaximize"></a>';
-//	html += '      <a href="javascript:mcWindows.windows[\'' + name + '\'].minimize();" onmousedown="return false;" class="mceWindowMinimize"></a>';
-	html += '    </div>';
-	html += '</div><div id="' + id + '_body" class="mceWindowBody" style="width: ' + width + 'px; height: ' + height + 'px;">';
-	html += '<iframe id="' + id + '_iframe" name="' + id + '_iframe" onfocus="parent.mcWindows.windows[\'' + name + '\'].focus();" frameborder="0" width="' + iframeWidth + '" height="' + iframeHeight + '" src="' + url + '" class="mceWindowBodyIframe"></iframe></div>';
-	html += '<div id="' + id + '_statusbar" class="mceWindowStatusbar" onmousedown="parent.mcWindows.windows[\'' + name + '\'].focus();">';
-	html += '<div id="' + id + '_resize" class="mceWindowResize"><img onmousedown="parent.mcWindows.windows[\'' + name + '\'].focus();" border="0" src="../jscripts/tiny_mce/themes/advanced/images/window_resize.gif" /></div>';
-	html += '</div>';
-	html += '</div>';
-
-	html += '</body>';
-	html += '</html>';
-
-	// Create iframe
-	this.createFloatingIFrame(id, features['left'], features['top'], features['width'], features['height'], html);
-};
-
-// Gets called when wrapper iframe is initialized
-MCWindows.prototype.onLoad = function(name) {
-	var win = mcWindows.windows[name];
-	var id = "mcWindow_" + name;
-	var wrapperIframe = window.frames[id + "_iframe"].frames[0];
-	var wrapperDoc = window.frames[id + "_iframe"].document;
-	var doc = window.frames[id + "_iframe"].document;
-	var winDiv = document.getElementById("mcWindow_" + name + "_div");
-	var realIframe = window.frames[id + "_iframe"].frames[0];
-
-	// Set window data
-	win.id = "mcWindow_" + name + "_iframe";
-	win.winElement = winDiv;
-	win.bodyElement = doc.getElementById(id + '_body');
-	win.iframeElement = doc.getElementById(id + '_iframe');
-	win.headElement = doc.getElementById(id + '_head');
-	win.titleElement = doc.getElementById(id + '_title');
-	win.resizeElement = doc.getElementById(id + '_resize');
-	win.containerElement = doc.getElementById(id + '_container');
-	win.left = win.features['left'];
-	win.top = win.features['top'];
-	win.frame = window.frames[id + '_iframe'].frames[0];
-	win.wrapperFrame = window.frames[id + '_iframe'];
-	win.wrapperIFrameElement = document.getElementById(id + "_iframe");
-
-	// Add event handlers
-	mcWindows.addEvent(win.headElement, "mousedown", mcWindows.eventDispatcher);
-	mcWindows.addEvent(win.resizeElement, "mousedown", mcWindows.eventDispatcher);
-
-	if (mcWindows.isMSIE) {
-		mcWindows.addEvent(realIframe.document, "mousemove", mcWindows.eventDispatcher);
-		mcWindows.addEvent(realIframe.document, "mouseup", mcWindows.eventDispatcher);
-	} else {
-		mcWindows.addEvent(realIframe, "mousemove", mcWindows.eventDispatcher);
-		mcWindows.addEvent(realIframe, "mouseup", mcWindows.eventDispatcher);
-		mcWindows.addEvent(realIframe, "focus", mcWindows.eventDispatcher);
-	}
-
-	for (var i=0; i<window.frames.length; i++) {
-		if (!window.frames[i]._hasMouseHandlers) {
-			if (mcWindows.isMSIE) {
-				mcWindows.addEvent(window.frames[i].document, "mousemove", mcWindows.eventDispatcher);
-				mcWindows.addEvent(window.frames[i].document, "mouseup", mcWindows.eventDispatcher);
-			} else {
-				mcWindows.addEvent(window.frames[i], "mousemove", mcWindows.eventDispatcher);
-				mcWindows.addEvent(window.frames[i], "mouseup", mcWindows.eventDispatcher);
-			}
-
-			window.frames[i]._hasMouseHandlers = true;
-		}
-	}
-
-	if (mcWindows.isMSIE) {
-		mcWindows.addEvent(win.frame.document, "mousemove", mcWindows.eventDispatcher);
-		mcWindows.addEvent(win.frame.document, "mouseup", mcWindows.eventDispatcher);
-	} else {
-		mcWindows.addEvent(win.frame, "mousemove", mcWindows.eventDispatcher);
-		mcWindows.addEvent(win.frame, "mouseup", mcWindows.eventDispatcher);
-		mcWindows.addEvent(win.frame, "focus", mcWindows.eventDispatcher);
-	}
-
-	this.selectedWindow = win;
-};
-
-MCWindows.prototype.createFloatingIFrame = function(id_prefix, left, top, width, height, html) {
-	var iframe = document.createElement("iframe");
-	var div = document.createElement("div");
-
-	width = parseInt(width);
-	height = parseInt(height)+1;
-
-	// Create wrapper div
-	div.setAttribute("id", id_prefix + "_div");
-	div.setAttribute("width", width);
-	div.setAttribute("height", (height));
-	div.style.position = "absolute";
-	div.style.left = left + "px";
-	div.style.top = top + "px";
-	div.style.width = width + "px";
-	div.style.height = (height) + "px";
-	div.style.backgroundColor = "white";
-	div.style.display = "none";
-
-	if (this.isGecko) {
-		iframeWidth = width + 2;
-		iframeHeight = height + 2;
-	} else {
-		iframeWidth = width;
-		iframeHeight = height + 1;
-	}
-
-	// Create iframe
-	iframe.setAttribute("id", id_prefix + "_iframe");
-	iframe.setAttribute("name", id_prefix + "_iframe");
-	iframe.setAttribute("border", "0");
-	iframe.setAttribute("frameBorder", "0");
-	iframe.setAttribute("marginWidth", "0");
-	iframe.setAttribute("marginHeight", "0");
-	iframe.setAttribute("leftMargin", "0");
-	iframe.setAttribute("topMargin", "0");
-	iframe.setAttribute("width", iframeWidth);
-	iframe.setAttribute("height", iframeHeight);
-//	iframe.setAttribute("src", "../jscripts/tiny_mce/blank.htm");
-	// iframe.setAttribute("allowtransparency", "false");
-	iframe.setAttribute("scrolling", "no");
-	iframe.style.width = iframeWidth + "px";
-	iframe.style.height = iframeHeight + "px";
-	iframe.style.backgroundColor = "white";
-	div.appendChild(iframe);
-
-	document.body.appendChild(div);
-
-	// Fixed MSIE 5.0 issue
-	div.innerHTML = div.innerHTML;
-
-	if (this.isSafari) {
-		// Give Safari some time to setup
-		window.setTimeout(function() {
-			doc = window.frames[id_prefix + '_iframe'].document;
-			doc.open();
-			doc.write(html);
-			doc.close();
-		}, 10);
-	} else {
-		doc = window.frames[id_prefix + '_iframe'].window.document
-		doc.open();
-		doc.write(html);
-		doc.close();
-	}
-
-	div.style.display = "block";
-
-	return div;
-};
-
-// Window instance
-function MCWindow() {
-};
-
-MCWindow.prototype.focus = function() {
-	this.winElement.style.zIndex = mcWindows.zindex++;
-	mcWindows.selectedWindow = this;
-};
-
-MCWindow.prototype.minimize = function() {
-};
-
-MCWindow.prototype.maximize = function() {
-	
-};
-
-MCWindow.prototype.startResize = function() {
-	mcWindows.action = "resize";
-};
-
-MCWindow.prototype.startMove = function(e) {
-	mcWindows.action = "move";
-};
-
-MCWindow.prototype.close = function() {
-	document.body.removeChild(this.winElement);
-	mcWindows.windows[this.name] = null;
-};
-
-MCWindow.prototype.onMouseMove = function(e) {
-	var scrollX = 0;//this.doc.body.scrollLeft;
-	var scrollY = 0;//this.doc.body.scrollTop;
-
-	// Calculate real X, Y
-	var dx = e.screenX - mcWindows.mouseDownScreenX;
-	var dy = e.screenY - mcWindows.mouseDownScreenY;
-
-	switch (mcWindows.action) {
-		case "resize":
-			width = mcWindows.mouseDownWidth + (e.screenX - mcWindows.mouseDownScreenX);
-			height = mcWindows.mouseDownHeight + (e.screenY - mcWindows.mouseDownScreenY);
-
-			width = width < 100 ? 100 : width;
-			height = height < 100 ? 100 : height;
-
-			this.wrapperIFrameElement.style.width = width+2;
-			this.wrapperIFrameElement.style.height = height+2;
-			this.wrapperIFrameElement.width = width+2;
-			this.wrapperIFrameElement.height = height+2;
-			this.winElement.style.width = width;
-			this.winElement.style.height = height;
-
-			height = height-12-19;
-
-			this.containerElement.style.width = width;
-
-			this.iframeElement.style.width = width;
-			this.iframeElement.style.height = height;
-			this.bodyElement.style.width = width;
-			this.bodyElement.style.height = height;
-			this.headElement.style.width = width;
-			//this.statusElement.style.width = width;
-
-			mcWindows.cancelEvent(e);
-			break;
-
-		case "move":
-			this.left = mcWindows.mouseDownLayerX + (e.screenX - mcWindows.mouseDownScreenX);
-			this.top = mcWindows.mouseDownLayerY + (e.screenY - mcWindows.mouseDownScreenY);
-			this.winElement.style.left = this.left + "px";
-			this.winElement.style.top = this.top + "px";
-
-			mcWindows.cancelEvent(e);
-			break;
-	}
-};
-
-MCWindow.prototype.onMouseUp = function(e) {
-	mcWindows.action = "none";
-};
-
-MCWindow.prototype.onFocus = function(e) {
-	// Gecko only handler
-	var winRef = e.currentTarget;
-
-	for (var n in mcWindows.windows) {
-		var win = mcWindows.windows[n];
-		if (typeof(win) == 'function')
-			continue;
-
-		if (winRef.name == win.id) {
-			win.focus();
-			return;
-		}
-	}
-};
-
-MCWindow.prototype.onMouseDown = function(e) {
-	var elm = mcWindows.isMSIE ? this.wrapperFrame.event.srcElement : e.target;
-
-	var scrollX = 0;//this.doc.body.scrollLeft;
-	var scrollY = 0;//this.doc.body.scrollTop;
-
-	mcWindows.mouseDownScreenX = e.screenX;
-	mcWindows.mouseDownScreenY = e.screenY;
-	mcWindows.mouseDownLayerX = this.left;
-	mcWindows.mouseDownLayerY = this.top;
-	mcWindows.mouseDownWidth = parseInt(this.winElement.style.width);
-	mcWindows.mouseDownHeight = parseInt(this.winElement.style.height);
-
-	if (elm == this.resizeElement.firstChild)
-		this.startResize(e);
-	else
-		this.startMove(e);
-
-	mcWindows.cancelEvent(e);
-};
-
-// Global instance
-var mcWindows = new MCWindows();
Binary file includes/clientside/tinymce/plugins/inlinepopups/skins/clearlooks2/img/alert.gif has changed
Binary file includes/clientside/tinymce/plugins/inlinepopups/skins/clearlooks2/img/button.gif has changed
Binary file includes/clientside/tinymce/plugins/inlinepopups/skins/clearlooks2/img/buttons.gif has changed
Binary file includes/clientside/tinymce/plugins/inlinepopups/skins/clearlooks2/img/confirm.gif has changed
Binary file includes/clientside/tinymce/plugins/inlinepopups/skins/clearlooks2/img/corners.gif has changed
Binary file includes/clientside/tinymce/plugins/inlinepopups/skins/clearlooks2/img/horizontal.gif has changed
Binary file includes/clientside/tinymce/plugins/inlinepopups/skins/clearlooks2/img/vertical.gif has changed
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/includes/clientside/tinymce/plugins/inlinepopups/skins/clearlooks2/window.css	Fri Feb 22 12:51:53 2008 -0500
@@ -0,0 +1,87 @@
+/* Clearlooks 2 */
+
+/* General */
+.clearlooks2 div, .clearlooks2 span, .clearlooks2 a {position:absolute; border:0; padding:0; margin:0; background:transparent; font-family:Arial,Verdana; font-size:11px; color:#000; text-decoration:none; font-weight:normal; width:auto; height:auto; overflow:hidden; display:block}
+.clearlooks2 {position:absolute}
+.clearlooks2 .wrapper {position:static}
+.mceEventBlocker {position:absolute; left:0; top:0; background:url(img/horizontal.gif) no-repeat 0 -75px; width:100%; height:100%}
+.clearlooks2 .placeholder {border:1px solid #000; background:#888; top:0; left:0; opacity:0.5; filter:alpha(opacity=50)}
+
+/* Top */
+.clearlooks2 .top, .clearlooks2 .top div {top:0; width:100%; height:23px}
+.clearlooks2 .top .left {width:6px; background:url(img/corners.gif)}
+.clearlooks2 .top .center {right:6px; width:100%; height:23px; background:url(img/horizontal.gif) 12px 0; clip:rect(auto auto auto 12px)}
+.clearlooks2 .top .right {right:0; width:6px; height:23px; background:url(img/corners.gif) -12px 0}
+.clearlooks2 .top span {width:100%; text-align:center; vertical-align:middle; line-height:23px; font-weight:bold}
+.clearlooks2 .focus .top .left {background:url(img/corners.gif) -6px 0}
+.clearlooks2 .focus .top .center {background:url(img/horizontal.gif) 0 -23px}
+.clearlooks2 .focus .top .right {background:url(img/corners.gif) -18px 0}
+.clearlooks2 .focus .top span {color:#FFF}
+
+/* Middle */
+.clearlooks2 .middle, .clearlooks2 .middle div {top:0}
+.clearlooks2 .middle {width:100%; height:100%; clip:rect(23px auto auto auto)}
+.clearlooks2 .middle .left {left:0; width:5px; height:100%; background:url(img/vertical.gif) -5px 0}
+.clearlooks2 .middle span {top:23px; left:5px; width:100%; height:100%; background:#FFF}
+.clearlooks2 .middle .right {right:0; width:5px; height:100%; background:url(img/vertical.gif)}
+
+/* Bottom */
+.clearlooks2 .bottom, .clearlooks2 .bottom div {height:6px}
+.clearlooks2 .bottom {left:0; bottom:0; width:100%}
+.clearlooks2 .bottom div {top:0}
+.clearlooks2 .bottom .left {left:0; width:5px; background:url(img/corners.gif) -34px -6px}
+.clearlooks2 .bottom .center {left:5px; width:100%; background:url(img/horizontal.gif) 0 -46px}
+.clearlooks2 .bottom .right {right:0; width:5px; background: url(img/corners.gif) -34px 0}
+.clearlooks2 .bottom span {display:none}
+.clearlooks2 .statusbar .bottom, .clearlooks2 .statusbar .bottom div {height:23px}
+.clearlooks2 .statusbar .bottom .left {background:url(img/corners.gif) -29px 0}
+.clearlooks2 .statusbar .bottom .center {background:url(img/horizontal.gif) 0 -52px}
+.clearlooks2 .statusbar .bottom .right {background:url(img/corners.gif) -24px 0}
+.clearlooks2 .statusbar .bottom span {display:block; left:7px; font-family:Arial, Verdana; font-size:11px; line-height:23px}
+
+/* Actions */
+.clearlooks2 a {width:29px; height:16px; top:3px;}
+.clearlooks2 .close {right:6px; background:url(img/buttons.gif) -87px 0}
+.clearlooks2 .min {display:none; right:68px; background:url(img/buttons.gif) 0 0}
+.clearlooks2 .med {display:none; right:37px; background:url(img/buttons.gif) -29px 0}
+.clearlooks2 .max {display:none; right:37px; background:url(img/buttons.gif) -58px 0}
+.clearlooks2 .move {display:none;width:100%;cursor:move;background:url(img/corners.gif) no-repeat -100px -100px}
+.clearlooks2 .movable .move {display:block}
+.clearlooks2 .focus .close {right:6px; background:url(img/buttons.gif) -87px -16px}
+.clearlooks2 .focus .min {right:68px; background:url(img/buttons.gif) 0 -16px}
+.clearlooks2 .focus .med {right:37px; background:url(img/buttons.gif) -29px -16px}
+.clearlooks2 .focus .max {right:37px; background:url(img/buttons.gif) -58px -16px}
+.clearlooks2 .focus .close:hover {right:6px; background:url(img/buttons.gif) -87px -32px}
+.clearlooks2 .focus .close:hover {right:6px; background:url(img/buttons.gif) -87px -32px}
+.clearlooks2 .focus .min:hover {right:68px; background:url(img/buttons.gif) 0 -32px}
+.clearlooks2 .focus .med:hover {right:37px; background:url(img/buttons.gif) -29px -32px}
+.clearlooks2 .focus .max:hover {right:37px; background:url(img/buttons.gif) -58px -32px}
+
+/* Resize */
+.clearlooks2 .resize {top:auto; left:auto; display:none; width:5px; height:5px; background:url(img/horizontal.gif) no-repeat 0 -75px}
+.clearlooks2 .resizable .resize {display:block}
+.clearlooks2 .resizable .min, .clearlooks2 .max {display:none}
+.clearlooks2 .minimizable .min {display:block}
+.clearlooks2 .maximizable .max {display:block}
+.clearlooks2 .maximized .med {display:block}
+.clearlooks2 .maximized .max {display:none}
+.clearlooks2 a.resize-n {top:0; left:0; width:100%; cursor:n-resize}
+.clearlooks2 a.resize-nw {top:0; left:0; cursor:nw-resize}
+.clearlooks2 a.resize-ne {top:0; right:0; cursor:ne-resize}
+.clearlooks2 a.resize-w {top:0; left:0; height:100%; cursor:w-resize;}
+.clearlooks2 a.resize-e {top:0; right:0; height:100%; cursor:e-resize}
+.clearlooks2 a.resize-s {bottom:0; left:0; width:100%; cursor:s-resize}
+.clearlooks2 a.resize-sw {bottom:0; left:0; cursor:sw-resize}
+.clearlooks2 a.resize-se {bottom:0; right:0; cursor:se-resize}
+
+/* Alert/Confirm */
+.clearlooks2 .button {font-weight:bold; bottom:10px; width:80px; height:30px; background:url(img/button.gif); line-height:30px; vertical-align:middle; text-align:center; outline:0}
+.clearlooks2 .middle .icon {left:15px; top:35px; width:32px; height:32px}
+.clearlooks2 .alert .middle span, .clearlooks2 .confirm .middle span {background:transparent;left:60px; top:35px; width:320px; height:50px; font-weight:bold; overflow:auto; white-space:normal}
+.clearlooks2 a:hover {font-weight:bold;}
+.clearlooks2 .alert .middle, .clearlooks2 .confirm .middle {background:#D6D7D5}
+.clearlooks2 .alert .ok {left:50%; top:auto; margin-left: -40px}
+.clearlooks2 .alert .icon {background:url(img/alert.gif)}
+.clearlooks2 .confirm .ok {left:50%; top:auto; margin-left: -90px}
+.clearlooks2 .confirm .cancel {left:50%; top:auto}
+.clearlooks2 .confirm .icon {background:url(img/confirm.gif)}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/includes/clientside/tinymce/plugins/inlinepopups/template.htm	Fri Feb 22 12:51:53 2008 -0500
@@ -0,0 +1,387 @@
+<!-- <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> -->
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Template for dialogs</title>
+<link rel="stylesheet" type="text/css" href="skins/clearlooks2/window.css" />
+</head>
+<body>
+
+<div class="mceEditor">
+	<div class="clearlooks2" style="width:400px; height:100px; left:10px;">
+		<div class="wrapper">
+			<div class="top">
+				<div class="left"></div>
+				<div class="center"></div>
+				<div class="right"></div>
+				<span>Blured</span>
+			</div>
+
+			<div class="middle">
+				<div class="left"></div>
+				<span>Content</span>
+				<div class="right"></div>
+			</div>
+
+			<div class="bottom">
+				<div class="left"></div>
+				<div class="center"></div>
+				<div class="right"></div>
+				<span>Statusbar text.</span>
+			</div>
+
+			<a class="move" href="#"></a>
+			<a class="min" href="#"></a>
+			<a class="max" href="#"></a>
+			<a class="med" href="#"></a>
+			<a class="close" href="#"></a>
+			<a class="resize resize-n" href="#"></a>
+			<a class="resize resize-s" href="#"></a>
+			<a class="resize resize-w" href="#"></a>
+			<a class="resize resize-e" href="#"></a>
+			<a class="resize resize-nw" href="#"></a>
+			<a class="resize resize-ne" href="#"></a>
+			<a class="resize resize-sw" href="#"></a>
+			<a class="resize resize-se" href="#"></a>
+		</div>
+	</div>
+
+	<div class="clearlooks2" style="width:400px; height:100px; left:420px;">
+		<div class="wrapper movable focus">
+			<div class="top">
+				<div class="left"></div>
+				<div class="center"></div>
+				<div class="right"></div>
+				<span>Focused</span>
+			</div>
+
+			<div class="middle">
+				<div class="left"></div>
+				<span>Content</span>
+				<div class="right"></div>
+			</div>
+
+			<div class="bottom">
+				<div class="left"></div>
+				<div class="center"></div>
+				<div class="right"></div>
+				<span>Statusbar text.</span>
+			</div>
+
+			<a class="move" href="#"></a>
+			<a class="min" href="#"></a>
+			<a class="max" href="#"></a>
+			<a class="med" href="#"></a>
+			<a class="close" href="#"></a>
+			<a class="resize resize-n" href="#"></a>
+			<a class="resize resize-s" href="#"></a>
+			<a class="resize resize-w" href="#"></a>
+			<a class="resize resize-e" href="#"></a>
+			<a class="resize resize-nw" href="#"></a>
+			<a class="resize resize-ne" href="#"></a>
+			<a class="resize resize-sw" href="#"></a>
+			<a class="resize resize-se" href="#"></a>
+		</div>
+	</div>
+
+	<div class="clearlooks2" style="width:400px; height:100px; left:10px; top:120px;">
+		<div class="wrapper movable focus statusbar">
+			<div class="top">
+				<div class="left"></div>
+				<div class="center"></div>
+				<div class="right"></div>
+				<span>Statusbar</span>
+			</div>
+
+			<div class="middle">
+				<div class="left"></div>
+				<span>Content</span>
+				<div class="right"></div>
+			</div>
+
+			<div class="bottom">
+				<div class="left"></div>
+				<div class="center"></div>
+				<div class="right"></div>
+				<span>Statusbar text.</span>
+			</div>
+
+			<a class="move" href="#"></a>
+			<a class="min" href="#"></a>
+			<a class="max" href="#"></a>
+			<a class="med" href="#"></a>
+			<a class="close" href="#"></a>
+			<a class="resize resize-n" href="#"></a>
+			<a class="resize resize-s" href="#"></a>
+			<a class="resize resize-w" href="#"></a>
+			<a class="resize resize-e" href="#"></a>
+			<a class="resize resize-nw" href="#"></a>
+			<a class="resize resize-ne" href="#"></a>
+			<a class="resize resize-sw" href="#"></a>
+			<a class="resize resize-se" href="#"></a>
+		</div>
+	</div>
+
+	<div class="clearlooks2" style="width:400px; height:100px; left:420px; top:120px;">
+		<div class="wrapper movable focus statusbar resizable">
+			<div class="top">
+				<div class="left"></div>
+				<div class="center"></div>
+				<div class="right"></div>
+				<span>Statusbar, Resizable</span>
+			</div>
+
+			<div class="middle">
+				<div class="left"></div>
+				<span>Content</span>
+				<div class="right"></div>
+			</div>
+
+			<div class="bottom">
+				<div class="left"></div>
+				<div class="center"></div>
+				<div class="right"></div>
+				<span>Statusbar text.</span>
+			</div>
+
+			<a class="move" href="#"></a>
+			<a class="min" href="#"></a>
+			<a class="max" href="#"></a>
+			<a class="med" href="#"></a>
+			<a class="close" href="#"></a>
+			<a class="resize resize-n" href="#"></a>
+			<a class="resize resize-s" href="#"></a>
+			<a class="resize resize-w" href="#"></a>
+			<a class="resize resize-e" href="#"></a>
+			<a class="resize resize-nw" href="#"></a>
+			<a class="resize resize-ne" href="#"></a>
+			<a class="resize resize-sw" href="#"></a>
+			<a class="resize resize-se" href="#"></a>
+		</div>
+	</div>
+
+	<div class="clearlooks2" style="width:400px; height:100px; left:10px; top:230px;">
+		<div class="wrapper movable focus resizable maximizable">
+			<div class="top">
+				<div class="left"></div>
+				<div class="center"></div>
+				<div class="right"></div>
+				<span>Resizable, Maximizable</span>
+			</div>
+
+			<div class="middle">
+				<div class="left"></div>
+				<span>Content</span>
+				<div class="right"></div>
+			</div>
+
+			<div class="bottom">
+				<div class="left"></div>
+				<div class="center"></div>
+				<div class="right"></div>
+				<span>Statusbar text.</span>
+			</div>
+
+			<a class="move" href="#"></a>
+			<a class="min" href="#"></a>
+			<a class="max" href="#"></a>
+			<a class="med" href="#"></a>
+			<a class="close" href="#"></a>
+			<a class="resize resize-n" href="#"></a>
+			<a class="resize resize-s" href="#"></a>
+			<a class="resize resize-w" href="#"></a>
+			<a class="resize resize-e" href="#"></a>
+			<a class="resize resize-nw" href="#"></a>
+			<a class="resize resize-ne" href="#"></a>
+			<a class="resize resize-sw" href="#"></a>
+			<a class="resize resize-se" href="#"></a>
+		</div>
+	</div>
+
+	<div class="clearlooks2" style="width:400px; height:100px; left:420px; top:230px;">
+		<div class="wrapper movable statusbar resizable maximizable">
+			<div class="top">
+				<div class="left"></div>
+				<div class="center"></div>
+				<div class="right"></div>
+				<span>Blurred, Maximizable, Statusbar, Resizable</span>
+			</div>
+
+			<div class="middle">
+				<div class="left"></div>
+				<span>Content</span>
+				<div class="right"></div>
+			</div>
+
+			<div class="bottom">
+				<div class="left"></div>
+				<div class="center"></div>
+				<div class="right"></div>
+				<span>Statusbar text.</span>
+			</div>
+
+			<a class="move" href="#"></a>
+			<a class="min" href="#"></a>
+			<a class="max" href="#"></a>
+			<a class="med" href="#"></a>
+			<a class="close" href="#"></a>
+			<a class="resize resize-n" href="#"></a>
+			<a class="resize resize-s" href="#"></a>
+			<a class="resize resize-w" href="#"></a>
+			<a class="resize resize-e" href="#"></a>
+			<a class="resize resize-nw" href="#"></a>
+			<a class="resize resize-ne" href="#"></a>
+			<a class="resize resize-sw" href="#"></a>
+			<a class="resize resize-se" href="#"></a>
+		</div>
+	</div>
+
+	<div class="clearlooks2" style="width:400px; height:100px; left:10px; top:340px;">
+		<div class="wrapper movable focus resizable maximized minimizable maximizable">
+			<div class="top">
+				<div class="left"></div>
+				<div class="center"></div>
+				<div class="right"></div>
+				<span>Maximized, Maximizable, Minimizable, Focused</span>
+			</div>
+
+			<div class="middle">
+				<div class="left"></div>
+				<span>Content</span>
+				<div class="right"></div>
+			</div>
+
+			<div class="bottom">
+				<div class="left"></div>
+				<div class="center"></div>
+				<div class="right"></div>
+				<span>Statusbar text.</span>
+			</div>
+
+			<a class="move" href="#"></a>
+			<a class="min" href="#"></a>
+			<a class="max" href="#"></a>
+			<a class="med" href="#"></a>
+			<a class="close" href="#"></a>
+			<a class="resize resize-n" href="#"></a>
+			<a class="resize resize-s" href="#"></a>
+			<a class="resize resize-w" href="#"></a>
+			<a class="resize resize-e" href="#"></a>
+			<a class="resize resize-nw" href="#"></a>
+			<a class="resize resize-ne" href="#"></a>
+			<a class="resize resize-sw" href="#"></a>
+			<a class="resize resize-se" href="#"></a>
+		</div>
+	</div>
+
+	<div class="clearlooks2" style="width:400px; height:100px; left:420px; top:340px;">
+		<div class="wrapper movable statusbar resizable maximized minimizable maximizable">
+			<div class="top">
+				<div class="left"></div>
+				<div class="center"></div>
+				<div class="right"></div>
+				<span>Maximized, Maximizable, Minimizable</span>
+			</div>
+
+			<div class="middle">
+				<div class="left"></div>
+				<span>Content</span>
+				<div class="right"></div>
+			</div>
+
+			<div class="bottom">
+				<div class="left"></div>
+				<div class="center"></div>
+				<div class="right"></div>
+				<span>Statusbar text.</span>
+			</div>
+
+			<a class="move" href="#"></a>
+			<a class="min" href="#"></a>
+			<a class="med" href="#"></a>
+			<a class="max" href="#"></a>
+			<a class="close" href="#"></a>
+			<a class="resize resize-n" href="#"></a>
+			<a class="resize resize-s" href="#"></a>
+			<a class="resize resize-w" href="#"></a>
+			<a class="resize resize-e" href="#"></a>
+			<a class="resize resize-nw" href="#"></a>
+			<a class="resize resize-ne" href="#"></a>
+			<a class="resize resize-sw" href="#"></a>
+			<a class="resize resize-se" href="#"></a>
+		</div>
+	</div>
+
+	<div class="clearlooks2" style="width:400px; height:130px; left:10px; top:450px;">
+		<div class="wrapper movable focus modal alert">
+			<div class="top">
+				<div class="left"></div>
+				<div class="center"></div>
+				<div class="right"></div>
+				<span>Alert</span>
+			</div>
+
+			<div class="middle">
+				<div class="left"></div>
+				<span>
+					This is a very long error message. This is a very long error message.
+					This is a very long error message. This is a very long error message.
+					This is a very long error message. This is a very long error message.
+					This is a very long error message. This is a very long error message.
+					This is a very long error message. This is a very long error message.
+					This is a very long error message. This is a very long error message.
+				</span>
+				<div class="right"></div>
+				<div class="icon"></div>
+			</div>
+
+			<div class="bottom">
+				<div class="left"></div>
+				<div class="center"></div>
+				<div class="right"></div>
+			</div>
+
+			<a class="move" href="#"></a>
+			<a class="button ok" href="#">Ok</a>
+			<a class="close" href="#"></a>
+		</div>
+	</div>
+
+	<div class="clearlooks2" style="width:400px; height:130px; left:420px; top:450px;">
+		<div class="wrapper movable focus modal confirm">
+			<div class="top">
+				<div class="left"></div>
+				<div class="center"></div>
+				<div class="right"></div>
+				<span>Confirm</span>
+			</div>
+
+			<div class="middle">
+				<div class="left"></div>
+				<span>
+					This is a very long error message. This is a very long error message.
+					This is a very long error message. This is a very long error message.
+					This is a very long error message. This is a very long error message.
+					This is a very long error message. This is a very long error message.
+					This is a very long error message. This is a very long error message.
+					This is a very long error message. This is a very long error message.
+					</span>
+				<div class="right"></div>
+				<div class="icon"></div>
+			</div>
+
+			<div class="bottom">
+				<div class="left"></div>
+				<div class="center"></div>
+				<div class="right"></div>
+			</div>
+
+			<a class="move" href="#"></a>
+			<a class="button ok" href="#">Ok</a>
+			<a class="button cancel" href="#">Cancel</a>
+			<a class="close" href="#"></a>
+		</div>
+	</div>
+</div>
+
+</body>
+</html>
--- a/includes/clientside/tinymce/plugins/insertdatetime/editor_plugin.js	Fri Feb 22 12:46:51 2008 -0500
+++ b/includes/clientside/tinymce/plugins/insertdatetime/editor_plugin.js	Fri Feb 22 12:51:53 2008 -0500
@@ -1,1 +1,1 @@
-tinyMCE.importPluginLanguagePack('insertdatetime');var TinyMCE_InsertDateTimePlugin={getInfo:function(){return{longname:'Insert date/time',author:'Moxiecode Systems AB',authorurl:'http://tinymce.moxiecode.com',infourl:'http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/insertdatetime',version:tinyMCE.majorVersion+"."+tinyMCE.minorVersion}},getControlHTML:function(cn){switch(cn){case"insertdate":return tinyMCE.getButtonHTML(cn,'lang_insertdate_desc','{$pluginurl}/images/insertdate.gif','mceInsertDate');case"inserttime":return tinyMCE.getButtonHTML(cn,'lang_inserttime_desc','{$pluginurl}/images/inserttime.gif','mceInsertTime')}return""},execCommand:function(editor_id,element,command,user_interface,value){function addZeros(value,len){value=""+value;if(value.length<len){for(var i=0;i<(len-value.length);i++)value="0"+value}return value}function getDateTime(d,fmt){fmt=fmt.replace("%D","%m/%d/%y");fmt=fmt.replace("%r","%I:%M:%S %p");fmt=fmt.replace("%Y",""+d.getFullYear());fmt=fmt.replace("%y",""+d.getYear());fmt=fmt.replace("%m",addZeros(d.getMonth()+1,2));fmt=fmt.replace("%d",addZeros(d.getDate(),2));fmt=fmt.replace("%H",""+addZeros(d.getHours(),2));fmt=fmt.replace("%M",""+addZeros(d.getMinutes(),2));fmt=fmt.replace("%S",""+addZeros(d.getSeconds(),2));fmt=fmt.replace("%I",""+((d.getHours()+11)%12+1));fmt=fmt.replace("%p",""+(d.getHours()<12?"AM":"PM"));fmt=fmt.replace("%B",""+tinyMCE.getLang("lang_inserttime_months_long")[d.getMonth()]);fmt=fmt.replace("%b",""+tinyMCE.getLang("lang_inserttime_months_short")[d.getMonth()]);fmt=fmt.replace("%A",""+tinyMCE.getLang("lang_inserttime_day_long")[d.getDay()]);fmt=fmt.replace("%a",""+tinyMCE.getLang("lang_inserttime_day_short")[d.getDay()]);fmt=fmt.replace("%%","%");return fmt}switch(command){case"mceInsertDate":tinyMCE.execInstanceCommand(editor_id,'mceInsertContent',false,getDateTime(new Date(),tinyMCE.getParam("plugin_insertdate_dateFormat",tinyMCE.getLang('lang_insertdate_def_fmt'))));return true;case"mceInsertTime":tinyMCE.execInstanceCommand(editor_id,'mceInsertContent',false,getDateTime(new Date(),tinyMCE.getParam("plugin_insertdate_timeFormat",tinyMCE.getLang('lang_inserttime_def_fmt'))));return true}return false}};tinyMCE.addPlugin("insertdatetime",TinyMCE_InsertDateTimePlugin);
\ No newline at end of file
+(function(){tinymce.create('tinymce.plugins.InsertDateTime',{init:function(ed,url){var t=this;t.editor=ed;ed.addCommand('mceInsertDate',function(){var str=t._getDateTime(new Date(),ed.getParam("plugin_insertdate_dateFormat",ed.getLang('insertdatetime.date_fmt')));ed.execCommand('mceInsertContent',false,str);});ed.addCommand('mceInsertTime',function(){var str=t._getDateTime(new Date(),ed.getParam("plugin_insertdate_timeFormat",ed.getLang('insertdatetime.time_fmt')));ed.execCommand('mceInsertContent',false,str);});ed.addButton('insertdate',{title:'insertdatetime.insertdate_desc',cmd:'mceInsertDate'});ed.addButton('inserttime',{title:'insertdatetime.inserttime_desc',cmd:'mceInsertTime'});},getInfo:function(){return{longname:'Insert date/time',author:'Moxiecode Systems AB',authorurl:'http://tinymce.moxiecode.com',infourl:'http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/insertdatetime',version:tinymce.majorVersion+"."+tinymce.minorVersion};},_getDateTime:function(d,fmt){var ed=this.editor;function addZeros(value,len){value=""+value;if(value.length<len){for(var i=0;i<(len-value.length);i++)value="0"+value;}return value;};fmt=fmt.replace("%D","%m/%d/%y");fmt=fmt.replace("%r","%I:%M:%S %p");fmt=fmt.replace("%Y",""+d.getFullYear());fmt=fmt.replace("%y",""+d.getYear());fmt=fmt.replace("%m",addZeros(d.getMonth()+1,2));fmt=fmt.replace("%d",addZeros(d.getDate(),2));fmt=fmt.replace("%H",""+addZeros(d.getHours(),2));fmt=fmt.replace("%M",""+addZeros(d.getMinutes(),2));fmt=fmt.replace("%S",""+addZeros(d.getSeconds(),2));fmt=fmt.replace("%I",""+((d.getHours()+11)%12+1));fmt=fmt.replace("%p",""+(d.getHours()<12?"AM":"PM"));fmt=fmt.replace("%B",""+ed.getLang("insertdatetime.months_long").split(',')[d.getMonth()]);fmt=fmt.replace("%b",""+ed.getLang("insertdatetime.months_short").split(',')[d.getMonth()]);fmt=fmt.replace("%A",""+ed.getLang("insertdatetime.day_long").split(',')[d.getDay()]);fmt=fmt.replace("%a",""+ed.getLang("insertdatetime.day_short").split(',')[d.getDay()]);fmt=fmt.replace("%%","%");return fmt;}});tinymce.PluginManager.add('insertdatetime',tinymce.plugins.InsertDateTime);})();
\ No newline at end of file
--- a/includes/clientside/tinymce/plugins/insertdatetime/editor_plugin_src.js	Fri Feb 22 12:46:51 2008 -0500
+++ b/includes/clientside/tinymce/plugins/insertdatetime/editor_plugin_src.js	Fri Feb 22 12:51:53 2008 -0500
@@ -1,56 +1,59 @@
 /**
- * $Id: editor_plugin_src.js 201 2007-02-12 15:56:56Z spocke $
+ * $Id: editor_plugin_src.js 520 2008-01-07 16:30:32Z spocke $
  *
  * @author Moxiecode
- * @copyright Copyright © 2004-2007, Moxiecode Systems AB, All rights reserved.
+ * @copyright Copyright © 2004-2008, Moxiecode Systems AB, All rights reserved.
  */
 
-/* Import plugin specific language pack */
-tinyMCE.importPluginLanguagePack('insertdatetime');
+(function() {
+	tinymce.create('tinymce.plugins.InsertDateTime', {
+		init : function(ed, url) {
+			var t = this;
+
+			t.editor = ed;
+
+			ed.addCommand('mceInsertDate', function() {
+				var str = t._getDateTime(new Date(), ed.getParam("plugin_insertdate_dateFormat", ed.getLang('insertdatetime.date_fmt')));
 
-var TinyMCE_InsertDateTimePlugin = {
-	getInfo : function() {
-		return {
-			longname : 'Insert date/time',
-			author : 'Moxiecode Systems AB',
-			authorurl : 'http://tinymce.moxiecode.com',
-			infourl : 'http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/insertdatetime',
-			version : tinyMCE.majorVersion + "." + tinyMCE.minorVersion
-		};
-	},
+				ed.execCommand('mceInsertContent', false, str);
+			});
+
+			ed.addCommand('mceInsertTime', function() {
+				var str = t._getDateTime(new Date(), ed.getParam("plugin_insertdate_timeFormat", ed.getLang('insertdatetime.time_fmt')));
 
-	/**
-	 * Returns the HTML contents of the insertdate, inserttime controls.
-	 */
-	getControlHTML : function(cn) {
-		switch (cn) {
-			case "insertdate":
-				return tinyMCE.getButtonHTML(cn, 'lang_insertdate_desc', '{$pluginurl}/images/insertdate.gif', 'mceInsertDate');
+				ed.execCommand('mceInsertContent', false, str);
+			});
+
+			ed.addButton('insertdate', {title : 'insertdatetime.insertdate_desc', cmd : 'mceInsertDate'});
+			ed.addButton('inserttime', {title : 'insertdatetime.inserttime_desc', cmd : 'mceInsertTime'});
+		},
 
-			case "inserttime":
-				return tinyMCE.getButtonHTML(cn, 'lang_inserttime_desc', '{$pluginurl}/images/inserttime.gif', 'mceInsertTime');
-		}
+		getInfo : function() {
+			return {
+				longname : 'Insert date/time',
+				author : 'Moxiecode Systems AB',
+				authorurl : 'http://tinymce.moxiecode.com',
+				infourl : 'http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/insertdatetime',
+				version : tinymce.majorVersion + "." + tinymce.minorVersion
+			};
+		},
 
-		return "";
-	},
+		// Private methods
 
-	/**
-	 * Executes the mceInsertDate command.
-	 */
-	execCommand : function(editor_id, element, command, user_interface, value) {
-		/* Adds zeros infront of value */
-		function addZeros(value, len) {
-			value = "" + value;
+		_getDateTime : function(d, fmt) {
+			var ed = this.editor;
+
+			function addZeros(value, len) {
+				value = "" + value;
 
-			if (value.length < len) {
-				for (var i=0; i<(len-value.length); i++)
-					value = "0" + value;
-			}
+				if (value.length < len) {
+					for (var i=0; i<(len-value.length); i++)
+						value = "0" + value;
+				}
 
-			return value;
-		}
+				return value;
+			};
 
-		function getDateTime(d, fmt) {
 			fmt = fmt.replace("%D", "%m/%d/%y");
 			fmt = fmt.replace("%r", "%I:%M:%S %p");
 			fmt = fmt.replace("%Y", "" + d.getFullYear());
@@ -62,29 +65,16 @@
 			fmt = fmt.replace("%S", "" + addZeros(d.getSeconds(), 2));
 			fmt = fmt.replace("%I", "" + ((d.getHours() + 11) % 12 + 1));
 			fmt = fmt.replace("%p", "" + (d.getHours() < 12 ? "AM" : "PM"));
-			fmt = fmt.replace("%B", "" + tinyMCE.getLang("lang_inserttime_months_long")[d.getMonth()]);
-			fmt = fmt.replace("%b", "" + tinyMCE.getLang("lang_inserttime_months_short")[d.getMonth()]);
-			fmt = fmt.replace("%A", "" + tinyMCE.getLang("lang_inserttime_day_long")[d.getDay()]);
-			fmt = fmt.replace("%a", "" + tinyMCE.getLang("lang_inserttime_day_short")[d.getDay()]);
+			fmt = fmt.replace("%B", "" + ed.getLang("insertdatetime.months_long").split(',')[d.getMonth()]);
+			fmt = fmt.replace("%b", "" + ed.getLang("insertdatetime.months_short").split(',')[d.getMonth()]);
+			fmt = fmt.replace("%A", "" + ed.getLang("insertdatetime.day_long").split(',')[d.getDay()]);
+			fmt = fmt.replace("%a", "" + ed.getLang("insertdatetime.day_short").split(',')[d.getDay()]);
 			fmt = fmt.replace("%%", "%");
 
 			return fmt;
 		}
-
-		// Handle commands
-		switch (command) {
-			case "mceInsertDate":
-				tinyMCE.execInstanceCommand(editor_id, 'mceInsertContent', false, getDateTime(new Date(), tinyMCE.getParam("plugin_insertdate_dateFormat", tinyMCE.getLang('lang_insertdate_def_fmt'))));
-				return true;
+	});
 
-			case "mceInsertTime":
-				tinyMCE.execInstanceCommand(editor_id, 'mceInsertContent', false, getDateTime(new Date(), tinyMCE.getParam("plugin_insertdate_timeFormat", tinyMCE.getLang('lang_inserttime_def_fmt'))));
-				return true;
-		}
-
-		// Pass to next handler in chain
-		return false;
-	}
-};
-
-tinyMCE.addPlugin("insertdatetime", TinyMCE_InsertDateTimePlugin);
+	// Register plugin
+	tinymce.PluginManager.add('insertdatetime', tinymce.plugins.InsertDateTime);
+})();
\ No newline at end of file
Binary file includes/clientside/tinymce/plugins/insertdatetime/images/insertdate.gif has changed
Binary file includes/clientside/tinymce/plugins/insertdatetime/images/inserttime.gif has changed
--- a/includes/clientside/tinymce/plugins/insertdatetime/langs/en.js	Fri Feb 22 12:46:51 2008 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,12 +0,0 @@
-// UK lang variables
-
-tinyMCE.addToLang('',{
-insertdate_def_fmt : '%Y-%m-%d',
-inserttime_def_fmt : '%H:%M:%S',
-insertdate_desc : 'Insert date',
-inserttime_desc : 'Insert time',
-inserttime_months_long : new Array("January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"),
-inserttime_months_short : new Array("Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"),
-inserttime_day_long : new Array("Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"),
-inserttime_day_short : new Array("Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun")
-});
--- a/includes/clientside/tinymce/plugins/insertdatetime/readme.txt	Fri Feb 22 12:46:51 2008 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1 +0,0 @@
-Check the TinyMCE documentation for details on this plugin.
--- a/includes/clientside/tinymce/plugins/layer/editor_plugin.js	Fri Feb 22 12:46:51 2008 -0500
+++ b/includes/clientside/tinymce/plugins/layer/editor_plugin.js	Fri Feb 22 12:51:53 2008 -0500
@@ -1,1 +1,1 @@
-tinyMCE.importPluginLanguagePack('layer');var TinyMCE_LayerPlugin={getInfo:function(){return{longname:'Layer',author:'Moxiecode Systems AB',authorurl:'http://tinymce.moxiecode.com',infourl:'http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/layer',version:tinyMCE.majorVersion+"."+tinyMCE.minorVersion}},initInstance:function(inst){if(tinyMCE.isMSIE&&!tinyMCE.isOpera)inst.getDoc().execCommand('2D-Position')},handleEvent:function(e){var inst=tinyMCE.selectedInstance;var w=inst.getWin(),le=inst._lastStyleElm,e;if(tinyMCE.isGecko){e=this._getParentLayer(inst.getFocusElement());if(e){if(!inst._lastStyleElm){e.style.overflow='auto';inst._lastStyleElm=e}}else if(le){le=inst._lastStyleElm;le.style.width=le.scrollWidth+'px';le.style.height=le.scrollHeight+'px';le.style.overflow='';inst._lastStyleElm=null}}return true},handleVisualAid:function(el,deep,state,inst){var nl=inst.getDoc().getElementsByTagName("div"),i;for(i=0;i<nl.length;i++){if(new RegExp('absolute|relative|static','gi').test(nl[i].style.position)){if(state)tinyMCE.addCSSClass(nl[i],'mceVisualAid');else tinyMCE.removeCSSClass(nl[i],'mceVisualAid')}}},getControlHTML:function(cn){switch(cn){case"moveforward":return tinyMCE.getButtonHTML(cn,'lang_layer_forward_desc','{$pluginurl}/images/moveforward.gif','mceMoveForward',true);case"movebackward":return tinyMCE.getButtonHTML(cn,'lang_layer_backward_desc','{$pluginurl}/images/movebackward.gif','mceMoveBackward',true);case"absolute":return tinyMCE.getButtonHTML(cn,'lang_layer_absolute_desc','{$pluginurl}/images/absolute.gif','mceMakeAbsolute',true);case"insertlayer":return tinyMCE.getButtonHTML(cn,'lang_layer_insertlayer_desc','{$pluginurl}/images/insertlayer.gif','mceInsertLayer',true)}return""},execCommand:function(editor_id,element,command,user_interface,value){switch(command){case"mceInsertLayer":this._insertLayer();return true;case"mceMoveForward":this._move(1);return true;case"mceMoveBackward":this._move(-1);return true;case"mceMakeAbsolute":this._toggleAbsolute();return true}return false},handleNodeChange:function(editor_id,node,undo_index,undo_levels,visual_aid,any_selection){var inst=tinyMCE.getInstanceById(editor_id);var le=this._getParentLayer(inst.getFocusElement());var p=tinyMCE.getParentElement(inst.getFocusElement(),'div,p,img');tinyMCE.switchClass(editor_id+'_absolute','mceButtonDisabled');tinyMCE.switchClass(editor_id+'_moveforward','mceButtonDisabled');tinyMCE.switchClass(editor_id+'_movebackward','mceButtonDisabled');if(p)tinyMCE.switchClass(editor_id+'_absolute','mceButtonNormal');if(le&&le.style.position.toLowerCase()=="absolute"){tinyMCE.switchClass(editor_id+'_absolute','mceButtonSelected');tinyMCE.switchClass(editor_id+'_moveforward','mceButtonNormal');tinyMCE.switchClass(editor_id+'_movebackward','mceButtonNormal')}},_move:function(d){var inst=tinyMCE.selectedInstance,i,z=new Array();var le=this._getParentLayer(inst.getFocusElement()),ci=-1,fi=-1;var nl=tinyMCE.selectNodes(inst.getBody(),function(n){return n.nodeType==1&&new RegExp('absolute|relative|static','gi').test(n.style.position)});for(i=0;i<nl.length;i++){z[i]=nl[i].style.zIndex?parseInt(nl[i].style.zIndex):0;if(ci<0&&nl[i]==le)ci=i}if(d<0){for(i=0;i<z.length;i++){if(z[i]<z[ci]){fi=i;break}}if(fi>-1){nl[ci].style.zIndex=z[fi];nl[fi].style.zIndex=z[ci]}else{if(z[ci]>0)nl[ci].style.zIndex=z[ci]-1}}else{for(i=0;i<z.length;i++){if(z[i]>z[ci]){fi=i;break}}if(fi>-1){nl[ci].style.zIndex=z[fi];nl[fi].style.zIndex=z[ci]}else nl[ci].style.zIndex=z[ci]+1}inst.repaint()},_getParentLayer:function(n){return tinyMCE.getParentNode(n,function(n){return n.nodeType==1&&new RegExp('absolute|relative|static','gi').test(n.style.position)})},_insertLayer:function(){var inst=tinyMCE.selectedInstance;var e=tinyMCE.getParentElement(inst.getFocusElement());var p=tinyMCE.getAbsPosition(e);var d=inst.getDoc();var ne=d.createElement('div');var h=inst.selection.getSelectedHTML();ne.style.position='absolute';ne.style.left=p.absLeft+'px';ne.style.top=(p.absTop>20?p.absTop:20)+'px';ne.style.width='100px';ne.style.height='100px';ne.className='mceVisualAid';if(!h)h=tinyMCE.getLang('lang_layer_content');ne.innerHTML=h;d.body.appendChild(ne)},_toggleAbsolute:function(){var inst=tinyMCE.selectedInstance;var le=this._getParentLayer(inst.getFocusElement());if(le==null)le=tinyMCE.getParentElement(inst.getFocusElement(),'div,p,img');if(le){if(le.style.position.toLowerCase()=="absolute"){le.style.position="";le.style.left="";le.style.top=""}else{le.style.position="absolute";if(le.style.left=="")le.style.left=20+'px';if(le.style.top=="")le.style.top=20+'px';if(le.style.width=="")le.style.width=le.width?(le.width+'px'):'100px';if(le.style.height=="")le.style.height=le.height?(le.height+'px'):'100px';tinyMCE.handleVisualAid(inst.getBody(),true,inst.visualAid,inst)}inst.repaint();tinyMCE.triggerNodeChange()}}};tinyMCE.addPlugin("layer",TinyMCE_LayerPlugin);
\ No newline at end of file
+(function(){tinymce.create('tinymce.plugins.Layer',{init:function(ed,url){var t=this;t.editor=ed;ed.addCommand('mceInsertLayer',t._insertLayer,t);ed.addCommand('mceMoveForward',function(){t._move(1);});ed.addCommand('mceMoveBackward',function(){t._move(-1);});ed.addCommand('mceMakeAbsolute',function(){t._toggleAbsolute();});ed.addButton('moveforward',{title:'layer.forward_desc',cmd:'mceMoveForward'});ed.addButton('movebackward',{title:'layer.backward_desc',cmd:'mceMoveBackward'});ed.addButton('absolute',{title:'layer.absolute_desc',cmd:'mceMakeAbsolute'});ed.addButton('insertlayer',{title:'layer.insertlayer_desc',cmd:'mceInsertLayer'});ed.onInit.add(function(){if(tinymce.isIE)ed.execCommand('2D-Position');});ed.onNodeChange.add(t._nodeChange,t);ed.onVisualAid.add(t._visualAid,t);},getInfo:function(){return{longname:'Layer',author:'Moxiecode Systems AB',authorurl:'http://tinymce.moxiecode.com',infourl:'http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/layer',version:tinymce.majorVersion+"."+tinymce.minorVersion};},_nodeChange:function(ed,cm,n){var le,p;le=this._getParentLayer(n);p=ed.dom.getParent(n,'DIV,P,IMG');if(!p){cm.setDisabled('absolute',1);cm.setDisabled('moveforward',1);cm.setDisabled('movebackward',1);}else{cm.setDisabled('absolute',0);cm.setDisabled('moveforward',!le);cm.setDisabled('movebackward',!le);cm.setActive('absolute',le&&le.style.position.toLowerCase()=="absolute");}},_visualAid:function(ed,e,s){var dom=ed.dom;tinymce.each(dom.select('div,p',e),function(e){if(/^(absolute|relative|static)$/i.test(e.style.position)){if(s)dom.addClass(e,'mceVisualAid');else dom.removeClass(e,'mceVisualAid');}});},_move:function(d){var ed=this.editor,i,z=[],le=this._getParentLayer(ed.selection.getNode()),ci=-1,fi=-1,nl;nl=[];tinymce.walk(ed.getBody(),function(n){if(n.nodeType==1&&/^(absolute|relative|static)$/i.test(n.style.position))nl.push(n);},'childNodes');for(i=0;i<nl.length;i++){z[i]=nl[i].style.zIndex?parseInt(nl[i].style.zIndex):0;if(ci<0&&nl[i]==le)ci=i;}if(d<0){for(i=0;i<z.length;i++){if(z[i]<z[ci]){fi=i;break;}}if(fi>-1){nl[ci].style.zIndex=z[fi];nl[fi].style.zIndex=z[ci];}else{if(z[ci]>0)nl[ci].style.zIndex=z[ci]-1;}}else{for(i=0;i<z.length;i++){if(z[i]>z[ci]){fi=i;break;}}if(fi>-1){nl[ci].style.zIndex=z[fi];nl[fi].style.zIndex=z[ci];}else nl[ci].style.zIndex=z[ci]+1;}ed.execCommand('mceRepaint');},_getParentLayer:function(n){return this.editor.dom.getParent(n,function(n){return n.nodeType==1&&/^(absolute|relative|static)$/i.test(n.style.position);});},_insertLayer:function(){var ed=this.editor,p=ed.dom.getPos(ed.dom.getParent(ed.selection.getNode(),'*'));ed.dom.add(ed.getBody(),'div',{style:{position:'absolute',left:p.x,top:(p.y>20?p.y:20),width:100,height:100},'class':'mceVisualAid'},ed.selection.getContent()||ed.getLang('layer.content'));},_toggleAbsolute:function(){var ed=this.editor,le=this._getParentLayer(ed.selection.getNode());if(!le)le=ed.dom.getParent(ed.selection.getNode(),'DIV,P,IMG');if(le){if(le.style.position.toLowerCase()=="absolute"){ed.dom.setStyles(le,{position:'',left:'',top:'',width:'',height:''});ed.dom.removeClass(le,'mceVisualAid');}else{if(le.style.left=="")le.style.left=20+'px';if(le.style.top=="")le.style.top=20+'px';if(le.style.width=="")le.style.width=le.width?(le.width+'px'):'100px';if(le.style.height=="")le.style.height=le.height?(le.height+'px'):'100px';le.style.position="absolute";ed.addVisual(ed.getBody());}ed.execCommand('mceRepaint');ed.nodeChanged();}}});tinymce.PluginManager.add('layer',tinymce.plugins.Layer);})();
\ No newline at end of file
--- a/includes/clientside/tinymce/plugins/layer/editor_plugin_src.js	Fri Feb 22 12:46:51 2008 -0500
+++ b/includes/clientside/tinymce/plugins/layer/editor_plugin_src.js	Fri Feb 22 12:51:53 2008 -0500
@@ -1,248 +1,209 @@
 /**
- * $Id: editor_plugin_src.js 201 2007-02-12 15:56:56Z spocke $
+ * $Id: editor_plugin_src.js 520 2008-01-07 16:30:32Z spocke $
  *
  * @author Moxiecode
- * @copyright Copyright © 2004-2007, Moxiecode Systems AB, All rights reserved.
+ * @copyright Copyright © 2004-2008, Moxiecode Systems AB, All rights reserved.
  */
 
-/* Import plugin specific language pack */
-tinyMCE.importPluginLanguagePack('layer');
+(function() {
+	tinymce.create('tinymce.plugins.Layer', {
+		init : function(ed, url) {
+			var t = this;
+
+			t.editor = ed;
+
+			// Register commands
+			ed.addCommand('mceInsertLayer', t._insertLayer, t);
+
+			ed.addCommand('mceMoveForward', function() {
+				t._move(1);
+			});
+
+			ed.addCommand('mceMoveBackward', function() {
+				t._move(-1);
+			});
+
+			ed.addCommand('mceMakeAbsolute', function() {
+				t._toggleAbsolute();
+			});
+
+			// Register buttons
+			ed.addButton('moveforward', {title : 'layer.forward_desc', cmd : 'mceMoveForward'});
+			ed.addButton('movebackward', {title : 'layer.backward_desc', cmd : 'mceMoveBackward'});
+			ed.addButton('absolute', {title : 'layer.absolute_desc', cmd : 'mceMakeAbsolute'});
+			ed.addButton('insertlayer', {title : 'layer.insertlayer_desc', cmd : 'mceInsertLayer'});
+
+			ed.onInit.add(function() {
+				if (tinymce.isIE)
+					ed.execCommand('2D-Position');
+			});
+
+			ed.onNodeChange.add(t._nodeChange, t);
+			ed.onVisualAid.add(t._visualAid, t);
+		},
+
+		getInfo : function() {
+			return {
+				longname : 'Layer',
+				author : 'Moxiecode Systems AB',
+				authorurl : 'http://tinymce.moxiecode.com',
+				infourl : 'http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/layer',
+				version : tinymce.majorVersion + "." + tinymce.minorVersion
+			};
+		},
 
-var TinyMCE_LayerPlugin = {
-	getInfo : function() {
-		return {
-			longname : 'Layer',
-			author : 'Moxiecode Systems AB',
-			authorurl : 'http://tinymce.moxiecode.com',
-			infourl : 'http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/layer',
-			version : tinyMCE.majorVersion + "." + tinyMCE.minorVersion
-		};
-	},
+		// Private methods
+
+		_nodeChange : function(ed, cm, n) {
+			var le, p;
+
+			le = this._getParentLayer(n);
+			p = ed.dom.getParent(n, 'DIV,P,IMG');
+
+			if (!p) {
+				cm.setDisabled('absolute', 1);
+				cm.setDisabled('moveforward', 1);
+				cm.setDisabled('movebackward', 1);
+			} else {
+				cm.setDisabled('absolute', 0);
+				cm.setDisabled('moveforward', !le);
+				cm.setDisabled('movebackward', !le);
+				cm.setActive('absolute', le && le.style.position.toLowerCase() == "absolute");
+			}
+		},
+
+		// Private methods
 
-	initInstance : function(inst) {
-		if (tinyMCE.isMSIE && !tinyMCE.isOpera)
-			inst.getDoc().execCommand('2D-Position');
-	},
+		_visualAid : function(ed, e, s) {
+			var dom = ed.dom;
+
+			tinymce.each(dom.select('div,p', e), function(e) {
+				if (/^(absolute|relative|static)$/i.test(e.style.position)) {
+					if (s)
+						dom.addClass(e, 'mceVisualAid');
+					else
+						dom.removeClass(e, 'mceVisualAid');	
+				}
+			});
+		},
 
-	handleEvent : function(e) {
-		var inst = tinyMCE.selectedInstance;
-		var w = inst.getWin(), le = inst._lastStyleElm, e;
+		_move : function(d) {
+			var ed = this.editor, i, z = [], le = this._getParentLayer(ed.selection.getNode()), ci = -1, fi = -1, nl;
 
-		if (tinyMCE.isGecko) {
-			e = this._getParentLayer(inst.getFocusElement());
+			nl = [];
+			tinymce.walk(ed.getBody(), function(n) {
+				if (n.nodeType == 1 && /^(absolute|relative|static)$/i.test(n.style.position))
+					nl.push(n); 
+			}, 'childNodes');
+
+			// Find z-indexes
+			for (i=0; i<nl.length; i++) {
+				z[i] = nl[i].style.zIndex ? parseInt(nl[i].style.zIndex) : 0;
 
-			if (e) {
-				if (!inst._lastStyleElm) {
-					e.style.overflow = 'auto';
-					inst._lastStyleElm = e;
+				if (ci < 0 && nl[i] == le)
+					ci = i;
+			}
+
+			if (d < 0) {
+				// Move back
+
+				// Try find a lower one
+				for (i=0; i<z.length; i++) {
+					if (z[i] < z[ci]) {
+						fi = i;
+						break;
+					}
 				}
-			} else if (le) {
-				le = inst._lastStyleElm;
-				le.style.width = le.scrollWidth + 'px';
-				le.style.height = le.scrollHeight + 'px';
-				le.style.overflow = '';
-				inst._lastStyleElm = null;
+
+				if (fi > -1) {
+					nl[ci].style.zIndex = z[fi];
+					nl[fi].style.zIndex = z[ci];
+				} else {
+					if (z[ci] > 0)
+						nl[ci].style.zIndex = z[ci] - 1;
+				}
+			} else {
+				// Move forward
+
+				// Try find a higher one
+				for (i=0; i<z.length; i++) {
+					if (z[i] > z[ci]) {
+						fi = i;
+						break;
+					}
+				}
+
+				if (fi > -1) {
+					nl[ci].style.zIndex = z[fi];
+					nl[fi].style.zIndex = z[ci];
+				} else
+					nl[ci].style.zIndex = z[ci] + 1;
 			}
-		}
+
+			ed.execCommand('mceRepaint');
+		},
+
+		_getParentLayer : function(n) {
+			return this.editor.dom.getParent(n, function(n) {
+				return n.nodeType == 1 && /^(absolute|relative|static)$/i.test(n.style.position);
+			});
+		},
+
+		_insertLayer : function() {
+			var ed = this.editor, p = ed.dom.getPos(ed.dom.getParent(ed.selection.getNode(), '*'));
 
-		return true;
-	},
+			ed.dom.add(ed.getBody(), 'div', {
+				style : {
+					position : 'absolute',
+					left : p.x,
+					top : (p.y > 20 ? p.y : 20),
+					width : 100,
+					height : 100
+				},
+				'class' : 'mceVisualAid'
+			}, ed.selection.getContent() || ed.getLang('layer.content'));
+		},
+
+		_toggleAbsolute : function() {
+			var ed = this.editor, le = this._getParentLayer(ed.selection.getNode());
+
+			if (!le)
+				le = ed.dom.getParent(ed.selection.getNode(), 'DIV,P,IMG');
 
-	handleVisualAid : function(el, deep, state, inst) {
-		var nl = inst.getDoc().getElementsByTagName("div"), i;
+			if (le) {
+				if (le.style.position.toLowerCase() == "absolute") {
+					ed.dom.setStyles(le, {
+						position : '',
+						left : '',
+						top : '',
+						width : '',
+						height : ''
+					});
+
+					ed.dom.removeClass(le, 'mceVisualAid');
+				} else {
+					if (le.style.left == "")
+						le.style.left = 20 + 'px';
 
-		for (i=0; i<nl.length; i++) {
-			if (new RegExp('absolute|relative|static', 'gi').test(nl[i].style.position)) {
-				if (state)
-					tinyMCE.addCSSClass(nl[i], 'mceVisualAid');
-				else
-					tinyMCE.removeCSSClass(nl[i], 'mceVisualAid');					
+					if (le.style.top == "")
+						le.style.top = 20 + 'px';
+
+					if (le.style.width == "")
+						le.style.width = le.width ? (le.width + 'px') : '100px';
+
+					if (le.style.height == "")
+						le.style.height = le.height ? (le.height + 'px') : '100px';
+
+					le.style.position = "absolute";
+					ed.addVisual(ed.getBody());
+				}
+
+				ed.execCommand('mceRepaint');
+				ed.nodeChanged();
 			}
 		}
-	},
-
-	getControlHTML : function(cn) {
-		switch (cn) {
-			case "moveforward":
-				return tinyMCE.getButtonHTML(cn, 'lang_layer_forward_desc', '{$pluginurl}/images/moveforward.gif', 'mceMoveForward', true);
-
-			case "movebackward":
-				return tinyMCE.getButtonHTML(cn, 'lang_layer_backward_desc', '{$pluginurl}/images/movebackward.gif', 'mceMoveBackward', true);
-
-			case "absolute":
-				return tinyMCE.getButtonHTML(cn, 'lang_layer_absolute_desc', '{$pluginurl}/images/absolute.gif', 'mceMakeAbsolute', true);
-
-			case "insertlayer":
-				return tinyMCE.getButtonHTML(cn, 'lang_layer_insertlayer_desc', '{$pluginurl}/images/insertlayer.gif', 'mceInsertLayer', true);
-		}
-
-		return "";
-	},
-
-	execCommand : function(editor_id, element, command, user_interface, value) {
-		// Handle commands
-		switch (command) {
-			case "mceInsertLayer":
-				this._insertLayer();
-				return true;
-
-			case "mceMoveForward":
-				this._move(1);
-				return true;
-
-			case "mceMoveBackward":
-				this._move(-1);
-				return true;
-
-			case "mceMakeAbsolute":
-				this._toggleAbsolute();
-				return true;
-		}
-
-		// Pass to next handler in chain
-		return false;
-	},
-
-	handleNodeChange : function(editor_id, node, undo_index, undo_levels, visual_aid, any_selection) {
-		var inst = tinyMCE.getInstanceById(editor_id);
-		var le = this._getParentLayer(inst.getFocusElement());
-		var p = tinyMCE.getParentElement(inst.getFocusElement(), 'div,p,img');
-
-		tinyMCE.switchClass(editor_id + '_absolute', 'mceButtonDisabled');
-		tinyMCE.switchClass(editor_id + '_moveforward', 'mceButtonDisabled');
-		tinyMCE.switchClass(editor_id + '_movebackward', 'mceButtonDisabled');
-
-		if (p)
-			tinyMCE.switchClass(editor_id + '_absolute', 'mceButtonNormal');
-
-		if (le && le.style.position.toLowerCase() == "absolute") {
-			tinyMCE.switchClass(editor_id + '_absolute', 'mceButtonSelected');
-			tinyMCE.switchClass(editor_id + '_moveforward', 'mceButtonNormal');
-			tinyMCE.switchClass(editor_id + '_movebackward', 'mceButtonNormal');
-		}
-	},
-
-	// Private plugin specific methods
-
-	_move : function(d) {
-		var inst = tinyMCE.selectedInstance, i, z = new Array();
-		var le = this._getParentLayer(inst.getFocusElement()), ci = -1, fi = -1;
-		var nl = tinyMCE.selectNodes(inst.getBody(), function(n) {
-			return n.nodeType == 1 && new RegExp('absolute|relative|static', 'gi').test(n.style.position);
-		});
-
-		// Find z-indexes
-		for (i=0; i<nl.length; i++) {
-			z[i] = nl[i].style.zIndex ? parseInt(nl[i].style.zIndex) : 0;
-
-			if (ci < 0 && nl[i] == le)
-				ci = i;
-		}
-
-		if (d < 0) {
-			// Move back
-
-			// Try find a lower one
-			for (i=0; i<z.length; i++) {
-				if (z[i] < z[ci]) {
-					fi = i;
-					break;
-				}
-			}
+	});
 
-			if (fi > -1) {
-				nl[ci].style.zIndex = z[fi];
-				nl[fi].style.zIndex = z[ci];
-			} else {
-				if (z[ci] > 0)
-					nl[ci].style.zIndex = z[ci] - 1;
-			}
-		} else {
-			// Move forward
-
-			// Try find a higher one
-			for (i=0; i<z.length; i++) {
-				if (z[i] > z[ci]) {
-					fi = i;
-					break;
-				}
-			}
-
-			if (fi > -1) {
-				nl[ci].style.zIndex = z[fi];
-				nl[fi].style.zIndex = z[ci];
-			} else
-				nl[ci].style.zIndex = z[ci] + 1;
-		}
-
-		inst.repaint();
-	},
-
-	_getParentLayer : function(n) {
-		return tinyMCE.getParentNode(n, function(n) {
-			return n.nodeType == 1 && new RegExp('absolute|relative|static', 'gi').test(n.style.position);
-		});
-	},
-
-	_insertLayer : function() {
-		var inst = tinyMCE.selectedInstance;
-		var e = tinyMCE.getParentElement(inst.getFocusElement());
-		var p = tinyMCE.getAbsPosition(e);
-		var d = inst.getDoc();
-		var ne = d.createElement('div');
-		var h = inst.selection.getSelectedHTML();
-
-		// Move div
-		ne.style.position = 'absolute';
-		ne.style.left = p.absLeft + 'px';
-		ne.style.top = (p.absTop > 20 ? p.absTop : 20) + 'px';
-		ne.style.width = '100px';
-		ne.style.height = '100px';
-		ne.className = 'mceVisualAid';
-
-		if (!h)
-			h = tinyMCE.getLang('lang_layer_content');
-
-		ne.innerHTML = h;
-
-		// Add it
-		d.body.appendChild(ne);
-	},
-
-	_toggleAbsolute : function() {
-		var inst = tinyMCE.selectedInstance;
-		var le = this._getParentLayer(inst.getFocusElement());
-
-		if (le == null)
-			le = tinyMCE.getParentElement(inst.getFocusElement(), 'div,p,img');
-
-		if (le) {
-			if (le.style.position.toLowerCase() == "absolute") {
-				le.style.position = "";
-				le.style.left = "";
-				le.style.top = "";
-			} else {
-				le.style.position = "absolute";
-
-				if (le.style.left == "")
-					le.style.left = 20 + 'px';
-
-				if (le.style.top == "")
-					le.style.top = 20 + 'px';
-
-				if (le.style.width == "")
-					le.style.width = le.width ? (le.width + 'px') : '100px';
-
-				if (le.style.height == "")
-					le.style.height = le.height ? (le.height + 'px') : '100px';
-
-				tinyMCE.handleVisualAid(inst.getBody(), true, inst.visualAid, inst);
-			}
-
-			inst.repaint();
-			tinyMCE.triggerNodeChange();
-		}
-	}
-};
-
-tinyMCE.addPlugin("layer", TinyMCE_LayerPlugin);
+	// Register plugin
+	tinymce.PluginManager.add('layer', tinymce.plugins.Layer);
+})();
\ No newline at end of file
Binary file includes/clientside/tinymce/plugins/layer/images/absolute.gif has changed
Binary file includes/clientside/tinymce/plugins/layer/images/backward.gif has changed
Binary file includes/clientside/tinymce/plugins/layer/images/forward.gif has changed
Binary file includes/clientside/tinymce/plugins/layer/images/insert_layer.gif has changed
Binary file includes/clientside/tinymce/plugins/layer/images/insertlayer.gif has changed
Binary file includes/clientside/tinymce/plugins/layer/images/movebackward.gif has changed
Binary file includes/clientside/tinymce/plugins/layer/images/moveforward.gif has changed
--- a/includes/clientside/tinymce/plugins/layer/langs/en.js	Fri Feb 22 12:46:51 2008 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,9 +0,0 @@
-// UK lang variables
-
-tinyMCE.addToLang('layer',{
-insertlayer_desc : 'Insert new layer',
-forward_desc : 'Move forward',
-backward_desc : 'Move backward',
-absolute_desc : 'Toggle absolute positioning',
-content : 'New layer...'
-});
--- a/includes/clientside/tinymce/plugins/layer/readme.txt	Fri Feb 22 12:46:51 2008 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1 +0,0 @@
-Check the TinyMCE documentation for details on this plugin.
--- a/includes/clientside/tinymce/plugins/media/css/content.css	Fri Feb 22 12:46:51 2008 -0500
+++ b/includes/clientside/tinymce/plugins/media/css/content.css	Fri Feb 22 12:51:53 2008 -0500
@@ -1,26 +1,6 @@
-.mceItemFlash, .mceItemShockWave, .mceItemQuickTime, .mceItemWindowsMedia, .mceItemRealMedia {
-	border: 1px dotted #cc0000;
-	background-position: center;
-	background-repeat: no-repeat;
-	background-color: #ffffcc;
-}
-
-.mceItemShockWave {
-	background-image: url('../images/shockwave.gif');
-}
-
-.mceItemFlash {
-	background-image: url('../images/flash.gif');
-}
-
-.mceItemQuickTime {
-	background-image: url('../images/quicktime.gif');
-}
-
-.mceItemWindowsMedia {
-	background-image: url('../images/windowsmedia.gif');
-}
-
-.mceItemRealMedia {
-	background-image: url('../images/realmedia.gif');
-}
+.mceItemFlash, .mceItemShockWave, .mceItemQuickTime, .mceItemWindowsMedia, .mceItemRealMedia {border:1px dotted #cc0000; background-position:center; background-repeat:no-repeat; background-color:#ffffcc;}
+.mceItemShockWave {background-image: url(../img/shockwave.gif);}
+.mceItemFlash {background-image:url(../img/flash.gif);}
+.mceItemQuickTime {background-image:url(../img/quicktime.gif);}
+.mceItemWindowsMedia {background-image:url(../img/windowsmedia.gif);}
+.mceItemRealMedia {background-image:url(../img/realmedia.gif);}
--- a/includes/clientside/tinymce/plugins/media/editor_plugin.js	Fri Feb 22 12:46:51 2008 -0500
+++ b/includes/clientside/tinymce/plugins/media/editor_plugin.js	Fri Feb 22 12:51:53 2008 -0500
@@ -1,1 +1,1 @@
-tinyMCE.importPluginLanguagePack('media');var TinyMCE_MediaPlugin={getInfo:function(){return{longname:'Media',author:'Moxiecode Systems AB',authorurl:'http://tinymce.moxiecode.com',infourl:'http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/media',version:tinyMCE.majorVersion+"."+tinyMCE.minorVersion}},initInstance:function(inst){if(inst.hasPlugin('flash')&&!tinyMCE.flashWarn){alert('Flash plugin is deprecated and should not be used together with the media plugin.');tinyMCE.flashWarn=true}if(!tinyMCE.settings['media_skip_plugin_css'])tinyMCE.importCSS(inst.getDoc(),tinyMCE.baseURL+"/plugins/media/css/content.css")},getControlHTML:function(cn){switch(cn){case"media":return tinyMCE.getButtonHTML(cn,'lang_media_desc','{$pluginurl}/images/media.gif','mceMedia')}return""},execCommand:function(editor_id,element,command,user_interface,value){switch(command){case"mceMedia":tinyMCE.openWindow({file:'../../plugins/media/media.htm',width:430+tinyMCE.getLang('lang_media_delta_width',0),height:470+tinyMCE.getLang('lang_media_delta_height',0)},{editor_id:editor_id,inline:"yes"});return true}return false},cleanup:function(type,content,inst){var nl,img,i,ne,d,s,ci;switch(type){case"insert_to_editor":img=tinyMCE.getParam("theme_href")+'/images/spacer.gif';content=content.replace(/<script[^>]*>\s*write(Flash|ShockWave|WindowsMedia|QuickTime|RealMedia)\(\{([^\)]*)\}\);\s*<\/script>/gi,'<img class="mceItem$1" title="$2" src="'+img+'" />');content=content.replace(/<object([^>]*)>/gi,'<div class="mceItemObject" $1>');content=content.replace(/<embed([^>]*)>/gi,'<div class="mceItemObjectEmbed" $1>');content=content.replace(/<\/(object|embed)([^>]*)>/gi,'</div>');content=content.replace(/<param([^>]*)>/gi,'<div $1 class="mceItemParam"></div>');content=content.replace(new RegExp('\\/ class="mceItemParam"><\\/div>','gi'),'class="mceItemParam"></div>');break;case"insert_to_editor_dom":d=inst.getDoc();nl=content.getElementsByTagName("img");for(i=0;i<nl.length;i++){if(/mceItem(Flash|ShockWave|WindowsMedia|QuickTime|RealMedia)/.test(nl[i].className)){nl[i].width=nl[i].title.replace(/.*width:[^0-9]?([0-9]+)%?.*/g,'$1');nl[i].height=nl[i].title.replace(/.*height:[^0-9]?([0-9]+)%?.*/g,'$1');}}nl=tinyMCE.selectElements(content,'DIV',function(n){return tinyMCE.hasCSSClass(n,'mceItemObject')});for(i=0;i<nl.length;i++){ci=tinyMCE.getAttrib(nl[i],"classid").toLowerCase().replace(/\s+/g,'');switch(ci){case'clsid:d27cdb6e-ae6d-11cf-96b8-444553540000':nl[i].parentNode.replaceChild(TinyMCE_MediaPlugin._createImg('mceItemFlash',d,nl[i]),nl[i]);break;case'clsid:166b1bca-3f9c-11cf-8075-444553540000':nl[i].parentNode.replaceChild(TinyMCE_MediaPlugin._createImg('mceItemShockWave',d,nl[i]),nl[i]);break;case'clsid:6bf52a52-394a-11d3-b153-00c04f79faa6':nl[i].parentNode.replaceChild(TinyMCE_MediaPlugin._createImg('mceItemWindowsMedia',d,nl[i]),nl[i]);break;case'clsid:02bf25d5-8c17-4b23-bc80-d3488abddc6b':nl[i].parentNode.replaceChild(TinyMCE_MediaPlugin._createImg('mceItemQuickTime',d,nl[i]),nl[i]);break;case'clsid:cfcdaa03-8be4-11cf-b84b-0020afbbccfa':case'clsid:22d6f312-b0f6-11d0-94ab-0080c74c7e95':case'clsid:05589fa1-c356-11ce-bf01-00aa0055595a':nl[i].parentNode.replaceChild(TinyMCE_MediaPlugin._createImg('mceItemRealMedia',d,nl[i]),nl[i]);break}}nl=tinyMCE.selectNodes(content,function(n){return n.className=='mceItemObjectEmbed'});for(i=0;i<nl.length;i++){switch(tinyMCE.getAttrib(nl[i],'type')){case'application/x-shockwave-flash':TinyMCE_MediaPlugin._createImgFromEmbed(nl[i],d,'mceItemFlash');break;case'application/x-director':TinyMCE_MediaPlugin._createImgFromEmbed(nl[i],d,'mceItemShockWave');break;case'application/x-mplayer2':TinyMCE_MediaPlugin._createImgFromEmbed(nl[i],d,'mceItemWindowsMedia');break;case'video/quicktime':TinyMCE_MediaPlugin._createImgFromEmbed(nl[i],d,'mceItemQuickTime');break;case'audio/x-pn-realaudio-plugin':TinyMCE_MediaPlugin._createImgFromEmbed(nl[i],d,'mceItemRealMedia');break}}break;case"get_from_editor":var startPos=-1,endPos,attribs,chunkBefore,chunkAfter,embedHTML,at,pl,cb,mt,ex;while((startPos=content.indexOf('<img',startPos+1))!=-1){endPos=content.indexOf('/>',startPos);attribs=TinyMCE_MediaPlugin._parseAttributes(content.substring(startPos+4,endPos));if(!/mceItem(Flash|ShockWave|WindowsMedia|QuickTime|RealMedia)/.test(attribs['class']))continue;endPos+=2;at=attribs['title'];if(at){at=at.replace(/&(#39|apos);/g,"'");at=at.replace(/&#quot;/g,'"');try{pl=eval('x={'+at+'};')}catch(ex){pl={}}}if(!tinyMCE.getParam('media_use_script',false)){switch(attribs['class']){case'mceItemFlash':ci='d27cdb6e-ae6d-11cf-96b8-444553540000';cb='http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,40,0';mt='application/x-shockwave-flash';break;case'mceItemShockWave':ci='166B1BCA-3F9C-11CF-8075-444553540000';cb='http://download.macromedia.com/pub/shockwave/cabs/director/sw.cab#version=8,5,1,0';mt='application/x-director';break;case'mceItemWindowsMedia':ci=tinyMCE.getParam('media_wmp6_compatible')?'05589FA1-C356-11CE-BF01-00AA0055595A':'6BF52A52-394A-11D3-B153-00C04F79FAA6';cb='http://activex.microsoft.com/activex/controls/mplayer/en/nsmp2inf.cab#Version=5,1,52,701';mt='application/x-mplayer2';break;case'mceItemQuickTime':ci='02BF25D5-8C17-4B23-BC80-D3488ABDDC6B';cb='http://www.apple.com/qtactivex/qtplugin.cab#version=6,0,2,0';mt='video/quicktime';break;case'mceItemRealMedia':ci='CFCDAA03-8BE4-11cf-B84B-0020AFBBCCFA';cb='http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,40,0';mt='audio/x-pn-realaudio-plugin';break}if(!tinyMCE.getParam("relative_urls"))pl.src=tinyMCE.convertRelativeToAbsoluteURL(tinyMCE.settings['base_href'],pl.src);embedHTML=TinyMCE_MediaPlugin._getEmbed(ci,cb,mt,pl,attribs)}else{switch(attribs['class']){case'mceItemFlash':s='writeFlash';break;case'mceItemShockWave':s='writeShockWave';break;case'mceItemWindowsMedia':s='writeWindowsMedia';break;case'mceItemQuickTime':s='writeQuickTime';break;case'mceItemRealMedia':s='writeRealMedia';break}if(attribs.width)at=at.replace(/width:[^0-9]?[0-9]+%?[^0-9]?/g,"width:'"+attribs.width+"'");if(attribs.height)at=at.replace(/height:[^0-9]?[0-9]+%?[^0-9]?/g,"height:'"+attribs.height+"'");if(!tinyMCE.getParam("relative_urls")){pl.src=tinyMCE.convertRelativeToAbsoluteURL(tinyMCE.settings['base_href'],pl.src);at=at.replace(new RegExp("src:'[^']*'","g"),"src:'"+pl.src+"'")}embedHTML='<script type="text/javascript">'+s+'({'+at+'});</script>'}chunkBefore=content.substring(0,startPos);chunkAfter=content.substring(endPos);content=chunkBefore+embedHTML+chunkAfter}break}return content},handleNodeChange:function(editor_id,node,undo_index,undo_levels,visual_aid,any_selection){if(node==null)return;do{if(node.nodeName=="IMG"&&/mceItem(Flash|ShockWave|WindowsMedia|QuickTime|RealMedia)/.test(tinyMCE.getAttrib(node,'class'))){tinyMCE.switchClass(editor_id+'_media','mceButtonSelected');return true}}while((node=node.parentNode));tinyMCE.switchClass(editor_id+'_media','mceButtonNormal');return true},_createImgFromEmbed:function(n,d,cl){var ne,at,i,ti='',an;ne=d.createElement('img');ne.src=tinyMCE.getParam("theme_href")+'/images/spacer.gif';ne.width=tinyMCE.getAttrib(n,'width');ne.height=tinyMCE.getAttrib(n,'height');ne.className=cl;at=n.attributes;for(i=0;i<at.length;i++){if(at[i].specified&&at[i].nodeValue){an=at[i].nodeName.toLowerCase();if(an=='src')continue;if(an=='mce_src')an='src';if(an.indexOf('mce_')==-1&&!new RegExp('^(class|type)$').test(an))ti+=an.toLowerCase()+':\''+at[i].nodeValue+"',"}}ti=ti.length>0?ti.substring(0,ti.length-1):ti;ne.title=ti;n.parentNode.replaceChild(ne,n)},_createImg:function(cl,d,n){var i,nl,ti="",an,av,al=new Array();ne=d.createElement('img');ne.src=tinyMCE.getParam("theme_href")+'/images/spacer.gif';ne.width=tinyMCE.getAttrib(n,'width');ne.height=tinyMCE.getAttrib(n,'height');ne.className=cl;al.id=tinyMCE.getAttrib(n,'id');al.name=tinyMCE.getAttrib(n,'name');al.width=tinyMCE.getAttrib(n,'width');al.height=tinyMCE.getAttrib(n,'height');al.bgcolor=tinyMCE.getAttrib(n,'bgcolor');al.align=tinyMCE.getAttrib(n,'align');al.class_name=tinyMCE.getAttrib(n,'mce_class');nl=n.getElementsByTagName('div');for(i=0;i<nl.length;i++){av=tinyMCE.getAttrib(nl[i],'value');av=av.replace(new RegExp('\\\\','g'),'\\\\');av=av.replace(new RegExp('"','g'),'\\"');av=av.replace(new RegExp("'",'g'),"\\'");an=tinyMCE.getAttrib(nl[i],'name');al[an]=av}if(al.movie){al.src=al.movie;al.movie=null}for(an in al){if(al[an]!=null&&typeof(al[an])!="function"&&al[an]!='')ti+=an.toLowerCase()+':\''+al[an]+"',"}ti=ti.length>0?ti.substring(0,ti.length-1):ti;ne.title=ti;return ne},_getEmbed:function(cls,cb,mt,p,at){var h='',n;p.width=at.width?at.width:p.width;p.height=at.height?at.height:p.height;h+='<object classid="clsid:'+cls+'" codebase="'+cb+'"';h+=typeof(p.id)!="undefined"?' id="'+p.id+'"':'';h+=typeof(p.name)!="undefined"?' name="'+p.name+'"':'';h+=typeof(p.width)!="undefined"?' width="'+p.width+'"':'';h+=typeof(p.height)!="undefined"?' height="'+p.height+'"':'';h+=typeof(p.align)!="undefined"?' align="'+p.align+'"':'';h+='>';for(n in p){if(p[n]&&typeof(p[n])!="function"){h+='<param name="'+n+'" value="'+p[n]+'" />';if(n=='src'&&p[n].indexOf('://')!=-1&&mt=='application/x-mplayer2')h+='<param name="url" value="'+p[n]+'" />'}}h+='<embed type="'+mt+'"';for(n in p){if(typeof(p[n])=="function")continue;if(!(n=='url'&&mt=='application/x-mplayer2'))h+=' '+n+'="'+p[n]+'"'}h+='></embed></object>';return h},_parseAttributes:function(attribute_string){var attributeName="",endChr='"';var attributeValue="";var withInName;var withInValue;var attributes=new Array();var whiteSpaceRegExp=new RegExp('^[ \n\r\t]+','g');if(attribute_string==null||attribute_string.length<2)return null;withInName=withInValue=false;for(var i=0;i<attribute_string.length;i++){var chr=attribute_string.charAt(i);if((chr=='"'||chr=="'")&&!withInValue){withInValue=true;endChr=chr}else if(chr==endChr&&withInValue){withInValue=false;var pos=attributeName.lastIndexOf(' ');if(pos!=-1)attributeName=attributeName.substring(pos+1);attributes[attributeName.toLowerCase()]=attributeValue.substring(1);attributeName="";attributeValue=""}else if(!whiteSpaceRegExp.test(chr)&&!withInName&&!withInValue)withInName=true;if(chr=='='&&withInName)withInName=false;if(withInName)attributeName+=chr;if(withInValue)attributeValue+=chr}return attributes}};tinyMCE.addPlugin("media",TinyMCE_MediaPlugin);
\ No newline at end of file
+(function(){var each=tinymce.each;tinymce.create('tinymce.plugins.MediaPlugin',{init:function(ed,url){var t=this;t.editor=ed;t.url=url;function isMediaElm(n){return/^(mceItemFlash|mceItemShockWave|mceItemWindowsMedia|mceItemQuickTime|mceItemRealMedia)$/.test(n.className);};ed.addCommand('mceMedia',function(){ed.windowManager.open({file:url+'/media.htm',width:430+parseInt(ed.getLang('media.delta_width',0)),height:470+parseInt(ed.getLang('media.delta_height',0)),inline:1},{plugin_url:url});});ed.addButton('media',{title:'media.desc',cmd:'mceMedia'});ed.onNodeChange.add(function(ed,cm,n){cm.setActive('media',n.nodeName=='IMG'&&isMediaElm(n));});ed.onInit.add(function(){var lo={mceItemFlash:'flash',mceItemShockWave:'shockwave',mceItemWindowsMedia:'windowsmedia',mceItemQuickTime:'quicktime',mceItemRealMedia:'realmedia'};ed.dom.loadCSS(url+"/css/content.css");if(ed.theme.onResolveName){ed.theme.onResolveName.add(function(th,o){if(o.name=='img'){each(lo,function(v,k){if(ed.dom.hasClass(o.node,k)){o.name=v;o.title=ed.dom.getAttrib(o.node,'title');return false;}});}});}if(ed&&ed.plugins.contextmenu){ed.plugins.contextmenu.onContextMenu.add(function(th,m,e){if(e.nodeName=='IMG'&&/mceItem(Flash|ShockWave|WindowsMedia|QuickTime|RealMedia)/.test(e.className)){m.add({title:'media.edit',icon:'media',cmd:'mceMedia'});}});}});ed.onBeforeSetContent.add(function(ed,o){var h=o.content;h=h.replace(/<script[^>]*>\s*write(Flash|ShockWave|WindowsMedia|QuickTime|RealMedia)\(\{([^\)]*)\}\);\s*<\/script>/gi,function(a,b,c){var o=eval("({"+c+"})");return'<img class="mceItem'+b+'" title="'+ed.dom.encode(c)+'" src="'+url+'/img/trans.gif" width="'+o.width+'" height="'+o.height+'" />'});h=h.replace(/<object([^>]*)>/gi,'<span class="mceItemObject" $1>');h=h.replace(/<embed([^>]*)>/gi,'<span class="mceItemEmbed" $1>');h=h.replace(/<\/(object|embed)([^>]*)>/gi,'</span>');h=h.replace(/<param([^>]*)>/gi,function(a,b){return'<span '+b.replace(/value=/g,'_value=')+' class="mceItemParam"></span>'});h=h.replace(/\/ class=\"mceItemParam\"><\/span>/gi,'class="mceItemParam"></span>');o.content=h;});ed.onSetContent.add(function(){t._spansToImgs(ed.getBody());});ed.onPreProcess.add(function(ed,o){var dom=ed.dom;if(o.set){t._spansToImgs(o.node);each(dom.select('IMG',o.node),function(n){var p;if(isMediaElm(n)){p=t._parse(n.title);dom.setAttrib(n,'width',dom.getAttrib(n,'width',p.width||100));dom.setAttrib(n,'height',dom.getAttrib(n,'height',p.height||100));}});}if(o.get){each(dom.select('IMG',o.node),function(n){var ci,cb,mt;if(ed.getParam('media_use_script')){if(isMediaElm(n))n.className=n.className.replace(/mceItem/g,'mceTemp');return;}switch(n.className){case'mceItemFlash':ci='d27cdb6e-ae6d-11cf-96b8-444553540000';cb='http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,40,0';mt='application/x-shockwave-flash';break;case'mceItemShockWave':ci='166b1bca-3f9c-11cf-8075-444553540000';cb='http://download.macromedia.com/pub/shockwave/cabs/director/sw.cab#version=8,5,1,0';mt='application/x-director';break;case'mceItemWindowsMedia':ci=ed.getParam('media_wmp6_compatible')?'05589fa1-c356-11ce-bf01-00aa0055595a':'6bf52a52-394a-11d3-b153-00c04f79faa6';cb='http://activex.microsoft.com/activex/controls/mplayer/en/nsmp2inf.cab#Version=5,1,52,701';mt='application/x-mplayer2';break;case'mceItemQuickTime':ci='02bf25d5-8c17-4b23-bc80-d3488abddc6b';cb='http://www.apple.com/qtactivex/qtplugin.cab#version=6,0,2,0';mt='video/quicktime';break;case'mceItemRealMedia':ci='cfcdaa03-8be4-11cf-b84b-0020afbbccfa';cb='http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,40,0';mt='audio/x-pn-realaudio-plugin';break;}if(ci){dom.replace(t._buildObj({classid:ci,codebase:cb,type:mt},n),n);}});}});ed.onPostProcess.add(function(ed,o){o.content=o.content.replace(/_value=/g,'value=');});if(ed.getParam('media_use_script')){function getAttr(s,n){n=new RegExp(n+'=\"([^\"]+)\"','g').exec(s);return n?ed.dom.decode(n[1]):'';};ed.onPostProcess.add(function(ed,o){o.content=o.content.replace(/<img[^>]+>/g,function(im){var cl=getAttr(im,'class');if(/^(mceTempFlash|mceTempShockWave|mceTempWindowsMedia|mceTempQuickTime|mceTempRealMedia)$/.test(cl)){at=t._parse(getAttr(im,'title'));at.width=getAttr(im,'width');at.height=getAttr(im,'height');im='<script type="text/javascript">write'+cl.substring(7)+'({'+t._serialize(at)+'});</script>';}return im;});});}},getInfo:function(){return{longname:'Media',author:'Moxiecode Systems AB',authorurl:'http://tinymce.moxiecode.com',infourl:'http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/media',version:tinymce.majorVersion+"."+tinymce.minorVersion};},_buildObj:function(o,n){var ob,ed=this.editor,dom=ed.dom,p=this._parse(n.title);p.width=o.width=dom.getAttrib(n,'width')||100;p.height=o.height=dom.getAttrib(n,'height')||100;ob=dom.create('span',{mce_name:'object',classid:"clsid:"+o.classid,codebase:o.codebase,width:o.width,height:o.height});if(p.src)p.src=ed.convertURL(p.src,'src',n);each(p,function(v,k){if(v&&!/^(width|height|codebase|classid)$/.test(k))dom.add(ob,'span',{mce_name:'param',name:k,'_value':v});});dom.add(ob,'span',tinymce.extend({mce_name:'embed',type:o.type},p));return ob;},_spansToImgs:function(p){var t=this,dom=t.editor.dom,im,ci;each(dom.select('span',p),function(n){if(dom.getAttrib(n,'class')=='mceItemObject'){ci=dom.getAttrib(n,"classid").toLowerCase().replace(/\s+/g,'');switch(ci){case'clsid:d27cdb6e-ae6d-11cf-96b8-444553540000':dom.replace(t._createImg('mceItemFlash',n),n);break;case'clsid:166b1bca-3f9c-11cf-8075-444553540000':dom.replace(t._createImg('mceItemShockWave',n),n);break;case'clsid:6bf52a52-394a-11d3-b153-00c04f79faa6':case'clsid:22d6f312-b0f6-11d0-94ab-0080c74c7e95':case'clsid:05589fa1-c356-11ce-bf01-00aa0055595a':dom.replace(t._createImg('mceItemWindowsMedia',n),n);break;case'clsid:02bf25d5-8c17-4b23-bc80-d3488abddc6b':dom.replace(t._createImg('mceItemQuickTime',n),n);break;case'clsid:cfcdaa03-8be4-11cf-b84b-0020afbbccfa':dom.replace(t._createImg('mceItemRealMedia',n),n);break;default:dom.replace(t._createImg('mceItemFlash',n),n);}}});},_createImg:function(cl,n){var im,dom=this.editor.dom,pa={},ti='';im=dom.create('img',{src:this.url+'/img/trans.gif',width:dom.getAttrib(n,'width')||100,height:dom.getAttrib(n,'height')||100,'class':cl});each(['id','name','width','height','bgcolor','align'],function(n){var v=dom.getAttrib(n,'align');if(v)pa[v]=v;});each(dom.select('span',n),function(n){if(dom.hasClass(n,'mceItemParam'))pa[dom.getAttrib(n,'name')]=dom.getAttrib(n,'_value');});if(pa.movie){pa.src=pa.movie;delete pa.movie;}delete pa.width;delete pa.height;im.title=this._serialize(pa);return im;},_parse:function(s){return tinymce.util.JSON.parse('{'+s+'}');},_serialize:function(o){return tinymce.util.JSON.serialize(o).replace(/[{}]/g,'');}});tinymce.PluginManager.add('media',tinymce.plugins.MediaPlugin);})();
\ No newline at end of file
--- a/includes/clientside/tinymce/plugins/media/editor_plugin_src.js	Fri Feb 22 12:46:51 2008 -0500
+++ b/includes/clientside/tinymce/plugins/media/editor_plugin_src.js	Fri Feb 22 12:51:53 2008 -0500
@@ -1,174 +1,128 @@
 /**
- * $Id: editor_plugin_src.js 201 2007-02-12 15:56:56Z spocke $
+ * $Id: editor_plugin_src.js 561 2008-01-23 15:18:19Z spocke $
  *
  * @author Moxiecode
- * @copyright Copyright © 2004-2007, Moxiecode Systems AB, All rights reserved.
+ * @copyright Copyright © 2004-2008, Moxiecode Systems AB, All rights reserved.
  */
 
-/* Import plugin specific language pack */
-tinyMCE.importPluginLanguagePack('media');
+(function() {
+	var each = tinymce.each;
 
-var TinyMCE_MediaPlugin = {
-	getInfo : function() {
-		return {
-			longname : 'Media',
-			author : 'Moxiecode Systems AB',
-			authorurl : 'http://tinymce.moxiecode.com',
-			infourl : 'http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/media',
-			version : tinyMCE.majorVersion + "." + tinyMCE.minorVersion
-		};
-	},
+	tinymce.create('tinymce.plugins.MediaPlugin', {
+		init : function(ed, url) {
+			var t = this;
+			
+			t.editor = ed;
+			t.url = url;
 
-	initInstance : function(inst) {
-		// Warn if user has flash plugin and media plugin at the same time
-		if (inst.hasPlugin('flash') && !tinyMCE.flashWarn) {
-			alert('Flash plugin is deprecated and should not be used together with the media plugin.');
-			tinyMCE.flashWarn = true;
-		}
+			function isMediaElm(n) {
+				return /^(mceItemFlash|mceItemShockWave|mceItemWindowsMedia|mceItemQuickTime|mceItemRealMedia)$/.test(n.className);
+			};
 
-		if (!tinyMCE.settings['media_skip_plugin_css'])
-			tinyMCE.importCSS(inst.getDoc(), tinyMCE.baseURL + "/plugins/media/css/content.css");
-	},
-
-	getControlHTML : function(cn) {
-		switch (cn) {
-			case "media":
-				return tinyMCE.getButtonHTML(cn, 'lang_media_desc', '{$pluginurl}/images/media.gif', 'mceMedia');
-		}
-
-		return "";
-	},
+			// Register commands
+			ed.addCommand('mceMedia', function() {
+				ed.windowManager.open({
+					file : url + '/media.htm',
+					width : 430 + parseInt(ed.getLang('media.delta_width', 0)),
+					height : 470 + parseInt(ed.getLang('media.delta_height', 0)),
+					inline : 1
+				}, {
+					plugin_url : url
+				});
+			});
 
-	execCommand : function(editor_id, element, command, user_interface, value) {
-		// Handle commands
-		switch (command) {
-			case "mceMedia":
-				tinyMCE.openWindow({
-						file : '../../plugins/media/media.htm',
-						width : 430 + tinyMCE.getLang('lang_media_delta_width', 0),
-						height : 470 + tinyMCE.getLang('lang_media_delta_height', 0)
-					}, {
-						editor_id : editor_id,
-						inline : "yes"
-				});
+			// Register buttons
+			ed.addButton('media', {title : 'media.desc', cmd : 'mceMedia'});
 
-				return true;
-	   }
-
-	   // Pass to next handler in chain
-	   return false;
-	},
+			ed.onNodeChange.add(function(ed, cm, n) {
+				cm.setActive('media', n.nodeName == 'IMG' && isMediaElm(n));
+			});
 
-	cleanup : function(type, content, inst) {
-		var nl, img, i, ne, d, s, ci;
+			ed.onInit.add(function() {
+				var lo = {
+					mceItemFlash : 'flash',
+					mceItemShockWave : 'shockwave',
+					mceItemWindowsMedia : 'windowsmedia',
+					mceItemQuickTime : 'quicktime',
+					mceItemRealMedia : 'realmedia'
+				};
+
+				ed.dom.loadCSS(url + "/css/content.css");
 
-		switch (type) {
-			case "insert_to_editor":
-				img = tinyMCE.getParam("theme_href") + '/images/spacer.gif';
-				content = content.replace(/<script[^>]*>\s*write(Flash|ShockWave|WindowsMedia|QuickTime|RealMedia)\(\{([^\)]*)\}\);\s*<\/script>/gi, '<img class="mceItem$1" title="$2" src="' + img + '" />');
-				content = content.replace(/<object([^>]*)>/gi, '<div class="mceItemObject" $1>');
-				content = content.replace(/<embed([^>]*)>/gi, '<div class="mceItemObjectEmbed" $1>');
-				content = content.replace(/<\/(object|embed)([^>]*)>/gi, '</div>');
-				content = content.replace(/<param([^>]*)>/gi, '<div $1 class="mceItemParam"></div>');
-				content = content.replace(new RegExp('\\/ class="mceItemParam"><\\/div>', 'gi'), 'class="mceItemParam"></div>');
-				break;
-
-			case "insert_to_editor_dom":
-				d = inst.getDoc();
-				nl = content.getElementsByTagName("img");
-				for (i=0; i<nl.length; i++) {
-					if (/mceItem(Flash|ShockWave|WindowsMedia|QuickTime|RealMedia)/.test(nl[i].className)) {
-						nl[i].width = nl[i].title.replace(/.*width:[^0-9]?([0-9]+)%?.*/g, '$1');
-						nl[i].height = nl[i].title.replace(/.*height:[^0-9]?([0-9]+)%?.*/g, '$1');
-						//nl[i].align = nl[i].title.replace(/.*align:([a-z]+).*/gi, '$1');
-					}
+				if (ed.theme.onResolveName) {
+					ed.theme.onResolveName.add(function(th, o) {
+						if (o.name == 'img') {
+							each(lo, function(v, k) {
+								if (ed.dom.hasClass(o.node, k)) {
+									o.name = v;
+									o.title = ed.dom.getAttrib(o.node, 'title');
+									return false;
+								}
+							});
+						}
+					});
 				}
 
-				nl = tinyMCE.selectElements(content, 'DIV', function (n) {return tinyMCE.hasCSSClass(n, 'mceItemObject');});
-				for (i=0; i<nl.length; i++) {
-					ci = tinyMCE.getAttrib(nl[i], "classid").toLowerCase().replace(/\s+/g, '');
+				if (ed && ed.plugins.contextmenu) {
+					ed.plugins.contextmenu.onContextMenu.add(function(th, m, e) {
+						if (e.nodeName == 'IMG' && /mceItem(Flash|ShockWave|WindowsMedia|QuickTime|RealMedia)/.test(e.className)) {
+							m.add({title : 'media.edit', icon : 'media', cmd : 'mceMedia'});
+						}
+					});
+				}
+			});
 
-					switch (ci) {
-						case 'clsid:d27cdb6e-ae6d-11cf-96b8-444553540000':
-							nl[i].parentNode.replaceChild(TinyMCE_MediaPlugin._createImg('mceItemFlash', d, nl[i]), nl[i]);
-							break;
+			ed.onBeforeSetContent.add(function(ed, o) {
+				var h = o.content;
 
-						case 'clsid:166b1bca-3f9c-11cf-8075-444553540000':
-							nl[i].parentNode.replaceChild(TinyMCE_MediaPlugin._createImg('mceItemShockWave', d, nl[i]), nl[i]);
-							break;
+				h = h.replace(/<script[^>]*>\s*write(Flash|ShockWave|WindowsMedia|QuickTime|RealMedia)\(\{([^\)]*)\}\);\s*<\/script>/gi, function(a, b, c) {
+					var o = eval("({" + c + "})");
+
+					return '<img class="mceItem' + b + '" title="' + ed.dom.encode(c) + '" src="' + url + '/img/trans.gif" width="' + o.width + '" height="' + o.height + '" />'
+				});
 
-						case 'clsid:6bf52a52-394a-11d3-b153-00c04f79faa6':
-							nl[i].parentNode.replaceChild(TinyMCE_MediaPlugin._createImg('mceItemWindowsMedia', d, nl[i]), nl[i]);
-							break;
+				h = h.replace(/<object([^>]*)>/gi, '<span class="mceItemObject" $1>');
+				h = h.replace(/<embed([^>]*)>/gi, '<span class="mceItemEmbed" $1>');
+				h = h.replace(/<\/(object|embed)([^>]*)>/gi, '</span>');
+				h = h.replace(/<param([^>]*)>/gi, function(a, b) {return '<span ' + b.replace(/value=/g, '_value=') + ' class="mceItemParam"></span>'});
+				h = h.replace(/\/ class=\"mceItemParam\"><\/span>/gi, 'class="mceItemParam"></span>');
+
+				o.content = h;
+			});
+
+			ed.onSetContent.add(function() {
+				t._spansToImgs(ed.getBody());
+			});
 
-						case 'clsid:02bf25d5-8c17-4b23-bc80-d3488abddc6b':
-							nl[i].parentNode.replaceChild(TinyMCE_MediaPlugin._createImg('mceItemQuickTime', d, nl[i]), nl[i]);
-							break;
+			ed.onPreProcess.add(function(ed, o) {
+				var dom = ed.dom;
+
+				if (o.set) {
+					t._spansToImgs(o.node);
 
-						case 'clsid:cfcdaa03-8be4-11cf-b84b-0020afbbccfa':
-						case 'clsid:22d6f312-b0f6-11d0-94ab-0080c74c7e95':
-						case 'clsid:05589fa1-c356-11ce-bf01-00aa0055595a':
-							nl[i].parentNode.replaceChild(TinyMCE_MediaPlugin._createImg('mceItemRealMedia', d, nl[i]), nl[i]);
-							break;
-					}
+					each(dom.select('IMG', o.node), function(n) {
+						var p;
+
+						if (isMediaElm(n)) {
+							p = t._parse(n.title);
+							dom.setAttrib(n, 'width', dom.getAttrib(n, 'width', p.width || 100));
+							dom.setAttrib(n, 'height', dom.getAttrib(n, 'height', p.height || 100));
+						}
+					});
 				}
 
-				// Handle embed (if any)
-				nl = tinyMCE.selectNodes(content, function (n) {return n.className == 'mceItemObjectEmbed';});
-				for (i=0; i<nl.length; i++) {
-					switch (tinyMCE.getAttrib(nl[i], 'type')) {
-						case 'application/x-shockwave-flash':
-							TinyMCE_MediaPlugin._createImgFromEmbed(nl[i], d, 'mceItemFlash');
-							break;
-
-						case 'application/x-director':
-							TinyMCE_MediaPlugin._createImgFromEmbed(nl[i], d, 'mceItemShockWave');
-							break;
-
-						case 'application/x-mplayer2':
-							TinyMCE_MediaPlugin._createImgFromEmbed(nl[i], d, 'mceItemWindowsMedia');
-							break;
-
-						case 'video/quicktime':
-							TinyMCE_MediaPlugin._createImgFromEmbed(nl[i], d, 'mceItemQuickTime');
-							break;
-
-						case 'audio/x-pn-realaudio-plugin':
-							TinyMCE_MediaPlugin._createImgFromEmbed(nl[i], d, 'mceItemRealMedia');
-							break;
-					}
-				}
-				break;
+				if (o.get) {
+					each(dom.select('IMG', o.node), function(n) {
+						var ci, cb, mt;
 
-			case "get_from_editor":
-				var startPos = -1, endPos, attribs, chunkBefore, chunkAfter, embedHTML, at, pl, cb, mt, ex;
-
-				while ((startPos = content.indexOf('<img', startPos+1)) != -1) {
-					endPos = content.indexOf('/>', startPos);
-					attribs = TinyMCE_MediaPlugin._parseAttributes(content.substring(startPos + 4, endPos));
-
-					// Is not flash, skip it
-					if (!/mceItem(Flash|ShockWave|WindowsMedia|QuickTime|RealMedia)/.test(attribs['class']))
-						continue;
-
-					endPos += 2;
+						if (ed.getParam('media_use_script')) {
+							if (isMediaElm(n))
+								n.className = n.className.replace(/mceItem/g, 'mceTemp');
 
-					// Parse attributes
-					at = attribs['title'];
-					if (at) {
-						at = at.replace(/&(#39|apos);/g, "'");
-						at = at.replace(/&#quot;/g, '"');
+							return;
+						}
 
-						try {
-							pl = eval('x={' + at + '};');
-						} catch (ex) {
-							pl = {};
-						}
-					}
-
-					// Use object/embed
-					if (!tinyMCE.getParam('media_use_script', false)) {
-						switch (attribs['class']) {
+						switch (n.className) {
 							case 'mceItemFlash':
 								ci = 'd27cdb6e-ae6d-11cf-96b8-444553540000';
 								cb = 'http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,40,0';
@@ -176,260 +130,194 @@
 								break;
 
 							case 'mceItemShockWave':
-								ci = '166B1BCA-3F9C-11CF-8075-444553540000';
+								ci = '166b1bca-3f9c-11cf-8075-444553540000';
 								cb = 'http://download.macromedia.com/pub/shockwave/cabs/director/sw.cab#version=8,5,1,0';
 								mt = 'application/x-director';
 								break;
 
 							case 'mceItemWindowsMedia':
-								ci = tinyMCE.getParam('media_wmp6_compatible') ? '05589FA1-C356-11CE-BF01-00AA0055595A' : '6BF52A52-394A-11D3-B153-00C04F79FAA6';
+								ci = ed.getParam('media_wmp6_compatible') ? '05589fa1-c356-11ce-bf01-00aa0055595a' : '6bf52a52-394a-11d3-b153-00c04f79faa6';
 								cb = 'http://activex.microsoft.com/activex/controls/mplayer/en/nsmp2inf.cab#Version=5,1,52,701';
 								mt = 'application/x-mplayer2';
 								break;
 
 							case 'mceItemQuickTime':
-								ci = '02BF25D5-8C17-4B23-BC80-D3488ABDDC6B';
+								ci = '02bf25d5-8c17-4b23-bc80-d3488abddc6b';
 								cb = 'http://www.apple.com/qtactivex/qtplugin.cab#version=6,0,2,0';
 								mt = 'video/quicktime';
 								break;
 
 							case 'mceItemRealMedia':
-								ci = 'CFCDAA03-8BE4-11cf-B84B-0020AFBBCCFA';
+								ci = 'cfcdaa03-8be4-11cf-b84b-0020afbbccfa';
 								cb = 'http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,40,0';
 								mt = 'audio/x-pn-realaudio-plugin';
 								break;
 						}
 
-						// Force absolute URL
-						if (!tinyMCE.getParam("relative_urls"))
-							pl.src = tinyMCE.convertRelativeToAbsoluteURL(tinyMCE.settings['base_href'], pl.src);
+						if (ci) {
+							dom.replace(t._buildObj({
+								classid : ci,
+								codebase : cb,
+								type : mt
+							}, n), n);
+						}
+					});
+				}
+			});
 
-						embedHTML = TinyMCE_MediaPlugin._getEmbed(ci, cb, mt, pl, attribs);
-					} else {
-						// Use script version
-						switch (attribs['class']) {
-							case 'mceItemFlash':
-								s = 'writeFlash';
-								break;
-
-							case 'mceItemShockWave':
-								s = 'writeShockWave';
-								break;
-
-							case 'mceItemWindowsMedia':
-								s = 'writeWindowsMedia';
-								break;
+			ed.onPostProcess.add(function(ed, o) {
+				o.content = o.content.replace(/_value=/g, 'value=');
+			});
 
-							case 'mceItemQuickTime':
-								s = 'writeQuickTime';
-								break;
+			if (ed.getParam('media_use_script')) {
+				function getAttr(s, n) {
+					n = new RegExp(n + '=\"([^\"]+)\"', 'g').exec(s);
 
-							case 'mceItemRealMedia':
-								s = 'writeRealMedia';
-								break;
-						}
+					return n ? ed.dom.decode(n[1]) : '';
+				};
 
-						if (attribs.width)
-							at = at.replace(/width:[^0-9]?[0-9]+%?[^0-9]?/g, "width:'" + attribs.width + "'");
+				ed.onPostProcess.add(function(ed, o) {
+					o.content = o.content.replace(/<img[^>]+>/g, function(im) {
+						var cl = getAttr(im, 'class');
 
-						if (attribs.height)
-							at = at.replace(/height:[^0-9]?[0-9]+%?[^0-9]?/g, "height:'" + attribs.height + "'");
-
-						// Force absolute URL
-						if (!tinyMCE.getParam("relative_urls")) {
-							pl.src = tinyMCE.convertRelativeToAbsoluteURL(tinyMCE.settings['base_href'], pl.src);
-							at = at.replace(new RegExp("src:'[^']*'", "g"), "src:'" + pl.src + "'");
+						if (/^(mceTempFlash|mceTempShockWave|mceTempWindowsMedia|mceTempQuickTime|mceTempRealMedia)$/.test(cl)) {
+							at = t._parse(getAttr(im, 'title'));
+							at.width = getAttr(im, 'width');
+							at.height = getAttr(im, 'height');
+							im = '<script type="text/javascript">write' + cl.substring(7) + '({' + t._serialize(at) + '});</script>';
 						}
 
-						embedHTML = '<script type="text/javascript">' + s + '({' + at + '});</script>';
-					}
-
-					// Insert embed/object chunk
-					chunkBefore = content.substring(0, startPos);
-					chunkAfter = content.substring(endPos);
-					content = chunkBefore + embedHTML + chunkAfter;
-				}
-				break;
-		}
-
-		return content;
-	},
-
-	handleNodeChange : function(editor_id, node, undo_index, undo_levels, visual_aid, any_selection) {
-		if (node == null)
-			return;
+						return im;
+					});
+				});
+			}
+		},
 
-		do {
-			if (node.nodeName == "IMG" && /mceItem(Flash|ShockWave|WindowsMedia|QuickTime|RealMedia)/.test(tinyMCE.getAttrib(node, 'class'))) {
-				tinyMCE.switchClass(editor_id + '_media', 'mceButtonSelected');
-				return true;
-			}
-		} while ((node = node.parentNode));
-
-		tinyMCE.switchClass(editor_id + '_media', 'mceButtonNormal');
-
-		return true;
-	},
+		getInfo : function() {
+			return {
+				longname : 'Media',
+				author : 'Moxiecode Systems AB',
+				authorurl : 'http://tinymce.moxiecode.com',
+				infourl : 'http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/media',
+				version : tinymce.majorVersion + "." + tinymce.minorVersion
+			};
+		},
 
-	_createImgFromEmbed : function(n, d, cl) {
-		var ne, at, i, ti = '', an;
+		// Private methods
 
-		ne = d.createElement('img');
-		ne.src = tinyMCE.getParam("theme_href") + '/images/spacer.gif';
-		ne.width = tinyMCE.getAttrib(n, 'width');
-		ne.height = tinyMCE.getAttrib(n, 'height');
-		ne.className = cl;
+		_buildObj : function(o, n) {
+			var ob, ed = this.editor, dom = ed.dom, p = this._parse(n.title);
 
-		at = n.attributes;
-		for (i=0; i<at.length; i++) {
-			if (at[i].specified && at[i].nodeValue) {
-				an = at[i].nodeName.toLowerCase();
+			p.width = o.width = dom.getAttrib(n, 'width') || 100;
+			p.height = o.height = dom.getAttrib(n, 'height') || 100;
 
-				if (an == 'src')
-					continue;
-
-				if (an == 'mce_src')
-					an = 'src';
+			ob = dom.create('span', {
+				mce_name : 'object',
+				classid : "clsid:" + o.classid,
+				codebase : o.codebase,
+				width : o.width,
+				height : o.height
+			});
 
-				if (an.indexOf('mce_') == -1 && !new RegExp('^(class|type)$').test(an))
-					ti += an.toLowerCase() + ':\'' + at[i].nodeValue + "',";
-			}
-		}
+			if (p.src)
+				p.src = ed.convertURL(p.src, 'src', n);
 
-		ti = ti.length > 0 ? ti.substring(0, ti.length - 1) : ti;
-		ne.title = ti;
+			each (p, function(v, k) {
+				if (v && !/^(width|height|codebase|classid)$/.test(k))
+					dom.add(ob, 'span', {mce_name : 'param', name : k, '_value' : v});
+			});
 
-		n.parentNode.replaceChild(ne, n);
-	},
-
-	_createImg : function(cl, d, n) {
-		var i, nl, ti = "", an, av, al = new Array();
+			dom.add(ob, 'span', tinymce.extend({mce_name : 'embed', type : o.type}, p));
 
-		ne = d.createElement('img');
-		ne.src = tinyMCE.getParam("theme_href") + '/images/spacer.gif';
-		ne.width = tinyMCE.getAttrib(n, 'width');
-		ne.height = tinyMCE.getAttrib(n, 'height');
-		ne.className = cl;
+			return ob;
+		},
 
-		al.id = tinyMCE.getAttrib(n, 'id');
-		al.name = tinyMCE.getAttrib(n, 'name');
-		al.width = tinyMCE.getAttrib(n, 'width');
-		al.height = tinyMCE.getAttrib(n, 'height');
-		al.bgcolor = tinyMCE.getAttrib(n, 'bgcolor');
-		al.align = tinyMCE.getAttrib(n, 'align');
-		al.class_name = tinyMCE.getAttrib(n, 'mce_class');
+		_spansToImgs : function(p) {
+			var t = this, dom = t.editor.dom, im, ci;
 
-		nl = n.getElementsByTagName('div');
-		for (i=0; i<nl.length; i++) {
-			av = tinyMCE.getAttrib(nl[i], 'value');
-			av = av.replace(new RegExp('\\\\', 'g'), '\\\\');
-			av = av.replace(new RegExp('"', 'g'), '\\"');
-			av = av.replace(new RegExp("'", 'g'), "\\'");
-			an = tinyMCE.getAttrib(nl[i], 'name');
-			al[an] = av;
-		}
+			each(dom.select('span', p), function(n) {
+				// Convert object into image
+				if (dom.getAttrib(n, 'class') == 'mceItemObject') {
+					ci = dom.getAttrib(n, "classid").toLowerCase().replace(/\s+/g, '');
 
-		if (al.movie) {
-			al.src = al.movie;
-			al.movie = null;
-		}
+					switch (ci) {
+						case 'clsid:d27cdb6e-ae6d-11cf-96b8-444553540000':
+							dom.replace(t._createImg('mceItemFlash', n), n);
+							break;
+
+						case 'clsid:166b1bca-3f9c-11cf-8075-444553540000':
+							dom.replace(t._createImg('mceItemShockWave', n), n);
+							break;
 
-		for (an in al) {
-			if (al[an] != null && typeof(al[an]) != "function" && al[an] != '')
-				ti += an.toLowerCase() + ':\'' + al[an] + "',";
-		}
-
-		ti = ti.length > 0 ? ti.substring(0, ti.length - 1) : ti;
-		ne.title = ti;
+						case 'clsid:6bf52a52-394a-11d3-b153-00c04f79faa6':
+						case 'clsid:22d6f312-b0f6-11d0-94ab-0080c74c7e95':
+						case 'clsid:05589fa1-c356-11ce-bf01-00aa0055595a':
+							dom.replace(t._createImg('mceItemWindowsMedia', n), n);
+							break;
 
-		return ne;
-	},
+						case 'clsid:02bf25d5-8c17-4b23-bc80-d3488abddc6b':
+							dom.replace(t._createImg('mceItemQuickTime', n), n);
+							break;
 
-	_getEmbed : function(cls, cb, mt, p, at) {
-		var h = '', n;
-
-		p.width = at.width ? at.width : p.width;
-		p.height = at.height ? at.height : p.height;
+						case 'clsid:cfcdaa03-8be4-11cf-b84b-0020afbbccfa':
+							dom.replace(t._createImg('mceItemRealMedia', n), n);
+							break;
 
-		h += '<object classid="clsid:' + cls + '" codebase="' + cb + '"';
-		h += typeof(p.id) != "undefined" ? ' id="' + p.id + '"' : '';
-		h += typeof(p.name) != "undefined" ? ' name="' + p.name + '"' : '';
-		h += typeof(p.width) != "undefined" ? ' width="' + p.width + '"' : '';
-		h += typeof(p.height) != "undefined" ? ' height="' + p.height + '"' : '';
-		h += typeof(p.align) != "undefined" ? ' align="' + p.align + '"' : '';
-		h += '>';
+						default:
+							dom.replace(t._createImg('mceItemFlash', n), n);
+					}
+				}
+			});
+		},
 
-		for (n in p) {
-			if (p[n] && typeof(p[n]) != "function") {
-				h += '<param name="' + n + '" value="' + p[n] + '" />';
+		_createImg : function(cl, n) {
+			var im, dom = this.editor.dom, pa = {}, ti = '';
 
-				// Add extra url parameter if it's an absolute URL on WMP
-				if (n == 'src' && p[n].indexOf('://') != -1 && mt == 'application/x-mplayer2')
-					h += '<param name="url" value="' + p[n] + '" />';
-			}
-		}
-
-		h += '<embed type="' + mt + '"';
+			// Create image
+			im = dom.create('img', {
+				src : this.url + '/img/trans.gif',
+				width : dom.getAttrib(n, 'width') || 100,
+				height : dom.getAttrib(n, 'height') || 100,
+				'class' : cl
+			});
 
-		for (n in p) {
-			if (typeof(p[n]) == "function")
-				continue;
-
-			// Skip url parameter for embed tag on WMP
-			if (!(n == 'url' && mt == 'application/x-mplayer2'))
-				h += ' ' + n + '="' + p[n] + '"';
-		}
-
-		h += '></embed></object>';
+			// Setup base parameters
+			each(['id', 'name', 'width', 'height', 'bgcolor', 'align'], function(n) {
+				var v = dom.getAttrib(n, 'align');
 
-		return h;
-	},
-
-	_parseAttributes : function(attribute_string) {
-		var attributeName = "", endChr = '"';
-		var attributeValue = "";
-		var withInName;
-		var withInValue;
-		var attributes = new Array();
-		var whiteSpaceRegExp = new RegExp('^[ \n\r\t]+', 'g');
+				if (v)
+					pa[v] = v;
+			});
 
-		if (attribute_string == null || attribute_string.length < 2)
-			return null;
-
-		withInName = withInValue = false;
+			// Add optional parameters
+			each(dom.select('span', n), function(n) {
+				if (dom.hasClass(n, 'mceItemParam'))
+					pa[dom.getAttrib(n, 'name')] = dom.getAttrib(n, '_value');
+			});
 
-		for (var i=0; i<attribute_string.length; i++) {
-			var chr = attribute_string.charAt(i);
-
-			if ((chr == '"' || chr == "'") && !withInValue) {
-				withInValue = true;
-				endChr = chr;
-			} else if (chr == endChr && withInValue) {
-				withInValue = false;
+			// Use src not movie
+			if (pa.movie) {
+				pa.src = pa.movie;
+				delete pa.movie;
+			}
 
-				var pos = attributeName.lastIndexOf(' ');
-				if (pos != -1)
-					attributeName = attributeName.substring(pos+1);
+			delete pa.width;
+			delete pa.height;
 
-				attributes[attributeName.toLowerCase()] = attributeValue.substring(1);
+			im.title = this._serialize(pa);
 
-				attributeName = "";
-				attributeValue = "";
-			} else if (!whiteSpaceRegExp.test(chr) && !withInName && !withInValue)
-				withInName = true;
+			return im;
+		},
 
-			if (chr == '=' && withInName)
-				withInName = false;
-
-			if (withInName)
-				attributeName += chr;
+		_parse : function(s) {
+			return tinymce.util.JSON.parse('{' + s + '}');
+		},
 
-			if (withInValue)
-				attributeValue += chr;
+		_serialize : function(o) {
+			return tinymce.util.JSON.serialize(o).replace(/[{}]/g, '');
 		}
+	});
 
-		return attributes;
-	}
-};
-
-tinyMCE.addPlugin("media", TinyMCE_MediaPlugin);
+	// Register plugin
+	tinymce.PluginManager.add('media', tinymce.plugins.MediaPlugin);
+})();
\ No newline at end of file
Binary file includes/clientside/tinymce/plugins/media/images/flash.gif has changed
Binary file includes/clientside/tinymce/plugins/media/images/media.gif has changed
Binary file includes/clientside/tinymce/plugins/media/images/quicktime.gif has changed
Binary file includes/clientside/tinymce/plugins/media/images/realmedia.gif has changed
Binary file includes/clientside/tinymce/plugins/media/images/shockwave.gif has changed
Binary file includes/clientside/tinymce/plugins/media/images/windowsmedia.gif has changed
Binary file includes/clientside/tinymce/plugins/media/img/flash.gif has changed
Binary file includes/clientside/tinymce/plugins/media/img/flv_player.swf has changed
Binary file includes/clientside/tinymce/plugins/media/img/quicktime.gif has changed
Binary file includes/clientside/tinymce/plugins/media/img/realmedia.gif has changed
Binary file includes/clientside/tinymce/plugins/media/img/shockwave.gif has changed
Binary file includes/clientside/tinymce/plugins/media/img/trans.gif has changed
Binary file includes/clientside/tinymce/plugins/media/img/windowsmedia.gif has changed
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/includes/clientside/tinymce/plugins/media/js/embed.js	Fri Feb 22 12:51:53 2008 -0500
@@ -0,0 +1,73 @@
+/**
+ * This script contains embed functions for common plugins. This scripts are complety free to use for any purpose.
+ */
+
+function writeFlash(p) {
+	writeEmbed(
+		'D27CDB6E-AE6D-11cf-96B8-444553540000',
+		'http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,40,0',
+		'application/x-shockwave-flash',
+		p
+	);
+}
+
+function writeShockWave(p) {
+	writeEmbed(
+	'166B1BCA-3F9C-11CF-8075-444553540000',
+	'http://download.macromedia.com/pub/shockwave/cabs/director/sw.cab#version=8,5,1,0',
+	'application/x-director',
+		p
+	);
+}
+
+function writeQuickTime(p) {
+	writeEmbed(
+		'02BF25D5-8C17-4B23-BC80-D3488ABDDC6B',
+		'http://www.apple.com/qtactivex/qtplugin.cab#version=6,0,2,0',
+		'video/quicktime',
+		p
+	);
+}
+
+function writeRealMedia(p) {
+	writeEmbed(
+		'CFCDAA03-8BE4-11cf-B84B-0020AFBBCCFA',
+		'http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,40,0',
+		'audio/x-pn-realaudio-plugin',
+		p
+	);
+}
+
+function writeWindowsMedia(p) {
+	p.url = p.src;
+	writeEmbed(
+		'6BF52A52-394A-11D3-B153-00C04F79FAA6',
+		'http://activex.microsoft.com/activex/controls/mplayer/en/nsmp2inf.cab#Version=5,1,52,701',
+		'application/x-mplayer2',
+		p
+	);
+}
+
+function writeEmbed(cls, cb, mt, p) {
+	var h = '', n;
+
+	h += '<object classid="clsid:' + cls + '" codebase="' + cb + '"';
+	h += typeof(p.id) != "undefined" ? 'id="' + p.id + '"' : '';
+	h += typeof(p.name) != "undefined" ? 'name="' + p.name + '"' : '';
+	h += typeof(p.width) != "undefined" ? 'width="' + p.width + '"' : '';
+	h += typeof(p.height) != "undefined" ? 'height="' + p.height + '"' : '';
+	h += typeof(p.align) != "undefined" ? 'align="' + p.align + '"' : '';
+	h += '>';
+
+	for (n in p)
+		h += '<param name="' + n + '" value="' + p[n] + '">';
+
+	h += '<embed type="' + mt + '"';
+
+	for (n in p)
+		h += n + '="' + p[n] + '" ';
+
+	h += '></embed></object>';
+
+	document.write(h);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/includes/clientside/tinymce/plugins/media/js/media.js	Fri Feb 22 12:51:53 2008 -0500
@@ -0,0 +1,616 @@
+tinyMCEPopup.requireLangPack();
+
+var oldWidth, oldHeight, ed, url;
+
+if (url = tinyMCEPopup.getParam("media_external_list_url"))
+	document.write('<script language="javascript" type="text/javascript" src="' + tinyMCEPopup.editor.documentBaseURI.toAbsolute(url) + '"></script>');
+
+function init() {
+	var pl = "", f, val;
+	var type = "flash", fe, i;
+
+	ed = tinyMCEPopup.editor;
+
+	tinyMCEPopup.resizeToInnerSize();
+	f = document.forms[0]
+
+	fe = ed.selection.getNode();
+	if (/mceItem(Flash|ShockWave|WindowsMedia|QuickTime|RealMedia)/.test(ed.dom.getAttrib(fe, 'class'))) {
+		pl = "x={" + fe.title + "};";
+
+		switch (ed.dom.getAttrib(fe, 'class')) {
+			case 'mceItemFlash':
+				type = 'flash';
+				break;
+
+			case 'mceItemFlashVideo':
+				type = 'flv';
+				break;
+
+			case 'mceItemShockWave':
+				type = 'shockwave';
+				break;
+
+			case 'mceItemWindowsMedia':
+				type = 'wmp';
+				break;
+
+			case 'mceItemQuickTime':
+				type = 'qt';
+				break;
+
+			case 'mceItemRealMedia':
+				type = 'rmp';
+				break;
+		}
+
+		document.forms[0].insert.value = ed.getLang('update', 'Insert', true); 
+	}
+
+	document.getElementById('filebrowsercontainer').innerHTML = getBrowserHTML('filebrowser','src','media','media');
+	document.getElementById('qtsrcfilebrowsercontainer').innerHTML = getBrowserHTML('qtsrcfilebrowser','qt_qtsrc','media','media');
+	document.getElementById('bgcolor_pickcontainer').innerHTML = getColorPickerHTML('bgcolor_pick','bgcolor');
+
+	var html = getMediaListHTML('medialist','src','media','media');
+	if (html == "")
+		document.getElementById("linklistrow").style.display = 'none';
+	else
+		document.getElementById("linklistcontainer").innerHTML = html;
+
+	// Resize some elements
+	if (isVisible('filebrowser'))
+		document.getElementById('src').style.width = '230px';
+
+	// Setup form
+	if (pl != "") {
+		pl = eval(pl);
+
+		switch (type) {
+			case "flash":
+				setBool(pl, 'flash', 'play');
+				setBool(pl, 'flash', 'loop');
+				setBool(pl, 'flash', 'menu');
+				setBool(pl, 'flash', 'swliveconnect');
+				setStr(pl, 'flash', 'quality');
+				setStr(pl, 'flash', 'scale');
+				setStr(pl, 'flash', 'salign');
+				setStr(pl, 'flash', 'wmode');
+				setStr(pl, 'flash', 'base');
+				setStr(pl, 'flash', 'flashvars');
+			break;
+
+			case "qt":
+				setBool(pl, 'qt', 'loop');
+				setBool(pl, 'qt', 'autoplay');
+				setBool(pl, 'qt', 'cache');
+				setBool(pl, 'qt', 'controller');
+				setBool(pl, 'qt', 'correction');
+				setBool(pl, 'qt', 'enablejavascript');
+				setBool(pl, 'qt', 'kioskmode');
+				setBool(pl, 'qt', 'autohref');
+				setBool(pl, 'qt', 'playeveryframe');
+				setBool(pl, 'qt', 'tarsetcache');
+				setStr(pl, 'qt', 'scale');
+				setStr(pl, 'qt', 'starttime');
+				setStr(pl, 'qt', 'endtime');
+				setStr(pl, 'qt', 'tarset');
+				setStr(pl, 'qt', 'qtsrcchokespeed');
+				setStr(pl, 'qt', 'volume');
+				setStr(pl, 'qt', 'qtsrc');
+			break;
+
+			case "shockwave":
+				setBool(pl, 'shockwave', 'sound');
+				setBool(pl, 'shockwave', 'progress');
+				setBool(pl, 'shockwave', 'autostart');
+				setBool(pl, 'shockwave', 'swliveconnect');
+				setStr(pl, 'shockwave', 'swvolume');
+				setStr(pl, 'shockwave', 'swstretchstyle');
+				setStr(pl, 'shockwave', 'swstretchhalign');
+				setStr(pl, 'shockwave', 'swstretchvalign');
+			break;
+
+			case "wmp":
+				setBool(pl, 'wmp', 'autostart');
+				setBool(pl, 'wmp', 'enabled');
+				setBool(pl, 'wmp', 'enablecontextmenu');
+				setBool(pl, 'wmp', 'fullscreen');
+				setBool(pl, 'wmp', 'invokeurls');
+				setBool(pl, 'wmp', 'mute');
+				setBool(pl, 'wmp', 'stretchtofit');
+				setBool(pl, 'wmp', 'windowlessvideo');
+				setStr(pl, 'wmp', 'balance');
+				setStr(pl, 'wmp', 'baseurl');
+				setStr(pl, 'wmp', 'captioningid');
+				setStr(pl, 'wmp', 'currentmarker');
+				setStr(pl, 'wmp', 'currentposition');
+				setStr(pl, 'wmp', 'defaultframe');
+				setStr(pl, 'wmp', 'playcount');
+				setStr(pl, 'wmp', 'rate');
+				setStr(pl, 'wmp', 'uimode');
+				setStr(pl, 'wmp', 'volume');
+			break;
+
+			case "rmp":
+				setBool(pl, 'rmp', 'autostart');
+				setBool(pl, 'rmp', 'loop');
+				setBool(pl, 'rmp', 'autogotourl');
+				setBool(pl, 'rmp', 'center');
+				setBool(pl, 'rmp', 'imagestatus');
+				setBool(pl, 'rmp', 'maintainaspect');
+				setBool(pl, 'rmp', 'nojava');
+				setBool(pl, 'rmp', 'prefetch');
+				setBool(pl, 'rmp', 'shuffle');
+				setStr(pl, 'rmp', 'console');
+				setStr(pl, 'rmp', 'controls');
+				setStr(pl, 'rmp', 'numloop');
+				setStr(pl, 'rmp', 'scriptcallbacks');
+			break;
+		}
+
+		setStr(pl, null, 'src');
+		setStr(pl, null, 'id');
+		setStr(pl, null, 'name');
+		setStr(pl, null, 'vspace');
+		setStr(pl, null, 'hspace');
+		setStr(pl, null, 'bgcolor');
+		setStr(pl, null, 'align');
+		setStr(pl, null, 'width');
+		setStr(pl, null, 'height');
+
+		if ((val = ed.dom.getAttrib(fe, "width")) != "")
+			pl.width = f.width.value = val;
+
+		if ((val = ed.dom.getAttrib(fe, "height")) != "")
+			pl.height = f.height.value = val;
+
+		oldWidth = pl.width ? parseInt(pl.width) : 0;
+		oldHeight = pl.height ? parseInt(pl.height) : 0;
+	} else
+		oldWidth = oldHeight = 0;
+
+	selectByValue(f, 'media_type', type);
+	changedType(type);
+	updateColor('bgcolor_pick', 'bgcolor');
+
+	TinyMCE_EditableSelects.init();
+	generatePreview();
+}
+
+function insertMedia() {
+	var fe, f = document.forms[0], h;
+
+	if (!AutoValidator.validate(f)) {
+		alert(ed.getLang('invalid_data'));
+		return false;
+	}
+
+	f.width.value = f.width.value == "" ? 100 : f.width.value;
+	f.height.value = f.height.value == "" ? 100 : f.height.value;
+
+	fe = ed.selection.getNode();
+	if (fe != null && /mceItem(Flash|ShockWave|WindowsMedia|QuickTime|RealMedia)/.test(ed.dom.getAttrib(fe, 'class'))) {
+		switch (f.media_type.options[f.media_type.selectedIndex].value) {
+			case "flash":
+				fe.className = "mceItemFlash";
+				break;
+
+			case "flv":
+				fe.className = "mceItemFlashVideo";
+				break;
+
+			case "shockwave":
+				fe.className = "mceItemShockWave";
+				break;
+
+			case "qt":
+				fe.className = "mceItemQuickTime";
+				break;
+
+			case "wmp":
+				fe.className = "mceItemWindowsMedia";
+				break;
+
+			case "rmp":
+				fe.className = "mceItemRealMedia";
+				break;
+		}
+
+		if (fe.width != f.width.value || fe.height != f.height.height)
+			ed.execCommand('mceRepaint');
+
+		fe.title = serializeParameters();
+		fe.width = f.width.value;
+		fe.height = f.height.value;
+		fe.style.width = f.width.value + (f.width.value.indexOf('%') == -1 ? 'px' : '');
+		fe.style.height = f.height.value + (f.height.value.indexOf('%') == -1 ? 'px' : '');
+		fe.align = f.align.options[f.align.selectedIndex].value;
+	} else {
+		h = '<img src="' + tinyMCEPopup.getWindowArg("plugin_url") + '/img/trans.gif"' ;
+
+		switch (f.media_type.options[f.media_type.selectedIndex].value) {
+			case "flash":
+				h += ' class="mceItemFlash"';
+				break;
+
+			case "flv":
+				h += ' class="mceItemFlashVideo"';
+				break;
+
+			case "shockwave":
+				h += ' class="mceItemShockWave"';
+				break;
+
+			case "qt":
+				h += ' class="mceItemQuickTime"';
+				break;
+
+			case "wmp":
+				h += ' class="mceItemWindowsMedia"';
+				break;
+
+			case "rmp":
+				h += ' class="mceItemRealMedia"';
+				break;
+		}
+
+		h += ' title="' + serializeParameters() + '"';
+		h += ' width="' + f.width.value + '"';
+		h += ' height="' + f.height.value + '"';
+		h += ' align="' + f.align.options[f.align.selectedIndex].value + '"';
+
+		h += ' />';
+
+		ed.execCommand('mceInsertContent', false, h);
+	}
+
+	tinyMCEPopup.close();
+}
+
+function updatePreview() {
+	var f = document.forms[0], type;
+
+	f.width.value = f.width.value || '320';
+	f.height.value = f.height.value || '240';
+
+	type = getType(f.src.value);
+	selectByValue(f, 'media_type', type);
+	changedType(type);
+	generatePreview();
+}
+
+function getMediaListHTML() {
+	if (typeof(tinyMCEMediaList) != "undefined" && tinyMCEMediaList.length > 0) {
+		var html = "";
+
+		html += '<select id="linklist" name="linklist" style="width: 250px" onchange="this.form.src.value=this.options[this.selectedIndex].value;updatePreview();">';
+		html += '<option value="">---</option>';
+
+		for (var i=0; i<tinyMCEMediaList.length; i++)
+			html += '<option value="' + tinyMCEMediaList[i][1] + '">' + tinyMCEMediaList[i][0] + '</option>';
+
+		html += '</select>';
+
+		return html;
+	}
+
+	return "";
+}
+
+function getType(v) {
+	var fo, i, c, el, x, f = document.forms[0];
+
+	fo = ed.getParam("media_types", "flash=swf;flv=flv;shockwave=dcr;qt=mov,qt,mpg,mp3,mp4,mpeg;shockwave=dcr;wmp=avi,wmv,wm,asf,asx,wmx,wvx;rmp=rm,ra,ram").split(';');
+
+	// YouTube
+	if (v.match(/v=(.+)(.*)/)) {
+		f.width.value = '425';
+		f.height.value = '350';
+		f.src.value = 'http://www.youtube.com/v/' + v.match(/v=(.*)(.*)/)[0].split('=')[1];
+		return 'flash';
+	}
+
+	// Google video
+	if (v.indexOf('http://video.google.com/videoplay?docid=') == 0) {
+		f.width.value = '425';
+		f.height.value = '326';
+		f.src.value = 'http://video.google.com/googleplayer.swf?docId=' + v.substring('http://video.google.com/videoplay?docid='.length) + '&hl=en';
+		return 'flash';
+	}
+
+	for (i=0; i<fo.length; i++) {
+		c = fo[i].split('=');
+
+		el = c[1].split(',');
+		for (x=0; x<el.length; x++)
+		if (v.indexOf('.' + el[x]) != -1)
+			return c[0];
+	}
+
+	return null;
+}
+
+function switchType(v) {
+	var t = getType(v), d = document, f = d.forms[0];
+
+	if (!t)
+		return;
+
+	selectByValue(d.forms[0], 'media_type', t);
+	changedType(t);
+
+	// Update qtsrc also
+	if (t == 'qt' && f.src.value.toLowerCase().indexOf('rtsp://') != -1) {
+		alert(ed.getLang("media_qt_stream_warn"));
+
+		if (f.qt_qtsrc.value == '')
+			f.qt_qtsrc.value = f.src.value;
+	}
+}
+
+function changedType(t) {
+	var d = document;
+
+	d.getElementById('flash_options').style.display = 'none';
+	d.getElementById('flv_options').style.display = 'none';
+	d.getElementById('qt_options').style.display = 'none';
+	d.getElementById('shockwave_options').style.display = 'none';
+	d.getElementById('wmp_options').style.display = 'none';
+	d.getElementById('rmp_options').style.display = 'none';
+	d.getElementById(t + '_options').style.display = 'block';
+}
+
+function serializeParameters() {
+	var d = document, f = d.forms[0], s = '';
+
+	switch (f.media_type.options[f.media_type.selectedIndex].value) {
+		case "flash":
+			s += getBool('flash', 'play', true);
+			s += getBool('flash', 'loop', true);
+			s += getBool('flash', 'menu', true);
+			s += getBool('flash', 'swliveconnect', false);
+			s += getStr('flash', 'quality');
+			s += getStr('flash', 'scale');
+			s += getStr('flash', 'salign');
+			s += getStr('flash', 'wmode');
+			s += getStr('flash', 'base');
+			s += getStr('flash', 'flashvars');
+		break;
+
+		case "qt":
+			s += getBool('qt', 'loop', false);
+			s += getBool('qt', 'autoplay', true);
+			s += getBool('qt', 'cache', false);
+			s += getBool('qt', 'controller', true);
+			s += getBool('qt', 'correction', false, 'none', 'full');
+			s += getBool('qt', 'enablejavascript', false);
+			s += getBool('qt', 'kioskmode', false);
+			s += getBool('qt', 'autohref', false);
+			s += getBool('qt', 'playeveryframe', false);
+			s += getBool('qt', 'targetcache', false);
+			s += getStr('qt', 'scale');
+			s += getStr('qt', 'starttime');
+			s += getStr('qt', 'endtime');
+			s += getStr('qt', 'target');
+			s += getStr('qt', 'qtsrcchokespeed');
+			s += getStr('qt', 'volume');
+			s += getStr('qt', 'qtsrc');
+		break;
+
+		case "shockwave":
+			s += getBool('shockwave', 'sound');
+			s += getBool('shockwave', 'progress');
+			s += getBool('shockwave', 'autostart');
+			s += getBool('shockwave', 'swliveconnect');
+			s += getStr('shockwave', 'swvolume');
+			s += getStr('shockwave', 'swstretchstyle');
+			s += getStr('shockwave', 'swstretchhalign');
+			s += getStr('shockwave', 'swstretchvalign');
+		break;
+
+		case "wmp":
+			s += getBool('wmp', 'autostart', true);
+			s += getBool('wmp', 'enabled', false);
+			s += getBool('wmp', 'enablecontextmenu', true);
+			s += getBool('wmp', 'fullscreen', false);
+			s += getBool('wmp', 'invokeurls', true);
+			s += getBool('wmp', 'mute', false);
+			s += getBool('wmp', 'stretchtofit', false);
+			s += getBool('wmp', 'windowlessvideo', false);
+			s += getStr('wmp', 'balance');
+			s += getStr('wmp', 'baseurl');
+			s += getStr('wmp', 'captioningid');
+			s += getStr('wmp', 'currentmarker');
+			s += getStr('wmp', 'currentposition');
+			s += getStr('wmp', 'defaultframe');
+			s += getStr('wmp', 'playcount');
+			s += getStr('wmp', 'rate');
+			s += getStr('wmp', 'uimode');
+			s += getStr('wmp', 'volume');
+		break;
+
+		case "rmp":
+			s += getBool('rmp', 'autostart', false);
+			s += getBool('rmp', 'loop', false);
+			s += getBool('rmp', 'autogotourl', true);
+			s += getBool('rmp', 'center', false);
+			s += getBool('rmp', 'imagestatus', true);
+			s += getBool('rmp', 'maintainaspect', false);
+			s += getBool('rmp', 'nojava', false);
+			s += getBool('rmp', 'prefetch', false);
+			s += getBool('rmp', 'shuffle', false);
+			s += getStr('rmp', 'console');
+			s += getStr('rmp', 'controls');
+			s += getStr('rmp', 'numloop');
+			s += getStr('rmp', 'scriptcallbacks');
+		break;
+	}
+
+	s += getStr(null, 'id');
+	s += getStr(null, 'name');
+	s += getStr(null, 'src');
+	s += getStr(null, 'align');
+	s += getStr(null, 'bgcolor');
+	s += getInt(null, 'vspace');
+	s += getInt(null, 'hspace');
+	s += getStr(null, 'width');
+	s += getStr(null, 'height');
+
+	s = s.length > 0 ? s.substring(0, s.length - 1) : s;
+
+	return s;
+}
+
+function setBool(pl, p, n) {
+	if (typeof(pl[n]) == "undefined")
+		return;
+
+	document.forms[0].elements[p + "_" + n].checked = pl[n];
+}
+
+function setStr(pl, p, n) {
+	var f = document.forms[0], e = f.elements[(p != null ? p + "_" : '') + n];
+
+	if (typeof(pl[n]) == "undefined")
+		return;
+
+	if (e.type == "text")
+		e.value = pl[n];
+	else
+		selectByValue(f, (p != null ? p + "_" : '') + n, pl[n]);
+}
+
+function getBool(p, n, d, tv, fv) {
+	var v = document.forms[0].elements[p + "_" + n].checked;
+
+	tv = typeof(tv) == 'undefined' ? 'true' : "'" + jsEncode(tv) + "'";
+	fv = typeof(fv) == 'undefined' ? 'false' : "'" + jsEncode(fv) + "'";
+
+	return (v == d) ? '' : n + (v ? ':' + tv + ',' : ':' + fv + ',');
+}
+
+function getStr(p, n, d) {
+	var e = document.forms[0].elements[(p != null ? p + "_" : "") + n];
+	var v = e.type == "text" ? e.value : e.options[e.selectedIndex].value;
+
+	return ((n == d || v == '') ? '' : n + ":'" + jsEncode(v) + "',");
+}
+
+function getInt(p, n, d) {
+	var e = document.forms[0].elements[(p != null ? p + "_" : "") + n];
+	var v = e.type == "text" ? e.value : e.options[e.selectedIndex].value;
+
+	return ((n == d || v == '') ? '' : n + ":" + v.replace(/[^0-9]+/g, '') + ",");
+}
+
+function jsEncode(s) {
+	s = s.replace(new RegExp('\\\\', 'g'), '\\\\');
+	s = s.replace(new RegExp('"', 'g'), '\\"');
+	s = s.replace(new RegExp("'", 'g'), "\\'");
+
+	return s;
+}
+
+function generatePreview(c) {
+	var f = document.forms[0], p = document.getElementById('prev'), h = '', cls, pl, n, type, codebase, wp, hp, nw, nh;
+
+	p.innerHTML = '<!-- x --->';
+
+	nw = parseInt(f.width.value);
+	nh = parseInt(f.height.value);
+
+	if (f.width.value != "" && f.height.value != "") {
+		if (f.constrain.checked) {
+			if (c == 'width' && oldWidth != 0) {
+				wp = nw / oldWidth;
+				nh = Math.round(wp * nh);
+				f.height.value = nh;
+			} else if (c == 'height' && oldHeight != 0) {
+				hp = nh / oldHeight;
+				nw = Math.round(hp * nw);
+				f.width.value = nw;
+			}
+		}
+	}
+
+	if (f.width.value != "")
+		oldWidth = nw;
+
+	if (f.height.value != "")
+		oldHeight = nh;
+
+	// After constrain
+	pl = serializeParameters();
+
+	switch (f.media_type.options[f.media_type.selectedIndex].value) {
+		case "flash":
+			cls = 'clsid:D27CDB6E-AE6D-11cf-96B8-444553540000';
+			codebase = 'http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,40,0';
+			type = 'application/x-shockwave-flash';
+			break;
+
+		case "shockwave":
+			cls = 'clsid:166B1BCA-3F9C-11CF-8075-444553540000';
+			codebase = 'http://download.macromedia.com/pub/shockwave/cabs/director/sw.cab#version=8,5,1,0';
+			type = 'application/x-director';
+			break;
+
+		case "qt":
+			cls = 'clsid:02BF25D5-8C17-4B23-BC80-D3488ABDDC6B';
+			codebase = 'http://www.apple.com/qtactivex/qtplugin.cab#version=6,0,2,0';
+			type = 'video/quicktime';
+			break;
+
+		case "wmp":
+			cls = ed.getParam('media_wmp6_compatible') ? 'clsid:05589FA1-C356-11CE-BF01-00AA0055595A' : 'clsid:6BF52A52-394A-11D3-B153-00C04F79FAA6';
+			codebase = 'http://activex.microsoft.com/activex/controls/mplayer/en/nsmp2inf.cab#Version=5,1,52,701';
+			type = 'application/x-mplayer2';
+			break;
+
+		case "rmp":
+			cls = 'clsid:CFCDAA03-8BE4-11cf-B84B-0020AFBBCCFA';
+			codebase = 'http://activex.microsoft.com/activex/controls/mplayer/en/nsmp2inf.cab#Version=5,1,52,701';
+			type = 'audio/x-pn-realaudio-plugin';
+			break;
+	}
+
+	if (pl == '') {
+		p.innerHTML = '';
+		return;
+	}
+
+	pl = eval('x={' + pl + '};');
+
+	if (!pl.src) {
+		p.innerHTML = '';
+		return;
+	}
+
+	pl.src = tinyMCEPopup.editor.documentBaseURI.toAbsolute(pl.src);
+	pl.width = !pl.width ? 100 : pl.width;
+	pl.height = !pl.height ? 100 : pl.height;
+	pl.id = !pl.id ? 'obj' : pl.id;
+	pl.name = !pl.name ? 'eobj' : pl.name;
+	pl.align = !pl.align ? '' : pl.align;
+
+	h += '<object classid="clsid:' + cls + '" codebase="' + codebase + '" width="' + pl.width + '" height="' + pl.height + '" id="' + pl.id + '" name="' + pl.name + '" align="' + pl.align + '">';
+
+	for (n in pl) {
+		h += '<param name="' + n + '" value="' + pl[n] + '">';
+
+		// Add extra url parameter if it's an absolute URL
+		if (n == 'src' && pl[n].indexOf('://') != -1)
+			h += '<param name="url" value="' + pl[n] + '" />';
+	}
+
+	h += '<embed type="' + type + '" ';
+
+	for (n in pl)
+		h += n + '="' + pl[n] + '" ';
+
+	h += '></embed></object>';
+
+	p.innerHTML = "<!-- x --->" + h;
+}
+
+tinyMCEPopup.onInit.add(init);
--- a/includes/clientside/tinymce/plugins/media/jscripts/embed.js	Fri Feb 22 12:46:51 2008 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,73 +0,0 @@
-/**
- * This script contains embed functions for common plugins. This scripts are complety free to use for any purpose.
- */
-
-function writeFlash(p) {
-	writeEmbed(
-		'D27CDB6E-AE6D-11cf-96B8-444553540000',
-		'http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,40,0',
-		'application/x-shockwave-flash',
-		p
-	);
-}
-
-function writeShockWave(p) {
-	writeEmbed(
-	'166B1BCA-3F9C-11CF-8075-444553540000',
-	'http://download.macromedia.com/pub/shockwave/cabs/director/sw.cab#version=8,5,1,0',
-	'application/x-director',
-		p
-	);
-}
-
-function writeQuickTime(p) {
-	writeEmbed(
-		'02BF25D5-8C17-4B23-BC80-D3488ABDDC6B',
-		'http://www.apple.com/qtactivex/qtplugin.cab#version=6,0,2,0',
-		'video/quicktime',
-		p
-	);
-}
-
-function writeRealMedia(p) {
-	writeEmbed(
-		'CFCDAA03-8BE4-11cf-B84B-0020AFBBCCFA',
-		'http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,40,0',
-		'audio/x-pn-realaudio-plugin',
-		p
-	);
-}
-
-function writeWindowsMedia(p) {
-	p.url = p.src;
-	writeEmbed(
-		'6BF52A52-394A-11D3-B153-00C04F79FAA6',
-		'http://activex.microsoft.com/activex/controls/mplayer/en/nsmp2inf.cab#Version=5,1,52,701',
-		'application/x-mplayer2',
-		p
-	);
-}
-
-function writeEmbed(cls, cb, mt, p) {
-	var h = '', n;
-
-	h += '<object classid="clsid:' + cls + '" codebase="' + cb + '"';
-	h += typeof(p.id) != "undefined" ? 'id="' + p.id + '"' : '';
-	h += typeof(p.name) != "undefined" ? 'name="' + p.name + '"' : '';
-	h += typeof(p.width) != "undefined" ? 'width="' + p.width + '"' : '';
-	h += typeof(p.height) != "undefined" ? 'height="' + p.height + '"' : '';
-	h += typeof(p.align) != "undefined" ? 'align="' + p.align + '"' : '';
-	h += '>';
-
-	for (n in p)
-		h += '<param name="' + n + '" value="' + p[n] + '">';
-
-	h += '<embed type="' + mt + '"';
-
-	for (n in p)
-		h += n + '="' + p[n] + '" ';
-
-	h += '></embed></object>';
-
-	document.write(h);
-}
--- a/includes/clientside/tinymce/plugins/media/jscripts/media.js	Fri Feb 22 12:46:51 2008 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,572 +0,0 @@
-var oldWidth, oldHeight;
-var url = tinyMCE.getParam("media_external_list_url");
-if (url != null) {
-	// Fix relative
-	if (url.charAt(0) != '/' && url.indexOf('://') == -1)
-		url = tinyMCE.documentBasePath + "/" + url;
-
-	document.write('<sc'+'ript language="javascript" type="text/javascript" src="' + url + '"></sc'+'ript>');
-}
-
-function init() {
-	var pl = "", f, val;
-	var type = "flash", fe, i;
-
-	tinyMCEPopup.resizeToInnerSize();
-	f = document.forms[0]
-
-	fe = tinyMCE.selectedInstance.getFocusElement();
-	if (/mceItem(Flash|ShockWave|WindowsMedia|QuickTime|RealMedia)/.test(tinyMCE.getAttrib(fe, 'class'))) {
-		pl = "x={" + fe.title + "};";
-
-		switch (tinyMCE.getAttrib(fe, 'class')) {
-			case 'mceItemFlash':
-				type = 'flash';
-				break;
-
-			case 'mceItemShockWave':
-				type = 'shockwave';
-				break;
-
-			case 'mceItemWindowsMedia':
-				type = 'wmp';
-				break;
-
-			case 'mceItemQuickTime':
-				type = 'qt';
-				break;
-
-			case 'mceItemRealMedia':
-				type = 'rmp';
-				break;
-		}
-
-		document.forms[0].insert.value = tinyMCE.getLang('lang_update', 'Insert', true); 
-	}
-
-	document.getElementById('filebrowsercontainer').innerHTML = getBrowserHTML('filebrowser','src','media','media');
-	document.getElementById('qtsrcfilebrowsercontainer').innerHTML = getBrowserHTML('qtsrcfilebrowser','qt_qtsrc','media','media');
-	document.getElementById('bgcolor_pickcontainer').innerHTML = getColorPickerHTML('bgcolor_pick','bgcolor');
-
-	var html = getMediaListHTML('filebrowser','src','media','media');
-	if (html == "")
-		document.getElementById("linklistrow").style.display = 'none';
-	else
-		document.getElementById("linklistcontainer").innerHTML = html;
-
-	// Resize some elements
-	if (isVisible('filebrowsercontainer'))
-		document.getElementById('src').style.width = '230px';
-
-	// Setup form
-	if (pl != "") {
-		pl = eval(pl);
-
-		switch (type) {
-			case "flash":
-				setBool(pl, 'flash', 'play');
-				setBool(pl, 'flash', 'loop');
-				setBool(pl, 'flash', 'menu');
-				setBool(pl, 'flash', 'swliveconnect');
-				setStr(pl, 'flash', 'quality');
-				setStr(pl, 'flash', 'scale');
-				setStr(pl, 'flash', 'salign');
-				setStr(pl, 'flash', 'wmode');
-				setStr(pl, 'flash', 'base');
-				setStr(pl, 'flash', 'flashvars');
-			break;
-
-			case "qt":
-				setBool(pl, 'qt', 'loop');
-				setBool(pl, 'qt', 'autoplay');
-				setBool(pl, 'qt', 'cache');
-				setBool(pl, 'qt', 'controller');
-				setBool(pl, 'qt', 'correction');
-				setBool(pl, 'qt', 'enablejavascript');
-				setBool(pl, 'qt', 'kioskmode');
-				setBool(pl, 'qt', 'autohref');
-				setBool(pl, 'qt', 'playeveryframe');
-				setBool(pl, 'qt', 'tarsetcache');
-				setStr(pl, 'qt', 'scale');
-				setStr(pl, 'qt', 'starttime');
-				setStr(pl, 'qt', 'endtime');
-				setStr(pl, 'qt', 'tarset');
-				setStr(pl, 'qt', 'qtsrcchokespeed');
-				setStr(pl, 'qt', 'volume');
-				setStr(pl, 'qt', 'qtsrc');
-			break;
-
-			case "shockwave":
-				setBool(pl, 'shockwave', 'sound');
-				setBool(pl, 'shockwave', 'progress');
-				setBool(pl, 'shockwave', 'autostart');
-				setBool(pl, 'shockwave', 'swliveconnect');
-				setStr(pl, 'shockwave', 'swvolume');
-				setStr(pl, 'shockwave', 'swstretchstyle');
-				setStr(pl, 'shockwave', 'swstretchhalign');
-				setStr(pl, 'shockwave', 'swstretchvalign');
-			break;
-
-			case "wmp":
-				setBool(pl, 'wmp', 'autostart');
-				setBool(pl, 'wmp', 'enabled');
-				setBool(pl, 'wmp', 'enablecontextmenu');
-				setBool(pl, 'wmp', 'fullscreen');
-				setBool(pl, 'wmp', 'invokeurls');
-				setBool(pl, 'wmp', 'mute');
-				setBool(pl, 'wmp', 'stretchtofit');
-				setBool(pl, 'wmp', 'windowlessvideo');
-				setStr(pl, 'wmp', 'balance');
-				setStr(pl, 'wmp', 'baseurl');
-				setStr(pl, 'wmp', 'captioningid');
-				setStr(pl, 'wmp', 'currentmarker');
-				setStr(pl, 'wmp', 'currentposition');
-				setStr(pl, 'wmp', 'defaultframe');
-				setStr(pl, 'wmp', 'playcount');
-				setStr(pl, 'wmp', 'rate');
-				setStr(pl, 'wmp', 'uimode');
-				setStr(pl, 'wmp', 'volume');
-			break;
-
-			case "rmp":
-				setBool(pl, 'rmp', 'autostart');
-				setBool(pl, 'rmp', 'loop');
-				setBool(pl, 'rmp', 'autogotourl');
-				setBool(pl, 'rmp', 'center');
-				setBool(pl, 'rmp', 'imagestatus');
-				setBool(pl, 'rmp', 'maintainaspect');
-				setBool(pl, 'rmp', 'nojava');
-				setBool(pl, 'rmp', 'prefetch');
-				setBool(pl, 'rmp', 'shuffle');
-				setStr(pl, 'rmp', 'console');
-				setStr(pl, 'rmp', 'controls');
-				setStr(pl, 'rmp', 'numloop');
-				setStr(pl, 'rmp', 'scriptcallbacks');
-			break;
-		}
-
-		setStr(pl, null, 'src');
-		setStr(pl, null, 'id');
-		setStr(pl, null, 'name');
-		setStr(pl, null, 'vspace');
-		setStr(pl, null, 'hspace');
-		setStr(pl, null, 'bgcolor');
-		setStr(pl, null, 'align');
-		setStr(pl, null, 'width');
-		setStr(pl, null, 'height');
-
-		if ((val = tinyMCE.getAttrib(fe, "width")) != "")
-			pl.width = f.width.value = val;
-
-		if ((val = tinyMCE.getAttrib(fe, "height")) != "")
-			pl.height = f.height.value = val;
-
-		oldWidth = pl.width ? parseInt(pl.width) : 0;
-		oldHeight = pl.height ? parseInt(pl.height) : 0;
-	} else
-		oldWidth = oldHeight = 0;
-
-	selectByValue(f, 'media_type', type);
-	changedType(type);
-	updateColor('bgcolor_pick', 'bgcolor');
-
-	TinyMCE_EditableSelects.init();
-	generatePreview();
-}
-
-function insertMedia() {
-	var fe, f = document.forms[0], h;
-
-	if (!AutoValidator.validate(f)) {
-		alert(tinyMCE.getLang('lang_invalid_data'));
-		return false;
-	}
-
-	f.width.value = f.width.value == "" ? 100 : f.width.value;
-	f.height.value = f.height.value == "" ? 100 : f.height.value;
-
-	fe = tinyMCE.selectedInstance.getFocusElement();
-	if (fe != null && /mceItem(Flash|ShockWave|WindowsMedia|QuickTime|RealMedia)/.test(tinyMCE.getAttrib(fe, 'class'))) {
-		switch (f.media_type.options[f.media_type.selectedIndex].value) {
-			case "flash":
-				fe.className = "mceItemFlash";
-				break;
-
-			case "shockwave":
-				fe.className = "mceItemShockWave";
-				break;
-
-			case "qt":
-				fe.className = "mceItemQuickTime";
-				break;
-
-			case "wmp":
-				fe.className = "mceItemWindowsMedia";
-				break;
-
-			case "rmp":
-				fe.className = "mceItemRealMedia";
-				break;
-		}
-
-		if (fe.width != f.width.value || fe.height != f.width.height)
-			tinyMCE.selectedInstance.repaint();
-
-		fe.title = serializeParameters();
-		fe.width = f.width.value;
-		fe.height = f.height.value;
-		fe.style.width = f.width.value + (f.width.value.indexOf('%') == -1 ? 'px' : '');
-		fe.style.height = f.height.value + (f.height.value.indexOf('%') == -1 ? 'px' : '');
-		fe.align = f.align.options[f.align.selectedIndex].value;
-	} else {
-		h = '<img src="' + tinyMCE.getParam("theme_href") + '/images/spacer.gif"' ;
-
-		switch (f.media_type.options[f.media_type.selectedIndex].value) {
-			case "flash":
-				h += ' class="mceItemFlash"';
-				break;
-
-			case "shockwave":
-				h += ' class="mceItemShockWave"';
-				break;
-
-			case "qt":
-				h += ' class="mceItemQuickTime"';
-				break;
-
-			case "wmp":
-				h += ' class="mceItemWindowsMedia"';
-				break;
-
-			case "rmp":
-				h += ' class="mceItemRealMedia"';
-				break;
-		}
-
-		h += ' title="' + serializeParameters() + '"';
-		h += ' width="' + f.width.value + '"';
-		h += ' height="' + f.height.value + '"';
-		h += ' align="' + f.align.options[f.align.selectedIndex].value + '"';
-
-		h += ' />';
-
-		tinyMCE.selectedInstance.execCommand('mceInsertContent', false, h);
-	}
-
-	tinyMCEPopup.close();
-}
-
-function getMediaListHTML() {
-	if (typeof(tinyMCEMediaList) != "undefined" && tinyMCEMediaList.length > 0) {
-		var html = "";
-
-		html += '<select id="linklist" name="linklist" style="width: 250px" onfocus="tinyMCE.addSelectAccessibility(event, this, window);" onchange="this.form.src.value=this.options[this.selectedIndex].value;">';
-		html += '<option value="">---</option>';
-
-		for (var i=0; i<tinyMCEMediaList.length; i++)
-			html += '<option value="' + tinyMCEMediaList[i][1] + '">' + tinyMCEMediaList[i][0] + '</option>';
-
-		html += '</select>';
-
-		return html;
-	}
-
-	return "";
-}
-
-function getType(v) {
-	var fo = tinyMCE.getParam("media_types", "flash=swf;shockwave=dcr;qt=mov,qt,mpg,mp3,mp4,mpeg;shockwave=dcr;wmp=avi,wmv,wm,asf,asx,wmx,wvx;rmp=rm,ra,ram").split(';'), i, c, el, x;
-
-	for (i=0; i<fo.length; i++) {
-		c = fo[i].split('=');
-
-		el = c[1].split(',');
-		for (x=0; x<el.length; x++)
-		if (v.indexOf('.' + el[x]) != -1)
-			return c[0];
-	}
-
-	return null;
-}
-
-function switchType(v) {
-	var t = getType(v), d = document, f = d.forms[0];
-
-	if (!t)
-		return;
-
-	selectByValue(d.forms[0], 'media_type', t);
-	changedType(t);
-
-	// Update qtsrc also
-	if (t == 'qt' && f.src.value.toLowerCase().indexOf('rtsp://') != -1) {
-		alert(tinyMCE.getLang("lang_media_qt_stream_warn"));
-
-		if (f.qt_qtsrc.value == '')
-			f.qt_qtsrc.value = f.src.value;
-	}
-}
-
-function changedType(t) {
-	var d = document;
-
-	d.getElementById('flash_options').style.display = 'none';
-	d.getElementById('qt_options').style.display = 'none';
-	d.getElementById('shockwave_options').style.display = 'none';
-	d.getElementById('wmp_options').style.display = 'none';
-	d.getElementById('rmp_options').style.display = 'none';
-	d.getElementById(t + '_options').style.display = 'block';
-}
-
-function serializeParameters() {
-	var d = document, f = d.forms[0], s = '';
-
-	switch (f.media_type.options[f.media_type.selectedIndex].value) {
-		case "flash":
-			s += getBool('flash', 'play', true);
-			s += getBool('flash', 'loop', true);
-			s += getBool('flash', 'menu', true);
-			s += getBool('flash', 'swliveconnect', false);
-			s += getStr('flash', 'quality');
-			s += getStr('flash', 'scale');
-			s += getStr('flash', 'salign');
-			s += getStr('flash', 'wmode');
-			s += getStr('flash', 'base');
-			s += getStr('flash', 'flashvars');
-		break;
-
-		case "qt":
-			s += getBool('qt', 'loop', false);
-			s += getBool('qt', 'autoplay', false);
-			s += getBool('qt', 'cache', false);
-			s += getBool('qt', 'controller', true);
-			s += getBool('qt', 'correction', false, 'none', 'full');
-			s += getBool('qt', 'enablejavascript', false);
-			s += getBool('qt', 'kioskmode', false);
-			s += getBool('qt', 'autohref', false);
-			s += getBool('qt', 'playeveryframe', false);
-			s += getBool('qt', 'targetcache', false);
-			s += getStr('qt', 'scale');
-			s += getStr('qt', 'starttime');
-			s += getStr('qt', 'endtime');
-			s += getStr('qt', 'target');
-			s += getStr('qt', 'qtsrcchokespeed');
-			s += getStr('qt', 'volume');
-			s += getStr('qt', 'qtsrc');
-		break;
-
-		case "shockwave":
-			s += getBool('shockwave', 'sound');
-			s += getBool('shockwave', 'progress');
-			s += getBool('shockwave', 'autostart');
-			s += getBool('shockwave', 'swliveconnect');
-			s += getStr('shockwave', 'swvolume');
-			s += getStr('shockwave', 'swstretchstyle');
-			s += getStr('shockwave', 'swstretchhalign');
-			s += getStr('shockwave', 'swstretchvalign');
-		break;
-
-		case "wmp":
-			s += getBool('wmp', 'autostart', true);
-			s += getBool('wmp', 'enabled', false);
-			s += getBool('wmp', 'enablecontextmenu', true);
-			s += getBool('wmp', 'fullscreen', false);
-			s += getBool('wmp', 'invokeurls', true);
-			s += getBool('wmp', 'mute', false);
-			s += getBool('wmp', 'stretchtofit', false);
-			s += getBool('wmp', 'windowlessvideo', false);
-			s += getStr('wmp', 'balance');
-			s += getStr('wmp', 'baseurl');
-			s += getStr('wmp', 'captioningid');
-			s += getStr('wmp', 'currentmarker');
-			s += getStr('wmp', 'currentposition');
-			s += getStr('wmp', 'defaultframe');
-			s += getStr('wmp', 'playcount');
-			s += getStr('wmp', 'rate');
-			s += getStr('wmp', 'uimode');
-			s += getStr('wmp', 'volume');
-		break;
-
-		case "rmp":
-			s += getBool('rmp', 'autostart', false);
-			s += getBool('rmp', 'loop', false);
-			s += getBool('rmp', 'autogotourl', true);
-			s += getBool('rmp', 'center', false);
-			s += getBool('rmp', 'imagestatus', true);
-			s += getBool('rmp', 'maintainaspect', false);
-			s += getBool('rmp', 'nojava', false);
-			s += getBool('rmp', 'prefetch', false);
-			s += getBool('rmp', 'shuffle', false);
-			s += getStr('rmp', 'console');
-			s += getStr('rmp', 'controls');
-			s += getStr('rmp', 'numloop');
-			s += getStr('rmp', 'scriptcallbacks');
-		break;
-	}
-
-	s += getStr(null, 'id');
-	s += getStr(null, 'name');
-	s += getStr(null, 'src');
-	s += getStr(null, 'align');
-	s += getStr(null, 'bgcolor');
-	s += getInt(null, 'vspace');
-	s += getInt(null, 'hspace');
-	s += getStr(null, 'width');
-	s += getStr(null, 'height');
-
-	s = s.length > 0 ? s.substring(0, s.length - 1) : s;
-
-	return s;
-}
-
-function setBool(pl, p, n) {
-	if (typeof(pl[n]) == "undefined")
-		return;
-
-	document.forms[0].elements[p + "_" + n].checked = pl[n];
-}
-
-function setStr(pl, p, n) {
-	var f = document.forms[0], e = f.elements[(p != null ? p + "_" : '') + n];
-
-	if (typeof(pl[n]) == "undefined")
-		return;
-
-	if (e.type == "text")
-		e.value = pl[n];
-	else
-		selectByValue(f, (p != null ? p + "_" : '') + n, pl[n]);
-}
-
-function getBool(p, n, d, tv, fv) {
-	var v = document.forms[0].elements[p + "_" + n].checked;
-
-	tv = typeof(tv) == 'undefined' ? 'true' : "'" + jsEncode(tv) + "'";
-	fv = typeof(fv) == 'undefined' ? 'false' : "'" + jsEncode(fv) + "'";
-
-	return (v == d) ? '' : n + (v ? ':' + tv + ',' : ':' + fv + ',');
-}
-
-function getStr(p, n, d) {
-	var e = document.forms[0].elements[(p != null ? p + "_" : "") + n];
-	var v = e.type == "text" ? e.value : e.options[e.selectedIndex].value;
-
-	return ((n == d || v == '') ? '' : n + ":'" + jsEncode(v) + "',");
-}
-
-function getInt(p, n, d) {
-	var e = document.forms[0].elements[(p != null ? p + "_" : "") + n];
-	var v = e.type == "text" ? e.value : e.options[e.selectedIndex].value;
-
-	return ((n == d || v == '') ? '' : n + ":" + v.replace(/[^0-9]+/g, '') + ",");
-}
-
-function jsEncode(s) {
-	s = s.replace(new RegExp('\\\\', 'g'), '\\\\');
-	s = s.replace(new RegExp('"', 'g'), '\\"');
-	s = s.replace(new RegExp("'", 'g'), "\\'");
-
-	return s;
-}
-
-function generatePreview(c) {
-	var f = document.forms[0], p = document.getElementById('prev'), h = '', cls, pl, n, type, codebase, wp, hp, nw, nh;
-
-	p.innerHTML = '<!-- x --->';
-
-	nw = parseInt(f.width.value);
-	nh = parseInt(f.height.value);
-
-	if (f.width.value != "" && f.height.value != "") {
-		if (f.constrain.checked) {
-			if (c == 'width' && oldWidth != 0) {
-				wp = nw / oldWidth;
-				nh = Math.round(wp * nh);
-				f.height.value = nh;
-			} else if (c == 'height' && oldHeight != 0) {
-				hp = nh / oldHeight;
-				nw = Math.round(hp * nw);
-				f.width.value = nw;
-			}
-		}
-	}
-
-	if (f.width.value != "")
-		oldWidth = nw;
-
-	if (f.height.value != "")
-		oldHeight = nh;
-
-	// After constrain
-	pl = serializeParameters();
-
-	switch (f.media_type.options[f.media_type.selectedIndex].value) {
-		case "flash":
-			cls = 'clsid:D27CDB6E-AE6D-11cf-96B8-444553540000';
-			codebase = 'http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,40,0';
-			type = 'application/x-shockwave-flash';
-			break;
-
-		case "shockwave":
-			cls = 'clsid:166B1BCA-3F9C-11CF-8075-444553540000';
-			codebase = 'http://download.macromedia.com/pub/shockwave/cabs/director/sw.cab#version=8,5,1,0';
-			type = 'application/x-director';
-			break;
-
-		case "qt":
-			cls = 'clsid:02BF25D5-8C17-4B23-BC80-D3488ABDDC6B';
-			codebase = 'http://www.apple.com/qtactivex/qtplugin.cab#version=6,0,2,0';
-			type = 'video/quicktime';
-			break;
-
-		case "wmp":
-			cls = tinyMCE.getParam('media_wmp6_compatible') ? 'clsid:05589FA1-C356-11CE-BF01-00AA0055595A' : 'clsid:6BF52A52-394A-11D3-B153-00C04F79FAA6';
-			codebase = 'http://activex.microsoft.com/activex/controls/mplayer/en/nsmp2inf.cab#Version=5,1,52,701';
-			type = 'application/x-mplayer2';
-			break;
-
-		case "rmp":
-			cls = 'clsid:CFCDAA03-8BE4-11cf-B84B-0020AFBBCCFA';
-			codebase = 'http://activex.microsoft.com/activex/controls/mplayer/en/nsmp2inf.cab#Version=5,1,52,701';
-			type = 'audio/x-pn-realaudio-plugin';
-			break;
-	}
-
-	if (pl == '') {
-		p.innerHTML = '';
-		return;
-	}
-
-	pl = eval('x={' + pl + '};');
-
-	if (!pl.src) {
-		p.innerHTML = '';
-		return;
-	}
-
-	pl.src = tinyMCE.convertRelativeToAbsoluteURL(tinyMCE.settings['base_href'], pl.src);
-	pl.width = !pl.width ? 100 : pl.width;
-	pl.height = !pl.height ? 100 : pl.height;
-	pl.id = !pl.id ? 'obj' : pl.id;
-	pl.name = !pl.name ? 'eobj' : pl.name;
-	pl.align = !pl.align ? '' : pl.align;
-
-	h += '<object classid="clsid:' + cls + '" codebase="' + codebase + '" width="' + pl.width + '" height="' + pl.height + '" id="' + pl.id + '" name="' + pl.name + '" align="' + pl.align + '">';
-
-	for (n in pl) {
-		h += '<param name="' + n + '" value="' + pl[n] + '">';
-
-		// Add extra url parameter if it's an absolute URL
-		if (n == 'src' && pl[n].indexOf('://') != -1)
-			h += '<param name="url" value="' + pl[n] + '" />';
-	}
-
-	h += '<embed type="' + type + '" ';
-
-	for (n in pl)
-		h += n + '="' + pl[n] + '" ';
-
-	h += '></embed></object>';
-
-	p.innerHTML = "<!-- x --->" + h;
-}
--- a/includes/clientside/tinymce/plugins/media/langs/en.js	Fri Feb 22 12:46:51 2008 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,94 +0,0 @@
-// UK lang variables
-
-tinyMCE.addToLang('media',{
-title : 'Insert / edit embedded media',
-desc : 'Insert / edit embedded media',
-general : 'General',
-advanced : 'Advanced',
-file : 'File',
-list : 'List',
-size : 'Dimensions',
-preview : 'Preview',
-constrain_proportions : 'Constrain proportions',
-type : 'Type',
-id : 'Id',
-name : 'Name',
-class_name : 'Class',
-vspace : 'V-Space',
-hspace : 'H-Space',
-play : 'Auto play',
-loop : 'Loop',
-menu : 'Show menu',
-quality : 'Quality',
-scale : 'Scale',
-align : 'Align',
-salign : 'SAlign',
-wmode : 'WMode',
-bgcolor : 'Background',
-base : 'Base',
-flashvars : 'Flashvars',
-liveconnect : 'SWLiveConnect',
-autohref : 'AutoHREF',
-cache : 'Cache',
-hidden : 'Hidden',
-controller : 'Controller',
-kioskmode : 'Kiosk mode',
-playeveryframe : 'Play every frame',
-targetcache : 'Target cache',
-correction : 'No correction',
-enablejavascript : 'Enable JavaScript',
-starttime : 'Start time',
-endtime : 'End time',
-href : 'Href',
-qtsrcchokespeed : 'Choke speed',
-target : 'Target',
-volume : 'Volume',
-autostart : 'Auto start',
-enabled : 'Enabled',
-fullscreen : 'Fullscreen',
-invokeurls : 'Invoke URLs',
-mute : 'Mute',
-stretchtofit : 'Stretch to fit',
-windowlessvideo : 'Windowless video',
-balance : 'Balance',
-baseurl : 'Base URL',
-captioningid : 'Captioning id',
-currentmarker : 'Current marker',
-currentposition : 'Current position',
-defaultframe : 'Default frame',
-playcount : 'Play count',
-rate : 'Rate',
-uimode : 'UI Mode',
-flash_options : 'Flash options',
-qt_options : 'Quicktime options',
-wmp_options : 'Windows media player options',
-rmp_options : 'Real media player options',
-shockwave_options : 'Shockwave options',
-autogotourl : 'Auto goto URL',
-center : 'Center',
-imagestatus : 'Image status',
-maintainaspect : 'Maintain aspect',
-nojava : 'No java',
-prefetch : 'Prefetch',
-shuffle : 'Shuffle',
-console : 'Console',
-numloop : 'Num loops',
-controls : 'Controls',
-scriptcallbacks : 'Script callbacks',
-swstretchstyle : 'Stretch style',
-swstretchhalign : 'Stretch H-Align',
-swstretchvalign : 'Stretch V-Align',
-sound : 'Sound',
-progress : 'Progress',
-qtsrc : 'QT Src',
-qt_stream_warn : 'Streamed rtsp resources should be added to the QT Src field under the advanced tab.\nYou should also add a non streamed version to the Src field..',
-align_top : 'Top',
-align_right : 'Right',
-align_bottom : 'Bottom',
-align_left : 'Left',
-align_center : 'Center',
-align_top_left : 'Top left',
-align_top_right : 'Top right',
-align_bottom_left : 'Bottom left',
-align_bottom_right : 'Bottom right'
-});
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/includes/clientside/tinymce/plugins/media/langs/en_dlg.js	Fri Feb 22 12:51:53 2008 -0500
@@ -0,0 +1,103 @@
+tinyMCE.addI18n('en.media_dlg',{
+title:"Insert / edit embedded media",
+general:"General",
+advanced:"Advanced",
+file:"File/URL",
+list:"List",
+size:"Dimensions",
+preview:"Preview",
+constrain_proportions:"Constrain proportions",
+type:"Type",
+id:"Id",
+name:"Name",
+class_name:"Class",
+vspace:"V-Space",
+hspace:"H-Space",
+play:"Auto play",
+loop:"Loop",
+menu:"Show menu",
+quality:"Quality",
+scale:"Scale",
+align:"Align",
+salign:"SAlign",
+wmode:"WMode",
+bgcolor:"Background",
+base:"Base",
+flashvars:"Flashvars",
+liveconnect:"SWLiveConnect",
+autohref:"AutoHREF",
+cache:"Cache",
+hidden:"Hidden",
+controller:"Controller",
+kioskmode:"Kiosk mode",
+playeveryframe:"Play every frame",
+targetcache:"Target cache",
+correction:"No correction",
+enablejavascript:"Enable JavaScript",
+starttime:"Start time",
+endtime:"End time",
+href:"Href",
+qtsrcchokespeed:"Choke speed",
+target:"Target",
+volume:"Volume",
+autostart:"Auto start",
+enabled:"Enabled",
+fullscreen:"Fullscreen",
+invokeurls:"Invoke URLs",
+mute:"Mute",
+stretchtofit:"Stretch to fit",
+windowlessvideo:"Windowless video",
+balance:"Balance",
+baseurl:"Base URL",
+captioningid:"Captioning id",
+currentmarker:"Current marker",
+currentposition:"Current position",
+defaultframe:"Default frame",
+playcount:"Play count",
+rate:"Rate",
+uimode:"UI Mode",
+flash_options:"Flash options",
+qt_options:"Quicktime options",
+wmp_options:"Windows media player options",
+rmp_options:"Real media player options",
+shockwave_options:"Shockwave options",
+autogotourl:"Auto goto URL",
+center:"Center",
+imagestatus:"Image status",
+maintainaspect:"Maintain aspect",
+nojava:"No java",
+prefetch:"Prefetch",
+shuffle:"Shuffle",
+console:"Console",
+numloop:"Num loops",
+controls:"Controls",
+scriptcallbacks:"Script callbacks",
+swstretchstyle:"Stretch style",
+swstretchhalign:"Stretch H-Align",
+swstretchvalign:"Stretch V-Align",
+sound:"Sound",
+progress:"Progress",
+qtsrc:"QT Src",
+qt_stream_warn:"Streamed rtsp resources should be added to the QT Src field under the advanced tab.\nYou should also add a non streamed version to the Src field..",
+align_top:"Top",
+align_right:"Right",
+align_bottom:"Bottom",
+align_left:"Left",
+align_center:"Center",
+align_top_left:"Top left",
+align_top_right:"Top right",
+align_bottom_left:"Bottom left",
+align_bottom_right:"Bottom right",
+flv_options:"Flash video options",
+flv_scalemode:"Scale mode",
+flv_buffer:"Buffer",
+flv_startimage:"Start image",
+flv_starttime:"Start time",
+flv_defaultvolume:"Default volumne",
+flv_hiddengui:"Hidden GUI",
+flv_autostart:"Auto start",
+flv_loop:"Loop",
+flv_showscalemodes:"Show scale modes",
+flv_smoothvideo:"Smooth video",
+flv_jscallback:"JS Callback"
+});
\ No newline at end of file
--- a/includes/clientside/tinymce/plugins/media/media.htm	Fri Feb 22 12:46:51 2008 -0500
+++ b/includes/clientside/tinymce/plugins/media/media.htm	Fri Feb 22 12:51:53 2008 -0500
@@ -1,35 +1,37 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
 <html xmlns="http://www.w3.org/1999/xhtml">
 <head>
-	<title>{$lang_media_title}</title>
-	<script language="javascript" type="text/javascript" src="../../tiny_mce_popup.js"></script>
-	<script language="javascript" type="text/javascript" src="jscripts/media.js"></script>
-	<script language="javascript" type="text/javascript" src="../../utils/mctabs.js"></script>
-	<script language="javascript" type="text/javascript" src="../../utils/validate.js"></script>
-	<script language="javascript" type="text/javascript" src="../../utils/form_utils.js"></script>
-	<script language="javascript" type="text/javascript" src="../../utils/editable_selects.js"></script>
+	<title>{#media_dlg.title}</title>
+	<script type="text/javascript" src="../../tiny_mce_popup.js"></script>
+	<script type="text/javascript" src="js/media.js"></script>
+	<script type="text/javascript" src="../../utils/mctabs.js"></script>
+	<script type="text/javascript" src="../../utils/validate.js"></script>
+	<script type="text/javascript" src="../../utils/form_utils.js"></script>
+	<script type="text/javascript" src="../../utils/editable_selects.js"></script>
 	<link href="css/media.css" rel="stylesheet" type="text/css" />
 	<base target="_self" />
 </head>
-<body onload="tinyMCEPopup.executeOnLoad('init();');" style="display: none">
+<body style="display: none">
     <form onsubmit="insertMedia();return false;" action="#">
 		<div class="tabs">
 			<ul>
-				<li id="general_tab" class="current"><span><a href="javascript:mcTabs.displayTab('general_tab','general_panel');generatePreview();" onmousedown="return false;">{$lang_media_general}</a></span></li>
-				<li id="advanced_tab"><span><a href="javascript:mcTabs.displayTab('advanced_tab','advanced_panel');" onmousedown="return false;">{$lang_media_advanced}</a></span></li>
+				<li id="general_tab" class="current"><span><a href="javascript:mcTabs.displayTab('general_tab','general_panel');generatePreview();" onmousedown="return false;">{#media_dlg.general}</a></span></li>
+				<li id="advanced_tab"><span><a href="javascript:mcTabs.displayTab('advanced_tab','advanced_panel');" onmousedown="return false;">{#media_dlg.advanced}</a></span></li>
 			</ul>
 		</div>
 
 		<div class="panel_wrapper">
 			<div id="general_panel" class="panel current">
 				<fieldset>
-					<legend>{$lang_media_general}</legend>
+					<legend>{#media_dlg.general}</legend>
 
 					<table border="0" cellpadding="4" cellspacing="0">
 							<tr>
-								<td><label for="media_type">{$lang_media_type}</label></td>
+								<td><label for="media_type">{#media_dlg.type}</label></td>
 								<td>
 									<select id="media_type" name="media_type" onchange="changedType(this.value);generatePreview();">
 										<option value="flash">Flash</option>
+										<!-- <option value="flv">Flash video (FLV)</option> -->
 										<option value="qt">Quicktime</option>
 										<option value="shockwave">Shockware</option>
 										<option value="wmp">Windows Media</option>
@@ -38,7 +40,7 @@
 								</td>
 							</tr>
 							<tr>
-							<td><label for="src">{$lang_media_file}</label></td>
+							<td><label for="src">{#media_dlg.file}</label></td>
 							  <td>
 									<table border="0" cellspacing="0" cellpadding="0">
 									  <tr>
@@ -49,54 +51,55 @@
 								</td>
 							</tr>
 							<tr id="linklistrow">
-								<td><label for="linklist">{$lang_media_list}</label></td>
+								<td><label for="linklist">{#media_dlg.list}</label></td>
 								<td id="linklistcontainer">&nbsp;</td>
 							</tr>
 							<tr>
-								<td><label for="width">{$lang_media_size}</label></td>
+								<td><label for="width">{#media_dlg.size}</label></td>
 								<td>
-								<table border="0" cellpadding="0" cellspacing="0">
-									<tr>
-										<td><input type="text" id="width" name="width" value="" class="size" onchange="generatePreview('width');" /> x <input type="text" id="height" name="height" value="" class="size"  onchange="generatePreview('height');" /></td>
-										<td>&nbsp;&nbsp;<input id="constrain" type="checkbox" name="constrain" class="checkbox" /></td>
-										<td><label id="constrainlabel" for="constrain">{$lang_media_constrain_proportions}</label></td>
-									</tr>
-								</table>
+									<table border="0" cellpadding="0" cellspacing="0">
+										<tr>
+											<td><input type="text" id="width" name="width" value="" class="size" onchange="generatePreview('width');" /> x <input type="text" id="height" name="height" value="" class="size"  onchange="generatePreview('height');" /></td>
+											<td>&nbsp;&nbsp;<input id="constrain" type="checkbox" name="constrain" class="checkbox" /></td>
+											<td><label id="constrainlabel" for="constrain">{#media_dlg.constrain_proportions}</label></td>
+										</tr>
+									</table>
+								</td>
 							</tr>
 					</table>
 				</fieldset>
 
 				<fieldset>
-					<legend>{$lang_media_preview}</legend>
+					<legend>{#media_dlg.preview}</legend>
 					<div id="prev"></div>
 				</fieldset>
 			</div>
 
 			<div id="advanced_panel" class="panel">
 				<fieldset>
-					<legend>{$lang_media_advanced}</legend>
+					<legend>{#media_dlg.advanced}</legend>
 
 					<table border="0" cellpadding="4" cellspacing="0" width="100%">
 						<tr>
-							<td><label for="id">{$lang_media_id}</label></td>
+							<td><label for="id">{#media_dlg.id}</label></td>
 							<td><input type="text" id="id" name="id" onchange="generatePreview();" /></td>
-							<td><label for="name">{$lang_media_name}</label></td>
+							<td><label for="name">{#media_dlg.name}</label></td>
 							<td><input type="text" id="name" name="name" onchange="generatePreview();" /></td>
 						</tr>
 
 						<tr>
-							<td><label for="align">{$lang_media_align}</label></td>
+							<td><label for="align">{#media_dlg.align}</label></td>
 							<td>
 								<select id="align" name="align" onchange="generatePreview();">
-									<option value="">{$lang_not_set}</option> 
-									<option value="top">{$lang_media_align_top}</option>
-									<option value="right">{$lang_media_align_right}</option>
-									<option value="bottom">{$lang_media_align_bottom}</option>
-									<option value="left">{$lang_media_align_left}</option>
+									<option value="">{#not_set}</option> 
+									<option value="top">{#media_dlg.align_top}</option>
+									<option value="right">{#media_dlg.align_right}</option>
+									<option value="bottom">{#media_dlg.align_bottom}</option>
+									<option value="left">{#media_dlg.align_left}</option>
 								</select>
 							</td>
 
-							<td><label for="bgcolor">{$lang_media_bgcolor}</label></td>
+							<td><label for="bgcolor">{#media_dlg.bgcolor}</label></td>
 							<td>
 								<table border="0" cellpadding="0" cellspacing="0">
 									<tr>
@@ -108,23 +111,23 @@
 						</tr>
 
 						<tr>
-							<td><label for="vspace">{$lang_media_vspace}</label></td>
+							<td><label for="vspace">{#media_dlg.vspace}</label></td>
 							<td><input type="text" id="vspace" name="vspace" class="number" onchange="generatePreview();" /></td>
-							<td><label for="hspace">{$lang_media_hspace}</label></td>
+							<td><label for="hspace">{#media_dlg.hspace}</label></td>
 							<td><input type="text" id="hspace" name="hspace" class="number" onchange="generatePreview();" /></td>
 						</tr>
 					</table>
 				</fieldset>
 
 				<fieldset id="flash_options">
-					<legend>{$lang_media_flash_options}</legend>
+					<legend>{#media_dlg.flash_options}</legend>
 
 					<table border="0" cellpadding="4" cellspacing="0">
 						<tr>
-							<td><label for="flash_quality">{$lang_media_quality}</label></td>
+							<td><label for="flash_quality">{#media_dlg.quality}</label></td>
 							<td>
 								<select id="flash_quality" name="flash_quality" onchange="generatePreview();">
-									<option value="">{$lang_not_set}</option> 
+									<option value="">{#not_set}</option> 
 									<option value="high">high</option>
 									<option value="low">low</option>
 									<option value="autolow">autolow</option>
@@ -133,10 +136,10 @@
 								</select>
 							</td>
 
-							<td><label for="flash_scale">{$lang_media_scale}</label></td>
+							<td><label for="flash_scale">{#media_dlg.scale}</label></td>
 							<td>
 								<select id="flash_scale" name="flash_scale" onchange="generatePreview();">
-									<option value="">{$lang_not_set}</option> 
+									<option value="">{#not_set}</option> 
 									<option value="showall">showall</option>
 									<option value="noborder">noborder</option>
 									<option value="exactfit">exactfit</option>
@@ -145,28 +148,28 @@
 						</tr>
 
 						<tr>
-							<td><label for="flash_wmode">{$lang_media_wmode}</label></td>
+							<td><label for="flash_wmode">{#media_dlg.wmode}</label></td>
 							<td>
 								<select id="flash_wmode" name="flash_wmode" onchange="generatePreview();">
-									<option value="">{$lang_not_set}</option> 
+									<option value="">{#not_set}</option> 
 									<option value="window">window</option>
 									<option value="opaque">opaque</option>
 									<option value="transparent">transparent</option>
 								</select>
 							</td>
 
-							<td><label for="flash_salign">{$lang_media_salign}</label></td>
+							<td><label for="flash_salign">{#media_dlg.salign}</label></td>
 							<td>
 								<select id="flash_salign" name="flash_salign" onchange="generatePreview();">
-									<option value="">{$lang_not_set}</option> 
-									<option value="l">{$lang_media_align_left}</option>
-									<option value="t">{$lang_media_align_top}</option>
-									<option value="r">{$lang_media_align_right}</option>
-									<option value="b">{$lang_media_align_bottom}</option>
-									<option value="tl">{$lang_media_align_top_left}</option>
-									<option value="tr">{$lang_media_align_top_right}</option>
-									<option value="bl">{$lang_media_align_bottom_left}</option>
-									<option value="br">{$lang_media_align_bottom_right}</option>
+									<option value="">{#not_set}</option> 
+									<option value="l">{#media_dlg.align_left}</option>
+									<option value="t">{#media_dlg.align_top}</option>
+									<option value="r">{#media_dlg.align_right}</option>
+									<option value="b">{#media_dlg.align_bottom}</option>
+									<option value="tl">{#media_dlg.align_top_left}</option>
+									<option value="tr">{#media_dlg.align_top_right}</option>
+									<option value="bl">{#media_dlg.align_bottom_left}</option>
+									<option value="br">{#media_dlg.align_bottom_right}</option>
 								</select>
 							</td>
 						</tr>
@@ -176,7 +179,7 @@
 								<table border="0" cellpadding="0" cellspacing="0">
 									<tr>
 										<td><input type="checkbox" class="checkbox" id="flash_play" name="flash_play" checked="checked" onchange="generatePreview();" /></td>
-										<td><label for="flash_play">{$lang_media_play}</label></td>
+										<td><label for="flash_play">{#media_dlg.play}</label></td>
 									</tr>
 								</table>
 							</td>
@@ -185,7 +188,7 @@
 								<table border="0" cellpadding="0" cellspacing="0">
 									<tr>
 										<td><input type="checkbox" class="checkbox" id="flash_loop" name="flash_loop" checked="checked" onchange="generatePreview();" /></td>
-										<td><label for="flash_loop">{$lang_media_loop}</label></td>
+										<td><label for="flash_loop">{#media_dlg.loop}</label></td>
 									</tr>
 								</table>
 							</td>
@@ -196,7 +199,7 @@
 								<table border="0" cellpadding="0" cellspacing="0">
 									<tr>
 										<td><input type="checkbox" class="checkbox" id="flash_menu" name="flash_menu" checked="checked" onchange="generatePreview();" /></td>
-										<td><label for="flash_menu">{$lang_media_menu}</label></td>
+										<td><label for="flash_menu">{#media_dlg.menu}</label></td>
 									</tr>
 								</table>
 							</td>
@@ -205,7 +208,7 @@
 								<table border="0" cellpadding="0" cellspacing="0">
 									<tr>
 										<td><input type="checkbox" class="checkbox" id="flash_swliveconnect" name="flash_swliveconnect" onchange="generatePreview();" /></td>
-										<td><label for="flash_swliveconnect">{$lang_media_liveconnect}</label></td>
+										<td><label for="flash_swliveconnect">{#media_dlg.liveconnect}</label></td>
 									</tr>
 								</table>
 							</td>
@@ -214,19 +217,116 @@
 
 					<table>
 						<tr>
-							<td><label for="flash_base">{$lang_media_base}</label></td>
+							<td><label for="flash_base">{#media_dlg.base}</label></td>
 							<td><input type="text" id="flash_base" name="flash_base" onchange="generatePreview();" /></td>
 						</tr>
 
 						<tr>
-							<td><label for="flash_flashvars">{$lang_media_flashvars}</label></td>
+							<td><label for="flash_flashvars">{#media_dlg.flashvars}</label></td>
 							<td><input type="text" id="flash_flashvars" name="flash_flashvars" onchange="generatePreview();" /></td>
 						</tr>
 					</table>
 				</fieldset>
 
+				<fieldset id="flv_options">
+					<legend>{#media_dlg.flv_options}</legend>
+
+					<table border="0" cellpadding="4" cellspacing="0">
+						<tr>
+							<td><label for="flv_scalemode">{#media_dlg.flv_scalemode}</label></td>
+							<td>
+								<select id="flv_scalemode" name="flv_scalemode" onchange="generatePreview();">
+									<option value="">{#not_set}</option> 
+									<option value="none">none</option>
+									<option value="double">double</option>
+									<option value="full">full</option>
+								</select>
+							</td>
+
+							<td><label for="flv_buffer">{#media_dlg.flv_buffer}</label></td>
+							<td><input type="text" id="flv_buffer" name="flv_buffer" onchange="generatePreview();" /></td>
+						</tr>
+
+						<tr>
+							<td><label for="flv_startimage">{#media_dlg.flv_startimage}</label></td>
+							<td><input type="text" id="flv_startimage" name="flv_startimage" onchange="generatePreview();" /></td>
+
+							<td><label for="flv_starttime">{#media_dlg.flv_starttime}</label></td>
+							<td><input type="text" id="flv_starttime" name="flv_starttime" onchange="generatePreview();" /></td>
+						</tr>
+
+						<tr>
+							<td><label for="flv_defaultvolume">{#media_dlg.flv_defaultvolume}</label></td>
+							<td><input type="text" id="flv_defaultvolume" name="flv_defaultvolume" onchange="generatePreview();" /></td>
+
+							<td><label for="flv_starttime">{#media_dlg.flv_starttime}</label></td>
+							<td><input type="text" id="flv_starttime" name="flv_starttime" onchange="generatePreview();" /></td>
+						</tr>
+
+						<tr>
+							<td colspan="2">
+								<table border="0" cellpadding="0" cellspacing="0">
+									<tr>
+										<td><input type="checkbox" class="checkbox" id="flv_hiddengui" name="flv_hiddengui" checked="checked" onchange="generatePreview();" /></td>
+										<td><label for="flv_hiddengui">{#media_dlg.flv_hiddengui}</label></td>
+									</tr>
+								</table>
+							</td>
+
+							<td colspan="2">
+								<table border="0" cellpadding="0" cellspacing="0">
+									<tr>
+										<td><input type="checkbox" class="checkbox" id="flv_autostart" name="flv_autostart" checked="checked" onchange="generatePreview();" /></td>
+										<td><label for="flv_autostart">{#media_dlg.flv_autostart}</label></td>
+									</tr>
+								</table>
+							</td>
+						</tr>
+
+						<tr>
+							<td colspan="2">
+								<table border="0" cellpadding="0" cellspacing="0">
+									<tr>
+										<td><input type="checkbox" class="checkbox" id="flv_loop" name="flv_loop" checked="checked" onchange="generatePreview();" /></td>
+										<td><label for="flv_loop">{#media_dlg.flv_loop}</label></td>
+									</tr>
+								</table>
+							</td>
+
+							<td colspan="2">
+								<table border="0" cellpadding="0" cellspacing="0">
+									<tr>
+										<td><input type="checkbox" class="checkbox" id="flv_showscalemodes" name="flv_showscalemodes" onchange="generatePreview();" /></td>
+										<td><label for="flv_showscalemodes">{#media_dlg.flv_showscalemodes}</label></td>
+									</tr>
+								</table>
+							</td>
+						</tr>
+
+						<tr>
+							<td colspan="2">
+								<table border="0" cellpadding="0" cellspacing="0">
+									<tr>
+										<td><input type="checkbox" class="checkbox" id="flv_smoothvideo" name="flash_flv_flv_smoothvideosmoothvideo" checked="checked" onchange="generatePreview();" /></td>
+										<td><label for="flv_smoothvideo">{#media_dlg.flv_smoothvideo}</label></td>
+									</tr>
+								</table>
+							</td>
+
+							<td colspan="2">
+								<table border="0" cellpadding="0" cellspacing="0">
+									<tr>
+										<td><input type="checkbox" class="checkbox" id="flv_jscallback" name="flv_jscallback" onchange="generatePreview();" /></td>
+										<td><label for="flv_jscallback">{#media_dlg.flv_jscallback}</label></td>
+									</tr>
+								</table>
+							</td>
+						</tr>
+					</table>
+				</fieldset>
+
 				<fieldset id="qt_options">
-					<legend>{$lang_media_qt_options}</legend>
+					<legend>{#media_dlg.qt_options}</legend>
 
 					<table border="0" cellpadding="4" cellspacing="0">
 						<tr>
@@ -234,7 +334,7 @@
 								<table border="0" cellpadding="0" cellspacing="0">
 									<tr>
 										<td><input type="checkbox" class="checkbox" id="qt_loop" name="qt_loop" onchange="generatePreview();" /></td>
-										<td><label for="qt_loop">{$lang_media_loop}</label></td>
+										<td><label for="qt_loop">{#media_dlg.loop}</label></td>
 									</tr>
 								</table>
 							</td>
@@ -242,8 +342,8 @@
 							<td colspan="2">
 								<table border="0" cellpadding="0" cellspacing="0">
 									<tr>
-										<td><input type="checkbox" class="checkbox" id="qt_autoplay" name="qt_autoplay" onchange="generatePreview();" /></td>
-										<td><label for="qt_autoplay">{$lang_media_play}</label></td>
+										<td><input type="checkbox" class="checkbox" id="qt_autoplay" name="qt_autoplay" checked="checked" onchange="generatePreview();" /></td>
+										<td><label for="qt_autoplay">{#media_dlg.play}</label></td>
 									</tr>
 								</table>
 							</td>
@@ -254,7 +354,7 @@
 								<table border="0" cellpadding="0" cellspacing="0">
 									<tr>
 										<td><input type="checkbox" class="checkbox" id="qt_cache" name="qt_cache" onchange="generatePreview();" /></td>
-										<td><label for="qt_cache">{$lang_media_cache}</label></td>
+										<td><label for="qt_cache">{#media_dlg.cache}</label></td>
 									</tr>
 								</table>
 							</td>
@@ -263,7 +363,7 @@
 								<table border="0" cellpadding="0" cellspacing="0">
 									<tr>
 										<td><input type="checkbox" class="checkbox" id="qt_controller" name="qt_controller" checked="checked" onchange="generatePreview();" /></td>
-										<td><label for="qt_controller">{$lang_media_controller}</label></td>
+										<td><label for="qt_controller">{#media_dlg.controller}</label></td>
 									</tr>
 								</table>
 							</td>
@@ -274,7 +374,7 @@
 								<table border="0" cellpadding="0" cellspacing="0">
 									<tr>
 										<td><input type="checkbox" class="checkbox" id="qt_correction" name="qt_correction" onchange="generatePreview();" /></td>
-										<td><label for="qt_correction">{$lang_media_correction}</label></td>
+										<td><label for="qt_correction">{#media_dlg.correction}</label></td>
 									</tr>
 								</table>
 							</td>
@@ -283,7 +383,7 @@
 								<table border="0" cellpadding="0" cellspacing="0">
 									<tr>
 										<td><input type="checkbox" class="checkbox" id="qt_enablejavascript" name="qt_enablejavascript" onchange="generatePreview();" /></td>
-										<td><label for="qt_enablejavascript">{$lang_media_enablejavascript}</label></td>
+										<td><label for="qt_enablejavascript">{#media_dlg.enablejavascript}</label></td>
 									</tr>
 								</table>
 							</td>
@@ -294,7 +394,7 @@
 								<table border="0" cellpadding="0" cellspacing="0">
 									<tr>
 										<td><input type="checkbox" class="checkbox" id="qt_kioskmode" name="qt_kioskmode" onchange="generatePreview();" /></td>
-										<td><label for="qt_kioskmode">{$lang_media_kioskmode}</label></td>
+										<td><label for="qt_kioskmode">{#media_dlg.kioskmode}</label></td>
 									</tr>
 								</table>
 							</td>
@@ -303,7 +403,7 @@
 								<table border="0" cellpadding="0" cellspacing="0">
 									<tr>
 										<td><input type="checkbox" class="checkbox" id="qt_autohref" name="qt_autohref" onchange="generatePreview();" /></td>
-										<td><label for="qt_autohref">{$lang_media_autohref}</label></td>
+										<td><label for="qt_autohref">{#media_dlg.autohref}</label></td>
 									</tr>
 								</table>
 							</td>
@@ -314,7 +414,7 @@
 								<table border="0" cellpadding="0" cellspacing="0">
 									<tr>
 										<td><input type="checkbox" class="checkbox" id="qt_playeveryframe" name="qt_playeveryframe" onchange="generatePreview();" /></td>
-										<td><label for="qt_playeveryframe">{$lang_media_playeveryframe}</label></td>
+										<td><label for="qt_playeveryframe">{#media_dlg.playeveryframe}</label></td>
 									</tr>
 								</table>
 							</td>
@@ -323,16 +423,16 @@
 								<table border="0" cellpadding="0" cellspacing="0">
 									<tr>
 										<td><input type="checkbox" class="checkbox" id="qt_targetcache" name="qt_targetcache" onchange="generatePreview();" /></td>
-										<td><label for="qt_targetcache">{$lang_media_targetcache}</label></td>
+										<td><label for="qt_targetcache">{#media_dlg.targetcache}</label></td>
 									</tr>
 								</table>
 							</td>
 						</tr>
 
 						<tr>
-							<td><label for="qt_scale">{$lang_media_scale}</label></td>
+							<td><label for="qt_scale">{#media_dlg.scale}</label></td>
 							<td><select id="qt_scale" name="qt_scale" class="mceEditableSelect" onchange="generatePreview();">
-									<option value="">{$lang_not_set}</option> 
+									<option value="">{#not_set}</option> 
 									<option value="tofit">tofit</option>
 									<option value="aspect">aspect</option>
 								</select>
@@ -342,31 +442,31 @@
 						</tr>
 
 						<tr>
-							<td><label for="qt_starttime">{$lang_media_starttime}</label></td>
+							<td><label for="qt_starttime">{#media_dlg.starttime}</label></td>
 							<td><input type="text" id="qt_starttime" name="qt_starttime" onchange="generatePreview();" /></td>
 
-							<td><label for="qt_endtime">{$lang_media_endtime}</label></td>
+							<td><label for="qt_endtime">{#media_dlg.endtime}</label></td>
 							<td><input type="text" id="qt_endtime" name="qt_endtime" onchange="generatePreview();" /></td>
 						</tr>
 
 						<tr>
-							<td><label for="qt_target">{$lang_media_target}</label></td>
+							<td><label for="qt_target">{#media_dlg.target}</label></td>
 							<td><input type="text" id="qt_target" name="qt_target" onchange="generatePreview();" /></td>
 
-							<td><label for="qt_href">{$lang_media_href}</label></td>
+							<td><label for="qt_href">{#media_dlg.href}</label></td>
 							<td><input type="text" id="qt_href" name="qt_href" onchange="generatePreview();" /></td>
 						</tr>
 
 						<tr>
-							<td><label for="qt_qtsrcchokespeed">{$lang_media_qtsrcchokespeed}</label></td>
+							<td><label for="qt_qtsrcchokespeed">{#media_dlg.qtsrcchokespeed}</label></td>
 							<td><input type="text" id="qt_qtsrcchokespeed" name="qt_qtsrcchokespeed" onchange="generatePreview();" /></td>
 
-							<td><label for="qt_volume">{$lang_media_volume}</label></td>
+							<td><label for="qt_volume">{#media_dlg.volume}</label></td>
 							<td><input type="text" id="qt_volume" name="qt_volume" onchange="generatePreview();" /></td>
 						</tr>
 
 						<tr>
-							<td><label for="qt_qtsrc">{$lang_media_qtsrc}</label></td>
+							<td><label for="qt_qtsrc">{#media_dlg.qtsrc}</label></td>
 							<td colspan="4">
 							<table border="0" cellspacing="0" cellpadding="0">
 								  <tr>
@@ -380,7 +480,7 @@
 				</fieldset>
 
 				<fieldset id="wmp_options">
-					<legend>{$lang_media_wmp_options}</legend>
+					<legend>{#media_dlg.wmp_options}</legend>
 
 					<table border="0" cellpadding="4" cellspacing="0">
 						<tr>
@@ -388,7 +488,7 @@
 								<table border="0" cellpadding="0" cellspacing="0">
 									<tr>
 										<td><input type="checkbox" class="checkbox" id="wmp_autostart" name="wmp_autostart" checked="checked" onchange="generatePreview();" /></td>
-										<td><label for="wmp_autostart">{$lang_media_autostart}</label></td>
+										<td><label for="wmp_autostart">{#media_dlg.autostart}</label></td>
 									</tr>
 								</table>
 							</td>
@@ -397,7 +497,7 @@
 								<table border="0" cellpadding="0" cellspacing="0">
 									<tr>
 										<td><input type="checkbox" class="checkbox" id="wmp_enabled" name="wmp_enabled" onchange="generatePreview();" /></td>
-										<td><label for="wmp_enabled">{$lang_media_enabled}</label></td>
+										<td><label for="wmp_enabled">{#media_dlg.enabled}</label></td>
 									</tr>
 								</table>
 							</td>
@@ -408,7 +508,7 @@
 								<table border="0" cellpadding="0" cellspacing="0">
 									<tr>
 										<td><input type="checkbox" class="checkbox" id="wmp_enablecontextmenu" name="wmp_enablecontextmenu" checked="checked" onchange="generatePreview();" /></td>
-										<td><label for="wmp_enablecontextmenu">{$lang_media_menu}</label></td>
+										<td><label for="wmp_enablecontextmenu">{#media_dlg.menu}</label></td>
 									</tr>
 								</table>
 							</td>
@@ -417,7 +517,7 @@
 								<table border="0" cellpadding="0" cellspacing="0">
 									<tr>
 										<td><input type="checkbox" class="checkbox" id="wmp_fullscreen" name="wmp_fullscreen" onchange="generatePreview();" /></td>
-										<td><label for="wmp_fullscreen">{$lang_media_fullscreen}</label></td>
+										<td><label for="wmp_fullscreen">{#media_dlg.fullscreen}</label></td>
 									</tr>
 								</table>
 							</td>
@@ -428,7 +528,7 @@
 								<table border="0" cellpadding="0" cellspacing="0">
 									<tr>
 										<td><input type="checkbox" class="checkbox" id="wmp_invokeurls" name="wmp_invokeurls" checked="checked" onchange="generatePreview();" /></td>
-										<td><label for="wmp_invokeurls">{$lang_media_invokeurls}</label></td>
+										<td><label for="wmp_invokeurls">{#media_dlg.invokeurls}</label></td>
 									</tr>
 								</table>
 							</td>
@@ -437,7 +537,7 @@
 								<table border="0" cellpadding="0" cellspacing="0">
 									<tr>
 										<td><input type="checkbox" class="checkbox" id="wmp_mute" name="wmp_mute" onchange="generatePreview();" /></td>
-										<td><label for="wmp_mute">{$lang_media_mute}</label></td>
+										<td><label for="wmp_mute">{#media_dlg.mute}</label></td>
 									</tr>
 								</table>
 							</td>
@@ -448,7 +548,7 @@
 								<table border="0" cellpadding="0" cellspacing="0">
 									<tr>
 										<td><input type="checkbox" class="checkbox" id="wmp_stretchtofit" name="wmp_stretchtofit" onchange="generatePreview();" /></td>
-										<td><label for="wmp_stretchtofit">{$lang_media_stretchtofit}</label></td>
+										<td><label for="wmp_stretchtofit">{#media_dlg.stretchtofit}</label></td>
 									</tr>
 								</table>
 							</td>
@@ -457,49 +557,49 @@
 								<table border="0" cellpadding="0" cellspacing="0">
 									<tr>
 										<td><input type="checkbox" class="checkbox" id="wmp_windowlessvideo" name="wmp_windowlessvideo" onchange="generatePreview();" /></td>
-										<td><label for="wmp_windowlessvideo">{$lang_media_windowlessvideo}</label></td>
+										<td><label for="wmp_windowlessvideo">{#media_dlg.windowlessvideo}</label></td>
 									</tr>
 								</table>
 							</td>
 						</tr>
 
 						<tr>
-							<td><label for="wmp_balance">{$lang_media_balance}</label></td>
+							<td><label for="wmp_balance">{#media_dlg.balance}</label></td>
 							<td><input type="text" id="wmp_balance" name="wmp_balance" onchange="generatePreview();" /></td>
 
-							<td><label for="wmp_baseurl">{$lang_media_baseurl}</label></td>
+							<td><label for="wmp_baseurl">{#media_dlg.baseurl}</label></td>
 							<td><input type="text" id="wmp_baseurl" name="wmp_baseurl" onchange="generatePreview();" /></td>
 						</tr>
 
 						<tr>
-							<td><label for="wmp_captioningid">{$lang_media_captioningid}</label></td>
+							<td><label for="wmp_captioningid">{#media_dlg.captioningid}</label></td>
 							<td><input type="text" id="wmp_captioningid" name="wmp_captioningid" onchange="generatePreview();" /></td>
 
-							<td><label for="wmp_currentmarker">{$lang_media_currentmarker}</label></td>
+							<td><label for="wmp_currentmarker">{#media_dlg.currentmarker}</label></td>
 							<td><input type="text" id="wmp_currentmarker" name="wmp_currentmarker" onchange="generatePreview();" /></td>
 						</tr>
 
 						<tr>
-							<td><label for="wmp_currentposition">{$lang_media_currentposition}</label></td>
+							<td><label for="wmp_currentposition">{#media_dlg.currentposition}</label></td>
 							<td><input type="text" id="wmp_currentposition" name="wmp_currentposition" onchange="generatePreview();" /></td>
 
-							<td><label for="wmp_defaultframe">{$lang_media_defaultframe}</label></td>
+							<td><label for="wmp_defaultframe">{#media_dlg.defaultframe}</label></td>
 							<td><input type="text" id="wmp_defaultframe" name="wmp_defaultframe" onchange="generatePreview();" /></td>
 						</tr>
 
 						<tr>
-							<td><label for="wmp_playcount">{$lang_media_playcount}</label></td>
+							<td><label for="wmp_playcount">{#media_dlg.playcount}</label></td>
 							<td><input type="text" id="wmp_playcount" name="wmp_playcount" onchange="generatePreview();" /></td>
 
-							<td><label for="wmp_rate">{$lang_media_rate}</label></td>
+							<td><label for="wmp_rate">{#media_dlg.rate}</label></td>
 							<td><input type="text" id="wmp_rate" name="wmp_rate" onchange="generatePreview();" /></td>
 						</tr>
 
 						<tr>
-							<td><label for="wmp_uimode">{$lang_media_uimode}</label></td>
+							<td><label for="wmp_uimode">{#media_dlg.uimode}</label></td>
 							<td><input type="text" id="wmp_uimode" name="wmp_uimode" onchange="generatePreview();" /></td>
 
-							<td><label for="wmp_volume">{$lang_media_volume}</label></td>
+							<td><label for="wmp_volume">{#media_dlg.volume}</label></td>
 							<td><input type="text" id="wmp_volume" name="wmp_volume" onchange="generatePreview();" /></td>
 						</tr>
 
@@ -507,7 +607,7 @@
 				</fieldset>
 
 				<fieldset id="rmp_options">
-					<legend>{$lang_media_rmp_options}</legend>
+					<legend>{#media_dlg.rmp_options}</legend>
 
 					<table border="0" cellpadding="4" cellspacing="0">
 						<tr>
@@ -515,7 +615,7 @@
 								<table border="0" cellpadding="0" cellspacing="0">
 									<tr>
 										<td><input type="checkbox" class="checkbox" id="rmp_autostart" name="rmp_autostart" onchange="generatePreview();" /></td>
-										<td><label for="rmp_autostart">{$lang_media_autostart}</label></td>
+										<td><label for="rmp_autostart">{#media_dlg.autostart}</label></td>
 									</tr>
 								</table>
 							</td>
@@ -524,7 +624,7 @@
 								<table border="0" cellpadding="0" cellspacing="0">
 									<tr>
 										<td><input type="checkbox" class="checkbox" id="rmp_loop" name="rmp_loop" onchange="generatePreview();" /></td>
-										<td><label for="rmp_loop">{$lang_media_loop}</label></td>
+										<td><label for="rmp_loop">{#media_dlg.loop}</label></td>
 									</tr>
 								</table>
 							</td>
@@ -535,7 +635,7 @@
 								<table border="0" cellpadding="0" cellspacing="0">
 									<tr>
 										<td><input type="checkbox" class="checkbox" id="rmp_autogotourl" name="rmp_autogotourl" checked="checked" onchange="generatePreview();" /></td>
-										<td><label for="rmp_autogotourl">{$lang_media_autogotourl}</label></td>
+										<td><label for="rmp_autogotourl">{#media_dlg.autogotourl}</label></td>
 									</tr>
 								</table>
 							</td>
@@ -544,7 +644,7 @@
 								<table border="0" cellpadding="0" cellspacing="0">
 									<tr>
 										<td><input type="checkbox" class="checkbox" id="rmp_center" name="rmp_center" onchange="generatePreview();" /></td>
-										<td><label for="rmp_center">{$lang_media_center}</label></td>
+										<td><label for="rmp_center">{#media_dlg.center}</label></td>
 									</tr>
 								</table>
 							</td>
@@ -555,7 +655,7 @@
 								<table border="0" cellpadding="0" cellspacing="0">
 									<tr>
 										<td><input type="checkbox" class="checkbox" id="rmp_imagestatus" name="rmp_imagestatus" checked="checked" onchange="generatePreview();" /></td>
-										<td><label for="rmp_imagestatus">{$lang_media_imagestatus}</label></td>
+										<td><label for="rmp_imagestatus">{#media_dlg.imagestatus}</label></td>
 									</tr>
 								</table>
 							</td>
@@ -564,7 +664,7 @@
 								<table border="0" cellpadding="0" cellspacing="0">
 									<tr>
 										<td><input type="checkbox" class="checkbox" id="rmp_maintainaspect" name="rmp_maintainaspect" onchange="generatePreview();" /></td>
-										<td><label for="rmp_maintainaspect">{$lang_media_maintainaspect}</label></td>
+										<td><label for="rmp_maintainaspect">{#media_dlg.maintainaspect}</label></td>
 									</tr>
 								</table>
 							</td>
@@ -575,7 +675,7 @@
 								<table border="0" cellpadding="0" cellspacing="0">
 									<tr>
 										<td><input type="checkbox" class="checkbox" id="rmp_nojava" name="rmp_nojava" onchange="generatePreview();" /></td>
-										<td><label for="rmp_nojava">{$lang_media_nojava}</label></td>
+										<td><label for="rmp_nojava">{#media_dlg.nojava}</label></td>
 									</tr>
 								</table>
 							</td>
@@ -584,7 +684,7 @@
 								<table border="0" cellpadding="0" cellspacing="0">
 									<tr>
 										<td><input type="checkbox" class="checkbox" id="rmp_prefetch" name="rmp_prefetch" onchange="generatePreview();" /></td>
-										<td><label for="rmp_prefetch">{$lang_media_prefetch}</label></td>
+										<td><label for="rmp_prefetch">{#media_dlg.prefetch}</label></td>
 									</tr>
 								</table>
 							</td>
@@ -595,7 +695,7 @@
 								<table border="0" cellpadding="0" cellspacing="0">
 									<tr>
 										<td><input type="checkbox" class="checkbox" id="rmp_shuffle" name="rmp_shuffle" onchange="generatePreview();" /></td>
-										<td><label for="rmp_shuffle">{$lang_media_shuffle}</label></td>
+										<td><label for="rmp_shuffle">{#media_dlg.shuffle}</label></td>
 									</tr>
 								</table>
 							</td>
@@ -606,57 +706,57 @@
 						</tr>
 
 						<tr>
-							<td><label for="rmp_console">{$lang_media_console}</label></td>
+							<td><label for="rmp_console">{#media_dlg.console}</label></td>
 							<td><input type="text" id="rmp_console" name="rmp_console" onchange="generatePreview();" /></td>
 
-							<td><label for="rmp_controls">{$lang_media_controls}</label></td>
+							<td><label for="rmp_controls">{#media_dlg.controls}</label></td>
 							<td><input type="text" id="rmp_controls" name="rmp_controls" onchange="generatePreview();" /></td>
 						</tr>
 
 						<tr>
-							<td><label for="rmp_numloop">{$lang_media_numloop}</label></td>
+							<td><label for="rmp_numloop">{#media_dlg.numloop}</label></td>
 							<td><input type="text" id="rmp_numloop" name="rmp_numloop" onchange="generatePreview();" /></td>
 
-							<td><label for="rmp_scriptcallbacks">{$lang_media_scriptcallbacks}</label></td>
+							<td><label for="rmp_scriptcallbacks">{#media_dlg.scriptcallbacks}</label></td>
 							<td><input type="text" id="rmp_scriptcallbacks" name="rmp_scriptcallbacks" onchange="generatePreview();" /></td>
 						</tr>
 					</table>
 				</fieldset>
 
 				<fieldset id="shockwave_options">
-					<legend>{$lang_media_shockwave_options}</legend>
+					<legend>{#media_dlg.shockwave_options}</legend>
 
 					<table border="0" cellpadding="4" cellspacing="0">
 						<tr>
-							<td><label for="shockwave_swstretchstyle">{$lang_media_swstretchstyle}</label></td>
+							<td><label for="shockwave_swstretchstyle">{#media_dlg.swstretchstyle}</label></td>
 							<td>
 								<select id="shockwave_swstretchstyle" name="shockwave_swstretchstyle" onchange="generatePreview();">
-									<option value="none">{$lang_not_set}</option>
+									<option value="none">{#not_set}</option>
 									<option value="meet">Meet</option>
 									<option value="fill">Fill</option>
 									<option value="stage">Stage</option>
 								</select>
 							</td>
 
-							<td><label for="shockwave_swvolume">{$lang_media_volume}</label></td>
+							<td><label for="shockwave_swvolume">{#media_dlg.volume}</label></td>
 							<td><input type="text" id="shockwave_swvolume" name="shockwave_swvolume" onchange="generatePreview();" /></td>
 						</tr>
 
 						<tr>
-							<td><label for="shockwave_swstretchhalign">{$lang_media_swstretchhalign}</label></td>
+							<td><label for="shockwave_swstretchhalign">{#media_dlg.swstretchhalign}</label></td>
 							<td>
 								<select id="shockwave_swstretchhalign" name="shockwave_swstretchhalign" onchange="generatePreview();">
-									<option value="none">{$lang_not_set}</option>
-									<option value="left">{$lang_media_align_left}</option>
-									<option value="center">{$lang_media_align_center}</option>
-									<option value="right">{$lang_media_align_right}</option>
+									<option value="none">{#not_set}</option>
+									<option value="left">{#media_dlg.align_left}</option>
+									<option value="center">{#media_dlg.align_center}</option>
+									<option value="right">{#media_dlg.align_right}</option>
 								</select>
 							</td>
 
-							<td><label for="shockwave_swstretchvalign">{$lang_media_swstretchvalign}</label></td>
+							<td><label for="shockwave_swstretchvalign">{#media_dlg.swstretchvalign}</label></td>
 							<td>
 								<select id="shockwave_swstretchvalign" name="shockwave_swstretchvalign" onchange="generatePreview();">
-									<option value="none">{$lang_not_set}</option>
+									<option value="none">{#not_set}</option>
 									<option value="meet">Meet</option>
 									<option value="fill">Fill</option>
 									<option value="stage">Stage</option>
@@ -669,7 +769,7 @@
 								<table border="0" cellpadding="0" cellspacing="0">
 									<tr>
 										<td><input type="checkbox" class="checkbox" id="shockwave_autostart" name="shockwave_autostart" onchange="generatePreview();" checked="checked" /></td>
-										<td><label for="shockwave_autostart">{$lang_media_autostart}</label></td>
+										<td><label for="shockwave_autostart">{#media_dlg.autostart}</label></td>
 									</tr>
 								</table>
 							</td>
@@ -678,7 +778,7 @@
 								<table border="0" cellpadding="0" cellspacing="0">
 									<tr>
 										<td><input type="checkbox" class="checkbox" id="shockwave_sound" name="shockwave_sound" onchange="generatePreview();" checked="checked" /></td>
-										<td><label for="shockwave_sound">{$lang_media_sound}</label></td>
+										<td><label for="shockwave_sound">{#media_dlg.sound}</label></td>
 									</tr>
 								</table>
 							</td>
@@ -690,7 +790,7 @@
 								<table border="0" cellpadding="0" cellspacing="0">
 									<tr>
 										<td><input type="checkbox" class="checkbox" id="shockwave_swliveconnect" name="shockwave_swliveconnect" onchange="generatePreview();" /></td>
-										<td><label for="shockwave_swliveconnect">{$lang_media_liveconnect}</label></td>
+										<td><label for="shockwave_swliveconnect">{#media_dlg.liveconnect}</label></td>
 									</tr>
 								</table>
 							</td>
@@ -699,7 +799,7 @@
 								<table border="0" cellpadding="0" cellspacing="0">
 									<tr>
 										<td><input type="checkbox" class="checkbox" id="shockwave_progress" name="shockwave_progress" onchange="generatePreview();" checked="checked" /></td>
-										<td><label for="shockwave_progress">{$lang_media_progress}</label></td>
+										<td><label for="shockwave_progress">{#media_dlg.progress}</label></td>
 									</tr>
 								</table>
 							</td>
@@ -711,11 +811,11 @@
 
 		<div class="mceActionPanel">
 			<div style="float: left">
-				<input type="button" id="insert" name="insert" value="{$lang_insert}" onclick="insertMedia();" />
+				<input type="button" id="insert" name="insert" value="{#insert}" onclick="insertMedia();" />
 			</div>
 
 			<div style="float: right">
-				<input type="button" id="cancel" name="cancel" value="{$lang_cancel}" onclick="tinyMCEPopup.close();" />
+				<input type="button" id="cancel" name="cancel" value="{#cancel}" onclick="tinyMCEPopup.close();" />
 			</div>
 		</div>
 	</form>
--- a/includes/clientside/tinymce/plugins/nonbreaking/editor_plugin.js	Fri Feb 22 12:46:51 2008 -0500
+++ b/includes/clientside/tinymce/plugins/nonbreaking/editor_plugin.js	Fri Feb 22 12:51:53 2008 -0500
@@ -1,1 +1,1 @@
-tinyMCE.importPluginLanguagePack('nonbreaking');var TinyMCE_NonBreakingPlugin={getInfo:function(){return{longname:'Nonbreaking space',author:'Moxiecode Systems AB',authorurl:'http://tinymce.moxiecode.com',infourl:'http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/nonbreaking',version:tinyMCE.majorVersion+"."+tinyMCE.minorVersion}},getControlHTML:function(cn){switch(cn){case"nonbreaking":return tinyMCE.getButtonHTML(cn,'lang_nonbreaking_desc','{$pluginurl}/images/nonbreaking.gif','mceNonBreaking',false)}return""},execCommand:function(editor_id,element,command,user_interface,value){var inst=tinyMCE.getInstanceById(editor_id),h;switch(command){case"mceNonBreaking":h=(inst.visualChars&&inst.visualChars.state)?'<span class="mceItemHiddenVisualChar">&middot;</span>':'&nbsp;';tinyMCE.execInstanceCommand(editor_id,'mceInsertContent',false,h);return true}return false},handleEvent:function(e){var inst,h;if(!tinyMCE.isOpera&&e.type=='keydown'&&e.keyCode==9&&tinyMCE.getParam('nonbreaking_force_tab',false)){inst=tinyMCE.selectedInstance;h=(inst.visualChars&&inst.visualChars.state)?'<span class="mceItemHiddenVisualChar">&middot;&middot;&middot;</span>':'&nbsp;&nbsp;&nbsp;';tinyMCE.execInstanceCommand(inst.editorId,'mceInsertContent',false,h);tinyMCE.cancelEvent(e);return false}return true}};tinyMCE.addPlugin("nonbreaking",TinyMCE_NonBreakingPlugin);
\ No newline at end of file
+(function(){tinymce.create('tinymce.plugins.Nonbreaking',{init:function(ed,url){var t=this;t.editor=ed;ed.addCommand('mceNonBreaking',function(){ed.execCommand('mceInsertContent',false,(ed.plugins.visualchars&&ed.plugins.visualchars.state)?'<span class="mceItemHidden mceVisualNbsp">&middot;</span>':'&nbsp;');});ed.addButton('nonbreaking',{title:'nonbreaking.nonbreaking_desc',cmd:'mceNonBreaking'});if(ed.getParam('nonbreaking_force_tab')){ed.onKeyDown.add(function(ed,e){if(tinymce.isIE&&e.keyCode==9){ed.execCommand('mceNonBreaking');ed.execCommand('mceNonBreaking');ed.execCommand('mceNonBreaking');tinymce.dom.Event.cancel(e);}});}},getInfo:function(){return{longname:'Nonbreaking space',author:'Moxiecode Systems AB',authorurl:'http://tinymce.moxiecode.com',infourl:'http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/nonbreaking',version:tinymce.majorVersion+"."+tinymce.minorVersion};}});tinymce.PluginManager.add('nonbreaking',tinymce.plugins.Nonbreaking);})();
\ No newline at end of file
--- a/includes/clientside/tinymce/plugins/nonbreaking/editor_plugin_src.js	Fri Feb 22 12:46:51 2008 -0500
+++ b/includes/clientside/tinymce/plugins/nonbreaking/editor_plugin_src.js	Fri Feb 22 12:51:53 2008 -0500
@@ -1,62 +1,50 @@
 /**
- * $Id: editor_plugin_src.js 42 2006-08-08 14:32:24Z spocke $
+ * $Id: editor_plugin_src.js 201 2007-02-12 15:56:56Z spocke $
  *
  * @author Moxiecode
- * @copyright Copyright © 2004-2007, Moxiecode Systems AB, All rights reserved.
+ * @copyright Copyright © 2004-2008, Moxiecode Systems AB, All rights reserved.
  */
 
-/* Import plugin specific language pack */
-tinyMCE.importPluginLanguagePack('nonbreaking');
+(function() {
+	tinymce.create('tinymce.plugins.Nonbreaking', {
+		init : function(ed, url) {
+			var t = this;
+
+			t.editor = ed;
+
+			// Register commands
+			ed.addCommand('mceNonBreaking', function() {
+				ed.execCommand('mceInsertContent', false, (ed.plugins.visualchars && ed.plugins.visualchars.state) ? '<span class="mceItemHidden mceVisualNbsp">&middot;</span>' : '&nbsp;');
+			});
+
+			// Register buttons
+			ed.addButton('nonbreaking', {title : 'nonbreaking.nonbreaking_desc', cmd : 'mceNonBreaking'});
 
-var TinyMCE_NonBreakingPlugin = {
-	getInfo : function() {
-		return {
-			longname : 'Nonbreaking space',
-			author : 'Moxiecode Systems AB',
-			authorurl : 'http://tinymce.moxiecode.com',
-			infourl : 'http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/nonbreaking',
-			version : tinyMCE.majorVersion + "." + tinyMCE.minorVersion
-		};
-	},
+			if (ed.getParam('nonbreaking_force_tab')) {
+				ed.onKeyDown.add(function(ed, e) {
+					if (tinymce.isIE && e.keyCode == 9) {
+						ed.execCommand('mceNonBreaking');
+						ed.execCommand('mceNonBreaking');
+						ed.execCommand('mceNonBreaking');
+						tinymce.dom.Event.cancel(e);
+					}
+				});
+			}
+		},
 
-	getControlHTML : function(cn) {
-		switch (cn) {
-			case "nonbreaking":
-				return tinyMCE.getButtonHTML(cn, 'lang_nonbreaking_desc', '{$pluginurl}/images/nonbreaking.gif', 'mceNonBreaking', false);
+		getInfo : function() {
+			return {
+				longname : 'Nonbreaking space',
+				author : 'Moxiecode Systems AB',
+				authorurl : 'http://tinymce.moxiecode.com',
+				infourl : 'http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/nonbreaking',
+				version : tinymce.majorVersion + "." + tinymce.minorVersion
+			};
 		}
 
-		return "";
-	},
-
-
-	execCommand : function(editor_id, element, command, user_interface, value) {
-		var inst = tinyMCE.getInstanceById(editor_id), h;
-
-		switch (command) {
-			case "mceNonBreaking":
-				h = (inst.visualChars && inst.visualChars.state) ? '<span class="mceItemHiddenVisualChar">&middot;</span>' : '&nbsp;';
-				tinyMCE.execInstanceCommand(editor_id, 'mceInsertContent', false, h);
-				return true;
-		}
-
-		return false;
-	},
+		// Private methods
+	});
 
-	handleEvent : function(e) {
-		var inst, h;
-
-		if (!tinyMCE.isOpera && e.type == 'keydown' && e.keyCode == 9 && tinyMCE.getParam('nonbreaking_force_tab', false)) {
-			inst = tinyMCE.selectedInstance;
-
-			h = (inst.visualChars && inst.visualChars.state) ? '<span class="mceItemHiddenVisualChar">&middot;&middot;&middot;</span>' : '&nbsp;&nbsp;&nbsp;';
-			tinyMCE.execInstanceCommand(inst.editorId, 'mceInsertContent', false, h);
-
-			tinyMCE.cancelEvent(e);
-			return false;
-		}
-
-		return true;
-	}
-};
-
-tinyMCE.addPlugin("nonbreaking", TinyMCE_NonBreakingPlugin);
+	// Register plugin
+	tinymce.PluginManager.add('nonbreaking', tinymce.plugins.Nonbreaking);
+})();
\ No newline at end of file
Binary file includes/clientside/tinymce/plugins/nonbreaking/images/nonbreaking.gif has changed
--- a/includes/clientside/tinymce/plugins/nonbreaking/langs/en.js	Fri Feb 22 12:46:51 2008 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,5 +0,0 @@
-// UK lang variables
-
-tinyMCE.addToLang('nonbreaking',{
-desc : 'Insert non-breaking space character'
-});
--- a/includes/clientside/tinymce/plugins/noneditable/css/noneditable.css	Fri Feb 22 12:46:51 2008 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,9 +0,0 @@
-/* This is the CSS file for the noneditable elements plugin */
-
-.mceEditable {
-	/*border: 1px dotted #0000cc;*/
-}
-
-.mceNonEditable {
-	/*border: 1px dotted #cc0000;*/
-}
--- a/includes/clientside/tinymce/plugins/noneditable/editor_plugin.js	Fri Feb 22 12:46:51 2008 -0500
+++ b/includes/clientside/tinymce/plugins/noneditable/editor_plugin.js	Fri Feb 22 12:51:53 2008 -0500
@@ -1,1 +1,1 @@
-var TinyMCE_NonEditablePlugin={getInfo:function(){return{longname:'Non editable elements',author:'Moxiecode Systems AB',authorurl:'http://tinymce.moxiecode.com',infourl:'http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/noneditable',version:tinyMCE.majorVersion+"."+tinyMCE.minorVersion}},initInstance:function(inst){tinyMCE.importCSS(inst.getDoc(),tinyMCE.baseURL+"/plugins/noneditable/css/noneditable.css");if(tinyMCE.isMSIE5_0)tinyMCE.settings['plugins']=tinyMCE.settings['plugins'].replace(/noneditable/gi,'Noneditable')},handleEvent:function(e){return this._moveSelection(e,tinyMCE.selectedInstance)},cleanup:function(type,content,inst){switch(type){case"insert_to_editor_dom":var nodes,i,editClass,nonEditClass,editable,elm;if(tinyMCE.isGecko)return content;nodes=tinyMCE.getNodeTree(content,[],1);editClass=tinyMCE.getParam("noneditable_editable_class","mceEditable");nonEditClass=tinyMCE.getParam("noneditable_noneditable_class","mceNonEditable");for(i=0;i<nodes.length;i++){elm=nodes[i];editable=tinyMCE.getAttrib(elm,"contenteditable");if(new RegExp("true|false","gi").test(editable))TinyMCE_NonEditablePlugin._setEditable(elm,editable=="true");if(tinyMCE.isIE){if(tinyMCE.hasCSSClass(elm,editClass))elm.contentEditable=true;if(tinyMCE.hasCSSClass(elm,nonEditClass))elm.contentEditable=false}}break;case"insert_to_editor":var editClass=tinyMCE.getParam("noneditable_editable_class","mceEditable");var nonEditClass=tinyMCE.getParam("noneditable_noneditable_class","mceNonEditable");content=content.replace(/mceItemEditable/g,editClass);content=content.replace(/mceItemNonEditable/g,nonEditClass);if(tinyMCE.isIE&&(content.indexOf(editClass)!=-1||content.indexOf(nonEditClass)!=-1)){content=content.replace(new RegExp("class=\"(.+)("+editClass+")\"","gi"),'class="$1$2" contenteditable="true"');content=content.replace(new RegExp("class=\"(.+)("+nonEditClass+")\"","gi"),'class="$1$2" contenteditable="false"');content=content.replace(new RegExp("class=\"("+editClass+")([^\"]*)\"","gi"),'class="$1$2" contenteditable="true"');content=content.replace(new RegExp("class=\"("+nonEditClass+")([^\"]*)\"","gi"),'class="$1$2" contenteditable="false"');content=content.replace(new RegExp("class=\"(.+)("+editClass+")([^\"]*)\"","gi"),'class="$1$2$3" contenteditable="true"');content=content.replace(new RegExp("class=\"(.+)("+nonEditClass+")([^\"]*)\"","gi"),'class="$1$2$3" contenteditable="false"')}break;case"get_from_editor_dom":if(tinyMCE.isGecko)return content;if(tinyMCE.getParam("noneditable_leave_contenteditable",false)){var nodes=tinyMCE.getNodeTree(content,new Array(),1);for(var i=0;i<nodes.length;i++)nodes[i].removeAttribute("contenteditable")}break}return content},_moveSelection:function(e,inst){var s,r,sc,ec,el,c=tinyMCE.getParam('noneditable_editable_class','mceNonEditable');if(!inst)return true;if(tinyMCE.isGecko){s=inst.selection.getSel();r=s.getRangeAt(0);sc=tinyMCE.getParentNode(r.startContainer,function(n){return tinyMCE.hasCSSClass(n,c)});ec=tinyMCE.getParentNode(r.endContainer,function(n){return tinyMCE.hasCSSClass(n,c)});sc&&r.setStartBefore(sc);ec&&r.setEndAfter(ec);if(sc||ec){if(e.type=='keypress'&&e.keyCode==39){el=sc||ec;}s.removeAllRanges();s.addRange(r);return tinyMCE.cancelEvent(e)}}return true},_setEditable:function(elm,state){var editClass=tinyMCE.getParam("noneditable_editable_class","mceEditable");var nonEditClass=tinyMCE.getParam("noneditable_noneditable_class","mceNonEditable");var className=elm.className?elm.className:"";if(className.indexOf(editClass)!=-1||className.indexOf(nonEditClass)!=-1)return;if((className=tinyMCE.getAttrib(elm,"class"))!="")className+=" ";className+=state?editClass:nonEditClass;elm.setAttribute("class",className);elm.className=className}};tinyMCE.addPlugin("noneditable",TinyMCE_NonEditablePlugin);
\ No newline at end of file
+(function(){var Event=tinymce.dom.Event;tinymce.create('tinymce.plugins.NonEditablePlugin',{init:function(ed,url){var t=this,editClass,nonEditClass;t.editor=ed;editClass=ed.getParam("noneditable_editable_class","mceEditable");nonEditClass=ed.getParam("noneditable_noneditable_class","mceNonEditable");ed.onNodeChange.addToTop(function(ed,cm,n){var sc,ec;sc=ed.dom.getParent(ed.selection.getStart(),function(n){return ed.dom.hasClass(n,nonEditClass);});ec=ed.dom.getParent(ed.selection.getEnd(),function(n){return ed.dom.hasClass(n,nonEditClass);});if(sc||ec){t._setDisabled(1);return false;}else t._setDisabled(0);});},getInfo:function(){return{longname:'Non editable elements',author:'Moxiecode Systems AB',authorurl:'http://tinymce.moxiecode.com',infourl:'http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/noneditable',version:tinymce.majorVersion+"."+tinymce.minorVersion};},_block:function(ed,e){return Event.cancel(e);},_setDisabled:function(s){var t=this,ed=t.editor;tinymce.each(ed.controlManager.controls,function(c){c.setDisabled(s);});if(s!==t.disabled){if(s){ed.onKeyDown.addToTop(t._block);ed.onKeyPress.addToTop(t._block);ed.onKeyUp.addToTop(t._block);ed.onPaste.addToTop(t._block);}else{ed.onKeyDown.remove(t._block);ed.onKeyPress.remove(t._block);ed.onKeyUp.remove(t._block);ed.onPaste.remove(t._block);}t.disabled=s;}}});tinymce.PluginManager.add('noneditable',tinymce.plugins.NonEditablePlugin);})();
\ No newline at end of file
--- a/includes/clientside/tinymce/plugins/noneditable/editor_plugin_src.js	Fri Feb 22 12:46:51 2008 -0500
+++ b/includes/clientside/tinymce/plugins/noneditable/editor_plugin_src.js	Fri Feb 22 12:51:53 2008 -0500
@@ -1,153 +1,81 @@
 /**
- * $Id: editor_plugin_src.js 205 2007-02-12 18:58:29Z spocke $
+ * $Id: editor_plugin_src.js 520 2008-01-07 16:30:32Z spocke $
  *
  * @author Moxiecode
- * @copyright Copyright © 2004-2007, Moxiecode Systems AB, All rights reserved.
+ * @copyright Copyright © 2004-2008, Moxiecode Systems AB, All rights reserved.
  */
 
-var TinyMCE_NonEditablePlugin = {
-	getInfo : function() {
-		return {
-			longname : 'Non editable elements',
-			author : 'Moxiecode Systems AB',
-			authorurl : 'http://tinymce.moxiecode.com',
-			infourl : 'http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/noneditable',
-			version : tinyMCE.majorVersion + "." + tinyMCE.minorVersion
-		};
-	},
+(function() {
+	var Event = tinymce.dom.Event;
+
+	tinymce.create('tinymce.plugins.NonEditablePlugin', {
+		init : function(ed, url) {
+			var t = this, editClass, nonEditClass;
+
+			t.editor = ed;
+			editClass = ed.getParam("noneditable_editable_class", "mceEditable");
+			nonEditClass = ed.getParam("noneditable_noneditable_class", "mceNonEditable");
+
+			ed.onNodeChange.addToTop(function(ed, cm, n) {
+				var sc, ec;
 
-	initInstance : function(inst) {
-		tinyMCE.importCSS(inst.getDoc(), tinyMCE.baseURL + "/plugins/noneditable/css/noneditable.css");
+				// Block if start or end is inside a non editable element
+				sc = ed.dom.getParent(ed.selection.getStart(), function(n) {
+					return ed.dom.hasClass(n, nonEditClass);
+				});
+
+				ec = ed.dom.getParent(ed.selection.getEnd(), function(n) {
+					return ed.dom.hasClass(n, nonEditClass);
+				});
 
-		// Ugly hack
-		if (tinyMCE.isMSIE5_0)
-			tinyMCE.settings['plugins'] = tinyMCE.settings['plugins'].replace(/noneditable/gi, 'Noneditable');
-	},
-
-	handleEvent : function(e) {
-		return this._moveSelection(e, tinyMCE.selectedInstance);
-	},
+				// Block or unblock
+				if (sc || ec) {
+					t._setDisabled(1);
+					return false;
+				} else
+					t._setDisabled(0);
+			});
+		},
 
-	cleanup : function(type, content, inst) {
-		switch (type) {
-			case "insert_to_editor_dom":
-				var nodes, i, editClass, nonEditClass, editable, elm;
+		getInfo : function() {
+			return {
+				longname : 'Non editable elements',
+				author : 'Moxiecode Systems AB',
+				authorurl : 'http://tinymce.moxiecode.com',
+				infourl : 'http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/noneditable',
+				version : tinymce.majorVersion + "." + tinymce.minorVersion
+			};
+		},
 
-				// Pass through Gecko
-				if (tinyMCE.isGecko)
-					return content;
-
-				nodes = tinyMCE.getNodeTree(content, [], 1);
-
-				editClass = tinyMCE.getParam("noneditable_editable_class", "mceEditable");
-				nonEditClass = tinyMCE.getParam("noneditable_noneditable_class", "mceNonEditable");
+		_block : function(ed, e) {
+			return Event.cancel(e);
+		},
 
-				for (i=0; i<nodes.length; i++) {
-					elm = nodes[i];
+		_setDisabled : function(s) {
+			var t = this, ed = t.editor;
 
-					// Convert contenteditable to classes
-					editable = tinyMCE.getAttrib(elm, "contenteditable");
-					if (new RegExp("true|false","gi").test(editable))
-						TinyMCE_NonEditablePlugin._setEditable(elm, editable == "true");
+			tinymce.each(ed.controlManager.controls, function(c) {
+				c.setDisabled(s);
+			});
 
-					if (tinyMCE.isIE) {
-						if (tinyMCE.hasCSSClass(elm, editClass))
-							elm.contentEditable = true;
-
-						if (tinyMCE.hasCSSClass(elm, nonEditClass))
-							elm.contentEditable = false;
-					}
+			if (s !== t.disabled) {
+				if (s) {
+					ed.onKeyDown.addToTop(t._block);
+					ed.onKeyPress.addToTop(t._block);
+					ed.onKeyUp.addToTop(t._block);
+					ed.onPaste.addToTop(t._block);
+				} else {
+					ed.onKeyDown.remove(t._block);
+					ed.onKeyPress.remove(t._block);
+					ed.onKeyUp.remove(t._block);
+					ed.onPaste.remove(t._block);
 				}
 
-				break;
-
-			case "insert_to_editor":
-				var editClass = tinyMCE.getParam("noneditable_editable_class", "mceEditable");
-				var nonEditClass = tinyMCE.getParam("noneditable_noneditable_class", "mceNonEditable");
-
-				// Replace mceItem to new school
-				content = content.replace(/mceItemEditable/g, editClass);
-				content = content.replace(/mceItemNonEditable/g, nonEditClass);
-
-				if (tinyMCE.isIE && (content.indexOf(editClass) != -1 || content.indexOf(nonEditClass) != -1)) {
-					content = content.replace(new RegExp("class=\"(.+)(" + editClass + ")\"", "gi"), 'class="$1$2" contenteditable="true"');
-					content = content.replace(new RegExp("class=\"(.+)(" + nonEditClass + ")\"", "gi"), 'class="$1$2" contenteditable="false"');
-					content = content.replace(new RegExp("class=\"(" + editClass + ")([^\"]*)\"", "gi"), 'class="$1$2" contenteditable="true"');
-					content = content.replace(new RegExp("class=\"(" + nonEditClass + ")([^\"]*)\"", "gi"), 'class="$1$2" contenteditable="false"');
-					content = content.replace(new RegExp("class=\"(.+)(" + editClass + ")([^\"]*)\"", "gi"), 'class="$1$2$3" contenteditable="true"');
-					content = content.replace(new RegExp("class=\"(.+)(" + nonEditClass + ")([^\"]*)\"", "gi"), 'class="$1$2$3" contenteditable="false"');
-				}
-
-				break;
-
-			case "get_from_editor_dom":
-				// Pass through Gecko
-				if (tinyMCE.isGecko)
-					return content;
-
-				if (tinyMCE.getParam("noneditable_leave_contenteditable", false)) {
-					var nodes = tinyMCE.getNodeTree(content, new Array(), 1);
-
-					for (var i=0; i<nodes.length; i++)
-						nodes[i].removeAttribute("contenteditable");
-				}
-
-				break;
-		}
-
-		return content;
-	},
-
-	_moveSelection : function(e, inst) {
-		var s, r, sc, ec, el, c = tinyMCE.getParam('noneditable_editable_class', 'mceNonEditable');
-
-		if (!inst)
-			return true;
-
-		// Always select whole element
-		if (tinyMCE.isGecko) {
-			s = inst.selection.getSel();
-			r = s.getRangeAt(0);
-			sc = tinyMCE.getParentNode(r.startContainer, function (n) {return tinyMCE.hasCSSClass(n, c);});
-			ec = tinyMCE.getParentNode(r.endContainer, function (n) {return tinyMCE.hasCSSClass(n, c);});
-
-			sc && r.setStartBefore(sc);
-			ec && r.setEndAfter(ec);
-
-			if (sc || ec) {
-				if (e.type == 'keypress' && e.keyCode == 39) {
-					el = sc || ec;
-
-					// Try!!
-				}
-
-				s.removeAllRanges();
-				s.addRange(r);
-
-				return tinyMCE.cancelEvent(e);
+				t.disabled = s;
 			}
 		}
-
-		return true;
-	},
-
-	_setEditable : function(elm, state) {
-		var editClass = tinyMCE.getParam("noneditable_editable_class", "mceEditable");
-		var nonEditClass = tinyMCE.getParam("noneditable_noneditable_class", "mceNonEditable");
-
-		var className = elm.className ? elm.className : "";
+	});
 
-		if (className.indexOf(editClass) != -1 || className.indexOf(nonEditClass) != -1)
-			return;
-
-		if ((className = tinyMCE.getAttrib(elm, "class")) != "")
-			className += " ";
-
-		className += state ? editClass : nonEditClass;
-
-		elm.setAttribute("class", className);
-		elm.className = className;
-	}
-};
-
-tinyMCE.addPlugin("noneditable", TinyMCE_NonEditablePlugin);
+	// Register plugin
+	tinymce.PluginManager.add('noneditable', tinymce.plugins.NonEditablePlugin);
+})();
\ No newline at end of file
--- a/includes/clientside/tinymce/plugins/noneditable/readme.txt	Fri Feb 22 12:46:51 2008 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1 +0,0 @@
-Check the TinyMCE documentation for details on this plugin.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/includes/clientside/tinymce/plugins/pagebreak/css/content.css	Fri Feb 22 12:51:53 2008 -0500
@@ -0,0 +1,1 @@
+.mcePageBreak {display:block;border:0;width:100%;height:12px;border-top:1px dotted #ccc;margin-top:15px;background:#fff url(../img/pagebreak.gif) no-repeat center top;}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/includes/clientside/tinymce/plugins/pagebreak/editor_plugin.js	Fri Feb 22 12:51:53 2008 -0500
@@ -0,0 +1,1 @@
+(function(){tinymce.create('tinymce.plugins.PageBreakPlugin',{init:function(ed,url){var pb='<img src="'+url+'/img/trans.gif" class="mcePageBreak mceItemNoResize" />',cls='mcePageBreak',sep=ed.getParam('pagebreak_separator','<!-- pagebreak -->'),pbRE;pbRE=new RegExp(sep.replace(/[\?\.\*\[\]\(\)\{\}\+\^\$\:]/g,function(a){return'\\'+a;}),'g');ed.addCommand('mcePageBreak',function(){ed.execCommand('mceInsertContent',0,pb);});ed.addButton('pagebreak',{title:'pagebreak.desc',cmd:cls});ed.onInit.add(function(){ed.dom.loadCSS(url+"/css/content.css");if(ed.theme.onResolveName){ed.theme.onResolveName.add(function(th,o){if(o.node.nodeName=='IMG'&&ed.dom.hasClass(o.node,cls))o.name='pagebreak';});}});ed.onClick.add(function(ed,e){e=e.target;if(e.nodeName==='IMG'&&ed.dom.hasClass(e,cls))ed.selection.select(e);});ed.onNodeChange.add(function(ed,cm,n){cm.setActive('pagebreak',n.nodeName==='IMG'&&ed.dom.hasClass(n,cls));});ed.onBeforeSetContent.add(function(ed,o){o.content=o.content.replace(pbRE,pb);});ed.onPostProcess.add(function(ed,o){if(o.get)o.content=o.content.replace(/<img[^>]+>/g,function(im){if(im.indexOf('class="mcePageBreak')!==-1)im=sep;return im;});});},getInfo:function(){return{longname:'PageBreak',author:'Moxiecode Systems AB',authorurl:'http://tinymce.moxiecode.com',infourl:'http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/pagebreak',version:tinymce.majorVersion+"."+tinymce.minorVersion};}});tinymce.PluginManager.add('pagebreak',tinymce.plugins.PageBreakPlugin);})();
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/includes/clientside/tinymce/plugins/pagebreak/editor_plugin_src.js	Fri Feb 22 12:51:53 2008 -0500
@@ -0,0 +1,73 @@
+/**
+ * $Id: editor_plugin_src.js 201 2007-02-12 15:56:56Z spocke $
+ *
+ * @author Moxiecode
+ * @copyright Copyright © 2004-2008, Moxiecode Systems AB, All rights reserved.
+ */
+
+(function() {
+	tinymce.create('tinymce.plugins.PageBreakPlugin', {
+		init : function(ed, url) {
+			var pb = '<img src="' + url + '/img/trans.gif" class="mcePageBreak mceItemNoResize" />', cls = 'mcePageBreak', sep = ed.getParam('pagebreak_separator', '<!-- pagebreak -->'), pbRE;
+
+			pbRE = new RegExp(sep.replace(/[\?\.\*\[\]\(\)\{\}\+\^\$\:]/g, function(a) {return '\\' + a;}), 'g');
+
+			// Register commands
+			ed.addCommand('mcePageBreak', function() {
+				ed.execCommand('mceInsertContent', 0, pb);
+			});
+
+			// Register buttons
+			ed.addButton('pagebreak', {title : 'pagebreak.desc', cmd : cls});
+
+			ed.onInit.add(function() {
+				ed.dom.loadCSS(url + "/css/content.css");
+
+				if (ed.theme.onResolveName) {
+					ed.theme.onResolveName.add(function(th, o) {
+						if (o.node.nodeName == 'IMG' && ed.dom.hasClass(o.node, cls))
+							o.name = 'pagebreak';
+					});
+				}
+			});
+
+			ed.onClick.add(function(ed, e) {
+				e = e.target;
+
+				if (e.nodeName === 'IMG' && ed.dom.hasClass(e, cls))
+					ed.selection.select(e);
+			});
+
+			ed.onNodeChange.add(function(ed, cm, n) {
+				cm.setActive('pagebreak', n.nodeName === 'IMG' && ed.dom.hasClass(n, cls));
+			});
+
+			ed.onBeforeSetContent.add(function(ed, o) {
+				o.content = o.content.replace(pbRE, pb);
+			});
+
+			ed.onPostProcess.add(function(ed, o) {
+				if (o.get)
+					o.content = o.content.replace(/<img[^>]+>/g, function(im) {
+						if (im.indexOf('class="mcePageBreak') !== -1)
+							im = sep;
+
+						return im;
+					});
+			});
+		},
+
+		getInfo : function() {
+			return {
+				longname : 'PageBreak',
+				author : 'Moxiecode Systems AB',
+				authorurl : 'http://tinymce.moxiecode.com',
+				infourl : 'http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/pagebreak',
+				version : tinymce.majorVersion + "." + tinymce.minorVersion
+			};
+		}
+	});
+
+	// Register plugin
+	tinymce.PluginManager.add('pagebreak', tinymce.plugins.PageBreakPlugin);
+})();
\ No newline at end of file
Binary file includes/clientside/tinymce/plugins/pagebreak/img/pagebreak.gif has changed
Binary file includes/clientside/tinymce/plugins/pagebreak/img/trans.gif has changed
--- a/includes/clientside/tinymce/plugins/paste/blank.htm	Fri Feb 22 12:46:51 2008 -0500
+++ b/includes/clientside/tinymce/plugins/paste/blank.htm	Fri Feb 22 12:51:53 2008 -0500
@@ -1,17 +1,20 @@
 <html xmlns="http://www.w3.org/1999/xhtml">
 <head>
-	<title>blank_page</title>
-	<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
-	<script language="javascript">
-		function init() {
-			document.body.contentEditable = true;
-			document.designMode = 'on';
-			parent.initIframe(document);
-			window.focus();
-		}
-	</script>
-	<link href="css/blank.css" rel="stylesheet" type="text/css" />
-	<base target="_self" />
+<title>blank_page</title>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
+<link href="css/blank.css" rel="stylesheet" type="text/css" />
+<base target="_self" />
+<script type="text/javascript">
+function init() {
+	if (parent.tinymce.isIE)
+		document.body.contentEditable = true;
+	else
+		document.designMode = 'on';
+
+	parent.initIframe(document);
+	window.focus();
+}
+</script>
 </head>
 <body onload="init();">
 
--- a/includes/clientside/tinymce/plugins/paste/css/blank.css	Fri Feb 22 12:46:51 2008 -0500
+++ b/includes/clientside/tinymce/plugins/paste/css/blank.css	Fri Feb 22 12:51:53 2008 -0500
@@ -1,13 +1,14 @@
+html, body {height:98%}
 body {
-	background-color: #FFFFFF;
-	font-family: Verdana, Arial, Helvetica, sans-serif;
-	font-size: 10px;
-	scrollbar-3dlight-color: #F0F0EE;
-	scrollbar-arrow-color: #676662;
-	scrollbar-base-color: #F0F0EE;
-	scrollbar-darkshadow-color: #DDDDDD;
-	scrollbar-face-color: #E0E0DD;
-	scrollbar-highlight-color: #F0F0EE;
-	scrollbar-shadow-color: #F0F0EE;
-	scrollbar-track-color: #F5F5F5;
+background-color: #FFFFFF;
+font-family: Verdana, Arial, Helvetica, sans-serif;
+font-size: 10px;
+scrollbar-3dlight-color: #F0F0EE;
+scrollbar-arrow-color: #676662;
+scrollbar-base-color: #F0F0EE;
+scrollbar-darkshadow-color: #DDDDDD;
+scrollbar-face-color: #E0E0DD;
+scrollbar-highlight-color: #F0F0EE;
+scrollbar-shadow-color: #F0F0EE;
+scrollbar-track-color: #F5F5F5;
 }
--- a/includes/clientside/tinymce/plugins/paste/editor_plugin.js	Fri Feb 22 12:46:51 2008 -0500
+++ b/includes/clientside/tinymce/plugins/paste/editor_plugin.js	Fri Feb 22 12:51:53 2008 -0500
@@ -1,1 +1,1 @@
-tinyMCE.importPluginLanguagePack('paste');var TinyMCE_PastePlugin={getInfo:function(){return{longname:'Paste text/word',author:'Moxiecode Systems AB',authorurl:'http://tinymce.moxiecode.com',infourl:'http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/paste',version:tinyMCE.majorVersion+"."+tinyMCE.minorVersion}},initInstance:function(inst){if(tinyMCE.isMSIE&&tinyMCE.getParam("paste_auto_cleanup_on_paste",false))tinyMCE.addEvent(inst.getBody(),"paste",TinyMCE_PastePlugin._handlePasteEvent)},handleEvent:function(e){if(!tinyMCE.isRealIE&&tinyMCE.getParam("paste_auto_cleanup_on_paste",false)&&e.ctrlKey&&e.keyCode==86&&e.type=="keydown"){window.setTimeout('tinyMCE.selectedInstance.execCommand("mcePasteText",true)',1);return tinyMCE.cancelEvent(e)}return true},getControlHTML:function(cn){switch(cn){case"pastetext":return tinyMCE.getButtonHTML(cn,'lang_paste_text_desc','{$pluginurl}/images/pastetext.gif','mcePasteText',true);case"pasteword":return tinyMCE.getButtonHTML(cn,'lang_paste_word_desc','{$pluginurl}/images/pasteword.gif','mcePasteWord',true);case"selectall":return tinyMCE.getButtonHTML(cn,'lang_selectall_desc','{$pluginurl}/images/selectall.gif','mceSelectAll',true)}return''},execCommand:function(editor_id,element,command,user_interface,value){switch(command){case"mcePasteText":if(user_interface){if((tinyMCE.isMSIE&&!tinyMCE.isOpera)&&!tinyMCE.getParam('paste_use_dialog',false))TinyMCE_PastePlugin._insertText(clipboardData.getData("Text"),true);else{var template=new Array();template['file']='../../plugins/paste/pastetext.htm';template['width']=450;template['height']=400;var plain_text="";tinyMCE.openWindow(template,{editor_id:editor_id,plain_text:plain_text,resizable:"yes",scrollbars:"no",inline:"yes",mceDo:'insert'})}}else TinyMCE_PastePlugin._insertText(value['html'],value['linebreaks']);return true;case"mcePasteWord":if(user_interface){if((tinyMCE.isMSIE&&!tinyMCE.isOpera)&&!tinyMCE.getParam('paste_use_dialog',false)){TinyMCE_PastePlugin._insertWordContent(TinyMCE_PastePlugin._clipboardHTML())}else{var template=new Array();template['file']='../../plugins/paste/pasteword.htm';template['width']=450;template['height']=400;var plain_text="";tinyMCE.openWindow(template,{editor_id:editor_id,plain_text:plain_text,resizable:"yes",scrollbars:"no",inline:"yes",mceDo:'insert'})}}else TinyMCE_PastePlugin._insertWordContent(value);return true;case"mceSelectAll":tinyMCE.execInstanceCommand(editor_id,'selectall');return true}return false},_handlePasteEvent:function(e){switch(e.type){case"paste":var html=TinyMCE_PastePlugin._clipboardHTML();var r,inst=tinyMCE.selectedInstance;if(inst&&(r=inst.getRng())&&r.text.length>0)tinyMCE.execCommand('delete');if(html&&html.length>0)tinyMCE.execCommand('mcePasteWord',false,html);tinyMCE.cancelEvent(e);return false}return true},_insertText:function(content,bLinebreaks){if(content&&content.length>0){if(bLinebreaks){if(tinyMCE.getParam("paste_create_paragraphs",true)){var rl=tinyMCE.getParam("paste_replace_list",'\u2122,<sup>TM</sup>,\u2026,...,\u201c|\u201d,",\u2019,\',\u2013|\u2014|\u2015|\u2212,-').split(',');for(var i=0;i<rl.length;i+=2)content=content.replace(new RegExp(rl[i],'gi'),rl[i+1]);content=tinyMCE.regexpReplace(content,"\r\n\r\n","</p><p>","gi");content=tinyMCE.regexpReplace(content,"\r\r","</p><p>","gi");content=tinyMCE.regexpReplace(content,"\n\n","</p><p>","gi");if((pos=content.indexOf('</p><p>'))!=-1){tinyMCE.execCommand("Delete");var node=tinyMCE.selectedInstance.getFocusElement();var breakElms=new Array();do{if(node.nodeType==1){if(node.nodeName=="TD"||node.nodeName=="BODY")break;breakElms[breakElms.length]=node}}while(node=node.parentNode);var before="",after="</p>";before+=content.substring(0,pos);for(var i=0;i<breakElms.length;i++){before+="</"+breakElms[i].nodeName+">";after+="<"+breakElms[(breakElms.length-1)-i].nodeName+">"}before+="<p>";content=before+content.substring(pos+7)+after}}if(tinyMCE.getParam("paste_create_linebreaks",true)){content=tinyMCE.regexpReplace(content,"\r\n","<br />","gi");content=tinyMCE.regexpReplace(content,"\r","<br />","gi");content=tinyMCE.regexpReplace(content,"\n","<br />","gi")}}tinyMCE.execCommand("mceInsertRawHTML",false,content)}},_insertWordContent:function(content){if(content&&content.length>0){var bull=String.fromCharCode(8226);var middot=String.fromCharCode(183);var cb;if((cb=tinyMCE.getParam("paste_insert_word_content_callback",""))!="")content=eval(cb+"('before', content)");var rl=tinyMCE.getParam("paste_replace_list",'\u2122,<sup>TM</sup>,\u2026,...,\u201c|\u201d,",\u2019,\',\u2013|\u2014|\u2015|\u2212,-').split(',');for(var i=0;i<rl.length;i+=2)content=content.replace(new RegExp(rl[i],'gi'),rl[i+1]);if(tinyMCE.getParam("paste_convert_headers_to_strong",false)){content=content.replace(new RegExp('<p class=MsoHeading.*?>(.*?)<\/p>','gi'),'<p><b>$1</b></p>')}content=content.replace(new RegExp('tab-stops: list [0-9]+.0pt">','gi'),'">'+"--list--");content=content.replace(new RegExp(bull+"(.*?)<BR>","gi"),"<p>"+middot+"$1</p>");content=content.replace(new RegExp('<SPAN style="mso-list: Ignore">','gi'),"<span>"+bull);content=content.replace(/<o:p><\/o:p>/gi,"");content=content.replace(new RegExp('<br style="page-break-before: always;.*>','gi'),'-- page break --');content=content.replace(new RegExp('<(!--)([^>]*)(--)>','g'),"");if(tinyMCE.getParam("paste_remove_spans",true))content=content.replace(/<\/?span[^>]*>/gi,"");if(tinyMCE.getParam("paste_remove_styles",true))content=content.replace(new RegExp('<(\\w[^>]*) style="([^"]*)"([^>]*)','gi'),"<$1$3");content=content.replace(/<\/?font[^>]*>/gi,"");switch(tinyMCE.getParam("paste_strip_class_attributes","all")){case"all":content=content.replace(/<(\w[^>]*) class=([^ |>]*)([^>]*)/gi,"<$1$3");break;case"mso":content=content.replace(new RegExp('<(\\w[^>]*) class="?mso([^ |>]*)([^>]*)','gi'),"<$1$3");break}content=content.replace(new RegExp('href="?'+TinyMCE_PastePlugin._reEscape(""+document.location)+'','gi'),'href="'+tinyMCE.settings['document_base_url']);content=content.replace(/<(\w[^>]*) lang=([^ |>]*)([^>]*)/gi,"<$1$3");content=content.replace(/<\\?\?xml[^>]*>/gi,"");content=content.replace(/<\/?\w+:[^>]*>/gi,"");content=content.replace(/-- page break --\s*<p>&nbsp;<\/p>/gi,"");content=content.replace(/-- page break --/gi,"");if(!tinyMCE.settings['force_p_newlines']){content=content.replace('','','gi');content=content.replace('</p>','<br /><br />','gi')}if(!tinyMCE.isMSIE&&!tinyMCE.settings['force_p_newlines']){content=content.replace(/<\/?p[^>]*>/gi,"")}content=content.replace(/<\/?div[^>]*>/gi,"");if(tinyMCE.getParam("paste_convert_middot_lists",true)){var div=document.createElement("div");div.innerHTML=content;var className=tinyMCE.getParam("paste_unindented_list_class","unIndentedList");while(TinyMCE_PastePlugin._convertMiddots(div,"--list--"));while(TinyMCE_PastePlugin._convertMiddots(div,middot,className));while(TinyMCE_PastePlugin._convertMiddots(div,bull));content=div.innerHTML}if(tinyMCE.getParam("paste_convert_headers_to_strong",false)){content=content.replace(/<h[1-6]>&nbsp;<\/h[1-6]>/gi,'<p>&nbsp;&nbsp;</p>');content=content.replace(/<h[1-6]>/gi,'<p><b>');content=content.replace(/<\/h[1-6]>/gi,'</b></p>');content=content.replace(/<b>&nbsp;<\/b>/gi,'<b>&nbsp;&nbsp;</b>');content=content.replace(/^(&nbsp;)*/gi,'')}content=content.replace(/--list--/gi,"");if((cb=tinyMCE.getParam("paste_insert_word_content_callback",""))!="")content=eval(cb+"('after', content)");tinyMCE.execCommand("mceInsertContent",false,content);if(tinyMCE.getParam('paste_force_cleanup_wordpaste',true))window.setTimeout('tinyMCE.execCommand("mceCleanup");',1);}},_reEscape:function(s){var l="?.\\*[](){}+^$:";var o="";for(var i=0;i<s.length;i++){var c=s.charAt(i);if(l.indexOf(c)!=-1)o+='\\'+c;else o+=c}return o},_convertMiddots:function(div,search,class_name){var mdot=String.fromCharCode(183);var bull=String.fromCharCode(8226);var nodes=div.getElementsByTagName("p");var prevul;for(var i=0;i<nodes.length;i++){var p=nodes[i];if(p.innerHTML.indexOf(search)==0){var ul=document.createElement("ul");if(class_name)ul.className=class_name;var li=document.createElement("li");li.innerHTML=p.innerHTML.replace(new RegExp(''+mdot+'|'+bull+'|--list--|&nbsp;',"gi"),'');ul.appendChild(li);var np=p.nextSibling;while(np){if(np.nodeType==3&&new RegExp('^\\s$','m').test(np.nodeValue)){np=np.nextSibling;continue}if(search==mdot){if(np.nodeType==1&&new RegExp('^o(\\s+|&nbsp;)').test(np.innerHTML)){if(!prevul){prevul=ul;ul=document.createElement("ul");prevul.appendChild(ul)}np.innerHTML=np.innerHTML.replace(/^o/,'')}else{if(prevul){ul=prevul;prevul=null}if(np.nodeType!=1||np.innerHTML.indexOf(search)!=0)break}}else{if(np.nodeType!=1||np.innerHTML.indexOf(search)!=0)break}var cp=np.nextSibling;var li=document.createElement("li");li.innerHTML=np.innerHTML.replace(new RegExp(''+mdot+'|'+bull+'|--list--|&nbsp;',"gi"),'');np.parentNode.removeChild(np);ul.appendChild(li);np=cp}p.parentNode.replaceChild(ul,p);return true}}return false},_clipboardHTML:function(){var div=document.getElementById('_TinyMCE_clipboardHTML');if(!div){var div=document.createElement('DIV');div.id='_TinyMCE_clipboardHTML';with(div.style){visibility='hidden';overflow='hidden';position='absolute';width=1;height=1}document.body.appendChild(div)}div.innerHTML='';var rng=document.body.createTextRange();rng.moveToElementText(div);rng.execCommand('Paste');var html=div.innerHTML;div.innerHTML='';return html}};tinyMCE.addPlugin("paste",TinyMCE_PastePlugin);
\ No newline at end of file
+(function(){var Event=tinymce.dom.Event;tinymce.create('tinymce.plugins.PastePlugin',{init:function(ed,url){var t=this;t.editor=ed;ed.addCommand('mcePasteText',function(ui,v){if(ui){ed.windowManager.open({file:url+'/pastetext.htm',width:450,height:400,inline:1},{plugin_url:url});}else t._insertText(v.html,v.linebreaks);});ed.addCommand('mcePasteWord',function(ui,v){if(ui){ed.windowManager.open({file:url+'/pasteword.htm',width:450,height:400,inline:1},{plugin_url:url});}else t._insertWordContent(v);});ed.addCommand('mceSelectAll',function(){ed.execCommand('selectall');});ed.addButton('pastetext',{title:'paste.paste_text_desc',cmd:'mcePasteText',ui:true});ed.addButton('pasteword',{title:'paste.paste_word_desc',cmd:'mcePasteWord',ui:true});ed.addButton('selectall',{title:'paste.selectall_desc',cmd:'mceSelectAll'});if(ed.getParam("paste_auto_cleanup_on_paste",false)){ed.onPaste.add(function(ed,e){return t._handlePasteEvent(e)});}if(!tinymce.isIE&&ed.getParam("paste_auto_cleanup_on_paste",false)){ed.onKeyDown.add(function(ed,e){if(e.ctrlKey&&e.keyCode==86){window.setTimeout(function(){ed.execCommand("mcePasteText",true);},1);Event.cancel(e);}});}},getInfo:function(){return{longname:'Paste text/word',author:'Moxiecode Systems AB',authorurl:'http://tinymce.moxiecode.com',infourl:'http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/paste',version:tinymce.majorVersion+"."+tinymce.minorVersion};},_handlePasteEvent:function(e){var html=this._clipboardHTML(),ed=this.editor,sel=ed.selection,r;if(ed&&(r=sel.getRng())&&r.text.length>0)ed.execCommand('delete');if(html&&html.length>0)ed.execCommand('mcePasteWord',false,html);return Event.cancel(e);},_insertText:function(content,bLinebreaks){if(content&&content.length>0){if(bLinebreaks){if(this.editor.getParam("paste_create_paragraphs",true)){var rl=this.editor.getParam("paste_replace_list",'\u2122,<sup>TM</sup>,\u2026,...,\u201c|\u201d,",\u2019,\',\u2013|\u2014|\u2015|\u2212,-').split(',');for(var i=0;i<rl.length;i+=2)content=content.replace(new RegExp(rl[i],'gi'),rl[i+1]);content=content.replace(/\r\n\r\n/g,'</p><p>');content=content.replace(/\r\r/g,'</p><p>');content=content.replace(/\n\n/g,'</p><p>');if((pos=content.indexOf('</p><p>'))!=-1){this.editor.execCommand("Delete");var node=this.editor.selection.getNode();var breakElms=[];do{if(node.nodeType==1){if(node.nodeName=="TD"||node.nodeName=="BODY")break;breakElms[breakElms.length]=node;}}while(node=node.parentNode);var before="",after="</p>";before+=content.substring(0,pos);for(var i=0;i<breakElms.length;i++){before+="</"+breakElms[i].nodeName+">";after+="<"+breakElms[(breakElms.length-1)-i].nodeName+">";}before+="<p>";content=before+content.substring(pos+7)+after;}}if(this.editor.getParam("paste_create_linebreaks",true)){content=content.replace(/\r\n/g,'<br />');content=content.replace(/\r/g,'<br />');content=content.replace(/\n/g,'<br />');}}this.editor.execCommand("mceInsertRawHTML",false,content);}},_insertWordContent:function(content){var t=this,ed=t.editor;if(content&&content.length>0){var bull=String.fromCharCode(8226);var middot=String.fromCharCode(183);var cb;if((cb=this.editor.getParam("paste_insert_word_content_callback",""))!="")content=eval(cb+"('before', content)");var rl=this.editor.getParam("paste_replace_list",'\u2122,<sup>TM</sup>,\u2026,...,\u201c|\u201d,",\u2019,\',\u2013|\u2014|\u2015|\u2212,-').split(',');for(var i=0;i<rl.length;i+=2)content=content.replace(new RegExp(rl[i],'gi'),rl[i+1]);if(this.editor.getParam("paste_convert_headers_to_strong",false)){content=content.replace(new RegExp('<p class=MsoHeading.*?>(.*?)<\/p>','gi'),'<p><b>$1</b></p>');}content=content.replace(new RegExp('tab-stops: list [0-9]+.0pt">','gi'),'">'+"--list--");content=content.replace(new RegExp(bull+"(.*?)<BR>","gi"),"<p>"+middot+"$1</p>");content=content.replace(new RegExp('<SPAN style="mso-list: Ignore">','gi'),"<span>"+bull);content=content.replace(/<o:p><\/o:p>/gi,"");content=content.replace(new RegExp('<br style="page-break-before: always;.*>','gi'),'-- page break --');content=content.replace(new RegExp('<(!--)([^>]*)(--)>','g'),"");if(this.editor.getParam("paste_remove_spans",true))content=content.replace(/<\/?span[^>]*>/gi,"");if(this.editor.getParam("paste_remove_styles",true))content=content.replace(new RegExp('<(\\w[^>]*) style="([^"]*)"([^>]*)','gi'),"<$1$3");content=content.replace(/<\/?font[^>]*>/gi,"");switch(this.editor.getParam("paste_strip_class_attributes","all")){case"all":content=content.replace(/<(\w[^>]*) class=([^ |>]*)([^>]*)/gi,"<$1$3");break;case"mso":content=content.replace(new RegExp('<(\\w[^>]*) class="?mso([^ |>]*)([^>]*)','gi'),"<$1$3");break;}content=content.replace(new RegExp('href="?'+this._reEscape(""+document.location)+'','gi'),'href="'+this.editor.documentBaseURI.getURI());content=content.replace(/<(\w[^>]*) lang=([^ |>]*)([^>]*)/gi,"<$1$3");content=content.replace(/<\\?\?xml[^>]*>/gi,"");content=content.replace(/<\/?\w+:[^>]*>/gi,"");content=content.replace(/-- page break --\s*<p>&nbsp;<\/p>/gi,"");content=content.replace(/-- page break --/gi,"");if(!this.editor.getParam('force_p_newlines')){content=content.replace('','','gi');content=content.replace('</p>','<br /><br />','gi');}if(!tinymce.isIE&&!this.editor.getParam('force_p_newlines')){content=content.replace(/<\/?p[^>]*>/gi,"");}content=content.replace(/<\/?div[^>]*>/gi,"");if(this.editor.getParam("paste_convert_middot_lists",true)){var div=ed.dom.create("div",null,content);var className=this.editor.getParam("paste_unindented_list_class","unIndentedList");while(this._convertMiddots(div,"--list--"));while(this._convertMiddots(div,middot,className));while(this._convertMiddots(div,bull));content=div.innerHTML;}if(this.editor.getParam("paste_convert_headers_to_strong",false)){content=content.replace(/<h[1-6]>&nbsp;<\/h[1-6]>/gi,'<p>&nbsp;&nbsp;</p>');content=content.replace(/<h[1-6]>/gi,'<p><b>');content=content.replace(/<\/h[1-6]>/gi,'</b></p>');content=content.replace(/<b>&nbsp;<\/b>/gi,'<b>&nbsp;&nbsp;</b>');content=content.replace(/^(&nbsp;)*/gi,'');}content=content.replace(/--list--/gi,"");if((cb=this.editor.getParam("paste_insert_word_content_callback",""))!="")content=eval(cb+"('after', content)");this.editor.execCommand("mceInsertContent",false,content);if(this.editor.getParam('paste_force_cleanup_wordpaste',true)){var ed=this.editor;window.setTimeout(function(){ed.execCommand("mceCleanup");},1);}}},_reEscape:function(s){var l="?.\\*[](){}+^$:";var o="";for(var i=0;i<s.length;i++){var c=s.charAt(i);if(l.indexOf(c)!=-1)o+='\\'+c;else o+=c;}return o;},_convertMiddots:function(div,search,class_name){var mdot=String.fromCharCode(183);var bull=String.fromCharCode(8226);var nodes=div.getElementsByTagName("p");var prevul;for(var i=0;i<nodes.length;i++){var p=nodes[i];if(p.innerHTML.indexOf(search)==0){var ul=document.createElement("ul");if(class_name)ul.className=class_name;var li=document.createElement("li");li.innerHTML=p.innerHTML.replace(new RegExp(''+mdot+'|'+bull+'|--list--|&nbsp;',"gi"),'');ul.appendChild(li);var np=p.nextSibling;while(np){if(np.nodeType==3&&new RegExp('^\\s$','m').test(np.nodeValue)){np=np.nextSibling;continue;}if(search==mdot){if(np.nodeType==1&&new RegExp('^o(\\s+|&nbsp;)').test(np.innerHTML)){if(!prevul){prevul=ul;ul=document.createElement("ul");prevul.appendChild(ul);}np.innerHTML=np.innerHTML.replace(/^o/,'');}else{if(prevul){ul=prevul;prevul=null;}if(np.nodeType!=1||np.innerHTML.indexOf(search)!=0)break;}}else{if(np.nodeType!=1||np.innerHTML.indexOf(search)!=0)break;}var cp=np.nextSibling;var li=document.createElement("li");li.innerHTML=np.innerHTML.replace(new RegExp(''+mdot+'|'+bull+'|--list--|&nbsp;',"gi"),'');np.parentNode.removeChild(np);ul.appendChild(li);np=cp;}p.parentNode.replaceChild(ul,p);return true;}}return false;},_clipboardHTML:function(){var div=document.getElementById('_TinyMCE_clipboardHTML');if(!div){var div=document.createElement('DIV');div.id='_TinyMCE_clipboardHTML';with(div.style){visibility='hidden';overflow='hidden';position='absolute';width=1;height=1;}document.body.appendChild(div);}div.innerHTML='';var rng=document.body.createTextRange();rng.moveToElementText(div);rng.execCommand('Paste');var html=div.innerHTML;div.innerHTML='';return html;}});tinymce.PluginManager.add('paste',tinymce.plugins.PastePlugin);})();
\ No newline at end of file
--- a/includes/clientside/tinymce/plugins/paste/editor_plugin_src.js	Fri Feb 22 12:46:51 2008 -0500
+++ b/includes/clientside/tinymce/plugins/paste/editor_plugin_src.js	Fri Feb 22 12:51:53 2008 -0500
@@ -1,395 +1,383 @@
 /**
- * $Id: editor_plugin_src.js 201 2007-02-12 15:56:56Z spocke $
+ * $Id: editor_plugin_src.js 520 2008-01-07 16:30:32Z spocke $
  *
  * @author Moxiecode
- * @copyright Copyright © 2004-2007, Moxiecode Systems AB, All rights reserved.
+ * @copyright Copyright © 2004-2008, Moxiecode Systems AB, All rights reserved.
  */
 
-/* Import plugin specific language pack */ 
-tinyMCE.importPluginLanguagePack('paste');
-
-var TinyMCE_PastePlugin = {
-	getInfo : function() {
-		return {
-			longname : 'Paste text/word',
-			author : 'Moxiecode Systems AB',
-			authorurl : 'http://tinymce.moxiecode.com',
-			infourl : 'http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/paste',
-			version : tinyMCE.majorVersion + "." + tinyMCE.minorVersion
-		};
-	},
-
-	initInstance : function(inst) {
-		if (tinyMCE.isMSIE && tinyMCE.getParam("paste_auto_cleanup_on_paste", false))
-			tinyMCE.addEvent(inst.getBody(), "paste", TinyMCE_PastePlugin._handlePasteEvent);
-	},
+(function() {
+	var Event = tinymce.dom.Event;
 
-	handleEvent : function(e) {
-		// Force paste dialog if non IE browser
-		if (!tinyMCE.isRealIE && tinyMCE.getParam("paste_auto_cleanup_on_paste", false) && e.ctrlKey && e.keyCode == 86 && e.type == "keydown") {
-			window.setTimeout('tinyMCE.selectedInstance.execCommand("mcePasteText",true)', 1);
-			return tinyMCE.cancelEvent(e);
-		}
-
-		return true;
-	},
+	tinymce.create('tinymce.plugins.PastePlugin', {
+		init : function(ed, url) {
+			var t = this;
 
-	getControlHTML : function(cn) { 
-		switch (cn) { 
-			case "pastetext":
-				return tinyMCE.getButtonHTML(cn, 'lang_paste_text_desc', '{$pluginurl}/images/pastetext.gif', 'mcePasteText', true);
-
-			case "pasteword":
-				return tinyMCE.getButtonHTML(cn, 'lang_paste_word_desc', '{$pluginurl}/images/pasteword.gif', 'mcePasteWord', true);
-
-			case "selectall":
-				return tinyMCE.getButtonHTML(cn, 'lang_selectall_desc', '{$pluginurl}/images/selectall.gif', 'mceSelectAll', true);
-		} 
-
-		return ''; 
-	},
+			t.editor = ed; 
 
-	execCommand : function(editor_id, element, command, user_interface, value) { 
-		switch (command) { 
-			case "mcePasteText": 
-				if (user_interface) {
-					if ((tinyMCE.isMSIE && !tinyMCE.isOpera) && !tinyMCE.getParam('paste_use_dialog', false))
-						TinyMCE_PastePlugin._insertText(clipboardData.getData("Text"), true); 
-					else { 
-						var template = new Array(); 
-						template['file']	= '../../plugins/paste/pastetext.htm'; // Relative to theme 
-						template['width']  = 450; 
-						template['height'] = 400; 
-						var plain_text = ""; 
-						tinyMCE.openWindow(template, {editor_id : editor_id, plain_text: plain_text, resizable : "yes", scrollbars : "no", inline : "yes", mceDo : 'insert'}); 
-					}
+			// Register commands
+			ed.addCommand('mcePasteText', function(ui, v) {
+				if (ui) {
+					ed.windowManager.open({
+						file : url + '/pastetext.htm',
+						width : 450,
+						height : 400,
+						inline : 1
+					}, {
+						plugin_url : url
+					});
 				} else
-					TinyMCE_PastePlugin._insertText(value['html'], value['linebreaks']);
-
-				return true;
-
-			case "mcePasteWord": 
-				if (user_interface) {
-					if ((tinyMCE.isMSIE && !tinyMCE.isOpera) && !tinyMCE.getParam('paste_use_dialog', false)) {
-						TinyMCE_PastePlugin._insertWordContent(TinyMCE_PastePlugin._clipboardHTML());
-					} else { 
-						var template = new Array(); 
-						template['file']	= '../../plugins/paste/pasteword.htm'; // Relative to theme 
-						template['width']  = 450; 
-						template['height'] = 400; 
-						var plain_text = ""; 
-						tinyMCE.openWindow(template, {editor_id : editor_id, plain_text: plain_text, resizable : "yes", scrollbars : "no", inline : "yes", mceDo : 'insert'});
-					}
-				} else
-					TinyMCE_PastePlugin._insertWordContent(value);
-
-				return true;
-
-			case "mceSelectAll":
-				tinyMCE.execInstanceCommand(editor_id, 'selectall'); 
-				return true; 
-
-		} 
-
-		// Pass to next handler in chain 
-		return false; 
-	},
-
-	// Private plugin internal methods
+					t._insertText(v.html, v.linebreaks);
+			});
 
-	_handlePasteEvent : function(e) {
-		switch (e.type) {
-			case "paste":
-				var html = TinyMCE_PastePlugin._clipboardHTML();
-				var r, inst = tinyMCE.selectedInstance;
-
-				// Removes italic, strong etc, the if was needed due to bug #1437114
-				if (inst && (r = inst.getRng()) && r.text.length > 0)
-					tinyMCE.execCommand('delete');
-
-				if (html && html.length > 0)
-					tinyMCE.execCommand('mcePasteWord', false, html);
-
-				tinyMCE.cancelEvent(e);
-				return false;
-		}
-
-		return true;
-	},
-
-	_insertText : function(content, bLinebreaks) { 
-		if (content && content.length > 0) {
-			if (bLinebreaks) { 
-				// Special paragraph treatment 
-				if (tinyMCE.getParam("paste_create_paragraphs", true)) {
-					var rl = tinyMCE.getParam("paste_replace_list", '\u2122,<sup>TM</sup>,\u2026,...,\u201c|\u201d,",\u2019,\',\u2013|\u2014|\u2015|\u2212,-').split(',');
-					for (var i=0; i<rl.length; i+=2)
-						content = content.replace(new RegExp(rl[i], 'gi'), rl[i+1]);
-
-					content = tinyMCE.regexpReplace(content, "\r\n\r\n", "</p><p>", "gi"); 
-					content = tinyMCE.regexpReplace(content, "\r\r", "</p><p>", "gi"); 
-					content = tinyMCE.regexpReplace(content, "\n\n", "</p><p>", "gi"); 
-
-					// Has paragraphs 
-					if ((pos = content.indexOf('</p><p>')) != -1) { 
-						tinyMCE.execCommand("Delete"); 
-
-						var node = tinyMCE.selectedInstance.getFocusElement(); 
-
-						// Get list of elements to break 
-						var breakElms = new Array(); 
+			ed.addCommand('mcePasteWord', function(ui, v) {
+				if (ui) {
+					ed.windowManager.open({
+						file : url + '/pasteword.htm',
+						width : 450,
+						height : 400,
+						inline : 1
+					}, {
+						plugin_url : url
+					});
+				} else
+					t._insertWordContent(v);
+			});
 
-						do { 
-							if (node.nodeType == 1) { 
-								// Don't break tables and break at body 
-								if (node.nodeName == "TD" || node.nodeName == "BODY") 
-									break; 
-		
-								breakElms[breakElms.length] = node; 
-							} 
-						} while(node = node.parentNode); 
-
-						var before = "", after = "</p>"; 
-						before += content.substring(0, pos); 
-
-						for (var i=0; i<breakElms.length; i++) { 
-							before += "</" + breakElms[i].nodeName + ">"; 
-							after += "<" + breakElms[(breakElms.length-1)-i].nodeName + ">"; 
-						} 
-
-						before += "<p>"; 
-						content = before + content.substring(pos+7) + after; 
-					} 
-				} 
+			ed.addCommand('mceSelectAll', function() {
+				ed.execCommand('selectall'); 
+			});
 
-				if (tinyMCE.getParam("paste_create_linebreaks", true)) {
-					content = tinyMCE.regexpReplace(content, "\r\n", "<br />", "gi"); 
-					content = tinyMCE.regexpReplace(content, "\r", "<br />", "gi"); 
-					content = tinyMCE.regexpReplace(content, "\n", "<br />", "gi"); 
-				}
-			} 
-		
-			tinyMCE.execCommand("mceInsertRawHTML", false, content); 
-		}
-	},
+			// Register buttons
+			ed.addButton('pastetext', {title : 'paste.paste_text_desc', cmd : 'mcePasteText', ui : true});
+			ed.addButton('pasteword', {title : 'paste.paste_word_desc', cmd : 'mcePasteWord', ui : true});
+			ed.addButton('selectall', {title : 'paste.selectall_desc', cmd : 'mceSelectAll'});
 
-	_insertWordContent : function(content) { 
-		if (content && content.length > 0) {
-			// Cleanup Word content
-			var bull = String.fromCharCode(8226);
-			var middot = String.fromCharCode(183);
-			var cb;
-
-			if ((cb = tinyMCE.getParam("paste_insert_word_content_callback", "")) != "")
-				content = eval(cb + "('before', content)");
-
-			var rl = tinyMCE.getParam("paste_replace_list", '\u2122,<sup>TM</sup>,\u2026,...,\u201c|\u201d,",\u2019,\',\u2013|\u2014|\u2015|\u2212,-').split(',');
-			for (var i=0; i<rl.length; i+=2)
-				content = content.replace(new RegExp(rl[i], 'gi'), rl[i+1]);
-
-			if (tinyMCE.getParam("paste_convert_headers_to_strong", false)) {
-				content = content.replace(new RegExp('<p class=MsoHeading.*?>(.*?)<\/p>', 'gi'), '<p><b>$1</b></p>');
+			if (ed.getParam("paste_auto_cleanup_on_paste", false)) {
+				ed.onPaste.add(function(ed, e) {
+					return t._handlePasteEvent(e)
+				});
 			}
 
-			content = content.replace(new RegExp('tab-stops: list [0-9]+.0pt">', 'gi'), '">' + "--list--");
-			content = content.replace(new RegExp(bull + "(.*?)<BR>", "gi"), "<p>" + middot + "$1</p>");
-			content = content.replace(new RegExp('<SPAN style="mso-list: Ignore">', 'gi'), "<span>" + bull); // Covert to bull list
-			content = content.replace(/<o:p><\/o:p>/gi, "");
-			content = content.replace(new RegExp('<br style="page-break-before: always;.*>', 'gi'), '-- page break --'); // Replace pagebreaks
-			content = content.replace(new RegExp('<(!--)([^>]*)(--)>', 'g'), "");  // Word comments
+			if (!tinymce.isIE && ed.getParam("paste_auto_cleanup_on_paste", false)) {
+				// Force paste dialog if non IE browser
+				ed.onKeyDown.add(function(ed, e) {
+					if (e.ctrlKey && e.keyCode == 86) {
+						window.setTimeout(function() {
+							ed.execCommand("mcePasteText", true);
+						}, 1);
+
+						Event.cancel(e);
+					}
+				});
+			}
+		},
+
+		getInfo : function() {
+			return {
+				longname : 'Paste text/word',
+				author : 'Moxiecode Systems AB',
+				authorurl : 'http://tinymce.moxiecode.com',
+				infourl : 'http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/paste',
+				version : tinymce.majorVersion + "." + tinymce.minorVersion
+			};
+		},
+
+		// Private methods
 
-			if (tinyMCE.getParam("paste_remove_spans", true))
-				content = content.replace(/<\/?span[^>]*>/gi, "");
+		_handlePasteEvent : function(e) {
+			var html = this._clipboardHTML(), ed = this.editor, sel = ed.selection, r;
+
+			// Removes italic, strong etc, the if was needed due to bug #1437114
+			if (ed && (r = sel.getRng()) && r.text.length > 0)
+				ed.execCommand('delete');
+
+			if (html && html.length > 0)
+				ed.execCommand('mcePasteWord', false, html);
+
+			return Event.cancel(e);
+		},
 
-			if (tinyMCE.getParam("paste_remove_styles", true))
-				content = content.replace(new RegExp('<(\\w[^>]*) style="([^"]*)"([^>]*)', 'gi'), "<$1$3");
+		_insertText : function(content, bLinebreaks) { 
+			if (content && content.length > 0) {
+				if (bLinebreaks) { 
+					// Special paragraph treatment 
+					if (this.editor.getParam("paste_create_paragraphs", true)) {
+						var rl = this.editor.getParam("paste_replace_list", '\u2122,<sup>TM</sup>,\u2026,...,\u201c|\u201d,",\u2019,\',\u2013|\u2014|\u2015|\u2212,-').split(',');
+						for (var i=0; i<rl.length; i+=2)
+							content = content.replace(new RegExp(rl[i], 'gi'), rl[i+1]);
 
-			content = content.replace(/<\/?font[^>]*>/gi, "");
+						content = content.replace(/\r\n\r\n/g, '</p><p>');
+						content = content.replace(/\r\r/g, '</p><p>');
+						content = content.replace(/\n\n/g, '</p><p>');
 
-			// Strips class attributes.
-			switch (tinyMCE.getParam("paste_strip_class_attributes", "all")) {
-				case "all":
-					content = content.replace(/<(\w[^>]*) class=([^ |>]*)([^>]*)/gi, "<$1$3");
-					break;
+						// Has paragraphs 
+						if ((pos = content.indexOf('</p><p>')) != -1) { 
+							this.editor.execCommand("Delete"); 
+
+							var node = this.editor.selection.getNode(); 
+
+							// Get list of elements to break 
+							var breakElms = [];
+
+							do { 
+								if (node.nodeType == 1) { 
+									// Don't break tables and break at body 
+									if (node.nodeName == "TD" || node.nodeName == "BODY") 
+										break; 
+			
+									breakElms[breakElms.length] = node; 
+								} 
+							} while(node = node.parentNode); 
+
+							var before = "", after = "</p>"; 
+							before += content.substring(0, pos); 
+
+							for (var i=0; i<breakElms.length; i++) { 
+								before += "</" + breakElms[i].nodeName + ">"; 
+								after += "<" + breakElms[(breakElms.length-1)-i].nodeName + ">"; 
+							} 
 
-				case "mso":
-					content = content.replace(new RegExp('<(\\w[^>]*) class="?mso([^ |>]*)([^>]*)', 'gi'), "<$1$3");
-					break;
-			}
+							before += "<p>"; 
+							content = before + content.substring(pos+7) + after; 
+						} 
+					} 
 
-			content = content.replace(new RegExp('href="?' + TinyMCE_PastePlugin._reEscape("" + document.location) + '', 'gi'), 'href="' + tinyMCE.settings['document_base_url']);
-			content = content.replace(/<(\w[^>]*) lang=([^ |>]*)([^>]*)/gi, "<$1$3");
-			content = content.replace(/<\\?\?xml[^>]*>/gi, "");
-			content = content.replace(/<\/?\w+:[^>]*>/gi, "");
-			content = content.replace(/-- page break --\s*<p>&nbsp;<\/p>/gi, ""); // Remove pagebreaks
-			content = content.replace(/-- page break --/gi, ""); // Remove pagebreaks
+					if (this.editor.getParam("paste_create_linebreaks", true)) {
+						content = content.replace(/\r\n/g, '<br />');
+						content = content.replace(/\r/g, '<br />');
+						content = content.replace(/\n/g, '<br />');
+					}
+				} 
+			
+				this.editor.execCommand("mceInsertRawHTML", false, content); 
+			}
+		},
+
+		_insertWordContent : function(content) { 
+			var t = this, ed = t.editor;
+
+			if (content && content.length > 0) {
+				// Cleanup Word content
+				var bull = String.fromCharCode(8226);
+				var middot = String.fromCharCode(183);
+				var cb;
+
+				if ((cb = this.editor.getParam("paste_insert_word_content_callback", "")) != "")
+					content = eval(cb + "('before', content)");
 
-	//		content = content.replace(/\/?&nbsp;*/gi, ""); &nbsp;
-	//		content = content.replace(/<p>&nbsp;<\/p>/gi, '');
+				var rl = this.editor.getParam("paste_replace_list", '\u2122,<sup>TM</sup>,\u2026,...,\u201c|\u201d,",\u2019,\',\u2013|\u2014|\u2015|\u2212,-').split(',');
+				for (var i=0; i<rl.length; i+=2)
+					content = content.replace(new RegExp(rl[i], 'gi'), rl[i+1]);
+
+				if (this.editor.getParam("paste_convert_headers_to_strong", false)) {
+					content = content.replace(new RegExp('<p class=MsoHeading.*?>(.*?)<\/p>', 'gi'), '<p><b>$1</b></p>');
+				}
+
+				content = content.replace(new RegExp('tab-stops: list [0-9]+.0pt">', 'gi'), '">' + "--list--");
+				content = content.replace(new RegExp(bull + "(.*?)<BR>", "gi"), "<p>" + middot + "$1</p>");
+				content = content.replace(new RegExp('<SPAN style="mso-list: Ignore">', 'gi'), "<span>" + bull); // Covert to bull list
+				content = content.replace(/<o:p><\/o:p>/gi, "");
+				content = content.replace(new RegExp('<br style="page-break-before: always;.*>', 'gi'), '-- page break --'); // Replace pagebreaks
+				content = content.replace(new RegExp('<(!--)([^>]*)(--)>', 'g'), "");  // Word comments
+
+				if (this.editor.getParam("paste_remove_spans", true))
+					content = content.replace(/<\/?span[^>]*>/gi, "");
+
+				if (this.editor.getParam("paste_remove_styles", true))
+					content = content.replace(new RegExp('<(\\w[^>]*) style="([^"]*)"([^>]*)', 'gi'), "<$1$3");
+
+				content = content.replace(/<\/?font[^>]*>/gi, "");
 
-			if (!tinyMCE.settings['force_p_newlines']) {
-				content = content.replace('', '' ,'gi');
-				content = content.replace('</p>', '<br /><br />' ,'gi');
-			}
+				// Strips class attributes.
+				switch (this.editor.getParam("paste_strip_class_attributes", "all")) {
+					case "all":
+						content = content.replace(/<(\w[^>]*) class=([^ |>]*)([^>]*)/gi, "<$1$3");
+						break;
+
+					case "mso":
+						content = content.replace(new RegExp('<(\\w[^>]*) class="?mso([^ |>]*)([^>]*)', 'gi'), "<$1$3");
+						break;
+				}
 
-			if (!tinyMCE.isMSIE && !tinyMCE.settings['force_p_newlines']) {
-				content = content.replace(/<\/?p[^>]*>/gi, "");
-			}
+				content = content.replace(new RegExp('href="?' + this._reEscape("" + document.location) + '', 'gi'), 'href="' + this.editor.documentBaseURI.getURI());
+				content = content.replace(/<(\w[^>]*) lang=([^ |>]*)([^>]*)/gi, "<$1$3");
+				content = content.replace(/<\\?\?xml[^>]*>/gi, "");
+				content = content.replace(/<\/?\w+:[^>]*>/gi, "");
+				content = content.replace(/-- page break --\s*<p>&nbsp;<\/p>/gi, ""); // Remove pagebreaks
+				content = content.replace(/-- page break --/gi, ""); // Remove pagebreaks
 
-			content = content.replace(/<\/?div[^>]*>/gi, "");
+		//		content = content.replace(/\/?&nbsp;*/gi, ""); &nbsp;
+		//		content = content.replace(/<p>&nbsp;<\/p>/gi, '');
+
+				if (!this.editor.getParam('force_p_newlines')) {
+					content = content.replace('', '' ,'gi');
+					content = content.replace('</p>', '<br /><br />' ,'gi');
+				}
+
+				if (!tinymce.isIE && !this.editor.getParam('force_p_newlines')) {
+					content = content.replace(/<\/?p[^>]*>/gi, "");
+				}
 
-			// Convert all middlot lists to UL lists
-			if (tinyMCE.getParam("paste_convert_middot_lists", true)) {
-				var div = document.createElement("div");
-				div.innerHTML = content;
+				content = content.replace(/<\/?div[^>]*>/gi, "");
+
+				// Convert all middlot lists to UL lists
+				if (this.editor.getParam("paste_convert_middot_lists", true)) {
+					var div = ed.dom.create("div", null, content);
+
+					// Convert all middot paragraphs to li elements
+					var className = this.editor.getParam("paste_unindented_list_class", "unIndentedList");
+
+					while (this._convertMiddots(div, "--list--")) ; // bull
+					while (this._convertMiddots(div, middot, className)) ; // Middot
+					while (this._convertMiddots(div, bull)) ; // bull
 
-				// Convert all middot paragraphs to li elements
-				var className = tinyMCE.getParam("paste_unindented_list_class", "unIndentedList");
+					content = div.innerHTML;
+				}
+
+				// Replace all headers with strong and fix some other issues
+				if (this.editor.getParam("paste_convert_headers_to_strong", false)) {
+					content = content.replace(/<h[1-6]>&nbsp;<\/h[1-6]>/gi, '<p>&nbsp;&nbsp;</p>');
+					content = content.replace(/<h[1-6]>/gi, '<p><b>');
+					content = content.replace(/<\/h[1-6]>/gi, '</b></p>');
+					content = content.replace(/<b>&nbsp;<\/b>/gi, '<b>&nbsp;&nbsp;</b>');
+					content = content.replace(/^(&nbsp;)*/gi, '');
+				}
+
+				content = content.replace(/--list--/gi, ""); // Remove --list--
 
-				while (TinyMCE_PastePlugin._convertMiddots(div, "--list--")) ; // bull
-				while (TinyMCE_PastePlugin._convertMiddots(div, middot, className)) ; // Middot
-				while (TinyMCE_PastePlugin._convertMiddots(div, bull)) ; // bull
+				if ((cb = this.editor.getParam("paste_insert_word_content_callback", "")) != "")
+					content = eval(cb + "('after', content)");
 
-				content = div.innerHTML;
-			}
+				// Insert cleaned content
+				this.editor.execCommand("mceInsertContent", false, content);
+
+				if (this.editor.getParam('paste_force_cleanup_wordpaste', true)) {
+					var ed = this.editor;
 
-			// Replace all headers with strong and fix some other issues
-			if (tinyMCE.getParam("paste_convert_headers_to_strong", false)) {
-				content = content.replace(/<h[1-6]>&nbsp;<\/h[1-6]>/gi, '<p>&nbsp;&nbsp;</p>');
-				content = content.replace(/<h[1-6]>/gi, '<p><b>');
-				content = content.replace(/<\/h[1-6]>/gi, '</b></p>');
-				content = content.replace(/<b>&nbsp;<\/b>/gi, '<b>&nbsp;&nbsp;</b>');
-				content = content.replace(/^(&nbsp;)*/gi, '');
+					window.setTimeout(function() {
+						ed.execCommand("mceCleanup");
+					}, 1); // Do normal cleanup detached from this thread
+				}
+			}
+		},
+
+		_reEscape : function(s) {
+			var l = "?.\\*[](){}+^$:";
+			var o = "";
+
+			for (var i=0; i<s.length; i++) {
+				var c = s.charAt(i);
+
+				if (l.indexOf(c) != -1)
+					o += '\\' + c;
+				else
+					o += c;
 			}
 
-			content = content.replace(/--list--/gi, ""); // Remove --list--
+			return o;
+		},
 
-			if ((cb = tinyMCE.getParam("paste_insert_word_content_callback", "")) != "")
-				content = eval(cb + "('after', content)");
-
-			// Insert cleaned content
-			tinyMCE.execCommand("mceInsertContent", false, content);
+		_convertMiddots : function(div, search, class_name) {
+			var mdot = String.fromCharCode(183);
+			var bull = String.fromCharCode(8226);
 
-			if (tinyMCE.getParam('paste_force_cleanup_wordpaste', true))
-				window.setTimeout('tinyMCE.execCommand("mceCleanup");', 1); // Do normal cleanup detached from this thread
-		}
-	},
+			var nodes = div.getElementsByTagName("p");
+			var prevul;
+			for (var i=0; i<nodes.length; i++) {
+				var p = nodes[i];
 
-	_reEscape : function(s) {
-		var l = "?.\\*[](){}+^$:";
-		var o = "";
-
-		for (var i=0; i<s.length; i++) {
-			var c = s.charAt(i);
+				// Is middot
+				if (p.innerHTML.indexOf(search) == 0) {
+					var ul = document.createElement("ul");
 
-			if (l.indexOf(c) != -1)
-				o += '\\' + c;
-			else
-				o += c;
-		}
+					if (class_name)
+						ul.className = class_name;
 
-		return o;
-	},
+					// Add the first one
+					var li = document.createElement("li");
+					li.innerHTML = p.innerHTML.replace(new RegExp('' + mdot + '|' + bull + '|--list--|&nbsp;', "gi"), '');
+					ul.appendChild(li);
 
-	_convertMiddots : function(div, search, class_name) {
-		var mdot = String.fromCharCode(183);
-		var bull = String.fromCharCode(8226);
-
-		var nodes = div.getElementsByTagName("p");
-		var prevul;
-		for (var i=0; i<nodes.length; i++) {
-			var p = nodes[i];
-
-			// Is middot
-			if (p.innerHTML.indexOf(search) == 0) {
-				var ul = document.createElement("ul");
-
-				if (class_name)
-					ul.className = class_name;
+					// Add the rest
+					var np = p.nextSibling;
+					while (np) {
+						// If the node is whitespace, then
+						// ignore it and continue on.
+						if (np.nodeType == 3 && new RegExp('^\\s$', 'm').test(np.nodeValue)) {
+								np = np.nextSibling;
+								continue;
+						}
 
-				// Add the first one
-				var li = document.createElement("li");
-				li.innerHTML = p.innerHTML.replace(new RegExp('' + mdot + '|' + bull + '|--list--|&nbsp;', "gi"), '');
-				ul.appendChild(li);
-
-				// Add the rest
-				var np = p.nextSibling;
-				while (np) {
-			        // If the node is whitespace, then
-			        // ignore it and continue on.
-			        if (np.nodeType == 3 && new RegExp('^\\s$', 'm').test(np.nodeValue)) {
-			                np = np.nextSibling;
-			                continue;
-			        }
+						if (search == mdot) {
+								if (np.nodeType == 1 && new RegExp('^o(\\s+|&nbsp;)').test(np.innerHTML)) {
+										// Second level of nesting
+										if (!prevul) {
+												prevul = ul;
+												ul = document.createElement("ul");
+												prevul.appendChild(ul);
+										}
+										np.innerHTML = np.innerHTML.replace(/^o/, '');
+								} else {
+										// Pop the stack if we're going back up to the first level
+										if (prevul) {
+												ul = prevul;
+												prevul = null;
+										}
+										// Not element or middot paragraph
+										if (np.nodeType != 1 || np.innerHTML.indexOf(search) != 0)
+												break;
+								}
+						} else {
+								// Not element or middot paragraph
+								if (np.nodeType != 1 || np.innerHTML.indexOf(search) != 0)
+										break;
+							}
 
-					if (search == mdot) {
-					        if (np.nodeType == 1 && new RegExp('^o(\\s+|&nbsp;)').test(np.innerHTML)) {
-					                // Second level of nesting
-					                if (!prevul) {
-					                        prevul = ul;
-					                        ul = document.createElement("ul");
-					                        prevul.appendChild(ul);
-					                }
-					                np.innerHTML = np.innerHTML.replace(/^o/, '');
-					        } else {
-					                // Pop the stack if we're going back up to the first level
-					                if (prevul) {
-					                        ul = prevul;
-					                        prevul = null;
-					                }
-					                // Not element or middot paragraph
-					                if (np.nodeType != 1 || np.innerHTML.indexOf(search) != 0)
-					                        break;
-					        }
-					} else {
-					        // Not element or middot paragraph
-					        if (np.nodeType != 1 || np.innerHTML.indexOf(search) != 0)
-					                break;
-				        }
+						var cp = np.nextSibling;
+						var li = document.createElement("li");
+						li.innerHTML = np.innerHTML.replace(new RegExp('' + mdot + '|' + bull + '|--list--|&nbsp;', "gi"), '');
+						np.parentNode.removeChild(np);
+						ul.appendChild(li);
+						np = cp;
+					}
+
+					p.parentNode.replaceChild(ul, p);
+
+					return true;
+				}
+			}
 
-					var cp = np.nextSibling;
-					var li = document.createElement("li");
-					li.innerHTML = np.innerHTML.replace(new RegExp('' + mdot + '|' + bull + '|--list--|&nbsp;', "gi"), '');
-					np.parentNode.removeChild(np);
-					ul.appendChild(li);
-					np = cp;
+			return false;
+		},
+
+		_clipboardHTML : function() {
+			var div = document.getElementById('_TinyMCE_clipboardHTML');
+
+			if (!div) {
+				var div = document.createElement('DIV');
+				div.id = '_TinyMCE_clipboardHTML';
+
+				with (div.style) {
+					visibility = 'hidden';
+					overflow = 'hidden';
+					position = 'absolute';
+					width = 1;
+					height = 1;
 				}
 
-				p.parentNode.replaceChild(ul, p);
-
-				return true;
-			}
-		}
-
-		return false;
-	},
-
-	_clipboardHTML : function() {
-		var div = document.getElementById('_TinyMCE_clipboardHTML');
-
-		if (!div) {
-			var div = document.createElement('DIV');
-			div.id = '_TinyMCE_clipboardHTML';
-
-			with (div.style) {
-				visibility = 'hidden';
-				overflow = 'hidden';
-				position = 'absolute';
-				width = 1;
-				height = 1;
+				document.body.appendChild(div);
 			}
 
-			document.body.appendChild(div);
+			div.innerHTML = '';
+			var rng = document.body.createTextRange();
+			rng.moveToElementText(div);
+			rng.execCommand('Paste');
+			var html = div.innerHTML;
+			div.innerHTML = '';
+			return html;
 		}
+	});
 
-		div.innerHTML = '';
-		var rng = document.body.createTextRange();
-		rng.moveToElementText(div);
-		rng.execCommand('Paste');
-		var html = div.innerHTML;
-		div.innerHTML = '';
-		return html;
-	}
-};
-
-tinyMCE.addPlugin("paste", TinyMCE_PastePlugin);
+	// Register plugin
+	tinymce.PluginManager.add('paste', tinymce.plugins.PastePlugin);
+})();
\ No newline at end of file
Binary file includes/clientside/tinymce/plugins/paste/images/pastetext.gif has changed
Binary file includes/clientside/tinymce/plugins/paste/images/pasteword.gif has changed
Binary file includes/clientside/tinymce/plugins/paste/images/selectall.gif has changed
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/includes/clientside/tinymce/plugins/paste/js/pastetext.js	Fri Feb 22 12:51:53 2008 -0500
@@ -0,0 +1,42 @@
+tinyMCEPopup.requireLangPack();
+
+function saveContent() {
+	if (document.forms[0].htmlSource.value == '') {
+		tinyMCEPopup.close();
+		return false;
+	}
+
+	tinyMCEPopup.execCommand('mcePasteText', false, {
+		html : document.forms[0].htmlSource.value,
+		linebreaks : document.forms[0].linebreaks.checked
+	});
+
+	tinyMCEPopup.close();
+}
+
+function onLoadInit() {
+	tinyMCEPopup.resizeToInnerSize();
+
+	// Remove Gecko spellchecking
+	if (tinymce.isGecko)
+		document.body.spellcheck = tinyMCEPopup.getParam("gecko_spellcheck");
+
+	resizeInputs();
+}
+
+var wHeight=0, wWidth=0, owHeight=0, owWidth=0;
+
+function resizeInputs() {
+	if (!tinymce.isIE) {
+		wHeight = self.innerHeight-80;
+		wWidth = self.innerWidth-17;
+	} else {
+		wHeight = document.body.clientHeight-80;
+		wWidth = document.body.clientWidth-17;
+	}
+
+	document.forms[0].htmlSource.style.height = Math.abs(wHeight) + 'px';
+	document.forms[0].htmlSource.style.width  = Math.abs(wWidth) + 'px';
+}
+
+tinyMCEPopup.onInit.add(onLoadInit);
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/includes/clientside/tinymce/plugins/paste/js/pasteword.js	Fri Feb 22 12:51:53 2008 -0500
@@ -0,0 +1,56 @@
+tinyMCEPopup.requireLangPack();
+
+function saveContent() {
+	var html = document.getElementById("frmData").contentWindow.document.body.innerHTML;
+
+	if (html == ''){
+		tinyMCEPopup.close();
+		return false;
+	}
+
+	tinyMCEPopup.execCommand('mcePasteWord', false, html);
+	tinyMCEPopup.close();
+}
+
+function onLoadInit() {
+	tinyMCEPopup.resizeToInnerSize();
+
+	// Fix for endless reloading in FF
+	window.setTimeout('createIFrame();', 10);
+}
+
+function createIFrame() {
+	document.getElementById('iframecontainer').innerHTML = '<iframe id="frmData" name="frmData" class="sourceIframe" src="blank.htm" height="280" width="400" frameborder="0" style="background-color:#FFFFFF; width:100%;" dir="ltr" wrap="soft"></iframe>';
+}
+
+var wHeight=0, wWidth=0, owHeight=0, owWidth=0;
+
+function initIframe(doc) {
+	var dir = tinyMCEPopup.editor.settings.directionality;
+
+	doc.body.dir = dir;
+
+	// Remove Gecko spellchecking
+	if (tinymce.isGecko)
+		doc.body.spellcheck = tinyMCEPopup.getParam("gecko_spellcheck");
+
+	resizeInputs();
+}
+
+function resizeInputs() {
+	if (!tinymce.isIE) {
+		wHeight = self.innerHeight - 80;
+		wWidth = self.innerWidth - 18;
+	} else {
+		wHeight = document.body.clientHeight - 80;
+		wWidth = document.body.clientWidth - 18;
+	}
+
+	var elm = document.getElementById('frmData');
+	if (elm) {
+		elm.style.height = Math.abs(wHeight) + 'px';
+		elm.style.width  = Math.abs(wWidth) + 'px';
+	}
+}
+
+tinyMCEPopup.onInit.add(onLoadInit);
--- a/includes/clientside/tinymce/plugins/paste/jscripts/pastetext.js	Fri Feb 22 12:46:51 2008 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,38 +0,0 @@
-function saveContent() {
-	if (document.forms[0].htmlSource.value == '') {
-		tinyMCEPopup.close();
-		return false;
-	}
-
-	tinyMCEPopup.execCommand('mcePasteText', false, {
-		html : document.forms[0].htmlSource.value,
-		linebreaks : document.forms[0].linebreaks.checked
-	});
-
-	tinyMCEPopup.close();
-}
-
-function onLoadInit() {
-	tinyMCEPopup.resizeToInnerSize();
-
-	// Remove Gecko spellchecking
-	if (tinyMCE.isGecko)
-		document.body.spellcheck = tinyMCE.getParam("gecko_spellcheck");
-
-	resizeInputs();
-}
-
-var wHeight=0, wWidth=0, owHeight=0, owWidth=0;
-
-function resizeInputs() {
-	if (!tinyMCE.isMSIE) {
-		wHeight = self.innerHeight-80;
-		wWidth = self.innerWidth-17;
-	} else {
-		wHeight = document.body.clientHeight-80;
-		wWidth = document.body.clientWidth-17;
-	}
-
-	document.forms[0].htmlSource.style.height = Math.abs(wHeight) + 'px';
-	document.forms[0].htmlSource.style.width  = Math.abs(wWidth) + 'px';
-}
--- a/includes/clientside/tinymce/plugins/paste/jscripts/pasteword.js	Fri Feb 22 12:46:51 2008 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,52 +0,0 @@
-function saveContent() {
-	var html = document.getElementById("frmData").contentWindow.document.body.innerHTML;
-
-	if (html == ''){
-		tinyMCEPopup.close();
-		return false;
-	}
-
-	tinyMCEPopup.execCommand('mcePasteWord', false, html);
-	tinyMCEPopup.close();
-}
-
-function onLoadInit() {
-	tinyMCEPopup.resizeToInnerSize();
-
-	// Fix for endless reloading in FF
-	window.setTimeout('createIFrame();', 10);
-}
-
-function createIFrame() {
-	document.getElementById('iframecontainer').innerHTML = '<iframe id="frmData" name="frmData" class="sourceIframe" src="blank.htm" height="280" width="400" frameborder="0" style="background-color:#FFFFFF; width:100%;" dir="ltr" wrap="soft"></iframe>';
-}
-
-var wHeight=0, wWidth=0, owHeight=0, owWidth=0;
-
-function initIframe(doc) {
-	var dir = tinyMCE.selectedInstance.settings['directionality'];
-
-	doc.body.dir = dir;
-
-	// Remove Gecko spellchecking
-	if (tinyMCE.isGecko)
-		doc.body.spellcheck = tinyMCE.getParam("gecko_spellcheck");
-
-	resizeInputs();
-}
-
-function resizeInputs() {
-	if (!tinyMCE.isMSIE) {
-		wHeight = self.innerHeight - 80;
-		wWidth = self.innerWidth - 18;
-	} else {
-		wHeight = document.body.clientHeight - 80;
-		wWidth = document.body.clientWidth - 18;
-	}
-
-	var elm = document.getElementById('frmData');
-	if (elm) {
-		elm.style.height = Math.abs(wHeight) + 'px';
-		elm.style.width  = Math.abs(wWidth) + 'px';
-	}
-}
--- a/includes/clientside/tinymce/plugins/paste/langs/en.js	Fri Feb 22 12:46:51 2008 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,10 +0,0 @@
-// UK lang variables
-
-tinyMCE.addToLang('',{
-paste_text_desc : 'Paste as Plain Text',
-paste_text_title : 'Use CTRL+V on your keyboard to paste the text into the window.',
-paste_text_linebreaks : 'Keep linebreaks',
-paste_word_desc : 'Paste from Word',
-paste_word_title : 'Use CTRL+V on your keyboard to paste the text into the window.',
-selectall_desc : 'Select All'
-});
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/includes/clientside/tinymce/plugins/paste/langs/en_dlg.js	Fri Feb 22 12:51:53 2008 -0500
@@ -0,0 +1,5 @@
+tinyMCE.addI18n('en.paste_dlg',{
+text_title:"Use CTRL+V on your keyboard to paste the text into the window.",
+text_linebreaks:"Keep linebreaks",
+word_title:"Use CTRL+V on your keyboard to paste the text into the window."
+});
\ No newline at end of file
--- a/includes/clientside/tinymce/plugins/paste/pastetext.htm	Fri Feb 22 12:46:51 2008 -0500
+++ b/includes/clientside/tinymce/plugins/paste/pastetext.htm	Fri Feb 22 12:51:53 2008 -0500
@@ -1,32 +1,32 @@
 <html xmlns="http://www.w3.org/1999/xhtml">
 <head>
-	<title>{$lang_paste_text_desc}</title>
+	<title>{#paste.paste_text_desc}</title>
 	<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
-	<script language="javascript" type="text/javascript" src="../../tiny_mce_popup.js"></script>
-	<script language="javascript" type="text/javascript" src="jscripts/pastetext.js"></script>
+	<script type="text/javascript" src="../../tiny_mce_popup.js"></script>
+	<script type="text/javascript" src="js/pastetext.js"></script>
 	<base target="_self" />
 </head>
-<body onload="tinyMCEPopup.executeOnLoad('onLoadInit();');" onresize="resizeInputs();" style="display: none">
+<body onresize="resizeInputs();" style="display:none; overflow:hidden;">
 <form name="source" onsubmit="saveContent();">
-	<div style="float: left" class="title">{$lang_paste_text_desc}</div>
+	<div style="float: left" class="title">{#paste.paste_text_desc}</div>
 
 	<div style="float: right">
-		<input type="checkbox" name="linebreaks" id="linebreaks" class="wordWrapCode" checked="checked" /><label for="linebreaks">{$lang_paste_text_linebreaks}</label>
+		<input type="checkbox" name="linebreaks" id="linebreaks" class="wordWrapCode" checked="checked" /><label for="linebreaks">{#paste_dlg.text_linebreaks}</label>
 	</div>
 
 	<br style="clear: both" />
 
-	<div>{$lang_paste_text_title}</div>
+	<div>{#paste_dlg.text_title}</div>
 
 	<textarea name="htmlSource" id="htmlSource" rows="15" cols="100" style="width: 100%; height: 100%; font-family: 'Courier New',Courier,mono; font-size: 12px;" dir="ltr" wrap="soft"></textarea>
 
 	<div class="mceActionPanel">
 		<div style="float: left">
-			<input type="button" name="insert" value="{$lang_insert}" onclick="saveContent();" id="insert" />
+			<input type="button" name="insert" value="{#insert}" onclick="saveContent();" id="insert" />
 		</div>
 
 		<div style="float: right">
-			<input type="button" name="cancel" value="{$lang_cancel}" onclick="tinyMCEPopup.close();" id="cancel" />
+			<input type="button" name="cancel" value="{#cancel}" onclick="tinyMCEPopup.close();" id="cancel" />
 		</div>
 	</div>
 </form>
--- a/includes/clientside/tinymce/plugins/paste/pasteword.htm	Fri Feb 22 12:46:51 2008 -0500
+++ b/includes/clientside/tinymce/plugins/paste/pasteword.htm	Fri Feb 22 12:51:53 2008 -0500
@@ -1,27 +1,27 @@
 <html xmlns="http://www.w3.org/1999/xhtml">
 <head>
 	<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
-	<title>{$lang_paste_word_desc}</title>
-	<script language="javascript" type="text/javascript" src="../../tiny_mce_popup.js"></script>
-	<script language="javascript" type="text/javascript" src="jscripts/pasteword.js"></script>
+	<title>{#paste.paste_word_desc}</title>
+	<script type="text/javascript" src="../../tiny_mce_popup.js"></script>
+	<script type="text/javascript" src="js/pasteword.js"></script>
 	<link href="css/pasteword.css" rel="stylesheet" type="text/css" />
 	<base target="_self" />
 </head>
-<body onload="tinyMCEPopup.executeOnLoad('onLoadInit();');" onresize="resizeInputs();" style="display: none">
+<body onresize="resizeInputs();" style="display:none; overflow:hidden;">
 	<form name="source" onsubmit="saveContent();" action="#">
-		<div class="title">{$lang_paste_word_desc}</div>
+		<div class="title">{#paste.paste_word_desc}</div>
 
-		<div>{$lang_paste_word_title}</div>
+		<div>{#paste_dlg.word_title}</div>
 
 		<div id="iframecontainer"></div>
 
 		<div class="mceActionPanel">
 			<div style="float: left">
-				<input type="button" id="insert" name="insert" value="{$lang_insert}" onclick="saveContent();" />
+				<input type="button" id="insert" name="insert" value="{#insert}" onclick="saveContent();" />
 			</div>
 
 			<div style="float: right">
-				<input type="button" id="cancel" name="cancel" value="{$lang_cancel}" onclick="tinyMCEPopup.close();" />
+				<input type="button" id="cancel" name="cancel" value="{#cancel}" onclick="tinyMCEPopup.close();" />
 			</div>
 		</div>
 	</form>
--- a/includes/clientside/tinymce/plugins/paste/readme.txt	Fri Feb 22 12:46:51 2008 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1 +0,0 @@
-Check the TinyMCE documentation for details on this plugin.
--- a/includes/clientside/tinymce/plugins/preview/editor_plugin.js	Fri Feb 22 12:46:51 2008 -0500
+++ b/includes/clientside/tinymce/plugins/preview/editor_plugin.js	Fri Feb 22 12:51:53 2008 -0500
@@ -1,1 +1,1 @@
-tinyMCE.importPluginLanguagePack('preview');var TinyMCE_PreviewPlugin={getInfo:function(){return{longname:'Preview',author:'Moxiecode Systems AB',authorurl:'http://tinymce.moxiecode.com',infourl:'http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/preview',version:tinyMCE.majorVersion+"."+tinyMCE.minorVersion}},getControlHTML:function(cn){switch(cn){case"preview":return tinyMCE.getButtonHTML(cn,'lang_preview_desc','{$pluginurl}/images/preview.gif','mcePreview')}return""},execCommand:function(editor_id,element,command,user_interface,value){switch(command){case"mcePreview":var previewPage=tinyMCE.getParam("plugin_preview_pageurl",null);var previewWidth=tinyMCE.getParam("plugin_preview_width","550");var previewHeight=tinyMCE.getParam("plugin_preview_height","600");if(previewPage){var template=new Array();template['file']=previewPage;template['width']=previewWidth;template['height']=previewHeight;tinyMCE.openWindow(template,{editor_id:editor_id,resizable:"yes",scrollbars:"yes",inline:"yes",content:tinyMCE.getContent(),content_css:tinyMCE.getParam("content_css")})}else{var win=window.open("","mcePreview","menubar=no,toolbar=no,scrollbars=yes,resizable=yes,left=20,top=20,width="+previewWidth+",height="+previewHeight);var html="",i;var c=tinyMCE.getContent();var pos=c.indexOf('<body'),pos2,css=tinyMCE.getParam("content_css").split(',');if(pos!=-1){pos=c.indexOf('>',pos);pos2=c.lastIndexOf('</body>');c=c.substring(pos+1,pos2)}html+=tinyMCE.getParam('doctype');html+='<html xmlns="http://www.w3.org/1999/xhtml">';html+='<head>';html+='<title>'+tinyMCE.getLang('lang_preview_desc')+'</title>';html+='<base href="'+tinyMCE.settings['base_href']+'" />';html+='<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />';for(i=0;i<css.length;i++)html+='<link href="'+css[i]+'" rel="stylesheet" type="text/css" />';html+='<script type="text/javascript">';html+='window.opener.TinyMCE_PreviewPlugin._setDoc(document);';html+='window.opener.TinyMCE_PreviewPlugin._setWin(window);';html+='writeFlash = window.opener.TinyMCE_PreviewPlugin._writeFlash;';html+='writeShockWave = window.opener.TinyMCE_PreviewPlugin._writeShockWave;';html+='writeQuickTime = window.opener.TinyMCE_PreviewPlugin._writeQuickTime;';html+='writeRealMedia = window.opener.TinyMCE_PreviewPlugin._writeRealMedia;';html+='writeWindowsMedia = window.opener.TinyMCE_PreviewPlugin._writeWindowsMedia;';html+='writeEmbed = window.opener.TinyMCE_PreviewPlugin._writeEmbed;';html+='</script>';html+='</head>';html+='<body dir="'+tinyMCE.getParam("directionality")+'" onload="window.opener.TinyMCE_PreviewPlugin._onLoad();">';html+=c;html+='</body>';html+='</html>';win.document.write(html);win.document.close()}return true}return false},_setDoc:function(d){TinyMCE_PreviewPlugin._doc=d;d._embeds=new Array()},_setWin:function(d){TinyMCE_PreviewPlugin._win=d},_onLoad:function(){var nl,i,el=new Array(),d=TinyMCE_PreviewPlugin._doc,sv,ne;nl=d.getElementsByTagName("script");for(i=0;i<nl.length;i++){sv=tinyMCE.isMSIE?nl[i].innerHTML:nl[i].firstChild.nodeValue;if(new RegExp('write(Flash|ShockWave|WindowsMedia|QuickTime|RealMedia)\\(.*','g').test(sv))el[el.length]=nl[i]}for(i=0;i<el.length;i++){ne=d.createElement("div");ne.innerHTML=d._embeds[i];el[i].parentNode.insertBefore(ne.firstChild,el[i])}},_writeFlash:function(p){p.src=tinyMCE.convertRelativeToAbsoluteURL(tinyMCE.settings['base_href'],p.src);TinyMCE_PreviewPlugin._writeEmbed('D27CDB6E-AE6D-11cf-96B8-444553540000','http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,40,0','application/x-shockwave-flash',p)},_writeShockWave:function(p){p.src=tinyMCE.convertRelativeToAbsoluteURL(tinyMCE.settings['base_href'],p.src);TinyMCE_PreviewPlugin._writeEmbed('166B1BCA-3F9C-11CF-8075-444553540000','http://download.macromedia.com/pub/shockwave/cabs/director/sw.cab#version=8,5,1,0','application/x-director',p)},_writeQuickTime:function(p){p.src=tinyMCE.convertRelativeToAbsoluteURL(tinyMCE.settings['base_href'],p.src);TinyMCE_PreviewPlugin._writeEmbed('02BF25D5-8C17-4B23-BC80-D3488ABDDC6B','http://www.apple.com/qtactivex/qtplugin.cab#version=6,0,2,0','video/quicktime',p)},_writeRealMedia:function(p){p.src=tinyMCE.convertRelativeToAbsoluteURL(tinyMCE.settings['base_href'],p.src);TinyMCE_PreviewPlugin._writeEmbed('CFCDAA03-8BE4-11cf-B84B-0020AFBBCCFA','http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,40,0','audio/x-pn-realaudio-plugin',p)},_writeWindowsMedia:function(p){p.src=tinyMCE.convertRelativeToAbsoluteURL(tinyMCE.settings['base_href'],p.src);p.url=p.src;TinyMCE_PreviewPlugin._writeEmbed('6BF52A52-394A-11D3-B153-00C04F79FAA6','http://activex.microsoft.com/activex/controls/mplayer/en/nsmp2inf.cab#Version=5,1,52,701','application/x-mplayer2',p)},_writeEmbed:function(cls,cb,mt,p){var h='',n,d=TinyMCE_PreviewPlugin._doc,ne,c;h+='<object classid="clsid:'+cls+'" codebase="'+cb+'"';h+=typeof(p.id)!="undefined"?'id="'+p.id+'"':'';h+=typeof(p.name)!="undefined"?'name="'+p.name+'"':'';h+=typeof(p.width)!="undefined"?'width="'+p.width+'"':'';h+=typeof(p.height)!="undefined"?'height="'+p.height+'"':'';h+=typeof(p.align)!="undefined"?'align="'+p.align+'"':'';h+='>';for(n in p)h+='<param name="'+n+'" value="'+p[n]+'">';h+='<embed type="'+mt+'"';for(n in p)h+=n+'="'+p[n]+'" ';h+='></embed></object>';d._embeds[d._embeds.length]=h}};tinyMCE.addPlugin("preview",TinyMCE_PreviewPlugin);
\ No newline at end of file
+(function(){tinymce.create('tinymce.plugins.Preview',{init:function(ed,url){var t=this;t.editor=ed;ed.addCommand('mcePreview',t._preview,t);ed.addButton('preview',{title:'preview.preview_desc',cmd:'mcePreview'});},getInfo:function(){return{longname:'Preview',author:'Moxiecode Systems AB',authorurl:'http://tinymce.moxiecode.com',infourl:'http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/preview',version:tinymce.majorVersion+"."+tinymce.minorVersion};},_preview:function(){var ed=this.editor,win,html,c,pos,pos2,css,i,page=ed.getParam("plugin_preview_pageurl",null),w=ed.getParam("plugin_preview_width","550"),h=ed.getParam("plugin_preview_height","600");if(page){ed.windowManager.open({file:ed.getParam("plugin_preview_pageurl",null),width:w,height:h},{resizable:"yes",scrollbars:"yes",inline:1});}else{win=window.open("","mcePreview","menubar=no,toolbar=no,scrollbars=yes,resizable=yes,left=20,top=20,width="+w+",height="+h);html="";c=ed.getContent();pos=c.indexOf('<body');css=ed.getParam("content_css",'').split(',');tinymce.map(css,function(u){return ed.documentBaseURI.toAbsolute(u);});if(pos!=-1){pos=c.indexOf('>',pos);pos2=c.lastIndexOf('</body>');c=c.substring(pos+1,pos2);}html+=ed.getParam('doctype');html+='<html xmlns="http://www.w3.org/1999/xhtml">';html+='<head>';html+='<title>'+ed.getLang('preview.preview_desc')+'</title>';html+='<base href="'+ed.documentBaseURI.getURI()+'" />';html+='<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />';for(i=0;i<css.length;i++)html+='<link href="'+css[i]+'" rel="stylesheet" type="text/css" />';html+='</head>';html+='<body dir="'+ed.getParam("directionality")+'" onload="window.opener.tinymce.EditorManager.get(\''+ed.id+'\').plugins[\'preview\']._onLoad(window,document);">';html+=c;html+='</body>';html+='</html>';win.document.write(html);win.document.close();}},_onLoad:function(w,d){var t=this,nl,i,el=[],sv,ne;t._doc=d;w.writeFlash=t._writeFlash;w.writeShockWave=t._writeShockWave;w.writeQuickTime=t._writeQuickTime;w.writeRealMedia=t._writeRealMedia;w.writeWindowsMedia=t._writeWindowsMedia;w.writeEmbed=t._writeEmbed;nl=d.getElementsByTagName("script");for(i=0;i<nl.length;i++){sv=tinymce.isIE?nl[i].innerHTML:nl[i].firstChild.nodeValue;if(new RegExp('write(Flash|ShockWave|WindowsMedia|QuickTime|RealMedia)\\(.*','g').test(sv))el[el.length]=nl[i];}for(i=0;i<el.length;i++){ne=d.createElement("div");ne.innerHTML=d._embeds[i];el[i].parentNode.insertBefore(ne.firstChild,el[i]);}},_writeFlash:function(p){p.src=this.editor.documentBaseURI.toAbsolute(p.src);TinyMCE_PreviewPlugin._writeEmbed('D27CDB6E-AE6D-11cf-96B8-444553540000','http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,40,0','application/x-shockwave-flash',p);},_writeShockWave:function(p){this.editor.documentBaseURI.toAbsolute(p.src);TinyMCE_PreviewPlugin._writeEmbed('166B1BCA-3F9C-11CF-8075-444553540000','http://download.macromedia.com/pub/shockwave/cabs/director/sw.cab#version=8,5,1,0','application/x-director',p);},_writeQuickTime:function(p){this.editor.documentBaseURI.toAbsolute(p.src);TinyMCE_PreviewPlugin._writeEmbed('02BF25D5-8C17-4B23-BC80-D3488ABDDC6B','http://www.apple.com/qtactivex/qtplugin.cab#version=6,0,2,0','video/quicktime',p);},_writeRealMedia:function(p){this.editor.documentBaseURI.toAbsolute(p.src);TinyMCE_PreviewPlugin._writeEmbed('CFCDAA03-8BE4-11cf-B84B-0020AFBBCCFA','http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,40,0','audio/x-pn-realaudio-plugin',p);},_writeWindowsMedia:function(p){this.editor.documentBaseURI.toAbsolute(p.src);p.url=p.src;TinyMCE_PreviewPlugin._writeEmbed('6BF52A52-394A-11D3-B153-00C04F79FAA6','http://activex.microsoft.com/activex/controls/mplayer/en/nsmp2inf.cab#Version=5,1,52,701','application/x-mplayer2',p);},_writeEmbed:function(cls,cb,mt,p){var h='',n,d=t._doc,ne,c;h+='<object classid="clsid:'+cls+'" codebase="'+cb+'"';h+=typeof(p.id)!="undefined"?'id="'+p.id+'"':'';h+=typeof(p.name)!="undefined"?'name="'+p.name+'"':'';h+=typeof(p.width)!="undefined"?'width="'+p.width+'"':'';h+=typeof(p.height)!="undefined"?'height="'+p.height+'"':'';h+=typeof(p.align)!="undefined"?'align="'+p.align+'"':'';h+='>';for(n in p)h+='<param name="'+n+'" value="'+p[n]+'">';h+='<embed type="'+mt+'"';for(n in p)h+=n+'="'+p[n]+'" ';h+='></embed></object>';d._embeds[d._embeds.length]=h;}});tinymce.PluginManager.add('preview',tinymce.plugins.Preview);})();
\ No newline at end of file
--- a/includes/clientside/tinymce/plugins/preview/editor_plugin_src.js	Fri Feb 22 12:46:51 2008 -0500
+++ b/includes/clientside/tinymce/plugins/preview/editor_plugin_src.js	Fri Feb 22 12:51:53 2008 -0500
@@ -1,205 +1,187 @@
 /**
- * $Id: editor_plugin_src.js 201 2007-02-12 15:56:56Z spocke $
+ * $Id: editor_plugin_src.js 537 2008-01-14 16:38:33Z spocke $
  *
  * @author Moxiecode
- * @copyright Copyright © 2004-2007, Moxiecode Systems AB, All rights reserved.
+ * @copyright Copyright © 2004-2008, Moxiecode Systems AB, All rights reserved.
  */
 
-/* Import plugin specific language pack */
-tinyMCE.importPluginLanguagePack('preview');
+(function() {
+	tinymce.create('tinymce.plugins.Preview', {
+		init : function(ed, url) {
+			var t = this;
 
-var TinyMCE_PreviewPlugin = {
-	getInfo : function() {
-		return {
-			longname : 'Preview',
-			author : 'Moxiecode Systems AB',
-			authorurl : 'http://tinymce.moxiecode.com',
-			infourl : 'http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/preview',
-			version : tinyMCE.majorVersion + "." + tinyMCE.minorVersion
-		};
-	},
+			t.editor = ed;
+
+			ed.addCommand('mcePreview', t._preview, t);
+			ed.addButton('preview', {title : 'preview.preview_desc', cmd : 'mcePreview'});
+		},
 
-	/**
-	 * Returns the HTML contents of the preview control.
-	 */
-	getControlHTML : function(cn) {
-		switch (cn) {
-			case "preview":
-				return tinyMCE.getButtonHTML(cn, 'lang_preview_desc', '{$pluginurl}/images/preview.gif', 'mcePreview');
-		}
-
-		return "";
-	},
+		getInfo : function() {
+			return {
+				longname : 'Preview',
+				author : 'Moxiecode Systems AB',
+				authorurl : 'http://tinymce.moxiecode.com',
+				infourl : 'http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/preview',
+				version : tinymce.majorVersion + "." + tinymce.minorVersion
+			};
+		},
 
-	/**
-	 * Executes the mcePreview command.
-	 */
-	execCommand : function(editor_id, element, command, user_interface, value) {
-		// Handle commands
-		switch (command) {
-			case "mcePreview":
-				var previewPage = tinyMCE.getParam("plugin_preview_pageurl", null);
-				var previewWidth = tinyMCE.getParam("plugin_preview_width", "550");
-				var previewHeight = tinyMCE.getParam("plugin_preview_height", "600");
+		// Private methods
 
-				// Use a custom preview page
-				if (previewPage) {
-					var template = new Array();
+		_preview : function() {
+			var ed = this.editor, win, html, c, pos, pos2, css, i, page = ed.getParam("plugin_preview_pageurl", null), w = ed.getParam("plugin_preview_width", "550"), h = ed.getParam("plugin_preview_height", "600");
 
-					template['file'] = previewPage;
-					template['width'] = previewWidth;
-					template['height'] = previewHeight;
-
-					tinyMCE.openWindow(template, {editor_id : editor_id, resizable : "yes", scrollbars : "yes", inline : "yes", content : tinyMCE.getContent(), content_css : tinyMCE.getParam("content_css")});
-				} else {
-					var win = window.open("", "mcePreview", "menubar=no,toolbar=no,scrollbars=yes,resizable=yes,left=20,top=20,width=" + previewWidth + ",height="  + previewHeight);
-					var html = "", i;
-					var c = tinyMCE.getContent();
-					var pos = c.indexOf('<body'), pos2, css = tinyMCE.getParam("content_css").split(',');
-
-					if (pos != -1) {
-						pos = c.indexOf('>', pos);
-						pos2 = c.lastIndexOf('</body>');
-						c = c.substring(pos + 1, pos2);
-					}
+			// Use a custom preview page
+			if (page) {
+				ed.windowManager.open({
+					file : ed.getParam("plugin_preview_pageurl", null),
+					width : w,
+					height : h
+				}, {
+					resizable : "yes",
+					scrollbars : "yes",
+					inline : 1
+				});
+			} else {
+				win = window.open("", "mcePreview", "menubar=no,toolbar=no,scrollbars=yes,resizable=yes,left=20,top=20,width=" + w + ",height="  + h);
+				html = "";
+				c = ed.getContent();
+				pos = c.indexOf('<body');
+				css = ed.getParam("content_css", '').split(',');
 
-					html += tinyMCE.getParam('doctype');
-					html += '<html xmlns="http://www.w3.org/1999/xhtml">';
-					html += '<head>';
-					html += '<title>' + tinyMCE.getLang('lang_preview_desc') + '</title>';
-					html += '<base href="' + tinyMCE.settings['base_href'] + '" />';
-					html += '<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />';
-
-					for (i=0; i<css.length; i++)
-						html += '<link href="' + css[i] + '" rel="stylesheet" type="text/css" />';
+				tinymce.map(css, function(u) {
+					return ed.documentBaseURI.toAbsolute(u);
+				});
 
-					html += '<script type="text/javascript">';
-					html += 'window.opener.TinyMCE_PreviewPlugin._setDoc(document);';
-					html += 'window.opener.TinyMCE_PreviewPlugin._setWin(window);';
-					html += 'writeFlash = window.opener.TinyMCE_PreviewPlugin._writeFlash;';
-					html += 'writeShockWave = window.opener.TinyMCE_PreviewPlugin._writeShockWave;';
-					html += 'writeQuickTime = window.opener.TinyMCE_PreviewPlugin._writeQuickTime;';
-					html += 'writeRealMedia = window.opener.TinyMCE_PreviewPlugin._writeRealMedia;';
-					html += 'writeWindowsMedia = window.opener.TinyMCE_PreviewPlugin._writeWindowsMedia;';
-					html += 'writeEmbed = window.opener.TinyMCE_PreviewPlugin._writeEmbed;';
-					html += '</script>';
-					html += '</head>';
-					html += '<body dir="' + tinyMCE.getParam("directionality") + '" onload="window.opener.TinyMCE_PreviewPlugin._onLoad();">';
-					html += c;
-					html += '</body>';
-					html += '</html>';
-
-					win.document.write(html);
-					win.document.close();
+				if (pos != -1) {
+					pos = c.indexOf('>', pos);
+					pos2 = c.lastIndexOf('</body>');
+					c = c.substring(pos + 1, pos2);
 				}
 
-				return true;
-		}
+				html += ed.getParam('doctype');
+				html += '<html xmlns="http://www.w3.org/1999/xhtml">';
+				html += '<head>';
+				html += '<title>' + ed.getLang('preview.preview_desc') + '</title>';
+				html += '<base href="' + ed.documentBaseURI.getURI() + '" />';
+				html += '<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />';
 
-		return false;
-	},
-
-	_setDoc : function(d) {
-		TinyMCE_PreviewPlugin._doc = d;
-		d._embeds = new Array();
-	},
+				for (i=0; i<css.length; i++)
+					html += '<link href="' + css[i] + '" rel="stylesheet" type="text/css" />';
 
-	_setWin : function(d) {
-		TinyMCE_PreviewPlugin._win = d;
-	},
-
-	_onLoad : function() {
-		var nl, i, el = new Array(), d = TinyMCE_PreviewPlugin._doc, sv, ne;
+				html += '</head>';
+				html += '<body dir="' + ed.getParam("directionality") + '" onload="window.opener.tinymce.EditorManager.get(\'' + ed.id + '\').plugins[\'preview\']._onLoad(window,document);">';
+				html += c;
+				html += '</body>';
+				html += '</html>';
 
-		nl = d.getElementsByTagName("script");
-		for (i=0; i<nl.length; i++) {
-			sv = tinyMCE.isMSIE ? nl[i].innerHTML : nl[i].firstChild.nodeValue;
+				win.document.write(html);
+				win.document.close();
+			}
+		},
 
-			if (new RegExp('write(Flash|ShockWave|WindowsMedia|QuickTime|RealMedia)\\(.*', 'g').test(sv))
-				el[el.length] = nl[i];
-		}
+		_onLoad : function(w, d) {
+			var t = this, nl, i, el = [], sv, ne;
 
-		for (i=0; i<el.length; i++) {
-			ne = d.createElement("div");
-			ne.innerHTML = d._embeds[i];
-			el[i].parentNode.insertBefore(ne.firstChild, el[i]);
-		}
-	},
+			t._doc = d;
+			w.writeFlash = t._writeFlash;
+			w.writeShockWave = t._writeShockWave;
+			w.writeQuickTime = t._writeQuickTime;
+			w.writeRealMedia = t._writeRealMedia;
+			w.writeWindowsMedia = t._writeWindowsMedia;
+			w.writeEmbed = t._writeEmbed;
+
+			nl = d.getElementsByTagName("script");
+			for (i=0; i<nl.length; i++) {
+				sv = tinymce.isIE ? nl[i].innerHTML : nl[i].firstChild.nodeValue;
+
+				if (new RegExp('write(Flash|ShockWave|WindowsMedia|QuickTime|RealMedia)\\(.*', 'g').test(sv))
+					el[el.length] = nl[i];
+			}
 
-	_writeFlash : function(p) {
-		p.src = tinyMCE.convertRelativeToAbsoluteURL(tinyMCE.settings['base_href'], p.src);
-		TinyMCE_PreviewPlugin._writeEmbed(
-			'D27CDB6E-AE6D-11cf-96B8-444553540000',
-			'http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,40,0',
-			'application/x-shockwave-flash',
-			p
-		);
-	},
+			for (i=0; i<el.length; i++) {
+				ne = d.createElement("div");
+				ne.innerHTML = d._embeds[i];
+				el[i].parentNode.insertBefore(ne.firstChild, el[i]);
+			}
+		},
 
-	_writeShockWave : function(p) {
-		p.src = tinyMCE.convertRelativeToAbsoluteURL(tinyMCE.settings['base_href'], p.src);
-		TinyMCE_PreviewPlugin._writeEmbed(
-			'166B1BCA-3F9C-11CF-8075-444553540000',
-			'http://download.macromedia.com/pub/shockwave/cabs/director/sw.cab#version=8,5,1,0',
-			'application/x-director',
-			p
-		);
-	},
+		_writeFlash : function(p) {
+			p.src = this.editor.documentBaseURI.toAbsolute(p.src);
+			TinyMCE_PreviewPlugin._writeEmbed(
+				'D27CDB6E-AE6D-11cf-96B8-444553540000',
+				'http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,40,0',
+				'application/x-shockwave-flash',
+				p
+			);
+		},
 
-	_writeQuickTime : function(p) {
-		p.src = tinyMCE.convertRelativeToAbsoluteURL(tinyMCE.settings['base_href'], p.src);
-		TinyMCE_PreviewPlugin._writeEmbed(
-			'02BF25D5-8C17-4B23-BC80-D3488ABDDC6B',
-			'http://www.apple.com/qtactivex/qtplugin.cab#version=6,0,2,0',
-			'video/quicktime',
-			p
-		);
-	},
+		_writeShockWave : function(p) {
+			this.editor.documentBaseURI.toAbsolute(p.src);
+			TinyMCE_PreviewPlugin._writeEmbed(
+				'166B1BCA-3F9C-11CF-8075-444553540000',
+				'http://download.macromedia.com/pub/shockwave/cabs/director/sw.cab#version=8,5,1,0',
+				'application/x-director',
+				p
+			);
+		},
 
-	_writeRealMedia : function(p) {
-		p.src = tinyMCE.convertRelativeToAbsoluteURL(tinyMCE.settings['base_href'], p.src);
-		TinyMCE_PreviewPlugin._writeEmbed(
-			'CFCDAA03-8BE4-11cf-B84B-0020AFBBCCFA',
-			'http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,40,0',
-			'audio/x-pn-realaudio-plugin',
-			p
-		);
-	},
+		_writeQuickTime : function(p) {
+			this.editor.documentBaseURI.toAbsolute(p.src);
+			TinyMCE_PreviewPlugin._writeEmbed(
+				'02BF25D5-8C17-4B23-BC80-D3488ABDDC6B',
+				'http://www.apple.com/qtactivex/qtplugin.cab#version=6,0,2,0',
+				'video/quicktime',
+				p
+			);
+		},
+
+		_writeRealMedia : function(p) {
+			this.editor.documentBaseURI.toAbsolute(p.src);
+			TinyMCE_PreviewPlugin._writeEmbed(
+				'CFCDAA03-8BE4-11cf-B84B-0020AFBBCCFA',
+				'http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,40,0',
+				'audio/x-pn-realaudio-plugin',
+				p
+			);
+		},
 
-	_writeWindowsMedia : function(p) {
-		p.src = tinyMCE.convertRelativeToAbsoluteURL(tinyMCE.settings['base_href'], p.src);
-		p.url = p.src;
-		TinyMCE_PreviewPlugin._writeEmbed(
-			'6BF52A52-394A-11D3-B153-00C04F79FAA6',
-			'http://activex.microsoft.com/activex/controls/mplayer/en/nsmp2inf.cab#Version=5,1,52,701',
-			'application/x-mplayer2',
-			p
-		);
-	},
+		_writeWindowsMedia : function(p) {
+			this.editor.documentBaseURI.toAbsolute(p.src);
+			p.url = p.src;
+			TinyMCE_PreviewPlugin._writeEmbed(
+				'6BF52A52-394A-11D3-B153-00C04F79FAA6',
+				'http://activex.microsoft.com/activex/controls/mplayer/en/nsmp2inf.cab#Version=5,1,52,701',
+				'application/x-mplayer2',
+				p
+			);
+		},
 
-	_writeEmbed : function(cls, cb, mt, p) {
-		var h = '', n, d = TinyMCE_PreviewPlugin._doc, ne, c;
+		_writeEmbed : function(cls, cb, mt, p) {
+			var h = '', n, d = t._doc, ne, c;
 
-		h += '<object classid="clsid:' + cls + '" codebase="' + cb + '"';
-		h += typeof(p.id) != "undefined" ? 'id="' + p.id + '"' : '';
-		h += typeof(p.name) != "undefined" ? 'name="' + p.name + '"' : '';
-		h += typeof(p.width) != "undefined" ? 'width="' + p.width + '"' : '';
-		h += typeof(p.height) != "undefined" ? 'height="' + p.height + '"' : '';
-		h += typeof(p.align) != "undefined" ? 'align="' + p.align + '"' : '';
-		h += '>';
+			h += '<object classid="clsid:' + cls + '" codebase="' + cb + '"';
+			h += typeof(p.id) != "undefined" ? 'id="' + p.id + '"' : '';
+			h += typeof(p.name) != "undefined" ? 'name="' + p.name + '"' : '';
+			h += typeof(p.width) != "undefined" ? 'width="' + p.width + '"' : '';
+			h += typeof(p.height) != "undefined" ? 'height="' + p.height + '"' : '';
+			h += typeof(p.align) != "undefined" ? 'align="' + p.align + '"' : '';
+			h += '>';
 
-		for (n in p)
-			h += '<param name="' + n + '" value="' + p[n] + '">';
+			for (n in p)
+				h += '<param name="' + n + '" value="' + p[n] + '">';
+
+			h += '<embed type="' + mt + '"';
 
-		h += '<embed type="' + mt + '"';
+			for (n in p)
+				h += n + '="' + p[n] + '" ';
 
-		for (n in p)
-			h += n + '="' + p[n] + '" ';
+			h += '></embed></object>';
 
-		h += '></embed></object>';
+			d._embeds[d._embeds.length] = h;
+		}
+	});
 
-		d._embeds[d._embeds.length] = h;
-	}
-};
-
-tinyMCE.addPlugin("preview", TinyMCE_PreviewPlugin);
+	// Register plugin
+	tinymce.PluginManager.add('preview', tinymce.plugins.Preview);
+})();
\ No newline at end of file
--- a/includes/clientside/tinymce/plugins/preview/example.html	Fri Feb 22 12:46:51 2008 -0500
+++ b/includes/clientside/tinymce/plugins/preview/example.html	Fri Feb 22 12:51:53 2008 -0500
@@ -2,13 +2,27 @@
 <head>
 <script language="javascript" src="../../tiny_mce_popup.js"></script>
 <script type="text/javascript" src="jscripts/embed.js"></script>
+<script type="text/javascript">
+tinyMCEPopup.onInit.add(function(ed) {
+	var dom = tinyMCEPopup.dom;
+
+	// Load editor content_css
+	tinymce.each(ed.settings.content_css.split(','), function(u) {
+		dom.loadCSS(ed.documentBaseURI.toAbsolute(u));
+	});
+
+	// Place contents inside div container
+	dom.setHTML('content', ed.getContent());
+});
+</script>
 <title>Example of a custom preview page</title>
-<link href="{$content_css}" rel="stylesheet" type="text/css" />
 </head>
 <body>
 
 Editor contents: <br />
-{$content}
+<div id="content">
+<!-- Gets filled with editor contents -->
+</div>
 
 </body>
 </html>
Binary file includes/clientside/tinymce/plugins/preview/images/preview.gif has changed
--- a/includes/clientside/tinymce/plugins/preview/langs/en.js	Fri Feb 22 12:46:51 2008 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,5 +0,0 @@
-// UK lang variables
-
-tinyMCE.addToLang('',{
-preview_desc : 'Preview'
-});
--- a/includes/clientside/tinymce/plugins/preview/readme.txt	Fri Feb 22 12:46:51 2008 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1 +0,0 @@
-Check the TinyMCE documentation for details on this plugin.
--- a/includes/clientside/tinymce/plugins/print/editor_plugin.js	Fri Feb 22 12:46:51 2008 -0500
+++ b/includes/clientside/tinymce/plugins/print/editor_plugin.js	Fri Feb 22 12:51:53 2008 -0500
@@ -1,1 +1,1 @@
-tinyMCE.importPluginLanguagePack('print');var TinyMCE_PrintPlugin={getInfo:function(){return{longname:'Print',author:'Moxiecode Systems AB',authorurl:'http://tinymce.moxiecode.com',infourl:'http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/print',version:tinyMCE.majorVersion+"."+tinyMCE.minorVersion}},getControlHTML:function(cn){switch(cn){case"print":return tinyMCE.getButtonHTML(cn,'lang_print_desc','{$pluginurl}/images/print.gif','mcePrint')}return""},execCommand:function(editor_id,element,command,user_interface,value){switch(command){case"mcePrint":tinyMCE.getInstanceById(editor_id).contentWindow.print();return true}return false}};tinyMCE.addPlugin("print",TinyMCE_PrintPlugin);
\ No newline at end of file
+(function(){tinymce.create('tinymce.plugins.Print',{init:function(ed,url){ed.addCommand('mcePrint',function(){ed.getWin().print();});ed.addButton('print',{title:'print.print_desc',cmd:'mcePrint'});},getInfo:function(){return{longname:'Print',author:'Moxiecode Systems AB',authorurl:'http://tinymce.moxiecode.com',infourl:'http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/print',version:tinymce.majorVersion+"."+tinymce.minorVersion};}});tinymce.PluginManager.add('print',tinymce.plugins.Print);})();
\ No newline at end of file
--- a/includes/clientside/tinymce/plugins/print/editor_plugin_src.js	Fri Feb 22 12:46:51 2008 -0500
+++ b/includes/clientside/tinymce/plugins/print/editor_plugin_src.js	Fri Feb 22 12:51:53 2008 -0500
@@ -1,47 +1,31 @@
 /**
- * $Id: editor_plugin_src.js 201 2007-02-12 15:56:56Z spocke $
+ * $Id: editor_plugin_src.js 520 2008-01-07 16:30:32Z spocke $
  *
  * @author Moxiecode
- * @copyright Copyright © 2004-2007, Moxiecode Systems AB, All rights reserved.
+ * @copyright Copyright © 2004-2008, Moxiecode Systems AB, All rights reserved.
  */
 
-/* Import theme	specific language pack */
-tinyMCE.importPluginLanguagePack('print');
+(function() {
+	tinymce.create('tinymce.plugins.Print', {
+		init : function(ed, url) {
+			ed.addCommand('mcePrint', function() {
+				ed.getWin().print();
+			});
 
-var TinyMCE_PrintPlugin = {
-	getInfo : function() {
-		return {
-			longname : 'Print',
-			author : 'Moxiecode Systems AB',
-			authorurl : 'http://tinymce.moxiecode.com',
-			infourl : 'http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/print',
-			version : tinyMCE.majorVersion + "." + tinyMCE.minorVersion
-		};
-	},
-
-	getControlHTML : function(cn)	{
-		switch (cn) {
-			case "print":
-				return tinyMCE.getButtonHTML(cn, 'lang_print_desc', '{$pluginurl}/images/print.gif', 'mcePrint');
-		}
+			ed.addButton('print', {title : 'print.print_desc', cmd : 'mcePrint'});
+		},
 
-		return "";
-	},
+		getInfo : function() {
+			return {
+				longname : 'Print',
+				author : 'Moxiecode Systems AB',
+				authorurl : 'http://tinymce.moxiecode.com',
+				infourl : 'http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/print',
+				version : tinymce.majorVersion + "." + tinymce.minorVersion
+			};
+		}
+	});
 
-	/**
-	 * Executes	the	search/replace commands.
-	 */
-	execCommand : function(editor_id, element, command,	user_interface,	value) {
-		// Handle commands
-		switch (command) {
-			case "mcePrint":
-				tinyMCE.getInstanceById(editor_id).contentWindow.print();
-				return true;
-		}
-
-		// Pass to next handler in chain
-		return false;
-	}
-};
-
-tinyMCE.addPlugin("print", TinyMCE_PrintPlugin);
+	// Register plugin
+	tinymce.PluginManager.add('print', tinymce.plugins.Print);
+})();
Binary file includes/clientside/tinymce/plugins/print/images/print.gif has changed
--- a/includes/clientside/tinymce/plugins/print/langs/en.js	Fri Feb 22 12:46:51 2008 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,5 +0,0 @@
-// UK lang variables
-
-tinyMCE.addToLang('',{
-print_desc : 'Print'
-});
--- a/includes/clientside/tinymce/plugins/print/readme.txt	Fri Feb 22 12:46:51 2008 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1 +0,0 @@
-Check the TinyMCE documentation for details on this plugin.
--- a/includes/clientside/tinymce/plugins/readme.txt	Fri Feb 22 12:46:51 2008 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1 +0,0 @@
-This is the location you place TinyMCE plugins.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/includes/clientside/tinymce/plugins/safari/blank.htm	Fri Feb 22 12:51:53 2008 -0500
@@ -0,0 +1,1 @@
+<!-- WebKit -->
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/includes/clientside/tinymce/plugins/safari/editor_plugin.js	Fri Feb 22 12:51:53 2008 -0500
@@ -0,0 +1,1 @@
+(function(){var Event=tinymce.dom.Event,grep=tinymce.grep,each=tinymce.each,inArray=tinymce.inArray,isOldWebKit=tinymce.isOldWebKit;tinymce.create('tinymce.plugins.Safari',{init:function(ed){var t=this,dom;if(!tinymce.isWebKit)return;t.editor=ed;t.webKitFontSizes=['x-small','small','medium','large','x-large','xx-large','-webkit-xxx-large'];t.namedFontSizes=['xx-small','x-small','small','medium','large','x-large','xx-large'];ed.addCommand('FormatBlock',function(u,v){var dom=ed.dom,e=dom.getParent(ed.selection.getNode(),dom.isBlock);if(e)dom.replace(dom.create(v),e,1);else ed.getDoc().execCommand("FormatBlock",false,v);});ed.addCommand('mceInsertContent',function(u,v){ed.getDoc().execCommand("InsertText",false,'mce_marker');ed.getBody().innerHTML=ed.getBody().innerHTML.replace(/mce_marker/g,v+'<span id="_mce_tmp">XX</span>');ed.selection.select(ed.dom.get('_mce_tmp'));ed.getDoc().execCommand("Delete",false,' ');});ed.onKeyPress.add(function(ed,e){if(e.keyCode==13&&e.shiftKey){t._insertBR(ed);Event.cancel(e);}});ed.addQueryValueHandler('FontSize',function(u,v){var e,v;if((e=ed.dom.getParent(ed.selection.getStart(),'span'))&&(v=e.style.fontSize))return tinymce.inArray(t.namedFontSizes,v)+1;if((e=ed.dom.getParent(ed.selection.getEnd(),'span'))&&(v=e.style.fontSize))return tinymce.inArray(t.namedFontSizes,v)+1;return ed.getDoc().queryCommandValue('FontSize');});ed.addQueryValueHandler('FontName',function(u,v){var e,v;if((e=ed.dom.getParent(ed.selection.getStart(),'span'))&&(v=e.style.fontFamily))return v.replace(/, /g,',');if((e=ed.dom.getParent(ed.selection.getEnd(),'span'))&&(v=e.style.fontFamily))return v.replace(/, /g,',');return ed.getDoc().queryCommandValue('FontName');});ed.onClick.add(function(ed,e){e=e.target;if(e.nodeName=='IMG'){t.selElm=e;ed.selection.select(e);}else t.selElm=null;});ed.onBeforeExecCommand.add(function(ed,c,b){var r=t.bookmarkRng;if(r){ed.selection.setRng(r);t.bookmarkRng=null;}});ed.onInit.add(function(){t._fixWebKitSpans();ed.windowManager.onOpen.add(function(){var r=ed.selection.getRng();if(r.startContainer!=ed.getDoc()){t.bookmarkRng=r.cloneRange();}});ed.windowManager.onClose.add(function(){t.bookmarkRng=null;});if(isOldWebKit)t._patchSafari2x(ed);});ed.onSetContent.add(function(){dom=ed.dom;each(['strong','b','em','u','strike','sub','sup','a'],function(v){each(grep(dom.select(v)).reverse(),function(n){var nn=n.nodeName.toLowerCase(),st;if(nn=='a'){if(n.name)dom.replace(dom.create('img',{mce_name:'a',name:n.name,'class':'mceItemAnchor'}),n);return;}switch(nn){case'b':case'strong':if(nn=='b')nn='strong';st='font-weight: bold;';break;case'em':st='font-style: italic;';break;case'u':st='text-decoration: underline;';break;case'sub':st='vertical-align: sub;';break;case'sup':st='vertical-align: super;';break;case'strike':st='text-decoration: line-through;';break;}dom.replace(dom.create('span',{mce_name:nn,style:st,'class':'Apple-style-span'}),n,1);});});});ed.onPreProcess.add(function(ed,o){dom=ed.dom;each(grep(o.node.getElementsByTagName('span')).reverse(),function(n){var v,bg;if(o.get){if(dom.hasClass(n,'Apple-style-span')){bg=n.style.backgroundColor;switch(dom.getAttrib(n,'mce_name')){case'font':if(!ed.settings.convert_fonts_to_spans)dom.setAttrib(n,'style','');break;case'strong':case'em':case'sub':case'sup':dom.setAttrib(n,'style','');break;case'strike':case'u':if(!ed.settings.inline_styles)dom.setAttrib(n,'style','');else dom.setAttrib(n,'mce_name','');break;default:if(!ed.settings.inline_styles)dom.setAttrib(n,'style','');}if(bg)n.style.backgroundColor=bg;}}if(dom.hasClass(n,'mceItemRemoved'))dom.remove(n,1);});});ed.onPostProcess.add(function(ed,o){o.content=o.content.replace(/<br \/><\/(h[1-6]|div|p|address|pre)>/g,'</$1>');o.content=o.content.replace(/ id=\"undefined\"/g,'');});},_fixWebKitSpans:function(){var t=this,ed=t.editor;if(!isOldWebKit){Event.add(ed.getDoc(),'DOMNodeInserted',function(e){e=e.target;if(e&&e.nodeType==1)t._fixAppleSpan(e);});}else{ed.onExecCommand.add(function(){each(ed.dom.select('span'),function(n){t._fixAppleSpan(n);});ed.nodeChanged();});}},_fixAppleSpan:function(e){var ed=this.editor,dom=ed.dom,fz=this.webKitFontSizes,fzn=this.namedFontSizes,s=ed.settings,st,p;if(dom.getAttrib(e,'mce_fixed'))return;if(e.nodeName=='SPAN'&&e.className=='Apple-style-span'){st=e.style;if(!s.convert_fonts_to_spans){if(st.fontSize){dom.setAttrib(e,'mce_name','font');dom.setAttrib(e,'size',inArray(fz,st.fontSize)+1);}if(st.fontFamily){dom.setAttrib(e,'mce_name','font');dom.setAttrib(e,'face',st.fontFamily);}if(st.color){dom.setAttrib(e,'mce_name','font');dom.setAttrib(e,'color',dom.toHex(st.color));}if(st.backgroundColor){dom.setAttrib(e,'mce_name','font');dom.setStyle(e,'background-color',st.backgroundColor);}}else{if(st.fontSize)dom.setStyle(e,'fontSize',fzn[inArray(fz,st.fontSize)]);}if(st.fontWeight=='bold')dom.setAttrib(e,'mce_name','strong');if(st.fontStyle=='italic')dom.setAttrib(e,'mce_name','em');if(st.textDecoration=='underline')dom.setAttrib(e,'mce_name','u');if(st.textDecoration=='line-through')dom.setAttrib(e,'mce_name','strike');if(st.verticalAlign=='super')dom.setAttrib(e,'mce_name','sup');if(st.verticalAlign=='sub')dom.setAttrib(e,'mce_name','sub');dom.setAttrib(e,'mce_fixed','1');}},_patchSafari2x:function(ed){var t=this,setContent,getNode,dom=ed.dom,lr;if(ed.windowManager.onBeforeOpen){ed.windowManager.onBeforeOpen.add(function(){r=ed.selection.getRng();});}ed.selection.select=function(n){this.getSel().setBaseAndExtent(n,0,n,1);};getNode=ed.selection.getNode;ed.selection.getNode=function(){return t.selElm||getNode.call(this);};ed.selection.getRng=function(){var t=this,s=t.getSel(),d=ed.getDoc(),r,rb,ra,di;if(s.anchorNode){r=d.createRange();try{rb=d.createRange();rb.setStart(s.anchorNode,s.anchorOffset);rb.collapse(1);ra=d.createRange();ra.setStart(s.focusNode,s.focusOffset);ra.collapse(1);di=rb.compareBoundaryPoints(rb.START_TO_END,ra)<0;r.setStart(di?s.anchorNode:s.focusNode,di?s.anchorOffset:s.focusOffset);r.setEnd(di?s.focusNode:s.anchorNode,di?s.focusOffset:s.anchorOffset);lr=r;}catch(ex){}}return r||lr;};setContent=ed.selection.setContent;ed.selection.setContent=function(h,s){var r=this.getRng(),b;try{setContent.call(this,h,s);}catch(ex){b=dom.create('body');b.innerHTML=h;each(b.childNodes,function(n){r.insertNode(n.cloneNode(true));});}};},_insertBR:function(ed){var dom=ed.dom,s=ed.selection,r=s.getRng(),br;r.insertNode(br=dom.create('br'));r.setStartAfter(br);r.setEndAfter(br);s.setRng(r);if(s.getSel().focusNode==br.previousSibling){s.select(dom.insertAfter(dom.doc.createTextNode('\u00a0'),br));s.collapse(1);}ed.getWin().scrollTo(0,dom.getPos(s.getRng().startContainer).y);}});tinymce.PluginManager.add('safari',tinymce.plugins.Safari);})();
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/includes/clientside/tinymce/plugins/safari/editor_plugin_src.js	Fri Feb 22 12:51:53 2008 -0500
@@ -0,0 +1,414 @@
+/**
+ * $Id: editor_plugin_src.js 264 2007-04-26 20:53:09Z spocke $
+ *
+ * @author Moxiecode
+ * @copyright Copyright © 2004-2008, Moxiecode Systems AB, All rights reserved.
+ */
+
+(function() {
+	var Event = tinymce.dom.Event, grep = tinymce.grep, each = tinymce.each, inArray = tinymce.inArray, isOldWebKit = tinymce.isOldWebKit;
+
+	tinymce.create('tinymce.plugins.Safari', {
+		init : function(ed) {
+			var t = this, dom;
+
+			// Ignore on non webkit
+			if (!tinymce.isWebKit)
+				return;
+
+			t.editor = ed;
+			t.webKitFontSizes = ['x-small', 'small', 'medium', 'large', 'x-large', 'xx-large', '-webkit-xxx-large'];
+			t.namedFontSizes = ['xx-small', 'x-small','small','medium','large','x-large', 'xx-large'];
+
+			// Safari will crash if the build in createlink command is used
+/*			ed.addCommand('CreateLink', function(u, v) {
+				ed.execCommand("mceInsertContent", false, '<a href="' + dom.encode(v) + '">' + ed.selection.getContent() + '</a>');
+			});*/
+
+			// Workaround for FormatBlock bug, http://bugs.webkit.org/show_bug.cgi?id=16004
+			ed.addCommand('FormatBlock', function(u, v) {
+				var dom = ed.dom, e = dom.getParent(ed.selection.getNode(), dom.isBlock);
+
+				if (e)
+					dom.replace(dom.create(v), e, 1);
+				else
+					ed.getDoc().execCommand("FormatBlock", false, v);
+			});
+
+			// Workaround for InsertHTML bug, http://bugs.webkit.org/show_bug.cgi?id=16382
+			ed.addCommand('mceInsertContent', function(u, v) {
+				ed.getDoc().execCommand("InsertText", false, 'mce_marker');
+				ed.getBody().innerHTML = ed.getBody().innerHTML.replace(/mce_marker/g, v + '<span id="_mce_tmp">XX</span>');
+				ed.selection.select(ed.dom.get('_mce_tmp'));
+				ed.getDoc().execCommand("Delete", false, ' ');
+			});
+
+			// Workaround for missing shift+enter support, http://bugs.webkit.org/show_bug.cgi?id=16973
+			ed.onKeyPress.add(function(ed, e) {
+				if (e.keyCode == 13 && e.shiftKey) {
+					t._insertBR(ed);
+					Event.cancel(e);
+				}
+			});
+
+			// Safari returns incorrect values
+			ed.addQueryValueHandler('FontSize', function(u, v) {
+				var e, v;
+
+				// Check for the real font size at the start of selection
+				if ((e = ed.dom.getParent(ed.selection.getStart(), 'span')) && (v = e.style.fontSize))
+					return tinymce.inArray(t.namedFontSizes, v) + 1;
+
+				// Check for the real font size at the end of selection
+				if ((e = ed.dom.getParent(ed.selection.getEnd(), 'span')) && (v = e.style.fontSize))
+					return tinymce.inArray(t.namedFontSizes, v) + 1;
+
+				// Return default value it's better than nothing right!
+				return ed.getDoc().queryCommandValue('FontSize');
+			});
+
+			// Safari returns incorrect values
+			ed.addQueryValueHandler('FontName', function(u, v) {
+				var e, v;
+
+				// Check for the real font name at the start of selection
+				if ((e = ed.dom.getParent(ed.selection.getStart(), 'span')) && (v = e.style.fontFamily))
+					return v.replace(/, /g, ',');
+
+				// Check for the real font name at the end of selection
+				if ((e = ed.dom.getParent(ed.selection.getEnd(), 'span')) && (v = e.style.fontFamily))
+					return v.replace(/, /g, ',');
+
+				// Return default value it's better than nothing right!
+				return ed.getDoc().queryCommandValue('FontName');
+			});
+
+			// Workaround for bug, http://bugs.webkit.org/show_bug.cgi?id=12250
+			ed.onClick.add(function(ed, e) {
+				e = e.target;
+
+				if (e.nodeName == 'IMG') {
+					t.selElm = e;
+					ed.selection.select(e);
+				} else
+					t.selElm = null;
+			});
+
+			ed.onBeforeExecCommand.add(function(ed, c, b) {
+				var r = t.bookmarkRng;
+
+				// Restore selection
+				if (r) {
+					ed.selection.setRng(r);
+					t.bookmarkRng = null;
+					//console.debug('restore', r.startContainer, r.startOffset, r.endContainer, r.endOffset);
+				}
+			});
+
+			ed.onInit.add(function() {
+				t._fixWebKitSpans();
+
+				ed.windowManager.onOpen.add(function() {
+					var r = ed.selection.getRng();
+
+					// Store selection if valid
+					if (r.startContainer != ed.getDoc()) {
+						t.bookmarkRng = r.cloneRange();
+						//console.debug('store', r.startContainer, r.startOffset, r.endContainer, r.endOffset);
+					}
+				});
+
+				ed.windowManager.onClose.add(function() {
+					t.bookmarkRng = null;
+				});
+
+				if (isOldWebKit)
+					t._patchSafari2x(ed);
+			});
+
+			ed.onSetContent.add(function() {
+				dom = ed.dom;
+
+				// Convert strong,b,em,u,strike to spans
+				each(['strong','b','em','u','strike','sub','sup','a'], function(v) {
+					each(grep(dom.select(v)).reverse(), function(n) {
+						var nn = n.nodeName.toLowerCase(), st;
+
+						// Convert anchors into images
+						if (nn == 'a') {
+							if (n.name)
+								dom.replace(dom.create('img', {mce_name : 'a', name : n.name, 'class' : 'mceItemAnchor'}), n);
+
+							return;
+						}
+
+						switch (nn) {
+							case 'b':
+							case 'strong':
+								if (nn == 'b')
+									nn = 'strong';
+
+								st = 'font-weight: bold;';
+								break;
+
+							case 'em':
+								st = 'font-style: italic;';
+								break;
+
+							case 'u':
+								st = 'text-decoration: underline;';
+								break;
+
+							case 'sub':
+								st = 'vertical-align: sub;';
+								break;
+
+							case 'sup':
+								st = 'vertical-align: super;';
+								break;
+
+							case 'strike':
+								st = 'text-decoration: line-through;';
+								break;
+						}
+
+						dom.replace(dom.create('span', {mce_name : nn, style : st, 'class' : 'Apple-style-span'}), n, 1);
+					});
+				});
+			});
+
+			ed.onPreProcess.add(function(ed, o) {
+				dom = ed.dom;
+
+				each(grep(o.node.getElementsByTagName('span')).reverse(), function(n) {
+					var v, bg;
+
+					if (o.get) {
+						if (dom.hasClass(n, 'Apple-style-span')) {
+							bg = n.style.backgroundColor;
+
+							switch (dom.getAttrib(n, 'mce_name')) {
+								case 'font':
+									if (!ed.settings.convert_fonts_to_spans)
+										dom.setAttrib(n, 'style', '');
+									break;
+
+								case 'strong':
+								case 'em':
+								case 'sub':
+								case 'sup':
+									dom.setAttrib(n, 'style', '');
+									break;
+
+								case 'strike':
+								case 'u':
+									if (!ed.settings.inline_styles)
+										dom.setAttrib(n, 'style', '');
+									else
+										dom.setAttrib(n, 'mce_name', '');
+
+									break;
+
+								default:
+									if (!ed.settings.inline_styles)
+										dom.setAttrib(n, 'style', '');
+							}
+
+
+							if (bg)
+								n.style.backgroundColor = bg;
+						}
+					}
+
+					if (dom.hasClass(n, 'mceItemRemoved'))
+						dom.remove(n, 1);
+				});
+			});
+
+			ed.onPostProcess.add(function(ed, o) {
+				// Safari adds BR at end of all block elements
+				o.content = o.content.replace(/<br \/><\/(h[1-6]|div|p|address|pre)>/g, '</$1>');
+
+				// Safari adds id="undefined" to HR elements
+				o.content = o.content.replace(/ id=\"undefined\"/g, '');
+			});
+		},
+
+		_fixWebKitSpans : function() {
+			var t = this, ed = t.editor;
+
+			if (!isOldWebKit) {
+				// Use mutator events on new WebKit
+				Event.add(ed.getDoc(), 'DOMNodeInserted', function(e) {
+					e = e.target;
+
+					if (e && e.nodeType == 1)
+						t._fixAppleSpan(e);
+				});
+			} else {
+				// Do post command processing in old WebKit since the browser crashes on Mutator events :(
+				ed.onExecCommand.add(function() {
+					each(ed.dom.select('span'), function(n) {
+						t._fixAppleSpan(n);
+					});
+
+					ed.nodeChanged();
+				});
+			}
+		},
+
+		_fixAppleSpan : function(e) {
+			var ed = this.editor, dom = ed.dom, fz = this.webKitFontSizes, fzn = this.namedFontSizes, s = ed.settings, st, p;
+
+			if (dom.getAttrib(e, 'mce_fixed'))
+				return;
+
+			// Handle Apple style spans
+			if (e.nodeName == 'SPAN' && e.className == 'Apple-style-span') {
+				st = e.style;
+
+				if (!s.convert_fonts_to_spans) {
+					if (st.fontSize) {
+						dom.setAttrib(e, 'mce_name', 'font');
+						dom.setAttrib(e, 'size', inArray(fz, st.fontSize) + 1);
+					}
+
+					if (st.fontFamily) {
+						dom.setAttrib(e, 'mce_name', 'font');
+						dom.setAttrib(e, 'face', st.fontFamily);
+					}
+
+					if (st.color) {
+						dom.setAttrib(e, 'mce_name', 'font');
+						dom.setAttrib(e, 'color', dom.toHex(st.color));
+					}
+
+					if (st.backgroundColor) {
+						dom.setAttrib(e, 'mce_name', 'font');
+						dom.setStyle(e, 'background-color', st.backgroundColor);
+					}
+				} else {
+					if (st.fontSize)
+						dom.setStyle(e, 'fontSize', fzn[inArray(fz, st.fontSize)]);
+				}
+
+				if (st.fontWeight == 'bold')
+					dom.setAttrib(e, 'mce_name', 'strong');
+
+				if (st.fontStyle == 'italic')
+					dom.setAttrib(e, 'mce_name', 'em');
+
+				if (st.textDecoration == 'underline')
+					dom.setAttrib(e, 'mce_name', 'u');
+
+				if (st.textDecoration == 'line-through')
+					dom.setAttrib(e, 'mce_name', 'strike');
+
+				if (st.verticalAlign == 'super')
+					dom.setAttrib(e, 'mce_name', 'sup');
+
+				if (st.verticalAlign == 'sub')
+					dom.setAttrib(e, 'mce_name', 'sub');
+
+				dom.setAttrib(e, 'mce_fixed', '1');
+			}
+		},
+
+		_patchSafari2x : function(ed) {
+			var t = this, setContent, getNode, dom = ed.dom, lr;
+
+			// Inline dialogs
+			if (ed.windowManager.onBeforeOpen) {
+				ed.windowManager.onBeforeOpen.add(function() {
+					r = ed.selection.getRng();
+				});
+			}
+
+			// Fake select on 2.x
+			ed.selection.select = function(n) {
+				this.getSel().setBaseAndExtent(n, 0, n, 1);
+			};
+
+			getNode = ed.selection.getNode;
+			ed.selection.getNode = function() {
+				return t.selElm || getNode.call(this);
+			};
+
+			// Fake range on Safari 2.x
+			ed.selection.getRng = function() {
+				var t = this, s = t.getSel(), d = ed.getDoc(), r, rb, ra, di;
+
+				// Fake range on Safari 2.x
+				if (s.anchorNode) {
+					r = d.createRange();
+
+					try {
+						// Setup before range
+						rb = d.createRange();
+						rb.setStart(s.anchorNode, s.anchorOffset);
+						rb.collapse(1);
+
+						// Setup after range
+						ra = d.createRange();
+						ra.setStart(s.focusNode, s.focusOffset);
+						ra.collapse(1);
+
+						// Setup start/end points by comparing locations
+						di = rb.compareBoundaryPoints(rb.START_TO_END, ra) < 0;
+						r.setStart(di ? s.anchorNode : s.focusNode, di ? s.anchorOffset : s.focusOffset);
+						r.setEnd(di ? s.focusNode : s.anchorNode, di ? s.focusOffset : s.anchorOffset);
+
+						lr = r;
+					} catch (ex) {
+						// Sometimes fails, at least we tried to do it by the book. I hope Safari 2.x will go disappear soooon!!!
+					}
+				}
+
+				return r || lr;
+			};
+
+			// Fix setContent so it works
+			setContent = ed.selection.setContent;
+			ed.selection.setContent = function(h, s) {
+				var r = this.getRng(), b;
+
+				try {
+					setContent.call(this, h, s);
+				} catch (ex) {
+					// Workaround for Safari 2.x
+					b = dom.create('body');
+					b.innerHTML = h;
+
+					each(b.childNodes, function(n) {
+						r.insertNode(n.cloneNode(true));
+					});
+				}
+			};
+		},
+
+		_insertBR : function(ed) {
+			var dom = ed.dom, s = ed.selection, r = s.getRng(), br;
+
+			// Insert BR element
+			r.insertNode(br = dom.create('br'));
+
+			// Place caret after BR
+			r.setStartAfter(br);
+			r.setEndAfter(br);
+			s.setRng(r);
+
+			// Could not place caret after BR then insert an nbsp entity and move the caret
+			if (s.getSel().focusNode == br.previousSibling) {
+				s.select(dom.insertAfter(dom.doc.createTextNode('\u00a0'), br));
+				s.collapse(1);
+			}
+
+			// Scroll to new position, scrollIntoView can't be used due to bug: http://bugs.webkit.org/show_bug.cgi?id=16117
+			ed.getWin().scrollTo(0, dom.getPos(s.getRng().startContainer).y);
+		}
+	});
+
+	// Register plugin
+	tinymce.PluginManager.add('safari', tinymce.plugins.Safari);
+})();
+
--- a/includes/clientside/tinymce/plugins/save/editor_plugin.js	Fri Feb 22 12:46:51 2008 -0500
+++ b/includes/clientside/tinymce/plugins/save/editor_plugin.js	Fri Feb 22 12:51:53 2008 -0500
@@ -1,1 +1,1 @@
-tinyMCE.importPluginLanguagePack('save');var TinyMCE_SavePlugin={getInfo:function(){return{longname:'Save',author:'Moxiecode Systems AB',authorurl:'http://tinymce.moxiecode.com',infourl:'http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/save',version:tinyMCE.majorVersion+"."+tinyMCE.minorVersion}},initInstance:function(inst){inst.addShortcut('ctrl','s','lang_save_desc','mceSave')},getControlHTML:function(cn){switch(cn){case"save":return tinyMCE.getButtonHTML(cn,'lang_save_desc','{$pluginurl}/images/save.gif','mceSave')}return""},execCommand:function(editor_id,element,command,user_interface,value){switch(command){case"mceSave":if(tinyMCE.getParam("fullscreen_is_enabled"))return true;var inst=tinyMCE.selectedInstance;var formObj=inst.formElement.form;if(tinyMCE.getParam("save_enablewhendirty")&&!inst.isDirty())return true;if(formObj){tinyMCE.triggerSave();var os;if((os=tinyMCE.getParam("save_onsavecallback"))){if(eval(os+'(inst);')){inst.startContent=tinyMCE.trim(inst.getBody().innerHTML);tinyMCE.triggerNodeChange(false,true)}return true}for(var i=0;i<formObj.elements.length;i++){var elementId=formObj.elements[i].name?formObj.elements[i].name:formObj.elements[i].id;if(elementId.indexOf('mce_editor_')==0)formObj.elements[i].disabled=true}tinyMCE.isNotDirty=true;if(formObj.onsubmit==null||formObj.onsubmit()!=false)inst.formElement.form.submit()}else alert("Error: No form element found.");return true}return false},handleNodeChange:function(editor_id,node,undo_index,undo_levels,visual_aid,any_selection){if(tinyMCE.getParam("fullscreen_is_enabled")){tinyMCE.switchClass(editor_id+'_save','mceButtonDisabled');return true}if(tinyMCE.getParam("save_enablewhendirty")){var inst=tinyMCE.getInstanceById(editor_id);if(inst.isDirty()){tinyMCE.switchClass(editor_id+'_save','mceButtonNormal');return true}tinyMCE.switchClass(editor_id+'_save','mceButtonDisabled')}return true}};tinyMCE.addPlugin("save",TinyMCE_SavePlugin);
\ No newline at end of file
+(function(){tinymce.create('tinymce.plugins.Save',{init:function(ed,url){var t=this;t.editor=ed;ed.addCommand('mceSave',t._save,t);ed.addCommand('mceCancel',t._cancel,t);ed.addButton('save',{title:'save.save_desc',cmd:'mceSave'});ed.addButton('cancel',{title:'save.cancel_desc',cmd:'mceCancel'});ed.onNodeChange.add(t._nodeChange,t);ed.addShortcut('ctrl+s',ed.getLang('save.save_desc'),'mceSave');},getInfo:function(){return{longname:'Save',author:'Moxiecode Systems AB',authorurl:'http://tinymce.moxiecode.com',infourl:'http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/save',version:tinymce.majorVersion+"."+tinymce.minorVersion};},_nodeChange:function(ed,cm,n){var ed=this.editor;if(ed.getParam('save_enablewhendirty')){cm.setDisabled('save',!ed.isDirty());cm.setDisabled('cancel',!ed.isDirty());}},_save:function(){var ed=this.editor,formObj,os,i,elementId;if(ed.getParam("fullscreen_is_enabled"))return true;formObj=tinymce.DOM.get(ed.id).form||tinymce.DOM.getParent(ed.id,'form');if(ed.getParam("save_enablewhendirty")&&!ed.isDirty())return true;if(formObj){tinyMCE.triggerSave();if(os=ed.getParam("save_onsavecallback")){if(ed.execCallback('save_onsavecallback',ed)){ed.startContent=tinymce.trim(ed.getContent({format:'raw'}));ed.nodeChanged();}return;}ed.isNotDirty=true;if(formObj.onsubmit==null||formObj.onsubmit()!=false)formObj.submit();ed.nodeChanged();}else ed.windowManager.alert("Error: No form element found.");return true;},_cancel:function(){var ed=this.editor,os,h=tinymce.trim(ed.startContent);if(os=ed.getParam("save_oncancelcallback")){ed.execCallback('save_oncancelcallback',ed);return;}ed.setContent(h);ed.undoManager.clear();ed.nodeChanged();}});tinymce.PluginManager.add('save',tinymce.plugins.Save);})();
\ No newline at end of file
--- a/includes/clientside/tinymce/plugins/save/editor_plugin_src.js	Fri Feb 22 12:46:51 2008 -0500
+++ b/includes/clientside/tinymce/plugins/save/editor_plugin_src.js	Fri Feb 22 12:51:53 2008 -0500
@@ -1,115 +1,103 @@
 /**
- * $Id: editor_plugin_src.js 201 2007-02-12 15:56:56Z spocke $
+ * $Id: editor_plugin_src.js 531 2008-01-14 13:34:28Z spocke $
  *
  * @author Moxiecode
- * @copyright Copyright © 2004-2007, Moxiecode Systems AB, All rights reserved.
+ * @copyright Copyright © 2004-2008, Moxiecode Systems AB, All rights reserved.
  */
 
-/* Import plugin specific language pack */
-tinyMCE.importPluginLanguagePack('save');
+(function() {
+	tinymce.create('tinymce.plugins.Save', {
+		init : function(ed, url) {
+			var t = this;
+
+			t.editor = ed;
 
-var TinyMCE_SavePlugin = {
-	getInfo : function() {
-		return {
-			longname : 'Save',
-			author : 'Moxiecode Systems AB',
-			authorurl : 'http://tinymce.moxiecode.com',
-			infourl : 'http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/save',
-			version : tinyMCE.majorVersion + "." + tinyMCE.minorVersion
-		};
-	},
+			// Register commands
+			ed.addCommand('mceSave', t._save, t);
+			ed.addCommand('mceCancel', t._cancel, t);
+
+			// Register buttons
+			ed.addButton('save', {title : 'save.save_desc', cmd : 'mceSave'});
+			ed.addButton('cancel', {title : 'save.cancel_desc', cmd : 'mceCancel'});
 
-	initInstance : function(inst) {
-		inst.addShortcut('ctrl', 's', 'lang_save_desc', 'mceSave');
-	},
+			ed.onNodeChange.add(t._nodeChange, t);
+			ed.addShortcut('ctrl+s', ed.getLang('save.save_desc'), 'mceSave');
+		},
 
-	/**
-	 * Returns the HTML contents of the save control.
-	 */
-	getControlHTML : function(cn) {
-		switch (cn) {
-			case "save":
-				return tinyMCE.getButtonHTML(cn, 'lang_save_desc', '{$pluginurl}/images/save.gif', 'mceSave');
-		}
+		getInfo : function() {
+			return {
+				longname : 'Save',
+				author : 'Moxiecode Systems AB',
+				authorurl : 'http://tinymce.moxiecode.com',
+				infourl : 'http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/save',
+				version : tinymce.majorVersion + "." + tinymce.minorVersion
+			};
+		},
 
-		return "";
-	},
+		// Private methods
 
-	/**
-	 * Executes the save command.
-	 */
-	execCommand : function(editor_id, element, command, user_interface, value) {
-		// Handle commands
-		switch (command) {
-			case "mceSave":
-				if (tinyMCE.getParam("fullscreen_is_enabled"))
-					return true;
+		_nodeChange : function(ed, cm, n) {
+			var ed = this.editor;
 
-				var inst = tinyMCE.selectedInstance;
-				var formObj = inst.formElement.form;
+			if (ed.getParam('save_enablewhendirty')) {
+				cm.setDisabled('save', !ed.isDirty());
+				cm.setDisabled('cancel', !ed.isDirty());
+			}
+		},
 
-				if (tinyMCE.getParam("save_enablewhendirty") && !inst.isDirty())
-					return true;
+		// Private methods
+
+		_save : function() {
+			var ed = this.editor, formObj, os, i, elementId;
 
-				if (formObj) {
-					tinyMCE.triggerSave();
+			if (ed.getParam("fullscreen_is_enabled"))
+				return true;
+
+			formObj = tinymce.DOM.get(ed.id).form || tinymce.DOM.getParent(ed.id, 'form');
+
+			if (ed.getParam("save_enablewhendirty") && !ed.isDirty())
+				return true;
 
-					// Use callback instead
-					var os;
-					if ((os = tinyMCE.getParam("save_onsavecallback"))) {
-						if (eval(os + '(inst);')) {
-							inst.startContent = tinyMCE.trim(inst.getBody().innerHTML);
-							/*inst.undoLevels = new Array();
-							inst.undoIndex = 0;
-							inst.typingUndoIndex = -1;
-							inst.undoRedo = true;
-							inst.undoLevels[inst.undoLevels.length] = inst.startContent;*/
-							tinyMCE.triggerNodeChange(false, true);
-						}
+			if (formObj) {
+				tinyMCE.triggerSave();
 
-						return true;
+				// Use callback instead
+				if (os = ed.getParam("save_onsavecallback")) {
+					if (ed.execCallback('save_onsavecallback', ed)) {
+						ed.startContent = tinymce.trim(ed.getContent({format : 'raw'}));
+						ed.nodeChanged();
 					}
 
-					// Disable all UI form elements that TinyMCE created
-					for (var i=0; i<formObj.elements.length; i++) {
-						var elementId = formObj.elements[i].name ? formObj.elements[i].name : formObj.elements[i].id;
+					return;
+				}
 
-						if (elementId.indexOf('mce_editor_') == 0)
-							formObj.elements[i].disabled = true;
-					}
+				ed.isNotDirty = true;
 
-					tinyMCE.isNotDirty = true;
-
-					if (formObj.onsubmit == null || formObj.onsubmit() != false)
-						inst.formElement.form.submit();
-				} else
-					alert("Error: No form element found.");
+				if (formObj.onsubmit == null || formObj.onsubmit() != false)
+					formObj.submit();
 
-				return true;
-		}
-		// Pass to next handler in chain
-		return false;
-	},
+				ed.nodeChanged();
+			} else
+				ed.windowManager.alert("Error: No form element found.");
+
+			return true;
+		},
 
-	handleNodeChange : function(editor_id, node, undo_index, undo_levels, visual_aid, any_selection) {
-		if (tinyMCE.getParam("fullscreen_is_enabled")) {
-			tinyMCE.switchClass(editor_id + '_save', 'mceButtonDisabled');
-			return true;
-		}
+		_cancel : function() {
+			var ed = this.editor, os, h = tinymce.trim(ed.startContent);
 
-		if (tinyMCE.getParam("save_enablewhendirty")) {
-			var inst = tinyMCE.getInstanceById(editor_id);
-
-			if (inst.isDirty()) {
-				tinyMCE.switchClass(editor_id + '_save', 'mceButtonNormal');
-				return true;
+			// Use callback instead
+			if (os = ed.getParam("save_oncancelcallback")) {
+				ed.execCallback('save_oncancelcallback', ed);
+				return;
 			}
 
-			tinyMCE.switchClass(editor_id + '_save', 'mceButtonDisabled');
+			ed.setContent(h);
+			ed.undoManager.clear();
+			ed.nodeChanged();
 		}
+	});
 
-		return true;
-	}
-};
-
-tinyMCE.addPlugin("save", TinyMCE_SavePlugin);
+	// Register plugin
+	tinymce.PluginManager.add('save', tinymce.plugins.Save);
+})();
\ No newline at end of file
Binary file includes/clientside/tinymce/plugins/save/images/save.gif has changed
--- a/includes/clientside/tinymce/plugins/save/langs/en.js	Fri Feb 22 12:46:51 2008 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,5 +0,0 @@
-// UK lang variables
-
-tinyMCE.addToLang('',{
-save_desc : 'Save'
-});
--- a/includes/clientside/tinymce/plugins/save/readme.txt	Fri Feb 22 12:46:51 2008 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1 +0,0 @@
-Check the TinyMCE documentation for details on this plugin.
--- a/includes/clientside/tinymce/plugins/searchreplace/css/searchreplace.css	Fri Feb 22 12:46:51 2008 -0500
+++ b/includes/clientside/tinymce/plugins/searchreplace/css/searchreplace.css	Fri Feb 22 12:51:53 2008 -0500
@@ -1,20 +1,6 @@
-/* stylesheet for advsearchreplace plugin*/
-
-.panel_wrapper { height: 85px; }
-.panel_wrapper div.current { height: 85px; }
-
-/* MS IE only styles */
-* html .panel_wrapper { height: 100px; }
-* html .panel_wrapper div.current { height: 100px; }
+.panel_wrapper {height:85px;}
+.panel_wrapper div.current {height:85px;}
 
-#replaceBtn, #replaceAllBtn {
-	padding-bottom: 2px;
-	font-weight: bold;
-	width: 90px;
-	height: 21px;
-	border: 0;
-	cursor: pointer;
-}
-
-#replaceBtn { background: url(../images/replace_button_bg.gif); }
-#replaceAllBtn { background: url(../images/replace_all_button_bg.gif); }
+/* IE */
+* html .panel_wrapper {height:100px;}
+* html .panel_wrapper div.current {height:100px;}
--- a/includes/clientside/tinymce/plugins/searchreplace/editor_plugin.js	Fri Feb 22 12:46:51 2008 -0500
+++ b/includes/clientside/tinymce/plugins/searchreplace/editor_plugin.js	Fri Feb 22 12:51:53 2008 -0500
@@ -1,1 +1,1 @@
-tinyMCE.importPluginLanguagePack('searchreplace');var TinyMCE_SearchReplacePlugin={getInfo:function(){return{longname:'Search/Replace',author:'Moxiecode Systems AB',authorurl:'http://tinymce.moxiecode.com',infourl:'http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/searchreplace',version:tinyMCE.majorVersion+"."+tinyMCE.minorVersion}},initInstance:function(inst){inst.addShortcut('ctrl','f','lang_searchreplace_search_desc','mceSearch',true);},getControlHTML:function(cn){switch(cn){case"search":return tinyMCE.getButtonHTML(cn,'lang_searchreplace_search_desc','{$pluginurl}/images/search.gif','mceSearch',true);case"replace":return tinyMCE.getButtonHTML(cn,'lang_searchreplace_replace_desc','{$pluginurl}/images/replace.gif','mceSearchReplace',true)}return""},execCommand:function(editor_id,element,command,user_interface,value){var inst=tinyMCE.getInstanceById(editor_id),selectedText=inst.selection.getSelectedText(),rng;function defValue(key,default_value){value[key]=typeof(value[key])=="undefined"?default_value:value[key]}function replaceSel(search_str,str,back){if(!inst.selection.isCollapsed()){if(tinyMCE.isRealIE)inst.selection.getRng().duplicate().pasteHTML(str);else inst.execCommand('mceInsertContent',false,str)}}if(!value)value=[];defValue("editor_id",editor_id);defValue("searchstring",selectedText);defValue("replacestring",null);defValue("replacemode","none");defValue("casesensitive",false);defValue("backwards",false);defValue("wrap",false);defValue("wholeword",false);defValue("inline","yes");defValue("resizable","no");switch(command){case"mceSearch":if(user_interface){var template=new Array();template['file']='../../plugins/searchreplace/searchreplace.htm';template['width']=380;template['height']=155+(tinyMCE.isNS7?20:0)+(tinyMCE.isMSIE?15:0);template['width']+=tinyMCE.getLang('lang_searchreplace_delta_width',0);template['height']+=tinyMCE.getLang('lang_searchreplace_delta_height',0);inst.selection.collapse(true);tinyMCE.openWindow(template,value)}else{var win=tinyMCE.getInstanceById(editor_id).contentWindow;var doc=tinyMCE.getInstanceById(editor_id).contentWindow.document;var body=tinyMCE.getInstanceById(editor_id).contentWindow.document.body;var awin=value.win,found;if(body.innerHTML==""){awin.alert(tinyMCE.getLang('lang_searchreplace_notfound'));return true}if(value['replacemode']=="current"){replaceSel(value['string'],value['replacestring'],value['backwards']);value['replacemode']="none";}inst.selection.collapse(value['backwards']);if(tinyMCE.isMSIE){var rng=inst.selection.getRng();var flags=0;if(value['wholeword'])flags=flags|2;if(value['casesensitive'])flags=flags|4;if(!rng.findText){awin.alert('This operation is currently not supported by this browser.');return true}if(value['replacemode']=="all"){found=false;while(rng.findText(value['string'],value['backwards']?-1:1,flags)){found=true;rng.scrollIntoView();rng.select();replaceSel(value['string'],value['replacestring'],value['backwards'])}if(found)awin.alert(tinyMCE.getLang('lang_searchreplace_allreplaced'));else awin.alert(tinyMCE.getLang('lang_searchreplace_notfound'));return true}if(rng.findText(value['string'],value['backwards']?-1:1,flags)){rng.scrollIntoView();rng.select()}else awin.alert(tinyMCE.getLang('lang_searchreplace_notfound'))}else{if(value['replacemode']=="all"){found=false;while(win.find(value['string'],value['casesensitive'],value['backwards'],value['wrap'],value['wholeword'],false,false)){found=true;replaceSel(value['string'],value['replacestring'],value['backwards'])}if(found)awin.alert(tinyMCE.getLang('lang_searchreplace_allreplaced'));else awin.alert(tinyMCE.getLang('lang_searchreplace_notfound'));return true}if(!win.find(value['string'],value['casesensitive'],value['backwards'],value['wrap'],value['wholeword'],false,false))awin.alert(tinyMCE.getLang('lang_searchreplace_notfound'))}}return true;case"mceSearchReplace":value['replacestring']="";tinyMCE.execInstanceCommand(editor_id,'mceSearch',user_interface,value,false);return true}return false}};tinyMCE.addPlugin("searchreplace",TinyMCE_SearchReplacePlugin);
\ No newline at end of file
+(function(){tinymce.create('tinymce.plugins.SearchReplacePlugin',{init:function(ed,url){function open(m){ed.windowManager.open({file:url+'/searchreplace.htm',width:400+parseInt(ed.getLang('searchreplace.delta_width',0)),height:160+parseInt(ed.getLang('searchreplace.delta_height',0)),inline:1},{mode:m,search_string:ed.selection.getContent({format:'text'}),plugin_url:url});};ed.addCommand('mceSearch',function(){open('search');});ed.addCommand('mceReplace',function(){open('replace');});ed.addButton('search',{title:'searchreplace.search_desc',cmd:'mceSearch'});ed.addButton('replace',{title:'searchreplace.replace_desc',cmd:'mceReplace'});ed.addShortcut('ctrl+f','searchreplace.search_desc','mceSearch');},getInfo:function(){return{longname:'Search/Replace',author:'Moxiecode Systems AB',authorurl:'http://tinymce.moxiecode.com',infourl:'http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/searchreplace',version:tinymce.majorVersion+"."+tinymce.minorVersion};}});tinymce.PluginManager.add('searchreplace',tinymce.plugins.SearchReplacePlugin);})();
\ No newline at end of file
--- a/includes/clientside/tinymce/plugins/searchreplace/editor_plugin_src.js	Fri Feb 22 12:46:51 2008 -0500
+++ b/includes/clientside/tinymce/plugins/searchreplace/editor_plugin_src.js	Fri Feb 22 12:51:53 2008 -0500
@@ -1,173 +1,53 @@
 /**
- * $Id: editor_plugin_src.js 201 2007-02-12 15:56:56Z spocke $
+ * $Id: editor_plugin_src.js 520 2008-01-07 16:30:32Z spocke $
  *
  * @author Moxiecode
- * @copyright Copyright © 2004-2007, Moxiecode Systems AB, All rights reserved.
+ * @copyright Copyright © 2004-2008, Moxiecode Systems AB, All rights reserved.
  */
 
-tinyMCE.importPluginLanguagePack('searchreplace');
-
-var TinyMCE_SearchReplacePlugin = {
-	getInfo : function() {
-		return {
-			longname : 'Search/Replace',
-			author : 'Moxiecode Systems AB',
-			authorurl : 'http://tinymce.moxiecode.com',
-			infourl : 'http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/searchreplace',
-			version : tinyMCE.majorVersion + "." + tinyMCE.minorVersion
-		};
-	},
-
-	initInstance : function (inst) {
-		inst.addShortcut('ctrl', 'f', 'lang_searchreplace_search_desc', 'mceSearch', true);
-		// No CTRL+R for "replace" because browsers will reload page instead of executing plugin
-	},
-
-	getControlHTML : function (cn) {
-		switch (cn) {
-			case "search" :
-				return tinyMCE.getButtonHTML(cn, 'lang_searchreplace_search_desc', '{$pluginurl}/images/search.gif','mceSearch', true);
-
-			case "replace" :
-				return tinyMCE.getButtonHTML(cn, 'lang_searchreplace_replace_desc', '{$pluginurl}/images/replace.gif', 'mceSearchReplace', true);
-		}
-
-		return "";
-	},
-
-	execCommand : function (editor_id, element, command, user_interface, value) {
-		var inst = tinyMCE.getInstanceById(editor_id), selectedText = inst.selection.getSelectedText(), rng;
-
-		function defValue(key, default_value) {
-			value[key] = typeof(value[key]) == "undefined" ? default_value : value[key];
-		}
+(function() {
+	tinymce.create('tinymce.plugins.SearchReplacePlugin', {
+		init : function(ed, url) {
+			function open(m) {
+				ed.windowManager.open({
+					file : url + '/searchreplace.htm',
+					width : 400 + parseInt(ed.getLang('searchreplace.delta_width', 0)),
+					height : 160 + parseInt(ed.getLang('searchreplace.delta_height', 0)),
+					inline : 1
+				}, {
+					mode : m,
+					search_string : ed.selection.getContent({format : 'text'}),
+					plugin_url : url
+				});
+			};
 
-		function replaceSel(search_str, str, back) {
-			if (!inst.selection.isCollapsed()) {
-				if (tinyMCE.isRealIE)
-					inst.selection.getRng().duplicate().pasteHTML(str); // Needs to be duplicated due to selection bug in IE
-				else
-					inst.execCommand('mceInsertContent', false, str);
-			}
-		}
-
-		if (!value)
-			value = [];
-
-		defValue("editor_id", editor_id);
-		defValue("searchstring", selectedText);
-		defValue("replacestring", null);
-		defValue("replacemode", "none");
-		defValue("casesensitive", false);
-		defValue("backwards", false);
-		defValue("wrap", false);
-		defValue("wholeword", false);
-		defValue("inline", "yes");
-		defValue("resizable", "no");
-
-		switch (command) {
-			case "mceSearch" :
-				if (user_interface) {
-					var template = new Array();
-
-					template['file'] = '../../plugins/searchreplace/searchreplace.htm';
-					template['width'] = 380;
-					template['height'] = 155 + (tinyMCE.isNS7 ? 20 : 0) + (tinyMCE.isMSIE ? 15 : 0);
-					template['width'] += tinyMCE.getLang('lang_searchreplace_delta_width', 0);
-					template['height'] += tinyMCE.getLang('lang_searchreplace_delta_height', 0);
-
-					inst.selection.collapse(true);
-
-					tinyMCE.openWindow(template, value);
-				} else {
-					var win = tinyMCE.getInstanceById(editor_id).contentWindow;
-					var doc = tinyMCE.getInstanceById(editor_id).contentWindow.document;
-					var body = tinyMCE.getInstanceById(editor_id).contentWindow.document.body;
-					var awin = value.win, found;
+			// Register commands
+			ed.addCommand('mceSearch', function() {
+				open('search');
+			});
 
-					if (body.innerHTML == "") {
-						awin.alert(tinyMCE.getLang('lang_searchreplace_notfound'));
-						return true;
-					}
-
-					if (value['replacemode'] == "current") {
-						replaceSel(value['string'], value['replacestring'], value['backwards']);
-						value['replacemode'] = "none";
-						//tinyMCE.execInstanceCommand(editor_id, 'mceSearch', user_interface, value);
-						//return true;
-					}
-
-					inst.selection.collapse(value['backwards']);
-
-					if (tinyMCE.isMSIE) {
-						var rng = inst.selection.getRng();
-						var flags = 0;
-						if (value['wholeword'])
-							flags = flags | 2;
+			ed.addCommand('mceReplace', function() {
+				open('replace');
+			});
 
-						if (value['casesensitive'])
-							flags = flags | 4;
-
-						if (!rng.findText) {
-							awin.alert('This operation is currently not supported by this browser.');
-							return true;
-						}
-
-						if (value['replacemode'] == "all") {
-							found = false;
+			// Register buttons
+			ed.addButton('search', {title : 'searchreplace.search_desc', cmd : 'mceSearch'});
+			ed.addButton('replace', {title : 'searchreplace.replace_desc', cmd : 'mceReplace'});
 
-							while (rng.findText(value['string'], value['backwards'] ? -1 : 1, flags)) {
-								found = true;
-								rng.scrollIntoView();
-								rng.select();
-								replaceSel(value['string'], value['replacestring'], value['backwards']);
-							}
-
-							if (found)
-								awin.alert(tinyMCE.getLang('lang_searchreplace_allreplaced'));
-							else
-								awin.alert(tinyMCE.getLang('lang_searchreplace_notfound'));
+			ed.addShortcut('ctrl+f', 'searchreplace.search_desc', 'mceSearch');
+		},
 
-							return true;
-						}
-
-						if (rng.findText(value['string'], value['backwards'] ? -1 : 1, flags)) {
-							rng.scrollIntoView();
-							rng.select();
-						} else
-							awin.alert(tinyMCE.getLang('lang_searchreplace_notfound'));
-					} else {
-						if (value['replacemode'] == "all") {
-							found = false;
-
-							while (win.find(value['string'], value['casesensitive'], value['backwards'], value['wrap'], value['wholeword'], false, false)) {
-								found = true;
-								replaceSel(value['string'], value['replacestring'], value['backwards']);
-							}
-
-							if (found)
-								awin.alert(tinyMCE.getLang('lang_searchreplace_allreplaced'));
-							else
-								awin.alert(tinyMCE.getLang('lang_searchreplace_notfound'));
+		getInfo : function() {
+			return {
+				longname : 'Search/Replace',
+				author : 'Moxiecode Systems AB',
+				authorurl : 'http://tinymce.moxiecode.com',
+				infourl : 'http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/searchreplace',
+				version : tinymce.majorVersion + "." + tinymce.minorVersion
+			};
+		}
+	});
 
-							return true;
-						}
-
-						if (!win.find(value['string'], value['casesensitive'], value['backwards'], value['wrap'], value['wholeword'], false, false))
-							awin.alert(tinyMCE.getLang('lang_searchreplace_notfound'));
-					}
-				}
-
-				return true;
-
-			case "mceSearchReplace" :
-				value['replacestring'] = "";
-				tinyMCE.execInstanceCommand(editor_id, 'mceSearch', user_interface, value, false);
-				return true;
-		}
-
-		return false;
-	}
-};
-
-tinyMCE.addPlugin("searchreplace", TinyMCE_SearchReplacePlugin);
\ No newline at end of file
+	// Register plugin
+	tinymce.PluginManager.add('searchreplace', tinymce.plugins.SearchReplacePlugin);
+})();
\ No newline at end of file
Binary file includes/clientside/tinymce/plugins/searchreplace/images/replace.gif has changed
Binary file includes/clientside/tinymce/plugins/searchreplace/images/replace_all_button_bg.gif has changed
Binary file includes/clientside/tinymce/plugins/searchreplace/images/replace_button_bg.gif has changed
Binary file includes/clientside/tinymce/plugins/searchreplace/images/search.gif has changed
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/includes/clientside/tinymce/plugins/searchreplace/js/searchreplace.js	Fri Feb 22 12:51:53 2008 -0500
@@ -0,0 +1,109 @@
+tinyMCEPopup.requireLangPack();
+
+var SearchReplaceDialog = {
+	init : function(ed) {
+		var f = document.forms[0], m = tinyMCEPopup.getWindowArg("mode");
+
+		this.switchMode(m);
+
+		f[m + '_panel_searchstring'].value = tinyMCEPopup.getWindowArg("search_string");
+	},
+
+	switchMode : function(m) {
+		var f, lm = this.lastMode;
+
+		if (lm != m) {
+			f = document.forms[0];
+
+			if (lm) {
+				f[m + '_panel_searchstring'].value = f[lm + '_panel_searchstring'].value;
+				f[m + '_panel_backwardsu'].checked = f[lm + '_panel_backwardsu'].checked;
+				f[m + '_panel_backwardsd'].checked = f[lm + '_panel_backwardsd'].checked;
+				f[m + '_panel_casesensitivebox'].checked = f[lm + '_panel_casesensitivebox'].checked;
+			}
+
+			mcTabs.displayTab(m + '_tab',  m + '_panel');
+			document.getElementById("replace_buttons").style.visibility = (m == "replace") ? "visible" : "hidden";
+			this.lastMode = m;
+		}
+	},
+
+	searchNext : function(a) {
+		var ed = tinyMCEPopup.editor, se = ed.selection, r = se.getRng(), f, m = this.lastMode, s, b, fl = 0, w = ed.getWin(), wm = ed.windowManager, fo = 0;
+
+		// Get input
+		f = document.forms[0];
+		s = f[m + '_panel_searchstring'].value;
+		b = f[m + '_panel_backwardsu'].checked;
+		ca = f[m + '_panel_casesensitivebox'].checked;
+		rs = f['replace_panel_replacestring'].value;
+
+		function fix() {
+			// Correct Firefox graphics glitches
+			r = se.getRng().cloneRange();
+			ed.getDoc().execCommand('SelectAll', false, null);
+			se.setRng(r);
+		};
+
+		function replace() {
+			if (tinymce.isIE)
+				ed.selection.getRng().duplicate().pasteHTML(rs); // Needs to be duplicated due to selection bug in IE
+			else
+				ed.getDoc().execCommand('InsertHTML', false, rs);
+		};
+
+		// IE flags
+		if (ca)
+			fl = fl | 4;
+
+		switch (a) {
+			case 'all':
+				if (tinymce.isIE) {
+					while (r.findText(s, b ? -1 : 1, fl)) {
+						r.scrollIntoView();
+						r.select();
+						replace();
+						fo = 1;
+					}
+
+					tinyMCEPopup.storeSelection();
+				} else {
+					while (w.find(s, ca, b, false, false, false, false)) {
+						replace();
+						fo = 1;
+					}
+				}
+
+				if (fo)
+					wm.alert(ed.getLang('searchreplace_dlg.allreplaced'));
+				else
+					wm.alert(ed.getLang('searchreplace_dlg.notfound'));
+
+				return;
+
+			case 'current':
+				replace();
+				break;
+		}
+
+		se.collapse(b);
+		r = se.getRng();
+
+		if (tinymce.isIE) {
+			if (r.findText(s, b ? -1 : 1, fl)) {
+				r.scrollIntoView();
+				r.select();
+			} else
+				wm.alert(ed.getLang('searchreplace_dlg.notfound'));
+
+			tinyMCEPopup.storeSelection();
+		} else {
+			if (!w.find(s, ca, b, false, false, false, false))
+				wm.alert(ed.getLang('searchreplace_dlg.notfound'));
+			else
+				fix();
+		}
+	}
+};
+
+tinyMCEPopup.onInit.add(SearchReplaceDialog.init, SearchReplaceDialog);
--- a/includes/clientside/tinymce/plugins/searchreplace/jscripts/searchreplace.js	Fri Feb 22 12:46:51 2008 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,86 +0,0 @@
-function init() {
-	tinyMCEPopup.resizeToInnerSize();
-
-	// start with appropiate tab
-	var task = (tinyMCE.getWindowArg("replacestring") != null) ? "replace" : "search";
-	mcTabs.displayTab(task + '_tab', task +'_panel');
-	manageReplaceButtons();
-	
-	var formObj = document.forms[0];
-
-	formObj[task + "_panel_searchstring"].value = tinyMCE.getWindowArg("searchstring");
-	formObj["replace_panel_replacestring"].value = (tinyMCE.getWindowArg("replacestring") != null) ? tinyMCE.getWindowArg("replacestring") : "";
-	formObj[task + "_panel_casesensitivebox"].checked = tinyMCE.getWindowArg("casesensitive");
-	formObj[task + "_panel_backwardsu"].checked = tinyMCE.getWindowArg("backwards");
-	formObj[task + "_panel_backwardsd"].checked = !tinyMCE.getWindowArg("backwards");
-}
-
-function searchNext(replacemode) {
-	// "search" or "replace" mode of operation?
-	var task = (document.getElementById("search_tab").className == "current") ? "search" : "replace";
-
-	var formObj = document.forms[0];
-
-	if (task == "replace") {
-		// Whats the point?
-		if (formObj[task + "_panel_searchstring"].value == "" || formObj[task + "_panel_searchstring"].value == formObj[task + "_panel_replacestring"].value)
-			return false;
-	}
-
-	// Do search
-	tinyMCEPopup.execCommand('mceSearch', false, { 
-		string : formObj[task + "_panel_searchstring"].value,
-		replacestring : formObj["replace_panel_replacestring"].value,
-		replacemode : replacemode,
-		casesensitive : formObj[task + "_panel_casesensitivebox"].checked,
-		backwards : formObj[task + "_panel_backwardsu"].checked,
-		win : window
-		}, false);
-
-	window.focus();
-
-	return false;
-}
-
-function cancelAction() {
-	tinyMCEPopup.close();
-}
-
-function manageReplaceButtons() {
-	// "search" or "replace" mode of operation?
-	var task = (document.getElementById("search_tab").className == "current") ? "search" : "replace";
-	document.getElementById("replace_buttons").style.visibility = (task == "replace") ? "visible" : "hidden";
-}
-
-function copyValues(link) {
-	// check if tab is already active
-	var tab = link;
-	while (tab.tagName && tab.tagName.toLowerCase() != "li") tab = tab.parentNode;
-	if (tab.className) return false; // tab is already active -> no need to copy any values!
-
-	// copy values from one panel to the other (if they exist there)
-	var from_panel_name = tab.id.match(/^search/i) ? "replace_panel" : "search_panel";
-	var to_panel_name = (from_panel_name == "search_panel") ? "replace_panel" : "search_panel";
-
-	// find all elements with IDs to copy their values
-	var elms = document.getElementById(from_panel_name).getElementsByTagName("*");
-	for (var i = 0; i < elms.length; i++) {
-		if (elms[i].id && elms[i].id != "") {
-			var checked = "undefined";
-			if (elms[i].type.toLowerCase() == "checkbox" || elms[i].type.toLowerCase() == "radio")
-				checked = elms[i].checked;
-
-			// copy values if element exists in other panel
-			var to_elm_name = to_panel_name + elms[i].id.substring(from_panel_name.length, elms[i].id.length);
-			var to_elm = document.getElementById(to_elm_name);
-			if (to_elm) {
-				if (checked != "undefined")
-					to_elm.checked = checked;
-				else
-					to_elm.value = elms[i].value;
-			}
-		}
-	}
-
-	return false;
-}
\ No newline at end of file
--- a/includes/clientside/tinymce/plugins/searchreplace/langs/en.js	Fri Feb 22 12:46:51 2008 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,21 +0,0 @@
-// UK lang variables
-
-tinyMCE.addToLang('',{
-searchreplace_search_desc : 'Find',
-searchreplace_searchnext_desc : 'Find again',
-searchreplace_replace_desc : 'Find/Replace',
-searchreplace_notfound : 'The search has been completed. The search string could not be found.',
-searchreplace_search_title : 'Find',
-searchreplace_replace_title : 'Find/Replace',
-searchreplace_allreplaced : 'All occurrences of the search string were replaced.',
-searchreplace_findwhat : 'Find what',
-searchreplace_replacewith : 'Replace with',
-searchreplace_direction : 'Direction',
-searchreplace_up : 'Up',
-searchreplace_down : 'Down',
-searchreplace_case : 'Match case',
-searchreplace_findnext : 'Find&nbsp;next',
-searchreplace_replace : 'Replace',
-searchreplace_replaceall : 'Replace&nbsp;all',
-searchreplace_cancel : 'Cancel'
-});
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/includes/clientside/tinymce/plugins/searchreplace/langs/en_dlg.js	Fri Feb 22 12:51:53 2008 -0500
@@ -0,0 +1,16 @@
+tinyMCE.addI18n('en.searchreplace_dlg',{
+searchnext_desc:"Find again",
+notfound:"The search has been completed. The search string could not be found.",
+search_title:"Find",
+replace_title:"Find/Replace",
+allreplaced:"All occurrences of the search string were replaced.",
+findwhat:"Find what",
+replacewith:"Replace with",
+direction:"Direction",
+up:"Up",
+down:"Down",
+mcase:"Match case",
+findnext:"Find next",
+replace:"Replace",
+replaceall:"Replace all"
+});
\ No newline at end of file
--- a/includes/clientside/tinymce/plugins/searchreplace/readme.txt	Fri Feb 22 12:46:51 2008 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1 +0,0 @@
-Check the TinyMCE documentation for details on this plugin.
--- a/includes/clientside/tinymce/plugins/searchreplace/searchreplace.htm	Fri Feb 22 12:46:51 2008 -0500
+++ b/includes/clientside/tinymce/plugins/searchreplace/searchreplace.htm	Fri Feb 22 12:51:53 2008 -0500
@@ -1,39 +1,39 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
 <html xmlns="http://www.w3.org/1999/xhtml">
 <head>
-	<title>{$lang_searchreplace_replace_title}</title>
-	<script language="javascript" type="text/javascript" src="../../tiny_mce_popup.js"></script>
-	<script language="javascript" type="text/javascript" src="../../utils/mctabs.js"></script>
-	<script language="javascript" type="text/javascript" src="../../utils/form_utils.js"></script>
-	<script language="javascript" type="text/javascript" src="jscripts/searchreplace.js"></script>
+	<title>{#searchreplace_dlg.replace_title}</title>
+	<script type="text/javascript" src="../../tiny_mce_popup.js"></script>
+	<script type="text/javascript" src="../../utils/mctabs.js"></script>
+	<script type="text/javascript" src="../../utils/form_utils.js"></script>
+	<script type="text/javascript" src="js/searchreplace.js"></script>
 	<link rel="stylesheet" type="text/css" href="css/searchreplace.css" />
 	<base target="_self" />
 </head>
-<body onload="tinyMCEPopup.executeOnLoad('init();');" style="display: none; margin: 4px;">
+<body style="display:none;">
 <form onsubmit="return false;" action="#">
 	<div class="tabs">
 		<ul>
-			<li id="search_tab"><span><a href="javascript:mcTabs.displayTab('search_tab','search_panel');manageReplaceButtons();" onmousedown="return copyValues(this);">{$lang_searchreplace_search_desc}</a></span></li>
-			<li id="replace_tab"><span><a href="javascript:mcTabs.displayTab('replace_tab','replace_panel');manageReplaceButtons();" onmousedown="return copyValues(this);">{$lang_searchreplace_replace}</a></span></li>
+			<li id="search_tab"><span><a href="javascript:SearchReplaceDialog.switchMode('search');" onmousedown="return false;">{#searchreplace.search_desc}</a></span></li>
+			<li id="replace_tab"><span><a href="javascript:SearchReplaceDialog.switchMode('replace');" onmousedown="return false;">{#searchreplace_dlg.replace}</a></span></li>
 		</ul>
 	</div>
 
 	<div class="panel_wrapper">
-
 		<div id="search_panel" class="panel">
 			<table border="0" cellspacing="0" cellpadding="2">
 				<tr>
-					<td><label for="search_panel_searchstring">{$lang_searchreplace_findwhat}</label></td>
+					<td><label for="search_panel_searchstring">{#searchreplace_dlg.findwhat}</label></td>
 					<td><input type="text" id="search_panel_searchstring" name="search_panel_searchstring" style="width: 200px" /></td>
 				</tr>
 				<tr>
 					<td colspan="2">
 						<table border="0" cellspacing="0" cellpadding="0" class="direction">
 							<tr>
-								<td><label>{$lang_searchreplace_direction}</label></td>
+								<td><label>{#searchreplace_dlg.direction}</label></td>
 								<td><input id="search_panel_backwardsu" name="search_panel_backwards" class="radio" type="radio" /></td>
-								<td><label for="search_panel_backwardsu">{$lang_searchreplace_up}</label></td>
-								<td><input id="search_panel_backwardsd" name="search_panel_backwards" class="radio" type="radio" /></td>
-								<td><label for="search_panel_backwardsd">{$lang_searchreplace_down}</label></td>
+								<td><label for="search_panel_backwardsu">{#searchreplace_dlg.up}</label></td>
+								<td><input id="search_panel_backwardsd" name="search_panel_backwards" class="radio" type="radio" checked="checked" /></td>
+								<td><label for="search_panel_backwardsd">{#searchreplace_dlg.down}</label></td>
 							</tr>
 						</table>
 					</td>
@@ -43,7 +43,7 @@
 						<table border="0" cellspacing="0" cellpadding="0">
 							<tr>
 								<td><input id="search_panel_casesensitivebox" name="search_panel_casesensitivebox" class="checkbox" type="checkbox" /></td>
-								<td><label for="search_panel_casesensitivebox">{$lang_searchreplace_case}</label></td>
+								<td><label for="search_panel_casesensitivebox">{#searchreplace_dlg.mcase}</label></td>
 							</tr>
 						</table>
 					</td>
@@ -54,22 +54,22 @@
 		<div id="replace_panel" class="panel">
 			<table border="0" cellspacing="0" cellpadding="2">
 				<tr>
-					<td><label for="replace_panel_searchstring">{$lang_searchreplace_findwhat}</label></td>
+					<td><label for="replace_panel_searchstring">{#searchreplace_dlg.findwhat}</label></td>
 					<td><input type="text" id="replace_panel_searchstring" name="replace_panel_searchstring" style="width: 200px" /></td>
 				</tr>
 				<tr>
-					<td><label for="replace_panel_replacestring">{$lang_searchreplace_replacewith}</label></td>
+					<td><label for="replace_panel_replacestring">{#searchreplace_dlg.replacewith}</label></td>
 					<td><input type="text" id="replace_panel_replacestring" name="replace_panel_replacestring" style="width: 200px" /></td>
 				</tr>
 				<tr>
 					<td colspan="2">
 						<table border="0" cellspacing="0" cellpadding="0" class="direction">
 							<tr>
-								<td><label>{$lang_searchreplace_direction}</label></td>
+								<td><label>{#searchreplace_dlg.direction}</label></td>
 								<td><input id="replace_panel_backwardsu" name="replace_panel_backwards" class="radio" type="radio" /></td>
-								<td><label for="replace_panel_backwardsu">{$lang_searchreplace_up}</label></td>
-								<td><input id="replace_panel_backwardsd" name="replace_panel_backwards" class="radio" type="radio" /></td>
-								<td><label for="replace_panel_backwardsd">{$lang_searchreplace_down}</label></td>
+								<td><label for="replace_panel_backwardsu">{#searchreplace_dlg.up}</label></td>
+								<td><input id="replace_panel_backwardsd" name="replace_panel_backwards" class="radio" type="radio" checked="checked" /></td>
+								<td><label for="replace_panel_backwardsd">{#searchreplace_dlg.down}</label></td>
 							</tr>
 						</table>
 					</td>
@@ -79,7 +79,7 @@
 						<table border="0" cellspacing="0" cellpadding="0">
 							<tr>
 								<td><input id="replace_panel_casesensitivebox" name="replace_panel_casesensitivebox" class="checkbox" type="checkbox" /></td>
-								<td><label for="replace_panel_casesensitivebox">{$lang_searchreplace_case}</label></td>
+								<td><label for="replace_panel_casesensitivebox">{#searchreplace_dlg.mcase}</label></td>
 							</tr>
 						</table>
 					</td>
@@ -91,15 +91,15 @@
 
 	<div class="mceActionPanel">
 		<div style="float: left">
-			<input type="button" id="insert" name="insert" value="{$lang_searchreplace_findnext}" onclick="searchNext('none');" />
+			<input type="button" id="insert" name="insert" value="{#searchreplace_dlg.findnext}" onclick="SearchReplaceDialog.searchNext('none');" />
 			<span id="replace_buttons">
-				<input type="button" id="replaceBtn" name="replaceBtn" value="{$lang_searchreplace_replace}" onclick="searchNext('current');" />
-				<input type="button" id="replaceAllBtn" name="replaceAllBtn" value="{$lang_searchreplace_replaceall}" onclick="searchNext('all');;" />
+				<input type="button" class="button" id="replaceBtn" name="replaceBtn" value="{#searchreplace_dlg.replace}" onclick="SearchReplaceDialog.searchNext('current');" />
+				<input type="button" class="button" id="replaceAllBtn" name="replaceAllBtn" value="{#searchreplace_dlg.replaceall}" onclick="SearchReplaceDialog.searchNext('all');" />
 			</span>
 		</div>
 
 		<div style="float: right">	
-			<input type="button" id="cancel" name="cancel" value="{$lang_searchreplace_cancel}" onclick="tinyMCEPopup.close();" />
+			<input type="button" id="cancel" name="cancel" value="{#cancel}" onclick="tinyMCEPopup.close();" />
 		</div>
 	</div>
 </form>
--- a/includes/clientside/tinymce/plugins/style/css/props.css	Fri Feb 22 12:46:51 2008 -0500
+++ b/includes/clientside/tinymce/plugins/style/css/props.css	Fri Feb 22 12:51:53 2008 -0500
@@ -1,62 +1,13 @@
-#text_font {
-	width: 250px;
-}
-
-#text_size {
-	width: 70px;
-}
-
-.mceAddSelectValue {
-	background-color: #DDDDDD;
-}
-
-select, #block_text_indent, #box_width, #box_height, #box_padding_top, #box_padding_right, #box_padding_bottom, #box_padding_left {
-	width: 70px;
-}
-
-#box_margin_top, #box_margin_right, #box_margin_bottom, #box_margin_left, #positioning_width, #positioning_height, #positioning_zindex {
-	width: 70px;
-}
-
-#positioning_placement_top, #positioning_placement_right, #positioning_placement_bottom, #positioning_placement_left {
-	width: 70px;
-}
-
-#positioning_clip_top, #positioning_clip_right, #positioning_clip_bottom, #positioning_clip_left {
-	width: 70px;
-}
-
-.panel_wrapper div.current {
-	padding-top: 10px;
-	height: 230px;
-}
-
-.delim {
-	border-left: 1px solid gray;
-}
-
-.tdelim {
-	border-bottom: 1px solid gray;	
-}
-
-#block_display {
-	width: 145px;
-}
-
-#list_type {
-	width: 115px;
-}
-
-.disabled {
-	background-color: #EEEEEE;
-}
-
-#apply {
-	font-weight: bold;
-	width: 78px;
-	height: 21px;
-	border: 0;
-	background-image: url('../images/apply_button_bg.gif');
-	cursor: pointer;
-}
-
+#text_font {width:250px;}
+#text_size {width:70px;}
+.mceAddSelectValue {background:#DDD;}
+select, #block_text_indent, #box_width, #box_height, #box_padding_top, #box_padding_right, #box_padding_bottom, #box_padding_left {width:70px;}
+#box_margin_top, #box_margin_right, #box_margin_bottom, #box_margin_left, #positioning_width, #positioning_height, #positioning_zindex {width:70px;}
+#positioning_placement_top, #positioning_placement_right, #positioning_placement_bottom, #positioning_placement_left {width:70px;}
+#positioning_clip_top, #positioning_clip_right, #positioning_clip_bottom, #positioning_clip_left {width:70px;}
+.panel_wrapper div.current {padding-top:10px;height:230px;}
+.delim {border-left:1px solid gray;}
+.tdelim {border-bottom:1px solid gray;}
+#block_display {width:145px;}
+#list_type {width:115px;}
+.disabled {background:#EEE;}
--- a/includes/clientside/tinymce/plugins/style/editor_plugin.js	Fri Feb 22 12:46:51 2008 -0500
+++ b/includes/clientside/tinymce/plugins/style/editor_plugin.js	Fri Feb 22 12:51:53 2008 -0500
@@ -1,1 +1,1 @@
-tinyMCE.importPluginLanguagePack('style');var TinyMCE_StylePlugin={getInfo:function(){return{longname:'Style',author:'Moxiecode Systems AB',authorurl:'http://tinymce.moxiecode.com',infourl:'http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/style',version:tinyMCE.majorVersion+"."+tinyMCE.minorVersion}},getControlHTML:function(cn){switch(cn){case"styleprops":return tinyMCE.getButtonHTML(cn,'lang_style_styleinfo_desc','{$pluginurl}/images/styleprops.gif','mceStyleProps',true)}return""},execCommand:function(editor_id,element,command,user_interface,value){var e,inst;switch(command){case"mceStyleProps":TinyMCE_StylePlugin._styleProps();return true;case"mceSetElementStyle":inst=tinyMCE.getInstanceById(editor_id);e=inst.selection.getFocusElement();if(e){e.style.cssText=value;inst.repaint()}return true}return false},handleNodeChange:function(editor_id,node,undo_index,undo_levels,visual_aid,any_selection){if(node.nodeName=='BODY')tinyMCE.switchClass(editor_id+'_styleprops','mceButtonDisabled');else tinyMCE.switchClass(editor_id+'_styleprops','mceButtonNormal')},_styleProps:function(){var e=tinyMCE.selectedInstance.selection.getFocusElement();if(!e||e.nodeName=='BODY')return;tinyMCE.openWindow({file:'../../plugins/style/props.htm',width:480+tinyMCE.getLang('lang_style_props_delta_width',0),height:320+tinyMCE.getLang('lang_style_props_delta_height',0)},{editor_id:tinyMCE.selectedInstance.editorId,inline:"yes",style_text:e.style.cssText})}};tinyMCE.addPlugin("style",TinyMCE_StylePlugin);
\ No newline at end of file
+(function(){tinymce.create('tinymce.plugins.StylePlugin',{init:function(ed,url){ed.addCommand('mceStyleProps',function(){ed.windowManager.open({file:url+'/props.htm',width:480+parseInt(ed.getLang('style.delta_width',0)),height:320+parseInt(ed.getLang('style.delta_height',0)),inline:1},{plugin_url:url,style_text:ed.selection.getNode().style.cssText});});ed.addCommand('mceSetElementStyle',function(ui,v){if(e=ed.selection.getNode()){ed.dom.setAttrib(e,'style',v);ed.execCommand('mceRepaint');}});ed.addButton('styleprops',{title:'style.desc',cmd:'mceStyleProps'});},getInfo:function(){return{longname:'Style',author:'Moxiecode Systems AB',authorurl:'http://tinymce.moxiecode.com',infourl:'http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/style',version:tinymce.majorVersion+"."+tinymce.minorVersion};}});tinymce.PluginManager.add('style',tinymce.plugins.StylePlugin);})();
\ No newline at end of file
--- a/includes/clientside/tinymce/plugins/style/editor_plugin_src.js	Fri Feb 22 12:46:51 2008 -0500
+++ b/includes/clientside/tinymce/plugins/style/editor_plugin_src.js	Fri Feb 22 12:51:53 2008 -0500
@@ -1,83 +1,48 @@
 /**
- * $Id: editor_plugin_src.js 201 2007-02-12 15:56:56Z spocke $
+ * $Id: editor_plugin_src.js 520 2008-01-07 16:30:32Z spocke $
  *
  * @author Moxiecode
- * @copyright Copyright © 2004-2007, Moxiecode Systems AB, All rights reserved.
+ * @copyright Copyright © 2004-2008, Moxiecode Systems AB, All rights reserved.
  */
 
-/* Import plugin specific language pack */
-tinyMCE.importPluginLanguagePack('style');
-
-var TinyMCE_StylePlugin = {
-	getInfo : function() {
-		return {
-			longname : 'Style',
-			author : 'Moxiecode Systems AB',
-			authorurl : 'http://tinymce.moxiecode.com',
-			infourl : 'http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/style',
-			version : tinyMCE.majorVersion + "." + tinyMCE.minorVersion
-		};
-	},
-
-	getControlHTML : function(cn) {
-		switch (cn) {
-			case "styleprops":
-				return tinyMCE.getButtonHTML(cn, 'lang_style_styleinfo_desc', '{$pluginurl}/images/styleprops.gif', 'mceStyleProps', true);
-		}
-
-		return "";
-	},
-
-	execCommand : function(editor_id, element, command, user_interface, value) {
-		var e, inst;
-
-		// Handle commands
-		switch (command) {
-			case "mceStyleProps":
-				TinyMCE_StylePlugin._styleProps();
-				return true;
-
-			case "mceSetElementStyle":
-				inst = tinyMCE.getInstanceById(editor_id);
-				e = inst.selection.getFocusElement();
+(function() {
+	tinymce.create('tinymce.plugins.StylePlugin', {
+		init : function(ed, url) {
+			// Register commands
+			ed.addCommand('mceStyleProps', function() {
+				ed.windowManager.open({
+					file : url + '/props.htm',
+					width : 480 + parseInt(ed.getLang('style.delta_width', 0)),
+					height : 320 + parseInt(ed.getLang('style.delta_height', 0)),
+					inline : 1
+				}, {
+					plugin_url : url,
+					style_text : ed.selection.getNode().style.cssText
+				});
+			});
 
-				if (e) {
-					e.style.cssText = value;
-					inst.repaint();
+			ed.addCommand('mceSetElementStyle', function(ui, v) {
+				if (e = ed.selection.getNode()) {
+					ed.dom.setAttrib(e, 'style', v);
+					ed.execCommand('mceRepaint');
 				}
-
-				return true;
-		}
+			});
 
-		// Pass to next handler in chain
-		return false;
-	},
-
-	handleNodeChange : function(editor_id, node, undo_index, undo_levels, visual_aid, any_selection) {
-		if (node.nodeName == 'BODY')
-			tinyMCE.switchClass(editor_id + '_styleprops', 'mceButtonDisabled');
-		else
-			tinyMCE.switchClass(editor_id + '_styleprops', 'mceButtonNormal');
-	},
+			// Register buttons
+			ed.addButton('styleprops', {title : 'style.desc', cmd : 'mceStyleProps'});
+		},
 
-	// Private plugin specific methods
-
-	_styleProps : function() {
-		var e = tinyMCE.selectedInstance.selection.getFocusElement();
-
-		if (!e || e.nodeName == 'BODY')
-			return;
+		getInfo : function() {
+			return {
+				longname : 'Style',
+				author : 'Moxiecode Systems AB',
+				authorurl : 'http://tinymce.moxiecode.com',
+				infourl : 'http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/style',
+				version : tinymce.majorVersion + "." + tinymce.minorVersion
+			};
+		}
+	});
 
-		tinyMCE.openWindow({
-			file : '../../plugins/style/props.htm',
-			width : 480 + tinyMCE.getLang('lang_style_props_delta_width', 0),
-			height : 320 + tinyMCE.getLang('lang_style_props_delta_height', 0)
-		}, {
-			editor_id : tinyMCE.selectedInstance.editorId,
-			inline : "yes",
-			style_text : e.style.cssText
-		});
-	}
-};
-
-tinyMCE.addPlugin("style", TinyMCE_StylePlugin);
+	// Register plugin
+	tinymce.PluginManager.add('style', tinymce.plugins.StylePlugin);
+})();
\ No newline at end of file
Binary file includes/clientside/tinymce/plugins/style/images/apply_button_bg.gif has changed
Binary file includes/clientside/tinymce/plugins/style/images/style_info.gif has changed
Binary file includes/clientside/tinymce/plugins/style/images/styleprops.gif has changed
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/includes/clientside/tinymce/plugins/style/js/props.js	Fri Feb 22 12:51:53 2008 -0500
@@ -0,0 +1,636 @@
+tinyMCEPopup.requireLangPack();
+
+var defaultFonts = "" + 
+	"Arial, Helvetica, sans-serif=Arial, Helvetica, sans-serif;" + 
+	"Times New Roman, Times, serif=Times New Roman, Times, serif;" + 
+	"Courier New, Courier, mono=Courier New, Courier, mono;" + 
+	"Times New Roman, Times, serif=Times New Roman, Times, serif;" + 
+	"Georgia, Times New Roman, Times, serif=Georgia, Times New Roman, Times, serif;" + 
+	"Verdana, Arial, Helvetica, sans-serif=Verdana, Arial, Helvetica, sans-serif;" + 
+	"Geneva, Arial, Helvetica, sans-serif=Geneva, Arial, Helvetica, sans-serif";
+
+var defaultSizes = "9;10;12;14;16;18;24;xx-small;x-small;small;medium;large;x-large;xx-large;smaller;larger";
+var defaultMeasurement = "+pixels=px;points=pt;em;in;cm;mm;picas;ems;exs;%";
+var defaultSpacingMeasurement = "pixels=px;points=pt;in;cm;mm;picas;+ems;exs;%";
+var defaultIndentMeasurement = "pixels=px;+points=pt;in;cm;mm;picas;ems;exs;%";
+var defaultWeight = "normal;bold;bolder;lighter;100;200;300;400;500;600;700;800;900";
+var defaultTextStyle = "normal;italic;oblique";
+var defaultVariant = "normal;small-caps";
+var defaultLineHeight = "normal";
+var defaultAttachment = "fixed;scroll";
+var defaultRepeat = "no-repeat;repeat;repeat-x;repeat-y";
+var defaultPosH = "left;center;right";
+var defaultPosV = "top;center;bottom";
+var defaultVAlign = "baseline;sub;super;top;text-top;middle;bottom;text-bottom";
+var defaultDisplay = "inline;block;list-item;run-in;compact;marker;table;inline-table;table-row-group;table-header-group;table-footer-group;table-row;table-column-group;table-column;table-cell;table-caption;none";
+var defaultBorderStyle = "none;solid;dashed;dotted;double;groove;ridge;inset;outset";
+var defaultBorderWidth = "thin;medium;thick";
+var defaultListType = "disc;circle;square;decimal;lower-roman;upper-roman;lower-alpha;upper-alpha;none";
+
+function init() {
+	var ce = document.getElementById('container'), h;
+
+	ce.style.cssText = tinyMCEPopup.getWindowArg('style_text');
+
+	h = getBrowserHTML('background_image_browser','background_image','image','advimage');
+	document.getElementById("background_image_browser").innerHTML = h;
+
+	document.getElementById('text_color_pickcontainer').innerHTML = getColorPickerHTML('text_color_pick','text_color');
+	document.getElementById('background_color_pickcontainer').innerHTML = getColorPickerHTML('background_color_pick','background_color');
+	document.getElementById('border_color_top_pickcontainer').innerHTML = getColorPickerHTML('border_color_top_pick','border_color_top');
+	document.getElementById('border_color_right_pickcontainer').innerHTML = getColorPickerHTML('border_color_right_pick','border_color_right');
+	document.getElementById('border_color_bottom_pickcontainer').innerHTML = getColorPickerHTML('border_color_bottom_pick','border_color_bottom');
+	document.getElementById('border_color_left_pickcontainer').innerHTML = getColorPickerHTML('border_color_left_pick','border_color_left');
+
+	fillSelect(0, 'text_font', 'style_font', defaultFonts, ';', true);
+	fillSelect(0, 'text_size', 'style_font_size', defaultSizes, ';', true);
+	fillSelect(0, 'text_size_measurement', 'style_font_size_measurement', defaultMeasurement, ';', true);
+	fillSelect(0, 'text_case', 'style_text_case', "capitalize;uppercase;lowercase", ';', true);
+	fillSelect(0, 'text_weight', 'style_font_weight', defaultWeight, ';', true);
+	fillSelect(0, 'text_style', 'style_font_style', defaultTextStyle, ';', true);
+	fillSelect(0, 'text_variant', 'style_font_variant', defaultVariant, ';', true);
+	fillSelect(0, 'text_lineheight', 'style_font_line_height', defaultLineHeight, ';', true);
+	fillSelect(0, 'text_lineheight_measurement', 'style_font_line_height_measurement', defaultMeasurement, ';', true);
+
+	fillSelect(0, 'background_attachment', 'style_background_attachment', defaultAttachment, ';', true);
+	fillSelect(0, 'background_repeat', 'style_background_repeat', defaultRepeat, ';', true);
+
+	fillSelect(0, 'background_hpos_measurement', 'style_background_hpos_measurement', defaultMeasurement, ';', true);
+	fillSelect(0, 'background_vpos_measurement', 'style_background_vpos_measurement', defaultMeasurement, ';', true);
+
+	fillSelect(0, 'background_hpos', 'style_background_hpos', defaultPosH, ';', true);
+	fillSelect(0, 'background_vpos', 'style_background_vpos', defaultPosV, ';', true);
+
+	fillSelect(0, 'block_wordspacing', 'style_wordspacing', 'normal', ';', true);
+	fillSelect(0, 'block_wordspacing_measurement', 'style_wordspacing_measurement', defaultSpacingMeasurement, ';', true);
+	fillSelect(0, 'block_letterspacing', 'style_letterspacing', 'normal', ';', true);
+	fillSelect(0, 'block_letterspacing_measurement', 'style_letterspacing_measurement', defaultSpacingMeasurement, ';', true);
+	fillSelect(0, 'block_vertical_alignment', 'style_vertical_alignment', defaultVAlign, ';', true);
+	fillSelect(0, 'block_text_align', 'style_text_align', "left;right;center;justify", ';', true);
+	fillSelect(0, 'block_whitespace', 'style_whitespace', "normal;pre;nowrap", ';', true);
+	fillSelect(0, 'block_display', 'style_display', defaultDisplay, ';', true);
+	fillSelect(0, 'block_text_indent_measurement', 'style_text_indent_measurement', defaultIndentMeasurement, ';', true);
+
+	fillSelect(0, 'box_width_measurement', 'style_box_width_measurement', defaultMeasurement, ';', true);
+	fillSelect(0, 'box_height_measurement', 'style_box_height_measurement', defaultMeasurement, ';', true);
+	fillSelect(0, 'box_float', 'style_float', 'left;right;none', ';', true);
+	fillSelect(0, 'box_clear', 'style_clear', 'left;right;both;none', ';', true);
+	fillSelect(0, 'box_padding_left_measurement', 'style_padding_left_measurement', defaultMeasurement, ';', true);
+	fillSelect(0, 'box_padding_top_measurement', 'style_padding_top_measurement', defaultMeasurement, ';', true);
+	fillSelect(0, 'box_padding_bottom_measurement', 'style_padding_bottom_measurement', defaultMeasurement, ';', true);
+	fillSelect(0, 'box_padding_right_measurement', 'style_padding_right_measurement', defaultMeasurement, ';', true);
+	fillSelect(0, 'box_margin_left_measurement', 'style_margin_left_measurement', defaultMeasurement, ';', true);
+	fillSelect(0, 'box_margin_top_measurement', 'style_margin_top_measurement', defaultMeasurement, ';', true);
+	fillSelect(0, 'box_margin_bottom_measurement', 'style_margin_bottom_measurement', defaultMeasurement, ';', true);
+	fillSelect(0, 'box_margin_right_measurement', 'style_margin_right_measurement', defaultMeasurement, ';', true);
+
+	fillSelect(0, 'border_style_top', 'style_border_style_top', defaultBorderStyle, ';', true);
+	fillSelect(0, 'border_style_right', 'style_border_style_right', defaultBorderStyle, ';', true);
+	fillSelect(0, 'border_style_bottom', 'style_border_style_bottom', defaultBorderStyle, ';', true);
+	fillSelect(0, 'border_style_left', 'style_border_style_left', defaultBorderStyle, ';', true);
+
+	fillSelect(0, 'border_width_top', 'style_border_width_top', defaultBorderWidth, ';', true);
+	fillSelect(0, 'border_width_right', 'style_border_width_right', defaultBorderWidth, ';', true);
+	fillSelect(0, 'border_width_bottom', 'style_border_width_bottom', defaultBorderWidth, ';', true);
+	fillSelect(0, 'border_width_left', 'style_border_width_left', defaultBorderWidth, ';', true);
+
+	fillSelect(0, 'border_width_top_measurement', 'style_border_width_top_measurement', defaultMeasurement, ';', true);
+	fillSelect(0, 'border_width_right_measurement', 'style_border_width_right_measurement', defaultMeasurement, ';', true);
+	fillSelect(0, 'border_width_bottom_measurement', 'style_border_width_bottom_measurement', defaultMeasurement, ';', true);
+	fillSelect(0, 'border_width_left_measurement', 'style_border_width_left_measurement', defaultMeasurement, ';', true);
+
+	fillSelect(0, 'list_type', 'style_list_type', defaultListType, ';', true);
+	fillSelect(0, 'list_position', 'style_list_position', "inside;outside", ';', true);
+
+	fillSelect(0, 'positioning_type', 'style_positioning_type', "absolute;relative;static", ';', true);
+	fillSelect(0, 'positioning_visibility', 'style_positioning_visibility', "inherit;visible;hidden", ';', true);
+
+	fillSelect(0, 'positioning_width_measurement', 'style_positioning_width_measurement', defaultMeasurement, ';', true);
+	fillSelect(0, 'positioning_height_measurement', 'style_positioning_height_measurement', defaultMeasurement, ';', true);
+	fillSelect(0, 'positioning_overflow', 'style_positioning_overflow', "visible;hidden;scroll;auto", ';', true);
+
+	fillSelect(0, 'positioning_placement_top_measurement', 'style_positioning_placement_top_measurement', defaultMeasurement, ';', true);
+	fillSelect(0, 'positioning_placement_right_measurement', 'style_positioning_placement_right_measurement', defaultMeasurement, ';', true);
+	fillSelect(0, 'positioning_placement_bottom_measurement', 'style_positioning_placement_bottom_measurement', defaultMeasurement, ';', true);
+	fillSelect(0, 'positioning_placement_left_measurement', 'style_positioning_placement_left_measurement', defaultMeasurement, ';', true);
+
+	fillSelect(0, 'positioning_clip_top_measurement', 'style_positioning_clip_top_measurement', defaultMeasurement, ';', true);
+	fillSelect(0, 'positioning_clip_right_measurement', 'style_positioning_clip_right_measurement', defaultMeasurement, ';', true);
+	fillSelect(0, 'positioning_clip_bottom_measurement', 'style_positioning_clip_bottom_measurement', defaultMeasurement, ';', true);
+	fillSelect(0, 'positioning_clip_left_measurement', 'style_positioning_clip_left_measurement', defaultMeasurement, ';', true);
+
+	TinyMCE_EditableSelects.init();
+	setupFormData();
+	showDisabledControls();
+}
+
+function setupFormData() {
+	var ce = document.getElementById('container'), f = document.forms[0], s, b, i;
+
+	// Setup text fields
+
+	selectByValue(f, 'text_font', ce.style.fontFamily, true, true);
+	selectByValue(f, 'text_size', getNum(ce.style.fontSize), true, true);
+	selectByValue(f, 'text_size_measurement', getMeasurement(ce.style.fontSize));
+	selectByValue(f, 'text_weight', ce.style.fontWeight, true, true);
+	selectByValue(f, 'text_style', ce.style.fontStyle, true, true);
+	selectByValue(f, 'text_lineheight', getNum(ce.style.lineHeight), true, true);
+	selectByValue(f, 'text_lineheight_measurement', getMeasurement(ce.style.lineHeight));
+	selectByValue(f, 'text_case', ce.style.textTransform, true, true);
+	selectByValue(f, 'text_variant', ce.style.fontVariant, true, true);
+	f.text_color.value = ce.style.color;
+	updateColor('text_color_pick', 'text_color');
+	f.text_underline.checked = inStr(ce.style.textDecoration, 'underline');
+	f.text_overline.checked = inStr(ce.style.textDecoration, 'overline');
+	f.text_linethrough.checked = inStr(ce.style.textDecoration, 'line-through');
+	f.text_blink.checked = inStr(ce.style.textDecoration, 'blink');
+
+	// Setup background fields
+
+	f.background_color.value = ce.style.backgroundColor;
+	updateColor('background_color_pick', 'background_color');
+	f.background_image.value = ce.style.backgroundImage.replace(new RegExp("url\\('?([^']*)'?\\)", 'gi'), "$1");
+	selectByValue(f, 'background_repeat', ce.style.backgroundRepeat, true, true);
+	selectByValue(f, 'background_attachment', ce.style.backgroundAttachment, true, true);
+	selectByValue(f, 'background_hpos', getNum(getVal(ce.style.backgroundPosition, 0)), true, true);
+	selectByValue(f, 'background_hpos_measurement', getMeasurement(getVal(ce.style.backgroundPosition, 0)));
+	selectByValue(f, 'background_vpos', getNum(getVal(ce.style.backgroundPosition, 1)), true, true);
+	selectByValue(f, 'background_vpos_measurement', getMeasurement(getVal(ce.style.backgroundPosition, 1)));
+
+	// Setup block fields
+
+	selectByValue(f, 'block_wordspacing', getNum(ce.style.wordSpacing), true, true);
+	selectByValue(f, 'block_wordspacing_measurement', getMeasurement(ce.style.wordSpacing));
+	selectByValue(f, 'block_letterspacing', getNum(ce.style.letterSpacing), true, true);
+	selectByValue(f, 'block_letterspacing_measurement', getMeasurement(ce.style.letterSpacing));
+	selectByValue(f, 'block_vertical_alignment', ce.style.verticalAlign, true, true);
+	selectByValue(f, 'block_text_align', ce.style.textAlign, true, true);
+	f.block_text_indent.value = getNum(ce.style.textIndent);
+	selectByValue(f, 'block_text_indent_measurement', getMeasurement(ce.style.textIndent));
+	selectByValue(f, 'block_whitespace', ce.style.whiteSpace, true, true);
+	selectByValue(f, 'block_display', ce.style.display, true, true);
+
+	// Setup box fields
+
+	f.box_width.value = getNum(ce.style.width);
+	selectByValue(f, 'box_width_measurement', getMeasurement(ce.style.width));
+
+	f.box_height.value = getNum(ce.style.height);
+	selectByValue(f, 'box_height_measurement', getMeasurement(ce.style.height));
+
+	if (tinymce.isGecko)
+		selectByValue(f, 'box_float', ce.style.cssFloat, true, true);
+	else
+		selectByValue(f, 'box_float', ce.style.styleFloat, true, true);
+
+	selectByValue(f, 'box_clear', ce.style.clear, true, true);
+
+	setupBox(f, ce, 'box_padding', 'padding', '');
+	setupBox(f, ce, 'box_margin', 'margin', '');
+
+	// Setup border fields
+
+	setupBox(f, ce, 'border_style', 'border', 'Style');
+	setupBox(f, ce, 'border_width', 'border', 'Width');
+	setupBox(f, ce, 'border_color', 'border', 'Color');
+
+	updateColor('border_color_top_pick', 'border_color_top');
+	updateColor('border_color_right_pick', 'border_color_right');
+	updateColor('border_color_bottom_pick', 'border_color_bottom');
+	updateColor('border_color_left_pick', 'border_color_left');
+
+	// Setup list fields
+
+	selectByValue(f, 'list_type', ce.style.listStyleType, true, true);
+	selectByValue(f, 'list_position', ce.style.listStylePosition, true, true);
+	f.list_bullet_image.value = ce.style.listStyleImage.replace(new RegExp("url\\('?([^']*)'?\\)", 'gi'), "$1");
+
+	// Setup box fields
+
+	selectByValue(f, 'positioning_type', ce.style.position, true, true);
+	selectByValue(f, 'positioning_visibility', ce.style.visibility, true, true);
+	selectByValue(f, 'positioning_overflow', ce.style.overflow, true, true);
+	f.positioning_zindex.value = ce.style.zIndex ? ce.style.zIndex : "";
+
+	f.positioning_width.value = getNum(ce.style.width);
+	selectByValue(f, 'positioning_width_measurement', getMeasurement(ce.style.width));
+
+	f.positioning_height.value = getNum(ce.style.height);
+	selectByValue(f, 'positioning_height_measurement', getMeasurement(ce.style.height));
+
+	setupBox(f, ce, 'positioning_placement', '', '', new Array('top', 'right', 'bottom', 'left'));
+
+	s = ce.style.clip.replace(new RegExp("rect\\('?([^']*)'?\\)", 'gi'), "$1");
+	s = s.replace(/,/g, ' ');
+
+	if (!hasEqualValues(new Array(getVal(s, 0), getVal(s, 1), getVal(s, 2), getVal(s, 3)))) {
+		f.positioning_clip_top.value = getNum(getVal(s, 0));
+		selectByValue(f, 'positioning_clip_top_measurement', getMeasurement(getVal(s, 0)));
+		f.positioning_clip_right.value = getNum(getVal(s, 1));
+		selectByValue(f, 'positioning_clip_right_measurement', getMeasurement(getVal(s, 1)));
+		f.positioning_clip_bottom.value = getNum(getVal(s, 2));
+		selectByValue(f, 'positioning_clip_bottom_measurement', getMeasurement(getVal(s, 2)));
+		f.positioning_clip_left.value = getNum(getVal(s, 3));
+		selectByValue(f, 'positioning_clip_left_measurement', getMeasurement(getVal(s, 3)));
+	} else {
+		f.positioning_clip_top.value = getNum(getVal(s, 0));
+		selectByValue(f, 'positioning_clip_top_measurement', getMeasurement(getVal(s, 0)));
+		f.positioning_clip_right.value = f.positioning_clip_bottom.value = f.positioning_clip_left.value;
+	}
+
+//	setupBox(f, ce, '', 'border', 'Color');
+}
+
+function getMeasurement(s) {
+	return s.replace(/^([0-9]+)(.*)$/, "$2");
+}
+
+function getNum(s) {
+	if (new RegExp('^[0-9]+[a-z%]+$', 'gi').test(s))
+		return s.replace(/[^0-9]/g, '');
+
+	return s;
+}
+
+function inStr(s, n) {
+	return new RegExp(n, 'gi').test(s);
+}
+
+function getVal(s, i) {
+	var a = s.split(' ');
+
+	if (a.length > 1)
+		return a[i];
+
+	return "";
+}
+
+function setValue(f, n, v) {
+	if (f.elements[n].type == "text")
+		f.elements[n].value = v;
+	else
+		selectByValue(f, n, v, true, true);
+}
+
+function setupBox(f, ce, fp, pr, sf, b) {
+	if (typeof(b) == "undefined")
+		b = new Array('Top', 'Right', 'Bottom', 'Left');
+
+	if (isSame(ce, pr, sf, b)) {
+		f.elements[fp + "_same"].checked = true;
+
+		setValue(f, fp + "_top", getNum(ce.style[pr + b[0] + sf]));
+		f.elements[fp + "_top"].disabled = false;
+
+		f.elements[fp + "_right"].value = "";
+		f.elements[fp + "_right"].disabled = true;
+		f.elements[fp + "_bottom"].value = "";
+		f.elements[fp + "_bottom"].disabled = true;
+		f.elements[fp + "_left"].value = "";
+		f.elements[fp + "_left"].disabled = true;
+
+		if (f.elements[fp + "_top_measurement"]) {
+			selectByValue(f, fp + '_top_measurement', getMeasurement(ce.style[pr + b[0] + sf]));
+			f.elements[fp + "_left_measurement"].disabled = true;
+			f.elements[fp + "_bottom_measurement"].disabled = true;
+			f.elements[fp + "_right_measurement"].disabled = true;
+		}
+	} else {
+		f.elements[fp + "_same"].checked = false;
+
+		setValue(f, fp + "_top", getNum(ce.style[pr + b[0] + sf]));
+		f.elements[fp + "_top"].disabled = false;
+
+		setValue(f, fp + "_right", getNum(ce.style[pr + b[1] + sf]));
+		f.elements[fp + "_right"].disabled = false;
+
+		setValue(f, fp + "_bottom", getNum(ce.style[pr + b[2] + sf]));
+		f.elements[fp + "_bottom"].disabled = false;
+
+		setValue(f, fp + "_left", getNum(ce.style[pr + b[3] + sf]));
+		f.elements[fp + "_left"].disabled = false;
+
+		if (f.elements[fp + "_top_measurement"]) {
+			selectByValue(f, fp + '_top_measurement', getMeasurement(ce.style[pr + b[0] + sf]));
+			selectByValue(f, fp + '_right_measurement', getMeasurement(ce.style[pr + b[1] + sf]));
+			selectByValue(f, fp + '_bottom_measurement', getMeasurement(ce.style[pr + b[2] + sf]));
+			selectByValue(f, fp + '_left_measurement', getMeasurement(ce.style[pr + b[3] + sf]));
+			f.elements[fp + "_left_measurement"].disabled = false;
+			f.elements[fp + "_bottom_measurement"].disabled = false;
+			f.elements[fp + "_right_measurement"].disabled = false;
+		}
+	}
+}
+
+function isSame(e, pr, sf, b) {
+	var a = new Array(), i, x;
+
+	if (typeof(b) == "undefined")
+		b = new Array('Top', 'Right', 'Bottom', 'Left');
+
+	if (typeof(sf) == "undefined" || sf == null)
+		sf = "";
+
+	a[0] = e.style[pr + b[0] + sf];
+	a[1] = e.style[pr + b[1] + sf];
+	a[2] = e.style[pr + b[2] + sf];
+	a[3] = e.style[pr + b[3] + sf];
+
+	for (i=0; i<a.length; i++) {
+		if (a[i] == null)
+			return false;
+
+		for (x=0; x<a.length; x++) {
+			if (a[x] != a[i])
+				return false;
+		}
+	}
+
+	return true;
+};
+
+function hasEqualValues(a) {
+	var i, x;
+
+	for (i=0; i<a.length; i++) {
+		if (a[i] == null)
+			return false;
+
+		for (x=0; x<a.length; x++) {
+			if (a[x] != a[i])
+				return false;
+		}
+	}
+
+	return true;
+}
+
+function applyAction() {
+	var ce = document.getElementById('container'), ed = tinyMCEPopup.editor;
+
+	generateCSS();
+
+	tinyMCEPopup.restoreSelection();
+	ed.dom.setAttrib(ed.selection.getNode(), 'style', tinyMCEPopup.editor.dom.serializeStyle(tinyMCEPopup.editor.dom.parseStyle(ce.style.cssText)));
+}
+
+function updateAction() {
+	applyAction();
+	tinyMCEPopup.close();
+}
+
+function generateCSS() {
+	var ce = document.getElementById('container'), f = document.forms[0], num = new RegExp('[0-9]+', 'g'), s, t;
+
+	ce.style.cssText = "";
+
+	// Build text styles
+	ce.style.fontFamily = f.text_font.value;
+	ce.style.fontSize = f.text_size.value + (isNum(f.text_size.value) ? (f.text_size_measurement.value || 'px') : "");
+	ce.style.fontStyle = f.text_style.value;
+	ce.style.lineHeight = f.text_lineheight.value + (isNum(f.text_lineheight.value) ? f.text_lineheight_measurement.value : "");
+	ce.style.textTransform = f.text_case.value;
+	ce.style.fontWeight = f.text_weight.value;
+	ce.style.fontVariant = f.text_variant.value;
+	ce.style.color = f.text_color.value;
+
+	s = "";
+	s += f.text_underline.checked ? " underline" : "";
+	s += f.text_overline.checked ? " overline" : "";
+	s += f.text_linethrough.checked ? " line-through" : "";
+	s += f.text_blink.checked ? " blink" : "";
+	s = s.length > 0 ? s.substring(1) : s;
+
+	if (f.text_none.checked)
+		s = "none";
+
+	ce.style.textDecoration = s;
+
+	// Build background styles
+
+	ce.style.backgroundColor = f.background_color.value;
+	ce.style.backgroundImage = f.background_image.value != "" ? "url(" + f.background_image.value + ")" : "";
+	ce.style.backgroundRepeat = f.background_repeat.value;
+	ce.style.backgroundAttachment = f.background_attachment.value;
+
+	if (f.background_hpos.value != "") {
+		s = "";
+		s += f.background_hpos.value + (isNum(f.background_hpos.value) ? f.background_hpos_measurement.value : "") + " ";
+		s += f.background_vpos.value + (isNum(f.background_vpos.value) ? f.background_vpos_measurement.value : "");
+		ce.style.backgroundPosition = s;
+	}
+
+	// Build block styles
+
+	ce.style.wordSpacing = f.block_wordspacing.value + (isNum(f.block_wordspacing.value) ? f.block_wordspacing_measurement.value : "");
+	ce.style.letterSpacing = f.block_letterspacing.value + (isNum(f.block_letterspacing.value) ? f.block_letterspacing_measurement.value : "");
+	ce.style.verticalAlign = f.block_vertical_alignment.value;
+	ce.style.textAlign = f.block_text_align.value;
+	ce.style.textIndent = f.block_text_indent.value + (isNum(f.block_text_indent.value) ? f.block_text_indent_measurement.value : "");
+	ce.style.whiteSpace = f.block_whitespace.value;
+	ce.style.display = f.block_display.value;
+
+	// Build box styles
+
+	ce.style.width = f.box_width.value + (isNum(f.box_width.value) ? f.box_width_measurement.value : "");
+	ce.style.height = f.box_height.value + (isNum(f.box_height.value) ? f.box_height_measurement.value : "");
+	ce.style.styleFloat = f.box_float.value;
+
+	if (tinymce.isGecko)
+		ce.style.cssFloat = f.box_float.value;
+
+	ce.style.clear = f.box_clear.value;
+
+	if (!f.box_padding_same.checked) {
+		ce.style.paddingTop = f.box_padding_top.value + (isNum(f.box_padding_top.value) ? f.box_padding_top_measurement.value : "");
+		ce.style.paddingRight = f.box_padding_right.value + (isNum(f.box_padding_right.value) ? f.box_padding_right_measurement.value : "");
+		ce.style.paddingBottom = f.box_padding_bottom.value + (isNum(f.box_padding_bottom.value) ? f.box_padding_bottom_measurement.value : "");
+		ce.style.paddingLeft = f.box_padding_left.value + (isNum(f.box_padding_left.value) ? f.box_padding_left_measurement.value : "");
+	} else
+		ce.style.padding = f.box_padding_top.value + (isNum(f.box_padding_top.value) ? f.box_padding_top_measurement.value : "");		
+
+	if (!f.box_margin_same.checked) {
+		ce.style.marginTop = f.box_margin_top.value + (isNum(f.box_margin_top.value) ? f.box_margin_top_measurement.value : "");
+		ce.style.marginRight = f.box_margin_right.value + (isNum(f.box_margin_right.value) ? f.box_margin_right_measurement.value : "");
+		ce.style.marginBottom = f.box_margin_bottom.value + (isNum(f.box_margin_bottom.value) ? f.box_margin_bottom_measurement.value : "");
+		ce.style.marginLeft = f.box_margin_left.value + (isNum(f.box_margin_left.value) ? f.box_margin_left_measurement.value : "");
+	} else
+		ce.style.margin = f.box_margin_top.value + (isNum(f.box_margin_top.value) ? f.box_margin_top_measurement.value : "");		
+
+	// Build border styles
+
+	if (!f.border_style_same.checked) {
+		ce.style.borderTopStyle = f.border_style_top.value;
+		ce.style.borderRightStyle = f.border_style_right.value;
+		ce.style.borderBottomStyle = f.border_style_bottom.value;
+		ce.style.borderLeftStyle = f.border_style_left.value;
+	} else
+		ce.style.borderStyle = f.border_style_top.value;
+
+	if (!f.border_width_same.checked) {
+		ce.style.borderTopWidth = f.border_width_top.value + (isNum(f.border_width_top.value) ? f.border_width_top_measurement.value : "");
+		ce.style.borderRightWidth = f.border_width_right.value + (isNum(f.border_width_right.value) ? f.border_width_right_measurement.value : "");
+		ce.style.borderBottomWidth = f.border_width_bottom.value + (isNum(f.border_width_bottom.value) ? f.border_width_bottom_measurement.value : "");
+		ce.style.borderLeftWidth = f.border_width_left.value + (isNum(f.border_width_left.value) ? f.border_width_left_measurement.value : "");
+	} else
+		ce.style.borderWidth = f.border_width_top.value;
+
+	if (!f.border_color_same.checked) {
+		ce.style.borderTopColor = f.border_color_top.value;
+		ce.style.borderRightColor = f.border_color_right.value;
+		ce.style.borderBottomColor = f.border_color_bottom.value;
+		ce.style.borderLeftColor = f.border_color_left.value;
+	} else
+		ce.style.borderColor = f.border_color_top.value;
+
+	// Build list styles
+
+	ce.style.listStyleType = f.list_type.value;
+	ce.style.listStylePosition = f.list_position.value;
+	ce.style.listStyleImage = f.list_bullet_image.value != "" ? "url(" + f.list_bullet_image.value + ")" : "";
+
+	// Build positioning styles
+
+	ce.style.position = f.positioning_type.value;
+	ce.style.visibility = f.positioning_visibility.value;
+
+	if (ce.style.width == "")
+		ce.style.width = f.positioning_width.value + (isNum(f.positioning_width.value) ? f.positioning_width_measurement.value : "");
+
+	if (ce.style.height == "")
+		ce.style.height = f.positioning_height.value + (isNum(f.positioning_height.value) ? f.positioning_height_measurement.value : "");
+
+	ce.style.zIndex = f.positioning_zindex.value;
+	ce.style.overflow = f.positioning_overflow.value;
+
+	if (!f.positioning_placement_same.checked) {
+		ce.style.top = f.positioning_placement_top.value + (isNum(f.positioning_placement_top.value) ? f.positioning_placement_top_measurement.value : "");
+		ce.style.right = f.positioning_placement_right.value + (isNum(f.positioning_placement_right.value) ? f.positioning_placement_right_measurement.value : "");
+		ce.style.bottom = f.positioning_placement_bottom.value + (isNum(f.positioning_placement_bottom.value) ? f.positioning_placement_bottom_measurement.value : "");
+		ce.style.left = f.positioning_placement_left.value + (isNum(f.positioning_placement_left.value) ? f.positioning_placement_left_measurement.value : "");
+	} else {
+		s = f.positioning_placement_top.value + (isNum(f.positioning_placement_top.value) ? f.positioning_placement_top_measurement.value : "");
+		ce.style.top = s;
+		ce.style.right = s;
+		ce.style.bottom = s;
+		ce.style.left = s;
+	}
+
+	if (!f.positioning_clip_same.checked) {
+		s = "rect(";
+		s += (isNum(f.positioning_clip_top.value) ? f.positioning_clip_top.value + f.positioning_clip_top_measurement.value : "auto") + " ";
+		s += (isNum(f.positioning_clip_right.value) ? f.positioning_clip_right.value + f.positioning_clip_right_measurement.value : "auto") + " ";
+		s += (isNum(f.positioning_clip_bottom.value) ? f.positioning_clip_bottom.value + f.positioning_clip_bottom_measurement.value : "auto") + " ";
+		s += (isNum(f.positioning_clip_left.value) ? f.positioning_clip_left.value + f.positioning_clip_left_measurement.value : "auto");
+		s += ")";
+
+		if (s != "rect(auto auto auto auto)")
+			ce.style.clip = s;
+	} else {
+		s = "rect(";
+		t = isNum(f.positioning_clip_top.value) ? f.positioning_clip_top.value + f.positioning_clip_top_measurement.value : "auto";
+		s += t + " ";
+		s += t + " ";
+		s += t + " ";
+		s += t + ")";
+
+		if (s != "rect(auto auto auto auto)")
+			ce.style.clip = s;
+	}
+
+	ce.style.cssText = ce.style.cssText;
+}
+
+function isNum(s) {
+	return new RegExp('[0-9]+', 'g').test(s);
+}
+
+function showDisabledControls() {
+	var f = document.forms, i, a;
+
+	for (i=0; i<f.length; i++) {
+		for (a=0; a<f[i].elements.length; a++) {
+			if (f[i].elements[a].disabled)
+				tinyMCEPopup.editor.dom.addClass(f[i].elements[a], "disabled");
+			else
+				tinyMCEPopup.editor.dom.removeClass(f[i].elements[a], "disabled");
+		}
+	}
+}
+
+function fillSelect(f, s, param, dval, sep, em) {
+	var i, ar, p, se;
+
+	f = document.forms[f];
+	sep = typeof(sep) == "undefined" ? ";" : sep;
+
+	if (em)
+		addSelectValue(f, s, "", "");
+
+	ar = tinyMCEPopup.getParam(param, dval).split(sep);
+	for (i=0; i<ar.length; i++) {
+		se = false;
+
+		if (ar[i].charAt(0) == '+') {
+			ar[i] = ar[i].substring(1);
+			se = true;
+		}
+
+		p = ar[i].split('=');
+
+		if (p.length > 1) {
+			addSelectValue(f, s, p[0], p[1]);
+
+			if (se)
+				selectByValue(f, s, p[1]);
+		} else {
+			addSelectValue(f, s, p[0], p[0]);
+
+			if (se)
+				selectByValue(f, s, p[0]);
+		}
+	}
+}
+
+function toggleSame(ce, pre) {
+	var el = document.forms[0].elements, i;
+
+	if (ce.checked) {
+		el[pre + "_top"].disabled = false;
+		el[pre + "_right"].disabled = true;
+		el[pre + "_bottom"].disabled = true;
+		el[pre + "_left"].disabled = true;
+
+		if (el[pre + "_top_measurement"]) {
+			el[pre + "_top_measurement"].disabled = false;
+			el[pre + "_right_measurement"].disabled = true;
+			el[pre + "_bottom_measurement"].disabled = true;
+			el[pre + "_left_measurement"].disabled = true;
+		}
+	} else {
+		el[pre + "_top"].disabled = false;
+		el[pre + "_right"].disabled = false;
+		el[pre + "_bottom"].disabled = false;
+		el[pre + "_left"].disabled = false;
+
+		if (el[pre + "_top_measurement"]) {
+			el[pre + "_top_measurement"].disabled = false;
+			el[pre + "_right_measurement"].disabled = false;
+			el[pre + "_bottom_measurement"].disabled = false;
+			el[pre + "_left_measurement"].disabled = false;
+		}
+	}
+
+	showDisabledControls();
+}
+
+function synch(fr, to) {
+	var f = document.forms[0];
+
+	f.elements[to].value = f.elements[fr].value;
+
+	if (f.elements[fr + "_measurement"])
+		selectByValue(f, to + "_measurement", f.elements[fr + "_measurement"].value);
+}
+
+tinyMCEPopup.onInit.add(init);
--- a/includes/clientside/tinymce/plugins/style/jscripts/props.js	Fri Feb 22 12:46:51 2008 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,633 +0,0 @@
-var defaultFonts = "" + 
-	"Arial, Helvetica, sans-serif=Arial, Helvetica, sans-serif;" + 
-	"Times New Roman, Times, serif=Times New Roman, Times, serif;" + 
-	"Courier New, Courier, mono=Courier New, Courier, mono;" + 
-	"Times New Roman, Times, serif=Times New Roman, Times, serif;" + 
-	"Georgia, Times New Roman, Times, serif=Georgia, Times New Roman, Times, serif;" + 
-	"Verdana, Arial, Helvetica, sans-serif=Verdana, Arial, Helvetica, sans-serif;" + 
-	"Geneva, Arial, Helvetica, sans-serif=Geneva, Arial, Helvetica, sans-serif";
-
-var defaultSizes = "9;10;12;14;16;18;24;xx-small;x-small;small;medium;large;x-large;xx-large;smaller;larger";
-var defaultMeasurement = "+pixels=px;points=pt;in;cm;mm;picas;ems;exs;%";
-var defaultSpacingMeasurement = "pixels=px;points=pt;in;cm;mm;picas;+ems;exs;%";
-var defaultIndentMeasurement = "pixels=px;+points=pt;in;cm;mm;picas;ems;exs;%";
-var defaultWeight = "normal;bold;bolder;lighter;100;200;300;400;500;600;700;800;900";
-var defaultTextStyle = "normal;italic;oblique";
-var defaultVariant = "normal;small-caps";
-var defaultLineHeight = "normal";
-var defaultAttachment = "fixed;scroll";
-var defaultRepeat = "no-repeat;repeat;repeat-x;repeat-y";
-var defaultPosH = "left;center;right";
-var defaultPosV = "top;center;bottom";
-var defaultVAlign = "baseline;sub;super;top;text-top;middle;bottom;text-bottom";
-var defaultDisplay = "inline;block;list-item;run-in;compact;marker;table;inline-table;table-row-group;table-header-group;table-footer-group;table-row;table-column-group;table-column;table-cell;table-caption;none";
-var defaultBorderStyle = "none;solid;dashed;dotted;double;groove;ridge;inset;outset";
-var defaultBorderWidth = "thin;medium;thick";
-var defaultListType = "disc;circle;square;decimal;lower-roman;upper-roman;lower-alpha;upper-alpha;none";
-
-function init() {
-	var ce = document.getElementById('container'), h;
-
-	ce.style.cssText = tinyMCEPopup.getWindowArg('style_text');
-
-	h = getBrowserHTML('background_image_browser','background_image','image','advimage');
-	document.getElementById("background_image_browser").innerHTML = h;
-
-	tinyMCEPopup.resizeToInnerSize();
-
-	document.getElementById('text_color_pickcontainer').innerHTML = getColorPickerHTML('text_color_pick','text_color');
-	document.getElementById('background_color_pickcontainer').innerHTML = getColorPickerHTML('background_color_pick','background_color');
-	document.getElementById('border_color_top_pickcontainer').innerHTML = getColorPickerHTML('border_color_top_pick','border_color_top');
-	document.getElementById('border_color_right_pickcontainer').innerHTML = getColorPickerHTML('border_color_right_pick','border_color_right');
-	document.getElementById('border_color_bottom_pickcontainer').innerHTML = getColorPickerHTML('border_color_bottom_pick','border_color_bottom');
-	document.getElementById('border_color_left_pickcontainer').innerHTML = getColorPickerHTML('border_color_left_pick','border_color_left');
-
-	fillSelect(0, 'text_font', 'style_font', defaultFonts, ';', true);
-	fillSelect(0, 'text_size', 'style_font_size', defaultSizes, ';', true);
-	fillSelect(0, 'text_size_measurement', 'style_font_size_measurement', defaultMeasurement, ';', true);
-	fillSelect(0, 'text_case', 'style_text_case', "capitalize;uppercase;lowercase", ';', true);
-	fillSelect(0, 'text_weight', 'style_font_weight', defaultWeight, ';', true);
-	fillSelect(0, 'text_style', 'style_font_style', defaultTextStyle, ';', true);
-	fillSelect(0, 'text_variant', 'style_font_variant', defaultVariant, ';', true);
-	fillSelect(0, 'text_lineheight', 'style_font_line_height', defaultLineHeight, ';', true);
-	fillSelect(0, 'text_lineheight_measurement', 'style_font_line_height_measurement', defaultMeasurement, ';', true);
-
-	fillSelect(0, 'background_attachment', 'style_background_attachment', defaultAttachment, ';', true);
-	fillSelect(0, 'background_repeat', 'style_background_repeat', defaultRepeat, ';', true);
-
-	fillSelect(0, 'background_hpos_measurement', 'style_background_hpos_measurement', defaultMeasurement, ';', true);
-	fillSelect(0, 'background_vpos_measurement', 'style_background_vpos_measurement', defaultMeasurement, ';', true);
-
-	fillSelect(0, 'background_hpos', 'style_background_hpos', defaultPosH, ';', true);
-	fillSelect(0, 'background_vpos', 'style_background_vpos', defaultPosV, ';', true);
-
-	fillSelect(0, 'block_wordspacing', 'style_wordspacing', 'normal', ';', true);
-	fillSelect(0, 'block_wordspacing_measurement', 'style_wordspacing_measurement', defaultSpacingMeasurement, ';', true);
-	fillSelect(0, 'block_letterspacing', 'style_letterspacing', 'normal', ';', true);
-	fillSelect(0, 'block_letterspacing_measurement', 'style_letterspacing_measurement', defaultSpacingMeasurement, ';', true);
-	fillSelect(0, 'block_vertical_alignment', 'style_vertical_alignment', defaultVAlign, ';', true);
-	fillSelect(0, 'block_text_align', 'style_text_align', "left;right;center;justify", ';', true);
-	fillSelect(0, 'block_whitespace', 'style_whitespace', "normal;pre;nowrap", ';', true);
-	fillSelect(0, 'block_display', 'style_display', defaultDisplay, ';', true);
-	fillSelect(0, 'block_text_indent_measurement', 'style_text_indent_measurement', defaultIndentMeasurement, ';', true);
-
-	fillSelect(0, 'box_width_measurement', 'style_box_width_measurement', defaultMeasurement, ';', true);
-	fillSelect(0, 'box_height_measurement', 'style_box_height_measurement', defaultMeasurement, ';', true);
-	fillSelect(0, 'box_float', 'style_float', 'left;right;none', ';', true);
-	fillSelect(0, 'box_clear', 'style_clear', 'left;right;both;none', ';', true);
-	fillSelect(0, 'box_padding_left_measurement', 'style_padding_left_measurement', defaultMeasurement, ';', true);
-	fillSelect(0, 'box_padding_top_measurement', 'style_padding_top_measurement', defaultMeasurement, ';', true);
-	fillSelect(0, 'box_padding_bottom_measurement', 'style_padding_bottom_measurement', defaultMeasurement, ';', true);
-	fillSelect(0, 'box_padding_right_measurement', 'style_padding_right_measurement', defaultMeasurement, ';', true);
-	fillSelect(0, 'box_margin_left_measurement', 'style_margin_left_measurement', defaultMeasurement, ';', true);
-	fillSelect(0, 'box_margin_top_measurement', 'style_margin_top_measurement', defaultMeasurement, ';', true);
-	fillSelect(0, 'box_margin_bottom_measurement', 'style_margin_bottom_measurement', defaultMeasurement, ';', true);
-	fillSelect(0, 'box_margin_right_measurement', 'style_margin_right_measurement', defaultMeasurement, ';', true);
-
-	fillSelect(0, 'border_style_top', 'style_border_style_top', defaultBorderStyle, ';', true);
-	fillSelect(0, 'border_style_right', 'style_border_style_right', defaultBorderStyle, ';', true);
-	fillSelect(0, 'border_style_bottom', 'style_border_style_bottom', defaultBorderStyle, ';', true);
-	fillSelect(0, 'border_style_left', 'style_border_style_left', defaultBorderStyle, ';', true);
-
-	fillSelect(0, 'border_width_top', 'style_border_width_top', defaultBorderWidth, ';', true);
-	fillSelect(0, 'border_width_right', 'style_border_width_right', defaultBorderWidth, ';', true);
-	fillSelect(0, 'border_width_bottom', 'style_border_width_bottom', defaultBorderWidth, ';', true);
-	fillSelect(0, 'border_width_left', 'style_border_width_left', defaultBorderWidth, ';', true);
-
-	fillSelect(0, 'border_width_top_measurement', 'style_border_width_top_measurement', defaultMeasurement, ';', true);
-	fillSelect(0, 'border_width_right_measurement', 'style_border_width_right_measurement', defaultMeasurement, ';', true);
-	fillSelect(0, 'border_width_bottom_measurement', 'style_border_width_bottom_measurement', defaultMeasurement, ';', true);
-	fillSelect(0, 'border_width_left_measurement', 'style_border_width_left_measurement', defaultMeasurement, ';', true);
-
-	fillSelect(0, 'list_type', 'style_list_type', defaultListType, ';', true);
-	fillSelect(0, 'list_position', 'style_list_position', "inside;outside", ';', true);
-
-	fillSelect(0, 'positioning_type', 'style_positioning_type', "absolute;relative;static", ';', true);
-	fillSelect(0, 'positioning_visibility', 'style_positioning_visibility', "inherit;visible;hidden", ';', true);
-
-	fillSelect(0, 'positioning_width_measurement', 'style_positioning_width_measurement', defaultMeasurement, ';', true);
-	fillSelect(0, 'positioning_height_measurement', 'style_positioning_height_measurement', defaultMeasurement, ';', true);
-	fillSelect(0, 'positioning_overflow', 'style_positioning_overflow', "visible;hidden;scroll;auto", ';', true);
-
-	fillSelect(0, 'positioning_placement_top_measurement', 'style_positioning_placement_top_measurement', defaultMeasurement, ';', true);
-	fillSelect(0, 'positioning_placement_right_measurement', 'style_positioning_placement_right_measurement', defaultMeasurement, ';', true);
-	fillSelect(0, 'positioning_placement_bottom_measurement', 'style_positioning_placement_bottom_measurement', defaultMeasurement, ';', true);
-	fillSelect(0, 'positioning_placement_left_measurement', 'style_positioning_placement_left_measurement', defaultMeasurement, ';', true);
-
-	fillSelect(0, 'positioning_clip_top_measurement', 'style_positioning_clip_top_measurement', defaultMeasurement, ';', true);
-	fillSelect(0, 'positioning_clip_right_measurement', 'style_positioning_clip_right_measurement', defaultMeasurement, ';', true);
-	fillSelect(0, 'positioning_clip_bottom_measurement', 'style_positioning_clip_bottom_measurement', defaultMeasurement, ';', true);
-	fillSelect(0, 'positioning_clip_left_measurement', 'style_positioning_clip_left_measurement', defaultMeasurement, ';', true);
-
-	TinyMCE_EditableSelects.init();
-	setupFormData();
-	showDisabledControls();
-}
-
-function setupFormData() {
-	var ce = document.getElementById('container'), f = document.forms[0], s, b, i;
-
-	// Setup text fields
-
-	selectByValue(f, 'text_font', ce.style.fontFamily, true, true);
-	selectByValue(f, 'text_size', getNum(ce.style.fontSize), true, true);
-	selectByValue(f, 'text_size_measurement', getMeasurement(ce.style.fontSize));
-	selectByValue(f, 'text_weight', ce.style.fontWeight, true, true);
-	selectByValue(f, 'text_style', ce.style.fontStyle, true, true);
-	selectByValue(f, 'text_lineheight', getNum(ce.style.lineHeight), true, true);
-	selectByValue(f, 'text_lineheight_measurement', getMeasurement(ce.style.lineHeight));
-	selectByValue(f, 'text_case', ce.style.textTransform, true, true);
-	selectByValue(f, 'text_variant', ce.style.fontVariant, true, true);
-	f.text_color.value = ce.style.color;
-	updateColor('text_color_pick', 'text_color');
-	f.text_underline.checked = inStr(ce.style.textDecoration, 'underline');
-	f.text_overline.checked = inStr(ce.style.textDecoration, 'overline');
-	f.text_linethrough.checked = inStr(ce.style.textDecoration, 'line-through');
-	f.text_blink.checked = inStr(ce.style.textDecoration, 'blink');
-
-	// Setup background fields
-
-	f.background_color.value = ce.style.backgroundColor;
-	updateColor('background_color_pick', 'background_color');
-	f.background_image.value = ce.style.backgroundImage.replace(new RegExp("url\\('?([^']*)'?\\)", 'gi'), "$1");
-	selectByValue(f, 'background_repeat', ce.style.backgroundRepeat, true, true);
-	selectByValue(f, 'background_attachment', ce.style.backgroundAttachment, true, true);
-	selectByValue(f, 'background_hpos', getNum(getVal(ce.style.backgroundPosition, 0)), true, true);
-	selectByValue(f, 'background_hpos_measurement', getMeasurement(getVal(ce.style.backgroundPosition, 0)));
-	selectByValue(f, 'background_vpos', getNum(getVal(ce.style.backgroundPosition, 1)), true, true);
-	selectByValue(f, 'background_vpos_measurement', getMeasurement(getVal(ce.style.backgroundPosition, 1)));
-
-	// Setup block fields
-
-	selectByValue(f, 'block_wordspacing', getNum(ce.style.wordSpacing), true, true);
-	selectByValue(f, 'block_wordspacing_measurement', getMeasurement(ce.style.wordSpacing));
-	selectByValue(f, 'block_letterspacing', getNum(ce.style.letterSpacing), true, true);
-	selectByValue(f, 'block_letterspacing_measurement', getMeasurement(ce.style.letterSpacing));
-	selectByValue(f, 'block_vertical_alignment', ce.style.verticalAlign, true, true);
-	selectByValue(f, 'block_text_align', ce.style.textAlign, true, true);
-	f.block_text_indent.value = getNum(ce.style.textIndent);
-	selectByValue(f, 'block_text_indent_measurement', getMeasurement(ce.style.textIndent));
-	selectByValue(f, 'block_whitespace', ce.style.whiteSpace, true, true);
-	selectByValue(f, 'block_display', ce.style.display, true, true);
-
-	// Setup box fields
-
-	f.box_width.value = getNum(ce.style.width);
-	selectByValue(f, 'box_width_measurement', getMeasurement(ce.style.width));
-
-	f.box_height.value = getNum(ce.style.height);
-	selectByValue(f, 'box_height_measurement', getMeasurement(ce.style.height));
-
-	if (tinyMCE.isGecko)
-		selectByValue(f, 'box_float', ce.style.cssFloat, true, true);
-	else
-		selectByValue(f, 'box_float', ce.style.styleFloat, true, true);
-
-	selectByValue(f, 'box_clear', ce.style.clear, true, true);
-
-	setupBox(f, ce, 'box_padding', 'padding', '');
-	setupBox(f, ce, 'box_margin', 'margin', '');
-
-	// Setup border fields
-
-	setupBox(f, ce, 'border_style', 'border', 'Style');
-	setupBox(f, ce, 'border_width', 'border', 'Width');
-	setupBox(f, ce, 'border_color', 'border', 'Color');
-
-	updateColor('border_color_top_pick', 'border_color_top');
-	updateColor('border_color_right_pick', 'border_color_right');
-	updateColor('border_color_bottom_pick', 'border_color_bottom');
-	updateColor('border_color_left_pick', 'border_color_left');
-
-	// Setup list fields
-
-	selectByValue(f, 'list_type', ce.style.listStyleType, true, true);
-	selectByValue(f, 'list_position', ce.style.listStylePosition, true, true);
-	f.list_bullet_image.value = ce.style.listStyleImage.replace(new RegExp("url\\('?([^']*)'?\\)", 'gi'), "$1");
-
-	// Setup box fields
-
-	selectByValue(f, 'positioning_type', ce.style.position, true, true);
-	selectByValue(f, 'positioning_visibility', ce.style.visibility, true, true);
-	selectByValue(f, 'positioning_overflow', ce.style.overflow, true, true);
-	f.positioning_zindex.value = ce.style.zIndex ? ce.style.zIndex : "";
-
-	f.positioning_width.value = getNum(ce.style.width);
-	selectByValue(f, 'positioning_width_measurement', getMeasurement(ce.style.width));
-
-	f.positioning_height.value = getNum(ce.style.height);
-	selectByValue(f, 'positioning_height_measurement', getMeasurement(ce.style.height));
-
-	setupBox(f, ce, 'positioning_placement', '', '', new Array('top', 'right', 'bottom', 'left'));
-
-	s = ce.style.clip.replace(new RegExp("rect\\('?([^']*)'?\\)", 'gi'), "$1");
-	s = s.replace(/,/g, ' ');
-
-	if (!hasEqualValues(new Array(getVal(s, 0), getVal(s, 1), getVal(s, 2), getVal(s, 3)))) {
-		f.positioning_clip_top.value = getNum(getVal(s, 0));
-		selectByValue(f, 'positioning_clip_top_measurement', getMeasurement(getVal(s, 0)));
-		f.positioning_clip_right.value = getNum(getVal(s, 1));
-		selectByValue(f, 'positioning_clip_right_measurement', getMeasurement(getVal(s, 1)));
-		f.positioning_clip_bottom.value = getNum(getVal(s, 2));
-		selectByValue(f, 'positioning_clip_bottom_measurement', getMeasurement(getVal(s, 2)));
-		f.positioning_clip_left.value = getNum(getVal(s, 3));
-		selectByValue(f, 'positioning_clip_left_measurement', getMeasurement(getVal(s, 3)));
-	} else {
-		f.positioning_clip_top.value = getNum(getVal(s, 0));
-		selectByValue(f, 'positioning_clip_top_measurement', getMeasurement(getVal(s, 0)));
-		f.positioning_clip_right.value = f.positioning_clip_bottom.value = f.positioning_clip_left.value;
-	}
-
-//	setupBox(f, ce, '', 'border', 'Color');
-}
-
-function getMeasurement(s) {
-	return s.replace(/^([0-9]+)(.*)$/, "$2");
-}
-
-function getNum(s) {
-	if (new RegExp('^[0-9]+[a-z%]+$', 'gi').test(s))
-		return s.replace(/[^0-9]/g, '');
-
-	return s;
-}
-
-function inStr(s, n) {
-	return new RegExp(n, 'gi').test(s);
-}
-
-function getVal(s, i) {
-	var a = tinyMCE.explode(' ', s);
-
-	if (a.length > 1)
-		return a[i];
-
-	return "";
-}
-
-function setValue(f, n, v) {
-	if (f.elements[n].type == "text")
-		f.elements[n].value = v;
-	else
-		selectByValue(f, n, v, true, true);
-}
-
-function setupBox(f, ce, fp, pr, sf, b) {
-	if (typeof(b) == "undefined")
-		b = new Array('Top', 'Right', 'Bottom', 'Left');
-
-	if (isSame(ce, pr, sf, b)) {
-		f.elements[fp + "_same"].checked = true;
-
-		setValue(f, fp + "_top", getNum(ce.style[pr + b[0] + sf]));
-		f.elements[fp + "_top"].disabled = false;
-
-		f.elements[fp + "_right"].value = "";
-		f.elements[fp + "_right"].disabled = true;
-		f.elements[fp + "_bottom"].value = "";
-		f.elements[fp + "_bottom"].disabled = true;
-		f.elements[fp + "_left"].value = "";
-		f.elements[fp + "_left"].disabled = true;
-
-		if (f.elements[fp + "_top_measurement"]) {
-			selectByValue(f, fp + '_top_measurement', getMeasurement(ce.style[pr + b[0] + sf]));
-			f.elements[fp + "_left_measurement"].disabled = true;
-			f.elements[fp + "_bottom_measurement"].disabled = true;
-			f.elements[fp + "_right_measurement"].disabled = true;
-		}
-	} else {
-		f.elements[fp + "_same"].checked = false;
-
-		setValue(f, fp + "_top", getNum(ce.style[pr + b[0] + sf]));
-		f.elements[fp + "_top"].disabled = false;
-
-		setValue(f, fp + "_right", getNum(ce.style[pr + b[1] + sf]));
-		f.elements[fp + "_right"].disabled = false;
-
-		setValue(f, fp + "_bottom", getNum(ce.style[pr + b[2] + sf]));
-		f.elements[fp + "_bottom"].disabled = false;
-
-		setValue(f, fp + "_left", getNum(ce.style[pr + b[3] + sf]));
-		f.elements[fp + "_left"].disabled = false;
-
-		if (f.elements[fp + "_top_measurement"]) {
-			selectByValue(f, fp + '_top_measurement', getMeasurement(ce.style[pr + b[0] + sf]));
-			selectByValue(f, fp + '_right_measurement', getMeasurement(ce.style[pr + b[1] + sf]));
-			selectByValue(f, fp + '_bottom_measurement', getMeasurement(ce.style[pr + b[2] + sf]));
-			selectByValue(f, fp + '_left_measurement', getMeasurement(ce.style[pr + b[3] + sf]));
-			f.elements[fp + "_left_measurement"].disabled = false;
-			f.elements[fp + "_bottom_measurement"].disabled = false;
-			f.elements[fp + "_right_measurement"].disabled = false;
-		}
-	}
-}
-
-function isSame(e, pr, sf, b) {
-	var a = new Array(), i, x;
-
-	if (typeof(b) == "undefined")
-		b = new Array('Top', 'Right', 'Bottom', 'Left');
-
-	if (typeof(sf) == "undefined" || sf == null)
-		sf = "";
-
-	a[0] = e.style[pr + b[0] + sf];
-	a[1] = e.style[pr + b[1] + sf];
-	a[2] = e.style[pr + b[2] + sf];
-	a[3] = e.style[pr + b[3] + sf];
-
-	for (i=0; i<a.length; i++) {
-		if (a[i] == null)
-			return false;
-
-		for (x=0; x<a.length; x++) {
-			if (a[x] != a[i])
-				return false;
-		}
-	}
-
-	return true;
-};
-
-function hasEqualValues(a) {
-	var i, x;
-
-	for (i=0; i<a.length; i++) {
-		if (a[i] == null)
-			return false;
-
-		for (x=0; x<a.length; x++) {
-			if (a[x] != a[i])
-				return false;
-		}
-	}
-
-	return true;
-}
-
-function applyAction() {
-	var ce = document.getElementById('container');
-
-	generateCSS();
-
-	tinyMCEPopup.execCommand('mceSetElementStyle', false, tinyMCE.serializeStyle(tinyMCE.parseStyle(ce.style.cssText)));
-}
-
-function updateAction() {
-	applyAction();
-	tinyMCEPopup.close();
-}
-
-function generateCSS() {
-	var ce = document.getElementById('container'), f = document.forms[0], num = new RegExp('[0-9]+', 'g'), s, t;
-
-	ce.style.cssText = "";
-
-	// Build text styles
-	ce.style.fontFamily = f.text_font.value;
-	ce.style.fontSize = f.text_size.value + (isNum(f.text_size.value) ? f.text_size_measurement.value : "");
-	ce.style.fontStyle = f.text_style.value;
-	ce.style.lineHeight = f.text_lineheight.value + (isNum(f.text_lineheight.value) ? f.text_lineheight_measurement.value : "");
-	ce.style.textTransform = f.text_case.value;
-	ce.style.fontWeight = f.text_weight.value;
-	ce.style.fontVariant = f.text_variant.value;
-	ce.style.color = f.text_color.value;
-
-	s = "";
-	s += f.text_underline.checked ? " underline" : "";
-	s += f.text_overline.checked ? " overline" : "";
-	s += f.text_linethrough.checked ? " line-through" : "";
-	s += f.text_blink.checked ? " blink" : "";
-	s = s.length > 0 ? s.substring(1) : s;
-
-	if (f.text_none.checked)
-		s = "none";
-
-	ce.style.textDecoration = s;
-
-	// Build background styles
-
-	ce.style.backgroundColor = f.background_color.value;
-	ce.style.backgroundImage = f.background_image.value != "" ? "url(" + f.background_image.value + ")" : "";
-	ce.style.backgroundRepeat = f.background_repeat.value;
-	ce.style.backgroundAttachment = f.background_attachment.value;
-
-	if (f.background_hpos.value != "") {
-		s = "";
-		s += f.background_hpos.value + (isNum(f.background_hpos.value) ? f.background_hpos_measurement.value : "") + " ";
-		s += f.background_vpos.value + (isNum(f.background_vpos.value) ? f.background_vpos_measurement.value : "");
-		ce.style.backgroundPosition = s;
-	}
-
-	// Build block styles
-
-	ce.style.wordSpacing = f.block_wordspacing.value + (isNum(f.block_wordspacing.value) ? f.block_wordspacing_measurement.value : "");
-	ce.style.letterSpacing = f.block_letterspacing.value + (isNum(f.block_letterspacing.value) ? f.block_letterspacing_measurement.value : "");
-	ce.style.verticalAlign = f.block_vertical_alignment.value;
-	ce.style.textAlign = f.block_text_align.value;
-	ce.style.textIndent = f.block_text_indent.value + (isNum(f.block_text_indent.value) ? f.block_text_indent_measurement.value : "");
-	ce.style.whiteSpace = f.block_whitespace.value;
-	ce.style.display = f.block_display.value;
-
-	// Build box styles
-
-	ce.style.width = f.box_width.value + (isNum(f.box_width.value) ? f.box_width_measurement.value : "");
-	ce.style.height = f.box_height.value + (isNum(f.box_height.value) ? f.box_height_measurement.value : "");
-	ce.style.styleFloat = f.box_float.value;
-
-	if (tinyMCE.isGecko)
-		ce.style.cssFloat = f.box_float.value;
-
-	ce.style.clear = f.box_clear.value;
-
-	if (!f.box_padding_same.checked) {
-		ce.style.paddingTop = f.box_padding_top.value + (isNum(f.box_padding_top.value) ? f.box_padding_top_measurement.value : "");
-		ce.style.paddingRight = f.box_padding_right.value + (isNum(f.box_padding_right.value) ? f.box_padding_right_measurement.value : "");
-		ce.style.paddingBottom = f.box_padding_bottom.value + (isNum(f.box_padding_bottom.value) ? f.box_padding_bottom_measurement.value : "");
-		ce.style.paddingLeft = f.box_padding_left.value + (isNum(f.box_padding_left.value) ? f.box_padding_left_measurement.value : "");
-	} else
-		ce.style.padding = f.box_padding_top.value + (isNum(f.box_padding_top.value) ? f.box_padding_top_measurement.value : "");		
-
-	if (!f.box_margin_same.checked) {
-		ce.style.marginTop = f.box_margin_top.value + (isNum(f.box_margin_top.value) ? f.box_margin_top_measurement.value : "");
-		ce.style.marginRight = f.box_margin_right.value + (isNum(f.box_margin_right.value) ? f.box_margin_right_measurement.value : "");
-		ce.style.marginBottom = f.box_margin_bottom.value + (isNum(f.box_margin_bottom.value) ? f.box_margin_bottom_measurement.value : "");
-		ce.style.marginLeft = f.box_margin_left.value + (isNum(f.box_margin_left.value) ? f.box_margin_left_measurement.value : "");
-	} else
-		ce.style.margin = f.box_margin_top.value + (isNum(f.box_margin_top.value) ? f.box_margin_top_measurement.value : "");		
-
-	// Build border styles
-
-	if (!f.border_style_same.checked) {
-		ce.style.borderTopStyle = f.border_style_top.value;
-		ce.style.borderRightStyle = f.border_style_right.value;
-		ce.style.borderBottomStyle = f.border_style_bottom.value;
-		ce.style.borderLeftStyle = f.border_style_left.value;
-	} else
-		ce.style.borderStyle = f.border_style_top.value;
-
-	if (!f.border_width_same.checked) {
-		ce.style.borderTopWidth = f.border_width_top.value + (isNum(f.border_width_top.value) ? f.border_width_top_measurement.value : "");
-		ce.style.borderRightWidth = f.border_width_right.value + (isNum(f.border_width_right.value) ? f.border_width_right_measurement.value : "");
-		ce.style.borderBottomWidth = f.border_width_bottom.value + (isNum(f.border_width_bottom.value) ? f.border_width_bottom_measurement.value : "");
-		ce.style.borderLeftWidth = f.border_width_left.value + (isNum(f.border_width_left.value) ? f.border_width_left_measurement.value : "");
-	} else
-		ce.style.borderWidth = f.border_width_top.value;
-
-	if (!f.border_color_same.checked) {
-		ce.style.borderTopColor = f.border_color_top.value;
-		ce.style.borderRightColor = f.border_color_right.value;
-		ce.style.borderBottomColor = f.border_color_bottom.value;
-		ce.style.borderLeftColor = f.border_color_left.value;
-	} else
-		ce.style.borderColor = f.border_color_top.value;
-
-	// Build list styles
-
-	ce.style.listStyleType = f.list_type.value;
-	ce.style.listStylePosition = f.list_position.value;
-	ce.style.listStyleImage = f.list_bullet_image.value != "" ? "url(" + f.list_bullet_image.value + ")" : "";
-
-	// Build positioning styles
-
-	ce.style.position = f.positioning_type.value;
-	ce.style.visibility = f.positioning_visibility.value;
-
-	if (ce.style.width == "")
-		ce.style.width = f.positioning_width.value + (isNum(f.positioning_width.value) ? f.positioning_width_measurement.value : "");
-
-	if (ce.style.height == "")
-		ce.style.height = f.positioning_height.value + (isNum(f.positioning_height.value) ? f.positioning_height_measurement.value : "");
-
-	ce.style.zIndex = f.positioning_zindex.value;
-	ce.style.overflow = f.positioning_overflow.value;
-
-	if (!f.positioning_placement_same.checked) {
-		ce.style.top = f.positioning_placement_top.value + (isNum(f.positioning_placement_top.value) ? f.positioning_placement_top_measurement.value : "");
-		ce.style.right = f.positioning_placement_right.value + (isNum(f.positioning_placement_right.value) ? f.positioning_placement_right_measurement.value : "");
-		ce.style.bottom = f.positioning_placement_bottom.value + (isNum(f.positioning_placement_bottom.value) ? f.positioning_placement_bottom_measurement.value : "");
-		ce.style.left = f.positioning_placement_left.value + (isNum(f.positioning_placement_left.value) ? f.positioning_placement_left_measurement.value : "");
-	} else {
-		s = f.positioning_placement_top.value + (isNum(f.positioning_placement_top.value) ? f.positioning_placement_top_measurement.value : "");
-		ce.style.top = s;
-		ce.style.right = s;
-		ce.style.bottom = s;
-		ce.style.left = s;
-	}
-
-	if (!f.positioning_clip_same.checked) {
-		s = "rect(";
-		s += (isNum(f.positioning_clip_top.value) ? f.positioning_clip_top.value + f.positioning_clip_top_measurement.value : "auto") + " ";
-		s += (isNum(f.positioning_clip_right.value) ? f.positioning_clip_right.value + f.positioning_clip_right_measurement.value : "auto") + " ";
-		s += (isNum(f.positioning_clip_bottom.value) ? f.positioning_clip_bottom.value + f.positioning_clip_bottom_measurement.value : "auto") + " ";
-		s += (isNum(f.positioning_clip_left.value) ? f.positioning_clip_left.value + f.positioning_clip_left_measurement.value : "auto");
-		s += ")";
-
-		if (s != "rect(auto auto auto auto)")
-			ce.style.clip = s;
-	} else {
-		s = "rect(";
-		t = isNum(f.positioning_clip_top.value) ? f.positioning_clip_top.value + f.positioning_clip_top_measurement.value : "auto";
-		s += t + " ";
-		s += t + " ";
-		s += t + " ";
-		s += t + ")";
-
-		if (s != "rect(auto auto auto auto)")
-			ce.style.clip = s;
-	}
-
-	ce.style.cssText = tinyMCE.serializeStyle(tinyMCE.parseStyle(ce.style.cssText));
-}
-
-function isNum(s) {
-	return new RegExp('[0-9]+', 'g').test(s);
-}
-
-function showDisabledControls() {
-	var f = document.forms, i, a;
-
-	for (i=0; i<f.length; i++) {
-		for (a=0; a<f[i].elements.length; a++) {
-			if (f[i].elements[a].disabled)
-				tinyMCE.addCSSClass(f[i].elements[a], "disabled");
-			else
-				tinyMCE.removeCSSClass(f[i].elements[a], "disabled");
-		}
-	}
-}
-
-function fillSelect(f, s, param, dval, sep, em) {
-	var i, ar, p, se;
-
-	f = document.forms[f];
-	sep = typeof(sep) == "undefined" ? ";" : sep;
-
-	if (em)
-		addSelectValue(f, s, "", "");
-
-	ar = tinyMCE.getParam(param, dval).split(sep);
-	for (i=0; i<ar.length; i++) {
-		se = false;
-
-		if (ar[i].charAt(0) == '+') {
-			ar[i] = ar[i].substring(1);
-			se = true;
-		}
-
-		p = ar[i].split('=');
-
-		if (p.length > 1) {
-			addSelectValue(f, s, p[0], p[1]);
-
-			if (se)
-				selectByValue(f, s, p[1]);
-		} else {
-			addSelectValue(f, s, p[0], p[0]);
-
-			if (se)
-				selectByValue(f, s, p[0]);
-		}
-	}
-}
-
-function toggleSame(ce, pre) {
-	var el = document.forms[0].elements, i;
-
-	if (ce.checked) {
-		el[pre + "_top"].disabled = false;
-		el[pre + "_right"].disabled = true;
-		el[pre + "_bottom"].disabled = true;
-		el[pre + "_left"].disabled = true;
-
-		if (el[pre + "_top_measurement"]) {
-			el[pre + "_top_measurement"].disabled = false;
-			el[pre + "_right_measurement"].disabled = true;
-			el[pre + "_bottom_measurement"].disabled = true;
-			el[pre + "_left_measurement"].disabled = true;
-		}
-	} else {
-		el[pre + "_top"].disabled = false;
-		el[pre + "_right"].disabled = false;
-		el[pre + "_bottom"].disabled = false;
-		el[pre + "_left"].disabled = false;
-
-		if (el[pre + "_top_measurement"]) {
-			el[pre + "_top_measurement"].disabled = false;
-			el[pre + "_right_measurement"].disabled = false;
-			el[pre + "_bottom_measurement"].disabled = false;
-			el[pre + "_left_measurement"].disabled = false;
-		}
-	}
-
-	showDisabledControls();
-}
-
-function synch(fr, to) {
-	var f = document.forms[0];
-
-	f.elements[to].value = f.elements[fr].value;
-
-	if (f.elements[fr + "_measurement"])
-		selectByValue(f, to + "_measurement", f.elements[fr + "_measurement"].value);
-}
--- a/includes/clientside/tinymce/plugins/style/langs/en.js	Fri Feb 22 12:46:51 2008 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,66 +0,0 @@
-// UK lang variables
-
-tinyMCE.addToLang('style',{
-title : 'Edit CSS Style',
-styleinfo_desc : 'Edit CSS Style',
-apply : 'Apply',
-text_tab : 'Text',
-background_tab : 'Background',
-block_tab : 'Block',
-box_tab : 'Box',
-border_tab : 'Border',
-list_tab : 'List',
-positioning_tab : 'Positioning',
-text_props : 'Text',
-text_font : 'Font',
-text_size : 'Size',
-text_weight : 'Weight',
-text_style : 'Style',
-text_variant : 'Variant',
-text_lineheight : 'Line height',
-text_case : 'Case',
-text_color : 'Color',
-text_decoration : 'Decoration',
-text_overline : 'overline',
-text_underline : 'underline',
-text_striketrough : 'strikethrough',
-text_blink : 'blink',
-text_none : 'none',
-background_color : 'Background color',
-background_image : 'Background image',
-background_repeat : 'Repeat',
-background_attachment : 'Attachment',
-background_hpos : 'Horizontal position',
-background_vpos : 'Vertical position',
-block_wordspacing : 'Word spacing',
-block_letterspacing : 'Letter spacing',
-block_vertical_alignment : 'Vertical alignment',
-block_text_align : 'Text align',
-block_text_indent : 'Text indent',
-block_whitespace : 'Whitespace',
-block_display : 'Display',
-box_width : 'Width',
-box_height : 'Height',
-box_float : 'Float',
-box_clear : 'Clear',
-padding : 'Padding',
-same : 'Same for all',
-top : 'Top',
-right : 'Right',
-bottom : 'Bottom',
-left : 'Left',
-margin : 'Margin',
-style : 'Style',
-width : 'Width',
-height : 'Height',
-color : 'Color',
-list_type : 'Type',
-bullet_image : 'Bullet image',
-position : 'Position',
-positioning_type : 'Type',
-visibility : 'Visibility',
-zindex : 'Z-index',
-overflow : 'Overflow',
-placement : 'Placement',
-clip : 'Clip'
-});
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/includes/clientside/tinymce/plugins/style/langs/en_dlg.js	Fri Feb 22 12:51:53 2008 -0500
@@ -0,0 +1,63 @@
+tinyMCE.addI18n('en.style_dlg',{
+title:"Edit CSS Style",
+apply:"Apply",
+text_tab:"Text",
+background_tab:"Background",
+block_tab:"Block",
+box_tab:"Box",
+border_tab:"Border",
+list_tab:"List",
+positioning_tab:"Positioning",
+text_props:"Text",
+text_font:"Font",
+text_size:"Size",
+text_weight:"Weight",
+text_style:"Style",
+text_variant:"Variant",
+text_lineheight:"Line height",
+text_case:"Case",
+text_color:"Color",
+text_decoration:"Decoration",
+text_overline:"overline",
+text_underline:"underline",
+text_striketrough:"strikethrough",
+text_blink:"blink",
+text_none:"none",
+background_color:"Background color",
+background_image:"Background image",
+background_repeat:"Repeat",
+background_attachment:"Attachment",
+background_hpos:"Horizontal position",
+background_vpos:"Vertical position",
+block_wordspacing:"Word spacing",
+block_letterspacing:"Letter spacing",
+block_vertical_alignment:"Vertical alignment",
+block_text_align:"Text align",
+block_text_indent:"Text indent",
+block_whitespace:"Whitespace",
+block_display:"Display",
+box_width:"Width",
+box_height:"Height",
+box_float:"Float",
+box_clear:"Clear",
+padding:"Padding",
+same:"Same for all",
+top:"Top",
+right:"Right",
+bottom:"Bottom",
+left:"Left",
+margin:"Margin",
+style:"Style",
+width:"Width",
+height:"Height",
+color:"Color",
+list_type:"Type",
+bullet_image:"Bullet image",
+position:"Position",
+positioning_type:"Type",
+visibility:"Visibility",
+zindex:"Z-index",
+overflow:"Overflow",
+placement:"Placement",
+clip:"Clip"
+});
\ No newline at end of file
--- a/includes/clientside/tinymce/plugins/style/props.htm	Fri Feb 22 12:46:51 2008 -0500
+++ b/includes/clientside/tinymce/plugins/style/props.htm	Fri Feb 22 12:51:53 2008 -0500
@@ -1,26 +1,27 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
 <html xmlns="http://www.w3.org/1999/xhtml">
 <head>
-	<title>{$lang_style_title}</title>
-	<script language="javascript" type="text/javascript" src="../../tiny_mce_popup.js"></script>
-	<script language="javascript" type="text/javascript" src="../../utils/mctabs.js"></script>
-	<script language="javascript" type="text/javascript" src="../../utils/editable_selects.js"></script>
-	<script language="javascript" type="text/javascript" src="../../utils/form_utils.js"></script>
-	<script language="javascript" type="text/javascript" src="jscripts/props.js"></script>
+	<title>{#style_dlg.title}</title>
+	<script type="text/javascript" src="../../tiny_mce_popup.js"></script>
+	<script type="text/javascript" src="../../utils/mctabs.js"></script>
+	<script type="text/javascript" src="../../utils/editable_selects.js"></script>
+	<script type="text/javascript" src="../../utils/form_utils.js"></script>
+	<script type="text/javascript" src="js/props.js"></script>
 	<link href="css/props.css" rel="stylesheet" type="text/css" />
 	<base target="_self" />
 </head>
 
-<body id="styleprops" onLoad="tinyMCEPopup.executeOnLoad('init();');" style="display: none">
+<body id="styleprops" style="display: none">
 <form onSubmit="updateAction();return false;" action="#">
 <div class="tabs">
 	<ul>
-		<li id="text_tab" class="current"><span><a href="javascript:mcTabs.displayTab('text_tab','text_panel');" onMouseDown="return false;">{$lang_style_text_tab}</a></span></li>
-		<li id="background_tab"><span><a href="javascript:mcTabs.displayTab('background_tab','background_panel');" onMouseDown="return false;">{$lang_style_background_tab}</a></span></li>
-		<li id="block_tab"><span><a href="javascript:mcTabs.displayTab('block_tab','block_panel');" onMouseDown="return false;">{$lang_style_block_tab}</a></span></li>
-		<li id="box_tab"><span><a href="javascript:mcTabs.displayTab('box_tab','box_panel');" onMouseDown="return false;">{$lang_style_box_tab}</a></span></li>
-		<li id="border_tab"><span><a href="javascript:mcTabs.displayTab('border_tab','border_panel');" onMouseDown="return false;">{$lang_style_border_tab}</a></span></li>
-		<li id="list_tab"><span><a href="javascript:mcTabs.displayTab('list_tab','list_panel');" onMouseDown="return false;">{$lang_style_list_tab}</a></span></li>
-		<li id="positioning_tab"><span><a href="javascript:mcTabs.displayTab('positioning_tab','positioning_panel');" onMouseDown="return false;">{$lang_style_positioning_tab}</a></span></li>
+		<li id="text_tab" class="current"><span><a href="javascript:mcTabs.displayTab('text_tab','text_panel');" onMouseDown="return false;">{#style_dlg.text_tab}</a></span></li>
+		<li id="background_tab"><span><a href="javascript:mcTabs.displayTab('background_tab','background_panel');" onMouseDown="return false;">{#style_dlg.background_tab}</a></span></li>
+		<li id="block_tab"><span><a href="javascript:mcTabs.displayTab('block_tab','block_panel');" onMouseDown="return false;">{#style_dlg.block_tab}</a></span></li>
+		<li id="box_tab"><span><a href="javascript:mcTabs.displayTab('box_tab','box_panel');" onMouseDown="return false;">{#style_dlg.box_tab}</a></span></li>
+		<li id="border_tab"><span><a href="javascript:mcTabs.displayTab('border_tab','border_panel');" onMouseDown="return false;">{#style_dlg.border_tab}</a></span></li>
+		<li id="list_tab"><span><a href="javascript:mcTabs.displayTab('list_tab','list_panel');" onMouseDown="return false;">{#style_dlg.list_tab}</a></span></li>
+		<li id="positioning_tab"><span><a href="javascript:mcTabs.displayTab('positioning_tab','positioning_panel');" onMouseDown="return false;">{#style_dlg.positioning_tab}</a></span></li>
 	</ul>
 </div>
 
@@ -28,13 +29,13 @@
 <div id="text_panel" class="panel current">
 	<table border="0" width="100%">
 		<tr>
-			<td><label for="text_font">{$lang_style_text_font}</label></td>
+			<td><label for="text_font">{#style_dlg.text_font}</label></td>
 			<td colspan="3">
 				<select id="text_font" name="text_font" class="mceEditableSelect" onChange="alert(this.options[this.selectedIndex].value);"></select>
 			</td>
 		</tr>
 		<tr>
-			<td><label for="text_size">{$lang_style_text_size}</label></td>
+			<td><label for="text_size">{#style_dlg.text_size}</label></td>
 			<td>
 				<table border="0" cellspacing="0" cellpadding="0">
 					<tr>
@@ -44,23 +45,23 @@
 					</tr>
 				</table>
 			</td>
-			<td><label for="text_weight">{$lang_style_text_weight}</label></td>
+			<td><label for="text_weight">{#style_dlg.text_weight}</label></td>
 			<td>
 				<select id="text_weight" name="text_weight"></select>
 			</td>
 		</tr>
 		<tr>
-			<td><label for="text_style">{$lang_style_text_style}</label></td>
+			<td><label for="text_style">{#style_dlg.text_style}</label></td>
 			<td>
 				<select id="text_style" name="text_style" class="mceEditableSelect"></select>
 			</td>
-			<td><label for="text_variant">{$lang_style_text_variant}</label></td>
+			<td><label for="text_variant">{#style_dlg.text_variant}</label></td>
 			<td>
 				<select id="text_variant" name="text_variant"></select>
 			</td>
 		</tr>
 		<tr>
-			<td><label for="text_lineheight">{$lang_style_text_lineheight}</label></td>
+			<td><label for="text_lineheight">{#style_dlg.text_lineheight}</label></td>
 			<td>
 				<table border="0" cellspacing="0" cellpadding="0">
 					<tr>
@@ -68,17 +69,17 @@
 							<select id="text_lineheight" name="text_lineheight" class="mceEditableSelect"></select>
 						</td>
 						<td>&nbsp;</td>
-      <td><select id="text_lineheight_measurement" name="text_lineheight_measurement"></select></td>
+						<td><select id="text_lineheight_measurement" name="text_lineheight_measurement"></select></td>
 					</tr>
 				</table>
 			</td>
-			<td><label for="text_case">{$lang_style_text_case}</label></td>
+			<td><label for="text_case">{#style_dlg.text_case}</label></td>
 			<td>
 				<select id="text_case" name="text_case"></select>
 			</td>
 		</tr>
 		<tr>
-			<td><label for="text_color">{$lang_style_text_color}</label></td>
+			<td><label for="text_color">{#style_dlg.text_color}</label></td>
 			<td colspan="2">
 				<table border="0" cellpadding="0" cellspacing="0">
 					<tr>
@@ -89,28 +90,28 @@
 			</td>
 		</tr>
 		<tr>
-			<td valign="top" style="vertical-align: top; padding-top: 3px;">{$lang_style_text_decoration}</td>
+			<td valign="top" style="vertical-align: top; padding-top: 3px;">{#style_dlg.text_decoration}</td>
 			<td colspan="2">
 				<table border="0" cellspacing="0" cellpadding="0">
 					<tr>
 						<td><input id="text_underline" name="text_underline" class="checkbox" type="checkbox" /></td>
-						<td><label for="text_underline">{$lang_style_text_underline}</label></td>
+						<td><label for="text_underline">{#style_dlg.text_underline}</label></td>
 					</tr>
 					<tr>
 						<td><input id="text_overline" name="text_overline" class="checkbox" type="checkbox" /></td>
-						<td><label for="text_overline">{$lang_style_text_overline}</label></td>
+						<td><label for="text_overline">{#style_dlg.text_overline}</label></td>
 					</tr>
 					<tr>
 						<td><input id="text_linethrough" name="text_linethrough" class="checkbox" type="checkbox" /></td>
-						<td><label for="text_linethrough">{$lang_style_text_striketrough}</label></td>
+						<td><label for="text_linethrough">{#style_dlg.text_striketrough}</label></td>
 					</tr>
 					<tr>
 						<td><input id="text_blink" name="text_blink" class="checkbox" type="checkbox" /></td>
-						<td><label for="text_blink">{$lang_style_text_blink}</label></td>
+						<td><label for="text_blink">{#style_dlg.text_blink}</label></td>
 					</tr>
 					<tr>
 						<td><input id="text_none" name="text_none" class="checkbox" type="checkbox" /></td>
-						<td><label for="text_none">{$lang_style_text_none}</label></td>
+						<td><label for="text_none">{#style_dlg.text_none}</label></td>
 					</tr>
 				</table>
 			</td>
@@ -121,7 +122,7 @@
 <div id="background_panel" class="panel">
 	<table border="0">
 		<tr>
-			<td><label for="background_color">{$lang_style_background_color}</label></td>
+			<td><label for="background_color">{#style_dlg.background_color}</label></td>
 			<td>
 				<table border="0" cellpadding="0" cellspacing="0">
 					<tr>
@@ -133,7 +134,7 @@
 		</tr>
 
 		<tr>
-			<td><label for="background_image">{$lang_style_background_image}</label></td>
+			<td><label for="background_image">{#style_dlg.background_image}</label></td>
 			<td><table border="0" cellspacing="0" cellpadding="0">
 				<tr> 
 				  <td><input id="background_image" name="background_image" type="text" /></td> 
@@ -144,36 +145,36 @@
 		</tr>
 
 		<tr>
-			<td><label for="background_repeat">{$lang_style_background_repeat}</label></td>
+			<td><label for="background_repeat">{#style_dlg.background_repeat}</label></td>
 			<td><select id="background_repeat" name="background_repeat" class="mceEditableSelect"></select></td>
 		</tr>
 
 		<tr>
-			<td><label for="background_attachment">{$lang_style_background_attachment}</label></td>
+			<td><label for="background_attachment">{#style_dlg.background_attachment}</label></td>
 			<td><select id="background_attachment" name="background_attachment" class="mceEditableSelect"></select></td>
 		</tr>
 
 		<tr>
-			<td><label for="background_hpos">{$lang_style_background_hpos}</label></td>
+			<td><label for="background_hpos">{#style_dlg.background_hpos}</label></td>
 			<td>
 				<table border="0" cellspacing="0" cellpadding="0">
 					<tr>
 						<td><select id="background_hpos" name="background_hpos" class="mceEditableSelect"></select></td>
 						<td>&nbsp;</td>
-      <td><select id="background_hpos_measurement" name="background_hpos_measurement"></select></td>
+						<td><select id="background_hpos_measurement" name="background_hpos_measurement"></select></td>
 					</tr>
 				</table>
 			</td>
 		</tr>
 
 		<tr>
-			<td><label for="background_vpos">{$lang_style_background_vpos}</label></td>
+			<td><label for="background_vpos">{#style_dlg.background_vpos}</label></td>
 			<td>
 				<table border="0" cellspacing="0" cellpadding="0">
 					<tr>
 						<td><select id="background_vpos" name="background_vpos" class="mceEditableSelect"></select></td>
 						<td>&nbsp;</td>
-      <td><select id="background_vpos_measurement" name="background_vpos_measurement"></select></td>
+						<td><select id="background_vpos_measurement" name="background_vpos_measurement"></select></td>
 					</tr>
 				</table>
 			</td>
@@ -184,61 +185,61 @@
 <div id="block_panel" class="panel">
 	<table border="0">
 		<tr>
-			<td><label for="block_wordspacing">{$lang_style_block_wordspacing}</label></td>
+			<td><label for="block_wordspacing">{#style_dlg.block_wordspacing}</label></td>
 			<td>
 				<table border="0" cellspacing="0" cellpadding="0">
 					<tr>
 						<td><select id="block_wordspacing" name="block_wordspacing" class="mceEditableSelect"></select></td>
 						<td>&nbsp;</td>
-      <td><select id="block_wordspacing_measurement" name="block_wordspacing_measurement"></select></td>
+						<td><select id="block_wordspacing_measurement" name="block_wordspacing_measurement"></select></td>
 					</tr>
 				</table>
 			</td>
 		</tr>
 
 		<tr>
-			<td><label for="block_letterspacing">{$lang_style_block_letterspacing}</label></td>
+			<td><label for="block_letterspacing">{#style_dlg.block_letterspacing}</label></td>
 			<td>
 				<table border="0" cellspacing="0" cellpadding="0">
 					<tr>
 						<td><select id="block_letterspacing" name="block_letterspacing" class="mceEditableSelect"></select></td>
 						<td>&nbsp;</td>
-      <td><select id="block_letterspacing_measurement" name="block_letterspacing_measurement"></select></td>
+						<td><select id="block_letterspacing_measurement" name="block_letterspacing_measurement"></select></td>
 					</tr>
 				</table>
 			</td>
 		</tr>
 
 		<tr>
-			<td><label for="block_vertical_alignment">{$lang_style_block_vertical_alignment}</label></td>
+			<td><label for="block_vertical_alignment">{#style_dlg.block_vertical_alignment}</label></td>
 			<td><select id="block_vertical_alignment" name="block_vertical_alignment" class="mceEditableSelect"></select></td>
 		</tr>
 
 		<tr>
-			<td><label for="block_text_align">{$lang_style_block_text_align}</label></td>
+			<td><label for="block_text_align">{#style_dlg.block_text_align}</label></td>
 			<td><select id="block_text_align" name="block_text_align" class="mceEditableSelect"></select></td>
 		</tr>
 
 		<tr>
-			<td><label for="block_text_indent">{$lang_style_block_text_indent}</label></td>
+			<td><label for="block_text_indent">{#style_dlg.block_text_indent}</label></td>
 			<td>
 				<table border="0" cellspacing="0" cellpadding="0">
 					<tr>
 						<td><input type="text" id="block_text_indent" name="block_text_indent" /></td>
 						<td>&nbsp;</td>
-      <td><select id="block_text_indent_measurement" name="block_text_indent_measurement"></select></td>
+						<td><select id="block_text_indent_measurement" name="block_text_indent_measurement"></select></td>
 					</tr>
 				</table>
 			</td>
 		</tr>
 
 		<tr>
-			<td><label for="block_whitespace">{$lang_style_block_whitespace}</label></td>
+			<td><label for="block_whitespace">{#style_dlg.block_whitespace}</label></td>
 			<td><select id="block_whitespace" name="block_whitespace" class="mceEditableSelect"></select></td>
 		</tr>
 
 		<tr>
-			<td><label for="block_display">{$lang_style_block_display}</label></td>
+			<td><label for="block_display">{#style_dlg.block_display}</label></td>
 			<td><select id="block_display" name="block_display" class="mceEditableSelect"></select></td>
 		</tr>
 	</table>
@@ -247,88 +248,88 @@
 <div id="box_panel" class="panel">
 <table border="0">
 	<tr>
-		<td><label for="box_width">{$lang_style_box_width}</label></td>
+		<td><label for="box_width">{#style_dlg.box_width}</label></td>
 		<td>
 			<table border="0" cellspacing="0" cellpadding="0">
 				<tr>
 					<td><input type="text" id="box_width" name="box_width" class="mceEditableSelect" onChange="synch('box_width','positioning_width');" /></td>
 					<td>&nbsp;</td>
-     <td><select id="box_width_measurement" name="box_width_measurement"></select></td>
+					<td><select id="box_width_measurement" name="box_width_measurement"></select></td>
 				</tr>
 			</table>
 		</td>
-		<td>&nbsp;&nbsp;&nbsp;<label for="box_float">{$lang_style_box_float}</label></td>
+		<td>&nbsp;&nbsp;&nbsp;<label for="box_float">{#style_dlg.box_float}</label></td>
 		<td><select id="box_float" name="box_float" class="mceEditableSelect"></select></td>
 	</tr>
 
 	<tr>
-		<td><label for="box_height">{$lang_style_box_height}</label></td>
+		<td><label for="box_height">{#style_dlg.box_height}</label></td>
 		<td>
 			<table border="0" cellspacing="0" cellpadding="0">
 				<tr>
 					<td><input type="text" id="box_height" name="box_height" class="mceEditableSelect" onChange="synch('box_height','positioning_height');" /></td>
 					<td>&nbsp;</td>
-     <td><select id="box_height_measurement" name="box_height_measurement"></select></td>
+					<td><select id="box_height_measurement" name="box_height_measurement"></select></td>
 				</tr>
 			</table>
 		</td>
-		<td>&nbsp;&nbsp;&nbsp;<label for="box_clear">{$lang_style_box_clear}</label></td>
+		<td>&nbsp;&nbsp;&nbsp;<label for="box_clear">{#style_dlg.box_clear}</label></td>
 		<td><select id="box_clear" name="box_clear" class="mceEditableSelect"></select></td>
 	</tr>
 </table>
 <div style="float: left; width: 49%">
 	<fieldset>
-		<legend>{$lang_style_padding}</legend>
+		<legend>{#style_dlg.padding}</legend>
 
 		<table border="0">
 			<tr>
 				<td>&nbsp;</td>
-				<td><input type="checkbox" id="box_padding_same" name="box_padding_same" class="checkbox" checked="checked" onClick="toggleSame(this,'box_padding');" /> <label for="box_padding_same">{$lang_style_same}</label></td>
+				<td><input type="checkbox" id="box_padding_same" name="box_padding_same" class="checkbox" checked="checked" onClick="toggleSame(this,'box_padding');" /> <label for="box_padding_same">{#style_dlg.same}</label></td>
 			</tr>
 			<tr>
-				<td><label for="box_padding_top">{$lang_style_top}</label></td>
+				<td><label for="box_padding_top">{#style_dlg.top}</label></td>
 				<td>
 					<table border="0" cellspacing="0" cellpadding="0">
 						<tr>
 							<td><input type="text" id="box_padding_top" name="box_padding_top" class="mceEditableSelect" /></td>
 							<td>&nbsp;</td>
-       <td><select id="box_padding_top_measurement" name="box_padding_top_measurement"></select></td>
+							<td><select id="box_padding_top_measurement" name="box_padding_top_measurement"></select></td>
 						</tr>
 					</table>
 				</td>
 			</tr>
 			<tr>
-				<td><label for="box_padding_right">{$lang_style_right}</label></td>
+				<td><label for="box_padding_right">{#style_dlg.right}</label></td>
 				<td>
 					<table border="0" cellspacing="0" cellpadding="0">
 						<tr>
 							<td><input type="text" id="box_padding_right" name="box_padding_right" class="mceEditableSelect" disabled="disabled" /></td>
 							<td>&nbsp;</td>
-       <td><select id="box_padding_right_measurement" name="box_padding_right_measurement" disabled="disabled"></select></td>
+							<td><select id="box_padding_right_measurement" name="box_padding_right_measurement" disabled="disabled"></select></td>
 						</tr>
 					</table>
 				</td>
 			</tr>
 			<tr>
-				<td><label for="box_padding_bottom">{$lang_style_bottom}</label></td>
+				<td><label for="box_padding_bottom">{#style_dlg.bottom}</label></td>
 				<td>
 					<table border="0" cellspacing="0" cellpadding="0">
 						<tr>
 							<td><input type="text" id="box_padding_bottom" name="box_padding_bottom" class="mceEditableSelect" disabled="disabled" /></td>
 							<td>&nbsp;</td>
-       <td><select id="box_padding_bottom_measurement" name="box_padding_bottom_measurement" disabled="disabled"></select></td>
+							<td><select id="box_padding_bottom_measurement" name="box_padding_bottom_measurement" disabled="disabled"></select></td>
 						</tr>
 					</table>
 				</td>
 			</tr>
 			<tr>
-				<td><label for="box_padding_left">{$lang_style_left}</label></td>
+				<td><label for="box_padding_left">{#style_dlg.left}</label></td>
 				<td>
 					<table border="0" cellspacing="0" cellpadding="0">
 						<tr>
 							<td><input type="text" id="box_padding_left" name="box_padding_left" class="mceEditableSelect" disabled="disabled" /></td>
 							<td>&nbsp;</td>
-       <td><select id="box_padding_left_measurement" name="box_padding_left_measurement" disabled="disabled"></select></td>
+							<td><select id="box_padding_left_measurement" name="box_padding_left_measurement" disabled="disabled"></select></td>
 						</tr>
 					</table>
 				</td>
@@ -339,57 +340,57 @@
 
 <div style="float: right; width: 49%">
 	<fieldset>
-		<legend>{$lang_style_margin}</legend>
+		<legend>{#style_dlg.margin}</legend>
 
 		<table border="0">
 			<tr>
 				<td>&nbsp;</td>
-				<td><input type="checkbox" id="box_margin_same" name="box_margin_same" class="checkbox" checked="checked" onClick="toggleSame(this,'box_margin');" /> <label for="box_margin_same">{$lang_style_same}</label></td>
+				<td><input type="checkbox" id="box_margin_same" name="box_margin_same" class="checkbox" checked="checked" onClick="toggleSame(this,'box_margin');" /> <label for="box_margin_same">{#style_dlg.same}</label></td>
 			</tr>
 			<tr>
-				<td><label for="box_margin_top">{$lang_style_top}</label></td>
+				<td><label for="box_margin_top">{#style_dlg.top}</label></td>
 				<td>
 					<table border="0" cellspacing="0" cellpadding="0">
 						<tr>
 							<td><input type="text" id="box_margin_top" name="box_margin_top" class="mceEditableSelect" /></td>
 							<td>&nbsp;</td>
-       <td><select id="box_margin_top_measurement" name="box_margin_top_measurement"></select></td>
+							<td><select id="box_margin_top_measurement" name="box_margin_top_measurement"></select></td>
 						</tr>
 					</table>
 				</td>
 			</tr>
 			<tr>
-				<td><label for="box_margin_right">{$lang_style_right}</label></td>
+				<td><label for="box_margin_right">{#style_dlg.right}</label></td>
 				<td>
 					<table border="0" cellspacing="0" cellpadding="0">
 						<tr>
 							<td><input type="text" id="box_margin_right" name="box_margin_right" class="mceEditableSelect" disabled="disabled" /></td>
 							<td>&nbsp;</td>
-       <td><select id="box_margin_right_measurement" name="box_margin_right_measurement" disabled="disabled"></select></td>
+							<td><select id="box_margin_right_measurement" name="box_margin_right_measurement" disabled="disabled"></select></td>
 						</tr>
 					</table>
 				</td>
 			</tr>
 			<tr>
-				<td><label for="box_margin_bottom">{$lang_style_bottom}</label></td>
+				<td><label for="box_margin_bottom">{#style_dlg.bottom}</label></td>
 				<td>
 					<table border="0" cellspacing="0" cellpadding="0">
 						<tr>
 							<td><input type="text" id="box_margin_bottom" name="box_margin_bottom" class="mceEditableSelect" disabled="disabled" /></td>
 							<td>&nbsp;</td>
-       <td><select id="box_margin_bottom_measurement" name="box_margin_bottom_measurement" disabled="disabled"></select></td>
+							<td><select id="box_margin_bottom_measurement" name="box_margin_bottom_measurement" disabled="disabled"></select></td>
 						</tr>
 					</table>
 				</td>
 			</tr>
 			<tr>
-				<td><label for="box_margin_left">{$lang_style_left}</label></td>
+				<td><label for="box_margin_left">{#style_dlg.left}</label></td>
 				<td>
 					<table border="0" cellspacing="0" cellpadding="0">
 						<tr>
 							<td><input type="text" id="box_margin_left" name="box_margin_left" class="mceEditableSelect" disabled="disabled" /></td>
 							<td>&nbsp;</td>
-       <td><select id="box_margin_left_measurement" name="box_margin_left_measurement" disabled="disabled"></select></td>
+							<td><select id="box_margin_left_measurement" name="box_margin_left_measurement" disabled="disabled"></select></td>
 						</tr>
 					</table>
 				</td>
@@ -405,25 +406,25 @@
 <tr>
 	<td class="tdelim">&nbsp;</td>
 	<td class="tdelim delim">&nbsp;</td>
-	<td class="tdelim">{$lang_style_style}</td>
+	<td class="tdelim">{#style_dlg.style}</td>
 	<td class="tdelim delim">&nbsp;</td>
-	<td class="tdelim">{$lang_style_width}</td>
+	<td class="tdelim">{#style_dlg.width}</td>
 	<td class="tdelim delim">&nbsp;</td>
-	<td class="tdelim">{$lang_style_color}</td>
+	<td class="tdelim">{#style_dlg.color}</td>
 </tr>
 
 <tr>
 	<td>&nbsp;</td>
 	<td class="delim">&nbsp;</td>
-	<td><input type="checkbox" id="border_style_same" name="border_style_same" class="checkbox" checked="checked" onClick="toggleSame(this,'border_style');" /> <label for="border_style_same">{$lang_style_same}</label></td>
+	<td><input type="checkbox" id="border_style_same" name="border_style_same" class="checkbox" checked="checked" onClick="toggleSame(this,'border_style');" /> <label for="border_style_same">{#style_dlg.same}</label></td>
 	<td class="delim">&nbsp;</td>
-	<td><input type="checkbox" id="border_width_same" name="border_width_same" class="checkbox" checked="checked" onClick="toggleSame(this,'border_width');" /> <label for="border_width_same">{$lang_style_same}</label></td>
+	<td><input type="checkbox" id="border_width_same" name="border_width_same" class="checkbox" checked="checked" onClick="toggleSame(this,'border_width');" /> <label for="border_width_same">{#style_dlg.same}</label></td>
 	<td class="delim">&nbsp;</td>
-	<td><input type="checkbox" id="border_color_same" name="border_color_same" class="checkbox" checked="checked" onClick="toggleSame(this,'border_color');" /> <label for="border_color_same">{$lang_style_same}</label></td>
+	<td><input type="checkbox" id="border_color_same" name="border_color_same" class="checkbox" checked="checked" onClick="toggleSame(this,'border_color');" /> <label for="border_color_same">{#style_dlg.same}</label></td>
 </tr>
 
 <tr>
-	<td>{$lang_style_top}</td>
+	<td>{#style_dlg.top}</td>
 	<td class="delim">&nbsp;</td>
 	<td><select id="border_style_top" name="border_style_top" class="mceEditableSelect"></select></td>
 	<td class="delim">&nbsp;</td>
@@ -432,7 +433,7 @@
 			<tr>
 				<td><select id="border_width_top" name="border_width_top" class="mceEditableSelect"></select></td>
 				<td>&nbsp;</td>
-    <td><select id="border_width_top_measurement" name="border_width_top_measurement"></select></td>
+				<td><select id="border_width_top_measurement" name="border_width_top_measurement"></select></td>
 			</tr>
 		</table>
 	</td>
@@ -448,7 +449,7 @@
 </tr>
 
 <tr>
-	<td>{$lang_style_right}</td>
+	<td>{#style_dlg.right}</td>
 	<td class="delim">&nbsp;</td>
 	<td><select id="border_style_right" name="border_style_right" class="mceEditableSelect" disabled="disabled"></select></td>
 	<td class="delim">&nbsp;</td>
@@ -457,7 +458,7 @@
 			<tr>
 				<td><select id="border_width_right" name="border_width_right" class="mceEditableSelect" disabled="disabled"></select></td>
 				<td>&nbsp;</td>
-    <td><select id="border_width_right_measurement" name="border_width_right_measurement" disabled="disabled"></select></td>
+				<td><select id="border_width_right_measurement" name="border_width_right_measurement" disabled="disabled"></select></td>
 			</tr>
 		</table>
 	</td>
@@ -473,7 +474,7 @@
 </tr>
 
 <tr>
-	<td>{$lang_style_bottom}</td>
+	<td>{#style_dlg.bottom}</td>
 	<td class="delim">&nbsp;</td>
 	<td><select id="border_style_bottom" name="border_style_bottom" class="mceEditableSelect" disabled="disabled"></select></td>
 	<td class="delim">&nbsp;</td>
@@ -482,7 +483,7 @@
 			<tr>
 				<td><select id="border_width_bottom" name="border_width_bottom" class="mceEditableSelect" disabled="disabled"></select></td>
 				<td>&nbsp;</td>
-    <td><select id="border_width_bottom_measurement" name="border_width_bottom_measurement" disabled="disabled"></select></td>
+				<td><select id="border_width_bottom_measurement" name="border_width_bottom_measurement" disabled="disabled"></select></td>
 			</tr>
 		</table>
 	</td>
@@ -498,7 +499,7 @@
 </tr>
 
 <tr>
-	<td>{$lang_style_left}</td>
+	<td>{#style_dlg.left}</td>
 	<td class="delim">&nbsp;</td>
 	<td><select id="border_style_left" name="border_style_left" class="mceEditableSelect" disabled="disabled"></select></td>
 	<td class="delim">&nbsp;</td>
@@ -507,7 +508,7 @@
 			<tr>
 				<td><select id="border_width_left" name="border_width_left" class="mceEditableSelect" disabled="disabled"></select></td>
 				<td>&nbsp;</td>
-    <td><select id="border_width_left_measurement" name="border_width_left_measurement" disabled="disabled"></select></td>
+				<td><select id="border_width_left_measurement" name="border_width_left_measurement" disabled="disabled"></select></td>
 			</tr>
 		</table>
 	</td>
@@ -527,17 +528,17 @@
 <div id="list_panel" class="panel">
 	<table border="0">
 		<tr>
-			<td><label for="list_type">{$lang_style_list_type}</label></td>
+			<td><label for="list_type">{#style_dlg.list_type}</label></td>
 			<td><select id="list_type" name="list_type" class="mceEditableSelect"></select></td>
 		</tr>
 
 		<tr>
-			<td><label for="list_bullet_image">{$lang_style_bullet_image}</label></td>
+			<td><label for="list_bullet_image">{#style_dlg.bullet_image}</label></td>
 			<td><input id="list_bullet_image" name="list_bullet_image" type="text" /></td>
 		</tr>
 
 		<tr>
-			<td><label for="list_position">{$lang_style_position}</label></td>
+			<td><label for="list_position">{#style_dlg.position}</label></td>
 			<td><select id="list_position" name="list_position" class="mceEditableSelect"></select></td>
 		</tr>
 	</table>
@@ -546,96 +547,96 @@
 <div id="positioning_panel" class="panel">
 <table border="0">
 	<tr>
-		<td><label for="positioning_type">{$lang_style_positioning_type}</label></td>
+		<td><label for="positioning_type">{#style_dlg.positioning_type}</label></td>
 		<td><select id="positioning_type" name="positioning_type" class="mceEditableSelect"></select></td>
-		<td>&nbsp;&nbsp;&nbsp;<label for="positioning_visibility">{$lang_style_visibility}</label></td>
+		<td>&nbsp;&nbsp;&nbsp;<label for="positioning_visibility">{#style_dlg.visibility}</label></td>
 		<td><select id="positioning_visibility" name="positioning_visibility" class="mceEditableSelect"></select></td>
 	</tr>
 
 	<tr>
-		<td><label for="positioning_width">{$lang_style_width}</label></td>
+		<td><label for="positioning_width">{#style_dlg.width}</label></td>
 		<td>
 			<table border="0" cellspacing="0" cellpadding="0">
 				<tr>
 					<td><input type="text" id="positioning_width" name="positioning_width" onChange="synch('positioning_width','box_width');" /></td>
 					<td>&nbsp;</td>
-     <td><select id="positioning_width_measurement" name="positioning_width_measurement"></select></td>
+					<td><select id="positioning_width_measurement" name="positioning_width_measurement"></select></td>
 				</tr>
 			</table>
 		</td>
-		<td>&nbsp;&nbsp;&nbsp;<label for="positioning_zindex">{$lang_style_zindex}</label></td>
+		<td>&nbsp;&nbsp;&nbsp;<label for="positioning_zindex">{#style_dlg.zindex}</label></td>
 		<td><input type="text" id="positioning_zindex" name="positioning_zindex" /></td>
 	</tr>
 
 	<tr>
-		<td><label for="positioning_height">{$lang_style_height}</label></td>
+		<td><label for="positioning_height">{#style_dlg.height}</label></td>
 		<td>
 			<table border="0" cellspacing="0" cellpadding="0">
 				<tr>
 					<td><input type="text" id="positioning_height" name="positioning_height" onChange="synch('positioning_height','box_height');" /></td>
 					<td>&nbsp;</td>
-     <td><select id="positioning_height_measurement" name="positioning_height_measurement"></select></td>
+					<td><select id="positioning_height_measurement" name="positioning_height_measurement"></select></td>
 				</tr>
 			</table>
 		</td>
-		<td>&nbsp;&nbsp;&nbsp;<label for="positioning_overflow">{$lang_style_overflow}</label></td>
+		<td>&nbsp;&nbsp;&nbsp;<label for="positioning_overflow">{#style_dlg.overflow}</label></td>
 		<td><select id="positioning_overflow" name="positioning_overflow" class="mceEditableSelect"></select></td>
 	</tr>
 </table>
 
 <div style="float: left; width: 49%">
 	<fieldset>
-		<legend>{$lang_style_placement}</legend>
+		<legend>{#style_dlg.placement}</legend>
 
 		<table border="0">
 			<tr>
 				<td>&nbsp;</td>
-				<td><input type="checkbox" id="positioning_placement_same" name="positioning_placement_same" class="checkbox" checked="checked" onClick="toggleSame(this,'positioning_placement');" /> <label for="positioning_placement_same">{$lang_style_same}</label></td>
+				<td><input type="checkbox" id="positioning_placement_same" name="positioning_placement_same" class="checkbox" checked="checked" onClick="toggleSame(this,'positioning_placement');" /> <label for="positioning_placement_same">{#style_dlg.same}</label></td>
 			</tr>
 			<tr>
-				<td>{$lang_style_top}</td>
+				<td>{#style_dlg.top}</td>
 				<td>
 					<table border="0" cellspacing="0" cellpadding="0">
 						<tr>
 							<td><input type="text" id="positioning_placement_top" name="positioning_placement_top" /></td>
 							<td>&nbsp;</td>
-       <td><select id="positioning_placement_top_measurement" name="positioning_placement_top_measurement"></select></td>
+							<td><select id="positioning_placement_top_measurement" name="positioning_placement_top_measurement"></select></td>
 						</tr>
 					</table>
 				</td>
 			</tr>
 			<tr>
-				<td>{$lang_style_right}</td>
+				<td>{#style_dlg.right}</td>
 				<td>
 					<table border="0" cellspacing="0" cellpadding="0">
 						<tr>
 							<td><input type="text" id="positioning_placement_right" name="positioning_placement_right" disabled="disabled" /></td>
 							<td>&nbsp;</td>
-       <td><select id="positioning_placement_right_measurement" name="positioning_placement_right_measurement" disabled="disabled"></select></td>
+							<td><select id="positioning_placement_right_measurement" name="positioning_placement_right_measurement" disabled="disabled"></select></td>
 						</tr>
 					</table>
 				</td>
 			</tr>
 			<tr>
-				<td>{$lang_style_bottom}</td>
+				<td>{#style_dlg.bottom}</td>
 				<td>
 					<table border="0" cellspacing="0" cellpadding="0">
 						<tr>
 							<td><input type="text" id="positioning_placement_bottom" name="positioning_placement_bottom" disabled="disabled" /></td>
 							<td>&nbsp;</td>
-       <td><select id="positioning_placement_bottom_measurement" name="positioning_placement_bottom_measurement" disabled="disabled"></select></td>
+							<td><select id="positioning_placement_bottom_measurement" name="positioning_placement_bottom_measurement" disabled="disabled"></select></td>
 						</tr>
 					</table>
 				</td>
 			</tr>
 			<tr>
-				<td>{$lang_style_left}</td>
+				<td>{#style_dlg.left}</td>
 				<td>
 					<table border="0" cellspacing="0" cellpadding="0">
 						<tr>
 							<td><input type="text" id="positioning_placement_left" name="positioning_placement_left" disabled="disabled" /></td>
 							<td>&nbsp;</td>
-       <td><select id="positioning_placement_left_measurement" name="positioning_placement_left_measurement" disabled="disabled"></select></td>
+							<td><select id="positioning_placement_left_measurement" name="positioning_placement_left_measurement" disabled="disabled"></select></td>
 						</tr>
 					</table>
 				</td>
@@ -646,57 +647,57 @@
 
 <div style="float: right; width: 49%">
 	<fieldset>
-		<legend>{$lang_style_clip}</legend>
+		<legend>{#style_dlg.clip}</legend>
 
 		<table border="0">
 			<tr>
 				<td>&nbsp;</td>
-				<td><input type="checkbox" id="positioning_clip_same" name="positioning_clip_same" class="checkbox" checked="checked" onClick="toggleSame(this,'positioning_clip');" /> <label for="positioning_clip_same">{$lang_style_same}</label></td>
+				<td><input type="checkbox" id="positioning_clip_same" name="positioning_clip_same" class="checkbox" checked="checked" onClick="toggleSame(this,'positioning_clip');" /> <label for="positioning_clip_same">{#style_dlg.same}</label></td>
 			</tr>
 			<tr>
-				<td>{$lang_style_top}</td>
+				<td>{#style_dlg.top}</td>
 				<td>
 					<table border="0" cellspacing="0" cellpadding="0">
 						<tr>
 							<td><input type="text" id="positioning_clip_top" name="positioning_clip_top" /></td>
 							<td>&nbsp;</td>
-       <td><select id="positioning_clip_top_measurement" name="positioning_clip_top_measurement"></select></td>
+							<td><select id="positioning_clip_top_measurement" name="positioning_clip_top_measurement"></select></td>
 						</tr>
 					</table>
 				</td>
 			</tr>
 			<tr>
-				<td>{$lang_style_right}</td>
+				<td>{#style_dlg.right}</td>
 				<td>
 					<table border="0" cellspacing="0" cellpadding="0">
 						<tr>
 							<td><input type="text" id="positioning_clip_right" name="positioning_clip_right" disabled="disabled" /></td>
 							<td>&nbsp;</td>
-       <td><select id="positioning_clip_right_measurement" name="positioning_clip_right_measurement" disabled="disabled"></select></td>
+							<td><select id="positioning_clip_right_measurement" name="positioning_clip_right_measurement" disabled="disabled"></select></td>
 						</tr>
 					</table>
 				</td>
 			</tr>
 			<tr>
-				<td>{$lang_style_bottom}</td>
+				<td>{#style_dlg.bottom}</td>
 				<td>
 					<table border="0" cellspacing="0" cellpadding="0">
 						<tr>
 							<td><input type="text" id="positioning_clip_bottom" name="positioning_clip_bottom" disabled="disabled" /></td>
 							<td>&nbsp;</td>
-       <td><select id="positioning_clip_bottom_measurement" name="positioning_clip_bottom_measurement" disabled="disabled"></select></td>
+							<td><select id="positioning_clip_bottom_measurement" name="positioning_clip_bottom_measurement" disabled="disabled"></select></td>
 						</tr>
 					</table>
 				</td>
 			</tr>
 			<tr>
-				<td>{$lang_style_left}</td>
+				<td>{#style_dlg.left}</td>
 				<td>
 					<table border="0" cellspacing="0" cellpadding="0">
 						<tr>
 							<td><input type="text" id="positioning_clip_left" name="positioning_clip_left" disabled="disabled" /></td>
 							<td>&nbsp;</td>
-       <td><select id="positioning_clip_left_measurement" name="positioning_clip_left_measurement" disabled="disabled"></select></td>
+							<td><select id="positioning_clip_left_measurement" name="positioning_clip_left_measurement" disabled="disabled"></select></td>
 						</tr>
 					</table>
 				</td>
@@ -710,14 +711,14 @@
 
 <div class="mceActionPanel">
 	<div style="float: left">
-		<div style="float: left"><input type="button" id="insert" name="insert" value="{$lang_update}" onClick="updateAction();" /></div>
+		<div style="float: left"><input type="button" id="insert" name="insert" value="{#update}" onClick="updateAction();" /></div>
 
-		<div style="float: left">&nbsp;<input type="button" id="apply" name="apply" value="{$lang_style_apply}" onClick="applyAction();" class="updateButton" /></div>
+		<div style="float: left">&nbsp;<input type="button" class="button" id="apply" name="apply" value="{#style_dlg.apply}" onClick="applyAction();" /></div>
 		<br style="clear: both" />
 	</div>
 
 	<div style="float: right">
-		<input type="button" id="cancel" name="cancel" value="{$lang_cancel}" onClick="tinyMCEPopup.close();" />
+		<input type="button" id="cancel" name="cancel" value="{#cancel}" onClick="tinyMCEPopup.close();" />
 	</div>
 </div>
 </form>
@@ -725,5 +726,6 @@
 <div style="display: none">
 	<div id="container"></div>
 </div>
+
 </body>
 </html>
--- a/includes/clientside/tinymce/plugins/style/readme.txt	Fri Feb 22 12:46:51 2008 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1 +0,0 @@
-Check the TinyMCE documentation for details on this plugin.
--- a/includes/clientside/tinymce/plugins/table/cell.htm	Fri Feb 22 12:46:51 2008 -0500
+++ b/includes/clientside/tinymce/plugins/table/cell.htm	Fri Feb 22 12:51:53 2008 -0500
@@ -1,85 +1,86 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
 <html xmlns="http://www.w3.org/1999/xhtml">
 <head>
-	<title>{$lang_table_cell_title}</title>
-	<script language="javascript" type="text/javascript" src="../../tiny_mce_popup.js"></script>
-	<script language="javascript" type="text/javascript" src="../../utils/mctabs.js"></script>
-	<script language="javascript" type="text/javascript" src="../../utils/form_utils.js"></script>
-	<script language="javascript" type="text/javascript" src="jscripts/cell.js"></script>
+	<title>{#table_dlg.cell_title}</title>
+	<script type="text/javascript" src="../../tiny_mce_popup.js"></script>
+	<script type="text/javascript" src="../../utils/mctabs.js"></script>
+	<script type="text/javascript" src="../../utils/form_utils.js"></script>
+	<script type="text/javascript" src="js/cell.js"></script>
 	<link href="css/cell.css" rel="stylesheet" type="text/css" />
 	<base target="_self" />
 </head>
-<body id="tablecell" onload="tinyMCEPopup.executeOnLoad('init();');" style="display: none">
+<body id="tablecell" style="display: none">
 	<form onsubmit="updateAction();return false;" action="#">
 		<div class="tabs">
 			<ul>
-				<li id="general_tab" class="current"><span><a href="javascript:mcTabs.displayTab('general_tab','general_panel');" onmousedown="return false;">{$lang_table_general_tab}</a></span></li>
-				<li id="advanced_tab"><span><a href="javascript:mcTabs.displayTab('advanced_tab','advanced_panel');" onmousedown="return false;">{$lang_table_advanced_tab}</a></span></li>
+				<li id="general_tab" class="current"><span><a href="javascript:mcTabs.displayTab('general_tab','general_panel');" onmousedown="return false;">{#table_dlg.general_tab}</a></span></li>
+				<li id="advanced_tab"><span><a href="javascript:mcTabs.displayTab('advanced_tab','advanced_panel');" onmousedown="return false;">{#table_dlg.advanced_tab}</a></span></li>
 			</ul>
 		</div>
 
 		<div class="panel_wrapper">
 			<div id="general_panel" class="panel current">
 				<fieldset>
-					<legend>{$lang_table_general_props}</legend>
+					<legend>{#table_dlg.general_props}</legend>
 
 					<table border="0" cellpadding="4" cellspacing="0">
 						<tr>
-							<td><label for="align">{$lang_table_align}</label></td>
+							<td><label for="align">{#table_dlg.align}</label></td>
 							<td>
 								<select id="align" name="align">
-									<option value="">{$lang_not_set}</option>
-									<option value="center">{$lang_table_align_middle}</option>
-									<option value="left">{$lang_table_align_left}</option>
-									<option value="right">{$lang_table_align_right}</option>
+									<option value="">{#not_set}</option>
+									<option value="center">{#table_dlg.align_middle}</option>
+									<option value="left">{#table_dlg.align_left}</option>
+									<option value="right">{#table_dlg.align_right}</option>
 								</select>
 							</td>
 		
-							<td><label for="celltype">{$lang_table_cell_type}</label></td>
+							<td><label for="celltype">{#table_dlg.cell_type}</label></td>
 							<td>
 								<select id="celltype" name="celltype">
-									<option value="td">{$lang_table_td}</option>
-									<option value="th">{$lang_table_th}</option>
+									<option value="td">{#table_dlg.td}</option>
+									<option value="th">{#table_dlg.th}</option>
 								</select>
 							</td>
 						</tr>
 
 						<tr>
-							<td><label for="valign">{$lang_table_valign}</label></td>
+							<td><label for="valign">{#table_dlg.valign}</label></td>
 							<td>
 								<select id="valign" name="valign">
-									<option value="">{$lang_not_set}</option>
-									<option value="top">{$lang_table_align_top}</option>
-									<option value="middle">{$lang_table_align_middle}</option>
-									<option value="bottom">{$lang_table_align_bottom}</option>
+									<option value="">{#not_set}</option>
+									<option value="top">{#table_dlg.align_top}</option>
+									<option value="middle">{#table_dlg.align_middle}</option>
+									<option value="bottom">{#table_dlg.align_bottom}</option>
 								</select>
 							</td>
 
-							<td><label for="scope">{$lang_table_scope}</label></td>
+							<td><label for="scope">{#table_dlg.scope}</label></td>
 							<td>
 								<select id="scope" name="scope">
-									<option value="">{$lang_not_set}</option>
-									<option value="col">{$lang_table_col}</option>
-									<option value="row">{$lang_table_row}</option>
-									<option value="rowgroup">{$lang_table_rowgroup}</option>
-									<option value="colgroup">{$lang_table_colgroup}</option>
+									<option value="">{#not_set}</option>
+									<option value="col">{#table.col}</option>
+									<option value="row">{#table.row}</option>
+									<option value="rowgroup">{#table_dlg.rowgroup}</option>
+									<option value="colgroup">{#table_dlg.colgroup}</option>
 								</select>
 							</td>
 
 						</tr>
 
 						<tr>
-							<td><label for="width">{$lang_table_width}</label></td>
+							<td><label for="width">{#table_dlg.width}</label></td>
 							<td><input id="width" name="width" type="text" value="" size="4" maxlength="4" onchange="changedSize();" /></td>
 
-							<td><label for="height">{$lang_table_height}</label></td>
+							<td><label for="height">{#table_dlg.height}</label></td>
 							<td><input id="height" name="height" type="text" value="" size="4" maxlength="4" onchange="changedSize();" /></td>
 						</tr>
 
 						<tr id="styleSelectRow">
-							<td><label for="class">{$lang_class_name}</label></td>
+							<td><label for="class">{#class_name}</label></td>
 							<td colspan="3">
 								<select id="class" name="class">
-									<option value="" selected="selected">{$lang_not_set}</option>
+									<option value="" selected="selected">{#not_set}</option>
 								</select>
 							</td>
 						</tr>
@@ -89,39 +90,39 @@
 
 			<div id="advanced_panel" class="panel">
 				<fieldset>
-					<legend>{$lang_table_advanced_props}</legend>
+					<legend>{#table_dlg.advanced_props}</legend>
 
 					<table border="0" cellpadding="0" cellspacing="4">
 						<tr>
-							<td class="column1"><label for="id">{$lang_table_id}</label></td> 
+							<td class="column1"><label for="id">{#table_dlg.id}</label></td> 
 							<td><input id="id" name="id" type="text" value="" style="width: 200px" /></td> 
 						</tr>
 
 						<tr>
-							<td><label for="style">{$lang_table_style}</label></td>
+							<td><label for="style">{#table_dlg.style}</label></td>
 							<td><input type="text" id="style" name="style" value="" style="width: 200px;" onchange="changedStyle();" /></td>
 						</tr>
 
 						<tr>
-							<td class="column1"><label for="dir">{$lang_table_langdir}</label></td> 
+							<td class="column1"><label for="dir">{#table_dlg.langdir}</label></td> 
 							<td>
 								<select id="dir" name="dir" style="width: 200px"> 
-										<option value="">{$lang_not_set}</option> 
-										<option value="ltr">{$lang_table_ltr}</option> 
-										<option value="rtl">{$lang_table_rtl}</option> 
+										<option value="">{#not_set}</option> 
+										<option value="ltr">{#table_dlg.ltr}</option> 
+										<option value="rtl">{#table_dlg.rtl}</option> 
 								</select>
 							</td> 
 						</tr>
 
 						<tr>
-							<td class="column1"><label for="lang">{$lang_table_langcode}</label></td> 
+							<td class="column1"><label for="lang">{#table_dlg.langcode}</label></td> 
 							<td>
 								<input id="lang" name="lang" type="text" value="" style="width: 200px" />
 							</td> 
 						</tr>
 
 						<tr>
-							<td class="column1"><label for="backgroundimage">{$lang_table_bgimage}</label></td> 
+							<td class="column1"><label for="backgroundimage">{#table_dlg.bgimage}</label></td> 
 							<td>
 								<table border="0" cellpadding="0" cellspacing="0">
 									<tr>
@@ -133,7 +134,7 @@
 						</tr>
 
 						<tr>
-							<td class="column1"><label for="bordercolor">{$lang_table_bordercolor}</label></td> 
+							<td class="column1"><label for="bordercolor">{#table_dlg.bordercolor}</label></td> 
 							<td>
 								<table border="0" cellpadding="0" cellspacing="0">
 									<tr>
@@ -145,7 +146,7 @@
 						</tr>
 
 						<tr>
-							<td class="column1"><label for="bgcolor">{$lang_table_bgcolor}</label></td> 
+							<td class="column1"><label for="bgcolor">{#table_dlg.bgcolor}</label></td> 
 							<td>
 								<table border="0" cellpadding="0" cellspacing="0">
 									<tr>
@@ -163,18 +164,18 @@
 		<div class="mceActionPanel">
 			<div>
 				<select id="action" name="action">
-					<option value="cell">{$lang_table_cell_cell}</option>
-					<option value="row">{$lang_table_cell_row}</option>
-					<option value="all">{$lang_table_cell_all}</option>
+					<option value="cell">{#table_dlg.cell_cell}</option>
+					<option value="row">{#table_dlg.cell_row}</option>
+					<option value="all">{#table_dlg.cell_all}</option>
 				</select>
 			</div>
 
 			<div style="float: left">
-				<div><input type="button" id="insert" name="insert" value="{$lang_update}" onclick="updateAction();" /></div>
+				<div><input type="button" id="insert" name="insert" value="{#update}" onclick="updateAction();" /></div>
 			</div>
 
 			<div style="float: right">
-				<input type="button" id="cancel" name="cancel" value="{$lang_cancel}" onclick="tinyMCEPopup.close();" />
+				<input type="button" id="cancel" name="cancel" value="{#cancel}" onclick="tinyMCEPopup.close();" />
 			</div>
 		</div>
 	</form>
--- a/includes/clientside/tinymce/plugins/table/css/table.css	Fri Feb 22 12:46:51 2008 -0500
+++ b/includes/clientside/tinymce/plugins/table/css/table.css	Fri Feb 22 12:51:53 2008 -0500
@@ -1,7 +1,7 @@
 /* CSS file for table dialog in the table plugin */
 
 .panel_wrapper div.current {
-	height: 220px;
+	height: 245px;
 }
 
 .advfield {
--- a/includes/clientside/tinymce/plugins/table/editor_plugin.js	Fri Feb 22 12:46:51 2008 -0500
+++ b/includes/clientside/tinymce/plugins/table/editor_plugin.js	Fri Feb 22 12:51:53 2008 -0500
@@ -1,1 +1,1 @@
-tinyMCE.importPluginLanguagePack('table');var TinyMCE_TablePlugin={getInfo:function(){return{longname:'Tables',author:'Moxiecode Systems AB',authorurl:'http://tinymce.moxiecode.com',infourl:'http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/table',version:tinyMCE.majorVersion+"."+tinyMCE.minorVersion}},initInstance:function(inst){if(tinyMCE.isGecko){var doc=inst.getDoc();tinyMCE.addEvent(doc,"mouseup",TinyMCE_TablePlugin._mouseDownHandler)}inst.tableRowClipboard=null},getControlHTML:function(control_name){var controls=new Array(['table','table.gif','lang_table_desc','mceInsertTable',true],['delete_table','table_delete.gif','lang_table_del','mceTableDelete'],['delete_col','table_delete_col.gif','lang_table_delete_col_desc','mceTableDeleteCol'],['delete_row','table_delete_row.gif','lang_table_delete_row_desc','mceTableDeleteRow'],['col_after','table_insert_col_after.gif','lang_table_col_after_desc','mceTableInsertColAfter'],['col_before','table_insert_col_before.gif','lang_table_col_before_desc','mceTableInsertColBefore'],['row_after','table_insert_row_after.gif','lang_table_row_after_desc','mceTableInsertRowAfter'],['row_before','table_insert_row_before.gif','lang_table_row_before_desc','mceTableInsertRowBefore'],['row_props','table_row_props.gif','lang_table_row_desc','mceTableRowProps',true],['cell_props','table_cell_props.gif','lang_table_cell_desc','mceTableCellProps',true],['split_cells','table_split_cells.gif','lang_table_split_cells_desc','mceTableSplitCells',true],['merge_cells','table_merge_cells.gif','lang_table_merge_cells_desc','mceTableMergeCells',true]);for(var i=0;i<controls.length;i++){var but=controls[i];var cmd='tinyMCE.execInstanceCommand(\'{$editor_id}\',\''+but[3]+'\', '+(but.length>4?but[4]:false)+(but.length>5?', \''+but[5]+'\'':'')+');return false;';if(but[0]==control_name)return tinyMCE.getButtonHTML(control_name,but[2],'{$pluginurl}/images/'+but[1],but[3],(but.length>4?but[4]:false))}if(control_name=="tablecontrols"){var html="";html+=tinyMCE.getControlHTML("table");html+=tinyMCE.getControlHTML("separator");html+=tinyMCE.getControlHTML("row_props");html+=tinyMCE.getControlHTML("cell_props");html+=tinyMCE.getControlHTML("separator");html+=tinyMCE.getControlHTML("row_before");html+=tinyMCE.getControlHTML("row_after");html+=tinyMCE.getControlHTML("delete_row");html+=tinyMCE.getControlHTML("separator");html+=tinyMCE.getControlHTML("col_before");html+=tinyMCE.getControlHTML("col_after");html+=tinyMCE.getControlHTML("delete_col");html+=tinyMCE.getControlHTML("separator");html+=tinyMCE.getControlHTML("split_cells");html+=tinyMCE.getControlHTML("merge_cells");return html}return""},execCommand:function(editor_id,element,command,user_interface,value){switch(command){case"mceInsertTable":case"mceTableRowProps":case"mceTableCellProps":case"mceTableSplitCells":case"mceTableMergeCells":case"mceTableInsertRowBefore":case"mceTableInsertRowAfter":case"mceTableDeleteRow":case"mceTableInsertColBefore":case"mceTableInsertColAfter":case"mceTableDeleteCol":case"mceTableCutRow":case"mceTableCopyRow":case"mceTablePasteRowBefore":case"mceTablePasteRowAfter":case"mceTableDelete":var inst=tinyMCE.getInstanceById(editor_id);inst.execCommand('mceBeginUndoLevel');TinyMCE_TablePlugin._doExecCommand(editor_id,element,command,user_interface,value);inst.execCommand('mceEndUndoLevel');return true}return false},handleNodeChange:function(editor_id,node,undo_index,undo_levels,visual_aid,any_selection){var colspan="1",rowspan="1",tdElm;var inst=tinyMCE.getInstanceById(editor_id);tinyMCE.switchClass(editor_id+'_table','mceButtonNormal');tinyMCE.switchClass(editor_id+'_delete_table','mceButtonDisabled');tinyMCE.switchClass(editor_id+'_row_props','mceButtonDisabled');tinyMCE.switchClass(editor_id+'_cell_props','mceButtonDisabled');tinyMCE.switchClass(editor_id+'_row_before','mceButtonDisabled');tinyMCE.switchClass(editor_id+'_row_after','mceButtonDisabled');tinyMCE.switchClass(editor_id+'_delete_row','mceButtonDisabled');tinyMCE.switchClass(editor_id+'_col_before','mceButtonDisabled');tinyMCE.switchClass(editor_id+'_col_after','mceButtonDisabled');tinyMCE.switchClass(editor_id+'_delete_col','mceButtonDisabled');tinyMCE.switchClass(editor_id+'_split_cells','mceButtonDisabled');tinyMCE.switchClass(editor_id+'_merge_cells','mceButtonDisabled');if(tdElm=tinyMCE.getParentElement(node,"td,th")){tinyMCE.switchClass(editor_id+'_cell_props','mceButtonSelected');tinyMCE.switchClass(editor_id+'_delete_table','mceButtonNormal');tinyMCE.switchClass(editor_id+'_row_before','mceButtonNormal');tinyMCE.switchClass(editor_id+'_row_after','mceButtonNormal');tinyMCE.switchClass(editor_id+'_delete_row','mceButtonNormal');tinyMCE.switchClass(editor_id+'_col_before','mceButtonNormal');tinyMCE.switchClass(editor_id+'_col_after','mceButtonNormal');tinyMCE.switchClass(editor_id+'_delete_col','mceButtonNormal');colspan=tinyMCE.getAttrib(tdElm,"colspan");rowspan=tinyMCE.getAttrib(tdElm,"rowspan");colspan=colspan==""?"1":colspan;rowspan=rowspan==""?"1":rowspan;if(colspan!="1"||rowspan!="1")tinyMCE.switchClass(editor_id+'_split_cells','mceButtonNormal')}if(tinyMCE.getParentElement(node,"tr"))tinyMCE.switchClass(editor_id+'_row_props','mceButtonSelected');if(tinyMCE.getParentElement(node,"table")){tinyMCE.switchClass(editor_id+'_table','mceButtonSelected');tinyMCE.switchClass(editor_id+'_merge_cells','mceButtonNormal')}},_mouseDownHandler:function(e){var elm=tinyMCE.isMSIE?event.srcElement:e.target;var focusElm=tinyMCE.selectedInstance.getFocusElement();if(elm.nodeName=="BODY"&&(focusElm.nodeName=="TD"||focusElm.nodeName=="TH"||(focusElm.parentNode&&focusElm.parentNode.nodeName=="TD")||(focusElm.parentNode&&focusElm.parentNode.nodeName=="TH"))){window.setTimeout(function(){var tableElm=tinyMCE.getParentElement(focusElm,"table");tinyMCE.handleVisualAid(tableElm,true,tinyMCE.settings['visual'],tinyMCE.selectedInstance)},10)}},_doExecCommand:function(editor_id,element,command,user_interface,value){var inst=tinyMCE.getInstanceById(editor_id);var focusElm=inst.getFocusElement();var trElm=tinyMCE.getParentElement(focusElm,"tr");var tdElm=tinyMCE.getParentElement(focusElm,"td,th");var tableElm=tinyMCE.getParentElement(focusElm,"table");var doc=inst.contentWindow.document;var tableBorder=tableElm?tableElm.getAttribute("border"):"";if(trElm&&tdElm==null)tdElm=trElm.cells[0];function inArray(ar,v){for(var i=0;i<ar.length;i++){if(ar[i].length>0&&inArray(ar[i],v))return true;if(ar[i]==v)return true}return false}function makeTD(){var newTD=doc.createElement("td");newTD.innerHTML="&nbsp;"}function getColRowSpan(td){var colspan=tinyMCE.getAttrib(td,"colspan");var rowspan=tinyMCE.getAttrib(td,"rowspan");colspan=colspan==""?1:parseInt(colspan);rowspan=rowspan==""?1:parseInt(rowspan);return{colspan:colspan,rowspan:rowspan}}function getCellPos(grid,td){var x,y;for(y=0;y<grid.length;y++){for(x=0;x<grid[y].length;x++){if(grid[y][x]==td)return{cellindex:x,rowindex:y}}}return null}function getCell(grid,row,col){if(grid[row]&&grid[row][col])return grid[row][col];return null}function getTableGrid(table){var grid=new Array(),rows=table.rows,x,y,td,sd,xstart,x2,y2;for(y=0;y<rows.length;y++){for(x=0;x<rows[y].cells.length;x++){td=rows[y].cells[x];sd=getColRowSpan(td);for(xstart=x;grid[y]&&grid[y][xstart];xstart++);for(y2=y;y2<y+sd['rowspan'];y2++){if(!grid[y2])grid[y2]=new Array();for(x2=xstart;x2<xstart+sd['colspan'];x2++)grid[y2][x2]=td}}}return grid}function trimRow(table,tr,td,new_tr){var grid=getTableGrid(table),cpos=getCellPos(grid,td);var cells,lastElm;if(new_tr.cells.length!=tr.childNodes.length){cells=tr.childNodes;lastElm=null;for(var x=0;td=getCell(grid,cpos.rowindex,x);x++){var remove=true;var sd=getColRowSpan(td);if(inArray(cells,td)){new_tr.childNodes[x]._delete=true}else if((lastElm==null||td!=lastElm)&&sd.colspan>1){for(var i=x;i<x+td.colSpan;i++)new_tr.childNodes[i]._delete=true}if((lastElm==null||td!=lastElm)&&sd.rowspan>1)td.rowSpan=sd.rowspan+1;lastElm=td}deleteMarked(tableElm)}}function prevElm(node,name){while((node=node.previousSibling)!=null){if(node.nodeName==name)return node}return null}function nextElm(node,names){var namesAr=names.split(',');while((node=node.nextSibling)!=null){for(var i=0;i<namesAr.length;i++){if(node.nodeName.toLowerCase()==namesAr[i].toLowerCase())return node}}return null}function deleteMarked(tbl){if(tbl.rows==0)return;var tr=tbl.rows[0];do{var next=nextElm(tr,"TR");if(tr._delete){tr.parentNode.removeChild(tr);continue}var td=tr.cells[0];if(td.cells>1){do{var nexttd=nextElm(td,"TD,TH");if(td._delete)td.parentNode.removeChild(td)}while((td=nexttd)!=null)}}while((tr=next)!=null)}function addRows(td_elm,tr_elm,rowspan){td_elm.rowSpan=1;var trNext=nextElm(tr_elm,"TR");for(var i=1;i<rowspan&&trNext;i++){var newTD=doc.createElement("td");newTD.innerHTML="&nbsp;";if(tinyMCE.isMSIE)trNext.insertBefore(newTD,trNext.cells(td_elm.cellIndex));else trNext.insertBefore(newTD,trNext.cells[td_elm.cellIndex]);trNext=nextElm(trNext,"TR")}}function copyRow(doc,table,tr){var grid=getTableGrid(table);var newTR=tr.cloneNode(false);var cpos=getCellPos(grid,tr.cells[0]);var lastCell=null;var tableBorder=tinyMCE.getAttrib(table,"border");var tdElm=null;for(var x=0;tdElm=getCell(grid,cpos.rowindex,x);x++){var newTD=null;if(lastCell!=tdElm){for(var i=0;i<tr.cells.length;i++){if(tdElm==tr.cells[i]){newTD=tdElm.cloneNode(true);break}}}if(newTD==null){newTD=doc.createElement("td");newTD.innerHTML="&nbsp;"}newTD.colSpan=1;newTD.rowSpan=1;newTR.appendChild(newTD);lastCell=tdElm}return newTR}switch(command){case"mceTableRowProps":if(trElm==null)return true;if(user_interface){var template=new Array();template['file']='../../plugins/table/row.htm';template['width']=380;template['height']=295;template['width']+=tinyMCE.getLang('lang_table_rowprops_delta_width',0);template['height']+=tinyMCE.getLang('lang_table_rowprops_delta_height',0);tinyMCE.openWindow(template,{editor_id:inst.editorId,inline:"yes"})}return true;case"mceTableCellProps":if(tdElm==null)return true;if(user_interface){var template=new Array();template['file']='../../plugins/table/cell.htm';template['width']=380;template['height']=295;template['width']+=tinyMCE.getLang('lang_table_cellprops_delta_width',0);template['height']+=tinyMCE.getLang('lang_table_cellprops_delta_height',0);tinyMCE.openWindow(template,{editor_id:inst.editorId,inline:"yes"})}return true;case"mceInsertTable":if(user_interface){var template=new Array();template['file']='../../plugins/table/table.htm';template['width']=380;template['height']=295;template['width']+=tinyMCE.getLang('lang_table_table_delta_width',0);template['height']+=tinyMCE.getLang('lang_table_table_delta_height',0);tinyMCE.openWindow(template,{editor_id:inst.editorId,inline:"yes",action:value})}return true;case"mceTableDelete":var table=tinyMCE.getParentElement(inst.getFocusElement(),"table");if(table){table.parentNode.removeChild(table);inst.repaint()}return true;case"mceTableSplitCells":case"mceTableMergeCells":case"mceTableInsertRowBefore":case"mceTableInsertRowAfter":case"mceTableDeleteRow":case"mceTableInsertColBefore":case"mceTableInsertColAfter":case"mceTableDeleteCol":case"mceTableCutRow":case"mceTableCopyRow":case"mceTablePasteRowBefore":case"mceTablePasteRowAfter":if(!tableElm)return true;if(trElm&&tableElm!=trElm.parentNode)tableElm=trElm.parentNode;if(tableElm&&trElm){switch(command){case"mceTableCutRow":if(!trElm||!tdElm)return true;inst.tableRowClipboard=copyRow(doc,tableElm,trElm);inst.execCommand("mceTableDeleteRow");break;case"mceTableCopyRow":if(!trElm||!tdElm)return true;inst.tableRowClipboard=copyRow(doc,tableElm,trElm);break;case"mceTablePasteRowBefore":if(!trElm||!tdElm)return true;var newTR=inst.tableRowClipboard.cloneNode(true);var prevTR=prevElm(trElm,"TR");if(prevTR!=null)trimRow(tableElm,prevTR,prevTR.cells[0],newTR);trElm.parentNode.insertBefore(newTR,trElm);break;case"mceTablePasteRowAfter":if(!trElm||!tdElm)return true;var nextTR=nextElm(trElm,"TR");var newTR=inst.tableRowClipboard.cloneNode(true);trimRow(tableElm,trElm,tdElm,newTR);if(nextTR==null)trElm.parentNode.appendChild(newTR);else nextTR.parentNode.insertBefore(newTR,nextTR);break;case"mceTableInsertRowBefore":if(!trElm||!tdElm)return true;var grid=getTableGrid(tableElm);var cpos=getCellPos(grid,tdElm);var newTR=doc.createElement("tr");var lastTDElm=null;cpos.rowindex--;if(cpos.rowindex<0)cpos.rowindex=0;for(var x=0;tdElm=getCell(grid,cpos.rowindex,x);x++){if(tdElm!=lastTDElm){var sd=getColRowSpan(tdElm);if(sd['rowspan']==1){var newTD=doc.createElement("td");newTD.innerHTML="&nbsp;";newTD.colSpan=tdElm.colSpan;newTR.appendChild(newTD)}else tdElm.rowSpan=sd['rowspan']+1;lastTDElm=tdElm}}trElm.parentNode.insertBefore(newTR,trElm);grid=getTableGrid(tableElm);inst.selection.selectNode(getCell(grid,cpos.rowindex+1,cpos.cellindex),tinyMCE.isGecko,true);break;case"mceTableInsertRowAfter":if(!trElm||!tdElm)return true;var grid=getTableGrid(tableElm);var cpos=getCellPos(grid,tdElm);var newTR=doc.createElement("tr");var lastTDElm=null;for(var x=0;tdElm=getCell(grid,cpos.rowindex,x);x++){if(tdElm!=lastTDElm){var sd=getColRowSpan(tdElm);if(sd['rowspan']==1){var newTD=doc.createElement("td");newTD.innerHTML="&nbsp;";newTD.colSpan=tdElm.colSpan;newTR.appendChild(newTD)}else tdElm.rowSpan=sd['rowspan']+1;lastTDElm=tdElm}}if(newTR.hasChildNodes()){var nextTR=nextElm(trElm,"TR");if(nextTR)nextTR.parentNode.insertBefore(newTR,nextTR);else tableElm.appendChild(newTR)}grid=getTableGrid(tableElm);inst.selection.selectNode(getCell(grid,cpos.rowindex,cpos.cellindex),tinyMCE.isGecko,true);break;case"mceTableDeleteRow":if(!trElm||!tdElm)return true;var grid=getTableGrid(tableElm);var cpos=getCellPos(grid,tdElm);if(grid.length==1){tableElm=tinyMCE.getParentElement(tableElm,"table");tableElm.parentNode.removeChild(tableElm);return true}var cells=trElm.cells;var nextTR=nextElm(trElm,"TR");for(var x=0;x<cells.length;x++){if(cells[x].rowSpan>1){var newTD=cells[x].cloneNode(true);var sd=getColRowSpan(cells[x]);newTD.rowSpan=sd.rowspan-1;var nextTD=nextTR.cells[x];if(nextTD==null)nextTR.appendChild(newTD);else nextTR.insertBefore(newTD,nextTD)}}var lastTDElm=null;for(var x=0;tdElm=getCell(grid,cpos.rowindex,x);x++){if(tdElm!=lastTDElm){var sd=getColRowSpan(tdElm);if(sd.rowspan>1){tdElm.rowSpan=sd.rowspan-1}else{trElm=tdElm.parentNode;if(trElm.parentNode)trElm._delete=true}lastTDElm=tdElm}}deleteMarked(tableElm);cpos.rowindex--;if(cpos.rowindex<0)cpos.rowindex=0;grid=getTableGrid(tableElm);inst.selection.selectNode(getCell(grid,cpos.rowindex,0),tinyMCE.isGecko,true);break;case"mceTableInsertColBefore":if(!trElm||!tdElm)return true;var grid=getTableGrid(tableElm);var cpos=getCellPos(grid,tdElm);var lastTDElm=null;for(var y=0;tdElm=getCell(grid,y,cpos.cellindex);y++){if(tdElm!=lastTDElm){var sd=getColRowSpan(tdElm);if(sd['colspan']==1){var newTD=doc.createElement(tdElm.nodeName);newTD.innerHTML="&nbsp;";newTD.rowSpan=tdElm.rowSpan;tdElm.parentNode.insertBefore(newTD,tdElm)}else tdElm.colSpan++;lastTDElm=tdElm}}grid=getTableGrid(tableElm);inst.selection.selectNode(getCell(grid,cpos.rowindex,cpos.cellindex+1),tinyMCE.isGecko,true);break;case"mceTableInsertColAfter":if(!trElm||!tdElm)return true;var grid=getTableGrid(tableElm);var cpos=getCellPos(grid,tdElm);var lastTDElm=null;for(var y=0;tdElm=getCell(grid,y,cpos.cellindex);y++){if(tdElm!=lastTDElm){var sd=getColRowSpan(tdElm);if(sd['colspan']==1){var newTD=doc.createElement(tdElm.nodeName);newTD.innerHTML="&nbsp;";newTD.rowSpan=tdElm.rowSpan;var nextTD=nextElm(tdElm,"TD,TH");if(nextTD==null)tdElm.parentNode.appendChild(newTD);else nextTD.parentNode.insertBefore(newTD,nextTD)}else tdElm.colSpan++;lastTDElm=tdElm}}grid=getTableGrid(tableElm);inst.selection.selectNode(getCell(grid,cpos.rowindex,cpos.cellindex),tinyMCE.isGecko,true);break;case"mceTableDeleteCol":if(!trElm||!tdElm)return true;var grid=getTableGrid(tableElm);var cpos=getCellPos(grid,tdElm);var lastTDElm=null;if(grid.length>1&&grid[0].length<=1){tableElm=tinyMCE.getParentElement(tableElm,"table");tableElm.parentNode.removeChild(tableElm);return true}for(var y=0;tdElm=getCell(grid,y,cpos.cellindex);y++){if(tdElm!=lastTDElm){var sd=getColRowSpan(tdElm);if(sd['colspan']>1)tdElm.colSpan=sd['colspan']-1;else{if(tdElm.parentNode)tdElm.parentNode.removeChild(tdElm)}lastTDElm=tdElm}}cpos.cellindex--;if(cpos.cellindex<0)cpos.cellindex=0;grid=getTableGrid(tableElm);inst.selection.selectNode(getCell(grid,cpos.rowindex,0),tinyMCE.isGecko,true);break;case"mceTableSplitCells":if(!trElm||!tdElm)return true;var spandata=getColRowSpan(tdElm);var colspan=spandata["colspan"];var rowspan=spandata["rowspan"];if(colspan>1||rowspan>1){tdElm.colSpan=1;for(var i=1;i<colspan;i++){var newTD=doc.createElement("td");newTD.innerHTML="&nbsp;";trElm.insertBefore(newTD,nextElm(tdElm,"TD,TH"));if(rowspan>1)addRows(newTD,trElm,rowspan)}addRows(tdElm,trElm,rowspan)}tableElm=tinyMCE.getParentElement(inst.getFocusElement(),"table");break;case"mceTableMergeCells":var rows=new Array();var sel=inst.getSel();var grid=getTableGrid(tableElm);if(tinyMCE.isMSIE||sel.rangeCount==1){if(user_interface){var template=new Array();var sp=getColRowSpan(tdElm);template['file']='../../plugins/table/merge_cells.htm';template['width']=250;template['height']=105+(tinyMCE.isNS7?25:0);template['width']+=tinyMCE.getLang('lang_table_merge_cells_delta_width',0);template['height']+=tinyMCE.getLang('lang_table_merge_cells_delta_height',0);tinyMCE.openWindow(template,{editor_id:inst.editorId,inline:"yes",action:"update",numcols:sp.colspan,numrows:sp.rowspan});return true}else{var numRows=parseInt(value['numrows']);var numCols=parseInt(value['numcols']);var cpos=getCellPos(grid,tdElm);if((""+numRows)=="NaN")numRows=1;if((""+numCols)=="NaN")numCols=1;var tRows=tableElm.rows;for(var y=cpos.rowindex;y<grid.length;y++){var rowCells=new Array();for(var x=cpos.cellindex;x<grid[y].length;x++){var td=getCell(grid,y,x);if(td&&!inArray(rows,td)&&!inArray(rowCells,td)){var cp=getCellPos(grid,td);if(cp.cellindex<cpos.cellindex+numCols&&cp.rowindex<cpos.rowindex+numRows)rowCells[rowCells.length]=td}}if(rowCells.length>0)rows[rows.length]=rowCells}}}else{var cells=new Array();var sel=inst.getSel();var lastTR=null;var curRow=null;var x1=-1,y1=-1,x2,y2;if(sel.rangeCount<2)return true;for(var i=0;i<sel.rangeCount;i++){var rng=sel.getRangeAt(i);var tdElm=rng.startContainer.childNodes[rng.startOffset];if(!tdElm)break;if(tdElm.nodeName=="TD")cells[cells.length]=tdElm}var tRows=tableElm.rows;for(var y=0;y<tRows.length;y++){var rowCells=new Array();for(var x=0;x<tRows[y].cells.length;x++){var td=tRows[y].cells[x];for(var i=0;i<cells.length;i++){if(td==cells[i]){rowCells[rowCells.length]=td}}}if(rowCells.length>0)rows[rows.length]=rowCells}var curRow=new Array();var lastTR=null;for(var y=0;y<grid.length;y++){for(var x=0;x<grid[y].length;x++){grid[y][x]._selected=false;for(var i=0;i<cells.length;i++){if(grid[y][x]==cells[i]){if(x1==-1){x1=x;y1=y}x2=x;y2=y;grid[y][x]._selected=true}}}}for(var y=y1;y<=y2;y++){for(var x=x1;x<=x2;x++){if(!grid[y][x]._selected){alert("Invalid selection for merge.");return true}}}}var rowSpan=1,colSpan=1;var lastRowSpan=-1;for(var y=0;y<rows.length;y++){var rowColSpan=0;for(var x=0;x<rows[y].length;x++){var sd=getColRowSpan(rows[y][x]);rowColSpan+=sd['colspan'];if(lastRowSpan!=-1&&sd['rowspan']!=lastRowSpan){alert("Invalid selection for merge.");return true}lastRowSpan=sd['rowspan']}if(rowColSpan>colSpan)colSpan=rowColSpan;lastRowSpan=-1}var lastColSpan=-1;for(var x=0;x<rows[0].length;x++){var colRowSpan=0;for(var y=0;y<rows.length;y++){var sd=getColRowSpan(rows[y][x]);colRowSpan+=sd['rowspan'];if(lastColSpan!=-1&&sd['colspan']!=lastColSpan){alert("Invalid selection for merge.");return true}lastColSpan=sd['colspan']}if(colRowSpan>rowSpan)rowSpan=colRowSpan;lastColSpan=-1}tdElm=rows[0][0];tdElm.rowSpan=rowSpan;tdElm.colSpan=colSpan;for(var y=0;y<rows.length;y++){for(var x=0;x<rows[y].length;x++){var html=rows[y][x].innerHTML;var chk=tinyMCE.regexpReplace(html,"[ \t\r\n]","");if(chk!="<br/>"&&chk!="<br>"&&chk!="&nbsp;"&&(x+y>0))tdElm.innerHTML+=html;if(rows[y][x]!=tdElm&&!rows[y][x]._deleted){var cpos=getCellPos(grid,rows[y][x]);var tr=rows[y][x].parentNode;tr.removeChild(rows[y][x]);rows[y][x]._deleted=true;if(!tr.hasChildNodes()){tr.parentNode.removeChild(tr);var lastCell=null;for(var x=0;cellElm=getCell(grid,cpos.rowindex,x);x++){if(cellElm!=lastCell&&cellElm.rowSpan>1)cellElm.rowSpan--;lastCell=cellElm}if(tdElm.rowSpan>1)tdElm.rowSpan--}}}}break}tableElm=tinyMCE.getParentElement(inst.getFocusElement(),"table");tinyMCE.handleVisualAid(tableElm,true,tinyMCE.settings['visual'],tinyMCE.selectedInstance);tinyMCE.triggerNodeChange();inst.repaint()}return true}return false}};tinyMCE.addPlugin("table",TinyMCE_TablePlugin);
\ No newline at end of file
+(function(){var each=tinymce.each;tinymce.create('tinymce.plugins.TablePlugin',{init:function(ed,url){var t=this;t.editor=ed;t.url=url;each([['table','table.desc','mceInsertTable',true],['delete_table','table.del','mceTableDelete'],['delete_col','table.delete_col_desc','mceTableDeleteCol'],['delete_row','table.delete_row_desc','mceTableDeleteRow'],['col_after','table.col_after_desc','mceTableInsertColAfter'],['col_before','table.col_before_desc','mceTableInsertColBefore'],['row_after','table.row_after_desc','mceTableInsertRowAfter'],['row_before','table.row_before_desc','mceTableInsertRowBefore'],['row_props','table.row_desc','mceTableRowProps',true],['cell_props','table.cell_desc','mceTableCellProps',true],['split_cells','table.split_cells_desc','mceTableSplitCells',true],['merge_cells','table.merge_cells_desc','mceTableMergeCells',true]],function(c){ed.addButton(c[0],{title:c[1],cmd:c[2],ui:c[3]});});ed.onInit.add(function(){if(ed&&ed.plugins.contextmenu){ed.plugins.contextmenu.onContextMenu.add(function(th,m,e){var sm;if(ed.dom.getParent(e,'td')||ed.dom.getParent(e,'th')){m.removeAll();m.add({title:'table.desc',icon:'table',cmd:'mceInsertTable',ui:true,value:{action:'insert'}});m.add({title:'table.props_desc',icon:'table_props',cmd:'mceInsertTable',ui:true});m.add({title:'table.del',icon:'delete_table',cmd:'mceTableDelete',ui:true});m.addSeparator();sm=m.addMenu({title:'table.cell'});sm.add({title:'table.cell_desc',icon:'cell_props',cmd:'mceTableCellProps',ui:true});sm.add({title:'table.split_cells_desc',icon:'split_cells',cmd:'mceTableSplitCells',ui:true});sm.add({title:'table.merge_cells_desc',icon:'merge_cells',cmd:'mceTableMergeCells',ui:true});sm=m.addMenu({title:'table.row'});sm.add({title:'table.row_desc',icon:'row_props',cmd:'mceTableRowProps',ui:true});sm.add({title:'table.row_before_desc',icon:'row_before',cmd:'mceTableInsertRowBefore'});sm.add({title:'table.row_after_desc',icon:'row_after',cmd:'mceTableInsertRowAfter'});sm.add({title:'table.delete_row_desc',icon:'delete_row',cmd:'mceTableDeleteRow'});sm.addSeparator();sm.add({title:'table.cut_row_desc',icon:'cut',cmd:'mceTableCutRow'});sm.add({title:'table.copy_row_desc',icon:'copy',cmd:'mceTableCopyRow'});sm.add({title:'table.paste_row_before_desc',icon:'paste',cmd:'mceTablePasteRowBefore'});sm.add({title:'table.paste_row_after_desc',icon:'paste',cmd:'mceTablePasteRowAfter'});sm=m.addMenu({title:'table.col'});sm.add({title:'table.col_before_desc',icon:'col_before',cmd:'mceTableInsertColBefore'});sm.add({title:'table.col_after_desc',icon:'col_after',cmd:'mceTableInsertColAfter'});sm.add({title:'table.delete_col_desc',icon:'delete_col',cmd:'mceTableDeleteCol'});}else m.add({title:'table.desc',icon:'table',cmd:'mceInsertTable',ui:true});});}});ed.onNodeChange.add(function(ed,cm,n){var p=ed.dom.getParent(n,'td,th,caption');cm.setActive('table',!!p);if(p&&p.nodeName==='CAPTION')p=null;cm.setDisabled('delete_table',!p);cm.setDisabled('delete_col',!p);cm.setDisabled('delete_table',!p);cm.setDisabled('delete_row',!p);cm.setDisabled('col_after',!p);cm.setDisabled('col_before',!p);cm.setDisabled('row_after',!p);cm.setDisabled('row_before',!p);cm.setDisabled('row_props',!p);cm.setDisabled('cell_props',!p);cm.setDisabled('split_cells',!p||(parseInt(ed.dom.getAttrib(p,'colspan','1'))<2&&parseInt(ed.dom.getAttrib(p,'rowspan','1'))<2));cm.setDisabled('merge_cells',!p);});},execCommand:function(cmd,ui,val){var ed=this.editor,b;switch(cmd){case"mceInsertTable":case"mceTableRowProps":case"mceTableCellProps":case"mceTableSplitCells":case"mceTableMergeCells":case"mceTableInsertRowBefore":case"mceTableInsertRowAfter":case"mceTableDeleteRow":case"mceTableInsertColBefore":case"mceTableInsertColAfter":case"mceTableDeleteCol":case"mceTableCutRow":case"mceTableCopyRow":case"mceTablePasteRowBefore":case"mceTablePasteRowAfter":case"mceTableDelete":ed.execCommand('mceBeginUndoLevel');this._doExecCommand(cmd,ui,val);ed.execCommand('mceEndUndoLevel');return true;}return false;},getInfo:function(){return{longname:'Tables',author:'Moxiecode Systems AB',authorurl:'http://tinymce.moxiecode.com',infourl:'http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/table',version:tinymce.majorVersion+"."+tinymce.minorVersion};},_doExecCommand:function(command,user_interface,value){var inst=this.editor,ed=inst,url=this.url;var focusElm=inst.selection.getNode();var trElm=inst.dom.getParent(focusElm,"tr");var tdElm=inst.dom.getParent(focusElm,"td,th");var tableElm=inst.dom.getParent(focusElm,"table");var doc=inst.contentWindow.document;var tableBorder=tableElm?tableElm.getAttribute("border"):"";if(trElm&&tdElm==null)tdElm=trElm.cells[0];function inArray(ar,v){for(var i=0;i<ar.length;i++){if(ar[i].length>0&&inArray(ar[i],v))return true;if(ar[i]==v)return true;}return false;}function select(dx,dy){var td;grid=getTableGrid(tableElm);dx=dx||0;dy=dy||0;dx=Math.max(cpos.cellindex+dx,0);dy=Math.max(cpos.rowindex+dy,0);inst.execCommand('mceRepaint');td=getCell(grid,dy,dx);if(td){inst.selection.select(td.firstChild||td);inst.selection.collapse(1);}};function makeTD(){var newTD=doc.createElement("td");if(!tinymce.isIE)newTD.innerHTML='<br mce_bogus="1"/>';}function getColRowSpan(td){var colspan=inst.dom.getAttrib(td,"colspan");var rowspan=inst.dom.getAttrib(td,"rowspan");colspan=colspan==""?1:parseInt(colspan);rowspan=rowspan==""?1:parseInt(rowspan);return{colspan:colspan,rowspan:rowspan};}function getCellPos(grid,td){var x,y;for(y=0;y<grid.length;y++){for(x=0;x<grid[y].length;x++){if(grid[y][x]==td)return{cellindex:x,rowindex:y};}}return null;}function getCell(grid,row,col){if(grid[row]&&grid[row][col])return grid[row][col];return null;}function getTableGrid(table){var grid=new Array(),rows=table.rows,x,y,td,sd,xstart,x2,y2;for(y=0;y<rows.length;y++){for(x=0;x<rows[y].cells.length;x++){td=rows[y].cells[x];sd=getColRowSpan(td);for(xstart=x;grid[y]&&grid[y][xstart];xstart++);for(y2=y;y2<y+sd['rowspan'];y2++){if(!grid[y2])grid[y2]=new Array();for(x2=xstart;x2<xstart+sd['colspan'];x2++)grid[y2][x2]=td;}}}return grid;}function trimRow(table,tr,td,new_tr){var grid=getTableGrid(table),cpos=getCellPos(grid,td);var cells,lastElm;if(new_tr.cells.length!=tr.childNodes.length){cells=tr.childNodes;lastElm=null;for(var x=0;td=getCell(grid,cpos.rowindex,x);x++){var remove=true;var sd=getColRowSpan(td);if(inArray(cells,td)){new_tr.childNodes[x]._delete=true;}else if((lastElm==null||td!=lastElm)&&sd.colspan>1){for(var i=x;i<x+td.colSpan;i++)new_tr.childNodes[i]._delete=true;}if((lastElm==null||td!=lastElm)&&sd.rowspan>1)td.rowSpan=sd.rowspan+1;lastElm=td;}deleteMarked(tableElm);}}function prevElm(node,name){while((node=node.previousSibling)!=null){if(node.nodeName==name)return node;}return null;}function nextElm(node,names){var namesAr=names.split(',');while((node=node.nextSibling)!=null){for(var i=0;i<namesAr.length;i++){if(node.nodeName.toLowerCase()==namesAr[i].toLowerCase())return node;}}return null;}function deleteMarked(tbl){if(tbl.rows==0)return;var tr=tbl.rows[0];do{var next=nextElm(tr,"TR");if(tr._delete){tr.parentNode.removeChild(tr);continue;}var td=tr.cells[0];if(td.cells>1){do{var nexttd=nextElm(td,"TD,TH");if(td._delete)td.parentNode.removeChild(td);}while((td=nexttd)!=null);}}while((tr=next)!=null);}function addRows(td_elm,tr_elm,rowspan){td_elm.rowSpan=1;var trNext=nextElm(tr_elm,"TR");for(var i=1;i<rowspan&&trNext;i++){var newTD=doc.createElement("td");if(!tinymce.isIE)newTD.innerHTML='<br mce_bogus="1"/>';if(tinymce.isIE)trNext.insertBefore(newTD,trNext.cells(td_elm.cellIndex));else trNext.insertBefore(newTD,trNext.cells[td_elm.cellIndex]);trNext=nextElm(trNext,"TR");}}function copyRow(doc,table,tr){var grid=getTableGrid(table);var newTR=tr.cloneNode(false);var cpos=getCellPos(grid,tr.cells[0]);var lastCell=null;var tableBorder=inst.dom.getAttrib(table,"border");var tdElm=null;for(var x=0;tdElm=getCell(grid,cpos.rowindex,x);x++){var newTD=null;if(lastCell!=tdElm){for(var i=0;i<tr.cells.length;i++){if(tdElm==tr.cells[i]){newTD=tdElm.cloneNode(true);break;}}}if(newTD==null){newTD=doc.createElement("td");if(!tinymce.isIE)newTD.innerHTML='<br mce_bogus="1"/>';}newTD.colSpan=1;newTD.rowSpan=1;newTR.appendChild(newTD);lastCell=tdElm;}return newTR;}switch(command){case"mceTableRowProps":if(trElm==null)return true;if(user_interface){inst.windowManager.open({url:url+'/row.htm',width:400+parseInt(inst.getLang('table.rowprops_delta_width',0)),height:295+parseInt(inst.getLang('table.rowprops_delta_height',0)),inline:1},{plugin_url:url});}return true;case"mceTableCellProps":if(tdElm==null)return true;if(user_interface){inst.windowManager.open({url:url+'/cell.htm',width:400+parseInt(inst.getLang('table.cellprops_delta_width',0)),height:295+parseInt(inst.getLang('table.cellprops_delta_height',0)),inline:1},{plugin_url:url});}return true;case"mceInsertTable":if(user_interface){inst.windowManager.open({url:url+'/table.htm',width:400+parseInt(inst.getLang('table.table_delta_width',0)),height:320+parseInt(inst.getLang('table.table_delta_height',0)),inline:1},{plugin_url:url,action:value?value.action:0});}return true;case"mceTableDelete":var table=inst.dom.getParent(inst.selection.getNode(),"table");if(table){table.parentNode.removeChild(table);inst.execCommand('mceRepaint');}return true;case"mceTableSplitCells":case"mceTableMergeCells":case"mceTableInsertRowBefore":case"mceTableInsertRowAfter":case"mceTableDeleteRow":case"mceTableInsertColBefore":case"mceTableInsertColAfter":case"mceTableDeleteCol":case"mceTableCutRow":case"mceTableCopyRow":case"mceTablePasteRowBefore":case"mceTablePasteRowAfter":if(!tableElm)return true;if(trElm&&tableElm!=trElm.parentNode)tableElm=trElm.parentNode;if(tableElm&&trElm){switch(command){case"mceTableCutRow":if(!trElm||!tdElm)return true;inst.tableRowClipboard=copyRow(doc,tableElm,trElm);inst.execCommand("mceTableDeleteRow");break;case"mceTableCopyRow":if(!trElm||!tdElm)return true;inst.tableRowClipboard=copyRow(doc,tableElm,trElm);break;case"mceTablePasteRowBefore":if(!trElm||!tdElm)return true;var newTR=inst.tableRowClipboard.cloneNode(true);var prevTR=prevElm(trElm,"TR");if(prevTR!=null)trimRow(tableElm,prevTR,prevTR.cells[0],newTR);trElm.parentNode.insertBefore(newTR,trElm);break;case"mceTablePasteRowAfter":if(!trElm||!tdElm)return true;var nextTR=nextElm(trElm,"TR");var newTR=inst.tableRowClipboard.cloneNode(true);trimRow(tableElm,trElm,tdElm,newTR);if(nextTR==null)trElm.parentNode.appendChild(newTR);else nextTR.parentNode.insertBefore(newTR,nextTR);break;case"mceTableInsertRowBefore":if(!trElm||!tdElm)return true;var grid=getTableGrid(tableElm);var cpos=getCellPos(grid,tdElm);var newTR=doc.createElement("tr");var lastTDElm=null;cpos.rowindex--;if(cpos.rowindex<0)cpos.rowindex=0;for(var x=0;tdElm=getCell(grid,cpos.rowindex,x);x++){if(tdElm!=lastTDElm){var sd=getColRowSpan(tdElm);if(sd['rowspan']==1){var newTD=doc.createElement("td");if(!tinymce.isIE)newTD.innerHTML='<br mce_bogus="1"/>';newTD.colSpan=tdElm.colSpan;newTR.appendChild(newTD);}else tdElm.rowSpan=sd['rowspan']+1;lastTDElm=tdElm;}}trElm.parentNode.insertBefore(newTR,trElm);select(0,1);break;case"mceTableInsertRowAfter":if(!trElm||!tdElm)return true;var grid=getTableGrid(tableElm);var cpos=getCellPos(grid,tdElm);var newTR=doc.createElement("tr");var lastTDElm=null;for(var x=0;tdElm=getCell(grid,cpos.rowindex,x);x++){if(tdElm!=lastTDElm){var sd=getColRowSpan(tdElm);if(sd['rowspan']==1){var newTD=doc.createElement("td");if(!tinymce.isIE)newTD.innerHTML='<br mce_bogus="1"/>';newTD.colSpan=tdElm.colSpan;newTR.appendChild(newTD);}else tdElm.rowSpan=sd['rowspan']+1;lastTDElm=tdElm;}}if(newTR.hasChildNodes()){var nextTR=nextElm(trElm,"TR");if(nextTR)nextTR.parentNode.insertBefore(newTR,nextTR);else tableElm.appendChild(newTR);}select(0,1);break;case"mceTableDeleteRow":if(!trElm||!tdElm)return true;var grid=getTableGrid(tableElm);var cpos=getCellPos(grid,tdElm);if(grid.length==1){inst.dom.remove(inst.dom.getParent(tableElm,"table"));return true;}var cells=trElm.cells;var nextTR=nextElm(trElm,"TR");for(var x=0;x<cells.length;x++){if(cells[x].rowSpan>1){var newTD=cells[x].cloneNode(true);var sd=getColRowSpan(cells[x]);newTD.rowSpan=sd.rowspan-1;var nextTD=nextTR.cells[x];if(nextTD==null)nextTR.appendChild(newTD);else nextTR.insertBefore(newTD,nextTD);}}var lastTDElm=null;for(var x=0;tdElm=getCell(grid,cpos.rowindex,x);x++){if(tdElm!=lastTDElm){var sd=getColRowSpan(tdElm);if(sd.rowspan>1){tdElm.rowSpan=sd.rowspan-1;}else{trElm=tdElm.parentNode;if(trElm.parentNode)trElm._delete=true;}lastTDElm=tdElm;}}deleteMarked(tableElm);select(0,-1);break;case"mceTableInsertColBefore":if(!trElm||!tdElm)return true;var grid=getTableGrid(tableElm);var cpos=getCellPos(grid,tdElm);var lastTDElm=null;for(var y=0;tdElm=getCell(grid,y,cpos.cellindex);y++){if(tdElm!=lastTDElm){var sd=getColRowSpan(tdElm);if(sd['colspan']==1){var newTD=doc.createElement(tdElm.nodeName);if(!tinymce.isIE)newTD.innerHTML='<br mce_bogus="1"/>';newTD.rowSpan=tdElm.rowSpan;tdElm.parentNode.insertBefore(newTD,tdElm);}else tdElm.colSpan++;lastTDElm=tdElm;}}select();break;case"mceTableInsertColAfter":if(!trElm||!tdElm)return true;var grid=getTableGrid(tableElm);var cpos=getCellPos(grid,tdElm);var lastTDElm=null;for(var y=0;tdElm=getCell(grid,y,cpos.cellindex);y++){if(tdElm!=lastTDElm){var sd=getColRowSpan(tdElm);if(sd['colspan']==1){var newTD=doc.createElement(tdElm.nodeName);if(!tinymce.isIE)newTD.innerHTML='<br mce_bogus="1"/>';newTD.rowSpan=tdElm.rowSpan;var nextTD=nextElm(tdElm,"TD,TH");if(nextTD==null)tdElm.parentNode.appendChild(newTD);else nextTD.parentNode.insertBefore(newTD,nextTD);}else tdElm.colSpan++;lastTDElm=tdElm;}}select(1);break;case"mceTableDeleteCol":if(!trElm||!tdElm)return true;var grid=getTableGrid(tableElm);var cpos=getCellPos(grid,tdElm);var lastTDElm=null;if(grid.length>1&&grid[0].length<=1){inst.dom.remove(inst.dom.getParent(tableElm,"table"));return true;}for(var y=0;tdElm=getCell(grid,y,cpos.cellindex);y++){if(tdElm!=lastTDElm){var sd=getColRowSpan(tdElm);if(sd['colspan']>1)tdElm.colSpan=sd['colspan']-1;else{if(tdElm.parentNode)tdElm.parentNode.removeChild(tdElm);}lastTDElm=tdElm;}}select(-1);break;case"mceTableSplitCells":if(!trElm||!tdElm)return true;var spandata=getColRowSpan(tdElm);var colspan=spandata["colspan"];var rowspan=spandata["rowspan"];if(colspan>1||rowspan>1){tdElm.colSpan=1;for(var i=1;i<colspan;i++){var newTD=doc.createElement("td");if(!tinymce.isIE)newTD.innerHTML='<br mce_bogus="1"/>';trElm.insertBefore(newTD,nextElm(tdElm,"TD,TH"));if(rowspan>1)addRows(newTD,trElm,rowspan);}addRows(tdElm,trElm,rowspan);}tableElm=inst.dom.getParent(inst.selection.getNode(),"table");break;case"mceTableMergeCells":var rows=[];var sel=inst.selection.getSel();var grid=getTableGrid(tableElm);if(tinymce.isIE||sel.rangeCount==1){if(user_interface){var sp=getColRowSpan(tdElm);inst.windowManager.open({url:url+'/merge_cells.htm',width:240+parseInt(inst.getLang('table.merge_cells_delta_width',0)),height:110+parseInt(inst.getLang('table.merge_cells_delta_height',0)),inline:1},{action:"update",numcols:sp.colspan,numrows:sp.rowspan,plugin_url:url});return true;}else{var numRows=parseInt(value['numrows']);var numCols=parseInt(value['numcols']);var cpos=getCellPos(grid,tdElm);if((""+numRows)=="NaN")numRows=1;if((""+numCols)=="NaN")numCols=1;var tRows=tableElm.rows;for(var y=cpos.rowindex;y<grid.length;y++){var rowCells=new Array();for(var x=cpos.cellindex;x<grid[y].length;x++){var td=getCell(grid,y,x);if(td&&!inArray(rows,td)&&!inArray(rowCells,td)){var cp=getCellPos(grid,td);if(cp.cellindex<cpos.cellindex+numCols&&cp.rowindex<cpos.rowindex+numRows)rowCells[rowCells.length]=td;}}if(rowCells.length>0)rows[rows.length]=rowCells;}}}else{var cells=[];var sel=inst.selection.getSel();var lastTR=null;var curRow=null;var x1=-1,y1=-1,x2,y2;if(sel.rangeCount<2)return true;for(var i=0;i<sel.rangeCount;i++){var rng=sel.getRangeAt(i);var tdElm=rng.startContainer.childNodes[rng.startOffset];if(!tdElm)break;if(tdElm.nodeName=="TD")cells[cells.length]=tdElm;}var tRows=tableElm.rows;for(var y=0;y<tRows.length;y++){var rowCells=new Array();for(var x=0;x<tRows[y].cells.length;x++){var td=tRows[y].cells[x];for(var i=0;i<cells.length;i++){if(td==cells[i]){rowCells[rowCells.length]=td;}}}if(rowCells.length>0)rows[rows.length]=rowCells;}var curRow=new Array();var lastTR=null;for(var y=0;y<grid.length;y++){for(var x=0;x<grid[y].length;x++){grid[y][x]._selected=false;for(var i=0;i<cells.length;i++){if(grid[y][x]==cells[i]){if(x1==-1){x1=x;y1=y;}x2=x;y2=y;grid[y][x]._selected=true;}}}}for(var y=y1;y<=y2;y++){for(var x=x1;x<=x2;x++){if(!grid[y][x]._selected){alert("Invalid selection for merge.");return true;}}}}var rowSpan=1,colSpan=1;var lastRowSpan=-1;for(var y=0;y<rows.length;y++){var rowColSpan=0;for(var x=0;x<rows[y].length;x++){var sd=getColRowSpan(rows[y][x]);rowColSpan+=sd['colspan'];if(lastRowSpan!=-1&&sd['rowspan']!=lastRowSpan){alert("Invalid selection for merge.");return true;}lastRowSpan=sd['rowspan'];}if(rowColSpan>colSpan)colSpan=rowColSpan;lastRowSpan=-1;}var lastColSpan=-1;for(var x=0;x<rows[0].length;x++){var colRowSpan=0;for(var y=0;y<rows.length;y++){var sd=getColRowSpan(rows[y][x]);colRowSpan+=sd['rowspan'];if(lastColSpan!=-1&&sd['colspan']!=lastColSpan){alert("Invalid selection for merge.");return true;}lastColSpan=sd['colspan'];}if(colRowSpan>rowSpan)rowSpan=colRowSpan;lastColSpan=-1;}tdElm=rows[0][0];tdElm.rowSpan=rowSpan;tdElm.colSpan=colSpan;for(var y=0;y<rows.length;y++){for(var x=0;x<rows[y].length;x++){var html=rows[y][x].innerHTML;var chk=html.replace(/[ \t\r\n]/g,"");if(chk!="<br/>"&&chk!="<br>"&&chk!='<br mce_bogus="1"/>'&&(x+y>0))tdElm.innerHTML+=html;if(rows[y][x]!=tdElm&&!rows[y][x]._deleted){var cpos=getCellPos(grid,rows[y][x]);var tr=rows[y][x].parentNode;tr.removeChild(rows[y][x]);rows[y][x]._deleted=true;if(!tr.hasChildNodes()){tr.parentNode.removeChild(tr);var lastCell=null;for(var x=0;cellElm=getCell(grid,cpos.rowindex,x);x++){if(cellElm!=lastCell&&cellElm.rowSpan>1)cellElm.rowSpan--;lastCell=cellElm;}if(tdElm.rowSpan>1)tdElm.rowSpan--;}}}}break;}tableElm=inst.dom.getParent(inst.selection.getNode(),"table");inst.addVisual(tableElm);inst.nodeChanged();}return true;}return false;}});tinymce.PluginManager.add('table',tinymce.plugins.TablePlugin);})();
\ No newline at end of file
--- a/includes/clientside/tinymce/plugins/table/editor_plugin_src.js	Fri Feb 22 12:46:51 2008 -0500
+++ b/includes/clientside/tinymce/plugins/table/editor_plugin_src.js	Fri Feb 22 12:51:53 2008 -0500
@@ -1,879 +1,881 @@
 /**
- * $Id: editor_plugin_src.js 201 2007-02-12 15:56:56Z spocke $
+ * $Id: editor_plugin_src.js 520 2008-01-07 16:30:32Z spocke $
  *
  * @author Moxiecode
- * @copyright Copyright © 2004-2007, Moxiecode Systems AB, All rights reserved.
+ * @copyright Copyright © 2004-2008, Moxiecode Systems AB, All rights reserved.
  */
 
-/* Import plugin specific language pack */
-tinyMCE.importPluginLanguagePack('table');
+(function() {
+	var each = tinymce.each;
 
-var TinyMCE_TablePlugin = {
-	getInfo : function() {
-		return {
-			longname : 'Tables',
-			author : 'Moxiecode Systems AB',
-			authorurl : 'http://tinymce.moxiecode.com',
-			infourl : 'http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/table',
-			version : tinyMCE.majorVersion + "." + tinyMCE.minorVersion
-		};
-	},
+	tinymce.create('tinymce.plugins.TablePlugin', {
+		init : function(ed, url) {
+			var t = this;
 
-	initInstance : function(inst) {
-		if (tinyMCE.isGecko) {
-			var doc = inst.getDoc();
-			tinyMCE.addEvent(doc, "mouseup", TinyMCE_TablePlugin._mouseDownHandler);
-		}
-
-		inst.tableRowClipboard = null;
-	},
+			t.editor = ed;
+			t.url = url;
 
-	/**
-	 * Returns the HTML contents of the table control.
-	 */
-	getControlHTML : function(control_name) {
-		var controls = new Array(
-			['table', 'table.gif', 'lang_table_desc', 'mceInsertTable', true],
-			['delete_table', 'table_delete.gif', 'lang_table_del', 'mceTableDelete'],
-			['delete_col', 'table_delete_col.gif', 'lang_table_delete_col_desc', 'mceTableDeleteCol'],
-			['delete_row', 'table_delete_row.gif', 'lang_table_delete_row_desc', 'mceTableDeleteRow'],
-			['col_after', 'table_insert_col_after.gif', 'lang_table_col_after_desc', 'mceTableInsertColAfter'],
-			['col_before', 'table_insert_col_before.gif', 'lang_table_col_before_desc', 'mceTableInsertColBefore'],
-			['row_after', 'table_insert_row_after.gif', 'lang_table_row_after_desc', 'mceTableInsertRowAfter'],
-			['row_before', 'table_insert_row_before.gif', 'lang_table_row_before_desc', 'mceTableInsertRowBefore'],
-			['row_props', 'table_row_props.gif', 'lang_table_row_desc', 'mceTableRowProps', true],
-			['cell_props', 'table_cell_props.gif', 'lang_table_cell_desc', 'mceTableCellProps', true],
-			['split_cells', 'table_split_cells.gif', 'lang_table_split_cells_desc', 'mceTableSplitCells', true],
-			['merge_cells', 'table_merge_cells.gif', 'lang_table_merge_cells_desc', 'mceTableMergeCells', true]);
-
-		// Render table control
-		for (var i=0; i<controls.length; i++) {
-			var but = controls[i];
-			var cmd = 'tinyMCE.execInstanceCommand(\'{$editor_id}\',\'' + but[3] + '\', ' + (but.length > 4 ? but[4] : false) + (but.length > 5 ? ', \'' + but[5] + '\'' : '') + ');return false;';
-
-			if (but[0] == control_name)
-				return tinyMCE.getButtonHTML(control_name, but[2], '{$pluginurl}/images/'+ but[1], but[3], (but.length > 4 ? but[4] : false));
-		}
+			// Register buttons
+			each([
+				['table', 'table.desc', 'mceInsertTable', true],
+				['delete_table', 'table.del', 'mceTableDelete'],
+				['delete_col', 'table.delete_col_desc', 'mceTableDeleteCol'],
+				['delete_row', 'table.delete_row_desc', 'mceTableDeleteRow'],
+				['col_after', 'table.col_after_desc', 'mceTableInsertColAfter'],
+				['col_before', 'table.col_before_desc', 'mceTableInsertColBefore'],
+				['row_after', 'table.row_after_desc', 'mceTableInsertRowAfter'],
+				['row_before', 'table.row_before_desc', 'mceTableInsertRowBefore'],
+				['row_props', 'table.row_desc', 'mceTableRowProps', true],
+				['cell_props', 'table.cell_desc', 'mceTableCellProps', true],
+				['split_cells', 'table.split_cells_desc', 'mceTableSplitCells', true],
+				['merge_cells', 'table.merge_cells_desc', 'mceTableMergeCells', true]
+			], function(c) {
+				ed.addButton(c[0], {title : c[1], cmd : c[2], ui : c[3]});
+			});
 
-		// Special tablecontrols
-		if (control_name == "tablecontrols") {
-			var html = "";
+			ed.onInit.add(function() {
+				if (ed && ed.plugins.contextmenu) {
+					ed.plugins.contextmenu.onContextMenu.add(function(th, m, e) {
+						var sm;
 
-			html += tinyMCE.getControlHTML("table");
-			html += tinyMCE.getControlHTML("separator");
-			html += tinyMCE.getControlHTML("row_props");
-			html += tinyMCE.getControlHTML("cell_props");
-			html += tinyMCE.getControlHTML("separator");
-			html += tinyMCE.getControlHTML("row_before");
-			html += tinyMCE.getControlHTML("row_after");
-			html += tinyMCE.getControlHTML("delete_row");
-			html += tinyMCE.getControlHTML("separator");
-			html += tinyMCE.getControlHTML("col_before");
-			html += tinyMCE.getControlHTML("col_after");
-			html += tinyMCE.getControlHTML("delete_col");
-			html += tinyMCE.getControlHTML("separator");
-			html += tinyMCE.getControlHTML("split_cells");
-			html += tinyMCE.getControlHTML("merge_cells");
-
-			return html;
-		}
+						if (ed.dom.getParent(e, 'td') || ed.dom.getParent(e, 'th')) {
+							m.removeAll();
+							m.add({title : 'table.desc', icon : 'table', cmd : 'mceInsertTable', ui : true, value : {action : 'insert'}});
+							m.add({title : 'table.props_desc', icon : 'table_props', cmd : 'mceInsertTable', ui : true});
+							m.add({title : 'table.del', icon : 'delete_table', cmd : 'mceTableDelete', ui : true});
+							m.addSeparator();
 
-		return "";
-	},
+							// Cell menu
+							sm = m.addMenu({title : 'table.cell'});
+							sm.add({title : 'table.cell_desc', icon : 'cell_props', cmd : 'mceTableCellProps', ui : true});
+							sm.add({title : 'table.split_cells_desc', icon : 'split_cells', cmd : 'mceTableSplitCells', ui : true});
+							sm.add({title : 'table.merge_cells_desc', icon : 'merge_cells', cmd : 'mceTableMergeCells', ui : true});
 
-	/**
-	 * Executes the table commands.
-	 */
-	execCommand : function(editor_id, element, command, user_interface, value) {
-		// Is table command
-		switch (command) {
-			case "mceInsertTable":
-			case "mceTableRowProps":
-			case "mceTableCellProps":
-			case "mceTableSplitCells":
-			case "mceTableMergeCells":
-			case "mceTableInsertRowBefore":
-			case "mceTableInsertRowAfter":
-			case "mceTableDeleteRow":
-			case "mceTableInsertColBefore":
-			case "mceTableInsertColAfter":
-			case "mceTableDeleteCol":
-			case "mceTableCutRow":
-			case "mceTableCopyRow":
-			case "mceTablePasteRowBefore":
-			case "mceTablePasteRowAfter":
-			case "mceTableDelete":
-				var inst = tinyMCE.getInstanceById(editor_id);
+							// Row menu
+							sm = m.addMenu({title : 'table.row'});
+							sm.add({title : 'table.row_desc', icon : 'row_props', cmd : 'mceTableRowProps', ui : true});
+							sm.add({title : 'table.row_before_desc', icon : 'row_before', cmd : 'mceTableInsertRowBefore'});
+							sm.add({title : 'table.row_after_desc', icon : 'row_after', cmd : 'mceTableInsertRowAfter'});
+							sm.add({title : 'table.delete_row_desc', icon : 'delete_row', cmd : 'mceTableDeleteRow'});
+							sm.addSeparator();
+							sm.add({title : 'table.cut_row_desc', icon : 'cut', cmd : 'mceTableCutRow'});
+							sm.add({title : 'table.copy_row_desc', icon : 'copy', cmd : 'mceTableCopyRow'});
+							sm.add({title : 'table.paste_row_before_desc', icon : 'paste', cmd : 'mceTablePasteRowBefore'});
+							sm.add({title : 'table.paste_row_after_desc', icon : 'paste', cmd : 'mceTablePasteRowAfter'});
 
-				inst.execCommand('mceBeginUndoLevel');
-				TinyMCE_TablePlugin._doExecCommand(editor_id, element, command, user_interface, value);
-				inst.execCommand('mceEndUndoLevel');
-
-				return true;
-		}
-
-		// Pass to next handler in chain
-		return false;
-	},
-
-	handleNodeChange : function(editor_id, node, undo_index, undo_levels, visual_aid, any_selection) {
-		var colspan = "1", rowspan = "1", tdElm;
-
-		var inst = tinyMCE.getInstanceById(editor_id);
+							// Column menu
+							sm = m.addMenu({title : 'table.col'});
+							sm.add({title : 'table.col_before_desc', icon : 'col_before', cmd : 'mceTableInsertColBefore'});
+							sm.add({title : 'table.col_after_desc', icon : 'col_after', cmd : 'mceTableInsertColAfter'});
+							sm.add({title : 'table.delete_col_desc', icon : 'delete_col', cmd : 'mceTableDeleteCol'});
+						} else
+							m.add({title : 'table.desc', icon : 'table', cmd : 'mceInsertTable', ui : true});
+					});
+				}
+			});
 
-		// Reset table controls
-		tinyMCE.switchClass(editor_id + '_table', 'mceButtonNormal');
-		tinyMCE.switchClass(editor_id + '_delete_table', 'mceButtonDisabled');
-		tinyMCE.switchClass(editor_id + '_row_props', 'mceButtonDisabled');
-		tinyMCE.switchClass(editor_id + '_cell_props', 'mceButtonDisabled');
-		tinyMCE.switchClass(editor_id + '_row_before', 'mceButtonDisabled');
-		tinyMCE.switchClass(editor_id + '_row_after', 'mceButtonDisabled');
-		tinyMCE.switchClass(editor_id + '_delete_row', 'mceButtonDisabled');
-		tinyMCE.switchClass(editor_id + '_col_before', 'mceButtonDisabled');
-		tinyMCE.switchClass(editor_id + '_col_after', 'mceButtonDisabled');
-		tinyMCE.switchClass(editor_id + '_delete_col', 'mceButtonDisabled');
-		tinyMCE.switchClass(editor_id + '_split_cells', 'mceButtonDisabled');
-		tinyMCE.switchClass(editor_id + '_merge_cells', 'mceButtonDisabled');
+			ed.onNodeChange.add(function(ed, cm, n) {
+				var p = ed.dom.getParent(n, 'td,th,caption');
 
-		// Within a td element
-		if (tdElm = tinyMCE.getParentElement(node, "td,th")) {
-			tinyMCE.switchClass(editor_id + '_cell_props', 'mceButtonSelected');
-			tinyMCE.switchClass(editor_id + '_delete_table', 'mceButtonNormal');
-			tinyMCE.switchClass(editor_id + '_row_before', 'mceButtonNormal');
-			tinyMCE.switchClass(editor_id + '_row_after', 'mceButtonNormal');
-			tinyMCE.switchClass(editor_id + '_delete_row', 'mceButtonNormal');
-			tinyMCE.switchClass(editor_id + '_col_before', 'mceButtonNormal');
-			tinyMCE.switchClass(editor_id + '_col_after', 'mceButtonNormal');
-			tinyMCE.switchClass(editor_id + '_delete_col', 'mceButtonNormal');
-
-			colspan = tinyMCE.getAttrib(tdElm, "colspan");
-			rowspan = tinyMCE.getAttrib(tdElm, "rowspan");
-
-			colspan = colspan == "" ? "1" : colspan;
-			rowspan = rowspan == "" ? "1" : rowspan;
-
-			if (colspan != "1" || rowspan != "1")
-				tinyMCE.switchClass(editor_id + '_split_cells', 'mceButtonNormal');
-		}
+				cm.setActive('table', !!p);
+				if (p && p.nodeName === 'CAPTION')
+					p = null;
 
-		// Within a tr element
-		if (tinyMCE.getParentElement(node, "tr"))
-			tinyMCE.switchClass(editor_id + '_row_props', 'mceButtonSelected');
-
-		// Within table
-		if (tinyMCE.getParentElement(node, "table")) {
-			tinyMCE.switchClass(editor_id + '_table', 'mceButtonSelected');
-			tinyMCE.switchClass(editor_id + '_merge_cells', 'mceButtonNormal');
-		}
-	},
-
-	// Private plugin internal methods
+				cm.setDisabled('delete_table', !p);
+				cm.setDisabled('delete_col', !p);
+				cm.setDisabled('delete_table', !p);
+				cm.setDisabled('delete_row', !p);
+				cm.setDisabled('col_after', !p);
+				cm.setDisabled('col_before', !p);
+				cm.setDisabled('row_after', !p);
+				cm.setDisabled('row_before', !p);
+				cm.setDisabled('row_props', !p);
+				cm.setDisabled('cell_props', !p);
+				cm.setDisabled('split_cells', !p || (parseInt(ed.dom.getAttrib(p, 'colspan', '1')) < 2 && parseInt(ed.dom.getAttrib(p, 'rowspan', '1')) < 2));
+				cm.setDisabled('merge_cells', !p);
+			});
+		},
 
-	_mouseDownHandler : function(e) {
-		var elm = tinyMCE.isMSIE ? event.srcElement : e.target;
-		var focusElm = tinyMCE.selectedInstance.getFocusElement();
-
-		// If press on special Mozilla create TD/TR thingie
-		if (elm.nodeName == "BODY" && (focusElm.nodeName == "TD" || focusElm.nodeName == "TH" || (focusElm.parentNode && focusElm.parentNode.nodeName == "TD") ||(focusElm.parentNode && focusElm.parentNode.nodeName == "TH") )) {
-			window.setTimeout(function() {
-				var tableElm = tinyMCE.getParentElement(focusElm, "table");
-				tinyMCE.handleVisualAid(tableElm, true, tinyMCE.settings['visual'], tinyMCE.selectedInstance);
-			}, 10);
-		}
-	},
+		execCommand : function(cmd, ui, val) {
+			var ed = this.editor, b;
 
-	/**
-	 * Executes the table commands.
-	 */
-	_doExecCommand : function(editor_id, element, command, user_interface, value) {
-		var inst = tinyMCE.getInstanceById(editor_id);
-		var focusElm = inst.getFocusElement();
-		var trElm = tinyMCE.getParentElement(focusElm, "tr");
-		var tdElm = tinyMCE.getParentElement(focusElm, "td,th");
-		var tableElm = tinyMCE.getParentElement(focusElm, "table");
-		var doc = inst.contentWindow.document;
-		var tableBorder = tableElm ? tableElm.getAttribute("border") : "";
+			// Is table command
+			switch (cmd) {
+				case "mceInsertTable":
+				case "mceTableRowProps":
+				case "mceTableCellProps":
+				case "mceTableSplitCells":
+				case "mceTableMergeCells":
+				case "mceTableInsertRowBefore":
+				case "mceTableInsertRowAfter":
+				case "mceTableDeleteRow":
+				case "mceTableInsertColBefore":
+				case "mceTableInsertColAfter":
+				case "mceTableDeleteCol":
+				case "mceTableCutRow":
+				case "mceTableCopyRow":
+				case "mceTablePasteRowBefore":
+				case "mceTablePasteRowAfter":
+				case "mceTableDelete":
+					ed.execCommand('mceBeginUndoLevel');
+					this._doExecCommand(cmd, ui, val);
+					ed.execCommand('mceEndUndoLevel');
 
-		// Get first TD if no TD found
-		if (trElm && tdElm == null)
-			tdElm = trElm.cells[0];
-
-		// ------- Inner functions ---------
-		function inArray(ar, v) {
-			for (var i=0; i<ar.length; i++) {
-				// Is array
-				if (ar[i].length > 0 && inArray(ar[i], v))
-					return true;
-
-				// Found value
-				if (ar[i] == v)
 					return true;
 			}
 
+			// Pass to next handler in chain
 			return false;
-		}
-
-		function makeTD() {
-			var newTD = doc.createElement("td");
-			newTD.innerHTML = "&nbsp;";
-		}
-
-		function getColRowSpan(td) {
-			var colspan = tinyMCE.getAttrib(td, "colspan");
-			var rowspan = tinyMCE.getAttrib(td, "rowspan");
+		},
 
-			colspan = colspan == "" ? 1 : parseInt(colspan);
-			rowspan = rowspan == "" ? 1 : parseInt(rowspan);
-
-			return {colspan : colspan, rowspan : rowspan};
-		}
+		getInfo : function() {
+			return {
+				longname : 'Tables',
+				author : 'Moxiecode Systems AB',
+				authorurl : 'http://tinymce.moxiecode.com',
+				infourl : 'http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/table',
+				version : tinymce.majorVersion + "." + tinymce.minorVersion
+			};
+		},
 
-		function getCellPos(grid, td) {
-			var x, y;
-
-			for (y=0; y<grid.length; y++) {
-				for (x=0; x<grid[y].length; x++) {
-					if (grid[y][x] == td)
-						return {cellindex : x, rowindex : y};
-				}
-			}
+		// Private plugin internal methods
 
-			return null;
-		}
-
-		function getCell(grid, row, col) {
-			if (grid[row] && grid[row][col])
-				return grid[row][col];
-
-			return null;
-		}
-
-		function getTableGrid(table) {
-			var grid = new Array(), rows = table.rows, x, y, td, sd, xstart, x2, y2;
+		/**
+		 * Executes the table commands.
+		 */
+		_doExecCommand : function(command, user_interface, value) {
+			var inst = this.editor, ed = inst, url = this.url;
+			var focusElm = inst.selection.getNode();
+			var trElm = inst.dom.getParent(focusElm, "tr");
+			var tdElm = inst.dom.getParent(focusElm, "td,th");
+			var tableElm = inst.dom.getParent(focusElm, "table");
+			var doc = inst.contentWindow.document;
+			var tableBorder = tableElm ? tableElm.getAttribute("border") : "";
 
-			for (y=0; y<rows.length; y++) {
-				for (x=0; x<rows[y].cells.length; x++) {
-					td = rows[y].cells[x];
-					sd = getColRowSpan(td);
-
-					// All ready filled
-					for (xstart = x; grid[y] && grid[y][xstart]; xstart++) ;
+			// Get first TD if no TD found
+			if (trElm && tdElm == null)
+				tdElm = trElm.cells[0];
 
-					// Fill box
-					for (y2=y; y2<y+sd['rowspan']; y2++) {
-						if (!grid[y2])
-							grid[y2] = new Array();
+			function inArray(ar, v) {
+				for (var i=0; i<ar.length; i++) {
+					// Is array
+					if (ar[i].length > 0 && inArray(ar[i], v))
+						return true;
 
-						for (x2=xstart; x2<xstart+sd['colspan']; x2++)
-							grid[y2][x2] = td;
-					}
+					// Found value
+					if (ar[i] == v)
+						return true;
 				}
+
+				return false;
 			}
 
-			return grid;
-		}
-
-		function trimRow(table, tr, td, new_tr) {
-			var grid = getTableGrid(table), cpos = getCellPos(grid, td);
-			var cells, lastElm;
+			function select(dx, dy) {
+				var td;
 
-			// Time to crop away some
-			if (new_tr.cells.length != tr.childNodes.length) {
-				cells = tr.childNodes;
-				lastElm = null;
-
-				for (var x=0; td = getCell(grid, cpos.rowindex, x); x++) {
-					var remove = true;
-					var sd = getColRowSpan(td);
+				grid = getTableGrid(tableElm);
+				dx = dx || 0;
+				dy = dy || 0;
+				dx = Math.max(cpos.cellindex + dx, 0);
+				dy = Math.max(cpos.rowindex + dy, 0);
 
-					// Remove due to rowspan
-					if (inArray(cells, td)) {
-						new_tr.childNodes[x]._delete = true;
-					} else if ((lastElm == null || td != lastElm) && sd.colspan > 1) { // Remove due to colspan
-						for (var i=x; i<x+td.colSpan; i++)
-							new_tr.childNodes[i]._delete = true;
-					}
-
-					if ((lastElm == null || td != lastElm) && sd.rowspan > 1)
-						td.rowSpan = sd.rowspan + 1;
+				// Recalculate grid and select
+				inst.execCommand('mceRepaint');
+				td = getCell(grid, dy, dx);
 
-					lastElm = td;
+				if (td) {
+					inst.selection.select(td.firstChild || td);
+					inst.selection.collapse(1);
 				}
+			};
 
-				deleteMarked(tableElm);
-			}
-		}
+			function makeTD() {
+				var newTD = doc.createElement("td");
 
-		function prevElm(node, name) {
-			while ((node = node.previousSibling) != null) {
-				if (node.nodeName == name)
-					return node;
+				if (!tinymce.isIE)
+					newTD.innerHTML = '<br mce_bogus="1"/>';
 			}
 
-			return null;
-		}
-
-		function nextElm(node, names) {
-			var namesAr = names.split(',');
+			function getColRowSpan(td) {
+				var colspan = inst.dom.getAttrib(td, "colspan");
+				var rowspan = inst.dom.getAttrib(td, "rowspan");
 
-			while ((node = node.nextSibling) != null) {
-				for (var i=0; i<namesAr.length; i++) {
-					if (node.nodeName.toLowerCase() == namesAr[i].toLowerCase() )
-						return node;
-				}
+				colspan = colspan == "" ? 1 : parseInt(colspan);
+				rowspan = rowspan == "" ? 1 : parseInt(rowspan);
+
+				return {colspan : colspan, rowspan : rowspan};
 			}
 
-			return null;
-		}
-
-		function deleteMarked(tbl) {
-			if (tbl.rows == 0)
-				return;
+			function getCellPos(grid, td) {
+				var x, y;
 
-			var tr = tbl.rows[0];
-			do {
-				var next = nextElm(tr, "TR");
-
-				// Delete row
-				if (tr._delete) {
-					tr.parentNode.removeChild(tr);
-					continue;
+				for (y=0; y<grid.length; y++) {
+					for (x=0; x<grid[y].length; x++) {
+						if (grid[y][x] == td)
+							return {cellindex : x, rowindex : y};
+					}
 				}
 
-				// Delete cells
-				var td = tr.cells[0];
-				if (td.cells > 1) {
-					do {
-						var nexttd = nextElm(td, "TD,TH");
+				return null;
+			}
 
-						if (td._delete)
-							td.parentNode.removeChild(td);
-					} while ((td = nexttd) != null);
-				}
-			} while ((tr = next) != null);
-		}
+			function getCell(grid, row, col) {
+				if (grid[row] && grid[row][col])
+					return grid[row][col];
 
-		function addRows(td_elm, tr_elm, rowspan) {
-			// Add rows
-			td_elm.rowSpan = 1;
-			var trNext = nextElm(tr_elm, "TR");
-			for (var i=1; i<rowspan && trNext; i++) {
-				var newTD = doc.createElement("td");
-				newTD.innerHTML = "&nbsp;";
+				return null;
+			}
+
+			function getTableGrid(table) {
+				var grid = new Array(), rows = table.rows, x, y, td, sd, xstart, x2, y2;
 
-				if (tinyMCE.isMSIE)
-					trNext.insertBefore(newTD, trNext.cells(td_elm.cellIndex));
-				else
-					trNext.insertBefore(newTD, trNext.cells[td_elm.cellIndex]);
+				for (y=0; y<rows.length; y++) {
+					for (x=0; x<rows[y].cells.length; x++) {
+						td = rows[y].cells[x];
+						sd = getColRowSpan(td);
 
-				trNext = nextElm(trNext, "TR");
-			}
-		}
+						// All ready filled
+						for (xstart = x; grid[y] && grid[y][xstart]; xstart++) ;
 
-		function copyRow(doc, table, tr) {
-			var grid = getTableGrid(table);
-			var newTR = tr.cloneNode(false);
-			var cpos = getCellPos(grid, tr.cells[0]);
-			var lastCell = null;
-			var tableBorder = tinyMCE.getAttrib(table, "border");
-			var tdElm = null;
+						// Fill box
+						for (y2=y; y2<y+sd['rowspan']; y2++) {
+							if (!grid[y2])
+								grid[y2] = new Array();
 
-			for (var x=0; tdElm = getCell(grid, cpos.rowindex, x); x++) {
-				var newTD = null;
-
-				if (lastCell != tdElm) {
-					for (var i=0; i<tr.cells.length; i++) {
-						if (tdElm == tr.cells[i]) {
-							newTD = tdElm.cloneNode(true);
-							break;
+							for (x2=xstart; x2<xstart+sd['colspan']; x2++)
+								grid[y2][x2] = td;
 						}
 					}
 				}
 
-				if (newTD == null) {
-					newTD = doc.createElement("td");
-					newTD.innerHTML = "&nbsp;";
+				return grid;
+			}
+
+			function trimRow(table, tr, td, new_tr) {
+				var grid = getTableGrid(table), cpos = getCellPos(grid, td);
+				var cells, lastElm;
+
+				// Time to crop away some
+				if (new_tr.cells.length != tr.childNodes.length) {
+					cells = tr.childNodes;
+					lastElm = null;
+
+					for (var x=0; td = getCell(grid, cpos.rowindex, x); x++) {
+						var remove = true;
+						var sd = getColRowSpan(td);
+
+						// Remove due to rowspan
+						if (inArray(cells, td)) {
+							new_tr.childNodes[x]._delete = true;
+						} else if ((lastElm == null || td != lastElm) && sd.colspan > 1) { // Remove due to colspan
+							for (var i=x; i<x+td.colSpan; i++)
+								new_tr.childNodes[i]._delete = true;
+						}
+
+						if ((lastElm == null || td != lastElm) && sd.rowspan > 1)
+							td.rowSpan = sd.rowspan + 1;
+
+						lastElm = td;
+					}
+
+					deleteMarked(tableElm);
+				}
+			}
+
+			function prevElm(node, name) {
+				while ((node = node.previousSibling) != null) {
+					if (node.nodeName == name)
+						return node;
 				}
 
-				// Reset col/row span
-				newTD.colSpan = 1;
-				newTD.rowSpan = 1;
+				return null;
+			}
+
+			function nextElm(node, names) {
+				var namesAr = names.split(',');
 
-				newTR.appendChild(newTD);
+				while ((node = node.nextSibling) != null) {
+					for (var i=0; i<namesAr.length; i++) {
+						if (node.nodeName.toLowerCase() == namesAr[i].toLowerCase() )
+							return node;
+					}
+				}
 
-				lastCell = tdElm;
+				return null;
 			}
 
-			return newTR;
-		}
+			function deleteMarked(tbl) {
+				if (tbl.rows == 0)
+					return;
 
-		// ---- Commands -----
+				var tr = tbl.rows[0];
+				do {
+					var next = nextElm(tr, "TR");
+
+					// Delete row
+					if (tr._delete) {
+						tr.parentNode.removeChild(tr);
+						continue;
+					}
 
-		// Handle commands
-		switch (command) {
-			case "mceTableRowProps":
-				if (trElm == null)
-					return true;
+					// Delete cells
+					var td = tr.cells[0];
+					if (td.cells > 1) {
+						do {
+							var nexttd = nextElm(td, "TD,TH");
+
+							if (td._delete)
+								td.parentNode.removeChild(td);
+						} while ((td = nexttd) != null);
+					}
+				} while ((tr = next) != null);
+			}
+
+			function addRows(td_elm, tr_elm, rowspan) {
+				// Add rows
+				td_elm.rowSpan = 1;
+				var trNext = nextElm(tr_elm, "TR");
+				for (var i=1; i<rowspan && trNext; i++) {
+					var newTD = doc.createElement("td");
+
+					if (!tinymce.isIE)
+						newTD.innerHTML = '<br mce_bogus="1"/>';
 
-				if (user_interface) {
-					// Setup template
-					var template = new Array();
+					if (tinymce.isIE)
+						trNext.insertBefore(newTD, trNext.cells(td_elm.cellIndex));
+					else
+						trNext.insertBefore(newTD, trNext.cells[td_elm.cellIndex]);
+
+					trNext = nextElm(trNext, "TR");
+				}
+			}
+
+			function copyRow(doc, table, tr) {
+				var grid = getTableGrid(table);
+				var newTR = tr.cloneNode(false);
+				var cpos = getCellPos(grid, tr.cells[0]);
+				var lastCell = null;
+				var tableBorder = inst.dom.getAttrib(table, "border");
+				var tdElm = null;
+
+				for (var x=0; tdElm = getCell(grid, cpos.rowindex, x); x++) {
+					var newTD = null;
 
-					template['file'] = '../../plugins/table/row.htm';
-					template['width'] = 380;
-					template['height'] = 295;
+					if (lastCell != tdElm) {
+						for (var i=0; i<tr.cells.length; i++) {
+							if (tdElm == tr.cells[i]) {
+								newTD = tdElm.cloneNode(true);
+								break;
+							}
+						}
+					}
+
+					if (newTD == null) {
+						newTD = doc.createElement("td");
 
-					// Language specific width and height addons
-					template['width'] += tinyMCE.getLang('lang_table_rowprops_delta_width', 0);
-					template['height'] += tinyMCE.getLang('lang_table_rowprops_delta_height', 0);
+						if (!tinymce.isIE)
+							newTD.innerHTML = '<br mce_bogus="1"/>';
+					}
 
-					// Open window
-					tinyMCE.openWindow(template, {editor_id : inst.editorId, inline : "yes"});
+					// Reset col/row span
+					newTD.colSpan = 1;
+					newTD.rowSpan = 1;
+
+					newTR.appendChild(newTD);
+
+					lastCell = tdElm;
 				}
 
-				return true;
+				return newTR;
+			}
+
+			// ---- Commands -----
+
+			// Handle commands
+			switch (command) {
+				case "mceTableRowProps":
+					if (trElm == null)
+						return true;
 
-			case "mceTableCellProps":
-				if (tdElm == null)
+					if (user_interface) {
+						inst.windowManager.open({
+							url : url + '/row.htm',
+							width : 400 + parseInt(inst.getLang('table.rowprops_delta_width', 0)),
+							height : 295 + parseInt(inst.getLang('table.rowprops_delta_height', 0)),
+							inline : 1
+						}, {
+							plugin_url : url
+						});
+					}
+
 					return true;
 
-				if (user_interface) {
-					// Setup template
-					var template = new Array();
-
-					template['file'] = '../../plugins/table/cell.htm';
-					template['width'] = 380;
-					template['height'] = 295;
-
-					// Language specific width and height addons
-					template['width'] += tinyMCE.getLang('lang_table_cellprops_delta_width', 0);
-					template['height'] += tinyMCE.getLang('lang_table_cellprops_delta_height', 0);
+				case "mceTableCellProps":
+					if (tdElm == null)
+						return true;
 
-					// Open window
-					tinyMCE.openWindow(template, {editor_id : inst.editorId, inline : "yes"});
-				}
-
-				return true;
+					if (user_interface) {
+						inst.windowManager.open({
+							url : url + '/cell.htm',
+							width : 400 + parseInt(inst.getLang('table.cellprops_delta_width', 0)),
+							height : 295 + parseInt(inst.getLang('table.cellprops_delta_height', 0)),
+							inline : 1
+						}, {
+							plugin_url : url
+						});
+					}
 
-			case "mceInsertTable":
-				if (user_interface) {
-					// Setup template
-					var template = new Array();
-
-					template['file'] = '../../plugins/table/table.htm';
-					template['width'] = 380;
-					template['height'] = 295;
+					return true;
 
-					// Language specific width and height addons
-					template['width'] += tinyMCE.getLang('lang_table_table_delta_width', 0);
-					template['height'] += tinyMCE.getLang('lang_table_table_delta_height', 0);
-
-					// Open window
-					tinyMCE.openWindow(template, {editor_id : inst.editorId, inline : "yes", action : value});
-				}
-
-				return true;
+				case "mceInsertTable":
+					if (user_interface) {
+						inst.windowManager.open({
+							url : url + '/table.htm',
+							width : 400 + parseInt(inst.getLang('table.table_delta_width', 0)),
+							height : 320 + parseInt(inst.getLang('table.table_delta_height', 0)),
+							inline : 1
+						}, {
+							plugin_url : url,
+							action : value ? value.action : 0
+						});
+					}
 
-			case "mceTableDelete":
-				var table = tinyMCE.getParentElement(inst.getFocusElement(), "table");
-				if (table) {
-					table.parentNode.removeChild(table);
-					inst.repaint();
-				}
-				return true;
+					return true;
 
-			case "mceTableSplitCells":
-			case "mceTableMergeCells":
-			case "mceTableInsertRowBefore":
-			case "mceTableInsertRowAfter":
-			case "mceTableDeleteRow":
-			case "mceTableInsertColBefore":
-			case "mceTableInsertColAfter":
-			case "mceTableDeleteCol":
-			case "mceTableCutRow":
-			case "mceTableCopyRow":
-			case "mceTablePasteRowBefore":
-			case "mceTablePasteRowAfter":
-				// No table just return (invalid command)
-				if (!tableElm)
+				case "mceTableDelete":
+					var table = inst.dom.getParent(inst.selection.getNode(), "table");
+					if (table) {
+						table.parentNode.removeChild(table);
+						inst.execCommand('mceRepaint');
+					}
 					return true;
 
-				// Table has a tbody use that reference
-				// Changed logic by ApTest 2005.07.12 (www.aptest.com)
-				// Now lookk at the focused element and take its parentNode.  That will be a tbody or a table.
-				if (trElm && tableElm != trElm.parentNode)
-					tableElm = trElm.parentNode;
+				case "mceTableSplitCells":
+				case "mceTableMergeCells":
+				case "mceTableInsertRowBefore":
+				case "mceTableInsertRowAfter":
+				case "mceTableDeleteRow":
+				case "mceTableInsertColBefore":
+				case "mceTableInsertColAfter":
+				case "mceTableDeleteCol":
+				case "mceTableCutRow":
+				case "mceTableCopyRow":
+				case "mceTablePasteRowBefore":
+				case "mceTablePasteRowAfter":
+					// No table just return (invalid command)
+					if (!tableElm)
+						return true;
+
+					// Table has a tbody use that reference
+					// Changed logic by ApTest 2005.07.12 (www.aptest.com)
+					// Now lookk at the focused element and take its parentNode.  That will be a tbody or a table.
+					if (trElm && tableElm != trElm.parentNode)
+						tableElm = trElm.parentNode;
+
+					if (tableElm && trElm) {
+						switch (command) {
+							case "mceTableCutRow":
+								if (!trElm || !tdElm)
+									return true;
+
+								inst.tableRowClipboard = copyRow(doc, tableElm, trElm);
+								inst.execCommand("mceTableDeleteRow");
+								break;
+
+							case "mceTableCopyRow":
+								if (!trElm || !tdElm)
+									return true;
+
+								inst.tableRowClipboard = copyRow(doc, tableElm, trElm);
+								break;
+
+							case "mceTablePasteRowBefore":
+								if (!trElm || !tdElm)
+									return true;
+
+								var newTR = inst.tableRowClipboard.cloneNode(true);
+
+								var prevTR = prevElm(trElm, "TR");
+								if (prevTR != null)
+									trimRow(tableElm, prevTR, prevTR.cells[0], newTR);
+
+								trElm.parentNode.insertBefore(newTR, trElm);
+								break;
 
-				if (tableElm && trElm) {
-					switch (command) {
-						case "mceTableCutRow":
-							if (!trElm || !tdElm)
-								return true;
+							case "mceTablePasteRowAfter":
+								if (!trElm || !tdElm)
+									return true;
+								
+								var nextTR = nextElm(trElm, "TR");
+								var newTR = inst.tableRowClipboard.cloneNode(true);
+
+								trimRow(tableElm, trElm, tdElm, newTR);
+
+								if (nextTR == null)
+									trElm.parentNode.appendChild(newTR);
+								else
+									nextTR.parentNode.insertBefore(newTR, nextTR);
+
+								break;
+
+							case "mceTableInsertRowBefore":
+								if (!trElm || !tdElm)
+									return true;
+
+								var grid = getTableGrid(tableElm);
+								var cpos = getCellPos(grid, tdElm);
+								var newTR = doc.createElement("tr");
+								var lastTDElm = null;
 
-							inst.tableRowClipboard = copyRow(doc, tableElm, trElm);
-							inst.execCommand("mceTableDeleteRow");
-							break;
+								cpos.rowindex--;
+								if (cpos.rowindex < 0)
+									cpos.rowindex = 0;
+
+								// Create cells
+								for (var x=0; tdElm = getCell(grid, cpos.rowindex, x); x++) {
+									if (tdElm != lastTDElm) {
+										var sd = getColRowSpan(tdElm);
+
+										if (sd['rowspan'] == 1) {
+											var newTD = doc.createElement("td");
 
-						case "mceTableCopyRow":
-							if (!trElm || !tdElm)
-								return true;
+											if (!tinymce.isIE)
+												newTD.innerHTML = '<br mce_bogus="1"/>';
+
+											newTD.colSpan = tdElm.colSpan;
 
-							inst.tableRowClipboard = copyRow(doc, tableElm, trElm);
+											newTR.appendChild(newTD);
+										} else
+											tdElm.rowSpan = sd['rowspan'] + 1;
+
+										lastTDElm = tdElm;
+									}
+								}
+
+								trElm.parentNode.insertBefore(newTR, trElm);
+								select(0, 1);
 							break;
 
-						case "mceTablePasteRowBefore":
-							if (!trElm || !tdElm)
-								return true;
+							case "mceTableInsertRowAfter":
+								if (!trElm || !tdElm)
+									return true;
 
-							var newTR = inst.tableRowClipboard.cloneNode(true);
+								var grid = getTableGrid(tableElm);
+								var cpos = getCellPos(grid, tdElm);
+								var newTR = doc.createElement("tr");
+								var lastTDElm = null;
 
-							var prevTR = prevElm(trElm, "TR");
-							if (prevTR != null)
-								trimRow(tableElm, prevTR, prevTR.cells[0], newTR);
+								// Create cells
+								for (var x=0; tdElm = getCell(grid, cpos.rowindex, x); x++) {
+									if (tdElm != lastTDElm) {
+										var sd = getColRowSpan(tdElm);
 
-							trElm.parentNode.insertBefore(newTR, trElm);
-							break;
+										if (sd['rowspan'] == 1) {
+											var newTD = doc.createElement("td");
+
+											if (!tinymce.isIE)
+												newTD.innerHTML = '<br mce_bogus="1"/>';
 
-						case "mceTablePasteRowAfter":
-							if (!trElm || !tdElm)
-								return true;
-							
-							var nextTR = nextElm(trElm, "TR");
-							var newTR = inst.tableRowClipboard.cloneNode(true);
+											newTD.colSpan = tdElm.colSpan;
+
+											newTR.appendChild(newTD);
+										} else
+											tdElm.rowSpan = sd['rowspan'] + 1;
+
+										lastTDElm = tdElm;
+									}
+								}
 
-							trimRow(tableElm, trElm, tdElm, newTR);
+								if (newTR.hasChildNodes()) {
+									var nextTR = nextElm(trElm, "TR");
+									if (nextTR)
+										nextTR.parentNode.insertBefore(newTR, nextTR);
+									else
+										tableElm.appendChild(newTR);
+								}
 
-							if (nextTR == null)
-								trElm.parentNode.appendChild(newTR);
-							else
-								nextTR.parentNode.insertBefore(newTR, nextTR);
-
+								select(0, 1);
 							break;
 
-						case "mceTableInsertRowBefore":
-							if (!trElm || !tdElm)
-								return true;
+							case "mceTableDeleteRow":
+								if (!trElm || !tdElm)
+									return true;
 
-							var grid = getTableGrid(tableElm);
-							var cpos = getCellPos(grid, tdElm);
-							var newTR = doc.createElement("tr");
-							var lastTDElm = null;
+								var grid = getTableGrid(tableElm);
+								var cpos = getCellPos(grid, tdElm);
+
+								// Only one row, remove whole table
+								if (grid.length == 1) {
+									inst.dom.remove(inst.dom.getParent(tableElm, "table"));
+									return true;
+								}
 
-							cpos.rowindex--;
-							if (cpos.rowindex < 0)
-								cpos.rowindex = 0;
+								// Move down row spanned cells
+								var cells = trElm.cells;
+								var nextTR = nextElm(trElm, "TR");
+								for (var x=0; x<cells.length; x++) {
+									if (cells[x].rowSpan > 1) {
+										var newTD = cells[x].cloneNode(true);
+										var sd = getColRowSpan(cells[x]);
+
+										newTD.rowSpan = sd.rowspan - 1;
+
+										var nextTD = nextTR.cells[x];
 
-							// Create cells
-							for (var x=0; tdElm = getCell(grid, cpos.rowindex, x); x++) {
-								if (tdElm != lastTDElm) {
-									var sd = getColRowSpan(tdElm);
+										if (nextTD == null)
+											nextTR.appendChild(newTD);
+										else
+											nextTR.insertBefore(newTD, nextTD);
+									}
+								}
+
+								// Delete cells
+								var lastTDElm = null;
+								for (var x=0; tdElm = getCell(grid, cpos.rowindex, x); x++) {
+									if (tdElm != lastTDElm) {
+										var sd = getColRowSpan(tdElm);
 
-									if (sd['rowspan'] == 1) {
-										var newTD = doc.createElement("td");
+										if (sd.rowspan > 1) {
+											tdElm.rowSpan = sd.rowspan - 1;
+										} else {
+											trElm = tdElm.parentNode;
+
+											if (trElm.parentNode)
+												trElm._delete = true;
+										}
 
-										newTD.innerHTML = "&nbsp;";
-										newTD.colSpan = tdElm.colSpan;
+										lastTDElm = tdElm;
+									}
+								}
 
-										newTR.appendChild(newTD);
-									} else
-										tdElm.rowSpan = sd['rowspan'] + 1;
+								deleteMarked(tableElm);
+
+								select(0, -1);
+							break;
 
-									lastTDElm = tdElm;
-								}
-							}
+							case "mceTableInsertColBefore":
+								if (!trElm || !tdElm)
+									return true;
+
+								var grid = getTableGrid(tableElm);
+								var cpos = getCellPos(grid, tdElm);
+								var lastTDElm = null;
 
-							trElm.parentNode.insertBefore(newTR, trElm);
+								for (var y=0; tdElm = getCell(grid, y, cpos.cellindex); y++) {
+									if (tdElm != lastTDElm) {
+										var sd = getColRowSpan(tdElm);
 
-							grid = getTableGrid(tableElm);
-							inst.selection.selectNode(getCell(grid, cpos.rowindex + 1, cpos.cellindex), tinyMCE.isGecko, true); // Only collape on gecko
-						break;
+										if (sd['colspan'] == 1) {
+											var newTD = doc.createElement(tdElm.nodeName);
+
+											if (!tinymce.isIE)
+												newTD.innerHTML = '<br mce_bogus="1"/>';
+
+											newTD.rowSpan = tdElm.rowSpan;
 
-						case "mceTableInsertRowAfter":
-							if (!trElm || !tdElm)
-								return true;
+											tdElm.parentNode.insertBefore(newTD, tdElm);
+										} else
+											tdElm.colSpan++;
+
+										lastTDElm = tdElm;
+									}
+								}
 
-							var grid = getTableGrid(tableElm);
-							var cpos = getCellPos(grid, tdElm);
-							var newTR = doc.createElement("tr");
-							var lastTDElm = null;
+								select();
+							break;
+
+							case "mceTableInsertColAfter":
+								if (!trElm || !tdElm)
+									return true;
+
+								var grid = getTableGrid(tableElm);
+								var cpos = getCellPos(grid, tdElm);
+								var lastTDElm = null;
 
-							// Create cells
-							for (var x=0; tdElm = getCell(grid, cpos.rowindex, x); x++) {
-								if (tdElm != lastTDElm) {
-									var sd = getColRowSpan(tdElm);
+								for (var y=0; tdElm = getCell(grid, y, cpos.cellindex); y++) {
+									if (tdElm != lastTDElm) {
+										var sd = getColRowSpan(tdElm);
+
+										if (sd['colspan'] == 1) {
+											var newTD = doc.createElement(tdElm.nodeName);
+
+											if (!tinymce.isIE)
+												newTD.innerHTML = '<br mce_bogus="1"/>';
 
-									if (sd['rowspan'] == 1) {
-										var newTD = doc.createElement("td");
+											newTD.rowSpan = tdElm.rowSpan;
 
-										newTD.innerHTML = "&nbsp;";
-										newTD.colSpan = tdElm.colSpan;
+											var nextTD = nextElm(tdElm, "TD,TH");
+											if (nextTD == null)
+												tdElm.parentNode.appendChild(newTD);
+											else
+												nextTD.parentNode.insertBefore(newTD, nextTD);
+										} else
+											tdElm.colSpan++;
 
-										newTR.appendChild(newTD);
-									} else
-										tdElm.rowSpan = sd['rowspan'] + 1;
+										lastTDElm = tdElm;
+									}
+								}
+
+								select(1);
+							break;
 
-									lastTDElm = tdElm;
+							case "mceTableDeleteCol":
+								if (!trElm || !tdElm)
+									return true;
+
+								var grid = getTableGrid(tableElm);
+								var cpos = getCellPos(grid, tdElm);
+								var lastTDElm = null;
+
+								// Only one col, remove whole table
+								if (grid.length > 1 && grid[0].length <= 1) {
+									inst.dom.remove(inst.dom.getParent(tableElm, "table"));
+									return true;
 								}
-							}
 
-							if (newTR.hasChildNodes()) {
-								var nextTR = nextElm(trElm, "TR");
-								if (nextTR)
-									nextTR.parentNode.insertBefore(newTR, nextTR);
-								else
-									tableElm.appendChild(newTR);
-							}
+								// Delete cells
+								for (var y=0; tdElm = getCell(grid, y, cpos.cellindex); y++) {
+									if (tdElm != lastTDElm) {
+										var sd = getColRowSpan(tdElm);
 
-							grid = getTableGrid(tableElm);
-							inst.selection.selectNode(getCell(grid, cpos.rowindex, cpos.cellindex), tinyMCE.isGecko, true); // Only collape on gecko
-						break;
+										if (sd['colspan'] > 1)
+											tdElm.colSpan = sd['colspan'] - 1;
+										else {
+											if (tdElm.parentNode)
+												tdElm.parentNode.removeChild(tdElm);
+										}
 
-						case "mceTableDeleteRow":
+										lastTDElm = tdElm;
+									}
+								}
+
+								select(-1);
+							break;
+
+						case "mceTableSplitCells":
 							if (!trElm || !tdElm)
 								return true;
 
-							var grid = getTableGrid(tableElm);
-							var cpos = getCellPos(grid, tdElm);
-
-							// Only one row, remove whole table
-							if (grid.length == 1) {
-								tableElm = tinyMCE.getParentElement(tableElm, "table"); // Look for table instead of tbody
-								tableElm.parentNode.removeChild(tableElm);
-								return true;
-							}
-
-							// Move down row spanned cells
-							var cells = trElm.cells;
-							var nextTR = nextElm(trElm, "TR");
-							for (var x=0; x<cells.length; x++) {
-								if (cells[x].rowSpan > 1) {
-									var newTD = cells[x].cloneNode(true);
-									var sd = getColRowSpan(cells[x]);
-
-									newTD.rowSpan = sd.rowspan - 1;
+							var spandata = getColRowSpan(tdElm);
 
-									var nextTD = nextTR.cells[x];
-
-									if (nextTD == null)
-										nextTR.appendChild(newTD);
-									else
-										nextTR.insertBefore(newTD, nextTD);
-								}
-							}
-
-							// Delete cells
-							var lastTDElm = null;
-							for (var x=0; tdElm = getCell(grid, cpos.rowindex, x); x++) {
-								if (tdElm != lastTDElm) {
-									var sd = getColRowSpan(tdElm);
-
-									if (sd.rowspan > 1) {
-										tdElm.rowSpan = sd.rowspan - 1;
-									} else {
-										trElm = tdElm.parentNode;
+							var colspan = spandata["colspan"];
+							var rowspan = spandata["rowspan"];
 
-										if (trElm.parentNode)
-											trElm._delete = true;
-									}
-
-									lastTDElm = tdElm;
-								}
-							}
-
-							deleteMarked(tableElm);
-
-							cpos.rowindex--;
-							if (cpos.rowindex < 0)
-								cpos.rowindex = 0;
-
-							// Recalculate grid and select
-							grid = getTableGrid(tableElm);
-							inst.selection.selectNode(getCell(grid, cpos.rowindex, 0), tinyMCE.isGecko, true); // Only collape on gecko
-						break;
+							// Needs splitting
+							if (colspan > 1 || rowspan > 1) {
+								// Generate cols
+								tdElm.colSpan = 1;
+								for (var i=1; i<colspan; i++) {
+									var newTD = doc.createElement("td");
 
-						case "mceTableInsertColBefore":
-							if (!trElm || !tdElm)
-								return true;
+									if (!tinymce.isIE)
+										newTD.innerHTML = '<br mce_bogus="1"/>';
 
-							var grid = getTableGrid(tableElm);
-							var cpos = getCellPos(grid, tdElm);
-							var lastTDElm = null;
-
-							for (var y=0; tdElm = getCell(grid, y, cpos.cellindex); y++) {
-								if (tdElm != lastTDElm) {
-									var sd = getColRowSpan(tdElm);
+									trElm.insertBefore(newTD, nextElm(tdElm, "TD,TH"));
 
-									if (sd['colspan'] == 1) {
-										var newTD = doc.createElement(tdElm.nodeName);
-
-										newTD.innerHTML = "&nbsp;";
-										newTD.rowSpan = tdElm.rowSpan;
+									if (rowspan > 1)
+										addRows(newTD, trElm, rowspan);
+								}
 
-										tdElm.parentNode.insertBefore(newTD, tdElm);
-									} else
-										tdElm.colSpan++;
-
-									lastTDElm = tdElm;
-								}
+								addRows(tdElm, trElm, rowspan);
 							}
 
-							grid = getTableGrid(tableElm);
-							inst.selection.selectNode(getCell(grid, cpos.rowindex, cpos.cellindex + 1), tinyMCE.isGecko, true); // Only collape on gecko
-						break;
+							// Apply visual aids
+							tableElm = inst.dom.getParent(inst.selection.getNode(), "table");
+							break;
 
-						case "mceTableInsertColAfter":
-							if (!trElm || !tdElm)
-								return true;
-
+						case "mceTableMergeCells":
+							var rows = [];
+							var sel = inst.selection.getSel();
 							var grid = getTableGrid(tableElm);
-							var cpos = getCellPos(grid, tdElm);
-							var lastTDElm = null;
 
-							for (var y=0; tdElm = getCell(grid, y, cpos.cellindex); y++) {
-								if (tdElm != lastTDElm) {
-									var sd = getColRowSpan(tdElm);
-
-									if (sd['colspan'] == 1) {
-										var newTD = doc.createElement(tdElm.nodeName);
+							if (tinymce.isIE || sel.rangeCount == 1) {
+								if (user_interface) {
+									// Setup template
+									var sp = getColRowSpan(tdElm);
 
-										newTD.innerHTML = "&nbsp;";
-										newTD.rowSpan = tdElm.rowSpan;
-
-										var nextTD = nextElm(tdElm, "TD,TH");
-										if (nextTD == null)
-											tdElm.parentNode.appendChild(newTD);
-										else
-											nextTD.parentNode.insertBefore(newTD, nextTD);
-									} else
-										tdElm.colSpan++;
+									inst.windowManager.open({
+										url : url + '/merge_cells.htm',
+										width : 240 + parseInt(inst.getLang('table.merge_cells_delta_width', 0)),
+										height : 110 + parseInt(inst.getLang('table.merge_cells_delta_height', 0)),
+										inline : 1
+									}, {
+										action : "update",
+										numcols : sp.colspan,
+										numrows : sp.rowspan,
+										plugin_url : url
+									});
 
-									lastTDElm = tdElm;
-								}
-							}
-
-							grid = getTableGrid(tableElm);
-							inst.selection.selectNode(getCell(grid, cpos.rowindex, cpos.cellindex), tinyMCE.isGecko, true); // Only collape on gecko
-						break;
+									return true;
+								} else {
+									var numRows = parseInt(value['numrows']);
+									var numCols = parseInt(value['numcols']);
+									var cpos = getCellPos(grid, tdElm);
 
-						case "mceTableDeleteCol":
-							if (!trElm || !tdElm)
-								return true;
+									if (("" + numRows) == "NaN")
+										numRows = 1;
 
-							var grid = getTableGrid(tableElm);
-							var cpos = getCellPos(grid, tdElm);
-							var lastTDElm = null;
+									if (("" + numCols) == "NaN")
+										numCols = 1;
 
-							// Only one col, remove whole table
-							if (grid.length > 1 && grid[0].length <= 1) {
-								tableElm = tinyMCE.getParentElement(tableElm, "table"); // Look for table instead of tbody
-								tableElm.parentNode.removeChild(tableElm);
-								return true;
-							}
+									// Get rows and cells
+									var tRows = tableElm.rows;
+									for (var y=cpos.rowindex; y<grid.length; y++) {
+										var rowCells = new Array();
+
+										for (var x=cpos.cellindex; x<grid[y].length; x++) {
+											var td = getCell(grid, y, x);
 
-							// Delete cells
-							for (var y=0; tdElm = getCell(grid, y, cpos.cellindex); y++) {
-								if (tdElm != lastTDElm) {
-									var sd = getColRowSpan(tdElm);
+											if (td && !inArray(rows, td) && !inArray(rowCells, td)) {
+												var cp = getCellPos(grid, td);
 
-									if (sd['colspan'] > 1)
-										tdElm.colSpan = sd['colspan'] - 1;
-									else {
-										if (tdElm.parentNode)
-											tdElm.parentNode.removeChild(tdElm);
+												// Within range
+												if (cp.cellindex < cpos.cellindex+numCols && cp.rowindex < cpos.rowindex+numRows)
+													rowCells[rowCells.length] = td;
+											}
+										}
+
+										if (rowCells.length > 0)
+											rows[rows.length] = rowCells;
 									}
 
-									lastTDElm = tdElm;
+									//return true;
 								}
-							}
-
-							cpos.cellindex--;
-							if (cpos.cellindex < 0)
-								cpos.cellindex = 0;
-
-							// Recalculate grid and select
-							grid = getTableGrid(tableElm);
-							inst.selection.selectNode(getCell(grid, cpos.rowindex, 0), tinyMCE.isGecko, true); // Only collape on gecko
-						break;
-
-					case "mceTableSplitCells":
-						if (!trElm || !tdElm)
-							return true;
-
-						var spandata = getColRowSpan(tdElm);
-
-						var colspan = spandata["colspan"];
-						var rowspan = spandata["rowspan"];
-
-						// Needs splitting
-						if (colspan > 1 || rowspan > 1) {
-							// Generate cols
-							tdElm.colSpan = 1;
-							for (var i=1; i<colspan; i++) {
-								var newTD = doc.createElement("td");
-
-								newTD.innerHTML = "&nbsp;";
-
-								trElm.insertBefore(newTD, nextElm(tdElm, "TD,TH"));
-
-								if (rowspan > 1)
-									addRows(newTD, trElm, rowspan);
-							}
+							} else {
+								var cells = [];
+								var sel = inst.selection.getSel();
+								var lastTR = null;
+								var curRow = null;
+								var x1 = -1, y1 = -1, x2, y2;
 
-							addRows(tdElm, trElm, rowspan);
-						}
-
-						// Apply visual aids
-						tableElm = tinyMCE.getParentElement(inst.getFocusElement(), "table");
-						break;
-
-					case "mceTableMergeCells":
-						var rows = new Array();
-						var sel = inst.getSel();
-						var grid = getTableGrid(tableElm);
-
-						if (tinyMCE.isMSIE || sel.rangeCount == 1) {
-							if (user_interface) {
-								// Setup template
-								var template = new Array();
-								var sp = getColRowSpan(tdElm);
+								// Only one cell selected, whats the point?
+								if (sel.rangeCount < 2)
+									return true;
 
-								template['file'] = '../../plugins/table/merge_cells.htm';
-								template['width'] = 250;
-								template['height'] = 105 + (tinyMCE.isNS7 ? 25 : 0);
-
-								// Language specific width and height addons
-								template['width'] += tinyMCE.getLang('lang_table_merge_cells_delta_width', 0);
-								template['height'] += tinyMCE.getLang('lang_table_merge_cells_delta_height', 0);
-
-								// Open window
-								tinyMCE.openWindow(template, {editor_id : inst.editorId, inline : "yes", action : "update", numcols : sp.colspan, numrows : sp.rowspan});
+								// Get all selected cells
+								for (var i=0; i<sel.rangeCount; i++) {
+									var rng = sel.getRangeAt(i);
+									var tdElm = rng.startContainer.childNodes[rng.startOffset];
 
-								return true;
-							} else {
-								var numRows = parseInt(value['numrows']);
-								var numCols = parseInt(value['numcols']);
-								var cpos = getCellPos(grid, tdElm);
+									if (!tdElm)
+										break;
 
-								if (("" + numRows) == "NaN")
-									numRows = 1;
-
-								if (("" + numCols) == "NaN")
-									numCols = 1;
+									if (tdElm.nodeName == "TD")
+										cells[cells.length] = tdElm;
+								}
 
 								// Get rows and cells
 								var tRows = tableElm.rows;
-								for (var y=cpos.rowindex; y<grid.length; y++) {
+								for (var y=0; y<tRows.length; y++) {
 									var rowCells = new Array();
 
-									for (var x=cpos.cellindex; x<grid[y].length; x++) {
-										var td = getCell(grid, y, x);
+									for (var x=0; x<tRows[y].cells.length; x++) {
+										var td = tRows[y].cells[x];
 
-										if (td && !inArray(rows, td) && !inArray(rowCells, td)) {
-											var cp = getCellPos(grid, td);
-
-											// Within range
-											if (cp.cellindex < cpos.cellindex+numCols && cp.rowindex < cpos.rowindex+numRows)
+										for (var i=0; i<cells.length; i++) {
+											if (td == cells[i]) {
 												rowCells[rowCells.length] = td;
+											}
 										}
 									}
 
@@ -881,193 +883,150 @@
 										rows[rows.length] = rowCells;
 								}
 
-								//return true;
-							}
-						} else {
-							var cells = new Array();
-							var sel = inst.getSel();
-							var lastTR = null;
-							var curRow = null;
-							var x1 = -1, y1 = -1, x2, y2;
-
-							// Only one cell selected, whats the point?
-							if (sel.rangeCount < 2)
-								return true;
-
-							// Get all selected cells
-							for (var i=0; i<sel.rangeCount; i++) {
-								var rng = sel.getRangeAt(i);
-								var tdElm = rng.startContainer.childNodes[rng.startOffset];
+								// Find selected cells in grid and box
+								var curRow = new Array();
+								var lastTR = null;
+								for (var y=0; y<grid.length; y++) {
+									for (var x=0; x<grid[y].length; x++) {
+										grid[y][x]._selected = false;
 
-								if (!tdElm)
-									break;
-
-								if (tdElm.nodeName == "TD")
-									cells[cells.length] = tdElm;
-							}
+										for (var i=0; i<cells.length; i++) {
+											if (grid[y][x] == cells[i]) {
+												// Get start pos
+												if (x1 == -1) {
+													x1 = x;
+													y1 = y;
+												}
 
-							// Get rows and cells
-							var tRows = tableElm.rows;
-							for (var y=0; y<tRows.length; y++) {
-								var rowCells = new Array();
+												// Get end pos
+												x2 = x;
+												y2 = y;
 
-								for (var x=0; x<tRows[y].cells.length; x++) {
-									var td = tRows[y].cells[x];
-
-									for (var i=0; i<cells.length; i++) {
-										if (td == cells[i]) {
-											rowCells[rowCells.length] = td;
+												grid[y][x]._selected = true;
+											}
 										}
 									}
 								}
 
-								if (rowCells.length > 0)
-									rows[rows.length] = rowCells;
-							}
-
-							// Find selected cells in grid and box
-							var curRow = new Array();
-							var lastTR = null;
-							for (var y=0; y<grid.length; y++) {
-								for (var x=0; x<grid[y].length; x++) {
-									grid[y][x]._selected = false;
-
-									for (var i=0; i<cells.length; i++) {
-										if (grid[y][x] == cells[i]) {
-											// Get start pos
-											if (x1 == -1) {
-												x1 = x;
-												y1 = y;
-											}
-
-											// Get end pos
-											x2 = x;
-											y2 = y;
-
-											grid[y][x]._selected = true;
+								// Is there gaps, if so deny
+								for (var y=y1; y<=y2; y++) {
+									for (var x=x1; x<=x2; x++) {
+										if (!grid[y][x]._selected) {
+											alert("Invalid selection for merge.");
+											return true;
 										}
 									}
 								}
 							}
 
-							// Is there gaps, if so deny
-							for (var y=y1; y<=y2; y++) {
-								for (var x=x1; x<=x2; x++) {
-									if (!grid[y][x]._selected) {
+							// Validate selection and get total rowspan and colspan
+							var rowSpan = 1, colSpan = 1;
+
+							// Validate horizontal and get total colspan
+							var lastRowSpan = -1;
+							for (var y=0; y<rows.length; y++) {
+								var rowColSpan = 0;
+
+								for (var x=0; x<rows[y].length; x++) {
+									var sd = getColRowSpan(rows[y][x]);
+
+									rowColSpan += sd['colspan'];
+
+									if (lastRowSpan != -1 && sd['rowspan'] != lastRowSpan) {
+										alert("Invalid selection for merge.");
+										return true;
+									}
+
+									lastRowSpan = sd['rowspan'];
+								}
+
+								if (rowColSpan > colSpan)
+									colSpan = rowColSpan;
+
+								lastRowSpan = -1;
+							}
+
+							// Validate vertical and get total rowspan
+							var lastColSpan = -1;
+							for (var x=0; x<rows[0].length; x++) {
+								var colRowSpan = 0;
+
+								for (var y=0; y<rows.length; y++) {
+									var sd = getColRowSpan(rows[y][x]);
+
+									colRowSpan += sd['rowspan'];
+
+									if (lastColSpan != -1 && sd['colspan'] != lastColSpan) {
 										alert("Invalid selection for merge.");
 										return true;
 									}
+
+									lastColSpan = sd['colspan'];
+								}
+
+								if (colRowSpan > rowSpan)
+									rowSpan = colRowSpan;
+
+								lastColSpan = -1;
+							}
+
+							// Setup td
+							tdElm = rows[0][0];
+							tdElm.rowSpan = rowSpan;
+							tdElm.colSpan = colSpan;
+
+							// Merge cells
+							for (var y=0; y<rows.length; y++) {
+								for (var x=0; x<rows[y].length; x++) {
+									var html = rows[y][x].innerHTML;
+									var chk = html.replace(/[ \t\r\n]/g, "");
+
+									if (chk != "<br/>" && chk != "<br>" && chk != '<br mce_bogus="1"/>' && (x+y > 0))
+										tdElm.innerHTML += html;
+
+									// Not current cell
+									if (rows[y][x] != tdElm && !rows[y][x]._deleted) {
+										var cpos = getCellPos(grid, rows[y][x]);
+										var tr = rows[y][x].parentNode;
+
+										tr.removeChild(rows[y][x]);
+										rows[y][x]._deleted = true;
+
+										// Empty TR, remove it
+										if (!tr.hasChildNodes()) {
+											tr.parentNode.removeChild(tr);
+
+											var lastCell = null;
+											for (var x=0; cellElm = getCell(grid, cpos.rowindex, x); x++) {
+												if (cellElm != lastCell && cellElm.rowSpan > 1)
+													cellElm.rowSpan--;
+
+												lastCell = cellElm;
+											}
+
+											if (tdElm.rowSpan > 1)
+												tdElm.rowSpan--;
+										}
+									}
 								}
 							}
-						}
 
-						// Validate selection and get total rowspan and colspan
-						var rowSpan = 1, colSpan = 1;
-
-						// Validate horizontal and get total colspan
-						var lastRowSpan = -1;
-						for (var y=0; y<rows.length; y++) {
-							var rowColSpan = 0;
-
-							for (var x=0; x<rows[y].length; x++) {
-								var sd = getColRowSpan(rows[y][x]);
-
-								rowColSpan += sd['colspan'];
-
-								if (lastRowSpan != -1 && sd['rowspan'] != lastRowSpan) {
-									alert("Invalid selection for merge.");
-									return true;
-								}
-
-								lastRowSpan = sd['rowspan'];
-							}
-
-							if (rowColSpan > colSpan)
-								colSpan = rowColSpan;
-
-							lastRowSpan = -1;
-						}
-
-						// Validate vertical and get total rowspan
-						var lastColSpan = -1;
-						for (var x=0; x<rows[0].length; x++) {
-							var colRowSpan = 0;
-
-							for (var y=0; y<rows.length; y++) {
-								var sd = getColRowSpan(rows[y][x]);
-
-								colRowSpan += sd['rowspan'];
-
-								if (lastColSpan != -1 && sd['colspan'] != lastColSpan) {
-									alert("Invalid selection for merge.");
-									return true;
-								}
-
-								lastColSpan = sd['colspan'];
-							}
-
-							if (colRowSpan > rowSpan)
-								rowSpan = colRowSpan;
-
-							lastColSpan = -1;
+							break;
 						}
 
-						// Setup td
-						tdElm = rows[0][0];
-						tdElm.rowSpan = rowSpan;
-						tdElm.colSpan = colSpan;
-
-						// Merge cells
-						for (var y=0; y<rows.length; y++) {
-							for (var x=0; x<rows[y].length; x++) {
-								var html = rows[y][x].innerHTML;
-								var chk = tinyMCE.regexpReplace(html, "[ \t\r\n]", "");
-
-								if (chk != "<br/>" && chk != "<br>" && chk != "&nbsp;" && (x+y > 0))
-									tdElm.innerHTML += html;
-
-								// Not current cell
-								if (rows[y][x] != tdElm && !rows[y][x]._deleted) {
-									var cpos = getCellPos(grid, rows[y][x]);
-									var tr = rows[y][x].parentNode;
-
-									tr.removeChild(rows[y][x]);
-									rows[y][x]._deleted = true;
-
-									// Empty TR, remove it
-									if (!tr.hasChildNodes()) {
-										tr.parentNode.removeChild(tr);
-
-										var lastCell = null;
-										for (var x=0; cellElm = getCell(grid, cpos.rowindex, x); x++) {
-											if (cellElm != lastCell && cellElm.rowSpan > 1)
-												cellElm.rowSpan--;
-
-											lastCell = cellElm;
-										}
-
-										if (tdElm.rowSpan > 1)
-											tdElm.rowSpan--;
-									}
-								}
-							}
-						}
-
-						break;
+						tableElm = inst.dom.getParent(inst.selection.getNode(), "table");
+						inst.addVisual(tableElm);
+						inst.nodeChanged();
 					}
 
-					tableElm = tinyMCE.getParentElement(inst.getFocusElement(), "table");
-					tinyMCE.handleVisualAid(tableElm, true, tinyMCE.settings['visual'], tinyMCE.selectedInstance);
-					tinyMCE.triggerNodeChange();
-					inst.repaint();
-				}
+				return true;
+			}
 
-			return true;
+			// Pass to next handler in chain
+			return false;
 		}
+	});
 
-		// Pass to next handler in chain
-		return false;
-	}
-};
-
-tinyMCE.addPlugin("table", TinyMCE_TablePlugin);
+	// Register plugin
+	tinymce.PluginManager.add('table', tinymce.plugins.TablePlugin);
+})();
\ No newline at end of file
Binary file includes/clientside/tinymce/plugins/table/images/buttons.gif has changed
Binary file includes/clientside/tinymce/plugins/table/images/table.gif has changed
Binary file includes/clientside/tinymce/plugins/table/images/table_cell_props.gif has changed
Binary file includes/clientside/tinymce/plugins/table/images/table_delete.gif has changed
Binary file includes/clientside/tinymce/plugins/table/images/table_delete_col.gif has changed
Binary file includes/clientside/tinymce/plugins/table/images/table_delete_row.gif has changed
Binary file includes/clientside/tinymce/plugins/table/images/table_insert_col_after.gif has changed
Binary file includes/clientside/tinymce/plugins/table/images/table_insert_col_before.gif has changed
Binary file includes/clientside/tinymce/plugins/table/images/table_insert_row_after.gif has changed
Binary file includes/clientside/tinymce/plugins/table/images/table_insert_row_before.gif has changed
Binary file includes/clientside/tinymce/plugins/table/images/table_merge_cells.gif has changed
Binary file includes/clientside/tinymce/plugins/table/images/table_row_props.gif has changed
Binary file includes/clientside/tinymce/plugins/table/images/table_split_cells.gif has changed
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/includes/clientside/tinymce/plugins/table/js/cell.js	Fri Feb 22 12:51:53 2008 -0500
@@ -0,0 +1,258 @@
+tinyMCEPopup.requireLangPack();
+
+var ed;
+
+function init() {
+	ed = tinyMCEPopup.editor;
+	tinyMCEPopup.resizeToInnerSize();
+
+	document.getElementById('backgroundimagebrowsercontainer').innerHTML = getBrowserHTML('backgroundimagebrowser','backgroundimage','image','table');
+	document.getElementById('bordercolor_pickcontainer').innerHTML = getColorPickerHTML('bordercolor_pick','bordercolor');
+	document.getElementById('bgcolor_pickcontainer').innerHTML = getColorPickerHTML('bgcolor_pick','bgcolor')
+
+	var inst = ed;
+	var tdElm = ed.dom.getParent(ed.selection.getNode(), "td,th");
+	var formObj = document.forms[0];
+	var st = ed.dom.parseStyle(ed.dom.getAttrib(tdElm, "style"));
+
+	// Get table cell data
+	var celltype = tdElm.nodeName.toLowerCase();
+	var align = ed.dom.getAttrib(tdElm, 'align');
+	var valign = ed.dom.getAttrib(tdElm, 'valign');
+	var width = trimSize(getStyle(tdElm, 'width', 'width'));
+	var height = trimSize(getStyle(tdElm, 'height', 'height'));
+	var bordercolor = convertRGBToHex(getStyle(tdElm, 'bordercolor', 'borderLeftColor'));
+	var bgcolor = convertRGBToHex(getStyle(tdElm, 'bgcolor', 'backgroundColor'));
+	var className = ed.dom.getAttrib(tdElm, 'class');
+	var backgroundimage = getStyle(tdElm, 'background', 'backgroundImage').replace(new RegExp("url\\('?([^']*)'?\\)", 'gi'), "$1");;
+	var id = ed.dom.getAttrib(tdElm, 'id');
+	var lang = ed.dom.getAttrib(tdElm, 'lang');
+	var dir = ed.dom.getAttrib(tdElm, 'dir');
+	var scope = ed.dom.getAttrib(tdElm, 'scope');
+
+	// Setup form
+	addClassesToList('class', 'table_cell_styles');
+	formObj.bordercolor.value = bordercolor;
+	formObj.bgcolor.value = bgcolor;
+	formObj.backgroundimage.value = backgroundimage;
+	formObj.width.value = width;
+	formObj.height.value = height;
+	formObj.id.value = id;
+	formObj.lang.value = lang;
+	formObj.style.value = ed.dom.serializeStyle(st);
+	selectByValue(formObj, 'align', align);
+	selectByValue(formObj, 'valign', valign);
+	selectByValue(formObj, 'class', className);
+	selectByValue(formObj, 'celltype', celltype);
+	selectByValue(formObj, 'dir', dir);
+	selectByValue(formObj, 'scope', scope);
+
+	// Resize some elements
+	if (isVisible('backgroundimagebrowser'))
+		document.getElementById('backgroundimage').style.width = '180px';
+
+	updateColor('bordercolor_pick', 'bordercolor');
+	updateColor('bgcolor_pick', 'bgcolor');
+}
+
+function updateAction() {
+	var el = ed.selection.getNode();
+	var inst = ed;
+	var tdElm = ed.dom.getParent(el, "td,th");
+	var trElm = ed.dom.getParent(el, "tr");
+	var tableElm = ed.dom.getParent(el, "table");
+	var formObj = document.forms[0];
+
+	ed.execCommand('mceBeginUndoLevel');
+
+	switch (getSelectValue(formObj, 'action')) {
+		case "cell":
+			var celltype = getSelectValue(formObj, 'celltype');
+			var scope = getSelectValue(formObj, 'scope');
+
+			if (ed.getParam("accessibility_warnings")) {
+				if (celltype == "th" && scope == "")
+					var answer = confirm(ed.getLang('table_dlg.missing_scope', '', true));
+				else
+					var answer = true;
+
+				if (!answer)
+					return;
+			}
+
+			updateCell(tdElm);
+			break;
+
+		case "row":
+			var cell = trElm.firstChild;
+
+			if (cell.nodeName != "TD" && cell.nodeName != "TH")
+				cell = nextCell(cell);
+
+			do {
+				cell = updateCell(cell, true);
+			} while ((cell = nextCell(cell)) != null);
+
+			break;
+
+		case "all":
+			var rows = tableElm.getElementsByTagName("tr");
+
+			for (var i=0; i<rows.length; i++) {
+				var cell = rows[i].firstChild;
+
+				if (cell.nodeName != "TD" && cell.nodeName != "TH")
+					cell = nextCell(cell);
+
+				do {
+					cell = updateCell(cell, true);
+				} while ((cell = nextCell(cell)) != null);
+			}
+
+			break;
+	}
+
+	ed.addVisual();
+	ed.nodeChanged();
+	inst.execCommand('mceEndUndoLevel');
+	tinyMCEPopup.close();
+}
+
+function nextCell(elm) {
+	while ((elm = elm.nextSibling) != null) {
+		if (elm.nodeName == "TD" || elm.nodeName == "TH")
+			return elm;
+	}
+
+	return null;
+}
+
+function updateCell(td, skip_id) {
+	var inst = ed;
+	var formObj = document.forms[0];
+	var curCellType = td.nodeName.toLowerCase();
+	var celltype = getSelectValue(formObj, 'celltype');
+	var doc = inst.getDoc();
+	var dom = ed.dom;
+
+	if (!skip_id)
+		td.setAttribute('id', formObj.id.value);
+
+	td.setAttribute('align', formObj.align.value);
+	td.setAttribute('vAlign', formObj.valign.value);
+	td.setAttribute('lang', formObj.lang.value);
+	td.setAttribute('dir', getSelectValue(formObj, 'dir'));
+	td.setAttribute('style', ed.dom.serializeStyle(ed.dom.parseStyle(formObj.style.value)));
+	td.setAttribute('scope', formObj.scope.value);
+	ed.dom.setAttrib(td, 'class', getSelectValue(formObj, 'class'));
+
+	// Clear deprecated attributes
+	ed.dom.setAttrib(td, 'width', '');
+	ed.dom.setAttrib(td, 'height', '');
+	ed.dom.setAttrib(td, 'bgColor', '');
+	ed.dom.setAttrib(td, 'borderColor', '');
+	ed.dom.setAttrib(td, 'background', '');
+
+	// Set styles
+	td.style.width = getCSSSize(formObj.width.value);
+	td.style.height = getCSSSize(formObj.height.value);
+	if (formObj.bordercolor.value != "") {
+		td.style.borderColor = formObj.bordercolor.value;
+		td.style.borderStyle = td.style.borderStyle == "" ? "solid" : td.style.borderStyle;
+		td.style.borderWidth = td.style.borderWidth == "" ? "1px" : td.style.borderWidth;
+	} else
+		td.style.borderColor = '';
+
+	td.style.backgroundColor = formObj.bgcolor.value;
+
+	if (formObj.backgroundimage.value != "")
+		td.style.backgroundImage = "url('" + formObj.backgroundimage.value + "')";
+	else
+		td.style.backgroundImage = '';
+
+	if (curCellType != celltype) {
+		// changing to a different node type
+		var newCell = doc.createElement(celltype);
+
+		for (var c=0; c<td.childNodes.length; c++)
+			newCell.appendChild(td.childNodes[c].cloneNode(1));
+
+		for (var a=0; a<td.attributes.length; a++) {
+			var attr = td.attributes[a];
+			newCell.setAttribute(attr.name, attr.value);
+		}
+
+		td.parentNode.replaceChild(newCell, td);
+		td = newCell;
+	}
+
+	dom.setAttrib(td, 'style', dom.serializeStyle(dom.parseStyle(td.style.cssText)));
+
+	return td;
+}
+
+function changedBackgroundImage() {
+	var formObj = document.forms[0];
+	var st = ed.dom.parseStyle(formObj.style.value);
+
+	st['background-image'] = "url('" + formObj.backgroundimage.value + "')";
+
+	formObj.style.value = ed.dom.serializeStyle(st);
+}
+
+function changedSize() {
+	var formObj = document.forms[0];
+	var st = ed.dom.parseStyle(formObj.style.value);
+
+	var width = formObj.width.value;
+	if (width != "")
+		st['width'] = getCSSSize(width);
+	else
+		st['width'] = "";
+
+	var height = formObj.height.value;
+	if (height != "")
+		st['height'] = getCSSSize(height);
+	else
+		st['height'] = "";
+
+	formObj.style.value = ed.dom.serializeStyle(st);
+}
+
+function changedColor() {
+	var formObj = document.forms[0];
+	var st = ed.dom.parseStyle(formObj.style.value);
+
+	st['background-color'] = formObj.bgcolor.value;
+	st['border-color'] = formObj.bordercolor.value;
+
+	formObj.style.value = ed.dom.serializeStyle(st);
+}
+
+function changedStyle() {
+	var formObj = document.forms[0];
+	var st = ed.dom.parseStyle(formObj.style.value);
+
+	if (st['background-image'])
+		formObj.backgroundimage.value = st['background-image'].replace(new RegExp("url\\('?([^']*)'?\\)", 'gi'), "$1");
+	else
+		formObj.backgroundimage.value = '';
+
+	if (st['width'])
+		formObj.width.value = trimSize(st['width']);
+
+	if (st['height'])
+		formObj.height.value = trimSize(st['height']);
+
+	if (st['background-color']) {
+		formObj.bgcolor.value = st['background-color'];
+		updateColor('bgcolor_pick','bgcolor');
+	}
+
+	if (st['border-color']) {
+		formObj.bordercolor.value = st['border-color'];
+		updateColor('bordercolor_pick','bordercolor');
+	}
+}
+
+tinyMCEPopup.onInit.add(init);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/includes/clientside/tinymce/plugins/table/js/merge_cells.js	Fri Feb 22 12:51:53 2008 -0500
@@ -0,0 +1,28 @@
+tinyMCEPopup.requireLangPack();
+
+function init() {
+	tinyMCEPopup.resizeToInnerSize();
+
+	var formObj = document.forms[0];
+
+	formObj.numcols.value = tinyMCEPopup.getWindowArg('numcols', 1);
+	formObj.numrows.value = tinyMCEPopup.getWindowArg('numrows', 1);
+}
+
+function mergeCells() {
+	var args = new Array();
+	var formObj = document.forms[0];
+
+	if (!AutoValidator.validate(formObj)) {
+		alert(tinyMCEPopup.getLang('invalid_data'));
+		return false;
+	}
+
+	args["numcols"] = formObj.numcols.value;
+	args["numrows"] = formObj.numrows.value;
+
+	tinyMCEPopup.execCommand("mceTableMergeCells", false, args);
+	tinyMCEPopup.close();
+}
+
+tinyMCEPopup.onInit.add(init);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/includes/clientside/tinymce/plugins/table/js/row.js	Fri Feb 22 12:51:53 2008 -0500
@@ -0,0 +1,207 @@
+tinyMCEPopup.requireLangPack();
+
+function init() {
+	tinyMCEPopup.resizeToInnerSize();
+
+	document.getElementById('backgroundimagebrowsercontainer').innerHTML = getBrowserHTML('backgroundimagebrowser','backgroundimage','image','table');
+	document.getElementById('bgcolor_pickcontainer').innerHTML = getColorPickerHTML('bgcolor_pick','bgcolor');
+
+	var inst = tinyMCEPopup.editor;
+	var dom = inst.dom;
+	var trElm = dom.getParent(inst.selection.getNode(), "tr");
+	var formObj = document.forms[0];
+	var st = dom.parseStyle(dom.getAttrib(trElm, "style"));
+
+	// Get table row data
+	var rowtype = trElm.parentNode.nodeName.toLowerCase();
+	var align = dom.getAttrib(trElm, 'align');
+	var valign = dom.getAttrib(trElm, 'valign');
+	var height = trimSize(getStyle(trElm, 'height', 'height'));
+	var className = dom.getAttrib(trElm, 'class');
+	var bgcolor = convertRGBToHex(getStyle(trElm, 'bgcolor', 'backgroundColor'));
+	var backgroundimage = getStyle(trElm, 'background', 'backgroundImage').replace(new RegExp("url\\('?([^']*)'?\\)", 'gi'), "$1");;
+	var id = dom.getAttrib(trElm, 'id');
+	var lang = dom.getAttrib(trElm, 'lang');
+	var dir = dom.getAttrib(trElm, 'dir');
+
+	// Setup form
+	addClassesToList('class', 'table_row_styles');
+	formObj.bgcolor.value = bgcolor;
+	formObj.backgroundimage.value = backgroundimage;
+	formObj.height.value = height;
+	formObj.id.value = id;
+	formObj.lang.value = lang;
+	formObj.style.value = dom.serializeStyle(st);
+	selectByValue(formObj, 'align', align);
+	selectByValue(formObj, 'valign', valign);
+	selectByValue(formObj, 'class', className);
+	selectByValue(formObj, 'rowtype', rowtype);
+	selectByValue(formObj, 'dir', dir);
+
+	// Resize some elements
+	if (isVisible('backgroundimagebrowser'))
+		document.getElementById('backgroundimage').style.width = '180px';
+
+	updateColor('bgcolor_pick', 'bgcolor');
+}
+
+function updateAction() {
+	var inst = tinyMCEPopup.editor;
+	var dom = inst.dom;
+	var trElm = dom.getParent(inst.selection.getNode(), "tr");
+	var tableElm = dom.getParent(inst.selection.getNode(), "table");
+	var formObj = document.forms[0];
+	var action = getSelectValue(formObj, 'action');
+
+	inst.execCommand('mceBeginUndoLevel');
+
+	switch (action) {
+		case "row":
+			updateRow(trElm);
+			break;
+
+		case "all":
+			var rows = tableElm.getElementsByTagName("tr");
+
+			for (var i=0; i<rows.length; i++)
+				updateRow(rows[i], true);
+
+			break;
+
+		case "odd":
+		case "even":
+			var rows = tableElm.getElementsByTagName("tr");
+
+			for (var i=0; i<rows.length; i++) {
+				if ((i % 2 == 0 && action == "odd") || (i % 2 != 0 && action == "even"))
+					updateRow(rows[i], true, true);
+			}
+
+			break;
+	}
+
+	inst.addVisual();
+	inst.nodeChanged();
+	inst.execCommand('mceEndUndoLevel');
+	tinyMCEPopup.close();
+}
+
+function updateRow(tr_elm, skip_id, skip_parent) {
+	var inst = tinyMCEPopup.editor;
+	var formObj = document.forms[0];
+	var dom = inst.dom;
+	var curRowType = tr_elm.parentNode.nodeName.toLowerCase();
+	var rowtype = getSelectValue(formObj, 'rowtype');
+	var doc = inst.getDoc();
+
+	// Update row element
+	if (!skip_id)
+		tr_elm.setAttribute('id', formObj.id.value);
+
+	tr_elm.setAttribute('align', getSelectValue(formObj, 'align'));
+	tr_elm.setAttribute('vAlign', getSelectValue(formObj, 'valign'));
+	tr_elm.setAttribute('lang', formObj.lang.value);
+	tr_elm.setAttribute('dir', getSelectValue(formObj, 'dir'));
+	tr_elm.setAttribute('style', dom.serializeStyle(dom.parseStyle(formObj.style.value)));
+	dom.setAttrib(tr_elm, 'class', getSelectValue(formObj, 'class'));
+
+	// Clear deprecated attributes
+	tr_elm.setAttribute('background', '');
+	tr_elm.setAttribute('bgColor', '');
+	tr_elm.setAttribute('height', '');
+
+	// Set styles
+	tr_elm.style.height = getCSSSize(formObj.height.value);
+	tr_elm.style.backgroundColor = formObj.bgcolor.value;
+
+	if (formObj.backgroundimage.value != "")
+		tr_elm.style.backgroundImage = "url('" + formObj.backgroundimage.value + "')";
+	else
+		tr_elm.style.backgroundImage = '';
+
+	// Setup new rowtype
+	if (curRowType != rowtype && !skip_parent) {
+		// first, clone the node we are working on
+		var newRow = tr_elm.cloneNode(1);
+
+		// next, find the parent of its new destination (creating it if necessary)
+		var theTable = dom.getParent(tr_elm, "table");
+		var dest = rowtype;
+		var newParent = null;
+		for (var i = 0; i < theTable.childNodes.length; i++) {
+			if (theTable.childNodes[i].nodeName.toLowerCase() == dest)
+				newParent = theTable.childNodes[i];
+		}
+
+		if (newParent == null) {
+			newParent = doc.createElement(dest);
+
+			if (dest == "thead")
+				theTable.insertBefore(newParent, theTable.firstChild);
+			else
+				theTable.appendChild(newParent);
+		}
+
+		// append the row to the new parent
+		newParent.appendChild(newRow);
+
+		// remove the original
+		tr_elm.parentNode.removeChild(tr_elm);
+
+		// set tr_elm to the new node
+		tr_elm = newRow;
+	}
+
+	dom.setAttrib(tr_elm, 'style', dom.serializeStyle(dom.parseStyle(tr_elm.style.cssText)));
+}
+
+function changedBackgroundImage() {
+	var formObj = document.forms[0], dom = tinyMCEPopup.editor.dom;
+	var st = dom.parseStyle(formObj.style.value);
+
+	st['background-image'] = "url('" + formObj.backgroundimage.value + "')";
+
+	formObj.style.value = dom.serializeStyle(st);
+}
+
+function changedStyle() {
+	var formObj = document.forms[0], dom = tinyMCEPopup.editor.dom;
+	var st = dom.parseStyle(formObj.style.value);
+
+	if (st['background-image'])
+		formObj.backgroundimage.value = st['background-image'].replace(new RegExp("url\\('?([^']*)'?\\)", 'gi'), "$1");
+	else
+		formObj.backgroundimage.value = '';
+
+	if (st['height'])
+		formObj.height.value = trimSize(st['height']);
+
+	if (st['background-color']) {
+		formObj.bgcolor.value = st['background-color'];
+		updateColor('bgcolor_pick','bgcolor');
+	}
+}
+
+function changedSize() {
+	var formObj = document.forms[0], dom = tinyMCEPopup.editor.dom;
+	var st = dom.parseStyle(formObj.style.value);
+
+	var height = formObj.height.value;
+	if (height != "")
+		st['height'] = getCSSSize(height);
+	else
+		st['height'] = "";
+
+	formObj.style.value = dom.serializeStyle(st);
+}
+
+function changedColor() {
+	var formObj = document.forms[0], dom = tinyMCEPopup.editor.dom;
+	var st = dom.parseStyle(formObj.style.value);
+
+	st['background-color'] = formObj.bgcolor.value;
+
+	formObj.style.value = dom.serializeStyle(st);
+}
+
+tinyMCEPopup.onInit.add(init);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/includes/clientside/tinymce/plugins/table/js/table.js	Fri Feb 22 12:51:53 2008 -0500
@@ -0,0 +1,382 @@
+tinyMCEPopup.requireLangPack();
+
+var action, orgTableWidth, orgTableHeight, dom = tinyMCEPopup.editor.dom;
+
+function insertTable() {
+	var formObj = document.forms[0];
+	var inst = tinyMCEPopup.editor, dom = inst.dom;
+	var cols = 2, rows = 2, border = 0, cellpadding = -1, cellspacing = -1, align, width, height, className, caption, frame, rules;
+	var html = '', capEl, elm;
+	var cellLimit, rowLimit, colLimit;
+
+	if (!AutoValidator.validate(formObj)) {
+		alert(inst.getLang('invalid_data'));
+		return false;
+	}
+
+	elm = dom.getParent(inst.selection.getNode(), 'table');
+
+	// Get form data
+	cols = formObj.elements['cols'].value;
+	rows = formObj.elements['rows'].value;
+	border = formObj.elements['border'].value != "" ? formObj.elements['border'].value  : 0;
+	cellpadding = formObj.elements['cellpadding'].value != "" ? formObj.elements['cellpadding'].value : "";
+	cellspacing = formObj.elements['cellspacing'].value != "" ? formObj.elements['cellspacing'].value : "";
+	align = formObj.elements['align'].options[formObj.elements['align'].selectedIndex].value;
+	frame = formObj.elements['frame'].options[formObj.elements['frame'].selectedIndex].value;
+	rules = formObj.elements['rules'].options[formObj.elements['rules'].selectedIndex].value;
+	width = formObj.elements['width'].value;
+	height = formObj.elements['height'].value;
+	bordercolor = formObj.elements['bordercolor'].value;
+	bgcolor = formObj.elements['bgcolor'].value;
+	className = formObj.elements['class'].options[formObj.elements['class'].selectedIndex].value;
+	id = formObj.elements['id'].value;
+	summary = formObj.elements['summary'].value;
+	style = formObj.elements['style'].value;
+	dir = formObj.elements['dir'].value;
+	lang = formObj.elements['lang'].value;
+	background = formObj.elements['backgroundimage'].value;
+	caption = formObj.elements['caption'].checked;
+
+	cellLimit = tinyMCEPopup.getParam('table_cell_limit', false);
+	rowLimit = tinyMCEPopup.getParam('table_row_limit', false);
+	colLimit = tinyMCEPopup.getParam('table_col_limit', false);
+
+	// Validate table size
+	if (colLimit && cols > colLimit) {
+		alert(inst.getLang('table_col_limit', '', true, {cols : colLimit}));
+		return false;
+	} else if (rowLimit && rows > rowLimit) {
+		alert(inst.getLang('table_row_limit', '', true, {rows : rowLimit}));
+		return false;
+	} else if (cellLimit && cols * rows > cellLimit) {
+		alert(inst.getLang('table_cell_limit', '', true, {cells : cellLimit}));
+		return false;
+	}
+
+	// Update table
+	if (action == "update") {
+		inst.execCommand('mceBeginUndoLevel');
+
+		dom.setAttrib(elm, 'cellPadding', cellpadding, true);
+		dom.setAttrib(elm, 'cellSpacing', cellspacing, true);
+		dom.setAttrib(elm, 'border', border);
+		dom.setAttrib(elm, 'align', align);
+		dom.setAttrib(elm, 'frame', frame);
+		dom.setAttrib(elm, 'rules', rules);
+		dom.setAttrib(elm, 'class', className);
+		dom.setAttrib(elm, 'style', style);
+		dom.setAttrib(elm, 'id', id);
+		dom.setAttrib(elm, 'summary', summary);
+		dom.setAttrib(elm, 'dir', dir);
+		dom.setAttrib(elm, 'lang', lang);
+
+		capEl = inst.dom.select('caption', elm)[0];
+
+		if (capEl && !caption)
+			capEl.parentNode.removeChild(capEl);
+
+		if (!capEl && caption) {
+			capEl = elm.ownerDocument.createElement('caption');
+
+			if (!tinymce.isIE)
+				capEl.innerHTML = '<br mce_bogus="1"/>';
+
+			elm.insertBefore(capEl, elm.firstChild);
+		}
+
+		dom.setAttrib(elm, 'width', width, true);
+
+		// Remove these since they are not valid XHTML
+		dom.setAttrib(elm, 'borderColor', '');
+		dom.setAttrib(elm, 'bgColor', '');
+		dom.setAttrib(elm, 'background', '');
+		dom.setAttrib(elm, 'height', '');
+
+		if (background != '')
+			elm.style.backgroundImage = "url('" + background + "')";
+		else
+			elm.style.backgroundImage = '';
+
+/*		if (tinyMCEPopup.getParam("inline_styles")) {
+			if (width != '')
+				elm.style.width = getCSSSize(width);
+		}*/
+
+		if (bordercolor != "") {
+			elm.style.borderColor = bordercolor;
+			elm.style.borderStyle = elm.style.borderStyle == "" ? "solid" : elm.style.borderStyle;
+			elm.style.borderWidth = border == "" ? "1px" : border;
+		} else
+			elm.style.borderColor = '';
+
+		elm.style.backgroundColor = bgcolor;
+		elm.style.height = getCSSSize(height);
+
+		inst.addVisual();
+
+		// Fix for stange MSIE align bug
+		//elm.outerHTML = elm.outerHTML;
+
+		inst.nodeChanged();
+		inst.execCommand('mceEndUndoLevel');
+
+		// Repaint if dimensions changed
+		if (formObj.width.value != orgTableWidth || formObj.height.value != orgTableHeight)
+			inst.execCommand('mceRepaint');
+
+		tinyMCEPopup.close();
+		return true;
+	}
+
+	// Create new table
+	html += '<table';
+
+	html += makeAttrib('id', id);
+	html += makeAttrib('border', border);
+	html += makeAttrib('cellpadding', cellpadding);
+	html += makeAttrib('cellspacing', cellspacing);
+	html += makeAttrib('width', width);
+	//html += makeAttrib('height', height);
+	//html += makeAttrib('bordercolor', bordercolor);
+	//html += makeAttrib('bgcolor', bgcolor);
+	html += makeAttrib('align', align);
+	html += makeAttrib('frame', frame);
+	html += makeAttrib('rules', rules);
+	html += makeAttrib('class', className);
+	html += makeAttrib('style', style);
+	html += makeAttrib('summary', summary);
+	html += makeAttrib('dir', dir);
+	html += makeAttrib('lang', lang);
+	html += '>';
+
+	if (caption) {
+		if (!tinymce.isIE)
+			html += '<caption><br mce_bogus="1"/></caption>';
+		else
+			html += '<caption></caption>';
+	}
+
+	for (var y=0; y<rows; y++) {
+		html += "<tr>";
+
+		for (var x=0; x<cols; x++) {
+			if (!tinymce.isIE)
+				html += '<td><br mce_bogus="1"/></td>';
+			else
+				html += '<td></td>';
+		}
+
+		html += "</tr>";
+	}
+
+	html += "</table>";
+
+	inst.execCommand('mceBeginUndoLevel');
+	inst.execCommand('mceInsertContent', false, html);
+	inst.addVisual();
+	inst.execCommand('mceEndUndoLevel');
+
+	tinyMCEPopup.close();
+}
+
+function makeAttrib(attrib, value) {
+	var formObj = document.forms[0];
+	var valueElm = formObj.elements[attrib];
+
+	if (typeof(value) == "undefined" || value == null) {
+		value = "";
+
+		if (valueElm)
+			value = valueElm.value;
+	}
+
+	if (value == "")
+		return "";
+
+	// XML encode it
+	value = value.replace(/&/g, '&amp;');
+	value = value.replace(/\"/g, '&quot;');
+	value = value.replace(/</g, '&lt;');
+	value = value.replace(/>/g, '&gt;');
+
+	return ' ' + attrib + '="' + value + '"';
+}
+
+function init() {
+	tinyMCEPopup.resizeToInnerSize();
+
+	document.getElementById('backgroundimagebrowsercontainer').innerHTML = getBrowserHTML('backgroundimagebrowser','backgroundimage','image','table');
+	document.getElementById('backgroundimagebrowsercontainer').innerHTML = getBrowserHTML('backgroundimagebrowser','backgroundimage','image','table');
+	document.getElementById('bordercolor_pickcontainer').innerHTML = getColorPickerHTML('bordercolor_pick','bordercolor');
+	document.getElementById('bgcolor_pickcontainer').innerHTML = getColorPickerHTML('bgcolor_pick','bgcolor');
+
+	var cols = 2, rows = 2, border = tinyMCEPopup.getParam('table_default_border', '0'), cellpadding = tinyMCEPopup.getParam('table_default_cellpadding', ''), cellspacing = tinyMCEPopup.getParam('table_default_cellspacing', '');
+	var align = "", width = "", height = "", bordercolor = "", bgcolor = "", className = "";
+	var id = "", summary = "", style = "", dir = "", lang = "", background = "", bgcolor = "", bordercolor = "", rules, frame;
+	var inst = tinyMCEPopup.editor, dom = inst.dom;
+	var formObj = document.forms[0];
+	var elm = dom.getParent(inst.selection.getNode(), "table");
+
+	action = tinyMCEPopup.getWindowArg('action');
+
+	if (!action)
+		action = elm ? "update" : "insert";
+
+	if (elm && action != "insert") {
+		var rowsAr = elm.rows;
+		var cols = 0;
+		for (var i=0; i<rowsAr.length; i++)
+			if (rowsAr[i].cells.length > cols)
+				cols = rowsAr[i].cells.length;
+
+		cols = cols;
+		rows = rowsAr.length;
+
+		st = dom.parseStyle(dom.getAttrib(elm, "style"));
+		border = trimSize(getStyle(elm, 'border', 'borderWidth'));
+		cellpadding = dom.getAttrib(elm, 'cellpadding', "");
+		cellspacing = dom.getAttrib(elm, 'cellspacing', "");
+		width = trimSize(getStyle(elm, 'width', 'width'));
+		height = trimSize(getStyle(elm, 'height', 'height'));
+		bordercolor = convertRGBToHex(getStyle(elm, 'bordercolor', 'borderLeftColor'));
+		bgcolor = convertRGBToHex(getStyle(elm, 'bgcolor', 'backgroundColor'));
+		align = dom.getAttrib(elm, 'align', align);
+		frame = dom.getAttrib(elm, 'frame');
+		rules = dom.getAttrib(elm, 'rules');
+		className = tinymce.trim(dom.getAttrib(elm, 'class').replace(/mceItem.+/g, ''));
+		id = dom.getAttrib(elm, 'id');
+		summary = dom.getAttrib(elm, 'summary');
+		style = dom.serializeStyle(st);
+		dir = dom.getAttrib(elm, 'dir');
+		lang = dom.getAttrib(elm, 'lang');
+		background = getStyle(elm, 'background', 'backgroundImage').replace(new RegExp("url\\('?([^']*)'?\\)", 'gi'), "$1");
+		formObj.caption.checked = elm.getElementsByTagName('caption').length > 0;
+
+		orgTableWidth = width;
+		orgTableHeight = height;
+
+		action = "update";
+		formObj.insert.value = inst.getLang('update');
+	}
+
+	addClassesToList('class', "table_styles");
+
+	// Update form
+	selectByValue(formObj, 'align', align);
+	selectByValue(formObj, 'frame', frame);
+	selectByValue(formObj, 'rules', rules);
+	selectByValue(formObj, 'class', className);
+	formObj.cols.value = cols;
+	formObj.rows.value = rows;
+	formObj.border.value = border;
+	formObj.cellpadding.value = cellpadding;
+	formObj.cellspacing.value = cellspacing;
+	formObj.width.value = width;
+	formObj.height.value = height;
+	formObj.bordercolor.value = bordercolor;
+	formObj.bgcolor.value = bgcolor;
+	formObj.id.value = id;
+	formObj.summary.value = summary;
+	formObj.style.value = style;
+	formObj.dir.value = dir;
+	formObj.lang.value = lang;
+	formObj.backgroundimage.value = background;
+
+	updateColor('bordercolor_pick', 'bordercolor');
+	updateColor('bgcolor_pick', 'bgcolor');
+
+	// Resize some elements
+	if (isVisible('backgroundimagebrowser'))
+		document.getElementById('backgroundimage').style.width = '180px';
+
+	// Disable some fields in update mode
+	if (action == "update") {
+		formObj.cols.disabled = true;
+		formObj.rows.disabled = true;
+	}
+}
+
+function changedSize() {
+	var formObj = document.forms[0];
+	var st = dom.parseStyle(formObj.style.value);
+
+/*	var width = formObj.width.value;
+	if (width != "")
+		st['width'] = tinyMCEPopup.getParam("inline_styles") ? getCSSSize(width) : "";
+	else
+		st['width'] = "";*/
+
+	var height = formObj.height.value;
+	if (height != "")
+		st['height'] = getCSSSize(height);
+	else
+		st['height'] = "";
+
+	formObj.style.value = dom.serializeStyle(st);
+}
+
+function changedBackgroundImage() {
+	var formObj = document.forms[0];
+	var st = dom.parseStyle(formObj.style.value);
+
+	st['background-image'] = "url('" + formObj.backgroundimage.value + "')";
+
+	formObj.style.value = dom.serializeStyle(st);
+}
+
+function changedBorder() {
+	var formObj = document.forms[0];
+	var st = dom.parseStyle(formObj.style.value);
+
+	// Update border width if the element has a color
+	if (formObj.border.value != "" && formObj.bordercolor.value != "")
+		st['border-width'] = formObj.border.value + "px";
+
+	formObj.style.value = dom.serializeStyle(st);
+}
+
+function changedColor() {
+	var formObj = document.forms[0];
+	var st = dom.parseStyle(formObj.style.value);
+
+	st['background-color'] = formObj.bgcolor.value;
+
+	if (formObj.bordercolor.value != "") {
+		st['border-color'] = formObj.bordercolor.value;
+
+		// Add border-width if it's missing
+		if (!st['border-width'])
+			st['border-width'] = formObj.border.value == "" ? "1px" : formObj.border.value + "px";
+	}
+
+	formObj.style.value = dom.serializeStyle(st);
+}
+
+function changedStyle() {
+	var formObj = document.forms[0];
+	var st = dom.parseStyle(formObj.style.value);
+
+	if (st['background-image'])
+		formObj.backgroundimage.value = st['background-image'].replace(new RegExp("url\\('?([^']*)'?\\)", 'gi'), "$1");
+	else
+		formObj.backgroundimage.value = '';
+
+	if (st['width'])
+		formObj.width.value = trimSize(st['width']);
+
+	if (st['height'])
+		formObj.height.value = trimSize(st['height']);
+
+	if (st['background-color']) {
+		formObj.bgcolor.value = st['background-color'];
+		updateColor('bgcolor_pick','bgcolor');
+	}
+
+	if (st['border-color']) {
+		formObj.bordercolor.value = st['border-color'];
+		updateColor('bordercolor_pick','bordercolor');
+	}
+}
+
+tinyMCEPopup.onInit.add(init);
--- a/includes/clientside/tinymce/plugins/table/jscripts/cell.js	Fri Feb 22 12:46:51 2008 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,249 +0,0 @@
-function init() {
-	tinyMCEPopup.resizeToInnerSize();
-
-	document.getElementById('backgroundimagebrowsercontainer').innerHTML = getBrowserHTML('backgroundimagebrowser','backgroundimage','image','table');
-	document.getElementById('bordercolor_pickcontainer').innerHTML = getColorPickerHTML('bordercolor_pick','bordercolor');
-	document.getElementById('bgcolor_pickcontainer').innerHTML = getColorPickerHTML('bgcolor_pick','bgcolor')
-
-	var inst = tinyMCE.selectedInstance;
-	var tdElm = tinyMCE.getParentElement(inst.getFocusElement(), "td,th");
-	var formObj = document.forms[0];
-	var st = tinyMCE.parseStyle(tinyMCE.getAttrib(tdElm, "style"));
-
-	// Get table cell data
-	var celltype = tdElm.nodeName.toLowerCase();
-	var align = tinyMCE.getAttrib(tdElm, 'align');
-	var valign = tinyMCE.getAttrib(tdElm, 'valign');
-	var width = trimSize(getStyle(tdElm, 'width', 'width'));
-	var height = trimSize(getStyle(tdElm, 'height', 'height'));
-	var bordercolor = convertRGBToHex(getStyle(tdElm, 'bordercolor', 'borderLeftColor'));
-	var bgcolor = convertRGBToHex(getStyle(tdElm, 'bgcolor', 'backgroundColor'));
-	var className = tinyMCE.getVisualAidClass(tinyMCE.getAttrib(tdElm, 'class'), false);
-	var backgroundimage = getStyle(tdElm, 'background', 'backgroundImage').replace(new RegExp("url\\('?([^']*)'?\\)", 'gi'), "$1");;
-	var id = tinyMCE.getAttrib(tdElm, 'id');
-	var lang = tinyMCE.getAttrib(tdElm, 'lang');
-	var dir = tinyMCE.getAttrib(tdElm, 'dir');
-	var scope = tinyMCE.getAttrib(tdElm, 'scope');
-
-	// Setup form
-	addClassesToList('class', 'table_cell_styles');
-	formObj.bordercolor.value = bordercolor;
-	formObj.bgcolor.value = bgcolor;
-	formObj.backgroundimage.value = backgroundimage;
-	formObj.width.value = width;
-	formObj.height.value = height;
-	formObj.id.value = id;
-	formObj.lang.value = lang;
-	formObj.style.value = tinyMCE.serializeStyle(st);
-	selectByValue(formObj, 'align', align);
-	selectByValue(formObj, 'valign', valign);
-	selectByValue(formObj, 'class', className);
-	selectByValue(formObj, 'celltype', celltype);
-	selectByValue(formObj, 'dir', dir);
-	selectByValue(formObj, 'scope', scope);
-
-	// Resize some elements
-	if (isVisible('backgroundimagebrowser'))
-		document.getElementById('backgroundimage').style.width = '180px';
-
-	updateColor('bordercolor_pick', 'bordercolor');
-	updateColor('bgcolor_pick', 'bgcolor');
-}
-
-function updateAction() {
-	tinyMCEPopup.restoreSelection();
-
-	var inst = tinyMCE.selectedInstance;
-	var tdElm = tinyMCE.getParentElement(inst.getFocusElement(), "td,th");
-	var trElm = tinyMCE.getParentElement(inst.getFocusElement(), "tr");
-	var tableElm = tinyMCE.getParentElement(inst.getFocusElement(), "table");
-	var formObj = document.forms[0];
-
-	inst.execCommand('mceBeginUndoLevel');
-
-	switch (getSelectValue(formObj, 'action')) {
-		case "cell":
-			var celltype = getSelectValue(formObj, 'celltype');
-			var scope = getSelectValue(formObj, 'scope');
-
-			if (tinyMCE.getParam("accessibility_warnings")) {
-				if (celltype == "th" && scope == "")
-					var answer = confirm(tinyMCE.getLang('lang_table_missing_scope', '', true));
-				else
-					var answer = true;
-
-				if (!answer)
-					return;
-			}
-
-			updateCell(tdElm);
-			break;
-
-		case "row":
-			var cell = trElm.firstChild;
-
-			if (cell.nodeName != "TD" && cell.nodeName != "TH")
-				cell = nextCell(cell);
-
-			do {
-				cell = updateCell(cell, true);
-			} while ((cell = nextCell(cell)) != null);
-
-			break;
-
-		case "all":
-			var rows = tableElm.getElementsByTagName("tr");
-
-			for (var i=0; i<rows.length; i++) {
-				var cell = rows[i].firstChild;
-
-				if (cell.nodeName != "TD" && cell.nodeName != "TH")
-					cell = nextCell(cell);
-
-				do {
-					cell = updateCell(cell, true);
-				} while ((cell = nextCell(cell)) != null);
-			}
-
-			break;
-	}
-
-	tinyMCE.handleVisualAid(inst.getBody(), true, inst.visualAid, inst);
-	tinyMCE.triggerNodeChange();
-	inst.execCommand('mceEndUndoLevel');
-	tinyMCEPopup.close();
-}
-
-function nextCell(elm) {
-	while ((elm = elm.nextSibling) != null) {
-		if (elm.nodeName == "TD" || elm.nodeName == "TH")
-			return elm;
-	}
-
-	return null;
-}
-
-function updateCell(td, skip_id) {
-	var inst = tinyMCE.selectedInstance;
-	var formObj = document.forms[0];
-	var curCellType = td.nodeName.toLowerCase();
-	var celltype = getSelectValue(formObj, 'celltype');
-	var doc = inst.getDoc();
-
-	if (!skip_id)
-		td.setAttribute('id', formObj.id.value);
-
-	td.setAttribute('align', formObj.align.value);
-	td.setAttribute('vAlign', formObj.valign.value);
-	td.setAttribute('lang', formObj.lang.value);
-	td.setAttribute('dir', getSelectValue(formObj, 'dir'));
-	td.setAttribute('style', tinyMCE.serializeStyle(tinyMCE.parseStyle(formObj.style.value)));
-	td.setAttribute('scope', formObj.scope.value);
-	tinyMCE.setAttrib(td, 'class', getSelectValue(formObj, 'class'));
-
-	// Clear deprecated attributes
-	tinyMCE.setAttrib(td, 'width', '');
-	tinyMCE.setAttrib(td, 'height', '');
-	tinyMCE.setAttrib(td, 'bgColor', '');
-	tinyMCE.setAttrib(td, 'borderColor', '');
-	tinyMCE.setAttrib(td, 'background', '');
-
-	// Set styles
-	td.style.width = getCSSSize(formObj.width.value);
-	td.style.height = getCSSSize(formObj.height.value);
-	if (formObj.bordercolor.value != "") {
-		td.style.borderColor = formObj.bordercolor.value;
-		td.style.borderStyle = td.style.borderStyle == "" ? "solid" : td.style.borderStyle;
-		td.style.borderWidth = td.style.borderWidth == "" ? "1px" : td.style.borderWidth;
-	} else
-		td.style.borderColor = '';
-
-	td.style.backgroundColor = formObj.bgcolor.value;
-
-	if (formObj.backgroundimage.value != "")
-		td.style.backgroundImage = "url('" + formObj.backgroundimage.value + "')";
-	else
-		td.style.backgroundImage = '';
-
-	if (curCellType != celltype) {
-		// changing to a different node type
-		var newCell = doc.createElement(celltype);
-
-		for (var c=0; c<td.childNodes.length; c++)
-			newCell.appendChild(td.childNodes[c].cloneNode(1));
-
-		for (var a=0; a<td.attributes.length; a++) {
-			var attr = td.attributes[a];
-			newCell.setAttribute(attr.name, attr.value);
-		}
-
-		td.parentNode.replaceChild(newCell, td);
-		td = newCell;
-	}
-
-	return td;
-}
-
-function changedBackgroundImage() {
-	var formObj = document.forms[0];
-	var st = tinyMCE.parseStyle(formObj.style.value);
-
-	st['background-image'] = "url('" + formObj.backgroundimage.value + "')";
-
-	formObj.style.value = tinyMCE.serializeStyle(st);
-}
-
-function changedSize() {
-	var formObj = document.forms[0];
-	var st = tinyMCE.parseStyle(formObj.style.value);
-
-	var width = formObj.width.value;
-	if (width != "")
-		st['width'] = getCSSSize(width);
-	else
-		st['width'] = "";
-
-	var height = formObj.height.value;
-	if (height != "")
-		st['height'] = getCSSSize(height);
-	else
-		st['height'] = "";
-
-	formObj.style.value = tinyMCE.serializeStyle(st);
-}
-
-function changedColor() {
-	var formObj = document.forms[0];
-	var st = tinyMCE.parseStyle(formObj.style.value);
-
-	st['background-color'] = formObj.bgcolor.value;
-	st['border-color'] = formObj.bordercolor.value;
-
-	formObj.style.value = tinyMCE.serializeStyle(st);
-}
-
-function changedStyle() {
-	var formObj = document.forms[0];
-	var st = tinyMCE.parseStyle(formObj.style.value);
-
-	if (st['background-image'])
-		formObj.backgroundimage.value = st['background-image'].replace(new RegExp("url\\('?([^']*)'?\\)", 'gi'), "$1");
-	else
-		formObj.backgroundimage.value = '';
-
-	if (st['width'])
-		formObj.width.value = trimSize(st['width']);
-
-	if (st['height'])
-		formObj.height.value = trimSize(st['height']);
-
-	if (st['background-color']) {
-		formObj.bgcolor.value = st['background-color'];
-		updateColor('bgcolor_pick','bgcolor');
-	}
-
-	if (st['border-color']) {
-		formObj.bordercolor.value = st['border-color'];
-		updateColor('bordercolor_pick','bordercolor');
-	}
-}
--- a/includes/clientside/tinymce/plugins/table/jscripts/merge_cells.js	Fri Feb 22 12:46:51 2008 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,24 +0,0 @@
-function init() {
-	tinyMCEPopup.resizeToInnerSize();
-
-	var formObj = document.forms[0];
-
-	formObj.numcols.value = tinyMCE.getWindowArg('numcols', 1);
-	formObj.numrows.value = tinyMCE.getWindowArg('numrows', 1);
-}
-
-function mergeCells() {
-	var args = new Array();
-	var formObj = document.forms[0];
-
-	if (!AutoValidator.validate(formObj)) {
-		alert(tinyMCE.getLang('lang_invalid_data'));
-		return false;
-	}
-
-	args["numcols"] = formObj.numcols.value;
-	args["numrows"] = formObj.numrows.value;
-
-	tinyMCEPopup.execCommand("mceTableMergeCells", false, args);
-	tinyMCEPopup.close();
-}
--- a/includes/clientside/tinymce/plugins/table/jscripts/row.js	Fri Feb 22 12:46:51 2008 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,200 +0,0 @@
-function init() {
-	tinyMCEPopup.resizeToInnerSize();
-
-	document.getElementById('backgroundimagebrowsercontainer').innerHTML = getBrowserHTML('backgroundimagebrowser','backgroundimage','image','table');
-	document.getElementById('bgcolor_pickcontainer').innerHTML = getColorPickerHTML('bgcolor_pick','bgcolor');
-
-	var inst = tinyMCE.selectedInstance;
-	var trElm = tinyMCE.getParentElement(inst.getFocusElement(), "tr");
-	var formObj = document.forms[0];
-	var st = tinyMCE.parseStyle(tinyMCE.getAttrib(trElm, "style"));
-
-	// Get table row data
-	var rowtype = trElm.parentNode.nodeName.toLowerCase();
-	var align = tinyMCE.getAttrib(trElm, 'align');
-	var valign = tinyMCE.getAttrib(trElm, 'valign');
-	var height = trimSize(getStyle(trElm, 'height', 'height'));
-	var className = tinyMCE.getVisualAidClass(tinyMCE.getAttrib(trElm, 'class'), false);
-	var bgcolor = convertRGBToHex(getStyle(trElm, 'bgcolor', 'backgroundColor'));
-	var backgroundimage = getStyle(trElm, 'background', 'backgroundImage').replace(new RegExp("url\\('?([^']*)'?\\)", 'gi'), "$1");;
-	var id = tinyMCE.getAttrib(trElm, 'id');
-	var lang = tinyMCE.getAttrib(trElm, 'lang');
-	var dir = tinyMCE.getAttrib(trElm, 'dir');
-
-	// Setup form
-	addClassesToList('class', 'table_row_styles');
-	formObj.bgcolor.value = bgcolor;
-	formObj.backgroundimage.value = backgroundimage;
-	formObj.height.value = height;
-	formObj.id.value = id;
-	formObj.lang.value = lang;
-	formObj.style.value = tinyMCE.serializeStyle(st);
-	selectByValue(formObj, 'align', align);
-	selectByValue(formObj, 'valign', valign);
-	selectByValue(formObj, 'class', className);
-	selectByValue(formObj, 'rowtype', rowtype);
-	selectByValue(formObj, 'dir', dir);
-
-	// Resize some elements
-	if (isVisible('backgroundimagebrowser'))
-		document.getElementById('backgroundimage').style.width = '180px';
-
-	updateColor('bgcolor_pick', 'bgcolor');
-}
-
-function updateAction() {
-	tinyMCEPopup.restoreSelection();
-
-	var inst = tinyMCE.selectedInstance;
-	var trElm = tinyMCE.getParentElement(inst.getFocusElement(), "tr");
-	var tableElm = tinyMCE.getParentElement(inst.getFocusElement(), "table");
-	var formObj = document.forms[0];
-	var action = getSelectValue(formObj, 'action');
-
-	inst.execCommand('mceBeginUndoLevel');
-
-	switch (action) {
-		case "row":
-			updateRow(trElm);
-			break;
-
-		case "all":
-			var rows = tableElm.getElementsByTagName("tr");
-
-			for (var i=0; i<rows.length; i++)
-				updateRow(rows[i], true);
-
-			break;
-
-		case "odd":
-		case "even":
-			var rows = tableElm.getElementsByTagName("tr");
-
-			for (var i=0; i<rows.length; i++) {
-				if ((i % 2 == 0 && action == "odd") || (i % 2 != 0 && action == "even"))
-					updateRow(rows[i], true, true);
-			}
-
-			break;
-	}
-
-	tinyMCE.handleVisualAid(inst.getBody(), true, inst.visualAid, inst);
-	tinyMCE.triggerNodeChange();
-	inst.execCommand('mceEndUndoLevel');
-	tinyMCEPopup.close();
-}
-
-function updateRow(tr_elm, skip_id, skip_parent) {
-	var inst = tinyMCE.selectedInstance;
-	var formObj = document.forms[0];
-	var curRowType = tr_elm.parentNode.nodeName.toLowerCase();
-	var rowtype = getSelectValue(formObj, 'rowtype');
-	var doc = inst.getDoc();
-
-	// Update row element
-	if (!skip_id)
-		tr_elm.setAttribute('id', formObj.id.value);
-
-	tr_elm.setAttribute('align', getSelectValue(formObj, 'align'));
-	tr_elm.setAttribute('vAlign', getSelectValue(formObj, 'valign'));
-	tr_elm.setAttribute('lang', formObj.lang.value);
-	tr_elm.setAttribute('dir', getSelectValue(formObj, 'dir'));
-	tr_elm.setAttribute('style', tinyMCE.serializeStyle(tinyMCE.parseStyle(formObj.style.value)));
-	tinyMCE.setAttrib(tr_elm, 'class', getSelectValue(formObj, 'class'));
-
-	// Clear deprecated attributes
-	tr_elm.setAttribute('background', '');
-	tr_elm.setAttribute('bgColor', '');
-	tr_elm.setAttribute('height', '');
-
-	// Set styles
-	tr_elm.style.height = getCSSSize(formObj.height.value);
-	tr_elm.style.backgroundColor = formObj.bgcolor.value;
-
-	if (formObj.backgroundimage.value != "")
-		tr_elm.style.backgroundImage = "url('" + formObj.backgroundimage.value + "')";
-	else
-		tr_elm.style.backgroundImage = '';
-
-	// Setup new rowtype
-	if (curRowType != rowtype && !skip_parent) {
-		// first, clone the node we are working on
-		var newRow = tr_elm.cloneNode(1);
-
-		// next, find the parent of its new destination (creating it if necessary)
-		var theTable = tinyMCE.getParentElement(tr_elm, "table");
-		var dest = rowtype;
-		var newParent = null;
-		for (var i = 0; i < theTable.childNodes.length; i++) {
-			if (theTable.childNodes[i].nodeName.toLowerCase() == dest)
-				newParent = theTable.childNodes[i];
-		}
-
-		if (newParent == null) {
-			newParent = doc.createElement(dest);
-
-			if (dest == "thead")
-				theTable.insertBefore(newParent, theTable.firstChild);
-			else
-				theTable.appendChild(newParent);
-		}
-
-		// append the row to the new parent
-		newParent.appendChild(newRow);
-
-		// remove the original
-		tr_elm.parentNode.removeChild(tr_elm);
-
-		// set tr_elm to the new node
-		tr_elm = newRow;
-	}
-}
-
-function changedBackgroundImage() {
-	var formObj = document.forms[0];
-	var st = tinyMCE.parseStyle(formObj.style.value);
-
-	st['background-image'] = "url('" + formObj.backgroundimage.value + "')";
-
-	formObj.style.value = tinyMCE.serializeStyle(st);
-}
-
-function changedStyle() {
-	var formObj = document.forms[0];
-	var st = tinyMCE.parseStyle(formObj.style.value);
-
-	if (st['background-image'])
-		formObj.backgroundimage.value = st['background-image'].replace(new RegExp("url\\('?([^']*)'?\\)", 'gi'), "$1");
-	else
-		formObj.backgroundimage.value = '';
-
-	if (st['height'])
-		formObj.height.value = trimSize(st['height']);
-
-	if (st['background-color']) {
-		formObj.bgcolor.value = st['background-color'];
-		updateColor('bgcolor_pick','bgcolor');
-	}
-}
-
-function changedSize() {
-	var formObj = document.forms[0];
-	var st = tinyMCE.parseStyle(formObj.style.value);
-
-	var height = formObj.height.value;
-	if (height != "")
-		st['height'] = getCSSSize(height);
-	else
-		st['height'] = "";
-
-	formObj.style.value = tinyMCE.serializeStyle(st);
-}
-
-function changedColor() {
-	var formObj = document.forms[0];
-	var st = tinyMCE.parseStyle(formObj.style.value);
-
-	st['background-color'] = formObj.bgcolor.value;
-
-	formObj.style.value = tinyMCE.serializeStyle(st);
-}
--- a/includes/clientside/tinymce/plugins/table/jscripts/table.js	Fri Feb 22 12:46:51 2008 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,364 +0,0 @@
-var action, orgTableWidth, orgTableHeight;
-
-function insertTable() {
-	var formObj = document.forms[0];
-	var inst = tinyMCE.selectedInstance;
-	var cols = 2, rows = 2, border = 0, cellpadding = -1, cellspacing = -1, align, width, height, className, caption;
-	var html = '', capEl;
-	var elm = tinyMCE.tableElm;
-	var cellLimit, rowLimit, colLimit;
-
-	if (!AutoValidator.validate(formObj)) {
-		alert(tinyMCE.getLang('lang_invalid_data'));
-		return false;
-	}
-
-	tinyMCEPopup.restoreSelection();
-
-	// Get form data
-	cols = formObj.elements['cols'].value;
-	rows = formObj.elements['rows'].value;
-	border = formObj.elements['border'].value != "" ? formObj.elements['border'].value  : 0;
-	cellpadding = formObj.elements['cellpadding'].value != "" ? formObj.elements['cellpadding'].value : "";
-	cellspacing = formObj.elements['cellspacing'].value != "" ? formObj.elements['cellspacing'].value : "";
-	align = formObj.elements['align'].options[formObj.elements['align'].selectedIndex].value;
-	width = formObj.elements['width'].value;
-	height = formObj.elements['height'].value;
-	bordercolor = formObj.elements['bordercolor'].value;
-	bgcolor = formObj.elements['bgcolor'].value;
-	className = formObj.elements['class'].options[formObj.elements['class'].selectedIndex].value;
-	id = formObj.elements['id'].value;
-	summary = formObj.elements['summary'].value;
-	style = formObj.elements['style'].value;
-	dir = formObj.elements['dir'].value;
-	lang = formObj.elements['lang'].value;
-	background = formObj.elements['backgroundimage'].value;
-	caption = formObj.elements['caption'].checked;
-
-	cellLimit = tinyMCE.getParam('table_cell_limit', false);
-	rowLimit = tinyMCE.getParam('table_row_limit', false);
-	colLimit = tinyMCE.getParam('table_col_limit', false);
-
-	// Validate table size
-	if (colLimit && cols > colLimit) {
-		alert(tinyMCE.getLang('lang_table_col_limit', '', true, {cols : colLimit}));
-		return false;
-	} else if (rowLimit && rows > rowLimit) {
-		alert(tinyMCE.getLang('lang_table_row_limit', '', true, {rows : rowLimit}));
-		return false;
-	} else if (cellLimit && cols * rows > cellLimit) {
-		alert(tinyMCE.getLang('lang_table_cell_limit', '', true, {cells : cellLimit}));
-		return false;
-	}
-
-	// Update table
-	if (action == "update") {
-		inst.execCommand('mceBeginUndoLevel');
-
-		tinyMCE.setAttrib(elm, 'cellPadding', cellpadding, true);
-		tinyMCE.setAttrib(elm, 'cellSpacing', cellspacing, true);
-		tinyMCE.setAttrib(elm, 'border', border, true);
-		tinyMCE.setAttrib(elm, 'align', align);
-		tinyMCE.setAttrib(elm, 'class', className);
-		tinyMCE.setAttrib(elm, 'style', style);
-		tinyMCE.setAttrib(elm, 'id', id);
-		tinyMCE.setAttrib(elm, 'summary', summary);
-		tinyMCE.setAttrib(elm, 'dir', dir);
-		tinyMCE.setAttrib(elm, 'lang', lang);
-
-		capEl = elm.getElementsByTagName('caption')[0];
-
-		if (capEl && !caption)
-			capEl.parentNode.removeChild(capEl);
-
-		if (!capEl && caption) {
-			capEl = elm.ownerDocument.createElement('caption');
-			capEl.innerHTML = '&nbsp;';
-			elm.insertBefore(capEl, elm.firstChild);
-		}
-
-		// Not inline styles
-		if (!tinyMCE.getParam("inline_styles"))
-			tinyMCE.setAttrib(elm, 'width', width, true);
-
-		// Remove these since they are not valid XHTML
-		tinyMCE.setAttrib(elm, 'borderColor', '');
-		tinyMCE.setAttrib(elm, 'bgColor', '');
-		tinyMCE.setAttrib(elm, 'background', '');
-		tinyMCE.setAttrib(elm, 'height', '');
-
-		if (background != '')
-			elm.style.backgroundImage = "url('" + background + "')";
-		else
-			elm.style.backgroundImage = '';
-
-		if (tinyMCE.getParam("inline_styles"))
-			elm.style.borderWidth = border + "px";
-
-		if (tinyMCE.getParam("inline_styles")) {
-			if (width != '')
-				elm.style.width = getCSSSize(width);
-		}
-
-		if (bordercolor != "") {
-			elm.style.borderColor = bordercolor;
-			elm.style.borderStyle = elm.style.borderStyle == "" ? "solid" : elm.style.borderStyle;
-			elm.style.borderWidth = border == "" ? "1px" : border;
-		} else
-			elm.style.borderColor = '';
-
-		elm.style.backgroundColor = bgcolor;
-		elm.style.height = getCSSSize(height);
-
-		tinyMCE.handleVisualAid(tinyMCE.tableElm, false, inst.visualAid, inst);
-
-		// Fix for stange MSIE align bug
-		tinyMCE.tableElm.outerHTML = tinyMCE.tableElm.outerHTML;
-
-		tinyMCE.handleVisualAid(inst.getBody(), true, inst.visualAid, inst);
-		tinyMCE.triggerNodeChange();
-		inst.execCommand('mceEndUndoLevel');
-
-		// Repaint if dimensions changed
-		if (formObj.width.value != orgTableWidth || formObj.height.value != orgTableHeight)
-			inst.repaint();
-
-		tinyMCEPopup.close();
-		return true;
-	}
-
-	// Create new table
-	html += '<table';
-
-	html += makeAttrib('id', id);
-	html += makeAttrib('border', border);
-	html += makeAttrib('cellpadding', cellpadding);
-	html += makeAttrib('cellspacing', cellspacing);
-	html += makeAttrib('width', width);
-	//html += makeAttrib('height', height);
-	//html += makeAttrib('bordercolor', bordercolor);
-	//html += makeAttrib('bgcolor', bgcolor);
-	html += makeAttrib('align', align);
-	html += makeAttrib('class', tinyMCE.getVisualAidClass(className, border == 0));
-	html += makeAttrib('style', style);
-	html += makeAttrib('summary', summary);
-	html += makeAttrib('dir', dir);
-	html += makeAttrib('lang', lang);
-	html += '>';
-
-	if (caption)
-		html += '<caption>&nbsp;</caption>';
-
-	for (var y=0; y<rows; y++) {
-		html += "<tr>";
-
-		for (var x=0; x<cols; x++)
-			html += '<td>&nbsp;</td>';
-
-		html += "</tr>";
-	}
-
-	html += "</table>";
-
-	inst.execCommand('mceBeginUndoLevel');
-	inst.execCommand('mceInsertContent', false, html);
-	tinyMCE.handleVisualAid(inst.getBody(), true, tinyMCE.settings['visual']);
-	inst.execCommand('mceEndUndoLevel');
-
-	tinyMCEPopup.close();
-}
-
-function makeAttrib(attrib, value) {
-	var formObj = document.forms[0];
-	var valueElm = formObj.elements[attrib];
-
-	if (typeof(value) == "undefined" || value == null) {
-		value = "";
-
-		if (valueElm)
-			value = valueElm.value;
-	}
-
-	if (value == "")
-		return "";
-
-	// XML encode it
-	value = value.replace(/&/g, '&amp;');
-	value = value.replace(/\"/g, '&quot;');
-	value = value.replace(/</g, '&lt;');
-	value = value.replace(/>/g, '&gt;');
-
-	return ' ' + attrib + '="' + value + '"';
-}
-
-function init() {
-	tinyMCEPopup.resizeToInnerSize();
-
-	document.getElementById('backgroundimagebrowsercontainer').innerHTML = getBrowserHTML('backgroundimagebrowser','backgroundimage','image','table');
-	document.getElementById('backgroundimagebrowsercontainer').innerHTML = getBrowserHTML('backgroundimagebrowser','backgroundimage','image','table');
-	document.getElementById('bordercolor_pickcontainer').innerHTML = getColorPickerHTML('bordercolor_pick','bordercolor');
-	document.getElementById('bgcolor_pickcontainer').innerHTML = getColorPickerHTML('bgcolor_pick','bgcolor');
-
-	var cols = 2, rows = 2, border = tinyMCE.getParam('table_default_border', '0'), cellpadding = tinyMCE.getParam('table_default_cellpadding', ''), cellspacing = tinyMCE.getParam('table_default_cellspacing', '');
-	var align = "", width = "", height = "", bordercolor = "", bgcolor = "", className = "";
-	var id = "", summary = "", style = "", dir = "", lang = "", background = "", bgcolor = "", bordercolor = "";
-	var inst = tinyMCE.selectedInstance;
-	var formObj = document.forms[0];
-	var elm = tinyMCE.getParentElement(inst.getFocusElement(), "table");
-
-	tinyMCE.tableElm = elm;
-	action = tinyMCE.getWindowArg('action');
-	if (action == null)
-		action = tinyMCE.tableElm ? "update" : "insert";
-
-	if (tinyMCE.tableElm && action != "insert") {
-		var rowsAr = tinyMCE.tableElm.rows;
-		var cols = 0;
-		for (var i=0; i<rowsAr.length; i++)
-			if (rowsAr[i].cells.length > cols)
-				cols = rowsAr[i].cells.length;
-
-		cols = cols;
-		rows = rowsAr.length;
-
-		st = tinyMCE.parseStyle(tinyMCE.getAttrib(tinyMCE.tableElm, "style"));
-		border = trimSize(getStyle(elm, 'border', 'borderWidth'));
-		cellpadding = tinyMCE.getAttrib(tinyMCE.tableElm, 'cellpadding', "");
-		cellspacing = tinyMCE.getAttrib(tinyMCE.tableElm, 'cellspacing', "");
-		width = trimSize(getStyle(elm, 'width', 'width'));
-		height = trimSize(getStyle(elm, 'height', 'height'));
-		bordercolor = convertRGBToHex(getStyle(elm, 'bordercolor', 'borderLeftColor'));
-		bgcolor = convertRGBToHex(getStyle(elm, 'bgcolor', 'backgroundColor'));
-		align = tinyMCE.getAttrib(tinyMCE.tableElm, 'align', align);
-		className = tinyMCE.getVisualAidClass(tinyMCE.getAttrib(tinyMCE.tableElm, 'class'), false);
-		id = tinyMCE.getAttrib(tinyMCE.tableElm, 'id');
-		summary = tinyMCE.getAttrib(tinyMCE.tableElm, 'summary');
-		style = tinyMCE.serializeStyle(st);
-		dir = tinyMCE.getAttrib(tinyMCE.tableElm, 'dir');
-		lang = tinyMCE.getAttrib(tinyMCE.tableElm, 'lang');
-		background = getStyle(elm, 'background', 'backgroundImage').replace(new RegExp("url\\('?([^']*)'?\\)", 'gi'), "$1");
-		formObj.caption.checked = tinyMCE.tableElm.getElementsByTagName('caption').length > 0;
-
-		orgTableWidth = width;
-		orgTableHeight = height;
-
-		action = "update";
-	}
-
-	addClassesToList('class', "table_styles");
-
-	// Update form
-	selectByValue(formObj, 'align', align);
-	selectByValue(formObj, 'class', className);
-	formObj.cols.value = cols;
-	formObj.rows.value = rows;
-	formObj.border.value = border;
-	formObj.cellpadding.value = cellpadding;
-	formObj.cellspacing.value = cellspacing;
-	formObj.width.value = width;
-	formObj.height.value = height;
-	formObj.bordercolor.value = bordercolor;
-	formObj.bgcolor.value = bgcolor;
-	formObj.id.value = id;
-	formObj.summary.value = summary;
-	formObj.style.value = style;
-	formObj.dir.value = dir;
-	formObj.lang.value = lang;
-	formObj.backgroundimage.value = background;
-	formObj.insert.value = tinyMCE.getLang('lang_' + action, 'Insert', true); 
-
-	updateColor('bordercolor_pick', 'bordercolor');
-	updateColor('bgcolor_pick', 'bgcolor');
-
-	// Resize some elements
-	if (isVisible('backgroundimagebrowser'))
-		document.getElementById('backgroundimage').style.width = '180px';
-
-	// Disable some fields in update mode
-	if (action == "update") {
-		formObj.cols.disabled = true;
-		formObj.rows.disabled = true;
-	}
-}
-
-function changedSize() {
-	var formObj = document.forms[0];
-	var st = tinyMCE.parseStyle(formObj.style.value);
-
-	var width = formObj.width.value;
-	if (width != "")
-		st['width'] = tinyMCE.getParam("inline_styles") ? getCSSSize(width) : "";
-	else
-		st['width'] = "";
-
-	var height = formObj.height.value;
-	if (height != "")
-		st['height'] = getCSSSize(height);
-	else
-		st['height'] = "";
-
-	formObj.style.value = tinyMCE.serializeStyle(st);
-}
-
-function changedBackgroundImage() {
-	var formObj = document.forms[0];
-	var st = tinyMCE.parseStyle(formObj.style.value);
-
-	st['background-image'] = "url('" + formObj.backgroundimage.value + "')";
-
-	formObj.style.value = tinyMCE.serializeStyle(st);
-}
-
-function changedBorder() {
-	var formObj = document.forms[0];
-	var st = tinyMCE.parseStyle(formObj.style.value);
-
-	// Update border width if the element has a color
-	if (formObj.border.value != "" && formObj.bordercolor.value != "")
-		st['border-width'] = formObj.border.value + "px";
-
-	formObj.style.value = tinyMCE.serializeStyle(st);
-}
-
-function changedColor() {
-	var formObj = document.forms[0];
-	var st = tinyMCE.parseStyle(formObj.style.value);
-
-	st['background-color'] = formObj.bgcolor.value;
-
-	if (formObj.bordercolor.value != "") {
-		st['border-color'] = formObj.bordercolor.value;
-
-		// Add border-width if it's missing
-		if (!st['border-width'])
-			st['border-width'] = formObj.border.value == "" ? "1px" : formObj.border.value + "px";
-	}
-
-	formObj.style.value = tinyMCE.serializeStyle(st);
-}
-
-function changedStyle() {
-	var formObj = document.forms[0];
-	var st = tinyMCE.parseStyle(formObj.style.value);
-
-	if (st['background-image'])
-		formObj.backgroundimage.value = st['background-image'].replace(new RegExp("url\\('?([^']*)'?\\)", 'gi'), "$1");
-	else
-		formObj.backgroundimage.value = '';
-
-	if (st['width'])
-		formObj.width.value = trimSize(st['width']);
-
-	if (st['height'])
-		formObj.height.value = trimSize(st['height']);
-
-	if (st['background-color']) {
-		formObj.bgcolor.value = st['background-color'];
-		updateColor('bgcolor_pick','bgcolor');
-	}
-
-	if (st['border-color']) {
-		formObj.bordercolor.value = st['border-color'];
-		updateColor('bordercolor_pick','bordercolor');
-	}
-}
--- a/includes/clientside/tinymce/plugins/table/langs/en.js	Fri Feb 22 12:46:51 2008 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,79 +0,0 @@
-// UK lang variables
-
-tinyMCE.addToLang('table',{
-general_tab : 'General',
-advanced_tab : 'Advanced',
-general_props : 'General properties',
-advanced_props : 'Advanced properties',
-desc : 'Inserts a new table',
-row_before_desc : 'Insert row before',
-row_after_desc : 'Insert row after',
-delete_row_desc : 'Delete row',
-col_before_desc : 'Insert column before',
-col_after_desc : 'Insert column after',
-delete_col_desc : 'Remove column',
-rowtype : 'Row in table part',
-title : 'Insert/Modify table',
-width : 'Width',
-height : 'Height',
-cols : 'Columns',
-rows : 'Rows',
-cellspacing : 'Cellspacing',
-cellpadding : 'Cellpadding',
-border : 'Border',
-align : 'Alignment',
-align_default : 'Default',
-align_left : 'Left',
-align_right : 'Right',
-align_middle : 'Center',
-row_title : 'Table row properties',
-cell_title : 'Table cell properties',
-cell_type : 'Cell type',
-row_desc : 'Table row properties',
-cell_desc : 'Table cell properties',
-valign : 'Vertical alignment',
-align_top : 'Top',
-align_bottom : 'Bottom',
-props_desc : 'Table properties',
-bordercolor : 'Border color',
-bgcolor : 'Background color',
-merge_cells_title : 'Merge table cells',
-split_cells_desc : 'Split table cells',
-merge_cells_desc : 'Merge table cells',
-cut_row_desc : 'Cut table row',
-copy_row_desc : 'Copy table row',
-paste_row_before_desc : 'Paste table row before',
-paste_row_after_desc : 'Paste table row after',
-id : 'Id',
-style: 'Style',
-langdir : 'Language direction',
-langcode : 'Language code',
-mime : 'Target MIME type',
-ltr : 'Left to right',
-rtl : 'Right to left',
-bgimage : 'Background image',
-summary : 'Summary',
-td : "Data",
-th : "Header",
-cell_cell : 'Update current cell',
-cell_row : 'Update all cells in row',
-cell_all : 'Update all cells in table',
-row_row : 'Update current row',
-row_odd : 'Update odd rows in table',
-row_even : 'Update even rows in table',
-row_all : 'Update all rows in table',
-thead : 'Table Head',
-tbody : 'Table Body',
-tfoot : 'Table Foot',
-del : 'Delete table',
-scope : 'Scope',
-row : 'Row',
-col : 'Col',
-rowgroup : 'Row Group',
-colgroup : 'Col Group',
-col_limit : 'You\'ve exceeded the maximum number of columns of {$cols}.',
-row_limit : 'You\'ve exceeded the maximum number of rows of {$rows}.',
-cell_limit : 'You\'ve exceeded the maximum number of cells of {$cells}.',
-missing_scope: 'Are you sure you want to continue without specifying a scope for this table header cell. Without it, it may be difficult for some users with disabilities to understand the content or data displayed of the table.',
-caption : 'Table caption'
-});
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/includes/clientside/tinymce/plugins/table/langs/en_dlg.js	Fri Feb 22 12:51:53 2008 -0500
@@ -0,0 +1,74 @@
+tinyMCE.addI18n('en.table_dlg',{
+general_tab:"General",
+advanced_tab:"Advanced",
+general_props:"General properties",
+advanced_props:"Advanced properties",
+rowtype:"Row in table part",
+title:"Insert/Modify table",
+width:"Width",
+height:"Height",
+cols:"Cols",
+rows:"Rows",
+cellspacing:"Cellspacing",
+cellpadding:"Cellpadding",
+border:"Border",
+align:"Alignment",
+align_default:"Default",
+align_left:"Left",
+align_right:"Right",
+align_middle:"Center",
+row_title:"Table row properties",
+cell_title:"Table cell properties",
+cell_type:"Cell type",
+valign:"Vertical alignment",
+align_top:"Top",
+align_bottom:"Bottom",
+bordercolor:"Border color",
+bgcolor:"Background color",
+merge_cells_title:"Merge table cells",
+id:"Id",
+style:"Style",
+langdir:"Language direction",
+langcode:"Language code",
+mime:"Target MIME type",
+ltr:"Left to right",
+rtl:"Right to left",
+bgimage:"Background image",
+summary:"Summary",
+td:"Data",
+th:"Header",
+cell_cell:"Update current cell",
+cell_row:"Update all cells in row",
+cell_all:"Update all cells in table",
+row_row:"Update current row",
+row_odd:"Update odd rows in table",
+row_even:"Update even rows in table",
+row_all:"Update all rows in table",
+thead:"Table Head",
+tbody:"Table Body",
+tfoot:"Table Foot",
+scope:"Scope",
+rowgroup:"Row Group",
+colgroup:"Col Group",
+col_limit:"You've exceeded the maximum number of columns of {$cols}.",
+row_limit:"You've exceeded the maximum number of rows of {$rows}.",
+cell_limit:"You've exceeded the maximum number of cells of {$cells}.",
+missing_scope:"Are you sure you want to continue without specifying a scope for this table header cell. Without it, it may be difficult for some users with disabilities to understand the content or data displayed of the table.",
+caption:"Table caption",
+frame:"Frame",
+frame_none:"none",
+frame_groups:"groups",
+frame_rows:"rows",
+frame_cols:"cols",
+frame_all:"all",
+rules:"Rules",
+rules_void:"void",
+rules_above:"above",
+rules_below:"below",
+rules_hsides:"hsides",
+rules_lhs:"lhs",
+rules_rhs:"rhs",
+rules_vsides:"vsides",
+rules_box:"box",
+rules_border:"border"
+});
\ No newline at end of file
--- a/includes/clientside/tinymce/plugins/table/merge_cells.htm	Fri Feb 22 12:46:51 2008 -0500
+++ b/includes/clientside/tinymce/plugins/table/merge_cells.htm	Fri Feb 22 12:51:53 2008 -0500
@@ -1,24 +1,24 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
 <html xmlns="http://www.w3.org/1999/xhtml">
 <head>
-	<title>{$lang_table_merge_cells_title}</title>
-	<script language="javascript" type="text/javascript" src="../../tiny_mce_popup.js"></script>
-	<script language="javascript" type="text/javascript" src="../../utils/mctabs.js"></script>
-	<script language="javascript" type="text/javascript" src="../../utils/validate.js"></script>
-	<script language="javascript" type="text/javascript" src="jscripts/merge_cells.js"></script>
+	<title>{#table_dlg.merge_cells_title}</title>
+	<script type="text/javascript" src="../../tiny_mce_popup.js"></script>
+	<script type="text/javascript" src="../../utils/mctabs.js"></script>
+	<script type="text/javascript" src="../../utils/validate.js"></script>
+	<script type="text/javascript" src="js/merge_cells.js"></script>
 	<base target="_self" />
 </head>
-<body onload="tinyMCEPopup.executeOnLoad('init();');" style="margin: 8px" style="display: none">
+<body style="margin: 8px" style="display: none">
 <form onsubmit="insertTable();return false;" action="#">
 	<fieldset>
-		<legend>{$lang_table_merge_cells_title}</legend>
+		<legend>{#table_dlg.merge_cells_title}</legend>
 		  <table border="0" cellpadding="0" cellspacing="3" width="100%">
 			  <tr>
-				<td>{$lang_table_cols}:</td>
+				<td>{#table_dlg.cols}:</td>
 				<td align="right"><input type="text" name="numcols" value="" class="number min1" style="width: 30px" /></td>
-				<td>
 			  </tr>
 			  <tr>
-				<td>{$lang_table_rows}:</td>
+				<td>{#table_dlg.rows}:</td>
 				<td align="right"><input type="text" name="numrows" value="" class="number min1" style="width: 30px" /></td>
 			  </tr>
 		  </table>
@@ -26,11 +26,11 @@
 
 	<div class="mceActionPanel">
 		<div style="float: left">
-			<input type="button" id="insert" name="insert" value="{$lang_update}" onclick="mergeCells();" />
+			<input type="button" id="insert" name="insert" value="{#update}" onclick="mergeCells();" />
 		</div>
 
 		<div style="float: right">
-			<input type="button" id="cancel" name="cancel" value="{$lang_cancel}" onclick="tinyMCEPopup.close();" />
+			<input type="button" id="cancel" name="cancel" value="{#cancel}" onclick="tinyMCEPopup.close();" />
 		</div>
 	</div>
 </form>
--- a/includes/clientside/tinymce/plugins/table/readme.txt	Fri Feb 22 12:46:51 2008 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1 +0,0 @@
-Check the TinyMCE documentation for details on this plugin.
--- a/includes/clientside/tinymce/plugins/table/row.htm	Fri Feb 22 12:46:51 2008 -0500
+++ b/includes/clientside/tinymce/plugins/table/row.htm	Fri Feb 22 12:51:53 2008 -0500
@@ -1,74 +1,75 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
 <html xmlns="http://www.w3.org/1999/xhtml">
 <head>
-	<title>{$lang_table_row_title}</title>
-	<script language="javascript" type="text/javascript" src="../../tiny_mce_popup.js"></script>
-	<script language="javascript" type="text/javascript" src="../../utils/mctabs.js"></script>
-	<script language="javascript" type="text/javascript" src="../../utils/form_utils.js"></script>
-	<script language="javascript" type="text/javascript" src="jscripts/row.js"></script>
+	<title>{#table_dlg.row_title}</title>
+	<script type="text/javascript" src="../../tiny_mce_popup.js"></script>
+	<script type="text/javascript" src="../../utils/mctabs.js"></script>
+	<script type="text/javascript" src="../../utils/form_utils.js"></script>
+	<script type="text/javascript" src="js/row.js"></script>
 	<link href="css/row.css" rel="stylesheet" type="text/css" />
 	<base target="_self" />
 </head>
-<body id="tablerow" onload="tinyMCEPopup.executeOnLoad('init();');" style="display: none">
+<body id="tablerow" style="display: none">
 	<form onsubmit="updateAction();return false;">
 		<div class="tabs">
 			<ul>
-				<li id="general_tab" class="current"><span><a href="javascript:mcTabs.displayTab('general_tab','general_panel');" onmousedown="return false;">{$lang_table_general_tab}</a></span></li>
-				<li id="advanced_tab"><span><a href="javascript:mcTabs.displayTab('advanced_tab','advanced_panel');" onmousedown="return false;">{$lang_table_advanced_tab}</a></span></li>
+				<li id="general_tab" class="current"><span><a href="javascript:mcTabs.displayTab('general_tab','general_panel');" onmousedown="return false;">{#table_dlg.general_tab}</a></span></li>
+				<li id="advanced_tab"><span><a href="javascript:mcTabs.displayTab('advanced_tab','advanced_panel');" onmousedown="return false;">{#table_dlg.advanced_tab}</a></span></li>
 			</ul>
 		</div>
 
 		<div class="panel_wrapper">
 			<div id="general_panel" class="panel current">
 				<fieldset>
-					<legend>{$lang_table_general_props}</legend>
+					<legend>{#table_dlg.general_props}</legend>
 
 					<table border="0" cellpadding="4" cellspacing="0">
 						<tr>
-							<td><label for="rowtype">{$lang_table_rowtype}</label></td>
+							<td><label for="rowtype">{#table_dlg.rowtype}</label></td>
 							<td class="col2">
 								<select id="rowtype" name="rowtype">
-									<option value="thead">{$lang_table_thead}</option>
-									<option value="tbody">{$lang_table_tbody}</option>
-									<option value="tfoot">{$lang_table_tfoot}</option>
+									<option value="thead">{#table_dlg.thead}</option>
+									<option value="tbody">{#table_dlg.tbody}</option>
+									<option value="tfoot">{#table_dlg.tfoot}</option>
 								</select>
 							</td>
 						</tr>
 
 						<tr>
-							<td><label for="align">{$lang_table_align}</label></td>
+							<td><label for="align">{#table_dlg.align}</label></td>
 							<td class="col2">
 								<select id="align" name="align">
-									<option value="">{$lang_not_set}</option>
-									<option value="center">{$lang_table_align_middle}</option>
-									<option value="left">{$lang_table_align_left}</option>
-									<option value="right">{$lang_table_align_right}</option>
+									<option value="">{#not_set}</option>
+									<option value="center">{#table_dlg.align_middle}</option>
+									<option value="left">{#table_dlg.align_left}</option>
+									<option value="right">{#table_dlg.align_right}</option>
 								</select>
 							</td>
 						</tr>
 
 						<tr>
-							<td><label for="valign">{$lang_table_valign}</label></td>
+							<td><label for="valign">{#table_dlg.valign}</label></td>
 							<td class="col2">
 								<select id="valign" name="valign">
-									<option value="">{$lang_not_set}</option>
-									<option value="top">{$lang_table_align_top}</option>
-									<option value="middle">{$lang_table_align_middle}</option>
-									<option value="bottom">{$lang_table_align_bottom}</option>
+									<option value="">{#not_set}</option>
+									<option value="top">{#table_dlg.align_top}</option>
+									<option value="middle">{#table_dlg.align_middle}</option>
+									<option value="bottom">{#table_dlg.align_bottom}</option>
 								</select>
 							</td>
 						</tr>
 
 						<tr id="styleSelectRow">
-							<td><label for="class">{$lang_class_name}</label></td>
+							<td><label for="class">{#class_name}</label></td>
 							<td class="col2">
 								<select id="class" name="class">
-									<option value="" selected="selected">{$lang_not_set}</option>
+									<option value="" selected="selected">{#not_set}</option>
 								</select>
 							</td>
 						</tr>
 
 						<tr>
-							<td><label for="height">{$lang_table_height}</label></td>
+							<td><label for="height">{#table_dlg.height}</label></td>
 							<td class="col2"><input name="height" type="text" id="height" value="" size="4" maxlength="4" onchange="changedSize();" /></td>
 						</tr>
 					</table>
@@ -77,39 +78,39 @@
 
 			<div id="advanced_panel" class="panel">
 				<fieldset>
-					<legend>{$lang_table_advanced_props}</legend>
+					<legend>{#table_dlg.advanced_props}</legend>
 
 					<table border="0" cellpadding="0" cellspacing="4">
 						<tr>
-							<td class="column1"><label for="id">{$lang_table_id}</label></td> 
+							<td class="column1"><label for="id">{#table_dlg.id}</label></td> 
 							<td><input id="id" name="id" type="text" value="" style="width: 200px" /></td> 
 						</tr>
 
 						<tr>
-							<td><label for="style">{$lang_table_style}</label></td>
+							<td><label for="style">{#table_dlg.style}</label></td>
 							<td><input type="text" id="style" name="style" value="" style="width: 200px;" onchange="changedStyle();" /></td>
 						</tr>
 
 						<tr>
-							<td class="column1"><label for="dir">{$lang_table_langdir}</label></td> 
+							<td class="column1"><label for="dir">{#table_dlg.langdir}</label></td> 
 							<td>
 								<select id="dir" name="dir" style="width: 200px"> 
-										<option value="">{$lang_not_set}</option> 
-										<option value="ltr">{$lang_table_ltr}</option> 
-										<option value="rtl">{$lang_table_rtl}</option> 
+										<option value="">{#not_set}</option> 
+										<option value="ltr">{#table_dlg.ltr}</option> 
+										<option value="rtl">{#table_dlg.rtl}</option> 
 								</select>
 							</td> 
 						</tr>
 
 						<tr>
-							<td class="column1"><label for="lang">{$lang_table_langcode}</label></td> 
+							<td class="column1"><label for="lang">{#table_dlg.langcode}</label></td> 
 							<td>
 								<input id="lang" name="lang" type="text" value="" style="width: 200px" />
 							</td> 
 						</tr>
 
 						<tr>
-							<td class="column1"><label for="backgroundimage">{$lang_table_bgimage}</label></td> 
+							<td class="column1"><label for="backgroundimage">{#table_dlg.bgimage}</label></td> 
 							<td>
 								<table border="0" cellpadding="0" cellspacing="0">
 									<tr>
@@ -121,7 +122,7 @@
 						</tr>
 
 						<tr>
-							<td class="column1"><label for="bgcolor">{$lang_table_bgcolor}</label></td> 
+							<td class="column1"><label for="bgcolor">{#table_dlg.bgcolor}</label></td> 
 							<td>
 								<table border="0" cellpadding="0" cellspacing="0">
 									<tr>
@@ -139,19 +140,19 @@
 		<div class="mceActionPanel">
 			<div>
 				<select id="action" name="action">
-					<option value="row">{$lang_table_row_row}</option>
-					<option value="odd">{$lang_table_row_odd}</option>
-					<option value="even">{$lang_table_row_even}</option>
-					<option value="all">{$lang_table_row_all}</option>
+					<option value="row">{#table_dlg.row_row}</option>
+					<option value="odd">{#table_dlg.row_odd}</option>
+					<option value="even">{#table_dlg.row_even}</option>
+					<option value="all">{#table_dlg.row_all}</option>
 				</select>
 			</div>
 
 			<div style="float: left">
-				<div><input type="button" id="insert" name="insert" value="{$lang_update}" onclick="updateAction();" /></div>
+				<div><input type="button" id="insert" name="insert" value="{#update}" onclick="updateAction();" /></div>
 			</div>
 
 			<div style="float: right">
-				<input type="button" id="cancel" name="cancel" value="{$lang_cancel}" onclick="tinyMCEPopup.close();" />
+				<input type="button" id="cancel" name="cancel" value="{#cancel}" onclick="tinyMCEPopup.close();" />
 			</div>
 		</div>
 	</form>
--- a/includes/clientside/tinymce/plugins/table/table.htm	Fri Feb 22 12:46:51 2008 -0500
+++ b/includes/clientside/tinymce/plugins/table/table.htm	Fri Feb 22 12:51:53 2008 -0500
@@ -1,68 +1,68 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
 <html xmlns="http://www.w3.org/1999/xhtml">
 <head>
-	<title>{$lang_table_title}</title>
-	<script language="javascript" type="text/javascript" src="../../tiny_mce_popup.js"></script>
-	<script language="javascript" type="text/javascript" src="../../utils/mctabs.js"></script>
-	<script language="javascript" type="text/javascript" src="../../utils/form_utils.js"></script>
-	<script language="javascript" type="text/javascript" src="../../utils/validate.js"></script>
-	<script language="javascript" type="text/javascript" src="jscripts/table.js"></script>
+	<title>{#table_dlg.title}</title>
+	<script type="text/javascript" src="../../tiny_mce_popup.js"></script>
+	<script type="text/javascript" src="../../utils/mctabs.js"></script>
+	<script type="text/javascript" src="../../utils/form_utils.js"></script>
+	<script type="text/javascript" src="../../utils/validate.js"></script>
+	<script type="text/javascript" src="js/table.js"></script>
 	<link href="css/table.css" rel="stylesheet" type="text/css" />
 	<base target="_self" />
 </head>
-<body id="table" onload="tinyMCEPopup.executeOnLoad('init();');" style="display: none">
+<body id="table" style="display: none">
 	<form onsubmit="insertTable();return false;" action="#">
 		<div class="tabs">
 			<ul>
-				<li id="general_tab" class="current"><span><a href="javascript:mcTabs.displayTab('general_tab','general_panel');" onmousedown="return false;">{$lang_table_general_tab}</a></span></li>
-				<li id="advanced_tab"><span><a href="javascript:mcTabs.displayTab('advanced_tab','advanced_panel');" onmousedown="return false;">{$lang_table_advanced_tab}</a></span></li>
+				<li id="general_tab" class="current"><span><a href="javascript:mcTabs.displayTab('general_tab','general_panel');" onmousedown="return false;">{#table_dlg.general_tab}</a></span></li>
+				<li id="advanced_tab"><span><a href="javascript:mcTabs.displayTab('advanced_tab','advanced_panel');" onmousedown="return false;">{#table_dlg.advanced_tab}</a></span></li>
 			</ul>
 		</div>
 
 		<div class="panel_wrapper">
 			<div id="general_panel" class="panel current">
 				<fieldset>
-					<legend>{$lang_table_general_props}</legend>
-
+					<legend>{#table_dlg.general_props}</legend>
 					  <table border="0" cellpadding="4" cellspacing="0" width="100%">
 							  <tr>
-								<td><label id="colslabel" for="cols">{$lang_table_cols}</label></td>
+								<td><label id="colslabel" for="cols">{#table_dlg.cols}</label></td>
 								<td><input id="cols" name="cols" type="text" value="" size="3" maxlength="3" class="required number min1" /></td>
-								<td><label id="rowslabel" for="rows">{$lang_table_rows}</label></td>
+								<td><label id="rowslabel" for="rows">{#table_dlg.rows}</label></td>
 								<td><input id="rows" name="rows" type="text" value="" size="3" maxlength="3" class="required number min1" /></td>
 							  </tr>
 							  <tr>
-								<td><label id="cellpaddinglabel" for="cellpadding">{$lang_table_cellpadding}</label></td>
+								<td><label id="cellpaddinglabel" for="cellpadding">{#table_dlg.cellpadding}</label></td>
 								<td><input id="cellpadding" name="cellpadding" type="text" value="" size="3" maxlength="3" class="number" /></td>
-								<td><label id="cellspacinglabel" for="cellspacing">{$lang_table_cellspacing}</label></td>
+								<td><label id="cellspacinglabel" for="cellspacing">{#table_dlg.cellspacing}</label></td>
 								<td><input id="cellspacing" name="cellspacing" type="text" value="" size="3" maxlength="3" class="number" /></td>
 							  </tr>
 							  <tr>
-								<td><label id="alignlabel" for="align">{$lang_table_align}</label></td>
+								<td><label id="alignlabel" for="align">{#table_dlg.align}</label></td>
 								<td><select id="align" name="align">
-									<option value="">{$lang_not_set}</option>
-									<option value="center">{$lang_table_align_middle}</option>
-									<option value="left">{$lang_table_align_left}</option>
-									<option value="right">{$lang_table_align_right}</option>
+									<option value="">{#not_set}</option>
+									<option value="center">{#table_dlg.align_middle}</option>
+									<option value="left">{#table_dlg.align_left}</option>
+									<option value="right">{#table_dlg.align_right}</option>
 								  </select></td>
-								<td><label id="borderlabel" for="border">{$lang_table_border}</label></td>
+								<td><label id="borderlabel" for="border">{#table_dlg.border}</label></td>
 								<td><input id="border" name="border" type="text" value="" size="3" maxlength="3" onchange="changedBorder();" class="number" /></td>
 							  </tr>
 							  <tr id="width_row">
-								<td><label id="widthlabel" for="width">{$lang_table_width}</label></td>
+								<td><label id="widthlabel" for="width">{#table_dlg.width}</label></td>
 								<td><input name="width" type="text" id="width" value="" size="4" maxlength="4" onchange="changedSize();" class="size" /></td>
-								<td><label id="heightlabel" for="height">{$lang_table_height}</label></td>
+								<td><label id="heightlabel" for="height">{#table_dlg.height}</label></td>
 								<td><input name="height" type="text" id="height" value="" size="4" maxlength="4" onchange="changedSize();" class="size" /></td>
 							  </tr>
 							  <tr id="styleSelectRow">
-								<td><label id="classlabel" for="class">{$lang_class_name}</label></td>
+								<td><label id="classlabel" for="class">{#class_name}</label></td>
 								<td colspan="3">
 								 <select id="class" name="class">
-									<option value="" selected>{$lang_not_set}</option>
+									<option value="" selected>{#not_set}</option>
 								 </select></td>
 							  </tr>
 							  <tr>
-								<td class="column1"><label for="caption">{$lang_table_caption}</label></td> 
-								<td><input id="caption" name="caption" type="checkbox" value="true" /></td> 
+								<td class="column1"><label for="caption">{#table_dlg.caption}</label></td> 
+								<td><input id="caption" name="caption" type="checkbox" class="checkbox" value="true" /></td> 
 							  </tr>
 							</table>
 				</fieldset>
@@ -70,44 +70,33 @@
 
 			<div id="advanced_panel" class="panel">
 				<fieldset>
-					<legend>{$lang_table_advanced_props}</legend>
+					<legend>{#table_dlg.advanced_props}</legend>
 
 					<table border="0" cellpadding="0" cellspacing="4">
 						<tr>
-							<td class="column1"><label for="id">{$lang_table_id}</label></td> 
+							<td class="column1"><label for="id">{#table_dlg.id}</label></td> 
 							<td><input id="id" name="id" type="text" value="" class="advfield" /></td> 
 						</tr>
 
 						<tr>
-							<td class="column1"><label for="summary">{$lang_table_summary}</label></td> 
+							<td class="column1"><label for="summary">{#table_dlg.summary}</label></td> 
 							<td><input id="summary" name="summary" type="text" value="" class="advfield" /></td> 
 						</tr>
 
 						<tr>
-							<td><label for="style">{$lang_table_style}</label></td>
+							<td><label for="style">{#table_dlg.style}</label></td>
 							<td><input type="text" id="style" name="style" value="" class="advfield" onchange="changedStyle();" /></td>
 						</tr>
 
 						<tr>
-							<td class="column1"><label for="dir">{$lang_table_langdir}</label></td> 
-							<td>
-								<select id="dir" name="dir" class="advfield"> 
-										<option value="">{$lang_not_set}</option> 
-										<option value="ltr">{$lang_table_ltr}</option> 
-										<option value="rtl">{$lang_table_rtl}</option> 
-								</select>
-							</td> 
-						</tr>
-
-						<tr>
-							<td class="column1"><label id="langlabel" for="lang">{$lang_table_langcode}</label></td> 
+							<td class="column1"><label id="langlabel" for="lang">{#table_dlg.langcode}</label></td> 
 							<td>
 								<input id="lang" name="lang" type="text" value="" class="advfield" />
 							</td> 
 						</tr>
 
 						<tr>
-							<td class="column1"><label for="backgroundimage">{$lang_table_bgimage}</label></td> 
+							<td class="column1"><label for="backgroundimage">{#table_dlg.bgimage}</label></td> 
 							<td>
 								<table border="0" cellpadding="0" cellspacing="0">
 									<tr>
@@ -119,7 +108,50 @@
 						</tr>
 
 						<tr>
-							<td class="column1"><label for="bordercolor">{$lang_table_bordercolor}</label></td> 
+							<td class="column1"><label for="frame">{#table_dlg.frame}</label></td> 
+							<td>
+								<select id="frame" name="frame" class="advfield"> 
+										<option value="">{#not_set}</option> 
+										<option value="none">{#table_dlg.frame_none}</option>
+										<option value="groups">{#table_dlg.frame_groups}</option>
+										<option value="rows">{#table_dlg.frame_rows}</option>
+										<option value="cols">{#table_dlg.frame_cols}</option>
+										<option value="all">{#table_dlg.frame_all}</option>
+								</select>
+							</td> 
+						</tr>
+
+						<tr>
+							<td class="column1"><label for="rules">{#table_dlg.rules}</label></td> 
+							<td>
+								<select id="rules" name="rules" class="advfield"> 
+										<option value="">{#not_set}</option> 
+										<option value="void">{#table_dlg.rules_void}</option>
+										<option value="above">{#table_dlg.rules_above}</option> 
+										<option value="below">{#table_dlg.rules_below}</option> 
+										<option value="hsides">{#table_dlg.rules_hsides}</option> 
+										<option value="lhs">{#table_dlg.rules_lhs}</option> 
+										<option value="rhs">{#table_dlg.rules_rhs}</option> 
+										<option value="vsides">{#table_dlg.rules_vsides}</option> 
+										<option value="box">{#table_dlg.rules_box}</option> 
+										<option value="border">{#table_dlg.rules_border}</option> 
+									</select>
+							</td> 
+						</tr>
+
+						<tr>
+							<td class="column1"><label for="dir">{#table_dlg.langdir}</label></td> 
+							<td>
+								<select id="dir" name="dir" class="advfield"> 
+										<option value="">{#not_set}</option> 
+										<option value="ltr">{#table_dlg.ltr}</option> 
+										<option value="rtl">{#table_dlg.rtl}</option> 
+								</select>
+							</td> 
+						</tr>
+
+						<tr>
+							<td class="column1"><label for="bordercolor">{#table_dlg.bordercolor}</label></td> 
 							<td>
 								<table border="0" cellpadding="0" cellspacing="0">
 									<tr>
@@ -131,7 +163,7 @@
 						</tr>
 
 						<tr>
-							<td class="column1"><label for="bgcolor">{$lang_table_bgcolor}</label></td> 
+							<td class="column1"><label for="bgcolor">{#table_dlg.bgcolor}</label></td> 
 							<td>
 								<table border="0" cellpadding="0" cellspacing="0">
 									<tr>
@@ -148,11 +180,11 @@
 
 		<div class="mceActionPanel">
 			<div style="float: left">
-				<input type="button" id="insert" name="insert" value="{$lang_insert}" onclick="insertTable();" />
+				<input type="button" id="insert" name="insert" value="{#insert}" onclick="insertTable();" />
 			</div>
 
 			<div style="float: right">
-				<input type="button" id="cancel" name="cancel" value="{$lang_cancel}" onclick="tinyMCEPopup.close();" />
+				<input type="button" id="cancel" name="cancel" value="{#cancel}" onclick="tinyMCEPopup.close();" />
 			</div>
 		</div>
 	</form>
--- a/includes/clientside/tinymce/plugins/template/blank.htm	Fri Feb 22 12:46:51 2008 -0500
+++ b/includes/clientside/tinymce/plugins/template/blank.htm	Fri Feb 22 12:51:53 2008 -0500
@@ -3,21 +3,10 @@
 	<title>blank_page</title>
 	<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
 	<script type="text/javascript">
-		var tinyMCE = parent.tinyMCE, css = tinyMCE.getParam("content_css").split(','), i, u;
-
-		// Load content CSS files
-		for (i=0; i<css.length; i++) {
-			u = css[i];
-
-			// Fix relative
-			if (u.charAt(0) != '/' && u.indexOf('://') == -1)
-				u = tinyMCE.documentBasePath + "/" + u;
-
-			document.write('<link href="' + u + '" rel="stylesheet" type="text/css" />');
-		}
+		parent.TemplateDialog.loadCSSFiles(document);
 	</script>
 </head>
-<body id="mceTemplatePreview">
+<body id="mceTemplatePreview" class="mceContentBody">
 
 </body>
 </html>
--- a/includes/clientside/tinymce/plugins/template/editor_plugin.js	Fri Feb 22 12:46:51 2008 -0500
+++ b/includes/clientside/tinymce/plugins/template/editor_plugin.js	Fri Feb 22 12:51:53 2008 -0500
@@ -1,1 +1,1 @@
-tinyMCE.importPluginLanguagePack('template');var TinyMCE_TemplatePlugin={getInfo:function(){return{longname:'Template plugin',author:'Moxiecode Systems AB',authorurl:'http://www.moxiecode.com',infourl:'http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/template',version:tinyMCE.majorVersion+"."+tinyMCE.minorVersion}},initInstance:function(inst){var cdate,mdate,content,x=0,key,value,rvals,ds=inst.getData('template');cdate=tinyMCE.getParam("template_cdate_classes",'').split(/\s+/);mdate=tinyMCE.getParam("template_mdate_classes",'').split(/\s+/);content=tinyMCE.getParam("template_selected_content_classes",'').split(/\s+/);for(x=0;x<cdate.length;x++)TinyMCE_TemplatePlugin.functions[cdate[x]]=TinyMCE_TemplatePlugin.functions['cdate'];for(x=0;x<mdate.length;x++)TinyMCE_TemplatePlugin.functions[mdate[x]]=TinyMCE_TemplatePlugin.functions['mdate'];for(x=0;x<content.length;x++)TinyMCE_TemplatePlugin.functions[content[x]]=TinyMCE_TemplatePlugin.functions['selectedContent'];rvals=tinyMCE.getParam("template_replace_values",false);for(key in rvals){value=rvals[key];if(typeof value=="function")TinyMCE_TemplatePlugin.functions[key]=value;else TinyMCE_TemplatePlugin.functions[key]=TinyMCE_TemplatePlugin.functions['generateReplacer'](value)}rvals=tinyMCE.getParam("template_replace_values",false);ds.replace_items={};for(key in rvals)ds.replace_items[key]=rvals[key];inst.addShortcut('ctrl','t','lang_template_desc','mceTemplate');ds.currentAction="insert";ds.currentTmplNode=null},getControlHTML:function(cn){switch(cn){case"template":return tinyMCE.getButtonHTML(cn,'lang_template_desc','{$pluginurl}/images/template.gif','mceTemplate',true)}return""},execCommand:function(editor_id,element,command,user_interface,value){var nodeArray,current,newTmpl,x,inst=tinyMCE.getInstanceById(editor_id),ds=inst.getData('template'),telm;switch(command){case"mceTemplate":if(user_interface){tinyMCE.openWindow({file:'../../plugins/template/template.htm',width:tinyMCE.getParam('template_popup_width',750),height:tinyMCE.getParam('template_popup_height',600)},{editor_id:editor_id,resizable:"yes",scrollbars:"no",pluginObj:TinyMCE_TemplatePlugin})}else{telm=TinyMCE_TemplatePlugin._convertToNode(value.body);nodeArray=tinyMCE.selectElements(telm,'div',function(n){return tinyMCE.hasCSSClass(n,TinyMCE_TemplatePlugin.TMPL)});telm=nodeArray.length>0?nodeArray[0]:null;nodeArray=[];if(ds.currentAction=="insert"){if(telm){tinyMCE.execCommand('mceBeginUndoLevel');ds.currentAction="insert-new";TinyMCE_TemplatePlugin._insertTemplate(editor_id,telm,value.title,value.tsrc,true);ds.currentAction=="insert";tinyMCE.execCommand('mceEndUndoLevel');tinyMCE.execInstanceCommand(editor_id,'mceCleanup',false)}else tinyMCE.execCommand('mceInsertContent',false,this._replaceValues(value.body))}else{nodeArray=TinyMCE_TemplatePlugin._collectTemplateElements(ds.currentTmplNode);current=[];newTmpl=[];tinyMCE.getNodeTree(telm,newTmpl);for(x=0;x<nodeArray.length;x++)tinyMCE.getNodeTree(nodeArray[x],current);var _test=function(elm){var replaced=true;if(elm.className){var names=elm.className.split(/\s+/),c,n;for(c=0;c<names.length;c++){if(names[c].match(/^mce/i))continue;for(n=0;n<newTmpl.length;n++){replaced=false;if(newTmpl[n].className&&newTmpl[n].className.match(new RegExp(names[c],"gi"))){newTmpl[n].innerHTML=elm.innerHTML;replaced=true;break}}}}return replaced};var cont=true;var asked=false;for(x=0;x<current.length;x++){if(!_test(current[x])){cont=(asked||confirm("The new template has less elements than the currently selected content.\nIf you proceed you will loose content.\nAre you sure you want to proceed?","Proceed?"));asked=true;if(!cont)break}};if(cont){tinyMCE.execCommand('mceBeginUndoLevel');TinyMCE_TemplatePlugin._replaceTemplateContent(current[0],editor_id,telm,value.title,value.tsrc);tinyMCE.execCommand('mceEndUndoLevel');tinyMCE.execInstanceCommand(editor_id,'mceCleanup',false)}}tinyMCE.triggerNodeChange(true)}return true}return false},handleNodeChange:function(editor_id,node,undo_index,undo_levels,visual_aid,any_selection){var inst=tinyMCE.getInstanceById(editor_id),ds=inst.getData('template');if(tinyMCE.hasCSSClass(node,TinyMCE_TemplatePlugin.TMPL_ELEMENT)||tinyMCE.hasCSSClass(node.parentNode,TinyMCE_TemplatePlugin.TMPL_ELEMENT)){tinyMCE.switchClass(editor_id+'_template','mceButtonSelected');ds.currentAction="update";ds.currentTmplNode=node;return true}ds.currentAction="insert";ds.currentTmplNode=null;tinyMCE.switchClass(editor_id+'_template','mceButtonNormal');return false},cleanup:function(type,content,inst){var nodes=[];switch(type){case"get_from_editor":content=content.replace(new RegExp('<div class="'+TinyMCE_TemplatePlugin.TMPL+'">','gi'),'<!-- '+TinyMCE_TemplatePlugin.TMPL_BEGINS+' -->');content=content.replace(new RegExp('<div class="'+TinyMCE_TemplatePlugin.TMPL+'">(\s|&nbsp;|&#160;)?(<!-- '+TinyMCE_TemplatePlugin.TMPL_ENDS+' -->|\s)?</div>','gi'),'');content=content.replace(new RegExp('<!-- '+TinyMCE_TemplatePlugin.TMPL_ENDS+' --></div>','gi'),'<!-- '+TinyMCE_TemplatePlugin.TMPL_ENDS+' -->');break;case"insert_to_editor":content=content.replace(new RegExp('<!-- '+TinyMCE_TemplatePlugin.TMPL_BEGINS+' -->','gi'),'<div class="'+TinyMCE_TemplatePlugin.TMPL+'">');content=content.replace(new RegExp('<!-- '+TinyMCE_TemplatePlugin.TMPL_ENDS+' -->','gi'),'<!-- '+TinyMCE_TemplatePlugin.TMPL_ENDS+' --></div>');break;case"get_from_editor_dom":nodes=tinyMCE.selectNodes(content,function(n){return tinyMCE.hasCSSClass(n,TinyMCE_TemplatePlugin.TMPL_ELEMENT)});TinyMCE_TemplatePlugin._applyFunctions(nodes,type);break;case"insert_to_editor_dom":nodes=tinyMCE.selectNodes(content,function(n){return tinyMCE.hasCSSClass(n,TinyMCE_TemplatePlugin.TMPL_ELEMENT)});TinyMCE_TemplatePlugin._applyFunctions(nodes,type);break}return content},_convertToNode:function(html){var elm=document.createElement('div');elm.innerHTML=html;return elm},_prepareTemplateContent:function(elms){var x,n,nodes=[];if(!elms)return{};if(!elms.length)elms=[elms];for(x=0;x<elms.length;x++)tinyMCE.getNodeTree(elms[x],nodes,1);for(n=0;n<nodes.length;n++){tinyMCE.addCSSClass(nodes[n],TinyMCE_TemplatePlugin.TMPL_ELEMENT);TinyMCE_TemplatePlugin._applyFunctions(nodes[n],TinyMCE_TemplatePlugin.TMPL_TEMPLATE_EVENT)}return elms},_replaceValues:function(s){var t=this,ds=tinyMCE.selectedInstance.getData('template');return s.replace(/\{\$([^\}]+)\}/g,function(a,b){var it=ds.replace_items[b];if(it){if(typeof(it)!='function')return it}return b})},_applyFunctions:function(elms,editor_event){var x,elm,names,c,f;if(!elms)return{};if(!elms.length)elms=[elms];for(x=0;x<elms.length;x++){elm=elms[x];if(elm.className){names=elm.className.split(/\s+/);for(c=0;c<names.length;c++){if(names[c]==TinyMCE_TemplatePlugin.TMPL_ELEMENT)continue;f=(TinyMCE_TemplatePlugin.functions[names[c]]?TinyMCE_TemplatePlugin.functions[names[c]]:TinyMCE_TemplatePlugin.functions['blank']);f(elm,editor_event)}}}return elms},_collectTemplateElements:function(node){var nodeArray=[],p;p=tinyMCE.getParentElement(node,'DIV',function(n){return tinyMCE.hasCSSClass(n,TinyMCE_TemplatePlugin.TMPL)});if(p)tinyMCE.getNodeTree(p,nodeArray);return nodeArray},_replaceTemplateContent:function(currentNode,editor_id,newTemplate,title,tsrc){TinyMCE_TemplatePlugin._deleteTemplateContent(currentNode);TinyMCE_TemplatePlugin._insertTemplate(editor_id,newTemplate,title,tsrc,false)},_deleteTemplateContent:function(node){var p=tinyMCE.getParentElement(node,'DIV',function(n){return tinyMCE.hasCSSClass(n,TinyMCE_TemplatePlugin.TMPL)});if(p)p.parentNode.removeChild(p,true)},_insertTemplate:function(editor_id,elm,title,tsrc,incComments){var html;TinyMCE_TemplatePlugin._prepareTemplateContent(elm);html='<div class="'+TinyMCE_TemplatePlugin.TMPL+'">';html+=elm.innerHTML;html+='<!-- '+TinyMCE_TemplatePlugin.TMPL_ENDS+' --></div>';tinyMCE.execInstanceCommand(editor_id,'mceInsertContent',false,html)},functions:{blank:function(elm,editor_event){},cdate:function(elm,editor_event){var d,dsrc;if(editor_event!=TinyMCE_TemplatePlugin.TMPL_TEMPLATE_EVENT)return;d=new Date();dsrc=elm.innerHTML.match(new RegExp("<!-- "+TinyMCE_TemplatePlugin.TMPL_DATE_SRC_ATTR+":(.*)  -->","gi"));if(dsrc)d=new Date(RegExp.$1);elm.innerHTML=TinyMCE_TemplatePlugin._getDateTime(d,tinyMCE.getParam("template_cdate_format",tinyMCE.getLang("lang_template_def_date_format")));elm.innerHTML+="<!-- "+TinyMCE_TemplatePlugin.TMPL_DATE_SRC_ATTR+":"+d.toUTCString()+"  -->"},mdate:function(elm,editor_event){var d=new Date();elm.innerHTML=TinyMCE_TemplatePlugin._getDateTime(d,tinyMCE.getParam("template_mdate_format",tinyMCE.getLang("lang_template_def_date_format")))},selectedContent:function(elm,editor_event){var ds=tinyMCE.selectedInstance.getData('template');if(editor_event!=TinyMCE_TemplatePlugin.TMPL_TEMPLATE_EVENT)return;if(ds.currentAction=="insert-new"&&!tinyMCE.hasCSSClass(elm,TinyMCE_TemplatePlugin.TMPL_SEL_HTML_DONE)){elm.innerHTML=tinyMCE.selectedInstance.selection.getSelectedHTML();tinyMCE.addCSSClass(elm,TinyMCE_TemplatePlugin.TMPL_SEL_HTML_DONE)}},generateReplacer:function(s){return function(elm,editor_event){elm.innerHTML=""+s}}},_getDateTime:function(d,fmt){if(!fmt)return"";function addZeros(value,len){var i;value=""+value;if(value.length<len){for(i=0;i<(len-value.length);i++)value="0"+value}return value}fmt=fmt.replace("%D","%m/%d/%y");fmt=fmt.replace("%r","%I:%M:%S %p");fmt=fmt.replace("%Y",""+d.getFullYear());fmt=fmt.replace("%y",""+d.getYear());fmt=fmt.replace("%m",addZeros(d.getMonth()+1,2));fmt=fmt.replace("%d",addZeros(d.getDate(),2));fmt=fmt.replace("%H",""+addZeros(d.getHours(),2));fmt=fmt.replace("%M",""+addZeros(d.getMinutes(),2));fmt=fmt.replace("%S",""+addZeros(d.getSeconds(),2));fmt=fmt.replace("%I",""+((d.getHours()+11)%12+1));fmt=fmt.replace("%p",""+(d.getHours()<12?"AM":"PM"));fmt=fmt.replace("%B",""+tinyMCE.getLang("lang_template_months_long")[d.getMonth()]);fmt=fmt.replace("%b",""+tinyMCE.getLang("lang_template_months_short")[d.getMonth()]);fmt=fmt.replace("%A",""+tinyMCE.getLang("lang_template_day_long")[d.getDay()]);fmt=fmt.replace("%a",""+tinyMCE.getLang("lang_template_day_short")[d.getDay()]);fmt=fmt.replace("%%","%");return fmt},TMPL_ELEMENT:'mceTmplElm',TMPL:'mceTmpl',TMPL_BEGINS:'mceTmplBegins',TMPL_SEL_HTML_DONE:'mceSelHTMLDone',TMPL_ENDS:'mceTmplEnds',TMPL_DATE_SRC_ATTR:'mcetmpldtesrc',TMPL_TEMPLATE_EVENT:'prepare_template'};tinyMCE.addPlugin("template",TinyMCE_TemplatePlugin);
\ No newline at end of file
+(function(){var each=tinymce.each;tinymce.create('tinymce.plugins.TemplatePlugin',{init:function(ed,url){var t=this;t.editor=ed;ed.addCommand('mceTemplate',function(ui){ed.windowManager.open({file:url+'/template.htm',width:ed.getParam('template_popup_width',750),height:ed.getParam('template_popup_height',600),inline:1},{plugin_url:url});});ed.addCommand('mceInsertTemplate',t._insertTemplate,t);ed.addButton('template',{title:'template.desc',cmd:'mceTemplate'});ed.onPreProcess.add(function(ed,o){var dom=ed.dom;each(dom.select('div',o.node),function(e){if(dom.hasClass(e,'mceTmpl')){each(dom.select('*',e),function(e){if(dom.hasClass(e,ed.getParam('template_mdate_classes').replace(/\s+/g,'|')))e.innerHTML=t._getDateTime(new Date(),ed.getParam("template_mdate_format",ed.getLang("template.mdate_format")));});t._replaceVals(e);}});});},getInfo:function(){return{longname:'Template plugin',author:'Moxiecode Systems AB',authorurl:'http://www.moxiecode.com',infourl:'http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/template',version:tinymce.majorVersion+"."+tinymce.minorVersion};},_insertTemplate:function(ui,v){var t=this,ed=t.editor,h,el,dom=ed.dom,sel=ed.selection.getContent();h=v.content;each(t.editor.getParam('template_replace_values'),function(v,k){if(typeof(v)!='function')h=h.replace(new RegExp('\\{\\$'+k+'\\}','g'),v);});el=dom.create('div',null,h);function hasClass(n,c){return new RegExp('\\b'+c+'\\b','g').test(n.className);};each(dom.select('*',el),function(n){if(hasClass(n,ed.getParam('template_cdate_classes','cdate').replace(/\s+/g,'|')))n.innerHTML=t._getDateTime(new Date(),ed.getParam("template_cdate_format",ed.getLang("template.cdate_format")));if(hasClass(n,ed.getParam('template_mdate_classes','mdate').replace(/\s+/g,'|')))n.innerHTML=t._getDateTime(new Date(),ed.getParam("template_mdate_format",ed.getLang("template.mdate_format")));if(hasClass(n,ed.getParam('template_selected_content_classes','selcontent').replace(/\s+/g,'|')))n.innerHTML=sel;});t._replaceVals(el);ed.execCommand('mceInsertContent',false,el.innerHTML);ed.addVisual();},_replaceVals:function(e){var dom=this.editor.dom,vl=this.editor.getParam('template_replace_values');each(dom.select('*',e),function(e){each(vl,function(v,k){if(dom.hasClass(e,k)){if(typeof(vl[k])=='function')vl[k](e);}});});},_getDateTime:function(d,fmt){if(!fmt)return"";function addZeros(value,len){var i;value=""+value;if(value.length<len){for(i=0;i<(len-value.length);i++)value="0"+value;}return value;}fmt=fmt.replace("%D","%m/%d/%y");fmt=fmt.replace("%r","%I:%M:%S %p");fmt=fmt.replace("%Y",""+d.getFullYear());fmt=fmt.replace("%y",""+d.getYear());fmt=fmt.replace("%m",addZeros(d.getMonth()+1,2));fmt=fmt.replace("%d",addZeros(d.getDate(),2));fmt=fmt.replace("%H",""+addZeros(d.getHours(),2));fmt=fmt.replace("%M",""+addZeros(d.getMinutes(),2));fmt=fmt.replace("%S",""+addZeros(d.getSeconds(),2));fmt=fmt.replace("%I",""+((d.getHours()+11)%12+1));fmt=fmt.replace("%p",""+(d.getHours()<12?"AM":"PM"));fmt=fmt.replace("%B",""+tinyMCE.getLang("template_months_long").split(',')[d.getMonth()]);fmt=fmt.replace("%b",""+tinyMCE.getLang("template_months_short").split(',')[d.getMonth()]);fmt=fmt.replace("%A",""+tinyMCE.getLang("template_day_long").split(',')[d.getDay()]);fmt=fmt.replace("%a",""+tinyMCE.getLang("template_day_short").split(',')[d.getDay()]);fmt=fmt.replace("%%","%");return fmt;}});tinymce.PluginManager.add('template',tinymce.plugins.TemplatePlugin);})();
\ No newline at end of file
--- a/includes/clientside/tinymce/plugins/template/editor_plugin_src.js	Fri Feb 22 12:46:51 2008 -0500
+++ b/includes/clientside/tinymce/plugins/template/editor_plugin_src.js	Fri Feb 22 12:51:53 2008 -0500
@@ -1,551 +1,149 @@
 /**
- * $Id: editor_plugin_src.js 162 2007-01-03 16:16:52Z spocke $
+ * $Id: editor_plugin_src.js 201 2007-02-12 15:56:56Z spocke $
  *
  * @author Moxiecode
- * @copyright Copyright © 2004-2007, Moxiecode Systems AB, All rights reserved.
+ * @copyright Copyright © 2004-2008, Moxiecode Systems AB, All rights reserved.
  */
 
-tinyMCE.importPluginLanguagePack('template');
+(function() {
+	var each = tinymce.each;
 
-var TinyMCE_TemplatePlugin = {
-	getInfo : function() {
-		return {
-			longname : 'Template plugin',
-			author : 'Moxiecode Systems AB',
-			authorurl : 'http://www.moxiecode.com',
-			infourl : 'http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/template',
-			version : tinyMCE.majorVersion + "." + tinyMCE.minorVersion
-		};
-	},
+	tinymce.create('tinymce.plugins.TemplatePlugin', {
+		init : function(ed, url) {
+			var t = this;
 
-	initInstance : function(inst) {
-		var cdate, mdate, content, x = 0, key, value, rvals, ds = inst.getData('template');
-
-		// ensure the required elements and sttributes are added
-		//inst.cleanup.addRuleStr('*[' + TinyMCE_TemplatePlugin.TMPL_DATE_SRC_ATTR + '],div[title,tsrc]');
+			t.editor = ed;
 
-		//setup template content functions
-		// creation date and modified date classes
-		cdate = tinyMCE.getParam("template_cdate_classes", '').split(/\s+/);
-		mdate = tinyMCE.getParam("template_mdate_classes", '').split(/\s+/);
-
-		// classes that specify where selected content should go
-		content = tinyMCE.getParam("template_selected_content_classes", '').split(/\s+/);
-
-		for (x = 0; x < cdate.length; x++)
-			TinyMCE_TemplatePlugin.functions[cdate[x]] = TinyMCE_TemplatePlugin.functions['cdate'];	
+			// Register commands
+			ed.addCommand('mceTemplate', function(ui) {
+				ed.windowManager.open({
+					file : url + '/template.htm',
+					width : ed.getParam('template_popup_width', 750),
+					height : ed.getParam('template_popup_height', 600),
+					inline : 1
+				}, {
+					plugin_url : url
+				});
+			});
 
-		for (x = 0; x < mdate.length; x++)
-			TinyMCE_TemplatePlugin.functions[mdate[x]] = TinyMCE_TemplatePlugin.functions['mdate'];
+			ed.addCommand('mceInsertTemplate', t._insertTemplate, t);
 
-		for (x = 0; x < content.length; x++)
-			TinyMCE_TemplatePlugin.functions[content[x]] = TinyMCE_TemplatePlugin.functions['selectedContent'];
-
-		// special template functions for replacing template content
-		rvals = tinyMCE.getParam("template_replace_values", false);
-		for (key in rvals) {
-			value = rvals[key];
+			// Register buttons
+			ed.addButton('template', {title : 'template.desc', cmd : 'mceTemplate'});
 
-			if (typeof value == "function")
-				TinyMCE_TemplatePlugin.functions[key] = value;
-			else
-				TinyMCE_TemplatePlugin.functions[key] = TinyMCE_TemplatePlugin.functions['generateReplacer'](value);
-		}
-
-		// Setup replace_items
-		rvals = tinyMCE.getParam("template_replace_values", false);
-		ds.replace_items = {};
+			ed.onPreProcess.add(function(ed, o) {
+				var dom = ed.dom;
 
-		for (key in rvals)
-			ds.replace_items[key] = rvals[key];
-
-		inst.addShortcut('ctrl', 't', 'lang_template_desc', 'mceTemplate');
-
-		// Setup data storage
-		ds.currentAction = "insert";
-		ds.currentTmplNode = null;
-	},
+				each(dom.select('div', o.node), function(e) {
+					if (dom.hasClass(e, 'mceTmpl')) {
+						each(dom.select('*', e), function(e) {
+							if (dom.hasClass(e, ed.getParam('template_mdate_classes').replace(/\s+/g, '|')))
+								e.innerHTML = t._getDateTime(new Date(), ed.getParam("template_mdate_format", ed.getLang("template.mdate_format")));
+						});
 
-	getControlHTML : function(cn) {
-		switch (cn) {
-			case "template":
-				return tinyMCE.getButtonHTML(cn, 'lang_template_desc', '{$pluginurl}/images/template.gif', 'mceTemplate', true);
-		}
-
-		return "";
-	},
-
-	execCommand : function(editor_id, element, command, user_interface, value) {
-		var nodeArray, current, newTmpl, x, inst = tinyMCE.getInstanceById(editor_id), ds = inst.getData('template'), telm;
+						t._replaceVals(e);
+					}
+				});
+			});
+		},
 
-		switch (command) {
-			case "mceTemplate":
-				if (user_interface) {
-					// called from toolbar button - show the popup
-					tinyMCE.openWindow({
-						file : '../../plugins/template/template.htm', // Relative to theme
-						width : tinyMCE.getParam('template_popup_width', 750),
-						height : tinyMCE.getParam('template_popup_height', 600)
-					}, {editor_id : editor_id, resizable : "yes", scrollbars : "no", pluginObj : TinyMCE_TemplatePlugin});
-				} else {
-					// internal command do the template stuff
+		getInfo : function() {
+			return {
+				longname : 'Template plugin',
+				author : 'Moxiecode Systems AB',
+				authorurl : 'http://www.moxiecode.com',
+				infourl : 'http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/template',
+				version : tinymce.majorVersion + "." + tinymce.minorVersion
+			};
+		},
 
-					// get the returned HTML string from the pop-up and appened it to a DIV element
-					telm = TinyMCE_TemplatePlugin._convertToNode(value.body);
+		_insertTemplate : function(ui, v) {
+			var t = this, ed = t.editor, h, el, dom = ed.dom, sel = ed.selection.getContent();
+
+			h = v.content;
 
-					// Find template body
-					nodeArray = tinyMCE.selectElements(telm, 'div', function(n) {
-						return tinyMCE.hasCSSClass(n, TinyMCE_TemplatePlugin.TMPL);
-					});
+			each(t.editor.getParam('template_replace_values'), function(v, k) {
+				if (typeof(v) != 'function')
+					h = h.replace(new RegExp('\\{\\$' + k + '\\}', 'g'), v);
+			});
 
-					telm = nodeArray.length > 0 ? nodeArray[0] : null;
-					nodeArray = [];
+			el = dom.create('div', null, h);
 
-					if (ds.currentAction == "insert") {
-						//insert new template after applying all the template content functions
+			function hasClass(n, c) {
+				return new RegExp('\\b' + c + '\\b', 'g').test(n.className);
+			};
 
-						// Is it a template or snippet
-						if (telm) {
-							tinyMCE.execCommand('mceBeginUndoLevel');
-							ds.currentAction = "insert-new";
-							TinyMCE_TemplatePlugin._insertTemplate(editor_id, telm, value.title, value.tsrc, true);
-							ds.currentAction == "insert";
-							tinyMCE.execCommand('mceEndUndoLevel');
-							tinyMCE.execInstanceCommand(editor_id, 'mceCleanup', false);
-						} else
-							tinyMCE.execCommand('mceInsertContent', false, this._replaceValues(value.body));
-					} else {
-						// First collect the selected template in the editor
-						nodeArray = TinyMCE_TemplatePlugin._collectTemplateElements(ds.currentTmplNode);
-						current = [];
-						newTmpl = [];
-						tinyMCE.getNodeTree(telm, newTmpl);
+			each(dom.select('*', el), function(n) {
+				// Replace cdate
+				if (hasClass(n, ed.getParam('template_cdate_classes', 'cdate').replace(/\s+/g, '|')))
+					n.innerHTML = t._getDateTime(new Date(), ed.getParam("template_cdate_format", ed.getLang("template.cdate_format")));
 
-						for (x=0; x<nodeArray.length; x++)
-							tinyMCE.getNodeTree(nodeArray[x], current);
+				// Replace mdate
+				if (hasClass(n, ed.getParam('template_mdate_classes', 'mdate').replace(/\s+/g, '|')))
+					n.innerHTML = t._getDateTime(new Date(), ed.getParam("template_mdate_format", ed.getLang("template.mdate_format")));
 
-						/** 
-						 * inner function used in the loop below.
-						 * compares the supplied HTML element to the new template to:
-						 * - find a match with the new template and copy the element's content over
-						 * - find no match and indicate content will be lost
-						 */
-						var _test = function(elm) {
-							var replaced = true;
+				// Replace selection
+				if (hasClass(n, ed.getParam('template_selected_content_classes', 'selcontent').replace(/\s+/g, '|')))
+					n.innerHTML = sel;
+			});
 
-							if (elm.className) {
-								var names = elm.className.split(/\s+/), c, n;
+			t._replaceVals(el);
 
-								for (c = 0; c<names.length; c++) {
-									if (names[c].match(/^mce/i))
-										continue; // ignore all internal class names
-
-									for (n=0; n<newTmpl.length; n++){
-										replaced = false;
+			ed.execCommand('mceInsertContent', false, el.innerHTML);
+			ed.addVisual();
+		},
 
-										if (newTmpl[n].className && newTmpl[n].className.match(new RegExp(names[c], "gi"))) {
-											newTmpl[n].innerHTML = elm.innerHTML;
-											//if(tinyMCE.getAttrib(elm,TinyMCE_TemplatePlugin.TMPL_DATE_SRC_ATTR,"") != "") {
-											//	tinyMCE.setAttrib(newTmpl[n], TinyMCE_TemplatePlugin.TMPL_DATE_SRC_ATTR, tinyMCE.getAttrib(elm,TinyMCE_TemplatePlugin.TMPL_DATE_SRC_ATTR)); 
-											//}
-											replaced = true;
-											break;
-										}
+		_replaceVals : function(e) {
+			var dom = this.editor.dom, vl = this.editor.getParam('template_replace_values');
 
-									}
-								}
-							}
-	
-							return replaced;
-						};
-
-						// comparison loop - first mis-match alerts user for confirmation.
-						var cont = true;
-						var asked = false;
+			each(dom.select('*', e), function(e) {
+				each(vl, function(v, k) {
+					if (dom.hasClass(e, k)) {
+						if (typeof(vl[k]) == 'function')
+							vl[k](e);
+					}
+				});
+			});
+		},
 
-						for (x = 0; x < current.length; x++) {
-							if(!_test(current[x])) {
-								cont = (asked || confirm("The new template has less elements than the currently selected content.\nIf you proceed you will loose content.\nAre you sure you want to proceed?", "Proceed?"));
-								asked = true;
+		_getDateTime : function(d, fmt) {
+				if (!fmt)
+					return "";
 
-								if (!cont)
-									break;
-							}
-						};
+				function addZeros(value, len) {
+					var i;
 
-						// apply replacement if allowed to
-						if (cont) {
-							tinyMCE.execCommand('mceBeginUndoLevel');
-							TinyMCE_TemplatePlugin._replaceTemplateContent(current[0], editor_id, telm, value.title, value.tsrc);
-							tinyMCE.execCommand('mceEndUndoLevel');
-							tinyMCE.execInstanceCommand(editor_id, 'mceCleanup', false);
-						}
+					value = "" + value;
+
+					if (value.length < len) {
+						for (i=0; i<(len-value.length); i++)
+							value = "0" + value;
 					}
 
-					tinyMCE.triggerNodeChange(true);
+					return value;
 				}
 
-				return true;
-		}
-
-		return false;
-	},
-
-	handleNodeChange : function(editor_id, node, undo_index, undo_levels, visual_aid, any_selection) {
-		var inst = tinyMCE.getInstanceById(editor_id), ds = inst.getData('template');
-
-		if (tinyMCE.hasCSSClass(node, TinyMCE_TemplatePlugin.TMPL_ELEMENT) || tinyMCE.hasCSSClass(node.parentNode, TinyMCE_TemplatePlugin.TMPL_ELEMENT)) {
-			tinyMCE.switchClass(editor_id + '_template', 'mceButtonSelected');
-			ds.currentAction = "update";
-			ds.currentTmplNode = node;
-
-			return true;
-		}
-
-		ds.currentAction = "insert";
-		ds.currentTmplNode = null;
-		tinyMCE.switchClass(editor_id + '_template', 'mceButtonNormal');
-
-		return false;
-	},
-
-	cleanup : function(type, content, inst) {
-		var nodes = [];
-
-		switch (type) {
-			case "get_from_editor":
-				// replace the opening wrapper div tag with a HTML comment
-				content = content.replace(
-					new RegExp('<div class="' + TinyMCE_TemplatePlugin.TMPL + '">', 'gi'),
-					'<!-- ' + TinyMCE_TemplatePlugin.TMPL_BEGINS + ' -->'
-				);
-
-				// delete any empty template wrappers
-				content = content.replace(
-					new RegExp('<div class="' + TinyMCE_TemplatePlugin.TMPL + '">(\s|&nbsp;|&#160;)?(<!-- ' + TinyMCE_TemplatePlugin.TMPL_ENDS + ' -->|\s)?</div>', 'gi'),
-					''
-				);
-
-				// replace the closing wrapper tag
-				content = content.replace(
-					new RegExp('<!-- ' + TinyMCE_TemplatePlugin.TMPL_ENDS + ' --></div>', 'gi'),
-					'<!-- ' + TinyMCE_TemplatePlugin.TMPL_ENDS + ' -->'
-				);
-
-				break;
-
-			case "insert_to_editor":
-				// replace HTML comment with DIV wrapper
-				content = content.replace(
-					new RegExp('<!-- ' + TinyMCE_TemplatePlugin.TMPL_BEGINS + ' -->', 'gi'),
-					'<div class="' + TinyMCE_TemplatePlugin.TMPL + '">'
-				);
-
-				content = content.replace(
-					new RegExp('<!-- ' + TinyMCE_TemplatePlugin.TMPL_ENDS + ' -->', 'gi'),
-					'<!-- ' + TinyMCE_TemplatePlugin.TMPL_ENDS + ' --></div>'
-				);
-
-				break;
-
-			case "get_from_editor_dom":
-				// apply template content replacement functions
-				nodes = tinyMCE.selectNodes(content, function(n) {
-						return tinyMCE.hasCSSClass(n, TinyMCE_TemplatePlugin.TMPL_ELEMENT);
-					}
-				);
-
-				TinyMCE_TemplatePlugin._applyFunctions(nodes, type);
-
-				break;
-
-			case "insert_to_editor_dom":
-				// apply template content replacement functions
-				nodes = tinyMCE.selectNodes(content, function(n) {
-						return tinyMCE.hasCSSClass(n, TinyMCE_TemplatePlugin.TMPL_ELEMENT);
-					}
-				);
-
-				TinyMCE_TemplatePlugin._applyFunctions(nodes, type);
-
-				break;
-		}
-
-		return content;
-	},
-
-	// Private plugin internal methods
-
-	/**
-	 * Creates a HTML DIV element and sets the innerHTML to equal the temlate innerHTML so that the template can be manipulated as DOM nodes.
-	 *
-	 * @param {string} Template innerHTML
-	 * @return a HTML Element
-	 * @type HTMLElement
-	 */
-	_convertToNode : function(html) {
-		var elm = document.createElement('div');
-
-		elm.innerHTML = html;
-
-		return elm;
-	},
-
-	/**
-	 * pass an array of template html elements and they will have the template class name added and any template functions applied
-	 *
-	 * @param {array} template HTML elements
-	 * @return array of template HTML elements
-	 * @type array
-	 */
-	_prepareTemplateContent : function(elms) {
-		var x, n, nodes = [];
-
-		if (!elms)
-			return {};
-
-		if (!elms.length)
-			elms = [elms];
-
-		for (x = 0; x<elms.length; x++)
-			tinyMCE.getNodeTree(elms[x], nodes, 1);
-
-		for (n = 0; n<nodes.length; n++) {
-			tinyMCE.addCSSClass(nodes[n], TinyMCE_TemplatePlugin.TMPL_ELEMENT);
-			TinyMCE_TemplatePlugin._applyFunctions(nodes[n], TinyMCE_TemplatePlugin.TMPL_TEMPLATE_EVENT);
-		}
-
-		return elms;
-	},
-
-	_replaceValues : function(s) {
-		var t = this, ds = tinyMCE.selectedInstance.getData('template');
-
-		return s.replace(/\{\$([^\}]+)\}/g, function(a, b) {
-			var it = ds.replace_items[b];
-
-			if (it) {
-				// Only supports text for now
-				if (typeof(it) != 'function')
-					return it;
-			}
-
-			return b;
-		});
-	},
-
-	/**
-	 * Applies any special functions to the template elements
-	 *
-	 * @param {array} template HTML elements
-	 * @return array of template HTML elements
-	 * @type array
-	 */
-	_applyFunctions : function(elms, editor_event) {
-		var x, elm, names, c, f;
-
-		if (!elms)
-			return {};
-
-		if (!elms.length)
-			elms = [elms];
-
-		for(x = 0; x < elms.length; x++) {
-			elm = elms[x];
-
-			if (elm.className){
-				names = elm.className.split(/\s+/);
-
-				for (c = 0; c < names.length; c++){
-					if (names[c] == TinyMCE_TemplatePlugin.TMPL_ELEMENT)
-						continue;
-
-					f = (TinyMCE_TemplatePlugin.functions[names[c]] ? TinyMCE_TemplatePlugin.functions[names[c]] : TinyMCE_TemplatePlugin.functions['blank']);
-					f(elm, editor_event);
-				}
-			}
-		}
+				fmt = fmt.replace("%D", "%m/%d/%y");
+				fmt = fmt.replace("%r", "%I:%M:%S %p");
+				fmt = fmt.replace("%Y", "" + d.getFullYear());
+				fmt = fmt.replace("%y", "" + d.getYear());
+				fmt = fmt.replace("%m", addZeros(d.getMonth()+1, 2));
+				fmt = fmt.replace("%d", addZeros(d.getDate(), 2));
+				fmt = fmt.replace("%H", "" + addZeros(d.getHours(), 2));
+				fmt = fmt.replace("%M", "" + addZeros(d.getMinutes(), 2));
+				fmt = fmt.replace("%S", "" + addZeros(d.getSeconds(), 2));
+				fmt = fmt.replace("%I", "" + ((d.getHours() + 11) % 12 + 1));
+				fmt = fmt.replace("%p", "" + (d.getHours() < 12 ? "AM" : "PM"));
+				fmt = fmt.replace("%B", "" + tinyMCE.getLang("template_months_long").split(',')[d.getMonth()]);
+				fmt = fmt.replace("%b", "" + tinyMCE.getLang("template_months_short").split(',')[d.getMonth()]);
+				fmt = fmt.replace("%A", "" + tinyMCE.getLang("template_day_long").split(',')[d.getDay()]);
+				fmt = fmt.replace("%a", "" + tinyMCE.getLang("template_day_short").split(',')[d.getDay()]);
+				fmt = fmt.replace("%%", "%");
 
-		return elms;
-	},
-
-	/**
-	 * Given one node reference this function will collect all the nodes of the template to which it belongs.
-	 * It does this by finding the parent template wrapper DIV and returning all child nodes.
-	 *
-	 * @param {HTMLElement} a HTMLElement which is part of a template
-	 * @return array of template HTML elements
-	 * @type array
-	 */
-	_collectTemplateElements : function(node) {
-		var nodeArray = [], p;
-
-		p = tinyMCE.getParentElement(node, 'DIV', function(n) {
-			return tinyMCE.hasCSSClass(n, TinyMCE_TemplatePlugin.TMPL);
-		});
-
-		if (p)
-			tinyMCE.getNodeTree(p, nodeArray);
-
-		return nodeArray;
-	},
-
-	/**
-	 * Simply calls TinyMCE_TemplatePlugin._deleteTemplateContent and then TinyMCE_TemplatePlugin._insertTemplate
-	 *
-	 * @param {HTMLElement} currently selected template node in editor
-	 * @param {string} id of editor instance
-	 * @param {HTMLElement} template contents as a HTMLElement (the parent DIV wrapper)
-	 * @param {string} title of template (unused as yet)
-	 * @param {string} source URI of the template file (unused as yet)
-	 * @return array of template HTML elements
-	 * @type array
-	 */
-	_replaceTemplateContent : function(currentNode, editor_id, newTemplate, title, tsrc) {
-		TinyMCE_TemplatePlugin._deleteTemplateContent(currentNode);
-		TinyMCE_TemplatePlugin._insertTemplate(editor_id, newTemplate, title, tsrc, false);
-	},
-
-	/**
-	 * Deletes a template from the editor content
-	 * Finds the parent DIV wrapper and deletes it and all children
-	 * @param {HTMLElement} currently selected template node in editor
-	 */
-	_deleteTemplateContent : function(node) {
-		var p = tinyMCE.getParentElement(node, 'DIV', function(n) {
-			return tinyMCE.hasCSSClass(n, TinyMCE_TemplatePlugin.TMPL);
-		});
-
-		if (p)
-			p.parentNode.removeChild(p, true);
-	},
-
-	/**
-	 *  Inserts a template into the specified editor
-	 *
-	 * @param {string} id of editor instance
-	 * @param {HTMLElement} template contents as a HTMLElement (the parent DIV wrapper)
-	 * @param {string} title of template (unused as yet)
-	 * @param {string} source URI of the template file (unused as yet)
-	 */
-	_insertTemplate : function(editor_id, elm, title, tsrc, incComments) {
-		var html;
-
-		TinyMCE_TemplatePlugin._prepareTemplateContent(elm);
-
-		html = '<div class="' + TinyMCE_TemplatePlugin.TMPL + '">';
-		html += elm.innerHTML;
-		html += '<!-- ' + TinyMCE_TemplatePlugin.TMPL_ENDS + ' --></div>';
-
-		tinyMCE.execInstanceCommand(editor_id, 'mceInsertContent', false, html);
-	},
-
-	/**
-	 * template functions - functions for modifying template content
-	 */
-	functions : { 
-		blank : function(elm, editor_event) {},
-
-		cdate : function(elm, editor_event) {
-			var d, dsrc;
-
-			if (editor_event != TinyMCE_TemplatePlugin.TMPL_TEMPLATE_EVENT)
-				return;
-
-			d = new Date();
-			// find out if the creation date was previously stored
-			dsrc = elm.innerHTML.match(new RegExp("<!-- " + TinyMCE_TemplatePlugin.TMPL_DATE_SRC_ATTR + ":(.*)  -->", "gi"));
+				return fmt;
+		}
+	});
 
-			if (dsrc)
-				d = new Date(RegExp.$1);
-
-			elm.innerHTML = TinyMCE_TemplatePlugin._getDateTime(d, tinyMCE.getParam("template_cdate_format", tinyMCE.getLang("lang_template_def_date_format")));
-			//now we have to store the date value in a format easily read again, in case a future template change changes the date format...
-			elm.innerHTML += "<!-- " + TinyMCE_TemplatePlugin.TMPL_DATE_SRC_ATTR + ":" + d.toUTCString() + "  -->";
-		},
-
-		mdate : function(elm, editor_event) {
-			var d = new Date();
-			elm.innerHTML = TinyMCE_TemplatePlugin._getDateTime(d, tinyMCE.getParam("template_mdate_format", tinyMCE.getLang("lang_template_def_date_format")));
-		},
-
-		/**
-		 * This will insert the currently selected editor content into the template element.
-		 * It only does this if the template inserted is a new one and if the element does not have the special class.
-		 * The special class name prevents this from happening more than once.
-		 */
-		selectedContent : function(elm, editor_event) {
-			var ds = tinyMCE.selectedInstance.getData('template');
-	
-			if (editor_event != TinyMCE_TemplatePlugin.TMPL_TEMPLATE_EVENT)
-				return;
-
-			if (ds.currentAction == "insert-new" && !tinyMCE.hasCSSClass(elm, TinyMCE_TemplatePlugin.TMPL_SEL_HTML_DONE)) {
-				elm.innerHTML = tinyMCE.selectedInstance.selection.getSelectedHTML();
-				tinyMCE.addCSSClass(elm, TinyMCE_TemplatePlugin.TMPL_SEL_HTML_DONE);
-			}
-		},
-
-		/**
-		 * When the plugin is initialised this generates the functions that insert configured strings into template elements.
-		 */
-		generateReplacer : function(s) {
-			return function(elm, editor_event) {elm.innerHTML = "" + s;};
-		}
-	},
-
-	/**
-	 * formats a date according to the format string - straight from the 'insert date/time' plugin
-	 *
-	 * @param {Date} date object
-	 * @param {string} format string
-	 * @return formatted date
-	 * @type string
-	 */
-	_getDateTime : function(d,fmt) {
-			if (!fmt)
-				return "";
-
-			function addZeros(value, len) {
-				var i;
-
-				value = "" + value;
-
-				if (value.length < len) {
-					for (i=0; i<(len-value.length); i++)
-						value = "0" + value;
-				}
-
-				return value;
-			}
-
-			fmt = fmt.replace("%D", "%m/%d/%y");
-			fmt = fmt.replace("%r", "%I:%M:%S %p");
-			fmt = fmt.replace("%Y", "" + d.getFullYear());
-			fmt = fmt.replace("%y", "" + d.getYear());
-			fmt = fmt.replace("%m", addZeros(d.getMonth()+1, 2));
-			fmt = fmt.replace("%d", addZeros(d.getDate(), 2));
-			fmt = fmt.replace("%H", "" + addZeros(d.getHours(), 2));
-			fmt = fmt.replace("%M", "" + addZeros(d.getMinutes(), 2));
-			fmt = fmt.replace("%S", "" + addZeros(d.getSeconds(), 2));
-			fmt = fmt.replace("%I", "" + ((d.getHours() + 11) % 12 + 1));
-			fmt = fmt.replace("%p", "" + (d.getHours() < 12 ? "AM" : "PM"));
-			fmt = fmt.replace("%B", "" + tinyMCE.getLang("lang_template_months_long")[d.getMonth()]);
-			fmt = fmt.replace("%b", "" + tinyMCE.getLang("lang_template_months_short")[d.getMonth()]);
-			fmt = fmt.replace("%A", "" + tinyMCE.getLang("lang_template_day_long")[d.getDay()]);
-			fmt = fmt.replace("%a", "" + tinyMCE.getLang("lang_template_day_short")[d.getDay()]);
-			fmt = fmt.replace("%%", "%");
-
-			return fmt;
-	},
-
-	TMPL_ELEMENT : 'mceTmplElm',
-	TMPL : 'mceTmpl',
-	TMPL_BEGINS : 'mceTmplBegins',
-	TMPL_SEL_HTML_DONE : 'mceSelHTMLDone',
-	TMPL_ENDS : 'mceTmplEnds',
-	TMPL_DATE_SRC_ATTR : 'mcetmpldtesrc',
-	TMPL_TEMPLATE_EVENT : 'prepare_template'
-};
-
-tinyMCE.addPlugin("template", TinyMCE_TemplatePlugin);
+	// Register plugin
+	tinymce.PluginManager.add('template', tinymce.plugins.TemplatePlugin);
+})();
\ No newline at end of file
Binary file includes/clientside/tinymce/plugins/template/images/template.gif has changed
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/includes/clientside/tinymce/plugins/template/js/template.js	Fri Feb 22 12:51:53 2008 -0500
@@ -0,0 +1,100 @@
+tinyMCEPopup.requireLangPack();
+
+var TemplateDialog = {
+	preInit : function() {
+		var url = tinyMCEPopup.getParam("template_external_list_url");
+
+		if (url != null)
+			document.write('<sc'+'ript language="javascript" type="text/javascript" src="' + tinyMCEPopup.editor.documentBaseURI.toAbsolute(url) + '"></sc'+'ript>');
+	},
+
+	init : function() {
+		var ed = tinyMCEPopup.editor, tsrc, sel, x, u;
+
+ 		tsrc = ed.getParam("template_templates", false);
+ 		sel = document.getElementById('tpath');
+
+		// Setup external template list
+		if (!tsrc && typeof(tinyMCETemplateList) != 'undefined') {
+			for (x=0, tsrc = []; x<tinyMCETemplateList.length; x++)
+				tsrc.push({title : tinyMCETemplateList[x][0], src : tinyMCETemplateList[x][1], description : tinyMCETemplateList[x][2]});
+		}
+
+		for (x=0; x<tsrc.length; x++)
+			sel.options[sel.options.length] = new Option(tsrc[x].title, tinyMCEPopup.editor.documentBaseURI.toAbsolute(tsrc[x].src));
+
+		this.resize();
+	},
+
+	resize : function() {
+		var w, h, e;
+
+		if (!self.innerWidth) {
+			w = document.body.clientWidth - 50;
+			h = document.body.clientHeight - 160;
+		} else {
+			w = self.innerWidth - 50;
+			h = self.innerHeight - 170;
+		}
+
+		e = document.getElementById('templatesrc');
+
+		if (e) {
+			e.style.height = Math.abs(h) + 'px';
+			e.style.width  = Math.abs(w - 5) + 'px';
+		}
+	},
+
+	loadCSSFiles : function(d) {
+		var ed = tinyMCEPopup.editor;
+
+		tinymce.each(ed.getParam("content_css", '').split(','), function(u) {
+			d.write('<link href="' + ed.documentBaseURI.toAbsolute(u) + '" rel="stylesheet" type="text/css" />');
+		});
+	},
+
+	selectTemplate : function(u) {
+		var d = window.frames['templatesrc'].document;
+
+		if (!u)
+			return;
+
+		d.body.innerHTML = this.templateHTML = this.getFileContents(u);
+	},
+
+ 	insert : function() {
+		tinyMCEPopup.execCommand('mceInsertTemplate', false, {
+			content : this.templateHTML,
+			selection : tinyMCEPopup.editor.selection.getContent()
+		});
+
+		tinyMCEPopup.close();
+	},
+
+	getFileContents : function(u) {
+		var x, d, t = 'text/plain';
+
+		function g(s) {
+			x = 0;
+
+			try {
+				x = new ActiveXObject(s);
+			} catch (s) {
+			}
+
+			return x;
+		};
+
+		x = window.ActiveXObject ? g('Msxml2.XMLHTTP') || g('Microsoft.XMLHTTP') : new XMLHttpRequest();
+
+		// Synchronous AJAX load file
+		x.overrideMimeType && x.overrideMimeType(t);
+		x.open("GET", u, false);
+		x.send(null);
+
+		return x.responseText;
+	}
+};
+
+TemplateDialog.preInit();
+tinyMCEPopup.onInit.add(TemplateDialog.init, TemplateDialog);
--- a/includes/clientside/tinymce/plugins/template/jscripts/template.js	Fri Feb 22 12:46:51 2008 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,143 +0,0 @@
-// Import external list url javascript
-var url = tinyMCE.getParam("template_external_list_url");
-if (url != null) {
-	// Fix relative
-	if (url.charAt(0) != '/' && url.indexOf('://') == -1)
-		url = tinyMCE.documentBasePath + "/" + url;
-
-	document.write('<sc'+'ript language="javascript" type="text/javascript" src="' + url + '"></sc'+'ript>');
-}
-
-var TPU = { //Template Popup Utils
-	currentTemplateHTML : null,
-	templates : [],
-	inst : tinyMCE.getInstanceById(tinyMCE.getWindowArg('editor_id')),
-	plugin : tinyMCE.getWindowArg('pluginObj'),
-	data : tinyMCE.selectedInstance.getData('template'),
-
- 	init : function() {
- 		document.forms[0].insert.value = tinyMCE.getLang('lang_' + this.data.currentAction, 'Insert', true); 
-		TPU.loadTemplatePaths();
-
-		if (this.data.currentAction == "update")
-			document.getElementById('warning').innerHTML = tinyMCE.getLang('lang_template_warning');
-
-		this.resizeInputs();
-	},
-
- 	loadTemplatePaths : function() {
-		var tsrc, sel, x, u;
-
- 		tsrc = tinyMCE.getParam("template_templates", false);
- 		sel = document.getElementById('tpath');
-
-		// Setup external template list
-		if (!tsrc && typeof(tinyMCETemplateList) != 'undefined') {
-			for (x=0, tsrc = []; x<tinyMCETemplateList.length; x++)
-				tsrc.push({title : tinyMCETemplateList[x][0], src : tinyMCETemplateList[x][1], description : tinyMCETemplateList[x][2]});
-		}
-
-		for (x=0; x<tsrc.length; x++) {
-			u = tsrc[x].src;
-
-			// Force absolute
-			if (u.indexOf('://') == -1 && u.indexOf('/') != 0)
-				u = tinyMCE.documentBasePath + "/" + u;
-
-			tsrc[x].src = u;
-		}
-
-		TPU.templates = tsrc;
-
-		for (x = 0; x < tsrc.length; x++)
-			sel.options[sel.options.length] = new Option(tsrc[x].title, tsrc[x].src);
-	},
-
- 	selectTemplate : function(o) {
-		var x, d = window.frames['templatesrc'].document;
-
-		this.currentTemplateHTML = this.plugin._replaceValues(this.getFileContents(o.value));
-
-		// Force complete document
-		if (!/<body/gi.test(this.currentTemplateHTML)) {
-			this.currentTemplateHTML = '<html xmlns="http://www.w3.org/1999/xhtml">' + 
-				'<head>' + 
-					'<title>blank_page</title>' + 
-					'<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />' + 
-				'</head>' + 
-				'<body>' + 
-				this.currentTemplateHTML + 
-				'</body>' + 
-				'</html>';
-		}
-
-		// Write HTML to preview iframe
-		d.body.innerHTML = this.currentTemplateHTML;
-
-		// Display description
- 		for (x = 0; x < TPU.templates.length; x++) {
-			if (TPU.templates[x].src == o.value) {
-				document.getElementById('tmpldesc').innerHTML = TPU.templates[x].description;
-				break;
-			}
-		}
- 	},
-
- 	insertTemplate : function() {
-		var sel, opt;
-
-		sel = document.getElementById('tpath');
-		opt = sel.options[sel.selectedIndex];
-
-		// Is it a template or snippet
-		if (TPU.currentTemplateHTML.indexOf('mceTmpl'))
-			tinyMCEPopup.execCommand('mceTemplate', false, {title : opt.text, tsrc : opt.value, body : TPU.currentTemplateHTML});
-		else
-			tinyMCEPopup.execCommand('mceInsertContent', false, TPU.currentTemplateHTML);
-
-		tinyMCEPopup.close();
-	},
-
-	getFileContents : function(u) {
-		var x, d, t = 'text/plain';
-
-		function g(s) {
-			x = 0;
-
-			try {
-				x = new ActiveXObject(s);
-			} catch (s) {
-			}
-
-			return x;
-		};
-
-		x = window.ActiveXObject ? g('Msxml2.XMLHTTP') || g('Microsoft.XMLHTTP') : new XMLHttpRequest();
-
-		// Synchronous AJAX load file
-		x.overrideMimeType && x.overrideMimeType(t);
-		x.open("GET", u, false);
-		x.send(null);
-
-		return x.responseText;
-	},
-
-	resizeInputs : function() {
-		var wHeight, wWidth, elm;
-
-		if (!self.innerWidth) {
-			wHeight = document.body.clientHeight - 160;
-			wWidth = document.body.clientWidth - 40;
-		} else {
-			wHeight = self.innerHeight - 160;
-			wWidth = self.innerWidth - 40;
-		}
-
-		elm = document.getElementById('templatesrc');
-
-		if (elm) {
-			elm.style.height = Math.abs(wHeight) + 'px';
-			elm.style.width  = Math.abs(wWidth - 5) + 'px';
-		}
-	}
-};
--- a/includes/clientside/tinymce/plugins/template/langs/en.js	Fri Feb 22 12:46:51 2008 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,16 +0,0 @@
-// UK lang variables
-
-tinyMCE.addToLang('template',{
-title : 'Templates',
-label : 'Template',
-desc_label : 'Description',
-desc : 'Insert predefined template content',
-select : 'Select a template',
-preview : 'Preview',
-warning : 'Warning: Updating a template with a different one may cause data loss.',
-def_date_format : '%Y-%m-%d %H:%M:%S',
-months_long : new Array("January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"),
-months_short : new Array("Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"),
-day_long : new Array("Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"),
-day_short : new Array("Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun")
-});
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/includes/clientside/tinymce/plugins/template/langs/en_dlg.js	Fri Feb 22 12:51:53 2008 -0500
@@ -0,0 +1,15 @@
+tinyMCE.addI18n('en.template_dlg',{
+title:"Templates",
+label:"Template",
+desc_label:"Description",
+desc:"Insert predefined template content",
+select:"Select a template",
+preview:"Preview",
+warning:"Warning: Updating a template with a different one may cause data loss.",
+mdate_format:"%Y-%m-%d %H:%M:%S",
+cdate_format:"%Y-%m-%d %H:%M:%S",
+months_long:"January,February,March,April,May,June,July,August,September,October,November,December",
+months_short:"Jan,Feb,Mar,Apr,May,Jun,Jul,Aug,Sep,Oct,Nov,Dec",
+day_long:"Sunday,Monday,Tuesday,Wednesday,Thursday,Friday,Saturday,Sunday",
+day_short:"Sun,Mon,Tue,Wed,Thu,Fri,Sat,Sun"
+});
\ No newline at end of file
--- a/includes/clientside/tinymce/plugins/template/template.htm	Fri Feb 22 12:46:51 2008 -0500
+++ b/includes/clientside/tinymce/plugins/template/template.htm	Fri Feb 22 12:51:53 2008 -0500
@@ -1,36 +1,38 @@
 <html xmlns="http://www.w3.org/1999/xhtml">
 <head>
-	<title>{$lang_template_title}</title>
-	<script language="javascript" type="text/javascript" src="../../tiny_mce_popup.js"></script>
-	<script language="javascript" type="text/javascript" src="jscripts/template.js"></script>
+	<title>{#template_dlg.title}</title>
+	<script type="text/javascript" src="../../tiny_mce_popup.js"></script>
+	<script type="text/javascript" src="js/template.js"></script>
 	<link href="css/template.css" rel="stylesheet" type="text/css" />
 	<base target="_self" />
 </head>
-<body onload="tinyMCEPopup.executeOnLoad('TPU.init();');" onresize="TPU.resizeInputs();"> 
-	<form onsubmit="insert();return false;">
+<body onresize="TemplateDialog.resize();"> 
+	<form onsubmit="TemplateDialog.insert();return false;">
 		<div id="frmbody">
-			<div class="title">{$lang_template_desc}</div>
-			<div class="frmRow"><label for="tpath" title="{$lang_template_select}">{$lang_template_label}:</label>
-			<select id="tpath" name="tpath" onfocus="tinyMCE.addSelectAccessibility(event, this, window);" onchange="TPU.selectTemplate(this.options[this.selectedIndex]);">
-				<option value="">{$lang_template_select}...</option>
+			<div class="title">{#template_dlg.desc}</div>
+			<div class="frmRow"><label for="tpath" title="{#template_dlg.select}">{#template_dlg.label}:</label>
+			<select id="tpath" name="tpath" onchange="TemplateDialog.selectTemplate(this.options[this.selectedIndex].value);">
+				<option value="">{#template_dlg.select}...</option>
 			</select>
 			<span id="warning"></span></div>
-			<div class="frmRow"><label for="tdesc">{$lang_template_desc_label}:</label>
+			<div class="frmRow"><label for="tdesc">{#template_dlg.desc_label}:</label>
 			<span id="tmpldesc"></span></div>
 			<fieldset>
-				<legend>{$lang_template_preview}</legend>
+				<legend>{#template_dlg.preview}</legend>
 				<iframe id="templatesrc" name="templatesrc" src="blank.htm" width="690" height="400" frameborder="0"></iframe>
 			</fieldset>
 		</div>
 		
 		<div class="mceActionPanel">
 			<div style="float: left">
-				<input type="button" id="insert" name="insert" value="{$lang_insert}" onclick="TPU.insertTemplate();" />
+				<input type="button" id="insert" name="insert" value="{#insert}" onclick="TemplateDialog.insert();" />
 			</div>
 
 			<div style="float: right">
-				<input type="button" id="cancel" name="cancel" value="{$lang_cancel}" onclick="tinyMCEPopup.close();" />
+				<input type="button" id="cancel" name="cancel" value="{#cancel}" onclick="tinyMCEPopup.close();" />
 			</div>
+
+			<br style="clear:both" />
 		</div>
 	</form>
 </body> 
--- a/includes/clientside/tinymce/plugins/visualchars/editor_plugin.js	Fri Feb 22 12:46:51 2008 -0500
+++ b/includes/clientside/tinymce/plugins/visualchars/editor_plugin.js	Fri Feb 22 12:51:53 2008 -0500
@@ -1,1 +1,1 @@
-tinyMCE.importPluginLanguagePack('visualchars');var TinyMCE_VisualCharsPlugin={getInfo:function(){return{longname:'Visual characters',author:'Moxiecode Systems AB',authorurl:'http://tinymce.moxiecode.com',infourl:'http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/visualchars',version:tinyMCE.majorVersion+"."+tinyMCE.minorVersion}},initInstance:function(inst){inst.visualChars={state:false}},getControlHTML:function(cn){switch(cn){case"visualchars":return tinyMCE.getButtonHTML(cn,'lang_visualchars_desc','{$pluginurl}/images/visualchars.gif','mceVisualChars',false)}return""},execCommand:function(editor_id,element,command,user_interface,value){var inst=tinyMCE.getInstanceById(editor_id);switch(command){case"mceVisualChars":this._toggleVisualChars(editor_id,inst);return true}return false},cleanup:function(type,content,inst){if(type=="insert_to_editor_dom"||type=="get_from_editor_dom"){inst.visualChars.state=true;this._toggleVisualChars(inst.editorId,inst)}return content},_toggleVisualChars:function(editor_id,inst){var nl,i,h,d=inst.getDoc(),b=inst.getBody(),nv,s=inst.selection,bo;inst.visualChars.state=!inst.visualChars.state;bo=s.getBookmark(true);tinyMCE.switchClass(editor_id+'_visualchars',inst.visualChars.state?'mceButtonSelected':'mceButtonNormal');if(inst.visualChars.state){nl=tinyMCE.selectNodes(b,function(n){return n.nodeType==3&&n.nodeValue&&n.nodeValue.indexOf('\u00a0')!=-1});for(i=0;i<nl.length;i++){nv=nl[i].nodeValue;nv=nv.replace(/(\u00a0+)/g,'<span class="mceItemHiddenVisualChar">$1</span>');nv=nv.replace(/\u00a0/g,'\u00b7');tinyMCE.setOuterHTML(nl[i],nv,d)}}else{nl=tinyMCE.selectNodes(b,function(n){return n.nodeType==1&&n.nodeName=='SPAN'&&n.className=='mceItemHiddenVisualChar'});for(i=0;i<nl.length;i++)tinyMCE.setOuterHTML(nl[i],nl[i].innerHTML.replace(/(&middot;|\u00b7)/g,'&nbsp;'),d)}}};tinyMCE.addPlugin("visualchars",TinyMCE_VisualCharsPlugin);
\ No newline at end of file
+(function(){tinymce.create('tinymce.plugins.VisualChars',{init:function(ed,url){var t=this;t.editor=ed;ed.addCommand('mceVisualChars',t._toggleVisualChars,t);ed.addButton('visualchars',{title:'visualchars.desc',cmd:'mceVisualChars'});ed.onBeforeGetContent.add(function(ed,o){if(t.state){t.state=true;t._toggleVisualChars();}});},getInfo:function(){return{longname:'Visual characters',author:'Moxiecode Systems AB',authorurl:'http://tinymce.moxiecode.com',infourl:'http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/visualchars',version:tinymce.majorVersion+"."+tinymce.minorVersion};},_toggleVisualChars:function(){var t=this,ed=t.editor,nl,i,h,d=ed.getDoc(),b=ed.getBody(),nv,s=ed.selection,bo;t.state=!t.state;ed.controlManager.setActive('visualchars',t.state);if(t.state){nl=[];tinymce.walk(b,function(n){if(n.nodeType==3&&n.nodeValue&&n.nodeValue.indexOf('\u00a0')!=-1)nl.push(n);},'childNodes');for(i=0;i<nl.length;i++){nv=nl[i].nodeValue;nv=nv.replace(/(\u00a0+)/g,'<span class="mceItemHidden mceVisualNbsp">$1</span>');nv=nv.replace(/\u00a0/g,'\u00b7');ed.dom.setOuterHTML(nl[i],nv,d);}}else{nl=tinymce.grep(ed.dom.select('span',b),function(n){return ed.dom.hasClass(n,'mceVisualNbsp');});for(i=0;i<nl.length;i++)ed.dom.setOuterHTML(nl[i],nl[i].innerHTML.replace(/(&middot;|\u00b7)/g,'&nbsp;'),d);}}});tinymce.PluginManager.add('visualchars',tinymce.plugins.VisualChars);})();
\ No newline at end of file
--- a/includes/clientside/tinymce/plugins/visualchars/editor_plugin_src.js	Fri Feb 22 12:46:51 2008 -0500
+++ b/includes/clientside/tinymce/plugins/visualchars/editor_plugin_src.js	Fri Feb 22 12:51:53 2008 -0500
@@ -1,89 +1,73 @@
 /**
- * $Id: editor_plugin_src.js 42 2006-08-08 14:32:24Z spocke $
+ * $Id: editor_plugin_src.js 201 2007-02-12 15:56:56Z spocke $
  *
  * @author Moxiecode
- * @copyright Copyright © 2004-2007, Moxiecode Systems AB, All rights reserved.
+ * @copyright Copyright © 2004-2008, Moxiecode Systems AB, All rights reserved.
  */
 
-/* Import plugin specific language pack */
-tinyMCE.importPluginLanguagePack('visualchars');
+(function() {
+	tinymce.create('tinymce.plugins.VisualChars', {
+		init : function(ed, url) {
+			var t = this;
 
-var TinyMCE_VisualCharsPlugin = {
-	getInfo : function() {
-		return {
-			longname : 'Visual characters',
-			author : 'Moxiecode Systems AB',
-			authorurl : 'http://tinymce.moxiecode.com',
-			infourl : 'http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/visualchars',
-			version : tinyMCE.majorVersion + "." + tinyMCE.minorVersion
-		};
-	},
+			t.editor = ed;
 
-	initInstance : function(inst) {
-		inst.visualChars = {
-			state : false
-		};
-	},
+			// Register commands
+			ed.addCommand('mceVisualChars', t._toggleVisualChars, t);
+
+			// Register buttons
+			ed.addButton('visualchars', {title : 'visualchars.desc', cmd : 'mceVisualChars'});
 
-	getControlHTML : function(cn) {
-		switch (cn) {
-			case "visualchars":
-				return tinyMCE.getButtonHTML(cn, 'lang_visualchars_desc', '{$pluginurl}/images/visualchars.gif', 'mceVisualChars', false);
-		}
-
-		return "";
-	},
+			ed.onBeforeGetContent.add(function(ed, o) {
+				if (t.state) {
+					t.state = true;
+					t._toggleVisualChars();
+				}
+			});
+		},
 
-	execCommand : function(editor_id, element, command, user_interface, value) {
-		var inst = tinyMCE.getInstanceById(editor_id);
+		getInfo : function() {
+			return {
+				longname : 'Visual characters',
+				author : 'Moxiecode Systems AB',
+				authorurl : 'http://tinymce.moxiecode.com',
+				infourl : 'http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/visualchars',
+				version : tinymce.majorVersion + "." + tinymce.minorVersion
+			};
+		},
 
-		switch (command) {
-			case "mceVisualChars":
-				this._toggleVisualChars(editor_id, inst);
-				return true;
-		}
-
-		return false;
-	},
+		// Private methods
 
-	cleanup : function(type, content, inst) {
-		if (type == "insert_to_editor_dom" || type == "get_from_editor_dom") {
-			inst.visualChars.state = true;
-			this._toggleVisualChars(inst.editorId, inst);
-		}
+		_toggleVisualChars : function() {
+			var t = this, ed = t.editor, nl, i, h, d = ed.getDoc(), b = ed.getBody(), nv, s = ed.selection, bo;
 
-		return content;
-	},
+			t.state = !t.state;
+			ed.controlManager.setActive('visualchars', t.state);
 
-	// Private plugin internal methods
-
-	_toggleVisualChars : function(editor_id, inst) {
-		var nl, i, h, d = inst.getDoc(), b = inst.getBody(), nv, s = inst.selection, bo;
-
-		inst.visualChars.state = !inst.visualChars.state;
-
-		bo = s.getBookmark(true);
-
-		tinyMCE.switchClass(editor_id + '_visualchars', inst.visualChars.state ? 'mceButtonSelected' : 'mceButtonNormal');
+			if (t.state) {
+				nl = [];
+				tinymce.walk(b, function(n) {
+					if (n.nodeType == 3 && n.nodeValue && n.nodeValue.indexOf('\u00a0') != -1)
+						nl.push(n);
+				}, 'childNodes');
 
-		if (inst.visualChars.state) {
-			nl = tinyMCE.selectNodes(b, function(n) {return n.nodeType == 3 && n.nodeValue && n.nodeValue.indexOf('\u00a0') != -1;});
+				for (i=0; i<nl.length; i++) {
+					nv = nl[i].nodeValue;
+					nv = nv.replace(/(\u00a0+)/g, '<span class="mceItemHidden mceVisualNbsp">$1</span>');
+					nv = nv.replace(/\u00a0/g, '\u00b7');
+					ed.dom.setOuterHTML(nl[i], nv, d);
+				}
+			} else {
+				nl = tinymce.grep(ed.dom.select('span', b), function(n) {
+					return ed.dom.hasClass(n, 'mceVisualNbsp');
+				});
 
-			for (i=0; i<nl.length; i++) {
-				nv = nl[i].nodeValue;
-				nv = nv.replace(/(\u00a0+)/g, '<span class="mceItemHiddenVisualChar">$1</span>');
-				nv = nv.replace(/\u00a0/g, '\u00b7');
-				tinyMCE.setOuterHTML(nl[i], nv, d);
+				for (i=0; i<nl.length; i++)
+					ed.dom.setOuterHTML(nl[i], nl[i].innerHTML.replace(/(&middot;|\u00b7)/g, '&nbsp;'), d);
 			}
-		} else {
-			nl = tinyMCE.selectNodes(b, function(n) {return n.nodeType == 1 && n.nodeName == 'SPAN' && n.className == 'mceItemHiddenVisualChar';});
+		}
+	});
 
-			for (i=0; i<nl.length; i++)
-				tinyMCE.setOuterHTML(nl[i], nl[i].innerHTML.replace(/(&middot;|\u00b7)/g, '&nbsp;'), d);
-		}
-
-		//s.moveToBookmark(bo);
-	}
-};
-
-tinyMCE.addPlugin("visualchars", TinyMCE_VisualCharsPlugin);
+	// Register plugin
+	tinymce.PluginManager.add('visualchars', tinymce.plugins.VisualChars);
+})();
\ No newline at end of file
Binary file includes/clientside/tinymce/plugins/visualchars/images/visualchars.gif has changed
--- a/includes/clientside/tinymce/plugins/visualchars/langs/en.js	Fri Feb 22 12:46:51 2008 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,5 +0,0 @@
-// EN lang variables
-
-tinyMCE.addToLang('visualchars',{
-desc : 'Visual control characters on/off.'
-});
--- a/includes/clientside/tinymce/plugins/xhtmlxtras/abbr.htm	Fri Feb 22 12:46:51 2008 -0500
+++ b/includes/clientside/tinymce/plugins/xhtmlxtras/abbr.htm	Fri Feb 22 12:51:53 2008 -0500
@@ -1,61 +1,62 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
 <html xmlns="http://www.w3.org/1999/xhtml">
 <head>
-	<title>{$lang_xhtmlxtras_title_abbr_element}</title>
-	<script language="javascript" type="text/javascript" src="../../tiny_mce_popup.js"></script>
-	<script language="javascript" type="text/javascript" src="../../utils/mctabs.js"></script>
-	<script language="javascript" type="text/javascript" src="../../utils/form_utils.js"></script>
-	<script language="javascript" type="text/javascript" src="../../utils/editable_selects.js"></script>
-	<script language="javascript" type="text/javascript" src="jscripts/element_common.js"></script>
-	<script language="javascript" type="text/javascript" src="jscripts/abbr.js"></script>
+	<title>{#xhtmlxtras_dlg.title_abbr_element}</title>
+	<script type="text/javascript" src="../../tiny_mce_popup.js"></script>
+	<script type="text/javascript" src="../../utils/mctabs.js"></script>
+	<script type="text/javascript" src="../../utils/form_utils.js"></script>
+	<script type="text/javascript" src="../../utils/editable_selects.js"></script>
+	<script type="text/javascript" src="js/element_common.js"></script>
+	<script type="text/javascript" src="js/abbr.js"></script>
 	<link rel="stylesheet" type="text/css" href="css/popup.css" />
 	<base target="_self" />
 </head>
-<body onload="tinyMCEPopup.executeOnLoad('init();');" style="display: none">
+<body style="display: none">
 <form onsubmit="insertAbbr();return false;" action="#">
 	<div class="tabs">
 		<ul>
-			<li id="general_tab" class="current"><span><a href="javascript:mcTabs.displayTab('general_tab','general_panel');" onmousedown="return false;">{$lang_xhtmlxtras_general_tab}</a></span></li>
-			<!-- <li id="events_tab"><span><a href="javascript:mcTabs.displayTab('events_tab','events_panel');" onmousedown="return false;">{$lang_xhtmlxtras_events_tab}</a></span></li> -->
+			<li id="general_tab" class="current"><span><a href="javascript:mcTabs.displayTab('general_tab','general_panel');" onmousedown="return false;">{#xhtmlxtras_dlg.general_tab}</a></span></li>
+			<!-- <li id="events_tab"><span><a href="javascript:mcTabs.displayTab('events_tab','events_panel');" onmousedown="return false;">{#xhtmlxtras_dlg.events_tab}</a></span></li> -->
 		</ul>
 	</div>
 
 	<div class="panel_wrapper">
 		<div id="general_panel" class="panel current">
 			<fieldset>
-				<legend>{$lang_xhtmlxtras_fieldset_attrib_tab}</legend>
+				<legend>{#xhtmlxtras_dlg.fieldset_attrib_tab}</legend>
 				<table border="0" cellpadding="0" cellspacing="4">
 					<tr>
-						<td class="label"><label id="titlelabel" for="title">{$lang_xhtmlxtras_attribute_label_title}</label>:</td> 
+						<td class="label"><label id="titlelabel" for="title">{#xhtmlxtras_dlg.attribute_label_title}</label>:</td> 
 						<td><input id="title" name="title" type="text" value="" class="field" /></td> 
 					</tr>
 					<tr>
-						<td class="label"><label id="idlabel" for="id">{$lang_xhtmlxtras_attribute_label_id}</label>:</td> 
+						<td class="label"><label id="idlabel" for="id">{#xhtmlxtras_dlg.attribute_label_id}</label>:</td> 
 						<td><input id="id" name="id" type="text" value="" class="field" /></td> 
 					</tr>
 					<tr>
-						<td class="label"><label id="classlabel" for="class">{$lang_xhtmlxtras_attribute_label_class}</label>:</td> 
+						<td class="label"><label id="classlabel" for="class">{#xhtmlxtras_dlg.attribute_label_class}</label>:</td> 
 						<td>
 							<select id="class" name="class" class="field mceEditableSelect">
-								<option value="">{$lang_xhtmlxtras_not_set}</option> 
+								<option value="">{#not_set}</option> 
 							</select>
 						</td>
 					</tr>
 					<tr>
-						<td class="label"><label id="stylelabel" for="class">{$lang_xhtmlxtras_attribute_label_style}</label>:</td> 
+						<td class="label"><label id="stylelabel" for="class">{#xhtmlxtras_dlg.attribute_label_style}</label>:</td> 
 						<td><input id="style" name="style" type="text" value="" class="field" /></td> 
 					</tr>
 					<tr>
-						<td class="label"><label id="dirlabel" for="dir">{$lang_xhtmlxtras_attribute_label_langdir}</label>:</td> 
+						<td class="label"><label id="dirlabel" for="dir">{#xhtmlxtras_dlg.attribute_label_langdir}</label>:</td> 
 						<td>
 							<select id="dir" name="dir" class="field"> 
-								<option value="">{$lang_xhtmlxtras_not_set}</option> 
-								<option value="ltr">{$lang_xhtmlxtras_attribute_option_ltr}</option> 
-								<option value="rtl">{$lang_xhtmlxtras_attribute_option_rtl}</option> 
+								<option value="">{#not_set}</option> 
+								<option value="ltr">{#xhtmlxtras_dlg.attribute_option_ltr}</option> 
+								<option value="rtl">{#xhtmlxtras_dlg.attribute_option_rtl}</option> 
 							</select>
 						</td> 
 					</tr>
 					<tr>
-						<td class="label"><label id="langlabel" for="lang">{$lang_xhtmlxtras_attribute_label_langcode}</label>:</td> 
+						<td class="label"><label id="langlabel" for="lang">{#xhtmlxtras_dlg.attribute_label_langcode}</label>:</td> 
 						<td>
 							<input id="lang" name="lang" type="text" value="" class="field" />
 						</td> 
@@ -65,7 +66,7 @@
 		</div>
 		<div id="events_panel" class="panel">
 			<fieldset>
-				<legend>{$lang_xhtmlxtras_fieldset_events_tab}</legend>
+				<legend>{#xhtmlxtras_dlg.fieldset_events_tab}</legend>
 
 				<table border="0" cellpadding="0" cellspacing="4">
 					<tr>
@@ -133,13 +134,13 @@
 	</div>
 	<div class="mceActionPanel">
 		<div style="float: left">
-			<input type="button" id="insert" name="insert" value="{$lang_update}" onclick="insertAbbr();" />
+			<input type="button" id="insert" name="insert" value="{#update}" onclick="insertAbbr();" />
 		</div>
 		<div style="float: left">
-			<input type="button" id="remove" name="remove" value="{$lang_xhtmlxtras_remove}" onclick="removeAbbr();" style="display: none;" />
+			<input type="button" id="remove" name="remove" class="button" value="{#xhtmlxtras_dlg.remove}" onclick="removeAbbr();" style="display: none;" />
 		</div>
 		<div style="float: right">
-			<input type="button" id="cancel" name="cancel" value="{$lang_cancel}" onclick="tinyMCEPopup.close();" />
+			<input type="button" id="cancel" name="cancel" value="{#cancel}" onclick="tinyMCEPopup.close();" />
 		</div>
 	</div>
 
--- a/includes/clientside/tinymce/plugins/xhtmlxtras/acronym.htm	Fri Feb 22 12:46:51 2008 -0500
+++ b/includes/clientside/tinymce/plugins/xhtmlxtras/acronym.htm	Fri Feb 22 12:51:53 2008 -0500
@@ -1,61 +1,62 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
 <html xmlns="http://www.w3.org/1999/xhtml">
 <head>
-	<title>{$lang_xhtmlxtras_title_acronym_element}</title>
-	<script language="javascript" type="text/javascript" src="../../tiny_mce_popup.js"></script>
-	<script language="javascript" type="text/javascript" src="../../utils/mctabs.js"></script>
-	<script language="javascript" type="text/javascript" src="../../utils/form_utils.js"></script>
-	<script language="javascript" type="text/javascript" src="../../utils/editable_selects.js"></script>
-	<script language="javascript" type="text/javascript" src="jscripts/element_common.js"></script>
-	<script language="javascript" type="text/javascript" src="jscripts/acronym.js"></script>
+	<title>{#xhtmlxtras_dlg.title_acronym_element}</title>
+	<script type="text/javascript" src="../../tiny_mce_popup.js"></script>
+	<script type="text/javascript" src="../../utils/mctabs.js"></script>
+	<script type="text/javascript" src="../../utils/form_utils.js"></script>
+	<script type="text/javascript" src="../../utils/editable_selects.js"></script>
+	<script type="text/javascript" src="js/element_common.js"></script>
+	<script type="text/javascript" src="js/acronym.js"></script>
 	<link rel="stylesheet" type="text/css" href="css/popup.css" />
 	<base target="_self" />
 </head>
-<body onload="tinyMCEPopup.executeOnLoad('init();');" style="display: none">
+<body style="display: none">
 <form onsubmit="insertAcronym();return false;" action="#">
 	<div class="tabs">
 		<ul>
-			<li id="general_tab" class="current"><span><a href="javascript:mcTabs.displayTab('general_tab','general_panel');" onmousedown="return false;">{$lang_xhtmlxtras_general_tab}</a></span></li>
-			<!-- <li id="events_tab"><span><a href="javascript:mcTabs.displayTab('events_tab','events_panel');" onmousedown="return false;">{$lang_xhtmlxtras_events_tab}</a></span></li> -->
+			<li id="general_tab" class="current"><span><a href="javascript:mcTabs.displayTab('general_tab','general_panel');" onmousedown="return false;">{#xhtmlxtras_dlg.general_tab}</a></span></li>
+			<!-- <li id="events_tab"><span><a href="javascript:mcTabs.displayTab('events_tab','events_panel');" onmousedown="return false;">{#xhtmlxtras_dlg.events_tab}</a></span></li> -->
 		</ul>
 	</div>
 
 	<div class="panel_wrapper">
 		<div id="general_panel" class="panel current">
 			<fieldset>
-				<legend>{$lang_xhtmlxtras_fieldset_attrib_tab}</legend>
+				<legend>{#xhtmlxtras_dlg.fieldset_attrib_tab}</legend>
 				<table border="0" cellpadding="0" cellspacing="4">
 					<tr>
-						<td class="label"><label id="titlelabel" for="title">{$lang_xhtmlxtras_attribute_label_title}</label>:</td> 
+						<td class="label"><label id="titlelabel" for="title">{#xhtmlxtras_dlg.attribute_label_title}</label>:</td> 
 						<td><input id="title" name="title" type="text" value="" class="field" /></td> 
 					</tr>
 					<tr>
-						<td class="label"><label id="idlabel" for="id">{$lang_xhtmlxtras_attribute_label_id}</label>:</td> 
+						<td class="label"><label id="idlabel" for="id">{#xhtmlxtras_dlg.attribute_label_id}</label>:</td> 
 						<td><input id="id" name="id" type="text" value="" class="field" /></td> 
 					</tr>
 					<tr>
-						<td class="label"><label id="classlabel" for="class">{$lang_xhtmlxtras_attribute_label_class}</label>:</td> 
+						<td class="label"><label id="classlabel" for="class">{#xhtmlxtras_dlg.attribute_label_class}</label>:</td> 
 						<td>
 							<select id="class" name="class" class="field mceEditableSelect">
-								<option value="">{$lang_xhtmlxtras_not_set}</option> 
+								<option value="">{#not_set}</option> 
 							</select>
 						</td>
 					</tr>
 					<tr>
-						<td class="label"><label id="stylelabel" for="class">{$lang_xhtmlxtras_attribute_label_style}</label>:</td> 
+						<td class="label"><label id="stylelabel" for="class">{#xhtmlxtras_dlg.attribute_label_style}</label>:</td> 
 						<td><input id="style" name="style" type="text" value="" class="field" /></td> 
 					</tr>
 					<tr>
-						<td class="label"><label id="dirlabel" for="dir">{$lang_xhtmlxtras_attribute_label_langdir}</label>:</td> 
+						<td class="label"><label id="dirlabel" for="dir">{#xhtmlxtras_dlg.attribute_label_langdir}</label>:</td> 
 						<td>
 							<select id="dir" name="dir" class="field"> 
-								<option value="">{$lang_xhtmlxtras_not_set}</option> 
-								<option value="ltr">{$lang_xhtmlxtras_attribute_option_ltr}</option> 
-								<option value="rtl">{$lang_xhtmlxtras_attribute_option_rtl}</option> 
+								<option value="">{#not_set}</option> 
+								<option value="ltr">{#xhtmlxtras_dlg.attribute_option_ltr}</option> 
+								<option value="rtl">{#xhtmlxtras_dlg.attribute_option_rtl}</option> 
 							</select>
 						</td> 
 					</tr>
 					<tr>
-						<td class="label"><label id="langlabel" for="lang">{$lang_xhtmlxtras_attribute_label_langcode}</label>:</td> 
+						<td class="label"><label id="langlabel" for="lang">{#xhtmlxtras_dlg.attribute_label_langcode}</label>:</td> 
 						<td>
 							<input id="lang" name="lang" type="text" value="" class="field" />
 						</td> 
@@ -65,7 +66,7 @@
 		</div>
 		<div id="events_panel" class="panel">
 			<fieldset>
-				<legend>{$lang_xhtmlxtras_fieldset_events_tab}</legend>
+				<legend>{#xhtmlxtras_dlg.fieldset_events_tab}</legend>
 
 				<table border="0" cellpadding="0" cellspacing="4">
 					<tr>
@@ -133,13 +134,13 @@
 	</div>
 	<div class="mceActionPanel">
 		<div style="float: left">
-			<input type="button" id="insert" name="insert" value="{$lang_update}" onclick="insertAcronym();" />
+			<input type="button" id="insert" name="insert" value="{#update}" onclick="insertAcronym();" />
 		</div>
 		<div style="float: left">
-			<input type="button" id="remove" name="remove" value="{$lang_xhtmlxtras_remove}" onclick="removeAcronym();" style="display: none;" />
+			<input type="button" id="remove" name="remove" class="button" value="{#xhtmlxtras_dlg.remove}" onclick="removeAcronym();" style="display: none;" />
 		</div>
 		<div style="float: right">
-			<input type="button" id="cancel" name="cancel" value="{$lang_cancel}" onclick="tinyMCEPopup.close();" />
+			<input type="button" id="cancel" name="cancel" value="{#cancel}" onclick="tinyMCEPopup.close();" />
 		</div>
 	</div>
 
--- a/includes/clientside/tinymce/plugins/xhtmlxtras/attributes.htm	Fri Feb 22 12:46:51 2008 -0500
+++ b/includes/clientside/tinymce/plugins/xhtmlxtras/attributes.htm	Fri Feb 22 12:51:53 2008 -0500
@@ -1,71 +1,72 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
 <html xmlns="http://www.w3.org/1999/xhtml">
 <head>
-	<title>{$lang_xhtmlxtras_attribs_title}</title>
-	<script language="javascript" type="text/javascript" src="../../tiny_mce_popup.js"></script>
-	<script language="javascript" type="text/javascript" src="../../utils/mctabs.js"></script>
-	<script language="javascript" type="text/javascript" src="../../utils/editable_selects.js"></script>
-	<script language="javascript" type="text/javascript" src="../../utils/form_utils.js"></script>
-	<script language="javascript" type="text/javascript" src="jscripts/attributes.js"></script>
+	<title>{#xhtmlxtras_dlg.attribs_title}</title>
+	<script type="text/javascript" src="../../tiny_mce_popup.js"></script>
+	<script type="text/javascript" src="../../utils/mctabs.js"></script>
+	<script type="text/javascript" src="../../utils/editable_selects.js"></script>
+	<script type="text/javascript" src="../../utils/form_utils.js"></script>
+	<script type="text/javascript" src="js/attributes.js"></script>
 	<link rel="stylesheet" type="text/css" href="css/attributes.css" />
 	<base target="_self" />
 </head>
-<body onload="tinyMCEPopup.executeOnLoad('init();');" style="display: none">
+<body style="display: none">
 <form onsubmit="insertAction();return false;" action="#">
 	<div class="tabs">
 		<ul>
-			<li id="general_tab" class="current"><span><a href="javascript:mcTabs.displayTab('general_tab','general_panel');" onmousedown="return false;">{$lang_xhtmlxtras_attribute_attrib_tab}</a></span></li>
-			<li id="events_tab"><span><a href="javascript:mcTabs.displayTab('events_tab','events_panel');" onmousedown="return false;">{$lang_xhtmlxtras_attribute_events_tab}</a></span></li>
+			<li id="general_tab" class="current"><span><a href="javascript:mcTabs.displayTab('general_tab','general_panel');" onmousedown="return false;">{#xhtmlxtras_dlg.attribute_attrib_tab}</a></span></li>
+			<li id="events_tab"><span><a href="javascript:mcTabs.displayTab('events_tab','events_panel');" onmousedown="return false;">{#xhtmlxtras_dlg.attribute_events_tab}</a></span></li>
 		</ul>
 	</div>
 
 	<div class="panel_wrapper">
 		<div id="general_panel" class="panel current">
 			<fieldset>
-				<legend>{$lang_xhtmlxtras_attribute_attrib_tab}</legend>
+				<legend>{#xhtmlxtras_dlg.attribute_attrib_tab}</legend>
 				<table border="0" cellpadding="0" cellspacing="4">
 					<tr>
-						<td class="label"><label id="titlelabel" for="title">{$lang_xhtmlxtras_attribute_label_title}</label>:</td> 
+						<td class="label"><label id="titlelabel" for="title">{#xhtmlxtras_dlg.attribute_label_title}</label>:</td> 
 						<td><input id="title" name="title" type="text" value="" /></td> 
 					</tr>
 					<tr>
-						<td class="label"><label id="idlabel" for="id">{$lang_xhtmlxtras_attribute_label_id}</label>:</td> 
+						<td class="label"><label id="idlabel" for="id">{#xhtmlxtras_dlg.attribute_label_id}</label>:</td> 
 						<td><input id="id" name="id" type="text" value="" /></td> 
 					</tr>
 					<tr>
-						<td><label id="classlabel" for="classlist">{$lang_class_name}</label></td>
+						<td><label id="classlabel" for="classlist">{#class_name}</label></td>
 						<td>
 							<select id="classlist" name="classlist" class="mceEditableSelect">
-								<option value="" selected>{$lang_not_set}</option>
+								<option value="" selected>{#not_set}</option>
 							</select>
 						</td>
 					</tr>
 					<tr>
-						<td class="label"><label id="stylelabel" for="class">{$lang_xhtmlxtras_attribute_label_style}</label>:</td> 
+						<td class="label"><label id="stylelabel" for="class">{#xhtmlxtras_dlg.attribute_label_style}</label>:</td> 
 						<td><input id="style" name="style" type="text" value="" /></td> 
 					</tr>
 					<tr>
-						<td class="label"><label id="dirlabel" for="dir">{$lang_xhtmlxtras_attribute_label_langdir}</label>:</td> 
+						<td class="label"><label id="dirlabel" for="dir">{#xhtmlxtras_dlg.attribute_label_langdir}</label>:</td> 
 						<td>
 							<select id="dir" name="dir"> 
-								<option value="">{$lang_xhtmlxtras_not_set}</option> 
-								<option value="ltr">{$lang_xhtmlxtras_option_ltr}</option> 
-								<option value="rtl">{$lang_xhtmlxtras_option_rtl}</option> 
+								<option value="">{#not_set}</option> 
+								<option value="ltr">{#xhtmlxtras_dlg.option_ltr}</option> 
+								<option value="rtl">{#xhtmlxtras_dlg.option_rtl}</option> 
 							</select>
 						</td> 
 					</tr>
 					<tr>
-						<td class="label"><label id="langlabel" for="lang">{$lang_xhtmlxtras_attribute_label_langcode}</label>:</td> 
+						<td class="label"><label id="langlabel" for="lang">{#xhtmlxtras_dlg.attribute_label_langcode}</label>:</td> 
 						<td>
 							<input id="lang" name="lang" type="text" value="" />
 						</td> 
 					</tr>
 					<tr>
-							<td><label id="tabindexlabel" for="tabindex">{$lang_xhtmlxtras_attribute_label_tabindex}</label></td>
+							<td><label id="tabindexlabel" for="tabindex">{#xhtmlxtras_dlg.attribute_label_tabindex}</label></td>
 							<td><input type="text" id="tabindex" name="tabindex" value="" /></td>
 						</tr>
 
 						<tr>
-							<td><label id="accesskeylabel" for="accesskey">{$lang_xhtmlxtras_attribute_label_accesskey}</label></td>
+							<td><label id="accesskeylabel" for="accesskey">{#xhtmlxtras_dlg.attribute_label_accesskey}</label></td>
 							<td><input type="text" id="accesskey" name="accesskey" value="" /></td>
 						</tr>
 				</table>
@@ -73,7 +74,7 @@
 		</div>
 		<div id="events_panel" class="panel">
 			<fieldset>
-				<legend>{$lang_xhtmlxtras_attribute_events_tab}</legend>
+				<legend>{#xhtmlxtras_dlg.attribute_events_tab}</legend>
 
 				<table border="0" cellpadding="0" cellspacing="4">
 					<tr>
@@ -141,10 +142,10 @@
 	</div>
 	<div class="mceActionPanel">
 		<div style="float: left">
-			<input type="button" id="insert" name="insert" value="{$lang_insert}" onclick="insertAction();" />
+			<input type="button" id="insert" name="insert" value="{#insert}" onclick="insertAction();" />
 		</div>
 		<div style="float: right">
-			<input type="button" id="cancel" name="cancel" value="{$lang_cancel}" onclick="tinyMCEPopup.close();" />
+			<input type="button" id="cancel" name="cancel" value="{#cancel}" onclick="tinyMCEPopup.close();" />
 		</div>
 	</div>
 
--- a/includes/clientside/tinymce/plugins/xhtmlxtras/cite.htm	Fri Feb 22 12:46:51 2008 -0500
+++ b/includes/clientside/tinymce/plugins/xhtmlxtras/cite.htm	Fri Feb 22 12:51:53 2008 -0500
@@ -1,61 +1,62 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
 <html xmlns="http://www.w3.org/1999/xhtml">
 <head>
-	<title>{$lang_xhtmlxtras_title_cite_element}</title>
-	<script language="javascript" type="text/javascript" src="../../tiny_mce_popup.js"></script>
-	<script language="javascript" type="text/javascript" src="../../utils/mctabs.js"></script>
-	<script language="javascript" type="text/javascript" src="../../utils/form_utils.js"></script>
-	<script language="javascript" type="text/javascript" src="../../utils/editable_selects.js"></script>
-	<script language="javascript" type="text/javascript" src="jscripts/element_common.js"></script>
-	<script language="javascript" type="text/javascript" src="jscripts/cite.js"></script>
+	<title>{#xhtmlxtras_dlg.title_cite_element}</title>
+	<script type="text/javascript" src="../../tiny_mce_popup.js"></script>
+	<script type="text/javascript" src="../../utils/mctabs.js"></script>
+	<script type="text/javascript" src="../../utils/form_utils.js"></script>
+	<script type="text/javascript" src="../../utils/editable_selects.js"></script>
+	<script type="text/javascript" src="js/element_common.js"></script>
+	<script type="text/javascript" src="js/cite.js"></script>
 	<link rel="stylesheet" type="text/css" href="css/popup.css" />
 	<base target="_self" />
 </head>
-<body onload="tinyMCEPopup.executeOnLoad('init();');" style="display: none">
+<body style="display: none">
 <form onsubmit="insertCite();return false;" action="#">
 	<div class="tabs">
 		<ul>
-			<li id="general_tab" class="current"><span><a href="javascript:mcTabs.displayTab('general_tab','general_panel');" onmousedown="return false;">{$lang_xhtmlxtras_general_tab}</a></span></li>
-			<!-- <li id="events_tab"><span><a href="javascript:mcTabs.displayTab('events_tab','events_panel');" onmousedown="return false;">{$lang_xhtmlxtras_events_tab}</a></span></li> -->
+			<li id="general_tab" class="current"><span><a href="javascript:mcTabs.displayTab('general_tab','general_panel');" onmousedown="return false;">{#xhtmlxtras_dlg.general_tab}</a></span></li>
+			<!-- <li id="events_tab"><span><a href="javascript:mcTabs.displayTab('events_tab','events_panel');" onmousedown="return false;">{#xhtmlxtras_dlg.events_tab}</a></span></li> -->
 		</ul>
 	</div>
 
 	<div class="panel_wrapper">
 		<div id="general_panel" class="panel current">
 			<fieldset>
-				<legend>{$lang_xhtmlxtras_fieldset_attrib_tab}</legend>
+				<legend>{#xhtmlxtras_dlg.fieldset_attrib_tab}</legend>
 				<table border="0" cellpadding="0" cellspacing="4">
 					<tr>
-						<td class="label"><label id="titlelabel" for="title">{$lang_xhtmlxtras_attribute_label_title}</label>:</td> 
+						<td class="label"><label id="titlelabel" for="title">{#xhtmlxtras_dlg.attribute_label_title}</label>:</td> 
 						<td><input id="title" name="title" type="text" value="" class="field" /></td> 
 					</tr>
 					<tr>
-						<td class="label"><label id="idlabel" for="id">{$lang_xhtmlxtras_attribute_label_id}</label>:</td> 
+						<td class="label"><label id="idlabel" for="id">{#xhtmlxtras_dlg.attribute_label_id}</label>:</td> 
 						<td><input id="id" name="id" type="text" value="" class="field" /></td> 
 					</tr>
 					<tr>
-						<td class="label"><label id="classlabel" for="class">{$lang_xhtmlxtras_attribute_label_class}</label>:</td> 
+						<td class="label"><label id="classlabel" for="class">{#xhtmlxtras_dlg.attribute_label_class}</label>:</td> 
 						<td>
 							<select id="class" name="class" class="field mceEditableSelect">
-								<option value="">{$lang_xhtmlxtras_not_set}</option> 
+								<option value="">{#not_set}</option> 
 							</select>
 						</td>
 					</tr>
 					<tr>
-						<td class="label"><label id="stylelabel" for="class">{$lang_xhtmlxtras_attribute_label_style}</label>:</td> 
+						<td class="label"><label id="stylelabel" for="class">{#xhtmlxtras_dlg.attribute_label_style}</label>:</td> 
 						<td><input id="style" name="style" type="text" value="" class="field" /></td> 
 					</tr>
 					<tr>
-						<td class="label"><label id="dirlabel" for="dir">{$lang_xhtmlxtras_attribute_label_langdir}</label>:</td> 
+						<td class="label"><label id="dirlabel" for="dir">{#xhtmlxtras_dlg.attribute_label_langdir}</label>:</td> 
 						<td>
 							<select id="dir" name="dir" class="field"> 
-								<option value="">{$lang_xhtmlxtras_not_set}</option> 
-								<option value="ltr">{$lang_xhtmlxtras_attribute_option_ltr}</option> 
-								<option value="rtl">{$lang_xhtmlxtras_attribute_option_rtl}</option> 
+								<option value="">{#not_set}</option> 
+								<option value="ltr">{#xhtmlxtras_dlg.attribute_option_ltr}</option> 
+								<option value="rtl">{#xhtmlxtras_dlg.attribute_option_rtl}</option> 
 							</select>
 						</td> 
 					</tr>
 					<tr>
-						<td class="label"><label id="langlabel" for="lang">{$lang_xhtmlxtras_attribute_label_langcode}</label>:</td> 
+						<td class="label"><label id="langlabel" for="lang">{#xhtmlxtras_dlg.attribute_label_langcode}</label>:</td> 
 						<td>
 							<input id="lang" name="lang" type="text" value="" class="field" />
 						</td> 
@@ -65,7 +66,7 @@
 		</div>
 		<div id="events_panel" class="panel">
 			<fieldset>
-				<legend>{$lang_xhtmlxtras_fieldset_events_tab}</legend>
+				<legend>{#xhtmlxtras_dlg.fieldset_events_tab}</legend>
 
 				<table border="0" cellpadding="0" cellspacing="4">
 					<tr>
@@ -133,13 +134,13 @@
 	</div>
 	<div class="mceActionPanel">
 		<div style="float: left">
-			<input type="button" id="insert" name="insert" value="{$lang_update}" onclick="insertCite();" />
+			<input type="button" id="insert" name="insert" value="{#update}" onclick="insertCite();" />
 		</div>
 		<div style="float: left">
-			<input type="button" id="remove" name="remove" value="{$lang_xhtmlxtras_remove}" onclick="removeCite();" style="display: none;" />
+			<input type="button" id="remove" name="remove" class="button" value="{#xhtmlxtras_dlg.remove}" onclick="removeCite();" style="display: none;" />
 		</div>
 		<div style="float: right">
-			<input type="button" id="cancel" name="cancel" value="{$lang_cancel}" onclick="tinyMCEPopup.close();" />
+			<input type="button" id="cancel" name="cancel" value="{#cancel}" onclick="tinyMCEPopup.close();" />
 		</div>
 	</div>
 
--- a/includes/clientside/tinymce/plugins/xhtmlxtras/css/popup.css	Fri Feb 22 12:46:51 2008 -0500
+++ b/includes/clientside/tinymce/plugins/xhtmlxtras/css/popup.css	Fri Feb 22 12:51:53 2008 -0500
@@ -1,46 +1,9 @@
-a.mceButtonNormal img, a.mceButtonSelected img {border: 1px solid #F0F0EE !important;}
-a.mceButtonNormal img:hover, a.mceButtonSelected img:hover {border: 1px solid #0A246A !important;  cursor: default;  background-color: #B6BDD2;}
-
-img {
-	border: 0;
-}
-
-input.field, select.field {
-	width: 200px;
-}
-
-input.picker {
-	width: 179px;
-	margin-left: 5px;
-}
-
-input.disabled {
-	border-color: #F2F2F2;
-}
-
-img.picker {
-	vertical-align: text-bottom;
-	cursor: pointer;
-}
-
-h1 {
-	padding: 0 0 5px 0;
-}
-
-#remove {
-	font-weight: bold;
-	width: 90px;
-	height: 21px;
-	border: 0px;
-	background-image: url('../images/remove_button_bg.gif');
-	cursor: pointer;
-	margin-left: 3px;
-}
-
-.panel_wrapper div.current {
-	height: 160px;
-}
-
-#xhtmlxtrasdel .panel_wrapper div.current, #xhtmlxtrasins .panel_wrapper div.current {
-	height: 220px;
-}
+input.field, select.field {width:200px;}
+input.picker {width:179px; margin-left: 5px;}
+input.disabled {border-color:#F2F2F2;}
+img.picker {vertical-align:text-bottom; cursor:pointer;}
+h1 {padding: 0 0 5px 0;}
+.panel_wrapper div.current {height:160px;}
+#xhtmlxtrasdel .panel_wrapper div.current, #xhtmlxtrasins .panel_wrapper div.current {height: 230px;}
+a.browse span {display:block; width:20px; height:20px; background:url('../../../themes/advanced/img/icons.gif') -140px -20px;}
+#datetime {width:180px;}
--- a/includes/clientside/tinymce/plugins/xhtmlxtras/del.htm	Fri Feb 22 12:46:51 2008 -0500
+++ b/includes/clientside/tinymce/plugins/xhtmlxtras/del.htm	Fri Feb 22 12:51:53 2008 -0500
@@ -1,81 +1,82 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
 <html xmlns="http://www.w3.org/1999/xhtml">
 <head>
-	<title>{$lang_xhtmlxtras_title_del_element}</title>
-	<script language="javascript" type="text/javascript" src="../../tiny_mce_popup.js"></script>
-	<script language="javascript" type="text/javascript" src="../../utils/mctabs.js"></script>
-	<script language="javascript" type="text/javascript" src="../../utils/form_utils.js"></script>
-	<script language="javascript" type="text/javascript" src="../../utils/editable_selects.js"></script>
-	<script language="javascript" type="text/javascript" src="jscripts/element_common.js"></script>
-	<script language="javascript" type="text/javascript" src="jscripts/del.js"></script>
+	<title>{#xhtmlxtras_dlg.title_del_element}</title>
+	<script type="text/javascript" src="../../tiny_mce_popup.js"></script>
+	<script type="text/javascript" src="../../utils/mctabs.js"></script>
+	<script type="text/javascript" src="../../utils/form_utils.js"></script>
+	<script type="text/javascript" src="../../utils/editable_selects.js"></script>
+	<script type="text/javascript" src="js/element_common.js"></script>
+	<script type="text/javascript" src="js/del.js"></script>
 	<link rel="stylesheet" type="text/css" href="css/popup.css" />
 	<base target="_self" />
 </head>
-<body id="xhtmlxtrasins" onload="tinyMCEPopup.executeOnLoad('init();');" style="display: none">
+<body id="xhtmlxtrasins" style="display: none">
 <form onsubmit="insertDel();return false;" action="#">
 	<div class="tabs">
 		<ul>
-			<li id="general_tab" class="current"><span><a href="javascript:mcTabs.displayTab('general_tab','general_panel');" onmousedown="return false;">{$lang_xhtmlxtras_general_tab}</a></span></li>
-			<!-- <li id="events_tab"><span><a href="javascript:mcTabs.displayTab('events_tab','events_panel');" onmousedown="return false;">{$lang_xhtmlxtras_events_tab}</a></span></li> -->
+			<li id="general_tab" class="current"><span><a href="javascript:mcTabs.displayTab('general_tab','general_panel');" onmousedown="return false;">{#xhtmlxtras_dlg.general_tab}</a></span></li>
+			<!-- <li id="events_tab"><span><a href="javascript:mcTabs.displayTab('events_tab','events_panel');" onmousedown="return false;">{#xhtmlxtras_dlg.events_tab}</a></span></li> -->
 		</ul>
 	</div>
 
 	<div class="panel_wrapper">
 		<div id="general_panel" class="panel current">
 			<fieldset>
-				<legend>{$lang_xhtmlxtras_fieldset_general_tab}</legend>
+				<legend>{#xhtmlxtras_dlg.fieldset_general_tab}</legend>
 				<table border="0" cellpadding="0" cellspacing="4">
 					<tr>
-						<td class="label"><label id="datetimelabel" for="datetime">{$lang_xhtmlxtras_attribute_label_datetime}</label>:</td>
+						<td class="label"><label id="datetimelabel" for="datetime">{#xhtmlxtras_dlg.attribute_label_datetime}</label>:</td>
 						<td>
 							<table border="0" cellspacing="0" cellpadding="0">
 								<tr> 
 									<td><input id="datetime" name="datetime" type="text" value="" maxlength="19" class="field" /></td> 
-									<td><a href="javascript:insertDateTime('datetime');" class="mceButtonNormal"><img src="images/date_time.gif" class="picker" alt="{$lang_xhtmlxtras_insert_date}" title="{$lang_xhtmlxtras_insert_date}" /></a></td>
+									<td><a href="javascript:insertDateTime('datetime');" onmousedown="return false;" class="browse"><span class="datetime" alt="{#xhtmlxtras_dlg.insert_date}" title="{#xhtmlxtras_dlg.insert_date}"></span></a></td>
 								</tr>
 							</table>
 						</td>
 					</tr>
 					<tr>
-						<td class="label"><label id="citelabel" for="cite">{$lang_xhtmlxtras_attribute_label_cite}</label>:</td>
+						<td class="label"><label id="citelabel" for="cite">{#xhtmlxtras_dlg.attribute_label_cite}</label>:</td>
 						<td><input id="cite" name="cite" type="text" value="" class="field" /></td> 
 					</tr>
 				</table>
 			</fieldset>
 			<fieldset>
-				<legend>{$lang_xhtmlxtras_fieldset_attrib_tab}</legend>
+				<legend>{#xhtmlxtras_dlg.fieldset_attrib_tab}</legend>
 				<table border="0" cellpadding="0" cellspacing="4">
 					<tr>
-						<td class="label"><label id="titlelabel" for="title">{$lang_xhtmlxtras_attribute_label_title}</label>:</td> 
+						<td class="label"><label id="titlelabel" for="title">{#xhtmlxtras_dlg.attribute_label_title}</label>:</td> 
 						<td><input id="title" name="title" type="text" value="" class="field" /></td> 
 					</tr>
 					<tr>
-						<td class="label"><label id="idlabel" for="id">{$lang_xhtmlxtras_attribute_label_id}</label>:</td> 
+						<td class="label"><label id="idlabel" for="id">{#xhtmlxtras_dlg.attribute_label_id}</label>:</td> 
 						<td><input id="id" name="id" type="text" value="" class="field" /></td> 
 					</tr>
 					<tr>
-						<td class="label"><label id="classlabel" for="class">{$lang_xhtmlxtras_attribute_label_class}</label>:</td> 
+						<td class="label"><label id="classlabel" for="class">{#xhtmlxtras_dlg.attribute_label_class}</label>:</td> 
 						<td>
 							<select id="class" name="class" class="field mceEditableSelect">
-								<option value="">{$lang_xhtmlxtras_not_set}</option> 
+								<option value="">{#not_set}</option> 
 							</select>
 						</td>
 					</tr>
 					<tr>
-						<td class="label"><label id="stylelabel" for="class">{$lang_xhtmlxtras_attribute_label_style}</label>:</td> 
+						<td class="label"><label id="stylelabel" for="class">{#xhtmlxtras_dlg.attribute_label_style}</label>:</td> 
 						<td><input id="style" name="style" type="text" value="" class="field" /></td> 
 					</tr>
 					<tr>
-						<td class="label"><label id="dirlabel" for="dir">{$lang_xhtmlxtras_attribute_label_langdir}</label>:</td> 
+						<td class="label"><label id="dirlabel" for="dir">{#xhtmlxtras_dlg.attribute_label_langdir}</label>:</td> 
 						<td>
 							<select id="dir" name="dir" class="field"> 
-								<option value="">{$lang_xhtmlxtras_not_set}</option> 
-								<option value="ltr">{$lang_xhtmlxtras_attribute_option_ltr}</option> 
-								<option value="rtl">{$lang_xhtmlxtras_attribute_option_rtl}</option> 
+								<option value="">{#not_set}</option> 
+								<option value="ltr">{#xhtmlxtras_dlg.attribute_option_ltr}</option> 
+								<option value="rtl">{#xhtmlxtras_dlg.attribute_option_rtl}</option> 
 							</select>
 						</td> 
 					</tr>
 					<tr>
-						<td class="label"><label id="langlabel" for="lang">{$lang_xhtmlxtras_attribute_label_langcode}</label>:</td> 
+						<td class="label"><label id="langlabel" for="lang">{#xhtmlxtras_dlg.attribute_label_langcode}</label>:</td> 
 						<td>
 							<input id="lang" name="lang" type="text" value="" class="field" />
 						</td> 
@@ -85,7 +86,7 @@
 		</div>
 		<div id="events_panel" class="panel">
 			<fieldset>
-				<legend>{$lang_xhtmlxtras_fieldset_events_tab}</legend>
+				<legend>{#xhtmlxtras_dlg.fieldset_events_tab}</legend>
 
 				<table border="0" cellpadding="0" cellspacing="4">
 					<tr>
@@ -153,13 +154,13 @@
 	</div>
 	<div class="mceActionPanel">
 		<div style="float: left">
-			<input type="button" id="insert" name="insert" value="{$lang_update}" onclick="insertDel();" />
+			<input type="button" id="insert" name="insert" value="{#update}" onclick="insertDel();" />
 		</div>
 		<div style="float: left">
-			<input type="button" id="remove" name="remove" value="{$lang_xhtmlxtras_remove}" onclick="removeDel();" style="display: none;" />
+			<input type="button" id="remove" name="remove" class="button" value="{#xhtmlxtras_dlg.remove}" onclick="removeDel();" style="display: none;" />
 		</div>
 		<div style="float: right">
-			<input type="button" id="cancel" name="cancel" value="{$lang_cancel}" onclick="tinyMCEPopup.close();" />
+			<input type="button" id="cancel" name="cancel" value="{#cancel}" onclick="tinyMCEPopup.close();" />
 		</div>
 	</div>
 
--- a/includes/clientside/tinymce/plugins/xhtmlxtras/editor_plugin.js	Fri Feb 22 12:46:51 2008 -0500
+++ b/includes/clientside/tinymce/plugins/xhtmlxtras/editor_plugin.js	Fri Feb 22 12:51:53 2008 -0500
@@ -1,1 +1,1 @@
-tinyMCE.importPluginLanguagePack('xhtmlxtras');var TinyMCE_XHTMLXtrasPlugin={getInfo:function(){return{longname:'XHTML Xtras Plugin',author:'Moxiecode Systems AB',authorurl:'http://tinymce.moxiecode.com',infourl:'http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/xhtmlxtras',version:tinyMCE.majorVersion+"."+tinyMCE.minorVersion}},initInstance:function(inst){tinyMCE.importCSS(inst.getDoc(),tinyMCE.baseURL+"/plugins/xhtmlxtras/css/xhtmlxtras.css")},getControlHTML:function(cn){switch(cn){case"cite":return tinyMCE.getButtonHTML(cn,'lang_xhtmlxtras_cite_desc','{$pluginurl}/images/cite.gif','mceCite',true);case"acronym":return tinyMCE.getButtonHTML(cn,'lang_xhtmlxtras_acronym_desc','{$pluginurl}/images/acronym.gif','mceAcronym',true);case"abbr":return tinyMCE.getButtonHTML(cn,'lang_xhtmlxtras_abbr_desc','{$pluginurl}/images/abbr.gif','mceAbbr',true);case"del":return tinyMCE.getButtonHTML(cn,'lang_xhtmlxtras_del_desc','{$pluginurl}/images/del.gif','mceDel',true);case"ins":return tinyMCE.getButtonHTML(cn,'lang_xhtmlxtras_ins_desc','{$pluginurl}/images/ins.gif','mceIns',true);case"attribs":return tinyMCE.getButtonHTML(cn,'lang_xhtmlxtras_attribs_desc','{$pluginurl}/images/attribs.gif','mceAttributes',true)}return""},execCommand:function(editor_id,element,command,user_interface,value){var template,inst,elm;switch(command){case"mceCite":if(!this._anySel(editor_id))return true;template=new Array();template['file']='../../plugins/xhtmlxtras/cite.htm';template['width']=350;template['height']=250;tinyMCE.openWindow(template,{editor_id:editor_id});return true;case"mceAcronym":if(!this._anySel(editor_id))return true;template=new Array();template['file']='../../plugins/xhtmlxtras/acronym.htm';template['width']=350;template['height']=250;tinyMCE.openWindow(template,{editor_id:editor_id});return true;case"mceAbbr":if(!this._anySel(editor_id))return true;template=new Array();template['file']='../../plugins/xhtmlxtras/abbr.htm';template['width']=350;template['height']=250;tinyMCE.openWindow(template,{editor_id:editor_id});return true;case"mceIns":if(!this._anySel(editor_id))return true;template=new Array();template['file']='../../plugins/xhtmlxtras/ins.htm';template['width']=350;template['height']=310;tinyMCE.openWindow(template,{editor_id:editor_id});return true;case"mceDel":if(!this._anySel(editor_id))return true;template=new Array();template['file']='../../plugins/xhtmlxtras/del.htm';template['width']=350;template['height']=310;tinyMCE.openWindow(template,{editor_id:editor_id});return true;case"mceAttributes":inst=tinyMCE.getInstanceById(editor_id);elm=inst.getFocusElement();if(elm&&elm.nodeName!=='BODY'&&elm.className.indexOf('mceItem')==-1){tinyMCE.openWindow({file:'../../plugins/xhtmlxtras/attributes.htm',width:380,height:370},{editor_id:editor_id})}return true}return false},cleanup:function(type,content,inst){if(type=='insert_to_editor'&&tinyMCE.isIE&&!tinyMCE.isOpera){content=content.replace(/<abbr([^>]+)>/gi,'<html:ABBR $1>');content=content.replace(/<\/abbr>/gi,'</html:ABBR>')}return content},handleNodeChange:function(editor_id,node,undo_index,undo_levels,visual_aid,any_selection){var elm=tinyMCE.getParentElement(node);if(node==null)return;tinyMCE.switchClass(editor_id+'_attribs','mceButtonDisabled');if(!any_selection){tinyMCE.switchClass(editor_id+'_cite','mceButtonDisabled');tinyMCE.switchClass(editor_id+'_acronym','mceButtonDisabled');tinyMCE.switchClass(editor_id+'_abbr','mceButtonDisabled');tinyMCE.switchClass(editor_id+'_del','mceButtonDisabled');tinyMCE.switchClass(editor_id+'_ins','mceButtonDisabled')}else{tinyMCE.switchClass(editor_id+'_cite','mceButtonNormal');tinyMCE.switchClass(editor_id+'_acronym','mceButtonNormal');tinyMCE.switchClass(editor_id+'_abbr','mceButtonNormal');tinyMCE.switchClass(editor_id+'_del','mceButtonNormal');tinyMCE.switchClass(editor_id+'_ins','mceButtonNormal')}if(elm&&elm.nodeName!='BODY'&&elm.className.indexOf('mceItem')==-1)tinyMCE.switchClass(editor_id+'_attribs','mceButtonNormal');switch(node.nodeName){case"CITE":tinyMCE.switchClass(editor_id+'_cite','mceButtonSelected');return true;case"ACRONYM":tinyMCE.switchClass(editor_id+'_acronym','mceButtonSelected');return true;case"abbr":case"HTML:ABBR":case"ABBR":tinyMCE.switchClass(editor_id+'_abbr','mceButtonSelected');return true;case"DEL":tinyMCE.switchClass(editor_id+'_del','mceButtonSelected');return true;case"INS":tinyMCE.switchClass(editor_id+'_ins','mceButtonSelected');return true}return true},_anySel:function(editor_id){var inst=tinyMCE.getInstanceById(editor_id),t=inst.selection.getSelectedText(),pe;pe=tinyMCE.getParentElement(inst.getFocusElement(),'CITE,ACRONYM,ABBR,HTML:ABBR,DEL,INS');return pe||inst.getFocusElement().nodeName=="IMG"||(t&&t.length>0)}};tinyMCE.addPlugin("xhtmlxtras",TinyMCE_XHTMLXtrasPlugin);
\ No newline at end of file
+(function(){tinymce.create('tinymce.plugins.XHTMLXtrasPlugin',{init:function(ed,url){ed.addCommand('mceCite',function(){ed.windowManager.open({file:url+'/cite.htm',width:350+parseInt(ed.getLang('xhtmlxtras.cite_delta_width',0)),height:250+parseInt(ed.getLang('xhtmlxtras.cite_delta_height',0)),inline:1},{plugin_url:url});});ed.addCommand('mceAcronym',function(){ed.windowManager.open({file:url+'/acronym.htm',width:350+parseInt(ed.getLang('xhtmlxtras.acronym_delta_width',0)),height:250+parseInt(ed.getLang('xhtmlxtras.acronym_delta_width',0)),inline:1},{plugin_url:url});});ed.addCommand('mceAbbr',function(){ed.windowManager.open({file:url+'/abbr.htm',width:350+parseInt(ed.getLang('xhtmlxtras.abbr_delta_width',0)),height:250+parseInt(ed.getLang('xhtmlxtras.abbr_delta_width',0)),inline:1},{plugin_url:url});});ed.addCommand('mceDel',function(){ed.windowManager.open({file:url+'/del.htm',width:340+parseInt(ed.getLang('xhtmlxtras.del_delta_width',0)),height:310+parseInt(ed.getLang('xhtmlxtras.del_delta_width',0)),inline:1},{plugin_url:url});});ed.addCommand('mceIns',function(){ed.windowManager.open({file:url+'/ins.htm',width:340+parseInt(ed.getLang('xhtmlxtras.ins_delta_width',0)),height:310+parseInt(ed.getLang('xhtmlxtras.ins_delta_width',0)),inline:1},{plugin_url:url});});ed.addCommand('mceAttributes',function(){ed.windowManager.open({file:url+'/attributes.htm',width:380,height:370,inline:1},{plugin_url:url});});ed.addButton('cite',{title:'xhtmlxtras.cite_desc',cmd:'mceCite'});ed.addButton('acronym',{title:'xhtmlxtras.acronym_desc',cmd:'mceAcronym'});ed.addButton('abbr',{title:'xhtmlxtras.abbr_desc',cmd:'mceAbbr'});ed.addButton('del',{title:'xhtmlxtras.del_desc',cmd:'mceDel'});ed.addButton('ins',{title:'xhtmlxtras.ins_desc',cmd:'mceIns'});ed.addButton('attribs',{title:'xhtmlxtras.attribs_desc',cmd:'mceAttributes'});if(tinymce.isIE){function fix(ed,o){if(o.set){o.content=o.content.replace(/<abbr([^>]+)>/gi,'<html:abbr $1>');o.content=o.content.replace(/<\/abbr>/gi,'</html:abbr>');}};ed.onBeforeSetContent.add(fix);ed.onPostProcess.add(fix);}ed.onNodeChange.add(function(ed,cm,n,co){n=ed.dom.getParent(n,'CITE,ACRONYM,ABBR,DEL,INS');cm.setDisabled('cite',co);cm.setDisabled('acronym',co);cm.setDisabled('abbr',co);cm.setDisabled('del',co);cm.setDisabled('ins',co);cm.setDisabled('attribs',n&&n.nodeName=='BODY');if(n){cm.setDisabled(n.nodeName.toLowerCase(),0);cm.setActive(n.nodeName.toLowerCase(),1);}else{cm.setActive('cite',0);cm.setActive('acronym',0);cm.setActive('abbr',0);cm.setActive('del',0);cm.setActive('ins',0);}});},getInfo:function(){return{longname:'XHTML Xtras Plugin',author:'Moxiecode Systems AB',authorurl:'http://tinymce.moxiecode.com',infourl:'http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/xhtmlxtras',version:tinymce.majorVersion+"."+tinymce.minorVersion};}});tinymce.PluginManager.add('xhtmlxtras',tinymce.plugins.XHTMLXtrasPlugin);})();
\ No newline at end of file
--- a/includes/clientside/tinymce/plugins/xhtmlxtras/editor_plugin_src.js	Fri Feb 22 12:46:51 2008 -0500
+++ b/includes/clientside/tinymce/plugins/xhtmlxtras/editor_plugin_src.js	Fri Feb 22 12:51:53 2008 -0500
@@ -1,199 +1,134 @@
- /**
- * $Id: editor_plugin_src.js 42 2006-08-08 14:32:24Z spocke $
+/**
+ * $Id: editor_plugin_src.js 201 2007-02-12 15:56:56Z spocke $
  *
- * @author Moxiecode - based on work by Andrew Tetlaw
- * @copyright Copyright © 2004-2007, Moxiecode Systems AB, All rights reserved.
+ * @author Moxiecode
+ * @copyright Copyright © 2004-2008, Moxiecode Systems AB, All rights reserved.
  */
 
-/* Import plugin specific language pack */
-tinyMCE.importPluginLanguagePack('xhtmlxtras');
-
-var TinyMCE_XHTMLXtrasPlugin = {
-	getInfo : function() {
-		return {
-			longname : 'XHTML Xtras Plugin',
-			author : 'Moxiecode Systems AB',
-			authorurl : 'http://tinymce.moxiecode.com',
-			infourl : 'http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/xhtmlxtras',
-			version : tinyMCE.majorVersion + "." + tinyMCE.minorVersion
-		};
-	},
-
-	initInstance : function(inst) {
-		tinyMCE.importCSS(inst.getDoc(), tinyMCE.baseURL + "/plugins/xhtmlxtras/css/xhtmlxtras.css");
-	},
+(function() {
+	tinymce.create('tinymce.plugins.XHTMLXtrasPlugin', {
+		init : function(ed, url) {
+			// Register commands
+			ed.addCommand('mceCite', function() {
+				ed.windowManager.open({
+					file : url + '/cite.htm',
+					width : 350 + parseInt(ed.getLang('xhtmlxtras.cite_delta_width', 0)),
+					height : 250 + parseInt(ed.getLang('xhtmlxtras.cite_delta_height', 0)),
+					inline : 1
+				}, {
+					plugin_url : url
+				});
+			});
 
-	getControlHTML : function(cn) {
-		switch (cn) {
-			case "cite":
-				return tinyMCE.getButtonHTML(cn, 'lang_xhtmlxtras_cite_desc', '{$pluginurl}/images/cite.gif', 'mceCite', true);
-
-			case "acronym":
-				return tinyMCE.getButtonHTML(cn, 'lang_xhtmlxtras_acronym_desc', '{$pluginurl}/images/acronym.gif', 'mceAcronym', true);
-
-			case "abbr":
-				return tinyMCE.getButtonHTML(cn, 'lang_xhtmlxtras_abbr_desc', '{$pluginurl}/images/abbr.gif', 'mceAbbr', true);
-
-			case "del":
-				return tinyMCE.getButtonHTML(cn, 'lang_xhtmlxtras_del_desc', '{$pluginurl}/images/del.gif', 'mceDel', true);
-
-			case "ins":
-				return tinyMCE.getButtonHTML(cn, 'lang_xhtmlxtras_ins_desc', '{$pluginurl}/images/ins.gif', 'mceIns', true);
-
-			case "attribs":
-				return tinyMCE.getButtonHTML(cn, 'lang_xhtmlxtras_attribs_desc', '{$pluginurl}/images/attribs.gif', 'mceAttributes', true);
-		}
-
-		return "";
-	},
-
-	execCommand : function(editor_id, element, command, user_interface, value) {
-		var template, inst, elm;
+			ed.addCommand('mceAcronym', function() {
+				ed.windowManager.open({
+					file : url + '/acronym.htm',
+					width : 350 + parseInt(ed.getLang('xhtmlxtras.acronym_delta_width', 0)),
+					height : 250 + parseInt(ed.getLang('xhtmlxtras.acronym_delta_width', 0)),
+					inline : 1
+				}, {
+					plugin_url : url
+				});
+			});
 
-		switch (command) {
-			case "mceCite":
-				if (!this._anySel(editor_id))
-					return true;
-
-				template = new Array();
-				template['file'] = '../../plugins/xhtmlxtras/cite.htm';
-				template['width'] = 350;
-				template['height'] = 250;
-				tinyMCE.openWindow(template, {editor_id : editor_id});
-				return true;
-
-			case "mceAcronym":
-				if (!this._anySel(editor_id))
-					return true;
-
-				template = new Array();
-				template['file'] = '../../plugins/xhtmlxtras/acronym.htm';
-				template['width'] = 350;
-				template['height'] = 250;
-				tinyMCE.openWindow(template, {editor_id : editor_id});
-				return true;
+			ed.addCommand('mceAbbr', function() {
+				ed.windowManager.open({
+					file : url + '/abbr.htm',
+					width : 350 + parseInt(ed.getLang('xhtmlxtras.abbr_delta_width', 0)),
+					height : 250 + parseInt(ed.getLang('xhtmlxtras.abbr_delta_width', 0)),
+					inline : 1
+				}, {
+					plugin_url : url
+				});
+			});
 
-			case "mceAbbr":
-				if (!this._anySel(editor_id))
-					return true;
-
-				template = new Array();
-				template['file'] = '../../plugins/xhtmlxtras/abbr.htm';
-				template['width'] = 350;
-				template['height'] = 250;
-				tinyMCE.openWindow(template, {editor_id : editor_id});
-				return true;
+			ed.addCommand('mceDel', function() {
+				ed.windowManager.open({
+					file : url + '/del.htm',
+					width : 340 + parseInt(ed.getLang('xhtmlxtras.del_delta_width', 0)),
+					height : 310 + parseInt(ed.getLang('xhtmlxtras.del_delta_width', 0)),
+					inline : 1
+				}, {
+					plugin_url : url
+				});
+			});
 
-			case "mceIns":
-				if (!this._anySel(editor_id))
-					return true;
-
-				template = new Array();
-				template['file'] = '../../plugins/xhtmlxtras/ins.htm';
-				template['width'] = 350;
-				template['height'] = 310;
-				tinyMCE.openWindow(template, {editor_id : editor_id});
-				return true;
-
-			case "mceDel":
-				if (!this._anySel(editor_id))
-					return true;
+			ed.addCommand('mceIns', function() {
+				ed.windowManager.open({
+					file : url + '/ins.htm',
+					width : 340 + parseInt(ed.getLang('xhtmlxtras.ins_delta_width', 0)),
+					height : 310 + parseInt(ed.getLang('xhtmlxtras.ins_delta_width', 0)),
+					inline : 1
+				}, {
+					plugin_url : url
+				});
+			});
 
-				template = new Array();
-				template['file'] = '../../plugins/xhtmlxtras/del.htm';
-				template['width'] = 350;
-				template['height'] = 310;
-				tinyMCE.openWindow(template, {editor_id : editor_id});
-				return true;
-
-			case "mceAttributes":
-				inst = tinyMCE.getInstanceById(editor_id);
-				elm = inst.getFocusElement();
-
-				if (elm && elm.nodeName !== 'BODY' && elm.className.indexOf('mceItem') == -1) {
-					tinyMCE.openWindow({
-						file : '../../plugins/xhtmlxtras/attributes.htm',
-						width : 380,
-						height : 370
-					}, {editor_id : editor_id});
-				}
+			ed.addCommand('mceAttributes', function() {
+				ed.windowManager.open({
+					file : url + '/attributes.htm',
+					width : 380,
+					height : 370,
+					inline : 1
+				}, {
+					plugin_url : url
+				});
+			});
 
-				return true;
-		}
-
-		return false;
-	},
+			// Register buttons
+			ed.addButton('cite', {title : 'xhtmlxtras.cite_desc', cmd : 'mceCite'});
+			ed.addButton('acronym', {title : 'xhtmlxtras.acronym_desc', cmd : 'mceAcronym'});
+			ed.addButton('abbr', {title : 'xhtmlxtras.abbr_desc', cmd : 'mceAbbr'});
+			ed.addButton('del', {title : 'xhtmlxtras.del_desc', cmd : 'mceDel'});
+			ed.addButton('ins', {title : 'xhtmlxtras.ins_desc', cmd : 'mceIns'});
+			ed.addButton('attribs', {title : 'xhtmlxtras.attribs_desc', cmd : 'mceAttributes'});
 
-	cleanup : function(type, content, inst) {
-		if (type == 'insert_to_editor' && tinyMCE.isIE && !tinyMCE.isOpera) {
-			content = content.replace(/<abbr([^>]+)>/gi, '<html:ABBR $1>');
-			content = content.replace(/<\/abbr>/gi, '</html:ABBR>');
-		}
+			if (tinymce.isIE) {
+				function fix(ed, o) {
+					if (o.set) {
+						o.content = o.content.replace(/<abbr([^>]+)>/gi, '<html:abbr $1>');
+						o.content = o.content.replace(/<\/abbr>/gi, '</html:abbr>');
+					}
+				};
 
-		return content;
-	},
+				ed.onBeforeSetContent.add(fix);
+				ed.onPostProcess.add(fix);
+			}
 
-	handleNodeChange : function(editor_id, node, undo_index,undo_levels, visual_aid, any_selection) {
-		var elm = tinyMCE.getParentElement(node);
-
-		if (node == null)
-			return;
-
-		tinyMCE.switchClass(editor_id + '_attribs', 'mceButtonDisabled');
+			ed.onNodeChange.add(function(ed, cm, n, co) {
+				n = ed.dom.getParent(n, 'CITE,ACRONYM,ABBR,DEL,INS');
 
-		if (!any_selection) {
-			// Disable the buttons
-			tinyMCE.switchClass(editor_id + '_cite', 'mceButtonDisabled');
-			tinyMCE.switchClass(editor_id + '_acronym', 'mceButtonDisabled');
-			tinyMCE.switchClass(editor_id + '_abbr', 'mceButtonDisabled');
-			tinyMCE.switchClass(editor_id + '_del', 'mceButtonDisabled');
-			tinyMCE.switchClass(editor_id + '_ins', 'mceButtonDisabled');
-		} else {
-			// A selection means the buttons should be active.
-			tinyMCE.switchClass(editor_id + '_cite', 'mceButtonNormal');
-			tinyMCE.switchClass(editor_id + '_acronym', 'mceButtonNormal');
-			tinyMCE.switchClass(editor_id + '_abbr', 'mceButtonNormal');
-			tinyMCE.switchClass(editor_id + '_del', 'mceButtonNormal');
-			tinyMCE.switchClass(editor_id + '_ins', 'mceButtonNormal');
-		}
-
-		if (elm && elm.nodeName != 'BODY' && elm.className.indexOf('mceItem') == -1)
-			tinyMCE.switchClass(editor_id + '_attribs', 'mceButtonNormal');
-
-		switch (node.nodeName) {
-			case "CITE":
-				tinyMCE.switchClass(editor_id + '_cite', 'mceButtonSelected');
-				return true;
-
-			case "ACRONYM":
-				tinyMCE.switchClass(editor_id + '_acronym', 'mceButtonSelected');
-				return true;
+				cm.setDisabled('cite', co);
+				cm.setDisabled('acronym', co);
+				cm.setDisabled('abbr', co);
+				cm.setDisabled('del', co);
+				cm.setDisabled('ins', co);
+				cm.setDisabled('attribs', n && n.nodeName == 'BODY');
 
-			case "abbr": // IE
-			case "HTML:ABBR": // FF
-			case "ABBR":
-				tinyMCE.switchClass(editor_id + '_abbr', 'mceButtonSelected');
-				return true;
+				if (n) {
+					cm.setDisabled(n.nodeName.toLowerCase(), 0);
+					cm.setActive(n.nodeName.toLowerCase(), 1);
+				} else {
+					cm.setActive('cite', 0);
+					cm.setActive('acronym', 0);
+					cm.setActive('abbr', 0);
+					cm.setActive('del', 0);
+					cm.setActive('ins', 0);
+				}
+			});
+		},
 
-			case "DEL":
-				tinyMCE.switchClass(editor_id + '_del', 'mceButtonSelected');
-				return true;
-
-			case "INS":
-				tinyMCE.switchClass(editor_id + '_ins', 'mceButtonSelected');
-				return true;
+		getInfo : function() {
+			return {
+				longname : 'XHTML Xtras Plugin',
+				author : 'Moxiecode Systems AB',
+				authorurl : 'http://tinymce.moxiecode.com',
+				infourl : 'http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/xhtmlxtras',
+				version : tinymce.majorVersion + "." + tinymce.minorVersion
+			};
 		}
-
-		return true;
-	},
-
-	_anySel : function(editor_id) {
-		var inst = tinyMCE.getInstanceById(editor_id), t = inst.selection.getSelectedText(), pe;
+	});
 
-		pe = tinyMCE.getParentElement(inst.getFocusElement(), 'CITE,ACRONYM,ABBR,HTML:ABBR,DEL,INS');
-
-		return pe || inst.getFocusElement().nodeName == "IMG" || (t && t.length > 0);
-	}
-};
-
-tinyMCE.addPlugin("xhtmlxtras", TinyMCE_XHTMLXtrasPlugin);
+	// Register plugin
+	tinymce.PluginManager.add('xhtmlxtras', tinymce.plugins.XHTMLXtrasPlugin);
+})();
\ No newline at end of file
Binary file includes/clientside/tinymce/plugins/xhtmlxtras/images/abbr.gif has changed
Binary file includes/clientside/tinymce/plugins/xhtmlxtras/images/acronym.gif has changed
Binary file includes/clientside/tinymce/plugins/xhtmlxtras/images/attribs.gif has changed
Binary file includes/clientside/tinymce/plugins/xhtmlxtras/images/cite.gif has changed
Binary file includes/clientside/tinymce/plugins/xhtmlxtras/images/date_time.gif has changed
Binary file includes/clientside/tinymce/plugins/xhtmlxtras/images/del.gif has changed
Binary file includes/clientside/tinymce/plugins/xhtmlxtras/images/ins.gif has changed
Binary file includes/clientside/tinymce/plugins/xhtmlxtras/images/remove_button_bg.gif has changed
--- a/includes/clientside/tinymce/plugins/xhtmlxtras/ins.htm	Fri Feb 22 12:46:51 2008 -0500
+++ b/includes/clientside/tinymce/plugins/xhtmlxtras/ins.htm	Fri Feb 22 12:51:53 2008 -0500
@@ -1,81 +1,82 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
 <html xmlns="http://www.w3.org/1999/xhtml">
 <head>
-	<title>{$lang_xhtmlxtras_title_ins_element}</title>
-	<script language="javascript" type="text/javascript" src="../../tiny_mce_popup.js"></script>
-	<script language="javascript" type="text/javascript" src="../../utils/mctabs.js"></script>
-	<script language="javascript" type="text/javascript" src="../../utils/form_utils.js"></script>
-	<script language="javascript" type="text/javascript" src="../../utils/editable_selects.js"></script>
-	<script language="javascript" type="text/javascript" src="jscripts/element_common.js"></script>
-	<script language="javascript" type="text/javascript" src="jscripts/ins.js"></script>
+	<title>{#xhtmlxtras_dlg.title_ins_element}</title>
+	<script type="text/javascript" src="../../tiny_mce_popup.js"></script>
+	<script type="text/javascript" src="../../utils/mctabs.js"></script>
+	<script type="text/javascript" src="../../utils/form_utils.js"></script>
+	<script type="text/javascript" src="../../utils/editable_selects.js"></script>
+	<script type="text/javascript" src="js/element_common.js"></script>
+	<script type="text/javascript" src="js/ins.js"></script>
 	<link rel="stylesheet" type="text/css" href="css/popup.css" />
 	<base target="_self" />
 </head>
-<body id="xhtmlxtrasins" onload="tinyMCEPopup.executeOnLoad('init();');" style="display: none">
+<body id="xhtmlxtrasins" style="display: none">
 <form onsubmit="insertIns();return false;" action="#">
 	<div class="tabs">
 		<ul>
-			<li id="general_tab" class="current"><span><a href="javascript:mcTabs.displayTab('general_tab','general_panel');" onmousedown="return false;">{$lang_xhtmlxtras_general_tab}</a></span></li>
-			<!-- <li id="events_tab"><span><a href="javascript:mcTabs.displayTab('events_tab','events_panel');" onmousedown="return false;">{$lang_xhtmlxtras_events_tab}</a></span></li> -->
+			<li id="general_tab" class="current"><span><a href="javascript:mcTabs.displayTab('general_tab','general_panel');" onmousedown="return false;">{#xhtmlxtras_dlg.general_tab}</a></span></li>
+			<!-- <li id="events_tab"><span><a href="javascript:mcTabs.displayTab('events_tab','events_panel');" onmousedown="return false;">{#xhtmlxtras_dlg.events_tab}</a></span></li> -->
 		</ul>
 	</div>
 
 	<div class="panel_wrapper">
 		<div id="general_panel" class="panel current">
 			<fieldset>
-				<legend>{$lang_xhtmlxtras_fieldset_general_tab}</legend>
+				<legend>{#xhtmlxtras_dlg.fieldset_general_tab}</legend>
 				<table border="0" cellpadding="0" cellspacing="4">
 					<tr>
-						<td class="label"><label id="datetimelabel" for="datetime">{$lang_xhtmlxtras_attribute_label_datetime}</label>:</td> 
+						<td class="label"><label id="datetimelabel" for="datetime">{#xhtmlxtras_dlg.attribute_label_datetime}</label>:</td> 
 						<td>
 							<table border="0" cellspacing="0" cellpadding="0">
 								<tr> 
 									<td><input id="datetime" name="datetime" type="text" value="" maxlength="19" class="field" /></td> 
-									<td><a href="javascript:insertDateTime('datetime');" class="mceButtonNormal"><img src="images/date_time.gif" class="picker" alt="{$lang_xhtmlxtras_insert_date}" title="{$lang_xhtmlxtras_insert_date}" /></a></td>
+									<td><a href="javascript:insertDateTime('datetime');" onmousedown="return false;" class="browse"><span class="datetime" alt="{#xhtmlxtras_dlg.insert_date}" title="{#xhtmlxtras_dlg.insert_date}"></span></a></td>
 								</tr>
 							</table>
 						</td>
 					</tr>
 					<tr>
-						<td class="label"><label id="citelabel" for="cite">{$lang_xhtmlxtras_attribute_label_cite}</label>:</td> 
+						<td class="label"><label id="citelabel" for="cite">{#xhtmlxtras_dlg.attribute_label_cite}</label>:</td> 
 						<td><input id="cite" name="cite" type="text" value="" class="field" /></td> 
 					</tr>
 				</table>
 			</fieldset>
 			<fieldset>
-				<legend>{$lang_xhtmlxtras_fieldset_attrib_tab}</legend>
+				<legend>{#xhtmlxtras_dlg.fieldset_attrib_tab}</legend>
 				<table border="0" cellpadding="0" cellspacing="4">
 					<tr>
-						<td class="label"><label id="titlelabel" for="title">{$lang_xhtmlxtras_attribute_label_title}</label>:</td> 
+						<td class="label"><label id="titlelabel" for="title">{#xhtmlxtras_dlg.attribute_label_title}</label>:</td> 
 						<td><input id="title" name="title" type="text" value="" class="field" /></td> 
 					</tr>
 					<tr>
-						<td class="label"><label id="idlabel" for="id">{$lang_xhtmlxtras_attribute_label_id}</label>:</td> 
+						<td class="label"><label id="idlabel" for="id">{#xhtmlxtras_dlg.attribute_label_id}</label>:</td> 
 						<td><input id="id" name="id" type="text" value="" class="field" /></td> 
 					</tr>
 					<tr>
-						<td class="label"><label id="classlabel" for="class">{$lang_xhtmlxtras_attribute_label_class}</label>:</td> 
+						<td class="label"><label id="classlabel" for="class">{#xhtmlxtras_dlg.attribute_label_class}</label>:</td> 
 						<td>
 							<select id="class" name="class" class="field mceEditableSelect">
-								<option value="">{$lang_xhtmlxtras_not_set}</option> 
+								<option value="">{#not_set}</option> 
 							</select>
 						</td>
 					</tr>
 					<tr>
-						<td class="label"><label id="stylelabel" for="class">{$lang_xhtmlxtras_attribute_label_style}</label>:</td> 
+						<td class="label"><label id="stylelabel" for="class">{#xhtmlxtras_dlg.attribute_label_style}</label>:</td> 
 						<td><input id="style" name="style" type="text" value="" class="field" /></td> 
 					</tr>
 					<tr>
-						<td class="label"><label id="dirlabel" for="dir">{$lang_xhtmlxtras_attribute_label_langdir}</label>:</td> 
+						<td class="label"><label id="dirlabel" for="dir">{#xhtmlxtras_dlg.attribute_label_langdir}</label>:</td> 
 						<td>
 							<select id="dir" name="dir" class="field"> 
-								<option value="">{$lang_xhtmlxtras_not_set}</option> 
-								<option value="ltr">{$lang_xhtmlxtras_attribute_option_ltr}</option> 
-								<option value="rtl">{$lang_xhtmlxtras_attribute_option_rtl}</option> 
+								<option value="">{#not_set}</option> 
+								<option value="ltr">{#xhtmlxtras_dlg.attribute_option_ltr}</option> 
+								<option value="rtl">{#xhtmlxtras_dlg.attribute_option_rtl}</option> 
 							</select>
 						</td> 
 					</tr>
 					<tr>
-						<td class="label"><label id="langlabel" for="lang">{$lang_xhtmlxtras_attribute_label_langcode}</label>:</td> 
+						<td class="label"><label id="langlabel" for="lang">{#xhtmlxtras_dlg.attribute_label_langcode}</label>:</td> 
 						<td>
 							<input id="lang" name="lang" type="text" value="" class="field" />
 						</td> 
@@ -85,7 +86,7 @@
 		</div>
 		<div id="events_panel" class="panel">
 			<fieldset>
-				<legend>{$lang_xhtmlxtras_fieldset_events_tab}</legend>
+				<legend>{#xhtmlxtras_dlg.fieldset_events_tab}</legend>
 
 				<table border="0" cellpadding="0" cellspacing="4">
 					<tr>
@@ -153,13 +154,13 @@
 	</div>
 	<div class="mceActionPanel">
 		<div style="float: left">
-			<input type="button" id="insert" name="insert" value="{$lang_update}" onclick="insertIns();" />
+			<input type="button" id="insert" name="insert" value="{#update}" onclick="insertIns();" />
 		</div>
 		<div style="float: left">
-			<input type="button" id="remove" name="remove" value="{$lang_xhtmlxtras_remove}" onclick="removeIns();" style="display: none;" />
+			<input type="button" id="remove" name="remove" class="button" value="{#xhtmlxtras_dlg.remove}" onclick="removeIns();" style="display: none;" />
 		</div>
 		<div style="float: right">
-			<input type="button" id="cancel" name="cancel" value="{$lang_cancel}" onclick="tinyMCEPopup.close();" />
+			<input type="button" id="cancel" name="cancel" value="{#cancel}" onclick="tinyMCEPopup.close();" />
 		</div>
 	</div>
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/includes/clientside/tinymce/plugins/xhtmlxtras/js/abbr.js	Fri Feb 22 12:51:53 2008 -0500
@@ -0,0 +1,25 @@
+ /**
+ * $Id: editor_plugin_src.js 42 2006-08-08 14:32:24Z spocke $
+ *
+ * @author Moxiecode - based on work by Andrew Tetlaw
+ * @copyright Copyright © 2004-2008, Moxiecode Systems AB, All rights reserved.
+ */
+
+function init() {
+	SXE.initElementDialog('abbr');
+	if (SXE.currentAction == "update") {
+		SXE.showRemoveButton();
+	}
+}
+
+function insertAbbr() {
+	SXE.insertElement(tinymce.isIE ? 'html:abbr' : 'abbr');
+	tinyMCEPopup.close();
+}
+
+function removeAbbr() {
+	SXE.removeElement('abbr');
+	tinyMCEPopup.close();
+}
+
+tinyMCEPopup.onInit.add(init);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/includes/clientside/tinymce/plugins/xhtmlxtras/js/acronym.js	Fri Feb 22 12:51:53 2008 -0500
@@ -0,0 +1,25 @@
+ /**
+ * $Id: editor_plugin_src.js 42 2006-08-08 14:32:24Z spocke $
+ *
+ * @author Moxiecode - based on work by Andrew Tetlaw
+ * @copyright Copyright © 2004-2008, Moxiecode Systems AB, All rights reserved.
+ */
+
+function init() {
+	SXE.initElementDialog('acronym');
+	if (SXE.currentAction == "update") {
+		SXE.showRemoveButton();
+	}
+}
+
+function insertAcronym() {
+	SXE.insertElement('acronym');
+	tinyMCEPopup.close();
+}
+
+function removeAcronym() {
+	SXE.removeElement('acronym');
+	tinyMCEPopup.close();
+}
+
+tinyMCEPopup.onInit.add(init);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/includes/clientside/tinymce/plugins/xhtmlxtras/js/attributes.js	Fri Feb 22 12:51:53 2008 -0500
@@ -0,0 +1,123 @@
+ /**
+ * $Id: editor_plugin_src.js 42 2006-08-08 14:32:24Z spocke $
+ *
+ * @author Moxiecode - based on work by Andrew Tetlaw
+ * @copyright Copyright © 2004-2006, Moxiecode Systems AB, All rights reserved.
+ */
+
+function init() {
+	tinyMCEPopup.resizeToInnerSize();
+	var inst = tinyMCEPopup.editor;
+	var dom = inst.dom;
+	var elm = inst.selection.getNode();
+	var f = document.forms[0];
+	var onclick = dom.getAttrib(elm, 'onclick');
+
+	setFormValue('title', dom.getAttrib(elm, 'title'));
+	setFormValue('id', dom.getAttrib(elm, 'id'));
+	setFormValue('style', dom.getAttrib(elm, "style"));
+	setFormValue('dir', dom.getAttrib(elm, 'dir'));
+	setFormValue('lang', dom.getAttrib(elm, 'lang'));
+	setFormValue('tabindex', dom.getAttrib(elm, 'tabindex', typeof(elm.tabindex) != "undefined" ? elm.tabindex : ""));
+	setFormValue('accesskey', dom.getAttrib(elm, 'accesskey', typeof(elm.accesskey) != "undefined" ? elm.accesskey : ""));
+	setFormValue('onfocus', dom.getAttrib(elm, 'onfocus'));
+	setFormValue('onblur', dom.getAttrib(elm, 'onblur'));
+	setFormValue('onclick', onclick);
+	setFormValue('ondblclick', dom.getAttrib(elm, 'ondblclick'));
+	setFormValue('onmousedown', dom.getAttrib(elm, 'onmousedown'));
+	setFormValue('onmouseup', dom.getAttrib(elm, 'onmouseup'));
+	setFormValue('onmouseover', dom.getAttrib(elm, 'onmouseover'));
+	setFormValue('onmousemove', dom.getAttrib(elm, 'onmousemove'));
+	setFormValue('onmouseout', dom.getAttrib(elm, 'onmouseout'));
+	setFormValue('onkeypress', dom.getAttrib(elm, 'onkeypress'));
+	setFormValue('onkeydown', dom.getAttrib(elm, 'onkeydown'));
+	setFormValue('onkeyup', dom.getAttrib(elm, 'onkeyup'));
+	className = dom.getAttrib(elm, 'class');
+
+	addClassesToList('classlist', 'advlink_styles');
+	selectByValue(f, 'classlist', className, true);
+
+	TinyMCE_EditableSelects.init();
+}
+
+function setFormValue(name, value) {
+	if(value && document.forms[0].elements[name]){
+		document.forms[0].elements[name].value = value;
+	}
+}
+
+function insertAction() {
+	var inst = tinyMCEPopup.editor;
+	var elm = inst.selection.getNode();
+
+	tinyMCEPopup.execCommand("mceBeginUndoLevel");	
+	setAllAttribs(elm);
+	tinyMCEPopup.execCommand("mceEndUndoLevel");
+	tinyMCEPopup.close();
+}
+
+function setAttrib(elm, attrib, value) {
+	var formObj = document.forms[0];
+	var valueElm = formObj.elements[attrib.toLowerCase()];
+	var inst = tinyMCEPopup.editor;
+	var dom = inst.dom;
+
+	if (typeof(value) == "undefined" || value == null) {
+		value = "";
+
+		if (valueElm)
+			value = valueElm.value;
+	}
+
+	if (value != "") {
+		dom.setAttrib(elm, attrib.toLowerCase(), value);
+
+		if (attrib == "style")
+			attrib = "style.cssText";
+
+		if (attrib.substring(0, 2) == 'on')
+			value = 'return true;' + value;
+
+		if (attrib == "class")
+			attrib = "className";
+
+		eval('elm.' + attrib + "=value;");
+	} else
+		elm.removeAttribute(attrib);
+}
+
+function setAllAttribs(elm) {
+	var f = document.forms[0];
+
+	setAttrib(elm, 'title');
+	setAttrib(elm, 'id');
+	setAttrib(elm, 'style');
+	setAttrib(elm, 'class', getSelectValue(f, 'classlist'));
+	setAttrib(elm, 'dir');
+	setAttrib(elm, 'lang');
+	setAttrib(elm, 'tabindex');
+	setAttrib(elm, 'accesskey');
+	setAttrib(elm, 'onfocus');
+	setAttrib(elm, 'onblur');
+	setAttrib(elm, 'onclick');
+	setAttrib(elm, 'ondblclick');
+	setAttrib(elm, 'onmousedown');
+	setAttrib(elm, 'onmouseup');
+	setAttrib(elm, 'onmouseover');
+	setAttrib(elm, 'onmousemove');
+	setAttrib(elm, 'onmouseout');
+	setAttrib(elm, 'onkeypress');
+	setAttrib(elm, 'onkeydown');
+	setAttrib(elm, 'onkeyup');
+
+	// Refresh in old MSIE
+//	if (tinyMCE.isMSIE5)
+//		elm.outerHTML = elm.outerHTML;
+}
+
+function insertAttribute() {
+	tinyMCEPopup.close();
+}
+
+tinyMCEPopup.onInit.add(init);
+tinyMCEPopup.requireLangPack();
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/includes/clientside/tinymce/plugins/xhtmlxtras/js/cite.js	Fri Feb 22 12:51:53 2008 -0500
@@ -0,0 +1,25 @@
+ /**
+ * $Id: editor_plugin_src.js 42 2006-08-08 14:32:24Z spocke $
+ *
+ * @author Moxiecode - based on work by Andrew Tetlaw
+ * @copyright Copyright © 2004-2008, Moxiecode Systems AB, All rights reserved.
+ */
+
+function init() {
+	SXE.initElementDialog('cite');
+	if (SXE.currentAction == "update") {
+		SXE.showRemoveButton();
+	}
+}
+
+function insertCite() {
+	SXE.insertElement('cite');
+	tinyMCEPopup.close();
+}
+
+function removeCite() {
+	SXE.removeElement('cite');
+	tinyMCEPopup.close();
+}
+
+tinyMCEPopup.onInit.add(init);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/includes/clientside/tinymce/plugins/xhtmlxtras/js/del.js	Fri Feb 22 12:51:53 2008 -0500
@@ -0,0 +1,50 @@
+ /**
+ * $Id: editor_plugin_src.js 42 2006-08-08 14:32:24Z spocke $
+ *
+ * @author Moxiecode - based on work by Andrew Tetlaw
+ * @copyright Copyright © 2004-2008, Moxiecode Systems AB, All rights reserved.
+ */
+
+function init() {
+	SXE.initElementDialog('del');
+	if (SXE.currentAction == "update") {
+		setFormValue('datetime', tinyMCEPopup.editor.dom.getAttrib(SXE.updateElement, 'datetime'));
+		setFormValue('cite', tinyMCEPopup.editor.dom.getAttrib(SXE.updateElement, 'cite'));
+		SXE.showRemoveButton();
+	}
+}
+
+function setElementAttribs(elm) {
+	setAllCommonAttribs(elm);
+	setAttrib(elm, 'datetime');
+	setAttrib(elm, 'cite');
+}
+
+function insertDel() {
+	var elm = tinyMCEPopup.editor.dom.getParent(SXE.focusElement, 'DEL');
+
+	tinyMCEPopup.execCommand('mceBeginUndoLevel');
+	if (elm == null) {
+		var s = SXE.inst.selection.getContent();
+		if(s.length > 0) {
+			tinyMCEPopup.execCommand('mceInsertContent', false, '<del id="#sxe_temp_del#">' + s + '</del>');
+			var elementArray = tinymce.grep(SXE.inst.dom.select('del'), function(n) {return n.id == '#sxe_temp_del#';});
+			for (var i=0; i<elementArray.length; i++) {
+				var elm = elementArray[i];
+				setElementAttribs(elm);
+			}
+		}
+	} else {
+		setElementAttribs(elm);
+	}
+	tinyMCEPopup.editor.nodeChanged();
+	tinyMCEPopup.execCommand('mceEndUndoLevel');
+	tinyMCEPopup.close();
+}
+
+function removeDel() {
+	SXE.removeElement('del');
+	tinyMCEPopup.close();
+}
+
+tinyMCEPopup.onInit.add(init);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/includes/clientside/tinymce/plugins/xhtmlxtras/js/element_common.js	Fri Feb 22 12:51:53 2008 -0500
@@ -0,0 +1,221 @@
+ /**
+ * $Id: editor_plugin_src.js 42 2006-08-08 14:32:24Z spocke $
+ *
+ * @author Moxiecode - based on work by Andrew Tetlaw
+ * @copyright Copyright © 2004-2008, Moxiecode Systems AB, All rights reserved.
+ */
+
+tinyMCEPopup.requireLangPack();
+
+function initCommonAttributes(elm) {
+	var formObj = document.forms[0], dom = tinyMCEPopup.editor.dom;
+
+	// Setup form data for common element attributes
+	setFormValue('title', dom.getAttrib(elm, 'title'));
+	setFormValue('id', dom.getAttrib(elm, 'id'));
+	selectByValue(formObj, 'class', dom.getAttrib(elm, 'class'), true);
+	setFormValue('style', dom.getAttrib(elm, 'style'));
+	selectByValue(formObj, 'dir', dom.getAttrib(elm, 'dir'));
+	setFormValue('lang', dom.getAttrib(elm, 'lang'));
+	setFormValue('onfocus', dom.getAttrib(elm, 'onfocus'));
+	setFormValue('onblur', dom.getAttrib(elm, 'onblur'));
+	setFormValue('onclick', dom.getAttrib(elm, 'onclick'));
+	setFormValue('ondblclick', dom.getAttrib(elm, 'ondblclick'));
+	setFormValue('onmousedown', dom.getAttrib(elm, 'onmousedown'));
+	setFormValue('onmouseup', dom.getAttrib(elm, 'onmouseup'));
+	setFormValue('onmouseover', dom.getAttrib(elm, 'onmouseover'));
+	setFormValue('onmousemove', dom.getAttrib(elm, 'onmousemove'));
+	setFormValue('onmouseout', dom.getAttrib(elm, 'onmouseout'));
+	setFormValue('onkeypress', dom.getAttrib(elm, 'onkeypress'));
+	setFormValue('onkeydown', dom.getAttrib(elm, 'onkeydown'));
+	setFormValue('onkeyup', dom.getAttrib(elm, 'onkeyup'));
+}
+
+function setFormValue(name, value) {
+	if(document.forms[0].elements[name]) document.forms[0].elements[name].value = value;
+}
+
+function insertDateTime(id) {
+	document.getElementById(id).value = getDateTime(new Date(), "%Y-%m-%dT%H:%M:%S");
+}
+
+function getDateTime(d, fmt) {
+	fmt = fmt.replace("%D", "%m/%d/%y");
+	fmt = fmt.replace("%r", "%I:%M:%S %p");
+	fmt = fmt.replace("%Y", "" + d.getFullYear());
+	fmt = fmt.replace("%y", "" + d.getYear());
+	fmt = fmt.replace("%m", addZeros(d.getMonth()+1, 2));
+	fmt = fmt.replace("%d", addZeros(d.getDate(), 2));
+	fmt = fmt.replace("%H", "" + addZeros(d.getHours(), 2));
+	fmt = fmt.replace("%M", "" + addZeros(d.getMinutes(), 2));
+	fmt = fmt.replace("%S", "" + addZeros(d.getSeconds(), 2));
+	fmt = fmt.replace("%I", "" + ((d.getHours() + 11) % 12 + 1));
+	fmt = fmt.replace("%p", "" + (d.getHours() < 12 ? "AM" : "PM"));
+	fmt = fmt.replace("%%", "%");
+
+	return fmt;
+}
+
+function addZeros(value, len) {
+	var i;
+
+	value = "" + value;
+
+	if (value.length < len) {
+		for (i=0; i<(len-value.length); i++)
+			value = "0" + value;
+	}
+
+	return value;
+}
+
+function selectByValue(form_obj, field_name, value, add_custom, ignore_case) {
+	if (!form_obj || !form_obj.elements[field_name])
+		return;
+
+	var sel = form_obj.elements[field_name];
+
+	var found = false;
+	for (var i=0; i<sel.options.length; i++) {
+		var option = sel.options[i];
+
+		if (option.value == value || (ignore_case && option.value.toLowerCase() == value.toLowerCase())) {
+			option.selected = true;
+			found = true;
+		} else
+			option.selected = false;
+	}
+
+	if (!found && add_custom && value != '') {
+		var option = new Option('Value: ' + value, value);
+		option.selected = true;
+		sel.options[sel.options.length] = option;
+	}
+
+	return found;
+}
+
+function setAttrib(elm, attrib, value) {
+	var formObj = document.forms[0];
+	var valueElm = formObj.elements[attrib.toLowerCase()];
+	tinyMCEPopup.editor.dom.setAttrib(elm, attrib, value || valueElm.value);
+}
+
+function setAllCommonAttribs(elm) {
+	setAttrib(elm, 'title');
+	setAttrib(elm, 'id');
+	setAttrib(elm, 'class');
+	setAttrib(elm, 'style');
+	setAttrib(elm, 'dir');
+	setAttrib(elm, 'lang');
+	/*setAttrib(elm, 'onfocus');
+	setAttrib(elm, 'onblur');
+	setAttrib(elm, 'onclick');
+	setAttrib(elm, 'ondblclick');
+	setAttrib(elm, 'onmousedown');
+	setAttrib(elm, 'onmouseup');
+	setAttrib(elm, 'onmouseover');
+	setAttrib(elm, 'onmousemove');
+	setAttrib(elm, 'onmouseout');
+	setAttrib(elm, 'onkeypress');
+	setAttrib(elm, 'onkeydown');
+	setAttrib(elm, 'onkeyup');*/
+}
+
+SXE = {
+	currentAction : "insert",
+	inst : tinyMCEPopup.editor,
+	updateElement : null
+}
+
+SXE.focusElement = SXE.inst.selection.getNode();
+
+SXE.initElementDialog = function(element_name) {
+	addClassesToList('class', 'xhtmlxtras_styles');
+	TinyMCE_EditableSelects.init();
+
+	element_name = element_name.toLowerCase();
+	var elm = SXE.inst.dom.getParent(SXE.focusElement, element_name.toUpperCase());
+	if (elm != null && elm.nodeName == element_name.toUpperCase()) {
+		SXE.currentAction = "update";
+	}
+
+	if (SXE.currentAction == "update") {
+		initCommonAttributes(elm);
+		SXE.updateElement = elm;
+	}
+
+	document.forms[0].insert.value = tinyMCEPopup.getLang(SXE.currentAction, 'Insert', true); 
+}
+
+SXE.insertElement = function(element_name) {
+	var elm = SXE.inst.dom.getParent(SXE.focusElement, element_name.toUpperCase()), h, tagName;
+
+	tinyMCEPopup.execCommand('mceBeginUndoLevel');
+	if (elm == null) {
+		var s = SXE.inst.selection.getContent();
+		if(s.length > 0) {
+			tagName = element_name;
+
+			if (tinymce.isIE && element_name.indexOf('html:') == 0)
+				element_name = element_name.substring(5).toLowerCase();
+
+			h = '<' + tagName + ' id="#sxe_temp_' + element_name + '#">' + s + '</' + tagName + '>';
+
+			tinyMCEPopup.execCommand('mceInsertContent', false, h);
+
+			var elementArray = tinymce.grep(SXE.inst.dom.select(element_name), function(n) {return n.id == '#sxe_temp_' + element_name + '#';});
+			for (var i=0; i<elementArray.length; i++) {
+				var elm = elementArray[i];
+
+				elm.id = '';
+				elm.setAttribute('id', '');
+				elm.removeAttribute('id');
+
+				setAllCommonAttribs(elm);
+			}
+		}
+	} else {
+		setAllCommonAttribs(elm);
+	}
+	SXE.inst.nodeChanged();
+	tinyMCEPopup.execCommand('mceEndUndoLevel');
+}
+
+SXE.removeElement = function(element_name){
+	element_name = element_name.toLowerCase();
+	elm = SXE.inst.dom.getParent(SXE.focusElement, element_name.toUpperCase());
+	if(elm && elm.nodeName == element_name.toUpperCase()){
+		tinyMCEPopup.execCommand('mceBeginUndoLevel');
+		tinyMCE.execCommand('mceRemoveNode', false, elm);
+		SXE.inst.nodeChanged();
+		tinyMCEPopup.execCommand('mceEndUndoLevel');
+	}
+}
+
+SXE.showRemoveButton = function() {
+		document.getElementById("remove").style.display = 'block';
+}
+
+SXE.containsClass = function(elm,cl) {
+	return (elm.className.indexOf(cl) > -1) ? true : false;
+}
+
+SXE.removeClass = function(elm,cl) {
+	if(elm.className == null || elm.className == "" || !SXE.containsClass(elm,cl)) {
+		return true;
+	}
+	var classNames = elm.className.split(" ");
+	var newClassNames = "";
+	for (var x = 0, cnl = classNames.length; x < cnl; x++) {
+		if (classNames[x] != cl) {
+			newClassNames += (classNames[x] + " ");
+		}
+	}
+	elm.className = newClassNames.substring(0,newClassNames.length-1); //removes extra space at the end
+}
+
+SXE.addClass = function(elm,cl) {
+	if(!SXE.containsClass(elm,cl)) elm.className ? elm.className += " " + cl : elm.className = cl;
+	return true;
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/includes/clientside/tinymce/plugins/xhtmlxtras/js/ins.js	Fri Feb 22 12:51:53 2008 -0500
@@ -0,0 +1,49 @@
+ /**
+ * $Id: editor_plugin_src.js 42 2006-08-08 14:32:24Z spocke $
+ *
+ * @author Moxiecode - based on work by Andrew Tetlaw
+ * @copyright Copyright © 2004-2008, Moxiecode Systems AB, All rights reserved.
+ */
+
+function init() {
+	SXE.initElementDialog('ins');
+	if (SXE.currentAction == "update") {
+		setFormValue('datetime', tinyMCEPopup.editor.dom.getAttrib(SXE.updateElement, 'datetime'));
+		setFormValue('cite', tinyMCEPopup.editor.dom.getAttrib(SXE.updateElement, 'cite'));
+		SXE.showRemoveButton();
+	}
+}
+
+function setElementAttribs(elm) {
+	setAllCommonAttribs(elm);
+	setAttrib(elm, 'datetime');
+	setAttrib(elm, 'cite');
+}
+
+function insertIns() {
+	var elm = tinyMCEPopup.editor.dom.getParent(SXE.focusElement, 'INS');
+	tinyMCEPopup.execCommand('mceBeginUndoLevel');
+	if (elm == null) {
+		var s = SXE.inst.selection.getContent();
+		if(s.length > 0) {
+			tinyMCEPopup.execCommand('mceInsertContent', false, '<ins id="#sxe_temp_ins#">' + s + '</ins>');
+			var elementArray = tinymce.grep(SXE.inst.dom.select('ins'), function(n) {return n.id == '#sxe_temp_ins#';});
+			for (var i=0; i<elementArray.length; i++) {
+				var elm = elementArray[i];
+				setElementAttribs(elm);
+			}
+		}
+	} else {
+		setElementAttribs(elm);
+	}
+	tinyMCEPopup.editor.nodeChanged();
+	tinyMCEPopup.execCommand('mceEndUndoLevel');
+	tinyMCEPopup.close();
+}
+
+function removeIns() {
+	SXE.removeElement('ins');
+	tinyMCEPopup.close();
+}
+
+tinyMCEPopup.onInit.add(init);
--- a/includes/clientside/tinymce/plugins/xhtmlxtras/jscripts/abbr.js	Fri Feb 22 12:46:51 2008 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,29 +0,0 @@
- /**
- * $Id: editor_plugin_src.js 42 2006-08-08 14:32:24Z spocke $
- *
- * @author Moxiecode - based on work by Andrew Tetlaw
- * @copyright Copyright © 2004-2007, Moxiecode Systems AB, All rights reserved.
- */
-
-function preinit() {
-	// Initialize
-	tinyMCE.setWindowArg('mce_windowresize', false);
-}
-
-function init() {
-	tinyMCEPopup.resizeToInnerSize();
-	SXE.initElementDialog('abbr');
-	if (SXE.currentAction == "update") {
-		SXE.showRemoveButton();
-	}
-}
-
-function insertAbbr() {
-	SXE.insertElement(tinyMCE.isIE && !tinyMCE.isOpera ? 'html:ABBR' : 'abbr');
-	tinyMCEPopup.close();
-}
-
-function removeAbbr() {
-	SXE.removeElement('abbr');
-	tinyMCEPopup.close();
-}
\ No newline at end of file
--- a/includes/clientside/tinymce/plugins/xhtmlxtras/jscripts/acronym.js	Fri Feb 22 12:46:51 2008 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,29 +0,0 @@
- /**
- * $Id: editor_plugin_src.js 42 2006-08-08 14:32:24Z spocke $
- *
- * @author Moxiecode - based on work by Andrew Tetlaw
- * @copyright Copyright © 2004-2007, Moxiecode Systems AB, All rights reserved.
- */
-
-function preinit() {
-	// Initialize
-	tinyMCE.setWindowArg('mce_windowresize', false);
-}
-
-function init() {
-	tinyMCEPopup.resizeToInnerSize();
-	SXE.initElementDialog('acronym');
-	if (SXE.currentAction == "update") {
-		SXE.showRemoveButton();
-	}
-}
-
-function insertAcronym() {
-	SXE.insertElement('acronym');
-	tinyMCEPopup.close();
-}
-
-function removeAcronym() {
-	SXE.removeElement('acronym');
-	tinyMCEPopup.close();
-}
\ No newline at end of file
--- a/includes/clientside/tinymce/plugins/xhtmlxtras/jscripts/attributes.js	Fri Feb 22 12:46:51 2008 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,130 +0,0 @@
- /**
- * $Id: editor_plugin_src.js 42 2006-08-08 14:32:24Z spocke $
- *
- * @author Moxiecode - based on work by Andrew Tetlaw
- * @copyright Copyright © 2004-2006, Moxiecode Systems AB, All rights reserved.
- */
-
-function preinit() {
-	// Initialize
-	tinyMCE.setWindowArg('mce_windowresize', false);
-}
-
-function init() {
-	tinyMCEPopup.resizeToInnerSize();
-	var inst = tinyMCE.getInstanceById(tinyMCE.getWindowArg('editor_id'));
-	var elm = inst.getFocusElement();
-
-	var f = document.forms[0];
-	
-	var onclick = tinyMCE.cleanupEventStr(tinyMCE.getAttrib(elm, 'onclick'));
-
-	setFormValue('title', tinyMCE.getAttrib(elm, 'title'));
-	setFormValue('id', tinyMCE.getAttrib(elm, 'id'));
-	setFormValue('style', tinyMCE.serializeStyle(tinyMCE.parseStyle(tinyMCE.getAttrib(elm, "style"))));
-	setFormValue('dir', tinyMCE.getAttrib(elm, 'dir'));
-	setFormValue('lang', tinyMCE.getAttrib(elm, 'lang'));
-	setFormValue('tabindex', tinyMCE.getAttrib(elm, 'tabindex', typeof(elm.tabindex) != "undefined" ? elm.tabindex : ""));
-	setFormValue('accesskey', tinyMCE.getAttrib(elm, 'accesskey', typeof(elm.accesskey) != "undefined" ? elm.accesskey : ""));
-	setFormValue('onfocus', tinyMCE.cleanupEventStr(tinyMCE.getAttrib(elm, 'onfocus')));
-	setFormValue('onblur', tinyMCE.cleanupEventStr(tinyMCE.getAttrib(elm, 'onblur')));
-	setFormValue('onclick', onclick);
-	setFormValue('ondblclick', tinyMCE.cleanupEventStr(tinyMCE.getAttrib(elm, 'ondblclick')));
-	setFormValue('onmousedown', tinyMCE.cleanupEventStr(tinyMCE.getAttrib(elm, 'onmousedown')));
-	setFormValue('onmouseup', tinyMCE.cleanupEventStr(tinyMCE.getAttrib(elm, 'onmouseup')));
-	setFormValue('onmouseover', tinyMCE.cleanupEventStr(tinyMCE.getAttrib(elm, 'onmouseover')));
-	setFormValue('onmousemove', tinyMCE.cleanupEventStr(tinyMCE.getAttrib(elm, 'onmousemove')));
-	setFormValue('onmouseout', tinyMCE.cleanupEventStr(tinyMCE.getAttrib(elm, 'onmouseout')));
-	setFormValue('onkeypress', tinyMCE.cleanupEventStr(tinyMCE.getAttrib(elm, 'onkeypress')));
-	setFormValue('onkeydown', tinyMCE.cleanupEventStr(tinyMCE.getAttrib(elm, 'onkeydown')));
-	setFormValue('onkeyup', tinyMCE.cleanupEventStr(tinyMCE.getAttrib(elm, 'onkeyup')));
-	
-	className = tinyMCE.getVisualAidClass(tinyMCE.getAttrib(elm, 'class'), false);
-		
-	addClassesToList('classlist', 'advlink_styles');
-	selectByValue(f, 'classlist', className, true);
-	
-	TinyMCE_EditableSelects.init();
-}
-
-function setFormValue(name, value) {
-	if(value && document.forms[0].elements[name]){
-		document.forms[0].elements[name].value = value;
-	}
-}
-
-function insertAction() {
-	var inst = tinyMCE.getInstanceById(tinyMCE.getWindowArg('editor_id'));
-	var elm = inst.getFocusElement();
-
-	tinyMCEPopup.execCommand("mceBeginUndoLevel");	
-	tinyMCEPopup.restoreSelection();
-	
-	setAllAttribs(elm);
-	
-	tinyMCE.handleVisualAid(inst.getBody(), true, inst.visualAid, inst);
-	tinyMCE._setEventsEnabled(inst.getBody(), false);
-	tinyMCEPopup.execCommand("mceEndUndoLevel");
-	tinyMCEPopup.close();
-}
-
-function setAttrib(elm, attrib, value) {
-	var formObj = document.forms[0];
-	var valueElm = formObj.elements[attrib.toLowerCase()];
-
-	if (typeof(value) == "undefined" || value == null) {
-		value = "";
-
-		if (valueElm)
-			value = valueElm.value;
-	}
-
-	if (value != "") {
-		tinyMCE.setAttrib(elm, attrib.toLowerCase(), value);
-
-		if (attrib == "style")
-			attrib = "style.cssText";
-
-		if (attrib.substring(0, 2) == 'on')
-			value = 'return true;' + value;
-
-		if (attrib == "class")
-			attrib = "className";
-
-		eval('elm.' + attrib + "=value;");
-	} else
-		elm.removeAttribute(attrib);
-}
-
-function setAllAttribs(elm) {
-	var f = document.forms[0];
-
-	setAttrib(elm, 'title');
-	setAttrib(elm, 'id');
-	setAttrib(elm, 'style');
-	setAttrib(elm, 'class', getSelectValue(f, 'classlist'));
-	setAttrib(elm, 'dir');
-	setAttrib(elm, 'lang');
-	setAttrib(elm, 'tabindex');
-	setAttrib(elm, 'accesskey');
-	setAttrib(elm, 'onfocus');
-	setAttrib(elm, 'onblur');
-	setAttrib(elm, 'onclick');
-	setAttrib(elm, 'ondblclick');
-	setAttrib(elm, 'onmousedown');
-	setAttrib(elm, 'onmouseup');
-	setAttrib(elm, 'onmouseover');
-	setAttrib(elm, 'onmousemove');
-	setAttrib(elm, 'onmouseout');
-	setAttrib(elm, 'onkeypress');
-	setAttrib(elm, 'onkeydown');
-	setAttrib(elm, 'onkeyup');
-
-	// Refresh in old MSIE
-	if (tinyMCE.isMSIE5)
-		elm.outerHTML = elm.outerHTML;
-}
-
-function insertAttribute() {
-	tinyMCEPopup.close();
-}
\ No newline at end of file
--- a/includes/clientside/tinymce/plugins/xhtmlxtras/jscripts/cite.js	Fri Feb 22 12:46:51 2008 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,29 +0,0 @@
- /**
- * $Id: editor_plugin_src.js 42 2006-08-08 14:32:24Z spocke $
- *
- * @author Moxiecode - based on work by Andrew Tetlaw
- * @copyright Copyright © 2004-2007, Moxiecode Systems AB, All rights reserved.
- */
-
-function preinit() {
-	// Initialize
-	tinyMCE.setWindowArg('mce_windowresize', false);
-}
-
-function init() {
-	tinyMCEPopup.resizeToInnerSize();
-	SXE.initElementDialog('cite');
-	if (SXE.currentAction == "update") {
-		SXE.showRemoveButton();
-	}
-}
-
-function insertCite() {
-	SXE.insertElement('cite');
-	tinyMCEPopup.close();
-}
-
-function removeCite() {
-	SXE.removeElement('cite');
-	tinyMCEPopup.close();
-}
\ No newline at end of file
--- a/includes/clientside/tinymce/plugins/xhtmlxtras/jscripts/del.js	Fri Feb 22 12:46:51 2008 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,54 +0,0 @@
- /**
- * $Id: editor_plugin_src.js 42 2006-08-08 14:32:24Z spocke $
- *
- * @author Moxiecode - based on work by Andrew Tetlaw
- * @copyright Copyright © 2004-2007, Moxiecode Systems AB, All rights reserved.
- */
-
-function preinit() {
-	// Initialize
-	tinyMCE.setWindowArg('mce_windowresize', false);
-}
-
-function init() {
-	tinyMCEPopup.resizeToInnerSize();
-	SXE.initElementDialog('del');
-	if (SXE.currentAction == "update") {
-		setFormValue('datetime', tinyMCE.getAttrib(SXE.updateElement, 'datetime'));
-		setFormValue('cite', tinyMCE.getAttrib(SXE.updateElement, 'cite'));
-		SXE.showRemoveButton();
-	}
-}
-
-function setElementAttribs(elm) {
-	setAllCommonAttribs(elm);
-	setAttrib(elm, 'datetime');
-	setAttrib(elm, 'cite');
-}
-
-function insertDel() {
-	var elm = tinyMCE.getParentElement(SXE.focusElement, 'del');
-
-	tinyMCEPopup.execCommand('mceBeginUndoLevel');
-	if (elm == null) {
-		var s = SXE.inst.selection.getSelectedHTML();
-		if(s.length > 0) {
-			tinyMCEPopup.execCommand('mceInsertContent', false, '<del id="#sxe_temp_del#">' + s + '</del>');
-			var elementArray = tinyMCE.getElementsByAttributeValue(SXE.inst.getBody(), 'del', 'id', '#sxe_temp_del#');
-			for (var i=0; i<elementArray.length; i++) {
-				var elm = elementArray[i];
-				setElementAttribs(elm);
-			}
-		}
-	} else {
-		setElementAttribs(elm);
-	}
-	tinyMCE.triggerNodeChange();
-	tinyMCEPopup.execCommand('mceEndUndoLevel');
-	tinyMCEPopup.close();
-}
-
-function removeDel() {
-	SXE.removeElement('del');
-	tinyMCEPopup.close();
-}
\ No newline at end of file
--- a/includes/clientside/tinymce/plugins/xhtmlxtras/jscripts/element_common.js	Fri Feb 22 12:46:51 2008 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,241 +0,0 @@
- /**
- * $Id: editor_plugin_src.js 42 2006-08-08 14:32:24Z spocke $
- *
- * @author Moxiecode - based on work by Andrew Tetlaw
- * @copyright Copyright © 2004-2007, Moxiecode Systems AB, All rights reserved.
- */
-
-function initCommonAttributes(elm) {
-	var formObj = document.forms[0];
-
-	// Setup form data for common element attributes
-	setFormValue('title', tinyMCE.getAttrib(elm, 'title'));
-	setFormValue('id', tinyMCE.getAttrib(elm, 'id'));
-	selectByValue(formObj, 'class', tinyMCE.getAttrib(elm, 'class'), true);
-	setFormValue('style', tinyMCE.getAttrib(elm, 'style'));
-	selectByValue(formObj, 'dir', tinyMCE.getAttrib(elm, 'dir'));
-	setFormValue('lang', tinyMCE.getAttrib(elm, 'lang'));
-	setFormValue('onfocus', tinyMCE.getAttrib(elm, 'onfocus'));
-	setFormValue('onblur', tinyMCE.getAttrib(elm, 'onblur'));
-	setFormValue('onclick', tinyMCE.getAttrib(elm, 'onclick'));
-	setFormValue('ondblclick', tinyMCE.getAttrib(elm, 'ondblclick'));
-	setFormValue('onmousedown', tinyMCE.getAttrib(elm, 'onmousedown'));
-	setFormValue('onmouseup', tinyMCE.getAttrib(elm, 'onmouseup'));
-	setFormValue('onmouseover', tinyMCE.getAttrib(elm, 'onmouseover'));
-	setFormValue('onmousemove', tinyMCE.getAttrib(elm, 'onmousemove'));
-	setFormValue('onmouseout', tinyMCE.getAttrib(elm, 'onmouseout'));
-	setFormValue('onkeypress', tinyMCE.getAttrib(elm, 'onkeypress'));
-	setFormValue('onkeydown', tinyMCE.getAttrib(elm, 'onkeydown'));
-	setFormValue('onkeyup', tinyMCE.getAttrib(elm, 'onkeyup'));
-}
-
-function setFormValue(name, value) {
-	if(document.forms[0].elements[name]) document.forms[0].elements[name].value = value;
-}
-
-function insertDateTime(id) {
-	document.getElementById(id).value = getDateTime(new Date(), "%Y-%m-%dT%H:%M:%S");
-}
-
-function getDateTime(d, fmt) {
-	fmt = fmt.replace("%D", "%m/%d/%y");
-	fmt = fmt.replace("%r", "%I:%M:%S %p");
-	fmt = fmt.replace("%Y", "" + d.getFullYear());
-	fmt = fmt.replace("%y", "" + d.getYear());
-	fmt = fmt.replace("%m", addZeros(d.getMonth()+1, 2));
-	fmt = fmt.replace("%d", addZeros(d.getDate(), 2));
-	fmt = fmt.replace("%H", "" + addZeros(d.getHours(), 2));
-	fmt = fmt.replace("%M", "" + addZeros(d.getMinutes(), 2));
-	fmt = fmt.replace("%S", "" + addZeros(d.getSeconds(), 2));
-	fmt = fmt.replace("%I", "" + ((d.getHours() + 11) % 12 + 1));
-	fmt = fmt.replace("%p", "" + (d.getHours() < 12 ? "AM" : "PM"));
-	fmt = fmt.replace("%%", "%");
-
-	return fmt;
-}
-
-function addZeros(value, len) {
-	var i;
-
-	value = "" + value;
-
-	if (value.length < len) {
-		for (i=0; i<(len-value.length); i++)
-			value = "0" + value;
-	}
-
-	return value;
-}
-
-function selectByValue(form_obj, field_name, value, add_custom, ignore_case) {
-	if (!form_obj || !form_obj.elements[field_name])
-		return;
-
-	var sel = form_obj.elements[field_name];
-
-	var found = false;
-	for (var i=0; i<sel.options.length; i++) {
-		var option = sel.options[i];
-
-		if (option.value == value || (ignore_case && option.value.toLowerCase() == value.toLowerCase())) {
-			option.selected = true;
-			found = true;
-		} else
-			option.selected = false;
-	}
-
-	if (!found && add_custom && value != '') {
-		var option = new Option('Value: ' + value, value);
-		option.selected = true;
-		sel.options[sel.options.length] = option;
-	}
-
-	return found;
-}
-
-function setAttrib(elm, attrib, value) {
-	var formObj = document.forms[0];
-	var valueElm = formObj.elements[attrib.toLowerCase()];
-
-	if (typeof(value) == "undefined" || value == null) {
-		value = "";
-
-		if (valueElm)
-			value = valueElm.value;
-	}
-
-	if (value != "") {
-		if (attrib == "style")
-			attrib = "style.cssText";
-
-		if (attrib.substring(0, 2) == 'on')
-			value = 'return true;' + value;
-
-		if (attrib == "class") {
-			tinyMCE.addCSSClass(elm, value);
-			return;
-		}
-
-		elm.setAttribute(attrib.toLowerCase(), value);
-	} else
-		elm.removeAttribute(attrib);
-}
-
-function setAllCommonAttribs(elm) {
-	setAttrib(elm, 'title');
-	setAttrib(elm, 'id');
-	setAttrib(elm, 'class');
-	setAttrib(elm, 'style');
-	setAttrib(elm, 'dir');
-	setAttrib(elm, 'lang');
-	/*setAttrib(elm, 'onfocus');
-	setAttrib(elm, 'onblur');
-	setAttrib(elm, 'onclick');
-	setAttrib(elm, 'ondblclick');
-	setAttrib(elm, 'onmousedown');
-	setAttrib(elm, 'onmouseup');
-	setAttrib(elm, 'onmouseover');
-	setAttrib(elm, 'onmousemove');
-	setAttrib(elm, 'onmouseout');
-	setAttrib(elm, 'onkeypress');
-	setAttrib(elm, 'onkeydown');
-	setAttrib(elm, 'onkeyup');*/
-}
-
-SXE = {
-	currentAction : "insert",
-	inst : tinyMCE.getInstanceById(tinyMCE.getWindowArg('editor_id')),
-	updateElement : null
-}
-
-SXE.focusElement = SXE.inst.getFocusElement();
-
-SXE.initElementDialog = function(element_name) {
-	addClassesToList('class', 'xhtmlxtras_styles');
-	TinyMCE_EditableSelects.init();
-
-	element_name = element_name.toLowerCase();
-	var elm = tinyMCE.getParentElement(SXE.focusElement, element_name);
-	if (elm != null && elm.nodeName == element_name.toUpperCase()) {
-		SXE.currentAction = "update";
-	}
-
-	if (SXE.currentAction == "update") {
-		initCommonAttributes(elm);
-		SXE.updateElement = elm;
-	}
-
-	document.forms[0].insert.value = tinyMCE.getLang('lang_' + SXE.currentAction, 'Insert', true); 
-}
-
-SXE.insertElement = function(element_name) {
-	var elm = tinyMCE.getParentElement(SXE.focusElement, element_name), h, tagName;
-
-	tinyMCEPopup.execCommand('mceBeginUndoLevel');
-	if (elm == null) {
-		var s = SXE.inst.selection.getSelectedHTML();
-		if(s.length > 0) {
-			tagName = element_name;
-
-			if (tinyMCE.isIE && !tinyMCE.isOpera && element_name.indexOf('html:') == 0)
-				element_name = element_name.substring(5).toLowerCase();
-
-			h = '<' + tagName + ' id="#sxe_temp_' + element_name + '#">' + s + '</' + tagName + '>';
-
-			tinyMCEPopup.execCommand('mceInsertContent', false, h);
-
-			var elementArray = tinyMCE.getElementsByAttributeValue(SXE.inst.getBody(), element_name, 'id', '#sxe_temp_' + element_name + '#');
-			for (var i=0; i<elementArray.length; i++) {
-				var elm = elementArray[i];
-
-				elm.id = '';
-				elm.setAttribute('id', '');
-				elm.removeAttribute('id');
-
-				setAllCommonAttribs(elm);
-			}
-		}
-	} else {
-		setAllCommonAttribs(elm);
-	}
-	tinyMCE.triggerNodeChange();
-	tinyMCEPopup.execCommand('mceEndUndoLevel');
-}
-
-SXE.removeElement = function(element_name){
-	element_name = element_name.toLowerCase();
-	elm = tinyMCE.getParentElement(SXE.focusElement, element_name);
-	if(elm && elm.nodeName == element_name.toUpperCase()){
-		tinyMCEPopup.execCommand('mceBeginUndoLevel');
-		tinyMCE.execCommand('mceRemoveNode', false, elm);
-		tinyMCE.triggerNodeChange();
-		tinyMCEPopup.execCommand('mceEndUndoLevel');
-	}
-}
-
-SXE.showRemoveButton = function() {
-		document.getElementById("remove").style.display = 'block';
-}
-
-SXE.containsClass = function(elm,cl) {
-	return (elm.className.indexOf(cl) > -1) ? true : false;
-}
-
-SXE.removeClass = function(elm,cl) {
-	if(elm.className == null || elm.className == "" || !SXE.containsClass(elm,cl)) {
-		return true;
-	}
-	var classNames = elm.className.split(" ");
-	var newClassNames = "";
-	for (var x = 0, cnl = classNames.length; x < cnl; x++) {
-		if (classNames[x] != cl) {
-			newClassNames += (classNames[x] + " ");
-		}
-	}
-	elm.className = newClassNames.substring(0,newClassNames.length-1); //removes extra space at the end
-}
-
-SXE.addClass = function(elm,cl) {
-	if(!SXE.containsClass(elm,cl)) elm.className ? elm.className += " " + cl : elm.className = cl;
-	return true;
-}
\ No newline at end of file
--- a/includes/clientside/tinymce/plugins/xhtmlxtras/jscripts/ins.js	Fri Feb 22 12:46:51 2008 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,53 +0,0 @@
- /**
- * $Id: editor_plugin_src.js 42 2006-08-08 14:32:24Z spocke $
- *
- * @author Moxiecode - based on work by Andrew Tetlaw
- * @copyright Copyright © 2004-2007, Moxiecode Systems AB, All rights reserved.
- */
-
-function preinit() {
-	// Initialize
-	tinyMCE.setWindowArg('mce_windowresize', false);
-}
-
-function init() {
-	tinyMCEPopup.resizeToInnerSize();
-	SXE.initElementDialog('ins');
-	if (SXE.currentAction == "update") {
-		setFormValue('datetime', tinyMCE.getAttrib(SXE.updateElement, 'datetime'));
-		setFormValue('cite', tinyMCE.getAttrib(SXE.updateElement, 'cite'));
-		SXE.showRemoveButton();
-	}
-}
-
-function setElementAttribs(elm) {
-	setAllCommonAttribs(elm);
-	setAttrib(elm, 'datetime');
-	setAttrib(elm, 'cite');
-}
-
-function insertIns() {
-	var elm = tinyMCE.getParentElement(SXE.focusElement, 'ins');
-	tinyMCEPopup.execCommand('mceBeginUndoLevel');
-	if (elm == null) {
-		var s = SXE.inst.selection.getSelectedHTML();
-		if(s.length > 0) {
-			tinyMCEPopup.execCommand('mceInsertContent', false, '<ins id="#sxe_temp_ins#">' + s + '</ins>');
-			var elementArray = tinyMCE.getElementsByAttributeValue(SXE.inst.getBody(), 'ins', 'id', '#sxe_temp_ins#');
-			for (var i=0; i<elementArray.length; i++) {
-				var elm = elementArray[i];
-				setElementAttribs(elm);
-			}
-		}
-	} else {
-		setElementAttribs(elm);
-	}
-	tinyMCE.triggerNodeChange();
-	tinyMCEPopup.execCommand('mceEndUndoLevel');
-	tinyMCEPopup.close();
-}
-
-function removeIns() {
-	SXE.removeElement('ins');
-	tinyMCEPopup.close();
-}
\ No newline at end of file
--- a/includes/clientside/tinymce/plugins/xhtmlxtras/langs/en.js	Fri Feb 22 12:46:51 2008 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,42 +0,0 @@
-// UK lang variables
-
-tinyMCE.addToLang('xhtmlxtras',{
-cite_desc : 'Citation',
-abbr_desc : 'Abbreviation',
-acronym_desc : 'Acronym',
-del_desc : 'Deletion',
-ins_desc : 'Insertion',
-attribute_label_title : 'Title',
-attribute_label_id : 'ID',
-attribute_label_class : 'Class',
-attribute_label_style : 'Style',
-attribute_label_cite : 'Cite',
-attribute_label_datetime : 'Date/Time',
-attribute_label_langdir : 'Text Direction',
-attribute_option_ltr : 'Left to right',
-attribute_option_rtl : 'Right to left',
-attribute_label_langcode : 'Language',
-attribute_label_tabindex : 'TabIndex',
-attribute_label_accesskey : 'AccessKey',
-attribute_label_cite : 'Cite',
-attribute_events_tab : 'Events',
-attribute_attrib_tab : 'Attributes',
-general_tab : 'General',
-attrib_tab : 'Attributes',
-events_tab : 'Events',
-fieldset_general_tab : 'General Settings',
-fieldset_attrib_tab : 'Element Attributes',
-fieldset_events_tab : 'Element Events',
-title_ins_element : 'Insertion Element',
-title_del_element : 'Deletion Element',
-title_acronym_element : 'Acronym Element',
-title_abbr_element : 'Abbreviation Element',
-title_cite_element : 'Citation Element',
-remove : 'Remove',
-not_set : '--not set--',
-insert_date : 'Insert current date/time',
-option_ltr : 'Left to right',
-option_rtl : 'Right to left',
-attribs_desc : 'Insert/Edit Attributes',
-attribs_title : 'Insert/Edit Attributes'
-});
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/includes/clientside/tinymce/plugins/xhtmlxtras/langs/en_dlg.js	Fri Feb 22 12:51:53 2008 -0500
@@ -0,0 +1,32 @@
+tinyMCE.addI18n('en.xhtmlxtras_dlg',{
+attribute_label_title:"Title",
+attribute_label_id:"ID",
+attribute_label_class:"Class",
+attribute_label_style:"Style",
+attribute_label_cite:"Cite",
+attribute_label_datetime:"Date/Time",
+attribute_label_langdir:"Text Direction",
+attribute_option_ltr:"Left to right",
+attribute_option_rtl:"Right to left",
+attribute_label_langcode:"Language",
+attribute_label_tabindex:"TabIndex",
+attribute_label_accesskey:"AccessKey",
+attribute_events_tab:"Events",
+attribute_attrib_tab:"Attributes",
+general_tab:"General",
+attrib_tab:"Attributes",
+events_tab:"Events",
+fieldset_general_tab:"General Settings",
+fieldset_attrib_tab:"Element Attributes",
+fieldset_events_tab:"Element Events",
+title_ins_element:"Insertion Element",
+title_del_element:"Deletion Element",
+title_acronym_element:"Acronym Element",
+title_abbr_element:"Abbreviation Element",
+title_cite_element:"Citation Element",
+remove:"Remove",
+insert_date:"Insert current date/time",
+option_ltr:"Left to right",
+option_rtl:"Right to left",
+attribs_title:"Insert/Edit Attributes"
+});
\ No newline at end of file
--- a/includes/clientside/tinymce/plugins/zoom/editor_plugin.js	Fri Feb 22 12:46:51 2008 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1 +0,0 @@
-var TinyMCE_ZoomPlugin={getInfo:function(){return{longname:'Zoom',author:'Moxiecode Systems AB',authorurl:'http://tinymce.moxiecode.com',infourl:'http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/zoom',version:tinyMCE.majorVersion+"."+tinyMCE.minorVersion}},getControlHTML:function(control_name){if(!tinyMCE.isMSIE||tinyMCE.isMSIE5_0||tinyMCE.isOpera)return"";switch(control_name){case"zoom":return'<select id="{$editor_id}_zoomSelect" name="{$editor_id}_zoomSelect" onfocus="tinyMCE.addSelectAccessibility(event, this, window);" onchange="tinyMCE.execInstanceCommand(\'{$editor_id}\',\'mceZoom\',false,this.options[this.selectedIndex].value);" class="mceSelectList">'+'<option value="100%">+ 100%</option>'+'<option value="150%">+ 150%</option>'+'<option value="200%">+ 200%</option>'+'<option value="250%">+ 250%</option>'+'</select>'}return""},execCommand:function(editor_id,element,command,user_interface,value){switch(command){case"mceZoom":tinyMCE.getInstanceById(editor_id).contentDocument.body.style.zoom=value;tinyMCE.getInstanceById(editor_id).contentDocument.body.style.mozZoom=value;return true}return false}};tinyMCE.addPlugin("zoom",TinyMCE_ZoomPlugin);
\ No newline at end of file
--- a/includes/clientside/tinymce/plugins/zoom/editor_plugin_src.js	Fri Feb 22 12:46:51 2008 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,56 +0,0 @@
-/**
- * $Id: editor_plugin_src.js 201 2007-02-12 15:56:56Z spocke $
- *
- * @author Moxiecode
- * @copyright Copyright © 2004-2007, Moxiecode Systems AB, All rights reserved.
- */
-
-var TinyMCE_ZoomPlugin = {
-	getInfo : function() {
-		return {
-			longname : 'Zoom',
-			author : 'Moxiecode Systems AB',
-			authorurl : 'http://tinymce.moxiecode.com',
-			infourl : 'http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/zoom',
-			version : tinyMCE.majorVersion + "." + tinyMCE.minorVersion
-		};
-	},
-
-	/**
-	 * Returns the HTML contents of the zoom control.
-	 */
-	getControlHTML : function(control_name) {
-		if (!tinyMCE.isMSIE || tinyMCE.isMSIE5_0 || tinyMCE.isOpera)
-			return "";
-
-		switch (control_name) {
-			case "zoom":
-				return '<select id="{$editor_id}_zoomSelect" name="{$editor_id}_zoomSelect" onfocus="tinyMCE.addSelectAccessibility(event, this, window);" onchange="tinyMCE.execInstanceCommand(\'{$editor_id}\',\'mceZoom\',false,this.options[this.selectedIndex].value);" class="mceSelectList">' + 
-						'<option value="100%">+ 100%</option>' + 
-						'<option value="150%">+ 150%</option>' + 
-						'<option value="200%">+ 200%</option>' + 
-						'<option value="250%">+ 250%</option>' + 
-						'</select>';
-		}
-
-		return "";
-	},
-
-	/**
-	 * Executes the mceZoom command.
-	 */
-	execCommand : function(editor_id, element, command, user_interface, value) {
-		// Handle commands
-		switch (command) {
-			case "mceZoom":
-				tinyMCE.getInstanceById(editor_id).contentDocument.body.style.zoom = value;
-				tinyMCE.getInstanceById(editor_id).contentDocument.body.style.mozZoom = value;
-				return true;
-		}
-
-		// Pass to next handler in chain
-		return false;
-	}
-};
-
-tinyMCE.addPlugin("zoom", TinyMCE_ZoomPlugin);
--- a/includes/clientside/tinymce/plugins/zoom/readme.txt	Fri Feb 22 12:46:51 2008 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1 +0,0 @@
-Check the TinyMCE documentation for details on this plugin.
--- a/includes/clientside/tinymce/switcher.js	Fri Feb 22 12:46:51 2008 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,51 +0,0 @@
-function readCookie(name) {var nameEQ = name + "=";var ca = document.cookie.split(';');for(var i=0;i < ca.length;i++){var c = ca[i];while (c.charAt(0)==' ') c = c.substring(1,c.length);if (c.indexOf(nameEQ) == 0) return c.substring(nameEQ.length,c.length);}return null;}
-function createCookie(name,value,days){if (days){var date = new Date();date.setTime(date.getTime()+(days*24*60*60*1000));var expires = "; expires="+date.toGMTString();}else var expires = "";document.cookie = name+"="+value+expires+"; path=/";}
-function eraseCookie(name) {createCookie(name,"",-1);}
-
-function initSwitcher()
-{
-  if(readCookie('tmce_demo_mode') == 'tinymce')
-  {
-    switchToMCE();
-  }
-}
-
-function switchToMCE()
-{
-  elem = document.getElementById('tMceEditor');
-  tinyMCE.addMCEControl(elem, 'content', document);
-  createCookie('tmce_demo_mode', 'tinymce', 365);
-}
-
-function switchToText()
-{
-  elem = document.getElementById('tMceEditor');
-  tinyMCE.removeMCEControl('content');
-  createCookie('tmce_demo_mode', 'text', 365);
-}
-
-function switchEditor()
-{
-  if(readCookie('tmce_demo_mode') == 'tinymce')
-  {
-    switchToText();
-  }
-  else
-  {
-    switchToMCE();
-  }
-}
-
-window.onload = initSwitcher;
-
-tinyMCE.init({
-      mode : "exact",
-      elements : '',
-      theme_advanced_resize_horizontal : false,
-      theme_advanced_resizing : true,
-      theme_advanced_toolbar_location : "top",
-      theme_advanced_toolbar_align : "left",
-      theme_advanced_buttons1_add : "fontselect,fontsizeselect",
-      theme_advanced_statusbar_location : 'bottom'
-  });
-
--- a/includes/clientside/tinymce/themes/advanced/about.htm	Fri Feb 22 12:46:51 2008 -0500
+++ b/includes/clientside/tinymce/themes/advanced/about.htm	Fri Feb 22 12:51:53 2008 -0500
@@ -1,35 +1,39 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
 <html xmlns="http://www.w3.org/1999/xhtml">
 <head>
-	<title>{$lang_about_title}</title>
-	<script language="javascript" type="text/javascript" src="../../tiny_mce_popup.js"></script>
-	<script language="javascript" type="text/javascript" src="../../utils/mctabs.js"></script>
-	<script language="javascript" type="text/javascript" src="jscripts/about.js"></script>
-	<base target="_self" />
+	<title>{#advanced_dlg.about_title}</title>
+	<script type="text/javascript" src="../../tiny_mce_popup.js"></script>
+	<script type="text/javascript" src="../../utils/mctabs.js"></script>
+	<script type="text/javascript" src="js/about.js"></script>
 </head>
-<body id="about" onload="tinyMCEPopup.executeOnLoad('init();');" style="display: none">
+<body id="about" style="display: none">
 		<div class="tabs">
 			<ul>
-				<li id="general_tab" class="current"><span><a href="javascript:mcTabs.displayTab('general_tab','general_panel');" onmousedown="return false;">{$lang_about}</a></span></li>
-				<li id="help_tab"><span><a href="javascript:mcTabs.displayTab('help_tab','help_panel');" onmousedown="return false;">{$lang_help}</a></span></li>
-				<li id="plugins_tab"><span><a href="javascript:mcTabs.displayTab('plugins_tab','plugins_panel');" onmousedown="return false;">{$lang_plugins}</a></span></li>
+				<li id="general_tab" class="current"><span><a href="javascript:mcTabs.displayTab('general_tab','general_panel');" onmousedown="return false;">{#advanced_dlg.about_general}</a></span></li>
+				<li id="help_tab" style="display:none"><span><a href="javascript:mcTabs.displayTab('help_tab','help_panel');" onmousedown="return false;">{#advanced_dlg.about_help}</a></span></li>
+				<li id="plugins_tab"><span><a href="javascript:mcTabs.displayTab('plugins_tab','plugins_panel');" onmousedown="return false;">{#advanced_dlg.about_plugins}</a></span></li>
 			</ul>
 		</div>
 
 		<div class="panel_wrapper">
 			<div id="general_panel" class="panel current">
-				<h3>{$lang_about_title}</h3>
-				<p>Version: {$tinymce_version} ({$tinymce_releasedate})</p>
+				<h3>{#advanced_dlg.about_title}</h3>
+				<p>Version: <span id="version"></span> (<span id="date"></span>)</p>
 				<p>TinyMCE is a platform independent web based Javascript HTML WYSIWYG editor control released as Open Source under <a href="../../license.txt" target="_blank">LGPL</a>
 				by Moxiecode Systems AB. It has the ability to convert HTML TEXTAREA fields or other HTML elements to editor instances.</p>
 				<p>Copyright &copy; 2003-2007, <a href="http://www.moxiecode.com" target="_blank">Moxiecode Systems AB</a>, All rights reserved.</p>
 				<p>For more information about this software visit the <a href="http://tinymce.moxiecode.com" target="_blank">TinyMCE website</a>.</p>
 
-				<div id="buttoncontainer"></div>
+				<div id="buttoncontainer">
+					<a href="http://www.moxiecode.com" target="_blank"><img src="http://tinymce.moxiecode.com/images/gotmoxie.png" alt="Got Moxie?" border="0" /></a>
+					<a href="http://sourceforge.net/projects/tinymce/" target="_blank"><img src="http://sourceforge.net/sflogo.php?group_id=103281" alt="Hosted By Sourceforge" border="0" /></a>
+					<a href="http://www.freshmeat.net/projects/tinymce" target="_blank"><img src="http://tinymce.moxiecode.com/images/fm.gif" alt="Also on freshmeat" border="0" /></a>
+				</div>
 			</div>
 
 			<div id="plugins_panel" class="panel">
 				<div id="pluginscontainer">
-					<h3>{$lang_loaded_plugins}</h3>
+					<h3>{#advanced_dlg.about_loaded}</h3>
 
 					<div id="plugintablecontainer">
 					</div>
@@ -45,7 +49,7 @@
 
 		<div class="mceActionPanel">
 			<div style="float: right">
-				<input type="button" id="cancel" name="cancel" value="{$lang_close}" onclick="tinyMCEPopup.close();" />
+				<input type="button" id="cancel" name="cancel" value="{#close}" onclick="tinyMCEPopup.close();" />
 			</div>
 		</div>
 </body>
--- a/includes/clientside/tinymce/themes/advanced/anchor.htm	Fri Feb 22 12:46:51 2008 -0500
+++ b/includes/clientside/tinymce/themes/advanced/anchor.htm	Fri Feb 22 12:51:53 2008 -0500
@@ -1,33 +1,32 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
 <html xmlns="http://www.w3.org/1999/xhtml">
 <head>
-	<title>{$lang_insert_anchor_title}</title>
-	<script language="javascript" type="text/javascript" src="../../tiny_mce_popup.js"></script>
-	<script language="javascript" type="text/javascript" src="jscripts/anchor.js"></script>
+	<title>{#advanced_dlg.anchor_title}</title>
+	<script type="text/javascript" src="../../tiny_mce_popup.js"></script>
+	<script type="text/javascript" src="js/anchor.js"></script>
 	<base target="_self" />
 </head>
-<body onload="tinyMCEPopup.executeOnLoad('init();');" style="display: none">
-<form onsubmit="insertAnchor();return false;" action="#">
-
+<body style="display: none">
+<form onsubmit="AnchorDialog.update();return false;" action="#">
 	<table border="0" cellpadding="4" cellspacing="0">
 		<tr>
-			<td colspan="2" class="title">{$lang_insert_anchor_title}</td>
+			<td colspan="2" class="title">{#advanced_dlg.anchor_title}</td>
 		</tr>
 		<tr>
-			<td nowrap="nowrap">{$lang_insert_anchor_name}:</td>
+			<td nowrap="nowrap">{#advanced_dlg.anchor_name}:</td>
 			<td><input name="anchorName" type="text" id="anchorName" value="" style="width: 200px" /></td>
 		</tr>
 	</table>
 
 	<div class="mceActionPanel">
 		<div style="float: left">
-			<input type="button" id="insert" name="insert" value="{$lang_update}" onclick="insertAnchor();" />
+			<input type="button" id="insert" name="insert" value="{#update}" onclick="AnchorDialog.update();" />
 		</div>
 
 		<div style="float: right">
-			<input type="button" id="cancel" name="cancel" value="{$lang_cancel}" onclick="tinyMCEPopup.close();" />
+			<input type="button" id="cancel" name="cancel" value="{#cancel}" onclick="tinyMCEPopup.close();" />
 		</div>
 	</div>
-
 </form>
 </body>
 </html>
--- a/includes/clientside/tinymce/themes/advanced/charmap.htm	Fri Feb 22 12:46:51 2008 -0500
+++ b/includes/clientside/tinymce/themes/advanced/charmap.htm	Fri Feb 22 12:51:53 2008 -0500
@@ -1,19 +1,19 @@
 <html xmlns="http://www.w3.org/1999/xhtml">
 <head>
-	<title>{$lang_theme_charmap_title}</title>
+	<title>{#advanced_dlg.charmap_title}</title>
 	<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1" />
-	<script language="javascript" type="text/javascript" src="../../tiny_mce_popup.js"></script>
-	<script language="javascript" type="text/javascript" src="jscripts/charmap.js"></script>
+	<script type="text/javascript" src="../../tiny_mce_popup.js"></script>
+	<script type="text/javascript" src="js/charmap.js"></script>
 	<base target="_self" />
 </head>
-<body onload="tinyMCEPopup.executeOnLoad('init();');" style="display: none">
+<body style="display: none">
 <table align="center" border="0" cellspacing="0" cellpadding="2">
     <tr>
-        <td colspan="2" class="title">{$lang_theme_charmap_title}</td>
+        <td colspan="2" class="title">{#advanced_dlg.charmap_title}</td>
     </tr>
     <tr>
-        <td rowspan="2" align="left" valign="top">
-            <script language="javascript" type="text/javascript">renderCharMapHTML();</script>
+        <td id="charmap" rowspan="2" align="left" valign="top">
+			<!-- Chars will be rendered here -->
         </td>
         <td width="100" align="center" valign="top">
             <table border="0" cellpadding="0" cellspacing="0" width="100" style="height: 100px">
--- a/includes/clientside/tinymce/themes/advanced/color_picker.htm	Fri Feb 22 12:46:51 2008 -0500
+++ b/includes/clientside/tinymce/themes/advanced/color_picker.htm	Fri Feb 22 12:51:53 2008 -0500
@@ -1,27 +1,27 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
 <html xmlns="http://www.w3.org/1999/xhtml">
 <head>
-	<title>{$lang_theme_colorpicker_title}</title>
-	<script language="javascript" type="text/javascript" src="../../tiny_mce_popup.js"></script>
-	<script language="javascript" type="text/javascript" src="../../utils/mctabs.js"></script>
-	<script language="javascript" type="text/javascript" src="jscripts/color_picker.js"></script>
-	<link href="css/colorpicker.css" rel="stylesheet" type="text/css" />
+	<title>{#advanced_dlg.colorpicker_title}</title>
+	<script type="text/javascript" src="../../tiny_mce_popup.js"></script>
+	<script type="text/javascript" src="../../utils/mctabs.js"></script>
+	<script type="text/javascript" src="js/color_picker.js"></script>
 	<base target="_self" />
 </head>
-<body onload="tinyMCEPopup.executeOnLoad('init();');" style="display: none">
+<body id="colorpicker" style="display: none">
 	<div class="tabs">
 		<ul>
-			<li id="picker_tab" class="current"><span><a href="javascript:mcTabs.displayTab('picker_tab','picker_panel');" onmousedown="return false;">{$lang_color_picker_tab}</a></span></li>
-			<li id="rgb_tab"><span><a href="#" onclick="generateWebColors();mcTabs.displayTab('rgb_tab','rgb_panel');" onmousedown="return false;">{$lang_web_colors_tab}</a></span></li>
-			<li id="named_tab"><span><a  href="#" onclick="generateNamedColors();javascript:mcTabs.displayTab('named_tab','named_panel');" onmousedown="return false;">{$lang_named_colors_tab}</a></span></li>
+			<li id="picker_tab" class="current"><span><a href="javascript:mcTabs.displayTab('picker_tab','picker_panel');" onmousedown="return false;">{#advanced_dlg.colorpicker_picker_tab}</a></span></li>
+			<li id="rgb_tab"><span><a href="javascript:;" onclick="generateWebColors();mcTabs.displayTab('rgb_tab','rgb_panel');" onmousedown="return false;">{#advanced_dlg.colorpicker_palette_tab}</a></span></li>
+			<li id="named_tab"><span><a  href="javascript:;" onclick="generateNamedColors();javascript:mcTabs.displayTab('named_tab','named_panel');" onmousedown="return false;">{#advanced_dlg.colorpicker_named_tab}</a></span></li>
 		</ul>
 	</div>
 
 	<div class="panel_wrapper">
 		<div id="picker_panel" class="panel current">
 			<fieldset>
-				<legend>{$lang_color_picker}</legend>
+				<legend>{#advanced_dlg.colorpicker_picker_title}</legend>
 				<div id="picker">
-					<img id="colorpicker" src="images/colors.jpg" onclick="computeColor(event)" onmousedown="isMouseDown = true;return false;" onmouseup="isMouseDown = false;" onmousemove="if (isMouseDown && isMouseOver) computeColor(event); return false;" onmouseover="isMouseOver=true;" onmouseout="isMouseOver=false;" />
+					<img id="colors" src="img/colorpicker.jpg" onclick="computeColor(event)" onmousedown="isMouseDown = true;return false;" onmouseup="isMouseDown = false;" onmousemove="if (isMouseDown && isMouseOver) computeColor(event); return false;" onmouseover="isMouseOver=true;" onmouseout="isMouseOver=false;" />
 
 					<div id="light">
 						<!-- Will be filled with divs -->
@@ -34,7 +34,7 @@
 
 		<div id="rgb_panel" class="panel">
 			<fieldset>
-				<legend>{$lang_web_colors}</legend>
+				<legend>{#advanced_dlg.colorpicker_palette_title}</legend>
 				<div id="webcolors">
 					<!-- Gets filled with web safe colors-->
 				</div>
@@ -45,7 +45,7 @@
 
 		<div id="named_panel" class="panel">
 			<fieldset>
-				<legend>{$lang_named_colors}</legend>
+				<legend>{#advanced_dlg.colorpicker_named_title}</legend>
 				<div id="namedcolors">
 					<!-- Gets filled with named colors-->
 				</div>
@@ -53,7 +53,7 @@
 				<br style="clear: both" />
 
 				<div id="colornamecontainer">
-					{$lang_color_name} <span id="colorname"></span>
+					{#advanced_dlg.colorpicker_name} <span id="colorname"></span>
 				</div>
 			</fieldset>
 		</div>
@@ -61,13 +61,13 @@
 
 	<div class="mceActionPanel">
 		<div style="float: left">
-			<input type="button" id="insert" name="insert" value="{$lang_theme_colorpicker_apply}" onclick="insertAction();" />
+			<input type="button" id="insert" name="insert" value="{#apply}" onclick="insertAction();" />
 		</div>
 
 		<div id="preview"></div>
 
 		<div id="previewblock">
-			<label for="color">{$lang_color}</label> <input id="color" type="text" size="8" maxlength="8" class="text" />
+			<label for="color">{#advanced_dlg.colorpicker_color}</label> <input id="color" type="text" size="8" maxlength="8" class="text" />
 		</div>
 	</div>
 </body>
--- a/includes/clientside/tinymce/themes/advanced/css/colorpicker.css	Fri Feb 22 12:46:51 2008 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,53 +0,0 @@
-/* Colorpicker dialog specific CSS */
-
-#preview {
-	float: right;
-	width: 50px;
-	height: 14px;
-	line-height: 1px;
-	border: 1px solid black;
-	margin-left: 5px;
-}
-
-#colorpicker {
-	float: left;
-	cursor: crosshair;
-}
-
-#light {
-	border: 1px solid gray;
-	margin-left: 5px;
-	float: left;
-	width: 15px;
-	cursor: crosshair;
-}
-
-#light div {
-	overflow: hidden;
-}
-
-#previewblock {
-	float: right;
-	padding-left: 10px;
-	height: 20px;
-}
-
-.panel_wrapper div.current {
-	height: 175px;
-}
-
-#namedcolors {
-	width: 150px;
-}
-
-#namedcolors a {
-	display: block;
-	float: left;
-	width: 10px; height: 10px;
-	margin: 1px 1px 0 0;
-	overflow: hidden;
-}
-
-#colornamecontainer {
-	margin-top: 5px;
-}
\ No newline at end of file
--- a/includes/clientside/tinymce/themes/advanced/css/editor_content.css	Fri Feb 22 12:46:51 2008 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,58 +0,0 @@
-/* This file contains the CSS data for the editable area(iframe) of TinyMCE */
-/* You can extend this CSS by adding your own CSS file with the the content_css option */
-
-body, td, pre {
-	font-family: Verdana, Arial, Helvetica, sans-serif;
-	font-size: 10px;
-}
-
-body {
-	background-color: #FFFFFF;
-}
-
-.mceVisualAid {
-	border: 1px dashed #BBBBBB !important;
-}
-
-div.mceVisualAid {
-	background-image:url('../images/spacer.gif');
-	visibility: visible !important;
-}
-
-.mceItemAnchor {
-	width: 12px;
-	line-height: 6px;
-	overflow: hidden;
-	padding-left: 12px;
-	background-image: url('../images/anchor_symbol.gif');
-	background-position: bottom;
-	background-repeat: no-repeat;
-}
-
-/* Important is needed in Gecko browsers inorder to style links */
-/*
-a {
-	color: green !important;
-}
-*/
-
-/* Style selection range colors in Gecko browsers */
-/*
-::-moz-selection {
-	background-color: red;
-	color: green;
-}
-*/
-
-/* MSIE specific */
-
-* html body {
-	scrollbar-3dlight-color: #F0F0EE;
-	scrollbar-arrow-color: #676662;
-	scrollbar-base-color: #F0F0EE;
-	scrollbar-darkshadow-color: #DDDDDD;
-	scrollbar-face-color: #E0E0DD;
-	scrollbar-highlight-color: #F0F0EE;
-	scrollbar-shadow-color: #F0F0EE;
-	scrollbar-track-color: #F5F5F5;
-}
--- a/includes/clientside/tinymce/themes/advanced/css/editor_popup.css	Fri Feb 22 12:46:51 2008 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,331 +0,0 @@
-/* This file contains the CSS data for all popups in TinyMCE */
-
-body {
-	background-color: #F0F0EE;
-	font-family: Verdana, Arial, Helvetica, sans-serif;
-	font-size: 11px;
-	scrollbar-3dlight-color: #F0F0EE;
-	scrollbar-arrow-color: #676662;
-	scrollbar-base-color: #F0F0EE;
-	scrollbar-darkshadow-color: #DDDDDD;
-	scrollbar-face-color: #E0E0DD;
-	scrollbar-highlight-color: #F0F0EE;
-	scrollbar-shadow-color: #F0F0EE;
-	scrollbar-track-color: #F5F5F5;
-	margin: 8px;
-}
-
-td {
-	font-family: Verdana, Arial, Helvetica, sans-serif;
-	font-size: 11px;
-}
-
-input {
-	background: #FFFFFF;
-	border: 1px solid #cccccc;
-}
-
-td, input, select, textarea {
-	font-family: Verdana, Arial, Helvetica, sans-serif;
-	font-size: 10px;
-}
-
-input, select, textarea {
-	border: 1px solid #808080;
-}
-
-.input_noborder {
-	border: 0;
-}
-
-#insert, .updateButton {
-   font-weight: bold;
-   width: 90px;
-   height: 21px;
-   border: 0;
-   background-image: url('../images/insert_button_bg.gif');
-   cursor: pointer;
-}
-
-#cancel {
-   font-weight: bold;
-   width: 90px;
-   height: 21px;
-   border: 0;
-   background-image: url('../images/cancel_button_bg.gif');
-   cursor: pointer;
-}
-
-/* Mozilla only style */
-html>body #insert, html>body #cancel {
-	padding-bottom: 2px;
-}
-
-.title {
-	font-size: 12px;
-	font-weight: bold;
-	color: #2B6FB6;
-}
-
-table.charmap {
-	border-style: solid;
-	border-width: 1px;
-	border-color: #AAAAAA;
-}
-
-td.charmap, td.charmapOver {
-	color: #000000;
-	border-color: #AAAAAA;
-	border-style: solid;
-	border-width: 1px;
-	text-align: center;
-	font-size: 12px;
-}
-
-td.charmapOver {
-	background-color: #CCCCCC;
-	cursor: default;
-}
-
-a.charmap {
-	color: #000000;
-	text-decoration: none
-}
-
-.wordWrapCode {
-	vertical-align: middle;
-	border: 1px none #000000;
-	background-color: transparent;
-}
-
-input.radio {
-	border: 1px none #000000;
-	background-color: transparent;
-	vertical-align: middle;
-}
-
-input.checkbox {
-	border: 1px none #000000;
-	background-color: transparent;
-	vertical-align: middle;
-}
-
-.mceButtonNormal, .mceButtonOver, .mceButtonDown, .mceSeparator, .mceButtonDisabled, .mceButtonSelected {
-	margin-left: 1px;
-}
-
-.mceButtonNormal {
-	border-top: 1px solid;
-	border-left: 1px solid;
-	border-bottom: 1px solid;
-	border-right: 1px solid;
-	border-color: #F0F0EE;
-	cursor: default;
-}
-
-.mceButtonOver {
-	border: 1px solid #0A246A;
-	cursor: default;
-	background-color: #B6BDD2;
-}
-
-.mceButtonDown {
-	cursor: default;
-	border: 1px solid #0A246A;
-	background-color: #8592B5;
-}
-
-.mceButtonDisabled {
-	filter:progid:DXImageTransform.Microsoft.Alpha(opacity=30);
-	-moz-opacity:0.3;
-	opacity: 0.3;
-	border-top: 1px solid;
-	border-left: 1px solid;
-	border-bottom: 1px solid;
-	border-right: 1px solid;
-	border-color: #F0F0EE;
-	cursor: default;
-}
-
-.mceActionPanel {
-	margin-top: 5px;
-}
-
-/* Tabs classes */
-
-.tabs {
-	float: left;
-	width: 100%;
-	line-height: normal;
-	background-image: url("../images/xp/tabs_bg.gif");
-}
-
-.tabs ul {
-	margin: 0;
-	padding: 0 0 0;
-	list-style: none;
-}
-
-.tabs li {
-	float: left;
-	background: url("../images/xp/tab_bg.gif") no-repeat left top;
-	margin: 0;
-	margin-left: 0;
-	margin-right: 2px;
-	padding: 0 0 0 10px;
-	line-height: 18px;
-}
-
-.tabs li.current {
-	background: url("../images/xp/tab_sel_bg.gif") no-repeat left top;
-	margin-right: 2px;
-}
-
-.tabs span {
-	float: left;
-	display: block;
-	background: url("../images/xp/tab_end.gif") no-repeat right top;
-	padding: 0px 10px 0 0;
-}
-
-.tabs .current span {
-	background: url("../images/xp/tab_sel_end.gif") no-repeat right top;
-}
-
-.tabs a {
-	text-decoration: none;
-	font-family: Verdana, Arial;
-	font-size: 10px;
-}
-
-.tabs a:link, .tabs a:visited, .tabs a:hover {
-	color: black;
-}
-
-.tabs a:hover {
-}
-
-.tabs .current {
-}
-
-.tabs .current a, .tabs .current a:link, .tabs .current a:visited {
-}
-
-.panel_wrapper div.panel {
-	display: none;
-}
-
-.panel_wrapper div.current {
-	display: block;
-	width: 100%;
-	height: 300px;
-	overflow: visible; /* Should be auto but that breaks Safari */
-}
-
-.panel_wrapper {
-	border: 1px solid #919B9C;
-	border-top: 0px;
-	padding: 10px;
-	padding-top: 5px;
-	clear: both;
-	background-color: white;
-}
-
-fieldset {
-	border: 1px solid #919B9C;
-	font-family: Verdana, Arial;
-	font-size: 10px;
-	padding: 0;
-	margin: 0;
-	padding: 4px;
-}
-
-legend {
-	color: #2B6FB6;
-	font-weight: bold;
-}
-
-.properties {
-	width: 100%;
-}
-
-.properties .column1 {
-}
-
-.properties .column2 {
-	text-align: left;
-}
-
-a:link, a:visited {
-	color: black;
-}
-
-a:hover {
-	color: #2B6FB6;
-}
-
-#plugintable thead {
-	font-weight: bold;
-	background-color: #DDDDDD;
-}
-
-#plugintable, #about #plugintable td {
-	border: 1px solid #919B9C;
-}
-
-#plugintable {
-	width: 99%;
-	margin-top: 10px;
-}
-
-#pluginscontainer {
-	height: 290px;
-	overflow: auto;
-}
-
-/* MSIE Specific styles */
-
-* html .panel_wrapper {
-	width: 100%;
-}
-
-.column {
-	float: left;
-}
-
-h1, h2, h3, h4 {
-	color: #2B6FB6;
-	margin: 0;
-	padding: 0;
-	padding-top: 5px;
-}
-
-h3 {
-	font-size: 14px;
-}
-
-#link .panel_wrapper, #link div.current {
-	height: 125px;
-}
-
-#image .panel_wrapper, #image div.current {
-	height: 190px;
-}
-
-label.msg { display: none; }
-label.invalid { color: #EE0000; display: inline; }
-input.invalid { border: 1px solid #EE0000; }
-
-/* Disables the advanced tab in the table plugin. */
-/*
-#table #advanced_tab {
-	display: none;
-}
-*/
-
-/* Disables the border input field and label in the table plugin. */
-/*
-#table #border, #table #borderlabel {
-	display: none;
-}
-*/
--- a/includes/clientside/tinymce/themes/advanced/css/editor_ui.css	Fri Feb 22 12:46:51 2008 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,97 +0,0 @@
-/* This file contains the CSS data for the editor UI of TinyMCE instances */
-
-.mceToolbarTop a, .mceToolbarTop a:visited, .mceToolbarTop a:hover, .mceToolbarBottom a, .mceToolbarBottom a:visited, .mceToolbarBottom a:hover {border: 0; margin: 0; padding: 0; background: transparent;}
-.mceSeparatorLine {border: 0; padding: 0; margin-left: 4px; margin-right: 2px;}
-.mceSelectList {font-family: 'MS Sans Serif', sans-serif, Verdana, Arial; font-size: 7pt !important; font-weight: normal; margin-top: 3px; padding: 0; display: inline; vertical-align: top; background-color: #F0F0EE;}
-.mceLabel, .mceLabelDisabled {font-family: 'MS Sans Serif', sans-serif, Verdana, Arial; font-size: 9pt;}
-.mceLabel {color: #000000;}
-.mceLabelDisabled {cursor: text; color: #999999;}
-.mceEditor {background: #F0F0EE; border: 1px solid #cccccc; padding: 0; margin: 0;}
-.mceEditorArea { font-family: 'MS Sans Serif', sans-serif, Verdana, Arial; background: #FFFFFF; padding: 0; margin: 0; }
-.mceToolbarTop, .mceToolbarBottom {background: #F0F0EE; line-height: 1px; font-size: 1px;}
-.mceToolbarTop {border-bottom: 1px solid #cccccc; padding-bottom: 1px;}
-.mceToolbarBottom {border-top: 1px solid #cccccc;}
-.mceToolbarContainer {display: block; position: relative; left: 0; top: 0; width: 100%;}
-.mceStatusbarTop, .mceStatusbarBottom, .mceStatusbar {height: 20px;}
-.mceStatusbarTop .mceStatusbarPathText, .mceStatusbarBottom .mceStatusbarPathText, .mceStatusbar .mceStatusbarPathText {font-family: 'MS Sans Serif', sans-serif, Verdana, Arial; font-size: 9pt; padding: 2px; line-height: 16px; overflow: visible;}
-.mceStatusbarTop {border-bottom: 1px solid #cccccc;}
-.mceStatusbarBottom {border-top: 1px solid #cccccc;}
-.mceStatusbar {border-bottom: 1px solid #cccccc;}
-.mcePathItem, .mcePathItem:link, .mcePathItem:visited, .mcePathItem:hover {text-decoration: none; font-family: 'MS Sans Serif', sans-serif, Verdana, Arial; font-size: 9pt; color: #000000;}
-.mcePathItem:hover {text-decoration: underline;}
-.mceStatusbarPathText {float: left;}
-.mceStatusbarResize {float: right; background-image: url('../images/statusbar_resize.gif'); background-repeat: no-repeat; width: 11px; height: 20px; cursor: se-resize;}
-.mceResizeBox {width: 10px; height: 10px; display: none; border: 1px dotted gray; margin: 0; padding: 0;}
-.mceEditorIframe {border: 0;}
-
-/* Button CSS rules */
-
-a.mceButtonDisabled img, a.mceButtonNormal img, a.mceButtonSelected img {width: 20px; height: 20px; cursor: default; margin-top: 1px; margin-left: 1px;}
-a.mceButtonDisabled img {border: 0 !important;}
-a.mceButtonNormal img, a.mceButtonSelected img {border: 1px solid #F0F0EE !important;}
-a.mceButtonSelected img {border: 1px solid #6779AA !important; background-color: #D4D5D8;}
-a.mceButtonNormal img:hover, a.mceButtonSelected img:hover {border: 1px solid #0A246A !important; cursor: default; background-color: #B6BDD2;}
-a.mceButtonDisabled img {-moz-opacity:0.3; opacity: 0.3; border: 1px solid #F0F0EE !important; cursor: default;}
-a.mceTiledButton img {background-image: url('../images/buttons.gif'); background-repeat: no-repeat;}
-
-/* Menu button CSS rules */
-
-span.mceMenuButton img, span.mceMenuButtonSelected img {border: 1px solid #F0F0EE; margin-left: 1px;}
-span.mceMenuButtonSelected img {border: 1px solid #6779AA; background-color: #B6BDD2;}
-span.mceMenuButtonSelected img.mceMenuButton {border: 1px solid #F0F0EE; background-color: transparent;}
-span.mceMenuButton img.mceMenuButton, span.mceMenuButtonSelected img.mceMenuButton {border-left: 0; margin-left: 0;}
-span.mceMenuButton:hover img, span.mceMenuButtonSelected:hover img {border: 1px solid #0A246A; background-color: #B6BDD2;}
-span.mceMenuButton:hover img.mceMenuButton, span.mceMenuButtonSelected:hover img.mceMenuButton {border-left: 0;}
-span.mceMenuButtonFocus img {border: 1px solid gray; border-right: 0; margin-left: 1px; background-color: #F5F4F2;}
-span.mceMenuButtonFocus img.mceMenuButton {border: 1px solid gray; border-left: 1px solid #F5F4F2; margin-left: 0;}
-span.mceMenuHover img {border: 1px solid #0A246A; background-color: #B6BDD2;}
-span.mceMenuButtonSelected.mceMenuHover img.mceMenuButton {border: 1px solid #0A246A; background-color: #B6BDD2; border-left: 0;}
-
-/* Menu */
-
-.mceMenu {position: absolute; left: 0; top: 0; display: none; z-index: 1000; background-color: white; border: 1px solid gray; font-weight: normal;}
-.mceMenu a, .mceMenuTitle, .mceMenuDisabled {display: block; width: 100%; text-decoration: none; background-color: white; font-family: Tahoma, Verdana, Arial, Helvetica; font-size: 11px; line-height: 20px; color: black;}
-.mceMenu a:hover {background-color: #B6BDD2; color: black; text-decoration: none !important;}
-.mceMenu span {padding-left: 10px; padding-right: 10px; display: block; line-height: 20px;}
-.mceMenuSeparator {border-bottom: 1px solid gray; background-color: gray; height: 1px;}
-.mceMenuTitle span {padding-left: 5px;}
-.mceMenuTitle {background-color: #DDDDDD; font-weight: bold;}
-.mceMenuDisabled {color: gray;}
-span.mceMenuSelectedItem {background-image: url('../images/menu_check.gif'); background-repeat: no-repeat; background-position: 5px 8px; padding-left: 20px;}
-span.mceMenuCheckItem {padding-left: 20px;}
-span.mceMenuLine {display: block; position: absolute; left: 0; top: -1px; background-color: #F5F4F2; width: 30px; height: 1px; overflow: hidden; padding-left: 0; padding-right: 0;}
-.mceColors table, .mceColors td {margin: 0; padding: 2px;}
-a.mceMoreColors {width: auto; padding: 0; margin: 0 3px 3px 3px; text-align: center; border: 1px solid white; text-decoration: none !important;}
-.mceColorPreview {position: absolute; overflow:hidden; left: 0; top: 0; margin-left: 3px; margin-top: 15px; width: 16px; height: 4px; background-color: red;}
-a.mceMoreColors:hover {border: 1px solid #0A246A;}
-.mceColors td a {width: 9px; height: 9px; overflow: hidden; border: 1px solid #808080;}
-
-/* MSIE 6 specific rules */
-
-* html a.mceButtonNormal img, * html a.mceButtonSelected img, * html a.mceButtonDisabled img {border: 0 !important; margin-top: 2px; margin-bottom: 1px;}
-* html a.mceButtonDisabled img {/* \*/ filter:progid:DXImageTransform.Microsoft.Alpha(opacity=30); /* */ border: 0 !important;}
-* html a.mceButtonDisabled {border: 1px solid #F0F0EE !important;}
-* html a.mceButtonNormal, * html a.mceButtonSelected {border: 1px solid #F0F0EE !important; cursor: default;}
-* html a.mceButtonSelected {border: 1px solid #6779AA !important; background-color: #D4D5D8;}
-* html a.mceButtonNormal:hover, * html a.mceButtonSelected:hover {border: 1px solid #0A246A !important; background-color: #B6BDD2; cursor: default;}
-* html .mceSelectList {margin-top: 2px;}
-* html span.mceMenuButton, * html span.mceMenuButtonFocus {position: relative; left: 0; top: 0;}
-* html span.mceMenuButton img, * html span.mceMenuButtonSelected img, * html span.mceMenuButtonFocus img {position: relative; top: 1px;}
-* html a.mceMoreColors {width: auto;}
-* html .mceColors td a {width: 10px; height: 10px;}
-* html .mceColorPreview {margin-left: 2px; margin-top: 14px;}
-
-/* MSIE 7 specific rules */
-
-*:first-child+html a.mceButtonNormal img, *:first-child+html a.mceButtonSelected img, *:first-child+html a.mceButtonDisabled img {border: 0 !important; margin-top: 2px; margin-bottom: 1px;}
-*:first-child+html a.mceButtonDisabled img { /* \*/ filter:progid:DXImageTransform.Microsoft.Alpha(opacity=30); /* */ border: 0 !important;}
-*:first-child+html a.mceButtonDisabled {border: 1px solid #F0F0EE !important;}
-*:first-child+html a.mceButtonNormal, *:first-child+html a.mceButtonSelected {border: 1px solid #F0F0EE !important; cursor: default;}
-*:first-child+html a.mceButtonSelected {border: 1px solid #6779AA !important; background-color: #D4D5D8;}
-*:first-child+html a.mceButtonNormal:hover, *:first-child+html a.mceButtonSelected:hover {border: 1px solid #0A246A !important; background-color: #B6BDD2; cursor: default;}
-*:first-child+html .mceSelectList {margin-top: 2px;}
-*:first-child+html span.mceMenuButton, *:first-child+html span.mceMenuButtonFocus {position: relative; left: 0; top: 0;}
-*:first-child+html span.mceMenuButton img, *:first-child+html span.mceMenuButtonSelected img, *:first-child+html span.mceMenuButtonFocus img {position: relative; top: 1px;}
-*:first-child+html a.mceMoreColors {width: 137px;}
-*:first-child+html .mceColors td a {width: 10px; height: 10px;}
-*:first-child+html .mceColorPreview {margin: 0; padding-left: 4px; margin-top: 14px; width: 14px;}
--- a/includes/clientside/tinymce/themes/advanced/docs/en/about.htm	Fri Feb 22 12:46:51 2008 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,31 +0,0 @@
-<html xmlns="http://www.w3.org/1999/xhtml">
-<HEAD>
-<TITLE>About TinyMCE</TITLE>
-<link href="style.css" rel="stylesheet" type="text/css">
-</HEAD>
-
-<BODY>
-
-<table width="100%" border="0" cellpadding="1" cellspacing="3" class="pageheader">
-  <tr> 
-    <td><span class="title">About TinyMCE</span></td>
-    <td align="right"><a href="index.htm"><acronym title="Table of contents">TOC</acronym></a></td>
-  </tr>
-</table>
-<hr noshade>
-<br>
-TinyMCE is a small WYSIWYG editor control for web browsers such as MSIE or Mozilla 
-that enables you to edit HTML contents in a more user friendly way. It has common 
-features that are found in most word processors and should not be difficult to 
-use.<br>
-<br>
-<hr noshade>
-<table width="100%" border="0" cellpadding="1" cellspacing="3" class="pagefooter">
-  <tr> 
-    <td>Go to: <a href="index.htm">Table of contents</a></td>
-    <td align="right"><a href="#">Top</a></td>
-  </tr>
-</table>
-<br>
-</BODY>
-</HTML>
--- a/includes/clientside/tinymce/themes/advanced/docs/en/common_buttons.htm	Fri Feb 22 12:46:51 2008 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,162 +0,0 @@
-<html xmlns="http://www.w3.org/1999/xhtml">
-<HEAD>
-<TITLE>Common buttons</TITLE>
-<link href="style.css" rel="stylesheet" type="text/css">
-</HEAD>
-
-<BODY>
-
-<table width="100%" border="0" cellpadding="1" cellspacing="3" class="pageheader">
-  <tr> 
-    <td><span class="title">Common buttons</span></td>
-    <td align="right"><a href="index.htm"><acronym title="Table of contents">TOC</acronym></a></td>
-  </tr>
-</table>
-<hr noshade>
-<br>
-Below is a short description about each button.
-<br>
-<br>
-<table border="1" cellpadding="3" cellspacing="0">
-  <tr>
-    <td><img src="../../images/bold.gif" width="20" height="20" alt="Bold text icon" /></td>
-    <td>Bold text style (Ctrl+B).</td>
-  </tr>
-  <tr>
-    <td><img src="../../images/italic.gif" width="20" height="20" alt="Italic text icon" /></td>
-    <td>Italic text style (Ctrl+I).</td>
-  </tr>
-  <tr>
-    <td><img src="../../images/underline.gif" width="20" height="20" alt="Underline text icon." /></td>
-    <td>Underline text style (Ctrl+U).</td>
-  </tr>
-  <tr>
-    <td><img src="../../images/strikethrough.gif" width="20" height="20" alt="Strikethrough text icon." /></td>
-    <td>Strikethrough text style.</td>
-  </tr>
-  <tr>
-    <td><img src="../../images/justifyleft.gif" width="20" height="20" alt="Align left icon." /></td>
-    <td>Align left.</td>
-  </tr>
-  <tr>
-    <td><img src="../../images/justifycenter.gif" width="20" height="20" alt="Align center icon." /></td>
-    <td>Align center.</td>
-  </tr>
-  <tr>
-    <td><img src="../../images/justifyright.gif" width="20" height="20" alt="Align right icon." /></td>
-    <td>Align right.</td>
-  </tr>
-  <tr>
-    <td><img src="../../images/justifyfull.gif" width="20" height="20" alt="Align full icon." /></td>
-    <td>Align full.</td>
-  </tr>
-  <tr>
-    <td><img src="../../images/bullist.gif" width="20" height="20" alt="Unordered list/bullet list icon." /></td>
-    <td>Unordered list/bullet list.</td>
-  </tr>
-  <tr>
-    <td><img src="../../images/numlist.gif" width="20" height="20" alt="Ordered list/numbered list icon." /></td>
-    <td>Ordered list/numbered list</td>
-  </tr>
-  <tr>
-    <td><img src="../../images/outdent.gif" width="20" height="20" alt="Outdent/decrease indentation icon." /></td>
-    <td>Outdent/decrease indentation.</td>
-  </tr>
-  <tr>
-    <td><img src="../../images/indent.gif" width="20" height="20" alt="Indent/increase indentation icon." /></td>
-    <td>Indent/increase indentation.</td>
-  </tr>
-  <tr>
-    <td><img src="../../images/undo.gif" width="20" height="20" alt="Undo the last operation." /></td>
-    <td>Undo the last operation (Ctrl+Z).</td>
-  </tr>
-  <tr>
-    <td><img src="../../images/redo.gif" width="20" height="20" alt="Redo the last operation icon." /></td>
-    <td>Redo the last operation (Ctrl+Y).</td>
-  </tr>
-  <tr>
-    <td><img src="../../images/link.gif" width="20" height="20" alt="Insert a new link icon." /></td>
-    <td>Insert a new link, read more about this function in the <a href="insert_link_button.htm">Insert 
-      link section</a>.</td>
-  </tr>
-  <tr>
-    <td><img src="../../images/unlink.gif" width="20" height="20" alt="Unlinks the current selection icon." /></td>
-    <td>Unlinks the current selection/removes all selected links.</td>
-  </tr>
-  <tr>
-    <td><img src="../../images/anchor.gif" width="20" height="20" alt="Insert a new anchor icon." /></td>
-    <td>Insert a new anchor, read more about this function in the <a href="insert_anchor_button.htm">Insert anchor section.</a></td>
-  </tr>
-  <tr>
-    <td><img src="../../images/image.gif" width="20" height="20" alt="Insert a new image icon." /></td>
-    <td>Insert a new image, read more about this function in the <a href="insert_image_button.htm">Insert 
-      image section</a>.</td>
-  </tr>
-  <tr>
-    <td><img src="../../images/cleanup.gif" width="20" height="20" alt="Cleanup code icon." /></td>
-    <td>Cleanup code/Removes unwanted formating. This function is useful when 
-      you copy contents from for example a office product.</td>
-  </tr>
-  <tr>
-    <td><img src="../../images/help.gif" width="20" height="20" alt="Show help icon." /></td>
-    <td>Shows this help window.</td>
-  </tr>
-  <tr>
-    <td><img src="../../images/code.gif" width="20" height="20" alt="Source code editor icon." /></td>
-    <td>Opens HTML source code editor. </td>
-  </tr>
-  <tr>
-    <td><img src="../../../../plugins/table/images/table.gif" width="20" height="20" alt="Insert table icon." /></td>
-    <td>Inserts a new table at the current location. </td>
-  </tr>
-  <tr>
-    <td><img src="../../../../plugins/table/images/table_insert_row_before.gif" width="20" height="20" alt="Adds a row above icon." /></td>
-    <td>Adds a row above the current one. </td>
-  </tr>
-  <tr>
-    <td><img src="../../../../plugins/table/images/table_insert_row_after.gif" width="20" height="20" alt="Adds a row under icon." /></td>
-    <td>Adds a row under the current one. </td>
-  </tr>
-  <tr>
-    <td><img src="../../../../plugins/table/images/table_delete_row.gif" width="20" height="20" alt="Remove row icon." /></td>
-    <td>Removes the row. </td>
-  </tr>
-  <tr>
-    <td><img src="../../../../plugins/table/images/table_insert_col_before.gif" width="20" height="20" alt="Add column before icon." /></td>
-    <td>Adds a column before the current one.</td>
-  </tr>
-  <tr>
-    <td><img src="../../../../plugins/table/images/table_insert_col_after.gif" width="20" height="20" alt="Add column after icon." /></td>
-    <td>Adds a column after the current one.</td>
-  </tr>
-  <tr>
-    <td><img src="../../../../plugins/table/images/table_delete_col.gif" width="20" height="20" alt="Remove column icon." /></td>
-    <td>Removes the current column.</td>
-  </tr>
-  <tr>
-    <td><img src="../../images/hr.gif" width="20" height="20" alt="Insert horizontal ruler icon." /></td>
-    <td>Inserts a new horizontal ruler </td>
-  </tr>
-  <tr>
-    <td><img src="../../images/removeformat.gif" width="20" height="20" alt="Remove formatting icon." /></td>
-    <td>Removes formatting from the selection. </td>
-  </tr>
-  <tr>
-    <td><img src="../../images/sub.gif" width="20" height="20" alt="Subscript icon." /></td>
-    <td>Makes the selection to be subscript. </td>
-  </tr>
-  <tr>
-    <td><img src="../../images/sup.gif" width="20" height="20" alt="Superscript icon." /></td>
-    <td>Makes the selection to be superscripted. </td>
-  </tr>
-</table>
-<br>
-<hr noshade="noshade" />
-<table width="100%" border="0" cellpadding="1" cellspacing="3" class="pagefooter">
-  <tr> 
-    <td>Go to: <a href="index.htm">Table of contents</a></td>
-    <td align="right"><a href="#">Top</a></td>
-  </tr>
-</table>
-</BODY>
-</HTML>
--- a/includes/clientside/tinymce/themes/advanced/docs/en/create_accessible_content.htm	Fri Feb 22 12:46:51 2008 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,45 +0,0 @@
-<html xmlns="http://www.w3.org/1999/xhtml">
-<HEAD>
-<TITLE>Insert table button</TITLE>
-<link href="style.css" rel="stylesheet" type="text/css">
-</HEAD>
-
-<BODY>
-
-<table width="100%" border="0" cellpadding="1" cellspacing="3" class="pageheader">
-  <tr> 
-    <td><span class="title">Create accessible content</span></td>
-    <td align="right"><a href="index.htm"><acronym title="Table of contents">TOC</acronym></a></td>
-  </tr>
-</table>
-<hr noshade>
-<p>TinyMCE can create HTML content that will be accessible to all users, including those with disabilities using assistive technologies, as well as those using text-based browsers, or those browsing the Web with images turned off. </p>
-
-<p><strong>Things you can do to make your content accessible:</strong></p>
-<ol>
-<li><strong>Include an Image Description:</strong> Blind users, or others who are unable to view images, will rely on the Image Description (or Alt text) to take the place of the image. If an image contains no meaning, such as a decoration or a spacer image, leave the Image Description empty. TinyMCE will then insert an empty Alt text attribute that will force assistive technologies to ignore the image. <br /><br /></li>
-
-<li> <strong>Add Scope to data table header cells:</strong> In the table cell editor dialog window, choose a Scope when creating Header cells so the column or row label in that cell becomes explicitely associated with its data cells. Table cell headers will then be announced with each data cell, making it easier for blind users using a screen reader to understand what the content of each cell represents. <br /><br /></li>
-
-<li><strong> Structure content with properly nested headings:</strong> In the format selection menu choose Heading 1 to Heading 6 to represent headings in your content,  rather than using other font formating options. Blind users using a screen reader can then extract the headings from the page to generate a summary of the content it contains, and use those headings to navigate quickly to subsections within the page.<br /><br /></li>
-
-<li><strong> Include alternate content:</strong> Create an alternate page for non-HTML content such as Flash, Java applets, or  embedded movies. This might be a static image, with a description of the image, and a description of the content that would have appeared in its place. An alternate HTML page could also be created, and a link to it included next to the non-HTML object. This will ensure that the content will be accessible to users of assistive technologies that can not view or play the content, and ensure the content will be available to those who do not have the appropriate plugin or helper application installed.<br /><br /></li>
-
-<li><strong> Check accessbility: </strong> When the AChecker plugin is installed with TinyMCE, click on the Check Accessibility button to generate a report of potential accessibility problems.<br /><br /></li>
-
-</ol>
-
-<p>See the <a href="http://checker.atrc.utoronto.ca" target="_new">AChecker Web Site</a> for further details about creating content that will be accessible to all users.<br />
-</p>
-
-<hr noshade>
-<table width="100%" border="0" cellpadding="1" cellspacing="3" class="pagefooter">
-  <tr> 
-    <td>Go to: <a href="index.htm">Table of contents</a></td>
-    <td align="right"><a href="#">Top</a></td>
-  </tr>
-</table>
-
-<br>
-</BODY>
-</HTML>
Binary file includes/clientside/tinymce/themes/advanced/docs/en/images/insert_anchor_window.gif has changed
Binary file includes/clientside/tinymce/themes/advanced/docs/en/images/insert_image_window.gif has changed
Binary file includes/clientside/tinymce/themes/advanced/docs/en/images/insert_link_window.gif has changed
Binary file includes/clientside/tinymce/themes/advanced/docs/en/images/insert_table_window.gif has changed
--- a/includes/clientside/tinymce/themes/advanced/docs/en/index.htm	Fri Feb 22 12:46:51 2008 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,27 +0,0 @@
-<html xmlns="http://www.w3.org/1999/xhtml">
-<HEAD>
-<TITLE>Help Index</TITLE>
-<link href="style.css" rel="stylesheet" type="text/css">
-</HEAD>
-<BODY onload="window.focus();">
-<table width="100%" border="0" cellpadding="1" cellspacing="3" class="pageheader">
-  <tr> 
-    <td><span class="title">Table of contents</span></td>
-    <td align="right">&nbsp;</td>
-  </tr>
-</table>
-<hr noshade>
-<br>
-Click the links below to go to the different help sections. 
-<ul class="toc_ul">
-  <li class="toc_li"><a href="about.htm">About TinyMCE</a></li>
-  <li class="toc_li"><a href="common_buttons.htm">Common buttons</a></li>
-  <li class="toc_li"><a href="insert_image_button.htm">Insert image button</a></li>
-  <li class="toc_li"><a href="insert_link_button.htm">Insert link button</a></li>
-  <li class="toc_li"><a href="insert_anchor_button.htm">Insert anchor button</a></li>
-  <li class="toc_li"><a href="insert_table_button.htm">Insert table button</a></li>
- <li class="toc_li"><a href="create_accessible_content.htm">Create accessible content</a></li>
-</ul>
-<hr noshade>
-</BODY>
-</HTML>
--- a/includes/clientside/tinymce/themes/advanced/docs/en/insert_anchor_button.htm	Fri Feb 22 12:46:51 2008 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,32 +0,0 @@
-<html xmlns="http://www.w3.org/1999/xhtml">
-<HEAD>
-<TITLE>Insert anchor button</TITLE>
-<link href="style.css" rel="stylesheet" type="text/css">
-</HEAD>
-
-<BODY>
-
-<table width="100%" border="0" cellpadding="1" cellspacing="3" class="pageheader">
-  <tr> 
-    <td><span class="title">Insert anchor button</span></td>
-    <td align="right"><a href="index.htm"><acronym title="Table of contents">TOC</acronym></a></td>
-  </tr>
-</table>
-<hr noshade>
-<br>
-This button opens a new window with the insert/edit anchor function.<br>
-<br>
-<img src="images/insert_anchor_window.gif" width="330" height="139" alt="Anchor dialog/window" /><br>
-<br>
-There are one field in this window, this is where you enter the name of you anchor point. Remember the anchor name needs to be unique. <br>
-<br>
-<hr noshade>
-<table width="100%" border="0" cellpadding="1" cellspacing="3" class="pagefooter">
-  <tr> 
-    <td>Go to: <a href="index.htm">Table of contents</a></td>
-    <td align="right"><a href="#">Top</a></td>
-  </tr>
-</table>
-<br>
-</BODY>
-</HTML>
--- a/includes/clientside/tinymce/themes/advanced/docs/en/insert_image_button.htm	Fri Feb 22 12:46:51 2008 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,65 +0,0 @@
-<html xmlns="http://www.w3.org/1999/xhtml">
-<HEAD>
-<TITLE>Insert image button</TITLE>
-<link href="style.css" rel="stylesheet" type="text/css">
-</HEAD>
-
-<BODY>
-
-<table width="100%" border="0" cellpadding="1" cellspacing="3" class="pageheader">
-  <tr> 
-    <td><span class="title">Insert image button</span></td>
-    <td align="right"><a href="index.htm"><acronym title="Table of contents">TOC</acronym></a></td>
-  </tr>
-</table>
-<hr noshade>
-<br>
-The insert image button opens the window shown below.<br>
-<br>
-<img src="images/insert_image_window.gif" alt="Insert image dialog/window" /><br>
-<br>
-You simply enter a URL to the image you want to link to and enter a image description, 
-this is then displayed as an alternative text descripton of the image on the page.<br>
-<br>
-<strong>Field descriptions:</strong><br>
-<table border="1" cellspacing="0">
-  <tr>
-    <td width="150"><strong>Image URL </strong></td>
-    <td>URL/path to the image.</td>
-  </tr>
-  <tr>
-    <td width="150"><strong>Image description </strong></td>
-    <td>Alternative description of image contents.</td>
-  </tr>
-  <tr>
-    <td><strong>Dimentions</strong></td>
-    <td>Image width/height. </td>
-  </tr>
-  <tr>
-    <td><strong>Alignment</strong></td>
-    <td>Image alignment, useful when wrapping text around images.</td>
-  </tr>
-  <tr>
-    <td><strong>Border</strong></td>
-    <td>Border thickness. </td>
-  </tr>
-  <tr>
-    <td><strong>VSpace</strong></td>
-    <td>Vertical space, useful when wrapping text around images.</td>
-  </tr>
-  <tr>
-    <td><strong>HSpace</strong></td>
-    <td>Horizontal space, useful when wrapping text around images.</td>
-  </tr>
-</table>
-<br>
-<hr noshade>
-<table width="100%" border="0" cellpadding="1" cellspacing="3" class="pagefooter">
-  <tr> 
-    <td>Go to: <a href="index.htm">Table of contents</a></td>
-    <td align="right"><a href="#">Top</a></td>
-  </tr>
-</table>
-<br>
-</BODY>
-</HTML>
--- a/includes/clientside/tinymce/themes/advanced/docs/en/insert_link_button.htm	Fri Feb 22 12:46:51 2008 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,33 +0,0 @@
-<html xmlns="http://www.w3.org/1999/xhtml">
-<HEAD>
-<TITLE>Insert link button</TITLE>
-<link href="style.css" rel="stylesheet" type="text/css">
-</HEAD>
-
-<BODY>
-
-<table width="100%" border="0" cellpadding="1" cellspacing="3" class="pageheader">
-  <tr> 
-    <td><span class="title">Insert link button</span></td>
-    <td align="right"><a href="index.htm"><acronym title="Table of contents">TOC</acronym></a></td>
-  </tr>
-</table>
-<hr noshade>
-<br>
-This button opens a new window with the insert/edit link function.<br>
-<br>
-<img src="images/insert_link_window.gif" width="330" height="159" alt="Insert link dialog/window" /><br>
-<br>
-There are two fields in this window the first one &quot;Link URL&quot; is the 
-URL of the link. The target enables you to select how the link is to be opened.<br>
-<br>
-<hr noshade>
-<table width="100%" border="0" cellpadding="1" cellspacing="3" class="pagefooter">
-  <tr> 
-    <td>Go to: <a href="index.htm">Table of contents</a></td>
-    <td align="right"><a href="#">Top</a></td>
-  </tr>
-</table>
-<br>
-</BODY>
-</HTML>
--- a/includes/clientside/tinymce/themes/advanced/docs/en/insert_table_button.htm	Fri Feb 22 12:46:51 2008 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,71 +0,0 @@
-<html xmlns="http://www.w3.org/1999/xhtml">
-<HEAD>
-<TITLE>Insert table button</TITLE>
-<link href="style.css" rel="stylesheet" type="text/css">
-</HEAD>
-
-<BODY>
-
-<table width="100%" border="0" cellpadding="1" cellspacing="3" class="pageheader">
-  <tr> 
-    <td><span class="title">Insert table button</span></td>
-    <td align="right"><a href="index.htm"><acronym title="Table of contents">TOC</acronym></a></td>
-  </tr>
-</table>
-<hr noshade>
-<br>
-The insert table button opens the window shown below. This action enables you to create tables. <br>
-<br>
-<img src="images/insert_table_window.gif" width="340" height="229" alt="Image of table window" /><br>
-<br>
-<strong>Field descriptions:</strong><br>
-<table border="1" cellspacing="0">
-  <tr>
-    <td width="150"><strong>Columns</strong></td>
-    <td>Number of columns in the  table. </td>
-  </tr>
-  <tr>
-    <td width="150"><strong>Rows</strong></td>
-    <td>Number of rows in the new table.</td>
-  </tr>
-  <tr>
-    <td><strong>Cellpadding</strong></td>
-    <td>Cellpadding of the table . </td>
-  </tr>
-  <tr>
-    <td><strong>Cellspacing</strong></td>
-    <td>Cellspacing of the table .</td>
-  </tr>
-  <tr>
-    <td><strong>Alignment</strong></td>
-    <td>Table alignment . </td>
-  </tr>
-  <tr>
-    <td><strong>Border</strong></td>
-    <td>Border thinkness of table.</td>
-  </tr>
-  <tr>
-    <td><strong>Width</strong></td>
-    <td>Width in pixels of table .</td>
-  </tr>
-  <tr>
-    <td><strong>Height</strong></td>
-    <td>Height in pixels of table.</td>
-  </tr>
-  <tr>
-    <td><strong>Class</strong></td>
-    <td>Style or CSS class of table.</td>
-  </tr>
-</table>
-<br>
-<br>
-<hr noshade>
-<table width="100%" border="0" cellpadding="1" cellspacing="3" class="pagefooter">
-  <tr> 
-    <td>Go to: <a href="index.htm">Table of contents</a></td>
-    <td align="right"><a href="#">Top</a></td>
-  </tr>
-</table>
-<br>
-</BODY>
-</HTML>
--- a/includes/clientside/tinymce/themes/advanced/docs/en/style.css	Fri Feb 22 12:46:51 2008 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,28 +0,0 @@
-body { background-color: #FFFFFF; }
-body, td, .content { font-family: Verdana, Arial, helvetica, sans-serif; font-size: 12px; }
-.title { font-family: Verdana, Arial, helvetica, sans-serif; font-size: 16px; font-weight: bold; }
-.subtitle { font-size: 12px; font-weight: bold; }
-
-.toc_ul, .toc_li { margin-left: 8px; line-height: 16px; }
-.step_ol, .step_li { margin-left: 11px; line-height: 16px; }
-img { border: #000000 solid 1px; }
-
-a:visited { color: #666666; text-decoration: underline; }
-a:active { color: #666666; text-decoration: underline; }
-a:hover { color: #666666; text-decoration: underline; }
-a { color: #666666; text-decoration: underline; }
-
-.pageheader { border: #E0E0E0 solid 1px; }
-.pagefooter { border: #E0E0E0 solid 1px; }
-.sample { background-color: #FFFFFF; border: #000000 solid 1px; }
-.samplecontent { font-size: 10px; }
-
-.code { background-color: #FFFFFF; border: #000000 solid 1px; }
-.codecontent { font-size: 10px; }
-.codecontent a:visited { color: #666666; text-decoration: none; font-weight: bold }
-.codecontent a:active { color: #666666; text-decoration: none; font-weight: bold  }
-.codecontent a:hover { color: #666666; text-decoration: none; font-weight: bold  }
-.codecontent a { color: #666666; text-decoration: none; font-weight: bold  }
-
-hr { height: 1px; }
-
--- a/includes/clientside/tinymce/themes/advanced/editor_template.js	Fri Feb 22 12:46:51 2008 -0500
+++ b/includes/clientside/tinymce/themes/advanced/editor_template.js	Fri Feb 22 12:51:53 2008 -0500
@@ -1,1 +1,1 @@
-tinyMCE.importThemeLanguagePack('advanced');var TinyMCE_AdvancedTheme={_defColors:"000000,993300,333300,003300,003366,000080,333399,333333,800000,FF6600,808000,008000,008080,0000FF,666699,808080,FF0000,FF9900,99CC00,339966,33CCCC,3366FF,800080,999999,FF00FF,FFCC00,FFFF00,00FF00,00FFFF,00CCFF,993366,C0C0C0,FF99CC,FFCC99,FFFF99,CCFFCC,CCFFFF,99CCFF,CC99FF,FFFFFF",_autoImportCSSClasses:true,_resizer:{},_buttons:[['bold','{$lang_bold_img}','lang_bold_desc','Bold'],['italic','{$lang_italic_img}','lang_italic_desc','Italic'],['underline','{$lang_underline_img}','lang_underline_desc','Underline'],['strikethrough','strikethrough.gif','lang_striketrough_desc','Strikethrough'],['justifyleft','justifyleft.gif','lang_justifyleft_desc','JustifyLeft'],['justifycenter','justifycenter.gif','lang_justifycenter_desc','JustifyCenter'],['justifyright','justifyright.gif','lang_justifyright_desc','JustifyRight'],['justifyfull','justifyfull.gif','lang_justifyfull_desc','JustifyFull'],['bullist','bullist.gif','lang_bullist_desc','InsertUnorderedList'],['numlist','numlist.gif','lang_numlist_desc','InsertOrderedList'],['outdent','outdent.gif','lang_outdent_desc','Outdent'],['indent','indent.gif','lang_indent_desc','Indent'],['cut','cut.gif','lang_cut_desc','Cut'],['copy','copy.gif','lang_copy_desc','Copy'],['paste','paste.gif','lang_paste_desc','Paste'],['undo','undo.gif','lang_undo_desc','Undo'],['redo','redo.gif','lang_redo_desc','Redo'],['link','link.gif','lang_link_desc','mceLink',true],['unlink','unlink.gif','lang_unlink_desc','unlink'],['image','image.gif','lang_image_desc','mceImage',true],['cleanup','cleanup.gif','lang_cleanup_desc','mceCleanup'],['help','help.gif','lang_help_desc','mceHelp'],['code','code.gif','lang_theme_code_desc','mceCodeEditor'],['hr','hr.gif','lang_theme_hr_desc','inserthorizontalrule'],['removeformat','removeformat.gif','lang_theme_removeformat_desc','removeformat'],['sub','sub.gif','lang_theme_sub_desc','subscript'],['sup','sup.gif','lang_theme_sup_desc','superscript'],['forecolor','forecolor.gif','lang_theme_forecolor_desc','forecolor',true],['forecolorpicker','forecolor.gif','lang_theme_forecolor_desc','forecolorpicker',true],['backcolor','backcolor.gif','lang_theme_backcolor_desc','HiliteColor',true],['backcolorpicker','backcolor.gif','lang_theme_backcolor_desc','backcolorpicker',true],['charmap','charmap.gif','lang_theme_charmap_desc','mceCharMap'],['visualaid','visualaid.gif','lang_theme_visualaid_desc','mceToggleVisualAid'],['anchor','anchor.gif','lang_theme_anchor_desc','mceInsertAnchor'],['newdocument','newdocument.gif','lang_newdocument_desc','mceNewDocument']],_buttonMap:'anchor,backcolor,bold,bullist,charmap,cleanup,code,copy,cut,forecolor,help,hr,image,indent,italic,justifycenter,justifyfull,justifyleft,justifyright,link,newdocument,numlist,outdent,paste,redo,removeformat,strikethrough,sub,sup,underline,undo,unlink,visualaid,advhr,ltr,rtl,emotions,flash,fullpage,fullscreen,iespell,insertdate,inserttime,pastetext,pasteword,selectall,preview,print,save,replace,search,table,cell_props,delete_col,delete_row,col_after,col_before,row_after,row_before,merge_cells,row_props,split_cells,delete_table',getControlHTML:function(button_name){var i,x,but;for(i=0;i<TinyMCE_AdvancedTheme._buttons.length;i++){but=TinyMCE_AdvancedTheme._buttons[i];if(but[0]==button_name&&(button_name=="forecolor"||button_name=="backcolor"))return tinyMCE.getMenuButtonHTML(but[0],but[2],'{$themeurl}/images/'+but[1],but[3]+"Menu",but[3],(but.length>4?but[4]:false),(but.length>5?but[5]:null));if(but[0]==button_name)return tinyMCE.getButtonHTML(but[0],but[2],'{$themeurl}/images/'+but[1],but[3],(but.length>4?but[4]:false),(but.length>5?but[5]:null))}switch(button_name){case"formatselect":var html='<select id="{$editor_id}_formatSelect" name="{$editor_id}_formatSelect" onfocus="tinyMCE.addSelectAccessibility(event, this, window);" onchange="tinyMCE.execInstanceCommand(\'{$editor_id}\',\'FormatBlock\',false,this.options[this.selectedIndex].value);" class="mceSelectList">';var formats=tinyMCE.getParam("theme_advanced_blockformats","p,address,pre,h1,h2,h3,h4,h5,h6",true).split(',');var lookup=[['p','{$lang_theme_paragraph}'],['address','{$lang_theme_address}'],['pre','{$lang_theme_pre}'],['h1','{$lang_theme_h1}'],['h2','{$lang_theme_h2}'],['h3','{$lang_theme_h3}'],['h4','{$lang_theme_h4}'],['h5','{$lang_theme_h5}'],['h6','{$lang_theme_h6}'],['div','{$lang_theme_div}'],['blockquote','{$lang_theme_blockquote}'],['code','{$lang_theme_code}'],['dt','{$lang_theme_dt}'],['dd','{$lang_theme_dd}'],['samp','{$lang_theme_samp}']];html+='<option value="">{$lang_theme_block}</option>';for(var i=0;i<formats.length;i++){for(var x=0;x<lookup.length;x++){if(formats[i]==lookup[x][0])html+='<option value="&lt;'+lookup[x][0]+'&gt;">'+lookup[x][1]+'</option>'}}html+='</select>';return html;case"styleselect":return'<select id="{$editor_id}_styleSelect" onmousedown="tinyMCE.themes.advanced._setupCSSClasses(\'{$editor_id}\');" name="{$editor_id}_styleSelect" onfocus="tinyMCE.addSelectAccessibility(event,this,window);" onchange="tinyMCE.execInstanceCommand(\'{$editor_id}\',\'mceSetCSSClass\',false,this.options[this.selectedIndex].value);" class="mceSelectList">{$style_select_options}</select>';case"fontselect":var fontHTML='<select id="{$editor_id}_fontNameSelect" name="{$editor_id}_fontNameSelect" onfocus="tinyMCE.addSelectAccessibility(event, this, window);" onchange="tinyMCE.execInstanceCommand(\'{$editor_id}\',\'FontName\',false,this.options[this.selectedIndex].value);" class="mceSelectList"><option value="">{$lang_theme_fontdefault}</option>';var iFonts='Arial=arial,helvetica,sans-serif;Courier New=courier new,courier,monospace;Georgia=georgia,times new roman,times,serif;Tahoma=tahoma,arial,helvetica,sans-serif;Times New Roman=times new roman,times,serif;Verdana=verdana,arial,helvetica,sans-serif;Impact=impact;WingDings=wingdings';var nFonts='Andale Mono=andale mono,times;Arial=arial,helvetica,sans-serif;Arial Black=arial black,avant garde;Book Antiqua=book antiqua,palatino;Comic Sans MS=comic sans ms,sand;Courier New=courier new,courier;Georgia=georgia,palatino;Helvetica=helvetica;Impact=impact,chicago;Symbol=symbol;Tahoma=tahoma,arial,helvetica,sans-serif;Terminal=terminal,monaco;Times New Roman=times new roman,times;Trebuchet MS=trebuchet ms,geneva;Verdana=verdana,geneva;Webdings=webdings;Wingdings=wingdings,zapf dingbats';var fonts=tinyMCE.getParam("theme_advanced_fonts",nFonts).split(';');for(i=0;i<fonts.length;i++){if(fonts[i]!=''){var parts=fonts[i].split('=');fontHTML+='<option value="'+parts[1]+'">'+parts[0]+'</option>'}}fontHTML+='</select>';return fontHTML;case"fontsizeselect":return'<select id="{$editor_id}_fontSizeSelect" name="{$editor_id}_fontSizeSelect" onfocus="tinyMCE.addSelectAccessibility(event, this, window);" onchange="tinyMCE.execInstanceCommand(\'{$editor_id}\',\'FontSize\',false,this.options[this.selectedIndex].value);" class="mceSelectList">'+'<option value="0">{$lang_theme_font_size}</option>'+'<option value="1">1 (8 pt)</option>'+'<option value="2">2 (10 pt)</option>'+'<option value="3">3 (12 pt)</option>'+'<option value="4">4 (14 pt)</option>'+'<option value="5">5 (18 pt)</option>'+'<option value="6">6 (24 pt)</option>'+'<option value="7">7 (36 pt)</option>'+'</select>';case"|":case"separator":return'<img src="{$themeurl}/images/separator.gif" width="2" height="20" class="mceSeparatorLine" />';case"spacer":return'<img src="{$themeurl}/images/separator.gif" width="2" height="15" border="0" class="mceSeparatorLine" style="vertical-align: middle" />';case"rowseparator":return'<br />'}return""},execCommand:function(editor_id,element,command,user_interface,value){switch(command){case'mceHelp':tinyMCE.openWindow({file:'about.htm',width:480,height:380},{tinymce_version:tinyMCE.majorVersion+"."+tinyMCE.minorVersion,tinymce_releasedate:tinyMCE.releaseDate,inline:"yes"});return true;case"mceLink":var inst=tinyMCE.getInstanceById(editor_id);var doc=inst.getDoc();var selectedText="";if(tinyMCE.isMSIE){var rng=doc.selection.createRange();selectedText=rng.text}else selectedText=inst.getSel().toString();if(!tinyMCE.linkElement){if((tinyMCE.selectedElement.nodeName.toLowerCase()!="img")&&(selectedText.length<=0))return true}var href="",target="",title="",onclick="",action="insert",style_class="";if(tinyMCE.selectedElement.nodeName.toLowerCase()=="a")tinyMCE.linkElement=tinyMCE.selectedElement;if(tinyMCE.linkElement!=null&&tinyMCE.getAttrib(tinyMCE.linkElement,'href')=="")tinyMCE.linkElement=null;if(tinyMCE.linkElement){href=tinyMCE.getAttrib(tinyMCE.linkElement,'href');target=tinyMCE.getAttrib(tinyMCE.linkElement,'target');title=tinyMCE.getAttrib(tinyMCE.linkElement,'title');onclick=tinyMCE.getAttrib(tinyMCE.linkElement,'onclick');style_class=tinyMCE.getAttrib(tinyMCE.linkElement,'class');if(onclick=="")onclick=tinyMCE.getAttrib(tinyMCE.linkElement,'onclick');onclick=tinyMCE.cleanupEventStr(onclick);href=eval(tinyMCE.settings['urlconverter_callback']+"(href, tinyMCE.linkElement, true);");mceRealHref=tinyMCE.getAttrib(tinyMCE.linkElement,'mce_href');if(mceRealHref!=""){href=mceRealHref;if(tinyMCE.getParam('convert_urls'))href=eval(tinyMCE.settings['urlconverter_callback']+"(href, tinyMCE.linkElement, true);")}action="update"}var template=new Array();template['file']='link.htm';template['width']=310;template['height']=200;template['width']+=tinyMCE.getLang('lang_insert_link_delta_width',0);template['height']+=tinyMCE.getLang('lang_insert_link_delta_height',0);if(inst.settings['insertlink_callback']){var returnVal=eval(inst.settings['insertlink_callback']+"(href, target, title, onclick, action, style_class);");if(returnVal&&returnVal['href'])TinyMCE_AdvancedTheme._insertLink(returnVal['href'],returnVal['target'],returnVal['title'],returnVal['onclick'],returnVal['style_class'])}else{tinyMCE.openWindow(template,{href:href,target:target,title:title,onclick:onclick,action:action,className:style_class,inline:"yes"})}return true;case"mceImage":var src="",alt="",border="",hspace="",vspace="",width="",height="",align="";var title="",onmouseover="",onmouseout="",action="insert";var img=tinyMCE.imgElement;var inst=tinyMCE.getInstanceById(editor_id);if(tinyMCE.selectedElement!=null&&tinyMCE.selectedElement.nodeName.toLowerCase()=="img"){img=tinyMCE.selectedElement;tinyMCE.imgElement=img}if(img){if(tinyMCE.getAttrib(img,'name').indexOf('mce_')==0)return true;src=tinyMCE.getAttrib(img,'src');alt=tinyMCE.getAttrib(img,'alt');if(alt=="")alt=tinyMCE.getAttrib(img,'title');if(tinyMCE.isGecko){var w=img.style.width;if(w!=null&&w!="")img.setAttribute("width",w);var h=img.style.height;if(h!=null&&h!="")img.setAttribute("height",h)}border=tinyMCE.getAttrib(img,'border');hspace=tinyMCE.getAttrib(img,'hspace');vspace=tinyMCE.getAttrib(img,'vspace');width=tinyMCE.getAttrib(img,'width');height=tinyMCE.getAttrib(img,'height');align=tinyMCE.getAttrib(img,'align');onmouseover=tinyMCE.getAttrib(img,'onmouseover');onmouseout=tinyMCE.getAttrib(img,'onmouseout');title=tinyMCE.getAttrib(img,'title');if(tinyMCE.isMSIE){width=img.attributes['width'].specified?width:"";height=img.attributes['height'].specified?height:""}src=eval(tinyMCE.settings['urlconverter_callback']+"(src, img, true);");mceRealSrc=tinyMCE.getAttrib(img,'mce_src');if(mceRealSrc!=""){src=mceRealSrc;if(tinyMCE.getParam('convert_urls'))src=eval(tinyMCE.settings['urlconverter_callback']+"(src, img, true);")}action="update"}var template=new Array();template['file']='image.htm?src={$src}';template['width']=355;template['height']=265+(tinyMCE.isMSIE?25:0);template['width']+=tinyMCE.getLang('lang_insert_image_delta_width',0);template['height']+=tinyMCE.getLang('lang_insert_image_delta_height',0);if(inst.settings['insertimage_callback']){var returnVal=eval(inst.settings['insertimage_callback']+"(src, alt, border, hspace, vspace, width, height, align, title, onmouseover, onmouseout, action);");if(returnVal&&returnVal['src'])TinyMCE_AdvancedTheme._insertImage(returnVal['src'],returnVal['alt'],returnVal['border'],returnVal['hspace'],returnVal['vspace'],returnVal['width'],returnVal['height'],returnVal['align'],returnVal['title'],returnVal['onmouseover'],returnVal['onmouseout'])}else tinyMCE.openWindow(template,{src:src,alt:alt,border:border,hspace:hspace,vspace:vspace,width:width,height:height,align:align,title:title,onmouseover:onmouseover,onmouseout:onmouseout,action:action,inline:"yes"});return true;case"forecolor":var fcp=new TinyMCE_Layer(editor_id+'_fcPreview',false),p,img,elm;TinyMCE_AdvancedTheme._hideMenus(editor_id);if(!fcp.exists()){fcp.create('div','mceColorPreview',document.getElementById(editor_id+'_toolbar'));elm=fcp.getElement();elm._editor_id=editor_id;elm._command="forecolor";elm._switchId=editor_id+"_forecolor";tinyMCE.addEvent(elm,'click',TinyMCE_AdvancedTheme._handleMenuEvent);tinyMCE.addEvent(elm,'mouseover',TinyMCE_AdvancedTheme._handleMenuEvent);tinyMCE.addEvent(elm,'mouseout',TinyMCE_AdvancedTheme._handleMenuEvent)}img=tinyMCE.selectNodes(document.getElementById(editor_id+"_forecolor"),function(n){return n.nodeName=="IMG"})[0];p=tinyMCE.getAbsPosition(img,document.getElementById(editor_id+'_toolbar'));fcp.moveTo(p.absLeft,p.absTop);fcp.getElement().style.backgroundColor=value!=null?value:tinyMCE.getInstanceById(editor_id).foreColor;fcp.show();return false;case"forecolorpicker":this._pickColor(editor_id,'forecolor');return true;case"forecolorMenu":TinyMCE_AdvancedTheme._hideMenus(editor_id);var ml=new TinyMCE_Layer(editor_id+'_fcMenu');if(!ml.exists())ml.create('div','mceMenu',document.body,TinyMCE_AdvancedTheme._getColorHTML(editor_id,'theme_advanced_text_colors','forecolor'));tinyMCE.switchClass(editor_id+'_forecolor','mceMenuButtonFocus');ml.moveRelativeTo(document.getElementById(editor_id+"_forecolor"),'bl');ml.moveBy(tinyMCE.isMSIE&&!tinyMCE.isOpera?-1:1,-1);if(tinyMCE.isOpera)ml.moveBy(0,-2);ml.show();return true;case"HiliteColor":var bcp=new TinyMCE_Layer(editor_id+'_bcPreview',false),p,img;TinyMCE_AdvancedTheme._hideMenus(editor_id);if(!bcp.exists()){bcp.create('div','mceColorPreview',document.getElementById(editor_id+'_toolbar'));elm=bcp.getElement();elm._editor_id=editor_id;elm._command="HiliteColor";elm._switchId=editor_id+"_backcolor";tinyMCE.addEvent(elm,'click',TinyMCE_AdvancedTheme._handleMenuEvent);tinyMCE.addEvent(elm,'mouseover',TinyMCE_AdvancedTheme._handleMenuEvent);tinyMCE.addEvent(elm,'mouseout',TinyMCE_AdvancedTheme._handleMenuEvent)}img=tinyMCE.selectNodes(document.getElementById(editor_id+"_backcolor"),function(n){return n.nodeName=="IMG"})[0];p=tinyMCE.getAbsPosition(img,document.getElementById(editor_id+'_toolbar'));bcp.moveTo(p.absLeft,p.absTop);bcp.getElement().style.backgroundColor=value!=null?value:tinyMCE.getInstanceById(editor_id).backColor;bcp.show();return false;case"HiliteColorMenu":TinyMCE_AdvancedTheme._hideMenus(editor_id);var ml=new TinyMCE_Layer(editor_id+'_bcMenu');if(!ml.exists())ml.create('div','mceMenu',document.body,TinyMCE_AdvancedTheme._getColorHTML(editor_id,'theme_advanced_background_colors','HiliteColor'));tinyMCE.switchClass(editor_id+'_backcolor','mceMenuButtonFocus');ml.moveRelativeTo(document.getElementById(editor_id+"_backcolor"),'bl');ml.moveBy(tinyMCE.isMSIE&&!tinyMCE.isOpera?-1:1,-1);if(tinyMCE.isOpera)ml.moveBy(0,-2);ml.show();return true;case"backcolorpicker":this._pickColor(editor_id,'HiliteColor');return true;case"mceColorPicker":if(user_interface){var template=[];if(!value['callback']&&!value['color'])value['color']=value['document'].getElementById(value['element_id']).value;template['file']='color_picker.htm';template['width']=380;template['height']=250;template['close_previous']="no";template['width']+=tinyMCE.getLang('lang_theme_advanced_colorpicker_delta_width',0);template['height']+=tinyMCE.getLang('lang_theme_advanced_colorpicker_delta_height',0);if(typeof(value['store_selection'])=="undefined")value['store_selection']=true;tinyMCE.lastColorPickerValue=value;tinyMCE.openWindow(template,{editor_id:editor_id,mce_store_selection:value['store_selection'],inline:"yes",command:"mceColorPicker",input_color:value['color']})}else{var savedVal=tinyMCE.lastColorPickerValue,elm;if(savedVal['callback']){savedVal['callback'](value);return true}elm=savedVal['document'].getElementById(savedVal['element_id']);elm.value=value;if(elm.onchange!=null&&elm.onchange!='')eval('elm.onchange();')}return true;case"mceCodeEditor":var template=new Array();template['file']='source_editor.htm';template['width']=parseInt(tinyMCE.getParam("theme_advanced_source_editor_width",720));template['height']=parseInt(tinyMCE.getParam("theme_advanced_source_editor_height",580));tinyMCE.openWindow(template,{editor_id:editor_id,resizable:"yes",scrollbars:"no",inline:"yes"});return true;case"mceCharMap":var template=new Array();template['file']='charmap.htm';template['width']=550+(tinyMCE.isOpera?40:0);template['height']=250;template['width']+=tinyMCE.getLang('lang_theme_advanced_charmap_delta_width',0);template['height']+=tinyMCE.getLang('lang_theme_advanced_charmap_delta_height',0);tinyMCE.openWindow(template,{editor_id:editor_id,inline:"yes"});return true;case"mceInsertAnchor":var template=new Array();template['file']='anchor.htm';template['width']=320;template['height']=90+(tinyMCE.isNS7?30:0);template['width']+=tinyMCE.getLang('lang_theme_advanced_anchor_delta_width',0);template['height']+=tinyMCE.getLang('lang_theme_advanced_anchor_delta_height',0);tinyMCE.openWindow(template,{editor_id:editor_id,inline:"yes"});return true;case"mceNewDocument":if(confirm(tinyMCE.getLang('lang_newdocument')))tinyMCE.execInstanceCommand(editor_id,'mceSetContent',false,' ');return true}return false},getEditorTemplate:function(settings,editorId){function removeFromArray(in_array,remove_array){var outArray=new Array(),skip;for(var i=0;i<in_array.length;i++){skip=false;for(var j=0;j<remove_array.length;j++){if(in_array[i]==remove_array[j]){skip=true}}if(!skip){outArray[outArray.length]=in_array[i]}}return outArray}function addToArray(in_array,add_array){for(var i=0;i<add_array.length;i++){in_array[in_array.length]=add_array[i]}return in_array}var template=new Array();var deltaHeight=0;var resizing=tinyMCE.getParam("theme_advanced_resizing",false);var path=tinyMCE.getParam("theme_advanced_path",true);var statusbarHTML='<div id="{$editor_id}_path" class="mceStatusbarPathText" style="display: '+(path?"block":"none")+'">&#160;</div><div id="{$editor_id}_resize" class="mceStatusbarResize" style="display: '+(resizing?"block":"none")+'" onmousedown="tinyMCE.themes.advanced._setResizing(event,\'{$editor_id}\',true);"></div><br style="clear: both" />';var layoutManager=tinyMCE.getParam("theme_advanced_layout_manager","SimpleLayout");var styleSelectHTML='<option value="">{$lang_theme_style_select}</option>';if(settings['theme_advanced_styles']){var stylesAr=settings['theme_advanced_styles'].split(';');for(var i=0;i<stylesAr.length;i++){var key,value;key=stylesAr[i].split('=')[0];value=stylesAr[i].split('=')[1];styleSelectHTML+='<option value="'+value+'">'+key+'</option>'}TinyMCE_AdvancedTheme._autoImportCSSClasses=false}switch(layoutManager){case"SimpleLayout":var toolbarHTML="";var toolbarLocation=tinyMCE.getParam("theme_advanced_toolbar_location","bottom");var toolbarAlign=tinyMCE.getParam("theme_advanced_toolbar_align","center");var pathLocation=tinyMCE.getParam("theme_advanced_path_location","none");var statusbarLocation=tinyMCE.getParam("theme_advanced_statusbar_location",pathLocation);var defVals={theme_advanced_buttons1:"bold,italic,underline,strikethrough,separator,justifyleft,justifycenter,justifyright,justifyfull,separator,styleselect,formatselect",theme_advanced_buttons2:"bullist,numlist,separator,outdent,indent,separator,undo,redo,separator,link,unlink,anchor,image,cleanup,help,code",theme_advanced_buttons3:"hr,removeformat,visualaid,separator,sub,sup,separator,charmap"};toolbarHTML+='<a href="#" accesskey="q" title="'+tinyMCE.getLang("lang_toolbar_focus")+'"';if(!tinyMCE.getParam("accessibility_focus"))toolbarHTML+=' onfocus="tinyMCE.getInstanceById(\''+editorId+'\').getWin().focus();"';toolbarHTML+='></a>';for(var i=1;i<100;i++){var def=defVals["theme_advanced_buttons"+i];var buttons=tinyMCE.getParam("theme_advanced_buttons"+i,def==null?'':def,true,',');if(buttons.length==0)break;buttons=removeFromArray(buttons,tinyMCE.getParam("theme_advanced_disable","",true,','));buttons=addToArray(buttons,tinyMCE.getParam("theme_advanced_buttons"+i+"_add","",true,','));buttons=addToArray(tinyMCE.getParam("theme_advanced_buttons"+i+"_add_before","",true,','),buttons);for(var b=0;b<buttons.length;b++)toolbarHTML+=tinyMCE.getControlHTML(buttons[b]);if(buttons.length>0){toolbarHTML+="<br />";deltaHeight-=23}}toolbarHTML+='<a href="#" accesskey="z" onfocus="tinyMCE.getInstanceById(\''+editorId+'\').getWin().focus();"></a>';template['html']='<table class="mceEditor" border="0" cellpadding="0" cellspacing="0" width="{$width}" height="{$height}" style="width:{$width_style};height:{$height_style}"><tbody>';if(toolbarLocation=="top")template['html']+='<tr><td dir="ltr" class="mceToolbarTop" align="'+toolbarAlign+'" height="1" nowrap="nowrap"><span id="'+editorId+'_toolbar" class="mceToolbarContainer">'+toolbarHTML+'</span></td></tr>';if(statusbarLocation=="top"){template['html']+='<tr><td class="mceStatusbarTop" height="1">'+statusbarHTML+'</td></tr>';deltaHeight-=23}template['html']+='<tr><td align="center"><span id="{$editor_id}"></span></td></tr>';if(toolbarLocation=="bottom")template['html']+='<tr><td dir="ltr" class="mceToolbarBottom" align="'+toolbarAlign+'" height="1"><span id="'+editorId+'_toolbar" class="mceToolbarContainer">'+toolbarHTML+'</span></td></tr>';if(toolbarLocation=="external"){var bod=document.body;var elm=document.createElement("div");toolbarHTML=tinyMCE.replaceVar(toolbarHTML,'style_select_options',styleSelectHTML);toolbarHTML=tinyMCE.applyTemplate(toolbarHTML,{editor_id:editorId});elm.className="mceToolbarExternal";elm.id=editorId+"_toolbar";elm.innerHTML='<table width="100%" border="0" align="center"><tr><td align="center">'+toolbarHTML+'</td></tr></table>';bod.appendChild(elm);deltaHeight=0;tinyMCE.getInstanceById(editorId).toolbarElement=elm;}else{tinyMCE.getInstanceById(editorId).toolbarElement=null}if(statusbarLocation=="bottom"){template['html']+='<tr><td class="mceStatusbarBottom" height="1">'+statusbarHTML+'</td></tr>';deltaHeight-=23}template['html']+='</tbody></table>';break;case"RowLayout":template['html']='<table class="mceEditor" border="0" cellpadding="0" cellspacing="0" width="{$width}" height="{$height}" style="width:{$width}px;height:{$height}px"><tbody>';var containers=tinyMCE.getParam("theme_advanced_containers","",true,",");var defaultContainerCSS=tinyMCE.getParam("theme_advanced_containers_default_class","container");var defaultContainerAlign=tinyMCE.getParam("theme_advanced_containers_default_align","center");for(var i=0;i<containers.length;i++){if(containers[i]=="mceEditor")template['html']+='<tr><td align="center" class="mceEditor_border"><span id="{$editor_id}"></span></td></tr>';else if(containers[i]=="mceElementpath"||containers[i]=="mceStatusbar"){var pathClass="mceStatusbar";if(i==containers.length-1){pathClass="mceStatusbarBottom"}else if(i==0){pathClass="mceStatusbar"}else{deltaHeight-=2}template['html']+='<tr><td class="'+pathClass+'" height="1">'+statusbarHTML+'</td></tr>';deltaHeight-=22}else{var curContainer=tinyMCE.getParam("theme_advanced_container_"+containers[i],"",true,',');var curContainerHTML="";var curAlign=tinyMCE.getParam("theme_advanced_container_"+containers[i]+"_align",defaultContainerAlign);var curCSS=tinyMCE.getParam("theme_advanced_container_"+containers[i]+"_class",defaultContainerCSS);curContainer=removeFromArray(curContainer,tinyMCE.getParam("theme_advanced_disable","",true,','));for(var j=0;j<curContainer.length;j++)curContainerHTML+=tinyMCE.getControlHTML(curContainer[j]);if(curContainer.length>0){curContainerHTML+="<br />";deltaHeight-=23}template['html']+='<tr><td class="'+curCSS+'" align="'+curAlign+'" height="1">'+curContainerHTML+'</td></tr>'}}template['html']+='</tbody></table>';break;case"CustomLayout":var customLayout=tinyMCE.getParam("theme_advanced_custom_layout","");if(customLayout!=""&&eval("typeof("+customLayout+")")!="undefined"){template=eval(customLayout+"(template);")}break}if(resizing)template['html']+='<span id="{$editor_id}_resize_box" class="mceResizeBox"></span>';template['html']=tinyMCE.replaceVar(template['html'],'style_select_options',styleSelectHTML);if(!template['delta_width'])template['delta_width']=0;if(!template['delta_height'])template['delta_height']=deltaHeight;return template},initInstance:function(inst){if(tinyMCE.getParam("theme_advanced_resizing",false)){if(tinyMCE.getParam("theme_advanced_resizing_use_cookie",true)){var w=TinyMCE_AdvancedTheme._getCookie("TinyMCE_"+inst.editorId+"_width");var h=TinyMCE_AdvancedTheme._getCookie("TinyMCE_"+inst.editorId+"_height");TinyMCE_AdvancedTheme._resizeTo(inst,w,h,tinyMCE.getParam("theme_advanced_resize_horizontal",true))}}inst.addShortcut('ctrl','k','lang_link_desc','mceLink')},removeInstance:function(inst){new TinyMCE_Layer(inst.editorId+'_fcMenu').remove();new TinyMCE_Layer(inst.editorId+'_bcMenu').remove()},hideInstance:function(inst){TinyMCE_AdvancedTheme._hideMenus(inst.editorId)},_handleMenuEvent:function(e){var te=tinyMCE.isMSIE?window.event.srcElement:e.target;tinyMCE._menuButtonEvent(e.type=="mouseover"?"over":"out",document.getElementById(te._switchId));if(e.type=="click")tinyMCE.execInstanceCommand(te._editor_id,te._command)},_hideMenus:function(id){var fcml=new TinyMCE_Layer(id+'_fcMenu'),bcml=new TinyMCE_Layer(id+'_bcMenu');if(fcml.exists()&&fcml.isVisible()){tinyMCE.switchClass(id+'_forecolor','mceMenuButton');fcml.hide()}if(bcml.exists()&&bcml.isVisible()){tinyMCE.switchClass(id+'_backcolor','mceMenuButton');bcml.hide()}},handleNodeChange:function(editor_id,node,undo_index,undo_levels,visual_aid,any_selection,setup_content){var alignNode,breakOut,classNode;function selectByValue(select_elm,value,first_index){first_index=typeof(first_index)=="undefined"?false:true;if(select_elm){for(var i=0;i<select_elm.options.length;i++){var ov=""+select_elm.options[i].value;if(first_index&&ov.toLowerCase().indexOf(value.toLowerCase())==0){select_elm.selectedIndex=i;return true}if(ov==value){select_elm.selectedIndex=i;return true}}}return false};if(node==null)return;var pathElm=document.getElementById(editor_id+"_path");var inst=tinyMCE.getInstanceById(editor_id);var doc=inst.getDoc();TinyMCE_AdvancedTheme._hideMenus(editor_id);if(pathElm){var parentNode=node;var path=new Array();while(parentNode!=null){if(parentNode.nodeName.toUpperCase()=="BODY"){break}if(parentNode.nodeType==1&&tinyMCE.getAttrib(parentNode,"class").indexOf('mceItemHidden')==-1){path[path.length]=parentNode}parentNode=parentNode.parentNode}var html="";for(var i=path.length-1;i>=0;i--){var nodeName=path[i].nodeName.toLowerCase();var nodeData="";if(nodeName.indexOf("html:")==0)nodeName=nodeName.substring(5);if(nodeName=="b"){nodeName="strong"}if(nodeName=="i"){nodeName="em"}if(nodeName=="span"){var cn=tinyMCE.getAttrib(path[i],"class");if(cn!=""&&cn.indexOf('mceItem')==-1)nodeData+="class: "+cn+" ";var st=tinyMCE.getAttrib(path[i],"style");if(st!=""){st=tinyMCE.serializeStyle(tinyMCE.parseStyle(st));nodeData+="style: "+tinyMCE.xmlEncode(st)+" "}}if(nodeName=="font"){if(tinyMCE.getParam("convert_fonts_to_spans"))nodeName="span";var face=tinyMCE.getAttrib(path[i],"face");if(face!="")nodeData+="font: "+tinyMCE.xmlEncode(face)+" ";var size=tinyMCE.getAttrib(path[i],"size");if(size!="")nodeData+="size: "+tinyMCE.xmlEncode(size)+" ";var color=tinyMCE.getAttrib(path[i],"color");if(color!="")nodeData+="color: "+tinyMCE.xmlEncode(color)+" "}if(tinyMCE.getAttrib(path[i],'id')!=""){nodeData+="id: "+path[i].getAttribute('id')+" "}var className=tinyMCE.getVisualAidClass(tinyMCE.getAttrib(path[i],"class"),false);if(className!=""&&className.indexOf('mceItem')==-1)nodeData+="class: "+className+" ";if(tinyMCE.getAttrib(path[i],'src')!=""){var src=tinyMCE.getAttrib(path[i],"mce_src");if(src=="")src=tinyMCE.getAttrib(path[i],"src");nodeData+="src: "+tinyMCE.xmlEncode(src)+" "}if(path[i].nodeName=='A'&&tinyMCE.getAttrib(path[i],'href')!=""){var href=tinyMCE.getAttrib(path[i],"mce_href");if(href=="")href=tinyMCE.getAttrib(path[i],"href");nodeData+="href: "+tinyMCE.xmlEncode(href)+" "}className=tinyMCE.getAttrib(path[i],"class");if((nodeName=="img"||nodeName=="span")&&className.indexOf('mceItem')!=-1){nodeName=className.replace(/mceItem([a-z]+)/gi,'$1').toLowerCase();nodeData=path[i].getAttribute('title')}if(nodeName=="a"&&(anchor=tinyMCE.getAttrib(path[i],"name"))!=""){nodeName="a";nodeName+="#"+tinyMCE.xmlEncode(anchor);nodeData=""}if(tinyMCE.getAttrib(path[i],'name').indexOf("mce_")!=0){var className=tinyMCE.getVisualAidClass(tinyMCE.getAttrib(path[i],"class"),false);if(className!=""&&className.indexOf('mceItem')==-1){nodeName+="."+className}}var cmd='tinyMCE.execInstanceCommand(\''+editor_id+'\',\'mceSelectNodeDepth\',false,\''+i+'\');';html+='<a title="'+nodeData+'" href="javascript:'+cmd+'" onclick="'+cmd+'return false;" onmousedown="return false;" target="_self" class="mcePathItem">'+nodeName+'</a>';if(i>0){html+=" &raquo; "}}pathElm.innerHTML='<a href="#" accesskey="x"></a>'+tinyMCE.getLang('lang_theme_path')+": "+html+'&#160;'}tinyMCE.switchClass(editor_id+'_justifyleft','mceButtonNormal');tinyMCE.switchClass(editor_id+'_justifyright','mceButtonNormal');tinyMCE.switchClass(editor_id+'_justifycenter','mceButtonNormal');tinyMCE.switchClass(editor_id+'_justifyfull','mceButtonNormal');tinyMCE.switchClass(editor_id+'_bold','mceButtonNormal');tinyMCE.switchClass(editor_id+'_italic','mceButtonNormal');tinyMCE.switchClass(editor_id+'_underline','mceButtonNormal');tinyMCE.switchClass(editor_id+'_strikethrough','mceButtonNormal');tinyMCE.switchClass(editor_id+'_bullist','mceButtonNormal');tinyMCE.switchClass(editor_id+'_numlist','mceButtonNormal');tinyMCE.switchClass(editor_id+'_sub','mceButtonNormal');tinyMCE.switchClass(editor_id+'_sup','mceButtonNormal');tinyMCE.switchClass(editor_id+'_anchor','mceButtonNormal');tinyMCE.switchClass(editor_id+'_link','mceButtonDisabled');tinyMCE.switchClass(editor_id+'_unlink','mceButtonDisabled');tinyMCE.switchClass(editor_id+'_outdent','mceButtonDisabled');tinyMCE.switchClass(editor_id+'_image','mceButtonNormal');tinyMCE.switchClass(editor_id+'_hr','mceButtonNormal');if(node.nodeName=="A"&&tinyMCE.getAttrib(node,"class").indexOf('mceItemAnchor')!=-1)tinyMCE.switchClass(editor_id+'_anchor','mceButtonSelected');var anchorLink=tinyMCE.getParentElement(node,"a","href");if(anchorLink||any_selection){tinyMCE.switchClass(editor_id+'_link',anchorLink?'mceButtonSelected':'mceButtonNormal');tinyMCE.switchClass(editor_id+'_unlink',anchorLink?'mceButtonSelected':'mceButtonNormal')}tinyMCE.switchClass(editor_id+'_visualaid',visual_aid?'mceButtonSelected':'mceButtonNormal');if(undo_levels!=-1){tinyMCE.switchClass(editor_id+'_undo','mceButtonDisabled');tinyMCE.switchClass(editor_id+'_redo','mceButtonDisabled')}if(tinyMCE.getParentElement(node,"li,blockquote"))tinyMCE.switchClass(editor_id+'_outdent','mceButtonNormal');if(undo_index!=-1&&(undo_index<undo_levels-1&&undo_levels>0))tinyMCE.switchClass(editor_id+'_redo','mceButtonNormal');if(undo_index!=-1&&(undo_index>0&&undo_levels>0))tinyMCE.switchClass(editor_id+'_undo','mceButtonNormal');var selectElm=document.getElementById(editor_id+"_styleSelect");if(selectElm){TinyMCE_AdvancedTheme._setupCSSClasses(editor_id);classNode=node;breakOut=false;var index=0;do{if(classNode&&classNode.className){for(var i=0;i<selectElm.options.length;i++){if(selectElm.options[i].value==classNode.className){index=i;breakOut=true;break}}}}while(!breakOut&&classNode!=null&&(classNode=classNode.parentNode)!=null);selectElm.selectedIndex=index}var selectElm=document.getElementById(editor_id+"_formatSelect");if(selectElm){var elm=tinyMCE.getParentElement(node,"p,div,h1,h2,h3,h4,h5,h6,pre,address");if(elm)selectByValue(selectElm,"<"+elm.nodeName.toLowerCase()+">");else selectByValue(selectElm,"")}var selectElm=document.getElementById(editor_id+"_fontNameSelect");if(selectElm){if(!tinyMCE.isSafari&&!(tinyMCE.isMSIE&&!tinyMCE.isOpera)){var face=inst.queryCommandValue('FontName');face=face==null||face==""?"":face;selectByValue(selectElm,face,face!="")}else{var elm=tinyMCE.getParentElement(node,"font","face");if(elm){var family=tinyMCE.getAttrib(elm,"face");if(family=='')family=''+elm.style.fontFamily;if(!selectByValue(selectElm,family,family!=""))selectByValue(selectElm,"")}else selectByValue(selectElm,"")}}var selectElm=document.getElementById(editor_id+"_fontSizeSelect");if(selectElm){if(!tinyMCE.isSafari&&!tinyMCE.isOpera){var size=inst.queryCommandValue('FontSize');selectByValue(selectElm,size==null||size==""?"0":size)}else{var elm=tinyMCE.getParentElement(node,"font","size");if(elm){var size=tinyMCE.getAttrib(elm,"size");if(size==''){var sizes=new Array('','8px','10px','12px','14px','18px','24px','36px');size=''+elm.style.fontSize;for(var i=0;i<sizes.length;i++){if((''+sizes[i])==size){size=i;break}}}if(!selectByValue(selectElm,size))selectByValue(selectElm,"")}else selectByValue(selectElm,"0")}}alignNode=node;breakOut=false;do{if(!alignNode.getAttribute||!alignNode.getAttribute('align'))continue;switch(alignNode.getAttribute('align').toLowerCase()){case"left":tinyMCE.switchClass(editor_id+'_justifyleft','mceButtonSelected');breakOut=true;break;case"right":tinyMCE.switchClass(editor_id+'_justifyright','mceButtonSelected');breakOut=true;break;case"middle":case"center":tinyMCE.switchClass(editor_id+'_justifycenter','mceButtonSelected');breakOut=true;break;case"justify":tinyMCE.switchClass(editor_id+'_justifyfull','mceButtonSelected');breakOut=true;break}}while(!breakOut&&(alignNode=alignNode.parentNode)!=null);var div=tinyMCE.getParentElement(node,"div");if(div&&div.style.textAlign=="center")tinyMCE.switchClass(editor_id+'_justifycenter','mceButtonSelected');if(!setup_content){var ar=new Array("Bold","_bold","Italic","_italic","Strikethrough","_strikethrough","superscript","_sup","subscript","_sub");for(var i=0;i<ar.length;i+=2){if(inst.queryCommandState(ar[i]))tinyMCE.switchClass(editor_id+ar[i+1],'mceButtonSelected')}if(inst.queryCommandState("Underline")&&(node.parentNode==null||node.parentNode.nodeName!="A"))tinyMCE.switchClass(editor_id+'_underline','mceButtonSelected')}do{switch(node.nodeName){case"UL":tinyMCE.switchClass(editor_id+'_bullist','mceButtonSelected');break;case"OL":tinyMCE.switchClass(editor_id+'_numlist','mceButtonSelected');break;case"HR":tinyMCE.switchClass(editor_id+'_hr','mceButtonSelected');break;case"IMG":if(tinyMCE.getAttrib(node,'name').indexOf('mce_')!=0&&tinyMCE.getAttrib(node,'class').indexOf('mceItem')==-1){tinyMCE.switchClass(editor_id+'_image','mceButtonSelected')}break}}while((node=node.parentNode)!=null)},_setupCSSClasses:function(editor_id){var i,selectElm;if(!TinyMCE_AdvancedTheme._autoImportCSSClasses)return;selectElm=document.getElementById(editor_id+'_styleSelect');if(selectElm&&selectElm.getAttribute('cssImported')!='true'){var csses=tinyMCE.getCSSClasses(editor_id);if(csses&&selectElm){for(i=0;i<csses.length;i++)selectElm.options[selectElm.options.length]=new Option(csses[i],csses[i])}if(csses!=null&&csses.length>0)selectElm.setAttribute('cssImported','true')}},_setCookie:function(name,value,expires,path,domain,secure){var curCookie=name+"="+escape(value)+((expires)?"; expires="+expires.toGMTString():"")+((path)?"; path="+escape(path):"")+((domain)?"; domain="+domain:"")+((secure)?"; secure":"");document.cookie=curCookie},_getCookie:function(name){var dc=document.cookie;var prefix=name+"=";var begin=dc.indexOf("; "+prefix);if(begin==-1){begin=dc.indexOf(prefix);if(begin!=0)return null}else begin+=2;var end=document.cookie.indexOf(";",begin);if(end==-1)end=dc.length;return unescape(dc.substring(begin+prefix.length,end))},_resizeTo:function(inst,w,h,set_w){var editorContainer=document.getElementById(inst.editorId+'_parent');var tableElm=editorContainer.firstChild;var iframe=inst.iframeElement;if(w==null||w=="null"){set_w=false;w=0}if(h==null||h=="null")return;w=parseInt(w);h=parseInt(h);if(tinyMCE.isGecko){w+=2;h+=2}var dx=w-tableElm.clientWidth;var dy=h-tableElm.clientHeight;w=w<1?30:w;h=h<1?30:h;if(set_w)tableElm.style.width=w+"px";tableElm.style.height=h+"px";iw=iframe.clientWidth+dx;ih=iframe.clientHeight+dy;iw=iw<1?30:iw;ih=ih<1?30:ih;if(tinyMCE.isGecko){iw-=2;ih-=2}if(set_w)iframe.style.width=iw+"px";iframe.style.height=ih+"px";if(set_w){var tableBodyElm=tableElm.firstChild;var minIframeWidth=tableBodyElm.scrollWidth;if(inst.iframeElement.clientWidth<minIframeWidth){dx=minIframeWidth-inst.iframeElement.clientWidth;inst.iframeElement.style.width=(iw+dx)+"px"}}inst.useCSS=false},_resizeEventHandler:function(e){var resizer=TinyMCE_AdvancedTheme._resizer;if(!resizer.resizing)return;e=typeof(e)=="undefined"?window.event:e;var dx=e.screenX-resizer.downX;var dy=e.screenY-resizer.downY;var resizeBox=resizer.resizeBox;var editorId=resizer.editorId;switch(e.type){case"mousemove":var w,h;w=resizer.width+dx;h=resizer.height+dy;w=w<1?1:w;h=h<1?1:h;if(resizer.horizontal)resizeBox.style.width=w+"px";resizeBox.style.height=h+"px";break;case"mouseup":TinyMCE_AdvancedTheme._setResizing(e,editorId,false);TinyMCE_AdvancedTheme._resizeTo(tinyMCE.getInstanceById(editorId),resizer.width+dx,resizer.height+dy,resizer.horizontal);if(tinyMCE.getParam("theme_advanced_resizing_use_cookie",true)){var expires=new Date();expires.setTime(expires.getTime()+3600000*24*30);TinyMCE_AdvancedTheme._setCookie("TinyMCE_"+editorId+"_width",""+(resizer.horizontal?resizer.width+dx:""),expires);TinyMCE_AdvancedTheme._setCookie("TinyMCE_"+editorId+"_height",""+(resizer.height+dy),expires)}break}},_setResizing:function(e,editor_id,state){e=typeof(e)=="undefined"?window.event:e;var resizer=TinyMCE_AdvancedTheme._resizer;var editorContainer=document.getElementById(editor_id+'_parent');var editorArea=document.getElementById(editor_id+'_parent').firstChild;var resizeBox=document.getElementById(editor_id+'_resize_box');var inst=tinyMCE.getInstanceById(editor_id);if(state){var width=editorArea.clientWidth;var height=editorArea.clientHeight;resizeBox.style.width=width+"px";resizeBox.style.height=height+"px";resizer.iframeWidth=inst.iframeElement.clientWidth;resizer.iframeHeight=inst.iframeElement.clientHeight;editorArea.style.display="none";resizeBox.style.display="block";if(!resizer.eventHandlers){if(tinyMCE.isMSIE)tinyMCE.addEvent(document,"mousemove",TinyMCE_AdvancedTheme._resizeEventHandler);else tinyMCE.addEvent(window,"mousemove",TinyMCE_AdvancedTheme._resizeEventHandler);tinyMCE.addEvent(document,"mouseup",TinyMCE_AdvancedTheme._resizeEventHandler);resizer.eventHandlers=true}resizer.resizing=true;resizer.downX=e.screenX;resizer.downY=e.screenY;resizer.width=parseInt(resizeBox.style.width);resizer.height=parseInt(resizeBox.style.height);resizer.editorId=editor_id;resizer.resizeBox=resizeBox;resizer.horizontal=tinyMCE.getParam("theme_advanced_resize_horizontal",true)}else{resizer.resizing=false;resizeBox.style.display="none";editorArea.style.display=tinyMCE.isMSIE&&!tinyMCE.isOpera?"block":"table";tinyMCE.execCommand('mceResetDesignMode')}},_getColorHTML:function(id,n,cm){var i,h,cl;h='<span class="mceMenuLine"></span>';cl=tinyMCE.getParam(n,TinyMCE_AdvancedTheme._defColors).split(',');h+='<table class="mceColors"><tr>';for(i=0;i<cl.length;i++){c='tinyMCE.execInstanceCommand(\''+id+'\', \''+cm+'\', false, \'#'+cl[i]+'\');';h+='<td><a href="javascript:'+c+'" style="background-color: #'+cl[i]+'" onclick="'+c+';return false;"></a></td>';if((i+1)%8==0)h+='</tr><tr>'}h+='</tr></table>';if(tinyMCE.getParam("theme_advanced_more_colors",true))h+='<a href="#" onclick="TinyMCE_AdvancedTheme._pickColor(\''+id+'\',\''+cm+'\');" class="mceMoreColors">'+tinyMCE.getLang('lang_more_colors')+'</a>';return h},_pickColor:function(id,cm){var inputColor,inst=tinyMCE.selectedInstance;if(cm=='forecolor'&&inst)inputColor=inst.foreColor;if((cm=='backcolor'||cm=='HiliteColor')&&inst)inputColor=inst.backColor;tinyMCE.execCommand('mceColorPicker',true,{color:inputColor,callback:function(c){tinyMCE.execInstanceCommand(id,cm,false,c)}})},_insertImage:function(src,alt,border,hspace,vspace,width,height,align,title,onmouseover,onmouseout){tinyMCE.execCommand('mceBeginUndoLevel');if(src=="")return;if(!tinyMCE.imgElement&&tinyMCE.isSafari){var html="";html+='<img src="'+src+'" alt="'+alt+'"';html+=' border="'+border+'" hspace="'+hspace+'"';html+=' vspace="'+vspace+'" width="'+width+'"';html+=' height="'+height+'" align="'+align+'" title="'+title+'" onmouseover="'+onmouseover+'" onmouseout="'+onmouseout+'" />';tinyMCE.execCommand("mceInsertContent",false,html)}else{if(!tinyMCE.imgElement&&tinyMCE.selectedInstance){if(tinyMCE.isSafari)tinyMCE.execCommand("mceInsertContent",false,'<img src="'+tinyMCE.uniqueURL+'" />');else tinyMCE.selectedInstance.contentDocument.execCommand("insertimage",false,tinyMCE.uniqueURL);tinyMCE.imgElement=tinyMCE.getElementByAttributeValue(tinyMCE.selectedInstance.contentDocument.body,"img","src",tinyMCE.uniqueURL)}}if(tinyMCE.imgElement){var needsRepaint=false;var msrc=src;src=eval(tinyMCE.settings['urlconverter_callback']+"(src, tinyMCE.imgElement);");if(tinyMCE.getParam('convert_urls'))msrc=src;if(onmouseover&&onmouseover!="")onmouseover="this.src='"+eval(tinyMCE.settings['urlconverter_callback']+"(onmouseover, tinyMCE.imgElement);")+"';";if(onmouseout&&onmouseout!="")onmouseout="this.src='"+eval(tinyMCE.settings['urlconverter_callback']+"(onmouseout, tinyMCE.imgElement);")+"';";if(typeof(title)=="undefined")title=alt;if(width!=tinyMCE.imgElement.getAttribute("width")||height!=tinyMCE.imgElement.getAttribute("height")||align!=tinyMCE.imgElement.getAttribute("align"))needsRepaint=true;tinyMCE.setAttrib(tinyMCE.imgElement,'src',src);tinyMCE.setAttrib(tinyMCE.imgElement,'mce_src',msrc);tinyMCE.setAttrib(tinyMCE.imgElement,'alt',alt);tinyMCE.setAttrib(tinyMCE.imgElement,'title',title);tinyMCE.setAttrib(tinyMCE.imgElement,'align',align);tinyMCE.setAttrib(tinyMCE.imgElement,'border',border,true);tinyMCE.setAttrib(tinyMCE.imgElement,'hspace',hspace,true);tinyMCE.setAttrib(tinyMCE.imgElement,'vspace',vspace,true);tinyMCE.setAttrib(tinyMCE.imgElement,'width',width,true);tinyMCE.setAttrib(tinyMCE.imgElement,'height',height,true);tinyMCE.setAttrib(tinyMCE.imgElement,'onmouseover',onmouseover);tinyMCE.setAttrib(tinyMCE.imgElement,'onmouseout',onmouseout);if(width&&width!="")tinyMCE.imgElement.style.pixelWidth=width;if(height&&height!="")tinyMCE.imgElement.style.pixelHeight=height;if(needsRepaint)tinyMCE.selectedInstance.repaint()}tinyMCE.execCommand('mceEndUndoLevel')},_insertLink:function(href,target,title,onclick,style_class){tinyMCE.execCommand('mceBeginUndoLevel');if(tinyMCE.selectedInstance&&tinyMCE.selectedElement&&tinyMCE.selectedElement.nodeName.toLowerCase()=="img"){var doc=tinyMCE.selectedInstance.getDoc();var linkElement=tinyMCE.getParentElement(tinyMCE.selectedElement,"a");var newLink=false;if(!linkElement){linkElement=doc.createElement("a");newLink=true}var mhref=href;var thref=eval(tinyMCE.settings['urlconverter_callback']+"(href, linkElement);");mhref=tinyMCE.getParam('convert_urls')?href:mhref;tinyMCE.setAttrib(linkElement,'href',thref);tinyMCE.setAttrib(linkElement,'mce_href',mhref);tinyMCE.setAttrib(linkElement,'target',target);tinyMCE.setAttrib(linkElement,'title',title);tinyMCE.setAttrib(linkElement,'onclick',onclick);tinyMCE.setAttrib(linkElement,'class',style_class);if(newLink){linkElement.appendChild(tinyMCE.selectedElement.cloneNode(true));tinyMCE.selectedElement.parentNode.replaceChild(linkElement,tinyMCE.selectedElement)}return}if(!tinyMCE.linkElement&&tinyMCE.selectedInstance){if(tinyMCE.isSafari){tinyMCE.execCommand("mceInsertContent",false,'<a href="'+tinyMCE.uniqueURL+'">'+tinyMCE.selectedInstance.selection.getSelectedHTML()+'</a>')}else tinyMCE.selectedInstance.contentDocument.execCommand("createlink",false,tinyMCE.uniqueURL);tinyMCE.linkElement=tinyMCE.getElementByAttributeValue(tinyMCE.selectedInstance.contentDocument.body,"a","href",tinyMCE.uniqueURL);var elementArray=tinyMCE.getElementsByAttributeValue(tinyMCE.selectedInstance.contentDocument.body,"a","href",tinyMCE.uniqueURL);for(var i=0;i<elementArray.length;i++){var mhref=href;var thref=eval(tinyMCE.settings['urlconverter_callback']+"(href, elementArray[i]);");mhref=tinyMCE.getParam('convert_urls')?href:mhref;tinyMCE.setAttrib(elementArray[i],'href',thref);tinyMCE.setAttrib(elementArray[i],'mce_href',mhref);tinyMCE.setAttrib(elementArray[i],'target',target);tinyMCE.setAttrib(elementArray[i],'title',title);tinyMCE.setAttrib(elementArray[i],'onclick',onclick);tinyMCE.setAttrib(elementArray[i],'class',style_class)}tinyMCE.linkElement=elementArray[0]}if(tinyMCE.linkElement){var mhref=href;href=eval(tinyMCE.settings['urlconverter_callback']+"(href, tinyMCE.linkElement);");mhref=tinyMCE.getParam('convert_urls')?href:mhref;tinyMCE.setAttrib(tinyMCE.linkElement,'href',href);tinyMCE.setAttrib(tinyMCE.linkElement,'mce_href',mhref);tinyMCE.setAttrib(tinyMCE.linkElement,'target',target);tinyMCE.setAttrib(tinyMCE.linkElement,'title',title);tinyMCE.setAttrib(tinyMCE.linkElement,'onclick',onclick);tinyMCE.setAttrib(tinyMCE.linkElement,'class',style_class)}tinyMCE.execCommand('mceEndUndoLevel')}};tinyMCE.addTheme("advanced",TinyMCE_AdvancedTheme);tinyMCE.addButtonMap(TinyMCE_AdvancedTheme._buttonMap);
\ No newline at end of file
+(function(){var DOM=tinymce.DOM,Event=tinymce.dom.Event,extend=tinymce.extend,each=tinymce.each,Cookie=tinymce.util.Cookie,lastExtID;tinymce.ThemeManager.requireLangPack('advanced');tinymce.create('tinymce.themes.AdvancedTheme',{controls:{bold:['bold_desc','Bold'],italic:['italic_desc','Italic'],underline:['underline_desc','Underline'],strikethrough:['striketrough_desc','Strikethrough'],justifyleft:['justifyleft_desc','JustifyLeft'],justifycenter:['justifycenter_desc','JustifyCenter'],justifyright:['justifyright_desc','JustifyRight'],justifyfull:['justifyfull_desc','JustifyFull'],bullist:['bullist_desc','InsertUnorderedList'],numlist:['numlist_desc','InsertOrderedList'],outdent:['outdent_desc','Outdent'],indent:['indent_desc','Indent'],cut:['cut_desc','Cut'],copy:['copy_desc','Copy'],paste:['paste_desc','Paste'],undo:['undo_desc','Undo'],redo:['redo_desc','Redo'],link:['link_desc','mceLink'],unlink:['unlink_desc','unlink'],image:['image_desc','mceImage'],cleanup:['cleanup_desc','mceCleanup'],help:['help_desc','mceHelp'],code:['code_desc','mceCodeEditor'],hr:['hr_desc','InsertHorizontalRule'],removeformat:['removeformat_desc','RemoveFormat'],sub:['sub_desc','subscript'],sup:['sup_desc','superscript'],forecolor:['forecolor_desc','ForeColor'],forecolorpicker:['forecolor_desc','mceForeColor'],backcolor:['backcolor_desc','HiliteColor'],backcolorpicker:['backcolor_desc','mceBackColor'],charmap:['charmap_desc','mceCharMap'],visualaid:['visualaid_desc','mceToggleVisualAid'],anchor:['anchor_desc','mceInsertAnchor'],newdocument:['newdocument_desc','mceNewDocument'],blockquote:['blockquote_desc','mceBlockQuote']},stateControls:['bold','italic','underline','strikethrough','bullist','numlist','justifyleft','justifycenter','justifyright','justifyfull','sub','sup','blockquote'],init:function(ed,url){var t=this,s;t.editor=ed;t.url=url;t.onResolveName=new tinymce.util.Dispatcher(this);t.settings=s=extend({theme_advanced_path:true,theme_advanced_toolbar_location:'bottom',theme_advanced_buttons1:"bold,italic,underline,strikethrough,|,justifyleft,justifycenter,justifyright,justifyfull,|,styleselect,formatselect",theme_advanced_buttons2:"bullist,numlist,|,outdent,indent,|,undo,redo,|,link,unlink,anchor,image,cleanup,help,code",theme_advanced_buttons3:"hr,removeformat,visualaid,|,sub,sup,|,charmap",theme_advanced_blockformats:"p,address,pre,h1,h2,h3,h4,h5,h6",theme_advanced_toolbar_align:"center",theme_advanced_fonts:"Andale Mono=andale mono,times;Arial=arial,helvetica,sans-serif;Arial Black=arial black,avant garde;Book Antiqua=book antiqua,palatino;Comic Sans MS=comic sans ms,sans-serif;Courier New=courier new,courier;Georgia=georgia,palatino;Helvetica=helvetica;Impact=impact,chicago;Symbol=symbol;Tahoma=tahoma,arial,helvetica,sans-serif;Terminal=terminal,monaco;Times New Roman=times new roman,times;Trebuchet MS=trebuchet ms,geneva;Verdana=verdana,geneva;Webdings=webdings;Wingdings=wingdings,zapf dingbats",theme_advanced_font_sizes:"1,2,3,4,5,6,7",theme_advanced_more_colors:1,theme_advanced_row_height:23,theme_advanced_resize_horizontal:1,theme_advanced_resizing_use_cookie:1},ed.settings);if(s.theme_advanced_path_location)s.theme_advanced_statusbar_location=s.theme_advanced_path_location;if(s.theme_advanced_statusbar_location=='none')s.theme_advanced_statusbar_location=0;ed.onInit.add(function(){ed.onNodeChange.add(t._nodeChanged,t);ed.dom.loadCSS(ed.baseURI.toAbsolute("themes/advanced/skins/"+ed.settings.skin+"/content.css"));});ed.onSetProgressState.add(function(ed,b,ti){var co,id=ed.id,tb;if(b){t.progressTimer=setTimeout(function(){co=ed.getContainer();co=co.insertBefore(DOM.create('DIV',{style:'position:relative'}),co.firstChild);tb=DOM.get(ed.id+'_tbl');DOM.add(co,'div',{id:id+'_blocker','class':'mceBlocker',style:{width:tb.clientWidth+2,height:tb.clientHeight+2}});DOM.add(co,'div',{id:id+'_progress','class':'mceProgress',style:{left:tb.clientWidth/ 2, top : tb.clientHeight /2}});},ti||0);}else{DOM.remove(id+'_blocker');DOM.remove(id+'_progress');clearTimeout(t.progressTimer);}});DOM.loadCSS(ed.baseURI.toAbsolute(s.editor_css||"themes/advanced/skins/"+ed.settings.skin+"/ui.css"));},createControl:function(n,cf){var cd,c;if(c=cf.createControl(n))return c;switch(n){case"styleselect":return this._createStyleSelect();case"formatselect":return this._createBlockFormats();case"fontselect":return this._createFontSelect();case"fontsizeselect":return this._createFontSizeSelect();case"forecolor":return this._createForeColorMenu();case"backcolor":return this._createBackColorMenu();}if((cd=this.controls[n]))return cf.createButton(n,{title:"advanced."+cd[0],cmd:cd[1],ui:cd[2],value:cd[3]});},execCommand:function(cmd,ui,val){var f=this['_'+cmd];if(f){f.call(this,ui,val);return true;}return false;},_importClasses:function(){var ed=this.editor,c=ed.controlManager.get('styleselect');if(c.getLength()==0){each(ed.dom.getClasses(),function(o){c.add(o['class'],o['class']);});}},_createStyleSelect:function(n){var t=this,ed=t.editor,cf=ed.controlManager,c=cf.createListBox('styleselect',{title:'advanced.style_select',onselect:function(v){if(c.selectedValue===v){ed.execCommand('mceSetStyleInfo',0,{command:'removeformat'});c.select();return false;}else ed.execCommand('mceSetCSSClass',0,v);}});each((t.settings.theme_advanced_styles||'').split(';'),function(v){var p=v.split('=');if(v)c.add(t.editor.translate(p[0]),p[1]);});c.onPostRender.add(function(ed,n){Event.add(n,'focus',t._importClasses,t);Event.add(n,'mousedown',t._importClasses,t);});return c;},_createFontSelect:function(){var c,t=this;c=t.editor.controlManager.createListBox('fontselect',{title:'advanced.fontdefault',cmd:'FontName'});each(t.settings.theme_advanced_fonts.split(';'),function(v){var p=v.split('='),st;if(p[1].indexOf('dings')==-1)st='font-family:'+p[1];c.add(t.editor.translate(p[0]),p[1],{style:st});});return c;},_createFontSizeSelect:function(){var c,t=this,lo=["1 (8 pt)","2 (10 pt)","3 (12 pt)","4 (14 pt)","5 (18 pt)","6 (24 pt)","7 (36 pt)"],fz=[8,10,12,14,18,24,36];c=t.editor.controlManager.createListBox('fontsizeselect',{title:'advanced.font_size',cmd:'FontSize'});each(t.settings.theme_advanced_font_sizes.split(','),function(v){c.add(lo[parseInt(v)-1],v,{'style':'font-size:'+fz[v-1]+'pt','class':'fontSize'+v});});return c;},_createBlockFormats:function(){var c,fmts={p:'advanced.paragraph',address:'advanced.address',pre:'advanced.pre',h1:'advanced.h1',h2:'advanced.h2',h3:'advanced.h3',h4:'advanced.h4',h5:'advanced.h5',h6:'advanced.h6',div:'advanced.div',blockquote:'advanced.blockquote',code:'advanced.code',dt:'advanced.dt',dd:'advanced.dd',samp:'advanced.samp'},t=this;c=t.editor.controlManager.createListBox('formatselect',{title:'advanced.block',cmd:'FormatBlock'});each(t.settings.theme_advanced_blockformats.split(','),function(v){c.add(t.editor.translate(fmts[v]),v,{element:v,'class':v.indexOf('h')==0?'':'preview'});});return c;},_createForeColorMenu:function(){var c,t=this,s=t.settings,o={},v;if(s.theme_advanced_more_colors){o.more_colors_func=function(){t._mceColorPicker(0,{color:c.value,func:function(co){c.setColor(co);}});};}if(v=s.theme_advanced_text_colors)o.colors=v;o.title='advanced.forecolor_desc';o.cmd='ForeColor';o.scope=this;c=t.editor.controlManager.createColorSplitButton('forecolor',o);return c;},_createBackColorMenu:function(){var c,t=this,s=t.settings,o={},v;if(s.theme_advanced_more_colors){o.more_colors_func=function(){t._mceColorPicker(0,{color:c.value,func:function(co){c.setColor(co);}});};}if(v=s.theme_advanced_background_colors)o.colors=v;o.title='advanced.backcolor_desc';o.cmd='HiliteColor';o.scope=this;c=t.editor.controlManager.createColorSplitButton('backcolor',o);return c;},renderUI:function(o){var n,ic,tb,t=this,ed=t.editor,s=t.settings,sc,p,nl;n=p=DOM.create('div',{id:ed.id+'_parent','class':'mceEditor '+ed.settings.skin+'Skin'});if(!DOM.boxModel)n=DOM.add(n,'div',{'class':'mceOldBoxModel'});n=sc=DOM.add(n,'table',{id:ed.id+'_tbl','class':'mceLayout',cellSpacing:0,cellPadding:0});n=tb=DOM.add(n,'tbody');switch((s.theme_advanced_layout_manager||'').toLowerCase()){case"rowlayout":ic=t._rowLayout(s,tb,o);break;case"customlayout":ic=ed.execCallback("theme_advanced_custom_layout",s,tb,o,p);break;default:ic=t._simpleLayout(s,tb,o,p);}n=o.targetNode;nl=sc.rows;DOM.addClass(nl[0],'first');DOM.addClass(nl[nl.length-1],'last');each(DOM.select('tr',tb),function(n){DOM.addClass(n.firstChild,'first');DOM.addClass(n.childNodes[n.childNodes.length-1],'last');});if(DOM.get(s.theme_advanced_toolbar_container))DOM.get(s.theme_advanced_toolbar_container).appendChild(p);else DOM.insertAfter(p,n);Event.add(ed.id+'_path_row','click',function(e){e=e.target;if(e.nodeName=='A'){t._sel(e.href.replace(/^[^#]*#/,''));return Event.cancel(e);}});if(!ed.getParam('accessibility_focus')||ed.getParam('tab_focus'))Event.add(DOM.add(p,'a',{href:'#'},'<!-- IE -->'),'focus',function(){tinyMCE.get(ed.id).focus();});if(s.theme_advanced_toolbar_location=='external')o.deltaHeight=0;t.deltaHeight=o.deltaHeight;o.targetNode=null;return{iframeContainer:ic,editorContainer:ed.id+'_parent',sizeContainer:sc,deltaHeight:o.deltaHeight};},getInfo:function(){return{longname:'Simple theme',author:'Moxiecode Systems AB',authorurl:'http://tinymce.moxiecode.com',version:tinymce.majorVersion+"."+tinymce.minorVersion}},_simpleLayout:function(s,tb,o,p){var t=this,ed=t.editor,lo=s.theme_advanced_toolbar_location,sl=s.theme_advanced_statusbar_location,n,ic,etb,c;if(lo=='top')t._addToolbars(tb,o);if(lo=='external'){n=c=DOM.create('div',{style:'position:relative'});n=DOM.add(n,'div',{id:ed.id+'_external','class':'mceExternalToolbar'});DOM.add(n,'a',{id:ed.id+'_external_close',href:'javascript:;','class':'mceExternalClose'});n=DOM.add(n,'table',{id:ed.id+'_tblext',cellSpacing:0,cellPadding:0});etb=DOM.add(n,'tbody');if(p.firstChild.className=='mceOldBoxModel')p.firstChild.appendChild(c);else p.insertBefore(c,p.firstChild);t._addToolbars(etb,o);ed.onMouseUp.add(function(){var e=DOM.get(ed.id+'_external');DOM.show(e);DOM.hide(lastExtID);var f=Event.add(ed.id+'_external_close','click',function(){DOM.hide(ed.id+'_external');Event.remove(ed.id+'_external_close','click',f);});DOM.show(e);DOM.setStyle(e,'top',0-DOM.getRect(ed.id+'_tblext').h-1);DOM.hide(e);DOM.show(e);e.style.filter='';lastExtID=ed.id+'_external';e=null;});}if(sl=='top')t._addStatusBar(tb,o);if(!s.theme_advanced_toolbar_container){n=DOM.add(tb,'tr');n=ic=DOM.add(n,'td',{'class':'mceIframeContainer'});}if(lo=='bottom')t._addToolbars(tb,o);if(sl=='bottom')t._addStatusBar(tb,o);return ic;},_rowLayout:function(s,tb,o){var t=this,ed=t.editor,dc,da,cf=ed.controlManager,n,ic,to;dc=s.theme_advanced_containers_default_class||'';da=s.theme_advanced_containers_default_align||'center';each((s.theme_advanced_containers||'').split(','),function(c,i){var v=s['theme_advanced_container_'+c]||'';switch(c.toLowerCase()){case'mceeditor':n=DOM.add(tb,'tr');n=ic=DOM.add(n,'td',{'class':'mceIframeContainer'});break;case'mceelementpath':t._addStatusBar(tb,o);break;default:n=DOM.add(DOM.add(tb,'tr'),'td',{'class':'mceToolbar '+(s['theme_advanced_container_'+c+'_class']||dc),align:s['theme_advanced_container_'+c+'_align']||da});to=cf.createToolbar("toolbar"+i);t._addControls(v,to);DOM.setHTML(n,to.renderHTML());o.deltaHeight-=s.theme_advanced_row_height;}});return ic;},_addControls:function(v,tb){var t=this,s=t.settings,di,cf=t.editor.controlManager;if(s.theme_advanced_disable&&!t._disabled){di={};each(s.theme_advanced_disable.split(','),function(v){di[v]=1;});t._disabled=di;}else di=t._disabled;each(v.split(','),function(n){var c;if(di&&di[n])return;if(n=='tablecontrols'){each(["table","|","row_props","cell_props","|","row_before","row_after","delete_row","|","col_before","col_after","delete_col","|","split_cells","merge_cells"],function(n){n=t.createControl(n,cf);if(n)tb.add(n);});return;}c=t.createControl(n,cf);if(c)tb.add(c);});},_addToolbars:function(c,o){var t=this,i,tb,ed=t.editor,s=t.settings,v,cf=ed.controlManager,di,n,h=[];n=DOM.add(DOM.add(c,'tr'),'td',{'class':'mceToolbar',align:s.theme_advanced_toolbar_align});if(!ed.getParam('accessibility_focus')||ed.getParam('tab_focus'))h.push(DOM.createHTML('a',{href:'#',onfocus:'tinyMCE.get(\''+ed.id+'\').focus();'},'<!-- IE -->'));h.push(DOM.createHTML('a',{href:'#',accesskey:'q',title:ed.getLang("advanced.toolbar_focus")},'<!-- IE -->'));for(i=1;(v=s['theme_advanced_buttons'+i]);i++){tb=cf.createToolbar("toolbar"+i,{'class':'mceToolbarRow'+i});if(s['theme_advanced_buttons'+i+'_add'])v+=','+s['theme_advanced_buttons'+i+'_add'];if(s['theme_advanced_buttons'+i+'_add_before'])v=s['theme_advanced_buttons'+i+'_add_before']+','+v;t._addControls(v,tb);h.push(tb.renderHTML());o.deltaHeight-=s.theme_advanced_row_height;}h.push(DOM.createHTML('a',{href:'#',accesskey:'z',title:ed.getLang("advanced.toolbar_focus"),onfocus:'tinyMCE.getInstanceById(\''+ed.id+'\').focus();'},'<!-- IE -->'));DOM.setHTML(n,h.join(''));},_addStatusBar:function(tb,o){var n,t=this,ed=t.editor,s=t.settings,r,mf,me,td;n=DOM.add(tb,'tr');n=td=DOM.add(n,'td',{'class':'mceStatusbar'});n=DOM.add(n,'div',{id:ed.id+'_path_row'},s.theme_advanced_path?ed.translate('advanced.path')+': ':'&nbsp;');DOM.add(n,'a',{href:'#',accesskey:'x'});if(s.theme_advanced_resizing&&!tinymce.isOldWebKit){DOM.add(td,'a',{id:ed.id+'_resize',href:'javascript:;',onclick:"return false;",'class':'resize'});if(s.theme_advanced_resizing_use_cookie){ed.onPostRender.add(function(){var o=Cookie.getHash("TinyMCE_"+ed.id+"_size"),c=DOM.get(ed.id+'_tbl');if(!o)return;if(s.theme_advanced_resize_horizontal)c.style.width=o.cw+'px';c.style.height=o.ch+'px';DOM.get(ed.id+'_ifr').style.height=(parseInt(o.ch)+t.deltaHeight)+'px';});}ed.onPostRender.add(function(){Event.add(ed.id+'_resize','mousedown',function(e){var c,p,w,h,n,pa;c=DOM.get(ed.id+'_tbl');w=c.clientWidth;h=c.clientHeight;miw=s.theme_advanced_resizing_min_width||100;mih=s.theme_advanced_resizing_min_height||100;maw=s.theme_advanced_resizing_max_width||0xFFFF;mah=s.theme_advanced_resizing_max_height||0xFFFF;p=DOM.add(DOM.get(ed.id+'_parent'),'div',{'class':'mcePlaceHolder'});DOM.setStyles(p,{width:w,height:h});DOM.hide(c);DOM.show(p);r={x:e.screenX,y:e.screenY,w:w,h:h,dx:null,dy:null};mf=Event.add(document,'mousemove',function(e){var w,h;r.dx=e.screenX-r.x;r.dy=e.screenY-r.y;w=Math.max(miw,r.w+r.dx);h=Math.max(mih,r.h+r.dy);w=Math.min(maw,w);h=Math.min(mah,h);if(s.theme_advanced_resize_horizontal)p.style.width=w+'px';p.style.height=h+'px';return Event.cancel(e);});me=Event.add(document,'mouseup',function(e){var ifr;Event.remove(document,'mousemove',mf);Event.remove(document,'mouseup',me);c.style.display='';DOM.remove(p);if(r.dx===null)return;ifr=DOM.get(ed.id+'_ifr');if(s.theme_advanced_resize_horizontal)c.style.width=(r.w+r.dx)+'px';c.style.height=(r.h+r.dy)+'px';ifr.style.height=(ifr.clientHeight+r.dy)+'px';if(s.theme_advanced_resizing_use_cookie){Cookie.setHash("TinyMCE_"+ed.id+"_size",{cw:r.w+r.dx,ch:r.h+r.dy});}});return Event.cancel(e);});});}o.deltaHeight-=21;n=tb=null;},_nodeChanged:function(ed,cm,n,co){var t=this,p,de=0,v,c,s=t.settings;tinymce.each(t.stateControls,function(c){cm.setActive(c,ed.queryCommandState(t.controls[c][1]));});cm.setActive('visualaid',ed.hasVisual);cm.setDisabled('undo',!ed.undoManager.hasUndo()&&!ed.typing);cm.setDisabled('redo',!ed.undoManager.hasRedo());cm.setDisabled('outdent',!ed.queryCommandState('Outdent'));p=DOM.getParent(n,'A');if(c=cm.get('link')){if(!p||!p.name){c.setDisabled(!p&&co);c.setActive(!!p);}}if(c=cm.get('unlink')){c.setDisabled(!p&&co);c.setActive(!!p&&!p.name);}if(c=cm.get('anchor')){c.setActive(!!p&&p.name);if(tinymce.isWebKit){p=DOM.getParent(n,'IMG');c.setActive(!!p&&DOM.getAttrib(p,'mce_name')=='a');}}p=DOM.getParent(n,'IMG');if(c=cm.get('image'))c.setActive(!!p&&n.className.indexOf('mceItem')==-1);if(c=cm.get('styleselect')){if(n.className){t._importClasses();c.select(n.className);}else c.select();}if(c=cm.get('formatselect')){p=DOM.getParent(n,DOM.isBlock);if(p)c.select(p.nodeName.toLowerCase());}if(c=cm.get('fontselect'))c.select(ed.queryCommandValue('FontName'));if(c=cm.get('fontsizeselect'))c.select(ed.queryCommandValue('FontSize'));if(s.theme_advanced_path&&s.theme_advanced_statusbar_location){p=DOM.get(ed.id+'_path')||DOM.add(ed.id+'_path_row','span',{id:ed.id+'_path'});DOM.setHTML(p,'');ed.dom.getParent(n,function(n){var na=n.nodeName.toLowerCase(),u,pi,ti='';if(n.nodeType!=1||(DOM.hasClass(n,'mceItemHidden')||DOM.hasClass(n,'mceItemRemoved')))return;if(v=DOM.getAttrib(n,'mce_name'))na=v;if(tinymce.isIE&&n.scopeName!=='HTML')na=n.scopeName+':'+na;na=na.replace(/mce\:/g,'');switch(na){case'b':na='strong';break;case'i':na='em';break;case'img':if(v=DOM.getAttrib(n,'src'))ti+='src: '+v+' ';break;case'a':if(v=DOM.getAttrib(n,'name')){ti+='name: '+v+' ';na+='#'+v;}if(v=DOM.getAttrib(n,'href'))ti+='href: '+v+' ';break;case'font':if(s.convert_fonts_to_spans)na='span';if(v=DOM.getAttrib(n,'face'))ti+='font: '+v+' ';if(v=DOM.getAttrib(n,'size'))ti+='size: '+v+' ';if(v=DOM.getAttrib(n,'color'))ti+='color: '+v+' ';break;case'span':if(v=DOM.getAttrib(n,'style'))ti+='style: '+v+' ';break;}if(v=DOM.getAttrib(n,'id'))ti+='id: '+v+' ';if(v=n.className){v=v.replace(/(webkit-[\w\-]+|Apple-[\w\-]+|mceItem\w+|mceVisualAid)/g,'');if(v&&v.indexOf('mceItem')==-1){ti+='class: '+v+' ';if(DOM.isBlock(n)||na=='img'||na=='span')na+='.'+v;}}na=na.replace(/(html:)/g,'');na={name:na,node:n,title:ti};t.onResolveName.dispatch(t,na);ti=na.title;na=na.name;pi=DOM.create('a',{'href':"#"+(de++)+"",onmousedown:"return false;",title:ti},na);if(p.hasChildNodes()){p.insertBefore(document.createTextNode(' \u00bb '),p.firstChild);p.insertBefore(pi,p.firstChild);}else p.appendChild(pi);},ed.getBody());}},_sel:function(v){this.editor.execCommand('mceSelectNodeDepth',false,v);},_mceInsertAnchor:function(ui,v){var ed=this.editor;ed.windowManager.open({url:tinymce.baseURL+'/themes/advanced/anchor.htm',width:320+parseInt(ed.getLang('advanced.anchor_delta_width',0)),height:90+parseInt(ed.getLang('advanced.anchor_delta_height',0)),inline:true},{theme_url:this.url});},_mceCharMap:function(){var ed=this.editor;ed.windowManager.open({url:tinymce.baseURL+'/themes/advanced/charmap.htm',width:550+parseInt(ed.getLang('advanced.charmap_delta_width',0)),height:250+parseInt(ed.getLang('advanced.charmap_delta_height',0)),inline:true},{theme_url:this.url});},_mceHelp:function(){var ed=this.editor;ed.windowManager.open({url:tinymce.baseURL+'/themes/advanced/about.htm',width:480,height:380,inline:true},{theme_url:this.url});},_mceColorPicker:function(u,v){var ed=this.editor;v=v||{};ed.windowManager.open({url:tinymce.baseURL+'/themes/advanced/color_picker.htm',width:375+parseInt(ed.getLang('advanced.colorpicker_delta_width',0)),height:250+parseInt(ed.getLang('advanced.colorpicker_delta_height',0)),close_previous:false,inline:true},{input_color:v.color,func:v.func,theme_url:this.url});},_mceCodeEditor:function(ui,val){var ed=this.editor;ed.windowManager.open({url:tinymce.baseURL+'/themes/advanced/source_editor.htm',width:parseInt(ed.getParam("theme_advanced_source_editor_width",720)),height:parseInt(ed.getParam("theme_advanced_source_editor_height",580)),inline:true,resizable:true,maximizable:true},{theme_url:this.url});},_mceImage:function(ui,val){var ed=this.editor;ed.windowManager.open({url:tinymce.baseURL+'/themes/advanced/image.htm',width:355+parseInt(ed.getLang('advanced.image_delta_width',0)),height:275+parseInt(ed.getLang('advanced.image_delta_height',0)),inline:true},{theme_url:this.url});},_mceLink:function(ui,val){var ed=this.editor;ed.windowManager.open({url:tinymce.baseURL+'/themes/advanced/link.htm',width:310+parseInt(ed.getLang('advanced.link_delta_width',0)),height:200+parseInt(ed.getLang('advanced.link_delta_height',0)),inline:true},{theme_url:this.url});},_mceNewDocument:function(){var ed=this.editor;ed.windowManager.confirm('advanced.newdocument',function(s){if(s)ed.execCommand('mceSetContent',false,'');});},_mceForeColor:function(){var t=this;this._mceColorPicker(0,{func:function(co){t.editor.execCommand('ForeColor',false,co);}});},_mceBackColor:function(){var t=this;this._mceColorPicker(0,{func:function(co){t.editor.execCommand('HiliteColor',false,co);}});}});tinymce.ThemeManager.add('advanced',tinymce.themes.AdvancedTheme);}());
\ No newline at end of file
--- a/includes/clientside/tinymce/themes/advanced/editor_template_src.js	Fri Feb 22 12:46:51 2008 -0500
+++ b/includes/clientside/tinymce/themes/advanced/editor_template_src.js	Fri Feb 22 12:51:53 2008 -0500
@@ -1,1574 +1,999 @@
 /**
- * $Id: editor_template_src.js 218 2007-02-13 11:08:01Z spocke $
+ * $Id: editor_template_src.js 555 2008-01-19 19:08:37Z spocke $
  *
  * @author Moxiecode
- * @copyright Copyright © 2004-2007, Moxiecode Systems AB, All rights reserved.
+ * @copyright Copyright © 2004-2008, Moxiecode Systems AB, All rights reserved.
  */
 
-/* Import theme specific language pack */
-tinyMCE.importThemeLanguagePack('advanced');
+(function() {
+	var DOM = tinymce.DOM, Event = tinymce.dom.Event, extend = tinymce.extend, each = tinymce.each, Cookie = tinymce.util.Cookie, lastExtID;
+
+	// Tell it to load theme specific language pack(s)
+	tinymce.ThemeManager.requireLangPack('advanced');
+
+	tinymce.create('tinymce.themes.AdvancedTheme', {
+		// Control name lookup, format: title, command
+		controls : {
+			bold : ['bold_desc', 'Bold'],
+			italic : ['italic_desc', 'Italic'],
+			underline : ['underline_desc', 'Underline'],
+			strikethrough : ['striketrough_desc', 'Strikethrough'],
+			justifyleft : ['justifyleft_desc', 'JustifyLeft'],
+			justifycenter : ['justifycenter_desc', 'JustifyCenter'],
+			justifyright : ['justifyright_desc', 'JustifyRight'],
+			justifyfull : ['justifyfull_desc', 'JustifyFull'],
+			bullist : ['bullist_desc', 'InsertUnorderedList'],
+			numlist : ['numlist_desc', 'InsertOrderedList'],
+			outdent : ['outdent_desc', 'Outdent'],
+			indent : ['indent_desc', 'Indent'],
+			cut : ['cut_desc', 'Cut'],
+			copy : ['copy_desc', 'Copy'],
+			paste : ['paste_desc', 'Paste'],
+			undo : ['undo_desc', 'Undo'],
+			redo : ['redo_desc', 'Redo'],
+			link : ['link_desc', 'mceLink'],
+			unlink : ['unlink_desc', 'unlink'],
+			image : ['image_desc', 'mceImage'],
+			cleanup : ['cleanup_desc', 'mceCleanup'],
+			help : ['help_desc', 'mceHelp'],
+			code : ['code_desc', 'mceCodeEditor'],
+			hr : ['hr_desc', 'InsertHorizontalRule'],
+			removeformat : ['removeformat_desc', 'RemoveFormat'],
+			sub : ['sub_desc', 'subscript'],
+			sup : ['sup_desc', 'superscript'],
+			forecolor : ['forecolor_desc', 'ForeColor'],
+			forecolorpicker : ['forecolor_desc', 'mceForeColor'],
+			backcolor : ['backcolor_desc', 'HiliteColor'],
+			backcolorpicker : ['backcolor_desc', 'mceBackColor'],
+			charmap : ['charmap_desc', 'mceCharMap'],
+			visualaid : ['visualaid_desc', 'mceToggleVisualAid'],
+			anchor : ['anchor_desc', 'mceInsertAnchor'],
+			newdocument : ['newdocument_desc', 'mceNewDocument'],
+			blockquote : ['blockquote_desc', 'mceBlockQuote']
+		},
+
+		stateControls : ['bold', 'italic', 'underline', 'strikethrough', 'bullist', 'numlist', 'justifyleft', 'justifycenter', 'justifyright', 'justifyfull', 'sub', 'sup', 'blockquote'],
+
+		init : function(ed, url) {
+			var t = this, s;
+
+			t.editor = ed;
+			t.url = url;
+			t.onResolveName = new tinymce.util.Dispatcher(this);
 
-var TinyMCE_AdvancedTheme = {
-	// Private theme fields
-	_defColors : "000000,993300,333300,003300,003366,000080,333399,333333,800000,FF6600,808000,008000,008080,0000FF,666699,808080,FF0000,FF9900,99CC00,339966,33CCCC,3366FF,800080,999999,FF00FF,FFCC00,FFFF00,00FF00,00FFFF,00CCFF,993366,C0C0C0,FF99CC,FFCC99,FFFF99,CCFFCC,CCFFFF,99CCFF,CC99FF,FFFFFF",
-	_autoImportCSSClasses : true,
-	_resizer : {},
-	_buttons : [
-		// Control id, button img, button title, command, user_interface, value
-		['bold', '{$lang_bold_img}', 'lang_bold_desc', 'Bold'],
-		['italic', '{$lang_italic_img}', 'lang_italic_desc', 'Italic'],
-		['underline', '{$lang_underline_img}', 'lang_underline_desc', 'Underline'],
-		['strikethrough', 'strikethrough.gif', 'lang_striketrough_desc', 'Strikethrough'],
-		['justifyleft', 'justifyleft.gif', 'lang_justifyleft_desc', 'JustifyLeft'],
-		['justifycenter', 'justifycenter.gif', 'lang_justifycenter_desc', 'JustifyCenter'],
-		['justifyright', 'justifyright.gif', 'lang_justifyright_desc', 'JustifyRight'],
-		['justifyfull', 'justifyfull.gif', 'lang_justifyfull_desc', 'JustifyFull'],
-		['bullist', 'bullist.gif', 'lang_bullist_desc', 'InsertUnorderedList'],
-		['numlist', 'numlist.gif', 'lang_numlist_desc', 'InsertOrderedList'],
-		['outdent', 'outdent.gif', 'lang_outdent_desc', 'Outdent'],
-		['indent', 'indent.gif', 'lang_indent_desc', 'Indent'],
-		['cut', 'cut.gif', 'lang_cut_desc', 'Cut'],
-		['copy', 'copy.gif', 'lang_copy_desc', 'Copy'],
-		['paste', 'paste.gif', 'lang_paste_desc', 'Paste'],
-		['undo', 'undo.gif', 'lang_undo_desc', 'Undo'],
-		['redo', 'redo.gif', 'lang_redo_desc', 'Redo'],
-		['link', 'link.gif', 'lang_link_desc', 'mceLink', true],
-		['unlink', 'unlink.gif', 'lang_unlink_desc', 'unlink'],
-		['image', 'image.gif', 'lang_image_desc', 'mceImage', true],
-		['cleanup', 'cleanup.gif', 'lang_cleanup_desc', 'mceCleanup'],
-		['help', 'help.gif', 'lang_help_desc', 'mceHelp'],
-		['code', 'code.gif', 'lang_theme_code_desc', 'mceCodeEditor'],
-		['hr', 'hr.gif', 'lang_theme_hr_desc', 'inserthorizontalrule'],
-		['removeformat', 'removeformat.gif', 'lang_theme_removeformat_desc', 'removeformat'],
-		['sub', 'sub.gif', 'lang_theme_sub_desc', 'subscript'],
-		['sup', 'sup.gif', 'lang_theme_sup_desc', 'superscript'],
-		['forecolor', 'forecolor.gif', 'lang_theme_forecolor_desc', 'forecolor', true],
-		['forecolorpicker', 'forecolor.gif', 'lang_theme_forecolor_desc', 'forecolorpicker', true],
-		['backcolor', 'backcolor.gif', 'lang_theme_backcolor_desc', 'HiliteColor', true],
-		['backcolorpicker', 'backcolor.gif', 'lang_theme_backcolor_desc', 'backcolorpicker', true],
-		['charmap', 'charmap.gif', 'lang_theme_charmap_desc', 'mceCharMap'],
-		['visualaid', 'visualaid.gif', 'lang_theme_visualaid_desc', 'mceToggleVisualAid'],
-		['anchor', 'anchor.gif', 'lang_theme_anchor_desc', 'mceInsertAnchor'],
-		['newdocument', 'newdocument.gif', 'lang_newdocument_desc', 'mceNewDocument']
-	],
+			// Default settings
+			t.settings = s = extend({
+				theme_advanced_path : true,
+				theme_advanced_toolbar_location : 'bottom',
+				theme_advanced_buttons1 : "bold,italic,underline,strikethrough,|,justifyleft,justifycenter,justifyright,justifyfull,|,styleselect,formatselect",
+				theme_advanced_buttons2 : "bullist,numlist,|,outdent,indent,|,undo,redo,|,link,unlink,anchor,image,cleanup,help,code",
+				theme_advanced_buttons3 : "hr,removeformat,visualaid,|,sub,sup,|,charmap",
+				theme_advanced_blockformats : "p,address,pre,h1,h2,h3,h4,h5,h6",
+				theme_advanced_toolbar_align : "center",
+				theme_advanced_fonts : "Andale Mono=andale mono,times;Arial=arial,helvetica,sans-serif;Arial Black=arial black,avant garde;Book Antiqua=book antiqua,palatino;Comic Sans MS=comic sans ms,sans-serif;Courier New=courier new,courier;Georgia=georgia,palatino;Helvetica=helvetica;Impact=impact,chicago;Symbol=symbol;Tahoma=tahoma,arial,helvetica,sans-serif;Terminal=terminal,monaco;Times New Roman=times new roman,times;Trebuchet MS=trebuchet ms,geneva;Verdana=verdana,geneva;Webdings=webdings;Wingdings=wingdings,zapf dingbats",
+				theme_advanced_font_sizes : "1,2,3,4,5,6,7",
+				theme_advanced_more_colors : 1,
+				theme_advanced_row_height : 23,
+				theme_advanced_resize_horizontal : 1,
+				theme_advanced_resizing_use_cookie : 1
+			}, ed.settings);
+
+			if (s.theme_advanced_path_location)
+				s.theme_advanced_statusbar_location = s.theme_advanced_path_location;
+
+			if (s.theme_advanced_statusbar_location == 'none')
+				s.theme_advanced_statusbar_location = 0;
+
+			// Init editor
+			ed.onInit.add(function() {
+				ed.onNodeChange.add(t._nodeChanged, t);
+				ed.dom.loadCSS(ed.baseURI.toAbsolute("themes/advanced/skins/" + ed.settings.skin + "/content.css"));
+			});
+
+			ed.onSetProgressState.add(function(ed, b, ti) {
+				var co, id = ed.id, tb;
 
-	_buttonMap : 'anchor,backcolor,bold,bullist,charmap,cleanup,code,copy,cut,forecolor,help,hr,image,indent,italic,justifycenter,justifyfull,justifyleft,justifyright,link,newdocument,numlist,outdent,paste,redo,removeformat,strikethrough,sub,sup,underline,undo,unlink,visualaid,advhr,ltr,rtl,emotions,flash,fullpage,fullscreen,iespell,insertdate,inserttime,pastetext,pasteword,selectall,preview,print,save,replace,search,table,cell_props,delete_col,delete_row,col_after,col_before,row_after,row_before,merge_cells,row_props,split_cells,delete_table',
+				if (b) {
+					t.progressTimer = setTimeout(function() {
+						co = ed.getContainer();
+						co = co.insertBefore(DOM.create('DIV', {style : 'position:relative'}), co.firstChild);
+						tb = DOM.get(ed.id + '_tbl');
+
+						DOM.add(co, 'div', {id : id + '_blocker', 'class' : 'mceBlocker', style : {width : tb.clientWidth + 2, height : tb.clientHeight + 2}});
+						DOM.add(co, 'div', {id : id + '_progress', 'class' : 'mceProgress', style : {left : tb.clientWidth / 2, top : tb.clientHeight / 2}});
+					}, ti || 0);
+				} else {
+					DOM.remove(id + '_blocker');
+					DOM.remove(id + '_progress');
+					clearTimeout(t.progressTimer);
+				}
+			});
+
+			DOM.loadCSS(ed.baseURI.toAbsolute(s.editor_css || "themes/advanced/skins/" + ed.settings.skin + "/ui.css"));
+		},
 
-	/**
-	 * Returns HTML code for the specificed control.
-	 */
-	getControlHTML : function(button_name) {
-		var i, x, but;
+		createControl : function(n, cf) {
+			var cd, c;
+
+			if (c = cf.createControl(n))
+				return c;
+
+			switch (n) {
+				case "styleselect":
+					return this._createStyleSelect();
 
-		// Lookup button in button list
-		for (i=0; i<TinyMCE_AdvancedTheme._buttons.length; i++) {
-			but = TinyMCE_AdvancedTheme._buttons[i];
+				case "formatselect":
+					return this._createBlockFormats();
+
+				case "fontselect":
+					return this._createFontSelect();
+
+				case "fontsizeselect":
+					return this._createFontSizeSelect();
+
+				case "forecolor":
+					return this._createForeColorMenu();
 
-			if (but[0] == button_name && (button_name == "forecolor" || button_name == "backcolor"))
-				return tinyMCE.getMenuButtonHTML(but[0], but[2], '{$themeurl}/images/' + but[1], but[3] + "Menu", but[3], (but.length > 4 ? but[4] : false), (but.length > 5 ? but[5] : null));
+				case "backcolor":
+					return this._createBackColorMenu();
+			}
+
+			if ((cd = this.controls[n]))
+				return cf.createButton(n, {title : "advanced." + cd[0], cmd : cd[1], ui : cd[2], value : cd[3]});
+		},
+
+		execCommand : function(cmd, ui, val) {
+			var f = this['_' + cmd];
 
-			if (but[0] == button_name)
-				return tinyMCE.getButtonHTML(but[0], but[2], '{$themeurl}/images/' + but[1], but[3], (but.length > 4 ? but[4] : false), (but.length > 5 ? but[5] : null));
-		}
+			if (f) {
+				f.call(this, ui, val);
+				return true;
+			}
+
+			return false;
+		},
+
+		_importClasses : function() {
+			var ed = this.editor, c = ed.controlManager.get('styleselect');
+
+			if (c.getLength() == 0) {
+				each(ed.dom.getClasses(), function(o) {
+					c.add(o['class'], o['class']);
+				});
+			}
+		},
 
-		// Custom controlls other than buttons
-		switch (button_name) {
-			case "formatselect":
-				var html = '<select id="{$editor_id}_formatSelect" name="{$editor_id}_formatSelect" onfocus="tinyMCE.addSelectAccessibility(event, this, window);" onchange="tinyMCE.execInstanceCommand(\'{$editor_id}\',\'FormatBlock\',false,this.options[this.selectedIndex].value);" class="mceSelectList">';
-				var formats = tinyMCE.getParam("theme_advanced_blockformats", "p,address,pre,h1,h2,h3,h4,h5,h6", true).split(',');
-				var lookup = [
-					['p', '{$lang_theme_paragraph}'],
-					['address', '{$lang_theme_address}'],
-					['pre', '{$lang_theme_pre}'],
-					['h1', '{$lang_theme_h1}'],
-					['h2', '{$lang_theme_h2}'],
-					['h3', '{$lang_theme_h3}'],
-					['h4', '{$lang_theme_h4}'],
-					['h5', '{$lang_theme_h5}'],
-					['h6', '{$lang_theme_h6}'],
-					['div', '{$lang_theme_div}'],
-					['blockquote', '{$lang_theme_blockquote}'],
-					['code', '{$lang_theme_code}'],
-					['dt', '{$lang_theme_dt}'],
-					['dd', '{$lang_theme_dd}'],
-					['samp', '{$lang_theme_samp}']
-				];
+		_createStyleSelect : function(n) {
+			var t = this, ed = t.editor, cf = ed.controlManager, c = cf.createListBox('styleselect', {
+				title : 'advanced.style_select',
+				onselect : function(v) {
+					if (c.selectedValue === v) {
+						ed.execCommand('mceSetStyleInfo', 0, {command : 'removeformat'});
+						c.select();
+						return false;
+					} else
+						ed.execCommand('mceSetCSSClass', 0, v);
+				}
+			});
+
+			each((t.settings.theme_advanced_styles || '').split(';'), function(v) {
+				var p = v.split('=');
+
+				if (v)
+					c.add(t.editor.translate(p[0]), p[1]);
+			});
+
+			c.onPostRender.add(function(ed, n) {
+				Event.add(n, 'focus', t._importClasses, t);
+				Event.add(n, 'mousedown', t._importClasses, t);
+			});
+
+			return c;
+		},
+
+		_createFontSelect : function() {
+			var c, t = this;
+
+			c = t.editor.controlManager.createListBox('fontselect', {title : 'advanced.fontdefault', cmd : 'FontName'});
+
+			each(t.settings.theme_advanced_fonts.split(';'), function(v) {
+				var p = v.split('='), st;
+
+				if (p[1].indexOf('dings') == -1)
+					st = 'font-family:' + p[1];
 
-				html += '<option value="">{$lang_theme_block}</option>';
+				c.add(t.editor.translate(p[0]), p[1], {style : st});
+			});
+
+			return c;
+		},
 
-				// Build format select
-				for (var i=0; i<formats.length; i++) {
-					for (var x=0; x<lookup.length; x++) {
-						if (formats[i] == lookup[x][0])
-							html += '<option value="&lt;' + lookup[x][0] + '&gt;">' + lookup[x][1] + '</option>';
-					}
-				}
+		_createFontSizeSelect : function() {
+			var c, t = this, lo = [
+				"1 (8 pt)",
+				"2 (10 pt)",
+				"3 (12 pt)",
+				"4 (14 pt)",
+				"5 (18 pt)",
+				"6 (24 pt)",
+				"7 (36 pt)"
+			], fz = [8, 10, 12, 14, 18, 24, 36];
 
-				html += '</select>';
+			c = t.editor.controlManager.createListBox('fontsizeselect', {title : 'advanced.font_size', cmd : 'FontSize'});
 
-				return html;
+			each(t.settings.theme_advanced_font_sizes.split(','), function(v) {
+				c.add(lo[parseInt(v) - 1], v, {'style' : 'font-size:' + fz[v - 1] + 'pt', 'class' : 'fontSize' + v});
+			});
+
+			return c;
+		},
 
-			case "styleselect":
-				return '<select id="{$editor_id}_styleSelect" onmousedown="tinyMCE.themes.advanced._setupCSSClasses(\'{$editor_id}\');" name="{$editor_id}_styleSelect" onfocus="tinyMCE.addSelectAccessibility(event,this,window);" onchange="tinyMCE.execInstanceCommand(\'{$editor_id}\',\'mceSetCSSClass\',false,this.options[this.selectedIndex].value);" class="mceSelectList">{$style_select_options}</select>';
+		_createBlockFormats : function() {
+			var c, fmts = {
+				p : 'advanced.paragraph',
+				address : 'advanced.address',
+				pre : 'advanced.pre',
+				h1 : 'advanced.h1',
+				h2 : 'advanced.h2',
+				h3 : 'advanced.h3',
+				h4 : 'advanced.h4',
+				h5 : 'advanced.h5',
+				h6 : 'advanced.h6',
+				div : 'advanced.div',
+				blockquote : 'advanced.blockquote',
+				code : 'advanced.code',
+				dt : 'advanced.dt',
+				dd : 'advanced.dd',
+				samp : 'advanced.samp'
+			}, t = this;
+
+			c = t.editor.controlManager.createListBox('formatselect', {title : 'advanced.block', cmd : 'FormatBlock'});
 
-			case "fontselect":
-				var fontHTML = '<select id="{$editor_id}_fontNameSelect" name="{$editor_id}_fontNameSelect" onfocus="tinyMCE.addSelectAccessibility(event, this, window);" onchange="tinyMCE.execInstanceCommand(\'{$editor_id}\',\'FontName\',false,this.options[this.selectedIndex].value);" class="mceSelectList"><option value="">{$lang_theme_fontdefault}</option>';
-				var iFonts = 'Arial=arial,helvetica,sans-serif;Courier New=courier new,courier,monospace;Georgia=georgia,times new roman,times,serif;Tahoma=tahoma,arial,helvetica,sans-serif;Times New Roman=times new roman,times,serif;Verdana=verdana,arial,helvetica,sans-serif;Impact=impact;WingDings=wingdings';
-				var nFonts = 'Andale Mono=andale mono,times;Arial=arial,helvetica,sans-serif;Arial Black=arial black,avant garde;Book Antiqua=book antiqua,palatino;Comic Sans MS=comic sans ms,sand;Courier New=courier new,courier;Georgia=georgia,palatino;Helvetica=helvetica;Impact=impact,chicago;Symbol=symbol;Tahoma=tahoma,arial,helvetica,sans-serif;Terminal=terminal,monaco;Times New Roman=times new roman,times;Trebuchet MS=trebuchet ms,geneva;Verdana=verdana,geneva;Webdings=webdings;Wingdings=wingdings,zapf dingbats';
-				var fonts = tinyMCE.getParam("theme_advanced_fonts", nFonts).split(';');
-				for (i=0; i<fonts.length; i++) {
-					if (fonts[i] != '') {
-						var parts = fonts[i].split('=');
-						fontHTML += '<option value="' + parts[1] + '">' + parts[0] + '</option>';
-					}
-				}
+			each(t.settings.theme_advanced_blockformats.split(','), function(v) {
+				c.add(t.editor.translate(fmts[v]), v, {element : v, 'class' : v.indexOf('h') == 0 ? '' : 'preview'});
+			});
+
+			return c;
+		},
+
+		_createForeColorMenu : function() {
+			var c, t = this, s = t.settings, o = {}, v;
 
-				fontHTML += '</select>';
-				return fontHTML;
+			if (s.theme_advanced_more_colors) {
+				o.more_colors_func = function() {
+					t._mceColorPicker(0, {
+						color : c.value,
+						func : function(co) {
+							c.setColor(co);
+						}
+					});
+				};
+			}
 
-			case "fontsizeselect":
-				return '<select id="{$editor_id}_fontSizeSelect" name="{$editor_id}_fontSizeSelect" onfocus="tinyMCE.addSelectAccessibility(event, this, window);" onchange="tinyMCE.execInstanceCommand(\'{$editor_id}\',\'FontSize\',false,this.options[this.selectedIndex].value);" class="mceSelectList">'+
-						'<option value="0">{$lang_theme_font_size}</option>'+
-						'<option value="1">1 (8 pt)</option>'+
-						'<option value="2">2 (10 pt)</option>'+
-						'<option value="3">3 (12 pt)</option>'+
-						'<option value="4">4 (14 pt)</option>'+
-						'<option value="5">5 (18 pt)</option>'+
-						'<option value="6">6 (24 pt)</option>'+
-						'<option value="7">7 (36 pt)</option>'+
-						'</select>';
+			if (v = s.theme_advanced_text_colors)
+				o.colors = v;
+
+			o.title = 'advanced.forecolor_desc';
+			o.cmd = 'ForeColor';
+			o.scope = this;
+
+			c = t.editor.controlManager.createColorSplitButton('forecolor', o);
+
+			return c;
+		},
+
+		_createBackColorMenu : function() {
+			var c, t = this, s = t.settings, o = {}, v;
+
+			if (s.theme_advanced_more_colors) {
+				o.more_colors_func = function() {
+					t._mceColorPicker(0, {
+						color : c.value,
+						func : function(co) {
+							c.setColor(co);
+						}
+					});
+				};
+			}
+
+			if (v = s.theme_advanced_background_colors)
+				o.colors = v;
 
-			case "|":
-			case "separator":
-				return '<img src="{$themeurl}/images/separator.gif" width="2" height="20" class="mceSeparatorLine" />';
+			o.title = 'advanced.backcolor_desc';
+			o.cmd = 'HiliteColor';
+			o.scope = this;
+
+			c = t.editor.controlManager.createColorSplitButton('backcolor', o);
 
-			case "spacer":
-				return '<img src="{$themeurl}/images/separator.gif" width="2" height="15" border="0" class="mceSeparatorLine" style="vertical-align: middle" />';
+			return c;
+		},
+
+		renderUI : function(o) {
+			var n, ic, tb, t = this, ed = t.editor, s = t.settings, sc, p, nl;
+
+			n = p = DOM.create('div', {id : ed.id + '_parent', 'class' : 'mceEditor ' + ed.settings.skin + 'Skin'});
+
+			if (!DOM.boxModel)
+				n = DOM.add(n, 'div', {'class' : 'mceOldBoxModel'});
 
-			case "rowseparator":
-				return '<br />';
-		}
+			n = sc = DOM.add(n, 'table', {id : ed.id + '_tbl', 'class' : 'mceLayout', cellSpacing : 0, cellPadding : 0});
+			n = tb = DOM.add(n, 'tbody');
+
+			switch ((s.theme_advanced_layout_manager || '').toLowerCase()) {
+				case "rowlayout":
+					ic = t._rowLayout(s, tb, o);
+					break;
 
-		return "";
-	},
+				case "customlayout":
+					ic = ed.execCallback("theme_advanced_custom_layout", s, tb, o, p);
+					break;
+
+				default:
+					ic = t._simpleLayout(s, tb, o, p);
+			}
+
+			n = o.targetNode;
 
-	/**
-	 * Theme specific execcommand handling.
-	 */
-	execCommand : function(editor_id, element, command, user_interface, value) {
-		switch (command) {
-			case 'mceHelp':
-				tinyMCE.openWindow({
-					file : 'about.htm',
-					width : 480,
-					height : 380
-				}, {
-					tinymce_version : tinyMCE.majorVersion + "." + tinyMCE.minorVersion,
-					tinymce_releasedate : tinyMCE.releaseDate,
-					inline : "yes"
-				});
-			return true;
+			// Add classes to first and last TRs
+			nl = sc.rows;
+			DOM.addClass(nl[0], 'first');
+			DOM.addClass(nl[nl.length - 1], 'last');
+
+			// Add classes to first and last TDs
+			each(DOM.select('tr', tb), function(n) {
+				DOM.addClass(n.firstChild, 'first');
+				DOM.addClass(n.childNodes[n.childNodes.length - 1], 'last');
+			});
+
+			if (DOM.get(s.theme_advanced_toolbar_container))
+				DOM.get(s.theme_advanced_toolbar_container).appendChild(p);
+			else
+				DOM.insertAfter(p, n);
+
+			Event.add(ed.id + '_path_row', 'click', function(e) {
+				e = e.target;
+
+				if (e.nodeName == 'A') {
+					t._sel(e.href.replace(/^[^#]*#/, ''));
+
+					return Event.cancel(e);
+				}
+			});
+/*
+			if (DOM.get(ed.id + '_path_row')) {
+				Event.add(ed.id + '_tbl', 'mouseover', function(e) {
+					var re;
+	
+					e = e.target;
 
-			case "mceLink":
-				var inst = tinyMCE.getInstanceById(editor_id);
-				var doc = inst.getDoc();
-				var selectedText = "";
+					if (e.nodeName == 'SPAN' && DOM.hasClass(e.parentNode, 'mceButton')) {
+						re = DOM.get(ed.id + '_path_row');
+						t.lastPath = re.innerHTML;
+						DOM.setHTML(re, e.parentNode.title);
+					}
+				});
+
+				Event.add(ed.id + '_tbl', 'mouseout', function(e) {
+					if (t.lastPath) {
+						DOM.setHTML(ed.id + '_path_row', t.lastPath);
+						t.lastPath = 0;
+					}
+				});
+			}
+*/
 
-				if (tinyMCE.isMSIE) {
-					var rng = doc.selection.createRange();
-					selectedText = rng.text;
-				} else
-					selectedText = inst.getSel().toString();
+			if (!ed.getParam('accessibility_focus') || ed.getParam('tab_focus'))
+				Event.add(DOM.add(p, 'a', {href : '#'}, '<!-- IE -->'), 'focus', function() {tinyMCE.get(ed.id).focus();});
+
+			if (s.theme_advanced_toolbar_location == 'external')
+				o.deltaHeight = 0;
 
-				if (!tinyMCE.linkElement) {
-					if ((tinyMCE.selectedElement.nodeName.toLowerCase() != "img") && (selectedText.length <= 0))
-						return true;
-				}
+			t.deltaHeight = o.deltaHeight;
+			o.targetNode = null;
 
-				var href = "", target = "", title = "", onclick = "", action = "insert", style_class = "";
+			return {
+				iframeContainer : ic,
+				editorContainer : ed.id + '_parent',
+				sizeContainer : sc,
+				deltaHeight : o.deltaHeight
+			};
+		},
 
-				if (tinyMCE.selectedElement.nodeName.toLowerCase() == "a")
-					tinyMCE.linkElement = tinyMCE.selectedElement;
+		getInfo : function() {
+			return {
+				longname : 'Simple theme',
+				author : 'Moxiecode Systems AB',
+				authorurl : 'http://tinymce.moxiecode.com',
+				version : tinymce.majorVersion + "." + tinymce.minorVersion
+			}
+		},
 
-				// Is anchor not a link
-				if (tinyMCE.linkElement != null && tinyMCE.getAttrib(tinyMCE.linkElement, 'href') == "")
-					tinyMCE.linkElement = null;
+		_simpleLayout : function(s, tb, o, p) {
+			var t = this, ed = t.editor, lo = s.theme_advanced_toolbar_location, sl = s.theme_advanced_statusbar_location, n, ic, etb, c;
 
-				if (tinyMCE.linkElement) {
-					href = tinyMCE.getAttrib(tinyMCE.linkElement, 'href');
-					target = tinyMCE.getAttrib(tinyMCE.linkElement, 'target');
-					title = tinyMCE.getAttrib(tinyMCE.linkElement, 'title');
-					onclick = tinyMCE.getAttrib(tinyMCE.linkElement, 'onclick');
-					style_class = tinyMCE.getAttrib(tinyMCE.linkElement, 'class');
+			// Create toolbar container at top
+			if (lo == 'top')
+				t._addToolbars(tb, o);
+
+			// Create external toolbar
+			if (lo == 'external') {
+				n = c = DOM.create('div', {style : 'position:relative'});
+				n = DOM.add(n, 'div', {id : ed.id + '_external', 'class' : 'mceExternalToolbar'});
+				DOM.add(n, 'a', {id : ed.id + '_external_close', href : 'javascript:;', 'class' : 'mceExternalClose'});
+				n = DOM.add(n, 'table', {id : ed.id + '_tblext', cellSpacing : 0, cellPadding : 0});
+				etb = DOM.add(n, 'tbody');
+
+				if (p.firstChild.className == 'mceOldBoxModel')
+					p.firstChild.appendChild(c);
+				else
+					p.insertBefore(c, p.firstChild);
+
+				t._addToolbars(etb, o);
 
-					// Try old onclick to if copy/pasted content
-					if (onclick == "")
-						onclick = tinyMCE.getAttrib(tinyMCE.linkElement, 'onclick');
+				ed.onMouseUp.add(function() {
+					var e = DOM.get(ed.id + '_external');
+					DOM.show(e);
+
+					DOM.hide(lastExtID);
 
-					onclick = tinyMCE.cleanupEventStr(onclick);
+					var f = Event.add(ed.id + '_external_close', 'click', function() {
+						DOM.hide(ed.id + '_external');
+						Event.remove(ed.id + '_external_close', 'click', f);
+					});
 
-					href = eval(tinyMCE.settings['urlconverter_callback'] + "(href, tinyMCE.linkElement, true);");
+					DOM.show(e);
+					DOM.setStyle(e, 'top', 0 - DOM.getRect(ed.id + '_tblext').h - 1);
+
+					// Fixes IE rendering bug
+					DOM.hide(e);
+					DOM.show(e);
+					e.style.filter = '';
 
-					// Use mce_href if defined
-					mceRealHref = tinyMCE.getAttrib(tinyMCE.linkElement, 'mce_href');
-					if (mceRealHref != "") {
-						href = mceRealHref;
+					lastExtID = ed.id + '_external';
+
+					e = null;
+				});
+			}
+
+			if (sl == 'top')
+				t._addStatusBar(tb, o);
 
-						if (tinyMCE.getParam('convert_urls'))
-							href = eval(tinyMCE.settings['urlconverter_callback'] + "(href, tinyMCE.linkElement, true);");
-					}
+			// Create iframe container
+			if (!s.theme_advanced_toolbar_container) {
+				n = DOM.add(tb, 'tr');
+				n = ic = DOM.add(n, 'td', {'class' : 'mceIframeContainer'});
+			}
+
+			// Create toolbar container at bottom
+			if (lo == 'bottom')
+				t._addToolbars(tb, o);
 
-					action = "update";
-				}
+			if (sl == 'bottom')
+				t._addStatusBar(tb, o);
+
+			return ic;
+		},
 
-				var template = new Array();
+		_rowLayout : function(s, tb, o) {
+			var t = this, ed = t.editor, dc, da, cf = ed.controlManager, n, ic, to;
+
+			dc = s.theme_advanced_containers_default_class || '';
+			da = s.theme_advanced_containers_default_align || 'center';
+
+			each((s.theme_advanced_containers || '').split(','), function(c, i) {
+				var v = s['theme_advanced_container_' + c] || '';
 
-				template['file'] = 'link.htm';
-				template['width'] = 310;
-				template['height'] = 200;
+				switch (c.toLowerCase()) {
+					case 'mceeditor':
+						n = DOM.add(tb, 'tr');
+						n = ic = DOM.add(n, 'td', {'class' : 'mceIframeContainer'});
+						break;
 
-				// Language specific width and height addons
-				template['width'] += tinyMCE.getLang('lang_insert_link_delta_width', 0);
-				template['height'] += tinyMCE.getLang('lang_insert_link_delta_height', 0);
+					case 'mceelementpath':
+						t._addStatusBar(tb, o);
+						break;
+
+					default:
+						n = DOM.add(DOM.add(tb, 'tr'), 'td', {
+							'class' : 'mceToolbar ' + (s['theme_advanced_container_' + c + '_class'] || dc),
+							align : s['theme_advanced_container_' + c + '_align'] || da
+						});
 
-				if (inst.settings['insertlink_callback']) {
-					var returnVal = eval(inst.settings['insertlink_callback'] + "(href, target, title, onclick, action, style_class);");
-					if (returnVal && returnVal['href'])
-						TinyMCE_AdvancedTheme._insertLink(returnVal['href'], returnVal['target'], returnVal['title'], returnVal['onclick'], returnVal['style_class']);
-				} else {
-					tinyMCE.openWindow(template, {href : href, target : target, title : title, onclick : onclick, action : action, className : style_class, inline : "yes"});
+						to = cf.createToolbar("toolbar" + i);
+						t._addControls(v, to);
+						DOM.setHTML(n, to.renderHTML());
+						o.deltaHeight -= s.theme_advanced_row_height;
 				}
+			});
 
-				return true;
+			return ic;
+		},
+
+		_addControls : function(v, tb) {
+			var t = this, s = t.settings, di, cf = t.editor.controlManager;
+
+			if (s.theme_advanced_disable && !t._disabled) {
+				di = {};
+
+				each(s.theme_advanced_disable.split(','), function(v) {
+					di[v] = 1;
+				});
 
-			case "mceImage":
-				var src = "", alt = "", border = "", hspace = "", vspace = "", width = "", height = "", align = "";
-				var title = "", onmouseover = "", onmouseout = "", action = "insert";
-				var img = tinyMCE.imgElement;
-				var inst = tinyMCE.getInstanceById(editor_id);
+				t._disabled = di;
+			} else
+				di = t._disabled;
+
+			each(v.split(','), function(n) {
+				var c;
+
+				if (di && di[n])
+					return;
 
-				if (tinyMCE.selectedElement != null && tinyMCE.selectedElement.nodeName.toLowerCase() == "img") {
-					img = tinyMCE.selectedElement;
-					tinyMCE.imgElement = img;
+				// Compatiblity with 2.x
+				if (n == 'tablecontrols') {
+					each(["table","|","row_props","cell_props","|","row_before","row_after","delete_row","|","col_before","col_after","delete_col","|","split_cells","merge_cells"], function(n) {
+						n = t.createControl(n, cf);
+
+						if (n)
+							tb.add(n);
+					});
+
+					return;
 				}
 
-				if (img) {
-					// Is it a internal MCE visual aid image, then skip this one.
-					if (tinyMCE.getAttrib(img, 'name').indexOf('mce_') == 0)
-						return true;
+				c = t.createControl(n, cf);
 
-					src = tinyMCE.getAttrib(img, 'src');
-					alt = tinyMCE.getAttrib(img, 'alt');
+				if (c)
+					tb.add(c);
+			});
+		},
 
-					// Try polling out the title
-					if (alt == "")
-						alt = tinyMCE.getAttrib(img, 'title');
+		_addToolbars : function(c, o) {
+			var t = this, i, tb, ed = t.editor, s = t.settings, v, cf = ed.controlManager, di, n, h = [];
 
-					// Fix width/height attributes if the styles is specified
-					if (tinyMCE.isGecko) {
-						var w = img.style.width;
-						if (w != null && w != "")
-							img.setAttribute("width", w);
+			n = DOM.add(DOM.add(c, 'tr'), 'td', {'class' : 'mceToolbar', align : s.theme_advanced_toolbar_align});
+
+			if (!ed.getParam('accessibility_focus') || ed.getParam('tab_focus'))
+				h.push(DOM.createHTML('a', {href : '#', onfocus : 'tinyMCE.get(\'' + ed.id + '\').focus();'}, '<!-- IE -->'));
 
-						var h = img.style.height;
-						if (h != null && h != "")
-							img.setAttribute("height", h);
-					}
+			h.push(DOM.createHTML('a', {href : '#', accesskey : 'q', title : ed.getLang("advanced.toolbar_focus")}, '<!-- IE -->'));
+
+			// Create toolbar and add the controls
+			for (i=1; (v = s['theme_advanced_buttons' + i]); i++) {
+				tb = cf.createToolbar("toolbar" + i, {'class' : 'mceToolbarRow' + i});
 
-					border = tinyMCE.getAttrib(img, 'border');
-					hspace = tinyMCE.getAttrib(img, 'hspace');
-					vspace = tinyMCE.getAttrib(img, 'vspace');
-					width = tinyMCE.getAttrib(img, 'width');
-					height = tinyMCE.getAttrib(img, 'height');
-					align = tinyMCE.getAttrib(img, 'align');
-					onmouseover = tinyMCE.getAttrib(img, 'onmouseover');
-					onmouseout = tinyMCE.getAttrib(img, 'onmouseout');
-					title = tinyMCE.getAttrib(img, 'title');
+				if (s['theme_advanced_buttons' + i + '_add'])
+					v += ',' + s['theme_advanced_buttons' + i + '_add'];
 
-					// Is realy specified?
-					if (tinyMCE.isMSIE) {
-						width = img.attributes['width'].specified ? width : "";
-						height = img.attributes['height'].specified ? height : "";
-					}
+				if (s['theme_advanced_buttons' + i + '_add_before'])
+					v = s['theme_advanced_buttons' + i + '_add_before'] + ',' + v;
 
-					//onmouseover = tinyMCE.getImageSrc(tinyMCE.cleanupEventStr(onmouseover));
-					//onmouseout = tinyMCE.getImageSrc(tinyMCE.cleanupEventStr(onmouseout));
+				t._addControls(v, tb);
 
-					src = eval(tinyMCE.settings['urlconverter_callback'] + "(src, img, true);");
+				//n.appendChild(n = tb.render());
+				h.push(tb.renderHTML());
 
-					// Use mce_src if defined
-					mceRealSrc = tinyMCE.getAttrib(img, 'mce_src');
-					if (mceRealSrc != "") {
-						src = mceRealSrc;
+				o.deltaHeight -= s.theme_advanced_row_height;
+			}
 
-						if (tinyMCE.getParam('convert_urls'))
-							src = eval(tinyMCE.settings['urlconverter_callback'] + "(src, img, true);");
-					}
-
-					//if (onmouseover != "")
-					//	onmouseover = eval(tinyMCE.settings['urlconverter_callback'] + "(onmouseover, img, true);");
+			h.push(DOM.createHTML('a', {href : '#', accesskey : 'z', title : ed.getLang("advanced.toolbar_focus"), onfocus : 'tinyMCE.getInstanceById(\'' + ed.id + '\').focus();'}, '<!-- IE -->'));
+			DOM.setHTML(n, h.join(''));
+		},
 
-					//if (onmouseout != "")
-					//	onmouseout = eval(tinyMCE.settings['urlconverter_callback'] + "(onmouseout, img, true);");
-
-					action = "update";
-				}
+		_addStatusBar : function(tb, o) {
+			var n, t = this, ed = t.editor, s = t.settings, r, mf, me, td;
 
-				var template = new Array();
-
-				template['file'] = 'image.htm?src={$src}';
-				template['width'] = 355;
-				template['height'] = 265 + (tinyMCE.isMSIE ? 25 : 0);
+			n = DOM.add(tb, 'tr');
+			n = td = DOM.add(n, 'td', {'class' : 'mceStatusbar'});
+			n = DOM.add(n, 'div', {id : ed.id + '_path_row'}, s.theme_advanced_path ? ed.translate('advanced.path') + ': ' : '&nbsp;');
+			DOM.add(n, 'a', {href : '#', accesskey : 'x'});
 
-				// Language specific width and height addons
-				template['width'] += tinyMCE.getLang('lang_insert_image_delta_width', 0);
-				template['height'] += tinyMCE.getLang('lang_insert_image_delta_height', 0);
+			if (s.theme_advanced_resizing && !tinymce.isOldWebKit) {
+				DOM.add(td, 'a', {id : ed.id + '_resize', href : 'javascript:;', onclick : "return false;", 'class' : 'resize'});
 
-				if (inst.settings['insertimage_callback']) {
-					var returnVal = eval(inst.settings['insertimage_callback'] + "(src, alt, border, hspace, vspace, width, height, align, title, onmouseover, onmouseout, action);");
-					if (returnVal && returnVal['src'])
-						TinyMCE_AdvancedTheme._insertImage(returnVal['src'], returnVal['alt'], returnVal['border'], returnVal['hspace'], returnVal['vspace'], returnVal['width'], returnVal['height'], returnVal['align'], returnVal['title'], returnVal['onmouseover'], returnVal['onmouseout']);
-				} else
-					tinyMCE.openWindow(template, {src : src, alt : alt, border : border, hspace : hspace, vspace : vspace, width : width, height : height, align : align, title : title, onmouseover : onmouseover, onmouseout : onmouseout, action : action, inline : "yes"});
-
-				return true;
+				if (s.theme_advanced_resizing_use_cookie) {
+					ed.onPostRender.add(function() {
+						var o = Cookie.getHash("TinyMCE_" + ed.id + "_size"), c = DOM.get(ed.id + '_tbl');
 
-			case "forecolor":
-				var fcp = new TinyMCE_Layer(editor_id + '_fcPreview', false), p, img, elm;
-
-				TinyMCE_AdvancedTheme._hideMenus(editor_id);
+						if (!o)
+							return;
 
-				if (!fcp.exists()) {
-					fcp.create('div', 'mceColorPreview', document.getElementById(editor_id + '_toolbar'));
-					elm = fcp.getElement();
-					elm._editor_id = editor_id;
-					elm._command = "forecolor";
-					elm._switchId = editor_id + "_forecolor";
-					tinyMCE.addEvent(elm, 'click', TinyMCE_AdvancedTheme._handleMenuEvent);
-					tinyMCE.addEvent(elm, 'mouseover', TinyMCE_AdvancedTheme._handleMenuEvent);
-					tinyMCE.addEvent(elm, 'mouseout', TinyMCE_AdvancedTheme._handleMenuEvent);
+						if (s.theme_advanced_resize_horizontal)
+							c.style.width = o.cw + 'px';
+
+						c.style.height = o.ch + 'px';
+						DOM.get(ed.id + '_ifr').style.height = (parseInt(o.ch) + t.deltaHeight) + 'px';
+					});
 				}
 
-				img = tinyMCE.selectNodes(document.getElementById(editor_id + "_forecolor"), function(n) {return n.nodeName == "IMG";})[0];
-				p = tinyMCE.getAbsPosition(img, document.getElementById(editor_id + '_toolbar'));
-
-				fcp.moveTo(p.absLeft, p.absTop);
-				fcp.getElement().style.backgroundColor = value != null ? value : tinyMCE.getInstanceById(editor_id).foreColor;
-				fcp.show();
-
-				return false;
+				ed.onPostRender.add(function() {
+					Event.add(ed.id + '_resize', 'mousedown', function(e) {
+						var c, p, w, h, n, pa;
 
-			case "forecolorpicker":
-				this._pickColor(editor_id, 'forecolor');
-				return true;
-
-			case "forecolorMenu":
-				TinyMCE_AdvancedTheme._hideMenus(editor_id);
-
-				// Create color layer
-				var ml = new TinyMCE_Layer(editor_id + '_fcMenu');
+						// Measure container
+						c = DOM.get(ed.id + '_tbl');
+						w = c.clientWidth;
+						h = c.clientHeight;
 
-				if (!ml.exists())
-					ml.create('div', 'mceMenu', document.body, TinyMCE_AdvancedTheme._getColorHTML(editor_id, 'theme_advanced_text_colors', 'forecolor'));
-
-				tinyMCE.switchClass(editor_id + '_forecolor', 'mceMenuButtonFocus');
-				ml.moveRelativeTo(document.getElementById(editor_id + "_forecolor"), 'bl');
-
-				ml.moveBy(tinyMCE.isMSIE && !tinyMCE.isOpera ? -1 : 1, -1);
+						miw = s.theme_advanced_resizing_min_width || 100;
+						mih = s.theme_advanced_resizing_min_height || 100;
+						maw = s.theme_advanced_resizing_max_width || 0xFFFF;
+						mah = s.theme_advanced_resizing_max_height || 0xFFFF;
 
-				if (tinyMCE.isOpera)
-					ml.moveBy(0, -2);
+						// Setup placeholder
+						p = DOM.add(DOM.get(ed.id + '_parent'), 'div', {'class' : 'mcePlaceHolder'});
+						DOM.setStyles(p, {width : w, height : h});
 
-				ml.show();
-			return true;
-
-			case "HiliteColor":
-				var bcp = new TinyMCE_Layer(editor_id + '_bcPreview', false), p, img;
-
-				TinyMCE_AdvancedTheme._hideMenus(editor_id);
+						// Replace with placeholder
+						DOM.hide(c);
+						DOM.show(p);
 
-				if (!bcp.exists()) {
-					bcp.create('div', 'mceColorPreview', document.getElementById(editor_id + '_toolbar'));
-					elm = bcp.getElement();
-					elm._editor_id = editor_id;
-					elm._command = "HiliteColor";
-					elm._switchId = editor_id + "_backcolor";
-					tinyMCE.addEvent(elm, 'click', TinyMCE_AdvancedTheme._handleMenuEvent);
-					tinyMCE.addEvent(elm, 'mouseover', TinyMCE_AdvancedTheme._handleMenuEvent);
-					tinyMCE.addEvent(elm, 'mouseout', TinyMCE_AdvancedTheme._handleMenuEvent);
-				}
+						// Create internal resize obj
+						r = {
+							x : e.screenX,
+							y : e.screenY,
+							w : w,
+							h : h,
+							dx : null,
+							dy : null
+						};
 
-				img = tinyMCE.selectNodes(document.getElementById(editor_id + "_backcolor"), function(n) {return n.nodeName == "IMG";})[0];
-				p = tinyMCE.getAbsPosition(img, document.getElementById(editor_id + '_toolbar'));
-
-				bcp.moveTo(p.absLeft, p.absTop);
-				bcp.getElement().style.backgroundColor = value != null ? value : tinyMCE.getInstanceById(editor_id).backColor;
-				bcp.show();
-
-				return false;
-
-			case "HiliteColorMenu":
-				TinyMCE_AdvancedTheme._hideMenus(editor_id);
+						// Start listening
+						mf = Event.add(document, 'mousemove', function(e) {
+							var w, h;
 
-				// Create color layer
-				var ml = new TinyMCE_Layer(editor_id + '_bcMenu');
-
-				if (!ml.exists())
-					ml.create('div', 'mceMenu', document.body, TinyMCE_AdvancedTheme._getColorHTML(editor_id, 'theme_advanced_background_colors', 'HiliteColor'));
-
-				tinyMCE.switchClass(editor_id + '_backcolor', 'mceMenuButtonFocus');
-				ml.moveRelativeTo(document.getElementById(editor_id + "_backcolor"), 'bl');
-
-				ml.moveBy(tinyMCE.isMSIE && !tinyMCE.isOpera ? -1 : 1, -1);
-
-				if (tinyMCE.isOpera)
-					ml.moveBy(0, -2);
+							// Calc delta values
+							r.dx = e.screenX - r.x;
+							r.dy = e.screenY - r.y;
 
-				ml.show();
-			return true;
-	
-			case "backcolorpicker":
-				this._pickColor(editor_id, 'HiliteColor');
-				return true;
+							// Boundery fix box
+							w = Math.max(miw, r.w + r.dx);
+							h = Math.max(mih, r.h + r.dy);
+							w = Math.min(maw, w);
+							h = Math.min(mah, h);
 
-			case "mceColorPicker":
-				if (user_interface) {
-					var template = [];
-	
-					if (!value['callback'] && !value['color'])
-						value['color'] = value['document'].getElementById(value['element_id']).value;
+							// Resize placeholder
+							if (s.theme_advanced_resize_horizontal)
+								p.style.width = w + 'px';
+
+							p.style.height = h + 'px';
+
+							return Event.cancel(e);
+						});
 
-					template['file'] = 'color_picker.htm';
-					template['width'] = 380;
-					template['height'] = 250;
-					template['close_previous'] = "no";
-
-					template['width'] += tinyMCE.getLang('lang_theme_advanced_colorpicker_delta_width', 0);
-					template['height'] += tinyMCE.getLang('lang_theme_advanced_colorpicker_delta_height', 0);
+						me = Event.add(document, 'mouseup', function(e) {
+							var ifr;
 
-					if (typeof(value['store_selection']) == "undefined")
-						value['store_selection'] = true;
+							// Stop listening
+							Event.remove(document, 'mousemove', mf);
+							Event.remove(document, 'mouseup', me);
 
-					tinyMCE.lastColorPickerValue = value;
-					tinyMCE.openWindow(template, {editor_id : editor_id, mce_store_selection : value['store_selection'], inline : "yes", command : "mceColorPicker", input_color : value['color']});
-				} else {
-					var savedVal = tinyMCE.lastColorPickerValue, elm;
-
-					if (savedVal['callback']) {
-						savedVal['callback'](value);
-						return true;
-					}
+							c.style.display = '';
+							DOM.remove(p);
 
-					elm = savedVal['document'].getElementById(savedVal['element_id']);
-					elm.value = value;
+							if (r.dx === null)
+								return;
 
-					if (elm.onchange != null && elm.onchange != '')
-						eval('elm.onchange();');
-				}
-			return true;
-
-			case "mceCodeEditor":
-				var template = new Array();
+							ifr = DOM.get(ed.id + '_ifr');
 
-				template['file'] = 'source_editor.htm';
-				template['width'] = parseInt(tinyMCE.getParam("theme_advanced_source_editor_width", 720));
-				template['height'] = parseInt(tinyMCE.getParam("theme_advanced_source_editor_height", 580));
-
-				tinyMCE.openWindow(template, {editor_id : editor_id, resizable : "yes", scrollbars : "no", inline : "yes"});
-				return true;
+							if (s.theme_advanced_resize_horizontal)
+								c.style.width = (r.w + r.dx) + 'px';
 
-			case "mceCharMap":
-				var template = new Array();
-
-				template['file'] = 'charmap.htm';
-				template['width'] = 550 + (tinyMCE.isOpera ? 40 : 0);
-				template['height'] = 250;
+							c.style.height = (r.h + r.dy) + 'px';
+							ifr.style.height = (ifr.clientHeight + r.dy) + 'px';
 
-				template['width'] += tinyMCE.getLang('lang_theme_advanced_charmap_delta_width', 0);
-				template['height'] += tinyMCE.getLang('lang_theme_advanced_charmap_delta_height', 0);
-
-				tinyMCE.openWindow(template, {editor_id : editor_id, inline : "yes"});
-				return true;
-
-			case "mceInsertAnchor":
-				var template = new Array();
+							if (s.theme_advanced_resizing_use_cookie) {
+								Cookie.setHash("TinyMCE_" + ed.id + "_size", {
+									cw : r.w + r.dx,
+									ch : r.h + r.dy
+								});
+							}
+						});
 
-				template['file'] = 'anchor.htm';
-				template['width'] = 320;
-				template['height'] = 90 + (tinyMCE.isNS7 ? 30 : 0);
-
-				template['width'] += tinyMCE.getLang('lang_theme_advanced_anchor_delta_width', 0);
-				template['height'] += tinyMCE.getLang('lang_theme_advanced_anchor_delta_height', 0);
+						return Event.cancel(e);
+					});
+				});
+			}
 
-				tinyMCE.openWindow(template, {editor_id : editor_id, inline : "yes"});
-				return true;
-
-			case "mceNewDocument":
-				if (confirm(tinyMCE.getLang('lang_newdocument')))
-					tinyMCE.execInstanceCommand(editor_id, 'mceSetContent', false, ' ');
+			o.deltaHeight -= 21;
+			n = tb = null;
+		},
 
-				return true;
-		}
+		_nodeChanged : function(ed, cm, n, co) {
+			var t = this, p, de = 0, v, c, s = t.settings;
 
-		return false;
-	},
+			tinymce.each(t.stateControls, function(c) {
+				cm.setActive(c, ed.queryCommandState(t.controls[c][1]));
+			});
 
-	/**
-	 * Editor instance template function.
-	 */
-	getEditorTemplate : function(settings, editorId) {
-		function removeFromArray(in_array, remove_array) {
-			var outArray = new Array(), skip;
-			
-			for (var i=0; i<in_array.length; i++) {
-				skip = false;
+			cm.setActive('visualaid', ed.hasVisual);
+			cm.setDisabled('undo', !ed.undoManager.hasUndo() && !ed.typing);
+			cm.setDisabled('redo', !ed.undoManager.hasRedo());
+			cm.setDisabled('outdent', !ed.queryCommandState('Outdent'));
 
-				for (var j=0; j<remove_array.length; j++) {
-					if (in_array[i] == remove_array[j]) {
-						skip = true;
-					}
-				}
-
-				if (!skip) {
-					outArray[outArray.length] = in_array[i];
+			p = DOM.getParent(n, 'A');
+			if (c = cm.get('link')) {
+				if (!p || !p.name) {
+					c.setDisabled(!p && co);
+					c.setActive(!!p);
 				}
 			}
 
-			return outArray;
-		}
-
-		function addToArray(in_array, add_array) {
-			for (var i=0; i<add_array.length; i++) {
-				in_array[in_array.length] = add_array[i];
-			}
-
-			return in_array;
-		}
-
-		var template = new Array();
-		var deltaHeight = 0;
-		var resizing = tinyMCE.getParam("theme_advanced_resizing", false);
-		var path = tinyMCE.getParam("theme_advanced_path", true);
-		var statusbarHTML = '<div id="{$editor_id}_path" class="mceStatusbarPathText" style="display: ' + (path ? "block" : "none") + '">&#160;</div><div id="{$editor_id}_resize" class="mceStatusbarResize" style="display: ' + (resizing ? "block" : "none") + '" onmousedown="tinyMCE.themes.advanced._setResizing(event,\'{$editor_id}\',true);"></div><br style="clear: both" />';
-		var layoutManager = tinyMCE.getParam("theme_advanced_layout_manager", "SimpleLayout");
-
-		// Setup style select options -- MOVED UP FOR EXTERNAL TOOLBAR COMPATABILITY!
-		var styleSelectHTML = '<option value="">{$lang_theme_style_select}</option>';
-		if (settings['theme_advanced_styles']) {
-			var stylesAr = settings['theme_advanced_styles'].split(';');
-			
-			for (var i=0; i<stylesAr.length; i++) {
-				var key, value;
-
-				key = stylesAr[i].split('=')[0];
-				value = stylesAr[i].split('=')[1];
-
-				styleSelectHTML += '<option value="' + value + '">' + key + '</option>';
+			if (c = cm.get('unlink')) {
+				c.setDisabled(!p && co);
+				c.setActive(!!p && !p.name);
 			}
 
-			TinyMCE_AdvancedTheme._autoImportCSSClasses = false;
-		}
-
-		switch(layoutManager) {
-			case "SimpleLayout" : //the default TinyMCE Layout (for backwards compatibility)...
-				var toolbarHTML = "";
-				var toolbarLocation = tinyMCE.getParam("theme_advanced_toolbar_location", "bottom");
-				var toolbarAlign = tinyMCE.getParam("theme_advanced_toolbar_align", "center");
-				var pathLocation = tinyMCE.getParam("theme_advanced_path_location", "none"); // Compatiblity
-				var statusbarLocation = tinyMCE.getParam("theme_advanced_statusbar_location", pathLocation);
-				var defVals = {
-					theme_advanced_buttons1 : "bold,italic,underline,strikethrough,separator,justifyleft,justifycenter,justifyright,justifyfull,separator,styleselect,formatselect",
-					theme_advanced_buttons2 : "bullist,numlist,separator,outdent,indent,separator,undo,redo,separator,link,unlink,anchor,image,cleanup,help,code",
-					theme_advanced_buttons3 : "hr,removeformat,visualaid,separator,sub,sup,separator,charmap"
-				};
-
-				// Add accessibility control
-				toolbarHTML += '<a href="#" accesskey="q" title="' + tinyMCE.getLang("lang_toolbar_focus") + '"';
-
-				if (!tinyMCE.getParam("accessibility_focus"))
-					toolbarHTML += ' onfocus="tinyMCE.getInstanceById(\'' + editorId + '\').getWin().focus();"';
-
-				toolbarHTML += '></a>';
-
-				// Render rows
-				for (var i=1; i<100; i++) {
-					var def = defVals["theme_advanced_buttons" + i];
-
-					var buttons = tinyMCE.getParam("theme_advanced_buttons" + i, def == null ? '' : def, true, ',');
-					if (buttons.length == 0)
-						break;
-
-					buttons = removeFromArray(buttons, tinyMCE.getParam("theme_advanced_disable", "", true, ','));
-					buttons = addToArray(buttons, tinyMCE.getParam("theme_advanced_buttons" + i + "_add", "", true, ','));
-					buttons = addToArray(tinyMCE.getParam("theme_advanced_buttons" + i + "_add_before", "", true, ','), buttons);
-
-					for (var b=0; b<buttons.length; b++)
-						toolbarHTML += tinyMCE.getControlHTML(buttons[b]);
-
-					if (buttons.length > 0) {
-						toolbarHTML += "<br />";
-						deltaHeight -= 23;
-					}
-				}
-
-				// Add accessibility control
-				toolbarHTML += '<a href="#" accesskey="z" onfocus="tinyMCE.getInstanceById(\'' + editorId + '\').getWin().focus();"></a>';
-
-				// Setup template html
-				template['html'] = '<table class="mceEditor" border="0" cellpadding="0" cellspacing="0" width="{$width}" height="{$height}" style="width:{$width_style};height:{$height_style}"><tbody>';
-
-				if (toolbarLocation == "top")
-					template['html'] += '<tr><td dir="ltr" class="mceToolbarTop" align="' + toolbarAlign + '" height="1" nowrap="nowrap"><span id="' + editorId + '_toolbar" class="mceToolbarContainer">' + toolbarHTML + '</span></td></tr>';
-
-				if (statusbarLocation == "top") {
-					template['html'] += '<tr><td class="mceStatusbarTop" height="1">' + statusbarHTML + '</td></tr>';
-					deltaHeight -= 23;
-				}
-
-				template['html'] += '<tr><td align="center"><span id="{$editor_id}"></span></td></tr>';
-
-				if (toolbarLocation == "bottom")
-					template['html'] += '<tr><td dir="ltr" class="mceToolbarBottom" align="' + toolbarAlign + '" height="1"><span id="' + editorId + '_toolbar" class="mceToolbarContainer">' + toolbarHTML + '</span></td></tr>';
-
-				// External toolbar changes
-				if (toolbarLocation == "external") {
-					var bod = document.body;
-					var elm = document.createElement ("div");
-
-					toolbarHTML = tinyMCE.replaceVar(toolbarHTML, 'style_select_options', styleSelectHTML);
-					toolbarHTML = tinyMCE.applyTemplate(toolbarHTML, {editor_id : editorId});
-
-					elm.className = "mceToolbarExternal";
-					elm.id = editorId+"_toolbar";
-					elm.innerHTML = '<table width="100%" border="0" align="center"><tr><td align="center">'+toolbarHTML+'</td></tr></table>';
-					bod.appendChild (elm);
-					// bod.style.marginTop = elm.offsetHeight + "px";
-
-					deltaHeight = 0;
-					tinyMCE.getInstanceById(editorId).toolbarElement = elm;
-
-					//template['html'] = '<div id="mceExternalToolbar" align="center" class="mceToolbarExternal"><table width="100%" border="0" align="center"><tr><td align="center">'+toolbarHTML+'</td></tr></table></div>' + template["html"];
-				} else {
-					tinyMCE.getInstanceById(editorId).toolbarElement = null;
-				}
-
-				if (statusbarLocation == "bottom") {
-					template['html'] += '<tr><td class="mceStatusbarBottom" height="1">' + statusbarHTML + '</td></tr>';
-					deltaHeight -= 23;
-				}
-
-				template['html'] += '</tbody></table>';
-				//"SimpleLayout"
-			break;
-
-			case "RowLayout" : //Container Layout - containers defined in "theme_advanced_containers" are rendered from top to bottom.
-				template['html'] = '<table class="mceEditor" border="0" cellpadding="0" cellspacing="0" width="{$width}" height="{$height}" style="width:{$width}px;height:{$height}px"><tbody>';
-
-				var containers = tinyMCE.getParam("theme_advanced_containers", "", true, ",");
-				var defaultContainerCSS = tinyMCE.getParam("theme_advanced_containers_default_class", "container");
-				var defaultContainerAlign = tinyMCE.getParam("theme_advanced_containers_default_align", "center");
-
-				//Render Containers:
-				for (var i = 0; i < containers.length; i++)
-				{
-					if (containers[i] == "mceEditor") //Exceptions for mceEditor and ...
-						template['html'] += '<tr><td align="center" class="mceEditor_border"><span id="{$editor_id}"></span></td></tr>';
-					else if (containers[i] == "mceElementpath" || containers[i] == "mceStatusbar") // ... mceElementpath:
-					{
-						var pathClass = "mceStatusbar";
-
-						if (i == containers.length-1)
-						{
-							pathClass = "mceStatusbarBottom";
-						}
-						else if (i == 0)
-						{
-							pathClass = "mceStatusbar";
-						}
-						else
-						{
-							deltaHeight-=2;
-						}
-
-						template['html'] += '<tr><td class="' + pathClass + '" height="1">' + statusbarHTML + '</td></tr>';
-						deltaHeight -= 22;
-					} else { // Render normal Container
-						var curContainer = tinyMCE.getParam("theme_advanced_container_"+containers[i], "", true, ',');
-						var curContainerHTML = "";
-						var curAlign = tinyMCE.getParam("theme_advanced_container_"+containers[i]+"_align", defaultContainerAlign);
-						var curCSS = tinyMCE.getParam("theme_advanced_container_"+containers[i]+"_class", defaultContainerCSS);
-
-						curContainer = removeFromArray(curContainer, tinyMCE.getParam("theme_advanced_disable", "", true, ','));
-
-						for (var j=0; j<curContainer.length; j++)
-							curContainerHTML += tinyMCE.getControlHTML(curContainer[j]);
-
-						if (curContainer.length > 0) {
-							curContainerHTML += "<br />";
-							deltaHeight -= 23;
-						}
-
-						template['html'] += '<tr><td class="' + curCSS + '" align="' + curAlign + '" height="1">' + curContainerHTML + '</td></tr>';
-					}
-				}
-
-				template['html'] += '</tbody></table>';
-				//RowLayout
-			break;
-
-			case "CustomLayout" : //User defined layout callback...
-				var customLayout = tinyMCE.getParam("theme_advanced_custom_layout","");
-
-				if (customLayout != "" && eval("typeof(" + customLayout + ")") != "undefined") {
-					template = eval(customLayout + "(template);");
-				}
-			break;
-		}
-
-		if (resizing)
-			template['html'] += '<span id="{$editor_id}_resize_box" class="mceResizeBox"></span>';
-
-		template['html'] = tinyMCE.replaceVar(template['html'], 'style_select_options', styleSelectHTML);
-
-		// Set to default values
-		if (!template['delta_width'])
-			template['delta_width'] = 0;
-
-		if (!template['delta_height'])
-			template['delta_height'] = deltaHeight;
-
-		return template;
-	},
-
-	initInstance : function(inst) {
-		if (tinyMCE.getParam("theme_advanced_resizing", false)) {
-			if (tinyMCE.getParam("theme_advanced_resizing_use_cookie", true)) {
-				var w = TinyMCE_AdvancedTheme._getCookie("TinyMCE_" + inst.editorId + "_width");
-				var h = TinyMCE_AdvancedTheme._getCookie("TinyMCE_" + inst.editorId + "_height");
-
-				TinyMCE_AdvancedTheme._resizeTo(inst, w, h, tinyMCE.getParam("theme_advanced_resize_horizontal", true));
-			}
-		}
+			if (c = cm.get('anchor')) {
+				c.setActive(!!p && p.name);
 
-		inst.addShortcut('ctrl', 'k', 'lang_link_desc', 'mceLink');
-	},
-
-	removeInstance : function(inst) {
-		new TinyMCE_Layer(inst.editorId + '_fcMenu').remove();
-		new TinyMCE_Layer(inst.editorId + '_bcMenu').remove();
-	},
-
-	hideInstance : function(inst) {
-		TinyMCE_AdvancedTheme._hideMenus(inst.editorId);
-	},
-
-	_handleMenuEvent : function(e) {
-		var te = tinyMCE.isMSIE ? window.event.srcElement : e.target;
-		tinyMCE._menuButtonEvent(e.type == "mouseover" ? "over" : "out", document.getElementById(te._switchId));
-
-		if (e.type == "click")
-			tinyMCE.execInstanceCommand(te._editor_id, te._command);
-	},
-
-	_hideMenus : function(id) {
-		var fcml = new TinyMCE_Layer(id + '_fcMenu'), bcml = new TinyMCE_Layer(id + '_bcMenu');
-
-		if (fcml.exists() && fcml.isVisible()) {
-			tinyMCE.switchClass(id + '_forecolor', 'mceMenuButton');
-			fcml.hide();
-		}
-
-		if (bcml.exists() && bcml.isVisible()) {
-			tinyMCE.switchClass(id + '_backcolor', 'mceMenuButton');
-			bcml.hide();
-		}
-	},
-
-	/**
-	 * Node change handler.
-	 */
-	handleNodeChange : function(editor_id, node, undo_index, undo_levels, visual_aid, any_selection, setup_content) {
-		var alignNode, breakOut, classNode;
-
-		function selectByValue(select_elm, value, first_index) {
-			first_index = typeof(first_index) == "undefined" ? false : true;
-
-			if (select_elm) {
-				for (var i=0; i<select_elm.options.length; i++) {
-					var ov = "" + select_elm.options[i].value;
-
-					if (first_index && ov.toLowerCase().indexOf(value.toLowerCase()) == 0) {
-						select_elm.selectedIndex = i;
-						return true;
-					}
-
-					if (ov == value) {
-						select_elm.selectedIndex = i;
-						return true;
-					}
-				}
-			}
-
-			return false;
-		};
-
-		// No node provided
-		if (node == null)
-			return;
-
-		// Update path
-		var pathElm = document.getElementById(editor_id + "_path");
-		var inst = tinyMCE.getInstanceById(editor_id);
-		var doc = inst.getDoc();
-		TinyMCE_AdvancedTheme._hideMenus(editor_id);
-
-		if (pathElm) {
-			// Get node path
-			var parentNode = node;
-			var path = new Array();
-			
-			while (parentNode != null) {
-				if (parentNode.nodeName.toUpperCase() == "BODY") {
-					break;
-				}
-
-				// Only append element nodes to path
-				if (parentNode.nodeType == 1 && tinyMCE.getAttrib(parentNode, "class").indexOf('mceItemHidden') == -1) {
-					path[path.length] = parentNode;
-				}
-
-				parentNode = parentNode.parentNode;
-			}
-
-			// Setup HTML
-			var html = "";
-			for (var i=path.length-1; i>=0; i--) {
-				var nodeName = path[i].nodeName.toLowerCase();
-				var nodeData = "";
-
-				if (nodeName.indexOf("html:") == 0)
-					nodeName = nodeName.substring(5);
-
-				if (nodeName == "b") {
-					nodeName = "strong";
-				}
-
-				if (nodeName == "i") {
-					nodeName = "em";
-				}
-
-				if (nodeName == "span") {
-					var cn = tinyMCE.getAttrib(path[i], "class");
-					if (cn != "" && cn.indexOf('mceItem') == -1)
-						nodeData += "class: " + cn + " ";
-
-					var st = tinyMCE.getAttrib(path[i], "style");
-					if (st != "") {
-						st = tinyMCE.serializeStyle(tinyMCE.parseStyle(st));
-						nodeData += "style: " + tinyMCE.xmlEncode(st) + " ";
-					}
-				}
-
-				if (nodeName == "font") {
-					if (tinyMCE.getParam("convert_fonts_to_spans"))
-						nodeName = "span";
-
-					var face = tinyMCE.getAttrib(path[i], "face");
-					if (face != "")
-						nodeData += "font: " + tinyMCE.xmlEncode(face) + " ";
-
-					var size = tinyMCE.getAttrib(path[i], "size");
-					if (size != "")
-						nodeData += "size: " + tinyMCE.xmlEncode(size) + " ";
-
-					var color = tinyMCE.getAttrib(path[i], "color");
-					if (color != "")
-						nodeData += "color: " + tinyMCE.xmlEncode(color) + " ";
-				}
-
-				if (tinyMCE.getAttrib(path[i], 'id') != "") {
-					nodeData += "id: " + path[i].getAttribute('id') + " ";
-				}
-
-				var className = tinyMCE.getVisualAidClass(tinyMCE.getAttrib(path[i], "class"), false);
-				if (className != "" && className.indexOf('mceItem') == -1)
-					nodeData += "class: " + className + " ";
-
-				if (tinyMCE.getAttrib(path[i], 'src') != "") {
-					var src = tinyMCE.getAttrib(path[i], "mce_src");
-
-					if (src == "")
-						 src = tinyMCE.getAttrib(path[i], "src");
-
-					nodeData += "src: " + tinyMCE.xmlEncode(src) + " ";
-				}
-
-				if (path[i].nodeName == 'A' && tinyMCE.getAttrib(path[i], 'href') != "") {
-					var href = tinyMCE.getAttrib(path[i], "mce_href");
-
-					if (href == "")
-						 href = tinyMCE.getAttrib(path[i], "href");
-
-					nodeData += "href: " + tinyMCE.xmlEncode(href) + " ";
-				}
-
-				className = tinyMCE.getAttrib(path[i], "class");
-				if ((nodeName == "img" || nodeName == "span") && className.indexOf('mceItem') != -1) {
-					nodeName = className.replace(/mceItem([a-z]+)/gi, '$1').toLowerCase();
-					nodeData = path[i].getAttribute('title');
-				}
-
-				if (nodeName == "a" && (anchor = tinyMCE.getAttrib(path[i], "name")) != "") {
-					nodeName = "a";
-					nodeName += "#" + tinyMCE.xmlEncode(anchor);
-					nodeData = "";
-				}
-
-				if (tinyMCE.getAttrib(path[i], 'name').indexOf("mce_") != 0) {
-					var className = tinyMCE.getVisualAidClass(tinyMCE.getAttrib(path[i], "class"), false);
-					if (className != "" && className.indexOf('mceItem') == -1) {
-						nodeName += "." + className;
-					}
-				}
-
-				var cmd = 'tinyMCE.execInstanceCommand(\'' + editor_id + '\',\'mceSelectNodeDepth\',false,\'' + i + '\');';
-				html += '<a title="' + nodeData + '" href="javascript:' + cmd + '" onclick="' + cmd + 'return false;" onmousedown="return false;" target="_self" class="mcePathItem">' + nodeName + '</a>';
-
-				if (i > 0) {
-					html += " &raquo; ";
+				if (tinymce.isWebKit) {
+					p = DOM.getParent(n, 'IMG');
+					c.setActive(!!p && DOM.getAttrib(p, 'mce_name') == 'a');
 				}
 			}
 
-			pathElm.innerHTML = '<a href="#" accesskey="x"></a>' + tinyMCE.getLang('lang_theme_path') + ": " + html + '&#160;';
-		}
+			p = DOM.getParent(n, 'IMG');
+			if (c = cm.get('image'))
+				c.setActive(!!p && n.className.indexOf('mceItem') == -1);
+
+			if (c = cm.get('styleselect')) {
+				if (n.className) {
+					t._importClasses();
+					c.select(n.className);
+				} else
+					c.select();
+			}
 
-		// Reset old states
-		tinyMCE.switchClass(editor_id + '_justifyleft', 'mceButtonNormal');
-		tinyMCE.switchClass(editor_id + '_justifyright', 'mceButtonNormal');
-		tinyMCE.switchClass(editor_id + '_justifycenter', 'mceButtonNormal');
-		tinyMCE.switchClass(editor_id + '_justifyfull', 'mceButtonNormal');
-		tinyMCE.switchClass(editor_id + '_bold', 'mceButtonNormal');
-		tinyMCE.switchClass(editor_id + '_italic', 'mceButtonNormal');
-		tinyMCE.switchClass(editor_id + '_underline', 'mceButtonNormal');
-		tinyMCE.switchClass(editor_id + '_strikethrough', 'mceButtonNormal');
-		tinyMCE.switchClass(editor_id + '_bullist', 'mceButtonNormal');
-		tinyMCE.switchClass(editor_id + '_numlist', 'mceButtonNormal');
-		tinyMCE.switchClass(editor_id + '_sub', 'mceButtonNormal');
-		tinyMCE.switchClass(editor_id + '_sup', 'mceButtonNormal');
-		tinyMCE.switchClass(editor_id + '_anchor', 'mceButtonNormal');
-		tinyMCE.switchClass(editor_id + '_link', 'mceButtonDisabled');
-		tinyMCE.switchClass(editor_id + '_unlink', 'mceButtonDisabled');
-		tinyMCE.switchClass(editor_id + '_outdent', 'mceButtonDisabled');
-		tinyMCE.switchClass(editor_id + '_image', 'mceButtonNormal');
-		tinyMCE.switchClass(editor_id + '_hr', 'mceButtonNormal');
+			if (c = cm.get('formatselect')) {
+				p = DOM.getParent(n, DOM.isBlock);
 
-		if (node.nodeName == "A" && tinyMCE.getAttrib(node, "class").indexOf('mceItemAnchor') != -1)
-			tinyMCE.switchClass(editor_id + '_anchor', 'mceButtonSelected');
+				if (p)
+					c.select(p.nodeName.toLowerCase());
+			}
 
-		// Get link
-		var anchorLink = tinyMCE.getParentElement(node, "a", "href");
+			if (c = cm.get('fontselect'))
+				c.select(ed.queryCommandValue('FontName'));
+
+			if (c = cm.get('fontsizeselect'))
+				c.select(ed.queryCommandValue('FontSize'));
 
-		if (anchorLink || any_selection) {
-			tinyMCE.switchClass(editor_id + '_link', anchorLink ? 'mceButtonSelected' : 'mceButtonNormal');
-			tinyMCE.switchClass(editor_id + '_unlink', anchorLink ? 'mceButtonSelected' : 'mceButtonNormal');
-		}
-
-		// Handle visual aid
-		tinyMCE.switchClass(editor_id + '_visualaid', visual_aid ? 'mceButtonSelected' : 'mceButtonNormal');
+			if (s.theme_advanced_path && s.theme_advanced_statusbar_location) {
+				p = DOM.get(ed.id + '_path') || DOM.add(ed.id + '_path_row', 'span', {id : ed.id + '_path'});
+				DOM.setHTML(p, '');
 
-		if (undo_levels != -1) {
-			tinyMCE.switchClass(editor_id + '_undo', 'mceButtonDisabled');
-			tinyMCE.switchClass(editor_id + '_redo', 'mceButtonDisabled');
-		}
+				ed.dom.getParent(n, function(n) {
+					var na = n.nodeName.toLowerCase(), u, pi, ti = '';
 
-		// Within li, blockquote
-		if (tinyMCE.getParentElement(node, "li,blockquote"))
-			tinyMCE.switchClass(editor_id + '_outdent', 'mceButtonNormal');
+					// Ignore non element and hidden elements
+					if (n.nodeType != 1 || (DOM.hasClass(n, 'mceItemHidden') || DOM.hasClass(n, 'mceItemRemoved')))
+						return;
 
-		// Has redo levels
-		if (undo_index != -1 && (undo_index < undo_levels-1 && undo_levels > 0))
-			tinyMCE.switchClass(editor_id + '_redo', 'mceButtonNormal');
-
-		// Has undo levels
-		if (undo_index != -1 && (undo_index > 0 && undo_levels > 0))
-			tinyMCE.switchClass(editor_id + '_undo', 'mceButtonNormal');
+					// Fake name
+					if (v = DOM.getAttrib(n, 'mce_name'))
+						na = v;
+	
+					// Handle prefix
+					if (tinymce.isIE && n.scopeName !== 'HTML')
+						na = n.scopeName + ':' + na;
 
-		// Select class in select box
-		var selectElm = document.getElementById(editor_id + "_styleSelect");
-		
-		if (selectElm) {
-			TinyMCE_AdvancedTheme._setupCSSClasses(editor_id);
+					// Remove internal prefix
+					na = na.replace(/mce\:/g, '');
 
-			classNode = node;
-			breakOut = false;
-			var index = 0;
+					// Handle node name
+					switch (na) {
+						case 'b':
+							na = 'strong';
+							break;
 
-			do {
-				if (classNode && classNode.className) {
-					for (var i=0; i<selectElm.options.length; i++) {
-						if (selectElm.options[i].value == classNode.className) {
-							index = i;
-							breakOut = true;
+						case 'i':
+							na = 'em';
 							break;
-						}
-					}
-				}
-			} while (!breakOut && classNode != null && (classNode = classNode.parentNode) != null);
 
-			selectElm.selectedIndex = index;
-		}
+						case 'img':
+							if (v = DOM.getAttrib(n, 'src'))
+								ti += 'src: ' + v + ' ';
+
+							break;
 
-		// Select formatblock
-		var selectElm = document.getElementById(editor_id + "_formatSelect");
-		if (selectElm) {
-			var elm = tinyMCE.getParentElement(node, "p,div,h1,h2,h3,h4,h5,h6,pre,address");
+						case 'a':
+							if (v = DOM.getAttrib(n, 'name')) {
+								ti += 'name: ' + v + ' ';
+								na += '#' + v;
+							}
 
-			if (elm)
-				selectByValue(selectElm, "<" + elm.nodeName.toLowerCase() + ">");
-			else
-				selectByValue(selectElm, "");
-		}
+							if (v = DOM.getAttrib(n, 'href'))
+								ti += 'href: ' + v + ' ';
 
-		// Select fontselect
-		var selectElm = document.getElementById(editor_id + "_fontNameSelect");
-		if (selectElm) {
-			if (!tinyMCE.isSafari && !(tinyMCE.isMSIE && !tinyMCE.isOpera)) {
-				var face = inst.queryCommandValue('FontName');
+							break;
 
-				face = face == null || face == "" ? "" : face;
+						case 'font':
+							if (s.convert_fonts_to_spans)
+								na = 'span';
 
-				selectByValue(selectElm, face, face != "");
-			} else {
-				var elm = tinyMCE.getParentElement(node, "font", "face");
+							if (v = DOM.getAttrib(n, 'face'))
+								ti += 'font: ' + v + ' ';
 
-				if (elm) {
-					var family = tinyMCE.getAttrib(elm, "face");
+							if (v = DOM.getAttrib(n, 'size'))
+								ti += 'size: ' + v + ' ';
 
-					if (family == '')
-						family = '' + elm.style.fontFamily;
+							if (v = DOM.getAttrib(n, 'color'))
+								ti += 'color: ' + v + ' ';
 
-					if (!selectByValue(selectElm, family, family != ""))
-						selectByValue(selectElm, "");
-				} else
-					selectByValue(selectElm, "");
-			}
-		}
+							break;
+
+						case 'span':
+							if (v = DOM.getAttrib(n, 'style'))
+								ti += 'style: ' + v + ' ';
 
-		// Select fontsize
-		var selectElm = document.getElementById(editor_id + "_fontSizeSelect");
-		if (selectElm) {
-			if (!tinyMCE.isSafari && !tinyMCE.isOpera) {
-				var size = inst.queryCommandValue('FontSize');
-				selectByValue(selectElm, size == null || size == "" ? "0" : size);
-			} else {
-				var elm = tinyMCE.getParentElement(node, "font", "size");
-				if (elm) {
-					var size = tinyMCE.getAttrib(elm, "size");
+							break;
+					}
+
+					if (v = DOM.getAttrib(n, 'id'))
+						ti += 'id: ' + v + ' ';
 
-					if (size == '') {
-						var sizes = new Array('', '8px', '10px', '12px', '14px', '18px', '24px', '36px');
-
-						size = '' + elm.style.fontSize;
+					if (v = n.className) {
+						v = v.replace(/(webkit-[\w\-]+|Apple-[\w\-]+|mceItem\w+|mceVisualAid)/g, '');
 
-						for (var i=0; i<sizes.length; i++) {
-							if (('' + sizes[i]) == size) {
-								size = i;
-								break;
-							}
+						if (v && v.indexOf('mceItem') == -1) {
+							ti += 'class: ' + v + ' ';
+
+							if (DOM.isBlock(n) || na == 'img' || na == 'span')
+								na += '.' + v;
 						}
 					}
 
-					if (!selectByValue(selectElm, size))
-						selectByValue(selectElm, "");
-				} else
-					selectByValue(selectElm, "0");
-			}
-		}
+					na = na.replace(/(html:)/g, '');
+					na = {name : na, node : n, title : ti};
+					t.onResolveName.dispatch(t, na);
+					ti = na.title;
+					na = na.name;
 
-		// Handle align attributes
-		alignNode = node;
-		breakOut = false;
-		do {
-			if (!alignNode.getAttribute || !alignNode.getAttribute('align'))
-				continue;
-
-			switch (alignNode.getAttribute('align').toLowerCase()) {
-				case "left":
-					tinyMCE.switchClass(editor_id + '_justifyleft', 'mceButtonSelected');
-					breakOut = true;
-				break;
-
-				case "right":
-					tinyMCE.switchClass(editor_id + '_justifyright', 'mceButtonSelected');
-					breakOut = true;
-				break;
+					//u = "javascript:tinymce.EditorManager.get('" + ed.id + "').theme._sel('" + (de++) + "');";
+					pi = DOM.create('a', {'href' : "#" + (de++) + "", onmousedown : "return false;", title : ti}, na);
 
-				case "middle":
-				case "center":
-					tinyMCE.switchClass(editor_id + '_justifycenter', 'mceButtonSelected');
-					breakOut = true;
-				break;
-
-				case "justify":
-					tinyMCE.switchClass(editor_id + '_justifyfull', 'mceButtonSelected');
-					breakOut = true;
-				break;
+					if (p.hasChildNodes()) {
+						p.insertBefore(document.createTextNode(' \u00bb '), p.firstChild);
+						p.insertBefore(pi, p.firstChild);
+					} else
+						p.appendChild(pi);
+				}, ed.getBody());
 			}
-		} while (!breakOut && (alignNode = alignNode.parentNode) != null);
+		},
 
-		// Div justification
-		var div = tinyMCE.getParentElement(node, "div");
-		if (div && div.style.textAlign == "center")
-			tinyMCE.switchClass(editor_id + '_justifycenter', 'mceButtonSelected');
+		// Commands gets called by execCommand
 
-		// Do special text
-		if (!setup_content) {
-			// , "JustifyLeft", "_justifyleft", "JustifyCenter", "justifycenter", "JustifyRight", "justifyright", "JustifyFull", "justifyfull", "InsertUnorderedList", "bullist", "InsertOrderedList", "numlist", "InsertUnorderedList", "bullist", "Outdent", "outdent", "Indent", "indent", "subscript", "sub"
-			var ar = new Array("Bold", "_bold", "Italic", "_italic", "Strikethrough", "_strikethrough", "superscript", "_sup", "subscript", "_sub");
-			for (var i=0; i<ar.length; i+=2) {
-				if (inst.queryCommandState(ar[i]))
-					tinyMCE.switchClass(editor_id + ar[i+1], 'mceButtonSelected');
-			}
+		_sel : function(v) {
+			this.editor.execCommand('mceSelectNodeDepth', false, v);
+		},
 
-			if (inst.queryCommandState("Underline") && (node.parentNode == null || node.parentNode.nodeName != "A"))
-				tinyMCE.switchClass(editor_id + '_underline', 'mceButtonSelected');
-		}
+		_mceInsertAnchor : function(ui, v) {
+			var ed = this.editor;
 
-		// Handle elements
-		do {
-			switch (node.nodeName) {
-				case "UL":
-					tinyMCE.switchClass(editor_id + '_bullist', 'mceButtonSelected');
-				break;
-
-				case "OL":
-					tinyMCE.switchClass(editor_id + '_numlist', 'mceButtonSelected');
-				break;
-
-				case "HR":
-					 tinyMCE.switchClass(editor_id + '_hr', 'mceButtonSelected');
-				break;
+			ed.windowManager.open({
+				url : tinymce.baseURL + '/themes/advanced/anchor.htm',
+				width : 320 + parseInt(ed.getLang('advanced.anchor_delta_width', 0)),
+				height : 90 + parseInt(ed.getLang('advanced.anchor_delta_height', 0)),
+				inline : true
+			}, {
+				theme_url : this.url
+			});
+		},
 
-				case "IMG":
-				if (tinyMCE.getAttrib(node, 'name').indexOf('mce_') != 0 && tinyMCE.getAttrib(node, 'class').indexOf('mceItem') == -1) {
-					tinyMCE.switchClass(editor_id + '_image', 'mceButtonSelected');
-				}
-				break;
-			}
-		} while ((node = node.parentNode) != null);
-	},
-
-	// Private theme internal functions
-
-	// This function auto imports CSS classes into the class selection droplist
-	_setupCSSClasses : function(editor_id) {
-		var i, selectElm;
-
-		if (!TinyMCE_AdvancedTheme._autoImportCSSClasses)
-			return;
+		_mceCharMap : function() {
+			var ed = this.editor;
 
-		selectElm = document.getElementById(editor_id + '_styleSelect');
+			ed.windowManager.open({
+				url : tinymce.baseURL + '/themes/advanced/charmap.htm',
+				width : 550 + parseInt(ed.getLang('advanced.charmap_delta_width', 0)),
+				height : 250 + parseInt(ed.getLang('advanced.charmap_delta_height', 0)),
+				inline : true
+			}, {
+				theme_url : this.url
+			});
+		},
 
-		if (selectElm && selectElm.getAttribute('cssImported') != 'true') {
-			var csses = tinyMCE.getCSSClasses(editor_id);
-			if (csses && selectElm)	{
-				for (i=0; i<csses.length; i++)
-					selectElm.options[selectElm.options.length] = new Option(csses[i], csses[i]);
-			}
-
-			// Only do this once
-			if (csses != null && csses.length > 0)
-				selectElm.setAttribute('cssImported', 'true');
-		}
-	},
+		_mceHelp : function() {
+			var ed = this.editor;
 
-	_setCookie : function(name, value, expires, path, domain, secure) {
-		var curCookie = name + "=" + escape(value) +
-			((expires) ? "; expires=" + expires.toGMTString() : "") +
-			((path) ? "; path=" + escape(path) : "") +
-			((domain) ? "; domain=" + domain : "") +
-			((secure) ? "; secure" : "");
+			ed.windowManager.open({
+				url : tinymce.baseURL + '/themes/advanced/about.htm',
+				width : 480,
+				height : 380,
+				inline : true
+			}, {
+				theme_url : this.url
+			});
+		},
 
-		document.cookie = curCookie;
-	},
+		_mceColorPicker : function(u, v) {
+			var ed = this.editor;
 
-	_getCookie : function(name) {
-		var dc = document.cookie;
-		var prefix = name + "=";
-		var begin = dc.indexOf("; " + prefix);
-
-		if (begin == -1) {
-			begin = dc.indexOf(prefix);
+			v = v || {};
 
-			if (begin != 0)
-				return null;
-		} else
-			begin += 2;
-
-		var end = document.cookie.indexOf(";", begin);
-
-		if (end == -1)
-			end = dc.length;
-
-		return unescape(dc.substring(begin + prefix.length, end));
-	},
+			ed.windowManager.open({
+				url : tinymce.baseURL + '/themes/advanced/color_picker.htm',
+				width : 375 + parseInt(ed.getLang('advanced.colorpicker_delta_width', 0)),
+				height : 250 + parseInt(ed.getLang('advanced.colorpicker_delta_height', 0)),
+				close_previous : false,
+				inline : true
+			}, {
+				input_color : v.color,
+				func : v.func,
+				theme_url : this.url
+			});
+		},
 
-	_resizeTo : function(inst, w, h, set_w) {
-		var editorContainer = document.getElementById(inst.editorId + '_parent');
-		var tableElm = editorContainer.firstChild;
-		var iframe = inst.iframeElement;
-
-		if (w == null || w == "null") {
-			set_w = false;
-			w = 0;
-		}
-
-		if (h == null || h == "null")
-			return;
-
-		w = parseInt(w);
-		h = parseInt(h);
+		_mceCodeEditor : function(ui, val) {
+			var ed = this.editor;
 
-		if (tinyMCE.isGecko) {
-			w += 2;
-			h += 2;
-		}
-
-		var dx = w - tableElm.clientWidth;
-		var dy = h - tableElm.clientHeight;
-
-		w = w < 1 ? 30 : w;
-		h = h < 1 ? 30 : h;
-
-		if (set_w)
-			tableElm.style.width = w + "px";
-
-		tableElm.style.height = h + "px";
+			ed.windowManager.open({
+				url : tinymce.baseURL + '/themes/advanced/source_editor.htm',
+				width : parseInt(ed.getParam("theme_advanced_source_editor_width", 720)),
+				height : parseInt(ed.getParam("theme_advanced_source_editor_height", 580)),
+				inline : true,
+				resizable : true,
+				maximizable : true
+			}, {
+				theme_url : this.url
+			});
+		},
 
-		iw = iframe.clientWidth + dx;
-		ih = iframe.clientHeight + dy;
-
-		iw = iw < 1 ? 30 : iw;
-		ih = ih < 1 ? 30 : ih;
+		_mceImage : function(ui, val) {
+			var ed = this.editor;
 
-		if (tinyMCE.isGecko) {
-			iw -= 2;
-			ih -= 2;
-		}
-
-		if (set_w)
-			iframe.style.width = iw + "px";
-
-		iframe.style.height = ih + "px";
+			ed.windowManager.open({
+				url : tinymce.baseURL + '/themes/advanced/image.htm',
+				width : 355 + parseInt(ed.getLang('advanced.image_delta_width', 0)),
+				height : 275 + parseInt(ed.getLang('advanced.image_delta_height', 0)),
+				inline : true
+			}, {
+				theme_url : this.url
+			});
+		},
 
-		// Is it to small, make it bigger again
-		if (set_w) {
-			var tableBodyElm = tableElm.firstChild;
-			var minIframeWidth = tableBodyElm.scrollWidth;
-			if (inst.iframeElement.clientWidth < minIframeWidth) {
-				dx = minIframeWidth - inst.iframeElement.clientWidth;
-
-				inst.iframeElement.style.width = (iw + dx) + "px";
-			}
-		}
+		_mceLink : function(ui, val) {
+			var ed = this.editor;
 
-		// Remove pesky table controls
-		inst.useCSS = false;
-	},
+			ed.windowManager.open({
+				url : tinymce.baseURL + '/themes/advanced/link.htm',
+				width : 310 + parseInt(ed.getLang('advanced.link_delta_width', 0)),
+				height : 200 + parseInt(ed.getLang('advanced.link_delta_height', 0)),
+				inline : true
+			}, {
+				theme_url : this.url
+			});
+		},
 
-	/**
-	 * Handles resizing events.
-	 */
-	_resizeEventHandler : function(e) {
-		var resizer = TinyMCE_AdvancedTheme._resizer;
-
-		// Do nothing
-		if (!resizer.resizing)
-			return;
-
-		e = typeof(e) == "undefined" ? window.event : e;
+		_mceNewDocument : function() {
+			var ed = this.editor;
 
-		var dx = e.screenX - resizer.downX;
-		var dy = e.screenY - resizer.downY;
-		var resizeBox = resizer.resizeBox;
-		var editorId = resizer.editorId;
-
-		switch (e.type) {
-			case "mousemove":
-				var w, h;
+			ed.windowManager.confirm('advanced.newdocument', function(s) {
+				if (s)
+					ed.execCommand('mceSetContent', false, '');
+			});
+		},
 
-				w = resizer.width + dx;
-				h = resizer.height + dy;
-
-				w = w < 1 ? 1 : w;
-				h = h < 1 ? 1 : h;
-
-				if (resizer.horizontal)
-					resizeBox.style.width = w + "px";
+		_mceForeColor : function() {
+			var t = this;
 
-				resizeBox.style.height = h + "px";
-				break;
-
-			case "mouseup":
-				TinyMCE_AdvancedTheme._setResizing(e, editorId, false);
-				TinyMCE_AdvancedTheme._resizeTo(tinyMCE.getInstanceById(editorId), resizer.width + dx, resizer.height + dy, resizer.horizontal);
+			this._mceColorPicker(0, {
+				func : function(co) {
+					t.editor.execCommand('ForeColor', false, co);
+				}
+			});
+		},
 
-				// Expire in a month
-				if (tinyMCE.getParam("theme_advanced_resizing_use_cookie", true)) {
-					var expires = new Date();
-					expires.setTime(expires.getTime() + 3600000 * 24 * 30);
+		_mceBackColor : function() {
+			var t = this;
 
-					// Set the cookies
-					TinyMCE_AdvancedTheme._setCookie("TinyMCE_" + editorId + "_width", "" + (resizer.horizontal ? resizer.width + dx : ""), expires);
-					TinyMCE_AdvancedTheme._setCookie("TinyMCE_" + editorId + "_height", "" + (resizer.height + dy), expires);
+			this._mceColorPicker(0, {
+				func : function(co) {
+					t.editor.execCommand('HiliteColor', false, co);
 				}
-				break;
+			});
 		}
-	},
-
-	/**
-	 * Starts/stops the editor resizing.
-	 */
-	_setResizing : function(e, editor_id, state) {
-		e = typeof(e) == "undefined" ? window.event : e;
-
-		var resizer = TinyMCE_AdvancedTheme._resizer;
-		var editorContainer = document.getElementById(editor_id + '_parent');
-		var editorArea = document.getElementById(editor_id + '_parent').firstChild;
-		var resizeBox = document.getElementById(editor_id + '_resize_box');
-		var inst = tinyMCE.getInstanceById(editor_id);
-
-		if (state) {
-			// Place box over editor area
-			var width = editorArea.clientWidth;
-			var height = editorArea.clientHeight;
-
-			resizeBox.style.width = width + "px";
-			resizeBox.style.height = height + "px";
-
-			resizer.iframeWidth = inst.iframeElement.clientWidth;
-			resizer.iframeHeight = inst.iframeElement.clientHeight;
-
-			// Hide editor and show resize box
-			editorArea.style.display = "none";
-			resizeBox.style.display = "block";
-
-			// Add event handlers, only once
-			if (!resizer.eventHandlers) {
-				if (tinyMCE.isMSIE)
-					tinyMCE.addEvent(document, "mousemove", TinyMCE_AdvancedTheme._resizeEventHandler);
-				else
-					tinyMCE.addEvent(window, "mousemove", TinyMCE_AdvancedTheme._resizeEventHandler);
-
-				tinyMCE.addEvent(document, "mouseup", TinyMCE_AdvancedTheme._resizeEventHandler);
-
-				resizer.eventHandlers = true;
-			}
-
-			resizer.resizing = true;
-			resizer.downX = e.screenX;
-			resizer.downY = e.screenY;
-			resizer.width = parseInt(resizeBox.style.width);
-			resizer.height = parseInt(resizeBox.style.height);
-			resizer.editorId = editor_id;
-			resizer.resizeBox = resizeBox;
-			resizer.horizontal = tinyMCE.getParam("theme_advanced_resize_horizontal", true);
-		} else {
-			resizer.resizing = false;
-			resizeBox.style.display = "none";
-			editorArea.style.display = tinyMCE.isMSIE && !tinyMCE.isOpera ? "block" : "table";
-			tinyMCE.execCommand('mceResetDesignMode');
-		}
-	},
-
-	_getColorHTML : function(id, n, cm) {
-		var i, h, cl;
-
-		h = '<span class="mceMenuLine"></span>';
-		cl = tinyMCE.getParam(n, TinyMCE_AdvancedTheme._defColors).split(',');
-
-		h += '<table class="mceColors"><tr>';
-		for (i=0; i<cl.length; i++) {
-			c = 'tinyMCE.execInstanceCommand(\'' + id + '\', \'' + cm + '\', false, \'#' + cl[i] + '\');';
-			h += '<td><a href="javascript:' + c + '" style="background-color: #' + cl[i] + '" onclick="' + c + ';return false;"></a></td>';
-
-			if ((i+1) % 8 == 0)
-				h += '</tr><tr>';
-		}
-
-		h += '</tr></table>';
-
-		if (tinyMCE.getParam("theme_advanced_more_colors", true))
-			h += '<a href="#" onclick="TinyMCE_AdvancedTheme._pickColor(\'' + id + '\',\'' + cm + '\');" class="mceMoreColors">' + tinyMCE.getLang('lang_more_colors') + '</a>';
-
-		return h;
-	},
-
-	_pickColor : function(id, cm) {
-		var inputColor, inst = tinyMCE.selectedInstance;
-
-		if (cm == 'forecolor' && inst)
-			inputColor = inst.foreColor;
-
-		if ((cm == 'backcolor' || cm == 'HiliteColor') && inst)
-			inputColor = inst.backColor;
-
-		tinyMCE.execCommand('mceColorPicker', true, {color : inputColor, callback : function(c) {
-			tinyMCE.execInstanceCommand(id, cm, false, c);
-		}});
-	},
-
-	_insertImage : function(src, alt, border, hspace, vspace, width, height, align, title, onmouseover, onmouseout) {
-		tinyMCE.execCommand('mceBeginUndoLevel');
-
-		if (src == "")
-			return;
-
-		if (!tinyMCE.imgElement && tinyMCE.isSafari) {
-			var html = "";
-
-			html += '<img src="' + src + '" alt="' + alt + '"';
-			html += ' border="' + border + '" hspace="' + hspace + '"';
-			html += ' vspace="' + vspace + '" width="' + width + '"';
-			html += ' height="' + height + '" align="' + align + '" title="' + title + '" onmouseover="' + onmouseover + '" onmouseout="' + onmouseout + '" />';
-
-			tinyMCE.execCommand("mceInsertContent", false, html);
-		} else {
-			if (!tinyMCE.imgElement && tinyMCE.selectedInstance) {
-				if (tinyMCE.isSafari)
-					tinyMCE.execCommand("mceInsertContent", false, '<img src="' + tinyMCE.uniqueURL + '" />');
-				else
-					tinyMCE.selectedInstance.contentDocument.execCommand("insertimage", false, tinyMCE.uniqueURL);
-
-				tinyMCE.imgElement = tinyMCE.getElementByAttributeValue(tinyMCE.selectedInstance.contentDocument.body, "img", "src", tinyMCE.uniqueURL);
-			}
-		}
-
-		if (tinyMCE.imgElement) {
-			var needsRepaint = false;
-			var msrc = src;
+	});
 
-			src = eval(tinyMCE.settings['urlconverter_callback'] + "(src, tinyMCE.imgElement);");
-
-			if (tinyMCE.getParam('convert_urls'))
-				msrc = src;
-
-			if (onmouseover && onmouseover != "")
-				onmouseover = "this.src='" + eval(tinyMCE.settings['urlconverter_callback'] + "(onmouseover, tinyMCE.imgElement);") + "';";
-
-			if (onmouseout && onmouseout != "")
-				onmouseout = "this.src='" + eval(tinyMCE.settings['urlconverter_callback'] + "(onmouseout, tinyMCE.imgElement);") + "';";
-
-			// Use alt as title if it's undefined
-			if (typeof(title) == "undefined")
-				title = alt;
-
-			if (width != tinyMCE.imgElement.getAttribute("width") || height != tinyMCE.imgElement.getAttribute("height") || align != tinyMCE.imgElement.getAttribute("align"))
-				needsRepaint = true;
-
-			tinyMCE.setAttrib(tinyMCE.imgElement, 'src', src);
-			tinyMCE.setAttrib(tinyMCE.imgElement, 'mce_src', msrc);
-			tinyMCE.setAttrib(tinyMCE.imgElement, 'alt', alt);
-			tinyMCE.setAttrib(tinyMCE.imgElement, 'title', title);
-			tinyMCE.setAttrib(tinyMCE.imgElement, 'align', align);
-			tinyMCE.setAttrib(tinyMCE.imgElement, 'border', border, true);
-			tinyMCE.setAttrib(tinyMCE.imgElement, 'hspace', hspace, true);
-			tinyMCE.setAttrib(tinyMCE.imgElement, 'vspace', vspace, true);
-			tinyMCE.setAttrib(tinyMCE.imgElement, 'width', width, true);
-			tinyMCE.setAttrib(tinyMCE.imgElement, 'height', height, true);
-			tinyMCE.setAttrib(tinyMCE.imgElement, 'onmouseover', onmouseover);
-			tinyMCE.setAttrib(tinyMCE.imgElement, 'onmouseout', onmouseout);
-
-			// Fix for bug #989846 - Image resize bug
-			if (width && width != "")
-				tinyMCE.imgElement.style.pixelWidth = width;
-
-			if (height && height != "")
-				tinyMCE.imgElement.style.pixelHeight = height;
-
-			if (needsRepaint)
-				tinyMCE.selectedInstance.repaint();
-		}
-
-		tinyMCE.execCommand('mceEndUndoLevel');
-	},
-
-	_insertLink : function(href, target, title, onclick, style_class) {
-		tinyMCE.execCommand('mceBeginUndoLevel');
-
-		if (tinyMCE.selectedInstance && tinyMCE.selectedElement && tinyMCE.selectedElement.nodeName.toLowerCase() == "img") {
-			var doc = tinyMCE.selectedInstance.getDoc();
-			var linkElement = tinyMCE.getParentElement(tinyMCE.selectedElement, "a");
-			var newLink = false;
-
-			if (!linkElement) {
-				linkElement = doc.createElement("a");
-				newLink = true;
-			}
-
-			var mhref = href;
-			var thref = eval(tinyMCE.settings['urlconverter_callback'] + "(href, linkElement);");
-			mhref = tinyMCE.getParam('convert_urls') ? href : mhref;
-
-			tinyMCE.setAttrib(linkElement, 'href', thref);
-			tinyMCE.setAttrib(linkElement, 'mce_href', mhref);
-			tinyMCE.setAttrib(linkElement, 'target', target);
-			tinyMCE.setAttrib(linkElement, 'title', title);
-			tinyMCE.setAttrib(linkElement, 'onclick', onclick);
-			tinyMCE.setAttrib(linkElement, 'class', style_class);
-
-			if (newLink) {
-				linkElement.appendChild(tinyMCE.selectedElement.cloneNode(true));
-				tinyMCE.selectedElement.parentNode.replaceChild(linkElement, tinyMCE.selectedElement);
-			}
-
-			return;
-		}
-
-		if (!tinyMCE.linkElement && tinyMCE.selectedInstance) {
-			if (tinyMCE.isSafari) {
-				tinyMCE.execCommand("mceInsertContent", false, '<a href="' + tinyMCE.uniqueURL + '">' + tinyMCE.selectedInstance.selection.getSelectedHTML() + '</a>');
-			} else
-				tinyMCE.selectedInstance.contentDocument.execCommand("createlink", false, tinyMCE.uniqueURL);
-
-			tinyMCE.linkElement = tinyMCE.getElementByAttributeValue(tinyMCE.selectedInstance.contentDocument.body, "a", "href", tinyMCE.uniqueURL);
-
-			var elementArray = tinyMCE.getElementsByAttributeValue(tinyMCE.selectedInstance.contentDocument.body, "a", "href", tinyMCE.uniqueURL);
-
-			for (var i=0; i<elementArray.length; i++) {
-				var mhref = href;
-				var thref = eval(tinyMCE.settings['urlconverter_callback'] + "(href, elementArray[i]);");
-				mhref = tinyMCE.getParam('convert_urls') ? href : mhref;
-
-				tinyMCE.setAttrib(elementArray[i], 'href', thref);
-				tinyMCE.setAttrib(elementArray[i], 'mce_href', mhref);
-				tinyMCE.setAttrib(elementArray[i], 'target', target);
-				tinyMCE.setAttrib(elementArray[i], 'title', title);
-				tinyMCE.setAttrib(elementArray[i], 'onclick', onclick);
-				tinyMCE.setAttrib(elementArray[i], 'class', style_class);
-			}
-
-			tinyMCE.linkElement = elementArray[0];
-		}
-
-		if (tinyMCE.linkElement) {
-			var mhref = href;
-			href = eval(tinyMCE.settings['urlconverter_callback'] + "(href, tinyMCE.linkElement);");
-			mhref = tinyMCE.getParam('convert_urls') ? href : mhref;
-
-			tinyMCE.setAttrib(tinyMCE.linkElement, 'href', href);
-			tinyMCE.setAttrib(tinyMCE.linkElement, 'mce_href', mhref);
-			tinyMCE.setAttrib(tinyMCE.linkElement, 'target', target);
-			tinyMCE.setAttrib(tinyMCE.linkElement, 'title', title);
-			tinyMCE.setAttrib(tinyMCE.linkElement, 'onclick', onclick);
-			tinyMCE.setAttrib(tinyMCE.linkElement, 'class', style_class);
-		}
-
-		tinyMCE.execCommand('mceEndUndoLevel');
-	}
-};
-
-tinyMCE.addTheme("advanced", TinyMCE_AdvancedTheme);
-
-// Add default buttons maps for advanced theme and all internal plugins
-tinyMCE.addButtonMap(TinyMCE_AdvancedTheme._buttonMap);
+	tinymce.ThemeManager.add('advanced', tinymce.themes.AdvancedTheme);
+}());
\ No newline at end of file
--- a/includes/clientside/tinymce/themes/advanced/image.htm	Fri Feb 22 12:46:51 2008 -0500
+++ b/includes/clientside/tinymce/themes/advanced/image.htm	Fri Feb 22 12:51:53 2008 -0500
@@ -1,17 +1,18 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
 <html xmlns="http://www.w3.org/1999/xhtml">
 <head>
-	<title>{$lang_insert_image_title}</title>
-	<script language="javascript" type="text/javascript" src="../../tiny_mce_popup.js"></script>
-	<script language="javascript" type="text/javascript" src="../../utils/mctabs.js"></script>
-	<script language="javascript" type="text/javascript" src="../../utils/form_utils.js"></script>
-	<script language="javascript" type="text/javascript" src="jscripts/image.js"></script>
+	<title>{#advanced_dlg.image_title}</title>
+	<script type="text/javascript" src="../../tiny_mce_popup.js"></script>
+	<script type="text/javascript" src="../../utils/mctabs.js"></script>
+	<script type="text/javascript" src="../../utils/form_utils.js"></script>
+	<script type="text/javascript" src="js/image.js"></script>
 	<base target="_self" />
 </head>
-<body id="image" onload="tinyMCEPopup.executeOnLoad('init();');" style="display: none">
-<form onsubmit="insertImage();return false;" action="#">
+<body id="image" style="display: none">
+<form onsubmit="ImageDialog.update();return false;" action="#">
 	<div class="tabs">
 		<ul>
-			<li id="general_tab" class="current"><span><a href="javascript:mcTabs.displayTab('general_tab','general_panel');" onmousedown="return false;">{$lang_insert_image_title}</a></span></li>
+			<li id="general_tab" class="current"><span><a href="javascript:mcTabs.displayTab('general_tab','general_panel');" onmousedown="return false;">{#advanced_dlg.image_title}</a></span></li>
 		</ul>
 	</div>
 
@@ -19,68 +20,53 @@
 		<div id="general_panel" class="panel current">
      <table border="0" cellpadding="4" cellspacing="0">
           <tr>
-            <td nowrap="nowrap"><label for="src">{$lang_insert_image_src}</label></td>
+            <td nowrap="nowrap"><label for="src">{#advanced_dlg.image_src}</label></td>
             <td><table border="0" cellspacing="0" cellpadding="0">
                 <tr>
-                  <td><input id="src" name="src" type="text" value="" style="width: 200px" onchange="getImageData();"></td>
+                  <td><input id="src" name="src" type="text" value="" style="width: 200px" onchange="ImageDialog.getImageData();" /></td>
                   <td id="srcbrowsercontainer">&nbsp;</td>
                 </tr>
               </table></td>
           </tr>
-		  <!-- Image list -->
-		  <script language="javascript">
-			if (typeof(tinyMCEImageList) != "undefined" && tinyMCEImageList.length > 0) {
-				var html = "";
-
-				html += '<tr><td><label for="image_list">{$lang_image_list}</label></td>';
-				html += '<td><select id="image_list" name="image_list" style="width: 200px" onchange="this.form.src.value=this.options[this.selectedIndex].value;resetImageData();getImageData();">';
-				html += '<option value="">---</option>';
-
-				for (var i=0; i<tinyMCEImageList.length; i++)
-					html += '<option value="' + tinyMCEImageList[i][1] + '">' + tinyMCEImageList[i][0] + '</option>';
-
-				html += '</select></td></tr>';
-
-				document.write(html);
-			}
-		  </script>
-		  <!-- /Image list -->
+		  <tr>
+			<td><label for="image_list">{#advanced_dlg.image_list}</label></td>
+			<td><select id="image_list" name="image_list" onchange="document.getElementById('src').value=this.options[this.selectedIndex].value;document.getElementById('alt').value=this.options[this.selectedIndex].text;"></select></td>
+		  </tr>
           <tr>
-            <td nowrap="nowrap"><label for="alt">{$lang_insert_image_alt}</label></td>
-            <td><input id="alt" name="alt" type="text" value="" style="width: 200px"></td>
+            <td nowrap="nowrap"><label for="alt">{#advanced_dlg.image_alt}</label></td>
+            <td><input id="alt" name="alt" type="text" value="" style="width: 200px" /></td>
           </tr>
           <tr>
-            <td nowrap="nowrap"><label for="align">{$lang_insert_image_align}</label></td>
-            <td><select id="align" name="align">
-                <option value="">{$lang_insert_image_align_default}</option>
-                <option value="baseline">{$lang_insert_image_align_baseline}</option>
-                <option value="top">{$lang_insert_image_align_top}</option>
-                <option value="middle">{$lang_insert_image_align_middle}</option>
-                <option value="bottom">{$lang_insert_image_align_bottom}</option>
-                <option value="texttop">{$lang_insert_image_align_texttop}</option>
-                <option value="absmiddle">{$lang_insert_image_align_absmiddle}</option>
-                <option value="absbottom">{$lang_insert_image_align_absbottom}</option>
-                <option value="left">{$lang_insert_image_align_left}</option>
-                <option value="right">{$lang_insert_image_align_right}</option>
+            <td nowrap="nowrap"><label for="align">{#advanced_dlg.image_align}</label></td>
+            <td><select id="align" name="align" onchange="ImageDialog.updateStyle();">
+                <option value="">{#not_set}</option>
+                <option value="baseline">{#advanced_dlg.image_align_baseline}</option>
+                <option value="top">{#advanced_dlg.image_align_top}</option>
+                <option value="middle">{#advanced_dlg.image_align_middle}</option>
+                <option value="bottom">{#advanced_dlg.image_align_bottom}</option>
+                <option value="text-top">{#advanced_dlg.image_align_texttop}</option>
+                <option value="text-bottom">{#advanced_dlg.image_align_textbottom}</option>
+                <option value="left">{#advanced_dlg.image_align_left}</option>
+                <option value="right">{#advanced_dlg.image_align_right}</option>
               </select></td>
           </tr>
           <tr>
-            <td nowrap="nowrap"><label for="width">{$lang_insert_image_dimensions}</label></td>
-            <td><input id="width" name="width" type="text" value="" size="3" maxlength="3">
+            <td nowrap="nowrap"><label for="width">{#advanced_dlg.image_dimensions}</label></td>
+            <td><input id="width" name="width" type="text" value="" size="3" maxlength="5" />
               x
-              <input id="height" name="height" type="text" value="" size="3" maxlength="3"></td>
+              <input id="height" name="height" type="text" value="" size="3" maxlength="5" /></td>
           </tr>
           <tr>
-            <td nowrap="nowrap"><label for="border">{$lang_insert_image_border}</label></td>
-            <td><input id="border" name="border" type="text" value="" size="3" maxlength="3"></td>
+            <td nowrap="nowrap"><label for="border">{#advanced_dlg.image_border}</label></td>
+            <td><input id="border" name="border" type="text" value="" size="3" maxlength="3" onchange="ImageDialog.updateStyle();" /></td>
           </tr>
           <tr>
-            <td nowrap="nowrap"><label for="vspace">{$lang_insert_image_vspace}</label></td>
-            <td><input id="vspace" name="vspace" type="text" value="" size="3" maxlength="3"></td>
+            <td nowrap="nowrap"><label for="vspace">{#advanced_dlg.image_vspace}</label></td>
+            <td><input id="vspace" name="vspace" type="text" value="" size="3" maxlength="3" onchange="ImageDialog.updateStyle();" /></td>
           </tr>
           <tr>
-            <td nowrap="nowrap"><label for="hspace">{$lang_insert_image_hspace}</label></td>
-            <td><input id="hspace" name="hspace" type="text" value="" size="3" maxlength="3"></td>
+            <td nowrap="nowrap"><label for="hspace">{#advanced_dlg.image_hspace}</label></td>
+            <td><input id="hspace" name="hspace" type="text" value="" size="3" maxlength="3" onchange="ImageDialog.updateStyle();" /></td>
           </tr>
         </table>
 		</div>
@@ -88,11 +74,11 @@
 
 	<div class="mceActionPanel">
 		<div style="float: left">
-			<input type="button" id="insert" name="insert" value="{$lang_insert}" onclick="insertImage();" />
+			<input type="button" id="insert" name="insert" value="{#insert}" onclick="ImageDialog.update();" />
 		</div>
 
 		<div style="float: right">
-			<input type="button" id="cancel" name="cancel" value="{$lang_cancel}" onclick="tinyMCEPopup.close();" />
+			<input type="button" id="cancel" name="cancel" value="{#cancel}" onclick="tinyMCEPopup.close();" />
 		</div>
 	</div>
 </form>
Binary file includes/clientside/tinymce/themes/advanced/images/anchor.gif has changed
Binary file includes/clientside/tinymce/themes/advanced/images/anchor_symbol.gif has changed
Binary file includes/clientside/tinymce/themes/advanced/images/backcolor.gif has changed
Binary file includes/clientside/tinymce/themes/advanced/images/bold.gif has changed
Binary file includes/clientside/tinymce/themes/advanced/images/bold_de_se.gif has changed
Binary file includes/clientside/tinymce/themes/advanced/images/bold_es.gif has changed
Binary file includes/clientside/tinymce/themes/advanced/images/bold_fr.gif has changed
Binary file includes/clientside/tinymce/themes/advanced/images/bold_ru.gif has changed
Binary file includes/clientside/tinymce/themes/advanced/images/bold_tw.gif has changed
Binary file includes/clientside/tinymce/themes/advanced/images/browse.gif has changed
Binary file includes/clientside/tinymce/themes/advanced/images/bullist.gif has changed
Binary file includes/clientside/tinymce/themes/advanced/images/button_menu.gif has changed
Binary file includes/clientside/tinymce/themes/advanced/images/buttons.gif has changed
Binary file includes/clientside/tinymce/themes/advanced/images/cancel_button_bg.gif has changed
Binary file includes/clientside/tinymce/themes/advanced/images/charmap.gif has changed
Binary file includes/clientside/tinymce/themes/advanced/images/cleanup.gif has changed
Binary file includes/clientside/tinymce/themes/advanced/images/close.gif has changed
Binary file includes/clientside/tinymce/themes/advanced/images/code.gif has changed
Binary file includes/clientside/tinymce/themes/advanced/images/color.gif has changed
Binary file includes/clientside/tinymce/themes/advanced/images/colors.jpg has changed
Binary file includes/clientside/tinymce/themes/advanced/images/copy.gif has changed
Binary file includes/clientside/tinymce/themes/advanced/images/custom_1.gif has changed
Binary file includes/clientside/tinymce/themes/advanced/images/cut.gif has changed
Binary file includes/clientside/tinymce/themes/advanced/images/forecolor.gif has changed
Binary file includes/clientside/tinymce/themes/advanced/images/help.gif has changed
Binary file includes/clientside/tinymce/themes/advanced/images/hr.gif has changed
Binary file includes/clientside/tinymce/themes/advanced/images/image.gif has changed
Binary file includes/clientside/tinymce/themes/advanced/images/indent.gif has changed
Binary file includes/clientside/tinymce/themes/advanced/images/insert_button_bg.gif has changed
Binary file includes/clientside/tinymce/themes/advanced/images/italic.gif has changed
Binary file includes/clientside/tinymce/themes/advanced/images/italic_de_se.gif has changed
Binary file includes/clientside/tinymce/themes/advanced/images/italic_es.gif has changed
Binary file includes/clientside/tinymce/themes/advanced/images/italic_ru.gif has changed
Binary file includes/clientside/tinymce/themes/advanced/images/italic_tw.gif has changed
Binary file includes/clientside/tinymce/themes/advanced/images/justifycenter.gif has changed
Binary file includes/clientside/tinymce/themes/advanced/images/justifyfull.gif has changed
Binary file includes/clientside/tinymce/themes/advanced/images/justifyleft.gif has changed
Binary file includes/clientside/tinymce/themes/advanced/images/justifyright.gif has changed
Binary file includes/clientside/tinymce/themes/advanced/images/link.gif has changed
Binary file includes/clientside/tinymce/themes/advanced/images/menu_check.gif has changed
Binary file includes/clientside/tinymce/themes/advanced/images/newdocument.gif has changed
Binary file includes/clientside/tinymce/themes/advanced/images/numlist.gif has changed
Binary file includes/clientside/tinymce/themes/advanced/images/opacity.png has changed
Binary file includes/clientside/tinymce/themes/advanced/images/outdent.gif has changed
Binary file includes/clientside/tinymce/themes/advanced/images/paste.gif has changed
Binary file includes/clientside/tinymce/themes/advanced/images/redo.gif has changed
Binary file includes/clientside/tinymce/themes/advanced/images/removeformat.gif has changed
Binary file includes/clientside/tinymce/themes/advanced/images/separator.gif has changed
Binary file includes/clientside/tinymce/themes/advanced/images/spacer.gif has changed
Binary file includes/clientside/tinymce/themes/advanced/images/statusbar_resize.gif has changed
Binary file includes/clientside/tinymce/themes/advanced/images/strikethrough.gif has changed
Binary file includes/clientside/tinymce/themes/advanced/images/sub.gif has changed
Binary file includes/clientside/tinymce/themes/advanced/images/sup.gif has changed
Binary file includes/clientside/tinymce/themes/advanced/images/underline.gif has changed
Binary file includes/clientside/tinymce/themes/advanced/images/underline_es.gif has changed
Binary file includes/clientside/tinymce/themes/advanced/images/underline_fr.gif has changed
Binary file includes/clientside/tinymce/themes/advanced/images/underline_ru.gif has changed
Binary file includes/clientside/tinymce/themes/advanced/images/underline_tw.gif has changed
Binary file includes/clientside/tinymce/themes/advanced/images/undo.gif has changed
Binary file includes/clientside/tinymce/themes/advanced/images/unlink.gif has changed
Binary file includes/clientside/tinymce/themes/advanced/images/visualaid.gif has changed
Binary file includes/clientside/tinymce/themes/advanced/images/xp/tab_bg.gif has changed
Binary file includes/clientside/tinymce/themes/advanced/images/xp/tab_end.gif has changed
Binary file includes/clientside/tinymce/themes/advanced/images/xp/tab_sel_bg.gif has changed
Binary file includes/clientside/tinymce/themes/advanced/images/xp/tab_sel_end.gif has changed
Binary file includes/clientside/tinymce/themes/advanced/images/xp/tabs_bg.gif has changed
Binary file includes/clientside/tinymce/themes/advanced/img/colorpicker.jpg has changed
Binary file includes/clientside/tinymce/themes/advanced/img/icons.gif has changed
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/includes/clientside/tinymce/themes/advanced/js/about.js	Fri Feb 22 12:51:53 2008 -0500
@@ -0,0 +1,76 @@
+tinyMCEPopup.requireLangPack();
+
+function init() {
+	var ed, tcont;
+
+	tinyMCEPopup.resizeToInnerSize();
+	ed = tinyMCEPopup.editor;
+
+	// Give FF some time
+	window.setTimeout('insertHelpIFrame();', 10);
+
+	tcont = document.getElementById('plugintablecontainer');
+	document.getElementById('plugins_tab').style.display = 'none';
+
+	var html = "";
+	html += '<table id="plugintable">';
+	html += '<thead>';
+	html += '<tr>';
+	html += '<td>' + ed.getLang('advanced_dlg.about_plugin') + '</td>';
+	html += '<td>' + ed.getLang('advanced_dlg.about_author') + '</td>';
+	html += '<td>' + ed.getLang('advanced_dlg.about_version') + '</td>';
+	html += '</tr>';
+	html += '</thead>';
+	html += '<tbody>';
+
+	tinymce.each(ed.plugins, function(p, n) {
+		var info;
+
+		if (!p.getInfo)
+			return;
+
+		html += '<tr>';
+
+		info = p.getInfo();
+
+		if (info.infourl != null && info.infourl != '')
+			html += '<td width="50%" title="' + n + '"><a href="' + info.infourl + '" target="_blank">' + info.longname + '</a></td>';
+		else
+			html += '<td width="50%" title="' + n + '">' + info.longname + '</td>';
+
+		if (info.authorurl != null && info.authorurl != '')
+			html += '<td width="35%"><a href="' + info.authorurl + '" target="_blank">' + info.author + '</a></td>';
+		else
+			html += '<td width="35%">' + info.author + '</td>';
+
+		html += '<td width="15%">' + info.version + '</td>';
+		html += '</tr>';
+
+		document.getElementById('plugins_tab').style.display = '';
+
+	});
+
+	html += '</tbody>';
+	html += '</table>';
+
+	tcont.innerHTML = html;
+
+	tinyMCEPopup.dom.get('version').innerHTML = tinymce.majorVersion + "." + tinymce.minorVersion;
+	tinyMCEPopup.dom.get('date').innerHTML = tinymce.releaseDate;
+}
+
+function insertHelpIFrame() {
+	var html;
+
+	if (tinyMCEPopup.getParam('docs_url')) {
+		html = '<iframe width="100%" height="300" src="' + tinyMCEPopup.editor.baseURI.toAbsolute(tinyMCEPopup.getParam('docs_url')) + '"></iframe>';
+		document.getElementById('iframecontainer').innerHTML = html;
+		document.getElementById('help_tab').style.display = 'block';
+	}
+}
+
+tinyMCEPopup.onInit.add(init);
+
+// For modal dialogs in IE
+if (tinymce.isIE)
+	document.write('<base target="_self" />');
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/includes/clientside/tinymce/themes/advanced/js/anchor.js	Fri Feb 22 12:51:53 2008 -0500
@@ -0,0 +1,33 @@
+tinyMCEPopup.requireLangPack();
+
+var AnchorDialog = {
+	init : function(ed) {
+		var action, elm, f = document.forms[0];
+
+		this.editor = ed;
+		elm = ed.dom.getParent(ed.selection.getNode(), 'A,IMG');
+		v = ed.dom.getAttrib(elm, 'name');
+
+		if (v)
+			f.anchorName.value = v;
+
+		f.insert.value = ed.getLang(elm ? 'update' : 'insert');
+	},
+
+	update : function() {
+		var ed = this.editor;
+		
+		tinyMCEPopup.restoreSelection();
+		ed.selection.collapse(1);
+
+		// Webkit acts weird if empty inline element is inserted so we need to use a image instead
+		if (tinymce.isWebKit)
+			ed.execCommand('mceInsertContent', 0, ed.dom.createHTML('img', {mce_name : 'a', name : document.forms[0].anchorName.value, 'class' : 'mceItemAnchor'}));
+		else
+			ed.execCommand('mceInsertContent', 0, ed.dom.createHTML('a', {name : document.forms[0].anchorName.value, 'class' : 'mceItemAnchor'}, ''));
+
+		tinyMCEPopup.close();
+	}
+};
+
+tinyMCEPopup.onInit.add(AnchorDialog.init, AnchorDialog);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/includes/clientside/tinymce/themes/advanced/js/charmap.js	Fri Feb 22 12:51:53 2008 -0500
@@ -0,0 +1,328 @@
+tinyMCEPopup.requireLangPack();
+
+var charmap = [
+	['&nbsp;',    '&#160;',  true, 'no-break space'],
+	['&amp;',     '&#38;',   true, 'ampersand'],
+	['&quot;',    '&#34;',   true, 'quotation mark'],
+// finance
+	['&cent;',    '&#162;',  true, 'cent sign'],
+	['&euro;',    '&#8364;', true, 'euro sign'],
+	['&pound;',   '&#163;',  true, 'pound sign'],
+	['&yen;',     '&#165;',  true, 'yen sign'],
+// signs
+	['&copy;',    '&#169;',  true, 'copyright sign'],
+	['&reg;',     '&#174;',  true, 'registered sign'],
+	['&trade;',   '&#8482;', true, 'trade mark sign'],
+	['&permil;',  '&#8240;', true, 'per mille sign'],
+	['&micro;',   '&#181;',  true, 'micro sign'],
+	['&middot;',  '&#183;',  true, 'middle dot'],
+	['&bull;',    '&#8226;', true, 'bullet'],
+	['&hellip;',  '&#8230;', true, 'three dot leader'],
+	['&prime;',   '&#8242;', true, 'minutes / feet'],
+	['&Prime;',   '&#8243;', true, 'seconds / inches'],
+	['&sect;',    '&#167;',  true, 'section sign'],
+	['&para;',    '&#182;',  true, 'paragraph sign'],
+	['&szlig;',   '&#223;',  true, 'sharp s / ess-zed'],
+// quotations
+	['&lsaquo;',  '&#8249;', true, 'single left-pointing angle quotation mark'],
+	['&rsaquo;',  '&#8250;', true, 'single right-pointing angle quotation mark'],
+	['&laquo;',   '&#171;',  true, 'left pointing guillemet'],
+	['&raquo;',   '&#187;',  true, 'right pointing guillemet'],
+	['&lsquo;',   '&#8216;', true, 'left single quotation mark'],
+	['&rsquo;',   '&#8217;', true, 'right single quotation mark'],
+	['&ldquo;',   '&#8220;', true, 'left double quotation mark'],
+	['&rdquo;',   '&#8221;', true, 'right double quotation mark'],
+	['&sbquo;',   '&#8218;', true, 'single low-9 quotation mark'],
+	['&bdquo;',   '&#8222;', true, 'double low-9 quotation mark'],
+	['&lt;',      '&#60;',   true, 'less-than sign'],
+	['&gt;',      '&#62;',   true, 'greater-than sign'],
+	['&le;',      '&#8804;', true, 'less-than or equal to'],
+	['&ge;',      '&#8805;', true, 'greater-than or equal to'],
+	['&ndash;',   '&#8211;', true, 'en dash'],
+	['&mdash;',   '&#8212;', true, 'em dash'],
+	['&macr;',    '&#175;',  true, 'macron'],
+	['&oline;',   '&#8254;', true, 'overline'],
+	['&curren;',  '&#164;',  true, 'currency sign'],
+	['&brvbar;',  '&#166;',  true, 'broken bar'],
+	['&uml;',     '&#168;',  true, 'diaeresis'],
+	['&iexcl;',   '&#161;',  true, 'inverted exclamation mark'],
+	['&iquest;',  '&#191;',  true, 'turned question mark'],
+	['&circ;',    '&#710;',  true, 'circumflex accent'],
+	['&tilde;',   '&#732;',  true, 'small tilde'],
+	['&deg;',     '&#176;',  true, 'degree sign'],
+	['&minus;',   '&#8722;', true, 'minus sign'],
+	['&plusmn;',  '&#177;',  true, 'plus-minus sign'],
+	['&divide;',  '&#247;',  true, 'division sign'],
+	['&frasl;',   '&#8260;', true, 'fraction slash'],
+	['&times;',   '&#215;',  true, 'multiplication sign'],
+	['&sup1;',    '&#185;',  true, 'superscript one'],
+	['&sup2;',    '&#178;',  true, 'superscript two'],
+	['&sup3;',    '&#179;',  true, 'superscript three'],
+	['&frac14;',  '&#188;',  true, 'fraction one quarter'],
+	['&frac12;',  '&#189;',  true, 'fraction one half'],
+	['&frac34;',  '&#190;',  true, 'fraction three quarters'],
+// math / logical
+	['&fnof;',    '&#402;',  true, 'function / florin'],
+	['&int;',     '&#8747;', true, 'integral'],
+	['&sum;',     '&#8721;', true, 'n-ary sumation'],
+	['&infin;',   '&#8734;', true, 'infinity'],
+	['&radic;',   '&#8730;', true, 'square root'],
+	['&sim;',     '&#8764;', false,'similar to'],
+	['&cong;',    '&#8773;', false,'approximately equal to'],
+	['&asymp;',   '&#8776;', true, 'almost equal to'],
+	['&ne;',      '&#8800;', true, 'not equal to'],
+	['&equiv;',   '&#8801;', true, 'identical to'],
+	['&isin;',    '&#8712;', false,'element of'],
+	['&notin;',   '&#8713;', false,'not an element of'],
+	['&ni;',      '&#8715;', false,'contains as member'],
+	['&prod;',    '&#8719;', true, 'n-ary product'],
+	['&and;',     '&#8743;', false,'logical and'],
+	['&or;',      '&#8744;', false,'logical or'],
+	['&not;',     '&#172;',  true, 'not sign'],
+	['&cap;',     '&#8745;', true, 'intersection'],
+	['&cup;',     '&#8746;', false,'union'],
+	['&part;',    '&#8706;', true, 'partial differential'],
+	['&forall;',  '&#8704;', false,'for all'],
+	['&exist;',   '&#8707;', false,'there exists'],
+	['&empty;',   '&#8709;', false,'diameter'],
+	['&nabla;',   '&#8711;', false,'backward difference'],
+	['&lowast;',  '&#8727;', false,'asterisk operator'],
+	['&prop;',    '&#8733;', false,'proportional to'],
+	['&ang;',     '&#8736;', false,'angle'],
+// undefined
+	['&acute;',   '&#180;',  true, 'acute accent'],
+	['&cedil;',   '&#184;',  true, 'cedilla'],
+	['&ordf;',    '&#170;',  true, 'feminine ordinal indicator'],
+	['&ordm;',    '&#186;',  true, 'masculine ordinal indicator'],
+	['&dagger;',  '&#8224;', true, 'dagger'],
+	['&Dagger;',  '&#8225;', true, 'double dagger'],
+// alphabetical special chars
+	['&Agrave;',  '&#192;',  true, 'A - grave'],
+	['&Aacute;',  '&#193;',  true, 'A - acute'],
+	['&Acirc;',   '&#194;',  true, 'A - circumflex'],
+	['&Atilde;',  '&#195;',  true, 'A - tilde'],
+	['&Auml;',    '&#196;',  true, 'A - diaeresis'],
+	['&Aring;',   '&#197;',  true, 'A - ring above'],
+	['&AElig;',   '&#198;',  true, 'ligature AE'],
+	['&Ccedil;',  '&#199;',  true, 'C - cedilla'],
+	['&Egrave;',  '&#200;',  true, 'E - grave'],
+	['&Eacute;',  '&#201;',  true, 'E - acute'],
+	['&Ecirc;',   '&#202;',  true, 'E - circumflex'],
+	['&Euml;',    '&#203;',  true, 'E - diaeresis'],
+	['&Igrave;',  '&#204;',  true, 'I - grave'],
+	['&Iacute;',  '&#205;',  true, 'I - acute'],
+	['&Icirc;',   '&#206;',  true, 'I - circumflex'],
+	['&Iuml;',    '&#207;',  true, 'I - diaeresis'],
+	['&ETH;',     '&#208;',  true, 'ETH'],
+	['&Ntilde;',  '&#209;',  true, 'N - tilde'],
+	['&Ograve;',  '&#210;',  true, 'O - grave'],
+	['&Oacute;',  '&#211;',  true, 'O - acute'],
+	['&Ocirc;',   '&#212;',  true, 'O - circumflex'],
+	['&Otilde;',  '&#213;',  true, 'O - tilde'],
+	['&Ouml;',    '&#214;',  true, 'O - diaeresis'],
+	['&Oslash;',  '&#216;',  true, 'O - slash'],
+	['&OElig;',   '&#338;',  true, 'ligature OE'],
+	['&Scaron;',  '&#352;',  true, 'S - caron'],
+	['&Ugrave;',  '&#217;',  true, 'U - grave'],
+	['&Uacute;',  '&#218;',  true, 'U - acute'],
+	['&Ucirc;',   '&#219;',  true, 'U - circumflex'],
+	['&Uuml;',    '&#220;',  true, 'U - diaeresis'],
+	['&Yacute;',  '&#221;',  true, 'Y - acute'],
+	['&Yuml;',    '&#376;',  true, 'Y - diaeresis'],
+	['&THORN;',   '&#222;',  true, 'THORN'],
+	['&agrave;',  '&#224;',  true, 'a - grave'],
+	['&aacute;',  '&#225;',  true, 'a - acute'],
+	['&acirc;',   '&#226;',  true, 'a - circumflex'],
+	['&atilde;',  '&#227;',  true, 'a - tilde'],
+	['&auml;',    '&#228;',  true, 'a - diaeresis'],
+	['&aring;',   '&#229;',  true, 'a - ring above'],
+	['&aelig;',   '&#230;',  true, 'ligature ae'],
+	['&ccedil;',  '&#231;',  true, 'c - cedilla'],
+	['&egrave;',  '&#232;',  true, 'e - grave'],
+	['&eacute;',  '&#233;',  true, 'e - acute'],
+	['&ecirc;',   '&#234;',  true, 'e - circumflex'],
+	['&euml;',    '&#235;',  true, 'e - diaeresis'],
+	['&igrave;',  '&#236;',  true, 'i - grave'],
+	['&iacute;',  '&#237;',  true, 'i - acute'],
+	['&icirc;',   '&#238;',  true, 'i - circumflex'],
+	['&iuml;',    '&#239;',  true, 'i - diaeresis'],
+	['&eth;',     '&#240;',  true, 'eth'],
+	['&ntilde;',  '&#241;',  true, 'n - tilde'],
+	['&ograve;',  '&#242;',  true, 'o - grave'],
+	['&oacute;',  '&#243;',  true, 'o - acute'],
+	['&ocirc;',   '&#244;',  true, 'o - circumflex'],
+	['&otilde;',  '&#245;',  true, 'o - tilde'],
+	['&ouml;',    '&#246;',  true, 'o - diaeresis'],
+	['&oslash;',  '&#248;',  true, 'o slash'],
+	['&oelig;',   '&#339;',  true, 'ligature oe'],
+	['&scaron;',  '&#353;',  true, 's - caron'],
+	['&ugrave;',  '&#249;',  true, 'u - grave'],
+	['&uacute;',  '&#250;',  true, 'u - acute'],
+	['&ucirc;',   '&#251;',  true, 'u - circumflex'],
+	['&uuml;',    '&#252;',  true, 'u - diaeresis'],
+	['&yacute;',  '&#253;',  true, 'y - acute'],
+	['&thorn;',   '&#254;',  true, 'thorn'],
+	['&yuml;',    '&#255;',  true, 'y - diaeresis'],
+    ['&Alpha;',   '&#913;',  true, 'Alpha'],
+	['&Beta;',    '&#914;',  true, 'Beta'],
+	['&Gamma;',   '&#915;',  true, 'Gamma'],
+	['&Delta;',   '&#916;',  true, 'Delta'],
+	['&Epsilon;', '&#917;',  true, 'Epsilon'],
+	['&Zeta;',    '&#918;',  true, 'Zeta'],
+	['&Eta;',     '&#919;',  true, 'Eta'],
+	['&Theta;',   '&#920;',  true, 'Theta'],
+	['&Iota;',    '&#921;',  true, 'Iota'],
+	['&Kappa;',   '&#922;',  true, 'Kappa'],
+	['&Lambda;',  '&#923;',  true, 'Lambda'],
+	['&Mu;',      '&#924;',  true, 'Mu'],
+	['&Nu;',      '&#925;',  true, 'Nu'],
+	['&Xi;',      '&#926;',  true, 'Xi'],
+	['&Omicron;', '&#927;',  true, 'Omicron'],
+	['&Pi;',      '&#928;',  true, 'Pi'],
+	['&Rho;',     '&#929;',  true, 'Rho'],
+	['&Sigma;',   '&#931;',  true, 'Sigma'],
+	['&Tau;',     '&#932;',  true, 'Tau'],
+	['&Upsilon;', '&#933;',  true, 'Upsilon'],
+	['&Phi;',     '&#934;',  true, 'Phi'],
+	['&Chi;',     '&#935;',  true, 'Chi'],
+	['&Psi;',     '&#936;',  true, 'Psi'],
+	['&Omega;',   '&#937;',  true, 'Omega'],
+	['&alpha;',   '&#945;',  true, 'alpha'],
+	['&beta;',    '&#946;',  true, 'beta'],
+	['&gamma;',   '&#947;',  true, 'gamma'],
+	['&delta;',   '&#948;',  true, 'delta'],
+	['&epsilon;', '&#949;',  true, 'epsilon'],
+	['&zeta;',    '&#950;',  true, 'zeta'],
+	['&eta;',     '&#951;',  true, 'eta'],
+	['&theta;',   '&#952;',  true, 'theta'],
+	['&iota;',    '&#953;',  true, 'iota'],
+	['&kappa;',   '&#954;',  true, 'kappa'],
+	['&lambda;',  '&#955;',  true, 'lambda'],
+	['&mu;',      '&#956;',  true, 'mu'],
+	['&nu;',      '&#957;',  true, 'nu'],
+	['&xi;',      '&#958;',  true, 'xi'],
+	['&omicron;', '&#959;',  true, 'omicron'],
+	['&pi;',      '&#960;',  true, 'pi'],
+	['&rho;',     '&#961;',  true, 'rho'],
+	['&sigmaf;',  '&#962;',  true, 'final sigma'],
+	['&sigma;',   '&#963;',  true, 'sigma'],
+	['&tau;',     '&#964;',  true, 'tau'],
+	['&upsilon;', '&#965;',  true, 'upsilon'],
+	['&phi;',     '&#966;',  true, 'phi'],
+	['&chi;',     '&#967;',  true, 'chi'],
+	['&psi;',     '&#968;',  true, 'psi'],
+	['&omega;',   '&#969;',  true, 'omega'],
+// symbols
+	['&alefsym;', '&#8501;', false,'alef symbol'],
+	['&piv;',     '&#982;',  false,'pi symbol'],
+	['&real;',    '&#8476;', false,'real part symbol'],
+	['&thetasym;','&#977;',  false,'theta symbol'],
+	['&upsih;',   '&#978;',  false,'upsilon - hook symbol'],
+	['&weierp;',  '&#8472;', false,'Weierstrass p'],
+	['&image;',   '&#8465;', false,'imaginary part'],
+// arrows
+	['&larr;',    '&#8592;', true, 'leftwards arrow'],
+	['&uarr;',    '&#8593;', true, 'upwards arrow'],
+	['&rarr;',    '&#8594;', true, 'rightwards arrow'],
+	['&darr;',    '&#8595;', true, 'downwards arrow'],
+	['&harr;',    '&#8596;', true, 'left right arrow'],
+	['&crarr;',   '&#8629;', false,'carriage return'],
+	['&lArr;',    '&#8656;', false,'leftwards double arrow'],
+	['&uArr;',    '&#8657;', false,'upwards double arrow'],
+	['&rArr;',    '&#8658;', false,'rightwards double arrow'],
+	['&dArr;',    '&#8659;', false,'downwards double arrow'],
+	['&hArr;',    '&#8660;', false,'left right double arrow'],
+	['&there4;',  '&#8756;', false,'therefore'],
+	['&sub;',     '&#8834;', false,'subset of'],
+	['&sup;',     '&#8835;', false,'superset of'],
+	['&nsub;',    '&#8836;', false,'not a subset of'],
+	['&sube;',    '&#8838;', false,'subset of or equal to'],
+	['&supe;',    '&#8839;', false,'superset of or equal to'],
+	['&oplus;',   '&#8853;', false,'circled plus'],
+	['&otimes;',  '&#8855;', false,'circled times'],
+	['&perp;',    '&#8869;', false,'perpendicular'],
+	['&sdot;',    '&#8901;', false,'dot operator'],
+	['&lceil;',   '&#8968;', false,'left ceiling'],
+	['&rceil;',   '&#8969;', false,'right ceiling'],
+	['&lfloor;',  '&#8970;', false,'left floor'],
+	['&rfloor;',  '&#8971;', false,'right floor'],
+	['&lang;',    '&#9001;', false,'left-pointing angle bracket'],
+	['&rang;',    '&#9002;', false,'right-pointing angle bracket'],
+	['&loz;',     '&#9674;', true,'lozenge'],
+	['&spades;',  '&#9824;', false,'black spade suit'],
+	['&clubs;',   '&#9827;', true, 'black club suit'],
+	['&hearts;',  '&#9829;', true, 'black heart suit'],
+	['&diams;',   '&#9830;', true, 'black diamond suit'],
+	['&ensp;',    '&#8194;', false,'en space'],
+	['&emsp;',    '&#8195;', false,'em space'],
+	['&thinsp;',  '&#8201;', false,'thin space'],
+	['&zwnj;',    '&#8204;', false,'zero width non-joiner'],
+	['&zwj;',     '&#8205;', false,'zero width joiner'],
+	['&lrm;',     '&#8206;', false,'left-to-right mark'],
+	['&rlm;',     '&#8207;', false,'right-to-left mark'],
+	['&shy;',     '&#173;',  false,'soft hyphen']
+];
+
+tinyMCEPopup.onInit.add(function() {
+	tinyMCEPopup.dom.setHTML('charmap', renderCharMapHTML());
+});
+
+function renderCharMapHTML() {
+	var charsPerRow = 20, tdWidth=20, tdHeight=20, i;
+	var html = '<table border="0" cellspacing="1" cellpadding="0" width="' + (tdWidth*charsPerRow) + '"><tr height="' + tdHeight + '">';
+	var cols=-1;
+
+	for (i=0; i<charmap.length; i++) {
+		if (charmap[i][2]==true) {
+			cols++;
+			html += ''
+				+ '<td width="' + tdWidth + '" height="' + tdHeight + '" class="charmap"'
+				+ ' onmouseover="this.className=\'charmapOver\';'
+				+ 'previewChar(\'' + charmap[i][1].substring(1,charmap[i][1].length) + '\',\'' + charmap[i][0].substring(1,charmap[i][0].length) + '\',\'' + charmap[i][3] + '\');"'
+				+ ' onmouseout="this.className=\'charmap\';"'
+				+ ' nowrap="nowrap" onclick="insertChar(\'' + charmap[i][1].substring(2,charmap[i][1].length-1) + '\');"><a style="text-decoration: none;" onfocus="previewChar(\'' + charmap[i][1].substring(1,charmap[i][1].length) + '\',\'' + charmap[i][0].substring(1,charmap[i][0].length) + '\',\'' + charmap[i][3] + '\');" href="javascript:insertChar(\'' + charmap[i][1].substring(2,charmap[i][1].length-1) + '\');" onclick="return false;" onmousedown="return false;" title="' + charmap[i][3] + '">'
+				+ charmap[i][1]
+				+ '</a></td>';
+			if ((cols+1) % charsPerRow == 0)
+				html += '</tr><tr height="' + tdHeight + '">';
+		}
+	 }
+
+	if (cols % charsPerRow > 0) {
+		var padd = charsPerRow - (cols % charsPerRow);
+		for (var i=0; i<padd-1; i++)
+			html += '<td width="' + tdWidth + '" height="' + tdHeight + '" class="charmap">&nbsp;</td>';
+	}
+
+	html += '</tr></table>';
+
+	return html;
+}
+
+function insertChar(chr) {
+	tinyMCEPopup.execCommand('mceInsertContent', false, '&#' + chr + ';');
+
+	// Refocus in window
+	if (tinyMCEPopup.isWindow)
+		window.focus();
+
+	tinyMCEPopup.editor.focus();
+	tinyMCEPopup.close();
+}
+
+function previewChar(codeA, codeB, codeN) {
+	var elmA = document.getElementById('codeA');
+	var elmB = document.getElementById('codeB');
+	var elmV = document.getElementById('codeV');
+	var elmN = document.getElementById('codeN');
+
+	if (codeA=='#160;') {
+		elmV.innerHTML = '__';
+	} else {
+		elmV.innerHTML = '&' + codeA;
+	}
+
+	elmB.innerHTML = '&amp;' + codeA;
+	elmA.innerHTML = '&amp;' + codeB;
+	elmN.innerHTML = codeN;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/includes/clientside/tinymce/themes/advanced/js/color_picker.js	Fri Feb 22 12:51:53 2008 -0500
@@ -0,0 +1,245 @@
+tinyMCEPopup.requireLangPack();
+
+var detail = 50, strhex = "0123456789abcdef", i, isMouseDown = false, isMouseOver = false;
+
+var colors = new Array(
+	"#000000","#000033","#000066","#000099","#0000cc","#0000ff","#330000","#330033",
+	"#330066","#330099","#3300cc","#3300ff","#660000","#660033","#660066","#660099",
+	"#6600cc","#6600ff","#990000","#990033","#990066","#990099","#9900cc","#9900ff",
+	"#cc0000","#cc0033","#cc0066","#cc0099","#cc00cc","#cc00ff","#ff0000","#ff0033",
+	"#ff0066","#ff0099","#ff00cc","#ff00ff","#003300","#003333","#003366","#003399",
+	"#0033cc","#0033ff","#333300","#333333","#333366","#333399","#3333cc","#3333ff",
+	"#663300","#663333","#663366","#663399","#6633cc","#6633ff","#993300","#993333",
+	"#993366","#993399","#9933cc","#9933ff","#cc3300","#cc3333","#cc3366","#cc3399",
+	"#cc33cc","#cc33ff","#ff3300","#ff3333","#ff3366","#ff3399","#ff33cc","#ff33ff",
+	"#006600","#006633","#006666","#006699","#0066cc","#0066ff","#336600","#336633",
+	"#336666","#336699","#3366cc","#3366ff","#666600","#666633","#666666","#666699",
+	"#6666cc","#6666ff","#996600","#996633","#996666","#996699","#9966cc","#9966ff",
+	"#cc6600","#cc6633","#cc6666","#cc6699","#cc66cc","#cc66ff","#ff6600","#ff6633",
+	"#ff6666","#ff6699","#ff66cc","#ff66ff","#009900","#009933","#009966","#009999",
+	"#0099cc","#0099ff","#339900","#339933","#339966","#339999","#3399cc","#3399ff",
+	"#669900","#669933","#669966","#669999","#6699cc","#6699ff","#999900","#999933",
+	"#999966","#999999","#9999cc","#9999ff","#cc9900","#cc9933","#cc9966","#cc9999",
+	"#cc99cc","#cc99ff","#ff9900","#ff9933","#ff9966","#ff9999","#ff99cc","#ff99ff",
+	"#00cc00","#00cc33","#00cc66","#00cc99","#00cccc","#00ccff","#33cc00","#33cc33",
+	"#33cc66","#33cc99","#33cccc","#33ccff","#66cc00","#66cc33","#66cc66","#66cc99",
+	"#66cccc","#66ccff","#99cc00","#99cc33","#99cc66","#99cc99","#99cccc","#99ccff",
+	"#cccc00","#cccc33","#cccc66","#cccc99","#cccccc","#ccccff","#ffcc00","#ffcc33",
+	"#ffcc66","#ffcc99","#ffcccc","#ffccff","#00ff00","#00ff33","#00ff66","#00ff99",
+	"#00ffcc","#00ffff","#33ff00","#33ff33","#33ff66","#33ff99","#33ffcc","#33ffff",
+	"#66ff00","#66ff33","#66ff66","#66ff99","#66ffcc","#66ffff","#99ff00","#99ff33",
+	"#99ff66","#99ff99","#99ffcc","#99ffff","#ccff00","#ccff33","#ccff66","#ccff99",
+	"#ccffcc","#ccffff","#ffff00","#ffff33","#ffff66","#ffff99","#ffffcc","#ffffff"
+);
+
+var named = {
+	'#F0F8FF':'AliceBlue','#FAEBD7':'AntiqueWhite','#00FFFF':'Aqua','#7FFFD4':'Aquamarine','#F0FFFF':'Azure','#F5F5DC':'Beige',
+	'#FFE4C4':'Bisque','#000000':'Black','#FFEBCD':'BlanchedAlmond','#0000FF':'Blue','#8A2BE2':'BlueViolet','#A52A2A':'Brown',
+	'#DEB887':'BurlyWood','#5F9EA0':'CadetBlue','#7FFF00':'Chartreuse','#D2691E':'Chocolate','#FF7F50':'Coral','#6495ED':'CornflowerBlue',
+	'#FFF8DC':'Cornsilk','#DC143C':'Crimson','#00FFFF':'Cyan','#00008B':'DarkBlue','#008B8B':'DarkCyan','#B8860B':'DarkGoldenRod',
+	'#A9A9A9':'DarkGray','#A9A9A9':'DarkGrey','#006400':'DarkGreen','#BDB76B':'DarkKhaki','#8B008B':'DarkMagenta','#556B2F':'DarkOliveGreen',
+	'#FF8C00':'Darkorange','#9932CC':'DarkOrchid','#8B0000':'DarkRed','#E9967A':'DarkSalmon','#8FBC8F':'DarkSeaGreen','#483D8B':'DarkSlateBlue',
+	'#2F4F4F':'DarkSlateGray','#2F4F4F':'DarkSlateGrey','#00CED1':'DarkTurquoise','#9400D3':'DarkViolet','#FF1493':'DeepPink','#00BFFF':'DeepSkyBlue',
+	'#696969':'DimGray','#696969':'DimGrey','#1E90FF':'DodgerBlue','#B22222':'FireBrick','#FFFAF0':'FloralWhite','#228B22':'ForestGreen',
+	'#FF00FF':'Fuchsia','#DCDCDC':'Gainsboro','#F8F8FF':'GhostWhite','#FFD700':'Gold','#DAA520':'GoldenRod','#808080':'Gray','#808080':'Grey',
+	'#008000':'Green','#ADFF2F':'GreenYellow','#F0FFF0':'HoneyDew','#FF69B4':'HotPink','#CD5C5C':'IndianRed','#4B0082':'Indigo','#FFFFF0':'Ivory',
+	'#F0E68C':'Khaki','#E6E6FA':'Lavender','#FFF0F5':'LavenderBlush','#7CFC00':'LawnGreen','#FFFACD':'LemonChiffon','#ADD8E6':'LightBlue',
+	'#F08080':'LightCoral','#E0FFFF':'LightCyan','#FAFAD2':'LightGoldenRodYellow','#D3D3D3':'LightGray','#D3D3D3':'LightGrey','#90EE90':'LightGreen',
+	'#FFB6C1':'LightPink','#FFA07A':'LightSalmon','#20B2AA':'LightSeaGreen','#87CEFA':'LightSkyBlue','#778899':'LightSlateGray','#778899':'LightSlateGrey',
+	'#B0C4DE':'LightSteelBlue','#FFFFE0':'LightYellow','#00FF00':'Lime','#32CD32':'LimeGreen','#FAF0E6':'Linen','#FF00FF':'Magenta','#800000':'Maroon',
+	'#66CDAA':'MediumAquaMarine','#0000CD':'MediumBlue','#BA55D3':'MediumOrchid','#9370D8':'MediumPurple','#3CB371':'MediumSeaGreen','#7B68EE':'MediumSlateBlue',
+	'#00FA9A':'MediumSpringGreen','#48D1CC':'MediumTurquoise','#C71585':'MediumVioletRed','#191970':'MidnightBlue','#F5FFFA':'MintCream','#FFE4E1':'MistyRose','#FFE4B5':'Moccasin',
+	'#FFDEAD':'NavajoWhite','#000080':'Navy','#FDF5E6':'OldLace','#808000':'Olive','#6B8E23':'OliveDrab','#FFA500':'Orange','#FF4500':'OrangeRed','#DA70D6':'Orchid',
+	'#EEE8AA':'PaleGoldenRod','#98FB98':'PaleGreen','#AFEEEE':'PaleTurquoise','#D87093':'PaleVioletRed','#FFEFD5':'PapayaWhip','#FFDAB9':'PeachPuff',
+	'#CD853F':'Peru','#FFC0CB':'Pink','#DDA0DD':'Plum','#B0E0E6':'PowderBlue','#800080':'Purple','#FF0000':'Red','#BC8F8F':'RosyBrown','#4169E1':'RoyalBlue',
+	'#8B4513':'SaddleBrown','#FA8072':'Salmon','#F4A460':'SandyBrown','#2E8B57':'SeaGreen','#FFF5EE':'SeaShell','#A0522D':'Sienna','#C0C0C0':'Silver',
+	'#87CEEB':'SkyBlue','#6A5ACD':'SlateBlue','#708090':'SlateGray','#708090':'SlateGrey','#FFFAFA':'Snow','#00FF7F':'SpringGreen',
+	'#4682B4':'SteelBlue','#D2B48C':'Tan','#008080':'Teal','#D8BFD8':'Thistle','#FF6347':'Tomato','#40E0D0':'Turquoise','#EE82EE':'Violet',
+	'#F5DEB3':'Wheat','#FFFFFF':'White','#F5F5F5':'WhiteSmoke','#FFFF00':'Yellow','#9ACD32':'YellowGreen'
+};
+
+function init() {
+	var inputColor = convertRGBToHex(tinyMCEPopup.getWindowArg('input_color'));
+
+	tinyMCEPopup.resizeToInnerSize();
+
+	generatePicker();
+
+	if (inputColor) {
+		changeFinalColor(inputColor);
+
+		col = convertHexToRGB(inputColor);
+
+		if (col)
+			updateLight(col.r, col.g, col.b);
+	}
+}
+
+function insertAction() {
+	var color = document.getElementById("color").value, f = tinyMCEPopup.getWindowArg('func');
+
+	tinyMCEPopup.restoreSelection();
+
+	if (f)
+		f(color);
+
+	tinyMCEPopup.close();
+}
+
+function showColor(color, name) {
+	if (name)
+		document.getElementById("colorname").innerHTML = name;
+
+	document.getElementById("preview").style.backgroundColor = color;
+	document.getElementById("color").value = color.toLowerCase();
+}
+
+function convertRGBToHex(col) {
+	var re = new RegExp("rgb\\s*\\(\\s*([0-9]+).*,\\s*([0-9]+).*,\\s*([0-9]+).*\\)", "gi");
+
+	if (!col)
+		return col;
+
+	var rgb = col.replace(re, "$1,$2,$3").split(',');
+	if (rgb.length == 3) {
+		r = parseInt(rgb[0]).toString(16);
+		g = parseInt(rgb[1]).toString(16);
+		b = parseInt(rgb[2]).toString(16);
+
+		r = r.length == 1 ? '0' + r : r;
+		g = g.length == 1 ? '0' + g : g;
+		b = b.length == 1 ? '0' + b : b;
+
+		return "#" + r + g + b;
+	}
+
+	return col;
+}
+
+function convertHexToRGB(col) {
+	if (col.indexOf('#') != -1) {
+		col = col.replace(new RegExp('[^0-9A-F]', 'gi'), '');
+
+		r = parseInt(col.substring(0, 2), 16);
+		g = parseInt(col.substring(2, 4), 16);
+		b = parseInt(col.substring(4, 6), 16);
+
+		return {r : r, g : g, b : b};
+	}
+
+	return null;
+}
+
+function generatePicker() {
+	var el = document.getElementById('light'), h = '', i;
+
+	for (i = 0; i < detail; i++){
+		h += '<div id="gs'+i+'" style="background-color:#000000; width:15px; height:3px; border-style:none; border-width:0px;"'
+		+ ' onclick="changeFinalColor(this.style.backgroundColor)"'
+		+ ' onmousedown="isMouseDown = true; return false;"'
+		+ ' onmouseup="isMouseDown = false;"'
+		+ ' onmousemove="if (isMouseDown && isMouseOver) changeFinalColor(this.style.backgroundColor); return false;"'
+		+ ' onmouseover="isMouseOver = true;"'
+		+ ' onmouseout="isMouseOver = false;"'
+		+ '></div>';
+	}
+
+	el.innerHTML = h;
+}
+
+function generateWebColors() {
+	var el = document.getElementById('webcolors'), h = '', i;
+
+	if (el.className == 'generated')
+		return;
+
+	h += '<table border="0" cellspacing="1" cellpadding="0">'
+		+ '<tr>';
+
+	for (i=0; i<colors.length; i++) {
+		h += '<td bgcolor="' + colors[i] + '" width="10" height="10">'
+			+ '<a href="javascript:insertAction();" onfocus="showColor(\'' + colors[i] +  '\');" onmouseover="showColor(\'' + colors[i] +  '\');" style="display:block;width:10px;height:10px;overflow:hidden;">'
+			+ '</a></td>';
+		if ((i+1) % 18 == 0)
+			h += '</tr><tr>';
+	}
+
+	h += '</table>';
+
+	el.innerHTML = h;
+	el.className = 'generated';
+}
+
+function generateNamedColors() {
+	var el = document.getElementById('namedcolors'), h = '', n, v, i = 0;
+
+	if (el.className == 'generated')
+		return;
+
+	for (n in named) {
+		v = named[n];
+		h += '<a href="javascript:insertAction();" onmouseover="showColor(\'' + n +  '\',\'' + v + '\');" style="background-color: ' + n + '"><!-- IE --></a>'
+	}
+
+	el.innerHTML = h;
+	el.className = 'generated';
+}
+
+function dechex(n) {
+	return strhex.charAt(Math.floor(n / 16)) + strhex.charAt(n % 16);
+}
+
+function computeColor(e) {
+	var x, y, partWidth, partDetail, imHeight, r, g, b, coef, i, finalCoef, finalR, finalG, finalB;
+
+	x = e.offsetX ? e.offsetX : (e.target ? e.clientX - e.target.x : 0);
+	y = e.offsetY ? e.offsetY : (e.target ? e.clientY - e.target.y : 0);
+
+	partWidth = document.getElementById('colors').width / 6;
+	partDetail = detail / 2;
+	imHeight = document.getElementById('colors').height;
+
+	r = (x >= 0)*(x < partWidth)*255 + (x >= partWidth)*(x < 2*partWidth)*(2*255 - x * 255 / partWidth) + (x >= 4*partWidth)*(x < 5*partWidth)*(-4*255 + x * 255 / partWidth) + (x >= 5*partWidth)*(x < 6*partWidth)*255;
+	g = (x >= 0)*(x < partWidth)*(x * 255 / partWidth) + (x >= partWidth)*(x < 3*partWidth)*255	+ (x >= 3*partWidth)*(x < 4*partWidth)*(4*255 - x * 255 / partWidth);
+	b = (x >= 2*partWidth)*(x < 3*partWidth)*(-2*255 + x * 255 / partWidth) + (x >= 3*partWidth)*(x < 5*partWidth)*255 + (x >= 5*partWidth)*(x < 6*partWidth)*(6*255 - x * 255 / partWidth);
+
+	coef = (imHeight - y) / imHeight;
+	r = 128 + (r - 128) * coef;
+	g = 128 + (g - 128) * coef;
+	b = 128 + (b - 128) * coef;
+
+	changeFinalColor('#' + dechex(r) + dechex(g) + dechex(b));
+	updateLight(r, g, b);
+}
+
+function updateLight(r, g, b) {
+	var i, partDetail = detail / 2, finalCoef, finalR, finalG, finalB, color;
+
+	for (i=0; i<detail; i++) {
+		if ((i>=0) && (i<partDetail)) {
+			finalCoef = i / partDetail;
+			finalR = dechex(255 - (255 - r) * finalCoef);
+			finalG = dechex(255 - (255 - g) * finalCoef);
+			finalB = dechex(255 - (255 - b) * finalCoef);
+		} else {
+			finalCoef = 2 - i / partDetail;
+			finalR = dechex(r * finalCoef);
+			finalG = dechex(g * finalCoef);
+			finalB = dechex(b * finalCoef);
+		}
+
+		color = finalR + finalG + finalB;
+
+		document.getElementById('gs' + i).style.backgroundColor = '#'+color;
+	}
+}
+
+function changeFinalColor(color) {
+	if (color.indexOf('#') == -1)
+		color = convertRGBToHex(color);
+
+	document.getElementById('preview').style.backgroundColor = color;
+	document.getElementById('color').value = color;
+}
+
+tinyMCEPopup.onInit.add(init);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/includes/clientside/tinymce/themes/advanced/js/image.js	Fri Feb 22 12:51:53 2008 -0500
@@ -0,0 +1,239 @@
+var ImageDialog = {
+	preInit : function() {
+		var url;
+
+		tinyMCEPopup.requireLangPack();
+
+		if (url = tinyMCEPopup.getParam("external_image_list_url"))
+			document.write('<script language="javascript" type="text/javascript" src="' + tinyMCEPopup.editor.documentBaseURI.toAbsolute(url) + '"></script>');
+	},
+
+	init : function() {
+		var f = document.forms[0], ed = tinyMCEPopup.editor;
+
+		// Setup browse button
+		document.getElementById('srcbrowsercontainer').innerHTML = getBrowserHTML('srcbrowser','src','image','theme_advanced_image');
+		if (isVisible('srcbrowser'))
+			document.getElementById('src').style.width = '180px';
+
+		e = ed.selection.getNode();
+
+		this.fillFileList('image_list', 'tinyMCEImageList');
+
+		if (e.nodeName == 'IMG') {
+			f.src.value = ed.dom.getAttrib(e, 'src');
+			f.alt.value = ed.dom.getAttrib(e, 'alt');
+			f.border.value = this.getAttrib(e, 'border');
+			f.vspace.value = this.getAttrib(e, 'vspace');
+			f.hspace.value = this.getAttrib(e, 'hspace');
+			f.width.value = ed.dom.getAttrib(e, 'width');
+			f.height.value = ed.dom.getAttrib(e, 'height');
+			f.insert.value = ed.getLang('update');
+			this.styleVal = ed.dom.getAttrib(e, 'style');
+			selectByValue(f, 'image_list', f.src.value);
+			selectByValue(f, 'align', this.getAttrib(e, 'align'));
+			this.updateStyle();
+		}
+	},
+
+	fillFileList : function(id, l) {
+		var dom = tinyMCEPopup.dom, lst = dom.get(id), v, cl;
+
+		l = window[l];
+
+		if (l && l.length > 0) {
+			lst.options[lst.options.length] = new Option('', '');
+
+			tinymce.each(l, function(o) {
+				lst.options[lst.options.length] = new Option(o[0], o[1]);
+			});
+		} else
+			dom.remove(dom.getParent(id, 'tr'));
+	},
+
+	update : function() {
+		var f = document.forms[0], nl = f.elements, ed = tinyMCEPopup.editor, args = {}, el;
+
+		if (f.src.value === '') {
+			ed.dom.remove(ed.selection.getNode());
+			ed.execCommand('mceRepaint');
+			tinyMCEPopup.close();
+			return;
+		}
+
+		if (!ed.settings.inline_styles) {
+			args = tinymce.extend(args, {
+				vspace : nl.vspace.value,
+				hspace : nl.hspace.value,
+				border : nl.border.value,
+				align : getSelectValue(f, 'align')
+			});
+		} else
+			args.style = this.styleVal;
+
+		tinymce.extend(args, {
+			src : f.src.value,
+			alt : f.alt.value,
+			width : f.width.value,
+			height : f.height.value
+		});
+
+		el = ed.selection.getNode();
+
+		if (el && el.nodeName == 'IMG') {
+			ed.dom.setAttribs(el, args);
+		} else {
+			ed.execCommand('mceInsertContent', false, '<img id="__mce_tmp" src="javascript:;" />');
+			ed.dom.setAttribs('__mce_tmp', args);
+			ed.dom.setAttrib('__mce_tmp', 'id', '');
+		}
+
+		tinyMCEPopup.close();
+	},
+
+	updateStyle : function() {
+		var dom = tinyMCEPopup.dom, st, v, f = document.forms[0];
+
+		if (tinyMCEPopup.editor.settings.inline_styles) {
+			st = tinyMCEPopup.dom.parseStyle(this.styleVal);
+
+			// Handle align
+			v = getSelectValue(f, 'align');
+			if (v) {
+				if (v == 'left' || v == 'right') {
+					st['float'] = v;
+					delete st['vertical-align'];
+				} else {
+					st['vertical-align'] = v;
+					delete st['float'];
+				}
+			} else {
+				delete st['float'];
+				delete st['vertical-align'];
+			}
+
+			// Handle border
+			v = f.border.value;
+			if (v || v == '0') {
+				if (v == '0')
+					st['border'] = '0';
+				else
+					st['border'] = v + 'px solid black';
+			} else
+				delete st['border'];
+
+			// Handle hspace
+			v = f.hspace.value;
+			if (v) {
+				delete st['margin'];
+				st['margin-left'] = v + 'px';
+				st['margin-right'] = v + 'px';
+			} else {
+				delete st['margin-left'];
+				delete st['margin-right'];
+			}
+
+			// Handle vspace
+			v = f.vspace.value;
+			if (v) {
+				delete st['margin'];
+				st['margin-top'] = v + 'px';
+				st['margin-bottom'] = v + 'px';
+			} else {
+				delete st['margin-top'];
+				delete st['margin-bottom'];
+			}
+
+			// Merge
+			st = tinyMCEPopup.dom.parseStyle(dom.serializeStyle(st));
+			this.styleVal = dom.serializeStyle(st);
+		}
+	},
+
+	getAttrib : function(e, at) {
+		var ed = tinyMCEPopup.editor, dom = ed.dom, v, v2;
+
+		if (ed.settings.inline_styles) {
+			switch (at) {
+				case 'align':
+					if (v = dom.getStyle(e, 'float'))
+						return v;
+
+					if (v = dom.getStyle(e, 'vertical-align'))
+						return v;
+
+					break;
+
+				case 'hspace':
+					v = dom.getStyle(e, 'margin-left')
+					v2 = dom.getStyle(e, 'margin-right');
+					if (v && v == v2)
+						return parseInt(v.replace(/[^0-9]/g, ''));
+
+					break;
+
+				case 'vspace':
+					v = dom.getStyle(e, 'margin-top')
+					v2 = dom.getStyle(e, 'margin-bottom');
+					if (v && v == v2)
+						return parseInt(v.replace(/[^0-9]/g, ''));
+
+					break;
+
+				case 'border':
+					v = 0;
+
+					tinymce.each(['top', 'right', 'bottom', 'left'], function(sv) {
+						sv = dom.getStyle(e, 'border-' + sv + '-width');
+
+						// False or not the same as prev
+						if (!sv || (sv != v && v !== 0)) {
+							v = 0;
+							return false;
+						}
+
+						if (sv)
+							v = sv;
+					});
+
+					if (v)
+						return parseInt(v.replace(/[^0-9]/g, ''));
+
+					break;
+			}
+		}
+
+		if (v = dom.getAttrib(e, at))
+			return v;
+
+		return '';
+	},
+
+	resetImageData : function() {
+		var f = document.forms[0];
+
+		f.width.value = f.height.value = "";	
+	},
+
+	updateImageData : function() {
+		var f = document.forms[0], t = ImageDialog;
+
+		if (f.width.value == "")
+			f.width.value = t.preloadImg.width;
+
+		if (f.height.value == "")
+			f.height.value = t.preloadImg.height;
+	},
+
+	getImageData : function() {
+		var f = document.forms[0];
+
+		this.preloadImg = new Image();
+		this.preloadImg.onload = this.updateImageData;
+		this.preloadImg.onerror = this.resetImageData;
+		this.preloadImg.src = tinyMCEPopup.editor.documentBaseURI.toAbsolute(f.src.value);
+	}
+};
+
+ImageDialog.preInit();
+tinyMCEPopup.onInit.add(ImageDialog.init, ImageDialog);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/includes/clientside/tinymce/themes/advanced/js/link.js	Fri Feb 22 12:51:53 2008 -0500
@@ -0,0 +1,124 @@
+tinyMCEPopup.requireLangPack();
+
+var LinkDialog = {
+	preInit : function() {
+		var url;
+
+		if (url = tinyMCEPopup.getParam("external_link_list_url"))
+			document.write('<script language="javascript" type="text/javascript" src="' + tinyMCEPopup.editor.documentBaseURI.toAbsolute(url) + '"></script>');
+	},
+
+	init : function() {
+		var f = document.forms[0], ed = tinyMCEPopup.editor;
+
+		// Setup browse button
+		document.getElementById('hrefbrowsercontainer').innerHTML = getBrowserHTML('hrefbrowser', 'href', 'file', 'theme_advanced_link');
+		if (isVisible('hrefbrowser'))
+			document.getElementById('href').style.width = '180px';
+
+		this.fillClassList('class_list');
+		this.fillFileList('link_list', 'tinyMCELinkList');
+		this.fillTargetList('target_list');
+
+		if (e = ed.dom.getParent(ed.selection.getNode(), 'A')) {
+			f.href.value = ed.dom.getAttrib(e, 'href');
+			f.linktitle.value = ed.dom.getAttrib(e, 'title');
+			f.insert.value = ed.getLang('update');
+			selectByValue(f, 'link_list', f.href.value);
+			selectByValue(f, 'target_list', ed.dom.getAttrib(e, 'target'));
+			selectByValue(f, 'class_list', ed.dom.getAttrib(e, 'class'));
+		}
+	},
+
+	update : function() {
+		var f = document.forms[0], ed = tinyMCEPopup.editor, e, b;
+
+		// Remove element if there is no href
+		if (!f.href.value) {
+			e = ed.dom.getParent(ed.selection.getNode(), 'A');
+			if (e) {
+				tinyMCEPopup.execCommand("mceBeginUndoLevel");
+				b = ed.selection.getBookmark();
+				ed.dom.remove(e, 1);
+				ed.selection.moveToBookmark(b);
+				tinyMCEPopup.execCommand("mceEndUndoLevel");
+				tinyMCEPopup.close();
+				return;
+			}
+		}
+
+		ed.execCommand('mceInsertLink', false, {
+			href : f.href.value,
+			title : f.linktitle.value,
+			target : f.target_list ? f.target_list.options[f.target_list.selectedIndex].value : null,
+			'class' : f.class_list ? f.class_list.options[f.class_list.selectedIndex].value : null
+		});
+
+		tinyMCEPopup.close();
+	},
+
+	checkPrefix : function(n) {
+		if (n.value && Validator.isEmail(n) && !/^\s*mailto:/i.test(n.value) && confirm(tinyMCEPopup.getLang('advanced_dlg.link_is_email')))
+			n.value = 'mailto:' + n.value;
+
+		if (/^\s*www./i.test(n.value) && confirm(tinyMCEPopup.getLang('advanced_dlg.link_is_external')))
+			n.value = 'http://' + n.value;
+	},
+
+	fillFileList : function(id, l) {
+		var dom = tinyMCEPopup.dom, lst = dom.get(id), v, cl;
+
+		l = window[l];
+
+		if (l && l.length > 0) {
+			lst.options[lst.options.length] = new Option('', '');
+
+			tinymce.each(l, function(o) {
+				lst.options[lst.options.length] = new Option(o[0], o[1]);
+			});
+		} else
+			dom.remove(dom.getParent(id, 'tr'));
+	},
+
+	fillClassList : function(id) {
+		var dom = tinyMCEPopup.dom, lst = dom.get(id), v, cl;
+
+		if (v = tinyMCEPopup.getParam('theme_advanced_styles')) {
+			cl = [];
+
+			tinymce.each(v.split(';'), function(v) {
+				var p = v.split('=');
+
+				cl.push({'title' : p[0], 'class' : p[1]});
+			});
+		} else
+			cl = tinyMCEPopup.editor.dom.getClasses();
+
+		if (cl.length > 0) {
+			lst.options[lst.options.length] = new Option(tinyMCEPopup.getLang('not_set'), '');
+
+			tinymce.each(cl, function(o) {
+				lst.options[lst.options.length] = new Option(o.title || o['class'], o['class']);
+			});
+		} else
+			dom.remove(dom.getParent(id, 'tr'));
+	},
+
+	fillTargetList : function(id) {
+		var dom = tinyMCEPopup.dom, lst = dom.get(id), v;
+
+		lst.options[lst.options.length] = new Option(tinyMCEPopup.getLang('not_set'), '');
+		lst.options[lst.options.length] = new Option(tinyMCEPopup.getLang('advanced_dlg.link_target_same'), '_self');
+		lst.options[lst.options.length] = new Option(tinyMCEPopup.getLang('advanced_dlg.link_target_blank'), '_blank');
+
+		if (v = tinyMCEPopup.getParam('theme_advanced_link_targets')) {
+			tinymce.each(v.split(','), function(v) {
+				v = v.split('=');
+				html += '<option value="' + v[1] + '">' + v[0] + '</option>';
+			});
+		}
+	}
+};
+
+LinkDialog.preInit();
+tinyMCEPopup.onInit.add(LinkDialog.init, LinkDialog);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/includes/clientside/tinymce/themes/advanced/js/source_editor.js	Fri Feb 22 12:51:53 2008 -0500
@@ -0,0 +1,62 @@
+tinyMCEPopup.requireLangPack();
+tinyMCEPopup.onInit.add(onLoadInit);
+
+function saveContent() {
+	tinyMCEPopup.editor.setContent(document.getElementById('htmlSource').value);
+	tinyMCEPopup.close();
+}
+
+function onLoadInit() {
+	tinyMCEPopup.resizeToInnerSize();
+
+	// Remove Gecko spellchecking
+	if (tinymce.isGecko)
+		document.body.spellcheck = tinyMCEPopup.editor.getParam("gecko_spellcheck");
+
+	document.getElementById('htmlSource').value = tinyMCEPopup.editor.getContent();
+
+	if (tinyMCEPopup.editor.getParam("theme_advanced_source_editor_wrap", true)) {
+		setWrap('soft');
+		document.getElementById('wraped').checked = true;
+	}
+
+	resizeInputs();
+}
+
+function setWrap(val) {
+	var v, n, s = document.getElementById('htmlSource');
+
+	s.wrap = val;
+
+	if (!tinymce.isIE) {
+		v = s.value;
+		n = s.cloneNode(false);
+		n.setAttribute("wrap", val);
+		s.parentNode.replaceChild(n, s);
+		n.value = v;
+	}
+}
+
+function toggleWordWrap(elm) {
+	if (elm.checked)
+		setWrap('soft');
+	else
+		setWrap('off');
+}
+
+var wHeight=0, wWidth=0, owHeight=0, owWidth=0;
+
+function resizeInputs() {
+	var el = document.getElementById('htmlSource');
+
+	if (!tinymce.isIE) {
+		 wHeight = self.innerHeight - 65;
+		 wWidth = self.innerWidth - 16;
+	} else {
+		 wHeight = document.body.clientHeight - 70;
+		 wWidth = document.body.clientWidth - 16;
+	}
+
+	el.style.height = Math.abs(wHeight) + 'px';
+	el.style.width  = Math.abs(wWidth) + 'px';
+}
--- a/includes/clientside/tinymce/themes/advanced/jscripts/about.js	Fri Feb 22 12:46:51 2008 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,75 +0,0 @@
-function init() {
-	var inst;
-
-	tinyMCEPopup.resizeToInnerSize();
-	inst = tinyMCE.selectedInstance;
-
-	// Give FF some time
-	window.setTimeout('insertHelpIFrame();', 10);
-
-	var tcont = document.getElementById('plugintablecontainer');
-	var plugins = tinyMCE.getParam('plugins', '', true, ',');
-	if (plugins.length == 0)
-		document.getElementById('plugins_tab').style.display = 'none';
-
-	var html = "";
-	html += '<table id="plugintable">';
-	html += '<thead>';
-	html += '<tr>';
-	html += '<td>' + tinyMCE.getLang('lang_plugin') + '</td>';
-	html += '<td>' + tinyMCE.getLang('lang_author') + '</td>';
-	html += '<td>' + tinyMCE.getLang('lang_version') + '</td>';
-	html += '</tr>';
-	html += '</thead>';
-	html += '<tbody>';
-
-	for (var i=0; i<inst.plugins.length; i++) {
-		var info = getPluginInfo(inst.plugins[i]);
-
-		html += '<tr>';
-
-		if (info.infourl != null && info.infourl != '')
-			html += '<td width="50%" title="' + plugins[i] + '"><a href="' + info.infourl + '" target="mceplugin">' + info.longname + '</a></td>';
-		else
-			html += '<td width="50%" title="' + plugins[i] + '">' + info.longname + '</td>';
-
-		if (info.authorurl != null && info.authorurl != '')
-			html += '<td width="35%"><a href="' + info.authorurl + '" target="mceplugin">' + info.author + '</a></td>';
-		else
-			html += '<td width="35%">' + info.author + '</td>';
-
-		html += '<td width="15%">' + info.version + '</td>';
-		html += '</tr>';
-	}
-
-	html += '</tbody>';
-	html += '</table>';
-
-	tcont.innerHTML = html;
-}
-
-function getPluginInfo(name) {
-	if (tinyMCE.plugins[name].getInfo)
-		return tinyMCE.plugins[name].getInfo();
-
-	return {
-		longname : name,
-		authorurl : '',
-		infourl : '',
-		author : '--',
-		version : '--'
-	};
-}
-
-function insertHelpIFrame() {
-	var html = '<iframe width="100%" height="300" src="' + tinyMCE.themeURL + "/docs/" + tinyMCE.settings['docs_language'] + "/index.htm" + '"></iframe>';
-
-	document.getElementById('iframecontainer').innerHTML = html;
-
-	html = '';
-	html += '<a href="http://www.moxiecode.com" target="_blank"><img src="http://tinymce.moxiecode.com/images/gotmoxie.png" alt="Got Moxie?" border="0" /></a> ';
-	html += '<a href="http://sourceforge.net/projects/tinymce/" target="_blank"><img src="http://sourceforge.net/sflogo.php?group_id=103281" alt="Hosted By Sourceforge" border="0" /></a> ';
-	html += '<a href="http://www.freshmeat.net/projects/tinymce" target="_blank"><img src="http://tinymce.moxiecode.com/images/fm.gif" alt="Also on freshmeat" border="0" /></a> ';
-
-	document.getElementById('buttoncontainer').innerHTML = html;
-}
--- a/includes/clientside/tinymce/themes/advanced/jscripts/anchor.js	Fri Feb 22 12:46:51 2008 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,74 +0,0 @@
-var action, element;
-
-function init() {
-	tinyMCEPopup.resizeToInnerSize();
-
-	var inst = tinyMCE.getInstanceById(tinyMCE.getWindowArg('editor_id'));
-	var anchor = tinyMCE.getParentElement(inst.getFocusElement(), "a", "name");
-	var img = inst.getFocusElement();
-	action = 'insert';
-
-	if (anchor != null) {
-		element = anchor;
-		action = "update";
-	}
-
-	if (tinyMCE.getAttrib(img, "class") == "mceItemAnchor") {
-		element = img;
-		action = "update";
-	}
-
-	if (action == "update")
-		document.forms[0].anchorName.value = element.nodeName == "IMG" ? element.getAttribute("title") : element.getAttribute("name");
-
-	document.forms[0].insert.value = tinyMCE.getLang('lang_' + action, 'Insert', true);
-}
-
-function insertAnchor() {
-	var inst = tinyMCE.getInstanceById(tinyMCE.getWindowArg('editor_id'));
-	var name = document.forms[0].anchorName.value, e;
-
-	tinyMCEPopup.execCommand("mceBeginUndoLevel");
-
-	if (action == "update") {
-		if (element.nodeName == "IMG")
-			element.setAttribute("title", name);
-		else
-			element.setAttribute("name", name);
-	} else {
-		var rng = inst.getRng();
-
-		if (rng.collapse)
-			rng.collapse(false);
-
-		name = name.replace(/&/g, '&amp;');
-		name = name.replace(/\"/g, '&quot;');
-		name = name.replace(/</g, '&lt;');
-		name = name.replace(/>/g, '&gt;');
-
-		// Fix for bug #1447335
-		if (tinyMCE.isGecko)
-			html = '<a id="mceNewAnchor" name="' + name + '"></a>';
-		else
-			html = '<a name="' + name + '"></a>';
-
-		tinyMCEPopup.execCommand("mceInsertContent", false, html);
-
-		// Fix for bug #1447335 force cursor after the anchor element
-		if (tinyMCE.isGecko) {
-			e = inst.getDoc().getElementById('mceNewAnchor');
-
-			if (e) {
-				inst.selection.selectNode(e, true, false, false);
-				e.removeAttribute('id');
-			}
-		}
-
-		tinyMCE.handleVisualAid(inst.getBody(), true, inst.visualAid, inst);
-	}
-
-	tinyMCEPopup.execCommand("mceEndUndoLevel");
-
-	tinyMCE.triggerNodeChange();
-	tinyMCEPopup.close();
-}
--- a/includes/clientside/tinymce/themes/advanced/jscripts/charmap.js	Fri Feb 22 12:46:51 2008 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,326 +0,0 @@
-function init() {
-	tinyMCEPopup.resizeToInnerSize();
-}
-
-var charmap = new Array();
-
-// for mor details please see w3c.org
-// now here is the complete list ;)
-
-charmap = [
-	['&nbsp;',    '&#160;',  true, 'no-break space'],
-	['&amp;',     '&#38;',   true, 'ampersand'],
-	['&quot;',    '&#34;',   true, 'quotation mark'],
-// finance
-	['&cent;',    '&#162;',  true, 'cent sign'],
-	['&euro;',    '&#8364;', true, 'euro sign'],
-	['&pound;',   '&#163;',  true, 'pound sign'],
-	['&yen;',     '&#165;',  true, 'yen sign'],
-// signs
-	['&copy;',    '&#169;',  true, 'copyright sign'],
-	['&reg;',     '&#174;',  true, 'registered sign'],
-	['&trade;',   '&#8482;', true, 'trade mark sign'],
-	['&permil;',  '&#8240;', true, 'per mille sign'],
-	['&micro;',   '&#181;',  true, 'micro sign'],
-	['&middot;',  '&#183;',  true, 'middle dot'],
-	['&bull;',    '&#8226;', true, 'bullet'],
-	['&hellip;',  '&#8230;', true, 'three dot leader'],
-	['&prime;',   '&#8242;', true, 'minutes / feet'],
-	['&Prime;',   '&#8243;', true, 'seconds / inches'],
-	['&sect;',    '&#167;',  true, 'section sign'],
-	['&para;',    '&#182;',  true, 'paragraph sign'],
-	['&szlig;',   '&#223;',  true, 'sharp s / ess-zed'],
-// quotations
-	['&lsaquo;',  '&#8249;', true, 'single left-pointing angle quotation mark'],
-	['&rsaquo;',  '&#8250;', true, 'single right-pointing angle quotation mark'],
-	['&laquo;',   '&#171;',  true, 'left pointing guillemet'],
-	['&raquo;',   '&#187;',  true, 'right pointing guillemet'],
-	['&lsquo;',   '&#8216;', true, 'left single quotation mark'],
-	['&rsquo;',   '&#8217;', true, 'right single quotation mark'],
-	['&ldquo;',   '&#8220;', true, 'left double quotation mark'],
-	['&rdquo;',   '&#8221;', true, 'right double quotation mark'],
-	['&sbquo;',   '&#8218;', true, 'single low-9 quotation mark'],
-	['&bdquo;',   '&#8222;', true, 'double low-9 quotation mark'],
-	['&lt;',      '&#60;',   true, 'less-than sign'],
-	['&gt;',      '&#62;',   true, 'greater-than sign'],
-	['&le;',      '&#8804;', true, 'less-than or equal to'],
-	['&ge;',      '&#8805;', true, 'greater-than or equal to'],
-	['&ndash;',   '&#8211;', true, 'en dash'],
-	['&mdash;',   '&#8212;', true, 'em dash'],
-	['&macr;',    '&#175;',  true, 'macron'],
-	['&oline;',   '&#8254;', true, 'overline'],
-	['&curren;',  '&#164;',  true, 'currency sign'],
-	['&brvbar;',  '&#166;',  true, 'broken bar'],
-	['&uml;',     '&#168;',  true, 'diaeresis'],
-	['&iexcl;',   '&#161;',  true, 'inverted exclamation mark'],
-	['&iquest;',  '&#191;',  true, 'turned question mark'],
-	['&circ;',    '&#710;',  true, 'circumflex accent'],
-	['&tilde;',   '&#732;',  true, 'small tilde'],
-	['&deg;',     '&#176;',  true, 'degree sign'],
-	['&minus;',   '&#8722;', true, 'minus sign'],
-	['&plusmn;',  '&#177;',  true, 'plus-minus sign'],
-	['&divide;',  '&#247;',  true, 'division sign'],
-	['&frasl;',   '&#8260;', true, 'fraction slash'],
-	['&times;',   '&#215;',  true, 'multiplication sign'],
-	['&sup1;',    '&#185;',  true, 'superscript one'],
-	['&sup2;',    '&#178;',  true, 'superscript two'],
-	['&sup3;',    '&#179;',  true, 'superscript three'],
-	['&frac14;',  '&#188;',  true, 'fraction one quarter'],
-	['&frac12;',  '&#189;',  true, 'fraction one half'],
-	['&frac34;',  '&#190;',  true, 'fraction three quarters'],
-// math / logical
-	['&fnof;',    '&#402;',  true, 'function / florin'],
-	['&int;',     '&#8747;', true, 'integral'],
-	['&sum;',     '&#8721;', true, 'n-ary sumation'],
-	['&infin;',   '&#8734;', true, 'infinity'],
-	['&radic;',   '&#8730;', true, 'square root'],
-	['&sim;',     '&#8764;', false,'similar to'],
-	['&cong;',    '&#8773;', false,'approximately equal to'],
-	['&asymp;',   '&#8776;', true, 'almost equal to'],
-	['&ne;',      '&#8800;', true, 'not equal to'],
-	['&equiv;',   '&#8801;', true, 'identical to'],
-	['&isin;',    '&#8712;', false,'element of'],
-	['&notin;',   '&#8713;', false,'not an element of'],
-	['&ni;',      '&#8715;', false,'contains as member'],
-	['&prod;',    '&#8719;', true, 'n-ary product'],
-	['&and;',     '&#8743;', false,'logical and'],
-	['&or;',      '&#8744;', false,'logical or'],
-	['&not;',     '&#172;',  true, 'not sign'],
-	['&cap;',     '&#8745;', true, 'intersection'],
-	['&cup;',     '&#8746;', false,'union'],
-	['&part;',    '&#8706;', true, 'partial differential'],
-	['&forall;',  '&#8704;', false,'for all'],
-	['&exist;',   '&#8707;', false,'there exists'],
-	['&empty;',   '&#8709;', false,'diameter'],
-	['&nabla;',   '&#8711;', false,'backward difference'],
-	['&lowast;',  '&#8727;', false,'asterisk operator'],
-	['&prop;',    '&#8733;', false,'proportional to'],
-	['&ang;',     '&#8736;', false,'angle'],
-// undefined
-	['&acute;',   '&#180;',  true, 'acute accent'],
-	['&cedil;',   '&#184;',  true, 'cedilla'],
-	['&ordf;',    '&#170;',  true, 'feminine ordinal indicator'],
-	['&ordm;',    '&#186;',  true, 'masculine ordinal indicator'],
-	['&dagger;',  '&#8224;', true, 'dagger'],
-	['&Dagger;',  '&#8225;', true, 'double dagger'],
-// alphabetical special chars
-	['&Agrave;',  '&#192;',  true, 'A - grave'],
-	['&Aacute;',  '&#193;',  true, 'A - acute'],
-	['&Acirc;',   '&#194;',  true, 'A - circumflex'],
-	['&Atilde;',  '&#195;',  true, 'A - tilde'],
-	['&Auml;',    '&#196;',  true, 'A - diaeresis'],
-	['&Aring;',   '&#197;',  true, 'A - ring above'],
-	['&AElig;',   '&#198;',  true, 'ligature AE'],
-	['&Ccedil;',  '&#199;',  true, 'C - cedilla'],
-	['&Egrave;',  '&#200;',  true, 'E - grave'],
-	['&Eacute;',  '&#201;',  true, 'E - acute'],
-	['&Ecirc;',   '&#202;',  true, 'E - circumflex'],
-	['&Euml;',    '&#203;',  true, 'E - diaeresis'],
-	['&Igrave;',  '&#204;',  true, 'I - grave'],
-	['&Iacute;',  '&#205;',  true, 'I - acute'],
-	['&Icirc;',   '&#206;',  true, 'I - circumflex'],
-	['&Iuml;',    '&#207;',  true, 'I - diaeresis'],
-	['&ETH;',     '&#208;',  true, 'ETH'],
-	['&Ntilde;',  '&#209;',  true, 'N - tilde'],
-	['&Ograve;',  '&#210;',  true, 'O - grave'],
-	['&Oacute;',  '&#211;',  true, 'O - acute'],
-	['&Ocirc;',   '&#212;',  true, 'O - circumflex'],
-	['&Otilde;',  '&#213;',  true, 'O - tilde'],
-	['&Ouml;',    '&#214;',  true, 'O - diaeresis'],
-	['&Oslash;',  '&#216;',  true, 'O - slash'],
-	['&OElig;',   '&#338;',  true, 'ligature OE'],
-	['&Scaron;',  '&#352;',  true, 'S - caron'],
-	['&Ugrave;',  '&#217;',  true, 'U - grave'],
-	['&Uacute;',  '&#218;',  true, 'U - acute'],
-	['&Ucirc;',   '&#219;',  true, 'U - circumflex'],
-	['&Uuml;',    '&#220;',  true, 'U - diaeresis'],
-	['&Yacute;',  '&#221;',  true, 'Y - acute'],
-	['&Yuml;',    '&#376;',  true, 'Y - diaeresis'],
-	['&THORN;',   '&#222;',  true, 'THORN'],
-	['&agrave;',  '&#224;',  true, 'a - grave'],
-	['&aacute;',  '&#225;',  true, 'a - acute'],
-	['&acirc;',   '&#226;',  true, 'a - circumflex'],
-	['&atilde;',  '&#227;',  true, 'a - tilde'],
-	['&auml;',    '&#228;',  true, 'a - diaeresis'],
-	['&aring;',   '&#229;',  true, 'a - ring above'],
-	['&aelig;',   '&#230;',  true, 'ligature ae'],
-	['&ccedil;',  '&#231;',  true, 'c - cedilla'],
-	['&egrave;',  '&#232;',  true, 'e - grave'],
-	['&eacute;',  '&#233;',  true, 'e - acute'],
-	['&ecirc;',   '&#234;',  true, 'e - circumflex'],
-	['&euml;',    '&#235;',  true, 'e - diaeresis'],
-	['&igrave;',  '&#236;',  true, 'i - grave'],
-	['&iacute;',  '&#237;',  true, 'i - acute'],
-	['&icirc;',   '&#238;',  true, 'i - circumflex'],
-	['&iuml;',    '&#239;',  true, 'i - diaeresis'],
-	['&eth;',     '&#240;',  true, 'eth'],
-	['&ntilde;',  '&#241;',  true, 'n - tilde'],
-	['&ograve;',  '&#242;',  true, 'o - grave'],
-	['&oacute;',  '&#243;',  true, 'o - acute'],
-	['&ocirc;',   '&#244;',  true, 'o - circumflex'],
-	['&otilde;',  '&#245;',  true, 'o - tilde'],
-	['&ouml;',    '&#246;',  true, 'o - diaeresis'],
-	['&oslash;',  '&#248;',  true, 'o slash'],
-	['&oelig;',   '&#339;',  true, 'ligature oe'],
-	['&scaron;',  '&#353;',  true, 's - caron'],
-	['&ugrave;',  '&#249;',  true, 'u - grave'],
-	['&uacute;',  '&#250;',  true, 'u - acute'],
-	['&ucirc;',   '&#251;',  true, 'u - circumflex'],
-	['&uuml;',    '&#252;',  true, 'u - diaeresis'],
-	['&yacute;',  '&#253;',  true, 'y - acute'],
-	['&thorn;',   '&#254;',  true, 'thorn'],
-	['&yuml;',    '&#255;',  true, 'y - diaeresis'],
-    ['&Alpha;',   '&#913;',  true, 'Alpha'],
-	['&Beta;',    '&#914;',  true, 'Beta'],
-	['&Gamma;',   '&#915;',  true, 'Gamma'],
-	['&Delta;',   '&#916;',  true, 'Delta'],
-	['&Epsilon;', '&#917;',  true, 'Epsilon'],
-	['&Zeta;',    '&#918;',  true, 'Zeta'],
-	['&Eta;',     '&#919;',  true, 'Eta'],
-	['&Theta;',   '&#920;',  true, 'Theta'],
-	['&Iota;',    '&#921;',  true, 'Iota'],
-	['&Kappa;',   '&#922;',  true, 'Kappa'],
-	['&Lambda;',  '&#923;',  true, 'Lambda'],
-	['&Mu;',      '&#924;',  true, 'Mu'],
-	['&Nu;',      '&#925;',  true, 'Nu'],
-	['&Xi;',      '&#926;',  true, 'Xi'],
-	['&Omicron;', '&#927;',  true, 'Omicron'],
-	['&Pi;',      '&#928;',  true, 'Pi'],
-	['&Rho;',     '&#929;',  true, 'Rho'],
-	['&Sigma;',   '&#931;',  true, 'Sigma'],
-	['&Tau;',     '&#932;',  true, 'Tau'],
-	['&Upsilon;', '&#933;',  true, 'Upsilon'],
-	['&Phi;',     '&#934;',  true, 'Phi'],
-	['&Chi;',     '&#935;',  true, 'Chi'],
-	['&Psi;',     '&#936;',  true, 'Psi'],
-	['&Omega;',   '&#937;',  true, 'Omega'],
-	['&alpha;',   '&#945;',  true, 'alpha'],
-	['&beta;',    '&#946;',  true, 'beta'],
-	['&gamma;',   '&#947;',  true, 'gamma'],
-	['&delta;',   '&#948;',  true, 'delta'],
-	['&epsilon;', '&#949;',  true, 'epsilon'],
-	['&zeta;',    '&#950;',  true, 'zeta'],
-	['&eta;',     '&#951;',  true, 'eta'],
-	['&theta;',   '&#952;',  true, 'theta'],
-	['&iota;',    '&#953;',  true, 'iota'],
-	['&kappa;',   '&#954;',  true, 'kappa'],
-	['&lambda;',  '&#955;',  true, 'lambda'],
-	['&mu;',      '&#956;',  true, 'mu'],
-	['&nu;',      '&#957;',  true, 'nu'],
-	['&xi;',      '&#958;',  true, 'xi'],
-	['&omicron;', '&#959;',  true, 'omicron'],
-	['&pi;',      '&#960;',  true, 'pi'],
-	['&rho;',     '&#961;',  true, 'rho'],
-	['&sigmaf;',  '&#962;',  true, 'final sigma'],
-	['&sigma;',   '&#963;',  true, 'sigma'],
-	['&tau;',     '&#964;',  true, 'tau'],
-	['&upsilon;', '&#965;',  true, 'upsilon'],
-	['&phi;',     '&#966;',  true, 'phi'],
-	['&chi;',     '&#967;',  true, 'chi'],
-	['&psi;',     '&#968;',  true, 'psi'],
-	['&omega;',   '&#969;',  true, 'omega'],
-// symbols
-	['&alefsym;', '&#8501;', false,'alef symbol'],
-	['&piv;',     '&#982;',  false,'pi symbol'],
-	['&real;',    '&#8476;', false,'real part symbol'],
-	['&thetasym;','&#977;',  false,'theta symbol'],
-	['&upsih;',   '&#978;',  false,'upsilon - hook symbol'],
-	['&weierp;',  '&#8472;', false,'Weierstrass p'],
-	['&image;',   '&#8465;', false,'imaginary part'],
-// arrows
-	['&larr;',    '&#8592;', true, 'leftwards arrow'],
-	['&uarr;',    '&#8593;', true, 'upwards arrow'],
-	['&rarr;',    '&#8594;', true, 'rightwards arrow'],
-	['&darr;',    '&#8595;', true, 'downwards arrow'],
-	['&harr;',    '&#8596;', true, 'left right arrow'],
-	['&crarr;',   '&#8629;', false,'carriage return'],
-	['&lArr;',    '&#8656;', false,'leftwards double arrow'],
-	['&uArr;',    '&#8657;', false,'upwards double arrow'],
-	['&rArr;',    '&#8658;', false,'rightwards double arrow'],
-	['&dArr;',    '&#8659;', false,'downwards double arrow'],
-	['&hArr;',    '&#8660;', false,'left right double arrow'],
-	['&there4;',  '&#8756;', false,'therefore'],
-	['&sub;',     '&#8834;', false,'subset of'],
-	['&sup;',     '&#8835;', false,'superset of'],
-	['&nsub;',    '&#8836;', false,'not a subset of'],
-	['&sube;',    '&#8838;', false,'subset of or equal to'],
-	['&supe;',    '&#8839;', false,'superset of or equal to'],
-	['&oplus;',   '&#8853;', false,'circled plus'],
-	['&otimes;',  '&#8855;', false,'circled times'],
-	['&perp;',    '&#8869;', false,'perpendicular'],
-	['&sdot;',    '&#8901;', false,'dot operator'],
-	['&lceil;',   '&#8968;', false,'left ceiling'],
-	['&rceil;',   '&#8969;', false,'right ceiling'],
-	['&lfloor;',  '&#8970;', false,'left floor'],
-	['&rfloor;',  '&#8971;', false,'right floor'],
-	['&lang;',    '&#9001;', false,'left-pointing angle bracket'],
-	['&rang;',    '&#9002;', false,'right-pointing angle bracket'],
-	['&loz;',     '&#9674;', true,'lozenge'],
-	['&spades;',  '&#9824;', false,'black spade suit'],
-	['&clubs;',   '&#9827;', true, 'black club suit'],
-	['&hearts;',  '&#9829;', true, 'black heart suit'],
-	['&diams;',   '&#9830;', true, 'black diamond suit'],
-	['&ensp;',    '&#8194;', false,'en space'],
-	['&emsp;',    '&#8195;', false,'em space'],
-	['&thinsp;',  '&#8201;', false,'thin space'],
-	['&zwnj;',    '&#8204;', false,'zero width non-joiner'],
-	['&zwj;',     '&#8205;', false,'zero width joiner'],
-	['&lrm;',     '&#8206;', false,'left-to-right mark'],
-	['&rlm;',     '&#8207;', false,'right-to-left mark'],
-	['&shy;',     '&#173;',  false,'soft hyphen']
-];
-
-function renderCharMapHTML() {
-	var charsPerRow = 20, tdWidth=20, tdHeight=20;
-	var html = '<table border="0" cellspacing="1" cellpadding="0" width="' + (tdWidth*charsPerRow) + '"><tr height="' + tdHeight + '">';
-	var cols=-1;
-	for (var i=0; i<charmap.length; i++) {
-		if (charmap[i][2]==true) {
-			cols++;
-			html += ''
-				+ '<td width="' + tdWidth + '" height="' + tdHeight + '" class="charmap"'
-				+ ' onmouseover="this.className=\'charmapOver\';'
-				+ 'previewChar(\'' + charmap[i][1].substring(1,charmap[i][1].length) + '\',\'' + charmap[i][0].substring(1,charmap[i][0].length) + '\',\'' + charmap[i][3] + '\');"'
-				+ ' onmouseout="this.className=\'charmap\';"'
-				+ ' nowrap="nowrap" onclick="insertChar(\'' + charmap[i][1].substring(2,charmap[i][1].length-1) + '\');"><a style="text-decoration: none;" onfocus="previewChar(\'' + charmap[i][1].substring(1,charmap[i][1].length) + '\',\'' + charmap[i][0].substring(1,charmap[i][0].length) + '\',\'' + charmap[i][3] + '\');" href="javascript:insertChar(\'' + charmap[i][1].substring(2,charmap[i][1].length-1) + '\');" onclick="return false;" onmousedown="return false;" title="' + charmap[i][3] + '">'
-				+ charmap[i][1]
-				+ '</a></td>';
-			if ((cols+1) % charsPerRow == 0)
-				html += '</tr><tr height="' + tdHeight + '">';
-		}
-	 }
-	if (cols % charsPerRow > 0) {
-		var padd = charsPerRow - (cols % charsPerRow);
-		for (var i=0; i<padd-1; i++)
-			html += '<td width="' + tdWidth + '" height="' + tdHeight + '" class="charmap">&nbsp;</td>';
-	}
-	html += '</tr></table>';
-	document.write(html);
-}
-
-function insertChar(chr) {
-	tinyMCEPopup.execCommand('mceInsertContent', false, '&#' + chr + ';');
-
-	// Refocus in window
-	if (tinyMCEPopup.isWindow)
-		window.focus();
-
-	tinyMCEPopup.close();
-}
-
-function previewChar(codeA, codeB, codeN) {
-	var elmA = document.getElementById('codeA');
-	var elmB = document.getElementById('codeB');
-	var elmV = document.getElementById('codeV');
-	var elmN = document.getElementById('codeN');
-
-	if (codeA=='#160;') {
-		elmV.innerHTML = '__';
-	} else {
-		elmV.innerHTML = '&' + codeA;
-	}
-
-	elmB.innerHTML = '&amp;' + codeA;
-	elmA.innerHTML = '&amp;' + codeB;
-	elmN.innerHTML = codeN;
-}
--- a/includes/clientside/tinymce/themes/advanced/jscripts/color_picker.js	Fri Feb 22 12:46:51 2008 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,249 +0,0 @@
-var detail = 50, strhex = "0123456789abcdef", i, isMouseDown = false, isMouseOver = false;
-
-var colors = new Array(
-	"#000000","#000033","#000066","#000099","#0000cc","#0000ff","#330000","#330033",
-	"#330066","#330099","#3300cc","#3300ff","#660000","#660033","#660066","#660099",
-	"#6600cc","#6600ff","#990000","#990033","#990066","#990099","#9900cc","#9900ff",
-	"#cc0000","#cc0033","#cc0066","#cc0099","#cc00cc","#cc00ff","#ff0000","#ff0033",
-	"#ff0066","#ff0099","#ff00cc","#ff00ff","#003300","#003333","#003366","#003399",
-	"#0033cc","#0033ff","#333300","#333333","#333366","#333399","#3333cc","#3333ff",
-	"#663300","#663333","#663366","#663399","#6633cc","#6633ff","#993300","#993333",
-	"#993366","#993399","#9933cc","#9933ff","#cc3300","#cc3333","#cc3366","#cc3399",
-	"#cc33cc","#cc33ff","#ff3300","#ff3333","#ff3366","#ff3399","#ff33cc","#ff33ff",
-	"#006600","#006633","#006666","#006699","#0066cc","#0066ff","#336600","#336633",
-	"#336666","#336699","#3366cc","#3366ff","#666600","#666633","#666666","#666699",
-	"#6666cc","#6666ff","#996600","#996633","#996666","#996699","#9966cc","#9966ff",
-	"#cc6600","#cc6633","#cc6666","#cc6699","#cc66cc","#cc66ff","#ff6600","#ff6633",
-	"#ff6666","#ff6699","#ff66cc","#ff66ff","#009900","#009933","#009966","#009999",
-	"#0099cc","#0099ff","#339900","#339933","#339966","#339999","#3399cc","#3399ff",
-	"#669900","#669933","#669966","#669999","#6699cc","#6699ff","#999900","#999933",
-	"#999966","#999999","#9999cc","#9999ff","#cc9900","#cc9933","#cc9966","#cc9999",
-	"#cc99cc","#cc99ff","#ff9900","#ff9933","#ff9966","#ff9999","#ff99cc","#ff99ff",
-	"#00cc00","#00cc33","#00cc66","#00cc99","#00cccc","#00ccff","#33cc00","#33cc33",
-	"#33cc66","#33cc99","#33cccc","#33ccff","#66cc00","#66cc33","#66cc66","#66cc99",
-	"#66cccc","#66ccff","#99cc00","#99cc33","#99cc66","#99cc99","#99cccc","#99ccff",
-	"#cccc00","#cccc33","#cccc66","#cccc99","#cccccc","#ccccff","#ffcc00","#ffcc33",
-	"#ffcc66","#ffcc99","#ffcccc","#ffccff","#00ff00","#00ff33","#00ff66","#00ff99",
-	"#00ffcc","#00ffff","#33ff00","#33ff33","#33ff66","#33ff99","#33ffcc","#33ffff",
-	"#66ff00","#66ff33","#66ff66","#66ff99","#66ffcc","#66ffff","#99ff00","#99ff33",
-	"#99ff66","#99ff99","#99ffcc","#99ffff","#ccff00","#ccff33","#ccff66","#ccff99",
-	"#ccffcc","#ccffff","#ffff00","#ffff33","#ffff66","#ffff99","#ffffcc","#ffffff"
-);
-
-var named = {
-	'#F0F8FF':'AliceBlue','#FAEBD7':'AntiqueWhite','#00FFFF':'Aqua','#7FFFD4':'Aquamarine','#F0FFFF':'Azure','#F5F5DC':'Beige',
-	'#FFE4C4':'Bisque','#000000':'Black','#FFEBCD':'BlanchedAlmond','#0000FF':'Blue','#8A2BE2':'BlueViolet','#A52A2A':'Brown',
-	'#DEB887':'BurlyWood','#5F9EA0':'CadetBlue','#7FFF00':'Chartreuse','#D2691E':'Chocolate','#FF7F50':'Coral','#6495ED':'CornflowerBlue',
-	'#FFF8DC':'Cornsilk','#DC143C':'Crimson','#00FFFF':'Cyan','#00008B':'DarkBlue','#008B8B':'DarkCyan','#B8860B':'DarkGoldenRod',
-	'#A9A9A9':'DarkGray','#A9A9A9':'DarkGrey','#006400':'DarkGreen','#BDB76B':'DarkKhaki','#8B008B':'DarkMagenta','#556B2F':'DarkOliveGreen',
-	'#FF8C00':'Darkorange','#9932CC':'DarkOrchid','#8B0000':'DarkRed','#E9967A':'DarkSalmon','#8FBC8F':'DarkSeaGreen','#483D8B':'DarkSlateBlue',
-	'#2F4F4F':'DarkSlateGray','#2F4F4F':'DarkSlateGrey','#00CED1':'DarkTurquoise','#9400D3':'DarkViolet','#FF1493':'DeepPink','#00BFFF':'DeepSkyBlue',
-	'#696969':'DimGray','#696969':'DimGrey','#1E90FF':'DodgerBlue','#B22222':'FireBrick','#FFFAF0':'FloralWhite','#228B22':'ForestGreen',
-	'#FF00FF':'Fuchsia','#DCDCDC':'Gainsboro','#F8F8FF':'GhostWhite','#FFD700':'Gold','#DAA520':'GoldenRod','#808080':'Gray','#808080':'Grey',
-	'#008000':'Green','#ADFF2F':'GreenYellow','#F0FFF0':'HoneyDew','#FF69B4':'HotPink','#CD5C5C':'IndianRed','#4B0082':'Indigo','#FFFFF0':'Ivory',
-	'#F0E68C':'Khaki','#E6E6FA':'Lavender','#FFF0F5':'LavenderBlush','#7CFC00':'LawnGreen','#FFFACD':'LemonChiffon','#ADD8E6':'LightBlue',
-	'#F08080':'LightCoral','#E0FFFF':'LightCyan','#FAFAD2':'LightGoldenRodYellow','#D3D3D3':'LightGray','#D3D3D3':'LightGrey','#90EE90':'LightGreen',
-	'#FFB6C1':'LightPink','#FFA07A':'LightSalmon','#20B2AA':'LightSeaGreen','#87CEFA':'LightSkyBlue','#778899':'LightSlateGray','#778899':'LightSlateGrey',
-	'#B0C4DE':'LightSteelBlue','#FFFFE0':'LightYellow','#00FF00':'Lime','#32CD32':'LimeGreen','#FAF0E6':'Linen','#FF00FF':'Magenta','#800000':'Maroon',
-	'#66CDAA':'MediumAquaMarine','#0000CD':'MediumBlue','#BA55D3':'MediumOrchid','#9370D8':'MediumPurple','#3CB371':'MediumSeaGreen','#7B68EE':'MediumSlateBlue',
-	'#00FA9A':'MediumSpringGreen','#48D1CC':'MediumTurquoise','#C71585':'MediumVioletRed','#191970':'MidnightBlue','#F5FFFA':'MintCream','#FFE4E1':'MistyRose','#FFE4B5':'Moccasin',
-	'#FFDEAD':'NavajoWhite','#000080':'Navy','#FDF5E6':'OldLace','#808000':'Olive','#6B8E23':'OliveDrab','#FFA500':'Orange','#FF4500':'OrangeRed','#DA70D6':'Orchid',
-	'#EEE8AA':'PaleGoldenRod','#98FB98':'PaleGreen','#AFEEEE':'PaleTurquoise','#D87093':'PaleVioletRed','#FFEFD5':'PapayaWhip','#FFDAB9':'PeachPuff',
-	'#CD853F':'Peru','#FFC0CB':'Pink','#DDA0DD':'Plum','#B0E0E6':'PowderBlue','#800080':'Purple','#FF0000':'Red','#BC8F8F':'RosyBrown','#4169E1':'RoyalBlue',
-	'#8B4513':'SaddleBrown','#FA8072':'Salmon','#F4A460':'SandyBrown','#2E8B57':'SeaGreen','#FFF5EE':'SeaShell','#A0522D':'Sienna','#C0C0C0':'Silver',
-	'#87CEEB':'SkyBlue','#6A5ACD':'SlateBlue','#708090':'SlateGray','#708090':'SlateGrey','#FFFAFA':'Snow','#00FF7F':'SpringGreen',
-	'#4682B4':'SteelBlue','#D2B48C':'Tan','#008080':'Teal','#D8BFD8':'Thistle','#FF6347':'Tomato','#40E0D0':'Turquoise','#EE82EE':'Violet',
-	'#F5DEB3':'Wheat','#FFFFFF':'White','#F5F5F5':'WhiteSmoke','#FFFF00':'Yellow','#9ACD32':'YellowGreen'
-};
-
-function init() {
-	var inputColor = convertRGBToHex(tinyMCE.getWindowArg('input_color'));
-
-	if (tinyMCE.isMSIE)
-		tinyMCEPopup.resizeToInnerSize();
-
-	generatePicker();
-
-	if (inputColor) {
-		changeFinalColor(inputColor);
-
-		col = convertHexToRGB(inputColor);
-
-		if (col)
-			updateLight(col.r, col.g, col.b);
-	}
-}
-
-function insertAction() {
-	var color = document.getElementById("color").value;
-
-	tinyMCEPopup.execCommand(tinyMCE.getWindowArg('command'), false, color);
-	tinyMCEPopup.close();
-}
-
-function showColor(color, name) {
-	if (name)
-		document.getElementById("colorname").innerHTML = name;
-
-	document.getElementById("preview").style.backgroundColor = color;
-	document.getElementById("color").value = color;
-}
-
-function convertRGBToHex(col) {
-	var re = new RegExp("rgb\\s*\\(\\s*([0-9]+).*,\\s*([0-9]+).*,\\s*([0-9]+).*\\)", "gi");
-
-	if (!col)
-		return col;
-
-	var rgb = col.replace(re, "$1,$2,$3").split(',');
-	if (rgb.length == 3) {
-		r = parseInt(rgb[0]).toString(16);
-		g = parseInt(rgb[1]).toString(16);
-		b = parseInt(rgb[2]).toString(16);
-
-		r = r.length == 1 ? '0' + r : r;
-		g = g.length == 1 ? '0' + g : g;
-		b = b.length == 1 ? '0' + b : b;
-
-		return "#" + r + g + b;
-	}
-
-	return col;
-}
-
-function convertHexToRGB(col) {
-	if (col.indexOf('#') != -1) {
-		col = col.replace(new RegExp('[^0-9A-F]', 'gi'), '');
-
-		r = parseInt(col.substring(0, 2), 16);
-		g = parseInt(col.substring(2, 4), 16);
-		b = parseInt(col.substring(4, 6), 16);
-
-		return {r : r, g : g, b : b};
-	}
-
-	return null;
-}
-
-function generatePicker() {
-	var el = document.getElementById('light'), h = '', i;
-
-	for (i = 0; i < detail; i++){
-		h += '<div id="gs'+i+'" style="background-color:#000000; width:15px; height:3px; border-style:none; border-width:0px;"'
-		+ ' onclick="changeFinalColor(this.style.backgroundColor)"'
-		+ ' onmousedown="isMouseDown = true; return false;"'
-		+ ' onmouseup="isMouseDown = false;"'
-		+ ' onmousemove="if (isMouseDown && isMouseOver) changeFinalColor(this.style.backgroundColor); return false;"'
-		+ ' onmouseover="isMouseOver = true;"'
-		+ ' onmouseout="isMouseOver = false;"'
-		+ '></div>';
-	}
-
-	el.innerHTML = h;
-}
-
-function generateWebColors() {
-	var el = document.getElementById('webcolors'), h = '', i;
-
-	if (el.className == 'generated')
-		return;
-
-	h += '<table border="0" cellspacing="1" cellpadding="0">'
-		+ '<tr>';
-
-	for (i=0; i<colors.length; i++) {
-		h += '<td bgcolor="' + colors[i] + '">'
-			+ '<a href="javascript:selectColor();" onfocus="showColor(\'' + colors[i] +  '\');" onmouseover="showColor(\'' + colors[i] +  '\');">'
-			+ '<img border="0" src="images/spacer.gif" width="10" height="10" title="' + colors[i] +  '" alt="' + colors[i] +  '" /></a></td>';
-		if ((i+1) % 18 == 0)
-			h += '</tr><tr>';
-	}
-
-	h += '</table>';
-
-	el.innerHTML = h;
-	el.className = 'generated';
-}
-
-function generateNamedColors() {
-	var el = document.getElementById('namedcolors'), h = '', n, v, i = 0;
-
-	if (el.className == 'generated')
-		return;
-
-	for (n in named) {
-		v = named[n];
-		h += '<a href="javascript:selectColor();" onmouseover="showColor(\'' + n +  '\',\'' + v + '\');" style="background-color: ' + n + '"><!-- IE --></a>'
-	}
-
-	el.innerHTML = h;
-	el.className = 'generated';
-}
-
-function selectColor() {
-	var color = document.getElementById("color").value;
-
-	if(window.opener)
-		window.opener.tinyMCE.execInstanceCommand(tinyMCE.getWindowArg('editor_id'),tinyMCE.getWindowArg('command'),false,color);
-
-	window.close();
-}
-
-function dechex(n) {
-	return strhex.charAt(Math.floor(n / 16)) + strhex.charAt(n % 16);
-}
-
-function computeColor(e) {
-	var x, y, partWidth, partDetail, imHeight, r, g, b, coef, i, finalCoef, finalR, finalG, finalB;
-
-	x = e.offsetX ? e.offsetX : (e.target ? e.clientX - e.target.x : 0);
-	y = e.offsetY ? e.offsetY : (e.target ? e.clientY - e.target.y : 0);
-
-	partWidth = document.getElementById('colorpicker').width / 6;
-	partDetail = detail / 2;
-	imHeight = document.getElementById('colorpicker').height;
-
-	r = (x >= 0)*(x < partWidth)*255 + (x >= partWidth)*(x < 2*partWidth)*(2*255 - x * 255 / partWidth) + (x >= 4*partWidth)*(x < 5*partWidth)*(-4*255 + x * 255 / partWidth) + (x >= 5*partWidth)*(x < 6*partWidth)*255;
-	g = (x >= 0)*(x < partWidth)*(x * 255 / partWidth) + (x >= partWidth)*(x < 3*partWidth)*255	+ (x >= 3*partWidth)*(x < 4*partWidth)*(4*255 - x * 255 / partWidth);
-	b = (x >= 2*partWidth)*(x < 3*partWidth)*(-2*255 + x * 255 / partWidth) + (x >= 3*partWidth)*(x < 5*partWidth)*255 + (x >= 5*partWidth)*(x < 6*partWidth)*(6*255 - x * 255 / partWidth);
-
-	coef = (imHeight - y) / imHeight;
-	r = 128 + (r - 128) * coef;
-	g = 128 + (g - 128) * coef;
-	b = 128 + (b - 128) * coef;
-
-	changeFinalColor('#' + dechex(r) + dechex(g) + dechex(b));
-	updateLight(r, g, b);
-}
-
-function updateLight(r, g, b) {
-	var i, partDetail = detail / 2, finalCoef, finalR, finalG, finalB, color;
-
-	for (i=0; i<detail; i++) {
-		if ((i>=0) && (i<partDetail)) {
-			finalCoef = i / partDetail;
-			finalR = dechex(255 - (255 - r) * finalCoef);
-			finalG = dechex(255 - (255 - g) * finalCoef);
-			finalB = dechex(255 - (255 - b) * finalCoef);
-		} else {
-			finalCoef = 2 - i / partDetail;
-			finalR = dechex(r * finalCoef);
-			finalG = dechex(g * finalCoef);
-			finalB = dechex(b * finalCoef);
-		}
-
-		color = finalR + finalG + finalB;
-
-		document.getElementById('gs' + i).style.backgroundColor = '#'+color;
-	}
-}
-
-function changeFinalColor(color) {
-	if (color.indexOf('#') == -1)
-		color = convertRGBToHex(color);
-
-	document.getElementById('preview').style.backgroundColor = color;
-	document.getElementById('color').value = color;
-}
-
-window.focus();
\ No newline at end of file
--- a/includes/clientside/tinymce/themes/advanced/jscripts/image.js	Fri Feb 22 12:46:51 2008 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,81 +0,0 @@
-var url = tinyMCE.getParam("external_image_list_url");
-if (url != null) {
-	// Fix relative
-	if (url.charAt(0) != '/' && url.indexOf('://') == -1)
-		url = tinyMCE.documentBasePath + "/" + url;
-
-	document.write('<sc'+'ript language="javascript" type="text/javascript" src="' + url + '"></sc'+'ript>');
-}
-
-function insertImage() {
-	var src = document.forms[0].src.value;
-	var alt = document.forms[0].alt.value;
-	var border = document.forms[0].border.value;
-	var vspace = document.forms[0].vspace.value;
-	var hspace = document.forms[0].hspace.value;
-	var width = document.forms[0].width.value;
-	var height = document.forms[0].height.value;
-	var align = document.forms[0].align.options[document.forms[0].align.selectedIndex].value;
-
-	tinyMCEPopup.restoreSelection();
-	tinyMCE.themes['advanced']._insertImage(src, alt, border, hspace, vspace, width, height, align);
-	tinyMCEPopup.close();
-}
-
-function init() {
-	tinyMCEPopup.resizeToInnerSize();
-
-	document.getElementById('srcbrowsercontainer').innerHTML = getBrowserHTML('srcbrowser','src','image','theme_advanced_image');
-
-	var formObj = document.forms[0];
-
-	for (var i=0; i<document.forms[0].align.options.length; i++) {
-		if (document.forms[0].align.options[i].value == tinyMCE.getWindowArg('align'))
-			document.forms[0].align.options.selectedIndex = i;
-	}
-
-	formObj.src.value = tinyMCE.getWindowArg('src');
-	formObj.alt.value = tinyMCE.getWindowArg('alt');
-	formObj.border.value = tinyMCE.getWindowArg('border');
-	formObj.vspace.value = tinyMCE.getWindowArg('vspace');
-	formObj.hspace.value = tinyMCE.getWindowArg('hspace');
-	formObj.width.value = tinyMCE.getWindowArg('width');
-	formObj.height.value = tinyMCE.getWindowArg('height');
-	formObj.insert.value = tinyMCE.getLang('lang_' + tinyMCE.getWindowArg('action'), 'Insert', true); 
-
-	// Handle file browser
-	if (isVisible('srcbrowser'))
-		document.getElementById('src').style.width = '180px';
-
-	// Auto select image in list
-	if (typeof(tinyMCEImageList) != "undefined" && tinyMCEImageList.length > 0) {
-		for (var i=0; i<formObj.image_list.length; i++) {
-			if (formObj.image_list.options[i].value == tinyMCE.getWindowArg('src'))
-				formObj.image_list.options[i].selected = true;
-		}
-	}
-}
-
-var preloadImg = new Image();
-
-function resetImageData() {
-	var formObj = document.forms[0];
-	formObj.width.value = formObj.height.value = "";	
-}
-
-function updateImageData() {
-	var formObj = document.forms[0];
-
-	if (formObj.width.value == "")
-		formObj.width.value = preloadImg.width;
-
-	if (formObj.height.value == "")
-		formObj.height.value = preloadImg.height;
-}
-
-function getImageData() {
-	preloadImg = new Image();
-	tinyMCE.addEvent(preloadImg, "load", updateImageData);
-	tinyMCE.addEvent(preloadImg, "error", function () {var formObj = document.forms[0];formObj.width.value = formObj.height.value = "";});
-	preloadImg.src = tinyMCE.convertRelativeToAbsoluteURL(tinyMCE.settings['base_href'], document.forms[0].src.value);
-}
--- a/includes/clientside/tinymce/themes/advanced/jscripts/link.js	Fri Feb 22 12:46:51 2008 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,66 +0,0 @@
-var url = tinyMCE.getParam("external_link_list_url");
-if (url != null) {
-	// Fix relative
-	if (url.charAt(0) != '/' && url.indexOf('://') == -1)
-		url = tinyMCE.documentBasePath + "/" + url;
-
-	document.write('<sc'+'ript language="javascript" type="text/javascript" src="' + url + '"></sc'+'ript>');
-}
-
-function init() {
-	tinyMCEPopup.resizeToInnerSize();
-
-	document.getElementById('hrefbrowsercontainer').innerHTML = getBrowserHTML('hrefbrowser','href','file','theme_advanced_link');
-
-	// Handle file browser
-	if (isVisible('hrefbrowser'))
-		document.getElementById('href').style.width = '180px';
-
-	var formObj = document.forms[0];
-
-	for (var i=0; i<document.forms[0].target.options.length; i++) {
-		var option = document.forms[0].target.options[i];
-
-		if (option.value == tinyMCE.getWindowArg('target'))
-			option.selected = true;
-	}
-
-	document.forms[0].href.value = tinyMCE.getWindowArg('href');
-	document.forms[0].linktitle.value = tinyMCE.getWindowArg('title');
-	document.forms[0].insert.value = tinyMCE.getLang('lang_' + tinyMCE.getWindowArg('action'), 'Insert', true); 
-
-	addClassesToList('styleSelect', 'theme_advanced_link_styles');
-	selectByValue(formObj, 'styleSelect', tinyMCE.getWindowArg('className'), true);
-
-	// Hide css select row if no CSS classes
-	if (formObj.styleSelect && formObj.styleSelect.options.length <= 1) {
-		var sr = document.getElementById('styleSelectRow');
-		sr.style.display = 'none';
-		sr.parentNode.removeChild(sr);
-	}
-
-	// Auto select link in list
-	if (typeof(tinyMCELinkList) != "undefined" && tinyMCELinkList.length > 0) {
-		var formObj = document.forms[0];
-
-		for (var i=0; i<formObj.link_list.length; i++) {
-			if (formObj.link_list.options[i].value == tinyMCE.getWindowArg('href'))
-				formObj.link_list.options[i].selected = true;
-		}
-	}
-}
-
-function insertLink() {
-	var href = document.forms[0].href.value;
-	var target = document.forms[0].target.options[document.forms[0].target.selectedIndex].value;
-	var title = document.forms[0].linktitle.value;
-	var style_class = document.forms[0].styleSelect ? document.forms[0].styleSelect.value : "";
-	var dummy;
-
-	if (target == '_self')
-		target = '';
-
-	tinyMCEPopup.restoreSelection();
-	tinyMCE.themes['advanced']._insertLink(href, target, title, dummy, style_class);
-	tinyMCEPopup.close();
-}
--- a/includes/clientside/tinymce/themes/advanced/jscripts/source_editor.js	Fri Feb 22 12:46:51 2008 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,59 +0,0 @@
-function saveContent() {
-	tinyMCE.setContent(document.getElementById('htmlSource').value);
-	tinyMCE.closeWindow(window);
-}
-
-function onLoadInit() {
-	tinyMCEPopup.resizeToInnerSize();
-
-	// Remove Gecko spellchecking
-	if (tinyMCE.isGecko)
-		document.body.spellcheck = tinyMCE.getParam("gecko_spellcheck");
-
-	document.getElementById('htmlSource').value = tinyMCE.getContent(tinyMCE.getWindowArg('editor_id'));
-
-	resizeInputs();
-
-	if (tinyMCE.getParam("theme_advanced_source_editor_wrap", true)) {
-		setWrap('soft');
-		document.getElementById('wraped').checked = true;
-	}
-}
-
-function setWrap(val) {
-	var s = document.getElementById('htmlSource');
-
-	s.wrap = val;
-
-	if (tinyMCE.isGecko || tinyMCE.isOpera) {
-		var v = s.value;
-		var n = s.cloneNode(false);
-		n.setAttribute("wrap", val);
-		s.parentNode.replaceChild(n, s);
-		n.value = v;
-	}
-}
-
-function toggleWordWrap(elm) {
-	if (elm.checked)
-		setWrap('soft');
-	else
-		setWrap('off');
-}
-
-var wHeight=0, wWidth=0, owHeight=0, owWidth=0;
-
-function resizeInputs() {
-	var el = document.getElementById('htmlSource');
-
-	if (!tinyMCE.isMSIE) {
-		 wHeight = self.innerHeight - 60;
-		 wWidth = self.innerWidth - 16;
-	} else {
-		 wHeight = document.body.clientHeight - 60;
-		 wWidth = document.body.clientWidth - 16;
-	}
-
-	el.style.height = Math.abs(wHeight) + 'px';
-	el.style.width  = Math.abs(wWidth) + 'px';
-}
--- a/includes/clientside/tinymce/themes/advanced/langs/en.js	Fri Feb 22 12:46:51 2008 -0500
+++ b/includes/clientside/tinymce/themes/advanced/langs/en.js	Fri Feb 22 12:51:53 2008 -0500
@@ -1,91 +1,62 @@
-// UK lang variables
-
-tinyMCE.addToLang('',{
-theme_style_select : '-- Styles --',
-theme_code_desc : 'Edit HTML Source',
-theme_code_title : 'HTML Source Editor',
-theme_code_wordwrap : 'Word wrap',
-theme_sub_desc : 'Subscript',
-theme_sup_desc : 'Superscript',
-theme_hr_desc : 'Insert horizontal ruler',
-theme_removeformat_desc : 'Remove formatting',
-theme_custom1_desc : 'Your custom description here',
-insert_image_border : 'Border',
-insert_image_dimensions : 'Dimensions',
-insert_image_vspace : 'Vertical space',
-insert_image_hspace : 'Horizontal space',
-insert_image_align : 'Alignment',
-insert_image_align_default : '-- Not set --',
-insert_image_align_baseline : 'Baseline',
-insert_image_align_top : 'Top',
-insert_image_align_middle : 'Middle',
-insert_image_align_bottom : 'Bottom',
-insert_image_align_texttop : 'TextTop',
-insert_image_align_absmiddle : 'Absolute Middle',
-insert_image_align_absbottom : 'Absolute Bottom',
-insert_image_align_left : 'Left',
-insert_image_align_right : 'Right',
-theme_font_size : '-- Font size --',
-theme_fontdefault : '-- Font family --',
-theme_block : '-- Format --',
-theme_paragraph : 'Paragraph',
-theme_div : 'Div',
-theme_address : 'Address',
-theme_pre : 'Preformatted',
-theme_h1 : 'Heading 1',
-theme_h2 : 'Heading 2',
-theme_h3 : 'Heading 3',
-theme_h4 : 'Heading 4',
-theme_h5 : 'Heading 5',
-theme_h6 : 'Heading 6',
-theme_blockquote : 'Blockquote',
-theme_code : 'Code',
-theme_samp : 'Code sample',
-theme_dt : 'Definition term ',
-theme_dd : 'Definition description',
-theme_colorpicker_title : 'Select a color',
-theme_colorpicker_apply : 'Apply',
-theme_forecolor_desc : 'Select text color',
-theme_backcolor_desc : 'Select background color',
-theme_charmap_title : 'Select custom character',
-theme_charmap_desc : 'Insert custom character',
-theme_visualaid_desc : 'Toggle guidelines/invisible elements',
-insert_anchor_title : 'Insert/edit anchor',
-insert_anchor_name : 'Anchor name',
-theme_anchor_desc : 'Insert/edit anchor',
-theme_insert_link_titlefield : 'Title',
-theme_clipboard_msg : 'Copy/Cut/Paste is not available in Mozilla and Firefox.\nDo you want more information about this issue?',
-theme_path : 'Path',
-cut_desc : 'Cut',
-copy_desc : 'Copy',
-paste_desc : 'Paste',
-link_list : 'Link list',
-image_list : 'Image list',
-browse : 'Browse',
-image_props_desc : 'Image properties',
-newdocument_desc : 'New document',
-class_name : 'Class',
-newdocument : 'Are you sure you want clear all contents?',
-about_title : 'About TinyMCE',
-about : 'About',
-license : 'License',
-plugins : 'Plugins',
-plugin : 'Plugin',
-author : 'Author',
-version : 'Version',
-loaded_plugins : 'Loaded plugins',
-help : 'Help',
-not_set : '-- Not set --',
-close : 'Close',
-toolbar_focus : 'Jump to tool buttons - Alt+Q, Jump to editor - Alt-Z, Jump to element path - Alt-X',
-invalid_data : 'Error: Invalid values entered, these are marked in red.',
-more_colors : 'More colors',
-color_picker_tab : 'Picker',
-color_picker : 'Color picker',
-web_colors_tab : 'Web safe',
-web_colors : 'Web safe colors',
-named_colors_tab : 'Named',
-named_colors : 'Named colors',
-color : 'Color:',
-color_name : 'Name:'
-});
+tinyMCE.addI18n('en.advanced',{
+style_select:"Styles",
+font_size:"Font size",
+fontdefault:"Font family",
+block:"Format",
+paragraph:"Paragraph",
+div:"Div",
+address:"Address",
+pre:"Preformatted",
+h1:"Heading 1",
+h2:"Heading 2",
+h3:"Heading 3",
+h4:"Heading 4",
+h5:"Heading 5",
+h6:"Heading 6",
+blockquote:"Blockquote",
+code:"Code",
+samp:"Code sample",
+dt:"Definition term ",
+dd:"Definition description",
+bold_desc:"Bold (Ctrl+B)",
+italic_desc:"Italic (Ctrl+I)",
+underline_desc:"Underline (Ctrl+U)",
+striketrough_desc:"Strikethrough",
+justifyleft_desc:"Align left",
+justifycenter_desc:"Align center",
+justifyright_desc:"Align right",
+justifyfull_desc:"Align full",
+bullist_desc:"Unordered list",
+numlist_desc:"Ordered list",
+outdent_desc:"Outdent",
+indent_desc:"Indent",
+undo_desc:"Undo (Ctrl+Z)",
+redo_desc:"Redo (Ctrl+Y)",
+link_desc:"Insert/edit link",
+unlink_desc:"Unlink",
+image_desc:"Insert/edit image",
+cleanup_desc:"Cleanup messy code",
+code_desc:"Edit HTML Source",
+sub_desc:"Subscript",
+sup_desc:"Superscript",
+hr_desc:"Insert horizontal ruler",
+removeformat_desc:"Remove formatting",
+custom1_desc:"Your custom description here",
+forecolor_desc:"Select text color",
+backcolor_desc:"Select background color",
+charmap_desc:"Insert custom character",
+visualaid_desc:"Toggle guidelines/invisible elements",
+anchor_desc:"Insert/edit anchor",
+cut_desc:"Cut",
+copy_desc:"Copy",
+paste_desc:"Paste",
+image_props_desc:"Image properties",
+newdocument_desc:"New document",
+help_desc:"Help",
+blockquote_desc:"Blockquote",
+clipboard_msg:"Copy/Cut/Paste is not available in Mozilla and Firefox.\r\nDo you want more information about this issue?",
+path:"Path",
+newdocument:"Are you sure you want clear all contents?",
+toolbar_focus:"Jump to tool buttons - Alt+Q, Jump to editor - Alt-Z, Jump to element path - Alt-X",
+more_colors:"More colors"
+});
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/includes/clientside/tinymce/themes/advanced/langs/en_dlg.js	Fri Feb 22 12:51:53 2008 -0500
@@ -0,0 +1,51 @@
+tinyMCE.addI18n('en.advanced_dlg',{
+about_title:"About TinyMCE",
+about_general:"About",
+about_help:"Help",
+about_license:"License",
+about_plugins:"Plugins",
+about_plugin:"Plugin",
+about_author:"Author",
+about_version:"Version",
+about_loaded:"Loaded plugins",
+anchor_title:"Insert/edit anchor",
+anchor_name:"Anchor name",
+code_title:"HTML Source Editor",
+code_wordwrap:"Word wrap",
+colorpicker_title:"Select a color",
+colorpicker_picker_tab:"Picker",
+colorpicker_picker_title:"Color picker",
+colorpicker_palette_tab:"Palette",
+colorpicker_palette_title:"Palette colors",
+colorpicker_named_tab:"Named",
+colorpicker_named_title:"Named colors",
+colorpicker_color:"Color:",
+colorpicker_name:"Name:",
+charmap_title:"Select custom character",
+image_title:"Insert/edit image",
+image_src:"Image URL",
+image_alt:"Image description",
+image_list:"Image list",
+image_border:"Border",
+image_dimensions:"Dimensions",
+image_vspace:"Vertical space",
+image_hspace:"Horizontal space",
+image_align:"Alignment",
+image_align_baseline:"Baseline",
+image_align_top:"Top",
+image_align_middle:"Middle",
+image_align_bottom:"Bottom",
+image_align_texttop:"Text top",
+image_align_textbottom:"Text bottom",
+image_align_left:"Left",
+image_align_right:"Right",
+link_title:"Insert/edit link",
+link_url:"Link URL",
+link_target:"Target",
+link_target_same:"Open link in the same window",
+link_target_blank:"Open link in a new window",
+link_titlefield:"Title",
+link_is_email:"The URL you entered seems to be an email address, do you want to add the required mailto: prefix?",
+link_is_external:"The URL you entered seems to external link, do you want to add the required http:// prefix?",
+link_list:"Link list"
+});
\ No newline at end of file
--- a/includes/clientside/tinymce/themes/advanced/link.htm	Fri Feb 22 12:46:51 2008 -0500
+++ b/includes/clientside/tinymce/themes/advanced/link.htm	Fri Feb 22 12:51:53 2008 -0500
@@ -1,17 +1,19 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
 <html xmlns="http://www.w3.org/1999/xhtml">
 <head>
-	<title>{$lang_insert_link_title}</title>
-	<script language="javascript" type="text/javascript" src="../../tiny_mce_popup.js"></script>
-	<script language="javascript" type="text/javascript" src="../../utils/mctabs.js"></script>
-	<script language="javascript" type="text/javascript" src="../../utils/form_utils.js"></script>
-	<script language="javascript" type="text/javascript" src="jscripts/link.js"></script>
+	<title>{#advanced_dlg.link_title}</title>
+	<script type="text/javascript" src="../../tiny_mce_popup.js"></script>
+	<script type="text/javascript" src="../../utils/mctabs.js"></script>
+	<script type="text/javascript" src="../../utils/form_utils.js"></script>
+	<script type="text/javascript" src="../../utils/validate.js"></script>
+	<script type="text/javascript" src="js/link.js"></script>
 	<base target="_self" />
 </head>
-<body id="link" onload="tinyMCEPopup.executeOnLoad('init();');" style="display: none">
-<form onsubmit="insertLink();return false;" action="#">
+<body id="link" style="display: none">
+<form onsubmit="LinkDialog.update();return false;" action="#">
 	<div class="tabs">
 		<ul>
-			<li id="general_tab" class="current"><span><a href="javascript:mcTabs.displayTab('general_tab','general_panel');" onmousedown="return false;">{$lang_insert_link_title}</a></span></li>
+			<li id="general_tab" class="current"><span><a href="javascript:mcTabs.displayTab('general_tab','general_panel');" onmousedown="return false;">{#advanced_dlg.link_title}</a></span></li>
 		</ul>
 	</div>
 
@@ -20,79 +22,41 @@
 
 		<table border="0" cellpadding="4" cellspacing="0">
           <tr>
-            <td nowrap="nowrap"><label for="href">{$lang_insert_link_url}</label></td>
+            <td nowrap="nowrap"><label for="href">{#advanced_dlg.link_url}</label></td>
             <td><table border="0" cellspacing="0" cellpadding="0"> 
 				  <tr> 
-					<td><input id="href" name="href" type="text" value="" style="width: 200px" /></td> 
+					<td><input id="href" name="href" type="text" value="" style="width: 200px" onchange="LinkDialog.checkPrefix(this);" /></td> 
 					<td id="hrefbrowsercontainer">&nbsp;</td>
 				  </tr> 
 				</table></td>
           </tr>
-		  <!-- Link list -->
-		  <script language="javascript">
-			if (typeof(tinyMCELinkList) != "undefined" && tinyMCELinkList.length > 0) {
-				var html = "";
-
-				html += '<tr><td><label for="link_list">{$lang_link_list}</label></td>';
-				html += '<td><select id="link_list" name="link_list" style="width: 200px" onchange="this.form.href.value=this.options[this.selectedIndex].value;">';
-				html += '<option value="">---</option>';
-
-				for (var i=0; i<tinyMCELinkList.length; i++)
-					html += '<option value="' + tinyMCELinkList[i][1] + '">' + tinyMCELinkList[i][0] + '</option>';
-
-				html += '</select></td></tr>';
-
-				document.write(html);
-			}
-		  </script>
-		  <!-- /Link list -->
+		  <tr>
+			<td><label for="link_list">{#advanced_dlg.link_list}</label></td>
+			<td><select id="link_list" name="link_list" onchange="document.getElementById('href').value=this.options[this.selectedIndex].value;"></select></td>
+		  </tr>
+		<tr>
+			<td><label id="targetlistlabel" for="targetlist">{#advanced_dlg.link_target}</label></td>
+			<td><select id="target_list" name="target_list"></select></td>
+		</tr>
           <tr>
-            <td nowrap="nowrap"><label for="target">{$lang_insert_link_target}</label></td>
-            <td><select id="target" name="target" style="width: 200px">
-                <option value="_self">{$lang_insert_link_target_same}</option>
-                <option value="_blank">{$lang_insert_link_target_blank}</option>
-				<script language="javascript">
-					var html = "";
-					var targets = tinyMCE.getParam('theme_advanced_link_targets', '').split(';');
-
-					for (var i=0; i<targets.length; i++) {
-						var key, value;
-
-						if (targets[i] == "")
-							continue;
-
-						key = targets[i].split('=')[0];
-						value = targets[i].split('=')[1];
-
-						html += '<option value="' + value + '">' + key + '</option>';
-					}
-
-					document.write(html);
-				</script>
-            </select></td>
+            <td nowrap="nowrap"><label for="linktitle">{#advanced_dlg.link_titlefield}</label></td>
+            <td><input id="linktitle" name="linktitle" type="text" value="" style="width: 200px" /></td>
           </tr>
-          <tr>
-            <td nowrap="nowrap"><label for="linktitle">{$lang_theme_insert_link_titlefield}</label></td>
-            <td><input id="linktitle" name="linktitle" type="text" value="" style="width: 200px"></td>
-          </tr>
-          <tr id="styleSelectRow">
-            <td><label for="styleSelect">{$lang_class_name}</label></td>
-            <td>
-			 <select id="styleSelect" name="styleSelect">
-                <option value="" selected>{$lang_theme_style_select}</option>
-             </select></td>
-          </tr>
+			<tr>
+				<td><label for="class_list">{#class_name}</label></td>
+				<td><select id="class_list" name="class_list"></select></td>
+			</tr>
         </table>
 		</div>
 	</div>
 
 	<div class="mceActionPanel">
 		<div style="float: left">
-			<input type="button" id="insert" name="insert" value="{$lang_insert}" onclick="insertLink();" />
+			<input type="button" id="insert" name="insert" value="{#insert}" onclick="LinkDialog.update();" />
 		</div>
 
 		<div style="float: right">
-			<input type="button" id="cancel" name="cancel" value="{$lang_cancel}" onclick="tinyMCEPopup.close();" />
+			<input type="button" id="cancel" name="cancel" value="{#cancel}" onclick="tinyMCEPopup.close();" />
 		</div>
 	</div>
 </form>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/includes/clientside/tinymce/themes/advanced/skins/default/content.css	Fri Feb 22 12:51:53 2008 -0500
@@ -0,0 +1,18 @@
+body, td, pre {font-family:Verdana, Arial, Helvetica, sans-serif; font-size:10px; margin:8px; }
+body {background:#FFF;}
+.mceItemTable, .mceItemTable td, .mceItemTable th, .mceItemTable caption, .mceVisualAid {border: 1px dashed #BBB;}
+a.mceItemAnchor {width:12px; line-height:6px; overflow:hidden; padding-left:12px; background:url(img/items.gif) no-repeat bottom left;}
+img.mceItemAnchor {width:12px; height:12px; background:url(img/items.gif) no-repeat;}
+img {border:0;}
+
+/* IE */
+* html body {
+scrollbar-3dlight-color:#F0F0EE;
+scrollbar-arrow-color:#676662;
+scrollbar-base-color:#F0F0EE;
+scrollbar-darkshadow-color:#DDD;
+scrollbar-face-color:#E0E0DD;
+scrollbar-highlight-color:#F0F0EE;
+scrollbar-shadow-color:#F0F0EE;
+scrollbar-track-color:#F5F5F5;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/includes/clientside/tinymce/themes/advanced/skins/default/dialog.css	Fri Feb 22 12:51:53 2008 -0500
@@ -0,0 +1,111 @@
+/* Generic */
+body {
+font-family:Verdana, Arial, Helvetica, sans-serif; font-size:11px;
+scrollbar-3dlight-color:#F0F0EE;
+scrollbar-arrow-color:#676662;
+scrollbar-base-color:#F0F0EE;
+scrollbar-darkshadow-color:#DDDDDD;
+scrollbar-face-color:#E0E0DD;
+scrollbar-highlight-color:#F0F0EE;
+scrollbar-shadow-color:#F0F0EE;
+scrollbar-track-color:#F5F5F5;
+background:#F0F0EE;
+padding:0;
+margin:8px 8px 0 8px;
+}
+
+html {background:#F0F0EE;}
+td {font-family:Verdana, Arial, Helvetica, sans-serif; font-size:10px;}
+textarea {resize:none;outline:none;}
+a:link, a:visited {color:black;}
+a:hover {color:#2B6FB6;}
+
+/* Forms */
+fieldset {margin:0; padding:4px; border:1px solid #919B9C; font-family:Verdana, Arial; font-size:10px;}
+legend {color:#2B6FB6; font-weight:bold;}
+label.msg {display:none;}
+label.invalid {color:#EE0000; display:inline;}
+input.invalid {border:1px solid #EE0000;}
+input {background:#FFF; border:1px solid #CCC;}
+input, select, textarea {font-family:Verdana, Arial, Helvetica, sans-serif; font-size:10px;}
+input, select, textarea {border:1px solid #808080;}
+input.radio {border:1px none #000000; background:transparent; vertical-align:middle;}
+input.checkbox {border:1px none #000000; background:transparent; vertical-align:middle;}
+.input_noborder {border:0;}
+
+/* Buttons */
+#insert, #cancel, input.button, .updateButton {
+border:0; margin:0; padding:0;
+font-weight:bold;
+width:94px; height:26px;
+background:url(img/buttons.png) 0 -26px;
+cursor:pointer;
+padding-bottom:2px;
+}
+
+#insert {background:url(img/buttons.png) 0 -52px;}
+#cancel {background:url(img/buttons.png) 0 0;}
+
+/* Browse */
+a.browse span {display:block; width:20px; height:18px; background:url(../../img/icons.gif) -860px 0; border:1px solid #FFF; margin-left:1px;}
+.mceOldBoxModel a.browse span {width:22px; height:20px;}
+a.browse:hover span {border:1px solid #0A246A; background-color:#B2BBD0;}
+a.browse span.disabled {border:1px solid white; -moz-opacity:0.3; opacity:0.3; filter:progid:DXImageTransform.Microsoft.Alpha(opacity=30);}
+a.browse:hover span.disabled {border:1px solid white; background-color:transparent;}
+a.pickcolor span {display:block; width:20px; height:16px; background:url(../../img/icons.gif) -840px 0; margin-left:2px;}
+.mceOldBoxModel a.pickcolor span {width:21px; height:17px;}
+a.pickcolor:hover span {background-color:#B2BBD0;}
+a.pickcolor:hover span.disabled {}
+
+/* Charmap */
+table.charmap {border-style:solid; border-width:1px; border-color:#AAA;}
+td.charmap, td.charmapOver {color:#000; border-color:#AAA; border-style:solid; border-width:1px; text-align:center; font-size:12px;}
+td.charmapOver {background:#CCC; cursor:default;}
+a.charmap {color:#000; text-decoration:none}
+
+/* Source */
+.wordWrapCode {vertical-align:middle; border:1px none #000000; background:transparent;}
+.mceActionPanel {margin-top:5px;}
+
+/* Tabs classes */
+.tabs {width:100%; height:18px; line-height:normal; background:url(img/tabs.gif) repeat-x 0 -72px;}
+.tabs ul {margin:0; padding:0; list-style:none;}
+.tabs li {float:left; background:url(img/tabs.gif) no-repeat 0 0; margin:0 2px 0 0; padding:0 0 0 10px; line-height:18px;}
+.tabs li.current {background:url(img/tabs.gif) no-repeat 0 -18px; margin-right:2px;}
+.tabs span {float:left; display:block; background:url(img/tabs.gif) no-repeat right -36px; padding:0px 10px 0 0;}
+.tabs .current span {background:url(img/tabs.gif) no-repeat right -54px;}
+.tabs a {text-decoration:none; font-family:Verdana, Arial; font-size:10px;}
+.tabs a:link, .tabs a:visited, .tabs a:hover {color:black;}
+
+/* Panels */
+.panel_wrapper div.panel {display:none;}
+.panel_wrapper div.current {display:block; width:100%; height:300px; overflow:visible;}
+.panel_wrapper {border:1px solid #919B9C; border-top:0px; padding:10px; padding-top:5px; clear:both; background:white;}
+
+/* Columns */
+.column {float:left;}
+.properties {width:100%;}
+.properties .column1 {}
+.properties .column2 {text-align:left;}
+
+/* Titles */
+h1, h2, h3, h4 {color:#2B6FB6; margin:0; padding:0; padding-top:5px;}
+h3 {font-size:14px;}
+.title {font-size:12px; font-weight:bold; color:#2B6FB6;}
+
+/* Dialog specific */
+#link .panel_wrapper, #link div.current {height:125px;}
+#image .panel_wrapper, #image div.current {height:200px;}
+#plugintable thead {font-weight:bold; background:#DDD;}
+#plugintable, #about #plugintable td {border:1px solid #919B9C;}
+#plugintable {width:96%; margin-top:10px;}
+#pluginscontainer {height:290px; overflow:auto;}
+#colorpicker #preview {float:right; width:50px; height:14px;line-height:1px; border:1px solid black; margin-left:5px;}
+#colorpicker #colors {float:left; border:1px solid gray; cursor:crosshair;}
+#colorpicker #light {border:1px solid gray; margin-left:5px; float:left;width:15px; height:150px; cursor:crosshair;}
+#colorpicker #light div {overflow:hidden;}
+#colorpicker #previewblock {float:right; padding-left:10px; height:20px;}
+#colorpicker .panel_wrapper div.current {height:175px;}
+#colorpicker #namedcolors {width:150px;}
+#colorpicker #namedcolors a {display:block; float:left; width:10px; height:10px; margin:1px 1px 0 0; overflow:hidden;}
+#colorpicker #colornamecontainer {margin-top:5px;}
Binary file includes/clientside/tinymce/themes/advanced/skins/default/img/buttons.png has changed
Binary file includes/clientside/tinymce/themes/advanced/skins/default/img/items.gif has changed
Binary file includes/clientside/tinymce/themes/advanced/skins/default/img/menu_arrow.gif has changed
Binary file includes/clientside/tinymce/themes/advanced/skins/default/img/menu_check.gif has changed
Binary file includes/clientside/tinymce/themes/advanced/skins/default/img/progress.gif has changed
Binary file includes/clientside/tinymce/themes/advanced/skins/default/img/tabs.gif has changed
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/includes/clientside/tinymce/themes/advanced/skins/default/ui.css	Fri Feb 22 12:51:53 2008 -0500
@@ -0,0 +1,193 @@
+/* Reset */
+.defaultSkin table, .defaultSkin tbody, .defaultSkin a, .defaultSkin img, .defaultSkin tr, .defaultSkin div, .defaultSkin td, .defaultSkin iframe, .defaultSkin span, .defaultSkin *, .defaultSkin .text {border:0; margin:0; padding:0; background:transparent; white-space:nowrap; text-decoration:none; font-weight:normal; cursor:default; color:#000; vertical-align:baseline; width:auto; border-collapse:separate}
+.defaultSkin a:hover, .defaultSkin a:link, .defaultSkin a:visited, .defaultSkin a:active {text-decoration:none; font-weight:normal; cursor:default; color:#000}
+.defaultSkin table td {vertical-align:middle}
+
+/* Containers */
+.defaultSkin table {background:#F0F0EE}
+.defaultSkin iframe {display:block; background:#FFF}
+.defaultSkin .mceToolbar {height:26px}
+.defaultSkin .left {text-align:left}
+.defaultSkin .right {text-align:right}
+
+/* External */
+.defaultSkin .mceExternalToolbar {position:absolute; border:1px solid #CCC; border-bottom:0; display:none;}
+.defaultSkin .mceExternalToolbar td.mceToolbar {padding-right:13px;}
+.defaultSkin .mceExternalClose {position:absolute; top:3px; right:3px; width:7px; height:7px; background:url(../../img/icons.gif) -820px 0}
+
+/* Layout */
+.defaultSkin table.mceLayout {border:0; border-left:1px solid #CCC; border-right:1px solid #CCC}
+.defaultSkin table.mceLayout tr.first td {border-top:1px solid #CCC}
+.defaultSkin table.mceLayout tr.last td {border-bottom:1px solid #CCC}
+.defaultSkin table.mceToolbar, .defaultSkin tr.first .mceToolbar tr td, .defaultSkin tr.last .mceToolbar tr td {border:0; margin:0; padding:0;}
+.defaultSkin td.mceToolbar {padding-top:1px; vertical-align:top}
+.defaultSkin .mceIframeContainer {border-top:1px solid #CCC; border-bottom:1px solid #CCC}
+.defaultSkin .mceStatusbar {position:relative; font-family:'MS Sans Serif',sans-serif,Verdana,Arial; font-size:9pt; line-height:16px; overflow:visible; padding:2px; color:#000; display:block}
+.defaultSkin .mceStatusbar a.resize {display:block; position:absolute; top:0; right:0; background:url(../../img/icons.gif) -800px 0; width:20px; height:20px; cursor:se-resize}
+.defaultSkin .mceStatusbar a:hover {text-decoration:underline}
+.defaultSkin table.mceToolbar {margin-left:3px}
+.defaultSkin span.icon, .defaultSkin img.icon {display:block; width:20px; height:20px}
+.defaultSkin .icon {background:url(../../img/icons.gif) no-repeat 20px 20px}
+
+/* Button */
+.defaultSkin .mceButton {display:block; border:1px solid #F0F0EE; width:20px; height:20px; margin-right:1px;}
+.defaultSkin a.mceButtonEnabled:hover {border:1px solid #0A246A; background-color:#B2BBD0}
+.defaultSkin a.mceButtonActive, .defaultSkin a.mceButtonSelected {border:1px solid #0A246A; background-color:#C2CBE0}
+.defaultSkin .mceButtonDisabled .icon {opacity:0.3; filter:alpha(opacity=30)}
+
+/* Separator */
+.defaultSkin .mceSeparator {display:block; background:url(../../img/icons.gif) -180px 0; width:2px; height:20px; margin:2px 2px 0 4px}
+
+/* ListBox */
+.defaultSkin .mceListBox, .defaultSkin .mceListBox a {display:block}
+.defaultSkin .mceListBox .text {padding-left:4px; width:70px; text-align:left; border:1px solid #CCC; border-right:0; background:#FFF; font-family:Tahoma,Verdana,Arial,Helvetica; font-size:11px; height:20px; line-height:20px; overflow:hidden}
+.defaultSkin .mceListBox .open {width:9px; height:20px; background:url(../../img/icons.gif) -741px 0; margin-right:2px; border:1px solid #CCC;}
+.defaultSkin table.mceListBoxEnabled:hover .text, .defaultSkin .mceListBoxHover .text, .defaultSkin .mceListBoxSelected .text {border:1px solid #A2ABC0; border-right:0; background:#FFF}
+.defaultSkin table.mceListBoxEnabled:hover .open, .defaultSkin .mceListBoxHover .open, .defaultSkin .mceListBoxSelected .open {background-color:#FFF; border:1px solid #A2ABC0}
+.defaultSkin .mceListBoxDisabled a.text {color:gray; background-color:transparent;}
+.defaultSkin .mceListBoxMenu {overflow:auto; overflow-x:hidden}
+.defaultSkin .mceOldBoxModel .mceListBox .text {height:22px}
+.defaultSkin .mceOldBoxModel .mceListBox .open {width:11px; height:22px;}
+.defaultSkin select.mceNativeListBox {font-family:'MS Sans Serif',sans-serif,Verdana,Arial; font-size:7pt; background:#F0F0EE; border:1px solid gray; margin-right:2px;}
+
+/* SplitButton */
+.defaultSkin .mceSplitButton {width:32px; height:20px}
+.defaultSkin .mceSplitButton a, .defaultSkin .mceSplitButton span {height:20px; display:block}
+.defaultSkin .mceSplitButton a.action {width:20px; border:1px solid #F0F0EE; border-right:0;}
+.defaultSkin .mceSplitButton span.action {width:20px; background:url(../../img/icons.gif) 20px 20px;}
+.defaultSkin .mceSplitButton a.open {width:9px; border:1px solid #F0F0EE;}
+.defaultSkin .mceSplitButton span.open {width:9px; background:url(../../img/icons.gif) -741px 0;}
+.defaultSkin table.mceSplitButtonEnabled:hover a.action, .defaultSkin .mceSplitButtonHover a.action, .defaultSkin .mceSplitButtonSelected a.action {border:1px solid #0A246A; border-right:0; background-color:#B2BBD0}
+.defaultSkin table.mceSplitButtonEnabled:hover a.open, .defaultSkin .mceSplitButtonHover a.open, .defaultSkin .mceSplitButtonSelected a.open {border:1px solid #0A246A;}
+.defaultSkin table.mceSplitButtonEnabled:hover span.open, .defaultSkin .mceSplitButtonHover span.open, .defaultSkin .mceSplitButtonSelected span.open {background-color:#B2BBD0}
+.defaultSkin .mceSplitButtonDisabled .action, .defaultSkin .mceSplitButtonDisabled span.open {opacity:0.3; filter:alpha(opacity=30)}
+.defaultSkin .mceSplitButtonActive a.action {border:1px solid #0A246A; background-color:#C2CBE0}
+.defaultSkin .mceSplitButtonActive a.open {border-left:0;}
+
+/* ColorSplitButton */
+.defaultSkin div.mceColorSplitMenu table {background:#FFF; border:1px solid gray}
+.defaultSkin .mceColorSplitMenu td {padding:2px}
+.defaultSkin .mceColorSplitMenu a {display:block; width:9px; height:9px; overflow:hidden; border:1px solid #808080}
+.defaultSkin .mceColorSplitMenu td.morecolors {padding:1px 3px 1px 1px}
+.defaultSkin .mceColorSplitMenu a.morecolors {width:100%; height:auto; text-align:center; font-family:Tahoma,Verdana,Arial,Helvetica; font-size:11px; line-height:20px; border:1px solid #FFF}
+.defaultSkin .mceColorSplitMenu a.morecolors:hover {border:1px solid #0A246A; background-color:#B6BDD2}
+.defaultSkin a.mceMoreColors:hover {border:1px solid #0A246A}
+.defaultSkin .mceColorPreview {position:absolute; top:15px; left:2px; width:16px; height:4px; overflow:hidden}
+
+/* Menu */
+.defaultSkin .mceMenu {position:absolute; left:0; top:0; z-index:1000; border:1px solid #D4D0C8}
+.defaultSkin .noIcons span.icon {width:0;}
+.defaultSkin .noIcons a .text {padding-left:10px}
+.defaultSkin .mceMenu table {background:#FFF}
+.defaultSkin .mceMenu a, .defaultSkin .mceMenu span, .defaultSkin .mceMenu {display:block}
+.defaultSkin .mceMenu td {height:20px}
+.defaultSkin .mceMenu a {position:relative;padding:3px 0 4px 0}
+.defaultSkin .mceMenu .text {position:relative; display:block; font-family:Tahoma,Verdana,Arial,Helvetica; color:#000; cursor:default; margin:0; padding:0 25px 0 25px; display:block}
+.defaultSkin .mceMenu span.text, .defaultSkin .mceMenu .preview {font-size:11px}
+.defaultSkin .mceMenu pre.text {font-family:Monospace}
+.defaultSkin .mceMenu .icon {position:absolute; top:0; left:0; width:22px;}
+.defaultSkin .mceMenu .mceMenuItemEnabled a:hover, .defaultSkin .mceMenu .mceMenuItemActive {background-color:#dbecf3}
+.defaultSkin td.mceMenuItemSeparator {background:#DDD; height:1px}
+.defaultSkin .mceMenuItemTitle a {border:0; background:#EEE; border-bottom:1px solid #DDD}
+.defaultSkin .mceMenuItemTitle span.text {color:#000; font-weight:bold; padding-left:4px}
+.defaultSkin .mceMenuItemDisabled .text {color:#888}
+.defaultSkin .mceMenuItemSelected .icon {background:url(img/menu_check.gif)}
+.defaultSkin .noIcons .mceMenuItemSelected a {background:url(img/menu_arrow.gif) no-repeat -6px center}
+.defaultSkin .mceMenu span.mceMenuLine {display:none}
+.defaultSkin .mceMenuItemSub a {background:url(img/menu_arrow.gif) no-repeat top right;}
+
+/* Progress,Resize */
+.defaultSkin .mceBlocker {position:absolute; left:0; top:0; z-index:1000; opacity:0.5; filter:alpha(opacity=50); background:#FFF}
+.defaultSkin .mceProgress {position:absolute; left:0; top:0; z-index:1001; background:url(img/progress.gif) no-repeat; width:32px; height:32px; margin:-16px 0 0 -16px}
+.defaultSkin .mcePlaceHolder {border:1px dotted gray}
+
+/* Theme */
+.defaultSkin span.bold {background-position:0 0}
+.defaultSkin span.italic {background-position:-60px 0}
+.defaultSkin span.underline {background-position:-140px 0}
+.defaultSkin span.strikethrough {background-position:-120px 0}
+.defaultSkin span.undo {background-position:-160px 0}
+.defaultSkin span.redo {background-position:-100px 0}
+.defaultSkin span.cleanup {background-position:-40px 0}
+.defaultSkin span.bullist {background-position:-20px 0}
+.defaultSkin span.numlist {background-position:-80px 0}
+.defaultSkin span.justifyleft {background-position:-460px 0}
+.defaultSkin span.justifyright {background-position:-480px 0}
+.defaultSkin span.justifycenter {background-position:-420px 0}
+.defaultSkin span.justifyfull {background-position:-440px 0}
+.defaultSkin span.anchor {background-position:-200px 0}
+.defaultSkin span.indent {background-position:-400px 0}
+.defaultSkin span.outdent {background-position:-540px 0}
+.defaultSkin span.link {background-position:-500px 0}
+.defaultSkin span.unlink {background-position:-640px 0}
+.defaultSkin span.sub {background-position:-600px 0}
+.defaultSkin span.sup {background-position:-620px 0}
+.defaultSkin span.removeformat {background-position:-580px 0}
+.defaultSkin span.newdocument {background-position:-520px 0}
+.defaultSkin span.image {background-position:-380px 0}
+.defaultSkin span.help {background-position:-340px 0}
+.defaultSkin span.code {background-position:-260px 0}
+.defaultSkin span.hr {background-position:-360px 0}
+.defaultSkin span.visualaid {background-position:-660px 0}
+.defaultSkin span.charmap {background-position:-240px 0}
+.defaultSkin span.paste {background-position:-560px 0}
+.defaultSkin span.copy {background-position:-700px 0}
+.defaultSkin span.cut {background-position:-680px 0}
+.defaultSkin span.blockquote {background-position:-220px 0}
+.defaultSkin .forecolor span.action {background-position:-720px 0}
+.defaultSkin .backcolor span.action {background-position:-760px 0}
+.defaultSkin .forecolorpicker {background-position:-720px 0}
+.defaultSkin .backcolorpicker {background-position:-760px 0}
+
+/* Plugins */
+.defaultSkin span.advhr {background-position:-0px -20px}
+.defaultSkin span.ltr {background-position:-20px -20px}
+.defaultSkin span.rtl {background-position:-40px -20px}
+.defaultSkin span.emotions {background-position:-60px -20px}
+.defaultSkin span.fullpage {background-position:-80px -20px}
+.defaultSkin span.fullscreen {background-position:-100px -20px}
+.defaultSkin span.iespell {background-position:-120px -20px}
+.defaultSkin span.insertdate {background-position:-140px -20px}
+.defaultSkin span.inserttime {background-position:-160px -20px}
+.defaultSkin span.absolute {background-position:-180px -20px}
+.defaultSkin span.backward {background-position:-200px -20px}
+.defaultSkin span.forward {background-position:-220px -20px}
+.defaultSkin span.insert_layer {background-position:-240px -20px}
+.defaultSkin span.insertlayer {background-position:-260px -20px}
+.defaultSkin span.movebackward {background-position:-280px -20px}
+.defaultSkin span.moveforward {background-position:-300px -20px}
+.defaultSkin span.media {background-position:-320px -20px}
+.defaultSkin span.nonbreaking {background-position:-340px -20px}
+.defaultSkin span.pastetext {background-position:-360px -20px}
+.defaultSkin span.pasteword {background-position:-380px -20px}
+.defaultSkin span.selectall {background-position:-400px -20px}
+.defaultSkin span.preview {background-position:-420px -20px}
+.defaultSkin span.print {background-position:-440px -20px}
+.defaultSkin span.cancel {background-position:-460px -20px}
+.defaultSkin span.save {background-position:-480px -20px}
+.defaultSkin span.replace {background-position:-500px -20px}
+.defaultSkin span.search {background-position:-520px -20px}
+.defaultSkin span.styleprops {background-position:-560px -20px}
+.defaultSkin span.table {background-position:-580px -20px}
+.defaultSkin span.cell_props {background-position:-600px -20px}
+.defaultSkin span.delete_table {background-position:-620px -20px}
+.defaultSkin span.delete_col {background-position:-640px -20px}
+.defaultSkin span.delete_row {background-position:-660px -20px}
+.defaultSkin span.col_after {background-position:-680px -20px}
+.defaultSkin span.col_before {background-position:-700px -20px}
+.defaultSkin span.row_after {background-position:-720px -20px}
+.defaultSkin span.row_before {background-position:-740px -20px}
+.defaultSkin span.merge_cells {background-position:-760px -20px}
+.defaultSkin span.table_props {background-position:-980px -20px}
+.defaultSkin span.row_props {background-position:-780px -20px}
+.defaultSkin span.split_cells {background-position:-800px -20px}
+.defaultSkin span.template {background-position:-820px -20px}
+.defaultSkin span.visualchars {background-position:-840px -20px}
+.defaultSkin span.abbr {background-position:-860px -20px}
+.defaultSkin span.acronym {background-position:-880px -20px}
+.defaultSkin span.attribs {background-position:-900px -20px}
+.defaultSkin span.cite {background-position:-920px -20px}
+.defaultSkin span.del {background-position:-940px -20px}
+.defaultSkin span.ins {background-position:-960px -20px}
+.defaultSkin span.pagebreak {background-position:0 -40px}
+.defaultSkin .spellchecker span.action {background-position:-540px -20px}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/includes/clientside/tinymce/themes/advanced/skins/o2k7/content.css	Fri Feb 22 12:51:53 2008 -0500
@@ -0,0 +1,18 @@
+body, td, pre {font-family:Verdana, Arial, Helvetica, sans-serif; font-size:10px; margin:8px;}
+body {background:#FFF;}
+.mceItemTable, .mceItemTable td, .mceItemTable th, .mceItemTable caption, .mceVisualAid {border: 1px dashed #BBB;}
+a.mceItemAnchor {width:12px; line-height:6px; overflow:hidden; padding-left:12px; background:url(../default/img/items.gif) no-repeat bottom left;}
+img.mceItemAnchor {width:12px; height:12px; background:url(../default/img/items.gif) no-repeat;}
+img {border:0;}
+
+/* IE */
+* html body {
+scrollbar-3dlight-color:#F0F0EE;
+scrollbar-arrow-color:#676662;
+scrollbar-base-color:#F0F0EE;
+scrollbar-darkshadow-color:#DDD;
+scrollbar-face-color:#E0E0DD;
+scrollbar-highlight-color:#F0F0EE;
+scrollbar-shadow-color:#F0F0EE;
+scrollbar-track-color:#F5F5F5;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/includes/clientside/tinymce/themes/advanced/skins/o2k7/dialog.css	Fri Feb 22 12:51:53 2008 -0500
@@ -0,0 +1,111 @@
+/* Generic */
+body {
+font-family:Verdana, Arial, Helvetica, sans-serif; font-size:11px;
+scrollbar-3dlight-color:#F0F0EE;
+scrollbar-arrow-color:#676662;
+scrollbar-base-color:#F0F0EE;
+scrollbar-darkshadow-color:#DDDDDD;
+scrollbar-face-color:#E0E0DD;
+scrollbar-highlight-color:#F0F0EE;
+scrollbar-shadow-color:#F0F0EE;
+scrollbar-track-color:#F5F5F5;
+background:#F0F0EE;
+padding:0;
+margin:8px 8px 0 8px;
+}
+
+html {background:#F0F0EE;}
+td {font-family:Verdana, Arial, Helvetica, sans-serif; font-size:10px;}
+textarea {resize:none;outline:none;}
+a:link, a:visited {color:black;}
+a:hover {color:#2B6FB6;}
+
+/* Forms */
+fieldset {margin:0; padding:4px; border:1px solid #919B9C; font-family:Verdana, Arial; font-size:10px;}
+legend {color:#2B6FB6; font-weight:bold;}
+label.msg {display:none;}
+label.invalid {color:#EE0000; display:inline;}
+input.invalid {border:1px solid #EE0000;}
+input {background:#FFF; border:1px solid #CCC;}
+input, select, textarea {font-family:Verdana, Arial, Helvetica, sans-serif; font-size:10px;}
+input, select, textarea {border:1px solid #808080;}
+input.radio {border:1px none #000000; background:transparent; vertical-align:middle;}
+input.checkbox {border:1px none #000000; background:transparent; vertical-align:middle;}
+.input_noborder {border:0;}
+
+/* Buttons */
+#insert, #cancel, input.button, .updateButton {
+border:0; margin:0; padding:0;
+font-weight:bold;
+width:94px; height:26px;
+background:url(../default/img/buttons.png) 0 -26px;
+cursor:pointer;
+padding-bottom:2px;
+}
+
+#insert {background:url(../default/img/buttons.png) 0 -52px;}
+#cancel {background:url(../default/img/buttons.png) 0 0;}
+
+/* Browse */
+a.browse span {display:block; width:20px; height:18px; background:url(../../img/icons.gif) -860px 0; border:1px solid #FFF; margin-left:1px;}
+.mceOldBoxModel a.browse span {width:22px; height:20px;}
+a.browse:hover span {border:1px solid #0A246A; background-color:#B2BBD0;}
+a.browse span.disabled {border:1px solid white; -moz-opacity:0.3; opacity:0.3; filter:progid:DXImageTransform.Microsoft.Alpha(opacity=30);}
+a.browse:hover span.disabled {border:1px solid white; background-color:transparent;}
+a.pickcolor span {display:block; width:20px; height:16px; background:url(../../img/icons.gif) -840px 0; margin-left:2px;}
+.mceOldBoxModel a.pickcolor span {width:21px; height:17px;}
+a.pickcolor:hover span {background-color:#B2BBD0;}
+a.pickcolor:hover span.disabled {}
+
+/* Charmap */
+table.charmap {border-style:solid; border-width:1px; border-color:#AAA;}
+td.charmap, td.charmapOver {color:#000; border-color:#AAA; border-style:solid; border-width:1px; text-align:center; font-size:12px;}
+td.charmapOver {background:#CCC; cursor:default;}
+a.charmap {color:#000; text-decoration:none}
+
+/* Source */
+.wordWrapCode {vertical-align:middle; border:1px none #000000; background:transparent;}
+.mceActionPanel {margin-top:5px;}
+
+/* Tabs classes */
+.tabs {width:100%; height:18px; line-height:normal; background:url(../default/img/tabs.gif) repeat-x 0 -72px;}
+.tabs ul {margin:0; padding:0; list-style:none;}
+.tabs li {float:left; background:url(../default/img/tabs.gif) no-repeat 0 0; margin:0 2px 0 0; padding:0 0 0 10px; line-height:18px;}
+.tabs li.current {background:url(../default/img/tabs.gif) no-repeat 0 -18px; margin-right:2px;}
+.tabs span {float:left; display:block; background:url(../default/img/tabs.gif) no-repeat right -36px; padding:0px 10px 0 0;}
+.tabs .current span {background:url(../default/img/tabs.gif) no-repeat right -54px;}
+.tabs a {text-decoration:none; font-family:Verdana, Arial; font-size:10px;}
+.tabs a:link, .tabs a:visited, .tabs a:hover {color:black;}
+
+/* Panels */
+.panel_wrapper div.panel {display:none;}
+.panel_wrapper div.current {display:block; width:100%; height:300px; overflow:visible;}
+.panel_wrapper {border:1px solid #919B9C; border-top:0px; padding:10px; padding-top:5px; clear:both; background:white;}
+
+/* Columns */
+.column {float:left;}
+.properties {width:100%;}
+.properties .column1 {}
+.properties .column2 {text-align:left;}
+
+/* Titles */
+h1, h2, h3, h4 {color:#2B6FB6; margin:0; padding:0; padding-top:5px;}
+h3 {font-size:14px;}
+.title {font-size:12px; font-weight:bold; color:#2B6FB6;}
+
+/* Dialog specific */
+#link .panel_wrapper, #link div.current {height:125px;}
+#image .panel_wrapper, #image div.current {height:200px;}
+#plugintable thead {font-weight:bold; background:#DDD;}
+#plugintable, #about #plugintable td {border:1px solid #919B9C;}
+#plugintable {width:96%; margin-top:10px;}
+#pluginscontainer {height:290px; overflow:auto;}
+#colorpicker #preview {float:right; width:50px; height:14px;line-height:1px; border:1px solid black; margin-left:5px;}
+#colorpicker #colors {float:left; border:1px solid gray; cursor:crosshair;}
+#colorpicker #light {border:1px solid gray; margin-left:5px; float:left;width:15px; height:150px; cursor:crosshair;}
+#colorpicker #light div {overflow:hidden;}
+#colorpicker #previewblock {float:right; padding-left:10px; height:20px;}
+#colorpicker .panel_wrapper div.current {height:175px;}
+#colorpicker #namedcolors {width:150px;}
+#colorpicker #namedcolors a {display:block; float:left; width:10px; height:10px; margin:1px 1px 0 0; overflow:hidden;}
+#colorpicker #colornamecontainer {margin-top:5px;}
Binary file includes/clientside/tinymce/themes/advanced/skins/o2k7/img/button_bg.png has changed
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/includes/clientside/tinymce/themes/advanced/skins/o2k7/ui.css	Fri Feb 22 12:51:53 2008 -0500
@@ -0,0 +1,193 @@
+/* Reset */
+.o2k7Skin table, .o2k7Skin tbody, .o2k7Skin a, .o2k7Skin img, .o2k7Skin tr, .o2k7Skin div, .o2k7Skin td, .o2k7Skin iframe, .o2k7Skin span, .o2k7Skin *, .o2k7Skin .text {border:0; margin:0; padding:0; background:transparent; white-space:nowrap; text-decoration:none; font-weight:normal; cursor:default; color:#000; vertical-align:baseline; width:auto; border-collapse:separate}
+.o2k7Skin a:hover, .o2k7Skin a:link, .o2k7Skin a:visited, .o2k7Skin a:active {text-decoration:none; font-weight:normal; cursor:default; color:#000}
+.o2k7Skin table td {vertical-align:middle}
+
+/* Containers */
+.o2k7Skin table {background:#E5EFFD}
+.o2k7Skin iframe {display:block; background:#FFF}
+.o2k7Skin .mceToolbar {height:26px}
+
+/* External */
+.o2k7Skin .mceExternalToolbar {position:absolute; border:1px solid #ABC6DD; border-bottom:0; display:none}
+.o2k7Skin .mceExternalToolbar td.mceToolbar {padding-right:13px;}
+.o2k7Skin .mceExternalClose {position:absolute; top:3px; right:3px; width:7px; height:7px; background:url(../../img/icons.gif) -820px 0}
+
+/* Layout */
+.o2k7Skin table.mceLayout {border:0; border-left:1px solid #ABC6DD; border-right:1px solid #ABC6DD}
+.o2k7Skin table.mceLayout tr.first td {border-top:1px solid #ABC6DD}
+.o2k7Skin table.mceLayout tr.last td {border-bottom:1px solid #ABC6DD}
+.o2k7Skin table.mceToolbar, .o2k7Skin tr.first .mceToolbar tr td, .o2k7Skin tr.last .mceToolbar tr td {border:0; margin:0; padding:0}
+.o2k7Skin .mceIframeContainer {border-top:1px solid #ABC6DD; border-bottom:1px solid #ABC6DD}
+.o2k7Skin .mceStatusbar {display:block; font-family:'MS Sans Serif',sans-serif,Verdana,Arial; font-size:9pt; line-height:16px; overflow:visible; color:#000; height:20px;}
+.o2k7Skin .mceStatusbar div {float:left; padding:2px;}
+.o2k7Skin .mceStatusbar a.resize {display:block; float:right; background:url(../../img/icons.gif) -800px 0; width:20px; height:20px; cursor:se-resize}
+.o2k7Skin .mceStatusbar a:hover {text-decoration:underline}
+.o2k7Skin table.mceToolbar {margin-left:3px}
+.o2k7Skin .mceToolbar .mceToolbarStart span {display:block; background:url(img/button_bg.png) -22px 0; width:1px; height:22px; }
+.o2k7Skin .mceToolbar .mceToolbarEnd span {display:block; background:url(img/button_bg.png) -22px 0; width:1px; height:22px}
+.o2k7Skin .mceToolbar .mceToolbarEndListBox span {display:none}
+.o2k7Skin span.icon, .o2k7Skin img.icon {display:block; width:20px; height:20px}
+.o2k7Skin .icon {background:url(../../img/icons.gif) no-repeat 20px 20px}
+
+/* Button */
+.o2k7Skin .mceButton {display:block; background:url(img/button_bg.png); width:22px; height:22px}
+.o2k7Skin a.mceButton span, .o2k7Skin a.mceButton img {margin-left:1px}
+.o2k7Skin .mceOldBoxModel a.mceButton span, .o2k7Skin .mceOldBoxModel a.mceButton img {margin:0 0 0 1px}
+.o2k7Skin a.mceButtonEnabled:hover {background-color:#B2BBD0; background-position:0 -22px}
+.o2k7Skin a.mceButtonActive, .o2k7Skin a.mceButtonSelected {background-position:0 -44px}
+.o2k7Skin .mceButtonDisabled .icon {opacity:0.3; filter:alpha(opacity=30)}
+
+/* Separator */
+.o2k7Skin .mceSeparator {display:block; background:url(img/button_bg.png) -22px 0; width:5px; height:22px}
+
+/* ListBox */
+.o2k7Skin .mceListBox, .o2k7Skin .mceListBox a {display:block}
+.o2k7Skin .mceListBox .text {padding-left:4px; text-align:left; width:70px; border:1px solid #b3c7e1; border-right:0; background:#eaf2fb; font-family:Tahoma,Verdana,Arial,Helvetica; font-size:11px; height:20px; line-height:20px; overflow:hidden}
+.o2k7Skin .mceListBox .open {width:14px; height:22px; background:url(img/button_bg.png) -66px 0; margin-right:2px}
+.o2k7Skin table.mceListBoxEnabled:hover .text, .o2k7Skin .mceListBoxHover .text, .o2k7Skin .mceListBoxSelected .text {background:#FFF}
+.o2k7Skin table.mceListBoxEnabled:hover .open, .o2k7Skin .mceListBoxHover .open, .o2k7Skin .mceListBoxSelected .open {background-position:-66px -22px}
+.o2k7Skin .mceListBoxDisabled .text {color:gray}
+.o2k7Skin .mceListBoxMenu {overflow:auto; overflow-x:hidden}
+.o2k7Skin .mceOldBoxModel .mceListBox .text {height:22px}
+.o2k7Skin select.mceListBox {font-family:Tahoma,Verdana,Arial,Helvetica; font-size:12px; border:1px solid #b3c7e1; background:#FFF;}
+
+/* SplitButton */
+.o2k7Skin .mceSplitButton, .o2k7Skin .mceSplitButton a, .o2k7Skin .mceSplitButton span {display:block; height:22px}
+.o2k7Skin .mceSplitButton {background:url(img/button_bg.png)}
+.o2k7Skin .mceSplitButton a.action {width:22px}
+.o2k7Skin .mceSplitButton span.action {width:22px; background:url(../../img/icons.gif) 20px 20px}
+.o2k7Skin .mceSplitButton a.open {width:10px}
+.o2k7Skin .mceSplitButton span.open {width:10px; background:url(img/button_bg.png) -44px 0}
+.o2k7Skin table.mceSplitButtonEnabled:hover a.action, .o2k7Skin .mceSplitButtonHover a.action, .o2k7Skin .mceSplitButtonSelected {background:url(img/button_bg.png) 0 -22px}
+.o2k7Skin table.mceSplitButtonEnabled:hover span.open, .o2k7Skin .mceSplitButtonHover span.open, .o2k7Skin .mceSplitButtonSelected span.open {background-position:-44px -44px}
+.o2k7Skin .mceSplitButtonDisabled .action {opacity:0.3; filter:alpha(opacity=30)}
+.o2k7Skin .mceSplitButtonActive {background-position:0 -44px}
+
+/* ColorSplitButton */
+.o2k7Skin div.mceColorSplitMenu table {background:#FFF; border:1px solid gray}
+.o2k7Skin .mceColorSplitMenu td {padding:2px}
+.o2k7Skin .mceColorSplitMenu a {display:block; width:9px; height:9px; overflow:hidden; border:1px solid #808080}
+.o2k7Skin .mceColorSplitMenu td.morecolors {padding:1px 3px 1px 1px}
+.o2k7Skin .mceColorSplitMenu a.morecolors {width:100%; height:auto; text-align:center; font-family:Tahoma,Verdana,Arial,Helvetica; font-size:11px; line-height:20px; border:1px solid #FFF}
+.o2k7Skin .mceColorSplitMenu a.morecolors:hover {border:1px solid #0A246A; background-color:#B6BDD2}
+.o2k7Skin a.mceMoreColors:hover {border:1px solid #0A246A}
+.o2k7Skin .mceColorPreview {position:absolute; top:15px; left:2px; width:16px; height:4px; overflow:hidden}
+
+/* Menu */
+.o2k7Skin .mceMenu {position:absolute; left:0; top:0; z-index:1000; border:1px solid #ABC6DD}
+.o2k7Skin .noIcons span.icon {width:0;}
+.o2k7Skin .noIcons a .text {padding-left:10px}
+.o2k7Skin .mceMenu table {background:#FFF}
+.o2k7Skin .mceMenu a, .o2k7Skin .mceMenu span, .o2k7Skin .mceMenu {display:block}
+.o2k7Skin .mceMenu td {height:20px}
+.o2k7Skin .mceMenu a {position:relative;padding:3px 0 4px 0}
+.o2k7Skin .mceMenu .text {position:relative; display:block; font-family:Tahoma,Verdana,Arial,Helvetica; color:#000; cursor:default; margin:0; padding:0 25px 0 25px; display:block}
+.o2k7Skin .mceMenu span.text, .o2k7Skin .mceMenu .preview {font-size:11px}
+.o2k7Skin .mceMenu pre.text {font-family:Monospace}
+.o2k7Skin .mceMenu .icon {position:absolute; top:0; left:0; width:22px;}
+.o2k7Skin .mceMenu .mceMenuItemEnabled a:hover, .o2k7Skin .mceMenu .mceMenuItemActive {background-color:#dbecf3}
+.o2k7Skin td.mceMenuItemSeparator {background:#DDD; height:1px}
+.o2k7Skin .mceMenuItemTitle a {border:0; background:#E5EFFD; border-bottom:1px solid #ABC6DD}
+.o2k7Skin .mceMenuItemTitle span.text {color:#000; font-weight:bold; padding-left:4px}
+.o2k7Skin .mceMenuItemDisabled .text {color:#888}
+.o2k7Skin .mceMenuItemSelected .icon {background:url(../default/img/menu_check.gif)}
+.o2k7Skin .noIcons .mceMenuItemSelected a {background:url(../default/img/menu_arrow.gif) no-repeat -6px center}
+.o2k7Skin .mceMenu span.mceMenuLine {display:none}
+.o2k7Skin .mceMenuItemSub a {background:url(../default/img/menu_arrow.gif) no-repeat top right;}
+
+/* Progress,Resize */
+.o2k7Skin .mceBlocker {position:absolute; left:0; top:0; z-index:1000; opacity:0.5; filter:alpha(opacity=50); background:#FFF}
+.o2k7Skin .mceProgress {position:absolute; left:0; top:0; z-index:1001; background:url(../default/img/progress.gif) no-repeat; width:32px; height:32px; margin:-16px 0 0 -16px}
+.o2k7Skin .mcePlaceHolder {border:1px dotted gray}
+
+/* Theme */
+.o2k7Skin span.bold {background-position:0 0}
+.o2k7Skin span.italic {background-position:-60px 0}
+.o2k7Skin span.underline {background-position:-140px 0}
+.o2k7Skin span.strikethrough {background-position:-120px 0}
+.o2k7Skin span.undo {background-position:-160px 0}
+.o2k7Skin span.redo {background-position:-100px 0}
+.o2k7Skin span.cleanup {background-position:-40px 0}
+.o2k7Skin span.bullist {background-position:-20px 0}
+.o2k7Skin span.numlist {background-position:-80px 0}
+.o2k7Skin span.justifyleft {background-position:-460px 0}
+.o2k7Skin span.justifyright {background-position:-480px 0}
+.o2k7Skin span.justifycenter {background-position:-420px 0}
+.o2k7Skin span.justifyfull {background-position:-440px 0}
+.o2k7Skin span.anchor {background-position:-200px 0}
+.o2k7Skin span.indent {background-position:-400px 0}
+.o2k7Skin span.outdent {background-position:-540px 0}
+.o2k7Skin span.link {background-position:-500px 0}
+.o2k7Skin span.unlink {background-position:-640px 0}
+.o2k7Skin span.sub {background-position:-600px 0}
+.o2k7Skin span.sup {background-position:-620px 0}
+.o2k7Skin span.removeformat {background-position:-580px 0}
+.o2k7Skin span.newdocument {background-position:-520px 0}
+.o2k7Skin span.image {background-position:-380px 0}
+.o2k7Skin span.help {background-position:-340px 0}
+.o2k7Skin span.code {background-position:-260px 0}
+.o2k7Skin span.hr {background-position:-360px 0}
+.o2k7Skin span.visualaid {background-position:-660px 0}
+.o2k7Skin span.charmap {background-position:-240px 0}
+.o2k7Skin span.paste {background-position:-560px 0}
+.o2k7Skin span.copy {background-position:-700px 0}
+.o2k7Skin span.cut {background-position:-680px 0}
+.o2k7Skin span.blockquote {background-position:-220px 0}
+.o2k7Skin .forecolor span.action {background-position:-720px 0}
+.o2k7Skin .backcolor span.action {background-position:-760px 0}
+.o2k7Skin .forecolorpicker {background-position:-720px 0}
+.o2k7Skin .backcolorpicker {background-position:-760px 0}
+
+/* Plugins */
+.o2k7Skin span.advhr {background-position:-0px -20px}
+.o2k7Skin span.ltr {background-position:-20px -20px}
+.o2k7Skin span.rtl {background-position:-40px -20px}
+.o2k7Skin span.emotions {background-position:-60px -20px}
+.o2k7Skin span.fullpage {background-position:-80px -20px}
+.o2k7Skin span.fullscreen {background-position:-100px -20px}
+.o2k7Skin span.iespell {background-position:-120px -20px}
+.o2k7Skin span.insertdate {background-position:-140px -20px}
+.o2k7Skin span.inserttime {background-position:-160px -20px}
+.o2k7Skin span.absolute {background-position:-180px -20px}
+.o2k7Skin span.backward {background-position:-200px -20px}
+.o2k7Skin span.forward {background-position:-220px -20px}
+.o2k7Skin span.insert_layer {background-position:-240px -20px}
+.o2k7Skin span.insertlayer {background-position:-260px -20px}
+.o2k7Skin span.movebackward {background-position:-280px -20px}
+.o2k7Skin span.moveforward {background-position:-300px -20px}
+.o2k7Skin span.media {background-position:-320px -20px}
+.o2k7Skin span.nonbreaking {background-position:-340px -20px}
+.o2k7Skin span.pastetext {background-position:-360px -20px}
+.o2k7Skin span.pasteword {background-position:-380px -20px}
+.o2k7Skin span.selectall {background-position:-400px -20px}
+.o2k7Skin span.preview {background-position:-420px -20px}
+.o2k7Skin span.print {background-position:-440px -20px}
+.o2k7Skin span.cancel {background-position:-460px -20px}
+.o2k7Skin span.save {background-position:-480px -20px}
+.o2k7Skin span.replace {background-position:-500px -20px}
+.o2k7Skin span.search {background-position:-520px -20px}
+.o2k7Skin span.styleprops {background-position:-560px -20px}
+.o2k7Skin span.table {background-position:-580px -20px}
+.o2k7Skin span.cell_props {background-position:-600px -20px}
+.o2k7Skin span.delete_table {background-position:-620px -20px}
+.o2k7Skin span.delete_col {background-position:-640px -20px}
+.o2k7Skin span.delete_row {background-position:-660px -20px}
+.o2k7Skin span.col_after {background-position:-680px -20px}
+.o2k7Skin span.col_before {background-position:-700px -20px}
+.o2k7Skin span.row_after {background-position:-720px -20px}
+.o2k7Skin span.row_before {background-position:-740px -20px}
+.o2k7Skin span.merge_cells {background-position:-760px -20px}
+.o2k7Skin span.table_props {background-position:-980px -20px}
+.o2k7Skin span.row_props {background-position:-780px -20px}
+.o2k7Skin span.split_cells {background-position:-800px -20px}
+.o2k7Skin span.template {background-position:-820px -20px}
+.o2k7Skin span.visualchars {background-position:-840px -20px}
+.o2k7Skin span.abbr {background-position:-860px -20px}
+.o2k7Skin span.acronym {background-position:-880px -20px}
+.o2k7Skin span.attribs {background-position:-900px -20px}
+.o2k7Skin span.cite {background-position:-920px -20px}
+.o2k7Skin span.del {background-position:-940px -20px}
+.o2k7Skin span.ins {background-position:-960px -20px}
+.o2k7Skin span.pagebreak {background-position:0 -40px}
+.o2k7Skin .spellchecker span.action {background-position:-540px -20px}
--- a/includes/clientside/tinymce/themes/advanced/source_editor.htm	Fri Feb 22 12:46:51 2008 -0500
+++ b/includes/clientside/tinymce/themes/advanced/source_editor.htm	Fri Feb 22 12:51:53 2008 -0500
@@ -1,30 +1,30 @@
 <html xmlns="http://www.w3.org/1999/xhtml">
 <head>
 	<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
-	<title>{$lang_theme_code_title}</title>
-	<script language="javascript" type="text/javascript" src="../../tiny_mce_popup.js"></script>
-	<script language="javascript" type="text/javascript" src="jscripts/source_editor.js"></script>
+	<title>{#advanced_dlg.code_title}</title>
+	<script type="text/javascript" src="../../tiny_mce_popup.js"></script>
+	<script type="text/javascript" src="js/source_editor.js"></script>
 	<base target="_self" />
 </head>
-<body onload="tinyMCEPopup.executeOnLoad('onLoadInit();');" onresize="resizeInputs();" style="display: none">
+<body onresize="resizeInputs();" style="display:none; overflow:hidden;">
 	<form name="source" onsubmit="saveContent();" action="#">
-		<div style="float: left" class="title">{$lang_theme_code_title}</div>
+		<div style="float: left" class="title">{#advanced_dlg.code_title}</div>
 
 		<div id="wrapline" style="float: right">
-			<input type="checkbox" name="wraped" id="wraped" onclick="toggleWordWrap(this);" class="wordWrapCode" /><label for="wraped">{$lang_theme_code_wordwrap}</label>
+			<input type="checkbox" name="wraped" id="wraped" onclick="toggleWordWrap(this);" class="wordWrapCode" /><label for="wraped">{#advanced_dlg.code_wordwrap}</label>
 		</div>
 
 		<br style="clear: both" />
 
-		<textarea name="htmlSource" id="htmlSource" rows="15" cols="100" style="width: 100%; height: 100%; font-family: 'Courier New',Courier,mono; font-size: 12px" dir="ltr" wrap="off"></textarea>
+		<textarea name="htmlSource" id="htmlSource" rows="15" cols="100" style="width: 100%; height: 100%; font-family: 'Courier New',Courier,monospace; font-size: 12px;" dir="ltr" wrap="off"></textarea>
 
 		<div class="mceActionPanel">
 			<div style="float: left">
-				<input type="button" name="insert" value="{$lang_update}" onclick="saveContent();" id="insert" />
+				<input type="button" name="insert" value="{#update}" onclick="saveContent();" id="insert" />
 			</div>
 
 			<div style="float: right">
-				<input type="button" name="cancel" value="{$lang_cancel}" onclick="tinyMCEPopup.close();" id="cancel" />
+				<input type="button" name="cancel" value="{#cancel}" onclick="tinyMCEPopup.close();" id="cancel" />
 			</div>
 		</div>
 	</form>
--- a/includes/clientside/tinymce/themes/simple/css/editor_content.css	Fri Feb 22 12:46:51 2008 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,25 +0,0 @@
-body, td, pre {
-	font-family: Verdana, Arial, Helvetica, sans-serif;
-	font-size: 10px;
-}
-
-body {
-	background-color: #FFFFFF;
-}
-
-.mceVisualAid {
-	border: 1px dashed #BBBBBB;
-}
-
-/* MSIE specific */
-
-* html body {
-	scrollbar-3dlight-color: #F0F0EE;
-	scrollbar-arrow-color: #676662;
-	scrollbar-base-color: #F0F0EE;
-	scrollbar-darkshadow-color: #DDDDDD;
-	scrollbar-face-color: #E0E0DD;
-	scrollbar-highlight-color: #F0F0EE;
-	scrollbar-shadow-color: #F0F0EE;
-	scrollbar-track-color: #F5F5F5;	
-}
--- a/includes/clientside/tinymce/themes/simple/css/editor_popup.css	Fri Feb 22 12:46:51 2008 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,41 +0,0 @@
-body {
-	background-color: #F0F0EE;
-	font-family: Verdana, Arial, Helvetica, sans-serif;
-	font-size: 11px;
-	scrollbar-3dlight-color: #F0F0EE;
-	scrollbar-arrow-color: #676662;
-	scrollbar-base-color: #F0F0EE;
-	scrollbar-darkshadow-color: #DDDDDD;
-	scrollbar-face-color: #E0E0DD;
-	scrollbar-highlight-color: #F0F0EE;
-	scrollbar-shadow-color: #F0F0EE;
-	scrollbar-track-color: #F5F5F5;
-}
-
-td {
-	font-family: Verdana, Arial, Helvetica, sans-serif;
-	font-size: 11px;
-}
-
-input {
-	background: #FFFFFF;
-	border: 1px solid #cccccc;
-}
-
-td, input, select, textarea {
-	font-family: Verdana, Arial, Helvetica, sans-serif;
-	font-size: 10px;
-}
-
-input, select, textarea {
-	border: 1px solid #808080;
-}
-
-.input_noborder {
-	border: 0;
-}
-
-.title {
-	font-size: 12px;
-	font-weight: bold;
-}
\ No newline at end of file
--- a/includes/clientside/tinymce/themes/simple/css/editor_ui.css	Fri Feb 22 12:46:51 2008 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,125 +0,0 @@
-.mceSeparatorLine {
-	border: 0;
-	padding: 0;
-	margin-left: 4px;
-	margin-right: 2px;
-}
-
-.mceSelectList {
-	font-family: "MS Sans Serif";
-	font-size: 7pt;
-	font-weight: normal;
-	margin-top: 2px;
-}
-
-.mceLabel, .mceLabelDisabled {
-	font-family: "MS Sans Serif";
-	font-size: 9pt;
-}
-
-.mceLabel {
-	color: #000000;
-}
-
-.mceLabelDisabled {
-	cursor: text;
-	color: #999999;
-}
-
-.mceEditor {
-	background: #F0F0EE;
-	border: 1px solid #cccccc;
-}
-
-.mceEditorArea {
-	font-family: "MS Sans Serif";
-	background: #FFFFFF;
-}
-
-.mceToolbar {
-	background: #F0F0EE;
-	border-top: 1px solid #cccccc;
-	line-height: 1px;
-	font-size: 1px;
-	padding-bottom: 1px;
-}
-
-.mceEditorIframe {
-	border: 0;
-}
-
-/* Button CSS rules */
-
-a.mceButtonDisabled img, a.mceButtonNormal img, a.mceButtonSelected img {
-	width: 20px;
-	height: 20px;
-	cursor: default;
-	margin-top: 1px;
-	margin-left: 1px;
-}
-
-a.mceButtonDisabled img {
-	border: 0 !important;
-}
-
-a.mceButtonNormal img, a.mceButtonSelected img {
-	border: 1px solid #F0F0EE !important;
-}
-
-a.mceButtonSelected img {
-	border: 1px solid #C0C0BB !important;
-}
-
-a.mceButtonNormal img:hover, a.mceButtonSelected img:hover {
-	border: 1px solid #0A246A !important;
-	cursor: default;
-	background-color: #B6BDD2;
-}
-
-a.mceButtonDisabled img {
-	-moz-opacity:0.3;
-	opacity: 0.3;
-	border: 1px solid #F0F0EE !important;
-	cursor: default;
-}
-
-a.mceTiledButton img {
-	background-image: url('../images/buttons.gif');
-	background-repeat: no-repeat;
-}
-
-/* MSIE specific rules */
-
-* html a.mceButtonNormal img, * html a.mceButtonSelected img, * html a.mceButtonDisabled img {
-	border: 0px !important;
-	margin-top: 2px;
-	margin-bottom: 1px;
-}
-
-* html a.mceButtonDisabled img {
-	filter:progid:DXImageTransform.Microsoft.Alpha(opacity=30);
-	border: 0px !important;
-}
-
-* html a.mceButtonDisabled {
-	border: 1px solid #F0F0EE !important;
-}
-
-* html a.mceButtonNormal, * html a.mceButtonSelected {
-	border: 1px solid #F0F0EE;
-	cursor: default;
-}
-
-* html a.mceButtonSelected {
-	border: 1px solid #C0C0BB;
-}
-
-* html a.mceButtonNormal:hover, * html a.mceButtonSelected:hover {
-	border: 1px solid #0A246A;
-	cursor: default;
-	background-color: #B6BDD2;
-}
-
-* html .mceSelectList {
-	margin-top: 2px;
-}
--- a/includes/clientside/tinymce/themes/simple/editor_template.js	Fri Feb 22 12:46:51 2008 -0500
+++ b/includes/clientside/tinymce/themes/simple/editor_template.js	Fri Feb 22 12:51:53 2008 -0500
@@ -1,1 +1,1 @@
-var TinyMCE_SimpleTheme={_buttonMap:'bold,bullist,cleanup,italic,numlist,redo,strikethrough,underline,undo',getEditorTemplate:function(){var html='';html+='<table class="mceEditor" border="0" cellpadding="0" cellspacing="0" width="{$width}" height="{$height}">';html+='<tr><td align="center">';html+='<span id="{$editor_id}">IFRAME</span>';html+='</td></tr>';html+='<tr><td class="mceToolbar" align="center" height="1">';html+=tinyMCE.getButtonHTML('bold','lang_bold_desc','{$themeurl}/images/{$lang_bold_img}','Bold');html+=tinyMCE.getButtonHTML('italic','lang_italic_desc','{$themeurl}/images/{$lang_italic_img}','Italic');html+=tinyMCE.getButtonHTML('underline','lang_underline_desc','{$themeurl}/images/{$lang_underline_img}','Underline');html+=tinyMCE.getButtonHTML('strikethrough','lang_striketrough_desc','{$themeurl}/images/strikethrough.gif','Strikethrough');html+='<img src="{$themeurl}/images/separator.gif" width="2" height="20" class="mceSeparatorLine" />';html+=tinyMCE.getButtonHTML('undo','lang_undo_desc','{$themeurl}/images/undo.gif','Undo');html+=tinyMCE.getButtonHTML('redo','lang_redo_desc','{$themeurl}/images/redo.gif','Redo');html+='<img src="{$themeurl}/images/separator.gif" width="2" height="20" class="mceSeparatorLine" />';html+=tinyMCE.getButtonHTML('cleanup','lang_cleanup_desc','{$themeurl}/images/cleanup.gif','mceCleanup');html+='<img src="{$themeurl}/images/separator.gif" width="2" height="20" class="mceSeparatorLine" />';html+=tinyMCE.getButtonHTML('bullist','lang_bullist_desc','{$themeurl}/images/bullist.gif','InsertUnorderedList');html+=tinyMCE.getButtonHTML('numlist','lang_numlist_desc','{$themeurl}/images/numlist.gif','InsertOrderedList');html+='</td></tr></table>';return{delta_width:0,delta_height:20,html:html}},handleNodeChange:function(editor_id,node){tinyMCE.switchClass(editor_id+'_bold','mceButtonNormal');tinyMCE.switchClass(editor_id+'_italic','mceButtonNormal');tinyMCE.switchClass(editor_id+'_underline','mceButtonNormal');tinyMCE.switchClass(editor_id+'_strikethrough','mceButtonNormal');tinyMCE.switchClass(editor_id+'_bullist','mceButtonNormal');tinyMCE.switchClass(editor_id+'_numlist','mceButtonNormal');do{switch(node.nodeName.toLowerCase()){case"b":case"strong":tinyMCE.switchClass(editor_id+'_bold','mceButtonSelected');break;case"i":case"em":tinyMCE.switchClass(editor_id+'_italic','mceButtonSelected');break;case"u":tinyMCE.switchClass(editor_id+'_underline','mceButtonSelected');break;case"strike":tinyMCE.switchClass(editor_id+'_strikethrough','mceButtonSelected');break;case"ul":tinyMCE.switchClass(editor_id+'_bullist','mceButtonSelected');break;case"ol":tinyMCE.switchClass(editor_id+'_numlist','mceButtonSelected');break}}while((node=node.parentNode)!=null)}};tinyMCE.addTheme("simple",TinyMCE_SimpleTheme);tinyMCE.addButtonMap(TinyMCE_SimpleTheme._buttonMap);
\ No newline at end of file
+(function(){var DOM=tinymce.DOM;tinymce.ThemeManager.requireLangPack('simple');tinymce.create('tinymce.themes.SimpleTheme',{init:function(ed,url){var t=this,states=['Bold','Italic','Underline','Strikethrough','InsertUnorderedList','InsertOrderedList'],s=ed.settings;t.editor=ed;ed.onInit.add(function(){ed.onNodeChange.add(function(ed,cm){tinymce.each(states,function(c){cm.get(c.toLowerCase()).setActive(ed.queryCommandState(c));});});ed.dom.loadCSS(url+"/skins/"+s.skin+"/content.css");});DOM.loadCSS(url+"/skins/"+s.skin+"/ui.css");},renderUI:function(o){var t=this,n=o.targetNode,ic,tb,ed=t.editor,cf=ed.controlManager,sc;n=DOM.insertAfter(DOM.create('div',{id:ed.id+'_container','class':'mceEditor '+ed.settings.skin+'SimpleSkin'}),n);n=sc=DOM.add(n,'table',{cellPadding:0,cellSpacing:0,'class':'mceLayout'});n=tb=DOM.add(n,'tbody');n=DOM.add(tb,'tr');n=ic=DOM.add(DOM.add(n,'td'),'div',{'class':'mceIframeContainer'});n=DOM.add(DOM.add(tb,'tr',{'class':'last'}),'td',{'class':'mceToolbar last',align:'center'});tb=t.toolbar=cf.createToolbar("tools1");tb.add(cf.createButton('bold',{title:'simple.bold_desc',cmd:'Bold'}));tb.add(cf.createButton('italic',{title:'simple.italic_desc',cmd:'Italic'}));tb.add(cf.createButton('underline',{title:'simple.underline_desc',cmd:'Underline'}));tb.add(cf.createButton('strikethrough',{title:'simple.striketrough_desc',cmd:'Strikethrough'}));tb.add(cf.createSeparator());tb.add(cf.createButton('undo',{title:'simple.undo_desc',cmd:'Undo'}));tb.add(cf.createButton('redo',{title:'simple.redo_desc',cmd:'Redo'}));tb.add(cf.createSeparator());tb.add(cf.createButton('cleanup',{title:'simple.cleanup_desc',cmd:'mceCleanup'}));tb.add(cf.createSeparator());tb.add(cf.createButton('insertunorderedlist',{title:'simple.bullist_desc',cmd:'InsertUnorderedList'}));tb.add(cf.createButton('insertorderedlist',{title:'simple.numlist_desc',cmd:'InsertOrderedList'}));tb.renderTo(n);return{iframeContainer:ic,editorContainer:ed.id+'_container',sizeContainer:sc,deltaHeight:-20};},getInfo:function(){return{longname:'Simple theme',author:'Moxiecode Systems AB',authorurl:'http://tinymce.moxiecode.com',version:tinymce.majorVersion+"."+tinymce.minorVersion}}});tinymce.ThemeManager.add('simple',tinymce.themes.SimpleTheme);})();
\ No newline at end of file
--- a/includes/clientside/tinymce/themes/simple/editor_template_src.js	Fri Feb 22 12:46:51 2008 -0500
+++ b/includes/clientside/tinymce/themes/simple/editor_template_src.js	Fri Feb 22 12:51:53 2008 -0500
@@ -1,84 +1,85 @@
 /**
- * $Id: editor_template_src.js 162 2007-01-03 16:16:52Z spocke $
+ * $Id: editor_template_src.js 520 2008-01-07 16:30:32Z spocke $
+ *
+ * This file is meant to showcase how to create a simple theme. The advanced
+ * theme is more suitable for production use.
  *
  * @author Moxiecode
- * @copyright Copyright © 2004-2007, Moxiecode Systems AB, All rights reserved.
+ * @copyright Copyright © 2004-2008, Moxiecode Systems AB, All rights reserved.
  */
 
-var TinyMCE_SimpleTheme = {
-	// List of button ids in tile map
-	_buttonMap : 'bold,bullist,cleanup,italic,numlist,redo,strikethrough,underline,undo',
+(function() {
+	var DOM = tinymce.DOM;
+
+	// Tell it to load theme specific language pack(s)
+	tinymce.ThemeManager.requireLangPack('simple');
 
-	getEditorTemplate : function() {
-		var html = '';
+	tinymce.create('tinymce.themes.SimpleTheme', {
+		init : function(ed, url) {
+			var t = this, states = ['Bold', 'Italic', 'Underline', 'Strikethrough', 'InsertUnorderedList', 'InsertOrderedList'], s = ed.settings;
+
+			t.editor = ed;
 
-		html += '<table class="mceEditor" border="0" cellpadding="0" cellspacing="0" width="{$width}" height="{$height}">';
-		html += '<tr><td align="center">';
-		html += '<span id="{$editor_id}">IFRAME</span>';
-		html += '</td></tr>';
-		html += '<tr><td class="mceToolbar" align="center" height="1">';
-		html += tinyMCE.getButtonHTML('bold', 'lang_bold_desc', '{$themeurl}/images/{$lang_bold_img}', 'Bold');
-		html += tinyMCE.getButtonHTML('italic', 'lang_italic_desc', '{$themeurl}/images/{$lang_italic_img}', 'Italic');
-		html += tinyMCE.getButtonHTML('underline', 'lang_underline_desc', '{$themeurl}/images/{$lang_underline_img}', 'Underline');
-		html += tinyMCE.getButtonHTML('strikethrough', 'lang_striketrough_desc', '{$themeurl}/images/strikethrough.gif', 'Strikethrough');
-		html += '<img src="{$themeurl}/images/separator.gif" width="2" height="20" class="mceSeparatorLine" />';
-		html += tinyMCE.getButtonHTML('undo', 'lang_undo_desc', '{$themeurl}/images/undo.gif', 'Undo');
-		html += tinyMCE.getButtonHTML('redo', 'lang_redo_desc', '{$themeurl}/images/redo.gif', 'Redo');
-		html += '<img src="{$themeurl}/images/separator.gif" width="2" height="20" class="mceSeparatorLine" />';
-		html += tinyMCE.getButtonHTML('cleanup', 'lang_cleanup_desc', '{$themeurl}/images/cleanup.gif', 'mceCleanup');
-		html += '<img src="{$themeurl}/images/separator.gif" width="2" height="20" class="mceSeparatorLine" />';
-		html += tinyMCE.getButtonHTML('bullist', 'lang_bullist_desc', '{$themeurl}/images/bullist.gif', 'InsertUnorderedList');
-		html += tinyMCE.getButtonHTML('numlist', 'lang_numlist_desc', '{$themeurl}/images/numlist.gif', 'InsertOrderedList');
-		html += '</td></tr></table>';
+			ed.onInit.add(function() {
+				ed.onNodeChange.add(function(ed, cm) {
+					tinymce.each(states, function(c) {
+						cm.get(c.toLowerCase()).setActive(ed.queryCommandState(c));
+					});
+				});
+
+				ed.dom.loadCSS(url + "/skins/" + s.skin + "/content.css");
+			});
 
-		return {
-			delta_width : 0,
-			delta_height : 20,
-			html : html
-		};
-	},
+			DOM.loadCSS(url + "/skins/" + s.skin + "/ui.css");
+		},
+
+		renderUI : function(o) {
+			var t = this, n = o.targetNode, ic, tb, ed = t.editor, cf = ed.controlManager, sc;
+
+			n = DOM.insertAfter(DOM.create('div', {id : ed.id + '_container', 'class' : 'mceEditor ' + ed.settings.skin + 'SimpleSkin'}), n);
+			n = sc = DOM.add(n, 'table', {cellPadding : 0, cellSpacing : 0, 'class' : 'mceLayout'});
+			n = tb = DOM.add(n, 'tbody');
+
+			// Create iframe container
+			n = DOM.add(tb, 'tr');
+			n = ic = DOM.add(DOM.add(n, 'td'), 'div', {'class' : 'mceIframeContainer'});
 
-	handleNodeChange : function(editor_id, node) {
-		// Reset old states
-		tinyMCE.switchClass(editor_id + '_bold', 'mceButtonNormal');
-		tinyMCE.switchClass(editor_id + '_italic', 'mceButtonNormal');
-		tinyMCE.switchClass(editor_id + '_underline', 'mceButtonNormal');
-		tinyMCE.switchClass(editor_id + '_strikethrough', 'mceButtonNormal');
-		tinyMCE.switchClass(editor_id + '_bullist', 'mceButtonNormal');
-		tinyMCE.switchClass(editor_id + '_numlist', 'mceButtonNormal');
+			// Create toolbar container
+			n = DOM.add(DOM.add(tb, 'tr', {'class' : 'last'}), 'td', {'class' : 'mceToolbar last', align : 'center'});
 
-		// Handle elements
-		do {
-			switch (node.nodeName.toLowerCase()) {
-				case "b":
-				case "strong":
-					tinyMCE.switchClass(editor_id + '_bold', 'mceButtonSelected');
-				break;
-
-				case "i":
-				case "em":
-					tinyMCE.switchClass(editor_id + '_italic', 'mceButtonSelected');
-				break;
+			// Create toolbar
+			tb = t.toolbar = cf.createToolbar("tools1");
+			tb.add(cf.createButton('bold', {title : 'simple.bold_desc', cmd : 'Bold'}));
+			tb.add(cf.createButton('italic', {title : 'simple.italic_desc', cmd : 'Italic'}));
+			tb.add(cf.createButton('underline', {title : 'simple.underline_desc', cmd : 'Underline'}));
+			tb.add(cf.createButton('strikethrough', {title : 'simple.striketrough_desc', cmd : 'Strikethrough'}));
+			tb.add(cf.createSeparator());
+			tb.add(cf.createButton('undo', {title : 'simple.undo_desc', cmd : 'Undo'}));
+			tb.add(cf.createButton('redo', {title : 'simple.redo_desc', cmd : 'Redo'}));
+			tb.add(cf.createSeparator());
+			tb.add(cf.createButton('cleanup', {title : 'simple.cleanup_desc', cmd : 'mceCleanup'}));
+			tb.add(cf.createSeparator());
+			tb.add(cf.createButton('insertunorderedlist', {title : 'simple.bullist_desc', cmd : 'InsertUnorderedList'}));
+			tb.add(cf.createButton('insertorderedlist', {title : 'simple.numlist_desc', cmd : 'InsertOrderedList'}));
+			tb.renderTo(n);
 
-				case "u":
-					tinyMCE.switchClass(editor_id + '_underline', 'mceButtonSelected');
-				break;
+			return {
+				iframeContainer : ic,
+				editorContainer : ed.id + '_container',
+				sizeContainer : sc,
+				deltaHeight : -20
+			};
+		},
 
-				case "strike":
-					tinyMCE.switchClass(editor_id + '_strikethrough', 'mceButtonSelected');
-				break;
-				
-				case "ul":
-					tinyMCE.switchClass(editor_id + '_bullist', 'mceButtonSelected');
-				break;
+		getInfo : function() {
+			return {
+				longname : 'Simple theme',
+				author : 'Moxiecode Systems AB',
+				authorurl : 'http://tinymce.moxiecode.com',
+				version : tinymce.majorVersion + "." + tinymce.minorVersion
+			}
+		}
+	});
 
-				case "ol":
-					tinyMCE.switchClass(editor_id + '_numlist', 'mceButtonSelected');
-				break;
-			}
-		} while ((node = node.parentNode) != null);
-	}
-};
-
-tinyMCE.addTheme("simple", TinyMCE_SimpleTheme);
-tinyMCE.addButtonMap(TinyMCE_SimpleTheme._buttonMap);
+	tinymce.ThemeManager.add('simple', tinymce.themes.SimpleTheme);
+})();
\ No newline at end of file
Binary file includes/clientside/tinymce/themes/simple/images/bold.gif has changed
Binary file includes/clientside/tinymce/themes/simple/images/bold_de_se.gif has changed
Binary file includes/clientside/tinymce/themes/simple/images/bold_fr.gif has changed
Binary file includes/clientside/tinymce/themes/simple/images/bold_ru.gif has changed
Binary file includes/clientside/tinymce/themes/simple/images/bold_tw.gif has changed
Binary file includes/clientside/tinymce/themes/simple/images/bullist.gif has changed
Binary file includes/clientside/tinymce/themes/simple/images/buttons.gif has changed
Binary file includes/clientside/tinymce/themes/simple/images/cleanup.gif has changed
Binary file includes/clientside/tinymce/themes/simple/images/italic.gif has changed
Binary file includes/clientside/tinymce/themes/simple/images/italic_de_se.gif has changed
Binary file includes/clientside/tinymce/themes/simple/images/italic_ru.gif has changed
Binary file includes/clientside/tinymce/themes/simple/images/italic_tw.gif has changed
Binary file includes/clientside/tinymce/themes/simple/images/numlist.gif has changed
Binary file includes/clientside/tinymce/themes/simple/images/redo.gif has changed
Binary file includes/clientside/tinymce/themes/simple/images/separator.gif has changed
Binary file includes/clientside/tinymce/themes/simple/images/spacer.gif has changed
Binary file includes/clientside/tinymce/themes/simple/images/strikethrough.gif has changed
Binary file includes/clientside/tinymce/themes/simple/images/underline.gif has changed
Binary file includes/clientside/tinymce/themes/simple/images/underline_fr.gif has changed
Binary file includes/clientside/tinymce/themes/simple/images/underline_ru.gif has changed
Binary file includes/clientside/tinymce/themes/simple/images/underline_tw.gif has changed
Binary file includes/clientside/tinymce/themes/simple/images/undo.gif has changed
Binary file includes/clientside/tinymce/themes/simple/img/icons.gif has changed
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/includes/clientside/tinymce/themes/simple/langs/en.js	Fri Feb 22 12:51:53 2008 -0500
@@ -0,0 +1,11 @@
+tinyMCE.addI18n('en.simple',{
+bold_desc:"Bold (Ctrl+B)",
+italic_desc:"Italic (Ctrl+I)",
+underline_desc:"Underline (Ctrl+U)",
+striketrough_desc:"Strikethrough",
+bullist_desc:"Unordered list",
+numlist_desc:"Ordered list",
+undo_desc:"Undo (Ctrl+Z)",
+redo_desc:"Redo (Ctrl+Y)",
+cleanup_desc:"Cleanup messy code"
+});
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/includes/clientside/tinymce/themes/simple/skins/default/content.css	Fri Feb 22 12:51:53 2008 -0500
@@ -0,0 +1,25 @@
+body, td, pre {
+	font-family: Verdana, Arial, Helvetica, sans-serif;
+	font-size: 10px;
+}
+
+body {
+	background-color: #FFFFFF;
+}
+
+.mceVisualAid {
+	border: 1px dashed #BBBBBB;
+}
+
+/* MSIE specific */
+
+* html body {
+	scrollbar-3dlight-color: #F0F0EE;
+	scrollbar-arrow-color: #676662;
+	scrollbar-base-color: #F0F0EE;
+	scrollbar-darkshadow-color: #DDDDDD;
+	scrollbar-face-color: #E0E0DD;
+	scrollbar-highlight-color: #F0F0EE;
+	scrollbar-shadow-color: #F0F0EE;
+	scrollbar-track-color: #F5F5F5;	
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/includes/clientside/tinymce/themes/simple/skins/default/ui.css	Fri Feb 22 12:51:53 2008 -0500
@@ -0,0 +1,32 @@
+/* Reset */
+.defaultSimpleSkin table, .defaultSimpleSkin tbody, .defaultSimpleSkin a, .defaultSimpleSkin img, .defaultSimpleSkin tr, .defaultSimpleSkin div, .defaultSimpleSkin td, .defaultSimpleSkin iframe, .defaultSimpleSkin span, .defaultSimpleSkin * {border:0; margin:0; padding:0; background:transparent; white-space:nowrap; text-decoration:none; font-weight:normal; cursor:default; color:#000}
+
+/* Containers */
+.defaultSimpleSkin {position:relative}
+.defaultSimpleSkin table.mceLayout {background:#F0F0EE; border:1px solid #CCC;}
+.defaultSimpleSkin iframe {display:block; background:#FFF; border-bottom:1px solid #CCC;}
+.defaultSimpleSkin .mceToolbar {height:24px;}
+
+/* Layout */
+.defaultSimpleSkin span.icon, .defaultSimpleSkin img.icon {display:block; width:20px; height:20px}
+.defaultSimpleSkin .icon {background:url(../../img/icons.gif) no-repeat 20px 20px}
+
+/* Button */
+.defaultSimpleSkin .mceButton {display:block; border:1px solid #F0F0EE; width:20px; height:20px}
+.defaultSimpleSkin a.mceButtonEnabled:hover {border:1px solid #0A246A; background-color:#B2BBD0}
+.defaultSimpleSkin a.mceButtonActive {border:1px solid #0A246A; background-color:#C2CBE0}
+.defaultSimpleSkin .mceButtonDisabled span {opacity:0.3; filter:alpha(opacity=30)}
+
+/* Separator */
+.defaultSimpleSkin .mceSeparator {display:block; background:url(../../img/icons.gif) -180px 0; width:2px; height:20px; margin:0 2px 0 4px}
+
+/* Theme */
+.defaultSimpleSkin span.bold {background-position:0 0}
+.defaultSimpleSkin span.italic {background-position:-60px 0}
+.defaultSimpleSkin span.underline {background-position:-140px 0}
+.defaultSimpleSkin span.strikethrough {background-position:-120px 0}
+.defaultSimpleSkin span.undo {background-position:-160px 0}
+.defaultSimpleSkin span.redo {background-position:-100px 0}
+.defaultSimpleSkin span.cleanup {background-position:-40px 0}
+.defaultSimpleSkin span.insertunorderedlist {background-position:-20px 0}
+.defaultSimpleSkin span.insertorderedlist {background-position:-80px 0}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/includes/clientside/tinymce/themes/simple/skins/o2k7/content.css	Fri Feb 22 12:51:53 2008 -0500
@@ -0,0 +1,17 @@
+body, td, pre {font-family:Verdana, Arial, Helvetica, sans-serif; font-size:10px;}
+
+body {background: #FFF;}
+.mceVisualAid {border: 1px dashed #BBB;}
+
+/* IE */
+
+* html body {
+scrollbar-3dlight-color: #F0F0EE;
+scrollbar-arrow-color: #676662;
+scrollbar-base-color: #F0F0EE;
+scrollbar-darkshadow-color: #DDDDDD;
+scrollbar-face-color: #E0E0DD;
+scrollbar-highlight-color: #F0F0EE;
+scrollbar-shadow-color: #F0F0EE;
+scrollbar-track-color: #F5F5F5;	
+}
Binary file includes/clientside/tinymce/themes/simple/skins/o2k7/img/button_bg.png has changed
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/includes/clientside/tinymce/themes/simple/skins/o2k7/ui.css	Fri Feb 22 12:51:53 2008 -0500
@@ -0,0 +1,35 @@
+/* Reset */
+.o2k7SimpleSkin table, .o2k7SimpleSkin tbody, .o2k7SimpleSkin a, .o2k7SimpleSkin img, .o2k7SimpleSkin tr, .o2k7SimpleSkin div, .o2k7SimpleSkin td, .o2k7SimpleSkin iframe, .o2k7SimpleSkin span, .o2k7SimpleSkin * {border:0; margin:0; padding:0; background:transparent; white-space:nowrap; text-decoration:none; font-weight:normal; cursor:default; color:#000}
+
+/* Containers */
+.o2k7SimpleSkin {position:relative}
+.o2k7SimpleSkin table.mceLayout {background:#E5EFFD; border:1px solid #ABC6DD;}
+.o2k7SimpleSkin iframe {display:block; background:#FFF; border-bottom:1px solid #ABC6DD;}
+.o2k7SimpleSkin .mceToolbar {height:26px;}
+
+/* Layout */
+.o2k7SimpleSkin .mceToolbar .mceToolbarStart span {display:block; background:url(img/button_bg.png) -22px 0; width:1px; height:22px; }
+.o2k7SimpleSkin .mceToolbar .mceToolbarEnd span {display:block; background:url(img/button_bg.png) -22px 0; width:1px; height:22px}
+.o2k7SimpleSkin span.icon, .o2k7SimpleSkin img.icon {display:block; width:20px; height:20px}
+.o2k7SimpleSkin .icon {background:url(../../img/icons.gif) no-repeat 20px 20px}
+
+/* Button */
+.o2k7SimpleSkin .mceButton {display:block; background:url(img/button_bg.png); width:22px; height:22px}
+.o2k7SimpleSkin a.mceButton span, .o2k7SimpleSkin a.mceButton img {margin:1px 0 0 1px}
+.o2k7SimpleSkin a.mceButtonEnabled:hover {background-color:#B2BBD0; background-position:0 -22px}
+.o2k7SimpleSkin a.mceButtonActive {background-position:0 -44px}
+.o2k7SimpleSkin .mceButtonDisabled span {opacity:0.3; filter:alpha(opacity=30)}
+
+/* Separator */
+.o2k7SimpleSkin .mceSeparator {display:block; background:url(img/button_bg.png) -22px 0; width:5px; height:22px}
+
+/* Theme */
+.o2k7SimpleSkin span.bold {background-position:0 0}
+.o2k7SimpleSkin span.italic {background-position:-60px 0}
+.o2k7SimpleSkin span.underline {background-position:-140px 0}
+.o2k7SimpleSkin span.strikethrough {background-position:-120px 0}
+.o2k7SimpleSkin span.undo {background-position:-160px 0}
+.o2k7SimpleSkin span.redo {background-position:-100px 0}
+.o2k7SimpleSkin span.cleanup {background-position:-40px 0}
+.o2k7SimpleSkin span.insertunorderedlist {background-position:-20px 0}
+.o2k7SimpleSkin span.insertorderedlist {background-position:-80px 0}
--- a/includes/clientside/tinymce/tiny_mce.js	Fri Feb 22 12:46:51 2008 -0500
+++ b/includes/clientside/tinymce/tiny_mce.js	Fri Feb 22 12:51:53 2008 -0500
@@ -1,1 +1,1 @@
-function TinyMCE_Engine(){var ua;this.majorVersion="2";this.minorVersion="1.0";this.releaseDate="2007-02-13";this.instances=new Array();this.switchClassCache=new Array();this.windowArgs=new Array();this.loadedFiles=new Array();this.pendingFiles=new Array();this.loadingIndex=0;this.configs=new Array();this.currentConfig=0;this.eventHandlers=new Array();this.log=new Array();this.undoLevels=[];this.undoIndex=0;this.typingUndoIndex=-1;ua=navigator.userAgent;this.isMSIE=(navigator.appName=="Microsoft Internet Explorer");this.isMSIE5=this.isMSIE&&(ua.indexOf('MSIE 5')!=-1);this.isMSIE5_0=this.isMSIE&&(ua.indexOf('MSIE 5.0')!=-1);this.isMSIE7=this.isMSIE&&(ua.indexOf('MSIE 7')!=-1);this.isGecko=ua.indexOf('Gecko')!=-1;this.isSafari=ua.indexOf('Safari')!=-1;this.isOpera=ua.indexOf('Opera')!=-1;this.isMac=ua.indexOf('Mac')!=-1;this.isNS7=ua.indexOf('Netscape/7')!=-1;this.isNS71=ua.indexOf('Netscape/7.1')!=-1;this.dialogCounter=0;this.plugins=new Array();this.themes=new Array();this.menus=new Array();this.loadedPlugins=new Array();this.buttonMap=new Array();this.isLoaded=false;if(this.isOpera){this.isMSIE=true;this.isGecko=false;this.isSafari=false}this.isIE=this.isMSIE;this.isRealIE=this.isMSIE&&!this.isOpera;this.idCounter=0};TinyMCE_Engine.prototype={init:function(settings){var theme,nl,baseHREF="",i;if(this.isMSIE5_0)return;this.settings=settings;if(typeof(document.execCommand)=='undefined')return;if(!tinyMCE.baseURL){var elements=document.getElementsByTagName('script');nl=document.getElementsByTagName('base');for(i=0;i<nl.length;i++){if(nl[i].href)baseHREF=nl[i].href}for(var i=0;i<elements.length;i++){if(elements[i].src&&(elements[i].src.indexOf("tiny_mce.js")!=-1||elements[i].src.indexOf("tiny_mce_dev.js")!=-1||elements[i].src.indexOf("tiny_mce_src.js")!=-1||elements[i].src.indexOf("tiny_mce_gzip")!=-1)){var src=elements[i].src;tinyMCE.srcMode=(src.indexOf('_src')!=-1||src.indexOf('_dev')!=-1)?'_src':'';tinyMCE.gzipMode=src.indexOf('_gzip')!=-1;src=src.substring(0,src.lastIndexOf('/'));if(settings.exec_mode=="src"||settings.exec_mode=="normal")tinyMCE.srcMode=settings.exec_mode=="src"?'_src':'';if(baseHREF!=""&&src.indexOf('://')==-1)tinyMCE.baseURL=baseHREF+src;else tinyMCE.baseURL=src;break}}}this.documentBasePath=document.location.href;if(this.documentBasePath.indexOf('?')!=-1)this.documentBasePath=this.documentBasePath.substring(0,this.documentBasePath.indexOf('?'));this.documentURL=this.documentBasePath;this.documentBasePath=this.documentBasePath.substring(0,this.documentBasePath.lastIndexOf('/'));if(tinyMCE.baseURL.indexOf('://')==-1&&tinyMCE.baseURL.charAt(0)!='/'){tinyMCE.baseURL=this.documentBasePath+"/"+tinyMCE.baseURL}this._def("mode","none");this._def("theme","advanced");this._def("plugins","",true);this._def("language","en");this._def("docs_language",this.settings['language']);this._def("elements","");this._def("textarea_trigger","mce_editable");this._def("editor_selector","");this._def("editor_deselector","mceNoEditor");this._def("valid_elements","+a[id|style|rel|rev|charset|hreflang|dir|lang|tabindex|accesskey|type|name|href|target|title|class|onfocus|onblur|onclick|ondblclick|onmousedown|onmouseup|onmouseover|onmousemove|onmouseout|onkeypress|onkeydown|onkeyup],-strong/-b[class|style],-em/-i[class|style],-strike[class|style],-u[class|style],#p[id|style|dir|class|align],-ol[class|style],-ul[class|style],-li[class|style],br,img[id|dir|lang|longdesc|usemap|style|class|src|onmouseover|onmouseout|border|alt=|title|hspace|vspace|width|height|align],-sub[style|class],-sup[style|class],-blockquote[dir|style],-table[border=0|cellspacing|cellpadding|width|height|class|align|summary|style|dir|id|lang|bgcolor|background|bordercolor],-tr[id|lang|dir|class|rowspan|width|height|align|valign|style|bgcolor|background|bordercolor],tbody[id|class],thead[id|class],tfoot[id|class],#td[id|lang|dir|class|colspan|rowspan|width|height|align|valign|style|bgcolor|background|bordercolor|scope],-th[id|lang|dir|class|colspan|rowspan|width|height|align|valign|style|scope],caption[id|lang|dir|class|style],-div[id|dir|class|align|style],-span[style|class|align],-pre[class|align|style],address[class|align|style],-h1[id|style|dir|class|align],-h2[id|style|dir|class|align],-h3[id|style|dir|class|align],-h4[id|style|dir|class|align],-h5[id|style|dir|class|align],-h6[id|style|dir|class|align],hr[class|style],-font[face|size|style|id|class|dir|color],dd[id|class|title|style|dir|lang],dl[id|class|title|style|dir|lang],dt[id|class|title|style|dir|lang],cite[title|id|class|style|dir|lang],abbr[title|id|class|style|dir|lang],acronym[title|id|class|style|dir|lang],del[title|id|class|style|dir|lang|datetime|cite],ins[title|id|class|style|dir|lang|datetime|cite]");this._def("extended_valid_elements","");this._def("invalid_elements","");this._def("encoding","");this._def("urlconverter_callback",tinyMCE.getParam("urlconvertor_callback","TinyMCE_Engine.prototype.convertURL"));this._def("save_callback","");this._def("debug",false);this._def("force_br_newlines",false);this._def("force_p_newlines",true);this._def("add_form_submit_trigger",true);this._def("relative_urls",true);this._def("remove_script_host",true);this._def("focus_alert",true);this._def("document_base_url",this.documentURL);this._def("visual",true);this._def("visual_table_class","mceVisualAid");this._def("setupcontent_callback","");this._def("fix_content_duplication",true);this._def("custom_undo_redo",true);this._def("custom_undo_redo_levels",-1);this._def("custom_undo_redo_keyboard_shortcuts",true);this._def("custom_undo_redo_restore_selection",true);this._def("custom_undo_redo_global",false);this._def("verify_html",true);this._def("apply_source_formatting",false);this._def("directionality","ltr");this._def("cleanup_on_startup",false);this._def("inline_styles",false);this._def("convert_newlines_to_brs",false);this._def("auto_reset_designmode",true);this._def("entities","39,#39,160,nbsp,161,iexcl,162,cent,163,pound,164,curren,165,yen,166,brvbar,167,sect,168,uml,169,copy,170,ordf,171,laquo,172,not,173,shy,174,reg,175,macr,176,deg,177,plusmn,178,sup2,179,sup3,180,acute,181,micro,182,para,183,middot,184,cedil,185,sup1,186,ordm,187,raquo,188,frac14,189,frac12,190,frac34,191,iquest,192,Agrave,193,Aacute,194,Acirc,195,Atilde,196,Auml,197,Aring,198,AElig,199,Ccedil,200,Egrave,201,Eacute,202,Ecirc,203,Euml,204,Igrave,205,Iacute,206,Icirc,207,Iuml,208,ETH,209,Ntilde,210,Ograve,211,Oacute,212,Ocirc,213,Otilde,214,Ouml,215,times,216,Oslash,217,Ugrave,218,Uacute,219,Ucirc,220,Uuml,221,Yacute,222,THORN,223,szlig,224,agrave,225,aacute,226,acirc,227,atilde,228,auml,229,aring,230,aelig,231,ccedil,232,egrave,233,eacute,234,ecirc,235,euml,236,igrave,237,iacute,238,icirc,239,iuml,240,eth,241,ntilde,242,ograve,243,oacute,244,ocirc,245,otilde,246,ouml,247,divide,248,oslash,249,ugrave,250,uacute,251,ucirc,252,uuml,253,yacute,254,thorn,255,yuml,402,fnof,913,Alpha,914,Beta,915,Gamma,916,Delta,917,Epsilon,918,Zeta,919,Eta,920,Theta,921,Iota,922,Kappa,923,Lambda,924,Mu,925,Nu,926,Xi,927,Omicron,928,Pi,929,Rho,931,Sigma,932,Tau,933,Upsilon,934,Phi,935,Chi,936,Psi,937,Omega,945,alpha,946,beta,947,gamma,948,delta,949,epsilon,950,zeta,951,eta,952,theta,953,iota,954,kappa,955,lambda,956,mu,957,nu,958,xi,959,omicron,960,pi,961,rho,962,sigmaf,963,sigma,964,tau,965,upsilon,966,phi,967,chi,968,psi,969,omega,977,thetasym,978,upsih,982,piv,8226,bull,8230,hellip,8242,prime,8243,Prime,8254,oline,8260,frasl,8472,weierp,8465,image,8476,real,8482,trade,8501,alefsym,8592,larr,8593,uarr,8594,rarr,8595,darr,8596,harr,8629,crarr,8656,lArr,8657,uArr,8658,rArr,8659,dArr,8660,hArr,8704,forall,8706,part,8707,exist,8709,empty,8711,nabla,8712,isin,8713,notin,8715,ni,8719,prod,8721,sum,8722,minus,8727,lowast,8730,radic,8733,prop,8734,infin,8736,ang,8743,and,8744,or,8745,cap,8746,cup,8747,int,8756,there4,8764,sim,8773,cong,8776,asymp,8800,ne,8801,equiv,8804,le,8805,ge,8834,sub,8835,sup,8836,nsub,8838,sube,8839,supe,8853,oplus,8855,otimes,8869,perp,8901,sdot,8968,lceil,8969,rceil,8970,lfloor,8971,rfloor,9001,lang,9002,rang,9674,loz,9824,spades,9827,clubs,9829,hearts,9830,diams,34,quot,38,amp,60,lt,62,gt,338,OElig,339,oelig,352,Scaron,353,scaron,376,Yuml,710,circ,732,tilde,8194,ensp,8195,emsp,8201,thinsp,8204,zwnj,8205,zwj,8206,lrm,8207,rlm,8211,ndash,8212,mdash,8216,lsquo,8217,rsquo,8218,sbquo,8220,ldquo,8221,rdquo,8222,bdquo,8224,dagger,8225,Dagger,8240,permil,8249,lsaquo,8250,rsaquo,8364,euro",true);this._def("entity_encoding","named");this._def("cleanup_callback","");this._def("add_unload_trigger",true);this._def("ask",false);this._def("nowrap",false);this._def("auto_resize",false);this._def("auto_focus",false);this._def("cleanup",true);this._def("remove_linebreaks",true);this._def("button_tile_map",false);this._def("submit_patch",true);this._def("browsers","msie,safari,gecko,opera",true);this._def("dialog_type","window");this._def("accessibility_warnings",true);this._def("accessibility_focus",true);this._def("merge_styles_invalid_parents","");this._def("force_hex_style_colors",true);this._def("trim_span_elements",true);this._def("convert_fonts_to_spans",false);this._def("doctype",'<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">');this._def("font_size_classes",'');this._def("font_size_style_values",'xx-small,x-small,small,medium,large,x-large,xx-large',true);this._def("event_elements",'a,img',true);this._def("convert_urls",true);this._def("table_inline_editing",false);this._def("object_resizing",true);this._def("custom_shortcuts",true);this._def("convert_on_click",false);this._def("content_css",'');this._def("fix_list_elements",true);this._def("fix_table_elements",false);this._def("strict_loading_mode",document.contentType=='application/xhtml+xml');this._def("hidden_tab_class",'');this._def("display_tab_class",'');this._def("gecko_spellcheck",false);this._def("hide_selects_on_submit",true);if(this.isMSIE&&!this.isOpera)this.settings.strict_loading_mode=false;if(this.isMSIE&&this.settings['browsers'].indexOf('msie')==-1)return;if(this.isGecko&&this.settings['browsers'].indexOf('gecko')==-1)return;if(this.isSafari&&this.settings['browsers'].indexOf('safari')==-1)return;if(this.isOpera&&this.settings['browsers'].indexOf('opera')==-1)return;baseHREF=tinyMCE.settings['document_base_url'];var h=document.location.href;var p=h.indexOf('://');if(p>0&&document.location.protocol!="file:"){p=h.indexOf('/',p+3);h=h.substring(0,p);if(baseHREF.indexOf('://')==-1)baseHREF=h+baseHREF;tinyMCE.settings['document_base_url']=baseHREF;tinyMCE.settings['document_base_prefix']=h}if(baseHREF.indexOf('?')!=-1)baseHREF=baseHREF.substring(0,baseHREF.indexOf('?'));this.settings['base_href']=baseHREF.substring(0,baseHREF.lastIndexOf('/'))+"/";theme=this.settings['theme'];this.inlineStrict='A|BR|SPAN|BDO|MAP|OBJECT|IMG|TT|I|B|BIG|SMALL|EM|STRONG|DFN|CODE|Q|SAMP|KBD|VAR|CITE|ABBR|ACRONYM|SUB|SUP|#text|#comment';this.inlineTransitional='A|BR|SPAN|BDO|OBJECT|APPLET|IMG|MAP|IFRAME|TT|I|B|U|S|STRIKE|BIG|SMALL|FONT|BASEFONT|EM|STRONG|DFN|CODE|Q|SAMP|KBD|VAR|CITE|ABBR|ACRONYM|SUB|SUP|INPUT|SELECT|TEXTAREA|LABEL|BUTTON|#text|#comment';this.blockElms='H[1-6]|P|DIV|ADDRESS|PRE|FORM|TABLE|LI|OL|UL|TD|BLOCKQUOTE|CENTER|DL|DT|DD|DIR|FIELDSET|FORM|NOSCRIPT|NOFRAMES|MENU|ISINDEX|SAMP';this.blockRegExp=new RegExp("^("+this.blockElms+")$","i");this.posKeyCodes=new Array(13,45,36,35,33,34,37,38,39,40);this.uniqueURL='javascript:void(091039730);';this.uniqueTag='<div id="mceTMPElement" style="display: none">TMP</div>';this.callbacks=new Array('onInit','getInfo','getEditorTemplate','setupContent','onChange','onPageLoad','handleNodeChange','initInstance','execCommand','getControlHTML','handleEvent','cleanup','removeInstance');this.settings['theme_href']=tinyMCE.baseURL+"/themes/"+theme;if(!tinyMCE.isIE||tinyMCE.isOpera)this.settings['force_br_newlines']=false;if(tinyMCE.getParam("popups_css",false)){var cssPath=tinyMCE.getParam("popups_css","");if(cssPath.indexOf('://')==-1&&cssPath.charAt(0)!='/')this.settings['popups_css']=this.documentBasePath+"/"+cssPath;else this.settings['popups_css']=cssPath}else this.settings['popups_css']=tinyMCE.baseURL+"/themes/"+theme+"/css/editor_popup.css";if(tinyMCE.getParam("editor_css",false)){var cssPath=tinyMCE.getParam("editor_css","");if(cssPath.indexOf('://')==-1&&cssPath.charAt(0)!='/')this.settings['editor_css']=this.documentBasePath+"/"+cssPath;else this.settings['editor_css']=cssPath}else{if(this.settings.editor_css!='')this.settings['editor_css']=tinyMCE.baseURL+"/themes/"+theme+"/css/editor_ui.css"}if(tinyMCE.settings['debug']){var msg="Debug: \n";msg+="baseURL: "+this.baseURL+"\n";msg+="documentBasePath: "+this.documentBasePath+"\n";msg+="content_css: "+this.settings['content_css']+"\n";msg+="popups_css: "+this.settings['popups_css']+"\n";msg+="editor_css: "+this.settings['editor_css']+"\n";alert(msg)}if(this.configs.length==0){if(typeof(TinyMCECompressed)=="undefined"){tinyMCE.addEvent(window,"DOMContentLoaded",TinyMCE_Engine.prototype.onLoad);if(tinyMCE.isRealIE){if(document.body)tinyMCE.addEvent(document.body,"readystatechange",TinyMCE_Engine.prototype.onLoad);else tinyMCE.addEvent(document,"readystatechange",TinyMCE_Engine.prototype.onLoad)}tinyMCE.addEvent(window,"load",TinyMCE_Engine.prototype.onLoad);tinyMCE._addUnloadEvents()}}this.loadScript(tinyMCE.baseURL+'/themes/'+this.settings['theme']+'/editor_template'+tinyMCE.srcMode+'.js');this.loadScript(tinyMCE.baseURL+'/langs/'+this.settings['language']+'.js');this.loadCSS(this.settings['editor_css']);var p=tinyMCE.getParam('plugins','',true,',');if(p.length>0){for(var i=0;i<p.length;i++){if(p[i].charAt(0)!='-')this.loadScript(tinyMCE.baseURL+'/plugins/'+p[i]+'/editor_plugin'+tinyMCE.srcMode+'.js')}}if(tinyMCE.getParam('entity_encoding')=='named'){settings['cleanup_entities']=new Array();var entities=tinyMCE.getParam('entities','',true,',');for(var i=0;i<entities.length;i+=2)settings['cleanup_entities']['c'+entities[i]]=entities[i+1]}settings['index']=this.configs.length;this.configs[this.configs.length]=settings;this.loadNextScript();if(this.isIE&&!this.isOpera){try{document.execCommand('BackgroundImageCache',false,true)}catch(e){}}this.xmlEncodeAposRe=new RegExp('[<>&"\']','g');this.xmlEncodeRe=new RegExp('[<>&"]','g');},_addUnloadEvents:function(){if(tinyMCE.isIE){if(tinyMCE.settings['add_unload_trigger']){tinyMCE.addEvent(window,"unload",TinyMCE_Engine.prototype.unloadHandler);tinyMCE.addEvent(window.document,"beforeunload",TinyMCE_Engine.prototype.unloadHandler)}}else{if(tinyMCE.settings['add_unload_trigger'])tinyMCE.addEvent(window,"unload",function(){tinyMCE.triggerSave(true,true)})}},_def:function(key,def_val,t){var v=tinyMCE.getParam(key,def_val);v=t?v.replace(/\s+/g,""):v;this.settings[key]=v},hasPlugin:function(n){return typeof(this.plugins[n])!="undefined"&&this.plugins[n]!=null},addPlugin:function(n,p){var op=this.plugins[n];p.baseURL=op?op.baseURL:tinyMCE.baseURL+"/plugins/"+n;this.plugins[n]=p;this.loadNextScript()},setPluginBaseURL:function(n,u){var op=this.plugins[n];if(op)op.baseURL=u;else this.plugins[n]={baseURL:u}},loadPlugin:function(n,u){u=u.indexOf('.js')!=-1?u.substring(0,u.lastIndexOf('/')):u;u=u.charAt(u.length-1)=='/'?u.substring(0,u.length-1):u;this.plugins[n]={baseURL:u};this.loadScript(u+"/editor_plugin"+(tinyMCE.srcMode?'_src':'')+".js")},hasTheme:function(n){return typeof(this.themes[n])!="undefined"&&this.themes[n]!=null},addTheme:function(n,t){this.themes[n]=t;this.loadNextScript()},addMenu:function(n,m){this.menus[n]=m},hasMenu:function(n){return typeof(this.plugins[n])!="undefined"&&this.plugins[n]!=null},loadScript:function(url){var i;for(i=0;i<this.loadedFiles.length;i++){if(this.loadedFiles[i]==url)return}if(tinyMCE.settings.strict_loading_mode)this.pendingFiles[this.pendingFiles.length]=url;else document.write('<sc'+'ript language="javascript" type="text/javascript" src="'+url+'"></script>');this.loadedFiles[this.loadedFiles.length]=url},loadNextScript:function(){var d=document,se;if(!tinyMCE.settings.strict_loading_mode)return;if(this.loadingIndex<this.pendingFiles.length){se=d.createElementNS('http://www.w3.org/1999/xhtml','script');se.setAttribute('language','javascript');se.setAttribute('type','text/javascript');se.setAttribute('src',this.pendingFiles[this.loadingIndex++]);d.getElementsByTagName("head")[0].appendChild(se)}else this.loadingIndex=-1;},loadCSS:function(url){var ar=url.replace(/\s+/,'').split(',');var lflen=0,csslen=0;var skip=false;var x=0,i=0,nl,le;for(x=0,csslen=ar.length;x<csslen;x++){if(ar[x]!=null&&ar[x]!='null'&&ar[x].length>0){for(i=0,lflen=this.loadedFiles.length;i<lflen;i++){if(this.loadedFiles[i]==ar[x]){skip=true;break}}if(!skip){if(tinyMCE.settings.strict_loading_mode){nl=document.getElementsByTagName("head");le=document.createElement('link');le.setAttribute('href',ar[x]);le.setAttribute('rel','stylesheet');le.setAttribute('type','text/css');nl[0].appendChild(le)}else document.write('<link href="'+ar[x]+'" rel="stylesheet" type="text/css" />');this.loadedFiles[this.loadedFiles.length]=ar[x]}}}},importCSS:function(doc,css){var css_ary=css.replace(/\s+/,'').split(',');var csslen,elm,headArr,x,css_file;for(x=0,csslen=css_ary.length;x<csslen;x++){css_file=css_ary[x];if(css_file!=null&&css_file!='null'&&css_file.length>0){if(css_file.indexOf('://')==-1&&css_file.charAt(0)!='/')css_file=this.documentBasePath+"/"+css_file;if(typeof(doc.createStyleSheet)=="undefined"){elm=doc.createElement("link");elm.rel="stylesheet";elm.href=css_file;if((headArr=doc.getElementsByTagName("head"))!=null&&headArr.length>0)headArr[0].appendChild(elm)}else doc.createStyleSheet(css_file)}}},confirmAdd:function(e,settings){var elm=tinyMCE.isIE?event.srcElement:e.target;var elementId=elm.name?elm.name:elm.id;tinyMCE.settings=settings;if(tinyMCE.settings['convert_on_click']||(!elm.getAttribute('mce_noask')&&confirm(tinyMCELang['lang_edit_confirm'])))tinyMCE.addMCEControl(elm,elementId);elm.setAttribute('mce_noask','true')},updateContent:function(form_element_name){var formElement=document.getElementById(form_element_name);for(var n in tinyMCE.instances){var inst=tinyMCE.instances[n];if(!tinyMCE.isInstance(inst))continue;inst.switchSettings();if(inst.formElement==formElement){var doc=inst.getDoc();tinyMCE._setHTML(doc,inst.formElement.value);if(!tinyMCE.isIE)doc.body.innerHTML=tinyMCE._cleanupHTML(inst,doc,this.settings,doc.body,inst.visualAid)}}},addMCEControl:function(replace_element,form_element_name,target_document){var id="mce_editor_"+tinyMCE.idCounter++;var inst=new TinyMCE_Control(tinyMCE.settings);inst.editorId=id;this.instances[id]=inst;inst._onAdd(replace_element,form_element_name,target_document)},removeInstance:function(ti){var t=[],n,i;for(n in tinyMCE.instances){i=tinyMCE.instances[n];if(tinyMCE.isInstance(i)&&ti!=i)t[n]=i}tinyMCE.instances=t;n=[];t=tinyMCE.undoLevels;for(i=0;i<t.length;i++){if(t[i]!=ti)n.push(t[i])}tinyMCE.undoLevels=n;tinyMCE.undoIndex=n.length;tinyMCE.dispatchCallback(ti,'remove_instance_callback','removeInstance',ti);return ti},removeMCEControl:function(editor_id){var inst=tinyMCE.getInstanceById(editor_id),h,re,ot,tn;if(inst){inst.switchSettings();editor_id=inst.editorId;h=tinyMCE.getContent(editor_id);this.removeInstance(inst);tinyMCE.selectedElement=null;tinyMCE.selectedInstance=null;re=document.getElementById(editor_id+"_parent");ot=inst.oldTargetElement;tn=ot.nodeName.toLowerCase();if(tn=="textarea"||tn=="input"){re.parentNode.removeChild(re);ot.style.display="inline";ot.value=h}else{ot.innerHTML=h;ot.style.display='block';re.parentNode.insertBefore(ot,re);re.parentNode.removeChild(re)}}},triggerSave:function(skip_cleanup,skip_callback){var inst,n;if(typeof(skip_cleanup)=="undefined")skip_cleanup=false;if(typeof(skip_callback)=="undefined")skip_callback=false;for(n in tinyMCE.instances){inst=tinyMCE.instances[n];if(!tinyMCE.isInstance(inst))continue;inst.triggerSave(skip_cleanup,skip_callback)}},resetForm:function(form_index){var i,inst,n,formObj=document.forms[form_index];for(n in tinyMCE.instances){inst=tinyMCE.instances[n];if(!tinyMCE.isInstance(inst))continue;inst.switchSettings();for(i=0;i<formObj.elements.length;i++){if(inst.formTargetElementId==formObj.elements[i].name)inst.getBody().innerHTML=inst.startContent}}},execInstanceCommand:function(editor_id,command,user_interface,value,focus){var inst=tinyMCE.getInstanceById(editor_id),r;if(inst){r=inst.selection.getRng();if(typeof(focus)=="undefined")focus=true;if(focus&&(!r||!r.item))inst.contentWindow.focus();inst.autoResetDesignMode();this.selectedElement=inst.getFocusElement();inst.select();tinyMCE.execCommand(command,user_interface,value);if(tinyMCE.isIE&&window.event!=null)tinyMCE.cancelEvent(window.event)}},execCommand:function(command,user_interface,value){var inst=tinyMCE.selectedInstance;user_interface=user_interface?user_interface:false;value=value?value:null;if(inst)inst.switchSettings();switch(command){case"Undo":if(this.getParam('custom_undo_redo_global')){if(this.undoIndex>0){tinyMCE.nextUndoRedoAction='Undo';inst=this.undoLevels[--this.undoIndex];inst.select();if(!tinyMCE.nextUndoRedoInstanceId)inst.execCommand('Undo')}}else inst.execCommand('Undo');return true;case"Redo":if(this.getParam('custom_undo_redo_global')){if(this.undoIndex<=this.undoLevels.length-1){tinyMCE.nextUndoRedoAction='Redo';inst=this.undoLevels[this.undoIndex++];inst.select();if(!tinyMCE.nextUndoRedoInstanceId)inst.execCommand('Redo')}}else inst.execCommand('Redo');return true;case'mceFocus':var inst=tinyMCE.getInstanceById(value);if(inst)inst.getWin().focus();return;case"mceAddControl":case"mceAddEditor":tinyMCE.addMCEControl(tinyMCE._getElementById(value),value);return;case"mceAddFrameControl":tinyMCE.addMCEControl(tinyMCE._getElementById(value['element'],value['document']),value['element'],value['document']);return;case"mceRemoveControl":case"mceRemoveEditor":tinyMCE.removeMCEControl(value);return;case"mceToggleEditor":var inst=tinyMCE.getInstanceById(value),pe,te;if(inst){pe=document.getElementById(inst.editorId+'_parent');te=inst.oldTargetElement;if(typeof(inst.enabled)=='undefined')inst.enabled=true;inst.enabled=!inst.enabled;if(!inst.enabled){pe.style.display='none';te.value=inst.getHTML();te.style.display=inst.oldTargetDisplay;tinyMCE.dispatchCallback(inst,'hide_instance_callback','hideInstance',inst)}else{pe.style.display='block';te.style.display='none';inst.setHTML(te.value);inst.useCSS=false;tinyMCE.dispatchCallback(inst,'show_instance_callback','showInstance',inst)}}else tinyMCE.addMCEControl(tinyMCE._getElementById(value),value);return;case"mceResetDesignMode":if(!tinyMCE.isIE){for(var n in tinyMCE.instances){if(!tinyMCE.isInstance(tinyMCE.instances[n]))continue;try{tinyMCE.instances[n].getDoc().designMode="on"}catch(e){}}}return}if(inst){inst.execCommand(command,user_interface,value)}else if(tinyMCE.settings['focus_alert'])alert(tinyMCELang['lang_focus_alert'])},_createIFrame:function(replace_element,doc,win){var iframe,id=replace_element.getAttribute("id");var aw,ah;if(typeof(doc)=="undefined")doc=document;if(typeof(win)=="undefined")win=window;iframe=doc.createElement("iframe");aw=""+tinyMCE.settings['area_width'];ah=""+tinyMCE.settings['area_height'];if(aw.indexOf('%')==-1){aw=parseInt(aw);aw=(isNaN(aw)||aw<0)?300:aw;aw=aw+"px"}if(ah.indexOf('%')==-1){ah=parseInt(ah);ah=(isNaN(ah)||ah<0)?240:ah;ah=ah+"px"}iframe.setAttribute("id",id);iframe.setAttribute("name",id);iframe.setAttribute("class","mceEditorIframe");iframe.setAttribute("border","0");iframe.setAttribute("frameBorder","0");iframe.setAttribute("marginWidth","0");iframe.setAttribute("marginHeight","0");iframe.setAttribute("leftMargin","0");iframe.setAttribute("topMargin","0");iframe.setAttribute("width",aw);iframe.setAttribute("height",ah);iframe.setAttribute("allowtransparency","true");iframe.className='mceEditorIframe';if(tinyMCE.settings["auto_resize"])iframe.setAttribute("scrolling","no");if(tinyMCE.isRealIE)iframe.setAttribute("src",this.settings['default_document']);iframe.style.width=aw;iframe.style.height=ah;if(tinyMCE.settings.strict_loading_mode)iframe.style.marginBottom='-5px';if(tinyMCE.isRealIE)replace_element.outerHTML=iframe.outerHTML;else replace_element.parentNode.replaceChild(iframe,replace_element);if(tinyMCE.isRealIE)return win.frames[id];else return iframe},setupContent:function(editor_id){var inst=tinyMCE.instances[editor_id],i;var doc=inst.getDoc();var head=doc.getElementsByTagName('head').item(0);var content=inst.startContent;if(tinyMCE.settings.strict_loading_mode){content=content.replace(/&lt;/g,'<');content=content.replace(/&gt;/g,'>');content=content.replace(/&quot;/g,'"');content=content.replace(/&amp;/g,'&')}tinyMCE.selectedInstance=inst;inst.switchSettings();if(!tinyMCE.isIE&&tinyMCE.getParam("setupcontent_reload",false)&&doc.title!="blank_page"){try{doc.location.href=tinyMCE.baseURL+"/blank.htm"}catch(ex){}window.setTimeout("tinyMCE.setupContent('"+editor_id+"');",1000);return}if(!head){window.setTimeout("tinyMCE.setupContent('"+editor_id+"');",10);return}tinyMCE.importCSS(inst.getDoc(),tinyMCE.baseURL+"/themes/"+inst.settings['theme']+"/css/editor_content.css");tinyMCE.importCSS(inst.getDoc(),inst.settings['content_css']);tinyMCE.dispatchCallback(inst,'init_instance_callback','initInstance',inst);if(tinyMCE.getParam('custom_undo_redo_keyboard_shortcuts')){inst.addShortcut('ctrl','z','lang_undo_desc','Undo');inst.addShortcut('ctrl','y','lang_redo_desc','Redo')}for(i=1;i<=6;i++)inst.addShortcut('ctrl',''+i,'','FormatBlock',false,'<h'+i+'>');inst.addShortcut('ctrl','7','','FormatBlock',false,'<p>');inst.addShortcut('ctrl','8','','FormatBlock',false,'<div>');inst.addShortcut('ctrl','9','','FormatBlock',false,'<address>');if(tinyMCE.isGecko){inst.addShortcut('ctrl','b','lang_bold_desc','Bold');inst.addShortcut('ctrl','i','lang_italic_desc','Italic');inst.addShortcut('ctrl','u','lang_underline_desc','Underline')}if(tinyMCE.getParam("convert_fonts_to_spans"))inst.getBody().setAttribute('id','mceSpanFonts');if(tinyMCE.settings['nowrap'])doc.body.style.whiteSpace="nowrap";doc.body.dir=this.settings['directionality'];doc.editorId=editor_id;if(!tinyMCE.isIE)doc.documentElement.editorId=editor_id;inst.setBaseHREF(tinyMCE.settings['base_href']);if(tinyMCE.settings['convert_newlines_to_brs']){content=tinyMCE.regexpReplace(content,"\r\n","<br />","gi");content=tinyMCE.regexpReplace(content,"\r","<br />","gi");content=tinyMCE.regexpReplace(content,"\n","<br />","gi")}content=tinyMCE.storeAwayURLs(content);content=tinyMCE._customCleanup(inst,"insert_to_editor",content);if(tinyMCE.isIE){window.setInterval('try{tinyMCE.getCSSClasses(tinyMCE.instances["'+editor_id+'"].getDoc(), "'+editor_id+'");}catch(e){}',500);if(tinyMCE.settings["force_br_newlines"])doc.styleSheets[0].addRule("p","margin: 0;");var body=inst.getBody();body.editorId=editor_id}content=tinyMCE.cleanupHTMLCode(content);if(!tinyMCE.isIE){var contentElement=inst.getDoc().createElement("body");var doc=inst.getDoc();contentElement.innerHTML=content;if(tinyMCE.isGecko&&tinyMCE.settings['remove_lt_gt'])content=content.replace(new RegExp('&lt;&gt;','g'),"");if(tinyMCE.settings['cleanup_on_startup'])tinyMCE.setInnerHTML(inst.getBody(),tinyMCE._cleanupHTML(inst,doc,this.settings,contentElement));else tinyMCE.setInnerHTML(inst.getBody(),content);tinyMCE.convertAllRelativeURLs(inst.getBody())}else{if(tinyMCE.settings['cleanup_on_startup']){tinyMCE._setHTML(inst.getDoc(),content);eval('try {tinyMCE.setInnerHTML(inst.getBody(), tinyMCE._cleanupHTML(inst, inst.contentDocument, this.settings, inst.getBody()));} catch(e) {}')}else tinyMCE._setHTML(inst.getDoc(),content)}tinyMCE.handleVisualAid(inst.getBody(),true,tinyMCE.settings['visual'],inst);tinyMCE.dispatchCallback(inst,'setupcontent_callback','setupContent',editor_id,inst.getBody(),inst.getDoc());if(!tinyMCE.isIE)tinyMCE.addEventHandlers(inst);if(tinyMCE.isIE){tinyMCE.addEvent(inst.getBody(),"blur",TinyMCE_Engine.prototype._eventPatch);tinyMCE.addEvent(inst.getBody(),"beforedeactivate",TinyMCE_Engine.prototype._eventPatch);if(!tinyMCE.isOpera){tinyMCE.addEvent(doc.body,"mousemove",TinyMCE_Engine.prototype.onMouseMove);tinyMCE.addEvent(doc.body,"beforepaste",TinyMCE_Engine.prototype._eventPatch);tinyMCE.addEvent(doc.body,"drop",TinyMCE_Engine.prototype._eventPatch)}}inst.select();tinyMCE.selectedElement=inst.contentWindow.document.body;tinyMCE._customCleanup(inst,"insert_to_editor_dom",inst.getBody());tinyMCE._customCleanup(inst,"setup_content_dom",inst.getBody());tinyMCE._setEventsEnabled(inst.getBody(),false);tinyMCE.cleanupAnchors(inst.getDoc());if(tinyMCE.getParam("convert_fonts_to_spans"))tinyMCE.convertSpansToFonts(inst.getDoc());inst.startContent=tinyMCE.trim(inst.getBody().innerHTML);inst.undoRedo.add({content:inst.startContent});if(tinyMCE.isGecko){tinyMCE.selectNodes(inst.getBody(),function(n){if(n.nodeType==3||n.nodeType==8)n.nodeValue=n.nodeValue.replace(new RegExp('\\s(mce_src|mce_href)=\"[^\"]*\"','gi'),"");return false})}if(tinyMCE.isGecko)inst.getBody().spellcheck=tinyMCE.getParam("gecko_spellcheck");tinyMCE._removeInternal(inst.getBody());inst.select();tinyMCE.triggerNodeChange(false,true)},storeAwayURLs:function(s){if(!s.match(/(mce_src|mce_href)/gi,s)){s=s.replace(new RegExp('src\\s*=\\s*\"([^ >\"]*)\"','gi'),'src="$1" mce_src="$1"');s=s.replace(new RegExp('href\\s*=\\s*\"([^ >\"]*)\"','gi'),'href="$1" mce_href="$1"')}return s},_removeInternal:function(n){if(tinyMCE.isGecko){tinyMCE.selectNodes(n,function(n){if(n.nodeType==3||n.nodeType==8)n.nodeValue=n.nodeValue.replace(new RegExp('\\s(mce_src|mce_href)=\"[^\"]*\"','gi'),"");return false})}},removeTinyMCEFormElements:function(form_obj){var i,elementId;if(!tinyMCE.getParam('hide_selects_on_submit'))return;if(typeof(form_obj)=="undefined"||form_obj==null)return;if(form_obj.nodeName!="FORM"){if(form_obj.form)form_obj=form_obj.form;else form_obj=tinyMCE.getParentElement(form_obj,"form")}if(form_obj==null)return;for(i=0;i<form_obj.elements.length;i++){elementId=form_obj.elements[i].name?form_obj.elements[i].name:form_obj.elements[i].id;if(elementId.indexOf('mce_editor_')==0)form_obj.elements[i].disabled=true}},handleEvent:function(e){var inst=tinyMCE.selectedInstance;if(typeof(tinyMCE)=="undefined")return true;if(tinyMCE.executeCallback(tinyMCE.selectedInstance,'handle_event_callback','handleEvent',e))return false;switch(e.type){case"beforedeactivate":case"blur":if(tinyMCE.selectedInstance)tinyMCE.selectedInstance.execCommand('mceEndTyping');tinyMCE.hideMenus();return;case"drop":case"beforepaste":if(tinyMCE.selectedInstance)tinyMCE.selectedInstance.setBaseHREF(null);if(tinyMCE.isRealIE){var ife=tinyMCE.selectedInstance.iframeElement;if(ife.style.height.indexOf('%')!=-1){ife._oldHeight=ife.style.height;ife.style.height=ife.clientHeight}}window.setTimeout("tinyMCE.selectedInstance.setBaseHREF(tinyMCE.settings['base_href']);tinyMCE._resetIframeHeight();",1);return;case"submit":tinyMCE.removeTinyMCEFormElements(tinyMCE.isMSIE?window.event.srcElement:e.target);tinyMCE.triggerSave();tinyMCE.isNotDirty=true;return;case"reset":var formObj=tinyMCE.isIE?window.event.srcElement:e.target;for(var i=0;i<document.forms.length;i++){if(document.forms[i]==formObj)window.setTimeout('tinyMCE.resetForm('+i+');',10)}return;case"keypress":if(inst&&inst.handleShortcut(e))return false;if(e.target.editorId){tinyMCE.instances[e.target.editorId].select()}else{if(e.target.ownerDocument.editorId)tinyMCE.instances[e.target.ownerDocument.editorId].select()}if(tinyMCE.selectedInstance)tinyMCE.selectedInstance.switchSettings();if((tinyMCE.isGecko||tinyMCE.isOpera||tinyMCE.isSafari)&&tinyMCE.settings['force_p_newlines']&&e.keyCode==13&&!e.shiftKey){if(TinyMCE_ForceParagraphs._insertPara(tinyMCE.selectedInstance,e)){tinyMCE.execCommand("mceAddUndoLevel");return tinyMCE.cancelEvent(e)}}if((tinyMCE.isGecko&&!tinyMCE.isSafari)&&tinyMCE.settings['force_p_newlines']&&(e.keyCode==8||e.keyCode==46)&&!e.shiftKey){if(TinyMCE_ForceParagraphs._handleBackSpace(tinyMCE.selectedInstance,e.type)){tinyMCE.execCommand("mceAddUndoLevel");return tinyMCE.cancelEvent(e)}}if(tinyMCE.isIE&&tinyMCE.settings['force_br_newlines']&&e.keyCode==13){if(e.target.editorId)tinyMCE.instances[e.target.editorId].select();if(tinyMCE.selectedInstance){var sel=tinyMCE.selectedInstance.getDoc().selection;var rng=sel.createRange();if(tinyMCE.getParentElement(rng.parentElement(),"li")!=null)return false;e.returnValue=false;e.cancelBubble=true;rng.pasteHTML("<br />");rng.collapse(false);rng.select();tinyMCE.execCommand("mceAddUndoLevel");tinyMCE.triggerNodeChange(false);return false}}if(e.keyCode==8||e.keyCode==46){tinyMCE.selectedElement=e.target;tinyMCE.linkElement=tinyMCE.getParentElement(e.target,"a");tinyMCE.imgElement=tinyMCE.getParentElement(e.target,"img");tinyMCE.triggerNodeChange(false)}return false;break;case"keyup":case"keydown":tinyMCE.hideMenus();tinyMCE.hasMouseMoved=false;if(inst&&inst.handleShortcut(e))return false;if(e.target.editorId)tinyMCE.instances[e.target.editorId].select();if(tinyMCE.selectedInstance)tinyMCE.selectedInstance.switchSettings();var inst=tinyMCE.selectedInstance;if(tinyMCE.isGecko&&tinyMCE.settings['force_p_newlines']&&(e.keyCode==8||e.keyCode==46)&&!e.shiftKey){if(TinyMCE_ForceParagraphs._handleBackSpace(tinyMCE.selectedInstance,e.type)){tinyMCE.execCommand("mceAddUndoLevel");e.preventDefault();return false}}tinyMCE.selectedElement=null;tinyMCE.selectedNode=null;var elm=tinyMCE.selectedInstance.getFocusElement();tinyMCE.linkElement=tinyMCE.getParentElement(elm,"a");tinyMCE.imgElement=tinyMCE.getParentElement(elm,"img");tinyMCE.selectedElement=elm;if(tinyMCE.isGecko&&e.type=="keyup"&&e.keyCode==9)tinyMCE.handleVisualAid(tinyMCE.selectedInstance.getBody(),true,tinyMCE.settings['visual'],tinyMCE.selectedInstance);if(tinyMCE.isIE&&e.type=="keydown"&&e.keyCode==13)tinyMCE.enterKeyElement=tinyMCE.selectedInstance.getFocusElement();if(tinyMCE.isIE&&e.type=="keyup"&&e.keyCode==13){var elm=tinyMCE.enterKeyElement;if(elm){var re=new RegExp('^HR|IMG|BR$','g');var dre=new RegExp('^H[1-6]$','g');if(!elm.hasChildNodes()&&!re.test(elm.nodeName)){if(dre.test(elm.nodeName))elm.innerHTML="&nbsp;&nbsp;";else elm.innerHTML="&nbsp;"}}}var keys=tinyMCE.posKeyCodes;var posKey=false;for(var i=0;i<keys.length;i++){if(keys[i]==e.keyCode){posKey=true;break}}if(tinyMCE.isIE&&tinyMCE.settings['custom_undo_redo']){var keys=new Array(8,46);for(var i=0;i<keys.length;i++){if(keys[i]==e.keyCode){if(e.type=="keyup")tinyMCE.triggerNodeChange(false)}}}if(e.keyCode==17)return true;if(tinyMCE.isGecko){if(!posKey&&e.type=="keyup"&&!e.ctrlKey||(e.ctrlKey&&(e.keyCode==86||e.keyCode==88)))tinyMCE.execCommand("mceStartTyping")}else{if(!posKey&&e.type=="keyup")tinyMCE.execCommand("mceStartTyping")}if(e.type=="keydown"&&(posKey||e.ctrlKey)&&inst)inst.undoBookmark=inst.selection.getBookmark();if(e.type=="keyup"&&(posKey||e.ctrlKey))tinyMCE.execCommand("mceEndTyping");if(posKey&&e.type=="keyup")tinyMCE.triggerNodeChange(false);if(tinyMCE.isIE&&e.ctrlKey)window.setTimeout('tinyMCE.triggerNodeChange(false);',1);break;case"mousedown":case"mouseup":case"click":case"dblclick":case"focus":tinyMCE.hideMenus();if(tinyMCE.selectedInstance){tinyMCE.selectedInstance.switchSettings();tinyMCE.selectedInstance.isFocused=true}var targetBody=tinyMCE.getParentElement(e.target,"html");for(var instanceName in tinyMCE.instances){if(!tinyMCE.isInstance(tinyMCE.instances[instanceName]))continue;var inst=tinyMCE.instances[instanceName];inst.autoResetDesignMode();if(inst.getBody().parentNode==targetBody){inst.select();tinyMCE.selectedElement=e.target;tinyMCE.linkElement=tinyMCE.getParentElement(tinyMCE.selectedElement,"a");tinyMCE.imgElement=tinyMCE.getParentElement(tinyMCE.selectedElement,"img");break}}if(!tinyMCE.selectedInstance.undoRedo.undoLevels[0].bookmark&&(e.type=="mouseup"||e.type=="dblclick"))tinyMCE.selectedInstance.undoRedo.undoLevels[0].bookmark=tinyMCE.selectedInstance.selection.getBookmark();if(e.type!="focus")tinyMCE.selectedNode=null;tinyMCE.triggerNodeChange(false);tinyMCE.execCommand("mceEndTyping");if(e.type=="mouseup")tinyMCE.execCommand("mceAddUndoLevel");if(!tinyMCE.selectedInstance&&e.target.editorId)tinyMCE.instances[e.target.editorId].select();return false;break}},getButtonHTML:function(id,lang,img,cmd,ui,val){var h='',m,x,io='';cmd='tinyMCE.execInstanceCommand(\'{$editor_id}\',\''+cmd+'\'';if(typeof(ui)!="undefined"&&ui!=null)cmd+=','+ui;if(typeof(val)!="undefined"&&val!=null)cmd+=",'"+val+"'";cmd+=');';if(tinyMCE.isRealIE)io='onmouseover="tinyMCE.lastHover = this;"';if(tinyMCE.getParam('button_tile_map')&&(!tinyMCE.isIE||tinyMCE.isOpera)&&(m=this.buttonMap[id])!=null&&(tinyMCE.getParam("language")=="en"||img.indexOf('$lang')==-1)){x=0-(m*20)==0?'0':0-(m*20);h+='<a id="{$editor_id}_'+id+'" href="javascript:'+cmd+'" onclick="'+cmd+'return false;" onmousedown="return false;" '+io+' class="mceTiledButton mceButtonNormal" target="_self">';h+='<img src="{$themeurl}/images/spacer.gif" style="background-position: '+x+'px 0" title="{$'+lang+'}" />';h+='</a>'}else{h+='<a id="{$editor_id}_'+id+'" href="javascript:'+cmd+'" onclick="'+cmd+'return false;" onmousedown="return false;" '+io+' class="mceButtonNormal" target="_self">';h+='<img src="'+img+'" title="{$'+lang+'}" />';h+='</a>'}return h},getMenuButtonHTML:function(id,lang,img,mcmd,cmd,ui,val){var h='',m,x;mcmd='tinyMCE.execInstanceCommand(\'{$editor_id}\',\''+mcmd+'\');';cmd='tinyMCE.execInstanceCommand(\'{$editor_id}\',\''+cmd+'\'';if(typeof(ui)!="undefined"&&ui!=null)cmd+=','+ui;if(typeof(val)!="undefined"&&val!=null)cmd+=",'"+val+"'";cmd+=');';if(tinyMCE.getParam('button_tile_map')&&(!tinyMCE.isIE||tinyMCE.isOpera)&&(m=tinyMCE.buttonMap[id])!=null&&(tinyMCE.getParam("language")=="en"||img.indexOf('$lang')==-1)){x=0-(m*20)==0?'0':0-(m*20);if(tinyMCE.isRealIE)h+='<span id="{$editor_id}_'+id+'" class="mceMenuButton" onmouseover="tinyMCE._menuButtonEvent(\'over\',this);tinyMCE.lastHover = this;" onmouseout="tinyMCE._menuButtonEvent(\'out\',this);">';else h+='<span id="{$editor_id}_'+id+'" class="mceMenuButton">';h+='<a href="javascript:'+cmd+'" onclick="'+cmd+'return false;" onmousedown="return false;" class="mceTiledButton mceMenuButtonNormal" target="_self">';h+='<img src="{$themeurl}/images/spacer.gif" style="width: 20px; height: 20px; background-position: '+x+'px 0" title="{$'+lang+'}" /></a>';h+='<a href="javascript:'+mcmd+'" onclick="'+mcmd+'return false;" onmousedown="return false;"><img src="{$themeurl}/images/button_menu.gif" title="{$'+lang+'}" class="mceMenuButton" />';h+='</a></span>'}else{if(tinyMCE.isRealIE)h+='<span id="{$editor_id}_'+id+'" dir="ltr" class="mceMenuButton" onmouseover="tinyMCE._menuButtonEvent(\'over\',this);tinyMCE.lastHover = this;" onmouseout="tinyMCE._menuButtonEvent(\'out\',this);">';else h+='<span id="{$editor_id}_'+id+'" dir="ltr" class="mceMenuButton">';h+='<a href="javascript:'+cmd+'" onclick="'+cmd+'return false;" onmousedown="return false;" class="mceMenuButtonNormal" target="_self">';h+='<img src="'+img+'" title="{$'+lang+'}" /></a>';h+='<a href="javascript:'+mcmd+'" onclick="'+mcmd+'return false;" onmousedown="return false;"><img src="{$themeurl}/images/button_menu.gif" title="{$'+lang+'}" class="mceMenuButton" />';h+='</a></span>'}return h},_menuButtonEvent:function(e,o){if(o.className=='mceMenuButtonFocus')return;if(e=='over')o.className=o.className+' mceMenuHover';else o.className=o.className.replace(/\s.*$/,'')},addButtonMap:function(m){var i,a=m.replace(/\s+/,'').split(',');for(i=0;i<a.length;i++)this.buttonMap[a[i]]=i},submitPatch:function(){tinyMCE.removeTinyMCEFormElements(this);tinyMCE.triggerSave();tinyMCE.isNotDirty=true;this.mceOldSubmit()},onLoad:function(){var r;if(tinyMCE.settings.strict_loading_mode&&this.loadingIndex!=-1){window.setTimeout('tinyMCE.onLoad();',1);return}if(tinyMCE.isRealIE&&window.event.type=="readystatechange"&&document.readyState!="complete")return true;if(tinyMCE.isLoaded)return true;tinyMCE.isLoaded=true;if(tinyMCE.isRealIE&&document.body){r=document.body.createTextRange();r.collapse(true);r.select()}tinyMCE.dispatchCallback(null,'onpageload','onPageLoad');for(var c=0;c<tinyMCE.configs.length;c++){tinyMCE.settings=tinyMCE.configs[c];var selector=tinyMCE.getParam("editor_selector");var deselector=tinyMCE.getParam("editor_deselector");var elementRefAr=new Array();if(document.forms&&tinyMCE.settings['add_form_submit_trigger']&&!tinyMCE.submitTriggers){for(var i=0;i<document.forms.length;i++){var form=document.forms[i];tinyMCE.addEvent(form,"submit",TinyMCE_Engine.prototype.handleEvent);tinyMCE.addEvent(form,"reset",TinyMCE_Engine.prototype.handleEvent);tinyMCE.submitTriggers=true;if(tinyMCE.settings['submit_patch']){try{form.mceOldSubmit=form.submit;form.submit=TinyMCE_Engine.prototype.submitPatch}catch(e){}}}}var mode=tinyMCE.settings['mode'];switch(mode){case"exact":var elements=tinyMCE.getParam('elements','',true,',');for(var i=0;i<elements.length;i++){var element=tinyMCE._getElementById(elements[i]);var trigger=element?element.getAttribute(tinyMCE.settings['textarea_trigger']):"";if(new RegExp('\\b'+deselector+'\\b').test(tinyMCE.getAttrib(element,"class")))continue;if(trigger=="false")continue;if((tinyMCE.settings['ask']||tinyMCE.settings['convert_on_click'])&&element){elementRefAr[elementRefAr.length]=element;continue}if(element)tinyMCE.addMCEControl(element,elements[i]);else if(tinyMCE.settings['debug'])alert("Error: Could not find element by id or name: "+elements[i])}break;case"specific_textareas":case"textareas":var nodeList=document.getElementsByTagName("textarea");for(var i=0;i<nodeList.length;i++){var elm=nodeList.item(i);var trigger=elm.getAttribute(tinyMCE.settings['textarea_trigger']);if(selector!=''&&!new RegExp('\\b'+selector+'\\b').test(tinyMCE.getAttrib(elm,"class")))continue;if(selector!='')trigger=selector!=""?"true":"";if(new RegExp('\\b'+deselector+'\\b').test(tinyMCE.getAttrib(elm,"class")))continue;if((mode=="specific_textareas"&&trigger=="true")||(mode=="textareas"&&trigger!="false"))elementRefAr[elementRefAr.length]=elm}break}for(var i=0;i<elementRefAr.length;i++){var element=elementRefAr[i];var elementId=element.name?element.name:element.id;if(tinyMCE.settings['ask']||tinyMCE.settings['convert_on_click']){if(tinyMCE.isGecko){var settings=tinyMCE.settings;tinyMCE.addEvent(element,"focus",function(e){window.setTimeout(function(){TinyMCE_Engine.prototype.confirmAdd(e,settings)},10)});if(element.nodeName!="TEXTAREA"&&element.nodeName!="INPUT")tinyMCE.addEvent(element,"click",function(e){window.setTimeout(function(){TinyMCE_Engine.prototype.confirmAdd(e,settings)},10)});}else{var settings=tinyMCE.settings;tinyMCE.addEvent(element,"focus",function(){TinyMCE_Engine.prototype.confirmAdd(null,settings)});tinyMCE.addEvent(element,"click",function(){TinyMCE_Engine.prototype.confirmAdd(null,settings)});}}else tinyMCE.addMCEControl(element,elementId)}if(tinyMCE.settings['auto_focus']){window.setTimeout(function(){var inst=tinyMCE.getInstanceById(tinyMCE.settings['auto_focus']);inst.selection.selectNode(inst.getBody(),true,true);inst.contentWindow.focus()},100)}tinyMCE.dispatchCallback(null,'oninit','onInit')}},isInstance:function(o){return o!=null&&typeof(o)=="object"&&o.isTinyMCE_Control},getParam:function(name,default_value,strip_whitespace,split_chr){var value=(typeof(this.settings[name])=="undefined")?default_value:this.settings[name];if(value=="true"||value=="false")return(value=="true");if(strip_whitespace)value=tinyMCE.regexpReplace(value,"[ \t\r\n]","");if(typeof(split_chr)!="undefined"&&split_chr!=null){value=value.split(split_chr);var outArray=new Array();for(var i=0;i<value.length;i++){if(value[i]&&value[i]!="")outArray[outArray.length]=value[i]}value=outArray}return value},getLang:function(name,default_value,parse_entities,va){var v=(typeof(tinyMCELang[name])=="undefined")?default_value:tinyMCELang[name],n;if(parse_entities)v=tinyMCE.entityDecode(v);if(va){for(n in va)v=this.replaceVar(v,n,va[n])}return v},entityDecode:function(s){var e=document.createElement("div");e.innerHTML=s;return e.firstChild.nodeValue},addToLang:function(prefix,ar){for(var key in ar){if(typeof(ar[key])=='function')continue;tinyMCELang[(key.indexOf('lang_')==-1?'lang_':'')+(prefix!=''?(prefix+"_"):'')+key]=ar[key]}this.loadNextScript();},triggerNodeChange:function(focus,setup_content){var elm,inst,editorId,undoIndex=-1,undoLevels=-1,doc,anySelection=false,st;if(tinyMCE.selectedInstance){inst=tinyMCE.selectedInstance;elm=(typeof(setup_content)!="undefined"&&setup_content)?tinyMCE.selectedElement:inst.getFocusElement();editorId=inst.editorId;st=inst.selection.getSelectedText();if(tinyMCE.settings.auto_resize)inst.resizeToContent();if(setup_content&&tinyMCE.isGecko&&inst.isHidden())elm=inst.getBody();inst.switchSettings();if(tinyMCE.selectedElement)anySelection=(tinyMCE.selectedElement.nodeName.toLowerCase()=="img")||(st&&st.length>0);if(tinyMCE.settings['custom_undo_redo']){undoIndex=inst.undoRedo.undoIndex;undoLevels=inst.undoRedo.undoLevels.length}tinyMCE.dispatchCallback(inst,'handle_node_change_callback','handleNodeChange',editorId,elm,undoIndex,undoLevels,inst.visualAid,anySelection,setup_content)}if(this.selectedInstance&&(typeof(focus)=="undefined"||focus))this.selectedInstance.contentWindow.focus()},_customCleanup:function(inst,type,content){var pl,po,i;var customCleanup=tinyMCE.settings['cleanup_callback'];if(customCleanup!=""&&eval("typeof("+customCleanup+")")!="undefined")content=eval(customCleanup+"(type, content, inst);");po=tinyMCE.themes[tinyMCE.settings['theme']];if(po&&po.cleanup)content=po.cleanup(type,content,inst);pl=inst.plugins;for(i=0;i<pl.length;i++){po=tinyMCE.plugins[pl[i]];if(po&&po.cleanup)content=po.cleanup(type,content,inst)}return content},setContent:function(h){if(tinyMCE.selectedInstance){tinyMCE.selectedInstance.execCommand('mceSetContent',false,h);tinyMCE.selectedInstance.repaint()}},importThemeLanguagePack:function(name){if(typeof(name)=="undefined")name=tinyMCE.settings['theme'];tinyMCE.loadScript(tinyMCE.baseURL+'/themes/'+name+'/langs/'+tinyMCE.settings['language']+'.js')},importPluginLanguagePack:function(name){var b=tinyMCE.baseURL+'/plugins/'+name;if(this.plugins[name])b=this.plugins[name].baseURL;tinyMCE.loadScript(b+'/langs/'+tinyMCE.settings['language']+'.js')},applyTemplate:function(h,as){return h.replace(new RegExp('\\{\\$([a-z0-9_]+)\\}','gi'),function(m,s){if(s.indexOf('lang_')==0&&tinyMCELang[s])return tinyMCELang[s];if(as&&as[s])return as[s];if(tinyMCE.settings[s])return tinyMCE.settings[s];if(m=='themeurl')return tinyMCE.themeURL;return m})},replaceVar:function(h,r,v){return h.replace(new RegExp('{\\\$'+r+'}','g'),v)},openWindow:function(template,args){var html,width,height,x,y,resizable,scrollbars,url;args=!args?{}:args;args['mce_template_file']=template['file'];args['mce_width']=template['width'];args['mce_height']=template['height'];tinyMCE.windowArgs=args;html=template['html'];if(!(width=parseInt(template['width'])))width=320;if(!(height=parseInt(template['height'])))height=200;if(tinyMCE.isIE)height+=40;else height+=20;x=parseInt(screen.width/ 2.0) - (width /2.0);y=parseInt(screen.height/ 2.0) - (height /2.0);resizable=(args&&args['resizable'])?args['resizable']:"no";scrollbars=(args&&args['scrollbars'])?args['scrollbars']:"no";if(template['file'].charAt(0)!='/'&&template['file'].indexOf('://')==-1)url=tinyMCE.baseURL+"/themes/"+tinyMCE.getParam("theme")+"/"+template['file'];else url=template['file'];for(var name in args){if(typeof(args[name])=='function')continue;url=tinyMCE.replaceVar(url,name,escape(args[name]))}if(html){html=tinyMCE.replaceVar(html,"css",this.settings['popups_css']);html=tinyMCE.applyTemplate(html,args);var win=window.open("","mcePopup"+new Date().getTime(),"top="+y+",left="+x+",scrollbars="+scrollbars+",dialog=yes,minimizable="+resizable+",modal=yes,width="+width+",height="+height+",resizable="+resizable);if(win==null){alert(tinyMCELang['lang_popup_blocked']);return}win.document.write(html);win.document.close();win.resizeTo(width,height);win.focus()}else{if((tinyMCE.isRealIE)&&resizable!='yes'&&tinyMCE.settings["dialog_type"]=="modal"){height+=10;var features="resizable:"+resizable+";scroll:"+scrollbars+";status:yes;center:yes;help:no;dialogWidth:"+width+"px;dialogHeight:"+height+"px;";window.showModalDialog(url,window,features)}else{var modal=(resizable=="yes")?"no":"yes";if(tinyMCE.isGecko&&tinyMCE.isMac)modal="no";if(template['close_previous']!="no")try{tinyMCE.lastWindow.close()}catch(ex){}var win=window.open(url,"mcePopup"+new Date().getTime(),"top="+y+",left="+x+",scrollbars="+scrollbars+",dialog="+modal+",minimizable="+resizable+",modal="+modal+",width="+width+",height="+height+",resizable="+resizable);if(win==null){alert(tinyMCELang['lang_popup_blocked']);return}if(template['close_previous']!="no")tinyMCE.lastWindow=win;eval('try { win.resizeTo(width, height); } catch(e) { }');if(tinyMCE.isGecko){if(win.document.defaultView.statusbar.visible)win.resizeBy(0,tinyMCE.isMac?10:24)}win.focus()}}},closeWindow:function(win){win.close()},getVisualAidClass:function(class_name,state){var aidClass=tinyMCE.settings['visual_table_class'];if(typeof(state)=="undefined")state=tinyMCE.settings['visual'];var classNames=new Array();var ar=class_name.split(' ');for(var i=0;i<ar.length;i++){if(ar[i]==aidClass)ar[i]="";if(ar[i]!="")classNames[classNames.length]=ar[i]}if(state)classNames[classNames.length]=aidClass;var className="";for(var i=0;i<classNames.length;i++){if(i>0)className+=" ";className+=classNames[i]}return className},handleVisualAid:function(el,deep,state,inst,skip_dispatch){if(!el)return;if(!skip_dispatch)tinyMCE.dispatchCallback(inst,'handle_visual_aid_callback','handleVisualAid',el,deep,state,inst);var tableElement=null;switch(el.nodeName){case"TABLE":var oldW=el.style.width;var oldH=el.style.height;var bo=tinyMCE.getAttrib(el,"border");bo=bo==""||bo=="0"?true:false;tinyMCE.setAttrib(el,"class",tinyMCE.getVisualAidClass(tinyMCE.getAttrib(el,"class"),state&&bo));el.style.width=oldW;el.style.height=oldH;for(var y=0;y<el.rows.length;y++){for(var x=0;x<el.rows[y].cells.length;x++){var cn=tinyMCE.getVisualAidClass(tinyMCE.getAttrib(el.rows[y].cells[x],"class"),state&&bo);tinyMCE.setAttrib(el.rows[y].cells[x],"class",cn)}}break;case"A":var anchorName=tinyMCE.getAttrib(el,"name");if(anchorName!=''&&state){el.title=anchorName;tinyMCE.addCSSClass(el,'mceItemAnchor')}else if(anchorName!=''&&!state)el.className='';break}if(deep&&el.hasChildNodes()){for(var i=0;i<el.childNodes.length;i++)tinyMCE.handleVisualAid(el.childNodes[i],deep,state,inst,true)}},fixGeckoBaseHREFBug:function(m,e,h){var xsrc,xhref;if(tinyMCE.isGecko){if(m==1){h=h.replace(/\ssrc=/gi," mce_tsrc=");h=h.replace(/\shref=/gi," mce_thref=");return h}else{if(!new RegExp('(src|href)=','g').test(h))return h;tinyMCE.selectElements(e,'A,IMG,SELECT,AREA,IFRAME,BASE,INPUT,SCRIPT,EMBED,OBJECT,LINK',function(n){xsrc=tinyMCE.getAttrib(n,"mce_tsrc");xhref=tinyMCE.getAttrib(n,"mce_thref");if(xsrc!=""){try{n.src=tinyMCE.convertRelativeToAbsoluteURL(tinyMCE.settings['base_href'],xsrc)}catch(e){}n.removeAttribute("mce_tsrc")}if(xhref!=""){try{n.href=tinyMCE.convertRelativeToAbsoluteURL(tinyMCE.settings['base_href'],xhref)}catch(e){}n.removeAttribute("mce_thref")}return false});tinyMCE.selectNodes(e,function(n){if(n.nodeType==3||n.nodeType==8){n.nodeValue=n.nodeValue.replace(/\smce_tsrc=/gi," src=");n.nodeValue=n.nodeValue.replace(/\smce_thref=/gi," href=")}return false})}}return h},_setHTML:function(doc,html_content){html_content=tinyMCE.cleanupHTMLCode(html_content);try{tinyMCE.setInnerHTML(doc.body,html_content)}catch(e){if(this.isMSIE)doc.body.createTextRange().pasteHTML(html_content)}if(tinyMCE.isIE&&tinyMCE.settings['fix_content_duplication']){var paras=doc.getElementsByTagName("P");for(var i=0;i<paras.length;i++){var node=paras[i];while((node=node.parentNode)!=null){if(node.nodeName=="P")node.outerHTML=node.innerHTML}}var html=doc.body.innerHTML;tinyMCE.setInnerHTML(doc.body,html)}tinyMCE.cleanupAnchors(doc);if(tinyMCE.getParam("convert_fonts_to_spans"))tinyMCE.convertSpansToFonts(doc)},getEditorId:function(form_element){var inst=this.getInstanceById(form_element);if(!inst)return null;return inst.editorId},getInstanceById:function(editor_id){var inst=this.instances[editor_id];if(!inst){for(var n in tinyMCE.instances){var instance=tinyMCE.instances[n];if(!tinyMCE.isInstance(instance))continue;if(instance.formTargetElementId==editor_id){inst=instance;break}}}return inst},queryInstanceCommandValue:function(editor_id,command){var inst=tinyMCE.getInstanceById(editor_id);if(inst)return inst.queryCommandValue(command);return false},queryInstanceCommandState:function(editor_id,command){var inst=tinyMCE.getInstanceById(editor_id);if(inst)return inst.queryCommandState(command);return null},setWindowArg:function(n,v){this.windowArgs[n]=v},getWindowArg:function(n,d){return(typeof(this.windowArgs[n])=="undefined")?d:this.windowArgs[n]},getCSSClasses:function(editor_id,doc){var inst=tinyMCE.getInstanceById(editor_id);if(inst&&inst.cssClasses.length>0)return inst.cssClasses;if(typeof(editor_id)=="undefined"&&typeof(doc)=="undefined"){var instance;for(var instanceName in tinyMCE.instances){instance=tinyMCE.instances[instanceName];if(!tinyMCE.isInstance(instance))continue;break}doc=instance.getDoc()}if(typeof(doc)=="undefined"){var instance=tinyMCE.getInstanceById(editor_id);doc=instance.getDoc()}if(doc){var styles=doc.styleSheets;if(styles&&styles.length>0){for(var x=0;x<styles.length;x++){var csses=null;eval("try {var csses = tinyMCE.isIE ? doc.styleSheets("+x+").rules : styles["+x+"].cssRules;} catch(e) {}");if(!csses)return new Array();for(var i=0;i<csses.length;i++){var selectorText=csses[i].selectorText;if(selectorText){var rules=selectorText.split(',');for(var c=0;c<rules.length;c++){var rule=rules[c];while(rule.indexOf(' ')==0)rule=rule.substring(1);if(rule.indexOf(' ')!=-1||rule.indexOf(':')!=-1||rule.indexOf('mceItem')!=-1)continue;if(rule.indexOf(tinyMCE.settings['visual_table_class'])!=-1||rule.indexOf('mceEditable')!=-1||rule.indexOf('mceNonEditable')!=-1)continue;if(rule.indexOf('.')!=-1){var cssClass=rule.substring(rule.indexOf('.')+1);var addClass=true;for(var p=0;p<inst.cssClasses.length&&addClass;p++){if(inst.cssClasses[p]==cssClass)addClass=false}if(addClass)inst.cssClasses[inst.cssClasses.length]=cssClass}}}}}}}return inst.cssClasses},regexpReplace:function(in_str,reg_exp,replace_str,opts){if(in_str==null)return in_str;if(typeof(opts)=="undefined")opts='g';var re=new RegExp(reg_exp,opts);return in_str.replace(re,replace_str)},trim:function(s){return s.replace(/^\s*|\s*$/g,"")},cleanupEventStr:function(s){s=""+s;s=s.replace('function anonymous()\n{\n','');s=s.replace('\n}','');s=s.replace(/^return true;/gi,'');return s},getControlHTML:function(c){var i,l,n,o,v,rtl=tinyMCE.getLang('lang_dir')=='rtl';l=tinyMCE.plugins;for(n in l){o=l[n];if(o.getControlHTML&&(v=o.getControlHTML(c))!=''){if(rtl)return'<span dir="rtl">'+tinyMCE.replaceVar(v,"pluginurl",o.baseURL)+'</span>';return tinyMCE.replaceVar(v,"pluginurl",o.baseURL)}}o=tinyMCE.themes[tinyMCE.settings['theme']];if(o.getControlHTML&&(v=o.getControlHTML(c))!=''){if(rtl)return'<span dir="rtl">'+v+'</span>';return v}return''},evalFunc:function(f,idx,a,o){o=!o?window:o;f=typeof(f)=='function'?f:o[f];return f.apply(o,Array.prototype.slice.call(a,idx))},dispatchCallback:function(i,p,n){return this.callFunc(i,p,n,0,this.dispatchCallback.arguments)},executeCallback:function(i,p,n){return this.callFunc(i,p,n,1,this.executeCallback.arguments)},execCommandCallback:function(i,p,n){return this.callFunc(i,p,n,2,this.execCommandCallback.arguments)},callFunc:function(ins,p,n,m,a){var l,i,on,o,s,v;s=m==2;l=tinyMCE.getParam(p,'');if(l!=''&&(v=tinyMCE.evalFunc(l,3,a))==s&&m>0)return true;if(ins!=null){for(i=0,l=ins.plugins;i<l.length;i++){o=tinyMCE.plugins[l[i]];if(o[n]&&(v=tinyMCE.evalFunc(n,3,a,o))==s&&m>0)return true}}l=tinyMCE.themes;for(on in l){o=l[on];if(o[n]&&(v=tinyMCE.evalFunc(n,3,a,o))==s&&m>0)return true}return false},xmlEncode:function(s,skip_apos){return s?(''+s).replace(!skip_apos?this.xmlEncodeAposRe:this.xmlEncodeRe,function(c,b){switch(c){case'&':return'&amp;';case'"':return'&quot;';case'\'':return'&#39;';case'<':return'&lt;';case'>':return'&gt;'}return c}):s},extend:function(p,np){var o={};o.parent=p;for(n in p)o[n]=p[n];for(n in np)o[n]=np[n];return o},hideMenus:function(){var e=tinyMCE.lastSelectedMenuBtn;if(tinyMCE.lastMenu){tinyMCE.lastMenu.hide();tinyMCE.lastMenu=null}if(e){tinyMCE.switchClass(e,tinyMCE.lastMenuBtnClass);tinyMCE.lastSelectedMenuBtn=null}}};var TinyMCE=TinyMCE_Engine;var tinyMCE=new TinyMCE_Engine();var tinyMCELang={};function TinyMCE_Control(settings){var t,i,to,fu,p,x,fn,fu,pn,s=settings;this.undoRedoLevel=true;this.isTinyMCE_Control=true;this.settings=s;this.settings['theme']=tinyMCE.getParam("theme","default");this.settings['width']=tinyMCE.getParam("width",-1);this.settings['height']=tinyMCE.getParam("height",-1);this.selection=new TinyMCE_Selection(this);this.undoRedo=new TinyMCE_UndoRedo(this);this.cleanup=new TinyMCE_Cleanup();this.shortcuts=new Array();this.hasMouseMoved=false;this.foreColor=this.backColor="#999999";this.data={};this.cssClasses=[];this.cleanup.init({valid_elements:s.valid_elements,extended_valid_elements:s.extended_valid_elements,valid_child_elements:s.valid_child_elements,entities:s.entities,entity_encoding:s.entity_encoding,debug:s.cleanup_debug,indent:s.apply_source_formatting,invalid_elements:s.invalid_elements,verify_html:s.verify_html,fix_content_duplication:s.fix_content_duplication,convert_fonts_to_spans:s.convert_fonts_to_spans});t=this.settings['theme'];if(!tinyMCE.hasTheme(t)){fn=tinyMCE.callbacks;to={};for(i=0;i<fn.length;i++){if((fu=window['TinyMCE_'+t+"_"+fn[i]]))to[fn[i]]=fu}tinyMCE.addTheme(t,to)}this.plugins=new Array();p=tinyMCE.getParam('plugins','',true,',');if(p.length>0){for(i=0;i<p.length;i++){pn=p[i];if(pn.charAt(0)=='-')pn=pn.substring(1);if(!tinyMCE.hasPlugin(pn)){fn=tinyMCE.callbacks;to={};for(x=0;x<fn.length;x++){if((fu=window['TinyMCE_'+pn+"_"+fn[x]]))to[fn[x]]=fu}tinyMCE.addPlugin(pn,to)}this.plugins[this.plugins.length]=pn}}};TinyMCE_Control.prototype={selection:null,settings:null,cleanup:null,getData:function(na){var o=this.data[na];if(!o)o=this.data[na]={};return o},hasPlugin:function(n){var i;for(i=0;i<this.plugins.length;i++){if(this.plugins[i]==n)return true}return false},addPlugin:function(n,p){if(!this.hasPlugin(n)){tinyMCE.addPlugin(n,p);this.plugins[this.plugins.length]=n}},repaint:function(){var s,b,ex;if(tinyMCE.isRealIE)return;try{s=this.selection;b=s.getBookmark(true);this.getBody().style.display='none';this.getDoc().execCommand('selectall',false,null);this.getSel().collapseToStart();this.getBody().style.display='block';s.moveToBookmark(b)}catch(ex){}},switchSettings:function(){if(tinyMCE.configs.length>1&&tinyMCE.currentConfig!=this.settings['index']){tinyMCE.settings=this.settings;tinyMCE.currentConfig=this.settings['index']}},select:function(){var oldInst=tinyMCE.selectedInstance;if(oldInst!=this){if(oldInst)oldInst.execCommand('mceEndTyping');tinyMCE.dispatchCallback(this,'select_instance_callback','selectInstance',this,oldInst);tinyMCE.selectedInstance=this}},getBody:function(){return this.contentBody?this.contentBody:this.getDoc().body},getDoc:function(){return this.contentWindow.document},getWin:function(){return this.contentWindow},getContainerWin:function(){return this.containerWindow?this.containerWindow:window},getViewPort:function(){return tinyMCE.getViewPort(this.getWin())},getParentNode:function(n,f){return tinyMCE.getParentNode(n,f,this.getBody())},getParentElement:function(n,na,f){return tinyMCE.getParentElement(n,na,f,this.getBody())},getParentBlockElement:function(n){return tinyMCE.getParentBlockElement(n,this.getBody())},resizeToContent:function(){var d=this.getDoc(),b=d.body,de=d.documentElement;this.iframeElement.style.height=(tinyMCE.isRealIE)?b.scrollHeight:de.offsetHeight+'px'},addShortcut:function(m,k,d,cmd,ui,va){var n=typeof(k)=="number",ie=tinyMCE.isIE,c,sc,i,scl=this.shortcuts;if(!tinyMCE.getParam('custom_shortcuts'))return false;m=m.toLowerCase();k=ie&&!n?k.toUpperCase():k;c=n?null:k.charCodeAt(0);d=d&&d.indexOf('lang_')==0?tinyMCE.getLang(d):d;sc={alt:m.indexOf('alt')!=-1,ctrl:m.indexOf('ctrl')!=-1,shift:m.indexOf('shift')!=-1,charCode:c,keyCode:n?k:(ie?c:null),desc:d,cmd:cmd,ui:ui,val:va};for(i=0;i<scl.length;i++){if(sc.alt==scl[i].alt&&sc.ctrl==scl[i].ctrl&&sc.shift==scl[i].shift&&sc.charCode==scl[i].charCode&&sc.keyCode==scl[i].keyCode){return false}}scl[scl.length]=sc;return true},handleShortcut:function(e){var i,s,o;if(!e.altKey&&!e.ctrlKey)return false;s=this.shortcuts;for(i=0;i<s.length;i++){o=s[i];if(o.alt==e.altKey&&o.ctrl==e.ctrlKey&&(o.keyCode==e.keyCode||o.charCode==e.charCode)){if(o.cmd&&(e.type=="keydown"||(e.type=="keypress"&&!tinyMCE.isOpera)))tinyMCE.execCommand(o.cmd,o.ui,o.val);tinyMCE.cancelEvent(e);return true}}return false},autoResetDesignMode:function(){if(!tinyMCE.isIE&&this.isHidden()&&tinyMCE.getParam('auto_reset_designmode'))eval('try { this.getDoc().designMode = "On"; this.useCSS = false; } catch(e) {}')},isHidden:function(){var s;if(tinyMCE.isIE)return false;s=this.getSel();return(!s||!s.rangeCount||s.rangeCount==0)},isDirty:function(){return tinyMCE.trim(this.startContent)!=tinyMCE.trim(this.getBody().innerHTML)&&!tinyMCE.isNotDirty},_mergeElements:function(scmd,pa,ch,override){if(scmd=="removeformat"){pa.className="";pa.style.cssText="";ch.className="";ch.style.cssText="";return}var st=tinyMCE.parseStyle(tinyMCE.getAttrib(pa,"style"));var stc=tinyMCE.parseStyle(tinyMCE.getAttrib(ch,"style"));var className=tinyMCE.getAttrib(pa,"class");className=tinyMCE.getAttrib(ch,"class");if(override){for(var n in st){if(typeof(st[n])=='function')continue;stc[n]=st[n]}}else{for(var n in stc){if(typeof(stc[n])=='function')continue;st[n]=stc[n]}}tinyMCE.setAttrib(pa,"style",tinyMCE.serializeStyle(st));tinyMCE.setAttrib(pa,"class",tinyMCE.trim(className));ch.className="";ch.style.cssText="";ch.removeAttribute("class");ch.removeAttribute("style")},_setUseCSS:function(b){var d=this.getDoc();try{d.execCommand("useCSS",false,!b)}catch(ex){}try{d.execCommand("styleWithCSS",false,b)}catch(ex){}if(!tinyMCE.getParam("table_inline_editing"))try{d.execCommand('enableInlineTableEditing',false,"false")}catch(ex){}if(!tinyMCE.getParam("object_resizing"))try{d.execCommand('enableObjectResizing',false,"false")}catch(ex){}},execCommand:function(command,user_interface,value){var doc=this.getDoc(),win=this.getWin(),focusElm=this.getFocusElement();if(!new RegExp('mceStartTyping|mceEndTyping|mceBeginUndoLevel|mceEndUndoLevel|mceAddUndoLevel','gi').test(command))this.undoBookmark=null;if(!tinyMCE.isIE&&!this.useCSS){this._setUseCSS(false);this.useCSS=true}this.contentDocument=doc;if(!/mceStartTyping|mceEndTyping/.test(command)){if(tinyMCE.execCommandCallback(this,'execcommand_callback','execCommand',this.editorId,this.getBody(),command,user_interface,value))return}if(focusElm&&focusElm.nodeName=="IMG"){var align=focusElm.getAttribute('align');var img=command=="JustifyCenter"?focusElm.cloneNode(false):focusElm;switch(command){case"JustifyLeft":if(align=='left')img.removeAttribute('align');else img.setAttribute('align','left');var div=focusElm.parentNode;if(div&&div.nodeName=="DIV"&&div.childNodes.length==1&&div.parentNode)div.parentNode.replaceChild(img,div);this.selection.selectNode(img);this.repaint();tinyMCE.triggerNodeChange();return;case"JustifyCenter":img.removeAttribute('align');var div=tinyMCE.getParentElement(focusElm,"div");if(div&&div.style.textAlign=="center"){if(div.nodeName=="DIV"&&div.childNodes.length==1&&div.parentNode)div.parentNode.replaceChild(img,div)}else{var div=this.getDoc().createElement("div");div.style.textAlign='center';div.appendChild(img);focusElm.parentNode.replaceChild(div,focusElm)}this.selection.selectNode(img);this.repaint();tinyMCE.triggerNodeChange();return;case"JustifyRight":if(align=='right')img.removeAttribute('align');else img.setAttribute('align','right');var div=focusElm.parentNode;if(div&&div.nodeName=="DIV"&&div.childNodes.length==1&&div.parentNode)div.parentNode.replaceChild(img,div);this.selection.selectNode(img);this.repaint();tinyMCE.triggerNodeChange();return}}if(tinyMCE.settings['force_br_newlines']){var alignValue="";if(doc.selection.type!="Control"){switch(command){case"JustifyLeft":alignValue="left";break;case"JustifyCenter":alignValue="center";break;case"JustifyFull":alignValue="justify";break;case"JustifyRight":alignValue="right";break}if(alignValue!=""){var rng=doc.selection.createRange();if((divElm=tinyMCE.getParentElement(rng.parentElement(),"div"))!=null)divElm.setAttribute("align",alignValue);else if(rng.pasteHTML&&rng.htmlText.length>0)rng.pasteHTML('<div align="'+alignValue+'">'+rng.htmlText+"</div>");tinyMCE.triggerNodeChange();return}}}switch(command){case"mceRepaint":this.repaint();return true;case"unlink":if(tinyMCE.isGecko&&this.getSel().isCollapsed){focusElm=tinyMCE.getParentElement(focusElm,'A');if(focusElm)this.selection.selectNode(focusElm,false)}this.getDoc().execCommand(command,user_interface,value);tinyMCE.isGecko&&this.getSel().collapseToEnd();tinyMCE.triggerNodeChange();return true;case"InsertUnorderedList":case"InsertOrderedList":this.getDoc().execCommand(command,user_interface,value);tinyMCE.triggerNodeChange();break;case"Strikethrough":this.getDoc().execCommand(command,user_interface,value);tinyMCE.triggerNodeChange();break;case"mceSelectNode":this.selection.selectNode(value);tinyMCE.triggerNodeChange();tinyMCE.selectedNode=value;break;case"FormatBlock":if(value==null||value==""){var elm=tinyMCE.getParentElement(this.getFocusElement(),"p,div,h1,h2,h3,h4,h5,h6,pre,address,blockquote,dt,dl,dd,samp");if(elm)this.execCommand("mceRemoveNode",false,elm)}else{if(!this.cleanup.isValid(value))return true;if(tinyMCE.isGecko&&new RegExp('<(div|blockquote|code|dt|dd|dl|samp)>','gi').test(value))value=value.replace(/[^a-z]/gi,'');if(tinyMCE.isIE&&new RegExp('blockquote|code|samp','gi').test(value)){var b=this.selection.getBookmark();this.getDoc().execCommand("FormatBlock",false,'<p>');tinyMCE.renameElement(tinyMCE.getParentBlockElement(this.getFocusElement()),value);this.selection.moveToBookmark(b)}else this.getDoc().execCommand("FormatBlock",false,value)}tinyMCE.triggerNodeChange();break;case"mceRemoveNode":if(!value)value=tinyMCE.getParentElement(this.getFocusElement());if(tinyMCE.isIE){value.outerHTML=value.innerHTML}else{var rng=value.ownerDocument.createRange();rng.setStartBefore(value);rng.setEndAfter(value);rng.deleteContents();rng.insertNode(rng.createContextualFragment(value.innerHTML))}tinyMCE.triggerNodeChange();break;case"mceSelectNodeDepth":var parentNode=this.getFocusElement();for(var i=0;parentNode;i++){if(parentNode.nodeName.toLowerCase()=="body")break;if(parentNode.nodeName.toLowerCase()=="#text"){i--;parentNode=parentNode.parentNode;continue}if(i==value){this.selection.selectNode(parentNode,false);tinyMCE.triggerNodeChange();tinyMCE.selectedNode=parentNode;return}parentNode=parentNode.parentNode}break;case"mceSetStyleInfo":case"SetStyleInfo":var rng=this.getRng();var sel=this.getSel();var scmd=value['command'];var sname=value['name'];var svalue=value['value']==null?'':value['value'];var wrapper=value['wrapper']?value['wrapper']:"span";var parentElm=null;var invalidRe=new RegExp("^BODY|HTML$","g");var invalidParentsRe=tinyMCE.settings['merge_styles_invalid_parents']!=''?new RegExp(tinyMCE.settings['merge_styles_invalid_parents'],"gi"):null;if(tinyMCE.isIE){if(rng.item)parentElm=rng.item(0);else{var pelm=rng.parentElement();var prng=doc.selection.createRange();prng.moveToElementText(pelm);if(rng.htmlText==prng.htmlText||rng.boundingWidth==0){if(invalidParentsRe==null||!invalidParentsRe.test(pelm.nodeName))parentElm=pelm}}}else{var felm=this.getFocusElement();if(sel.isCollapsed||(new RegExp('td|tr|tbody|table','gi').test(felm.nodeName)&&sel.anchorNode==felm.parentNode))parentElm=felm}if(parentElm&&!invalidRe.test(parentElm.nodeName)){if(scmd=="setstyle")tinyMCE.setStyleAttrib(parentElm,sname,svalue);if(scmd=="setattrib")tinyMCE.setAttrib(parentElm,sname,svalue);if(scmd=="removeformat"){parentElm.style.cssText='';tinyMCE.setAttrib(parentElm,'class','')}var ch=tinyMCE.getNodeTree(parentElm,new Array(),1);for(var z=0;z<ch.length;z++){if(ch[z]==parentElm)continue;if(scmd=="setstyle")tinyMCE.setStyleAttrib(ch[z],sname,'');if(scmd=="setattrib")tinyMCE.setAttrib(ch[z],sname,'');if(scmd=="removeformat"){ch[z].style.cssText='';tinyMCE.setAttrib(ch[z],'class','')}}}else{this._setUseCSS(false);doc.execCommand("FontName",false,"#mce_temp_font#");var elementArray=tinyMCE.getElementsByAttributeValue(this.getBody(),"font","face","#mce_temp_font#");for(var x=0;x<elementArray.length;x++){elm=elementArray[x];if(elm){var spanElm=doc.createElement(wrapper);if(scmd=="setstyle")tinyMCE.setStyleAttrib(spanElm,sname,svalue);if(scmd=="setattrib")tinyMCE.setAttrib(spanElm,sname,svalue);if(scmd=="removeformat"){spanElm.style.cssText='';tinyMCE.setAttrib(spanElm,'class','')}if(elm.hasChildNodes()){for(var i=0;i<elm.childNodes.length;i++)spanElm.appendChild(elm.childNodes[i].cloneNode(true))}spanElm.setAttribute("mce_new","true");elm.parentNode.replaceChild(spanElm,elm);var ch=tinyMCE.getNodeTree(spanElm,new Array(),1);for(var z=0;z<ch.length;z++){if(ch[z]==spanElm)continue;if(scmd=="setstyle")tinyMCE.setStyleAttrib(ch[z],sname,'');if(scmd=="setattrib")tinyMCE.setAttrib(ch[z],sname,'');if(scmd=="removeformat"){ch[z].style.cssText='';tinyMCE.setAttrib(ch[z],'class','')}}}}}var nodes=doc.getElementsByTagName(wrapper);for(var i=nodes.length-1;i>=0;i--){var elm=nodes[i];var isNew=tinyMCE.getAttrib(elm,"mce_new")=="true";elm.removeAttribute("mce_new");if(elm.childNodes&&elm.childNodes.length==1&&elm.childNodes[0].nodeType==1){this._mergeElements(scmd,elm,elm.childNodes[0],isNew);continue}if(elm.parentNode.childNodes.length==1&&!invalidRe.test(elm.nodeName)&&!invalidRe.test(elm.parentNode.nodeName)){if(invalidParentsRe==null||!invalidParentsRe.test(elm.parentNode.nodeName))this._mergeElements(scmd,elm.parentNode,elm,false)}}var nodes=doc.getElementsByTagName(wrapper);for(var i=nodes.length-1;i>=0;i--){var elm=nodes[i];var isEmpty=true;var tmp=doc.createElement("body");tmp.appendChild(elm.cloneNode(false));tmp.innerHTML=tmp.innerHTML.replace(new RegExp('style=""|class=""','gi'),'');if(new RegExp('<span>','gi').test(tmp.innerHTML)){for(var x=0;x<elm.childNodes.length;x++){if(elm.parentNode!=null)elm.parentNode.insertBefore(elm.childNodes[x].cloneNode(true),elm)}elm.parentNode.removeChild(elm)}}if(scmd=="removeformat")tinyMCE.handleVisualAid(this.getBody(),true,this.visualAid,this);tinyMCE.triggerNodeChange();break;case"FontName":if(value==null){var s=this.getSel();if(tinyMCE.isGecko&&s.isCollapsed){var f=tinyMCE.getParentElement(this.getFocusElement(),"font");if(f!=null)this.selection.selectNode(f,false)}this.getDoc().execCommand("RemoveFormat",false,null);if(f!=null&&tinyMCE.isGecko){var r=this.getRng().cloneRange();r.collapse(true);s.removeAllRanges();s.addRange(r)}}else this.getDoc().execCommand('FontName',false,value);if(tinyMCE.isGecko)window.setTimeout('tinyMCE.triggerNodeChange(false);',1);return;case"FontSize":this.getDoc().execCommand('FontSize',false,value);if(tinyMCE.isGecko)window.setTimeout('tinyMCE.triggerNodeChange(false);',1);return;case"forecolor":value=value==null?this.foreColor:value;value=tinyMCE.trim(value);value=value.charAt(0)!='#'?(isNaN('0x'+value)?value:'#'+value):value;this.foreColor=value;this.getDoc().execCommand('forecolor',false,value);break;case"HiliteColor":value=value==null?this.backColor:value;value=tinyMCE.trim(value);value=value.charAt(0)!='#'?(isNaN('0x'+value)?value:'#'+value):value;this.backColor=value;if(tinyMCE.isGecko){this._setUseCSS(true);this.getDoc().execCommand('hilitecolor',false,value);this._setUseCSS(false)}else this.getDoc().execCommand('BackColor',false,value);break;case"Cut":case"Copy":case"Paste":var cmdFailed=false;eval('try {this.getDoc().execCommand(command, user_interface, value);} catch (e) {cmdFailed = true;}');if(tinyMCE.isOpera&&cmdFailed)alert('Currently not supported by your browser, use keyboard shortcuts instead.');if(tinyMCE.isGecko&&cmdFailed){if(confirm(tinyMCE.entityDecode(tinyMCE.getLang('lang_clipboard_msg'))))window.open('http://www.mozilla.org/editor/midasdemo/securityprefs.html','mceExternal');return}else tinyMCE.triggerNodeChange();break;case"mceSetContent":if(!value)value="";value=tinyMCE.storeAwayURLs(value);value=tinyMCE._customCleanup(this,"insert_to_editor",value);if(this.getBody().nodeName=='BODY')tinyMCE._setHTML(doc,value);else this.getBody().innerHTML=value;tinyMCE.setInnerHTML(this.getBody(),tinyMCE._cleanupHTML(this,doc,this.settings,this.getBody(),false,false,false,true));tinyMCE.convertAllRelativeURLs(this.getBody());tinyMCE._removeInternal(this.getBody());if(tinyMCE.getParam("convert_fonts_to_spans"))tinyMCE.convertSpansToFonts(doc);tinyMCE.handleVisualAid(this.getBody(),true,this.visualAid,this);tinyMCE._setEventsEnabled(this.getBody(),false);return true;case"mceCleanup":var b=this.selection.getBookmark();tinyMCE._setHTML(this.contentDocument,this.getBody().innerHTML);tinyMCE.setInnerHTML(this.getBody(),tinyMCE._cleanupHTML(this,this.contentDocument,this.settings,this.getBody(),this.visualAid));tinyMCE.convertAllRelativeURLs(doc.body);if(tinyMCE.getParam("convert_fonts_to_spans"))tinyMCE.convertSpansToFonts(doc);tinyMCE.handleVisualAid(this.getBody(),true,this.visualAid,this);tinyMCE._setEventsEnabled(this.getBody(),false);this.repaint();this.selection.moveToBookmark(b);tinyMCE.triggerNodeChange();break;case"mceReplaceContent":if(!value)value='';this.getWin().focus();var selectedText="";if(tinyMCE.isIE){var rng=doc.selection.createRange();selectedText=rng.text}else selectedText=this.getSel().toString();if(selectedText.length>0){value=tinyMCE.replaceVar(value,"selection",selectedText);tinyMCE.execCommand('mceInsertContent',false,value)}tinyMCE.triggerNodeChange();break;case"mceSetAttribute":if(typeof(value)=='object'){var targetElms=(typeof(value['targets'])=="undefined")?"p,img,span,div,td,h1,h2,h3,h4,h5,h6,pre,address":value['targets'];var targetNode=tinyMCE.getParentElement(this.getFocusElement(),targetElms);if(targetNode){targetNode.setAttribute(value['name'],value['value']);tinyMCE.triggerNodeChange()}}break;case"mceSetCSSClass":this.execCommand("mceSetStyleInfo",false,{command:"setattrib",name:"class",value:value});break;case"mceInsertRawHTML":var key='tiny_mce_marker';this.execCommand('mceBeginUndoLevel');this.execCommand('mceInsertContent',false,key);var scrollX=this.getBody().scrollLeft+this.getDoc().documentElement.scrollLeft;var scrollY=this.getBody().scrollTop+this.getDoc().documentElement.scrollTop;var html=this.getBody().innerHTML;if((pos=html.indexOf(key))!=-1)tinyMCE.setInnerHTML(this.getBody(),html.substring(0,pos)+value+html.substring(pos+key.length));this.contentWindow.scrollTo(scrollX,scrollY);this.execCommand('mceEndUndoLevel');break;case"mceInsertContent":if(!value)value='';var insertHTMLFailed=false;if(tinyMCE.isGecko||tinyMCE.isOpera){try{if(value.indexOf('<')==-1&&!value.match(/(&#38;|&#160;|&#60;|&#62;)/g)){var r=this.getRng();var n=this.getDoc().createTextNode(tinyMCE.entityDecode(value));var s=this.getSel();var r2=r.cloneRange();s.removeAllRanges();r.deleteContents();r.insertNode(n);r2.selectNode(n);r2.collapse(false);s.removeAllRanges();s.addRange(r2)}else{value=tinyMCE.fixGeckoBaseHREFBug(1,this.getDoc(),value);this.getDoc().execCommand('inserthtml',false,value);tinyMCE.fixGeckoBaseHREFBug(2,this.getDoc(),value)}}catch(ex){insertHTMLFailed=true}if(!insertHTMLFailed){tinyMCE.triggerNodeChange();return}}if(!tinyMCE.isIE){var isHTML=value.indexOf('<')!=-1;var sel=this.getSel();var rng=this.getRng();if(isHTML){if(tinyMCE.isSafari){var tmpRng=this.getDoc().createRange();tmpRng.setStart(this.getBody(),0);tmpRng.setEnd(this.getBody(),0);value=tmpRng.createContextualFragment(value)}else value=rng.createContextualFragment(value)}else{var el=document.createElement("div");el.innerHTML=value;value=el.firstChild.nodeValue;value=doc.createTextNode(value)}if(tinyMCE.isSafari&&!isHTML){this.execCommand('InsertText',false,value.nodeValue);tinyMCE.triggerNodeChange();return true}else if(tinyMCE.isSafari&&isHTML){rng.deleteContents();rng.insertNode(value);tinyMCE.triggerNodeChange();return true}rng.deleteContents();if(rng.startContainer.nodeType==3){var node=rng.startContainer.splitText(rng.startOffset);node.parentNode.insertBefore(value,node)}else rng.insertNode(value);if(!isHTML){sel.selectAllChildren(doc.body);sel.removeAllRanges();var rng=doc.createRange();rng.selectNode(value);rng.collapse(false);sel.addRange(rng)}else rng.collapse(false);tinyMCE.fixGeckoBaseHREFBug(2,this.getDoc(),value)}else{var rng=doc.selection.createRange(),tmpRng=null;var c=value.indexOf('<!--')!=-1;if(c)value=tinyMCE.uniqueTag+value;if(rng.item)rng.item(0).outerHTML=value;else rng.pasteHTML(value);if(c){var e=this.getDoc().getElementById('mceTMPElement');e.parentNode.removeChild(e)}}tinyMCE.execCommand("mceAddUndoLevel");tinyMCE.triggerNodeChange();break;case"mceStartTyping":if(tinyMCE.settings['custom_undo_redo']&&this.undoRedo.typingUndoIndex==-1){this.undoRedo.typingUndoIndex=this.undoRedo.undoIndex;tinyMCE.typingUndoIndex=tinyMCE.undoIndex;this.execCommand('mceAddUndoLevel')}break;case"mceEndTyping":if(tinyMCE.settings['custom_undo_redo']&&this.undoRedo.typingUndoIndex!=-1){this.execCommand('mceAddUndoLevel');this.undoRedo.typingUndoIndex=-1}tinyMCE.typingUndoIndex=-1;break;case"mceBeginUndoLevel":this.undoRedoLevel=false;break;case"mceEndUndoLevel":this.undoRedoLevel=true;this.execCommand('mceAddUndoLevel');break;case"mceAddUndoLevel":if(tinyMCE.settings['custom_undo_redo']&&this.undoRedoLevel){if(this.undoRedo.add())tinyMCE.triggerNodeChange(false)}break;case"Undo":if(tinyMCE.settings['custom_undo_redo']){tinyMCE.execCommand("mceEndTyping");this.undoRedo.undo();tinyMCE.triggerNodeChange()}else this.getDoc().execCommand(command,user_interface,value);break;case"Redo":if(tinyMCE.settings['custom_undo_redo']){tinyMCE.execCommand("mceEndTyping");this.undoRedo.redo();tinyMCE.triggerNodeChange()}else this.getDoc().execCommand(command,user_interface,value);break;case"mceToggleVisualAid":this.visualAid=!this.visualAid;tinyMCE.handleVisualAid(this.getBody(),true,this.visualAid,this);tinyMCE.triggerNodeChange();break;case"Indent":this.getDoc().execCommand(command,user_interface,value);tinyMCE.triggerNodeChange();if(tinyMCE.isIE){var n=tinyMCE.getParentElement(this.getFocusElement(),"blockquote");do{if(n&&n.nodeName=="BLOCKQUOTE"){n.removeAttribute("dir");n.removeAttribute("style")}}while(n!=null&&(n=n.parentNode)!=null)}break;case"RemoveFormat":case"removeformat":var text=this.selection.getSelectedText();if(tinyMCE.isOpera){this.getDoc().execCommand("RemoveFormat",false,null);return}if(tinyMCE.isIE){try{var rng=doc.selection.createRange();rng.execCommand("RemoveFormat",false,null)}catch(e){}this.execCommand("mceSetStyleInfo",false,{command:"removeformat"})}else{this.getDoc().execCommand(command,user_interface,value);this.execCommand("mceSetStyleInfo",false,{command:"removeformat"})}if(text.length==0)this.execCommand("mceSetCSSClass",false,"");tinyMCE.triggerNodeChange();break;default:this.getDoc().execCommand(command,user_interface,value);if(tinyMCE.isGecko)window.setTimeout('tinyMCE.triggerNodeChange(false);',1);else tinyMCE.triggerNodeChange()}if(command!="mceAddUndoLevel"&&command!="Undo"&&command!="Redo"&&command!="mceStartTyping"&&command!="mceEndTyping")tinyMCE.execCommand("mceAddUndoLevel")},queryCommandValue:function(c){try{return this.getDoc().queryCommandValue(c)}catch(e){return null}},queryCommandState:function(c){return this.getDoc().queryCommandState(c)},_onAdd:function(replace_element,form_element_name,target_document){var hc,th,to,editorTemplate;th=this.settings['theme'];to=tinyMCE.themes[th];var targetDoc=target_document?target_document:document;this.targetDoc=targetDoc;tinyMCE.themeURL=tinyMCE.baseURL+"/themes/"+this.settings['theme'];this.settings['themeurl']=tinyMCE.themeURL;if(!replace_element){alert("Error: Could not find the target element.");return false}if(to.getEditorTemplate)editorTemplate=to.getEditorTemplate(this.settings,this.editorId);var deltaWidth=editorTemplate['delta_width']?editorTemplate['delta_width']:0;var deltaHeight=editorTemplate['delta_height']?editorTemplate['delta_height']:0;var html='<span id="'+this.editorId+'_parent" class="mceEditorContainer">'+editorTemplate['html'];html=tinyMCE.replaceVar(html,"editor_id",this.editorId);this.settings['default_document']=tinyMCE.baseURL+"/blank.htm";this.settings['old_width']=this.settings['width'];this.settings['old_height']=this.settings['height'];if(this.settings['width']==-1)this.settings['width']=replace_element.offsetWidth;if(this.settings['height']==-1)this.settings['height']=replace_element.offsetHeight;if(this.settings['width']==0)this.settings['width']=replace_element.style.width;if(this.settings['height']==0)this.settings['height']=replace_element.style.height;if(this.settings['width']==0)this.settings['width']=320;if(this.settings['height']==0)this.settings['height']=240;this.settings['area_width']=parseInt(this.settings['width']);this.settings['area_height']=parseInt(this.settings['height']);this.settings['area_width']+=deltaWidth;this.settings['area_height']+=deltaHeight;this.settings['width_style']=""+this.settings['width'];this.settings['height_style']=""+this.settings['height'];if((""+this.settings['width']).indexOf('%')!=-1)this.settings['area_width']="100%";else this.settings['width_style']+='px';if((""+this.settings['height']).indexOf('%')!=-1)this.settings['area_height']="100%";else this.settings['height_style']+='px';if((""+replace_element.style.width).indexOf('%')!=-1){this.settings['width']=replace_element.style.width;this.settings['area_width']="100%";this.settings['width_style']="100%"}if((""+replace_element.style.height).indexOf('%')!=-1){this.settings['height']=replace_element.style.height;this.settings['area_height']="100%";this.settings['height_style']="100%"}html=tinyMCE.applyTemplate(html);this.settings['width']=this.settings['old_width'];this.settings['height']=this.settings['old_height'];this.visualAid=this.settings['visual'];this.formTargetElementId=form_element_name;if(replace_element.nodeName=="TEXTAREA"||replace_element.nodeName=="INPUT")this.startContent=replace_element.value;else this.startContent=replace_element.innerHTML;if(replace_element.nodeName!="TEXTAREA"&&replace_element.nodeName!="INPUT"){this.oldTargetElement=replace_element;if(tinyMCE.settings['debug']){hc='<textarea wrap="off" id="'+form_element_name+'" name="'+form_element_name+'" cols="100" rows="15"></textarea>'}else{hc='<input type="hidden" id="'+form_element_name+'" name="'+form_element_name+'" />';this.oldTargetDisplay=tinyMCE.getStyle(this.oldTargetElement,'display','inline');this.oldTargetElement.style.display="none"}html+='</span>';if(tinyMCE.isGecko)html=hc+html;else html+=hc;if(tinyMCE.isGecko){var rng=replace_element.ownerDocument.createRange();rng.setStartBefore(replace_element);var fragment=rng.createContextualFragment(html);tinyMCE.insertAfter(fragment,replace_element)}else replace_element.insertAdjacentHTML("beforeBegin",html)}else{html+='</span>';this.oldTargetElement=replace_element;if(!tinyMCE.settings['debug']){this.oldTargetDisplay=tinyMCE.getStyle(this.oldTargetElement,'display','inline');this.oldTargetElement.style.display="none"}if(tinyMCE.isGecko){var rng=replace_element.ownerDocument.createRange();rng.setStartBefore(replace_element);var fragment=rng.createContextualFragment(html);tinyMCE.insertAfter(fragment,replace_element)}else replace_element.insertAdjacentHTML("beforeBegin",html)}var dynamicIFrame=false;var tElm=targetDoc.getElementById(this.editorId);if(!tinyMCE.isIE){if(tElm&&(tElm.nodeName=="SPAN"||tElm.nodeName=="span")){tElm=tinyMCE._createIFrame(tElm,targetDoc);dynamicIFrame=true}this.targetElement=tElm;this.iframeElement=tElm;this.contentDocument=tElm.contentDocument;this.contentWindow=tElm.contentWindow;}else{if(tElm&&tElm.nodeName=="SPAN")tElm=tinyMCE._createIFrame(tElm,targetDoc,targetDoc.parentWindow);else tElm=targetDoc.frames[this.editorId];this.targetElement=tElm;this.iframeElement=targetDoc.getElementById(this.editorId);if(tinyMCE.isOpera){this.contentDocument=this.iframeElement.contentDocument;this.contentWindow=this.iframeElement.contentWindow;dynamicIFrame=true}else{this.contentDocument=tElm.window.document;this.contentWindow=tElm.window}this.getDoc().designMode="on"}var doc=this.contentDocument;if(dynamicIFrame){var html=tinyMCE.getParam('doctype')+'<html><head xmlns="http://www.w3.org/1999/xhtml"><base href="'+tinyMCE.settings['base_href']+'" /><title>blank_page</title><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"></head><body class="mceContentBody"></body></html>';try{if(!this.isHidden())this.getDoc().designMode="on";doc.open();doc.write(html);doc.close()}catch(e){this.getDoc().location.href=tinyMCE.baseURL+"/blank.htm"}}if(tinyMCE.isIE)window.setTimeout("tinyMCE.addEventHandlers(tinyMCE.instances[\""+this.editorId+"\"]);",1);var parentElm=this.targetDoc.getElementById(this.editorId+'_parent');this.formElement=tinyMCE.isGecko?parentElm.previousSibling:parentElm.nextSibling;tinyMCE.setupContent(this.editorId,true);return true},setBaseHREF:function(u){var h,b,d,nl;d=this.getDoc();nl=d.getElementsByTagName("base");b=nl.length>0?nl[0]:null;if(!b){nl=d.getElementsByTagName("head");h=nl.length>0?nl[0]:null;b=d.createElement("base");b.setAttribute('href',u);h.appendChild(b)}else{if(u==""||u==null)b.parentNode.removeChild(b);else b.setAttribute('href',u)}},getHTML:function(r){var h,d=this.getDoc(),b=this.getBody();if(r)return b.innerHTML;h=tinyMCE._cleanupHTML(this,d,this.settings,b,false,true,false,true);if(tinyMCE.getParam("convert_fonts_to_spans"))tinyMCE.convertSpansToFonts(d);return h},setHTML:function(h){this.execCommand('mceSetContent',false,h);this.repaint()},getFocusElement:function(){return this.selection.getFocusElement()},getSel:function(){return this.selection.getSel()},getRng:function(){return this.selection.getRng()},triggerSave:function(skip_cleanup,skip_callback){var e,nl=[],i,s;this.switchSettings();s=tinyMCE.settings;if(tinyMCE.isRealIE){e=this.iframeElement;do{if(e.style&&e.style.display=='none'){e.style.display='block';nl[nl.length]={elm:e,type:'style'}}if(e.style&&s.hidden_tab_class.length>0&&e.className.indexOf(s.hidden_tab_class)!=-1){e.className=s.display_tab_class;nl[nl.length]={elm:e,type:'class'}}}while((e=e.parentNode)!=null)}tinyMCE.settings['preformatted']=false;if(typeof(skip_cleanup)=="undefined")skip_cleanup=false;if(typeof(skip_callback)=="undefined")skip_callback=false;tinyMCE._setHTML(this.getDoc(),this.getBody().innerHTML);if(this.settings['cleanup']==false){tinyMCE.handleVisualAid(this.getBody(),true,false,this);tinyMCE._setEventsEnabled(this.getBody(),true)}tinyMCE._customCleanup(this,"submit_content_dom",this.contentWindow.document.body);var htm=skip_cleanup?this.getBody().innerHTML:tinyMCE._cleanupHTML(this,this.getDoc(),this.settings,this.getBody(),tinyMCE.visualAid,true,true);htm=tinyMCE._customCleanup(this,"submit_content",htm);if(!skip_callback&&tinyMCE.settings['save_callback']!="")var content=eval(tinyMCE.settings['save_callback']+"(this.formTargetElementId,htm,this.getBody());");if((typeof(content)!="undefined")&&content!=null)htm=content;htm=tinyMCE.regexpReplace(htm,"&#40;","(","gi");htm=tinyMCE.regexpReplace(htm,"&#41;",")","gi");htm=tinyMCE.regexpReplace(htm,"&#59;",";","gi");htm=tinyMCE.regexpReplace(htm,"&#34;","&quot;","gi");htm=tinyMCE.regexpReplace(htm,"&#94;","^","gi");if(this.formElement)this.formElement.value=htm;if(tinyMCE.isSafari&&this.formElement)this.formElement.innerText=htm;for(i=0;i<nl.length;i++){if(nl[i].type=='style')nl[i].elm.style.display='none';else nl[i].elm.className=s.hidden_tab_class}}};TinyMCE_Engine.prototype.cleanupHTMLCode=function(s){s=s.replace(new RegExp('<p \\/>','gi'),'<p>&nbsp;</p>');s=s.replace(new RegExp('<p>\\s*<\\/p>','gi'),'<p>&nbsp;</p>');s=s.replace(new RegExp('<br>\\s*<\\/br>','gi'),'<br />');s=s.replace(new RegExp('<(h[1-6]|p|div|address|pre|form|table|li|ol|ul|td|b|font|em|strong|i|strike|u|span|a|ul|ol|li|blockquote)([a-z]*)([^\\\\|>]*)\\/>','gi'),'<$1$2$3></$1$2>');s=s.replace(new RegExp('\\s+></','gi'),'></');s=s.replace(new RegExp('<(img|br|hr)([^>]*)><\\/(img|br|hr)>','gi'),'<$1$2 />');if(tinyMCE.isIE)s=s.replace(new RegExp('<p><hr \\/><\\/p>','gi'),"<hr>");if(tinyMCE.isIE)s=s.replace(/<!(\s*)\/>/g,'');return s};TinyMCE_Engine.prototype.parseStyle=function(str){var ar=new Array();if(str==null)return ar;var st=str.split(';');tinyMCE.clearArray(ar);for(var i=0;i<st.length;i++){if(st[i]=='')continue;var re=new RegExp('^\\s*([^:]*):\\s*(.*)\\s*$');var pa=st[i].replace(re,'$1||$2').split('||');if(pa.length==2)ar[pa[0].toLowerCase()]=pa[1]}return ar};TinyMCE_Engine.prototype.compressStyle=function(ar,pr,sf,res){var box=new Array();box[0]=ar[pr+'-top'+sf];box[1]=ar[pr+'-left'+sf];box[2]=ar[pr+'-right'+sf];box[3]=ar[pr+'-bottom'+sf];for(var i=0;i<box.length;i++){if(box[i]==null)return;for(var a=0;a<box.length;a++){if(box[a]!=box[i])return}}ar[res]=box[0];ar[pr+'-top'+sf]=null;ar[pr+'-left'+sf]=null;ar[pr+'-right'+sf]=null;ar[pr+'-bottom'+sf]=null};TinyMCE_Engine.prototype.serializeStyle=function(ar){var str="";tinyMCE.compressStyle(ar,"border","","border");tinyMCE.compressStyle(ar,"border","-width","border-width");tinyMCE.compressStyle(ar,"border","-color","border-color");tinyMCE.compressStyle(ar,"border","-style","border-style");tinyMCE.compressStyle(ar,"padding","","padding");tinyMCE.compressStyle(ar,"margin","","margin");for(var key in ar){var val=ar[key];if(typeof(val)=='function')continue;if(key.indexOf('mso-')==0)continue;if(val!=null&&val!=''){val=''+val;val=val.replace(new RegExp("url\\(\\'?([^\\']*)\\'?\\)",'gi'),"url('$1')");if(val.indexOf('url(')!=-1&&tinyMCE.getParam('convert_urls')){var m=new RegExp("url\\('(.*?)'\\)").exec(val);if(m.length>1)val="url('"+eval(tinyMCE.getParam('urlconverter_callback')+"(m[1], null, true);")+"')"}if(tinyMCE.getParam("force_hex_style_colors"))val=tinyMCE.convertRGBToHex(val,true);val=val.replace(/\"/g,'\'');if(val!="url('')")str+=key.toLowerCase()+": "+val+"; "}}if(new RegExp('; $').test(str))str=str.substring(0,str.length-2);return str};TinyMCE_Engine.prototype.convertRGBToHex=function(s,k){if(s.toLowerCase().indexOf('rgb')!=-1){var re=new RegExp("(.*?)rgb\\s*?\\(\\s*?([0-9]+).*?,\\s*?([0-9]+).*?,\\s*?([0-9]+).*?\\)(.*?)","gi");var rgb=s.replace(re,"$1,$2,$3,$4,$5").split(',');if(rgb.length==5){r=parseInt(rgb[1]).toString(16);g=parseInt(rgb[2]).toString(16);b=parseInt(rgb[3]).toString(16);r=r.length==1?'0'+r:r;g=g.length==1?'0'+g:g;b=b.length==1?'0'+b:b;s="#"+r+g+b;if(k)s=rgb[0]+s+rgb[4]}}return s};TinyMCE_Engine.prototype.convertHexToRGB=function(s){if(s.indexOf('#')!=-1){s=s.replace(new RegExp('[^0-9A-F]','gi'),'');return"rgb("+parseInt(s.substring(0,2),16)+","+parseInt(s.substring(2,4),16)+","+parseInt(s.substring(4,6),16)+")"}return s};TinyMCE_Engine.prototype.convertSpansToFonts=function(doc){var sizes=tinyMCE.getParam('font_size_style_values').replace(/\s+/,'').split(',');var s=tinyMCE.selectElements(doc,'span,font');for(var i=0;i<s.length;i++){var size=tinyMCE.trim(s[i].style.fontSize).toLowerCase();var fSize=0;for(var x=0;x<sizes.length;x++){if(sizes[x]==size){fSize=x+1;break}}if(fSize>0){tinyMCE.setAttrib(s[i],'size',fSize);s[i].style.fontSize=''}var fFace=s[i].style.fontFamily;if(fFace!=null&&fFace!=""){tinyMCE.setAttrib(s[i],'face',fFace);s[i].style.fontFamily=''}var fColor=s[i].style.color;if(fColor!=null&&fColor!=""){tinyMCE.setAttrib(s[i],'color',tinyMCE.convertRGBToHex(fColor));s[i].style.color=''}}};TinyMCE_Engine.prototype.convertFontsToSpans=function(doc){var sizes=tinyMCE.getParam('font_size_style_values').replace(/\s+/,'').split(',');var fsClasses=tinyMCE.getParam('font_size_classes');if(fsClasses!='')fsClasses=fsClasses.replace(/\s+/,'').split(',');else fsClasses=null;var s=tinyMCE.selectElements(doc,'span,font');for(var i=0;i<s.length;i++){var fSize,fFace,fColor;fSize=tinyMCE.getAttrib(s[i],'size');fFace=tinyMCE.getAttrib(s[i],'face');fColor=tinyMCE.getAttrib(s[i],'color');if(fSize!=""){fSize=parseInt(fSize);if(fSize>0&&fSize<8){if(fsClasses!=null)tinyMCE.setAttrib(s[i],'class',fsClasses[fSize-1]);else s[i].style.fontSize=sizes[fSize-1]}s[i].removeAttribute('size')}if(fFace!=""){s[i].style.fontFamily=fFace;s[i].removeAttribute('face')}if(fColor!=""){s[i].style.color=fColor;s[i].removeAttribute('color')}}};TinyMCE_Engine.prototype.cleanupAnchors=function(doc){var i,cn,x,an=doc.getElementsByTagName("a");for(i=an.length-1;i>=0;i--){if(tinyMCE.getAttrib(an[i],"name")!=""&&tinyMCE.getAttrib(an[i],"href")==""){cn=an[i].childNodes;for(x=cn.length-1;x>=0;x--)tinyMCE.insertAfter(cn[x],an[i])}}};TinyMCE_Engine.prototype.getContent=function(editor_id){if(typeof(editor_id)!="undefined")tinyMCE.getInstanceById(editor_id).select();if(tinyMCE.selectedInstance)return tinyMCE.selectedInstance.getHTML();return null};TinyMCE_Engine.prototype._fixListElements=function(d){var nl,x,a=['ol','ul'],i,n,p,r=new RegExp('^(OL|UL)$'),np;for(x=0;x<a.length;x++){nl=d.getElementsByTagName(a[x]);for(i=0;i<nl.length;i++){n=nl[i];p=n.parentNode;if(r.test(p.nodeName)){np=tinyMCE.prevNode(n,'LI');if(!np){np=d.createElement('li');np.innerHTML='&nbsp;';np.appendChild(n);p.insertBefore(np,p.firstChild)}else np.appendChild(n)}}}};TinyMCE_Engine.prototype._fixTables=function(d){var nl,i,n,p,np,x,t;nl=d.getElementsByTagName('table');for(i=0;i<nl.length;i++){n=nl[i];if((p=tinyMCE.getParentElement(n,'p,h1,h2,h3,h4,h5,h6'))!=null){np=p.cloneNode(false);np.removeAttribute('id');t=n;while((n=n.nextSibling))np.appendChild(n);tinyMCE.insertAfter(np,p);tinyMCE.insertAfter(t,p)}}};TinyMCE_Engine.prototype._cleanupHTML=function(inst,doc,config,elm,visual,on_save,on_submit,inn){var h,d,t1,t2,t3,t4,t5,c,s,nb;if(!tinyMCE.getParam('cleanup'))return elm.innerHTML;on_save=typeof(on_save)=='undefined'?false:on_save;c=inst.cleanup;s=inst.settings;d=c.settings.debug;if(d)t1=new Date().getTime();if(tinyMCE.getParam("convert_fonts_to_spans"))tinyMCE.convertFontsToSpans(doc);if(tinyMCE.getParam("fix_list_elements"))tinyMCE._fixListElements(doc);if(tinyMCE.getParam("fix_table_elements"))tinyMCE._fixTables(doc);tinyMCE._customCleanup(inst,on_save?"get_from_editor_dom":"insert_to_editor_dom",doc.body);if(d)t2=new Date().getTime();c.settings.on_save=on_save;c.idCount=0;c.serializationId++;c.serializedNodes=new Array();c.sourceIndex=-1;if(s.cleanup_serializer=="xml")h=c.serializeNodeAsXML(elm,inn);else h=c.serializeNodeAsHTML(elm,inn);if(d)t3=new Date().getTime();nb=tinyMCE.getParam('entity_encoding')=='numeric'?'&#160;':'&nbsp;';h=h.replace(/<\/?(body|head|html)[^>]*>/gi,'');h=h.replace(new RegExp(' (rowspan="1"|colspan="1")','g'),'');h=h.replace(/<p><hr \/><\/p>/g,'<hr />');h=h.replace(/<p>(&nbsp;|&#160;)<\/p><hr \/><p>(&nbsp;|&#160;)<\/p>/g,'<hr />');h=h.replace(/<td>\s*<br \/>\s*<\/td>/g,'<td>'+nb+'</td>');h=h.replace(/<p>\s*<br \/>\s*<\/p>/g,'<p>'+nb+'</p>');h=h.replace(/<br \/>$/,'');h=h.replace(/<br \/><\/p>/g,'</p>');h=h.replace(/<p>\s*(&nbsp;|&#160;)\s*<br \/>\s*(&nbsp;|&#160;)\s*<\/p>/g,'<p>'+nb+'</p>');h=h.replace(/<p>\s*(&nbsp;|&#160;)\s*<br \/>\s*<\/p>/g,'<p>'+nb+'</p>');h=h.replace(/<p>\s*<br \/>\s*&nbsp;\s*<\/p>/g,'<p>'+nb+'</p>');h=h.replace(new RegExp('<a>(.*?)<\\/a>','g'),'$1');h=h.replace(/<p([^>]*)>\s*<\/p>/g,'<p$1>'+nb+'</p>');if(/^\s*(<br \/>|<p>&nbsp;<\/p>|<p>&#160;<\/p>|<p><\/p>)\s*$/.test(h))h='';if(s.preformatted){h=h.replace(/^<pre>/,'');h=h.replace(/<\/pre>$/,'');h='<pre>'+h+'</pre>'}if(tinyMCE.isGecko){h=h.replace(/<o:p _moz-userdefined="" \/>/g,'');h=h.replace(/<td([^>]*)>\s*<br \/>\s*<\/td>/g,'<td$1>'+nb+'</td>')}if(s.force_br_newlines)h=h.replace(/<p>(&nbsp;|&#160;)<\/p>/g,'<br />');h=tinyMCE._customCleanup(inst,on_save?"get_from_editor":"insert_to_editor",h);if(on_save){h=h.replace(new RegExp(' ?(mceItem[a-zA-Z0-9]*|'+s.visual_table_class+')','g'),'');h=h.replace(new RegExp(' ?class=""','g'),'')}if(s.remove_linebreaks&&!c.settings.indent)h=h.replace(/\n|\r/g,' ');if(d)t4=new Date().getTime();if(on_save&&c.settings.indent)h=c.formatHTML(h);if(on_submit&&(s.encoding=="xml"||s.encoding=="html"))h=c.xmlEncode(h);if(d)t5=new Date().getTime();if(c.settings.debug)tinyMCE.debug("Cleanup in ms: Pre="+(t2-t1)+", Serialize: "+(t3-t2)+", Post: "+(t4-t3)+", Format: "+(t5-t4)+", Sum: "+(t5-t1)+".");return h};function TinyMCE_Cleanup(){this.isIE=(navigator.appName=="Microsoft Internet Explorer");this.rules=tinyMCE.clearArray(new Array());this.settings={indent_elements:'head,table,tbody,thead,tfoot,form,tr,ul,ol,blockquote,object',newline_before_elements:'h1,h2,h3,h4,h5,h6,pre,address,div,ul,ol,li,meta,option,area,title,link,base,script,td',newline_after_elements:'br,hr,p,pre,address,div,ul,ol,meta,option,area,link,base,script',newline_before_after_elements:'html,head,body,table,thead,tbody,tfoot,tr,form,ul,ol,blockquote,p,object,param,hr,div',indent_char:'\t',indent_levels:1,entity_encoding:'raw',valid_elements:'*[*]',entities:'',url_converter:'',invalid_elements:'',verify_html:false};this.vElements=tinyMCE.clearArray(new Array());this.vElementsRe='';this.closeElementsRe=/^(IMG|BR|HR|LINK|META|BASE|INPUT|AREA)$/;this.codeElementsRe=/^(SCRIPT|STYLE)$/;this.serializationId=0;this.mceAttribs={href:'mce_href',src:'mce_src',type:'mce_type'}}TinyMCE_Cleanup.prototype={init:function(s){var n,a,i,ir,or,st;for(n in s)this.settings[n]=s[n];s=this.settings;this.inRe=this._arrayToRe(s.indent_elements.split(','),'','^<(',')[^>]*');this.ouRe=this._arrayToRe(s.indent_elements.split(','),'','^<\\/(',')[^>]*');this.nlBeforeRe=this._arrayToRe(s.newline_before_elements.split(','),'gi','<(',')([^>]*)>');this.nlAfterRe=this._arrayToRe(s.newline_after_elements.split(','),'gi','<(',')([^>]*)>');this.nlBeforeAfterRe=this._arrayToRe(s.newline_before_after_elements.split(','),'gi','<(\\/?)(',')([^>]*)>');this.serializedNodes=[];if(s.invalid_elements!='')this.iveRe=this._arrayToRe(s.invalid_elements.toUpperCase().split(','),'g','^(',')$');else this.iveRe=null;st='';for(i=0;i<s.indent_levels;i++)st+=s.indent_char;this.inStr=st;if(!s.verify_html){s.valid_elements='*[*]';s.extended_valid_elements=''}this.fillStr=s.entity_encoding=="named"?"&nbsp;":"&#160;";this.idCount=0;this.xmlEncodeRe=new RegExp('[\u007F-\uFFFF<>&"]','g');this.xmlEncodeAposRe=new RegExp('[\u007F-\uFFFF<>&"\']','g')},addRuleStr:function(s){var r=this.parseRuleStr(s);var n;for(n in r){if(r[n])this.rules[n]=r[n]}this.vElements=tinyMCE.clearArray(new Array());for(n in this.rules){if(this.rules[n])this.vElements[this.vElements.length]=this.rules[n].tag}this.vElementsRe=this._arrayToRe(this.vElements,'')},isValid:function(n){this._setupRules();if(!n)return true;n=n.replace(/[^a-z0-9]+/gi,'').toUpperCase();return!tinyMCE.getParam('cleanup')||this.vElementsRe.test(n)},addChildRemoveRuleStr:function(s){var x,y,p,i,t,tn,ta,cl,r;if(!s)return;ta=s.split(',');for(x=0;x<ta.length;x++){s=ta[x];p=this.split(/\[|\]/,s);if(p==null||p.length<1)t=s.toUpperCase();else t=p[0].toUpperCase();tn=this.split('/',t);for(y=0;y<tn.length;y++){r="^(";cl=this.split(/\|/,p[1]);for(i=0;i<cl.length;i++){if(cl[i]=='%istrict')r+=tinyMCE.inlineStrict;else if(cl[i]=='%itrans')r+=tinyMCE.inlineTransitional;else if(cl[i]=='%istrict_na')r+=tinyMCE.inlineStrict.substring(2);else if(cl[i]=='%itrans_na')r+=tinyMCE.inlineTransitional.substring(2);else if(cl[i]=='%btrans')r+=tinyMCE.blockElms;else if(cl[i]=='%strict')r+=tinyMCE.blockStrict;else r+=(cl[i].charAt(0)!='#'?cl[i].toUpperCase():cl[i]);r+=(i!=cl.length-1?'|':'')}r+=')$';if(this.childRules==null)this.childRules=tinyMCE.clearArray(new Array());this.childRules[tn[y]]=new RegExp(r);if(p.length>1)this.childRules[tn[y]].wrapTag=p[2]}}},parseRuleStr:function(s){var ta,p,r,a,i,x,px,t,tn,y,av,or=tinyMCE.clearArray(new Array()),dv;if(s==null||s.length==0)return or;ta=s.split(',');for(x=0;x<ta.length;x++){s=ta[x];if(s.length==0)continue;p=this.split(/\[|\]/,s);if(p==null||p.length<1)t=s.toUpperCase();else t=p[0].toUpperCase();tn=this.split('/',t);for(y=0;y<tn.length;y++){r={};r.tag=tn[y];r.forceAttribs=null;r.defaultAttribs=null;r.validAttribValues=null;px=r.tag.charAt(0);r.forceOpen=px=='+';r.removeEmpty=px=='-';r.fill=px=='#';r.tag=r.tag.replace(/\+|-|#/g,'');r.oTagName=tn[0].replace(/\+|-|#/g,'').toLowerCase();r.isWild=new RegExp('\\*|\\?|\\+','g').test(r.tag);r.validRe=new RegExp(this._wildcardToRe('^'+r.tag+'$'));if(p.length>1){r.vAttribsRe='^(';a=this.split(/\|/,p[1]);for(i=0;i<a.length;i++){t=a[i];if(t.charAt(0)=='!'){a[i]=t=t.substring(1);if(!r.reqAttribsRe)r.reqAttribsRe='\\s+('+t;else r.reqAttribsRe+='|'+t}av=new RegExp('(=|:|<)(.*?)$').exec(t);t=t.replace(new RegExp('(=|:|<).*?$'),'');if(av&&av.length>0){if(av[0].charAt(0)==':'){if(!r.forceAttribs)r.forceAttribs=tinyMCE.clearArray(new Array());r.forceAttribs[t.toLowerCase()]=av[0].substring(1)}else if(av[0].charAt(0)=='='){if(!r.defaultAttribs)r.defaultAttribs=tinyMCE.clearArray(new Array());dv=av[0].substring(1);r.defaultAttribs[t.toLowerCase()]=dv==""?"mce_empty":dv}else if(av[0].charAt(0)=='<'){if(!r.validAttribValues)r.validAttribValues=tinyMCE.clearArray(new Array());r.validAttribValues[t.toLowerCase()]=this._arrayToRe(this.split('?',av[0].substring(1)),'i')}}r.vAttribsRe+=''+t.toLowerCase()+(i!=a.length-1?'|':'');a[i]=t.toLowerCase()}if(r.reqAttribsRe)r.reqAttribsRe=new RegExp(r.reqAttribsRe+')=\"','g');r.vAttribsRe+=')$';r.vAttribsRe=this._wildcardToRe(r.vAttribsRe);r.vAttribsReIsWild=new RegExp('\\*|\\?|\\+','g').test(r.vAttribsRe);r.vAttribsRe=new RegExp(r.vAttribsRe);r.vAttribs=a.reverse();}else{r.vAttribsRe='';r.vAttribs=tinyMCE.clearArray(new Array());r.vAttribsReIsWild=false}or[r.tag]=r}}return or},serializeNodeAsXML:function(n){var s,b;if(!this.xmlDoc){if(this.isIE){try{this.xmlDoc=new ActiveXObject('MSXML2.DOMDocument')}catch(e){}if(!this.xmlDoc)try{this.xmlDoc=new ActiveXObject('Microsoft.XmlDom')}catch(e){}}else this.xmlDoc=document.implementation.createDocument('','',null);if(!this.xmlDoc)alert("Error XML Parser could not be found.")}if(this.xmlDoc.firstChild)this.xmlDoc.removeChild(this.xmlDoc.firstChild);b=this.xmlDoc.createElement("html");b=this.xmlDoc.appendChild(b);this._convertToXML(n,b);if(this.isIE)return this.xmlDoc.xml;else return new XMLSerializer().serializeToString(this.xmlDoc)},_convertToXML:function(n,xn){var xd,el,i,l,cn,at,no,hc=false;if(tinyMCE.isRealIE&&this._isDuplicate(n))return;xd=this.xmlDoc;switch(n.nodeType){case 1:hc=n.hasChildNodes();el=xd.createElement(n.nodeName.toLowerCase());at=n.attributes;for(i=at.length-1;i>-1;i--){no=at[i];if(no.specified&&no.nodeValue)el.setAttribute(no.nodeName.toLowerCase(),no.nodeValue)}if(!hc&&!this.closeElementsRe.test(n.nodeName))el.appendChild(xd.createTextNode(""));xn=xn.appendChild(el);break;case 3:xn.appendChild(xd.createTextNode(n.nodeValue));return;case 8:xn.appendChild(xd.createComment(n.nodeValue));return}if(hc){cn=n.childNodes;for(i=0,l=cn.length;i<l;i++)this._convertToXML(cn[i],xn)}},serializeNodeAsHTML:function(n,inn){var en,no,h='',i,l,t,st,r,cn,va=false,f=false,at,hc,cr,nn;this._setupRules();if(tinyMCE.isRealIE&&this._isDuplicate(n))return'';if(n.parentNode&&this.childRules!=null){cr=this.childRules[n.parentNode.nodeName];if(typeof(cr)!="undefined"&&!cr.test(n.nodeName)){st=true;t=null}}switch(n.nodeType){case 1:hc=n.hasChildNodes();if(st)break;if((tinyMCE.isRealIE)&&n.nodeName.indexOf('/')!=-1)break;nn=n.nodeName;if(this.settings.convert_fonts_to_spans){if(this.settings.on_save&&nn=='FONT')nn='SPAN';if(!this.settings.on_save&&nn=='SPAN')nn='FONT'}if(this.vElementsRe.test(nn)&&(!this.iveRe||!this.iveRe.test(nn))&&!inn){va=true;r=this.rules[nn];if(!r){at=this.rules;for(no in at){if(at[no]&&at[no].validRe.test(nn)){r=at[no];break}}}en=r.isWild?nn.toLowerCase():r.oTagName;f=r.fill;if(r.removeEmpty&&!hc)return"";t='<'+en;if(r.vAttribsReIsWild){at=n.attributes;for(i=at.length-1;i>-1;i--){no=at[i];if(no.specified&&r.vAttribsRe.test(no.nodeName))t+=this._serializeAttribute(n,r,no.nodeName)}}else{for(i=r.vAttribs.length-1;i>-1;i--)t+=this._serializeAttribute(n,r,r.vAttribs[i])}if(!this.settings.on_save){at=this.mceAttribs;for(no in at){if(at[no])t+=this._serializeAttribute(n,r,at[no])}}if(r.reqAttribsRe&&!t.match(r.reqAttribsRe))t=null;if(t!=null&&this.closeElementsRe.test(nn))return t+' />';if(t!=null)h+=t+'>';if(this.isIE&&this.codeElementsRe.test(nn))h+=n.innerHTML}break;case 3:if(st)break;if(n.parentNode&&this.codeElementsRe.test(n.parentNode.nodeName))return this.isIE?'':n.nodeValue;return this.xmlEncode(n.nodeValue);case 8:if(st)break;return"<!--"+this._trimComment(n.nodeValue)+"-->"}if(hc){cn=n.childNodes;for(i=0,l=cn.length;i<l;i++)h+=this.serializeNodeAsHTML(cn[i])}if(f&&!hc)h+=this.fillStr;if(t!=null&&va)h+='</'+en+'>';return h},_serializeAttribute:function(n,r,an){var av='',t,os=this.settings.on_save;if(os&&(an.indexOf('mce_')==0||an.indexOf('_moz')==0))return'';if(os&&this.mceAttribs[an])av=this._getAttrib(n,this.mceAttribs[an]);if(av.length==0)av=this._getAttrib(n,an);if(av.length==0&&r.defaultAttribs&&(t=r.defaultAttribs[an])){av=t;if(av=="mce_empty")return" "+an+'=""'}if(r.forceAttribs&&(t=r.forceAttribs[an]))av=t;if(os&&av.length!=0&&/^(src|href|longdesc)$/.test(an))av=this._urlConverter(this,n,av);if(av.length!=0&&r.validAttribValues&&r.validAttribValues[an]&&!r.validAttribValues[an].test(av))return"";if(av.length!=0&&av=="{$uid}")av="uid_"+(this.idCount++);if(av.length!=0){if(an.indexOf('on')!=0)av=this.xmlEncode(av,1);return" "+an+"="+'"'+av+'"'}return""},formatHTML:function(h){var s=this.settings,p='',i=0,li=0,o='',l;h=h.replace(/<pre([^>]*)>(.*?)<\/pre>/gi,function(a,b,c){c=c.replace(/<br\s*\/>/gi,'\n');return'<pre'+b+'>'+c+'</pre>'});h=h.replace(/\r/g,'');h='\n'+h;h=h.replace(new RegExp('\\n\\s+','gi'),'\n');h=h.replace(this.nlBeforeRe,'\n<$1$2>');h=h.replace(this.nlAfterRe,'<$1$2>\n');h=h.replace(this.nlBeforeAfterRe,'\n<$1$2$3>\n');h+='\n';while((i=h.indexOf('\n',i+1))!=-1){if((l=h.substring(li+1,i)).length!=0){if(this.ouRe.test(l)&&p.length>=s.indent_levels)p=p.substring(s.indent_levels);o+=p+l+'\n';if(this.inRe.test(l))p+=this.inStr}li=i}return o},xmlEncode:function(s,skip_apos){var cl=this,re=!skip_apos?this.xmlEncodeAposRe:this.xmlEncodeRe;this._setupEntities();switch(this.settings.entity_encoding){case"raw":return tinyMCE.xmlEncode(s,skip_apos);case"named":return s.replace(re,function(c,b){b=cl.entities[c.charCodeAt(0)];return b?'&'+b+';':c});case"numeric":return s.replace(re,function(c,b){return b?'&#'+c.charCodeAt(0)+';':c})}return s},split:function(re,s){var c=s.split(re);var i,l,o=new Array();for(i=0,l=c.length;i<l;i++){if(c[i]!='')o[i]=c[i]}return o},_trimComment:function(s){s=s.replace(new RegExp('\\smce_src=\"[^\"]*\"','gi'),"");s=s.replace(new RegExp('\\smce_href=\"[^\"]*\"','gi'),"");return s},_getAttrib:function(e,n,d){var v,ex,nn;if(typeof(d)=="undefined")d="";if(!e||e.nodeType!=1)return d;try{v=e.getAttribute(n,0)}catch(ex){v=e.getAttribute(n,2)}if(n=="class"&&!v)v=e.className;if(this.isIE){if(n=="http-equiv")v=e.httpEquiv;nn=e.nodeName;if(nn=="FORM"&&n=="enctype"&&v=="application/x-www-form-urlencoded")v="";if(nn=="INPUT"&&n=="size"&&v=="20")v="";if(nn=="INPUT"&&n=="maxlength"&&v=="2147483647")v=""}if(n=='style'&&v){if(!tinyMCE.isOpera)v=e.style.cssText;v=tinyMCE.serializeStyle(tinyMCE.parseStyle(v))}if(this.settings.on_save&&n.indexOf('on')!=-1&&this.settings.on_save&&v&&v!="")v=tinyMCE.cleanupEventStr(v);return(v&&v!="")?''+v:d},_urlConverter:function(c,n,v){if(!c.settings.on_save)return tinyMCE.convertRelativeToAbsoluteURL(tinyMCE.settings.base_href,v);else if(tinyMCE.getParam('convert_urls')){if(!this.urlConverter)this.urlConverter=eval(tinyMCE.settings.urlconverter_callback);return this.urlConverter(v,n,true)}return v},_arrayToRe:function(a,op,be,af){var i,r;op=typeof(op)=="undefined"?"gi":op;be=typeof(be)=="undefined"?"^(":be;af=typeof(af)=="undefined"?")$":af;r=be;for(i=0;i<a.length;i++)r+=this._wildcardToRe(a[i])+(i!=a.length-1?"|":"");r+=af;return new RegExp(r,op)},_wildcardToRe:function(s){s=s.replace(/\?/g,'(\\S?)');s=s.replace(/\+/g,'(\\S+)');s=s.replace(/\*/g,'(\\S*)');return s},_setupEntities:function(){var n,a,i,s=this.settings;if(!this.entitiesDone){if(s.entity_encoding=="named"){n=tinyMCE.clearArray(new Array());a=this.split(',',s.entities);for(i=0;i<a.length;i+=2)n[a[i]]=a[i+1];this.entities=n}this.entitiesDone=true}},_setupRules:function(){var s=this.settings;if(!this.rulesDone){this.addRuleStr(s.valid_elements);this.addRuleStr(s.extended_valid_elements);this.addChildRemoveRuleStr(s.valid_child_elements);this.rulesDone=true}},_isDuplicate:function(n){var i;if(!this.settings.fix_content_duplication)return false;if(tinyMCE.isRealIE&&n.nodeType==1){if(n.mce_serialized==this.serializationId)return true;n.setAttribute('mce_serialized',this.serializationId)}else{for(i=0;i<this.serializedNodes.length;i++){if(this.serializedNodes[i]==n)return true}this.serializedNodes[this.serializedNodes.length]=n}return false}};TinyMCE_Engine.prototype.createTagHTML=function(tn,a,h){var o='',f=tinyMCE.xmlEncode;o='<'+tn;if(a){for(n in a){if(typeof(a[n])!='function'&&a[n]!=null)o+=' '+f(n)+'="'+f(''+a[n])+'"'}}o+=!h?' />':'>'+h+'</'+tn+'>';return o};TinyMCE_Engine.prototype.createTag=function(d,tn,a,h){var o=d.createElement(tn);if(a){for(n in a){if(typeof(a[n])!='function'&&a[n]!=null)tinyMCE.setAttrib(o,n,a[n])}}if(h)o.innerHTML=h;return o};TinyMCE_Engine.prototype.getElementByAttributeValue=function(n,e,a,v){return(n=this.getElementsByAttributeValue(n,e,a,v)).length==0?null:n[0]};TinyMCE_Engine.prototype.getElementsByAttributeValue=function(n,e,a,v){var i,nl=n.getElementsByTagName(e),o=new Array();for(i=0;i<nl.length;i++){if(tinyMCE.getAttrib(nl[i],a).indexOf(v)!=-1)o[o.length]=nl[i]}return o};TinyMCE_Engine.prototype.isBlockElement=function(n){return n!=null&&n.nodeType==1&&this.blockRegExp.test(n.nodeName)};TinyMCE_Engine.prototype.getParentBlockElement=function(n,r){return this.getParentNode(n,function(n){return tinyMCE.isBlockElement(n)},r);return null};TinyMCE_Engine.prototype.insertAfter=function(n,r){if(r.nextSibling)r.parentNode.insertBefore(n,r.nextSibling);else r.parentNode.appendChild(n)};TinyMCE_Engine.prototype.setInnerHTML=function(e,h){var i,nl,n;if(tinyMCE.isGecko){h=h.replace(/<embed([^>]*)>/gi,'<tmpembed$1>');h=h.replace(/<em([^>]*)>/gi,'<i$1>');h=h.replace(/<tmpembed([^>]*)>/gi,'<embed$1>');h=h.replace(/<strong([^>]*)>/gi,'<b$1>');h=h.replace(/<\/strong>/gi,'</b>');h=h.replace(/<\/em>/gi,'</i>')}if(tinyMCE.isRealIE){h=h.replace(/\s\/>/g,'>');h=h.replace(/<p([^>]*)>\u00A0?<\/p>/gi,'<p$1 mce_keep="true">&nbsp;</p>');h=h.replace(/<p([^>]*)>\s*&nbsp;\s*<\/p>/gi,'<p$1 mce_keep="true">&nbsp;</p>');h=h.replace(/<p([^>]*)>\s+<\/p>/gi,'<p$1 mce_keep="true">&nbsp;</p>');e.innerHTML=tinyMCE.uniqueTag+h;e.firstChild.removeNode(true);nl=e.getElementsByTagName("p");for(i=nl.length-1;i>=0;i--){n=nl[i];if(n.nodeName=='P'&&!n.hasChildNodes()&&!n.mce_keep)n.parentNode.removeChild(n)}}else{h=this.fixGeckoBaseHREFBug(1,e,h);e.innerHTML=h;this.fixGeckoBaseHREFBug(2,e,h)}};TinyMCE_Engine.prototype.getOuterHTML=function(e){if(tinyMCE.isIE)return e.outerHTML;var d=e.ownerDocument.createElement("body");d.appendChild(e.cloneNode(true));return d.innerHTML};TinyMCE_Engine.prototype.setOuterHTML=function(e,h,d){var d=typeof(d)=="undefined"?e.ownerDocument:d,i,nl,t;if(tinyMCE.isIE&&e.nodeType==1)e.outerHTML=h;else{t=d.createElement("body");t.innerHTML=h;for(i=0,nl=t.childNodes;i<nl.length;i++)e.parentNode.insertBefore(nl[i].cloneNode(true),e);e.parentNode.removeChild(e)}};TinyMCE_Engine.prototype._getElementById=function(id,d){var e,i,j,f;if(typeof(d)=="undefined")d=document;e=d.getElementById(id);if(!e){f=d.forms;for(i=0;i<f.length;i++){for(j=0;j<f[i].elements.length;j++){if(f[i].elements[j].name==id){e=f[i].elements[j];break}}}}return e};TinyMCE_Engine.prototype.getNodeTree=function(n,na,t,nn){return this.selectNodes(n,function(n){return(!t||n.nodeType==t)&&(!nn||n.nodeName==nn)},na?na:new Array())};TinyMCE_Engine.prototype.getParentElement=function(n,na,f,r){var re=na?new RegExp('^('+na.toUpperCase().replace(/,/g,'|')+')$'):0,v;if(f&&typeof(f)=='string')return this.getParentElement(n,na,function(no){return tinyMCE.getAttrib(no,f)!=''});return this.getParentNode(n,function(n){return((n.nodeType==1&&!re)||(re&&re.test(n.nodeName)))&&(!f||f(n))},r)};TinyMCE_Engine.prototype.getParentNode=function(n,f,r){while(n){if(n==r)return null;if(f(n))return n;n=n.parentNode}return null};TinyMCE_Engine.prototype.getAttrib=function(elm,name,dv){var v;if(typeof(dv)=="undefined")dv="";if(!elm||elm.nodeType!=1)return dv;try{v=elm.getAttribute(name,0)}catch(ex){v=elm.getAttribute(name,2)}if(name=="class"&&!v)v=elm.className;if(tinyMCE.isGecko&&name=="src"&&elm.src!=null&&elm.src!="")v=elm.src;if(tinyMCE.isGecko&&name=="href"&&elm.href!=null&&elm.href!="")v=elm.href;if(name=="http-equiv"&&tinyMCE.isIE)v=elm.httpEquiv;if(name=="style"&&!tinyMCE.isOpera)v=elm.style.cssText;return(v&&v!="")?v:dv};TinyMCE_Engine.prototype.setAttrib=function(el,name,va,fix){if(typeof(va)=="number"&&va!=null)va=""+va;if(fix){if(va==null)va="";va=va.replace(/[^0-9%]/g,'')}if(name=="style")el.style.cssText=va;if(name=="class")el.className=va;if(va!=null&&va!=""&&va!=-1)el.setAttribute(name,va);else el.removeAttribute(name)};TinyMCE_Engine.prototype.setStyleAttrib=function(e,n,v){e.style[n]=v;if(tinyMCE.isIE&&v==null||v==''){v=tinyMCE.serializeStyle(tinyMCE.parseStyle(e.style.cssText));e.style.cssText=v;e.setAttribute("style",v)}};TinyMCE_Engine.prototype.switchClass=function(ei,c){var e;if(tinyMCE.switchClassCache[ei])e=tinyMCE.switchClassCache[ei];else e=tinyMCE.switchClassCache[ei]=document.getElementById(ei);if(e){if(tinyMCE.settings.button_tile_map&&e.className&&e.className.indexOf('mceTiledButton')==0)c='mceTiledButton '+c;e.className=c}};TinyMCE_Engine.prototype.getAbsPosition=function(n,cn){var l=0,t=0;while(n&&n!=cn){l+=n.offsetLeft;t+=n.offsetTop;n=n.offsetParent}return{absLeft:l,absTop:t}};TinyMCE_Engine.prototype.prevNode=function(e,n){var a=n.split(','),i;while((e=e.previousSibling)!=null){for(i=0;i<a.length;i++){if(e.nodeName==a[i])return e}}return null};TinyMCE_Engine.prototype.nextNode=function(e,n){var a=n.split(','),i;while((e=e.nextSibling)!=null){for(i=0;i<a.length;i++){if(e.nodeName==a[i])return e}}return null};TinyMCE_Engine.prototype.selectElements=function(n,na,f){var i,a=[],nl,x;for(x=0,na=na.split(',');x<na.length;x++)for(i=0,nl=n.getElementsByTagName(na[x]);i<nl.length;i++)(!f||f(nl[i]))&&a.push(nl[i]);return a};TinyMCE_Engine.prototype.selectNodes=function(n,f,a){var i;if(!a)a=new Array();if(f(n))a[a.length]=n;if(n.hasChildNodes()){for(i=0;i<n.childNodes.length;i++)tinyMCE.selectNodes(n.childNodes[i],f,a)}return a};TinyMCE_Engine.prototype.addCSSClass=function(e,c,b){var o=this.removeCSSClass(e,c);return e.className=b?c+(o!=''?(' '+o):''):(o!=''?(o+' '):'')+c};TinyMCE_Engine.prototype.removeCSSClass=function(e,c){c=e.className.replace(new RegExp("(^|\\s+)"+c+"(\\s+|$)"),' ');return e.className=c!=' '?c:''};TinyMCE_Engine.prototype.hasCSSClass=function(n,c){return new RegExp('\\b'+c+'\\b','g').test(n.className)};TinyMCE_Engine.prototype.renameElement=function(e,n,d){var ne,i,ar;d=typeof(d)=="undefined"?tinyMCE.selectedInstance.getDoc():d;if(e){ne=d.createElement(n);ar=e.attributes;for(i=ar.length-1;i>-1;i--){if(ar[i].specified&&ar[i].nodeValue)ne.setAttribute(ar[i].nodeName.toLowerCase(),ar[i].nodeValue)}ar=e.childNodes;for(i=0;i<ar.length;i++)ne.appendChild(ar[i].cloneNode(true));e.parentNode.replaceChild(ne,e)}};TinyMCE_Engine.prototype.getViewPort=function(w){var d=w.document,m=d.compatMode=='CSS1Compat',b=d.body,de=d.documentElement;return{left:w.pageXOffset||(m?de.scrollLeft:b.scrollLeft),top:w.pageYOffset||(m?de.scrollTop:b.scrollTop),width:w.innerWidth||(m?de.clientWidth:b.clientWidth),height:w.innerHeight||(m?de.clientHeight:b.clientHeight)}};TinyMCE_Engine.prototype.getStyle=function(n,na,d){if(!n)return false;if(tinyMCE.isGecko&&n.ownerDocument.defaultView){try{return n.ownerDocument.defaultView.getComputedStyle(n,null).getPropertyValue(na)}catch(n){return null}}na=na.replace(/-(\D)/g,function(a,b){return b.toUpperCase()});if(n.currentStyle)return n.currentStyle[na];return false};TinyMCE_Engine.prototype.parseURL=function(url_str){var urlParts=new Array();if(url_str){var pos,lastPos;pos=url_str.indexOf('://');if(pos!=-1){urlParts['protocol']=url_str.substring(0,pos);lastPos=pos+3}for(var i=lastPos;i<url_str.length;i++){var chr=url_str.charAt(i);if(chr==':')break;if(chr=='/')break}pos=i;urlParts['host']=url_str.substring(lastPos,pos);urlParts['port']="";lastPos=pos;if(url_str.charAt(pos)==':'){pos=url_str.indexOf('/',lastPos);urlParts['port']=url_str.substring(lastPos+1,pos)}lastPos=pos;pos=url_str.indexOf('?',lastPos);if(pos==-1)pos=url_str.indexOf('#',lastPos);if(pos==-1)pos=url_str.length;urlParts['path']=url_str.substring(lastPos,pos);lastPos=pos;if(url_str.charAt(pos)=='?'){pos=url_str.indexOf('#');pos=(pos==-1)?url_str.length:pos;urlParts['query']=url_str.substring(lastPos+1,pos)}lastPos=pos;if(url_str.charAt(pos)=='#'){pos=url_str.length;urlParts['anchor']=url_str.substring(lastPos+1,pos)}}return urlParts};TinyMCE_Engine.prototype.serializeURL=function(up){var o="";if(up['protocol'])o+=up['protocol']+"://";if(up['host'])o+=up['host'];if(up['port'])o+=":"+up['port'];if(up['path'])o+=up['path'];if(up['query'])o+="?"+up['query'];if(up['anchor'])o+="#"+up['anchor'];return o};TinyMCE_Engine.prototype.convertAbsoluteURLToRelativeURL=function(base_url,url_to_relative){var baseURL=this.parseURL(base_url);var targetURL=this.parseURL(url_to_relative);var strTok1;var strTok2;var breakPoint=0;var outPath="";var forceSlash=false;if(targetURL.path=="")targetURL.path="/";else forceSlash=true;base_url=baseURL.path.substring(0,baseURL.path.lastIndexOf('/'));strTok1=base_url.split('/');strTok2=targetURL.path.split('/');if(strTok1.length>=strTok2.length){for(var i=0;i<strTok1.length;i++){if(i>=strTok2.length||strTok1[i]!=strTok2[i]){breakPoint=i+1;break}}}if(strTok1.length<strTok2.length){for(var i=0;i<strTok2.length;i++){if(i>=strTok1.length||strTok1[i]!=strTok2[i]){breakPoint=i+1;break}}}if(breakPoint==1)return targetURL.path;for(var i=0;i<(strTok1.length-(breakPoint-1));i++)outPath+="../";for(var i=breakPoint-1;i<strTok2.length;i++){if(i!=(breakPoint-1))outPath+="/"+strTok2[i];else outPath+=strTok2[i]}targetURL.protocol=null;targetURL.host=null;targetURL.port=null;targetURL.path=outPath==""&&forceSlash?"/":outPath;var fileName=baseURL.path;var pos;if((pos=fileName.lastIndexOf('/'))!=-1)fileName=fileName.substring(pos+1);if(fileName==targetURL.path&&targetURL.anchor!="")targetURL.path="";if(targetURL.path==""&&!targetURL.anchor)targetURL.path=fileName!=""?fileName:"/";return this.serializeURL(targetURL)};TinyMCE_Engine.prototype.convertRelativeToAbsoluteURL=function(base_url,relative_url){var baseURL=this.parseURL(base_url),baseURLParts,relURLParts;var relURL=this.parseURL(relative_url);if(relative_url==""||relative_url.indexOf('://')!=-1||/^(mailto:|javascript:|#|\/)/.test(relative_url))return relative_url;baseURLParts=baseURL['path'].split('/');relURLParts=relURL['path'].split('/');var newBaseURLParts=new Array();for(var i=baseURLParts.length-1;i>=0;i--){if(baseURLParts[i].length==0)continue;newBaseURLParts[newBaseURLParts.length]=baseURLParts[i]}baseURLParts=newBaseURLParts.reverse();var newRelURLParts=new Array();var numBack=0;for(var i=relURLParts.length-1;i>=0;i--){if(relURLParts[i].length==0||relURLParts[i]==".")continue;if(relURLParts[i]=='..'){numBack++;continue}if(numBack>0){numBack--;continue}newRelURLParts[newRelURLParts.length]=relURLParts[i]}relURLParts=newRelURLParts.reverse();var len=baseURLParts.length-numBack;var absPath=(len<=0?"":"/")+baseURLParts.slice(0,len).join('/')+"/"+relURLParts.join('/');var start="",end="";relURL.protocol=baseURL.protocol;relURL.host=baseURL.host;relURL.port=baseURL.port;if(relURL.path.charAt(relURL.path.length-1)=="/")absPath+="/";relURL.path=absPath;return this.serializeURL(relURL)};TinyMCE_Engine.prototype.convertURL=function(url,node,on_save){var prot=document.location.protocol;var host=document.location.hostname;var port=document.location.port;if(prot=="file:")return url;url=tinyMCE.regexpReplace(url,'(http|https):///','/');if(url.indexOf('mailto:')!=-1||url.indexOf('javascript:')!=-1||tinyMCE.regexpReplace(url,'[ \t\r\n\+]|%20','').charAt(0)=="#")return url;if(!tinyMCE.isIE&&!on_save&&url.indexOf("://")==-1&&url.charAt(0)!='/')return tinyMCE.settings['base_href']+url;if(on_save&&tinyMCE.getParam('relative_urls')){var curl=tinyMCE.convertRelativeToAbsoluteURL(tinyMCE.settings['base_href'],url);if(curl.charAt(0)=='/')curl=tinyMCE.settings['document_base_prefix']+curl;var urlParts=tinyMCE.parseURL(curl);var tmpUrlParts=tinyMCE.parseURL(tinyMCE.settings['document_base_url']);if(urlParts['host']==tmpUrlParts['host']&&(urlParts['port']==tmpUrlParts['port']))return tinyMCE.convertAbsoluteURLToRelativeURL(tinyMCE.settings['document_base_url'],curl)}if(!tinyMCE.getParam('relative_urls')){var urlParts=tinyMCE.parseURL(url);var baseUrlParts=tinyMCE.parseURL(tinyMCE.settings['base_href']);url=tinyMCE.convertRelativeToAbsoluteURL(tinyMCE.settings['base_href'],url);if(urlParts['anchor']&&urlParts['path']==baseUrlParts['path'])return"#"+urlParts['anchor']}if(tinyMCE.getParam('remove_script_host')){var start="",portPart="";if(port!="")portPart=":"+port;start=prot+"//"+host+portPart+"/";if(url.indexOf(start)==0)url=url.substring(start.length-1)}return url};TinyMCE_Engine.prototype.convertAllRelativeURLs=function(body){var i,elms,src,href,mhref,msrc;elms=body.getElementsByTagName("img");for(i=0;i<elms.length;i++){src=tinyMCE.getAttrib(elms[i],'src');msrc=tinyMCE.getAttrib(elms[i],'mce_src');if(msrc!="")src=msrc;if(src!=""){src=tinyMCE.convertRelativeToAbsoluteURL(tinyMCE.settings['base_href'],src);elms[i].setAttribute("src",src)}}elms=body.getElementsByTagName("a");for(i=0;i<elms.length;i++){href=tinyMCE.getAttrib(elms[i],'href');mhref=tinyMCE.getAttrib(elms[i],'mce_href');if(mhref!="")href=mhref;if(href&&href!=""){href=tinyMCE.convertRelativeToAbsoluteURL(tinyMCE.settings['base_href'],href);elms[i].setAttribute("href",href)}}};TinyMCE_Engine.prototype.clearArray=function(a){var n;for(n in a)a[n]=null;return a};TinyMCE_Engine.prototype.explode=function(d,s){var ar=s.split(d),oar=new Array(),i;for(i=0;i<ar.length;i++){if(ar[i]!="")oar[oar.length]=ar[i]}return oar};TinyMCE_Engine.prototype._setEventsEnabled=function(node,state){var evs,x,y,elms,i,event;var events=['onfocus','onblur','onclick','ondblclick','onmousedown','onmouseup','onmouseover','onmousemove','onmouseout','onkeypress','onkeydown','onkeydown','onkeyup'];evs=tinyMCE.settings['event_elements'].split(',');for(y=0;y<evs.length;y++){elms=node.getElementsByTagName(evs[y]);for(i=0;i<elms.length;i++){event="";for(x=0;x<events.length;x++){if((event=tinyMCE.getAttrib(elms[i],events[x]))!=''){event=tinyMCE.cleanupEventStr(""+event);if(!state)event="return true;"+event;else event=event.replace(/^return true;/gi,'');elms[i].removeAttribute(events[x]);elms[i].setAttribute(events[x],event)}}}}};TinyMCE_Engine.prototype._eventPatch=function(editor_id){var n,inst,win,e;if(typeof(tinyMCE)=="undefined")return true;try{if(tinyMCE.selectedInstance){win=tinyMCE.selectedInstance.getWin();if(win&&win.event){e=win.event;if(!e.target)e.target=e.srcElement;TinyMCE_Engine.prototype.handleEvent(e);return}}for(n in tinyMCE.instances){inst=tinyMCE.instances[n];if(!tinyMCE.isInstance(inst))continue;inst.select();win=inst.getWin();if(win&&win.event){e=win.event;if(!e.target)e.target=e.srcElement;TinyMCE_Engine.prototype.handleEvent(e);return}}}catch(ex){}};TinyMCE_Engine.prototype.findEvent=function(e){var n,inst;if(e)return e;for(n in tinyMCE.instances){inst=tinyMCE.instances[n];if(tinyMCE.isInstance(inst)&&inst.getWin().event)return inst.getWin().event}return null};TinyMCE_Engine.prototype.unloadHandler=function(){tinyMCE.triggerSave(true,true)};TinyMCE_Engine.prototype.addEventHandlers=function(inst){this.setEventHandlers(inst,1)};TinyMCE_Engine.prototype.setEventHandlers=function(inst,s){var doc=inst.getDoc(),ie,ot,i,f=s?tinyMCE.addEvent:tinyMCE.removeEvent;ie=['keypress','keyup','keydown','click','mouseup','mousedown','controlselect','dblclick'];ot=['keypress','keyup','keydown','click','mouseup','mousedown','focus','blur','dragdrop'];inst.switchSettings();if(tinyMCE.isIE){for(i=0;i<ie.length;i++)f(doc,ie[i],TinyMCE_Engine.prototype._eventPatch)}else{for(i=0;i<ot.length;i++)f(doc,ot[i],tinyMCE.handleEvent);try{doc.designMode="On"}catch(e){}}};TinyMCE_Engine.prototype.onMouseMove=function(){var inst,lh;if(tinyMCE.lastHover){lh=tinyMCE.lastHover;if(lh.className.indexOf('mceMenu')!=-1)tinyMCE._menuButtonEvent('out',lh);else lh.className=lh.className;tinyMCE.lastHover=null}if(!tinyMCE.hasMouseMoved){inst=tinyMCE.selectedInstance;if(inst.isFocused){inst.undoBookmark=inst.selection.getBookmark();tinyMCE.hasMouseMoved=true}}};TinyMCE_Engine.prototype.cancelEvent=function(e){if(!e)return false;if(tinyMCE.isIE){e.returnValue=false;e.cancelBubble=true}else{e.preventDefault();e.stopPropagation&&e.stopPropagation()}return false};TinyMCE_Engine.prototype.addEvent=function(o,n,h){if(n!='unload'){function clean(){var ex;try{tinyMCE.removeEvent(o,n,h);tinyMCE.removeEvent(window,'unload',clean);o=n=h=null}catch(ex){}}tinyMCE.addEvent(window,'unload',clean)}if(o.attachEvent)o.attachEvent("on"+n,h);else o.addEventListener(n,h,false)};TinyMCE_Engine.prototype.removeEvent=function(o,n,h){if(o.detachEvent)o.detachEvent("on"+n,h);else o.removeEventListener(n,h,false)};TinyMCE_Engine.prototype.addSelectAccessibility=function(e,s,w){if(!s._isAccessible){s.onkeydown=tinyMCE.accessibleEventHandler;s.onblur=tinyMCE.accessibleEventHandler;s._isAccessible=true;s._win=w}return false};TinyMCE_Engine.prototype.accessibleEventHandler=function(e){var win=this._win;e=tinyMCE.isIE?win.event:e;var elm=tinyMCE.isIE?e.srcElement:e.target;if(e.type=="blur"){if(elm.oldonchange){elm.onchange=elm.oldonchange;elm.oldonchange=null}return true}if(elm.nodeName=="SELECT"&&!elm.oldonchange){elm.oldonchange=elm.onchange;elm.onchange=null}if(e.keyCode==13||e.keyCode==32){elm.onchange=elm.oldonchange;elm.onchange();elm.oldonchange=null;tinyMCE.cancelEvent(e);return false}return true};TinyMCE_Engine.prototype._resetIframeHeight=function(){var ife;if(tinyMCE.isRealIE){ife=tinyMCE.selectedInstance.iframeElement;if(ife._oldHeight){ife.style.height=ife._oldHeight;ife.height=ife._oldHeight}}};function TinyMCE_Selection(inst){this.instance=inst};TinyMCE_Selection.prototype={getSelectedHTML:function(){var inst=this.instance;var e,r=this.getRng(),h;if(!r)return null;e=document.createElement("body");if(r.cloneContents)e.appendChild(r.cloneContents());else if(typeof(r.item)!='undefined'||typeof(r.htmlText)!='undefined')e.innerHTML=r.item?r.item(0).outerHTML:r.htmlText;else e.innerHTML=r.toString();h=tinyMCE._cleanupHTML(inst,inst.contentDocument,inst.settings,e,e,false,true,false);return h},getSelectedText:function(){var inst=this.instance;var d,r,s,t;if(tinyMCE.isIE){d=inst.getDoc();if(d.selection.type=="Text"){r=d.selection.createRange();t=r.text}else t=''}else{s=this.getSel();if(s&&s.toString)t=s.toString();else t=''}return t},getBookmark:function(simple){var inst=this.instance;var rng=this.getRng();var doc=inst.getDoc(),b=inst.getBody();var sp,le,s,e,nl,i,si,ei,w;var trng,sx,sy,xx=-999999999,vp=inst.getViewPort();sx=vp.left;sy=vp.top;if(tinyMCE.isSafari||tinyMCE.isOpera||simple)return{rng:rng,scrollX:sx,scrollY:sy};if(tinyMCE.isIE){if(rng.item){e=rng.item(0);nl=b.getElementsByTagName(e.nodeName);for(i=0;i<nl.length;i++){if(e==nl[i]){sp=i;break}}return{tag:e.nodeName,index:sp,scrollX:sx,scrollY:sy}}else{trng=doc.body.createTextRange();trng.moveToElementText(inst.getBody());trng.collapse(true);bp=Math.abs(trng.move('character',xx));trng=rng.duplicate();trng.collapse(true);sp=Math.abs(trng.move('character',xx));trng=rng.duplicate();trng.collapse(false);le=Math.abs(trng.move('character',xx))-sp;return{start:sp-bp,length:le,scrollX:sx,scrollY:sy}}}if(tinyMCE.isGecko){s=this.getSel();e=this.getFocusElement();if(!s)return null;if(e&&e.nodeName=='IMG'){return{start:-1,end:-1,index:sp,scrollX:sx,scrollY:sy}}if(s.anchorNode==s.focusNode&&s.anchorOffset==s.focusOffset){e=this._getPosText(b,s.anchorNode,s.focusNode);if(!e)return{scrollX:sx,scrollY:sy};return{start:e.start+s.anchorOffset,end:e.end+s.focusOffset,scrollX:sx,scrollY:sy}}else{e=this._getPosText(b,rng.startContainer,rng.endContainer);if(!e)return{scrollX:sx,scrollY:sy};return{start:e.start+rng.startOffset,end:e.end+rng.endOffset,scrollX:sx,scrollY:sy}}}return null},moveToBookmark:function(bookmark){var inst=this.instance;var rng,nl,i,ex,b=inst.getBody(),sd;var doc=inst.getDoc();var win=inst.getWin();var sel=this.getSel();if(!bookmark)return false;if(tinyMCE.isSafari){sel.setBaseAndExtent(bookmark.rng.startContainer,bookmark.rng.startOffset,bookmark.rng.endContainer,bookmark.rng.endOffset);return true}if(tinyMCE.isRealIE){if(bookmark.rng){try{bookmark.rng.select()}catch(ex){}return true}win.focus();if(bookmark.tag){rng=b.createControlRange();nl=b.getElementsByTagName(bookmark.tag);if(nl.length>bookmark.index){try{rng.addElement(nl[bookmark.index])}catch(ex){}}}else{try{if(bookmark.start<0)return true;rng=inst.getSel().createRange();rng.moveToElementText(inst.getBody());rng.collapse(true);rng.moveStart('character',bookmark.start);rng.moveEnd('character',bookmark.length)}catch(ex){return true}}rng.select();win.scrollTo(bookmark.scrollX,bookmark.scrollY);return true}if(tinyMCE.isGecko||tinyMCE.isOpera){if(!sel)return false;if(bookmark.rng){sel.removeAllRanges();sel.addRange(bookmark.rng)}if(bookmark.start!=-1&&bookmark.end!=-1){try{sd=this._getTextPos(b,bookmark.start,bookmark.end);rng=doc.createRange();rng.setStart(sd.startNode,sd.startOffset);rng.setEnd(sd.endNode,sd.endOffset);sel.removeAllRanges();sel.addRange(rng);win.focus()}catch(ex){}}win.scrollTo(bookmark.scrollX,bookmark.scrollY);return true}return false},_getPosText:function(r,sn,en){var w=document.createTreeWalker(r,NodeFilter.SHOW_TEXT,null,false),n,p=0,d={};while((n=w.nextNode())!=null){if(n==sn)d.start=p;if(n==en){d.end=p;return d}p+=n.nodeValue?n.nodeValue.length:0}return null},_getTextPos:function(r,sp,ep){var w=document.createTreeWalker(r,NodeFilter.SHOW_TEXT,null,false),n,p=0,d={};while((n=w.nextNode())!=null){p+=n.nodeValue?n.nodeValue.length:0;if(p>=sp&&!d.startNode){d.startNode=n;d.startOffset=sp-(p-n.nodeValue.length)}if(p>=ep){d.endNode=n;d.endOffset=ep-(p-n.nodeValue.length);return d}}return null},selectNode:function(node,collapse,select_text_node,to_start){var inst=this.instance,sel,rng,nodes;if(!node)return;if(typeof(collapse)=="undefined")collapse=true;if(typeof(select_text_node)=="undefined")select_text_node=false;if(typeof(to_start)=="undefined")to_start=true;if(inst.settings.auto_resize)inst.resizeToContent();if(tinyMCE.isRealIE){rng=inst.getDoc().body.createTextRange();try{rng.moveToElementText(node);if(collapse)rng.collapse(to_start);rng.select()}catch(e){}}else{sel=this.getSel();if(!sel)return;if(tinyMCE.isSafari){sel.setBaseAndExtent(node,0,node,node.innerText.length);if(collapse){if(to_start)sel.collapseToStart();else sel.collapseToEnd()}this.scrollToNode(node);return}rng=inst.getDoc().createRange();if(select_text_node){nodes=tinyMCE.getNodeTree(node,new Array(),3);if(nodes.length>0)rng.selectNodeContents(nodes[0]);else rng.selectNodeContents(node)}else rng.selectNode(node);if(collapse){if(!to_start&&node.nodeType==3){rng.setStart(node,node.nodeValue.length);rng.setEnd(node,node.nodeValue.length)}else rng.collapse(to_start)}sel.removeAllRanges();sel.addRange(rng)}this.scrollToNode(node);tinyMCE.selectedElement=null;if(node.nodeType==1)tinyMCE.selectedElement=node},scrollToNode:function(node){var inst=this.instance,w=inst.getWin(),vp=inst.getViewPort(),pos=tinyMCE.getAbsPosition(node),cvp,p,cwin;if(pos.absLeft<vp.left||pos.absLeft>vp.left+vp.width||pos.absTop<vp.top||pos.absTop>vp.top+(vp.height-25))w.scrollTo(pos.absLeft,pos.absTop-vp.height+25);if(inst.settings.auto_resize){cwin=inst.getContainerWin();cvp=tinyMCE.getViewPort(cwin);p=this.getAbsPosition(node);if(p.absLeft<cvp.left||p.absLeft>cvp.left+cvp.width||p.absTop<cvp.top||p.absTop>cvp.top+cvp.height)cwin.scrollTo(p.absLeft,p.absTop-cvp.height+25)}},getAbsPosition:function(n){var pos=tinyMCE.getAbsPosition(n),ipos=tinyMCE.getAbsPosition(this.instance.iframeElement);return{absLeft:ipos.absLeft+pos.absLeft,absTop:ipos.absTop+pos.absTop}},getSel:function(){var inst=this.instance;if(tinyMCE.isRealIE)return inst.getDoc().selection;return inst.contentWindow.getSelection()},getRng:function(){var s=this.getSel();if(s==null)return null;if(tinyMCE.isRealIE)return s.createRange();if(tinyMCE.isSafari&&!s.getRangeAt)return''+window.getSelection();if(s.rangeCount>0)return s.getRangeAt(0);return null},isCollapsed:function(){var r=this.getRng();if(r.item)return false;return r.boundingWidth==0||this.getSel().isCollapsed},collapse:function(b){var r=this.getRng(),s=this.getSel();if(r.select){r.collapse(b);r.select()}else{if(b)s.collapseToStart();else s.collapseToEnd()}},getFocusElement:function(){var inst=this.instance,doc,rng,sel,elm;if(tinyMCE.isRealIE){doc=inst.getDoc();rng=doc.selection.createRange();elm=rng.item?rng.item(0):rng.parentElement()}else{if(!tinyMCE.isSafari&&inst.isHidden())return inst.getBody();sel=this.getSel();rng=this.getRng();if(!sel||!rng)return null;elm=rng.commonAncestorContainer;if(!rng.collapsed){if(rng.startContainer==rng.endContainer){if(rng.startOffset-rng.endOffset<2){if(rng.startContainer.hasChildNodes())elm=rng.startContainer.childNodes[rng.startOffset]}}}elm=tinyMCE.getParentElement(elm);}return elm}};function TinyMCE_UndoRedo(inst){this.instance=inst;this.undoLevels=new Array();this.undoIndex=0;this.typingUndoIndex=-1;this.undoRedo=true};TinyMCE_UndoRedo.prototype={add:function(l){var b,customUndoLevels,newHTML,inst=this.instance,i,ul,ur;if(l){this.undoLevels[this.undoLevels.length]=l;return true}if(this.typingUndoIndex!=-1){this.undoIndex=this.typingUndoIndex;if(tinyMCE.typingUndoIndex!=-1)tinyMCE.undoIndex=tinyMCE.typingUndoIndex}newHTML=tinyMCE.trim(inst.getBody().innerHTML);if(this.undoLevels[this.undoIndex]&&newHTML!=this.undoLevels[this.undoIndex].content){tinyMCE.dispatchCallback(inst,'onchange_callback','onChange',inst);customUndoLevels=tinyMCE.settings['custom_undo_redo_levels'];if(customUndoLevels!=-1&&this.undoLevels.length>customUndoLevels){for(i=0;i<this.undoLevels.length-1;i++)this.undoLevels[i]=this.undoLevels[i+1];this.undoLevels.length--;this.undoIndex--;}b=inst.undoBookmark;if(!b)b=inst.selection.getBookmark();this.undoIndex++;this.undoLevels[this.undoIndex]={content:newHTML,bookmark:b};ul=tinyMCE.undoLevels;for(i=tinyMCE.undoIndex+1;i<ul.length;i++){ur=ul[i].undoRedo;if(ur.undoIndex==ur.undoLevels.length-1)ur.undoIndex--;ur.undoLevels.length--}tinyMCE.undoLevels[tinyMCE.undoIndex++]=inst;tinyMCE.undoLevels.length=tinyMCE.undoIndex;this.undoLevels.length=this.undoIndex+1;return true}return false},undo:function(){var inst=this.instance;if(this.undoIndex>0){this.undoIndex--;tinyMCE.setInnerHTML(inst.getBody(),this.undoLevels[this.undoIndex].content);inst.repaint();if(inst.settings.custom_undo_redo_restore_selection)inst.selection.moveToBookmark(this.undoLevels[this.undoIndex].bookmark)}},redo:function(){var inst=this.instance;tinyMCE.execCommand("mceEndTyping");if(this.undoIndex<(this.undoLevels.length-1)){this.undoIndex++;tinyMCE.setInnerHTML(inst.getBody(),this.undoLevels[this.undoIndex].content);inst.repaint();if(inst.settings.custom_undo_redo_restore_selection)inst.selection.moveToBookmark(this.undoLevels[this.undoIndex].bookmark)}tinyMCE.triggerNodeChange()}};var TinyMCE_ForceParagraphs={_insertPara:function(inst,e){var doc=inst.getDoc(),sel=inst.getSel(),body=inst.getBody(),win=inst.contentWindow,rng=sel.getRangeAt(0);var rootElm=doc.documentElement,blockName="P",startNode,endNode,startBlock,endBlock;var rngBefore,rngAfter,direct,startNode,startOffset,endNode,endOffset,b=tinyMCE.isOpera?inst.selection.getBookmark():null;var paraBefore,paraAfter,startChop,endChop,contents;function isEmpty(para){function isEmptyHTML(html){return html.replace(new RegExp('[ \t\r\n]+','g'),'').toLowerCase()==""}if(para.getElementsByTagName("img").length>0)return false;if(para.getElementsByTagName("table").length>0)return false;if(para.getElementsByTagName("hr").length>0)return false;var nodes=tinyMCE.getNodeTree(para,new Array(),3);for(var i=0;i<nodes.length;i++){if(!isEmptyHTML(nodes[i].nodeValue))return false}return true}rngBefore=doc.createRange();rngBefore.setStart(sel.anchorNode,sel.anchorOffset);rngBefore.collapse(true);rngAfter=doc.createRange();rngAfter.setStart(sel.focusNode,sel.focusOffset);rngAfter.collapse(true);direct=rngBefore.compareBoundaryPoints(rngBefore.START_TO_END,rngAfter)<0;startNode=direct?sel.anchorNode:sel.focusNode;startOffset=direct?sel.anchorOffset:sel.focusOffset;endNode=direct?sel.focusNode:sel.anchorNode;endOffset=direct?sel.focusOffset:sel.anchorOffset;startNode=startNode.nodeName=="BODY"?startNode.firstChild:startNode;endNode=endNode.nodeName=="BODY"?endNode.firstChild:endNode;startBlock=inst.getParentBlockElement(startNode);endBlock=inst.getParentBlockElement(endNode);if(startBlock&&new RegExp('absolute|relative|static','gi').test(startBlock.style.position))startBlock=null;if(endBlock&&new RegExp('absolute|relative|static','gi').test(endBlock.style.position))endBlock=null;if(startBlock!=null){blockName=startBlock.nodeName;if(blockName=="TD"||blockName=="TABLE"||(blockName=="DIV"&&new RegExp('left|right','gi').test(startBlock.style.cssFloat)))blockName="P"}if(tinyMCE.getParentElement(startBlock,"OL,UL",null,body)!=null)return false;if((startBlock!=null&&startBlock.nodeName=="TABLE")||(endBlock!=null&&endBlock.nodeName=="TABLE"))startBlock=endBlock=null;paraBefore=(startBlock!=null&&startBlock.nodeName==blockName)?startBlock.cloneNode(false):doc.createElement(blockName);paraAfter=(endBlock!=null&&endBlock.nodeName==blockName)?endBlock.cloneNode(false):doc.createElement(blockName);if(/^(H[1-6])$/.test(blockName))paraAfter=doc.createElement("p");startChop=startNode;endChop=endNode;node=startChop;do{if(node==body||node.nodeType==9||tinyMCE.isBlockElement(node))break;startChop=node}while((node=node.previousSibling?node.previousSibling:node.parentNode));node=endChop;do{if(node==body||node.nodeType==9||tinyMCE.isBlockElement(node))break;endChop=node}while((node=node.nextSibling?node.nextSibling:node.parentNode));if(startChop.nodeName=="TD")startChop=startChop.firstChild;if(endChop.nodeName=="TD")endChop=endChop.lastChild;if(startBlock==null){rng.deleteContents();if(!tinyMCE.isSafari)sel.removeAllRanges();if(startChop!=rootElm&&endChop!=rootElm){rngBefore=rng.cloneRange();if(startChop==body)rngBefore.setStart(startChop,0);else rngBefore.setStartBefore(startChop);paraBefore.appendChild(rngBefore.cloneContents());if(endChop.parentNode.nodeName==blockName)endChop=endChop.parentNode;rng.setEndAfter(endChop);if(endChop.nodeName!="#text"&&endChop.nodeName!="BODY")rngBefore.setEndAfter(endChop);contents=rng.cloneContents();if(contents.firstChild&&(contents.firstChild.nodeName==blockName||contents.firstChild.nodeName=="BODY"))paraAfter.innerHTML=contents.firstChild.innerHTML;else paraAfter.appendChild(contents);if(isEmpty(paraBefore))paraBefore.innerHTML="&nbsp;";if(isEmpty(paraAfter))paraAfter.innerHTML="&nbsp;";rng.deleteContents();rngAfter.deleteContents();rngBefore.deleteContents();if(tinyMCE.isOpera){paraBefore.normalize();rngBefore.insertNode(paraBefore);paraAfter.normalize();rngBefore.insertNode(paraAfter)}else{paraAfter.normalize();rngBefore.insertNode(paraAfter);paraBefore.normalize();rngBefore.insertNode(paraBefore)}}else{body.innerHTML="<"+blockName+">&nbsp;</"+blockName+"><"+blockName+">&nbsp;</"+blockName+">";paraAfter=body.childNodes[1]}inst.selection.moveToBookmark(b);inst.selection.selectNode(paraAfter,true,true);return true}if(startChop.nodeName==blockName)rngBefore.setStart(startChop,0);else rngBefore.setStartBefore(startChop);rngBefore.setEnd(startNode,startOffset);paraBefore.appendChild(rngBefore.cloneContents());rngAfter.setEndAfter(endChop);rngAfter.setStart(endNode,endOffset);contents=rngAfter.cloneContents();if(contents.firstChild&&contents.firstChild.nodeName==blockName){paraAfter.innerHTML=contents.firstChild.innerHTML}else paraAfter.appendChild(contents);if(isEmpty(paraBefore))paraBefore.innerHTML="&nbsp;";if(isEmpty(paraAfter))paraAfter.innerHTML="&nbsp;";rng=doc.createRange();if(!startChop.previousSibling&&startChop.parentNode.nodeName.toUpperCase()==blockName){rng.setStartBefore(startChop.parentNode)}else{if(rngBefore.startContainer.nodeName.toUpperCase()==blockName&&rngBefore.startOffset==0)rng.setStartBefore(rngBefore.startContainer);else rng.setStart(rngBefore.startContainer,rngBefore.startOffset)}if(!endChop.nextSibling&&endChop.parentNode.nodeName.toUpperCase()==blockName)rng.setEndAfter(endChop.parentNode);else rng.setEnd(rngAfter.endContainer,rngAfter.endOffset);rng.deleteContents();if(tinyMCE.isOpera){rng.insertNode(paraBefore);rng.insertNode(paraAfter)}else{rng.insertNode(paraAfter);rng.insertNode(paraBefore)}paraAfter.normalize();paraBefore.normalize();inst.selection.moveToBookmark(b);inst.selection.selectNode(paraAfter,true,true);return true},_handleBackSpace:function(inst){var r=inst.getRng(),sn=r.startContainer,nv,s=false;if(sn&&sn.nextSibling&&sn.nextSibling.nodeName=="BR"&&sn.parentNode.nodeName!="BODY"){nv=sn.nodeValue;if(nv!=null&&r.startOffset==nv.length)sn.nextSibling.parentNode.removeChild(sn.nextSibling)}if(inst.settings.auto_resize)inst.resizeToContent();return s}};function TinyMCE_Layer(id,bm){this.id=id;this.blockerElement=null;this.events=false;this.element=null;this.blockMode=typeof(bm)!='undefined'?bm:true;this.doc=document};TinyMCE_Layer.prototype={moveRelativeTo:function(re,p){var rep=this.getAbsPosition(re);var w=parseInt(re.offsetWidth);var h=parseInt(re.offsetHeight);var e=this.getElement();var ew=parseInt(e.offsetWidth);var eh=parseInt(e.offsetHeight);var x,y;switch(p){case"tl":x=rep.absLeft;y=rep.absTop;break;case"tr":x=rep.absLeft+w;y=rep.absTop;break;case"bl":x=rep.absLeft;y=rep.absTop+h;break;case"br":x=rep.absLeft+w;y=rep.absTop+h;break;case"cc":x=rep.absLeft+(w/ 2) - (ew /2);y=rep.absTop+(h/ 2) - (eh /2);break}this.moveTo(x,y)},moveBy:function(x,y){var e=this.getElement();this.moveTo(parseInt(e.style.left)+x,parseInt(e.style.top)+y)},moveTo:function(x,y){var e=this.getElement();e.style.left=x+"px";e.style.top=y+"px";this.updateBlocker()},resizeBy:function(w,h){var e=this.getElement();this.resizeTo(parseInt(e.style.width)+w,parseInt(e.style.height)+h)},resizeTo:function(w,h){var e=this.getElement();if(w!=null)e.style.width=w+"px";if(h!=null)e.style.height=h+"px";this.updateBlocker()},show:function(){var el=this.getElement();if(el){el.style.display='block';this.updateBlocker()}},hide:function(){var el=this.getElement();if(el){el.style.display='none';this.updateBlocker()}},isVisible:function(){return this.getElement().style.display=='block'},getElement:function(){if(!this.element)this.element=this.doc.getElementById(this.id);return this.element},setBlockMode:function(s){this.blockMode=s},updateBlocker:function(){var e,b,x,y,w,h;b=this.getBlocker();if(b){if(this.blockMode){e=this.getElement();x=this.parseInt(e.style.left);y=this.parseInt(e.style.top);w=this.parseInt(e.offsetWidth);h=this.parseInt(e.offsetHeight);b.style.left=x+'px';b.style.top=y+'px';b.style.width=w+'px';b.style.height=h+'px';b.style.display=e.style.display}else b.style.display='none'}},getBlocker:function(){var d,b;if(!this.blockerElement&&this.blockMode){d=this.doc;b=d.getElementById(this.id+"_blocker");if(!b){b=d.createElement("iframe");b.setAttribute('id',this.id+"_blocker");b.style.cssText='display: none; position: absolute; left: 0; top: 0';b.src='javascript:false;';b.frameBorder='0';b.scrolling='no';d.body.appendChild(b)}this.blockerElement=b}return this.blockerElement},getAbsPosition:function(n){var p={absLeft:0,absTop:0};while(n){p.absLeft+=n.offsetLeft;p.absTop+=n.offsetTop;n=n.offsetParent}return p},create:function(n,c,p,h){var d=this.doc,e=d.createElement(n);e.setAttribute('id',this.id);if(c)e.className=c;if(!p)p=d.body;if(h)e.innerHTML=h;p.appendChild(e);return this.element=e},exists:function(){return this.doc.getElementById(this.id)!=null},parseInt:function(s){if(s==null||s=='')return 0;return parseInt(s)},remove:function(){var e=this.getElement(),b=this.getBlocker();if(e)e.parentNode.removeChild(e);if(b)b.parentNode.removeChild(b)}};function TinyMCE_Menu(){var id;if(typeof(tinyMCE.menuCounter)=="undefined")tinyMCE.menuCounter=0;id="mc_menu_"+tinyMCE.menuCounter++;TinyMCE_Layer.call(this,id,true);this.id=id;this.items=new Array();this.needsUpdate=true};TinyMCE_Menu.prototype=tinyMCE.extend(TinyMCE_Layer.prototype,{init:function(s){var n;this.settings={separator_class:'mceMenuSeparator',title_class:'mceMenuTitle',disabled_class:'mceMenuDisabled',menu_class:'mceMenu',drop_menu:true};for(n in s)this.settings[n]=s[n];this.create('div',this.settings.menu_class)},clear:function(){this.items=new Array()},addTitle:function(t){this.add({type:'title',text:t})},addDisabled:function(t){this.add({type:'disabled',text:t})},addSeparator:function(){this.add({type:'separator'})},addItem:function(t,js){this.add({text:t,js:js})},add:function(mi){this.items[this.items.length]=mi;this.needsUpdate=true},update:function(){var e=this.getElement(),h='',i,t,m=this.items,s=this.settings;if(this.settings.drop_menu)h+='<span class="mceMenuLine"></span>';h+='<table border="0" cellpadding="0" cellspacing="0">';for(i=0;i<m.length;i++){t=tinyMCE.xmlEncode(m[i].text);c=m[i].class_name?' class="'+m[i].class_name+'"':'';switch(m[i].type){case'separator':h+='<tr class="'+s.separator_class+'"><td>';break;case'title':h+='<tr class="'+s.title_class+'"><td><span'+c+'>'+t+'</span>';break;case'disabled':h+='<tr class="'+s.disabled_class+'"><td><span'+c+'>'+t+'</span>';break;default:h+='<tr><td><a href="'+tinyMCE.xmlEncode(m[i].js)+'" onmousedown="'+tinyMCE.xmlEncode(m[i].js)+';return tinyMCE.cancelEvent(event);" onclick="return tinyMCE.cancelEvent(event);" onmouseup="return tinyMCE.cancelEvent(event);"><span'+c+'>'+t+'</span></a>'}h+='</td></tr>'}h+='</table>';e.innerHTML=h;this.needsUpdate=false;this.updateBlocker()},show:function(){var nl,i;if(tinyMCE.lastMenu==this)return;if(this.needsUpdate)this.update();if(tinyMCE.lastMenu&&tinyMCE.lastMenu!=this)tinyMCE.lastMenu.hide();TinyMCE_Layer.prototype.show.call(this);if(!tinyMCE.isOpera){}tinyMCE.lastMenu=this}});if(!Function.prototype.call){Function.prototype.call=function(){var a=arguments,s=a[0],i,as='',r,o;for(i=1;i<a.length;i++)as+=(i>1?',':'')+'a['+i+']';o=s._fu;s._fu=this;r=eval('s._fu('+as+')');s._fu=o;return r}};TinyMCE_Engine.prototype.debug=function(){var m="",a,i,l=tinyMCE.log.length;for(i=0,a=this.debug.arguments;i<a.length;i++){m+=a[i];if(i<a.length-1)m+=', '}if(l<1000)tinyMCE.log[l]="[debug] "+m};
\ No newline at end of file
+var tinymce={majorVersion:'3',minorVersion:'0',releaseDate:'2008-01-30',_init:function(){var t=this,ua=navigator.userAgent,i,nl,n,base;t.isOpera=window.opera&&opera.buildNumber;t.isWebKit=/WebKit/.test(ua);t.isOldWebKit=t.isWebKit&&!window.getSelection().getRangeAt;t.isIE=!t.isWebKit&&!t.isOpera&&(/MSIE/gi).test(ua)&&(/Explorer/gi).test(navigator.appName);t.isIE6=t.isIE&&/MSIE [56]/.test(ua);t.isGecko=!t.isWebKit&&/Gecko/.test(ua);t.isMac=ua.indexOf('Mac')!=-1;if(window.tinyMCEPreInit){t.suffix=tinyMCEPreInit.suffix;t.baseURL=tinyMCEPreInit.base;return;}t.suffix='';nl=document.getElementsByTagName('base');for(i=0;i<nl.length;i++){if(nl[i].href)base=nl[i].href;}function getBase(n){if(n.src&&/tiny_mce(|_dev|_src|_gzip|_jquery|_prototype).js/.test(n.src)){if(/_(src|dev)\.js/g.test(n.src))t.suffix='_src';t.baseURL=n.src.substring(0,n.src.lastIndexOf('/'));if(base&&t.baseURL.indexOf('://')==-1)t.baseURL=base+t.baseURL;return t.baseURL;}return null;};nl=document.getElementsByTagName('script');for(i=0;i<nl.length;i++){if(getBase(nl[i]))return;}n=document.getElementsByTagName('head')[0];if(n){nl=n.getElementsByTagName('script');for(i=0;i<nl.length;i++){if(getBase(nl[i]))return;}}return;},is:function(o,t){var n=typeof(o);if(!t)return n!='undefined';if(t=='array'&&(o instanceof Array))return true;return n==t;},each:function(o,cb,s){var n,l;if(!o)return 0;s=s||o;if(typeof(o.length)!='undefined'){for(n=0,l=o.length;n<l;n++){if(cb.call(s,o[n],n,o)===false)return 0;}}else{for(n in o){if(o.hasOwnProperty(n)){if(cb.call(s,o[n],n,o)===false)return 0;}}}return 1;},map:function(a,f){var o=[];tinymce.each(a,function(v){o.push(f(v));});return o;},grep:function(a,f){var o=[];tinymce.each(a,function(v){if(!f||f(v))o.push(v);});return o;},inArray:function(a,v){var i,l;if(a){for(i=0,l=a.length;i<l;i++){if(a[i]===v)return i;}}return-1;},extend:function(o,e){var i,a=arguments;for(i=1;i<a.length;i++){e=a[i];tinymce.each(e,function(v,n){if(typeof(v)!=='undefined')o[n]=v;});}return o;},trim:function(s){return(s?''+s:'').replace(/^\s*|\s*$/g,'');},create:function(s,p){var t=this,sp,ns,cn,scn,c,de=0;s=/^((static) )?([\w.]+)(:([\w.]+))?/.exec(s);cn=s[3].match(/(^|\.)(\w+)$/i)[2];ns=t.createNS(s[3].replace(/\.\w+$/,''));if(ns[cn])return;if(s[2]=='static'){ns[cn]=p;if(this.onCreate)this.onCreate(s[2],s[3],ns[cn]);return;}if(!p[cn]){p[cn]=function(){};de=1;}ns[cn]=p[cn];t.extend(ns[cn].prototype,p);if(s[5]){sp=t.resolve(s[5]).prototype;scn=s[5].match(/\.(\w+)$/i)[1];c=ns[cn];if(de){ns[cn]=function(){return sp[scn].apply(this,arguments);};}else{ns[cn]=function(){this.parent=sp[scn];return c.apply(this,arguments);};}ns[cn].prototype[cn]=ns[cn];t.each(sp,function(f,n){if(n!=scn)ns[cn].prototype[n]=sp[n];});t.each(p,function(f,n){if(sp[n]){ns[cn].prototype[n]=function(){this.parent=sp[n];return f.apply(this,arguments);};}else{if(n!=cn)ns[cn].prototype[n]=f;}});}t.each(p['static'],function(f,n){ns[cn][n]=f;});if(this.onCreate)this.onCreate(s[2],s[3],ns[cn].prototype);},walk:function(o,f,n,s){s=s||this;if(o){if(n)o=o[n];tinymce.each(o,function(o,i){if(f.call(s,o,i,n)===false)return false;tinymce.walk(o,f,n,s);});}},createNS:function(n,o){var i,v;o=o||window;n=n.split('.');for(i=0;i<n.length;i++){v=n[i];if(!o[v])o[v]={};o=o[v];}return o;},resolve:function(n,o){var i,l;o=o||window;n=n.split('.');for(i=0,l=n.length;i<l;i++){o=o[n[i]];if(!o)break;}return o;},addUnload:function(f,s){var t=this,w=window,unload;f={func:f,scope:s||this};if(!t.unloads){unload=function(){var li=t.unloads,o,n;for(n in li){o=li[n];if(o&&o.func)o.func.call(o.scope);}if(w.detachEvent)w.detachEvent('onunload',unload);else if(w.removeEventListener)w.removeEventListener('unload',unload,false);o=li=w=unload=null;if(window.CollectGarbage)window.CollectGarbage();};if(w.attachEvent)w.attachEvent('onunload',unload);else if(w.addEventListener)w.addEventListener('unload',unload,false);t.unloads=[f];}else t.unloads.push(f);return f;},removeUnload:function(f){var u=this.unloads,r=null;tinymce.each(u,function(o,i){if(o&&o.func==f){u.splice(i,1);r=f;return false;}});return r;}};window.tinymce=tinymce;tinymce._init();tinymce.create('tinymce.util.Dispatcher',{scope:null,listeners:null,Dispatcher:function(s){this.scope=s||this;this.listeners=[];},add:function(cb,s){this.listeners.push({cb:cb,scope:s||this.scope});return cb;},addToTop:function(cb,s){this.listeners.unshift({cb:cb,scope:s||this.scope});return cb;},remove:function(cb){var l=this.listeners,o=null;tinymce.each(l,function(c,i){if(cb==c.cb){o=cb;l.splice(i,1);return false;}});return o;},dispatch:function(){var s,a=arguments;tinymce.each(this.listeners,function(c){return s=c.cb.apply(c.scope,a);});return s;}});(function(){var each=tinymce.each;tinymce.create('tinymce.util.URI',{URI:function(u,s){var t=this,o,a,b;s=t.settings=s||{};if(/^(mailto|news|javascript|about):/i.test(u)||/^\s*#/.test(u)){t.source=u;return;}if(u.indexOf('/')===0&&u.indexOf('//')!==0)u=(s.base_uri?s.base_uri.protocol||'http':'http')+'://mce_host'+u;if(u.indexOf('://')===-1&&u.indexOf('//')!==0)u=(s.base_uri.protocol||'http')+'://mce_host'+t.toAbsPath(s.base_uri.path,u);u=u.replace(/@@/g,'(mce_at)');u=/^(?:(?![^:@]+:[^:@\/]*@)([^:\/?#.]+):)?(?:\/\/)?((?:(([^:@]*):?([^:@]*))?@)?([^:\/?#]*)(?::(\d*))?)(((\/(?:[^?#](?![^?#\/]*\.[^?#\/.]+(?:[?#]|$)))*\/?)?([^?#\/]*))(?:\?([^#]*))?(?:#(.*))?)/.exec(u);each(["source","protocol","authority","userInfo","user","password","host","port","relative","path","directory","file","query","anchor"],function(v,i){var s=u[i];if(s)s=s.replace(/\(mce_at\)/g,'@@');t[v]=s;});if(b=s.base_uri){if(!t.protocol)t.protocol=b.protocol;if(!t.userInfo)t.userInfo=b.userInfo;if(!t.port&&t.host=='mce_host')t.port=b.port;if(!t.host||t.host=='mce_host')t.host=b.host;t.source='';}},setPath:function(p){var t=this;p=/^(.*?)\/?(\w+)?$/.exec(p);t.path=p[0];t.directory=p[1];t.file=p[2];t.source='';t.getURI();},toRelative:function(u){var t=this,o;u=new tinymce.util.URI(u,{base_uri:t});if((u.host!='mce_host'&&t.host!=u.host&&u.host)||t.port!=u.port||t.protocol!=u.protocol)return u.getURI();o=t.toRelPath(t.path,u.path);if(u.query)o+='?'+u.query;if(u.anchor)o+='#'+u.anchor;return o;},toAbsolute:function(u,nh){var u=new tinymce.util.URI(u,{base_uri:this});return u.getURI(this.host==u.host?nh:0);},toRelPath:function(base,path){var items,bp=0,out='',i;base=base.substring(0,base.lastIndexOf('/'));base=base.split('/');items=path.split('/');if(base.length>=items.length){for(i=0;i<base.length;i++){if(i>=items.length||base[i]!=items[i]){bp=i+1;break;}}}if(base.length<items.length){for(i=0;i<items.length;i++){if(i>=base.length||base[i]!=items[i]){bp=i+1;break;}}}if(bp==1)return path;for(i=0;i<base.length-(bp-1);i++)out+="../";for(i=bp-1;i<items.length;i++){if(i!=bp-1)out+="/"+items[i];else out+=items[i];}return out;},toAbsPath:function(base,path){var i,nb=0,o=[];base=base.split('/');path=path.split('/');each(base,function(k){if(k)o.push(k);});base=o;for(i=path.length-1,o=[];i>=0;i--){if(path[i].length==0||path[i]==".")continue;if(path[i]=='..'){nb++;continue;}if(nb>0){nb--;continue;}o.push(path[i]);}i=base.length-nb;if(i<=0)return'/'+o.reverse().join('/');return'/'+base.slice(0,i).join('/')+'/'+o.reverse().join('/');},getURI:function(nh){var s,t=this;if(!t.source||nh){s='';if(!nh){if(t.protocol)s+=t.protocol+'://';if(t.userInfo)s+=t.userInfo+'@';if(t.host)s+=t.host;if(t.port)s+=':'+t.port;}if(t.path)s+=t.path;if(t.query)s+='?'+t.query;if(t.anchor)s+='#'+t.anchor;t.source=s;}return t.source;}});})();(function(){var each=tinymce.each;tinymce.create('static tinymce.util.Cookie',{getHash:function(n){var v=this.get(n),h;if(v){each(v.split('&'),function(v){v=v.split('=');h=h||{};h[unescape(v[0])]=unescape(v[1]);});}return h;},setHash:function(n,v,e,p,d,s){var o='';each(v,function(v,k){o+=(!o?'':'&')+escape(k)+'='+escape(v);});this.set(n,o,e,p,d,s);},get:function(n){var c=document.cookie,e,p=n+"=",b;if(!c)return;b=c.indexOf("; "+p);if(b==-1){b=c.indexOf(p);if(b!=0)return null;}else b+=2;e=c.indexOf(";",b);if(e==-1)e=c.length;return unescape(c.substring(b+p.length,e));},set:function(n,v,e,p,d,s){document.cookie=n+"="+escape(v)+((e)?"; expires="+e.toGMTString():"")+((p)?"; path="+escape(p):"")+((d)?"; domain="+d:"")+((s)?"; secure":"");},remove:function(n,p){var d=new Date();d.setTime(d.getTime()-1000);this.set(n,'',d,p,d);}});})();tinymce.create('static tinymce.util.JSON',{serialize:function(o){var i,v,s=tinymce.util.JSON.serialize,t;if(o==null)return'null';t=typeof o;if(t=='string'){v='\bb\tt\nn\ff\rr\""\'\'\\\\';return'"'+o.replace(/([\u0080-\uFFFF\x00-\x1f\"\'])/g,function(a,b){i=v.indexOf(b);if(i+1)return'\\'+v.charAt(i+1);a=b.charCodeAt().toString(16);return'\\u'+'0000'.substring(a.length)+a;})+'"';}if(t=='object'){if(o instanceof Array){for(i=0,v='[';i<o.length;i++)v+=(i>0?',':'')+s(o[i]);return v+']';}v='{';for(i in o)v+=typeof o[i]!='function'?(v.length>1?',"':'"')+i+'":'+s(o[i]):'';return v+'}';}return''+o;},parse:function(s){try{return eval('('+s+')');}catch(ex){}}});tinymce.create('static tinymce.util.XHR',{send:function(o){var x,t,w=window,c=0;o.scope=o.scope||this;o.success_scope=o.success_scope||o.scope;o.error_scope=o.error_scope||o.scope;o.async=o.async===false?false:true;o.data=o.data||'';function get(s){x=0;try{x=new ActiveXObject(s);}catch(ex){}return x;};x=w.XMLHttpRequest?new XMLHttpRequest():get('Microsoft.XMLHTTP')||get('Msxml2.XMLHTTP');if(x){if(x.overrideMimeType)x.overrideMimeType(o.content_type);x.open(o.type||(o.data?'POST':'GET'),o.url,o.async);if(o.content_type)x.setRequestHeader('Content-Type',o.content_type);x.send(o.data);t=w.setInterval(function(){if(x.readyState==4||c++>10000){w.clearInterval(t);if(o.success&&c<10000&&x.status==200)o.success.call(o.success_scope,''+x.responseText,x,o);else if(o.error)o.error.call(o.error_scope,c>10000?'TIMED_OUT':'GENERAL',x,o);x=null;}},10);}}});(function(){var extend=tinymce.extend,JSON=tinymce.util.JSON,XHR=tinymce.util.XHR;tinymce.create('tinymce.util.JSONRequest',{JSONRequest:function(s){this.settings=extend({},s);this.count=0;},send:function(o){var ecb=o.error,scb=o.success;o=extend(this.settings,o);o.success=function(c,x){c=JSON.parse(c);if(typeof(c)=='undefined'){c={error:'JSON Parse error.'};}if(c.error)ecb.call(o.error_scope||o.scope,c.error,x);else scb.call(o.success_scope||o.scope,c.result);};o.error=function(ty,x){ecb.call(o.error_scope||o.scope,ty,x);};o.data=JSON.serialize({id:o.id||'c'+(this.count++),method:o.method,params:o.params});XHR.send(o);},'static':{sendRPC:function(o){return new tinymce.util.JSONRequest().send(o);}}});}());(function(){var each=tinymce.each,is=tinymce.is;var isWebKit=tinymce.isWebKit,isIE=tinymce.isIE;tinymce.create('tinymce.dom.DOMUtils',{doc:null,root:null,files:null,listeners:{},pixelStyles:/^(top|left|bottom|right|width|height|borderWidth)$/,cache:{},idPattern:/^#[\w]+$/,elmPattern:/^[\w_*]+$/,elmClassPattern:/^([\w_]*)\.([\w_]+)$/,DOMUtils:function(d,s){var t=this;t.doc=d;t.files={};t.cssFlicker=false;t.counter=0;t.boxModel=!tinymce.isIE||d.compatMode=="CSS1Compat";this.settings=s=tinymce.extend({keep_values:false,hex_colors:1,process_html:1},s);if(tinymce.isIE6){try{d.execCommand('BackgroundImageCache',false,true);}catch(e){t.cssFlicker=true;}}tinymce.addUnload(function(){t.doc=t.root=null;});},getRoot:function(){var t=this,s=t.settings;return(s&&t.get(s.root_element))||t.doc.body;},getViewPort:function(w){var d,b;w=!w?window:w;d=w.document;b=this.boxModel?d.documentElement:d.body;return{x:w.pageXOffset||b.scrollLeft,y:w.pageYOffset||b.scrollTop,w:w.innerWidth||b.clientWidth,h:w.innerHeight||b.clientHeight};},getRect:function(e){var p,t=this,w,h;e=t.get(e);p=t.getPos(e);w=t.getStyle(e,'width');h=t.getStyle(e,'height');if(w.indexOf('px')===-1)w=0;if(h.indexOf('px')===-1)h=0;return{x:p.x,y:p.y,w:parseInt(w)||e.offsetWidth||e.clientWidth,h:parseInt(h)||e.offsetHeight||e.clientHeight};},getParent:function(n,f,r){var na,se=this.settings;n=this.get(n);if(se.strict_root)r=r||this.getRoot();if(is(f,'string')){na=f.toUpperCase();f=function(n){var s=false;if(n.nodeType==1&&na==='*'){s=true;return false;}each(na.split(','),function(v){if(n.nodeType==1&&((se.strict&&n.nodeName.toUpperCase()==v)||n.nodeName==v)){s=true;return false;}});return s;};}while(n){if(n==r)return null;if(f(n))return n;n=n.parentNode;}return null;},get:function(e){if(typeof(e)=='string')return this.doc.getElementById(e);return e;},select:function(pa,s){var t=this,cs,c,pl,o=[],x,i,l,n;s=t.get(s)||t.doc;if(t.settings.strict){function get(s,n){return s.getElementsByTagName(n.toLowerCase());};}else{function get(s,n){return s.getElementsByTagName(n);};}if(t.elmPattern.test(pa)){x=get(s,pa);for(i=0,l=x.length;i<l;i++)o.push(x[i]);return o;}if(t.elmClassPattern.test(pa)){pl=t.elmClassPattern.exec(pa);x=get(s,pl[1]||'*');c=' '+pl[2]+' ';for(i=0,l=x.length;i<l;i++){n=x[i];if(n.className&&(' '+n.className+' ').indexOf(c)!==-1)o.push(n);}return o;}function collect(n){if(!n.mce_save){n.mce_save=1;o.push(n);}};function collectIE(n){if(!n.getAttribute('mce_save')){n.setAttribute('mce_save','1');o.push(n);}};function find(n,f,r){var i,l,nl=get(r,n);for(i=0,l=nl.length;i<l;i++)f(nl[i]);};each(pa.split(','),function(v,i){v=tinymce.trim(v);if(t.elmPattern.test(v)){each(get(s,v),function(n){collect(n);});return;}if(t.elmClassPattern.test(v)){x=t.elmClassPattern.exec(v);each(get(s,x[1]),function(n){if(t.hasClass(n,x[2]))collect(n);});return;}if(!(cs=t.cache[pa])){cs='x=(function(cf, s) {';pl=v.split(' ');each(pl,function(v){var p=/^([\w\\*]+)?(?:#([\w\\]+))?(?:\.([\w\\\.]+))?(?:\[\@([\w\\]+)([\^\$\*!]?=)([\w\\]+)\])?(?:\:([\w\\]+))?/i.exec(v);p[1]=p[1]||'*';cs+='find("'+p[1]+'", function(n) {';if(p[2])cs+='if (n.id !== "'+p[2]+'") return;';if(p[3]){cs+='var c = " " + n.className + " ";';cs+='if (';c='';each(p[3].split('.'),function(v){if(v)c+=(c?'||':'')+'c.indexOf(" '+v+' ") === -1';});cs+=c+') return;';}});cs+='cf(n);';for(i=pl.length-1;i>=0;i--)cs+='}, '+(i?'n':'s')+');';cs+='})';t.cache[pa]=cs=eval(cs);}cs(isIE?collectIE:collect,s);});each(o,function(n){if(isIE)n.removeAttribute('mce_save');else delete n.mce_save;});return o;},add:function(p,n,a,h,c){var t=this;return this.run(p,function(p){var e,k;e=is(n,'string')?t.doc.createElement(n):n;if(a){for(k in a){if(a.hasOwnProperty(k)&&!is(a[k],'object'))t.setAttrib(e,k,''+a[k]);}if(a.style&&!is(a.style,'string')){each(a.style,function(v,n){t.setStyle(e,n,v);});}}if(h){if(h.nodeType)e.appendChild(h);else t.setHTML(e,h);}return!c?p.appendChild(e):e;});},create:function(n,a,h){return this.add(this.doc.createElement(n),n,a,h,1);},createHTML:function(n,a,h){var o='',t=this,k;o+='<'+n;for(k in a){if(a.hasOwnProperty(k))o+=' '+k+'="'+t.encode(a[k])+'"';}if(tinymce.is(h))return o+'>'+h+'</'+n+'>';return o+' />';},remove:function(n,k){return this.run(n,function(n){var p;p=n.parentNode;if(!p)return null;if(k){each(n.childNodes,function(c){p.insertBefore(c.cloneNode(true),n);});}return p.removeChild(n);});},setStyle:function(n,na,v){var t=this;return t.run(n,function(e){var s,i;s=e.style;na=na.replace(/-(\D)/g,function(a,b){return b.toUpperCase();});if(t.pixelStyles.test(na)&&(tinymce.is(v,'number')||/^[\-0-9\.]+$/.test(v)))v+='px';switch(na){case'opacity':if(isIE){s.filter=v===''?'':"alpha(opacity="+(v*100)+")";if(!n.currentStyle||!n.currentStyle.hasLayout)s.display='inline-block';}s['-moz-opacity']=s['-khtml-opacity']=v;break;case'float':isIE?s.styleFloat=v:s.cssFloat=v;break;}s[na]=v||'';if(t.settings.update_styles)t.setAttrib(e,'mce_style');});},getStyle:function(n,na,c){n=this.get(n);if(!n)return false;if(this.doc.defaultView&&c){na=na.replace(/[A-Z]/g,function(a){return'-'+a;});try{return this.doc.defaultView.getComputedStyle(n,null).getPropertyValue(na);}catch(ex){return null;}}na=na.replace(/-(\D)/g,function(a,b){return b.toUpperCase();});if(na=='float')na=isIE?'styleFloat':'cssFloat';if(n.currentStyle&&c)return n.currentStyle[na];return n.style[na];},setStyles:function(e,o){var t=this,s=t.settings,ol;ol=s.update_styles;s.update_styles=0;each(o,function(v,n){t.setStyle(e,n,v);});s.update_styles=ol;if(s.update_styles)t.setAttrib(e,s.cssText);},setAttrib:function(e,n,v){var t=this;if(t.settings.strict)n=n.toLowerCase();return this.run(e,function(e){var s=t.settings;switch(n){case"style":if(s.keep_values){if(v)e.setAttribute('mce_style',v,2);else e.removeAttribute('mce_style',2);}e.style.cssText=v;break;case"class":e.className=v;break;case"src":case"href":if(s.keep_values){if(s.url_converter)v=s.url_converter.call(s.url_converter_scope||t,v,n,e);t.setAttrib(e,'mce_'+n,v,2);}break;}if(is(v)&&v!==null&&v.length!==0)e.setAttribute(n,''+v,2);else e.removeAttribute(n,2);});},setAttribs:function(e,o){var t=this;return this.run(e,function(e){each(o,function(v,n){t.setAttrib(e,n,v);});});},getAttrib:function(e,n,dv){var v,t=this;e=t.get(e);if(!e)return false;if(!is(dv))dv="";if(/^(src|href|style|coords)$/.test(n)){v=e.getAttribute("mce_"+n);if(v)return v;}v=e.getAttribute(n,2);if(!v){switch(n){case'class':v=e.className;break;default:v=e.attributes[n];v=v&&is(v.nodeValue)?v.nodeValue:v;}}switch(n){case'style':v=v||e.style.cssText;if(v){v=t.serializeStyle(t.parseStyle(v));if(t.settings.keep_values)e.setAttribute('mce_style',v);}break;}if(isWebKit&&n==="class"&&v)v=v.replace(/(apple|webkit)\-[a-z\-]+/gi,'');if(isIE){switch(n){case'rowspan':case'colspan':if(v===1)v='';break;case'size':if(v==='+0')v='';break;case'hspace':if(v===-1)v='';break;case'tabindex':if(v===32768)v='';break;case'shape':v=v.toLowerCase();break;default:if(n.indexOf('on')===0&&v)v=(''+v).replace(/^function\s+anonymous\(\)\s+\{\s+(.*)\s+\}$/,'$1');}}return(v&&v!='')?''+v:dv;},getPos:function(n){var t=this,x=0,y=0,e,d=t.doc,r;n=t.get(n);if(n&&isIE){n=n.getBoundingClientRect();e=t.boxModel?d.documentElement:d.body;x=t.getStyle(t.select('html')[0],'borderWidth');x=(x=='medium'||t.boxModel&&!t.isIE6)&&2||x;n.top+=window.self!=window.top?2:0;return{x:n.left+e.scrollLeft-x,y:n.top+e.scrollTop-x};}r=n;while(r){x+=r.offsetLeft||0;y+=r.offsetTop||0;r=r.offsetParent;}r=n;while(r){x-=r.scrollLeft||0;y-=r.scrollTop||0;r=r.parentNode;if(r==d.body)break;}return{x:x,y:y};},parseStyle:function(st){var t=this,s=t.settings,o={};if(!st)return o;function compress(p,s,ot){var t,r,b,l;t=o[p+'-top'+s];if(!t)return;r=o[p+'-right'+s];if(t!=r)return;b=o[p+'-bottom'+s];if(r!=b)return;l=o[p+'-left'+s];if(b!=l)return;o[ot]=l;delete o[p+'-top'+s];delete o[p+'-right'+s];delete o[p+'-bottom'+s];delete o[p+'-left'+s];};function compress2(ta,a,b,c){var t;t=o[a];if(!t)return;t=o[b];if(!t)return;t=o[c];if(!t)return;o[ta]=o[a]+' '+o[b]+' '+o[c];delete o[a];delete o[b];delete o[c];};each(st.split(';'),function(v){var sv,ur=[];if(v){v=v.replace(/url\([^\)]+\)/g,function(v){ur.push(v);return'url('+ur.length+')';});v=v.split(':');sv=tinymce.trim(v[1]);sv=sv.replace(/url\(([^\)]+)\)/g,function(a,b){return ur[parseInt(b)-1];});sv=sv.replace(/rgb\([^\)]+\)/g,function(v){return t.toHex(v);});if(s.url_converter){sv=sv.replace(/url\([\'\"]?([^\)\'\"]+)[\'\"]?\)/g,function(x,c){return'url('+t.encode(s.url_converter.call(s.url_converter_scope||t,t.decode(c),'style',null))+')';});}o[tinymce.trim(v[0]).toLowerCase()]=sv;}});compress("border","","border");compress("border","-width","border-width");compress("border","-color","border-color");compress("border","-style","border-style");compress("padding","","padding");compress("margin","","margin");compress2('border','border-width','border-style','border-color');if(isIE){if(o.border=='medium none')o.border='';}return o;},serializeStyle:function(o){var s='';each(o,function(v,k){if(k&&v){switch(k){case'color':case'background-color':v=v.toLowerCase();break;}s+=(s?' ':'')+k+': '+v+';';}});return s;},loadCSS:function(u){var t=this,d=this.doc;if(!u)u='';each(u.split(','),function(u){if(t.files[u])return;t.files[u]=true;if(!d.createStyleSheet)t.add(t.select('head')[0],'link',{rel:'stylesheet',href:u});else d.createStyleSheet(u);});},addClass:function(e,c){return this.run(e,function(e){var o;if(!c)return 0;if(this.hasClass(e,c))return e.className;o=this.removeClass(e,c);return e.className=(o!=''?(o+' '):'')+c;});},removeClass:function(e,c){var t=this,re;return t.run(e,function(e){var v;if(t.hasClass(e,c)){if(!re)re=new RegExp("(^|\\s+)"+c+"(\\s+|$)","g");v=e.className.replace(re,' ');return e.className=tinymce.trim(v!=' '?v:'');}return e.className;});},hasClass:function(n,c){n=this.get(n);if(!n||!c)return false;return(' '+n.className+' ').indexOf(' '+c+' ')!==-1;},show:function(e){return this.setStyle(e,'display','block');},hide:function(e){return this.setStyle(e,'display','none');},isHidden:function(e){e=this.get(e);return e.style.display=='none'||this.getStyle(e,'display')=='none';},uniqueId:function(p){return(!p?'mce_':p)+(this.counter++);},setHTML:function(e,h){var t=this;return this.run(e,function(e){var x;h=t.processHTML(h);if(isIE){try{e.innerHTML='<br />'+h;e.removeChild(e.firstChild);}catch(ex){x=t.create('div');x.innerHTML='<br />'+h;each(x.childNodes,function(n,i){if(i>1)e.appendChild(n);});}}else e.innerHTML=h;return h;});},processHTML:function(h){var t=this,s=t.settings;if(!s.process_html)return h;if(tinymce.isGecko){h=h.replace(/<(\/?)strong>|<strong( [^>]+)>/gi,'<$1b$2>');h=h.replace(/<(\/?)em>|<em( [^>]+)>/gi,'<$1i$2>');}h=h.replace(/<a( )([^>]+)\/>|<a\/>/gi,'<a$1$2></a>');if(s.keep_values){if(h.indexOf('<script')!==-1){h=h.replace(/<script>/g,'<script type="text/javascript">');h=h.replace(/<script(|[^>]+)>(\s*<!--|\/\/\s*<\[CDATA\[)?[\r\n]*/g,'<mce:script$1><!--\n');h=h.replace(/\s*(\/\/\s*-->|\/\/\s*]]>)?<\/script>/g,'\n// --></mce:script>');h=h.replace(/<mce:script(|[^>]+)><!--\n\/\/ --><\/mce:script>/g,'<mce:script$1></mce:script>');}h=h.replace(/<([\w:]+) [^>]*(src|href|style|coords)[^>]*>/gi,function(a,n){function handle(m,b,c){var u=c;if(a.indexOf('mce_'+b)!=-1)return m;if(b=='style'){if(s.hex_colors){u=u.replace(/rgb\([^\)]+\)/g,function(v){return t.toHex(v);});}if(s.url_converter){u=u.replace(/url\([\'\"]?([^\)\'\"]+)\)/g,function(x,c){return'url('+t.encode(s.url_converter.call(s.url_converter_scope||t,t.decode(c),b,n))+')';});}}else if(b!='coords'){if(s.url_converter)u=t.encode(s.url_converter.call(s.url_converter_scope||t,t.decode(c),b,n));}return' '+b+'="'+c+'" mce_'+b+'="'+u+'"';};a=a.replace(/ (src|href|style|coords)=[\"]([^\"]+)[\"]/gi,handle);a=a.replace(/ (src|href|style|coords)=[\']([^\']+)[\']/gi,handle);return a.replace(/ (src|href|style|coords)=([^\s\"\'>]+)/gi,handle);});}return h;},getOuterHTML:function(e){var d;e=this.get(e);if(!e)return null;if(isIE)return e.outerHTML;d=(e.ownerDocument||this.doc).createElement("body");d.appendChild(e.cloneNode(true));return d.innerHTML;},setOuterHTML:function(e,h,d){var t=this;return this.run(e,function(e){var n,tp;e=t.get(e);d=d||e.ownerDocument||t.doc;if(isIE&&e.nodeType==1)e.outerHTML=h;else{tp=d.createElement("body");tp.innerHTML=h;n=tp.lastChild;while(n){t.insertAfter(n.cloneNode(true),e);n=n.previousSibling;}t.remove(e);}});},decode:function(s){var e=document.createElement("div");e.innerHTML=s;return!e.firstChild?s:e.firstChild.nodeValue;},encode:function(s){return s?(''+s).replace(/[<>&\"]/g,function(c,b){switch(c){case'&':return'&amp;';case'"':return'&quot;';case'<':return'&lt;';case'>':return'&gt;';}return c;}):s;},insertAfter:function(n,r){var t=this;r=t.get(r);return this.run(n,function(n){var p,ns;p=r.parentNode;ns=r.nextSibling;if(ns)p.insertBefore(n,ns);else p.appendChild(n);return n;});},isBlock:function(n){if(n.nodeType&&n.nodeType!==1)return false;n=n.nodeName||n;return/^(H[1-6]|HR|P|DIV|ADDRESS|PRE|FORM|TABLE|LI|OL|UL|TD|CAPTION|BLOCKQUOTE|CENTER|DL|DT|DD|DIR|FIELDSET|FORM|NOSCRIPT|NOFRAMES|MENU|ISINDEX|SAMP)$/.test(n);},replace:function(n,o,k){if(is(o,'array'))n=n.cloneNode(true);return this.run(o,function(o){if(k){each(o.childNodes,function(c){n.appendChild(c.cloneNode(true));});}return o.parentNode.replaceChild(n,o);});},toHex:function(s){var c=/^\s*rgb\s*?\(\s*?([0-9]+)\s*?,\s*?([0-9]+)\s*?,\s*?([0-9]+)\s*?\)\s*$/i.exec(s);function hex(s){s=parseInt(s).toString(16);return s.length>1?s:'0'+s;};if(c){s='#'+hex(c[1])+hex(c[2])+hex(c[3]);return s;}return s;},getClasses:function(){var t=this,cl=[],i,lo={},f=t.settings.class_filter;if(t.classes)return t.classes;function addClasses(s){each(s.imports,function(r){addClasses(r);});each(s.cssRules||s.rules,function(r){switch(r.type||1){case 1:if(r.selectorText){each(r.selectorText.split(','),function(v){v=v.replace(/^\s*|\s*$|^\s\./g,"");if(f&&!(v=f(v)))return;if(/^\.mce/.test(v)||!/^\.[\w\-]+$/.test(v))return;v=v.substring(1);if(!lo[v]){cl.push({'class':v});lo[v]=1;}});}break;case 3:addClasses(r.styleSheet);break;}});};try{each(t.doc.styleSheets,addClasses);}catch(ex){}if(cl.length>0)t.classes=cl;return cl;},run:function(e,f,s){var t=this,o;if(typeof(e)==='string')e=t.doc.getElementById(e);if(!e)return false;s=s||this;if(!e.nodeType&&(e.length||e.length===0)){o=[];each(e,function(e,i){if(e){if(typeof(e)=='string')e=t.doc.getElementById(e);o.push(f.call(s,e,i));}});return o;}return f.call(s,e);}});tinymce.DOM=new tinymce.dom.DOMUtils(document,{process_html:0});})();(function(){var each=tinymce.each,DOM=tinymce.DOM,isIE=tinymce.isIE,isWebKit=tinymce.isWebKit,Event;tinymce.create('static tinymce.dom.Event',{inits:[],events:[],add:function(o,n,f,s){var cb,t=this,el=t.events,r;if(o&&o instanceof Array){r=[];each(o,function(o){o=DOM.get(o);r.push(t.add(o,n,f,s));});return r;}o=DOM.get(o);if(!o)return;cb=function(e){e=e||window.event;if(e&&!e.target&&isIE)e.target=e.srcElement;if(!s)return f(e);return f.call(s,e);};if(n=='unload'){tinymce.unloads.unshift({func:cb});return cb;}if(n=='init'){if(t.domLoaded)cb();else t.inits.push(cb);return cb;}el.push({obj:o,name:n,func:f,cfunc:cb,scope:s});t._add(o,n,cb);return f;},remove:function(o,n,f){var t=this,a=t.events,s=false,r;if(o&&o instanceof Array){r=[];each(o,function(o){o=DOM.get(o);r.push(t.remove(o,n,f));});return r;}o=DOM.get(o);each(a,function(e,i){if(e.obj==o&&e.name==n&&(!f||(e.func==f||e.cfunc==f))){a.splice(i,1);t._remove(o,n,e.cfunc);s=true;return false;}});return s;},cancel:function(e){if(!e)return false;this.stop(e);return this.prevent(e);},stop:function(e){if(e.stopPropagation)e.stopPropagation();else e.cancelBubble=true;return false;},prevent:function(e){if(e.preventDefault)e.preventDefault();else e.returnValue=false;return false;},_unload:function(){var t=Event;each(t.events,function(e,i){t._remove(e.obj,e.name,e.cfunc);e.obj=e.cfunc=null;});t.events=[];t=null;},_add:function(o,n,f){if(o.attachEvent)o.attachEvent('on'+n,f);else if(o.addEventListener)o.addEventListener(n,f,false);else o['on'+n]=f;},_remove:function(o,n,f){if(o.detachEvent)o.detachEvent('on'+n,f);else if(o.removeEventListener)o.removeEventListener(n,f,false);else o['on'+n]=null;},_pageInit:function(){var e=Event;e._remove(window,'DOMContentLoaded',e._pageInit);e.domLoaded=true;each(e.inits,function(c){c();});e.inits=[];},_wait:function(){var t;if(window.tinyMCE_GZ&&tinyMCE_GZ.loaded)return;if(isIE&&document.location.protocol!='https:'){document.write('<script id=__ie_onload defer src=\'javascript:""\';><\/script>');DOM.get("__ie_onload").onreadystatechange=function(){if(this.readyState=="complete"){Event._pageInit();DOM.get("__ie_onload").onreadystatechange=null;}};}else{Event._add(window,'DOMContentLoaded',Event._pageInit,Event);if(isIE||isWebKit){t=setInterval(function(){if(/loaded|complete/.test(document.readyState)){clearInterval(t);Event._pageInit();}},10);}}}});Event=tinymce.dom.Event;Event._wait();tinymce.addUnload(Event._unload);})();(function(){var each=tinymce.each;tinymce.create('tinymce.dom.Element',{Element:function(id,s){var t=this,dom,el;s=s||{};t.id=id;t.dom=dom=s.dom||tinymce.DOM;t.settings=s;if(!tinymce.isIE)el=t.dom.get(t.id);each(['getPos','getRect','getParent','add','setStyle','getStyle','setStyles','setAttrib','setAttribs','getAttrib','addClass','removeClass','hasClass','getOuterHTML','setOuterHTML','remove','show','hide','isHidden','setHTML','get'],function(k){t[k]=function(){var a=arguments,o;if(tinymce.isOpera){a=[id];each(arguments,function(v){a.push(v);});}else Array.prototype.unshift.call(a,el||id);o=dom[k].apply(dom,a);t.update(k);return o;};});},on:function(n,f,s){return tinymce.dom.Event.add(this.id,n,f,s);},getXY:function(){return{x:parseInt(this.getStyle('left')),y:parseInt(this.getStyle('top'))};},getSize:function(){var n=this.dom.get(this.id);return{w:parseInt(this.getStyle('width')||n.clientWidth),h:parseInt(this.getStyle('height')||n.clientHeight)};},moveTo:function(x,y){this.setStyles({left:x,top:y});},moveBy:function(x,y){var p=this.getXY();this.moveTo(p.x+x,p.y+y);},resizeTo:function(w,h){this.setStyles({width:w,height:h});},resizeBy:function(w,h){var s=this.getSize();this.resizeTo(s.w+w,s.h+h);},update:function(k){var t=this,b,dom=t.dom;if(tinymce.isIE6&&t.settings.blocker){k=k||'';if(k.indexOf('get')===0||k.indexOf('has')===0||k.indexOf('is')===0)return;if(k=='remove'){dom.remove(t.blocker);return;}if(!t.blocker){t.blocker=dom.uniqueId();b=dom.add(t.settings.container||dom.getRoot(),'iframe',{id:t.blocker,style:'position:absolute;',frameBorder:0,src:'javascript:""'});dom.setStyle(b,'opacity',0);}else b=dom.get(t.blocker);dom.setStyle(b,'left',t.getStyle('left',1));dom.setStyle(b,'top',t.getStyle('top',1));dom.setStyle(b,'width',t.getStyle('width',1));dom.setStyle(b,'height',t.getStyle('height',1));dom.setStyle(b,'display',t.getStyle('display',1));dom.setStyle(b,'zIndex',parseInt(t.getStyle('zIndex',1)||0)-1);}}});})();(function(){var is=tinymce.is,isIE=tinymce.isIE,each=tinymce.each;tinymce.create('tinymce.dom.Selection',{Selection:function(dom,win,serializer){var t=this;t.dom=dom;t.win=win;t.serializer=serializer;tinymce.addUnload(function(){t.win=null;});},getContent:function(s){var t=this,r=t.getRng(),e=t.dom.create("body"),se=t.getSel(),wb,wa,n;s=s||{};wb=wa='';s.get=true;s.format=s.format||'html';if(s.format=='text')return t.isCollapsed()?'':(r.text||(se.toString?se.toString():''));if(r.cloneContents){n=r.cloneContents();if(n)e.appendChild(n);}else if(is(r.item)||is(r.htmlText))e.innerHTML=r.item?r.item(0).outerHTML:r.htmlText;else e.innerHTML=r.toString();if(/^\s/.test(e.innerHTML))wb=' ';if(/\s+$/.test(e.innerHTML))wa=' ';s.getInner=true;return t.isCollapsed()?'':wb+t.serializer.serialize(e,s)+wa;},setContent:function(h,s){var t=this,r=t.getRng(),d;s=s||{format:'html'};s.set=true;h=t.dom.processHTML(h);if(r.insertNode){d=t.win.document;if(tinymce.isGecko&&h.indexOf('<')==-1){r.deleteContents();r.insertNode(t.getRng().createContextualFragment(h+'<span id="__caret">_</span>'));t.select(t.dom.get('__caret'));t.getRng().deleteContents();return;}if(d.queryCommandEnabled('InsertHTML'))return d.execCommand('InsertHTML',false,h);r.deleteContents();r.insertNode(t.getRng().createContextualFragment(h));}else{if(r.item)r.item(0).outerHTML=h;else r.pasteHTML(h);}},getStart:function(){var t=this,r=t.getRng(),e;if(isIE){if(r.item)return r.item(0);r=r.duplicate();r.collapse(1);e=r.parentElement();if(e.nodeName=='BODY')return e.firstChild;return e;}else{e=r.startContainer;if(e.nodeName=='BODY')return e.firstChild;return t.dom.getParent(e,function(n){return n.nodeType==1;});}},getEnd:function(){var t=this,r=t.getRng(),e;if(isIE){if(r.item)return r.item(0);r=r.duplicate();r.collapse(0);e=r.parentElement();if(e.nodeName=='BODY')return e.lastChild;return e;}else{e=r.endContainer;if(e.nodeName=='BODY')return e.lastChild;return t.dom.getParent(e,function(n){return n.nodeType==1;});}},getBookmark:function(si){var t=this,r=t.getRng(),tr,sx,sy,vp=t.dom.getViewPort(t.win),e,sp,bp,le,c=-0xFFFFFF,s,ro=t.dom.getRoot();sx=vp.x;sy=vp.y;if(si=='simple')return{rng:r,scrollX:sx,scrollY:sy};if(isIE){if(r.item){e=r.item(0);each(t.dom.select(e.nodeName),function(n,i){if(e==n){sp=i;return false;}});return{tag:e.nodeName,index:sp,scrollX:sx,scrollY:sy};}tr=t.dom.doc.body.createTextRange();tr.moveToElementText(ro);tr.collapse(true);bp=Math.abs(tr.move('character',c));tr=r.duplicate();tr.collapse(true);sp=Math.abs(tr.move('character',c));tr=r.duplicate();tr.collapse(false);le=Math.abs(tr.move('character',c))-sp;return{start:sp-bp,length:le,scrollX:sx,scrollY:sy};}e=t.getNode();s=t.getSel();if(!s)return null;if(e&&e.nodeName=='IMG'){return{scrollX:sx,scrollY:sy};}function getPos(r,sn,en){var w=document.createTreeWalker(r,NodeFilter.SHOW_TEXT,null,false),n,p=0,d={};while((n=w.nextNode())!=null){if(n==sn)d.start=p;if(n==en){d.end=p;return d;}p+=n.nodeValue?n.nodeValue.length:0;}return null;};if(s.anchorNode==s.focusNode&&s.anchorOffset==s.focusOffset){e=getPos(ro,s.anchorNode,s.focusNode);if(!e)return{scrollX:sx,scrollY:sy};return{start:e.start+s.anchorOffset,end:e.end+s.focusOffset,scrollX:sx,scrollY:sy};}else{e=getPos(ro,r.startContainer,r.endContainer);if(!e)return{scrollX:sx,scrollY:sy};return{start:e.start+r.startOffset,end:e.end+r.endOffset,scrollX:sx,scrollY:sy};}},moveToBookmark:function(b){var t=this,r=t.getRng(),s=t.getSel(),ro=t.dom.getRoot(),sd;function getPos(r,sp,ep){var w=document.createTreeWalker(r,NodeFilter.SHOW_TEXT,null,false),n,p=0,d={};while((n=w.nextNode())!=null){p+=n.nodeValue?n.nodeValue.length:0;if(p>=sp&&!d.startNode){d.startNode=n;d.startOffset=sp-(p-n.nodeValue.length);}if(p>=ep){d.endNode=n;d.endOffset=ep-(p-n.nodeValue.length);return d;}}return null;};if(!b)return false;t.win.scrollTo(b.scrollX,b.scrollY);if(isIE){if(r=b.rng){try{r.select();}catch(ex){}return true;}t.win.focus();if(b.tag){r=ro.createControlRange();each(t.dom.select(b.tag),function(n,i){if(i==b.index)r.addElement(n);});}else{try{if(b.start<0)return true;r=s.createRange();r.moveToElementText(ro);r.collapse(true);r.moveStart('character',b.start);r.moveEnd('character',b.length);}catch(ex2){return true;}}try{r.select();}catch(ex){}return true;}if(!s)return false;if(b.rng){s.removeAllRanges();s.addRange(b.rng);}else{if(is(b.start)&&is(b.end)){try{sd=getPos(ro,b.start,b.end);if(sd){r=t.dom.doc.createRange();r.setStart(sd.startNode,sd.startOffset);r.setEnd(sd.endNode,sd.endOffset);s.removeAllRanges();s.addRange(r);}if(!tinymce.isOpera)t.win.focus();}catch(ex){}}}},select:function(n,c){var t=this,r=t.getRng(),s=t.getSel(),b,fn,ln,d=t.win.document;function first(n){return n?d.createTreeWalker(n,NodeFilter.SHOW_TEXT,null,false).nextNode():null;};function last(n){var c,o,w;if(!n)return null;w=d.createTreeWalker(n,NodeFilter.SHOW_TEXT,null,false);while(c=w.nextNode())o=c;return o;};if(isIE){try{b=d.body;if(/^(IMG|TABLE)$/.test(n.nodeName)){r=b.createControlRange();r.addElement(n);}else{r=b.createTextRange();r.moveToElementText(n);}r.select();}catch(ex){}}else{if(c){fn=first(n);ln=last(n);if(fn&&ln){r=d.createRange();r.setStart(fn,0);r.setEnd(ln,ln.nodeValue.length);}else r.selectNode(n);}else r.selectNode(n);t.setRng(r);}return n;},isCollapsed:function(){var t=this,r=t.getRng(),s=t.getSel();if(!r||r.item)return false;return!s||r.boundingWidth==0||s.isCollapsed;},collapse:function(b){var t=this,r=t.getRng(),n;if(r.item){n=r.item(0);r=this.win.document.body.createTextRange();r.moveToElementText(n);}r.collapse(!!b);t.setRng(r);},getSel:function(){var t=this,w=this.win;return w.getSelection?w.getSelection():w.document.selection;},getRng:function(){var t=this,s=t.getSel(),r;try{if(s)r=s.rangeCount>0?s.getRangeAt(0):(s.createRange?s.createRange():t.win.document.createRange());}catch(ex){}if(!r)r=isIE?t.win.document.body.createTextRange():t.win.document.createRange();return r;},setRng:function(r){var s;if(!isIE){s=this.getSel();if(s){s.removeAllRanges();s.addRange(r);}}else{try{r.select();}catch(ex){}}},setNode:function(n){var t=this;t.setContent(t.dom.getOuterHTML(n));return n;},getNode:function(){var t=this,r=t.getRng(),s=t.getSel(),e;if(!isIE){if(!r)return t.dom.getRoot();e=r.commonAncestorContainer;if(!r.collapsed){if(r.startContainer==r.endContainer||(tinymce.isWebKit&&r.startContainer==r.endContainer.parentNode)){if(r.startOffset-r.endOffset<2||tinymce.isWebKit){if(r.startContainer.hasChildNodes())e=r.startContainer.childNodes[r.startOffset];}}}return t.dom.getParent(e,function(n){return n.nodeType==1;});}return r.item?r.item(0):r.parentElement();}});})();(function(){tinymce.create('tinymce.dom.XMLWriter',{node:null,XMLWriter:function(s){function getXML(){var i=document.implementation;if(!i||!i.createDocument){try{return new ActiveXObject('MSXML2.DOMDocument');}catch(ex){}try{return new ActiveXObject('Microsoft.XmlDom');}catch(ex){}}else return i.createDocument('','',null);};this.doc=getXML();this.reset();},reset:function(){var t=this,d=t.doc;if(d.firstChild)d.removeChild(d.firstChild);t.node=d.appendChild(d.createElement("html"));},writeStartElement:function(n){var t=this;t.node=t.node.appendChild(t.doc.createElement(n));},writeAttribute:function(n,v){if(tinymce.isOpera)v=v.replace(/>/g,'|>');this.node.setAttribute(n,v);},writeEndElement:function(){this.node=this.node.parentNode;},writeFullEndElement:function(){var t=this,n=t.node;n.appendChild(t.doc.createTextNode(""));t.node=n.parentNode;},writeText:function(v){if(tinymce.isOpera)v=v.replace(/>/g,'|>');this.node.appendChild(this.doc.createTextNode(v));},writeCDATA:function(v){this.node.appendChild(this.doc.createCDATA(v));},writeComment:function(v){this.node.appendChild(this.doc.createComment(v));},getContent:function(){var h;h=this.doc.xml||new XMLSerializer().serializeToString(this.doc);h=h.replace(/<\?[^?]+\?>|<html>|<\/html>|<html\/>|<!DOCTYPE[^>]+>/g,'');h=h.replace(/ ?\/>/g,' />');if(tinymce.isOpera)h=h.replace(/\|>/g,'&gt;');return h;}});})();(function(){var extend=tinymce.extend,each=tinymce.each,Dispatcher=tinymce.util.Dispatcher,isIE=tinymce.isIE;function getIEAtts(n){var o=[];if(n.nodeName=='OBJECT')return n.attributes;n.cloneNode(false).outerHTML.replace(/([a-z0-9\-_]+)=/gi,function(a,b){o.push({specified:1,nodeName:b});});return o;};function wildcardToRE(s){return s.replace(/([?+*])/g,'.$1');};tinymce.create('tinymce.dom.Serializer',{Serializer:function(s){var t=this;t.key=0;t.onPreProcess=new Dispatcher(t);t.onPostProcess=new Dispatcher(t);t.writer=new tinymce.dom.XMLWriter();t.settings=s=extend({dom:tinymce.DOM,valid_nodes:0,node_filter:0,attr_filter:0,invalid_attrs:/^(mce_|_moz_$)/,closed:/(br|hr|input|meta|img|link|param)/,entity_encoding:'named',entities:'160,nbsp,161,iexcl,162,cent,163,pound,164,curren,165,yen,166,brvbar,167,sect,168,uml,169,copy,170,ordf,171,laquo,172,not,173,shy,174,reg,175,macr,176,deg,177,plusmn,178,sup2,179,sup3,180,acute,181,micro,182,para,183,middot,184,cedil,185,sup1,186,ordm,187,raquo,188,frac14,189,frac12,190,frac34,191,iquest,192,Agrave,193,Aacute,194,Acirc,195,Atilde,196,Auml,197,Aring,198,AElig,199,Ccedil,200,Egrave,201,Eacute,202,Ecirc,203,Euml,204,Igrave,205,Iacute,206,Icirc,207,Iuml,208,ETH,209,Ntilde,210,Ograve,211,Oacute,212,Ocirc,213,Otilde,214,Ouml,215,times,216,Oslash,217,Ugrave,218,Uacute,219,Ucirc,220,Uuml,221,Yacute,222,THORN,223,szlig,224,agrave,225,aacute,226,acirc,227,atilde,228,auml,229,aring,230,aelig,231,ccedil,232,egrave,233,eacute,234,ecirc,235,euml,236,igrave,237,iacute,238,icirc,239,iuml,240,eth,241,ntilde,242,ograve,243,oacute,244,ocirc,245,otilde,246,ouml,247,divide,248,oslash,249,ugrave,250,uacute,251,ucirc,252,uuml,253,yacute,254,thorn,255,yuml,402,fnof,913,Alpha,914,Beta,915,Gamma,916,Delta,917,Epsilon,918,Zeta,919,Eta,920,Theta,921,Iota,922,Kappa,923,Lambda,924,Mu,925,Nu,926,Xi,927,Omicron,928,Pi,929,Rho,931,Sigma,932,Tau,933,Upsilon,934,Phi,935,Chi,936,Psi,937,Omega,945,alpha,946,beta,947,gamma,948,delta,949,epsilon,950,zeta,951,eta,952,theta,953,iota,954,kappa,955,lambda,956,mu,957,nu,958,xi,959,omicron,960,pi,961,rho,962,sigmaf,963,sigma,964,tau,965,upsilon,966,phi,967,chi,968,psi,969,omega,977,thetasym,978,upsih,982,piv,8226,bull,8230,hellip,8242,prime,8243,Prime,8254,oline,8260,frasl,8472,weierp,8465,image,8476,real,8482,trade,8501,alefsym,8592,larr,8593,uarr,8594,rarr,8595,darr,8596,harr,8629,crarr,8656,lArr,8657,uArr,8658,rArr,8659,dArr,8660,hArr,8704,forall,8706,part,8707,exist,8709,empty,8711,nabla,8712,isin,8713,notin,8715,ni,8719,prod,8721,sum,8722,minus,8727,lowast,8730,radic,8733,prop,8734,infin,8736,ang,8743,and,8744,or,8745,cap,8746,cup,8747,int,8756,there4,8764,sim,8773,cong,8776,asymp,8800,ne,8801,equiv,8804,le,8805,ge,8834,sub,8835,sup,8836,nsub,8838,sube,8839,supe,8853,oplus,8855,otimes,8869,perp,8901,sdot,8968,lceil,8969,rceil,8970,lfloor,8971,rfloor,9001,lang,9002,rang,9674,loz,9824,spades,9827,clubs,9829,hearts,9830,diams,338,OElig,339,oelig,352,Scaron,353,scaron,376,Yuml,710,circ,732,tilde,8194,ensp,8195,emsp,8201,thinsp,8204,zwnj,8205,zwj,8206,lrm,8207,rlm,8211,ndash,8212,mdash,8216,lsquo,8217,rsquo,8218,sbquo,8220,ldquo,8221,rdquo,8222,bdquo,8224,dagger,8225,Dagger,8240,permil,8249,lsaquo,8250,rsaquo,8364,euro',valid_elements:'*[*]',extended_valid_elements:0,valid_child_elements:0,invalid_elements:0,fix_table_elements:0,fix_list_elements:true,fix_content_duplication:true,convert_fonts_to_spans:false,font_size_classes:0,font_size_style_values:0,apply_source_formatting:0,indent_mode:'simple',indent_char:'\t',indent_levels:1,remove_linebreaks:1},s);t.dom=s.dom;if(s.fix_list_elements){t.onPreProcess.add(function(se,o){var nl,x,a=['ol','ul'],i,n,p,r=/^(OL|UL)$/,np;function prevNode(e,n){var a=n.split(','),i;while((e=e.previousSibling)!=null){for(i=0;i<a.length;i++){if(e.nodeName==a[i])return e;}}return null;};for(x=0;x<a.length;x++){nl=t.dom.select(a[x],o.node);for(i=0;i<nl.length;i++){n=nl[i];p=n.parentNode;if(r.test(p.nodeName)){np=prevNode(n,'LI');if(!np){np=t.dom.create('li');np.innerHTML='&nbsp;';np.appendChild(n);p.insertBefore(np,p.firstChild);}else np.appendChild(n);}}}});}if(s.fix_table_elements){t.onPreProcess.add(function(se,o){var ta=[],d=t.dom.doc;each(t.dom.select('table',o.node),function(e){var pa=t.dom.getParent(e,'H1,H2,H3,H4,H5,H6,P'),p=[],i,h;if(pa){t.dom.getParent(e,function(n){if(n!=e)p.push(n.nodeName);});h='';for(i=0;i<p.length;i++)h+='</'+p[i]+'>';h+=t.dom.getOuterHTML(e);for(i=p.length-1;i>=0;i--)h+='<'+p[i]+'>';ta.push(h);e.parentNode.replaceChild(d.createComment('mcetable:'+(ta.length-1)),e);}});t.dom.setHTML(o.node,o.node.innerHTML.replace(/<!--mcetable:([0-9]+)-->/g,function(a,b){return ta[parseInt(b)];}));});}},setEntities:function(s){var t=this,a,i,l={},re='',v;if(t.entityLookup)return;a=s.split(',');for(i=0;i<a.length;i+=2){v=a[i];if(v==34||v==38||v==60||v==62)continue;l[String.fromCharCode(a[i])]=a[i+1];v=parseInt(a[i]).toString(16);re+='\\u'+'0000'.substring(v.length)+v;}if(!re){t.settings.entity_encoding='raw';return;}t.entitiesRE=new RegExp('['+re+']','g');t.entityLookup=l;},setValidChildRules:function(s){this.childRules=null;this.addValidChildRules(s);},addValidChildRules:function(s){var t=this,inst,intr,bloc;if(!s)return;inst='A|BR|SPAN|BDO|MAP|OBJECT|IMG|TT|I|B|BIG|SMALL|EM|STRONG|DFN|CODE|Q|SAMP|KBD|VAR|CITE|ABBR|ACRONYM|SUB|SUP|#text|#comment';intr='A|BR|SPAN|BDO|OBJECT|APPLET|IMG|MAP|IFRAME|TT|I|B|U|S|STRIKE|BIG|SMALL|FONT|BASEFONT|EM|STRONG|DFN|CODE|Q|SAMP|KBD|VAR|CITE|ABBR|ACRONYM|SUB|SUP|INPUT|SELECT|TEXTAREA|LABEL|BUTTON|#text|#comment';bloc='H[1-6]|P|DIV|ADDRESS|PRE|FORM|TABLE|LI|OL|UL|TD|CAPTION|BLOCKQUOTE|CENTER|DL|DT|DD|DIR|FIELDSET|FORM|NOSCRIPT|NOFRAMES|MENU|ISINDEX|SAMP';each(s.split(','),function(s){var p=s.split(/\[|\]/),re;s='';each(p[1].split('|'),function(v){if(s)s+='|';switch(v){case'%itrans':v=intr;break;case'%itrans_na':v=intr.substring(2);break;case'%istrict':v=inst;break;case'%istrict_na':v=inst.substring(2);break;case'%btrans':v=bloc;break;case'%bstrict':v=bloc;break;}s+=v;});re=new RegExp('^('+s.toLowerCase()+')$','i');each(p[0].split('/'),function(s){t.childRules=t.childRules||{};t.childRules[s]=re;});});s='';each(t.childRules,function(v,k){if(s)s+='|';s+=k;});t.parentElementsRE=new RegExp('^('+s.toLowerCase()+')$','i');},setRules:function(s){var t=this;t._setup();t.rules={};t.wildRules=[];t.validElements={};return t.addRules(s);},addRules:function(s){var t=this,dr;if(!s)return;t._setup();each(s.split(','),function(s){var p=s.split(/\[|\]/),tn=p[0].split('/'),ra,at,wat,va=[];if(dr)at=tinymce.extend([],dr.attribs);if(p.length>1){each(p[1].split('|'),function(s){var ar={},i;at=at||[];s=s.replace(/::/g,'~');s=/^([!\-])?([\w*.?~]+|)([=:<])?(.+)?$/.exec(s);s[2]=s[2].replace(/~/g,':');if(s[1]=='!'){ra=ra||[];ra.push(s[2]);}if(s[1]=='-'){for(i=0;i<at.length;i++){if(at[i].name==s[2]){at.splice(i,1);return;}}}switch(s[3]){case'=':ar.defaultVal=s[4]||'';break;case':':ar.forcedVal=s[4];break;case'<':ar.validVals=s[4].split('?');break;}if(/[*.?]/.test(s[2])){wat=wat||[];ar.nameRE=new RegExp('^'+wildcardToRE(s[2])+'$');wat.push(ar);}else{ar.name=s[2];at.push(ar);}va.push(s[2]);});}each(tn,function(s,i){var pr=s.charAt(0),x=1,ru={};if(dr){if(dr.noEmpty)ru.noEmpty=dr.noEmpty;if(dr.fullEnd)ru.fullEnd=dr.fullEnd;if(dr.padd)ru.padd=dr.padd;}switch(pr){case'-':ru.noEmpty=true;break;case'+':ru.fullEnd=true;break;case'#':ru.padd=true;break;default:x=0;}tn[i]=s=s.substring(x);t.validElements[s]=1;if(/[*.?]/.test(tn[0])){ru.nameRE=new RegExp('^'+wildcardToRE(tn[0])+'$');t.wildRules=t.wildRules||{};t.wildRules.push(ru);}else{ru.name=tn[0];if(tn[0]=='@')dr=ru;t.rules[s]=ru;}ru.attribs=at;if(ra)ru.requiredAttribs=ra;if(wat){s='';each(va,function(v){if(s)s+='|';s+='('+wildcardToRE(v)+')';});ru.validAttribsRE=new RegExp('^'+s.toLowerCase()+'$');ru.wildAttribs=wat;}});});s='';each(t.validElements,function(v,k){if(s)s+='|';if(k!='@')s+=k;});t.validElementsRE=new RegExp('^('+wildcardToRE(s.toLowerCase())+')$');},findRule:function(n){var t=this,rl=t.rules,i,r;t._setup();r=rl[n];if(r)return r;rl=t.wildRules;for(i=0;i<rl.length;i++){if(rl[i].nameRE.test(n))return rl[i];}return null;},findAttribRule:function(ru,n){var i,wa=ru.wildAttribs;for(i=0;i<wa.length;i++){if(wa[i].nameRE.test(n))return wa[i];}return null;},serialize:function(n,o){var h,t=this;t._setup();o=o||{};o.format=o.format||'html';t.processObj=o;n=n.cloneNode(true);t.key=''+(parseInt(t.key)+1);if(!o.no_events){o.node=n;t.onPreProcess.dispatch(t,o);}t.writer.reset();t._serializeNode(n,o.getInner);o.content=t.writer.getContent();if(!o.no_events)t.onPostProcess.dispatch(t,o);t._postProcess(o);o.node=null;return tinymce.trim(o.content);},_postProcess:function(o){var t=this,s=t.settings,h=o.content,sc=[],p,l;if(o.format=='html'){p=t._protect({content:h,patterns:[/(<script[^>]*>)(.*?)(<\/script>)/g,/(<style[^>]*>)(.*?)(<\/style>)/g,/(<pre[^>]*>)(.*?)(<\/pre>)/g]});h=p.content;if(s.entity_encoding!=='raw'){if(s.entity_encoding.indexOf('named')!=-1){t.setEntities(s.entities);l=t.entityLookup;h=h.replace(t.entitiesRE,function(a){var v;if(v=l[a])a='&'+v+';';return a;});}if(s.entity_encoding.indexOf('numeric')!=-1){h=h.replace(/[\u007E-\uFFFF]/g,function(a){return'&#'+a.charCodeAt(0)+';';});}}if(o.set)h=h.replace(/<p>\s+(&nbsp;|&#160;|\u00a0|<br \/>)\s+<\/p>/g,'<p><br /></p>');else h=h.replace(/<p>\s+(&nbsp;|&#160;|\u00a0|<br \/>)\s+<\/p>/g,'<p>$1</p>');if(!o.set){if(s.remove_linebreaks){h=h.replace(/(<[^>]+>)\s+/g,'$1 ');h=h.replace(/\s+(<\/[^>]+>)/g,' $1');h=h.replace(/<(p|h[1-6]|hr|div|table|tbody|tr|td|body|head|html|title|meta|style|pre|script|link|object) ([^>]+)>\s+/g,'<$1 $2>');h=h.replace(/<(p|h[1-6]|hr|div|table|tbody|tr|td|body|head|html|title|meta|style|pre|script|link|object)>\s+/g,'<$1>');h=h.replace(/\s+<\/(p|h[1-6]|hr|div|table|tbody|tr|td|body|head|html|title|meta|style|pre|script|link|object)>/g,'</$1>');}if(s.apply_source_formatting&&s.indent_mode=='simple'){h=h.replace(/<(\/?)(ul|hr|table|meta|link|tbody|tr|object|body|head|html|map)(|[^>]+)>\s*/g,'\n<$1$2$3>\n');h=h.replace(/\s*<(p|h[1-6]|div|title|style|pre|script|td|li|area)(|[^>]+)>/g,'\n<$1$2>');h=h.replace(/<\/(p|h[1-6]|div|title|style|pre|script|td|li)>\s*/g,'</$1>\n');h=h.replace(/\n\n/g,'\n');}}h=t._unprotect(h,p);}o.content=h;},_serializeNode:function(n,inn){var t=this,s=t.settings,w=t.writer,hc,el,cn,i,l,a,at,no,v,nn,ru,ar,iv;if(!s.node_filter||s.node_filter(n)){switch(n.nodeType){case 1:if(n.hasAttribute?n.hasAttribute('mce_bogus'):n.getAttribute('mce_bogus'))return;iv=false;hc=n.hasChildNodes();nn=n.getAttribute('mce_name')||n.nodeName.toLowerCase();if(isIE){if(n.scopeName!=='HTML'&&n.scopeName!=='html')nn=n.scopeName+':'+nn;}if(nn.indexOf('mce:')===0)nn=nn.substring(4);if(!t.validElementsRE.test(nn)||(t.invalidElementsRE&&t.invalidElementsRE.test(nn))||inn){iv=true;break;}if(isIE){if(s.fix_content_duplication){if(n.mce_serialized==t.key)return;n.mce_serialized=t.key;}if(nn.charAt(0)=='/')nn=nn.substring(1);}if(t.childRules){if(t.parentElementsRE.test(t.elementName)){if(!t.childRules[t.elementName].test(nn)){iv=true;break;}}t.elementName=nn;}ru=t.findRule(nn);nn=ru.name||nn;if((!hc&&ru.noEmpty)||(isIE&&!nn)){iv=true;break;}if(ru.requiredAttribs){a=ru.requiredAttribs;for(i=a.length-1;i>=0;i--){if(this.dom.getAttrib(n,a[i])!=='')break;}if(i==-1){iv=true;break;}}w.writeStartElement(nn);if(ru.attribs){for(i=0,at=ru.attribs,l=at.length;i<l;i++){a=at[i];v=t._getAttrib(n,a);if(v!==null)w.writeAttribute(a.name,v);}}if(ru.validAttribsRE){at=isIE?getIEAtts(n):n.attributes;for(i=at.length-1;i>-1;i--){no=at[i];if(no.specified){a=no.nodeName.toLowerCase();if(s.invalid_attrs.test(a)||!ru.validAttribsRE.test(a))continue;ar=t.findAttribRule(ru,a);v=t._getAttrib(n,ar,a);if(v!==null)w.writeAttribute(a,v);}}}if(!hc&&ru.padd)w.writeText('\u00a0');break;case 3:if(t.childRules&&t.parentElementsRE.test(t.elementName)){if(!t.childRules[t.elementName].test(n.nodeName))return;}return w.writeText(n.nodeValue);case 4:return w.writeCDATA(n.nodeValue);case 8:return w.writeComment(n.nodeValue);}}else if(n.nodeType==1)hc=n.hasChildNodes();if(hc){cn=n.firstChild;while(cn){t._serializeNode(cn);t.elementName=nn;cn=cn.nextSibling;}}if(!iv){if(hc||!s.closed.test(nn))w.writeFullEndElement();else w.writeEndElement();}},_protect:function(o){o.items=o.items||[];function enc(s){return s.replace(/[\r\n]/g,function(c){if(c==='\n')return'\\n';return'\\r';});};function dec(s){return s.replace(/\\[rn]/g,function(c){if(c==='\\n')return'\n';return'\r';});};each(o.patterns,function(p){o.content=dec(enc(o.content).replace(p,function(x,a,b,c){o.items.push(dec(b));return a+'<!--mce:'+(o.items.length-1)+'-->'+c;}));});return o;},_unprotect:function(h,o){h=h.replace(/\<!--mce:([0-9]+)--\>/g,function(a,b){return o.items[parseInt(b)];});o.items=[];return h;},_setup:function(){var t=this,s=this.settings;if(t.done)return;t.done=1;t.setRules(s.valid_elements);t.addRules(s.extended_valid_elements);t.addValidChildRules(s.valid_child_elements);if(s.invalid_elements)t.invalidElementsRE=new RegExp('^('+wildcardToRE(s.invalid_elements.replace(',','|').toLowerCase())+')$');if(s.attrib_value_filter)t.attribValueFilter=s.attribValueFilter;},_getAttrib:function(n,a,na){var i,v;na=na||a.name;if(a.forcedVal&&(v=a.forcedVal)){if(v==='{$uid}')return this.dom.uniqueId();return v;}v=this.dom.getAttrib(n,na);switch(na){case'rowspan':case'colspan':if(v=='1')v='';break;}if(this.attribValueFilter)v=this.attribValueFilter(na,v,n);if(a.validVals){for(i=a.validVals.length-1;i>=0;i--){if(v==a.validVals[i])break;}if(i==-1)return null;}if(v===''&&typeof(a.defaultVal)!='undefined'){v=a.defaultVal;if(v==='{$uid}')return this.dom.uniqueId();return v;}else{if(na=='class'&&this.processObj.get)v=v.replace(/\bmceItem\w+\b/g,'');}if(v==='')return null;return v;}});})();(function(){var each=tinymce.each;tinymce.create('tinymce.dom.ScriptLoader',{ScriptLoader:function(s){this.settings=s||{};this.queue=[];this.lookup={};},markDone:function(u){this.lookup[u]={state:2,url:u};},add:function(u,cb,s,pr){var t=this,lo=t.lookup,o;if(o=lo[u]){if(cb&&o.state==2)cb.call(s||this);return o;}o={state:0,url:u,func:cb,scope:s||this};if(pr)t.queue.unshift(o);else t.queue.push(o);lo[u]=o;return o;},load:function(u,cb,s){var t=this,o;function loadScript(u){if(tinymce.dom.Event.domLoaded||t.settings.strict_mode){tinymce.util.XHR.send({url:u,error:t.settings.error,async:false,success:function(co){t.eval(co);}});}else document.write('<script type="text/javascript" src="'+u+'"></script>');};if(!tinymce.is(u,'string')){each(u,function(u){loadScript(u);});if(cb)cb.call(s||t);}else{loadScript(u);if(cb)cb.call(s||t);}},loadQueue:function(cb,s){var t=this;if(!t.queueLoading){t.queueLoading=1;t.queueCallbacks=[];t.loadScripts(t.queue,function(){t.queueLoading=0;if(cb)cb.call(s||t);each(t.queueCallbacks,function(o){o.func.call(o.scope);});});}else if(cb)t.queueCallbacks.push({func:cb,scope:s||t});},eval:function(co){var w=window;if(!w.execScript){try{eval.call(w,co);}catch(ex){eval(co,w);}}else w.execScript(co);},loadScripts:function(sc,cb,s){var t=this,lo=t.lookup;function done(o){o.state=2;if(o.func)o.func.call(o.scope||t);};function allDone(){var l;l=sc.length;each(sc,function(o){o=lo[o.url];if(o.state===2){done(o);l--;}else load(o);});if(l===0&&cb){cb.call(s||t);cb=0;}};function load(o){if(o.state>0)return;o.state=1;tinymce.util.XHR.send({url:o.url,error:t.settings.error,success:function(co){t.eval(co);done(o);allDone();}});};each(sc,function(o){var u=o.url;if(!lo[u]){lo[u]=o;t.queue.push(o);}else o=lo[u];if(o.state>0)return;if(!tinymce.dom.Event.domLoaded&&!t.settings.strict_mode){var ix,ol='';if(cb||o.func){o.state=1;ix=tinymce.dom.ScriptLoader._addOnLoad(function(){done(o);allDone();});if(tinymce.isIE)ol=' onreadystatechange="';else ol=' onload="';ol+='tinymce.dom.ScriptLoader._onLoad(this,\''+u+'\','+ix+');"';}document.write('<script type="text/javascript" src="'+u+'"'+ol+'></script>');if(!o.func)done(o);}else load(o);});allDone();},'static':{_addOnLoad:function(f){var t=this;t._funcs=t._funcs||[];t._funcs.push(f);return t._funcs.length-1;},_onLoad:function(e,u,ix){if(!tinymce.isIE||e.readyState=='complete')this._funcs[ix].call(this);}}});tinymce.ScriptLoader=new tinymce.dom.ScriptLoader();})();(function(){var DOM=tinymce.DOM,is=tinymce.is;tinymce.create('tinymce.ui.Control',{Control:function(id,s){this.id=id;this.settings=s=s||{};this.rendered=false;this.onRender=new tinymce.util.Dispatcher(this);this.classPrefix='';this.scope=s.scope||this;this.disabled=0;this.active=0;},setDisabled:function(s){var e;if(s!=this.disabled){e=DOM.get(this.id);if(e&&this.settings.unavailable_prefix){if(s){this.prevTitle=e.title;e.title=this.settings.unavailable_prefix+": "+e.title;}else e.title=this.prevTitle;}this.setState('Disabled',s);this.setState('Enabled',!s);this.disabled=s;}},isDisabled:function(){return this.disabled;},setActive:function(s){if(s!=this.active){this.setState('Active',s);this.active=s;}},isActive:function(){return this.active;},setState:function(c,s){var n=DOM.get(this.id);c=this.classPrefix+c;if(s)DOM.addClass(n,c);else DOM.removeClass(n,c);},isRendered:function(){return this.rendered;},renderHTML:function(){},renderTo:function(n){DOM.setHTML(n,this.renderHTML());},postRender:function(){var t=this,b;if(is(t.disabled)){b=t.disabled;t.disabled=-1;t.setDisabled(b);}if(is(t.active)){b=t.active;t.active=-1;t.setActive(b);}},destroy:function(){DOM.remove(this.id);}});})();tinymce.create('tinymce.ui.Container:tinymce.ui.Control',{Container:function(id,s){this.parent(id,s);this.controls=[];this.lookup={};},add:function(c){this.lookup[c.id]=c;this.controls.push(c);return c;},get:function(n){return this.lookup[n];}});tinymce.create('tinymce.ui.Separator:tinymce.ui.Control',{renderHTML:function(){return tinymce.DOM.createHTML('span',{'class':'mceSeparator'});}});(function(){var is=tinymce.is,DOM=tinymce.DOM,each=tinymce.each,walk=tinymce.walk;tinymce.create('tinymce.ui.MenuItem:tinymce.ui.Control',{MenuItem:function(id,s){this.parent(id,s);this.classPrefix='mceMenuItem';},setSelected:function(s){this.setState('Selected',s);this.selected=s;},isSelected:function(){return this.selected;},postRender:function(){var t=this;t.parent();if(is(t.selected))t.setSelected(t.selected);}});})();(function(){var is=tinymce.is,DOM=tinymce.DOM,each=tinymce.each,walk=tinymce.walk;tinymce.create('tinymce.ui.Menu:tinymce.ui.MenuItem',{Menu:function(id,s){var t=this;t.parent(id,s);t.items={};t.collapsed=false;t.menuCount=0;t.onAddItem=new tinymce.util.Dispatcher(this);},expand:function(d){var t=this;if(d){walk(t,function(o){if(o.expand)o.expand();},'items',t);}t.collapsed=false;},collapse:function(d){var t=this;if(d){walk(t,function(o){if(o.collapse)o.collapse();},'items',t);}t.collapsed=true;},isCollapsed:function(){return this.collapsed;},add:function(o){if(!o.settings)o=new tinymce.ui.MenuItem(o.id||DOM.uniqueId(),o);this.onAddItem.dispatch(this,o);return this.items[o.id]=o;},addSeparator:function(){return this.add({separator:true});},addMenu:function(o){if(!o.collapse)o=this.createMenu(o);this.menuCount++;return this.add(o);},hasMenus:function(){return this.menuCount!==0;},remove:function(o){delete this.items[o.id];},removeAll:function(){var t=this;walk(t,function(o){if(o.removeAll)o.removeAll();o.destroy();},'items',t);t.items={};},createMenu:function(o){var m=new tinymce.ui.Menu(o.id||DOM.uniqueId(),o);m.onAddItem.add(this.onAddItem.dispatch,this.onAddItem);return m;}});})();(function(){var is=tinymce.is,DOM=tinymce.DOM,each=tinymce.each,Event=tinymce.dom.Event,Element=tinymce.dom.Element;tinymce.create('tinymce.ui.DropMenu:tinymce.ui.Menu',{DropMenu:function(id,s){s=s||{};s.container=s.container||document.body;s.offset_x=s.offset_x||0;s.offset_y=s.offset_y||0;s.vp_offset_x=s.vp_offset_x||0;s.vp_offset_y=s.vp_offset_y||0;if(is(s.icons)&&!s.icons)s['class']+=' noIcons';this.parent(id,s);this.onHideMenu=new tinymce.util.Dispatcher(this);this.classPrefix='mceMenu';},createMenu:function(s){var t=this,cs=t.settings,m;s.container=s.container||cs.container;s.parent=t;s.constrain=s.constrain||cs.constrain;s['class']=s['class']||cs['class'];s.vp_offset_x=s.vp_offset_x||cs.vp_offset_x;s.vp_offset_y=s.vp_offset_y||cs.vp_offset_y;m=new tinymce.ui.DropMenu(s.id||DOM.uniqueId(),s);m.onAddItem.add(t.onAddItem.dispatch,t.onAddItem);return m;},update:function(){var t=this,s=t.settings,tb=DOM.get('menu_'+t.id+'_tbl'),co=DOM.get('menu_'+t.id+'_co'),tw,th;tw=s.max_width?Math.min(tb.clientWidth,s.max_width):tb.clientWidth;th=s.max_height?Math.min(tb.clientHeight,s.max_height):tb.clientHeight;if(!DOM.boxModel)t.element.setStyles({width:tw+2,height:th+2});else t.element.setStyles({width:tw,height:th});if(s.max_width)DOM.setStyle(co,'width',tw);if(s.max_height){DOM.setStyle(co,'height',th);if(tb.clientHeight<s.max_height)DOM.setStyle(co,'overflow','hidden');}},showMenu:function(x,y,px){var t=this,s=t.settings,co,vp=DOM.getViewPort(),w,h,mx,my,ot=2,dm,tb;t.collapse(1);if(t.isMenuVisible)return;if(!t.rendered){co=DOM.add(t.settings.container,t.renderNode());each(t.items,function(o){o.postRender();});t.element=new Element('menu_'+t.id,{blocker:1,container:s.container});}else co=DOM.get('menu_'+t.id);DOM.setStyles(co,{left:-0xFFFF,top:-0xFFFF});DOM.show(co);t.update();x+=s.offset_x||0;y+=s.offset_y||0;vp.w-=4;vp.h-=4;if(s.constrain){w=co.clientWidth-ot;h=co.clientHeight-ot;mx=vp.x+vp.w;my=vp.y+vp.h;if((x+s.vp_offset_x+w)>mx)x=px?px-w:Math.max(0,(mx-s.vp_offset_x)-w);if((y+s.vp_offset_y+h)>my)y=Math.max(0,(my-s.vp_offset_y)-h);}DOM.setStyles(co,{left:x,top:y});t.element.update();t.isMenuVisible=1;t.mouseClickFunc=Event.add(co,'click',function(e){var m;e=e.target;if(e&&(e=DOM.getParent(e,'TR'))&&!DOM.hasClass(e,'mceMenuItemSub')){m=t.items[e.id];if(m.isDisabled())return;if(m.settings.onclick)m.settings.onclick(e);dm=t;while(dm){if(dm.hideMenu)dm.hideMenu();dm=dm.settings.parent;}return Event.cancel(e);}});if(t.hasMenus()){t.mouseOverFunc=Event.add(co,'mouseover',function(e){var m,r,mi;e=e.target;if(e&&(e=DOM.getParent(e,'TR'))){m=t.items[e.id];if(t.lastMenu)t.lastMenu.collapse(1);if(m.isDisabled())return;if(e&&DOM.hasClass(e,'mceMenuItemSub')){r=DOM.getRect(e);m.showMenu((r.x+r.w-ot),r.y-ot,r.x);t.lastMenu=m;DOM.addClass(DOM.get(m.id).firstChild,'mceMenuItemActive');}}});}},hideMenu:function(c){var t=this,co=DOM.get('menu_'+t.id),e;if(!t.isMenuVisible)return;Event.remove(co,'mouseover',t.mouseOverFunc);Event.remove(co,'click',t.mouseClickFunc);DOM.hide(co);t.isMenuVisible=0;if(!c)t.collapse(1);if(t.element)t.element.hide();if(e=DOM.get(t.id))DOM.removeClass(e.firstChild,'mceMenuItemActive');t.onHideMenu.dispatch(t);},add:function(o){var t=this,co;o=t.parent(o);if(t.isRendered&&(co=DOM.get('menu_'+t.id)))t._add(DOM.select('tbody',co)[0],o);return o;},collapse:function(d){this.parent(d);this.hideMenu(1);},remove:function(o){DOM.remove(o.id);return this.parent(o);},destroy:function(){var t=this,co=DOM.get('menu_'+t.id);Event.remove(co,'mouseover',t.mouseOverFunc);Event.remove(co,'click',t.mouseClickFunc);if(t.element)t.element.remove();DOM.remove(co);},renderNode:function(){var t=this,s=t.settings,n,tb,co,w;w=DOM.create('div',{id:'menu_'+t.id,'class':s['class'],'style':'position:absolute;left:0;top:0;z-index:150'});co=DOM.add(w,'div',{id:'menu_'+t.id+'_co','class':'mceMenu'+(s['class']?' '+s['class']:'')});t.element=new Element('menu_'+t.id,{blocker:1,container:s.container});if(s.menu_line)DOM.add(co,'span',{'class':'mceMenuLine'});n=DOM.add(co,'table',{id:'menu_'+t.id+'_tbl',border:0,cellPadding:0,cellSpacing:0});tb=DOM.add(n,'tbody');each(t.items,function(o){t._add(tb,o);});t.rendered=true;return w;},_add:function(tb,o){var n,s=o.settings,a,ro,it;if(s.separator){ro=DOM.add(tb,'tr',{id:o.id,'class':'mceMenuItemSeparator'});DOM.add(ro,'td',{'class':'mceMenuItemSeparator'});if(n=ro.previousSibling)DOM.addClass(n,'last');return;}n=ro=DOM.add(tb,'tr',{id:o.id,'class':'mceMenuItem mceMenuItemEnabled'});n=it=DOM.add(n,'td');n=a=DOM.add(n,'a',{href:'javascript:;',onclick:"return false;",onmousedown:'return false;'});DOM.addClass(it,s['class']);DOM.add(n,'span',{'class':'icon'+(s.icon?' '+s.icon:'')});n=DOM.add(n,s.element||'span',{'class':'text',title:o.settings.title},o.settings.title);if(o.settings.style)DOM.setAttrib(n,'style',o.settings.style);if(tb.childNodes.length==1)DOM.addClass(ro,'first');if((n=ro.previousSibling)&&DOM.hasClass(n,'mceMenuItemSeparator'))DOM.addClass(ro,'first');if(o.collapse)DOM.addClass(ro,'mceMenuItemSub');if(n=ro.previousSibling)DOM.removeClass(n,'last');DOM.addClass(ro,'last');}});})();(function(){var DOM=tinymce.DOM;tinymce.create('tinymce.ui.Button:tinymce.ui.Control',{Button:function(id,s){this.parent(id,s);this.classPrefix='mceButton';},renderHTML:function(){var s=this.settings,h='<a id="'+this.id+'" href="javascript:;" class="mceButton mceButtonEnabled '+s['class']+'" onmousedown="return false;" onclick="return false;" title="'+DOM.encode(s.title)+'">';if(s.image)h+='<img class="icon" src="'+s.image+'" /></a>';else h+='<span class="icon '+s['class']+'"></span></a>';return h;},postRender:function(){var t=this,s=t.settings;tinymce.dom.Event.add(t.id,'click',function(e){if(!t.isDisabled())return s.onclick.call(s.scope,e);});}});})();(function(){var DOM=tinymce.DOM,Event=tinymce.dom.Event,each=tinymce.each,Dispatcher=tinymce.util.Dispatcher;tinymce.create('tinymce.ui.ListBox:tinymce.ui.Control',{ListBox:function(id,s){var t=this;t.parent(id,s);t.items=[];t.onChange=new Dispatcher(t);t.onPostRender=new Dispatcher(t);t.onAdd=new Dispatcher(t);t.onRenderMenu=new tinymce.util.Dispatcher(this);t.classPrefix='mceListBox';},select:function(v){var t=this,e,fv;if(v!=t.selectedValue){e=DOM.get(t.id+'_text');t.selectedValue=v;each(t.items,function(o){if(o.value==v){DOM.setHTML(e,DOM.encode(o.title));fv=1;return false;}});if(!fv){DOM.setHTML(e,DOM.encode(t.settings.title));DOM.addClass(e,'title');e=0;return;}else DOM.removeClass(e,'title');}e=0;},add:function(n,v,o){var t=this;o=o||{};o=tinymce.extend(o,{title:n,value:v});t.items.push(o);t.onAdd.dispatch(t,o);},getLength:function(){return this.items.length;},renderHTML:function(){var h='',t=this,s=t.settings;h='<table id="'+t.id+'" cellpadding="0" cellspacing="0" class="mceListBox mceListBoxEnabled'+(s['class']?(' '+s['class']):'')+'"><tbody><tr>';h+='<td>'+DOM.createHTML('a',{id:t.id+'_text',href:'javascript:;','class':'text',onclick:"return false;",onmousedown:'return false;'},DOM.encode(t.settings.title))+'</td>';h+='<td>'+DOM.createHTML('a',{id:t.id+'_open',href:'javascript:;','class':'open',onclick:"return false;",onmousedown:'return false;'},'<span></span>')+'</td>';h+='</tr></tbody></table>';return h;},showMenu:function(){var t=this,p1,p2,e=DOM.get(this.id),m;if(t.isDisabled()||t.items.length==0)return;if(!t.isMenuRendered){t.renderMenu();t.isMenuRendered=true;}p1=DOM.getPos(this.settings.menu_container);p2=DOM.getPos(e);m=t.menu;m.settings.offset_x=p2.x;m.settings.offset_y=p2.y;if(t.oldID)m.items[t.oldID].setSelected(0);each(t.items,function(o){if(o.value===t.selectedValue){m.items[o.id].setSelected(1);t.oldID=o.id;}});m.showMenu(0,e.clientHeight);Event.add(document,'mousedown',t.hideMenu,t);DOM.addClass(t.id,'mceListBoxSelected');},hideMenu:function(e){var t=this;if(!e||!DOM.getParent(e.target,function(n){return DOM.hasClass(n,'mceMenu');})){DOM.removeClass(t.id,'mceListBoxSelected');Event.remove(document,'mousedown',t.hideMenu,t);if(t.menu)t.menu.hideMenu();}},renderMenu:function(){var t=this,m;m=t.settings.control_manager.createDropMenu(t.id+'_menu',{menu_line:1,'class':'mceListBoxMenu noIcons',max_width:150,max_height:150});m.onHideMenu.add(t.hideMenu,t);m.add({title:t.settings.title,'class':'mceMenuItemTitle'}).setDisabled(1);each(t.items,function(o){o.id=DOM.uniqueId();o.onclick=function(){if(t.settings.onselect(o.value)!==false)t.select(o.value);};m.add(o);});t.onRenderMenu.dispatch(t,m);t.menu=m;},postRender:function(){var t=this;Event.add(t.id,'click',t.showMenu,t);if(tinymce.isIE6||!DOM.boxModel){Event.add(t.id,'mouseover',function(){if(!DOM.hasClass(t.id,'mceListBoxDisabled'))DOM.addClass(t.id,'mceListBoxHover');});Event.add(t.id,'mouseout',function(){if(!DOM.hasClass(t.id,'mceListBoxDisabled'))DOM.removeClass(t.id,'mceListBoxHover');});}t.onPostRender.dispatch(t,DOM.get(t.id));}});})();(function(){var DOM=tinymce.DOM,Event=tinymce.dom.Event,each=tinymce.each,Dispatcher=tinymce.util.Dispatcher;tinymce.create('tinymce.ui.NativeListBox:tinymce.ui.ListBox',{NativeListBox:function(id,s){this.parent(id,s);this.classPrefix='mceNativeListBox';},setDisabled:function(s){DOM.get(this.id).disabled=s;},isDisabled:function(){return DOM.get(this.id).disabled;},select:function(v){var e=DOM.get(this.id),ol=e.options;v=''+(v||'');e.selectedIndex=0;each(ol,function(o,i){if(o.value==v){e.selectedIndex=i;return false;}});},add:function(n,v,a){var o,t=this;a=a||{};a.value=v;if(t.isRendered())DOM.add(DOM.get(this.id),'option',a,n);o={title:n,value:v,attribs:a};t.items.push(o);t.onAdd.dispatch(t,o);},getLength:function(){return DOM.get(this.id).options.length-1;},renderHTML:function(){var h,t=this;h=DOM.createHTML('option',{value:''},'-- '+t.settings.title+' --');each(t.items,function(it){h+=DOM.createHTML('option',{value:it.value},it.title);});h=DOM.createHTML('select',{id:t.id,'class':'mceNativeListBox'},h);return h;},postRender:function(){var t=this,ch;t.rendered=true;function onChange(e){var v=e.target.options[e.target.selectedIndex].value;t.onChange.dispatch(t,v);if(t.settings.onselect)t.settings.onselect(v);};Event.add(t.id,'change',onChange);Event.add(t.id,'keydown',function(e){var bf;Event.remove(t.id,'change',ch);bf=Event.add(t.id,'blur',function(){Event.add(t.id,'change',onChange);Event.remove(t.id,'blur',bf);});if(e.keyCode==13||e.keyCode==32){onChange(e);return Event.cancel(e);}});t.onPostRender.dispatch(t,DOM.get(t.id));}});})();(function(){var DOM=tinymce.DOM,Event=tinymce.dom.Event,each=tinymce.each;tinymce.create('tinymce.ui.MenuButton:tinymce.ui.Button',{MenuButton:function(id,s){this.parent(id,s);this.onRenderMenu=new tinymce.util.Dispatcher(this);s.menu_container=s.menu_container||document.body;},showMenu:function(){var t=this,p1,p2,e=DOM.get(t.id),m;if(t.isDisabled())return;if(!t.isMenuRendered){t.renderMenu();t.isMenuRendered=true;}p1=DOM.getPos(t.settings.menu_container);p2=DOM.getPos(e);m=t.menu;m.settings.offset_x=p2.x;m.settings.offset_y=p2.y;m.settings.vp_offset_x=p2.x;m.settings.vp_offset_y=p2.y;m.showMenu(0,e.clientHeight);Event.add(document,'mousedown',t.hideMenu,t);t.setState('Selected',1);},renderMenu:function(){var t=this,m;m=t.settings.control_manager.createDropMenu(t.id+'_menu',{menu_line:1,'class':this.classPrefix+'Menu',icons:t.settings.icons});m.onHideMenu.add(t.hideMenu,t);t.onRenderMenu.dispatch(t,m);t.menu=m;},hideMenu:function(e){var t=this;if(!e||!DOM.getParent(e.target,function(n){return DOM.hasClass(n,'mceMenu');})){t.setState('Selected',0);Event.remove(document,'mousedown',t.hideMenu,t);if(t.menu)t.menu.hideMenu();}},postRender:function(){var t=this,s=t.settings;Event.add(t.id,'click',function(){if(!t.isDisabled()){if(s.onclick)s.onclick(t.value);t.showMenu();}});}});})();(function(){var DOM=tinymce.DOM,Event=tinymce.dom.Event,each=tinymce.each;tinymce.create('tinymce.ui.SplitButton:tinymce.ui.MenuButton',{SplitButton:function(id,s){this.parent(id,s);this.classPrefix='mceSplitButton';},renderHTML:function(){var h,t=this,s=t.settings,h1;h='<tbody><tr>';if(s.image)h1=DOM.createHTML('img ',{src:s.image,'class':'action '+s['class']});else h1=DOM.createHTML('span',{'class':'action '+s['class']});h+='<td>'+DOM.createHTML('a',{id:t.id+'_action',href:'javascript:;','class':'action '+s['class'],onclick:"return false;",onmousedown:'return false;',title:s.title},h1)+'</td>';h1=DOM.createHTML('span',{'class':'open '+s['class']});h+='<td>'+DOM.createHTML('a',{id:t.id+'_open',href:'javascript:;','class':'open '+s['class'],onclick:"return false;",onmousedown:'return false;',title:s.title},h1)+'</td>';h+='</tr></tbody>';return DOM.createHTML('table',{id:t.id,'class':'mceSplitButton mceSplitButtonEnabled '+s['class'],cellpadding:'0',cellspacing:'0',onmousedown:'return false;',title:s.title},h);},postRender:function(){var t=this,s=t.settings;if(s.onclick){Event.add(t.id+'_action','click',function(){if(!t.isDisabled())s.onclick(t.value);});}Event.add(t.id+'_open','click',t.showMenu,t);if(tinymce.isIE6||!DOM.boxModel){Event.add(t.id,'mouseover',function(){if(!DOM.hasClass(t.id,'mceSplitButtonDisabled'))DOM.addClass(t.id,'mceSplitButtonHover');});Event.add(t.id,'mouseout',function(){if(!DOM.hasClass(t.id,'mceSplitButtonDisabled'))DOM.removeClass(t.id,'mceSplitButtonHover');});}}});})();(function(){var DOM=tinymce.DOM,Event=tinymce.dom.Event,is=tinymce.is,each=tinymce.each;tinymce.create('tinymce.ui.ColorSplitButton:tinymce.ui.SplitButton',{ColorSplitButton:function(id,s){var t=this;t.parent(id,s);t.settings=s=tinymce.extend({colors:'000000,993300,333300,003300,003366,000080,333399,333333,800000,FF6600,808000,008000,008080,0000FF,666699,808080,FF0000,FF9900,99CC00,339966,33CCCC,3366FF,800080,999999,FF00FF,FFCC00,FFFF00,00FF00,00FFFF,00CCFF,993366,C0C0C0,FF99CC,FFCC99,FFFF99,CCFFCC,CCFFFF,99CCFF,CC99FF,FFFFFF',grid_width:8,default_color:'#888888'},t.settings);t.value=s.default_color;},showMenu:function(){var t=this,r,p,e;if(t.isDisabled())return;if(!t.isMenuRendered){t.renderMenu();t.isMenuRendered=true;}e=DOM.get(t.id);DOM.show(t.id+'_menu');DOM.addClass(e,'mceSplitButtonSelected');p2=DOM.getPos(e);DOM.setStyles(t.id+'_menu',{left:p2.x,top:p2.y+e.clientHeight,zIndex:150});e=0;Event.add(document,'mousedown',t.hideMenu,t);},hideMenu:function(e){var t=this;if(!e||!DOM.getParent(e.target,function(n){return DOM.hasClass(n,'mceSplitButtonMenu');})){DOM.removeClass(t.id,'mceSplitButtonSelected');Event.remove(document,'mousedown',t.hideMenu,t);DOM.hide(t.id+'_menu');}},renderMenu:function(){var t=this,m,i=0,s=t.settings,n,tb,tr,w;w=DOM.add(s.menu_container,'div',{id:t.id+'_menu','class':s['menu_class']+' '+s['class'],style:'position:absolute;left:0;top:-1000px;'});m=DOM.add(w,'div',{'class':s['class']+' mceSplitButtonMenu'});DOM.add(m,'span',{'class':'mceMenuLine'});n=DOM.add(m,'table',{'class':'mceColorSplitMenu'});tb=DOM.add(n,'tbody');i=0;each(is(s.colors,'array')?s.colors:s.colors.split(','),function(c){c=c.replace(/^#/,'');if(!i--){tr=DOM.add(tb,'tr');i=s.grid_width-1;}n=DOM.add(tr,'td');n=DOM.add(n,'a',{href:'javascript:;',style:{backgroundColor:'#'+c}});Event.add(n,'mousedown',function(){t.setColor('#'+c);});});if(s.more_colors_func){n=DOM.add(tb,'tr');n=DOM.add(n,'td',{colspan:s.grid_width,'class':'morecolors'});n=DOM.add(n,'a',{href:'javascript:;',onclick:'return false;','class':'morecolors'},s.more_colors_title);Event.add(n,'click',function(e){s.more_colors_func.call(s.more_colors_scope||this);return Event.cancel(e);});}DOM.addClass(m,'mceColorSplitMenu');return w;},setColor:function(c){var t=this,p,s=this.settings,co=s.menu_container,po,cp,id=t.id+'_preview';if(!(p=DOM.get(id))){DOM.setStyle(t.id+'_action','position','relative');p=DOM.add(t.id+'_action','div',{id:id,'class':'mceColorPreview'});}p.style.backgroundColor=c;t.value=c;t.hideMenu();s.onselect(c);}});})();tinymce.create('tinymce.ui.Toolbar:tinymce.ui.Container',{renderHTML:function(){var t=this,h='',c='mceToolbarEnd',co,dom=tinymce.DOM,s=t.settings;h+=dom.createHTML('td',{'class':'mceToolbarStart'},dom.createHTML('span',null,'<!-- IE -->'));tinymce.each(t.controls,function(c){h+='<td>'+c.renderHTML()+'</td>';});co=t.controls[t.controls.length-1].constructor;if(co===tinymce.ui.Button)c+=' mceToolbarEndButton';else if(co===tinymce.ui.SplitButton)c+=' mceToolbarEndSplitButton';else if(co===tinymce.ui.ListBox)c+=' mceToolbarEndListBox';h+=dom.createHTML('td',{'class':c},dom.createHTML('span',null,'<!-- IE -->'));return dom.createHTML('table',{id:t.id,'class':'mceToolbar'+(s['class']?' '+s['class']:''),cellpadding:'0',cellspacing:'0',align:t.settings.align||''},'<tbody><tr>'+h+'</tr></tbody>');}});(function(){var Dispatcher=tinymce.util.Dispatcher,each=tinymce.each;tinymce.create('tinymce.AddOnManager',{items:[],urls:{},lookup:{},onAdd:new Dispatcher(this),get:function(n){return this.lookup[n];},requireLangPack:function(n){var u,s;if(tinymce.EditorManager.settings){u=this.urls[n]+'/langs/'+tinymce.EditorManager.settings.language+'.js';s=tinymce.EditorManager.settings;if(s){if(!tinymce.dom.Event.domLoaded&&!s.strict_mode)tinymce.ScriptLoader.load(u);else tinymce.ScriptLoader.add(u);}}},add:function(id,o){this.items.push(o);this.lookup[id]=o;this.onAdd.dispatch(this,id,o);return o;},load:function(n,u,cb,s){if(u.indexOf('/')!=0&&u.indexOf('://')==-1)u=tinymce.baseURL+'/'+u;this.urls[n]=u.substring(0,u.lastIndexOf('/'));tinymce.ScriptLoader.add(u,cb,s);}});tinymce.PluginManager=new tinymce.AddOnManager();tinymce.ThemeManager=new tinymce.AddOnManager();}());(function(){var each=tinymce.each,extend=tinymce.extend,DOM=tinymce.DOM,Event=tinymce.dom.Event,ThemeManager=tinymce.ThemeManager,PluginManager=tinymce.PluginManager;tinymce.create('static tinymce.EditorManager',{editors:{},i18n:{},activeEditor:null,init:function(s){var t=this,pl,sl=tinymce.ScriptLoader;function execCallback(se,n,s){var f=se[n];if(!f)return;if(tinymce.is(f,'string')){s=f.replace(/\.\w+$/,'');s=s?tinymce.resolve(s):0;f=tinymce.resolve(f);}return f.apply(s||this,Array.prototype.slice.call(arguments,2));};s=extend({theme:"simple",language:"en",strict_loading_mode:document.contentType=='application/xhtml+xml'},s);t.settings=s;if(!Event.domLoaded&&!s.strict_loading_mode){if(s.language)sl.add(tinymce.baseURL+'/langs/'+s.language+'.js');if(s.theme&&s.theme.charAt(0)!='-')ThemeManager.load(s.theme,'themes/'+s.theme+'/editor_template'+tinymce.suffix+'.js');if(s.plugins){pl=s.plugins.split(',');if(tinymce.inArray(pl,'compat2x')!=-1)PluginManager.load('compat2x','plugins/compat2x/editor_plugin'+tinymce.suffix+'.js');each(pl,function(v){if(v&&v.charAt(0)!='-'){if(!tinymce.isWebKit&&v=='safari')return;PluginManager.load(v,'plugins/'+v+'/editor_plugin'+tinymce.suffix+'.js');}});}sl.loadQueue();}Event.add(document,'init',function(){var l,co;execCallback(s,'onpageload');if(s.browsers){l=false;each(s.browsers.split(','),function(v){switch(v){case'ie':case'msie':if(tinymce.isIE)l=true;break;case'gecko':if(tinymce.isGecko)l=true;break;case'safari':case'webkit':if(tinymce.isWebKit)l=true;break;case'opera':if(tinymce.isOpera)l=true;break;}});if(!l)return;}switch(s.mode){case"exact":l=s.elements||'';each(l.split(','),function(v){new tinymce.Editor(v,s).render();});break;case"textareas":function hasClass(n,c){return new RegExp('\\b'+c+'\\b','g').test(n.className);};each(DOM.select('textarea'),function(v){if(s.editor_deselector&&hasClass(v,s.editor_deselector))return;if(!s.editor_selector||hasClass(v,s.editor_selector))new tinymce.Editor(v.id=(v.id||v.name||(v.id=DOM.uniqueId())),s).render();});break;}if(s.oninit){l=co=0;each(t.editors,function(ed){co++;if(!ed.initialized){ed.onInit.add(function(){l++;if(l==co)execCallback(s,'oninit');});}else l++;if(l==co)execCallback(s,'oninit');});}});},get:function(id){return this.editors[id];},getInstanceById:function(id){return this.get(id);},add:function(e){this.editors[e.id]=e;this._setActive(e);return e;},remove:function(e){var t=this;if(!t.editors[e.id])return null;delete t.editors[e.id];if(t.activeEditor==e){each(t.editors,function(e){t._setActive(e);return false;});}e._destroy();return e;},execCommand:function(c,u,v){var t=this,ed=t.get(v);switch(c){case"mceFocus":ed.focus();return true;case"mceAddEditor":case"mceAddControl":new tinymce.Editor(v,t.settings).render();return true;case"mceAddFrameControl":return true;case"mceRemoveEditor":case"mceRemoveControl":ed.remove();return true;case'mceToggleEditor':if(!ed){t.execCommand('mceAddControl',0,v);return true;}if(ed.isHidden())ed.show();else ed.hide();return true;}if(t.activeEditor)return t.activeEditor.execCommand(c,u,v);return false;},execInstanceCommand:function(id,c,u,v){var ed=this.get(id);if(ed)return ed.execCommand(c,u,v);return false;},triggerSave:function(){each(this.editors,function(e){e.save();});},addI18n:function(p,o){var lo,i18n=this.i18n;if(!tinymce.is(p,'string')){each(p,function(o,lc){each(o,function(o,g){each(o,function(o,k){if(g==='common')i18n[lc+'.'+k]=o;else i18n[lc+'.'+g+'.'+k]=o;});});});}else{each(o,function(o,k){i18n[p+'.'+k]=o;});}},_setActive:function(e){this.selectedInstance=this.activeEditor=e;}});tinymce.documentBaseURL=window.location.href.replace(/[\?#].*$/,'').replace(/[\/\\][^\/]+$/,'');if(!/[\/\\]$/.test(tinymce.documentBaseURL))tinymce.documentBaseURL+='/';tinymce.baseURL=new tinymce.util.URI(tinymce.documentBaseURL).toAbsolute(tinymce.baseURL);tinymce.EditorManager.baseURI=new tinymce.util.URI(tinymce.baseURL);})();var tinyMCE=window.tinyMCE=tinymce.EditorManager;(function(){var DOM=tinymce.DOM,Event=tinymce.dom.Event,extend=tinymce.extend,Dispatcher=tinymce.util.Dispatcher;var each=tinymce.each,isGecko=tinymce.isGecko,isIE=tinymce.isIE,isWebKit=tinymce.isWebKit;var is=tinymce.is,ThemeManager=tinymce.ThemeManager,PluginManager=tinymce.PluginManager,EditorManager=tinymce.EditorManager;var inArray=tinymce.inArray,grep=tinymce.grep;tinymce.create('tinymce.Editor',{Editor:function(id,s){var t=this;t.id=t.editorId=id;t.execCommands={};t.queryStateCommands={};t.queryValueCommands={};t.plugins={};each(['onPreInit','onBeforeRenderUI','onPostRender','onInit','onRemove','onActivate','onDeactivate','onClick','onEvent','onMouseUp','onMouseDown','onDblClick','onKeyDown','onKeyUp','onKeyPress','onContextMenu','onSubmit','onReset','onPaste','onPreProcess','onPostProcess','onBeforeSetContent','onBeforeGetContent','onSetContent','onGetContent','onLoadContent','onSaveContent','onNodeChange','onChange','onBeforeExecCommand','onExecCommand','onUndo','onRedo','onVisualAid','onSetProgressState'],function(e){t[e]=new Dispatcher(t);});t.settings=s=extend({id:id,language:'en',docs_language:'en',theme:'simple',skin:'default',delta_width:0,delta_height:0,popup_css:'',plugins:'',document_base_url:tinymce.documentBaseURL,add_form_submit_trigger:1,submit_patch:1,add_unload_trigger:1,convert_urls:1,relative_urls:1,remove_script_host:1,table_inline_editing:0,object_resizing:1,cleanup:1,accessibility_focus:1,custom_shortcuts:1,custom_undo_redo_keyboard_shortcuts:1,custom_undo_redo_restore_selection:1,custom_undo_redo:1,doctype:'<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">',visual_table_class:'mceItemTable',visual:1,inline_styles:true,convert_fonts_to_spans:true,font_size_style_values:'xx-small,x-small,small,medium,large,x-large,xx-large',apply_source_formatting:1,directionality:'ltr',forced_root_block:'p',valid_elements:'@[id|class|style|title|dir<ltr?rtl|lang|xml::lang|onclick|ondblclick|onmousedown|onmouseup|onmouseover|onmousemove|onmouseout|onkeypress|onkeydown|onkeyup],a[rel|rev|charset|hreflang|tabindex|accesskey|type|name|href|target|title|class|onfocus|onblur],strong/b,em/i,strike,u,#p[align],-ol[type|compact],-ul[type|compact],-li,br,img[longdesc|usemap|src|border|alt=|title|hspace|vspace|width|height|align],-sub,-sup,-blockquote,-table[border=0|cellspacing|cellpadding|width|frame|rules|height|align|summary|bgcolor|background|bordercolor],-tr[rowspan|width|height|align|valign|bgcolor|background|bordercolor],tbody,thead,tfoot,#td[colspan|rowspan|width|height|align|valign|bgcolor|background|bordercolor|scope],#th[colspan|rowspan|width|height|align|valign|scope],caption,-div,-span,-pre,address,-h1,-h2,-h3,-h4,-h5,-h6,hr[size|noshade],-font[face|size|color],dd,dl,dt,cite,abbr,acronym,del[datetime|cite],ins[datetime|cite],object[classid|width|height|codebase|*],param[name|value|_value],embed[type|width|height|src|*],script[type],map[name],area[shape|coords|href|alt|target]',hidden_input:1,padd_empty_editor:1,render_ui:1,init_theme:1,indentation:'30px'},s);t.documentBaseURI=new tinymce.util.URI(s.document_base_url||tinymce.documentBaseURL,{base_uri:tinyMCE.baseURI});t.baseURI=EditorManager.baseURI;t.execCallback('setup',t);},render:function(){var t=this,s=t.settings,id=t.id,sl=tinymce.ScriptLoader;if(!t.getElement())return;if(s.strict_loading_mode){sl.settings.strict_mode=s.strict_loading_mode;tinymce.DOM.settings.strict=1;}if(!/TEXTAREA|INPUT/i.test(t.getElement().nodeName)&&s.hidden_input&&DOM.getParent(id,'form'))DOM.insertAfter(DOM.create('input',{type:'hidden',name:id}),id);t.windowManager=new tinymce.WindowManager(t);if(s.encoding=='xml'){t.onGetContent.add(function(ed,o){if(o.get)o.content=DOM.encode(o.content);});}if(s.add_form_submit_trigger){t.onSubmit.addToTop(function(){if(t.initialized){t.save();t.isNotDirty=1;}});}Event.add(document,'unload',function(){if(t.initialized&&!t.destroyed&&s.add_unload_trigger)t.save({format:'raw',no_events:true});});tinymce.addUnload(t._destroy,t);if(s.submit_patch){t.onBeforeRenderUI.add(function(){var n=t.getElement().form;if(!n)return;if(n._mceOldSubmit)return;if(!n.submit.nodeType){t.formElement=n;n._mceOldSubmit=n.submit;n.submit=function(){EditorManager.triggerSave();t.isNotDirty=1;return this._mceOldSubmit(this);};}n=null;});}function loadScripts(){sl.add(tinymce.baseURL+'/langs/'+s.language+'.js');if(s.theme.charAt(0)!='-')ThemeManager.load(s.theme,'themes/'+s.theme+'/editor_template'+tinymce.suffix+'.js');each(s.plugins.split(','),function(p){if(p&&p.charAt(0)!='-'){if(!isWebKit&&p=='safari')return;PluginManager.load(p,'plugins/'+p+'/editor_plugin'+tinymce.suffix+'.js');}});sl.loadQueue(function(){if(s.ask){function ask(){t.windowManager.confirm(t.getLang('edit_confirm'),function(s){if(s)t.init();else Event.remove(t.id,'focus',ask);});};Event.add(t.id,'focus',ask);return;}if(!t.removed)t.init();});};if(s.plugins.indexOf('compat2x')!=-1){PluginManager.load('compat2x','plugins/compat2x/editor_plugin'+tinymce.suffix+'.js');sl.loadQueue(loadScripts);}else loadScripts();},init:function(){var n,t=this,s=t.settings,w,h,e=t.getElement(),o,ti;EditorManager.add(t);s.theme=s.theme.replace(/-/,'');o=ThemeManager.get(s.theme);t.theme=new o();if(t.theme.init&&s.init_theme)t.theme.init(t,ThemeManager.urls[s.theme]||tinymce.documentBaseURL.replace(/\/$/,''));each(s.plugins.replace(/\-/g,'').split(','),function(p){var c=PluginManager.get(p),u=PluginManager.urls[p]||tinymce.documentBaseURL.replace(/\/$/,''),po;if(c){po=new c(t,u);t.plugins[p]=po;if(po.init)po.init(t,u);}});s.popup_css=t.baseURI.toAbsolute(s.popup_css||"themes/"+s.theme+"/skins/"+s.skin+"/dialog.css");if(s.popup_css_add)s.popup_css+=','+s.popup_css_add;t.controlManager=new tinymce.ControlManager(t);t.undoManager=new tinymce.UndoManager(t);t.undoManager.onAdd.add(function(um,l){return t.onChange.dispatch(t,l,um);});t.undoManager.onUndo.add(function(um,l){return t.onUndo.dispatch(t,l,um);});t.undoManager.onRedo.add(function(um,l){return t.onRedo.dispatch(t,l,um);});if(s.custom_undo_redo){t.onExecCommand.add(function(ed,cmd){if(cmd!='Undo'&&cmd!='Redo'&&cmd!='mceRepaint')t.undoManager.add();});}t.onExecCommand.add(function(ed,c){if(!/^(FontName|FontSize)$/.test(c))t.nodeChanged();});if(isGecko){function repaint(){t.execCommand('mceRepaint');};t.onUndo.add(repaint);t.onRedo.add(repaint);t.onSetContent.add(repaint);}t.onBeforeRenderUI.dispatch(t,t.controlManager);if(s.render_ui){w=s.width||e.style.width||e.clientWidth;h=s.height||e.style.height||e.clientHeight;t.orgDisplay=e.style.display;if((''+w).indexOf('%')==-1)w=Math.max(parseInt(w)+(o.deltaWidth||0),100);if((''+h).indexOf('%')==-1)h=Math.max(parseInt(h)+(o.deltaHeight||0),100);o=t.theme.renderUI({targetNode:e,width:w,height:h,deltaWidth:s.delta_width,deltaHeight:s.delta_height});t.editorContainer=o.editorContainer;}DOM.setStyles(o.sizeContainer||o.editorContainer,{width:w,height:h});h=(o.iframeHeight||h)+((h+'').indexOf('%')==-1?(o.deltaHeight||0):'');if(h<100)h=100;n=DOM.add(o.iframeContainer,'iframe',{id:s.id+"_ifr",src:'javascript:""',frameBorder:'0',style:{width:'100%',height:h}});t.contentAreaContainer=o.iframeContainer;DOM.get(o.editorContainer).style.display=t.orgDisplay;DOM.get(s.id).style.display='none';if(tinymce.isOldWebKit){Event.add(n,'load',t.setupIframe,t);n.src=tinymce.baseURL+'/plugins/safari/blank.htm';}else{t.setupIframe();e=n=o=null;}},setupIframe:function(){var t=this,s=t.settings,e=DOM.get(s.id),d=t.getDoc();d.open();d.write(s.doctype+'<html><head xmlns="http://www.w3.org/1999/xhtml"><base href="'+t.documentBaseURI.getURI()+'" /><meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /></head><body id="tinymce" class="mceContentBody"></body></html>');d.close();if(!isIE){try{d.designMode='On';}catch(ex){}}if(isIE)t.getBody().contentEditable=true;t.dom=new tinymce.DOM.DOMUtils(t.getDoc(),{keep_values:true,url_converter:t.convertURL,url_converter_scope:t,hex_colors:s.force_hex_style_colors,class_filter:s.class_filter,update_styles:1});t.serializer=new tinymce.dom.Serializer({entity_encoding:s.entity_encoding,entities:s.entities,valid_elements:s.verify_html===false?'*[*]':s.valid_elements,extended_valid_elements:s.extended_valid_elements,valid_child_elements:s.valid_child_elements,invalid_elements:s.invalid_elements,fix_table_elements:s.fix_table_elements,fix_list_elements:s.fix_list_elements,fix_content_duplication:s.fix_content_duplication,convert_fonts_to_spans:s.convert_fonts_to_spans,font_size_classes:s.font_size_classes,font_size_style_values:s.font_size_style_values,apply_source_formatting:s.apply_source_formatting,remove_linebreaks:s.remove_linebreaks,dom:t.dom});t.selection=new tinymce.dom.Selection(t.dom,t.getWin(),t.serializer);t.forceBlocks=new tinymce.ForceBlocks(t,{forced_root_block:s.forced_root_block});t.editorCommands=new tinymce.EditorCommands(t);t.serializer.onPreProcess.add(function(se,o){return t.onPreProcess.dispatch(t,o,se);});t.serializer.onPostProcess.add(function(se,o){return t.onPostProcess.dispatch(t,o,se);});t.onPreInit.dispatch(t);if(!s.gecko_spellcheck)t.getBody().spellcheck=0;t._addEvents();t.controlManager.onPostRender.dispatch(t,t.controlManager);t.onPostRender.dispatch(t);if(s.directionality)t.getBody().dir=s.directionality;if(s.nowrap)t.getBody().style.whiteSpace="nowrap";if(s.auto_resize)t.onNodeChange.add(t.resizeToContent,t);if(s.handle_node_change_callback){t.onNodeChange.add(function(ed,cm,n){t.execCallback('handle_node_change_callback',t.id,n,-1,-1,true,t.selection.isCollapsed());});}if(s.save_callback){t.onSaveContent.add(function(ed,o){var h=t.execCallback('save_callback',t.id,o.content,t.getBody());if(h)o.content=h;});}if(s.onchange_callback){t.onChange.add(function(ed,l){t.execCallback('onchange_callback',t,l);});}if(s.convert_newlines_to_brs){t.onBeforeSetContent.add(function(ed,o){if(o.initial)o.content=o.content.replace(/\r?\n/g,'<br />');});}if(s.fix_nesting&&isIE){t.onBeforeSetContent.add(function(ed,o){o.content=t._fixNesting(o.content);});}if(s.preformatted){t.onPostProcess.add(function(ed,o){o.content=o.content.replace(/^\s*<pre.*?>/,'');o.content=o.content.replace(/<\/pre>\s*$/,'');if(o.set)o.content='<pre class="mceItemHidden">'+o.content+'</pre>';});}if(s.verify_css_classes){t.serializer.attribValueFilter=function(n,v){var s,cl;if(n=='class'){if(!t.classesRE){cl=t.dom.getClasses();if(cl.length>0){s='';each(cl,function(o){s+=(s?'|':'')+o['class'];});t.classesRE=new RegExp('('+s+')','gi');}}return!t.classesRE||/(\bmceItem\w+\b|\bmceTemp\w+\b)/g.test(v)||t.classesRE.test(v)?v:'';}return v;};}if(s.convert_fonts_to_spans)t._convertFonts();if(s.inline_styles)t._convertInlineElements();if(s.cleanup_callback){t.onBeforeSetContent.add(function(ed,o){o.content=t.execCallback('cleanup_callback','insert_to_editor',o.content,o);});t.onPreProcess.add(function(ed,o){if(o.set)t.execCallback('cleanup_callback','insert_to_editor_dom',o.node,o);if(o.get)t.execCallback('cleanup_callback','get_from_editor_dom',o.node,o);});t.onPostProcess.add(function(ed,o){if(o.set)o.content=t.execCallback('cleanup_callback','insert_to_editor',o.content,o);if(o.get)o.content=t.execCallback('cleanup_callback','get_from_editor',o.content,o);});}if(s.save_callback){t.onGetContent.add(function(ed,o){if(o.save)o.content=t.execCallback('save_callback',t.id,o.content,t.getBody());});}if(s.handle_event_callback){t.onEvent.add(function(ed,e,o){if(t.execCallback('handle_event_callback',e,ed,o)===false)Event.cancel(e);});}t.onSetContent.add(function(){t.addVisual(t.getBody());});if(s.padd_empty_editor){t.onPostProcess.add(function(ed,o){o.content=o.content.replace(/^<p>(&nbsp;|#160;|\s)<\/p>$/,'');});}if(isGecko){try{d.designMode='Off';d.designMode='On';}catch(ex){}}setTimeout(function(){if(t.removed)return;t.load({initial:true,format:(s.cleanup_on_startup?'html':'raw')});t.startContent=t.getContent({format:'raw'});t.undoManager.add({initial:true});t.initialized=true;t.onInit.dispatch(t);t.execCallback('setupcontent_callback',t.id,t.getBody(),t.getDoc());t.execCallback('init_instance_callback',t);t.focus(true);t.nodeChanged({initial:1});if(s.content_css){tinymce.each(s.content_css.split(','),function(u){t.dom.loadCSS(t.documentBaseURI.toAbsolute(u));});}if(s.auto_focus){setTimeout(function(){var ed=EditorManager.get(s.auto_focus);ed.selection.select(ed.getBody(),1);ed.selection.collapse(1);ed.getWin().focus();},100);}},1);e=null;},focus:function(sf){var oed,t=this;if(!sf){t.getWin().focus();}if(EditorManager.activeEditor!=t){if((oed=EditorManager.activeEditor)!=null)oed.onDeactivate.dispatch(oed,t);t.onActivate.dispatch(t,oed);}EditorManager._setActive(t);},execCallback:function(n){var t=this,f=t.settings[n],s;if(!f)return;if(t.callbackLookup&&(s=t.callbackLookup[n])){f=s.func;s=s.scope;}if(is(f,'string')){s=f.replace(/\.\w+$/,'');s=s?tinymce.resolve(s):0;f=tinymce.resolve(f);t.callbackLookup=t.callbackLookup||{};t.callbackLookup[n]={func:f,scope:s};}return f.apply(s||t,Array.prototype.slice.call(arguments,1));},translate:function(s){var c=this.settings.language,i18n=EditorManager.i18n;if(!s)return'';return i18n[c+'.'+s]||s.replace(/{\#([^}]+)\}/g,function(a,b){return i18n[c+'.'+b]||'{#'+b+'}';});},getLang:function(n,dv){return EditorManager.i18n[this.settings.language+'.'+n]||(is(dv)?dv:'{#'+n+'}');},getParam:function(n,dv){return is(this.settings[n])?this.settings[n]:dv;},nodeChanged:function(o){var t=this,s=t.selection,n=s.getNode()||this.getBody();this.onNodeChange.dispatch(t,o?o.controlManager||t.controlManager:t.controlManager,isIE&&n.ownerDocument!=t.getDoc()?this.getBody():n,s.isCollapsed(),o);},addButton:function(n,s){var t=this;t.buttons=t.buttons||{};t.buttons[n]=s;},addCommand:function(n,f,s){this.execCommands[n]={func:f,scope:s||this};},addQueryStateHandler:function(n,f,s){this.queryStateCommands[n]={func:f,scope:s||this};},addQueryValueHandler:function(n,f,s){this.queryValueCommands[n]={func:f,scope:s||this};},addShortcut:function(pa,desc,cmd_func,sc){var t=this,c;if(!t.settings.custom_shortcuts)return false;t.shortcuts=t.shortcuts||{};if(is(cmd_func,'string')){c=cmd_func;cmd_func=function(){t.execCommand(c,false,null);};}if(is(cmd_func,'object')){c=cmd_func;cmd_func=function(){t.execCommand(c[0],c[1],c[2]);};}each(pa.split(','),function(pa){var o={func:cmd_func,scope:sc||this,desc:desc,alt:false,ctrl:false,shift:false};each(pa.split('+'),function(v){switch(v){case'alt':case'ctrl':case'shift':o[v]=true;break;default:o.charCode=v.charCodeAt(0);o.keyCode=v.toUpperCase().charCodeAt(0);}});t.shortcuts[(o.ctrl?'ctrl':'')+','+(o.alt?'alt':'')+','+(o.shift?'shift':'')+','+o.keyCode]=o;});return true;},execCommand:function(cmd,ui,val,a){var t=this,s=0,o;if(!/^(mceAddUndoLevel|mceEndUndoLevel|mceBeginUndoLevel|mceRepaint|SelectAll)$/.test(cmd)&&(!a||!a.skip_focus))t.focus();o={};t.onBeforeExecCommand.dispatch(t,cmd,ui,val,o);if(o.terminate)return false;if(t.execCallback('execcommand_callback',t.id,t.selection.getNode(),cmd,ui,val)){t.onExecCommand.dispatch(t,cmd,ui,val);return true;}if(o=t.execCommands[cmd]){s=o.func.call(o.scope,ui,val);t.onExecCommand.dispatch(t,cmd,ui,val);return s;}each(t.plugins,function(p){if(p.execCommand&&p.execCommand(cmd,ui,val)){t.onExecCommand.dispatch(t,cmd,ui,val);s=1;return false;}});if(s)return true;if(t.theme.execCommand&&t.theme.execCommand(cmd,ui,val)){t.onExecCommand.dispatch(t,cmd,ui,val);return true;}if(t.editorCommands.execCommand(cmd,ui,val)){t.onExecCommand.dispatch(t,cmd,ui,val);return true;}t.getDoc().execCommand(cmd,ui,val);t.onExecCommand.dispatch(t,cmd,ui,val);},queryCommandState:function(c){var t=this,o;if(t._isHidden())return;if(o=t.queryStateCommands[c])return o.func.call(o.scope);o=t.editorCommands.queryCommandState(c);if(o!==-1)return o;return this.getDoc().queryCommandState(c);},queryCommandValue:function(c){var t=this,o;if(t._isHidden())return;if(o=t.queryValueCommands[c])return o.func.call(o.scope);o=t.editorCommands.queryCommandValue(c);if(is(o))return o;return this.getDoc().queryCommandValue(c);},show:function(){var t=this;DOM.show(t.getContainer());DOM.hide(t.id);t.load();},hide:function(){var t=this,s=t.settings,d=t.getDoc();if(isIE&&d)d.execCommand('SelectAll');DOM.hide(t.getContainer());DOM.setStyle(s.id,'display',t.orgDisplay);t.save();},isHidden:function(){return!DOM.isHidden(this.id);},setProgressState:function(b,ti,o){this.onSetProgressState.dispatch(this,b,ti,o);return b;},remove:function(){var t=this;t.removed=1;t.hide();DOM.remove(t.getContainer());t.execCallback('remove_instance_callback',t);t.onRemove.dispatch(t);EditorManager.remove(t);},resizeToContent:function(){var t=this;DOM.setStyle(t.id+"_ifr",'height',t.getBody().scrollHeight);},load:function(o){var t=this,e=t.getElement(),h;o=o||{};o.load=true;h=t.setContent(is(e.value)?e.value:e.innerHTML,o);o.element=e;if(!o.no_events)t.onLoadContent.dispatch(t,o);o.element=e=null;return h;},save:function(o){var t=this,e=t.getElement(),h,f;if(!t.initialized)return;o=o||{};o.save=true;o.element=e;h=o.content=t.getContent(o);if(!o.no_events)t.onSaveContent.dispatch(t,o);h=o.content;if(!/TEXTAREA|INPUT/i.test(e.nodeName)){e.innerHTML=h;if(f=DOM.getParent(t.id,'form')){each(f.elements,function(e){if(e.name==t.id){e.value=h;return false;}});}}else e.value=h;o.element=e=null;return h;},setContent:function(h,o){var t=this;o=o||{};o.format=o.format||'html';o.set=true;o.content=h;if(!o.no_events)t.onBeforeSetContent.dispatch(t,o);if(!tinymce.isIE&&(h.length===0||/^\s+$/.test(h))){o.content=t.dom.setHTML(t.getBody(),'<br mce_bogus="1" />',1);o.format='raw';}o.content=t.dom.setHTML(t.getBody(),tinymce.trim(o.content));if(o.format!='raw'&&t.settings.cleanup){o.getInner=true;o.content=t.dom.setHTML(t.getBody(),t.serializer.serialize(t.getBody(),o));}if(!o.no_events)t.onSetContent.dispatch(t,o);return o.content;},getContent:function(o){var t=this,h;o=o||{};o.format=o.format||'html';o.get=true;if(!o.no_events)t.onBeforeGetContent.dispatch(t,o);if(o.format!='raw'&&t.settings.cleanup){o.getInner=true;h=t.serializer.serialize(t.getBody(),o);}else h=t.getBody().innerHTML;h=h.replace(/^\s*|\s*$/g,'');o={content:h};t.onGetContent.dispatch(t,o);return o.content;},isDirty:function(){var t=this;return tinymce.trim(t.startContent)!=tinymce.trim(t.getContent({format:'raw',no_events:1}))&&!t.isNotDirty;},getContainer:function(){var t=this;if(!t.container)t.container=DOM.get(t.editorContainer||t.id+'_parent');return t.container;},getContentAreaContainer:function(){return this.contentAreaContainer;},getElement:function(){return DOM.get(this.settings.content_element||this.id);},getWin:function(){var t=this,e;if(!t.contentWindow){e=DOM.get(t.id+"_ifr");if(e)t.contentWindow=e.contentWindow;}return t.contentWindow;},getDoc:function(){var t=this,w;if(!t.contentDocument){w=this.getWin();if(w)t.contentDocument=w.document;}return t.contentDocument;},getBody:function(){return this.bodyElement||this.getDoc().body;},convertURL:function(u,n,e){var t=this,s=t.settings;if(s.urlconverter_callback)return t.execCallback('urlconverter_callback',u,e,true,n);if(!s.convert_urls||(e&&e.nodeName=='LINK'))return u;if(s.relative_urls)return t.documentBaseURI.toRelative(u);u=t.documentBaseURI.toAbsolute(u,s.remove_script_host);return u;},addVisual:function(e){var t=this,s=t.settings;e=e||t.getBody();if(!is(t.hasVisual))t.hasVisual=s.visual;each(t.dom.select('table,a',e),function(e){var v;switch(e.nodeName){case'TABLE':v=t.dom.getAttrib(e,'border');if(!v||v=='0'){if(t.hasVisual)t.dom.addClass(e,s.visual_table_class);else t.dom.removeClass(e,s.visual_table_class);}return;case'A':v=t.dom.getAttrib(e,'name');if(v){if(t.hasVisual)t.dom.addClass(e,'mceItemAnchor');else t.dom.removeClass(e,'mceItemAnchor');}return;}});t.onVisualAid.dispatch(t,e,t.hasVisual);},_addEvents:function(){var t=this,i,s=t.settings,lo={mouseup:'onMouseUp',mousedown:'onMouseDown',click:'onClick',keyup:'onKeyUp',keydown:'onKeyDown',keypress:'onKeyPress',submit:'onSubmit',reset:'onReset',contextmenu:'onContextMenu',dblclick:'onDblClick',paste:'onPaste'};function eventHandler(e,o){var ty=e.type;if(t.removed)return;if(t.onEvent.dispatch(t,e,o)!==false){t[lo[e.fakeType||e.type]].dispatch(t,e,o);}};each(lo,function(v,k){switch(k){case'contextmenu':if(tinymce.isOpera){Event.add(t.getDoc(),'mousedown',function(e){if(e.ctrlKey){e.fakeType='contextmenu';eventHandler(e);}});}else Event.add(t.getDoc(),k,eventHandler);break;case'paste':Event.add(t.getBody(),k,function(e){var tx,h,el,r;if(e.clipboardData)tx=e.clipboardData.getData('text/plain');else if(tinymce.isIE)tx=t.getWin().clipboardData.getData('Text');eventHandler(e,{text:tx,html:h});});break;case'submit':case'reset':Event.add(t.getElement().form||DOM.getParent(t.id,'form'),k,eventHandler);break;default:Event.add(s.content_editable?t.getBody():t.getDoc(),k,eventHandler);}});Event.add(s.content_editable?t.getBody():(isGecko?t.getDoc():t.getWin()),'focus',function(e){t.focus(true);});if(tinymce.isGecko){Event.add(t.getDoc(),'DOMNodeInserted',function(e){var v;e=e.target;if(e.nodeType===1&&e.nodeName==='IMG'&&(v=e.getAttribute('mce_src')))e.src=t.documentBaseURI.toAbsolute(v);});}if(isGecko){function setOpts(){var t=this,d=t.getDoc(),s=t.settings;if(isGecko){if(t._isHidden()){try{d.designMode='On';}catch(ex){}}try{d.execCommand("styleWithCSS",0,false);}catch(ex){if(!t._isHidden())d.execCommand("useCSS",0,true);}if(!s.table_inline_editing)try{d.execCommand('enableInlineTableEditing',false,false);}catch(ex){}if(!s.object_resizing)try{d.execCommand('enableObjectResizing',false,false);}catch(ex){}}};t.onBeforeExecCommand.add(setOpts);t.onMouseDown.add(setOpts);}t.onMouseUp.add(t.nodeChanged);t.onClick.add(t.nodeChanged);t.onKeyUp.add(function(ed,e){if((e.keyCode>=33&&e.keyCode<=36)||(e.keyCode>=37&&e.keyCode<=40)||e.keyCode==13||e.keyCode==45||e.keyCode==46||e.keyCode==8||e.ctrlKey)t.nodeChanged();});t.onReset.add(function(){t.setContent(t.startContent,{format:'raw'});});if(t.getParam('tab_focus')){function tabCancel(ed,e){if(e.keyCode===9)return Event.cancel(e);};function tabHandler(ed,e){var v,f,el;function find(d){f=DOM.getParent(ed.id,'form'),el=f.elements;if(f){each(f.elements,function(e,i){if(e.id==ed.id){i=i+d;if(i<0||i>el.length)return;el=el[i];}});}return el;};if(e.keyCode===9){v=ed.getParam('tab_focus').split(',');if(v.length==1){v[1]=v[0];v[0]=':prev';}if(e.shiftKey){if(v[0]==':prev')el=find(-1);else el=DOM.get(v[0]);}else{if(v[1]==':next')el=find(1);else el=DOM.get(v[1]);}if(el){if(ed=EditorManager.get(el.id||el.name))ed.focus();else window.setTimeout(function(){window.focus();el.focus();},10);return Event.cancel(e);}}};t.onKeyUp.add(tabCancel);if(isGecko){t.onKeyPress.add(tabHandler);t.onKeyDown.add(tabCancel);}else t.onKeyDown.add(tabHandler);}if(s.custom_shortcuts){if(s.custom_undo_redo_keyboard_shortcuts){t.addShortcut('ctrl+z',t.getLang('undo_desc'),'Undo');t.addShortcut('ctrl+y',t.getLang('redo_desc'),'Redo');}if(isGecko){t.addShortcut('ctrl+b',t.getLang('bold_desc'),'Bold');t.addShortcut('ctrl+i',t.getLang('italic_desc'),'Italic');t.addShortcut('ctrl+u',t.getLang('underline_desc'),'Underline');}for(i=1;i<=6;i++)t.addShortcut('ctrl+'+i,'',['FormatBlock',false,'<h'+i+'>']);t.addShortcut('ctrl+7','',['FormatBlock',false,'<p>']);t.addShortcut('ctrl+8','',['FormatBlock',false,'<div>']);t.addShortcut('ctrl+9','',['FormatBlock',false,'<address>']);function find(e){var v=null;if(!e.altKey&&!e.ctrlKey&&!e.metaKey)return v;each(t.shortcuts,function(o){if(o.ctrl!=e.ctrlKey&&(!tinymce.isMac||o.ctrl==e.metaKey))return;if(o.alt!=e.altKey)return;if(o.shift!=e.shiftKey)return;if(e.keyCode==o.keyCode||(e.charCode&&e.charCode==o.charCode)){v=o;return false;}});return v;};t.onKeyUp.add(function(ed,e){var o=find(e);if(o)return Event.cancel(e);});t.onKeyPress.add(function(ed,e){var o=find(e);if(o)return Event.cancel(e);});t.onKeyDown.add(function(ed,e){var o=find(e);if(o){o.func.call(o.scope);return Event.cancel(e);}});}if(tinymce.isIE){Event.add(t.getDoc(),'controlselect',function(e){var re=t.resizeInfo,cb;e=e.target;if(re)Event.remove(re.node,re.ev,re.cb);if(!t.dom.hasClass(e,'mceItemNoResize')){ev='resizeend';cb=Event.add(e,ev,function(e){var v;e=e.target;if(v=t.dom.getStyle(e,'width')){t.dom.setAttrib(e,'width',v.replace(/[^0-9%]+/g,''));t.dom.setStyle(e,'width','');}if(v=t.dom.getStyle(e,'height')){t.dom.setAttrib(e,'height',v.replace(/[^0-9%]+/g,''));t.dom.setStyle(e,'height','');}});}else{ev='resizestart';cb=Event.add(e,'resizestart',Event.cancel,Event);}re=t.resizeInfo={node:e,ev:ev,cb:cb};});t.onKeyDown.add(function(ed,e){switch(e.keyCode){case 8:if(t.selection.getRng().item){t.selection.getRng().item(0).removeNode();return Event.cancel(e);}}});}if(tinymce.isOpera){t.onClick.add(function(ed,e){Event.prevent(e);});}if(s.custom_undo_redo){function addUndo(){t.undoManager.typing=0;t.undoManager.add();};if(tinymce.isIE){Event.add(t.getWin(),'blur',function(e){var n;if(t.selection){n=t.selection.getNode();if(!t.removed&&n.ownerDocument&&n.ownerDocument!=t.getDoc())addUndo();}});}else{Event.add(t.getDoc(),'blur',function(){if(t.selection&&!t.removed)addUndo();});}t.onMouseDown.add(addUndo);t.onKeyUp.add(function(ed,e){if((e.keyCode>=33&&e.keyCode<=36)||(e.keyCode>=37&&e.keyCode<=40)||e.keyCode==13||e.keyCode==45||e.ctrlKey){t.undoManager.typing=0;t.undoManager.add();}});t.onKeyDown.add(function(ed,e){if((e.keyCode>=33&&e.keyCode<=36)||(e.keyCode>=37&&e.keyCode<=40)||e.keyCode==13||e.keyCode==45){if(t.undoManager.typing){t.undoManager.add();t.undoManager.typing=0;}return;}if(!t.undoManager.typing){t.undoManager.add();t.undoManager.typing=1;}});}},_destroy:function(){var t=this;if(t.formElement){t.formElement.submit=t.formElement._mceOldSubmit;t.formElement._mceOldSubmit=null;}t.contentAreaContainer=t.formElement=t.container=t.contentDocument=t.contentWindow=null;if(t.selection)t.selection=t.selection.win=t.selection.dom=t.selection.dom.doc=null;t.destroyed=1;},_convertInlineElements:function(){var t=this,s=t.settings,dom=t.dom;function convert(ed,o){if(!s.inline_styles)return;if(o.get){each(t.dom.select('table,u,strike',o.node),function(n){switch(n.nodeName){case'TABLE':if(v=dom.getAttrib(n,'height')){dom.setStyle(n,'height',v);dom.setAttrib(n,'height','');}break;case'U':dom.replace(dom.create('span',{style:'text-decoration: underline;'}),n,1);break;case'STRIKE':dom.replace(dom.create('span',{style:'text-decoration: line-through;'}),n,1);break;}});}else if(o.set){each(t.dom.select('table,span',o.node),function(n){if(n.nodeName=='TABLE'){if(v=dom.getStyle(n,'height'))dom.setAttrib(n,'height',v.replace(/[^0-9%]+/g,''));}else{if(n.style.textDecoration=='underline')dom.replace(dom.create('u'),n,1);else if(n.style.textDecoration=='line-through')dom.replace(dom.create('strike'),n,1);}});}};t.onPreProcess.add(convert);if(!s.cleanup_on_startup){t.onInit.add(function(){convert(t,{node:t.getBody(),set:1});});}},_convertFonts:function(){var t=this,s=t.settings,dom=t.dom,sl,cl,fz,fzn,v,i;fz=[8,10,12,14,18,24,36];fzn=['xx-small','x-small','small','medium','large','x-large','xx-large'];if(sl=s.font_size_style_values)sl=sl.split(',');if(cl=s.font_size_classes)cl=cl.split(',');t.onPreProcess.add(function(ed,o){if(!s.inline_styles)return;if(o.set){if(tinymce.isWebKit)return;each(t.dom.select('span',o.node),function(n){var f=dom.create('font',{color:dom.toHex(dom.getStyle(n,'color')),face:dom.getStyle(n,'fontFamily')});if(sl){i=inArray(sl,dom.getStyle(n,'fontSize'));if(i!=-1)dom.setAttrib(f,'size',''+(i+1||1));}else if(cl){i=inArray(cl,dom.getAttrib(n,'class'));v=dom.getStyle(n,'fontSize');if(i==-1&&v.indexOf('pt')>0)i=inArray(fz,parseInt(v));if(i==-1)i=inArray(fzn,v);if(i!=-1)dom.setAttrib(f,'size',''+(i+1||1));}if(f.color||f.face||f.size)dom.replace(f,n,1);});}else if(o.get){each(t.dom.select('font',o.node),function(n){var sp=dom.create('span',{style:{fontFamily:dom.getAttrib(n,'face'),color:dom.getAttrib(n,'color'),backgroundColor:n.style.backgroundColor}});if(n.size){if(sl)dom.setStyle(sp,'fontSize',sl[parseInt(n.size)-1]);else dom.setAttrib(sp,'class',cl[parseInt(n.size)-1]);}dom.replace(sp,n,1);});}});},_isHidden:function(){var s;if(!isGecko)return 0;s=this.selection.getSel();return(!s||!s.rangeCount||s.rangeCount==0);},_fixNesting:function(s){var d=[],i;s=s.replace(/<(\/)?([^\s>]+)[^>]*?>/g,function(a,b,c){var e;if(b==='/'){if(!d.length)return'';if(c!==d[d.length-1].tag){for(i=d.length-1;i>=0;i--){if(d[i].tag===c){d[i].close=1;break;}}return'';}else{d.pop();if(d.length&&d[d.length-1].close){a=a+'</'+d[d.length-1].tag+'>';d.pop();}}}else{if(/^(br|hr|input|meta|img|link|param)$/i.test(c))return a;if(/\/>$/.test(a))return a;d.push({tag:c});}return a;});for(i=d.length-1;i>=0;i--)s+='</'+d[i].tag+'>';return s;}});})();(function(){var each=tinymce.each,isIE=tinymce.isIE,isGecko=tinymce.isGecko,isOpera=tinymce.isOpera,isWebKit=tinymce.isWebKit;tinymce.create('tinymce.EditorCommands',{EditorCommands:function(ed){this.editor=ed;},execCommand:function(cmd,ui,val){var t=this,ed=t.editor,f;switch(cmd){case'Cut':case'Copy':case'Paste':try{ed.getDoc().execCommand(cmd,ui,val);}catch(ex){if(isGecko){ed.windowManager.confirm(ed.getLang('clipboard_msg'),function(s){if(s)window.open('http://www.mozilla.org/editor/midasdemo/securityprefs.html','mceExternal');});}else ed.windowManager.alert(ed.getLang('clipboard_no_support'));}return true;case'mceResetDesignMode':case'mceBeginUndoLevel':return true;case'unlink':t.UnLink();return true;case'JustifyLeft':case'JustifyCenter':case'JustifyRight':case'JustifyFull':t.mceJustify(cmd,cmd.substring(7).toLowerCase());return true;case'mceEndUndoLevel':case'mceAddUndoLevel':ed.undoManager.add();return true;default:f=this[cmd];if(f){f.call(this,ui,val);return true;}}return false;},Indent:function(){var ed=this.editor,d=ed.dom,s=ed.selection,e,iv,iu;iv=ed.settings.indentation;iu=/[a-z%]+$/i.exec(iv);iv=parseInt(iv);if(ed.settings.inline_styles&&(!this.queryStateInsertUnorderedList()&&!this.queryStateInsertOrderedList())){each(this._getSelectedBlocks(),function(e){d.setStyle(e,'paddingLeft',(parseInt(e.style.paddingLeft||0)+iv)+iu);});return;}ed.getDoc().execCommand('Indent',false,null);if(isIE){d.getParent(s.getNode(),function(n){if(n.nodeName=='BLOCKQUOTE'){n.dir=n.style.cssText='';}});}},Outdent:function(){var ed=this.editor,d=ed.dom,s=ed.selection,e,v,iv,iu;iv=ed.settings.indentation;iu=/[a-z%]+$/i.exec(iv);iv=parseInt(iv);if(ed.settings.inline_styles&&(!this.queryStateInsertUnorderedList()&&!this.queryStateInsertOrderedList())){each(this._getSelectedBlocks(),function(e){v=Math.max(0,parseInt(e.style.paddingLeft||0)-iv);d.setStyle(e,'paddingLeft',v?v+iu:'');});return;}ed.getDoc().execCommand('Outdent',false,null);},mceSetAttribute:function(u,v){var ed=this.editor,d=ed.dom,e;if(e=d.getParent(ed.selection.getNode(),d.isBlock))d.setAttrib(e,v.name,v.value);},mceSetContent:function(u,v){this.editor.setContent(v);},mceToggleVisualAid:function(){var ed=this.editor;ed.hasVisual=!ed.hasVisual;ed.addVisual();},mceReplaceContent:function(u,v){var s=this.editor.selection;s.setContent(v.replace(/\{\$selection\}/g,s.getContent({format:'text'})));},mceInsertLink:function(u,v){var ed=this.editor,e=ed.dom.getParent(ed.selection.getNode(),'A');if(tinymce.is(v,'string'))v={href:v};function set(e){each(v,function(v,k){ed.dom.setAttrib(e,k,v);});};if(!e){ed.execCommand('CreateLink',false,'javascript:mctmp(0);');each(ed.dom.select('a'),function(e){if(e.href=='javascript:mctmp(0);')set(e);});}else{if(v.href)set(e);else ed.dom.remove(e,1);}},UnLink:function(){var ed=this.editor,s=ed.selection;if(s.isCollapsed())s.select(s.getNode());ed.getDoc().execCommand('unlink',false,null);s.collapse(0);},FontName:function(u,v){var t=this,ed=t.editor,s=ed.selection,e;if(!v){if(s.isCollapsed())s.select(s.getNode());t.RemoveFormat();}else ed.getDoc().execCommand('FontName',false,v);},queryCommandValue:function(c){var f=this['queryValue'+c];if(f)return f.call(this,c);return false;},queryCommandState:function(cmd){var f;switch(cmd){case'JustifyLeft':case'JustifyCenter':case'JustifyRight':case'JustifyFull':return this.queryStateJustify(cmd,cmd.substring(7).toLowerCase());default:if(f=this['queryState'+cmd])return f.call(this,cmd);}return-1;},queryValueFontSize:function(){var ed=this.editor,v=0,p;if(isOpera||isWebKit){if(p=ed.dom.getParent(ed.selection.getNode(),'FONT'))v=p.size;return v;}return ed.getDoc().queryCommandValue('FontSize');},queryValueFontName:function(){var ed=this.editor,v=0,p;if(p=ed.dom.getParent(ed.selection.getNode(),'FONT'))v=p.face;if(!v)v=ed.getDoc().queryCommandValue('FontName');return v;},mceJustify:function(c,v){var ed=this.editor,se=ed.selection,n=se.getNode(),nn=n.nodeName,bl,nb,dom=ed.dom,rm;if(ed.settings.inline_styles&&this.queryStateJustify(c,v))rm=1;bl=dom.getParent(n,ed.dom.isBlock);if(nn=='IMG'){if(v=='full')return;if(rm){dom.setStyle(n,'float','');this.mceRepaint();return;}if(v=='center'){if(!bl||bl.childNodes.length>1){nb=dom.create('p');nb.appendChild(n.cloneNode(false));if(bl)dom.insertAfter(nb,bl);else dom.insertAfter(nb,n);dom.remove(n);n=nb.firstChild;bl=nb;}dom.setStyle(bl,'textAlign',v);dom.setStyle(n,'float','');}else dom.setStyle(n,'float',v);this.mceRepaint();return;}if(ed.settings.inline_styles&&ed.settings.forced_root_block){if(rm)v='';each(this._getSelectedBlocks(dom.getParent(se.getStart(),dom.isBlock),dom.getParent(se.getEnd(),dom.isBlock)),function(e){dom.setAttrib(e,'align','');dom.setStyle(e,'textAlign',v=='full'?'justify':v);});return;}else if(!rm)ed.getDoc().execCommand(c,false,null);if(ed.settings.inline_styles){if(rm){dom.getParent(ed.selection.getNode(),function(n){if(n.style&&n.style.textAlign)dom.setStyle(n,'textAlign','');});return;}each(dom.select('*'),function(n){var v=n.align;if(v){if(v=='full')v='justify';dom.setStyle(n,'textAlign',v);dom.setAttrib(n,'align','');}});}},mceSetCSSClass:function(u,v){this.mceSetStyleInfo(0,{command:'setattrib',name:'class',value:v});},getSelectedElement:function(){var t=this,ed=t.editor,dom=ed.dom,se=ed.selection,r=se.getRng(),r1,r2,sc,ec,so,eo,e,sp,ep,re;if(se.isCollapsed()||r.item)return se.getNode();re=ed.settings.merge_styles_invalid_parents;if(tinymce.is(re,'string'))re=new RegExp(re,'i');if(isIE){r1=r.duplicate();r1.collapse(true);sc=r1.parentElement();r2=r.duplicate();r2.collapse(false);ec=r2.parentElement();if(sc!=ec){r1.move('character',1);sc=r1.parentElement();}if(sc==ec){r1=r.duplicate();r1.moveToElementText(sc);if(r1.compareEndPoints('StartToStart',r)==0&&r1.compareEndPoints('EndToEnd',r)==0)return re&&re.test(sc.nodeName)?null:sc;}}else{function getParent(n){return dom.getParent(n,function(n){return n.nodeType==1;});};sc=r.startContainer;ec=r.endContainer;so=r.startOffset;eo=r.endOffset;if(!r.collapsed){if(sc==ec){if(so-eo<2){if(sc.hasChildNodes()){sp=sc.childNodes[so];return re&&re.test(sp.nodeName)?null:sp;}}}}if(sc.nodeType!=3||ec.nodeType!=3)return null;if(so==0){sp=getParent(sc);if(sp&&sp.firstChild!=sc)sp=null;}if(so==sc.nodeValue.length){e=sc.nextSibling;if(e&&e.nodeType==1)sp=sc.nextSibling;}if(eo==0){e=ec.previousSibling;if(e&&e.nodeType==1)ep=e;}if(eo==ec.nodeValue.length){ep=getParent(ec);if(ep&&ep.lastChild!=ec)ep=null;}if(sp==ep)return re&&sp&&re.test(sp.nodeName)?null:sp;}return null;},InsertHorizontalRule:function(){if(isGecko||isIE)this.editor.selection.setContent('<hr />');else this.editor.getDoc().execCommand('InsertHorizontalRule',false,'');},RemoveFormat:function(){var t=this,ed=t.editor,s=ed.selection,b;if(isWebKit)s.setContent(s.getContent({format:'raw'}).replace(/(<(span|b|i|strong|em|strike) [^>]+>|<(span|b|i|strong|em|strike)>|<\/(span|b|i|strong|em|strike)>|)/g,''),{format:'raw'});else ed.getDoc().execCommand('RemoveFormat',false,null);t.mceSetStyleInfo(0,{command:'removeformat'});ed.addVisual();},mceSetStyleInfo:function(u,v){var t=this,ed=t.editor,d=ed.getDoc(),dom=ed.dom,e,b,s=ed.selection,nn=v.wrapper||'span',b=s.getBookmark(),re;function set(n,e){if(n.nodeType==1){switch(v.command){case'setattrib':return dom.setAttrib(n,v.name,v.value);case'setstyle':return dom.setStyle(n,v.name,v.value);case'removeformat':return dom.setAttrib(n,'class','');}}};re=ed.settings.merge_styles_invalid_parents;if(tinymce.is(re,'string'))re=new RegExp(re,'i');if(e=t.getSelectedElement())set(e,1);else{d.execCommand('FontName',false,'__');each(isWebKit?dom.select('span'):dom.select('font'),function(n){var sp,e;if(dom.getAttrib(n,'face')=='__'||n.style.fontFamily==='__'){sp=dom.create(nn,{mce_new:'1'});set(sp);each(n.childNodes,function(n){sp.appendChild(n.cloneNode(true));});dom.replace(sp,n);}});}each(dom.select(nn).reverse(),function(n){var p=n.parentNode;dom.setAttrib(n,'mce_new','');if(!dom.getAttrib(n,'mce_new')){p=dom.getParent(n,function(n){return n.nodeType==1&&dom.getAttrib(n,'mce_new');});if(p)dom.remove(n,1);}});each(dom.select(nn).reverse(),function(n){var p=n.parentNode;if(!p)return;if(p.nodeName==nn.toUpperCase()&&p.childNodes.length==1)return dom.remove(p,1);if(n.nodeType==1&&(!re||!re.test(p.nodeName))&&p.childNodes.length==1){set(p);dom.setAttrib(n,'class','');}});each(dom.select(nn).reverse(),function(n){if(!dom.getAttrib(n,'class')&&!dom.getAttrib(n,'style'))return dom.remove(n,1);});s.moveToBookmark(b);},queryStateJustify:function(c,v){var ed=this.editor,n=ed.selection.getNode(),dom=ed.dom;if(n&&n.nodeName=='IMG')return dom.getStyle(n,'float')==v;n=dom.getParent(ed.selection.getStart(),function(n){return n.nodeType==1&&n.style.textAlign;});if(v=='full')v='justify';if(ed.settings.inline_styles)return(n&&n.style.textAlign==v);return ed.getDoc().queryCommandState(c);},HiliteColor:function(ui,val){var t=this,ed=t.editor,d=ed.getDoc();function set(s){if(!isGecko)return;try{d.execCommand("styleWithCSS",0,s);}catch(ex){d.execCommand("useCSS",0,!s);}};if(isGecko||isOpera){set(true);d.execCommand('hilitecolor',false,val);set(false);}else d.execCommand('BackColor',false,val);},Undo:function(){var ed=this.editor;if(ed.settings.custom_undo_redo){ed.undoManager.undo();ed.nodeChanged();}else ed.getDoc().execCommand('Undo',false,null);},Redo:function(){var ed=this.editor;if(ed.settings.custom_undo_redo){ed.undoManager.redo();ed.nodeChanged();}else ed.getDoc().execCommand('Redo',false,null);},FormatBlock:function(ui,val){var t=this,ed=t.editor;val=ed.settings.forced_root_block?(val||'<p>'):val;t.mceRemoveNode();if(val.indexOf('<')==-1)val='<'+val+'>';if(tinymce.isGecko)val=val.replace(/<(div|blockquote|code|dt|dd|dl|samp)>/gi,'$1');ed.getDoc().execCommand('FormatBlock',false,val);},mceCleanup:function(){var ed=this.editor,s=ed.selection,b=s.getBookmark();ed.setContent(ed.getContent());s.moveToBookmark(b);},mceRemoveNode:function(ui,val){var ed=this.editor,s=ed.selection,b,n=val||s.getNode();if(n==ed.getBody())return;b=s.getBookmark();ed.dom.remove(n,1);s.moveToBookmark(b);ed.nodeChanged();},mceSelectNodeDepth:function(ui,val){var ed=this.editor,s=ed.selection,c=0;ed.dom.getParent(s.getNode(),function(n){if(n.nodeType==1&&c++==val){s.select(n);ed.nodeChanged();return false;}},ed.getBody());},mceSelectNode:function(u,v){this.editor.selection.select(v);},mceInsertContent:function(ui,val){this.editor.selection.setContent(val);},mceInsertRawHTML:function(ui,val){var ed=this.editor;ed.execCommand('mceInsertContent',false,'tiny_mce_marker');ed.setContent(ed.getContent().replace(/tiny_mce_marker/g,val));},mceRepaint:function(){var s,b,e=this.editor;if(tinymce.isGecko){try{s=e.selection;b=s.getBookmark(true);if(s.getSel())s.getSel().selectAllChildren(e.getBody());s.collapse(true);s.moveToBookmark(b);}catch(ex){}}},queryStateUnderline:function(){var ed=this.editor,n;if(n&&n.nodeName=='A')return false;return ed.getDoc().queryCommandState('Underline');},queryStateOutdent:function(){var ed=this.editor,n;if(ed.settings.inline_styles){if((n=ed.dom.getParent(ed.selection.getStart(),ed.dom.isBlock))&&parseInt(n.style.paddingLeft)>0)return true;if((n=ed.dom.getParent(ed.selection.getEnd(),ed.dom.isBlock))&&parseInt(n.style.paddingLeft)>0)return true;}else return!!ed.dom.getParent(ed.selection.getNode(),'BLOCKQUOTE');return this.queryStateInsertUnorderedList()||this.queryStateInsertOrderedList();},queryStateInsertUnorderedList:function(){return this.editor.dom.getParent(this.editor.selection.getNode(),'UL');},queryStateInsertOrderedList:function(){return this.editor.dom.getParent(this.editor.selection.getNode(),'OL');},queryStatemceBlockQuote:function(){return!!this.editor.dom.getParent(this.editor.selection.getStart(),function(n){return n.nodeName==='BLOCKQUOTE';});},mceBlockQuote:function(){var t=this,s=t.editor.selection,b=s.getBookmark(),bq,dom=t.editor.dom;function findBQ(e){return dom.getParent(e,function(n){return n.nodeName==='BLOCKQUOTE';});};if(findBQ(s.getStart())){each(t._getSelectedBlocks(findBQ(s.getStart()),findBQ(s.getEnd())),function(e){if(e.nodeName=='BLOCKQUOTE')dom.remove(e,1);});t.editor.selection.moveToBookmark(b);return;}each(t._getSelectedBlocks(findBQ(s.getStart()),findBQ(s.getEnd())),function(e){var n;if(e.nodeName=='BLOCKQUOTE'&&!bq){bq=e;return;}if(!bq){bq=dom.create('blockquote');e.parentNode.insertBefore(bq,e);}if(e.nodeName=='BLOCKQUOTE'&&bq){n=e.firstChild;while(n){bq.appendChild(n.cloneNode(true));n=n.nextSibling;}dom.remove(e);return;}bq.appendChild(dom.remove(e));});t.editor.selection.moveToBookmark(b);},_getSelectedBlocks:function(st,en){var ed=this.editor,dom=ed.dom,s=ed.selection,sb,eb,n,bl=[];sb=dom.getParent(st||s.getStart(),dom.isBlock);eb=dom.getParent(en||s.getEnd(),dom.isBlock);if(sb)bl.push(sb);if(sb&&eb&&sb!=eb){n=sb;while((n=n.nextSibling)&&n!=eb){if(dom.isBlock(n))bl.push(n);}}if(eb&&sb!=eb)bl.push(eb);return bl;}});})();tinymce.create('tinymce.UndoManager',{index:0,data:null,typing:0,UndoManager:function(ed){var t=this,Dispatcher=tinymce.util.Dispatcher;t.editor=ed;t.data=[];t.onAdd=new Dispatcher(this);t.onUndo=new Dispatcher(this);t.onRedo=new Dispatcher(this);},add:function(l){var t=this,i,ed=t.editor,b,s=ed.settings,la;l=l||{};l.content=l.content||ed.getContent({format:'raw',no_events:1});l.content=l.content.replace(/^\s*|\s*$/g,'');la=t.data[t.index>0?t.index-1:0];if(!l.initial&&la&&l.content==la.content)return null;if(s.custom_undo_redo_levels){if(t.data.length>s.custom_undo_redo_levels){for(i=0;i<t.data.length-1;i++)t.data[i]=t.data[i+1];t.data.length--;t.index=t.data.length;}}if(s.custom_undo_redo_restore_selection)l.bookmark=b=l.bookmark||ed.selection.getBookmark();if(t.index<t.data.length&&t.data[t.index].initial)t.index++;t.data.length=t.index+1;t.data[t.index++]=l;if(l.initial)t.index=0;if(t.data.length==2&&t.data[0].initial)t.data[0].bookmark=b;t.onAdd.dispatch(t,l);ed.isNotDirty=0;return l;},undo:function(){var t=this,ed=t.editor,l=l,i;if(t.typing){t.add();t.typing=0;}if(t.index>0){if(t.index==t.data.length&&t.index>1){i=t.index;t.typing=0;if(!t.add())t.index=i;--t.index;}l=t.data[--t.index];ed.setContent(l.content,{format:'raw'});ed.selection.moveToBookmark(l.bookmark);t.onUndo.dispatch(t,l);}return l;},redo:function(){var t=this,ed=t.editor,l=null;if(t.index<t.data.length-1){l=t.data[++t.index];ed.setContent(l.content,{format:'raw'});ed.selection.moveToBookmark(l.bookmark);t.onRedo.dispatch(t,l);}return l;},clear:function(){var t=this;t.data=[];t.index=0;t.typing=0;t.add({initial:true});},hasUndo:function(){return this.index!=0||this.typing;},hasRedo:function(){return this.index<this.data.length-1;}});(function(){var Event,isIE,isGecko,isOpera,each,extend;Event=tinymce.dom.Event;isIE=tinymce.isIE;isGecko=tinymce.isGecko;isOpera=tinymce.isOpera;each=tinymce.each;extend=tinymce.extend;tinymce.create('tinymce.ForceBlocks',{ForceBlocks:function(ed){var t=this,s;t.editor=ed;t.dom=ed.dom;t.settings=s=extend({element:'P',forced_root_block:'p',force_p_newlines:true},ed.settings);ed.onPreInit.add(t.setup,t);function padd(ed,o){if(isOpera)o.content=o.content.replace(/(\u00a0|&#160;|&nbsp;)<\/p>/gi,'</p>');o.content=o.content.replace(/<p( )([^>]+)><\/p>|<p( )([^>]+)\/>|<p( )([^>]+)>\s+<\/p>|<p><\/p>|<p\/>|<p>\s+<\/p>/gi,'<p$1$2$3$4$5$6>\u00a0</p>');if(!isIE&&o.set){o.content=o.content.replace(/<p( )([^>]+)>[\s\u00a0]+<\/p>|<p>[\s\u00a0]+<\/p>/gi,'<p$1$2><br /></p>');}else{o.content=o.content.replace(/<p( )([^>]+)>\s*<br \/>\s*<\/p>|<p>\s*<br \/>\s*<\/p>/gi,'<p$1$2>\u00a0</p>');o.content=o.content.replace(/\s*<br \/>\s*<\/p>/gi,'</p>');}};ed.onBeforeSetContent.add(padd);ed.onPostProcess.add(padd);if(s.forced_root_block){ed.onInit.add(t.forceRoots,t);ed.onSetContent.add(t.forceRoots,t);ed.onBeforeGetContent.add(t.forceRoots,t);}},setup:function(){var t=this,ed=t.editor,s=t.settings;if(s.forced_root_block){ed.onKeyUp.add(t.forceRoots,t);ed.onPreProcess.add(t.forceRoots,t);}if(s.force_br_newlines){if(isIE){ed.onKeyPress.add(function(ed,e){var n,s=ed.selection;if(e.keyCode==13){s.setContent('<br id="__" /> ',{format:'raw'});n=ed.dom.get('__');n.removeAttribute('id');s.select(n);s.collapse();return Event.cancel(e);}});}return;}if(!isIE&&s.force_p_newlines){ed.onPreProcess.add(function(ed,o){each(ed.dom.select('br',o.node),function(n){var p=n.parentNode;if(p&&p.nodeName=='p'&&(p.childNodes.length==1||p.lastChild==n))p.replaceChild(ed.getDoc().createTextNode('\u00a0'),n);});});ed.onKeyPress.add(function(ed,e){if(e.keyCode==13&&!e.shiftKey){if(!t.insertPara(e))Event.cancel(e);}});if(isGecko){ed.onKeyDown.add(function(ed,e){if((e.keyCode==8||e.keyCode==46)&&!e.shiftKey)t.backspaceDelete(e,e.keyCode==8);});}}},find:function(n,t,s){var ed=this.editor,w=ed.getDoc().createTreeWalker(n,4,null,false),c=-1;while(n=w.nextNode()){c++;if(t==0&&n==s)return c;if(t==1&&c==s)return n;}return-1;},forceRoots:function(ed,e){var t=this,ed=t.editor,b=ed.getBody(),d=ed.getDoc(),se=ed.selection,s=se.getSel(),r=se.getRng(),si=-2,ei,so,eo,tr,c=-0xFFFFFF;var nx,bl,bp,sp,le,nl=b.childNodes,i;if(e&&e.keyCode==13)return true;for(i=nl.length-1;i>=0;i--){nx=nl[i];if(nx.nodeType==3||!t.dom.isBlock(nx)){if(!bl){if(nx.nodeType!=3||/[^\s]/g.test(nx.nodeValue)){if(si==-2&&r){if(!isIE){so=r.startOffset;eo=r.endOffset;si=t.find(b,0,r.startContainer);ei=t.find(b,0,r.endContainer);}else{tr=d.body.createTextRange();tr.moveToElementText(b);tr.collapse(1);bp=tr.move('character',c)*-1;tr=r.duplicate();tr.collapse(1);sp=tr.move('character',c)*-1;tr=r.duplicate();tr.collapse(0);le=(tr.move('character',c)*-1)-sp;si=sp-bp;ei=le;}}bl=ed.dom.create(t.settings.forced_root_block);bl.appendChild(nx.cloneNode(1));nx.parentNode.replaceChild(bl,nx);}}else{if(bl.hasChildNodes())bl.insertBefore(nx,bl.firstChild);else bl.appendChild(nx);}}else bl=null;}if(si!=-2){if(!isIE){bl=d.getElementsByTagName(t.settings.element)[0];r=d.createRange();if(si!=-1)r.setStart(t.find(b,1,si),so);else r.setStart(bl,0);if(ei!=-1)r.setEnd(t.find(b,1,ei),eo);else r.setEnd(bl,0);if(s){s.removeAllRanges();s.addRange(r);}}else{try{r=s.createRange();r.moveToElementText(b);r.collapse(1);r.moveStart('character',si);r.moveEnd('character',ei);r.select();}catch(ex){}}}},getParentBlock:function(n){var d=this.dom;return d.getParent(n,d.isBlock);},insertPara:function(e){var t=this,ed=t.editor,d=ed.getDoc(),se=t.settings,s=ed.selection.getSel(),r=s.getRangeAt(0),b=d.body;var rb,ra,dir,sn,so,en,eo,sb,eb,bn,bef,aft,sc,ec,n;function isEmpty(n){n=n.innerHTML;n=n.replace(/<(img|hr|table)/gi,'-');n=n.replace(/<[^>]+>/g,'');return n.replace(/[ \t\r\n]+/g,'')=='';};rb=d.createRange();rb.setStart(s.anchorNode,s.anchorOffset);rb.collapse(true);ra=d.createRange();ra.setStart(s.focusNode,s.focusOffset);ra.collapse(true);dir=rb.compareBoundaryPoints(rb.START_TO_END,ra)<0;sn=dir?s.anchorNode:s.focusNode;so=dir?s.anchorOffset:s.focusOffset;en=dir?s.focusNode:s.anchorNode;eo=dir?s.focusOffset:s.anchorOffset;if(sn==b&&en==b&&b.firstChild&&ed.dom.isBlock(b.firstChild)){sn=en=sn.firstChild;so=eo=0;rb=d.createRange();rb.setStart(sn,0);ra=d.createRange();ra.setStart(en,0);}sn=sn.nodeName=="BODY"?sn.firstChild:sn;en=en.nodeName=="BODY"?en.firstChild:en;sb=t.getParentBlock(sn);eb=t.getParentBlock(en);bn=sb?sb.nodeName:se.element;if(t.dom.getParent(sb,function(n){return/OL|UL|PRE/.test(n.nodeName);}))return true;if(sb&&(sb.nodeName=='CAPTION'||/absolute|relative|static/gi.test(sb.style.position))){bn=se.element;sb=null;}if(eb&&(eb.nodeName=='CAPTION'||/absolute|relative|static/gi.test(eb.style.position))){bn=se.element;eb=null;}if(/(TD|TABLE|TH|CAPTION)/.test(bn)||(sb&&bn=="DIV"&&/left|right/gi.test(sb.style.cssFloat))){bn=se.element;sb=eb=null;}bef=(sb&&sb.nodeName==bn)?sb.cloneNode(0):ed.dom.create(bn);aft=(eb&&eb.nodeName==bn)?eb.cloneNode(0):ed.dom.create(bn);aft.removeAttribute('id');if(/^(H[1-6])$/.test(bn)&&sn.nodeValue&&so==sn.nodeValue.length)aft=ed.dom.create(se.element);n=sc=sn;do{if(n==b||n.nodeType==9||t.dom.isBlock(n)||/(TD|TABLE|TH|CAPTION)/.test(n.nodeName))break;sc=n;}while((n=n.previousSibling?n.previousSibling:n.parentNode));n=ec=en;do{if(n==b||n.nodeType==9||t.dom.isBlock(n)||/(TD|TABLE|TH|CAPTION)/.test(n.nodeName))break;ec=n;}while((n=n.nextSibling?n.nextSibling:n.parentNode));if(sc.nodeName==bn)rb.setStart(sc,0);else rb.setStartBefore(sc);rb.setEnd(sn,so);bef.appendChild(rb.cloneContents()||d.createTextNode(''));try{ra.setEndAfter(ec);}catch(ex){}ra.setStart(en,eo);aft.appendChild(ra.cloneContents()||d.createTextNode(''));r=d.createRange();if(!sc.previousSibling&&sc.parentNode.nodeName==bn){r.setStartBefore(sc.parentNode);}else{if(rb.startContainer.nodeName==bn&&rb.startOffset==0)r.setStartBefore(rb.startContainer);else r.setStart(rb.startContainer,rb.startOffset);}if(!ec.nextSibling&&ec.parentNode.nodeName==bn)r.setEndAfter(ec.parentNode);else r.setEnd(ra.endContainer,ra.endOffset);r.deleteContents();if(bef.firstChild&&bef.firstChild.nodeName==bn)bef.innerHTML=bef.firstChild.innerHTML;if(aft.firstChild&&aft.firstChild.nodeName==bn)aft.innerHTML=aft.firstChild.innerHTML;if(isEmpty(bef))bef.innerHTML='<br />';if(isEmpty(aft))aft.innerHTML=isOpera?'&nbsp;':'<br />';if(isOpera){r.insertNode(bef);r.insertNode(aft);}else{r.insertNode(aft);r.insertNode(bef);}aft.normalize();bef.normalize();r=d.createRange();r.selectNodeContents(aft);r.collapse(1);s.removeAllRanges();s.addRange(r);if(tinymce.isWebKit)ed.getWin().scrollTo(0,ed.dom.getPos(aft).y);else aft.scrollIntoView(0);return false;},backspaceDelete:function(e,bs){var t=this,ed=t.editor,b=ed.getBody(),n,se=ed.selection,r=se.getRng(),sc=r.startContainer,n;if(sc&&ed.dom.isBlock(sc)&&bs){if(sc.childNodes.length==1&&sc.firstChild.nodeName=='BR'){n=sc.previousSibling;if(n){ed.dom.remove(sc);se.select(n,1);se.collapse(0);return Event.cancel(e);}}}function handler(e){e=e.target;if(e&&e.parentNode&&e.nodeName=='BR'&&t.getParentBlock(e)){ed.dom.remove(e);Event.remove(b,'DOMNodeInserted',handler);}};Event._add(b,'DOMNodeInserted',handler);window.setTimeout(function(){Event._remove(b,'DOMNodeInserted',handler);},1);}});})();(function(){var DOM=tinymce.DOM,Event=tinymce.dom.Event,each=tinymce.each,extend=tinymce.extend;tinymce.create('tinymce.ControlManager',{ControlManager:function(ed,s){var t=this,i;s=s||{};t.editor=ed;t.controls={};t.onAdd=new tinymce.util.Dispatcher(t);t.onPostRender=new tinymce.util.Dispatcher(t);t.prefix=s.prefix||ed.id+'_';t.onPostRender.add(function(){each(t.controls,function(c){c.postRender();});});},get:function(id){return this.controls[this.prefix+id]||this.controls[id];},setActive:function(id,s){var c=null;if(c=this.get(id))c.setActive(s);return c;},setDisabled:function(id,s){var c=null;if(c=this.get(id))c.setDisabled(s);return c;},add:function(c){var t=this;if(c){t.controls[c.id]=c;t.onAdd.dispatch(c,t);}return c;},createControl:function(n){var c,t=this,ed=t.editor;each(ed.plugins,function(p){if(p.createControl){c=p.createControl(n,t);if(c)return false;}});switch(n){case"|":case"separator":return t.createSeparator();}if(!c&&ed.buttons&&(c=ed.buttons[n]))return t.createButton(n,c);return t.add(c);},createDropMenu:function(id,s){var t=this,ed=t.editor,c;s=extend({'class':'mceDropDown'},s);s['class']=s['class']+' '+ed.getParam('skin')+'Skin';id=t.prefix+id;c=t.controls[id]=new tinymce.ui.DropMenu(id,s);c.onAddItem.add(function(c,o){var s=o.settings;s.title=ed.getLang(s.title,s.title);if(!s.onclick){s.onclick=function(v){ed.execCommand(s.cmd,s.ui||false,v||s.value);};}});ed.onRemove.add(function(){c.destroy();});return t.add(c);},createListBox:function(id,s){var t=this,ed=t.editor,cmd,c;if(t.get(id))return null;s.title=ed.translate(s.title);s.scope=s.scope||ed;if(!s.onselect){s.onselect=function(v){ed.execCommand(s.cmd,s.ui||false,v||s.value);};}s=extend({title:s.title,'class':id,scope:s.scope,control_manager:t},s);id=t.prefix+id;if(ed.settings.use_native_selects)c=new tinymce.ui.NativeListBox(id,s);else c=new tinymce.ui.ListBox(id,s);t.controls[id]=c;if(tinymce.isWebKit){c.onPostRender.add(function(c,n){Event.add(n,'mousedown',function(){ed.bookmark=ed.selection.getBookmark('simple');});Event.add(n,'focus',function(){ed.selection.moveToBookmark(ed.bookmark);ed.bookmark=null;});});}if(c.hideMenu)ed.onMouseDown.add(c.hideMenu,c);return t.add(c);},createButton:function(id,s){var t=this,ed=t.editor,o,c;if(t.get(id))return null;s.title=ed.translate(s.title);s.scope=s.scope||ed;if(!s.onclick&&!s.menu_button){s.onclick=function(){ed.execCommand(s.cmd,s.ui||false,s.value);};}s=extend({title:s.title,'class':id,unavailable_prefix:ed.getLang('unavailable',''),scope:s.scope,control_manager:t},s);id=t.prefix+id;if(s.menu_button){c=new tinymce.ui.MenuButton(id,s);ed.onMouseDown.add(c.hideMenu,c);}else c=new tinymce.ui.Button(id,s);return t.add(c);},createMenuButton:function(id,s){s=s||{};s.menu_button=1;return this.createButton(id,s);},createSplitButton:function(id,s){var t=this,ed=t.editor,cmd,c;if(t.get(id))return null;s.title=ed.translate(s.title);s.scope=s.scope||ed;if(!s.onclick){s.onclick=function(v){ed.execCommand(s.cmd,s.ui||false,v||s.value);};}if(!s.onselect){s.onselect=function(v){ed.execCommand(s.cmd,s.ui||false,v||s.value);};}s=extend({title:s.title,'class':id,scope:s.scope,control_manager:t},s);id=t.prefix+id;c=t.add(new tinymce.ui.SplitButton(id,s));ed.onMouseDown.add(c.hideMenu,c);return c;},createColorSplitButton:function(id,s){var t=this,ed=t.editor,cmd,c;if(t.get(id))return null;s.title=ed.translate(s.title);s.scope=s.scope||ed;if(!s.onclick){s.onclick=function(v){ed.execCommand(s.cmd,s.ui||false,v||s.value);};}if(!s.onselect){s.onselect=function(v){ed.execCommand(s.cmd,s.ui||false,v||s.value);};}s=extend({title:s.title,'class':id,'menu_class':ed.getParam('skin')+'Skin',scope:s.scope,more_colors_title:ed.getLang('more_colors')},s);id=t.prefix+id;c=new tinymce.ui.ColorSplitButton(id,s);ed.onMouseDown.add(c.hideMenu,c);return t.add(c);},createToolbar:function(id,s){var c,t=this;id=t.prefix+id;c=new tinymce.ui.Toolbar(id,s);if(t.get(id))return null;return t.add(c);},createSeparator:function(){return new tinymce.ui.Separator();}});})();(function(){var Dispatcher=tinymce.util.Dispatcher,each=tinymce.each,isIE=tinymce.isIE,isOpera=tinymce.isOpera;tinymce.create('tinymce.WindowManager',{WindowManager:function(ed){var t=this;t.editor=ed;t.onOpen=new Dispatcher(t);t.onClose=new Dispatcher(t);t.params={};t.features={};},open:function(s,p){var t=this,f='',x,y,mo=t.editor.settings.dialog_type=='modal',w,sw,sh,vp=tinymce.DOM.getViewPort();s=s||{};p=p||{};sw=isOpera?vp.w:screen.width;sh=isOpera?vp.h:screen.height;s.name=s.name||'mc_'+new Date().getTime();s.width=parseInt(s.width||320);s.height=parseInt(s.height||240);s.resizable=true;s.left=s.left||parseInt(sw/ 2.0) - (s.width /2.0);s.top=s.top||parseInt(sh/ 2.0) - (s.height /2.0);p.inline=false;p.mce_width=s.width;p.mce_height=s.height;if(mo){if(isIE){s.center=true;s.help=false;s.dialogWidth=s.width+'px';s.dialogHeight=s.height+'px';s.scroll=s.scrollbars||false;}else s.modal=s.alwaysRaised=s.dialog=s.centerscreen=s.dependent=true;}each(s,function(v,k){if(tinymce.is(v,'boolean'))v=v?'yes':'no';if(!/^(name|url)$/.test(k)){if(isIE&&mo)f+=(f?';':'')+k+':'+v;else f+=(f?',':'')+k+'='+v;}});t.features=s;t.params=p;t.onOpen.dispatch(t,s,p);try{if(isIE&&mo){w=1;window.showModalDialog(s.url||s.file,window,f);}else w=window.open(s.url||s.file,s.name,f);}catch(ex){}if(!w)alert(t.editor.getLang('popup_blocked'));},close:function(w){w.close();this.onClose.dispatch(this);},createInstance:function(cl){var a=arguments,i,f=tinymce.resolve(cl),s='';for(i=1;i<a.length;i++)s+=(i>1?',':'')+'a['+i+']';return eval('(new f('+s+'))');},confirm:function(t,cb,s){cb.call(s||this,confirm(this._decode(this.editor.getLang(t,t))));},alert:function(t,cb,s){alert(this._decode(t));if(cb)cb.call(s||this);},_decode:function(s){return tinymce.DOM.decode(s).replace(/\\n/g,'\n');}});}());
\ No newline at end of file
--- a/includes/clientside/tinymce/tiny_mce_popup.js	Fri Feb 22 12:46:51 2008 -0500
+++ b/includes/clientside/tinymce/tiny_mce_popup.js	Fri Feb 22 12:51:53 2008 -0500
@@ -1,288 +1,224 @@
-// Some global instances, this will be filled later
-var tinyMCE = null, tinyMCELang = null;
+// Some global instances
+var tinymce = null, tinyMCEPopup, tinyMCE;
 
-function TinyMCE_Popup() {
-};
+tinyMCEPopup = {
+	init : function() {
+		var t = this, w = t.getWin(), ti;
 
-TinyMCE_Popup.prototype = {
-	findWin : function(w) {
-		var c;
+		// Find API
+		tinymce = w.tinymce;
+		tinyMCE = w.tinyMCE;
+		t.editor = tinymce.EditorManager.activeEditor;
+		t.params = t.editor.windowManager.params;
 
-		// Check parents
-		c = w;
-		while (c && (c = c.parent) != null) {
-			if (typeof(c.tinyMCE) != "undefined")
-				return c;
-		}
+		// Setup local DOM
+		t.dom = t.editor.windowManager.createInstance('tinymce.dom.DOMUtils', document);
+		t.dom.loadCSS(t.editor.settings.popup_css);
 
-		// Check openers
-		c = w;
-		while (c && (c = c.opener) != null) {
-			if (typeof(c.tinyMCE) != "undefined")
-				return c;
-		}
+		// Setup on init listeners
+		t.listeners = [];
+		t.onInit = {
+			add : function(f, s) {
+				t.listeners.push({func : f, scope : s});
+			}
+		};
 
-		// Try top
-		if (typeof(top.tinyMCE) != "undefined")
-			return top;
-
-		return null;
+		t.isWindow = !t.getWindowArg('mce_inline');
+		t.id = t.getWindowArg('mce_window_id');
+		t.editor.windowManager.onOpen.dispatch(t.editor.windowManager, window);
 	},
 
-	init : function() {
-		var win = window.opener ? window.opener : window.dialogArguments, c;
-		var inst;
-
-		if (!win)
-			win = this.findWin(window);
-
-		if (!win) {
-			alert("tinyMCE object reference not found from popup.");
-			return;
-		}
-
-		window.opener = win;
-		this.windowOpener = win;
-		this.onLoadEval = "";
-
-		// Setup parent references
-		tinyMCE = win.tinyMCE;
-		tinyMCELang = win.tinyMCELang;
-
-		inst = tinyMCE.selectedInstance;
-		this.isWindow = tinyMCE.getWindowArg('mce_inside_iframe', false) == false;
-		this.storeSelection = (tinyMCE.isRealIE) && !this.isWindow && tinyMCE.getWindowArg('mce_store_selection', true);
-
-		if (this.isWindow)
-			window.focus();
-
-		// Store selection
-		if (this.storeSelection)
-			inst.selectionBookmark = inst.selection.getBookmark(true);
+	getWin : function() {
+		return window.dialogArguments || opener || parent || top;
+	},
 
-		// Setup dir
-		if (tinyMCELang['lang_dir'])
-			document.dir = tinyMCELang['lang_dir'];
-
-		// Setup title
-		var re = new RegExp('{|\\\$|}', 'g');
-		var title = document.title.replace(re, "");
-		if (typeof tinyMCELang[title] != "undefined") {
-			var divElm = document.createElement("div");
-			divElm.innerHTML = tinyMCELang[title];
-			document.title = divElm.innerHTML;
+	getWindowArg : function(n, dv) {
+		var v = this.params[n];
 
-			if (tinyMCE.setWindowTitle != null)
-				tinyMCE.setWindowTitle(window, divElm.innerHTML);
-		}
-
-		// Output Popup CSS class
-		document.write('<link href="' + tinyMCE.getParam("popups_css") + '" rel="stylesheet" type="text/css">');
-
-		if (tinyMCE.getParam("popups_css_add")) {
-			c = tinyMCE.getParam("popups_css_add");
-
-			// Is relative
-			if (c.indexOf('://') == -1 && c.charAt(0) != '/')
-				c = tinyMCE.documentBasePath + "/" + c;
-
-			document.write('<link href="' + c + '" rel="stylesheet" type="text/css">');
-		}
-
-		tinyMCE.addEvent(window, "load", this.onLoad);
+		return tinymce.is(v) ? v : dv;
 	},
 
-	onLoad : function() {
-		var dir, i, elms, body = document.body;
-
-		if (tinyMCE.getWindowArg('mce_replacevariables', true))
-			body.innerHTML = tinyMCE.applyTemplate(body.innerHTML, tinyMCE.windowArgs);
-
-		dir = tinyMCE.selectedInstance.settings['directionality'];
-		if (dir == "rtl" && document.forms && document.forms.length > 0) {
-			elms = document.forms[0].elements;
-			for (i=0; i<elms.length; i++) {
-				if ((elms[i].type == "text" || elms[i].type == "textarea") && elms[i].getAttribute("dir") != "ltr")
-					elms[i].dir = dir;
-			}
-		}
-
-		if (body.style.display == 'none')
-			body.style.display = 'block';
-
-		// Execute real onload (Opera fix)
-		if (tinyMCEPopup.onLoadEval != "")
-			eval(tinyMCEPopup.onLoadEval);
+	getParam : function(n, dv) {
+		return this.editor.getParam(n, dv);
 	},
 
-	executeOnLoad : function(str) {
-		if (tinyMCE.isOpera)
-			this.onLoadEval = str;
-		else
-			eval(str);
+	getLang : function(n, dv) {
+		return this.editor.getLang(n, dv);
+	},
+
+	execCommand : function(cmd, ui, val, a) {
+		this.restoreSelection();
+		return this.editor.execCommand(cmd, ui, val, a || {skip_focus : 1});
 	},
 
 	resizeToInnerSize : function() {
-		// Netscape 7.1 workaround
-		if (this.isWindow && tinyMCE.isNS71) {
-			window.resizeBy(0, 10);
-			return;
-		}
-
-		if (this.isWindow) {
-			var doc = document;
-			var body = doc.body;
-			var oldMargin, wrapper, iframe, nodes, dx, dy;
-
-			if (body.style.display == 'none')
-				body.style.display = 'block';
+		var t = this, n, b = document.body, vp = t.dom.getViewPort(window), dw, dh;
 
-			// Remove margin
-			oldMargin = body.style.margin;
-			body.style.margin = '0';
-
-			// Create wrapper
-			wrapper = doc.createElement("div");
-			wrapper.id = 'mcBodyWrapper';
-			wrapper.style.display = 'none';
-			wrapper.style.margin = '0';
-
-			// Wrap body elements
-			nodes = doc.body.childNodes;
-			for (var i=nodes.length-1; i>=0; i--) {
-				if (wrapper.hasChildNodes())
-					wrapper.insertBefore(nodes[i].cloneNode(true), wrapper.firstChild);
-				else
-					wrapper.appendChild(nodes[i].cloneNode(true));
+		dw = t.getWindowArg('mce_width') - vp.w;
+		dh = t.getWindowArg('mce_height') - vp.h;
 
-				nodes[i].parentNode.removeChild(nodes[i]);
-			}
-
-			// Add wrapper
-			doc.body.appendChild(wrapper);
-
-			// Create iframe
-			iframe = document.createElement("iframe");
-			iframe.id = "mcWinIframe";
-			iframe.src = document.location.href.toLowerCase().indexOf('https') == -1 ? "about:blank" : tinyMCE.settings['default_document'];
-			iframe.width = "100%";
-			iframe.height = "100%";
-			iframe.style.margin = '0';
-
-			// Add iframe
-			doc.body.appendChild(iframe);
-
-			// Measure iframe
-			iframe = document.getElementById('mcWinIframe');
-			dx = tinyMCE.getWindowArg('mce_width') - iframe.clientWidth;
-			dy = tinyMCE.getWindowArg('mce_height') - iframe.clientHeight;
-
-			// Resize window
-			// tinyMCE.debug(tinyMCE.getWindowArg('mce_width') + "," + tinyMCE.getWindowArg('mce_height') + " - " + dx + "," + dy);
-			window.resizeBy(dx, dy);
-
-			// Hide iframe and show wrapper
-			body.style.margin = oldMargin;
-			iframe.style.display = 'none';
-			wrapper.style.display = 'block';
-		}
+		if (t.isWindow)
+			window.resizeBy(dw, dh);
+		else
+			t.editor.windowManager.resizeBy(dw, dh, t.id);
 	},
 
-	resizeToContent : function() {
-		var isMSIE = (navigator.appName == "Microsoft Internet Explorer");
-		var isOpera = (navigator.userAgent.indexOf("Opera") != -1);
-
-		if (isOpera)
-			return;
-
-		if (isMSIE) {
-			try { window.resizeTo(10, 10); } catch (e) {}
-
-			var elm = document.body;
-			var width = elm.offsetWidth;
-			var height = elm.offsetHeight;
-			var dx = (elm.scrollWidth - width) + 4;
-			var dy = elm.scrollHeight - height;
-
-			try { window.resizeBy(dx, dy); } catch (e) {}
-		} else {
-			window.scrollBy(1000, 1000);
-			if (window.scrollX > 0 || window.scrollY > 0) {
-				window.resizeBy(window.innerWidth * 2, window.innerHeight * 2);
-				window.sizeToContent();
-				window.scrollTo(0, 0);
-				var x = parseInt(screen.width / 2.0) - (window.outerWidth / 2.0);
-				var y = parseInt(screen.height / 2.0) - (window.outerHeight / 2.0);
-				window.moveTo(x, y);
-			}
-		}
+	executeOnLoad : function(s) {
+		this.onInit.add(function() {
+			eval(s);
+		});
 	},
 
-	getWindowArg : function(name, default_value) {
-		return tinyMCE.getWindowArg(name, default_value);
+	storeSelection : function() {
+		this.editor.windowManager.bookmark = tinyMCEPopup.editor.selection.getBookmark('simple');
 	},
 
 	restoreSelection : function() {
-		if (this.storeSelection) {
-			var inst = tinyMCE.selectedInstance;
+		var t = tinyMCEPopup;
 
-			inst.getWin().focus();
-
-			if (inst.selectionBookmark)
-				inst.selection.moveToBookmark(inst.selectionBookmark);
-		}
+		if (!t.isWindow && tinymce.isIE)
+			t.editor.selection.moveToBookmark(t.editor.windowManager.bookmark);
 	},
 
-	execCommand : function(command, user_interface, value) {
-		var inst = tinyMCE.selectedInstance;
-
-		this.restoreSelection();
-		inst.execCommand(command, user_interface, value);
+	requireLangPack : function() {
+		var u = this.getWindowArg('plugin_url') || this.getWindowArg('theme_url');
 
-		// Store selection
-		if (this.storeSelection)
-			inst.selectionBookmark = inst.selection.getBookmark(true);
-	},
-
-	close : function() {
-		tinyMCE.closeWindow(window);
+		if (u)
+			document.write('<script type="text/javascript" src="' + u + '/langs/' + this.editor.settings.language + '_dlg.js' + '"></script>');
 	},
 
 	pickColor : function(e, element_id) {
-		tinyMCE.selectedInstance.execCommand('mceColorPicker', true, {
-			element_id : element_id,
-			document : document,
-			window : window,
-			store_selection : false
+		this.execCommand('mceColorPicker', true, {
+			color : document.getElementById(element_id).value,
+			func : function(c) {
+				document.getElementById(element_id).value = c;
+
+				try {
+					document.getElementById(element_id).onchange();
+				} catch (ex) {
+					// Try fire event, ignore errors
+				}
+			}
 		});
 	},
 
 	openBrowser : function(element_id, type, option) {
-		var cb = tinyMCE.getParam(option, tinyMCE.getParam("file_browser_callback"));
-		var url = document.getElementById(element_id).value;
+		tinyMCEPopup.restoreSelection();
+		this.editor.execCallback('file_browser_callback', element_id, document.getElementById(element_id).value, type, window);
+	},
 
-		tinyMCE.setWindowArg("window", window);
-		tinyMCE.setWindowArg("document", document);
+	close : function() {
+		var t = this;
 
-		// Call to external callback
-		if (eval('typeof(tinyMCEPopup.windowOpener.' + cb + ')') == "undefined")
-			alert("Callback function: " + cb + " could not be found.");
-		else
-			eval("tinyMCEPopup.windowOpener." + cb + "(element_id, url, type, window);");
+		t.dom = t.dom.doc = null; // Cleanup
+		t.editor.windowManager.close(window, t.id);
+	},
+
+	// Internal functions	
+
+	_restoreSelection : function() {
+		var e = window.event.srcElement;
+
+		if (e.nodeName == 'INPUT' && (e.type == 'submit' || e.type == 'button'))
+			tinyMCEPopup.restoreSelection();
 	},
 
-	importClass : function(c) {
-		window[c] = function() {};
+/*	_restoreSelection : function() {
+		var e = window.event.srcElement;
+
+		// If user focus a non text input or textarea
+		if ((e.nodeName != 'INPUT' && e.nodeName != 'TEXTAREA') || e.type != 'text')
+			tinyMCEPopup.restoreSelection();
+	},*/
+
+	_onDOMLoaded : function() {
+		var t = this, ti = document.title, bm, h;
+
+		// Translate page
+		h = document.body.innerHTML;
+
+		// Replace a=x with a="x" in IE
+		if (tinymce.isIE)
+			h = h.replace(/ (value|title|alt)=([^\s>]+)/gi, ' $1="$2"');
+
+		document.body.innerHTML = t.editor.translate(h);
+		document.title = ti = t.editor.translate(ti);
+		document.body.style.display = '';
 
-		for (var n in window.opener[c].prototype)
-			window[c].prototype[n] = window.opener[c].prototype[n];
+		// Restore selection in IE when focus is placed on a non textarea or input element of the type text
+		if (tinymce.isIE)
+			document.attachEvent('onmouseup', tinyMCEPopup._restoreSelection);
+
+		t.restoreSelection();
+
+		// Call onInit
+		tinymce.each(t.listeners, function(o) {
+			o.func.call(o.scope, t.editor);
+		});
+
+		t.resizeToInnerSize();
+
+		if (t.isWindow)
+			window.focus();
+		else
+			t.editor.windowManager.setTitle(ti, t.id);
+
+		if (!tinymce.isIE && !t.isWindow) {
+			tinymce.dom.Event._add(document, 'focus', function() {
+				t.editor.windowManager.focus(t.id)
+			});
+		}
 
-		window[c].constructor = window.opener[c].constructor;
-	}
+		// Patch for accessibility
+		tinymce.each(t.dom.select('select'), function(e) {
+			e.onkeydown = tinyMCEPopup._accessHandler;
+		});
+
+		// Move focus to window
+		window.focus();
+	},
+
+	_accessHandler : function(e) {
+		var e = e || window.event;
+
+		if (e.keyCode == 13 || e.keyCode == 32) {
+			e = e.target || e.srcElement;
+
+			if (e.onchange)
+				e.onchange();
+
+			return tinymce.dom.Event.cancel(e);
+		}
+	},
+
+	_wait : function() {
+		var t = this, ti;
 
-	};
-
-// Setup global instance
-var tinyMCEPopup = new TinyMCE_Popup();
+		if (tinymce.isIE && document.location.protocol != 'https:') {
+			// Fake DOMContentLoaded on IE
+			document.write('<script id=__ie_onload defer src=\'javascript:""\';><\/script>');
+			document.getElementById("__ie_onload").onreadystatechange = function() {
+				if (this.readyState == "complete") {
+					t._onDOMLoaded();
+					document.getElementById("__ie_onload").onreadystatechange = null; // Prevent leak
+				}
+			};
+		} else {
+			if (tinymce.isIE || tinymce.isWebKit) {
+				ti = setInterval(function() {
+					if (/loaded|complete/.test(document.readyState)) {
+						clearInterval(ti);
+						t._onDOMLoaded();
+					}
+				}, 10);
+			} else {
+				window.addEventListener('DOMContentLoaded', function() {
+					t._onDOMLoaded();
+				}, false);
+			}
+		}
+	}
+};
 
 tinyMCEPopup.init();
+tinyMCEPopup._wait(); // Wait for DOM Content Loaded
--- a/includes/clientside/tinymce/tiny_mce_src.js	Fri Feb 22 12:46:51 2008 -0500
+++ b/includes/clientside/tinymce/tiny_mce_src.js	Fri Feb 22 12:51:53 2008 -0500
@@ -1,6339 +1,2639 @@
 
-/* file:jscripts/tiny_mce/classes/TinyMCE_Engine.class.js */
-
-function TinyMCE_Engine() {
-	var ua;
-
-	this.majorVersion = "2";
-	this.minorVersion = "1.0";
-	this.releaseDate = "2007-02-13";
-
-	this.instances = new Array();
-	this.switchClassCache = new Array();
-	this.windowArgs = new Array();
-	this.loadedFiles = new Array();
-	this.pendingFiles = new Array();
-	this.loadingIndex = 0;
-	this.configs = new Array();
-	this.currentConfig = 0;
-	this.eventHandlers = new Array();
-	this.log = new Array();
-	this.undoLevels = [];
-	this.undoIndex = 0;
-	this.typingUndoIndex = -1;
-
-	// Browser check
-	ua = navigator.userAgent;
-	this.isMSIE = (navigator.appName == "Microsoft Internet Explorer");
-	this.isMSIE5 = this.isMSIE && (ua.indexOf('MSIE 5') != -1);
-	this.isMSIE5_0 = this.isMSIE && (ua.indexOf('MSIE 5.0') != -1);
-	this.isMSIE7 = this.isMSIE && (ua.indexOf('MSIE 7') != -1);
-	this.isGecko = ua.indexOf('Gecko') != -1;
-	this.isSafari = ua.indexOf('Safari') != -1;
-	this.isOpera = ua.indexOf('Opera') != -1;
-	this.isMac = ua.indexOf('Mac') != -1;
-	this.isNS7 = ua.indexOf('Netscape/7') != -1;
-	this.isNS71 = ua.indexOf('Netscape/7.1') != -1;
-	this.dialogCounter = 0;
-	this.plugins = new Array();
-	this.themes = new Array();
-	this.menus = new Array();
-	this.loadedPlugins = new Array();
-	this.buttonMap = new Array();
-	this.isLoaded = false;
-
-	// Fake MSIE on Opera and if Opera fakes IE, Gecko or Safari cancel those
-	if (this.isOpera) {
-		this.isMSIE = true;
-		this.isGecko = false;
-		this.isSafari =  false;
-	}
-
-	this.isIE = this.isMSIE;
-	this.isRealIE = this.isMSIE && !this.isOpera;
-
-	// TinyMCE editor id instance counter
-	this.idCounter = 0;
-};
-
-TinyMCE_Engine.prototype = {
-	init : function(settings) {
-		var theme, nl, baseHREF = "", i;
-
-		// IE 5.0x is no longer supported since 5.5, 6.0 and 7.0 now exists. We can't support old browsers forever, sorry.
-		if (this.isMSIE5_0)
+/* file:jscripts/tiny_mce/classes/tinymce.js */
+
+var tinymce = {
+	majorVersion : '3',
+	minorVersion : '0',
+	releaseDate : '2008-01-30',
+
+	_init : function() {
+		var t = this, ua = navigator.userAgent, i, nl, n, base;
+
+		// Browser checks
+		t.isOpera = window.opera && opera.buildNumber;
+		t.isWebKit = /WebKit/.test(ua);
+		t.isOldWebKit = t.isWebKit && !window.getSelection().getRangeAt;
+		t.isIE = !t.isWebKit && !t.isOpera && (/MSIE/gi).test(ua) && (/Explorer/gi).test(navigator.appName);
+		t.isIE6 = t.isIE && /MSIE [56]/.test(ua);
+		t.isGecko = !t.isWebKit && /Gecko/.test(ua);
+//		t.isGecko3 = t.isGecko && /(Firefox|Minefield)\/[3-9]/.test(ua);
+		t.isMac = ua.indexOf('Mac') != -1;
+
+		// TinyMCE .NET webcontrol might be setting the values for TinyMCE
+		if (window.tinyMCEPreInit) {
+			t.suffix = tinyMCEPreInit.suffix;
+			t.baseURL = tinyMCEPreInit.base;
 			return;
-
-		this.settings = settings;
-
-		// Check if valid browser has execcommand support
-		if (typeof(document.execCommand) == 'undefined')
-			return;
-
-		// Get script base path
-		if (!tinyMCE.baseURL) {
-			var elements = document.getElementsByTagName('script');
-
-			// If base element found, add that infront of baseURL
-			nl = document.getElementsByTagName('base');
+		}
+
+		// Get suffix and base
+		t.suffix = '';
+
+		// If base element found, add that infront of baseURL
+		nl = document.getElementsByTagName('base');
+		for (i=0; i<nl.length; i++) {
+			if (nl[i].href)
+				base = nl[i].href;
+		}
+
+		function getBase(n) {
+			if (n.src && /tiny_mce(|_dev|_src|_gzip|_jquery|_prototype).js/.test(n.src)) {
+				if (/_(src|dev)\.js/g.test(n.src))
+					t.suffix = '_src';
+
+				t.baseURL = n.src.substring(0, n.src.lastIndexOf('/'));
+
+				// If path to script is relative and a base href was found add that one infront
+				if (base && t.baseURL.indexOf('://') == -1)
+					t.baseURL = base + t.baseURL;
+
+				return t.baseURL;
+			}
+
+			return null;
+		};
+
+		// Check document
+		nl = document.getElementsByTagName('script');
+		for (i=0; i<nl.length; i++) {
+			if (getBase(nl[i]))
+				return;
+		}
+
+		// Check head
+		n = document.getElementsByTagName('head')[0];
+		if (n) {
+			nl = n.getElementsByTagName('script');
 			for (i=0; i<nl.length; i++) {
-				if (nl[i].href)
-					baseHREF = nl[i].href;
-			}
-
-			for (var i=0; i<elements.length; i++) {
-				if (elements[i].src && (elements[i].src.indexOf("tiny_mce.js") != -1 || elements[i].src.indexOf("tiny_mce_dev.js") != -1 || elements[i].src.indexOf("tiny_mce_src.js") != -1 || elements[i].src.indexOf("tiny_mce_gzip") != -1)) {
-					var src = elements[i].src;
-
-					tinyMCE.srcMode = (src.indexOf('_src') != -1 || src.indexOf('_dev') != -1) ? '_src' : '';
-					tinyMCE.gzipMode = src.indexOf('_gzip') != -1;
-					src = src.substring(0, src.lastIndexOf('/'));
-
-					if (settings.exec_mode == "src" || settings.exec_mode == "normal")
-						tinyMCE.srcMode = settings.exec_mode == "src" ? '_src' : '';
-
-					// Force it absolute if page has a base href
-					if (baseHREF != "" && src.indexOf('://') == -1)
-						tinyMCE.baseURL = baseHREF + src;
-					else
-						tinyMCE.baseURL = src;
-
-					break;
-				}
+				if (getBase(nl[i]))
+					return;
 			}
 		}
 
-		// Get document base path
-		this.documentBasePath = document.location.href;
-		if (this.documentBasePath.indexOf('?') != -1)
-			this.documentBasePath = this.documentBasePath.substring(0, this.documentBasePath.indexOf('?'));
-		this.documentURL = this.documentBasePath;
-		this.documentBasePath = this.documentBasePath.substring(0, this.documentBasePath.lastIndexOf('/'));
-
-		// If not HTTP absolute
-		if (tinyMCE.baseURL.indexOf('://') == -1 && tinyMCE.baseURL.charAt(0) != '/') {
-			// If site absolute
-			tinyMCE.baseURL = this.documentBasePath + "/" + tinyMCE.baseURL;
-		}
-
-		// Set default values on settings
-		this._def("mode", "none");
-		this._def("theme", "advanced");
-		this._def("plugins", "", true);
-		this._def("language", "en");
-		this._def("docs_language", this.settings['language']);
-		this._def("elements", "");
-		this._def("textarea_trigger", "mce_editable");
-		this._def("editor_selector", "");
-		this._def("editor_deselector", "mceNoEditor");
-		this._def("valid_elements", "+a[id|style|rel|rev|charset|hreflang|dir|lang|tabindex|accesskey|type|name|href|target|title|class|onfocus|onblur|onclick|ondblclick|onmousedown|onmouseup|onmouseover|onmousemove|onmouseout|onkeypress|onkeydown|onkeyup],-strong/-b[class|style],-em/-i[class|style],-strike[class|style],-u[class|style],#p[id|style|dir|class|align],-ol[class|style],-ul[class|style],-li[class|style],br,img[id|dir|lang|longdesc|usemap|style|class|src|onmouseover|onmouseout|border|alt=|title|hspace|vspace|width|height|align],-sub[style|class],-sup[style|class],-blockquote[dir|style],-table[border=0|cellspacing|cellpadding|width|height|class|align|summary|style|dir|id|lang|bgcolor|background|bordercolor],-tr[id|lang|dir|class|rowspan|width|height|align|valign|style|bgcolor|background|bordercolor],tbody[id|class],thead[id|class],tfoot[id|class],#td[id|lang|dir|class|colspan|rowspan|width|height|align|valign|style|bgcolor|background|bordercolor|scope],-th[id|lang|dir|class|colspan|rowspan|width|height|align|valign|style|scope],caption[id|lang|dir|class|style],-div[id|dir|class|align|style],-span[style|class|align],-pre[class|align|style],address[class|align|style],-h1[id|style|dir|class|align],-h2[id|style|dir|class|align],-h3[id|style|dir|class|align],-h4[id|style|dir|class|align],-h5[id|style|dir|class|align],-h6[id|style|dir|class|align],hr[class|style],-font[face|size|style|id|class|dir|color],dd[id|class|title|style|dir|lang],dl[id|class|title|style|dir|lang],dt[id|class|title|style|dir|lang],cite[title|id|class|style|dir|lang],abbr[title|id|class|style|dir|lang],acronym[title|id|class|style|dir|lang],del[title|id|class|style|dir|lang|datetime|cite],ins[title|id|class|style|dir|lang|datetime|cite]");
-		this._def("extended_valid_elements", "");
-		this._def("invalid_elements", "");
-		this._def("encoding", "");
-		this._def("urlconverter_callback", tinyMCE.getParam("urlconvertor_callback", "TinyMCE_Engine.prototype.convertURL"));
-		this._def("save_callback", "");
-		this._def("debug", false);
-		this._def("force_br_newlines", false);
-		this._def("force_p_newlines", true);
-		this._def("add_form_submit_trigger", true);
-		this._def("relative_urls", true);
-		this._def("remove_script_host", true);
-		this._def("focus_alert", true);
-		this._def("document_base_url", this.documentURL);
-		this._def("visual", true);
-		this._def("visual_table_class", "mceVisualAid");
-		this._def("setupcontent_callback", "");
-		this._def("fix_content_duplication", true);
-		this._def("custom_undo_redo", true);
-		this._def("custom_undo_redo_levels", -1);
-		this._def("custom_undo_redo_keyboard_shortcuts", true);
-		this._def("custom_undo_redo_restore_selection", true);
-		this._def("custom_undo_redo_global", false);
-		this._def("verify_html", true);
-		this._def("apply_source_formatting", false);
-		this._def("directionality", "ltr");
-		this._def("cleanup_on_startup", false);
-		this._def("inline_styles", false);
-		this._def("convert_newlines_to_brs", false);
-		this._def("auto_reset_designmode", true);
-		this._def("entities", "39,#39,160,nbsp,161,iexcl,162,cent,163,pound,164,curren,165,yen,166,brvbar,167,sect,168,uml,169,copy,170,ordf,171,laquo,172,not,173,shy,174,reg,175,macr,176,deg,177,plusmn,178,sup2,179,sup3,180,acute,181,micro,182,para,183,middot,184,cedil,185,sup1,186,ordm,187,raquo,188,frac14,189,frac12,190,frac34,191,iquest,192,Agrave,193,Aacute,194,Acirc,195,Atilde,196,Auml,197,Aring,198,AElig,199,Ccedil,200,Egrave,201,Eacute,202,Ecirc,203,Euml,204,Igrave,205,Iacute,206,Icirc,207,Iuml,208,ETH,209,Ntilde,210,Ograve,211,Oacute,212,Ocirc,213,Otilde,214,Ouml,215,times,216,Oslash,217,Ugrave,218,Uacute,219,Ucirc,220,Uuml,221,Yacute,222,THORN,223,szlig,224,agrave,225,aacute,226,acirc,227,atilde,228,auml,229,aring,230,aelig,231,ccedil,232,egrave,233,eacute,234,ecirc,235,euml,236,igrave,237,iacute,238,icirc,239,iuml,240,eth,241,ntilde,242,ograve,243,oacute,244,ocirc,245,otilde,246,ouml,247,divide,248,oslash,249,ugrave,250,uacute,251,ucirc,252,uuml,253,yacute,254,thorn,255,yuml,402,fnof,913,Alpha,914,Beta,915,Gamma,916,Delta,917,Epsilon,918,Zeta,919,Eta,920,Theta,921,Iota,922,Kappa,923,Lambda,924,Mu,925,Nu,926,Xi,927,Omicron,928,Pi,929,Rho,931,Sigma,932,Tau,933,Upsilon,934,Phi,935,Chi,936,Psi,937,Omega,945,alpha,946,beta,947,gamma,948,delta,949,epsilon,950,zeta,951,eta,952,theta,953,iota,954,kappa,955,lambda,956,mu,957,nu,958,xi,959,omicron,960,pi,961,rho,962,sigmaf,963,sigma,964,tau,965,upsilon,966,phi,967,chi,968,psi,969,omega,977,thetasym,978,upsih,982,piv,8226,bull,8230,hellip,8242,prime,8243,Prime,8254,oline,8260,frasl,8472,weierp,8465,image,8476,real,8482,trade,8501,alefsym,8592,larr,8593,uarr,8594,rarr,8595,darr,8596,harr,8629,crarr,8656,lArr,8657,uArr,8658,rArr,8659,dArr,8660,hArr,8704,forall,8706,part,8707,exist,8709,empty,8711,nabla,8712,isin,8713,notin,8715,ni,8719,prod,8721,sum,8722,minus,8727,lowast,8730,radic,8733,prop,8734,infin,8736,ang,8743,and,8744,or,8745,cap,8746,cup,8747,int,8756,there4,8764,sim,8773,cong,8776,asymp,8800,ne,8801,equiv,8804,le,8805,ge,8834,sub,8835,sup,8836,nsub,8838,sube,8839,supe,8853,oplus,8855,otimes,8869,perp,8901,sdot,8968,lceil,8969,rceil,8970,lfloor,8971,rfloor,9001,lang,9002,rang,9674,loz,9824,spades,9827,clubs,9829,hearts,9830,diams,34,quot,38,amp,60,lt,62,gt,338,OElig,339,oelig,352,Scaron,353,scaron,376,Yuml,710,circ,732,tilde,8194,ensp,8195,emsp,8201,thinsp,8204,zwnj,8205,zwj,8206,lrm,8207,rlm,8211,ndash,8212,mdash,8216,lsquo,8217,rsquo,8218,sbquo,8220,ldquo,8221,rdquo,8222,bdquo,8224,dagger,8225,Dagger,8240,permil,8249,lsaquo,8250,rsaquo,8364,euro", true);
-		this._def("entity_encoding", "named");
-		this._def("cleanup_callback", "");
-		this._def("add_unload_trigger", true);
-		this._def("ask", false);
-		this._def("nowrap", false);
-		this._def("auto_resize", false);
-		this._def("auto_focus", false);
-		this._def("cleanup", true);
-		this._def("remove_linebreaks", true);
-		this._def("button_tile_map", false);
-		this._def("submit_patch", true);
-		this._def("browsers", "msie,safari,gecko,opera", true);
-		this._def("dialog_type", "window");
-		this._def("accessibility_warnings", true);
-		this._def("accessibility_focus", true);
-		this._def("merge_styles_invalid_parents", "");
-		this._def("force_hex_style_colors", true);
-		this._def("trim_span_elements", true);
-		this._def("convert_fonts_to_spans", false);
-		this._def("doctype", '<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">');
-		this._def("font_size_classes", '');
-		this._def("font_size_style_values", 'xx-small,x-small,small,medium,large,x-large,xx-large', true);
-		this._def("event_elements", 'a,img', true);
-		this._def("convert_urls", true);
-		this._def("table_inline_editing", false);
-		this._def("object_resizing", true);
-		this._def("custom_shortcuts", true);
-		this._def("convert_on_click", false);
-		this._def("content_css", '');
-		this._def("fix_list_elements", true);
-		this._def("fix_table_elements", false);
-		this._def("strict_loading_mode", ( ( IE ) ? true : true ) ); // document.contentType == 'application/xhtml+xml');
-		this._def("hidden_tab_class", '');
-		this._def("display_tab_class", '');
-		this._def("gecko_spellcheck", false);
-		this._def("hide_selects_on_submit", true);
-
-		// Force strict loading mode to false on non Gecko browsers
-		//if (this.isMSIE && !this.isOpera)
-		//	this.settings.strict_loading_mode = false;
-
-		// Browser check IE
-		if (this.isMSIE && this.settings['browsers'].indexOf('msie') == -1)
-			return;
-
-		// Browser check Gecko
-		if (this.isGecko && this.settings['browsers'].indexOf('gecko') == -1)
-			return;
-
-		// Browser check Safari
-		if (this.isSafari && this.settings['browsers'].indexOf('safari') == -1)
-			return;
-
-		// Browser check Opera
-		if (this.isOpera && this.settings['browsers'].indexOf('opera') == -1)
-			return;
-
-		// If not super absolute make it so
-		baseHREF = tinyMCE.settings['document_base_url'];
-		var h = document.location.href;
-		var p = h.indexOf('://');
-		if (p > 0 && document.location.protocol != "file:") {
-			p = h.indexOf('/', p + 3);
-			h = h.substring(0, p);
-
-			if (baseHREF.indexOf('://') == -1)
-				baseHREF = h + baseHREF;
-
-			tinyMCE.settings['document_base_url'] = baseHREF;
-			tinyMCE.settings['document_base_prefix'] = h;
-		}
-
-		// Trim away query part
-		if (baseHREF.indexOf('?') != -1)
-			baseHREF = baseHREF.substring(0, baseHREF.indexOf('?'));
-
-		this.settings['base_href'] = baseHREF.substring(0, baseHREF.lastIndexOf('/')) + "/";
-
-		theme = this.settings['theme'];
-		this.inlineStrict = 'A|BR|SPAN|BDO|MAP|OBJECT|IMG|TT|I|B|BIG|SMALL|EM|STRONG|DFN|CODE|Q|SAMP|KBD|VAR|CITE|ABBR|ACRONYM|SUB|SUP|#text|#comment';
-		this.inlineTransitional = 'A|BR|SPAN|BDO|OBJECT|APPLET|IMG|MAP|IFRAME|TT|I|B|U|S|STRIKE|BIG|SMALL|FONT|BASEFONT|EM|STRONG|DFN|CODE|Q|SAMP|KBD|VAR|CITE|ABBR|ACRONYM|SUB|SUP|INPUT|SELECT|TEXTAREA|LABEL|BUTTON|#text|#comment';
-		this.blockElms = 'H[1-6]|P|DIV|ADDRESS|PRE|FORM|TABLE|LI|OL|UL|TD|BLOCKQUOTE|CENTER|DL|DT|DD|DIR|FIELDSET|FORM|NOSCRIPT|NOFRAMES|MENU|ISINDEX|SAMP';
-		this.blockRegExp = new RegExp("^(" + this.blockElms + ")$", "i");
-		this.posKeyCodes = new Array(13,45,36,35,33,34,37,38,39,40);
-		this.uniqueURL = 'javascript:void(091039730);'; // Make unique URL non real URL
-		this.uniqueTag = '<div id="mceTMPElement" style="display: none">TMP</div>';
-		this.callbacks = new Array('onInit', 'getInfo', 'getEditorTemplate', 'setupContent', 'onChange', 'onPageLoad', 'handleNodeChange', 'initInstance', 'execCommand', 'getControlHTML', 'handleEvent', 'cleanup', 'removeInstance');
-
-		// Theme url
-		this.settings['theme_href'] = tinyMCE.baseURL + "/themes/" + theme;
-
-		if (!tinyMCE.isIE || tinyMCE.isOpera)
-			this.settings['force_br_newlines'] = false;
-
-		if (tinyMCE.getParam("popups_css", false)) {
-			var cssPath = tinyMCE.getParam("popups_css", "");
-
-			// Is relative
-			if (cssPath.indexOf('://') == -1 && cssPath.charAt(0) != '/')
-				this.settings['popups_css'] = this.documentBasePath + "/" + cssPath;
-			else
-				this.settings['popups_css'] = cssPath;
-		} else
-			this.settings['popups_css'] = tinyMCE.baseURL + "/themes/" + theme + "/css/editor_popup.css";
-
-		if (tinyMCE.getParam("editor_css", false)) {
-			var cssPath = tinyMCE.getParam("editor_css", "");
-
-			// Is relative
-			if (cssPath.indexOf('://') == -1 && cssPath.charAt(0) != '/')
-				this.settings['editor_css'] = this.documentBasePath + "/" + cssPath;
-			else
-				this.settings['editor_css'] = cssPath;
-		} else {
-			if (this.settings.editor_css != '')
-				this.settings['editor_css'] = tinyMCE.baseURL + "/themes/" + theme + "/css/editor_ui.css";
-		}
-
-		if (tinyMCE.settings['debug']) {
-			var msg = "Debug: \n";
-
-			msg += "baseURL: " + this.baseURL + "\n";
-			msg += "documentBasePath: " + this.documentBasePath + "\n";
-			msg += "content_css: " + this.settings['content_css'] + "\n";
-			msg += "popups_css: " + this.settings['popups_css'] + "\n";
-			msg += "editor_css: " + this.settings['editor_css'] + "\n";
-
-			alert(msg);
-		}
-
-		// Only do this once
-		if (this.configs.length == 0) {
-			if (typeof(TinyMCECompressed) == "undefined") {
-				tinyMCE.addEvent(window, "DOMContentLoaded", TinyMCE_Engine.prototype.onLoad);
-
-				if (tinyMCE.isRealIE) {
-					if (document.body)
-						tinyMCE.addEvent(document.body, "readystatechange", TinyMCE_Engine.prototype.onLoad);
-					else
-						tinyMCE.addEvent(document, "readystatechange", TinyMCE_Engine.prototype.onLoad);
-				}
-
-				tinyMCE.addEvent(window, "load", TinyMCE_Engine.prototype.onLoad);
-				tinyMCE._addUnloadEvents();
-			}
-		}
-
-		this.loadScript(tinyMCE.baseURL + '/themes/' + this.settings['theme'] + '/editor_template' + tinyMCE.srcMode + '.js');
-		this.loadScript(tinyMCE.baseURL + '/langs/' + this.settings['language'] +  '.js');
-		this.loadCSS(this.settings['editor_css']);
-
-		// Add plugins
-		var p = tinyMCE.getParam('plugins', '', true, ',');
-		if (p.length > 0) {
-			for (var i=0; i<p.length; i++) {
-				if (p[i].charAt(0) != '-')
-					this.loadScript(tinyMCE.baseURL + '/plugins/' + p[i] + '/editor_plugin' + tinyMCE.srcMode + '.js');
-			}
-		}
-
-		// Setup entities
-		if (tinyMCE.getParam('entity_encoding') == 'named') {
-			settings['cleanup_entities'] = new Array();
-			var entities = tinyMCE.getParam('entities', '', true, ',');
-			for (var i=0; i<entities.length; i+=2)
-				settings['cleanup_entities']['c' + entities[i]] = entities[i+1];
-		}
-
-		// Save away this config
-		settings['index'] = this.configs.length;
-		this.configs[this.configs.length] = settings;
-
-		// Start loading first one in chain
-		this.loadNextScript();
-
-		// Force flicker free CSS backgrounds in IE
-		if (this.isIE && !this.isOpera) {
-			try {
-				document.execCommand('BackgroundImageCache', false, true);
-			} catch (e) {
-			}
-		}
-
-		// Setup XML encoding regexps
-		this.xmlEncodeAposRe = new RegExp('[<>&"\']', 'g');
-		this.xmlEncodeRe = new RegExp('[<>&"]', 'g');
-//		this.xmlEncodeEnts = {'&':'&amp;','"':'&quot;',"'":'&#39;','<':'&lt;','>':'&gt;'};
+		return;
+	},
+
+	is : function(o, t) {
+		var n = typeof(o);
+
+		if (!t)
+			return n != 'undefined';
+
+		if (t == 'array' && (o instanceof Array))
+			return true;
+
+		return n == t;
 	},
 
-	_addUnloadEvents : function() {
-		if (tinyMCE.isIE) {
-			if (tinyMCE.settings['add_unload_trigger']) {
-				tinyMCE.addEvent(window, "unload", TinyMCE_Engine.prototype.unloadHandler);
-				tinyMCE.addEvent(window.document, "beforeunload", TinyMCE_Engine.prototype.unloadHandler);
+	// #if !jquery
+
+	each : function(o, cb, s) {
+		var n, l;
+
+		if (!o)
+			return 0;
+
+		s = s || o;
+
+		if (typeof(o.length) != 'undefined') {
+			// Indexed arrays, needed for Safari
+			for (n=0, l = o.length; n<l; n++) {
+				if (cb.call(s, o[n], n, o) === false)
+					return 0;
 			}
 		} else {
-			if (tinyMCE.settings['add_unload_trigger'])
-				tinyMCE.addEvent(window, "unload", function () {tinyMCE.triggerSave(true, true);});
-		}
-	},
-
-	_def : function(key, def_val, t) {
-		var v = tinyMCE.getParam(key, def_val);
-
-		v = t ? v.replace(/\s+/g, "") : v;
-
-		this.settings[key] = v;
-	},
-
-	hasPlugin : function(n) {
-		return typeof(this.plugins[n]) != "undefined" && this.plugins[n] != null;
-	},
-
-	addPlugin : function(n, p) {
-		var op = this.plugins[n];
-
-		// Use the previous plugin object base URL used when loading external plugins
-		p.baseURL = op ? op.baseURL : tinyMCE.baseURL + "/plugins/" + n;
-		this.plugins[n] = p;
-
-		this.loadNextScript();
-	},
-
-	setPluginBaseURL : function(n, u) {
-		var op = this.plugins[n];
-
-		if (op)
-			op.baseURL = u;
-		else
-			this.plugins[n] = {baseURL : u};
-	},
-
-	loadPlugin : function(n, u) {
-		u = u.indexOf('.js') != -1 ? u.substring(0, u.lastIndexOf('/')) : u;
-		u = u.charAt(u.length-1) == '/' ? u.substring(0, u.length-1) : u;
-		this.plugins[n] = {baseURL : u};
-		this.loadScript(u + "/editor_plugin" + (tinyMCE.srcMode ? '_src' : '') + ".js");
-	},
-
-	hasTheme : function(n) {
-		return typeof(this.themes[n]) != "undefined" && this.themes[n] != null;
-	},
-
-	addTheme : function(n, t) {
-		this.themes[n] = t;
-
-		this.loadNextScript();
-	},
-
-	addMenu : function(n, m) {
-		this.menus[n] = m;
-	},
-
-	hasMenu : function(n) {
-		return typeof(this.plugins[n]) != "undefined" && this.plugins[n] != null;
-	},
-
-	loadScript : function(url) {
-		var i;
-
-		for (i=0; i<this.loadedFiles.length; i++) {
-			if (this.loadedFiles[i] == url)
-				return;
-		}
-
-		if (tinyMCE.settings.strict_loading_mode)
-			this.pendingFiles[this.pendingFiles.length] = url;
-		else
-    {
-      document.write('<sc'+'ript language="javascript" type="text/javascript" src="' + url + '"></script>');
-    }
-
-		this.loadedFiles[this.loadedFiles.length] = url;
-	},
-
-	loadNextScript : function() {
-		var d = document, se;
-
-		if (!tinyMCE.settings.strict_loading_mode)
-			return;
-
-		if (this.loadingIndex < this.pendingFiles.length) {
-      try {
-        /*
-        se = d.createElementNS('http://www.w3.org/1999/xhtml', 'script');
-        se.setAttribute('language', 'javascript');
-        se.setAttribute('type', 'text/javascript');
-        se.setAttribute('src', this.pendingFiles[this.loadingIndex++]);
-        */
-        
-        se = d.createElement('script');
-        se.language = 'javascript';
-        se.type = 'text/javascript';
-        se.src = this.pendingFiles[this.loadingIndex++];
-  
-        d.getElementsByTagName("head")[0].appendChild(se);
-      } catch(e) {
-        var error = e.toString();
-        alert(error);
-      }
-		} else
-			this.loadingIndex = -1; // Done with loading
-	},
-
-	loadCSS : function(url) {
-		var ar = url.replace(/\s+/, '').split(',');
-		var lflen = 0, csslen = 0;
-		var skip = false;
-		var x = 0, i = 0, nl, le;
-
-		for (x = 0,csslen = ar.length; x<csslen; x++) {
-			if (ar[x] != null && ar[x] != 'null' && ar[x].length > 0) {
-				/* Make sure it doesn't exist. */
-				for (i=0, lflen=this.loadedFiles.length; i<lflen; i++) {
-					if (this.loadedFiles[i] == ar[x]) {
-						skip = true;
-						break;
-					}
-				}
-
-				if (!skip) {
-					if (tinyMCE.settings.strict_loading_mode) {
-						nl = document.getElementsByTagName("head");
-
-						le = document.createElement('link');
-						le.setAttribute('href', ar[x]);
-						le.setAttribute('rel', 'stylesheet');
-						le.setAttribute('type', 'text/css');
-
-						nl[0].appendChild(le);			
-					} else
-          {
-            document.write('<link href="' + ar[x] + '" rel="stylesheet" type="text/css" />');
-          }
-
-					this.loadedFiles[this.loadedFiles.length] = ar[x];
+			// Hashtables
+			for (n in o) {
+				if (o.hasOwnProperty(n)) {
+					if (cb.call(s, o[n], n, o) === false)
+						return 0;
 				}
 			}
 		}
-	},
-
-	importCSS : function(doc, css) {
-		var css_ary = css.replace(/\s+/, '').split(',');
-		var csslen, elm, headArr, x, css_file;
-
-		for (x = 0, csslen = css_ary.length; x<csslen; x++) {
-			css_file = css_ary[x];
-
-			if (css_file != null && css_file != 'null' && css_file.length > 0) {
-				// Is relative, make absolute
-				if (css_file.indexOf('://') == -1 && css_file.charAt(0) != '/')
-					css_file = this.documentBasePath + "/" + css_file;
-
-				if (typeof(doc.createStyleSheet) == "undefined") {
-					elm = doc.createElement("link");
-
-					elm.rel = "stylesheet";
-					elm.href = css_file;
-
-					if ((headArr = doc.getElementsByTagName("head")) != null && headArr.length > 0)
-						headArr[0].appendChild(elm);
-				} else
-					doc.createStyleSheet(css_file);
-			}
-		}
-	},
-
-	confirmAdd : function(e, settings) {
-		var elm = tinyMCE.isIE ? event.srcElement : e.target;
-		var elementId = elm.name ? elm.name : elm.id;
-
-		tinyMCE.settings = settings;
-
-		if (tinyMCE.settings['convert_on_click'] || (!elm.getAttribute('mce_noask') && confirm(tinyMCELang['lang_edit_confirm'])))
-			tinyMCE.addMCEControl(elm, elementId);
-
-		elm.setAttribute('mce_noask', 'true');
-	},
-
-	updateContent : function(form_element_name) {
-		// Find MCE instance linked to given form element and copy it's value
-		var formElement = document.getElementById(form_element_name);
-		for (var n in tinyMCE.instances) {
-			var inst = tinyMCE.instances[n];
-			if (!tinyMCE.isInstance(inst))
-				continue;
-
-			inst.switchSettings();
-
-			if (inst.formElement == formElement) {
-				var doc = inst.getDoc();
-		
-				tinyMCE._setHTML(doc, inst.formElement.value);
-
-				if (!tinyMCE.isIE)
-					doc.body.innerHTML = tinyMCE._cleanupHTML(inst, doc, this.settings, doc.body, inst.visualAid);
-			}
-		}
-	},
-
-	addMCEControl : function(replace_element, form_element_name, target_document) {
-		var id = "mce_editor_" + tinyMCE.idCounter++;
-    
-    var inst = new TinyMCE_Control(tinyMCE.settings);
-
-		inst.editorId = id;
-		this.instances[id] = inst;
-
-		inst._onAdd(replace_element, form_element_name, target_document);
-	},
-
-	removeInstance : function(ti) {
-		var t = [], n, i;
-
-		// Remove from instances
-		for (n in tinyMCE.instances) {
-			i = tinyMCE.instances[n];
-
-			if (tinyMCE.isInstance(i) && ti != i)
-					t[n] = i;
-		}
-
-		tinyMCE.instances = t;
-
-		// Remove from global undo/redo
-		n = [];
-		t = tinyMCE.undoLevels;
-
-		for (i=0; i<t.length; i++) {
-			if (t[i] != ti)
-				n.push(t[i]);
-		}
-
-		tinyMCE.undoLevels = n;
-		tinyMCE.undoIndex = n.length;
-
-		// Dispatch remove instance call
-		tinyMCE.dispatchCallback(ti, 'remove_instance_callback', 'removeInstance', ti);
-
-		return ti;
-	},
-
-	removeMCEControl : function(editor_id) {
-		var inst = tinyMCE.getInstanceById(editor_id), h, re, ot, tn;
-
-		if (inst) {
-			inst.switchSettings();
-
-			editor_id = inst.editorId;
-			h = tinyMCE.getContent(editor_id);
-
-			this.removeInstance(inst);
-
-			tinyMCE.selectedElement = null;
-			tinyMCE.selectedInstance = null;
-
-			// Remove element
-			re = document.getElementById(editor_id + "_parent");
-			ot = inst.oldTargetElement;
-			tn = ot.nodeName.toLowerCase();
-
-			if (tn == "textarea" || tn == "input") {
-				re.parentNode.removeChild(re);
-				ot.style.display = "inline";
-				ot.value = h;
-			} else {
-				ot.innerHTML = h;
-				ot.style.display = 'block';
-				re.parentNode.insertBefore(ot, re);
-				re.parentNode.removeChild(re);
-			}
-		}
-	},
-
-	triggerSave : function(skip_cleanup, skip_callback) {
-		var inst, n;
-
-		// Default to false
-		if (typeof(skip_cleanup) == "undefined")
-			skip_cleanup = false;
-
-		// Default to false
-		if (typeof(skip_callback) == "undefined")
-			skip_callback = false;
-
-		// Cleanup and set all form fields
-		for (n in tinyMCE.instances) {
-			inst = tinyMCE.instances[n];
-
-			if (!tinyMCE.isInstance(inst))
-				continue;
-
-			inst.triggerSave(skip_cleanup, skip_callback);
-		}
-	},
-
-	resetForm : function(form_index) {
-		var i, inst, n, formObj = document.forms[form_index];
-
-		for (n in tinyMCE.instances) {
-			inst = tinyMCE.instances[n];
-
-			if (!tinyMCE.isInstance(inst))
-				continue;
-
-			inst.switchSettings();
-
-			for (i=0; i<formObj.elements.length; i++) {
-				if (inst.formTargetElementId == formObj.elements[i].name)
-					inst.getBody().innerHTML = inst.startContent;
-			}
-		}
-	},
-
-	execInstanceCommand : function(editor_id, command, user_interface, value, focus) {
-		var inst = tinyMCE.getInstanceById(editor_id), r;
-
-		if (inst) {
-			r = inst.selection.getRng();
-
-			if (typeof(focus) == "undefined")
-				focus = true;
-
-			// IE bug lost focus on images in absolute divs Bug #1534575
-			if (focus && (!r || !r.item))
-				inst.contentWindow.focus();
-
-			// Reset design mode if lost
-			inst.autoResetDesignMode();
-
-			this.selectedElement = inst.getFocusElement();
-			inst.select();
-			tinyMCE.execCommand(command, user_interface, value);
-
-			// Cancel event so it doesn't call onbeforeonunlaod
-			if (tinyMCE.isIE && window.event != null)
-				tinyMCE.cancelEvent(window.event);
-		}
-	},
-
-	execCommand : function(command, user_interface, value) {
-		var inst = tinyMCE.selectedInstance;
-
-		// Default input
-		user_interface = user_interface ? user_interface : false;
-		value = value ? value : null;
-
-		if (inst)
-			inst.switchSettings();
-
-		switch (command) {
-			case "Undo":
-				if (this.getParam('custom_undo_redo_global')) {
-					if (this.undoIndex > 0) {
-						tinyMCE.nextUndoRedoAction = 'Undo';
-						inst = this.undoLevels[--this.undoIndex];
-						inst.select();
-
-						if (!tinyMCE.nextUndoRedoInstanceId)
-							inst.execCommand('Undo');
-					}
-				} else
-					inst.execCommand('Undo');
-				return true;
-
-			case "Redo":
-				if (this.getParam('custom_undo_redo_global')) {
-					if (this.undoIndex <= this.undoLevels.length - 1) {
-						tinyMCE.nextUndoRedoAction = 'Redo';
-						inst = this.undoLevels[this.undoIndex++];
-						inst.select();
-
-						if (!tinyMCE.nextUndoRedoInstanceId)
-							inst.execCommand('Redo');
-					}
-				} else
-					inst.execCommand('Redo');
-
-				return true;
-
-			case 'mceFocus':
-				var inst = tinyMCE.getInstanceById(value);
-				if (inst)
-					inst.getWin().focus();
-			return;
-
-			case "mceAddControl":
-			case "mceAddEditor":
-				tinyMCE.addMCEControl(tinyMCE._getElementById(value), value);
-				return;
-
-			case "mceAddFrameControl":
-				tinyMCE.addMCEControl(tinyMCE._getElementById(value['element'], value['document']), value['element'], value['document']);
-				return;
-
-			case "mceRemoveControl":
-			case "mceRemoveEditor":
-				tinyMCE.removeMCEControl(value);
-				return;
-
-			case "mceToggleEditor":
-				var inst = tinyMCE.getInstanceById(value), pe, te;
-
-				if (inst) {
-					pe = document.getElementById(inst.editorId + '_parent');
-					te = inst.oldTargetElement;
-
-					if (typeof(inst.enabled) == 'undefined')
-						inst.enabled = true;
-
-					inst.enabled = !inst.enabled;
-
-					if (!inst.enabled) {
-						pe.style.display = 'none';
-						te.value = inst.getHTML();
-						te.style.display = inst.oldTargetDisplay;
-						tinyMCE.dispatchCallback(inst, 'hide_instance_callback', 'hideInstance', inst);
-					} else {
-						pe.style.display = 'block';
-						te.style.display = 'none';
-						inst.setHTML(te.value);
-						inst.useCSS = false;
-						tinyMCE.dispatchCallback(inst, 'show_instance_callback', 'showInstance', inst);
-					}
-				} else
-					tinyMCE.addMCEControl(tinyMCE._getElementById(value), value);
-
-				return;
-
-			case "mceResetDesignMode":
-				// Resets the designmode state of the editors in Gecko
-				if (!tinyMCE.isIE) {
-					for (var n in tinyMCE.instances) {
-						if (!tinyMCE.isInstance(tinyMCE.instances[n]))
-							continue;
-
-						try {
-							tinyMCE.instances[n].getDoc().designMode = "on";
-						} catch (e) {
-							// Ignore any errors
-						}
-					}
-				}
-
-				return;
-		}
-
-		if (inst) {
-			inst.execCommand(command, user_interface, value);
-		} else if (tinyMCE.settings['focus_alert'])
-			alert(tinyMCELang['lang_focus_alert']);
-	},
-
-	_createIFrame : function(replace_element, doc, win) {
-		var iframe, id = replace_element.getAttribute("id");
-		var aw, ah;
-
-		if (typeof(doc) == "undefined")
-			doc = document;
-
-		if (typeof(win) == "undefined")
-			win = window;
-
-		iframe = doc.createElement("iframe");
-
-		aw = "" + tinyMCE.settings['area_width'];
-		ah = "" + tinyMCE.settings['area_height'];
-
-		if (aw.indexOf('%') == -1) {
-			aw = parseInt(aw);
-			aw = (isNaN(aw) || aw < 0) ? 300 : aw;
-			aw = aw + "px";
-		}
-
-		if (ah.indexOf('%') == -1) {
-			ah = parseInt(ah);
-			ah = (isNaN(ah) || ah < 0) ? 240 : ah;
-			ah = ah + "px";
-		}
-
-		iframe.setAttribute("id", id);
-		iframe.setAttribute("name", id);
-		iframe.setAttribute("class", "mceEditorIframe");
-		iframe.setAttribute("border", "0");
-		iframe.setAttribute("frameBorder", "0");
-		iframe.setAttribute("marginWidth", "0");
-		iframe.setAttribute("marginHeight", "0");
-		iframe.setAttribute("leftMargin", "0");
-		iframe.setAttribute("topMargin", "0");
-		iframe.setAttribute("width", aw);
-		iframe.setAttribute("height", ah);
-		iframe.setAttribute("allowtransparency", "true");
-		iframe.className = 'mceEditorIframe';
-
-		if (tinyMCE.settings["auto_resize"])
-			iframe.setAttribute("scrolling", "no");
-
-		// Must have a src element in MSIE HTTPs breaks aswell as absoute URLs
-		if (tinyMCE.isRealIE)
-			iframe.setAttribute("src", this.settings['default_document']);
-
-		iframe.style.width = aw;
-		iframe.style.height = ah;
-
-		// Ugly hack for Gecko problem in strict mode
-		if (tinyMCE.settings.strict_loading_mode)
-			iframe.style.marginBottom = '-5px';
-
-		// MSIE 5.0 issue
-		if (tinyMCE.isRealIE)
-			replace_element.outerHTML = iframe.outerHTML;
-		else
-			replace_element.parentNode.replaceChild(iframe, replace_element);
-
-		if (tinyMCE.isRealIE)
-			return win.frames[id];
-		else
-			return iframe;
-	},
-
-	setupContent : function(editor_id) {
-		var inst = tinyMCE.instances[editor_id], i;
-		var doc = inst.getDoc();
-		var head = doc.getElementsByTagName('head').item(0);
-		var content = inst.startContent;
-
-		// HTML values get XML encoded in strict mode
-		if (tinyMCE.settings.strict_loading_mode) {
-			content = content.replace(/&lt;/g, '<');
-			content = content.replace(/&gt;/g, '>');
-			content = content.replace(/&quot;/g, '"');
-			content = content.replace(/&amp;/g, '&');
-		}
-
-		tinyMCE.selectedInstance = inst;
-		inst.switchSettings();
-
-		// Not loaded correctly hit it again, Mozilla bug #997860
-		if (!tinyMCE.isIE && tinyMCE.getParam("setupcontent_reload", false) && doc.title != "blank_page") {
-			// This part will remove the designMode status
-			// Failes first time in Firefox 1.5b2 on Mac
-			try {doc.location.href = tinyMCE.baseURL + "/blank.htm";} catch (ex) {}
-			window.setTimeout("tinyMCE.setupContent('" + editor_id + "');", 1000);
-			return;
-		}
-
-		if (!head) {
-			window.setTimeout("tinyMCE.setupContent('" + editor_id + "');", 10);
-			return;
-		}
-
-		// Import theme specific content CSS the user specific
-		tinyMCE.importCSS(inst.getDoc(), tinyMCE.baseURL + "/themes/" + inst.settings['theme'] + "/css/editor_content.css");
-		tinyMCE.importCSS(inst.getDoc(), inst.settings['content_css']);
-		tinyMCE.dispatchCallback(inst, 'init_instance_callback', 'initInstance', inst);
-
-		// Setup keyboard shortcuts
-		if (tinyMCE.getParam('custom_undo_redo_keyboard_shortcuts')) {
-			inst.addShortcut('ctrl', 'z', 'lang_undo_desc', 'Undo');
-			inst.addShortcut('ctrl', 'y', 'lang_redo_desc', 'Redo');
-		}
-
-		// BlockFormat shortcuts keys
-		for (i=1; i<=6; i++)
-			inst.addShortcut('ctrl', '' + i, '', 'FormatBlock', false, '<h' + i + '>');
-
-		inst.addShortcut('ctrl', '7', '', 'FormatBlock', false, '<p>');
-		inst.addShortcut('ctrl', '8', '', 'FormatBlock', false, '<div>');
-		inst.addShortcut('ctrl', '9', '', 'FormatBlock', false, '<address>');
-
-		// Add default shortcuts for gecko
-		if (tinyMCE.isGecko) {
-			inst.addShortcut('ctrl', 'b', 'lang_bold_desc', 'Bold');
-			inst.addShortcut('ctrl', 'i', 'lang_italic_desc', 'Italic');
-			inst.addShortcut('ctrl', 'u', 'lang_underline_desc', 'Underline');
-		}
-
-		// Setup span styles
-		if (tinyMCE.getParam("convert_fonts_to_spans"))
-			inst.getBody().setAttribute('id', 'mceSpanFonts');
-
-		if (tinyMCE.settings['nowrap'])
-			doc.body.style.whiteSpace = "nowrap";
-
-		doc.body.dir = this.settings['directionality'];
-		doc.editorId = editor_id;
-
-		// Add on document element in Mozilla
-		if (!tinyMCE.isIE)
-			doc.documentElement.editorId = editor_id;
-
-		inst.setBaseHREF(tinyMCE.settings['base_href']);
-
-		// Replace new line characters to BRs
-		if (tinyMCE.settings['convert_newlines_to_brs']) {
-			content = tinyMCE.regexpReplace(content, "\r\n", "<br />", "gi");
-			content = tinyMCE.regexpReplace(content, "\r", "<br />", "gi");
-			content = tinyMCE.regexpReplace(content, "\n", "<br />", "gi");
-		}
-
-		// Open closed anchors
-	//	content = content.replace(new RegExp('<a(.*?)/>', 'gi'), '<a$1></a>');
-
-		// Call custom cleanup code
-		content = tinyMCE.storeAwayURLs(content);
-		content = tinyMCE._customCleanup(inst, "insert_to_editor", content);
-
-		if (tinyMCE.isIE) {
-			// Ugly!!!
-			window.setInterval('try{tinyMCE.getCSSClasses(tinyMCE.instances["' + editor_id + '"].getDoc(), "' + editor_id + '");}catch(e){}', 500);
-
-			if (tinyMCE.settings["force_br_newlines"])
-				doc.styleSheets[0].addRule("p", "margin: 0;");
-
-			var body = inst.getBody();
-			body.editorId = editor_id;
-		}
-
-		content = tinyMCE.cleanupHTMLCode(content);
-
-		// Fix for bug #958637
-		if (!tinyMCE.isIE) {
-			var contentElement = inst.getDoc().createElement("body");
-			var doc = inst.getDoc();
-
-			contentElement.innerHTML = content;
-
-			// Remove weridness!
-			if (tinyMCE.isGecko && tinyMCE.settings['remove_lt_gt'])
-				content = content.replace(new RegExp('&lt;&gt;', 'g'), "");
-
-			if (tinyMCE.settings['cleanup_on_startup'])
-				tinyMCE.setInnerHTML(inst.getBody(), tinyMCE._cleanupHTML(inst, doc, this.settings, contentElement));
-			else
-				tinyMCE.setInnerHTML(inst.getBody(), content);
-
-			tinyMCE.convertAllRelativeURLs(inst.getBody());
-		} else {
-			if (tinyMCE.settings['cleanup_on_startup']) {
-				tinyMCE._setHTML(inst.getDoc(), content);
-
-				// Produces permission denied error in MSIE 5.5
-				eval('try {tinyMCE.setInnerHTML(inst.getBody(), tinyMCE._cleanupHTML(inst, inst.contentDocument, this.settings, inst.getBody()));} catch(e) {}');
-			} else
-				tinyMCE._setHTML(inst.getDoc(), content);
-		}
-
-		// Fix for bug #957681
-		//inst.getDoc().designMode = inst.getDoc().designMode;
-
-		tinyMCE.handleVisualAid(inst.getBody(), true, tinyMCE.settings['visual'], inst);
-		tinyMCE.dispatchCallback(inst, 'setupcontent_callback', 'setupContent', editor_id, inst.getBody(), inst.getDoc());
-
-		// Re-add design mode on mozilla
-		if (!tinyMCE.isIE)
-			tinyMCE.addEventHandlers(inst);
-
-		// Add blur handler
-		if (tinyMCE.isIE) {
-			tinyMCE.addEvent(inst.getBody(), "blur", TinyMCE_Engine.prototype._eventPatch);
-			tinyMCE.addEvent(inst.getBody(), "beforedeactivate", TinyMCE_Engine.prototype._eventPatch); // Bug #1439953
-
-			// Workaround for drag drop/copy paste base href bug
-			if (!tinyMCE.isOpera) {
-				tinyMCE.addEvent(doc.body, "mousemove", TinyMCE_Engine.prototype.onMouseMove);
-				tinyMCE.addEvent(doc.body, "beforepaste", TinyMCE_Engine.prototype._eventPatch);
-				tinyMCE.addEvent(doc.body, "drop", TinyMCE_Engine.prototype._eventPatch);
-			}
-		}
-
-		// Trigger node change, this call locks buttons for tables and so forth
-		inst.select();
-		tinyMCE.selectedElement = inst.contentWindow.document.body;
-
-		// Call custom DOM cleanup
-		tinyMCE._customCleanup(inst, "insert_to_editor_dom", inst.getBody());
-		tinyMCE._customCleanup(inst, "setup_content_dom", inst.getBody());
-		tinyMCE._setEventsEnabled(inst.getBody(), false);
-		tinyMCE.cleanupAnchors(inst.getDoc());
-
-		if (tinyMCE.getParam("convert_fonts_to_spans"))
-			tinyMCE.convertSpansToFonts(inst.getDoc());
-
-		inst.startContent = tinyMCE.trim(inst.getBody().innerHTML);
-		inst.undoRedo.add({ content : inst.startContent });
-
-		// Cleanup any mess left from storyAwayURLs
-		if (tinyMCE.isGecko) {
-			// Remove mce_src from textnodes and comments
-			tinyMCE.selectNodes(inst.getBody(), function(n) {
-				if (n.nodeType == 3 || n.nodeType == 8)
-					n.nodeValue = n.nodeValue.replace(new RegExp('\\s(mce_src|mce_href)=\"[^\"]*\"', 'gi'), "");
-
-				return false;
-			});
-		}
-
-		// Remove Gecko spellchecking
-		if (tinyMCE.isGecko)
-			inst.getBody().spellcheck = tinyMCE.getParam("gecko_spellcheck");
-
-		// Cleanup any mess left from storyAwayURLs
-		tinyMCE._removeInternal(inst.getBody());
-
-		inst.select();
-		tinyMCE.triggerNodeChange(false, true);
-	},
-
-	storeAwayURLs : function(s) {
-		// Remove all mce_src, mce_href and replace them with new ones
-		// s = s.replace(new RegExp('mce_src\\s*=\\s*\"[^ >\"]*\"', 'gi'), '');
-		// s = s.replace(new RegExp('mce_href\\s*=\\s*\"[^ >\"]*\"', 'gi'), '');
-
-		if (!s.match(/(mce_src|mce_href)/gi, s)) {
-			s = s.replace(new RegExp('src\\s*=\\s*\"([^ >\"]*)\"', 'gi'), 'src="$1" mce_src="$1"');
-			s = s.replace(new RegExp('href\\s*=\\s*\"([^ >\"]*)\"', 'gi'), 'href="$1" mce_href="$1"');
-		}
-
-		return s;
-	},
-
-	_removeInternal : function(n) {
-		if (tinyMCE.isGecko) {
-			// Remove mce_src from textnodes and comments
-			tinyMCE.selectNodes(n, function(n) {
-				if (n.nodeType == 3 || n.nodeType == 8)
-					n.nodeValue = n.nodeValue.replace(new RegExp('\\s(mce_src|mce_href)=\"[^\"]*\"', 'gi'), "");
-
-				return false;
-			});
-		}
-	},
-
-	removeTinyMCEFormElements : function(form_obj) {
-		var i, elementId;
-
-		// Skip form element removal
-		if (!tinyMCE.getParam('hide_selects_on_submit'))
-			return;
-
-		// Check if form is valid
-		if (typeof(form_obj) == "undefined" || form_obj == null)
-			return;
-
-		// If not a form, find the form
-		if (form_obj.nodeName != "FORM") {
-			if (form_obj.form)
-				form_obj = form_obj.form;
-			else
-				form_obj = tinyMCE.getParentElement(form_obj, "form");
-		}
-
-		// Still nothing
-		if (form_obj == null)
-			return;
-
-		// Disable all UI form elements that TinyMCE created
-		for (i=0; i<form_obj.elements.length; i++) {
-			elementId = form_obj.elements[i].name ? form_obj.elements[i].name : form_obj.elements[i].id;
-
-			if (elementId.indexOf('mce_editor_') == 0)
-				form_obj.elements[i].disabled = true;
-		}
-	},
-
-	handleEvent : function(e) {
-		var inst = tinyMCE.selectedInstance;
-
-		// Remove odd, error
-		if (typeof(tinyMCE) == "undefined")
-			return true;
-
-		//tinyMCE.debug(e.type + " " + e.target.nodeName + " " + (e.relatedTarget ? e.relatedTarget.nodeName : ""));
-
-		if (tinyMCE.executeCallback(tinyMCE.selectedInstance, 'handle_event_callback', 'handleEvent', e))
-			return false;
-
-		switch (e.type) {
-			case "beforedeactivate": // Was added due to bug #1439953
-			case "blur":
-				if (tinyMCE.selectedInstance)
-					tinyMCE.selectedInstance.execCommand('mceEndTyping');
-
-				tinyMCE.hideMenus();
-
-				return;
-
-			// Workaround for drag drop/copy paste base href bug
-			case "drop":
-			case "beforepaste":
-				if (tinyMCE.selectedInstance)
-					tinyMCE.selectedInstance.setBaseHREF(null);
-
-				// Fixes odd MSIE bug where drag/droping elements in a iframe with height 100% breaks
-				// This logic forces the width/height to be in pixels while the user is drag/dropping
-				if (tinyMCE.isRealIE) {
-					var ife = tinyMCE.selectedInstance.iframeElement;
-
-					/*if (ife.style.width.indexOf('%') != -1) {
-						ife._oldWidth = ife.width.height;
-						ife.style.width = ife.clientWidth;
-					}*/
-
-					if (ife.style.height.indexOf('%') != -1) {
-						ife._oldHeight = ife.style.height;
-						ife.style.height = ife.clientHeight;
-					}
-				}
-
-				window.setTimeout("tinyMCE.selectedInstance.setBaseHREF(tinyMCE.settings['base_href']);tinyMCE._resetIframeHeight();", 1);
-				return;
-
-			case "submit":
-				tinyMCE.removeTinyMCEFormElements(tinyMCE.isMSIE ? window.event.srcElement : e.target);
-				tinyMCE.triggerSave();
-				tinyMCE.isNotDirty = true;
-				return;
-
-			case "reset":
-				var formObj = tinyMCE.isIE ? window.event.srcElement : e.target;
-
-				for (var i=0; i<document.forms.length; i++) {
-					if (document.forms[i] == formObj)
-						window.setTimeout('tinyMCE.resetForm(' + i + ');', 10);
-				}
-
-				return;
-
-			case "keypress":
-				if (inst && inst.handleShortcut(e))
-					return false;
-
-				if (e.target.editorId) {
-					tinyMCE.instances[e.target.editorId].select();
-				} else {
-					if (e.target.ownerDocument.editorId)
-						tinyMCE.instances[e.target.ownerDocument.editorId].select();
-				}
-
-				if (tinyMCE.selectedInstance)
-					tinyMCE.selectedInstance.switchSettings();
-
-				// Insert P element
-				if ((tinyMCE.isGecko || tinyMCE.isOpera || tinyMCE.isSafari) && tinyMCE.settings['force_p_newlines'] && e.keyCode == 13 && !e.shiftKey) {
-					// Insert P element instead of BR
-					if (TinyMCE_ForceParagraphs._insertPara(tinyMCE.selectedInstance, e)) {
-						// Cancel event
-						tinyMCE.execCommand("mceAddUndoLevel");
-						return tinyMCE.cancelEvent(e);
-					}
-				}
-
-				// Handle backspace
-				if ((tinyMCE.isGecko && !tinyMCE.isSafari) && tinyMCE.settings['force_p_newlines'] && (e.keyCode == 8 || e.keyCode == 46) && !e.shiftKey) {
-					// Insert P element instead of BR
-					if (TinyMCE_ForceParagraphs._handleBackSpace(tinyMCE.selectedInstance, e.type)) {
-						// Cancel event
-						tinyMCE.execCommand("mceAddUndoLevel");
-						return tinyMCE.cancelEvent(e);
-					}
-				}
-
-				// Return key pressed
-				if (tinyMCE.isIE && tinyMCE.settings['force_br_newlines'] && e.keyCode == 13) {
-					if (e.target.editorId)
-						tinyMCE.instances[e.target.editorId].select();
-
-					if (tinyMCE.selectedInstance) {
-						var sel = tinyMCE.selectedInstance.getDoc().selection;
-						var rng = sel.createRange();
-
-						if (tinyMCE.getParentElement(rng.parentElement(), "li") != null)
-							return false;
-
-						// Cancel event
-						e.returnValue = false;
-						e.cancelBubble = true;
-
-						// Insert BR element
-						rng.pasteHTML("<br />");
-						rng.collapse(false);
-						rng.select();
-
-						tinyMCE.execCommand("mceAddUndoLevel");
-						tinyMCE.triggerNodeChange(false);
-						return false;
-					}
-				}
-
-				// Backspace or delete
-				if (e.keyCode == 8 || e.keyCode == 46) {
-					tinyMCE.selectedElement = e.target;
-					tinyMCE.linkElement = tinyMCE.getParentElement(e.target, "a");
-					tinyMCE.imgElement = tinyMCE.getParentElement(e.target, "img");
-					tinyMCE.triggerNodeChange(false);
-				}
-
-				return false;
-			break;
-
-			case "keyup":
-			case "keydown":
-				tinyMCE.hideMenus();
-				tinyMCE.hasMouseMoved = false;
-
-				if (inst && inst.handleShortcut(e))
-					return false;
-
-				if (e.target.editorId)
-					tinyMCE.instances[e.target.editorId].select();
-
-				if (tinyMCE.selectedInstance)
-					tinyMCE.selectedInstance.switchSettings();
-
-				var inst = tinyMCE.selectedInstance;
-
-				// Handle backspace
-				if (tinyMCE.isGecko && tinyMCE.settings['force_p_newlines'] && (e.keyCode == 8 || e.keyCode == 46) && !e.shiftKey) {
-					// Insert P element instead of BR
-					if (TinyMCE_ForceParagraphs._handleBackSpace(tinyMCE.selectedInstance, e.type)) {
-						// Cancel event
-						tinyMCE.execCommand("mceAddUndoLevel");
-						e.preventDefault();
-						return false;
-					}
-				}
-
-				tinyMCE.selectedElement = null;
-				tinyMCE.selectedNode = null;
-				var elm = tinyMCE.selectedInstance.getFocusElement();
-				tinyMCE.linkElement = tinyMCE.getParentElement(elm, "a");
-				tinyMCE.imgElement = tinyMCE.getParentElement(elm, "img");
-				tinyMCE.selectedElement = elm;
-
-				// Update visualaids on tabs
-				if (tinyMCE.isGecko && e.type == "keyup" && e.keyCode == 9)
-					tinyMCE.handleVisualAid(tinyMCE.selectedInstance.getBody(), true, tinyMCE.settings['visual'], tinyMCE.selectedInstance);
-
-				// Fix empty elements on return/enter, check where enter occured
-				if (tinyMCE.isIE && e.type == "keydown" && e.keyCode == 13)
-					tinyMCE.enterKeyElement = tinyMCE.selectedInstance.getFocusElement();
-
-				// Fix empty elements on return/enter
-				if (tinyMCE.isIE && e.type == "keyup" && e.keyCode == 13) {
-					var elm = tinyMCE.enterKeyElement;
-					if (elm) {
-						var re = new RegExp('^HR|IMG|BR$','g'); // Skip these
-						var dre = new RegExp('^H[1-6]$','g'); // Add double on these
-
-						if (!elm.hasChildNodes() && !re.test(elm.nodeName)) {
-							if (dre.test(elm.nodeName))
-								elm.innerHTML = "&nbsp;&nbsp;";
-							else
-								elm.innerHTML = "&nbsp;";
-						}
-					}
-				}
-
-				// Check if it's a position key
-				var keys = tinyMCE.posKeyCodes;
-				var posKey = false;
-				for (var i=0; i<keys.length; i++) {
-					if (keys[i] == e.keyCode) {
-						posKey = true;
-						break;
-					}
-				}
-
-				// MSIE custom key handling
-				if (tinyMCE.isIE && tinyMCE.settings['custom_undo_redo']) {
-					var keys = new Array(8,46); // Backspace,Delete
-
-					for (var i=0; i<keys.length; i++) {
-						if (keys[i] == e.keyCode) {
-							if (e.type == "keyup")
-								tinyMCE.triggerNodeChange(false);
-						}
-					}
-				}
-
-				// If Ctrl key
-				if (e.keyCode == 17)
-					return true;
-
-				// Handle Undo/Redo when typing content
-
-				if (tinyMCE.isGecko) {
-					// Start typing (not a position key or ctrl key, but ctrl+x and ctrl+p is ok)
-					if (!posKey && e.type == "keyup" && !e.ctrlKey || (e.ctrlKey && (e.keyCode == 86 || e.keyCode == 88)))
-						tinyMCE.execCommand("mceStartTyping");
-				} else {
-					// IE seems to be working better with this setting
-					if (!posKey && e.type == "keyup")
-						tinyMCE.execCommand("mceStartTyping");
-				}
-
-				// Store undo bookmark
-				if (e.type == "keydown" && (posKey || e.ctrlKey) && inst)
-					inst.undoBookmark = inst.selection.getBookmark();
-
-				// End typing (position key) or some Ctrl event
-				if (e.type == "keyup" && (posKey || e.ctrlKey))
-					tinyMCE.execCommand("mceEndTyping");
-
-				if (posKey && e.type == "keyup")
-					tinyMCE.triggerNodeChange(false);
-
-				if (tinyMCE.isIE && e.ctrlKey)
-					window.setTimeout('tinyMCE.triggerNodeChange(false);', 1);
-			break;
-
-			case "mousedown":
-			case "mouseup":
-			case "click":
-			case "dblclick":
-			case "focus":
-				tinyMCE.hideMenus();
-
-				if (tinyMCE.selectedInstance) {
-					tinyMCE.selectedInstance.switchSettings();
-					tinyMCE.selectedInstance.isFocused = true;
-				}
-
-				// Check instance event trigged on
-				var targetBody = tinyMCE.getParentElement(e.target, "html");
-				for (var instanceName in tinyMCE.instances) {
-					if (!tinyMCE.isInstance(tinyMCE.instances[instanceName]))
-						continue;
-
-					var inst = tinyMCE.instances[instanceName];
-
-					// Reset design mode if lost (on everything just in case)
-					inst.autoResetDesignMode();
-
-					// Use HTML element since users might click outside of body element
-					if (inst.getBody().parentNode == targetBody) {
-						inst.select();
-						tinyMCE.selectedElement = e.target;
-						tinyMCE.linkElement = tinyMCE.getParentElement(tinyMCE.selectedElement, "a");
-						tinyMCE.imgElement = tinyMCE.getParentElement(tinyMCE.selectedElement, "img");
-						break;
-					}
-				}
-
-				// Add first bookmark location
-				if (!tinyMCE.selectedInstance.undoRedo.undoLevels[0].bookmark && (e.type == "mouseup" || e.type == "dblclick"))
-					tinyMCE.selectedInstance.undoRedo.undoLevels[0].bookmark = tinyMCE.selectedInstance.selection.getBookmark();
-
-				// Reset selected node
-				if (e.type != "focus")
-					tinyMCE.selectedNode = null;
-
-				tinyMCE.triggerNodeChange(false);
-				tinyMCE.execCommand("mceEndTyping");
-
-				if (e.type == "mouseup")
-					tinyMCE.execCommand("mceAddUndoLevel");
-
-				// Just in case
-				if (!tinyMCE.selectedInstance && e.target.editorId)
-					tinyMCE.instances[e.target.editorId].select();
-
-				return false;
-			break;
-		}
-	},
-
-	getButtonHTML : function(id, lang, img, cmd, ui, val) {
-		var h = '', m, x, io = '';
-
-		cmd = 'tinyMCE.execInstanceCommand(\'{$editor_id}\',\'' + cmd + '\'';
-
-		if (typeof(ui) != "undefined" && ui != null)
-			cmd += ',' + ui;
-
-		if (typeof(val) != "undefined" && val != null)
-			cmd += ",'" + val + "'";
-
-		cmd += ');';
-
-		// Patch for IE7 bug with hover out not restoring correctly
-		if (tinyMCE.isRealIE)
-			io = 'onmouseover="tinyMCE.lastHover = this;"';
-
-		// Use tilemaps when enabled and found and never in MSIE since it loads the tile each time from cache if cahce is disabled
-		if (tinyMCE.getParam('button_tile_map') && (!tinyMCE.isIE || tinyMCE.isOpera) && (m = this.buttonMap[id]) != null && (tinyMCE.getParam("language") == "en" || img.indexOf('$lang') == -1)) {
-			// Tiled button
-			x = 0 - (m * 20) == 0 ? '0' : 0 - (m * 20);
-			h += '<a id="{$editor_id}_' + id + '" href="javascript:' + cmd + '" onclick="' + cmd + 'return false;" onmousedown="return false;" ' + io + ' class="mceTiledButton mceButtonNormal" target="_self">';
-			h += '<img src="{$themeurl}/images/spacer.gif" style="background-position: ' + x + 'px 0" title="{$' + lang + '}" />';
-			h += '</a>';
-		} else {
-			// Normal button
-			h += '<a id="{$editor_id}_' + id + '" href="javascript:' + cmd + '" onclick="' + cmd + 'return false;" onmousedown="return false;" ' + io + ' class="mceButtonNormal" target="_self">';
-			h += '<img src="' + img + '" title="{$' + lang + '}" />';
-			h += '</a>';
-		}
-
-		return h;
+
+		return 1;
 	},
 
-	getMenuButtonHTML : function(id, lang, img, mcmd, cmd, ui, val) {
-		var h = '', m, x;
-
-		mcmd = 'tinyMCE.execInstanceCommand(\'{$editor_id}\',\'' + mcmd + '\');';
-		cmd = 'tinyMCE.execInstanceCommand(\'{$editor_id}\',\'' + cmd + '\'';
-
-		if (typeof(ui) != "undefined" && ui != null)
-			cmd += ',' + ui;
-
-		if (typeof(val) != "undefined" && val != null)
-			cmd += ",'" + val + "'";
-
-		cmd += ');';
-
-		// Use tilemaps when enabled and found and never in MSIE since it loads the tile each time from cache if cahce is disabled
-		if (tinyMCE.getParam('button_tile_map') && (!tinyMCE.isIE || tinyMCE.isOpera) && (m = tinyMCE.buttonMap[id]) != null && (tinyMCE.getParam("language") == "en" || img.indexOf('$lang') == -1)) {
-			x = 0 - (m * 20) == 0 ? '0' : 0 - (m * 20);
-
-			if (tinyMCE.isRealIE)
-				h += '<span id="{$editor_id}_' + id + '" class="mceMenuButton" onmouseover="tinyMCE._menuButtonEvent(\'over\',this);tinyMCE.lastHover = this;" onmouseout="tinyMCE._menuButtonEvent(\'out\',this);">';
-			else
-				h += '<span id="{$editor_id}_' + id + '" class="mceMenuButton">';
-
-			h += '<a href="javascript:' + cmd + '" onclick="' + cmd + 'return false;" onmousedown="return false;" class="mceTiledButton mceMenuButtonNormal" target="_self">';
-			h += '<img src="{$themeurl}/images/spacer.gif" style="width: 20px; height: 20px; background-position: ' + x + 'px 0" title="{$' + lang + '}" /></a>';
-			h += '<a href="javascript:' + mcmd + '" onclick="' + mcmd + 'return false;" onmousedown="return false;"><img src="{$themeurl}/images/button_menu.gif" title="{$' + lang + '}" class="mceMenuButton" />';
-			h += '</a></span>';
-		} else {
-			if (tinyMCE.isRealIE)
-				h += '<span id="{$editor_id}_' + id + '" dir="ltr" class="mceMenuButton" onmouseover="tinyMCE._menuButtonEvent(\'over\',this);tinyMCE.lastHover = this;" onmouseout="tinyMCE._menuButtonEvent(\'out\',this);">';
-			else
-				h += '<span id="{$editor_id}_' + id + '" dir="ltr" class="mceMenuButton">';
-
-			h += '<a href="javascript:' + cmd + '" onclick="' + cmd + 'return false;" onmousedown="return false;" class="mceMenuButtonNormal" target="_self">';
-			h += '<img src="' + img + '" title="{$' + lang + '}" /></a>';
-			h += '<a href="javascript:' + mcmd + '" onclick="' + mcmd + 'return false;" onmousedown="return false;"><img src="{$themeurl}/images/button_menu.gif" title="{$' + lang + '}" class="mceMenuButton" />';
-			h += '</a></span>';
-		}
-
-		return h;
-	},
-
-	_menuButtonEvent : function(e, o) {
-		if (o.className == 'mceMenuButtonFocus')
-			return;
-
-		if (e == 'over')
-			o.className = o.className + ' mceMenuHover';
-		else
-			o.className = o.className.replace(/\s.*$/, '');
-	},
-
-	addButtonMap : function(m) {
-		var i, a = m.replace(/\s+/, '').split(',');
-
-		for (i=0; i<a.length; i++)
-			this.buttonMap[a[i]] = i;
-	},
-
-	submitPatch : function() {
-		tinyMCE.removeTinyMCEFormElements(this);
-		tinyMCE.triggerSave();
-		tinyMCE.isNotDirty = true;
-		this.mceOldSubmit();
-	},
-
-	onLoad : function() {
-		var r;
-
-		// Wait for everything to be loaded first
-		if (tinyMCE.settings.strict_loading_mode && this.loadingIndex != -1) {
-			window.setTimeout('tinyMCE.onLoad();', 1);
-			return;
-		}
-
-		if (tinyMCE.isRealIE)
-    {
-      try 
-      {
-        if ( typeof(window.event) == 'object' && window.event != null )
-        {
-          try
-          {
-            if ( window.event.type == "onreadystatechange" )
-            {
-              try
-              {
-                if ( document.readyState != "complete" )
-                {
-                  return true;
-                }
-              }
-              catch(e)
-              {
-                alert('inner error: ' + e.description);
-              }
-            }
-          }
-          catch(e)
-          {
-            alert('middle error: ' + e.description);
-          }
-        }
-      }
-      catch(e)
-      {
-        alert('Outer error: ' + e.description);
-      }
-    }
-
-		if (tinyMCE.isLoaded)
-			return true;
-
-		tinyMCE.isLoaded = true;
-
-		// IE produces JS error if TinyMCE is placed in a frame
-		// It seems to have something to do with the selection not beeing
-		// correctly initialized in IE so this hack solves the problem
-		if (tinyMCE.isRealIE && document.body) {
-			r = document.body.createTextRange();
-			r.collapse(true);
-			r.select();
-		}
-
-		tinyMCE.dispatchCallback(null, 'onpageload', 'onPageLoad');
-
-		for (var c=0; c<tinyMCE.configs.length; c++) {
-			tinyMCE.settings = tinyMCE.configs[c];
-
-			var selector = tinyMCE.getParam("editor_selector");
-			var deselector = tinyMCE.getParam("editor_deselector");
-			var elementRefAr = new Array();
-
-			// Add submit triggers
-			if (document.forms && tinyMCE.settings['add_form_submit_trigger'] && !tinyMCE.submitTriggers) {
-				for (var i=0; i<document.forms.length; i++) {
-					var form = document.forms[i];
-
-					tinyMCE.addEvent(form, "submit", TinyMCE_Engine.prototype.handleEvent);
-					tinyMCE.addEvent(form, "reset", TinyMCE_Engine.prototype.handleEvent);
-					tinyMCE.submitTriggers = true; // Do it only once
-
-					// Patch the form.submit function
-					if (tinyMCE.settings['submit_patch']) {
-						try {
-							form.mceOldSubmit = form.submit;
-							form.submit = TinyMCE_Engine.prototype.submitPatch;
-						} catch (e) {
-							// Do nothing
-						}
-					}
-				}
-			}
-
-			// Add editor instances based on mode
-			var mode = tinyMCE.settings['mode'];
-			switch (mode) {
-				case "exact":
-					var elements = tinyMCE.getParam('elements', '', true, ',');
-
-					for (var i=0; i<elements.length; i++) {
-						var element = tinyMCE._getElementById(elements[i]);
-						var trigger = element ? element.getAttribute(tinyMCE.settings['textarea_trigger']) : "";
-
-						if (new RegExp('\\b' + deselector + '\\b').test(tinyMCE.getAttrib(element, "class")))
-							continue;
-
-						if (trigger == "false")
-							continue;
-
-						if ((tinyMCE.settings['ask'] || tinyMCE.settings['convert_on_click']) && element) {
-							elementRefAr[elementRefAr.length] = element;
-							continue;
-						}
-
-						if (element)
-							tinyMCE.addMCEControl(element, elements[i]);
-						else if (tinyMCE.settings['debug'])
-							alert("Error: Could not find element by id or name: " + elements[i]);
-					}
-				break;
-
-				case "specific_textareas":
-				case "textareas":
-					var nodeList = document.getElementsByTagName("textarea");
-
-					for (var i=0; i<nodeList.length; i++) {
-						var elm = nodeList.item(i);
-						var trigger = elm.getAttribute(tinyMCE.settings['textarea_trigger']);
-
-						if (selector != '' && !new RegExp('\\b' + selector + '\\b').test(tinyMCE.getAttrib(elm, "class")))
-							continue;
-
-						if (selector != '')
-							trigger = selector != "" ? "true" : "";
-
-						if (new RegExp('\\b' + deselector + '\\b').test(tinyMCE.getAttrib(elm, "class")))
-							continue;
-
-						if ((mode == "specific_textareas" && trigger == "true") || (mode == "textareas" && trigger != "false"))
-							elementRefAr[elementRefAr.length] = elm;
-					}
-				break;
-			}
-
-			for (var i=0; i<elementRefAr.length; i++) {
-				var element = elementRefAr[i];
-				var elementId = element.name ? element.name : element.id;
-
-				if (tinyMCE.settings['ask'] || tinyMCE.settings['convert_on_click']) {
-					// Focus breaks in Mozilla
-					if (tinyMCE.isGecko) {
-						var settings = tinyMCE.settings;
-
-						tinyMCE.addEvent(element, "focus", function (e) {window.setTimeout(function() {TinyMCE_Engine.prototype.confirmAdd(e, settings);}, 10);});
-
-						if (element.nodeName != "TEXTAREA" && element.nodeName != "INPUT")
-							tinyMCE.addEvent(element, "click", function (e) {window.setTimeout(function() {TinyMCE_Engine.prototype.confirmAdd(e, settings);}, 10);});
-						// tinyMCE.addEvent(element, "mouseover", function (e) {window.setTimeout(function() {TinyMCE_Engine.prototype.confirmAdd(e, settings);}, 10);});
-					} else {
-						var settings = tinyMCE.settings;
-
-						tinyMCE.addEvent(element, "focus", function () { TinyMCE_Engine.prototype.confirmAdd(null, settings); });
-						tinyMCE.addEvent(element, "click", function () { TinyMCE_Engine.prototype.confirmAdd(null, settings); });
-						// tinyMCE.addEvent(element, "mouseenter", function () { TinyMCE_Engine.prototype.confirmAdd(null, settings); });
-					}
-				} else
-					tinyMCE.addMCEControl(element, elementId);
-			}
-
-			// Handle auto focus
-			if (tinyMCE.settings['auto_focus']) {
-				window.setTimeout(function () {
-					var inst = tinyMCE.getInstanceById(tinyMCE.settings['auto_focus']);
-					inst.selection.selectNode(inst.getBody(), true, true);
-					inst.contentWindow.focus();
-				}, 100);
-			}
-
-			tinyMCE.dispatchCallback(null, 'oninit', 'onInit');
-		}
-	},
-
-	isInstance : function(o) {
-		return o != null && typeof(o) == "object" && o.isTinyMCE_Control;
-	},
-
-	getParam : function(name, default_value, strip_whitespace, split_chr) {
-		var value = (typeof(this.settings[name]) == "undefined") ? default_value : this.settings[name];
-
-		// Fix bool values
-		if (value == "true" || value == "false")
-			return (value == "true");
-
-		if (strip_whitespace)
-			value = tinyMCE.regexpReplace(value, "[ \t\r\n]", "") + '';
-
-		if (typeof(split_chr) != "undefined" && split_chr != null) {
-			value = value.split(split_chr);
-			var outArray = new Array();
-
-			for (var i=0; i<value.length; i++) {
-				if (value[i] && value[i] != "")
-					outArray[outArray.length] = value[i];
-			}
-
-			value = outArray;
-		}
-
-		return value;
-	},
-
-	getLang : function(name, default_value, parse_entities, va) {
-		var v = (typeof(tinyMCELang[name]) == "undefined") ? default_value : tinyMCELang[name], n;
-
-		if (parse_entities)
-			v = tinyMCE.entityDecode(v);
-
-		if (va) {
-			for (n in va)
-				v = this.replaceVar(v, n, va[n]);
-		}
-
-		return v;
-	},
-
-	entityDecode : function(s) {
-		var e = document.createElement("div");
-
-		e.innerHTML = s;
-
-		return e.firstChild.nodeValue;
-	},
-
-	addToLang : function(prefix, ar) {
-		for (var key in ar) {
-			if (typeof(ar[key]) == 'function')
-				continue;
-
-			tinyMCELang[(key.indexOf('lang_') == -1 ? 'lang_' : '') + (prefix != '' ? (prefix + "_") : '') + key] = ar[key];
-		}
-
-		this.loadNextScript();
-
-	//	for (var key in ar)
-	//		tinyMCELang[(key.indexOf('lang_') == -1 ? 'lang_' : '') + (prefix != '' ? (prefix + "_") : '') + key] = "|" + ar[key] + "|";
-	},
-
-	triggerNodeChange : function(focus, setup_content) {
-		var elm, inst, editorId, undoIndex = -1, undoLevels = -1, doc, anySelection = false, st;
-
-		if (tinyMCE.selectedInstance) {
-			inst = tinyMCE.selectedInstance;
-			elm = (typeof(setup_content) != "undefined" && setup_content) ? tinyMCE.selectedElement : inst.getFocusElement();
-
-/*			if (elm == inst.lastTriggerEl)
-				return;
-
-			inst.lastTriggerEl = elm;*/
-
-			editorId = inst.editorId;
-			st = inst.selection.getSelectedText();
-
-			if (tinyMCE.settings.auto_resize)
-				inst.resizeToContent();
-
-			if (setup_content && tinyMCE.isGecko && inst.isHidden())
-				elm = inst.getBody();
-
-			inst.switchSettings();
-
-			if (tinyMCE.selectedElement)
-				anySelection = (tinyMCE.selectedElement.nodeName.toLowerCase() == "img") || (st && st.length > 0);
-
-			if (tinyMCE.settings['custom_undo_redo']) {
-				undoIndex = inst.undoRedo.undoIndex;
-				undoLevels = inst.undoRedo.undoLevels.length;
-			}
-
-			tinyMCE.dispatchCallback(inst, 'handle_node_change_callback', 'handleNodeChange', editorId, elm, undoIndex, undoLevels, inst.visualAid, anySelection, setup_content);
-		}
-
-		if (this.selectedInstance && (typeof(focus) == "undefined" || focus))
-			this.selectedInstance.contentWindow.focus();
-	},
-
-	_customCleanup : function(inst, type, content) {
-		var pl, po, i;
-
-		// Call custom cleanup
-		var customCleanup = tinyMCE.settings['cleanup_callback'];
-		if (customCleanup != "" && eval("typeof(" + customCleanup + ")") != "undefined")
-			content = eval(customCleanup + "(type, content, inst);");
-
-		// Trigger theme cleanup
-		po = tinyMCE.themes[tinyMCE.settings['theme']];
-		if (po && po.cleanup)
-			content = po.cleanup(type, content, inst);
-
-		// Trigger plugin cleanups
-		pl = inst.plugins;
-		for (i=0; i<pl.length; i++) {
-			po = tinyMCE.plugins[pl[i]];
-
-			if (po && po.cleanup)
-				content = po.cleanup(type, content, inst);
-		}
-
-		return content;
-	},
-
-	setContent : function(h) {
-		if (tinyMCE.selectedInstance) {
-			tinyMCE.selectedInstance.execCommand('mceSetContent', false, h);
-			tinyMCE.selectedInstance.repaint();
-		}
-	},
-
-	importThemeLanguagePack : function(name) {
-		if (typeof(name) == "undefined")
-			name = tinyMCE.settings['theme'];
-
-		tinyMCE.loadScript(tinyMCE.baseURL + '/themes/' + name + '/langs/' + tinyMCE.settings['language'] + '.js');
-	},
-
-	importPluginLanguagePack : function(name) {
-		var b = tinyMCE.baseURL + '/plugins/' + name;
-
-		if (this.plugins[name])
-			b = this.plugins[name].baseURL;
-
-		tinyMCE.loadScript(b + '/langs/' + tinyMCE.settings['language'] +  '.js');
-	},
-
-	applyTemplate : function(h, as) {
-		return h.replace(new RegExp('\\{\\$([a-z0-9_]+)\\}', 'gi'), function(m, s) {
-			if (s.indexOf('lang_') == 0 && tinyMCELang[s])
-				return tinyMCELang[s];
-
-			if (as && as[s])
-				return as[s];
-
-			if (tinyMCE.settings[s])
-				return tinyMCE.settings[s];
-
-			if (m == 'themeurl')
-				return tinyMCE.themeURL;
-
-			return m;
+	map : function(a, f) {
+		var o = [];
+
+		tinymce.each(a, function(v) {
+			o.push(f(v));
 		});
-	},
-
-	replaceVar : function(h, r, v) {
-		return h.replace(new RegExp('{\\\$' + r + '}', 'g'), v);
+
+		return o;
 	},
 
-	openWindow : function(template, args) {
-		var html, width, height, x, y, resizable, scrollbars, url;
-
-		args = !args ? {} : args;
-
-		args['mce_template_file'] = template['file'];
-		args['mce_width'] = template['width'];
-		args['mce_height'] = template['height'];
-		tinyMCE.windowArgs = args;
-
-		html = template['html'];
-		if (!(width = parseInt(template['width'])))
-			width = 320;
-
-		if (!(height = parseInt(template['height'])))
-			height = 200;
-
-		// Add to height in M$ due to SP2 WHY DON'T YOU GUYS IMPLEMENT innerWidth of windows!!
-		if (tinyMCE.isIE)
-			height += 40;
-		else
-			height += 20;
-
-		x = parseInt(screen.width / 2.0) - (width / 2.0);
-		y = parseInt(screen.height / 2.0) - (height / 2.0);
-
-		resizable = (args && args['resizable']) ? args['resizable'] : "no";
-		scrollbars = (args && args['scrollbars']) ? args['scrollbars'] : "no";
-
-		if (template['file'].charAt(0) != '/' && template['file'].indexOf('://') == -1)
-			url = tinyMCE.baseURL + "/themes/" + tinyMCE.getParam("theme") + "/" + template['file'];
-		else
-			url = template['file'];
-
-		// Replace all args as variables in URL
-		for (var name in args) {
-			if (typeof(args[name]) == 'function')
-				continue;
-
-			url = tinyMCE.replaceVar(url, name, escape(args[name]));
-		}
-
-		if (html) {
-			html = tinyMCE.replaceVar(html, "css", this.settings['popups_css']);
-			html = tinyMCE.applyTemplate(html, args);
-
-			var win = window.open("", "mcePopup" + new Date().getTime(), "top=" + y + ",left=" + x + ",scrollbars=" + scrollbars + ",dialog=yes,minimizable=" + resizable + ",modal=yes,width=" + width + ",height=" + height + ",resizable=" + resizable);
-			if (win == null) {
-				alert(tinyMCELang['lang_popup_blocked']);
-				return;
-			}
-
-      //alert('docwrite 2');
-			win.document.write(html);
-			win.document.close();
-			win.resizeTo(width, height);
-			win.focus();
-		} else {
-			if ((tinyMCE.isRealIE) && resizable != 'yes' && tinyMCE.settings["dialog_type"] == "modal") {
-				height += 10;
-
-				var features = "resizable:" + resizable 
-					+ ";scroll:"
-					+ scrollbars + ";status:yes;center:yes;help:no;dialogWidth:"
-					+ width + "px;dialogHeight:" + height + "px;";
-
-				window.showModalDialog(url, window, features);
-			} else {
-				var modal = (resizable == "yes") ? "no" : "yes";
-
-				if (tinyMCE.isGecko && tinyMCE.isMac)
-					modal = "no";
-
-				if (template['close_previous'] != "no")
-					try {tinyMCE.lastWindow.close();} catch (ex) {}
-
-				var win = window.open(url, "mcePopup" + new Date().getTime(), "top=" + y + ",left=" + x + ",scrollbars=" + scrollbars + ",dialog=" + modal + ",minimizable=" + resizable + ",modal=" + modal + ",width=" + width + ",height=" + height + ",resizable=" + resizable);
-				if (win == null) {
-					alert(tinyMCELang['lang_popup_blocked']);
-					return;
-				}
-
-				if (template['close_previous'] != "no")
-					tinyMCE.lastWindow = win;
-
-				eval('try { win.resizeTo(width, height); } catch(e) { }');
-
-				// Make it bigger if statusbar is forced
-				if (tinyMCE.isGecko) {
-					if (win.document.defaultView.statusbar.visible)
-						win.resizeBy(0, tinyMCE.isMac ? 10 : 24);
-				}
-
-				win.focus();
-			}
-		}
-	},
-
-	closeWindow : function(win) {
-		win.close();
-	},
-
-	getVisualAidClass : function(class_name, state) {
-		var aidClass = tinyMCE.settings['visual_table_class'];
-
-		if (typeof(state) == "undefined")
-			state = tinyMCE.settings['visual'];
-
-		// Split
-		var classNames = new Array();
-		var ar = class_name.split(' ');
-		for (var i=0; i<ar.length; i++) {
-			if (ar[i] == aidClass)
-				ar[i] = "";
-
-			if (ar[i] != "")
-				classNames[classNames.length] = ar[i];
-		}
-
-		if (state)
-			classNames[classNames.length] = aidClass;
-
-		// Glue
-		var className = "";
-		for (var i=0; i<classNames.length; i++) {
-			if (i > 0)
-				className += " ";
-
-			className += classNames[i];
-		}
-
-		return className;
-	},
-
-	handleVisualAid : function(el, deep, state, inst, skip_dispatch) {
-		if (!el)
-			return;
-
-		if (!skip_dispatch)
-			tinyMCE.dispatchCallback(inst, 'handle_visual_aid_callback', 'handleVisualAid', el, deep, state, inst);
-
-		var tableElement = null;
-
-		switch (el.nodeName) {
-			case "TABLE":
-				var oldW = el.style.width;
-				var oldH = el.style.height;
-				var bo = tinyMCE.getAttrib(el, "border");
-
-				bo = bo == "" || bo == "0" ? true : false;
-
-				tinyMCE.setAttrib(el, "class", tinyMCE.getVisualAidClass(tinyMCE.getAttrib(el, "class"), state && bo));
-
-				el.style.width = oldW;
-				el.style.height = oldH;
-
-				for (var y=0; y<el.rows.length; y++) {
-					for (var x=0; x<el.rows[y].cells.length; x++) {
-						var cn = tinyMCE.getVisualAidClass(tinyMCE.getAttrib(el.rows[y].cells[x], "class"), state && bo);
-						tinyMCE.setAttrib(el.rows[y].cells[x], "class", cn);
-					}
-				}
-
-				break;
-
-			case "A":
-				var anchorName = tinyMCE.getAttrib(el, "name");
-
-				if (anchorName != '' && state) {
-					el.title = anchorName;
-					tinyMCE.addCSSClass(el, 'mceItemAnchor');
-				} else if (anchorName != '' && !state)
-					el.className = '';
-
-				break;
-		}
-
-		if (deep && el.hasChildNodes()) {
-			for (var i=0; i<el.childNodes.length; i++)
-				tinyMCE.handleVisualAid(el.childNodes[i], deep, state, inst, true);
-		}
-	},
-
-	/*
-	applyClassesToFonts : function(doc, size) {
-		var f = doc.getElementsByTagName("font");
-		for (var i=0; i<f.length; i++) {
-			var s = tinyMCE.getAttrib(f[i], "size");
-
-			if (s != "")
-				tinyMCE.setAttrib(f[i], 'class', "mceItemFont" + s);
-		}
-
-		if (typeof(size) != "undefined") {
-			var css = "";
-
-			for (var x=0; x<doc.styleSheets.length; x++) {
-				for (var i=0; i<doc.styleSheets[x].rules.length; i++) {
-					if (doc.styleSheets[x].rules[i].selectorText == '#mceSpanFonts .mceItemFont' + size) {
-						css = doc.styleSheets[x].rules[i].style.cssText;
-						break;
-					}
-				}
-
-				if (css != "")
-					break;
-			}
-
-			if (doc.styleSheets[0].rules[0].selectorText == "FONT")
-				doc.styleSheets[0].removeRule(0);
-
-			doc.styleSheets[0].addRule("FONT", css, 0);
-		}
-	},
-	*/
-
-	fixGeckoBaseHREFBug : function(m, e, h) {
-		var xsrc, xhref;
-
-		if (tinyMCE.isGecko) {
-			if (m == 1) {
-				h = h.replace(/\ssrc=/gi, " mce_tsrc=");
-				h = h.replace(/\shref=/gi, " mce_thref=");
-
-				return h;
-			} else {
-				// Why bother if there is no src or href broken
-				if (!new RegExp('(src|href)=', 'g').test(h))
-					return h;
-
-				// Restore src and href that gets messed up by Gecko
-				tinyMCE.selectElements(e, 'A,IMG,SELECT,AREA,IFRAME,BASE,INPUT,SCRIPT,EMBED,OBJECT,LINK', function (n) {
-					xsrc = tinyMCE.getAttrib(n, "mce_tsrc");
-					xhref = tinyMCE.getAttrib(n, "mce_thref");
-
-					if (xsrc != "") {
-						try {
-							n.src = tinyMCE.convertRelativeToAbsoluteURL(tinyMCE.settings['base_href'], xsrc);
-						} catch (e) {
-							// Ignore, Firefox cast exception if local file wasn't found
-						}
-
-						n.removeAttribute("mce_tsrc");
-					}
-
-					if (xhref != "") {
-						try {
-							n.href = tinyMCE.convertRelativeToAbsoluteURL(tinyMCE.settings['base_href'], xhref);
-						} catch (e) {
-							// Ignore, Firefox cast exception if local file wasn't found
-						}
-
-						n.removeAttribute("mce_thref");
-					}
-
-					return false;
-				});
-
-				// Restore text/comment nodes
-				tinyMCE.selectNodes(e, function(n) {
-					if (n.nodeType == 3 || n.nodeType == 8) {
-						n.nodeValue = n.nodeValue.replace(/\smce_tsrc=/gi, " src=");
-						n.nodeValue = n.nodeValue.replace(/\smce_thref=/gi, " href=");
-					}
-
-					return false;
-				});
-			}
-		}
-
-		return h;
-	},
-
-	_setHTML : function(doc, html_content) {
-		// Force closed anchors open
-		//html_content = html_content.replace(new RegExp('<a(.*?)/>', 'gi'), '<a$1></a>');
-
-		html_content = tinyMCE.cleanupHTMLCode(html_content);
-
-		// Try innerHTML if it fails use pasteHTML in MSIE
-		try {
-			tinyMCE.setInnerHTML(doc.body, html_content);
-		} catch (e) {
-			if (this.isMSIE)
-				doc.body.createTextRange().pasteHTML(html_content);
-		}
-
-		// Content duplication bug fix
-		if (tinyMCE.isIE && tinyMCE.settings['fix_content_duplication']) {
-			// Remove P elements in P elements
-			var paras = doc.getElementsByTagName("P");
-			for (var i=0; i<paras.length; i++) {
-				var node = paras[i];
-				while ((node = node.parentNode) != null) {
-					if (node.nodeName == "P")
-						node.outerHTML = node.innerHTML;
-				}
-			}
-
-			// Content duplication bug fix (Seems to be word crap)
-			var html = doc.body.innerHTML;
-/*
-			if (html.indexOf('="mso') != -1) {
-				for (var i=0; i<doc.body.all.length; i++) {
-					var el = doc.body.all[i];
-					el.removeAttribute("className","",0);
-					el.removeAttribute("style","",0);
-				}
-
-				html = doc.body.innerHTML;
-				html = tinyMCE.regexpReplace(html, "<o:p><\/o:p>", "<br />");
-				html = tinyMCE.regexpReplace(html, "<o:p>&nbsp;<\/o:p>", "");
-				html = tinyMCE.regexpReplace(html, "<st1:.*?>", "");
-				html = tinyMCE.regexpReplace(html, "<p><\/p>", "");
-				html = tinyMCE.regexpReplace(html, "<p><\/p>\r\n<p><\/p>", "");
-				html = tinyMCE.regexpReplace(html, "<p>&nbsp;<\/p>", "<br />");
-				html = tinyMCE.regexpReplace(html, "<p>\s*(<p>\s*)?", "<p>");
-				html = tinyMCE.regexpReplace(html, "<\/p>\s*(<\/p>\s*)?", "</p>");
-			}*/
-
-			// Always set the htmlText output
-			tinyMCE.setInnerHTML(doc.body, html);
-		}
-
-		tinyMCE.cleanupAnchors(doc);
-
-		if (tinyMCE.getParam("convert_fonts_to_spans"))
-			tinyMCE.convertSpansToFonts(doc);
-	},
-
-	getEditorId : function(form_element) {
-		var inst = this.getInstanceById(form_element);
-		if (!inst)
-			return null;
-
-		return inst.editorId;
-	},
-
-	getInstanceById : function(editor_id) {
-		var inst = this.instances[editor_id];
-		if (!inst) {
-			for (var n in tinyMCE.instances) {
-				var instance = tinyMCE.instances[n];
-				if (!tinyMCE.isInstance(instance))
-					continue;
-
-				if (instance.formTargetElementId == editor_id) {
-					inst = instance;
-					break;
-				}
-			}
-		}
-
-		return inst;
-	},
-
-	queryInstanceCommandValue : function(editor_id, command) {
-		var inst = tinyMCE.getInstanceById(editor_id);
-		if (inst)
-			return inst.queryCommandValue(command);
-
-		return false;
-	},
-
-	queryInstanceCommandState : function(editor_id, command) {
-		var inst = tinyMCE.getInstanceById(editor_id);
-		if (inst)
-			return inst.queryCommandState(command);
-
-		return null;
-	},
-
-	setWindowArg : function(n, v) {
-		this.windowArgs[n] = v;
-	},
-
-	getWindowArg : function(n, d) {
-		return (typeof(this.windowArgs[n]) == "undefined") ? d : this.windowArgs[n];
-	},
-
-	getCSSClasses : function(editor_id, doc) {
-		var inst = tinyMCE.getInstanceById(editor_id);
-
-		// Is cached, use that
-		if (inst && inst.cssClasses.length > 0)
-			return inst.cssClasses;
-
-		if (typeof(editor_id) == "undefined" && typeof(doc) == "undefined") {
-			var instance;
-
-			for (var instanceName in tinyMCE.instances) {
-				instance = tinyMCE.instances[instanceName];
-				if (!tinyMCE.isInstance(instance))
-					continue;
-
-				break;
-			}
-
-			doc = instance.getDoc();
-		}
-
-		if (typeof(doc) == "undefined") {
-			var instance = tinyMCE.getInstanceById(editor_id);
-			doc = instance.getDoc();
-		}
-
-		if (doc) {
-			var styles = doc.styleSheets;
-
-			if (styles && styles.length > 0) {
-				for (var x=0; x<styles.length; x++) {
-					var csses = null;
-
-					// Just ignore any errors
-					eval("try {var csses = tinyMCE.isIE ? doc.styleSheets(" + x + ").rules : styles[" + x + "].cssRules;} catch(e) {}");
-					if (!csses)
-						return new Array();
-
-					for (var i=0; i<csses.length; i++) {
-						var selectorText = csses[i].selectorText;
-
-						// Can be multiple rules per selector
-						if (selectorText) {
-							var rules = selectorText.split(',');
-							for (var c=0; c<rules.length; c++) {
-								var rule = rules[c];
-
-								// Strip spaces between selectors
-								while (rule.indexOf(' ') == 0)
-									rule = rule.substring(1);
-
-								// Invalid rule
-								if (rule.indexOf(' ') != -1 || rule.indexOf(':') != -1 || rule.indexOf('mceItem') != -1)
-									continue;
-
-								if (rule.indexOf(tinyMCE.settings['visual_table_class']) != -1 || rule.indexOf('mceEditable') != -1 || rule.indexOf('mceNonEditable') != -1)
-									continue;
-
-								// Is class rule
-								if (rule.indexOf('.') != -1) {
-									var cssClass = rule.substring(rule.indexOf('.') + 1);
-									var addClass = true;
-
-									for (var p=0; p<inst.cssClasses.length && addClass; p++) {
-										if (inst.cssClasses[p] == cssClass)
-											addClass = false;
-									}
-
-									if (addClass)
-										inst.cssClasses[inst.cssClasses.length] = cssClass;
-								}
-							}
-						}
-					}
-				}
-			}
-		}
-
-		return inst.cssClasses;
-	},
-
-	regexpReplace : function(in_str, reg_exp, replace_str, opts) {
-		if (in_str == null)
-			return in_str;
-
-		if (typeof(opts) == "undefined")
-			opts = 'g';
-
-		var re = new RegExp(reg_exp, opts);
-		return in_str.replace(re, replace_str);
-	},
-
-	trim : function(s) {
-		return s.replace(/^\s*|\s*$/g, "");
-	},
-
-	cleanupEventStr : function(s) {
-		s = "" + s;
-		s = s.replace('function anonymous()\n{\n', '');
-		s = s.replace('\n}', '');
-		s = s.replace(/^return true;/gi, ''); // Remove event blocker
-
-		return s;
-	},
-
-	getControlHTML : function(c) {
-		var i, l, n, o, v, rtl = tinyMCE.getLang('lang_dir') == 'rtl';
-
-		l = tinyMCE.plugins;
-		for (n in l) {
-			o = l[n];
-
-			if (o.getControlHTML && (v = o.getControlHTML(c)) != '') {
-				if (rtl)
-					return '<span dir="rtl">' + tinyMCE.replaceVar(v, "pluginurl", o.baseURL) + '</span>';
-
-				return tinyMCE.replaceVar(v, "pluginurl", o.baseURL);
-			}
-		}
-
-		o = tinyMCE.themes[tinyMCE.settings['theme']];
-		if (o.getControlHTML && (v = o.getControlHTML(c)) != '') {
-			if (rtl)
-				return '<span dir="rtl">' + v + '</span>';
-
-			return v;
-		}
-
-		return '';
-	},
-
-	evalFunc : function(f, idx, a, o) {
-		o = !o ? window : o;
-		f = typeof(f) == 'function' ? f : o[f];
-
-		return f.apply(o, Array.prototype.slice.call(a, idx));
-	},
-
-	dispatchCallback : function(i, p, n) {
-		return this.callFunc(i, p, n, 0, this.dispatchCallback.arguments);
-	},
-
-	executeCallback : function(i, p, n) {
-		return this.callFunc(i, p, n, 1, this.executeCallback.arguments);
-	},
-
-	execCommandCallback : function(i, p, n) {
-		return this.callFunc(i, p, n, 2, this.execCommandCallback.arguments);
-	},
-
-	callFunc : function(ins, p, n, m, a) {
-		var l, i, on, o, s, v;
-
-		s = m == 2;
-
-		l = tinyMCE.getParam(p, '');
-
-		if (l != '' && (v = tinyMCE.evalFunc(l, 3, a)) == s && m > 0)
-			return true;
-
-		if (ins != null) {
-			for (i=0, l = ins.plugins; i<l.length; i++) {
-				o = tinyMCE.plugins[l[i]];
-
-				if (o[n] && (v = tinyMCE.evalFunc(n, 3, a, o)) == s && m > 0)
-					return true;
-			}
-		}
-
-		l = tinyMCE.themes;
-		for (on in l) {
-			o = l[on];
-
-			if (o[n] && (v = tinyMCE.evalFunc(n, 3, a, o)) == s && m > 0)
-				return true;
-		}
-
-		return false;
-	},
-
-	xmlEncode : function(s, skip_apos) {
-		return s ? ('' + s).replace(!skip_apos ? this.xmlEncodeAposRe : this.xmlEncodeRe, function (c, b) {
-			switch (c) {
-				case '&':
-					return '&amp;';
-
-				case '"':
-					return '&quot;';
-
-				case '\'':
-					return '&#39;'; // &apos; is not working in MSIE
-
-				case '<':
-					return '&lt;';
-
-				case '>':
-					return '&gt;';
-			}
-
-			return c;
-		}) : s;
-	},
-
-	extend : function(p, np) {
-		var o = {};
-
-		o.parent = p;
-
-		for (n in p)
-			o[n] = p[n];
-
-		for (n in np)
-			o[n] = np[n];
+	grep : function(a, f) {
+		var o = [];
+
+		tinymce.each(a, function(v) {
+			if (!f || f(v))
+				o.push(v);
+		});
 
 		return o;
 	},
 
-	hideMenus : function() {
-		var e = tinyMCE.lastSelectedMenuBtn;
-
-		if (tinyMCE.lastMenu) {
-			tinyMCE.lastMenu.hide();
-			tinyMCE.lastMenu = null;
-		}
-
-		if (e) {
-			tinyMCE.switchClass(e, tinyMCE.lastMenuBtnClass);
-			tinyMCE.lastSelectedMenuBtn = null;
+	inArray : function(a, v) {
+		var i, l;
+
+		if (a) {
+			for (i = 0, l = a.length; i < l; i++) {
+				if (a[i] === v)
+					return i;
+			}
 		}
-	}
-
-	};
-
-// Global instances
-var TinyMCE = TinyMCE_Engine; // Compatiblity with gzip compressors
-var tinyMCE = new TinyMCE_Engine();
-var tinyMCELang = {};
-
-/* file:jscripts/tiny_mce/classes/TinyMCE_Control.class.js */
-
-function TinyMCE_Control(settings) {
-  
-	var t, i, to, fu, p, x, fn, fu, pn, s = settings;
-
-	this.undoRedoLevel = true;
-	this.isTinyMCE_Control = true;
-  
-	// Default settings
-	this.settings = s;
-	this.settings['theme'] = tinyMCE.getParam("theme", "default");
-	this.settings['width'] = tinyMCE.getParam("width", -1);
-	this.settings['height'] = tinyMCE.getParam("height", -1);
-	this.selection = new TinyMCE_Selection(this);
-	this.undoRedo = new TinyMCE_UndoRedo(this);
-	this.cleanup = new TinyMCE_Cleanup();
-	this.shortcuts = new Array();
-	this.hasMouseMoved = false;
-	this.foreColor = this.backColor = "#999999";
-	this.data = {};
-	this.cssClasses = [];
-
-	this.cleanup.init({
-		valid_elements : s.valid_elements,
-		extended_valid_elements : s.extended_valid_elements,
-		valid_child_elements : s.valid_child_elements,
-		entities : s.entities,
-		entity_encoding : s.entity_encoding,
-		debug : s.cleanup_debug,
-		indent : s.apply_source_formatting,
-		invalid_elements : s.invalid_elements,
-		verify_html : s.verify_html,
-		fix_content_duplication : s.fix_content_duplication,
-		convert_fonts_to_spans : s.convert_fonts_to_spans
-	});
-
-	// Wrap old theme
-	t = this.settings['theme'];
-	if (!tinyMCE.hasTheme(t)) {
-		fn = tinyMCE.callbacks;
-		to = {};
-
-		for (i=0; i<fn.length; i++) {
-			if ((fu = window['TinyMCE_' + t + "_" + fn[i]]))
-				to[fn[i]] = fu;
+
+		return -1;
+	},
+
+	extend : function(o, e) {
+		var i, a = arguments;
+
+		for (i=1; i<a.length; i++) {
+			e = a[i];
+
+			tinymce.each(e, function(v, n) {
+				if (typeof(v) !== 'undefined')
+					o[n] = v;
+			});
 		}
 
-		tinyMCE.addTheme(t, to);
-	}
-
-	// Wrap old plugins
-	this.plugins = new Array();
-	p = tinyMCE.getParam('plugins', '', true, ',');
-	if (p.length > 0) {
-		for (i=0; i<p.length; i++) {
-			pn = p[i];
-
-			if (pn.charAt(0) == '-')
-				pn = pn.substring(1);
-
-			if (!tinyMCE.hasPlugin(pn)) {
-				fn = tinyMCE.callbacks;
-				to = {};
-
-				for (x=0; x<fn.length; x++) {
-					if ((fu = window['TinyMCE_' + pn + "_" + fn[x]]))
-						to[fn[x]] = fu;
-				}
-
-				tinyMCE.addPlugin(pn, to);
-			}
-
-			this.plugins[this.plugins.length] = pn; 
-		}
-	}
-};
-
-TinyMCE_Control.prototype = {
-	selection : null,
-
-	settings : null,
-
-	cleanup : null,
-
-	getData : function(na) {
-		var o = this.data[na];
-
-		if (!o)
-			o = this.data[na] = {};
-
 		return o;
 	},
 
-	hasPlugin : function(n) {
-		var i;
-
-		for (i=0; i<this.plugins.length; i++) {
-			if (this.plugins[i] == n)
-				return true;
-		}
-
-		return false;
-	},
-
-	addPlugin : function(n, p) {
-		if (!this.hasPlugin(n)) {
-			tinyMCE.addPlugin(n, p);
-			this.plugins[this.plugins.length] = n;
-		}
-	},
-
-	repaint : function() {
-		var s, b, ex;
-
-		if (tinyMCE.isRealIE)
-			return;
-
-		try {
-			s = this.selection;
-			b = s.getBookmark(true);
-			this.getBody().style.display = 'none';
-			this.getDoc().execCommand('selectall', false, null);
-			this.getSel().collapseToStart();
-			this.getBody().style.display = 'block';
-			s.moveToBookmark(b);
-		} catch (ex) {
-			// Ignore
-		}
-	},
-
-	switchSettings : function() {
-		if (tinyMCE.configs.length > 1 && tinyMCE.currentConfig != this.settings['index']) {
-			tinyMCE.settings = this.settings;
-			tinyMCE.currentConfig = this.settings['index'];
-		}
-	},
-
-	select : function() {
-		var oldInst = tinyMCE.selectedInstance;
-
-		if (oldInst != this) {
-			if (oldInst)
-				oldInst.execCommand('mceEndTyping');
-
-			tinyMCE.dispatchCallback(this, 'select_instance_callback', 'selectInstance', this, oldInst);
-			tinyMCE.selectedInstance = this;
-		}
-	},
-
-	getBody : function() {
-		return this.contentBody ? this.contentBody : this.getDoc().body;
-	},
-
-	getDoc : function() {
-//		return this.contentDocument ? this.contentDocument : this.contentWindow.document; // Removed due to IE 5.5 ?
-		return this.contentWindow.document;
-	},
-
-	getWin : function() {
-		return this.contentWindow;
-	},
-
-	getContainerWin : function() {
-		return this.containerWindow ? this.containerWindow : window;
-	},
-
-	getViewPort : function() {
-		return tinyMCE.getViewPort(this.getWin());
-	},
-
-	getParentNode : function(n, f) {
-		return tinyMCE.getParentNode(n, f, this.getBody());
-	},
-
-	getParentElement : function(n, na, f) {
-		return tinyMCE.getParentElement(n, na, f, this.getBody());
-	},
-
-	getParentBlockElement : function(n) {
-		return tinyMCE.getParentBlockElement(n, this.getBody());
+	trim : function(s) {
+		return (s ? '' + s : '').replace(/^\s*|\s*$/g, '');
 	},
 
-	resizeToContent : function() {
-		var d = this.getDoc(), b = d.body, de = d.documentElement;
-
-		this.iframeElement.style.height = (tinyMCE.isRealIE) ? b.scrollHeight : de.offsetHeight + 'px';
-	},
-
-	addShortcut : function(m, k, d, cmd, ui, va) {
-		var n = typeof(k) == "number", ie = tinyMCE.isIE, c, sc, i, scl = this.shortcuts;
-
-		if (!tinyMCE.getParam('custom_shortcuts'))
-			return false;
-
-		m = m.toLowerCase();
-		k = ie && !n ? k.toUpperCase() : k;
-		c = n ? null : k.charCodeAt(0);
-		d = d && d.indexOf('lang_') == 0 ? tinyMCE.getLang(d) : d;
-
-		sc = {
-			alt : m.indexOf('alt') != -1,
-			ctrl : m.indexOf('ctrl') != -1,
-			shift : m.indexOf('shift') != -1,
-			charCode : c,
-			keyCode : n ? k : (ie ? c : null),
-			desc : d,
-			cmd : cmd,
-			ui : ui,
-			val : va
-		};
-
-		for (i=0; i<scl.length; i++) {
-			if (sc.alt == scl[i].alt && sc.ctrl == scl[i].ctrl && sc.shift == scl[i].shift
-				&& sc.charCode == scl[i].charCode && sc.keyCode == scl[i].keyCode) {
-				return false;
-			}
-		}
-
-		scl[scl.length] = sc;
-
-		return true;
-	},
-
-	handleShortcut : function(e) {
-		var i, s, o;
-
-		// Normal key press, then ignore it
-		if (!e.altKey && !e.ctrlKey)
-			return false;
-
-		s = this.shortcuts;
-
-		for (i=0; i<s.length; i++) {
-			o = s[i];
-
-			if (o.alt == e.altKey && o.ctrl == e.ctrlKey && (o.keyCode == e.keyCode || o.charCode == e.charCode)) {
-				if (o.cmd && (e.type == "keydown" || (e.type == "keypress" && !tinyMCE.isOpera)))
-					tinyMCE.execCommand(o.cmd, o.ui, o.val);
-
-				tinyMCE.cancelEvent(e);
-				return true;
-			}
-		}
-
-		return false;
-	},
-
-	autoResetDesignMode : function() {
-		// Add fix for tab/style.display none/block problems in Gecko
-		if (!tinyMCE.isIE && this.isHidden() && tinyMCE.getParam('auto_reset_designmode'))
-			eval('try { this.getDoc().designMode = "On"; this.useCSS = false; } catch(e) {}');
-	},
-
-	isHidden : function() {
-		var s;
-
-		if (tinyMCE.isIE)
-			return false;
-
-		s = this.getSel();
-
-		// Weird, wheres that cursor selection?
-		return (!s || !s.rangeCount || s.rangeCount == 0);
-	},
-
-	isDirty : function() {
-		// Is content modified and not in a submit procedure
-		return tinyMCE.trim(this.startContent) != tinyMCE.trim(this.getBody().innerHTML) && !tinyMCE.isNotDirty;
-	},
-
-	_mergeElements : function(scmd, pa, ch, override) {
-		if (scmd == "removeformat") {
-			pa.className = "";
-			pa.style.cssText = "";
-			ch.className = "";
-			ch.style.cssText = "";
+	// #endif
+
+	create : function(s, p) {
+		var t = this, sp, ns, cn, scn, c, de = 0;
+
+		// Parse : <prefix> <class>:<super class>
+		s = /^((static) )?([\w.]+)(:([\w.]+))?/.exec(s);
+		cn = s[3].match(/(^|\.)(\w+)$/i)[2]; // Class name
+
+		// Create namespace for new class
+		ns = t.createNS(s[3].replace(/\.\w+$/, ''));
+
+		// Class already exists
+		if (ns[cn])
+			return;
+
+		// Make pure static class
+		if (s[2] == 'static') {
+			ns[cn] = p;
+
+			if (this.onCreate)
+				this.onCreate(s[2], s[3], ns[cn]);
+
 			return;
 		}
 
-		var st = tinyMCE.parseStyle(tinyMCE.getAttrib(pa, "style"));
-		var stc = tinyMCE.parseStyle(tinyMCE.getAttrib(ch, "style"));
-		var className = tinyMCE.getAttrib(pa, "class");
-
-		// Removed class adding due to bug #1478272
-		className = tinyMCE.getAttrib(ch, "class");
-
-		if (override) {
-			for (var n in st) {
-				if (typeof(st[n]) == 'function')
-					continue;
-
-				stc[n] = st[n];
-			}
-		} else {
-			for (var n in stc) {
-				if (typeof(stc[n]) == 'function')
-					continue;
-
-				st[n] = stc[n];
-			}
-		}
-
-		tinyMCE.setAttrib(pa, "style", tinyMCE.serializeStyle(st));
-		tinyMCE.setAttrib(pa, "class", tinyMCE.trim(className));
-		ch.className = "";
-		ch.style.cssText = "";
-		ch.removeAttribute("class");
-		ch.removeAttribute("style");
-	},
-
-	_setUseCSS : function(b) {
-		var d = this.getDoc();
-
-		try {d.execCommand("useCSS", false, !b);} catch (ex) {}
-		try {d.execCommand("styleWithCSS", false, b);} catch (ex) {}
-
-		if (!tinyMCE.getParam("table_inline_editing"))
-			try {d.execCommand('enableInlineTableEditing', false, "false");} catch (ex) {}
-
-		if (!tinyMCE.getParam("object_resizing"))
-			try {d.execCommand('enableObjectResizing', false, "false");} catch (ex) {}
-	},
-
-	execCommand : function(command, user_interface, value) {
-		var doc = this.getDoc(), win = this.getWin(), focusElm = this.getFocusElement();
-
-		// Is not a undo specific command
-		if (!new RegExp('mceStartTyping|mceEndTyping|mceBeginUndoLevel|mceEndUndoLevel|mceAddUndoLevel', 'gi').test(command))
-			this.undoBookmark = null;
-
-		// Mozilla issue
-		if (!tinyMCE.isIE && !this.useCSS) {
-			this._setUseCSS(false);
-			this.useCSS = true;
-		}
-
-		//debug("command: " + command + ", user_interface: " + user_interface + ", value: " + value);
-		this.contentDocument = doc; // <-- Strange, unless this is applied Mozilla 1.3 breaks
-
-		// Don't dispatch key commands
-		if (!/mceStartTyping|mceEndTyping/.test(command)) {
-			if (tinyMCE.execCommandCallback(this, 'execcommand_callback', 'execCommand', this.editorId, this.getBody(), command, user_interface, value))
-				return;
-		}
-
-		// Fix align on images
-		if (focusElm && focusElm.nodeName == "IMG") {
-			var align = focusElm.getAttribute('align');
-			var img = command == "JustifyCenter" ? focusElm.cloneNode(false) : focusElm;
-
-			switch (command) {
-				case "JustifyLeft":
-					if (align == 'left')
-						img.removeAttribute('align');
-					else
-						img.setAttribute('align', 'left');
-
-					// Remove the div
-					var div = focusElm.parentNode;
-					if (div && div.nodeName == "DIV" && div.childNodes.length == 1 && div.parentNode)
-						div.parentNode.replaceChild(img, div);
-
-					this.selection.selectNode(img);
-					this.repaint();
-					tinyMCE.triggerNodeChange();
-					return;
-
-				case "JustifyCenter":
-					img.removeAttribute('align');
-
-					// Is centered
-					var div = tinyMCE.getParentElement(focusElm, "div");
-					if (div && div.style.textAlign == "center") {
-						// Remove div
-						if (div.nodeName == "DIV" && div.childNodes.length == 1 && div.parentNode)
-							div.parentNode.replaceChild(img, div);
-					} else {
-						// Add div
-						var div = this.getDoc().createElement("div");
-						div.style.textAlign = 'center';
-						div.appendChild(img);
-						focusElm.parentNode.replaceChild(div, focusElm);
-					}
-
-					this.selection.selectNode(img);
-					this.repaint();
-					tinyMCE.triggerNodeChange();
-					return;
-
-				case "JustifyRight":
-					if (align == 'right')
-						img.removeAttribute('align');
-					else
-						img.setAttribute('align', 'right');
-
-					// Remove the div
-					var div = focusElm.parentNode;
-					if (div && div.nodeName == "DIV" && div.childNodes.length == 1 && div.parentNode)
-						div.parentNode.replaceChild(img, div);
-
-					this.selection.selectNode(img);
-					this.repaint();
-					tinyMCE.triggerNodeChange();
-					return;
-			}
-		}
-
-		if (tinyMCE.settings['force_br_newlines']) {
-			var alignValue = "";
-
-			if (doc.selection.type != "Control") {
-				switch (command) {
-						case "JustifyLeft":
-							alignValue = "left";
-							break;
-
-						case "JustifyCenter":
-							alignValue = "center";
-							break;
-
-						case "JustifyFull":
-							alignValue = "justify";
-							break;
-
-						case "JustifyRight":
-							alignValue = "right";
-							break;
-				}
-
-				if (alignValue != "") {
-					var rng = doc.selection.createRange();
-
-					if ((divElm = tinyMCE.getParentElement(rng.parentElement(), "div")) != null)
-						divElm.setAttribute("align", alignValue);
-					else if (rng.pasteHTML && rng.htmlText.length > 0)
-						rng.pasteHTML('<div align="' + alignValue + '">' + rng.htmlText + "</div>");
-
-					tinyMCE.triggerNodeChange();
-					return;
-				}
-			}
+		// Create default constructor
+		if (!p[cn]) {
+			p[cn] = function() {};
+			de = 1;
 		}
 
-		switch (command) {
-			case "mceRepaint":
-				this.repaint();
-				return true;
-
-			case "unlink":
-				// Unlink if caret is inside link
-				if (tinyMCE.isGecko && this.getSel().isCollapsed) {
-					focusElm = tinyMCE.getParentElement(focusElm, 'A');
-
-					if (focusElm)
-						this.selection.selectNode(focusElm, false);
-				}
-
-				this.getDoc().execCommand(command, user_interface, value);
-
-				tinyMCE.isGecko && this.getSel().collapseToEnd();
-
-				tinyMCE.triggerNodeChange();
-
-				return true;
-
-			case "InsertUnorderedList":
-			case "InsertOrderedList":
-				this.getDoc().execCommand(command, user_interface, value);
-				tinyMCE.triggerNodeChange();
-				break;
-
-			case "Strikethrough":
-				this.getDoc().execCommand(command, user_interface, value);
-				tinyMCE.triggerNodeChange();
-				break;
-
-			case "mceSelectNode":
-				this.selection.selectNode(value);
-				tinyMCE.triggerNodeChange();
-				tinyMCE.selectedNode = value;
-				break;
-
-			case "FormatBlock":
-				if (value == null || value == "") {
-					var elm = tinyMCE.getParentElement(this.getFocusElement(), "p,div,h1,h2,h3,h4,h5,h6,pre,address,blockquote,dt,dl,dd,samp");
-
-					if (elm)
-						this.execCommand("mceRemoveNode", false, elm);
-				} else {
-					if (!this.cleanup.isValid(value))
-						return true;
-
-					if (tinyMCE.isGecko && new RegExp('<(div|blockquote|code|dt|dd|dl|samp)>', 'gi').test(value))
-						value = value.replace(/[^a-z]/gi, '');
-
-					if (tinyMCE.isIE && new RegExp('blockquote|code|samp', 'gi').test(value)) {
-						var b = this.selection.getBookmark();
-						this.getDoc().execCommand("FormatBlock", false, '<p>');
-						tinyMCE.renameElement(tinyMCE.getParentBlockElement(this.getFocusElement()), value);
-						this.selection.moveToBookmark(b);
-					} else
-						this.getDoc().execCommand("FormatBlock", false, value);
-				}
-
-				tinyMCE.triggerNodeChange();
-
-				break;
-
-			case "mceRemoveNode":
-				if (!value)
-					value = tinyMCE.getParentElement(this.getFocusElement());
-
-				if (tinyMCE.isIE) {
-					value.outerHTML = value.innerHTML;
-				} else {
-					var rng = value.ownerDocument.createRange();
-					rng.setStartBefore(value);
-					rng.setEndAfter(value);
-					rng.deleteContents();
-					rng.insertNode(rng.createContextualFragment(value.innerHTML));
-				}
-
-				tinyMCE.triggerNodeChange();
-
-				break;
-
-			case "mceSelectNodeDepth":
-				var parentNode = this.getFocusElement();
-				for (var i=0; parentNode; i++) {
-					if (parentNode.nodeName.toLowerCase() == "body")
-						break;
-
-					if (parentNode.nodeName.toLowerCase() == "#text") {
-						i--;
-						parentNode = parentNode.parentNode;
-						continue;
-					}
-
-					if (i == value) {
-						this.selection.selectNode(parentNode, false);
-						tinyMCE.triggerNodeChange();
-						tinyMCE.selectedNode = parentNode;
-						return;
-					}
-
-					parentNode = parentNode.parentNode;
-				}
-
-				break;
-
-			case "mceSetStyleInfo":
-			case "SetStyleInfo":
-				var rng = this.getRng();
-				var sel = this.getSel();
-				var scmd = value['command'];
-				var sname = value['name'];
-				var svalue = value['value'] == null ? '' : value['value'];
-				//var svalue = value['value'] == null ? '' : value['value'];
-				var wrapper = value['wrapper'] ? value['wrapper'] : "span";
-				var parentElm = null;
-				var invalidRe = new RegExp("^BODY|HTML$", "g");
-				var invalidParentsRe = tinyMCE.settings['merge_styles_invalid_parents'] != '' ? new RegExp(tinyMCE.settings['merge_styles_invalid_parents'], "gi") : null;
-
-				// Whole element selected check
-				if (tinyMCE.isIE) {
-					// Control range
-					if (rng.item)
-						parentElm = rng.item(0);
-					else {
-						var pelm = rng.parentElement();
-						var prng = doc.selection.createRange();
-						prng.moveToElementText(pelm);
-
-						if (rng.htmlText == prng.htmlText || rng.boundingWidth == 0) {
-							if (invalidParentsRe == null || !invalidParentsRe.test(pelm.nodeName))
-								parentElm = pelm;
-						}
-					}
-				} else {
-					var felm = this.getFocusElement();
-					if (sel.isCollapsed || (new RegExp('td|tr|tbody|table', 'gi').test(felm.nodeName) && sel.anchorNode == felm.parentNode))
-						parentElm = felm;
-				}
-
-				// Whole element selected
-				if (parentElm && !invalidRe.test(parentElm.nodeName)) {
-					if (scmd == "setstyle")
-						tinyMCE.setStyleAttrib(parentElm, sname, svalue);
-
-					if (scmd == "setattrib")
-						tinyMCE.setAttrib(parentElm, sname, svalue);
-
-					if (scmd == "removeformat") {
-						parentElm.style.cssText = '';
-						tinyMCE.setAttrib(parentElm, 'class', '');
-					}
-
-					// Remove style/attribs from all children
-					var ch = tinyMCE.getNodeTree(parentElm, new Array(), 1);
-					for (var z=0; z<ch.length; z++) {
-						if (ch[z] == parentElm)
-							continue;
-
-						if (scmd == "setstyle")
-							tinyMCE.setStyleAttrib(ch[z], sname, '');
-
-						if (scmd == "setattrib")
-							tinyMCE.setAttrib(ch[z], sname, '');
-
-						if (scmd == "removeformat") {
-							ch[z].style.cssText = '';
-							tinyMCE.setAttrib(ch[z], 'class', '');
-						}
-					}
+		// Add constructor and methods
+		ns[cn] = p[cn];
+		t.extend(ns[cn].prototype, p);
+
+		// Extend
+		if (s[5]) {
+			sp = t.resolve(s[5]).prototype;
+			scn = s[5].match(/\.(\w+)$/i)[1]; // Class name
+
+			// Extend constructor
+			c = ns[cn];
+			if (de) {
+				// Add passthrough constructor
+				ns[cn] = function() {
+					return sp[scn].apply(this, arguments);
+				};
+			} else {
+				// Add inherit constructor
+				ns[cn] = function() {
+					this.parent = sp[scn];
+					return c.apply(this, arguments);
+				};
+			}
+			ns[cn].prototype[cn] = ns[cn];
+
+			// Add super methods
+			t.each(sp, function(f, n) {
+				if (n != scn)
+					ns[cn].prototype[n] = sp[n];
+			});
+
+			// Add overridden methods
+			t.each(p, function(f, n) {
+				// Extend methods if needed
+				if (sp[n]) {
+					ns[cn].prototype[n] = function() {
+						this.parent = sp[n];
+						return f.apply(this, arguments);
+					};
 				} else {
-					this._setUseCSS(false); // Bug in FF when running in fullscreen
-					doc.execCommand("FontName", false, "#mce_temp_font#");
-					var elementArray = tinyMCE.getElementsByAttributeValue(this.getBody(), "font", "face", "#mce_temp_font#");
-
-					// Change them all
-					for (var x=0; x<elementArray.length; x++) {
-						elm = elementArray[x];
-						if (elm) {
-							var spanElm = doc.createElement(wrapper);
-
-							if (scmd == "setstyle")
-								tinyMCE.setStyleAttrib(spanElm, sname, svalue);
-
-							if (scmd == "setattrib")
-								tinyMCE.setAttrib(spanElm, sname, svalue);
-
-							if (scmd == "removeformat") {
-								spanElm.style.cssText = '';
-								tinyMCE.setAttrib(spanElm, 'class', '');
-							}
-
-							if (elm.hasChildNodes()) {
-								for (var i=0; i<elm.childNodes.length; i++)
-									spanElm.appendChild(elm.childNodes[i].cloneNode(true));
-							}
-
-							spanElm.setAttribute("mce_new", "true");
-							elm.parentNode.replaceChild(spanElm, elm);
-
-							// Remove style/attribs from all children
-							var ch = tinyMCE.getNodeTree(spanElm, new Array(), 1);
-							for (var z=0; z<ch.length; z++) {
-								if (ch[z] == spanElm)
-									continue;
-
-								if (scmd == "setstyle")
-									tinyMCE.setStyleAttrib(ch[z], sname, '');
-
-								if (scmd == "setattrib")
-									tinyMCE.setAttrib(ch[z], sname, '');
-
-								if (scmd == "removeformat") {
-									ch[z].style.cssText = '';
-									tinyMCE.setAttrib(ch[z], 'class', '');
-								}
-							}
-						}
-					}
-				}
-
-				// Cleaup wrappers
-				var nodes = doc.getElementsByTagName(wrapper);
-				for (var i=nodes.length-1; i>=0; i--) {
-					var elm = nodes[i];
-					var isNew = tinyMCE.getAttrib(elm, "mce_new") == "true";
-
-					elm.removeAttribute("mce_new");
-
-					// Is only child a element
-					if (elm.childNodes && elm.childNodes.length == 1 && elm.childNodes[0].nodeType == 1) {
-						//tinyMCE.debug("merge1" + isNew);
-						this._mergeElements(scmd, elm, elm.childNodes[0], isNew);
-						continue;
-					}
-
-					// Is I the only child
-					if (elm.parentNode.childNodes.length == 1 && !invalidRe.test(elm.nodeName) && !invalidRe.test(elm.parentNode.nodeName)) {
-						//tinyMCE.debug("merge2" + isNew + "," + elm.nodeName + "," + elm.parentNode.nodeName);
-						if (invalidParentsRe == null || !invalidParentsRe.test(elm.parentNode.nodeName))
-							this._mergeElements(scmd, elm.parentNode, elm, false);
-					}
-				}
-
-				// Remove empty wrappers
-				var nodes = doc.getElementsByTagName(wrapper);
-				for (var i=nodes.length-1; i>=0; i--) {
-					var elm = nodes[i];
-					var isEmpty = true;
-
-					// Check if it has any attribs
-					var tmp = doc.createElement("body");
-					tmp.appendChild(elm.cloneNode(false));
-
-					// Is empty span, remove it
-					tmp.innerHTML = tmp.innerHTML.replace(new RegExp('style=""|class=""', 'gi'), '');
-					//tinyMCE.debug(tmp.innerHTML);
-					if (new RegExp('<span>', 'gi').test(tmp.innerHTML)) {
-						for (var x=0; x<elm.childNodes.length; x++) {
-							if (elm.parentNode != null)
-								elm.parentNode.insertBefore(elm.childNodes[x].cloneNode(true), elm);
-						}
-
-						elm.parentNode.removeChild(elm);
-					}
-				}
-
-				// Re add the visual aids
-				if (scmd == "removeformat")
-					tinyMCE.handleVisualAid(this.getBody(), true, this.visualAid, this);
-
-				tinyMCE.triggerNodeChange();
-
-				break;
-
-			case "FontName":
-				if (value == null) {
-					var s = this.getSel();
-
-					// Find font and select it
-					if (tinyMCE.isGecko && s.isCollapsed) {
-						var f = tinyMCE.getParentElement(this.getFocusElement(), "font");
-
-						if (f != null)
-							this.selection.selectNode(f, false);
-					}
-
-					// Remove format
-					this.getDoc().execCommand("RemoveFormat", false, null);
-
-					// Collapse range if font was found
-					if (f != null && tinyMCE.isGecko) {
-						var r = this.getRng().cloneRange();
-						r.collapse(true);
-						s.removeAllRanges();
-						s.addRange(r);
-					}
-				} else
-					this.getDoc().execCommand('FontName', false, value);
-
-				if (tinyMCE.isGecko)
-					window.setTimeout('tinyMCE.triggerNodeChange(false);', 1);
-
-				return;
-
-			case "FontSize":
-				this.getDoc().execCommand('FontSize', false, value);
-
-				if (tinyMCE.isGecko)
-					window.setTimeout('tinyMCE.triggerNodeChange(false);', 1);
-
-				return;
-
-			case "forecolor":
-				value = value == null ? this.foreColor : value;
-				value = tinyMCE.trim(value);
-				value = value.charAt(0) != '#' ? (isNaN('0x' + value) ? value : '#' + value) : value;
-
-				this.foreColor = value;
-				this.getDoc().execCommand('forecolor', false, value);
-				break;
-
-			case "HiliteColor":
-				value = value == null ? this.backColor : value;
-				value = tinyMCE.trim(value);
-				value = value.charAt(0) != '#' ? (isNaN('0x' + value) ? value : '#' + value) : value;
-				this.backColor = value;
-
-				if (tinyMCE.isGecko) {
-					this._setUseCSS(true);
-					this.getDoc().execCommand('hilitecolor', false, value);
-					this._setUseCSS(false);
-				} else
-					this.getDoc().execCommand('BackColor', false, value);
-				break;
-
-			case "Cut":
-			case "Copy":
-			case "Paste":
-				var cmdFailed = false;
-
-				// Try executing command
-				eval('try {this.getDoc().execCommand(command, user_interface, value);} catch (e) {cmdFailed = true;}');
-
-				if (tinyMCE.isOpera && cmdFailed)
-					alert('Currently not supported by your browser, use keyboard shortcuts instead.');
-
-				// Alert error in gecko if command failed
-				if (tinyMCE.isGecko && cmdFailed) {
-					// Confirm more info
-					if (confirm(tinyMCE.entityDecode(tinyMCE.getLang('lang_clipboard_msg'))))
-						window.open('http://www.mozilla.org/editor/midasdemo/securityprefs.html', 'mceExternal');
-
-					return;
-				} else
-					tinyMCE.triggerNodeChange();
-			break;
-
-			case "mceSetContent":
-				if (!value)
-					value = "";
-
-				// Call custom cleanup code
-				value = tinyMCE.storeAwayURLs(value);
-				value = tinyMCE._customCleanup(this, "insert_to_editor", value);
-
-				if (this.getBody().nodeName == 'BODY')
-					tinyMCE._setHTML(doc, value);
-				else
-					this.getBody().innerHTML = value;
-
-				tinyMCE.setInnerHTML(this.getBody(), tinyMCE._cleanupHTML(this, doc, this.settings, this.getBody(), false, false, false, true));
-				tinyMCE.convertAllRelativeURLs(this.getBody());
-
-				// Cleanup any mess left from storyAwayURLs
-				tinyMCE._removeInternal(this.getBody());
-
-				// When editing always use fonts internaly
-				if (tinyMCE.getParam("convert_fonts_to_spans"))
-					tinyMCE.convertSpansToFonts(doc);
-
-				tinyMCE.handleVisualAid(this.getBody(), true, this.visualAid, this);
-				tinyMCE._setEventsEnabled(this.getBody(), false);
-				return true;
-
-			case "mceCleanup":
-				var b = this.selection.getBookmark();
-				tinyMCE._setHTML(this.contentDocument, this.getBody().innerHTML);
-				tinyMCE.setInnerHTML(this.getBody(), tinyMCE._cleanupHTML(this, this.contentDocument, this.settings, this.getBody(), this.visualAid));
-				tinyMCE.convertAllRelativeURLs(doc.body);
-
-				// When editing always use fonts internaly
-				if (tinyMCE.getParam("convert_fonts_to_spans"))
-					tinyMCE.convertSpansToFonts(doc);
-
-				tinyMCE.handleVisualAid(this.getBody(), true, this.visualAid, this);
-				tinyMCE._setEventsEnabled(this.getBody(), false);
-				this.repaint();
-				this.selection.moveToBookmark(b);
-				tinyMCE.triggerNodeChange();
-			break;
-
-			case "mceReplaceContent":
-				// Force empty string
-				if (!value)
-					value = '';
-
-				this.getWin().focus();
-
-				var selectedText = "";
-
-				if (tinyMCE.isIE) {
-					var rng = doc.selection.createRange();
-					selectedText = rng.text;
-				} else
-					selectedText = this.getSel().toString();
-
-				if (selectedText.length > 0) {
-					value = tinyMCE.replaceVar(value, "selection", selectedText);
-					tinyMCE.execCommand('mceInsertContent', false, value);
-				}
-
-				tinyMCE.triggerNodeChange();
-			break;
-
-			case "mceSetAttribute":
-				if (typeof(value) == 'object') {
-					var targetElms = (typeof(value['targets']) == "undefined") ? "p,img,span,div,td,h1,h2,h3,h4,h5,h6,pre,address" : value['targets'];
-					var targetNode = tinyMCE.getParentElement(this.getFocusElement(), targetElms);
-
-					if (targetNode) {
-						targetNode.setAttribute(value['name'], value['value']);
-						tinyMCE.triggerNodeChange();
-					}
-				}
-			break;
-
-			case "mceSetCSSClass":
-				this.execCommand("mceSetStyleInfo", false, {command : "setattrib", name : "class", value : value});
-			break;
-
-			case "mceInsertRawHTML":
-				var key = 'tiny_mce_marker';
-
-				this.execCommand('mceBeginUndoLevel');
-
-				// Insert marker key
-				this.execCommand('mceInsertContent', false, key);
-
-				// Store away scroll pos
-				var scrollX = this.getBody().scrollLeft + this.getDoc().documentElement.scrollLeft;
-				var scrollY = this.getBody().scrollTop + this.getDoc().documentElement.scrollTop;
-
-				// Find marker and replace with RAW HTML
-				var html = this.getBody().innerHTML;
-				if ((pos = html.indexOf(key)) != -1)
-					tinyMCE.setInnerHTML(this.getBody(), html.substring(0, pos) + value + html.substring(pos + key.length));
-
-				// Restore scoll pos
-				this.contentWindow.scrollTo(scrollX, scrollY);
-
-				this.execCommand('mceEndUndoLevel');
-
-				break;
-
-			case "mceInsertContent":
-				// Force empty string
-				if (!value)
-					value = '';
-
-				var insertHTMLFailed = false;
-
-				// Removed since it produced problems in IE
-				// this.getWin().focus();
-
-				if (tinyMCE.isGecko || tinyMCE.isOpera) {
-					try {
-						// Is plain text or HTML, &amp;, &nbsp; etc will be encoded wrong in FF
-						if (value.indexOf('<') == -1 && !value.match(/(&#38;|&#160;|&#60;|&#62;)/g)) {
-							var r = this.getRng();
-							var n = this.getDoc().createTextNode(tinyMCE.entityDecode(value));
-							var s = this.getSel();
-							var r2 = r.cloneRange();
-
-							// Insert text at cursor position
-							s.removeAllRanges();
-							r.deleteContents();
-							r.insertNode(n);
-
-							// Move the cursor to the end of text
-							r2.selectNode(n);
-							r2.collapse(false);
-							s.removeAllRanges();
-							s.addRange(r2);
-						} else {
-							value = tinyMCE.fixGeckoBaseHREFBug(1, this.getDoc(), value);
-							this.getDoc().execCommand('inserthtml', false, value);
-							tinyMCE.fixGeckoBaseHREFBug(2, this.getDoc(), value);
-						}
-					} catch (ex) {
-						insertHTMLFailed = true;
-					}
-
-					if (!insertHTMLFailed) {
-						tinyMCE.triggerNodeChange();
-						return;
-					}
-				}
-
-				if (!tinyMCE.isIE) {
-					var isHTML = value.indexOf('<') != -1;
-					var sel = this.getSel();
-					var rng = this.getRng();
-
-					if (isHTML) {
-						if (tinyMCE.isSafari) {
-							var tmpRng = this.getDoc().createRange();
-
-							tmpRng.setStart(this.getBody(), 0);
-							tmpRng.setEnd(this.getBody(), 0);
-
-							value = tmpRng.createContextualFragment(value);
-						} else
-							value = rng.createContextualFragment(value);
-					} else {
-						// Setup text node
-						var el = document.createElement("div");
-						el.innerHTML = value;
-						value = el.firstChild.nodeValue;
-						value = doc.createTextNode(value);
-					}
-
-					// Insert plain text in Safari
-					if (tinyMCE.isSafari && !isHTML) {
-						this.execCommand('InsertText', false, value.nodeValue);
-						tinyMCE.triggerNodeChange();
-						return true;
-					} else if (tinyMCE.isSafari && isHTML) {
-						rng.deleteContents();
-						rng.insertNode(value);
-						tinyMCE.triggerNodeChange();
-						return true;
-					}
-
-					rng.deleteContents();
-
-					// If target node is text do special treatment, (Mozilla 1.3 fix)
-					if (rng.startContainer.nodeType == 3) {
-						var node = rng.startContainer.splitText(rng.startOffset);
-						node.parentNode.insertBefore(value, node); 
-					} else
-						rng.insertNode(value);
-
-					if (!isHTML) {
-						// Removes weird selection trails
-						sel.selectAllChildren(doc.body);
-						sel.removeAllRanges();
-
-						// Move cursor to end of content
-						var rng = doc.createRange();
-
-						rng.selectNode(value);
-						rng.collapse(false);
-
-						sel.addRange(rng);
-					} else
-						rng.collapse(false);
-
-					tinyMCE.fixGeckoBaseHREFBug(2, this.getDoc(), value);
-				} else {
-					var rng = doc.selection.createRange(), tmpRng = null;
-					var c = value.indexOf('<!--') != -1;
-
-					// Fix comment bug, add tag before comments
-					if (c)
-						value = tinyMCE.uniqueTag + value;
-
-					//	tmpRng = rng.duplicate(); // Store away range (Fixes Undo bookmark bug in IE)
-
-					if (rng.item)
-						rng.item(0).outerHTML = value;
-					else
-						rng.pasteHTML(value);
-
-					//if (tmpRng)
-					//	tmpRng.select(); // Restore range  (Fixes Undo bookmark bug in IE)
-
-					// Remove unique tag
-					if (c) {
-						var e = this.getDoc().getElementById('mceTMPElement');
-						e.parentNode.removeChild(e);
-					}
-				}
-
-				tinyMCE.execCommand("mceAddUndoLevel");
-				tinyMCE.triggerNodeChange();
-			break;
-
-			case "mceStartTyping":
-				if (tinyMCE.settings['custom_undo_redo'] && this.undoRedo.typingUndoIndex == -1) {
-					this.undoRedo.typingUndoIndex = this.undoRedo.undoIndex;
-					tinyMCE.typingUndoIndex = tinyMCE.undoIndex;
-					this.execCommand('mceAddUndoLevel');
-				}
-				break;
-
-			case "mceEndTyping":
-				if (tinyMCE.settings['custom_undo_redo'] && this.undoRedo.typingUndoIndex != -1) {
-					this.execCommand('mceAddUndoLevel');
-					this.undoRedo.typingUndoIndex = -1;
-				}
-
-				tinyMCE.typingUndoIndex = -1;
-				break;
-
-			case "mceBeginUndoLevel":
-				this.undoRedoLevel = false;
-				break;
-
-			case "mceEndUndoLevel":
-				this.undoRedoLevel = true;
-				this.execCommand('mceAddUndoLevel');
-				break;
-
-			case "mceAddUndoLevel":
-				if (tinyMCE.settings['custom_undo_redo'] && this.undoRedoLevel) {
-					if (this.undoRedo.add())
-						tinyMCE.triggerNodeChange(false);
-				}
-				break;
-
-			case "Undo":
-				if (tinyMCE.settings['custom_undo_redo']) {
-					tinyMCE.execCommand("mceEndTyping");
-					this.undoRedo.undo();
-					tinyMCE.triggerNodeChange();
-				} else
-					this.getDoc().execCommand(command, user_interface, value);
-				break;
-
-			case "Redo":
-				if (tinyMCE.settings['custom_undo_redo']) {
-					tinyMCE.execCommand("mceEndTyping");
-					this.undoRedo.redo();
-					tinyMCE.triggerNodeChange();
-				} else
-					this.getDoc().execCommand(command, user_interface, value);
-				break;
-
-			case "mceToggleVisualAid":
-				this.visualAid = !this.visualAid;
-				tinyMCE.handleVisualAid(this.getBody(), true, this.visualAid, this);
-				tinyMCE.triggerNodeChange();
-				break;
-
-			case "Indent":
-				this.getDoc().execCommand(command, user_interface, value);
-				tinyMCE.triggerNodeChange();
-
-				if (tinyMCE.isIE) {
-					var n = tinyMCE.getParentElement(this.getFocusElement(), "blockquote");
-					do {
-						if (n && n.nodeName == "BLOCKQUOTE") {
-							n.removeAttribute("dir");
-							n.removeAttribute("style");
-						}
-					} while (n != null && (n = n.parentNode) != null);
-				}
-				break;
-
-			case "RemoveFormat":
-			case "removeformat":
-				var text = this.selection.getSelectedText();
-
-				if (tinyMCE.isOpera) {
-					this.getDoc().execCommand("RemoveFormat", false, null);
-					return;
-				}
-
-				if (tinyMCE.isIE) {
-					try {
-						var rng = doc.selection.createRange();
-						rng.execCommand("RemoveFormat", false, null);
-					} catch (e) {
-						// Do nothing
-					}
-
-					this.execCommand("mceSetStyleInfo", false, {command : "removeformat"});
-				} else {
-					this.getDoc().execCommand(command, user_interface, value);
-
-					this.execCommand("mceSetStyleInfo", false, {command : "removeformat"});
-				}
-
-				// Remove class
-				if (text.length == 0)
-					this.execCommand("mceSetCSSClass", false, "");
-
-				tinyMCE.triggerNodeChange();
-				break;
-
-			default:
-				this.getDoc().execCommand(command, user_interface, value);
-
-				if (tinyMCE.isGecko)
-					window.setTimeout('tinyMCE.triggerNodeChange(false);', 1);
-				else
-					tinyMCE.triggerNodeChange();
+					if (n != cn)
+						ns[cn].prototype[n] = f;
+				}
+			});
 		}
 
-		// Add undo level after modification
-		if (command != "mceAddUndoLevel" && command != "Undo" && command != "Redo" && command != "mceStartTyping" && command != "mceEndTyping")
-			tinyMCE.execCommand("mceAddUndoLevel");
+		// Add static methods
+		t.each(p['static'], function(f, n) {
+			ns[cn][n] = f;
+		});
+
+		if (this.onCreate)
+			this.onCreate(s[2], s[3], ns[cn].prototype);
 	},
 
-	queryCommandValue : function(c) {
-		try {
-			return this.getDoc().queryCommandValue(c);
-		} catch (e) {
-			return null;
+	walk : function(o, f, n, s) {
+		s = s || this;
+
+		if (o) {
+			if (n)
+				o = o[n];
+
+			tinymce.each(o, function(o, i) {
+				if (f.call(s, o, i, n) === false)
+					return false;
+
+				tinymce.walk(o, f, n, s);
+			});
 		}
 	},
 
-	queryCommandState : function(c) {
-		return this.getDoc().queryCommandState(c);
-	},
-
-	_onAdd : function(replace_element, form_element_name, target_document) {
-		var hc, th, to, editorTemplate;
-
-		th = this.settings['theme'];
-		to = tinyMCE.themes[th];
-
-		var targetDoc = target_document ? target_document : document;
-
-		this.targetDoc = targetDoc;
-
-		tinyMCE.themeURL = tinyMCE.baseURL + "/themes/" + this.settings['theme'];
-		this.settings['themeurl'] = tinyMCE.themeURL;
-
-		if (!replace_element) {
-			alert("Error: Could not find the target element.");
-			return false;
-		}
-
-		if (to.getEditorTemplate)
-			editorTemplate = to.getEditorTemplate(this.settings, this.editorId);
-
-		var deltaWidth = editorTemplate['delta_width'] ? editorTemplate['delta_width'] : 0;
-		var deltaHeight = editorTemplate['delta_height'] ? editorTemplate['delta_height'] : 0;
-		var html = '<span id="' + this.editorId + '_parent" class="mceEditorContainer">' + editorTemplate['html'];
-
-		html = tinyMCE.replaceVar(html, "editor_id", this.editorId);
-		this.settings['default_document'] = tinyMCE.baseURL + "/blank.htm";
-
-		this.settings['old_width'] = this.settings['width'];
-		this.settings['old_height'] = this.settings['height'];
-
-		// Set default width, height
-		if (this.settings['width'] == -1)
-			this.settings['width'] = replace_element.offsetWidth;
-
-		if (this.settings['height'] == -1)
-			this.settings['height'] = replace_element.offsetHeight;
-
-		// Try the style width
-		if (this.settings['width'] == 0)
-			this.settings['width'] = replace_element.style.width;
-
-		// Try the style height
-		if (this.settings['height'] == 0)
-			this.settings['height'] = replace_element.style.height; 
-
-		// If no width/height then default to 320x240, better than nothing
-		if (this.settings['width'] == 0)
-			this.settings['width'] = 320;
-
-		if (this.settings['height'] == 0)
-			this.settings['height'] = 240;
-
-		this.settings['area_width'] = parseInt(this.settings['width']);
-		this.settings['area_height'] = parseInt(this.settings['height']);
-		this.settings['area_width'] += deltaWidth;
-		this.settings['area_height'] += deltaHeight;
-
-		this.settings['width_style'] = "" + this.settings['width'];
-		this.settings['height_style'] = "" + this.settings['height'];
-
-		// Special % handling
-		if (("" + this.settings['width']).indexOf('%') != -1)
-			this.settings['area_width'] = "100%";
-		else
-			this.settings['width_style'] += 'px';
-
-		if (("" + this.settings['height']).indexOf('%') != -1)
-			this.settings['area_height'] = "100%";
-		else
-			this.settings['height_style'] += 'px';
-
-		if (("" + replace_element.style.width).indexOf('%') != -1) {
-			this.settings['width'] = replace_element.style.width;
-			this.settings['area_width'] = "100%";
-			this.settings['width_style'] = "100%";
-		}
-
-		if (("" + replace_element.style.height).indexOf('%') != -1) {
-			this.settings['height'] = replace_element.style.height;
-			this.settings['area_height'] = "100%";
-			this.settings['height_style'] = "100%";
-		}
-
-		html = tinyMCE.applyTemplate(html);
-
-		this.settings['width'] = this.settings['old_width'];
-		this.settings['height'] = this.settings['old_height'];
-
-		this.visualAid = this.settings['visual'];
-		this.formTargetElementId = form_element_name;
-
-		// Get replace_element contents
-		if (replace_element.nodeName == "TEXTAREA" || replace_element.nodeName == "INPUT")
-			this.startContent = replace_element.value;
-		else
-			this.startContent = replace_element.innerHTML;
-
-		// If not text area or input
-		if (replace_element.nodeName != "TEXTAREA" && replace_element.nodeName != "INPUT") {
-			this.oldTargetElement = replace_element;
-
-			// Debug mode
-			if (tinyMCE.settings['debug']) {
-				hc = '<textarea wrap="off" id="' + form_element_name + '" name="' + form_element_name + '" cols="100" rows="15"></textarea>';
-			} else {
-				hc = '<input type="hidden" id="' + form_element_name + '" name="' + form_element_name + '" />';
-				this.oldTargetDisplay = tinyMCE.getStyle(this.oldTargetElement, 'display', 'inline');
-				this.oldTargetElement.style.display = "none";
-			}
-
-			html += '</span>';
-
-			if (tinyMCE.isGecko)
-				html = hc + html;
-			else
-				html += hc;
-
-			// Output HTML and set editable
-			if (tinyMCE.isGecko) {
-				var rng = replace_element.ownerDocument.createRange();
-				rng.setStartBefore(replace_element);
-
-				var fragment = rng.createContextualFragment(html);
-				tinyMCE.insertAfter(fragment, replace_element);
-			} else
-				replace_element.insertAdjacentHTML("beforeBegin", html);
-		} else {
-			html += '</span>';
-
-			// Just hide the textarea element
-			this.oldTargetElement = replace_element;
-
-			if (!tinyMCE.settings['debug']) {
-				this.oldTargetDisplay = tinyMCE.getStyle(this.oldTargetElement, 'display', 'inline');
-				this.oldTargetElement.style.display = "none";
-			}
-
-			// Output HTML and set editable
-			if (tinyMCE.isGecko) {
-				var rng = replace_element.ownerDocument.createRange();
-				rng.setStartBefore(replace_element);
-
-				var fragment = rng.createContextualFragment(html);
-				tinyMCE.insertAfter(fragment, replace_element);
-			} else
-				replace_element.insertAdjacentHTML("beforeBegin", html);
-		}
-
-		// Setup iframe
-		var dynamicIFrame = false;
-		var tElm = targetDoc.getElementById(this.editorId);
-
-		if (!tinyMCE.isIE) {
-			// Node case is preserved in XML strict mode
-			if (tElm && (tElm.nodeName == "SPAN" || tElm.nodeName == "span")) {
-				tElm = tinyMCE._createIFrame(tElm, targetDoc);
-				dynamicIFrame = true;
-			}
-
-			this.targetElement = tElm;
-			this.iframeElement = tElm;
-			this.contentDocument = tElm.contentDocument;
-			this.contentWindow = tElm.contentWindow;
-
-			//this.getDoc().designMode = "on";
-		} else {
-			if (tElm && tElm.nodeName == "SPAN")
-				tElm = tinyMCE._createIFrame(tElm, targetDoc, targetDoc.parentWindow);
-			else
-				tElm = targetDoc.frames[this.editorId];
-
-			this.targetElement = tElm;
-			this.iframeElement = targetDoc.getElementById(this.editorId);
-
-			if (tinyMCE.isOpera) {
-				this.contentDocument = this.iframeElement.contentDocument;
-				this.contentWindow = this.iframeElement.contentWindow;
-				dynamicIFrame = true;
-			} else {
-				this.contentDocument = tElm.window.document;
-				this.contentWindow = tElm.window;
-			}
-
-			this.getDoc().designMode = "on";
-		}
-
-		// Setup base HTML
-		var doc = this.contentDocument;
-		if (dynamicIFrame) {
-			var html = tinyMCE.getParam('doctype') + '<html><head xmlns="http://www.w3.org/1999/xhtml"><base href="' + tinyMCE.settings['base_href'] + '" /><title>blank_page</title><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"></head><body class="mceContentBody"></body></html>';
-
-			try {
-				if (!this.isHidden())
-					this.getDoc().designMode = "on";
-
-				doc.open();
-        //alert('docwrite 3');
-				doc.write(html);
-				doc.close();
-			} catch (e) {
-				// Failed Mozilla 1.3
-				this.getDoc().location.href = tinyMCE.baseURL + "/blank.htm";
-			}
-		}
-
-		// This timeout is needed in MSIE 5.5 for some odd reason
-		// it seems that the document.frames isn't initialized yet?
-		if (tinyMCE.isIE)
-			window.setTimeout("tinyMCE.addEventHandlers(tinyMCE.instances[\"" + this.editorId + "\"]);", 1);
-
-		// Setup element references
-		var parentElm = this.targetDoc.getElementById(this.editorId + '_parent');
-		this.formElement = tinyMCE.isGecko ? parentElm.previousSibling : parentElm.nextSibling;
-
-		tinyMCE.setupContent(this.editorId, true);
-
-		return true;
-	},
-
-	setBaseHREF : function(u) {
-		var h, b, d, nl;
-
-		d = this.getDoc();
-		nl = d.getElementsByTagName("base");
-		b = nl.length > 0 ? nl[0] : null;
-
-		if (!b) {
-			nl = d.getElementsByTagName("head");
-			h = nl.length > 0 ? nl[0] : null;
-
-			b = d.createElement("base");
-			b.setAttribute('href', u);
-			h.appendChild(b);
-		} else {
-			if (u == "" || u == null)
-				b.parentNode.removeChild(b);
-			else
-				b.setAttribute('href', u);
-		}
-	},
-
-	getHTML : function(r) {
-		var h, d = this.getDoc(), b = this.getBody();
-
-		if (r)
-			return b.innerHTML;
-
-		h = tinyMCE._cleanupHTML(this, d, this.settings, b, false, true, false, true);
-
-		if (tinyMCE.getParam("convert_fonts_to_spans"))
-			tinyMCE.convertSpansToFonts(d);
-
-		return h;
-	},
-
-	setHTML : function(h) {
-		this.execCommand('mceSetContent', false, h);
-		this.repaint();
-	},
-
-	getFocusElement : function() {
-		return this.selection.getFocusElement();
-	},
-
-	getSel : function() {
-		return this.selection.getSel();
-	},
-
-	getRng : function() {
-		return this.selection.getRng();
-	},
-
-	triggerSave : function(skip_cleanup, skip_callback) {
-		var e, nl = [], i, s;
-
-		this.switchSettings();
-		s = tinyMCE.settings;
-
-		// Force hidden tabs visible while serializing
-		if (tinyMCE.isRealIE) {
-			e = this.iframeElement;
-
-			do {
-				if (e.style && e.style.display == 'none') {
-					e.style.display = 'block';
-					nl[nl.length] = {elm : e, type : 'style'};
-				}
-
-				if (e.style && s.hidden_tab_class.length > 0 && e.className.indexOf(s.hidden_tab_class) != -1) {
-					e.className = s.display_tab_class;
-					nl[nl.length] = {elm : e, type : 'class'};
-				}
-			} while ((e = e.parentNode) != null)
-		}
-
-		tinyMCE.settings['preformatted'] = false;
-
-		// Default to false
-		if (typeof(skip_cleanup) == "undefined")
-			skip_cleanup = false;
-
-		// Default to false
-		if (typeof(skip_callback) == "undefined")
-			skip_callback = false;
-
-		tinyMCE._setHTML(this.getDoc(), this.getBody().innerHTML);
-
-		// Remove visual aids when cleanup is disabled
-		if (this.settings['cleanup'] == false) {
-			tinyMCE.handleVisualAid(this.getBody(), true, false, this);
-			tinyMCE._setEventsEnabled(this.getBody(), true);
-		}
-
-		tinyMCE._customCleanup(this, "submit_content_dom", this.contentWindow.document.body);
-		var htm = skip_cleanup ? this.getBody().innerHTML : tinyMCE._cleanupHTML(this, this.getDoc(), this.settings, this.getBody(), tinyMCE.visualAid, true, true);
-		htm = tinyMCE._customCleanup(this, "submit_content", htm);
-
-		if (!skip_callback && tinyMCE.settings['save_callback'] != "")
-			var content = eval(tinyMCE.settings['save_callback'] + "(this.formTargetElementId,htm,this.getBody());");
-
-		// Use callback content if available
-		if ((typeof(content) != "undefined") && content != null)
-			htm = content;
-
-		// Replace some weird entities (Bug: #1056343)
-		htm = tinyMCE.regexpReplace(htm, "&#40;", "(", "gi");
-		htm = tinyMCE.regexpReplace(htm, "&#41;", ")", "gi");
-		htm = tinyMCE.regexpReplace(htm, "&#59;", ";", "gi");
-		htm = tinyMCE.regexpReplace(htm, "&#34;", "&quot;", "gi");
-		htm = tinyMCE.regexpReplace(htm, "&#94;", "^", "gi");
-
-		if (this.formElement)
-			this.formElement.value = htm;
-
-		if (tinyMCE.isSafari && this.formElement)
-			this.formElement.innerText = htm;
-
-		// Hide them again (tabs in MSIE)
-		for (i=0; i<nl.length; i++) {
-			if (nl[i].type == 'style')
-				nl[i].elm.style.display = 'none';
-			else
-				nl[i].elm.className = s.hidden_tab_class;
-		}
-	}
-
-	};
-
-/* file:jscripts/tiny_mce/classes/TinyMCE_Cleanup.class.js */
-
-TinyMCE_Engine.prototype.cleanupHTMLCode = function(s) {
-	s = s.replace(new RegExp('<p \\/>', 'gi'), '<p>&nbsp;</p>');
-	s = s.replace(new RegExp('<p>\\s*<\\/p>', 'gi'), '<p>&nbsp;</p>');
-
-	// Fix close BR elements
-	s = s.replace(new RegExp('<br>\\s*<\\/br>', 'gi'), '<br />');
-
-	// Open closed tags like <b/> to <b></b>
-	s = s.replace(new RegExp('<(h[1-6]|p|div|address|pre|form|table|li|ol|ul|td|b|font|em|strong|i|strike|u|span|a|ul|ol|li|blockquote)([a-z]*)([^\\\\|>]*)\\/>', 'gi'), '<$1$2$3></$1$2>');
-
-	// Remove trailing space <b > to <b>
-	s = s.replace(new RegExp('\\s+></', 'gi'), '></');
-
-	// Close tags <img></img> to <img/>
-	s = s.replace(new RegExp('<(img|br|hr)([^>]*)><\\/(img|br|hr)>', 'gi'), '<$1$2 />');
-
-	// Weird MSIE bug, <p><hr /></p> breaks runtime?
-	if (tinyMCE.isIE)
-		s = s.replace(new RegExp('<p><hr \\/><\\/p>', 'gi'), "<hr>");
-
-	// Weird tags will make IE error #bug: 1538495
-	if (tinyMCE.isIE)
-		s = s.replace(/<!(\s*)\/>/g, '');
-
-	// Convert relative anchors to absolute URLs ex: #something to file.htm#something
-	// Removed: Since local document anchors should never be forced absolute example edit.php?id=something
-	//if (tinyMCE.getParam('convert_urls'))
-	//	s = s.replace(new RegExp('(href=\"{0,1})(\\s*#)', 'gi'), '$1' + tinyMCE.settings['document_base_url'] + "#");
-
-	return s;
-};
-
-TinyMCE_Engine.prototype.parseStyle = function(str) {
-	var ar = new Array();
-
-	if (str == null)
-		return ar;
-
-	var st = str.split(';');
-
-	tinyMCE.clearArray(ar);
-
-	for (var i=0; i<st.length; i++) {
-		if (st[i] == '')
-			continue;
-
-		var re = new RegExp('^\\s*([^:]*):\\s*(.*)\\s*$');
-		var pa = st[i].replace(re, '$1||$2').split('||');
-//tinyMCE.debug(str, pa[0] + "=" + pa[1], st[i].replace(re, '$1||$2'));
-		if (pa.length == 2)
-			ar[pa[0].toLowerCase()] = pa[1];
-	}
-
-	return ar;
-};
-
-TinyMCE_Engine.prototype.compressStyle = function(ar, pr, sf, res) {
-	var box = new Array();
-
-	box[0] = ar[pr + '-top' + sf];
-	box[1] = ar[pr + '-left' + sf];
-	box[2] = ar[pr + '-right' + sf];
-	box[3] = ar[pr + '-bottom' + sf];
-
-	for (var i=0; i<box.length; i++) {
-		if (box[i] == null)
-			return;
-
-		for (var a=0; a<box.length; a++) {
-			if (box[a] != box[i])
-				return;
-		}
-	}
-
-	// They are all the same
-	ar[res] = box[0];
-	ar[pr + '-top' + sf] = null;
-	ar[pr + '-left' + sf] = null;
-	ar[pr + '-right' + sf] = null;
-	ar[pr + '-bottom' + sf] = null;
-};
-
-TinyMCE_Engine.prototype.serializeStyle = function(ar) {
-	var str = "";
-
-	// Compress box
-	tinyMCE.compressStyle(ar, "border", "", "border");
-	tinyMCE.compressStyle(ar, "border", "-width", "border-width");
-	tinyMCE.compressStyle(ar, "border", "-color", "border-color");
-	tinyMCE.compressStyle(ar, "border", "-style", "border-style");
-	tinyMCE.compressStyle(ar, "padding", "", "padding");
-	tinyMCE.compressStyle(ar, "margin", "", "margin");
-
-	for (var key in ar) {
-		var val = ar[key];
-
-		if (typeof(val) == 'function')
-			continue;
-
-		if (key.indexOf('mso-') == 0)
-			continue;
-
-		if (val != null && val != '') {
-			val = '' + val; // Force string
-
-			// Fix style URL
-			val = val.replace(new RegExp("url\\(\\'?([^\\']*)\\'?\\)", 'gi'), "url('$1')");
-
-			// Convert URL
-			if (val.indexOf('url(') != -1 && tinyMCE.getParam('convert_urls')) {
-				var m = new RegExp("url\\('(.*?)'\\)").exec(val);
-
-				if (m.length > 1)
-					val = "url('" + eval(tinyMCE.getParam('urlconverter_callback') + "(m[1], null, true);") + "')";
-			}
-
-			// Force HEX colors
-			if (tinyMCE.getParam("force_hex_style_colors"))
-				val = tinyMCE.convertRGBToHex(val, true);
-
-			val = val.replace(/\"/g, '\'');
-
-			if (val != "url('')")
-				str += key.toLowerCase() + ": " + val + "; ";
-		}
-	}
-
-	if (new RegExp('; $').test(str))
-		str = str.substring(0, str.length - 2);
-
-	return str;
-};
-
-TinyMCE_Engine.prototype.convertRGBToHex = function(s, k) {
-	if (s.toLowerCase().indexOf('rgb') != -1) {
-		var re = new RegExp("(.*?)rgb\\s*?\\(\\s*?([0-9]+).*?,\\s*?([0-9]+).*?,\\s*?([0-9]+).*?\\)(.*?)", "gi");
-		var rgb = s.replace(re, "$1,$2,$3,$4,$5").split(',');
-		if (rgb.length == 5) {
-			r = parseInt(rgb[1]).toString(16);
-			g = parseInt(rgb[2]).toString(16);
-			b = parseInt(rgb[3]).toString(16);
-
-			r = r.length == 1 ? '0' + r : r;
-			g = g.length == 1 ? '0' + g : g;
-			b = b.length == 1 ? '0' + b : b;
-
-			s = "#" + r + g + b;
-
-			if (k)
-				s = rgb[0] + s + rgb[4];
-		}
-	}
-
-	return s;
-};
-
-TinyMCE_Engine.prototype.convertHexToRGB = function(s) {
-	if (s.indexOf('#') != -1) {
-		s = s.replace(new RegExp('[^0-9A-F]', 'gi'), '');
-		return "rgb(" + parseInt(s.substring(0, 2), 16) + "," + parseInt(s.substring(2, 4), 16) + "," + parseInt(s.substring(4, 6), 16) + ")";
-	}
-
-	return s;
-};
-
-TinyMCE_Engine.prototype.convertSpansToFonts = function(doc) {
-	var sizes = tinyMCE.getParam('font_size_style_values').replace(/\s+/, '').split(',');
-
-	/*var h = doc.body.innerHTML;
-	h = h.replace(/<span/gi, '<font');
-	h = h.replace(/<\/span/gi, '</font');
-	tinyMCE.setInnerHTML(doc.body, h);*/
-
-	var s = tinyMCE.selectElements(doc, 'span,font');
-	for (var i=0; i<s.length; i++) {
-		var size = tinyMCE.trim(s[i].style.fontSize).toLowerCase();
-		var fSize = 0;
-
-		for (var x=0; x<sizes.length; x++) {
-			if (sizes[x] == size) {
-				fSize = x + 1;
-				break;
-			}
-		}
-
-		if (fSize > 0) {
-			tinyMCE.setAttrib(s[i], 'size', fSize);
-			s[i].style.fontSize = '';
-		}
-
-		var fFace = s[i].style.fontFamily;
-		if (fFace != null && fFace != "") {
-			tinyMCE.setAttrib(s[i], 'face', fFace);
-			s[i].style.fontFamily = '';
-		}
-
-		var fColor = s[i].style.color;
-		if (fColor != null && fColor != "") {
-			tinyMCE.setAttrib(s[i], 'color', tinyMCE.convertRGBToHex(fColor));
-			s[i].style.color = '';
-		}
-	}
-};
-
-TinyMCE_Engine.prototype.convertFontsToSpans = function(doc) {
-	var sizes = tinyMCE.getParam('font_size_style_values').replace(/\s+/, '').split(',');
-
-/*	var h = doc.body.innerHTML;
-	h = h.replace(/<font/gi, '<span');
-	h = h.replace(/<\/font/gi, '</span');
-	tinyMCE.setInnerHTML(doc.body, h);*/
-
-	var fsClasses = tinyMCE.getParam('font_size_classes');
-	if (fsClasses != '')
-		fsClasses = fsClasses.replace(/\s+/, '').split(',');
-	else
-		fsClasses = null;
-
-	var s = tinyMCE.selectElements(doc, 'span,font');
-	for (var i=0; i<s.length; i++) {
-		var fSize, fFace, fColor;
-
-		fSize = tinyMCE.getAttrib(s[i], 'size');
-		fFace = tinyMCE.getAttrib(s[i], 'face');
-		fColor = tinyMCE.getAttrib(s[i], 'color');
-
-		if (fSize != "") {
-			fSize = parseInt(fSize);
-
-			if (fSize > 0 && fSize < 8) {
-				if (fsClasses != null)
-					tinyMCE.setAttrib(s[i], 'class', fsClasses[fSize-1]);
-				else
-					s[i].style.fontSize = sizes[fSize-1];
-			}
-
-			s[i].removeAttribute('size');
-		}
-
-		if (fFace != "") {
-			s[i].style.fontFamily = fFace;
-			s[i].removeAttribute('face');
-		}
-
-		if (fColor != "") {
-			s[i].style.color = fColor;
-			s[i].removeAttribute('color');
-		}
-	}
-};
-
-TinyMCE_Engine.prototype.cleanupAnchors = function(doc) {
-	var i, cn, x, an = doc.getElementsByTagName("a");
-
-	// Loops backwards due to bug #1467987
-	for (i=an.length-1; i>=0; i--) {
-		if (tinyMCE.getAttrib(an[i], "name") != "" && tinyMCE.getAttrib(an[i], "href") == "") {
-			cn = an[i].childNodes;
-
-			for (x=cn.length-1; x>=0; x--)
-				tinyMCE.insertAfter(cn[x], an[i]);
-		}
-	}
-};
-
-TinyMCE_Engine.prototype.getContent = function(editor_id) {
-	if (typeof(editor_id) != "undefined")
-		 tinyMCE.getInstanceById(editor_id).select();
-
-	if (tinyMCE.selectedInstance)
-		return tinyMCE.selectedInstance.getHTML();
-
-	return null;
-};
-
-TinyMCE_Engine.prototype._fixListElements = function(d) {
-	var nl, x, a = ['ol', 'ul'], i, n, p, r = new RegExp('^(OL|UL)$'), np;
-
-	for (x=0; x<a.length; x++) {
-		nl = d.getElementsByTagName(a[x]);
-
-		for (i=0; i<nl.length; i++) {
-			n = nl[i];
-			p = n.parentNode;
-
-			if (r.test(p.nodeName)) {
-				np = tinyMCE.prevNode(n, 'LI');
-
-				if (!np) {
-					np = d.createElement('li');
-					np.innerHTML = '&nbsp;';
-					np.appendChild(n);
-					p.insertBefore(np, p.firstChild);
-				} else
-					np.appendChild(n);
-			}
-		}
-	}
-};
-
-TinyMCE_Engine.prototype._fixTables = function(d) {
-	var nl, i, n, p, np, x, t;
-
-	nl = d.getElementsByTagName('table');
-	for (i=0; i<nl.length; i++) {
-		n = nl[i];
-
-		if ((p = tinyMCE.getParentElement(n, 'p,h1,h2,h3,h4,h5,h6')) != null) {
-			np = p.cloneNode(false);
-			np.removeAttribute('id');
-
-			t = n;
-
-			while ((n = n.nextSibling))
-				np.appendChild(n);
-
-			tinyMCE.insertAfter(np, p);
-			tinyMCE.insertAfter(t, p);
+	createNS : function(n, o) {
+		var i, v;
+
+		o = o || window;
+
+		n = n.split('.');
+		for (i=0; i<n.length; i++) {
+			v = n[i];
+
+			if (!o[v])
+				o[v] = {};
+
+			o = o[v];
 		}
-	}
-};
-
-TinyMCE_Engine.prototype._cleanupHTML = function(inst, doc, config, elm, visual, on_save, on_submit, inn) {
-	var h, d, t1, t2, t3, t4, t5, c, s, nb;
-
-	if (!tinyMCE.getParam('cleanup'))
-		return elm.innerHTML;
-
-	on_save = typeof(on_save) == 'undefined' ? false : on_save;
-
-	c = inst.cleanup;
-	s = inst.settings;
-	d = c.settings.debug;
-
-	if (d)
-		t1 = new Date().getTime();
-
-	if (tinyMCE.getParam("convert_fonts_to_spans"))
-		tinyMCE.convertFontsToSpans(doc);
-
-	if (tinyMCE.getParam("fix_list_elements"))
-		tinyMCE._fixListElements(doc);
-
-	if (tinyMCE.getParam("fix_table_elements"))
-		tinyMCE._fixTables(doc);
-
-	// Call custom cleanup code
-	tinyMCE._customCleanup(inst, on_save ? "get_from_editor_dom" : "insert_to_editor_dom", doc.body);
-
-	if (d)
-		t2 = new Date().getTime();
-
-	c.settings.on_save = on_save;
-	//for (var i=0; i<100; i++)
-
-	c.idCount = 0;
-	c.serializationId++;
-	c.serializedNodes = new Array();
-	c.sourceIndex = -1;
-
-	if (s.cleanup_serializer == "xml")
-		h = c.serializeNodeAsXML(elm, inn);
-	else
-		h = c.serializeNodeAsHTML(elm, inn);
-
-	if (d)
-		t3 = new Date().getTime();
-
-	// Post processing
-	nb = tinyMCE.getParam('entity_encoding') == 'numeric' ? '&#160;' : '&nbsp;';
-	h = h.replace(/<\/?(body|head|html)[^>]*>/gi, '');
-	h = h.replace(new RegExp(' (rowspan="1"|colspan="1")', 'g'), '');
-	h = h.replace(/<p><hr \/><\/p>/g, '<hr />');
-	h = h.replace(/<p>(&nbsp;|&#160;)<\/p><hr \/><p>(&nbsp;|&#160;)<\/p>/g, '<hr />');
-	h = h.replace(/<td>\s*<br \/>\s*<\/td>/g, '<td>' + nb + '</td>');
-	h = h.replace(/<p>\s*<br \/>\s*<\/p>/g, '<p>' + nb + '</p>');
-	h = h.replace(/<br \/>$/, ''); // Remove last BR for Gecko
-	h = h.replace(/<br \/><\/p>/g, '</p>'); // Remove last BR in P tags for Gecko
-	h = h.replace(/<p>\s*(&nbsp;|&#160;)\s*<br \/>\s*(&nbsp;|&#160;)\s*<\/p>/g, '<p>' + nb + '</p>');
-	h = h.replace(/<p>\s*(&nbsp;|&#160;)\s*<br \/>\s*<\/p>/g, '<p>' + nb + '</p>');
-	h = h.replace(/<p>\s*<br \/>\s*&nbsp;\s*<\/p>/g, '<p>' + nb + '</p>');
-	h = h.replace(new RegExp('<a>(.*?)<\\/a>', 'g'), '$1');
-	h = h.replace(/<p([^>]*)>\s*<\/p>/g, '<p$1>' + nb + '</p>');
-
-	// Clean body
-	if (/^\s*(<br \/>|<p>&nbsp;<\/p>|<p>&#160;<\/p>|<p><\/p>)\s*$/.test(h))
-		h = '';
-
-	// If preformatted
-	if (s.preformatted) {
-		h = h.replace(/^<pre>/, '');
-		h = h.replace(/<\/pre>$/, '');
-		h = '<pre>' + h + '</pre>';
-	}
-
-	// Gecko specific processing
-	if (tinyMCE.isGecko) {
-		h = h.replace(/<o:p _moz-userdefined="" \/>/g, '');
-		h = h.replace(/<td([^>]*)>\s*<br \/>\s*<\/td>/g, '<td$1>' + nb + '</td>');
-	}
-
-	if (s.force_br_newlines)
-		h = h.replace(/<p>(&nbsp;|&#160;)<\/p>/g, '<br />');
-
-	// Call custom cleanup code
-	h = tinyMCE._customCleanup(inst, on_save ? "get_from_editor" : "insert_to_editor", h);
-
-	// Remove internal classes
-	if (on_save) {
-		h = h.replace(new RegExp(' ?(mceItem[a-zA-Z0-9]*|' + s.visual_table_class + ')', 'g'), '');
-		h = h.replace(new RegExp(' ?class=""', 'g'), '');
-	}
-
-	if (s.remove_linebreaks && !c.settings.indent)
-		h = h.replace(/\n|\r/g, ' ');
-
-	if (d)
-		t4 = new Date().getTime();
-
-	if (on_save && c.settings.indent)
-		h = c.formatHTML(h);
-
-	// If encoding (not recommended option)
-	if (on_submit && (s.encoding == "xml" || s.encoding == "html"))
-		h = c.xmlEncode(h);
-
-	if (d)
-		t5 = new Date().getTime();
-
-	if (c.settings.debug)
-		tinyMCE.debug("Cleanup in ms: Pre=" + (t2-t1) + ", Serialize: " + (t3-t2) + ", Post: " + (t4-t3) + ", Format: " + (t5-t4) + ", Sum: " + (t5-t1) + ".");
-
-	return h;
-};
-
-function TinyMCE_Cleanup() {
-	this.isIE = (navigator.appName == "Microsoft Internet Explorer");
-	this.rules = tinyMCE.clearArray(new Array());
-
-	// Default config
-	this.settings = {
-		indent_elements : 'head,table,tbody,thead,tfoot,form,tr,ul,ol,blockquote,object',
-		newline_before_elements : 'h1,h2,h3,h4,h5,h6,pre,address,div,ul,ol,li,meta,option,area,title,link,base,script,td',
-		newline_after_elements : 'br,hr,p,pre,address,div,ul,ol,meta,option,area,link,base,script',
-		newline_before_after_elements : 'html,head,body,table,thead,tbody,tfoot,tr,form,ul,ol,blockquote,p,object,param,hr,div',
-		indent_char : '\t',
-		indent_levels : 1,
-		entity_encoding : 'raw',
-		valid_elements : '*[*]',
-		entities : '',
-		url_converter : '',
-		invalid_elements : '',
-		verify_html : false
-	};
-
-	this.vElements = tinyMCE.clearArray(new Array());
-	this.vElementsRe = '';
-	this.closeElementsRe = /^(IMG|BR|HR|LINK|META|BASE|INPUT|AREA)$/;
-	this.codeElementsRe = /^(SCRIPT|STYLE)$/;
-	this.serializationId = 0;
-	this.mceAttribs = {
-		href : 'mce_href',
-		src : 'mce_src',
-		type : 'mce_type'
-	};
-}
-
-TinyMCE_Cleanup.prototype = {
-	init : function(s) {
-		var n, a, i, ir, or, st;
-
-		for (n in s)
-			this.settings[n] = s[n];
-
-		// Setup code formating
-		s = this.settings;
-
-		// Setup regexps
-		this.inRe = this._arrayToRe(s.indent_elements.split(','), '', '^<(', ')[^>]*');
-		this.ouRe = this._arrayToRe(s.indent_elements.split(','), '', '^<\\/(', ')[^>]*');
-		this.nlBeforeRe = this._arrayToRe(s.newline_before_elements.split(','), 'gi', '<(',  ')([^>]*)>');
-		this.nlAfterRe = this._arrayToRe(s.newline_after_elements.split(','), 'gi', '<(',  ')([^>]*)>');
-		this.nlBeforeAfterRe = this._arrayToRe(s.newline_before_after_elements.split(','), 'gi', '<(\\/?)(', ')([^>]*)>');
-		this.serializedNodes = [];
-
-		if (s.invalid_elements != '')
-			this.iveRe = this._arrayToRe(s.invalid_elements.toUpperCase().split(','), 'g', '^(', ')$');
-		else
-			this.iveRe = null;
-
-		// Setup separator
-		st = '';
-		for (i=0; i<s.indent_levels; i++)
-			st += s.indent_char;
-
-		this.inStr = st;
-
-		// If verify_html if false force *[*]
-		if (!s.verify_html) {
-			s.valid_elements = '*[*]';
-			s.extended_valid_elements = '';
-		}
-
-		this.fillStr = s.entity_encoding == "named" ? "&nbsp;" : "&#160;";
-		this.idCount = 0;
-		this.xmlEncodeRe = new RegExp('[\u007F-\uFFFF<>&"]', 'g');
-		this.xmlEncodeAposRe = new RegExp('[\u007F-\uFFFF<>&"\']', 'g');
-	},
-
-	addRuleStr : function(s) {
-		var r = this.parseRuleStr(s);
-		var n;
-
-		for (n in r) {
-			if (r[n])
-				this.rules[n] = r[n];
-		}
-
-		this.vElements = tinyMCE.clearArray(new Array());
-
-		for (n in this.rules) {
-			if (this.rules[n])
-				this.vElements[this.vElements.length] = this.rules[n].tag;
-		}
-
-		this.vElementsRe = this._arrayToRe(this.vElements, '');
-	},
-
-	isValid : function(n) {
-		this._setupRules(); // Will initialize cleanup rules
-
-		// Empty is true since it removes formatting
-		if (!n)
-			return true;
-
-		// Clean the name up a bit
-		n = n.replace(/[^a-z0-9]+/gi, '').toUpperCase();
-
-		return !tinyMCE.getParam('cleanup') || this.vElementsRe.test(n);
-	},
-
-	addChildRemoveRuleStr : function(s) {
-		var x, y, p, i, t, tn, ta, cl, r;
-
-		if (!s)
-			return;
-
-		ta = s.split(',');
-		for (x=0; x<ta.length; x++) {
-			s = ta[x];
-
-			// Split tag/children
-			p = this.split(/\[|\]/, s);
-			if (p == null || p.length < 1)
-				t = s.toUpperCase();
-			else
-				t = p[0].toUpperCase();
-
-			// Handle all tag names
-			tn = this.split('/', t);
-			for (y=0; y<tn.length; y++) {
-				r = "^(";
-
-				// Build regex
-				cl = this.split(/\|/, p[1]);
-				for (i=0; i<cl.length; i++) {
-					if (cl[i] == '%istrict')
-						r += tinyMCE.inlineStrict;
-					else if (cl[i] == '%itrans')
-						r += tinyMCE.inlineTransitional;
-					else if (cl[i] == '%istrict_na')
-						r += tinyMCE.inlineStrict.substring(2);
-					else if (cl[i] == '%itrans_na')
-						r += tinyMCE.inlineTransitional.substring(2);
-					else if (cl[i] == '%btrans')
-						r += tinyMCE.blockElms;
-					else if (cl[i] == '%strict')
-						r += tinyMCE.blockStrict;
-					else
-						r += (cl[i].charAt(0) != '#' ? cl[i].toUpperCase() : cl[i]);
-
-					r += (i != cl.length - 1 ? '|' : '');
-				}
-
-				r += ')$';
-//tinyMCE.debug(t + "=" + r);
-				if (this.childRules == null)
-					this.childRules = tinyMCE.clearArray(new Array());
-
-				this.childRules[tn[y]] = new RegExp(r);
-
-				if (p.length > 1)
-					this.childRules[tn[y]].wrapTag = p[2];
-			}
-		}
-	},
-
-	parseRuleStr : function(s) {
-		var ta, p, r, a, i, x, px, t, tn, y, av, or = tinyMCE.clearArray(new Array()), dv;
-
-		if (s == null || s.length == 0)
-			return or;
-
-		ta = s.split(',');
-		for (x=0; x<ta.length; x++) {
-			s = ta[x];
-			if (s.length == 0)
-				continue;
-
-			// Split tag/attrs
-			p = this.split(/\[|\]/, s);
-			if (p == null || p.length < 1)
-				t = s.toUpperCase();
-			else
-				t = p[0].toUpperCase();
-
-			// Handle all tag names
-			tn = this.split('/', t);
-			for (y=0; y<tn.length; y++) {
-				r = {};
-
-				r.tag = tn[y];
-				r.forceAttribs = null;
-				r.defaultAttribs = null;
-				r.validAttribValues = null;
-
-				// Handle prefixes
-				px = r.tag.charAt(0);
-				r.forceOpen = px == '+';
-				r.removeEmpty = px == '-';
-				r.fill = px == '#';
-				r.tag = r.tag.replace(/\+|-|#/g, '');
-				r.oTagName = tn[0].replace(/\+|-|#/g, '').toLowerCase();
-				r.isWild = new RegExp('\\*|\\?|\\+', 'g').test(r.tag);
-				r.validRe = new RegExp(this._wildcardToRe('^' + r.tag + '$'));
-
-				// Setup valid attributes
-				if (p.length > 1) {
-					r.vAttribsRe = '^(';
-					a = this.split(/\|/, p[1]);
-
-					for (i=0; i<a.length; i++) {
-						t = a[i];
-
-						if (t.charAt(0) == '!') {
-							a[i] = t = t.substring(1);
-
-							if (!r.reqAttribsRe)
-								r.reqAttribsRe = '\\s+(' + t;
-							else
-								r.reqAttribsRe += '|' + t;
-						}
-
-						av = new RegExp('(=|:|<)(.*?)$').exec(t);
-						t = t.replace(new RegExp('(=|:|<).*?$'), '');
-						if (av && av.length > 0) {
-							if (av[0].charAt(0) == ':') {
-								if (!r.forceAttribs)
-									r.forceAttribs = tinyMCE.clearArray(new Array());
-
-								r.forceAttribs[t.toLowerCase()] = av[0].substring(1);
-							} else if (av[0].charAt(0) == '=') {
-								if (!r.defaultAttribs)
-									r.defaultAttribs = tinyMCE.clearArray(new Array());
-
-								dv = av[0].substring(1);
-
-								r.defaultAttribs[t.toLowerCase()] = dv == "" ? "mce_empty" : dv;
-							} else if (av[0].charAt(0) == '<') {
-								if (!r.validAttribValues)
-									r.validAttribValues = tinyMCE.clearArray(new Array());
-
-								r.validAttribValues[t.toLowerCase()] = this._arrayToRe(this.split('?', av[0].substring(1)), 'i');
-							}
-						}
-
-						r.vAttribsRe += '' + t.toLowerCase() + (i != a.length - 1 ? '|' : '');
-
-						a[i] = t.toLowerCase();
-					}
-
-					if (r.reqAttribsRe)
-						r.reqAttribsRe = new RegExp(r.reqAttribsRe + ')=\"', 'g');
-
-					r.vAttribsRe += ')$';
-					r.vAttribsRe = this._wildcardToRe(r.vAttribsRe);
-					r.vAttribsReIsWild = new RegExp('\\*|\\?|\\+', 'g').test(r.vAttribsRe);
-					r.vAttribsRe = new RegExp(r.vAttribsRe);
-					r.vAttribs = a.reverse();
-
-					//tinyMCE.debug(r.tag, r.oTagName, r.vAttribsRe, r.vAttribsReWC);
-				} else {
-					r.vAttribsRe = '';
-					r.vAttribs = tinyMCE.clearArray(new Array());
-					r.vAttribsReIsWild = false;
-				}
-
-				or[r.tag] = r;
-			}
-		}
-
-		return or;
-	},
-
-	serializeNodeAsXML : function(n) {
-		var s, b;
-
-		if (!this.xmlDoc) {
-			if (this.isIE) {
-				try {this.xmlDoc = new ActiveXObject('MSXML2.DOMDocument');} catch (e) {}
-
-				if (!this.xmlDoc)
-					try {this.xmlDoc = new ActiveXObject('Microsoft.XmlDom');} catch (e) {}
-			} else
-				this.xmlDoc = document.implementation.createDocument('', '', null);
-
-			if (!this.xmlDoc)
-				alert("Error XML Parser could not be found.");
-		}
-
-		if (this.xmlDoc.firstChild)
-			this.xmlDoc.removeChild(this.xmlDoc.firstChild);
-
-		b = this.xmlDoc.createElement("html");
-		b = this.xmlDoc.appendChild(b);
-
-		this._convertToXML(n, b);
-
-		if (this.isIE)
-			return this.xmlDoc.xml;
-		else
-			return new XMLSerializer().serializeToString(this.xmlDoc);
-	},
-
-	_convertToXML : function(n, xn) {
-		var xd, el, i, l, cn, at, no, hc = false;
-
-		if (tinyMCE.isRealIE && this._isDuplicate(n))
-			return;
-
-		xd = this.xmlDoc;
-
-		switch (n.nodeType) {
-			case 1: // Element
-				hc = n.hasChildNodes();
-
-				el = xd.createElement(n.nodeName.toLowerCase());
-
-				at = n.attributes;
-				for (i=at.length-1; i>-1; i--) {
-					no = at[i];
-
-					if (no.specified && no.nodeValue)
-						el.setAttribute(no.nodeName.toLowerCase(), no.nodeValue);
-				}
-
-				if (!hc && !this.closeElementsRe.test(n.nodeName))
-					el.appendChild(xd.createTextNode(""));
-
-				xn = xn.appendChild(el);
-				break;
-
-			case 3: // Text
-				xn.appendChild(xd.createTextNode(n.nodeValue));
-				return;
-
-			case 8: // Comment
-				xn.appendChild(xd.createComment(n.nodeValue));
-				return;
-		}
-
-		if (hc) {
-			cn = n.childNodes;
-
-			for (i=0, l=cn.length; i<l; i++)
-				this._convertToXML(cn[i], xn);
-		}
-	},
-
-	serializeNodeAsHTML : function(n, inn) {
-		var en, no, h = '', i, l, t, st, r, cn, va = false, f = false, at, hc, cr, nn;
-
-		this._setupRules(); // Will initialize cleanup rules
-
-		if (tinyMCE.isRealIE && this._isDuplicate(n))
-			return '';
-
-		// Skip non valid child elements
-		if (n.parentNode && this.childRules != null) {
-			cr = this.childRules[n.parentNode.nodeName];
-
-			if (typeof(cr) != "undefined" && !cr.test(n.nodeName)) {
-				st = true;
-				t = null;
-			}
-		}
-
-		switch (n.nodeType) {
-			case 1: // Element
-				hc = n.hasChildNodes();
-
-				if (st)
-					break;
-
-				// MSIE sometimes produces <//tag>
-				if ((tinyMCE.isRealIE) && n.nodeName.indexOf('/') != -1)
-					break;
-
-				nn = n.nodeName;
-
-				// Convert fonts to spans
-				if (this.settings.convert_fonts_to_spans) {
-					// On get content FONT -> SPAN
-					if (this.settings.on_save && nn == 'FONT')
-						nn = 'SPAN';
-
-					// On insert content SPAN -> FONT
-					if (!this.settings.on_save && nn == 'SPAN')
-						nn = 'FONT';
-				}
-
-				if (this.vElementsRe.test(nn) && (!this.iveRe || !this.iveRe.test(nn)) && !inn) {
-					va = true;
-
-					r = this.rules[nn];
-					if (!r) {
-						at = this.rules;
-						for (no in at) {
-							if (at[no] && at[no].validRe.test(nn)) {
-								r = at[no];
-								break;
-							}
-						}
-					}
-
-					en = r.isWild ? nn.toLowerCase() : r.oTagName;
-					f = r.fill;
-
-					if (r.removeEmpty && !hc)
-						return "";
-
-					t = '<' + en;
-
-					if (r.vAttribsReIsWild) {
-						// Serialize wildcard attributes
-						at = n.attributes;
-						for (i=at.length-1; i>-1; i--) {
-							no = at[i];
-							if (no.specified && r.vAttribsRe.test(no.nodeName))
-								t += this._serializeAttribute(n, r, no.nodeName);
-						}
-					} else {
-						// Serialize specific attributes
-						for (i=r.vAttribs.length-1; i>-1; i--)
-							t += this._serializeAttribute(n, r, r.vAttribs[i]);
-					}
-
-					// Serialize mce_ atts
-					if (!this.settings.on_save) {
-						at = this.mceAttribs;
-
-						for (no in at) {
-							if (at[no])
-								t += this._serializeAttribute(n, r, at[no]);
-						}
-					}
-
-					// Check for required attribs
-					if (r.reqAttribsRe && !t.match(r.reqAttribsRe))
-						t = null;
-
-					// Close these
-					if (t != null && this.closeElementsRe.test(nn))
-						return t + ' />';
-
-					if (t != null)
-						h += t + '>';
-
-					if (this.isIE && this.codeElementsRe.test(nn))
-						h += n.innerHTML;
-				}
-			break;
-
-			case 3: // Text
-				if (st)
-					break;
-
-				if (n.parentNode && this.codeElementsRe.test(n.parentNode.nodeName))
-					return this.isIE ? '' : n.nodeValue;
-
-				return this.xmlEncode(n.nodeValue);
-
-			case 8: // Comment
-				if (st)
-					break;
-
-				return "<!--" + this._trimComment(n.nodeValue) + "-->";
-		}
-
-		if (hc) {
-			cn = n.childNodes;
-
-			for (i=0, l=cn.length; i<l; i++)
-				h += this.serializeNodeAsHTML(cn[i]);
-		}
-
-		// Fill empty nodes
-		if (f && !hc)
-			h += this.fillStr;
-
-		// End element
-		if (t != null && va)
-			h += '</' + en + '>';
-
-		return h;
-	},
-
-	_serializeAttribute : function(n, r, an) {
-		var av = '', t, os = this.settings.on_save;
-
-		if (os && (an.indexOf('mce_') == 0 || an.indexOf('_moz') == 0))
-			return '';
-
-		if (os && this.mceAttribs[an])
-			av = this._getAttrib(n, this.mceAttribs[an]);
-
-		if (av.length == 0)
-			av = this._getAttrib(n, an);
-
-		if (av.length == 0 && r.defaultAttribs && (t = r.defaultAttribs[an])) {
-			av = t;
-
-			if (av == "mce_empty")
-				return " " + an + '=""';
-		}
-
-		if (r.forceAttribs && (t = r.forceAttribs[an]))
-			av = t;
-
-		if (os && av.length != 0 && /^(src|href|longdesc)$/.test(an))
-			av = this._urlConverter(this, n, av);
-
-		if (av.length != 0 && r.validAttribValues && r.validAttribValues[an] && !r.validAttribValues[an].test(av))
-			return "";
-
-		if (av.length != 0 && av == "{$uid}")
-			av = "uid_" + (this.idCount++);
-
-		if (av.length != 0) {
-			if (an.indexOf('on') != 0)
-				av = this.xmlEncode(av, 1);
-
-			return " " + an + "=" + '"' + av + '"';
-		}
-
-		return "";
-	},
-
-	formatHTML : function(h) {
-		var s = this.settings, p = '', i = 0, li = 0, o = '', l;
-
-		// Replace BR in pre elements to \n
-		h = h.replace(/<pre([^>]*)>(.*?)<\/pre>/gi, function (a, b, c) {
-			c = c.replace(/<br\s*\/>/gi, '\n');
-			return '<pre' + b + '>' + c + '</pre>';
-		});
-
-		h = h.replace(/\r/g, ''); // Windows sux, isn't carriage return a thing of the past :)
-		h = '\n' + h;
-		h = h.replace(new RegExp('\\n\\s+', 'gi'), '\n'); // Remove previous formatting
-		h = h.replace(this.nlBeforeRe, '\n<$1$2>');
-		h = h.replace(this.nlAfterRe, '<$1$2>\n');
-		h = h.replace(this.nlBeforeAfterRe, '\n<$1$2$3>\n');
-		h += '\n';
-
-		//tinyMCE.debug(h);
-
-		while ((i = h.indexOf('\n', i + 1)) != -1) {
-			if ((l = h.substring(li + 1, i)).length != 0) {
-				if (this.ouRe.test(l) && p.length >= s.indent_levels)
-					p = p.substring(s.indent_levels);
-
-				o += p + l + '\n';
-	
-				if (this.inRe.test(l))
-					p += this.inStr;
-			}
-
-			li = i;
-		}
-
-		//tinyMCE.debug(h);
 
 		return o;
 	},
 
-	xmlEncode : function(s, skip_apos) {
-		var cl = this, re = !skip_apos ? this.xmlEncodeAposRe : this.xmlEncodeRe;
-
-		this._setupEntities(); // Will intialize lookup table
-
-		switch (this.settings.entity_encoding) {
-			case "raw":
-				return tinyMCE.xmlEncode(s, skip_apos);
-
-			case "named":
-				return s.replace(re, function (c, b) {
-					b = cl.entities[c.charCodeAt(0)];
-
-					return b ? '&' + b + ';' : c;
-				});
-
-			case "numeric":
-				return s.replace(re, function (c, b) {
-					return b ? '&#' + c.charCodeAt(0) + ';' : c;
-				});
-		}
-
-		return s;
-	},
-
-	split : function(re, s) {
-		var c = s.split(re);
-		var i, l, o = new Array();
-
-		for (i=0, l=c.length; i<l; i++) {
-			if (c[i] != '')
-				o[i] = c[i];
+	resolve : function(n, o) {
+		var i, l;
+
+		o = o || window;
+
+		n = n.split('.');
+		for (i=0, l = n.length; i<l; i++) {
+			o = o[n[i]];
+
+			if (!o)
+				break;
 		}
 
 		return o;
 	},
 
-	_trimComment : function(s) {
-		// Remove mce_src, mce_href
-		s = s.replace(new RegExp('\\smce_src=\"[^\"]*\"', 'gi'), "");
-		s = s.replace(new RegExp('\\smce_href=\"[^\"]*\"', 'gi'), "");
-
-		return s;
-	},
-
-	_getAttrib : function(e, n, d) {
-		var v, ex, nn;
-
-		if (typeof(d) == "undefined")
-			d = "";
-
-		if (!e || e.nodeType != 1)
-			return d;
-
-		try {
-			v = e.getAttribute(n, 0);
-		} catch (ex) {
-			// IE 7 may cast exception on invalid attributes
-			v = e.getAttribute(n, 2);
-		}
-
-		if (n == "class" && !v)
-			v = e.className;
-
-		if (this.isIE) {
-			if (n == "http-equiv")
-				v = e.httpEquiv;
-
-			nn = e.nodeName;
-
-			// Skip the default values that IE returns
-			if (nn == "FORM" && n == "enctype" && v == "application/x-www-form-urlencoded")
-				v = "";
-
-			if (nn == "INPUT" && n == "size" && v == "20")
-				v = "";
-
-			if (nn == "INPUT" && n == "maxlength" && v == "2147483647")
-				v = "";
-		}
-
-		if (n == 'style' && v) {
-			if (!tinyMCE.isOpera)
-				v = e.style.cssText;
-
-			v = tinyMCE.serializeStyle(tinyMCE.parseStyle(v));
-		}
-
-		if (this.settings.on_save && n.indexOf('on') != -1 && this.settings.on_save && v && v != "")
-			v = tinyMCE.cleanupEventStr(v);
-
-		return (v && v != "") ? '' + v : d;
-	},
-
-	_urlConverter : function(c, n, v) {
-		if (!c.settings.on_save)
-			return tinyMCE.convertRelativeToAbsoluteURL(tinyMCE.settings.base_href, v);
-		else if (tinyMCE.getParam('convert_urls')) {
-			if (!this.urlConverter)
-				this.urlConverter = eval(tinyMCE.settings.urlconverter_callback);
-
-			return this.urlConverter(v, n, true);
-		}
-
-		return v;
+	addUnload : function(f, s) {
+		var t = this, w = window, unload;
+
+		f = {func : f, scope : s || this};
+
+		if (!t.unloads) {
+			unload = function() {
+				var li = t.unloads, o, n;
+
+				// Call unload handlers
+				for (n in li) {
+					o = li[n];
+
+					if (o && o.func)
+						o.func.call(o.scope);
+				}
+
+				// Detach unload function
+				if (w.detachEvent)
+					w.detachEvent('onunload', unload);
+				else if (w.removeEventListener)
+					w.removeEventListener('unload', unload, false);
+
+				// Destroy references
+				o = li = w = unload = null;
+
+				// Run garbarge collector on IE
+				if (window.CollectGarbage)
+					window.CollectGarbage();
+			};
+
+			// Attach unload handler
+			if (w.attachEvent)
+				w.attachEvent('onunload', unload);
+			else if (w.addEventListener)
+				w.addEventListener('unload', unload, false);
+
+			// Setup initial unload handler array
+			t.unloads = [f];
+		} else
+			t.unloads.push(f);
+
+		return f;
 	},
 
-	_arrayToRe : function(a, op, be, af) {
-		var i, r;
-
-		op = typeof(op) == "undefined" ? "gi" : op;
-		be = typeof(be) == "undefined" ? "^(" : be;
-		af = typeof(af) == "undefined" ? ")$" : af;
-
-		r = be;
-
-		for (i=0; i<a.length; i++)
-			r += this._wildcardToRe(a[i]) + (i != a.length-1 ? "|" : "");
-
-		r += af;
-
-		return new RegExp(r, op);
-	},
-
-	_wildcardToRe : function(s) {
-		s = s.replace(/\?/g, '(\\S?)');
-		s = s.replace(/\+/g, '(\\S+)');
-		s = s.replace(/\*/g, '(\\S*)');
-
-		return s;
-	},
-
-	_setupEntities : function() {
-		var n, a, i, s = this.settings;
-
-		// Setup entities
-		if (!this.entitiesDone) {
-			if (s.entity_encoding == "named") {
-				n = tinyMCE.clearArray(new Array());
-				a = this.split(',', s.entities);
-				for (i=0; i<a.length; i+=2)
-					n[a[i]] = a[i+1];
-
-				this.entities = n;
-			}
-
-			this.entitiesDone = true;
-		}
-	},
-
-	_setupRules : function() {
-		var s = this.settings;
-
-		// Setup default rule
-		if (!this.rulesDone) {
-			this.addRuleStr(s.valid_elements);
-			this.addRuleStr(s.extended_valid_elements);
-			this.addChildRemoveRuleStr(s.valid_child_elements);
-
-			this.rulesDone = true;
-		}
-	},
-
-	_isDuplicate : function(n) {
-		var i;
-
-		if (!this.settings.fix_content_duplication)
-			return false;
-
-		if (tinyMCE.isRealIE && n.nodeType == 1) {
-			// Mark elements
-			if (n.mce_serialized == this.serializationId)
-				return true;
-
-			n.setAttribute('mce_serialized', this.serializationId);
-		} else {
-			// Search lookup table for text nodes  and comments
-			for (i=0; i<this.serializedNodes.length; i++) {
-				if (this.serializedNodes[i] == n)
-					return true;
-			}
-
-			this.serializedNodes[this.serializedNodes.length] = n;
-		}
-
-		return false;
+	removeUnload : function(f) {
+		var u = this.unloads, r = null;
+
+		tinymce.each(u, function(o, i) {
+			if (o && o.func == f) {
+				u.splice(i, 1);
+				r = f;
+				return false;
+			}
+		});
+
+		return r;
 	}
 
 	};
 
-/* file:jscripts/tiny_mce/classes/TinyMCE_DOMUtils.class.js */
-
-TinyMCE_Engine.prototype.createTagHTML = function(tn, a, h) {
-	var o = '', f = tinyMCE.xmlEncode;
-
-	o = '<' + tn;
-
-	if (a) {
-		for (n in a) {
-			if (typeof(a[n]) != 'function' && a[n] != null)
-				o += ' ' + f(n) + '="' + f('' + a[n]) + '"';
-		}
+// Required for GZip AJAX loading
+window.tinymce = tinymce;
+
+// Initialize the API
+tinymce._init();
+
+/* file:jscripts/tiny_mce/classes/adapter/jquery/adapter.js */
+
+
+/* file:jscripts/tiny_mce/classes/adapter/prototype/adapter.js */
+
+
+/* file:jscripts/tiny_mce/classes/util/Dispatcher.js */
+
+tinymce.create('tinymce.util.Dispatcher', {
+	scope : null,
+	listeners : null,
+
+	Dispatcher : function(s) {
+		this.scope = s || this;
+		this.listeners = [];
+	},
+
+	add : function(cb, s) {
+		this.listeners.push({cb : cb, scope : s || this.scope});
+
+		return cb;
+	},
+
+	addToTop : function(cb, s) {
+		this.listeners.unshift({cb : cb, scope : s || this.scope});
+
+		return cb;
+	},
+
+	remove : function(cb) {
+		var l = this.listeners, o = null;
+
+		tinymce.each(l, function(c, i) {
+			if (cb == c.cb) {
+				o = cb;
+				l.splice(i, 1);
+				return false;
+			}
+		});
+
+		return o;
+	},
+
+	dispatch : function() {
+		var s, a = arguments;
+
+		tinymce.each(this.listeners, function(c) {
+			return s = c.cb.apply(c.scope, a);
+		});
+
+		return s;
 	}
 
-	o += !h ? ' />' : '>' + h + '</' + tn + '>';
-
-	return o;
-};
-
-TinyMCE_Engine.prototype.createTag = function(d, tn, a, h) {
-	var o = d.createElement(tn);
-
-	if (a) {
-		for (n in a) {
-			if (typeof(a[n]) != 'function' && a[n] != null)
-				tinyMCE.setAttrib(o, n, a[n]);
+	});
+
+/* file:jscripts/tiny_mce/classes/util/URI.js */
+
+(function() {
+	var each = tinymce.each;
+
+	tinymce.create('tinymce.util.URI', {
+		URI : function(u, s) {
+			var t = this, o, a, b;
+
+			// Default settings
+			s = t.settings = s || {};
+
+			// Strange app protocol or local anchor
+			if (/^(mailto|news|javascript|about):/i.test(u) || /^\s*#/.test(u)) {
+				t.source = u;
+				return;
+			}
+
+			// Absolute path with no host, fake host and protocol
+			if (u.indexOf('/') === 0 && u.indexOf('//') !== 0)
+				u = (s.base_uri ? s.base_uri.protocol || 'http' : 'http') + '://mce_host' + u;
+
+			// Relative path
+			if (u.indexOf('://') === -1 && u.indexOf('//') !== 0)
+				u = (s.base_uri.protocol || 'http') + '://mce_host' + t.toAbsPath(s.base_uri.path, u);
+
+			// Parse URL (Credits goes to Steave, http://blog.stevenlevithan.com/archives/parseuri)
+			u = u.replace(/@@/g, '(mce_at)'); // Zope 3 workaround, they use @@something
+			u = /^(?:(?![^:@]+:[^:@\/]*@)([^:\/?#.]+):)?(?:\/\/)?((?:(([^:@]*):?([^:@]*))?@)?([^:\/?#]*)(?::(\d*))?)(((\/(?:[^?#](?![^?#\/]*\.[^?#\/.]+(?:[?#]|$)))*\/?)?([^?#\/]*))(?:\?([^#]*))?(?:#(.*))?)/.exec(u);
+			each(["source","protocol","authority","userInfo","user","password","host","port","relative","path","directory","file","query","anchor"], function(v, i) {
+				var s = u[i];
+
+				// Zope 3 workaround, they use @@something
+				if (s)
+					s = s.replace(/\(mce_at\)/g, '@@');
+
+				t[v] = s;
+			});
+
+			if (b = s.base_uri) {
+				if (!t.protocol)
+					t.protocol = b.protocol;
+
+				if (!t.userInfo)
+					t.userInfo = b.userInfo;
+
+				if (!t.port && t.host == 'mce_host')
+					t.port = b.port;
+
+				if (!t.host || t.host == 'mce_host')
+					t.host = b.host;
+
+				t.source = '';
+			}
+
+			//t.path = t.path || '/';
+		},
+
+		setPath : function(p) {
+			var t = this;
+
+			p = /^(.*?)\/?(\w+)?$/.exec(p);
+
+			// Update path parts
+			t.path = p[0];
+			t.directory = p[1];
+			t.file = p[2];
+
+			// Rebuild source
+			t.source = '';
+			t.getURI();
+		},
+
+		toRelative : function(u) {
+			var t = this, o;
+
+			u = new tinymce.util.URI(u, {base_uri : t});
+
+			// Not on same domain/port or protocol
+			if ((u.host != 'mce_host' && t.host != u.host && u.host) || t.port != u.port || t.protocol != u.protocol)
+				return u.getURI();
+
+			o = t.toRelPath(t.path, u.path);
+
+			// Add query
+			if (u.query)
+				o += '?' + u.query;
+
+			// Add anchor
+			if (u.anchor)
+				o += '#' + u.anchor;
+
+			return o;
+		},
+	
+		toAbsolute : function(u, nh) {
+			var u = new tinymce.util.URI(u, {base_uri : this});
+
+			return u.getURI(this.host == u.host ? nh : 0);
+		},
+
+		toRelPath : function(base, path) {
+			var items, bp = 0, out = '', i;
+
+			// Split the paths
+			base = base.substring(0, base.lastIndexOf('/'));
+			base = base.split('/');
+			items = path.split('/');
+
+			if (base.length >= items.length) {
+				for (i = 0; i < base.length; i++) {
+					if (i >= items.length || base[i] != items[i]) {
+						bp = i + 1;
+						break;
+					}
+				}
+			}
+
+			if (base.length < items.length) {
+				for (i = 0; i < items.length; i++) {
+					if (i >= base.length || base[i] != items[i]) {
+						bp = i + 1;
+						break;
+					}
+				}
+			}
+
+			if (bp == 1)
+				return path;
+
+			for (i = 0; i < base.length - (bp - 1); i++)
+				out += "../";
+
+			for (i = bp - 1; i < items.length; i++) {
+				if (i != bp - 1)
+					out += "/" + items[i];
+				else
+					out += items[i];
+			}
+
+			return out;
+		},
+
+		toAbsPath : function(base, path) {
+			var i, nb = 0, o = [];
+
+			// Split paths
+			base = base.split('/');
+			path = path.split('/');
+
+			// Remove empty chunks
+			each(base, function(k) {
+				if (k)
+					o.push(k);
+			});
+
+			base = o;
+
+			// Merge relURLParts chunks
+			for (i = path.length - 1, o = []; i >= 0; i--) {
+				// Ignore empty or .
+				if (path[i].length == 0 || path[i] == ".")
+					continue;
+
+				// Is parent
+				if (path[i] == '..') {
+					nb++;
+					continue;
+				}
+
+				// Move up
+				if (nb > 0) {
+					nb--;
+					continue;
+				}
+
+				o.push(path[i]);
+			}
+
+			i = base.length - nb;
+
+			// If /a/b/c or /
+			if (i <= 0)
+				return '/' + o.reverse().join('/');
+
+			return '/' + base.slice(0, i).join('/') + '/' + o.reverse().join('/');
+		},
+
+		getURI : function(nh) {
+			var s, t = this;
+
+			// Rebuild source
+			if (!t.source || nh) {
+				s = '';
+
+				if (!nh) {
+					if (t.protocol)
+						s += t.protocol + '://';
+
+					if (t.userInfo)
+						s += t.userInfo + '@';
+
+					if (t.host)
+						s += t.host;
+
+					if (t.port)
+						s += ':' + t.port;
+				}
+
+				if (t.path)
+					s += t.path;
+
+				if (t.query)
+					s += '?' + t.query;
+
+				if (t.anchor)
+					s += '#' + t.anchor;
+
+				t.source = s;
+			}
+
+			return t.source;
+		}
+
+		});
+})();
+
+/* file:jscripts/tiny_mce/classes/util/Cookie.js */
+
+(function() {
+	var each = tinymce.each;
+
+	tinymce.create('static tinymce.util.Cookie', {
+		getHash : function(n) {
+			var v = this.get(n), h;
+
+			if (v) {
+				each(v.split('&'), function(v) {
+					v = v.split('=');
+					h = h || {};
+					h[unescape(v[0])] = unescape(v[1]);
+				});
+			}
+
+			return h;
+		},
+
+		setHash : function(n, v, e, p, d, s) {
+			var o = '';
+
+			each(v, function(v, k) {
+				o += (!o ? '' : '&') + escape(k) + '=' + escape(v);
+			});
+
+			this.set(n, o, e, p, d, s);
+		},
+
+		get : function(n) {
+			var c = document.cookie, e, p = n + "=", b;
+
+			// Strict mode
+			if (!c)
+				return;
+
+			b = c.indexOf("; " + p);
+
+			if (b == -1) {
+				b = c.indexOf(p);
+
+				if (b != 0)
+					return null;
+			} else
+				b += 2;
+
+			e = c.indexOf(";", b);
+
+			if (e == -1)
+				e = c.length;
+
+			return unescape(c.substring(b + p.length, e));
+		},
+
+		set : function(n, v, e, p, d, s) {
+			document.cookie = n + "=" + escape(v) +
+				((e) ? "; expires=" + e.toGMTString() : "") +
+				((p) ? "; path=" + escape(p) : "") +
+				((d) ? "; domain=" + d : "") +
+				((s) ? "; secure" : "");
+		},
+
+		remove : function(n, p) {
+			var d = new Date();
+
+			d.setTime(d.getTime() - 1000);
+
+			this.set(n, '', d, p, d);
+		}
+
+		});
+})();
+
+/* file:jscripts/tiny_mce/classes/util/JSON.js */
+
+tinymce.create('static tinymce.util.JSON', {
+	serialize : function(o) {
+		var i, v, s = tinymce.util.JSON.serialize, t;
+
+		if (o == null)
+			return 'null';
+
+		t = typeof o;
+
+		if (t == 'string') {
+			v = '\bb\tt\nn\ff\rr\""\'\'\\\\';
+
+			return '"' + o.replace(/([\u0080-\uFFFF\x00-\x1f\"\'])/g, function(a, b) {
+				i = v.indexOf(b);
+
+				if (i + 1)
+					return '\\' + v.charAt(i + 1);
+
+				a = b.charCodeAt().toString(16);
+
+				return '\\u' + '0000'.substring(a.length) + a;
+			}) + '"';
+		}
+
+		if (t == 'object') {
+			if (o instanceof Array) {
+					for (i=0, v = '['; i<o.length; i++)
+						v += (i > 0 ? ',' : '') + s(o[i]);
+
+					return v + ']';
+				}
+
+				v = '{';
+
+				for (i in o)
+					v += typeof o[i] != 'function' ? (v.length > 1 ? ',"' : '"') + i + '":' + s(o[i]) : '';
+
+				return v + '}';
+		}
+
+		return '' + o;
+	},
+
+	parse : function(s) {
+		try {
+			return eval('(' + s + ')');
+		} catch (ex) {
+			// Ignore
 		}
 	}
 
-	if (h)
-		o.innerHTML = h;
-
-	return o;
-};
-
-TinyMCE_Engine.prototype.getElementByAttributeValue = function(n, e, a, v) {
-	return (n = this.getElementsByAttributeValue(n, e, a, v)).length == 0 ? null : n[0];
-};
-
-TinyMCE_Engine.prototype.getElementsByAttributeValue = function(n, e, a, v) {
-	var i, nl = n.getElementsByTagName(e), o = new Array();
-
-	for (i=0; i<nl.length; i++) {
-		if (tinyMCE.getAttrib(nl[i], a).indexOf(v) != -1)
-			o[o.length] = nl[i];
-	}
-
-	return o;
-};
-
-TinyMCE_Engine.prototype.isBlockElement = function(n) {
-	return n != null && n.nodeType == 1 && this.blockRegExp.test(n.nodeName);
-};
-
-TinyMCE_Engine.prototype.getParentBlockElement = function(n, r) {
-	return this.getParentNode(n, function(n) {
-		return tinyMCE.isBlockElement(n);
-	}, r);
-
-	return null;
-};
-
-TinyMCE_Engine.prototype.insertAfter = function(n, r){
-	if (r.nextSibling)
-		r.parentNode.insertBefore(n, r.nextSibling);
-	else
-		r.parentNode.appendChild(n);
-};
-
-TinyMCE_Engine.prototype.setInnerHTML = function(e, h) {
-	var i, nl, n;
-
-	// Convert all strong/em to b/i in Gecko
-	if (tinyMCE.isGecko) {
-		h = h.replace(/<embed([^>]*)>/gi, '<tmpembed$1>');
-		h = h.replace(/<em([^>]*)>/gi, '<i$1>');
-		h = h.replace(/<tmpembed([^>]*)>/gi, '<embed$1>');
-		h = h.replace(/<strong([^>]*)>/gi, '<b$1>');
-		h = h.replace(/<\/strong>/gi, '</b>');
-		h = h.replace(/<\/em>/gi, '</i>');
-	}
-
-	if (tinyMCE.isRealIE) {
-		// Since MSIE handles invalid HTML better that valid XHTML we
-		// need to make some things invalid. <hr /> gets converted to <hr>.
-		h = h.replace(/\s\/>/g, '>');
-
-		// Since MSIE auto generated emtpy P tags some times we must tell it to keep the real ones
-		h = h.replace(/<p([^>]*)>\u00A0?<\/p>/gi, '<p$1 mce_keep="true">&nbsp;</p>'); // Keep empty paragraphs
-		h = h.replace(/<p([^>]*)>\s*&nbsp;\s*<\/p>/gi, '<p$1 mce_keep="true">&nbsp;</p>'); // Keep empty paragraphs
-		h = h.replace(/<p([^>]*)>\s+<\/p>/gi, '<p$1 mce_keep="true">&nbsp;</p>'); // Keep empty paragraphs
-
-		// Remove first comment
-		e.innerHTML = tinyMCE.uniqueTag + h;
-		e.firstChild.removeNode(true);
-
-		// Remove weird auto generated empty paragraphs unless it's supposed to be there
-		nl = e.getElementsByTagName("p");
-		for (i=nl.length-1; i>=0; i--) {
-			n = nl[i];
-
-			if (n.nodeName == 'P' && !n.hasChildNodes() && !n.mce_keep)
-				n.parentNode.removeChild(n);
+	});
+
+/* file:jscripts/tiny_mce/classes/util/XHR.js */
+
+tinymce.create('static tinymce.util.XHR', {
+	send : function(o) {
+		var x, t, w = window, c = 0;
+
+		// Default settings
+		o.scope = o.scope || this;
+		o.success_scope = o.success_scope || o.scope;
+		o.error_scope = o.error_scope || o.scope;
+		o.async = o.async === false ? false : true;
+		o.data = o.data || '';
+
+		function get(s) {
+			x = 0;
+
+			try {
+				x = new ActiveXObject(s);
+			} catch (ex) {
+			}
+
+			return x;
+		};
+
+		x = w.XMLHttpRequest ? new XMLHttpRequest() : get('Microsoft.XMLHTTP') || get('Msxml2.XMLHTTP');
+
+		if (x) {
+			if (x.overrideMimeType)
+				x.overrideMimeType(o.content_type);
+
+			x.open(o.type || (o.data ? 'POST' : 'GET'), o.url, o.async);
+
+			if (o.content_type)
+				x.setRequestHeader('Content-Type', o.content_type);
+
+			x.send(o.data);
+
+			// Wait for response, onReadyStateChange can not be used since it leaks memory in IE
+			t = w.setInterval(function() {
+				if (x.readyState == 4 || c++ > 10000) {
+					w.clearInterval(t);
+
+					if (o.success && c < 10000 && x.status == 200)
+						o.success.call(o.success_scope, '' + x.responseText, x, o);
+					else if (o.error)
+						o.error.call(o.error_scope, c > 10000 ? 'TIMED_OUT' : 'GENERAL', x, o);
+
+					x = null;
+				}
+			}, 10);
+		}
+
+		}
+});
+
+/* file:jscripts/tiny_mce/classes/util/JSONRequest.js */
+
+(function() {
+	var extend = tinymce.extend, JSON = tinymce.util.JSON, XHR = tinymce.util.XHR;
+
+	tinymce.create('tinymce.util.JSONRequest', {
+		JSONRequest : function(s) {
+			this.settings = extend({
+			}, s);
+			this.count = 0;
+		},
+
+		send : function(o) {
+			var ecb = o.error, scb = o.success;
+
+			o = extend(this.settings, o);
+
+			o.success = function(c, x) {
+				c = JSON.parse(c);
+
+				if (typeof(c) == 'undefined') {
+					c = {
+						error : 'JSON Parse error.'
+					};
+				}
+
+				if (c.error)
+					ecb.call(o.error_scope || o.scope, c.error, x);
+				else
+					scb.call(o.success_scope || o.scope, c.result);
+			};
+
+			o.error = function(ty, x) {
+				ecb.call(o.error_scope || o.scope, ty, x);
+			};
+
+			o.data = JSON.serialize({
+				id : o.id || 'c' + (this.count++),
+				method : o.method,
+				params : o.params
+			});
+
+			XHR.send(o);
+		},
+
+		'static' : {
+			sendRPC : function(o) {
+				return new tinymce.util.JSONRequest().send(o);
+			}
 		}
-	} else {
-		h = this.fixGeckoBaseHREFBug(1, e, h);
-		e.innerHTML = h;
-		this.fixGeckoBaseHREFBug(2, e, h);
-	}
-};
-
-TinyMCE_Engine.prototype.getOuterHTML = function(e) {
-	if (tinyMCE.isIE)
-		return e.outerHTML;
-
-	var d = e.ownerDocument.createElement("body");
-	d.appendChild(e.cloneNode(true));
-	return d.innerHTML;
-};
-
-TinyMCE_Engine.prototype.setOuterHTML = function(e, h, d) {
-	var d = typeof(d) == "undefined" ? e.ownerDocument : d, i, nl, t;
-
-	if (tinyMCE.isIE && e.nodeType == 1)
-		e.outerHTML = h;
-	else {
-		t = d.createElement("body");
-		t.innerHTML = h;
-
-		for (i=0, nl=t.childNodes; i<nl.length; i++)
-			e.parentNode.insertBefore(nl[i].cloneNode(true), e);
-
-		e.parentNode.removeChild(e);
-	}
-};
-
-TinyMCE_Engine.prototype._getElementById = function(id, d) {
-	var e, i, j, f;
-
-	if (typeof(d) == "undefined")
-		d = document;
-
-	e = d.getElementById(id);
-	if (!e) {
-		f = d.forms;
-
-		for (i=0; i<f.length; i++) {
-			for (j=0; j<f[i].elements.length; j++) {
-				if (f[i].elements[j].name == id) {
-					e = f[i].elements[j];
+
+		});
+}());
+/* file:jscripts/tiny_mce/classes/dom/DOMUtils.js */
+
+(function() {
+	// Shorten names
+	var each = tinymce.each, is = tinymce.is;
+	var isWebKit = tinymce.isWebKit, isIE = tinymce.isIE;
+
+	tinymce.create('tinymce.dom.DOMUtils', {
+		doc : null,
+		root : null,
+		files : null,
+		listeners : {},
+		pixelStyles : /^(top|left|bottom|right|width|height|borderWidth)$/,
+		cache : {},
+		idPattern : /^#[\w]+$/,
+		elmPattern : /^[\w_*]+$/,
+		elmClassPattern : /^([\w_]*)\.([\w_]+)$/,
+
+		DOMUtils : function(d, s) {
+			var t = this;
+
+			t.doc = d;
+			t.files = {};
+			t.cssFlicker = false;
+			t.counter = 0;
+			t.boxModel = !tinymce.isIE || d.compatMode == "CSS1Compat"; 
+
+			this.settings = s = tinymce.extend({
+				keep_values : false,
+				hex_colors : 1,
+				process_html : 1
+			}, s);
+
+			// Fix IE6SP2 flicker and check it failed for pre SP2
+			if (tinymce.isIE6) {
+				try {
+					d.execCommand('BackgroundImageCache', false, true);
+				} catch (e) {
+					t.cssFlicker = true;
+				}
+			}
+
+			tinymce.addUnload(function() {
+				t.doc = t.root = null;
+			});
+		},
+
+		getRoot : function() {
+			var t = this, s = t.settings;
+
+			return (s && t.get(s.root_element)) || t.doc.body;
+		},
+
+		getViewPort : function(w) {
+			var d, b;
+
+			w = !w ? window : w;
+			d = w.document;
+			b = this.boxModel ? d.documentElement : d.body;
+
+			// Returns viewport size excluding scrollbars
+			return {
+				x : w.pageXOffset || b.scrollLeft,
+				y : w.pageYOffset || b.scrollTop,
+				w : w.innerWidth || b.clientWidth,
+				h : w.innerHeight || b.clientHeight
+			};
+		},
+
+		getRect : function(e) {
+			var p, t = this, w, h;
+
+			e = t.get(e);
+			p = t.getPos(e);
+			w = t.getStyle(e, 'width');
+			h = t.getStyle(e, 'height');
+
+			// Non pixel value, then force offset/clientWidth
+			if (w.indexOf('px') === -1)
+				w = 0;
+
+			// Non pixel value, then force offset/clientWidth
+			if (h.indexOf('px') === -1)
+				h = 0;
+
+			return {
+				x : p.x,
+				y : p.y,
+				w : parseInt(w) || e.offsetWidth || e.clientWidth,
+				h : parseInt(h) || e.offsetHeight || e.clientHeight
+			};
+		},
+
+		getParent : function(n, f, r) {
+			var na, se = this.settings;
+
+			n = this.get(n);
+
+			if (se.strict_root)
+				r = r || this.getRoot();
+
+			// Wrap node name as func
+			if (is(f, 'string')) {
+				na = f.toUpperCase();
+
+				f = function(n) {
+					var s = false;
+
+					// Any element
+					if (n.nodeType == 1 && na === '*') {
+						s = true;
+						return false;
+					}
+
+					each(na.split(','), function(v) {
+						if (n.nodeType == 1 && ((se.strict && n.nodeName.toUpperCase() == v) || n.nodeName == v)) {
+							s = true;
+							return false; // Break loop
+						}
+					});
+
+					return s;
+				};
+			}
+
+			while (n) {
+				if (n == r)
+					return null;
+
+				if (f(n))
+					return n;
+
+				n = n.parentNode;
+			}
+
+			return null;
+		},
+
+		get : function(e) {
+			if (typeof(e) == 'string')
+				return this.doc.getElementById(e);
+
+			return e;
+		},
+
+		// #if !jquery
+
+		select : function(pa, s) {
+			var t = this, cs, c, pl, o = [], x, i, l, n;
+
+			s = t.get(s) || t.doc;
+
+			if (t.settings.strict) {
+				function get(s, n) {
+					return s.getElementsByTagName(n.toLowerCase());
+				};
+			} else {
+				function get(s, n) {
+					return s.getElementsByTagName(n);
+				};
+			}
+
+			// Simple element pattern. For example: "p" or "*"
+			if (t.elmPattern.test(pa)) {
+				x = get(s, pa);
+
+				for (i = 0, l = x.length; i<l; i++)
+					o.push(x[i]);
+
+				return o;
+			}
+
+			// Simple class pattern. For example: "p.class" or ".class"
+			if (t.elmClassPattern.test(pa)) {
+				pl = t.elmClassPattern.exec(pa);
+				x = get(s, pl[1] || '*');
+				c = ' ' + pl[2] + ' ';
+
+				for (i = 0, l = x.length; i<l; i++) {
+					n = x[i];
+
+					if (n.className && (' ' + n.className + ' ').indexOf(c) !== -1)
+						o.push(n);
+				}
+
+				return o;
+			}
+
+			function collect(n) {
+				if (!n.mce_save) {
+					n.mce_save = 1;
+					o.push(n);
+				}
+			};
+
+			function collectIE(n) {
+				if (!n.getAttribute('mce_save')) {
+					n.setAttribute('mce_save', '1');
+					o.push(n);
+				}
+			};
+
+			function find(n, f, r) {
+				var i, l, nl = get(r, n);
+
+				for (i = 0, l = nl.length; i < l; i++)
+					f(nl[i]);
+			};
+
+			each(pa.split(','), function(v, i) {
+				v = tinymce.trim(v);
+
+				// Simple element pattern, most common in TinyMCE
+				if (t.elmPattern.test(v)) {
+					each(get(s, v), function(n) {
+						collect(n);
+					});
+
+					return;
+				}
+
+				// Simple element pattern with class, fairly common in TinyMCE
+				if (t.elmClassPattern.test(v)) {
+					x = t.elmClassPattern.exec(v);
+
+					each(get(s, x[1]), function(n) {
+						if (t.hasClass(n, x[2]))
+							collect(n);
+					});
+
+					return;
+				}
+
+				if (!(cs = t.cache[pa])) {
+					cs = 'x=(function(cf, s) {';
+					pl = v.split(' ');
+
+					each(pl, function(v) {
+						var p = /^([\w\\*]+)?(?:#([\w\\]+))?(?:\.([\w\\\.]+))?(?:\[\@([\w\\]+)([\^\$\*!]?=)([\w\\]+)\])?(?:\:([\w\\]+))?/i.exec(v);
+
+						// Find elements
+						p[1] = p[1] || '*';
+						cs += 'find("' + p[1] + '", function(n) {';
+
+						// Check id
+						if (p[2])
+							cs += 'if (n.id !== "' + p[2] + '") return;';
+
+						// Check classes
+						if (p[3]) {
+							cs += 'var c = " " + n.className + " ";';
+							cs += 'if (';
+							c = '';
+							each(p[3].split('.'), function(v) {
+								if (v)
+									c += (c ? '||' : '') + 'c.indexOf(" ' + v + ' ") === -1';
+							});
+							cs += c + ') return;';
+						}
+					});
+
+					cs += 'cf(n);';
+
+					for (i = pl.length - 1; i >= 0; i--)
+						cs += '}, ' + (i ? 'n' : 's') + ');';
+
+					cs += '})';
+
+					// Compile CSS pattern function
+					t.cache[pa] = cs = eval(cs);
+				}
+
+				// Run selector function
+				cs(isIE ? collectIE : collect, s);
+			});
+
+			// Cleanup
+			each(o, function(n) {
+				if (isIE)
+					n.removeAttribute('mce_save');
+				else
+					delete n.mce_save;
+			});
+
+			return o;
+		},
+
+		// #endif
+
+		add : function(p, n, a, h, c) {
+			var t = this;
+
+			return this.run(p, function(p) {
+				var e, k;
+
+				e = is(n, 'string') ? t.doc.createElement(n) : n;
+
+				if (a) {
+					for (k in a) {
+						if (a.hasOwnProperty(k) && !is(a[k], 'object'))
+							t.setAttrib(e, k, '' + a[k]);
+					}
+
+					if (a.style && !is(a.style, 'string')) {
+						each(a.style, function(v, n) {
+							t.setStyle(e, n, v);
+						});
+					}
+				}
+
+				if (h) {
+					if (h.nodeType)
+						e.appendChild(h);
+					else
+						t.setHTML(e, h);
+				}
+
+				return !c ? p.appendChild(e) : e;
+			});
+		},
+
+		create : function(n, a, h) {
+			return this.add(this.doc.createElement(n), n, a, h, 1);
+		},
+
+		createHTML : function(n, a, h) {
+			var o = '', t = this, k;
+
+			o += '<' + n;
+
+			for (k in a) {
+				if (a.hasOwnProperty(k))
+					o += ' ' + k + '="' + t.encode(a[k]) + '"';
+			}
+
+			if (tinymce.is(h))
+				return o + '>' + h + '</' + n + '>';
+
+			return o + ' />';
+		},
+
+		remove : function(n, k) {
+			return this.run(n, function(n) {
+				var p;
+
+				p = n.parentNode;
+
+				if (!p)
+					return null;
+
+				if (k) {
+					each (n.childNodes, function(c) {
+						p.insertBefore(c.cloneNode(true), n);
+					});
+				}
+
+				return p.removeChild(n);
+			});
+		},
+
+		// #if !jquery
+
+		setStyle : function(n, na, v) {
+			var t = this;
+
+			return t.run(n, function(e) {
+				var s, i;
+
+				s = e.style;
+
+				// Camelcase it, if needed
+				na = na.replace(/-(\D)/g, function(a, b){
+					return b.toUpperCase();
+				});
+
+				// Default px suffix on these
+				if (t.pixelStyles.test(na) && (tinymce.is(v, 'number') || /^[\-0-9\.]+$/.test(v)))
+					v += 'px';
+
+				switch (na) {
+					case 'opacity':
+						// IE specific opacity
+						if (isIE) {
+							s.filter = v === '' ? '' : "alpha(opacity=" + (v * 100) + ")";
+
+							if (!n.currentStyle || !n.currentStyle.hasLayout)
+								s.display = 'inline-block';
+						}
+
+						// Fix for older browsers
+						s['-moz-opacity'] = s['-khtml-opacity'] = v;
+						break;
+
+					case 'float':
+						isIE ? s.styleFloat = v : s.cssFloat = v;
+						break;
+				}
+
+				s[na] = v || '';
+
+				// Force update of the style data
+				if (t.settings.update_styles)
+					t.setAttrib(e, 'mce_style');
+			});
+		},
+
+		getStyle : function(n, na, c) {
+			n = this.get(n);
+
+			if (!n)
+				return false;
+
+			// Gecko
+			if (this.doc.defaultView && c) {
+				// Remove camelcase
+				na = na.replace(/[A-Z]/g, function(a){
+					return '-' + a;
+				});
+
+				try {
+					return this.doc.defaultView.getComputedStyle(n, null).getPropertyValue(na);
+				} catch (ex) {
+					// Old safari might fail
+					return null;
+				}
+			}
+
+			// Camelcase it, if needed
+			na = na.replace(/-(\D)/g, function(a, b){
+				return b.toUpperCase();
+			});
+
+			if (na == 'float')
+				na = isIE ? 'styleFloat' : 'cssFloat';
+
+			// IE & Opera
+			if (n.currentStyle && c)
+				return n.currentStyle[na];
+
+			return n.style[na];
+		},
+
+		setStyles : function(e, o) {
+			var t = this, s = t.settings, ol;
+
+			ol = s.update_styles;
+			s.update_styles = 0;
+
+			each(o, function(v, n) {
+				t.setStyle(e, n, v);
+			});
+
+			// Update style info
+			s.update_styles = ol;
+			if (s.update_styles)
+				t.setAttrib(e, s.cssText);
+		},
+
+		setAttrib : function(e, n, v) {
+			var t = this;
+
+			// Strict XML mode
+			if (t.settings.strict)
+				n = n.toLowerCase();
+
+			return this.run(e, function(e) {
+				var s = t.settings;
+
+				switch (n) {
+					case "style":
+						if (s.keep_values) {
+							if (v)
+								e.setAttribute('mce_style', v, 2);
+							else
+								e.removeAttribute('mce_style', 2);
+						}
+
+						e.style.cssText = v;
+						break;
+
+					case "class":
+						e.className = v;
+						break;
+
+					case "src":
+					case "href":
+						if (s.keep_values) {
+							if (s.url_converter)
+								v = s.url_converter.call(s.url_converter_scope || t, v, n, e);
+
+							t.setAttrib(e, 'mce_' + n, v, 2);
+						}
+
+						break;
+				}
+
+				if (is(v) && v !== null && v.length !== 0)
+					e.setAttribute(n, '' + v, 2);
+				else
+					e.removeAttribute(n, 2);
+			});
+		},
+
+		setAttribs : function(e, o) {
+			var t = this;
+
+			return this.run(e, function(e) {
+				each(o, function(v, n) {
+					t.setAttrib(e, n, v);
+				});
+			});
+		},
+
+		// #endif
+
+		getAttrib : function(e, n, dv) {
+			var v, t = this;
+
+			e = t.get(e);
+
+			if (!e)
+				return false;
+
+			if (!is(dv))
+				dv = "";
+
+			// Try the mce variant for these
+			if (/^(src|href|style|coords)$/.test(n)) {
+				v = e.getAttribute("mce_" + n);
+
+				if (v)
+					return v;
+			}
+
+			v = e.getAttribute(n, 2);
+
+			if (!v) {
+				switch (n) {
+					case 'class':
+						v = e.className;
+						break;
+
+					default:
+						v = e.attributes[n];
+						v = v && is(v.nodeValue) ? v.nodeValue : v;
+				}
+			}
+
+			switch (n) {
+				case 'style':
+					v = v || e.style.cssText;
+
+					if (v) {
+						v = t.serializeStyle(t.parseStyle(v));
+
+						if (t.settings.keep_values)
+							e.setAttribute('mce_style', v);
+					}
+
+					break;
+			}
+
+			// Remove Apple and WebKit stuff
+			if (isWebKit && n === "class" && v)
+				v = v.replace(/(apple|webkit)\-[a-z\-]+/gi, '');
+
+			// Handle IE issues
+			if (isIE) {
+				switch (n) {
+					case 'rowspan':
+					case 'colspan':
+						// IE returns 1 as default value
+						if (v === 1)
+							v = '';
+
+						break;
+
+					case 'size':
+						// IE returns +0 as default value for size
+						if (v === '+0')
+							v = '';
+
+						break;
+
+					case 'hspace':
+						// IE returns -1 as default value
+						if (v === -1)
+							v = '';
+
+						break;
+
+					case 'tabindex':
+						// IE returns 32768 as default value
+						if (v === 32768)
+							v = '';
+
+						break;
+
+					case 'shape':
+						v = v.toLowerCase();
+						break;
+
+					default:
+						// IE has odd anonymous function for event attributes
+						if (n.indexOf('on') === 0 && v)
+							v = ('' + v).replace(/^function\s+anonymous\(\)\s+\{\s+(.*)\s+\}$/, '$1');
+				}
+			}
+
+			return (v && v != '') ? '' + v : dv;
+		},
+
+		getPos : function(n) {
+			var t = this, x = 0, y = 0, e, d = t.doc, r;
+
+			n = t.get(n);
+
+			// Use getBoundingClientRect on IE, Opera has it but it's not perfect
+			if (n && isIE) {
+				n = n.getBoundingClientRect();
+				e = t.boxModel ? d.documentElement : d.body;
+				x = t.getStyle(t.select('html')[0], 'borderWidth'); // Remove border
+				x = (x == 'medium' || t.boxModel && !t.isIE6) && 2 || x;
+				n.top += window.self != window.top ? 2 : 0; // IE adds some strange extra cord if used in a frameset
+
+				return {x : n.left + e.scrollLeft - x, y : n.top + e.scrollTop - x};
+			}
+
+			r = n;
+			while (r) {
+				x += r.offsetLeft || 0;
+				y += r.offsetTop || 0;
+
+				r = r.offsetParent;
+			}
+
+			r = n;
+			while (r) {
+				x -= r.scrollLeft || 0;
+				y -= r.scrollTop || 0;
+
+				r = r.parentNode;
+
+				if (r == d.body)
 					break;
+			}
+
+			return {x : x, y : y};
+		},
+
+		parseStyle : function(st) {
+			var t = this, s = t.settings, o = {};
+
+			if (!st)
+				return o;
+
+			function compress(p, s, ot) {
+				var t, r, b, l;
+
+				// Get values and check it it needs compressing
+				t = o[p + '-top' + s];
+				if (!t)
+					return;
+
+				r = o[p + '-right' + s];
+				if (t != r)
+					return;
+
+				b = o[p + '-bottom' + s];
+				if (r != b)
+					return;
+
+				l = o[p + '-left' + s];
+				if (b != l)
+					return;
+
+				// Compress
+				o[ot] = l;
+				delete o[p + '-top' + s];
+				delete o[p + '-right' + s];
+				delete o[p + '-bottom' + s];
+				delete o[p + '-left' + s];
+			};
+
+			function compress2(ta, a, b, c) {
+				var t;
+
+				t = o[a];
+				if (!t)
+					return;
+
+				t = o[b];
+				if (!t)
+					return;
+
+				t = o[c];
+				if (!t)
+					return;
+
+				// Compress
+				o[ta] = o[a] + ' ' + o[b] + ' ' + o[c];
+				delete o[a];
+				delete o[b];
+				delete o[c];
+			};
+
+			each(st.split(';'), function(v) {
+				var sv, ur = [];
+
+				if (v) {
+					v = v.replace(/url\([^\)]+\)/g, function(v) {ur.push(v);return 'url(' + ur.length + ')';});
+					v = v.split(':');
+					sv = tinymce.trim(v[1]);
+					sv = sv.replace(/url\(([^\)]+)\)/g, function(a, b) {return ur[parseInt(b) - 1];});
+
+					sv = sv.replace(/rgb\([^\)]+\)/g, function(v) {
+						return t.toHex(v);
+					});
+
+					if (s.url_converter) {
+						sv = sv.replace(/url\([\'\"]?([^\)\'\"]+)[\'\"]?\)/g, function(x, c) {
+							return 'url(' + t.encode(s.url_converter.call(s.url_converter_scope || t, t.decode(c), 'style', null)) + ')';
+						});
+					}
+
+					o[tinymce.trim(v[0]).toLowerCase()] = sv;
+				}
+			});
+
+			compress("border", "", "border");
+			compress("border", "-width", "border-width");
+			compress("border", "-color", "border-color");
+			compress("border", "-style", "border-style");
+			compress("padding", "", "padding");
+			compress("margin", "", "margin");
+			compress2('border', 'border-width', 'border-style', 'border-color');
+
+			if (isIE) {
+				// Remove pointless border
+				if (o.border == 'medium none')
+					o.border = '';
+			}
+
+			return o;
+		},
+
+		serializeStyle : function(o) {
+			var s = '';
+
+			each(o, function(v, k) {
+				if (k && v) {
+					switch (k) {
+						case 'color':
+						case 'background-color':
+							v = v.toLowerCase();
+							break;
+					}
+
+					s += (s ? ' ' : '') + k + ': ' + v + ';';
+				}
+			});
+
+			return s;
+		},
+
+		loadCSS : function(u) {
+			var t = this, d = this.doc;
+
+			if (!u)
+				u = '';
+
+			each(u.split(','), function(u) {
+				if (t.files[u])
+					return;
+
+				t.files[u] = true;
+
+				if (!d.createStyleSheet)
+					t.add(t.select('head')[0], 'link', {rel : 'stylesheet', href : u});
+				else
+					d.createStyleSheet(u);
+			});
+		},
+
+		// #if !jquery
+
+		addClass : function(e, c) {
+			return this.run(e, function(e) {
+				var o;
+
+				if (!c)
+					return 0;
+
+				if (this.hasClass(e, c))
+					return e.className;
+
+				o = this.removeClass(e, c);
+
+				return e.className = (o != '' ? (o + ' ') : '') + c;
+			});
+		},
+
+		removeClass : function(e, c) {
+			var t = this, re;
+
+			return t.run(e, function(e) {
+				var v;
+
+				if (t.hasClass(e, c)) {
+					if (!re)
+						re = new RegExp("(^|\\s+)" + c + "(\\s+|$)", "g");
+
+					v = e.className.replace(re, ' ');
+
+					return e.className = tinymce.trim(v != ' ' ? v : '');
+				}
+
+				return e.className;
+			});
+		},
+
+		hasClass : function(n, c) {
+			n = this.get(n);
+
+			if (!n || !c)
+				return false;
+
+			return (' ' + n.className + ' ').indexOf(' ' + c + ' ') !== -1;
+		},
+
+		show : function(e) {
+			return this.setStyle(e, 'display', 'block');
+		},
+
+		hide : function(e) {
+			return this.setStyle(e, 'display', 'none');
+		},
+
+		isHidden : function(e) {
+			e = this.get(e);
+
+			return e.style.display == 'none' || this.getStyle(e, 'display') == 'none';
+		},
+
+		// #endif
+
+		uniqueId : function(p) {
+			return (!p ? 'mce_' : p) + (this.counter++);
+		},
+
+		setHTML : function(e, h) {
+			var t = this;
+
+			return this.run(e, function(e) {
+				var x;
+
+				h = t.processHTML(h);
+
+				if (isIE) {
+					try {
+						// IE will remove comments from the beginning
+						// unless you padd the contents with something
+						e.innerHTML = '<br />' + h;
+						e.removeChild(e.firstChild);
+					} catch (ex) {
+						// IE sometimes produces an unknown runtime error on innerHTML
+						// This seems to fix this issue, don't know why.
+						x = t.create('div');
+						x.innerHTML = '<br />' + h;
+
+						each (x.childNodes, function(n, i) {
+							// Skip the BR
+							if (i > 1)
+								e.appendChild(n);
+						});
+					}
+				} else
+					e.innerHTML = h;
+
+				return h;
+			});
+		},
+
+		processHTML : function(h) {
+			var t = this, s = t.settings;
+
+			if (!s.process_html)
+				return h;
+
+			// Convert strong and em to b and i in FF since it can't handle them
+			if (tinymce.isGecko) {
+				h = h.replace(/<(\/?)strong>|<strong( [^>]+)>/gi, '<$1b$2>');
+				h = h.replace(/<(\/?)em>|<em( [^>]+)>/gi, '<$1i$2>');
+			}
+
+			// Fix some issues
+			h = h.replace(/<a( )([^>]+)\/>|<a\/>/gi, '<a$1$2></a>'); // Force open
+
+			// Store away src and href in mce_src and mce_href since browsers mess them up
+			if (s.keep_values) {
+				// Wrap scripts in comments for serialization purposes
+				if (h.indexOf('<script') !== -1) {
+					h = h.replace(/<script>/g, '<script type="text/javascript">');
+					h = h.replace(/<script(|[^>]+)>(\s*<!--|\/\/\s*<\[CDATA\[)?[\r\n]*/g, '<mce:script$1><!--\n');
+					h = h.replace(/\s*(\/\/\s*-->|\/\/\s*]]>)?<\/script>/g, '\n// --></mce:script>');
+					h = h.replace(/<mce:script(|[^>]+)><!--\n\/\/ --><\/mce:script>/g, '<mce:script$1></mce:script>');
+				}
+
+				// Process all tags with src, href or style
+				h = h.replace(/<([\w:]+) [^>]*(src|href|style|coords)[^>]*>/gi, function(a, n) {
+					function handle(m, b, c) {
+						var u = c;
+
+						// Tag already got a mce_ version
+						if (a.indexOf('mce_' + b) != -1)
+							return m;
+
+						if (b == 'style') {
+							// Why did I need this one?
+							//if (isIE)
+							//	u = t.serializeStyle(t.parseStyle(u));
+
+							if (s.hex_colors) {
+								u = u.replace(/rgb\([^\)]+\)/g, function(v) {
+									return t.toHex(v);
+								});
+							}
+
+							if (s.url_converter) {
+								u = u.replace(/url\([\'\"]?([^\)\'\"]+)\)/g, function(x, c) {
+									return 'url(' + t.encode(s.url_converter.call(s.url_converter_scope || t, t.decode(c), b, n)) + ')';
+								});
+							}
+						} else if (b != 'coords') {
+							if (s.url_converter)
+								u = t.encode(s.url_converter.call(s.url_converter_scope || t, t.decode(c), b, n));
+						}
+
+						return ' ' + b + '="' + c + '" mce_' + b + '="' + u + '"';
+					};
+
+					a = a.replace(/ (src|href|style|coords)=[\"]([^\"]+)[\"]/gi, handle); // W3C
+					a = a.replace(/ (src|href|style|coords)=[\']([^\']+)[\']/gi, handle); // W3C
+
+					return a.replace(/ (src|href|style|coords)=([^\s\"\'>]+)/gi, handle); // IE
+				});
+			}
+
+			return h;
+		},
+
+		getOuterHTML : function(e) {
+			var d;
+
+			e = this.get(e);
+
+			if (!e)
+				return null;
+
+			if (isIE)
+				return e.outerHTML;
+
+			d = (e.ownerDocument || this.doc).createElement("body");
+			d.appendChild(e.cloneNode(true));
+
+			return d.innerHTML;
+		},
+
+		setOuterHTML : function(e, h, d) {
+			var t = this;
+
+			return this.run(e, function(e) {
+				var n, tp;
+
+				e = t.get(e);
+				d = d || e.ownerDocument || t.doc;
+
+				if (isIE && e.nodeType == 1)
+					e.outerHTML = h;
+				else {
+					tp = d.createElement("body");
+					tp.innerHTML = h;
+
+					n = tp.lastChild;
+					while (n) {
+						t.insertAfter(n.cloneNode(true), e);
+						n = n.previousSibling;
+					}
+
+					t.remove(e);
+				}
+			});
+		},
+
+		decode : function(s) {
+			var e = document.createElement("div");
+
+			e.innerHTML = s;
+
+			return !e.firstChild ? s : e.firstChild.nodeValue;
+		},
+
+		encode : function(s) {
+			return s ? ('' + s).replace(/[<>&\"]/g, function (c, b) {
+				switch (c) {
+					case '&':
+						return '&amp;';
+
+					case '"':
+						return '&quot;';
+
+					case '<':
+						return '&lt;';
+
+					case '>':
+						return '&gt;';
+				}
+
+				return c;
+			}) : s;
+		},
+
+		// #if !jquery
+
+		insertAfter : function(n, r) {
+			var t = this;
+
+			r = t.get(r);
+
+			return this.run(n, function(n) {
+				var p, ns;
+
+				p = r.parentNode;
+				ns = r.nextSibling;
+
+				if (ns)
+					p.insertBefore(n, ns);
+				else
+					p.appendChild(n);
+
+				return n;
+			});
+		},
+
+		// #endif
+
+		isBlock : function(n) {
+			if (n.nodeType && n.nodeType !== 1)
+				return false;
+
+			n = n.nodeName || n;
+
+			return /^(H[1-6]|HR|P|DIV|ADDRESS|PRE|FORM|TABLE|LI|OL|UL|TD|CAPTION|BLOCKQUOTE|CENTER|DL|DT|DD|DIR|FIELDSET|FORM|NOSCRIPT|NOFRAMES|MENU|ISINDEX|SAMP)$/.test(n);
+		},
+
+		// #if !jquery
+
+		replace : function(n, o, k) {
+			if (is(o, 'array'))
+				n = n.cloneNode(true);
+
+			return this.run(o, function(o) {
+				if (k) {
+					each(o.childNodes, function(c) {
+						n.appendChild(c.cloneNode(true));
+					});
+				}
+
+				return o.parentNode.replaceChild(n, o);
+			});
+		},
+
+		// #endif
+
+		toHex : function(s) {
+			var c = /^\s*rgb\s*?\(\s*?([0-9]+)\s*?,\s*?([0-9]+)\s*?,\s*?([0-9]+)\s*?\)\s*$/i.exec(s);
+
+			function hex(s) {
+				s = parseInt(s).toString(16);
+
+				return s.length > 1 ? s : '0' + s; // 0 -> 00
+			};
+
+			if (c) {
+				s = '#' + hex(c[1]) + hex(c[2]) + hex(c[3]);
+
+				return s;
+			}
+
+			return s;
+		},
+
+		getClasses : function() {
+			var t = this, cl = [], i, lo = {}, f = t.settings.class_filter;
+
+			if (t.classes)
+				return t.classes;
+
+			function addClasses(s) {
+				// IE style imports
+				each(s.imports, function(r) {
+					addClasses(r);
+				});
+
+				each(s.cssRules || s.rules, function(r) {
+					// Real type or fake it on IE
+					switch (r.type || 1) {
+						// Rule
+						case 1:
+							if (r.selectorText) {
+								each(r.selectorText.split(','), function(v) {
+									v = v.replace(/^\s*|\s*$|^\s\./g, "");
+
+									if (f && !(v = f(v)))
+										return;
+
+									if (/^\.mce/.test(v) || !/^\.[\w\-]+$/.test(v))
+										return;
+
+									v = v.substring(1);
+									if (!lo[v]) {
+										cl.push({'class' : v});
+										lo[v] = 1;
+									}
+								});
+							}
+							break;
+
+						// Import
+						case 3:
+							addClasses(r.styleSheet);
+							break;
+					}
+				});
+			};
+
+			try {
+				each(t.doc.styleSheets, addClasses);
+			} catch (ex) {
+				// Ignore
+			}
+
+			if (cl.length > 0)
+				t.classes = cl;
+
+			return cl;
+		},
+
+		run : function(e, f, s) {
+			var t = this, o;
+
+			if (typeof(e) === 'string')
+				e = t.doc.getElementById(e);
+
+			if (!e)
+				return false;
+
+			s = s || this;
+			if (!e.nodeType && (e.length || e.length === 0)) {
+				o = [];
+
+				each(e, function(e, i) {
+					if (e) {
+						if (typeof(e) == 'string')
+							e = t.doc.getElementById(e);
+
+						o.push(f.call(s, e, i));
+					}
+				});
+
+				return o;
+			}
+
+			return f.call(s, e);
+		}
+
+		/*
+		walk : function(n, f, s) {
+			var d = this.doc, w;
+
+			if (d.createTreeWalker) {
+				w = d.createTreeWalker(n, NodeFilter.SHOW_TEXT, null, false);
+
+				while ((n = w.nextNode()) != null)
+					f.call(s || this, n);
+			} else
+				tinymce.walk(n, f, 'childNodes', s);
+		}
+		*/
+
+		/*
+		toRGB : function(s) {
+			var c = /^\s*?#([0-9A-F]{2})([0-9A-F]{1,2})([0-9A-F]{2})?\s*?$/.exec(s);
+
+			if (c) {
+				// #FFF -> #FFFFFF
+				if (!is(c[3]))
+					c[3] = c[2] = c[1];
+
+				return "rgb(" + parseInt(c[1], 16) + "," + parseInt(c[2], 16) + "," + parseInt(c[3], 16) + ")";
+			}
+
+			return s;
+		}
+		*/
+
+		});
+
+	// Setup page DOM
+	tinymce.DOM = new tinymce.dom.DOMUtils(document, {process_html : 0});
+})();
+
+/* file:jscripts/tiny_mce/classes/dom/Event.js */
+
+(function() {
+	// Shorten names
+	var each = tinymce.each, DOM = tinymce.DOM, isIE = tinymce.isIE, isWebKit = tinymce.isWebKit, Event;
+
+	tinymce.create('static tinymce.dom.Event', {
+		inits : [],
+		events : [],
+
+		// #if !jquery
+
+		add : function(o, n, f, s) {
+			var cb, t = this, el = t.events, r;
+
+			// Handle array
+			if (o && o instanceof Array) {
+				r = [];
+
+				each(o, function(o) {
+					o = DOM.get(o);
+					r.push(t.add(o, n, f, s));
+				});
+
+				return r;
+			}
+
+			o = DOM.get(o);
+
+			if (!o)
+				return;
+
+			// Setup event callback
+			cb = function(e) {
+				e = e || window.event;
+
+				// Patch in target in IE it's W3C valid
+				if (e && !e.target && isIE)
+					e.target = e.srcElement;
+
+				if (!s)
+					return f(e);
+
+				return f.call(s, e);
+			};
+
+			if (n == 'unload') {
+				tinymce.unloads.unshift({func : cb});
+				return cb;
+			}
+
+			if (n == 'init') {
+				if (t.domLoaded)
+					cb();
+				else
+					t.inits.push(cb);
+
+				return cb;
+			}
+
+			// Store away listener reference
+			el.push({
+				obj : o,
+				name : n,
+				func : f,
+				cfunc : cb,
+				scope : s
+			});
+
+			t._add(o, n, cb);
+
+			return f;
+		},
+
+		remove : function(o, n, f) {
+			var t = this, a = t.events, s = false, r;
+
+			// Handle array
+			if (o && o instanceof Array) {
+				r = [];
+
+				each(o, function(o) {
+					o = DOM.get(o);
+					r.push(t.remove(o, n, f));
+				});
+
+				return r;
+			}
+
+			o = DOM.get(o);
+
+			each(a, function(e, i) {
+				if (e.obj == o && e.name == n && (!f || (e.func == f || e.cfunc == f))) {
+					a.splice(i, 1);
+					t._remove(o, n, e.cfunc);
+					s = true;
+					return false;
+				}
+			});
+
+			return s;
+		},
+
+		// #endif
+
+		cancel : function(e) {
+			if (!e)
+				return false;
+
+			this.stop(e);
+			return this.prevent(e);
+		},
+
+		stop : function(e) {
+			if (e.stopPropagation)
+				e.stopPropagation();
+			else
+				e.cancelBubble = true;
+
+			return false;
+		},
+
+		prevent : function(e) {
+			if (e.preventDefault)
+				e.preventDefault();
+			else
+				e.returnValue = false;
+
+			return false;
+		},
+
+		_unload : function() {
+			var t = Event;
+
+			each(t.events, function(e, i) {
+				t._remove(e.obj, e.name, e.cfunc);
+				e.obj = e.cfunc = null;
+			});
+
+			t.events = [];
+			t = null;
+		},
+
+		_add : function(o, n, f) {
+			if (o.attachEvent)
+				o.attachEvent('on' + n, f);
+			else if (o.addEventListener)
+				o.addEventListener(n, f, false);
+			else
+				o['on' + n] = f;
+		},
+
+		_remove : function(o, n, f) {
+			if (o.detachEvent)
+				o.detachEvent('on' + n, f);
+			else if (o.removeEventListener)
+				o.removeEventListener(n, f, false);
+			else
+				o['on' + n] = null;
+		},
+
+		_pageInit : function() {
+			var e = Event;
+
+			e._remove(window, 'DOMContentLoaded', e._pageInit);
+			e.domLoaded = true;
+
+			each(e.inits, function(c) {
+				c();
+			});
+
+			e.inits = [];
+		},
+
+		_wait : function() {
+			var t;
+
+			// No need since the document is already loaded
+			if (window.tinyMCE_GZ && tinyMCE_GZ.loaded)
+				return;
+
+			if (isIE && document.location.protocol != 'https:') {
+				// Fake DOMContentLoaded on IE
+				document.write('<script id=__ie_onload defer src=\'javascript:""\';><\/script>');
+				DOM.get("__ie_onload").onreadystatechange = function() {
+					if (this.readyState == "complete") {
+						Event._pageInit();
+						DOM.get("__ie_onload").onreadystatechange = null; // Prevent leak
+					}
+				};
+			} else {
+				Event._add(window, 'DOMContentLoaded', Event._pageInit, Event);
+
+				if (isIE || isWebKit) {
+					t = setInterval(function() {
+						if (/loaded|complete/.test(document.readyState)) {
+							clearInterval(t);
+							Event._pageInit();
+						}
+					}, 10);
 				}
 			}
 		}
-	}
-
-	return e;
-};
-
-TinyMCE_Engine.prototype.getNodeTree = function(n, na, t, nn) {
-	return this.selectNodes(n, function(n) {
-		return (!t || n.nodeType == t) && (!nn || n.nodeName == nn);
-	}, na ? na : new Array());
-};
-
-TinyMCE_Engine.prototype.getParentElement = function(n, na, f, r) {
-	var re = na ? new RegExp('^(' + na.toUpperCase().replace(/,/g, '|') + ')$') : 0, v;
-
-	// Compatiblity with old scripts where f param was a attribute string
-	if (f && typeof(f) == 'string')
-		return this.getParentElement(n, na, function(no) {return tinyMCE.getAttrib(no, f) != '';});
-
-	return this.getParentNode(n, function(n) {
-		return ((n.nodeType == 1 && !re) || (re && re.test(n.nodeName))) && (!f || f(n));
-	}, r);
-};
-
-TinyMCE_Engine.prototype.getParentNode = function(n, f, r) {
-	while (n) {
-		if (n == r)
-			return null;
-
-		if (f(n))
-			return n;
-
-		n = n.parentNode;
-	}
-
-	return null;
-};
-
-TinyMCE_Engine.prototype.getAttrib = function(elm, name, dv) {
-	var v;
-
-	if (typeof(dv) == "undefined")
-		dv = "";
-
-	// Not a element
-	if (!elm || elm.nodeType != 1)
-		return dv;
-
-	try {
-		v = elm.getAttribute(name, 0);
-	} catch (ex) {
-		// IE 7 may cast exception on invalid attributes
-		v = elm.getAttribute(name, 2);
-	}
-
-	// Try className for class attrib
-	if (name == "class" && !v)
-		v = elm.className;
-
-	// Workaround for a issue with Firefox 1.5rc2+
-	if (tinyMCE.isGecko && name == "src" && elm.src != null && elm.src != "")
-		v = elm.src;
-
-	// Workaround for a issue with Firefox 1.5rc2+
-	if (tinyMCE.isGecko && name == "href" && elm.href != null && elm.href != "")
-		v = elm.href;
-
-	if (name == "http-equiv" && tinyMCE.isIE)
-		v = elm.httpEquiv;
-
-	if (name == "style" && !tinyMCE.isOpera)
-		v = elm.style.cssText;
-
-	return (v && v != "") ? v : dv;
-};
-
-TinyMCE_Engine.prototype.setAttrib = function(el, name, va, fix) {
-	if (typeof(va) == "number" && va != null)
-		va = "" + va;
-
-	if (fix) {
-		if (va == null)
-			va = "";
-
-		va = va.replace(/[^0-9%]/g, '');
-	}
-
-	if (name == "style")
-		el.style.cssText = va;
-
-	if (name == "class")
-		el.className = va;
-
-	if (va != null && va != "" && va != -1)
-		el.setAttribute(name, va);
-	else
-		el.removeAttribute(name);
-};
-
-TinyMCE_Engine.prototype.setStyleAttrib = function(e, n, v) {
-	e.style[n] = v;
-
-	// Style attrib deleted in IE
-	if (tinyMCE.isIE && v == null || v == '') {
-		v = tinyMCE.serializeStyle(tinyMCE.parseStyle(e.style.cssText));
-		e.style.cssText = v;
-		e.setAttribute("style", v);
-	}
-};
-
-TinyMCE_Engine.prototype.switchClass = function(ei, c) {
-	var e;
-
-	if (tinyMCE.switchClassCache[ei])
-		e = tinyMCE.switchClassCache[ei];
-	else
-		e = tinyMCE.switchClassCache[ei] = document.getElementById(ei);
-
-	if (e) {
-		// Keep tile mode
-		if (tinyMCE.settings.button_tile_map && e.className && e.className.indexOf('mceTiledButton') == 0)
-			c = 'mceTiledButton ' + c;
-
-		e.className = c;
-	}
-};
-
-TinyMCE_Engine.prototype.getAbsPosition = function(n, cn) {
-	var l = 0, t = 0;
-
-	while (n && n != cn) {
-		l += n.offsetLeft;
-		t += n.offsetTop;
-		n = n.offsetParent;
-	}
-
-	return {absLeft : l, absTop : t};
-};
-
-TinyMCE_Engine.prototype.prevNode = function(e, n) {
-	var a = n.split(','), i;
-
-	while ((e = e.previousSibling) != null) {
-		for (i=0; i<a.length; i++) {
-			if (e.nodeName == a[i])
-				return e;
-		}
-	}
-
-	return null;
-};
-
-TinyMCE_Engine.prototype.nextNode = function(e, n) {
-	var a = n.split(','), i;
-
-	while ((e = e.nextSibling) != null) {
-		for (i=0; i<a.length; i++) {
-			if (e.nodeName == a[i])
-				return e;
-		}
-	}
-
-	return null;
-};
-
-TinyMCE_Engine.prototype.selectElements = function(n, na, f) {
-	var i, a = [], nl, x;
-
-	for (x=0, na = na.split(','); x<na.length; x++)
-		for (i=0, nl = n.getElementsByTagName(na[x]); i<nl.length; i++)
-			(!f || f(nl[i])) && a.push(nl[i]);
-
-	return a;
-};
-
-TinyMCE_Engine.prototype.selectNodes = function(n, f, a) {
-	var i;
-
-	if (!a)
-		a = new Array();
-
-	if (f(n))
-		a[a.length] = n;
-
-	if (n.hasChildNodes()) {
-		for (i=0; i<n.childNodes.length; i++)
-			tinyMCE.selectNodes(n.childNodes[i], f, a);
-	}
-
-	return a;
-};
-
-TinyMCE_Engine.prototype.addCSSClass = function(e, c, b) {
-	var o = this.removeCSSClass(e, c);
-	return e.className = b ? c + (o != '' ? (' ' + o) : '') : (o != '' ? (o + ' ') : '') + c;
-};
-
-TinyMCE_Engine.prototype.removeCSSClass = function(e, c) {
-	c = e.className.replace(new RegExp("(^|\\s+)" + c + "(\\s+|$)"), ' ');
-	return e.className = c != ' ' ? c : '';
-};
-
-TinyMCE_Engine.prototype.hasCSSClass = function(n, c) {
-	return new RegExp('\\b' + c + '\\b', 'g').test(n.className);
-};
-
-TinyMCE_Engine.prototype.renameElement = function(e, n, d) {
-	var ne, i, ar;
-
-	d = typeof(d) == "undefined" ? tinyMCE.selectedInstance.getDoc() : d;
-
-	if (e) {
-		ne = d.createElement(n);
-
-		ar = e.attributes;
-		for (i=ar.length-1; i>-1; i--) {
-			if (ar[i].specified && ar[i].nodeValue)
-				ne.setAttribute(ar[i].nodeName.toLowerCase(), ar[i].nodeValue);
-		}
-
-		ar = e.childNodes;
-		for (i=0; i<ar.length; i++)
-			ne.appendChild(ar[i].cloneNode(true));
-
-		e.parentNode.replaceChild(ne, e);
-	}
-};
-
-TinyMCE_Engine.prototype.getViewPort = function(w) {
-	var d = w.document, m = d.compatMode == 'CSS1Compat', b = d.body, de = d.documentElement;
-
-	return {
-		left : w.pageXOffset || (m ? de.scrollLeft : b.scrollLeft),
-		top : w.pageYOffset || (m ? de.scrollTop : b.scrollTop),
-		width : w.innerWidth || (m ? de.clientWidth : b.clientWidth),
-		height : w.innerHeight || (m ? de.clientHeight : b.clientHeight)
-	};
-};
-
-TinyMCE_Engine.prototype.getStyle = function(n, na, d) {
-	if (!n)
-		return false;
-
-	// Gecko
-	if (tinyMCE.isGecko && n.ownerDocument.defaultView) {
-		try {
-			return n.ownerDocument.defaultView.getComputedStyle(n, null).getPropertyValue(na);
-		} catch (n) {
-			// Old safari might fail
-			return null;
-		}
-	}
-
-	// Camelcase it, if needed
-	na = na.replace(/-(\D)/g, function(a, b){
-		return b.toUpperCase();
-	});
-
-	// IE & Opera
-	if (n.currentStyle)
-		return n.currentStyle[na];
-
-	return false;
-};
-
-/* file:jscripts/tiny_mce/classes/TinyMCE_URL.class.js */
-
-TinyMCE_Engine.prototype.parseURL = function(url_str) {
-	var urlParts = new Array();
-
-	if (url_str) {
-		var pos, lastPos;
-
-		// Parse protocol part
-		pos = url_str.indexOf('://');
-		if (pos != -1) {
-			urlParts['protocol'] = url_str.substring(0, pos);
-			lastPos = pos + 3;
-		}
-
-		// Find port or path start
-		for (var i=lastPos; i<url_str.length; i++) {
-			var chr = url_str.charAt(i);
-
-			if (chr == ':')
-				break;
-
-			if (chr == '/')
-				break;
-		}
-		pos = i;
-
-		// Get host
-		urlParts['host'] = url_str.substring(lastPos, pos);
-
-		// Get port
-		urlParts['port'] = "";
-		lastPos = pos;
-		if (url_str.charAt(pos) == ':') {
-			pos = url_str.indexOf('/', lastPos);
-			urlParts['port'] = url_str.substring(lastPos+1, pos);
-		}
-
-		// Get path
-		lastPos = pos;
-		pos = url_str.indexOf('?', lastPos);
-
-		if (pos == -1)
-			pos = url_str.indexOf('#', lastPos);
-
-		if (pos == -1)
-			pos = url_str.length;
-
-		urlParts['path'] = url_str.substring(lastPos, pos);
-
-		// Get query
-		lastPos = pos;
-		if (url_str.charAt(pos) == '?') {
-			pos = url_str.indexOf('#');
-			pos = (pos == -1) ? url_str.length : pos;
-			urlParts['query'] = url_str.substring(lastPos+1, pos);
-		}
-
-		// Get anchor
-		lastPos = pos;
-		if (url_str.charAt(pos) == '#') {
-			pos = url_str.length;
-			urlParts['anchor'] = url_str.substring(lastPos+1, pos);
-		}
-	}
-
-	return urlParts;
-};
-
-TinyMCE_Engine.prototype.serializeURL = function(up) {
-	var o = "";
-
-	if (up['protocol'])
-		o += up['protocol'] + "://";
-
-	if (up['host'])
-		o += up['host'];
-
-	if (up['port'])
-		o += ":" + up['port'];
-
-	if (up['path'])
-		o += up['path'];
-
-	if (up['query'])
-		o += "?" + up['query'];
-
-	if (up['anchor'])
-		o += "#" + up['anchor'];
-
-	return o;
-};
-
-TinyMCE_Engine.prototype.convertAbsoluteURLToRelativeURL = function(base_url, url_to_relative) {
-	var baseURL = this.parseURL(base_url);
-	var targetURL = this.parseURL(url_to_relative);
-	var strTok1;
-	var strTok2;
-	var breakPoint = 0;
-	var outPath = "";
-	var forceSlash = false;
-
-	if (targetURL.path == "")
-		targetURL.path = "/";
-	else
-		forceSlash = true;
-
-	// Crop away last path part
-	base_url = baseURL.path.substring(0, baseURL.path.lastIndexOf('/'));
-	strTok1 = base_url.split('/');
-	strTok2 = targetURL.path.split('/');
-
-	if (strTok1.length >= strTok2.length) {
-		for (var i=0; i<strTok1.length; i++) {
-			if (i >= strTok2.length || strTok1[i] != strTok2[i]) {
-				breakPoint = i + 1;
-				break;
-			}
-		}
-	}
-
-	if (strTok1.length < strTok2.length) {
-		for (var i=0; i<strTok2.length; i++) {
-			if (i >= strTok1.length || strTok1[i] != strTok2[i]) {
-				breakPoint = i + 1;
-				break;
+
+		});
+
+	// Shorten name
+	Event = tinymce.dom.Event;
+
+	// Dispatch DOM content loaded event for IE and Safari
+	Event._wait();
+	tinymce.addUnload(Event._unload);
+})();
+
+/* file:jscripts/tiny_mce/classes/dom/Element.js */
+
+(function() {
+	var each = tinymce.each;
+
+	tinymce.create('tinymce.dom.Element', {
+		Element : function(id, s) {
+			var t = this, dom, el;
+
+			s = s || {};
+			t.id = id;
+			t.dom = dom = s.dom || tinymce.DOM;
+			t.settings = s;
+
+			// Only IE leaks DOM references, this is a lot faster
+			if (!tinymce.isIE)
+				el = t.dom.get(t.id);
+
+			each([
+				'getPos',
+				'getRect',
+				'getParent',
+				'add',
+				'setStyle',
+				'getStyle',
+				'setStyles',
+				'setAttrib',
+				'setAttribs',
+				'getAttrib',
+				'addClass',
+				'removeClass',
+				'hasClass',
+				'getOuterHTML',
+				'setOuterHTML',
+				'remove',
+				'show',
+				'hide',
+				'isHidden',
+				'setHTML',
+				'get'
+			], function(k) {
+				t[k] = function() {
+					var a = arguments, o;
+
+					// Opera fails
+					if (tinymce.isOpera) {
+						a = [id];
+
+						each(arguments, function(v) {
+							a.push(v);
+						});
+					} else
+						Array.prototype.unshift.call(a, el || id);
+
+					o = dom[k].apply(dom, a);
+					t.update(k);
+
+					return o;
+				};
+			});
+		},
+
+		on : function(n, f, s) {
+			return tinymce.dom.Event.add(this.id, n, f, s);
+		},
+
+		getXY : function() {
+			return {
+				x : parseInt(this.getStyle('left')),
+				y : parseInt(this.getStyle('top'))
+			};
+		},
+
+		getSize : function() {
+			var n = this.dom.get(this.id);
+
+			return {
+				w : parseInt(this.getStyle('width') || n.clientWidth),
+				h : parseInt(this.getStyle('height') || n.clientHeight)
+			};
+		},
+
+		moveTo : function(x, y) {
+			this.setStyles({left : x, top : y});
+		},
+
+		moveBy : function(x, y) {
+			var p = this.getXY();
+
+			this.moveTo(p.x + x, p.y + y);
+		},
+
+		resizeTo : function(w, h) {
+			this.setStyles({width : w, height : h});
+		},
+
+		resizeBy : function(w, h) {
+			var s = this.getSize();
+
+			this.resizeTo(s.w + w, s.h + h);
+		},
+
+		update : function(k) {
+			var t = this, b, dom = t.dom;
+
+			if (tinymce.isIE6 && t.settings.blocker) {
+				k = k || '';
+
+				// Ignore getters
+				if (k.indexOf('get') === 0 || k.indexOf('has') === 0 || k.indexOf('is') === 0)
+					return;
+
+				// Remove blocker on remove
+				if (k == 'remove') {
+					dom.remove(t.blocker);
+					return;
+				}
+
+				if (!t.blocker) {
+					t.blocker = dom.uniqueId();
+					b = dom.add(t.settings.container || dom.getRoot(), 'iframe', {id : t.blocker, style : 'position:absolute;', frameBorder : 0, src : 'javascript:""'});
+					dom.setStyle(b, 'opacity', 0);
+				} else
+					b = dom.get(t.blocker);
+
+				dom.setStyle(b, 'left', t.getStyle('left', 1));
+				dom.setStyle(b, 'top', t.getStyle('top', 1));
+				dom.setStyle(b, 'width', t.getStyle('width', 1));
+				dom.setStyle(b, 'height', t.getStyle('height', 1));
+				dom.setStyle(b, 'display', t.getStyle('display', 1));
+				dom.setStyle(b, 'zIndex', parseInt(t.getStyle('zIndex', 1) || 0) - 1);
 			}
 		}
-	}
-
-	if (breakPoint == 1)
-		return targetURL.path;
-
-	for (var i=0; i<(strTok1.length-(breakPoint-1)); i++)
-		outPath += "../";
-
-	for (var i=breakPoint-1; i<strTok2.length; i++) {
-		if (i != (breakPoint-1))
-			outPath += "/" + strTok2[i];
-		else
-			outPath += strTok2[i];
-	}
-
-	targetURL.protocol = null;
-	targetURL.host = null;
-	targetURL.port = null;
-	targetURL.path = outPath == "" && forceSlash ? "/" : outPath;
-
-	// Remove document prefix from local anchors
-	var fileName = baseURL.path;
-	var pos;
-
-	if ((pos = fileName.lastIndexOf('/')) != -1)
-		fileName = fileName.substring(pos + 1);
-
-	// Is local anchor
-	if (fileName == targetURL.path && targetURL.anchor != "")
-		targetURL.path = "";
-
-	// If empty and not local anchor force filename or slash
-	if (targetURL.path == "" && !targetURL.anchor)
-		targetURL.path = fileName != "" ? fileName : "/";
-
-	return this.serializeURL(targetURL);
-};
-
-TinyMCE_Engine.prototype.convertRelativeToAbsoluteURL = function(base_url, relative_url) {
-	var baseURL = this.parseURL(base_url), baseURLParts, relURLParts;
-	var relURL = this.parseURL(relative_url);
-
-	if (relative_url == "" || relative_url.indexOf('://') != -1 || /^(mailto:|javascript:|#|\/)/.test(relative_url))
-		return relative_url;
-
-	// Split parts
-	baseURLParts = baseURL['path'].split('/');
-	relURLParts = relURL['path'].split('/');
-
-	// Remove empty chunks
-	var newBaseURLParts = new Array();
-	for (var i=baseURLParts.length-1; i>=0; i--) {
-		if (baseURLParts[i].length == 0)
-			continue;
-
-		newBaseURLParts[newBaseURLParts.length] = baseURLParts[i];
-	}
-	baseURLParts = newBaseURLParts.reverse();
-
-	// Merge relURLParts chunks
-	var newRelURLParts = new Array();
-	var numBack = 0;
-	for (var i=relURLParts.length-1; i>=0; i--) {
-		if (relURLParts[i].length == 0 || relURLParts[i] == ".")
-			continue;
-
-		if (relURLParts[i] == '..') {
-			numBack++;
-			continue;
-		}
-
-		if (numBack > 0) {
-			numBack--;
-			continue;
-		}
-
-		newRelURLParts[newRelURLParts.length] = relURLParts[i];
-	}
-
-	relURLParts = newRelURLParts.reverse();
-
-	// Remove end from absolute path
-	var len = baseURLParts.length-numBack;
-	var absPath = (len <= 0 ? "" : "/") + baseURLParts.slice(0, len).join('/') + "/" + relURLParts.join('/');
-	var start = "", end = "";
-
-	// Build output URL
-	relURL.protocol = baseURL.protocol;
-	relURL.host = baseURL.host;
-	relURL.port = baseURL.port;
-
-	// Re-add trailing slash if it's removed
-	if (relURL.path.charAt(relURL.path.length-1) == "/")
-		absPath += "/";
-
-	relURL.path = absPath;
-
-	return this.serializeURL(relURL);
-};
-
-TinyMCE_Engine.prototype.convertURL = function(url, node, on_save) {
-	var prot = document.location.protocol;
-	var host = document.location.hostname;
-	var port = document.location.port;
-
-	// Pass through file protocol
-	if (prot == "file:")
-		return url;
-
-	// Something is wrong, remove weirdness
-	url = tinyMCE.regexpReplace(url, '(http|https):///', '/');
-
-	// Mailto link or anchor (Pass through)
-	if (url.indexOf('mailto:') != -1 || url.indexOf('javascript:') != -1 || tinyMCE.regexpReplace(url,'[ \t\r\n\+]|%20','').charAt(0) == "#")
-		return url;
-
-	// Fix relative/Mozilla
-	if (!tinyMCE.isIE && !on_save && url.indexOf("://") == -1 && url.charAt(0) != '/')
-		return tinyMCE.settings['base_href'] + url;
-
-	// Handle relative URLs
-	if (on_save && tinyMCE.getParam('relative_urls')) {
-		var curl = tinyMCE.convertRelativeToAbsoluteURL(tinyMCE.settings['base_href'], url);
-		if (curl.charAt(0) == '/')
-			curl = tinyMCE.settings['document_base_prefix'] + curl;
-
-		var urlParts = tinyMCE.parseURL(curl);
-		var tmpUrlParts = tinyMCE.parseURL(tinyMCE.settings['document_base_url']);
-
-		// Force relative
-		if (urlParts['host'] == tmpUrlParts['host'] && (urlParts['port'] == tmpUrlParts['port']))
-			return tinyMCE.convertAbsoluteURLToRelativeURL(tinyMCE.settings['document_base_url'], curl);
-	}
-
-	// Handle absolute URLs
-	if (!tinyMCE.getParam('relative_urls')) {
-		var urlParts = tinyMCE.parseURL(url);
-		var baseUrlParts = tinyMCE.parseURL(tinyMCE.settings['base_href']);
-
-		// Force absolute URLs from relative URLs
-		url = tinyMCE.convertRelativeToAbsoluteURL(tinyMCE.settings['base_href'], url);
-
-		// If anchor and path is the same page
-		if (urlParts['anchor'] && urlParts['path'] == baseUrlParts['path'])
-			return "#" + urlParts['anchor'];
-	}
-
-	// Remove current domain
-	if (tinyMCE.getParam('remove_script_host')) {
-		var start = "", portPart = "";
-
-		if (port != "")
-			portPart = ":" + port;
-
-		start = prot + "//" + host + portPart + "/";
-
-		if (url.indexOf(start) == 0)
-			url = url.substring(start.length-1);
-	}
-
-	return url;
-};
-
-TinyMCE_Engine.prototype.convertAllRelativeURLs = function(body) {
-	var i, elms, src, href, mhref, msrc;
-
-	// Convert all image URL:s to absolute URL
-	elms = body.getElementsByTagName("img");
-	for (i=0; i<elms.length; i++) {
-		src = tinyMCE.getAttrib(elms[i], 'src');
-
-		msrc = tinyMCE.getAttrib(elms[i], 'mce_src');
-		if (msrc != "")
-			src = msrc;
-
-		if (src != "") {
-			src = tinyMCE.convertRelativeToAbsoluteURL(tinyMCE.settings['base_href'], src);
-			elms[i].setAttribute("src", src);
-		}
-	}
-
-	// Convert all link URL:s to absolute URL
-	elms = body.getElementsByTagName("a");
-	for (i=0; i<elms.length; i++) {
-		href = tinyMCE.getAttrib(elms[i], 'href');
-
-		mhref = tinyMCE.getAttrib(elms[i], 'mce_href');
-		if (mhref != "")
-			href = mhref;
-
-		if (href && href != "") {
-			href = tinyMCE.convertRelativeToAbsoluteURL(tinyMCE.settings['base_href'], href);
-			elms[i].setAttribute("href", href);
-		}
-	}
-};
-
-/* file:jscripts/tiny_mce/classes/TinyMCE_Array.class.js */
-
-TinyMCE_Engine.prototype.clearArray = function(a) {
-	var n;
-
-	for (n in a)
-		a[n] = null;
-
-	return a;
-};
-
-TinyMCE_Engine.prototype.explode = function(d, s) {
-	var ar = s.split(d), oar = new Array(), i;
-
-	for (i = 0; i<ar.length; i++) {
-		if (ar[i] != "")
-			oar[oar.length] = ar[i];
-	}
-
-	return oar;
-};
-
-/* file:jscripts/tiny_mce/classes/TinyMCE_Event.class.js */
-
-TinyMCE_Engine.prototype._setEventsEnabled = function(node, state) {
-	var evs, x, y, elms, i, event;
-	var events = ['onfocus','onblur','onclick','ondblclick',
-				'onmousedown','onmouseup','onmouseover','onmousemove',
-				'onmouseout','onkeypress','onkeydown','onkeydown','onkeyup'];
-
-	evs = tinyMCE.settings['event_elements'].split(',');
-	for (y=0; y<evs.length; y++){
-		elms = node.getElementsByTagName(evs[y]);
-		for (i=0; i<elms.length; i++) {
-			event = "";
-
-			for (x=0; x<events.length; x++) {
-				if ((event = tinyMCE.getAttrib(elms[i], events[x])) != '') {
-					event = tinyMCE.cleanupEventStr("" + event);
-
-					if (!state)
-						event = "return true;" + event;
-					else
-						event = event.replace(/^return true;/gi, '');
-
-					elms[i].removeAttribute(events[x]);
-					elms[i].setAttribute(events[x], event);
-				}
-			}
-		}
-	}
-};
-
-TinyMCE_Engine.prototype._eventPatch = function(editor_id) {
-	var n, inst, win, e;
-
-	// Remove odd, error
-	if (typeof(tinyMCE) == "undefined")
-		return true;
-
-	try {
-		// Try selected instance first
-		if (tinyMCE.selectedInstance) {
-			win = tinyMCE.selectedInstance.getWin();
-
-			if (win && win.event) {
-				e = win.event;
-
-				if (!e.target)
-					e.target = e.srcElement;
-
-				TinyMCE_Engine.prototype.handleEvent(e);
-				return;
-			}
-		}
-
-		// Search for it
-		for (n in tinyMCE.instances) {
-			inst = tinyMCE.instances[n];
-
-			if (!tinyMCE.isInstance(inst))
-				continue;
-
-			inst.select();
-			win = inst.getWin();
-
-			if (win && win.event) {
-				e = win.event;
-
-				if (!e.target)
-					e.target = e.srcElement;
-
-				TinyMCE_Engine.prototype.handleEvent(e);
-				return;
-			}
-		}
-	} catch (ex) {
-		// Ignore error if iframe is pointing to external URL
-	}
-};
-
-TinyMCE_Engine.prototype.findEvent = function(e) {
-	var n, inst;
-
-	if (e)
-		return e;
-
-	for (n in tinyMCE.instances) {
-		inst = tinyMCE.instances[n];
-
-		if (tinyMCE.isInstance(inst) && inst.getWin().event)
-			return inst.getWin().event;
-	}
-
-	return null;
-};
-
-TinyMCE_Engine.prototype.unloadHandler = function() {
-	tinyMCE.triggerSave(true, true);
-};
-
-TinyMCE_Engine.prototype.addEventHandlers = function(inst) {
-	this.setEventHandlers(inst, 1);
-};
-
-TinyMCE_Engine.prototype.setEventHandlers = function(inst, s) {
-	var doc = inst.getDoc(), ie, ot, i, f = s ? tinyMCE.addEvent : tinyMCE.removeEvent;
-
-	ie = ['keypress', 'keyup', 'keydown', 'click', 'mouseup', 'mousedown', 'controlselect', 'dblclick'];
-	ot = ['keypress', 'keyup', 'keydown', 'click', 'mouseup', 'mousedown', 'focus', 'blur', 'dragdrop'];
-
-	inst.switchSettings();
-
-	if (tinyMCE.isIE) {
-		for (i=0; i<ie.length; i++)
-			f(doc, ie[i], TinyMCE_Engine.prototype._eventPatch);
-	} else {
-		for (i=0; i<ot.length; i++)
-			f(doc, ot[i], tinyMCE.handleEvent);
-
-		// Force designmode
-		try {
-			doc.designMode = "On";
-		} catch (e) {
-			// Ignore
-		}
-	}
-};
-
-TinyMCE_Engine.prototype.onMouseMove = function() {
-	var inst, lh;
-
-	// Fix for IE7 bug where it's not restoring hover on anchors correctly
-	if (tinyMCE.lastHover) {
-		lh = tinyMCE.lastHover;
-
-		// Call out on menus and refresh class on normal buttons
-		if (lh.className.indexOf('mceMenu') != -1)
-			tinyMCE._menuButtonEvent('out', lh);
-		else
-			lh.className = lh.className;
-
-		tinyMCE.lastHover = null;
-	}
-
-	if (!tinyMCE.hasMouseMoved) {
-		inst = tinyMCE.selectedInstance;
-
-		// Workaround for bug #1437457 (Odd MSIE bug)
-		if (inst.isFocused) {
-			inst.undoBookmark = inst.selection.getBookmark();
-			tinyMCE.hasMouseMoved = true;
-		}
-	}
-
-//	tinyMCE.cancelEvent(inst.getWin().event);
-//	return false;
-};
-
-TinyMCE_Engine.prototype.cancelEvent = function(e) {
-	if (!e)
-		return false;
-
-	if (tinyMCE.isIE) {
-		e.returnValue = false;
-		e.cancelBubble = true;
-	} else {
-		e.preventDefault();
-		e.stopPropagation && e.stopPropagation();
-	}
-
-	return false;
-};
-
-TinyMCE_Engine.prototype.addEvent = function(o, n, h) {
-	// Add cleanup for all non unload events
-	if (n != 'unload') {
-		function clean() {
-			var ex;
-
-			try {
-				tinyMCE.removeEvent(o, n, h);
-				tinyMCE.removeEvent(window, 'unload', clean);
-				o = n = h = null;
-			} catch (ex) {
-				// IE may produce access denied exception on unload
-			}
-		}
-
-		// Add memory cleaner
-		tinyMCE.addEvent(window, 'unload', clean);
-	}
-
-	if (o.attachEvent)
-		o.attachEvent("on" + n, h);
-	else
-		o.addEventListener(n, h, false);
-};
-
-TinyMCE_Engine.prototype.removeEvent = function(o, n, h) {
-	if (o.detachEvent)
-		o.detachEvent("on" + n, h);
-	else
-		o.removeEventListener(n, h, false);
-};
-
-TinyMCE_Engine.prototype.addSelectAccessibility = function(e, s, w) {
-	// Add event handlers 
-	if (!s._isAccessible) {
-		s.onkeydown = tinyMCE.accessibleEventHandler;
-		s.onblur = tinyMCE.accessibleEventHandler;
-		s._isAccessible = true;
-		s._win = w;
-	}
-
-	return false;
-};
-
-TinyMCE_Engine.prototype.accessibleEventHandler = function(e) {
-	var win = this._win;
-	e = tinyMCE.isIE ? win.event : e;
-	var elm = tinyMCE.isIE ? e.srcElement : e.target;
-
-	// Unpiggyback onchange on blur
-	if (e.type == "blur") {
-		if (elm.oldonchange) {
-			elm.onchange = elm.oldonchange;
-			elm.oldonchange = null;
-		}
-
-		return true;
-	}
-
-	// Piggyback onchange
-	if (elm.nodeName == "SELECT" && !elm.oldonchange) {
-		elm.oldonchange = elm.onchange;
-		elm.onchange = null;
-	}
-
-	// Execute onchange and remove piggyback
-	if (e.keyCode == 13 || e.keyCode == 32) {
-		elm.onchange = elm.oldonchange;
-		elm.onchange();
-		elm.oldonchange = null;
-
-		tinyMCE.cancelEvent(e);
-		return false;
-	}
-
-	return true;
-};
-
-TinyMCE_Engine.prototype._resetIframeHeight = function() {
-	var ife;
-
-	if (tinyMCE.isRealIE) {
-		ife = tinyMCE.selectedInstance.iframeElement;
-
-/*		if (ife._oldWidth) {
-			ife.style.width = ife._oldWidth;
-			ife.width = ife._oldWidth;
-		}*/
-
-		if (ife._oldHeight) {
-			ife.style.height = ife._oldHeight;
-			ife.height = ife._oldHeight;
-		}
-	}
-};
-
-/* file:jscripts/tiny_mce/classes/TinyMCE_Selection.class.js */
-
-function TinyMCE_Selection(inst) {
-	this.instance = inst;
-};
-
-TinyMCE_Selection.prototype = {
-	getSelectedHTML : function() {
-		var inst = this.instance;
-		var e, r = this.getRng(), h;
-
-		if (!r)
-			return null;
-
-		e = document.createElement("body");
-
-		if (r.cloneContents)
-			e.appendChild(r.cloneContents());
-		else if (typeof(r.item) != 'undefined' || typeof(r.htmlText) != 'undefined')
-			e.innerHTML = r.item ? r.item(0).outerHTML : r.htmlText;
-		else
-			e.innerHTML = r.toString(); // Failed, use text for now
-
-		h = tinyMCE._cleanupHTML(inst, inst.contentDocument, inst.settings, e, e, false, true, false);
-
-		// When editing always use fonts internaly
-		//if (tinyMCE.getParam("convert_fonts_to_spans"))
-		//	tinyMCE.convertSpansToFonts(inst.getDoc());
-
-		return h;
-	},
-
-	getSelectedText : function() {
-		var inst = this.instance;
-		var d, r, s, t;
-
-		if (tinyMCE.isIE) {
-			d = inst.getDoc();
-
-			if (d.selection.type == "Text") {
-				r = d.selection.createRange();
-				t = r.text;
-			} else
-				t = '';
-		} else {
-			s = this.getSel();
-
-			if (s && s.toString)
-				t = s.toString();
+
+		});
+})();
+
+/* file:jscripts/tiny_mce/classes/dom/Selection.js */
+
+(function() {
+	// Shorten names
+	var is = tinymce.is, isIE = tinymce.isIE, each = tinymce.each;
+
+	tinymce.create('tinymce.dom.Selection', {
+		Selection : function(dom, win, serializer) {
+			var t = this;
+
+			t.dom = dom;
+			t.win = win;
+			t.serializer = serializer;
+
+			// Prevent leaks
+			tinymce.addUnload(function() {
+				t.win = null;
+			});
+		},
+
+		getContent : function(s) {
+			var t = this, r = t.getRng(), e = t.dom.create("body"), se = t.getSel(), wb, wa, n;
+
+			s = s || {};
+			wb = wa = '';
+			s.get = true;
+			s.format = s.format || 'html';
+
+			if (s.format == 'text')
+				return t.isCollapsed() ? '' : (r.text || (se.toString ? se.toString() : ''));
+
+			if (r.cloneContents) {
+				n = r.cloneContents();
+
+				if (n)
+					e.appendChild(n);
+			} else if (is(r.item) || is(r.htmlText))
+				e.innerHTML = r.item ? r.item(0).outerHTML : r.htmlText;
 			else
-				t = '';
-		}
-
-		return t;
-	},
-
-	getBookmark : function(simple) {
-		var inst = this.instance;
-		var rng = this.getRng();
-		var doc = inst.getDoc(), b = inst.getBody();
-		var sp, le, s, e, nl, i, si, ei, w;
-		var trng, sx, sy, xx = -999999999, vp = inst.getViewPort();
-
-		sx = vp.left;
-		sy = vp.top;
-
-		if (tinyMCE.isSafari || tinyMCE.isOpera || simple)
-			return {rng : rng, scrollX : sx, scrollY : sy};
-
-		if (tinyMCE.isIE) {
-			if (rng.item) {
-				e = rng.item(0);
-
-				nl = b.getElementsByTagName(e.nodeName);
-				for (i=0; i<nl.length; i++) {
-					if (e == nl[i]) {
-						sp = i;
-						break;
-					}
-				}
-
-				return {
-					tag : e.nodeName,
-					index : sp,
-					scrollX : sx,
-					scrollY : sy
-				};
+				e.innerHTML = r.toString();
+
+			// Keep whitespace before and after
+			if (/^\s/.test(e.innerHTML))
+				wb = ' ';
+
+			if (/\s+$/.test(e.innerHTML))
+				wa = ' ';
+
+			s.getInner = true;
+
+			return t.isCollapsed() ? '' : wb + t.serializer.serialize(e, s) + wa;
+		},
+
+		setContent : function(h, s) {
+			var t = this, r = t.getRng(), d;
+
+			s = s || {format : 'html'};
+			s.set = true;
+			h = t.dom.processHTML(h);
+
+			if (r.insertNode) {
+				d = t.win.document;
+
+				// Gecko has a bug where if you insert &nbsp; using InsertHTML it will insert a space instead
+				// So we simply check if the input is HTML or text and then insert text using the insertNode method
+				if (tinymce.isGecko && h.indexOf('<') == -1) {
+					r.deleteContents();
+					r.insertNode(t.getRng().createContextualFragment(h + '<span id="__caret">_</span>'));
+					t.select(t.dom.get('__caret'));
+					t.getRng().deleteContents();
+					return;
+				}
+
+				// Use insert HTML if it exists (places cursor after content)
+				if (d.queryCommandEnabled('InsertHTML'))
+					return d.execCommand('InsertHTML', false, h);
+
+				r.deleteContents();
+				r.insertNode(t.getRng().createContextualFragment(h));
+			} else {
+				if (r.item)
+					r.item(0).outerHTML = h;
+				else
+					r.pasteHTML(h);
+			}
+		},
+
+		getStart : function() {
+			var t = this, r = t.getRng(), e;
+
+			if (isIE) {
+				if (r.item)
+					return r.item(0);
+
+				r = r.duplicate();
+				r.collapse(1);
+				e = r.parentElement();
+
+				if (e.nodeName == 'BODY')
+					return e.firstChild;
+
+				return e;
 			} else {
-				trng = doc.body.createTextRange();
-				trng.moveToElementText(inst.getBody());
-				trng.collapse(true);
-				bp = Math.abs(trng.move('character', xx));
-
-				trng = rng.duplicate();
-				trng.collapse(true);
-				sp = Math.abs(trng.move('character', xx));
-
-				trng = rng.duplicate();
-				trng.collapse(false);
-				le = Math.abs(trng.move('character', xx)) - sp;
+				e = r.startContainer;
+
+				if (e.nodeName == 'BODY')
+					return e.firstChild;
+
+				return t.dom.getParent(e, function(n) {return n.nodeType == 1;});
+			}
+		},
+
+		getEnd : function() {
+			var t = this, r = t.getRng(), e;
+
+			if (isIE) {
+				if (r.item)
+					return r.item(0);
+
+				r = r.duplicate();
+				r.collapse(0);
+				e = r.parentElement();
+
+				if (e.nodeName == 'BODY')
+					return e.lastChild;
+
+				return e;
+			} else {
+				e = r.endContainer;
+
+				if (e.nodeName == 'BODY')
+					return e.lastChild;
+
+				return t.dom.getParent(e, function(n) {return n.nodeType == 1;});
+			}
+		},
+
+		getBookmark : function(si) {
+			var t = this, r = t.getRng(), tr, sx, sy, vp = t.dom.getViewPort(t.win), e, sp, bp, le, c = -0xFFFFFF, s, ro = t.dom.getRoot();
+
+			sx = vp.x;
+			sy = vp.y;
+
+			// Simple bookmark fast but not as persistent
+			if (si == 'simple')
+				return {rng : r, scrollX : sx, scrollY : sy};
+
+			// Handle IE
+			if (isIE) {
+				// Control selection
+				if (r.item) {
+					e = r.item(0);
+
+					each(t.dom.select(e.nodeName), function(n, i) {
+						if (e == n) {
+							sp = i;
+							return false;
+						}
+					});
+
+					return {
+						tag : e.nodeName,
+						index : sp,
+						scrollX : sx,
+						scrollY : sy
+					};
+				}
+
+				// Text selection
+				tr = t.dom.doc.body.createTextRange();
+				tr.moveToElementText(ro);
+				tr.collapse(true);
+				bp = Math.abs(tr.move('character', c));
+
+				tr = r.duplicate();
+				tr.collapse(true);
+				sp = Math.abs(tr.move('character', c));
+
+				tr = r.duplicate();
+				tr.collapse(false);
+				le = Math.abs(tr.move('character', c)) - sp;
 
 				return {
 					start : sp - bp,
@@ -6342,36 +2642,45 @@
 					scrollY : sy
 				};
 			}
-		}
-
-		if (tinyMCE.isGecko) {
-			s = this.getSel();
-			e = this.getFocusElement();
+
+			// Handle W3C
+			e = t.getNode();
+			s = t.getSel();
 
 			if (!s)
 				return null;
 
+			// Image selection
 			if (e && e.nodeName == 'IMG') {
-				/*nl = b.getElementsByTagName('IMG');
-				for (i=0; i<nl.length; i++) {
-					if (e == nl[i]) {
-						sp = i;
-						break;
-					}
-				}*/
-
 				return {
-					start : -1,
-					end : -1,
-					index : sp,
 					scrollX : sx,
 					scrollY : sy
 				};
 			}
 
+			// Text selection
+
+			function getPos(r, sn, en) {
+				var w = document.createTreeWalker(r, NodeFilter.SHOW_TEXT, null, false), n, p = 0, d = {};
+
+				while ((n = w.nextNode()) != null) {
+					if (n == sn)
+						d.start = p;
+
+					if (n == en) {
+						d.end = p;
+						return d;
+					}
+
+					p += n.nodeValue ? n.nodeValue.length : 0;
+				}
+
+				return null;
+			};
+
 			// Caret or selection
 			if (s.anchorNode == s.focusNode && s.anchorOffset == s.focusOffset) {
-				e = this._getPosText(b, s.anchorNode, s.focusNode);
+				e = getPos(ro, s.anchorNode, s.focusNode);
 
 				if (!e)
 					return {scrollX : sx, scrollY : sy};
@@ -6383,1162 +2692,6472 @@
 					scrollY : sy
 				};
 			} else {
-				e = this._getPosText(b, rng.startContainer, rng.endContainer);
+				e = getPos(ro, r.startContainer, r.endContainer);
 
 				if (!e)
 					return {scrollX : sx, scrollY : sy};
 
 				return {
-					start : e.start + rng.startOffset,
-					end : e.end + rng.endOffset,
+					start : e.start + r.startOffset,
+					end : e.end + r.endOffset,
 					scrollX : sx,
 					scrollY : sy
 				};
 			}
-		}
-
-		return null;
-	},
-
-	moveToBookmark : function(bookmark) {
-		var inst = this.instance;
-		var rng, nl, i, ex, b = inst.getBody(), sd;
-		var doc = inst.getDoc();
-		var win = inst.getWin();
-		var sel = this.getSel();
-
-		if (!bookmark)
-			return false;
-
-		if (tinyMCE.isSafari) {
-			sel.setBaseAndExtent(bookmark.rng.startContainer, bookmark.rng.startOffset, bookmark.rng.endContainer, bookmark.rng.endOffset);
-			return true;
-		}
-
-		if (tinyMCE.isRealIE) {
-			if (bookmark.rng) {
+		},
+
+		moveToBookmark : function(b) {
+			var t = this, r = t.getRng(), s = t.getSel(), ro = t.dom.getRoot(), sd;
+
+			function getPos(r, sp, ep) {
+				var w = document.createTreeWalker(r, NodeFilter.SHOW_TEXT, null, false), n, p = 0, d = {};
+
+				while ((n = w.nextNode()) != null) {
+					p += n.nodeValue ? n.nodeValue.length : 0;
+
+					if (p >= sp && !d.startNode) {
+						d.startNode = n;
+						d.startOffset = sp - (p - n.nodeValue.length);
+					}
+
+					if (p >= ep) {
+						d.endNode = n;
+						d.endOffset = ep - (p - n.nodeValue.length);
+
+						return d;
+					}
+				}
+
+				return null;
+			};
+
+			if (!b)
+				return false;
+
+			t.win.scrollTo(b.scrollX, b.scrollY);
+
+			// Handle explorer
+			if (isIE) {
+				// Handle simple
+				if (r = b.rng) {
+					try {
+						r.select();
+					} catch (ex) {
+						// Ignore
+					}
+
+					return true;
+				}
+
+				t.win.focus();
+
+				// Handle control bookmark
+				if (b.tag) {
+					r = ro.createControlRange();
+
+					each(t.dom.select(b.tag), function(n, i) {
+						if (i == b.index)
+							r.addElement(n);
+					});
+				} else {
+					// Try/catch needed since this operation breaks when TinyMCE is placed in hidden divs/tabs
+					try {
+						// Incorrect bookmark
+						if (b.start < 0)
+							return true;
+
+						r = s.createRange();
+						r.moveToElementText(ro);
+						r.collapse(true);
+						r.moveStart('character', b.start);
+						r.moveEnd('character', b.length);
+					} catch (ex2) {
+						return true;
+					}
+				}
+
 				try {
-					bookmark.rng.select();
+					r.select();
 				} catch (ex) {
-					// Ignore
+					// Needed for some odd IE bug #1843306
 				}
 
 				return true;
 			}
 
-			win.focus();
-
-			if (bookmark.tag) {
-				rng = b.createControlRange();
-
-				nl = b.getElementsByTagName(bookmark.tag);
-
-				if (nl.length > bookmark.index) {
+			// Handle W3C
+			if (!s)
+				return false;
+
+			// Handle simple
+			if (b.rng) {
+				s.removeAllRanges();
+				s.addRange(b.rng);
+			} else {
+				if (is(b.start) && is(b.end)) {
 					try {
-						rng.addElement(nl[bookmark.index]);
+						sd = getPos(ro, b.start, b.end);
+						if (sd) {
+							r = t.dom.doc.createRange();
+							r.setStart(sd.startNode, sd.startOffset);
+							r.setEnd(sd.endNode, sd.endOffset);
+							s.removeAllRanges();
+							s.addRange(r);
+						}
+
+						if (!tinymce.isOpera)
+							t.win.focus();
 					} catch (ex) {
-						// Might be thrown if the node no longer exists
+						// Ignore
+					}
+				}
+			}
+		},
+
+		select : function(n, c) {
+			var t = this, r = t.getRng(), s = t.getSel(), b, fn, ln, d = t.win.document;
+
+			function first(n) {
+				return n ? d.createTreeWalker(n, NodeFilter.SHOW_TEXT, null, false).nextNode() : null;
+			};
+
+			function last(n) {
+				var c, o, w;
+
+				if (!n)
+					return null;
+
+				w = d.createTreeWalker(n, NodeFilter.SHOW_TEXT, null, false);
+				while (c = w.nextNode())
+					o = c;
+
+				return o;
+			};
+
+			if (isIE) {
+				try {
+					b = d.body;
+
+					if (/^(IMG|TABLE)$/.test(n.nodeName)) {
+						r = b.createControlRange();
+						r.addElement(n);
+					} else {
+						r = b.createTextRange();
+						r.moveToElementText(n);
 					}
+
+					r.select();
+				} catch (ex) {
+					// Throws illigal agrument in IE some times
+				}
+			} else {
+				if (c) {
+					fn = first(n);
+					ln = last(n);
+
+					if (fn && ln) {
+						//console.debug(fn, ln);
+						r = d.createRange();
+						r.setStart(fn, 0);
+						r.setEnd(ln, ln.nodeValue.length);
+					} else
+						r.selectNode(n);
+				} else
+					r.selectNode(n);
+
+				t.setRng(r);
+			}
+
+			return n;
+		},
+
+		isCollapsed : function() {
+			var t = this, r = t.getRng(), s = t.getSel();
+
+			if (!r || r.item)
+				return false;
+
+			return !s || r.boundingWidth == 0 || s.isCollapsed;
+		},
+
+		collapse : function(b) {
+			var t = this, r = t.getRng(), n;
+
+			// Control range on IE
+			if (r.item) {
+				n = r.item(0);
+				r = this.win.document.body.createTextRange();
+				r.moveToElementText(n);
+			}
+
+			r.collapse(!!b);
+			t.setRng(r);
+		},
+
+		getSel : function() {
+			var t = this, w = this.win;
+
+			return w.getSelection ? w.getSelection() : w.document.selection;
+		},
+
+		getRng : function() {
+			var t = this, s = t.getSel(), r;
+
+			try {
+				if (s)
+					r = s.rangeCount > 0 ? s.getRangeAt(0) : (s.createRange ? s.createRange() : t.win.document.createRange());
+			} catch (ex) {
+				// IE throws unspecified error here if TinyMCE is placed in a frame/iframe
+			}
+
+			// No range found then create an empty one
+			// This can occur when the editor is placed in a hidden container element on Gecko
+			// Or on IE when there was an exception
+			if (!r)
+				r = isIE ? t.win.document.body.createTextRange() : t.win.document.createRange();
+
+			return r;
+		},
+
+		setRng : function(r) {
+			var s;
+
+			if (!isIE) {
+				s = this.getSel();
+
+				if (s) {
+					s.removeAllRanges();
+					s.addRange(r);
 				}
 			} else {
-				// Try/catch needed since this operation breaks when TinyMCE is placed in hidden divs/tabs
 				try {
-					// Incorrect bookmark
-					if (bookmark.start < 0)
-						return true;
-
-					rng = inst.getSel().createRange();
-					rng.moveToElementText(inst.getBody());
-					rng.collapse(true);
-					rng.moveStart('character', bookmark.start);
-					rng.moveEnd('character', bookmark.length);
-				} catch (ex) {
-					return true;
-				}
-			}
-
-			rng.select();
-
-			win.scrollTo(bookmark.scrollX, bookmark.scrollY);
-			return true;
-		}
-
-		if (tinyMCE.isGecko || tinyMCE.isOpera) {
-			if (!sel)
-				return false;
-
-			if (bookmark.rng) {
-				sel.removeAllRanges();
-				sel.addRange(bookmark.rng);
-			}
-
-			if (bookmark.start != -1 && bookmark.end != -1) {
-				try {
-					sd = this._getTextPos(b, bookmark.start, bookmark.end);
-					rng = doc.createRange();
-					rng.setStart(sd.startNode, sd.startOffset);
-					rng.setEnd(sd.endNode, sd.endOffset);
-					sel.removeAllRanges();
-					sel.addRange(rng);
-					win.focus();
+					r.select();
 				} catch (ex) {
-					// Ignore
-				}
-			}
-
-			/*
-			if (typeof(bookmark.index) != 'undefined') {
-				tinyMCE.selectElements(b, 'IMG', function (n) {
-					if (bookmark.index-- == 0) {
-						// Select image in Gecko here
+					// Needed for some odd IE bug #1843306
+				}
+			}
+		},
+
+		setNode : function(n) {
+			var t = this;
+
+			t.setContent(t.dom.getOuterHTML(n));
+
+			return n;
+		},
+
+		getNode : function() {
+			var t = this, r = t.getRng(), s = t.getSel(), e;
+
+			if (!isIE) {
+				// Range maybe lost after the editor is made visible again
+				if (!r)
+					return t.dom.getRoot();
+
+				e = r.commonAncestorContainer;
+
+				// Handle selection a image or other control like element such as anchors
+				if (!r.collapsed) {
+					if (r.startContainer == r.endContainer || (tinymce.isWebKit && r.startContainer == r.endContainer.parentNode)) {
+						if (r.startOffset - r.endOffset < 2 || tinymce.isWebKit) {
+							if (r.startContainer.hasChildNodes())
+								e = r.startContainer.childNodes[r.startOffset];
+						}
 					}
-
-					return false;
+				}
+
+				return t.dom.getParent(e, function(n) {
+					return n.nodeType == 1;
 				});
 			}
-			*/
-
-			win.scrollTo(bookmark.scrollX, bookmark.scrollY);
-			return true;
+
+			return r.item ? r.item(0) : r.parentElement();
+		}
+
+		});
+})();
+
+/* file:jscripts/tiny_mce/classes/dom/XMLWriter.js */
+
+(function() {
+	tinymce.create('tinymce.dom.XMLWriter', {
+		node : null,
+
+		XMLWriter : function(s) {
+			// Get XML document
+			function getXML() {
+				var i = document.implementation;
+
+				if (!i || !i.createDocument) {
+					// Try IE objects
+					try {return new ActiveXObject('MSXML2.DOMDocument');} catch (ex) {}
+					try {return new ActiveXObject('Microsoft.XmlDom');} catch (ex) {}
+				} else
+					return i.createDocument('', '', null);
+			};
+
+			this.doc = getXML();
+			this.reset();
+		},
+
+		reset : function() {
+			var t = this, d = t.doc;
+
+			if (d.firstChild)
+				d.removeChild(d.firstChild);
+
+			t.node = d.appendChild(d.createElement("html"));
+		},
+
+		writeStartElement : function(n) {
+			var t = this;
+
+			t.node = t.node.appendChild(t.doc.createElement(n));
+		},
+
+		writeAttribute : function(n, v) {
+			// Since Opera doesn't escape > into &gt; we need to do it our self
+			if (tinymce.isOpera)
+				v = v.replace(/>/g, '|>');
+
+			this.node.setAttribute(n, v);
+		},
+
+		writeEndElement : function() {
+			this.node = this.node.parentNode;
+		},
+
+		writeFullEndElement : function() {
+			var t = this, n = t.node;
+
+			n.appendChild(t.doc.createTextNode(""));
+			t.node = n.parentNode;
+		},
+
+		writeText : function(v) {
+			// Since Opera doesn't escape > into &gt; we need to do it our self
+			if (tinymce.isOpera)
+				v = v.replace(/>/g, '|>');
+
+			this.node.appendChild(this.doc.createTextNode(v));
+		},
+
+		writeCDATA : function(v) {
+			this.node.appendChild(this.doc.createCDATA(v));
+		},
+
+		writeComment : function(v) {
+			this.node.appendChild(this.doc.createComment(v));
+		},
+
+		getContent : function() {
+			var h;
+
+			h = this.doc.xml || new XMLSerializer().serializeToString(this.doc);
+			h = h.replace(/<\?[^?]+\?>|<html>|<\/html>|<html\/>|<!DOCTYPE[^>]+>/g, '');
+			h = h.replace(/ ?\/>/g, ' />');
+
+			// Since Opera doesn't escape > into &gt; we need to do it our self to normalize the output for all browsers
+			if (tinymce.isOpera)
+				h = h.replace(/\|>/g, '&gt;');
+
+			return h;
 		}
 
-		return false;
-	},
-
-	_getPosText : function(r, sn, en) {
-		var w = document.createTreeWalker(r, NodeFilter.SHOW_TEXT, null, false), n, p = 0, d = {};
-
-		while ((n = w.nextNode()) != null) {
-			if (n == sn)
-				d.start = p;
-
-			if (n == en) {
-				d.end = p;
-				return d;
-			}
-
-			p += n.nodeValue ? n.nodeValue.length : 0;
+		});
+})();
+
+/* file:jscripts/tiny_mce/classes/dom/Serializer.js */
+
+(function() {
+	// Shorten names
+	var extend = tinymce.extend, each = tinymce.each, Dispatcher = tinymce.util.Dispatcher, isIE = tinymce.isIE;
+
+	// Returns only attribites that have values not all attributes in IE
+	function getIEAtts(n) {
+		var o = [];
+
+		// Object will throw exception in IE
+		if (n.nodeName == 'OBJECT')
+			return n.attributes;
+
+		n.cloneNode(false).outerHTML.replace(/([a-z0-9\-_]+)=/gi, function(a, b) {
+			o.push({specified : 1, nodeName : b});
+		});
+
+		return o;
+	};
+
+	function wildcardToRE(s) {
+		return s.replace(/([?+*])/g, '.$1');
+	};
+
+	tinymce.create('tinymce.dom.Serializer', {
+		Serializer : function(s) {
+			var t = this;
+
+			t.key = 0;
+			t.onPreProcess = new Dispatcher(t);
+			t.onPostProcess = new Dispatcher(t);
+			t.writer = new tinymce.dom.XMLWriter();
+
+			// Default settings
+			t.settings = s = extend({
+				dom : tinymce.DOM,
+				valid_nodes : 0,
+				node_filter : 0,
+				attr_filter : 0,
+				invalid_attrs : /^(mce_|_moz_$)/,
+				closed : /(br|hr|input|meta|img|link|param)/,
+				entity_encoding : 'named',
+				entities : '160,nbsp,161,iexcl,162,cent,163,pound,164,curren,165,yen,166,brvbar,167,sect,168,uml,169,copy,170,ordf,171,laquo,172,not,173,shy,174,reg,175,macr,176,deg,177,plusmn,178,sup2,179,sup3,180,acute,181,micro,182,para,183,middot,184,cedil,185,sup1,186,ordm,187,raquo,188,frac14,189,frac12,190,frac34,191,iquest,192,Agrave,193,Aacute,194,Acirc,195,Atilde,196,Auml,197,Aring,198,AElig,199,Ccedil,200,Egrave,201,Eacute,202,Ecirc,203,Euml,204,Igrave,205,Iacute,206,Icirc,207,Iuml,208,ETH,209,Ntilde,210,Ograve,211,Oacute,212,Ocirc,213,Otilde,214,Ouml,215,times,216,Oslash,217,Ugrave,218,Uacute,219,Ucirc,220,Uuml,221,Yacute,222,THORN,223,szlig,224,agrave,225,aacute,226,acirc,227,atilde,228,auml,229,aring,230,aelig,231,ccedil,232,egrave,233,eacute,234,ecirc,235,euml,236,igrave,237,iacute,238,icirc,239,iuml,240,eth,241,ntilde,242,ograve,243,oacute,244,ocirc,245,otilde,246,ouml,247,divide,248,oslash,249,ugrave,250,uacute,251,ucirc,252,uuml,253,yacute,254,thorn,255,yuml,402,fnof,913,Alpha,914,Beta,915,Gamma,916,Delta,917,Epsilon,918,Zeta,919,Eta,920,Theta,921,Iota,922,Kappa,923,Lambda,924,Mu,925,Nu,926,Xi,927,Omicron,928,Pi,929,Rho,931,Sigma,932,Tau,933,Upsilon,934,Phi,935,Chi,936,Psi,937,Omega,945,alpha,946,beta,947,gamma,948,delta,949,epsilon,950,zeta,951,eta,952,theta,953,iota,954,kappa,955,lambda,956,mu,957,nu,958,xi,959,omicron,960,pi,961,rho,962,sigmaf,963,sigma,964,tau,965,upsilon,966,phi,967,chi,968,psi,969,omega,977,thetasym,978,upsih,982,piv,8226,bull,8230,hellip,8242,prime,8243,Prime,8254,oline,8260,frasl,8472,weierp,8465,image,8476,real,8482,trade,8501,alefsym,8592,larr,8593,uarr,8594,rarr,8595,darr,8596,harr,8629,crarr,8656,lArr,8657,uArr,8658,rArr,8659,dArr,8660,hArr,8704,forall,8706,part,8707,exist,8709,empty,8711,nabla,8712,isin,8713,notin,8715,ni,8719,prod,8721,sum,8722,minus,8727,lowast,8730,radic,8733,prop,8734,infin,8736,ang,8743,and,8744,or,8745,cap,8746,cup,8747,int,8756,there4,8764,sim,8773,cong,8776,asymp,8800,ne,8801,equiv,8804,le,8805,ge,8834,sub,8835,sup,8836,nsub,8838,sube,8839,supe,8853,oplus,8855,otimes,8869,perp,8901,sdot,8968,lceil,8969,rceil,8970,lfloor,8971,rfloor,9001,lang,9002,rang,9674,loz,9824,spades,9827,clubs,9829,hearts,9830,diams,338,OElig,339,oelig,352,Scaron,353,scaron,376,Yuml,710,circ,732,tilde,8194,ensp,8195,emsp,8201,thinsp,8204,zwnj,8205,zwj,8206,lrm,8207,rlm,8211,ndash,8212,mdash,8216,lsquo,8217,rsquo,8218,sbquo,8220,ldquo,8221,rdquo,8222,bdquo,8224,dagger,8225,Dagger,8240,permil,8249,lsaquo,8250,rsaquo,8364,euro',
+				valid_elements : '*[*]',
+				extended_valid_elements : 0,
+				valid_child_elements : 0,
+				invalid_elements : 0,
+				fix_table_elements : 0,
+				fix_list_elements : true,
+				fix_content_duplication : true,
+				convert_fonts_to_spans : false,
+				font_size_classes : 0,
+				font_size_style_values : 0,
+				apply_source_formatting : 0,
+				indent_mode : 'simple',
+				indent_char : '\t',
+				indent_levels : 1,
+				remove_linebreaks : 1
+			}, s);
+
+			t.dom = s.dom;
+
+			if (s.fix_list_elements) {
+				t.onPreProcess.add(function(se, o) {
+					var nl, x, a = ['ol', 'ul'], i, n, p, r = /^(OL|UL)$/, np;
+
+					function prevNode(e, n) {
+						var a = n.split(','), i;
+
+						while ((e = e.previousSibling) != null) {
+							for (i=0; i<a.length; i++) {
+								if (e.nodeName == a[i])
+									return e;
+							}
+						}
+
+						return null;
+					};
+
+					for (x=0; x<a.length; x++) {
+						nl = t.dom.select(a[x], o.node);
+
+						for (i=0; i<nl.length; i++) {
+							n = nl[i];
+							p = n.parentNode;
+
+							if (r.test(p.nodeName)) {
+								np = prevNode(n, 'LI');
+
+								if (!np) {
+									np = t.dom.create('li');
+									np.innerHTML = '&nbsp;';
+									np.appendChild(n);
+									p.insertBefore(np, p.firstChild);
+								} else
+									np.appendChild(n);
+							}
+						}
+					}
+				});
+			}
+
+			if (s.fix_table_elements) {
+				t.onPreProcess.add(function(se, o) {
+					var ta = [], d = t.dom.doc;
+
+					// Build list of HTML chunks and replace tables with comment placeholders
+					each(t.dom.select('table', o.node), function(e) {
+						var pa = t.dom.getParent(e, 'H1,H2,H3,H4,H5,H6,P'), p = [], i, h;
+
+						if (pa) {
+							t.dom.getParent(e, function(n) {
+								if (n != e)
+									p.push(n.nodeName);
+							});
+
+							h = '';
+
+							for (i = 0; i < p.length; i++)
+								h += '</' + p[i]+ '>';
+
+							h += t.dom.getOuterHTML(e);
+
+							for (i = p.length - 1; i >= 0; i--)
+								h += '<' + p[i]+ '>';
+
+							ta.push(h);
+							e.parentNode.replaceChild(d.createComment('mcetable:' + (ta.length - 1)), e);
+						}
+					});
+
+					// Replace table placeholders with end parents + table + start parents HTML code
+					t.dom.setHTML(o.node, o.node.innerHTML.replace(/<!--mcetable:([0-9]+)-->/g, function(a, b) {
+						return ta[parseInt(b)];
+					}));
+				});
+			}
+		},
+
+		setEntities : function(s) {
+			var t = this, a, i, l = {}, re = '', v;
+
+			// No need to setup more than once
+			if (t.entityLookup)
+				return;
+
+			// Build regex and lookup array
+			a = s.split(',');
+			for (i = 0; i < a.length; i += 2) {
+				v = a[i];
+
+				// Don't add default &amp; &quot; etc.
+				if (v == 34 || v == 38 || v == 60 || v == 62)
+					continue;
+
+				l[String.fromCharCode(a[i])] = a[i + 1];
+
+				v = parseInt(a[i]).toString(16);
+				re += '\\u' + '0000'.substring(v.length) + v;
+			}
+
+			if (!re) {
+				t.settings.entity_encoding = 'raw';
+				return;
+			}
+
+			t.entitiesRE = new RegExp('[' + re + ']', 'g');
+			t.entityLookup = l;
+		},
+
+		setValidChildRules : function(s) {
+			this.childRules = null;
+			this.addValidChildRules(s);
+		},
+
+		addValidChildRules : function(s) {
+			var t = this, inst, intr, bloc;
+
+			if (!s)
+				return;
+
+			inst = 'A|BR|SPAN|BDO|MAP|OBJECT|IMG|TT|I|B|BIG|SMALL|EM|STRONG|DFN|CODE|Q|SAMP|KBD|VAR|CITE|ABBR|ACRONYM|SUB|SUP|#text|#comment';
+			intr = 'A|BR|SPAN|BDO|OBJECT|APPLET|IMG|MAP|IFRAME|TT|I|B|U|S|STRIKE|BIG|SMALL|FONT|BASEFONT|EM|STRONG|DFN|CODE|Q|SAMP|KBD|VAR|CITE|ABBR|ACRONYM|SUB|SUP|INPUT|SELECT|TEXTAREA|LABEL|BUTTON|#text|#comment';
+			bloc = 'H[1-6]|P|DIV|ADDRESS|PRE|FORM|TABLE|LI|OL|UL|TD|CAPTION|BLOCKQUOTE|CENTER|DL|DT|DD|DIR|FIELDSET|FORM|NOSCRIPT|NOFRAMES|MENU|ISINDEX|SAMP';
+
+			each(s.split(','), function(s) {
+				var p = s.split(/\[|\]/), re;
+
+				s = '';
+				each(p[1].split('|'), function(v) {
+					if (s)
+						s += '|';
+
+					switch (v) {
+						case '%itrans':
+							v = intr;
+							break;
+
+						case '%itrans_na':
+							v = intr.substring(2);
+							break;
+
+						case '%istrict':
+							v = inst;
+							break;
+
+						case '%istrict_na':
+							v = inst.substring(2);
+							break;
+
+						case '%btrans':
+							v = bloc;
+							break;
+
+						case '%bstrict':
+							v = bloc;
+							break;
+					}
+
+					s += v;
+				});
+				re = new RegExp('^(' + s.toLowerCase() + ')$', 'i');
+
+				each(p[0].split('/'), function(s) {
+					t.childRules = t.childRules || {};
+					t.childRules[s] = re;
+				});
+			});
+
+			// Build regex
+			s = '';
+			each(t.childRules, function(v, k) {
+				if (s)
+					s += '|';
+
+				s += k;
+			});
+
+			t.parentElementsRE = new RegExp('^(' + s.toLowerCase() + ')$', 'i');
+
+			/*console.debug(t.parentElementsRE.toString());
+			each(t.childRules, function(v) {
+				console.debug(v.toString());
+			});*/
+		},
+
+		setRules : function(s) {
+			var t = this;
+
+			t._setup();
+			t.rules = {};
+			t.wildRules = [];
+			t.validElements = {};
+
+			return t.addRules(s);
+		},
+
+		addRules : function(s) {
+			var t = this, dr;
+
+			if (!s)
+				return;
+
+			t._setup();
+
+			each(s.split(','), function(s) {
+				var p = s.split(/\[|\]/), tn = p[0].split('/'), ra, at, wat, va = [];
+
+				// Extend with default rules
+				if (dr)
+					at = tinymce.extend([], dr.attribs);
+
+				// Parse attributes
+				if (p.length > 1) {
+					each(p[1].split('|'), function(s) {
+						var ar = {}, i;
+
+						at = at || [];
+
+						// Parse attribute rule
+						s = s.replace(/::/g, '~');
+						s = /^([!\-])?([\w*.?~]+|)([=:<])?(.+)?$/.exec(s);
+						s[2] = s[2].replace(/~/g, ':');
+
+						// Add required attributes
+						if (s[1] == '!') {
+							ra = ra || [];
+							ra.push(s[2]);
+						}
+
+						// Remove inherited attributes
+						if (s[1] == '-') {
+							for (i = 0; i <at.length; i++) {
+								if (at[i].name == s[2]) {
+									at.splice(i, 1);
+									return;
+								}
+							}
+						}
+
+						switch (s[3]) {
+							// Add default attrib values
+							case '=':
+								ar.defaultVal = s[4] || '';
+								break;
+
+							// Add forced attrib values
+							case ':':
+								ar.forcedVal = s[4];
+								break;
+
+							// Add validation values
+							case '<':
+								ar.validVals = s[4].split('?');
+								break;
+						}
+
+						if (/[*.?]/.test(s[2])) {
+							wat = wat || [];
+							ar.nameRE = new RegExp('^' + wildcardToRE(s[2]) + '$');
+							wat.push(ar);
+						} else {
+							ar.name = s[2];
+							at.push(ar);
+						}
+
+						va.push(s[2]);
+					});
+				}
+
+				// Handle element names
+				each(tn, function(s, i) {
+					var pr = s.charAt(0), x = 1, ru = {};
+
+					// Extend with default rule data
+					if (dr) {
+						if (dr.noEmpty)
+							ru.noEmpty = dr.noEmpty;
+
+						if (dr.fullEnd)
+							ru.fullEnd = dr.fullEnd;
+
+						if (dr.padd)
+							ru.padd = dr.padd;
+					}
+
+					// Handle prefixes
+					switch (pr) {
+						case '-':
+							ru.noEmpty = true;
+							break;
+
+						case '+':
+							ru.fullEnd = true;
+							break;
+
+						case '#':
+							ru.padd = true;
+							break;
+
+						default:
+							x = 0;
+					}
+
+					tn[i] = s = s.substring(x);
+					t.validElements[s] = 1;
+
+					// Add element name or element regex
+					if (/[*.?]/.test(tn[0])) {
+						ru.nameRE = new RegExp('^' + wildcardToRE(tn[0]) + '$');
+						t.wildRules = t.wildRules || {};
+						t.wildRules.push(ru);
+					} else {
+						ru.name = tn[0];
+
+						// Store away default rule
+						if (tn[0] == '@')
+							dr = ru;
+
+						t.rules[s] = ru;
+					}
+
+					ru.attribs = at;
+
+					if (ra)
+						ru.requiredAttribs = ra;
+
+					if (wat) {
+						// Build valid attributes regexp
+						s = '';
+						each(va, function(v) {
+							if (s)
+								s += '|';
+
+							s += '(' + wildcardToRE(v) + ')';
+						});
+						ru.validAttribsRE = new RegExp('^' + s.toLowerCase() + '$');
+						ru.wildAttribs = wat;
+					}
+				});
+			});
+
+			// Build valid elements regexp
+			s = '';
+			each(t.validElements, function(v, k) {
+				if (s)
+					s += '|';
+
+				if (k != '@')
+				s += k;
+			});
+			t.validElementsRE = new RegExp('^(' + wildcardToRE(s.toLowerCase()) + ')$');
+
+			//console.debug(t.validElementsRE.toString());
+			//console.dir(t.rules);
+			//console.dir(t.wildRules);
+		},
+
+		findRule : function(n) {
+			var t = this, rl = t.rules, i, r;
+
+			t._setup();
+
+			// Exact match
+			r = rl[n];
+			if (r)
+				return r;
+
+			// Try wildcards
+			rl = t.wildRules;
+			for (i = 0; i < rl.length; i++) {
+				if (rl[i].nameRE.test(n))
+					return rl[i];
+			}
+
+			return null;
+		},
+
+		findAttribRule : function(ru, n) {
+			var i, wa = ru.wildAttribs;
+
+			for (i = 0; i < wa.length; i++) {
+				if (wa[i].nameRE.test(n))
+					return wa[i];
+			}
+
+			return null;
+		},
+
+		serialize : function(n, o) {
+			var h, t = this;
+
+			t._setup();
+			o = o || {};
+			o.format = o.format || 'html';
+			t.processObj = o;
+			n = n.cloneNode(true);
+			t.key = '' + (parseInt(t.key) + 1);
+
+			// Pre process
+			if (!o.no_events) {
+				o.node = n;
+				t.onPreProcess.dispatch(t, o);
+			}
+
+			// Serialize HTML DOM into a string
+			t.writer.reset();
+			t._serializeNode(n, o.getInner);
+
+			// Post process
+			o.content = t.writer.getContent();
+
+			if (!o.no_events)
+				t.onPostProcess.dispatch(t, o);
+
+			t._postProcess(o);
+			o.node = null;
+
+			return tinymce.trim(o.content);
+		},
+
+		// Internal functions
+
+		_postProcess : function(o) {
+			var t = this, s = t.settings, h = o.content, sc = [], p, l;
+
+			if (o.format == 'html') {
+				// Protect some elements
+				p = t._protect({
+					content : h,
+					patterns : [
+						/(<script[^>]*>)(.*?)(<\/script>)/g,
+						/(<style[^>]*>)(.*?)(<\/style>)/g,
+						/(<pre[^>]*>)(.*?)(<\/pre>)/g
+					]
+				});
+
+				h = p.content;
+
+				// Entity encode
+				if (s.entity_encoding !== 'raw') {
+					if (s.entity_encoding.indexOf('named') != -1) {
+						t.setEntities(s.entities);
+						l = t.entityLookup;
+
+						h = h.replace(t.entitiesRE, function(a) {
+							var v;
+
+							if (v = l[a])
+								a = '&' + v + ';';
+
+							return a;
+						});
+					}
+
+					if (s.entity_encoding.indexOf('numeric') != -1) {
+						h = h.replace(/[\u007E-\uFFFF]/g, function(a) {
+							return '&#' + a.charCodeAt(0) + ';';
+						});
+					}
+				}
+
+				// Use BR instead of &nbsp; padded P elements inside editor and use <p>&nbsp;</p> outside editor
+				if (o.set)
+					h = h.replace(/<p>\s+(&nbsp;|&#160;|\u00a0|<br \/>)\s+<\/p>/g, '<p><br /></p>');
+				else
+					h = h.replace(/<p>\s+(&nbsp;|&#160;|\u00a0|<br \/>)\s+<\/p>/g, '<p>$1</p>');
+
+				// Since Gecko and Safari keeps whitespace in the DOM we need to
+				// remove it inorder to match other browsers. But I think Gecko and Safari is right.
+				// This process is only done when getting contents out from the editor.
+				if (!o.set) {
+					if (s.remove_linebreaks) {
+						h = h.replace(/(<[^>]+>)\s+/g, '$1 ');
+						h = h.replace(/\s+(<\/[^>]+>)/g, ' $1');
+						h = h.replace(/<(p|h[1-6]|hr|div|table|tbody|tr|td|body|head|html|title|meta|style|pre|script|link|object) ([^>]+)>\s+/g, '<$1 $2>'); // Trim block start
+						h = h.replace(/<(p|h[1-6]|hr|div|table|tbody|tr|td|body|head|html|title|meta|style|pre|script|link|object)>\s+/g, '<$1>'); // Trim block start
+						h = h.replace(/\s+<\/(p|h[1-6]|hr|div|table|tbody|tr|td|body|head|html|title|meta|style|pre|script|link|object)>/g, '</$1>'); // Trim block end
+					}
+
+					// Simple indentation
+					if (s.apply_source_formatting && s.indent_mode == 'simple') {
+						// Add line breaks before and after block elements
+						h = h.replace(/<(\/?)(ul|hr|table|meta|link|tbody|tr|object|body|head|html|map)(|[^>]+)>\s*/g, '\n<$1$2$3>\n');
+						h = h.replace(/\s*<(p|h[1-6]|div|title|style|pre|script|td|li|area)(|[^>]+)>/g, '\n<$1$2>');
+						h = h.replace(/<\/(p|h[1-6]|div|title|style|pre|script|td|li)>\s*/g, '</$1>\n');
+						h = h.replace(/\n\n/g, '\n');
+					}
+				}
+
+				h = t._unprotect(h, p);
+			}
+
+			o.content = h;
+		},
+
+		_serializeNode : function(n, inn) {
+			var t = this, s = t.settings, w = t.writer, hc, el, cn, i, l, a, at, no, v, nn, ru, ar, iv;
+
+			if (!s.node_filter || s.node_filter(n)) {
+				switch (n.nodeType) {
+					case 1: // Element
+						if (n.hasAttribute ? n.hasAttribute('mce_bogus') : n.getAttribute('mce_bogus'))
+							return;
+
+						iv = false;
+						hc = n.hasChildNodes();
+						nn = n.getAttribute('mce_name') || n.nodeName.toLowerCase();
+
+						// Add correct prefix on IE
+						if (isIE) {
+							if (n.scopeName !== 'HTML' && n.scopeName !== 'html')
+								nn = n.scopeName + ':' + nn;
+						}
+
+						// Remove mce prefix on IE needed for the abbr element
+						if (nn.indexOf('mce:') === 0)
+							nn = nn.substring(4);
+
+						// Check if valid
+						if (!t.validElementsRE.test(nn) || (t.invalidElementsRE && t.invalidElementsRE.test(nn)) || inn) {
+							iv = true;
+							break;
+						}
+
+						if (isIE) {
+							// Fix IE content duplication (DOM can have multiple copies of the same node)
+							if (s.fix_content_duplication) {
+								if (n.mce_serialized == t.key)
+									return;
+
+								n.mce_serialized = t.key;
+							}
+
+							// IE sometimes adds a / infront of the node name
+							if (nn.charAt(0) == '/')
+								nn = nn.substring(1);
+						}
+
+						// Check if valid child
+						if (t.childRules) {
+							if (t.parentElementsRE.test(t.elementName)) {
+								if (!t.childRules[t.elementName].test(nn)) {
+									iv = true;
+									break;
+								}
+							}
+
+							t.elementName = nn;
+						}
+
+						ru = t.findRule(nn);
+						nn = ru.name || nn;
+
+						// Skip empty nodes or empty node name in IE
+						if ((!hc && ru.noEmpty) || (isIE && !nn)) {
+							iv = true;
+							break;
+						}
+
+						// Check required
+						if (ru.requiredAttribs) {
+							a = ru.requiredAttribs;
+
+							for (i = a.length - 1; i >= 0; i--) {
+								if (this.dom.getAttrib(n, a[i]) !== '')
+									break;
+							}
+
+							// None of the required was there
+							if (i == -1) {
+								iv = true;
+								break;
+							}
+						}
+
+						w.writeStartElement(nn);
+
+						// Add ordered attributes
+						if (ru.attribs) {
+							for (i=0, at = ru.attribs, l = at.length; i<l; i++) {
+								a = at[i];
+								v = t._getAttrib(n, a);
+
+								if (v !== null)
+									w.writeAttribute(a.name, v);
+							}
+						}
+
+						// Add wild attributes
+						if (ru.validAttribsRE) {
+							at = isIE ? getIEAtts(n) : n.attributes;
+							for (i=at.length-1; i>-1; i--) {
+								no = at[i];
+
+								if (no.specified) {
+									a = no.nodeName.toLowerCase();
+
+									if (s.invalid_attrs.test(a) || !ru.validAttribsRE.test(a))
+										continue;
+
+									ar = t.findAttribRule(ru, a);
+									v = t._getAttrib(n, ar, a);
+
+									if (v !== null)
+										w.writeAttribute(a, v);
+								}
+							}
+						}
+
+						// Padd empty nodes with a &nbsp;
+						if (!hc && ru.padd)
+							w.writeText('\u00a0');
+
+						break;
+
+					case 3: // Text
+						// Check if valid child
+						if (t.childRules && t.parentElementsRE.test(t.elementName)) {
+							if (!t.childRules[t.elementName].test(n.nodeName))
+								return;
+						}
+
+						return w.writeText(n.nodeValue);
+
+					case 4: // CDATA
+						return w.writeCDATA(n.nodeValue);
+
+					case 8: // Comment
+						return w.writeComment(n.nodeValue);
+				}
+			} else if (n.nodeType == 1)
+				hc = n.hasChildNodes();
+
+			if (hc) {
+				cn = n.firstChild;
+
+				while (cn) {
+					t._serializeNode(cn);
+					t.elementName = nn;
+					cn = cn.nextSibling;
+				}
+			}
+
+			// Write element end
+			if (!iv) {
+				if (hc || !s.closed.test(nn))
+					w.writeFullEndElement();
+				else
+					w.writeEndElement();
+			}
+		},
+
+		_protect : function(o) {
+			o.items = o.items || [];
+
+			function enc(s) {
+				return s.replace(/[\r\n]/g, function(c) {
+					if (c === '\n')
+						return '\\n';
+
+					return '\\r';
+				});
+			};
+
+			function dec(s) {
+				return s.replace(/\\[rn]/g, function(c) {
+					if (c === '\\n')
+						return '\n';
+
+					return '\r';
+				});
+			};
+
+			each(o.patterns, function(p) {
+				o.content = dec(enc(o.content).replace(p, function(x, a, b, c) {
+					o.items.push(dec(b));
+					return a + '<!--mce:' + (o.items.length - 1) + '-->' + c;
+				}));
+			});
+
+			return o;
+		},
+
+		_unprotect : function(h, o) {
+			h = h.replace(/\<!--mce:([0-9]+)--\>/g, function(a, b) {
+				return o.items[parseInt(b)];
+			});
+
+			o.items = [];
+
+			return h;
+		},
+
+		_setup : function() {
+			var t = this, s = this.settings;
+
+			if (t.done)
+				return;
+
+			t.done = 1;
+
+			t.setRules(s.valid_elements);
+			t.addRules(s.extended_valid_elements);
+			t.addValidChildRules(s.valid_child_elements);
+
+			if (s.invalid_elements)
+				t.invalidElementsRE = new RegExp('^(' + wildcardToRE(s.invalid_elements.replace(',', '|').toLowerCase()) + ')$');
+
+			if (s.attrib_value_filter)
+				t.attribValueFilter = s.attribValueFilter;
+		},
+
+		_getAttrib : function(n, a, na) {
+			var i, v;
+
+			na = na || a.name;
+
+			if (a.forcedVal && (v = a.forcedVal)) {
+				if (v === '{$uid}')
+					return this.dom.uniqueId();
+
+				return v;
+			}
+
+			v = this.dom.getAttrib(n, na);
+
+			switch (na) {
+				case 'rowspan':
+				case 'colspan':
+					// Whats the point? Remove usless attribute value
+					if (v == '1')
+						v = '';
+
+					break;
+			}
+
+			if (this.attribValueFilter)
+				v = this.attribValueFilter(na, v, n);
+
+			if (a.validVals) {
+				for (i = a.validVals.length - 1; i >= 0; i--) {
+					if (v == a.validVals[i])
+						break;
+				}
+
+				if (i == -1)
+					return null;
+			}
+
+			if (v === '' && typeof(a.defaultVal) != 'undefined') {
+				v = a.defaultVal;
+
+				if (v === '{$uid}')
+					return this.dom.uniqueId();
+
+				return v;
+			} else {
+				// Remove internal mceItemXX classes when content is extracted from editor
+				if (na == 'class' && this.processObj.get)
+					v = v.replace(/\bmceItem\w+\b/g, '');
+			}
+
+			if (v === '')
+				return null;
+
+
+			return v;
 		}
 
-		return null;
-	},
-
-	_getTextPos : function(r, sp, ep) {
-		var w = document.createTreeWalker(r, NodeFilter.SHOW_TEXT, null, false), n, p = 0, d = {};
-
-		while ((n = w.nextNode()) != null) {
-			p += n.nodeValue ? n.nodeValue.length : 0;
-
-			if (p >= sp && !d.startNode) {
-				d.startNode = n;
-				d.startOffset = sp - (p - n.nodeValue.length);
-			}
-
-			if (p >= ep) {
-				d.endNode = n;
-				d.endOffset = ep - (p - n.nodeValue.length);
-
-				return d;
+		});
+})();
+
+/* file:jscripts/tiny_mce/classes/dom/ScriptLoader.js */
+
+(function() {
+	var each = tinymce.each;
+
+	tinymce.create('tinymce.dom.ScriptLoader', {
+		ScriptLoader : function(s) {
+			this.settings = s || {};
+			this.queue = [];
+			this.lookup = {};
+		},
+
+		markDone : function(u) {
+			this.lookup[u] = {state : 2, url : u};
+		},
+
+		add : function(u, cb, s, pr) {
+			var t = this, lo = t.lookup, o;
+
+			if (o = lo[u]) {
+				// Is loaded fire callback
+				if (cb && o.state == 2)
+					cb.call(s || this);
+
+				return o;
+			}
+
+			o = {state : 0, url : u, func : cb, scope : s || this};
+
+			if (pr)
+				t.queue.unshift(o);
+			else
+				t.queue.push(o);
+
+			lo[u] = o;
+
+			return o;
+		},
+
+		load : function(u, cb, s) {
+			var t = this, o;
+
+			function loadScript(u) {
+				if (tinymce.dom.Event.domLoaded || t.settings.strict_mode) {
+					tinymce.util.XHR.send({
+						url : u,
+						error : t.settings.error,
+						async : false,
+						success : function(co) {
+							t.eval(co);
+						}
+					});
+				} else
+					document.write('<script type="text/javascript" src="' + u + '"></script>');
+			};
+
+			if (!tinymce.is(u, 'string')) {
+				each(u, function(u) {
+					loadScript(u);
+				});
+
+				if (cb)
+					cb.call(s || t);
+			} else {
+				loadScript(u);
+
+				if (cb)
+					cb.call(s || t);
+			}
+		},
+
+		loadQueue : function(cb, s) {
+			var t = this;
+
+			if (!t.queueLoading) {
+				t.queueLoading = 1;
+				t.queueCallbacks = [];
+
+				t.loadScripts(t.queue, function() {
+					t.queueLoading = 0;
+
+					if (cb)
+						cb.call(s || t);
+
+					each(t.queueCallbacks, function(o) {
+						o.func.call(o.scope);
+					});
+				});
+			} else if (cb)
+				t.queueCallbacks.push({func : cb, scope : s || t});
+		},
+
+		eval : function(co) {
+			var w = window;
+
+			// Evaluate script
+			if (!w.execScript) {
+				try {
+					eval.call(w, co);
+				} catch (ex) {
+					eval(co, w); // Firefox 3.0a8
+				}
+			} else
+				w.execScript(co); // IE
+		},
+
+		loadScripts : function(sc, cb, s) {
+			var t = this, lo = t.lookup;
+
+			function done(o) {
+				o.state = 2; // Has been loaded
+
+				// Run callback
+				if (o.func)
+					o.func.call(o.scope || t);
+			};
+
+			function allDone() {
+				var l;
+
+				// Check if all files are loaded
+				l = sc.length;
+				each(sc, function(o) {
+					o = lo[o.url];
+
+					if (o.state === 2) {// It has finished loading
+						done(o);
+						l--;
+					} else
+						load(o);
+				});
+
+				// They are all loaded
+				if (l === 0 && cb) {
+					cb.call(s || t);
+					cb = 0;
+				}
+			};
+
+			function load(o) {
+				if (o.state > 0)
+					return;
+
+				o.state = 1; // Is loading
+
+				tinymce.util.XHR.send({
+					url : o.url,
+					error : t.settings.error,
+					success : function(co) {
+						t.eval(co);
+						done(o);
+						allDone();
+					}
+				});
+			};
+
+			each(sc, function(o) {
+				var u = o.url;
+
+				// Add to queue if needed
+				if (!lo[u]) {
+					lo[u] = o;
+					t.queue.push(o);
+				} else
+					o = lo[u];
+
+				// Is already loading or has been loaded
+				if (o.state > 0)
+					return;
+
+				if (!tinymce.dom.Event.domLoaded && !t.settings.strict_mode) {
+					var ix, ol = '';
+
+					// Add onload events
+					if (cb || o.func) {
+						o.state = 1; // Is loading
+
+						ix = tinymce.dom.ScriptLoader._addOnLoad(function() {
+							done(o);
+							allDone();
+						});
+
+						if (tinymce.isIE)
+							ol = ' onreadystatechange="';
+						else
+							ol = ' onload="';
+
+						ol += 'tinymce.dom.ScriptLoader._onLoad(this,\'' + u + '\',' + ix + ');"';
+					}
+
+					document.write('<script type="text/javascript" src="' + u + '"' + ol + '></script>');
+
+					if (!o.func)
+						done(o);
+				} else
+					load(o);
+			});
+
+			allDone();
+		},
+
+		// Static methods
+		'static' : {
+			_addOnLoad : function(f) {
+				var t = this;
+
+				t._funcs = t._funcs || [];
+				t._funcs.push(f);
+
+				return t._funcs.length - 1;
+			},
+
+			_onLoad : function(e, u, ix) {
+				if (!tinymce.isIE || e.readyState == 'complete')
+					this._funcs[ix].call(this);
 			}
 		}
 
-		return null;
+		});
+
+	// Global script loader
+	tinymce.ScriptLoader = new tinymce.dom.ScriptLoader();
+})();
+
+/* file:jscripts/tiny_mce/classes/ui/Control.js */
+
+(function() {
+	// Shorten class names
+	var DOM = tinymce.DOM, is = tinymce.is;
+
+	tinymce.create('tinymce.ui.Control', {
+		Control : function(id, s) {
+			this.id = id;
+			this.settings = s = s || {};
+			this.rendered = false;
+			this.onRender = new tinymce.util.Dispatcher(this);
+			this.classPrefix = '';
+			this.scope = s.scope || this;
+			this.disabled = 0;
+			this.active = 0;
+		},
+
+		setDisabled : function(s) {
+			var e;
+
+			if (s != this.disabled) {
+				e = DOM.get(this.id);
+
+				// Add accessibility title for unavailable actions
+				if (e && this.settings.unavailable_prefix) {
+					if (s) {
+						this.prevTitle = e.title;
+						e.title = this.settings.unavailable_prefix + ": " + e.title;
+					} else
+						e.title = this.prevTitle;
+				}
+
+				this.setState('Disabled', s);
+				this.setState('Enabled', !s);
+				this.disabled = s;
+			}
+		},
+
+		isDisabled : function() {
+			return this.disabled;
+		},
+
+		setActive : function(s) {
+			if (s != this.active) {
+				this.setState('Active', s);
+				this.active = s;
+			}
+		},
+
+		isActive : function() {
+			return this.active;
+		},
+
+		setState : function(c, s) {
+			var n = DOM.get(this.id);
+
+			c = this.classPrefix + c;
+
+			if (s)
+				DOM.addClass(n, c);
+			else
+				DOM.removeClass(n, c);
+		},
+
+		isRendered : function() {
+			return this.rendered;
+		},
+
+		renderHTML : function() {
+		},
+
+		renderTo : function(n) {
+			DOM.setHTML(n, this.renderHTML());
+		},
+
+		postRender : function() {
+			var t = this, b;
+
+			// Set pending states
+			if (is(t.disabled)) {
+				b = t.disabled;
+				t.disabled = -1;
+				t.setDisabled(b);
+			}
+
+			if (is(t.active)) {
+				b = t.active;
+				t.active = -1;
+				t.setActive(b);
+			}
+		},
+
+		destroy : function() {
+			DOM.remove(this.id);
+		}
+
+		});
+})();
+/* file:jscripts/tiny_mce/classes/ui/Container.js */
+
+tinymce.create('tinymce.ui.Container:tinymce.ui.Control', {
+	Container : function(id, s) {
+		this.parent(id, s);
+		this.controls = [];
+		this.lookup = {};
+	},
+
+	add : function(c) {
+		this.lookup[c.id] = c;
+		this.controls.push(c);
+
+		return c;
 	},
 
-	selectNode : function(node, collapse, select_text_node, to_start) {
-		var inst = this.instance, sel, rng, nodes;
-
-		if (!node)
-			return;
-
-		if (typeof(collapse) == "undefined")
-			collapse = true;
-
-		if (typeof(select_text_node) == "undefined")
-			select_text_node = false;
-
-		if (typeof(to_start) == "undefined")
-			to_start = true;
-
-		if (inst.settings.auto_resize)
-			inst.resizeToContent();
-
-		if (tinyMCE.isRealIE) {
-			rng = inst.getDoc().body.createTextRange();
-
-			try {
-				rng.moveToElementText(node);
-
-				if (collapse)
-					rng.collapse(to_start);
-
-				rng.select();
-			} catch (e) {
-				// Throws illigal agrument in MSIE some times
-			}
-		} else {
-			sel = this.getSel();
-
-			if (!sel)
+	get : function(n) {
+		return this.lookup[n];
+	}
+
+	});
+
+
+/* file:jscripts/tiny_mce/classes/ui/Separator.js */
+
+tinymce.create('tinymce.ui.Separator:tinymce.ui.Control', {
+	renderHTML : function() {
+		return tinymce.DOM.createHTML('span', {'class' : 'mceSeparator'});
+	}
+
+	});
+
+/* file:jscripts/tiny_mce/classes/ui/MenuItem.js */
+
+(function() {
+	var is = tinymce.is, DOM = tinymce.DOM, each = tinymce.each, walk = tinymce.walk;
+
+	tinymce.create('tinymce.ui.MenuItem:tinymce.ui.Control', {
+		MenuItem : function(id, s) {
+			this.parent(id, s);
+			this.classPrefix = 'mceMenuItem';
+		},
+
+		setSelected : function(s) {
+			this.setState('Selected', s);
+			this.selected = s;
+		},
+
+		isSelected : function() {
+			return this.selected;
+		},
+
+		postRender : function() {
+			var t = this;
+			
+			t.parent();
+
+			// Set pending state
+			if (is(t.selected))
+				t.setSelected(t.selected);
+		}
+
+		});
+})();
+
+/* file:jscripts/tiny_mce/classes/ui/Menu.js */
+
+(function() {
+	var is = tinymce.is, DOM = tinymce.DOM, each = tinymce.each, walk = tinymce.walk;
+
+	tinymce.create('tinymce.ui.Menu:tinymce.ui.MenuItem', {
+		Menu : function(id, s) {
+			var t = this;
+
+			t.parent(id, s);
+			t.items = {};
+			t.collapsed = false;
+			t.menuCount = 0;
+			t.onAddItem = new tinymce.util.Dispatcher(this);
+		},
+
+		expand : function(d) {
+			var t = this;
+
+			if (d) {
+				walk(t, function(o) {
+					if (o.expand)
+						o.expand();
+				}, 'items', t);
+			}
+
+			t.collapsed = false;
+		},
+
+		collapse : function(d) {
+			var t = this;
+
+			if (d) {
+				walk(t, function(o) {
+					if (o.collapse)
+						o.collapse();
+				}, 'items', t);
+			}
+
+			t.collapsed = true;
+		},
+
+		isCollapsed : function() {
+			return this.collapsed;
+		},
+
+		add : function(o) {
+			if (!o.settings)
+				o = new tinymce.ui.MenuItem(o.id || DOM.uniqueId(), o);
+
+			this.onAddItem.dispatch(this, o);
+
+			return this.items[o.id] = o;
+		},
+
+		addSeparator : function() {
+			return this.add({separator : true});
+		},
+
+		addMenu : function(o) {
+			if (!o.collapse)
+				o = this.createMenu(o);
+
+			this.menuCount++;
+
+			return this.add(o);
+		},
+
+		hasMenus : function() {
+			return this.menuCount !== 0;
+		},
+
+		remove : function(o) {
+			delete this.items[o.id];
+		},
+
+		removeAll : function() {
+			var t = this;
+
+			walk(t, function(o) {
+				if (o.removeAll)
+					o.removeAll();
+
+				o.destroy();
+			}, 'items', t);
+
+			t.items = {};
+		},
+
+		createMenu : function(o) {
+			var m = new tinymce.ui.Menu(o.id || DOM.uniqueId(), o);
+
+			m.onAddItem.add(this.onAddItem.dispatch, this.onAddItem);
+
+			return m;
+		}
+
+		});
+})();
+/* file:jscripts/tiny_mce/classes/ui/DropMenu.js */
+
+(function() {
+	var is = tinymce.is, DOM = tinymce.DOM, each = tinymce.each, Event = tinymce.dom.Event, Element = tinymce.dom.Element;
+
+	tinymce.create('tinymce.ui.DropMenu:tinymce.ui.Menu', {
+		DropMenu : function(id, s) {
+			s = s || {};
+			s.container = s.container || document.body;
+			s.offset_x = s.offset_x || 0;
+			s.offset_y = s.offset_y || 0;
+			s.vp_offset_x = s.vp_offset_x || 0;
+			s.vp_offset_y = s.vp_offset_y || 0;
+
+			if (is(s.icons) && !s.icons)
+				s['class'] += ' noIcons';
+
+			this.parent(id, s);
+			this.onHideMenu = new tinymce.util.Dispatcher(this);
+			this.classPrefix = 'mceMenu';
+		},
+
+		createMenu : function(s) {
+			var t = this, cs = t.settings, m;
+
+			s.container = s.container || cs.container;
+			s.parent = t;
+			s.constrain = s.constrain || cs.constrain;
+			s['class'] = s['class'] || cs['class'];
+			s.vp_offset_x = s.vp_offset_x || cs.vp_offset_x;
+			s.vp_offset_y = s.vp_offset_y || cs.vp_offset_y;
+			m = new tinymce.ui.DropMenu(s.id || DOM.uniqueId(), s);
+
+			m.onAddItem.add(t.onAddItem.dispatch, t.onAddItem);
+
+			return m;
+		},
+
+		update : function() {
+			var t = this, s = t.settings, tb = DOM.get('menu_' + t.id + '_tbl'), co = DOM.get('menu_' + t.id + '_co'), tw, th;
+
+			tw = s.max_width ? Math.min(tb.clientWidth, s.max_width) : tb.clientWidth;
+			th = s.max_height ? Math.min(tb.clientHeight, s.max_height) : tb.clientHeight;
+
+			if (!DOM.boxModel)
+				t.element.setStyles({width : tw + 2, height : th + 2});
+			else
+				t.element.setStyles({width : tw, height : th});
+
+			if (s.max_width)
+				DOM.setStyle(co, 'width', tw);
+
+			if (s.max_height) {
+				DOM.setStyle(co, 'height', th);
+
+				if (tb.clientHeight < s.max_height)
+					DOM.setStyle(co, 'overflow', 'hidden');
+			}
+		},
+
+		showMenu : function(x, y, px) {
+			var t = this, s = t.settings, co, vp = DOM.getViewPort(), w, h, mx, my, ot = 2, dm, tb;
+
+			t.collapse(1);
+
+			if (t.isMenuVisible)
 				return;
 
-			if (tinyMCE.isSafari) {
-				sel.setBaseAndExtent(node, 0, node, node.innerText.length);
-
-				if (collapse) {
-					if (to_start)
-						sel.collapseToStart();
-					else
-						sel.collapseToEnd();
-				}
-
-				this.scrollToNode(node);
+			if (!t.rendered) {
+				co = DOM.add(t.settings.container, t.renderNode());
+
+				each(t.items, function(o) {
+					o.postRender();
+				});
+
+				t.element = new Element('menu_' + t.id, {blocker : 1, container : s.container});
+			} else
+				co = DOM.get('menu_' + t.id);
+
+			DOM.setStyles(co, {left : -0xFFFF , top : -0xFFFF});
+			DOM.show(co);
+			t.update();
+
+			x += s.offset_x || 0;
+			y += s.offset_y || 0;
+			vp.w -= 4;
+			vp.h -= 4;
+
+			// Move inside viewport if not submenu
+			if (s.constrain) {
+				w = co.clientWidth - ot;
+				h = co.clientHeight - ot;
+				mx = vp.x + vp.w;
+				my = vp.y + vp.h;
+
+				if ((x + s.vp_offset_x + w) > mx)
+					x = px ? px - w : Math.max(0, (mx - s.vp_offset_x) - w);
+
+				if ((y + s.vp_offset_y + h) > my)
+					y = Math.max(0, (my - s.vp_offset_y) - h);
+			}
+
+			DOM.setStyles(co, {left : x , top : y});
+			t.element.update();
+
+			t.isMenuVisible = 1;
+			t.mouseClickFunc = Event.add(co, 'click', function(e) {
+				var m;
+
+				e = e.target;
+
+				if (e && (e = DOM.getParent(e, 'TR')) && !DOM.hasClass(e, 'mceMenuItemSub')) {
+					m = t.items[e.id];
+
+					if (m.isDisabled())
+						return;
+
+					if (m.settings.onclick)
+						m.settings.onclick(e);
+
+					dm = t;
+
+					while (dm) {
+						if (dm.hideMenu)
+							dm.hideMenu();
+
+						dm = dm.settings.parent;
+					}
+
+					return Event.cancel(e); // Cancel to fix onbeforeunload problem
+				}
+			});
+
+			if (t.hasMenus()) {
+				t.mouseOverFunc = Event.add(co, 'mouseover', function(e) {
+					var m, r, mi;
+
+					e = e.target;
+					if (e && (e = DOM.getParent(e, 'TR'))) {
+						m = t.items[e.id];
+
+						if (t.lastMenu)
+							t.lastMenu.collapse(1);
+
+						if (m.isDisabled())
+							return;
+
+						if (e && DOM.hasClass(e, 'mceMenuItemSub')) {
+							//p = DOM.getPos(s.container);
+							r = DOM.getRect(e);
+							m.showMenu((r.x + r.w - ot), r.y - ot, r.x);
+							t.lastMenu = m;
+							DOM.addClass(DOM.get(m.id).firstChild, 'mceMenuItemActive');
+						}
+					}
+				});
+			}
+		},
+
+		hideMenu : function(c) {
+			var t = this, co = DOM.get('menu_' + t.id), e;
+
+			if (!t.isMenuVisible)
+				return;
+
+			Event.remove(co, 'mouseover', t.mouseOverFunc);
+			Event.remove(co, 'click', t.mouseClickFunc);
+			DOM.hide(co);
+			t.isMenuVisible = 0;
+
+			if (!c)
+				t.collapse(1);
+
+			if (t.element)
+				t.element.hide();
+
+			if (e = DOM.get(t.id))
+				DOM.removeClass(e.firstChild, 'mceMenuItemActive');
+
+			t.onHideMenu.dispatch(t);
+		},
+
+		add : function(o) {
+			var t = this, co;
+
+			o = t.parent(o);
+
+			if (t.isRendered && (co = DOM.get('menu_' + t.id)))
+				t._add(DOM.select('tbody', co)[0], o);
+
+			return o;
+		},
+
+		collapse : function(d) {
+			this.parent(d);
+			this.hideMenu(1);
+		},
+
+		remove : function(o) {
+			DOM.remove(o.id);
+
+			return this.parent(o);
+		},
+
+		destroy : function() {
+			var t = this, co = DOM.get('menu_' + t.id);
+
+			Event.remove(co, 'mouseover', t.mouseOverFunc);
+			Event.remove(co, 'click', t.mouseClickFunc);
+
+			if (t.element)
+				t.element.remove();
+
+			DOM.remove(co);
+		},
+
+		renderNode : function() {
+			var t = this, s = t.settings, n, tb, co, w;
+
+			w = DOM.create('div', {id : 'menu_' + t.id, 'class' : s['class'], 'style' : 'position:absolute;left:0;top:0;z-index:150'});
+			co = DOM.add(w, 'div', {id : 'menu_' + t.id + '_co', 'class' : 'mceMenu' + (s['class'] ? ' ' + s['class'] : '')});
+			t.element = new Element('menu_' + t.id, {blocker : 1, container : s.container});
+
+			if (s.menu_line)
+				DOM.add(co, 'span', {'class' : 'mceMenuLine'});
+
+//			n = DOM.add(co, 'div', {id : 'menu_' + t.id + '_co', 'class' : 'mceMenuContainer'});
+			n = DOM.add(co, 'table', {id : 'menu_' + t.id + '_tbl', border : 0, cellPadding : 0, cellSpacing : 0});
+			tb = DOM.add(n, 'tbody');
+
+			each(t.items, function(o) {
+				t._add(tb, o);
+			});
+
+			t.rendered = true;
+
+			return w;
+		},
+
+		// Internal functions
+
+		_add : function(tb, o) {
+			var n, s = o.settings, a, ro, it;
+
+			if (s.separator) {
+				ro = DOM.add(tb, 'tr', {id : o.id, 'class' : 'mceMenuItemSeparator'});
+				DOM.add(ro, 'td', {'class' : 'mceMenuItemSeparator'});
+
+				if (n = ro.previousSibling)
+					DOM.addClass(n, 'last');
 
 				return;
 			}
 
-			rng = inst.getDoc().createRange();
-
-			if (select_text_node) {
-				// Find first textnode in tree
-				nodes = tinyMCE.getNodeTree(node, new Array(), 3);
-				if (nodes.length > 0)
-					rng.selectNodeContents(nodes[0]);
-				else
-					rng.selectNodeContents(node);
-			} else
-				rng.selectNode(node);
-
-			if (collapse) {
-				// Special treatment of textnode collapse
-				if (!to_start && node.nodeType == 3) {
-					rng.setStart(node, node.nodeValue.length);
-					rng.setEnd(node, node.nodeValue.length);
-				} else
-					rng.collapse(to_start);
-			}
-
-			sel.removeAllRanges();
-			sel.addRange(rng);
+			n = ro = DOM.add(tb, 'tr', {id : o.id, 'class' : 'mceMenuItem mceMenuItemEnabled'});
+			n = it = DOM.add(n, 'td');
+			n = a = DOM.add(n, 'a', {href : 'javascript:;', onclick : "return false;", onmousedown : 'return false;'});
+
+			DOM.addClass(it, s['class']);
+//			n = DOM.add(n, 'span', {'class' : 'item'});
+			DOM.add(n, 'span', {'class' : 'icon' + (s.icon ? ' ' + s.icon : '')});
+			n = DOM.add(n, s.element || 'span', {'class' : 'text', title : o.settings.title}, o.settings.title);
+
+			if (o.settings.style)
+				DOM.setAttrib(n, 'style', o.settings.style);
+
+			if (tb.childNodes.length == 1)
+				DOM.addClass(ro, 'first');
+
+			if ((n = ro.previousSibling) && DOM.hasClass(n, 'mceMenuItemSeparator'))
+				DOM.addClass(ro, 'first');
+
+			if (o.collapse)
+				DOM.addClass(ro, 'mceMenuItemSub');
+
+			if (n = ro.previousSibling)
+				DOM.removeClass(n, 'last');
+
+			DOM.addClass(ro, 'last');
+		}
+
+		});
+})();
+/* file:jscripts/tiny_mce/classes/ui/Button.js */
+
+(function() {
+	var DOM = tinymce.DOM;
+
+	tinymce.create('tinymce.ui.Button:tinymce.ui.Control', {
+		Button : function(id, s) {
+			this.parent(id, s);
+			this.classPrefix = 'mceButton';
+		},
+
+		renderHTML : function() {
+			var s = this.settings, h = '<a id="' + this.id + '" href="javascript:;" class="mceButton mceButtonEnabled ' + s['class'] + '" onmousedown="return false;" onclick="return false;" title="' + DOM.encode(s.title) + '">';
+
+			if (s.image)
+				h += '<img class="icon" src="' + s.image + '" /></a>';
+			else
+				h += '<span class="icon ' + s['class'] + '"></span></a>';
+
+			return h;
+		},
+
+		postRender : function() {
+			var t = this, s = t.settings;
+
+			tinymce.dom.Event.add(t.id, 'click', function(e) {
+				if (!t.isDisabled())
+					return s.onclick.call(s.scope, e);
+			});
 		}
 
-		this.scrollToNode(node);
-
-		// Set selected element
-		tinyMCE.selectedElement = null;
-		if (node.nodeType == 1)
-			tinyMCE.selectedElement = node;
-	},
-
-	scrollToNode : function(node) {
-		var inst = this.instance, w = inst.getWin(), vp = inst.getViewPort(), pos = tinyMCE.getAbsPosition(node), cvp, p, cwin;
-
-		// Only scroll if out of visible area
-		if (pos.absLeft < vp.left || pos.absLeft > vp.left + vp.width || pos.absTop < vp.top || pos.absTop > vp.top + (vp.height-25))
-			w.scrollTo(pos.absLeft, pos.absTop - vp.height + 25);
-
-		// Scroll container window
-		if (inst.settings.auto_resize) {
-			cwin = inst.getContainerWin();
-			cvp = tinyMCE.getViewPort(cwin);
-			p = this.getAbsPosition(node);
-
-			if (p.absLeft < cvp.left || p.absLeft > cvp.left + cvp.width || p.absTop < cvp.top || p.absTop > cvp.top + cvp.height)
-				cwin.scrollTo(p.absLeft, p.absTop - cvp.height + 25);
+		});
+})();
+
+/* file:jscripts/tiny_mce/classes/ui/ListBox.js */
+
+(function() {
+	var DOM = tinymce.DOM, Event = tinymce.dom.Event, each = tinymce.each, Dispatcher = tinymce.util.Dispatcher;
+
+	tinymce.create('tinymce.ui.ListBox:tinymce.ui.Control', {
+		ListBox : function(id, s) {
+			var t = this;
+
+			t.parent(id, s);
+			t.items = [];
+			t.onChange = new Dispatcher(t);
+			t.onPostRender = new Dispatcher(t);
+			t.onAdd = new Dispatcher(t);
+			t.onRenderMenu = new tinymce.util.Dispatcher(this);
+			t.classPrefix = 'mceListBox';
+		},
+
+		select : function(v) {
+			var t = this, e, fv;
+
+			// Do we need to do something?
+			if (v != t.selectedValue) {
+				e = DOM.get(t.id + '_text');
+				t.selectedValue = v;
+
+				// Find item
+				each(t.items, function(o) {
+					if (o.value == v) {
+						DOM.setHTML(e, DOM.encode(o.title));
+						fv = 1;
+						return false;
+					}
+				});
+
+				// If no item was found then present title
+				if (!fv) {
+					DOM.setHTML(e, DOM.encode(t.settings.title));
+					DOM.addClass(e, 'title');
+					e = 0;
+					return;
+				} else
+					DOM.removeClass(e, 'title');
+			}
+
+			e = 0;
+		},
+
+		add : function(n, v, o) {
+			var t = this;
+
+			o = o || {};
+			o = tinymce.extend(o, {
+				title : n,
+				value : v
+			});
+
+			t.items.push(o);
+			t.onAdd.dispatch(t, o);
+		},
+
+		getLength : function() {
+			return this.items.length;
+		},
+
+		renderHTML : function() {
+			var h = '', t = this, s = t.settings;
+
+			h = '<table id="' + t.id + '" cellpadding="0" cellspacing="0" class="mceListBox mceListBoxEnabled' + (s['class'] ? (' ' + s['class']) : '') + '"><tbody><tr>';
+			h += '<td>' + DOM.createHTML('a', {id : t.id + '_text', href : 'javascript:;', 'class' : 'text', onclick : "return false;", onmousedown : 'return false;'}, DOM.encode(t.settings.title)) + '</td>';
+			h += '<td>' + DOM.createHTML('a', {id : t.id + '_open', href : 'javascript:;', 'class' : 'open', onclick : "return false;", onmousedown : 'return false;'}, '<span></span>') + '</td>';
+			h += '</tr></tbody></table>';
+
+			return h;
+		},
+
+		showMenu : function() {
+			var t = this, p1, p2, e = DOM.get(this.id), m;
+
+			if (t.isDisabled() || t.items.length == 0)
+				return;
+
+			if (!t.isMenuRendered) {
+				t.renderMenu();
+				t.isMenuRendered = true;
+			}
+
+			p1 = DOM.getPos(this.settings.menu_container);
+			p2 = DOM.getPos(e);
+
+			m = t.menu;
+			m.settings.offset_x = p2.x;
+			m.settings.offset_y = p2.y;
+
+			// Select in menu
+			if (t.oldID)
+				m.items[t.oldID].setSelected(0);
+
+			each(t.items, function(o) {
+				if (o.value === t.selectedValue) {
+					m.items[o.id].setSelected(1);
+					t.oldID = o.id;
+				}
+			});
+
+			m.showMenu(0, e.clientHeight);
+
+			Event.add(document, 'mousedown', t.hideMenu, t);
+			DOM.addClass(t.id, 'mceListBoxSelected');
+		},
+
+		hideMenu : function(e) {
+			var t = this;
+
+			if (!e || !DOM.getParent(e.target, function(n) {return DOM.hasClass(n, 'mceMenu');})) {
+				DOM.removeClass(t.id, 'mceListBoxSelected');
+				Event.remove(document, 'mousedown', t.hideMenu, t);
+
+				if (t.menu)
+					t.menu.hideMenu();
+			}
+		},
+
+		renderMenu : function() {
+			var t = this, m;
+
+			m = t.settings.control_manager.createDropMenu(t.id + '_menu', {
+				menu_line : 1,
+				'class' : 'mceListBoxMenu noIcons',
+				max_width : 150,
+				max_height : 150
+			});
+
+			m.onHideMenu.add(t.hideMenu, t);
+
+			m.add({
+				title : t.settings.title,
+				'class' : 'mceMenuItemTitle'
+			}).setDisabled(1);
+
+			each(t.items, function(o) {
+				o.id = DOM.uniqueId();
+				o.onclick = function() {
+					if (t.settings.onselect(o.value) !== false)
+						t.select(o.value); // Must be runned after
+				};
+
+				m.add(o);
+			});
+
+			t.onRenderMenu.dispatch(t, m);
+			t.menu = m;
+		},
+
+		postRender : function() {
+			var t = this;
+
+			Event.add(t.id, 'click', t.showMenu, t);
+
+			// Old IE doesn't have hover on all elements
+			if (tinymce.isIE6 || !DOM.boxModel) {
+				Event.add(t.id, 'mouseover', function() {
+					if (!DOM.hasClass(t.id, 'mceListBoxDisabled'))
+						DOM.addClass(t.id, 'mceListBoxHover');
+				});
+
+				Event.add(t.id, 'mouseout', function() {
+					if (!DOM.hasClass(t.id, 'mceListBoxDisabled'))
+						DOM.removeClass(t.id, 'mceListBoxHover');
+				});
+			}
+
+			t.onPostRender.dispatch(t, DOM.get(t.id));
 		}
-	},
-
-	getAbsPosition : function(n) {
-		var pos = tinyMCE.getAbsPosition(n), ipos = tinyMCE.getAbsPosition(this.instance.iframeElement);
-
-		return {
-			absLeft : ipos.absLeft + pos.absLeft,
-			absTop : ipos.absTop + pos.absTop
-		};
-	},
-
-	getSel : function() {
-		var inst = this.instance;
-
-		if (tinyMCE.isRealIE)
-			return inst.getDoc().selection;
-
-		return inst.contentWindow.getSelection();
-	},
-
-	getRng : function() {
-		var s = this.getSel();
-
-		if (s == null)
-			return null;
-
-		if (tinyMCE.isRealIE)
-			return s.createRange();
-
-		if (tinyMCE.isSafari && !s.getRangeAt)
-			return '' + window.getSelection();
-
-		if (s.rangeCount > 0)
-			return s.getRangeAt(0);
-
-		return null;
-	},
-
-	isCollapsed : function() {
-		var r = this.getRng();
-
-		if (r.item)
-			return false;
-
-		return r.boundingWidth == 0 || this.getSel().isCollapsed;
-	},
-
-	collapse : function(b) {
-		var r = this.getRng(), s = this.getSel();
-
-		if (r.select) {
-			r.collapse(b);
-			r.select();
-		} else {
-			if (b)
-				s.collapseToStart();
+
+		});
+})();
+/* file:jscripts/tiny_mce/classes/ui/NativeListBox.js */
+
+(function() {
+	var DOM = tinymce.DOM, Event = tinymce.dom.Event, each = tinymce.each, Dispatcher = tinymce.util.Dispatcher;
+
+	tinymce.create('tinymce.ui.NativeListBox:tinymce.ui.ListBox', {
+		NativeListBox : function(id, s) {
+			this.parent(id, s);
+			this.classPrefix = 'mceNativeListBox';
+		},
+
+		setDisabled : function(s) {
+			DOM.get(this.id).disabled = s;
+		},
+
+		isDisabled : function() {
+			return DOM.get(this.id).disabled;
+		},
+
+		select : function(v) {
+			var e = DOM.get(this.id), ol = e.options;
+
+			v = '' + (v || '');
+
+			e.selectedIndex = 0;
+			each(ol, function(o, i) {
+				if (o.value == v) {
+					e.selectedIndex = i;
+					return false;
+				}
+			});
+		},
+
+		add : function(n, v, a) {
+			var o, t = this;
+
+			a = a || {};
+			a.value = v;
+
+			if (t.isRendered())
+				DOM.add(DOM.get(this.id), 'option', a, n);
+
+			o = {
+				title : n,
+				value : v,
+				attribs : a
+			};
+
+			t.items.push(o);
+			t.onAdd.dispatch(t, o);
+		},
+
+		getLength : function() {
+			return DOM.get(this.id).options.length - 1;
+		},
+
+		renderHTML : function() {
+			var h, t = this;
+
+			h = DOM.createHTML('option', {value : ''}, '-- ' + t.settings.title + ' --');
+
+			each(t.items, function(it) {
+				h += DOM.createHTML('option', {value : it.value}, it.title);
+			});
+
+			h = DOM.createHTML('select', {id : t.id, 'class' : 'mceNativeListBox'}, h);
+
+			return h;
+		},
+
+		postRender : function() {
+			var t = this, ch;
+
+			t.rendered = true;
+
+			function onChange(e) {
+				var v = e.target.options[e.target.selectedIndex].value;
+
+				t.onChange.dispatch(t, v);
+
+				if (t.settings.onselect)
+					t.settings.onselect(v);
+			};
+
+			Event.add(t.id, 'change', onChange);
+
+			// Accessibility keyhandler
+			Event.add(t.id, 'keydown', function(e) {
+				var bf;
+
+				Event.remove(t.id, 'change', ch);
+
+				bf = Event.add(t.id, 'blur', function() {
+					Event.add(t.id, 'change', onChange);
+					Event.remove(t.id, 'blur', bf);
+				});
+
+				if (e.keyCode == 13 || e.keyCode == 32) {
+					onChange(e);
+					return Event.cancel(e);
+				}
+			});
+
+			t.onPostRender.dispatch(t, DOM.get(t.id));
+		}
+
+		});
+})();
+/* file:jscripts/tiny_mce/classes/ui/MenuButton.js */
+
+(function() {
+	var DOM = tinymce.DOM, Event = tinymce.dom.Event, each = tinymce.each;
+
+	tinymce.create('tinymce.ui.MenuButton:tinymce.ui.Button', {
+		MenuButton : function(id, s) {
+			this.parent(id, s);
+			this.onRenderMenu = new tinymce.util.Dispatcher(this);
+			s.menu_container = s.menu_container || document.body;
+		},
+
+		showMenu : function() {
+			var t = this, p1, p2, e = DOM.get(t.id), m;
+
+			if (t.isDisabled())
+				return;
+
+			if (!t.isMenuRendered) {
+				t.renderMenu();
+				t.isMenuRendered = true;
+			}
+
+			p1 = DOM.getPos(t.settings.menu_container);
+			p2 = DOM.getPos(e);
+
+			m = t.menu;
+			m.settings.offset_x = p2.x;
+			m.settings.offset_y = p2.y;
+			m.settings.vp_offset_x = p2.x;
+			m.settings.vp_offset_y = p2.y;
+			m.showMenu(0, e.clientHeight);
+
+			Event.add(document, 'mousedown', t.hideMenu, t);
+			t.setState('Selected', 1);
+		},
+
+		renderMenu : function() {
+			var t = this, m;
+
+			m = t.settings.control_manager.createDropMenu(t.id + '_menu', {
+				menu_line : 1,
+				'class' : this.classPrefix + 'Menu',
+				icons : t.settings.icons
+			});
+
+			m.onHideMenu.add(t.hideMenu, t);
+
+			t.onRenderMenu.dispatch(t, m);
+			t.menu = m;
+		},
+
+		hideMenu : function(e) {
+			var t = this;
+
+			if (!e || !DOM.getParent(e.target, function(n) {return DOM.hasClass(n, 'mceMenu');})) {
+				t.setState('Selected', 0);
+				Event.remove(document, 'mousedown', t.hideMenu, t);
+				if (t.menu)
+					t.menu.hideMenu();
+			}
+		},
+
+		postRender : function() {
+			var t = this, s = t.settings;
+
+			Event.add(t.id, 'click', function() {
+				if (!t.isDisabled()) {
+					if (s.onclick)
+						s.onclick(t.value);
+
+					t.showMenu();
+				}
+			});
+		}
+
+		});
+})();
+
+/* file:jscripts/tiny_mce/classes/ui/SplitButton.js */
+
+(function() {
+	var DOM = tinymce.DOM, Event = tinymce.dom.Event, each = tinymce.each;
+
+	tinymce.create('tinymce.ui.SplitButton:tinymce.ui.MenuButton', {
+		SplitButton : function(id, s) {
+			this.parent(id, s);
+			this.classPrefix = 'mceSplitButton';
+		},
+
+		renderHTML : function() {
+			var h, t = this, s = t.settings, h1;
+
+			h = '<tbody><tr>';
+
+			if (s.image)
+				h1 = DOM.createHTML('img ', {src : s.image, 'class' : 'action ' + s['class']});
 			else
-				s.collapseToEnd();
+				h1 = DOM.createHTML('span', {'class' : 'action ' + s['class']});
+
+			h += '<td>' + DOM.createHTML('a', {id : t.id + '_action', href : 'javascript:;', 'class' : 'action ' + s['class'], onclick : "return false;", onmousedown : 'return false;', title : s.title}, h1) + '</td>';
+	
+			h1 = DOM.createHTML('span', {'class' : 'open ' + s['class']});
+			h += '<td>' + DOM.createHTML('a', {id : t.id + '_open', href : 'javascript:;', 'class' : 'open ' + s['class'], onclick : "return false;", onmousedown : 'return false;', title : s.title}, h1) + '</td>';
+
+			h += '</tr></tbody>';
+
+			return DOM.createHTML('table', {id : t.id, 'class' : 'mceSplitButton mceSplitButtonEnabled ' + s['class'], cellpadding : '0', cellspacing : '0', onmousedown : 'return false;', title : s.title}, h);
+		},
+
+		postRender : function() {
+			var t = this, s = t.settings;
+
+			if (s.onclick) {
+				Event.add(t.id + '_action', 'click', function() {
+					if (!t.isDisabled())
+						s.onclick(t.value);
+				});
+			}
+
+			Event.add(t.id + '_open', 'click', t.showMenu, t);
+
+			// Old IE doesn't have hover on all elements
+			if (tinymce.isIE6 || !DOM.boxModel) {
+				Event.add(t.id, 'mouseover', function() {
+					if (!DOM.hasClass(t.id, 'mceSplitButtonDisabled'))
+						DOM.addClass(t.id, 'mceSplitButtonHover');
+				});
+
+				Event.add(t.id, 'mouseout', function() {
+					if (!DOM.hasClass(t.id, 'mceSplitButtonDisabled'))
+						DOM.removeClass(t.id, 'mceSplitButtonHover');
+				});
+			}
+		}
+
+		});
+})();
+
+/* file:jscripts/tiny_mce/classes/ui/ColorSplitButton.js */
+
+(function() {
+	var DOM = tinymce.DOM, Event = tinymce.dom.Event, is = tinymce.is, each = tinymce.each;
+
+	tinymce.create('tinymce.ui.ColorSplitButton:tinymce.ui.SplitButton', {
+		ColorSplitButton : function(id, s) {
+			var t = this;
+
+			t.parent(id, s);
+
+			t.settings = s = tinymce.extend({
+				colors : '000000,993300,333300,003300,003366,000080,333399,333333,800000,FF6600,808000,008000,008080,0000FF,666699,808080,FF0000,FF9900,99CC00,339966,33CCCC,3366FF,800080,999999,FF00FF,FFCC00,FFFF00,00FF00,00FFFF,00CCFF,993366,C0C0C0,FF99CC,FFCC99,FFFF99,CCFFCC,CCFFFF,99CCFF,CC99FF,FFFFFF',
+				grid_width : 8,
+				default_color : '#888888'
+			}, t.settings);
+
+			t.value = s.default_color;
+		},
+
+		showMenu : function() {
+			var t = this, r, p, e;
+
+			if (t.isDisabled())
+				return;
+
+			if (!t.isMenuRendered) {
+				t.renderMenu();
+				t.isMenuRendered = true;
+			}
+
+			e = DOM.get(t.id);
+			DOM.show(t.id + '_menu');
+			DOM.addClass(e, 'mceSplitButtonSelected');
+			p2 = DOM.getPos(e);
+			DOM.setStyles(t.id + '_menu', {
+				left : p2.x,
+				top : p2.y + e.clientHeight,
+				zIndex : 150
+			});
+			e = 0;
+
+			Event.add(document, 'mousedown', t.hideMenu, t);
+		},
+
+		hideMenu : function(e) {
+			var t = this;
+
+			if (!e || !DOM.getParent(e.target, function(n) {return DOM.hasClass(n, 'mceSplitButtonMenu');})) {
+				DOM.removeClass(t.id, 'mceSplitButtonSelected');
+				Event.remove(document, 'mousedown', t.hideMenu, t);
+				DOM.hide(t.id + '_menu');
+			}
+		},
+
+		renderMenu : function() {
+			var t = this, m, i = 0, s = t.settings, n, tb, tr, w;
+
+			w = DOM.add(s.menu_container, 'div', {id : t.id + '_menu', 'class' : s['menu_class'] + ' ' + s['class'], style : 'position:absolute;left:0;top:-1000px;'});
+			m = DOM.add(w, 'div', {'class' : s['class'] + ' mceSplitButtonMenu'});
+			DOM.add(m, 'span', {'class' : 'mceMenuLine'});
+
+			n = DOM.add(m, 'table', {'class' : 'mceColorSplitMenu'});
+			tb = DOM.add(n, 'tbody');
+
+			// Generate color grid
+			i = 0;
+			each(is(s.colors, 'array') ? s.colors : s.colors.split(','), function(c) {
+				c = c.replace(/^#/, '');
+
+				if (!i--) {
+					tr = DOM.add(tb, 'tr');
+					i = s.grid_width - 1;
+				}
+
+				n = DOM.add(tr, 'td');
+
+				n = DOM.add(n, 'a', {
+					href : 'javascript:;',
+					style : {
+						backgroundColor : '#' + c
+					}
+				});
+
+				Event.add(n, 'mousedown', function() {
+					t.setColor('#' + c);
+				});
+			});
+
+			if (s.more_colors_func) {
+				n = DOM.add(tb, 'tr');
+				n = DOM.add(n, 'td', {colspan : s.grid_width, 'class' : 'morecolors'});
+				n = DOM.add(n, 'a', {href : 'javascript:;', onclick : 'return false;', 'class' : 'morecolors'}, s.more_colors_title);
+
+				Event.add(n, 'click', function(e) {
+					s.more_colors_func.call(s.more_colors_scope || this);
+					return Event.cancel(e); // Cancel to fix onbeforeunload problem
+				});
+			}
+
+			DOM.addClass(m, 'mceColorSplitMenu');
+
+			return w;
+		},
+
+		setColor : function(c) {
+			var t = this, p, s = this.settings, co = s.menu_container, po, cp, id = t.id + '_preview';
+
+			if (!(p = DOM.get(id))) {
+				DOM.setStyle(t.id + '_action', 'position', 'relative');
+				p = DOM.add(t.id + '_action', 'div', {id : id, 'class' : 'mceColorPreview'});
+			}
+
+			p.style.backgroundColor = c;
+
+			t.value = c;
+			t.hideMenu();
+			s.onselect(c);
+		}
+
+		});
+})();
+
+/* file:jscripts/tiny_mce/classes/ui/Toolbar.js */
+
+tinymce.create('tinymce.ui.Toolbar:tinymce.ui.Container', {
+	renderHTML : function() {
+		var t = this, h = '', c = 'mceToolbarEnd', co, dom = tinymce.DOM, s = t.settings;
+
+		h += dom.createHTML('td', {'class' : 'mceToolbarStart'}, dom.createHTML('span', null, '<!-- IE -->'));
+
+		tinymce.each(t.controls, function(c) {
+			h += '<td>' + c.renderHTML() + '</td>';
+		});
+
+		co = t.controls[t.controls.length - 1].constructor;
+
+		if (co === tinymce.ui.Button)
+			c += ' mceToolbarEndButton';
+		else if (co === tinymce.ui.SplitButton)
+			c += ' mceToolbarEndSplitButton';
+		else if (co === tinymce.ui.ListBox)
+			c += ' mceToolbarEndListBox';
+
+		h += dom.createHTML('td', {'class' : c}, dom.createHTML('span', null, '<!-- IE -->'));
+
+		return dom.createHTML('table', {id : t.id, 'class' : 'mceToolbar' + (s['class'] ? ' ' + s['class'] : ''), cellpadding : '0', cellspacing : '0', align : t.settings.align || ''}, '<tbody><tr>' + h + '</tr></tbody>');
+	}
+
+	});
+
+/* file:jscripts/tiny_mce/classes/AddOnManager.js */
+
+(function() {
+	var Dispatcher = tinymce.util.Dispatcher, each = tinymce.each;
+
+	tinymce.create('tinymce.AddOnManager', {
+		items : [],
+		urls : {},
+		lookup : {},
+		onAdd : new Dispatcher(this),
+
+		get : function(n) {
+			return this.lookup[n];
+		},
+
+		requireLangPack : function(n) {
+			var u, s;
+
+			if (tinymce.EditorManager.settings) {
+				u = this.urls[n] + '/langs/' + tinymce.EditorManager.settings.language + '.js';
+				s = tinymce.EditorManager.settings;
+
+				if (s) {
+					if (!tinymce.dom.Event.domLoaded && !s.strict_mode)
+						tinymce.ScriptLoader.load(u);
+					else
+						tinymce.ScriptLoader.add(u);
+				}
+			}
+		},
+
+		add : function(id, o) {
+			this.items.push(o);
+			this.lookup[id] = o;
+			this.onAdd.dispatch(this, id, o);
+
+			return o;
+		},
+
+		load : function(n, u, cb, s) {
+			if (u.indexOf('/') != 0 && u.indexOf('://') == -1)
+				u = tinymce.baseURL + '/' +  u;
+
+			this.urls[n] = u.substring(0, u.lastIndexOf('/'));
+			tinymce.ScriptLoader.add(u, cb, s);
 		}
-	},
-
-	getFocusElement : function() {
-		var inst = this.instance, doc, rng, sel, elm;
-
-		if (tinyMCE.isRealIE) {
-			doc = inst.getDoc();
-			rng = doc.selection.createRange();
-
-	//		if (rng.collapse)
-	//			rng.collapse(true);
-
-			elm = rng.item ? rng.item(0) : rng.parentElement();
-		} else {
-			if (!tinyMCE.isSafari && inst.isHidden())
-				return inst.getBody();
-
-			sel = this.getSel();
-			rng = this.getRng();
-
-			if (!sel || !rng)
+
+		});
+
+	// Create plugin and theme managers
+	tinymce.PluginManager = new tinymce.AddOnManager();
+	tinymce.ThemeManager = new tinymce.AddOnManager();
+}());
+/* file:jscripts/tiny_mce/classes/EditorManager.js */
+
+(function() {
+	// Shorten names
+	var each = tinymce.each, extend = tinymce.extend, DOM = tinymce.DOM, Event = tinymce.dom.Event, ThemeManager = tinymce.ThemeManager, PluginManager = tinymce.PluginManager;
+
+	tinymce.create('static tinymce.EditorManager', {
+		editors : {},
+		i18n : {},
+		activeEditor : null,
+
+		init : function(s) {
+			var t = this, pl, sl = tinymce.ScriptLoader;
+
+			function execCallback(se, n, s) {
+				var f = se[n];
+
+				if (!f)
+					return;
+
+				if (tinymce.is(f, 'string')) {
+					s = f.replace(/\.\w+$/, '');
+					s = s ? tinymce.resolve(s) : 0;
+					f = tinymce.resolve(f);
+				}
+
+				return f.apply(s || this, Array.prototype.slice.call(arguments, 2));
+			};
+
+			s = extend({
+				theme : "simple",
+				language : "en",
+				strict_loading_mode : document.contentType == 'application/xhtml+xml'
+			}, s);
+
+			t.settings = s;
+
+			// If page not loaded and strict mode isn't enabled then load them
+			if (!Event.domLoaded && !s.strict_loading_mode) {
+				// Load language
+				if (s.language)
+					sl.add(tinymce.baseURL + '/langs/' + s.language + '.js');
+
+				// Load theme
+				if (s.theme && s.theme.charAt(0) != '-')
+					ThemeManager.load(s.theme, 'themes/' + s.theme + '/editor_template' + tinymce.suffix + '.js');
+
+				// Load plugins
+				if (s.plugins) {
+					pl = s.plugins.split(',');
+
+					// Load compat2x first
+					if (tinymce.inArray(pl, 'compat2x') != -1)
+						PluginManager.load('compat2x', 'plugins/compat2x/editor_plugin' + tinymce.suffix + '.js');
+
+					// Load rest if plugins
+					each(pl, function(v) {
+						if (v && v.charAt(0) != '-') {
+							// Skip safari plugin for other browsers
+							if (!tinymce.isWebKit && v == 'safari')
+								return;
+
+							PluginManager.load(v, 'plugins/' + v + '/editor_plugin' + tinymce.suffix + '.js');
+						}
+					});
+				}
+
+				sl.loadQueue();
+			}
+
+			// Legacy call
+			Event.add(document, 'init', function() {
+				var l, co;
+
+				execCallback(s, 'onpageload');
+
+				// Verify that it's a valid browser
+				if (s.browsers) {
+					l = false;
+
+					each(s.browsers.split(','), function(v) {
+						switch (v) {
+							case 'ie':
+							case 'msie':
+								if (tinymce.isIE)
+									l = true;
+								break;
+
+							case 'gecko':
+								if (tinymce.isGecko)
+									l = true;
+								break;
+
+							case 'safari':
+							case 'webkit':
+								if (tinymce.isWebKit)
+									l = true;
+								break;
+
+							case 'opera':
+								if (tinymce.isOpera)
+									l = true;
+
+								break;
+						}
+					});
+
+					// Not a valid one
+					if (!l)
+						return;
+				}
+
+				switch (s.mode) {
+					case "exact":
+						l = s.elements || '';
+						each(l.split(','), function(v) {
+							new tinymce.Editor(v, s).render();
+						});
+						break;
+
+					case "textareas":
+						function hasClass(n, c) {
+							return new RegExp('\\b' + c + '\\b', 'g').test(n.className);
+						};
+
+						each(DOM.select('textarea'), function(v) {
+							if (s.editor_deselector && hasClass(v, s.editor_deselector))
+								return;
+
+							if (!s.editor_selector || hasClass(v, s.editor_selector))
+								new tinymce.Editor(v.id = (v.id || v.name || (v.id = DOM.uniqueId())), s).render();
+						});
+						break;
+				}
+
+				// Call onInit when all editors are initialized
+				if (s.oninit) {
+					l = co = 0;
+
+					each (t.editors, function(ed) {
+						co++;
+
+						if (!ed.initialized) {
+							// Wait for it
+							ed.onInit.add(function() {
+								l++;
+
+								// All done
+								if (l == co)
+									execCallback(s, 'oninit');
+							});
+						} else
+							l++;
+
+						// All done
+						if (l == co)
+							execCallback(s, 'oninit');					
+					});
+				}
+			});
+		},
+
+		get : function(id) {
+			return this.editors[id];
+		},
+
+		getInstanceById : function(id) {
+			return this.get(id);
+		},
+
+		add : function(e) {
+			this.editors[e.id] = e;
+			this._setActive(e);
+
+			return e;
+		},
+
+		remove : function(e) {
+			var t = this;
+
+			// Not in the collection
+			if (!t.editors[e.id])
 				return null;
 
-			elm = rng.commonAncestorContainer;
-			//elm = (sel && sel.anchorNode) ? sel.anchorNode : null;
-
-			// Handle selection a image or other control like element such as anchors
-			if (!rng.collapsed) {
-				// Is selection small
-				if (rng.startContainer == rng.endContainer) {
-					if (rng.startOffset - rng.endOffset < 2) {
-						if (rng.startContainer.hasChildNodes())
-							elm = rng.startContainer.childNodes[rng.startOffset];
+			delete t.editors[e.id];
+
+			// Select another editor since the active one was removed
+			if (t.activeEditor == e) {
+				each(t.editors, function(e) {
+					t._setActive(e);
+					return false; // Break
+				});
+			}
+
+			e._destroy();
+
+			return e;
+		},
+
+		execCommand : function(c, u, v) {
+			var t = this, ed = t.get(v);
+
+			// Manager commands
+			switch (c) {
+				case "mceFocus":
+					ed.focus();
+					return true;
+
+				case "mceAddEditor":
+				case "mceAddControl":
+					new tinymce.Editor(v, t.settings).render();
+					return true;
+
+				case "mceAddFrameControl":
+					// TODO: Implement this
+					return true;
+
+				case "mceRemoveEditor":
+				case "mceRemoveControl":
+					ed.remove();
+					return true;
+
+				case 'mceToggleEditor':
+					if (!ed) {
+						t.execCommand('mceAddControl', 0, v);
+						return true;
 					}
-				}
-			}
-
-			// Get the element parent of the node
-			elm = tinyMCE.getParentElement(elm);
-
-			//if (tinyMCE.selectedElement != null && tinyMCE.selectedElement.nodeName.toLowerCase() == "img")
-			//	elm = tinyMCE.selectedElement;
+
+					if (ed.isHidden())
+						ed.show();
+					else
+						ed.hide();
+
+					return true;
+			}
+
+			// Run command on active editor
+			if (t.activeEditor)
+				return t.activeEditor.execCommand(c, u, v);
+
+			return false;
+		},
+
+		execInstanceCommand : function(id, c, u, v) {
+			var ed = this.get(id);
+
+			if (ed)
+				return ed.execCommand(c, u, v);
+
+			return false;
+		},
+
+		triggerSave : function() {
+			each(this.editors, function(e) {
+				e.save();
+			});
+		},
+
+		addI18n : function(p, o) {
+			var lo, i18n = this.i18n;
+
+			if (!tinymce.is(p, 'string')) {
+				each(p, function(o, lc) {
+					each(o, function(o, g) {
+						each(o, function(o, k) {
+							if (g === 'common')
+								i18n[lc + '.' + k] = o;
+							else
+								i18n[lc + '.' + g + '.' + k] = o;
+						});
+					});
+				});
+			} else {
+				each(o, function(o, k) {
+					i18n[p + '.' + k] = o;
+				});
+			}
+		},
+
+		// Private methods
+
+		_setActive : function(e) {
+			this.selectedInstance = this.activeEditor = e;
 		}
 
-		return elm;
-	}
-
-	};
-
-/* file:jscripts/tiny_mce/classes/TinyMCE_UndoRedo.class.js */
-
-function TinyMCE_UndoRedo(inst) {
-	this.instance = inst;
-	this.undoLevels = new Array();
-	this.undoIndex = 0;
-	this.typingUndoIndex = -1;
-	this.undoRedo = true;
-};
-
-TinyMCE_UndoRedo.prototype = {
-	add : function(l) {
-		var b, customUndoLevels, newHTML, inst = this.instance, i, ul, ur;
-
-		if (l) {
-			this.undoLevels[this.undoLevels.length] = l;
-			return true;
-		}
-
-		if (this.typingUndoIndex != -1) {
-			this.undoIndex = this.typingUndoIndex;
-
-			if (tinyMCE.typingUndoIndex != -1)
-				tinyMCE.undoIndex = tinyMCE.typingUndoIndex;
-		}
-
-		newHTML = tinyMCE.trim(inst.getBody().innerHTML);
-		if (this.undoLevels[this.undoIndex] && newHTML != this.undoLevels[this.undoIndex].content) {
-			//tinyMCE.debug(newHTML, this.undoLevels[this.undoIndex].content);
-
-			tinyMCE.dispatchCallback(inst, 'onchange_callback', 'onChange', inst);
-
-			// Time to compress
-			customUndoLevels = tinyMCE.settings['custom_undo_redo_levels'];
-			if (customUndoLevels != -1 && this.undoLevels.length > customUndoLevels) {
-				for (i=0; i<this.undoLevels.length-1; i++)
-					this.undoLevels[i] = this.undoLevels[i+1];
-
-				this.undoLevels.length--;
-				this.undoIndex--;
-
-				// Todo: Implement global undo/redo logic here
-			}
-
-			b = inst.undoBookmark;
-
-			if (!b)
-				b = inst.selection.getBookmark();
-
-			this.undoIndex++;
-			this.undoLevels[this.undoIndex] = {
-				content : newHTML,
-				bookmark : b
+		});
+
+	// Setup some URLs where the editor API is located and where the document is
+	tinymce.documentBaseURL = window.location.href.replace(/[\?#].*$/, '').replace(/[\/\\][^\/]+$/, '');
+	if (!/[\/\\]$/.test(tinymce.documentBaseURL))
+		tinymce.documentBaseURL += '/';
+
+	tinymce.baseURL = new tinymce.util.URI(tinymce.documentBaseURL).toAbsolute(tinymce.baseURL);
+	tinymce.EditorManager.baseURI = new tinymce.util.URI(tinymce.baseURL);
+})();
+
+// Short for editor manager window.tinyMCE is needed when TinyMCE gets loaded though a XHR call
+var tinyMCE = window.tinyMCE = tinymce.EditorManager;
+
+/* file:jscripts/tiny_mce/classes/Editor.js */
+
+(function() {
+	var DOM = tinymce.DOM, Event = tinymce.dom.Event, extend = tinymce.extend, Dispatcher = tinymce.util.Dispatcher;
+	var each = tinymce.each, isGecko = tinymce.isGecko, isIE = tinymce.isIE, isWebKit = tinymce.isWebKit;
+	var is = tinymce.is, ThemeManager = tinymce.ThemeManager, PluginManager = tinymce.PluginManager, EditorManager = tinymce.EditorManager;
+	var inArray = tinymce.inArray, grep = tinymce.grep;
+
+	tinymce.create('tinymce.Editor', {
+		Editor : function(id, s) {
+			var t = this;
+
+			t.id = t.editorId = id;
+			t.execCommands = {};
+			t.queryStateCommands = {};
+			t.queryValueCommands = {};
+			t.plugins = {};
+
+			// Add events to the editor
+			each([
+				'onPreInit',
+				'onBeforeRenderUI',
+				'onPostRender',
+				'onInit',
+				'onRemove',
+				'onActivate',
+				'onDeactivate',
+				'onClick',
+				'onEvent',
+				'onMouseUp',
+				'onMouseDown',
+				'onDblClick',
+				'onKeyDown',
+				'onKeyUp',
+				'onKeyPress',
+				'onContextMenu',
+				'onSubmit',
+				'onReset',
+				'onPaste',
+				'onPreProcess',
+				'onPostProcess',
+				'onBeforeSetContent',
+				'onBeforeGetContent',
+				'onSetContent',
+				'onGetContent',
+				'onLoadContent',
+				'onSaveContent',
+				'onNodeChange',
+				'onChange',
+				'onBeforeExecCommand',
+				'onExecCommand',
+				'onUndo',
+				'onRedo',
+				'onVisualAid',
+				'onSetProgressState'
+			], function(e) {
+				t[e] = new Dispatcher(t);
+			});
+
+			// Default editor config
+			t.settings = s = extend({
+				id : id,
+				language : 'en',
+				docs_language : 'en',
+				theme : 'simple',
+				skin : 'default',
+				delta_width : 0,
+				delta_height : 0,
+				popup_css : '',
+				plugins : '',
+				document_base_url : tinymce.documentBaseURL,
+				add_form_submit_trigger : 1,
+				submit_patch : 1,
+				add_unload_trigger : 1,
+				convert_urls : 1,
+				relative_urls : 1,
+				remove_script_host : 1,
+				table_inline_editing : 0,
+				object_resizing : 1,
+				cleanup : 1,
+				accessibility_focus : 1,
+				custom_shortcuts : 1,
+				custom_undo_redo_keyboard_shortcuts : 1,
+				custom_undo_redo_restore_selection : 1,
+				custom_undo_redo : 1,
+				doctype : '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">',
+				visual_table_class : 'mceItemTable',
+				visual : 1,
+				inline_styles : true,
+				convert_fonts_to_spans : true,
+				font_size_style_values : 'xx-small,x-small,small,medium,large,x-large,xx-large',
+				apply_source_formatting : 1,
+				directionality : 'ltr',
+				forced_root_block : 'p',
+				valid_elements : '@[id|class|style|title|dir<ltr?rtl|lang|xml::lang|onclick|ondblclick|onmousedown|onmouseup|onmouseover|onmousemove|onmouseout|onkeypress|onkeydown|onkeyup],a[rel|rev|charset|hreflang|tabindex|accesskey|type|name|href|target|title|class|onfocus|onblur],strong/b,em/i,strike,u,#p[align],-ol[type|compact],-ul[type|compact],-li,br,img[longdesc|usemap|src|border|alt=|title|hspace|vspace|width|height|align],-sub,-sup,-blockquote,-table[border=0|cellspacing|cellpadding|width|frame|rules|height|align|summary|bgcolor|background|bordercolor],-tr[rowspan|width|height|align|valign|bgcolor|background|bordercolor],tbody,thead,tfoot,#td[colspan|rowspan|width|height|align|valign|bgcolor|background|bordercolor|scope],#th[colspan|rowspan|width|height|align|valign|scope],caption,-div,-span,-pre,address,-h1,-h2,-h3,-h4,-h5,-h6,hr[size|noshade],-font[face|size|color],dd,dl,dt,cite,abbr,acronym,del[datetime|cite],ins[datetime|cite],object[classid|width|height|codebase|*],param[name|value|_value],embed[type|width|height|src|*],script[type],map[name],area[shape|coords|href|alt|target]',
+				hidden_input : 1,
+				padd_empty_editor : 1,
+				render_ui : 1,
+				init_theme : 1,
+				indentation : '30px'
+			}, s);
+
+			// Setup URIs
+			t.documentBaseURI = new tinymce.util.URI(s.document_base_url || tinymce.documentBaseURL, {
+				base_uri : tinyMCE.baseURI
+			});
+			t.baseURI = EditorManager.baseURI;
+
+			// Call setup
+			t.execCallback('setup', t);
+		},
+
+		render : function() {
+			var t = this, s = t.settings, id = t.id, sl = tinymce.ScriptLoader;
+
+			// Element not found, then skip initialization
+			if (!t.getElement())
+				return;
+
+			if (s.strict_loading_mode) {
+				sl.settings.strict_mode = s.strict_loading_mode;
+				tinymce.DOM.settings.strict = 1;
+			}
+
+			// Add hidden input for non input elements inside form elements
+			if (!/TEXTAREA|INPUT/i.test(t.getElement().nodeName) && s.hidden_input && DOM.getParent(id, 'form'))
+				DOM.insertAfter(DOM.create('input', {type : 'hidden', name : id}), id);
+
+			t.windowManager = new tinymce.WindowManager(t);
+
+			if (s.encoding == 'xml') {
+				t.onGetContent.add(function(ed, o) {
+					if (o.get)
+						o.content = DOM.encode(o.content);
+				});
+			}
+
+			if (s.add_form_submit_trigger) {
+				t.onSubmit.addToTop(function() {
+					if (t.initialized) {
+						t.save();
+						t.isNotDirty = 1;
+					}
+				});
+			}
+
+			Event.add(document, 'unload', function() {
+				if (t.initialized && !t.destroyed && s.add_unload_trigger)
+					t.save({format : 'raw', no_events : true});
+			});
+
+			tinymce.addUnload(t._destroy, t);
+
+			if (s.submit_patch) {
+				t.onBeforeRenderUI.add(function() {
+					var n = t.getElement().form;
+
+					if (!n)
+						return;
+
+					// Already patched
+					if (n._mceOldSubmit)
+						return;
+
+					// Check page uses id="submit" or name="submit" for it's submit button
+					if (!n.submit.nodeType) {
+						t.formElement = n;
+						n._mceOldSubmit = n.submit;
+						n.submit = function() {
+							// Save all instances
+							EditorManager.triggerSave();
+							t.isNotDirty = 1;
+
+							return this._mceOldSubmit(this);
+						};
+					}
+
+					n = null;
+				});
+			}
+
+			// Load scripts
+			function loadScripts() {
+				sl.add(tinymce.baseURL + '/langs/' + s.language + '.js');
+
+				if (s.theme.charAt(0) != '-')
+					ThemeManager.load(s.theme, 'themes/' + s.theme + '/editor_template' + tinymce.suffix + '.js');
+
+				each(s.plugins.split(','), function(p) {
+					if (p && p.charAt(0) != '-') {
+						// Skip safari plugin for other browsers
+						if (!isWebKit && p == 'safari')
+							return;
+
+						PluginManager.load(p, 'plugins/' + p + '/editor_plugin' + tinymce.suffix + '.js');
+					}
+				});
+
+				// Init when que is loaded
+				sl.loadQueue(function() {
+					if (s.ask) {
+						function ask() {
+							t.windowManager.confirm(t.getLang('edit_confirm'), function(s) {
+								if (s)
+									t.init();
+								else
+									Event.remove(t.id, 'focus', ask);
+							});
+						};
+
+						Event.add(t.id, 'focus', ask);
+						return;
+					}
+
+					if (!t.removed)
+						t.init();
+				});
 			};
 
-			// Remove all above from global undo/redo
-			ul = tinyMCE.undoLevels;
-			for (i=tinyMCE.undoIndex + 1; i<ul.length; i++) {
-				ur = ul[i].undoRedo;
-
-				if (ur.undoIndex == ur.undoLevels.length -1)
-					ur.undoIndex--;
-
-				ur.undoLevels.length--;
-			}
-
-			// Add global undo level
-			tinyMCE.undoLevels[tinyMCE.undoIndex++] = inst;
-			tinyMCE.undoLevels.length = tinyMCE.undoIndex;
-
-			this.undoLevels.length = this.undoIndex + 1;
+			// Load compat2x first
+			if (s.plugins.indexOf('compat2x') != -1) {
+				PluginManager.load('compat2x', 'plugins/compat2x/editor_plugin' + tinymce.suffix + '.js');
+				sl.loadQueue(loadScripts);
+			} else
+				loadScripts();
+		},
+
+		init : function() {
+			var n, t = this, s = t.settings, w, h, e = t.getElement(), o, ti;
+
+			EditorManager.add(t);
+
+			// Create theme
+			s.theme = s.theme.replace(/-/, '');
+			o = ThemeManager.get(s.theme);
+			t.theme = new o();
+
+			if (t.theme.init && s.init_theme)
+				t.theme.init(t, ThemeManager.urls[s.theme] || tinymce.documentBaseURL.replace(/\/$/, ''));
+
+			// Create all plugins
+			each(s.plugins.replace(/\-/g, '').split(','), function(p) {
+				var c = PluginManager.get(p), u = PluginManager.urls[p] || tinymce.documentBaseURL.replace(/\/$/, ''), po;
+
+				if (c) {
+					po = new c(t, u);
+
+					t.plugins[p] = po;
+
+					if (po.init)
+						po.init(t, u);
+				}
+			});
+
+			// Setup popup CSS path(s)
+			s.popup_css = t.baseURI.toAbsolute(s.popup_css || "themes/" + s.theme + "/skins/" + s.skin + "/dialog.css");
+
+			if (s.popup_css_add)
+				s.popup_css += ',' + s.popup_css_add;
+
+			// Setup control factory
+			t.controlManager = new tinymce.ControlManager(t);
+			t.undoManager = new tinymce.UndoManager(t);
+
+			// Pass through
+			t.undoManager.onAdd.add(function(um, l) {
+				return t.onChange.dispatch(t, l, um);
+			});
+
+			t.undoManager.onUndo.add(function(um, l) {
+				return t.onUndo.dispatch(t, l, um);
+			});
+
+			t.undoManager.onRedo.add(function(um, l) {
+				return t.onRedo.dispatch(t, l, um);
+			});
+
+			if (s.custom_undo_redo) {
+				t.onExecCommand.add(function(ed, cmd) {
+					if (cmd != 'Undo' && cmd != 'Redo' && cmd != 'mceRepaint')
+						t.undoManager.add();
+				});
+			}
+
+			t.onExecCommand.add(function(ed, c) {
+				// Don't refresh the select lists until caret move
+				if (!/^(FontName|FontSize)$/.test(c))
+					t.nodeChanged();
+			});
+
+			// Remove ghost selections on images and tables in Gecko
+			if (isGecko) {
+				function repaint() {
+					t.execCommand('mceRepaint');
+				};
+
+				t.onUndo.add(repaint);
+				t.onRedo.add(repaint);
+				t.onSetContent.add(repaint);
+			}
+
+			// Enables users to override the control factory
+			t.onBeforeRenderUI.dispatch(t, t.controlManager);
+
+			// Measure box
+			if (s.render_ui) {
+				w = s.width || e.style.width || e.clientWidth;
+				h = s.height || e.style.height || e.clientHeight;
+				t.orgDisplay = e.style.display;
+
+				if (('' + w).indexOf('%') == -1)
+					w = Math.max(parseInt(w) + (o.deltaWidth || 0), 100);
+
+				if (('' + h).indexOf('%') == -1)
+					h = Math.max(parseInt(h) + (o.deltaHeight || 0), 100);
+
+				// Render UI
+				o = t.theme.renderUI({
+					targetNode : e,
+					width : w,
+					height : h,
+					deltaWidth : s.delta_width,
+					deltaHeight : s.delta_height
+				});
+
+				t.editorContainer = o.editorContainer;
+			}
+
+			
+			// Resize editor
+			DOM.setStyles(o.sizeContainer || o.editorContainer, {
+				width : w,
+				height : h
+			});
+
+			h = (o.iframeHeight || h) + ((h + '').indexOf('%') == -1 ? (o.deltaHeight || 0) : '');
+			if (h < 100)
+				h = 100;
+
+			// Create iframe
+			n = DOM.add(o.iframeContainer, 'iframe', {
+				id : s.id + "_ifr",
+				src : 'javascript:""', // Workaround for HTTPS warning in IE6/7
+				frameBorder : '0',
+				style : {
+					width : '100%',
+					height : h
+				}
+			});
+
+			t.contentAreaContainer = o.iframeContainer;
+			DOM.get(o.editorContainer).style.display = t.orgDisplay;
+			DOM.get(s.id).style.display = 'none';
+
+			// Safari 2.x requires us to wait for the load event and load a real HTML doc
+			if (tinymce.isOldWebKit) {
+				Event.add(n, 'load', t.setupIframe, t);
+				n.src = tinymce.baseURL + '/plugins/safari/blank.htm';
+			} else {
+				t.setupIframe();
+				e = n = o = null; // Cleanup
+			}
+		},
+
+		setupIframe : function() {
+			var t = this, s = t.settings, e = DOM.get(s.id), d = t.getDoc();
+
+			// Setup body
+			d.open();
+			d.write(s.doctype + '<html><head xmlns="http://www.w3.org/1999/xhtml"><base href="' + t.documentBaseURI.getURI() + '" /><meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /></head><body id="tinymce" class="mceContentBody"></body></html>');
+			d.close();
+
+			// Design mode needs to be added here Ctrl+A will fail otherwise
+			if (!isIE) {
+				try {
+					d.designMode = 'On';
+				} catch (ex) {
+					// Will fail on Gecko if the editor is placed in an hidden container element
+					// The design mode will be set ones the editor is focused
+				}
+			}
+
+			// IE needs to use contentEditable or it will display non secure items for HTTPS
+			if (isIE)
+				t.getBody().contentEditable = true;
+
+			// Setup objects
+			t.dom = new tinymce.DOM.DOMUtils(t.getDoc(), {
+				keep_values : true,
+				url_converter : t.convertURL,
+				url_converter_scope : t,
+				hex_colors : s.force_hex_style_colors,
+				class_filter : s.class_filter,
+				update_styles : 1
+			});
+
+			t.serializer = new tinymce.dom.Serializer({
+				entity_encoding : s.entity_encoding,
+				entities : s.entities,
+				valid_elements : s.verify_html === false ? '*[*]' : s.valid_elements,
+				extended_valid_elements : s.extended_valid_elements,
+				valid_child_elements : s.valid_child_elements,
+				invalid_elements : s.invalid_elements,
+				fix_table_elements : s.fix_table_elements,
+				fix_list_elements : s.fix_list_elements,
+				fix_content_duplication : s.fix_content_duplication,
+				convert_fonts_to_spans : s.convert_fonts_to_spans,
+				font_size_classes  : s.font_size_classes,
+				font_size_style_values : s.font_size_style_values,
+				apply_source_formatting : s.apply_source_formatting,
+				remove_linebreaks : s.remove_linebreaks,
+				dom : t.dom
+			});
+
+			t.selection = new tinymce.dom.Selection(t.dom, t.getWin(), t.serializer);
+			t.forceBlocks = new tinymce.ForceBlocks(t, {
+				forced_root_block : s.forced_root_block
+			});
+			t.editorCommands = new tinymce.EditorCommands(t);
+
+			// Pass through
+			t.serializer.onPreProcess.add(function(se, o) {
+				return t.onPreProcess.dispatch(t, o, se);
+			});
+
+			t.serializer.onPostProcess.add(function(se, o) {
+				return t.onPostProcess.dispatch(t, o, se);
+			});
+
+			t.onPreInit.dispatch(t);
+
+			if (!s.gecko_spellcheck)
+				t.getBody().spellcheck = 0;
+
+			t._addEvents();
+
+			t.controlManager.onPostRender.dispatch(t, t.controlManager);
+			t.onPostRender.dispatch(t);
+
+			if (s.directionality)
+				t.getBody().dir = s.directionality;
+
+			if (s.nowrap)
+				t.getBody().style.whiteSpace = "nowrap";
+
+			if (s.auto_resize)
+				t.onNodeChange.add(t.resizeToContent, t);
+
+			if (s.handle_node_change_callback) {
+				t.onNodeChange.add(function(ed, cm, n) {
+					t.execCallback('handle_node_change_callback', t.id, n, -1, -1, true, t.selection.isCollapsed());
+				});
+			}
+
+			if (s.save_callback) {
+				t.onSaveContent.add(function(ed, o) {
+					var h = t.execCallback('save_callback', t.id, o.content, t.getBody());
+
+					if (h)
+						o.content = h;
+				});
+			}
+
+			if (s.onchange_callback) {
+				t.onChange.add(function(ed, l) {
+					t.execCallback('onchange_callback', t, l);
+				});
+			}
+
+			if (s.convert_newlines_to_brs) {
+				t.onBeforeSetContent.add(function(ed, o) {
+					if (o.initial)
+						o.content = o.content.replace(/\r?\n/g, '<br />');
+				});
+			}
+
+			if (s.fix_nesting && isIE) {
+				t.onBeforeSetContent.add(function(ed, o) {
+					o.content = t._fixNesting(o.content);
+				});
+			}
+
+			if (s.preformatted) {
+				t.onPostProcess.add(function(ed, o) {
+					o.content = o.content.replace(/^\s*<pre.*?>/, '');
+					o.content = o.content.replace(/<\/pre>\s*$/, '');
+
+					if (o.set)
+						o.content = '<pre class="mceItemHidden">' + o.content + '</pre>';
+				});
+			}
+
+			if (s.verify_css_classes) {
+				t.serializer.attribValueFilter = function(n, v) {
+					var s, cl;
+
+					if (n == 'class') {
+						// Build regexp for classes
+						if (!t.classesRE) {
+							cl = t.dom.getClasses();
+
+							if (cl.length > 0) {
+								s = '';
+
+								each (cl, function(o) {
+									s += (s ? '|' : '') + o['class'];
+								});
+
+								t.classesRE = new RegExp('(' + s + ')', 'gi');
+							}
+						}
+
+						return !t.classesRE || /(\bmceItem\w+\b|\bmceTemp\w+\b)/g.test(v) || t.classesRE.test(v) ? v : '';
+					}
+
+					return v;
+				};
+			}
+
+			if (s.convert_fonts_to_spans)
+				t._convertFonts();
+
+			if (s.inline_styles)
+				t._convertInlineElements();
+
+			if (s.cleanup_callback) {
+				t.onBeforeSetContent.add(function(ed, o) {
+					o.content = t.execCallback('cleanup_callback', 'insert_to_editor', o.content, o);
+				});
+
+				t.onPreProcess.add(function(ed, o) {
+					if (o.set)
+						t.execCallback('cleanup_callback', 'insert_to_editor_dom', o.node, o);
+
+					if (o.get)
+						t.execCallback('cleanup_callback', 'get_from_editor_dom', o.node, o);
+				});
+
+				t.onPostProcess.add(function(ed, o) {
+					if (o.set)
+						o.content = t.execCallback('cleanup_callback', 'insert_to_editor', o.content, o);
+
+					if (o.get)						
+						o.content = t.execCallback('cleanup_callback', 'get_from_editor', o.content, o);
+				});
+			}
+
+			if (s.save_callback) {
+				t.onGetContent.add(function(ed, o) {
+					if (o.save)
+						o.content = t.execCallback('save_callback', t.id, o.content, t.getBody());
+				});
+			}
+
+			if (s.handle_event_callback) {
+				t.onEvent.add(function(ed, e, o) {
+					if (t.execCallback('handle_event_callback', e, ed, o) === false)
+						Event.cancel(e);
+				});
+			}
+
+			t.onSetContent.add(function() {
+				// Safari needs some time, it will crash the browser when a link is created otherwise
+				// I think this crash issue is resolved in the latest 3.0.4
+				//window.setTimeout(function() {
+					t.addVisual(t.getBody());
+				//}, 1);
+			});
+
+			// Remove empty contents
+			if (s.padd_empty_editor) {
+				t.onPostProcess.add(function(ed, o) {
+					o.content = o.content.replace(/^<p>(&nbsp;|#160;|\s)<\/p>$/, '');
+				});
+			}
+
+			if (isGecko) {
+				try {
+					// Design mode must be set here once again to fix a bug where
+					// Ctrl+A/Delete/Backspace didn't work if the editor was added using mceAddControl then removed then added again
+					d.designMode = 'Off';
+					d.designMode = 'On';
+				} catch (ex) {
+					// Will fail on Gecko if the editor is placed in an hidden container element
+					// The design mode will be set ones the editor is focused
+				}
+			}
+
+			// A small timeout was needed since firefox will remove. Bug: #1838304
+			setTimeout(function () {
+				if (t.removed)
+					return;
+
+				t.load({initial : true, format : (s.cleanup_on_startup ? 'html' : 'raw')});
+				t.startContent = t.getContent({format : 'raw'});
+				t.undoManager.add({initial : true});
+				t.initialized = true;
+
+				t.onInit.dispatch(t);
+				t.execCallback('setupcontent_callback', t.id, t.getBody(), t.getDoc());
+				t.execCallback('init_instance_callback', t);
+				t.focus(true);
+				t.nodeChanged({initial : 1});
+
+				// Load specified content CSS last
+				if (s.content_css) {
+					tinymce.each(s.content_css.split(','), function(u) {
+						t.dom.loadCSS(t.documentBaseURI.toAbsolute(u));
+					});
+				}
+
+				// Handle auto focus
+				if (s.auto_focus) {
+					setTimeout(function () {
+						var ed = EditorManager.get(s.auto_focus);
+
+						ed.selection.select(ed.getBody(), 1);
+						ed.selection.collapse(1);
+						ed.getWin().focus();
+					}, 100);
+				}
+			}, 1);
+	
+			e = null;
+		},
+
+		
+		focus : function(sf) {
+			var oed, t = this;
+
+			if (!sf) {
+				t.getWin().focus();
+
+							}
+
+			if (EditorManager.activeEditor != t) {
+				if ((oed = EditorManager.activeEditor) != null)
+					oed.onDeactivate.dispatch(oed, t);
+
+				t.onActivate.dispatch(t, oed);
+			}
+
+			EditorManager._setActive(t);
+		},
+
+		execCallback : function(n) {
+			var t = this, f = t.settings[n], s;
+
+			if (!f)
+				return;
+
+			// Look through lookup
+			if (t.callbackLookup && (s = t.callbackLookup[n])) {
+				f = s.func;
+				s = s.scope;
+			}
+
+			if (is(f, 'string')) {
+				s = f.replace(/\.\w+$/, '');
+				s = s ? tinymce.resolve(s) : 0;
+				f = tinymce.resolve(f);
+				t.callbackLookup = t.callbackLookup || {};
+				t.callbackLookup[n] = {func : f, scope : s};
+			}
+
+			return f.apply(s || t, Array.prototype.slice.call(arguments, 1));
+		},
+
+		translate : function(s) {
+			var c = this.settings.language, i18n = EditorManager.i18n;
+
+			if (!s)
+				return '';
+
+			return i18n[c + '.' + s] || s.replace(/{\#([^}]+)\}/g, function(a, b) {
+				return i18n[c + '.' + b] || '{#' + b + '}';
+			});
+		},
+
+		getLang : function(n, dv) {
+			return EditorManager.i18n[this.settings.language + '.' + n] || (is(dv) ? dv : '{#' + n + '}');
+		},
+
+		getParam : function(n, dv) {
+			return is(this.settings[n]) ? this.settings[n] : dv;
+		},
+
+		nodeChanged : function(o) {
+			var t = this, s = t.selection, n = s.getNode() || this.getBody();
+
+			this.onNodeChange.dispatch(
+				t,
+				o ? o.controlManager || t.controlManager : t.controlManager,
+				isIE && n.ownerDocument != t.getDoc() ? this.getBody() : n, // Fix for IE initial state
+				s.isCollapsed(),
+				o
+			);
+		},
+
+		addButton : function(n, s) {
+			var t = this;
+
+			t.buttons = t.buttons || {};
+			t.buttons[n] = s;
+		},
+
+		addCommand : function(n, f, s) {
+			this.execCommands[n] = {func : f, scope : s || this};
+		},
+
+		addQueryStateHandler : function(n, f, s) {
+			this.queryStateCommands[n] = {func : f, scope : s || this};
+		},
+
+		addQueryValueHandler : function(n, f, s) {
+			this.queryValueCommands[n] = {func : f, scope : s || this};
+		},
+
+		addShortcut : function(pa, desc, cmd_func, sc) {
+			var t = this, c;
+
+			if (!t.settings.custom_shortcuts)
+				return false;
+
+			t.shortcuts = t.shortcuts || {};
+
+			if (is(cmd_func, 'string')) {
+				c = cmd_func;
+
+				cmd_func = function() {
+					t.execCommand(c, false, null);
+				};
+			}
+
+			if (is(cmd_func, 'object')) {
+				c = cmd_func;
+
+				cmd_func = function() {
+					t.execCommand(c[0], c[1], c[2]);
+				};
+			}
+
+			each(pa.split(','), function(pa) {
+				var o = {
+					func : cmd_func,
+					scope : sc || this,
+					desc : desc,
+					alt : false,
+					ctrl : false,
+					shift : false
+				};
+
+				each(pa.split('+'), function(v) {
+					switch (v) {
+						case 'alt':
+						case 'ctrl':
+						case 'shift':
+							o[v] = true;
+							break;
+
+						default:
+							o.charCode = v.charCodeAt(0);
+							o.keyCode = v.toUpperCase().charCodeAt(0);
+					}
+				});
+
+				t.shortcuts[(o.ctrl ? 'ctrl' : '') + ',' + (o.alt ? 'alt' : '') + ',' + (o.shift ? 'shift' : '') + ',' + o.keyCode] = o;
+			});
 
 			return true;
+		},
+
+		execCommand : function(cmd, ui, val, a) {
+			var t = this, s = 0, o;
+
+			if (!/^(mceAddUndoLevel|mceEndUndoLevel|mceBeginUndoLevel|mceRepaint|SelectAll)$/.test(cmd) && (!a || !a.skip_focus))
+				t.focus();
+
+			o = {};
+			t.onBeforeExecCommand.dispatch(t, cmd, ui, val, o);
+			if (o.terminate)
+				return false;
+
+			// Comamnd callback
+			if (t.execCallback('execcommand_callback', t.id, t.selection.getNode(), cmd, ui, val)) {
+				t.onExecCommand.dispatch(t, cmd, ui, val);
+				return true;
+			}
+
+			// Registred commands
+			if (o = t.execCommands[cmd]) {
+				s = o.func.call(o.scope, ui, val);
+				t.onExecCommand.dispatch(t, cmd, ui, val);
+				return s;
+			}
+
+			// Plugin commands
+			each(t.plugins, function(p) {
+				if (p.execCommand && p.execCommand(cmd, ui, val)) {
+					t.onExecCommand.dispatch(t, cmd, ui, val);
+					s = 1;
+					return false;
+				}
+			});
+
+			if (s)
+				return true;
+
+			// Theme commands
+			if (t.theme.execCommand && t.theme.execCommand(cmd, ui, val)) {
+				t.onExecCommand.dispatch(t, cmd, ui, val);
+				return true;
+			}
+
+			// Editor commands
+			if (t.editorCommands.execCommand(cmd, ui, val)) {
+				t.onExecCommand.dispatch(t, cmd, ui, val);
+				return true;
+			}
+
+			// Browser commands
+			t.getDoc().execCommand(cmd, ui, val);
+			t.onExecCommand.dispatch(t, cmd, ui, val);
+		},
+
+		queryCommandState : function(c) {
+			var t = this, o;
+
+			// Is hidden then return undefined
+			if (t._isHidden())
+				return;
+
+			// Registred commands
+			if (o = t.queryStateCommands[c])
+				return o.func.call(o.scope);
+
+			// Registred commands
+			o = t.editorCommands.queryCommandState(c);
+			if (o !== -1)
+				return o;
+
+			// Browser commands
+			return this.getDoc().queryCommandState(c);
+		},
+
+		queryCommandValue : function(c) {
+			var t = this, o;
+
+			// Is hidden then return undefined
+			if (t._isHidden())
+				return;
+
+			// Registred commands
+			if (o = t.queryValueCommands[c])
+				return o.func.call(o.scope);
+
+			// Registred commands
+			o = t.editorCommands.queryCommandValue(c);
+			if (is(o))
+				return o;
+
+			// Browser commands
+			return this.getDoc().queryCommandValue(c);
+		},
+
+		show : function() {
+			var t = this;
+
+			DOM.show(t.getContainer());
+			DOM.hide(t.id);
+			t.load();
+		},
+
+		hide : function() {
+			var t = this, s = t.settings, d = t.getDoc();
+
+			// Fixed bug where IE has a blinking cursor left from the editor
+			if (isIE && d)
+				d.execCommand('SelectAll');
+
+			DOM.hide(t.getContainer());
+			DOM.setStyle(s.id, 'display', t.orgDisplay);
+			t.save();
+		},
+
+		isHidden : function() {
+			return !DOM.isHidden(this.id);
+		},
+
+		setProgressState : function(b, ti, o) {
+			this.onSetProgressState.dispatch(this, b, ti, o);
+
+			return b;
+		},
+
+		remove : function() {
+			var t = this;
+
+			t.removed = 1; // Cancels post remove event execution
+			t.hide();
+			DOM.remove(t.getContainer());
+
+			t.execCallback('remove_instance_callback', t);
+			t.onRemove.dispatch(t);
+
+			EditorManager.remove(t);
+		},
+
+		resizeToContent : function() {
+			var t = this;
+
+			DOM.setStyle(t.id + "_ifr", 'height', t.getBody().scrollHeight);
+		},
+
+		load : function(o) {
+			var t = this, e = t.getElement(), h;
+
+			o = o || {};
+			o.load = true;
+
+			h = t.setContent(is(e.value) ? e.value : e.innerHTML, o);
+			o.element = e;
+
+			if (!o.no_events)
+				t.onLoadContent.dispatch(t, o);
+
+			o.element = e = null;
+
+			return h;
+		},
+
+		save : function(o) {
+			var t = this, e = t.getElement(), h, f;
+
+			if (!t.initialized)
+				return;
+
+			o = o || {};
+			o.save = true;
+
+			o.element = e;
+			h = o.content = t.getContent(o);
+
+			if (!o.no_events)
+				t.onSaveContent.dispatch(t, o);
+
+			h = o.content;
+
+			if (!/TEXTAREA|INPUT/i.test(e.nodeName)) {
+				e.innerHTML = h;
+
+				// Update hidden form element
+				if (f = DOM.getParent(t.id, 'form')) {
+					each(f.elements, function(e) {
+						if (e.name == t.id) {
+							e.value = h;
+							return false;
+						}
+					});
+				}
+			} else
+				e.value = h;
+
+			o.element = e = null;
+
+			return h;
+		},
+
+		setContent : function(h, o) {
+			var t = this;
+
+			o = o || {};
+			o.format = o.format || 'html';
+			o.set = true;
+			o.content = h;
+
+			if (!o.no_events)
+				t.onBeforeSetContent.dispatch(t, o);
+
+			// Padd empty content in Gecko and Safari. Commands will otherwise fail on the content
+			// It will also be impossible to place the caret in the editor unless there is a BR element present
+			if (!tinymce.isIE && (h.length === 0 || /^\s+$/.test(h))) {
+				o.content = t.dom.setHTML(t.getBody(), '<br mce_bogus="1" />', 1);
+				o.format = 'raw';
+			}
+
+			o.content = t.dom.setHTML(t.getBody(), tinymce.trim(o.content));
+
+			if (o.format != 'raw' && t.settings.cleanup) {
+				o.getInner = true;
+				o.content = t.dom.setHTML(t.getBody(), t.serializer.serialize(t.getBody(), o));
+			}
+
+			if (!o.no_events)
+				t.onSetContent.dispatch(t, o);
+
+			return o.content;
+		},
+
+		getContent : function(o) {
+			var t = this, h;
+
+			o = o || {};
+			o.format = o.format || 'html';
+			o.get = true;
+
+			if (!o.no_events)
+				t.onBeforeGetContent.dispatch(t, o);
+
+			if (o.format != 'raw' && t.settings.cleanup) {
+				o.getInner = true;
+				h = t.serializer.serialize(t.getBody(), o);
+			} else
+				h = t.getBody().innerHTML;
+
+			h = h.replace(/^\s*|\s*$/g, '');
+			o = {content : h};
+			t.onGetContent.dispatch(t, o);
+
+			return o.content;
+		},
+
+		isDirty : function() {
+			var t = this;
+
+			return tinymce.trim(t.startContent) != tinymce.trim(t.getContent({format : 'raw', no_events : 1})) && !t.isNotDirty;
+		},
+
+		getContainer : function() {
+			var t = this;
+
+			if (!t.container)
+				t.container = DOM.get(t.editorContainer || t.id + '_parent');
+
+			return t.container;
+		},
+
+		getContentAreaContainer : function() {
+			return this.contentAreaContainer;
+		},
+
+		getElement : function() {
+			return DOM.get(this.settings.content_element || this.id);
+		},
+
+		getWin : function() {
+			var t = this, e;
+
+			if (!t.contentWindow) {
+				e = DOM.get(t.id + "_ifr");
+
+				if (e)
+					t.contentWindow = e.contentWindow;
+			}
+
+			return t.contentWindow;
+		},
+
+		getDoc : function() {
+			var t = this, w;
+
+			if (!t.contentDocument) {
+				w = this.getWin();
+
+				if (w)
+					t.contentDocument = w.document;
+			}
+
+			return t.contentDocument;
+		},
+
+		getBody : function() {
+			return this.bodyElement || this.getDoc().body;
+		},
+
+		convertURL : function(u, n, e) {
+			var t = this, s = t.settings;
+
+			// Use callback instead
+			if (s.urlconverter_callback)
+				return t.execCallback('urlconverter_callback', u, e, true, n);
+
+			// Don't convert link href since thats the CSS files that gets loaded into the editor
+			if (!s.convert_urls || (e && e.nodeName == 'LINK'))
+				return u;
+
+			// Convert to relative
+			if (s.relative_urls)
+				return t.documentBaseURI.toRelative(u);
+
+			// Convert to absolute
+			u = t.documentBaseURI.toAbsolute(u, s.remove_script_host);
+
+			return u;
+		},
+
+		addVisual : function(e) {
+			var t = this, s = t.settings;
+
+			e = e || t.getBody();
+
+			if (!is(t.hasVisual))
+				t.hasVisual = s.visual;
+
+			each(t.dom.select('table,a', e), function(e) {
+				var v;
+
+				switch (e.nodeName) {
+					case 'TABLE':
+						v = t.dom.getAttrib(e, 'border');
+
+						if (!v || v == '0') {
+							if (t.hasVisual)
+								t.dom.addClass(e, s.visual_table_class);
+							else
+								t.dom.removeClass(e, s.visual_table_class);
+						}
+
+						return;
+
+					case 'A':
+						v = t.dom.getAttrib(e, 'name');
+
+						if (v) {
+							if (t.hasVisual)
+								t.dom.addClass(e, 'mceItemAnchor');
+							else
+								t.dom.removeClass(e, 'mceItemAnchor');
+						}
+
+						return;
+				}
+			});
+
+			t.onVisualAid.dispatch(t, e, t.hasVisual);
+		},
+
+		// Internal functions
+
+		_addEvents : function() {
+			// 'focus', 'blur', 'dblclick', 'beforedeactivate', submit, reset
+			var t = this, i, s = t.settings, lo = {
+				mouseup : 'onMouseUp',
+				mousedown : 'onMouseDown',
+				click : 'onClick',
+				keyup : 'onKeyUp',
+				keydown : 'onKeyDown',
+				keypress : 'onKeyPress',
+				submit : 'onSubmit',
+				reset : 'onReset',
+				contextmenu : 'onContextMenu',
+				dblclick : 'onDblClick',
+				paste : 'onPaste' // Doesn't work in all browsers yet
+			};
+
+			function eventHandler(e, o) {
+				var ty = e.type;
+
+				// Don't fire events when it's removed
+				if (t.removed)
+					return;
+
+				// Generic event handler
+				if (t.onEvent.dispatch(t, e, o) !== false) {
+					// Specific event handler
+					t[lo[e.fakeType || e.type]].dispatch(t, e, o);
+				}
+			};
+
+			// Add DOM events
+			each(lo, function(v, k) {
+				switch (k) {
+					case 'contextmenu':
+						if (tinymce.isOpera) {
+							// Fake contextmenu on Opera
+							Event.add(t.getDoc(), 'mousedown', function(e) {
+								if (e.ctrlKey) {
+									e.fakeType = 'contextmenu';
+									eventHandler(e);
+								}
+							});
+						} else
+							Event.add(t.getDoc(), k, eventHandler);
+						break;
+
+					case 'paste':
+						Event.add(t.getBody(), k, function(e) {
+							var tx, h, el, r;
+
+							// Get plain text data
+							if (e.clipboardData)
+								tx = e.clipboardData.getData('text/plain');
+							else if (tinymce.isIE)
+								tx = t.getWin().clipboardData.getData('Text');
+
+							// Get HTML data
+							/*if (tinymce.isIE) {
+								el = DOM.add(document.body, 'div', {style : 'visibility:hidden;overflow:hidden;position:absolute;width:1px;height:1px'});
+								r = document.body.createTextRange();
+								r.moveToElementText(el);
+								r.execCommand('Paste');
+								h = el.innerHTML;
+								DOM.remove(el);
+							}*/
+
+							eventHandler(e, {text : tx, html : h});
+						});
+						break;
+
+					case 'submit':
+					case 'reset':
+						Event.add(t.getElement().form || DOM.getParent(t.id, 'form'), k, eventHandler);
+						break;
+
+					default:
+						Event.add(s.content_editable ? t.getBody() : t.getDoc(), k, eventHandler);
+				}
+			});
+
+			Event.add(s.content_editable ? t.getBody() : (isGecko ? t.getDoc() : t.getWin()), 'focus', function(e) {
+				t.focus(true);
+			});
+
+			// Fixes bug where a specified document_base_uri could result in broken images
+			// This will also fix drag drop of images in Gecko
+			if (tinymce.isGecko) {
+				// Convert all images to absolute URLs
+/*				t.onSetContent.add(function(ed, o) {
+					each(ed.dom.select('img'), function(e) {
+						var v;
+
+						if (v = e.getAttribute('mce_src'))
+							e.src = t.documentBaseURI.toAbsolute(v);
+					})
+				});*/
+
+				Event.add(t.getDoc(), 'DOMNodeInserted', function(e) {
+					var v;
+
+					e = e.target;
+
+					if (e.nodeType === 1 && e.nodeName === 'IMG' && (v = e.getAttribute('mce_src')))
+						e.src = t.documentBaseURI.toAbsolute(v);
+				});
+			}
+
+			// Set various midas options in Gecko
+			if (isGecko) {
+				function setOpts() {
+					var t = this, d = t.getDoc(), s = t.settings;
+
+					if (isGecko) {
+						if (t._isHidden()) {
+							try {
+								d.designMode = 'On';
+							} catch (ex) {
+								// Fails if it's hidden
+							}
+						}
+
+						try {
+							// Try new Gecko method
+							d.execCommand("styleWithCSS", 0, false);
+						} catch (ex) {
+							// Use old method
+							if (!t._isHidden())
+								d.execCommand("useCSS", 0, true);
+						}
+
+						if (!s.table_inline_editing)
+							try {d.execCommand('enableInlineTableEditing', false, false);} catch (ex) {}
+
+						if (!s.object_resizing)
+							try {d.execCommand('enableObjectResizing', false, false);} catch (ex) {}
+					}
+				};
+
+				t.onBeforeExecCommand.add(setOpts);
+				t.onMouseDown.add(setOpts);
+			}
+
+			// Add node change handlers
+			t.onMouseUp.add(t.nodeChanged);
+			t.onClick.add(t.nodeChanged);
+			t.onKeyUp.add(function(ed, e) {
+				if ((e.keyCode >= 33 && e.keyCode <= 36) || (e.keyCode >= 37 && e.keyCode <= 40) || e.keyCode == 13 || e.keyCode == 45 || e.keyCode == 46 || e.keyCode == 8 || e.ctrlKey)
+					t.nodeChanged();
+			});
+
+			// Add reset handler
+			t.onReset.add(function() {
+				t.setContent(t.startContent, {format : 'raw'});
+			});
+
+			if (t.getParam('tab_focus')) {
+				function tabCancel(ed, e) {
+					if (e.keyCode === 9)
+						return Event.cancel(e);
+				};
+
+				function tabHandler(ed, e) {
+					var v, f, el;
+
+					function find(d) {
+						f = DOM.getParent(ed.id, 'form'), el = f.elements;
+
+						if (f) {
+							each(f.elements, function(e, i) {
+								if (e.id == ed.id) {
+									i = i + d;
+
+									if (i < 0 || i > el.length)
+										return;
+
+									el = el[i];
+								}
+							});
+						}
+
+						return el;
+					};
+
+					if (e.keyCode === 9) {
+						v = ed.getParam('tab_focus').split(',');
+
+						if (v.length == 1) {
+							v[1] = v[0];
+							v[0] = ':prev';
+						}
+
+						// Find element to focus
+						if (e.shiftKey) {
+							if (v[0] == ':prev')
+								el = find(-1);
+							else
+								el = DOM.get(v[0]);
+						} else {
+							if (v[1] == ':next')
+								el = find(1);
+							else
+								el = DOM.get(v[1]);
+						}
+
+						if (el) {
+							if (ed = EditorManager.get(el.id || el.name))
+								ed.focus();
+							else
+								window.setTimeout(function() {window.focus();el.focus();}, 10);
+
+							return Event.cancel(e);
+						}
+					}
+				};
+
+				t.onKeyUp.add(tabCancel);
+
+				if (isGecko) {
+					t.onKeyPress.add(tabHandler);
+					t.onKeyDown.add(tabCancel);
+				} else
+					t.onKeyDown.add(tabHandler);
+			}
+
+			// Add shortcuts
+			if (s.custom_shortcuts) {
+				if (s.custom_undo_redo_keyboard_shortcuts) {
+					t.addShortcut('ctrl+z', t.getLang('undo_desc'), 'Undo');
+					t.addShortcut('ctrl+y', t.getLang('redo_desc'), 'Redo');
+				}
+
+				// Add default shortcuts for gecko
+				if (isGecko) {
+					t.addShortcut('ctrl+b', t.getLang('bold_desc'), 'Bold');
+					t.addShortcut('ctrl+i', t.getLang('italic_desc'), 'Italic');
+					t.addShortcut('ctrl+u', t.getLang('underline_desc'), 'Underline');
+				}
+
+				// BlockFormat shortcuts keys
+				for (i=1; i<=6; i++)
+					t.addShortcut('ctrl+' + i, '', ['FormatBlock', false, '<h' + i + '>']);
+
+				t.addShortcut('ctrl+7', '', ['FormatBlock', false, '<p>']);
+				t.addShortcut('ctrl+8', '', ['FormatBlock', false, '<div>']);
+				t.addShortcut('ctrl+9', '', ['FormatBlock', false, '<address>']);
+
+				function find(e) {
+					var v = null;
+
+					if (!e.altKey && !e.ctrlKey && !e.metaKey)
+						return v;
+
+					each(t.shortcuts, function(o) {
+						if (o.ctrl != e.ctrlKey && (!tinymce.isMac || o.ctrl == e.metaKey))
+							return;
+
+						if (o.alt != e.altKey)
+							return;
+
+						if (o.shift != e.shiftKey)
+							return;
+
+						if (e.keyCode == o.keyCode || (e.charCode && e.charCode == o.charCode)) {
+							v = o;
+							return false;
+						}
+					});
+
+					return v;
+				};
+
+				t.onKeyUp.add(function(ed, e) {
+					var o = find(e);
+
+					if (o)
+						return Event.cancel(e);
+				});
+
+				t.onKeyPress.add(function(ed, e) {
+					var o = find(e);
+
+					if (o)
+						return Event.cancel(e);
+				});
+
+				t.onKeyDown.add(function(ed, e) {
+					var o = find(e);
+
+					if (o) {
+						o.func.call(o.scope);
+						return Event.cancel(e);
+					}
+				});
+			}
+
+			if (tinymce.isIE) {
+				// Fix so resize will only update the width and height attributes not the styles of an image
+				// It will also block mceItemNoResize items
+				Event.add(t.getDoc(), 'controlselect', function(e) {
+					var re = t.resizeInfo, cb;
+
+					e = e.target;
+
+					if (re)
+						Event.remove(re.node, re.ev, re.cb);
+
+					if (!t.dom.hasClass(e, 'mceItemNoResize')) {
+						ev = 'resizeend';
+						cb = Event.add(e, ev, function(e) {
+							var v;
+
+							e = e.target;
+
+							if (v = t.dom.getStyle(e, 'width')) {
+								t.dom.setAttrib(e, 'width', v.replace(/[^0-9%]+/g, ''));
+								t.dom.setStyle(e, 'width', '');
+							}
+
+							if (v = t.dom.getStyle(e, 'height')) {
+								t.dom.setAttrib(e, 'height', v.replace(/[^0-9%]+/g, ''));
+								t.dom.setStyle(e, 'height', '');
+							}
+						});
+					} else {
+						ev = 'resizestart';
+						cb = Event.add(e, 'resizestart', Event.cancel, Event);
+					}
+
+					re = t.resizeInfo = {
+						node : e,
+						ev : ev,
+						cb : cb
+					};
+				});
+
+				t.onKeyDown.add(function(ed, e) {
+					switch (e.keyCode) {
+						case 8:
+							// Fix IE control + backspace browser bug
+							if (t.selection.getRng().item) {
+								t.selection.getRng().item(0).removeNode();
+								return Event.cancel(e);
+							}
+					}
+				});
+			}
+
+			if (tinymce.isOpera) {
+				t.onClick.add(function(ed, e) {
+					Event.prevent(e);
+				});
+			}
+
+			// Add custom undo/redo handlers
+			if (s.custom_undo_redo) {
+				function addUndo() {
+					t.undoManager.typing = 0;
+					t.undoManager.add();
+				};
+
+				// Add undo level on editor blur
+				if (tinymce.isIE) {
+					Event.add(t.getWin(), 'blur', function(e) {
+						var n;
+
+						// Check added for fullscreen bug
+						if (t.selection) {
+							n = t.selection.getNode();
+
+							// Add undo level is selection was lost to another document
+							if (!t.removed && n.ownerDocument && n.ownerDocument != t.getDoc())
+								addUndo();
+						}
+					});
+				} else {
+					Event.add(t.getDoc(), 'blur', function() {
+						if (t.selection && !t.removed)
+							addUndo();
+					});
+				}
+
+				t.onMouseDown.add(addUndo);
+
+				t.onKeyUp.add(function(ed, e) {
+					if ((e.keyCode >= 33 && e.keyCode <= 36) || (e.keyCode >= 37 && e.keyCode <= 40) || e.keyCode == 13 || e.keyCode == 45 || e.ctrlKey) {
+						t.undoManager.typing = 0;
+						t.undoManager.add();
+					}
+				});
+
+				t.onKeyDown.add(function(ed, e) {
+					// Is caracter positon keys
+					if ((e.keyCode >= 33 && e.keyCode <= 36) || (e.keyCode >= 37 && e.keyCode <= 40) || e.keyCode == 13 || e.keyCode == 45) {
+						if (t.undoManager.typing) {
+							t.undoManager.add();
+							t.undoManager.typing = 0;
+						}
+
+						return;
+					}
+
+					if (!t.undoManager.typing) {
+						t.undoManager.add();
+						t.undoManager.typing = 1;
+					}
+				});
+			}
+		},
+
+		_destroy : function() {
+			var t = this;
+
+			if (t.formElement) {
+				t.formElement.submit = t.formElement._mceOldSubmit;
+				t.formElement._mceOldSubmit = null;
+			}
+
+			t.contentAreaContainer = t.formElement = t.container = t.contentDocument = t.contentWindow = null;
+
+			if (t.selection)
+				t.selection = t.selection.win = t.selection.dom = t.selection.dom.doc = null;
+
+			t.destroyed = 1;
+		},
+
+		_convertInlineElements : function() {
+			var t = this, s = t.settings, dom = t.dom;
+
+			function convert(ed, o) {
+				if (!s.inline_styles)
+					return;
+
+				if (o.get) {
+					each(t.dom.select('table,u,strike', o.node), function(n) {
+						switch (n.nodeName) {
+							case 'TABLE':
+								if (v = dom.getAttrib(n, 'height')) {
+									dom.setStyle(n, 'height', v);
+									dom.setAttrib(n, 'height', '');
+								}
+								break;
+
+							case 'U':
+								dom.replace(dom.create('span', {style : 'text-decoration: underline;'}), n, 1);
+								break;
+
+							case 'STRIKE':
+								dom.replace(dom.create('span', {style : 'text-decoration: line-through;'}), n, 1);
+								break;
+						}
+					});
+				} else if (o.set) {
+					each(t.dom.select('table,span', o.node), function(n) {
+						if (n.nodeName == 'TABLE') {
+							if (v = dom.getStyle(n, 'height'))
+								dom.setAttrib(n, 'height', v.replace(/[^0-9%]+/g, ''));
+						} else {
+							// Convert spans to elements
+							if (n.style.textDecoration == 'underline')
+								dom.replace(dom.create('u'), n, 1);
+							else if (n.style.textDecoration == 'line-through')
+								dom.replace(dom.create('strike'), n, 1);
+						}
+					});
+				}
+			};
+
+			t.onPreProcess.add(convert);
+
+			if (!s.cleanup_on_startup) {
+				t.onInit.add(function() {
+					convert(t, {node : t.getBody(), set : 1});
+				});
+			}
+		},
+
+		_convertFonts : function() {
+			var t = this, s = t.settings, dom = t.dom, sl, cl, fz, fzn, v, i;
+
+			// Font pt values and font size names
+			fz = [8, 10, 12, 14, 18, 24, 36];
+			fzn = ['xx-small', 'x-small','small','medium','large','x-large', 'xx-large'];
+
+			if (sl = s.font_size_style_values)
+				sl = sl.split(',');
+
+			if (cl = s.font_size_classes)
+				cl = cl.split(',');
+
+			t.onPreProcess.add(function(ed, o) {
+				if (!s.inline_styles)
+					return;
+
+				if (o.set) {
+					// Convert spans to fonts on non WebKit browsers
+					if (tinymce.isWebKit)
+						return;
+
+					each(t.dom.select('span', o.node), function(n) {
+						var f = dom.create('font', {
+							color : dom.toHex(dom.getStyle(n, 'color')),
+							face : dom.getStyle(n, 'fontFamily')
+						});
+
+						if (sl) {
+							i = inArray(sl, dom.getStyle(n, 'fontSize'));
+
+							if (i != -1)
+								dom.setAttrib(f, 'size', '' + (i + 1 || 1));
+						} else if (cl) {
+							i = inArray(cl, dom.getAttrib(n, 'class'));
+
+							v = dom.getStyle(n, 'fontSize');
+
+							if (i == -1 && v.indexOf('pt') > 0)
+								i = inArray(fz, parseInt(v));
+
+							if (i == -1)
+								i = inArray(fzn, v);
+
+							if (i != -1)
+								dom.setAttrib(f, 'size', '' + (i + 1 || 1));
+						}
+
+						if (f.color || f.face || f.size)
+							dom.replace(f, n, 1);
+					});
+				} else if (o.get) {
+					each(t.dom.select('font', o.node), function(n) {
+						var sp = dom.create('span', {
+							style : {
+								fontFamily : dom.getAttrib(n, 'face'),
+								color : dom.getAttrib(n, 'color'),
+								backgroundColor : n.style.backgroundColor
+							}
+						});
+
+						if (n.size) {
+							if (sl)
+								dom.setStyle(sp, 'fontSize', sl[parseInt(n.size) - 1]);
+							else
+								dom.setAttrib(sp, 'class', cl[parseInt(n.size) - 1]);
+						}
+
+						dom.replace(sp, n, 1);
+					});
+				}
+			});
+		},
+
+		_isHidden : function() {
+			var s;
+
+			if (!isGecko)
+				return 0;
+
+			// Weird, wheres that cursor selection?
+			s = this.selection.getSel();
+			return (!s || !s.rangeCount || s.rangeCount == 0);
+		},
+
+		_fixNesting : function(s) {
+			var d = [], i;
+
+			s = s.replace(/<(\/)?([^\s>]+)[^>]*?>/g, function(a, b, c) {
+				var e;
+
+				// Handle end element
+				if (b === '/') {
+					if (!d.length)
+						return '';
+
+					if (c !== d[d.length - 1].tag) {
+						for (i=d.length - 1; i>=0; i--) {
+							if (d[i].tag === c) {
+								d[i].close = 1;
+								break;
+							}
+						}
+
+						return '';
+					} else {
+						d.pop();
+
+						if (d.length && d[d.length - 1].close) {
+							a = a + '</' + d[d.length - 1].tag + '>';
+							d.pop();
+						}
+					}
+				} else {
+					// Ignore these
+					if (/^(br|hr|input|meta|img|link|param)$/i.test(c))
+						return a;
+
+					// Ignore closed ones
+					if (/\/>$/.test(a))
+						return a;
+
+					d.push({tag : c}); // Push start element
+				}
+
+				return a;
+			});
+
+			// End all open tags
+			for (i=d.length - 1; i>=0; i--)
+				s += '</' + d[i].tag + '>';
+
+			return s;
 		}
 
-		return false;
+		});
+})();
+
+/* file:jscripts/tiny_mce/classes/EditorCommands.js */
+
+(function() {
+	var each = tinymce.each, isIE = tinymce.isIE, isGecko = tinymce.isGecko, isOpera = tinymce.isOpera, isWebKit = tinymce.isWebKit;
+
+	tinymce.create('tinymce.EditorCommands', {
+		EditorCommands : function(ed) {
+			this.editor = ed;
+		},
+
+		execCommand : function(cmd, ui, val) {
+			var t = this, ed = t.editor, f;
+
+			switch (cmd) {
+				case 'Cut':
+				case 'Copy':
+				case 'Paste':
+					try {
+						ed.getDoc().execCommand(cmd, ui, val);
+					} catch (ex) {
+						if (isGecko) {
+							ed.windowManager.confirm(ed.getLang('clipboard_msg'), function(s) {
+								if (s)
+									window.open('http://www.mozilla.org/editor/midasdemo/securityprefs.html', 'mceExternal');
+							});
+						} else
+							ed.windowManager.alert(ed.getLang('clipboard_no_support'));
+					}
+
+					return true;
+
+				// Ignore these
+				case 'mceResetDesignMode':
+				case 'mceBeginUndoLevel':
+					return true;
+
+				// Ignore these
+				case 'unlink':
+					t.UnLink();
+					return true;
+
+				// Bundle these together
+				case 'JustifyLeft':
+				case 'JustifyCenter':
+				case 'JustifyRight':
+				case 'JustifyFull':
+					t.mceJustify(cmd, cmd.substring(7).toLowerCase());
+					return true;
+
+				case 'mceEndUndoLevel':
+				case 'mceAddUndoLevel':
+					ed.undoManager.add();
+					return true;
+
+				default:
+					f = this[cmd];
+
+					if (f) {
+						f.call(this, ui, val);
+						return true;
+					}
+			}
+
+			return false;
+		},
+
+		Indent : function() {
+			var ed = this.editor, d = ed.dom, s = ed.selection, e, iv, iu;
+
+			// Setup indent level
+			iv = ed.settings.indentation;
+			iu = /[a-z%]+$/i.exec(iv);
+			iv = parseInt(iv);
+
+			if (ed.settings.inline_styles && (!this.queryStateInsertUnorderedList() && !this.queryStateInsertOrderedList())) {
+				each(this._getSelectedBlocks(), function(e) {
+					d.setStyle(e, 'paddingLeft', (parseInt(e.style.paddingLeft || 0) + iv) + iu);
+				});
+
+				return;
+			}
+
+			ed.getDoc().execCommand('Indent', false, null);
+
+			if (isIE) {
+				d.getParent(s.getNode(), function(n) {
+					if (n.nodeName == 'BLOCKQUOTE') {
+						n.dir = n.style.cssText = '';
+					}
+				});
+			}
+		},
+
+		Outdent : function() {
+			var ed = this.editor, d = ed.dom, s = ed.selection, e, v, iv, iu;
+
+			// Setup indent level
+			iv = ed.settings.indentation;
+			iu = /[a-z%]+$/i.exec(iv);
+			iv = parseInt(iv);
+
+			if (ed.settings.inline_styles && (!this.queryStateInsertUnorderedList() && !this.queryStateInsertOrderedList())) {
+				each(this._getSelectedBlocks(), function(e) {
+					v = Math.max(0, parseInt(e.style.paddingLeft || 0) - iv);
+					d.setStyle(e, 'paddingLeft', v ? v + iu : '');
+				});
+
+				return;
+			}
+
+			ed.getDoc().execCommand('Outdent', false, null);
+		},
+
+		mceSetAttribute : function(u, v) {
+			var ed = this.editor, d = ed.dom, e;
+
+			if (e = d.getParent(ed.selection.getNode(), d.isBlock))
+				d.setAttrib(e, v.name, v.value);
+		},
+
+		mceSetContent : function(u, v) {
+			this.editor.setContent(v);
+		},
+
+		mceToggleVisualAid : function() {
+			var ed = this.editor;
+
+			ed.hasVisual = !ed.hasVisual;
+			ed.addVisual();
+		},
+
+		mceReplaceContent : function(u, v) {
+			var s = this.editor.selection;
+
+			s.setContent(v.replace(/\{\$selection\}/g, s.getContent({format : 'text'})));
+		},
+
+		mceInsertLink : function(u, v) {
+			var ed = this.editor, e = ed.dom.getParent(ed.selection.getNode(), 'A');
+
+			if (tinymce.is(v, 'string'))
+				v = {href : v};
+
+			function set(e) {
+				each(v, function(v, k) {
+					ed.dom.setAttrib(e, k, v);
+				});
+			};
+
+			if (!e) {
+				ed.execCommand('CreateLink', false, 'javascript:mctmp(0);');
+				each(ed.dom.select('a'), function(e) {
+					if (e.href == 'javascript:mctmp(0);')
+						set(e);
+				});
+			} else {
+				if (v.href)
+					set(e);
+				else
+					ed.dom.remove(e, 1);
+			}
+		},
+
+		UnLink : function() {
+			var ed = this.editor, s = ed.selection;
+
+			if (s.isCollapsed())
+				s.select(s.getNode());
+
+			ed.getDoc().execCommand('unlink', false, null);
+			s.collapse(0);
+		},
+
+		FontName : function(u, v) {
+			var t = this, ed = t.editor, s = ed.selection, e;
+
+			if (!v) {
+				if (s.isCollapsed())
+					s.select(s.getNode());
+
+				t.RemoveFormat();
+			} else
+				ed.getDoc().execCommand('FontName', false, v);
+		},
+
+		queryCommandValue : function(c) {
+			var f = this['queryValue' + c];
+
+			if (f)
+				return f.call(this, c);
+
+			return false;
+		},
+
+		queryCommandState : function(cmd) {
+			var f;
+
+			switch (cmd) {
+				// Bundle these together
+				case 'JustifyLeft':
+				case 'JustifyCenter':
+				case 'JustifyRight':
+				case 'JustifyFull':
+					return this.queryStateJustify(cmd, cmd.substring(7).toLowerCase());
+
+				default:
+					if (f = this['queryState' + cmd])
+						return f.call(this, cmd);
+			}
+
+			return -1;
+		},
+
+		queryValueFontSize : function() {
+			var ed = this.editor, v = 0, p;
+
+			if (isOpera || isWebKit) {
+				if (p = ed.dom.getParent(ed.selection.getNode(), 'FONT'))
+					v = p.size;
+
+				return v;
+			}
+
+			return ed.getDoc().queryCommandValue('FontSize');
+		},
+
+		queryValueFontName : function() {
+			var ed = this.editor, v = 0, p;
+
+			if (p = ed.dom.getParent(ed.selection.getNode(), 'FONT'))
+				v = p.face;
+
+			if (!v)
+				v = ed.getDoc().queryCommandValue('FontName');
+
+			return v;
+		},
+
+		mceJustify : function(c, v) {
+			var ed = this.editor, se = ed.selection, n = se.getNode(), nn = n.nodeName, bl, nb, dom = ed.dom, rm;
+
+			if (ed.settings.inline_styles && this.queryStateJustify(c, v))
+				rm = 1;
+
+			bl = dom.getParent(n, ed.dom.isBlock);
+
+			if (nn == 'IMG') {
+				if (v == 'full')
+					return;
+
+				if (rm) {
+					dom.setStyle(n, 'float', '');
+					this.mceRepaint();
+					return;
+				}
+
+				if (v == 'center') {
+					if (!bl || bl.childNodes.length > 1) {
+						nb = dom.create('p');
+						nb.appendChild(n.cloneNode(false));
+
+						if (bl)
+							dom.insertAfter(nb, bl);
+						else
+							dom.insertAfter(nb, n);
+
+						dom.remove(n);
+						n = nb.firstChild;
+						bl = nb;
+					}
+
+					dom.setStyle(bl, 'textAlign', v);
+					dom.setStyle(n, 'float', '');
+				} else
+					dom.setStyle(n, 'float', v);
+
+				this.mceRepaint();
+				return;
+			}
+
+			// Handle the alignment outselfs, less quirks in all browsers
+			if (ed.settings.inline_styles && ed.settings.forced_root_block) {
+				if (rm)
+					v = '';
+
+				each(this._getSelectedBlocks(dom.getParent(se.getStart(), dom.isBlock), dom.getParent(se.getEnd(), dom.isBlock)), function(e) {
+					dom.setAttrib(e, 'align', '');
+					dom.setStyle(e, 'textAlign', v == 'full' ? 'justify' : v);
+				});
+
+				return;
+			} else if (!rm)
+				ed.getDoc().execCommand(c, false, null);
+
+			if (ed.settings.inline_styles) {
+				if (rm) {
+					dom.getParent(ed.selection.getNode(), function(n) {
+						if (n.style && n.style.textAlign)
+							dom.setStyle(n, 'textAlign', '');
+					});
+
+					return;
+				}
+
+				each(dom.select('*'), function(n) {
+					var v = n.align;
+
+					if (v) {
+						if (v == 'full')
+							v = 'justify';
+
+						dom.setStyle(n, 'textAlign', v);
+						dom.setAttrib(n, 'align', '');
+					}
+				});
+			}
+		},
+
+		mceSetCSSClass : function(u, v) {
+			this.mceSetStyleInfo(0, {command : 'setattrib', name : 'class', value : v});
+		},
+
+		getSelectedElement : function() {
+			var t = this, ed = t.editor, dom = ed.dom, se = ed.selection, r = se.getRng(), r1, r2, sc, ec, so, eo, e, sp, ep, re;
+
+			if (se.isCollapsed() || r.item)
+				return se.getNode();
+
+			// Setup regexp
+			re = ed.settings.merge_styles_invalid_parents;
+			if (tinymce.is(re, 'string'))
+				re = new RegExp(re, 'i');
+
+			if (isIE) {
+				r1 = r.duplicate();
+				r1.collapse(true);
+				sc = r1.parentElement();
+
+				r2 = r.duplicate();
+				r2.collapse(false);
+				ec = r2.parentElement();
+
+				if (sc != ec) {
+					r1.move('character', 1);
+					sc = r1.parentElement();
+				}
+
+				if (sc == ec) {
+					r1 = r.duplicate();
+					r1.moveToElementText(sc);
+
+					if (r1.compareEndPoints('StartToStart', r) == 0 && r1.compareEndPoints('EndToEnd', r) == 0)
+						return re && re.test(sc.nodeName) ? null : sc;
+				}
+			} else {
+				function getParent(n) {
+					return dom.getParent(n, function(n) {return n.nodeType == 1;});
+				};
+
+				sc = r.startContainer;
+				ec = r.endContainer;
+				so = r.startOffset;
+				eo = r.endOffset;
+
+				if (!r.collapsed) {
+					if (sc == ec) {
+						if (so - eo < 2) {
+							if (sc.hasChildNodes()) {
+								sp = sc.childNodes[so];
+								return re && re.test(sp.nodeName) ? null : sp;
+							}
+						}
+					}
+				}
+
+				if (sc.nodeType != 3 || ec.nodeType != 3)
+					return null;
+
+				if (so == 0) {
+					sp = getParent(sc);
+
+					if (sp && sp.firstChild != sc)
+						sp = null;
+				}
+
+				if (so == sc.nodeValue.length) {
+					e = sc.nextSibling;
+
+					if (e && e.nodeType == 1)
+						sp = sc.nextSibling;
+				}
+
+				if (eo == 0) {
+					e = ec.previousSibling;
+
+					if (e && e.nodeType == 1)
+						ep = e;
+				}
+
+				if (eo == ec.nodeValue.length) {
+					ep = getParent(ec);
+
+					if (ep && ep.lastChild != ec)
+						ep = null;
+				}
+
+				// Same element
+				if (sp == ep)
+					return re && sp && re.test(sp.nodeName) ? null : sp;
+			}
+
+			return null;
+		},
+
+		InsertHorizontalRule : function() {
+			// Fix for Gecko <hr size="1" /> issue and IE bug rep(/<a.*?href=\"(.*?)\".*?>(.*?)<\/a>/gi,"[url=$1]$2[/url]");
+			if (isGecko || isIE)
+				this.editor.selection.setContent('<hr />');
+			else
+				this.editor.getDoc().execCommand('InsertHorizontalRule', false, '');
+		},
+
+		RemoveFormat : function() {
+			var t = this, ed = t.editor, s = ed.selection, b;
+
+			// Safari breaks tables
+			if (isWebKit)
+				s.setContent(s.getContent({format : 'raw'}).replace(/(<(span|b|i|strong|em|strike) [^>]+>|<(span|b|i|strong|em|strike)>|<\/(span|b|i|strong|em|strike)>|)/g, ''), {format : 'raw'});
+			else
+				ed.getDoc().execCommand('RemoveFormat', false, null);
+
+			t.mceSetStyleInfo(0, {command : 'removeformat'});
+			ed.addVisual();
+		},
+
+		mceSetStyleInfo : function(u, v) {
+			var t = this, ed = t.editor, d = ed.getDoc(), dom = ed.dom, e, b, s = ed.selection, nn = v.wrapper || 'span', b = s.getBookmark(), re;
+
+			function set(n, e) {
+				if (n.nodeType == 1) {
+					switch (v.command) {
+						case 'setattrib':
+							return dom.setAttrib(n, v.name, v.value);
+
+						case 'setstyle':
+							return dom.setStyle(n, v.name, v.value);
+
+						case 'removeformat':
+							return dom.setAttrib(n, 'class', '');
+					}
+				}
+			};
+
+			// Setup regexp
+			re = ed.settings.merge_styles_invalid_parents;
+			if (tinymce.is(re, 'string'))
+				re = new RegExp(re, 'i');
+
+			// Set style info on selected element
+			if (e = t.getSelectedElement())
+				set(e, 1);
+			else {
+				// Generate wrappers and set styles on them
+				d.execCommand('FontName', false, '__');
+				each(isWebKit ? dom.select('span') : dom.select('font'), function(n) {
+					var sp, e;
+
+					if (dom.getAttrib(n, 'face') == '__' || n.style.fontFamily === '__') {
+						sp = dom.create(nn, {mce_new : '1'});
+
+						set(sp);
+
+						each (n.childNodes, function(n) {
+							sp.appendChild(n.cloneNode(true));
+						});
+
+						dom.replace(sp, n);
+					}
+				});
+			}
+
+			// Remove wrappers inside new ones
+			each(dom.select(nn).reverse(), function(n) {
+				var p = n.parentNode;
+
+				dom.setAttrib(n, 'mce_new', '');
+
+				// Check if it's an old span in a new wrapper
+				if (!dom.getAttrib(n, 'mce_new')) {
+					// Find new wrapper
+					p = dom.getParent(n, function(n) {
+						return n.nodeType == 1 && dom.getAttrib(n, 'mce_new');
+					});
+
+					if (p)
+						dom.remove(n, 1);
+				}
+			});
+
+			// Merge wrappers with parent wrappers
+			each(dom.select(nn).reverse(), function(n) {
+				var p = n.parentNode;
+
+				if (!p)
+					return;
+
+				// Has parent of the same type and only child
+				if (p.nodeName == nn.toUpperCase() && p.childNodes.length == 1)
+					return dom.remove(p, 1);
+
+				// Has parent that is more suitable to have the class and only child
+				if (n.nodeType == 1 && (!re || !re.test(p.nodeName)) && p.childNodes.length == 1) {
+					set(p); // Set style info on parent instead
+					dom.setAttrib(n, 'class', '');
+				}
+			});
+
+			// Remove empty wrappers
+			each(dom.select(nn).reverse(), function(n) {
+				if (!dom.getAttrib(n, 'class') && !dom.getAttrib(n, 'style'))
+					return dom.remove(n, 1);
+			});
+
+			s.moveToBookmark(b);
+		},
+
+		queryStateJustify : function(c, v) {
+			var ed = this.editor, n = ed.selection.getNode(), dom = ed.dom;
+
+			if (n && n.nodeName == 'IMG')
+				return dom.getStyle(n, 'float') == v;
+
+			n = dom.getParent(ed.selection.getStart(), function(n) {
+				return n.nodeType == 1 && n.style.textAlign;
+			});
+
+			if (v == 'full')
+				v = 'justify';
+
+			if (ed.settings.inline_styles)
+				return (n && n.style.textAlign == v);
+
+			return ed.getDoc().queryCommandState(c);
+		},
+
+		HiliteColor : function(ui, val) {
+			var t = this, ed = t.editor, d = ed.getDoc();
+
+			function set(s) {
+				if (!isGecko)
+					return;
+
+				try {
+					// Try new Gecko method
+					d.execCommand("styleWithCSS", 0, s);
+				} catch (ex) {
+					// Use old
+					d.execCommand("useCSS", 0, !s);
+				}
+			};
+
+			if (isGecko || isOpera) {
+				set(true);
+				d.execCommand('hilitecolor', false, val);
+				set(false);
+			} else
+				d.execCommand('BackColor', false, val);
+		},
+
+		Undo : function() {
+			var ed = this.editor;
+
+			if (ed.settings.custom_undo_redo) {
+				ed.undoManager.undo();
+				ed.nodeChanged();
+			} else
+				ed.getDoc().execCommand('Undo', false, null);
+		},
+
+		Redo : function() {
+			var ed = this.editor;
+
+			if (ed.settings.custom_undo_redo) {
+				ed.undoManager.redo();
+				ed.nodeChanged();
+			} else
+				ed.getDoc().execCommand('Redo', false, null);
+		},
+
+		FormatBlock : function(ui, val) {
+			var t = this, ed = t.editor;
+
+			val = ed.settings.forced_root_block ? (val || '<p>') : val;
+			t.mceRemoveNode();
+
+			if (val.indexOf('<') == -1)
+				val = '<' + val + '>';
+
+			if (tinymce.isGecko)
+				val = val.replace(/<(div|blockquote|code|dt|dd|dl|samp)>/gi, '$1');
+
+			ed.getDoc().execCommand('FormatBlock', false, val);
+		},
+
+		mceCleanup : function() {
+			var ed = this.editor, s = ed.selection, b = s.getBookmark();
+			ed.setContent(ed.getContent());
+			s.moveToBookmark(b);
+		},
+
+		mceRemoveNode : function(ui, val) {
+			var ed = this.editor, s = ed.selection, b, n = val || s.getNode();
+
+			// Make sure that the body node isn't removed
+			if (n == ed.getBody())
+				return;
+
+			b = s.getBookmark();
+			ed.dom.remove(n, 1);
+			s.moveToBookmark(b);
+			ed.nodeChanged();
+		},
+
+		mceSelectNodeDepth : function(ui, val) {
+			var ed = this.editor, s = ed.selection, c = 0;
+
+			ed.dom.getParent(s.getNode(), function(n) {
+				if (n.nodeType == 1 && c++ == val) {
+					s.select(n);
+					ed.nodeChanged();
+					return false;
+				}
+			}, ed.getBody());
+		},
+
+		mceSelectNode : function(u, v) {
+			this.editor.selection.select(v);
+		},
+
+		mceInsertContent : function(ui, val) {
+			this.editor.selection.setContent(val);
+		},
+
+		mceInsertRawHTML : function(ui, val) {
+			var ed = this.editor;
+
+			ed.execCommand('mceInsertContent', false, 'tiny_mce_marker');
+			ed.setContent(ed.getContent().replace(/tiny_mce_marker/g, val));
+		},
+
+		mceRepaint : function() {
+			var s, b, e = this.editor;
+
+			if (tinymce.isGecko) {
+				try {
+					s = e.selection;
+					b = s.getBookmark(true);
+
+					if (s.getSel())
+						s.getSel().selectAllChildren(e.getBody());
+
+					s.collapse(true);
+					s.moveToBookmark(b);
+				} catch (ex) {
+					// Ignore
+				}
+			}
+		},
+
+		queryStateUnderline : function() {
+			var ed = this.editor, n;
+
+			if (n && n.nodeName == 'A')
+				return false;
+
+			return ed.getDoc().queryCommandState('Underline');
+		},
+
+		queryStateOutdent : function() {
+			var ed = this.editor, n;
+
+			if (ed.settings.inline_styles) {
+				if ((n = ed.dom.getParent(ed.selection.getStart(), ed.dom.isBlock)) && parseInt(n.style.paddingLeft) > 0)
+					return true;
+
+				if ((n = ed.dom.getParent(ed.selection.getEnd(), ed.dom.isBlock)) && parseInt(n.style.paddingLeft) > 0)
+					return true;
+			} else
+				return !!ed.dom.getParent(ed.selection.getNode(), 'BLOCKQUOTE');
+
+			return this.queryStateInsertUnorderedList() || this.queryStateInsertOrderedList();
+		},
+
+		queryStateInsertUnorderedList : function() {
+			return this.editor.dom.getParent(this.editor.selection.getNode(), 'UL');
+		},
+
+		queryStateInsertOrderedList : function() {
+			return this.editor.dom.getParent(this.editor.selection.getNode(), 'OL');
+		},
+
+		queryStatemceBlockQuote : function() {
+			return !!this.editor.dom.getParent(this.editor.selection.getStart(), function(n) {return n.nodeName === 'BLOCKQUOTE';});
+		},
+
+		mceBlockQuote : function() {
+			var t = this, s = t.editor.selection, b = s.getBookmark(), bq, dom = t.editor.dom;
+
+			function findBQ(e) {
+				return dom.getParent(e, function(n) {return n.nodeName === 'BLOCKQUOTE';});
+			};
+
+			// Remove blockquote(s)
+			if (findBQ(s.getStart())) {
+				each(t._getSelectedBlocks(findBQ(s.getStart()), findBQ(s.getEnd())), function(e) {
+					// Found BQ lets remove it
+					if (e.nodeName == 'BLOCKQUOTE')
+						dom.remove(e, 1);
+				});
+
+				t.editor.selection.moveToBookmark(b);
+				return;
+			}
+
+			each(t._getSelectedBlocks(findBQ(s.getStart()), findBQ(s.getEnd())), function(e) {
+				var n;
+
+				// Found existing BQ add to this one
+				if (e.nodeName == 'BLOCKQUOTE' && !bq) {
+					bq = e;
+					return;
+				}
+
+				// No BQ found, create one
+				if (!bq) {
+					bq = dom.create('blockquote');
+					e.parentNode.insertBefore(bq, e);
+				}
+
+				// Add children from existing BQ
+				if (e.nodeName == 'BLOCKQUOTE' && bq) {
+					n = e.firstChild;
+
+					while (n) {
+						bq.appendChild(n.cloneNode(true));
+						n = n.nextSibling;
+					}
+
+					dom.remove(e);
+
+					return;
+				}
+
+				// Add non BQ element to BQ
+				bq.appendChild(dom.remove(e));
+			});
+
+			t.editor.selection.moveToBookmark(b);
+		},
+
+		_getSelectedBlocks : function(st, en) {
+			var ed = this.editor, dom = ed.dom, s = ed.selection, sb, eb, n, bl = [];
+
+			sb = dom.getParent(st || s.getStart(), dom.isBlock);
+			eb = dom.getParent(en || s.getEnd(), dom.isBlock);
+
+			if (sb)
+				bl.push(sb);
+
+			if (sb && eb && sb != eb) {
+				n = sb;
+
+				while ((n = n.nextSibling) && n != eb) {
+					if (dom.isBlock(n))
+						bl.push(n);
+				}
+			}
+
+			if (eb && sb != eb)
+				bl.push(eb);
+
+			return bl;
+		}
+	});
+})();
+
+
+/* file:jscripts/tiny_mce/classes/UndoManager.js */
+
+tinymce.create('tinymce.UndoManager', {
+	index : 0,
+	data : null,
+	typing : 0,
+
+	UndoManager : function(ed) {
+		var t = this, Dispatcher = tinymce.util.Dispatcher;
+
+		t.editor = ed;
+		t.data = [];
+		t.onAdd = new Dispatcher(this);
+		t.onUndo = new Dispatcher(this);
+		t.onRedo = new Dispatcher(this);
+	},
+
+	add : function(l) {
+		var t = this, i, ed = t.editor, b, s = ed.settings, la;
+
+		l = l || {};
+		l.content = l.content || ed.getContent({format : 'raw', no_events : 1});
+
+		// Add undo level if needed
+		l.content = l.content.replace(/^\s*|\s*$/g, '');
+		la = t.data[t.index > 0 ? t.index - 1 : 0];
+		if (!l.initial && la && l.content == la.content)
+			return null;
+
+		// Time to compress
+		if (s.custom_undo_redo_levels) {
+			if (t.data.length > s.custom_undo_redo_levels) {
+				for (i = 0; i < t.data.length - 1; i++)
+					t.data[i] = t.data[i + 1];
+
+				t.data.length--;
+				t.index = t.data.length;
+			}
+		}
+
+		if (s.custom_undo_redo_restore_selection)
+			l.bookmark = b = l.bookmark || ed.selection.getBookmark();
+
+		if (t.index < t.data.length && t.data[t.index].initial)
+			t.index++;
+
+		// Add level
+		t.data.length = t.index + 1;
+		t.data[t.index++] = l;
+
+		if (l.initial)
+			t.index = 0;
+
+		// Set initial bookmark use first real undo level
+		if (t.data.length == 2 && t.data[0].initial)
+			t.data[0].bookmark = b;
+
+		t.onAdd.dispatch(t, l);
+		ed.isNotDirty = 0;
+
+		//console.dir(t.data);
+
+		return l;
 	},
 
 	undo : function() {
-		var inst = this.instance;
-
-		// Do undo
-		if (this.undoIndex > 0) {
-			this.undoIndex--;
-
-			tinyMCE.setInnerHTML(inst.getBody(), this.undoLevels[this.undoIndex].content);
-			inst.repaint();
-
-			if (inst.settings.custom_undo_redo_restore_selection)
-				inst.selection.moveToBookmark(this.undoLevels[this.undoIndex].bookmark);
+		var t = this, ed = t.editor, l = l, i;
+
+		if (t.typing) {
+			t.add();
+			t.typing = 0;
 		}
+
+		if (t.index > 0) {
+			// If undo on last index then take snapshot
+			if (t.index == t.data.length && t.index > 1) {
+				i = t.index;
+				t.typing = 0;
+
+				if (!t.add())
+					t.index = i;
+
+				--t.index;
+			}
+
+			l = t.data[--t.index];
+			ed.setContent(l.content, {format : 'raw'});
+			ed.selection.moveToBookmark(l.bookmark);
+
+			t.onUndo.dispatch(t, l);
+		}
+
+		return l;
 	},
 
 	redo : function() {
-		var inst = this.instance;
-
-		tinyMCE.execCommand("mceEndTyping");
-
-		if (this.undoIndex < (this.undoLevels.length-1)) {
-			this.undoIndex++;
-
-			tinyMCE.setInnerHTML(inst.getBody(), this.undoLevels[this.undoIndex].content);
-			inst.repaint();
-
-			if (inst.settings.custom_undo_redo_restore_selection)
-				inst.selection.moveToBookmark(this.undoLevels[this.undoIndex].bookmark);
-		}
-
-		tinyMCE.triggerNodeChange();
-	}
-
-	};
-
-/* file:jscripts/tiny_mce/classes/TinyMCE_ForceParagraphs.class.js */
-
-var TinyMCE_ForceParagraphs = {
-	_insertPara : function(inst, e) {
-		var doc = inst.getDoc(), sel = inst.getSel(), body = inst.getBody(), win = inst.contentWindow, rng = sel.getRangeAt(0);
-		var rootElm = doc.documentElement, blockName = "P", startNode, endNode, startBlock, endBlock;
-		var rngBefore, rngAfter, direct, startNode, startOffset, endNode, endOffset, b = tinyMCE.isOpera ? inst.selection.getBookmark() : null;
-		var paraBefore, paraAfter, startChop, endChop, contents;
-
-		function isEmpty(para) {
-			function isEmptyHTML(html) {
-				return html.replace(new RegExp('[ \t\r\n]+', 'g'), '').toLowerCase() == "";
-			}
-
-			// Check for images
-			if (para.getElementsByTagName("img").length > 0)
-				return false;
-
-			// Check for tables
-			if (para.getElementsByTagName("table").length > 0)
-				return false;
-
-			// Check for HRs
-			if (para.getElementsByTagName("hr").length > 0)
-				return false;
-
-			// Check all textnodes
-			var nodes = tinyMCE.getNodeTree(para, new Array(), 3);
-			for (var i=0; i<nodes.length; i++) {
-				if (!isEmptyHTML(nodes[i].nodeValue))
-					return false;
-			}
-
-			// No images, no tables, no hrs, no text content then it's empty
-			return true;
-		}
-
-	//	tinyMCE.debug(body.innerHTML);
-
-	//	debug(e.target, sel.anchorNode.nodeName, sel.focusNode.nodeName, rng.startContainer, rng.endContainer, rng.commonAncestorContainer, sel.anchorOffset, sel.focusOffset, rng.toString());
-
-		// Setup before range
-		rngBefore = doc.createRange();
-		rngBefore.setStart(sel.anchorNode, sel.anchorOffset);
-		rngBefore.collapse(true);
-
-		// Setup after range
-		rngAfter = doc.createRange();
-		rngAfter.setStart(sel.focusNode, sel.focusOffset);
-		rngAfter.collapse(true);
-
-		// Setup start/end points
-		direct = rngBefore.compareBoundaryPoints(rngBefore.START_TO_END, rngAfter) < 0;
-		startNode = direct ? sel.anchorNode : sel.focusNode;
-		startOffset = direct ? sel.anchorOffset : sel.focusOffset;
-		endNode = direct ? sel.focusNode : sel.anchorNode;
-		endOffset = direct ? sel.focusOffset : sel.anchorOffset;
-
-		startNode = startNode.nodeName == "BODY" ? startNode.firstChild : startNode;
-		endNode = endNode.nodeName == "BODY" ? endNode.firstChild : endNode;
-
-		// Get block elements
-		startBlock = inst.getParentBlockElement(startNode);
-		endBlock = inst.getParentBlockElement(endNode);
-
-		// If absolute force paragraph generation within
-		if (startBlock && new RegExp('absolute|relative|static', 'gi').test(startBlock.style.position))
-			startBlock = null;
-
-		if (endBlock && new RegExp('absolute|relative|static', 'gi').test(endBlock.style.position))
-			endBlock = null;
-
-		// Use current block name
-		if (startBlock != null) {
-			blockName = startBlock.nodeName;
-
-			// Use P instead
-			if (blockName == "TD" || blockName == "TABLE" || (blockName == "DIV" && new RegExp('left|right', 'gi').test(startBlock.style.cssFloat)))
-				blockName = "P";
-		}
-
-		// Within a list use normal behaviour
-		if (tinyMCE.getParentElement(startBlock, "OL,UL", null, body) != null)
-			return false;
-
-		// Within a table create new paragraphs
-		if ((startBlock != null && startBlock.nodeName == "TABLE") || (endBlock != null && endBlock.nodeName == "TABLE"))
-			startBlock = endBlock = null;
-
-		// Setup new paragraphs
-		paraBefore = (startBlock != null && startBlock.nodeName == blockName) ? startBlock.cloneNode(false) : doc.createElement(blockName);
-		paraAfter = (endBlock != null && endBlock.nodeName == blockName) ? endBlock.cloneNode(false) : doc.createElement(blockName);
-
-		// Is header, then force paragraph under
-		if (/^(H[1-6])$/.test(blockName))
-			paraAfter = doc.createElement("p");
-
-		// Setup chop nodes
-		startChop = startNode;
-		endChop = endNode;
-
-		// Get startChop node
-		node = startChop;
-		do {
-			if (node == body || node.nodeType == 9 || tinyMCE.isBlockElement(node))
-				break;
-
-			startChop = node;
-		} while ((node = node.previousSibling ? node.previousSibling : node.parentNode));
-
-		// Get endChop node
-		node = endChop;
-		do {
-			if (node == body || node.nodeType == 9 || tinyMCE.isBlockElement(node))
-				break;
-
-			endChop = node;
-		} while ((node = node.nextSibling ? node.nextSibling : node.parentNode));
-
-		// Fix when only a image is within the TD
-		if (startChop.nodeName == "TD")
-			startChop = startChop.firstChild;
-
-		if (endChop.nodeName == "TD")
-			endChop = endChop.lastChild;
-
-		// If not in a block element
-		if (startBlock == null) {
-			// Delete selection
-			rng.deleteContents();
-
-			if (!tinyMCE.isSafari)
-				sel.removeAllRanges();
-
-			if (startChop != rootElm && endChop != rootElm) {
-				// Insert paragraph before
-				rngBefore = rng.cloneRange();
-
-				if (startChop == body)
-					rngBefore.setStart(startChop, 0);
-				else
-					rngBefore.setStartBefore(startChop);
-
-				paraBefore.appendChild(rngBefore.cloneContents());
-
-				// Insert paragraph after
-				if (endChop.parentNode.nodeName == blockName)
-					endChop = endChop.parentNode;
-
-				// If not after image
-				//if (rng.startContainer.nodeName != "BODY" && rng.endContainer.nodeName != "BODY")
-					rng.setEndAfter(endChop);
-
-				if (endChop.nodeName != "#text" && endChop.nodeName != "BODY")
-					rngBefore.setEndAfter(endChop);
-
-				contents = rng.cloneContents();
-				if (contents.firstChild && (contents.firstChild.nodeName == blockName || contents.firstChild.nodeName == "BODY"))
-					paraAfter.innerHTML = contents.firstChild.innerHTML;
-				else
-					paraAfter.appendChild(contents);
-
-				// Check if it's a empty paragraph
-				if (isEmpty(paraBefore))
-					paraBefore.innerHTML = "&nbsp;";
-
-				// Check if it's a empty paragraph
-				if (isEmpty(paraAfter))
-					paraAfter.innerHTML = "&nbsp;";
-
-				// Delete old contents
-				rng.deleteContents();
-				rngAfter.deleteContents();
-				rngBefore.deleteContents();
-
-				// Insert new paragraphs
-				if (tinyMCE.isOpera) {
-					paraBefore.normalize();
-					rngBefore.insertNode(paraBefore);
-					paraAfter.normalize();
-					rngBefore.insertNode(paraAfter);
-				} else {
-					paraAfter.normalize();
-					rngBefore.insertNode(paraAfter);
-					paraBefore.normalize();
-					rngBefore.insertNode(paraBefore);
-				}
-
-				//tinyMCE.debug("1: ", paraBefore.innerHTML, paraAfter.innerHTML);
-			} else {
-				body.innerHTML = "<" + blockName + ">&nbsp;</" + blockName + "><" + blockName + ">&nbsp;</" + blockName + ">";
-				paraAfter = body.childNodes[1];
-			}
-
-			inst.selection.moveToBookmark(b);
-			inst.selection.selectNode(paraAfter, true, true);
-
-			return true;
-		}
-
-		// Place first part within new paragraph
-		if (startChop.nodeName == blockName)
-			rngBefore.setStart(startChop, 0);
-		else
-			rngBefore.setStartBefore(startChop);
-
-		rngBefore.setEnd(startNode, startOffset);
-		paraBefore.appendChild(rngBefore.cloneContents());
-
-		// Place secound part within new paragraph
-		rngAfter.setEndAfter(endChop);
-		rngAfter.setStart(endNode, endOffset);
-		contents = rngAfter.cloneContents();
-
-		if (contents.firstChild && contents.firstChild.nodeName == blockName) {
-	/*		var nodes = contents.firstChild.childNodes;
-			for (var i=0; i<nodes.length; i++) {
-				//tinyMCE.debug(nodes[i].nodeName);
-				if (nodes[i].nodeName != "BODY")
-					paraAfter.appendChild(nodes[i]);
-			}
-	*/
-			paraAfter.innerHTML = contents.firstChild.innerHTML;
-		} else
-			paraAfter.appendChild(contents);
-
-		// Check if it's a empty paragraph
-		if (isEmpty(paraBefore))
-			paraBefore.innerHTML = "&nbsp;";
-
-		// Check if it's a empty paragraph
-		if (isEmpty(paraAfter))
-			paraAfter.innerHTML = "&nbsp;";
-
-		// Create a range around everything
-		rng = doc.createRange();
-
-		if (!startChop.previousSibling && startChop.parentNode.nodeName.toUpperCase() == blockName) {
-			rng.setStartBefore(startChop.parentNode);
-		} else {
-			if (rngBefore.startContainer.nodeName.toUpperCase() == blockName && rngBefore.startOffset == 0)
-				rng.setStartBefore(rngBefore.startContainer);
-			else
-				rng.setStart(rngBefore.startContainer, rngBefore.startOffset);
-		}
-
-		if (!endChop.nextSibling && endChop.parentNode.nodeName.toUpperCase() == blockName)
-			rng.setEndAfter(endChop.parentNode);
-		else
-			rng.setEnd(rngAfter.endContainer, rngAfter.endOffset);
-
-		// Delete all contents and insert new paragraphs
-		rng.deleteContents();
-
-		if (tinyMCE.isOpera) {
-			rng.insertNode(paraBefore);
-			rng.insertNode(paraAfter);
-		} else {
-			rng.insertNode(paraAfter);
-			rng.insertNode(paraBefore);
+		var t = this, ed = t.editor, l = null;
+
+		if (t.index < t.data.length - 1) {
+			l = t.data[++t.index];
+			ed.setContent(l.content, {format : 'raw'});
+			ed.selection.moveToBookmark(l.bookmark);
+
+			t.onRedo.dispatch(t, l);
 		}
 
-		//tinyMCE.debug("2", paraBefore.innerHTML, paraAfter.innerHTML);
-
-		// Normalize
-		paraAfter.normalize();
-		paraBefore.normalize();
-
-		inst.selection.moveToBookmark(b);
-		inst.selection.selectNode(paraAfter, true, true);
-
-		return true;
-	},
-
-	_handleBackSpace : function(inst) {
-		var r = inst.getRng(), sn = r.startContainer, nv, s = false;
-
-		// Added body check for bug #1527787
-		if (sn && sn.nextSibling && sn.nextSibling.nodeName == "BR" && sn.parentNode.nodeName != "BODY") {
-			nv = sn.nodeValue;
-
-			// Handle if a backspace is pressed after a space character #bug 1466054 removed since fix for #1527787
-			/*if (nv != null && nv.length >= r.startOffset && nv.charAt(r.startOffset - 1) == ' ')
-				s = true;*/
-
-			// Only remove BRs if we are at the end of line #bug 1464152
-			if (nv != null && r.startOffset == nv.length)
-				sn.nextSibling.parentNode.removeChild(sn.nextSibling);
-		}
-
-		if (inst.settings.auto_resize)
-			inst.resizeToContent();
-
-		return s;
-	}
-
-	};
-
-/* file:jscripts/tiny_mce/classes/TinyMCE_Layer.class.js */
-
-function TinyMCE_Layer(id, bm) {
-	this.id = id;
-	this.blockerElement = null;
-	this.events = false;
-	this.element = null;
-	this.blockMode = typeof(bm) != 'undefined' ? bm : true;
-	this.doc = document;
-};
-
-TinyMCE_Layer.prototype = {
-	moveRelativeTo : function(re, p) {
-		var rep = this.getAbsPosition(re);
-		var w = parseInt(re.offsetWidth);
-		var h = parseInt(re.offsetHeight);
-		var e = this.getElement();
-		var ew = parseInt(e.offsetWidth);
-		var eh = parseInt(e.offsetHeight);
-		var x, y;
-
-		switch (p) {
-			case "tl":
-				x = rep.absLeft;
-				y = rep.absTop;
-				break;
-
-			case "tr":
-				x = rep.absLeft + w;
-				y = rep.absTop;
-				break;
-
-			case "bl":
-				x = rep.absLeft;
-				y = rep.absTop + h;
-				break;
-
-			case "br":
-				x = rep.absLeft + w;
-				y = rep.absTop + h;
-				break;
-
-			case "cc":
-				x = rep.absLeft + (w / 2) - (ew / 2);
-				y = rep.absTop + (h / 2) - (eh / 2);
-				break;
-		}
-
-		this.moveTo(x, y);
-	},
-
-	moveBy : function(x, y) {
-		var e = this.getElement();
-		this.moveTo(parseInt(e.style.left) + x, parseInt(e.style.top) + y);
-	},
-
-	moveTo : function(x, y) {
-		var e = this.getElement();
-
-		e.style.left = x + "px";
-		e.style.top = y + "px";
-
-		this.updateBlocker();
-	},
-
-	resizeBy : function(w, h) {
-		var e = this.getElement();
-		this.resizeTo(parseInt(e.style.width) + w, parseInt(e.style.height) + h);
-	},
-
-	resizeTo : function(w, h) {
-		var e = this.getElement();
-
-		if (w != null)
-			e.style.width = w + "px";
-
-		if (h != null)
-			e.style.height = h + "px";
-
-		this.updateBlocker();
-	},
-
-	show : function() {
-		var el = this.getElement();
-
-		if (el) {
-			el.style.display = 'block';
-			this.updateBlocker();
-		}
-	},
-
-	hide : function() {
-		var el = this.getElement();
-
-		if (el) {
-			el.style.display = 'none';
-			this.updateBlocker();
-		}
-	},
-
-	isVisible : function() {
-		return this.getElement().style.display == 'block';
-	},
-
-	getElement : function() {
-		if (!this.element)
-			this.element = this.doc.getElementById(this.id);
-
-		return this.element;
-	},
-
-	setBlockMode : function(s) {
-		this.blockMode = s;
-	},
-
-	updateBlocker : function() {
-		var e, b, x, y, w, h;
-
-		b = this.getBlocker();
-		if (b) {
-			if (this.blockMode) {
-				e = this.getElement();
-				x = this.parseInt(e.style.left);
-				y = this.parseInt(e.style.top);
-				w = this.parseInt(e.offsetWidth);
-				h = this.parseInt(e.offsetHeight);
-
-				b.style.left = x + 'px';
-				b.style.top = y + 'px';
-				b.style.width = w + 'px';
-				b.style.height = h + 'px';
-				b.style.display = e.style.display;
-			} else
-				b.style.display = 'none';
-		}
-	},
-
-	getBlocker : function() {
-		var d, b;
-
-		if (!this.blockerElement && this.blockMode) {
-			d = this.doc;
-			b = d.getElementById(this.id + "_blocker");
-
-			if (!b) {
-				b = d.createElement("iframe");
-
-				b.setAttribute('id', this.id + "_blocker");
-				b.style.cssText = 'display: none; position: absolute; left: 0; top: 0';
-				b.src = 'javascript:false;';
-				b.frameBorder = '0';
-				b.scrolling = 'no';
-	
-				d.body.appendChild(b);
-			}
-
-			this.blockerElement = b;
-		}
-
-		return this.blockerElement;
-	},
-
-	getAbsPosition : function(n) {
-		var p = {absLeft : 0, absTop : 0};
-
-		while (n) {
-			p.absLeft += n.offsetLeft;
-			p.absTop += n.offsetTop;
-			n = n.offsetParent;
-		}
-
-		return p;
-	},
-
-	create : function(n, c, p, h) {
-		var d = this.doc, e = d.createElement(n);
-
-		e.setAttribute('id', this.id);
-
-		if (c)
-			e.className = c;
-
-		if (!p)
-			p = d.body;
-
-		if (h)
-			e.innerHTML = h;
-
-		p.appendChild(e);
-
-		return this.element = e;
-	},
-
-	exists : function() {
-		return this.doc.getElementById(this.id) != null;
-	},
-
-	parseInt : function(s) {
-		if (s == null || s == '')
-			return 0;
-
-		return parseInt(s);
-	},
-
-	remove : function() {
-		var e = this.getElement(), b = this.getBlocker();
-
-		if (e)
-			e.parentNode.removeChild(e);
-
-		if (b)
-			b.parentNode.removeChild(b);
-	}
-
-	};
-
-/* file:jscripts/tiny_mce/classes/TinyMCE_Menu.class.js */
-
-function TinyMCE_Menu() {
-	var id;
-
-	if (typeof(tinyMCE.menuCounter) == "undefined")
-		tinyMCE.menuCounter = 0;
-
-	id = "mc_menu_" + tinyMCE.menuCounter++;
-
-	TinyMCE_Layer.call(this, id, true);
-
-	this.id = id;
-	this.items = new Array();
-	this.needsUpdate = true;
-};
-
-TinyMCE_Menu.prototype = tinyMCE.extend(TinyMCE_Layer.prototype, {
-	init : function(s) {
-		var n;
-
-		// Default params
-		this.settings = {
-			separator_class : 'mceMenuSeparator',
-			title_class : 'mceMenuTitle',
-			disabled_class : 'mceMenuDisabled',
-			menu_class : 'mceMenu',
-			drop_menu : true
-		};
-
-		for (n in s)
-			this.settings[n] = s[n];
-
-		this.create('div', this.settings.menu_class);
+		return l;
 	},
 
 	clear : function() {
-		this.items = new Array();
-	},
-
-	addTitle : function(t) {
-		this.add({type : 'title', text : t});
-	},
-
-	addDisabled : function(t) {
-		this.add({type : 'disabled', text : t});
-	},
-
-	addSeparator : function() {
-		this.add({type : 'separator'});
-	},
-
-	addItem : function(t, js) {
-		this.add({text : t, js : js});
-	},
-
-	add : function(mi) {
-		this.items[this.items.length] = mi;
-		this.needsUpdate = true;
+		var t = this;
+
+		t.data = [];
+		t.index = 0;
+		t.typing = 0;
+		t.add({initial : true});
 	},
 
-	update : function() {
-		var e = this.getElement(), h = '', i, t, m = this.items, s = this.settings;
-
-		if (this.settings.drop_menu)
-			h += '<span class="mceMenuLine"></span>';
-
-		h += '<table border="0" cellpadding="0" cellspacing="0">';
-
-		for (i=0; i<m.length; i++) {
-			t = tinyMCE.xmlEncode(m[i].text);
-			c = m[i].class_name ? ' class="' + m[i].class_name + '"' : '';
-
-			switch (m[i].type) {
-				case 'separator':
-					h += '<tr class="' + s.separator_class + '"><td>';
-					break;
-
-				case 'title':
-					h += '<tr class="' + s.title_class + '"><td><span' + c +'>' + t + '</span>';
-					break;
-
-				case 'disabled':
-					h += '<tr class="' + s.disabled_class + '"><td><span' + c +'>' + t + '</span>';
-					break;
-
-				default:
-					h += '<tr><td><a href="' + tinyMCE.xmlEncode(m[i].js) + '" onmousedown="' + tinyMCE.xmlEncode(m[i].js) + ';return tinyMCE.cancelEvent(event);" onclick="return tinyMCE.cancelEvent(event);" onmouseup="return tinyMCE.cancelEvent(event);"><span' + c +'>' + t + '</span></a>';
-			}
-
-			h += '</td></tr>';
-		}
-
-		h += '</table>';
-
-		e.innerHTML = h;
-
-		this.needsUpdate = false;
-		this.updateBlocker();
+	hasUndo : function() {
+		return this.index != 0 || this.typing;
 	},
 
-	show : function() {
-		var nl, i;
-
-		if (tinyMCE.lastMenu == this)
-			return;
-
-		if (this.needsUpdate)
-			this.update();
-
-		if (tinyMCE.lastMenu && tinyMCE.lastMenu != this)
-			tinyMCE.lastMenu.hide();
-
-		TinyMCE_Layer.prototype.show.call(this);
-
-		if (!tinyMCE.isOpera) {
-			// Accessibility stuff
-/*			nl = this.getElement().getElementsByTagName("a");
-			if (nl.length > 0)
-				nl[0].focus();*/
-		}
-
-		tinyMCE.lastMenu = this;
+	hasRedo : function() {
+		return this.index < this.data.length - 1;
 	}
 
 	});
-
-/* file:jscripts/tiny_mce/classes/TinyMCE_Compatibility.class.js */
-
-if (!Function.prototype.call) {
-	Function.prototype.call = function() {
-		var a = arguments, s = a[0], i, as = '', r, o;
-
-		for (i=1; i<a.length; i++)
-			as += (i > 1 ? ',' : '') + 'a[' + i + ']';
-
-		o = s._fu;
-		s._fu = this;
-		r = eval('s._fu(' + as + ')');
-		s._fu = o;
-
-		return r;
-	};
-};
-
-/* file:jscripts/tiny_mce/classes/TinyMCE_Debug.class.js */
-
-TinyMCE_Engine.prototype.debug = function() {
-	var m = "", a, i, l = tinyMCE.log.length;
-
-	for (i=0, a = this.debug.arguments; i<a.length; i++) {
-		m += a[i];
-
-		if (i<a.length-1)
-			m += ', ';
-	}
-
-	if (l < 1000)
-		tinyMCE.log[l] = "[debug] " + m;
-};
-
+/* file:jscripts/tiny_mce/classes/ForceBlocks.js */
+
+(function() {
+	// Shorten names
+	var Event, isIE, isGecko, isOpera, each, extend;
+
+	Event = tinymce.dom.Event;
+	isIE = tinymce.isIE;
+	isGecko = tinymce.isGecko;
+	isOpera = tinymce.isOpera;
+	each = tinymce.each;
+	extend = tinymce.extend;
+
+	tinymce.create('tinymce.ForceBlocks', {
+		ForceBlocks : function(ed) {
+			var t = this, s;
+
+			t.editor = ed;
+			t.dom = ed.dom;
+
+			// Default settings
+			t.settings = s = extend({
+				element : 'P',
+				forced_root_block : 'p',
+				force_p_newlines : true
+			}, ed.settings);
+
+			ed.onPreInit.add(t.setup, t);
+
+			function padd(ed, o) {
+				if (isOpera)
+					o.content = o.content.replace(/(\u00a0|&#160;|&nbsp;)<\/p>/gi, '</p>');
+
+				o.content = o.content.replace(/<p( )([^>]+)><\/p>|<p( )([^>]+)\/>|<p( )([^>]+)>\s+<\/p>|<p><\/p>|<p\/>|<p>\s+<\/p>/gi, '<p$1$2$3$4$5$6>\u00a0</p>');
+
+				if (!isIE && o.set) {
+					// Use &nbsp; instead of BR in padded paragraphs
+					o.content = o.content.replace(/<p( )([^>]+)>[\s\u00a0]+<\/p>|<p>[\s\u00a0]+<\/p>/gi, '<p$1$2><br /></p>');
+				} else {
+					o.content = o.content.replace(/<p( )([^>]+)>\s*<br \/>\s*<\/p>|<p>\s*<br \/>\s*<\/p>/gi, '<p$1$2>\u00a0</p>');
+					o.content = o.content.replace(/\s*<br \/>\s*<\/p>/gi, '</p>');
+				}
+			};
+
+			ed.onBeforeSetContent.add(padd);
+			ed.onPostProcess.add(padd);
+
+			if (s.forced_root_block) {
+				ed.onInit.add(t.forceRoots, t);
+				ed.onSetContent.add(t.forceRoots, t);
+				ed.onBeforeGetContent.add(t.forceRoots, t);
+			}
+		},
+
+		setup : function() {
+			var t = this, ed = t.editor, s = t.settings;
+
+			// Force root blocks when typing and when getting output
+			if (s.forced_root_block) {
+				ed.onKeyUp.add(t.forceRoots, t);
+				ed.onPreProcess.add(t.forceRoots, t);
+			}
+
+			if (s.force_br_newlines) {
+				// Force IE to produce BRs on enter
+				if (isIE) {
+					ed.onKeyPress.add(function(ed, e) {
+						var n, s = ed.selection;
+
+						if (e.keyCode == 13) {
+							s.setContent('<br id="__" /> ', {format : 'raw'});
+							n = ed.dom.get('__');
+							n.removeAttribute('id');
+							s.select(n);
+							s.collapse();
+							return Event.cancel(e);
+						}
+					});
+				}
+
+				return;
+			}
+
+			if (!isIE && s.force_p_newlines) {
+				ed.onPreProcess.add(function(ed, o) {
+					each(ed.dom.select('br', o.node), function(n) {
+						var p = n.parentNode;
+
+						// Replace <p><br /></p> with <p>&nbsp;</p>
+						if (p && p.nodeName == 'p' && (p.childNodes.length == 1 || p.lastChild == n))
+							p.replaceChild(ed.getDoc().createTextNode('\u00a0'), n);
+					});
+				});
+
+				ed.onKeyPress.add(function(ed, e) {
+					if (e.keyCode == 13 && !e.shiftKey) {
+						if (!t.insertPara(e))
+							Event.cancel(e);
+					}
+				});
+
+				if (isGecko) {
+					ed.onKeyDown.add(function(ed, e) {
+						if ((e.keyCode == 8 || e.keyCode == 46) && !e.shiftKey)
+							t.backspaceDelete(e, e.keyCode == 8);
+					});
+				}
+			}
+		},
+
+		find : function(n, t, s) {
+			var ed = this.editor, w = ed.getDoc().createTreeWalker(n, 4, null, false), c = -1;
+
+			while (n = w.nextNode()) {
+				c++;
+
+				// Index by node
+				if (t == 0 && n == s)
+					return c;
+
+				// Node by index
+				if (t == 1 && c == s)
+					return n;
+			}
+
+			return -1;
+		},
+
+		forceRoots : function(ed, e) {
+			var t = this, ed = t.editor, b = ed.getBody(), d = ed.getDoc(), se = ed.selection, s = se.getSel(), r = se.getRng(), si = -2, ei, so, eo, tr, c = -0xFFFFFF;
+			var nx, bl, bp, sp, le, nl = b.childNodes, i;
+
+			// Fix for bug #1863847
+			if (e && e.keyCode == 13)
+				return true;
+
+			// Wrap non blocks into blocks
+			for (i = nl.length - 1; i >= 0; i--) {
+				nx = nl[i];
+
+				// Is text or non block element
+				if (nx.nodeType == 3 || !t.dom.isBlock(nx)) {
+					if (!bl) {
+						// Create new block but ignore whitespace
+						if (nx.nodeType != 3 || /[^\s]/g.test(nx.nodeValue)) {
+							// Store selection
+							if (si == -2 && r) {
+								if (!isIE) {
+									so = r.startOffset;
+									eo = r.endOffset;
+									si = t.find(b, 0, r.startContainer);
+									ei = t.find(b, 0, r.endContainer);
+								} else {
+									tr = d.body.createTextRange();
+									tr.moveToElementText(b);
+									tr.collapse(1);
+									bp = tr.move('character', c) * -1;
+
+									tr = r.duplicate();
+									tr.collapse(1);
+									sp = tr.move('character', c) * -1;
+
+									tr = r.duplicate();
+									tr.collapse(0);
+									le = (tr.move('character', c) * -1) - sp;
+
+									si = sp - bp;
+									ei = le;
+								}
+							}
+
+							bl = ed.dom.create(t.settings.forced_root_block);
+							bl.appendChild(nx.cloneNode(1));
+							nx.parentNode.replaceChild(bl, nx);
+						}
+					} else {
+						if (bl.hasChildNodes())
+							bl.insertBefore(nx, bl.firstChild);
+						else
+							bl.appendChild(nx);
+					}
+				} else
+					bl = null; // Time to create new block
+			}
+
+			// Restore selection
+			if (si != -2) {
+				if (!isIE) {
+					bl = d.getElementsByTagName(t.settings.element)[0];
+					r = d.createRange();
+
+					// Select last location or generated block
+					if (si != -1)
+						r.setStart(t.find(b, 1, si), so);
+					else
+						r.setStart(bl, 0);
+
+					// Select last location or generated block
+					if (ei != -1)
+						r.setEnd(t.find(b, 1, ei), eo);
+					else
+						r.setEnd(bl, 0);
+
+					if (s) {
+						s.removeAllRanges();
+						s.addRange(r);
+					}
+				} else {
+					try {
+						r = s.createRange();
+						r.moveToElementText(b);
+						r.collapse(1);
+						r.moveStart('character', si);
+						r.moveEnd('character', ei);
+						r.select();
+					} catch (ex) {
+						// Ignore
+					}
+				}
+			}
+		},
+
+		getParentBlock : function(n) {
+			var d = this.dom;
+
+			return d.getParent(n, d.isBlock);
+		},
+
+		insertPara : function(e) {
+			var t = this, ed = t.editor, d = ed.getDoc(), se = t.settings, s = ed.selection.getSel(), r = s.getRangeAt(0), b = d.body;
+			var rb, ra, dir, sn, so, en, eo, sb, eb, bn, bef, aft, sc, ec, n;
+
+			function isEmpty(n) {
+				n = n.innerHTML;
+				n = n.replace(/<(img|hr|table)/gi, '-'); // Keep these convert them to - chars
+				n = n.replace(/<[^>]+>/g, ''); // Remove all tags
+
+				return n.replace(/[ \t\r\n]+/g, '') == '';
+			};
+
+			// If root blocks are forced then use Operas default behavior since it's really good
+// Removed due to bug: #1853816
+//			if (se.forced_root_block && isOpera)
+//				return true;
+
+			// Setup before range
+			rb = d.createRange();
+
+			// If is before the first block element and in body, then move it into first block element
+			rb.setStart(s.anchorNode, s.anchorOffset);
+			rb.collapse(true);
+
+			// Setup after range
+			ra = d.createRange();
+
+			// If is before the first block element and in body, then move it into first block element
+			ra.setStart(s.focusNode, s.focusOffset);
+			ra.collapse(true);
+
+			// Setup start/end points
+			dir = rb.compareBoundaryPoints(rb.START_TO_END, ra) < 0;
+			sn = dir ? s.anchorNode : s.focusNode;
+			so = dir ? s.anchorOffset : s.focusOffset;
+			en = dir ? s.focusNode : s.anchorNode;
+			eo = dir ? s.focusOffset : s.anchorOffset;
+
+			// If the caret is in an invalid location in FF we need to move it into the first block
+			if (sn == b && en == b && b.firstChild && ed.dom.isBlock(b.firstChild)) {
+				sn = en = sn.firstChild;
+				so = eo = 0;
+				rb = d.createRange();
+				rb.setStart(sn, 0);
+				ra = d.createRange();
+				ra.setStart(en, 0);
+			}
+
+			// Never use body as start or end node
+			sn = sn.nodeName == "BODY" ? sn.firstChild : sn;
+			en = en.nodeName == "BODY" ? en.firstChild : en;
+
+			// Get start and end blocks
+			sb = t.getParentBlock(sn);
+			eb = t.getParentBlock(en);
+			bn = sb ? sb.nodeName : se.element; // Get block name to create
+
+			// Return inside list use default browser behavior
+			if (t.dom.getParent(sb, function(n) { return /OL|UL|PRE/.test(n.nodeName); }))
+				return true;
+
+			// If caption or absolute layers then always generate new blocks within
+			if (sb && (sb.nodeName == 'CAPTION' || /absolute|relative|static/gi.test(sb.style.position))) {
+				bn = se.element;
+				sb = null;
+			}
+
+			// If caption or absolute layers then always generate new blocks within
+			if (eb && (eb.nodeName == 'CAPTION' || /absolute|relative|static/gi.test(eb.style.position))) {
+				bn = se.element;
+				eb = null;
+			}
+
+			// Use P instead
+			if (/(TD|TABLE|TH|CAPTION)/.test(bn) || (sb && bn == "DIV" && /left|right/gi.test(sb.style.cssFloat))) {
+				bn = se.element;
+				sb = eb = null;
+			}
+
+			// Setup new before and after blocks
+			bef = (sb && sb.nodeName == bn) ? sb.cloneNode(0) : ed.dom.create(bn);
+			aft = (eb && eb.nodeName == bn) ? eb.cloneNode(0) : ed.dom.create(bn);
+
+			// Remove id from after clone
+			aft.removeAttribute('id');
+
+			// Is header and cursor is at the end, then force paragraph under
+			if (/^(H[1-6])$/.test(bn) && sn.nodeValue && so == sn.nodeValue.length)
+				aft = ed.dom.create(se.element);
+
+			// Find start chop node
+			n = sc = sn;
+			do {
+				if (n == b || n.nodeType == 9 || t.dom.isBlock(n) || /(TD|TABLE|TH|CAPTION)/.test(n.nodeName))
+					break;
+
+				sc = n;
+			} while ((n = n.previousSibling ? n.previousSibling : n.parentNode));
+
+			// Find end chop node
+			n = ec = en;
+			do {
+				if (n == b || n.nodeType == 9 || t.dom.isBlock(n) || /(TD|TABLE|TH|CAPTION)/.test(n.nodeName))
+					break;
+
+				ec = n;
+			} while ((n = n.nextSibling ? n.nextSibling : n.parentNode));
+
+			// Place first chop part into before block element
+			if (sc.nodeName == bn)
+				rb.setStart(sc, 0);
+			else
+				rb.setStartBefore(sc);
+
+			rb.setEnd(sn, so);
+			bef.appendChild(rb.cloneContents() || d.createTextNode('')); // Empty text node needed for Safari
+
+			// Place secnd chop part within new block element
+			try {
+				ra.setEndAfter(ec);
+			} catch(ex) {
+				//console.debug(s.focusNode, s.focusOffset);
+			}
+
+			ra.setStart(en, eo);
+			aft.appendChild(ra.cloneContents() || d.createTextNode('')); // Empty text node needed for Safari
+
+			// Create range around everything
+			r = d.createRange();
+			if (!sc.previousSibling && sc.parentNode.nodeName == bn) {
+				r.setStartBefore(sc.parentNode);
+			} else {
+				if (rb.startContainer.nodeName == bn && rb.startOffset == 0)
+					r.setStartBefore(rb.startContainer);
+				else
+					r.setStart(rb.startContainer, rb.startOffset);
+			}
+
+			if (!ec.nextSibling && ec.parentNode.nodeName == bn)
+				r.setEndAfter(ec.parentNode);
+			else
+				r.setEnd(ra.endContainer, ra.endOffset);
+
+			// Delete and replace it with new block elements
+			r.deleteContents();
+
+			// Never wrap blocks in blocks
+			if (bef.firstChild && bef.firstChild.nodeName == bn)
+				bef.innerHTML = bef.firstChild.innerHTML;
+
+			if (aft.firstChild && aft.firstChild.nodeName == bn)
+				aft.innerHTML = aft.firstChild.innerHTML;
+
+			// Padd empty blocks
+			if (isEmpty(bef))
+				bef.innerHTML = '<br />';
+
+			if (isEmpty(aft))
+				aft.innerHTML = isOpera ? '&nbsp;' : '<br />'; // Extra space for Opera so that the caret can move there
+
+			// Opera needs this one backwards
+			if (isOpera) {
+				r.insertNode(bef);
+				r.insertNode(aft);
+			} else {
+				r.insertNode(aft);
+				r.insertNode(bef);
+			}
+
+			// Normalize
+			aft.normalize();
+			bef.normalize();
+
+			// Move cursor and scroll into view
+			r = d.createRange();
+			r.selectNodeContents(aft);
+			r.collapse(1);
+			s.removeAllRanges();
+			s.addRange(r);
+
+			// Safari bug fix, http://bugs.webkit.org/show_bug.cgi?id=16117
+			if (tinymce.isWebKit)
+				ed.getWin().scrollTo(0, ed.dom.getPos(aft).y);
+			else
+				aft.scrollIntoView(0);
+
+			return false;
+		},
+
+		backspaceDelete : function(e, bs) {
+			var t = this, ed = t.editor, b = ed.getBody(), n, se = ed.selection, r = se.getRng(), sc = r.startContainer, n;
+
+			// The caret sometimes gets stuck in Gecko if you delete empty paragraphs
+			// This workaround removes the element by hand and moves the caret to the previous element
+			if (sc && ed.dom.isBlock(sc) && bs) {
+				if (sc.childNodes.length == 1 && sc.firstChild.nodeName == 'BR') {
+					n = sc.previousSibling;
+					if (n) { 
+						ed.dom.remove(sc);
+						se.select(n, 1);
+						se.collapse(0);
+						return Event.cancel(e);
+					}
+				}
+			}
+
+			// Gecko generates BR elements here and there, we don't like those so lets remove them
+			function handler(e) {
+				e = e.target;
+
+				// A new BR was created in a block element, remove it
+				if (e && e.parentNode && e.nodeName == 'BR' && t.getParentBlock(e)) {
+					ed.dom.remove(e);
+					Event.remove(b, 'DOMNodeInserted', handler);
+				}
+			};
+
+			// Listen for new nodes
+			Event._add(b, 'DOMNodeInserted', handler);
+
+			// Remove listener
+			window.setTimeout(function() {
+				Event._remove(b, 'DOMNodeInserted', handler);
+			}, 1);
+		}
+	});
+})();
+
+/* file:jscripts/tiny_mce/classes/ControlManager.js */
+
+(function() {
+	// Shorten names
+	var DOM = tinymce.DOM, Event = tinymce.dom.Event, each = tinymce.each, extend = tinymce.extend;
+
+	tinymce.create('tinymce.ControlManager', {
+		ControlManager : function(ed, s) {
+			var t = this, i;
+
+			s = s || {};
+			t.editor = ed;
+			t.controls = {};
+			t.onAdd = new tinymce.util.Dispatcher(t);
+			t.onPostRender = new tinymce.util.Dispatcher(t);
+			t.prefix = s.prefix || ed.id + '_';
+
+			t.onPostRender.add(function() {
+				each(t.controls, function(c) {
+					c.postRender();
+				});
+			});
+		},
+
+		get : function(id) {
+			return this.controls[this.prefix + id] || this.controls[id];
+		},
+
+		setActive : function(id, s) {
+			var c = null;
+
+			if (c = this.get(id))
+				c.setActive(s);
+
+			return c;
+		},
+
+		setDisabled : function(id, s) {
+			var c = null;
+
+			if (c = this.get(id))
+				c.setDisabled(s);
+
+			return c;
+		},
+
+		add : function(c) {
+			var t = this;
+
+			if (c) {
+				t.controls[c.id] = c;
+				t.onAdd.dispatch(c, t);
+			}
+
+			return c;
+		},
+
+		createControl : function(n) {
+			var c, t = this, ed = t.editor;
+
+			each(ed.plugins, function(p) {
+				if (p.createControl) {
+					c = p.createControl(n, t);
+
+					if (c)
+						return false;
+				}
+			});
+
+			switch (n) {
+				case "|":
+				case "separator":
+					return t.createSeparator();
+			}
+
+			if (!c && ed.buttons && (c = ed.buttons[n]))
+				return t.createButton(n, c);
+
+			return t.add(c);
+		},
+
+		createDropMenu : function(id, s) {
+			var t = this, ed = t.editor, c;
+
+			s = extend({
+				'class' : 'mceDropDown'
+			}, s);
+
+			s['class'] = s['class'] + ' ' + ed.getParam('skin') + 'Skin';
+
+			id = t.prefix + id;
+			c = t.controls[id] = new tinymce.ui.DropMenu(id, s);
+			c.onAddItem.add(function(c, o) {
+				var s = o.settings;
+
+				s.title = ed.getLang(s.title, s.title);
+
+				if (!s.onclick) {
+					s.onclick = function(v) {
+						ed.execCommand(s.cmd, s.ui || false, v || s.value);
+					};
+				}
+			});
+
+			ed.onRemove.add(function() {
+				c.destroy();
+			});
+
+			return t.add(c);
+		},
+
+		createListBox : function(id, s) {
+			var t = this, ed = t.editor, cmd, c;
+
+			if (t.get(id))
+				return null;
+
+			s.title = ed.translate(s.title);
+			s.scope = s.scope || ed;
+
+			if (!s.onselect) {
+				s.onselect = function(v) {
+					ed.execCommand(s.cmd, s.ui || false, v || s.value);
+				};
+			}
+
+			s = extend({
+				title : s.title,
+				'class' : id,
+				scope : s.scope,
+				control_manager : t
+			}, s);
+
+			id = t.prefix + id;
+
+			if (ed.settings.use_native_selects)
+				c = new tinymce.ui.NativeListBox(id, s);
+			else
+				c = new tinymce.ui.ListBox(id, s);
+
+			t.controls[id] = c;
+
+			// Fix focus problem in Safari
+			if (tinymce.isWebKit) {
+				c.onPostRender.add(function(c, n) {
+					// Store bookmark on mousedown
+					Event.add(n, 'mousedown', function() {
+						ed.bookmark = ed.selection.getBookmark('simple');
+					});
+
+					// Restore on focus, since it might be lost
+					Event.add(n, 'focus', function() {
+						ed.selection.moveToBookmark(ed.bookmark);
+						ed.bookmark = null;
+					});
+				});
+			}
+
+			if (c.hideMenu)
+				ed.onMouseDown.add(c.hideMenu, c);
+
+			return t.add(c);
+		},
+
+		createButton : function(id, s) {
+			var t = this, ed = t.editor, o, c;
+
+			if (t.get(id))
+				return null;
+
+			s.title = ed.translate(s.title);
+			s.scope = s.scope || ed;
+
+			if (!s.onclick && !s.menu_button) {
+				s.onclick = function() {
+					ed.execCommand(s.cmd, s.ui || false, s.value);
+				};
+			}
+
+			s = extend({
+				title : s.title,
+				'class' : id,
+				unavailable_prefix : ed.getLang('unavailable', ''),
+				scope : s.scope,
+				control_manager : t
+			}, s);
+
+			id = t.prefix + id;
+
+			if (s.menu_button) {
+				c = new tinymce.ui.MenuButton(id, s);
+				ed.onMouseDown.add(c.hideMenu, c);
+			} else
+				c = new tinymce.ui.Button(id, s);
+
+			return t.add(c);
+		},
+
+		createMenuButton : function(id, s) {
+			s = s || {};
+			s.menu_button = 1;
+
+			return this.createButton(id, s);
+		},
+
+		createSplitButton : function(id, s) {
+			var t = this, ed = t.editor, cmd, c;
+
+			if (t.get(id))
+				return null;
+
+			s.title = ed.translate(s.title);
+			s.scope = s.scope || ed;
+
+			if (!s.onclick) {
+				s.onclick = function(v) {
+					ed.execCommand(s.cmd, s.ui || false, v || s.value);
+				};
+			}
+
+			if (!s.onselect) {
+				s.onselect = function(v) {
+					ed.execCommand(s.cmd, s.ui || false, v || s.value);
+				};
+			}
+
+			s = extend({
+				title : s.title,
+				'class' : id,
+				scope : s.scope,
+				control_manager : t
+			}, s);
+
+			id = t.prefix + id;
+			c = t.add(new tinymce.ui.SplitButton(id, s));
+			ed.onMouseDown.add(c.hideMenu, c);
+
+			return c;
+		},
+
+		createColorSplitButton : function(id, s) {
+			var t = this, ed = t.editor, cmd, c;
+
+			if (t.get(id))
+				return null;
+
+			s.title = ed.translate(s.title);
+			s.scope = s.scope || ed;
+
+			if (!s.onclick) {
+				s.onclick = function(v) {
+					ed.execCommand(s.cmd, s.ui || false, v || s.value);
+				};
+			}
+
+			if (!s.onselect) {
+				s.onselect = function(v) {
+					ed.execCommand(s.cmd, s.ui || false, v || s.value);
+				};
+			}
+
+			s = extend({
+				title : s.title,
+				'class' : id,
+				'menu_class' : ed.getParam('skin') + 'Skin',
+				scope : s.scope,
+				more_colors_title : ed.getLang('more_colors')
+			}, s);
+
+			id = t.prefix + id;
+			c = new tinymce.ui.ColorSplitButton(id, s);
+			ed.onMouseDown.add(c.hideMenu, c);
+
+			return t.add(c);
+		},
+
+		createToolbar : function(id, s) {
+			var c, t = this;
+
+			id = t.prefix + id;
+			c = new tinymce.ui.Toolbar(id, s);
+
+			if (t.get(id))
+				return null;
+
+			return t.add(c);
+		},
+
+		createSeparator : function() {
+			return new tinymce.ui.Separator();
+		}
+
+		});
+})();
+
+/* file:jscripts/tiny_mce/classes/WindowManager.js */
+
+(function() {
+	var Dispatcher = tinymce.util.Dispatcher, each = tinymce.each, isIE = tinymce.isIE, isOpera = tinymce.isOpera;
+
+	tinymce.create('tinymce.WindowManager', {
+		WindowManager : function(ed) {
+			var t = this;
+
+			t.editor = ed;
+			t.onOpen = new Dispatcher(t);
+			t.onClose = new Dispatcher(t);
+			t.params = {};
+			t.features = {};
+		},
+
+		open : function(s, p) {
+			var t = this, f = '', x, y, mo = t.editor.settings.dialog_type == 'modal', w, sw, sh, vp = tinymce.DOM.getViewPort();
+
+			// Default some options
+			s = s || {};
+			p = p || {};
+			sw = isOpera ? vp.w : screen.width; // Opera uses windows inside the Opera window
+			sh = isOpera ? vp.h : screen.height;
+			s.name = s.name || 'mc_' + new Date().getTime();
+			s.width = parseInt(s.width || 320);
+			s.height = parseInt(s.height || 240);
+			s.resizable = true;
+			s.left = s.left || parseInt(sw / 2.0) - (s.width / 2.0);
+			s.top = s.top || parseInt(sh / 2.0) - (s.height / 2.0);
+			p.inline = false;
+			p.mce_width = s.width;
+			p.mce_height = s.height;
+
+			if (mo) {
+				if (isIE) {
+					s.center = true;
+					s.help = false;
+					s.dialogWidth = s.width + 'px';
+					s.dialogHeight = s.height + 'px';
+					s.scroll = s.scrollbars || false;
+				} else
+					s.modal = s.alwaysRaised = s.dialog = s.centerscreen = s.dependent = true;
+			}
+
+			// Build features string
+			each(s, function(v, k) {
+				if (tinymce.is(v, 'boolean'))
+					v = v ? 'yes' : 'no';
+
+				if (!/^(name|url)$/.test(k)) {
+					if (isIE && mo)
+						f += (f ? ';' : '') + k + ':' + v;
+					else
+						f += (f ? ',' : '') + k + '=' + v;
+				}
+			});
+
+			t.features = s;
+			t.params = p;
+			t.onOpen.dispatch(t, s, p);
+
+			try {
+				if (isIE && mo) {
+					w = 1;
+					window.showModalDialog(s.url || s.file, window, f);
+				} else
+					w = window.open(s.url || s.file, s.name, f);
+			} catch (ex) {
+				// Ignore
+			}
+
+			if (!w)
+				alert(t.editor.getLang('popup_blocked'));
+		},
+
+		close : function(w) {
+			w.close();
+			this.onClose.dispatch(this);
+		},
+
+		createInstance : function(cl) {
+			var a = arguments, i, f = tinymce.resolve(cl), s = '';
+
+			// Is there a better way to dynamically create
+			// a class with a dynamic number of arguments
+			for (i=1; i<a.length; i++)
+				s += (i > 1 ? ',' : '') + 'a[' + i + ']';
+
+			return eval('(new f(' + s + '))');
+		},
+
+		confirm : function(t, cb, s) {
+			cb.call(s || this, confirm(this._decode(this.editor.getLang(t, t))));
+		},
+
+		alert : function(t, cb, s) {
+			alert(this._decode(t));
+
+			if (cb)
+				cb.call(s || this);
+		},
+
+		// Internal functions
+
+		_decode : function(s) {
+			return tinymce.DOM.decode(s).replace(/\\n/g, '\n');
+		}
+
+		});
+}());
\ No newline at end of file
--- a/includes/clientside/tinymce/utils/editable_selects.js	Fri Feb 22 12:46:51 2008 -0500
+++ b/includes/clientside/tinymce/utils/editable_selects.js	Fri Feb 22 12:51:53 2008 -0500
@@ -1,10 +1,10 @@
 /**
- * $Id: editable_selects.js 162 2007-01-03 16:16:52Z spocke $
+ * $Id: editable_selects.js 520 2008-01-07 16:30:32Z spocke $
  *
  * Makes select boxes editable.
  *
  * @author Moxiecode
- * @copyright Copyright © 2004-2007, Moxiecode Systems AB, All rights reserved.
+ * @copyright Copyright © 2004-2008, Moxiecode Systems AB, All rights reserved.
  */
 
 var TinyMCE_EditableSelects = {
@@ -20,13 +20,13 @@
 				o.className = 'mceAddSelectValue';
 
 				nl[i].options[nl[i].options.length] = o;
-				nl[i].setAttribute('onchange', 'TinyMCE_EditableSelects.onChangeEditableSelect(this);');
+				nl[i].onchange = TinyMCE_EditableSelects.onChangeEditableSelect;
 			}
 		}
 	},
 
-	onChangeEditableSelect : function(se) {
-		var d = document, ne;
+	onChangeEditableSelect : function(e) {
+		var d = document, ne, se = window.event ? window.event.srcElement : e.target;
 
 		if (se.options[se.selectedIndex].value == '__mce_add_custom__') {
 			ne = d.createElement("input");
@@ -34,7 +34,7 @@
 			ne.name = se.name + "_custom";
 			ne.type = "text";
 
-			ne.style.width = se.clientWidth;
+			ne.style.width = se.offsetWidth + 'px';
 			se.parentNode.insertBefore(ne, se);
 			se.style.display = 'none';
 			ne.focus();
--- a/includes/clientside/tinymce/utils/form_utils.js	Fri Feb 22 12:46:51 2008 -0500
+++ b/includes/clientside/tinymce/utils/form_utils.js	Fri Feb 22 12:51:53 2008 -0500
@@ -1,33 +1,23 @@
 /**
- * $Id: form_utils.js 162 2007-01-03 16:16:52Z spocke $
+ * $Id: form_utils.js 520 2008-01-07 16:30:32Z spocke $
  *
  * Various form utilitiy functions.
  *
  * @author Moxiecode
- * @copyright Copyright © 2004-2007, Moxiecode Systems AB, All rights reserved.
+ * @copyright Copyright © 2004-2008, Moxiecode Systems AB, All rights reserved.
  */
 
-var themeBaseURL = tinyMCE.baseURL + '/themes/' + tinyMCE.getParam("theme");
+var themeBaseURL = tinyMCEPopup.editor.baseURI.toAbsolute('themes/' + tinyMCEPopup.getParam("theme"));
 
 function getColorPickerHTML(id, target_form_element) {
 	var h = "";
 
-	h += '<a id="' + id + '_link" href="javascript:void(0);" onkeydown="pickColor(event,\'' + target_form_element +'\');" onmousedown="pickColor(event,\'' + target_form_element +'\');return false;">';
-	h += '<img id="' + id + '" src="' + themeBaseURL + '/images/color.gif"';
-	h += ' onmouseover="this.className=\'mceButtonOver\'"';
-	h += ' onmouseout="this.className=\'mceButtonNormal\'"';
-	h += ' onmousedown="this.className=\'mceButtonDown\'"';
-	h += ' width="20" height="16" border="0" title="' + tinyMCE.getLang('lang_browse') + '"';
-	h += ' class="mceButtonNormal" alt="' + tinyMCE.getLang('lang_browse') + '" /></a>';
+	h += '<a id="' + id + '_link" href="javascript:;" onclick="tinyMCEPopup.pickColor(event,\'' + target_form_element +'\');" onmousedown="return false;" class="pickcolor">';
+	h += '<span id="' + id + '" title="' + tinyMCEPopup.getLang('browse') + '"></span></a>';
 
 	return h;
 }
 
-function pickColor(e, target_form_element) {
-	if ((e.keyCode == 32 || e.keyCode == 13) || e.type == "mousedown")
-		tinyMCEPopup.pickColor(e, target_form_element);
-}
-
 function updateColor(img_id, form_element_id) {
 	document.getElementById(img_id).style.backgroundColor = document.forms[0].elements[form_element_id].value;
 }
@@ -40,34 +30,30 @@
 		if (state) {
 			lnk.setAttribute("realhref", lnk.getAttribute("href"));
 			lnk.removeAttribute("href");
-			tinyMCE.switchClass(img, 'mceButtonDisabled', true);
+			tinyMCEPopup.dom.addClass(img, 'disabled');
 		} else {
 			lnk.setAttribute("href", lnk.getAttribute("realhref"));
-			tinyMCE.switchClass(img, 'mceButtonNormal', false);
+			tinyMCEPopup.dom.removeClass(img, 'disabled');
 		}
 	}
 }
 
 function getBrowserHTML(id, target_form_element, type, prefix) {
-	var option = prefix + "_" + type + "_browser_callback";
-	var cb = tinyMCE.getParam(option, tinyMCE.getParam("file_browser_callback"));
-	if (cb == null)
+	var option = prefix + "_" + type + "_browser_callback", cb, html;
+
+	cb = tinyMCEPopup.getParam(option, tinyMCEPopup.getParam("file_browser_callback"));
+
+	if (!cb)
 		return "";
 
-	var html = "";
-
-	html += '<a id="' + id + '_link" href="javascript:openBrower(\'' + id + '\',\'' + target_form_element + '\', \'' + type + '\',\'' + option + '\');" onmousedown="return false;">';
-	html += '<img id="' + id + '" src="' + themeBaseURL + '/images/browse.gif"';
-	html += ' onmouseover="this.className=\'mceButtonOver\';"';
-	html += ' onmouseout="this.className=\'mceButtonNormal\';"';
-	html += ' onmousedown="this.className=\'mceButtonDown\';"';
-	html += ' width="20" height="18" border="0" title="' + tinyMCE.getLang('lang_browse') + '"';
-	html += ' class="mceButtonNormal" alt="' + tinyMCE.getLang('lang_browse') + '" /></a>';
+	html = "";
+	html += '<a id="' + id + '_link" href="javascript:openBrowser(\'' + id + '\',\'' + target_form_element + '\', \'' + type + '\',\'' + option + '\');" onmousedown="return false;" class="browse">';
+	html += '<span id="' + id + '" title="' + tinyMCEPopup.getLang('browse') + '"></span></a>';
 
 	return html;
 }
 
-function openBrower(img_id, target_form_element, type, option) {
+function openBrowser(img_id, target_form_element, type, option) {
 	var img = document.getElementById(img_id);
 
 	if (img.className != "mceButtonDisabled")
@@ -119,8 +105,8 @@
 function addClassesToList(list_id, specific_option) {
 	// Setup class droplist
 	var styleSelectElm = document.getElementById(list_id);
-	var styles = tinyMCE.getParam('theme_advanced_styles', false);
-	styles = tinyMCE.getParam(specific_option, styles);
+	var styles = tinyMCEPopup.getParam('theme_advanced_styles', false);
+	styles = tinyMCEPopup.getParam(specific_option, styles);
 
 	if (styles) {
 		var stylesAr = styles.split(';');
@@ -136,10 +122,9 @@
 			}
 		}
 	} else {
-		// Use auto impored classes
-		var csses = tinyMCE.getCSSClasses(tinyMCE.getWindowArg('editor_id'));
-		for (var i=0; i<csses.length; i++)
-			styleSelectElm.options[styleSelectElm.length] = new Option(csses[i], csses[i]);
+		tinymce.each(tinyMCEPopup.editor.dom.getClasses(), function(o) {
+			styleSelectElm.options[styleSelectElm.length] = new Option(o.title || o['class'], o['class']);
+		});
 	}
 }
 
@@ -196,7 +181,7 @@
 }
 
 function getStyle(elm, attrib, style) {
-	var val = tinyMCE.getAttrib(elm, attrib);
+	var val = tinyMCEPopup.dom.getAttrib(elm, attrib);
 
 	if (val != '')
 		return '' + val;
@@ -204,7 +189,5 @@
 	if (typeof(style) == 'undefined')
 		style = attrib;
 
-	val = eval('elm.style.' + style);
-
-	return val == null ? '' : '' + val;
+	return tinyMCEPopup.dom.getStyle(elm, style);
 }
--- a/includes/clientside/tinymce/utils/mclayer.js	Fri Feb 22 12:46:51 2008 -0500
+++ b/includes/clientside/tinymce/utils/mclayer.js	Fri Feb 22 12:51:53 2008 -0500
@@ -1,10 +1,10 @@
 /**
- * $Id: mclayer.js 162 2007-01-03 16:16:52Z spocke $
+ * $Id: mclayer.js 520 2008-01-07 16:30:32Z spocke $
  *
  * Moxiecode floating layer script.
  *
  * @author Moxiecode
- * @copyright Copyright © 2004-2007, Moxiecode Systems AB, All rights reserved.
+ * @copyright Copyright © 2004-2008, Moxiecode Systems AB, All rights reserved.
  */
 
 function MCLayer(id) {
--- a/includes/clientside/tinymce/utils/mctabs.js	Fri Feb 22 12:46:51 2008 -0500
+++ b/includes/clientside/tinymce/utils/mctabs.js	Fri Feb 22 12:51:53 2008 -0500
@@ -1,10 +1,10 @@
 /**
- * $Id: mctabs.js 162 2007-01-03 16:16:52Z spocke $
+ * $Id: mctabs.js 520 2008-01-07 16:30:32Z spocke $
  *
  * Moxiecode DHTML Tabs script.
  *
  * @author Moxiecode
- * @copyright Copyright © 2004-2007, Moxiecode Systems AB, All rights reserved.
+ * @copyright Copyright © 2004-2008, Moxiecode Systems AB, All rights reserved.
  */
 
 function MCTabs() {
--- a/includes/clientside/tinymce/utils/validate.js	Fri Feb 22 12:46:51 2008 -0500
+++ b/includes/clientside/tinymce/utils/validate.js	Fri Feb 22 12:51:53 2008 -0500
@@ -1,10 +1,10 @@
 /**
- * $Id: validate.js 162 2007-01-03 16:16:52Z spocke $
+ * $Id: validate.js 520 2008-01-07 16:30:32Z spocke $
  *
  * Various form validation methods.
  *
  * @author Moxiecode
- * @copyright Copyright © 2004-2007, Moxiecode Systems AB, All rights reserved.
+ * @copyright Copyright © 2004-2008, Moxiecode Systems AB, All rights reserved.
  */
 
 /**
--- a/includes/comment.php	Fri Feb 22 12:46:51 2008 -0500
+++ b/includes/comment.php	Fri Feb 22 12:51:53 2008 -0500
@@ -2,7 +2,7 @@
 
 /*
  * Enano - an open-source CMS capable of wiki functions, Drupal-like sidebar blocks, and everything in between
- * Version 1.0.3 (Dyrad)
+ * Version 1.1.2 (Caoineag alpha 2)
  * Copyright (C) 2006-2007 Dan Fuhry
  *
  * This program is Free Software; you can redistribute and/or modify it under the terms of the GNU General Public License
@@ -64,15 +64,6 @@
   }
   
   /**
-   * PHP 4 constructor.
-   * @see Comments::__construct
-   */
-  function Comments($page_id, $namespace)
-  {
-    $this->__construct($page_id, $namespace);
-  }
-  
-  /**
    * Processes a command in JSON format.
    * @param string The JSON-encoded input, probably something sent from the Javascript/AJAX frontend
    */
@@ -80,23 +71,23 @@
   function process_json($json)
   {
     global $db, $session, $paths, $template, $plugins; // Common objects
-    $parser = new Services_JSON(SERVICES_JSON_LOOSE_TYPE);
-    $data = $parser->decode($json);
+    $data = enano_json_decode($json);
     $data = decode_unicode_array($data);
     if ( !isset($data['mode']) )
     {
       $ret = Array('mode'=>'error','error'=>'No mode defined!');
-      echo $parser->encode($ret);
+      echo enano_json_encode($ret);
       return $ret;
     }
     if ( getConfig('enable_comments') == '0' )
     {
       $ret = Array('mode'=>'error','error'=>'Comments are not enabled on this site.');
-      echo $parser->encode($ret);
+      echo enano_json_encode($ret);
       return $ret;
     }
     $ret = Array();
     $ret['mode'] = $data['mode'];
+    $ret['avatar_directory'] = getConfig('avatar_directory');
     switch ( $data['mode'] )
     {
       case 'fetch':
@@ -106,14 +97,14 @@
         {
           $ret['template'] = file_get_contents(ENANO_ROOT . '/themes/' . $template->theme . '/comment.tpl');
         }
-        $q = $db->sql_query('SELECT c.comment_id,c.name,c.subject,c.comment_data,c.time,c.approved,u.user_level,u.user_id,u.signature, b.buddy_id IS NOT NULL AS is_buddy, ( b.is_friend IS NOT NULL AND b.is_friend=1 ) AS is_friend FROM '.table_prefix.'comments AS c
+        $q = $db->sql_query('SELECT c.comment_id,c.name,c.subject,c.comment_data,c.time,c.approved,( c.ip_address IS NOT NULL ) AS have_ip,u.user_level,u.user_id,u.signature,u.user_has_avatar,u.avatar_type, b.buddy_id IS NOT NULL AS is_buddy, ( b.is_friend IS NOT NULL AND b.is_friend=1 ) AS is_friend FROM '.table_prefix.'comments AS c
                                LEFT JOIN '.table_prefix.'users AS u
                                  ON (u.user_id=c.user_id)
                                LEFT JOIN '.table_prefix.'buddies AS b
                                  ON ( ( b.user_id=' . $session->user_id.' AND b.buddy_user_id=c.user_id ) OR b.user_id IS NULL)
                                WHERE page_id=\'' . $this->page_id . '\'
                                  AND namespace=\'' . $this->namespace . '\'
-                               GROUP BY c.comment_id,c.name,c.subject,c.comment_data,c.time,c.approved,u.user_level,u.user_id,u.signature,b.buddy_id,b.is_friend
+                               GROUP BY c.comment_id,c.name,c.subject,c.comment_data,c.time,c.approved,c.ip_address,u.user_level,u.user_id,u.signature,u.user_has_avatar,u.avatar_type,b.buddy_id,b.is_friend
                                ORDER BY c.time ASC;');
         $count_appr = 0;
         $count_total = 0;
@@ -151,11 +142,14 @@
             }
             
             // Format date
-            $row['time'] = date('F d, Y h:i a', $row['time']);
+            $row['time'] = enano_date('F d, Y h:i a', $row['time']);
             
             // Format signature
             $row['signature'] = ( !empty($row['signature']) ) ? RenderMan::render($row['signature']) : '';
             
+            // Do we have the IP?
+            $row['have_ip'] = ( $row['have_ip'] == 1 );
+            
             // Add the comment to the list
             $ret['comments'][] = $row;
             
@@ -293,16 +287,19 @@
           $text = RenderMan::render($text);
           $appr = ( getConfig('approve_comments') == '1' ) ? '0' : '1';
           $time = time();
-          $date = date('F d, Y h:i a', $time);
+          $date = enano_date('F d, Y h:i a', $time);
+          $ip = $_SERVER['REMOTE_ADDR'];
+          if ( !is_valid_ip($ip) )
+            die('Hacking attempt');
           
           // Send it to the database
-          $q = $db->sql_query('INSERT INTO '.table_prefix.'comments(page_id,namespace,name,subject,comment_data,approved, time, user_id) VALUES' .
-                              "('$this->page_id', '$this->namespace', '$name', '$subj', '$sql_text', $appr, $time, $session->user_id);");
+          $q = $db->sql_query('INSERT INTO '.table_prefix.'comments(page_id,namespace,name,subject,comment_data,approved, time, user_id, ip_address) VALUES' . "\n  " .
+                             "('$this->page_id', '$this->namespace', '$name', '$subj', '$sql_text', $appr, $time, {$session->user_id}, '$ip');");
           if(!$q)
             $db->die_json();
           
           // Re-fetch
-          $q = $db->sql_query('SELECT c.comment_id,c.name,c.subject,c.comment_data,c.time,c.approved,u.user_level,u.user_id,u.signature FROM '.table_prefix.'comments AS c
+          $q = $db->sql_query('SELECT c.comment_id,c.name,c.subject,c.comment_data,c.time,c.approved,u.user_level,u.user_id,u.signature,u.user_has_avatar,u.avatar_type FROM '.table_prefix.'comments AS c
                                LEFT JOIN '.table_prefix.'users AS u
                                  ON (u.user_id=c.user_id)
                                WHERE page_id=\'' . $this->page_id . '\'
@@ -334,7 +331,7 @@
           $ret['user_level_list']['member'] = USER_LEVEL_MEMBER;
           $ret['user_level_list']['mod'] = USER_LEVEL_MOD;
           $ret['user_level_list']['admin'] = USER_LEVEL_ADMIN;
-          
+          $ret['avatar_directory'] = getConfig('avatar_directory');
         }
         
         break;
@@ -345,7 +342,7 @@
           'mode' => 'error', 
           'error' => 'You are not authorized to moderate comments.'
           );
-          echo $parser->encode($ret);
+          echo enano_json_encode($ret);
           return $ret;
         }
         
@@ -375,6 +372,45 @@
           );
         
         break;
+      case 'view_ip':
+        if ( !$session->get_permissions('mod_comments') )
+        {
+          return array(
+              'mode' => 'error',
+              'error' => 'Unauthorized'
+            );
+        }
+        // fetch comment info
+        if ( !is_int($data['id']) )
+        {
+          return array(
+              'mode' => 'error',
+              'error' => 'Unauthorized'
+            );
+        }
+        $id =& $data['id'];
+        $q = $db->sql_query('SELECT ip_address, name FROM ' . table_prefix . 'comments WHERE comment_id = ' . $id . ';');
+        if ( !$q || $db->numrows() < 1 )
+        {
+          $db->die_json();
+        }
+        list($ip_addr, $name) = $db->fetchrow_num($q);
+        $db->free_result();
+        $name = $db->escape($name);
+        $username = $db->escape($session->username);
+        // log this action
+        $q = $db->sql_query('INSERT INTO ' . table_prefix . "logs(time_id, log_type, action, page_text, author, edit_summary) VALUES\n  "
+                            . "( " . time() . ", 'security', 'view_comment_ip', '$name', '$username', '{$_SERVER['REMOTE_ADDR']}' );");
+        if ( !$q )
+          $db->die_json();
+        
+        // send packet
+        $ret = array(
+            'mode' => 'redraw',
+            'ip_addr' => $ip_addr,
+            'local_id' => $data['local_id']
+          );
+        break;
       default:
         $ret = Array(
           'mode' => 'error', 
@@ -382,7 +418,7 @@
           );
         break;
     }
-    echo $parser->encode($ret);
+    echo enano_json_encode($ret);
     return $ret;
   }
   
--- a/includes/common.php	Fri Feb 22 12:46:51 2008 -0500
+++ b/includes/common.php	Fri Feb 22 12:51:53 2008 -0500
@@ -2,7 +2,7 @@
 
 /*
  * Enano - an open-source CMS capable of wiki functions, Drupal-like sidebar blocks, and everything in between
- * Version 1.0.3 (Dyrad)
+ * Version 1.1.1
  * Copyright (C) 2006-2007 Dan Fuhry
  *
  * This program is Free Software; you can redistribute and/or modify it under the terms of the GNU General Public License
@@ -37,7 +37,7 @@
 // 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.0.3';
+$version = '1.1.3';
 
 /**
  * Returns a floating-point number with the current UNIX timestamp in microseconds. Defined very early because we gotta call it
@@ -95,12 +95,6 @@
 if ( !defined('ENANO_ROOT') )
   define('ENANO_ROOT', dirname(dirname($filename)));
 
-// 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.');
-}
-
 // 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
@@ -118,6 +112,7 @@
 require_once(ENANO_ROOT.'/includes/sessions.php');
 require_once(ENANO_ROOT.'/includes/template.php');
 require_once(ENANO_ROOT.'/includes/plugins.php');
+require_once(ENANO_ROOT.'/includes/lang.php');
 require_once(ENANO_ROOT.'/includes/comment.php');
 require_once(ENANO_ROOT.'/includes/wikiformat.php');
 require_once(ENANO_ROOT.'/includes/diff.php');
@@ -129,12 +124,15 @@
 require_once(ENANO_ROOT.'/includes/email.php');
 require_once(ENANO_ROOT.'/includes/search.php');
 require_once(ENANO_ROOT.'/includes/json.php');
+require_once(ENANO_ROOT.'/includes/json2.php');
 require_once(ENANO_ROOT.'/includes/wikiengine/Tables.php');
 require_once(ENANO_ROOT.'/includes/pageprocess.php');
 require_once(ENANO_ROOT.'/includes/tagcloud.php');
 
 strip_magic_quotes_gpc();
 
+profiler_log('Files included and magic_quotes_gpc reversed if applicable');
+
 // 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.
@@ -148,6 +146,13 @@
 // Jim Tucek's e-mail encryption code                      
 global $email;
 
+// Language object
+global $lang;
+
+// Timezone offset
+global $timezone;
+$timezone = 0;
+
 // 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']) )
@@ -165,7 +170,8 @@
 // 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.
 
-@include(ENANO_ROOT . '/config.php');
+$config_file = ( defined('IN_ENANO_INSTALL') ) ? '/config.new.php' : '/config.php';
+@include(ENANO_ROOT . $config_file);
 unset($dbuser, $dbpasswd);
 if ( !isset($dbdriver) )
   $dbdriver = 'mysql';
@@ -173,6 +179,8 @@
 $db = new $dbdriver();
 $db->connect();
 
+profiler_log('Database connected');
+
 // 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.
@@ -190,7 +198,7 @@
       unset($_COOKIE['sid']);
       setcookie('sid', '', time()-3600*24, scriptPath);
       setcookie('sid', '', time()-3600*24, scriptPath.'/');
-      die('Session cookie cleared. <a href="'.$_SERVER['PHP_SELF'].'">Continue</a>');
+      die('Session cookie cleared. <a href="'.htmlspecialchars($_SERVER['PHP_SELF']).'">Continue</a>');
       break;
   }
 }
@@ -213,10 +221,12 @@
 
 $db->free_result();
 
+profiler_log('Config fetched');
+
 // Now that we have the config, check the Enano version.
-if ( enano_version(false, true) != $version )
+if ( enano_version(false, true) != $version && !defined('IN_ENANO_UPGRADE') )
 {
-  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>');
+  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.'/install/upgrade.php">upgrade</a>?</p>');
 }
 
 //
@@ -249,32 +259,28 @@
   }
 }
 
-// Our list of tables included in Enano
-$system_table_list = Array(
-    table_prefix.'categories',
-    table_prefix.'comments',
-    table_prefix.'config',
-    table_prefix.'logs',
-    table_prefix.'page_text',
-    table_prefix.'session_keys',
-    table_prefix.'pages',
-    table_prefix.'users',
-    table_prefix.'users_extra',
-    table_prefix.'themes',
-    table_prefix.'buddies',
-    table_prefix.'banlist',
-    table_prefix.'files',
-    table_prefix.'privmsgs',
-    table_prefix.'sidebar',
-    table_prefix.'hits',
-    table_prefix.'search_index',
-    table_prefix.'groups',
-    table_prefix.'group_members',
-    table_prefix.'acl',
-    table_prefix.'page_groups',
-    table_prefix.'page_group_members',
-    table_prefix.'tags'
-  );
+// Is there no default language?
+if ( getConfig('default_language') === false && !defined('IN_ENANO_MIGRATION') )
+{
+  $q = $db->sql_query('SELECT lang_id FROM '.table_prefix.'language LIMIT 1;');
+  if ( !$q )
+    $db->_die('common.php - setting default language');
+  if ( $db->numrows() < 1 && !defined('ENANO_ALLOW_LOAD_NOLANG') )
+  {
+    grinding_halt('No languages', '<p>There are no languages installed on this site.</p>
+        <p>If you are the website administrator, you may install a language by writing and executing a simple PHP script to install it:</p>
+        <pre>
+&lt;?php
+define("ENANO_ALLOW_LOAD_NOLANG", 1);
+$_GET["title"] = "langinstall";
+require("includes/common.php");
+install_language("eng", "English", "English", ENANO_ROOT . "/language/english/enano.json");</pre>');
+  }
+  $row = $db->fetchrow();
+  setConfig('default_language', $row['lang_id']);
+}
+
+profiler_log('Ran checks');
 
 // Load plugin manager
 $plugins = new pluginLoader();
@@ -291,15 +297,20 @@
 // Load plugins from common because we can't give plugins full abilities in object context
 foreach ( $plugins->load_list as $f )
 {
-  include_once $f;
+  if ( file_exists($f) )
+    include_once $f;
 }
 
+profiler_log('Loaded plugins');
+
 // 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();
 
+profiler_log('Instanciated important singletons');
+
 // 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', '');
 
@@ -317,6 +328,8 @@
     eval($cmd);
   }
   
+  profiler_log('Finished base_classes_initted hook');
+  
   // 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());
@@ -325,6 +338,8 @@
     @call_user_func('page_'.$p[1].'_'.$p[0].'_preloader');
   }
   
+  profiler_log('Checked for preloader');
+  
   // One quick security check...
   if ( !is_valid_ip($_SERVER['REMOTE_ADDR']) )
   {
@@ -333,6 +348,19 @@
 
   // All checks passed! Start the main components up.  
   $session->start();
+  
+  // This is where plugins will want to add pages from 1.1.x on out. You can still add
+  // pages at base_classes_initted but the titles won't be localized. This is because
+  // the session manager has to be started before localization will work in the user's
+  // preferred language.
+  $code = $plugins->setHook('session_started');
+  foreach ( $code as $cmd )
+  {
+    eval($cmd);
+  }
+  
+  profiler_log('Ran session_started hook');
+  
   $paths->init();
   
   // We're ready for whatever life throws us now.
@@ -367,19 +395,21 @@
     $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');
+  // At this point all of Enano is fully initialized and running and you're ready to do whatever you want.
+  $code = $plugins->setHook('common_post');
   foreach ( $code as $cmd )
   {
     eval($cmd);
   }
   
+  profiler_log('Ran disabled-site checks and common_post');
+  
   if ( isset($_GET['noheaders']) )
     $template->no_headers = true;
 }
 
+profiler_log('common finished');
+
 // That's the end. Enano should be loaded now :-)
 
 ?>
--- a/includes/constants.php	Fri Feb 22 12:46:51 2008 -0500
+++ b/includes/constants.php	Fri Feb 22 12:51:53 2008 -0500
@@ -2,7 +2,7 @@
 
 /*
  * Enano - an open-source CMS capable of wiki functions, Drupal-like sidebar blocks, and everything in between
- * Version 1.0.3 (Dyrad)
+ * Version 1.1.2 (Caoineag alpha 2)
  * Copyright (C) 2006-2007 Dan Fuhry
  * constants.php - important defines used Enano-wide
  *
@@ -39,6 +39,9 @@
 define('PAGE_GRP_NORMAL', 3);
 define('PAGE_GRP_REGEX', 4);
 
+// Identifier for the default meta-language
+define('LANG_DEFAULT', 0);
+
 //
 // User types - don't touch these
 //
@@ -65,11 +68,21 @@
 define('GROUP_HIDDEN', 3);
 define('GROUP_OPEN', 4);
 
+// Private message flags
+define('PM_UNREAD', 1);
+define('PM_STARRED', 2);
+define('PM_SENT', 4);
+define('PM_DRAFT', 8);
+define('PM_ARCHIVE', 16);
+define('PM_TRASH', 32);
+define('PM_DELIVERED', 64);
+
 // Other stuff
 
 define('MAX_PMS_PER_BATCH', 7); // The maximum number of users that users can send PMs to in one go; restriction does not apply to users with mod_misc rights
 define('SEARCH_RESULTS_PER_PAGE', 10);
 define('MYSQL_MAX_PACKET_SIZE', 1048576); // 1MB; this is the default in MySQL 4.x I think
+define('ENANO_SUPPORT_AVATARS', 1);
 
 // Sidebar
 
@@ -85,6 +98,18 @@
 define('GENERAL_NOTICE', 'Information');
 define('CRITICAL_ERROR', 'Critical error');
 
+//
+// Enano versions progress
+//
+
+// These constants are used to perform "at least version X" type logic in plugins. Constants should
+// be defined as ENANO_ATLEAST_<major version>_<minor version>, and they should match the version of
+// the Enano API, not any forked version. This is to ensure that plugins know what features to enable
+// and disable for compatibility with both branches.
+
+define('ENANO_ATLEAST_1_0', '');
+define('ENANO_ATLEAST_1_1', '');
+
 // You can un-comment the next line to require database backups to be encrypted using the site's unique key.
 // This keeps the file safe in transit, but also prevents any type of editing to the file. This is NOT
 // recommended except for tiny sites because encrypting an average of 2MB of data will take a while.
@@ -112,8 +137,48 @@
 //   define('AES_BLOCKSIZE', AES_BITS);
 // }
 
+// You probably don't want to change the block size because it will cause the Javascript test vectors to fail. Changing it doesn't
+// significantly increase encryption strength either.
 define('AES_BLOCKSIZE', 128);
 
+// Our list of tables included in Enano
+$system_table_list = Array(
+    'categories',
+    'comments',
+    'config',
+    'logs',
+    'page_text',
+    'session_keys',
+    'pages',
+    'users',
+    'users_extra',
+    'themes',
+    'buddies',
+    'banlist',
+    'files',
+    'privmsgs',
+    'sidebar',
+    'hits',
+    'groups',
+    'group_members',
+    'acl',
+    'page_groups',
+    'page_group_members',
+    'tags',
+    'language',
+    'language_strings',
+    'lockout',
+    'search_index'
+  );
+
+if ( defined('table_prefix') )
+{
+  foreach ( $system_table_list as $i => $_ )
+  {
+    $system_table_list[$i] = table_prefix . $system_table_list[$i];
+  }
+}
+
 /*
  * MIMETYPES
  *
@@ -457,3 +522,38 @@
 }
 
 unset($k, $s, $x);
+
+/******************************************************************************
+* Global Variable:      JPEG_Segment_Names
+*
+* Contents:     The names of the JPEG segment markers, indexed by their marker number. This data is from the PHP JPEG Metadata Toolkit. Licensed under the GPLv2 or later.
+*
+******************************************************************************/
+
+$GLOBALS[ "JPEG_Segment_Names" ] = array(
+  0xC0 =>  "SOF0",  0xC1 =>  "SOF1",  0xC2 =>  "SOF2",  0xC3 =>  "SOF4",
+  0xC5 =>  "SOF5",  0xC6 =>  "SOF6",  0xC7 =>  "SOF7",  0xC8 =>  "JPG",
+  0xC9 =>  "SOF9",  0xCA =>  "SOF10", 0xCB =>  "SOF11", 0xCD =>  "SOF13",
+  0xCE =>  "SOF14", 0xCF =>  "SOF15",
+  0xC4 =>  "DHT",   0xCC =>  "DAC",
+  
+  0xD0 =>  "RST0",  0xD1 =>  "RST1",  0xD2 =>  "RST2",  0xD3 =>  "RST3",
+  0xD4 =>  "RST4",  0xD5 =>  "RST5",  0xD6 =>  "RST6",  0xD7 =>  "RST7",
+  
+  0xD8 =>  "SOI",   0xD9 =>  "EOI",   0xDA =>  "SOS",   0xDB =>  "DQT",
+  0xDC =>  "DNL",   0xDD =>  "DRI",   0xDE =>  "DHP",   0xDF =>  "EXP",
+  
+  0xE0 =>  "APP0",  0xE1 =>  "APP1",  0xE2 =>  "APP2",  0xE3 =>  "APP3",
+  0xE4 =>  "APP4",  0xE5 =>  "APP5",  0xE6 =>  "APP6",  0xE7 =>  "APP7",
+  0xE8 =>  "APP8",  0xE9 =>  "APP9",  0xEA =>  "APP10", 0xEB =>  "APP11",
+  0xEC =>  "APP12", 0xED =>  "APP13", 0xEE =>  "APP14", 0xEF =>  "APP15",
+  
+  
+  0xF0 =>  "JPG0",  0xF1 =>  "JPG1",  0xF2 =>  "JPG2",  0xF3 =>  "JPG3",
+  0xF4 =>  "JPG4",  0xF5 =>  "JPG5",  0xF6 =>  "JPG6",  0xF7 =>  "JPG7",
+  0xF8 =>  "JPG8",  0xF9 =>  "JPG9",  0xFA =>  "JPG10", 0xFB =>  "JPG11",
+  0xFC =>  "JPG12", 0xFD =>  "JPG13",
+  
+  0xFE =>  "COM",   0x01 =>  "TEM",   0x02 =>  "RES",
+);
+
--- a/includes/dbal.php	Fri Feb 22 12:46:51 2008 -0500
+++ b/includes/dbal.php	Fri Feb 22 12:51:53 2008 -0500
@@ -2,7 +2,7 @@
 
 /*
  * Enano - an open-source CMS capable of wiki functions, Drupal-like sidebar blocks, and everything in between
- * Version 1.0.3 (Dyrad)
+ * Version 1.1.1
  * Copyright (C) 2006-2007 Dan Fuhry
  *
  * This program is Free Software; you can redistribute and/or modify it under the terms of the GNU General Public License
@@ -41,6 +41,8 @@
   
   function enable_errorhandler()
   {
+    if ( !defined('ENANO_DEBUG') )
+      return true;
     // echo "DBAL: enabling error handler<br />";
     if ( function_exists('debug_backtrace') )
     {
@@ -50,6 +52,8 @@
   
   function disable_errorhandler()
   {
+    if ( !defined('ENANO_DEBUG') )
+      return true;
     // echo "DBAL: disabling error handler<br />";
     if ( $this->errhandler )
     {
@@ -163,9 +167,14 @@
           define('scriptPath', $sp);
           define('contentPath', "$sp/index.php?title=");
         }
-        $loc = scriptPath . '/install.php';
+        $loc = scriptPath . '/install/index.php';
+        define('IN_ENANO_INSTALL', 1);
+        $GLOBALS['lang'] = new Language('eng');
+        global $lang;
+        $lang->load_file('./language/english/core.json');
+        $lang->load_file('./language/english/install.json');
         // header("Location: $loc");
-        redirect($loc, 'Enano not installed', 'We can\'t seem to find an Enano installation (valid config file). You will be transferred to the installation wizard momentarily...', 3);
+        redirect($loc, 'Enano not installed', 'We can\'t seem to find an Enano installation (valid config file). You will be transferred to the installation wizard momentarily...', 0);
         exit;
       }
     }
@@ -174,10 +183,14 @@
     unset($dbuser);
     unset($dbpasswd); // Security
     
-    if ( !$this->_conn )
+    if ( !$this->_conn && !$manual_credentials )
     {
       grinding_halt('Enano is having a problem', '<p>Error: couldn\'t connect to MySQL.<br />'.mysql_error().'</p>');
     }
+    else if ( !$this->_conn && $manual_credentials )
+    {
+      return false;
+    }
     
     // Reset some variables
     $this->query_backtrace = array();
@@ -190,16 +203,21 @@
     $q = $this->sql_query('USE `'.$dbname.'`;');
     
     if ( !$q )
+    {
+      if ( $manual_credentials )
+        return false;
       $this->_die('The database could not be selected.');
+    }
     
     // We're in!
     $this->disable_errorhandler();
     return true;
   }
   
-  function sql_query($q)
+  function sql_query($q, $log_query = true)
   {
-    $this->enable_errorhandler();
+    if ( $log_query || defined('ENANO_DEBUG') )
+      $this->enable_errorhandler();
     
     if ( $this->debug && function_exists('debug_backtrace') )
     {
@@ -220,34 +238,48 @@
     }
     
     $this->num_queries++;
-    $this->query_backtrace[] = $q;
-    $this->latest_query = $q;
+    if ( $log_query || defined('ENANO_DEBUG') )
+    {
+      $this->query_backtrace[] = $q;
+      $this->latest_query = $q;
+    }
     // First make sure we have a connection
     if ( !$this->_conn )
     {
       $this->_die('A database connection has not yet been established.');
     }
+    // Start the timer
+    if ( $log_query || defined('ENANO_DEBUG') )
+      $time_start = microtime_float();
     // Does this query look malicious?
-    if ( !$this->check_query($q) )
+    if ( $log_query || defined('ENANO_DEBUG') )
     {
-      $this->report_query($q);
-      grinding_halt('SQL Injection attempt', '<p>Enano has caught and prevented an SQL injection attempt. Your IP address has been recorded and the administrator has been notified.</p><p>Query was:</p><pre>'.htmlspecialchars($q).'</pre>');
+      if ( !$this->check_query($q) )
+      {
+        $this->report_query($q);
+        grinding_halt('SQL Injection attempt', '<p>Enano has caught and prevented an SQL injection attempt. Your IP address has been recorded and the administrator has been notified.</p><p>Query was:</p><pre>'.htmlspecialchars($q).'</pre>');
+      }
     }
     
-    $time_start = microtime_float();
     $r = mysql_query($q, $this->_conn);
-    $this->query_times[$q] = microtime_float() - $time_start;
+    
+    if ( $log_query )
+      $this->query_times[$q] = microtime_float() - $time_start;
+    
     $this->latest_result = $r;
-    $this->disable_errorhandler();
+    
+    if ( $log_query )
+      $this->disable_errorhandler();
     return $r;
   }
   
-  function sql_unbuffered_query($q)
+  function sql_unbuffered_query($q, $log_query = true)
   {
     $this->enable_errorhandler();
     
     $this->num_queries++;
-    $this->query_backtrace[] = '(UNBUFFERED) ' . $q;
+    if ( $log_query || defined('ENANO_DEBUG') )
+      $this->query_backtrace[] = '(UNBUFFERED) ' . $q;
     $this->latest_query = $q;
     // First make sure we have a connection
     if ( !$this->_conn )
@@ -449,7 +481,7 @@
       $this->disable_errorhandler();
       return null;
     }
-    mysql_free_result($result);
+    @mysql_free_result($result);
     $this->disable_errorhandler();
     return null;
   }
@@ -469,7 +501,7 @@
     if(!$this->_conn) return false;
     if(!$r) $r = $this->latest_result;
     if(!$r) $this->_die('$db->fetchrow(): an invalid MySQL resource was passed.');
-    mysql_free_result($r);
+    @mysql_free_result($r);
   }
   function sql_numrows($r = false)
   {
@@ -672,14 +704,7 @@
 
 	function sql_error()
 	{
-		if ( $this->_conn )
-		{
-			return mysql_error();
-		}
-		else
-		{
-			return array();
-		}
+    return mysql_error();
 	}
   function sql_escape_string($t) 
   {
@@ -860,7 +885,7 @@
   }
   
   function get_error($t = '') {
-    header('HTTP/1.1 500 Internal Server Error');
+    @header('HTTP/1.1 500 Internal Server Error');
     $bt = $this->sql_backtrace();
     $e = htmlspecialchars(pg_last_error());
     if($e=='') $e='&lt;none&gt;';
@@ -928,10 +953,14 @@
     unset($dbuser);
     unset($dbpasswd); // Security
     
-    if ( !$this->_conn )
+    if ( !$this->_conn && !$manual_credentials )
     {
       grinding_halt('Enano is having a problem', '<p>Error: couldn\'t connect to PostgreSQL.<br />'.pg_last_error().'</p>');
     }
+    else if ( !$this->_conn && $manual_credentials )
+    {
+      return false;
+    }
     
     // Reset some variables
     $this->query_backtrace = array();
@@ -1198,7 +1227,7 @@
       $this->disable_errorhandler();
       return null;
     }
-    pg_free_result($result);
+    @pg_free_result($result);
     $this->disable_errorhandler();
     return null;
   }
@@ -1420,11 +1449,11 @@
 	{
 		if ( $this->_conn )
 		{
-			return mysql_error();
+			return pg_last_error();
 		}
 		else
 		{
-			return array();
+			return ( defined('IN_ENANO_INSTALL') ) ? $GLOBALS["lang"]->get('dbpgsql_msg_err_auth') : 'Access to the database was denied. Ensure that your database exists and that your username and password are correct.';
 		}
 	}
   function sql_escape_string($t) 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/includes/diffiehellman.php	Fri Feb 22 12:51:53 2008 -0500
@@ -0,0 +1,450 @@
+<?php
+
+/*
+ * Enano - an open-source CMS capable of wiki functions, Drupal-like sidebar blocks, and everything in between
+ * Version 1.1.2 (Caoineag alpha 2)
+ * Copyright (C) 2006-2007 Dan Fuhry
+ * diffiehellman.php - Diffie Hellman key exchange and supporting functions
+ *
+ * This program is Free Software; you can redistribute and/or modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.
+ *
+ * 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.
+ */
+
+/**
+ * Class to handle math operations that require the use of >32-bit integers.
+ */
+
+class EnanoMath
+{
+  
+  var $api = 'gmp';
+  var $limb = 16;
+  
+  function __construct()
+  {
+    /*
+    // big_int support is untested.
+    if ( extension_loaded('big_int') )
+    {
+      $this->api = 'bigint';
+    }
+    else
+    */
+    if ( function_exists('gmp_init') )
+    {
+      $this->api = 'gmp';
+    }
+    else if ( function_exists('bcpow') )
+    {
+      $this->api = 'bcmath';
+    }
+    else
+    {
+      throw new Exception('dh_err_not_supported');
+    }
+  }
+  
+  function powmod($base, $pow, $mod)
+  {
+    switch($this->api)
+    {
+      case 'bigint':
+        return ( pow($base, $pow) % $mod );
+        break;
+      case 'gmp':
+        return ( function_exists('gmp_powm') ) ? gmp_powm($base, $pow, $mod) : gmp_mod(gmp_pow($base, $pow), $mod);
+        break;
+      case 'bcmath':
+        return ( function_exists('bcpowmod') ) ? bcpowmod($base, $pow, $mod) : bcmod( bcpow($base, $pow), $mod );
+        break;
+    }
+  }
+  
+  function random($len)
+  {
+    switch($this->api)
+    {
+      case 'gmp':
+        return gmp_random($len);
+        break;
+      case 'bcmath':
+        return $this->_bcmath_random($len);
+        break;
+      case 'bigint':
+        return $this->_bigint_random($len);
+        break;
+    }
+  }
+  
+  function _bcmath_random($len)
+  {
+    $len = ( $this->limb / 2 ) * $len;
+    $chars = '0123456789abcdef';
+    $ret = '';
+    for ( $i = 0; $i < $len; $i++ )
+    {
+      $chid = mt_rand ( 0, strlen($chars) - 1 );
+      $chr = $chars{$chid};
+      $ret .= $chr;
+    }
+    return $this->basecon($ret, 16, 10);
+  }
+  
+  function _bigint_random($len)
+  {
+    $len = ( $this->limb / 2 ) * $len;
+    $chars = '0123456789abcdef';
+    $ret = '';
+    for ( $i = 0; $i < $len; $i++ )
+    {
+      $chid = mt_rand ( 0, strlen($chars) - 1 );
+      $chr = $chars{$chid};
+      $ret .= $chr;
+    }
+    return $this->basecon($ret, 16, 10);
+  }
+  
+  function basecon($int, $from, $to)
+  {
+    switch($this->api)
+    {
+      case 'gmp':
+        return gmp_strval(gmp_init($int, $from), $to);
+        break;
+      case 'bcmath':
+        return $this->_bcmath_baseconv($int, $from, $to);
+        break;
+      case 'bigint':
+        return base_convert($int, $from, $to);
+        break;
+    }
+  }
+  
+  function str($res, $base = 10)
+  {
+    switch($this->api)
+    {
+      case 'bigint':
+      case 'bcmath':
+        return strval($this->basecon($res, 10, $base));
+        break;
+      case 'gmp':
+        return gmp_strval($res, $base);
+        break;
+    }
+  }
+  
+  function compare($v1, $v2)
+  {
+    switch($this->api)
+    {
+      case 'bigint':
+        return ( $v1 === $v2 );
+        break;
+      case 'bcmath':
+        return ( bccomp($v1, $v2) === 0 );
+        break;
+      case 'gmp':
+        return ( gmp_cmp($v1, $v2) === 0 );
+        break;
+    }
+  }
+  
+  function _bcmath_baseconv($int, $from, $to)
+  {
+    if ( $from != 10 )
+      $int = $this->_bcmath_base2dec($int, $from);
+    if ( $to != 10 )
+      $int = $this->_bcmath_dec2base($int, $to);
+    return $int;
+  }
+  
+  // from us.php.net/bc:
+  // convert a decimal value to any other base value
+  function _bcmath_dec2base($dec,$base,$digits=FALSE) {
+      if($base<2 or $base>256) die("Invalid Base: ".$base);
+      bcscale(0);
+      $value="";
+      if(!$digits) $digits=$this->_bcmath_digits($base);
+      while($dec>$base-1) {
+          $rest=bcmod($dec,$base);
+          $dec=bcdiv($dec,$base);
+          $value=$digits[$rest].$value;
+      }
+      $value=$digits[intval($dec)].$value;
+      return (string) $value;
+  }
+  
+  // convert another base value to its decimal value
+  function _bcmath_base2dec($value,$base,$digits=FALSE) {
+      if($base<2 or $base>256) die("Invalid Base: ".$base);
+      bcscale(0);
+      if($base<37) $value=strtolower($value);
+      if(!$digits) $digits=$this->_bcmath_digits($base);
+      $size=strlen($value);
+      $dec="0";
+      for($loop=0;$loop<$size;$loop++) {
+          $element=strpos($digits,$value[$loop]);
+          $power=bcpow($base,$size-$loop-1);
+          $dec=bcadd($dec,bcmul($element,$power));
+      }
+      return (string) $dec;
+  }
+  
+  function _bcmath_digits($base) {
+      if($base>64) {
+          $digits="";
+          for($loop=0;$loop<256;$loop++) {
+              $digits.=chr($loop);
+          }
+      } else {
+          $digits ="0123456789abcdefghijklmnopqrstuvwxyz";
+          $digits.="ABCDEFGHIJKLMNOPQRSTUVWXYZ-_";
+      }
+      $digits=substr($digits,0,$base);
+      return (string) $digits;
+  }
+}
+
+/**
+ * The Diffie-Hellman key exchange protocol
+ */
+
+$GLOBALS['_math'] = new EnanoMath();
+// Our prime number as a base for operations.
+$GLOBALS['dh_prime'] = '82818079787776757473727170696867666564636261605958575655545352515049484746454443424140393837363534333231302928272625242322212019181716151413121110987654321';
+
+// g, a primitive root used as an exponent
+// (2 and 5 are acceptable, but BigInt is faster with odd numbers)
+$GLOBALS['dh_g'] = '5';
+
+/**
+ * Generates a Diffie-Hellman private key
+ * @return string(BigInt)
+ */
+
+function dh_gen_private()
+{
+  global $_math;
+  return $_math->random(256);
+}
+
+/**
+ * Calculates the public key from the private key
+ * @param string(BigInt)
+ * @return string(BigInt)
+ */
+
+function dh_gen_public($b)
+{
+  global $_math, $dh_g, $dh_prime;
+  return $_math->powmod($dh_g, $b, $dh_prime);
+}
+
+/**
+ * Calculates the shared secret.
+ * @param string(BigInt) Our private key
+ * @param string(BigInt) Remote party's public key
+ * @return string(BigInt)
+ */
+
+function dh_gen_shared_secret($a, $B)
+{
+  global $_math, $dh_g, $dh_prime;
+  return $_math->powmod($B, $a, $dh_prime);
+}
+
+/*
+SHA-256 algorithm - ported from Javascript
+
+Copyright (c) 2003-2004, Angel Marin
+All rights reserved.
+Portions copyright (c) 2008 Dan Fuhry.
+
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice, this
+   list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright notice,
+   this list of conditions and the following disclaimer in the documentation
+   and/or other materials provided with the distribution.
+ * Neither the name of the <ORGANIZATION> nor the names of its contributors may
+   be used to endorse or promote products derived from this software without
+   specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+class SHA256
+{
+  var $chrsz = 8;  /* bits per input character. 8 - ASCII; 16 - Unicode  */
+  
+  function safe_add ($x, $y) {
+    $lsw = ($x & 0xFFFF) + ($y & 0xFFFF);
+    $msw = ($x >> 16) + ($y >> 16) + ($lsw >> 16);
+    return ($msw << 16) | ($lsw & 0xFFFF);
+  }
+  function rshz($X, $n)
+  {
+    // equivalent to $X >>> $n in javascript
+    // pulled from http://www.tapouillo.com/firefox_extension/sourcecode.txt, public domain
+    $z = hexdec(80000000); 
+    if ($z & $X) 
+    { 
+        $X = ($X>>1); 
+        $X &= (~$z); 
+        $X |= 0x40000000; 
+        $X = ($X>>($n-1)); 
+    } 
+    else 
+    { 
+        $X = ($X>>$n); 
+    } 
+    return $X; 
+  }
+  function S ($X, $n) {return ( $this->rshz($X, $n) ) | ($X << (32 - $n));}
+  function R ($X, $n) {return ( $this->rshz($X, $n) );}
+  function Ch($x, $y, $z)  {return (($x & $y) ^ ((~$x) & $z));}
+  function Maj($x, $y, $z) {return (($x & $y) ^ ($x & $z) ^ ($y & $z));}
+  function Sigma0256($x) {return ($this->S($x, 2)  ^ $this->S($x, 13) ^ $this->S($x, 22));}
+  function Sigma1256($x) {return ($this->S($x, 6)  ^ $this->S($x, 11) ^ $this->S($x, 25));}
+  function Gamma0256($x) {return ($this->S($x, 7)  ^ $this->S($x, 18) ^ $this->R($x, 3));}
+  function Gamma1256($x) {return ($this->S($x, 17) ^ $this->S($x, 19) ^ $this->R($x, 10));}
+  function core_sha256 ($m, $l) {
+      $K = Array(0x428A2F98,0x71374491,0xB5C0FBCF,0xE9B5DBA5,0x3956C25B,0x59F111F1,0x923F82A4,0xAB1C5ED5,0xD807AA98,0x12835B01,0x243185BE,0x550C7DC3,0x72BE5D74,0x80DEB1FE,0x9BDC06A7,0xC19BF174,0xE49B69C1,0xEFBE4786,0xFC19DC6,0x240CA1CC,0x2DE92C6F,0x4A7484AA,0x5CB0A9DC,0x76F988DA,0x983E5152,0xA831C66D,0xB00327C8,0xBF597FC7,0xC6E00BF3,0xD5A79147,0x6CA6351,0x14292967,0x27B70A85,0x2E1B2138,0x4D2C6DFC,0x53380D13,0x650A7354,0x766A0ABB,0x81C2C92E,0x92722C85,0xA2BFE8A1,0xA81A664B,0xC24B8B70,0xC76C51A3,0xD192E819,0xD6990624,0xF40E3585,0x106AA070,0x19A4C116,0x1E376C08,0x2748774C,0x34B0BCB5,0x391C0CB3,0x4ED8AA4A,0x5B9CCA4F,0x682E6FF3,0x748F82EE,0x78A5636F,0x84C87814,0x8CC70208,0x90BEFFFA,0xA4506CEB,0xBEF9A3F7,0xC67178F2);
+      $HASH = Array(0x6A09E667, 0xBB67AE85, 0x3C6EF372, 0xA54FF53A, 0x510E527F, 0x9B05688C, 0x1F83D9AB, 0x5BE0CD19);
+      $W = Array(64);
+      /* append padding */
+      $m[$l >> 5] |= 0x80 << (24 - $l % 32);
+      $m[(($l + 64 >> 9) << 4) + 15] = $l;
+      for ( $i = 0; $i<count($m); $i+=16 ) {
+          $a = $HASH[0];
+          $b = $HASH[1];
+          $c = $HASH[2];
+          $d = $HASH[3];
+          $e = $HASH[4];
+          $f = $HASH[5];
+          $g = $HASH[6];
+          $h = $HASH[7];
+          for ( $j = 0; $j<64; $j++)
+          {
+              if ( $j < 16 )
+              {
+                $W[$j] = ( isset($m[$j + $i]) ) ? $m[$j + $i] : 0;
+              }
+              else
+              {
+                $W[$j] = $this->safe_add(
+                  $this->safe_add(
+                    $this->safe_add(
+                      $this->Gamma1256($W[$j - 2]), $W[$j - 7]),
+                    $this->Gamma0256($W[$j - 15])),
+                  $W[$j - 16]);
+              }
+              $T1 = $this->safe_add(
+                $this->safe_add(
+                  $this->safe_add(
+                    $this->safe_add($h, $this->Sigma1256($e)
+                      ),
+                    $this->Ch($e, $f, $g)),
+                  $K[$j]),
+                $W[$j]);
+              $T2 = $this->safe_add($this->Sigma0256($a), $this->Maj($a, $b, $c));
+              $h = $g;
+              $g = $f;
+              $f = $e;
+              $e = $this->safe_add($d, $T1);
+              $d = $c;
+              $c = $b;
+              $b = $a;
+              $a = $this->safe_add($T1, $T2);
+          }
+          $HASH[0] = $this->safe_add($a, $HASH[0]);
+          $HASH[1] = $this->safe_add($b, $HASH[1]);
+          $HASH[2] = $this->safe_add($c, $HASH[2]);
+          $HASH[3] = $this->safe_add($d, $HASH[3]);
+          $HASH[4] = $this->safe_add($e, $HASH[4]);
+          $HASH[5] = $this->safe_add($f, $HASH[5]);
+          $HASH[6] = $this->safe_add($g, $HASH[6]);
+          $HASH[7] = $this->safe_add($h, $HASH[7]);
+      }
+      return $HASH;
+  }
+  function str2binb ($str) {
+    $bin = Array();
+    for ( $i = 0; $i < strlen($str); $i++ )
+    {
+      $byte = ord($str{$i});
+      $block = floor($i / 4);
+      $stage = $i % 4;
+      if ( $stage == 0 )
+      {
+        $bin[$block] = $byte;
+      }
+      else
+      {
+        $bin[$block] <<= 8;
+        $bin[$block] |= $byte;
+      }
+    }
+    while ( $stage < 3 )
+    {
+      $stage++;
+      $bin[$block] <<= 8;
+    }
+    return $bin;
+  }
+  function byte2hex($byte)
+  {
+    $b = dechex(ord($byte));
+    return ( strlen($b) < 2 ) ? "0$b" : $b;
+  }
+  function binb2hex ($binarray) {
+    $hexcase = 0; /* hex output format. 0 - lowercase; 1 - uppercase */
+    $hex_tab = $hexcase ? "0123456789ABCDEF" : "0123456789abcdef";
+    $str = "";
+    foreach ( $binarray as $bytes )
+    {
+      $str .= implode('', array(
+          $this->byte2hex(chr(( $bytes >> 24 ) & 0xFF)),
+          $this->byte2hex(chr(( $bytes >> 16 ) & 0xFF)),
+          $this->byte2hex(chr(( $bytes >> 8 ) & 0xFF)),
+          $this->byte2hex(chr($bytes & 0xFF))
+        ));
+    }
+    return $str;
+  }
+  function hex_sha256 ( $s )
+  {
+    return $this->binb2hex(
+      $this->core_sha256(
+        $this->str2binb($s),
+        strlen($s) * $this->chrsz)
+      );
+  }
+}
+
+if ( !function_exists('sha256') )
+{
+  function sha256($text)
+  {
+    static $sha_obj = false;
+    if ( !is_object($sha_obj) )
+      $sha_obj = new SHA256();
+    return $sha_obj->hex_sha256($text);
+  }
+}
+
+?>
--- a/includes/email.php	Fri Feb 22 12:46:51 2008 -0500
+++ b/includes/email.php	Fri Feb 22 12:51:53 2008 -0500
@@ -2,7 +2,7 @@
 
 /*
  * Enano - an open-source CMS capable of wiki functions, Drupal-like sidebar blocks, and everything in between
- * Version 1.0.3 (Dyrad)
+ * Version 1.1.2 (Caoineag alpha 2)
  * Copyright (C) 2006-2007 Dan Fuhry
  *
  * This program is Free Software; you can redistribute and/or modify it under the terms of the GNU General Public License
@@ -27,7 +27,7 @@
 
   var $tpl_msg;
 
-  function emailer($use_smtp)
+  function __construct($use_smtp)
   {
     $this->reset();
     $this->use_smtp = $use_smtp;
@@ -151,7 +151,7 @@
                            (($this->from != '') ? "From: $this->from\n" : "From: " . getConfig('contact_email') . "\n") .
                            "Return-Path: " . getConfig('contact_email') .
                            "\nMessage-ID: <" . md5(uniqid(time())) . "@" . $_SERVER['SERVER_NAME'] . ">\nMIME-Version: 1.0\nContent-type: text/plain; charset=" . $this->encoding .
-                           "\nContent-transfer-encoding: 8bit\nDate: " . date('r', time()) .
+                           "\nContent-transfer-encoding: 8bit\nDate: " . enano_date('r', time()) .
                            "\nX-Priority: 3\nX-MSMail-Priority: Normal\nX-Mailer: PHP\nX-MimeOLE: Produced By Enano CMS\n" .
                            $this->extra_headers .
                            (($cc != '') ? "Cc: $cc\n" : '')  .
@@ -247,7 +247,7 @@
     {
       $this->mimeOut .= "From: ".$szFromAddress."\n";
       $this->mimeOut .= "To: ".$this->emailAddress."\n";
-      $this->mimeOut .= "Date: ".date("D, d M Y H:i:s") . " UT\n";
+      $this->mimeOut .= "Date: ".enano_date("D, d M Y H:i:s") . " UT\n";
       $this->mimeOut .= "Reply-To:".$szFromAddress."\n";
       $this->mimeOut .= "Subject: ".$this->mailSubject."\n";
       $this->mimeOut .= "X-Mailer: PHP/".phpversion()."\n";
@@ -349,11 +349,6 @@
     }
   }
   
-  function EmailEncryptor()
-  {
-    $this->__construct();
-  }
-  
   function testAll() {
     $size = sizeof($this->primes);
     
--- a/includes/functions.php	Fri Feb 22 12:46:51 2008 -0500
+++ b/includes/functions.php	Fri Feb 22 12:51:53 2008 -0500
@@ -2,7 +2,7 @@
 
 /*
  * Enano - an open-source CMS capable of wiki functions, Drupal-like sidebar blocks, and everything in between
- * Version 1.0.3 (Dyrad)
+ * Version 1.1.2 (Caoineag alpha 2)
  * Copyright (C) 2006-2007 Dan Fuhry
  *
  * This program is Free Software; you can redistribute and/or modify it under the terms of the GNU General Public License
@@ -82,10 +82,16 @@
     $flags .= $sep . 'theme='.$session->theme;
     $sep = '&';
   }
-  if ( isset($_GET['style'] ) ) {
+  if ( isset($_GET['style'] ) )
+  {
     $flags .= $sep . 'style='.$session->style;
     $sep = '&';
   }
+  if ( isset($_GET['lang']) && preg_match('/^[a-z0-9_]+$/', @$_GET['lang']) )
+  {
+    $flags .= $sep . 'lang=' . urlencode($_GET['lang']);
+    $sep = '&';
+  }
 
   $url = $session->append_sid(contentPath.$t.$flags);
   if($query)
@@ -133,6 +139,11 @@
     $flags .= $sep . 'style='.$session->style;
     $sep = '&';
   }
+  if ( isset($_GET['lang']) && preg_match('/^[a-z0-9_]+$/', @$_GET['lang']) )
+  {
+    $flags .= $sep . 'lang=' . urlencode($_GET['lang']);
+    $sep = '&';
+  }
 
   if(defined('ENANO_BASE_CLASSES_INITIALIZED'))
   {
@@ -201,6 +212,11 @@
     $flags .= $sep . 'style='.$session->style;
     $sep = '&';
   }
+  if ( isset($_GET['lang']) && preg_match('/^[a-z0-9_]+$/', @$_GET['lang']) )
+  {
+    $flags .= $sep . 'lang=' . urlencode($_GET['lang']);
+    $sep = '&';
+  }
 
   if(defined('ENANO_BASE_CLASSES_INITIALIZED'))
   {
@@ -225,6 +241,42 @@
 }
 
 /**
+ * Enano replacement for date(). Accounts for individual users' timezone preferences.
+ * @param string Date-formatted string
+ * @param int Optional - UNIX timestamp value to use. If omitted, the current time is used.
+ * @return string Formatted string
+ */
+
+function enano_date($string, $timestamp = false)
+{
+  if ( !is_int($timestamp) && !is_double($timestamp) && strval(intval($timestamp)) !== $timestamp )
+    $timestamp = time();
+  
+  /*
+  // List of valid characters for date()
+  $date_chars = 'dDjlNSwzWFmMntLoYyaABgGhHisueIOPTZFcrU';
+  // Split them into an array
+  $date_chars = enano_str_split($date_chars);
+  // Emulate date() formatting by replacing date characters with their
+  // percentage-signed counterparts, but not escaped characters which
+  // shouldn't be parsed.
+  foreach ( $date_chars as $char )
+  {
+    $string = str_replace($char, "%$char", $string);
+    $string = str_replace("\\%$char", $char, $string);
+  }
+  */
+  
+  // perform timestamp offset
+  global $timezone;
+  // it's gonna be in minutes, so multiply by 60 to offset the unix timestamp
+  $timestamp = $timestamp + ( $timezone * 60 );
+  
+  // Let PHP do the work for us =)
+  return date($string, $timestamp);
+}
+
+/**
  * Tells you the title for the given page ID string
  * @param string Page ID string (ex: Special:Administration)
  * @param bool Optional. If true, and if the namespace turns out to be something other than Article, the namespace prefix will be prepended to the return value.
@@ -280,14 +332,21 @@
  * @param string $timeout Timeout, in seconds, to delay the redirect. Defaults to 3.
  */
 
-function redirect($url, $title = 'Redirecting...', $message = 'Please wait while you are redirected.', $timeout = 3)
+function redirect($url, $title = 'etc_redirect_title', $message = 'etc_redirect_body', $timeout = 3)
 {
   global $db, $session, $paths, $template, $plugins; // Common objects
-
-  if ( $timeout == 0 )
+  global $lang;
+
+  // POST check added in 1.1.x because Firefox asks us if we want to "resend the form
+  // data to the new location", which can be confusing for some users.
+  if ( $timeout == 0 && empty($_POST) )
   {
     header('Location: ' . $url);
+    header('Content-length: 0');
     header('HTTP/1.1 307 Temporary Redirect');
+    
+    // with 3xx codes HTTP clients expect a response of 0 bytes, so just die here
+    exit();
   }
   
   if ( !is_object($template) )
@@ -296,7 +355,7 @@
     $template->load_theme('oxygen', 'bleu', false);
     $template->tpl_strings['SITE_NAME'] = 'Enano';
     $template->tpl_strings['SITE_DESC'] = 'This site is experiencing a critical error and cannot load.';
-    $template->tpl_strings['COPYRIGHT'] = 'Powered by Enano CMS - &copy; 2007 Dan Fuhry. This program is Free Software; see the <a href="' . scriptPath . '/install.php?mode=license">GPL file</a> included with this package for details.';
+    $template->tpl_strings['COPYRIGHT'] = 'Powered by Enano CMS - &copy; 2006-2008 Dan Fuhry. This program is Free Software; see the <a href="' . scriptPath . '/install.php?mode=license">GPL file</a> included with this package for details.';
     $template->tpl_strings['PAGE_NAME'] = htmlspecialchars($title);
   }
 
@@ -315,7 +374,12 @@
 
   $template->tpl_strings['PAGE_NAME'] = $title;
   $template->header(true);
-  echo '<p>' . $message . '</p><p>If you are not redirected within ' . $timeout . ' seconds, <a href="' . str_replace('"', '\\"', $url) . '">please click here</a>.</p>';
+  echo '<p>' . $message . '</p>';
+  $subst = array(
+      'timeout' => $timeout,
+      'redirect_url' => str_replace('"', '\\"', $url)
+    );
+  echo '<p>' . $lang->get('etc_redirect_timeout', $subst) . '</p>';
   $template->footer(true);
 
   $db->close();
@@ -396,10 +460,6 @@
     // echo 'Keyname: '.$keylist[$idx] . '<br />'; flush(); ob_flush(); // Debugger
     if($idx < 0) return $arr;
     if($keylist[$idx] == '' || $keylist[$idx] < 0 || !$keylist[$idx]) {
-      /* echo 'Infinite loop caught in arrayItemTop(<br /><pre>';
-      print_r($arr);
-      echo '</pre><br />, '.$keyname.');<br /><br />EnanoCMS: Critical error during function call, exiting to prevent excessive server load.';
-      exit; */
       return $arr;
     }
     $arr = arrayItemUp($arr, $keylist[$idx]);
@@ -443,7 +503,9 @@
   $str = '0x';
   foreach($nums as $n)
   {
-    $str .= (string)dechex($n);
+    $byte = (string)dechex($n);
+    if ( strlen($byte) < 2 )
+      $byte = '0' . $byte;
   }
   return $str;
 }
@@ -558,6 +620,7 @@
 function show_category_info()
 {
   global $db, $session, $paths, $template, $plugins; // Common objects
+  global $lang;
   
   if ( $paths->namespace == 'Category' )
   {
@@ -571,7 +634,7 @@
     {
       $db->_die();
     }
-    echo '<h3>Subcategories</h3>';
+    echo '<h3>' . $lang->get('onpage_cat_heading_subcategories') . '</h3>';
     echo '<div class="tblholder">';
     echo '<table border="0" cellspacing="1" cellpadding="4">';
     echo '<tr>';
@@ -594,10 +657,10 @@
         }
         else
         {
-          echo '<td class="' . $class . '">No subcategories.</td>';
+          echo '<td class="' . $class . '">' . $lang->get('onpage_cat_msg_no_subcategories') . '</td>';
         }
         echo '</tr></table></div>' . "\n\n";
-        echo '<h3>Pages</h3>';
+        echo '<h3>' . $lang->get('onpage_cat_heading_pages') . '</h3>';
         echo '<div class="tblholder">';
         echo '<table border="0" cellspacing="1" cellpadding="4">';
         echo '<tr>';
@@ -642,10 +705,10 @@
       }
       else
       {
-        echo '<td class="' . $class . '">No subcategories.</td>';
+        echo '<td class="' . $class . '">' . $lang->get('onpage_cat_msg_no_subcategories') . '</td>';
       }
       echo '</tr></table></div>' . "\n\n";
-      echo '<h3>Pages</h3>';
+      echo '<h3>' . $lang->get('onpage_cat_heading_pages') . '</h3>';
       echo '<div class="tblholder">';
       echo '<table border="0" cellspacing="1" cellpadding="4">';
       echo '<tr>';
@@ -664,7 +727,7 @@
     }
     else
     {
-      echo '<td class="' . $class . '">No pages in this category.</td>';
+      echo '<td class="' . $class . '">' . $lang->get('onpage_cat_msg_no_pages') . '</td>';
     }
     echo '</tr></table></div>' . "\n\n";
   }
@@ -673,9 +736,9 @@
   {
     echo '<div class="mdg-comment" style="margin: 10px 0 0 0;" id="category_box_wrapper">';
     echo '<div style="float: right;">';
-    echo '(<a href="#" onclick="ajaxCatToTag(); return false;">show page tags</a>)';
+    echo '(<a href="#" onclick="ajaxCatToTag(); return false;">' . $lang->get('tags_catbox_link') . '</a>)';
     echo '</div>';
-    echo '<div id="mdgCatBox">Categories: ';
+    echo '<div id="mdgCatBox">' . $lang->get('catedit_catbox_lbl_categories') . ' ';
     
     $where = '( c.page_id=\'' . $db->escape($paths->page_id) . '\' AND c.namespace=\'' . $db->escape($paths->namespace) . '\' )';
     $prefix = table_prefix;
@@ -705,13 +768,13 @@
     }
     else
     {
-      echo '(Uncategorized)';
+      echo $lang->get('catedit_catbox_lbl_uncategorized');
     }
     
     $can_edit = ( $session->get_permissions('edit_cat') && ( !$paths->page_protected || $session->get_permissions('even_when_protected') ) );
     if ( $can_edit )
     {
-      $edit_link = '<a href="' . makeUrl($paths->page, 'do=catedit', true) . '" onclick="ajaxCatEdit(); return false;">edit categorization</a>';
+      $edit_link = '<a href="' . makeUrl($paths->page, 'do=catedit', true) . '" onclick="ajaxCatEdit(); return false;">' . $lang->get('catedit_catbox_link_edit') . '</a>';
       echo ' [ ' . $edit_link . ' ]';
     }
     
@@ -728,65 +791,111 @@
 function show_file_info()
 {
   global $db, $session, $paths, $template, $plugins; // Common objects
-  if($paths->namespace != 'File') return null; // Prevent unnecessary work
-  $selfn = $paths->page_id; // substr($paths->page, strlen($paths->nslist['File']), strlen($paths->cpage));
-  if(substr($paths->cpage['name'], 0, strlen($paths->nslist['File']))==$paths->nslist['File']) $selfn = substr($paths->page_id, strlen($paths->nslist['File']), strlen($paths->page_id));
+  global $lang;
+  
+  // Prevent unnecessary work
+  if ( $paths->namespace != 'File' )
+    return null;
+  
+  $selfn = $paths->page_id;
+  if ( substr($paths->cpage['name'], 0, strlen($paths->nslist['File'])) == $paths->nslist['File'])
+  {
+    $selfn = substr($paths->page_id, strlen($paths->nslist['File']), strlen($paths->page_id));
+  }
   $q = $db->sql_query('SELECT mimetype,time_id,size FROM '.table_prefix.'files WHERE page_id=\''.$selfn.'\' ORDER BY time_id DESC;');
-  if(!$q) $db->_die('The file type could not be fetched.');
-  if($db->numrows() < 1) { echo '<div class="mdg-comment" style="margin-left: 0;"><h3>Uploaded file</h3><p>There are no files uploaded with this name yet. <a href="'.makeUrlNS('Special', 'UploadFile/'.$paths->page_id).'">Upload a file...</a></p></div><br />'; return; }
+  if ( !$q )
+  {
+    $db->_die('The file type could not be fetched.');
+  }
+  
+  if ( $db->numrows() < 1 )
+  {
+    echo '<div class="mdg-comment" style="margin-left: 0;">
+            <h3>' . $lang->get('onpage_filebox_heading') . '</h3>
+            <p>' . $lang->get('onpage_filebox_msg_not_found', array('upload_link' => makeUrlNS('Special', 'UploadFile/'.$paths->page_id))) . '</p>
+          </div>
+          <br />';
+    return;
+  }
   $r = $db->fetchrow();
   $mimetype = $r['mimetype'];
-  $datestring = date('F d, Y h:i a', (int)$r['time_id']);
-  echo '<div class="mdg-comment" style="margin-left: 0;"><p><h3>Uploaded file</h3></p><p>Type: '.$r['mimetype'].'<br />Size: ';
-  $fs = $r['size'];
-  echo $fs.' bytes';
-  $fs = (int)$fs;
-  if($fs >= 1048576)
+  $datestring = enano_date('F d, Y h:i a', (int)$r['time_id']);
+  echo '<div class="mdg-comment" style="margin-left: 0;">
+          <h3>' . $lang->get('onpage_filebox_heading') . '</h3>
+          <p>' . $lang->get('onpage_filebox_lbl_type') . ' '.$r['mimetype'].'<br />';
+  
+  $size = $r['size'] . ' ' . $lang->get('etc_unit_bytes');
+  if ( $r['size'] >= 1048576 )
+  {
+    $size .= ' (' . ( round($r['size'] / 1048576, 1) ) . ' ' . $lang->get('etc_unit_megabytes_short') . ')';
+  }
+  else if ( $r['size'] >= 1024 )
   {
-    $fs = round($fs / 1048576, 1);
-    echo ' ('.$fs.' MB)';
-  } elseif($fs >= 1024) {
-    $fs = round($fs / 1024, 1);
-    echo ' ('.$fs.' KB)';
+    $size .= ' (' . ( round($r['size'] / 1024, 1) ) . ' ' . $lang->get('etc_unit_kilobytes_short') . ')';
+  }
+          
+  echo $lang->get('onpage_filebox_lbl_size', array('size' => $size));
+  
+  echo '<br />' . $lang->get('onpage_filebox_lbl_uploaded') . ' ' . $datestring . '</p>';
+  if ( substr($mimetype, 0, 6) != 'image/' && ( substr($mimetype, 0, 5) != 'text/' || $mimetype == 'text/html' || $mimetype == 'text/javascript' ) )
+  {
+    echo '<div class="warning-box">
+            ' . $lang->get('onpage_filebox_msg_virus_warning') . '
+          </div>';
   }
-  echo '<br />Uploaded: '.$datestring.'</p>';
-  if(substr($mimetype, 0, 6)!='image/' && ( substr($mimetype, 0, 5) != 'text/' || $mimetype == 'text/html' || $mimetype == 'text/javascript' ))
+  if ( substr($mimetype, 0, 6) == 'image/' )
   {
-    echo '<div class="warning-box">This file type may contain viruses or other code that could harm your computer. You should exercise caution if you download it.</div>';
+    echo '<p>
+            <a href="'.makeUrlNS('Special', 'DownloadFile'.'/'.$selfn).'">
+              <img style="border: 0;" alt="'.$paths->page.'" src="'.makeUrlNS('Special', 'DownloadFile'.'/'.$selfn.htmlspecialchars(urlSeparator).'preview').'" />
+            </a>
+          </p>';
   }
-  if(substr($mimetype, 0, 6)=='image/')
-  {
-    echo '<p><a href="'.makeUrlNS('Special', 'DownloadFile'.'/'.$selfn).'"><img style="border: 0;" alt="'.$paths->page.'" src="'.makeUrlNS('Special', 'DownloadFile'.'/'.$selfn.htmlspecialchars(urlSeparator).'preview').'" /></a></p>';
-  }
-  echo '<p><a href="'.makeUrlNS('Special', 'DownloadFile'.'/'.$selfn.'/'.$r['time_id'].htmlspecialchars(urlSeparator).'download').'">Download this file</a>';
+  echo '<p>
+          <a href="'.makeUrlNS('Special', 'DownloadFile'.'/'.$selfn.'/'.$r['time_id'].htmlspecialchars(urlSeparator).'download').'">
+            ' . $lang->get('onpage_filebox_btn_download') . '
+          </a>';
   if(!$paths->page_protected && ( $paths->wiki_mode || $session->get_permissions('upload_new_version') ))
   {
-    echo '  |  <a href="'.makeUrlNS('Special', 'UploadFile'.'/'.$selfn).'">Upload new version</a>';
+    echo '  |  <a href="'.makeUrlNS('Special', 'UploadFile'.'/'.$selfn).'">
+            ' . $lang->get('onpage_filebox_btn_upload_new') . '
+          </a>';
   }
   echo '</p>';
-  if($db->numrows() > 1)
+  if ( $db->numrows() > 1 )
   {
-    echo '<h3>File history</h3><p>';
-    while($r = $db->fetchrow())
+    echo '<h3>' . $lang->get('onpage_filebox_heading_history') . '</h3><p>';
+    while ( $r = $db->fetchrow() )
     {
-      echo '(<a href="'.makeUrlNS('Special', 'DownloadFile'.'/'.$selfn.'/'.$r['time_id'].htmlspecialchars(urlSeparator).'download').'">this ver</a>) ';
-      if($session->get_permissions('history_rollback'))
-        echo ' (<a href="#" onclick="ajaxRollback(\''.$r['time_id'].'\'); return false;">revert</a>) ';
+      echo '(<a href="'.makeUrlNS('Special', 'DownloadFile'.'/'.$selfn.'/'.$r['time_id'].htmlspecialchars(urlSeparator).'download').'">' . $lang->get('onpage_filebox_btn_this_version') . '</a>) ';
+      if ( $session->get_permissions('history_rollback') )
+        echo ' (<a href="#" onclick="ajaxRollback(\''.$r['time_id'].'\'); return false;">' . $lang->get('onpage_filebox_btn_revert') . '</a>) ';
       $mimetype = $r['mimetype'];
-      $datestring = date('F d, Y h:i a', (int)$r['time_id']);
+      $datestring = enano_date('F d, Y h:i a', (int)$r['time_id']);
+      
       echo $datestring.': '.$r['mimetype'].', ';
+      
       $fs = $r['size'];
       $fs = (int)$fs;
+      
       if($fs >= 1048576)
       {
         $fs = round($fs / 1048576, 1);
-        echo ' '.$fs.' MB';
-      } elseif($fs >= 1024) {
+        $size = $fs . ' ' . $lang->get('etc_unit_megabytes_short');
+      }
+      else
+      if ( $fs >= 1024 )
+      {
         $fs = round($fs / 1024, 1);
-        echo ' '.$fs.' KB';
-      } else {
-        echo ' '.$fs.' bytes';
+        $size = $fs . ' ' . $lang->get('etc_unit_kilobytes_short');
       }
+      else
+      {
+        $size = $fs . ' ' . $lang->get('etc_unit_bytes');
+      }
+      
+      echo $size;
+      
       echo '<br />';
     }
     echo '</p>';
@@ -802,23 +911,19 @@
 function display_page_headers()
 {
   global $db, $session, $paths, $template, $plugins; // Common objects
+  global $lang;
   if($session->get_permissions('vote_reset') && $paths->cpage['delvotes'] > 0)
   {
     $delvote_ips = unserialize($paths->cpage['delvote_ips']);
     $hr = htmlspecialchars(implode(', ', $delvote_ips['u']));
-    $is = 'is';
-    $s = '';
-    $s2 = 's';
-    if ( $paths->cpage['delvotes'] > 1)
-    {
-      $is = 'are';
-      $s = 's';
-      $s2 = '';
-    }
+    
+    $string_id = ( $paths->cpage['delvotes'] == 1 ) ? 'delvote_lbl_votes_one' : 'delvote_lbl_votes_plural';
+    $string = $lang->get($string_id, array('num_users' => $paths->cpage['delvotes']));
+    
     echo '<div class="info-box" style="margin-left: 0; margin-top: 5px;" id="mdgDeleteVoteNoticeBox">
-            <b>Notice:</b> There '.$is.' '.$paths->cpage['delvotes'].' user'.$s.' that think'.$s2.' this page should be deleted.<br />
-            <b>Users that voted:</b> ' . $hr . '<br />
-            <a href="'.makeUrl($paths->page, 'do=deletepage').'" onclick="ajaxDeletePage(); return false;">Delete page</a>  |  <a href="'.makeUrl($paths->page, 'do=resetvotes').'" onclick="ajaxResetDelVotes(); return false;">Reset votes</a>
+            <b>' . $lang->get('etc_lbl_notice') . '</b> ' . $string . '<br />
+            <b>' . $lang->get('delvote_lbl_users_that_voted') . '</b> ' . $hr . '<br />
+            <a href="'.makeUrl($paths->page, 'do=deletepage').'" onclick="ajaxDeletePage(); return false;">' . $lang->get('delvote_btn_deletepage') . '</a>  |  <a href="'.makeUrl($paths->page, 'do=resetvotes').'" onclick="ajaxResetDelVotes(); return false;">' . $lang->get('delvote_btn_resetvotes') . '</a>
           </div>';
   }
 }
@@ -841,37 +946,6 @@
 }
 
 /**
- * Deprecated, do not use.
- */
-
-function password_prompt($id = false)
-{
-  global $db, $session, $paths, $template, $plugins; // Common objects
-  if(!$id) $id = $paths->page;
-  if(isset($paths->pages[$id]['password']) && strlen($paths->pages[$id]['password']) == 40 && !isset($_REQUEST['pagepass']))
-  {
-    die_friendly('Password required', '<p>You must supply a password to access this page.</p><form action="'.makeUrl($paths->pages[$id]['urlname']).'" method="post"><p>Password: <input name="pagepass" type="password" /></p><p><input type="submit" value="Submit" /></p>');
-  } elseif(isset($_REQUEST['pagepass'])) {
-    $p = (preg_match('#^([a-f0-9]*){40}$#', $_REQUEST['pagepass'])) ? $_REQUEST['pagepass'] : sha1($_REQUEST['pagepass']);
-    if($p != $paths->pages[$id]['password']) die_friendly('Password required', '<p style="color: red;">The password you entered is incorrect.</p><form action="'.makeUrl($paths->page).'" method="post"><p>Password: <input name="pagepass" type="password" /></p><p><input type="submit" value="Submit" /></p>');
-  }
-}
-
-/**
- * Some sort of primitive hex converter from back in the day. Deprecated, do not use.
- * @param string Text to encode
- * @return string
- */
-
-function str_hex($string){
-    $hex='';
-    for ($i=0; $i < strlen($string); $i++){
-        $hex .= ' '.dechex(ord($string[$i]));
-    }
-    return substr($hex, 1, strlen($hex));
-}
-
-/**
  * Essentially an return code reader for a socket. Don't use this unless you're writing mail code and smtp_send_email doesn't cut it. Ported from phpBB's smtp.php.
  * @param socket A socket resource
  * @param string The expected response from the server, this needs to be exactly three characters.
@@ -1137,7 +1211,10 @@
       '1.0.1.1'=> 'Loch Ness internal bugfix build',
       '1.0.2b1'=> 'Coblynau unstable',
       '1.0.2'  => 'Coblynau',
-      '1.0.3'  => 'Dyrad'
+      '1.0.3'  => 'Dyrad',
+      '1.1.1'  => 'Caoineag alpha 1',
+      '1.1.2'  => 'Caoineag alpha 2',
+      '1.1.3'  => 'Caoineag alpha 3',
     );
   $version = enano_version();
   if ( isset($names[$version]) )
@@ -1148,14 +1225,6 @@
 }
 
 /**
- * What kinda sh** was I thinking when I wrote this. Deprecated.
- */
-
-function _dualurlenc($t) {
-  return rawurlencode(rawurlencode($t));
-}
-
-/**
  * Badly named function to send back eval'able Javascript code with an error message. Deprecated, use JSON instead.
  * @param string Message to send
  */
@@ -1270,7 +1339,8 @@
 function enano_debug_print_backtrace($return = false)
 {
   ob_start();
-  echo '<pre>';
+  if ( !$return )
+    echo '<pre>';
   if ( function_exists('debug_print_backtrace') )
   {
     debug_print_backtrace();
@@ -1279,7 +1349,8 @@
   {
     echo '<b>Warning:</b> No debug_print_backtrace() support!';
   }
-  echo '</pre>';
+  if ( !$return )
+    echo '</pre>';
   $c = ob_get_contents();
   ob_end_clean();
   if($return) return $c;
@@ -1870,7 +1941,6 @@
   }
 
   return $html;
-
 }
 
 /**
@@ -2057,6 +2127,8 @@
 function paginate($q, $tpl_text, $num_results, $result_url, $start = 0, $perpage = 10, $callers = Array(), $header = '', $footer = '')
 {
   global $db, $session, $paths, $template, $plugins; // Common objects
+  global $lang;
+  
   $parser = $template->makeParserText($tpl_text);
   $num_pages = ceil ( $num_results / $perpage );
   $out = '';
@@ -2071,7 +2143,7 @@
             'display: table; margin: 10px 0 0 auto;';
   $begin = '<div class="tblholder" style="'. $pg_css . '">
     <table border="0" cellspacing="1" cellpadding="4">
-      <tr><th>Page:</th>';
+      <tr><th>' . $lang->get('paginate_lbl_page') . '</th>';
   $block = '<td class="row1" style="text-align: center;">{LINK}</td>';
   $end = '</tr></table></div>';
   $blk = $template->makeParserText($block);
@@ -2118,7 +2190,7 @@
       }
     }
     $url = sprintf($result_url, '0');
-    $link = ( 0 == $start ) ? "<b>First</b>" : "<a href=".'"'."$url".'"'." style='text-decoration: none;'>&laquo; First</a>";
+    $link = ( 0 == $start ) ? "<b>" . $lang->get('paginate_btn_first') . "</b>" : "<a href=".'"'."$url".'"'." style='text-decoration: none;'>&laquo; " . $lang->get('paginate_btn_first') . "</a>";
     $blk->assign_vars(array(
       'CLASS'=>$cls,
       'LINK'=>$link
@@ -2160,7 +2232,7 @@
       $offset = strval($total);
       $url = sprintf($result_url, $offset);
       $j = $i + 1;
-      $link = ( $offset == strval($start) ) ? "<b>Last</b>" : "<a href=".'"'."$url".'"'." style='text-decoration: none;'>Last &raquo;</a>";
+      $link = ( $offset == strval($start) ) ? "<b>" . $lang->get('paginate_btn_last') . "</b>" : "<a href=".'"'."$url".'"'." style='text-decoration: none;'>" . $lang->get('paginate_btn_last') . " &raquo;</a>";
       $blk->assign_vars(array(
         'CLASS'=>$cls,
         'LINK'=>$link
@@ -2231,6 +2303,8 @@
 function paginate_array($q, $num_results, $result_url, $start = 0, $perpage = 10, $header = '', $footer = '')
 {
   global $db, $session, $paths, $template, $plugins; // Common objects
+  global $lang;
+  
   $num_pages = ceil ( $num_results / $perpage );
   $out = '';
   $i = 0;
@@ -2239,17 +2313,18 @@
   // Build paginator
   $begin = '<div class="tblholder" style="display: table; margin: 10px 0 0 auto;">
     <table border="0" cellspacing="1" cellpadding="4">
-      <tr><th>Page:</th>';
+      <tr><th>' . $lang->get('paginate_lbl_page') . '</th>';
   $block = '<td class="row1" style="text-align: center;">{LINK}</td>';
   $end = '</tr></table></div>';
   $blk = $template->makeParserText($block);
   $inner = '';
   $cls = 'row2';
   $total = $num_pages * $perpage - $perpage;
+  /*
   if ( $start > 0 )
   {
     $url = sprintf($result_url, abs($start - $perpage));
-    $link = "<a href=".'"'."$url".'"'." style='text-decoration: none;'>&laquo; Prev</a>";
+    $link = "<a href=".'"'."$url".'"'." style='text-decoration: none;'>&laquo; " . $lang->get('paginate_btn_prev') . "</a>";
     $cls = ( $cls == 'row1' ) ? 'row2' : 'row1';
     $blk->assign_vars(array(
       'CLASS'=>$cls,
@@ -2257,6 +2332,7 @@
       ));
     $inner .= $blk->run();
   }
+  */
   if ( $num_pages < 5 )
   {
     for ( $i = 0; $i < $num_pages; $i++ )
@@ -2298,7 +2374,7 @@
       }
     }
     $url = sprintf($result_url, '0');
-    $link = ( 0 == $start ) ? "<b>First</b>" : "<a href=".'"'."$url".'"'." style='text-decoration: none;'>&laquo; First</a>";
+    $link = ( 0 == $start ) ? "<b>" . $lang->get('paginate_btn_first') . "</b>" : "<a href=".'"'."$url".'"'." style='text-decoration: none;'>&laquo; " . $lang->get('paginate_btn_first') . "</a>";
     $blk->assign_vars(array(
       'CLASS'=>$cls,
       'LINK'=>$link
@@ -2338,7 +2414,7 @@
       $offset = strval($total);
       $url = sprintf($result_url, $offset);
       $j = $i + 1;
-      $link = ( $offset == strval($start) ) ? "<b>Last</b>" : "<a href=".'"'."$url".'"'." style='text-decoration: none;'>Last &raquo;</a>";
+      $link = ( $offset == strval($start) ) ? "<b>" . $lang->get('paginate_btn_last') . "</b>" : "<a href=".'"'."$url".'"'." style='text-decoration: none;'>" . $lang->get('paginate_btn_last') . " &raquo;</a>";
       $blk->assign_vars(array(
         'CLASS'=>$cls,
         'LINK'=>$link
@@ -2348,12 +2424,12 @@
 
   }
 
+  /*
   if ( $start < $total )
   {
     $link_offset = abs($start + $perpage);
-    // i'm tired of debugging a defective sprintf
     $url = htmlspecialchars(sprintf($result_url, strval($link_offset)));
-    $link = "<a href=".'"'."$url".'"'." style='text-decoration: none;'>Next &raquo;</a>";
+    $link = "<a href=".'"'."$url".'"'." style='text-decoration: none;'>" . $lang->get('paginate_btn_next') . " &raquo;</a>";
     $cls = ( $cls == 'row1' ) ? 'row2' : 'row1';
     $blk->assign_vars(array(
       'CLASS'=>$cls,
@@ -2361,6 +2437,7 @@
       ));
     $inner .= $blk->run();
   }
+  */
 
   $inner .= '<td class="row2" style="cursor: pointer;" onclick="paginator_goto(this, '.$this_page.', '.$num_pages.', '.$perpage.', unescape(\'' . rawurlencode($result_url) . '\'));">&darr;</td>';
 
@@ -2422,9 +2499,9 @@
   
   if ( isset($paths->nslist['User']) )
   {
-    if ( preg_match('/^' . preg_quote($paths->nslist['User']) . '/', $page_id) )
+    if ( preg_match('/^' . str_replace('/', '\\/', preg_quote($paths->nslist['User'])) . '/', $page_id) )
     {
-      $ip = preg_replace('/^' . preg_quote($paths->nslist['User']) . '/', '', $page_id);
+      $ip = preg_replace('/^' . str_replace('/', '\\/', preg_quote($paths->nslist['User'])) . '/', '', $page_id);
       if ( is_valid_ip($ip) )
       {
         return $page_id;
@@ -2708,7 +2785,7 @@
     $gzip_contents = ob_get_contents();
     ob_end_clean();
     
-    $return = ob_gzhandler($gzip_contents);
+    $return = @ob_gzhandler($gzip_contents);
     if ( $return )
     {
       header('Content-encoding: gzip');
@@ -3192,6 +3269,111 @@
 }
 
 /**
+ * Installs a language.
+ * @param string The ISO-639-3 identifier for the language. Maximum of 6 characters, usually 3.
+ * @param string The name of the language in English (Spanish)
+ * @param string The name of the language natively (Español)
+ * @param string The path to the file containing the language's strings. Optional.
+ */
+
+function install_language($lang_code, $lang_name_neutral, $lang_name_local, $lang_file = false)
+{
+  global $db, $session, $paths, $template, $plugins; // Common objects
+  
+  $q = $db->sql_query('SELECT 1 FROM '.table_prefix.'language WHERE lang_code = \'' . $db->escape($lang_code) . '\';');
+  if ( !$q )
+    $db->_die('functions.php - checking for language existence');
+  
+  if ( $db->numrows() > 0 )
+    // Language already exists
+    return false;
+  
+  $q = $db->sql_query('INSERT INTO ' . table_prefix . 'language(lang_code, lang_name_default, lang_name_native) 
+                         VALUES(
+                           \'' . $db->escape($lang_code) . '\',
+                           \'' . $db->escape($lang_name_neutral) . '\',
+                           \'' . $db->escape($lang_name_local) . '\'
+                         );');
+  if ( !$q )
+    $db->_die('functions.php - installing language');
+  
+  if ( ENANO_DBLAYER == 'PGSQL' )
+  {
+    // exception for Postgres, which doesn't support insert IDs
+    // This will cause the Language class to just load by lang code
+    // instead of by numeric ID
+    $lang_id = $lang_code;
+  }
+  else
+  {
+    $lang_id = $db->insert_id();
+    if ( empty($lang_id) || $lang_id == 0 )
+    {
+      $db->_die('functions.php - invalid returned lang_id');
+    }
+  }
+  
+  // Do we also need to install a language file?
+  if ( is_string($lang_file) && file_exists($lang_file) )
+  {
+    $lang = new Language($lang_id);
+    $lang->import($lang_file);
+  }
+  else if ( is_string($lang_file) && !file_exists($lang_file) )
+  {
+    echo '<b>Notice:</b> Can\'t load language file, so the specified language wasn\'t fully installed.<br />';
+    return false;
+  }
+  return true;
+}
+
+/**
+ * Lists available languages.
+ * @return array Multi-depth. Associative, with children associative containing keys name, name_eng, and dir.
+ */
+
+function list_available_languages()
+{
+  // Pulled from install/includes/common.php
+  
+  // Build a list of available languages
+  $dir = @opendir( ENANO_ROOT . '/language' );
+  if ( !$dir )
+    die('CRITICAL: could not open language directory');
+  
+  $languages = array();
+  
+  while ( $dh = @readdir($dir) )
+  {
+    if ( $dh == '.' || $dh == '..' )
+      continue;
+    if ( file_exists( ENANO_ROOT . "/language/$dh/meta.json" ) )
+    {
+      // Found a language directory, determine metadata
+      $meta = @file_get_contents( ENANO_ROOT . "/language/$dh/meta.json" );
+      if ( empty($meta) )
+        // Could not read metadata file, continue silently
+        continue;
+        
+      // Do some syntax correction on the metadata
+      $meta = enano_clean_json($meta);
+        
+      $meta = enano_json_decode($meta);
+      if ( isset($meta['lang_name_english']) && isset($meta['lang_name_native']) && isset($meta['lang_code']) )
+      {
+        $languages[$meta['lang_code']] = array(
+            'name' => $meta['lang_name_native'],
+            'name_eng' => $meta['lang_name_english'],
+            'dir' => $dh
+          );
+      }
+    }
+  }
+  
+  return $languages;
+}
+
+/**
  * Scales an image to the specified width and height, and writes the output to the specified
  * file. Will use ImageMagick if present, but if not will attempt to scale with GD. This will
  * always scale images proportionally.
@@ -3354,6 +3536,645 @@
   return false;
 }
 
+/**
+ * Determines whether a GIF file is animated or not. Credit goes to ZeBadger from <http://www.php.net/imagecreatefromgif>.
+ * Modified to conform to Enano coding standards.
+ * @param string Path to GIF file
+ * @return bool If animated, returns true
+ */
+
+ 
+function is_gif_animated($filename)
+{
+  $filecontents = @file_get_contents($filename);
+  if ( empty($filecontents) )
+    return false;
+
+  $str_loc = 0;
+  $count = 0;
+  while ( $count < 2 ) // There is no point in continuing after we find a 2nd frame
+  {
+    $where1 = strpos($filecontents,"\x00\x21\xF9\x04", $str_loc);
+    if ( $where1 === false )
+    {
+      break;
+    }
+    else
+    {
+      $str_loc = $where1 + 1;
+      $where2 = strpos($filecontents,"\x00\x2C", $str_loc);
+      if ( $where2 === false )
+      {
+        break;
+      }
+      else
+      {
+        if ( $where1 + 8 == $where2 )
+        {
+          $count++;
+        }
+        $str_loc = $where2 + 1;
+      }
+    }
+  }
+  
+  return ( $count > 1 ) ? true : false;
+}
+
+/**
+ * Retrieves the dimensions of a GIF image.
+ * @param string The path to the GIF file.
+ * @return array Key 0 is width, key 1 is height
+ */
+
+function gif_get_dimensions($filename)
+{
+  $filecontents = @file_get_contents($filename);
+  if ( empty($filecontents) )
+    return false;
+  if ( strlen($filecontents) < 10 )
+    return false;
+  
+  $width = substr($filecontents, 6, 2);
+  $height = substr($filecontents, 8, 2);
+  $width = unpack('v', $width);
+  $height = unpack('v', $height);
+  return array($width[1], $height[1]);
+}
+
+/**
+ * Determines whether a PNG image is animated or not. Based on some specification information from <http://wiki.mozilla.org/APNG_Specification>.
+ * @param string Path to PNG file.
+ * @return bool If animated, returns true
+ */
+
+function is_png_animated($filename)
+{
+  $filecontents = @file_get_contents($filename);
+  if ( empty($filecontents) )
+    return false;
+  
+  $parsed = parse_png($filecontents);
+  if ( !$parsed )
+    return false;
+  
+  if ( !isset($parsed['fdAT']) )
+    return false;
+  
+  if ( count($parsed['fdAT']) > 1 )
+    return true;
+}
+
+/**
+ * Gets the dimensions of a PNG image.
+ * @param string Path to PNG file
+ * @return array Key 0 is width, key 1 is length.
+ */
+
+function png_get_dimensions($filename)
+{
+  $filecontents = @file_get_contents($filename);
+  if ( empty($filecontents) )
+    return false;
+  
+  $parsed = parse_png($filecontents);
+  if ( !$parsed )
+    return false;
+  
+  $ihdr_stream = $parsed['IHDR'][0];
+  $width = substr($ihdr_stream, 0, 4);
+  $height = substr($ihdr_stream, 4, 4);
+  $width = unpack('N', $width);
+  $height = unpack('N', $height);
+  $x = $width[1];
+  $y = $height[1];
+  return array($x, $y);
+}
+
+/**
+ * Internal function to parse out the streams of a PNG file. Based on the W3 PNG spec: http://www.w3.org/TR/PNG/
+ * @param string The contents of the PNG
+ * @return array Associative array containing the streams
+ */
+
+function parse_png($data)
+{
+  // Trim off first 8 bytes to check for PNG header
+  $header = substr($data, 0, 8);
+  if ( $header != "\x89\x50\x4e\x47\x0d\x0a\x1a\x0a" )
+  {
+    return false;
+  }
+  $return = array();
+  $data = substr($data, 8);
+  while ( strlen($data) > 0 )
+  {
+    $chunklen_bin = substr($data, 0, 4);
+    $chunk_type = substr($data, 4, 4);
+    $chunklen = unpack('N', $chunklen_bin);
+    $chunklen = $chunklen[1];
+    $chunk_data = substr($data, 8, $chunklen);
+    
+    // If the chunk type is not valid, this may be a malicious PNG with bad offsets. Break out of the loop.
+    if ( !preg_match('/^[A-z]{4}$/', $chunk_type) )
+      break;
+    
+    if ( !isset($return[$chunk_type]) )
+      $return[$chunk_type] = array();
+    $return[$chunk_type][] = $chunk_data;
+    
+    $offset_next = 4 // Length
+                 + 4 // Type
+                 + $chunklen // Data
+                 + 4; // CRC
+    $data = substr($data, $offset_next);
+  }
+  return $return;
+}
+
+/**
+ * Retreives information about the intrinsic characteristics of the jpeg image, such as Bits per Component, Height and Width. This function is from the PHP JPEG Metadata Toolkit. Licensed under the GPLv2 or later.
+ * @param array The JPEG header data, as retrieved from the get_jpeg_header_data function
+ * @return array An array containing the intrinsic JPEG values FALSE - if the comment segment couldnt be found
+ * @license GNU General Public License
+ * @copyright Copyright Evan Hunter 2004 
+ */
+
+function get_jpeg_intrinsic_values( $jpeg_header_data )
+{
+  // Create a blank array for the output
+  $Outputarray = array( );
+
+  //Cycle through the header segments until Start Of Frame (SOF) is found or we run out of segments
+  $i = 0;
+  while ( ( $i < count( $jpeg_header_data) )  && ( substr( $jpeg_header_data[$i]['SegName'], 0, 3 ) != "SOF" ) )
+  {
+    $i++;
+  }
+
+  // Check if a SOF segment has been found
+  if ( substr( $jpeg_header_data[$i]['SegName'], 0, 3 ) == "SOF" )
+  {
+    // SOF segment was found, extract the information
+
+    $data = $jpeg_header_data[$i]['SegData'];
+
+    // First byte is Bits per component
+    $Outputarray['Bits per Component'] = ord( $data{0} );
+
+    // Second and third bytes are Image Height
+    $Outputarray['Image Height'] = ord( $data{ 1 } ) * 256 + ord( $data{ 2 } );
+
+    // Forth and fifth bytes are Image Width
+    $Outputarray['Image Width'] = ord( $data{ 3 } ) * 256 + ord( $data{ 4 } );
+
+    // Sixth byte is number of components
+    $numcomponents = ord( $data{ 5 } );
+
+    // Following this is a table containing information about the components
+    for( $i = 0; $i < $numcomponents; $i++ )
+    {
+      $Outputarray['Components'][] = array (  'Component Identifier' => ord( $data{ 6 + $i * 3 } ),
+                'Horizontal Sampling Factor' => ( ord( $data{ 7 + $i * 3 } ) & 0xF0 ) / 16,
+                'Vertical Sampling Factor' => ( ord( $data{ 7 + $i * 3 } ) & 0x0F ),
+                'Quantization table destination selector' => ord( $data{ 8 + $i * 3 } ) );
+    }
+  }
+  else
+  {
+    // Couldn't find Start Of Frame segment, hence can't retrieve info
+    return FALSE;
+  }
+
+  return $Outputarray;
+}
+
+/**
+ * Reads all the JPEG header segments from an JPEG image file into an array. This function is from the PHP JPEG Metadata Toolkit. Licensed under the GPLv2 or later. Modified slightly for Enano coding standards and to remove unneeded capability.
+ * @param string the filename of the file to JPEG file to read
+ * @return string Array of JPEG header segments, or FALSE - if headers could not be read
+ * @license GNU General Public License
+ * @copyright Copyright Evan Hunter 2004
+ */
+
+function get_jpeg_header_data( $filename )
+{
+  // Attempt to open the jpeg file - the at symbol supresses the error message about
+  // not being able to open files. The file_exists would have been used, but it
+  // does not work with files fetched over http or ftp.
+  $filehnd = @fopen($filename, 'rb');
+
+  // Check if the file opened successfully
+  if ( ! $filehnd  )
+  {
+    // Could't open the file - exit
+    return FALSE;
+  }
+
+
+  // Read the first two characters
+  $data = fread( $filehnd, 2 );
+
+  // Check that the first two characters are 0xFF 0xDA  (SOI - Start of image)
+  if ( $data != "\xFF\xD8" )
+  {
+    // No SOI (FF D8) at start of file - This probably isn't a JPEG file - close file and return;
+    fclose($filehnd);
+    return FALSE;
+  }
+
+
+  // Read the third character
+  $data = fread( $filehnd, 2 );
+
+  // Check that the third character is 0xFF (Start of first segment header)
+  if ( $data{0} != "\xFF" )
+  {
+    // NO FF found - close file and return - JPEG is probably corrupted
+    fclose($filehnd);
+    return FALSE;
+  }
+
+  // Flag that we havent yet hit the compressed image data
+  $hit_compressed_image_data = FALSE;
+
+
+  // Cycle through the file until, one of: 1) an EOI (End of image) marker is hit,
+  //               2) we have hit the compressed image data (no more headers are allowed after data)
+  //               3) or end of file is hit
+
+  while ( ( $data{1} != "\xD9" ) && (! $hit_compressed_image_data) && ( ! feof( $filehnd ) ))
+  {
+    // Found a segment to look at.
+    // Check that the segment marker is not a Restart marker - restart markers don't have size or data after them
+    if (  ( ord($data{1}) < 0xD0 ) || ( ord($data{1}) > 0xD7 ) )
+    {
+      // Segment isn't a Restart marker
+      // Read the next two bytes (size)
+      $sizestr = fread( $filehnd, 2 );
+
+      // convert the size bytes to an integer
+      $decodedsize = unpack ("nsize", $sizestr);
+
+      // Save the start position of the data
+      $segdatastart = ftell( $filehnd );
+
+      // Read the segment data with length indicated by the previously read size
+      $segdata = fread( $filehnd, $decodedsize['size'] - 2 );
+
+
+      // Store the segment information in the output array
+      $headerdata[] = array(  "SegType" => ord($data{1}),
+            "SegName" => $GLOBALS[ "JPEG_Segment_Names" ][ ord($data{1}) ],
+            "SegDataStart" => $segdatastart,
+            "SegData" => $segdata );
+    }
+
+    // If this is a SOS (Start Of Scan) segment, then there is no more header data - the compressed image data follows
+    if ( $data{1} == "\xDA" )
+    {
+      // Flag that we have hit the compressed image data - exit loop as no more headers available.
+      $hit_compressed_image_data = TRUE;
+    }
+    else
+    {
+      // Not an SOS - Read the next two bytes - should be the segment marker for the next segment
+      $data = fread( $filehnd, 2 );
+
+      // Check that the first byte of the two is 0xFF as it should be for a marker
+      if ( $data{0} != "\xFF" )
+      {
+        // NO FF found - close file and return - JPEG is probably corrupted
+        fclose($filehnd);
+        return FALSE;
+      }
+    }
+  }
+
+  // Close File
+  fclose($filehnd);
+
+  // Return the header data retrieved
+  return $headerdata;
+}
+
+/**
+ * Returns the dimensions of a JPEG image in the same format as {php,gif}_get_dimensions().
+ * @param string JPEG file to check
+ * @return array Key 0 is width, key 1 is height
+ */
+
+function jpg_get_dimensions($filename)
+{
+  if ( !file_exists($filename) )
+  {
+    echo "Doesn't exist<br />";
+    return false;
+  }
+  
+  $headers = get_jpeg_header_data($filename);
+  if ( !$headers )
+  {
+    echo "Bad headers<br />";
+    return false;
+  }
+  
+  $metadata = get_jpeg_intrinsic_values($headers);
+  if ( !$metadata )
+  {
+    echo "Bad metadata: <pre>" . print_r($metadata, true) . "</pre><br />";
+    return false;
+  }
+  
+  if ( !isset($metadata['Image Width']) || !isset($metadata['Image Height']) )
+  {
+    echo "No metadata<br />";
+    return false;
+  }
+  
+  return array($metadata['Image Width'], $metadata['Image Height']);
+}
+
+/**
+ * Generates a URL for the avatar for the given user ID and avatar type.
+ * @param int User ID
+ * @param string Image type - must be one of jpg, png, or gif.
+ * @return string
+ */
+
+function make_avatar_url($user_id, $avi_type)
+{
+  if ( !is_int($user_id) )
+    return false;
+  if ( !in_array($avi_type, array('png', 'gif', 'jpg')) )
+    return false;
+  return scriptPath . '/' . getConfig('avatar_directory') . '/' . $user_id . '.' . $avi_type;
+}
+
+/**
+ * Determines an image's filetype based on its signature.
+ * @param string Path to image file
+ * @return string One of gif, png, or jpg, or false if none of these.
+ */
+
+function get_image_filetype($filename)
+{
+  $filecontents = @file_get_contents($filename);
+  if ( empty($filecontents) )
+    return false;
+  
+  if ( substr($filecontents, 0, 8) == "\x89\x50\x4e\x47\x0d\x0a\x1a\x0a" )
+    return 'png';
+  
+  if ( substr($filecontents, 0, 6) == 'GIF87a' || substr($filecontents, 0, 6) == 'GIF89a' )
+    return 'gif';
+  
+  if ( substr($filecontents, 0, 2) == "\xFF\xD8" )
+    return 'jpg';
+  
+  return false;
+}
+
+/**
+ * Generates a JSON encoder/decoder singleton.
+ * @return object
+ */
+
+function enano_json_singleton()
+{
+  static $json_obj;
+  if ( !is_object($json_obj) )
+    $json_obj = new Services_JSON(SERVICES_JSON_LOOSE_TYPE | SERVICES_JSON_SUPPRESS_ERRORS);
+  
+  return $json_obj;
+}
+
+/**
+ * Wrapper for JSON encoding.
+ * @param mixed Variable to encode
+ * @return string JSON-encoded string
+ */
+
+function enano_json_encode($data)
+{
+  /*
+  if ( function_exists('json_encode') )
+  {
+    // using PHP5 with JSON support
+    return json_encode($data);
+  }
+  */
+  
+  return Zend_Json::encode($data, true);
+}
+
+/**
+ * Wrapper for JSON decoding.
+ * @param string JSON-encoded string
+ * @return mixed Decoded value
+ */
+
+function enano_json_decode($data)
+{
+  /*
+  if ( function_exists('json_decode') )
+  {
+    // using PHP5 with JSON support
+    return json_decode($data);
+  }
+  */
+  
+  return Zend_Json::decode($data, Zend_Json::TYPE_ARRAY);
+}
+
+/**
+ * Cleans a snippet of JSON for closer standards compliance (shuts up the picky Zend parser)
+ * @param string Dirty JSON
+ * @return string Clean JSON
+ */
+
+function enano_clean_json($json)
+{
+  // eliminate comments
+  $json = preg_replace(array(
+          // eliminate single line comments in '// ...' form
+          '#^\s*//(.+)$#m',
+          // eliminate multi-line comments in '/* ... */' form, at start of string
+          '#^\s*/\*(.+)\*/#Us',
+          // eliminate multi-line comments in '/* ... */' form, at end of string
+          '#/\*(.+)\*/\s*$#Us'
+        ), '', $json);
+    
+  $json = preg_replace('/([,\{\[])([\s]*?)([a-z0-9_]+)([\s]*?):/', '\\1\\2"\\3" :', $json);
+  
+  return $json;
+}
+
+/**
+ * Starts the profiler.
+ */
+
+function profiler_start()
+{
+  global $_profiler;
+  $_profiler = array();
+  
+  if ( !defined('ENANO_DEBUG') )
+    return false;
+  
+  $_profiler[] = array(
+      'point' => 'Profiling started',
+      'time' => microtime_float(),
+      'backtrace' => false,
+      'mem' => false
+    );
+  if ( function_exists('memory_get_usage') )
+  {
+    $_profiler[ count($_profiler) - 1 ]['mem'] = memory_get_usage();
+  }
+}
+
+/**
+ * Logs something in the profiler.
+ * @param string Point name or message
+ * @param bool Optional. If true (default), a backtrace will be generated and added to the profiler data. False disables this, often for security reasons.
+ */
+
+function profiler_log($point, $allow_backtrace = true)
+{
+  if ( !defined('ENANO_DEBUG') )
+    return false;
+  
+  global $_profiler;
+  $backtrace = false;
+  if ( $allow_backtrace && function_exists('debug_print_backtrace') )
+  {
+    list(, $backtrace) = explode("\n", enano_debug_print_backtrace(true));
+  }
+  $_profiler[] = array(
+      'point' => $point,
+      'time' => microtime_float(),
+      'backtrace' => $backtrace,
+      'mem' => false
+    );
+  if ( function_exists('memory_get_usage') )
+  {
+    $_profiler[ count($_profiler) - 1 ]['mem'] = memory_get_usage();
+  }
+}
+
+/**
+ * Returns the profiler's data (so far).
+ * @return array
+ */
+
+function profiler_dump()
+{
+  return $GLOBALS['_profiler'];
+}
+
+/**
+ * Generates an HTML version of the performance profile. Not localized because only used as a debugging tool.
+ * @return string
+ */
+
+function profiler_make_html()
+{
+  if ( !defined('ENANO_DEBUG') )
+    return '';
+    
+  $profile = profiler_dump();
+  
+  $html = '<div class="tblholder">';
+  $html .= '<table border="0" cellspacing="1" cellpadding="4">';
+  
+  $time_start = $time_last = $profile[0]['time'];
+  
+  foreach ( $profile as $i => $entry )
+  {
+    $html .= "<!-- ########################################################## -->\n<tr>\n  <th colspan=\"2\">Event $i</th>\n</tr>";
+    
+    $html .= '<tr>' . "\n";
+    $html .= '  <td class="row2">Event:</td>' . "\n";
+    $html .= '  <td class="row1">' . htmlspecialchars($entry['point']) . '</td>' . "\n";
+    $html .= '</tr>' . "\n";
+    
+    $time = $entry['time'] - $time_start;
+    
+    $html .= '<tr>' . "\n";
+    $html .= '  <td class="row2">Time since start:</td>' . "\n";
+    $html .= '  <td class="row1">' . $time . 's</td>' . "\n";
+    $html .= '</tr>' . "\n";
+    
+    $time = $entry['time'] - $time_last;
+    if ( $time < 0.0001 )
+      $time = 'Marginal';
+    else
+      $time = "{$time}s";
+    
+    $html .= '<tr>' . "\n";
+    $html .= '  <td class="row2">Time since last event:</td>' . "\n";
+    $html .= '  <td class="row1">' . $time . '</td>' . "\n";
+    $html .= '</tr>' . "\n";
+    
+    if ( $entry['backtrace'] )
+    {
+      $html .= '<tr>' . "\n";
+      $html .= '  <td class="row2">Called from:</td>' . "\n";
+      $html .= '  <td class="row1">' . htmlspecialchars($entry['backtrace']) . '</td>' . "\n";
+      $html .= '</tr>' . "\n";
+    }
+    
+    if ( $entry['mem'] )
+    {
+      $html .= '<tr>' . "\n";
+      $html .= '  <td class="row2">Total mem usage:</td>' . "\n";
+      $html .= '  <td class="row1">' . htmlspecialchars($entry['mem']) . ' (bytes)</td>' . "\n";
+      $html .= '</tr>' . "\n";
+    }
+    
+    $html .= "\n";
+    
+    $time_last = $entry['time'];
+  }
+  $html .= '</table></div>';
+  
+  return $html;
+}
+
+// Might as well start the profiler, it has no external dependencies except from this file.
+profiler_start();
+
+/**
+ * Returns the number of times a character occurs in a given string.
+ * @param string Haystack
+ * @param string Needle
+ * @return int
+ */
+
+function get_char_count($string, $char)
+{
+  $char = substr($char, 0, 1);
+  $count = 0;
+  for ( $i = 0; $i < strlen($string); $i++ )
+  {
+    if ( $string{$i} == $char )
+      $count++;
+  }
+  return $count;
+}
+
+/**
+ * Returns the number of lines in a string.
+ * @param string String to check
+ * @return int
+ */
+
+function get_line_count($string)
+{
+  return ( get_char_count($string, "\n") ) + 1;
+}
+
 //die('<pre>Original:  01010101010100101010100101010101011010'."\nProcessed: ".uncompress_bitfield(compress_bitfield('01010101010100101010100101010101011010')).'</pre>');
 
 ?>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/includes/http.php	Fri Feb 22 12:51:53 2008 -0500
@@ -0,0 +1,793 @@
+<?php
+
+/*
+ * Enano - an open-source CMS capable of wiki functions, Drupal-like sidebar blocks, and everything in between
+ * Version 1.1.2 (Caoineag alpha 2)
+ * Copyright (C) 2006-2007 Dan Fuhry
+ * class_http.php - Pure PHP HTTP client library
+ *
+ * This program is Free Software; you can redistribute and/or modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.
+ *
+ * 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.
+ */
+
+//
+// HTTP status codes
+//
+
+// Informational
+define('HTTP_CONTINUE', 100);
+define('HTTP_SWITCHING_PROTOCOLS', 101);
+define('HTTP_PROCESSING', 102);
+
+// Success
+define('HTTP_OK', 200);
+define('HTTP_CREATED', 201);
+define('HTTP_ACCEPTED', 202);
+define('HTTP_NON_AUTHORITATIVE', 203);
+define('HTTP_NO_CONTENT', 204);
+define('HTTP_RESET_CONTENT', 205);
+define('HTTP_PARTIAL_CONTENT', 206);
+define('HTTP_MULTI_STATUS', 207);
+
+// Redirection
+define('HTTP_MULTIPLE_CHOICES', 300);
+define('HTTP_MOVED_PERMANENTLY', 301);
+define('HTTP_FOUND', 302);
+define('HTTP_SEE_OTHER', 303);
+define('HTTP_NOT_MODIFIED', 304);
+define('HTTP_USE_PROXY', 305);
+define('HTTP_SWITCH_PROXY', 306);
+define('HTTP_TEMPORARY_REDIRECT', 307);
+
+// Client Error
+define('HTTP_BAD_REQUEST', 400);
+define('HTTP_UNAUTHORIZED', 401);
+define('HTTP_PAYMENT_REQUIRED', 402);
+define('HTTP_FORBIDDEN', 403);
+define('HTTP_NOT_FOUND', 404);
+define('HTTP_METHOD_NOT_ALLOWED', 405);
+define('HTTP_NOT_ACCEPTABLE', 406);
+define('HTTP_PROXY_AUTHENTICATION_REQUIRED', 407);
+define('HTTP_REQUEST_TIMEOUT', 408);
+define('HTTP_CONFLICT', 409);
+define('HTTP_GONE', 410);
+define('HTTP_LENGTH_REQUIRED', 411);
+define('HTTP_PRECONDITION_FAILED', 412);
+define('HTTP_REQUEST_ENTITY_TOO_LARGE', 413);
+define('HTTP_REQUEST_URI_TOO_LONG', 414);
+define('HTTP_UNSUPPORTED_MEDIA_TYPE', 415);
+define('HTTP_REQUESTED_RANGE_NOT_SATISFIABLE', 416);
+define('HTTP_EXPECTATION_FAILED', 417);
+define('HTTP_UNPROCESSABLE_ENTITY', 422);
+define('HTTP_LOCKED', 423);
+define('HTTP_FAILED_DEPENDENCY', 424);
+define('HTTP_UNORDERED_COLLECTION', 425);
+define('HTTP_UPGRADE_REQUIRED', 426);
+define('HTTP_RETRY_WITH', 449);
+
+// Server error
+define('HTTP_INTERNAL_SERVER_ERROR', 500);
+define('HTTP_NOT_IMPLEMENTED', 501);
+define('HTTP_BAD_GATEWAY', 502);
+define('HTTP_SERVICE_TEMPORARILY_UNAVAILABLE', 503);
+define('HTTP_GATEWAY_TIMEOUT', 504);
+define('HTTP_HTTP_VERSION_NOT_SUPPORTED', 505);
+define('HTTP_VARIANT_ALSO_NEGOTIATES', 506);
+define('HTTP_INSUFFICIENT_STORAGE', 507);
+define('HTTP_BANDWIDTH_LIMIT_EXCEEDED', 509);
+define('HTTP_NOT_EXTENDED', 510);
+
+/**
+ * Class for making HTTP requests. This can do GET and POST, and when used properly it consumes under a meg of memory, even with huge files.
+ * @package Enano
+ * @subpackage Backend functions
+ * @copyright 2007 Dan Fuhry
+ */
+
+class Request_HTTP
+{
+  
+  /**
+   * Switch to enable or disable debugging. You want this off on production sites.
+   * @var bool
+   */
+  
+  var $debug = false;
+  
+  /**
+   * The host the request will be sent to.
+   * @var string
+   */
+  
+  var $host = '';
+  
+  /**
+   * The TCP port our connection is (will be) on.
+   * @var int
+   */
+  
+  var $port = 80;
+  
+  /**
+   * The request method. Can be GET or POST, defaults to GET.
+   * @var string
+   */
+  
+  var $method = 'GET';
+  
+  /**
+   * The URI to the remote script.
+   * @var string
+   */
+  
+  var $uri = '';
+  
+  /**
+   * The parameters to be sent on GET.
+   * @var array (associative)
+   */
+  
+  var $parms_get = array();
+  
+  /**
+   * The parameters to be sent on POST. Ignored if $this->method == GET.
+   * @var array (associative)
+   */
+  
+  var $parms_post = array();
+  
+  /**
+   * The list of cookies that will be sent.
+   * @var array (associative)
+   */
+  
+  var $cookies_out = array();
+  
+  /**
+   * Additional request headers.
+   * @var array (associative)
+   */
+  
+  var $headers = array();
+  
+  /**
+   * Cached response.
+   * @var string, or bool:false if the request hasn't been sent yet
+   */
+  
+  var $response = false;
+  
+  /**
+   * Cached response code
+   * @var int set to -1 if request hasn't been sent yet
+   */
+  
+  var $response_code = -1;
+  
+  /**
+   * Cached response code string
+   * @var string or bool:false if the request hasn't been sent yet
+   */
+  
+  var $response_string = false;
+  
+  /**
+   * Resource for the socket. False if a connection currently isn't going.
+   * @var resource
+   */
+  
+  var $socket = false;
+  
+  /**
+   * The state of our request. 0 means it hasn't been made yet. 1 means the socket is open, 2 means the socket is open and the request has been written, 3 means the headers have been fetched, and 4 means the request is completed.
+   * @var int
+   */
+  
+  var $state = 0;
+  
+  /**
+   * Constructor.
+   * @param string Hostname to send to
+   * @param string URI (/index.php)
+   * @param string Request method - GET or POST.
+   * @param int Optional. The port to open the request on. Defaults to 80.
+   */
+  
+  function Request_HTTP($host, $uri, $method = 'GET', $port = 80)
+  {
+    if ( !preg_match('/^(([a-z0-9-]+\.)*?)([a-z0-9-]+)$/', $host) )
+      die(__CLASS__ . ': Invalid hostname');
+    $this->host = $host;
+    $this->uri = $uri;
+    if ( is_int($port) && $port >= 1 && $port <= 65535 )
+      $this->port = $port;
+    else
+      die(__CLASS__ . ': Invalid port');
+    $method = strtoupper($method);
+    if ( $method == 'GET' || $method == 'POST' )
+      $this->method = $method;
+    else
+      die(__CLASS__ . ': Invalid request method');
+      
+    $newline = "\r\n";
+    $php_ver = PHP_VERSION;
+    $this->add_header('User-Agent', "PHP/$php_ver (Server: {$_SERVER['SERVER_SOFTWARE']}; automated bot request)");
+  }
+  
+  /**
+   * Sets one or more cookies to be sent to the server.
+   * @param string or array If a string, the cookie name. If an array, associative array in the form of cookiename => cookievalue
+   * @param string or bool If a string, the cookie value. If boolean, defaults to false, param 1 should be an array, and this should not be passed.
+   */
+  
+  function add_cookie($cookiename, $cookievalue = false)
+  {
+    if ( is_array($cookiename) && !$cookievalue )
+    {
+      foreach ( $cookiename as $name => $value )
+      {
+        $this->cookies_out[$name] = $value;
+      }
+    }
+    else if ( is_string($cookiename) && is_string($cookievalue) )
+    {
+      $this->cookies_out[$cookiename] = $cookievalue;
+    }
+    else
+    {
+      die(__CLASS__ . '::' . __METHOD__ . ': Invalid argument(s)');
+    }
+  }
+  
+  /**
+   * Sets one or more request header values.
+   * @param string or array If a string, the header name. If an array, associative array in the form of headername => headervalue
+   * @param string or bool If a string, the header value. If boolean, defaults to false, param 1 should be an array, and this should not be passed.
+   */
+  
+  function add_header($headername, $headervalue = false)
+  {
+    if ( is_array($headername) && !$headervalue )
+    {
+      foreach ( $headername as $name => $value )
+      {
+        $this->headers[$name] = $value;
+      }
+    }
+    else if ( is_string($headername) && is_string($headervalue) )
+    {
+      $this->headers[$headername] = $headervalue;
+    }
+    else
+    {
+      die(__CLASS__ . '::' . __METHOD__ . ': Invalid argument(s)');
+    }
+  }
+  
+  /**
+   * Adds one or more values to be passed on GET.
+   * @param string or array If a string, the parameter name. If an array, associative array in the form of parametername => parametervalue
+   * @param string or bool If a string, the parameter value. If boolean, defaults to false, param 1 should be an array, and this should not be passed.
+   */
+  
+  function add_get($getname, $getvalue = false)
+  {
+    if ( is_array($getname) && !$getvalue )
+    {
+      foreach ( $getname as $name => $value )
+      {
+        $this->parms_get[$name] = $value;
+      }
+    }
+    else if ( is_string($getname) && is_string($getvalue) )
+    {
+      $this->parms_get[$getname] = $getvalue;
+    }
+    else
+    {
+      die(__CLASS__ . '::' . __METHOD__ . ': Invalid argument(s)');
+    }
+  }
+  
+  /**
+   * Adds one or more values to be passed on POST.
+   * @param string or array If a string, the header name. If an array, associative array in the form of headername => headervalue
+   * @param string or bool If a string, the header value. If boolean, defaults to false, param 1 should be an array, and this should not be passed.
+   */
+  
+  function add_post($postname, $postvalue = false)
+  {
+    if ( is_array($postname) && !$postvalue )
+    {
+      foreach ( $postname as $name => $value )
+      {
+        $this->parms_post[$name] = $value;
+      }
+    }
+    else if ( is_string($postname) && is_string($postvalue) )
+    {
+      $this->parms_post[$postname] = $postvalue;
+    }
+    else
+    {
+      die(__CLASS__ . '::' . __METHOD__ . ': Invalid argument(s)');
+    }
+  }
+  
+  /**
+   * Internal function to open up the socket.
+   * @access private
+   */
+  
+  function _sock_open(&$connection)
+  {
+    // Open connection
+    $connection = fsockopen($this->host, $this->port);
+    if ( !$connection )
+      die(__CLASS__ . '::' . __METHOD__ . ': Could not make connection');
+    
+    // 1 = socket open
+    $this->state = 1;
+  }
+  
+  /**
+   * Internal function to actually write the request into the socket.
+   * @access private
+   */
+  
+  function _write_request(&$connection, &$headers, &$cookies, &$get, &$post)
+  {
+    $newline = "\r\n";
+    
+    if ( $this->debug )
+      echo '<p>Connection opened. Writing main request to socket. Raw socket data follows.</p><pre>';
+    
+    if ( $this->debug )
+    {
+      echo '<hr /><div style="white-space: nowrap;">';
+      echo '<p><b>' . __CLASS__ . ': Sending request</b></p><p>Request parameters:</p>';
+      echo "<p><b>Headers:</b></p><pre>$headers</pre>";
+      echo "<p><b>Cookies:</b> $cookies</p>";
+      echo "<p><b>GET URI:</b> " . htmlspecialchars($this->uri . $get) . "</p>";
+      echo "<p><b>POST DATA:</b> " . htmlspecialchars($post) . "</p>";
+      echo "<pre>";
+    }
+    
+    $this->_fputs($connection, "{$this->method} {$this->uri}{$get} HTTP/1.1{$newline}");
+    $this->_fputs($connection, "Host: {$this->host}{$newline}");
+    $this->_fputs($connection, $headers);
+    $this->_fputs($connection, $cookies);
+    
+    if ( $this->method == 'POST' )
+    {
+      // POST-specific parameters
+      $post_length = strlen($post);
+      $this->_fputs($connection, "Content-type: application/x-www-form-urlencoded{$newline}");
+      $this->_fputs($connection, "Content-length: {$post_length}{$newline}");
+    }
+    
+    $this->_fputs($connection, "Connection: close{$newline}");
+    $this->_fputs($connection, "{$newline}");
+    
+    if ( $this->method == 'POST' )
+    {
+      $this->_fputs($connection, $post);
+    }
+    
+    if ( $this->debug )
+      echo '</pre><p>Request written. Fetching response.</p>';
+    
+    // 2 = request written
+    $this->state = 2;
+  }
+  
+  /**
+   * Wrap up and close the socket. Nothing more than a call to fsockclose() except in debug mode.
+   * @access private
+   */
+  
+  function sock_close(&$connection)
+  {
+    if ( $this->debug )
+    {
+      echo '<p>Response fetched. Closing connection. Response text follows.</p><pre>';
+      echo htmlspecialchars($this->response);
+      echo '</pre></div><hr />';
+    }
+    
+    fclose($connection);
+  }
+  
+  /**
+   * Internal function to grab the response code and status string
+   * @access string
+   */
+  
+  function _parse_response_code($buffer)
+  {
+    // Retrieve response code and status
+    $pos_newline = strpos($buffer, "\n");
+    $pos_carriage_return = strpos($buffer, "\r");
+    $pos_end_first_line = ( $pos_carriage_return < $pos_newline && $pos_carriage_return > 0 ) ? $pos_carriage_return : $pos_newline;
+    
+    // First line is in format of:
+    // HTTP/1.1 ### Blah blah blah(\r?)\n
+    $response_code = substr($buffer, 9, 3);
+    $response_string = substr($buffer, 13, ( $pos_end_first_line - 13 ) );
+    $this->response_code = intval($response_code);
+    $this->response_string = $response_string;
+  }
+  
+  /**
+   * Internal function to send the request.
+   * @access private
+   */
+  
+  function _send_request()
+  {
+    $this->concat_headers($headers, $cookies, $get, $post);
+    
+    if ( $this->state < 1 )
+    {
+      $this->_sock_open($this->socket);
+    }
+    if ( $this->state < 2 )
+    {
+      $this->_write_request($this->socket, $headers, $cookies, $get, $post);
+    }
+    if ( $this->state == 2 )
+    {
+      $buffer = $this->_read_until_newlines($this->socket);
+      $this->state = 3;
+      $this->_parse_response_code($buffer);
+      $this->response = $buffer;
+    }
+    if ( $this->state == 3 )
+    {
+      // Determine transfer encoding
+      $is_chunked = preg_match("/Transfer-Encoding: (chunked)\r?\n/", $this->response);
+      
+      $buffer = '';
+      while ( !feof($this->socket) )
+      {
+        $part = fgets($this->socket, 1024);
+        if ( $is_chunked && preg_match("/^([a-f0-9]+)\x0D\x0A$/", $part, $match) )
+        {
+          $chunklen = hexdec($match[1]);
+          $part = ( $chunklen > 0 ) ? fread($this->socket, $chunklen) : '';
+          // remove the last newline from $part
+          $part = preg_replace("/\r?\n\$/m", "", $part);
+        }
+        $buffer .= $part;
+      }
+      $this->response .= $buffer;
+    }
+    $this->state = 4;
+    
+    $this->sock_close($this->socket);
+    $this->socket = false;
+  }
+  
+  /**
+   * Internal function to send the request but only fetch the headers. Leaves a connection open for a finish-up function.
+   * @access private
+   */
+  
+  function _send_request_headers_only()
+  {
+    $this->concat_headers($headers, $cookies, $get, $post);
+    
+    if ( $this->state < 1 )
+    {
+      $this->_sock_open($this->socket);
+    }
+    if ( $this->state < 2 )
+    {
+      $this->_write_request($this->socket, $headers, $cookies, $get, $post);
+    }
+    if ( $this->state == 2 )
+    {
+      $buffer = $this->_read_until_newlines($this->socket);
+      $this->state = 3;
+      $this->_parse_response_code($buffer);
+      $this->response = $buffer;
+    }
+  }
+  
+  /**
+   * Internal function to read from a socket until two consecutive newlines are hit.
+   * @access private
+   */
+  
+  function _read_until_newlines($sock)
+  {
+    $prev_char = '';
+    $prev1_char = '';
+    $prev2_char = '';
+    $buf = '';
+    while ( !feof($sock) )
+    {
+      $chr = fread($sock, 1);
+      $buf .= $chr;
+      if ( ( $chr == "\n" && $prev_char == "\n" ) ||
+           ( $chr == "\n" && $prev_char == "\r" && $prev1_char == "\n" && $prev2_char == "\r" ) )
+      {
+        return $buf;
+      }
+      $prev2_char = $prev1_char;
+      $prev1_char = $prev_char;
+      $prev_char = $chr;
+    }
+    return $buf;
+  }
+  
+  /**
+   * Returns the response text. If the request hasn't been sent, it will be sent here.
+   * @return string
+   */
+  
+  function get_response()
+  {
+    if ( $this->state == 4 )
+      return $this->response;
+    $this->_send_request();
+    return $this->response;
+  }
+  
+  /**
+   * Writes the response body to a file. This is good for conserving memory when downloading large files. If the file already exists it will be overwritten.
+   * @param string File to write to
+   * @param int Chunk size in KB to read from the socket. Optional and should only be needed in circumstances when extreme memory conservation is needed. Defaults to 768.
+   * @param int Maximum file size. Defaults to 0, which means no limit.
+   * @return bool True on success, false on failure
+   */
+  
+  function write_response_to_file($file, $chunklen = 768, $max_file_size = 0)
+  {
+    if ( !is_writeable( dirname($file) ) || !file_exists( dirname($file) ) )
+    {
+      return false;
+    }
+    $handle = @fopen($file, 'w');
+    if ( !$handle )
+      return false;
+    $chunklen = intval($chunklen);
+    if ( $chunklen < 1 )
+      return false;
+    if ( $this->state == 4 )
+    {
+      // we already have the response, so cheat
+      $response = $this->get_response_body();
+      fwrite($handle, $response);
+    }
+    else
+    {
+      // read data from the socket, write it immediately, and unset to free memory
+      $headers = $this->get_response_headers();
+      $transferred_bytes = 0;
+      $bandwidth_exceeded = false;
+      // if transfer-encoding is chunked, read using chunk sizes the server specifies
+      $is_chunked = preg_match("/Transfer-Encoding: (chunked)\r?\n/", $this->response);
+      if ( $is_chunked )
+      {
+        $buffer = '';
+        while ( !feof($this->socket) )
+        {
+          $part = fgets($this->socket, ( 1024 * $chunklen ));
+          // Theoretically if the encoding is really chunked then this should always match.
+          if ( $is_chunked && preg_match("/^([a-f0-9]+)\x0D\x0A$/", $part, $match) )
+          {
+            $chunk_length = hexdec($match[1]);
+            $part = ( $chunk_length > 0 ) ? fread($this->socket, $chunk_length) : '';
+            // remove the last newline from $part
+            $part = preg_replace("/\r?\n\$/m", "", $part);
+          }
+          
+          $transferred_bytes += strlen($part);
+          if ( $max_file_size && $transferred_bytes > $max_file_size )
+          {
+            // truncate output to $max_file_size bytes
+            $partlen = $max_file_size - ( $transferred_bytes - strlen($part) );
+            $part = substr($part, 0, $partlen);
+            $bandwidth_exceeded = true;
+          }
+          fwrite($handle, $part);
+          if ( $bandwidth_exceeded )
+          {
+            break;
+          }
+        }
+      }
+      else
+      {
+        $first_chunk = fread($this->socket, ( 1024 * $chunklen ));
+        fwrite($handle, $first_chunk);
+        while ( !feof($this->socket) )
+        {
+          $chunk = fread($this->socket, ( 1024 * $chunklen ));
+          
+          $transferred_bytes += strlen($chunk);
+          if ( $max_file_size && $transferred_bytes > $max_file_size )
+          {
+            // truncate output to $max_file_size bytes
+            $partlen = $max_file_size - ( $transferred_bytes - strlen($chunk) );
+            $chunk = substr($chunk, 0, $partlen);
+            $bandwidth_exceeded = true;
+          }
+          
+          fwrite($handle, $chunk);
+          unset($chunk);
+          
+          if ( $bandwidth_exceeded )
+          {
+            break;
+          }
+        }
+      }
+    }
+    fclose($handle);
+    // close socket and reset state, since we haven't cached the response
+    $this->sock_close($this->socket);
+    $this->state = 0;
+    return ($bandwidth_exceeded) ? false : true;
+  }
+  
+  /**
+   * Returns only the response headers.
+   * @return string
+   */
+  
+  function get_response_headers()
+  {
+    if ( $this->state == 3 )
+    {
+      return $this->response;
+    }
+    else if ( $this->state == 4 )
+    {
+      $pos_end = strpos($this->response, "\r\n\r\n");
+      $data = substr($this->response, 0, $pos_start);
+      return $data;
+    }
+    else
+    {
+      $this->_send_request_headers_only();
+      return $this->response;
+    }
+  }
+  
+  /**
+   * Returns only the response headers, as an associative array.
+   * @return array
+   */
+  
+  function get_response_headers_array()
+  {
+    $data = $this->get_response_headers();
+    preg_match_all("/(^|\n)([A-z0-9_-]+?): (.+?)(\r|\n|\$)/", $data, $matches);
+    $headers = array();
+    for ( $i = 0; $i < count($matches[0]); $i++ )
+    {
+      $headers[ $matches[2][$i] ] = $matches[3][$i];
+    }
+    return $headers;
+  }
+  
+  /**
+   * Returns only the body (not the headers) of the response. If the request hasn't been sent, it will be sent here.
+   * @return string
+   */
+  
+  function get_response_body()
+  {
+    $data = $this->get_response();
+    $pos_start = strpos($data, "\r\n\r\n") + 4;
+    $data = substr($data, $pos_start);
+    return $data;
+  }
+  
+  /**
+   * Returns all cookies requested to be set by the server as an associative array. If the request hasn't been sent, it will be sent here.
+   * @return array
+   */
+  
+  function get_cookies()
+  {
+    $data = $this->get_response();
+    $data = str_replace("\r\n", "\n", $data);
+    $pos = strpos($data, "\n\n");
+    $headers = substr($data, 0, $pos);
+    preg_match_all("/Set-Cookie: ([a-z0-9_]+)=([^;]+);( expires=([^;]+);)?( path=(.*?))?\n/", $headers, $cookiematch);
+    if ( count($cookiematch[0]) < 1 )
+      return array();
+    $cookies = array();
+    foreach ( $cookiematch[0] as $i => $cookie )
+    {
+      $cookies[$cookiematch[1][$i]] = $cookiematch[2][$i];
+    }
+    return $cookies;
+  }
+  
+  /**
+   * Internal method to write data to a socket with debugging possibility.
+   * @access private
+   */
+  
+  function _fputs($socket, $data)
+  {
+    if ( $this->debug )
+      echo htmlspecialchars($data);
+    return fputs($socket, $data);
+  }
+  
+  /**
+   * Internal function to stringify cookies, headers, get, and post.
+   * @access private
+   */
+  
+  function concat_headers(&$headers, &$cookies, &$get, &$post)
+  {
+    $headers = '';
+    $cookies = '';
+    foreach ( $this->headers as $name => $value )
+    {
+      $value = str_replace('\\n', '\\\\n', $value);
+      $value = str_replace("\n", '\\n', $value);
+      $headers .= "$name: $value\r\n";
+    }
+    unset($value);
+    if ( count($this->cookies_out) > 0 )
+    {
+      $i = 0;
+      $cookie_header = 'Cookie: ';
+      foreach ( $this->cookies_out as $name => $value )
+      {
+        $i++;
+        if ( $i > 1 )
+          $cookie_header .= '; ';
+        $value = str_replace(';', rawurlencode(';'), $value);
+        $value = str_replace('\\n', '\\\\n', $value);
+        $value = str_replace("\n", '\\n', $value);
+        $cookie_header .= "$name=$value";
+      }
+      $cookie_header .= "\r\n";
+      $cookies = $cookie_header;
+      unset($value, $cookie_header);
+    }
+    if ( count($this->parms_get) > 0 )
+    {
+      $get = '?';
+      $i = 0;
+      foreach ( $this->parms_get as $name => $value )
+      {
+        $i++;
+        if ( $i > 1 )
+          $get .= '&';
+        $value = urlencode($value);
+        if ( !empty($value) )
+          $get .= "$name=$value";
+        else
+          $get .= "$name";
+      }
+    }
+    if ( count($this->parms_post) > 0 )
+    {
+      $post = '';
+      $i = 0;
+      foreach ( $this->parms_post as $name => $value )
+      {
+        $i++;
+        if ( $i > 1 )
+          $post .= '&';
+        $value = urlencode($value);
+        $post .= "$name=$value";
+      }
+    }
+  }
+  
+}
+
+?>
--- a/includes/js-compressor.php	Fri Feb 22 12:46:51 2008 -0500
+++ b/includes/js-compressor.php	Fri Feb 22 12:51:53 2008 -0500
@@ -2,7 +2,7 @@
 
 /*
  * Enano - an open-source CMS capable of wiki functions, Drupal-like sidebar blocks, and everything in between
- * Version 1.0.3 (Dyrad)
+ * Version 1.1.2 (Caoineag alpha 2)
  * Copyright (C) 2006-2007 Dan Fuhry
  * Javascript compression library - used to compact the client-side Javascript code (all 72KB of it!) to save some bandwidth
  *
@@ -107,7 +107,7 @@
 	 * public constructor
          * 	creates a new BaseConvert class variable (base 36)
 	 */
-	function JavaScriptCompressor() {
+	function __construct() {
 		$this->__SourceMap = new SourceMap();
 		$this->__BC = new BaseConvert('0123456789abcdefghijklmnopqrstuvwxyz');
 		$this->__delimeter = array(
@@ -493,4 +493,35 @@
         return (($next - 1) % 2 === 0);
     }
 }
+
+/**
+ * Wrapper for the JavaScriptCompressor class.
+ * @param string Javascript code to compact. If this doesn't contain any newline characters, will be treated as a filename.
+ * @param bool If true, aggressively compresses the code. Otherwise, just strips comments and some whitespace.
+ * @return string Compressed JS
+ */
+
+function perform_js_compress($text_or_file, $aggressive = false)
+{
+  static $compressor = false;
+  
+  if ( !is_object($compressor) )
+    $compressor = new JavaScriptCompressor();
+  
+  if ( strpos($text_or_file, "\n") )
+  {
+    $text =& $text_or_file;
+  }
+  else if ( file_exists($text_or_file) )
+  {
+    $text = file_get_contents($text_or_file);
+  }
+  else
+  {
+    $text =& $text_or_file;
+  }
+  
+  return ( $aggressive ) ? $compressor->getPacked($text) : $compressor->getClean($text);
+}
+
 ?>
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/includes/json2.php	Fri Feb 22 12:51:53 2008 -0500
@@ -0,0 +1,1015 @@
+<?php
+/**
+ * Zend Framework
+ *
+ * LICENSE
+ *
+ * This source file is subject to the new BSD license that is bundled
+ * with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://framework.zend.com/license/new-bsd
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@zend.com so we can send you a copy immediately.
+ *
+ * @category   Zend
+ * @package    Zend_Json
+ * @copyright  Copyright (c) 2005-2007 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ */
+
+
+/**
+ * Encode PHP constructs to JSON
+ *
+ * @category   Zend
+ * @package    Zend_Json
+ * @copyright  Copyright (c) 2005-2007 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ */
+class Zend_Json_Encoder
+{
+    /**
+     * Whether or not to check for possible cycling
+     *
+     * @var boolean
+     */
+    protected $_cycleCheck;
+
+    /**
+     * Array of visited objects; used to prevent cycling.
+     *
+     * @var array
+     */
+    protected $_visited = array();
+
+    /**
+     * Constructor
+     *
+     * @param boolean $cycleCheck Whether or not to check for recursion when encoding
+     * @return void
+     */
+    protected function __construct($cycleCheck = false)
+    {
+        $this->_cycleCheck = $cycleCheck;
+    }
+
+    /**
+     * Use the JSON encoding scheme for the value specified
+     *
+     * @param mixed $value The value to be encoded
+     * @param boolean $cycleCheck Whether or not to check for possible object recursion when encoding
+     * @return string  The encoded value
+     */
+    public static function encode($value, $cycleCheck = false)
+    {
+        $encoder = new Zend_Json_Encoder(($cycleCheck) ? true : false);
+
+        return $encoder->_encodeValue($value);
+    }
+
+    /**
+     * Recursive driver which determines the type of value to be encoded
+     * and then dispatches to the appropriate method. $values are either
+     *    - objects (returns from {@link _encodeObject()})
+     *    - arrays (returns from {@link _encodeArray()})
+     *    - basic datums (e.g. numbers or strings) (returns from {@link _encodeDatum()})
+     *
+     * @param $value mixed The value to be encoded
+     * @return string Encoded value
+     */
+    protected function _encodeValue(&$value)
+    {
+        if (is_object($value)) {
+            return $this->_encodeObject($value);
+        } else if (is_array($value)) {
+            return $this->_encodeArray($value);
+        }
+
+        return $this->_encodeDatum($value);
+    }
+
+
+
+    /**
+     * Encode an object to JSON by encoding each of the public properties
+     *
+     * A special property is added to the JSON object called '__className'
+     * that contains the name of the class of $value. This is used to decode
+     * the object on the client into a specific class.
+     *
+     * @param $value object
+     * @return string
+     * @throws Zend_Json_Exception If recursive checks are enabled and the object has been serialized previously
+     */
+    protected function _encodeObject(&$value)
+    {
+        if ($this->_cycleCheck) {
+            if ($this->_wasVisited($value)) {
+                throw new Zend_Json_Exception(
+                    'Cycles not supported in JSON encoding, cycle introduced by '
+                    . 'class "' . get_class($value) . '"'
+                );
+            }
+
+            $this->_visited[] = $value;
+        }
+
+        $props = '';
+        foreach (get_object_vars($value) as $name => $propValue) {
+            if (isset($propValue)) {
+                $props .= ','
+                        . $this->_encodeValue($name)
+                        . ':'
+                        . $this->_encodeValue($propValue);
+            }
+        }
+
+        return '{"__className":"' . get_class($value) . '"'
+                . $props . '}';
+    }
+
+
+    /**
+     * Determine if an object has been serialized already
+     *
+     * @param mixed $value
+     * @return boolean
+     */
+    protected function _wasVisited(&$value)
+    {
+        if (in_array($value, $this->_visited, true)) {
+            return true;
+        }
+
+        return false;
+    }
+
+
+    /**
+     * JSON encode an array value
+     *
+     * Recursively encodes each value of an array and returns a JSON encoded
+     * array string.
+     *
+     * Arrays are defined as integer-indexed arrays starting at index 0, where
+     * the last index is (count($array) -1); any deviation from that is
+     * considered an associative array, and will be encoded as such.
+     *
+     * @param $array array
+     * @return string
+     */
+    protected function _encodeArray(&$array)
+    {
+        $tmpArray = array();
+
+        // Check for associative array
+        if (!empty($array) && (array_keys($array) !== range(0, count($array) - 1))) {
+            // Associative array
+            $result = '{';
+            foreach ($array as $key => $value) {
+                $key = (string) $key;
+                $tmpArray[] = $this->_encodeString($key)
+                            . ':'
+                            . $this->_encodeValue($value);
+            }
+            $result .= implode(',', $tmpArray);
+            $result .= '}';
+        } else {
+            // Indexed array
+            $result = '[';
+            $length = count($array);
+            for ($i = 0; $i < $length; $i++) {
+                $tmpArray[] = $this->_encodeValue($array[$i]);
+            }
+            $result .= implode(',', $tmpArray);
+            $result .= ']';
+        }
+
+        return $result;
+    }
+
+
+    /**
+     * JSON encode a basic data type (string, number, boolean, null)
+     *
+     * If value type is not a string, number, boolean, or null, the string
+     * 'null' is returned.
+     *
+     * @param $value mixed
+     * @return string
+     */
+    protected function _encodeDatum(&$value)
+    {
+        $result = 'null';
+
+        if (is_int($value) || is_float($value)) {
+            $result = (string)$value;
+        } elseif (is_string($value)) {
+            $result = $this->_encodeString($value);
+        } elseif (is_bool($value)) {
+            $result = $value ? 'true' : 'false';
+        }
+
+        return $result;
+    }
+
+
+    /**
+     * JSON encode a string value by escaping characters as necessary
+     *
+     * @param $value string
+     * @return string
+     */
+    protected function _encodeString(&$string)
+    {
+        // Escape these characters with a backslash:
+        // " \ / \n \r \t \b \f
+        $search  = array('\\', "\n", "\t", "\r", "\b", "\f", '"');
+        $replace = array('\\\\', '\\n', '\\t', '\\r', '\\b', '\\f', '\"');
+        $string  = str_replace($search, $replace, $string);
+
+        // Escape certain ASCII characters:
+        // 0x08 => \b
+        // 0x0c => \f
+        $string = str_replace(array(chr(0x08), chr(0x0C)), array('\b', '\f'), $string);
+
+        return '"' . $string . '"';
+    }
+
+
+    /**
+     * Encode the constants associated with the ReflectionClass
+     * parameter. The encoding format is based on the class2 format
+     *
+     * @param $cls ReflectionClass
+     * @return string Encoded constant block in class2 format
+     */
+    private static function _encodeConstants(ReflectionClass $cls)
+    {
+        $result    = "constants : {";
+        $constants = $cls->getConstants();
+
+        $tmpArray = array();
+        if (!empty($constants)) {
+            foreach ($constants as $key => $value) {
+                $tmpArray[] = "$key: " . self::encode($value);
+            }
+
+            $result .= implode(', ', $tmpArray);
+        }
+
+        return $result . "}";
+    }
+
+
+    /**
+     * Encode the public methods of the ReflectionClass in the
+     * class2 format
+     *
+     * @param $cls ReflectionClass
+     * @return string Encoded method fragment
+     *
+     */
+    private static function _encodeMethods(ReflectionClass $cls)
+    {
+        $methods = $cls->getMethods();
+        $result = 'methods:{';
+
+        $started = false;
+        foreach ($methods as $method) {
+            if (! $method->isPublic() || !$method->isUserDefined()) {
+                continue;
+            }
+
+            if ($started) {
+                $result .= ',';
+            }
+            $started = true;
+
+            $result .= '' . $method->getName(). ':function(';
+
+            if ('__construct' != $method->getName()) {
+                $parameters  = $method->getParameters();
+                $paramCount  = count($parameters);
+                $argsStarted = false;
+
+                $argNames = "var argNames=[";
+                foreach ($parameters as $param) {
+                    if ($argsStarted) {
+                        $result .= ',';
+                    }
+
+                    $result .= $param->getName();
+
+                    if ($argsStarted) {
+                        $argNames .= ',';
+                    }
+
+                    $argNames .= '"' . $param->getName() . '"';
+
+                    $argsStarted = true;
+                }
+                $argNames .= "];";
+
+                $result .= "){"
+                         . $argNames
+                         . 'var result = ZAjaxEngine.invokeRemoteMethod('
+                         . "this, '" . $method->getName()
+                         . "',argNames,arguments);"
+                         . 'return(result);}';
+            } else {
+                $result .= "){}";
+            }
+        }
+
+        return $result . "}";
+    }
+
+
+    /**
+     * Encode the public properties of the ReflectionClass in the class2
+     * format.
+     *
+     * @param $cls ReflectionClass
+     * @return string Encode properties list
+     *
+     */
+    private static function _encodeVariables(ReflectionClass $cls)
+    {
+        $properties = $cls->getProperties();
+        $propValues = get_class_vars($cls->getName());
+        $result = "variables:{";
+        $cnt = 0;
+
+        $tmpArray = array();
+        foreach ($properties as $prop) {
+            if (! $prop->isPublic()) {
+                continue;
+            }
+
+            $tmpArray[] = $prop->getName()
+                        . ':'
+                        . self::encode($propValues[$prop->getName()]);
+        }
+        $result .= implode(',', $tmpArray);
+
+        return $result . "}";
+    }
+
+    /**
+     * Encodes the given $className into the class2 model of encoding PHP
+     * classes into JavaScript class2 classes.
+     * NOTE: Currently only public methods and variables are proxied onto
+     * the client machine
+     *
+     * @param $className string The name of the class, the class must be
+     * instantiable using a null constructor
+     * @param $package string Optional package name appended to JavaScript
+     * proxy class name
+     * @return string The class2 (JavaScript) encoding of the class
+     * @throws Zend_Json_Exception
+     */
+    public static function encodeClass($className, $package = '')
+    {
+        $cls = new ReflectionClass($className);
+        if (! $cls->isInstantiable()) {
+            throw new Zend_Json_Exception("$className must be instantiable");
+        }
+
+        return "Class.create('$package$className',{"
+                . self::_encodeConstants($cls)    .","
+                . self::_encodeMethods($cls)      .","
+                . self::_encodeVariables($cls)    .'});';
+    }
+
+
+    /**
+     * Encode several classes at once
+     *
+     * Returns JSON encoded classes, using {@link encodeClass()}.
+     *
+     * @param array $classNames
+     * @param string $package
+     * @return string
+     */
+    public static function encodeClasses(array $classNames, $package = '')
+    {
+        $result = '';
+        foreach ($classNames as $className) {
+            $result .= self::encodeClass($className, $package);
+        }
+
+        return $result;
+    }
+
+}
+
+/**
+ * Decode JSON encoded string to PHP variable constructs
+ *
+ * @category   Zend
+ * @package    Zend_Json
+ * @copyright  Copyright (c) 2005-2007 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ */
+class Zend_Json_Decoder
+{
+    /**
+     * Parse tokens used to decode the JSON object. These are not
+     * for public consumption, they are just used internally to the
+     * class.
+     */
+    const EOF          = 0;
+    const DATUM        = 1;
+    const LBRACE       = 2;
+    const LBRACKET     = 3;
+    const RBRACE       = 4;
+    const RBRACKET     = 5;
+    const COMMA        = 6;
+    const COLON        = 7;
+
+    /**
+     * Use to maintain a "pointer" to the source being decoded
+     *
+     * @var string
+     */
+    protected $_source;
+
+    /**
+     * Caches the source length
+     *
+     * @var int
+     */
+    protected $_sourceLength;
+
+    /**
+     * The offset within the souce being decoded
+     *
+     * @var int
+     *
+     */
+    protected $_offset;
+
+    /**
+     * The current token being considered in the parser cycle
+     *
+     * @var int
+     */
+    protected $_token;
+
+    /**
+     * Flag indicating how objects should be decoded
+     *
+     * @var int
+     * @access protected
+     */
+    protected $_decodeType;
+
+    /**
+     * Constructor
+     *
+     * @param string $source String source to decode
+     * @param int $decodeType How objects should be decoded -- see
+     * {@link Zend_Json::TYPE_ARRAY} and {@link Zend_Json::TYPE_OBJECT} for
+     * valid values
+     * @return void
+     */
+    protected function __construct($source, $decodeType)
+    {
+        
+        // eliminate comments
+        $source = preg_replace(array(
+
+                  // eliminate single line comments in '// ...' form
+                  '#^\s*//(.+)$#m',
+    
+                  // eliminate multi-line comments in '/* ... */' form, at start of string
+                  '#^\s*/\*(.+)\*/#Us',
+    
+                  // eliminate multi-line comments in '/* ... */' form, at end of string
+                  '#/\*(.+)\*/\s*$#Us'
+    
+              ), '', $source);
+        
+        // Set defaults
+        $this->_source       = $source;
+        $this->_sourceLength = strlen($source);
+        $this->_token        = self::EOF;
+        $this->_offset       = 0;
+
+        // Normalize and set $decodeType
+        if (!in_array($decodeType, array(Zend_Json::TYPE_ARRAY, Zend_Json::TYPE_OBJECT)))
+        {
+            $decodeType = Zend_Json::TYPE_ARRAY;
+        }
+        $this->_decodeType   = $decodeType;
+
+        // Set pointer at first token
+        $this->_getNextToken();
+    }
+
+    /**
+     * Decode a JSON source string
+     *
+     * Decodes a JSON encoded string. The value returned will be one of the
+     * following:
+     *        - integer
+     *        - float
+     *        - boolean
+     *        - null
+     *      - StdClass
+     *      - array
+     *         - array of one or more of the above types
+     *
+     * By default, decoded objects will be returned as associative arrays; to
+     * return a StdClass object instead, pass {@link Zend_Json::TYPE_OBJECT} to
+     * the $objectDecodeType parameter.
+     *
+     * Throws a Zend_Json_Exception if the source string is null.
+     *
+     * @static
+     * @access public
+     * @param string $source String to be decoded
+     * @param int $objectDecodeType How objects should be decoded; should be
+     * either or {@link Zend_Json::TYPE_ARRAY} or
+     * {@link Zend_Json::TYPE_OBJECT}; defaults to TYPE_ARRAY
+     * @return mixed
+     * @throws Zend_Json_Exception
+     */
+    public static function decode($source = null, $objectDecodeType = Zend_Json::TYPE_ARRAY)
+    {
+        if (null === $source) {
+            throw new Zend_Json_Exception('Must specify JSON encoded source for decoding');
+        } elseif (!is_string($source)) {
+            throw new Zend_Json_Exception('Can only decode JSON encoded strings');
+        }
+
+        $decoder = new self($source, $objectDecodeType);
+
+        return $decoder->_decodeValue();
+    }
+
+
+    /**
+     * Recursive driving rountine for supported toplevel tops
+     *
+     * @return mixed
+     */
+    protected function _decodeValue()
+    {
+        switch ($this->_token) {
+            case self::DATUM:
+                $result  = $this->_tokenValue;
+                $this->_getNextToken();
+                return($result);
+                break;
+            case self::LBRACE:
+                return($this->_decodeObject());
+                break;
+            case self::LBRACKET:
+                return($this->_decodeArray());
+                break;
+            default:
+                return null;
+                break;
+        }
+    }
+
+    /**
+     * Decodes an object of the form:
+     *  { "attribute: value, "attribute2" : value,...}
+     *
+     * If ZJsonEnoder or ZJAjax was used to encode the original object
+     * then a special attribute called __className which specifies a class
+     * name that should wrap the data contained within the encoded source.
+     *
+     * Decodes to either an array or StdClass object, based on the value of
+     * {@link $_decodeType}. If invalid $_decodeType present, returns as an
+     * array.
+     *
+     * @return array|StdClass
+     */
+    protected function _decodeObject()
+    {
+        $members = array();
+        $tok = $this->_getNextToken();
+
+        while ($tok && $tok != self::RBRACE) {
+            if ($tok != self::DATUM || ! is_string($this->_tokenValue)) {
+                throw new Zend_Json_Exception('Missing key in object encoding: ' . $this->_source);
+            }
+
+            $key = $this->_tokenValue;
+            $tok = $this->_getNextToken();
+
+            if ($tok != self::COLON) {
+                throw new Zend_Json_Exception('Missing ":" in object encoding: ' . $this->_source);
+            }
+
+            $tok = $this->_getNextToken();
+            $members[$key] = $this->_decodeValue();
+            $tok = $this->_token;
+
+            if ($tok == self::RBRACE) {
+                break;
+            }
+
+            if ($tok != self::COMMA) {
+                throw new Zend_Json_Exception('Missing "," in object encoding: ' . $this->_source);
+            }
+
+            $tok = $this->_getNextToken();
+        }
+
+        switch ($this->_decodeType) {
+            case Zend_Json::TYPE_OBJECT:
+                // Create new StdClass and populate with $members
+                $result = new StdClass();
+                foreach ($members as $key => $value) {
+                    $result->$key = $value;
+                }
+                break;
+            case Zend_Json::TYPE_ARRAY:
+            default:
+                $result = $members;
+                break;
+        }
+
+        $this->_getNextToken();
+        return $result;
+    }
+
+    /**
+     * Decodes a JSON array format:
+     *    [element, element2,...,elementN]
+     *
+     * @return array
+     */
+    protected function _decodeArray()
+    {
+        $result = array();
+        $starttok = $tok = $this->_getNextToken(); // Move past the '['
+        $index  = 0;
+
+        while ($tok && $tok != self::RBRACKET) {
+            $result[$index++] = $this->_decodeValue();
+
+            $tok = $this->_token;
+
+            if ($tok == self::RBRACKET || !$tok) {
+                break;
+            }
+
+            if ($tok != self::COMMA) {
+                throw new Zend_Json_Exception('Missing "," in array encoding: ' . $this->_source);
+            }
+
+            $tok = $this->_getNextToken();
+        }
+
+        $this->_getNextToken();
+        return($result);
+    }
+
+
+    /**
+     * Removes whitepsace characters from the source input
+     */
+    protected function _eatWhitespace()
+    {
+        if (preg_match(
+                '/([\t\b\f\n\r ])*/s',
+                $this->_source,
+                $matches,
+                PREG_OFFSET_CAPTURE,
+                $this->_offset)
+            && $matches[0][1] == $this->_offset)
+        {
+            $this->_offset += strlen($matches[0][0]);
+        }
+    }
+
+
+    /**
+     * Retrieves the next token from the source stream
+     *
+     * @return int Token constant value specified in class definition
+     */
+    protected function _getNextToken()
+    {
+        $this->_token      = self::EOF;
+        $this->_tokenValue = null;
+        $this->_eatWhitespace();
+        
+        if ($this->_offset >= $this->_sourceLength) {
+            return(self::EOF);
+        }
+
+        $str        = $this->_source;
+        $str_length = $this->_sourceLength;
+        $i          = $this->_offset;
+        $start      = $i;
+        
+        switch ($str{$i}) {
+            case '{':
+               $this->_token = self::LBRACE;
+               break;
+            case '}':
+                $this->_token = self::RBRACE;
+                break;
+            case '[':
+                $this->_token = self::LBRACKET;
+                break;
+            case ']':
+                $this->_token = self::RBRACKET;
+                break;
+            case ',':
+                $this->_token = self::COMMA;
+                break;
+            case ':':
+                $this->_token = self::COLON;
+                break;
+            case  '"':
+                $result = '';
+                do {
+                    $i++;
+                    if ($i >= $str_length) {
+                        break;
+                    }
+
+                    $chr = $str{$i};
+                    if ($chr == '\\') {
+                        $i++;
+                        if ($i >= $str_length) {
+                            break;
+                        }
+                        $chr = $str{$i};
+                        switch ($chr) {
+                            case '"' :
+                                $result .= '"';
+                                break;
+                            case '\\':
+                                $result .= '\\';
+                                break;
+                            case '/' :
+                                $result .= '/';
+                                break;
+                            case 'b' :
+                                $result .= chr(8);
+                                break;
+                            case 'f' :
+                                $result .= chr(12);
+                                break;
+                            case 'n' :
+                                $result .= chr(10);
+                                break;
+                            case 'r' :
+                                $result .= chr(13);
+                                break;
+                            case 't' :
+                                $result .= chr(9);
+                                break;
+                            case '\'' :
+                                $result .= '\'';
+                                break;
+                            default:
+                                throw new Zend_Json_Exception("Illegal escape "
+                                    .  "sequence '" . $chr . "'");
+                            }
+                    } elseif ($chr == '"') {
+                        break;
+                    } else {
+                        $result .= $chr;
+                    }
+                } while ($i < $str_length);
+
+                $this->_token = self::DATUM;
+                //$this->_tokenValue = substr($str, $start + 1, $i - $start - 1);
+                $this->_tokenValue = $result;
+                break;
+            case  "'":
+                $result = '';
+                do {
+                    $i++;
+                    if ($i >= $str_length) {
+                        break;
+                    }
+
+                    $chr = $str{$i};
+                    if ($chr == '\\') {
+                        $i++;
+                        if ($i >= $str_length) {
+                            break;
+                        }
+                        $chr = $str{$i};
+                        switch ($chr) {
+                            case "'" :
+                                $result .= "'";
+                                break;
+                            case '\\':
+                                $result .= '\\';
+                                break;
+                            case '/' :
+                                $result .= '/';
+                                break;
+                            case 'b' :
+                                $result .= chr(8);
+                                break;
+                            case 'f' :
+                                $result .= chr(12);
+                                break;
+                            case 'n' :
+                                $result .= chr(10);
+                                break;
+                            case 'r' :
+                                $result .= chr(13);
+                                break;
+                            case 't' :
+                                $result .= chr(9);
+                                break;
+                            case '"' :
+                                $result .= '"';
+                                break;
+                            default:
+                                throw new Zend_Json_Exception("Illegal escape "
+                                    .  "sequence '" . $chr . "'");
+                            }
+                    } elseif ($chr == "'") {
+                        break;
+                    } else {
+                        $result .= $chr;
+                    }
+                } while ($i < $str_length);
+
+                $this->_token = self::DATUM;
+                //$this->_tokenValue = substr($str, $start + 1, $i - $start - 1);
+                $this->_tokenValue = $result;
+                break;
+            case 't':
+                if (($i+ 3) < $str_length && substr($str, $start, 4) == "true") {
+                    $this->_token = self::DATUM;
+                }
+                $this->_tokenValue = true;
+                $i += 3;
+                break;
+            case 'f':
+                if (($i+ 4) < $str_length && substr($str, $start, 5) == "false") {
+                    $this->_token = self::DATUM;
+                }
+                $this->_tokenValue = false;
+                $i += 4;
+                break;
+            case 'n':
+                if (($i+ 3) < $str_length && substr($str, $start, 4) == "null") {
+                    $this->_token = self::DATUM;
+                }
+                $this->_tokenValue = NULL;
+                $i += 3;
+                break;
+              case ' ':
+                break;
+        }
+
+        if ($this->_token != self::EOF) {
+            $this->_offset = $i + 1; // Consume the last token character
+            return($this->_token);
+        }
+
+        $chr = $str{$i};
+        if ($chr == '-' || $chr == '.' || ($chr >= '0' && $chr <= '9')) {
+            if (preg_match('/-?([0-9])*(\.[0-9]*)?((e|E)((-|\+)?)[0-9]+)?/s',
+                $str, $matches, PREG_OFFSET_CAPTURE, $start) && $matches[0][1] == $start) {
+
+                $datum = $matches[0][0];
+
+                if (is_numeric($datum)) {
+                    if (preg_match('/^0\d+$/', $datum)) {
+                        throw new Zend_Json_Exception("Octal notation not supported by JSON (value: $datum)");
+                    } else {
+                        $val  = intval($datum);
+                        $fVal = floatval($datum);
+                        $this->_tokenValue = ($val == $fVal ? $val : $fVal);
+                    }
+                } else {
+                    throw new Zend_Json_Exception("Illegal number format: $datum");
+                }
+
+                $this->_token = self::DATUM;
+                $this->_offset = $start + strlen($datum);
+            }
+        } else {
+            throw new Zend_Json_Exception("Illegal Token at pos $i: $chr\nContext:\n--------------------------------------------------" . substr($str, $i) . "\n--------------------------------------------------");
+        }
+
+        return($this->_token);
+    }
+}
+
+/**
+ * Zend Framework
+ *
+ * LICENSE
+ *
+ * This source file is subject to the new BSD license that is bundled
+ * with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://framework.zend.com/license/new-bsd
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@zend.com so we can send you a copy immediately.
+ *
+ * @category   Zend
+ * @package    Zend_Json
+ * @copyright  Copyright (c) 2005-2007 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ */
+
+
+/**
+ * @category   Zend
+ * @package    Zend_Json
+ * @copyright  Copyright (c) 2005-2007 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ */
+class Zend_Json_Exception extends Zend_Exception
+{}
+
+/**
+ * @category   Zend
+ * @package    Zend
+ * @copyright  Copyright (c) 2005-2007 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ */
+class Zend_Exception extends Exception
+{}
+
+/**
+ * Class for encoding to and decoding from JSON.
+ *
+ * @category   Zend
+ * @package    Zend_Json
+ * @copyright  Copyright (c) 2005-2007 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ */
+class Zend_Json
+{
+    /**
+     * How objects should be encoded -- arrays or as StdClass. TYPE_ARRAY is 1
+     * so that it is a boolean true value, allowing it to be used with
+     * ext/json's functions.
+     */
+    const TYPE_ARRAY  = 1;
+    const TYPE_OBJECT = 0;
+
+    /**
+     * @var bool
+     */
+    public static $useBuiltinEncoderDecoder = true;
+
+    /**
+     * Decodes the given $encodedValue string which is
+     * encoded in the JSON format
+     *
+     * Uses ext/json's json_decode if available.
+     *
+     * @param string $encodedValue Encoded in JSON format
+     * @param int $objectDecodeType Optional; flag indicating how to decode
+     * objects. See {@link ZJsonDecoder::decode()} for details.
+     * @return mixed
+     */
+    public static function decode($encodedValue, $objectDecodeType = Zend_Json::TYPE_ARRAY)
+    {
+        if (function_exists('json_decode') && self::$useBuiltinEncoderDecoder !== true) {
+            return json_decode($encodedValue, $objectDecodeType);
+        }
+
+        return Zend_Json_Decoder::decode($encodedValue, $objectDecodeType);
+    }
+
+
+    /**
+     * Encode the mixed $valueToEncode into the JSON format
+     *
+     * Encodes using ext/json's json_encode() if available.
+     *
+     * NOTE: Object should not contain cycles; the JSON format
+     * does not allow object reference.
+     *
+     * NOTE: Only public variables will be encoded
+     *
+     * @param mixed $valueToEncode
+     * @param boolean $cycleCheck Optional; whether or not to check for object recursion; off by default
+     * @return string JSON encoded object
+     */
+    public static function encode($valueToEncode, $cycleCheck = false)
+    {
+        if (function_exists('json_encode') && self::$useBuiltinEncoderDecoder !== true) {
+            return json_encode($valueToEncode);
+        }
+
+        return Zend_Json_Encoder::encode($valueToEncode, $cycleCheck);
+    }
+}
+
+?>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/includes/lang.php	Fri Feb 22 12:51:53 2008 -0500
@@ -0,0 +1,562 @@
+<?php
+
+/*
+ * Enano - an open-source CMS capable of wiki functions, Drupal-like sidebar blocks, and everything in between
+ * Version 1.1.1
+ * Copyright (C) 2006-2007 Dan Fuhry
+ *
+ * This program is Free Software; you can redistribute and/or modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.
+ *
+ * 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.
+ */
+
+/**
+ * Language class - processes, stores, and retrieves language strings.
+ * @package Enano
+ * @subpackage Localization
+ * @copyright 2007 Dan Fuhry
+ * @license GNU General Public License
+ */
+
+class Language
+{
+  
+  /**
+   * The numerical ID of the loaded language.
+   * @var int
+   */
+  
+  var $lang_id;
+  
+  /**
+   * The ISO-639-3 code for the loaded language. This should be grabbed directly from the database.
+   * @var string
+   */
+  
+  var $lang_code;
+
+  /**
+   * Used to track when a language was last changed, to allow browsers to cache language data
+   * @var int
+   */
+  
+  var $lang_timestamp;
+  
+  /**
+   * Will be an object that holds an instance of the class configured with the site's default language. Only instanciated when needed.
+   * @var object
+   */
+  
+  var $default;
+  
+  /**
+   * The list of loaded strings.
+   * @var array
+   * @access private
+   */
+  
+  var $strings = array();
+  
+  /**
+   * Constructor.
+   * @param int|string Language ID or code to load.
+   */
+  
+  function __construct($lang)
+  {
+    global $db, $session, $paths, $template, $plugins; // Common objects
+    
+    if ( defined('IN_ENANO_INSTALL') )
+    {
+      // special case for the Enano installer: it will load its own strings from a JSON file and just use this API for fetching and templatizing them.
+      $this->lang_id   = 1;
+      $this->lang_code = $lang;
+      return true;
+    }
+    if ( is_string($lang) )
+    {
+      $sql_col = 'lang_code=\'' . $db->escape($lang) . '\'';
+    }
+    else if ( is_int($lang) )
+    {
+      $sql_col = 'lang_id=' . $lang . '';
+    }
+    else
+    {
+      $db->_die('lang.php - attempting to pass invalid value to constructor');
+    }
+    
+    $lang_default = ( $x = getConfig('default_language') ) ? intval($x) : '\'def\'';
+    
+    $q = $db->sql_query("SELECT lang_id, lang_code, last_changed, ( lang_id = $lang_default ) AS is_default FROM " . table_prefix . "language WHERE $sql_col OR lang_id = $lang_default ORDER BY is_default ASC LIMIT 1;");
+    
+    if ( !$q )
+      $db->_die('lang.php - main select query');
+    
+    if ( $db->numrows() < 1 )
+      $db->_die('lang.php - There are no languages installed');
+    
+    $row = $db->fetchrow();
+    
+    $this->lang_id   = intval( $row['lang_id'] );
+    $this->lang_code = $row['lang_code'];
+    $this->lang_timestamp = $row['last_changed'];
+  }
+  
+  /**
+   * Fetches language strings from the database, or a cache file if it's available.
+   * @param bool If true (default), allows the cache to be used.
+   */
+  
+  function fetch($allow_cache = true)
+  {
+    global $db, $session, $paths, $template, $plugins; // Common objects
+    
+    $lang_file = ENANO_ROOT . "/cache/lang_{$this->lang_id}.php";
+    // Attempt to load the strings from a cache file
+    if ( file_exists($lang_file) && $allow_cache )
+    {
+      // Yay! found it
+      $this->load_cache_file($lang_file);
+    }
+    else
+    {
+      // No cache file - select and retrieve from the database
+      $q = $db->sql_unbuffered_query("SELECT string_category, string_name, string_content FROM " . table_prefix . "language_strings WHERE lang_id = {$this->lang_id};");
+      if ( !$q )
+        $db->_die('lang.php - selecting language string data');
+      if ( $row = $db->fetchrow() )
+      {
+        $strings = array();
+        do
+        {
+          $cat =& $row['string_category'];
+          if ( !is_array(@$strings[$cat]) )
+          {
+            $strings[$cat] = array();
+          }
+          $strings[$cat][ $row['string_name'] ] = $row['string_content'];
+        }
+        while ( $row = $db->fetchrow() );
+        // all done fetching
+        $this->merge($strings);
+      }
+      else
+      {
+        if ( !defined('ENANO_ALLOW_LOAD_NOLANG') )
+          $db->_die('lang.php - No strings for language ' . $this->lang_code);
+      }
+    }
+  }
+  
+  /**
+   * Loads a file from the disk cache (treated as PHP) and merges it into RAM.
+   * @param string File to load
+   */
+  
+  function load_cache_file($file)
+  {
+    global $db, $session, $paths, $template, $plugins; // Common objects
+    
+    // We're using eval() here because it makes handling scope easier.
+    
+    if ( !file_exists($file) )
+      $db->_die('lang.php - requested cache file doesn\'t exist');
+    
+    $contents = file_get_contents($file);
+    $contents = preg_replace('/([\s]*)<\?php/', '', $contents);
+    
+    @eval($contents);
+    
+    if ( !isset($lang_cache) || ( isset($lang_cache) && !is_array($lang_cache) ) )
+      $db->_die('lang.php - the cache file is invalid (didn\'t set $lang_cache as an array)');
+    
+    $this->merge($lang_cache);
+  }
+  
+  /**
+   * Loads a JSON language file and parses the strings into RAM. Will use the cache if possible, but stays far away from the database,
+   * which we assume doesn't exist yet.
+   */
+  
+  function load_file($file)
+  {
+    global $db, $session, $paths, $template, $plugins; // Common objects
+    
+    if ( !file_exists($file) )
+    {
+      if ( defined('IN_ENANO_INSTALL') )
+      {
+        die('lang.php - requested JSON file (' . htmlspecialchars($file) . ') doesn\'t exist');
+      }
+      else
+      {
+        $db->_die('lang.php - requested JSON file doesn\'t exist');
+      }
+    }
+    
+    $contents = trim(@file_get_contents($file));
+    if ( empty($contents) )
+      $db->_die('lang.php - empty language file...');
+    
+    // Trim off all text before and after the starting and ending braces
+    $contents = preg_replace('/^([^{]+)\{/', '{', $contents);
+    $contents = preg_replace('/\}([^}]+)$/', '}', $contents);
+    $contents = trim($contents);
+    
+    if ( empty($contents) )
+      $db->_die('lang.php - no meat to the language file...');
+    
+    $checksum = md5($contents);
+    if ( file_exists("./cache/lang_json_{$checksum}.php") )
+    {
+      $this->load_cache_file("./cache/lang_json_{$checksum}.php");
+    }
+    else
+    {
+      // Correct syntax to be nice to the json parser
+    
+      // eliminate comments
+      $contents = preg_replace(array(
+              // eliminate single line comments in '// ...' form
+              '#^\s*//(.+)$#m',
+              // eliminate multi-line comments in '/* ... */' form, at start of string
+              '#^\s*/\*(.+)\*/#Us',
+              // eliminate multi-line comments in '/* ... */' form, at end of string
+              '#/\*(.+)\*/\s*$#Us'
+            ), '', $contents);
+      
+      $contents = preg_replace('/([,\{\[])([\s]*?)([a-z0-9_]+)([\s]*?):/', '\\1\\2"\\3" :', $contents);
+      
+      try
+      {
+        $langdata = enano_json_decode($contents);
+      }
+      catch(Zend_Json_Exception $e)
+      {
+        $db->_die('lang.php - Exception caught by JSON parser</p><pre>' . htmlspecialchars(print_r($e, true)) . '</pre><p>');
+        exit;
+      }
+    
+      if ( !is_array($langdata) )
+        $db->_die('lang.php - invalid language file');
+      
+      if ( !isset($langdata['categories']) || !isset($langdata['strings']) )
+        $db->_die('lang.php - language file does not contain the proper items');
+      
+      $this->merge($langdata['strings']);
+      
+      $lang_file = "./cache/lang_json_{$checksum}.php";
+      
+      $handle = @fopen($lang_file, 'w');
+      if ( !$handle )
+        // Couldn't open the file. Silently fail and let the strings come from RAM.
+        return false;
+        
+      // The file's open, that means we should be good.
+      fwrite($handle, '<?php
+// This file was generated automatically by Enano. You should not edit this file because any changes you make
+// to it will not be visible in the ACP and all changes will be lost upon any changes to strings in the admin panel.
+
+$lang_cache = ');
+      
+      $exported = $this->var_export_string($this->strings);
+      if ( empty($exported) )
+        // Ehh, that's not good
+        $db->_die('lang.php - load_file(): var_export_string() failed');
+      
+      fwrite($handle, $exported . '; ?>');
+      
+      // Clean up
+      unset($exported, $langdata);
+      
+      // Done =)
+      fclose($handle);
+    }
+  }
+  
+  /**
+   * Merges a standard language assoc array ($arr[cat][stringid]) with the master in RAM.
+   * @param array
+   */
+  
+  function merge($strings)
+  {
+    // This is stupidly simple.
+    foreach ( $strings as $cat_id => $contents )
+    {
+      if ( !isset($this->strings[$cat_id]) || ( isset($this->strings[$cat_id]) && !is_array($this->strings[$cat_id]) ) )
+        $this->strings[$cat_id] = array();
+      foreach ( $contents as $string_id => $string )
+      {
+        $this->strings[$cat_id][$string_id] = $string;
+      }
+    }
+  }
+  
+  /**
+   * Imports a JSON-format language file into the database and merges with current strings.
+   * @param string Path to the JSON file to load
+   */
+  
+  function import($file)
+  {
+    global $db, $session, $paths, $template, $plugins; // Common objects
+    
+    if ( !file_exists($file) )
+      $db->_die('lang.php - can\'t import language file: string file doesn\'t exist');
+    
+    if ( $this->lang_id == 0 )
+      $db->_die('lang.php - BUG: trying to perform import when $lang->lang_id == 0');
+    
+    $contents = trim(@file_get_contents($file));
+    
+    if ( empty($contents) )
+      $db->_die('lang.php - can\'t load the contents of the language file');
+    
+    // Trim off all text before and after the starting and ending braces
+    $contents = preg_replace('/^([^{]+)\{/', '{', $contents);
+    $contents = preg_replace('/\}([^}]+)$/', '}', $contents);
+    
+    // Correct syntax to be nice to the json parser
+    $contents = enano_clean_json($contents);
+    
+    try
+    {
+      $langdata = enano_json_decode($contents);
+    }
+    catch(Zend_Json_Exception $e)
+    {
+      $db->_die('lang.php - Exception caught by JSON parser</p><pre>' . htmlspecialchars(print_r($e, true)) . '</pre><p>');
+      exit;
+    }
+    
+    if ( !is_array($langdata) )
+    {
+      $db->_die('lang.php - invalid or non-well-formed language file');
+    }
+    
+    if ( !isset($langdata['categories']) || !isset($langdata['strings']) )
+      $db->_die('lang.php - language file does not contain the proper items');
+    
+    $insert_list = array();
+    $delete_list = array();
+    
+    foreach ( $langdata['categories'] as $category )
+    {
+      if ( isset($langdata['strings'][$category]) )
+      {
+        foreach ( $langdata['strings'][$category] as $string_name => $string_value )
+        {
+          $string_name = $db->escape($string_name);
+          $string_value = $db->escape($string_value);
+          $category_name = $db->escape($category);
+          $insert_list[] = "({$this->lang_id}, '$category_name', '$string_name', '$string_value')";
+          $delete_list[] = "( lang_id = {$this->lang_id} AND string_category = '$category_name' AND string_name = '$string_name' )";
+        }
+      }
+    }
+    
+    $delete_list = implode(" OR\n  ", $delete_list);
+    
+    if ( !empty($delete_list) )
+    {
+      $sql = "DELETE FROM " . table_prefix . "language_strings WHERE $delete_list;";
+      
+      // Free some memory
+      unset($delete_list);
+      
+      // Run the query
+      $q = $db->sql_query($sql);
+      if ( !$q )
+        $db->_die('lang.php - couldn\'t kill off them old strings');
+    }
+    
+    if ( !empty($insert_list) )
+    {
+      $insert_list = implode(",\n  ", $insert_list);
+      $sql = "INSERT INTO " . table_prefix . "language_strings(lang_id, string_category, string_name, string_content) VALUES\n  $insert_list;";
+      
+      // Free some memory
+      unset($insert_list);
+      
+      // Run the query
+      $q = $db->sql_query($sql);
+      if ( !$q )
+        $db->_die('lang.php - couldn\'t insert strings in import()');
+    }
+    
+    // YAY! done!
+    // This will regenerate the cache file if possible.
+    $this->regen_caches();
+  }
+  
+  /**
+   * Refetches the strings and writes out the cache file.
+   */
+  
+  function regen_caches()
+  {
+    global $db, $session, $paths, $template, $plugins; // Common objects
+    
+    $lang_file = ENANO_ROOT . "/cache/lang_{$this->lang_id}.php";
+    
+    // Refresh the strings in RAM to the latest copies in the DB
+    $this->fetch(false);
+    
+    $handle = @fopen($lang_file, 'w');
+    if ( !$handle )
+      // Couldn't open the file. Silently fail and let the strings come from the database.
+      return false;
+      
+    // The file's open, that means we should be good.
+    fwrite($handle, '<?php
+// This file was generated automatically by Enano. You should not edit this file because any changes you make
+// to it will not be visible in the ACP and all changes will be lost upon any changes to strings in the admin panel.
+
+$lang_cache = ');
+    
+    $exported = $this->var_export_string($this->strings);
+    if ( empty($exported) )
+      // Ehh, that's not good
+      $db->_die('lang.php - var_export_string() failed');
+    
+    fwrite($handle, $exported . '; ?>');
+    
+    // Update timestamp in database
+    $q = $db->sql_query('UPDATE ' . table_prefix . 'language SET last_changed = ' . time() . ' WHERE lang_id = ' . $this->lang_id . ';');
+    if ( !$q )
+      $db->_die('lang.php - updating timestamp on language');
+    
+    // Done =)
+    fclose($handle);
+  }
+  
+  /**
+   * Calls var_export() on whatever, and returns the function's output.
+   * @param mixed Whatever you want var_exported. Usually an array.
+   * @return string
+   */
+  
+  function var_export_string($val)
+  {
+    ob_start();
+    var_export($val);
+    $contents = ob_get_contents();
+    ob_end_clean();
+    return $contents;
+  }
+  
+  /**
+   * Fetches a language string from the cache in RAM. If it isn't there, it will call fetch() again and then try. If it still can't find it, it will ask for the string
+   * in the default language. If even then the string can't be found, this function will return what was passed to it.
+   *
+   * This will also templatize strings. If a string contains variables in the format %foo%, you may specify the second parameter as an associative array in the format
+   * of 'foo' => 'foo substitute'.
+   *
+   * @param string ID of the string to fetch. This will always be in the format of category_stringid.
+   * @param array Optional. Associative array of substitutions.
+   * @return string
+   */
+  
+  function get($string_id, $substitutions = false)
+  {
+    if ( !is_array($substitutions) )
+      $substitutions = array();
+    return $this->substitute($this->get_uncensored($string_id), $substitutions);
+  }
+  
+  /**
+   * The same as get(), but does not perform any substitution or filtering. Used in get() (of course) and in the admin panel, where
+   * strings are updated only if they were changed.
+   *
+   * @param string ID of the string to fetch. This will always be in the format of category_stringid.
+   * @param array Optional. Associative array of substitutions.
+   * @return string
+   */
+  
+  function get_uncensored($string_id, $substitutions = false)
+  {
+    // Extract the category and string ID
+    $category = substr($string_id, 0, ( strpos($string_id, '_') ));
+    $string_name = substr($string_id, ( strpos($string_id, '_') + 1 ));
+    $found = false;
+    if ( isset($this->strings[$category]) && isset($this->strings[$category][$string_name]) )
+    {
+      $found = true;
+      $string = $this->strings[$category][$string_name];
+    }
+    if ( !$found )
+    {
+      // Ehh, the string wasn't found. Rerun fetch() and try again.
+      if ( defined('IN_ENANO_INSTALL') )
+      {
+        return $string_id;
+      }
+      $this->fetch();
+      if ( isset($this->strings[$category]) && isset($this->strings[$category][$string_name]) )
+      {
+        $found = true;
+        $string = $this->strings[$category][$string_name];
+      }
+      if ( !$found )
+      {
+        // STILL not found. Check the default language.
+        $lang_default = ( $x = getConfig('default_language') ) ? intval($x) : $this->lang_id;
+        if ( $lang_default != $this->lang_id )
+        {
+          if ( !is_object($this->default) )
+            $this->default = new Language($lang_default);
+          return $this->default->get_uncensored($string_id);
+        }
+      }
+    }
+    if ( !$found )
+    {
+      // Alright, it's nowhere. Return the input, grumble grumble...
+      return $string_id;
+    }
+    // Found it!
+    return $string;
+  }
+  
+  /**
+   * Processes substitutions.
+   * @param string
+   * @param array
+   * @return string
+   */
+  
+  function substitute($string, $subs)
+  {
+    preg_match_all('/%this\.([a-z0-9_]+)%/', $string, $matches);
+    if ( count($matches[0]) > 0 )
+    {
+      foreach ( $matches[1] as $i => $string_id )
+      {
+        $result = $this->get($string_id);
+        $string = str_replace($matches[0][$i], $result, $string);
+      }
+    }
+    preg_match_all('/%config\.([a-z0-9_]+)%/', $string, $matches);
+    if ( count($matches[0]) > 0 )
+    {
+      foreach ( $matches[1] as $i => $string_id )
+      {
+        $result = getConfig($string_id);
+        $string = str_replace($matches[0][$i], $result, $string);
+      }
+    }
+    foreach ( $subs as $key => $value )
+    {
+      $subs[$key] = strval($value);
+      $string = str_replace("%{$key}%", "{$subs[$key]}", $string);
+    }
+    return $string;
+  }
+  
+} // class Language
+
+?>
--- a/includes/pageprocess.php	Fri Feb 22 12:46:51 2008 -0500
+++ b/includes/pageprocess.php	Fri Feb 22 12:51:53 2008 -0500
@@ -2,7 +2,7 @@
 
 /*
  * Enano - an open-source CMS capable of wiki functions, Drupal-like sidebar blocks, and everything in between
- * Version 1.0.3 (Dyrad)
+ * Version 1.1.2 (Caoineag alpha 2)
  * pageprocess.php - intelligent retrieval of pages
  * Copyright (C) 2006-2007 Dan Fuhry
  *
@@ -131,6 +131,8 @@
   {
     global $db, $session, $paths, $template, $plugins; // Common objects
     
+    profiler_log("PageProcessor [{$namespace}:{$page_id}]: Started constructor");
+    
     // See if we can get some debug info
     if ( function_exists('debug_backtrace') && $this->debug['enable'] )
     {
@@ -148,8 +150,9 @@
     if ( !is_int($revision_id) )
       $revision_id = 0;
     
+    profiler_log("PageProcessor [{$namespace}:{$page_id}]: Ran initial checks");
+    
     $this->_setup( $page_id, $namespace, $revision_id );
-    
   }
   
   /**
@@ -160,13 +163,27 @@
   function send( $do_stats = false )
   {
     global $db, $session, $paths, $template, $plugins; // Common objects
+    global $lang;
+    
+    profiler_log("PageProcessor [{$this->namespace}:{$this->page_id}]: Started send process");
+    
     if ( !$this->perms->get_permissions('read') )
     {
       $this->err_access_denied();
+      profiler_log("PageProcessor [{$this->namespace}:{$this->page_id}]: Finished send process");
       return false;
     }
     $pathskey = $paths->nslist[ $this->namespace ] . $this->page_id;
     $strict_no_headers = false;
+    if ( $this->namespace == 'Admin' && strstr($this->page_id, '/') )
+    {
+      $this->page_id = substr($this->page_id, 0, strpos($this->page_id, '/'));
+      $funcname = "page_{$this->namespace}_{$this->page_id}";
+      if ( function_exists($funcname) )
+      {
+        $this->page_exists = true;
+      }
+    }
     if ( isset($paths->pages[$pathskey]) )
     {
       if ( $paths->pages[$pathskey]['special'] == 1 )
@@ -182,6 +199,7 @@
           if ( $this->password != $password )
           {
             $this->err_wrong_password();
+            profiler_log("PageProcessor [{$this->namespace}:{$this->page_id}]: Finished send process");
             return false;
           }
         }
@@ -195,18 +213,21 @@
     {
       if ( !$this->page_exists )
       {
-        redirect( makeUrl(getConfig('main_page')), 'Can\'t find special page', 'The special or administration page you requested does not exist. You will now be transferred to the main page.', 2 );
+        $func_name = "page_{$this->namespace}_{$this->page_id}";
+        die_semicritical($lang->get('page_msg_admin_404_title'), $lang->get('page_msg_admin_404_body', array('func_name' => $func_name)));
       }
       $func_name = "page_{$this->namespace}_{$this->page_id}";
       if ( function_exists($func_name) )
       {
-        return @call_user_func($func_name);
+        profiler_log("PageProcessor [{$this->namespace}:{$this->page_id}]: Calling special/admin page");
+        $result = @call_user_func($func_name);
+        profiler_log("PageProcessor [{$this->namespace}:{$this->page_id}]: Finished send process");
+        return $result;
       }
       else
       {
-        $title = 'Page backend not found';
-        $message = "The administration page you are looking for was properly registered using the page API, but the backend function
-                    (<tt>$fname</tt>) was not found. If this is a plugin page, then this is almost certainly a bug with the plugin.";
+        $title = $lang->get('page_err_custompage_function_missing_title');
+        $message = $lang->get('page_err_custompage_function_missing_body', array( 'function_name' => $fname ));
                     
         if ( $this->send_headers )
         {
@@ -220,6 +241,7 @@
           echo "<h2>$title</h2>
                 <p>$message</p>";
         }
+        profiler_log("PageProcessor [{$this->namespace}:{$this->page_id}]: Finished send process");
         return false;
       }
     }
@@ -237,7 +259,7 @@
       
       $text = RenderMan::render( $text );
       
-      echo $text;
+      eval( '?>' . $text );
       
       $this->footer();
     }
@@ -287,6 +309,7 @@
       if ( $text == 'err_no_text_rows' )
       {
         $this->err_no_rows();
+        profiler_log("PageProcessor [{$this->namespace}:{$this->page_id}]: Finished send process");
         return false;
       }
       else
@@ -299,7 +322,7 @@
           $page_id_data = RenderMan::strToPageID($page_to);
           if ( count($this->redirect_stack) >= 3 )
           {
-            $this->render( (!$strict_no_headers), '<div class="usermessage"><b>The maximum number of internal redirects has been exceeded.</b></div>' );
+            $this->render( (!$strict_no_headers), '<div class="usermessage"><b>' . $lang->get('page_err_redirects_exceeded') . '</b></div>' );
           }
           else
           {
@@ -317,6 +340,7 @@
         }
       }
     }
+    profiler_log("PageProcessor [{$this->namespace}:{$this->page_id}]: Finished send process");
   }
   
   /**
@@ -341,12 +365,14 @@
    * Updates the content of the page.
    * @param string The new text for the page
    * @param string A summary of edits made to the page.
+   * @param bool If true, the edit is marked as a minor revision
    * @return bool True on success, false on failure
    */
   
-  function update_page($text, $edit_summary = false)
+  function update_page($text, $edit_summary = false, $minor_edit = false)
   {
     global $db, $session, $paths, $template, $plugins; // Common objects
+    global $lang;
     
     // Create the page if it doesn't exist
     if ( !$this->page_exists )
@@ -369,14 +395,14 @@
       $db->_die('PageProcess updating page content');
     if ( $db->numrows() < 1 )
     {
-      $this->raise_error('Page doesn\'t exist in the database');
+      $this->raise_error($lang->get('editor_err_no_rows'));
       return false;
     }
     
     // Do we have permission to edit the page?
     if ( !$this->perms->get_permissions('edit_page') )
     {
-      $this->raise_error('You do not have permission to edit this page.');
+      $this->raise_error($lang->get('editor_err_no_permission'));
       return false;
     }
     
@@ -388,7 +414,7 @@
       // The page is protected - do we have permission to edit protected pages?
       if ( !$this->perms->get_permissions('even_when_protected') )
       {
-        $this->raise_error('This page is protected, and you do not have permission to edit protected pages.');
+        $this->raise_error($lang->get('editor_err_page_protected'));
         return false;
       }
     }
@@ -400,35 +426,71 @@
              ( $session->user_logged_in && $session->reg_time + ( 4 * 86400 ) >= time() ) ) // If so, have they been registered for 4 days?
            && !$this->perms->get_permissions('even_when_protected') ) // And of course, is there an ACL that overrides semi-protection?
       {
-        $this->raise_error('This page is protected, and you do not have permission to edit protected pages.');
+        $this->raise_error($lang->get('editor_err_page_protected'));
         return false;
       }
     }
     
-    // Protection validated
+    //
+    // Protection validated; update page content
+    //
+    
+    $text_undb = RenderMan::preprocess_text($text, false, false);
+    $text = $db->escape($text_undb);
+    $author = $db->escape($session->username);
+    $time = time();
+    $edit_summary = ( strval($edit_summary) === $edit_summary ) ? $db->escape($edit_summary) : '';
+    $minor_edit = ( $minor_edit ) ? '1' : '0';
+    $date_string = enano_date('d M Y h:i a');
+    
+    // Insert log entry
+    $sql = 'INSERT INTO ' . table_prefix . "logs ( time_id, date_string, log_type, action, page_id, namespace, author, page_text, edit_summary, minor_edit )\n"
+         . "  VALUES ( $time, '$date_string', 'page', 'edit', '{$this->page_id}', '{$this->namespace}', '$author', '$text', '$edit_summary', $minor_edit );";
+    if ( !$db->sql_query($sql) )
+    {
+      $this->raise_error($db->get_error());
+      return false;
+    }
+    
+    // Update the master text entry
+    $sql = 'UPDATE ' . table_prefix . "page_text SET page_text = '$text' WHERE page_id = '{$this->page_id}' AND namespace = '{$this->namespace}';";
+    if ( !$db->sql_query($sql) )
+    {
+      $this->raise_error($db->get_error());
+      return false;
+    }
+    
+    // Rebuild the search index
+    $paths->rebuild_page_index($this->page_id, $this->namespace);
+    
+    $this->text_cache = $text;
+    
+    return true;
     
   }
   
   /**
    * Creates the page if it doesn't already exist.
+   * @param string Optional page title.
    * @return bool True on success, false on failure.
    */
   
-  function create_page()
+  function create_page($title = false)
   {
     global $db, $session, $paths, $template, $plugins; // Common objects
+    global $lang;
     
     // Do we have permission to create the page?
     if ( !$this->perms->get_permissions('create_page') )
     {
-      $this->raise_error('You do not have permission to create this page.');
+      $this->raise_error($lang->get('pagetools_create_err_no_permission'));
       return false;
     }
     
     // Does it already exist?
     if ( $this->page_exists )
     {
-      $this->raise_error('The page already exists.');
+      $this->raise_error($lang->get('pagetools_create_err_already_exists'));
       return false;
     }
     
@@ -437,17 +499,17 @@
     // We can't create special, admin, or external pages.
     if ( $this->namespace == 'Special' || $this->namespace == 'Admin' || $this->namespace == 'Anonymous' )
     {
-      $this->raise_error('You cannot create Special or Admin pages - they can\'t be stored in the database.');
+      $this->raise_error($lang->get('pagetools_create_err_nodb_namespace'));
       return false;
     }
     
     // Guess the proper title
-    $name = dirtify_page_id($this->page_id);
+    $name = ( !empty($title) ) ? $title : dirtify_page_id($this->page_id);
     
     // Check for the restricted Project: prefix
     if ( substr($this->page_id, 0, 8) == 'Project:' )
     {
-      $this->raise_error('The prefix "Project:" is reserved for internal links and can\'t be used on a page name.');
+      $this->raise_error($lang->get('pagetools_create_err_reserved_prefix'));
       return false;
     }
     
@@ -486,6 +548,13 @@
     if ( !$q )
       $db->_die('PageProcessor page creation - text stage');
     
+    // Query 3: Log entry
+    $db->sql_query('INSERT INTO ' . table_prefix."logs(time_id, date_string, log_type, action, author, page_id, namespace)\n"
+                   . "  VALUES ( " . time() . ", '" . enano_date('d M Y h:i a') . "', 'page', 'create', \n"
+                   . "          '" . $db->escape($session->username) . "', '" . $db->escape($this->page_id) . "', '" . $this->namespace . "');");
+    if ( !$q )
+      $db->_die('PageProcessor page creation - logging stage');
+    
     // Page created. We're good!
     return true;
   }
@@ -515,11 +584,13 @@
     }
     
     // Does the page "exist"?
+    $pathskey = $paths->nslist[$namespace] . $page_id_cleaned;
+    
     if ( $paths->page_id == $page_id && $paths->namespace == $namespace && !$paths->page_exists && ( $this->namespace != 'Admin' || ($this->namespace == 'Admin' && !function_exists($fname) ) ) )
     {
       $this->page_exists = false;
     }
-    else if ( !isset( $paths->pages[ $paths->nslist[$namespace] . $page_id ] ) && ( $this->namespace == 'Admin' && !function_exists($fname) ) )
+    else if ( !isset( $paths->pages[ $pathskey ] ) && ( ( $this->namespace == 'Admin' && !function_exists($fname) ) || ( $this->namespace != 'Admin' ) ) )
     {
       $this->page_exists = false;
     }
@@ -550,6 +621,7 @@
     
     $this->title = get_page_title_ns($this->page_id, $this->namespace);
     
+    profiler_log("PageProcessor [{$this->namespace}:{$this->page_id}]: Ran _setup()");
   }
   
   /**
@@ -560,6 +632,7 @@
   function render($incl_inner_headers = true, $_errormsg = false)
   {
     global $db, $session, $paths, $template, $plugins; // Common objects
+    global $lang;
     
     $text = $this->fetch_text();
     $text = preg_replace('/([\s]*)__NOBREADCRUMBS__([\s]*)/', '', $text);
@@ -593,11 +666,7 @@
                     <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" onclick="window.open(this.href); return false;">Wiki formatting guide</a>.<br /><br />
-                    This page redirects to ' . $a . '.
+                    ' . $lang->get('page_msg_this_is_a_redirector', array( 'redirect_target' => $a )) . '
                   </td>
                 </tr>
               </table>
@@ -630,7 +699,7 @@
           $page_data = $paths->pages[$page_id_key];
           $title = ( isset($page_data['name']) ) ? $page_data['name'] : $paths->nslist[$oldtarget[1]] . htmlspecialchars( str_replace('_', ' ', dirtify_page_id( $oldtarget[0] ) ) );
           $a = '<a href="' . $url . '">' . $title . '</a>';
-          echo '<small>(Redirected from ' . $a . ')<br /></small>';
+          echo '<small>' . $lang->get('page_msg_redirected_from', array('from' => $a)) . '<br /></small>';
         }
       }
       display_page_headers();
@@ -638,7 +707,17 @@
     
     if ( $this->revision_id )
     {
-      echo '<div class="info-box" style="margin-left: 0; margin-top: 5px;"><b>Notice:</b><br />The page you are viewing was archived on '.date('F d, Y \a\t h:i a', $this->revision_id).'.<br /><a href="'.makeUrlNS($this->namespace, $this->page_id).'" onclick="ajaxReset(); return false;">View current version</a>  |  <a href="'.makeUrlNS($this->namespace, $this->page_id, 'do=rollback&amp;id='.$this->revision_id).'" onclick="ajaxRollback(\''.$this->revision_id.'\')">Restore this version</a></div><br />';
+      echo '<div class="info-box" style="margin-left: 0; margin-top: 5px;">
+              <b>' . $lang->get('page_msg_archived_title') . '</b><br />
+              ' . $lang->get('page_msg_archived_body', array(
+                  'archive_date' => enano_date('F d, Y', $this->revision_id),
+                  'archive_time' => enano_date('h:i a', $this->revision_id),
+                  'current_link' => makeUrlNS($this->namespace, $this->page_id),
+                  'restore_link' => makeUrlNS($this->namespace, $this->page_id, 'do=rollback&amp;id='.$this->revision_id),
+                  'restore_onclick' => 'ajaxRollback(\''.$this->revision_id.'\'); return false;',
+                )) . '
+            </div>
+            <br />';
     }
     
     if ( $redir_enabled )
@@ -819,6 +898,7 @@
   {
     global $db, $session, $paths, $template, $plugins; // Common objects
     global $email;
+    global $lang;
     
     $page_urlname = dirtify_page_id($this->page_id);
     if ( $this->page_id == $paths->page_id && $this->namespace == $paths->namespace )
@@ -837,13 +917,12 @@
         '>' => '&gt;'
         ));
     
-    $target_username = preg_replace('/^' . preg_quote($paths->nslist['User']) . '/', '', $target_username);
-    $target_username = explode('/', $target_username);
-    $target_username = $target_username[0];
+    $target_username = preg_replace('/^' . str_replace('/', '\\/', preg_quote($paths->nslist['User'])) . '/', '', $target_username);
+    list($target_username) = explode('/', $target_username);
     
     if ( ( $page_name == str_replace('_', ' ', $this->page_id) || $page_name == $paths->nslist['User'] . str_replace('_', ' ', $this->page_id) ) || !$this->page_exists )
     {
-      $page_name = "$target_username's user page";
+      $page_name = $lang->get('userpage_page_title', array('username' => htmlspecialchars($target_username)));
     }
     else
     {
@@ -853,14 +932,14 @@
     
     $template->tpl_strings['PAGE_NAME'] = htmlspecialchars($page_name);
     
-    $q = $db->sql_query('SELECT u.username, u.user_id AS authoritative_uid, u.real_name, u.email, u.reg_time, x.*, COUNT(c.comment_id) AS n_comments
+    $q = $db->sql_query('SELECT u.username, u.user_id AS authoritative_uid, u.real_name, u.email, u.reg_time, u.user_has_avatar, u.avatar_type, x.*, COUNT(c.comment_id) AS n_comments
                            FROM '.table_prefix.'users u
                            LEFT JOIN '.table_prefix.'users_extra AS x
                              ON ( u.user_id = x.user_id OR x.user_id IS NULL ) 
                            LEFT JOIN '.table_prefix.'comments AS c
                              ON ( ( c.user_id=u.user_id AND c.name=u.username AND c.approved=1 ) OR ( c.comment_id IS NULL AND c.approved IS NULL ) )
                            WHERE u.username=\'' . $db->escape($target_username) . '\'
-                           GROUP BY u.username, u.user_id, u.real_name, u.email, u.reg_time,x.user_id, x.user_aim, x.user_yahoo, x.user_msn, x.user_xmpp, x.user_homepage, x.user_location, x.user_job, x.user_hobbies, x.email_public;');
+                           GROUP BY u.username, u.user_id, u.real_name, u.email, u.reg_time, u.user_has_avatar, u.avatar_type, x.user_id, x.user_aim, x.user_yahoo, x.user_msn, x.user_xmpp, x.user_homepage, x.user_location, x.user_job, x.user_hobbies, x.email_public;');
     if ( !$q )
       $db->_die();
     
@@ -904,25 +983,29 @@
     
     // Basic user info
     
-    echo '<tr><th class="subhead">All about ' . htmlspecialchars($target_username) . '</th></tr>';
-    echo '<tr><td class="row3">Joined: ' . date('F d, Y h:i a', $userdata['reg_time']) . '</td></tr>';
-    echo '<tr><td class="row1">Total comments: ' . $userdata['n_comments'] . '</td></tr>';
+    echo '<tr><th class="subhead">' . $lang->get('userpage_heading_basics', array('username' => htmlspecialchars($target_username))) . '</th></tr>';
+    if ( $userdata['user_has_avatar'] == '1' )
+    {
+      echo '<tr><td class="row1" style="text-align: center;"><img alt="' . $lang->get('usercp_avatar_image_alt', array('username' => $userdata['username'])) . '" src="' . make_avatar_url(intval($userdata['authoritative_uid']), $userdata['avatar_type']) . '" /></td></tr>';
+    }
+    echo '<tr><td class="row3">' . $lang->get('userpage_lbl_joined') . ' ' . enano_date('F d, Y h:i a', $userdata['reg_time']) . '</td></tr>';
+    echo '<tr><td class="row1">' . $lang->get('userpage_lbl_num_comments') . ' ' . $userdata['n_comments'] . '</td></tr>';
     
     if ( !empty($userdata['real_name']) )
     {
-      echo '<tr><td class="row3">Real name: ' . $userdata['real_name'] . '</td></tr>';
+      echo '<tr><td class="row3">' . $lang->get('userpage_lbl_real_name') . ' ' . $userdata['real_name'] . '</td></tr>';
     }
     
     // Administer user button
     
     if ( $session->user_level >= USER_LEVEL_ADMIN )
     {
-      echo '<tr><td class="row1"><a href="' . makeUrlNS('Special', 'Administration', 'module=' . $paths->nslist['Admin'] . 'UserManager&src=get&user=' . urlencode($target_username), true) . '" onclick="ajaxAdminUser(\'' . addslashes($target_username) . '\'); return false;">Administer user</a></td></tr>';
+      echo '<tr><td class="row1"><a href="' . makeUrlNS('Special', 'Administration', 'module=' . $paths->nslist['Admin'] . 'UserManager&src=get&user=' . urlencode($target_username), true) . '" onclick="ajaxAdminUser(\'' . addslashes($target_username) . '\'); return false;">' . $lang->get('userpage_btn_administer_user') . '</a></td></tr>';
     }
     
     // Comments
     
-    echo '<tr><th class="subhead">' . htmlspecialchars($target_username) . '\'s latest comments</th></tr>';
+    echo '<tr><th class="subhead">' . $lang->get('userpage_heading_comments', array('username' => htmlspecialchars($target_username))) . '</th></tr>';
     $q = $db->sql_query('SELECT page_id, namespace, subject, time FROM '.table_prefix.'comments WHERE name=\'' . $db->escape($target_username) . '\' AND user_id=' . $userdata['authoritative_uid'] . ' AND approved=1 ORDER BY time DESC LIMIT 5;');
     if ( !$q )
       $db->_die();
@@ -934,7 +1017,7 @@
     {
       do 
       {
-        $row['time'] = date('F d, Y', $row['time']);
+        $row['time'] = enano_date('F d, Y', $row['time']);
         $comments[] = $row;
       }
       while ( $row = $db->fetchrow() );
@@ -953,7 +1036,7 @@
     $tpl = '<tr>
               <td class="{CLASS}">
                 <a href="{PAGE_LINK}" <!-- BEGINNOT page_exists -->class="wikilink-nonexistent"<!-- END page_exists -->>{PAGE}</a><br />
-                <small>Posted {DATE}<br /></small>
+                <small>{lang:userpage_comments_lbl_posted} {DATE}<br /></small>
                 <b><a href="{COMMENT_LINK}">{SUBJECT}</a></b>
               </td>
             </tr>';
@@ -992,7 +1075,7 @@
     }
     else
     {
-      echo '<tr><td class="' . $class . '">This user has not posted any comments.</td></tr>';
+      echo '<tr><td class="' . $class . '">' . $lang->get('userpage_msg_no_comments') . '</td></tr>';
     }
     echo '</table>';
     
@@ -1045,7 +1128,7 @@
     
     // Contact information
     
-    echo '<tr><th class="subhead">Get in touch</th></tr>';
+    echo '<tr><th class="subhead">' . $lang->get('userpage_heading_contact') . '</th></tr>';
     
     $class = 'row3';
     
@@ -1053,71 +1136,71 @@
     {
       $class = ( $class == 'row1' ) ? 'row3' : 'row1';
       $email_link = $email->encryptEmail($userdata['email']);
-      echo '<tr><td class="'.$class.'">E-mail address: ' . $email_link . '</td></tr>';
+      echo '<tr><td class="'.$class.'">' . $lang->get('userpage_lbl_email') . ' ' . $email_link . '</td></tr>';
     }
     
     $class = ( $class == 'row1' ) ? 'row3' : 'row1';
     if ( $session->user_logged_in )
     {
-      echo '<tr><td class="'.$class.'">Send ' . htmlspecialchars($target_username) . ' a <a href="' . makeUrlNS('Special', 'PrivateMessages/Compose/to/' . $this->page_id, false, true) . '">Private Message</a>!</td></tr>';
+      echo '<tr><td class="'.$class.'">' . $lang->get('userpage_btn_send_pm', array('username' => htmlspecialchars($target_username), 'pm_link' => makeUrlNS('Special', 'PrivateMessages/Compose/to/' . $this->page_id, false, true))) . '</td></tr>';
     }
     else
     {
-      echo '<tr><td class="'.$class.'">You could send ' . htmlspecialchars($target_username) . ' a private message if you were <a href="' . makeUrlNS('Special', 'Login/' . $paths->nslist[$this->namespace] . $this->page_id) . '">logged in</a>.</td></tr>';
+      echo '<tr><td class="'.$class.'">' . $lang->get('userpage_btn_send_pm_guest', array('username' => htmlspecialchars($target_username), 'login_flags' => 'href="' . makeUrlNS('Special', 'Login/' . $paths->nslist[$this->namespace] . $this->page_id) . '" onclick="ajaxStartLogin(); return false;"')) . '</td></tr>';
     }
     
     if ( !empty($userdata['user_aim']) )
     {
       $class = ( $class == 'row1' ) ? 'row3' : 'row1';
-      echo '<tr><td class="'.$class.'">AIM: ' . $userdata['user_aim'] . '</td></tr>';
+      echo '<tr><td class="'.$class.'">' . $lang->get('userpage_lbl_aim') . ' ' . $userdata['user_aim'] . '</td></tr>';
     }
     
     if ( !empty($userdata['user_yahoo']) )
     {
       $class = ( $class == 'row1' ) ? 'row3' : 'row1';
-      echo '<tr><td class="'.$class.'">Yahoo! IM: ' . $userdata['user_yahoo'] . '</td></tr>';
+      echo '<tr><td class="'.$class.'">' . $lang->get('userpage_lbl_yim') . ' ' . $userdata['user_yahoo'] . '</td></tr>';
     }
     
     if ( !empty($userdata['user_msn']) )
     {
       $class = ( $class == 'row1' ) ? 'row3' : 'row1';
       $email_link = $email->encryptEmail($userdata['user_msn']);
-      echo '<tr><td class="'.$class.'">WLM: ' . $email_link . '</td></tr>';
+      echo '<tr><td class="'.$class.'">' . $lang->get('userpage_lbl_wlm') . ' ' . $email_link . '</td></tr>';
     }
     
     if ( !empty($userdata['user_xmpp']) )
     {
       $class = ( $class == 'row1' ) ? 'row3' : 'row1';
       $email_link = $email->encryptEmail($userdata['user_xmpp']);
-      echo '<tr><td class="'.$class.'">XMPP/Jabber: ' . $email_link . '</td></tr>';
+      echo '<tr><td class="'.$class.'">' . $lang->get('userpage_lbl_xmpp') . ' ' . $email_link . '</td></tr>';
     }
     
     // Real life
     
-    echo '<tr><th class="subhead">' . htmlspecialchars($target_username) . ' in real life</th></tr>';
+    echo '<tr><th class="subhead">' . $lang->get('userpage_heading_real_life', array('username' => htmlspecialchars($target_username))) . '</th></tr>';
     
     if ( !empty($userdata['user_location']) )
     {
       $class = ( $class == 'row1' ) ? 'row3' : 'row1';
-      echo '<tr><td class="'.$class.'">Location: ' . $userdata['user_location'] . '</td></tr>';
+      echo '<tr><td class="'.$class.'">' . $lang->get('userpage_lbl_location') . ' ' . $userdata['user_location'] . '</td></tr>';
     }
     
     if ( !empty($userdata['user_job']) )
     {
       $class = ( $class == 'row1' ) ? 'row3' : 'row1';
-      echo '<tr><td class="'.$class.'">Job/occupation: ' . $userdata['user_job'] . '</td></tr>';
+      echo '<tr><td class="'.$class.'">' . $lang->get('userpage_lbl_job') . ' ' . $userdata['user_job'] . '</td></tr>';
     }
     
     if ( !empty($userdata['user_hobbies']) )
     {
       $class = ( $class == 'row1' ) ? 'row3' : 'row1';
-      echo '<tr><td class="'.$class.'">Enjoys: ' . $userdata['user_hobbies'] . '</td></tr>';
+      echo '<tr><td class="'.$class.'">' . $lang->get('userpage_lbl_hobbies') . ' ' . $userdata['user_hobbies'] . '</td></tr>';
     }
     
     if ( empty($userdata['user_location']) && empty($userdata['user_job']) && empty($userdata['user_hobbies']) )
     {
       $class = ( $class == 'row1' ) ? 'row3' : 'row1';
-      echo '<tr><td class="'.$class.'">' . htmlspecialchars($target_username) . ' hasn\'t posted any real-life contact information.</td></tr>';
+      echo '<tr><td class="'.$class.'">' . $lang->get('userpage_msg_no_contact_info', array('username' => htmlspecialchars($target_username))) . '</td></tr>';
     }
     
     $code = $plugins->setHook('userpage_sidebar_right');
@@ -1133,7 +1216,10 @@
     
     else:
     
-    echo '<p>Additional information: user "' . htmlspecialchars($target_username) . '" does not exist.</p>';
+    if ( !is_valid_ip($target_username) )
+    {
+      echo '<p>' . $lang->get('userpage_msg_user_not_exist', array('username' => htmlspecialchars($target_username))) . '</p>';
+    }
     
     endif;
     
@@ -1159,19 +1245,29 @@
   function _handle_redirect($page_id, $namespace)
   {
     global $db, $session, $paths, $template, $plugins; // Common objects
+    global $lang;
     $arr_pid = array($this->page_id, $this->namespace);
     if ( $namespace == 'Special' || $namespace == 'Admin' )
     {
-      return 'This page redirects to a Special or Administration page, which is not allowed.';
+      return $lang->get('page_err_redirect_to_special');
     }
-    if ( in_array($this->redirect_stack, $arr_pid) )
+    $looped = false;
+    foreach ( $this->redirect_stack as $page )
     {
-      return 'This page infinitely redirects with another page (or another series of pages), and the infinite redirect was trapped.';
+      if ( $page[0] == $arr_pid[0] && $page[1] == $arr_pid[1] )
+      {
+        $looped = true;
+        break;
+      }
+    }
+    if ( $looped )
+    {
+      return $lang->get('page_err_redirect_infinite_loop');
     }
     $page_id_key = $paths->nslist[ $namespace ] . sanitize_page_id($page_id);
     if ( !isset($paths->pages[$page_id_key]) )
     {
-      return 'This page redirects to another page that doesn\'t exist.';
+      return $lang->get('page_err_redirect_to_nonexistent');
     }
     $this->redirect_stack[] = $arr_pid;
     
@@ -1191,9 +1287,11 @@
   function err_access_denied()
   {
     global $db, $session, $paths, $template, $plugins; // Common objects
+    global $lang;
+    global $email;
     
     // Log it for crying out loud
-    $q = $db->sql_query('INSERT INTO '.table_prefix.'logs(log_type,action,time_id,date_string,author,edit_summary,page_text) VALUES(\'security\', \'illegal_page\', '.time().', \''.date('d M Y h:i a').'\', \''.$db->escape($session->username).'\', \''.$db->escape($_SERVER['REMOTE_ADDR']).'\', \'' . $db->escape(serialize(array($this->page_id, $this->namespace))) . '\')');
+    $q = $db->sql_query('INSERT INTO '.table_prefix.'logs(log_type,action,time_id,date_string,author,edit_summary,page_text) VALUES(\'security\', \'illegal_page\', '.time().', \''.enano_date('d M Y h:i a').'\', \''.$db->escape($session->username).'\', \''.$db->escape($_SERVER['REMOTE_ADDR']).'\', \'' . $db->escape(serialize(array($this->page_id, $this->namespace))) . '\')');
     
     $ob = '';
     //$template->tpl_strings['PAGE_NAME'] = 'Access denied';
@@ -1221,11 +1319,14 @@
         $title = ( isset($page_data['name']) ) ? $page_data['name'] : $paths->nslist[$this->namespace] . htmlspecialchars( str_replace('_', ' ', dirtify_page_id( $this->page_id ) ) );
         $b = '<a href="' . $url . '">' . $title . '</a>';
         
-        $ob .= '<small>(Redirected to ' . $b . ' from ' . $a . ')<br /></small>';
+        $ob .= '<small>' . $lang->get('page_msg_redirected_from_to', array('from' => $a, 'to' => $b)) . '<br /></small>';
       }
     }
     
-    $ob .= '<div class="error-box"><b>Access to this page is denied.</b><br />This may be because you are not logged in or you have not met certain criteria for viewing this page.</div>';
+    $email_link = $email->encryptEmail(getConfig('contact_email'), '', '', $lang->get('page_err_access_denied_siteadmin'));
+    
+    $ob .= "<h3>" . $lang->get('page_err_access_denied_title') . "</h3>";
+    $ob .= "<p>" . $lang->get('page_err_access_denied_body', array('site_administration' => $email_link)) . "</p>";
     
     if ( $this->send_headers )
     {
@@ -1242,12 +1343,15 @@
   function err_wrong_password()
   {
     global $db, $session, $paths, $template, $plugins; // Common objects
+    global $lang;
     
     $title = 'Password required';
-    $message = ( empty($this->password) ) ? '<p>Access to this page requires a password. Please enter the password for this page below:</p>' : '<p>The password you entered for this page was incorrect. Please enter the password for this page below:</p>';
+    $message = ( empty($this->password) ) ?
+                 '<p>' . $lang->get('page_msg_passrequired') . '</p>' :
+                 '<p>' . $lang->get('page_msg_pass_wrong') . '</p>';
     $message .= '<form action="' . makeUrlNS($this->namespace, $this->page_id) . '" method="post">
                    <p>
-                     <label>Password: <input name="pagepass" type="password" /></label>&nbsp;&nbsp;<input type="submit" value="Submit" />
+                     <label>' . $lang->get('page_lbl_password') . ' <input name="pagepass" type="password" /></label>&nbsp;&nbsp;<input type="submit" value="Submit" />
                    </p>
                  </form>';
     if ( $this->send_headers )
@@ -1297,51 +1401,75 @@
   function err_page_not_existent($userpage = false)
   {
     global $db, $session, $paths, $template, $plugins; // Common objects
+    global $lang;
     
     header('HTTP/1.1 404 Not Found');
     
     $this->header();
     $this->do_breadcrumbs();
     
-    if ( $userpage )
-    {
-      echo '<h3>There is no page with this title yet.</h3>
-             <p>This user has not created his or her user page yet.';
-    }
-    else
+    $msg = $paths->sysmsg('Page_not_found');
+    if ( $msg )
     {
-      echo '<h3>There is no page with this title yet.</h3>
-             <p>You have requested a page that doesn\'t exist yet.';
-    }
-    if ( $session->get_permissions('create_page') )
-    {
-      echo ' You can <a href="'.makeUrlNS($this->namespace, $this->page_id, 'do=edit', true).'" onclick="ajaxEditor(); return false;">create this page</a>, or return to the <a href="'.makeUrl(getConfig('main_page')).'">homepage</a>.';
+      $msg = RenderMan::render($msg);
+      eval( '?>' . $msg );
     }
     else
     {
-      echo ' Return to the <a href="'.makeUrl(getConfig('main_page')).'">homepage</a>.</p>';
-    }
-    if ( $session->get_permissions('history_rollback') )
-    {
-      $e = $db->sql_query('SELECT * FROM ' . table_prefix . 'logs WHERE action=\'delete\' AND page_id=\'' . $this->page_id . '\' AND namespace=\'' . $this->namespace . '\' ORDER BY time_id DESC;');
-      if ( !$e )
+      if ( $userpage )
+      {
+        echo '<h3>' . $lang->get('page_msg_404_title') . '</h3>
+               <p>' . $lang->get('page_msg_404_body_userpage');
+      }
+      else
+      {
+        echo '<h3>' . $lang->get('page_msg_404_title') . '</h3>
+               <p>' . $lang->get('page_msg_404_body');
+      }
+      if ( $session->get_permissions('create_page') )
       {
-        $db->_die('The deletion log could not be selected.');
+        echo ' ' . $lang->get('page_msg_404_create', array(
+            'create_flags' => 'href="'.makeUrlNS($this->namespace, $this->page_id, 'do=edit', true).'" onclick="ajaxEditor(); return false;"',
+            'mainpage_link' => makeUrl(getConfig('main_page'), false, true)
+          ));
       }
-      if ( $db->numrows() > 0 )
+      else
+      {
+        echo ' ' . $lang->get('page_msg_404_gohome', array(
+            'mainpage_link' => makeUrl(getConfig('main_page'), false, true)
+          ));
+      }
+      echo '</p>';
+      if ( $session->get_permissions('history_rollback') )
       {
-        $r = $db->fetchrow();
-        echo '<p><b>This page was deleted on ' . $r['date_string'] . '.</b> The stated reason was:</p><blockquote>' . $r['edit_summary'] . '</blockquote><p>You can probably <a href="'.makeUrl($paths->page, 'do=rollback&amp;id='.$r['time_id']).'" onclick="ajaxRollback(\''.$r['time_id'].'\'); return false;">roll back</a> the deletion.</p>';
-        if ( $session->user_level >= USER_LEVEL_ADMIN )
+        $e = $db->sql_query('SELECT * FROM ' . table_prefix . 'logs WHERE action=\'delete\' AND page_id=\'' . $this->page_id . '\' AND namespace=\'' . $this->namespace . '\' ORDER BY time_id DESC;');
+        if ( !$e )
         {
-          echo '<p>Additional admin options: <a href="' . makeUrl($paths->page, 'do=detag', true) . '" title="Remove any tags on this page">detag page</a></p>';
+          $db->_die('The deletion log could not be selected.');
         }
+        if ( $db->numrows() > 0 )
+        {
+          $r = $db->fetchrow();
+          echo '<p>' . $lang->get('page_msg_404_was_deleted', array(
+                    'delete_time' => enano_date('d M Y h:i a', $r['time_id']),
+                    'delete_reason' => htmlspecialchars($r['edit_summary']),
+                    'rollback_flags' => 'href="'.makeUrl($paths->page, 'do=rollback&amp;id='.$r['time_id']).'" onclick="ajaxRollback(\''.$r['time_id'].'\'); return false;"'
+                  ))
+                . '</p>';
+          if ( $session->user_level >= USER_LEVEL_ADMIN )
+          {
+            echo '<p>' . $lang->get('page_msg_404_admin_opts', array(
+                      'detag_link' => makeUrl($paths->page, 'do=detag', true)
+                    ))
+                  . '</p>';
+          }
+        }
+        $db->free_result();
       }
-      $db->free_result();
+      echo '<p>
+              ' . $lang->get('page_msg_404_http_response') . '
+            </p>';
     }
-    echo '<p>
-            HTTP Error: 404 Not Found
-          </p>';
     $this->footer();
   }
   
@@ -1398,16 +1526,6 @@
   }
   
   /**
-   * PHP 4 constructor.
-   * @see PageProcessor::__construct()
-   */
-  
-  function PageProcessor( $page_id, $namespace, $revision_id = 0 )
-  {
-    $this->__construct($page_id, $namespace, $revision_id);
-  }
-  
-  /**
    * Send an error message and die. For debugging or critical technical errors only - nothing that would under normal circumstances be shown to the user.
    * @var string Error message
    * @var bool If true, send DBAL's debugging information as well
@@ -1416,9 +1534,10 @@
   function send_error($message, $sql = false)
   {
     global $db, $session, $paths, $template, $plugins; // Common objects
+    global $lang;
     
     $content = "<p>$message</p>";
-    $template->tpl_strings['PAGE_NAME'] = 'General error in page fetcher';
+    $template->tpl_strings['PAGE_NAME'] = $lang->get('page_msg_general_error');
     
     if ( $this->debug['works'] )
     {
--- a/includes/pageutils.php	Fri Feb 22 12:46:51 2008 -0500
+++ b/includes/pageutils.php	Fri Feb 22 12:51:53 2008 -0500
@@ -1,7 +1,8 @@
 <?php
+
 /*
  * Enano - an open-source CMS capable of wiki functions, Drupal-like sidebar blocks, and everything in between
- * Version 1.0.3 (Dyrad)
+ * Version 1.1.1
  * Copyright (C) 2006-2007 Dan Fuhry
  * pageutils.php - a class that handles raw page manipulations, used mostly by AJAX requests or their old-fashioned form-based counterparts
  *
@@ -20,14 +21,14 @@
    * @return string
    */
   
-  function checkusername($name)
+  public static function checkusername($name)
   {
     global $db, $session, $paths, $template, $plugins; // Common objects
     $name = str_replace('_', ' ', $name);
     $q = $db->sql_query('SELECT username FROM ' . table_prefix.'users WHERE username=\'' . $db->escape(rawurldecode($name)) . '\'');
     if ( !$q )
     {
-      die(mysql_error());
+      die($db->get_error());
     }
     if ( $db->numrows() < 1)
     {
@@ -46,7 +47,7 @@
    * @todo (DONE) Make it require a password (just for security purposes)
    */
    
-  function getsource($page, $password = false)
+  public static function getsource($page, $password = false)
   {
     global $db, $session, $paths, $template, $plugins; // Common objects
     if(!isset($paths->pages[$page]))
@@ -88,235 +89,15 @@
   }
   
   /**
-   * Basically a frontend to RenderMan::getPage(), with the ability to send valid data for nonexistent pages
+   * DEPRECATED. Previously returned the full rendered contents of a page.
    * @param $page the full page id (Namespace:Pagename)
    * @param $send_headers true if the theme headers should be sent (still dependent on current page settings), false otherwise
    * @return string
    */
   
-  function getpage($page, $send_headers = false, $hist_id = false)
+  public static function getpage($page, $send_headers = false, $hist_id = false)
   {
     die('PageUtils->getpage is deprecated.');
-    global $db, $session, $paths, $template, $plugins; // Common objects
-    ob_start();
-    $pid = RenderMan::strToPageID($page);
-    //die('<pre>'.print_r($pid, true).'</pre>');
-    if(isset($paths->pages[$page]['password']) && strlen($paths->pages[$page]['password']) == 40)
-    {
-      password_prompt($page);
-    }
-    if(isset($paths->pages[$page]))
-    {
-      doStats($pid[0], $pid[1]);
-    }
-    if($paths->custom_page || $pid[1] == 'Special')
-    {
-      // If we don't have access to the page, get out and quick!
-      if(!$session->get_permissions('read') && $pid[0] != 'Login' && $pid[0] != 'Register')
-      {
-        $template->tpl_strings['PAGE_NAME'] = 'Access denied';
-        
-        if ( $send_headers )
-        {
-          $template->header();
-        }
-        
-        echo '<div class="error-box"><b>Access to this page is denied.</b><br />This may be because you are not logged in or you have not met certain criteria for viewing this page.</div>';
-        
-        if ( $send_headers )
-        {
-          $template->footer();
-        }
-        
-        $r = ob_get_contents();
-        ob_end_clean();
-        return $r;
-      }
-      
-      $fname = 'page_' . $pid[1] . '_' . $paths->pages[$page]['urlname_nons'];
-      @call_user_func($fname);
-      
-    }
-    else if ( $pid[1] == 'Admin' )
-    {
-      // If we don't have access to the page, get out and quick!
-      if(!$session->get_permissions('read'))
-      {
-        $template->tpl_strings['PAGE_NAME'] = 'Access denied';
-        if ( $send_headers )
-        {
-          $template->header();
-        }
-        echo '<div class="error-box"><b>Access to this page is denied.</b><br />This may be because you are not logged in or you have not met certain criteria for viewing this page.</div>';
-        if ( $send_headers )
-        {
-          $template->footer();
-        }
-        $r = ob_get_contents();
-        ob_end_clean();
-        return $r;
-      }
-      
-      $fname = 'page_' . $pid[1] . '_' . $pid[0];
-      if ( !function_exists($fname) )
-      {
-        $title = 'Page backend not found';
-        $message = "The administration page you are looking for was properly registered using the page API, but the backend function
-                    (<tt>$fname</tt>) was not found. If this is a plugin page, then this is almost certainly a bug with the plugin.";
-        if ( $send_headers )
-        {
-          die_friendly($title, "<p>$message</p>");
-        }
-        else
-        {
-          echo "<h2>$title</h2>\n<p>$message</p>";
-        }
-      }
-      @call_user_func($fname);
-    }
-    else if ( !isset( $paths->pages[$page] ) )
-    {
-      ob_start();
-      $code = $plugins->setHook('page_not_found');
-      foreach ( $code as $cmd )
-      {
-        eval($cmd);
-      }
-      $text = ob_get_contents();
-      if ( $text != '' )
-      {
-        ob_end_clean();
-        return $text;
-      }
-      $template->header();
-      if($m = $paths->sysmsg('Page_not_found'))
-      {
-        eval('?>'.RenderMan::render($m));
-      }
-      else
-      {
-        header('HTTP/1.1 404 Not Found');
-        echo '<h3>There is no page with this title yet.</h3>
-               <p>You have requested a page that doesn\'t exist yet.';
-        if($session->get_permissions('create_page')) echo ' You can <a href="'.makeUrl($paths->page, 'do=edit', true).'" onclick="ajaxEditor(); return false;">create this page</a>, or return to the <a href="'.makeUrl(getConfig('main_page')).'">homepage</a>.';
-        else echo ' Return to the <a href="'.makeUrl(getConfig('main_page')).'">homepage</a>.</p>';
-        if ( $session->get_permissions('history_rollback') )
-        {
-          $e = $db->sql_query('SELECT * FROM ' . table_prefix.'logs WHERE action=\'delete\' AND page_id=\'' . $paths->page_id . '\' AND namespace=\'' . $pid[1] . '\' ORDER BY time_id DESC;');
-          if ( !$e )
-          {
-            $db->_die('The deletion log could not be selected.');
-          }
-          if ($db->numrows() > 0 )
-          {
-            $r = $db->fetchrow();
-            echo '<p>This page also appears to have some log entries in the database - it seems that it was deleted on ' . $r['date_string'] . '. You can probably <a href="'.makeUrl($paths->page, 'do=rollback&amp;id=' . $r['time_id']) . '" onclick="ajaxRollback(\'' . $r['time_id'] . '\'); return false;">roll back</a> the deletion.</p>';
-          }
-          $db->free_result();
-        }
-        echo '<p>
-                HTTP Error: 404 Not Found
-              </p>';
-      }
-      $template->footer();
-    }
-    else
-    {
-      
-      // If we don't have access to the page, get out and quick!
-      if(!$session->get_permissions('read'))
-      {
-        $template->tpl_strings['PAGE_NAME'] = 'Access denied';
-        if($send_headers) $template->header();
-        echo '<div class="error-box"><b>Access to this page is denied.</b><br />This may be because you are not logged in or you have not met certain criteria for viewing this page.</div>';
-        if($send_headers) $template->footer();
-        $r = ob_get_contents();
-        ob_end_clean();
-        return $r;
-      }
-      
-      ob_start();
-      $code = $plugins->setHook('page_custom_handler');
-      foreach ( $code as $cmd )
-      {
-        eval($cmd);
-      }
-      $text = ob_get_contents();
-      if ( $text != '' )
-      {
-        ob_end_clean();
-        return $text;
-      }
-      
-      if ( $hist_id )
-      {
-        $e = $db->sql_query('SELECT page_text,date_string,char_tag FROM ' . table_prefix.'logs WHERE page_id=\'' . $paths->pages[$page]['urlname_nons'] . '\' AND namespace=\'' . $pid[1] . '\' AND log_type=\'page\' AND action=\'edit\' AND time_id=' . $db->escape($hist_id) . '');
-        if($db->numrows() < 1)
-        {
-          $db->_die('There were no rows in the text table that matched the page text query.');
-        }
-        $r = $db->fetchrow();
-        $db->free_result();
-        $message = '<div class="info-box" style="margin-left: 0; margin-top: 5px;"><b>Notice:</b><br />The page you are viewing was archived on ' . $r['date_string'] . '.<br /><a href="'.makeUrl($page).'" onclick="ajaxReset(); return false;">View current version</a>  |  <a href="'.makeUrl($page, 'do=rollback&amp;id=' . $hist_id) . '" onclick="ajaxRollback(\'' . $hist_id . '\')">Restore this version</a></div><br />'.RenderMan::render($r['page_text']);
-        
-        if( !$paths->pages[$page]['special'] )
-        {
-          if($send_headers)
-          {
-            $template->header(); 
-          }
-          display_page_headers();
-        }
-        
-        eval('?>' . $message);
-        
-        if( !$paths->pages[$page]['special'] )
-        {
-          display_page_footers();
-          if($send_headers)
-          {
-            $template->footer();
-          }
-        }
-        
-      } else {
-        if(!$paths->pages[$page]['special'])
-        {
-          $message = RenderMan::getPage($paths->pages[$page]['urlname_nons'], $pid[1]);
-        }
-        else
-        {
-          $message = RenderMan::getPage($paths->pages[$page]['urlname_nons'], $pid[1], 0, false, false, false, false);
-        }
-        // This line is used to debug wikiformatted code
-        // die('<pre>'.htmlspecialchars($message).'</pre>');
-        
-        if( !$paths->pages[$page]['special'] )
-        {
-          if($send_headers)
-          {
-            $template->header(); 
-          }
-          display_page_headers();
-        }
-
-        // This is it, this is what all of Enano has been working up to...
-        
-        eval('?>' . $message);
-        
-        if( !$paths->pages[$page]['special'] )
-        {
-          display_page_footers();
-          if($send_headers)
-          {
-            $template->footer();
-          }
-        }
-      }
-    }
-    $ret = ob_get_contents();
-    ob_end_clean();
-    return $ret;
   }
   
   /**
@@ -327,7 +108,7 @@
    * @return string
    */
    
-  function savepage($page_id, $namespace, $message, $summary = 'No edit summary given', $minor = false)
+  public static function savepage($page_id, $namespace, $message, $summary = 'No edit summary given', $minor = false)
   {
     global $db, $session, $paths, $template, $plugins; // Common objects
     $uid = sha1(microtime());
@@ -379,7 +160,7 @@
     $msg = $db->escape($message);
     
     $minor = $minor ? ENANO_SQL_BOOLEAN_TRUE : ENANO_SQL_BOOLEAN_FALSE;
-    $q='INSERT INTO ' . table_prefix.'logs(log_type,action,time_id,date_string,page_id,namespace,page_text,char_tag,author,edit_summary,minor_edit) VALUES(\'page\', \'edit\', '.time().', \''.date('d M Y h:i a').'\', \'' . $paths->page_id . '\', \'' . $paths->namespace . '\', ' . ENANO_SQL_MULTISTRING_PRFIX . '\'' . $msg . '\', \'' . $uid . '\', \'' . $session->username . '\', \'' . $db->escape(htmlspecialchars($summary)) . '\', ' . $minor . ');';
+    $q='INSERT INTO ' . table_prefix.'logs(log_type,action,time_id,date_string,page_id,namespace,page_text,char_tag,author,edit_summary,minor_edit) VALUES(\'page\', \'edit\', '.time().', \''.enano_date('d M Y h:i a').'\', \'' . $paths->page_id . '\', \'' . $paths->namespace . '\', ' . ENANO_SQL_MULTISTRING_PRFIX . '\'' . $msg . '\', \'' . $uid . '\', \'' . $session->username . '\', \'' . $db->escape(htmlspecialchars($summary)) . '\', ' . $minor . ');';
     if(!$db->sql_query($q)) $db->_die('The history (log) entry could not be inserted into the logs table.');
     
     $q = 'UPDATE ' . table_prefix.'page_text SET page_text=' . ENANO_SQL_MULTISTRING_PRFIX . '\'' . $msg . '\',char_tag=\'' . $uid . '\' WHERE page_id=\'' . $page_id . '\' AND namespace=\'' . $namespace . '\';';
@@ -398,7 +179,7 @@
    * @return bool true on success, false on failure
    */
   
-  function createPage($page_id, $namespace, $name = false, $visible = 1)
+  public static function createPage($page_id, $namespace, $name = false, $visible = 1)
   {
     global $db, $session, $paths, $template, $plugins; // Common objects
     if(in_array($namespace, Array('Special', 'Admin')))
@@ -438,16 +219,20 @@
       return 'The prefix "Project:" is reserved for a parser shortcut; if a page was created using this prefix, it would not be possible to link to it.';
     }
     
-    $page_id = dirtify_page_id($page_id);
-    
-    if ( !$name )
-      $name = str_replace('_', ' ', $page_id);
+    /*
+    // Dunno why this was here. Enano can handle more flexible names than this...
     $regex = '#^([A-z0-9 _\-\.\/\!\@\(\)]*)$#is';
     if(!preg_match($regex, $name))
     {
       //echo '<b>Notice:</b> PageUtils::createPage: Name contains invalid characters<br />';
       return 'Name contains invalid characters';
     }
+    */
+    
+    $page_id = dirtify_page_id($page_id);
+    
+    if ( !$name )
+      $name = str_replace('_', ' ', $page_id);
     
     $page_id = sanitize_page_id( $page_id );
     
@@ -471,7 +256,7 @@
     
     $qa = $db->sql_query('INSERT INTO ' . table_prefix.'pages(name,urlname,namespace,visible,protected,delvote_ips) VALUES(\'' . $db->escape($name) . '\', \'' . $db->escape($page_id) . '\', \'' . $namespace . '\', '. ( $visible ? '1' : '0' ) .', ' . $prot . ', \'' . $db->escape(serialize($ips)) . '\');');
     $qb = $db->sql_query('INSERT INTO ' . table_prefix.'page_text(page_id,namespace) VALUES(\'' . $db->escape($page_id) . '\', \'' . $namespace . '\');');
-    $qc = $db->sql_query('INSERT INTO ' . table_prefix.'logs(time_id,date_string,log_type,action,author,page_id,namespace) VALUES('.time().', \''.date('d M Y h:i a').'\', \'page\', \'create\', \'' . $session->username . '\', \'' . $db->escape($page_id) . '\', \'' . $namespace . '\');');
+    $qc = $db->sql_query('INSERT INTO ' . table_prefix.'logs(time_id,date_string,log_type,action,author,page_id,namespace) VALUES('.time().', \''.enano_date('d M Y h:i a').'\', \'page\', \'create\', \'' . $session->username . '\', \'' . $db->escape($page_id) . '\', \'' . $namespace . '\');');
     
     if($qa && $qb && $qc)
       return 'good';
@@ -489,7 +274,7 @@
    * @param $reason string why the page is being (un)protected
    * @return string - "good" on success, in all other cases, an error string (on query failure, calls $db->_die() )
    */
-  function protect($page_id, $namespace, $level, $reason)
+  public static function protect($page_id, $namespace, $level, $reason)
   {
     global $db, $session, $paths, $template, $plugins; // Common objects
     
@@ -513,13 +298,13 @@
     switch($level)
     {
       case 0:
-        $q = 'INSERT INTO ' . table_prefix.'logs(time_id,date_string,log_type,action,author,page_id,namespace,edit_summary) VALUES('.time().', \''.date('d M Y h:i a').'\', \'page\', \'unprot\', \'' . $session->username . '\', \'' . $page_id . '\', \'' . $namespace . '\', \'' . $db->escape(htmlspecialchars($reason)) . '\');';
+        $q = 'INSERT INTO ' . table_prefix.'logs(time_id,date_string,log_type,action,author,page_id,namespace,edit_summary) VALUES('.time().', \''.enano_date('d M Y h:i a').'\', \'page\', \'unprot\', \'' . $session->username . '\', \'' . $page_id . '\', \'' . $namespace . '\', \'' . $db->escape(htmlspecialchars($reason)) . '\');';
         break;
       case 1:
-        $q = 'INSERT INTO ' . table_prefix.'logs(time_id,date_string,log_type,action,author,page_id,namespace,edit_summary) VALUES('.time().', \''.date('d M Y h:i a').'\', \'page\', \'prot\', \'' . $session->username . '\', \'' . $page_id . '\', \'' . $namespace . '\', \'' . $db->escape(htmlspecialchars($reason)) . '\');';
+        $q = 'INSERT INTO ' . table_prefix.'logs(time_id,date_string,log_type,action,author,page_id,namespace,edit_summary) VALUES('.time().', \''.enano_date('d M Y h:i a').'\', \'page\', \'prot\', \'' . $session->username . '\', \'' . $page_id . '\', \'' . $namespace . '\', \'' . $db->escape(htmlspecialchars($reason)) . '\');';
         break;
       case 2:
-        $q = 'INSERT INTO ' . table_prefix.'logs(time_id,date_string,log_type,action,author,page_id,namespace,edit_summary) VALUES('.time().', \''.date('d M Y h:i a').'\', \'page\', \'semiprot\', \'' . $session->username . '\', \'' . $page_id . '\', \'' . $namespace . '\', \'' . $db->escape(htmlspecialchars($reason)) . '\');';
+        $q = 'INSERT INTO ' . table_prefix.'logs(time_id,date_string,log_type,action,author,page_id,namespace,edit_summary) VALUES('.time().', \''.enano_date('d M Y h:i a').'\', \'page\', \'semiprot\', \'' . $session->username . '\', \'' . $page_id . '\', \'' . $namespace . '\', \'' . $db->escape(htmlspecialchars($reason)) . '\');';
         break;
       default:
         return 'PageUtils::protect(): Invalid value for $level';
@@ -543,9 +328,10 @@
    * @return string
    */
   
-  function histlist($page_id, $namespace)
+  public static function histlist($page_id, $namespace)
   {
     global $db, $session, $paths, $template, $plugins; // Common objects
+    global $lang;
     
     if(!$session->get_permissions('history_view'))
       return 'Access denied';
@@ -556,16 +342,19 @@
     $wiki = ( ( $paths->pages[$pname]['wiki_mode'] == 2 && getConfig('wiki_mode') == '1') || $paths->pages[$pname]['wiki_mode'] == 1) ? true : false;
     $prot = ( ( $paths->pages[$pname]['protected'] == 2 && $session->user_logged_in && $session->reg_time + 60*60*24*4 < time() ) || $paths->pages[$pname]['protected'] == 1) ? true : false;
     
-    $q = 'SELECT time_id,date_string,page_id,namespace,author,edit_summary,minor_edit FROM ' . table_prefix.'logs WHERE log_type=\'page\' AND action=\'edit\' AND page_id=\'' . $page_id . '\' AND namespace=\'' . $namespace . '\' ORDER BY time_id DESC;';
+    $q = 'SELECT time_id,date_string,page_id,namespace,author,edit_summary,minor_edit FROM ' . table_prefix.'logs WHERE log_type=\'page\' AND action=\'edit\' AND page_id=\'' . $page_id . '\' AND namespace=\'' . $namespace . '\' AND is_draft != 1 ORDER BY time_id DESC;';
     if(!$db->sql_query($q)) $db->_die('The history data for the page "' . $paths->cpage['name'] . '" could not be selected.');
-    echo 'History of edits and actions<h3>Edits:</h3>';
+    echo $lang->get('history_page_subtitle') . '
+          <h3>' . $lang->get('history_heading_edits') . '</h3>';
     $numrows = $db->numrows();
-    if($numrows < 1) echo 'No history entries in this category.';
+    if ( $numrows < 1 )
+    {
+      echo $lang->get('history_no_entries');
+    }
     else
     {
-      
       echo '<form action="'.makeUrlNS($namespace, $page_id, 'do=diff').'" onsubmit="ajaxHistDiff(); return false;" method="get">
-            <input type="submit" value="Compare selected revisions" />
+            <input type="submit" value="' . $lang->get('history_btn_compare') . '" />
             ' . ( urlSeparator == '&' ? '<input type="hidden" name="title" value="' . htmlspecialchars($paths->nslist[$namespace] . $page_id) . '" />' : '' ) . '
             ' . ( $session->sid_super ? '<input type="hidden" name="auth"  value="' . $session->sid_super . '" />' : '') . '
             <input type="hidden" name="do" value="diff" />
@@ -573,17 +362,18 @@
             <div class="tblholder">
             <table border="0" width="100%" cellspacing="1" cellpadding="4">
             <tr>
-              <th colspan="2">Diff</th>
-              <th>Date/time</th>
-              <th>User</th>
-              <th>Edit summary</th>
-              <th>Minor</th>
-              <th colspan="3">Actions</th>
+              <th colspan="2">' . $lang->get('history_col_diff') . '</th>
+              <th>' . $lang->get('history_col_datetime') . '</th>
+              <th>' . $lang->get('history_col_user') . '</th>
+              <th>' . $lang->get('history_col_summary') . '</th>
+              <th>' . $lang->get('history_col_minor') . '</th>
+              <th colspan="3">' . $lang->get('history_col_actions') . '</th>
             </tr>'."\n"."\n";
       $cls = 'row2';
       $ticker = 0;
       
-      while($r = $db->fetchrow()) {
+      while ( $r = $db->fetchrow() )
+      {
         
         $ticker++;
         
@@ -612,12 +402,12 @@
         if($ticker < $numrows) echo '<td class="' . $cls . '" style="padding: 0;"><input ' . $s2 . 'name="diff2" type="radio" value="' . $r['time_id'] . '" id="diff2_' . $r['time_id'] . '" class="clsDiff2Radio" onclick="selectDiff2Button(this);" /></td>'."\n"; else echo '<td class="' . $cls . '"></td>';
         
         // Date and time
-        echo '<td class="' . $cls . '">' . $r['date_string'] . '</td class="' . $cls . '">'."\n";
+        echo '<td class="' . $cls . '" style="white-space: nowrap;">' . enano_date('d M Y h:i a', intval($r['time_id'])) . '</td class="' . $cls . '">'."\n";
         
         // User
         if ( $session->get_permissions('mod_misc') && is_valid_ip($r['author']) )
         {
-          $rc = ' style="cursor: pointer;" title="Click cell background for reverse DNS info" onclick="ajaxReverseDNS(this, \'' . $r['author'] . '\');"';
+          $rc = ' style="cursor: pointer;" title="' . $lang->get('history_tip_rdns') . '" onclick="ajaxReverseDNS(this, \'' . $r['author'] . '\');"';
         }
         else
         {
@@ -631,15 +421,19 @@
         echo '>' . $r['author'] . '</a></td class="' . $cls . '">'."\n";
         
         // Edit summary
+        if ( $r['edit_summary'] == 'Automatic backup created when logs were purged' )
+        {
+          $r['edit_summary'] = $lang->get('history_summary_clearlogs');
+        }
         echo '<td class="' . $cls . '">' . $r['edit_summary'] . '</td>'."\n";
         
         // Minor edit
         echo '<td class="' . $cls . '" style="text-align: center;">'. (( $r['minor_edit'] ) ? 'M' : '' ) .'</td>'."\n";
         
         // Actions!
-        echo '<td class="' . $cls . '" style="text-align: center;"><a href="'.makeUrlNS($namespace, $page_id, 'oldid=' . $r['time_id']) . '" onclick="ajaxHistView(\'' . $r['time_id'] . '\'); return false;">View revision</a></td>'."\n";
-        echo '<td class="' . $cls . '" style="text-align: center;"><a href="'.makeUrl($paths->nslist['Special'].'Contributions/' . $r['author']) . '">View user contribs</a></td>'."\n";
-        echo '<td class="' . $cls . '" style="text-align: center;"><a href="'.makeUrlNS($namespace, $page_id, 'do=rollback&amp;id=' . $r['time_id']) . '" onclick="ajaxRollback(\'' . $r['time_id'] . '\'); return false;">Revert to this revision</a></td>'."\n";
+        echo '<td class="' . $cls . '" style="text-align: center;"><a rel="nofollow" href="'.makeUrlNS($namespace, $page_id, 'oldid=' . $r['time_id']) . '" onclick="ajaxHistView(\'' . $r['time_id'] . '\'); return false;">' . $lang->get('history_action_view') . '</a></td>'."\n";
+        echo '<td class="' . $cls . '" style="text-align: center;"><a rel="nofollow" href="'.makeUrl($paths->nslist['Special'].'Contributions/' . $r['author']) . '">' . $lang->get('history_action_contrib') . '</a></td>'."\n";
+        echo '<td class="' . $cls . '" style="text-align: center;"><a rel="nofollow" href="'.makeUrlNS($namespace, $page_id, 'do=edit&amp;revid=' . $r['time_id']) . '" onclick="ajaxEditor(\'' . $r['time_id'] . '\'); return false;">' . $lang->get('history_action_restore') . '</a></td>'."\n";
         
         echo '</tr>'."\n"."\n";
         
@@ -648,18 +442,33 @@
             </div>
             <br />
             <input type="hidden" name="do" value="diff" />
-            <input type="submit" value="Compare selected revisions" />
+            <input type="submit" value="' . $lang->get('history_btn_compare') . '" />
             </form>
             <script type="text/javascript">if ( !KILL_SWITCH ) { buildDiffList(); }</script>';
     }
     $db->free_result();
-    echo '<h3>Other changes:</h3>';
+    echo '<h3>' . $lang->get('history_heading_other') . '</h3>';
     $q = 'SELECT time_id,action,date_string,page_id,namespace,author,edit_summary,minor_edit FROM ' . table_prefix.'logs WHERE log_type=\'page\' AND action!=\'edit\' AND page_id=\'' . $paths->page_id . '\' AND namespace=\'' . $paths->namespace . '\' ORDER BY time_id DESC;';
-    if(!$db->sql_query($q)) $db->_die('The history data for the page "' . $paths->cpage['name'] . '" could not be selected.');
-    if($db->numrows() < 1) echo 'No history entries in this category.';
-    else {
+    if ( !$db->sql_query($q) )
+    {
+      $db->_die('The history data for the page "' . htmlspecialchars($paths->cpage['name']) . '" could not be selected.');
+    }
+    if ( $db->numrows() < 1 )
+    {
+      echo $lang->get('history_no_entries');
+    }
+    else
+    {
       
-      echo '<div class="tblholder"><table border="0" width="100%" cellspacing="1" cellpadding="4"><tr><th>Date/time</th><th>User</th><th>Minor</th><th>Action taken</th><th>Extra info</th><th colspan="2"></th></tr>';
+      echo '<div class="tblholder">
+              <table border="0" width="100%" cellspacing="1" cellpadding="4"><tr>
+                <th>' . $lang->get('history_col_datetime') . '</th>
+                <th>' . $lang->get('history_col_user') . '</th>
+                <th>' . $lang->get('history_col_minor') . '</th>
+                <th>' . $lang->get('history_col_action_taken') . '</th>
+                <th>' . $lang->get('history_col_extra') . '</th>
+                <th colspan="2"></th>
+              </tr>';
       $cls = 'row2';
       while($r = $db->fetchrow()) {
         
@@ -669,7 +478,7 @@
         echo '<tr>';
         
         // Date and time
-        echo '<td class="' . $cls . '">' . $r['date_string'] . '</td class="' . $cls . '">';
+        echo '<td class="' . $cls . '">' . enano_date('d M Y h:i a', intval($r['time_id'])) . '</td class="' . $cls . '">';
         
         // User
         echo '<td class="' . $cls . '"><a href="'.makeUrlNS('User', sanitize_page_id($r['author'])).'" ';
@@ -683,23 +492,18 @@
         // Action taken
         echo '<td class="' . $cls . '">';
         // Some of these are sanitized at insert-time. Others follow the newer Enano policy of stripping HTML at runtime.
-        if    ($r['action']=='prot')     echo 'Protected page</td><td class="' . $cls . '">Reason: ' . $r['edit_summary'];
-        elseif($r['action']=='unprot')   echo 'Unprotected page</td><td class="' . $cls . '">Reason: ' . $r['edit_summary'];
-        elseif($r['action']=='semiprot') echo 'Semi-protected page</td><td class="' . $cls . '">Reason: ' . $r['edit_summary'];
-        elseif($r['action']=='rename')   echo 'Renamed page</td><td class="' . $cls . '">Old title: '.htmlspecialchars($r['edit_summary']);
-        elseif($r['action']=='create')   echo 'Created page</td><td class="' . $cls . '">';
-        elseif($r['action']=='delete')   echo 'Deleted page</td><td class="' . $cls . '">Reason: ' . $r['edit_summary'];
-        elseif($r['action']=='reupload') echo 'Uploaded new file version</td><td class="' . $cls . '">Reason: '.htmlspecialchars($r['edit_summary']);
+        if    ($r['action']=='prot')     echo $lang->get('history_log_protect') . '</td><td class="' . $cls . '">' . $lang->get('history_extra_reason') . ' ' . $r['edit_summary'];
+        elseif($r['action']=='unprot')   echo $lang->get('history_log_unprotect') . '</td><td class="' . $cls . '">' . $lang->get('history_extra_reason') . ' ' . $r['edit_summary'];
+        elseif($r['action']=='semiprot') echo $lang->get('history_log_semiprotect') . '</td><td class="' . $cls . '">' . $lang->get('history_extra_reason') . ' ' . $r['edit_summary'];
+        elseif($r['action']=='rename')   echo $lang->get('history_log_rename') . '</td><td class="' . $cls . '">' . $lang->get('history_extra_oldtitle') . ' '.htmlspecialchars($r['edit_summary']);
+        elseif($r['action']=='create')   echo $lang->get('history_log_create') . '</td><td class="' . $cls . '">';
+        elseif($r['action']=='delete')   echo $lang->get('history_log_delete') . '</td><td class="' . $cls . '">' . $lang->get('history_extra_reason') . ' ' . $r['edit_summary'];
+        elseif($r['action']=='reupload') echo $lang->get('history_log_uploadnew') . '</td><td class="' . $cls . '">' . $lang->get('history_extra_reason') . ' '.htmlspecialchars($r['edit_summary']);
         echo '</td>';
         
         // Actions!
-        echo '<td class="' . $cls . '" style="text-align: center;"><a href="'.makeUrl($paths->nslist['Special'].'Contributions/' . $r['author']) . '">View user contribs</a></td>';
-        echo '<td class="' . $cls . '" style="text-align: center;"><a href="'.makeUrlNS($namespace, $page_id, 'do=rollback&amp;id=' . $r['time_id']) . '" onclick="ajaxRollback(\'' . $r['time_id'] . '\'); return false;">Revert action</a></td>';
-        
-        //echo '(<a href="#" onclick="ajaxRollback(\'' . $r['time_id'] . '\'); return false;">rollback</a>) <i>' . $r['date_string'] . '</i> ' . $r['author'] . ' (<a href="'.makeUrl($paths->nslist['User'].$r['author']).'">Userpage</a>, <a href="'.makeUrl($paths->nslist['Special'].'Contributions/' . $r['author']) . '">Contrib</a>): ';
-        
-        if($r['minor_edit']) echo '<b> - minor edit</b>';
-        echo '<br />';
+        echo '<td class="' . $cls . '" style="text-align: center;"><a rel="nofollow" href="'.makeUrl($paths->nslist['Special'].'Contributions/' . $r['author']) . '">' . $lang->get('history_action_contrib') . '</a></td>';
+        echo '<td class="' . $cls . '" style="text-align: center;"><a rel="nofollow" href="'.makeUrlNS($namespace, $page_id, 'do=rollback&amp;id=' . $r['time_id']) . '" onclick="ajaxRollback(\'' . $r['time_id'] . '\'); return false;">' . $lang->get('history_action_revert') . '</a></td>';
         
         echo '</tr>';
       }
@@ -717,9 +521,13 @@
    * @return string
    */
    
-  function rollback($id)
+  public static function rollback($id)
   {
     global $db, $session, $paths, $template, $plugins; // Common objects
+    global $lang;
+    
+    // FIXME: l10n
+    
     if ( !$session->get_permissions('history_rollback') )
     {
       return('You are not authorized to perform rollbacks.');
@@ -780,32 +588,29 @@
       case "page":
         switch($rb['action'])
         {
-          case "edit":
-            if ( !$perms->get_permissions('edit_page') )
-              return "You don't have permission to edit pages, so rolling back edits can't be allowed either.";
-            $t = $db->escape($rb['page_text']);
-            $e = $db->sql_query('UPDATE ' . table_prefix.'page_text SET page_text=\'' . $t . '\',char_tag=\'' . $rb['char_tag'] . '\' WHERE page_id=\'' . $rb['page_id'] . '\' AND namespace=\'' . $rb['namespace'] . '\'');
+          // Support for rolling back edits removed in 1.1.2 - moved to page editor system
+          case "rename":
+            if ( !$perms->get_permissions('rename') )
+              return "You don't have permission to rename pages, so rolling back renames can't be allowed either.";
+            
+            $t = $rb['edit_summary'];
+            // result prediction
+            $subst = array(
+              'page_name_old' => get_page_title_ns($rb['page_id'], $rb['namespace']),
+              'page_name_new' => $t
+              );
+            
+            $e = PageUtils::rename($rb['page_id'], $rb['namespace'], $t);
+            
+            $e = ( $e == $lang->get('ajax_rename_success', $subst) );
+            
             if ( !$e )
             {
-              return("An error occurred during the rollback operation.\nMySQL said: ".mysql_error()."\n\nSQL backtrace:\n".$db->sql_backtrace());
+              return "An error occurred during the rollback operation.\nMySQL said: ".$db->get_error()."\n\nSQL backtrace:\n".$db->sql_backtrace();
             }
             else
             {
-              return 'The page "' . $paths->pages[$paths->nslist[$rb['namespace']].$rb['page_id']]['name'].'" has been rolled back to the state it was in on ' . $rb['date_string'] . '.';
-            }
-            break;
-          case "rename":
-            if ( !$perms->get_permissions('rename') )
-              return "You don't have permission to rename pages, so rolling back renames can't be allowed either.";
-            $t = $db->escape($rb['edit_summary']);
-            $e = $db->sql_query('UPDATE ' . table_prefix.'pages SET name=\'' . $t . '\' WHERE urlname=\'' . $rb['page_id'] . '\' AND namespace=\'' . $rb['namespace'] . '\'');
-            if ( !$e )
-            {
-              return "An error occurred during the rollback operation.\nMySQL said: ".mysql_error()."\n\nSQL backtrace:\n".$db->sql_backtrace();
-            }
-            else
-            {
-              return 'The page "' . $paths->pages[$paths->nslist[$rb['namespace']].$rb['page_id']]['name'].'" has been rolled back to the name it had ("' . $rb['edit_summary'] . '") before ' . $rb['date_string'] . '.';
+              return 'The page "' . $paths->pages[$paths->nslist[$rb['namespace']].$rb['page_id']]['name'].'" has been rolled back to the name it had ("' . $rb['edit_summary'] . '") before ' . enano_date('d M Y h:i a', intval($rb['time_id'])) . '.';
             }
             break;
           case "prot":
@@ -813,27 +618,27 @@
               return "You don't have permission to protect pages, so rolling back protection can't be allowed either.";
             $e = $db->sql_query('UPDATE ' . table_prefix.'pages SET protected=0 WHERE urlname=\'' . $rb['page_id'] . '\' AND namespace=\'' . $rb['namespace'] . '\'');
             if ( !$e )
-              return "An error occurred during the rollback operation.\nMySQL said: ".mysql_error()."\n\nSQL backtrace:\n".$db->sql_backtrace();
+              return "An error occurred during the rollback operation.\nMySQL said: ".$db->get_error()."\n\nSQL backtrace:\n".$db->sql_backtrace();
             else
-              return 'The page "' . $paths->pages[$paths->nslist[$rb['namespace']].$rb['page_id']]['name'].'" has been unprotected according to the log created at ' . $rb['date_string'] . '.';
+              return 'The page "' . $paths->pages[$paths->nslist[$rb['namespace']].$rb['page_id']]['name'].'" has been unprotected according to the log created at ' . enano_date('d M Y h:i a', intval($rb['time_id'])) . '.';
             break;
           case "semiprot":
             if ( !$perms->get_permissions('protect') )
               return "You don't have permission to protect pages, so rolling back protection can't be allowed either.";
             $e = $db->sql_query('UPDATE ' . table_prefix.'pages SET protected=0 WHERE urlname=\'' . $rb['page_id'] . '\' AND namespace=\'' . $rb['namespace'] . '\'');
             if ( !$e )
-              return "An error occurred during the rollback operation.\nMySQL said: ".mysql_error()."\n\nSQL backtrace:\n".$db->sql_backtrace();
+              return "An error occurred during the rollback operation.\nMySQL said: ".$db->get_error()."\n\nSQL backtrace:\n".$db->sql_backtrace();
             else
-              return 'The page "' . $paths->pages[$paths->nslist[$rb['namespace']].$rb['page_id']]['name'].'" has been unprotected according to the log created at ' . $rb['date_string'] . '.';
+              return 'The page "' . $paths->pages[$paths->nslist[$rb['namespace']].$rb['page_id']]['name'].'" has been unprotected according to the log created at ' . enano_date('d M Y h:i a', intval($rb['time_id'])) . '.';
             break;
           case "unprot":
             if ( !$perms->get_permissions('protect') )
               return "You don't have permission to protect pages, so rolling back protection can't be allowed either.";
             $e = $db->sql_query('UPDATE ' . table_prefix.'pages SET protected=1 WHERE urlname=\'' . $rb['page_id'] . '\' AND namespace=\'' . $rb['namespace'] . '\'');
             if ( !$e )
-              return "An error occurred during the rollback operation.\nMySQL said: ".mysql_error()."\n\nSQL backtrace:\n".$db->sql_backtrace();
+              return "An error occurred during the rollback operation.\nMySQL said: ".$db->get_error()."\n\nSQL backtrace:\n".$db->sql_backtrace();
             else
-              return 'The page "' . $paths->pages[$paths->nslist[$rb['namespace']].$rb['page_id']]['name'].'" has been protected according to the log created at ' . $rb['date_string'] . '.';
+              return 'The page "' . $paths->pages[$paths->nslist[$rb['namespace']].$rb['page_id']]['name'].'" has been protected according to the log created at ' . enano_date('d M Y h:i a', intval($rb['time_id'])) . '.';
             break;
           case "delete":
             if ( !$perms->get_permissions('history_rollback_extra') )
@@ -841,11 +646,11 @@
             if ( isset($paths->pages[$paths->cpage['urlname']]) )
               return 'You cannot raise a dead page that is alive.';
             $name = str_replace('_', ' ', $rb['page_id']);
-            $e = $db->sql_query('INSERT INTO ' . table_prefix.'pages(name,urlname,namespace) VALUES( \'' . $name . '\', \'' . $rb['page_id'] . '\',\'' . $rb['namespace'] . '\' )');if(!$e) return("An error occurred during the rollback operation.\nMySQL said: ".mysql_error()."\n\nSQL backtrace:\n".$db->sql_backtrace());
-            $e = $db->sql_query('SELECT page_text,char_tag FROM ' . table_prefix.'logs WHERE page_id=\'' . $rb['page_id'] . '\' AND namespace=\'' . $rb['namespace'] . '\' AND log_type=\'page\' AND action=\'edit\' ORDER BY time_id DESC;'); if(!$e) return("An error occurred during the rollback operation.\nMySQL said: ".mysql_error()."\n\nSQL backtrace:\n".$db->sql_backtrace());
+            $e = $db->sql_query('INSERT INTO ' . table_prefix.'pages(name,urlname,namespace) VALUES( \'' . $name . '\', \'' . $rb['page_id'] . '\',\'' . $rb['namespace'] . '\' )');if(!$e) return("An error occurred during the rollback operation.\nMySQL said: ".$db->get_error()."\n\nSQL backtrace:\n".$db->sql_backtrace());
+            $e = $db->sql_query('SELECT page_text,char_tag FROM ' . table_prefix.'logs WHERE page_id=\'' . $rb['page_id'] . '\' AND namespace=\'' . $rb['namespace'] . '\' AND log_type=\'page\' AND action=\'edit\' ORDER BY time_id DESC;'); if(!$e) return("An error occurred during the rollback operation.\nMySQL said: ".$db->get_error()."\n\nSQL backtrace:\n".$db->sql_backtrace());
             $r = $db->fetchrow();
-            $e = $db->sql_query('INSERT INTO ' . table_prefix.'page_text(page_id,namespace,page_text,char_tag) VALUES(\'' . $rb['page_id'] . '\',\'' . $rb['namespace'] . '\',\'' . $db->escape($r['page_text']) . '\',\'' . $r['char_tag'] . '\')'); if(!$e) return("An error occurred during the rollback operation.\nMySQL said: ".mysql_error()."\n\nSQL backtrace:\n".$db->sql_backtrace());
-            return 'The page "' . $name . '" has been undeleted according to the log created at ' . $rb['date_string'] . '.';
+            $e = $db->sql_query('INSERT INTO ' . table_prefix.'page_text(page_id,namespace,page_text,char_tag) VALUES(\'' . $rb['page_id'] . '\',\'' . $rb['namespace'] . '\',\'' . $db->escape($r['page_text']) . '\',\'' . $r['char_tag'] . '\')'); if(!$e) return("An error occurred during the rollback operation.\nMySQL said: ".$db->get_error()."\n\nSQL backtrace:\n".$db->sql_backtrace());
+            return 'The page "' . $name . '" has been undeleted according to the log created at ' . enano_date('d M Y h:i a', intval($rb['time_id'])) . '.';
             break;
           case "reupload":
             if ( !$session->get_permissions('history_rollback_extra') )
@@ -853,12 +658,12 @@
               return 'Administrative privileges are required for file rollbacks.';
             }
             $newtime = time();
-            $newdate = date('d M Y h:i a');
+            $newdate = enano_date('d M Y h:i a');
             if(!$db->sql_query('UPDATE ' . table_prefix.'logs SET time_id=' . $newtime . ',date_string=\'' . $newdate . '\' WHERE time_id=' . $id))
-              return 'Error during query: '.mysql_error();
+              return 'Error during query: '.$db->get_error();
             if(!$db->sql_query('UPDATE ' . table_prefix.'files SET time_id=' . $newtime . ' WHERE time_id=' . $id))
-              return 'Error during query: '.mysql_error();
-            return 'The file has been rolled back to the version uploaded on '.date('d M Y h:i a', (int)$id).'.';
+              return 'Error during query: '.$db->get_error();
+            return 'The file has been rolled back to the version uploaded on '.enano_date('d M Y h:i a', (int)$id).'.';
             break;
           default:
             return('Rollback of the action "' . $rb['action'] . '" is not yet supported.');
@@ -884,7 +689,7 @@
    * @return string javascript code
    */
    
-  function addcomment($page_id, $namespace, $name, $subject, $text, $captcha_code = false, $captcha_id = false)
+  public static function addcomment($page_id, $namespace, $name, $subject, $text, $captcha_code = false, $captcha_id = false)
   {
     global $db, $session, $paths, $template, $plugins; // Common objects
     $_ob = '';
@@ -903,7 +708,7 @@
     if(getConfig('approve_comments')=='1') $appr = '0'; else $appr = '1';
     $q = 'INSERT INTO ' . table_prefix.'comments(page_id,namespace,subject,comment_data,name,user_id,approved,time) VALUES(\'' . $page_id . '\',\'' . $namespace . '\',\'' . $subj . '\',\'' . $text . '\',\'' . $name . '\',' . $session->user_id . ',' . $appr . ','.time().')';
     $e = $db->sql_query($q);
-    if(!$e) die('alert(unescape(\''.rawurlencode('Error inserting comment data: '.mysql_error().'\n\nQuery:\n' . $q) . '\'))');
+    if(!$e) die('alert(unescape(\''.rawurlencode('Error inserting comment data: '.$db->get_error().'\n\nQuery:\n' . $q) . '\'))');
     else $_ob .= '<div class="info-box">Your comment has been posted.</div>';
     return PageUtils::comments($page_id, $namespace, false, Array(), $_ob);
   }
@@ -919,9 +724,10 @@
    * @access private
    */
    
-  function comments_raw($page_id, $namespace, $action = false, $flags = Array(), $_ob = '')
+  public static function comments_raw($page_id, $namespace, $action = false, $flags = Array(), $_ob = '')
   {
     global $db, $session, $paths, $template, $plugins; // Common objects
+    global $lang;
     
     $pname = $paths->nslist[$namespace] . $page_id;
     
@@ -941,7 +747,7 @@
           $q = 'DELETE FROM ' . table_prefix.'comments WHERE page_id=\'' . $page_id . '\' AND namespace=\'' . $namespace . '\' AND name=\'' . $n . '\' AND subject=\'' . $s . '\' AND comment_data=\'' . $t . '\' LIMIT 1;';
         }
         $e=$db->sql_query($q);
-        if(!$e) die('alert(unesape(\''.rawurlencode('Error during query: '.mysql_error().'\n\nQuery:\n' . $q) . '\'));');
+        if(!$e) die('alert(unesape(\''.rawurlencode('Error during query: '.$db->get_error().'\n\nQuery:\n' . $q) . '\'));');
         break;
       case "approve":
         if(isset($flags['id']))
@@ -955,15 +761,15 @@
         }
         $q = 'SELECT approved FROM ' . table_prefix.'comments WHERE page_id=\'' . $page_id . '\' AND namespace=\'' . $namespace . '\' AND ' . $where . ' LIMIT 1;';
         $e = $db->sql_query($q);
-        if(!$e) die('alert(unesape(\''.rawurlencode('Error selecting approval status: '.mysql_error().'\n\nQuery:\n' . $q) . '\'));');
+        if(!$e) die('alert(unesape(\''.rawurlencode('Error selecting approval status: '.$db->get_error().'\n\nQuery:\n' . $q) . '\'));');
         $r = $db->fetchrow();
         $db->free_result();
         $a = ( $r['approved'] ) ? '0' : '1';
         $q = 'UPDATE ' . table_prefix.'comments SET approved=' . $a . ' WHERE page_id=\'' . $page_id . '\' AND namespace=\'' . $namespace . '\' AND ' . $where . ';';
         $e=$db->sql_query($q);
-        if(!$e) die('alert(unesape(\''.rawurlencode('Error during query: '.mysql_error().'\n\nQuery:\n' . $q) . '\'));');
-        if($a=='1') $v = 'Unapprove';
-        else $v = 'Approve';
+        if(!$e) die('alert(unesape(\''.rawurlencode('Error during query: '.$db->get_error().'\n\nQuery:\n' . $q) . '\'));');
+        if($a=='1') $v = $lang->get('comment_btn_mod_unapprove');
+        else $v = $lang->get('comment_btn_mod_approve');
         echo 'document.getElementById("mdgApproveLink'.intval($_GET['id']).'").innerHTML="' . $v . '";';
         break;
       }
@@ -984,29 +790,39 @@
     if(!$e) $db->_die('The comment text data could not be selected.');
     $num_app = $db->numrows();
     $db->free_result();
-    $lq = $db->sql_query('SELECT c.comment_id,c.subject,c.name,c.comment_data,c.approved,c.time,c.user_id,u.user_level,u.signature
+    $lq = $db->sql_query('SELECT c.comment_id,c.subject,c.name,c.comment_data,c.approved,c.time,c.user_id,c.ip_address,u.user_level,u.signature,u.user_has_avatar,u.avatar_type
                   FROM ' . table_prefix.'comments AS c
                   LEFT JOIN ' . table_prefix.'users AS u
                     ON c.user_id=u.user_id
                   WHERE page_id=\'' . $page_id . '\'
                   AND namespace=\'' . $namespace . '\' ORDER BY c.time ASC;');
-    if(!$lq) _die('The comment text data could not be selected. '.mysql_error());
-    $_ob .= '<h3>Article Comments</h3>';
+    if(!$lq) _die('The comment text data could not be selected. '.$db->get_error());
+    $_ob .= '<h3>' . $lang->get('comment_heading') . '</h3>';
+    
     $n = ( $session->get_permissions('mod_comments')) ? $db->numrows() : $num_app;
-    if($n==1) $s = 'is ' . $n . ' comment'; else $s = 'are ' . $n . ' comments';
-    if($n < 1)
+    
+    $subst = array(
+        'num_comments' => $n,
+        'page_type' => $template->namespace_string
+      );
+    
+    $_ob .= '<p>';
+    $_ob .= ( $n == 0 ) ? $lang->get('comment_msg_count_zero', $subst) : ( $n == 1 ? $lang->get('comment_msg_count_one', $subst) : $lang->get('comment_msg_count_plural', $subst) );
+    
+    if ( $session->get_permissions('mod_comments') && $num_unapp > 0 )
     {
-      $_ob .= '<p>There are currently no comments on this '.strtolower($namespace).'';
-      if($namespace != 'Article') $_ob .= ' page';
-      $_ob .= '.</p>';
-    } else $_ob .= '<p>There ' . $s . ' on this article.';
-    if($session->get_permissions('mod_comments') && $num_unapp > 0) $_ob .= ' <span style="color: #D84308">' . $num_unapp . ' of those are unapproved.</span>';
-    elseif(!$session->get_permissions('mod_comments') && $num_unapp > 0) { $u = ($num_unapp == 1) ? "is $num_unapp comment" : "are $num_unapp comments"; $_ob .= ' However, there ' . $u . ' awating approval.'; }
+      $_ob .= ' <span style="color: #D84308">' . $lang->get('comment_msg_count_unapp_mod', array( 'num_unapp' => $num_unapp )) . '</span>';
+    }
+    else if ( !$session->get_permissions('mod_comments') && $num_unapp > 0 )
+    {
+      $ls = ( $num_unapp == 1 ) ? 'comment_msg_count_unapp_one' : 'comment_msg_count_unapp_plural';
+      $_ob .= ' <span>' . $lang->get($ls, array( 'num_unapp' => $num_unapp )) . '</span>';
+    }
     $_ob .= '</p>';
     $list = 'list = { ';
     // _die(htmlspecialchars($ttext));
     $i = -1;
-    while($row = $db->fetchrow($lq))
+    while ( $row = $db->fetchrow($lq) )
     {
       $i++;
       $strings = Array();
@@ -1020,34 +836,35 @@
         
         // Determine the name, and whether to link to the user page or not
         $name = '';
-        if($row['user_id'] > 0) $name .= '<a href="'.makeUrlNS('User', sanitize_page_id(' ', '_', $row['name'])).'">';
+        if($row['user_id'] > 1) $name .= '<a href="'.makeUrlNS('User', sanitize_page_id(' ', '_', $row['name'])).'">';
         $name .= $row['name'];
-        if($row['user_id'] > 0) $name .= '</a>';
+        if($row['user_id'] > 1) $name .= '</a>';
         $strings['NAME'] = $name; unset($name);
         
         // Subject
         $s = $row['subject'];
-        if(!$row['approved']) $s .= ' <span style="color: #D84308">(Unapproved)</span>';
+        if(!$row['approved']) $s .= ' <span style="color: #D84308">' . $lang->get('comment_msg_note_unapp') . '</span>';
         $strings['SUBJECT'] = $s;
         
         // Date and time
-        $strings['DATETIME'] = date('F d, Y h:i a', $row['time']);
+        $strings['DATETIME'] = enano_date('F d, Y h:i a', $row['time']);
         
         // User level
         switch($row['user_level'])
         {
           default:
           case USER_LEVEL_GUEST:
-            $l = 'Guest';
+            $l = $lang->get('user_type_guest');
             break;
           case USER_LEVEL_MEMBER:
-            $l = 'Member';
+          case USER_LEVEL_CHPREF:
+            $l = $lang->get('user_type_member');
             break;
           case USER_LEVEL_MOD:
-            $l = 'Moderator';
+            $l = $lang->get('user_type_mod');
             break;
           case USER_LEVEL_ADMIN:
-            $l = 'Administrator';
+            $l = $lang->get('user_type_admin');
             break;
         }
         $strings['USER_LEVEL'] = $l; unset($l);
@@ -1058,10 +875,10 @@
         if($session->get_permissions('edit_comments'))
         {
           // Edit link
-          $strings['EDIT_LINK'] = '<a href="'.makeUrlNS($namespace, $page_id, 'do=comments&amp;sub=editcomment&amp;id=' . $row['comment_id']) . '" id="editbtn_' . $i . '">edit</a>';
+          $strings['EDIT_LINK'] = '<a href="'.makeUrlNS($namespace, $page_id, 'do=comments&amp;sub=editcomment&amp;id=' . $row['comment_id']) . '" id="editbtn_' . $i . '">' . $lang->get('comment_btn_edit') . '</a>';
         
           // Delete link
-          $strings['DELETE_LINK'] = '<a href="'.makeUrlNS($namespace, $page_id, 'do=comments&amp;sub=deletecomment&amp;id=' . $row['comment_id']) . '">delete</a>';
+          $strings['DELETE_LINK'] = '<a href="'.makeUrlNS($namespace, $page_id, 'do=comments&amp;sub=deletecomment&amp;id=' . $row['comment_id']) . '">' . $lang->get('comment_btn_delete') . '</a>';
         }
         else
         {
@@ -1073,24 +890,34 @@
         }
         
         // Send PM link
-        $strings['SEND_PM_LINK'] = ( $session->user_logged_in && $row['user_id'] > 0 ) ? '<a href="'.makeUrlNS('Special', 'PrivateMessages/Compose/To/' . $row['name']) . '">Send private message</a><br />' : '';
+        $strings['SEND_PM_LINK'] = ( $session->user_logged_in && $row['user_id'] > 1 ) ? '<a href="'.makeUrlNS('Special', 'PrivateMessages/Compose/To/' . $row['name']) . '">' . $lang->get('comment_btn_send_privmsg') . '</a><br />' : '';
         
         // Add Buddy link
-        $strings['ADD_BUDDY_LINK'] = ( $session->user_logged_in && $row['user_id'] > 0 ) ? '<a href="'.makeUrlNS('Special', 'PrivateMessages/FriendList/Add/' . $row['name']) . '">Add to buddy list</a>' : '';
+        $strings['ADD_BUDDY_LINK'] = ( $session->user_logged_in && $row['user_id'] > 1 ) ? '<a href="'.makeUrlNS('Special', 'PrivateMessages/FriendList/Add/' . $row['name']) . '">' . $lang->get('comment_btn_add_buddy') . '</a>' : '';
         
         // Mod links
         $applink = '';
         $applink .= '<a href="'.makeUrlNS($namespace, $page_id, 'do=comments&amp;sub=admin&amp;action=approve&amp;id=' . $row['comment_id']) . '" id="mdgApproveLink' . $i . '">';
-        if($row['approved']) $applink .= 'Unapprove';
-        else $applink .= 'Approve';
+        if($row['approved']) $applink .= $lang->get('comment_btn_mod_unapprove');
+        else $applink .= $lang->get('comment_btn_mod_approve');
         $applink .= '</a>';
         $strings['MOD_APPROVE_LINK'] = $applink; unset($applink);
-        $strings['MOD_DELETE_LINK'] = '<a href="'.makeUrlNS($namespace, $page_id, 'do=comments&amp;sub=admin&amp;action=delete&amp;id=' . $row['comment_id']) . '">Delete</a>';
+        $strings['MOD_DELETE_LINK'] = '<a href="'.makeUrlNS($namespace, $page_id, 'do=comments&amp;sub=admin&amp;action=delete&amp;id=' . $row['comment_id']) . '">' . $lang->get('comment_btn_mod_delete') . '</a>';
+        $strings['MOD_IP_LINK'] = '<span style="opacity: 0.5; filter: alpha(opacity=50);">' . ( ( empty($row['ip_address']) ) ? $lang->get('comment_btn_mod_ip_missing') : $lang->get('comment_btn_mod_ip_notimplemented') ) . '</span>';
         
         // Signature
         $strings['SIGNATURE'] = '';
         if($row['signature'] != '') $strings['SIGNATURE'] = RenderMan::render($row['signature']);
         
+        // Avatar
+        if ( $row['user_has_avatar'] == 1 )
+        {
+          $bool['user_has_avatar'] = true;
+          $strings['AVATAR_ALT'] = $lang->get('usercp_avatar_image_alt', array('username' => $row['name']));
+          $strings['AVATAR_URL'] = make_avatar_url(intval($row['user_id']), $row['avatar_type']);
+          $strings['USERPAGE_LINK'] = makeUrlNS('User', $row['name']);
+        }
+        
         $bool['auth_mod'] = ($session->get_permissions('mod_comments')) ? true : false;
         $bool['can_edit'] = ( ( $session->user_logged_in && $row['name'] == $session->username && $session->get_permissions('edit_comments') ) || $session->get_permissions('mod_comments') ) ? true : false;
         $bool['signature'] = ( $strings['SIGNATURE'] == '' ) ? false : true;
@@ -1103,32 +930,31 @@
     }
     if(getConfig('comments_need_login') != '2' || $session->user_logged_in)
     {
-      if(!$session->get_permissions('post_comments'))
-      {
-        $_ob .= '<h3>Got something to say?</h3><p>Access to post comments on this page is denied.</p>';
-      }
-      else
+      if($session->get_permissions('post_comments'))
       {
-        $_ob .= '<h3>Got something to say?</h3>If you have comments or suggestions on this article, you can shout it out here.';
-        if(getConfig('approve_comments')=='1') $_ob .= '  Before your comment will be visible to the public, a moderator will have to approve it.';
-        if(getConfig('comments_need_login') == '1' && !$session->user_logged_in) $_ob .= ' Because you are not logged in, you will need to enter a visual confirmation before your comment will be posted.';
+        $_ob .= '<h3>' . $lang->get('comment_postform_title') . '</h3>';
+        $_ob .= $lang->get('comment_postform_blurb');
+        if(getConfig('approve_comments')=='1') $_ob .= ' ' . $lang->get('comment_postform_blurb_unapp');
+        if(getConfig('comments_need_login') == '1' && !$session->user_logged_in)
+        {
+          $_ob .= ' ' . $lang->get('comment_postform_blurb_captcha');
+        }
         $sn = $session->user_logged_in ? $session->username . '<input name="name" id="mdgScreenName" type="hidden" value="' . $session->username . '" />' : '<input name="name" id="mdgScreenName" type="text" size="35" />';
-        $_ob .= '  <a href="#" id="mdgCommentFormLink" style="display: none;" onclick="document.getElementById(\'mdgCommentForm\').style.display=\'block\';this.style.display=\'none\';return false;">Leave a comment...</a>
+        $_ob .= '  <a href="#" id="mdgCommentFormLink" style="display: none;" onclick="document.getElementById(\'mdgCommentForm\').style.display=\'block\';this.style.display=\'none\';return false;">' . $lang->get('comment_postform_blurb_link') . '</a>
         <div id="mdgCommentForm">
-        <h3>Comment form</h3>
         <form action="'.makeUrlNS($namespace, $page_id, 'do=comments&amp;sub=postcomment').'" method="post" style="margin-left: 1em">
         <table border="0">
-        <tr><td>Your name or screen name:</td><td>' . $sn . '</td></tr>
-        <tr><td>Comment subject:</td><td><input name="subj" id="mdgSubject" type="text" size="35" /></td></tr>';
+        <tr><td>' . $lang->get('comment_postform_field_name') . '</td><td>' . $sn . '</td></tr>
+        <tr><td>' . $lang->get('comment_postform_field_subject') . '</td><td><input name="subj" id="mdgSubject" type="text" size="35" /></td></tr>';
         if(getConfig('comments_need_login') == '1' && !$session->user_logged_in)
         {
           $session->kill_captcha();
           $captcha = $session->make_captcha();
-          $_ob .= '<tr><td>Visual confirmation:<br /><small>Please enter the code you see on the right.</small></td><td><img src="'.makeUrlNS('Special', 'Captcha/' . $captcha) . '" alt="Visual confirmation" style="cursor: pointer;" onclick="this.src = \''.makeUrlNS("Special", "Captcha/".$captcha).'/\'+Math.floor(Math.random() * 100000);" /><input name="captcha_id" id="mdgCaptchaID" type="hidden" value="' . $captcha . '" /><br />Code: <input name="captcha_input" id="mdgCaptchaInput" type="text" size="10" /><br /><small><script type="text/javascript">document.write("If you can\'t read the code, click on the image to generate a new one.");</script><noscript>If you can\'t read the code, please refresh this page to generate a new one.</noscript></small></td></tr>';
+          $_ob .= '<tr><td>' . $lang->get('comment_postform_field_captcha_title') . '<br /><small>' . $lang->get('comment_postform_field_captcha_blurb') . '</small></td><td><img src="'.makeUrlNS('Special', 'Captcha/' . $captcha) . '" alt="Visual confirmation" style="cursor: pointer;" onclick="this.src = \''.makeUrlNS("Special", "Captcha/".$captcha).'/\'+Math.floor(Math.random() * 100000);" /><input name="captcha_id" id="mdgCaptchaID" type="hidden" value="' . $captcha . '" /><br />' . $lang->get('comment_postform_field_captcha_label') . ' <input name="captcha_input" id="mdgCaptchaInput" type="text" size="10" /><br /><small><script type="text/javascript">document.write("' . $lang->get('comment_postform_field_captcha_cantread_js') . '");</script><noscript>' . $lang->get('comment_postform_field_captcha_cantread_nojs') . '</noscript></small></td></tr>';
         }
         $_ob .= '
-        <tr><td valign="top">Comment text:<br />(most HTML will be stripped)</td><td><textarea name="text" id="mdgCommentArea" rows="10" cols="40"></textarea></td></tr>
-        <tr><td colspan="2" style="text-align: center;"><input type="submit" value="Submit Comment" /></td></tr>
+        <tr><td valign="top">' . $lang->get('comment_postform_field_comment') . '</td><td><textarea name="text" id="mdgCommentArea" rows="10" cols="40"></textarea></td></tr>
+        <tr><td colspan="2" style="text-align: center;"><input type="submit" value="' . $lang->get('comment_postform_btn_submit') . '" /></td></tr>
         </table>
         </form>
         </div>';
@@ -1157,7 +983,7 @@
    * @return string
    */
    
-  function comments($page_id, $namespace, $action = false, $id = -1, $_ob = '')
+  public static function comments($page_id, $namespace, $action = false, $id = -1, $_ob = '')
   {
     global $db, $session, $paths, $template, $plugins; // Common objects
     $r = PageUtils::comments_raw($page_id, $namespace, $action, $id, $_ob);
@@ -1174,7 +1000,7 @@
    * @return string
    */
   
-  function comments_html($page_id, $namespace, $action = false, $id = -1, $_ob = '')
+  public static function comments_html($page_id, $namespace, $action = false, $id = -1, $_ob = '')
   {
     global $db, $session, $paths, $template, $plugins; // Common objects
     $r = PageUtils::comments_raw($page_id, $namespace, $action, $id, $_ob);
@@ -1193,7 +1019,7 @@
    * @return string
    */
   
-  function savecomment($page_id, $namespace, $subject, $text, $old_subject, $old_text, $id = -1)
+  public static function savecomment($page_id, $namespace, $subject, $text, $old_subject, $old_text, $id = -1)
   {
     global $db, $session, $paths, $template, $plugins; // Common objects
     if(!$session->get_permissions('edit_comments'))
@@ -1207,7 +1033,7 @@
       if(!$session->user_logged_in) _die('AJAX comment save safety check failed because you are not logged in. Sometimes this can happen because you are using a browser that does not send cookies as part of AJAX requests.<br /><br />Please log in and try again.');
       $q = 'SELECT c.name FROM ' . table_prefix.'comments c, ' . table_prefix.'users u WHERE comment_data=\'' . $old_text . '\' AND subject=\'' . $old_subject . '\' AND page_id=\'' . $page_id . '\' AND namespace=\'' . $namespace . '\' AND u.user_id=c.user_id;';
       $s = $db->sql_query($q);
-      if(!$s) _die('SQL error during safety check: '.mysql_error().'<br /><br />Attempted SQL:<br /><pre>'.htmlspecialchars($q).'</pre>');
+      if(!$s) _die('SQL error during safety check: '.$db->get_error().'<br /><br />Attempted SQL:<br /><pre>'.htmlspecialchars($q).'</pre>');
       $r = $db->fetchrow($s);
       $db->free_result();
       if($db->numrows() < 1 || $r['name'] != $session->username) _die('Safety check failed, probably due to a hacking attempt.');
@@ -1230,7 +1056,7 @@
       Performed SQL:
       ' . $sql . '
     
-      Error returned by MySQL: '.mysql_error()).'");';
+      Error returned by MySQL: '.$db->get_error()).'");';
     }
   }
   
@@ -1244,7 +1070,7 @@
    * @return string
    */
   
-  function savecomment_neater($page_id, $namespace, $subject, $text, $id)
+  public static function savecomment_neater($page_id, $namespace, $subject, $text, $id)
   {
     global $db, $session, $paths, $template, $plugins; // Common objects
     if(!is_int($id)) die('PageUtils::savecomment: $id is not an integer, aborting for safety');
@@ -1256,7 +1082,7 @@
       if(!$session->user_logged_in) _die('AJAX comment save safety check failed because you are not logged in. Sometimes this can happen because you are using a browser that does not send cookies as part of AJAX requests.<br /><br />Please log in and try again.');
       $q = 'SELECT c.name FROM ' . table_prefix.'comments c, ' . table_prefix.'users u WHERE comment_id=' . $id . ' AND page_id=\'' . $page_id . '\' AND namespace=\'' . $namespace . '\' AND u.user_id=c.user_id;';
       $s = $db->sql_query($q);
-      if(!$s) _die('SQL error during safety check: '.mysql_error().'<br /><br />Attempted SQL:<br /><pre>'.htmlspecialchars($q).'</pre>');
+      if(!$s) _die('SQL error during safety check: '.$db->get_error().'<br /><br />Attempted SQL:<br /><pre>'.htmlspecialchars($q).'</pre>');
       $r = $db->fetchrow($s);
       if($db->numrows() < 1 || $r['name'] != $session->username) _die('Safety check failed, probably due to a hacking attempt.');
       $db->free_result();
@@ -1271,7 +1097,7 @@
     Performed SQL:
     ' . $sql . '
     
-    Error returned by MySQL: '.mysql_error();
+    Error returned by MySQL: '.$db->get_error();
   }
   
   /**
@@ -1285,7 +1111,7 @@
    * @return string
    */
   
-  function deletecomment($page_id, $namespace, $name, $subj, $text, $id)
+  public static function deletecomment($page_id, $namespace, $name, $subj, $text, $id)
   {
     global $db, $session, $paths, $template, $plugins; // Common objects
     
@@ -1303,14 +1129,14 @@
       if(!$session->user_logged_in) _die('AJAX comment save safety check failed because you are not logged in. Sometimes this can happen because you are using a browser that does not send cookies as part of AJAX requests.<br /><br />Please log in and try again.');
       $q = 'SELECT c.name FROM ' . table_prefix.'comments c, ' . table_prefix.'users u WHERE comment_data=\'' . $t . '\' AND subject=\'' . $s . '\' AND page_id=\'' . $page_id . '\' AND namespace=\'' . $namespace . '\' AND u.user_id=c.user_id;';
       $s = $db->sql_query($q);
-      if(!$s) _die('SQL error during safety check: '.mysql_error().'<br /><br />Attempted SQL:<br /><pre>'.htmlspecialchars($q).'</pre>');
+      if(!$s) _die('SQL error during safety check: '.$db->get_error().'<br /><br />Attempted SQL:<br /><pre>'.htmlspecialchars($q).'</pre>');
       $r = $db->fetchrow($s);
       if($db->numrows() < 1 || $r['name'] != $session->username) _die('Safety check failed, probably due to a hacking attempt.');
       $db->free_result();
     }
     $q = 'DELETE FROM ' . table_prefix.'comments WHERE page_id=\'' . $page_id . '\' AND namespace=\'' . $namespace . '\' AND name=\'' . $n . '\' AND subject=\'' . $s . '\' AND comment_data=\'' . $t . '\' LIMIT 1;';
     $e=$db->sql_query($q);
-    if(!$e) return('alert(unesape(\''.rawurlencode('Error during query: '.mysql_error().'\n\nQuery:\n' . $q) . '\'));');
+    if(!$e) return('alert(unesape(\''.rawurlencode('Error during query: '.$db->get_error().'\n\nQuery:\n' . $q) . '\'));');
     return('good');
   }
   
@@ -1322,7 +1148,7 @@
    * @return string
    */
   
-  function deletecomment_neater($page_id, $namespace, $id)
+  public static function deletecomment_neater($page_id, $namespace, $id)
   {
     global $db, $session, $paths, $template, $plugins; // Common objects
     
@@ -1337,14 +1163,14 @@
       if(!$session->user_logged_in) _die('AJAX comment save safety check failed because you are not logged in. Sometimes this can happen because you are using a browser that does not send cookies as part of AJAX requests.<br /><br />Please log in and try again.');
       $q = 'SELECT c.name FROM ' . table_prefix.'comments c, ' . table_prefix.'users u WHERE comment_id=' . $id . ' AND page_id=\'' . $page_id . '\' AND namespace=\'' . $namespace . '\' AND u.user_id=c.user_id;';
       $s = $db->sql_query($q);
-      if(!$s) _die('SQL error during safety check: '.mysql_error().'<br /><br />Attempted SQL:<br /><pre>'.htmlspecialchars($q).'</pre>');
+      if(!$s) _die('SQL error during safety check: '.$db->get_error().'<br /><br />Attempted SQL:<br /><pre>'.htmlspecialchars($q).'</pre>');
       $r = $db->fetchrow($s);
       if($db->numrows() < 1 || $r['name'] != $session->username) _die('Safety check failed, probably due to a hacking attempt.');
       $db->free_result();
     }
     $q = 'DELETE FROM ' . table_prefix.'comments WHERE page_id=\'' . $page_id . '\' AND namespace=\'' . $namespace . '\' AND comment_id=' . $id . ' LIMIT 1;';
     $e=$db->sql_query($q);
-    if(!$e) return('alert(unesape(\''.rawurlencode('Error during query: '.mysql_error().'\n\nQuery:\n' . $q) . '\'));');
+    if(!$e) return('alert(unesape(\''.rawurlencode('Error during query: '.$db->get_error().'\n\nQuery:\n' . $q) . '\'));');
     return('good');
   }
   
@@ -1356,9 +1182,10 @@
    * @return string error string or success message
    */
    
-  function rename($page_id, $namespace, $name)
+  public static function rename($page_id, $namespace, $name)
   {
     global $db, $session, $paths, $template, $plugins; // Common objects
+    global $lang;
     
     $pname = $paths->nslist[$namespace] . $page_id;
     
@@ -1367,11 +1194,11 @@
     
     if( empty($name)) 
     {
-      die('Name is too short');
+      return($lang->get('ajax_rename_too_short'));
     }
     if( ( $session->get_permissions('rename') && ( ( $prot && $session->get_permissions('even_when_protected') ) || !$prot ) ) && ( $paths->namespace != 'Special' && $paths->namespace != 'Admin' ))
     {
-      $e = $db->sql_query('INSERT INTO ' . table_prefix.'logs(time_id,date_string,log_type,action,page_id,namespace,author,edit_summary) VALUES('.time().', \''.date('d M Y h:i a').'\', \'page\', \'rename\', \'' . $db->escape($paths->page_id) . '\', \'' . $paths->namespace . '\', \'' . $db->escape($session->username) . '\', \'' . $db->escape($paths->cpage['name']) . '\')');
+      $e = $db->sql_query('INSERT INTO ' . table_prefix.'logs(time_id,date_string,log_type,action,page_id,namespace,author,edit_summary) VALUES('.time().', \''.enano_date('d M Y h:i a').'\', \'page\', \'rename\', \'' . $db->escape($paths->page_id) . '\', \'' . $paths->namespace . '\', \'' . $db->escape($session->username) . '\', \'' . $db->escape($paths->cpage['name']) . '\')');
       if ( !$e )
       {
         $db->_die('The page title could not be updated.');
@@ -1383,12 +1210,16 @@
       }
       else
       {
-        return('The page "' . $paths->pages[$pname]['name'] . '" has been renamed to "' . $name . '". You are encouraged to leave a comment explaining your action.' . "\n\n" . 'You will see the change take effect the next time you reload this page.');
+        $subst = array(
+          'page_name_old' => $paths->pages[$pname]['name'],
+          'page_name_new' => $name
+          );
+        return $lang->get('ajax_rename_success', $subst);
       }
     }
     else
     {
-      return('Access is denied.');
+      return($lang->get('etc_access_denied'));
     }
   }
   
@@ -1399,10 +1230,19 @@
    * @return string error/success string
    */
    
-  function flushlogs($page_id, $namespace)
+  public static function flushlogs($page_id, $namespace)
   {
     global $db, $session, $paths, $template, $plugins; // Common objects
-    if(!$session->get_permissions('clear_logs')) die('Administrative privileges are required to flush logs, you loser.');
+    global $lang;
+    if ( !is_object($lang) && defined('IN_ENANO_INSTALL') )
+    {
+      // This is a special exception for the Enano installer, which doesn't init languages yet.
+      $lang = new Language('eng');
+    }
+    if(!$session->get_permissions('clear_logs') && !defined('IN_ENANO_INSTALL'))
+    {
+      return $lang->get('etc_access_denied');
+    }
     $e = $db->sql_query('DELETE FROM ' . table_prefix.'logs WHERE page_id=\'' . $db->escape($page_id) . '\' AND namespace=\'' . $db->escape($namespace) . '\';');
     if(!$e) $db->_die('The log entries could not be deleted.');
     
@@ -1415,10 +1255,10 @@
       $row = $db->fetchrow();
       $db->free_result();
       $minor_edit = ( ENANO_DBLAYER == 'MYSQL' ) ? 'false' : '0';
-      $q='INSERT INTO ' . table_prefix.'logs(log_type,action,time_id,date_string,page_id,namespace,page_text,char_tag,author,edit_summary,minor_edit) VALUES(\'page\', \'edit\', '.time().', \''.date('d M Y h:i a').'\', \'' . $page_id . '\', \'' . $namespace . '\', \'' . $db->escape($row['page_text']) . '\', \'' . $row['char_tag'] . '\', \'' . $session->username . '\', \''."Automatic backup created when logs were purged".'\', '.$minor_edit.');';
+      $q='INSERT INTO ' . table_prefix.'logs(log_type,action,time_id,date_string,page_id,namespace,page_text,char_tag,author,edit_summary,minor_edit) VALUES(\'page\', \'edit\', '.time().', \''.enano_date('d M Y h:i a').'\', \'' . $page_id . '\', \'' . $namespace . '\', \'' . $db->escape($row['page_text']) . '\', \'' . $row['char_tag'] . '\', \'' . $session->username . '\', \''."Automatic backup created when logs were purged".'\', '.$minor_edit.');';
       if(!$db->sql_query($q)) $db->_die('The history (log) entry could not be inserted into the logs table.');
     }
-    return('The logs for this page have been cleared. A backup of this page has been added to the logs table so that this page can be restored in case of vandalism or spam later.');
+    return $lang->get('ajax_clearlogs_success');
   }
   
   /**
@@ -1429,17 +1269,18 @@
    * @return string
    */
    
-  function deletepage($page_id, $namespace, $reason)
+  public static function deletepage($page_id, $namespace, $reason)
   {
     global $db, $session, $paths, $template, $plugins; // Common objects
+    global $lang;
     $perms = $session->fetch_page_acl($page_id, $namespace);
     $x = trim($reason);
     if ( empty($x) )
     {
-      return 'Invalid reason for deletion passed';
+      return $lang->get('ajax_delete_need_reason');
     }
     if(!$perms->get_permissions('delete_page')) return('Administrative privileges are required to delete pages, you loser.');
-    $e = $db->sql_query('INSERT INTO ' . table_prefix.'logs(time_id,date_string,log_type,action,page_id,namespace,author,edit_summary) VALUES('.time().', \''.date('d M Y h:i a').'\', \'page\', \'delete\', \'' . $page_id . '\', \'' . $namespace . '\', \'' . $session->username . '\', \'' . $db->escape(htmlspecialchars($reason)) . '\')');
+    $e = $db->sql_query('INSERT INTO ' . table_prefix.'logs(time_id,date_string,log_type,action,page_id,namespace,author,edit_summary) VALUES('.time().', \''.enano_date('d M Y h:i a').'\', \'page\', \'delete\', \'' . $page_id . '\', \'' . $namespace . '\', \'' . $session->username . '\', \'' . $db->escape(htmlspecialchars($reason)) . '\')');
     if(!$e) $db->_die('The page log entry could not be inserted.');
     $e = $db->sql_query('DELETE FROM ' . table_prefix.'categories WHERE page_id=\'' . $page_id . '\' AND namespace=\'' . $namespace . '\'');
     if(!$e) $db->_die('The page categorization entries could not be deleted.');
@@ -1451,7 +1292,7 @@
     if(!$e) $db->_die('The page entry could not be deleted.');
     $e = $db->sql_query('DELETE FROM ' . table_prefix.'files WHERE page_id=\'' . $page_id . '\'');
     if(!$e) $db->_die('The file entry could not be deleted.');
-    return('This page has been deleted. Note that there is still a log of edits and actions in the database, and anyone with admin rights can raise this page from the dead unless the log is cleared. If the deleted file is an image, there may still be cached thumbnails of it in the cache/ directory, which is inaccessible to users.');
+    return $lang->get('ajax_delete_success');
   }
   
   /**
@@ -1461,12 +1302,13 @@
    * @return string
    */
    
-  function delvote($page_id, $namespace)
+  public static function delvote($page_id, $namespace)
   {
     global $db, $session, $paths, $template, $plugins; // Common objects
+    global $lang;
     if ( !$session->get_permissions('vote_delete') )
     {
-      return 'Access denied';
+      return $lang->get('etc_access_denied');
     }
     
     if ( $namespace == 'Admin' || $namespace == 'Special' || $namespace == 'System' )
@@ -1505,7 +1347,7 @@
     
     if ( in_array($session->username, $ips['u']) || in_array($_SERVER['REMOTE_ADDR'], $ips['ip']) )
     {
-      return 'It appears that you have already voted to have this page deleted.';
+      return $lang->get('ajax_delvote_already_voted');
     }
     
     $ips['u'][] = $session->username;
@@ -1517,7 +1359,7 @@
     $q = 'UPDATE ' . table_prefix.'pages SET delvotes=' . $cv . ',delvote_ips=\'' . $ips . '\' WHERE urlname=\'' . $page_id . '\' AND namespace=\'' . $namespace . '\'';
     $w = $db->sql_query($q);
     
-    return 'Your vote to have this page deleted has been cast.'."\nYou are encouraged to leave a comment explaining the reason for your vote.";
+    return $lang->get('ajax_delvote_success');
   }
   
   /**
@@ -1527,14 +1369,21 @@
    * @return string
    */
   
-  function resetdelvotes($page_id, $namespace)
+  public static function resetdelvotes($page_id, $namespace)
   {
     global $db, $session, $paths, $template, $plugins; // Common objects
-    if(!$session->get_permissions('vote_reset')) die('You need moderator rights in order to do this, stinkin\' hacker.');
+    global $lang;
+    if(!$session->get_permissions('vote_reset'))
+    {
+      return $lang->get('etc_access_denied');
+    }
     $q = 'UPDATE ' . table_prefix.'pages SET delvotes=0,delvote_ips=\'' . $db->escape(serialize(array('ip'=>array(),'u'=>array()))) . '\' WHERE urlname=\'' . $page_id . '\' AND namespace=\'' . $namespace . '\'';
     $e = $db->sql_query($q);
     if(!$e) $db->_die('The number of delete votes was not reset.');
-    else return('The number of votes for having this page deleted has been reset to zero.');
+    else
+    {
+      return $lang->get('ajax_delvote_reset_success');
+    }
   }
   
   /**
@@ -1543,12 +1392,11 @@
    * @return string JSON string with an array containing a list of themes
    */
    
-  function getstyles()
+  public static function getstyles()
   {
-    $json = new Services_JSON(SERVICES_JSON_LOOSE_TYPE);
     
     if ( !preg_match('/^([a-z0-9_-]+)$/', $_GET['id']) )
-      return $json->encode(false);
+      return enano_json_encode(false);
     
     $dir = './themes/' . $_GET['id'] . '/css/';
     $list = Array();
@@ -1568,10 +1416,10 @@
     }
     else
     {
-      return($json->encode(Array('mode' => 'error', 'error' => $dir.' is not a dir')));
+      return(enano_json_encode(Array('mode' => 'error', 'error' => $dir.' is not a dir')));
     }
     
-    return $json->encode($list);
+    return enano_json_encode($list);
   }
   
   /**
@@ -1581,7 +1429,7 @@
    * @return string Javascript code
    */
    
-  function catedit($page_id, $namespace)
+  public static function catedit($page_id, $namespace)
   {
     $d = PageUtils::catedit_raw($page_id, $namespace);
     return $d[0] . ' /* BEGIN CONTENT */ document.getElementById("ajaxEditContainer").innerHTML = unescape(\''.rawurlencode($d[1]).'\');';
@@ -1592,13 +1440,15 @@
    * @access private
    */
    
-  function catedit_raw($page_id, $namespace)
+  public static function catedit_raw($page_id, $namespace)
   {
     global $db, $session, $paths, $template, $plugins; // Common objects
+    global $lang;
+    
     ob_start();
     $_ob = '';
     $e = $db->sql_query('SELECT category_id FROM ' . table_prefix.'categories WHERE page_id=\'' . $paths->page_id . '\' AND namespace=\'' . $paths->namespace . '\'');
-    if(!$e) jsdie('Error selecting category information for current page: '.mysql_error());
+    if(!$e) jsdie('Error selecting category information for current page: '.$db->get_error());
     $cat_current = Array();
     while($r = $db->fetchrow())
     {
@@ -1632,11 +1482,11 @@
     }
     
     echo 'catlist = new Array();'; // Initialize the client-side category list
-    $_ob .= '<h3>Select which categories this page should be included in.</h3>
+    $_ob .= '<h3>' . $lang->get('catedit_title') . '</h3>
              <form name="mdgCatForm" action="'.makeUrlNS($namespace, $page_id, 'do=catedit').'" method="post">';
     if ( sizeof($cat_info) < 1 )
     {
-      $_ob .= '<p>There are no categories on this site yet.</p>';
+      $_ob .= '<p>' . $lang->get('catedit_no_categories') . '</p>';
     }
     for ( $i = 0; $i < sizeof($cat_info) / 2; $i++ )
     {
@@ -1657,7 +1507,7 @@
     
     $disabled = ( sizeof($cat_info) < 1 ) ? 'disabled="disabled"' : '';
       
-    $_ob .= '<div style="border-top: 1px solid #CCC; padding-top: 5px; margin-top: 10px;"><input name="__enanoSaveButton" ' . $disabled . ' style="font-weight: bold;" type="submit" onclick="ajaxCatSave(); return false;" value="Save changes" /> <input name="__enanoCatCancel" type="submit" onclick="ajaxReset(); return false;" value="Cancel" /></div></form>';
+    $_ob .= '<div style="border-top: 1px solid #CCC; padding-top: 5px; margin-top: 10px;"><input name="__enanoSaveButton" ' . $disabled . ' style="font-weight: bold;" type="submit" onclick="ajaxCatSave(); return false;" value="' . $lang->get('etc_save_changes') . '" /> <input name="__enanoCatCancel" type="submit" onclick="ajaxReset(); return false;" value="' . $lang->get('etc_cancel') . '" /></div></form>';
     
     $cont = ob_get_contents();
     ob_end_clean();
@@ -1673,7 +1523,7 @@
    * @return string "GOOD" on success, error string on failure
    */
   
-  function catsave($page_id, $namespace, $which_cats)
+  public static function catsave($page_id, $namespace, $which_cats)
   {
     global $db, $session, $paths, $template, $plugins; // Common objects
     if(!$session->get_permissions('edit_cat')) return('Insufficient privileges to change category information');
@@ -1745,7 +1595,7 @@
    * @return string "GOOD" on success, error string on failure
    */
   
-  function setwikimode($page_id, $namespace, $level)
+  public static function setwikimode($page_id, $namespace, $level)
   {
     global $db, $session, $paths, $template, $plugins; // Common objects
     if(!$session->get_permissions('set_wiki_mode')) return('Insufficient access rights');
@@ -1756,7 +1606,7 @@
     $q = $db->sql_query('UPDATE ' . table_prefix.'pages SET wiki_mode=' . $level . ' WHERE urlname=\'' . $page_id . '\' AND namespace=\'' . $namespace . '\';');
     if ( !$q )
     {
-      return('Error during update query: '.mysql_error()."\n\nSQL Backtrace:\n".$db->sql_backtrace());
+      return('Error during update query: '.$db->get_error()."\n\nSQL Backtrace:\n".$db->sql_backtrace());
     }
     return('GOOD');
   }
@@ -1769,16 +1619,17 @@
    * @return string
    */
   
-  function setpass($page_id, $namespace, $pass)
+  public static function setpass($page_id, $namespace, $pass)
   {
     global $db, $session, $paths, $template, $plugins; // Common objects
+    global $lang;
     // Determine permissions
     if($paths->pages[$paths->nslist[$namespace].$page_id]['password'] != '')
       $a = $session->get_permissions('password_reset');
     else
       $a = $session->get_permissions('password_set');
     if(!$a)
-      return 'Access is denied';
+      return $lang->get('etc_access_denied');
     if(!isset($pass)) return('Password was not set on URL');
     $p = $pass;
     if ( !preg_match('#([0-9a-f]){40,40}#', $p) )
@@ -1791,14 +1642,17 @@
     $e = $db->sql_query('UPDATE ' . table_prefix.'pages SET password=\'' . $p . '\' WHERE urlname=\'' . $page_id . '\' AND namespace=\'' . $namespace . '\';');
     if ( !$e )
     {
-      die('PageUtils::setpass(): Error during update query: '.mysql_error()."\n\nSQL Backtrace:\n".$db->sql_backtrace());
+      die('PageUtils::setpass(): Error during update query: '.$db->get_error()."\n\nSQL Backtrace:\n".$db->sql_backtrace());
     }
     // Is the new password blank?
     if ( $p == '' )
     {
-      return('The password for this page has been disabled.');
+      return $lang->get('ajax_password_disable_success');
     }
-    else return('The password for this page has been set.');
+    else
+    {
+      return $lang->get('ajax_password_success');
+    }
   }
   
   /**
@@ -1807,9 +1661,10 @@
    * @return string
    */
    
-  function genPreview($text)
+  public static function genPreview($text)
   {
-    $ret = '<div class="info-box"><b>Reminder:</b> This is only a preview - your changes to this page have not yet been saved.</div><div style="background-color: #F8F8F8; padding: 10px; border: 1px dashed #406080; max-height: 250px; overflow: auto; margin: 1em 0 1em 1em;">';
+    global $lang;
+    $ret = '<div class="info-box">' . $lang->get('editor_preview_blurb') . '</div><div style="background-color: #F8F8F8; padding: 10px; border: 1px dashed #406080; max-height: 250px; overflow: auto; margin: 10px 0;">';
     $text = RenderMan::render(RenderMan::preprocess_text($text, false, false));
     ob_start();
     eval('?>' . $text);
@@ -1827,7 +1682,7 @@
    * @return string
    */
    
-  function scrollBox($text, $height = 250)
+  public static function scrollBox($text, $height = 250)
   {
     return '<div style="background-color: #F8F8F8; padding: 10px; border: 1px dashed #406080; max-height: '.(string)intval($height).'px; overflow: auto; margin: 1em 0 1em 1em;">' . $text . '</div>';
   }
@@ -1841,17 +1696,18 @@
    * @return string XHTML-formatted diff
    */
    
-  function pagediff($page_id, $namespace, $id1, $id2)
+  public static function pagediff($page_id, $namespace, $id1, $id2)
   {
     global $db, $session, $paths, $template, $plugins; // Common objects
+    global $lang;
     if(!$session->get_permissions('history_view'))
-      return 'Access denied';
+      return $lang->get('etc_access_denied');
     if(!preg_match('#^([0-9]+)$#', (string)$id1) ||
        !preg_match('#^([0-9]+)$#', (string)$id2  )) return 'SQL injection attempt';
     // OK we made it through security
     // Safest way to make sure we don't end up with the revisions in wrong columns is to make 2 queries
-    if(!$q1 = $db->sql_query('SELECT page_text,char_tag,author,edit_summary FROM ' . table_prefix.'logs WHERE time_id=' . $id1 . ' AND log_type=\'page\' AND action=\'edit\' AND page_id=\'' . $page_id . '\' AND namespace=\'' . $namespace . '\';')) return 'MySQL error: '.mysql_error();
-    if(!$q2 = $db->sql_query('SELECT page_text,char_tag,author,edit_summary FROM ' . table_prefix.'logs WHERE time_id=' . $id2 . ' AND log_type=\'page\' AND action=\'edit\' AND page_id=\'' . $page_id . '\' AND namespace=\'' . $namespace . '\';')) return 'MySQL error: '.mysql_error();
+    if(!$q1 = $db->sql_query('SELECT page_text,char_tag,author,edit_summary FROM ' . table_prefix.'logs WHERE time_id=' . $id1 . ' AND log_type=\'page\' AND action=\'edit\' AND page_id=\'' . $page_id . '\' AND namespace=\'' . $namespace . '\';')) return 'MySQL error: '.$db->get_error();
+    if(!$q2 = $db->sql_query('SELECT page_text,char_tag,author,edit_summary FROM ' . table_prefix.'logs WHERE time_id=' . $id2 . ' AND log_type=\'page\' AND action=\'edit\' AND page_id=\'' . $page_id . '\' AND namespace=\'' . $namespace . '\';')) return 'MySQL error: '.$db->get_error();
     $row1 = $db->fetchrow($q1);
     $db->free_result($q1);
     $row2 = $db->fetchrow($q2);
@@ -1859,10 +1715,10 @@
     if(sizeof($row1) < 1 || sizeof($row2) < 2) return 'Couldn\'t find any rows that matched the query. The time ID probably doesn\'t exist in the logs table.';
     $text1 = $row1['page_text'];
     $text2 = $row2['page_text'];
-    $time1 = date('F d, Y h:i a', $id1);
-    $time2 = date('F d, Y h:i a', $id2);
+    $time1 = enano_date('F d, Y h:i a', $id1);
+    $time2 = enano_date('F d, Y h:i a', $id2);
     $_ob = "
-    <p>Comparing revisions: {$time1} &rarr; {$time2}</p>
+    <p>" . $lang->get('history_lbl_comparingrevisions') . " {$time1} &rarr; {$time2}</p>
     ";
     // Free some memory
     unset($row1, $row2, $q1, $q2);
@@ -1873,20 +1729,20 @@
   
   /**
    * Gets ACL information about the selected page for target type X and target ID Y.
-   * @param string $page_id The page ID
-   * @param string $namespace The namespace
    * @param array $parms What to select. This is an array purely for JSON compatibility. It should be an associative array with keys target_type and target_id.
    * @return array
    */
    
-  function acl_editor($parms = Array())
+  public static function acl_editor($parms = Array())
   {
     global $db, $session, $paths, $template, $plugins; // Common objects
+    global $lang;
+    
     if(!$session->get_permissions('edit_acl') && $session->user_level < USER_LEVEL_ADMIN)
     {
       return Array(
         'mode' => 'error',
-        'error' => 'You are not authorized to view or edit access control lists.'
+        'error' => $lang->get('acl_err_access_denied')
         );
     }
     $parms['page_id'] = ( isset($parms['page_id']) ) ? $parms['page_id'] : false;
@@ -1904,7 +1760,7 @@
     {
       return Array(
         'mode' => 'error',
-        'error' => 'It seems that (a) the file acledit.tpl is missing from these theme, and (b) the JSON response is working.',
+        'error' => $lang->get('acl_err_missing_template'),
       );
     }
     $return['template'] = $template->extract_vars('acledit.tpl');
@@ -1957,19 +1813,19 @@
                     AND u.username=\'' . $db->escape($parms['target_id']) . '\'
                     ' . $page_where_clause . ';');
               if(!$q)
-                return(Array('mode'=>'error','error'=>mysql_error()));
+                return(Array('mode'=>'error','error'=>$db->get_error()));
               if($db->numrows() < 1)
               {
                 $return['type'] = 'new';
                 $q = $db->sql_query('SELECT user_id FROM ' . table_prefix.'users WHERE username=\'' . $db->escape($parms['target_id']) . '\';');
                 if(!$q)
-                  return(Array('mode'=>'error','error'=>mysql_error()));
+                  return(Array('mode'=>'error','error'=>$db->get_error()));
                 if($db->numrows() < 1)
-                  return Array('mode'=>'error','error'=>'The username you entered was not found.');
+                  return Array('mode'=>'error','error'=>$lang->get('acl_err_user_not_found'));
                 $row = $db->fetchrow();
                 $return['target_name'] = $return['target_id'];
                 $return['target_id'] = intval($row['user_id']);
-                $return['current_perms'] = $session->acl_types;
+                $return['current_perms'] = array();
               }
               else
               {
@@ -1977,7 +1833,7 @@
                 $row = $db->fetchrow();
                 $return['target_name'] = $return['target_id'];
                 $return['target_id'] = intval($row['user_id']);
-                $return['current_perms'] = $session->acl_merge($perms_obj->acl_types, $session->string_to_perm($row['rules']));
+                $return['current_perms'] = $session->string_to_perm($row['rules']);
               }
               $db->free_result();
               // Eliminate types that don't apply to this namespace
@@ -2004,19 +1860,19 @@
                     AND g.group_id=\''.intval($parms['target_id']).'\'
                     ' . $page_where_clause . ';');
               if(!$q)
-                return(Array('mode'=>'error','error'=>mysql_error()));
+                return(Array('mode'=>'error','error'=>$db->get_error()));
               if($db->numrows() < 1)
               {
                 $return['type'] = 'new';
                 $q = $db->sql_query('SELECT group_id,group_name FROM ' . table_prefix.'groups WHERE group_id=\''.intval($parms['target_id']).'\';');
                 if(!$q)
-                  return(Array('mode'=>'error','error'=>mysql_error()));
+                  return(Array('mode'=>'error','error'=>$db->get_error()));
                 if($db->numrows() < 1)
-                  return Array('mode'=>'error','error'=>'The group ID you submitted is not valid.');
+                  return Array('mode'=>'error','error'=>$lang->get('acl_err_bad_group_id'));
                 $row = $db->fetchrow();
                 $return['target_name'] = $row['group_name'];
                 $return['target_id'] = intval($row['group_id']);
-                $return['current_perms'] = $session->acl_types;
+                $return['current_perms'] = array();
               }
               else
               {
@@ -2024,7 +1880,7 @@
                 $row = $db->fetchrow();
                 $return['target_name'] = $row['group_name'];
                 $return['target_id'] = intval($row['group_id']);
-                $return['current_perms'] = $session->acl_merge($session->acl_types, $session->string_to_perm($row['rules']));
+                $return['current_perms'] = $session->string_to_perm($row['rules']);
               }
               $db->free_result();
               // Eliminate types that don't apply to this namespace
@@ -2054,25 +1910,30 @@
         case 'save_edit':
           if ( defined('ENANO_DEMO_MODE') )
           {
-            return Array('mode'=>'error','error'=>'Editing access control lists is disabled in the administration demo.');
+            return Array('mode'=>'error','error'=>$lang->get('acl_err_demo'));
           }
           $q = $db->sql_query('DELETE FROM ' . table_prefix.'acl WHERE target_type='.intval($parms['target_type']).' AND target_id='.intval($parms['target_id']).'
             ' . $page_where_clause_lite . ';');
           if(!$q)
-            return Array('mode'=>'error','error'=>mysql_error());
-          $rules = $session->perm_to_string($parms['perms']);
-          if ( sizeof ( $rules ) < 1 )
+            return Array('mode'=>'error','error'=>$db->get_error());
+          if ( sizeof ( $parms['perms'] ) < 1 )
           {
-            return array(
-                'mode' => 'error', 
-                'error' => 'Supplied rule list has a length of zero'
-              );
+            // As of 1.1.x, this returns success because the rule length is zero if the user selected "inherit" in all columns
+            return Array(
+              'mode' => 'success',
+              'target_type' => $parms['target_type'],
+              'target_id' => $parms['target_id'],
+              'target_name' => $parms['target_name'],
+              'page_id' => $page_id,
+              'namespace' => $namespace,
+            );
           }
+          $rules = $session->perm_to_string($parms['perms']);
           $q = ($page_id && $namespace) ? 'INSERT INTO ' . table_prefix.'acl ( target_type, target_id, page_id, namespace, rules )
                                              VALUES( '.intval($parms['target_type']).', '.intval($parms['target_id']).', \'' . $db->escape($page_id) . '\', \'' . $db->escape($namespace) . '\', \'' . $db->escape($rules) . '\' )' :
                                           'INSERT INTO ' . table_prefix.'acl ( target_type, target_id, rules )
                                              VALUES( '.intval($parms['target_type']).', '.intval($parms['target_id']).', \'' . $db->escape($rules) . '\' )';
-          if(!$db->sql_query($q)) return Array('mode'=>'error','error'=>mysql_error());
+          if(!$db->sql_query($q)) return Array('mode'=>'error','error'=>$db->get_error());
           return Array(
               'mode' => 'success',
               'target_type' => $parms['target_type'],
@@ -2085,12 +1946,12 @@
         case 'delete':
           if ( defined('ENANO_DEMO_MODE') )
           {
-            return Array('mode'=>'error','error'=>'Editing access control lists is disabled in the administration demo.');
+            return Array('mode'=>'error','error'=>$lang->get('acl_err_demo'));
           }
           $q = $db->sql_query('DELETE FROM ' . table_prefix.'acl WHERE target_type='.intval($parms['target_type']).' AND target_id='.intval($parms['target_id']).'
             ' . $page_where_clause_lite . ';');
           if(!$q)
-            return Array('mode'=>'error','error'=>mysql_error());
+            return Array('mode'=>'error','error'=>$db->get_error());
           return Array(
               'mode' => 'delete',
               'target_type' => $parms['target_type'],
@@ -2114,13 +1975,12 @@
    * @return string
    */
    
-  function acl_json($parms = '{ }')
+  public static function acl_json($parms = '{ }')
   {
     global $db, $session, $paths, $template, $plugins; // Common objects
-    $json = new Services_JSON(SERVICES_JSON_LOOSE_TYPE);
-    $parms = $json->decode($parms);
+    $parms = enano_json_decode($parms);
     $ret = PageUtils::acl_editor($parms);
-    $ret = $json->encode($ret);
+    $ret = enano_json_encode($ret);
     return $ret;
   }
   
@@ -2129,9 +1989,10 @@
    * @param array The request data, if any, this should be in the format required by PageUtils::acl_editor()
    */
    
-  function aclmanager($parms)
+  public static function aclmanager($parms)
   {
     global $db, $session, $paths, $template, $plugins; // Common objects
+    global $lang;
     ob_start();
     // Convenience
     $formstart = '<form 
@@ -2152,20 +2013,21 @@
         echo '<pre>' . htmlspecialchars($response['text']) . '</pre>';
         break;
       case 'stage1':
-        echo '<h3>Manage page access</h3>
-              <p>Please select who should be affected by this access rule.</p>';
+        echo '<h3>' . $lang->get('acl_lbl_welcome_title') . '</h3>
+              <p>' . $lang->get('acl_lbl_welcome_body') . '</p>';
         echo $formstart;
-        echo '<p><label><input type="radio" name="data[target_type]" value="' . ACL_TYPE_GROUP . '" checked="checked" /> A usergroup</label></p>
+        echo '<p><label><input type="radio" name="data[target_type]" value="' . ACL_TYPE_GROUP . '" checked="checked" /> ' . $lang->get('acl_radio_usergroup') . '</label></p>
               <p><select name="data[target_id_grp]">';
         foreach ( $response['groups'] as $group )
         {
           echo '<option value="' . $group['id'] . '">' . $group['name'] . '</option>';
         }
+        
         // page group selector
         $groupsel = '';
         if ( count($response['page_groups']) > 0 )
         {
-          $groupsel = '<p><label><input type="radio" name="data[scope]" value="page_group" /> A group of pages</label></p>
+          $groupsel = '<p><label><input type="radio" name="data[scope]" value="page_group" /> ' . $lang->get('acl_radio_scope_pagegroup') . '</label></p>
                        <p><select name="data[pg_id]">';
           foreach ( $response['page_groups'] as $grp )
           {
@@ -2175,24 +2037,24 @@
         }
         
         echo '</select></p>
-              <p><label><input type="radio" name="data[target_type]" value="' . ACL_TYPE_USER . '" /> A specific user</label></p>
+              <p><label><input type="radio" name="data[target_type]" value="' . ACL_TYPE_USER . '" /> ' . $lang->get('acl_radio_user') . '</label></p>
               <p>' . $template->username_field('data[target_id_user]') . '</p>
-              <p>What should this access rule control?</p>
-              <p><label><input name="data[scope]" value="only_this" type="radio" checked="checked" /> Only this page</p>
+              <p>' . $lang->get('acl_lbl_scope') . '</p>
+              <p><label><input name="data[scope]" value="only_this" type="radio" checked="checked" /> ' . $lang->get('acl_radio_scope_thispage') . '</p>
               ' . $groupsel . '
-              <p><label><input name="data[scope]" value="entire_site" type="radio" /> The entire site</p>
+              <p><label><input name="data[scope]" value="entire_site" type="radio" /> ' . $lang->get('acl_radio_scope_wholesite') . '</p>
               <div style="margin: 0 auto 0 0; text-align: right;">
                 <input name="data[mode]" value="seltarget" type="hidden" />
                 <input type="hidden" name="data[page_id]" value="' . $paths->page_id . '" />
                 <input type="hidden" name="data[namespace]" value="' . $paths->namespace . '" />
-                <input type="submit" value="Next &gt;" />
+                <input type="submit" value="' . htmlspecialchars($lang->get('etc_wizard_next')) . '" />
               </div>';
         echo $formend;
         break;
       case 'success':
         echo '<div class="info-box">
-                <b>Permissions updated</b><br />
-                The permissions for ' . $response['target_name'] . ' on this page have been updated successfully.<br />
+                <b>' . $lang->get('acl_lbl_save_success_title') . '</b><br />
+                ' . $lang->get('acl_lbl_save_success_body', array( 'target_name' => $response['target_name'] )) . '<br />
                 ' . $formstart . '
                 <input type="hidden" name="data[mode]" value="seltarget" />
                 <input type="hidden" name="data[target_type]" value="' . $response['target_type'] . '" />
@@ -2201,14 +2063,14 @@
                 <input type="hidden" name="data[scope]" value="' . ( ( $response['page_id'] ) ? 'only_this' : 'entire_site' ) . '" />
                 <input type="hidden" name="data[page_id]" value="' . ( ( $response['page_id'] ) ? $response['page_id'] : 'false' ) . '" />
                 <input type="hidden" name="data[namespace]" value="' . ( ( $response['namespace'] ) ? $response['namespace'] : 'false' ) . '" />
-                <input type="submit" value="Return to ACL editor" /> <input type="submit" name="data[act_go_stage1]" value="Return to user/scope selection" />
+                <input type="submit" value="' . $lang->get('acl_btn_returnto_editor') . '" /> <input type="submit" name="data[act_go_stage1]" value="' . $lang->get('acl_btn_returnto_userscope') . '" />
                 ' . $formend . '
               </div>';
         break;
       case 'delete':
         echo '<div class="info-box">
-                <b>Rule deleted</b><br />
-                The selected access rule has been successfully deleted.<br />
+                <b>' . $lang->get('acl_lbl_delete_success_title') . '</b><br />
+                ' . $lang->get('acl_lbl_delete_success_body', array('target_name' => $response['target_name'])) . '<br />
                 ' . $formstart . '
                 <input type="hidden" name="data[mode]" value="seltarget" />
                 <input type="hidden" name="data[target_type]" value="' . $response['target_type'] . '" />
@@ -2217,22 +2079,27 @@
                 <input type="hidden" name="data[scope]" value="' . ( ( $response['page_id'] ) ? 'only_this' : 'entire_site' ) . '" />
                 <input type="hidden" name="data[page_id]" value="' . ( ( $response['page_id'] ) ? $response['page_id'] : 'false' ) . '" />
                 <input type="hidden" name="data[namespace]" value="' . ( ( $response['namespace'] ) ? $response['namespace'] : 'false' ) . '" />
-                <input type="submit" value="Return to ACL editor" /> <input type="submit" name="data[act_go_stage1]" value="Return to user/scope selection" />
+                <input type="submit" value="' . $lang->get('acl_btn_returnto_editor') . '" /> <input type="submit" name="data[act_go_stage1]" value="' . $lang->get('acl_btn_returnto_userscope') . '" />
                 ' . $formend . '
               </div>';
         break;
       case 'seltarget':
         if ( $response['type'] == 'edit' )
         {
-          echo '<h3>Editing permissions</h3>';
+          echo '<h3>' . $lang->get('acl_lbl_editwin_title_edit') . '</h3>';
         }
         else
         {
-          echo '<h3>Create new rule</h3>';
+          echo '<h3>' . $lang->get('acl_lbl_editwin_title_create') . '</h3>';
         }
-        $type  = ( $response['target_type'] == ACL_TYPE_GROUP ) ? 'group' : 'user';
-        $scope = ( $response['page_id'] ) ? ( $response['namespace'] == '__PageGroup' ? 'this group of pages' : 'this page' ) : 'this entire site';
-        echo 'This panel allows you to edit what the ' . $type . ' "' . $response['target_name'] . '" can do on <b>' . $scope . '</b>. Unless you set a permission to "Deny", these permissions may be overridden by other rules.';
+        $type  = ( $response['target_type'] == ACL_TYPE_GROUP ) ? $lang->get('acl_target_type_group') : $lang->get('acl_target_type_user');
+        $scope = ( $response['page_id'] ) ? ( $response['namespace'] == '__PageGroup' ? $lang->get('acl_scope_type_pagegroup') : $lang->get('acl_scope_type_thispage') ) : $lang->get('acl_scope_type_wholesite');
+        $subs = array(
+            'target_type' => $type,
+            'target' => $response['target_name'],
+            'scope_type' => $scope
+          );
+        echo $lang->get('acl_lbl_editwin_body', $subs);
         echo $formstart;
         $parser = $template->makeParserText( $response['template']['acl_field_begin'] );
         echo $parser->run();
@@ -2241,6 +2108,7 @@
         foreach ( $response['acl_types'] as $acl_type => $value )
         {
           $vars = Array(
+              'FIELD_INHERIT_CHECKED' => '',
               'FIELD_DENY_CHECKED' => '',
               'FIELD_DISALLOW_CHECKED' => '',
               'FIELD_WIKIMODE_CHECKED' => '',
@@ -2251,6 +2119,10 @@
           
           switch ( $response['current_perms'][$acl_type] )
           {
+            case 'i':
+            default:
+              $vars['FIELD_INHERIT_CHECKED'] = 'checked="checked"';
+              break;
             case AUTH_ALLOW:
               $vars['FIELD_ALLOW_CHECKED'] = 'checked="checked"';
               break;
@@ -2258,7 +2130,6 @@
               $vars['FIELD_WIKIMODE_CHECKED'] = 'checked="checked"';
               break;
             case AUTH_DISALLOW:
-            default:
               $vars['FIELD_DISALLOW_CHECKED'] = 'checked="checked"';
               break;
              case AUTH_DENY:
@@ -2266,7 +2137,14 @@
               break;
           }
           $vars['FIELD_NAME'] = 'data[perms][' . $acl_type . ']';
-          $vars['FIELD_DESC'] = $response['acl_descs'][$acl_type];
+          if ( preg_match('/^([a-z0-9_]+)$/', $response['acl_descs'][$acl_type]) )
+          {
+            $vars['FIELD_DESC'] = $lang->get($response['acl_descs'][$acl_type]);
+          }
+          else
+          {
+            $vars['FIELD_DESC'] = $response['acl_descs'][$acl_type];
+          }
           $parser->assign_vars($vars);
           echo $parser->run();
         }
@@ -2279,7 +2157,7 @@
                 <input type="hidden" name="data[target_type]" value="' . $response['target_type'] . '" />
                 <input type="hidden" name="data[target_id]" value="' . $response['target_id'] . '" />
                 <input type="hidden" name="data[target_name]" value="' . $response['target_name'] . '" />
-                ' . ( ( $response['type'] == 'edit' ) ? '<input type="submit" value="Save changes" />&nbsp;&nbsp;<input type="submit" name="data[act_delete_rule]" value="Delete rule" style="color: #AA0000;" onclick="return confirm(\'Do you really want to delete this ACL rule?\');" />' : '<input type="submit" value="Create rule" />' ) . '
+                ' . ( ( $response['type'] == 'edit' ) ? '<input type="submit" value="' . $lang->get('etc_save_changes') . '" />&nbsp;&nbsp;<input type="submit" name="data[act_delete_rule]" value="' . $lang->get('acl_btn_deleterule') . '" style="color: #AA0000;" onclick="return confirm(\'' . addslashes($lang->get('acl_msg_deleterule_confirm')) . '\');" />' : '<input type="submit" value="' . $lang->get('acl_btn_createrule') . '" />' ) . '
               </div>';
         echo $formend;
         break;
@@ -2303,7 +2181,7 @@
    * @access private
    */
    
-  function acl_preprocess($parms)
+  public static function acl_preprocess($parms)
   {
     if ( !isset($parms['mode']) )
       // Nothing to do
@@ -2348,7 +2226,7 @@
     return $parms;
   }
   
-  function acl_postprocess($response)
+  public static function acl_postprocess($response)
   {
     if(!isset($response['mode']))
     {
--- a/includes/paths.php	Fri Feb 22 12:46:51 2008 -0500
+++ b/includes/paths.php	Fri Feb 22 12:51:53 2008 -0500
@@ -2,7 +2,7 @@
 
 /**
  * Enano - an open-source CMS capable of wiki functions, Drupal-like sidebar blocks, and everything in between
- * Version 1.0.3 (Dyrad)
+ * Version 1.1.2 (Caoineag alpha 2)
  * Copyright (C) 2006-2007 Dan Fuhry
  * paths.php - The part of Enano that actually manages content. Everything related to page handling and namespaces is in here.
  *
@@ -45,52 +45,55 @@
     // ACL types
     // These can also be added from within plugins
     
-    $session->register_acl_type('read',                   AUTH_ALLOW,    'Read page(s)');
-    $session->register_acl_type('post_comments',          AUTH_ALLOW,    'Post comments',                                                                                            Array('read'),                                            'Article|User|Project|Template|File|Help|System|Category');
-    $session->register_acl_type('edit_comments',          AUTH_ALLOW,    'Edit own comments',                                                                                        Array('post_comments'),                                   'Article|User|Project|Template|File|Help|System|Category');
-    $session->register_acl_type('edit_page',              AUTH_WIKIMODE, 'Edit page',                                                                                                Array('view_source'),                                     'Article|User|Project|Template|File|Help|System|Category');
-    $session->register_acl_type('view_source',            AUTH_WIKIMODE, 'View source',                                                                                              Array('read'),                                            'Article|User|Project|Template|File|Help|System|Category'); // Only used if the page is protected
-    $session->register_acl_type('mod_comments',           AUTH_DISALLOW, 'Moderate comments',                                                                                        Array('edit_comments'),                                   'Article|User|Project|Template|File|Help|System|Category');
-    $session->register_acl_type('history_view',           AUTH_WIKIMODE, 'View history/diffs',                                                                                       Array('read'),                                            'Article|User|Project|Template|File|Help|System|Category');
-    $session->register_acl_type('history_rollback',       AUTH_DISALLOW, 'Rollback history',                                                                                         Array('history_view'),                                    'Article|User|Project|Template|File|Help|System|Category');
-    $session->register_acl_type('history_rollback_extra', AUTH_DISALLOW, 'Undelete page(s)',                                                                                         Array('history_rollback'),                                'Article|User|Project|Template|File|Help|System|Category|Special');
-    $session->register_acl_type('protect',                AUTH_DISALLOW, 'Protect page(s)',                                                                                          Array('read'),                                            'Article|User|Project|Template|File|Help|System|Category');
-    $session->register_acl_type('rename',                 AUTH_WIKIMODE, 'Rename page(s)',                                                                                           Array('read'),                                            'Article|User|Project|Template|File|Help|System|Category');
-    $session->register_acl_type('clear_logs',             AUTH_DISALLOW, 'Clear page logs (dangerous)',                                                                              Array('read', 'protect', 'even_when_protected'),          'Article|User|Project|Template|File|Help|System|Category');
-    $session->register_acl_type('vote_delete',            AUTH_ALLOW,    'Vote to delete',                                                                                           Array('read'),                                            'Article|User|Project|Template|File|Help|System|Category');
-    $session->register_acl_type('vote_reset',             AUTH_DISALLOW, 'Reset delete votes',                                                                                       Array('read'),                                            'Article|User|Project|Template|File|Help|System|Category');
-    $session->register_acl_type('delete_page',            AUTH_DISALLOW, 'Delete page(s)',                                                                                           Array(),                                                  'Article|User|Project|Template|File|Help|System|Category');
-    $session->register_acl_type('tag_create',             AUTH_ALLOW,    'Tag page(s)',                                                                                              Array('read'),                                            'Article|User|Project|Template|File|Help|System|Category');
-    $session->register_acl_type('tag_delete_own',         AUTH_ALLOW,    'Remove own page tags',                                                                                     Array('read', 'tag_create'),                              'Article|User|Project|Template|File|Help|System|Category');
-    $session->register_acl_type('tag_delete_other',       AUTH_DISALLOW, 'Remove others\' page tags',                                                                                Array('read'),                                            'Article|User|Project|Template|File|Help|System|Category');
-    $session->register_acl_type('set_wiki_mode',          AUTH_DISALLOW, 'Set per-page wiki mode',                                                                                   Array('read'),                                            'Article|User|Project|Template|File|Help|System|Category');
-    $session->register_acl_type('password_set',           AUTH_DISALLOW, 'Set password',                                                                                             Array('read'),                                            'Article|User|Project|Template|File|Help|System|Category');
-    $session->register_acl_type('password_reset',         AUTH_DISALLOW, 'Disable/reset password',                                                                                   Array('read'),                                            'Article|User|Project|Template|File|Help|System|Category');
-    $session->register_acl_type('mod_misc',               AUTH_DISALLOW, 'Super moderator (generate SQL backtraces, view IP addresses, and send large numbers of private messages)', Array(),                                                  'All');
-    $session->register_acl_type('edit_cat',               AUTH_WIKIMODE, 'Edit categorization',                                                                                      Array('read'),                                            'Article|User|Project|Template|File|Help|System|Category');
-    $session->register_acl_type('even_when_protected',    AUTH_DISALLOW, 'Allow editing, renaming, and categorization even when protected',                                          Array('edit_page', 'rename', 'mod_comments', 'edit_cat'), 'Article|User|Project|Template|File|Help|System|Category');
-    $session->register_acl_type('upload_files',           AUTH_DISALLOW, 'Upload files',                                                                                             Array('create_page'),                                     'Article|User|Project|Template|File|Help|System|Category|Special');
-    $session->register_acl_type('upload_new_version',     AUTH_WIKIMODE, 'Upload new versions of files',                                                                             Array('upload_files'),                                    'Article|User|Project|Template|File|Help|System|Category|Special');
-    $session->register_acl_type('create_page',            AUTH_WIKIMODE, 'Create pages',                                                                                             Array(),                                                  'Article|User|Project|Template|File|Help|System|Category|Special');
-    $session->register_acl_type('php_in_pages',           AUTH_DISALLOW, 'Embed PHP code in pages',                                                                                  Array('edit_page'),                                       'Article|User|Project|Template|File|Help|System|Category|Admin');
-    $session->register_acl_type('edit_acl',               AUTH_DISALLOW, 'Edit access control lists', Array('read', 'post_comments', 'edit_comments', 'edit_page', 'view_source', 'mod_comments', 'history_view', 'history_rollback', 'history_rollback_extra', 'protect', 'rename', 'clear_logs', 'vote_delete', 'vote_reset', 'delete_page', 'set_wiki_mode', 'password_set', 'password_reset', 'mod_misc', 'edit_cat', 'even_when_protected', 'upload_files', 'upload_new_version', 'create_page', 'php_in_pages'));
+    $session->register_acl_type('read',                   AUTH_ALLOW,    'perm_read');
+    $session->register_acl_type('post_comments',          AUTH_ALLOW,    'perm_post_comments',          Array('read'),                                            'Article|User|Project|Template|File|Help|System|Category');
+    $session->register_acl_type('edit_comments',          AUTH_ALLOW,    'perm_edit_comments',          Array('post_comments'),                                   'Article|User|Project|Template|File|Help|System|Category');
+    $session->register_acl_type('edit_page',              AUTH_WIKIMODE, 'perm_edit_page',              Array('view_source'),                                     'Article|User|Project|Template|File|Help|System|Category');
+    $session->register_acl_type('edit_wysiwyg',           AUTH_ALLOW,    'perm_edit_wysiwyg',           Array('edit_page'),                                       'Article|User|Project|Template|File|Help|System|Category');
+    $session->register_acl_type('view_source',            AUTH_WIKIMODE, 'perm_view_source',            Array('read'),                                            'Article|User|Project|Template|File|Help|System|Category'); // Only used if the page is protected
+    $session->register_acl_type('mod_comments',           AUTH_DISALLOW, 'perm_mod_comments',           Array('edit_comments'),                                   'Article|User|Project|Template|File|Help|System|Category');
+    $session->register_acl_type('history_view',           AUTH_WIKIMODE, 'perm_history_view',           Array('read'),                                            'Article|User|Project|Template|File|Help|System|Category');
+    $session->register_acl_type('history_rollback',       AUTH_DISALLOW, 'perm_history_rollback',       Array('history_view'),                                    'Article|User|Project|Template|File|Help|System|Category');
+    $session->register_acl_type('history_rollback_extra', AUTH_DISALLOW, 'perm_history_rollback_extra', Array('history_rollback'),                                'Article|User|Project|Template|File|Help|System|Category|Special');
+    $session->register_acl_type('protect',                AUTH_DISALLOW, 'perm_protect',                Array('read'),                                            'Article|User|Project|Template|File|Help|System|Category');
+    $session->register_acl_type('rename',                 AUTH_WIKIMODE, 'perm_rename',                 Array('read'),                                            'Article|User|Project|Template|File|Help|System|Category');
+    $session->register_acl_type('clear_logs',             AUTH_DISALLOW, 'perm_clear_logs',             Array('read', 'protect', 'even_when_protected'),          'Article|User|Project|Template|File|Help|System|Category');
+    $session->register_acl_type('vote_delete',            AUTH_ALLOW,    'perm_vote_delete',            Array('read'),                                            'Article|User|Project|Template|File|Help|System|Category');
+    $session->register_acl_type('vote_reset',             AUTH_DISALLOW, 'perm_vote_reset',             Array('read'),                                            'Article|User|Project|Template|File|Help|System|Category');
+    $session->register_acl_type('delete_page',            AUTH_DISALLOW, 'perm_delete_page',            Array(),                                                  'Article|User|Project|Template|File|Help|System|Category');
+    $session->register_acl_type('tag_create',             AUTH_ALLOW,    'perm_tag_create',             Array('read'),                                            'Article|User|Project|Template|File|Help|System|Category');
+    $session->register_acl_type('tag_delete_own',         AUTH_ALLOW,    'perm_tag_delete_own',         Array('read', 'tag_create'),                              'Article|User|Project|Template|File|Help|System|Category');
+    $session->register_acl_type('tag_delete_other',       AUTH_DISALLOW, 'perm_tag_delete_other',       Array('read'),                                            'Article|User|Project|Template|File|Help|System|Category');
+    $session->register_acl_type('set_wiki_mode',          AUTH_DISALLOW, 'perm_set_wiki_mode',          Array('read'),                                            'Article|User|Project|Template|File|Help|System|Category');
+    $session->register_acl_type('password_set',           AUTH_DISALLOW, 'perm_password_set',           Array('read'),                                            'Article|User|Project|Template|File|Help|System|Category');
+    $session->register_acl_type('password_reset',         AUTH_DISALLOW, 'perm_password_reset',         Array('read'),                                            'Article|User|Project|Template|File|Help|System|Category');
+    $session->register_acl_type('mod_misc',               AUTH_DISALLOW, 'perm_mod_misc',               Array(),                                                  'All');
+    $session->register_acl_type('edit_cat',               AUTH_WIKIMODE, 'perm_edit_cat',               Array('read'),                                            'Article|User|Project|Template|File|Help|System|Category');
+    $session->register_acl_type('even_when_protected',    AUTH_DISALLOW, 'perm_even_when_protected',    Array('edit_page', 'rename', 'mod_comments', 'edit_cat'), 'Article|User|Project|Template|File|Help|System|Category');
+    $session->register_acl_type('upload_files',           AUTH_DISALLOW, 'perm_upload_files',           Array('create_page'),                                     'Article|User|Project|Template|File|Help|System|Category|Special');
+    $session->register_acl_type('upload_new_version',     AUTH_WIKIMODE, 'perm_upload_new_version',     Array('upload_files'),                                    'Article|User|Project|Template|File|Help|System|Category|Special');
+    $session->register_acl_type('create_page',            AUTH_WIKIMODE, 'perm_create_page',            Array(),                                                  'Article|User|Project|Template|File|Help|System|Category|Special');
+    $session->register_acl_type('html_in_pages',          AUTH_DISALLOW, 'perm_html_in_pages',          Array('edit_page'),                                       'Article|User|Project|Template|File|Help|System|Category|Admin');
+    $session->register_acl_type('php_in_pages',           AUTH_DISALLOW, 'perm_php_in_pages',           Array('edit_page', 'html_in_pages'),                      'Article|User|Project|Template|File|Help|System|Category|Admin');
+    $session->register_acl_type('edit_acl',               AUTH_DISALLOW, 'perm_edit_acl',               Array('read', 'post_comments', 'edit_comments', 'edit_page', 'view_source', 'mod_comments', 'history_view', 'history_rollback', 'history_rollback_extra', 'protect', 'rename', 'clear_logs', 'vote_delete', 'vote_reset', 'delete_page', 'set_wiki_mode', 'password_set', 'password_reset', 'mod_misc', 'edit_cat', 'even_when_protected', 'upload_files', 'upload_new_version', 'create_page', 'php_in_pages'));
     
     // DO NOT add new admin pages here! Use a plugin to call $paths->addAdminNode();
-    $this->addAdminNode('General', 'General Configuration', 'GeneralConfig');
-    $this->addAdminNode('General', 'File uploads', 'UploadConfig');
-    $this->addAdminNode('General', 'Allowed file types', 'UploadAllowedMimeTypes');
-    $this->addAdminNode('General', 'Manage Plugins', 'PluginManager');
-    $this->addAdminNode('General', 'Backup database', 'DBBackup');
-    $this->addAdminNode('Content', 'Manage Pages', 'PageManager');
-    $this->addAdminNode('Content', 'Edit page content', 'PageEditor');
-    $this->addAdminNode('Content', 'Manage page groups', 'PageGroups');
-    $this->addAdminNode('Appearance', 'Manage themes', 'ThemeManager');
-    $this->addAdminNode('Users', 'Manage users', 'UserManager');
-    $this->addAdminNode('Users', 'Edit groups', 'GroupManager');
-    $this->addAdminNode('Users', 'COPPA support', 'COPPA');
-    $this->addAdminNode('Users', 'Mass e-mail', 'MassEmail');
-    $this->addAdminNode('Security', 'Security log', 'SecurityLog');
-    $this->addAdminNode('Security', 'Ban control', 'BanControl');
+    $this->addAdminNode('adm_cat_general',    'adm_page_general_config', 'GeneralConfig');
+    $this->addAdminNode('adm_cat_general',    'adm_page_file_uploads',   'UploadConfig');
+    $this->addAdminNode('adm_cat_general',    'adm_page_file_types',     'UploadAllowedMimeTypes');
+    $this->addAdminNode('adm_cat_general',    'adm_page_plugins',        'PluginManager');
+    $this->addAdminNode('adm_cat_general',    'adm_page_db_backup',      'DBBackup');
+    $this->addAdminNode('adm_cat_general',    'adm_page_lang_manager',   'LangManager');
+    $this->addAdminNode('adm_cat_content',    'adm_page_manager',        'PageManager');
+    $this->addAdminNode('adm_cat_content',    'adm_page_editor',         'PageEditor');
+    $this->addAdminNode('adm_cat_content',    'adm_page_pg_groups',      'PageGroups');
+    $this->addAdminNode('adm_cat_appearance', 'adm_page_themes',         'ThemeManager');
+    $this->addAdminNode('adm_cat_users',      'adm_page_users',          'UserManager');
+    $this->addAdminNode('adm_cat_users',      'adm_page_user_groups',    'GroupManager');
+    $this->addAdminNode('adm_cat_users',      'adm_page_coppa',          'COPPA');
+    $this->addAdminNode('adm_cat_users',      'adm_page_mass_email',     'MassEmail');
+    $this->addAdminNode('adm_cat_security',   'adm_page_security_log',   'SecurityLog');
+    $this->addAdminNode('adm_cat_security',   'adm_page_ban_control',    'BanControl');
     
     $code = $plugins->setHook('acl_rule_init');
     foreach ( $code as $cmd )
@@ -101,13 +104,36 @@
     $this->wiki_mode = (int)getConfig('wiki_mode')=='1';
     $this->template_cache = Array();
   }
-  function pathManager()
+  function parse_url($sanitize = true)
   {
-    $this->__construct();
+    $title = '';
+    if( isset($_GET['title']) )
+    {
+      $title = $_GET['title'];
+    }
+    elseif( isset($_SERVER['PATH_INFO']) )
+    {
+      $title = substr($_SERVER['PATH_INFO'], ( strpos($_SERVER['PATH_INFO'], '/') ) + 1 );
+    }
+    else
+    {
+      // This method really isn't supported because apache has a habit of passing dots as underscores, thus corrupting the request
+      // If you really want to try it, the URI format is yoursite.com/?/Page_title
+      if ( count($_GET) > 0 )
+      {
+        list($getkey) = array_keys($_GET);
+        if ( substr($getkey, 0, 1) == '/' )
+        {
+          $title = substr($getkey, 1);
+        }
+      }
+    }
+    return ( $sanitize ) ? sanitize_page_id($title) : $title;
   }
   function init()
   {
     global $db, $session, $paths, $template, $plugins; // Common objects
+    global $lang;
     
     $code = $plugins->setHook('paths_init_before');
     foreach ( $code as $cmd )
@@ -125,7 +151,15 @@
     {
       
       $r['urlname_nons'] = $r['urlname'];
-      $r['urlname'] = $this->nslist[$r['namespace']] . $r['urlname']; // Applies the User:/File:/etc prefixes to the URL names
+      if ( isset($this->nslist[$r['namespace']]) )
+      {
+        $r['urlname'] = $this->nslist[$r['namespace']] . $r['urlname']; // Applies the User:/File:/etc prefixes to the URL names
+      }
+      else
+      {
+        $ns_char = substr($this->nslist['Special'], -1);
+        $r['urlname'] = $r['namespace'] . $ns_char . $r['urlname'];
+      }
       
       if ( $r['delvotes'] == null)
       {
@@ -149,107 +183,40 @@
       
     }
     $db->free_result();
-    if ( defined('ENANO_INTERFACE_INDEX') || defined('ENANO_INTERFACE_AJAX') || defined('IN_ENANO_INSTALL') || defined('IN_ENANO_UPGRADE') )
+    if ( defined('ENANO_INTERFACE_INDEX') || defined('ENANO_INTERFACE_AJAX') || defined('IN_ENANO_UPGRADE') )
     {
-      if( isset($_GET['title']) )
+      $title = $this->parse_url(false);
+      if ( empty($title) )
+      {
+        $this->main_page();
+      }
+      if ( strstr($title, ' ') || strstr($title, '+') || strstr($title, '%20') )
       {
-        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'];
+        $title = sanitize_page_id($title);
+        redirect(makeUrl($title), '', '', 0);
       }
-      elseif( isset($_SERVER['PATH_INFO']) )
+      $title = sanitize_page_id($title);
+      // We've got the title, pull the namespace from it
+      $namespace = 'Article';
+      $page_id = $title;
+      foreach ( $this->nslist as $ns => $prefix )
       {
-        $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'] )
+        $prefix_len = strlen($prefix);
+        if ( substr($title, 0, $prefix_len) == $prefix )
         {
-          $pi2 = $pi[1];
-        }
-        else
-        {
-          $pi2 = implode('/', $pi);
-        }
-        $this->page = $pi2;
-        $this->fullpage = implode('/', $pi);
-      }
-      else
-      {
-        $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();
+          $page_id = substr($title, $prefix_len);
+          $namespace = $ns;
         }
       }
+      $this->namespace = $namespace;
+      $this->fullpage = $title;
+      if ( $namespace == 'Special' || $namespace == 'Admin' )
+      {
+        list($page_id) = explode('/', $page_id);
+      }
+      $this->page = $this->nslist[$namespace] . $page_id;
+      $this->page_id = $page_id;
+      // die("All done setting parameters. What we've got:<br/>namespace: $namespace<br/>fullpage: $this->fullpage<br/>page: $this->page<br/>page_id: $this->page_id");
     }
     else
     {
@@ -393,8 +360,7 @@
         {
           $main_page = makeUrl($this->pages[0]['urlname']);
         }
-        $sp_link = '<a href="' . makeUrlNS('Special', 'SpecialPages') . '">here</a>';
-        redirect($main_page, 'Can\'t load special page', 'The special page you requested could not be found. This may be due to a plugin failing to load. A list of all special pages on this website can be viewed '.$sp_link.'. You will be redirected to the main page in 15 seconds.', 14);
+        redirect($main_page, $lang->get('page_msg_special_404_title'), $lang->get('page_msg_special_404_body', array('sp_link' => makeUrlNS('Special', 'SpecialPages'))), 15);
         exit;
       }
       // Allow the user to create/modify his user page uncondtionally (admins can still protect the page)
@@ -414,12 +380,21 @@
     }
     
     $session->init_permissions();
+    profiler_log('Paths and CMS core initted');
   }
   
   function add_page($flags)
   {
+    global $lang;
     $flags['urlname_nons'] = $flags['urlname'];
     $flags['urlname'] = $this->nslist[$flags['namespace']] . $flags['urlname']; // Applies the User:/File:/etc prefixes to the URL names
+    
+    if ( is_object($lang) )
+    {
+      if ( preg_match('/^[a-z0-9]+_[a-z0-9_]+$/', $flags['name']) )
+        $flags['name'] = $lang->get($flags['name']);
+    }
+    
     $pages_len = sizeof($this->pages)/2;
     $this->pages[$pages_len] = $flags;
     $this->pages[$flags['urlname']] =& $this->pages[$pages_len];
@@ -442,7 +417,7 @@
   function sysmsg($n)
   {
     global $db, $session, $paths, $template, $plugins; // Common objects
-    $q = $db->sql_query('SELECT page_text, char_tag FROM '.table_prefix.'page_text WHERE page_id=\''.$db->escape($n).'\' AND namespace=\'System\'');
+    $q = $db->sql_query('SELECT page_text, char_tag FROM '.table_prefix.'page_text WHERE page_id=\''.$db->escape(sanitize_page_id($n)).'\' AND namespace=\'System\'');
     if( !$q )
     {
       $db->_die('Error during generic selection of system page data.');
@@ -457,98 +432,46 @@
     $message = $r['page_text'];
     
     $message = preg_replace('/<noinclude>(.*?)<\/noinclude>/is', '', $message);
+    $message = preg_replace('/<nodisplay>(.*?)<\/nodisplay>/is', '\\1', $message);
     
     return $message;
   }
   function get_pageid_from_url()
   {
-    if(isset($_GET['title']))
-    {
-      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);
-        header('Location: '.$loc);
-        exit;
-      }
-      $ret = $_GET['title'];
-    }
-    elseif(isset($_SERVER['PATH_INFO']))
+    $url = $this->parse_url();
+    if ( substr($url, 0, strlen($this->nslist['Special'])) == $this->nslist['Special'] ||
+         substr($url, 0, strlen($this->nslist['Admin']))   == $this->nslist['Admin'])
     {
-      $pi = explode('/', $_SERVER['PATH_INFO']);
-      
-      if(!isset($pi[1]) || (isset($pi[1]) && $pi[1] == ''))
-      {
-        return false;
-      }
-      
-      if(strstr($pi[1], ' '))
-      {
-        $loc = urldecode(rawurldecode($_SERVER['REQUEST_URI']));
-        $loc = str_replace(' ', '_', $loc);
-        $loc = str_replace('+', '_', $loc);
-        header('Location: '.$loc);
-        exit;
-      }
-      unset($pi[0]);
-      $pi[1] = implode('/', $pi);
-      $ret = $pi[1];
+      list($url) = explode('/', $url);
     }
-    else
-    {
-      $k = array_keys($_GET);
-      foreach($k as $c)
-      {
-        if(substr($c, 0, 1) == '/')
-        {
-          $ret = substr($c, 1, strlen($c));
-          if(substr($ret, 0, strlen($this->nslist['Special'])) == $this->nslist['Special'] ||
-             substr($ret, 0, strlen($this->nslist['Admin'])) == $this->nslist['Admin'])
-          {
-            $ret = explode('/', $ret);
-            $ret = $ret[0];
-          }
-          break;
-        }
-      }
-    }
-    
-    if ( isset($ret) )
-    {
-      if ( substr($ret, 0, ( strlen($this->nslist['Special']) )) == $this->nslist['Special'] && strstr($ret, '/') )
-      {
-        list ( $ret ) = explode('/', $ret);
-      }
-    }
-    
-    return ( isset($ret) ) ? $ret : false;
+    return $url;
   }
   // Parses a (very carefully formed) array into Javascript code compatible with the Tigra Tree Menu used in the admin menu
   function parseAdminTree() 
   {
+    global $lang;
+    
     $k = array_keys($this->admin_tree);
     $i = 0;
     $ret = '';
-    $ret .= "var TREE_ITEMS = [\n  ['Administration panel home', 'javascript:ajaxPage(\'".$this->nslist['Admin']."Home\');',\n    ";
+    $ret .= "var TREE_ITEMS = [\n  ['" . $lang->get('adm_btn_home') . "', 'javascript:ajaxPage(\'".$this->nslist['Admin']."Home\');',\n    ";
     foreach($k as $key)
     {
       $i++;
-      $ret .= "['".$key."', 'javascript:trees[0].toggle($i)', \n";
+      $name = ( preg_match('/^[a-z0-9_]+$/', $key) ) ? $lang->get($key) : $key;
+      $ret .= "['".$name."', 'javascript:trees[0].toggle($i)', \n";
       foreach($this->admin_tree[$key] as $c)
       {
         $i++;
-        $ret .= "        ['".$c['name']."', 'javascript:ajaxPage(\\'".$this->nslist['Admin'].$c['pageid']."\\');'],\n";
+        $name = ( preg_match('/^[a-z0-9_]+$/', $key) ) ? $lang->get($c['name']) : $c['name'];
+        
+        $ret .= "        ['".$name."', 'javascript:ajaxPage(\\'".$this->nslist['Admin'].$c['pageid']."\\');'],\n";
       }
       $ret .= "      ],\n";
     }
-    $ret .= "    ['Log out of admin panel', 'javascript:ajaxPage(\\'".$this->nslist['Admin']."AdminLogout\\');'],\n";
-    $ret .= "    ['<span id=\\'keepalivestat\\'>Loading keep-alive control...</span>', 'javascript:ajaxToggleKeepalive();', 
-                   ['About keep-alive', 'javascript:aboutKeepAlive();']
+    $ret .= "    ['" . $lang->get('adm_btn_logout') . "', 'javascript:ajaxPage(\\'".$this->nslist['Admin']."AdminLogout\\');'],\n";
+    $ret .= "    ['<span id=\\'keepalivestat\\'>" . $lang->get('adm_btn_keepalive_loading') . "</span>', 'javascript:ajaxToggleKeepalive();', 
+                   ['" . $lang->get('adm_btn_keepalive_about') . "', 'javascript:aboutKeepAlive();']
                  ],\n";
     // I used this while I painstakingly wrote the Runt code that auto-expands certain nodes based on the value of a bitfield stored in a cookie. *shudders*
     // $ret .= "    ['(debug) Clear menu bitfield', 'javascript:createCookie(\\'admin_menu_state\\', \\'1\\', 365);'],\n";
@@ -568,80 +491,22 @@
   }
   function getParam($id = 0)
   {
-    // using !empty here is a bugfix for IIS 5.x on Windows 2000 Server
-    // It may affect other IIS versions as well
-    if(isset($_SERVER['PATH_INFO']) && !empty($_SERVER['PATH_INFO']))
-    {
-      $pi = explode('/', $_SERVER['PATH_INFO']);
-      $id = $id + 2;
-      return isset($pi[$id]) ? $pi[$id] : false;
-    }
-    else if( isset($_GET['title']) )
-    {
-      $pi = explode('/', $_GET['title']);
-      $id = $id + 1;
-      return isset($pi[$id]) ? $pi[$id] : false;
-    }
-    else
-    {
-      $k = array_keys($_GET);
-      foreach($k as $c)
-      {
-        if(substr($c, 0, 1) == '/')
-        {
-          // Bugfix for apache somehow passing dots as underscores
-          global $mime_types;
-          $exts = array_keys($mime_types);
-          $exts = '(' . implode('|', $exts) . ')';
-          if ( preg_match( '#_'.$exts.'#i', $c ) )
-            $c = preg_replace( '#_'.$exts.'#i', '.\\1', $c );
-          
-          $pi = explode('/', $c);
-          $id = $id + 2;
-          return isset($pi[$id]) ? $pi[$id] : false;
-        }
-      }
-      return false;
-    }
+    $title = $this->parse_url(false);
+    $regex = '/^' . str_replace('/', '\\/', preg_quote($this->nslist[$this->namespace])) . '\\/?/';
+    $title = preg_replace($regex, '', $title);
+    $title = explode('/', $title);
+    $id = $id + 1;
+    return ( isset($title[$id]) ) ? $title[$id] : false;
   }
   
   function getAllParams()
   {
-    // using !empty here is a bugfix for IIS 5.x on Windows 2000 Server
-    // It may affect other IIS versions as well
-    if(isset($_SERVER['PATH_INFO']) && !empty($_SERVER['PATH_INFO']))
-    {
-      $pi = explode('/', $_SERVER['PATH_INFO']);
-      unset($pi[0], $pi[1]);
-      return implode('/', $pi);
-    }
-    else if( isset($_GET['title']) )
-    {
-      $pi = explode('/', $_GET['title']);
-      unset($pi[0]);
-      return implode('/', $pi);
-    }
-    else
-    {
-      $k = array_keys($_GET);
-      foreach($k as $c)
-      {
-        if(substr($c, 0, 1) == '/')
-        {
-          // Bugfix for apache somehow passing dots as underscores
-          global $mime_types;
-          $exts = array_keys($mime_types);
-          $exts = '(' . implode('|', $exts) . ')';
-          if ( preg_match( '#_'.$exts.'#i', $c ) )
-            $c = preg_replace( '#_'.$exts.'#i', '.\\1', $c );
-          
-          $pi = explode('/', $c);
-          unset($pi[0], $pi[1]);
-          return implode('/', $pi);
-        }
-      }
-      return false;
-    }
+    $title = $this->parse_url(false);
+    $regex = '/^' . str_replace('/', '\\/', preg_quote($this->nslist[$this->namespace])) . '\\/?/';
+    $title = preg_replace($regex, '', $title);
+    $title = explode('/', $title);
+    unset($title[0]);
+    return implode('/', $title);
   }
   
   /**
@@ -875,7 +740,7 @@
     
   }
   
-  /*
+  /**
    * Creates an instance of the Searcher class, including index info
    * @return object
    */
--- a/includes/plugins.php	Fri Feb 22 12:46:51 2008 -0500
+++ b/includes/plugins.php	Fri Feb 22 12:51:53 2008 -0500
@@ -2,7 +2,7 @@
 
 /*
  * Enano - an open-source CMS capable of wiki functions, Drupal-like sidebar blocks, and everything in between
- * Version 1.0.3 (Dyrad)
+ * Version 1.1.2 (Caoineag alpha 2)
  * Copyright (C) 2006-2007 Dan Fuhry
  *
  * This program is Free Software; you can redistribute and/or modify it under the terms of the GNU General Public License
@@ -16,7 +16,7 @@
   var $hook_list;
   var $load_list;
   var $loaded_plugins;
-  var $system_plugins = Array('SpecialUserFuncs.php','SpecialUserPrefs.php','SpecialPageFuncs.php','SpecialAdmin.php','SpecialCSS.php','SpecialUpdownload.php','SpecialSearch.php','PrivateMessages.php','SpecialGroups.php');
+  var $system_plugins = Array('SpecialUserFuncs.php','SpecialUserPrefs.php','SpecialPageFuncs.php','SpecialAdmin.php','SpecialCSS.php','SpecialUpdownload.php','SpecialSearch.php','PrivateMessages.php','SpecialGroups.php', 'SpecialRecentChanges.php');
   function loadAll() 
   {
     $dir = ENANO_ROOT.'/plugins/';
@@ -39,7 +39,9 @@
             {
               $this->load_list[] = $dir . $file;
               $plugid = substr($file, 0, strlen($file)-4);
-              $f = file_get_contents($dir . $file);
+              $f = @file_get_contents($dir . $file);
+              if ( empty($f) )
+                continue;
               $f = explode("\n", $f);
               $f = array_slice($f, 2, 7);
               $f[0] = substr($f[0], 13);
@@ -78,7 +80,7 @@
     */
     if(isset($this->hook_list[$name]) && is_array($this->hook_list[$name]))
     {
-      return $this->hook_list[$name];
+      return array(implode("\n", $this->hook_list[$name]));
     }
     else
     {
--- a/includes/render.php	Fri Feb 22 12:46:51 2008 -0500
+++ b/includes/render.php	Fri Feb 22 12:51:53 2008 -0500
@@ -2,7 +2,7 @@
 
 /*
  * Enano - an open-source CMS capable of wiki functions, Drupal-like sidebar blocks, and everything in between
- * Version 1.0.3 (Dyrad)
+ * Version 1.1.2 (Caoineag alpha 2)
  * Copyright (C) 2006-2007 Dan Fuhry
  * render.php - handles fetching pages and parsing them into HTML
  *
@@ -15,7 +15,7 @@
  
 class RenderMan {
   
-  function strToPageID($string)
+  public static function strToPageID($string)
   {
     global $db, $session, $paths, $template, $plugins; // Common objects
     $k = array_keys($paths->nslist);
@@ -38,7 +38,7 @@
     return Array($pg, $ns);
   }
   
-  function getPage($page_id, $namespace, $wiki = 1, $smilies = true, $filter_links = true, $redir = true, $render = true)
+  public static function getPage($page_id, $namespace, $wiki = 1, $smilies = true, $filter_links = true, $redir = true, $render = true)
   {
     global $db, $session, $paths, $template, $plugins; // Common objects
     
@@ -112,7 +112,7 @@
     return ($render) ? RenderMan::render($message, $wiki, $smilies, $filter_links) : $message;
   }
   
-  function getTemplate($id, $parms)
+  public static function getTemplate($id, $parms)
   {
     global $db, $session, $paths, $template, $plugins; // Common objects
     if(!isset($paths->pages[$paths->nslist['Template'].$id])) 
@@ -150,7 +150,7 @@
     return $text;
   }
   
-  function fetch_template_text($id)
+  public static function fetch_template_text($id)
   {
     global $db, $session, $paths, $template, $plugins; // Common objects
     if(!isset($paths->pages[$paths->nslist['Template'].$id])) 
@@ -176,7 +176,7 @@
     return $text;
   }
   
-  function render($text, $wiki = 1, $smilies = true, $filter_links = true)
+  public static function render($text, $wiki = 1, $smilies = true, $filter_links = true)
   {
     global $db, $session, $paths, $template, $plugins; // Common objects
     if($smilies)
@@ -194,7 +194,7 @@
     return $text;
   }
   
-  function PlainTextRender($text, $wiki = 1, $smilies = false, $filter_links = true)
+  public static function PlainTextRender($text, $wiki = 1, $smilies = false, $filter_links = true)
   {
     global $db, $session, $paths, $template, $plugins; // Common objects
     if($smilies)
@@ -212,13 +212,30 @@
     return $text;
   }
   
-  function next_gen_wiki_format($text, $plaintext = false, $filter_links = true, $do_params = false)
+  public static function next_gen_wiki_format($text, $plaintext = false, $filter_links = true, $do_params = false)
   {
     global $db, $session, $paths, $template, $plugins; // Common objects
+    global $lang;
+    
+    profiler_log("RenderMan: starting wikitext render");
+    
     $random_id = md5( time() . mt_rand() );
     
     // Strip out <nowiki> sections and PHP code
     
+    $nw = preg_match_all('#<nowiki>(.*?)<\/nowiki>#is', $text, $nowiki);
+    
+    for($i=0;$i<sizeof($nowiki[1]);$i++)
+    {
+      $text = str_replace('<nowiki>'.$nowiki[1][$i].'</nowiki>', '{NOWIKI:'.$random_id.':'.$i.'}', $text);
+    }
+    
+    $code = $plugins->setHook('render_wikiformat_veryearly');
+    foreach ( $code as $cmd )
+    {
+      eval($cmd);
+    }
+    
     $php = preg_match_all('#<\?php(.*?)\?>#is', $text, $phpsec);
     
     for($i=0;$i<sizeof($phpsec[1]);$i++)
@@ -226,19 +243,25 @@
       $text = str_replace('<?php'.$phpsec[1][$i].'?>', '{PHP:'.$random_id.':'.$i.'}', $text);
     }
     
-    $nw = preg_match_all('#<nowiki>(.*?)<\/nowiki>#is', $text, $nowiki);
-    
-    for($i=0;$i<sizeof($nowiki[1]);$i++)
-    {
-      $text = str_replace('<nowiki>'.$nowiki[1][$i].'</nowiki>', '{NOWIKI:'.$random_id.':'.$i.'}', $text);
-    }
-    
     $text = preg_replace('/<noinclude>(.*?)<\/noinclude>/is', '\\1', $text);
     if ( $paths->namespace == 'Template' )
     {
       $text = preg_replace('/<nodisplay>(.*?)<\/nodisplay>/is', '', $text);
     }
     
+    preg_match_all('/<lang code="([a-z0-9_]+)">([\w\W]+?)<\/lang>/', $text, $langmatch);
+    foreach ( $langmatch[0] as $i => $match )
+    {
+      if ( $langmatch[1][$i] == $lang->lang_code )
+      {
+        $text = str_replace_once($match, $langmatch[2][$i], $text);
+      }
+      else
+      {
+        $text = str_replace_once($match, '', $text);
+      }
+    }
+    
     $code = $plugins->setHook('render_wikiformat_pre');
     foreach ( $code as $cmd )
     {
@@ -272,10 +295,13 @@
       $text = RenderMan::include_templates($text);
     }
     
+    // Before shipping it out to the renderer, replace spaces in between headings and paragraphs:
+    $text = preg_replace('/<\/(h[0-9]|div|p)>([\s]+)<(h[0-9]|div|p)( .+?)?>/i', '</\\1><\\3\\4>', $text);
+    
     $text = process_tables($text);
     $text = RenderMan::parse_internal_links($text);
     
-    $wiki =& Text_Wiki::singleton('Mediawiki');
+    $wiki = Text_Wiki::singleton('Mediawiki');
     if($plaintext)
     {
       $wiki->setRenderConf('Plain', 'wikilink', 'view_url', contentPath);
@@ -321,11 +347,13 @@
       $result = str_replace('{PHP:'.$random_id.':'.$i.'}', '<?php'.$phpsec[1][$i].'?>', $result);
     }
     
+    profiler_log("RenderMan: finished wikitext render");
+    
     return $result;
     
   }
   
-  function wikiFormat($message, $filter_links = true, $do_params = false, $plaintext = false)
+  public static function wikiFormat($message, $filter_links = true, $do_params = false, $plaintext = false)
   {
     global $db, $session, $paths, $template, $plugins; // Common objects
     
@@ -408,7 +436,7 @@
     return $result;
   }
   
-  function destroy_javascript($message, $_php = false)
+  public static function destroy_javascript($message, $_php = false)
   {
     $message = preg_replace('#<(script|object|applet|embed|iframe|frame|form|input|select)(.*?)>#is', '&lt;\\1\\2&gt;', $message);
     $message = preg_replace('#</(script|object|applet|embed|iframe|frame|form|input|select)(.*?)>#is', '&lt;/\\1\\2&gt;', $message);
@@ -425,12 +453,12 @@
     return $message;
   }
   
-  function strip_php($message)
+  public static function strip_php($message)
   {
     return RenderMan::destroy_javascript($message, true);
   }
   
-  function sanitize_html($text)
+  public static function sanitize_html($text)
   {
     $text = htmlspecialchars($text);
     $allowed_tags = Array('b', 'i', 'u', 'pre', 'code', 'tt', 'br', 'p', 'nowiki', '!--([\w\W]+)--');
@@ -449,7 +477,7 @@
    * @return string
    */
   
-  function parse_internal_links($text)
+  public static function parse_internal_links($text)
   {
     global $db, $session, $paths, $template, $plugins; // Common objects
     
@@ -503,7 +531,7 @@
    * [bar] => dolor sit amet
    */
   
-  function parse_template_vars($input)
+  public static function parse_template_vars($input)
   {
     if ( !preg_match('/^(\|[ ]*([A-z0-9_]+)([ ]*)=([ ]*)(.+?))*$/is', trim($input)) )
     {
@@ -570,7 +598,7 @@
    * </code>
    */
   
-  function include_templates($text)
+  public static function include_templates($text)
   {
     global $db, $session, $paths, $template, $plugins; // Common objects
     // $template_regex = "/\{\{([^\]]+?)((\n([ ]*?)[A-z0-9]+([ ]*?)=([ ]*?)(.+?))*)\}\}/is";
@@ -609,14 +637,25 @@
    * @param string $text
    * @param bool $strip_all_php - if true, strips all PHP regardless of user permissions. Else, strips PHP only if user level < USER_LEVEL_ADMIN.
    */
-  function preprocess_text($text, $strip_all_php = true, $sqlescape = true)
+  public static function preprocess_text($text, $strip_all_php = true, $sqlescape = true)
   {
     global $db, $session, $paths, $template, $plugins; // Common objects
     $random_id = md5( time() . mt_rand() );
     
-    $can_do_php = ( $session->get_permissions('php_in_pages') && !$strip_all_php );
+    $code = $plugins->setHook('render_sanitize_pre');
+    foreach ( $code as $cmd )
+    {
+      eval($cmd);
+    }
     
-    if ( !$can_do_php )
+    $can_do_php = ( $session->get_permissions('php_in_pages') && !$strip_all_php );
+    $can_do_html = $session->get_permissions('html_in_pages');
+    
+    if ( $can_do_html && !$can_do_php )
+    {
+      $text = preg_replace('#<(\?|\?php|%)(.*?)(\?|%)>#is', '&lt;\\1\\2\\3&gt;', $text);
+    }
+    else if ( !$can_do_html && !$can_do_php )
     {
       $text = sanitize_html($text, true);
       // If we can't do PHP, we can't do Javascript either.
@@ -641,10 +680,16 @@
       $text = str_replace('<nowiki>'.$nowiki[1][$i].'</nowiki>', '{NOWIKI:'.$random_id.':'.$i.'}', $text);
     }
     
-    $text = str_replace('~~~~~', date('G:i, j F Y (T)'), $text);
-    $text = str_replace('~~~~', "[[User:$session->username|$session->username]] ".date('G:i, j F Y (T)'), $text);
+    $text = str_replace('~~~~~', enano_date('G:i, j F Y (T)'), $text);
+    $text = str_replace('~~~~', "[[User:$session->username|$session->username]] ".enano_date('G:i, j F Y (T)'), $text);
     $text = str_replace('~~~', "[[User:$session->username|$session->username]] ", $text);
     
+    $code = $plugins->setHook('render_sanitize_post');
+    foreach ( $code as $cmd )
+    {
+      eval($cmd);
+    }
+    
     // Reinsert <nowiki> sections
     for($i=0;$i<$nw;$i++)
     {
@@ -664,7 +709,7 @@
     return $text;
   }
   
-  function smilieyize($text, $complete_urls = false)
+  public static function smilieyize($text, $complete_urls = false)
   {
     
     $random_id = md5( time() . mt_rand() );
@@ -736,7 +781,8 @@
     $keys = array_keys($smileys);
     foreach($keys as $k)
     {
-      $t = str_hex($k);
+      $t = hexencode($k, ' ', '');
+      $t = trim($t);
       $t = explode(' ', $t);
       $s = '';
       foreach($t as $b)
@@ -764,7 +810,7 @@
    * @return array key 0 is the escaped text, key 1 is the character tag
    * /
    
-  function escape_page_text($text)
+  public static function escape_page_text($text)
   {
     $char_tag = md5(microtime() . mt_rand());
     $text = str_replace("'",  "{APOS:$char_tag}",  $text);
@@ -781,7 +827,7 @@
    * @return string
    * /
    
-  function unescape_page_text($text, $char_tag)
+  public static function unescape_page_text($text, $char_tag)
   {
     $text = str_replace("{APOS:$char_tag}",  "'",  $text);
     $text = str_replace("{QUOT:$char_tag}",  '"',  $text);
@@ -796,7 +842,7 @@
    * @param $str2 string the second block of text
    * @return string
    */
-  function diff($str1, $str2)
+  public static function diff($str1, $str2)
   {
     global $db, $session, $paths, $template, $plugins; // Common objects
     $str1 = explode("\n", $str1);
@@ -813,7 +859,7 @@
    * @return string
    */
   
-  function process_image_tags($text, &$taglist)
+  public static function process_image_tags($text, &$taglist)
   {
     global $db, $session, $paths, $template, $plugins; // Common objects
     
@@ -822,7 +868,7 @@
     $taglist = array();
     
     // Wicked huh?
-    $regex = '/\[\[:' . $paths->nslist['File'] . '([\w\s0-9_\(\)!@%\^\+\|\.-]+?)((\|thumb)|(\|([0-9]+)x([0-9]+)))?(\|left|\|right)?(\|raw|\|(.+))?\]\]/i';
+    $regex = '/\[\[:' . str_replace('/', '\\/', preg_quote($paths->nslist['File'])) . '([\w\s0-9_\(\)!@%\^\+\|\.-]+?)((\|thumb)|(\|([0-9]+)x([0-9]+)))?(\|left|\|right)?(\|raw|\|(.+))?\]\]/i';
     
     preg_match_all($regex, $text, $matches);
     
@@ -965,7 +1011,7 @@
    * @param array The list of image tags created by RenderMan::process_image_tags()
    */
    
-  function process_imgtags_stage2($text, $taglist)
+  public static function process_imgtags_stage2($text, $taglist)
   {
     $s_delim = "\xFF";
     $f_delim = "\xFF";
--- a/includes/rijndael.php	Fri Feb 22 12:46:51 2008 -0500
+++ b/includes/rijndael.php	Fri Feb 22 12:51:53 2008 -0500
@@ -1,1099 +1,1083 @@
-<?php
-
-/**
- * Phijndael - an implementation of the AES encryption standard in PHP
- * Originally written by Fritz Schneider <fritz AT cd DOT ucsd DOT edu>
- * Ported to PHP by Dan Fuhry <dan AT enano DOT homelinux DOT org>
- * @package phijndael
- * @author Fritz Schneider
- * @author Dan Fuhry
- * @license BSD-style license
- */
-
-define ('ENC_HEX', 201);
-define ('ENC_BASE64', 202);
-define ('ENC_BINARY', 203);
-
-$_aes_objcache = array();
-
-class AESCrypt {
-  
-  var $debug = false;
-  var $mcrypt = false;
-  var $decrypt_cache = array();
-
-  // Rijndael parameters --  Valid values are 128, 192, or 256
-  
-  var $keySizeInBits = 128;
-  var $blockSizeInBits = 128;
-  
-  ///////  You shouldn't have to modify anything below this line except for
-  ///////  the function getRandomBytes().
-  //
-  // Note: in the following code the two dimensional arrays are indexed as
-  //       you would probably expect, as array[row][column]. The state arrays
-  //       are 2d arrays of the form state[4][Nb].
-  
-  
-  // The number of rounds for the cipher, indexed by [Nk][Nb]
-  var $roundsArray = Array(0,0,0,0,Array(0,0,0,0,10,0, 12,0, 14),0, 
-                               Array(0,0,0,0,12,0, 12,0, 14),0, 
-                               Array(0,0,0,0,14,0, 14,0, 14) );
-  
-  // The number of bytes to shift by in shiftRow, indexed by [Nb][row]
-  var $shiftOffsets = Array(0,0,0,0,Array(0,1, 2, 3),0,Array(0,1, 2, 3),0,Array(0,1, 3, 4) );
-  
-  // The round constants used in subkey expansion
-  var $Rcon = Array( 
-  0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 
-  0x40, 0x80, 0x1b, 0x36, 0x6c, 0xd8, 
-  0xab, 0x4d, 0x9a, 0x2f, 0x5e, 0xbc, 
-  0x63, 0xc6, 0x97, 0x35, 0x6a, 0xd4, 
-  0xb3, 0x7d, 0xfa, 0xef, 0xc5, 0x91 );
-  
-  // Precomputed lookup table for the SBox
-  var $SBox = Array(
-   99, 124, 119, 123, 242, 107, 111, 197,  48,   1, 103,  43, 254, 215, 171, 
-  118, 202, 130, 201, 125, 250,  89,  71, 240, 173, 212, 162, 175, 156, 164, 
-  114, 192, 183, 253, 147,  38,  54,  63, 247, 204,  52, 165, 229, 241, 113, 
-  216,  49,  21,   4, 199,  35, 195,  24, 150,   5, 154,   7,  18, 128, 226, 
-  235,  39, 178, 117,   9, 131,  44,  26,  27, 110,  90, 160,  82,  59, 214, 
-  179,  41, 227,  47, 132,  83, 209,   0, 237,  32, 252, 177,  91, 106, 203, 
-  190,  57,  74,  76,  88, 207, 208, 239, 170, 251,  67,  77,  51, 133,  69, 
-  249,   2, 127,  80,  60, 159, 168,  81, 163,  64, 143, 146, 157,  56, 245, 
-  188, 182, 218,  33,  16, 255, 243, 210, 205,  12,  19, 236,  95, 151,  68,  
-  23,  196, 167, 126,  61, 100,  93,  25, 115,  96, 129,  79, 220,  34,  42, 
-  144, 136,  70, 238, 184,  20, 222,  94,  11, 219, 224,  50,  58,  10,  73,
-    6,  36,  92, 194, 211, 172,  98, 145, 149, 228, 121, 231, 200,  55, 109, 
-  141, 213,  78, 169, 108,  86, 244, 234, 101, 122, 174,   8, 186, 120,  37,  
-   46,  28, 166, 180, 198, 232, 221, 116,  31,  75, 189, 139, 138, 112,  62, 
-  181, 102,  72,   3, 246,  14,  97,  53,  87, 185, 134, 193,  29, 158, 225,
-  248, 152,  17, 105, 217, 142, 148, 155,  30, 135, 233, 206,  85,  40, 223,
-  140, 161, 137,  13, 191, 230,  66, 104,  65, 153,  45,  15, 176,  84, 187,  
-   22 );
-  
-  // Precomputed lookup table for the inverse SBox
-  var $SBoxInverse = Array(
-   82,   9, 106, 213,  48,  54, 165,  56, 191,  64, 163, 158, 129, 243, 215, 
-  251, 124, 227,  57, 130, 155,  47, 255, 135,  52, 142,  67,  68, 196, 222, 
-  233, 203,  84, 123, 148,  50, 166, 194,  35,  61, 238,  76, 149,  11,  66, 
-  250, 195,  78,   8,  46, 161, 102,  40, 217,  36, 178, 118,  91, 162,  73, 
-  109, 139, 209,  37, 114, 248, 246, 100, 134, 104, 152,  22, 212, 164,  92, 
-  204,  93, 101, 182, 146, 108, 112,  72,  80, 253, 237, 185, 218,  94,  21,  
-   70,  87, 167, 141, 157, 132, 144, 216, 171,   0, 140, 188, 211,  10, 247, 
-  228,  88,   5, 184, 179,  69,   6, 208,  44,  30, 143, 202,  63,  15,   2, 
-  193, 175, 189,   3,   1,  19, 138, 107,  58, 145,  17,  65,  79, 103, 220, 
-  234, 151, 242, 207, 206, 240, 180, 230, 115, 150, 172, 116,  34, 231, 173,
-   53, 133, 226, 249,  55, 232,  28, 117, 223, 110,  71, 241,  26, 113,  29, 
-   41, 197, 137, 111, 183,  98,  14, 170,  24, 190,  27, 252,  86,  62,  75, 
-  198, 210, 121,  32, 154, 219, 192, 254, 120, 205,  90, 244,  31, 221, 168,
-   51, 136,   7, 199,  49, 177,  18,  16,  89,  39, 128, 236,  95,  96,  81,
-  127, 169,  25, 181,  74,  13,  45, 229, 122, 159, 147, 201, 156, 239, 160,
-  224,  59,  77, 174,  42, 245, 176, 200, 235, 187,  60, 131,  83, 153,  97, 
-   23,  43,   4, 126, 186, 119, 214,  38, 225, 105,  20,  99,  85,  33,  12,
-  125 );
-  
-  function AESCrypt($ks = 128, $bs = 128, $debug = false)
-  {
-    $this->__construct($ks, $bs, $debug);
-  }
-  
-  function __construct($ks = 128, $bs = 128, $debug = false)
-  {
-    $this->keySizeInBits = $ks;
-    $this->blockSizeInBits = $bs;
-    
-    // Use the Mcrypt library? This speeds things up dramatically.
-    if(defined('MCRYPT_RIJNDAEL_' . $ks) && defined('MCRYPT_ACCEL'))
-    {
-      eval('$mcb = MCRYPT_RIJNDAEL_' . $ks.';');
-      $bks = mcrypt_module_get_algo_block_size($mcb);
-      $bks = $bks * 8;
-      if ( $bks != $bs )
-      {
-        $mcb = false;
-        echo (string)$bks;
-      }
-    }
-    else
-    {
-      $mcb = false;
-    }
-      
-    $this->mcrypt = $mcb;
-    
-    // Cipher parameters ... do not change these
-    $this->Nk = $this->keySizeInBits / 32;
-    $this->Nb = $this->blockSizeInBits / 32;
-    $this->Nr = $this->roundsArray[$this->Nk][$this->Nb];
-    $this->debug = $debug;
-  }
-  
-  function singleton($key_size, $block_size)
-  {
-    global $_aes_objcache;
-    if ( isset($_aes_objcache["$key_size,$block_size"]) )
-    {
-      return $_aes_objcache["$key_size,$block_size"];
-    }
-    
-    $_aes_objcache["$key_size,$block_size"] = new AESCrypt($key_size, $block_size);
-    return $_aes_objcache["$key_size,$block_size"];
-  }
-  
-  // Error handler
-  
-  function trigger_error($text, $level = E_USER_NOTICE)
-  {
-    $bt = debug_backtrace();
-    $lastfunc =& $bt[1];
-    switch($level)
-    {
-      case E_USER_NOTICE:
-      default:
-        $desc = 'Notice';
-        break;
-      case E_USER_WARNING:
-        $desc = 'Warning';
-        break;
-      case E_USER_ERROR:
-        $desc = 'Fatal';
-        break;
-    }
-    ob_start();
-    if($this->debug || $level == E_USER_ERROR) echo "AES encryption: <b>{$desc}:</b> $text in {$lastfunc['file']} on line {$lastfunc['line']} in function {$lastfunc['function']}<br />";
-    if($this->debug)
-    {
-      //echo '<pre>'.enano_debug_print_backtrace(true).'</pre>';
-    }
-    ob_end_flush();
-    if($level == E_USER_ERROR)
-    {
-      echo '<p><b>This can sometimes happen if you are upgrading Enano to a new version and did not log out first.</b> <a href="'.$_SERVER['PHP_SELF'].'?do=diag&amp;sub=cookie_destroy">Click here</a> to force cookies to clear and try again. You will be logged out.</p>';
-      exit;
-    }
-  }
-  
-  function array_slice_js_compat($array, $start, $finish = 0)
-  {
-    $len = $finish - $start;
-    if($len < 0) $len = 0 - $len;
-    //if($this->debug) echo (string)$len . ' ';
-    //if(count($array) < $start + $len)
-    //  $this->trigger_error('Index out of range', E_USER_WARNING);
-    return array_slice($array, $start, $len);
-  }
-  
-  function concat($s1, $s2)
-  {
-    if(is_array($s1) && is_array($s2))
-      return array_merge($s1, $s2);
-    elseif( ( is_array($s1) && !is_array($s2) ) || ( !is_array($s1) && is_array($s2) ) )
-    {
-      $this->trigger_error('incompatible types - you can\'t combine a non-array with an array', E_USER_WARNING);
-      return false;
-    }
-    else
-      return $s1 . $s2;
-  }
-  
-  // This method circularly shifts the array left by the number of elements
-  // given in its parameter. It returns the resulting array and is used for 
-  // the ShiftRow step. Note that shift() and push() could be used for a more 
-  // elegant solution, but they require IE5.5+, so I chose to do it manually. 
-  
-  function cyclicShiftLeft($theArray, $positions) {
-    if(!is_int($positions))
-    {
-      $this->trigger_error('$positions is not an integer! Backtrace:<br /><pre>'.print_r(debug_backtrace(), true).'</pre>', E_USER_WARNING);
-      return false;
-    }
-    $second = array_slice($theArray, 0, $positions);
-    $first = array_slice($theArray, $positions);
-    $theArray = array_merge($first, $second);
-    return $theArray;
-  }
-  
-  // Multiplies the element "poly" of GF(2^8) by x. See the Rijndael spec.
-  
-  function xtime($poly) {
-    $poly <<= 1;
-    return (($poly & 0x100) ? ($poly ^ 0x11B) : ($poly));
-  }
-  
-  // Multiplies the two elements of GF(2^8) together and returns the result.
-  // See the Rijndael spec, but should be straightforward: for each power of
-  // the indeterminant that has a 1 coefficient in x, add y times that power
-  // to the result. x and y should be bytes representing elements of GF(2^8)
-  
-  function mult_GF256($x, $y) {
-    $result = 0;
-    
-    for ($bit = 1; $bit < 256; $bit *= 2, $y = $this->xtime($y)) {
-      if ($x & $bit) 
-        $result ^= $y;
-    }
-    return $result;
-  }
-  
-  // Performs the substitution step of the cipher. State is the 2d array of
-  // state information (see spec) and direction is string indicating whether
-  // we are performing the forward substitution ("encrypt") or inverse 
-  // substitution (anything else)
-  
-  function byteSub(&$state, $direction) {
-    //global $this->SBox, $this->SBoxInverse, $this->Nb;
-    if ($direction == "encrypt")           // Point S to the SBox we're using
-      $S =& $this->SBox;
-    else
-      $S =& $this->SBoxInverse;
-    for ($i = 0; $i < 4; $i++)           // Substitute for every byte in state
-      for ($j = 0; $j < $this->Nb; $j++)
-         $state[$i][$j] = $S[$state[$i][$j]];
-  }
-  
-  // Performs the row shifting step of the cipher.
-  
-  function shiftRow(&$state, $direction) {
-    //global $this->Nb, $this->shiftOffsets;
-    for ($i=1; $i<4; $i++)               // Row 0 never shifts
-      if ($direction == "encrypt")
-         $state[$i] = $this->cyclicShiftLeft($state[$i], $this->shiftOffsets[$this->Nb][$i]);
-      else
-         $state[$i] = $this->cyclicShiftLeft($state[$i], $this->Nb - $this->shiftOffsets[$this->Nb][$i]);
-  
-  }
-  
-  // Performs the column mixing step of the cipher. Most of these steps can
-  // be combined into table lookups on 32bit values (at least for encryption)
-  // to greatly increase the speed. 
-  
-  function mixColumn(&$state, $direction) {
-    //global $this->Nb;
-    $b = Array();                                  // Result of matrix multiplications
-    for ($j = 0; $j < $this->Nb; $j++) {                 // Go through each column...
-      for ($i = 0; $i < 4; $i++) {                 // and for each row in the column...
-        if ($direction == "encrypt")
-          $b[$i] = $this->mult_GF256($state[$i][$j], 2) ^ // perform mixing
-                   $this->mult_GF256($state[($i+1)%4][$j], 3) ^ 
-                   $state[($i+2)%4][$j] ^ 
-                   $state[($i+3)%4][$j];
-        else 
-          $b[$i] = $this->mult_GF256($state[$i][$j], 0xE) ^ 
-                   $this->mult_GF256($state[($i+1)%4][$j], 0xB) ^
-                   $this->mult_GF256($state[($i+2)%4][$j], 0xD) ^
-                   $this->mult_GF256($state[($i+3)%4][$j], 9);
-      }
-      for ($i = 0; $i < 4; $i++)          // Place result back into column
-        $state[$i][$j] = $b[$i];
-    }
-  }
-  
-  // Adds the current round key to the state information. Straightforward.
-  
-  function addRoundKey(&$state, $roundKey) {
-    //global $this->Nb;
-    for ($j = 0; $j < $this->Nb; $j++) {                      // Step through columns...
-      $state[0][$j] ^= ( $roundKey[$j] & 0xFF);         // and XOR
-      $state[1][$j] ^= (($roundKey[$j]>>8) & 0xFF);
-      $state[2][$j] ^= (($roundKey[$j]>>16) & 0xFF);
-      $state[3][$j] ^= (($roundKey[$j]>>24) & 0xFF);
-    }
-  }
-  
-  // This function creates the expanded key from the input (128/192/256-bit)
-  // key. The parameter key is an array of bytes holding the value of the key.
-  // The returned value is an array whose elements are the 32-bit words that 
-  // make up the expanded key.
-  
-  function keyExpansion($key) {
-    //global $this->keySizeInBits, $this->blockSizeInBits, $this->roundsArray, $this->Nk, $this->Nb, $this->Nr, $this->Nk, $this->SBox, $this->Rcon;
-    $expandedKey = Array();
-  
-    // in case the key size or parameters were changed...
-    $this->Nk = $this->keySizeInBits / 32;                   
-    $this->Nb = $this->blockSizeInBits / 32;
-    $this->Nr = $this->roundsArray[$this->Nk][$this->Nb];
-  
-    for ($j=0; $j < $this->Nk; $j++)     // Fill in input key first
-      $expandedKey[$j] = 
-        ($key[4*$j]) | ($key[4*$j+1]<<8) | ($key[4*$j+2]<<16) | ($key[4*$j+3]<<24);
-  
-    // Now walk down the rest of the array filling in expanded key bytes as
-    // per Rijndael's spec
-    for ($j = $this->Nk; $j < $this->Nb * ($this->Nr + 1); $j++) {    // For each word of expanded key
-      $temp = $expandedKey[$j - 1];
-      if ($j % $this->Nk == 0) 
-        $temp = ( ($this->SBox[($temp>>8) & 0xFF]) |
-                  ($this->SBox[($temp>>16) & 0xFF]<<8) |
-                  ($this->SBox[($temp>>24) & 0xFF]<<16) |
-                  ($this->SBox[$temp & 0xFF]<<24) ) ^ $this->Rcon[floor($j / $this->Nk) - 1];
-      elseif  ($this->Nk > 6 && $j % $this->Nk == 4)
-        $temp = ($this->SBox[($temp>>24) & 0xFF]<<24) |
-               ($this->SBox[($temp>>16) & 0xFF]<<16) |
-               ($this->SBox[($temp>>8) & 0xFF]<<8) |
-               ($this->SBox[ $temp & 0xFF]);
-      $expandedKey[$j] = $expandedKey[$j-$this->Nk] ^ $temp;
-    }
-    return $expandedKey;
-  }
-  
-  // Rijndael's round functions... 
-  
-  function RijndaelRound(&$state, $roundKey) {
-    $this->byteSub($state, "encrypt");
-    $this->shiftRow($state, "encrypt");
-    $this->mixColumn($state, "encrypt");
-    $this->addRoundKey($state, $roundKey);
-  }
-  
-  function InverseRijndaelRound(&$state, $roundKey) {
-    $this->addRoundKey($state, $roundKey);
-    $this->mixColumn($state, "decrypt");
-    $this->shiftRow($state, "decrypt");
-    $this->byteSub($state, "decrypt");
-  }
-  
-  function FinalRijndaelRound(&$state, $roundKey) {
-    $this->byteSub($state, "encrypt");
-    $this->shiftRow($state, "encrypt");
-    $this->addRoundKey($state, $roundKey);
-  }
-  
-  function InverseFinalRijndaelRound(&$state, $roundKey){
-    $this->addRoundKey($state, $roundKey);
-    $this->shiftRow($state, "decrypt");
-    $this->byteSub($state, "decrypt");  
-  }
-  
-  // encrypt is the basic encryption function. It takes parameters
-  // block, an array of bytes representing a plaintext block, and expandedKey,
-  // an array of words representing the expanded key previously returned by
-  // keyExpansion(). The ciphertext block is returned as an array of bytes.
-  
-  function cryptBlock($block, $expandedKey) {
-    //global $this->blockSizeInBits, $this->Nb, $this->Nr;
-    $t=count($block)*8;
-    if (!is_array($block) || count($block)*8 != $this->blockSizeInBits)
-    {
-      $this->trigger_error('block is bad or block size is wrong<pre>'.print_r($block, true).'</pre><p>Aiming for size '.$this->blockSizeInBits.', got '.$t.'.', E_USER_WARNING); 
-      return false;
-    }
-    if (!$expandedKey)
-      return;
-  
-    $block = $this->packBytes($block);
-    $this->addRoundKey($block, $expandedKey);
-    for ($i=1; $i<$this->Nr; $i++) 
-      $this->RijndaelRound($block, $this->array_slice_js_compat($expandedKey, $this->Nb*$i, $this->Nb*($i+1)));
-    $this->FinalRijndaelRound($block, $this->array_slice_js_compat($expandedKey, $this->Nb*$this->Nr));
-    $ret = $this->unpackBytes($block);
-    return $ret;
-  }
-  
-  // decrypt is the basic decryption function. It takes parameters
-  // block, an array of bytes representing a ciphertext block, and expandedKey,
-  // an array of words representing the expanded key previously returned by
-  // keyExpansion(). The decrypted block is returned as an array of bytes.
-  
-  function unCryptBlock($block, $expandedKey) {
-    $t = count($block)*8;
-    if (!is_array($block) || count($block)*8 != $this->blockSizeInBits)
-    {
-      $this->trigger_error('$block is not a valid rijndael-block array: '.$this->byteArrayToHex($block).'<pre>'.print_r($block, true).'</pre><p>Block size is '.$t.', should be '.$this->blockSizeInBits.'</p>', E_USER_WARNING);
-      return false;
-    }
-    if (!$expandedKey)
-    {
-      $this->trigger_error('$expandedKey is invalid', E_USER_WARNING);
-      return false;
-    }
-  
-    $block = $this->packBytes($block);
-    $this->InverseFinalRijndaelRound($block, $this->array_slice_js_compat($expandedKey, $this->Nb*$this->Nr)); 
-    for ($i = $this->Nr - 1; $i>0; $i--) 
-    {
-      $this->InverseRijndaelRound($block, $this->array_slice_js_compat($expandedKey, $this->Nb*$i, $this->Nb*($i+1)));
-    }
-    $this->addRoundKey($block, $expandedKey);
-    $ret = $this->unpackBytes($block);
-    if(!is_array($ret))
-    {
-      $this->trigger_error('$ret is not an array', E_USER_WARNING);
-    }
-    return $ret;
-  }
-  
-  // This method takes a byte array (byteArray) and converts it to a string by
-  // applying String.fromCharCode() to each value and concatenating the result.
-  // The resulting string is returned. Note that this function SKIPS zero bytes
-  // under the assumption that they are padding added in formatPlaintext().
-  // Obviously, do not invoke this method on raw data that can contain zero
-  // bytes. It is really only appropriate for printable ASCII/Latin-1 
-  // values. Roll your own function for more robust functionality :)
-  
-  function byteArrayToString($byteArray) {
-    $result = "";
-    for($i=0; $i<count($byteArray); $i++)
-      if ($byteArray[$i] != 0) 
-        $result .= chr($byteArray[$i]);
-    return $result;
-  }
-  
-  // This function takes an array of bytes (byteArray) and converts them
-  // to a hexadecimal string. Array element 0 is found at the beginning of 
-  // the resulting string, high nibble first. Consecutive elements follow
-  // similarly, for example [16, 255] --> "10ff". The function returns a 
-  // string.
-  
-  /*
-  function byteArrayToHex($byteArray) {
-    $result = "";
-    if (!$byteArray)
-      return;
-    for ($i=0; $i<count($byteArray); $i++)
-      $result .= (($byteArray[$i]<16) ? "0" : "") + toString($byteArray[$i]); // magic number here is 16, not sure how to handle this...
-  
-    return $result;
-  }
-  */
-  function byteArrayToHex($arr)
-  {
-    $ret = '';
-    foreach($arr as $a)
-    {
-      $nibble = (string)dechex(intval($a));
-      if(strlen($nibble) == 1) $nibble = '0' . $nibble;
-      $ret .= $nibble;
-    }
-    return $ret;
-  }
-  
-  // PHP equivalent of Javascript's toString()
-  function toString($bool)
-  {
-    if(is_bool($bool))
-      return ($bool) ? 'true' : 'false';
-    elseif(is_array($bool))
-      return implode(',', $bool);
-    else
-      return (string)$bool;
-  }
-  
-  // This function converts a string containing hexadecimal digits to an 
-  // array of bytes. The resulting byte array is filled in the order the
-  // values occur in the string, for example "10FF" --> [16, 255]. This
-  // function returns an array. 
-  
-  /*
-  function hexToByteArray($hexString) {
-    $byteArray = Array();
-    if (strlen($hexString) % 2)             // must have even length
-      return;
-    if (strstr($hexString, "0x") == $hexString || strstr($hexString, "0X") == $hexString)
-      $hexString = substr($hexString, 2);
-    for ($i = 0; $i<strlen($hexString); $i++,$i++) 
-      $byteArray[floor($i/2)] = intval(substr($hexString, $i, 2)); // again, that strange magic number: 16
-    return $byteArray;
-  }
-  */
-  function hexToByteArray($str)
-  {
-    if(substr($str, 0, 2) == '0x' || substr($str, 0, 2) == '0X')
-      $str = substr($str, 2);
-    $arr = Array();
-    $str = $this->enano_str_split($str, 2);
-    foreach($str as $s)
-    {
-      $arr[] = intval(hexdec($s));
-    }
-    return $arr;
-  }
-  
-  // This function packs an array of bytes into the four row form defined by
-  // Rijndael. It assumes the length of the array of bytes is divisible by
-  // four. Bytes are filled in according to the Rijndael spec (starting with
-  // column 0, row 0 to 3). This function returns a 2d array.
-  
-  function packBytes($octets) {
-    $state = Array();
-    if (!$octets || count($octets) % 4)
-      return;
-  
-    $state[0] = Array(); $state[1] = Array(); 
-    $state[2] = Array(); $state[3] = Array();
-    for ($j=0; $j<count($octets); $j = $j+4) {
-       $state[0][$j/4] = $octets[$j];
-       $state[1][$j/4] = $octets[$j+1];
-       $state[2][$j/4] = $octets[$j+2];
-       $state[3][$j/4] = $octets[$j+3];
-    }
-    return $state;
-  }
-  
-  // This function unpacks an array of bytes from the four row format preferred
-  // by Rijndael into a single 1d array of bytes. It assumes the input "packed"
-  // is a packed array. Bytes are filled in according to the Rijndael spec. 
-  // This function returns a 1d array of bytes.
-  
-  function unpackBytes($packed) {
-    $result = Array();
-    for ($j=0; $j<count($packed[0]); $j++) {
-      $result[] = $packed[0][$j];
-      $result[] = $packed[1][$j];
-      $result[] = $packed[2][$j];
-      $result[] = $packed[3][$j];
-    }
-    return $result;
-  }
-  
-  function charCodeAt($str, $i)
-  {
-    return ord(substr($str, $i, 1));
-  }
-  
-  function fromCharCode($str)
-  {
-    return chr($str);
-  }
-  
-  // This function takes a prospective plaintext (string or array of bytes)
-  // and pads it with zero bytes if its length is not a multiple of the block 
-  // size. If plaintext is a string, it is converted to an array of bytes
-  // in the process. The type checking can be made much nicer using the 
-  // instanceof operator, but this operator is not available until IE5.0 so I 
-  // chose to use the heuristic below. 
-  
-  function formatPlaintext($plaintext) {
-    //global $this->blockSizeInBits;
-    $bpb = $this->blockSizeInBits / 8;               // bytes per block
-  
-    // if primitive string or String instance
-    if (is_string($plaintext)) {
-      $plaintext = $this->enano_str_split($plaintext);
-      // Unicode issues here (ignoring high byte)
-      for ($i=0; $i<sizeof($plaintext); $i++)
-        $plaintext[$i] = $this->charCodeAt($plaintext[$i], 0) & 0xFF;
-    } 
-  
-    for ($i = $bpb - (sizeof($plaintext) % $bpb); $i > 0 && $i < $bpb; $i--) 
-      $plaintext[] = 0;
-    
-    return $plaintext;
-  }
-  
-  // Returns an array containing "howMany" random bytes. YOU SHOULD CHANGE THIS
-  // TO RETURN HIGHER QUALITY RANDOM BYTES IF YOU ARE USING THIS FOR A "REAL"
-  // APPLICATION. (edit: done, mt_rand() is relatively secure)
-  
-  function getRandomBytes($howMany) {
-    $bytes = Array();
-    for ($i=0; $i<$howMany; $i++)
-      $bytes[$i] = mt_rand(0, 255);
-    return $bytes;
-  }
-  
-  // rijndaelEncrypt(plaintext, key, mode)
-  // Encrypts the plaintext using the given key and in the given mode. 
-  // The parameter "plaintext" can either be a string or an array of bytes. 
-  // The parameter "key" must be an array of key bytes. If you have a hex 
-  // string representing the key, invoke hexToByteArray() on it to convert it 
-  // to an array of bytes. The third parameter "mode" is a string indicating
-  // the encryption mode to use, either "ECB" or "CBC". If the parameter is
-  // omitted, ECB is assumed.
-  // 
-  // An array of bytes representing the cihpertext is returned. To convert 
-  // this array to hex, invoke byteArrayToHex() on it. If you are using this 
-  // "for real" it is a good idea to change the function getRandomBytes() to 
-  // something that returns truly random bits.
-  
-  function rijndaelEncrypt($plaintext, $key, $mode = 'ECB') {
-    //global $this->blockSizeInBits, $this->keySizeInBits;
-    $bpb = $this->blockSizeInBits / 8;          // bytes per block
-    // var ct;                                 // ciphertext
-  
-    if($mode == 'CBC')
-    {
-      if (!is_string($plaintext) || !is_array($key))
-      {
-        $this->trigger_error('In CBC mode the first and second parameters should be strings', E_USER_WARNING);
-        return false;
-      }
-    } else {
-      if (!is_array($plaintext) || !is_array($key))
-      {
-        $this->trigger_error('In ECB mode the first and second parameters should be byte arrays', E_USER_WARNING);
-        return false;
-      }
-    }
-    if (sizeof($key)*8 != $this->keySizeInBits)
-    {
-      $this->trigger_error('The key needs to be '. ( $this->keySizeInBits / 8 ) .' bytes in length', E_USER_WARNING);
-      return false;
-    }
-    if ($mode == "CBC")
-      $ct = $this->getRandomBytes($bpb);             // get IV
-    else {
-      $mode = "ECB";
-      $ct = Array();
-    }
-    
-    // convert plaintext to byte array and pad with zeros if necessary. 
-    $plaintext = $this->formatPlaintext($plaintext);
-    
-    $expandedKey = $this->keyExpansion($key);
-    
-    for ($block=0; $block<sizeof($plaintext) / $bpb; $block++) {
-      $aBlock = $this->array_slice_js_compat($plaintext, $block*$bpb, ($block+1)*$bpb);
-      if ($mode == "CBC")
-      {
-        for ($i=0; $i<$bpb; $i++)
-        {
-          $aBlock[$i] ^= $ct[$block*$bpb + $i];
-        }
-      }
-      $cp = $this->cryptBlock($aBlock, $expandedKey);
-      $ct = $this->concat($ct, $cp);
-    }
-  
-    return $ct;
-  }
-  
-  // rijndaelDecrypt(ciphertext, key, mode)
-  // Decrypts the using the given key and mode. The parameter "ciphertext" 
-  // must be an array of bytes. The parameter "key" must be an array of key 
-  // bytes. If you have a hex string representing the ciphertext or key, 
-  // invoke hexToByteArray() on it to convert it to an array of bytes. The
-  // parameter "mode" is a string, either "CBC" or "ECB".
-  // 
-  // An array of bytes representing the plaintext is returned. To convert 
-  // this array to a hex string, invoke byteArrayToHex() on it. To convert it 
-  // to a string of characters, you can use byteArrayToString().
-  
-  function rijndaelDecrypt($ciphertext, $key, $mode = 'ECB') {
-    //global $this->blockSizeInBits, $this->keySizeInBits;
-    $bpb = $this->blockSizeInBits / 8;          // bytes per block
-    $pt = Array();                   // plaintext array
-    // $aBlock;                             // a decrypted block
-    // $block;                              // current block number
-  
-    if (!$ciphertext)
-    {
-      $this->trigger_error('$ciphertext should be a byte array', E_USER_WARNING);
-      return false;
-    }
-    if(  !is_array($key) )
-    {
-      $this->trigger_error('$key should be a byte array', E_USER_WARNING);
-      return false;
-    }
-    if( is_string($ciphertext) )
-    {
-      $this->trigger_error('$ciphertext should be a byte array', E_USER_WARNING);
-      return false;
-    }
-    if (sizeof($key)*8 != $this->keySizeInBits)
-    {
-      $this->trigger_error('Encryption key is the wrong length', E_USER_WARNING);
-      return false;
-    }
-    if (!$mode)
-      $mode = "ECB";                         // assume ECB if mode omitted
-  
-    $expandedKey = $this->keyExpansion($key);
-   
-    // work backwards to accomodate CBC mode 
-    for ($block=(sizeof($ciphertext) / $bpb)-1; $block>0; $block--)
-    {
-      if( ( $block*$bpb ) + ( ($block+1)*$bpb ) > count($ciphertext) )
-      {
-        //$this->trigger_error('$ciphertext index out of bounds', E_USER_ERROR);
-      }
-      $current_block = $this->array_slice_js_compat($ciphertext, $block*$bpb, ($block+1)*$bpb);
-      if(count($current_block) * 8 != $this->blockSizeInBits)
-      {
-        // $c=count($current_block)*8;
-        // $this->trigger_error('We got a '.$c.'-bit block, instead of '.$this->blockSizeInBits.'', E_USER_ERROR);
-      }
-      $aBlock = $this->uncryptBlock($current_block, $expandedKey);
-      if(!$aBlock)
-      {
-        $this->trigger_error('Shared block decryption routine returned false', E_USER_WARNING);
-        return false;
-      }
-      if ($mode == "CBC")
-        for ($i=0; $i<$bpb; $i++) 
-          $pt[($block-1)*$bpb + $i] = $aBlock[$i] ^ $ciphertext[($block-1)*$bpb + $i];
-      else
-        $pt = $this->concat($aBlock, $pt);
-    }
-  
-    // do last block if ECB (skips the IV in CBC)
-    if ($mode == "ECB")
-    {
-      $x = $this->uncryptBlock($this->array_slice_js_compat($ciphertext, 0, $bpb), $expandedKey);
-      if(!$x)
-      {
-        $this->trigger_error('ECB block decryption routine returned false', E_USER_WARNING);
-        return false;
-      }
-      $pt = $this->concat($x, $pt);
-      if(!$pt)
-      {
-        $this->trigger_error('ECB concatenation routine returned false', E_USER_WARNING);
-        return false;
-      }
-    }
-  
-    return $pt;
-  }
-  
-  /**
-   * Wrapper for encryption.
-   * @param string $text the text to encrypt
-   * @param string $key the raw binary key to encrypt with
-   * @param int $return_encoding optional - can be ENC_BINARY, ENC_HEX or ENC_BASE64
-   */
-   
-  function encrypt($text, $key, $return_encoding = ENC_HEX)
-  {
-    if ( $text == '' )
-      return '';
-    if ( $this->mcrypt && $this->blockSizeInBits == mcrypt_module_get_algo_block_size(eval('return MCRYPT_RIJNDAEL_'.$this->keySizeInBits.';')) )
-    {
-      $iv_size = mcrypt_get_iv_size($this->mcrypt, MCRYPT_MODE_ECB);
-      $iv = mcrypt_create_iv($iv_size, MCRYPT_RAND);
-      $cryptext = mcrypt_encrypt($this->mcrypt, $key, $text, MCRYPT_MODE_ECB, $iv);
-      switch($return_encoding)
-      {
-        case ENC_HEX:
-        default:
-          $cryptext = $this->strtohex($cryptext);
-          break;
-        case ENC_BINARY:
-          $cryptext = $cryptext;
-          break;
-        case ENC_BASE64:
-          $cryptext = base64_encode($cryptext);
-          break;
-      }
-    }
-    else
-    {
-      $key = $this->prepare_string($key);
-      $text = $this->prepare_string($text);
-      $cryptext = $this->rijndaelEncrypt($text, $key, 'ECB');
-      if(!is_array($cryptext))
-      {
-        echo 'Warning: encryption failed for string: '.print_r($text,true).'<br />';
-        return false;
-      }
-      switch($return_encoding)
-      {
-        case ENC_HEX:
-        default:
-          $cryptext = $this->byteArrayToHex($cryptext);
-          break;
-        case ENC_BINARY:
-          $cryptext = $this->byteArrayToString($cryptext);
-          break;
-        case ENC_BASE64:
-          $cryptext = base64_encode($this->byteArrayToString($cryptext));
-          break;
-      }
-    }
-    return $cryptext;
-  }
-  
-  /**
-   * Wrapper for decryption.
-   * @param string $text the encrypted text
-   * @param string $key the raw binary key used to encrypt the text
-   * @param int $input_encoding the encoding used for the encrypted string. Can be ENC_BINARY, ENC_HEX, or ENC_BASE64.
-   * @return string
-   */
-   
-  function decrypt($text, $key, $input_encoding = ENC_HEX)
-  {
-    if ( $text == '' )
-      return '';
-    $text_orig = $text;
-    if ( isset($this->decrypt_cache[$key]) && is_array($this->decrypt_cache[$key]) )
-    {
-      if ( isset($this->decrypt_cache[$key][$text]) )
-      {
-        return $this->decrypt_cache[$key][$text];
-      }
-    }
-    switch($input_encoding)
-    {
-      case ENC_BINARY:
-      default:
-        break;
-      case ENC_HEX:
-        $text = $this->hextostring($text);
-        break;
-      case ENC_BASE64:
-        $text = base64_decode($text);
-        break;
-    }
-    //$mod = strlen($text) % $this->blockSizeInBits;
-    //if($mod != 96)
-      //die('modulus check failed: '.$mod);
-    if ( $this->mcrypt )
-    {
-      $iv_size = mcrypt_get_iv_size($this->mcrypt, MCRYPT_MODE_ECB);
-      $iv = mcrypt_create_iv($iv_size, MCRYPT_RAND);
-      $dypt = mcrypt_decrypt($this->mcrypt, $key, $text, MCRYPT_MODE_ECB, $iv);
-    }
-    else
-    {
-      $etext = $this->prepare_string($text);
-      $ekey  = $this->prepare_string($key);
-      $mod = count($etext) % $this->blockSizeInBits;
-      $dypt = $this->rijndaelDecrypt($etext, $ekey, 'ECB');
-      if(!$dypt)
-      {
-        echo '<pre>'.print_r($dypt, true).'</pre>';
-        $this->trigger_error('Rijndael main decryption routine failed', E_USER_ERROR);
-      }
-      $dypt = $this->byteArrayToString($dypt);
-    }
-    if ( !isset($this->decrypt_cache[$key]) )
-      $this->decrypt_cache[$key] = array();
-    
-    $this->decrypt_cache[$key][$text_orig] = $dypt;
-    
-    return $dypt;
-  }
-  
-  /**
-   * Enano-ese equivalent of str_split() which is only found in PHP5
-   * @param $text string the text to split
-   * @param $inc int size of each block
-   * @return array
-   */
-   
-  function enano_str_split($text, $inc = 1)
-  {
-    if($inc < 1) return false;
-    if($inc >= strlen($text)) return Array($text);
-    $len = ceil(strlen($text) / $inc);
-    $ret = Array();
-    for($i=0;$i<strlen($text);$i=$i+$inc)
-    {
-      $ret[] = substr($text, $i, $inc);
-    }
-    return $ret;
-  }
-  
-  /**
-   * Generates a random key suitable for encryption
-   * @param int $len the length of the key, in bytes
-   * @return string a BINARY key
-   */
-  
-  function randkey($len = 32)
-  {
-    $key = '';
-    for($i=0;$i<$len;$i++)
-    {
-      $key .= chr(mt_rand(0, 255));
-    }
-    if ( file_exists('/dev/urandom') && is_readable('/dev/urandom') )
-    {
-      // Let's use something a little more secure
-      $ur = @fopen('/dev/urandom', 'r');
-      if ( !$ur )
-        return $key;
-      $ukey = @fread($ur, $len);
-      fclose($ur);
-      if ( strlen($ukey) != $len )
-        return $key;
-      return $ukey;
-    }
-    return $key;
-  }
-  
-  /*
-  function byteArrayToString($arr)
-  {
-    if(!is_array($arr))
-    {
-      $this->trigger_error('First parameter should be an array', E_USER_WARNING);
-      return false;
-    }
-    $ret = '';
-    foreach($arr as $a)
-    {
-      if($a != 0) $ret .= chr($a);
-    }
-    return $ret;
-  }
-  */
-  
-  function strtohex($str)
-  {
-    $str = $this->enano_str_split($str);
-    $ret = '';
-    foreach($str as $s)
-    {
-      $chr = dechex(ord($s));
-      if(strlen($chr) < 2) $chr = '0' . $chr;
-      $ret .= $chr;
-    }
-    return $ret;
-  }
-  
-  function gen_readymade_key()
-  {
-    $key = $this->strtohex($this->randkey($this->keySizeInBits / 8));
-    return $key;
-  }
-  
-  function prepare_string($text)
-  {
-    $ret = $this->hexToByteArray($this->strtohex($text));
-    if(count($ret) != strlen($text))
-    {
-      die('Could not convert string "' . $text . '" to hex byte array for encryption');
-    }
-    return $ret;
-  }
-  
-  /**
-   * Decodes a hex string.
-   * @param string $hex The hex code to decode
-   * @return string
-   */
-  
-  function hextostring($hex)
-  {
-    $hex = $this->enano_str_split($hex, 2);
-    $bin_key = '';
-    foreach($hex as $nibble)
-    {
-      $byte = chr(hexdec($nibble));
-      $bin_key .= $byte;
-    }
-    return $bin_key;
-  }
-}
-
-/**
- * XXTEA encryption arithmetic library.
- *
- * Copyright (C) 2006 Ma Bingyao <andot@ujn.edu.cn>
- * Version:      1.5
- * LastModified: Dec 5, 2006
- * This library is free.  You can redistribute it and/or modify it.
- * 
- * From dandaman32: I am treating this code as GPL, as implied by the license statement above.
- */
-class TEACrypt extends AESCrypt {
-  function long2str($v, $w) {
-      $len = count($v);
-      $n = ($len - 1) << 2;
-      if ($w) {
-          $m = $v[$len - 1];
-          if (($m < $n - 3) || ($m > $n)) return false;
-          $n = $m;
-      }
-      $s = array();
-      for ($i = 0; $i < $len; $i++) {
-          $s[$i] = pack("V", $v[$i]);
-      }
-      if ($w) {
-          return substr(join('', $s), 0, $n);
-      }
-      else {
-          return join('', $s);
-      }
-  }
-   
-  function str2long($s, $w) {
-      $v = unpack("V*", $s. str_repeat("\0", (4 - strlen($s) % 4) & 3));
-      $v = array_values($v);
-      if ($w) {
-          $v[count($v)] = strlen($s);
-      }
-      return $v;
-  }
-   
-  function int32($n) {
-      while ($n >= 2147483648) $n -= 4294967296;
-      while ($n <= -2147483649) $n += 4294967296;
-      return (int)$n;
-  }
-   
-  // The third parameter is to ensure compatibility with php 6.0-dev
-  function encrypt($str, $key, $unused = ENC_HEX) {
-      if ($str == "")
-      {
-          return "";
-      }
-      $v = $this->str2long($str, true);
-      $k = $this->str2long($key, false);
-      if (count($k) < 4) {
-          for ($i = count($k); $i < 4; $i++) {
-              $k[$i] = 0;
-          }
-      }
-      $n = count($v) - 1;
-   
-      $z = $v[$n];
-      $y = $v[0];
-      $delta = 0x9E3779B9;
-      $q = floor(6 + 52 / ($n + 1));
-      $sum = 0;
-      while (0 < $q--) {
-          $sum = $this->int32($sum + $delta);
-          $e = $sum >> 2 & 3;
-          for ($p = 0; $p < $n; $p++) {
-              $y = $v[$p + 1];
-              $mx = $this->int32((($z >> 5 & 0x07ffffff) ^ $y << 2) + (($y >> 3 & 0x1fffffff) ^ $z << 4)) ^ $this->int32(($sum ^ $y) + ($k[$p & 3 ^ $e] ^ $z));
-              $z = $v[$p] = $this->int32($v[$p] + $mx);
-          }
-          $y = $v[0];
-          $mx = $this->int32((($z >> 5 & 0x07ffffff) ^ $y << 2) + (($y >> 3 & 0x1fffffff) ^ $z << 4)) ^ $this->int32(($sum ^ $y) + ($k[$p & 3 ^ $e] ^ $z));
-          $z = $v[$n] = $this->int32($v[$n] + $mx);
-      }
-      return $this->long2str($v, false);
-  }
-   
-  // The third parameter is to ensure compatibility with php 6.0-dev
-  function decrypt($str, $key, $unused = ENC_HEX) {
-      if ($str == "") {
-          return "";
-      }
-      $v = $this->str2long($str, false);
-      $k = $this->str2long($key, false);
-      if (count($k) < 4) {
-          for ($i = count($k); $i < 4; $i++) {
-              $k[$i] = 0;
-          }
-      }
-      $n = count($v) - 1;
-   
-      $z = $v[$n];
-      $y = $v[0];
-      $delta = 0x9E3779B9;
-      $q = floor(6 + 52 / ($n + 1));
-      $sum = $this->int32($q * $delta);
-      while ($sum != 0) {
-          $e = $sum >> 2 & 3;
-          for ($p = $n; $p > 0; $p--) {
-              $z = $v[$p - 1];
-              $mx = $this->int32((($z >> 5 & 0x07ffffff) ^ $y << 2) + (($y >> 3 & 0x1fffffff) ^ $z << 4)) ^ $this->int32(($sum ^ $y) + ($k[$p & 3 ^ $e] ^ $z));
-              $y = $v[$p] = $this->int32($v[$p] - $mx);
-          }
-          $z = $v[$n];
-          $mx = $this->int32((($z >> 5 & 0x07ffffff) ^ $y << 2) + (($y >> 3 & 0x1fffffff) ^ $z << 4)) ^ $this->int32(($sum ^ $y) + ($k[$p & 3 ^ $e] ^ $z));
-          $y = $v[0] = $this->int32($v[0] - $mx);
-          $sum = $this->int32($sum - $delta);
-      }
-      return $this->long2str($v, true);
-  }
-}
-
-?>
+<?php
+
+/**
+ * Phijndael - an implementation of the AES encryption standard in PHP
+ * Originally written by Fritz Schneider <fritz AT cd DOT ucsd DOT edu>
+ * Ported to PHP by Dan Fuhry <dan AT enano DOT homelinux DOT org>
+ * @package phijndael
+ * @author Fritz Schneider
+ * @author Dan Fuhry
+ * @license BSD-style license
+ */
+
+define ('ENC_BASE64', 202);
+define ('ENC_BINARY', 203);
+
+$_aes_objcache = array();
+
+class AESCrypt {
+  
+  var $debug = false;
+  var $mcrypt = false;
+  var $decrypt_cache = array();
+
+  // Rijndael parameters --  Valid values are 128, 192, or 256
+  
+  var $keySizeInBits = 128;
+  var $blockSizeInBits = 128;
+  
+  ///////  You shouldn't have to modify anything below this line except for
+  ///////  the function getRandomBytes().
+  //
+  // Note: in the following code the two dimensional arrays are indexed as
+  //       you would probably expect, as array[row][column]. The state arrays
+  //       are 2d arrays of the form state[4][Nb].
+  
+  
+  // The number of rounds for the cipher, indexed by [Nk][Nb]
+  var $roundsArray = Array(0,0,0,0,Array(0,0,0,0,10,0, 12,0, 14),0, 
+                               Array(0,0,0,0,12,0, 12,0, 14),0, 
+                               Array(0,0,0,0,14,0, 14,0, 14) );
+  
+  // The number of bytes to shift by in shiftRow, indexed by [Nb][row]
+  var $shiftOffsets = Array(0,0,0,0,Array(0,1, 2, 3),0,Array(0,1, 2, 3),0,Array(0,1, 3, 4) );
+  
+  // The round constants used in subkey expansion
+  var $Rcon = Array( 
+  0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 
+  0x40, 0x80, 0x1b, 0x36, 0x6c, 0xd8, 
+  0xab, 0x4d, 0x9a, 0x2f, 0x5e, 0xbc, 
+  0x63, 0xc6, 0x97, 0x35, 0x6a, 0xd4, 
+  0xb3, 0x7d, 0xfa, 0xef, 0xc5, 0x91 );
+  
+  // Precomputed lookup table for the SBox
+  var $SBox = Array(
+   99, 124, 119, 123, 242, 107, 111, 197,  48,   1, 103,  43, 254, 215, 171, 
+  118, 202, 130, 201, 125, 250,  89,  71, 240, 173, 212, 162, 175, 156, 164, 
+  114, 192, 183, 253, 147,  38,  54,  63, 247, 204,  52, 165, 229, 241, 113, 
+  216,  49,  21,   4, 199,  35, 195,  24, 150,   5, 154,   7,  18, 128, 226, 
+  235,  39, 178, 117,   9, 131,  44,  26,  27, 110,  90, 160,  82,  59, 214, 
+  179,  41, 227,  47, 132,  83, 209,   0, 237,  32, 252, 177,  91, 106, 203, 
+  190,  57,  74,  76,  88, 207, 208, 239, 170, 251,  67,  77,  51, 133,  69, 
+  249,   2, 127,  80,  60, 159, 168,  81, 163,  64, 143, 146, 157,  56, 245, 
+  188, 182, 218,  33,  16, 255, 243, 210, 205,  12,  19, 236,  95, 151,  68,  
+  23,  196, 167, 126,  61, 100,  93,  25, 115,  96, 129,  79, 220,  34,  42, 
+  144, 136,  70, 238, 184,  20, 222,  94,  11, 219, 224,  50,  58,  10,  73,
+    6,  36,  92, 194, 211, 172,  98, 145, 149, 228, 121, 231, 200,  55, 109, 
+  141, 213,  78, 169, 108,  86, 244, 234, 101, 122, 174,   8, 186, 120,  37,  
+   46,  28, 166, 180, 198, 232, 221, 116,  31,  75, 189, 139, 138, 112,  62, 
+  181, 102,  72,   3, 246,  14,  97,  53,  87, 185, 134, 193,  29, 158, 225,
+  248, 152,  17, 105, 217, 142, 148, 155,  30, 135, 233, 206,  85,  40, 223,
+  140, 161, 137,  13, 191, 230,  66, 104,  65, 153,  45,  15, 176,  84, 187,  
+   22 );
+  
+  // Precomputed lookup table for the inverse SBox
+  var $SBoxInverse = Array(
+   82,   9, 106, 213,  48,  54, 165,  56, 191,  64, 163, 158, 129, 243, 215, 
+  251, 124, 227,  57, 130, 155,  47, 255, 135,  52, 142,  67,  68, 196, 222, 
+  233, 203,  84, 123, 148,  50, 166, 194,  35,  61, 238,  76, 149,  11,  66, 
+  250, 195,  78,   8,  46, 161, 102,  40, 217,  36, 178, 118,  91, 162,  73, 
+  109, 139, 209,  37, 114, 248, 246, 100, 134, 104, 152,  22, 212, 164,  92, 
+  204,  93, 101, 182, 146, 108, 112,  72,  80, 253, 237, 185, 218,  94,  21,  
+   70,  87, 167, 141, 157, 132, 144, 216, 171,   0, 140, 188, 211,  10, 247, 
+  228,  88,   5, 184, 179,  69,   6, 208,  44,  30, 143, 202,  63,  15,   2, 
+  193, 175, 189,   3,   1,  19, 138, 107,  58, 145,  17,  65,  79, 103, 220, 
+  234, 151, 242, 207, 206, 240, 180, 230, 115, 150, 172, 116,  34, 231, 173,
+   53, 133, 226, 249,  55, 232,  28, 117, 223, 110,  71, 241,  26, 113,  29, 
+   41, 197, 137, 111, 183,  98,  14, 170,  24, 190,  27, 252,  86,  62,  75, 
+  198, 210, 121,  32, 154, 219, 192, 254, 120, 205,  90, 244,  31, 221, 168,
+   51, 136,   7, 199,  49, 177,  18,  16,  89,  39, 128, 236,  95,  96,  81,
+  127, 169,  25, 181,  74,  13,  45, 229, 122, 159, 147, 201, 156, 239, 160,
+  224,  59,  77, 174,  42, 245, 176, 200, 235, 187,  60, 131,  83, 153,  97, 
+   23,  43,   4, 126, 186, 119, 214,  38, 225, 105,  20,  99,  85,  33,  12,
+  125 );
+  
+  function __construct($ks = 128, $bs = 128, $debug = false)
+  {
+    $this->keySizeInBits = $ks;
+    $this->blockSizeInBits = $bs;
+    
+    // Use the Mcrypt library? This speeds things up dramatically.
+    if(defined('MCRYPT_RIJNDAEL_' . $ks) && defined('MCRYPT_ACCEL'))
+    {
+      eval('$mcb = MCRYPT_RIJNDAEL_' . $ks.';');
+      $bks = mcrypt_module_get_algo_block_size($mcb);
+      $bks = $bks * 8;
+      if ( $bks != $bs )
+      {
+        $mcb = false;
+        echo (string)$bks;
+      }
+    }
+    else
+    {
+      $mcb = false;
+    }
+      
+    $this->mcrypt = $mcb;
+    
+    // Cipher parameters ... do not change these
+    $this->Nk = $this->keySizeInBits / 32;
+    $this->Nb = $this->blockSizeInBits / 32;
+    $this->Nr = $this->roundsArray[$this->Nk][$this->Nb];
+    $this->debug = $debug;
+  }
+  
+  public static function singleton($key_size, $block_size)
+  {
+    static $_aes_objcache;
+    if ( isset($_aes_objcache["$key_size,$block_size"]) )
+    {
+      return $_aes_objcache["$key_size,$block_size"];
+    }
+    
+    $_aes_objcache["$key_size,$block_size"] = new AESCrypt($key_size, $block_size);
+    return $_aes_objcache["$key_size,$block_size"];
+  }
+  
+  // Error handler
+  
+  function trigger_error($text, $level = E_USER_NOTICE)
+  {
+    $bt = debug_backtrace();
+    $lastfunc =& $bt[1];
+    switch($level)
+    {
+      case E_USER_NOTICE:
+      default:
+        $desc = 'Notice';
+        break;
+      case E_USER_WARNING:
+        $desc = 'Warning';
+        break;
+      case E_USER_ERROR:
+        $desc = 'Fatal';
+        break;
+    }
+    ob_start();
+    if($this->debug || $level == E_USER_ERROR) echo "AES encryption: <b>{$desc}:</b> $text in {$lastfunc['file']} on line {$lastfunc['line']} in function {$lastfunc['function']}<br />";
+    if($this->debug)
+    {
+      //echo '<pre>'.enano_debug_print_backtrace(true).'</pre>';
+    }
+    ob_end_flush();
+    if($level == E_USER_ERROR)
+    {
+      echo '<p><b>This can sometimes happen if you are upgrading Enano to a new version and did not log out first.</b> <a href="'.$_SERVER['PHP_SELF'].'?do=diag&amp;sub=cookie_destroy">Click here</a> to force cookies to clear and try again. You will be logged out.</p>';
+      exit;
+    }
+  }
+  
+  function array_slice_js_compat($array, $start, $finish = 0)
+  {
+    $len = $finish - $start;
+    if($len < 0) $len = 0 - $len;
+    //if($this->debug) echo (string)$len . ' ';
+    //if(count($array) < $start + $len)
+    //  $this->trigger_error('Index out of range', E_USER_WARNING);
+    return array_slice($array, $start, $len);
+  }
+  
+  function concat($s1, $s2)
+  {
+    if(is_array($s1) && is_array($s2))
+      return array_merge($s1, $s2);
+    elseif( ( is_array($s1) && !is_array($s2) ) || ( !is_array($s1) && is_array($s2) ) )
+    {
+      $this->trigger_error('incompatible types - you can\'t combine a non-array with an array', E_USER_WARNING);
+      return false;
+    }
+    else
+      return $s1 . $s2;
+  }
+  
+  // This method circularly shifts the array left by the number of elements
+  // given in its parameter. It returns the resulting array and is used for 
+  // the ShiftRow step. Note that shift() and push() could be used for a more 
+  // elegant solution, but they require IE5.5+, so I chose to do it manually. 
+  
+  function cyclicShiftLeft($theArray, $positions) {
+    if(!is_int($positions))
+    {
+      $this->trigger_error('$positions is not an integer! Backtrace:<br /><pre>'.print_r(debug_backtrace(), true).'</pre>', E_USER_WARNING);
+      return false;
+    }
+    $second = array_slice($theArray, 0, $positions);
+    $first = array_slice($theArray, $positions);
+    $theArray = array_merge($first, $second);
+    return $theArray;
+  }
+  
+  // Multiplies the element "poly" of GF(2^8) by x. See the Rijndael spec.
+  
+  function xtime($poly) {
+    $poly <<= 1;
+    return (($poly & 0x100) ? ($poly ^ 0x11B) : ($poly));
+  }
+  
+  // Multiplies the two elements of GF(2^8) together and returns the result.
+  // See the Rijndael spec, but should be straightforward: for each power of
+  // the indeterminant that has a 1 coefficient in x, add y times that power
+  // to the result. x and y should be bytes representing elements of GF(2^8)
+  
+  function mult_GF256($x, $y) {
+    $result = 0;
+    
+    for ($bit = 1; $bit < 256; $bit *= 2, $y = $this->xtime($y)) {
+      if ($x & $bit) 
+        $result ^= $y;
+    }
+    return $result;
+  }
+  
+  // Performs the substitution step of the cipher. State is the 2d array of
+  // state information (see spec) and direction is string indicating whether
+  // we are performing the forward substitution ("encrypt") or inverse 
+  // substitution (anything else)
+  
+  function byteSub(&$state, $direction) {
+    //global $this->SBox, $this->SBoxInverse, $this->Nb;
+    if ($direction == "encrypt")           // Point S to the SBox we're using
+      $S =& $this->SBox;
+    else
+      $S =& $this->SBoxInverse;
+    for ($i = 0; $i < 4; $i++)           // Substitute for every byte in state
+      for ($j = 0; $j < $this->Nb; $j++)
+         $state[$i][$j] = $S[$state[$i][$j]];
+  }
+  
+  // Performs the row shifting step of the cipher.
+  
+  function shiftRow(&$state, $direction) {
+    //global $this->Nb, $this->shiftOffsets;
+    for ($i=1; $i<4; $i++)               // Row 0 never shifts
+      if ($direction == "encrypt")
+         $state[$i] = $this->cyclicShiftLeft($state[$i], $this->shiftOffsets[$this->Nb][$i]);
+      else
+         $state[$i] = $this->cyclicShiftLeft($state[$i], $this->Nb - $this->shiftOffsets[$this->Nb][$i]);
+  
+  }
+  
+  // Performs the column mixing step of the cipher. Most of these steps can
+  // be combined into table lookups on 32bit values (at least for encryption)
+  // to greatly increase the speed. 
+  
+  function mixColumn(&$state, $direction) {
+    //global $this->Nb;
+    $b = Array();                                  // Result of matrix multiplications
+    for ($j = 0; $j < $this->Nb; $j++) {                 // Go through each column...
+      for ($i = 0; $i < 4; $i++) {                 // and for each row in the column...
+        if ($direction == "encrypt")
+          $b[$i] = $this->mult_GF256($state[$i][$j], 2) ^ // perform mixing
+                   $this->mult_GF256($state[($i+1)%4][$j], 3) ^ 
+                   $state[($i+2)%4][$j] ^ 
+                   $state[($i+3)%4][$j];
+        else 
+          $b[$i] = $this->mult_GF256($state[$i][$j], 0xE) ^ 
+                   $this->mult_GF256($state[($i+1)%4][$j], 0xB) ^
+                   $this->mult_GF256($state[($i+2)%4][$j], 0xD) ^
+                   $this->mult_GF256($state[($i+3)%4][$j], 9);
+      }
+      for ($i = 0; $i < 4; $i++)          // Place result back into column
+        $state[$i][$j] = $b[$i];
+    }
+  }
+  
+  // Adds the current round key to the state information. Straightforward.
+  
+  function addRoundKey(&$state, $roundKey) {
+    //global $this->Nb;
+    for ($j = 0; $j < $this->Nb; $j++) {                      // Step through columns...
+      $state[0][$j] ^= ( $roundKey[$j] & 0xFF);         // and XOR
+      $state[1][$j] ^= (($roundKey[$j]>>8) & 0xFF);
+      $state[2][$j] ^= (($roundKey[$j]>>16) & 0xFF);
+      $state[3][$j] ^= (($roundKey[$j]>>24) & 0xFF);
+    }
+  }
+  
+  // This function creates the expanded key from the input (128/192/256-bit)
+  // key. The parameter key is an array of bytes holding the value of the key.
+  // The returned value is an array whose elements are the 32-bit words that 
+  // make up the expanded key.
+  
+  function keyExpansion($key) {
+    //global $this->keySizeInBits, $this->blockSizeInBits, $this->roundsArray, $this->Nk, $this->Nb, $this->Nr, $this->Nk, $this->SBox, $this->Rcon;
+    $expandedKey = Array();
+  
+    // in case the key size or parameters were changed...
+    $this->Nk = $this->keySizeInBits / 32;                   
+    $this->Nb = $this->blockSizeInBits / 32;
+    $this->Nr = $this->roundsArray[$this->Nk][$this->Nb];
+  
+    for ($j=0; $j < $this->Nk; $j++)     // Fill in input key first
+      $expandedKey[$j] = 
+        ($key[4*$j]) | ($key[4*$j+1]<<8) | ($key[4*$j+2]<<16) | ($key[4*$j+3]<<24);
+  
+    // Now walk down the rest of the array filling in expanded key bytes as
+    // per Rijndael's spec
+    for ($j = $this->Nk; $j < $this->Nb * ($this->Nr + 1); $j++) {    // For each word of expanded key
+      $temp = $expandedKey[$j - 1];
+      if ($j % $this->Nk == 0) 
+        $temp = ( ($this->SBox[($temp>>8) & 0xFF]) |
+                  ($this->SBox[($temp>>16) & 0xFF]<<8) |
+                  ($this->SBox[($temp>>24) & 0xFF]<<16) |
+                  ($this->SBox[$temp & 0xFF]<<24) ) ^ $this->Rcon[floor($j / $this->Nk) - 1];
+      elseif  ($this->Nk > 6 && $j % $this->Nk == 4)
+        $temp = ($this->SBox[($temp>>24) & 0xFF]<<24) |
+               ($this->SBox[($temp>>16) & 0xFF]<<16) |
+               ($this->SBox[($temp>>8) & 0xFF]<<8) |
+               ($this->SBox[ $temp & 0xFF]);
+      $expandedKey[$j] = $expandedKey[$j-$this->Nk] ^ $temp;
+    }
+    return $expandedKey;
+  }
+  
+  // Rijndael's round functions... 
+  
+  function RijndaelRound(&$state, $roundKey) {
+    $this->byteSub($state, "encrypt");
+    $this->shiftRow($state, "encrypt");
+    $this->mixColumn($state, "encrypt");
+    $this->addRoundKey($state, $roundKey);
+  }
+  
+  function InverseRijndaelRound(&$state, $roundKey) {
+    $this->addRoundKey($state, $roundKey);
+    $this->mixColumn($state, "decrypt");
+    $this->shiftRow($state, "decrypt");
+    $this->byteSub($state, "decrypt");
+  }
+  
+  function FinalRijndaelRound(&$state, $roundKey) {
+    $this->byteSub($state, "encrypt");
+    $this->shiftRow($state, "encrypt");
+    $this->addRoundKey($state, $roundKey);
+  }
+  
+  function InverseFinalRijndaelRound(&$state, $roundKey){
+    $this->addRoundKey($state, $roundKey);
+    $this->shiftRow($state, "decrypt");
+    $this->byteSub($state, "decrypt");  
+  }
+  
+  // encrypt is the basic encryption function. It takes parameters
+  // block, an array of bytes representing a plaintext block, and expandedKey,
+  // an array of words representing the expanded key previously returned by
+  // keyExpansion(). The ciphertext block is returned as an array of bytes.
+  
+  function cryptBlock($block, $expandedKey) {
+    //global $this->blockSizeInBits, $this->Nb, $this->Nr;
+    $t=count($block)*8;
+    if (!is_array($block) || count($block)*8 != $this->blockSizeInBits)
+    {
+      $this->trigger_error('block is bad or block size is wrong<pre>'.print_r($block, true).'</pre><p>Aiming for size '.$this->blockSizeInBits.', got '.$t.'.', E_USER_WARNING); 
+      return false;
+    }
+    if (!$expandedKey)
+      return;
+  
+    $block = $this->packBytes($block);
+    $this->addRoundKey($block, $expandedKey);
+    for ($i=1; $i<$this->Nr; $i++) 
+      $this->RijndaelRound($block, $this->array_slice_js_compat($expandedKey, $this->Nb*$i, $this->Nb*($i+1)));
+    $this->FinalRijndaelRound($block, $this->array_slice_js_compat($expandedKey, $this->Nb*$this->Nr));
+    $ret = $this->unpackBytes($block);
+    return $ret;
+  }
+  
+  // decrypt is the basic decryption function. It takes parameters
+  // block, an array of bytes representing a ciphertext block, and expandedKey,
+  // an array of words representing the expanded key previously returned by
+  // keyExpansion(). The decrypted block is returned as an array of bytes.
+  
+  function unCryptBlock($block, $expandedKey) {
+    $t = count($block)*8;
+    if (!is_array($block) || count($block)*8 != $this->blockSizeInBits)
+    {
+      $this->trigger_error('$block is not a valid rijndael-block array: '.$this->byteArrayToHex($block).'<pre>'.print_r($block, true).'</pre><p>Block size is '.$t.', should be '.$this->blockSizeInBits.'</p>', E_USER_WARNING);
+      return false;
+    }
+    if (!$expandedKey)
+    {
+      $this->trigger_error('$expandedKey is invalid', E_USER_WARNING);
+      return false;
+    }
+  
+    $block = $this->packBytes($block);
+    $this->InverseFinalRijndaelRound($block, $this->array_slice_js_compat($expandedKey, $this->Nb*$this->Nr)); 
+    for ($i = $this->Nr - 1; $i>0; $i--) 
+    {
+      $this->InverseRijndaelRound($block, $this->array_slice_js_compat($expandedKey, $this->Nb*$i, $this->Nb*($i+1)));
+    }
+    $this->addRoundKey($block, $expandedKey);
+    $ret = $this->unpackBytes($block);
+    if(!is_array($ret))
+    {
+      $this->trigger_error('$ret is not an array', E_USER_WARNING);
+    }
+    return $ret;
+  }
+  
+  // This method takes a byte array (byteArray) and converts it to a string by
+  // applying String.fromCharCode() to each value and concatenating the result.
+  // The resulting string is returned. Note that this function SKIPS zero bytes
+  // under the assumption that they are padding added in formatPlaintext().
+  // Obviously, do not invoke this method on raw data that can contain zero
+  // bytes. It is really only appropriate for printable ASCII/Latin-1 
+  // values. Roll your own function for more robust functionality :)
+  
+  function byteArrayToString($byteArray) {
+    $result = "";
+    for($i=0; $i<count($byteArray); $i++)
+      if ($byteArray[$i] != 0) 
+        $result .= chr($byteArray[$i]);
+    return $result;
+  }
+  
+  // This function takes an array of bytes (byteArray) and converts them
+  // to a hexadecimal string. Array element 0 is found at the beginning of 
+  // the resulting string, high nibble first. Consecutive elements follow
+  // similarly, for example [16, 255] --> "10ff". The function returns a 
+  // string.
+  
+  /*
+  function byteArrayToHex($byteArray) {
+    $result = "";
+    if (!$byteArray)
+      return;
+    for ($i=0; $i<count($byteArray); $i++)
+      $result .= (($byteArray[$i]<16) ? "0" : "") + toString($byteArray[$i]); // magic number here is 16, not sure how to handle this...
+  
+    return $result;
+  }
+  */
+  function byteArrayToHex($arr)
+  {
+    $ret = '';
+    foreach($arr as $a)
+    {
+      $nibble = (string)dechex(intval($a));
+      if(strlen($nibble) == 1) $nibble = '0' . $nibble;
+      $ret .= $nibble;
+    }
+    return $ret;
+  }
+  
+  // PHP equivalent of Javascript's toString()
+  function toString($bool)
+  {
+    if(is_bool($bool))
+      return ($bool) ? 'true' : 'false';
+    elseif(is_array($bool))
+      return implode(',', $bool);
+    else
+      return (string)$bool;
+  }
+  
+  // This function converts a string containing hexadecimal digits to an 
+  // array of bytes. The resulting byte array is filled in the order the
+  // values occur in the string, for example "10FF" --> [16, 255]. This
+  // function returns an array. 
+  
+  /*
+  function hexToByteArray($hexString) {
+    $byteArray = Array();
+    if (strlen($hexString) % 2)             // must have even length
+      return;
+    if (strstr($hexString, "0x") == $hexString || strstr($hexString, "0X") == $hexString)
+      $hexString = substr($hexString, 2);
+    for ($i = 0; $i<strlen($hexString); $i++,$i++) 
+      $byteArray[floor($i/2)] = intval(substr($hexString, $i, 2)); // again, that strange magic number: 16
+    return $byteArray;
+  }
+  */
+  function hexToByteArray($str)
+  {
+    if(substr($str, 0, 2) == '0x' || substr($str, 0, 2) == '0X')
+      $str = substr($str, 2);
+    $arr = Array();
+    $str = $this->enano_str_split($str, 2);
+    foreach($str as $s)
+    {
+      $arr[] = intval(hexdec($s));
+    }
+    return $arr;
+  }
+  
+  // This function packs an array of bytes into the four row form defined by
+  // Rijndael. It assumes the length of the array of bytes is divisible by
+  // four. Bytes are filled in according to the Rijndael spec (starting with
+  // column 0, row 0 to 3). This function returns a 2d array.
+  
+  function packBytes($octets) {
+    $state = Array();
+    if (!$octets || count($octets) % 4)
+      return;
+  
+    $state[0] = Array(); $state[1] = Array(); 
+    $state[2] = Array(); $state[3] = Array();
+    for ($j=0; $j<count($octets); $j = $j+4) {
+       $state[0][$j/4] = $octets[$j];
+       $state[1][$j/4] = $octets[$j+1];
+       $state[2][$j/4] = $octets[$j+2];
+       $state[3][$j/4] = $octets[$j+3];
+    }
+    return $state;
+  }
+  
+  // This function unpacks an array of bytes from the four row format preferred
+  // by Rijndael into a single 1d array of bytes. It assumes the input "packed"
+  // is a packed array. Bytes are filled in according to the Rijndael spec. 
+  // This function returns a 1d array of bytes.
+  
+  function unpackBytes($packed) {
+    $result = Array();
+    for ($j=0; $j<count($packed[0]); $j++) {
+      $result[] = $packed[0][$j];
+      $result[] = $packed[1][$j];
+      $result[] = $packed[2][$j];
+      $result[] = $packed[3][$j];
+    }
+    return $result;
+  }
+  
+  function charCodeAt($str, $i)
+  {
+    return ord(substr($str, $i, 1));
+  }
+  
+  function fromCharCode($str)
+  {
+    return chr($str);
+  }
+  
+  // This function takes a prospective plaintext (string or array of bytes)
+  // and pads it with zero bytes if its length is not a multiple of the block 
+  // size. If plaintext is a string, it is converted to an array of bytes
+  // in the process. The type checking can be made much nicer using the 
+  // instanceof operator, but this operator is not available until IE5.0 so I 
+  // chose to use the heuristic below. 
+  
+  function formatPlaintext($plaintext) {
+    //global $this->blockSizeInBits;
+    $bpb = $this->blockSizeInBits / 8;               // bytes per block
+  
+    // if primitive string or String instance
+    if (is_string($plaintext)) {
+      $plaintext = $this->enano_str_split($plaintext);
+      // Unicode issues here (ignoring high byte)
+      for ($i=0; $i<sizeof($plaintext); $i++)
+        $plaintext[$i] = $this->charCodeAt($plaintext[$i], 0) & 0xFF;
+    } 
+  
+    for ($i = $bpb - (sizeof($plaintext) % $bpb); $i > 0 && $i < $bpb; $i--) 
+      $plaintext[] = 0;
+    
+    return $plaintext;
+  }
+  
+  // Returns an array containing "howMany" random bytes. YOU SHOULD CHANGE THIS
+  // TO RETURN HIGHER QUALITY RANDOM BYTES IF YOU ARE USING THIS FOR A "REAL"
+  // APPLICATION. (edit: done, mt_rand() is relatively secure)
+  
+  function getRandomBytes($howMany) {
+    $bytes = Array();
+    for ($i=0; $i<$howMany; $i++)
+      $bytes[$i] = mt_rand(0, 255);
+    return $bytes;
+  }
+  
+  // rijndaelEncrypt(plaintext, key, mode)
+  // Encrypts the plaintext using the given key and in the given mode. 
+  // The parameter "plaintext" can either be a string or an array of bytes. 
+  // The parameter "key" must be an array of key bytes. If you have a hex 
+  // string representing the key, invoke hexToByteArray() on it to convert it 
+  // to an array of bytes. The third parameter "mode" is a string indicating
+  // the encryption mode to use, either "ECB" or "CBC". If the parameter is
+  // omitted, ECB is assumed.
+  // 
+  // An array of bytes representing the cihpertext is returned. To convert 
+  // this array to hex, invoke byteArrayToHex() on it. If you are using this 
+  // "for real" it is a good idea to change the function getRandomBytes() to 
+  // something that returns truly random bits.
+  
+  function rijndaelEncrypt($plaintext, $key, $mode = 'ECB') {
+    //global $this->blockSizeInBits, $this->keySizeInBits;
+    $bpb = $this->blockSizeInBits / 8;          // bytes per block
+    // var ct;                                 // ciphertext
+  
+    if($mode == 'CBC')
+    {
+      if (!is_string($plaintext) || !is_array($key))
+      {
+        $this->trigger_error('In CBC mode the first and second parameters should be strings', E_USER_WARNING);
+        return false;
+      }
+    } else {
+      if (!is_array($plaintext) || !is_array($key))
+      {
+        $this->trigger_error('In ECB mode the first and second parameters should be byte arrays', E_USER_WARNING);
+        return false;
+      }
+    }
+    if (sizeof($key)*8 != $this->keySizeInBits)
+    {
+      $this->trigger_error('The key needs to be '. ( $this->keySizeInBits / 8 ) .' bytes in length', E_USER_WARNING);
+      return false;
+    }
+    if ($mode == "CBC")
+      $ct = $this->getRandomBytes($bpb);             // get IV
+    else {
+      $mode = "ECB";
+      $ct = Array();
+    }
+    
+    // convert plaintext to byte array and pad with zeros if necessary. 
+    $plaintext = $this->formatPlaintext($plaintext);
+    
+    $expandedKey = $this->keyExpansion($key);
+    
+    for ($block=0; $block<sizeof($plaintext) / $bpb; $block++) {
+      $aBlock = $this->array_slice_js_compat($plaintext, $block*$bpb, ($block+1)*$bpb);
+      if ($mode == "CBC")
+      {
+        for ($i=0; $i<$bpb; $i++)
+        {
+          $aBlock[$i] ^= $ct[$block*$bpb + $i];
+        }
+      }
+      $cp = $this->cryptBlock($aBlock, $expandedKey);
+      $ct = $this->concat($ct, $cp);
+    }
+  
+    return $ct;
+  }
+  
+  // rijndaelDecrypt(ciphertext, key, mode)
+  // Decrypts the using the given key and mode. The parameter "ciphertext" 
+  // must be an array of bytes. The parameter "key" must be an array of key 
+  // bytes. If you have a hex string representing the ciphertext or key, 
+  // invoke hexToByteArray() on it to convert it to an array of bytes. The
+  // parameter "mode" is a string, either "CBC" or "ECB".
+  // 
+  // An array of bytes representing the plaintext is returned. To convert 
+  // this array to a hex string, invoke byteArrayToHex() on it. To convert it 
+  // to a string of characters, you can use byteArrayToString().
+  
+  function rijndaelDecrypt($ciphertext, $key, $mode = 'ECB') {
+    //global $this->blockSizeInBits, $this->keySizeInBits;
+    $bpb = $this->blockSizeInBits / 8;          // bytes per block
+    $pt = Array();                   // plaintext array
+    // $aBlock;                             // a decrypted block
+    // $block;                              // current block number
+  
+    if (!$ciphertext)
+    {
+      $this->trigger_error('$ciphertext should be a byte array', E_USER_WARNING);
+      return false;
+    }
+    if(  !is_array($key) )
+    {
+      $this->trigger_error('$key should be a byte array', E_USER_WARNING);
+      return false;
+    }
+    if( is_string($ciphertext) )
+    {
+      $this->trigger_error('$ciphertext should be a byte array', E_USER_WARNING);
+      return false;
+    }
+    if (sizeof($key)*8 != $this->keySizeInBits)
+    {
+      $this->trigger_error('Encryption key is the wrong length', E_USER_WARNING);
+      return false;
+    }
+    if (!$mode)
+      $mode = "ECB";                         // assume ECB if mode omitted
+  
+    $expandedKey = $this->keyExpansion($key);
+   
+    // work backwards to accomodate CBC mode 
+    for ($block=(sizeof($ciphertext) / $bpb)-1; $block>0; $block--)
+    {
+      if( ( $block*$bpb ) + ( ($block+1)*$bpb ) > count($ciphertext) )
+      {
+        //$this->trigger_error('$ciphertext index out of bounds', E_USER_ERROR);
+      }
+      $current_block = $this->array_slice_js_compat($ciphertext, $block*$bpb, ($block+1)*$bpb);
+      if(count($current_block) * 8 != $this->blockSizeInBits)
+      {
+        // $c=count($current_block)*8;
+        // $this->trigger_error('We got a '.$c.'-bit block, instead of '.$this->blockSizeInBits.'', E_USER_ERROR);
+      }
+      $aBlock = $this->uncryptBlock($current_block, $expandedKey);
+      if(!$aBlock)
+      {
+        $this->trigger_error('Shared block decryption routine returned false', E_USER_WARNING);
+        return false;
+      }
+      if ($mode == "CBC")
+        for ($i=0; $i<$bpb; $i++) 
+          $pt[($block-1)*$bpb + $i] = $aBlock[$i] ^ $ciphertext[($block-1)*$bpb + $i];
+      else
+        $pt = $this->concat($aBlock, $pt);
+    }
+  
+    // do last block if ECB (skips the IV in CBC)
+    if ($mode == "ECB")
+    {
+      $x = $this->uncryptBlock($this->array_slice_js_compat($ciphertext, 0, $bpb), $expandedKey);
+      if(!$x)
+      {
+        $this->trigger_error('ECB block decryption routine returned false', E_USER_WARNING);
+        return false;
+      }
+      $pt = $this->concat($x, $pt);
+      if(!$pt)
+      {
+        $this->trigger_error('ECB concatenation routine returned false', E_USER_WARNING);
+        return false;
+      }
+    }
+  
+    return $pt;
+  }
+  
+  /**
+   * Wrapper for encryption.
+   * @param string $text the text to encrypt
+   * @param string $key the raw binary key to encrypt with
+   * @param int $return_encoding optional - can be ENC_BINARY, ENC_HEX or ENC_BASE64
+   */
+   
+  function encrypt($text, $key, $return_encoding = ENC_HEX)
+  {
+    if ( $text == '' )
+      return '';
+    if ( $this->mcrypt && $this->blockSizeInBits == mcrypt_module_get_algo_block_size(eval('return MCRYPT_RIJNDAEL_'.$this->keySizeInBits.';')) )
+    {
+      $iv_size = mcrypt_get_iv_size($this->mcrypt, MCRYPT_MODE_ECB);
+      $iv = mcrypt_create_iv($iv_size, MCRYPT_RAND);
+      $cryptext = mcrypt_encrypt($this->mcrypt, $key, $text, MCRYPT_MODE_ECB, $iv);
+      switch($return_encoding)
+      {
+        case ENC_HEX:
+        default:
+          $cryptext = $this->strtohex($cryptext);
+          break;
+        case ENC_BINARY:
+          $cryptext = $cryptext;
+          break;
+        case ENC_BASE64:
+          $cryptext = base64_encode($cryptext);
+          break;
+      }
+    }
+    else
+    {
+      $key = $this->prepare_string($key);
+      $text = $this->prepare_string($text);
+      profiler_log('AES: Started encryption of a string');
+      $cryptext = $this->rijndaelEncrypt($text, $key, 'ECB');
+      profiler_log('AES: Finished encryption of a string');
+      if(!is_array($cryptext))
+      {
+        echo 'Warning: encryption failed for string: '.print_r($text,true).'<br />';
+        return false;
+      }
+      switch($return_encoding)
+      {
+        case ENC_HEX:
+        default:
+          $cryptext = $this->byteArrayToHex($cryptext);
+          break;
+        case ENC_BINARY:
+          $cryptext = $this->byteArrayToString($cryptext);
+          break;
+        case ENC_BASE64:
+          $cryptext = base64_encode($this->byteArrayToString($cryptext));
+          break;
+      }
+    }
+    return $cryptext;
+  }
+  
+  /**
+   * Wrapper for decryption.
+   * @param string $text the encrypted text
+   * @param string $key the raw binary key used to encrypt the text
+   * @param int $input_encoding the encoding used for the encrypted string. Can be ENC_BINARY, ENC_HEX, or ENC_BASE64.
+   * @return string
+   */
+   
+  function decrypt($text, $key, $input_encoding = ENC_HEX)
+  {
+    if ( $text == '' )
+      return '';
+    
+    switch($input_encoding)
+    {
+      case ENC_BINARY:
+      default:
+        break;
+      case ENC_HEX:
+        $text = $this->hextostring($text);
+        break;
+      case ENC_BASE64:
+        $text = base64_decode($text);
+        break;
+    }
+    
+    // Run memory-cache check
+    if ( isset($this->decrypt_cache[$key]) && is_array($this->decrypt_cache[$key]) )
+    {
+      if ( isset($this->decrypt_cache[$key][$text]) )
+      {
+        return $this->decrypt_cache[$key][$text];
+      }
+    }
+    
+    // Run disk-cache check
+    $hash = sha1($text . '::' . $key);
+    if ( $dypt = aes_decrypt_cache_fetch($hash) )
+      return $dypt;
+    
+    $text_bin = $text;
+    $key_bin = $key;
+    
+    if ( $this->mcrypt )
+    {
+      $iv_size = mcrypt_get_iv_size($this->mcrypt, MCRYPT_MODE_ECB);
+      $iv = mcrypt_create_iv($iv_size, MCRYPT_RAND);
+      $dypt = mcrypt_decrypt($this->mcrypt, $key, $text, MCRYPT_MODE_ECB, $iv);
+    }
+    else
+    {
+      $etext = $this->prepare_string($text);
+      $ekey  = $this->prepare_string($key);
+      $mod = count($etext) % $this->blockSizeInBits;
+      profiler_log('AES: Started decryption of a string');
+      $dypt = $this->rijndaelDecrypt($etext, $ekey, 'ECB');
+      profiler_log('AES: Finished decryption of a string');
+      if(!$dypt)
+      {
+        echo '<pre>'.print_r($dypt, true).'</pre>';
+        $this->trigger_error('Rijndael main decryption routine failed', E_USER_ERROR);
+      }
+      $dypt = $this->byteArrayToString($dypt);
+    }
+    if ( !isset($this->decrypt_cache[$key_bin]) )
+      $this->decrypt_cache[$key_bin] = array();
+    
+    $this->decrypt_cache[$key_bin][$text_bin] = $dypt;
+    
+    aes_decrypt_cache_store($text_bin, $dypt, $key_bin);
+    
+    return $dypt;
+  }
+  
+  /**
+   * Enano-ese equivalent of str_split() which is only found in PHP5
+   * @param $text string the text to split
+   * @param $inc int size of each block
+   * @return array
+   */
+   
+  function enano_str_split($text, $inc = 1)
+  {
+    if($inc < 1) return false;
+    if($inc >= strlen($text)) return Array($text);
+    $len = ceil(strlen($text) / $inc);
+    $ret = Array();
+    for($i=0;$i<strlen($text);$i=$i+$inc)
+    {
+      $ret[] = substr($text, $i, $inc);
+    }
+    return $ret;
+  }
+  
+  /**
+   * Generates a random key suitable for encryption
+   * @param int $len the length of the key, in bytes
+   * @return string a BINARY key
+   */
+  
+  function randkey($len = 32)
+  {
+    $key = '';
+    for($i=0;$i<$len;$i++)
+    {
+      $key .= chr(mt_rand(0, 255));
+    }
+    if ( file_exists('/dev/urandom') && is_readable('/dev/urandom') )
+    {
+      // Let's use something a little more secure
+      $ur = @fopen('/dev/urandom', 'r');
+      if ( !$ur )
+        return $key;
+      $ukey = @fread($ur, $len);
+      fclose($ur);
+      if ( strlen($ukey) != $len )
+        return $key;
+      return $ukey;
+    }
+    return $key;
+  }
+  
+  /*
+  function byteArrayToString($arr)
+  {
+    if(!is_array($arr))
+    {
+      $this->trigger_error('First parameter should be an array', E_USER_WARNING);
+      return false;
+    }
+    $ret = '';
+    foreach($arr as $a)
+    {
+      if($a != 0) $ret .= chr($a);
+    }
+    return $ret;
+  }
+  */
+  
+  function strtohex($str)
+  {
+    $str = $this->enano_str_split($str);
+    $ret = '';
+    foreach($str as $s)
+    {
+      $chr = dechex(ord($s));
+      if(strlen($chr) < 2) $chr = '0' . $chr;
+      $ret .= $chr;
+    }
+    return $ret;
+  }
+  
+  function gen_readymade_key()
+  {
+    $key = $this->strtohex($this->randkey($this->keySizeInBits / 8));
+    return $key;
+  }
+  
+  function prepare_string($text)
+  {
+    $ret = $this->hexToByteArray($this->strtohex($text));
+    if(count($ret) != strlen($text))
+    {
+      die('Could not convert string "' . $text . '" to hex byte array for encryption');
+    }
+    return $ret;
+  }
+  
+  /**
+   * Decodes a hex string.
+   * @param string $hex The hex code to decode
+   * @return string
+   */
+  
+  function hextostring($hex)
+  {
+    $hex = $this->enano_str_split($hex, 2);
+    $bin_key = '';
+    foreach($hex as $nibble)
+    {
+      $byte = chr(hexdec($nibble));
+      $bin_key .= $byte;
+    }
+    return $bin_key;
+  }
+}
+
+function aes_decrypt_cache_store($encrypted, $decrypted, $key)
+{
+  $cache_file = ENANO_ROOT . '/cache/aes_decrypt.php';
+  // only cache if $decrypted is long enough to actually warrant caching
+  if ( strlen($decrypted) < 32 )
+  {
+    profiler_log("AES: Skipped caching a string (probably a password, we dunno) because it's too short");
+    return false;
+  }
+  if ( file_exists($cache_file) )
+  {
+    require_once($cache_file);
+    global $aes_decrypt_cache;
+    $cachekey = sha1($encrypted . '::' . $key);
+    $aes_decrypt_cache[$cachekey] = $decrypted;
+    
+    if ( count($aes_decrypt_cache) > 5000 )
+    {
+      // we've got a lot of strings in the cache, clear out a few
+      $keys = array_keys($aes_decrypt_cache);
+      for ( $i = 0; $i < 2500; $i++ )
+      {
+        unset($aes_decrypt_cache[$keys[$i]]);
+        unset($aes_decrypt_cache[$keys[$i]]);
+      }
+    }
+  }
+  else
+  {
+    $aes_decrypt_cache = array(
+      sha1($encrypted . '::' . $key) => $decrypted
+    );
+  }
+  // call var_export and collect contents
+  ob_start();
+  var_export($aes_decrypt_cache);
+  $dec_cache_string = ob_get_contents();
+  ob_end_clean();
+  $f = @fopen($cache_file, 'w');
+  if ( !$f )
+    return false;
+  fwrite($f, "<?php
+\$GLOBALS['aes_decrypt_cache'] = $dec_cache_string;
+");
+  fclose($f);
+  return true;
+}
+
+function aes_decrypt_cache_fetch($hash)
+{
+  $cache_file = ENANO_ROOT . '/cache/aes_decrypt.php';
+  if ( !file_exists($cache_file) )
+    return false;
+  
+  require_once($cache_file);
+  global $aes_decrypt_cache;
+  if ( isset($aes_decrypt_cache[$hash]) )
+  {
+    profiler_log("AES: Loaded cached decrypted string, hash is $hash");
+    return $aes_decrypt_cache[$hash];
+  }
+  
+  return false;
+}
+
+function aes_decrypt_cache_destroy($hash)
+{
+  $cache_file = ENANO_ROOT . '/cache/aes_decrypt.php';
+  if ( !file_exists($cache_file) )
+    return false;
+  
+  require_once($cache_file);
+  global $aes_decrypt_cache;
+  
+  if ( isset($aes_decrypt_cache[$hash]) )
+    unset($aes_decrypt_cache[$hash]);
+  
+  // call var_export and collect contents
+  ob_start();
+  var_export($aes_decrypt_cache);
+  $dec_cache_string = ob_get_contents();
+  ob_end_clean();
+  $f = @fopen($cache_file, 'w');
+  if ( !$f )
+    return false;
+  fwrite($f, "<?php
+\$GLOBALS['aes_decrypt_cache'] = $dec_cache_string;
+");
+  fclose($f);
+  return true;
+}
+
+?>
--- a/includes/search.php	Fri Feb 22 12:46:51 2008 -0500
+++ b/includes/search.php	Fri Feb 22 12:51:53 2008 -0500
@@ -2,7 +2,7 @@
 
 /*
  * Enano - an open-source CMS capable of wiki functions, Drupal-like sidebar blocks, and everything in between
- * Version 1.0.3 (Dyrad)
+ * Version 1.1.2 (Caoineag alpha 2)
  * Copyright (C) 2006-2007 Dan Fuhry
  * search.php - algorithm used to search pages
  *
@@ -75,7 +75,7 @@
       $words = explode(' ', $letters);
       foreach($words as $c => $w)
       {
-        if(strlen($w) < 2 || in_array($w, $stopwords) || strlen($w) > 63)
+        if(strlen($w) < 2 || in_array($w, $stopwords) || strlen($w) > 63 || preg_match('/[\']{2,}/', $w))
           unset($words[$c]);
         else
           $words[$c] = $w;
@@ -112,12 +112,15 @@
  * @param string Search query
  * @param string Will be filled with any warnings encountered whilst parsing the query
  * @param bool Case sensitivity - defaults to false
+ * @param array|reference Will be filled with the parsed list of words.
  * @return array
  */
 
-function perform_search($query, &$warnings, $case_sensitive = false)
+function perform_search($query, &$warnings, $case_sensitive = false, &$word_list)
 {
   global $db, $session, $paths, $template, $plugins; // Common objects
+  global $lang;
+  
   $warnings = array();
 
   $query = parse_search_query($query, $warnings);
@@ -165,7 +168,7 @@
   if ( count($query['any']) < 1 && count($query['req']) < 1 && count($query_phrase['any']) < 1 && count($query_phrase['req']) < 1 )
   {
     // This is both because of technical restrictions and devastation that would occur on shared servers/large sites.
-    $warnings[] = 'You need to have at least one keyword in your search query. Searching only for pages not containing a term is not allowed.';
+    $warnings[] = $lang->get('search_err_query_no_positive');
     return array();
   }
 
@@ -522,13 +525,13 @@
     if ( isset($scores[$idstring]) )
     {
       $page_data[$idstring] = array(
-          'page_name' => $page['name'],
+          'page_name' => highlight_search_result($page['name'], $word_list, $case_sensitive),
           'page_text' => '',
           'page_id' => $page['urlname_nons'],
           'namespace' => $page['namespace'],
           'score' => $scores[$idstring],
           'page_length' => 1,
-          'page_note' => '[Special page]'
+          'page_note' => '[' . $lang->get('search_result_tag_special') . ']'
         );
     }
   }
@@ -592,6 +595,11 @@
     // if ( $score > $divisor )
     //   $score = $divisor;
     $datum['score'] = round($score / $divisor, 2) * 100;
+    
+    // Highlight the URL
+    $datum['url_highlight'] = makeUrlComplete($datum['namespace'], $datum['page_id']);
+    $datum['url_highlight'] = preg_replace('/\?.+$/', '', $datum['url_highlight']);
+    $datum['url_highlight'] = highlight_search_result($datum['url_highlight'], $word_list, $case_sensitive);
 
     // Store it in our until-now-unused results array
     $results[] = $datum;
@@ -613,6 +621,8 @@
 
 function parse_search_query($query, &$warnings)
 {
+  global $lang;
+  
   $stopwords = get_stopwords();
   $ret = array(
     'any' => array(),
@@ -663,7 +673,7 @@
 
     if ( $ticker == 20 )
     {
-      $warnings[] = 'Some of your search terms were excluded because searches are limited to 20 terms to prevent excessive server load.';
+      $warnings[] = $lang->get('search_err_query_too_many_terms');
       break;
     }
 
@@ -672,13 +682,13 @@
       $word = substr ( $atom, 2, ( strlen( $atom ) - 3 ) );
       if ( strlen ( $word ) < 2 || in_array($word, $stopwords) )
       {
-        $warnings[] = 'One or more of your search terms was excluded because either it was less than 2 characters in length or is a common word (a stopword) that is typically found on a large number of pages. Examples of stopwords include "the", "this", "which", "with", etc.';
+        $warnings[] = $lang->get('search_err_query_has_stopwords');
         $ticker--;
         continue;
       }
       if(in_array($word, $ret['req']))
       {
-        $warnings[] = 'One or more of your search terms was excluded because duplicate terms were encountered.';
+        $warnings[] = $lang->get('search_err_query_dup_terms');
         $ticker--;
         continue;
       }
@@ -689,13 +699,13 @@
       $word = substr ( $atom, 2, ( strlen( $atom ) - 3 ) );
       if ( strlen ( $word ) < 4 )
       {
-        $warnings[] = 'One or more of your search terms was excluded because terms must be at least 4 characters in length.';
+        $warnings[] = $lang->get('search_err_query_term_too_short');
         $ticker--;
         continue;
       }
       if(in_array($word, $ret['not']))
       {
-        $warnings[] = 'One or more of your search terms was excluded because duplicate terms were encountered.';
+        $warnings[] = $lang->get('search_err_query_dup_terms');
         $ticker--;
         continue;
       }
@@ -706,13 +716,13 @@
       $word = substr ( $atom, 1 );
       if ( strlen ( $word ) < 2 || in_array($word, $stopwords) )
       {
-        $warnings[] = 'One or more of your search terms was excluded because either it was less than 2 characters in length or is a common word (a stopword) that is typically found on a large number of pages. Examples of stopwords include "the", "this", "which", "with", etc.';
+        $warnings[] = $lang->get('search_err_query_has_stopwords');
         $ticker--;
         continue;
       }
       if(in_array($word, $ret['req']))
       {
-        $warnings[] = 'One or more of your search terms was excluded because duplicate terms were encountered.';
+        $warnings[] = $lang->get('search_err_query_dup_terms');
         $ticker--;
         continue;
       }
@@ -723,13 +733,13 @@
       $word = substr ( $atom, 1 );
       if ( strlen ( $word ) < 2 || in_array($word, $stopwords) )
       {
-        $warnings[] = 'One or more of your search terms was excluded because either it was less than 2 characters in length or is a common word (a stopword) that is typically found on a large number of pages. Examples of stopwords include "the", "this", "which", "with", etc.';
+        $warnings[] = $lang->get('search_err_query_has_stopwords');
         $ticker--;
         continue;
       }
       if(in_array($word, $ret['not']))
       {
-        $warnings[] = 'One or more of your search terms was excluded because duplicate terms were encountered.';
+        $warnings[] = $lang->get('search_err_query_dup_terms');
         $ticker--;
         continue;
       }
@@ -740,13 +750,13 @@
       $word = substr ( $atom, 1, ( strlen ( $atom ) - 2 ) );
       if ( strlen ( $word ) < 2 || in_array($word, $stopwords) )
       {
-        $warnings[] = 'One or more of your search terms was excluded because either it was less than 2 characters in length or is a common word (a stopword) that is typically found on a large number of pages. Examples of stopwords include "the", "this", "which", "with", etc.';
+        $warnings[] = $lang->get('search_err_query_has_stopwords');
         $ticker--;
         continue;
       }
       if(in_array($word, $ret['any']))
       {
-        $warnings[] = 'One or more of your search terms was excluded because duplicate terms were encountered.';
+        $warnings[] = $lang->get('search_err_query_dup_terms');
         $ticker--;
         continue;
       }
@@ -757,13 +767,13 @@
       $word = $atom;
       if ( strlen ( $word ) < 2 || in_array($word, $stopwords) )
       {
-        $warnings[] = 'One or more of your search terms was excluded because either it was less than 2 characters in length or is a common word (a stopword) that is typically found on a large number of pages. Examples of stopwords include "the", "this", "which", "with", etc.';
+        $warnings[] = $lang->get('search_err_query_has_stopwords');
         $ticker--;
         continue;
       }
       if(in_array($word, $ret['any']))
       {
-        $warnings[] = 'One or more of your search terms was excluded because duplicate terms were encountered.';
+        $warnings[] = $lang->get('search_err_query_dup_terms');
         $ticker--;
         continue;
       }
--- a/includes/sessions.php	Fri Feb 22 12:46:51 2008 -0500
+++ b/includes/sessions.php	Fri Feb 22 12:51:53 2008 -0500
@@ -2,7 +2,7 @@
 
 /*
  * Enano - an open-source CMS capable of wiki functions, Drupal-like sidebar blocks, and everything in between
- * Version 1.0.3 (Dyrad)
+ * Version 1.1.2 (Caoineag alpha 2)
  * Copyright (C) 2006-2007 Dan Fuhry
  * sessions.php - everything related to security and user management
  *
@@ -13,9 +13,6 @@
  * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for details.
  */
  
-// Prepare a string for insertion into a MySQL database
-function filter($str) { return $db->escape($str); }
-
 /**
  * Anything and everything related to security and user management. This includes AES encryption, which is illegal in some countries.
  * Documenting the API was not easy - I hope you folks enjoy it.
@@ -50,11 +47,11 @@
   var $username;
   
   /**
-   * User ID of currently logged-in user, or -1 if not logged in
+   * User ID of currently logged-in user, or 1 if not logged in
    * @var int
    */
   
-  var $user_id;
+  var $user_id = 1;
   
   /**
    * Real name of currently logged-in user, or blank if not logged in
@@ -157,7 +154,7 @@
    * @var string
    */
    
-  var $auth_level = -1;
+  var $auth_level = 1;
   
   /**
    * State variable to track if a session timed out
@@ -324,13 +321,15 @@
   }
   
   /**
-   * PHP 4 compatible constructor.
+   * PHP 4 compatible constructor. Deprecated in 1.1.x.
    */
    
+  /*
   function sessionManager()
   {
     $this->__construct();
   }
+  */
   
   /**
    * Wrapper function to sanitize strings for MySQL and HTML
@@ -370,6 +369,8 @@
   function start()
   {
     global $db, $session, $paths, $template, $plugins; // Common objects
+    global $lang;
+    global $timezone;
     if($this->started) return;
     $this->started = true;
     $user = false;
@@ -389,19 +390,23 @@
         
         if(!$this->compat && $userdata['account_active'] != 1 && $data[1] != 'Special' && $data[1] != 'Admin')
         {
+          $language = intval(getConfig('default_language'));
+          $lang = new Language($language);
+          @setlocale(LC_ALL, $lang->lang_code);
+          
           $this->logout();
           $a = getConfig('account_activation');
           switch($a)
           {
             case 'none':
             default:
-              $solution = 'Your account was most likely deactivated by an administrator. Please contact the site administration for further assistance.';
+              $solution = $lang->get('user_login_noact_solution_none');
               break;
             case 'user':
-              $solution = 'Please check your e-mail; you should have been sent a message with instructions on how to activate your account. If you do not receive an e-mail from this site within 24 hours, please contact the site administration for further assistance.';
+              $solution = $lang->get('user_login_noact_solution_user');
               break;
             case 'admin':
-              $solution = 'This website has been configured so that all user accounts must be activated by the administrator before they can be used, so your account will most likely be activated the next time an administrator visits the site.';
+              $solution = $lang->get('user_login_noact_solution_admin');
               break;
           }
           
@@ -422,14 +427,14 @@
             $this->auth_level =    USER_LEVEL_MEMBER;
             $this->user_level =    USER_LEVEL_MEMBER;
             $this->logout();
-            redirect(scriptPath . '/', 'Logged out', 'You have successfully been logged out. All cookies cleared.', 4);
+            redirect(scriptPath . '/', $lang->get('user_login_noact_msg_logout_success_title'), $lang->get('user_login_noact_msg_logout_success_body'), 5);
           }
           
           if ( $can_request && !isset($_POST['activation_request']) )
           {
-            $form = '<p>If you are having trouble or did not receive the e-mail, you can request account activation from the administrators of this site.</p>
+            $form = '<p>' . $lang->get('user_login_noact_msg_ask_admins') . '</p>
                      <form action="' . makeUrlNS('System', 'ActivateStub') . '" method="post">
-                       <p><input type="submit" name="activation_request" value="Request account activation" /> <input type="submit" name="logout" value="Log out" /></p>
+                       <p><input type="submit" name="activation_request" value="' . $lang->get('user_login_noact_btn_request_activation') . '" /> <input type="submit" name="logout" value="' . $lang->get('user_login_noact_btn_log_out') . '" /></p>
                      </form>';
           }
           else
@@ -437,21 +442,21 @@
             if ( $can_request && isset($_POST['activation_request']) )
             {
               $this->admin_activation_request($userdata['username']);
-              $form = '<p>A request has just been sent to the administrators of this site. They will be able to activate your account or send you another activation e-mail if needed.</p>
+              $form = '<p>' . $lang->get('user_login_noact_msg_admins_just_asked') . '</p>
                        <form action="' . makeUrlNS('System', 'ActivateStub') . '" method="post">
-                         <p><input type="submit" name="logout" value="Log out" /></p>
+                         <p><input type="submit" name="logout" value="' . $lang->get('user_login_noact_btn_log_out') . '" /></p>
                        </form>';
             }
             else
             {
-              $form = '<p>There is an active request in the administrators\' control panel for your account to be activated.</p>
+              $form = '<p>' . $lang->get('user_login_noact_msg_admins_asked') . '</p>
                        <form action="' . makeUrlNS('System', 'ActivateStub') . '" method="post">
-                         <p><input type="submit" name="logout" value="Log out" /></p>
+                         <p><input type="submit" name="logout" value="' . $lang->get('user_login_noact_btn_log_out') . '" /></p>
                        </form>';
             }
           }
           
-          die_semicritical('Account error', '<p>It appears that your user account has not yet been activated. '.$solution.'</p>' . $form);
+          die_semicritical($lang->get('user_login_noact_title'), '<p>' . $lang->get('user_login_noact_msg_intro') . ' '.$solution.'</p>' . $form);
         }
         
         $this->sid = $_COOKIE['sid'];
@@ -470,9 +475,7 @@
           $this->signature =     $userdata['signature'];
           $this->reg_time =      $userdata['reg_time'];
         }
-        // Small security risk here - it allows someone who has already authenticated as an administrator to store the "super" key in
-        // the cookie. Change this to USER_LEVEL_MEMBER to override that. The same 15-minute restriction applies to this "exploit".
-        $this->auth_level =    $userdata['auth_level'];
+        $this->auth_level =    USER_LEVEL_MEMBER;
         if(!isset($template->named_theme_list[$this->theme]))
         {
           if($this->compat || !is_object($template))
@@ -487,6 +490,15 @@
           }
         }
         $user = true;
+        $GLOBALS['timezone'] = $userdata['user_timezone'];
+        
+        // Set language
+        if ( !defined('ENANO_ALLOW_LOAD_NOLANG') )
+        {
+          $lang_id = intval($userdata['user_lang']);
+          $lang = new Language($lang_id);
+          @setlocale(LC_ALL, $lang->lang_code);
+        }
         
         if(isset($_REQUEST['auth']) && !$this->sid_super)
         {
@@ -547,6 +559,7 @@
       $this->style = 'default';
     }
     
+    profiler_log('Sessions started');
   }
   
   # Logins
@@ -558,37 +571,95 @@
    * @param string $aes_key The MD5 hash of the encryption key, hex-encoded
    * @param string $challenge The 256-bit MD5 challenge string - first 128 bits should be the hash, the last 128 should be the challenge salt
    * @param int $level The privilege level we're authenticating for, defaults to 0
+   * @param array $captcha_hash Optional. If we're locked out and the lockout policy is captcha, this should be the identifier for the code.
+   * @param array $captcha_code Optional. If we're locked out and the lockout policy is captcha, this should be the code the user entered.
+   * @param bool $lookup_key Optional. If true (default) this queries the database for the "real" encryption key. Else, uses what is given.
    * @return string 'success' on success, or error string on failure
    */
    
-  function login_with_crypto($username, $aes_data, $aes_key_id, $challenge, $level = USER_LEVEL_MEMBER)
+  function login_with_crypto($username, $aes_data, $aes_key_id, $challenge, $level = USER_LEVEL_MEMBER, $captcha_hash = false, $captcha_code = false, $lookup_key = true)
   {
     global $db, $session, $paths, $template, $plugins; // Common objects
     
     $privcache = $this->private_key;
+
+    if ( !defined('IN_ENANO_INSTALL') )
+    {
+      $timestamp_cutoff = time() - $duration;
+      $q = $this->sql('SELECT timestamp FROM '.table_prefix.'lockout WHERE timestamp > ' . $timestamp_cutoff . ' AND ipaddr = \'' . $ipaddr . '\' ORDER BY timestamp DESC;');
+      $fails = $db->numrows();
+      // Lockout stuff
+      $threshold = ( $_ = getConfig('lockout_threshold') ) ? intval($_) : 5;
+      $duration  = ( $_ = getConfig('lockout_duration') ) ? intval($_) : 15;
+      // convert to minutes
+      $duration  = $duration * 60;
+      $policy = ( $x = getConfig('lockout_policy') && in_array(getConfig('lockout_policy'), array('lockout', 'disable', 'captcha')) ) ? getConfig('lockout_policy') : 'lockout';
+      if ( $policy == 'captcha' && $captcha_hash && $captcha_code )
+      {
+        // policy is captcha -- check if it's correct, and if so, bypass lockout check
+        $real_code = $this->get_captcha($captcha_hash);
+      }
+      if ( $policy != 'disable' && !( $policy == 'captcha' && isset($real_code) && strtolower($real_code) == strtolower($captcha_code) ) )
+      {
+        $ipaddr = $db->escape($_SERVER['REMOTE_ADDR']);
+        if ( $fails >= $threshold )
+        {
+          // ooh boy, somebody's in trouble ;-)
+          $row = $db->fetchrow();
+          $db->free_result();
+          return array(
+              'success' => false,
+              'error' => 'locked_out',
+              'lockout_threshold' => $threshold,
+              'lockout_duration' => ( $duration / 60 ),
+              'lockout_fails' => $fails,
+              'lockout_policy' => $policy,
+              'time_rem' => ( $duration / 60 ) - round( ( time() - $row['timestamp'] ) / 60 ),
+              'lockout_last_time' => $row['timestamp']
+            );
+        }
+      }
+      $db->free_result();
+    }
     
     // Instanciate the Rijndael encryption object
     $aes = AESCrypt::singleton(AES_BITS, AES_BLOCKSIZE);
     
     // Fetch our decryption key
     
-    $aes_key = $this->fetch_public_key($aes_key_id);
-    if ( !$aes_key )
+    if ( $lookup_key )
     {
-      // It could be that our key cache is full. If it seems larger than 65KB, clear it
-      if ( strlen(getConfig('login_key_cache')) > 65000 )
+      $aes_key = $this->fetch_public_key($aes_key_id);
+      if ( !$aes_key )
       {
-        setConfig('login_key_cache', '');
-        return 'It seems that the list of encryption keys used for login information has reached its maximum length, thus preventing new keys from being inserted. The list has been automatically cleared. Please try logging in again; if you are still unable to log in, please contact the site administration.';
+        // It could be that our key cache is full. If it seems larger than 65KB, clear it
+        if ( strlen(getConfig('login_key_cache')) > 65000 )
+        {
+          setConfig('login_key_cache', '');
+          return array(
+            'success' => false,
+            'error' => 'key_not_found_cleared',
+            );
+        }
+        return array(
+          'success' => false,
+          'error' => 'key_not_found'
+          );
       }
-      return 'Couldn\'t look up public key "'.htmlspecialchars($aes_key_id).'" for decryption';
+    }
+    else
+    {
+      $aes_key =& $aes_key_id;
     }
     
     // Convert the key to a binary string
     $bin_key = hexdecode($aes_key);
     
     if(strlen($bin_key) != AES_BITS / 8)
-      return 'The decryption key is the wrong length';
+      return array(
+        'success' => false,
+        'error' => 'key_wrong_length'
+        );
     
     // Decrypt our password
     $password = $aes->decrypt($aes_data, $bin_key, ENC_HEX);
@@ -607,10 +678,32 @@
     {
       // This wasn't logged in <1.0.2, dunno how it slipped through
       if($level > USER_LEVEL_MEMBER)
-        $this->sql('INSERT INTO '.table_prefix.'logs(log_type,action,time_id,date_string,author,edit_summary,page_text) VALUES(\'security\', \'admin_auth_bad\', '.time().', \''.date('d M Y h:i a').'\', \''.$db->escape($username).'\', \''.$db->escape($_SERVER['REMOTE_ADDR']).'\', ' . intval($level) . ')');
+        $this->sql('INSERT INTO '.table_prefix.'logs(log_type,action,time_id,date_string,author,edit_summary,page_text) VALUES(\'security\', \'admin_auth_bad\', '.time().', \''.enano_date('d M Y h:i a').'\', \''.$db->escape($username).'\', \''.$db->escape($_SERVER['REMOTE_ADDR']).'\', ' . intval($level) . ')');
       else
-        $this->sql('INSERT INTO '.table_prefix.'logs(log_type,action,time_id,date_string,author,edit_summary) VALUES(\'security\', \'auth_bad\', '.time().', \''.date('d M Y h:i a').'\', \''.$db->escape($username).'\', \''.$db->escape($_SERVER['REMOTE_ADDR']).'\')');
-      return "The username and/or password is incorrect.";  
+        $this->sql('INSERT INTO '.table_prefix.'logs(log_type,action,time_id,date_string,author,edit_summary) VALUES(\'security\', \'auth_bad\', '.time().', \''.enano_date('d M Y h:i a').'\', \''.$db->escape($username).'\', \''.$db->escape($_SERVER['REMOTE_ADDR']).'\')');
+    
+      if ( $policy != 'disable' && !defined('IN_ENANO_INSTALL') )
+      {
+        $ipaddr = $db->escape($_SERVER['REMOTE_ADDR']);
+        // increment fail count
+        $this->sql('INSERT INTO '.table_prefix.'lockout(ipaddr, timestamp, action) VALUES(\'' . $ipaddr . '\', ' . time() . ', \'credential\');');
+        $fails++;
+        // ooh boy, somebody's in trouble ;-)
+        return array(
+            'success' => false,
+            'error' => ( $fails >= $threshold ) ? 'locked_out' : 'invalid_credentials',
+            'lockout_threshold' => $threshold,
+            'lockout_duration' => ( $duration / 60 ),
+            'lockout_fails' => $fails,
+            'time_rem' => ( $duration / 60 ),
+            'lockout_policy' => $policy
+          );
+      }
+      
+      return array(
+          'success' => false,
+          'error' => 'invalid_credentials'
+        );
     }
     $row = $db->fetchrow();
     
@@ -629,7 +722,7 @@
           eval($cmd);
         }
         
-        redirect($url, 'Login sucessful', 'Please wait while you are transferred to the Password Reset form.');
+        redirect($url, '', '', 0);
         exit;
       }
     }
@@ -648,20 +741,27 @@
     {
       // Our password field is up-to-date with the >=1.0RC1 encryption standards, so decrypt the password in the table and see if we have a match; if so then do challenge authentication
       $real_pass = $aes->decrypt(hexdecode($row['password']), $this->private_key, ENC_BINARY);
-      if($password == $real_pass)
+      if($password === $real_pass && is_string($password))
       {
-        // Yay! We passed AES authentication, now do an MD5 challenge check to make sure we weren't spoofed
-        $chal = substr($challenge, 0, 32);
-        $salt = substr($challenge, 32, 32);
-        $correct_challenge = md5( $real_pass . $salt );
-        if($chal == $correct_challenge)
-          $success = true;
+        // Yay! We passed AES authentication. Previously an MD5 challenge was done here, this was deemed redundant in 1.1.3.
+        // It didn't seem to provide any additional security...
+        $success = true;
       }
     }
     if($success)
     {
       if($level > $row['user_level'])
-        return 'You are not authorized for this level of access.';
+        return array(
+          'success' => false,
+          'error' => 'too_big_for_britches'
+        );
+
+      /*        
+      return array(
+        'success' => false,
+        'error' => 'Successful authentication, but session manager is in debug mode - remove the "return array(...);" in includes/sessions.php:' . ( __LINE__ - 2 )
+      );
+      */
       
       $sess = $this->register_session(intval($row['user_id']), $username, $password, $level);
       if($sess)
@@ -672,28 +772,54 @@
         $this->style = $row['style'];
         
         if($level > USER_LEVEL_MEMBER)
-          $this->sql('INSERT INTO '.table_prefix.'logs(log_type,action,time_id,date_string,author,edit_summary,page_text) VALUES(\'security\', \'admin_auth_good\', '.time().', \''.date('d M Y h:i a').'\', \''.$db->escape($username).'\', \''.$db->escape($_SERVER['REMOTE_ADDR']).'\', ' . intval($level) . ')');
+          $this->sql('INSERT INTO '.table_prefix.'logs(log_type,action,time_id,date_string,author,edit_summary,page_text) VALUES(\'security\', \'admin_auth_good\', '.time().', \''.enano_date('d M Y h:i a').'\', \''.$db->escape($username).'\', \''.$db->escape($_SERVER['REMOTE_ADDR']).'\', ' . intval($level) . ')');
         else
-          $this->sql('INSERT INTO '.table_prefix.'logs(log_type,action,time_id,date_string,author,edit_summary) VALUES(\'security\', \'auth_good\', '.time().', \''.date('d M Y h:i a').'\', \''.$db->escape($username).'\', \''.$db->escape($_SERVER['REMOTE_ADDR']).'\')');
+          $this->sql('INSERT INTO '.table_prefix.'logs(log_type,action,time_id,date_string,author,edit_summary) VALUES(\'security\', \'auth_good\', '.time().', \''.enano_date('d M Y h:i a').'\', \''.$db->escape($username).'\', \''.$db->escape($_SERVER['REMOTE_ADDR']).'\')');
         
         $code = $plugins->setHook('login_success');
         foreach ( $code as $cmd )
         {
           eval($cmd);
         }
-        return 'success';
+        return array(
+          'success' => true
+        );
       }
       else
-        return 'Your login credentials were correct, but an internal error occurred while registering the session key in the database.';
+        return array(
+          'success' => false,
+          'error' => 'backend_fail'
+        );
     }
     else
     {
       if($level > USER_LEVEL_MEMBER)
-        $this->sql('INSERT INTO '.table_prefix.'logs(log_type,action,time_id,date_string,author,edit_summary,page_text) VALUES(\'security\', \'admin_auth_bad\', '.time().', \''.date('d M Y h:i a').'\', \''.$db->escape($username).'\', \''.$db->escape($_SERVER['REMOTE_ADDR']).'\', ' . intval($level) . ')');
+        $this->sql('INSERT INTO '.table_prefix.'logs(log_type,action,time_id,date_string,author,edit_summary,page_text) VALUES(\'security\', \'admin_auth_bad\', '.time().', \''.enano_date('d M Y h:i a').'\', \''.$db->escape($username).'\', \''.$db->escape($_SERVER['REMOTE_ADDR']).'\', ' . intval($level) . ')');
       else
-        $this->sql('INSERT INTO '.table_prefix.'logs(log_type,action,time_id,date_string,author,edit_summary) VALUES(\'security\', \'auth_bad\', '.time().', \''.date('d M Y h:i a').'\', \''.$db->escape($username).'\', \''.$db->escape($_SERVER['REMOTE_ADDR']).'\')');
+        $this->sql('INSERT INTO '.table_prefix.'logs(log_type,action,time_id,date_string,author,edit_summary) VALUES(\'security\', \'auth_bad\', '.time().', \''.enano_date('d M Y h:i a').'\', \''.$db->escape($username).'\', \''.$db->escape($_SERVER['REMOTE_ADDR']).'\')');
         
-      return 'The username and/or password is incorrect.';
+      // Do we also need to increment the lockout countdown?
+      if ( $policy != 'disable' && !defined('IN_ENANO_INSTALL') )
+      {
+        $ipaddr = $db->escape($_SERVER['REMOTE_ADDR']);
+        // increment fail count
+        $this->sql('INSERT INTO '.table_prefix.'lockout(ipaddr, timestamp, action) VALUES(\'' . $ipaddr . '\', ' . time() . ', \'credential\');');
+        $fails++;
+        return array(
+            'success' => false,
+            'error' => ( $fails >= $threshold ) ? 'locked_out' : 'invalid_credentials',
+            'lockout_threshold' => $threshold,
+            'lockout_duration' => ( $duration / 60 ),
+            'lockout_fails' => $fails,
+            'time_rem' => ( $duration / 60 ),
+            'lockout_policy' => $policy
+          );
+      }
+        
+      return array(
+        'success' => false,
+        'error' => 'invalid_credentials'
+      );
     }
   }
   
@@ -707,7 +833,7 @@
    * @param int $level The privilege level we're authenticating for, defaults to 0
    */
   
-  function login_without_crypto($username, $password, $already_md5ed = false, $level = USER_LEVEL_MEMBER)
+  function login_without_crypto($username, $password, $already_md5ed = false, $level = USER_LEVEL_MEMBER, $captcha_hash = false, $captcha_code = false)
   {
     global $db, $session, $paths, $template, $plugins; // Common objects
     
@@ -723,6 +849,50 @@
       return $this->login_compat($username, $pass_hashed, $level);
     }
     
+    if ( !defined('IN_ENANO_INSTALL') )
+    {
+      // Lockout stuff
+      $threshold = ( $_ = getConfig('lockout_threshold') ) ? intval($_) : 5;
+      $duration  = ( $_ = getConfig('lockout_duration') ) ? intval($_) : 15;
+      // convert to minutes
+      $duration  = $duration * 60;
+      
+      // get the lockout status
+      $timestamp_cutoff = time() - $duration;
+      $ipaddr = $db->escape($_SERVER['REMOTE_ADDR']);
+      $q = $this->sql('SELECT timestamp FROM '.table_prefix.'lockout WHERE timestamp > ' . $timestamp_cutoff . ' AND ipaddr = \'' . $ipaddr . '\' ORDER BY timestamp DESC;');
+      $fails = $db->numrows();
+      
+      $policy = ( $x = getConfig('lockout_policy') && in_array(getConfig('lockout_policy'), array('lockout', 'disable', 'captcha')) ) ? getConfig('lockout_policy') : 'lockout';
+      $captcha_good = false;
+      if ( $policy == 'captcha' && $captcha_hash && $captcha_code )
+      {
+        // policy is captcha -- check if it's correct, and if so, bypass lockout check
+        $real_code = $this->get_captcha($captcha_hash);
+        $captcha_good = ( strtolower($real_code) === strtolower($captcha_code) );
+      }
+      if ( $policy != 'disable' && !$captcha_good )
+      {
+        if ( $fails >= $threshold )
+        {
+          // ooh boy, somebody's in trouble ;-)
+          $row = $db->fetchrow();
+          $db->free_result();
+          return array(
+              'success' => false,
+              'error' => 'locked_out',
+              'lockout_threshold' => $threshold,
+              'lockout_duration' => ( $duration / 60 ),
+              'lockout_fails' => $fails,
+              'lockout_policy' => $policy,
+              'time_rem' => ( $duration / 60 ) - round( ( time() - $row['timestamp'] ) / 60 ),
+              'lockout_last_time' => $row['timestamp']
+            );
+        }
+      }
+      $db->free_result();
+    }
+    
     // Instanciate the Rijndael encryption object
     $aes = AESCrypt::singleton(AES_BITS, AES_BLOCKSIZE);
     
@@ -731,14 +901,35 @@
     
     // Retrieve the real password from the database
     $this->sql('SELECT password,old_encryption,user_id,user_level,temp_password,temp_password_time FROM '.table_prefix.'users WHERE ' . ENANO_SQLFUNC_LOWERCASE . '(username)=\''.$this->prepare_text(strtolower($username)).'\';');
-    if ( $db->numrows() < 1 )
+    if($db->numrows() < 1)
     {
       // This wasn't logged in <1.0.2, dunno how it slipped through
       if($level > USER_LEVEL_MEMBER)
-        $this->sql('INSERT INTO '.table_prefix.'logs(log_type,action,time_id,date_string,author,edit_summary,page_text) VALUES(\'security\', \'admin_auth_bad\', '.time().', \''.date('d M Y h:i a').'\', \''.$db->escape($username).'\', \''.$db->escape($_SERVER['REMOTE_ADDR']).'\', ' . intval($level) . ')');
+        $this->sql('INSERT INTO '.table_prefix.'logs(log_type,action,time_id,date_string,author,edit_summary,page_text) VALUES(\'security\', \'admin_auth_bad\', '.time().', \''.enano_date('d M Y h:i a').'\', \''.$db->escape($username).'\', \''.$db->escape($_SERVER['REMOTE_ADDR']).'\', ' . intval($level) . ')');
       else
-        $this->sql('INSERT INTO '.table_prefix.'logs(log_type,action,time_id,date_string,author,edit_summary) VALUES(\'security\', \'auth_bad\', '.time().', \''.date('d M Y h:i a').'\', \''.$db->escape($username).'\', \''.$db->escape($_SERVER['REMOTE_ADDR']).'\')');
-      return "The username and/or password is incorrect.";  
+        $this->sql('INSERT INTO '.table_prefix.'logs(log_type,action,time_id,date_string,author,edit_summary) VALUES(\'security\', \'auth_bad\', '.time().', \''.enano_date('d M Y h:i a').'\', \''.$db->escape($username).'\', \''.$db->escape($_SERVER['REMOTE_ADDR']).'\')');
+      
+      // Do we also need to increment the lockout countdown?
+      if ( @$policy != 'disable' && !defined('IN_ENANO_INSTALL') )
+      {
+        $ipaddr = $db->escape($_SERVER['REMOTE_ADDR']);
+        // increment fail count
+        $this->sql('INSERT INTO '.table_prefix.'lockout(ipaddr, timestamp, action) VALUES(\'' . $ipaddr . '\', ' . time() . ', \'credential\');');
+        $fails++;
+        return array(
+            'success' => false,
+            'error' => ( $fails >= $threshold ) ? 'locked_out' : 'invalid_credentials',
+            'lockout_threshold' => $threshold,
+            'lockout_duration' => ( $duration / 60 ),
+            'lockout_fails' => $fails,
+            'lockout_policy' => $policy
+          );
+      }
+      
+      return array(
+        'success' => false,
+        'error' => 'invalid_credentials'
+      );
     }
     $row = $db->fetchrow();
     
@@ -788,14 +979,17 @@
     if($success)
     {
       if((int)$level > (int)$row['user_level'])
-        return 'You are not authorized for this level of access.';
+        return array(
+          'success' => false,
+          'error' => 'too_big_for_britches'
+        );
       $sess = $this->register_session(intval($row['user_id']), $username, $real_pass, $level);
       if($sess)
       {
         if($level > USER_LEVEL_MEMBER)
-          $this->sql('INSERT INTO '.table_prefix.'logs(log_type,action,time_id,date_string,author,edit_summary,page_text) VALUES(\'security\', \'admin_auth_good\', '.time().', \''.date('d M Y h:i a').'\', \''.$db->escape($username).'\', \''.$db->escape($_SERVER['REMOTE_ADDR']).'\', ' . intval($level) . ')');
+          $this->sql('INSERT INTO '.table_prefix.'logs(log_type,action,time_id,date_string,author,edit_summary,page_text) VALUES(\'security\', \'admin_auth_good\', '.time().', \''.enano_date('d M Y h:i a').'\', \''.$db->escape($username).'\', \''.$db->escape($_SERVER['REMOTE_ADDR']).'\', ' . intval($level) . ')');
         else
-          $this->sql('INSERT INTO '.table_prefix.'logs(log_type,action,time_id,date_string,author,edit_summary) VALUES(\'security\', \'auth_good\', '.time().', \''.date('d M Y h:i a').'\', \''.$db->escape($username).'\', \''.$db->escape($_SERVER['REMOTE_ADDR']).'\')');
+          $this->sql('INSERT INTO '.table_prefix.'logs(log_type,action,time_id,date_string,author,edit_summary) VALUES(\'security\', \'auth_good\', '.time().', \''.enano_date('d M Y h:i a').'\', \''.$db->escape($username).'\', \''.$db->escape($_SERVER['REMOTE_ADDR']).'\')');
         
         $code = $plugins->setHook('login_success');
         foreach ( $code as $cmd )
@@ -803,19 +997,44 @@
           eval($cmd);
         }
         
-        return 'success';
+        return array(
+          'success' => true
+          );
       }
       else
-        return 'Your login credentials were correct, but an internal error occured while registering the session key in the database.';
+        return array(
+          'success' => false,
+          'error' => 'backend_fail'
+        );
     }
     else
     {
       if($level > USER_LEVEL_MEMBER)
-        $this->sql('INSERT INTO '.table_prefix.'logs(log_type,action,time_id,date_string,author,edit_summary,page_text) VALUES(\'security\', \'admin_auth_bad\', '.time().', \''.date('d M Y h:i a').'\', \''.$db->escape($username).'\', \''.$db->escape($_SERVER['REMOTE_ADDR']).'\', ' . intval($level) . ')');
+        $this->sql('INSERT INTO '.table_prefix.'logs(log_type,action,time_id,date_string,author,edit_summary,page_text) VALUES(\'security\', \'admin_auth_bad\', '.time().', \''.enano_date('d M Y h:i a').'\', \''.$db->escape($username).'\', \''.$db->escape($_SERVER['REMOTE_ADDR']).'\', ' . intval($level) . ')');
       else
-        $this->sql('INSERT INTO '.table_prefix.'logs(log_type,action,time_id,date_string,author,edit_summary) VALUES(\'security\', \'auth_bad\', '.time().', \''.date('d M Y h:i a').'\', \''.$db->escape($username).'\', \''.$db->escape($_SERVER['REMOTE_ADDR']).'\')');
+        $this->sql('INSERT INTO '.table_prefix.'logs(log_type,action,time_id,date_string,author,edit_summary) VALUES(\'security\', \'auth_bad\', '.time().', \''.enano_date('d M Y h:i a').'\', \''.$db->escape($username).'\', \''.$db->escape($_SERVER['REMOTE_ADDR']).'\')');
         
-      return 'The username and/or password is incorrect.';
+      // Do we also need to increment the lockout countdown?
+      if ( $policy != 'disable' && !defined('IN_ENANO_INSTALL') )
+      {
+        $ipaddr = $db->escape($_SERVER['REMOTE_ADDR']);
+        // increment fail count
+        $this->sql('INSERT INTO '.table_prefix.'lockout(ipaddr, timestamp, action) VALUES(\'' . $ipaddr . '\', ' . time() . ', \'credential\');');
+        $fails++;
+        return array(
+            'success' => false,
+            'error' => ( $fails >= $threshold ) ? 'locked_out' : 'invalid_credentials',
+            'lockout_threshold' => $threshold,
+            'lockout_duration' => ( $duration / 60 ),
+            'lockout_fails' => $fails,
+            'lockout_policy' => $policy
+          );
+      }
+        
+      return array(
+        'success' => false,
+        'error' => 'invalid_credentials'
+      );
     }
   }
   
@@ -949,6 +1168,7 @@
   function register_guest_session()
   {
     global $db, $session, $paths, $template, $plugins; // Common objects
+    global $lang;
     $this->username = $_SERVER['REMOTE_ADDR'];
     $this->user_level = USER_LEVEL_GUEST;
     if($this->compat || defined('IN_ENANO_INSTALL'))
@@ -962,6 +1182,13 @@
       $this->style = ( isset($_GET['style']) && file_exists(ENANO_ROOT.'/themes/'.$this->theme . '/css/'.$_GET['style'].'.css' )) ? $_GET['style'] : substr($template->named_theme_list[$this->theme]['default_style'], 0, strlen($template->named_theme_list[$this->theme]['default_style'])-4);
     }
     $this->user_id = 1;
+    // This is a VERY special case we are allowing. It lets the installer create languages using the Enano API.
+    if ( !defined('ENANO_ALLOW_LOAD_NOLANG') )
+    {
+      $language = ( isset($_GET['lang']) && preg_match('/^[a-z0-9_]+$/', @$_GET['lang']) ) ? $_GET['lang'] : intval(getConfig('default_language'));
+      $lang = new Language($language);
+      @setlocale(LC_ALL, $lang->lang_code);
+    }
   }
   
   /**
@@ -973,7 +1200,8 @@
   function validate_session($key)
   {
     global $db, $session, $paths, $template, $plugins; // Common objects
-    $aes = new AESCrypt(AES_BITS, AES_BLOCKSIZE, true);
+    profiler_log("SessionManager: checking session: " . sha1($key));
+    $aes = AESCrypt::singleton(AES_BITS, AES_BLOCKSIZE);
     $decrypted_key = $aes->decrypt($key, $this->private_key, ENC_HEX);
     
     if ( !$decrypted_key )
@@ -992,8 +1220,8 @@
     $salt = $db->escape($keydata[3]);
     // using a normal call to $db->sql_query to avoid failing on errors here
     $query = $db->sql_query('SELECT u.user_id AS uid,u.username,u.password,u.email,u.real_name,u.user_level,u.theme,u.style,u.signature,' . "\n"
-                             . '    u.reg_time,u.account_active,u.activation_key,k.source_ip,k.time,k.auth_level,COUNT(p.message_id) AS num_pms,' . "\n"
-                             . '    x.* FROM '.table_prefix.'session_keys AS k' . "\n"
+                             . '    u.reg_time,u.account_active,u.activation_key,u.user_lang,k.source_ip,k.time,k.auth_level,COUNT(p.message_id) AS num_pms,' . "\n"
+                             . '    u.user_timezone, x.* FROM '.table_prefix.'session_keys AS k' . "\n"
                              . '  LEFT JOIN '.table_prefix.'users AS u' . "\n"
                              . '    ON ( u.user_id=k.user_id )' . "\n"
                              . '  LEFT JOIN '.table_prefix.'users_extra AS x' . "\n"
@@ -1002,11 +1230,11 @@
                              . '    ON ( p.message_to=u.username AND p.message_read=0 )' . "\n"
                              . '  WHERE k.session_key=\''.$keyhash.'\'' . "\n"
                              . '    AND k.salt=\''.$salt.'\'' . "\n"
-                             . '  GROUP BY u.user_id,u.username,u.password,u.email,u.real_name,u.user_level,u.theme,u.style,u.signature,u.reg_time,u.account_active,u.activation_key,k.source_ip,k.time,k.auth_level,x.user_id, x.user_aim, x.user_yahoo, x.user_msn, x.user_xmpp, x.user_homepage, x.user_location, x.user_job, x.user_hobbies, x.email_public;');
+                             . '  GROUP BY u.user_id,u.username,u.password,u.email,u.real_name,u.user_level,u.theme,u.style,u.signature,u.reg_time,u.account_active,u.activation_key,u.user_lang,k.source_ip,k.time,k.auth_level,x.user_id, x.user_aim, x.user_yahoo, x.user_msn, x.user_xmpp, x.user_homepage, x.user_location, x.user_job, x.user_hobbies, x.email_public;');
     
     if ( !$query )
     {
-      $query = $this->sql('SELECT u.user_id AS uid,u.username,u.password,u.email,u.real_name,u.user_level,u.theme,u.style,u.signature,u.reg_time,u.account_active,u.activation_key,k.source_ip,k.time,k.auth_level,COUNT(p.message_id) AS num_pms FROM '.table_prefix.'session_keys AS k
+      $query = $this->sql('SELECT u.user_id AS uid,u.username,u.password,u.email,u.real_name,u.user_level,u.theme,u.style,u.signature,u.reg_time,u.account_active,u.activation_key,k.source_ip,k.time,k.auth_level,COUNT(p.message_id) AS num_pms, 1440 AS user_timezone FROM '.table_prefix.'session_keys AS k
                              LEFT JOIN '.table_prefix.'users AS u
                                ON ( u.user_id=k.user_id )
                              LEFT JOIN '.table_prefix.'privmsgs AS p
@@ -1066,13 +1294,18 @@
     $user_extra = array();
     foreach ( array('user_aim', 'user_yahoo', 'user_msn', 'user_xmpp', 'user_homepage', 'user_location', 'user_job', 'user_hobbies', 'email_public') as $column )
     {
-      $user_extra[$column] = $row[$column];
+      if ( isset($row[$column]) )
+        $user_extra[$column] = $row[$column];
     }
     
     $this->user_extra = $user_extra;
     // Leave the rest to PHP's automatic garbage collector ;-)
     
     $row['password'] = md5($real_pass);
+    $row['user_timezone'] = intval($row['user_timezone']) - 1440;
+    
+    profiler_log("SessionManager: finished session check");
+    
     return $row;
   }
   
@@ -1087,7 +1320,7 @@
     global $db, $session, $paths, $template, $plugins; // Common objects
     $key = $db->escape($key);
     
-    $query = $this->sql('SELECT u.user_id,u.username,u.password,u.email,u.real_name,u.user_level,k.source_ip,k.salt,k.time,k.auth_level FROM '.table_prefix.'session_keys AS k
+    $query = $this->sql('SELECT u.user_id,u.username,u.password,u.email,u.real_name,u.user_level,k.source_ip,k.salt,k.time,k.auth_level,1440 AS user_timezone FROM '.table_prefix.'session_keys AS k
                            LEFT JOIN '.table_prefix.'users AS u
                              ON u.user_id=k.user_id
                            WHERE k.session_key=\''.$key.'\';');
@@ -1132,6 +1365,8 @@
       return false;
     }
     
+    $row['user_timezone'] = intval($row['user_timezone']) - 1440;
+    
     return $row;
   }
    
@@ -1149,7 +1384,14 @@
     if($level > USER_LEVEL_CHPREF)
     {
       $aes = AESCrypt::singleton(AES_BITS, AES_BLOCKSIZE);
-      if(!$this->user_logged_in || $this->auth_level < USER_LEVEL_MOD) return 'success';
+      if(!$this->user_logged_in || $this->auth_level < ( USER_LEVEL_MEMBER + 1))
+      {
+        return 'success';
+      }
+      // See if we can get rid of the cached decrypted session key
+      $key_bin = $aes->hextostring(strrev($this->sid_super));
+      $key_hash = sha1($key_bin . '::' . $this->private_key);
+      aes_decrypt_cache_destroy($key_hash);
       // Destroy elevated privileges
       $keyhash = md5(strrev($this->sid_super));
       $this->sql('DELETE FROM '.table_prefix.'session_keys WHERE session_key=\''.$keyhash.'\' AND user_id=\'' . $this->user_id . '\';');
@@ -1160,6 +1402,11 @@
     {
       if($this->user_logged_in)
       {
+        $aes = AESCrypt::singleton(AES_BITS, AES_BLOCKSIZE);
+        // See if we can get rid of the cached decrypted session key
+        $key_bin = $aes->hextostring($this->sid);
+        $key_hash = sha1($key_bin . '::' . $this->private_key);
+        aes_decrypt_cache_destroy($key_hash);
         // Completely destroy our session
         if($this->auth_level > USER_LEVEL_CHPREF)
         {
@@ -1358,6 +1605,8 @@
   function check_banlist()
   {
     global $db, $session, $paths, $template, $plugins; // Common objects
+    global $lang;
+    
     $col_reason = ( $this->compat ) ? '"No reason entered (session manager is in compatibility mode)" AS reason' : 'reason';
     $banned = false;
     if ( $this->user_logged_in )
@@ -1388,9 +1637,9 @@
       $q = $this->sql($sql);
       if ( $db->numrows() > 0 )
       {
-        while ( list($reason, $ban_value, $ban_type, $is_regex) = $db->fetchrow_num() )
+        while ( list($reason_temp, $ban_value, $ban_type, $is_regex) = $db->fetchrow_num() )
         {
-          if ( $ban_type == BAN_IP && $row['is_regex'] != 1 )
+          if ( $ban_type == BAN_IP && $is_regex != 1 )
           {
             // check range
             $regexp = parse_ip_range_regex($ban_value);
@@ -1400,6 +1649,7 @@
             }
             if ( preg_match("/$regexp/", $_SERVER['REMOTE_ADDR']) )
             {
+              $reason = $reason_temp;
               $banned = true;
             }
           }
@@ -1407,6 +1657,7 @@
           {
             // User is banned
             $banned = true;
+            $reason = $reason_temp;
           }
         }
       }
@@ -1432,7 +1683,7 @@
       $q = $this->sql($sql);
       if ( $db->numrows() > 0 )
       {
-        while ( list($reason, $ban_value, $ban_type, $is_regex) = $db->fetchrow_num() )
+        while ( list($reason_temp, $ban_value, $ban_type, $is_regex) = $db->fetchrow_num() )
         {
           if ( $ban_type == BAN_IP && $row['is_regex'] != 1 )
           {
@@ -1442,12 +1693,14 @@
               continue;
             if ( preg_match("/$regexp/", $_SERVER['REMOTE_ADDR']) )
             {
+              $reason = $reason_temp;
               $banned = true;
             }
           }
           else
           {
             // User is banned
+            $reason = $reason_temp;
             $banned = true;
           }
         }
@@ -1457,7 +1710,7 @@
     if ( $banned && $paths->get_pageid_from_url() != $paths->nslist['Special'].'CSS' )
     {
       // This guy is banned - kill the session, kill the database connection, bail out, and be pretty about it
-      die_semicritical('Ban notice', '<div class="error-box">You have been banned from this website. Please contact the site administrator for more information.<br /><br />Reason:<br />'.$reason.'</div>');
+      die_semicritical($lang->get('user_ban_msg_title'), '<p>' . $lang->get('user_ban_msg_body') . '</p><div class="error-box"><b>' . $lang->get('user_ban_lbl_reason') . '</b><br />' . $reason . '</div>');
       exit;
     }
   }
@@ -1476,11 +1729,19 @@
   function create_user($username, $password, $email, $real_name = '', $coppa = false)
   {
     global $db, $session, $paths, $template, $plugins; // Common objects
+    global $lang;
     
     // Initialize AES
     $aes = AESCrypt::singleton(AES_BITS, AES_BLOCKSIZE);
     
-    if(!preg_match('#^'.$this->valid_username.'$#', $username)) return 'The username you chose contains invalid characters.';
+    // Since we're recording IP addresses, make sure the user's IP is safe.
+    $ip =& $_SERVER['REMOTE_ADDR'];
+    if ( !is_valid_ip($ip) )
+      return 'Invalid IP';
+    
+    if ( !preg_match('#^'.$this->valid_username.'$#', $username) )
+      return $lang->get('user_reg_err_username_banned_chars');
+    
     $username = str_replace('_', ' ', $username);
     $user_orig = $username;
     $username = $this->prepare_text($username);
@@ -1491,31 +1752,23 @@
     $q = $this->sql('SELECT * FROM '.table_prefix.'users WHERE ' . ENANO_SQLFUNC_LOWERCASE . '(username)=\''.strtolower($username).'\' OR email=\''.$email.'\''.$nameclause.';');
     if($db->numrows() > 0)
     {
-      $r = 'The ';
-      $i=0;
       $row = $db->fetchrow();
-      // Wow! An error checker that actually speaks English with the properest grammar! :-P
+      $str = 'user_reg_err_dupe';
+      
       if ( $row['username'] == $username )
       {
-        $r .= 'username';
-        $i++;
+        $str .= '_username';
       }
       if ( $row['email'] == $email )
       {
-        if($i) $r.=', ';
-        $r .= 'e-mail address';
-        $i++;
+        $str .= '_email';
       }
       if ( $row['real_name'] == $real_name && $real_name != '' )
       {
-        if($i) $r.=', and ';
-        $r .= 'real name';
-        $i++;
+        $str .= '_realname';
       }
-      $r .= ' that you entered ';
-      $r .= ( $i == 1 ) ? 'is' : 'are';
-      $r .= ' already in use by another user.';
-      return $r;
+      
+      return $lang->get($str);
     }
     
     // Is the password strong enough?
@@ -1525,7 +1778,7 @@
       $pass_score = password_score($password);
       if ( $pass_score < $min_score )
       {
-        return 'The password you entered did not meet the complexity requirements for this site. Please choose a stronger password.';
+        return $lang->get('user_reg_err_password_too_weak');
       }
     }
     
@@ -1554,16 +1807,15 @@
     $actkey = sha1 ( microtime() . mt_rand() );
 
     // We good, create the user
-    $this->sql('INSERT INTO '.table_prefix.'users ( username, password, email, real_name, theme, style, reg_time, account_active, activation_key, user_level, user_coppa ) VALUES ( \''.$username.'\', \''.$password.'\', \''.$email.'\', \''.$real_name.'\', \''.$template->default_theme.'\', \''.$template->default_style.'\', '.time().', '.$active.', \''.$actkey.'\', '.USER_LEVEL_CHPREF.', ' . $coppa_col . ' );');
+    $this->sql('INSERT INTO '.table_prefix.'users ( username, password, email, real_name, theme, style, reg_time, account_active, activation_key, user_level, user_coppa, user_registration_ip ) VALUES ( \''.$username.'\', \''.$password.'\', \''.$email.'\', \''.$real_name.'\', \''.$template->default_theme.'\', \''.$template->default_style.'\', '.time().', '.$active.', \''.$actkey.'\', '.USER_LEVEL_CHPREF.', ' . $coppa_col . ', \'' . $ip . '\' );');
     
     // Get user ID and create users_extra entry
     $q = $this->sql('SELECT user_id FROM '.table_prefix."users WHERE username='$username';");
     if ( $db->numrows() > 0 )
     {
-      $row = $db->fetchrow();
+      list($user_id) = $db->fetchrow_num();
       $db->free_result();
       
-      $user_id =& $row['user_id'];
       $this->sql('INSERT INTO '.table_prefix.'users_extra(user_id) VALUES(' . $user_id . ');');
     }
     
@@ -1609,7 +1861,7 @@
           if(!$a)
           {
             $this->admin_activation_request($username);
-            return 'The activation e-mail could not be sent due to an internal error. This could possibly be due to an incorrect SMTP configuration. A request has been sent to the administrator to activate your account for you. ' . $a;
+            return $lang->get('user_reg_err_actmail_failed') . ' ' . $a;
           }
           break;
         case 'admin':
@@ -1638,6 +1890,7 @@
   function send_activation_mail($u, $actkey = false)
   {
     global $db, $session, $paths, $template, $plugins; // Common objects
+    global $lang;
     $q = $this->sql('SELECT username,email FROM '.table_prefix.'users WHERE user_id=2 OR user_level=' . USER_LEVEL_ADMIN . ' ORDER BY user_id ASC;');
     $un = $db->fetchrow();
     $admin_user = $un['username'];
@@ -1645,31 +1898,21 @@
     $r = $db->fetchrow();
     if ( empty($r['email']) )
       $db->_die('BUG: $session->send_activation_mail(): no e-mail address in row');
-    $message = 'Dear '.$u.',
-Thank you for registering on '.getConfig('site_name').'. Your account creation is almost complete. To complete the registration process, please click the following link or paste it into your web browser:
     
-';
-    if(isset($_SERVER['HTTPS'])) $prot = 'https';
-    else $prot = 'http';                                                                           
-    if($_SERVER['SERVER_PORT'] == '80') $p = '';
-    else $p = ':'.$_SERVER['SERVER_PORT'];
-    $sidbak = false;
-    if($this->sid_super)
-      $sidbak = $this->sid_super;
-    $this->sid_super = false;
-    $aklink = makeUrlNS('Special', 'ActivateAccount/'.str_replace(' ', '_', $u).'/'. ( ( is_string($actkey) ) ? $actkey : $r['activation_key'] ) );
-    if($sidbak)
-      $this->sid_super = $sidbak;
-    unset($sidbak);
-    $message .= "$prot://".$_SERVER['HTTP_HOST'].$p.$aklink;
-      $message .= "\n\nSincerely yours, \n$admin_user and the ".$_SERVER['HTTP_HOST']." administration team";
+    $aklink = makeUrlComplete('Special', 'ActivateAccount/'.str_replace(' ', '_', $u).'/'. ( ( is_string($actkey) ) ? $actkey : $r['activation_key'] ) );
+    $message = $lang->get('user_reg_activation_email', array(
+        'activation_link' => $aklink,
+        'admin_user' => $admin_user,
+        'username' => $u
+      ));
+      
     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'));
+      $result = smtp_send_email($r['email'], $lang->get('user_reg_activation_email_subject'), preg_replace("#(?<!\r)\n#s", "\n", $message), getConfig('contact_email'));
       if($result == 'success') $result = true;
       else { echo $result; $result = false; }
     } else {
-      $result = mail($r['email'], getConfig('site_name').' website account activation', preg_replace("#(?<!\r)\n#s", "\n", $message), 'From: '.getConfig('contact_email'));
+      $result = mail($r['email'], $lang->get('user_reg_activation_email_subject'), preg_replace("#(?<!\r)\n#s", "\n", $message), 'From: '.getConfig('contact_email'));
     }
     return $result;
   }
@@ -1682,8 +1925,8 @@
    
   function send_coppa_mail($u, $actkey = false)
   {
-    
     global $db, $session, $paths, $template, $plugins; // Common objects
+    global $lang;
     
     $q = $this->sql('SELECT username,email FROM '.table_prefix.'users WHERE user_id=2 OR user_level=' . USER_LEVEL_ADMIN . ' ORDER BY user_id ASC;');
     $un = $db->fetchrow();
@@ -1707,33 +1950,15 @@
     unset($sidbak);
     $link = "$prot://".$_SERVER['HTTP_HOST'].scriptPath;
     
-    $message = 'Dear parent or legal guardian,
-A child under the username ' . $u . ' recently registered on our website. The child provided your e-mail address as the one of his or her authorized parent or legal guardian, and to comply with the United States Childrens\' Online Privacy Protection act, we ask that all parents of children ages 13 or under please mail us a written form authorizing their child\'s use of our website.
-
-If you wish for your child to be allowed access to our website, please print and fill out the form below, and mail it to this address:
-
-' . getConfig('coppa_address') . '
-
-If you do NOT wish for your child to be allowed access to our site, you do not need to do anything - your child will not be able to access our site as a registered user unless you authorize their account activation.
-
-Authorization form:
--------------------------------- Cut here --------------------------------
-
-I, _______________________________________, the legal parent or guardian of the child registered on the website "' . getConfig('site_name') . '" as ' . $u . ', hereby give my authorization for the child\'s e-mail address, instant messaging information, location, and real name, to be collected and stored in a database owned and maintained by ' . getConfig('site_name') . ' at the child\'s option, and for the administrators of this website to use this information according to the privacy policy displayed on their website <' . $link . '>.
-
-Child\'s name:               _____________________________________
-
-Child\'s e-mail address:     _____________________________________
-(optional - if you don\'t provide this, we\'ll just send site-related e-mails to your e-mail address)
-
-Signature of parent or guardian:
-
-____________________________________________________
-
-Date (YYYY-MM-DD): ______ / _____ / _____
-
--------------------------------- Cut here --------------------------------';
-    $message .= "\n\nSincerely yours, \n$admin_user and the ".$_SERVER['HTTP_HOST']." administration team";
+    $message = $lang->get(
+        'user_reg_activation_email_coppa',
+        array(
+          'username' => $u,
+          'admin_user' => $admin_user,
+          'site_link' => $link
+        )
+      );
+    
     
     if(getConfig('smtp_enabled') == '1')
     {
@@ -1764,6 +1989,8 @@
   function mail_password_reset($user)
   {
     global $db, $session, $paths, $template, $plugins; // Common objects
+    global $lang;
+    
     if(is_int($user))
     {
       $q = $this->sql('SELECT user_id,username,email FROM '.table_prefix.'users WHERE user_id='.$user.';'); // This is SAFE! This is only called if $user is an integer
@@ -1783,24 +2010,13 @@
     $this->register_temp_password($row['user_id'], $temp_pass);
     
     $site_name = getConfig('site_name');
-    
-    $message = "Dear {$row['username']},
-    
-Someone (hopefully you) on the {$site_name} website requested that a new password be created.
-
-The request was sent from the IP address {$_SERVER['REMOTE_ADDR']}.
-
-If you did not request the new password, then you do not need to do anything; the password will be invalidated after 24 hours.
-
-If you did request this password, then please log in using the password shown below:
-
-  Password: {$temp_pass}
-  
-After you log in using this password, you will be able to reset your real password. You can only log in using this temporary password once.
-
-Sincerely yours,
-The {$site_name} administration team
-";
+ 
+    $message = $lang->get('userfuncs_passreset_email', array(
+        'username' => $row['username'],
+        'site_name' => $site_name,
+        'remote_addr' => $_SERVER['REMOTE_ADDR'],
+        'temp_pass' => $temp_pass
+      ));
     
     if(getConfig('smtp_enabled') == '1')
     {
@@ -1842,7 +2058,7 @@
   function admin_activation_request($u)
   {
     global $db;
-    $this->sql('INSERT INTO '.table_prefix.'logs(log_type, action, time_id, date_string, author, edit_summary) VALUES(\'admin\', \'activ_req\', '.time().', \''.date('d M Y h:i a').'\', \''.$this->username.'\', \''.$db->escape($u).'\');');
+    $this->sql('INSERT INTO '.table_prefix.'logs(log_type, action, time_id, date_string, author, edit_summary) VALUES(\'admin\', \'activ_req\', '.time().', \''.enano_date('d M Y h:i a').'\', \''.$this->username.'\', \''.$db->escape($u).'\');');
   }
   
   /**
@@ -1858,11 +2074,11 @@
     $r = mysql_affected_rows();
     if ( $r > 0 )
     {
-      $e = $this->sql('INSERT INTO '.table_prefix.'logs(log_type,action,time_id,date_string,author,edit_summary) VALUES(\'security\', \'activ_good\', '.time().', \''.date('d M Y h:i a').'\', \''.$db->escape($user).'\', \''.$_SERVER['REMOTE_ADDR'].'\')');
+      $e = $this->sql('INSERT INTO '.table_prefix.'logs(log_type,action,time_id,date_string,author,edit_summary) VALUES(\'security\', \'activ_good\', '.time().', \''.enano_date('d M Y h:i a').'\', \''.$db->escape($user).'\', \''.$_SERVER['REMOTE_ADDR'].'\')');
     }
     else
     {
-      $e = $this->sql('INSERT INTO '.table_prefix.'logs(log_type,action,time_id,date_string,author,edit_summary) VALUES(\'security\', \'activ_bad\', '.time().', \''.date('d M Y h:i a').'\', \''.$db->escape($user).'\', \''.$_SERVER['REMOTE_ADDR'].'\')');
+      $e = $this->sql('INSERT INTO '.table_prefix.'logs(log_type,action,time_id,date_string,author,edit_summary) VALUES(\'security\', \'activ_bad\', '.time().', \''.enano_date('d M Y h:i a').'\', \''.$db->escape($user).'\', \''.$_SERVER['REMOTE_ADDR'].'\')');
     }
     return $r;
   }
@@ -1876,46 +2092,71 @@
   
   function userlevel_to_string($user_level, $short = false)
   {
-    if ( $short )
+    global $lang;
+    
+    static $levels = array(
+        'short' => array(
+            USER_LEVEL_GUEST => 'Guest',
+            USER_LEVEL_MEMBER => 'Member',
+            USER_LEVEL_CHPREF => 'Sensitive preferences changeable',
+            USER_LEVEL_MOD => 'Moderator',
+            USER_LEVEL_ADMIN => 'Administrative'
+          ),
+        'long' => array(
+            USER_LEVEL_GUEST => 'Low - guest privileges',
+            USER_LEVEL_MEMBER => 'Standard - normal member level',
+            USER_LEVEL_CHPREF => 'Medium - user can change his/her own e-mail address and password',
+            USER_LEVEL_MOD => 'High - moderator privileges',
+            USER_LEVEL_ADMIN => 'Highest - administrative privileges'
+          ),
+        'l10n' => false
+      );
+    
+    if ( is_object($lang) && !$levels['l10n'] )
     {
-      switch ( $user_level )
-      {
-        case USER_LEVEL_GUEST:
-          return 'Guest';
-        case USER_LEVEL_MEMBER:
-          return 'Member';
-        case USER_LEVEL_CHPREF:
-          return 'Sensitive preferences changeable';
-        case USER_LEVEL_MOD:
-          return 'Moderator';
-        case USER_LEVEL_ADMIN:
-          return 'Administrative';
-        default:
-          return "Level $user_level";
-      }
+      $levels = array(
+          'short' => array(
+              USER_LEVEL_GUEST => $lang->get('user_level_short_guest'),
+              USER_LEVEL_MEMBER => $lang->get('user_level_short_member'),
+              USER_LEVEL_CHPREF => $lang->get('user_level_short_chpref'),
+              USER_LEVEL_MOD => $lang->get('user_level_short_mod'),
+              USER_LEVEL_ADMIN => $lang->get('user_level_short_admin')
+            ),
+          'long' => array(
+              USER_LEVEL_GUEST => $lang->get('user_level_long_guest'),
+              USER_LEVEL_MEMBER => $lang->get('user_level_long_member'),
+              USER_LEVEL_CHPREF => $lang->get('user_level_long_chpref'),
+              USER_LEVEL_MOD => $lang->get('user_level_long_mod'),
+              USER_LEVEL_ADMIN => $lang->get('user_level_long_admin')
+            ),
+          'l10n' => true
+        );
+    }
+    
+    $key = ( $short ) ? 'short' : 'long';
+    if ( isset($levels[$key][$user_level]) )
+    {
+      return $levels[$key][$user_level];
     }
     else
     {
-      switch ( $user_level )
+      if ( $short )
       {
-        case USER_LEVEL_GUEST:
-          return 'Low - guest privileges';
-        case USER_LEVEL_MEMBER:
-          return 'Standard - normal member level';
-        case USER_LEVEL_CHPREF:
-          return 'Medium - user can change his/her own e-mail address and password';
-        case USER_LEVEL_MOD:
-          return 'High - moderator privileges';
-        case USER_LEVEL_ADMIN:
-          return 'Highest - administrative privileges';
-        default:
-          return "Unknown ($user_level)";
+        return ( is_object($lang) ) ? $lang->get('user_level_short_unknown', array('user_level' => $user_level)) : "Unknown - $user_level";
+      }
+      else
+      {
+        return ( is_object($lang) ) ? $lang->get('user_level_long_unknown', array('user_level' => $user_level)) : "Unknown level ($user_level)";
       }
     }
+    
+    return 'Linux rocks!';
+    
   }
   
   /**
    * Updates a user's information in the database. Note that any of the values except $user_id can be false if you want to preserve the old values.
+   * Not localized because this really isn't used a whole lot anymore.
    * @param int $user_id The user ID of the user to update - this cannot be changed
    * @param string $username The new username
    * @param string $old_pass The current password - only required if sessionManager::$user_level < USER_LEVEL_ADMIN. This should usually be an UNENCRYPTED string. This can also be an array - if it is, key 0 is treated as data AES-encrypted with key 1
@@ -2345,6 +2586,8 @@
     $s = '';
     foreach($perms as $perm => $ac)
     {
+      if ( $ac == 'i' )
+        continue;
       $s .= "$perm=$ac;";
     }
     return $s;
@@ -2393,6 +2636,31 @@
   }
   
   /**
+   * Merges two ACL arrays, but instead of calculating inheritance for missing permission types, just returns 'i' for that type. Useful
+   * for explicitly requiring inheritance in ACL editing interfaces
+   * @param array $perm1 The first set of permissions
+   * @param array $perm2 The second, authoritative set of permissions
+   */
+  
+  function acl_merge_inherit($perm1, $perm2)
+  {
+    foreach ( $perm1 as $type => $level )
+    {
+      $perm1[$type][$level] = 'i';
+    }
+    $ret = $perm1;
+    foreach ( $perm2 as $type => $level )
+    {
+      if ( isset( $ret[$type] ) )
+      {
+        if ( $ret[$type] != AUTH_DENY )
+          $ret[$type] = $level;
+      }
+    }
+    return $ret;
+  }
+  
+  /**
    * Merges the ACL array sent with the current permissions table, deciding precedence based on whether defaults are in effect or not.
    * @param array The array to merge into the master ACL list
    * @param bool If true, $perm is treated as the "new default"
@@ -2491,32 +2759,83 @@
   /**
    * Makes a CAPTCHA code and caches the code in the database
    * @param int $len The length of the code, in bytes
+   * @param string Optional, the hash to reuse
    * @return string A unique identifier assigned to the code. This hash should be passed to sessionManager::getCaptcha() to retrieve the code.
    */
   
-  function make_captcha($len = 7)
+  function make_captcha($len = 7, $hash = '')
   {
+    global $db, $session, $paths, $template, $plugins; // Common objects
     $code = $this->generate_captcha_code($len);
-    $hash = md5(microtime() . mt_rand());
-    $this->sql('INSERT INTO '.table_prefix.'session_keys(session_key,salt,auth_level,source_ip,user_id) VALUES(\''.$hash.'\', \'\', -1, \''.ip2hex($_SERVER['REMOTE_ADDR']).'\', -2);');
+    if ( !preg_match('/^[a-f0-9]{32}([a-z0-9]{8})?$/', $hash) )
+      $hash = md5(microtime() . mt_rand());
+    $session_data = $db->escape(serialize(array()));
+    
+    // sanity check
+    if ( !is_valid_ip(@$_SERVER['REMOTE_ADDR']) || !is_int($this->user_id) )
+      return false;
+    
+    $this->sql('DELETE FROM ' . table_prefix . "captcha WHERE session_id = '$hash';");
+    $this->sql('INSERT INTO ' . table_prefix . 'captcha(session_id, code, session_data, source_ip, user_id)' . " VALUES('$hash', '$code', '$session_data', '{$_SERVER['REMOTE_ADDR']}', {$this->user_id});");
     return $hash;
   }
   
   /**
-   * Generates the actual confirmation code text.
-   * @param int String length
+   * Generates a "pronouncable" or "human-friendly" word using various phonics rules
+   * @param int Optional. The length of the word.
    * @return string
    */
   
   function generate_captcha_code($len = 7)
   {
-    $chars = array('A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '1', '2', '3', '4', '5', '6', '7', '8', '9');
-    $s = '';
+    // don't use k and x, they get mixed up a lot
+    $consonants = 'bcdfghmnpqrsvwyz';
+    $vowels = 'aeiou';
+    $prev = 'vowel';
+    $prev_l = '';
+    $word = '';
+    $allow_next_vowel = true;
     for ( $i = 0; $i < $len; $i++ )
     {
-      $s .= $chars[mt_rand(0, count($chars)-1)];
+      if ( $prev == 'vowel' )
+      {
+        $allow_next_vowel = false;
+        if ( $prev_l == 'o' && mt_rand(0, 3) == 3 && $allow_next_vowel )
+          $word .= 'i';
+        else if ( $prev_l == 'q' && mt_rand(0, 3) != 1 && $allow_next_vowel )
+          $word .= 'u';
+        else if ( $prev_l == 'o' && mt_rand(0, 3) == 2 && $allow_next_vowel )
+          $word .= 'u';
+        else if ( $prev_l == 'a' && mt_rand(0, 3) == 3 && $allow_next_vowel )
+          $word .= 'i';
+        else if ( $prev_l == 'a' && mt_rand(0, 10) == 7 && $allow_next_vowel )
+          $word .= 'o';
+        else if ( $prev_l == 'a' && mt_rand(0, 7) == 2 && $allow_next_vowel )
+          $word .= 'u';
+        else
+        {
+          $allow_next_vowel = true;
+          $word .= $consonants{mt_rand(0, (strlen($consonants)-1))};
+        }
+      }
+      else if ( $prev == 'consonant' )
+      {
+        if ( $prev_l == 'p' && mt_rand(0, 7) == 4 )
+          $word .= 't';
+        else if ( $prev_l == 'p' && mt_rand(0, 5) == 1 )
+          $word .= 'h';
+        else
+          $word .= $vowels{mt_rand(0, (strlen($vowels)-1))};
+      }
+      $prev_l = substr($word, -1);
+      $l = ( mt_rand(0, 1) == 1 ) ? strtoupper($prev_l) : strtolower($prev_l);
+      $word = substr($word, 0, -1) . $l;
+      if ( strstr('aeiou', $prev_l) )
+        $prev = 'vowel';
+      else
+        $prev = 'consonant';
     }
-    return $s;
+    return $word;
   }
   
   /**
@@ -2528,15 +2847,33 @@
   function get_captcha($hash)
   {
     global $db, $session, $paths, $template, $plugins; // Common objects
-    $s = $this->sql('SELECT salt FROM '.table_prefix.'session_keys WHERE session_key=\''.$db->escape($hash).'\' AND source_ip=\''.ip2hex($_SERVER['REMOTE_ADDR']).'\';');
-    if ( $db->numrows() < 1 )
+    
+    if ( !preg_match('/^[a-f0-9]{32}([a-z0-9]{8})?$/', $hash) )
     {
+      die("session manager: bad captcha_hash $hash");
+      return false;
+    }
+    
+    // sanity check
+    if ( !is_valid_ip(@$_SERVER['REMOTE_ADDR']) )
+    {
+      die("session manager insanity: bad REMOTE_ADDR or invalid UID");
       return false;
     }
-    $r = $db->fetchrow();
+    
+    $q = $this->sql('SELECT code_id, code FROM ' . table_prefix . "captcha WHERE session_id = '$hash' AND source_ip = '{$_SERVER['REMOTE_ADDR']}';");
+    if ( $db->numrows() < 1 )
+    {
+      die("session manager: no rows for captcha_code $hash");
+      return false;
+    }
+    
+    list($code_id, $code) = $db->fetchrow_num();
+    
     $db->free_result();
-    $this->sql('DELETE FROM ' . table_prefix . 'session_keys WHERE salt=\'' . $db->escape($r['salt']) . '\';');
-    return $r['salt'];
+    $this->sql('DELETE FROM ' . table_prefix . "captcha WHERE code_id = $code_id;");
+    
+    return $code;
   }
   
   /**
@@ -2545,7 +2882,6 @@
   
   function kill_captcha()
   {
-    // $this->sql('DELETE FROM '.table_prefix.'session_keys WHERE user_id=-2 AND source_ip=\''.ip2hex($_SERVER['REMOTE_ADDR']).'\';');
     return true;
   }
   
@@ -2639,6 +2975,245 @@
     return $code;
   }
   
+  /**
+   * Backend code for the JSON login interface. Basically a frontend to the session API that takes all parameters in one huge array.
+   * @param array LoginAPI request
+   * @return array LoginAPI response
+   */
+  
+  function process_login_request($req)
+  {
+    global $db, $session, $paths, $template, $plugins; // Common objects
+    
+    // Setup EnanoMath and Diffie-Hellman
+    global $dh_supported;
+    $dh_supported = true;
+    try
+    {
+      require_once(ENANO_ROOT . '/includes/diffiehellman.php');
+    }
+    catch ( Exception $e )
+    {
+      $dh_supported = false;
+    }
+    global $_math;
+    
+    // Check for the mode
+    if ( !isset($req['mode']) )
+    {
+      return array(
+          'mode' => 'error',
+          'error' => 'ERR_JSON_NO_MODE'
+        );
+    }
+    
+    // Main processing switch
+    switch ( $req['mode'] )
+    {
+      default:
+        return array(
+            'mode' => 'error',
+            'error' => 'ERR_JSON_INVALID_MODE'
+          );
+        break;
+      case 'getkey':
+        
+        $this->start();
+        
+        // Query database for lockout info
+        $locked_out = false;
+        // are we locked out?
+        $threshold = ( $_ = getConfig('lockout_threshold') ) ? intval($_) : 5;
+        $duration  = ( $_ = getConfig('lockout_duration') ) ? intval($_) : 15;
+        // convert to minutes
+        $duration  = $duration * 60;
+        $policy = ( $x = getConfig('lockout_policy') && in_array(getConfig('lockout_policy'), array('lockout', 'disable', 'captcha')) ) ? getConfig('lockout_policy') : 'lockout';
+        if ( $policy != 'disable' )
+        {
+          $ipaddr = $db->escape($_SERVER['REMOTE_ADDR']);
+          $timestamp_cutoff = time() - $duration;
+          $q = $this->sql('SELECT timestamp FROM '.table_prefix.'lockout WHERE timestamp > ' . $timestamp_cutoff . ' AND ipaddr = \'' . $ipaddr . '\' ORDER BY timestamp DESC;');
+          $fails = $db->numrows();
+          $row = $db->fetchrow();
+          $locked_out = ( $fails >= $threshold );
+          $lockdata = array(
+              'locked_out' => $locked_out,
+              'lockout_threshold' => $threshold,
+              'lockout_duration' => ( $duration / 60 ),
+              'lockout_fails' => $fails,
+              'lockout_policy' => $policy,
+              'lockout_last_time' => $row['timestamp'],
+              'time_rem' => ( $duration / 60 ) - round( ( time() - $row['timestamp'] ) / 60 ),
+              'captcha' => ''
+            );
+          $db->free_result();
+        }
+        
+        $response = array('mode' => 'build_box');
+        $response['allow_diffiehellman'] = $dh_supported;
+        
+        $response['username'] = ( $this->user_logged_in ) ? $this->username : false;
+        $response['aes_key'] = $this->rijndael_genkey();
+        
+        // Lockout info
+        $response['locked_out'] = $locked_out;
+        
+        $response['lockout_info'] = $lockdata;
+        if ( $policy == 'captcha' && $locked_out )
+        {
+          $response['lockout_info']['captcha'] = $this->make_captcha();
+        }
+        
+        // Can we do Diffie-Hellman? If so, generate and stash a public/private key pair.
+        if ( $dh_supported )
+        {
+          $dh_key_priv = dh_gen_private();
+          $dh_key_pub = dh_gen_public($dh_key_priv);
+          $dh_key_priv = $_math->str($dh_key_priv);
+          $dh_key_pub = $_math->str($dh_key_pub);
+          $response['dh_public_key'] = $dh_key_pub;
+          // store the keys in the DB
+          $q = $db->sql_query('INSERT INTO ' . table_prefix . "diffiehellman( public_key, private_key ) VALUES ( '$dh_key_pub', '$dh_key_priv' );");
+          if ( !$q )
+            $db->die_json();
+        }
+        
+        return $response;
+        break;
+      case 'login_dh':
+        // User is requesting a login and has sent Diffie-Hellman data.
+        
+        //
+        // KEY RECONSTRUCTION
+        //
+        
+        $userinfo_crypt = $req['userinfo'];
+        $dh_public = $req['dh_public_key'];
+        $dh_hash = $req['dh_secret_hash'];
+        
+        // Check the key
+        if ( !preg_match('/^[0-9]+$/', $dh_public) || !preg_match('/^[0-9]+$/', $req['dh_client_key']) )
+        {
+          return array(
+            'mode' => 'error',
+            'error' => 'ERR_DH_KEY_NOT_NUMERIC'
+          );
+        }
+        
+        // Fetch private key
+        $q = $db->sql_query('SELECT private_key, key_id FROM ' . table_prefix . "diffiehellman WHERE public_key = '$dh_public';");
+        if ( !$q )
+          $db->die_json();
+        
+        if ( $db->numrows() < 1 )
+        {
+          return array(
+            'mode' => 'error',
+            'error' => 'ERR_DH_KEY_NOT_FOUND'
+          );
+        }
+        
+        list($dh_private, $dh_key_id) = $db->fetchrow_num();
+        $db->free_result();
+        
+        // We have the private key, now delete the key pair, we no longer need it
+        $q = $db->sql_query('DELETE FROM ' . table_prefix . "diffiehellman WHERE key_id = $dh_key_id;");
+        if ( !$q )
+          $db->die_json();
+        
+        // Generate the shared secret
+        $dh_secret = dh_gen_shared_secret($dh_private, $req['dh_client_key']);
+        $dh_secret = $_math->str($dh_secret);
+        
+        // Did we get all our math right?
+        $dh_secret_check = sha1($dh_secret);
+        if ( $dh_secret_check !== $dh_hash )
+        {
+          return array(
+            'mode' => 'error',
+            'error' => 'ERR_DH_HASH_NO_MATCH'
+          );
+        }
+        
+        // All good! Generate the AES key
+        $aes_key = substr(sha256($dh_secret), 0, ( AES_BITS / 4 ));
+      case 'login_aes':
+        if ( $req['mode'] == 'login_aes' )
+        {
+          // login_aes-specific code
+          $aes_key = $this->fetch_public_key($req['key_aes']);
+          if ( !$aes_key )
+          {
+            return array(
+              'mode' => 'error',
+              'error' => 'ERR_AES_LOOKUP_FAILED'
+            );
+          }
+          $userinfo_crypt = $req['userinfo'];
+        }
+        // shared between the two systems from here on out
+        
+        // decrypt user info
+        $aes_key = hexdecode($aes_key);
+        $aes = AESCrypt::singleton(AES_BITS, AES_BLOCKSIZE);
+        $userinfo_json = $aes->decrypt($userinfo_crypt, $aes_key, ENC_HEX);
+        if ( !$userinfo_json )
+        {
+          return array(
+            'mode' => 'error',
+            'error' => 'ERR_AES_DECRYPT_FAILED'
+          );
+        }
+        // de-JSON user info
+        try
+        {
+          $userinfo = enano_json_decode($userinfo_json);
+        }
+        catch ( Exception $e )
+        {
+          return array(
+            'mode' => 'error',
+            'error' => 'ERR_USERINFO_DECODE_FAILED'
+          );
+        }
+        
+        if ( !isset($userinfo['username']) || !isset($userinfo['password']) )
+        {
+          return array(
+            'mode' => 'error',
+            'error' => 'ERR_USERINFO_MISSING_VALUES'
+          );
+        }
+        
+        $username =& $userinfo['username'];
+        $password =& $userinfo['password'];
+        
+        // attempt the login
+        // function login_without_crypto($username, $password, $already_md5ed = false, $level = USER_LEVEL_MEMBER, $captcha_hash = false, $captcha_code = false)
+        $login_result = $this->login_without_crypto($username, $password, false, intval($req['level']), @$req['captcha_hash'], @$req['captcha_code']);
+        
+        if ( $login_result['success'] )
+        {
+          return array(
+              'mode' => 'login_success',
+              'key' => ( $this->sid_super ) ? $this->sid_super : false
+            );
+        }
+        else
+        {
+          return array(
+              'mode' => 'login_failure',
+              'error_code' => $login_result['error'],
+              // Use this to provide a way to respawn the login box
+              'respawn_info' => $this->process_login_request(array('mode' => 'getkey'))
+            );
+        }
+        
+        break;
+    }
+    
+  }
+  
 }
 
 /**
@@ -2913,7 +3488,7 @@
     {
       if ( isset($perm[$i]) )
       {
-        if ( $is_everyone && !$this->acl_defaults_used[$i] )
+        if ( $is_everyone && !@$this->acl_defaults_used[$i] )
           continue;
         // Decide precedence
         if ( isset($this->acl_defaults_used[$i]) )
--- a/includes/stats.php	Fri Feb 22 12:46:51 2008 -0500
+++ b/includes/stats.php	Fri Feb 22 12:51:53 2008 -0500
@@ -2,7 +2,7 @@
 
 /*
  * Enano - an open-source CMS capable of wiki functions, Drupal-like sidebar blocks, and everything in between
- * Version 1.0.3 (Dyrad)
+ * Version 1.1.2 (Caoineag alpha 2)
  * Copyright (C) 2006-2007 Dan Fuhry
  * stats.php - handles statistics for pages (disablable in the admin CP)
  *
--- a/includes/tagcloud.php	Fri Feb 22 12:46:51 2008 -0500
+++ b/includes/tagcloud.php	Fri Feb 22 12:51:53 2008 -0500
@@ -2,7 +2,7 @@
 
 /*
  * Enano - an open-source CMS capable of wiki functions, Drupal-like sidebar blocks, and everything in between
- * Version 1.0.3 (Dyrad)
+ * Version 1.1.2 (Caoineag alpha 2)
  * Copyright (C) 2006-2007 Dan Fuhry
  *
  * This program is Free Software; you can redistribute and/or modify it under the terms of the GNU General Public License
@@ -132,6 +132,7 @@
    
   function make_html($span_class = 'normal', $div_align = 'center')
   {
+    global $lang;
     $html = array();
     $max  = max($this->words);
     $size = $this->get_cloud_size();
@@ -147,8 +148,8 @@
         $newline = ( $inc == 5 ) ? "<br />" : '';
         ( $inc == 5 ) ? $inc = 0 : null;
         $url = makeUrlNS('Special', 'TagCloud/' . htmlspecialchars($word));
-        $s = ( $popularity != 1 ) ? 's' : '';
-        $html[] = "<span class='tc_word_{$span_class} tc_{$span_class}_index_{$index}'><a href='$url' title='$popularity page$s'>$word</a></span>"; // $newline";
+        $popstring = ( $popularity == 1 ) ? $lang->get('pagetools_tagcloug_tip_popularity_one') : $lang->get('pagetools_tagcloug_tip_popularity_plural', array('popularity' => $popularity));
+        $html[] = "<span class='tc_word_{$span_class} tc_{$span_class}_index_{$index}'><a href='$url' title='$popstring'>$word</a></span>"; // $newline";
       }
     }
     $html = '<div style="text-align: ' . $div_align . '; margin: 0 auto; max-width: 400px;">' . implode("\n", $html) . '</div>';
--- a/includes/template.php	Fri Feb 22 12:46:51 2008 -0500
+++ b/includes/template.php	Fri Feb 22 12:51:53 2008 -0500
@@ -2,7 +2,7 @@
 
 /*
  * Enano - an open-source CMS capable of wiki functions, Drupal-like sidebar blocks, and everything in between
- * Version 1.0.3 (Dyrad)
+ * Version 1.1.2 (Caoineag alpha 2)
  * Copyright (C) 2006-2007 Dan Fuhry
  *
  * This program is Free Software; you can redistribute and/or modify it under the terms of the GNU General Public License
@@ -42,7 +42,7 @@
     $this->theme_loaded = false;
     
     $this->fading_button = '<div style="background-image: url('.scriptPath.'/images/about-powered-enano-hover.png); background-repeat: no-repeat; width: 88px; height: 31px; margin: 0 auto 5px auto;">
-                              <a href="http://enanocms.org/" onclick="window.open(this.href); return false;"><img style="border-width: 0;" alt=" " src="'.scriptPath.'/images/about-powered-enano.png" onmouseover="domOpacity(this, 100, 0, 500);" onmouseout="domOpacity(this, 0, 100, 500);" /></a>
+                              <a style="background-image: none; padding-right: 0;" href="http://enanocms.org/" onclick="window.open(this.href); return false;"><img style="border-width: 0;" alt=" " src="'.scriptPath.'/images/about-powered-enano.png" onmouseover="domOpacity(this, 100, 0, 500);" onmouseout="domOpacity(this, 0, 100, 500);" /></a>
                             </div>';
     
     $this->theme_list = Array();
@@ -81,11 +81,7 @@
     $this->style_list = $list;
     
   }
-  function template()
-  {
-    $this->__construct();
-  }
-  function sidebar_widget($t, $h)
+  function sidebar_widget($t, $h, $use_normal_section = false)
   {
     global $db, $session, $paths, $template, $plugins; // Common objects
     if(!defined('ENANO_TEMPLATE_LOADED'))
@@ -95,9 +91,18 @@
     if(!$this->sidebar_widgets)
       $this->sidebar_widgets = '';
     $tplvars = $this->extract_vars('elements.tpl');
-    $parser = $this->makeParserText($tplvars['sidebar_section_raw']);
-    $parser->assign_vars(Array('TITLE'=>$t,'CONTENT'=>$h));
-    $this->plugin_blocks[$t] = $h;
+    
+    if ( $use_normal_section )
+    {
+      $parser = $this->makeParserText($tplvars['sidebar_section']);
+    }
+    else
+    {
+      $parser = $this->makeParserText($tplvars['sidebar_section_raw']);
+    }
+    
+    $parser->assign_vars(Array('TITLE' => '{TITLE}','CONTENT' => $h));
+    $this->plugin_blocks[$t] = $parser->run();
     $this->sidebar_widgets .= $parser->run();
   }
   function add_header($html)
@@ -134,6 +139,9 @@
   {
     global $db, $session, $paths, $template, $plugins; // Common objects
     global $email;
+    global $lang;
+    
+    profiler_log("template: starting var init");
     
     if(!$this->theme || !$this->style)
     {
@@ -153,7 +161,36 @@
     {
       $this->add_header('
         <!--[if lt IE 7]>
-        <script type="text/javascript" src="' . scriptPath . '/includes/clientside/ie-png.js"></script>
+        <script language="JavaScript">
+        function correctPNG() // correctly handle PNG transparency in Win IE 5.5 & 6.
+        {
+           var arVersion = navigator.appVersion.split("MSIE");
+           var version = parseFloat(arVersion[1]);
+           if (version >= 5.5 && typeof(document.body.filters) == "object")
+           {
+              for(var i=0; i<document.images.length; i++)
+              {
+                 var img = document.images[i];
+                 continue;
+                 var imgName = img.src.toUpperCase();
+                 if (imgName.substring(imgName.length-3, imgName.length) == "PNG")
+                 {
+                    var imgID = (img.id) ? "id=\'" + img.id + "\' " : "";
+                    var imgClass = (img.className) ? "class=\'" + img.className + "\' " : "";
+                    var imgTitle = (img.title) ? "title=\'" + img.title + "\' " : "title=\'" + img.alt + "\' ";
+                    var imgStyle = "display:inline-block;" + img.style.cssText;
+                    if (img.align == "left") imgStyle = "float:left;" + imgStyle;
+                    if (img.align == "right") imgStyle = "float:right;" + imgStyle;
+                    if (img.parentElement.href) imgStyle = "cursor:hand;" + imgStyle;
+                    var strNewHTML = "<span " + imgID + imgClass + imgTitle + " style=\\"" + "width:" + img.width + "px; height:" + img.height + "px;" + imgStyle + ";" + "filter:progid:DXImageTransform.Microsoft.AlphaImageLoader" + "(src=\\\'" + img.src + "\\\', sizingMethod=\'scale\');\\"></span>";
+                    img.outerHTML = strNewHTML;
+                    i = i-1;
+                 }
+              }
+           }   
+        }
+        window.attachEvent("onload", correctPNG);
+        </script>
         <![endif]-->
         ');
     }
@@ -162,40 +199,41 @@
     switch($paths->namespace) {
       case "Article":
       default:
-        $ns = 'article';
+        $ns = $lang->get('onpage_lbl_page_article');
         break;
       case "Admin":
-        $ns = 'administration page';
+        $ns = $lang->get('onpage_lbl_page_admin');
         break;
       case "System":
-        $ns = 'system message';
+        $ns = $lang->get('onpage_lbl_page_system');
         break;
       case "File":
-        $ns = 'uploaded file';
+        $ns = $lang->get('onpage_lbl_page_file');
         break;
       case "Help":
-        $ns = 'documentation page';
+        $ns = $lang->get('onpage_lbl_page_help');
         break;
       case "User":
-        $ns = 'user page';
+        $ns = $lang->get('onpage_lbl_page_user');
         break;
       case "Special":
-        $ns = 'special page';
+        $ns = $lang->get('onpage_lbl_page_special');
         break;
       case "Template":
-        $ns = 'template';
+        $ns = $lang->get('onpage_lbl_page_template');
         break;
       case "Project":
-        $ns = 'project page';
+        $ns = $lang->get('onpage_lbl_page_project');
         break;
       case "Category":
-        $ns = 'category';
+        $ns = $lang->get('onpage_lbl_page_category');
         break;
       case "Anonymous":
         $ns = 'external page';
         break;
     }
     $this->namespace_string = $ns;
+    unset($ns);
     $code = $plugins->setHook('page_type_string_set');
     foreach ( $code as $cmd )
     {
@@ -214,7 +252,7 @@
     if ( true || !$paths->anonymous_page )
     {
       $parser->assign_vars(array(
-          'FLAGS' => 'onclick="if ( !KILL_SWITCH ) { void(ajaxReset()); return false; }" title="View the page contents, all of the page contents, and nothing but the page contents (alt-a)" accesskey="a"',
+          '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
@@ -255,14 +293,25 @@
       $n = ( $session->get_permissions('mod_comments') ) ? (string)$nc : (string)$na;
       if ( $session->get_permissions('mod_comments') && $nu > 0 )
       {
-        $n .= ' total/'.$nu.' unapp.';
+        $subst = array(
+            'num_comments' => $nc,
+            'num_unapp' => $nu
+          );
+        $btn_text = $lang->get('onpage_btn_discussion_unapp', $subst);
+      }
+      else
+      {
+        $subst = array(
+          'num_comments' => $nc
+        );
+        $btn_text = $lang->get('onpage_btn_discussion', $subst);
       }
       
       $button->assign_vars(array(
-          'FLAGS' => 'onclick="if ( !KILL_SWITCH ) { void(ajaxComments()); return false; }" title="View the comments that other users have posted about this page (alt-c)" accesskey="c"',
+          'FLAGS' => 'onclick="if ( !KILL_SWITCH ) { void(ajaxComments()); return false; }" title="' . $lang->get('onpage_tip_comments') . '" accesskey="c"',
           'PARENTFLAGS' => 'id="mdgToolbar_discussion"',
           'HREF' => makeUrl($paths->page, 'do=comments', true),
-          'TEXT' => 'discussion ('.$n.')',
+          'TEXT' => $btn_text,
         ));
       
       $tb .= $button->run();
@@ -271,21 +320,21 @@
     if($session->get_permissions('read') && ($paths->namespace != 'Special' && $paths->namespace != 'Admin' && $paths->namespace != 'Anonymous') && ( $session->get_permissions('edit_page') && ( ( $paths->page_protected && $session->get_permissions('even_when_protected') ) || !$paths->page_protected ) ) )
     {
       $button->assign_vars(array(
-        'FLAGS' => 'onclick="if ( !KILL_SWITCH ) { void(ajaxEditor()); return false; }" title="Edit the contents of this page (alt-e)" accesskey="e"',
+        'FLAGS' => 'onclick="if ( !KILL_SWITCH ) { void(ajaxEditor()); return false; }" title="' . $lang->get('onpage_tip_edit') . '" accesskey="e"',
         'PARENTFLAGS' => 'id="mdgToolbar_edit"',
         'HREF' => makeUrl($paths->page, 'do=edit', true),
-        'TEXT' => 'edit this page'
+        'TEXT' => $lang->get('onpage_btn_edit')
         ));
       $tb .= $button->run();
     // View source button
     }
-    else if($session->get_permissions('view_source') && ( !$session->get_permissions('edit_page') || !$session->get_permissions('even_when_protected') && $paths->page_protected ) && $paths->namespace != 'Special' && $paths->namespace != 'Admin') 
+    else if($session->get_permissions('view_source') && ( !$session->get_permissions('edit_page') || !$session->get_permissions('even_when_protected') && $paths->page_protected ) && $paths->namespace != 'Special' && $paths->namespace != 'Admin' && $paths->namespace != 'Anonymous') 
     {
       $button->assign_vars(array(
-        'FLAGS' => 'onclick="if ( !KILL_SWITCH ) { void(ajaxViewSource()); return false; }" title="View the source code (wiki markup) that this page uses (alt-e)" accesskey="e"',
+        'FLAGS' => 'onclick="if ( !KILL_SWITCH ) { void(ajaxEditor()); return false; }" title="' . $lang->get('onpage_tip_viewsource') . '" accesskey="e"',
         'PARENTFLAGS' => 'id="mdgToolbar_edit"',
         'HREF' => makeUrl($paths->page, 'do=viewsource', true),
-        'TEXT' => 'view source'
+        'TEXT' => $lang->get('onpage_btn_viewsource')
         ));
       $tb .= $button->run();
     }
@@ -293,10 +342,10 @@
     if ( $session->get_permissions('read') /* && $paths->wiki_mode */ && $paths->page_exists && $paths->namespace != 'Special' && $paths->namespace != 'Admin' && $session->get_permissions('history_view') )
     {
       $button->assign_vars(array(
-        'FLAGS'       => 'onclick="if ( !KILL_SWITCH ) { void(ajaxHistory()); return false; }" title="View a log of actions taken on this page (alt-h)" accesskey="h"',
+        'FLAGS'       => 'onclick="if ( !KILL_SWITCH ) { void(ajaxHistory()); return false; }" title="' . $lang->get('onpage_tip_history') . '" accesskey="h"',
         'PARENTFLAGS' => 'id="mdgToolbar_history"',
         'HREF'        => makeUrl($paths->page, 'do=history', true),
-        'TEXT'        => 'history'
+        'TEXT'        => $lang->get('onpage_btn_history')
         ));
       $tb .= $button->run();
     }
@@ -308,9 +357,9 @@
     if ( $session->get_permissions('read') && $paths->page_exists && ( $session->get_permissions('rename') && ( $paths->page_protected && $session->get_permissions('even_when_protected') || !$paths->page_protected ) ) && $paths->namespace != 'Special' && $paths->namespace != 'Admin' )
     {
       $menubtn->assign_vars(array(
-          'FLAGS' => 'onclick="if ( !KILL_SWITCH ) { void(ajaxRename()); return false; }" title="Change the display name of this page (alt-r)" accesskey="r"',
+          'FLAGS' => 'onclick="if ( !KILL_SWITCH ) { void(ajaxRename()); return false; }" title="' . $lang->get('onpage_tip_rename') . '" accesskey="r"',
           'HREF'  => makeUrl($paths->page, 'do=rename', true),
-          'TEXT'  => 'rename',
+          'TEXT'  => $lang->get('onpage_btn_rename'),
         ));
       $this->toolbar_menu .= $menubtn->run();
     }
@@ -319,9 +368,9 @@
     if ( $paths->wiki_mode && $session->get_permissions('vote_delete') && $paths->page_exists && $paths->namespace != 'Special' && $paths->namespace != 'Admin')
     {
       $menubtn->assign_vars(array(
-          'FLAGS' => 'onclick="if ( !KILL_SWITCH ) { void(ajaxDelVote()); return false; }" title="Vote to have this page deleted (alt-d)" accesskey="d"',
+          'FLAGS' => 'onclick="if ( !KILL_SWITCH ) { void(ajaxDelVote()); return false; }" title="' . $lang->get('onpage_tip_delvote') . '" accesskey="d"',
           'HREF'  => makeUrl($paths->page, 'do=delvote', true),
-          'TEXT'  => 'vote to delete this page',
+          'TEXT'  => $lang->get('onpage_btn_votedelete'),
         ));
       $this->toolbar_menu .= $menubtn->run();
     }
@@ -330,9 +379,9 @@
     if ( $session->get_permissions('read') && $paths->wiki_mode && $paths->page_exists && $paths->namespace != 'Special' && $paths->namespace != 'Admin' && $session->get_permissions('vote_reset') && $paths->cpage['delvotes'] > 0)
     {
       $menubtn->assign_vars(array(
-          'FLAGS' => 'onclick="if ( !KILL_SWITCH ) { void(ajaxResetDelVotes()); return false; }" title="Vote to have this page deleted (alt-y)" accesskey="y"',
+          'FLAGS' => 'onclick="if ( !KILL_SWITCH ) { void(ajaxResetDelVotes()); return false; }" title="' . $lang->get('onpage_tip_resetvotes') . '" accesskey="y"',
           'HREF'  => makeUrl($paths->page, 'do=resetvotes', true),
-          'TEXT'  => 'reset deletion votes',
+          'TEXT'  => $lang->get('onpage_btn_votedelete_reset'),
         ));
       $this->toolbar_menu .= $menubtn->run();
     }
@@ -341,9 +390,9 @@
     if ( $paths->page_exists && $paths->namespace != 'Special' && $paths->namespace != 'Admin' )
     {
       $menubtn->assign_vars(array(
-          'FLAGS' => 'title="View a version of this page that is suitable for printing"',
+          'FLAGS' => 'title="' . $lang->get('onpage_tip_printable') . '"',
           'HREF'  => makeUrl($paths->page, 'printable=yes', true),
-          'TEXT'  => 'view printable version',
+          'TEXT'  => $lang->get('onpage_btn_printable'),
         ));
       $this->toolbar_menu .= $menubtn->run();
     }
@@ -353,7 +402,7 @@
     {
       
       $label = $this->makeParserText($tplvars['toolbar_label']);
-      $label->assign_vars(array('TEXT' => 'protection:'));
+      $label->assign_vars(array('TEXT' => $lang->get('onpage_lbl_protect')));
       $t0 = $label->run();
       
       $ctmp = ''; 
@@ -362,9 +411,9 @@
         $ctmp=' style="text-decoration: underline;"';
       }
       $menubtn->assign_vars(array(
-          'FLAGS' => 'accesskey="i" onclick="if ( !KILL_SWITCH ) { ajaxProtect(1); return false; }" id="protbtn_1" title="Prevents all non-administrators from editing this page. [alt-i]"'.$ctmp,
+          'FLAGS' => 'accesskey="i" onclick="if ( !KILL_SWITCH ) { ajaxProtect(1); return false; }" id="protbtn_1" title="' . $lang->get('onpage_tip_protect_on') . '"'.$ctmp,
           'HREF'  => makeUrl($paths->page, 'do=protect&level=1', true),
-          'TEXT'  => 'on'
+          'TEXT'  => $lang->get('onpage_btn_protect_on')
         ));
       $t1 = $menubtn->run();
       
@@ -374,9 +423,9 @@
         $ctmp=' style="text-decoration: underline;"';
       }
       $menubtn->assign_vars(array(
-          'FLAGS' => 'accesskey="o" onclick="if ( !KILL_SWITCH ) { ajaxProtect(0); return false; }" id="protbtn_0" title="Allows everyone to edit this page. [alt-o]"'.$ctmp,
+          'FLAGS' => 'accesskey="o" onclick="if ( !KILL_SWITCH ) { ajaxProtect(0); return false; }" id="protbtn_0" title="' . $lang->get('onpage_tip_protect_off') . '"'.$ctmp,
           'HREF'  => makeUrl($paths->page, 'do=protect&level=0', true),
-          'TEXT'  => 'off'
+          'TEXT'  => $lang->get('onpage_btn_protect_off')
         ));
       $t2 = $menubtn->run();
       
@@ -386,9 +435,9 @@
         $ctmp = ' style="text-decoration: underline;"';
       }
       $menubtn->assign_vars(array(
-          'FLAGS' => 'accesskey="p" onclick="if ( !KILL_SWITCH ) { ajaxProtect(2); return false; }" id="protbtn_2" title="Allows only users who have been registered for 4 days to edit this page. [alt-p]"'.$ctmp,
+          'FLAGS' => 'accesskey="p" onclick="if ( !KILL_SWITCH ) { ajaxProtect(2); return false; }" id="protbtn_2" title="' . $lang->get('onpage_tip_protect_semi') . '"'.$ctmp,
           'HREF'  => makeUrl($paths->page, 'do=protect&level=2', true),
-          'TEXT'  => 'semi'
+          'TEXT'  => $lang->get('onpage_btn_protect_semi')
         ));
       $t3 = $menubtn->run();
       
@@ -407,7 +456,7 @@
     {
       // label at start
       $label = $this->makeParserText($tplvars['toolbar_label']);
-      $label->assign_vars(array('TEXT' => 'page wiki mode:'));
+      $label->assign_vars(array('TEXT' => $lang->get('onpage_lbl_wikimode')));
       $t0 = $label->run();
       
       // on button
@@ -419,7 +468,7 @@
       $menubtn->assign_vars(array(
           'FLAGS' => /* 'onclick="if ( !KILL_SWITCH ) { ajaxSetWikiMode(1); return false; }" id="wikibtn_1" title="Forces wiki functions to be allowed on this page."'. */ $ctmp,
           'HREF' => makeUrl($paths->page, 'do=setwikimode&level=1', true),
-          'TEXT' => 'on'
+          'TEXT' => $lang->get('onpage_btn_wikimode_on')
         ));
       $t1 = $menubtn->run();
       
@@ -432,7 +481,7 @@
       $menubtn->assign_vars(array(
           'FLAGS' => /* 'onclick="if ( !KILL_SWITCH ) { ajaxSetWikiMode(0); return false; }" id="wikibtn_0" title="Forces wiki functions to be disabled on this page."'. */ $ctmp,
           'HREF' => makeUrl($paths->page, 'do=setwikimode&level=0', true),
-          'TEXT' => 'off'
+          'TEXT' => $lang->get('onpage_btn_wikimode_off')
         ));
       $t2 = $menubtn->run();
       
@@ -445,7 +494,7 @@
       $menubtn->assign_vars(array(
           'FLAGS' => /* 'onclick="if ( !KILL_SWITCH ) { ajaxSetWikiMode(2); return false; }" id="wikibtn_2" title="Causes this page to use the global wiki mode setting (default)"'. */ $ctmp,
           'HREF' => makeUrl($paths->page, 'do=setwikimode&level=2', true),
-          'TEXT' => 'global'
+          'TEXT' => $lang->get('onpage_btn_wikimode_global')
         ));
       $t3 = $menubtn->run();
       
@@ -464,9 +513,9 @@
     if ( $session->get_permissions('read') && $session->get_permissions('clear_logs') && $paths->namespace != 'Special' && $paths->namespace != 'Admin' )
     {
       $menubtn->assign_vars(array(
-          'FLAGS' => 'onclick="if ( !KILL_SWITCH ) { void(ajaxClearLogs()); return false; }" title="Remove all edit and action logs for this page from the database. IRREVERSIBLE! (alt-l)" accesskey="l"',
+          'FLAGS' => 'onclick="if ( !KILL_SWITCH ) { void(ajaxClearLogs()); return false; }" title="' . $lang->get('onpage_tip_flushlogs') . '" accesskey="l"',
           'HREF'  => makeUrl($paths->page, 'do=flushlogs', true),
-          'TEXT'  => 'clear page logs',
+          'TEXT'  => $lang->get('onpage_btn_clearlogs'),
         ));
       $this->toolbar_menu .= $menubtn->run();
     }
@@ -474,18 +523,26 @@
     // Delete page button
     if ( $session->get_permissions('read') && $session->get_permissions('delete_page') && $paths->page_exists && $paths->namespace != 'Special' && $paths->namespace != 'Admin' )
     {
-      $s = 'delete this page';
+      $s = $lang->get('onpage_btn_deletepage');
       if ( $paths->cpage['delvotes'] == 1 )
       {
-        $s .= ' (<b>'.$paths->cpage['delvotes'].'</b> vote)';
+        $subst = array(
+          'num_votes' => $paths->cpage['delvotes'],
+          'plural' => ''
+          );
+        $s .= $lang->get('onpage_btn_deletepage_votes', $subst);
       }
       else if ( $paths->cpage['delvotes'] > 1 )
       {
-        $s .= ' (<b>'.$paths->cpage['delvotes'].'</b> votes)';
+        $subst = array(
+          'num_votes' => $paths->cpage['delvotes'],
+          'plural' => $lang->get('meta_plural')
+          );
+        $s .= $lang->get('onpage_btn_deletepage_votes', $subst);
       }
       
       $menubtn->assign_vars(array(
-          'FLAGS' => 'onclick="if ( !KILL_SWITCH ) { void(ajaxDeletePage()); return false; }" title="Delete this page. This is always reversible unless the logs are cleared. (alt-k)" accesskey="k"',
+          'FLAGS' => 'onclick="if ( !KILL_SWITCH ) { void(ajaxDeletePage()); return false; }" title="' . $lang->get('onpage_tip_deletepage') . '" accesskey="k"',
           'HREF'  => makeUrl($paths->page, 'do=deletepage', true),
           'TEXT'  => $s,
         ));
@@ -513,13 +570,13 @@
     {
       // label at start
       $label = $this->makeParserText($tplvars['toolbar_label']);
-      $label->assign_vars(array('TEXT' => 'page password:'));
+      $label->assign_vars(array('TEXT' => $lang->get('onpage_lbl_password')));
       $t0 = $label->run();
       
       $menubtn->assign_vars(array(
-          'FLAGS' => 'onclick="if ( !KILL_SWITCH ) { void(ajaxSetPassword()); return false; }" title="Require a password in order for this page to be viewed"',
+          'FLAGS' => 'onclick="if ( !KILL_SWITCH ) { void(ajaxSetPassword()); return false; }" title="' . $lang->get('onpage_tip_password') . '"',
           'HREF'  => '#',
-          'TEXT'  => 'set',
+          'TEXT'  => $lang->get('onpage_btn_password_set'),
         ));
       $t = $menubtn->run();
       
@@ -530,9 +587,9 @@
     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="Manage who can do what with this page (alt-m)" accesskey="m"',
+          'FLAGS' => 'onclick="if ( !KILL_SWITCH ) { return ajaxOpenACLManager(); }" title="' . $lang->get('onpage_tip_aclmanager') . '" accesskey="m"',
           'HREF'  => makeUrl($paths->page, 'do=aclmanager', true),
-          'TEXT'  => 'manage page access',
+          'TEXT'  => $lang->get('onpage_btn_acl'),
         ));
       $this->toolbar_menu .= $menubtn->run();
     }
@@ -541,9 +598,9 @@
     if ( $session->user_level >= USER_LEVEL_ADMIN && $paths->page_exists && $paths->namespace != 'Special' && $paths->namespace != 'Admin' )
     {
       $menubtn->assign_vars(array(
-          'FLAGS' => 'onclick="if ( !KILL_SWITCH ) { void(ajaxAdminPage()); return false; }" title="Administrative options for this page" accesskey="g"',
+          'FLAGS' => 'onclick="if ( !KILL_SWITCH ) { void(ajaxAdminPage()); return false; }" title="' . $lang->get('onpage_tip_adminoptions') . '" accesskey="g"',
           'HREF'  => makeUrlNS('Special', 'Administration', 'module='.$paths->nslist['Admin'].'PageManager', true),
-          'TEXT'  => 'administrative options',
+          'TEXT'  => $lang->get('onpage_btn_admin'),
         ));
       $this->toolbar_menu .= $menubtn->run();
     }
@@ -551,10 +608,10 @@
     if ( strlen($this->toolbar_menu) > 0 )
     {
       $button->assign_vars(array(
-        'FLAGS'       => 'id="mdgToolbar_moreoptions" onclick="if ( !KILL_SWITCH ) { return false; }" title="Additional options for working with this page"',
+        'FLAGS'       => 'id="mdgToolbar_moreoptions" onclick="if ( !KILL_SWITCH ) { return false; }" title="' . $lang->get('onpage_tip_moreoptions') . '"',
         'PARENTFLAGS' => '',
         'HREF'        => makeUrl($paths->page, 'do=moreoptions', true),
-        'TEXT'        => 'more options'
+        'TEXT'        => $lang->get('onpage_btn_moreoptions')
         ));
       $tb .= $button->run();
     }
@@ -603,6 +660,10 @@
     // Add the e-mail address client code to the header
     $this->add_header($email->jscode());
     
+    // Add language file
+    $lang_uri = makeUrlNS('Special', 'LangExportJSON/' . $lang->lang_id, false, true);
+    $this->add_header("<script type=\"text/javascript\" src=\"$lang_uri\"></script>");
+    
     // Generate the code for the Log out and Change theme sidebar buttons
     // Once again, the new template parsing system can be used here
     
@@ -611,7 +672,7 @@
     $parser->assign_vars(Array(
         'HREF'=>makeUrlNS('Special', 'Logout'),
         'FLAGS'=>'onclick="if ( !KILL_SWITCH ) { mb_logout(); return false; }"',
-        'TEXT'=>'Log out',
+        'TEXT'=>$lang->get('sidebar_btn_logout'),
       ));
     
     $logout_link = $parser->run();
@@ -619,7 +680,7 @@
     $parser->assign_vars(Array(
         'HREF'=>makeUrlNS('Special', 'Login/' . $paths->page),
         'FLAGS'=>'onclick="if ( !KILL_SWITCH ) { ajaxStartLogin(); return false; }"',
-        'TEXT'=>'Log in',
+        'TEXT'=>$lang->get('sidebar_btn_login'),
       ));
     
     $login_link = $parser->run();
@@ -627,7 +688,7 @@
     $parser->assign_vars(Array(
         'HREF'=>makeUrlNS('Special', 'ChangeStyle/'.$paths->page),
         'FLAGS'=>'onclick="if ( !KILL_SWITCH ) { ajaxChangeStyle(); return false; }"',
-        'TEXT'=>'Change theme',
+        'TEXT'=>$lang->get('sidebar_btn_changestyle'),
       ));
     
     $theme_link = $parser->run();
@@ -635,7 +696,7 @@
     $parser->assign_vars(Array(
         'HREF'=>makeUrlNS('Special', 'Administration'),
         'FLAGS'=>'onclick="if ( !KILL_SWITCH ) { void(ajaxStartAdminLogin()); return false; }"',
-        'TEXT'=>'Administration',
+        'TEXT'=>$lang->get('sidebar_btn_administration'),
       ));
     
     $admin_link = $parser->run();
@@ -656,6 +717,7 @@
       var scriptPath=\''. scriptPath .'\';
       var contentPath=\''.contentPath.'\';
       var ENANO_SID =\'' . $SID . '\';
+      var user_level=' . $session->user_level . ';
       var auth_level=' . $session->auth_level . ';
       var USER_LEVEL_GUEST = ' . USER_LEVEL_GUEST . ';
       var USER_LEVEL_MEMBER = ' . USER_LEVEL_MEMBER . ';
@@ -681,7 +743,9 @@
             }
           }
       $js_dynamic .= '\';
-      var ENANO_CURRENT_THEME = \''. $session->theme .'\';';
+      var ENANO_CURRENT_THEME = \''. $session->theme .'\';
+      var ENANO_LANG_ID = ' . $lang->lang_id . ';
+      var ENANO_PAGE_TYPE = "' . addslashes($this->namespace_string) . '";';
       foreach($paths->nslist as $k => $c)
       {
         $js_dynamic .= "namespace_list['{$k}'] = '$c';";
@@ -739,11 +803,15 @@
     {
       eval($cmd);
     }
+    
+    profiler_log("template: finished var init");
   }
   
   function header($simple = false) 
   {
     global $db, $session, $paths, $template, $plugins; // Common objects
+    global $lang;
+    
     ob_start();
     
     if(!$this->theme_loaded)
@@ -769,21 +837,37 @@
     {
       $login_link = makeUrlNS('Special', 'Login/' . $paths->fullpage, 'level=' . $session->user_level, true);
       echo '<div class="usermessage">';
-      echo '<b>Your administrative session has timed out.</b> <a href="' . $login_link . '" onclick="ajaxPromptAdminAuth(function(k){ ENANO_SID = k; window.location = append_sid(makeUrl(title)); }, ' . $session->user_level . '); return false;">Log in again</a>';
+      echo $lang->get('user_msg_elev_timed_out', array( 'login_link' => $login_link ));
       echo '</div>';
     }
     if ( $this->site_disabled && $session->user_level >= USER_LEVEL_ADMIN && ( $paths->page != $paths->nslist['Special'] . 'Administration' ) )
     {
       $admin_link = makeUrlNS('Special', 'Administration', 'module=' . $paths->nslist['Admin'] . 'GeneralConfig', true);
-      echo '<div class="usermessage"><b>The site is currently disabled and thus is only accessible to administrators.</b><br />
-            You can re-enable the site through the <a href="' . $admin_link . '">administration panel</a>.
+      echo '<div class="usermessage"><b>' . $lang->get('page_sitedisabled_admin_msg_title') . '</b><br />
+            ' . $lang->get('page_sitedisabled_admin_msg_body', array('admin_link' => $admin_link)) . '
             </div>';
     }
   }
+  
   function footer($simple = false)
   {
+    echo $this->getFooter($simple);
+    ob_end_flush();
+  }
+  
+  function getHeader()
+  {
+    $headers_sent = true;
+    if(!defined('ENANO_HEADERS_SENT'))
+      define('ENANO_HEADERS_SENT', '');
+    if(!$this->no_headers) return $this->process_template('header.tpl');
+  }
+  function getFooter($simple = false)
+  {
     global $db, $session, $paths, $template, $plugins; // Common objects
-    if(!$this->no_headers) {
+    global $lang;
+    if ( !$this->no_headers )
+    {
       
       if(!defined('ENANO_HEADERS_SENT'))
         $this->header();
@@ -791,57 +875,46 @@
       global $_starttime;
       if(isset($_GET['sqldbg']) && $session->get_permissions('mod_misc'))
       {
-        echo '<h3>Query list as requested on URI</h3><pre style="margin-left: 1em">';
+        echo '<h3>' . $lang->get('page_heading_sql_list') . '</h3><pre style="margin-left: 1em">';
         echo htmlspecialchars($db->sql_backtrace());
         echo '</pre>';
       }
       
-      $f = microtime_float();
-      $f = $f - $_starttime;
-      $f = round($f, 4);
-      $dbg = 'Time: '.$f.'s  |  Queries: '.$db->num_queries;
       $t = ( $simple ) ? $this->process_template('simple-footer.tpl') : $this->process_template('footer.tpl');
-      $t = str_replace('[[Stats]]', $dbg, $t);
-      $t = str_replace('[[NumQueries]]', (string)$db->num_queries, $t);
-      $t = str_replace('[[GenTime]]', (string)$f, $t);
-      echo $t;
-      
-      ob_end_flush();
-    }
-    else return '';
-  }
-  function getHeader()
-  {
-    $headers_sent = true;
-    if(!defined('ENANO_HEADERS_SENT'))
-      define('ENANO_HEADERS_SENT', '');
-    if(!$this->no_headers) return $this->process_template('header.tpl');
-  }
-  function getFooter()
-  {
-    global $db, $session, $paths, $template, $plugins; // Common objects
-    if(!$this->no_headers) {
-      global $_starttime;
-      $t = '';
-      
-      if(isset($_GET['sqldbg']) && $session->get_permissions('mod_misc'))
-      {
-        $t .= '<h3>Query list as requested on URI</h3><pre style="margin-left: 1em">';
-        $t .= $db->sql_backtrace();
-        $t .= '</pre>';
-      }
       
       $f = microtime_float();
       $f = $f - $_starttime;
-      $f = round($f, 4);
-      $dbg = 'Time: '.$f.'s  |  Queries: '.$db->num_queries;
-      $t.= $this->process_template('footer.tpl');
+      $f = round($f, 2);
+      
+      $t_loc = $lang->get('page_msg_stats_gentime_short', array('time' => $f));
+      $t_loc_long = $lang->get('page_msg_stats_gentime_long', array('time' => $f));
+      $q_loc = '<a href="' . $this->tpl_strings['REPORT_URI'] . '">' . $lang->get('page_msg_stats_sql', array('nq' => $db->num_queries)) . '</a>';
+      $dbg = $t_loc;
+      $dbg_long = $t_loc_long;
+      if ( $session->user_level >= USER_LEVEL_ADMIN )
+      {
+        $dbg .= "&nbsp;&nbsp;|&nbsp;&nbsp;$q_loc";
+        $dbg_long .= "&nbsp;&nbsp;|&nbsp;&nbsp;$q_loc";
+      }
+      
       $t = str_replace('[[Stats]]', $dbg, $t);
+      $t = str_replace('[[StatsLong]]', $dbg_long, $t);
       $t = str_replace('[[NumQueries]]', (string)$db->num_queries, $t);
       $t = str_replace('[[GenTime]]', (string)$f, $t);
+      $t = str_replace('[[NumQueriesLoc]]', $q_loc, $t);
+      $t = str_replace('[[GenTimeLoc]]', $t_loc, $t);
+      $t = str_replace('[[EnanoPoweredLink]]', $lang->get('page_enano_powered', array('about_uri' => $this->tpl_strings['URL_ABOUT_ENANO'])), $t);
+      $t = str_replace('[[EnanoPoweredLinkLong]]', $lang->get('page_enano_powered_long', array('about_uri' => $this->tpl_strings['URL_ABOUT_ENANO'])), $t);
+      
+      if ( defined('ENANO_DEBUG') )
+        $t = str_replace('</body>', '<div id="profile" style="margin: 10px;">' . profiler_make_html() . '</div></body>', $t);
+      
       return $t;
     }
-    else return '';
+    else
+    {
+      return '';
+    }
   }
   
   /**
@@ -878,7 +951,7 @@
     // This is a bad coding practice so this function will always be picky.
     if ( !$this->theme )
     {
-      die('$template->extract_vars(): theme (' . $this->theme . ') not yet loaded, so we can\'t open template files yet...this is a bug and should be reported.<br /><br />Backtrace, most recent call first:<pre>'.enano_debug_print_backtrace(true).'</pre>');
+      die('$template->extract_vars(): theme not yet loaded, so we can\'t open template files yet...this is a bug and should be reported.<br /><br />Backtrace, most recent call first:<pre>'.enano_debug_print_backtrace(true).'</pre>');
     }
     
     // Full pathname of template file
@@ -965,7 +1038,7 @@
     $keywords = implode('|', $keywords);
     
     // Matches
-    //          1     2                               3                 4   56                       7     8
+    //          1     2                 3                 4   56                       7     8
     $regexp = '/(<!-- ('. $keywords .') ([A-z0-9_-]+) -->)(.*)((<!-- BEGINELSE \\3 -->)(.*))?(<!-- END \\3 -->)/isU';
     
     /*
@@ -1107,7 +1180,7 @@
       // matches the MD5 of the file that the compiled file was compiled from.
       if ( isset($md5) && $md5 == md5($text) )
       {
-        return str_replace('\\"', '"', $tpl_text);
+        return $this->compile_template_text_post(str_replace('\\"', '"', $tpl_text));
       }
     }
     
@@ -1146,7 +1219,7 @@
       fclose($h);
     }
     
-    return $text; //('<pre>'.htmlspecialchars($text).'</pre>');
+    return $this->compile_template_text_post($text); //('<pre>'.htmlspecialchars($text).'</pre>');
   }
   
   
@@ -1159,7 +1232,7 @@
   function compile_template_text($text)
   {
     // this might do something else in the future, possibly cache large templates
-    return $this->compile_tpl_code($text);
+    return $this->compile_template_text_post($this->compile_tpl_code($text));
   }
   
   /**
@@ -1171,9 +1244,30 @@
   function parse($text)
   {
     $text = $this->compile_template_text($text);
+    $text = $this->compile_template_text_post($text);
     return eval($text);
   }
   
+  /**
+   * Post-processor for template code. Basically what this does is it localizes {lang:foo} blocks.
+   * @param string Mostly-processed TPL code
+   * @return string
+   */
+  
+  function compile_template_text_post($text)
+  {
+    global $lang;
+    preg_match_all('/\{lang:([a-z0-9]+_[a-z0-9_]+)\}/', $text, $matches);
+    foreach ( $matches[1] as $i => $string_id )
+    {
+      $string = $lang->get($string_id);
+      $string = str_replace('\\', '\\\\', $string);
+      $string = str_replace('\'', '\\\'', $string);
+      $text = str_replace_once($matches[0][$i], $string, $text);
+    }
+    return $text;
+  }
+  
   // Steps to turn this:
   //   [[Project:Community Portal]]
   // into this:
@@ -1203,10 +1297,13 @@
   function tplWikiFormat($message, $filter_links = false, $filename = 'elements.tpl')
   {
     global $db, $session, $paths, $template, $plugins; // Common objects
+    global $lang;
+    
     $filter_links = false;
     $tplvars = $this->extract_vars($filename);
     if($session->sid_super) $as = htmlspecialchars(urlSeparator).'auth='.$session->sid_super;
     else $as = '';
+    error_reporting(E_ALL);
     $random_id = sha1(microtime().''); // A temp value
     
     /*
@@ -1330,6 +1427,15 @@
       }
     }
     
+    preg_match_all('/\{lang:([a-z0-9]+_[a-z0-9_]+)\}/', $message, $matches);
+    foreach ( $matches[1] as $i => $string_id )
+    {
+      $string = $lang->get($string_id);
+      $string = str_replace('\\', '\\\\', $string);
+      $string = str_replace('\'', '\\\'', $string);
+      $message = str_replace_once($matches[0][$i], $string, $message);
+    }
+    
     /*
      * HTML RENDERER
      */
@@ -1489,25 +1595,28 @@
   
   function tinymce_textarea($name, $content = '', $rows = 20, $cols = 60)
   {
+    global $lang;
     $randomid = md5(microtime() . mt_rand());
     $html = '';
     $html .= '<textarea name="' . $name . '" rows="'.$rows.'" cols="'.$cols.'" style="width: 100%;" id="toggleMCEroot_'.$randomid.'">' . $content . '</textarea>';
-    $html .= '<div style="float: right; display: table;" id="mceSwitchAgent_' . $randomid . '">text editor&nbsp;&nbsp;|&nbsp;&nbsp;<a href="#" onclick="if ( !KILL_SWITCH ) { toggleMCE_'.$randomid.'(); return false; }">graphical editor</a></div>';
+    $html .= '<div style="float: right; display: table;" id="mceSwitchAgent_' . $randomid . '">' . $lang->get('etc_tinymce_btn_text') . '&nbsp;&nbsp;|&nbsp;&nbsp;<a href="#" onclick="if ( !KILL_SWITCH ) { toggleMCE_'.$randomid.'(); return false; }">' . $lang->get('etc_tinymce_btn_graphical') . '</a></div>';
     $html .= '<script type="text/javascript">
                 // <![CDATA[
                 function toggleMCE_'.$randomid.'()
                 {
                   var the_obj = document.getElementById(\'toggleMCEroot_' . $randomid . '\');
                   var panel = document.getElementById(\'mceSwitchAgent_' . $randomid . '\');
+                  var text_editor = $lang.get("etc_tinymce_btn_text");
+                  var graphical_editor = $lang.get("etc_tinymce_btn_graphical");
                   if ( the_obj.dnIsMCE == "yes" )
                   {
                     $dynano(the_obj).destroyMCE();
-                    panel.innerHTML = \'text editor&nbsp;&nbsp;|&nbsp;&nbsp;<a href="#" onclick="if ( !KILL_SWITCH ) { toggleMCE_'.$randomid.'(); return false; }">graphical editor</a>\';
+                    panel.innerHTML = text_editor + \'&nbsp;&nbsp;|&nbsp;&nbsp;<a href="#" onclick="if ( !KILL_SWITCH ) { toggleMCE_'.$randomid.'(); return false; }">\' + graphical_editor + \'</a>\';
                   }
                   else
                   {
                     $dynano(the_obj).switchToMCE();
-                    panel.innerHTML = \'<a href="#" onclick="if ( !KILL_SWITCH ) { toggleMCE_'.$randomid.'(); return false; }">text editor</a>&nbsp;&nbsp;|&nbsp;&nbsp;graphical editor\';
+                    panel.innerHTML = \'<a href="#" onclick="if ( !KILL_SWITCH ) { toggleMCE_'.$randomid.'(); return false; }">\' + text_editor + \'</a>&nbsp;&nbsp;|&nbsp;&nbsp;\' + graphical_editor;
                   }
                 }
                 // ]]>
@@ -1608,13 +1717,18 @@
           ob_end_clean();
           break;
         case BLOCK_PLUGIN:
-          $parser = $this->makeParserText($vars['sidebar_section_raw']);
+          $parser = $this->makeParserText('{CONTENT}');
           $c = (gettype($this->fetch_block($row['block_content'])) == 'string') ? $this->fetch_block($row['block_content']) : 'Can\'t find plugin block';
           break;
       }
       $parser->assign_vars(Array( 'TITLE'=>$this->tplWikiFormat($row['block_name']), 'CONTENT'=>$c ));
-      if    ($row['sidebar_id'] == SIDEBAR_LEFT ) $left  .= $parser->run();
-      elseif($row['sidebar_id'] == SIDEBAR_RIGHT) $right .= $parser->run();
+      $run = $parser->run();
+      if ( $row['block_type'] == BLOCK_PLUGIN )
+      {
+        $run = str_replace('{TITLE}', $this->tplWikiFormat($row['block_name']), $run);
+      }
+      if    ($row['sidebar_id'] == SIDEBAR_LEFT ) $left  .= $run;
+      elseif($row['sidebar_id'] == SIDEBAR_RIGHT) $right .= $run;
       unset($parser);
     }
     $db->free_result();
@@ -1686,7 +1800,7 @@
     $messages = array();
     while ( $row = $db->fetchrow() )
     {
-      $messages[] = '<a href="' . makeUrlNS('Special', 'PrivateMessages/View/' . $row['message_id']) . '" title="Sent ' . date('F d, Y h:i a', $row['date']) . ' by ' . $row['message_from'] . '">' . $row['subject'] . '</a>';
+      $messages[] = '<a href="' . makeUrlNS('Special', 'PrivateMessages/View/' . $row['message_id']) . '" title="Sent ' . enano_date('F d, Y h:i a', $row['date']) . ' by ' . $row['message_from'] . '">' . $row['subject'] . '</a>';
     }
     $ob .= implode(",\n    " , $messages)."\n";
     $ob .= '</div>'."\n";
@@ -1719,12 +1833,14 @@
     $this->tpl_bool = $template->tpl_bool;
   }
   /**
-   * PHP 4 constructor.
+   * PHP 4 constructor. Deprecated in 1.1.x.
    */
+  /*
   function templateIndividual($text)
   {
     $this->__construct($text);
   }
+  */
   /**
    * Assigns an array of string values to the template. Strings can be accessed from the template by inserting {KEY_NAME} in the template file.
    * @param $vars array
@@ -1810,13 +1926,14 @@
   {
     global $sideinfo;
     global $this_page;
+    global $lang;
     global $db, $session, $paths, $template, $plugins; // Common objects
     $tplvars = $this->extract_vars('elements.tpl');
     $tb = '';
     // Get the "article" button text (depends on namespace)
-    if(defined('IN_ENANO_INSTALL')) $ns = 'installation page';
+    if(defined('IN_ENANO_INSTALL') && is_object($lang)) $ns = $lang->get('meta_btn_article');
     else $ns = 'system error page';
-    $t = str_replace('{FLAGS}', 'onclick="if ( !KILL_SWITCH ) { return false; }" title="Hey! A button that doesn\'t do anything. Clever..." accesskey="a"', $tplvars['toolbar_button']);
+    $t = str_replace('{FLAGS}', 'onclick="return false;" title="Hey! A button that doesn\'t do anything. Clever..." accesskey="a"', $tplvars['toolbar_button']);
     $t = str_replace('{HREF}', '#', $t);
     $t = str_replace('{TEXT}', $ns, $t);
     $tb .= $t;
@@ -1839,13 +1956,22 @@
     
     $title = ( is_object($paths) ) ? $paths->page : 'Critical error';
     
+    $headers = '<style type="text/css">div.pagenav { border-top: 1px solid #CCC; padding-top: 7px; margin-top: 10px; }</style>';
+    
+    $js_dynamic = '';
+    if ( defined('IN_ENANO_INSTALL') )
+    {
+      $js_dynamic .= '<script type="text/javascript" src="install.php?mode=langjs"></script>';
+    }
+    $js_dynamic .= '<script type="text/javascript">var title="'. $title .'"; var scriptPath="'.scriptPath.'"; var ENANO_SID=""; var AES_BITS='.AES_BITS.'; var AES_BLOCKSIZE=' . AES_BLOCKSIZE . '; var pagepass=\'\'; var ENANO_LANG_ID = 1;</script>';
+    
     // The rewritten template engine will process all required vars during the load_template stage instead of (cough) re-processing everything each time around.
     $tpl_strings = Array(
       'PAGE_NAME'=>$this_page,
       'PAGE_URLNAME'=>'Null',
-      'SITE_NAME'=>'Enano Installation',
+      'SITE_NAME'=> ( defined('IN_ENANO_INSTALL') && is_object($lang) ) ? $lang->get('meta_site_name') : 'Critical error',
       'USERNAME'=>'admin',
-      'SITE_DESC'=>'Install Enano on your server.',
+      'SITE_DESC'=>( defined('IN_ENANO_INSTALL') && is_object($lang) ) ? $lang->get('meta_site_desc') : 'This site is experiencing a problem and cannot load.',
       'TOOLBAR'=>$tb,
       'SCRIPTPATH'=>scriptPath,
       'CONTENTPATH'=>contentPath,
@@ -1854,7 +1980,7 @@
       'ADMIN_SID_AMP_HTML'=>'',
       'ADDITIONAL_HEADERS'=>$this->additional_headers,
       'SIDEBAR_EXTRA'=>'',
-      'COPYRIGHT'=>'Enano and all of its code, graphics, and more code is copyright &copy; 2006 Dan Fuhry.<br />This program is Free Software; see the file "GPL" included with this package for details.',
+      'COPYRIGHT'=>( defined('IN_ENANO_INSTALL') && is_object($lang) ) ? $lang->get('meta_enano_copyright') : ( defined('ENANO_CONFIG_FETCHED') ? getConfig('copyright_notice') : '' ),
       'TOOLBAR_EXTRAS'=>'',
       'REQUEST_URI'=>( isset($_SERVER['HTTP_HOST']) ? $_SERVER['HTTP_HOST'] : '' ).$_SERVER['REQUEST_URI'],
       'STYLE_LINK'=>$slink,
@@ -1863,9 +1989,10 @@
       'TEMPLATE_DIR'=>scriptPath.'/themes/'.$this->theme,
       'THEME_ID'=>$this->theme,
       'STYLE_ID'=>$this->style,
-      'JS_DYNAMIC_VARS'=>'<script type="text/javascript">var title="'. $title .'"; var scriptPath="'.scriptPath.'"; var ENANO_SID=""; var AES_BITS='.AES_BITS.'; var AES_BLOCKSIZE=' . AES_BLOCKSIZE . '; var pagepass=\'\';</script>',
+      'JS_DYNAMIC_VARS'=>$js_dynamic,
       'SIDEBAR_RIGHT'=>'',
-      'REPORT_URI' => ''
+      'REPORT_URI' => '',
+      'URL_ABOUT_ENANO' => 'http://enanocms.org/'
       );
     $this->tpl_strings = array_merge($tpl_strings, $this->tpl_strings);
     
@@ -1881,7 +2008,7 @@
       }
       $p = $this->makeParserText($tplvars['sidebar_section']);
       $p->assign_vars(Array(
-          'TITLE'=>'Installation progress',
+          'TITLE'=>$lang->get('meta_sidebar_heading'),
           'CONTENT'=>$sidebar,
         ));
       $sidebar = $p->run();
@@ -1912,28 +2039,55 @@
   function footer($simple = false)
   {
     global $db, $session, $paths, $template, $plugins; // Common objects
+    global $lang;
+    
     if(!$this->no_headers) {
       global $_starttime;
       
-      $f = microtime(true);
+      $filename = ( $simple ) ? 'simple-footer.tpl' : 'footer.tpl';
+      $t = $this->process_template($filename);
+      
+      $f = microtime_float();
       $f = $f - $_starttime;
       $f = round($f, 4);
-      if(defined('IN_ENANO_INSTALL')) $nq = 'N/A';
-      else $nq = $db->num_queries;
-      if($nq == 0) $nq = 'N/A';
-      $dbg = 'Time: '.$f.'s  |  Queries: '.$nq;
-      $filename = ( $simple ) ? 'simple-footer.tpl' : 'footer.tpl';
-      $t = $this->process_template($filename);
-      $t = str_replace('[[Stats]]', $dbg, $t);
-      if ( is_object($db) )
+      
+      if ( is_object($lang) )
       {
-        $t = str_replace('[[NumQueries]]', (string)$db->num_queries, $t);
+        $t_loc = $lang->get('page_msg_stats_gentime_short', array('time' => $f));
+        $t_loc_long = $lang->get('page_msg_stats_gentime_long', array('time' => $f));
+        $q_loc = '<a href="' . $this->tpl_strings['REPORT_URI'] . '">' . $lang->get('page_msg_stats_sql', array('nq' => ( is_object($db) ? $db->num_queries : 'N/A' ))) . '</a>';
+        $dbg = $t_loc;
+        $dbg_long = $t_loc_long;
+        if ( $session->user_level >= USER_LEVEL_ADMIN )
+        {
+          $dbg .= "&nbsp;&nbsp;|&nbsp;&nbsp;$q_loc";
+          $dbg_long .= "&nbsp;&nbsp;|&nbsp;&nbsp;$q_loc";
+        }
+        $t = str_replace('[[EnanoPoweredLink]]', $lang->get('page_enano_powered', array('about_uri' => $this->tpl_strings['URL_ABOUT_ENANO'])), $t);
+        $t = str_replace('[[EnanoPoweredLinkLong]]', $lang->get('page_enano_powered_long', array('about_uri' => $this->tpl_strings['URL_ABOUT_ENANO'])), $t);
       }
       else
       {
-        $t = str_replace('[[NumQueries]]', '0', $t);
+        $t_loc = "Time: {$f}s";
+        $t_loc_long = "Generated in {$f}sec";
+        $q_loc = '<a href="' . $this->tpl_strings['REPORT_URI'] . '">' . ( is_object($db) ? "{$db->num_queries} SQL" : 'Queries: N/A' ) . '</a>';
+        $dbg = $t_loc;
+        $dbg_long = $t_loc_long;
+        if ( $session->user_level >= USER_LEVEL_ADMIN )
+        {
+          $dbg .= "&nbsp;&nbsp;|&nbsp;&nbsp;$q_loc";
+          $dbg_long .= "&nbsp;&nbsp;|&nbsp;&nbsp;$q_loc";
+        }
+        $t = str_replace('[[EnanoPoweredLink]]', 'Powered by <a href="http://enanocms.org/" onclick="window.open(this.href); return false;">Enano</a>', $t);
+        $t = str_replace('[[EnanoPoweredLinkLong]]', 'Website engine powered by <a href="http://enanocms.org/" onclick="window.open(this.href); return false;">Enano</a>', $t);
       }
+      
+      $t = str_replace('[[Stats]]', $dbg, $t);
+      $t = str_replace('[[StatsLong]]', $dbg_long, $t);
+      $t = str_replace('[[NumQueries]]', ( is_object($db) ? (string)$db->num_queries : '0' ), $t);
       $t = str_replace('[[GenTime]]', (string)$f, $t);
+      $t = str_replace('[[NumQueriesLoc]]', $q_loc, $t);
+      $t = str_replace('[[GenTimeLoc]]', $t_loc, $t);
       
       echo $t;
     }
@@ -2066,9 +2220,9 @@
   /**
    * PHP 4 constructor.
    */
-  function templateIndividualSafe($text, $parent)
+  function templateIndividual($text)
   {
-    $this->__construct($text, $parent);
+    $this->__construct($text);
   }
   /**
    * Assigns an array of string values to the template. Strings can be accessed from the template by inserting {KEY_NAME} in the template file.
--- a/includes/wikiengine/Tables.php	Fri Feb 22 12:46:51 2008 -0500
+++ b/includes/wikiengine/Tables.php	Fri Feb 22 12:51:53 2008 -0500
@@ -2,7 +2,7 @@
 
 /*
  * Enano - an open-source CMS capable of wiki functions, Drupal-like sidebar blocks, and everything in between
- * Version 1.0.3 (Dyrad)
+ * Version 1.1.2 (Caoineag alpha 2)
  * Copyright (C) 2006-2007 Dan Fuhry
  *
  * This program is Free Software; you can redistribute and/or modify it under the terms of the GNU General Public License
@@ -587,6 +587,7 @@
       'nowiki'     => array(),
       'noinclude'  => array(),
       'nodisplay'  => array(),
+      'lang'       => array('code'),
       
       # XHTML stuff
       'acronym'    => $common
--- a/includes/wikiformat.php	Fri Feb 22 12:46:51 2008 -0500
+++ b/includes/wikiformat.php	Fri Feb 22 12:51:53 2008 -0500
@@ -107,6 +107,18 @@
         if (is_array($rules)) {
             $this->rules = $rules;
         }
+        
+        global $plugins;
+        // This code can be run from the installer, so in some cases $plugins
+        // isn't initted. (Bug in 1.1.2, fixed for 1.1.3)
+        if ( is_object($plugins) )
+        {
+          $code = $plugins->setHook('text_wiki_construct');
+          foreach ( $code as $cmd )
+          {
+              eval($cmd);
+          }
+        }
 
         $this->addPath(
             'parse',
@@ -119,11 +131,11 @@
 
     }
 
-    function &singleton($parser = 'Default', $rules = null)
+    public static function singleton($parser = 'Default', $rules = null)
     {
         static $only = array();
         if (!isset($only[$parser])) {
-            $ret =& Text_Wiki::factory($parser, $rules);
+            $ret = Text_Wiki::factory($parser, $rules);
             if (!$ret) {
                 return $ret;
             }
@@ -132,7 +144,7 @@
         return $only[$parser];
     }
 
-    function &factory($parser = 'Default', $rules = null)
+    public static function factory($parser = 'Default', $rules = null)
     {
         $d=getcwd();
         chdir(ENANO_ROOT);
@@ -154,7 +166,7 @@
         
         chdir($d);
 
-        $obj =& new $class($rules);
+        $obj = new $class($rules);
         return $obj;
     }
 
@@ -514,7 +526,7 @@
             }
         }
 
-        $this->parseObj[$rule] =& new $class($this);
+        $this->parseObj[$rule] = new $class($this);
 
     }
 
@@ -536,7 +548,7 @@
             }
         }
 
-        $this->renderObj[$rule] =& new $class($this);
+        $this->renderObj[$rule] = new $class($this);
     }
 
     function loadFormatObj($format)
@@ -556,7 +568,7 @@
             }
         }
 
-        $this->formatObj[$format] =& new $class($this);
+        $this->formatObj[$format] = new $class($this);
     }
 
     function addPath($type, $dir)
@@ -613,7 +625,7 @@
 
     function isError(&$obj)
     {
-        return is_a($obj, 'PEAR_Error');
+        return ( @get_class($obj) == 'PEAR_Error' );
     }
 }
 
--- a/index.php	Fri Feb 22 12:46:51 2008 -0500
+++ b/index.php	Fri Feb 22 12:51:53 2008 -0500
@@ -2,7 +2,7 @@
 
 /*
  * Enano - an open-source CMS capable of wiki functions, Drupal-like sidebar blocks, and everything in between
- * Version 1.0.3 (Dyrad)
+ * Version 1.1.2
  * Copyright (C) 2006-2007 Dan Fuhry
  *
  * This program is Free Software; you can redistribute and/or modify it under the terms of the GNU General Public License
@@ -17,13 +17,16 @@
  */
  
   define('ENANO_INTERFACE_INDEX', '');
+  
+  // For the mighty and brave.
+  // define('ENANO_DEBUG', '');
  
   // Set up gzip encoding before any output is sent
   
-  $aggressive_optimize_html = false;
+  $aggressive_optimize_html = true;
   
   global $do_gzip;
-  $do_gzip = false;
+  $do_gzip = true;
   
   if(isset($_SERVER['PATH_INFO'])) $v = $_SERVER['PATH_INFO'];
   elseif(isset($_GET['title'])) $v = $_GET['title'];
@@ -34,15 +37,6 @@
   
   error_reporting(E_ALL);
   
-  // if(!strstr($v, 'CSS') && !strstr($v, 'UploadFile') && !strstr($v, 'DownloadFile')) // These pages are blacklisted because we can't have debugConsole's HTML output disrupting the flow of header() calls and whatnot
-  // {
-  //   $do_gzip = ( function_exists('gzcompress') && ( isset($_SERVER['HTTP_ACCEPT_ENCODING']) && strstr($_SERVER['HTTP_ACCEPT_ENCODING'], 'gzip') ) ) ? true : false;
-  //   // Uncomment the following line to enable debugConsole (requires PHP 5 or later)
-  //   // define('ENANO_DEBUG', '');
-  // }
-  
-  if(defined('ENANO_DEBUG')) $do_gzip = false;
-  
   if($aggressive_optimize_html || $do_gzip)
   {
     ob_start();
@@ -97,11 +91,12 @@
           if(!$q) $db->_die('The comment data could not be selected.');
           $row = $db->fetchrow();
           $db->free_result();
+          $row['subject'] = str_replace('\'', '&#039;', $row['subject']);
           echo '<form action="'.makeUrl($paths->page, 'do=comments&amp;sub=savecomment').'" method="post">';
           echo "<br /><div class='tblholder'><table border='0' width='100%' cellspacing='1' cellpadding='4'>
-                  <tr><td class='row1'>Subject:</td><td class='row1'><input type='text' name='subj' value='{$row['subject']}' /></td></tr>
-                  <tr><td class='row2'>Comment:</td><td class='row2'><textarea rows='10' cols='40' style='width: 98%;' name='text'>{$row['comment_data']}</textarea></td></tr>
-                  <tr><td class='row1' colspan='2' class='row1' style='text-align: center;'><input type='hidden' name='id' value='{$row['comment_id']}' /><input type='submit' value='Save Changes' /></td></tr>
+                  <tr><td class='row1'>" . $lang->get('comment_postform_field_subject') . "</td><td class='row1'><input type='text' name='subj' value='{$row['subject']}' /></td></tr>
+                  <tr><td class='row2'>" . $lang->get('comment_postform_field_comment') . "</td><td class='row2'><textarea rows='10' cols='40' style='width: 98%;' name='text'>{$row['comment_data']}</textarea></td></tr>
+                  <tr><td class='row1' colspan='2' class='row1' style='text-align: center;'><input type='hidden' name='id' value='{$row['comment_id']}' /><input type='submit' value='" . $lang->get('etc_save_changes') . "' /></td></tr>
                 </table></div>";
           echo '</form>';
           break;
@@ -129,32 +124,106 @@
       }
       if(isset($_POST['_save']))
       {
-        $e = PageUtils::savepage($paths->page_id, $paths->namespace, $_POST['page_text'], $_POST['edit_summary'], isset($_POST['minor']));
-        if ( $e == 'good' )
+        $captcha_valid = true;
+        if ( !$session->user_logged_in && getConfig('guest_edit_require_captcha') == '1' )
         {
-          redirect(makeUrl($paths->page), 'Changes saved', 'Your changes to this page have been saved. Redirecting...', 3);
+          $captcha_valid = false;
+          if ( isset($_POST['captcha_id']) && isset($_POST['captcha_code']) )
+          {
+            $hash_correct = strtolower($session->get_captcha($_POST['captcha_id']));
+            $hash_input   = strtolower($_POST['captcha_code']);
+            if ( $hash_input === $hash_correct )
+              $captcha_valid = true;
+          }
+        }
+        if ( $captcha_valid )
+        {
+          $e = PageUtils::savepage($paths->page_id, $paths->namespace, $_POST['page_text'], $_POST['edit_summary'], isset($_POST['minor']));
+          if ( $e == 'good' )
+          {
+            redirect(makeUrl($paths->page), $lang->get('editor_msg_save_success_title'), $lang->get('editor_msg_save_success_body'), 3);
+          }
         }
       }
       $template->header();
+      if ( isset($captcha_valid) )
+      {
+        echo '<div class="usermessage">' . $lang->get('editor_err_captcha_wrong') . '</div>';
+      }
       if(isset($_POST['_preview']))
       {
         $text = $_POST['page_text'];
+        $edsumm = $_POST['edit_summary'];
         echo PageUtils::genPreview($_POST['page_text']);
+        $text = htmlspecialchars($text);
+        $revid = 0;
+      }
+      else
+      {
+        $revid = ( isset($_GET['revid']) ) ? intval($_GET['revid']) : 0;
+        $page = new PageProcessor($paths->page_id, $paths->namespace, $revid);
+        $text = $page->fetch_source();
+        $edsumm = '';
+        // $text = RenderMan::getPage($paths->cpage['urlname_nons'], $paths->namespace, 0, false, false, false, false);
       }
-      else $text = RenderMan::getPage($paths->page_id, $paths->namespace, 0, false, false, false, false);
+      if ( $revid > 0 )
+      {
+        echo '<div class="usermessage">' . $lang->get('editor_msg_editing_old_revision') . '</div>';
+        // Retrieve information about this revision and the current one
+        $q = $db->sql_query('SELECT l1.author AS currentrev_author, l2.author AS oldrev_author FROM ' . table_prefix . 'logs AS l1
+  LEFT JOIN ' . table_prefix . 'logs AS l2
+    ON ( l2.time_id = ' . $revid . '
+         AND l2.log_type  = \'page\'
+         AND l2.action    = \'edit\'
+         AND l2.page_id   = \'ACL_Tests\'
+         AND l2.namespace = \'Article\'
+        )
+  WHERE l1.log_type  = \'page\'
+    AND l1.action    = \'edit\'
+    AND l1.page_id   = \'ACL_Tests\'
+    AND l1.namespace = \'Article\'
+    AND l1.time_id >= ' . $revid . '
+  ORDER BY l1.time_id DESC;');
+        if ( !$q )
+          $db->die_json();
+        
+        $rev_count = $db->numrows() - 1;
+        $row = $db->fetchrow();
+        $undo_info = array(
+          'old_author'     => $row['oldrev_author'],
+          'current_author' => $row['currentrev_author'],
+          'undo_count'     => $rev_count,
+          'last_rev_id'    => $revid
+        );
+        $db->free_result();
+      }
       echo '
         <form action="'.makeUrl($paths->page, 'do=edit').'" method="post" enctype="multipart/form-data">
         <br />
         <textarea name="page_text" rows="20" cols="60" style="width: 97%;">'.$text.'</textarea><br />
         <br />
         ';
-      if($paths->wiki_mode)
-        echo 'Edit summary: <input name="edit_summary" type="text" size="40" /><br /><label><input type="checkbox" name="minor" /> This is a minor edit</label><br />';  
+      $edsumm = ( $revid > 0 ) ? $lang->get('editor_reversion_edit_summary', $undo_info) : $edsumm;
+      echo $lang->get('editor_lbl_edit_summary') . ' <input name="edit_summary" type="text" size="40" value="' . htmlspecialchars($edsumm) . '" /><br /><label><input type="checkbox" name="minor" /> ' . $lang->get('editor_lbl_minor_edit_field') . '</label><br />';
+      if ( !$session->user_logged_in && getConfig('guest_edit_require_captcha') == '1' )
+      {
+        echo '<br /><table border="0"><tr><td>';
+        echo '<b>' . $lang->get('editor_lbl_field_captcha') . '</b><br />'
+             . '<br />'
+             . $lang->get('editor_msg_captcha_pleaseenter') . '<br /><br />'
+             . $lang->get('editor_msg_captcha_blind');
+        echo '</td><td>';
+        $hash = $session->make_captcha();
+        echo '<img src="' . makeUrlNS('Special', "Captcha/$hash") . '" onclick="this.src+=\'/a\'" style="cursor: pointer;" /><br />';
+        echo '<input type="hidden" name="captcha_id" value="' . $hash . '" />';
+        echo $lang->get('editor_lbl_field_captcha_code') . ' <input type="text" name="captcha_code" value="" size="9" />';
+        echo '</td></tr></table>';
+      }
       echo '<br />
-          <input type="submit" name="_save" value="Save changes" style="font-weight: bold;" />
-          <input type="submit" name="_preview" value="Preview changes" />
-          <input type="submit" name="_revert" value="Revert changes" />
-          <input type="submit" name="_cancel" value="Cancel" />
+          <input type="submit" name="_save"    value="' . $lang->get('editor_btn_save') . '" style="font-weight: bold;" />
+          <input type="submit" name="_preview" value="' . $lang->get('editor_btn_preview') . '" />
+          <input type="submit" name="_revert"  value="' . $lang->get('editor_btn_revert') . '" />
+          <input type="submit" name="_cancel"  value="' . $lang->get('editor_btn_cancel') . '" />
         </form>
       ';
       if ( getConfig('wiki_edit_notice') == '1' )
@@ -167,12 +236,13 @@
     case 'viewsource':
       $template->header();
       $text = RenderMan::getPage($paths->page_id, $paths->namespace, 0, false, false, false, false);
+      $text = htmlspecialchars($text);
       echo '
         <form action="'.makeUrl($paths->page, 'do=edit').'" method="post">
         <br />
         <textarea readonly="readonly" name="page_text" rows="20" cols="60" style="width: 97%;">'.$text.'</textarea>';
       echo '<br />
-          <input type="submit" name="_cancel" value="Close viewer" />
+          <input type="submit" name="_cancel" value="' . $lang->get('editor_btn_closeviewer') . '" />
         </form>
       ';
       $template->footer();
@@ -214,7 +284,7 @@
       break;
     case 'moreoptions':
       $template->header();
-      echo '<div class="menu_nojs" style="width: 150px; padding: 0;"><ul style="display: block;"><li><div class="label">More options for this page</div><div style="clear: both;"></div></li>'.$template->tpl_strings['TOOLBAR_EXTRAS'].'</ul></div>';
+      echo '<div class="menu_nojs" style="width: 150px; padding: 0;"><ul style="display: block;"><li><div class="label">' . $lang->get('ajax_lbl_moreoptions_nojs') . '</div><div style="clear: both;"></div></li>'.$template->toolbar_menu.'</ul></div>';
       $template->footer();
       break;
     case 'protect':
@@ -223,32 +293,33 @@
       {
         if(!preg_match('#^([0-2]*){1}$#', $_POST['level'])) die_friendly('Error protecting page', '<p>Request validation failed</p>');
         PageUtils::protect($paths->page_id, $paths->namespace, intval($_POST['level']), $_POST['reason']);
-        die_friendly('Page protected', '<p>The protection setting has been applied. <a href="'.makeUrl($paths->page).'">Return to the page</a>.</p>');
+        
+        die_friendly($lang->get('page_protect_lbl_success_title'), '<p>' . $lang->get('page_protect_lbl_success_body', array( 'page_link' => makeUrl($paths->page) )) . '</p>');
       }
       $template->header();
       ?>
       <form action="<?php echo makeUrl($paths->page, 'do=protect'); ?>" method="post">
         <input type="hidden" name="level" value="<?php echo $_REQUEST['level']; ?>" />
-        <?php if(isset($_POST['reason'])) echo '<p style="color: red;">Error: you must enter a reason for protecting this page.</p>'; ?>
-        <p>Reason for protecting the page:</p>
+        <?php if(isset($_POST['reason'])) echo '<p style="color: red;">' . $lang->get('page_protect_err_need_reason') . '</p>'; ?>
+        <p><?php echo $lang->get('page_protect_lbl_reason'); ?></p>
         <p><input type="text" name="reason" size="40" /><br />
-           Protecion level to be applied: <b><?php
+           <?php echo $lang->get('page_protect_lbl_level'); ?> <b><?php
              switch($_REQUEST['level'])
              {
                case '0':
-                 echo 'No protection';
+                 echo $lang->get('page_protect_lbl_level_none');
                  break;
                case '1':
-                 echo 'Full protection';
+                 echo $lang->get('page_protect_lbl_level_full');
                  break;
                case '2':
-                 echo 'Semi-protection';
+                 echo $lang->get('page_protect_lbl_level_semi');
                  break;
                default:
                  echo 'None;</b> Warning: request validation will fail after clicking submit<b>';
              }
            ?></b></p>
-        <p><input type="submit" value="Protect page" style="font-weight: bold;" /></p> 
+        <p><input type="submit" value="<?php echo htmlspecialchars($lang->get('page_protect_btn_submit')) ?>" style="font-weight: bold;" /></p> 
       </form>
       <?php
       $template->footer();
@@ -257,37 +328,37 @@
       if(!empty($_POST['newname']))
       {
         $r = PageUtils::rename($paths->page_id, $paths->namespace, $_POST['newname']);
-        die_friendly('Page renamed', '<p>'.nl2br($r).' <a href="'.makeUrl($paths->page).'">Return to the page</a>.</p>');
+        die_friendly($lang->get('page_rename_success_title'), '<p>'.nl2br($r).' <a href="'.makeUrl($paths->page).'">' . $lang->get('etc_return_to_page') . '</a>.</p>');
       }
       $template->header();
       ?>
       <form action="<?php echo makeUrl($paths->page, 'do=rename'); ?>" method="post">
-        <?php if(isset($_POST['newname'])) echo '<p style="color: red;">Error: you must enter a new name for this page.</p>'; ?>
-        <p>Please enter a new name for this page:</p>
+        <?php if(isset($_POST['newname'])) echo '<p style="color: red;">' . $lang->get('page_rename_err_need_name') . '</p>'; ?>
+        <p><?php echo $lang->get('page_rename_lbl'); ?></p>
         <p><input type="text" name="newname" size="40" /></p>
-        <p><input type="submit" value="Rename page" style="font-weight: bold;" /></p> 
+        <p><input type="submit" value="<?php echo htmlspecialchars($lang->get('page_rename_btn_submit')); ?>" style="font-weight: bold;" /></p> 
       </form>
       <?php
       $template->footer();    
       break;
     case 'flushlogs':
-      if(!$session->get_permissions('clear_logs')) die_friendly('Access denied', '<p>Flushing the logs for a page <u>requires</u> administrative rights.</p>');
+      if(!$session->get_permissions('clear_logs'))
+      {
+        die_friendly($lang->get('etc_access_denied_short'), '<p>' . $lang->get('etc_access_denied') . '</p>');
+      }
       if(isset($_POST['_downthejohn']))
       {
         $template->header();
           $result = PageUtils::flushlogs($paths->page_id, $paths->namespace);
-          echo '<p>'.$result.' <a href="'.makeUrl($paths->page).'">Return to the page</a>.</p>';
+          echo '<p>'.$result.' <a href="'.makeUrl($paths->page).'">' . $lang->get('etc_return_to_page') . '</a>.</p>';
         $template->footer();
         break;
       }
       $template->header();
         ?>
         <form action="<?php echo makeUrl($paths->page, 'do=flushlogs'); ?>" method="post">
-          <h3>You are about to <span style="color: red;">destroy</span> all logged edits and actions on this page.</h3>
-           <p>Unlike deleting or editing this page, this action is <u>not reversible</u>! You should only do this if you are desparate for
-              database space.</p>
-           <p>Do you really want to continue?</p>
-           <p><input type="submit" name="_downthejohn" value="Flush logs" style="color: red; font-weight: bold;" /></p>
+           <?php echo $lang->get('page_flushlogs_warning_stern'); ?>
+           <p><input type="submit" name="_downthejohn" value="<?php echo htmlspecialchars($lang->get('page_flushlogs_btn_submit')); ?>" style="color: red; font-weight: bold;" /></p>
         </form>
         <?php
       $template->footer();
@@ -297,55 +368,66 @@
       {
         $template->header();
         $result = PageUtils::delvote($paths->page_id, $paths->namespace);
-        echo '<p>'.$result.' <a href="'.makeUrl($paths->page).'">Return to the page</a>.</p>';
+        echo '<p>'.$result.' <a href="'.makeUrl($paths->page).'">' . $lang->get('etc_return_to_page') . '</a>.</p>';
         $template->footer();
         break;
       }
       $template->header();
         ?>
         <form action="<?php echo makeUrl($paths->page, 'do=delvote'); ?>" method="post">
-          <h3>Your vote counts.</h3>
-           <p>If you think that this page is not relavent to the content on this site, or if it looks like this page was only created in
-              an attempt to spam the site, you can request that this page be deleted by an administrator.</p>
-           <p>After you vote, you should leave a comment explaining the reason for your vote, especially if you are the first person to
-              vote against this page.</p>
-           <p>So far, <?php echo ( $paths->cpage['delvotes'] == 1 ) ? $paths->cpage['delvotes'] . ' person has' : $paths->cpage['delvotes'] . ' people have'; ?> voted to delete this page.</p>
-           <p><input type="submit" name="_ballotbox" value="Vote to delete this page" /></p>
+           <?php
+             echo $lang->get('page_delvote_warning_stern');
+             echo '<p>';
+             switch($paths->cpage['delvotes'])
+             {
+               case 0:  echo $lang->get('page_delvote_count_zero'); break;
+               case 1:  echo $lang->get('page_delvote_count_one'); break;
+               default: echo $lang->get('page_delvote_count_plural', array('delvotes' => $paths->cpage['delvotes'])); break;
+             }
+             echo '</p>';
+           ?>
+           <p><input type="submit" name="_ballotbox" value="<?php echo htmlspecialchars($lang->get('page_delvote_btn_submit')); ?>" /></p>
         </form>
         <?php
       $template->footer();
       break;
     case 'resetvotes':
-      if(!$session->get_permissions('vote_reset')) die_friendly('Access denied', '<p>Resetting the deletion votes against this page <u>requires</u> admin rights.</p>');
+      if(!$session->get_permissions('vote_reset'))
+      {
+        die_friendly($lang->get('etc_access_denied_short'), '<p>' . $lang->get('etc_access_denied') . '</p>');
+      }
       if(isset($_POST['_youmaylivealittlelonger']))
       {
         $template->header();
           $result = PageUtils::resetdelvotes($paths->page_id, $paths->namespace);
-          echo '<p>'.$result.' <a href="'.makeUrl($paths->page).'">Return to the page</a>.</p>';
+          echo '<p>'.$result.' <a href="'.makeUrl($paths->page).'">' . $lang->get('etc_return_to_page') . '</a>.</p>';
         $template->footer();
         break;
       }
       $template->header();
         ?>
         <form action="<?php echo makeUrl($paths->page, 'do=resetvotes'); ?>" method="post">
-          <p>This action will reset the number of votes against this page to zero. Are you sure you want to do this?</p>
-          <p><input type="submit" name="_youmaylivealittlelonger" value="Reset votes" /></p>
+          <p><?php echo $lang->get('ajax_delvote_reset_confirm'); ?></p>
+          <p><input type="submit" name="_youmaylivealittlelonger" value="<?php echo htmlspecialchars($lang->get('page_delvote_reset_btn_submit')); ?>" /></p>
         </form>
         <?php
       $template->footer();
       break;
     case 'deletepage':
-      if(!$session->get_permissions('delete_page')) die_friendly('Access denied', '<p>Deleting pages <u>requires</u> admin rights.</p>');
+      if(!$session->get_permissions('delete_page'))
+      {
+        die_friendly($lang->get('etc_access_denied_short'), '<p>' . $lang->get('etc_access_denied') . '</p>');
+      }
       if(isset($_POST['_adiossucker']))
       {
         $reason = ( isset($_POST['reason']) ) ? $_POST['reason'] : false;
         if ( empty($reason) )
-          $error = 'Please enter a reason for deleting this page.';
+          $error = $lang->get('ajax_delete_prompt_reason');
         else
         {
           $template->header();
             $result = PageUtils::deletepage($paths->page_id, $paths->namespace, $reason);
-            echo '<p>'.$result.' <a href="'.makeUrl($paths->page).'">Return to the page</a>.</p>';
+            echo '<p>'.$result.' <a href="'.makeUrl($paths->page).'">' . $lang->get('etc_return_to_page') . '</a>.</p>';
           $template->footer();
           break;
         }
@@ -353,19 +435,19 @@
       $template->header();
         ?>
         <form action="<?php echo makeUrl($paths->page, 'do=deletepage'); ?>" method="post">
-          <h3>You are about to <span style="color: red;">destroy</span> this page.</h3>
-           <p>While the deletion of the page itself is completely reversible, it is impossible to recover any comments or category information on this page. If this is a file page, the file along with all older revisions of it will be permanently deleted. Also, any custom information that this page is tagged with, such as a custom name, protection status, or additional settings such as whether to allow comments, will be permanently lost.</p>
-           <p>Are you <u>absolutely sure</u> that you want to continue?<br />
-              You will not be asked again.</p>
+           <?php echo $lang->get('page_delete_warning_stern'); ?>
            <?php if ( isset($error) ) echo "<p>$error</p>"; ?>
-           <p>Reason for deleting: <input type="text" name="reason" size="50" /></p>
-           <p><input type="submit" name="_adiossucker" value="Delete this page" style="color: red; font-weight: bold;" /></p>
+           <p><?php echo $lang->get('page_delete_lbl_reason'); ?> <input type="text" name="reason" size="50" /></p>
+           <p><input type="submit" name="_adiossucker" value="<?php echo htmlspecialchars($lang->get('page_delete_btn_submit')); ?>" style="color: red; font-weight: bold;" /></p>
         </form>
         <?php
       $template->footer();
       break;
     case 'setwikimode':
-      if(!$session->get_permissions('set_wiki_mode')) die_friendly('Access denied', '<p>Changing the wiki mode setting <u>requires</u> admin rights.</p>');
+      if(!$session->get_permissions('set_wiki_mode'))
+      {
+        die_friendly($lang->get('etc_access_denied_short'), '<p>' . $lang->get('etc_access_denied') . '</p>');
+      }
       if ( isset($_POST['finish']) )
       {
         $level = intval($_POST['level']);
@@ -376,7 +458,7 @@
         $q = $db->sql_query('UPDATE '.table_prefix.'pages SET wiki_mode=' . $level . ' WHERE urlname=\'' . $db->escape($paths->page_id) . '\' AND namespace=\'' . $paths->namespace . '\';');
         if ( !$q )
           $db->_die();
-        redirect(makeUrl($paths->page), htmlspecialchars($paths->cpage['name']), 'Wiki mode for this page has been set. Redirecting you to the page...', 2);
+        redirect(makeUrl($paths->page), htmlspecialchars($paths->cpage['name']), $lang->get('page_wikimode_success_redirect'), 2);
       }
       else
       {
@@ -390,17 +472,13 @@
         echo '<form action="' . makeUrl($paths->page, 'do=setwikimode', true) . '" method="post">';
         echo '<input type="hidden" name="finish" value="foo" />';
         echo '<input type="hidden" name="level" value="' . $level . '" />';
-        $level_txt = ( $level == 0 ) ? 'disabled' : ( ( $level == 1 ) ? 'enabled' : 'use the global setting' );
-        $blurb = ( $level == 0 || ( $level == 2 && getConfig('wiki_mode') != '1' ) ) ? 'Because this will disable the wiki behavior on this page, several features, most
-           notably the ability for users to vote to have this page deleted, will be disabled as they are not relevant to non-wiki pages. In addition, users will not be able
-           to edit this page unless an ACL rule specifically permits them.' : 'Because this will enable the wiki behavior on this page, users will gain the ability to
-           freely edit this page unless an ACL rule specifically denies them. If your site is public and gets good traffic, you should be aware of the possiblity of vandalism, and you need to be ready to revert
-           malicious edits to this page.';
+        $level_txt = ( $level == 0 ) ? 'page_wikimode_level_off' : ( ( $level == 1 ) ? 'page_wikimode_level_on' : 'page_wikimode_level_global' );
+        $blurb = ( $level == 0 || ( $level == 2 && getConfig('wiki_mode') != '1' ) ) ? 'page_wikimode_blurb_disable' : 'page_wikimode_blurb_enable';
         ?>
-        <h3>You are changing wiki mode for this page.</h3>
-        <p>Wiki features will be set to <?php echo $level_txt; ?>. <?php echo $blurb; ?></p>
-        <p>If you want to continue, please click the button below.</p>
-        <p><input type="submit" value="Set wiki mode" /></p>
+        <h3><?php echo $lang->get('page_wikimode_heading'); ?></h3>
+        <p><?php echo $lang->get($level_txt) . ' ' . $lang->get($blurb); ?></p>
+        <p><?php echo $lang->get('page_wikimode_warning'); ?></p>
+        <p><input type="submit" value="<?php echo htmlspecialchars($lang->get('page_wikimode_btn_submit')); ?>" /></p>
         <?php
         echo '</form>';
         $template->footer();
@@ -419,16 +497,16 @@
     case 'detag':
       if ( $session->user_level < USER_LEVEL_ADMIN )
       {
-        die_friendly('Access denied', '<p>You need to be an administrator to detag pages.</p>');
+        die_friendly($lang->get('etc_access_denied_short'), '<p>' . $lang->get('etc_access_denied') . '</p>');
       }
       if ( $paths->page_exists )
       {
-        die_friendly('Invalid request', '<p>The detag action is only valid for pages that have been deleted in the past.</p>');
+        die_friendly($lang->get('etc_invalid_request_short'), '<p>' . $lang->get('page_detag_err_page_exists') . '</p>');
       }
       $q = $db->sql_query('DELETE FROM '.table_prefix.'tags WHERE page_id=\'' . $db->escape($paths->page_id) . '\' AND namespace=\'' . $paths->namespace . '\';');
       if ( !$q )
         $db->_die('Detag query, index.php:'.__LINE__);
-      die_friendly('Page detagged', '<p>All stale tags have been removed from this page.</p>');
+      die_friendly($lang->get('page_detag_success_title'), '<p>' . $lang->get('page_detag_success_body') . '</p>');
       break;
     case 'aclmanager':
       $data = ( isset($_POST['data']) ) ? $_POST['data'] : Array('mode' => 'listgroups');
--- a/install.php	Fri Feb 22 12:46:51 2008 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1914 +0,0 @@
-<?php
-
-/*
- * Enano - an open-source CMS capable of wiki functions, Drupal-like sidebar blocks, and everything in between
- * Version 1.0.3 (Dyrad)
- * Copyright (C) 2006-2007 Dan Fuhry
- * install.php - handles everything related to installation and initial configuration
- *
- * This program is Free Software; you can redistribute and/or modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.
- *
- * 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.
- */
- 
-@include('config.php');
-if( ( defined('ENANO_INSTALLED') || defined('MIDGET_INSTALLED') ) && ((isset($_GET['mode']) && ($_GET['mode']!='finish' && $_GET['mode']!='css') && $_GET['mode']!='showlicense') || !isset($_GET['mode'])))
-{
-  $_GET['title'] = 'Enano:Installation_locked';
-  require('includes/common.php');
-  die_friendly('Installation locked', '<p>The Enano installer has found a Enano installation in this directory. You MUST delete config.php if you want to re-install Enano.</p><p>If you wish to upgrade an older Enano installation to this version, please use the <a href="upgrade.php">upgrade script</a>.</p>');
-  exit;
-}
-
-function microtime_float()
-{
-  list($usec, $sec) = explode(" ", microtime());
-  return ((float)$usec + (float)$sec);
-}
-
-define('IN_ENANO_INSTALL', 'true');
-
-define('ENANO_VERSION', '1.0.3');
-// In beta versions, define ENANO_BETA_VERSION here
-
-if(!defined('scriptPath')) {
-  $sp = dirname($_SERVER['REQUEST_URI']);
-  if($sp == '/' || $sp == '\\') $sp = '';
-  define('scriptPath', $sp);
-}
-
-if(!defined('contentPath')) {
-  $sp = dirname($_SERVER['REQUEST_URI']);
-  if($sp == '/' || $sp == '\\') $sp = '';
-  define('contentPath', $sp);
-}
-global $_starttime, $this_page, $sideinfo;
-$_starttime = microtime(true);
-
-global $db;
-
-// Determine directory (special case for development servers)
-if ( strpos(__FILE__, '/repo/') && file_exists('.enanodev') )
-{
-  $filename = str_replace('/repo/', '/', __FILE__);
-}
-else
-{
-  $filename = __FILE__;
-}
-
-define('ENANO_ROOT', dirname($filename));
-
-function is_page($p)
-{
-  return true;
-}
-
-require('includes/wikiformat.php');
-require('includes/constants.php');
-require('includes/rijndael.php');
-require('includes/functions.php');
-require('includes/dbal.php');
-
-strip_magic_quotes_gpc();
-$neutral_color = 'C';
-
-//
-// INSTALLER LIBRARY
-//
-
-function run_installer_stage($stage_id, $stage_name, $function, $failure_explanation, $allow_skip = true)
-{
-  static $resumed = false;
-  static $resume_stack = array();
-  
-  if ( empty($resume_stack) && isset($_POST['resume_stack']) && preg_match('/[a-z_]+((\|[a-z_]+)+)/', $_POST['resume_stack']) )
-  {
-    $resume_stack = explode('|', $_POST['resume_stack']);
-  }
-  
-  $already_run = false;
-  if ( in_array($stage_id, $resume_stack) )
-  {
-    $already_run = true;
-  }
-  
-  if ( !$resumed )
-  {
-    if ( !isset($_GET['stage']) )
-      $resumed = true;
-    if ( isset($_GET['stage']) && $_GET['stage'] == $stage_id )
-    {
-      $resumed = true;
-    }
-  }
-  if ( !$resumed && $allow_skip )
-  {
-    echo_stage_success($stage_id, $stage_name);
-    return false;
-  }
-  if ( !function_exists($function) )
-    die('libenanoinstall: CRITICAL: function "' . $function . '" for ' . $stage_id . ' doesn\'t exist');
-  $result = @call_user_func($function, false, $already_run);
-  if ( $result )
-  {
-    echo_stage_success($stage_id, $stage_name);
-    $resume_stack[] = $stage_id;
-    return true;
-  }
-  else
-  {
-    echo_stage_failure($stage_id, $stage_name, $failure_explanation, $resume_stack);
-    return false;
-  }
-}
-
-function start_install_table()
-{
-  echo '<table border="0" cellspacing="0" cellpadding="0">' . "\n";
-  ob_start();
-}
-
-function close_install_table()
-{
-  echo '</table>' . "\n\n";
-  ob_end_flush();
-}
-
-function echo_stage_success($stage_id, $stage_name)
-{
-  global $neutral_color;
-  $neutral_color = ( $neutral_color == 'A' ) ? 'C' : 'A';
-  echo '<tr><td style="width: 500px; background-color: #' . "{$neutral_color}{$neutral_color}FF{$neutral_color}{$neutral_color}" . '; padding: 0 5px;">' . htmlspecialchars($stage_name) . '</td><td style="padding: 0 5px;"><img alt="Done" src="images/good.gif" /></td></tr>' . "\n";
-  ob_flush();
-}
-
-function echo_stage_failure($stage_id, $stage_name, $failure_explanation, $resume_stack)
-{
-  global $neutral_color;
-  
-  $neutral_color = ( $neutral_color == 'A' ) ? 'C' : 'A';
-  echo '<tr><td style="width: 500px; background-color: #' . "FF{$neutral_color}{$neutral_color}{$neutral_color}{$neutral_color}" . '; padding: 0 5px;">' . htmlspecialchars($stage_name) . '</td><td style="padding: 0 5px;"><img alt="Failed" src="images/bad.gif" /></td></tr>' . "\n";
-  ob_flush();
-  close_install_table();
-  $post_data = '';
-  $mysql_error = mysql_error();
-  foreach ( $_POST as $key => $value )
-  {
-    // FIXME: These should really also be sanitized for double quotes
-    $value = htmlspecialchars($value);
-    $key = htmlspecialchars($key);
-    $post_data .= "          <input type=\"hidden\" name=\"$key\" value=\"$value\" />\n";
-  }
-  echo '<form action="install.php?mode=install&amp;stage=' . $stage_id . '" method="post">
-          ' . $post_data . '
-          <input type="hidden" name="resume_stack" value="' . htmlspecialchars(implode('|', $resume_stack)) . '" />
-          <h3>Enano installation failed.</h3>
-           <p>' . $failure_explanation . '</p>
-           ' . ( !empty($mysql_error) ? "<p>The error returned from MySQL was: $mysql_error</p>" : '' ) . '
-           <p>When you have corrected the error, click the button below to attempt to continue the installation.</p>
-           <p style="text-align: center;"><input type="submit" value="Retry installation" /></p>
-        </form>';
-  global $template, $template_bak;
-  if ( is_object($template_bak) )
-    $template_bak->footer();
-  else
-    $template->footer();
-  exit;
-}
-
-//
-// INSTALLER STAGES
-//
-
-function stg_mysql_connect($act_get = false)
-{
-  global $db;
-  $db = new mysql();
-  
-  static $conn = false;
-  if ( $act_get )
-    return $conn;
-  
-  $db_user =& $_POST['db_user'];
-  $db_pass =& $_POST['db_pass'];
-  $db_name =& $_POST['db_name'];
-  
-  if ( !preg_match('/^[a-z0-9_-]+$/', $db_name) )
-  {
-    $db_name = htmlspecialchars($db_name);
-    die("<p>SECURITY: malformed database name \"$db_name\"</p>");
-  }
-  
-  // First, try to connect using the normal credentials
-  $conn = @mysql_connect($_POST['db_host'], $_POST['db_user'], $_POST['db_pass']);
-  if ( !$conn )
-  {
-    // Connection failed. Do we have the root username and password?
-    if ( !empty($_POST['db_root_user']) && !empty($_POST['db_root_pass']) )
-    {
-      $conn_root = @mysql_connect($_POST['db_host'], $_POST['db_root_user'], $_POST['db_root_pass']);
-      if ( !$conn_root )
-      {
-        // Couldn't connect using either set of credentials. Bail out.
-        return false;
-      }
-      unset($db_user, $db_pass);
-      $db_user = mysql_real_escape_string($_POST['db_user']);
-      $db_pass = mysql_real_escape_string($_POST['db_pass']);
-      // Create the user account
-      $q = @mysql_query("GRANT ALL PRIVILEGES ON test.* TO '{$db_user}'@'localhost' IDENTIFIED BY '$db_pass' WITH GRANT OPTION;", $conn_root);
-      if ( !$q )
-      {
-        return false;
-      }
-      // Revoke privileges from test, we don't need them
-      $q = @mysql_query("REVOKE ALL PRIVILEGES ON test.* FROM '{$db_user}'@'localhost';", $conn_root);
-      if ( !$q )
-      {
-        return false;
-      }
-      if ( $_POST['db_host'] != 'localhost' && $_POST['db_host'] != '127.0.0.1' && $_POST['db_host'] != '::1' )
-      {
-        // If not connecting to a server running on localhost, allow from any host
-        // this is safer than trying to detect the hostname of the webserver, but less secure
-        $q = @mysql_query("GRANT ALL PRIVILEGES ON test.* TO '{$db_user}'@'%' IDENTIFIED BY '$db_pass' WITH GRANT OPTION;", $conn_root);
-        if ( !$q )
-        {
-          return false;
-        }
-        // Revoke privileges from test, we don't need them
-        $q = @mysql_query("REVOKE ALL PRIVILEGES ON test.* FROM '{$db_user}'@'%';", $conn_root);
-        if ( !$q )
-        {
-          return false;
-        }
-      }
-      mysql_close($conn_root);
-      $conn = @mysql_connect($_POST['db_host'], $_POST['db_user'], $_POST['db_pass']);
-      if ( !$conn )
-      {
-        // This should honestly never happen.
-        return false;
-      }
-    }
-  }
-  $q = @mysql_query("USE `$db_name`;", $conn);
-  if ( !$q )
-  {
-    // access denied to the database; try the whole root schenanegan again
-    if ( !empty($_POST['db_root_user']) && !empty($_POST['db_root_pass']) )
-    {
-      $conn_root = @mysql_connect($_POST['db_host'], $_POST['db_root_user'], $_POST['db_root_pass']);
-      if ( !$conn_root )
-      {
-        // Couldn't connect as root; bail out
-        return false;
-      }
-      // create the database, if it doesn't exist
-      $q = @mysql_query("CREATE DATABASE IF NOT EXISTS `$db_name`;", $conn_root);
-      if ( !$q )
-      {
-        // this really should never fail, so don't give any tolerance to it
-        return false;
-      }
-      unset($db_user, $db_pass);
-      $db_user = mysql_real_escape_string($_POST['db_user']);
-      $db_pass = mysql_real_escape_string($_POST['db_pass']);
-      // we're in with root rights; grant access to the database
-      $q = @mysql_query("GRANT ALL PRIVILEGES ON `$db_name`.* TO '{$db_user}'@'localhost';", $conn_root);
-      if ( !$q )
-      {
-        return false;
-      }
-      if ( $_POST['db_host'] != 'localhost' && $_POST['db_host'] != '127.0.0.1' && $_POST['db_host'] != '::1' )
-      {
-        $q = @mysql_query("GRANT ALL PRIVILEGES ON `$db_name`.* TO '{$db_user}'@'%';", $conn_root);
-        if ( !$q )
-        {
-          return false;
-        }
-      }
-      mysql_close($conn_root);
-      // grant tables have hopefully been flushed, kill and reconnect our regular user connection
-      mysql_close($conn);
-      $conn = @mysql_connect($_POST['db_host'], $_POST['db_user'], $_POST['db_pass']);
-      if ( !$conn )
-      {
-        return false;
-      }
-    }
-    else
-    {
-      return false;
-    }
-    // try again
-    $q = @mysql_query("USE `$db_name`;", $conn);
-    if ( !$q )
-    {
-      // really failed this time; bail out
-      return false;
-    }
-  }
-  // initialize DBAL
-  $db->connect(true, $_POST['db_host'], $db_user, $db_pass, $db_name);
-  // connected and database exists
-  return true;
-}
-
-function stg_pgsql_connect($act_get = false)
-{
-  global $db;
-  $db = new postgresql();
-  
-  static $conn = false;
-  if ( $act_get )
-    return $conn;
-  
-  $db_user =& $_POST['db_user'];
-  $db_pass =& $_POST['db_pass'];
-  $db_name =& $_POST['db_name'];
-  
-  if ( !preg_match('/^[a-z0-9_-]+$/', $db_name) )
-  {
-    $db_name = htmlspecialchars($db_name);
-    die("<p>SECURITY: malformed database name \"$db_name\"</p>");
-  }
-  
-  // First, try to connect using the normal credentials
-  $conn = @pg_connect("host={$_POST['db_host']} port=5432 user={$_POST['db_user']} password={$_POST['db_pass']}");
-  if ( !$conn )
-  {
-    // Connection failed. Do we have the root username and password?
-    if ( !empty($_POST['db_root_user']) && !empty($_POST['db_root_pass']) )
-    {
-      $conn_root = @pg_connect("host={$_POST['db_host']} port=5432 user={$_POST['db_root_user']} password={$_POST['db_root_pass']}");
-      if ( !$conn_root )
-      {
-        // Couldn't connect using either set of credentials. Bail out.
-        return false;
-      }
-      unset($db_user, $db_pass);
-      $db_user = pg_escape_string($_POST['db_user']);
-      $db_pass = pg_escape_string($_POST['db_pass']);
-      // Create the user account
-      $q = @pg_query("CREATE ROLE '$db_user' WITH NOSUPERUSER UNENCRYPTED PASSWORD '$db_pass';", $conn_root);
-      if ( !$q )
-      {
-        return false;
-      }
-      pg_close($conn_root);
-      $conn = @pg_connect("host={$_POST['db_host']} port=5432 user={$_POST['db_user']} password={$_POST['db_pass']}");
-      if ( !$conn )
-      {
-        // This should honestly never happen.
-        return false;
-      }
-    }
-  }
-  if ( !$q )
-  {
-    // access denied to the database; try the whole root schenanegan again
-    if ( !empty($_POST['db_root_user']) && !empty($_POST['db_root_pass']) )
-    {
-      $conn_root = @pg_connect("host={$_POST['db_host']} port=5432 user={$_POST['db_root_user']} password={$_POST['db_root_pass']}");
-      if ( !$conn_root )
-      {
-        // Couldn't connect as root; bail out
-        return false;
-      }
-      unset($db_user, $db_pass);
-      $db_user = pg_escape_string($_POST['db_user']);
-      $db_pass = pg_escape_string($_POST['db_pass']);
-      // create the database, if it doesn't exist
-      $q = @mysql_query("CREATE DATABASE $db_name WITH OWNER $db_user;", $conn_root);
-      if ( !$q )
-      {
-        // this really should never fail, so don't give any tolerance to it
-        return false;
-      }
-      // Setting the owner to $db_user should grant all the rights we need
-      pg_close($conn_root);
-      // grant tables have hopefully been flushed, kill and reconnect our regular user connection
-      pg_close($conn);
-      $conn = @pg_connect("host={$_POST['db_host']} port=5432 user={$_POST['db_user']} password={$_POST['db_pass']}");
-      if ( !$conn )
-      {
-        return false;
-      }
-    }
-    else
-    {
-      return false;
-    }
-    // try again
-    $q = @mysql_query("USE `$db_name`;", $conn);
-    if ( !$q )
-    {
-      // really failed this time; bail out
-      return false;
-    }
-  }
-  // initialize DBAL
-  $db->connect(true, $_POST['db_host'], $db_user, $db_pass, $db_name);
-  // connected and database exists
-  return true;
-}
-
-function stg_drop_tables()
-{
-  global $db;
-  // Our list of tables included in Enano
-  $tables = Array( 'categories', 'comments', 'config', 'logs', 'page_text', 'session_keys', 'pages', 'users', 'users_extra', 'themes', 'buddies', 'banlist', 'files', 'privmsgs', 'sidebar', 'hits', 'search_index', 'groups', 'group_members', 'acl', 'tags', 'page_groups', 'page_group_members' );
-  
-  // Drop each table individually; if it fails, it probably means we're trying to drop a
-  // table that didn't exist in the Enano version we're deleting the database for.
-  foreach ( $tables as $table )
-  {
-    // Remember that table_prefix is sanitized.
-    $table = "{$_POST['table_prefix']}$table";
-    $db->sql_query("DROP TABLE $table;", $conn);
-  }
-  return true;
-}
-
-function stg_decrypt_admin_pass($act_get = false)
-{
-  static $decrypted_pass = false;
-  if ( $act_get )
-    return $decrypted_pass;
-  
-  $aes = AESCrypt::singleton(AES_BITS, AES_BLOCKSIZE);
-  
-  if ( !empty($_POST['crypt_data']) )
-  {
-    require('config.new.php');
-    if ( !isset($cryptkey) )
-    {
-      return false;
-    }
-    define('_INSTRESUME_AES_KEYBACKUP', $key);
-    $key = hexdecode($cryptkey);
-    
-    $decrypted_pass = $aes->decrypt($_POST['crypt_data'], $key, ENC_HEX);
-    
-  }
-  else
-  {
-    $decrypted_pass = $_POST['admin_pass'];
-  }
-  if ( empty($decrypted_pass) )
-    return false;
-  return true;
-}
-
-function stg_generate_aes_key($act_get = false)
-{
-  static $key = false;
-  if ( $act_get )
-    return $key;
-  
-  $aes = AESCrypt::singleton(AES_BITS, AES_BLOCKSIZE);
-  $key = $aes->gen_readymade_key();
-  return true;
-}
-
-function stg_parse_schema($act_get = false)
-{
-  static $schema;
-  if ( $act_get )
-    return $schema;
-  
-  global $db;
-  
-  $admin_pass = stg_decrypt_admin_pass(true);
-  $key = stg_generate_aes_key(true);
-  $aes = AESCrypt::singleton(AES_BITS, AES_BLOCKSIZE);
-  $key = $aes->hextostring($key);
-  $admin_pass = $aes->encrypt($admin_pass, $key, ENC_HEX);
-  
-  $cacheonoff = is_writable(ENANO_ROOT.'/cache/') ? '1' : '0';
-  
-  $admin_user = $_POST['admin_user'];
-  $admin_user = str_replace('_', ' ', $admin_user);
-  $admin_user = $db->escape($admin_user);
-  
-  $schema = file_get_contents('schema.sql');
-  $schema = str_replace('{{SITE_NAME}}',    $db->escape($_POST['sitename']   ), $schema);
-  $schema = str_replace('{{SITE_DESC}}',    $db->escape($_POST['sitedesc']   ), $schema);
-  $schema = str_replace('{{COPYRIGHT}}',    $db->escape($_POST['copyright']  ), $schema);
-  $schema = str_replace('{{ADMIN_USER}}',   $admin_user                                    , $schema);
-  $schema = str_replace('{{ADMIN_PASS}}',   $db->escape($admin_pass          ), $schema);
-  $schema = str_replace('{{ADMIN_EMAIL}}',  $db->escape($_POST['admin_email']), $schema);
-  $schema = str_replace('{{ENABLE_CACHE}}', $db->escape($cacheonoff          ), $schema);
-  $schema = str_replace('{{REAL_NAME}}',    '',                                              $schema);
-  $schema = str_replace('{{TABLE_PREFIX}}', $_POST['table_prefix'],                          $schema);
-  $schema = str_replace('{{VERSION}}',      ENANO_VERSION,                                   $schema);
-  $schema = str_replace('{{ADMIN_EMBED_PHP}}', $_POST['admin_embed_php'],                    $schema);
-  // Not anymore!! :-D
-  // $schema = str_replace('{{BETA_VERSION}}', ENANO_BETA_VERSION,                              $schema);
-  
-  if(isset($_POST['wiki_mode']))
-  {
-    $schema = str_replace('{{WIKI_MODE}}', '1', $schema);
-  }
-  else
-  {
-    $schema = str_replace('{{WIKI_MODE}}', '0', $schema);
-  }
-  
-  // Build an array of queries      
-  $schema = explode("\n", $schema);
-  
-  foreach ( $schema as $i => $sql )
-  {
-    $query =& $schema[$i];
-    $t = trim($query);
-    if ( empty($t) || preg_match('/^(\#|--)/i', $t) )
-    {
-      unset($schema[$i]);
-      unset($query);
-    }
-  }
-  
-  $schema = array_values($schema);
-  $schema = implode("\n", $schema);
-  $schema = explode(";\n", $schema);
-  
-  foreach ( $schema as $i => $sql )
-  {
-    $query =& $schema[$i];
-    if ( substr($query, ( strlen($query) - 1 ), 1 ) != ';' )
-    {
-      $query .= ';';
-    }
-  }
-  
-  return true;
-}
-
-function stg_install($_unused, $already_run)
-{
-  // This one's pretty easy.
-  $conn = stg_mysql_connect(true);
-  if ( !is_resource($conn) )
-    return false;
-  $schema = stg_parse_schema(true);
-  if ( !is_array($schema) )
-    return false;
-  
-  // If we're resuming installation, the encryption key was regenerated.
-  // This means we'll have to update the encrypted password in the database.
-  if ( $already_run )
-  {
-    $admin_pass = stg_decrypt_admin_pass(true);
-    $key = stg_generate_aes_key(true);
-    $aes = AESCrypt::singleton(AES_BITS, AES_BLOCKSIZE);
-    $key = $aes->hextostring($key);
-    $admin_pass = $aes->encrypt($admin_pass, $key, ENC_HEX);
-    $admin_user = mysql_real_escape_string($_POST['admin_user']);
-    $admin_user = str_replace('_', ' ', $admin_user);
-    
-    $q = @mysql_query("UPDATE {$_POST['table_prefix']}users SET password='$admin_pass' WHERE username='$admin_user';");
-    if ( !$q )
-    {
-      echo '<p><tt>MySQL return: ' . mysql_error() . '</tt></p>';
-      return false;
-    }
-    
-    return true;
-  }
-  
-  // OK, do the loop, baby!!!
-  foreach($schema as $q)
-  {
-    $r = mysql_query($q, $conn);
-    if ( !$r )
-    {
-      echo '<p><tt>MySQL return: ' . mysql_error() . '</tt></p>';
-      return false;
-    }
-  }
-  
-  return true;
-}
-
-function stg_write_config()
-{
-  $privkey = stg_generate_aes_key(true);
-  
-  switch($_POST['urlscheme'])
-  {
-    case "ugly":
-    default:
-      $cp = scriptPath.'/index.php?title=';
-      break;
-    case "short":
-      $cp = scriptPath.'/index.php/';
-      break;
-    case "tiny":
-      $cp = scriptPath.'/';
-      break;
-  }
-  
-  if ( $_POST['urlscheme'] == 'tiny' )
-  {
-    $contents = '# Begin Enano rules
-RewriteEngine on
-RewriteCond %{REQUEST_FILENAME} !-d
-RewriteCond %{REQUEST_FILENAME} !-f
-RewriteRule ^(.+) '.scriptPath.'/index.php?title=$1 [L,QSA]
-RewriteRule \.(php|html|gif|jpg|png|css|js)$ - [L]
-# End Enano rules
-';
-    if ( file_exists('./.htaccess') )
-      $ht = fopen(ENANO_ROOT.'/.htaccess', 'a+');
-    else
-      $ht = fopen(ENANO_ROOT.'/.htaccess.new', 'w');
-    if ( !$ht )
-      return false;
-    fwrite($ht, $contents);
-    fclose($ht);
-  }
-
-  $config_file = '<?php
-/* Enano auto-generated configuration file - editing not recommended! */
-$dbhost   = \''.addslashes($_POST['db_host']).'\';
-$dbname   = \''.addslashes($_POST['db_name']).'\';
-$dbuser   = \''.addslashes($_POST['db_user']).'\';
-$dbpasswd = \''.addslashes($_POST['db_pass']).'\';
-if ( !defined(\'ENANO_CONSTANTS\') )
-{
-define(\'ENANO_CONSTANTS\', \'\');
-define(\'table_prefix\', \''.addslashes($_POST['table_prefix']).'\');
-define(\'scriptPath\', \''.scriptPath.'\');
-define(\'contentPath\', \''.$cp.'\');
-define(\'ENANO_INSTALLED\', \'true\');
-}
-$crypto_key = \''.$privkey.'\';
-?>';
-
-  $cf_handle = fopen(ENANO_ROOT.'/config.new.php', 'w');
-  if ( !$cf_handle )
-    return false;
-  fwrite($cf_handle, $config_file);
-  
-  fclose($cf_handle);
-  
-  return true;
-}
-
-function _stg_rename_config_revert()
-{
-  if ( file_exists('./config.php') )
-  {
-    @rename('./config.php', './config.new.php');
-  }
-  
-  $handle = @fopen('./config.php.new', 'w');
-  if ( !$handle )
-    return false;
-  $contents = '<?php $cryptkey = \'' . _INSTRESUME_AES_KEYBACKUP . '\'; ?>';
-  fwrite($handle, $contents);
-  fclose($handle);
-  return true;
-}
-
-function stg_build_index()
-{
-  global $db, $session, $paths, $template, $plugins; // Common objects;
-  if ( $paths->rebuild_search_index() )
-    return true;
-  return false;
-}
-
-function stg_rename_config()
-{
-  if ( !@rename('./config.new.php', './config.php') )
-  {
-    echo '<p>Can\'t rename config.php</p>';
-    _stg_rename_config_revert();
-    return false;
-  }
-  
-  if ( $_POST['urlscheme'] == 'tiny' && !file_exists('./.htaccess') )
-  {
-    if ( !@rename('./.htaccess.new', './.htaccess') )
-    {
-      echo '<p>Can\'t rename .htaccess</p>';
-      _stg_rename_config_revert();
-      return false;
-    }
-  }
-  return true;
-}
-
-function stg_start_api_success()
-{
-  return true;
-}
-
-function stg_start_api_failure()
-{
-  return false;
-}
-
-function stg_init_logs()
-{
-  global $db, $session, $paths, $template, $plugins; // Common objects
-  
-  $q = $db->sql_query('INSERT INTO ' . table_prefix . 'logs(log_type,action,time_id,date_string,author,page_text,edit_summary) VALUES(\'security\', \'install_enano\', ' . time() . ', \'' . date('d M Y h:i a') . '\', \'' . mysql_real_escape_string($_POST['admin_user']) . '\', \'' . mysql_real_escape_string(ENANO_VERSION) . '\', \'' . mysql_real_escape_string($_SERVER['REMOTE_ADDR']) . '\');');
-  if ( !$q )
-  {
-    echo '<p><tt>MySQL return: ' . mysql_error() . '</tt></p>';
-    return false;
-  }
-  
-  if ( !$session->get_permissions('clear_logs') )
-  {
-    echo '<p><tt>$session: denied clear_logs</tt></p>';
-    return false;
-  }
-  
-  PageUtils::flushlogs('Main_Page', 'Article');
-  
-  return true;
-}
-
-//die('Key size: ' . AES_BITS . '<br />Block size: ' . AES_BLOCKSIZE);
-
-if(!function_exists('wikiFormat'))
-{
-  function wikiFormat($message, $filter_links = true)
-  {
-    $wiki = & Text_Wiki::singleton('Mediawiki');
-    $wiki->setRenderConf('Xhtml', 'code', 'css_filename', 'codefilename');
-    $wiki->setRenderConf('Xhtml', 'wikilink', 'view_url', contentPath);
-    $result = $wiki->transform($message, 'Xhtml');
-    
-    // HTML fixes
-    $result = preg_replace('#<tr>([\s]*?)<\/tr>#is', '', $result);
-    $result = preg_replace('#<p>([\s]*?)<\/p>#is', '', $result);
-    $result = preg_replace('#<br />([\s]*?)<table#is', '<table', $result);
-    
-    return $result;
-  }
-}
-
-global $failed, $warned;
-
-$failed = false;
-$warned = false;
-
-function not($var)
-{
-  if($var)
-  {
-    return false;
-  } 
-  else
-  {
-    return true;
-  }
-}
-
-function run_test($code, $desc, $extended_desc, $warn = false)
-{
-  global $failed, $warned;
-  static $cv = true;
-  $cv = not($cv);
-  $val = eval($code);
-  if($val)
-  {
-    if($cv) $color='CCFFCC'; else $color='AAFFAA';
-    echo "<tr><td style='background-color: #$color; width: 500px; padding: 5px;'>$desc</td><td style='padding-left: 10px;'><img alt='Test passed' src='images/good.gif' /></td></tr>";
-  } elseif(!$val && $warn) {
-    if($cv) $color='FFFFCC'; else $color='FFFFAA';
-    echo "<tr><td style='background-color: #$color; width: 500px; padding: 5px;'>$desc<br /><b>$extended_desc</b></td><td style='padding-left: 10px;'><img alt='Test passed with warning' src='images/unknown.gif' /></td></tr>";
-    $warned = true;
-  } else {
-    if($cv) $color='FFCCCC'; else $color='FFAAAA';
-    echo "<tr><td style='background-color: #$color; width: 500px; padding: 5px;'>$desc<br /><b>$extended_desc</b></td><td style='padding-left: 10px;'><img alt='Test failed' src='images/bad.gif' /></td></tr>";
-    $failed = true;
-  }
-}
-function is_apache() { $r = strstr($_SERVER['SERVER_SOFTWARE'], 'Apache') ? true : false; return $r; }
-
-function show_license($fb = false)
-{
-  ?>
-  <div style="height: 500px; clip: rect(0px,auto,500px,auto); overflow: auto; padding: 10px; border: 1px dashed #456798; margin: 1em;">
-   <h2>GNU General Public License</h2>
-   
-   <h3>Declaration of license usage</h3>
-   <p>Enano is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.</p>
-   <p>This program is distributed in the hope that it will be useful, but <u>without any warranty</u>; without even the implied warranty of <u>merchantability</u> or <u>fitness for a particular purpose</u>. See the GNU General Public License (below) for more details.</p>
-   <p><b>By clicking the button below or otherwise continuing the installation, you indicate your acceptance of this license agreement.</b></p>
-   
-   <h3>Human-readable version</h3>
-   <p>Enano is distributed under certain licensing terms that we believe make it of the greatest possible use to the public. The license we distribute it under, the GNU General Public License, provides certain terms and conditions that, rather than limit your use of Enano, allow you to get the most out of it. If you would like to read the full text, it can be found below. Here is a human-readable version that we think is a little easier to understand.</p>
-   
-   <ul>
-     <li>You may to run Enano for any purpose.</li>
-     <li>You may study how Enano works and adapt it to your needs.</li>
-     <li>You may redistribute copies so you can help your neighbor.</li>
-     <li>You may improve Enano and release your improvements to the public, so that the whole community benefits.</li>
-   </ul>
-   
-   <p>You may exercise the freedoms specified here provided that you comply with the express conditions of this license. The principal conditions are:</p>
-   
-   <ul>
-     <li>You must conspicuously and appropriately publish on each copy distributed an appropriate copyright notice and disclaimer of warranty and keep intact all the notices that refer to this License and to the absence of any warranty; and give any other recipients of Enano a copy of the GNU General Public License along with Enano. Any translation of the GNU General Public License must be accompanied by the GNU General Public License.</li>
-     <li>If you modify your copy or copies of Enano or any portion of it, or develop a program based upon it, you may distribute the resulting work provided you do so under the GNU General Public License. Any translation of the GNU General Public License must be accompanied by the GNU General Public License.</li>
-     <li>If you copy or distribute Enano, you must accompany it with the complete corresponding machine-readable source code or with a written offer, valid for at least three years, to furnish the complete corresponding machine-readable source code.</li>
-   </ul>
-   
-   <p><b>Disclaimer</b>: The above text is not a license. It is simply a handy reference for understanding the Legal Code (the full license) &ndash; it is a human-readable expression of some of its key terms. Think of it as the user-friendly interface to the Legal Code beneath. The above text itself has no legal value, and its contents do not appear in the actual license.<br /><span style="color: #CCC">Text copied from the <a href="http://creativecommons.org/licenses/GPL/2.0/">Creative Commons GPL Deed page</a></span></p>
-   <?php
-   if ( defined('ENANO_BETA_VERSION') )
-   {
-     ?>
-     <h3>Notice for prerelease versions</h3>
-     <p>This version of Enano is designed only for testing and evaluation purposes. <b>It is not yet completely stable, and should not be used on production websites.</b> As with any Enano version, Dan Fuhry and the Enano team cannot be responsible for any damage, physical or otherwise, to any property as a result of the use of Enano. While security is a number one priority, sometimes things slip through.</p>
-     <?php
-   }
-   ?>
-   <h3>Lawyer-readable version</h3>
-   <?php echo wikiFormat(file_get_contents(ENANO_ROOT . '/GPL')); ?>
-   <?php
-   global $template;
-   if ( $fb )
-   {
-     echo '<p style="text-align: center;">Because I could never find the Create a Page button in PHP-Nuke.</p>';
-     echo '<p>' . str_replace('http://enanocms.org/', 'http://www.2robots.com/2003/10/15/web-portals-suck/', $template->fading_button) . '</p>';
-     echo '<p style="text-align: center;">It\'s not a portal, my friends.</p>';
-   }
-   ?>
- </div>
- <?php
-}
-
-require_once('includes/template.php');
-
-if(!isset($_GET['mode'])) $_GET['mode'] = 'welcome';
-switch($_GET['mode'])
-{
-  case 'mysql_test':
-    error_reporting(0);
-    $dbhost     = rawurldecode($_POST['host']);
-    $dbname     = rawurldecode($_POST['name']);
-    $dbuser     = rawurldecode($_POST['user']);
-    $dbpass     = rawurldecode($_POST['pass']);
-    $dbrootuser = rawurldecode($_POST['root_user']);
-    $dbrootpass = rawurldecode($_POST['root_pass']);
-    if($dbrootuser != '')
-    {
-      $conn = mysql_connect($dbhost, $dbrootuser, $dbrootpass);
-      if(!$conn)
-      {
-        $e = mysql_error();
-        if(strstr($e, "Lost connection"))
-          die('host'.$e);
-        else
-          die('root'.$e);
-      }
-      $rsp = 'good';
-      $q = mysql_query('USE `' . mysql_real_escape_string($dbname) . '`;', $conn);
-      if(!$q)
-      {
-        $e = mysql_error();
-        if(strstr($e, 'Unknown database'))
-        {
-          $rsp .= '_creating_db';
-        }
-      }
-      mysql_close($conn);
-      $conn = mysql_connect($dbhost, $dbuser, $dbpass);
-      if(!$conn)
-      {
-        $e = mysql_error();
-        if(strstr($e, "Lost connection"))
-          die('host'.$e);
-        else
-          $rsp .= '_creating_user';
-      }
-      mysql_close($conn);
-      die($rsp);
-    }
-    else
-    {
-      $conn = mysql_connect($dbhost, $dbuser, $dbpass);
-      if(!$conn)
-      {
-        $e = mysql_error();
-        if(strstr($e, "Lost connection"))
-          die('host'.$e);
-        else
-          die('auth'.$e);
-      }
-      $q = mysql_query('USE `' . mysql_real_escape_string($dbname) . '`;', $conn);
-      if(!$q)
-      {
-        $e = mysql_error();
-        if(strstr($e, 'Unknown database'))
-        {
-          die('name'.$e);
-        }
-        else
-        {
-          die('perm'.$e);
-        }
-      }
-    }
-    $v = mysql_get_server_info();
-    if(version_compare($v, '4.1.17', '<')) die('vers'.$v);
-    mysql_close($conn);
-    die('good');
-    break;
-  case 'pgsql_test':
-    error_reporting(0);
-    $dbhost     = rawurldecode($_POST['host']);
-    $dbname     = rawurldecode($_POST['name']);
-    $dbuser     = rawurldecode($_POST['user']);
-    $dbpass     = rawurldecode($_POST['pass']);
-    $dbrootuser = rawurldecode($_POST['root_user']);
-    $dbrootpass = rawurldecode($_POST['root_pass']);
-    if($dbrootuser != '')
-    {
-      $conn = @pg_connect("host=$dbhost port=5432 user=$dbuser password=$dbpass dbname=$dbname");
-      if(!$conn)
-      {
-        $e = pg_last_error();
-        if(strstr($e, "Lost connection"))
-          die('host'.$e);
-        else
-          die('root'.$e);
-      }
-      $rsp = 'good';
-      $q = mysql_query('USE `' . mysql_real_escape_string($dbname) . '`;', $conn);
-      if(!$q)
-      {
-        $e = mysql_error();
-        if(strstr($e, 'Unknown database'))
-        {
-          $rsp .= '_creating_db';
-        }
-      }
-      mysql_close($conn);
-      $conn = mysql_connect($dbhost, $dbuser, $dbpass);
-      if(!$conn)
-      {
-        $e = mysql_error();
-        if(strstr($e, "Lost connection"))
-          die('host'.$e);
-        else
-          $rsp .= '_creating_user';
-      }
-      mysql_close($conn);
-      die($rsp);
-    }
-    else
-    {
-      $conn = mysql_connect($dbhost, $dbuser, $dbpass);
-      if(!$conn)
-      {
-        $e = mysql_error();
-        if(strstr($e, "Lost connection"))
-          die('host'.$e);
-        else
-          die('auth'.$e);
-      }
-      $q = mysql_query('USE `' . mysql_real_escape_string($dbname) . '`;', $conn);
-      if(!$q)
-      {
-        $e = mysql_error();
-        if(strstr($e, 'Unknown database'))
-        {
-          die('name'.$e);
-        }
-        else
-        {
-          die('perm'.$e);
-        }
-      }
-    }
-    $v = mysql_get_server_info();
-    if(version_compare($v, '4.1.17', '<')) die('vers'.$v);
-    mysql_close($conn);
-    die('good');
-    break;  
-  case 'pophelp':
-    $topic = ( isset($_GET['topic']) ) ? $_GET['topic'] : 'invalid';
-    switch($topic)
-    {
-      case 'admin_embed_php':
-        $title = 'Allow administrators to embed PHP';
-        $content = '<p>This option allows you to control whether anything between the standard &lt;?php and ?&gt; tags will be treated as
-                        PHP code by Enano. If this option is enabled, and members of the Administrators group use these tags, Enano will
-                        execute that code when the page is loaded. There are obvious potential security implications here, which should
-                        be carefully considered before enabling this option.</p>
-                    <p>If you are the only administrator of this site, or if you have a high level of trust for those will be administering
-                       the site with you, you should enable this to allow extreme customization of pages.</p>
-                    <p>Leave this option off if you are at all concerned about security – if your account is compromised and PHP embedding
-                       is enabled, an attacker can run arbitrary code on your server! Enabling this will also allow administrators to
-                       embed Javascript and arbitrary HTML and CSS.</p>
-                    <p>If you don\'t have experience coding in PHP, you can safely disable this option. You may change this at any time
-                       using the ACL editor by selecting the Administrators group and This Entire Website under the scope selection. <!-- , or by
-                       using the "embedded PHP kill switch" in the administration panel. --></p>';
-        break;
-      case 'url_schemes':
-        $title = 'URL schemes';
-        $content = '<p>The URL scheme allows you to decide how the URLs to your Enano pages will look.</p>
-                    <p>The first option (Standard URLs) works on any web server. You should select it if your server doesn\'t run Apache, or
-                       if you are at all unsure of your server\'s configuration. With this scheme, URLs at your site will look like <tt>
-                       http://yoursite.com/path-to-enano/index.php/Main_Page</tt>.</p>
-                    <p>The second option, Small URLs, will be selected by default if Enano detects Apache. Small URLs are more friendly towards
-                       search engines, but they don\'t work on very many non-Apache servers, or if PHP is set up through CGI on your server. Many
-                       free and low-cost web hosts will configure PHP through CGI in order to keep your user account as the owner of any files that
-                       Enano generates. With this scheme, URLs at your site will look like <tt>http://yoursite.com/path-to-enano/index.php/Main_Page</tt>.
-                       </p>
-                    <p>The last option, Tiny URLs, is the most friendly URL scheme for search engines, because your URLs won\'t have any special characters
-                       at all in them. However, this only works if your webhost has configured Apache with support for mod_rewrite. Most of the time if your
-                       host supports this you will see a listing for it in their feature matrix. None of the popular Linux distributions (such as Ubuntu,
-                       Debian, Red Hat Enterprise Linux&trade;, Fedora, openSUSE&trade;, or CentOS) come with mod_rewrite enabled, so if you run a
-                       home-brew server, you should consult your distribution\'s documentation for enabling mod_rewrite before selecting this option.
-                       With this scheme, URLs at your site will look like <tt>http://yoursite.com/path-to-enano/Main_Page</tt>.</p>
-                       </p>';
-        break;
-      default:
-        $title = 'Invalid topic';
-        $content = 'Invalid help topic.';
-        break;
-    }
-    echo <<<EOF
-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
-<html>
-  <head>
-    <title>Enano installation quick help &bull; {$title}</title>
-    <meta http-equiv="Content-type" content="text/html; charset=utf-8" />
-    <style type="text/css">
-      body {
-        font-family: trebuchet ms, verdana, arial, helvetica, sans-serif;
-        font-size: 9pt;
-      }
-      h2          { border-bottom: 1px solid #90B0D0; margin-bottom: 0; }
-      h3          { font-size: 11pt; font-weight: bold; }
-      li          { list-style: url(../images/bullet.gif); }
-      p           { margin: 1.0em; }
-      blockquote  { background-color: #F4F4F4; border: 1px dotted #406080; margin: 1em; padding: 10px; max-height: 250px; overflow: auto; }
-      a           { color: #7090B0; }
-      a:hover     { color: #90B0D0; }
-    </style>
-  </head>
-  <body>
-    <h2>{$title}</h2>
-    {$content}
-    <p style="text-align: right;">
-      <a href="#" onclick="window.close(); return false;">Close window</a>
-    </p>
-  </body>
-</html>
-EOF;
-    exit;
-    break;
-  default:
-    break;
-}
-
-$template = new template_nodb();
-$template->load_theme('oxygen', 'bleu', false);
-
-$modestrings = Array(
-              'welcome' => 'Welcome',
-              'license' => 'License Agreement',
-              'sysreqs' => 'Server requirements',
-              'database' => 'Select database driver',
-              'database_mysql'=> 'Database information',
-              'database_pgsql'=> 'Database information',
-              'website' => 'Website configuration',
-              'login'   => 'Administration login',
-              'confirm' => 'Confirm installation',
-              'install' => 'Database installation',
-              'finish'  => 'Installation complete',
-              '_hiddenstages' => '...', // all stages below this line are hidden
-              'showlicense' => 'License Agreement'
-            );
-
-$sideinfo = '';
-$vars = $template->extract_vars('elements.tpl');
-$p = $template->makeParserText($vars['sidebar_button']);
-$hidden = false;
-foreach ( $modestrings as $id => $str )
-{
-  if ( $_GET['mode'] == $id )
-  {
-    $flags = 'style="font-weight: bold; text-decoration: underline;"';
-    $this_page = $str;
-  }
-  else
-  {
-    $flags = '';
-  }
-  if ( $id == '_hiddenstages' )
-    $hidden = true;
-  if ( !$hidden )
-  {
-    $p->assign_vars(Array(
-        'HREF' => '#',
-        'FLAGS' => $flags . ' onclick="return false;"',
-        'TEXT' => $str
-      ));
-    $sideinfo .= $p->run();
-  }
-}
-
-$template->init_vars();
-
-if(isset($_GET['mode']) && $_GET['mode'] == 'css')
-{
-  header('Content-type: text/css');
-  echo $template->get_css();
-  exit;
-}
-
-$template->header();
-if ( !isset($_GET['mode']) )
-{
-  $_GET['mode'] = 'welcome';
-}
-switch($_GET['mode'])
-{ 
-  default:
-  case 'welcome':
-    ?>
-    <div style="text-align: center; margin-top: 10px;">
-      <img alt="[ Enano CMS Project logo ]" src="images/enano-artwork/installer-greeting-blue.png" style="display: block; margin: 0 auto; padding-left: 100px;" />
-      <h2>Welcome to Enano</h2>
-      <h3>Version 1.0.3 &ndash; stable<br />
-      <span style="font-weight: normal;">also affectionately known as "coblynau" <tt>:)</tt></span></h3>
-      <?php
-      if ( file_exists('./_nightly.php') )
-      {
-        echo '<div class="warning-box" style="text-align: left; margin: 10px 0;"><b>You are about to install a NIGHTLY BUILD of Enano.</b><br />Nightly builds are NOT upgradeable and may contain serious flaws, security problems, or extraneous debugging information. Installing this version of Enano on a production site is NOT recommended.</div>';
-      }
-      ?>
-      <form action="install.php?mode=license" method="post">
-        <input type="submit" value="Start installation" />
-      </form>
-    </div>
-    <?php
-    break;
-  case "license":
-    ?>
-    <h3>Welcome to the Enano installer.</h3>
-     <p>Thank you for choosing Enano as your CMS. You've selected the finest in design, the strongest in security, and the latest in Web 2.0 toys. Trust us, you'll like it.</p>
-     <p>To get started, please read and accept the following license agreement. You've probably seen it before.</p>
-     <?php show_license(); ?>
-     <div class="pagenav">
-       <form action="install.php?mode=sysreqs" method="post">
-         <table border="0">
-         <tr>
-         <td><input type="submit" value="I agree to the license terms" /></td><td><p><span style="font-weight: bold;">Before clicking continue:</span><br />&bull; Ensure that you agree with the terms of the license<br />&bull; Have your database host, name, username, and password available</p></td>
-         </tr>
-         </table>
-       </form>
-     </div>
-    <?php
-    break;
-  case "sysreqs":
-    error_reporting(E_ALL);
-    ?>
-    <h3>Checking your server</h3>
-     <p>Enano has several requirements that must be met before it can be installed. If all is good then note any warnings and click Continue below.</p>
-    <table border="0" cellspacing="0" cellpadding="0">
-    <?php
-    run_test('return version_compare(\'4.3.0\', PHP_VERSION, \'<\');', 'PHP Version >=4.3.0', 'It seems that the version of PHP that your server is running is too old to support Enano properly. If this is your server, please upgrade to the most recent version of PHP, remembering to use the --with-mysql configure option if you compile it yourself. If this is not your server, please contact your webhost and ask them if it would be possible to upgrade PHP. If this is not possible, you will need to switch to a different webhost in order to use Enano.');
-    run_test('return version_compare(\'5.2.0\', PHP_VERSION, \'<\');', 'PHP 5.2.0 or later', 'Your server does not have support for PHP 5.2.0. While you may continue installing Enano, please be warned that as of December 31, 2007, all support for Enano on PHP 4 servers is discontinued. If you have at least PHP 5.0.0, support will still be available, but there are many security problems in PHP versions under 5.2.0 that Enano cannot effectively prevent.', true);
-    run_test('return function_exists(\'mysql_connect\');', 'MySQL extension for PHP', 'It seems that your PHP installation does not have the MySQL extension enabled. The MySQL database driver will be unavailable. In many cases this is OK if you have another supported database type available. If this is your own server, you may need to just enable the "libmysql.so" extension in php.ini. If you do not have the MySQL extension installed, you will need to either use your distribution\'s package manager to install it, or you will have to compile PHP from source. If you compile PHP from source, please remember to use the "--with-mysql" configure option, and you will have to have the MySQL development files installed (they usually are). If this is not your server, please contact your hosting company and ask them to install the PHP MySQL extension.', true);
-    run_test('return function_exists(\'pg_connect\');', 'PostgreSQL extension for PHP', 'It seems that your PHP installation does not have the PostgreSQL extension enabled. Because of this, you won\'t be able to use the PostgreSQL database driver. This is OK in the majority of cases. If you want to use PostgreSQL support, you\'ll need to either compile the PHP extension for Postgres or install the extension with your distribution\'s package manager. Windows administrators will need enable php_pgsql.dll in their php.ini.', true);
-    run_test('return @ini_get(\'file_uploads\');', 'File upload support', 'It seems that your server does not support uploading files. Enano *requires* this functionality in order to work properly. Please ask your server administrator to set the "file_uploads" option in php.ini to "On".');
-    run_test('return is_apache();', 'Apache HTTP Server', 'Apparently your server is running a web server other than Apache. Enano will work nontheless, but there are some known bugs with non-Apache servers, and the "fancy" URLs will not work properly. The "Standard URLs" option will be set on the website configuration page, only change it if you are absolutely certain that your server is running Apache.', true);
-    //run_test('return function_exists(\'finfo_file\');', 'Fileinfo PECL extension', 'The MIME magic PHP extension is used to determine the type of a file by looking for a certain "magic" string of characters inside it. This functionality is used by Enano to more effectively prevent malicious file uploads. The MIME magic option will be disabled by default.', true);
-    run_test('return is_writable(ENANO_ROOT.\'/config.new.php\');', 'Configuration file writable', 'It looks like the configuration file, config.new.php, is not writable. Enano needs to be able to write to this file in order to install.<br /><br /><b>If you are installing Enano on a SourceForge web site:</b><br />SourceForge mounts the web partitions read-only now, so you will need to use the project shell service to symlink config.php to a file in the /tmp/persistent directory.');
-    run_test('return file_exists(\'/usr/bin/convert\');', 'ImageMagick support', 'Enano uses ImageMagick to scale images into thumbnails. Because ImageMagick was not found on your server, Enano will use the width= and height= attributes on the &lt;img&gt; tag to scale images. This can cause somewhat of a performance increase, but bandwidth usage will be higher, especially if you use high-resolution images on your site.<br /><br />If you are sure that you have ImageMagick, you can set the location of the "convert" program using the administration panel after installation is complete.', true);
-    run_test('return is_writable(ENANO_ROOT.\'/cache/\');', 'Cache directory writable', 'Apparently the cache/ directory is not writable. Enano will still work, but you will not be able to cache thumbnails, meaning the server will need to re-render them each time they are requested. In some cases, this can cause a significant slowdown.', true);
-    run_test('return is_writable(ENANO_ROOT.\'/files/\');', 'File uploads directory writable', 'It seems that the directory where uploaded files are stored (' . ENANO_ROOT . '/files) cannot be written by the server. Enano will still function, but file uploads will not function, and will be disabled by default.', true);
-    if ( !function_exists('mysql_connect') && !function_exists('pg_connect') )
-    {
-      run_test('return false;', 'No database drivers are available.', 'You need to have at least one database driver working to install Enano. See the warnings on MySQL and PostgreSQL above for more information on installing these database drivers.', false);
-    }
-    echo '</table>';
-    if(!$failed)
-    {
-      ?>
-      
-      <div class="pagenav">
-      <?php
-      if($warned) {
-        echo '<table border="0" cellspacing="0" cellpadding="0">';
-        run_test('return false;', 'Some of the features of Enano have been turned off to accommodate your server.', 'Enano has detected that some of the features or configuration settings on your server are not optimal for the best behavior and/or performance for Enano. As a result, Enano has disabled these features as a precaution to prevent errors and potential security issues.', true);
-        echo '</table>';
-      } else {
-        echo '<table border="0" cellspacing="0" cellpadding="0">';
-        run_test('return true;', '<b>Your server meets all the requirements for running Enano.</b><br />Click the button below to continue the installation.', 'You should never see this text. Congratulations for being an Enano hacker!');
-        echo '</table>';
-      }
-      ?>
-       <form action="install.php?mode=database" method="post">
-         <table border="0">
-         <tr>
-         <td><input type="submit" value="Continue" /></td><td><p><span style="font-weight: bold;">Before clicking continue:</span><br />&bull; Ensure that you are satisfied with any scalebacks that may have been made to accomodate your server configuration<br />&bull; Have your database host, name, username, and password available</p></td>
-         </tr>
-         </table>
-       </form>
-     </div>
-     <?php
-    } else {
-      if($failed) {
-        echo '<div class="pagenav"><table border="0" cellspacing="0" cellpadding="0">';
-        run_test('return false;', 'Your server does not meet the requirements for Enano to run.', 'As a precaution, Enano will not install until the above requirements have been met. Contact your server administrator or hosting company and convince them to upgrade. Good luck.');
-        echo '</table></div>';
-      }
-    }
-    ?>
-    <?php
-    break;
-  case "database":
-    ?>
-    <script type="text/javascript">
-      function ajaxGet(uri, f) {
-        if (window.XMLHttpRequest) {
-          ajax = new XMLHttpRequest();
-        } else {
-          if (window.ActiveXObject) {           
-            ajax = new ActiveXObject("Microsoft.XMLHTTP");
-          } else {
-            alert('Enano client-side runtime error: No AJAX support, unable to continue');
-            return;
-          }
-        }
-        ajax.onreadystatechange = f;
-        ajax.open('GET', uri, true);
-        ajax.send(null);
-      }
-      
-      function ajaxPost(uri, parms, f) {
-        if (window.XMLHttpRequest) {
-          ajax = new XMLHttpRequest();
-        } else {
-          if (window.ActiveXObject) {           
-            ajax = new ActiveXObject("Microsoft.XMLHTTP");
-          } else {
-            alert('Enano client-side runtime error: No AJAX support, unable to continue');
-            return;
-          }
-        }
-        ajax.onreadystatechange = f;
-        ajax.open('POST', uri, true);
-        ajax.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
-        ajax.setRequestHeader("Content-length", parms.length);
-        ajax.setRequestHeader("Connection", "close");
-        ajax.send(parms);
-      }
-      function ajaxTestConnection()
-      {
-        v = verify();
-        if(!v)
-        {
-          alert('One or more of the form fields is incorrect. Please correct any information in the form that has an "X" next to it.');
-          return false;
-        }
-        var frm = document.forms.dbinfo;
-        db_host      = escape(frm.db_host.value.replace('+', '%2B'));
-        db_name      = escape(frm.db_name.value.replace('+', '%2B'));
-        db_user      = escape(frm.db_user.value.replace('+', '%2B'));
-        db_pass      = escape(frm.db_pass.value.replace('+', '%2B'));
-        db_root_user = escape(frm.db_root_user.value.replace('+', '%2B'));
-        db_root_pass = escape(frm.db_root_pass.value.replace('+', '%2B'));
-        
-        parms = 'host='+db_host+'&name='+db_name+'&user='+db_user+'&pass='+db_pass+'&root_user='+db_root_user+'&root_pass='+db_root_pass;
-        ajaxPost('<?php echo scriptPath; ?>/install.php?mode=mysql_test', parms, function() {
-            if(ajax.readyState==4)
-            {
-              s = ajax.responseText.substr(0, 4);
-              t = ajax.responseText.substr(4, ajax.responseText.length);
-              if(s.substr(0, 4)=='good')
-              {
-                document.getElementById('s_db_host').src='images/good.gif';
-                document.getElementById('s_db_name').src='images/good.gif';
-                document.getElementById('s_db_auth').src='images/good.gif';
-                document.getElementById('s_db_root').src='images/good.gif';
-                if(t.match(/_creating_db/)) document.getElementById('e_db_name').innerHTML = '<b>Warning:<\/b> The database you specified does not exist. It will be created during installation.';
-                if(t.match(/_creating_user/)) document.getElementById('e_db_auth').innerHTML = '<b>Warning:<\/b> The specified regular user does not exist or the password is incorrect. The user will be created during installation. If the user already exists, the password will be reset.';
-                document.getElementById('s_mysql_version').src='images/good.gif';
-                document.getElementById('e_mysql_version').innerHTML = 'Your version of MySQL meets Enano requirements.';
-              }
-              else
-              {
-                switch(s)
-                {
-                case 'host':
-                  document.getElementById('s_db_host').src='images/bad.gif';
-                  document.getElementById('s_db_name').src='images/unknown.gif';
-                  document.getElementById('s_db_auth').src='images/unknown.gif';
-                  document.getElementById('s_db_root').src='images/unknown.gif';
-                  document.getElementById('e_db_host').innerHTML = '<b>Error:<\/b> The database server "'+document.forms.dbinfo.db_host.value+'" couldn\'t be contacted.<br \/>'+t;
-                  document.getElementById('e_mysql_version').innerHTML = 'The MySQL version that your server is running could not be determined.';
-                  break;
-                case 'auth':
-                  document.getElementById('s_db_host').src='images/good.gif';
-                  document.getElementById('s_db_name').src='images/unknown.gif';
-                  document.getElementById('s_db_auth').src='images/bad.gif';
-                  document.getElementById('s_db_root').src='images/unknown.gif';
-                  document.getElementById('e_db_auth').innerHTML = '<b>Error:<\/b> Access to MySQL under the specified credentials was denied.<br \/>'+t;
-                  document.getElementById('e_mysql_version').innerHTML = 'The MySQL version that your server is running could not be determined.';
-                  break;
-                case 'perm':
-                  document.getElementById('s_db_host').src='images/good.gif';
-                  document.getElementById('s_db_name').src='images/bad.gif';
-                  document.getElementById('s_db_auth').src='images/good.gif';
-                  document.getElementById('s_db_root').src='images/unknown.gif';
-                  document.getElementById('e_db_name').innerHTML = '<b>Error:<\/b> Access to the specified database using those login credentials was denied.<br \/>'+t;
-                  document.getElementById('e_mysql_version').innerHTML = 'The MySQL version that your server is running could not be determined.';
-                  break;
-                case 'name':
-                  document.getElementById('s_db_host').src='images/good.gif';
-                  document.getElementById('s_db_name').src='images/bad.gif';
-                  document.getElementById('s_db_auth').src='images/good.gif';
-                  document.getElementById('s_db_root').src='images/unknown.gif';
-                  document.getElementById('e_db_name').innerHTML = '<b>Error:<\/b> The specified database does not exist<br \/>'+t;
-                  document.getElementById('e_mysql_version').innerHTML = 'The MySQL version that your server is running could not be determined.';
-                  break;
-                case 'root':
-                  document.getElementById('s_db_host').src='images/good.gif';
-                  document.getElementById('s_db_name').src='images/unknown.gif';
-                  document.getElementById('s_db_auth').src='images/unknown.gif';
-                  document.getElementById('s_db_root').src='images/bad.gif';
-                  document.getElementById('e_db_root').innerHTML = '<b>Error:<\/b> Access to MySQL under the specified credentials was denied.<br \/>'+t;
-                  document.getElementById('e_mysql_version').innerHTML = 'The MySQL version that your server is running could not be determined.';
-                  break;
-                case 'vers':
-                  document.getElementById('s_db_host').src='images/good.gif';
-                  document.getElementById('s_db_name').src='images/good.gif';
-                  document.getElementById('s_db_auth').src='images/good.gif';
-                  document.getElementById('s_db_root').src='images/good.gif';
-                  if(t.match(/_creating_db/)) document.getElementById('e_db_name').innerHTML = '<b>Warning:<\/b> The database you specified does not exist. It will be created during installation.';
-                  if(t.match(/_creating_user/)) document.getElementById('e_db_auth').innerHTML = '<b>Warning:<\/b> The specified regular user does not exist or the password is incorrect. The user will be created during installation. If the user already exists, the password will be reset.';
-                  
-                  document.getElementById('e_mysql_version').innerHTML = '<b>Error:<\/b> Your version of MySQL ('+t+') is older than 4.1.17. Enano will still work, but there is a known bug with the comment system and MySQL 4.1.11 that involves some comments not being displayed, due to an issue with the PHP function mysql_fetch_row().';
-                  document.getElementById('s_mysql_version').src='images/bad.gif';
-                default:
-                  alert(t);
-                  break;
-                }
-              }
-            }
-          });
-      }
-      function verify()
-      {
-        document.getElementById('e_db_host').innerHTML = '';
-        document.getElementById('e_db_auth').innerHTML = '';
-        document.getElementById('e_db_name').innerHTML = '';
-        document.getElementById('e_db_root').innerHTML = '';
-        var frm = document.forms.dbinfo;
-        ret = true;
-        if(frm.db_host.value != '')
-        {
-          document.getElementById('s_db_host').src='images/unknown.gif';
-        }
-        else
-        {
-          document.getElementById('s_db_host').src='images/bad.gif';
-          ret = false;
-        }
-        if(frm.db_name.value.match(/^([a-z0-9_-]+)$/g))
-        {
-          document.getElementById('s_db_name').src='images/unknown.gif';
-        }
-        else
-        {
-          document.getElementById('s_db_name').src='images/bad.gif';
-          ret = false;
-        }
-        if(frm.db_user.value != '')
-        {
-          document.getElementById('s_db_auth').src='images/unknown.gif';
-        }
-        else
-        {
-          document.getElementById('s_db_auth').src='images/bad.gif';
-          ret = false;
-        }
-        if(frm.table_prefix.value.match(/^([a-z0-9_]*)$/g))
-        {
-          document.getElementById('s_table_prefix').src='images/good.gif';
-        }
-        else
-        {
-          document.getElementById('s_table_prefix').src='images/bad.gif';
-          ret = false;
-        }
-        if(frm.db_root_user.value == '')
-        {
-          document.getElementById('s_db_root').src='images/good.gif';
-        }
-        else if(frm.db_root_user.value != '' && frm.db_root_pass.value == '')
-        {
-          document.getElementById('s_db_root').src='images/bad.gif';
-          ret = false;
-        }
-        else
-        {
-          document.getElementById('s_db_root').src='images/unknown.gif';
-        }
-        if(ret) frm._cont.disabled = false;
-        else    frm._cont.disabled = true;
-        return ret;
-      }
-      window.onload = verify;
-    </script>
-    <p>Now we need some information that will allow Enano to contact your database server. Enano uses MySQL as a data storage backend,
-       and we need to have access to a MySQL server in order to continue.</p>
-    <p>If you do not have access to a MySQL server, and you are using your own server, you can download MySQL for free from
-       <a href="http://www.mysql.com/">MySQL.com</a>. <b>Please note that, like Enano, MySQL is licensed under the GNU GPL.</b>
-       If you need to modify MySQL and then distribute your modifications, you must either distribute them under the terms of the GPL
-       or purchase a proprietary license.</p>
-    <?php
-    if ( @file_exists('/etc/enano-is-virt-appliance') )
-    {
-      echo '<p><b>MySQL login information for this virtual appliance:</b><br /><br />Database hostname: localhost<br />Database login: username "enano", password: "clurichaun" (without quotes)<br />Database name: enano_www1</p>';
-    }
-    ?>
-    <form name="dbinfo" action="install.php?mode=website" method="post">
-      <table border="0">
-        <tr><td colspan="3" style="text-align: center"><h3>Database information</h3></td></tr>
-        <tr><td><b>Database hostname</b><br />This is the hostname (or sometimes the IP address) of your MySQL server. In many cases, this is "localhost".<br /><span style="color: #993300" id="e_db_host"></span></td><td><input onkeyup="verify();" name="db_host" size="30" type="text" /></td><td><img id="s_db_host" alt="Good/bad icon" src="images/bad.gif" /></td></tr>
-        <tr><td><b>Database name</b><br />The name of the actual database. If you don't already have a database, you can create one here, if you have the username and password of a MySQL user with administrative rights.<br /><span style="color: #993300" id="e_db_name"></span></td><td><input onkeyup="verify();" name="db_name" size="30" type="text" /></td><td><img id="s_db_name" alt="Good/bad icon" src="images/bad.gif" /></td></tr>
-        <tr><td rowspan="2"><b>Database login</b><br />These fields should be the username and password of a user with "select", "insert", "update", "delete", "create table", and "replace" privileges for your database.<br /><span style="color: #993300" id="e_db_auth"></span></td><td><input onkeyup="verify();" name="db_user" size="30" type="text" /></td><td rowspan="2"><img id="s_db_auth" alt="Good/bad icon" src="images/bad.gif" /></td></tr>
-        <tr><td><input name="db_pass" size="30" type="password" /></td></tr>
-        <tr><td colspan="3" style="text-align: center"><h3>Optional information</h3></td></tr>
-        <tr><td><b>Table prefix</b><br />The value that you enter here will be added to the beginning of the name of each Enano table. You may use lowercase letters (a-z), numbers (0-9), and underscores (_).</td><td><input onkeyup="verify();" name="table_prefix" size="30" type="text" /></td><td><img id="s_table_prefix" alt="Good/bad icon" src="images/good.gif" /></td></tr>
-        <tr><td rowspan="2"><b>Database administrative login</b><br />If the MySQL database or username that you entered above does not exist yet, you can create them here, assuming that you have the login information for an administrative user (such as root). Leave these fields blank unless you need to use them.<br /><span style="color: #993300" id="e_db_root"></span></td><td><input onkeyup="verify();" name="db_root_user" size="30" type="text" /></td><td rowspan="2"><img id="s_db_root" alt="Good/bad icon" src="images/good.gif" /></td></tr>
-        <tr><td><input onkeyup="verify();" name="db_root_pass" size="30" type="password" /></td></tr>
-        <tr><td><b>MySQL version</b></td><td id="e_mysql_version">MySQL version information will be checked when you click "Test Connection".</td><td><img id="s_mysql_version" alt="Good/bad icon" src="images/unknown.gif" /></td></tr>
-        <tr><td><b>Delete existing tables?</b><br />If this option is checked, all the tables that will be used by Enano will be dropped (deleted) before the schema is executed. Do NOT use this option unless specifically instructed to.</td><td><input type="checkbox" name="drop_tables" id="dtcheck" />  <label for="dtcheck">Drop existing tables</label></td></tr>
-        <tr><td colspan="3" style="text-align: center"><input type="button" value="Test connection" onclick="ajaxTestConnection();" /></td></tr>
-      </table>
-      <div class="pagenav">
-       <table border="0">
-       <tr>
-       <td><input type="submit" value="Continue" onclick="return verify();" name="_cont" /></td><td><p><span style="font-weight: bold;">Before clicking continue:</span><br />&bull; Check your MySQL connection using the "Test Connection" button.<br />&bull; Be aware that your database information will be transmitted unencrypted several times.</p></td>
-       </tr>
-       </table>
-     </div>
-    </form>
-    <?php
-    break;
-  case "website":
-    if(!isset($_POST['_cont'])) {
-      echo 'No POST data signature found. Please <a href="install.php?mode=sysreqs">restart the installation</a>.';
-      $template->footer();
-      exit;
-    }
-    unset($_POST['_cont']);
-    ?>
-    <script type="text/javascript">
-      function verify()
-      {
-        var frm = document.forms.siteinfo;
-        ret = true;
-        if(frm.sitename.value.match(/^(.+)$/g) && frm.sitename.value != 'Enano')
-        {
-          document.getElementById('s_name').src='images/good.gif';
-        }
-        else
-        {
-          document.getElementById('s_name').src='images/bad.gif';
-          ret = false;
-        }
-        if(frm.sitedesc.value.match(/^(.+)$/g))
-        {
-          document.getElementById('s_desc').src='images/good.gif';
-        }
-        else
-        {
-          document.getElementById('s_desc').src='images/bad.gif';
-          ret = false;
-        }
-        if(frm.copyright.value.match(/^(.+)$/g))
-        {
-          document.getElementById('s_copyright').src='images/good.gif';
-        }
-        else
-        {
-          document.getElementById('s_copyright').src='images/bad.gif';
-          ret = false;
-        }
-        if(ret) frm._cont.disabled = false;
-        else    frm._cont.disabled = true;
-        return ret;
-      }
-      window.onload = verify;
-    </script>
-    <form name="siteinfo" action="install.php?mode=login" method="post">
-      <?php
-        $k = array_keys($_POST);
-        for($i=0;$i<sizeof($_POST);$i++) {
-          echo '<input type="hidden" name="'.htmlspecialchars($k[$i]).'" value="'.htmlspecialchars($_POST[$k[$i]]).'" />'."\n";
-        }
-      ?>
-      <p>The next step is to enter some information about your website. You can always change this information later, using the administration panel.</p>
-      <table border="0">
-        <tr><td><b>Website name</b><br />The display name of your website. Allowed characters are uppercase and lowercase letters, numerals, and spaces. This must not be blank or "Enano".</td><td><input onkeyup="verify();" name="sitename" type="text" size="30" /></td><td><img id="s_name" alt="Good/bad icon" src="images/bad.gif" /></td></tr>
-        <tr><td><b>Website description</b><br />This text will be shown below the name of your website.</td><td><input onkeyup="verify();" name="sitedesc" type="text" size="30" /></td><td><img id="s_desc" alt="Good/bad icon" src="images/bad.gif" /></td></tr>
-        <tr><td><b>Copyright info</b><br />This should be a one-line legal notice that will appear at the bottom of all your pages.</td><td><input onkeyup="verify();" name="copyright" type="text" size="30" /></td><td><img id="s_copyright" alt="Good/bad icon" src="images/bad.gif" /></td></tr>
-        <tr><td><b>Wiki mode</b><br />This feature allows people to create and edit pages on your site. Enano keeps a history of all page modifications, and you can protect pages to prevent editing.</td><td><input name="wiki_mode" type="checkbox" id="wmcheck" />  <label for="wmcheck">Yes, make my website a wiki.</label></td><td></td></tr>
-        <tr><td><b>URL scheme</b><br />Choose how the page URLs will look. Depending on your server configuration, you may need to select the first option. If you don't know, select the first option, and you can always change it later.</td><td colspan="2"><input type="radio" <?php if(!is_apache()) echo 'checked="checked" '; ?>name="urlscheme" value="ugly" id="ugly">  <label for="ugly">Standard URLs - compatible with any web server (www.example.com/index.php?title=Page_name)</label><br /><input type="radio" <?php if(is_apache()) echo 'checked="checked" '; ?>name="urlscheme" value="short" id="short">  <label for="short">Short URLs - requires Apache with a PHP module (www.example.com/index.php/Page_name)</label><br /><input type="radio" name="urlscheme" value="tiny" id="petite">  <label for="petite">Tiny URLs - requires Apache on Linux/Unix/BSD with PHP module and mod_rewrite enabled (www.example.com/Page_name)</label><br /><small><a href="install.php?mode=pophelp&amp;topic=url_schemes" onclick="window.open(this.href, 'pophelpwin', 'width=550,height=400,status=no,toolbars=no,toolbar=no,address=no,scroll=yes'); return false;">Which URL scheme should I choose?</a></small></td></tr>
-      </table>
-      <div class="pagenav">
-       <table border="0">
-       <tr>
-       <td><input type="submit" value="Continue" onclick="return verify();" name="_cont" /></td><td><p><span style="font-weight: bold;">Before clicking continue:</span><br />&bull; Verify that your site information is correct. Again, all of the above settings can be changed from the administration panel.</p></td>
-       </tr>
-       </table>
-     </div>
-    </form>
-    <?php
-    break;
-  case "login":
-    if(!isset($_POST['_cont'])) {
-      echo 'No POST data signature found. Please <a href="install.php?mode=sysreqs">restart the installation</a>.';
-      $template->footer();
-      exit;
-    }
-    unset($_POST['_cont']);
-    require('config.new.php');
-    $aes = AESCrypt::singleton(AES_BITS, AES_BLOCKSIZE);
-    if ( isset($crypto_key) )
-    {
-      $cryptkey = $crypto_key;
-    }
-    if(!isset($cryptkey) || ( isset($cryptkey) && strlen($cryptkey) != AES_BITS / 4) )
-    {
-      $cryptkey = $aes->gen_readymade_key();
-      $handle = @fopen(ENANO_ROOT.'/config.new.php', 'w');
-      if(!$handle)
-      {
-        echo '<p>ERROR: Cannot open config.php for writing - exiting!</p>';
-        $template->footer();
-        exit;
-      }
-      fwrite($handle, '<?php $cryptkey = \''.$cryptkey.'\'; ?>');
-      fclose($handle);
-    }
-    // Sorry for the ugly hack, but this f***s up jEdit badly.
-    echo '
-    <script type="text/javascript">
-      function verify()
-      {
-        var frm = document.forms.login;
-        ret = true;
-        if ( frm.admin_user.value.match(/^([^<>&\?\'"%\/]+)$/) && !frm.admin_user.value.match(/^(?:(?:\\d{1,2}|1\\d\\d|2[0-4]\\d|25[0-5])\\.){3}(?:\\d{1,2}|1\\d\\d|2[0-4]\\d|25[0-5])$/) && frm.admin_user.value.toLowerCase() != \'anonymous\' )
-        {
-          document.getElementById(\'s_user\').src = \'images/good.gif\';
-        }
-        else
-        {
-          document.getElementById(\'s_user\').src = \'images/bad.gif\';
-          ret = false;
-        }
-        if(frm.admin_pass.value.length >= 6 && frm.admin_pass.value == frm.admin_pass_confirm.value)
-        {
-          document.getElementById(\'s_password\').src = \'images/good.gif\';
-        }
-        else
-        {
-          document.getElementById(\'s_password\').src = \'images/bad.gif\';
-          ret = false;
-        }
-        if(frm.admin_email.value.match(/^(?:[\\w\\d_-]+\\.?)+@(?:(?:[\\w\\d-]\\-?)+\\.)+\\w{2,4}$/))
-        {
-          document.getElementById(\'s_email\').src = \'images/good.gif\';
-        }
-        else
-        {
-          document.getElementById(\'s_email\').src = \'images/bad.gif\';
-          ret = false;
-        }
-        if(ret) frm._cont.disabled = false;
-        else    frm._cont.disabled = true;
-        return ret;
-      }
-      window.onload = verify;
-      
-      function cryptdata() 
-      {
-        if(!verify()) return false;
-      }
-    </script>
-    ';
-    ?>
-    <form name="login" action="install.php?mode=confirm" method="post" onsubmit="runEncryption();">
-      <?php
-        $k = array_keys($_POST);
-        for($i=0;$i<sizeof($_POST);$i++) {
-          echo '<input type="hidden" name="'.htmlspecialchars($k[$i]).'" value="'.htmlspecialchars($_POST[$k[$i]]).'" />'."\n";
-        }
-      ?>
-      <p>Next, enter your desired username and password. The account you create here will be used to administer your site.</p>
-      <table border="0">
-        <tr><td><b>Administration username</b><br /><small>The administration username you will use to log into your site.<br />This cannot be "anonymous" or in the form of an IP address.</small></td><td><input onkeyup="verify();" name="admin_user" type="text" size="30" /></td><td><img id="s_user" alt="Good/bad icon" src="images/bad.gif" /></td></tr>
-        <tr><td>Administration password:</td><td><input onkeyup="verify();" name="admin_pass" type="password" size="30" /></td><td rowspan="2"><img id="s_password" alt="Good/bad icon" src="images/bad.gif" /></td></tr>
-        <tr><td>Enter it again to confirm:</td><td><input onkeyup="verify();" name="admin_pass_confirm" type="password" size="30" /></td></tr>
-        <tr><td>Your e-mail address:</td><td><input onkeyup="verify();" name="admin_email" type="text" size="30" /></td><td><img id="s_email" alt="Good/bad icon" src="images/bad.gif" /></td></tr>
-        <tr>
-          <td>
-            Allow administrators to embed PHP code into pages:<br />
-            <small><span style="color: #D84308">Do not under any circumstances enable this option without reading these
-                   <a href="install.php?mode=pophelp&amp;topic=admin_embed_php"
-                      onclick="window.open(this.href, 'pophelpwin', 'width=550,height=400,status=no,toolbars=no,toolbar=no,address=no,scroll=yes'); return false;"
-                      style="color: #D84308; text-decoration: underline;">important security implications</a>.
-            </span></small>
-          </td>
-          <td>
-            <label><input type="radio" name="admin_embed_php" value="2" checked="checked" /> Disabled</label>&nbsp;&nbsp;
-            <label><input type="radio" name="admin_embed_php" value="4" /> Enabled</label>
-          </td>
-          <td></td>
-        </tr>
-        <tr><td colspan="3">If your browser supports Javascript, the password you enter here will be encrypted with AES before it is sent to the server.</td></tr>
-      </table>
-      <div class="pagenav">
-       <table border="0">
-       <tr>
-       <td><input type="submit" value="Continue" onclick="return cryptdata();" name="_cont" /></td><td><p><span style="font-weight: bold;">Before clicking continue:</span><br />&bull; Remember the username and password you enter here! You will not be able to administer your site without the information you enter on this page.</p></td>
-       </tr>
-       </table>
-      </div>
-      <div id="cryptdebug"></div>
-     <input type="hidden" name="use_crypt" value="no" />
-     <input type="hidden" name="crypt_key" value="<?php echo $cryptkey; ?>" />
-     <input type="hidden" name="crypt_data" value="" />
-    </form>
-    <script type="text/javascript">
-    // <![CDATA[
-      var frm = document.forms.login;
-      frm.admin_user.focus();
-      function runEncryption()
-      {
-        str = '';
-        for(i=0;i<keySizeInBits/4;i++) str+='0';
-        var key = hexToByteArray(str);
-        var pt = hexToByteArray(str);
-        var ct = rijndaelEncrypt(pt, key, "ECB");
-        var ect = byteArrayToHex(ct);
-        switch(keySizeInBits)
-        {
-          case 128:
-            v = '66e94bd4ef8a2c3b884cfa59ca342b2e';
-            break;
-          case 192:
-            v = 'aae06992acbf52a3e8f4a96ec9300bd7aae06992acbf52a3e8f4a96ec9300bd7';
-            break;
-          case 256:
-            v = 'dc95c078a2408989ad48a21492842087dc95c078a2408989ad48a21492842087';
-            break;
-        }
-        var testpassed = ( ect == v && md5_vm_test() );
-        var frm = document.forms.login;
-        if(testpassed)
-        {
-          // alert('encryption self-test passed');
-          frm.use_crypt.value = 'yes';
-          var cryptkey = frm.crypt_key.value;
-          frm.crypt_key.value = '';
-          if(cryptkey != byteArrayToHex(hexToByteArray(cryptkey)))
-          {
-            alert('Byte array conversion SUCKS');
-            testpassed = false;
-          }
-          cryptkey = hexToByteArray(cryptkey);
-          if(!cryptkey || ( ( typeof cryptkey == 'string' || typeof cryptkey == 'object' ) ) && cryptkey.length != keySizeInBits / 8 )
-          {
-            frm._cont.disabled = true;
-            len = ( typeof cryptkey == 'string' || typeof cryptkey == 'object' ) ? '\nLen: '+cryptkey.length : '';
-            alert('The key is messed up\nType: '+typeof(cryptkey)+len);
-          }
-        }
-        else
-        {
-          // alert('encryption self-test FAILED');
-        }
-        if(testpassed)
-        {
-          pass = frm.admin_pass.value;
-          pass = stringToByteArray(pass);
-          cryptstring = rijndaelEncrypt(pass, cryptkey, 'ECB');
-          //decrypted = rijndaelDecrypt(cryptstring, cryptkey, 'ECB');
-          //decrypted = byteArrayToString(decrypted);
-          //return false;
-          if(!cryptstring)
-          {
-            return false;
-          }
-          cryptstring = byteArrayToHex(cryptstring);
-          // document.getElementById('cryptdebug').innerHTML = '<pre>Data: '+cryptstring+'<br />Key:  '+byteArrayToHex(cryptkey)+'</pre>';
-          frm.crypt_data.value = cryptstring;
-          frm.admin_pass.value = '';
-          frm.admin_pass_confirm.value = '';
-        }
-        return false;
-      }
-      // ]]>
-    </script>
-    <?php
-    break;
-  case "confirm":
-    if(!isset($_POST['_cont'])) {
-      echo 'No POST data signature found. Please <a href="install.php?mode=sysreqs">restart the installation</a>.';
-      $template->footer();
-      exit;
-    }
-    unset($_POST['_cont']);
-    ?>
-    <form name="confirm" action="install.php?mode=install" method="post">
-      <?php
-        $k = array_keys($_POST);
-        for($i=0;$i<sizeof($_POST);$i++) {
-          echo '<input type="hidden" name="'.htmlspecialchars($k[$i]).'" value="'.htmlspecialchars($_POST[$k[$i]]).'" />'."\n";
-        }
-      ?>
-      <h3>Enano is ready to install.</h3>
-       <p>The wizard has finished collecting information and is ready to install the database schema. Please review the information below,
-          and then click the button below to install the database.</p>
-      <ul>
-        <li>Database hostname: <?php echo $_POST['db_host']; ?></li>
-        <li>Database name: <?php echo $_POST['db_name']; ?></li>
-        <li>Database user: <?php echo $_POST['db_user']; ?></li>
-        <li>Database password: &lt;hidden&gt;</li>
-        <li>Site name: <?php echo $_POST['sitename']; ?></li>
-        <li>Site description: <?php echo $_POST['sitedesc']; ?></li>
-        <li>Administration username: <?php echo $_POST['admin_user']; ?></li>
-        <li>Cipher strength: <?php echo (string)AES_BITS; ?>-bit AES<br /><small>Cipher strength is defined in the file constants.php; if you desire to change the cipher strength, you may do so and then restart installation. Unless your site is mission-critical, changing the cipher strength is not necessary.</small></li>
-      </ul>
-      <div class="pagenav">
-        <table border="0">
-          <tr>
-            <td><input type="submit" value="Install Enano!" name="_cont" /></td><td><p><span style="font-weight: bold;">Before clicking continue:</span><br />&bull; Pray.</p></td>
-          </tr>
-        </table>
-      </div>
-    </form>
-    <?php
-    break;
-  case "install":
-    if(!isset($_POST['db_host']) ||
-       !isset($_POST['db_name']) ||
-       !isset($_POST['db_user']) ||
-       !isset($_POST['db_pass']) ||
-       !isset($_POST['sitename']) ||
-       !isset($_POST['sitedesc']) ||
-       !isset($_POST['copyright']) ||
-       !isset($_POST['admin_user']) ||
-       !isset($_POST['admin_pass']) ||
-       !isset($_POST['admin_embed_php']) || ( isset($_POST['admin_embed_php']) && !in_array($_POST['admin_embed_php'], array('2', '4')) ) ||
-       !isset($_POST['urlscheme'])
-       )
-    {
-      echo 'The installer has detected that one or more required form values is not set. Please <a href="install.php?mode=sysreqs">restart the installation</a>.';
-      $template->footer();
-      exit;
-    }
-    switch($_POST['urlscheme'])
-    {
-      case "ugly":
-      default:
-        $cp = scriptPath.'/index.php?title=';
-        break;
-      case "short":
-        $cp = scriptPath.'/index.php/';
-        break;
-      case "tiny":
-        $cp = scriptPath.'/';
-        break;
-    }
-    function err($t) { global $template; echo $t; $template->footer(); exit; }
-    
-    // $stages = array('connect', 'decrypt', 'genkey', 'parse', 'sql', 'writeconfig', 'renameconfig', 'startapi', 'initlogs');
-    
-    if ( !preg_match('/^[a-z0-9_]*$/', $_POST['table_prefix']) )
-      err('Hacking attempt was detected in table_prefix.');
-    
-      start_install_table();
-      
-      // Are we just trying to auto-rename the config files? If so, skip everything else
-      if ( !isset($_GET['stage']) || ( isset($_GET['stage']) && $_GET['stage'] != 'renameconfig' ) )
-      {
-      
-        // The stages connect, decrypt, genkey, and parse are preprocessing and don't do any actual data modification.
-        // Thus, they need to be run on each retry, e.g. never skipped.
-        run_installer_stage('connect', 'Connect to MySQL', 'stg_mysql_connect', 'MySQL denied our attempt to connect to the database. This is most likely because your login information was incorrect. You will most likely need to <a href="install.php?mode=license">restart the installation</a>.', false);
-        if ( isset($_POST['drop_tables']) )
-        {
-          // Are we supposed to drop any existing tables? If so, do it now
-          run_installer_stage('drop', 'Drop existing Enano tables', 'stg_drop_tables', 'This step never returns failure');
-        }
-        run_installer_stage('decrypt', 'Decrypt administration password', 'stg_decrypt_admin_pass', 'The administration password you entered couldn\'t be decrypted. It is possible that your server did not properly store the encryption key in the configuration file. Please check the file permissions on config.new.php. You may have to return to the login stage of the installation, clear your browser cache, and then rerun this installation.', false);
-        run_installer_stage('genkey', 'Generate ' . AES_BITS . '-bit AES private key', 'stg_generate_aes_key', 'Enano encountered an internal error while generating the site encryption key. Please contact the Enano team for support.', false);
-        run_installer_stage('parse', 'Prepare to execute schema file', 'stg_parse_schema', 'Enano encountered an internal error while parsing the SQL file that contains the database structure and initial data. Please contact the Enano team for support.', false);
-        run_installer_stage('sql', 'Execute installer schema', 'stg_install', 'The installation failed because an SQL query wasn\'t quite correct. It is possible that you entered malformed data into a form field, or there may be a bug in Enano with your version of MySQL. Please contact the Enano team for support.', false);
-        run_installer_stage('writeconfig', 'Write configuration files', 'stg_write_config', 'Enano was unable to write the configuration file with your site\'s database credentials. This is almost always because your configuration file does not have the correct permissions. On Windows servers, you may see this message even if the check on the System Requirements page passed. Temporarily running IIS as the Administrator user may help.');
-        
-        // Mainstream installation complete - Enano should be usable now
-        // The stage of starting the API is special because it has to be called out of function context.
-        // To alleviate this, we have two functions, one that returns success and one that returns failure
-        // If the Enano API load is successful, the success function is called to report the action to the user
-        // If unsuccessful, the failure report is sent
-        
-        $template_bak = $template;
-        
-        $_GET['title'] = 'Main_Page';
-        require('includes/common.php');
-        
-        if ( is_object($db) && is_object($session) )
-        {
-          run_installer_stage('startapi', 'Start the Enano API', 'stg_start_api_success', '...', false);
-        }
-        else
-        {
-          run_installer_stage('startapi', 'Start the Enano API', 'stg_start_api_failure', 'The Enano API could not be started. This is an error that should never occur; please contact the Enano team for support.', false);
-        }
-        
-        // We need to be logged in (with admin rights) before logs can be flushed
-        $admin_password = stg_decrypt_admin_pass(true);
-        $session->login_without_crypto($_POST['admin_user'], $admin_password, false);
-        
-        // Now that login cookies are set, initialize the session manager and ACLs
-        $session->start();
-        $paths->init();
-        
-        run_installer_stage('initlogs', 'Initialize logs', 'stg_init_logs', '<b>The session manager denied the request to flush logs for the main page.</b><br />
-                             While under most circumstances you can still <a href="install.php?mode=finish">finish the installation</a> after renaming your configuration files, you should be aware that some servers cannot
-                             properly set cookies due to limitations with PHP. These limitations are exposed primarily when this issue is encountered during installation. If you choose
-                             to finish the installation, please be aware that you may be unable to log into your site.');
-        
-        run_installer_stage('buildindex', 'Initialize search index', 'stg_build_index', 'Something went wrong while the page manager was attempting to build a search index.');
-        
-        /*
-         * HACKERS:
-         * If you're making a custom distribution of Enano, put all your custom plugin-related code here.
-         * You have access to the full Enano API as well as being logged in with complete admin rights.
-         * Don't do anything horrendously fancy here, unless you add a new stage (or more than one) and
-         * have the progress printed out properly.
-         */
-        
-      } // check for stage == renameconfig
-      else
-      {
-        // If we did skip the main installer routine, set $template_bak to make the reversal later work properly
-        $template_bak = $template;
-      }
-
-      // Final step is to rename the config file
-      // In early revisions of 1.0.2, this step was performed prior to the initialization of the Enano API. It was decided to move
-      // this stage to the end because it will fail more often than any other stage, thus making alternate routes imperative. If this
-      // stage fails, then no big deal, we'll just have the user rename the files manually and then let them see the pretty success message.
-      run_installer_stage('renameconfig', 'Rename configuration files', 'stg_rename_config', 'Enano couldn\'t rename the configuration files to their correct production names. Please CHMOD the folder where your Enano files are to 777 and click the retry button below, <b><u>or</u></b> perform the following rename operations and then <a href="install.php?mode=finish">finish the installation</a>.<ul><li>Rename config.new.php to config.php</li><li>Rename .htaccess.new to .htaccess (only if you selected Tiny URLs)</li></ul>');
-      
-      close_install_table();
-      
-      unset($template);
-      $template =& $template_bak;
-    
-      echo '<h3>Installation of Enano is complete.</h3><p>Review any warnings above, and then <a href="install.php?mode=finish">click here to finish the installation</a>.';
-      
-      // echo '<script type="text/javascript">window.location="'.scriptPath.'/install.php?mode=finish";</script>';
-      
-    break;
-  case "finish":
-    echo '<h3>Congratulations!</h3>
-           <p>You have finished installing Enano on this server.</p>
-          <h3>Now what?</h3>
-           <p>Click the link below to see the main page for your website. Where to go from here:</p>
-           <ul>
-             <li>The first thing you should do is log into your site using the Log in link on the sidebar.</li>
-             <li>Go into the Administration panel, expand General, and click General Configuration. There you will be able to configure some basic information about your site.</li>
-             <li>Visit the <a href="http://enanocms.org/Category:Plugins" onclick="window.open(this.href); return false;">Enano Plugin Gallery</a> to download and use plugins on your site.</li>
-             <li>Periodically create a backup of your database and filesystem, in case something goes wrong. This should be done at least once a week &ndash; more for wiki-based sites.</li>
-             <li>Hire some moderators, to help you keep rowdy users tame.</li>
-             <li>Tell the <a href="http://enanocms.org/Contact_us">Enano team</a> what you think.</li>
-             <li><b>Spread the word about Enano by adding a link to the Enano homepage on your sidebar!</b> You can enable this option in the General Configuration section of the administration panel.</li>
-           </ul>
-           <p><a href="index.php">Go to your website...</a></p>';
-    break;
-  // this stage is never shown during the installation, but is provided for legal purposes
-  case "showlicense":
-    show_license(true);
-    break;
-}
-$template->footer();
- 
-?>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/install/.htaccess	Fri Feb 22 12:51:53 2008 -0500
@@ -0,0 +1,8 @@
+# Used for testing mod_rewrite.
+
+RewriteEngine on
+
+RewriteCond %{REQUEST_FILENAME} !-f
+RewriteCond %{REQUEST_FILENAME} !-d
+RewriteRule (.*) install.php?do=modrewrite_test&str=$1
+
Binary file install/images/balancer.png has changed
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/install/images/css/installer.css	Fri Feb 22 12:51:53 2008 -0500
@@ -0,0 +1,231 @@
+/*
+ * Enano - an open-source CMS capable of wiki functions, Drupal-like sidebar blocks, and everything in between
+ * Version 1.1.1
+ * Copyright (C) 2006-2007 Dan Fuhry
+ * Installation package
+ * installer.css - visual styling rules for the installer
+ *
+ * This program is Free Software; you can redistribute and/or modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.
+ *
+ * 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.
+ */
+
+body {
+  font-family: DejaVu Sans, Arial, Helvetica, sans-serif;
+  font-size: 9pt;
+  margin: 0;
+  padding: 0;
+}
+
+div#header {
+  margin: 0px auto;
+  width: 800px;
+  padding: 10px 0;
+}
+
+div#step {
+  float: right;
+  font-size: 12pt;
+  color: #D84308;
+  line-height: 48px;
+  background-image: url(../icons/install.png);
+  background-position: right center;
+  background-repeat: no-repeat;
+  padding-right: 56px;
+  margin: 10px 0 0 0;
+}
+
+div.stages-holder {
+  color: #ffffff;
+  background-color: #2f527a;
+  width: 100%;
+}
+
+ul.stages {
+  margin: 0;
+  line-height: 24px;
+  font-size: 8pt;
+  padding: 0;
+}
+ul.stages-fixed {
+  /*
+  width: 840px;
+  */
+  display: table;
+  margin: 0 auto;
+}
+li.stage {
+  list-style-type: none;
+  float: left;
+  text-align: center;
+  padding: 3px 20px 3px 20px;
+}
+li.stage-active {
+  font-weight: bold;
+  padding: 1px 20px 5px 20px;
+  background-image: url(../marker.gif);
+  background-position: center bottom;
+  background-repeat: no-repeat;
+  background-color: #5f82aa;
+}
+div#enano-fill {
+  background-image: url(../substages.png);
+  background-repeat: repeat-x;
+}
+div#enano-body {
+  width: 780px;
+  padding: 10px;
+  margin: 0 auto;
+}
+div#enano-body a {
+  color: #003366;
+  text-decoration: underline;
+}
+div#enano-body a:hover {
+  color: #0055AA;
+}
+div#copyright {
+  border-top: 1px dotted #003399;
+  font-size: 6pt;
+  padding: 10px;
+  background-image: url(../substages.png);
+  background-repeat: repeat-x;
+  width: 77%;
+  margin: 20px auto 0 auto;
+  text-align: center;
+  color: #808080;
+}
+td.balancer {
+  width: 21px;
+  background-image: url(../balancer.png);
+  background-position: center center;
+  background-repeat: no-repeat;
+}
+ul.icons {
+  margin: 0;
+  padding: 0;
+  list-style-type: none;
+  display: table;
+}
+ul.icons li:first-child {
+  border-top-color: #FFFFFF;
+}
+ul.icons li {
+  /* Invisible border to prevent size-switching later */
+  border: 1px solid #FFFFFF;
+  border-top-color: #F0F0F0;
+  margin: 0 0 -2px 0;
+  padding: 0;
+  display: block;
+}
+ul.icons li:hover {
+  border-color: #D0D0D0;
+  -moz-border-radius: 5px;
+}
+a.icon {
+  display: block;
+  font-size: 18pt;
+  line-height: 48px;
+  padding: 10px 20px 10px 68px;
+  background-position: 10px center;
+  background-repeat: no-repeat;
+  color: #002266;
+  text-decoration: none !important;
+}
+a.icon:hover {
+  cursor: pointer;
+  color: #002266 !important;
+  background-color: #F0F0F0;
+}
+a.icon-disabled {
+  color: #808080 !important;
+  opacity: 0.7;
+  filter: alpha(opacity=70);
+}
+a.icon-disabled:hover {
+  color: #808080 !important;
+  background-color: #FCFCFC;
+  border-color: #F8F8F8;
+}
+a.icon small, a.icon-disabled small {
+  display: block;
+  font-size: 8pt;
+  line-height: normal;
+  margin-top: -10px;
+}
+a.readme {
+  background-image: url(../icons/readme.png);
+}
+a.install {
+  background-image: url(../icons/install.png);
+}
+a.install-disabled {
+  background-image: url(../icons/install-disabled.png);
+}
+a.upgrade {
+  background-image: url(../icons/upgrade.png);
+}
+a.upgrade-disabled {
+  background-image: url(../icons/upgrade-disabled.png);
+}
+
+.scroller {
+  padding: 10px;
+  border: 1px dotted #002266;
+  background-color: #F0F0F0;
+  max-height: 500px;
+  clip: rect(0px, auto, auto, 0px);
+  overflow: auto;
+}
+
+div#installnotice {
+  margin: 5% 0 0 0;
+}
+
+table#installmenu {
+  margin: 0 auto 5% auto;
+}
+span.fieldtip_js {
+  display: block;
+  background-color: #F0F0FF;
+  padding: 10px;
+  border: 1px solid #245687;
+  position: absolute;
+}
+
+/* Inputs, form controls */
+
+input[type ^="button"], button {
+  background-color: #F8F8FB;
+  color: #202020;
+  border-color: #B0B0B8 #D0D0D8 #D0D0D8 #B0B0B8;
+  border-width: 1px;
+  border-style: solid;
+}
+input[type ^="submit"] {
+  background-color: #4F729A;
+  color: #FFFFFF;
+  border-width: 1px;
+  border-style: solid;
+  border-color: #1F426A #7FA2CA #7FA2CA #1F426A;
+}
+input[type ^="submit"]:hover, input[type ^="submit"]:focus {
+  background-color: #5f82aa;
+}
+input[type ^="text"], input[type ^="password"] {
+  color: #202020;
+  background-color: #F0F0F4;
+  border: 1px solid #D6D6E9;
+}
+input[type ^="text"]:hover, input[type ^="password"]:hover {
+  color: #202020;
+  background-color: #F4F4F8;
+  border: 1px solid #D6D6E9;
+}
+input[type ^="text"]:focus, input[type ^="password"]:focus {
+  color: #202020;
+  background-color: #FFFFFF;
+  border: 1px solid #D6D6E9;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/install/images/enano-artwork/README	Fri Feb 22 12:51:53 2008 -0500
@@ -0,0 +1,8 @@
+The images in this directory are copyright (C) 2007 Dan Fuhry. Except
+as permitted by applicable law, they may not be used in any way other
+than to promote the unmodified Enano CMS. You also may not modify and
+then distribute the images in this directory, or distribute them sep-
+arately from the Enano packages. The goal here is to establish a uni-
+que identity for  Enano through the use of  a logo, and that identity
+would be confused if this  logo is used for unofficial Enano distros.
+
Binary file install/images/enano-artwork/installer-greeting.png has changed
Binary file install/images/enano-artwork/installer-header-blue.png has changed
Binary file install/images/icons/install-disabled.png has changed
Binary file install/images/icons/install.png has changed
Binary file install/images/icons/readme.png has changed
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/install/images/icons/src/README	Fri Feb 22 12:51:53 2008 -0500
@@ -0,0 +1,3 @@
+These icons are from the Flygo icon set, which is based on icons from the Tango
+Desktop Project. They are released under the GNU General Public License.
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/install/images/icons/src/accessories-text-editor.svg	Fri Feb 22 12:51:53 2008 -0500
@@ -0,0 +1,916 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+<svg
+   xmlns:dc="http://purl.org/dc/elements/1.1/"
+   xmlns:cc="http://web.resource.org/cc/"
+   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+   xmlns:svg="http://www.w3.org/2000/svg"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:xlink="http://www.w3.org/1999/xlink"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   width="48"
+   height="48"
+   id="svg2"
+   sodipodi:version="0.32"
+   inkscape:version="0.44"
+   version="1.0"
+   sodipodi:docbase="/home/lapo/Icone/cvs/gnome-icon-theme/scalable/apps"
+   sodipodi:docname="accessories-text-editor.svg"
+   inkscape:output_extension="org.inkscape.output.svg.inkscape">
+  <defs
+     id="defs4">
+    <linearGradient
+       id="linearGradient4700"
+       inkscape:collect="always">
+      <stop
+         id="stop4702"
+         offset="0"
+         style="stop-color:#2e3436;stop-opacity:1" />
+      <stop
+         id="stop4704"
+         offset="1"
+         style="stop-color:#888a85;stop-opacity:1" />
+    </linearGradient>
+    <linearGradient
+       inkscape:collect="always"
+       id="linearGradient4690">
+      <stop
+         style="stop-color:white;stop-opacity:1"
+         offset="0"
+         id="stop4692" />
+      <stop
+         style="stop-color:#eeeeec;stop-opacity:1"
+         offset="1"
+         id="stop4694" />
+    </linearGradient>
+    <linearGradient
+       inkscape:collect="always"
+       id="linearGradient4682">
+      <stop
+         style="stop-color:white;stop-opacity:1;"
+         offset="0"
+         id="stop4684" />
+      <stop
+         style="stop-color:white;stop-opacity:0;"
+         offset="1"
+         id="stop4686" />
+    </linearGradient>
+    <linearGradient
+       inkscape:collect="always"
+       id="linearGradient4333">
+      <stop
+         style="stop-color:black;stop-opacity:1;"
+         offset="0"
+         id="stop4335" />
+      <stop
+         style="stop-color:black;stop-opacity:0;"
+         offset="1"
+         id="stop4337" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient3415">
+      <stop
+         style="stop-color:black;stop-opacity:0;"
+         offset="0"
+         id="stop3417" />
+      <stop
+         id="stop3423"
+         offset="0.5"
+         style="stop-color:black;stop-opacity:1;" />
+      <stop
+         style="stop-color:black;stop-opacity:0;"
+         offset="1"
+         id="stop3419" />
+    </linearGradient>
+    <linearGradient
+       inkscape:collect="always"
+       id="linearGradient3399">
+      <stop
+         style="stop-color:black;stop-opacity:1;"
+         offset="0"
+         id="stop3401" />
+      <stop
+         style="stop-color:black;stop-opacity:0;"
+         offset="1"
+         id="stop3403" />
+    </linearGradient>
+    <linearGradient
+       inkscape:collect="always"
+       id="linearGradient2919">
+      <stop
+         style="stop-color:#d3d7cf;stop-opacity:1;"
+         offset="0"
+         id="stop2921" />
+      <stop
+         style="stop-color:#d3d7cf;stop-opacity:0;"
+         offset="1"
+         id="stop2923" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient2804">
+      <stop
+         style="stop-color:white;stop-opacity:1"
+         offset="0"
+         id="stop2806" />
+      <stop
+         style="stop-color:#d3d7cf;stop-opacity:1"
+         offset="1"
+         id="stop2808" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient2791">
+      <stop
+         style="stop-color:#555753;stop-opacity:1;"
+         offset="0"
+         id="stop2793" />
+      <stop
+         id="stop2799"
+         offset="0.5"
+         style="stop-color:#cccdcb;stop-opacity:1;" />
+      <stop
+         style="stop-color:#555753;stop-opacity:1"
+         offset="1"
+         id="stop2795" />
+    </linearGradient>
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2791"
+       id="linearGradient2797"
+       x1="11.669194"
+       y1="6.728353"
+       x2="11.580806"
+       y2="14.662594"
+       gradientUnits="userSpaceOnUse" />
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2804"
+       id="radialGradient2810"
+       cx="12.321928"
+       cy="11.669307"
+       fx="12.321928"
+       fy="11.669307"
+       r="1.499999"
+       gradientTransform="matrix(9.835652,1.854444e-6,0,1.136384,-108.6942,-1.914856)"
+       gradientUnits="userSpaceOnUse" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2919"
+       id="linearGradient2925"
+       x1="11.949747"
+       y1="40.664974"
+       x2="94.364037"
+       y2="47.897068"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(1,0,0,1.489708,-2,-22.55226)" />
+    <linearGradient
+       id="linearGradient2275"
+       inkscape:collect="always">
+      <stop
+         id="stop2277"
+         offset="0"
+         style="stop-color:#fce94f;stop-opacity:1;" />
+      <stop
+         id="stop2279"
+         offset="1"
+         style="stop-color:#c4a000" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient2301"
+       inkscape:collect="always">
+      <stop
+         id="stop2303"
+         offset="0"
+         style="stop-color:#c4a000;stop-opacity:1;" />
+      <stop
+         id="stop2305"
+         offset="1"
+         style="stop-color:#edd400" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient1813"
+       inkscape:collect="always">
+      <stop
+         id="stop1815"
+         offset="0"
+         style="stop-color:#000000;stop-opacity:1;" />
+      <stop
+         id="stop1817"
+         offset="1"
+         style="stop-color:#000000;stop-opacity:0;" />
+    </linearGradient>
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient1813"
+       id="linearGradient3273"
+       gradientUnits="userSpaceOnUse"
+       x1="18.1875"
+       y1="18.53828"
+       x2="32.9375"
+       y2="18.392296"
+       gradientTransform="matrix(1,0,0,0.415008,0,14.33231)" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2275"
+       id="linearGradient3275"
+       gradientUnits="userSpaceOnUse"
+       x1="26.993084"
+       y1="11.252465"
+       x2="30.432114"
+       y2="14.691495" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2301"
+       id="linearGradient3277"
+       gradientUnits="userSpaceOnUse"
+       x1="29.03377"
+       y1="14.298466"
+       x2="25.991804"
+       y2="11.2565" />
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient3399"
+       id="radialGradient3430"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(1,0,0,2.166667,0,-46.08333)"
+       cx="6"
+       cy="39.5"
+       fx="6"
+       fy="39.5"
+       r="3" />
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient3399"
+       id="radialGradient3432"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(1,0,0,2.166667,-45,-125.0833)"
+       cx="6"
+       cy="39.5"
+       fx="6"
+       fy="39.5"
+       r="3" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient3415"
+       id="linearGradient3434"
+       gradientUnits="userSpaceOnUse"
+       x1="18"
+       y1="46"
+       x2="18"
+       y2="32.999397" />
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient4333"
+       id="radialGradient4339"
+       cx="37.375"
+       cy="33.1875"
+       fx="37.375"
+       fy="33.1875"
+       r="14.625"
+       gradientTransform="matrix(1,0,0,0.226496,0,25.67067)"
+       gradientUnits="userSpaceOnUse" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient4682"
+       id="linearGradient4688"
+       x1="6.7928934"
+       y1="32.963203"
+       x2="7.9215727"
+       y2="54.448856"
+       gradientUnits="userSpaceOnUse" />
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient4690"
+       id="radialGradient4696"
+       cx="29.480816"
+       cy="36.776756"
+       fx="29.480816"
+       fy="36.776756"
+       r="18.5"
+       gradientTransform="matrix(2.012905,0,0,1.338879,-28.88714,-12.68199)"
+       gradientUnits="userSpaceOnUse" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient4700"
+       id="linearGradient4698"
+       x1="5.6568546"
+       y1="53.320892"
+       x2="4"
+       y2="16.003418"
+       gradientUnits="userSpaceOnUse" />
+  </defs>
+  <sodipodi:namedview
+     id="base"
+     pagecolor="#ffffff"
+     bordercolor="#afafaf"
+     borderopacity="1"
+     inkscape:pageopacity="0.0"
+     inkscape:pageshadow="2"
+     inkscape:zoom="1"
+     inkscape:cx="33.31508"
+     inkscape:cy="5.7688415"
+     inkscape:document-units="px"
+     inkscape:current-layer="layer1"
+     width="48px"
+     height="48px"
+     gridspacingx="0.5px"
+     gridspacingy="0.5px"
+     inkscape:showpageshadow="false"
+     borderlayer="true"
+     gridempspacing="2"
+     inkscape:window-width="1051"
+     inkscape:window-height="797"
+     inkscape:window-x="0"
+     inkscape:window-y="25"
+     showgrid="false"
+     showborder="false"
+     showguides="true"
+     inkscape:guide-bbox="true"
+     inkscape:grid-points="true" />
+  <metadata
+     id="metadata7">
+    <rdf:RDF>
+      <cc:Work
+         rdf:about="">
+        <dc:format>image/svg+xml</dc:format>
+        <dc:type
+           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+        <dc:creator>
+          <cc:Agent>
+            <dc:title>Lapo Calamandrei</dc:title>
+          </cc:Agent>
+        </dc:creator>
+        <cc:license
+           rdf:resource="http://creativecommons.org/licenses/GPL/2.0/" />
+        <dc:title>Text editor</dc:title>
+      </cc:Work>
+      <cc:License
+         rdf:about="http://creativecommons.org/licenses/GPL/2.0/">
+        <cc:permits
+           rdf:resource="http://web.resource.org/cc/Reproduction" />
+        <cc:permits
+           rdf:resource="http://web.resource.org/cc/Distribution" />
+        <cc:requires
+           rdf:resource="http://web.resource.org/cc/Notice" />
+        <cc:permits
+           rdf:resource="http://web.resource.org/cc/DerivativeWorks" />
+        <cc:requires
+           rdf:resource="http://web.resource.org/cc/ShareAlike" />
+        <cc:requires
+           rdf:resource="http://web.resource.org/cc/SourceCode" />
+      </cc:License>
+    </rdf:RDF>
+  </metadata>
+  <g
+     inkscape:label="Livello 1"
+     inkscape:groupmode="layer"
+     id="layer1">
+    <path
+       style="opacity:1;fill:url(#radialGradient4696);fill-opacity:1.0;stroke:url(#linearGradient4698);stroke-width:0.99999952;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dashoffset:0;stroke-opacity:1"
+       d="M 8.267767,10.523348 L 36.73221,10.523348 C 37.711553,10.523348 38.428998,11.276023 38.499977,12.291115 L 40.437477,40 L 40.5,43.5 L 4.5,43.5 L 4.5,40 L 6.5,12.291115 C 6.570075,11.320264 7.288424,10.523348 8.267767,10.523348 z "
+       id="rect3790"
+       sodipodi:nodetypes="cczcccczc" />
+    <g
+       id="g3425"
+       transform="matrix(1.000001,0,0,0.375001,-1.538462e-6,28.12497)"
+       style="opacity:0.3">
+      <rect
+         y="33"
+         x="3"
+         height="13"
+         width="3"
+         id="rect3397"
+         style="opacity:1;fill:url(#radialGradient3430);fill-opacity:1;stroke:none;stroke-width:1.00199997;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:1.20000057;stroke-opacity:1" />
+      <rect
+         transform="scale(-1,-1)"
+         y="-46"
+         x="-42"
+         height="13"
+         width="3"
+         id="rect3407"
+         style="opacity:1;fill:url(#radialGradient3432);fill-opacity:1;stroke:none;stroke-width:1.00199997;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:1.20000057;stroke-opacity:1" />
+      <rect
+         y="33"
+         x="6"
+         height="13"
+         width="33"
+         id="rect3413"
+         style="opacity:1;fill:url(#linearGradient3434);fill-opacity:1;stroke:none;stroke-width:1.00199997;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:1.20000057;stroke-opacity:1" />
+    </g>
+    <path
+       sodipodi:type="arc"
+       style="opacity:0.07;fill:url(#radialGradient4339);fill-opacity:1;stroke:none;stroke-width:1.00199997;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:1.20000057;stroke-opacity:1"
+       id="path4331"
+       sodipodi:cx="37.375"
+       sodipodi:cy="33.1875"
+       sodipodi:rx="14.625"
+       sodipodi:ry="3.3125"
+       d="M 52 33.1875 A 14.625 3.3125 0 1 1  22.75,33.1875 A 14.625 3.3125 0 1 1  52 33.1875 z"
+       transform="matrix(0.897436,0,0,0.981132,1.333333,1.688679)" />
+    <g
+       id="g2894"
+       transform="translate(-1.75,-1)">
+      <path
+         transform="matrix(1.143498,0,0,1.268986,-1.524595,-5.176204)"
+         d="M 13.999999 15.109375 A 1.7421875 1.578125 0 1 1  10.515624,15.109375 A 1.7421875 1.578125 0 1 1  13.999999 15.109375 z"
+         sodipodi:ry="1.578125"
+         sodipodi:rx="1.7421875"
+         sodipodi:cy="15.109375"
+         sodipodi:cx="12.257812"
+         id="path2878"
+         style="opacity:1;fill:white;fill-opacity:1;stroke:none;stroke-width:1.00199997;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:1.20000057;stroke-opacity:1"
+         sodipodi:type="arc" />
+      <path
+         transform="matrix(1.143498,0,0,1.268986,2.475405,-5.176204)"
+         d="M 13.999999 15.109375 A 1.7421875 1.578125 0 1 1  10.515624,15.109375 A 1.7421875 1.578125 0 1 1  13.999999 15.109375 z"
+         sodipodi:ry="1.578125"
+         sodipodi:rx="1.7421875"
+         sodipodi:cy="15.109375"
+         sodipodi:cx="12.257812"
+         id="path2880"
+         style="opacity:1;fill:white;fill-opacity:1;stroke:none;stroke-width:1.00199997;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:1.20000057;stroke-opacity:1"
+         sodipodi:type="arc" />
+      <path
+         transform="matrix(1.143498,0,0,1.268986,6.475405,-5.176204)"
+         d="M 13.999999 15.109375 A 1.7421875 1.578125 0 1 1  10.515624,15.109375 A 1.7421875 1.578125 0 1 1  13.999999 15.109375 z"
+         sodipodi:ry="1.578125"
+         sodipodi:rx="1.7421875"
+         sodipodi:cy="15.109375"
+         sodipodi:cx="12.257812"
+         id="path2882"
+         style="opacity:1;fill:white;fill-opacity:1;stroke:none;stroke-width:1.00199997;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:1.20000057;stroke-opacity:1"
+         sodipodi:type="arc" />
+      <path
+         transform="matrix(1.143498,0,0,1.268986,10.47541,-5.176204)"
+         d="M 13.999999 15.109375 A 1.7421875 1.578125 0 1 1  10.515624,15.109375 A 1.7421875 1.578125 0 1 1  13.999999 15.109375 z"
+         sodipodi:ry="1.578125"
+         sodipodi:rx="1.7421875"
+         sodipodi:cy="15.109375"
+         sodipodi:cx="12.257812"
+         id="path2884"
+         style="opacity:1;fill:white;fill-opacity:1;stroke:none;stroke-width:1.00199997;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:1.20000057;stroke-opacity:1"
+         sodipodi:type="arc" />
+      <path
+         transform="matrix(1.143498,0,0,1.268986,14.47541,-5.176204)"
+         d="M 13.999999 15.109375 A 1.7421875 1.578125 0 1 1  10.515624,15.109375 A 1.7421875 1.578125 0 1 1  13.999999 15.109375 z"
+         sodipodi:ry="1.578125"
+         sodipodi:rx="1.7421875"
+         sodipodi:cy="15.109375"
+         sodipodi:cx="12.257812"
+         id="path2886"
+         style="opacity:1;fill:white;fill-opacity:1;stroke:none;stroke-width:1.00199997;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:1.20000057;stroke-opacity:1"
+         sodipodi:type="arc" />
+      <path
+         transform="matrix(1.143498,0,0,1.268986,18.47541,-5.176204)"
+         d="M 13.999999 15.109375 A 1.7421875 1.578125 0 1 1  10.515624,15.109375 A 1.7421875 1.578125 0 1 1  13.999999 15.109375 z"
+         sodipodi:ry="1.578125"
+         sodipodi:rx="1.7421875"
+         sodipodi:cy="15.109375"
+         sodipodi:cx="12.257812"
+         id="path2888"
+         style="opacity:1;fill:white;fill-opacity:1;stroke:none;stroke-width:1.00199997;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:1.20000057;stroke-opacity:1"
+         sodipodi:type="arc" />
+      <path
+         transform="matrix(1.143498,0,0,1.268986,22.47541,-5.176204)"
+         d="M 13.999999 15.109375 A 1.7421875 1.578125 0 1 1  10.515624,15.109375 A 1.7421875 1.578125 0 1 1  13.999999 15.109375 z"
+         sodipodi:ry="1.578125"
+         sodipodi:rx="1.7421875"
+         sodipodi:cy="15.109375"
+         sodipodi:cx="12.257812"
+         id="path2890"
+         style="opacity:1;fill:white;fill-opacity:1;stroke:none;stroke-width:1.00199997;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:1.20000057;stroke-opacity:1"
+         sodipodi:type="arc" />
+    </g>
+    <rect
+       style="opacity:1;fill:url(#linearGradient2925);fill-opacity:1;stroke:none;stroke-width:1.00199997;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:1.20000057;stroke-opacity:1"
+       id="rect2757"
+       width="35"
+       height="3.0103984"
+       x="5"
+       y="40" />
+    <path
+       sodipodi:type="inkscape:offset"
+       inkscape:radius="-0.9722718"
+       inkscape:original="M 8.28125 10.53125 C 7.301907 10.53125 6.570075 11.310399 6.5 12.28125 L 4.5 40 L 4.5 43.5 L 40.5 43.5 L 40.4375 40 L 38.5 12.28125 C 38.429021 11.266158 37.698095 10.53125 36.71875 10.53125 L 8.28125 10.53125 z "
+       style="opacity:1;fill:none;fill-opacity:1.0;stroke:url(#linearGradient4688);stroke-width:1;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dashoffset:0;stroke-opacity:1;stroke-dasharray:none"
+       id="path4680"
+       d="M 8.28125,11.5 C 7.8175892,11.5 7.5065211,11.820452 7.46875,12.34375 L 5.46875,40 L 5.46875,40.0625 L 5.46875,42.53125 L 39.5,42.53125 L 39.46875,40.0625 L 39.46875,40.03125 L 37.53125,12.34375 C 37.490391,11.75941 37.211695,11.5 36.71875,11.5 L 8.28125,11.5 z " />
+    <path
+       style="fill:none;fill-rule:evenodd;stroke:#c17d11;stroke-width:1px;stroke-linecap:square;stroke-linejoin:miter;stroke-opacity:1"
+       d="M 4.5,43.5 L 40.5,43.5"
+       id="path2760"
+       sodipodi:nodetypes="cc" />
+    <g
+       id="g2814"
+       transform="translate(-2,-1)">
+      <rect
+         ry="1.5072321"
+         rx="0.99899912"
+         y="9.5010004"
+         x="11.500997"
+         height="5.0440111"
+         width="1.9979982"
+         id="rect2776"
+         style="opacity:1;fill:url(#radialGradient2810);fill-opacity:1;stroke:url(#linearGradient2797);stroke-width:1.00199974;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:1.20000057;stroke-opacity:1" />
+      <path
+         transform="translate(-0.21875,-0.109374)"
+         d="M 12.71875 11.257812 A 0.59375 0.6484375 0 1 1  11.53125,11.257812 A 0.59375 0.6484375 0 1 1  12.71875 11.257812 z"
+         sodipodi:ry="0.6484375"
+         sodipodi:rx="0.59375"
+         sodipodi:cy="11.257812"
+         sodipodi:cx="12.125"
+         id="path2812"
+         style="opacity:1;fill:white;fill-opacity:1;stroke:none;stroke-width:1.00199997;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:1.20000057;stroke-opacity:1"
+         sodipodi:type="arc" />
+    </g>
+    <g
+       id="g2637"
+       inkscape:label="base"
+       style="display:inline"
+       transform="translate(60.78337,49.43458)" />
+    <g
+       id="g2953"
+       style="opacity:0.6"
+       transform="translate(0,-1)">
+      <rect
+         ry="0.5"
+         rx="0.5"
+         y="18"
+         x="31"
+         height="1"
+         width="5"
+         id="rect3297"
+         style="opacity:0.8;fill:#888a85;fill-opacity:1;stroke:none;stroke-width:1.00199997;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:1.20000057;stroke-opacity:1" />
+      <rect
+         ry="0.5"
+         rx="0.5"
+         y="20"
+         x="8.875"
+         height="1"
+         width="2.125"
+         id="rect3305"
+         style="opacity:0.8;fill:#888a85;fill-opacity:1;stroke:none;stroke-width:1.00199997;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:1.20000057;stroke-opacity:1" />
+      <rect
+         ry="0.5"
+         rx="0.46088129"
+         y="36"
+         x="7.828125"
+         height="1"
+         width="4.171875"
+         id="rect3287"
+         style="opacity:0.8;fill:#888a85;fill-opacity:1;stroke:none;stroke-width:1.00199997;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:1.20000057;stroke-opacity:1" />
+      <rect
+         ry="0.5"
+         rx="0.5"
+         y="23"
+         x="8.609375"
+         height="1"
+         width="8.390625"
+         id="rect3307"
+         style="opacity:0.8;fill:#888a85;fill-opacity:1;stroke:none;stroke-width:1.00199997;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:1.20000057;stroke-opacity:1" />
+      <rect
+         ry="0.5"
+         rx="0.49520382"
+         y="25"
+         x="8.484375"
+         height="1"
+         width="3.515625"
+         id="rect3309"
+         style="opacity:0.8;fill:#888a85;fill-opacity:1;stroke:none;stroke-width:1.00199997;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:1.20000057;stroke-opacity:1" />
+      <rect
+         ry="0.5"
+         rx="0.5"
+         y="33"
+         x="33"
+         height="1"
+         width="4"
+         id="rect3313"
+         style="opacity:0.8;fill:#888a85;fill-opacity:1;stroke:none;stroke-width:1.00199997;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:1.20000057;stroke-opacity:1" />
+      <rect
+         inkscape:transform-center-x="0.28125"
+         ry="0.5"
+         rx="0.5"
+         y="36"
+         x="21"
+         height="1"
+         width="3"
+         id="rect2940"
+         style="opacity:0.8;fill:#888a85;fill-opacity:1;stroke:none;stroke-width:1.00199997;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:1.20000057;stroke-opacity:1" />
+      <rect
+         ry="0.5"
+         rx="0.54237288"
+         y="23"
+         x="30"
+         height="1"
+         width="5"
+         id="rect2915"
+         style="opacity:0.8;fill:#888a85;fill-opacity:1;stroke:none;stroke-width:1.00199997;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:1.20000057;stroke-opacity:1" />
+      <rect
+         ry="0.5"
+         rx="0.5"
+         y="28"
+         x="8.359375"
+         height="1"
+         width="2.640625"
+         id="rect2885"
+         style="opacity:0.8;fill:#888a85;fill-opacity:1;stroke:none;stroke-width:1.00199997;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:1.20000057;stroke-opacity:1" />
+      <rect
+         ry="0.5"
+         rx="0.5"
+         y="18"
+         x="9"
+         height="1"
+         width="6"
+         id="rect2893"
+         style="opacity:0.8;fill:#888a85;fill-opacity:1;stroke:none;stroke-width:1.00199997;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:1.20000057;stroke-opacity:1" />
+      <rect
+         ry="0.5"
+         rx="0.5"
+         y="18"
+         x="21"
+         height="1"
+         width="5"
+         id="rect2895"
+         style="opacity:0.8;fill:#888a85;fill-opacity:1;stroke:none;stroke-width:1.00199997;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:1.20000057;stroke-opacity:1" />
+      <rect
+         ry="0.5"
+         rx="0.5"
+         y="18"
+         x="28"
+         height="1"
+         width="2"
+         id="rect2897"
+         style="opacity:0.8;fill:#888a85;fill-opacity:1;stroke:none;stroke-width:1.00199997;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:1.20000057;stroke-opacity:1" />
+      <rect
+         ry="0.5"
+         rx="0.5"
+         y="18"
+         x="16"
+         height="1"
+         width="2"
+         id="rect2899"
+         style="opacity:0.8;fill:#888a85;fill-opacity:1;stroke:none;stroke-width:1.00199997;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:1.20000057;stroke-opacity:1" />
+      <rect
+         ry="0.5"
+         rx="0.5"
+         y="18"
+         x="19"
+         height="1"
+         width="2"
+         id="rect2901"
+         style="opacity:0.8;fill:#888a85;fill-opacity:1;stroke:none;stroke-width:1.00199997;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:1.20000057;stroke-opacity:1" />
+      <rect
+         ry="0.5"
+         rx="0.54237288"
+         y="20"
+         x="12"
+         height="1"
+         width="4"
+         id="rect2903"
+         style="opacity:0.8;fill:#888a85;fill-opacity:1;stroke:none;stroke-width:1.00199997;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:1.20000057;stroke-opacity:1" />
+      <rect
+         ry="0.5"
+         rx="0.54237288"
+         y="20"
+         x="17"
+         height="1"
+         width="2"
+         id="rect2905"
+         style="opacity:0.8;fill:#888a85;fill-opacity:1;stroke:none;stroke-width:1.00199997;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:1.20000057;stroke-opacity:1" />
+      <rect
+         ry="0.5"
+         rx="0.54237288"
+         y="20"
+         x="20"
+         height="1"
+         width="4"
+         id="rect2907"
+         style="opacity:0.8;fill:#888a85;fill-opacity:1;stroke:none;stroke-width:1.00199997;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:1.20000057;stroke-opacity:1" />
+      <rect
+         ry="0.5"
+         rx="0.54237288"
+         y="23"
+         x="19"
+         height="1"
+         width="4"
+         id="rect2909"
+         style="opacity:0.8;fill:#888a85;fill-opacity:1;stroke:none;stroke-width:1.00199997;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:1.20000057;stroke-opacity:1" />
+      <rect
+         ry="0.5"
+         rx="0.54237288"
+         y="23"
+         x="23"
+         height="1"
+         width="2"
+         id="rect2911"
+         style="opacity:0.8;fill:#888a85;fill-opacity:1;stroke:none;stroke-width:1.00199997;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:1.20000057;stroke-opacity:1" />
+      <rect
+         ry="0.5"
+         rx="0.54237288"
+         y="23"
+         x="26"
+         height="1"
+         width="3"
+         id="rect2913"
+         style="opacity:0.8;fill:#888a85;fill-opacity:1;stroke:none;stroke-width:1.00199997;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:1.20000057;stroke-opacity:1" />
+      <rect
+         ry="0.5"
+         rx="0.54237288"
+         y="25"
+         x="13"
+         height="1"
+         width="2"
+         id="rect2919"
+         style="opacity:0.8;fill:#888a85;fill-opacity:1;stroke:none;stroke-width:1.00199997;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:1.20000057;stroke-opacity:1" />
+      <rect
+         ry="0.5"
+         rx="0.54237288"
+         y="25"
+         x="16"
+         height="1"
+         width="4"
+         id="rect2921"
+         style="opacity:0.8;fill:#888a85;fill-opacity:1;stroke:none;stroke-width:1.00199997;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:1.20000057;stroke-opacity:1" />
+      <rect
+         ry="0.5"
+         rx="0.54237288"
+         y="25"
+         x="20"
+         height="1"
+         width="2"
+         id="rect2923"
+         style="opacity:0.8;fill:#888a85;fill-opacity:1;stroke:none;stroke-width:1.00199997;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:1.20000057;stroke-opacity:1" />
+      <rect
+         ry="0.5"
+         rx="0.54237288"
+         y="25"
+         x="24"
+         height="1"
+         width="2"
+         id="rect2925"
+         style="opacity:0.8;fill:#888a85;fill-opacity:1;stroke:none;stroke-width:1.00199997;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:1.20000057;stroke-opacity:1" />
+      <rect
+         ry="0.5"
+         rx="0.54237288"
+         y="28"
+         x="12"
+         height="1"
+         width="2"
+         id="rect2931"
+         style="opacity:0.8;fill:#888a85;fill-opacity:1;stroke:none;stroke-width:1.00199997;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:1.20000057;stroke-opacity:1" />
+      <rect
+         ry="0.5"
+         rx="0.54237288"
+         y="28"
+         x="14"
+         height="1"
+         width="4"
+         id="rect2933"
+         style="opacity:0.8;fill:#888a85;fill-opacity:1;stroke:none;stroke-width:1.00199997;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:1.20000057;stroke-opacity:1" />
+      <rect
+         ry="0.5"
+         rx="0.54237288"
+         y="28"
+         x="19"
+         height="1"
+         width="2"
+         id="rect2935"
+         style="opacity:0.8;fill:#888a85;fill-opacity:1;stroke:none;stroke-width:1.00199997;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:1.20000057;stroke-opacity:1" />
+      <rect
+         ry="0.5"
+         rx="0.54237288"
+         y="36"
+         x="13"
+         height="1"
+         width="6"
+         id="rect2938"
+         style="opacity:0.8;fill:#888a85;fill-opacity:1;stroke:none;stroke-width:1.00199997;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:1.20000057;stroke-opacity:1" />
+      <rect
+         ry="0.5"
+         rx="0.5"
+         y="33"
+         x="8"
+         height="1"
+         width="2"
+         id="rect2942"
+         style="opacity:0.8;fill:#888a85;fill-opacity:1;stroke:none;stroke-width:1.00199997;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:1.20000057;stroke-opacity:1" />
+      <rect
+         ry="0.5"
+         rx="0.54237288"
+         y="33"
+         x="11"
+         height="1"
+         width="4"
+         id="rect2945"
+         style="opacity:0.8;fill:#888a85;fill-opacity:1;stroke:none;stroke-width:1.00199997;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:1.20000057;stroke-opacity:1" />
+      <rect
+         ry="0.5"
+         rx="0.54237288"
+         y="33"
+         x="17"
+         height="1"
+         width="5"
+         id="rect2947"
+         style="opacity:0.8;fill:#888a85;fill-opacity:1;stroke:none;stroke-width:1.00199997;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:1.20000057;stroke-opacity:1" />
+      <rect
+         ry="0.5"
+         rx="0.54237288"
+         y="33"
+         x="23"
+         height="1"
+         width="4"
+         id="rect2949"
+         style="opacity:0.8;fill:#888a85;fill-opacity:1;stroke:none;stroke-width:1.00199997;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:1.20000057;stroke-opacity:1" />
+      <rect
+         ry="0.5"
+         rx="0.54237288"
+         y="33.004311"
+         x="28.007845"
+         height="1"
+         width="4"
+         id="rect2951"
+         style="opacity:0.8;fill:#888a85;fill-opacity:1;stroke:none;stroke-width:1.00199997;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:1.20000057;stroke-opacity:1" />
+    </g>
+    <g
+       transform="translate(6.5485,12.43459)"
+       id="g2369">
+      <path
+         id="path2334"
+         d="M 34.53125,16.03125 L 19.53125,20.504163 L 19.40625,20.569008 L 19.3125,20.646822 L 16.5625,23.5 L 24,22.657016 L 24.28125,22.631078 L 24.46875,22.553264 L 34.53125,19.870071 L 34.53125,16.03125 z "
+         style="opacity:0.23529412;fill:url(#linearGradient3273);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;display:inline"
+         sodipodi:nodetypes="cccccccccc" />
+      <g
+         id="g2321"
+         transform="translate(-0.15625,-0.25)">
+        <path
+           sodipodi:nodetypes="cccccc"
+           id="path2273"
+           d="M 19.5,18 L 36.5,1 C 38.675049,1.359961 39.584719,2.7322249 40,4.5 L 23,21.5 L 17.5,23 L 19.5,18 z "
+           style="fill:url(#linearGradient3275);fill-opacity:1;fill-rule:evenodd;stroke:url(#linearGradient3277);stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+        <path
+           sodipodi:nodetypes="cccccc"
+           id="path2313"
+           d="M 20.399998,18.5 L 36.897748,2.1022524 C 37.987493,2.280687 38.415009,3.0901961 38.897748,4.1022524 L 22.5,20.600002 L 19.199997,21.500003 L 20.399998,18.5 z "
+           style="opacity:0.28235294;fill:none;fill-opacity:1;fill-rule:evenodd;stroke:white;stroke-width:1.0000006;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;display:inline" />
+        <path
+           sodipodi:nodetypes="cczcc"
+           id="path2298"
+           d="M 18.34633,22.276561 L 19.94414,18.268127 C 19.94414,18.268127 21.094356,18.503399 21.796875,19.203125 C 22.499394,19.902851 22.754217,21.067032 22.754217,21.067032 L 18.34633,22.276561 z "
+           style="opacity:0.50196078;fill:white;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.31200001;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+        <path
+           id="path2283"
+           d="M 17.5625,21.5 L 16.65625,23.75 L 19,23.09375 C 19.00202,23.061913 19,23.032344 19,23 C 19,22.197875 18.354692,21.540199 17.5625,21.5 z "
+           style="fill:black;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;display:inline"
+           sodipodi:nodetypes="cccsc" />
+      </g>
+    </g>
+    <use
+       x="0"
+       y="0"
+       xlink:href="#g2814"
+       id="use4712"
+       transform="translate(4,0)"
+       width="48"
+       height="48" />
+    <use
+       x="0"
+       y="0"
+       xlink:href="#g2814"
+       id="use4714"
+       transform="translate(8,0)"
+       width="48"
+       height="48" />
+    <use
+       x="0"
+       y="0"
+       xlink:href="#g2814"
+       id="use4716"
+       transform="translate(12,0)"
+       width="48"
+       height="48" />
+    <use
+       x="0"
+       y="0"
+       xlink:href="#g2814"
+       id="use4718"
+       transform="translate(16,0)"
+       width="48"
+       height="48" />
+    <use
+       x="0"
+       y="0"
+       xlink:href="#g2814"
+       id="use4720"
+       transform="translate(20,0)"
+       width="48"
+       height="48" />
+    <use
+       x="0"
+       y="0"
+       xlink:href="#g2814"
+       id="use4722"
+       transform="translate(24,0)"
+       width="48"
+       height="48" />
+  </g>
+</svg>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/install/images/icons/src/system-installer.svg	Fri Feb 22 12:51:53 2008 -0500
@@ -0,0 +1,495 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+<svg
+   xmlns:dc="http://purl.org/dc/elements/1.1/"
+   xmlns:cc="http://web.resource.org/cc/"
+   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+   xmlns:svg="http://www.w3.org/2000/svg"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:xlink="http://www.w3.org/1999/xlink"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   width="48.000000px"
+   height="48.000000px"
+   id="svg14603"
+   sodipodi:version="0.32"
+   inkscape:version="0.43+devel"
+   sodipodi:docbase="/home/jimmac/src/cvs/tango-icon-theme/scalable/apps"
+   sodipodi:docname="system-installer.svg">
+  <defs
+     id="defs3">
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient5060"
+       id="radialGradient5031"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(-2.774389,0,0,1.969706,112.7623,-872.8854)"
+       cx="605.71429"
+       cy="486.64789"
+       fx="605.71429"
+       fy="486.64789"
+       r="117.14286" />
+    <linearGradient
+       inkscape:collect="always"
+       id="linearGradient5060">
+      <stop
+         style="stop-color:black;stop-opacity:1;"
+         offset="0"
+         id="stop5062" />
+      <stop
+         style="stop-color:black;stop-opacity:0;"
+         offset="1"
+         id="stop5064" />
+    </linearGradient>
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient5060"
+       id="radialGradient5029"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(2.774389,0,0,1.969706,-1891.633,-872.8854)"
+       cx="605.71429"
+       cy="486.64789"
+       fx="605.71429"
+       fy="486.64789"
+       r="117.14286" />
+    <linearGradient
+       id="linearGradient5048">
+      <stop
+         style="stop-color:black;stop-opacity:0;"
+         offset="0"
+         id="stop5050" />
+      <stop
+         id="stop5056"
+         offset="0.5"
+         style="stop-color:black;stop-opacity:1;" />
+      <stop
+         style="stop-color:black;stop-opacity:0;"
+         offset="1"
+         id="stop5052" />
+    </linearGradient>
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient5048"
+       id="linearGradient5027"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(2.774389,0,0,1.969706,-1892.179,-872.8854)"
+       x1="302.85715"
+       y1="366.64789"
+       x2="302.85715"
+       y2="609.50507" />
+    <linearGradient
+       id="linearGradient7844"
+       inkscape:collect="always">
+      <stop
+         id="stop7846"
+         offset="0"
+         style="stop-color:#000000;stop-opacity:1;" />
+      <stop
+         id="stop7848"
+         offset="1"
+         style="stop-color:#000000;stop-opacity:0;" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient7834"
+       inkscape:collect="always">
+      <stop
+         id="stop7836"
+         offset="0"
+         style="stop-color:#ffffff;stop-opacity:1;" />
+      <stop
+         id="stop7838"
+         offset="1"
+         style="stop-color:#ffffff;stop-opacity:0;" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient7670">
+      <stop
+         id="stop7672"
+         offset="0"
+         style="stop-color:#dfdfdf;stop-opacity:1;" />
+      <stop
+         id="stop7674"
+         offset="1.0000000"
+         style="stop-color:#c0c0c0;stop-opacity:1.0000000;" />
+    </linearGradient>
+    <linearGradient
+       gradientTransform="matrix(1.008511,0.000000,0.000000,1.000000,-47.59576,-0.285714)"
+       gradientUnits="userSpaceOnUse"
+       y2="40.857143"
+       x2="72.857140"
+       y1="9.7142859"
+       x1="64.571426"
+       id="linearGradient7676"
+       xlink:href="#linearGradient7670"
+       inkscape:collect="always" />
+    <linearGradient
+       gradientTransform="translate(-2.000000,0.000000)"
+       gradientUnits="userSpaceOnUse"
+       y2="0.50379461"
+       x2="19.323767"
+       y1="11.312428"
+       x1="19.362535"
+       id="linearGradient7840"
+       xlink:href="#linearGradient7834"
+       inkscape:collect="always" />
+    <radialGradient
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(1.000000,0.000000,0.000000,0.333333,1.298874e-16,25.06362)"
+       r="22.728432"
+       fy="37.595428"
+       fx="24.546707"
+       cy="37.595428"
+       cx="24.546707"
+       id="radialGradient7850"
+       xlink:href="#linearGradient7844"
+       inkscape:collect="always" />
+    <linearGradient
+       id="aigrd1"
+       gradientUnits="userSpaceOnUse"
+       x1="14.9966"
+       y1="11.1885"
+       x2="32.511"
+       y2="34.3075">
+      <stop
+         offset="0"
+         style="stop-color:#EBEBEB"
+         id="stop3034" />
+      <stop
+         offset="0.5"
+         style="stop-color:#FFFFFF"
+         id="stop3036" />
+      <stop
+         offset="1"
+         style="stop-color:#EBEBEB"
+         id="stop3038" />
+    </linearGradient>
+    <linearGradient
+       id="aigrd2"
+       gradientUnits="userSpaceOnUse"
+       x1="12.2744"
+       y1="32.4165"
+       x2="35.3912"
+       y2="14.2033">
+      <stop
+         offset="0"
+         style="stop-color:#FBFBFB"
+         id="stop3043" />
+      <stop
+         offset="0.5"
+         style="stop-color:#B6B6B6"
+         id="stop3045" />
+      <stop
+         offset="1"
+         style="stop-color:#E4E4E4"
+         id="stop3047" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient4236">
+      <stop
+         style="stop-color:#ffffff;stop-opacity:0.32673267;"
+         offset="0.0000000"
+         id="stop4238" />
+      <stop
+         style="stop-color:#ffffff;stop-opacity:0.60396039;"
+         offset="1.0000000"
+         id="stop4240" />
+    </linearGradient>
+    <linearGradient
+       inkscape:collect="always"
+       id="linearGradient6028">
+      <stop
+         style="stop-color:#ffffff;stop-opacity:1;"
+         offset="0"
+         id="stop6030" />
+      <stop
+         style="stop-color:#ffffff;stop-opacity:0;"
+         offset="1"
+         id="stop6032" />
+    </linearGradient>
+    <linearGradient
+       inkscape:collect="always"
+       id="linearGradient6036">
+      <stop
+         style="stop-color:#ffffff;stop-opacity:1;"
+         offset="0"
+         id="stop6038" />
+      <stop
+         style="stop-color:#ffffff;stop-opacity:0;"
+         offset="1"
+         id="stop6040" />
+    </linearGradient>
+    <linearGradient
+       y2="14.2033"
+       x2="35.3912"
+       y1="32.4165"
+       x1="12.2744"
+       gradientUnits="userSpaceOnUse"
+       id="linearGradient3394">
+      <stop
+         id="stop3396"
+         style="stop-color:#fff307;stop-opacity:1.0000000;"
+         offset="0.0000000" />
+      <stop
+         id="stop3398"
+         style="stop-color:#166eff;stop-opacity:1.0000000;"
+         offset="0.50000000" />
+      <stop
+         id="stop3400"
+         style="stop-color:#ffffff;stop-opacity:0.0000000;"
+         offset="1.0000000" />
+    </linearGradient>
+    <radialGradient
+       r="22.728432"
+       fy="37.595428"
+       fx="24.546707"
+       cy="37.595428"
+       cx="24.546707"
+       gradientTransform="matrix(1.000000,0.000000,0.000000,0.333333,1.121564e-14,25.06362)"
+       gradientUnits="userSpaceOnUse"
+       id="radialGradient10566"
+       xlink:href="#linearGradient7844"
+       inkscape:collect="always" />
+    <linearGradient
+       y2="34.3075"
+       x2="32.511"
+       y1="11.1885"
+       x1="14.9966"
+       gradientTransform="matrix(0.683145,0.000000,0.000000,0.683145,18.55581,18.12886)"
+       gradientUnits="userSpaceOnUse"
+       id="linearGradient10568"
+       xlink:href="#aigrd1"
+       inkscape:collect="always" />
+    <linearGradient
+       y2="14.2033"
+       x2="35.3912"
+       y1="32.4165"
+       x1="12.2744"
+       gradientTransform="matrix(0.705308,0.000000,0.000000,0.705308,18.02392,17.61692)"
+       gradientUnits="userSpaceOnUse"
+       id="linearGradient10570"
+       xlink:href="#aigrd2"
+       inkscape:collect="always" />
+    <linearGradient
+       y2="28.000000"
+       x2="29.000000"
+       y1="14.625000"
+       x1="21.125000"
+       gradientTransform="matrix(0.717302,0.000000,0.000000,0.717302,17.73603,18.06909)"
+       gradientUnits="userSpaceOnUse"
+       id="linearGradient10572"
+       xlink:href="#linearGradient4236"
+       inkscape:collect="always" />
+    <linearGradient
+       y2="28.000000"
+       x2="29.000000"
+       y1="14.625000"
+       x1="21.125000"
+       gradientTransform="matrix(0.717302,0.000000,0.000000,0.717302,17.73603,18.06909)"
+       gradientUnits="userSpaceOnUse"
+       id="linearGradient10574"
+       xlink:href="#linearGradient4236"
+       inkscape:collect="always" />
+    <linearGradient
+       y2="54.698483"
+       x2="48.798885"
+       y1="3.6100161"
+       x1="10.501720"
+       gradientTransform="matrix(0.573842,0.000000,0.000000,0.573842,20.97995,19.56347)"
+       gradientUnits="userSpaceOnUse"
+       id="linearGradient10576"
+       xlink:href="#linearGradient6036"
+       inkscape:collect="always" />
+    <linearGradient
+       y2="18.366575"
+       x2="17.742729"
+       y1="31.494707"
+       x1="28.702885"
+       gradientUnits="userSpaceOnUse"
+       id="linearGradient10578"
+       xlink:href="#linearGradient6028"
+       inkscape:collect="always" />
+    <radialGradient
+       r="21.333334"
+       fy="27.569166"
+       fx="37.751469"
+       cy="27.569166"
+       cx="37.751469"
+       gradientTransform="matrix(0.441746,0.498655,-0.407098,0.360624,32.00755,10.21308)"
+       gradientUnits="userSpaceOnUse"
+       id="radialGradient10580"
+       xlink:href="#linearGradient3394"
+       inkscape:collect="always" />
+  </defs>
+  <sodipodi:namedview
+     fill="#a40000"
+     id="base"
+     pagecolor="#ffffff"
+     bordercolor="#666666"
+     borderopacity="0.26666667"
+     inkscape:pageopacity="0.0"
+     inkscape:pageshadow="2"
+     inkscape:zoom="1"
+     inkscape:cx="34.663875"
+     inkscape:cy="17.441956"
+     inkscape:current-layer="layer1"
+     showgrid="false"
+     inkscape:grid-bbox="true"
+     inkscape:document-units="px"
+     inkscape:showpageshadow="false"
+     inkscape:window-width="872"
+     inkscape:window-height="684"
+     inkscape:window-x="213"
+     inkscape:window-y="252" />
+  <metadata
+     id="metadata4">
+    <rdf:RDF>
+      <cc:Work
+         rdf:about="">
+        <dc:format>image/svg+xml</dc:format>
+        <dc:type
+           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+        <dc:title>System - Installer</dc:title>
+        <dc:creator>
+          <cc:Agent>
+            <dc:title>jakub Steiner</dc:title>
+          </cc:Agent>
+        </dc:creator>
+        <dc:source>http://jimmac.musichall.cz</dc:source>
+        <cc:license
+           rdf:resource="http://creativecommons.org/licenses/by-sa/2.0/" />
+      </cc:Work>
+      <cc:License
+         rdf:about="http://creativecommons.org/licenses/by-sa/2.0/">
+        <cc:permits
+           rdf:resource="http://web.resource.org/cc/Reproduction" />
+        <cc:permits
+           rdf:resource="http://web.resource.org/cc/Distribution" />
+        <cc:requires
+           rdf:resource="http://web.resource.org/cc/Notice" />
+        <cc:requires
+           rdf:resource="http://web.resource.org/cc/Attribution" />
+        <cc:permits
+           rdf:resource="http://web.resource.org/cc/DerivativeWorks" />
+        <cc:requires
+           rdf:resource="http://web.resource.org/cc/ShareAlike" />
+      </cc:License>
+    </rdf:RDF>
+  </metadata>
+  <g
+     id="layer1"
+     inkscape:label="Layer 1"
+     inkscape:groupmode="layer">
+    <path
+       sodipodi:nodetypes="ccccc"
+       id="path7822"
+       d="M 7.0663522,9.8326324 L 11.142857,5.5714286 L 34.714286,5.5714286 L 39.034663,9.9336477 L 7.0663522,9.8326324 z "
+       style="opacity:1.0000000;color:#000000;fill:#6b6c69;fill-opacity:1.0000000;fill-rule:evenodd;stroke:#606060;stroke-width:1.0000000;stroke-linecap:round;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4.0000000;stroke-dasharray:none;stroke-dashoffset:0.0000000;stroke-opacity:1.0000000;visibility:visible;display:inline;overflow:visible" />
+    <g
+       id="g5022"
+       transform="matrix(2.01828e-2,0,0,2.086758e-2,41.09416,37.29644)">
+      <rect
+         y="-150.69685"
+         x="-1559.2523"
+         height="478.35718"
+         width="1339.6335"
+         id="rect4173"
+         style="opacity:0.40206185;color:black;fill:url(#linearGradient5027);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;stroke-linecap:round;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible" />
+      <path
+         sodipodi:nodetypes="cccc"
+         id="path5058"
+         d="M -219.61876,-150.68038 C -219.61876,-150.68038 -219.61876,327.65041 -219.61876,327.65041 C -76.744594,328.55086 125.78146,220.48075 125.78138,88.454235 C 125.78138,-43.572302 -33.655436,-150.68036 -219.61876,-150.68038 z "
+         style="opacity:0.40206185;color:black;fill:url(#radialGradient5029);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;stroke-linecap:round;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible" />
+      <path
+         style="opacity:0.40206185;color:black;fill:url(#radialGradient5031);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;stroke-linecap:round;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
+         d="M -1559.2523,-150.68038 C -1559.2523,-150.68038 -1559.2523,327.65041 -1559.2523,327.65041 C -1702.1265,328.55086 -1904.6525,220.48075 -1904.6525,88.454235 C -1904.6525,-43.572302 -1745.2157,-150.68036 -1559.2523,-150.68038 z "
+         id="path5018"
+         sodipodi:nodetypes="cccc" />
+    </g>
+    <rect
+       ry="1.4285715"
+       rx="1.4285721"
+       y="9.4285717"
+       x="6.5756874"
+       height="31.142857"
+       width="32.848644"
+       id="rect6910"
+       style="opacity:1.0000000;color:#000000;fill:url(#linearGradient7676);fill-opacity:1.0000000;fill-rule:evenodd;stroke:#606060;stroke-width:1.0000001;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4.0000000;stroke-dasharray:none;stroke-dashoffset:0.0000000;stroke-opacity:1.0000000;visibility:visible;display:inline;overflow:visible" />
+    <path
+       sodipodi:nodetypes="cccccc"
+       id="rect7826"
+       d="M 38.857143,22.756128 L 38.857143,39.184701 C 38.857143,39.659558 38.494011,40.041844 38.042945,40.041844 L 15.874474,40.041844 L 15.923863,22.756128 C 15.923863,22.756128 38.857143,22.756128 38.857143,22.756128 z "
+       style="color:#000000;fill:#a40000;fill-opacity:1.0000000;fill-rule:evenodd;stroke:none;stroke-width:1.0000000;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4.0000000;stroke-dasharray:1.0000000 1.0000000 ;stroke-dashoffset:0.0000000;stroke-opacity:1.0000000;visibility:visible;display:inline;overflow:visible" />
+    <path
+       sodipodi:nodetypes="cc"
+       id="path7824"
+       d="M 15.379549,11.285714 L 15.379549,39.285714"
+       style="opacity:1.0000000;color:#000000;fill:none;fill-opacity:1.0000000;fill-rule:evenodd;stroke:#606060;stroke-width:1.0000000;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4.0000000;stroke-dasharray:1.0000000 1.0000000 ;stroke-dashoffset:0.0000000;stroke-opacity:1.0000000;visibility:visible;display:inline;overflow:visible" />
+    <path
+       style="color:#000000;fill:#f0f0f0;fill-opacity:1.0000000;fill-rule:evenodd;stroke:none;stroke-width:1.0000000;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4.0000000;stroke-dasharray:1.0000000 1.0000000 ;stroke-dashoffset:0.0000000;stroke-opacity:1.0000000;visibility:visible;display:inline;overflow:visible"
+       d="M 38.857143,22.613273 L 38.857143,11.470414 C 38.857143,10.995557 38.494011,10.613271 38.042945,10.613271 L 15.874474,10.613271 L 15.923863,22.613273 C 15.923863,22.613273 38.857143,22.613273 38.857143,22.613273 z "
+       id="path10582"
+       sodipodi:nodetypes="cccccc" />
+    <path
+       sodipodi:nodetypes="ccccccccs"
+       id="rect7829"
+       d="M 11.512932,6.5274685 C 11.512932,6.5274685 34.285047,6.5274685 34.285047,6.5274685 C 34.285047,6.5274685 38.542046,10.784467 38.542046,10.784467 L 38.542046,39.215524 C 38.542046,39.503290 38.310378,39.734958 38.022612,39.734958 L 7.9773979,39.734958 C 7.6896315,39.734958 7.4579639,39.503290 7.4579639,39.215524 L 7.4579639,10.784467 C 7.4579639,10.784467 11.512932,6.5274685 11.512932,6.5274685 z "
+       style="opacity:0.62566847;color:#000000;fill:none;fill-opacity:1.0000000;fill-rule:evenodd;stroke:url(#linearGradient7840);stroke-width:0.99999994;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4.0000000;stroke-dashoffset:0.0000000;stroke-opacity:1.0000000;visibility:visible;display:inline;overflow:visible" />
+    <g
+       transform="translate(-0.999997,-0.285714)"
+       id="g10554">
+      <path
+         transform="matrix(0.550240,0.000000,0.000000,0.550240,19.89726,20.62321)"
+         d="M 47.275139 37.595428 A 22.728432 7.5761442 0 1 1  1.8182755,37.595428 A 22.728432 7.5761442 0 1 1  47.275139 37.595428 z"
+         sodipodi:ry="7.5761442"
+         sodipodi:rx="22.728432"
+         sodipodi:cy="37.595428"
+         sodipodi:cx="24.546707"
+         id="path10170"
+         style="opacity:0.62566847;color:#000000;fill:url(#radialGradient10566);fill-opacity:1.0000000;fill-rule:evenodd;stroke:none;stroke-width:1.0000000;stroke-linecap:round;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4.0000000;stroke-dasharray:1.0000000 1.0000000 ;stroke-dashoffset:0.0000000;stroke-opacity:1.0000000;visibility:visible;display:inline;overflow:visible"
+         sodipodi:type="arc" />
+      <g
+         id="g10156"
+         transform="translate(-1.642857,-2.642857)">
+        <path
+           style="fill:url(#linearGradient10568);fill-rule:nonzero;stroke:none;stroke-miterlimit:4.0000000"
+           d="M 34.951289,21.954475 C 28.324780,21.954475 22.996247,27.283008 22.996247,33.909517 C 22.996247,40.536026 28.324780,45.864559 34.951289,45.864559 C 41.577799,45.864559 46.906332,40.536026 46.906332,33.909517 C 46.906332,27.283008 41.577799,21.954475 34.951289,21.954475 L 34.951289,21.954475 z M 34.951289,36.778727 C 33.380055,36.778727 32.082079,35.480751 32.082079,33.909517 C 32.082079,32.338283 33.380055,31.040307 34.951289,31.040307 C 36.522523,31.040307 37.820499,32.338283 37.820499,33.909517 C 37.820499,35.480751 36.522523,36.778727 34.951289,36.778727 z "
+           id="path3040" />
+        <path
+           style="fill:url(#linearGradient10570);fill-rule:nonzero;stroke:#808080;stroke-miterlimit:4.0000000;stroke-opacity:1.0000000"
+           d="M 34.951305,21.566644 C 28.109819,21.566644 22.608417,27.068045 22.608417,33.909532 C 22.608417,40.751018 28.109819,46.252419 34.951305,46.252419 C 41.792792,46.252419 47.294193,40.751018 47.294193,33.909532 C 47.294193,27.068045 41.792792,21.566644 34.951305,21.566644 L 34.951305,21.566644 z M 34.951305,36.871824 C 33.329097,36.871824 31.989012,35.531740 31.989012,33.909532 C 31.989012,32.287324 33.329097,30.947239 34.951305,30.947239 C 36.573513,30.947239 37.913598,32.287324 37.913598,33.909532 C 37.913598,35.531740 36.573513,36.871824 34.951305,36.871824 z "
+           id="path3049" />
+        <path
+           style="opacity:0.10999996;fill-rule:nonzero;stroke:none;stroke-miterlimit:4.0000000"
+           d="M 34.951289,28.111323 C 31.713337,28.111323 29.153095,30.746866 29.153095,33.909517 C 29.153095,37.147471 31.788638,39.707712 34.951289,39.707712 C 38.189242,39.707712 40.749484,37.072169 40.749484,33.909517 C 40.749484,30.671564 38.113940,28.111323 34.951289,28.111323 L 34.951289,28.111323 z M 34.951289,37.072169 C 33.219361,37.072169 31.788638,35.641446 31.788638,33.909517 C 31.788638,32.177589 33.219361,30.746866 34.951289,30.746866 C 36.683217,30.746866 38.113940,32.177589 38.113940,33.909517 C 38.113940,35.641446 36.683217,37.072169 34.951289,37.072169 z "
+           id="path3051" />
+        <path
+           id="path3916"
+           d="M 38.150519,22.816711 L 36.086643,30.847436 C 36.732045,31.019312 37.248181,31.418679 37.598790,31.971330 L 44.709966,27.639233 C 43.255134,25.269429 40.920193,23.525895 38.150519,22.816711 z "
+           style="fill:url(#linearGradient10572);fill-opacity:1.0000000;fill-rule:nonzero;stroke:none;stroke-miterlimit:4.0000000;stroke-opacity:1.0000000" />
+        <path
+           style="fill:url(#linearGradient10574);fill-opacity:1.0000000;fill-rule:nonzero;stroke:none;stroke-miterlimit:4.0000000;stroke-opacity:1.0000000"
+           d="M 30.911911,44.678269 L 33.629199,36.844465 C 33.000117,36.620097 32.518571,36.179639 32.214597,35.600027 L 24.771257,39.332667 C 26.026282,41.814082 28.209936,43.743724 30.911911,44.678269 z "
+           id="path4214" />
+        <path
+           sodipodi:nodetypes="cccccc"
+           id="path5264"
+           d="M 34.951287,22.548803 C 28.654207,22.548803 23.590575,27.612435 23.590575,33.909515 C 23.590575,40.206596 28.654207,45.270227 34.951287,45.270227 C 41.248368,45.270227 46.311999,40.206596 46.311999,33.909515 C 46.311999,27.612435 41.248368,22.548803 34.951287,22.548803 L 34.951287,22.548803 z "
+           style="opacity:0.54644811;fill:none;fill-rule:nonzero;stroke:url(#linearGradient10576);stroke-miterlimit:4.0000000;stroke-opacity:1.0000000" />
+        <path
+           transform="matrix(0.573842,0.000000,0.000000,0.573842,21.03068,19.61419)"
+           d="M 30.405591 24.930641 A 6.0987959 6.0987959 0 1 1  18.207999,24.930641 A 6.0987959 6.0987959 0 1 1  30.405591 24.930641 z"
+           sodipodi:ry="6.0987959"
+           sodipodi:rx="6.0987959"
+           sodipodi:cy="24.930641"
+           sodipodi:cx="24.306795"
+           id="path6026"
+           style="opacity:0.67213112;color:#000000;fill:none;fill-opacity:0.31638417;fill-rule:nonzero;stroke:url(#linearGradient10578);stroke-width:1.6215941;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4.0000000;stroke-dashoffset:0.0000000;stroke-opacity:1.0000000;visibility:visible;display:inline;overflow:visible"
+           sodipodi:type="arc" />
+        <path
+           id="path3390"
+           d="M 34.951289,23.065643 C 28.940684,23.065643 24.107415,27.898912 24.107415,33.909517 C 24.107415,39.920122 28.940684,44.753391 34.951289,44.753391 C 40.961895,44.753391 45.795164,39.920122 45.795164,33.909517 C 45.795164,27.898912 40.961895,23.065643 34.951289,23.065643 L 34.951289,23.065643 z M 34.951289,36.512047 C 33.526094,36.512047 32.348759,35.334712 32.348759,33.909517 C 32.348759,32.484322 33.526094,31.306987 34.951289,31.306987 C 36.376484,31.306987 37.553819,32.484322 37.553819,33.909517 C 37.553819,35.334712 36.376484,36.512047 34.951289,36.512047 z "
+           style="opacity:0.11428566;fill:url(#radialGradient10580);fill-opacity:1.0000000;fill-rule:nonzero;stroke:none;stroke-miterlimit:4.0000000;stroke-opacity:1.0000000" />
+      </g>
+    </g>
+  </g>
+</svg>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/install/images/icons/src/system-software-update.svg	Fri Feb 22 12:51:53 2008 -0500
@@ -0,0 +1,1378 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+<svg
+   xmlns:dc="http://purl.org/dc/elements/1.1/"
+   xmlns:cc="http://web.resource.org/cc/"
+   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+   xmlns:svg="http://www.w3.org/2000/svg"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:xlink="http://www.w3.org/1999/xlink"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   sodipodi:docname="system-software-update.svg"
+   sodipodi:docbase="/home/jimmac/src/cvs/tango-icon-theme/scalable/apps"
+   inkscape:version="0.43+devel"
+   sodipodi:version="0.32"
+   id="svg3440"
+   height="48px"
+   width="48px"
+   inkscape:export-filename="/home/jimmac/Desktop/big-software-update.png"
+   inkscape:export-xdpi="360.00000"
+   inkscape:export-ydpi="360.00000">
+  <defs
+     id="defs3">
+    <linearGradient
+       id="linearGradient264">
+      <stop
+         id="stop265"
+         offset="0.0000000"
+         style="stop-color:#000000;stop-opacity:0.50299400;" />
+      <stop
+         id="stop266"
+         offset="1.0000000"
+         style="stop-color:#000000;stop-opacity:0.0000000;" />
+    </linearGradient>
+    <linearGradient
+       y2="31.490198"
+       x2="28.783722"
+       y1="29.943159"
+       x1="28.632685"
+       gradientTransform="matrix(0.810817,0.000000,0.000000,1.233324,1.118717,-4.642761)"
+       gradientUnits="userSpaceOnUse"
+       id="linearGradient263"
+       xlink:href="#linearGradient264"
+       inkscape:collect="always" />
+    <linearGradient
+       id="linearGradient218">
+      <stop
+         id="stop219"
+         offset="0.0000000"
+         style="stop-color:#ffffff;stop-opacity:0.44910181;" />
+      <stop
+         id="stop222"
+         offset="1.0000000"
+         style="stop-color:#ffffff;stop-opacity:0.0000000;" />
+    </linearGradient>
+    <linearGradient
+       gradientUnits="userSpaceOnUse"
+       y2="22.227985"
+       x2="38.105118"
+       y1="22.227985"
+       x1="36.373066"
+       gradientTransform="matrix(1.138691,0.000000,0.000000,1.732051,-19.29901,-4.517761)"
+       id="linearGradient217"
+       xlink:href="#linearGradient218"
+       inkscape:collect="always" />
+    <linearGradient
+       id="linearGradient204">
+      <stop
+         id="stop205"
+         offset="0.0000000"
+         style="stop-color:#7a7a7a;stop-opacity:1.0000000;" />
+      <stop
+         id="stop207"
+         offset="0.19801980"
+         style="stop-color:#c5c5c5;stop-opacity:1.0000000;" />
+      <stop
+         id="stop208"
+         offset="0.59900987"
+         style="stop-color:#626262;stop-opacity:1.0000000;" />
+      <stop
+         id="stop206"
+         offset="1.0000000"
+         style="stop-color:#888888;stop-opacity:1.0000000;" />
+    </linearGradient>
+    <linearGradient
+       gradientUnits="userSpaceOnUse"
+       y2="43.915466"
+       x2="23.100046"
+       y1="38.296745"
+       x1="23.100046"
+       gradientTransform="matrix(0.983801,0.000000,0.000000,1.016466,1.118717,-3.017762)"
+       id="linearGradient203"
+       xlink:href="#linearGradient204"
+       inkscape:collect="always" />
+    <linearGradient
+       id="linearGradient178">
+      <stop
+         id="stop179"
+         offset="0.0000000"
+         style="stop-color:#ffffff;stop-opacity:0.0000000;" />
+      <stop
+         id="stop180"
+         offset="0.10827128"
+         style="stop-color:#ffffff;stop-opacity:0.70658684;" />
+      <stop
+         id="stop181"
+         offset="0.92053902"
+         style="stop-color:#ffffff;stop-opacity:0.70658684;" />
+      <stop
+         id="stop182"
+         offset="1.0000000"
+         style="stop-color:#ffffff;stop-opacity:0.0000000;" />
+    </linearGradient>
+    <linearGradient
+       y2="117.82710"
+       x2="15.343062"
+       y1="117.82710"
+       x1="1.6422368"
+       gradientTransform="matrix(2.740165,0,0,0.182471,1.118717,16.49994)"
+       gradientUnits="userSpaceOnUse"
+       id="linearGradient177"
+       xlink:href="#linearGradient178"
+       inkscape:collect="always" />
+    <linearGradient
+       gradientUnits="userSpaceOnUse"
+       y2="372.57819"
+       x2="5.0856376"
+       y1="372.57819"
+       x1="0.61210024"
+       gradientTransform="matrix(8.168597,0,0,0.228621,1.118717,-40.55063)"
+       id="linearGradient271"
+       xlink:href="#linearGradient272"
+       inkscape:collect="always" />
+    <linearGradient
+       id="linearGradient272">
+      <stop
+         id="stop273"
+         offset="0.0000000"
+         style="stop-color:#474747;stop-opacity:0.0000000;" />
+      <stop
+         id="stop275"
+         offset="0.10000000"
+         style="stop-color:#474747;stop-opacity:1.0000000;" />
+      <stop
+         id="stop276"
+         offset="0.89999998"
+         style="stop-color:#474747;stop-opacity:1.0000000;" />
+      <stop
+         id="stop274"
+         offset="1.0000000"
+         style="stop-color:#474747;stop-opacity:0.0000000;" />
+    </linearGradient>
+    <linearGradient
+       y2="372.57819"
+       x2="5.0856376"
+       y1="372.57819"
+       x1="0.61210024"
+       gradientTransform="matrix(8.168597,0.000000,0.000000,0.221210,1.118717,-41.93917)"
+       gradientUnits="userSpaceOnUse"
+       id="linearGradient283"
+       xlink:href="#linearGradient272"
+       inkscape:collect="always" />
+    <linearGradient
+       id="linearGradient158">
+      <stop
+         id="stop159"
+         offset="0.0000000"
+         style="stop-color:#686868;stop-opacity:0.0000000;" />
+      <stop
+         id="stop162"
+         offset="0.23762377"
+         style="stop-color:#686868;stop-opacity:1.0000000;" />
+      <stop
+         id="stop163"
+         offset="0.78109992"
+         style="stop-color:#686868;stop-opacity:1.0000000;" />
+      <stop
+         id="stop160"
+         offset="1.0000000"
+         style="stop-color:#686868;stop-opacity:0.0000000;" />
+    </linearGradient>
+    <linearGradient
+       y2="117.82710"
+       x2="15.343062"
+       y1="117.82710"
+       x1="1.6422368"
+       gradientTransform="matrix(2.740165,0.000000,0.000000,0.364942,1.118717,-4.017762)"
+       gradientUnits="userSpaceOnUse"
+       id="linearGradient175"
+       xlink:href="#linearGradient158"
+       inkscape:collect="always" />
+    <linearGradient
+       id="linearGradient6377">
+      <stop
+         id="stop6379"
+         offset="0.0000000"
+         style="stop-color:#e02b2b;stop-opacity:1.0000000;" />
+      <stop
+         id="stop6381"
+         offset="1.0000000"
+         style="stop-color:#e02b2b;stop-opacity:0.0000000;" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient6361">
+      <stop
+         style="stop-color:#143b68;stop-opacity:1;"
+         offset="0"
+         id="stop6363" />
+      <stop
+         style="stop-color:#143b68;stop-opacity:0;"
+         offset="1"
+         id="stop6365" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient4750">
+      <stop
+         id="stop4752"
+         offset="0"
+         style="stop-color:#ffffff;stop-opacity:1;" />
+      <stop
+         id="stop4758"
+         offset="0.37931034"
+         style="stop-color:#fefefe;stop-opacity:1.0000000;" />
+      <stop
+         id="stop4754"
+         offset="1.0000000"
+         style="stop-color:#1d1d1d;stop-opacity:1.0000000;" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient4350"
+       inkscape:collect="always">
+      <stop
+         id="stop4352"
+         offset="0"
+         style="stop-color:#ffffff;stop-opacity:1;" />
+      <stop
+         id="stop4354"
+         offset="1"
+         style="stop-color:#ffffff;stop-opacity:0;" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient4126">
+      <stop
+         id="stop4128"
+         offset="0.0000000"
+         style="stop-color:#ffffff;stop-opacity:1.0000000;" />
+      <stop
+         id="stop4130"
+         offset="1.0000000"
+         style="stop-color:#ffffff;stop-opacity:0.16494845;" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient4114"
+       inkscape:collect="always">
+      <stop
+         id="stop4116"
+         offset="0"
+         style="stop-color:#000000;stop-opacity:1;" />
+      <stop
+         id="stop4118"
+         offset="1"
+         style="stop-color:#000000;stop-opacity:0;" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient3962">
+      <stop
+         id="stop3964"
+         offset="0.0000000"
+         style="stop-color:#d3e9ff;stop-opacity:1.0000000;" />
+      <stop
+         id="stop4134"
+         offset="0.15517241"
+         style="stop-color:#d3e9ff;stop-opacity:1.0000000;" />
+      <stop
+         id="stop4346"
+         offset="0.75000000"
+         style="stop-color:#4074ae;stop-opacity:1.0000000;" />
+      <stop
+         id="stop3966"
+         offset="1.0000000"
+         style="stop-color:#36486c;stop-opacity:1.0000000;" />
+    </linearGradient>
+    <radialGradient
+       gradientUnits="userSpaceOnUse"
+       r="29.993349"
+       fy="15.716079"
+       fx="18.247644"
+       cy="15.716079"
+       cx="18.247644"
+       gradientTransform="matrix(0.674967,0.000000,0.000000,0.674981,7.864706,3.589839)"
+       id="radialGradient3968"
+       xlink:href="#linearGradient3962"
+       inkscape:collect="always" />
+    <radialGradient
+       gradientUnits="userSpaceOnUse"
+       r="12.289036"
+       fy="63.965388"
+       fx="15.115514"
+       cy="63.965388"
+       cx="15.115514"
+       gradientTransform="scale(1.64399,0.608276)"
+       id="radialGradient4120"
+       xlink:href="#linearGradient4114"
+       inkscape:collect="always" />
+    <radialGradient
+       gradientUnits="userSpaceOnUse"
+       r="43.526714"
+       fy="12.142302"
+       fx="15.601279"
+       cy="12.142302"
+       cx="15.601279"
+       gradientTransform="matrix(0.674967,0.000000,0.000000,0.674981,7.864706,3.589839)"
+       id="radialGradient4132"
+       xlink:href="#linearGradient4126"
+       inkscape:collect="always" />
+    <radialGradient
+       gradientUnits="userSpaceOnUse"
+       r="32.664848"
+       fy="10.476453"
+       fx="11.826907"
+       cy="10.476453"
+       cx="11.826907"
+       gradientTransform="scale(1.179536,0.847791)"
+       id="radialGradient4356"
+       xlink:href="#linearGradient4350"
+       inkscape:collect="always" />
+    <radialGradient
+       gradientUnits="userSpaceOnUse"
+       r="40.692665"
+       fy="17.810213"
+       fx="18.934305"
+       cy="17.486208"
+       cx="18.633780"
+       gradientTransform="scale(1.036822,0.964486)"
+       id="radialGradient4756"
+       xlink:href="#linearGradient4750"
+       inkscape:collect="always" />
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient4750"
+       id="radialGradient6261"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="scale(1.036822,0.964486)"
+       cx="18.633780"
+       cy="17.486208"
+       fx="18.934305"
+       fy="17.810213"
+       r="40.692665" />
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient4750"
+       id="radialGradient6263"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="scale(1.036822,0.964486)"
+       cx="18.633780"
+       cy="17.486208"
+       fx="18.934305"
+       fy="17.810213"
+       r="40.692665" />
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient4750"
+       id="radialGradient6265"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="scale(1.036822,0.964486)"
+       cx="18.633780"
+       cy="17.486208"
+       fx="18.934305"
+       fy="17.810213"
+       r="40.692665" />
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient4750"
+       id="radialGradient6267"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="scale(1.036822,0.964486)"
+       cx="18.633780"
+       cy="17.486208"
+       fx="18.934305"
+       fy="17.810213"
+       r="40.692665" />
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient4750"
+       id="radialGradient6269"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="scale(1.036822,0.964486)"
+       cx="18.633780"
+       cy="17.486208"
+       fx="18.934305"
+       fy="17.810213"
+       r="40.692665" />
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient4750"
+       id="radialGradient6271"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="scale(1.036822,0.964486)"
+       cx="18.633780"
+       cy="17.486208"
+       fx="18.934305"
+       fy="17.810213"
+       r="40.692665" />
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient4750"
+       id="radialGradient6273"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="scale(1.036822,0.964486)"
+       cx="18.633780"
+       cy="17.486208"
+       fx="18.934305"
+       fy="17.810213"
+       r="40.692665" />
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient4750"
+       id="radialGradient6275"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="scale(1.036822,0.964486)"
+       cx="18.633780"
+       cy="17.486208"
+       fx="18.934305"
+       fy="17.810213"
+       r="40.692665" />
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient4750"
+       id="radialGradient6277"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="scale(1.036822,0.964486)"
+       cx="18.633780"
+       cy="17.486208"
+       fx="18.934305"
+       fy="17.810213"
+       r="40.692665" />
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient4750"
+       id="radialGradient6279"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="scale(1.036822,0.964486)"
+       cx="18.633780"
+       cy="17.486208"
+       fx="18.934305"
+       fy="17.810213"
+       r="40.692665" />
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient4750"
+       id="radialGradient6281"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="scale(1.036822,0.964486)"
+       cx="18.633780"
+       cy="17.486208"
+       fx="18.934305"
+       fy="17.810213"
+       r="40.692665" />
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient4750"
+       id="radialGradient6283"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="scale(1.036822,0.964486)"
+       cx="18.633780"
+       cy="17.486208"
+       fx="18.934305"
+       fy="17.810213"
+       r="40.692665" />
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient4750"
+       id="radialGradient6285"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="scale(1.036822,0.964486)"
+       cx="18.633780"
+       cy="17.486208"
+       fx="18.934305"
+       fy="17.810213"
+       r="40.692665" />
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient4750"
+       id="radialGradient6287"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="scale(1.036822,0.964486)"
+       cx="18.633780"
+       cy="17.486208"
+       fx="18.934305"
+       fy="17.810213"
+       r="40.692665" />
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient4750"
+       id="radialGradient6289"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="scale(1.036822,0.964486)"
+       cx="18.633780"
+       cy="17.486208"
+       fx="18.934305"
+       fy="17.810213"
+       r="40.692665" />
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient4750"
+       id="radialGradient6291"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="scale(1.036822,0.964486)"
+       cx="18.633780"
+       cy="17.486208"
+       fx="18.934305"
+       fy="17.810213"
+       r="40.692665" />
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient4750"
+       id="radialGradient6293"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="scale(1.036822,0.964486)"
+       cx="18.633780"
+       cy="17.486208"
+       fx="18.934305"
+       fy="17.810213"
+       r="40.692665" />
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient4750"
+       id="radialGradient6295"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="scale(1.036822,0.964486)"
+       cx="18.633780"
+       cy="17.486208"
+       fx="18.934305"
+       fy="17.810213"
+       r="40.692665" />
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient4750"
+       id="radialGradient6297"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="scale(1.036822,0.964486)"
+       cx="18.633780"
+       cy="17.486208"
+       fx="18.934305"
+       fy="17.810213"
+       r="40.692665" />
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient4750"
+       id="radialGradient6299"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="scale(1.036822,0.964486)"
+       cx="18.633780"
+       cy="17.486208"
+       fx="18.934305"
+       fy="17.810213"
+       r="40.692665" />
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient4750"
+       id="radialGradient6301"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="scale(1.036822,0.964486)"
+       cx="18.633780"
+       cy="17.486208"
+       fx="18.934305"
+       fy="17.810213"
+       r="40.692665" />
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient4750"
+       id="radialGradient6303"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="scale(1.036822,0.964486)"
+       cx="18.633780"
+       cy="17.486208"
+       fx="18.934305"
+       fy="17.810213"
+       r="40.692665" />
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient4750"
+       id="radialGradient6305"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="scale(1.036822,0.964486)"
+       cx="18.633780"
+       cy="17.486208"
+       fx="18.934305"
+       fy="17.810213"
+       r="40.692665" />
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient4750"
+       id="radialGradient6307"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="scale(1.036822,0.964486)"
+       cx="18.633780"
+       cy="17.486208"
+       fx="18.934305"
+       fy="17.810213"
+       r="40.692665" />
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient4750"
+       id="radialGradient6309"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="scale(1.036822,0.964486)"
+       cx="18.633780"
+       cy="17.486208"
+       fx="18.934305"
+       fy="17.810213"
+       r="40.692665" />
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient4750"
+       id="radialGradient6311"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="scale(1.036822,0.964486)"
+       cx="18.633780"
+       cy="17.486208"
+       fx="18.934305"
+       fy="17.810213"
+       r="40.692665" />
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient4750"
+       id="radialGradient6313"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="scale(1.036822,0.964486)"
+       cx="18.633780"
+       cy="17.486208"
+       fx="18.934305"
+       fy="17.810213"
+       r="40.692665" />
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient4750"
+       id="radialGradient6315"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="scale(1.036822,0.964486)"
+       cx="18.633780"
+       cy="17.486208"
+       fx="18.934305"
+       fy="17.810213"
+       r="40.692665" />
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient4750"
+       id="radialGradient6317"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="scale(1.036822,0.964486)"
+       cx="18.633780"
+       cy="17.486208"
+       fx="18.934305"
+       fy="17.810213"
+       r="40.692665" />
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient4750"
+       id="radialGradient6319"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="scale(1.036822,0.964486)"
+       cx="18.633780"
+       cy="17.486208"
+       fx="18.934305"
+       fy="17.810213"
+       r="40.692665" />
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient4750"
+       id="radialGradient6321"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="scale(1.036822,0.964486)"
+       cx="18.633780"
+       cy="17.486208"
+       fx="18.934305"
+       fy="17.810213"
+       r="40.692665" />
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient4750"
+       id="radialGradient6323"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="scale(1.036822,0.964486)"
+       cx="18.633780"
+       cy="17.486208"
+       fx="18.934305"
+       fy="17.810213"
+       r="40.692665" />
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient4750"
+       id="radialGradient6325"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="scale(1.036822,0.964486)"
+       cx="18.633780"
+       cy="17.486208"
+       fx="18.934305"
+       fy="17.810213"
+       r="40.692665" />
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient4750"
+       id="radialGradient6327"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="scale(1.036822,0.964486)"
+       cx="18.633780"
+       cy="17.486208"
+       fx="18.934305"
+       fy="17.810213"
+       r="40.692665" />
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient4750"
+       id="radialGradient6329"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="scale(1.036822,0.964486)"
+       cx="18.633780"
+       cy="17.486208"
+       fx="18.934305"
+       fy="17.810213"
+       r="40.692665" />
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient4750"
+       id="radialGradient6331"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="scale(1.036822,0.964486)"
+       cx="18.633780"
+       cy="17.486208"
+       fx="18.934305"
+       fy="17.810213"
+       r="40.692665" />
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient4750"
+       id="radialGradient6333"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="scale(1.036822,0.964486)"
+       cx="18.633780"
+       cy="17.486208"
+       fx="18.934305"
+       fy="17.810213"
+       r="40.692665" />
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient4750"
+       id="radialGradient6335"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="scale(1.036822,0.964486)"
+       cx="18.633780"
+       cy="17.486208"
+       fx="18.934305"
+       fy="17.810213"
+       r="40.692665" />
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient4750"
+       id="radialGradient6337"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="scale(1.036822,0.964486)"
+       cx="18.633780"
+       cy="17.486208"
+       fx="18.934305"
+       fy="17.810213"
+       r="40.692665" />
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient4750"
+       id="radialGradient6339"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="scale(1.036822,0.964486)"
+       cx="18.633780"
+       cy="17.486208"
+       fx="18.934305"
+       fy="17.810213"
+       r="40.692665" />
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient4750"
+       id="radialGradient6341"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="scale(1.036822,0.964486)"
+       cx="18.633780"
+       cy="17.486208"
+       fx="18.934305"
+       fy="17.810213"
+       r="40.692665" />
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient4750"
+       id="radialGradient6343"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="scale(1.036822,0.964486)"
+       cx="18.633780"
+       cy="17.486208"
+       fx="18.934305"
+       fy="17.810213"
+       r="40.692665" />
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient4750"
+       id="radialGradient6345"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="scale(1.036822,0.964486)"
+       cx="18.633780"
+       cy="17.486208"
+       fx="18.934305"
+       fy="17.810213"
+       r="40.692665" />
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient4750"
+       id="radialGradient6347"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="scale(1.036822,0.964486)"
+       cx="18.633780"
+       cy="17.486208"
+       fx="18.934305"
+       fy="17.810213"
+       r="40.692665" />
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient4750"
+       id="radialGradient6349"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="scale(1.036822,0.964486)"
+       cx="18.633780"
+       cy="17.486208"
+       fx="18.934305"
+       fy="17.810213"
+       r="40.692665" />
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient4750"
+       id="radialGradient6351"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="scale(1.036822,0.964486)"
+       cx="18.633780"
+       cy="17.486208"
+       fx="18.934305"
+       fy="17.810213"
+       r="40.692665" />
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient4750"
+       id="radialGradient6353"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="scale(1.036822,0.964486)"
+       cx="18.633780"
+       cy="17.486208"
+       fx="18.934305"
+       fy="17.810213"
+       r="40.692665" />
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient4750"
+       id="radialGradient6355"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="scale(1.036822,0.964486)"
+       cx="18.633780"
+       cy="17.486208"
+       fx="18.934305"
+       fy="17.810213"
+       r="40.692665" />
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient4750"
+       id="radialGradient6357"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="scale(1.036822,0.964486)"
+       cx="18.633780"
+       cy="17.486208"
+       fx="18.934305"
+       fy="17.810213"
+       r="40.692665" />
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient4750"
+       id="radialGradient6359"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="scale(1.036822,0.964486)"
+       cx="18.633780"
+       cy="17.486208"
+       fx="18.934305"
+       fy="17.810213"
+       r="40.692665" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient6361"
+       id="linearGradient6367"
+       gradientTransform="matrix(0.950176,0.000000,0.000000,1.250550,-2.628603,-7.378111)"
+       x1="12.190513"
+       y1="12.062389"
+       x2="17.850138"
+       y2="31.674618"
+       gradientUnits="userSpaceOnUse" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient6377"
+       id="linearGradient6375"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(-0.950176,-5.364674e-17,7.060588e-17,-1.250550,51.70714,46.10410)"
+       x1="9.7568795"
+       y1="12.524661"
+       x2="17.850138"
+       y2="31.674618" />
+  </defs>
+  <sodipodi:namedview
+     inkscape:window-y="138"
+     inkscape:window-x="124"
+     inkscape:window-height="659"
+     inkscape:window-width="872"
+     inkscape:document-units="px"
+     inkscape:grid-bbox="true"
+     showgrid="true"
+     inkscape:current-layer="layer1"
+     inkscape:cy="12.601861"
+     inkscape:cx="40.499842"
+     inkscape:zoom="1"
+     inkscape:pageshadow="2"
+     inkscape:pageopacity="0.0"
+     borderopacity="0.16470588"
+     bordercolor="#666666"
+     pagecolor="#ffffff"
+     id="base"
+     inkscape:showpageshadow="false" />
+  <metadata
+     id="metadata4">
+    <rdf:RDF>
+      <cc:Work
+         rdf:about="">
+        <dc:format>image/svg+xml</dc:format>
+        <dc:type
+           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+        <dc:title>Software Update</dc:title>
+        <dc:creator>
+          <cc:Agent>
+            <dc:title>Jakub Steiner</dc:title>
+          </cc:Agent>
+        </dc:creator>
+        <dc:contributor>
+          <cc:Agent>
+            <dc:title />
+          </cc:Agent>
+        </dc:contributor>
+        <cc:license
+           rdf:resource="http://creativecommons.org/licenses/by-sa/2.0/" />
+        <dc:source>http://jimmac.musichall.cz</dc:source>
+        <dc:subject>
+          <rdf:Bag>
+            <rdf:li>network update</rdf:li>
+            <rdf:li>software</rdf:li>
+            <rdf:li>synchronize</rdf:li>
+          </rdf:Bag>
+        </dc:subject>
+      </cc:Work>
+      <cc:License
+         rdf:about="http://creativecommons.org/licenses/by-sa/2.0/">
+        <cc:permits
+           rdf:resource="http://web.resource.org/cc/Reproduction" />
+        <cc:permits
+           rdf:resource="http://web.resource.org/cc/Distribution" />
+        <cc:requires
+           rdf:resource="http://web.resource.org/cc/Notice" />
+        <cc:requires
+           rdf:resource="http://web.resource.org/cc/Attribution" />
+        <cc:permits
+           rdf:resource="http://web.resource.org/cc/DerivativeWorks" />
+        <cc:requires
+           rdf:resource="http://web.resource.org/cc/ShareAlike" />
+      </cc:License>
+    </rdf:RDF>
+  </metadata>
+  <g
+     inkscape:groupmode="layer"
+     inkscape:label="Layer 1"
+     id="layer1">
+    <rect
+       y="36.982246"
+       x="6.1187172"
+       height="4.0000000"
+       width="36.542522"
+       id="rect69"
+       style="color:#000000;fill:url(#linearGradient175);fill-opacity:1.0000000;fill-rule:nonzero;stroke:none;stroke-width:1.0000000;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4.0000000;stroke-dashoffset:0.0000000;stroke-opacity:1.0000000;marker:none;marker-start:none;marker-mid:none;marker-end:none;visibility:visible;display:block;overflow:visible" />
+    <path
+       transform="matrix(0.759089,0,0,0.877848,5.774479,4.605797)"
+       d="M 45.052803 38.908627 A 20.203051 7.4751287 0 1 1  4.6467018,38.908627 A 20.203051 7.4751287 0 1 1  45.052803 38.908627 z"
+       sodipodi:ry="7.4751287"
+       sodipodi:rx="20.203051"
+       sodipodi:cy="38.908627"
+       sodipodi:cx="24.849752"
+       id="path4112"
+       style="fill:url(#radialGradient4120);fill-opacity:1;stroke:none;stroke-opacity:1"
+       sodipodi:type="arc" />
+    <rect
+       y="39.984222"
+       x="6.1187172"
+       height="0.98959237"
+       width="36.542522"
+       id="rect255"
+       style="color:#000000;fill:url(#linearGradient283);fill-opacity:1.0000000;fill-rule:nonzero;stroke:none;stroke-width:1.0000000;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4.0000000;stroke-dashoffset:0.0000000;stroke-opacity:1.0000000;marker:none;marker-start:none;marker-mid:none;marker-end:none;visibility:visible;display:block;overflow:visible" />
+    <rect
+       y="36.017567"
+       x="6.1187172"
+       height="1.022747"
+       width="36.542522"
+       id="rect250"
+       style="color:black;fill:url(#linearGradient271);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:block;overflow:visible" />
+    <rect
+       y="37"
+       x="6.1187172"
+       height="2"
+       width="36.542522"
+       id="rect176"
+       style="color:black;fill:url(#linearGradient177);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:block;overflow:visible" />
+    <path
+       id="rect183"
+       d="M 22.584707,26.450993 C 21.801233,26.450993 21.178457,27.073767 21.178457,27.857243 L 21.178457,35.450993 L 18.115957,35.450993 C 17.332483,35.450993 16.709707,36.073767 16.709707,36.857243 L 16.709707,40.575993 C 16.709707,41.359467 17.332483,41.982246 18.115957,41.982243 L 30.303457,41.982243 C 31.086931,41.982243 31.709707,41.359464 31.709707,40.575993 L 31.709707,36.857243 C 31.709707,36.073769 31.086931,35.450993 30.303457,35.450993 L 27.709707,35.450993 L 27.709707,27.857243 C 27.709707,27.073769 27.086932,26.450993 26.303457,26.450993 L 22.584707,26.450993 z "
+       style="color:#000000;fill:url(#linearGradient203);fill-opacity:1.0000000;fill-rule:nonzero;stroke:#434343;stroke-width:1.0000000;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4.0000000;stroke-dashoffset:0.0000000;stroke-opacity:1.0000000;marker:none;marker-start:none;marker-mid:none;marker-end:none;visibility:visible;display:block;overflow:visible" />
+    <rect
+       ry="0.29955584"
+       rx="0.29955584"
+       y="32.482246"
+       x="22.118719"
+       height="3.0000000"
+       width="1.9722718"
+       id="rect209"
+       style="color:#000000;fill:url(#linearGradient217);fill-opacity:1.0000000;fill-rule:nonzero;stroke:none;stroke-width:1.0000000;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4.0000000;stroke-dashoffset:0.0000000;stroke-opacity:1.0000000;marker:none;marker-start:none;marker-mid:none;marker-end:none;visibility:visible;display:block;overflow:visible" />
+    <path
+       id="path3214"
+       d="M 37.536463,19.441939 C 37.536463,26.670720 31.676269,32.530847 24.448482,32.530847 C 17.220034,32.530847 11.360171,26.670654 11.360171,19.441939 C 11.360171,12.213491 17.220034,6.3539621 24.448482,6.3539621 C 31.676269,6.3539621 37.536463,12.213491 37.536463,19.441939 L 37.536463,19.441939 z "
+       style="fill:url(#radialGradient3968);fill-opacity:1.0000000;fill-rule:nonzero;stroke:#39396c;stroke-miterlimit:4.0000000;stroke-opacity:1.0000000;stroke-dasharray:none;stroke-width:2.0000000" />
+    <path
+       transform="matrix(0.564236,0.000000,0.000000,0.674974,14.53810,3.589842)"
+       d="M 30.708637 15.271057 A 12.929953 9.2934036 0 1 1  4.8487320,15.271057 A 12.929953 9.2934036 0 1 1  30.708637 15.271057 z"
+       sodipodi:ry="9.2934036"
+       sodipodi:rx="12.929953"
+       sodipodi:cy="15.271057"
+       sodipodi:cx="17.778685"
+       id="path4348"
+       style="opacity:0.42159382;fill:url(#radialGradient4356);fill-opacity:1.0000000;stroke:none;stroke-opacity:1.0000000"
+       sodipodi:type="arc" />
+    <path
+       sodipodi:nodetypes="cccc"
+       id="path258"
+       d="M 27.212467,32.185368 L 21.681217,32.185368 C 21.681217,32.185368 21.681217,33.872868 21.681217,34.357243 C 22.228092,32.575993 27.212467,32.185368 27.212467,32.185368 z "
+       style="color:#000000;fill:url(#linearGradient263);fill-opacity:1.0000000;fill-rule:nonzero;stroke:none;stroke-width:1.0000000;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4.0000000;stroke-dashoffset:0.0000000;stroke-opacity:1.0000000;marker:none;marker-start:none;marker-mid:none;marker-end:none;visibility:visible;display:block;overflow:visible" />
+    <g
+       transform="matrix(0.663075,0.000000,0.000000,0.663075,7.946434,3.747052)"
+       style="fill:#000000;fill-opacity:0.71345031;fill-rule:nonzero;stroke:none;stroke-miterlimit:4.0000000"
+       id="g4136">
+      <g
+         id="g4138">
+        <g
+           id="g4142">
+          <path
+             id="path4144"
+             d="M 44.071300,20.714400 C 44.071300,20.977100 44.071300,20.714400 44.071300,20.714400 L 43.526400,21.331600 C 43.192400,20.938000 42.817400,20.607000 42.436600,20.261300 L 41.600700,20.384300 L 40.837000,19.521000 L 40.837000,20.589400 L 41.491300,21.084500 L 41.926800,21.577700 L 42.508800,20.919500 C 42.655300,21.193900 42.799800,21.468300 42.945300,21.742700 L 42.945300,22.565000 L 42.290000,23.305200 L 41.090800,24.128400 L 40.182600,25.034700 L 39.600600,24.374500 L 39.891600,23.634300 L 39.310500,22.976100 L 38.329100,20.878400 L 37.493200,19.933100 L 37.274400,20.179200 L 37.602500,21.372600 L 38.219700,22.071800 C 38.572200,23.089400 38.920900,24.062000 39.383800,25.034700 C 40.101600,25.034700 40.778300,24.958500 41.491200,24.868700 L 41.491200,25.444900 L 40.619100,27.584100 L 39.819300,28.488400 L 39.165000,29.888800 C 39.165000,30.656400 39.165000,31.424000 39.165000,32.191500 L 39.383800,33.097800 L 39.020500,33.508000 L 38.219700,34.002100 L 37.383800,34.701300 L 38.075200,35.482600 L 37.129900,36.306800 L 37.311500,36.840000 L 35.893500,38.445500 L 34.949200,38.445500 L 34.149400,38.939600 L 33.639600,38.939600 L 33.639600,38.281400 L 33.422800,36.963000 C 33.141500,36.136800 32.848600,35.316500 32.550700,34.496200 C 32.550700,33.890700 32.586800,33.291100 32.623000,32.685700 L 32.987300,31.863400 L 32.477500,30.875100 L 32.514600,29.517700 L 31.823200,28.736400 L 32.168900,27.605500 L 31.606400,26.967300 L 30.624000,26.967300 L 30.296900,26.597200 L 29.315500,27.214900 L 28.916100,26.761300 L 28.006900,27.543000 C 27.389700,26.843300 26.771500,26.144100 26.153400,25.444900 L 25.426800,23.716400 L 26.081100,22.730100 L 25.717800,22.319000 L 26.516600,20.425400 C 27.172900,19.609000 27.858400,18.825800 28.551800,18.039700 L 29.788100,17.710600 L 31.169000,17.546500 L 32.114300,17.793600 L 33.459000,19.150000 L 33.931700,18.615800 L 34.585000,18.533800 L 35.821300,18.944900 L 36.766600,18.944900 L 37.420900,18.368700 L 37.711900,17.957600 L 37.056600,17.546500 L 35.965800,17.464500 C 35.663100,17.044600 35.381800,16.603200 35.022400,16.230100 L 34.658100,16.394200 L 34.512600,17.464500 L 33.858300,16.724300 L 33.713800,15.900100 L 32.987200,15.325900 L 32.695200,15.325900 L 33.422700,16.148200 L 33.131700,16.888400 L 32.550600,17.052500 L 32.913900,16.312300 L 32.258600,15.984200 L 31.678500,15.326000 L 30.586700,15.572100 L 30.442200,15.900200 L 29.787900,16.312300 L 29.424600,17.217600 L 28.516400,17.669700 L 28.116000,17.217600 L 27.680500,17.217600 L 27.680500,15.736200 L 28.625800,15.242100 L 29.352400,15.242100 L 29.205900,14.666900 L 28.625800,14.090700 L 29.606300,13.884600 L 30.151200,13.268400 L 30.586700,12.527200 L 31.387500,12.527200 L 31.168700,11.952000 L 31.678500,11.622900 L 31.678500,12.281100 L 32.768300,12.527200 L 33.858100,11.622900 L 33.931300,11.210800 L 34.875600,10.553100 C 34.533800,10.595600 34.192000,10.626800 33.858000,10.717700 L 33.858000,9.9766000 L 34.221300,9.1538000 L 33.858000,9.1538000 L 33.059600,9.8940000 L 32.840800,10.305600 L 33.059600,10.882300 L 32.695300,11.868600 L 32.114200,11.539500 L 31.606400,10.964300 L 30.805600,11.539500 L 30.514600,10.223600 L 31.895500,9.3188000 L 31.895500,8.8247000 L 32.768500,8.2490000 L 34.149400,7.9194000 L 35.094700,8.2490000 L 36.838800,8.5781000 L 36.403300,9.0713000 L 35.458000,9.0713000 L 36.403300,10.058600 L 37.129900,9.2363000 L 37.350600,8.8745000 C 37.350600,8.8745000 40.137700,11.372500 41.730500,14.105000 C 43.323300,16.838400 44.071300,20.060100 44.071300,20.714400 z " />
+        </g>
+      </g>
+      <g
+         id="g4146">
+        <g
+           id="g4150">
+          <path
+             id="path4152"
+             d="M 26.070300,9.2363000 L 25.997100,9.7295000 L 26.506900,10.058600 L 27.378000,9.4829000 L 26.942500,8.9892000 L 26.360500,9.3188000 L 26.070500,9.2363000" />
+        </g>
+      </g>
+      <g
+         id="g4154">
+        <g
+           id="g4158">
+          <path
+             id="path4160"
+             d="M 26.870100,5.8633000 L 24.979500,5.1226000 L 22.799800,5.3692000 L 20.109400,6.1094000 L 19.600600,6.6035000 L 21.272500,7.7549000 L 21.272500,8.4131000 L 20.618200,9.0713000 L 21.491200,10.800300 L 22.071300,10.470200 L 22.799800,9.3188000 C 23.922800,8.9716000 24.929700,8.5781000 25.997100,8.0844000 L 26.870100,5.8632000" />
+        </g>
+      </g>
+      <g
+         id="g4162">
+        <g
+           id="g4166">
+          <path
+             id="path4168"
+             d="M 28.833000,12.774900 L 28.542000,12.033700 L 28.032200,12.198700 L 28.178700,13.103000 L 28.833000,12.774900" />
+        </g>
+      </g>
+      <g
+         id="g4170">
+        <g
+           id="g4174">
+          <path
+             id="path4176"
+             d="M 29.123000,12.608900 L 28.977500,13.597200 L 29.777300,13.432200 L 30.358400,12.857000 L 29.849600,12.362900 C 29.678700,11.907800 29.482400,11.483000 29.268500,11.046500 L 28.833000,11.046500 L 28.833000,11.539700 L 29.123000,11.868800 L 29.123000,12.609000" />
+        </g>
+      </g>
+      <g
+         id="g4178">
+        <g
+           id="g4182">
+          <path
+             id="path4184"
+             d="M 18.365200,28.242200 L 17.783200,27.089900 L 16.692900,26.843300 L 16.111400,25.280800 L 14.657800,25.444900 L 13.422400,24.540600 L 12.113300,25.692000 L 12.113300,25.873600 C 11.717300,25.759300 11.230500,25.743700 10.877900,25.526900 L 10.586900,24.704600 L 10.586900,23.799300 L 9.7148000,23.881300 C 9.7876000,23.305100 9.8598000,22.729900 9.9331000,22.153800 L 9.4238000,22.153800 L 8.9155000,22.812000 L 8.4062000,23.058100 L 7.6791000,22.647900 L 7.6063000,21.742600 L 7.7518000,20.755300 L 8.8426000,19.933000 L 9.7147000,19.933000 L 9.8597000,19.438900 L 10.950000,19.685000 L 11.749800,20.673300 L 11.895300,19.026800 L 13.276600,17.875400 L 13.785400,16.641000 L 14.803000,16.229900 L 15.384500,15.407600 L 16.692600,15.159600 L 17.347400,14.173300 C 16.693100,14.173300 16.038800,14.173300 15.384500,14.173300 L 16.620300,13.597100 L 17.491900,13.597100 L 18.728200,13.185000 L 18.873700,12.692800 L 18.437200,12.280700 L 17.928400,12.115700 L 18.073900,11.622500 L 17.710600,10.882300 L 16.838000,11.210400 L 16.983500,10.552700 L 15.965900,9.9765000 L 15.166600,11.374400 L 15.238900,11.868500 L 14.439600,12.198600 L 13.930300,13.267900 L 13.712500,12.280600 L 12.331200,11.704400 L 12.112900,10.964200 L 13.930300,9.8939000 L 14.730100,9.1537000 L 14.802900,8.2489000 L 14.366900,8.0018000 L 13.785400,7.9193000 L 13.422100,8.8246000 C 13.422100,8.8246000 12.814200,8.9437000 12.657900,8.9823000 C 10.661800,10.821700 6.6286000,14.792400 5.6916000,22.288500 C 5.7287000,22.462300 6.3708000,23.470100 6.3708000,23.470100 L 7.8972000,24.374400 L 9.4236000,24.786500 L 10.078400,25.609700 L 11.095500,26.349900 L 11.677000,26.267900 L 12.113000,26.464200 L 12.113000,26.597000 L 11.531900,28.160000 L 11.095400,28.818200 L 11.240900,29.148300 L 10.877600,30.380700 L 12.186200,32.767400 L 13.494300,33.919700 L 14.076300,34.742000 L 14.003100,36.470500 L 14.439600,37.456800 L 14.003100,39.349400 C 14.003100,39.349400 13.968900,39.337700 14.024600,39.527100 C 14.080800,39.716600 16.353700,40.978300 16.498200,40.870900 C 16.642200,40.761500 16.765300,40.665800 16.765300,40.665800 L 16.620300,40.255600 L 17.201400,39.679400 L 17.419700,39.103200 L 18.365000,38.773100 L 19.091600,36.962600 L 18.873800,36.470400 L 19.381600,35.730200 L 20.472400,35.482200 L 21.054400,34.165800 L 20.908900,32.521300 L 21.781000,31.286900 L 21.926500,30.052500 C 20.733100,29.460700 19.549500,28.851300 18.365000,28.242000" />
+        </g>
+      </g>
+      <g
+         id="g4186">
+        <g
+           id="g4190">
+          <path
+             id="path4192"
+             d="M 16.765600,9.5649000 L 17.492200,10.058600 L 18.074200,10.058600 L 18.074200,9.4829000 L 17.347600,9.1538000 L 16.765600,9.5649000" />
+        </g>
+      </g>
+      <g
+         id="g4194">
+        <g
+           id="g4198">
+          <path
+             id="path4200"
+             d="M 14.876000,8.9072000 L 14.512200,9.8120000 L 15.239300,9.8120000 L 15.603100,8.9892000 C 15.916600,8.7675000 16.228600,8.5444000 16.547900,8.3310000 L 17.275000,8.5781000 C 17.759400,8.9072000 18.243800,9.2363000 18.728600,9.5649000 L 19.456100,8.9072000 L 18.655800,8.5781000 L 18.292000,7.8374000 L 16.911100,7.6728000 L 16.838300,7.2612000 L 16.184000,7.4262000 L 15.893600,8.0020000 L 15.529800,7.2613000 L 15.384800,7.5904000 L 15.457600,8.4132000 L 14.876000,8.9072000" />
+        </g>
+      </g>
+      <g
+         id="g4202">
+        <g
+           id="g4204"
+           style="opacity:0.75000000">
+          <path
+             d=""
+             id="path4206" />
+        </g>
+        <g
+           id="g4208">
+          <path
+             d=""
+             id="path4210" />
+        </g>
+      </g>
+      <g
+         id="g4212">
+        <g
+           id="g4214"
+           style="opacity:0.75000000">
+          <path
+             d=""
+             id="path4216" />
+        </g>
+        <g
+           id="g4218">
+          <path
+             d=""
+             id="path4220" />
+        </g>
+      </g>
+      <g
+         id="g4222">
+        <g
+           id="g4226">
+          <path
+             id="path4228"
+             d="M 17.492200,6.8496000 L 17.856000,6.5210000 L 18.583100,6.3564000 C 19.081100,6.1142000 19.581100,5.9511000 20.109500,5.7802000 L 19.819500,5.2865000 L 18.881000,5.4213000 L 18.437600,5.8632000 L 17.706600,5.9692000 L 17.056700,6.2744000 L 16.740800,6.4272000 L 16.547900,6.6855000 L 17.492200,6.8496000" />
+        </g>
+      </g>
+      <g
+         id="g4230">
+        <g
+           id="g4234">
+          <path
+             id="path4236"
+             d="M 18.728500,14.666500 L 19.165000,14.008300 L 18.510200,13.515100 L 18.728500,14.666500" />
+        </g>
+      </g>
+    </g>
+    <g
+       style="fill:#ffffff;fill-opacity:0.95906430"
+       id="g236"
+       transform="translate(9.098961e-2,-3.064632)">
+      <rect
+         ry="0.50000000"
+         rx="0.50000000"
+         y="40.000000"
+         x="20.000000"
+         height="1.0000000"
+         width="10.000000"
+         id="rect226"
+         style="color:#000000;fill-rule:nonzero;stroke:none;stroke-width:1.1400000;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4.0000000;stroke-dashoffset:0.0000000;stroke-opacity:1.0000000;marker:none;marker-start:none;marker-mid:none;marker-end:none;visibility:visible;display:block;overflow:visible" />
+      <path
+         transform="matrix(2.058824,0.000000,0.000000,2.058824,-19.49265,-43.10846)"
+         d="M 19.000000 40.625000 A 0.53125000 0.53125000 0 1 1  17.937500,40.625000 A 0.53125000 0.53125000 0 1 1  19.000000 40.625000 z"
+         sodipodi:ry="0.53125000"
+         sodipodi:rx="0.53125000"
+         sodipodi:cy="40.625000"
+         sodipodi:cx="18.468750"
+         id="path235"
+         style="color:#000000;fill-rule:nonzero;stroke:none;stroke-width:1.1400000;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4.0000000;stroke-dashoffset:0.0000000;stroke-opacity:1.0000000;marker:none;marker-start:none;marker-mid:none;marker-end:none;visibility:visible;display:block;overflow:visible"
+         sodipodi:type="arc" />
+    </g>
+    <g
+       transform="matrix(0.663075,0.000000,0.000000,0.663075,7.810068,3.610686)"
+       style="color:#000000;fill:url(#radialGradient6261);fill-opacity:1.0000000;fill-rule:nonzero;stroke:none;stroke-width:1.0179454;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4.0000000;stroke-dashoffset:0.0000000;stroke-opacity:1.0000000;marker:none;marker-start:none;marker-mid:none;marker-end:none;visibility:visible;display:inline;overflow:visible"
+       id="g3216">
+      <g
+         style="color:#000000;fill:url(#radialGradient6263);stroke-dashoffset:0.0000000;marker:none;marker-start:none;marker-mid:none;marker-end:none;visibility:visible;display:inline;overflow:visible"
+         id="g3218">
+        <g
+           style="color:#000000;fill:url(#radialGradient6267);stroke-dashoffset:0.0000000;marker:none;marker-start:none;marker-mid:none;marker-end:none;visibility:visible;display:inline;overflow:visible"
+           id="g3222">
+          <path
+             style="color:#000000;fill:url(#radialGradient6269);stroke-dashoffset:0.0000000;marker:none;marker-start:none;marker-mid:none;marker-end:none;visibility:visible;display:inline;overflow:visible"
+             id="path3224"
+             d="M 44.071300,20.714400 C 44.071300,20.977100 44.071300,20.714400 44.071300,20.714400 L 43.526400,21.331600 C 43.192400,20.938000 42.817400,20.607000 42.436600,20.261300 L 41.600700,20.384300 L 40.837000,19.521000 L 40.837000,20.589400 L 41.491300,21.084500 L 41.926800,21.577700 L 42.508800,20.919500 C 42.655300,21.193900 42.799800,21.468300 42.945300,21.742700 L 42.945300,22.565000 L 42.290000,23.305200 L 41.090800,24.128400 L 40.182600,25.034700 L 39.600600,24.374500 L 39.891600,23.634300 L 39.310500,22.976100 L 38.329100,20.878400 L 37.493200,19.933100 L 37.274400,20.179200 L 37.602500,21.372600 L 38.219700,22.071800 C 38.572200,23.089400 38.920900,24.062000 39.383800,25.034700 C 40.101600,25.034700 40.778300,24.958500 41.491200,24.868700 L 41.491200,25.444900 L 40.619100,27.584100 L 39.819300,28.488400 L 39.165000,29.888800 C 39.165000,30.656400 39.165000,31.424000 39.165000,32.191500 L 39.383800,33.097800 L 39.020500,33.508000 L 38.219700,34.002100 L 37.383800,34.701300 L 38.075200,35.482600 L 37.129900,36.306800 L 37.311500,36.840000 L 35.893500,38.445500 L 34.949200,38.445500 L 34.149400,38.939600 L 33.639600,38.939600 L 33.639600,38.281400 L 33.422800,36.963000 C 33.141500,36.136800 32.848600,35.316500 32.550700,34.496200 C 32.550700,33.890700 32.586800,33.291100 32.623000,32.685700 L 32.987300,31.863400 L 32.477500,30.875100 L 32.514600,29.517700 L 31.823200,28.736400 L 32.168900,27.605500 L 31.606400,26.967300 L 30.624000,26.967300 L 30.296900,26.597200 L 29.315500,27.214900 L 28.916100,26.761300 L 28.006900,27.543000 C 27.389700,26.843300 26.771500,26.144100 26.153400,25.444900 L 25.426800,23.716400 L 26.081100,22.730100 L 25.717800,22.319000 L 26.516600,20.425400 C 27.172900,19.609000 27.858400,18.825800 28.551800,18.039700 L 29.788100,17.710600 L 31.169000,17.546500 L 32.114300,17.793600 L 33.459000,19.150000 L 33.931700,18.615800 L 34.585000,18.533800 L 35.821300,18.944900 L 36.766600,18.944900 L 37.420900,18.368700 L 37.711900,17.957600 L 37.056600,17.546500 L 35.965800,17.464500 C 35.663100,17.044600 35.381800,16.603200 35.022400,16.230100 L 34.658100,16.394200 L 34.512600,17.464500 L 33.858300,16.724300 L 33.713800,15.900100 L 32.987200,15.325900 L 32.695200,15.325900 L 33.422700,16.148200 L 33.131700,16.888400 L 32.550600,17.052500 L 32.913900,16.312300 L 32.258600,15.984200 L 31.678500,15.326000 L 30.586700,15.572100 L 30.442200,15.900200 L 29.787900,16.312300 L 29.424600,17.217600 L 28.516400,17.669700 L 28.116000,17.217600 L 27.680500,17.217600 L 27.680500,15.736200 L 28.625800,15.242100 L 29.352400,15.242100 L 29.205900,14.666900 L 28.625800,14.090700 L 29.606300,13.884600 L 30.151200,13.268400 L 30.586700,12.527200 L 31.387500,12.527200 L 31.168700,11.952000 L 31.678500,11.622900 L 31.678500,12.281100 L 32.768300,12.527200 L 33.858100,11.622900 L 33.931300,11.210800 L 34.875600,10.553100 C 34.533800,10.595600 34.192000,10.626800 33.858000,10.717700 L 33.858000,9.9766000 L 34.221300,9.1538000 L 33.858000,9.1538000 L 33.059600,9.8940000 L 32.840800,10.305600 L 33.059600,10.882300 L 32.695300,11.868600 L 32.114200,11.539500 L 31.606400,10.964300 L 30.805600,11.539500 L 30.514600,10.223600 L 31.895500,9.3188000 L 31.895500,8.8247000 L 32.768500,8.2490000 L 34.149400,7.9194000 L 35.094700,8.2490000 L 36.838800,8.5781000 L 36.403300,9.0713000 L 35.458000,9.0713000 L 36.403300,10.058600 L 37.129900,9.2363000 L 37.350600,8.8745000 C 37.350600,8.8745000 40.137700,11.372500 41.730500,14.105000 C 43.323300,16.838400 44.071300,20.060100 44.071300,20.714400 z " />
+        </g>
+      </g>
+      <g
+         style="color:#000000;fill:url(#radialGradient6271);stroke-dashoffset:0.0000000;marker:none;marker-start:none;marker-mid:none;marker-end:none;visibility:visible;display:inline;overflow:visible"
+         id="g3226">
+        <g
+           style="color:#000000;fill:url(#radialGradient6275);stroke-dashoffset:0.0000000;marker:none;marker-start:none;marker-mid:none;marker-end:none;visibility:visible;display:inline;overflow:visible"
+           id="g3230">
+          <path
+             style="color:#000000;fill:url(#radialGradient6277);stroke-dashoffset:0.0000000;marker:none;marker-start:none;marker-mid:none;marker-end:none;visibility:visible;display:inline;overflow:visible"
+             id="path3232"
+             d="M 26.070300,9.2363000 L 25.997100,9.7295000 L 26.506900,10.058600 L 27.378000,9.4829000 L 26.942500,8.9892000 L 26.360500,9.3188000 L 26.070500,9.2363000" />
+        </g>
+      </g>
+      <g
+         style="color:#000000;fill:url(#radialGradient6279);stroke-dashoffset:0.0000000;marker:none;marker-start:none;marker-mid:none;marker-end:none;visibility:visible;display:inline;overflow:visible"
+         id="g3234">
+        <g
+           style="color:#000000;fill:url(#radialGradient6283);stroke-dashoffset:0.0000000;marker:none;marker-start:none;marker-mid:none;marker-end:none;visibility:visible;display:inline;overflow:visible"
+           id="g3238">
+          <path
+             style="color:#000000;fill:url(#radialGradient6285);stroke-dashoffset:0.0000000;marker:none;marker-start:none;marker-mid:none;marker-end:none;visibility:visible;display:inline;overflow:visible"
+             id="path3240"
+             d="M 26.870100,5.8633000 L 24.979500,5.1226000 L 22.799800,5.3692000 L 20.109400,6.1094000 L 19.600600,6.6035000 L 21.272500,7.7549000 L 21.272500,8.4131000 L 20.618200,9.0713000 L 21.491200,10.800300 L 22.071300,10.470200 L 22.799800,9.3188000 C 23.922800,8.9716000 24.929700,8.5781000 25.997100,8.0844000 L 26.870100,5.8632000" />
+        </g>
+      </g>
+      <g
+         style="color:#000000;fill:url(#radialGradient6287);stroke-dashoffset:0.0000000;marker:none;marker-start:none;marker-mid:none;marker-end:none;visibility:visible;display:inline;overflow:visible"
+         id="g3242">
+        <g
+           style="color:#000000;fill:url(#radialGradient6291);stroke-dashoffset:0.0000000;marker:none;marker-start:none;marker-mid:none;marker-end:none;visibility:visible;display:inline;overflow:visible"
+           id="g3246">
+          <path
+             style="color:#000000;fill:url(#radialGradient6293);stroke-dashoffset:0.0000000;marker:none;marker-start:none;marker-mid:none;marker-end:none;visibility:visible;display:inline;overflow:visible"
+             id="path3248"
+             d="M 28.833000,12.774900 L 28.542000,12.033700 L 28.032200,12.198700 L 28.178700,13.103000 L 28.833000,12.774900" />
+        </g>
+      </g>
+      <g
+         style="color:#000000;fill:url(#radialGradient6295);stroke-dashoffset:0.0000000;marker:none;marker-start:none;marker-mid:none;marker-end:none;visibility:visible;display:inline;overflow:visible"
+         id="g3250">
+        <g
+           style="color:#000000;fill:url(#radialGradient6299);stroke-dashoffset:0.0000000;marker:none;marker-start:none;marker-mid:none;marker-end:none;visibility:visible;display:inline;overflow:visible"
+           id="g3254">
+          <path
+             style="color:#000000;fill:url(#radialGradient6301);stroke-dashoffset:0.0000000;marker:none;marker-start:none;marker-mid:none;marker-end:none;visibility:visible;display:inline;overflow:visible"
+             id="path3256"
+             d="M 29.123000,12.608900 L 28.977500,13.597200 L 29.777300,13.432200 L 30.358400,12.857000 L 29.849600,12.362900 C 29.678700,11.907800 29.482400,11.483000 29.268500,11.046500 L 28.833000,11.046500 L 28.833000,11.539700 L 29.123000,11.868800 L 29.123000,12.609000" />
+        </g>
+      </g>
+      <g
+         style="color:#000000;fill:url(#radialGradient6303);stroke-dashoffset:0.0000000;marker:none;marker-start:none;marker-mid:none;marker-end:none;visibility:visible;display:inline;overflow:visible"
+         id="g3258">
+        <g
+           style="color:#000000;fill:url(#radialGradient6307);stroke-dashoffset:0.0000000;marker:none;marker-start:none;marker-mid:none;marker-end:none;visibility:visible;display:inline;overflow:visible"
+           id="g3262">
+          <path
+             style="color:#000000;fill:url(#radialGradient6309);stroke-dashoffset:0.0000000;marker:none;marker-start:none;marker-mid:none;marker-end:none;visibility:visible;display:inline;overflow:visible"
+             id="path3264"
+             d="M 18.365200,28.242200 L 17.783200,27.089900 L 16.692900,26.843300 L 16.111400,25.280800 L 14.657800,25.444900 L 13.422400,24.540600 L 12.113300,25.692000 L 12.113300,25.873600 C 11.717300,25.759300 11.230500,25.743700 10.877900,25.526900 L 10.586900,24.704600 L 10.586900,23.799300 L 9.7148000,23.881300 C 9.7876000,23.305100 9.8598000,22.729900 9.9331000,22.153800 L 9.4238000,22.153800 L 8.9155000,22.812000 L 8.4062000,23.058100 L 7.6791000,22.647900 L 7.6063000,21.742600 L 7.7518000,20.755300 L 8.8426000,19.933000 L 9.7147000,19.933000 L 9.8597000,19.438900 L 10.950000,19.685000 L 11.749800,20.673300 L 11.895300,19.026800 L 13.276600,17.875400 L 13.785400,16.641000 L 14.803000,16.229900 L 15.384500,15.407600 L 16.692600,15.159600 L 17.347400,14.173300 C 16.693100,14.173300 16.038800,14.173300 15.384500,14.173300 L 16.620300,13.597100 L 17.491900,13.597100 L 18.728200,13.185000 L 18.873700,12.692800 L 18.437200,12.280700 L 17.928400,12.115700 L 18.073900,11.622500 L 17.710600,10.882300 L 16.838000,11.210400 L 16.983500,10.552700 L 15.965900,9.9765000 L 15.166600,11.374400 L 15.238900,11.868500 L 14.439600,12.198600 L 13.930300,13.267900 L 13.712500,12.280600 L 12.331200,11.704400 L 12.112900,10.964200 L 13.930300,9.8939000 L 14.730100,9.1537000 L 14.802900,8.2489000 L 14.366900,8.0018000 L 13.785400,7.9193000 L 13.422100,8.8246000 C 13.422100,8.8246000 12.814200,8.9437000 12.657900,8.9823000 C 10.661800,10.821700 6.6286000,14.792400 5.6916000,22.288500 C 5.7287000,22.462300 6.3708000,23.470100 6.3708000,23.470100 L 7.8972000,24.374400 L 9.4236000,24.786500 L 10.078400,25.609700 L 11.095500,26.349900 L 11.677000,26.267900 L 12.113000,26.464200 L 12.113000,26.597000 L 11.531900,28.160000 L 11.095400,28.818200 L 11.240900,29.148300 L 10.877600,30.380700 L 12.186200,32.767400 L 13.494300,33.919700 L 14.076300,34.742000 L 14.003100,36.470500 L 14.439600,37.456800 L 14.003100,39.349400 C 14.003100,39.349400 13.968900,39.337700 14.024600,39.527100 C 14.080800,39.716600 16.353700,40.978300 16.498200,40.870900 C 16.642200,40.761500 16.765300,40.665800 16.765300,40.665800 L 16.620300,40.255600 L 17.201400,39.679400 L 17.419700,39.103200 L 18.365000,38.773100 L 19.091600,36.962600 L 18.873800,36.470400 L 19.381600,35.730200 L 20.472400,35.482200 L 21.054400,34.165800 L 20.908900,32.521300 L 21.781000,31.286900 L 21.926500,30.052500 C 20.733100,29.460700 19.549500,28.851300 18.365000,28.242000" />
+        </g>
+      </g>
+      <g
+         style="color:#000000;fill:url(#radialGradient6311);stroke-dashoffset:0.0000000;marker:none;marker-start:none;marker-mid:none;marker-end:none;visibility:visible;display:inline;overflow:visible"
+         id="g3266">
+        <g
+           style="color:#000000;fill:url(#radialGradient6315);stroke-dashoffset:0.0000000;marker:none;marker-start:none;marker-mid:none;marker-end:none;visibility:visible;display:inline;overflow:visible"
+           id="g3270">
+          <path
+             style="color:#000000;fill:url(#radialGradient6317);stroke-dashoffset:0.0000000;marker:none;marker-start:none;marker-mid:none;marker-end:none;visibility:visible;display:inline;overflow:visible"
+             id="path3272"
+             d="M 16.765600,9.5649000 L 17.492200,10.058600 L 18.074200,10.058600 L 18.074200,9.4829000 L 17.347600,9.1538000 L 16.765600,9.5649000" />
+        </g>
+      </g>
+      <g
+         style="color:#000000;fill:url(#radialGradient6319);stroke-dashoffset:0.0000000;marker:none;marker-start:none;marker-mid:none;marker-end:none;visibility:visible;display:inline;overflow:visible"
+         id="g3274">
+        <g
+           style="color:#000000;fill:url(#radialGradient6323);stroke-dashoffset:0.0000000;marker:none;marker-start:none;marker-mid:none;marker-end:none;visibility:visible;display:inline;overflow:visible"
+           id="g3278">
+          <path
+             style="color:#000000;fill:url(#radialGradient6325);stroke-dashoffset:0.0000000;marker:none;marker-start:none;marker-mid:none;marker-end:none;visibility:visible;display:inline;overflow:visible"
+             id="path3280"
+             d="M 14.876000,8.9072000 L 14.512200,9.8120000 L 15.239300,9.8120000 L 15.603100,8.9892000 C 15.916600,8.7675000 16.228600,8.5444000 16.547900,8.3310000 L 17.275000,8.5781000 C 17.759400,8.9072000 18.243800,9.2363000 18.728600,9.5649000 L 19.456100,8.9072000 L 18.655800,8.5781000 L 18.292000,7.8374000 L 16.911100,7.6728000 L 16.838300,7.2612000 L 16.184000,7.4262000 L 15.893600,8.0020000 L 15.529800,7.2613000 L 15.384800,7.5904000 L 15.457600,8.4132000 L 14.876000,8.9072000" />
+        </g>
+      </g>
+      <g
+         style="color:#000000;fill:url(#radialGradient6327);stroke-dashoffset:0.0000000;marker:none;marker-start:none;marker-mid:none;marker-end:none;visibility:visible;display:inline;overflow:visible"
+         id="g3282">
+        <g
+           id="g3284"
+           style="opacity:0.75000000;color:#000000;fill:url(#radialGradient6329);stroke-dashoffset:0.0000000;marker:none;marker-start:none;marker-mid:none;marker-end:none;visibility:visible;display:inline;overflow:visible">
+          <path
+             id="path3286"
+             style="color:#000000;fill:url(#radialGradient6331);stroke-dashoffset:0.0000000;marker:none;marker-start:none;marker-mid:none;marker-end:none;visibility:visible;display:inline;overflow:visible"
+             d="" />
+        </g>
+        <g
+           style="color:#000000;fill:url(#radialGradient6333);stroke-dashoffset:0.0000000;marker:none;marker-start:none;marker-mid:none;marker-end:none;visibility:visible;display:inline;overflow:visible"
+           id="g3288">
+          <path
+             style="color:#000000;fill:url(#radialGradient6335);stroke-dashoffset:0.0000000;marker:none;marker-start:none;marker-mid:none;marker-end:none;visibility:visible;display:inline;overflow:visible"
+             id="path3290"
+             d="" />
+        </g>
+      </g>
+      <g
+         style="color:#000000;fill:url(#radialGradient6337);stroke-dashoffset:0.0000000;marker:none;marker-start:none;marker-mid:none;marker-end:none;visibility:visible;display:inline;overflow:visible"
+         id="g3292">
+        <g
+           id="g3294"
+           style="opacity:0.75000000;color:#000000;fill:url(#radialGradient6339);stroke-dashoffset:0.0000000;marker:none;marker-start:none;marker-mid:none;marker-end:none;visibility:visible;display:inline;overflow:visible">
+          <path
+             id="path3296"
+             style="color:#000000;fill:url(#radialGradient6341);stroke-dashoffset:0.0000000;marker:none;marker-start:none;marker-mid:none;marker-end:none;visibility:visible;display:inline;overflow:visible"
+             d="" />
+        </g>
+        <g
+           style="color:#000000;fill:url(#radialGradient6343);stroke-dashoffset:0.0000000;marker:none;marker-start:none;marker-mid:none;marker-end:none;visibility:visible;display:inline;overflow:visible"
+           id="g3298">
+          <path
+             style="color:#000000;fill:url(#radialGradient6345);stroke-dashoffset:0.0000000;marker:none;marker-start:none;marker-mid:none;marker-end:none;visibility:visible;display:inline;overflow:visible"
+             id="path3300"
+             d="" />
+        </g>
+      </g>
+      <g
+         style="color:#000000;fill:url(#radialGradient6347);stroke-dashoffset:0.0000000;marker:none;marker-start:none;marker-mid:none;marker-end:none;visibility:visible;display:inline;overflow:visible"
+         id="g3302">
+        <g
+           style="color:#000000;fill:url(#radialGradient6351);stroke-dashoffset:0.0000000;marker:none;marker-start:none;marker-mid:none;marker-end:none;visibility:visible;display:inline;overflow:visible"
+           id="g3306">
+          <path
+             style="color:#000000;fill:url(#radialGradient6353);stroke-dashoffset:0.0000000;marker:none;marker-start:none;marker-mid:none;marker-end:none;visibility:visible;display:inline;overflow:visible"
+             id="path3308"
+             d="M 17.492200,6.8496000 L 17.856000,6.5210000 L 18.583100,6.3564000 C 19.081100,6.1142000 19.581100,5.9511000 20.109500,5.7802000 L 19.819500,5.2865000 L 18.881000,5.4213000 L 18.437600,5.8632000 L 17.706600,5.9692000 L 17.056700,6.2744000 L 16.740800,6.4272000 L 16.547900,6.6855000 L 17.492200,6.8496000" />
+        </g>
+      </g>
+      <g
+         style="color:#000000;fill:url(#radialGradient6355);stroke-dashoffset:0.0000000;marker:none;marker-start:none;marker-mid:none;marker-end:none;visibility:visible;display:inline;overflow:visible"
+         id="g3310">
+        <g
+           style="color:#000000;fill:url(#radialGradient6359);stroke-dashoffset:0.0000000;marker:none;marker-start:none;marker-mid:none;marker-end:none;visibility:visible;display:inline;overflow:visible"
+           id="g3314">
+          <path
+             style="color:#000000;fill:url(#radialGradient4756);stroke-dashoffset:0.0000000;marker:none;marker-start:none;marker-mid:none;marker-end:none;visibility:visible;display:inline;overflow:visible"
+             id="path3316"
+             d="M 18.728500,14.666500 L 19.165000,14.008300 L 18.510200,13.515100 L 18.728500,14.666500" />
+        </g>
+      </g>
+    </g>
+    <path
+       id="path4122"
+       d="M 36.871774,19.441963 C 36.871774,26.303627 31.309195,31.866145 24.448475,31.866145 C 17.587125,31.866145 12.024859,26.303564 12.024859,19.441963 C 12.024859,12.580614 17.587125,7.0186651 24.448475,7.0186651 C 31.309195,7.0186651 36.871774,12.580614 36.871774,19.441963 L 36.871774,19.441963 z "
+       style="fill:none;fill-opacity:1.0000000;fill-rule:nonzero;stroke:url(#radialGradient4132);stroke-miterlimit:4.0000000;stroke-opacity:1.0000000" />
+    <path
+       id="path5902"
+       d="M 5.3935749,10.941178 C 0.84819341,23.232818 9.4520542,34.433912 23.052696,34.433912 C 14.482897,34.433912 7.5108693,27.461952 7.5108693,18.892087 C 7.5108693,12.874995 11.030621,7.3515951 16.481428,4.8040746 L 0.53977192,8.6930816 L 5.3935749,10.941178 z "
+       style="fill:url(#linearGradient6367);fill-opacity:1.0000000;fill-rule:nonzero;stroke:none;stroke-miterlimit:4.0000000" />
+    <path
+       style="fill:url(#linearGradient6375);fill-opacity:1.0000000;fill-rule:nonzero;stroke:none;stroke-miterlimit:4.0000000"
+       d="M 43.684948,27.784836 C 48.230330,15.493195 39.626469,4.2921045 26.025828,4.2921045 C 34.595627,4.2921045 41.567654,11.264062 41.567654,19.833926 C 41.567654,25.851018 38.047903,31.374420 32.597096,33.921941 L 48.538752,30.032933 L 43.684948,27.784836 z "
+       id="path6369" />
+  </g>
+</svg>
Binary file install/images/icons/upgrade-disabled.png has changed
Binary file install/images/icons/upgrade.png has changed
Binary file install/images/marker.gif has changed
Binary file install/images/substages.png has changed
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/install/includes/common.php	Fri Feb 22 12:51:53 2008 -0500
@@ -0,0 +1,157 @@
+<?php
+
+/*
+ * Enano - an open-source CMS capable of wiki functions, Drupal-like sidebar blocks, and everything in between
+ * Version 1.1.1
+ * Copyright (C) 2006-2007 Dan Fuhry
+ * Installation package
+ * common.php - Installer common functions
+ *
+ * This program is Free Software; you can redistribute and/or modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.
+ *
+ * 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.
+ */
+
+// Our version number. This needs to be changed for any custom releases.
+$installer_version = array(
+  'version' => '1.1.3',
+  'type' => 'alpha'
+  // If type is set to "rc", "beta", or "alpha", optionally another version number can be issued with the key 'sub':
+  // 'sub' => '3' will produce Enano 1.1.1a3 / Enano 1.1.1 alpha 3
+);
+
+function installer_enano_version($long = false)
+{
+  global $installer_version;
+  static $keywords = array(
+    'alpha' => 'a',
+    'beta' => 'b',
+    'RC' => 'rc'
+    );
+  $v = $installer_version['version'];
+  if ( isset($installer_version['sub']) )
+  {
+    $v .= ( $short ) ? $keywords[$installer_version['type']] : " {$installer_version['type']} ";
+    $v .= $installer_version['sub'];
+  }
+  return $v;
+}
+ 
+// Determine Enano root directory
+
+if ( !defined('ENANO_ROOT') )
+{
+  $enano_root = dirname(dirname(dirname(__FILE__)));
+  if ( preg_match('#/repo$#', $enano_root) && file_exists("$enano_root/../.enanodev") )
+  {
+    $enano_root = preg_replace('#/repo$#', '', $enano_root);
+  }
+  
+  define('ENANO_ROOT', $enano_root);
+}
+
+chdir(ENANO_ROOT);
+
+// Determine our scriptPath
+if ( isset($_SERVER['REQUEST_URI']) && !defined('scriptPath') )
+{
+  // Use reverse-matching to determine where the REQUEST_URI overlaps the Enano root.
+  $requri = $_SERVER['REQUEST_URI'];
+  if ( isset($_SERVER['PATH_INFO']) && !preg_match('/index\.php$/', $_SERVER['PATH_INFO']) )
+  {
+    $requri = preg_replace(';' . preg_quote($_SERVER['PATH_INFO']) . '$;', '', $requri);
+  }
+  if ( !preg_match('/\.php$/', $requri) )
+  {
+    // user requested http://foo/enano as opposed to http://foo/enano/index.php
+    $requri .= '/index.php';
+  }
+  $sp = dirname($_SERVER['REQUEST_URI']);
+  if ( $sp == '/' || $sp == '\\' )
+  {
+    $sp = '';
+  }
+  $sp = preg_replace('#/install$#', '', $sp);
+  define('scriptPath', $sp);
+}
+
+// is Enano already installed?
+@include(ENANO_ROOT . '/config.php');
+if ( defined('ENANO_INSTALLED') && defined('ENANO_DANGEROUS') )
+{
+  $title = 'Installation locked';
+  require('includes/common.php');
+  $template->header();
+  echo '<p>The installer has detected that an installation of Enano already exists on your server. You MUST delete config.php if you wish to reinstall Enano.</p>';
+  $template->footer();
+  exit();
+}
+
+if ( !function_exists('microtime_float') )
+{
+  function microtime_float()
+  {
+    list($usec, $sec) = explode(" ", microtime());
+    return ((float)$usec + (float)$sec);
+  }
+}
+
+define('IN_ENANO_INSTALL', 1);
+
+require_once(ENANO_ROOT . '/install/includes/ui.php');
+require_once(ENANO_ROOT . '/includes/functions.php');
+require_once(ENANO_ROOT . '/includes/json.php');
+require_once(ENANO_ROOT . '/includes/constants.php');
+require_once(ENANO_ROOT . '/includes/rijndael.php');
+
+// If we have at least PHP 5, load json2
+if ( version_compare(PHP_VERSION, '5.0.0', '>=') )
+{
+  require_once(ENANO_ROOT . '/includes/json2.php');
+}
+
+strip_magic_quotes_gpc();
+
+// Build a list of available languages
+$dir = @opendir( ENANO_ROOT . '/language' );
+if ( !$dir )
+  die('CRITICAL: could not open language directory');
+
+$languages = array();
+// Use the old PHP4-compatible JSON decoder
+$json = new Services_JSON(SERVICES_JSON_LOOSE_TYPE);
+
+while ( $dh = @readdir($dir) )
+{
+  if ( $dh == '.' || $dh == '..' )
+    continue;
+  if ( file_exists( ENANO_ROOT . "/language/$dh/meta.json" ) )
+  {
+    // Found a language directory, determine metadata
+    $meta = @file_get_contents( ENANO_ROOT . "/language/$dh/meta.json" );
+    if ( empty($meta) )
+      // Could not read metadata file, continue silently
+      continue;
+    $meta = $json->decode($meta);
+    if ( isset($meta['lang_name_english']) && isset($meta['lang_name_native']) && isset($meta['lang_code']) )
+    {
+      $languages[$meta['lang_code']] = array(
+          'name' => $meta['lang_name_native'],
+          'name_eng' => $meta['lang_name_english'],
+          'dir' => $dh
+        );
+    }
+  }
+}
+
+if ( count($languages) < 1 )
+{
+  die('CRITICAL: No languages are available');
+}
+
+// List of available DB drivers
+$supported_drivers = array('mysql', 'postgresql');
+
+?>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/install/includes/js/formutils.js	Fri Feb 22 12:51:53 2008 -0500
@@ -0,0 +1,169 @@
+/**
+ * Images used for form field validation
+ * @var string img_bad: Shown on field validation failure
+ * @var string img_good: Shown on field validation success
+ * @var string img_neu: Shown when a field's value matches known good regexp but still needs testing (e.g. DB info)
+ */
+
+var img_bad = '../images/checkbad.png';
+var img_good = '../images/check.png';
+var img_neu = '../images/checkunk.png';
+
+/**
+ * Highlights the background of the next-up <tr> tag.
+ * @param object Form field
+ */
+
+function set_focus(item)
+{
+  var hint_id = ( item.type == 'radio' ) ? 'hint_' + item.name + '_' + item.value : 'hint_' + item.name;
+  if ( document.getElementById(hint_id) )
+  {
+    var el = document.getElementById(hint_id);
+    el.style.zIndex = String(getHighestZ() + 2);
+    domObjChangeOpac(0, el);
+    el.style.display = 'block';
+    domOpacity(el, 0, 100, 400);
+  }
+  item = getParentTR(item);
+  if ( item.tagName == 'TR' )
+  {
+    item.style.backgroundColor = '#FFFFE0';
+  }
+}
+
+/**
+ * Clears the background of the next-up <tr> tag.
+ * @param object Form field
+ */
+
+function clear_focus(item)
+{
+  var hint_id = ( item.type == 'radio' ) ? 'hint_' + item.name + '_' + item.value : 'hint_' + item.name;
+  if ( document.getElementById(hint_id) )
+  {
+    var el = document.getElementById(hint_id);
+    // el.style.display = 'none';
+    domOpacity(el, 100, 0, 200);
+    setTimeout(function()
+      {
+        el.style.display = 'none';
+      }, 250);
+  }
+  item = getParentTR(item);
+  if ( item.tagName == 'TR' )
+  {
+    if ( IE )
+    {
+      item.style.backgroundColor = 'transparent';
+    }
+    else
+    {
+      item.style.backgroundColor = null;
+    }
+  }
+}
+
+function getParentTR(item)
+{
+  var tagName = item.tagName;
+  while ( tagName != 'TR' && tagName != null )
+  {
+    item = item.parentNode;
+    tagName = item.tagName;
+  }
+  if ( tagName == 'TR' && item.className != 'nohighlight' )
+  {
+    return item;
+  }
+  return null;
+}
+
+function init_hint(input, hint)
+{
+  hint.className = 'fieldtip_js';
+  setTimeout(function()
+    {
+      if ( input.type == 'radio' )
+      {
+        var tr = getParentTR(input).parentNode.parentNode.parentNode;
+        var span_width = $(tr).Width() - 24;
+      }
+      else
+      {
+        var span_width = $(input).Width() - 24;
+      }
+      var span_top = $(input).Top() + $(input).Height();
+      var span_left = $(input).Left();
+      hint.style.top = span_top + 'px';
+      hint.style.left = span_left + 'px';
+      hint.style.width = span_width + 'px';
+      hint.style.display = 'none';
+    }, 100);
+}
+
+var set_inputs_to_highlight = function()
+{
+  var inputs = document.getElementsByTagName('input');
+  for ( var i = 0; i < inputs.length; i++ )
+  {
+    // Highlighting
+    var tr = getParentTR(inputs[i]);
+    if ( tr )
+    {
+      inputs[i].onfocus = function()
+      {
+        set_focus(this);
+      }
+      inputs[i].onblur = function()
+      {
+        clear_focus(this);
+      }
+    }
+    // Hints
+    var hint_id = ( inputs[i].type == 'radio' ) ? 'hint_' + inputs[i].name + '_' + inputs[i].value : 'hint_' + inputs[i].name;
+    if ( document.getElementById(hint_id) )
+    {
+      var el = document.getElementById(hint_id);
+      if ( el.tagName == 'SPAN' )
+      {
+        init_hint(inputs[i], el);
+      }
+    }
+  }
+}
+
+addOnloadHook(set_inputs_to_highlight);
+
+function install_set_ajax_loading()
+{
+  var base = document.getElementById('enano-body');
+  var hider = document.createElement('div');
+  hider.style.position = 'absolute';
+  hider.style.backgroundColor = '#FFFFFF';
+  hider.style.top = $(base).Top() + 'px';
+  hider.style.left = $(base).Left() + 'px';
+  hider.style.width = $(base).Width() + 'px';
+  hider.style.height = $(base).Height() + 'px';
+  hider.style.backgroundPosition = 'center center';
+  hider.style.backgroundImage = 'url(../images/loading-big.gif)';
+  hider.style.backgroundRepeat = 'no-repeat';
+  hider.id = 'ajax_loader';
+  domObjChangeOpac(0, hider);
+  var body = document.getElementsByTagName('body')[0];
+  body.appendChild(hider);
+  opacity('ajax_loader', 0, 70, 750);
+}
+
+function install_unset_ajax_loading()
+{
+  if ( document.getElementById('ajax_loader') )
+  {
+    opacity('ajax_loader', 70, 0, 750);
+    setTimeout(function()
+      {
+        var body = document.getElementsByTagName('body')[0];
+        body.removeChild(document.getElementById('ajax_loader'));
+      }, 1000);
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/install/includes/libenanoinstall.php	Fri Feb 22 12:51:53 2008 -0500
@@ -0,0 +1,119 @@
+<?php
+
+/*
+ * Enano - an open-source CMS capable of wiki functions, Drupal-like sidebar blocks, and everything in between
+ * Version 1.1.1
+ * Copyright (C) 2006-2007 Dan Fuhry
+ * Installation package
+ * libenanoinstall.php - Installation payload backend
+ *
+ * This program is Free Software; you can redistribute and/or modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.
+ *
+ * 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.
+ */
+
+$neutral_color = 'C';
+
+function run_installer_stage($stage_id, $stage_name, $function, $failure_explanation, $allow_skip = true)
+{
+  static $resumed = false;
+  static $resume_stack = array();
+  
+  if ( empty($resume_stack) && isset($_POST['resume_stack']) && preg_match('/[a-z_]+((\|[a-z_]+)+)/', $_POST['resume_stack']) )
+  {
+    $resume_stack = explode('|', $_POST['resume_stack']);
+  }
+  
+  $already_run = false;
+  if ( in_array($stage_id, $resume_stack) )
+  {
+    $already_run = true;
+  }
+  
+  if ( !$resumed )
+  {
+    if ( !isset($_GET['sub']) )
+      $resumed = true;
+    if ( isset($_GET['sub']) && $_GET['sub'] == $stage_id )
+    {
+      $resumed = true;
+    }
+  }
+  if ( !$resumed && $allow_skip )
+  {
+    echo_stage_success($stage_id, $stage_name);
+    return false;
+  }
+  if ( !function_exists($function) )
+    die('libenanoinstall: CRITICAL: function "' . $function . '" for ' . $stage_id . ' doesn\'t exist');
+  $result = @call_user_func($function, false, $already_run);
+  if ( $result )
+  {
+    echo_stage_success($stage_id, $stage_name);
+    $resume_stack[] = $stage_id;
+    return true;
+  }
+  else
+  {
+    echo_stage_failure($stage_id, $stage_name, $failure_explanation, $resume_stack);
+    return false;
+  }
+}
+
+function start_install_table()
+{
+  echo '<table border="0" cellspacing="0" cellpadding="0" style="margin-top: 10px;">' . "\n";
+}
+
+function close_install_table()
+{
+  echo '</table>' . "\n\n";
+  flush();
+}
+
+function echo_stage_success($stage_id, $stage_name)
+{
+  global $neutral_color;
+  $neutral_color = ( $neutral_color == 'A' ) ? 'C' : 'A';
+  echo '<tr><td style="width: 500px; background-color: #' . "{$neutral_color}{$neutral_color}FF{$neutral_color}{$neutral_color}" . '; padding: 0 5px;">' . htmlspecialchars($stage_name) . '</td><td style="padding: 0 5px;"><img alt="Done" src="../images/check.png" /></td></tr>' . "\n";
+  flush();
+}
+
+function echo_stage_failure($stage_id, $stage_name, $failure_explanation, $resume_stack)
+{
+  global $neutral_color;
+  global $lang;
+  
+  $neutral_color = ( $neutral_color == 'A' ) ? 'C' : 'A';
+  echo '<tr><td style="width: 500px; background-color: #' . "FF{$neutral_color}{$neutral_color}{$neutral_color}{$neutral_color}" . '; padding: 0 5px;">' . htmlspecialchars($stage_name) . '</td><td style="padding: 0 5px;"><img alt="Failed" src="../images/checkbad.png" /></td></tr>' . "\n";
+  flush();
+  close_install_table();
+  $post_data = '';
+  $mysql_error = mysql_error();
+  foreach ( $_POST as $key => $value )
+  {
+    // FIXME: These should really also be sanitized for double quotes
+    $value = htmlspecialchars($value);
+    $key = htmlspecialchars($key);
+    $post_data .= "          <input type=\"hidden\" name=\"$key\" value=\"$value\" />\n";
+  }
+  if ( $stage_id == 'renameconfig' )
+    echo '<p>' . $failure_explanation . '</p>';
+  else
+    echo '<form action="install.php?stage=install&amp;sub=' . $stage_id . '" method="post">
+            ' . $post_data . '
+            <input type="hidden" name="resume_stack" value="' . htmlspecialchars(implode('|', $resume_stack)) . '" />
+            <h3>' . $lang->get('meta_msg_err_stagefailed_title') . '</h3>
+             <p>' . $failure_explanation . '</p>
+             ' . ( !empty($mysql_error) ? "<p>" . $lang->get('meta_msg_err_stagefailed_mysqlerror') . " $mysql_error</p>" : '' ) . '
+             <p>' . $lang->get('meta_msg_err_stagefailed_body') . '</p>
+             <p style="text-align: center;"><input type="submit" value="' . $lang->get('meta_btn_retry_installation') . '" /></p>
+          </form>';
+  global $ui;
+  $ui->show_footer();
+  exit;
+}
+
+?>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/install/includes/payload.php	Fri Feb 22 12:51:53 2008 -0500
@@ -0,0 +1,423 @@
+<?php
+
+/*
+ * Enano - an open-source CMS capable of wiki functions, Drupal-like sidebar blocks, and everything in between
+ * Version 1.1.1
+ * Copyright (C) 2006-2007 Dan Fuhry
+ * Installation package
+ * payload.php - Installer payload (the installation logic)
+ *
+ * This program is Free Software; you can redistribute and/or modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.
+ *
+ * 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.
+ */
+
+if ( !defined('IN_ENANO_INSTALL') )
+  die();
+
+return true;
+
+function stg_sim_good()
+{
+  return true;
+}
+
+function stg_sim_bad()
+{
+  return true;
+}
+
+function stg_password_decode()
+{
+  global $db;
+  static $pass = false;
+  
+  if ( $pass )
+    return $pass;
+  
+  if ( !isset($_POST['crypt_data']) && !empty($_POST['password']) && $_POST['password'] === $_POST['password_confirm'] )
+    $pass = $_POST['password'];
+  
+  $aes = AESCrypt::singleton(AES_BITS, AES_BLOCKSIZE);
+  // retrieve encryption key
+  $q = $db->sql_query('SELECT config_value FROM ' . table_prefix . 'config WHERE config_name=\'install_aes_key\';');
+  if ( !$q )
+    $db->_die();
+  if ( $db->numrows() < 1 )
+    return false;
+  list($aes_key) = $db->fetchrow_num();
+  $aes_key = $aes->hextostring($aes_key);
+  
+  $pass = $aes->decrypt($_POST['crypt_data'], $aes_key, ENC_HEX);
+  if ( !$pass )
+    return false;
+  
+  return $pass; // Will be true if the password isn't crapped
+}
+
+function stg_make_private_key()
+{
+  global $db;
+  static $site_key = false;
+  
+  if ( $site_key )
+    return $site_key;
+  
+  // Is there already a key cached in the database?
+  $q = $db->sql_query('SELECT config_value FROM ' . table_prefix . 'config WHERE config_name=\'site_aes_key\';');
+  if ( !$q )
+    $db->_die();
+  
+  if ( $db->numrows() > 0 )
+  {
+    list($site_key) = $db->fetchrow_num();
+    $db->free_result();
+    return $site_key;
+  }
+  
+  $aes = AESCrypt::singleton(AES_BITS, AES_BLOCKSIZE);
+  // This will use /dev/urandom if possible
+  $site_key = $aes->gen_readymade_key();
+  
+  // Stash it in the database, don't check for errors though because we can always regenerate it
+  $db->sql_query('INSERT INTO ' . table_prefix . 'config ( config_name, config_value ) VALUES ( \'site_aes_key\', \'' . $site_key . '\' );');
+  
+  return $site_key;
+}
+
+function stg_load_schema()
+{
+  global $db, $dbdriver, $installer_version, $lang_id, $languages;
+  static $sql_parser = false;
+  
+  if ( is_object($sql_parser) )
+    return $sql_parser->parse();
+  
+  $aes = AESCrypt::singleton(AES_BITS, AES_BLOCKSIZE);
+  
+  $site_key = stg_make_private_key();
+  $site_key = $aes->hextostring($site_key);
+  $admin_pass_clean = stg_password_decode();
+  $admin_pass = $aes->encrypt($admin_pass_clean, $site_key, ENC_HEX);
+  
+  unset($admin_pass_clean); // Security
+  
+  try
+  {
+    $sql_parser = new SQL_Parser( ENANO_ROOT . "/install/schemas/{$dbdriver}_stage2.sql" );
+  }
+  catch ( Exception $e )
+  {
+    echo "<pre>$e</pre>";
+    return false;
+  }
+  
+  $wkt = ENANO_ROOT . "/language/{$languages[$lang_id]['dir']}/install/mainpage-default.wkt";
+  if ( !file_exists( $wkt ) )
+  {
+    echo '<div class="error-box">Error: could not locate wikitext for main page (' . $wkt . ')</div>';
+    return false;
+  }
+  $wkt = @file_get_contents($wkt);
+  if ( empty($wkt) )
+    return false;
+  
+  $wkt = $db->escape($wkt);
+  
+  $vars = array(
+      'TABLE_PREFIX'         => table_prefix,
+      'SITE_NAME'            => $db->escape($_POST['site_name']),
+      'SITE_DESC'            => $db->escape($_POST['site_desc']),
+      'COPYRIGHT'            => $db->escape($_POST['copyright']),
+      // FIXME: update form
+      'WIKI_MODE'            => ( isset($_POST['wiki_mode']) ? '1' : '0' ),
+      'ENABLE_CACHE'         => ( is_writable( ENANO_ROOT . '/cache/' ) ? '1' : '0' ),
+      'VERSION'              => $installer_version['version'],
+      'ADMIN_USER'           => $db->escape($_POST['username']),
+      'ADMIN_PASS'           => $admin_pass,
+      'ADMIN_EMAIL'          => $db->escape($_POST['email']),
+      'REAL_NAME'            => '', // This has always been stubbed.
+      'ADMIN_EMBED_PHP'      => strval(AUTH_DISALLOW),
+      'UNIX_TIME'            => strval(time()),
+      'MAIN_PAGE_CONTENT'    => $wkt,
+      'IP_ADDRESS'           => $db->escape($_SERVER['REMOTE_ADDR'])
+    );
+  
+  $sql_parser->assign_vars($vars);
+  return $sql_parser->parse();
+}
+
+function stg_deliver_payload()
+{
+  global $db;
+  $schema = stg_load_schema();
+  foreach ( $schema as $sql )
+  {
+    if ( !$db->sql_query($sql) )
+    {
+      echo $db->get_error();
+      return false;
+    }
+  }
+  return true;
+}
+
+function stg_write_config()
+{
+  global $dbhost, $dbuser, $dbpasswd, $dbname, $dbdriver;
+  $db_data = array(
+      'host' => str_replace("'", "\\'", $dbhost),
+      'user' => str_replace("'", "\\'", $dbuser),
+      'pass' => str_replace("'", "\\'", $dbpasswd),
+      'name' => str_replace("'", "\\'", $dbname),
+      'tp' => table_prefix,
+      'drv' => $dbdriver
+    );
+  
+  // Retrieves the existing key
+  $site_key = stg_make_private_key();
+  
+  // Determine contentPath
+  switch ( @$_POST['url_scheme'] )
+  {
+    case 'standard':
+    default:
+      $sp_append = '/index.php?title=';
+      break;
+    case 'shortened':
+      $sp_append = '/index.php/';
+      break;
+    case 'rewrite':
+      $sp_append = '/';
+      break;
+  }
+  
+  $scriptpath = scriptPath;
+  $contentpath = $scriptpath . $sp_append;
+  
+  $config_file = <<<EOF
+<?php
+
+/**
+ * Enano site configuration
+ * NOTE ON EDITING: You should almost never need to change anything in this
+ * file. The only exceptions are when your DB password/other info is changed
+ * or if you are moving your Enano installation to another directory.
+ */
+
+//
+// DATABASE INFO
+//
+
+// Database type to use, currently mysql and postgresql are supported
+\$dbdriver = '{$db_data['drv']}';
+
+// Hostname of your database server, probably localhost
+\$dbhost = '{$db_data['host']}';
+
+// Username used to connect to the database
+\$dbuser = '{$db_data['user']}';
+// Database password
+\$dbpasswd = '{$db_data['pass']}';
+
+// Name of the database
+\$dbname = '{$db_data['name']}';
+
+//
+// CONSTANTS
+//
+
+// if they're already defined, no use re-defining them
+if ( !defined('ENANO_CONSTANTS') )
+{
+  // The prefix for the tables in the database. Useful for holding more than
+  // one Enano installation in the same database.
+  define('table_prefix', '{$db_data['tp']}');
+  
+  // The path to Enano's files on your server, from the document root. If
+  // Enano is installed in your document root this will be blank; installing
+  // Enano in /enano/ will result in "/enano" here, etc.
+  define('scriptPath', '$scriptpath');
+  
+  // The authoritative prefix for pages. This should be very literal: to
+  // generate a URL on the site, the format is basically
+  // contentPath . \$page_name. This is based off of scriptPath and the URL
+  // scheme selected during installation. Pattern:
+  //
+  //    * Standard URLs:  scriptPath . '/index.php?title='
+  //    * Shortened URLs: scriptPath . '/index.php/'
+  //    * mod_rewrite:    scriptPath . '/'
+  
+  define('contentPath', '$contentpath');
+  
+  // Tell the Enano API that we're installed and that this file is complete
+  define('ENANO_INSTALLED', 'You bet!');
+  
+  define('ENANO_CONSTANTS', '');
+}
+
+// The AES encryption key used to store passwords. We have a very specific
+// reason for doing this; see the rationale at:
+//   http://docs.enanocms.org/Help:Appendix_B
+\$crypto_key = '$site_key';
+
+EOF;
+  
+  // Write config file
+  
+  $ch = @fopen ( ENANO_ROOT . '/config.new.php', 'w' );
+  if ( !$ch )
+    return false;
+  
+  fwrite($ch, $config_file);
+  fclose($ch);
+  
+  // If we are using mod_rewrite, also append any existing .htaccess
+  if ( @$_POST['url_scheme'] === 'rewrite' )
+  {
+    $hh = @fopen ( ENANO_ROOT . '/.htaccess.new', 'w' );
+    if ( !$hh )
+      return false;
+    $hhc = <<<EOF
+#
+# START ENANO RULES
+#
+
+# Enable mod_rewrite
+RewriteEngine on
+
+# Don't rewrite if the user requested a real directory or file
+RewriteCond %{REQUEST_FILENAME} !-f
+RewriteCond %{REQUEST_FILENAME} !-d
+
+# Main rule - short and sweet
+RewriteRule (.*) index.php?title=\$1 [L,QSA]
+
+EOF;
+    fwrite($hh, $hhc);
+    fclose($hh);
+  }
+  
+  return true;
+}
+
+function stg_language_setup()
+{
+  global $languages, $db;
+  global $lang_id;
+  $lang_info =& $languages[$lang_id];
+  if ( !is_array($lang_info) )
+    return false;
+  
+  // Install the language
+  // ($lang_code, $lang_name_neutral, $lang_name_local, $lang_file = false)
+  $result = install_language($lang_id, $lang_info['name_eng'], $lang_info['name'], ENANO_ROOT . "/language/{$lang_info['dir']}/core.json");
+  if ( !$result )
+    return false;
+  
+  $lang_local = new Language($lang_id);
+  $lang_local->import( ENANO_ROOT . "/language/{$lang_info['dir']}/user.json" );
+  $lang_local->import( ENANO_ROOT . "/language/{$lang_info['dir']}/tools.json" );
+  $lang_local->import( ENANO_ROOT . "/language/{$lang_info['dir']}/admin.json" );
+  
+  $q = $db->sql_query('SELECT lang_id FROM ' . table_prefix . 'language ORDER BY lang_id DESC LIMIT 1;');
+  if ( !$q )
+    $db->_die();
+  
+  list($lang_id_int) = $db->fetchrow_num();
+  $db->free_result();
+  setConfig('default_language', $lang_id_int);
+  
+  return true;
+}
+
+function stg_init_logs()
+{
+  global $db, $session, $paths, $template, $plugins; // Common objects
+  global $installer_version;
+  
+  $q = $db->sql_query('INSERT INTO ' . table_prefix . 'logs(log_type,action,time_id,date_string,author,page_text,edit_summary) VALUES(\'security\', \'install_enano\', ' . time() . ', \'' . enano_date('d M Y h:i a') . '\', \'' . $db->escape($_POST['admin_user']) . '\', \'' . $db->escape(enano_version()) . '\', \'' . $db->escape($_SERVER['REMOTE_ADDR']) . '\');');
+  if ( !$q )
+  {
+    echo '<p><tt>MySQL return: ' . $db->sql_error() . '</tt></p>';
+    return false;
+  }
+  
+  return true;
+}
+
+function stg_aes_cleanup()
+{
+  global $db, $session, $paths, $template, $plugins; // Common objects
+  $q = $db->sql_query('DELETE FROM ' . table_prefix . 'config WHERE config_name = \'install_aes_key\' OR config_name = \'site_aes_key\';');
+  if ( !$q )
+    $db->_die();
+  return true;
+}
+
+function _stg_rename_config_revert()
+{
+  if ( file_exists('./config.php') )
+  {
+    @rename('./config.php', './config.new.php');
+  }
+  
+  $handle = @fopen('./config.php.new', 'w');
+  if ( !$handle )
+    return false;
+  $contents = '<?php $cryptkey = \'' . _INSTRESUME_AES_KEYBACKUP . '\'; ?>';
+  fwrite($handle, $contents);
+  fclose($handle);
+  return true;
+}
+
+function stg_build_index()
+{
+  global $db, $session, $paths, $template, $plugins; // Common objects
+  if ( $paths->rebuild_search_index() )
+    return true;
+  return false;
+}
+
+function stg_rename_config()
+{
+  if ( !@rename(ENANO_ROOT . '/config.new.php', ENANO_ROOT . '/config.php') )
+  {
+    echo '<p>Can\'t rename config.php</p>';
+    _stg_rename_config_revert();
+    return false;
+  }
+  
+  if ( filesize(ENANO_ROOT . '/.htaccess.new') > 1 )
+  {
+    // rename/possibly concatenate .htaccess.new
+    $htaccess_base = '';
+    if ( file_exists(ENANO_ROOT . '/.htaccess') )
+      $htaccess_base .= @file_get_contents(ENANO_ROOT . '/.htaccess');
+    if ( strlen($htaccess_base) > 0 && !preg_match("/\n$/", $htaccess_base) )
+      $htaccess_base .= "\n\n";
+    $htaccess_base .= @file_get_contents(ENANO_ROOT . '/.htaccess.new');
+    if ( file_exists(ENANO_ROOT . '/.htaccess') )
+    {
+      $hh = @fopen(ENANO_ROOT . '/.htaccess', 'w');
+      if ( !$hh )
+        return false;
+      fwrite($hh, $htaccess_base);
+      fclose($hh);
+      @unlink(ENANO_ROOT . '/.htaccess.new');
+      return true;
+    }
+    else
+    {
+      return @rename(ENANO_ROOT . '/.htaccess.new', ENANO_ROOT . '/.htaccess');
+    }
+  }
+  else
+  {
+    @unlink(ENANO_ROOT . '/.htaccess.new');
+  }
+  return true;
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/install/includes/sql_parse.php	Fri Feb 22 12:51:53 2008 -0500
@@ -0,0 +1,149 @@
+<?php
+
+/*
+ * Enano - an open-source CMS capable of wiki functions, Drupal-like sidebar blocks, and everything in between
+ * Version 1.1.1
+ * Copyright (C) 2006-2007 Dan Fuhry
+ * Installation package
+ * sql_parse.php - SQL query splitter and templater
+ *
+ * This program is Free Software; you can redistribute and/or modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.
+ *
+ * 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.
+ */
+
+/**
+ * Parses a full file of SQL into individual queries. Also includes substitution (template) functions.
+ * @package Enano
+ * @subpackage Installer
+ * @author Dan Fuhry
+ */
+
+class SQL_Parser
+{
+  /**
+   * The SQL to be parsed.
+   * @var string
+   * @access private
+   */
+  
+  private $sql_string;
+  
+  /**
+   * Parsed SQL array
+   * @var array
+   * @access private
+   */
+  
+  private $sql_array;
+  
+  /**
+   * Template variables.
+   * @var array
+   * @access private
+   */
+  
+  private $tpl_strings;
+  
+  /**
+   * Constructor.
+   * @param string If this contains newlines, it will be treated as the target SQL. If not, will be treated as a filename.
+   */
+  
+  public function __construct($sql)
+  {
+    if ( strpos($sql, "\n") )
+    {
+      $this->sql_string = $sql;
+    }
+    else
+    {
+      if ( file_exists($sql) )
+      {
+        $this->sql_string = @file_get_contents($sql);
+        if ( empty($this->sql_string) )
+        {
+          throw new Exception('SQL file is blank or permissions are bad');
+        }
+      }
+      else
+      {
+        throw new Exception('SQL file doesn\'t exist');
+      }
+    }
+    $this->sql_array = false;
+    $this->tpl_strings = array();
+  }
+  
+  /**
+   * Sets template variables.
+   * @param array Associative array of template variables to assign
+   */
+  
+  public function assign_vars($vars)
+  {
+    if ( !is_array($vars) )
+      return false;
+    $this->tpl_strings = array_merge($this->tpl_strings, $vars);
+  }
+  
+  /**
+   * Internal function to parse the SQL.
+   * @access private
+   */
+  
+  private function parse_sql()
+  {
+    $this->sql_array = $this->sql_string;
+    foreach ( $this->tpl_strings as $key => $value )
+    {
+      $this->sql_array = str_replace("{{{$key}}}", $value, $this->sql_array);
+    }
+    
+    // Build an array of queries
+    $this->sql_array = explode("\n", $this->sql_array);
+    
+    foreach ( $this->sql_array as $i => $sql )
+    {
+      $query =& $this->sql_array[$i];
+      $t = trim($query);
+      if ( empty($t) || preg_match('/^(\#|--)/i', $t) )
+      {
+        unset($this->sql_array[$i]);
+        unset($query);
+      }
+    }
+    unset($query);
+    
+    $this->sql_array = array_values($this->sql_array);
+    $this->sql_array = implode("\n", $this->sql_array);
+    $this->sql_array = explode(";\n", $this->sql_array);
+    
+    foreach ( $this->sql_array as $i => $sql )
+    {
+      $query =& $this->sql_array[$i];
+      if ( substr($query, ( strlen($query) - 1 ), 1 ) != ';' )
+      {
+        $query .= ';';
+      }
+    }
+    unset($query);
+  }
+  
+  /**
+   * Returns the parsed array of SQL queries.
+   * @param bool Optional. Defaults to false. If true, a parse is performed even if it already happened.
+   * @return array
+   */
+  
+  public function parse($force_reparse = false)
+  {
+    if ( !$this->sql_array || $force_reparse )
+      $this->parse_sql();
+    return $this->sql_array;
+  }
+}
+
+?>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/install/includes/stages/confirm.php	Fri Feb 22 12:51:53 2008 -0500
@@ -0,0 +1,44 @@
+<?php
+
+/*
+ * Enano - an open-source CMS capable of wiki functions, Drupal-like sidebar blocks, and everything in between
+ * Version 1.1.1
+ * Copyright (C) 2006-2007 Dan Fuhry
+ * Installation package
+ * confirm.php - Installer installation summary/confirmation stage
+ *
+ * This program is Free Software; you can redistribute and/or modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.
+ *
+ * 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.
+ */
+
+if ( !defined('IN_ENANO_INSTALL') )
+  die();
+
+require_once( ENANO_ROOT . '/includes/constants.php' );
+
+$ui->show_header();
+?>
+           <h3><?php echo $lang->get('confirm_title'); ?></h3>
+            <p><?php echo $lang->get('confirm_body'); ?></p>
+            <p style="font-size: smaller;"><b><?php echo $lang->get('confirm_info_aes_title'); ?></b>
+               <?php echo $lang->get('confirm_info_aes_body', array('aes_bits' => AES_BITS)); ?>
+               </p>
+            <form action="install.php?stage=install" method="post" name="install_login" onsubmit="return ( verify() && submit_encrypt() );"><?php
+  foreach ( $_POST as $key => &$value )
+  {
+    if ( !preg_match('/^[a-z0-9_]+$/', $key) )
+      die('You idiot hacker...');
+    if ( $key == '_cont' )
+      continue;
+    $value_clean = str_replace(array('\\', '"', '<', '>'), array('\\\\', '\\"', '&lt;', '&gt;'), $value);
+    echo "\n              <input type=\"hidden\" name=\"$key\" value=\"$value_clean\" />";
+  }
+?>
+
+              <div style="text-align: center;">
+                <input type="submit" name="_cont" value="<?php echo $lang->get('confirm_btn_install_enano'); ?>" />
+              </div>
+            </form>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/install/includes/stages/database.php	Fri Feb 22 12:51:53 2008 -0500
@@ -0,0 +1,110 @@
+<?php
+
+/*
+ * Enano - an open-source CMS capable of wiki functions, Drupal-like sidebar blocks, and everything in between
+ * Version 1.1.1
+ * Copyright (C) 2006-2007 Dan Fuhry
+ * Installation package
+ * database.php - Installer database driver selection stage
+ *
+ * This program is Free Software; you can redistribute and/or modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.
+ *
+ * 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.
+ */
+
+if ( !defined('IN_ENANO_INSTALL') )
+  die();
+
+echo '<h3>' . $lang->get('database_driver_heading') . '</h3>';
+echo '<p>' . $lang->get('database_driver_intro') . '</p>';
+if ( @file_exists('/etc/enano-is-virt-appliance') )
+{
+  echo '<p>' . $lang->get('database_driver_msg_virt_appliance') . '</p>';
+}
+
+$mysql_disable_reason = '';
+$pgsql_disable_reason = '';
+$mysql_disable = '';
+$pgsql_disable = '';
+if ( !function_exists('mysql_connect') )
+{
+  $mysql_disable = ' disabled="disabled"';
+  $mysql_disable_reason = $lang->get('database_driver_err_no_mysql');
+}
+if ( !function_exists('pg_connect') )
+{
+  $pgsql_disable = ' disabled="disabled"';
+  $pgsql_disable_reason = $lang->get('database_driver_err_no_pgsql');
+}
+
+echo '<form action="install.php?stage=database" method="post" enctype="multipart/form-data">';
+echo '<input type="hidden" name="language" value="' . $lang_id . '" />';
+?>
+<table border="0" cellspacing="5">
+  <tr>
+    <td>
+      <?php 
+      if ( strpos($_SERVER['HTTP_USER_AGENT'], 'MSIE') ):
+      ?>
+      <input type="radio" checked="checked" name="driver" value="mysql" <?php echo $mysql_disable; ?>/>
+      <?php
+      else:
+      ?>
+      <button name="driver" value="mysql"<?php echo $mysql_disable; ?>>
+        <img src="../images/about-powered-mysql.png" />
+      </button>
+      <?php
+      endif;
+      ?>
+    </td>
+    <td<?php if ( $mysql_disable ) echo ' style="opacity: 0.5; filter: alpha(opacity=50);"'; ?>>
+      <b><?php echo $lang->get('database_driver_mysql'); ?></b><br />
+      <?php echo $lang->get('database_driver_mysql_intro'); ?>
+      <?php
+      if ( $mysql_disable )
+      {
+        echo "<br /><br /><b>$mysql_disable_reason</b>";
+      }
+      ?>
+    </td>
+  </tr>
+  <tr>
+    <td>
+      <?php
+      if ( strpos($_SERVER['HTTP_USER_AGENT'], 'MSIE') ):
+      ?>
+      <input type="radio" name="driver" value="mysql" <?php echo $pgsql_disable; ?>/>
+      <?php
+      else:
+      ?>
+      <button name="driver" value="postgresql"<?php echo $pgsql_disable; ?>>
+        <img src="../images/about-powered-pgsql.png" />
+      </button>
+      <?php
+      endif;
+      ?>
+    </td>
+    <td<?php if ( $pgsql_disable ) echo ' style="opacity: 0.5; filter: alpha(opacity=50);"'; ?>>
+      <b><?php echo $lang->get('database_driver_pgsql'); ?></b><br />
+      <?php echo $lang->get('database_driver_pgsql_intro'); ?>
+      <?php
+      if ( $pgsql_disable )
+      {
+        echo "<br /><br /><b>$pgsql_disable_reason</b>";
+      }
+      ?>
+    </td>
+  </tr>
+</table>
+
+<?php
+if ( strpos($_SERVER['HTTP_USER_AGENT'], 'MSIE') )
+{
+  echo '<div style="text-align: center;">
+          <input type="submit" />
+        </div>';
+}
+
+echo '</form>';
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/install/includes/stages/database_mysql.php	Fri Feb 22 12:51:53 2008 -0500
@@ -0,0 +1,512 @@
+<?php
+
+/*
+ * Enano - an open-source CMS capable of wiki functions, Drupal-like sidebar blocks, and everything in between
+ * Version 1.1.1
+ * Copyright (C) 2006-2007 Dan Fuhry
+ * Installation package
+ * database_mysql.php - Installer database info page, MySQL
+ *
+ * This program is Free Software; you can redistribute and/or modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.
+ *
+ * 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.
+ */
+
+if ( !defined('IN_ENANO_INSTALL') )
+  die();
+
+if ( isset($_POST['_cont']) )
+{
+  $allow_go = true;
+  // Do we have everything? If so, continue with installation.
+  foreach ( array('db_host', 'db_name', 'db_user', 'db_pass') as $field )
+  {
+    if ( empty($_POST[$field]) )
+    {
+      $allow_go = false;
+    }
+  }
+  if ( $allow_go )
+  {
+    require( ENANO_ROOT . '/install/includes/stages/database_post.php' );
+    return true;
+  }
+}
+
+if ( isset($_POST['ajax_test']) )
+{
+  // Test the database connection
+  $return = array(
+      'can_install' => false,
+      'host_good' => true,
+      'creating_user' => false,
+      'db_exist' => false,
+      'creating_db' => false,
+      'creating_db_grant' => false,
+      'root_fail' => false,
+      'version' => array(
+        'version' => 'unknown',
+        'good' => 'indeterminate'
+      ),
+      'last_error' => ''
+    );
+  
+  if ( !isset($_POST['info']) )
+    die();
+  
+  $info = $_POST['info'];
+  
+  // From here on out will be JSON responses
+  header('Content-type: application/json');
+  
+  try
+  {
+    $info = @enano_json_decode($info);
+  }
+  catch ( Zend_Json_Exception $e )
+  {
+    die(enano_json_encode(array(
+        'mode' => 'error',
+        'error' => 'Exception in JSON decoder'
+      )));
+  }
+  
+  // Try to connect as the normal user
+  $test = @mysql_connect($info['db_host'], $info['db_user'], $info['db_pass']);
+  if ( !$test )
+  {
+    $return['creating_user'] = true;
+    $return['last_error'] = mysql_error();
+    if ( strstr( $return['last_error'], 'Lost connection' ) || strstr( $return['last_error'], 'Unknown MySQL server host' ) )
+    {
+      $return['host_good'] = false;
+    }
+    // Doing that failed. If we have root credentials, test those
+    if ( !empty($info['db_root_user']) && !empty($info['db_root_pass']) )
+    {
+      // Log in with root rights and if that works, tell 'em we'll reset the password or create
+      // the account if it doesn't exist already. This is done with GRANT ALL PRIVILEGES ON enano_db.*
+      // etc etc, a little hackish but known to work with MySQL >= 4.1.
+      $test_root = @mysql_connect($info['db_host'], $info['db_root_user'], $info['db_root_pass']);
+      if ( $test_root )
+      {
+        // We logged in with root rights, assume that we have appropriate permissions.
+        // If not, well, the installation will fail. Tough on the user, but creating
+        // test databases/users is too risky.
+        
+        // Does the database exist?
+        $q = @mysql_query('USE `' . mysql_real_escape_string($info['db_name']) . '`;', $test_root);
+        if ( !$q )
+        {
+          // Nope, we'll have to create it
+          $return['creating_db'] = true;
+          $return['last_error'] = mysql_error();
+        }
+        
+        $version = mysql_get_server_info($test_root);
+        $return['version'] = array(
+          'version' => $version,
+          'good' => version_compare($version, '4.0.17', '>=')
+        );
+        
+        $return['can_install'] = ( $return['version']['good'] ) ? true : false;
+      }
+      else
+      {
+        // Well that helped. Root credentials are bad.
+        $return['creating_db'] = true;
+        $return['root_fail'] = true;
+      }
+    }
+    else
+    {
+      // No root credentials, fail out
+      $return['root_fail'] = true;
+    }
+  }
+  else
+  {
+    // We're connected; do we have permission to use the database?
+    $have_database = false;
+    $q = @mysql_query('USE `' . mysql_real_escape_string($info['db_name']) . '`;', $test);
+    if ( $q )
+    {
+      // Permissions are good and we're all connected. Perform version check...
+      $version = mysql_get_server_info($test);
+      $return['version'] = array(
+        'version' => $version,
+        'good' => version_compare($version, '4.0.17', '>=')
+      );
+      
+      $return['can_install'] = ( $return['version']['good'] ) ? true : false;
+    }
+    else
+    {
+      $return['last_error'] = mysql_error();
+      $return['creating_db'] = true;
+      
+      // We don't have permission to use the database or it doesn't exist.
+      // See if we have a root login to work with, if not then fail
+      if ( !empty($info['db_root_user']) && !empty($info['db_root_pass']) )
+      {
+        // Log in with root rights and if that works, tell 'em we'll create the database.
+        $test_root = @mysql_connect($info['db_host'], $info['db_root_user'], $info['db_root_pass']);
+        if ( $test_root )
+        {
+          // We logged in with root rights, assume that we have appropriate permissions.
+          // If not, well, the installation will fail. Tough on the user, but creating
+          // test databases/users is too risky.
+          
+          // See if the database already exists
+          $dbname = mysql_real_escape_string($info['db_name']);
+          $q = @mysql_query("SHOW DATABASES LIKE '$dbname';", $test_root);
+          if ( $q )
+          {
+            if ( mysql_num_rows($q) > 0 )
+            {
+              $return['creating_db'] = false;
+              $return['creating_db_grant'] = true;
+            }
+            @mysql_free_result($q);
+          }
+          
+          $version = mysql_get_server_info($test);
+          $return['version'] = array(
+            'version' => $version,
+            'good' => version_compare($version, '4.0.17', '>=')
+          );
+          
+          $return['can_install'] = ( $return['version']['good'] ) ? true : false;
+        }
+        else
+        {
+          // Well that helped. Root credentials are bad.
+          $return['creating_db'] = true;
+          $return['root_fail'] = true;
+        }
+      }
+      // No root credentials, fail out
+    }
+  }
+  
+  if ( isset($test) && @is_resource($test) )
+    @mysql_close($test);
+  
+  if ( isset($test_root) && @is_resource($test_root) )
+    @mysql_close($test_root);
+  
+  echo enano_json_encode($return);
+  
+  exit();
+}
+
+$ui->add_header('<script type="text/javascript" src="includes/js/formutils.js"></script>');
+$ui->show_header();
+
+?>
+
+<div style="float: right; padding: 10px 0 10px 10px;">
+  <img alt="MySQL logo" src="../images/about-powered-mysql.png" />
+</div>
+
+<p><?php echo $lang->get('dbmysql_blurb_needdb'); ?></p>
+<p><?php echo $lang->get('dbmysql_blurb_howtomysql'); ?></p>
+<?php
+if ( @file_exists('/etc/enano-is-virt-appliance') )
+{
+  echo '<p>
+          ' . $lang->get('database_vm_login_info', array( 'host' => 'localhost', 'user' => 'enano', 'pass' => 'clurichaun', 'name' => 'enano_www1' )) . '
+        </p>';
+}
+?>
+
+<script type="text/javascript">
+
+  var tested = false;
+
+  function verify(field)
+  {
+    if ( tested && !field )
+      return true;
+    tested = false;
+    if ( document.getElementById('verify_error').className != '' )
+    {
+      document.getElementById('verify_error').className = '';
+      document.getElementById('verify_error').innerHTML = '';
+    }
+    var frm = document.forms.database_info;
+    // List of fields
+    var fields = {
+      db_host: frm.db_host,
+      db_name: frm.db_name,
+      db_user: frm.db_user,
+      db_pass: frm.db_pass,
+      table_prefix: frm.table_prefix,
+      db_root_user: frm.db_root_user,
+      db_root_pass: frm.db_root_pass
+    };
+    var passed = true;
+    // Main validation
+    if ( field == fields.db_host || !field )
+    {
+      var matches = fields.db_host.value.match(/^([a-z0-9_-]+)((\.([a-z0-9_-]+))*)?$/);
+      document.getElementById('s_db_host').src = ( matches ) ? img_neu : img_bad;
+      if ( !matches )
+        passed = false;
+    }
+    if ( field == fields.db_name || !field )
+    {
+      var matches = fields.db_name.value.match(/^[A-z0-9_-]+$/);
+      document.getElementById('s_db_name').src = ( matches ) ? img_neu : img_bad;
+      if ( !matches )
+        passed = false;
+    }
+    if ( field == fields.db_user || field == fields.db_pass || !field )
+    {
+      var matches = fields.db_user.value.match(/^[A-z0-9_-]+$/);
+      document.getElementById('s_db_auth').src = ( matches ) ? img_neu : img_bad;
+      if ( !matches )
+        passed = false;
+    }
+    if ( field == fields.table_prefix || !field )
+    {
+      var matches = fields.table_prefix.value.match(/^[a-z0-9_]*$/);
+      document.getElementById('s_table_prefix').src = ( matches ) ? img_good : img_bad;
+      if ( !matches )
+        passed = false;
+    }
+    if ( field == fields.db_root_user || field == fields.db_root_pass || !field )
+    {
+      var matches = ( ( fields.db_root_user.value.match(/^[A-z0-9_-]+$/) && fields.db_root_pass.value.match(/^.+$/) ) || fields.db_root_user.value == '' );
+      document.getElementById('s_db_root').src = ( matches ) ? img_neu : img_bad;
+      if ( !matches )
+        passed = false;
+    }
+    return passed;
+  }
+  
+  function ajaxTestConnection()
+  {
+    if ( !verify() )
+    {
+      document.body.scrollTop = 0;
+      new Spry.Effect.Shake('enano-body', {duration: 750}).start();
+      document.getElementById('verify_error').className = 'error-box-mini';
+      document.getElementById('verify_error').innerHTML = $lang.get('meta_msg_err_verification');
+      return false;
+    }
+    install_set_ajax_loading();
+    
+    var frm = document.forms.database_info;
+    var connection_info = 'info=' + ajaxEscape(toJSONString({
+        db_host: frm.db_host.value,
+        db_name: frm.db_name.value,
+        db_user: frm.db_user.value,
+        db_pass: frm.db_pass.value,
+        db_root_user: frm.db_root_user.value,
+        db_root_pass: frm.db_root_pass.value
+      }));
+    
+    ajaxPost(scriptPath + '/install/install.php?stage=database', connection_info + '&driver=mysql&ajax_test=on&language=' + enano_lang_code[ENANO_LANG_ID], function()
+      {
+        if ( ajax.readyState == 4 && ajax.status == 200 )
+        {
+          setTimeout('install_unset_ajax_loading();', 750);
+          // Process response
+          var response = String(ajax.responseText + '');
+          if ( response.substr(0, 1) != '{' )
+          {
+            alert('Received an invalid JSON response from the server.');
+            return false;
+          }
+          response = parseJSON(response);
+          if ( response.mode == 'error' )
+          {
+            return false;
+          }
+          document.getElementById('e_db_host').innerHTML = '';
+          document.getElementById('e_db_name').innerHTML = '';
+          document.getElementById('e_db_auth').innerHTML = '';
+          document.getElementById('e_db_root').innerHTML = '';
+          if ( response.can_install )
+          {
+            tested = true;
+            var statuses = ['s_db_host', 's_db_name', 's_db_auth', 's_table_prefix', 's_db_root', 's_mysql_version'];
+            for ( var i in statuses )
+            {
+              var img = document.getElementById(statuses[i]);
+              if ( img )
+                img.src = img_good;
+            }
+            document.getElementById('e_mysql_version').innerHTML = $lang.get('dbmysql_msg_info_mysql_good');
+            document.getElementById('verify_error').className = 'info-box-mini';
+            document.getElementById('verify_error').innerHTML = $lang.get('dbmysql_msg_test_success');
+            if ( response.creating_db )
+            {
+              document.getElementById('e_db_name').innerHTML = $lang.get('dbmysql_msg_warn_creating_db');
+            }
+            if ( response.creating_user )
+            {
+              document.getElementById('e_db_auth').innerHTML = $lang.get('dbmysql_msg_warn_creating_user');
+            }
+          }
+          else
+          {
+            // Oh dear, oh dear, oh dear, oh dear, oh dear...
+            if ( response.creating_db )
+            {
+              document.getElementById('e_db_name').innerHTML = $lang.get('dbmysql_msg_err_mysql_dbexist', { mysql_error: response.last_error });
+              document.getElementById('s_db_name').src = img_bad;
+            }
+            if ( response.creating_user )
+            {
+              document.getElementById('e_db_auth').innerHTML = $lang.get('dbmysql_msg_err_mysql_auth', { mysql_error: response.last_error });
+              document.getElementById('s_db_auth').src = img_bad;
+            }
+            if ( !response.host_good )
+            {
+              document.getElementById('e_db_host').innerHTML = $lang.get('dbmysql_msg_err_mysql_connect', { db_host: frm.db_host.value, mysql_error: response.last_error });
+              document.getElementById('s_db_host').src = img_bad;
+            }
+          }
+        }
+      });
+  }
+
+</script>
+
+<form action="install.php?stage=database" method="post" name="database_info">
+<input type="hidden" name="language" value="<?php echo $lang_id; ?>" />
+<input type="hidden" name="driver" value="mysql" />
+
+<table border="0" cellspacing="0" cellpadding="10" width="100%">
+  <tr>
+    <td colspan="3" style="text-align: center">
+      <h3><?php echo $lang->get('dbmysql_table_title'); ?></h3>
+    </td>
+  </tr>
+  <tr>
+    <td>
+      <b><?php echo $lang->get('dbmysql_field_hostname_title'); ?></b>
+      <br /><?php echo $lang->get('dbmysql_field_hostname_body'); ?>
+      <br /><span style="color: #993300" id="e_db_host"></span>
+    </td>
+    <td>
+      <input onkeyup="verify(this);" tabindex="1" name="db_host" size="30" type="text" />
+    </td>
+    <td>
+      <img id="s_db_host" alt="Good/bad icon" src="../images/checkbad.png" />
+    </td>
+  </tr>
+  <tr>
+    <td>
+      <b><?php echo $lang->get('dbmysql_field_dbname_title'); ?></b><br />
+      <?php echo $lang->get('dbmysql_field_dbname_body'); ?><br />
+      <span style="color: #993300" id="e_db_name"></span>
+    </td>
+    <td>
+      <input onkeyup="verify(this);" tabindex="2" name="db_name" size="30" type="text" />
+    </td>
+    <td>
+      <img id="s_db_name" alt="Good/bad icon" src="../images/checkbad.png" />
+    </td>
+  </tr>
+  <tr>
+    <td>
+      <b><?php echo $lang->get('dbmysql_field_dbauth_title'); ?></b><br />
+      <?php echo $lang->get('dbmysql_field_dbauth_body'); ?><br />
+      <span style="color: #993300" id="e_db_auth"></span>
+    </td>
+    <td>
+      <input onkeyup="verify(this);" tabindex="3" name="db_user" size="30" type="text" /><br />
+      <br />
+      <input name="db_pass" tabindex="4" size="30" type="password" />
+    </td>
+    <td>
+      <img id="s_db_auth" alt="Good/bad icon" src="../images/checkbad.png" />
+    </td>
+  </tr>
+  <tr>
+    <td colspan="3" style="text-align: center">
+      <h3><?php echo $lang->get('database_heading_optionalinfo'); ?></h3>
+    </td>
+  </tr>
+  <tr>
+    <td>
+      <b><?php echo $lang->get('dbmysql_field_tableprefix_title'); ?></b><br />
+      <?php echo $lang->get('dbmysql_field_tableprefix_body'); ?>
+    </td>
+    <td>
+      <input onkeyup="verify(this);" tabindex="5" name="table_prefix" size="30" type="text" />
+    </td>
+    <td>
+      <img id="s_table_prefix" alt="Good/bad icon" src="../images/check.png" />
+    </td>
+  </tr>
+  <tr>
+    <td>
+      <b><?php echo $lang->get('dbmysql_field_rootauth_title'); ?></b><br />
+      <?php echo $lang->get('dbmysql_field_rootauth_body'); ?><br />
+      <span style="color: #993300" id="e_db_root"></span>
+    </td>
+    <td>
+      <input onkeyup="verify(this);" tabindex="6" name="db_root_user" size="30" type="text" /><br />
+      <br />
+      <input onkeyup="verify(this);" tabindex="7" name="db_root_pass" size="30" type="password" />
+    </td>
+    <td>
+      <img id="s_db_root" alt="Good/bad icon" src="../images/check.png" />
+    </td>
+  </tr>
+  <tr>
+    <td>
+      <b><?php echo $lang->get('dbmysql_field_mysqlversion_title'); ?></b>
+    </td>
+    <td id="e_mysql_version">
+      <?php echo $lang->get('dbmysql_field_mysqlversion_blurb_willbechecked'); ?>
+    </td>
+    <td>
+      <img id="s_mysql_version" alt="Good/bad icon" src="../images/checkunk.png" />
+    </td>
+  </tr>
+  <tr>
+    <td>
+      <b><?php echo $lang->get('dbmysql_field_droptables_title'); ?></b><br />
+      <?php echo $lang->get('dbmysql_field_droptables_body'); ?>
+    </td>
+    <td colspan="2">
+      <input type="checkbox" tabindex="8" name="drop_tables" id="dtcheck" />  <label for="dtcheck"><?php echo $lang->get('dbmysql_field_droptables_lbl'); ?></label>
+    </td>
+  </tr>
+  <tr>
+    <td colspan="3" style="text-align: center">
+      <input type="button" tabindex="9" value="<?php echo $lang->get('dbmysql_btn_testconnection'); ?>" onclick="ajaxTestConnection();" />
+      <div id="verify_error"></div>
+    </td>
+  </tr>
+
+</table>
+
+<table border="0">
+  <tr>
+    <td>
+      <input type="submit" tabindex="10" value="<?php echo $lang->get('meta_btn_continue'); ?>" onclick="return verify();" name="_cont" />
+    </td>
+    <td>
+      <p>
+        <span style="font-weight: bold;"><?php echo $lang->get('meta_lbl_before_continue'); ?></span><br />
+        &bull; <?php echo $lang->get('database_objective_test'); ?><br />
+        &bull; <?php echo $lang->get('database_objective_uncrypt'); ?>
+      </p>
+    </td>
+  </tr>
+</table>
+
+</form>
+
+<script type="text/javascript">
+  verify();
+</script>
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/install/includes/stages/database_post.php	Fri Feb 22 12:51:53 2008 -0500
@@ -0,0 +1,222 @@
+<?php
+
+/*
+ * Enano - an open-source CMS capable of wiki functions, Drupal-like sidebar blocks, and everything in between
+ * Version 1.1.1
+ * Copyright (C) 2006-2007 Dan Fuhry
+ * Installation package
+ * database_post.php - Database installation, stage 1
+ *
+ * This program is Free Software; you can redistribute and/or modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.
+ *
+ * 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.
+ */
+
+if ( !defined('IN_ENANO_INSTALL') )
+  die();
+
+// Start up the DBAL
+require( ENANO_ROOT . '/includes/dbal.php' );
+require( ENANO_ROOT . '/install/includes/sql_parse.php' );
+$dbal = new $driver();
+$db_host =& $_POST['db_host'];
+$db_user =& $_POST['db_user'];
+$db_pass =& $_POST['db_pass'];
+$db_name =& $_POST['db_name'];
+$db_prefix =& $_POST['table_prefix'];
+$db_root_user =& $_POST['db_root_user'];
+$db_root_pass =& $_POST['db_root_pass'];
+
+if ( !preg_match('/^[a-z0-9_]*$/', $db_prefix) )
+{
+  $ui->show_header();
+  echo '<p>That table prefix isn\'t going to work.</p>';
+  return true;
+}
+
+$result = $dbal->connect(true, $db_host, $db_user, $db_pass, $db_name);
+
+// If connection failed, we have the root login, AND we're on MySQL, try to force our way in
+if ( !$result && !empty($_POST['db_root_user']) && !empty($_POST['db_root_pass']) && $driver == 'mysql' )
+{
+  // Allow a jump / breakout
+  switch ( 'foo' ) { case 'foo':
+      
+    // Try to connect to the DB as root
+    $result_root = $dbal->connect(true, $db_host, $db_root_user, $db_root_pass, 'mysql');
+    if ( !$result_root )
+      break;
+    
+    $q = $dbal->sql_query('CREATE DATABASE IF NOT EXISTS `' . $dbal->escape($db_name) . '`;');
+    if ( !$q )
+      break;
+    
+    if ( $db_host == 'localhost' || $db_host == '127.0.0.1' )
+    {
+      $q = $dbal->sql_query('GRANT ALL PRIVILEGES ON `' . $dbal->escape($db_name) . '`.* TO \'' . $dbal->escape($db_user) . '\'@\'localhost\'' . "\n" .
+                            '  IDENTIFIED BY \'' . $dbal->escape($db_pass) . '\' WITH GRANT OPTION');
+    }
+    else
+    {
+      $q = $dbal->sql_query('GRANT ALL PRIVILEGES ON `' . $dbal->escape($db_name) . '`.* TO \'' . $dbal->escape($db_user) . '\'@\'%\'' . "\n" .
+                            '  IDENTIFIED BY \'' . $dbal->escape($db_pass) . '\' WITH GRANT OPTION');
+    }
+    
+    if ( !$q )
+      break;
+    
+    $dbal->close();
+    $result = $dbal->connect(true, $db_host, $db_user, $db_pass, $db_name);
+      
+    break;
+  }
+}
+
+$ui->show_header();
+
+if ( $result )
+{
+  // We're good, do table drop if requested
+  if ( isset($_POST['drop_tables']) )
+  {
+    global $system_table_list;
+    foreach ( $system_table_list as $table )
+    {
+      $dbal->sql_query("DROP TABLE {$db_prefix}$table");
+    }
+  }
+  // Write out a config file
+  $ch = @fopen( ENANO_ROOT . '/config.new.php', 'w' );
+  if ( !$ch )
+  {
+    ?>
+    <form action="install.php?stage=database" method="post" name="database_info">
+      <h3>Configuration file generation failed.</h3>
+      <p>Couldn't open the configuration file to write out database settings. Check your file permissions.</p>
+      <p>
+        <input type="submit" name="_cont" value="<?php echo $lang->get('database_btn_go_back'); ?>" />
+      </p>
+    </form>
+    <?php
+    return true;
+  }
+  $db_host = str_replace("'", "\\'", $db_host);
+  $db_user = str_replace("'", "\\'", $db_user);
+  $db_pass = str_replace("'", "\\'", $db_pass);
+  $db_name = str_replace("'", "\\'", $db_name);
+  $db_prefix = str_replace("'", "\\'", $db_prefix);
+  if ( !preg_match('/^[a-z0-9_]*$/', $db_prefix) )
+  {
+    echo '<p>That table prefix isn\'t going to work.</p>';
+    return true;
+  }
+  fwrite($ch, "<?php
+// Enano temporary configuration file, will be OVERWRITTEN after installation.
+
+\$dbdriver = '$driver';
+\$dbhost = '$db_host';
+\$dbname = '$db_name';
+\$dbuser = '$db_user';
+\$dbpasswd = '$db_pass';
+@define('table_prefix', '$db_prefix');
+
+@define('ENANO_INSTALL_HAVE_CONFIG', 1);
+");
+  fclose($ch);
+  // Create the config table
+  try
+  {
+    $sql_parser = new SQL_Parser( ENANO_ROOT . "/install/schemas/{$driver}_stage1.sql" );
+  }
+  catch ( Exception $e )
+  {
+    ?>
+    <h3>Can't load schema file</h3>
+    <p>The SQL schema file couldn't be loaded.</p>
+    <?php echo "<pre>$e</pre>"; ?>
+    <?php
+    return true;
+  }
+  // Check to see if the config table already exists
+  $q = $dbal->sql_query('SELECT config_name, config_value FROM ' . $db_prefix . 'config LIMIT 1;');
+  if ( !$q )
+  {
+    $sql_parser->assign_vars(array(
+        'TABLE_PREFIX' => $db_prefix
+      ));
+    $sql = $sql_parser->parse();
+    foreach ( $sql as $q )
+    {
+      if ( !$dbal->sql_query($q) )
+      {
+        ?>
+        <form action="install.php?stage=database" method="post" name="database_info">
+          <input type="hidden" name="language" value="<?php echo $lang_id; ?>" />
+          <input type="hidden" name="driver" value="<?php echo $driver; ?>" />
+          <h3><?php echo $lang->get('database_msg_sql_fail_title'); ?></h3>
+          <p><?php echo $lang->get('database_msg_sql_fail_body'); ?></p>
+          <p><?php echo $lang->get('database_msg_post_fail_desc'); ?>
+            <?php
+            echo $dbal->sql_error();
+            ?>
+          </p>
+          <p>
+            <input type="submit" name="_cont" value="<?php echo $lang->get('database_btn_go_back'); ?>" />
+          </p>
+        </form>
+        <?php
+        return true;
+      }
+    }
+  }
+  else
+  {
+    $dbal->free_result();
+    if ( !$dbal->sql_query('DELETE FROM ' . $db_prefix . 'config WHERE config_name = \'install_aes_key\';') )
+    {
+      $dbal->_die('install database_post.php trying to remove old AES installer key');
+    }
+  }
+  $dbal->close();
+  ?>
+  <form action="install.php?stage=website" method="post" name="install_db_post" onsubmit="return verify();">
+  <input type="hidden" name="language" value="<?php echo $lang_id; ?>" />
+  <?php
+  // FIXME: l10n
+  ?>
+  <h3><?php echo $lang->get('database_msg_success_title'); ?></h3>
+  <p><?php echo $lang->get('database_msg_success_body'); ?></p>
+  <p><input type="submit" name="_cont" value="<?php echo $lang->get('meta_btn_continue'); ?>" />  <?php echo $lang->get('database_msg_success_redirect'); ?></p>
+  </form>
+  <script type="text/javascript">
+    setTimeout(function()
+      {
+        var frm = document.forms.install_db_post;
+        frm.submit();
+      }, 200);
+  </script>
+  <?php
+}
+else
+{
+  // FIXME: l10n
+  ?>
+  <form action="install.php?stage=database" method="post" name="database_info">
+    <input type="hidden" name="language" value="<?php echo $lang_id; ?>" />
+    <input type="hidden" name="driver" value="<?php echo $driver; ?>" />
+    <h3><?php echo $lang->get('database_msg_post_fail_title'); ?></h3>
+    <p><?php echo $lang->get('database_msg_post_fail_body'); ?></p>
+    <p><?php echo $lang->get('database_msg_post_fail_desc'); ?>
+      <?php
+      echo $dbal->sql_error();
+      ?>
+    </p>
+    <p>
+      <input type="submit" name="_cont" value="<?php echo $lang->get('database_btn_go_back'); ?>" />
+    </p>
+  </form>
+  <?php
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/install/includes/stages/database_postgresql.php	Fri Feb 22 12:51:53 2008 -0500
@@ -0,0 +1,454 @@
+<?php
+
+/*
+ * Enano - an open-source CMS capable of wiki functions, Drupal-like sidebar blocks, and everything in between
+ * Version 1.1.1
+ * Copyright (C) 2006-2007 Dan Fuhry
+ * Installation package
+ * database_postgresql.php - Installer database info page, PostgreSQL
+ *
+ * This program is Free Software; you can redistribute and/or modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.
+ *
+ * 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.
+ */
+
+if ( !defined('IN_ENANO_INSTALL') )
+  die();
+
+if ( isset($_POST['_cont']) )
+{
+  $allow_go = true;
+  // Do we have everything? If so, continue with installation.
+  foreach ( array('db_host', 'db_name', 'db_user', 'db_pass') as $field )
+  {
+    if ( empty($_POST[$field]) )
+    {
+      $allow_go = false;
+    }
+  }
+  if ( $allow_go )
+  {
+    require( ENANO_ROOT . '/install/includes/stages/database_post.php' );
+    return true;
+  }
+}
+
+if ( isset($_POST['ajax_test']) )
+{
+  // Test the database connection
+  $return = array(
+      'can_install' => false,
+      'host_good' => true,
+      'creating_user' => false,
+      'db_exist' => false,
+      'creating_db' => false,
+      'creating_db_grant' => false,
+      'root_fail' => false,
+      'version' => array(
+        'version' => 'unknown',
+        'good' => 'indeterminate'
+      ),
+      'last_error' => ''
+    );
+  
+  if ( !isset($_POST['info']) )
+    die();
+  
+  $info = $_POST['info'];
+  
+  // From here on out will be JSON responses
+  header('Content-type: application/json');
+  
+  try
+  {
+    $info = @enano_json_decode($info);
+  }
+  catch ( Zend_Json_Exception $e )
+  {
+    die(enano_json_encode(array(
+        'mode' => 'error',
+        'error' => 'Exception in JSON decoder'
+      )));
+  }
+  
+  // Try to connect as the normal user
+  // generate connection string
+  $conn_string = "dbname = '" . addslashes($info['db_name']) . "' port = '5432' host = '" . addslashes($info['db_host']) . "' " . 
+                 "user= '" . addslashes($info['db_user']) . "' password = '" . addslashes($info['db_pass']) . "'";
+  $test = @pg_connect($conn_string);
+  if ( !$test )
+  {
+    // Connection as normal user failed. PgSQL doesn't give us an error string so
+    // just try to connect as root. If even that fails, exit with an error
+    $return['creating_user'] = true;
+    if ( !empty($info['db_root_user']) && !empty($info['db_root_pass']) )
+    {
+      $conn_string_root = "dbname = '" . addslashes($info['db_name']) . "' port = '5432' host = '" . addslashes($info['db_host']) . "' " . 
+                          "user= '" . addslashes($info['db_root_user']) . "' password = '" . addslashes($info['db_root_pass']) . "'";
+      // Attempt connection as root
+      $test_root = @pg_connect($conn_string_root);
+      if ( !$test_root )
+      {
+        $return['root_fail'] = true;
+      }
+      else
+      {
+        $return['can_install'] = true;
+      }
+    }
+  }
+  else
+  {
+    $return['can_install'] = true;
+  }
+  
+  $did_version_check = false;
+  
+  if ( isset($test) && @is_resource($test) )
+  {
+    $server_info = @pg_version($test);
+    if ( isset($server_info['server']) )
+    {
+      $did_version_check = true;
+      $return['version'] = array(
+          'version' => $server_info['server'],
+          'good' => ( version_compare($server_info['server'], '8.2.5', '>=') )
+        );
+    }
+    @pg_close($test);
+  }
+  
+  if ( isset($test_root) && @is_resource($test_root) )
+  {
+    $server_info = @pg_version($test_root);
+    if ( isset($server_info['server']) )
+    {
+      $did_version_check = true;
+      $return['version'] = array(
+          'version' => $server_info['server'],
+          'good' => ( version_compare($server_info['server'], '8.2.5', '>=') )
+        );
+    }
+    @pg_close($test_root);
+  }
+  
+  if ( !$did_version_check )
+  {
+    $return['version'] = array(
+        'version' => 'indeterminate',
+        'good' => false
+      );
+  }
+  else
+  {
+    if ( !$return['version']['good'] )
+    {
+      $return['can_install'] = false;
+    }
+  }
+  
+  echo enano_json_encode($return);
+  
+  exit();
+}
+
+$ui->add_header('<script type="text/javascript" src="includes/js/formutils.js"></script>');
+$ui->show_header();
+
+?>
+
+<script type="text/javascript">
+
+  var img_bad = '../images/checkbad.png';
+  var img_good = '../images/check.png';
+  var img_neu = '../images/checkunk.png';
+  
+  var tested = false;
+
+  function verify(field)
+  {
+    if ( tested && !field )
+      return true;
+    tested = false;
+    if ( document.getElementById('verify_error').className != '' )
+    {
+      document.getElementById('verify_error').className = '';
+      document.getElementById('verify_error').innerHTML = '';
+    }
+    var frm = document.forms.database_info;
+    // List of fields
+    var fields = {
+      db_host: frm.db_host,
+      db_name: frm.db_name,
+      db_user: frm.db_user,
+      db_pass: frm.db_pass,
+      table_prefix: frm.table_prefix,
+      db_root_user: frm.db_root_user,
+      db_root_pass: frm.db_root_pass
+    };
+    var passed = true;
+    // Main validation
+    if ( field == fields.db_host || !field )
+    {
+      var matches = fields.db_host.value.match(/^([a-z0-9_-]+)((\.([a-z0-9_-]+))*)?$/);
+      document.getElementById('s_db_host').src = ( matches ) ? img_neu : img_bad;
+      if ( !matches )
+        passed = false;
+    }
+    if ( field == fields.db_name || !field )
+    {
+      var matches = fields.db_name.value.match(/^[A-z0-9_-]+$/);
+      document.getElementById('s_db_name').src = ( matches ) ? img_neu : img_bad;
+      if ( !matches )
+        passed = false;
+    }
+    if ( field == fields.db_user || field == fields.db_pass || !field )
+    {
+      var matches = fields.db_user.value.match(/^[A-z0-9_-]+$/);
+      document.getElementById('s_db_auth').src = ( matches ) ? img_neu : img_bad;
+      if ( !matches )
+        passed = false;
+    }
+    if ( field == fields.table_prefix || !field )
+    {
+      var matches = fields.table_prefix.value.match(/^[a-z0-9_]*$/);
+      document.getElementById('s_table_prefix').src = ( matches ) ? img_good : img_bad;
+      if ( !matches )
+        passed = false;
+    }
+    if ( field == fields.db_root_user || field == fields.db_root_pass || !field )
+    {
+      var matches = ( ( fields.db_root_user.value.match(/^[A-z0-9_-]+$/) && fields.db_root_pass.value.match(/^.+$/) ) || fields.db_root_user.value == '' );
+      document.getElementById('s_db_root').src = ( matches ) ? img_neu : img_bad;
+      if ( !matches )
+        passed = false;
+    }
+    return passed;
+  }
+  
+  function ajaxTestConnection()
+  {
+    if ( !verify() )
+    {
+      document.body.scrollTop = 0;
+      new Spry.Effect.Shake('enano-body', {duration: 750}).start();
+      document.getElementById('verify_error').className = 'error-box-mini';
+      document.getElementById('verify_error').innerHTML = $lang.get('meta_msg_err_verification');
+      return false;
+    }
+    install_set_ajax_loading();
+    
+    var frm = document.forms.database_info;
+    var connection_info = 'info=' + ajaxEscape(toJSONString({
+        db_host: frm.db_host.value,
+        db_name: frm.db_name.value,
+        db_user: frm.db_user.value,
+        db_pass: frm.db_pass.value,
+        db_root_user: frm.db_root_user.value,
+        db_root_pass: frm.db_root_pass.value
+      }));
+    
+    ajaxPost(scriptPath + '/install/install.php?stage=database', connection_info + '&driver=postgresql&ajax_test=on&language=' + enano_lang_code[ENANO_LANG_ID], function()
+      {
+        if ( ajax.readyState == 4 && ajax.status == 200 )
+        {
+          setTimeout('install_unset_ajax_loading();', 750);
+          // Process response
+          var response = String(ajax.responseText + '');
+          if ( response.substr(0, 1) != '{' )
+          {
+            alert('Received an invalid JSON response from the server.');
+            return false;
+          }
+          response = parseJSON(response);
+          document.getElementById('e_db_host').innerHTML = '';
+          document.getElementById('e_db_name').innerHTML = '';
+          document.getElementById('e_db_auth').innerHTML = '';
+          document.getElementById('e_db_root').innerHTML = '';
+          if ( response.can_install )
+          {
+            tested = true;
+            var statuses = ['s_db_host', 's_db_name', 's_db_auth', 's_table_prefix', 's_db_root', 's_pgsql_version'];
+            for ( var i in statuses )
+            {
+              var img = document.getElementById(statuses[i]);
+              if ( img )
+                img.src = img_good;
+            }
+            document.getElementById('e_pgsql_version').innerHTML = $lang.get('dbpgsql_msg_info_version_good');
+            document.getElementById('verify_error').className = 'info-box-mini';
+            document.getElementById('verify_error').innerHTML = $lang.get('dbpgsql_msg_test_success');
+            if ( response.creating_db )
+            {
+              document.getElementById('e_db_name').innerHTML = $lang.get('dbpgsql_msg_warn_creating_db');
+            }
+            if ( response.creating_user )
+            {
+              document.getElementById('e_db_auth').innerHTML = $lang.get('dbpgsql_msg_warn_creating_user');
+            }
+          }
+          else
+          {
+            // Oh dear, oh dear, oh dear, oh dear, oh dear...
+            if ( response.creating_db )
+            {
+              document.getElementById('e_db_name').innerHTML = $lang.get('dbpgsql_msg_err_dbexist', { pg_error: response.last_error });
+              document.getElementById('s_db_name').src = img_bad;
+            }
+            if ( response.creating_user )
+            {
+              document.getElementById('e_db_auth').innerHTML = $lang.get('dbpgsql_msg_err_auth', { pg_error: response.last_error });
+              document.getElementById('s_db_auth').src = img_bad;
+            }
+            if ( !response.host_good )
+            {
+              document.getElementById('e_db_host').innerHTML = $lang.get('dbpgsql_msg_err_connect', { db_host: frm.db_host.value, pg_error: response.last_error });
+              document.getElementById('s_db_host').src = img_bad;
+            }
+            if ( !response.version.good )
+            {
+              document.getElementById('e_pgsql_version').innerHTML = $lang.get('dbpgsql_msg_err_version', { pg_version: response.version.version });
+              document.getElementById('s_pgsql_version').src = img_bad;
+            }
+          }
+        }
+      });
+  }
+
+</script>
+
+<form action="install.php?stage=database" method="post" name="database_info">
+<input type="hidden" name="language" value="<?php echo $lang_id; ?>" />
+<input type="hidden" name="driver" value="postgresql" />
+
+<table border="0" cellspacing="0" cellpadding="10" width="100%">
+  <tr>
+    <td colspan="3" style="text-align: center">
+      <h3><?php echo $lang->get('dbpgsql_table_title'); ?></h3>
+    </td>
+  </tr>
+  <tr>
+    <td>
+      <b><?php echo $lang->get('dbpgsql_field_hostname_title'); ?></b>
+      <br /><?php echo $lang->get('dbpgsql_field_hostname_body'); ?>
+      <br /><span style="color: #993300" id="e_db_host"></span>
+    </td>
+    <td>
+      <input onkeyup="verify(this);" tabindex="1" name="db_host" size="30" type="text" />
+    </td>
+    <td>
+      <img id="s_db_host" alt="Good/bad icon" src="../images/checkbad.png" />
+    </td>
+  </tr>
+  <tr>
+    <td>
+      <b><?php echo $lang->get('dbpgsql_field_dbname_title'); ?></b><br />
+      <?php echo $lang->get('dbpgsql_field_dbname_body'); ?><br />
+      <span style="color: #993300" id="e_db_name"></span>
+    </td>
+    <td>
+      <input onkeyup="verify(this);" tabindex="2" name="db_name" size="30" type="text" />
+    </td>
+    <td>
+      <img id="s_db_name" alt="Good/bad icon" src="../images/checkbad.png" />
+    </td>
+  </tr>
+  <tr>
+    <td>
+      <b><?php echo $lang->get('dbpgsql_field_dbauth_title'); ?></b><br />
+      <?php echo $lang->get('dbpgsql_field_dbauth_body'); ?><br />
+      <span style="color: #993300" id="e_db_auth"></span>
+    </td>
+    <td>
+      <input onkeyup="verify(this);" tabindex="3" name="db_user" size="30" type="text" /><br />
+      <br />
+      <input name="db_pass" size="30" tabindex="4" type="password" />
+    </td>
+    <td>
+      <img id="s_db_auth" alt="Good/bad icon" src="../images/checkbad.png" />
+    </td>
+  </tr>
+  <tr>
+    <td colspan="3" style="text-align: center">
+      <h3><?php echo $lang->get('database_heading_optionalinfo'); ?></h3>
+    </td>
+  </tr>
+  <tr>
+    <td>
+      <b><?php echo $lang->get('dbpgsql_field_tableprefix_title'); ?></b><br />
+      <?php echo $lang->get('dbpgsql_field_tableprefix_body'); ?>
+    </td>
+    <td>
+      <input onkeyup="verify(this);" tabindex="5" name="table_prefix" size="30" type="text" />
+    </td>
+    <td>
+      <img id="s_table_prefix" alt="Good/bad icon" src="../images/check.png" />
+    </td>
+  </tr>
+  <tr>
+    <td>
+      <b><?php echo $lang->get('dbpgsql_field_rootauth_title'); ?></b><br />
+      <?php echo $lang->get('dbpgsql_field_rootauth_body'); ?><br />
+      <span style="color: #993300" id="e_db_root"></span>
+    </td>
+    <td>
+      <input onkeyup="verify(this);" tabindex="6" name="db_root_user" size="30" type="text" /><br />
+      <br />
+      <input onkeyup="verify(this);" tabindex="7" name="db_root_pass" size="30" type="password" />
+    </td>
+    <td>
+      <img id="s_db_root" alt="Good/bad icon" src="../images/check.png" />
+    </td>
+  </tr>
+  <tr>
+    <td>
+      <b><?php echo $lang->get('dbpgsql_field_pgsqlversion_title'); ?></b>
+    </td>
+    <td id="e_pgsql_version">
+      <?php echo $lang->get('dbpgsql_field_pgsqlversion_blurb_willbechecked'); ?>
+    </td>
+    <td>
+      <img id="s_pgsql_version" alt="Good/bad icon" src="../images/checkunk.png" />
+    </td>
+  </tr>
+  <tr>
+    <td>
+      <b><?php echo $lang->get('dbpgsql_field_droptables_title'); ?></b><br />
+      <?php echo $lang->get('dbpgsql_field_droptables_body'); ?>
+    </td>
+    <td colspan="2">
+      <input type="checkbox" tabindex="8" name="drop_tables" id="dtcheck" />  <label for="dtcheck"><?php echo $lang->get('dbpgsql_field_droptables_lbl'); ?></label>
+    </td>
+  </tr>
+  <tr>
+    <td colspan="3" style="text-align: center">
+      <input type="button" value="<?php echo $lang->get('dbpgsql_btn_testconnection'); ?>" onclick="ajaxTestConnection();" />
+      <div id="verify_error"></div>
+    </td>
+  </tr>
+
+</table>
+
+<table border="0">
+  <tr>
+    <td>
+      <input type="submit" tabindex="9" value="<?php echo $lang->get('meta_btn_continue'); ?>" onclick="return verify();" name="_cont" />
+    </td>
+    <td>
+      <p>
+        <span style="font-weight: bold;"><?php echo $lang->get('meta_lbl_before_continue'); ?></span><br />
+        &bull; <?php echo $lang->get('database_objective_test'); ?><br />
+        &bull; <?php echo $lang->get('database_objective_uncrypt'); ?>
+      </p>
+    </td>
+  </tr>
+</table>
+
+</form>
+
+<script type="text/javascript">
+  verify();
+</script>
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/install/includes/stages/finish.php	Fri Feb 22 12:51:53 2008 -0500
@@ -0,0 +1,72 @@
+<?php
+
+/*
+ * Enano - an open-source CMS capable of wiki functions, Drupal-like sidebar blocks, and everything in between
+ * Version 1.1.1
+ * Copyright (C) 2006-2007 Dan Fuhry
+ * Installation package
+ * finish.php - Installer finalization stage
+ *
+ * This program is Free Software; you can redistribute and/or modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.
+ *
+ * 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.
+ */
+
+if ( !defined('IN_ENANO_INSTALL') )
+  die();
+
+require ( ENANO_ROOT . '/install/includes/libenanoinstall.php' );
+require ( ENANO_ROOT . '/install/includes/sql_parse.php' );
+require ( ENANO_ROOT . '/includes/common.php' );
+
+if ( !in_array($dbdriver, $supported_drivers) )
+{
+  $ui->show_header();
+  echo '<h3>Installation error</h3>
+         <p>ERROR: That database driver is not supported.</p>';
+  return true;
+}
+
+$ui->show_header();
+flush();
+
+?>
+<h3><?php echo $lang->get('finish_heading_progress'); ?></h3>
+<p><?php echo $lang->get('finish_msg_progress'); ?></p>
+
+<?php
+
+@set_time_limit(0);
+
+function stg_load_files()
+{
+  global $dbdriver;
+  if ( !@include( ENANO_ROOT . "/install/includes/payload.php" ) )
+    return false;
+  
+  return true;
+}
+
+// FIXME: l10n
+start_install_table();
+
+run_installer_stage('load', $lang->get('install_stg_load_title'), 'stg_load_files', $lang->get('install_stg_load_body'), false);
+run_installer_stage('cleanup', $lang->get('install_stg_cleanup_title'), 'stg_aes_cleanup', $lang->get('install_stg_cleanup_body'), false);
+run_installer_stage('buildindex', $lang->get('install_stg_buildindex_title'), 'stg_build_index', $lang->get('install_stg_buildindex_body'));
+run_installer_stage('renameconfig', $lang->get('install_stg_rename_title'), 'stg_rename_config', $lang->get('install_stg_rename_body', array('mainpage_link' => scriptPath . '/index.php')));
+
+close_install_table();
+
+?>
+<h3><?php echo $lang->get('finish_msg_success_title'); ?></h3>
+<p><?php echo $lang->get('finish_msg_success_body', array('mainpage_link' => makeUrlNS('Article', 'Main_Page'))); ?></p>
+<?php 
+  echo $lang->get('finish_body');
+  echo '<p>' . $lang->get('finish_link_mainpage', array('mainpage_link' => scriptPath . '/index.php')) . '</p>';
+?>
+<?php
+
+$db->close();
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/install/includes/stages/install.php	Fri Feb 22 12:51:53 2008 -0500
@@ -0,0 +1,125 @@
+<?php
+
+/*
+ * Enano - an open-source CMS capable of wiki functions, Drupal-like sidebar blocks, and everything in between
+ * Version 1.1.1
+ * Copyright (C) 2006-2007 Dan Fuhry
+ * Installation package
+ * install.php - Installer payload stage
+ *
+ * This program is Free Software; you can redistribute and/or modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.
+ *
+ * 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.
+ */
+
+if ( !defined('IN_ENANO_INSTALL') )
+  die();
+
+require ( ENANO_ROOT . '/install/includes/libenanoinstall.php' );
+require ( ENANO_ROOT . '/install/includes/sql_parse.php' );
+require ( ENANO_ROOT . '/includes/dbal.php' );
+require ( ENANO_ROOT . '/config.new.php' );
+
+if ( !in_array($dbdriver, $supported_drivers) )
+{
+  $ui->show_header();
+  echo '<h3>Installation error</h3>
+         <p>ERROR: That database driver is not supported.</p>';
+  return true;
+}
+
+$db = new $dbdriver();
+$result = $db->connect(true, $dbhost, $dbuser, $dbpasswd, $dbname);
+if ( !$result )
+{
+  $ui->show_header();
+  // FIXME: l10n
+  ?>
+  <form action="install.php?stage=database" method="post" name="database_info">
+    <input type="hidden" name="language" value="<?php echo $lang_id; ?>" />
+    <input type="hidden" name="driver" value="<?php echo $dbdriver; ?>" />
+    <h3><?php echo $lang->get('database_msg_post_fail_title'); ?></h3>
+    <p><?php echo $lang->get('database_msg_post_fail_body'); ?></p>
+    <p><?php echo $lang->get('database_msg_post_fail_desc'); ?>
+      <?php
+      echo $db->sql_error();
+      ?>
+    </p>
+    <p>
+      <input type="submit" name="_cont" value="Go back" />
+    </p>
+  </form>
+  <?php
+  return true;
+}
+
+// we're connected to the database now.
+
+$ui->show_header();
+flush();
+
+?>
+<h3><?php echo $lang->get('install_title'); ?></h3>
+<p><?php echo $lang->get('install_body'); ?></p>
+
+<h3><?php echo $lang->get('install_heading_progress'); ?></h3>
+
+<?php
+
+@set_time_limit(0);
+
+function stg_load_files()
+{
+  global $dbdriver;
+  if ( !@include( ENANO_ROOT . "/install/includes/payload.php" ) )
+    return false;
+  
+  return true;
+}
+
+// FIXME: l10n
+start_install_table();
+
+run_installer_stage('load', $lang->get('install_stg_load_title'), 'stg_load_files', $lang->get('install_stg_load_body'), false);
+run_installer_stage('setpass', $lang->get('install_stg_setpass_title'), 'stg_password_decode', $lang->get('install_stg_setpass_body'));
+run_installer_stage('genaes', $lang->get('install_stg_genaes_title'), 'stg_make_private_key', $lang->get('install_stg_genaes_body'));
+run_installer_stage('sqlparse', $lang->get('install_stg_sqlparse_title'), 'stg_load_schema', $lang->get('install_stg_sqlparse_body'));
+run_installer_stage('payload', $lang->get('install_stg_payload_title'), 'stg_deliver_payload', $lang->get('install_stg_payload_body'));
+run_installer_stage('writeconfig', $lang->get('install_stg_writeconfig_title'), 'stg_write_config', $lang->get('install_stg_writeconfig_body'));
+
+// Now that the config is written, shutdown our primitive API and startup the full Enano API
+$db->close();
+
+@define('ENANO_ALLOW_LOAD_NOLANG', 1);
+require(ENANO_ROOT . '/includes/common.php');
+        
+if ( is_object($db) && is_object($session) )
+{
+  run_installer_stage('startapi', $lang->get('install_stg_startapi_title'), 'stg_sim_good', '...', false);
+}
+else
+{
+  run_installer_stage('startapi', $lang->get('install_stg_startapi_title'), 'stg_sim_bad', $lang->get('install_stg_startapi_body'), false);
+}
+
+// Import languages
+run_installer_stage('importlang', $lang->get('install_stg_importlang_title'), 'stg_language_setup', $lang->get('install_stg_importlang_body'));
+
+// Init logs
+run_installer_stage('initlogs', $lang->get('install_stg_initlogs_title'), 'stg_init_logs', $lang->get('install_stg_initlogs_body'));
+
+close_install_table();
+
+?>
+<form action="install.php?stage=finish" method="post">
+  <input type="hidden" name="language" value="<?php echo $lang_id; ?>" />
+  <div style="text-align: center;">
+    <input type="submit" name="_cont" value="<?php echo $lang->get('meta_btn_continue'); ?>" tabindex="1" />
+  </div>
+</form>
+<?php
+
+$db->close();
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/install/includes/stages/license.php	Fri Feb 22 12:51:53 2008 -0500
@@ -0,0 +1,101 @@
+<?php
+
+/*
+ * Enano - an open-source CMS capable of wiki functions, Drupal-like sidebar blocks, and everything in between
+ * Version 1.1.1
+ * Copyright (C) 2006-2007 Dan Fuhry
+ * Installation package
+ * license.php - Installer license-agreement stage
+ *
+ * This program is Free Software; you can redistribute and/or modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.
+ *
+ * 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.
+ */
+
+if ( !defined('IN_ENANO_INSTALL') )
+  die();
+
+function show_license($fb = false)
+{
+  global $lang;
+  global $installer_version;
+  ?>
+  <div class="scroller">
+  <?php
+    if ( !file_exists('./GPL') || !file_exists('./language/english/install/license-deed.html') )
+    {
+      echo 'Cannot find the license files.';
+    }
+    echo file_get_contents('./language/english/install/license-deed.html');
+    if ( $installer_version['type'] != 'stable' )
+    {
+      ?>
+      <h3><?php echo $lang->get('license_info_unstable_title'); ?></h3>
+      <p><?php echo $lang->get('license_info_unstable_body'); ?></p>
+      <?php
+    }
+    ?>
+    <h3><?php echo $lang->get('license_section_gpl_heading'); ?></h3>
+    <?php if ( $lang->lang_code != 'eng' ): ?>
+    <p><i><?php echo $lang->get('license_gpl_blurb_inenglish'); ?></i></p>
+    <?php endif; ?>
+    <?php echo wikiFormat(file_get_contents(ENANO_ROOT . '/GPL')); ?>
+   <?php
+   global $template;
+   if ( $fb )
+   {
+     echo '<p style="text-align: center;">Because I could never find the Create a Page button in PHP-Nuke.</p>';
+     echo '<p>' . str_replace('http://enanocms.org/', 'http://www.2robots.com/2003/10/15/web-portals-suck/', $template->fading_button) . '</p>';
+     echo '<p style="text-align: center;">It\'s not a portal, my friends.</p>';
+   }
+   ?>
+ </div>
+ <?php
+}
+
+function wikiFormat($message, $filter_links = true)
+{
+  $wiki = & Text_Wiki::singleton('Mediawiki');
+  $wiki->setRenderConf('Xhtml', 'code', 'css_filename', 'codefilename');
+  $wiki->setRenderConf('Xhtml', 'wikilink', 'view_url', scriptPath . '/index.php?title=');
+  $result = $wiki->transform($message, 'Xhtml');
+  
+  // HTML fixes
+  $result = preg_replace('#<tr>([\s]*?)<\/tr>#is', '', $result);
+  $result = preg_replace('#<p>([\s]*?)<\/p>#is', '', $result);
+  $result = preg_replace('#<br />([\s]*?)<table#is', '<table', $result);
+  
+  return $result;
+}
+
+?>
+    <h3><?php echo $lang->get('license_heading'); ?></h3>
+     <p><?php echo $lang->get('license_blurb_thankyou'); ?></p>
+     <p><?php echo $lang->get('license_blurb_pleaseread'); ?></p>
+     <?php show_license(); ?>
+     <div class="pagenav">
+       <form action="install.php?stage=sysreqs" method="post">
+       <?php
+       echo '<input type="hidden" name="language" value="' . $lang_id . '" />';
+       ?>
+         <table border="0">
+         <tr>
+           <td>
+             <input type="submit" value="<?php echo $lang->get('license_btn_i_agree'); ?>" />
+           </td>
+           <td>
+             <p>
+               <span style="font-weight: bold;"><?php echo $lang->get('meta_lbl_before_continue'); ?></span><br />
+               &bull; <?php echo $lang->get('license_objective_ensure_agree'); ?><br />
+               &bull; <?php echo $lang->get('license_objective_have_db_info'); ?>
+             </p>
+           </td>
+         </tr>
+         </table>
+       </form>
+     </div>
+    <?php
+
+?>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/install/includes/stages/login.php	Fri Feb 22 12:51:53 2008 -0500
@@ -0,0 +1,228 @@
+<?php
+
+/*
+ * Enano - an open-source CMS capable of wiki functions, Drupal-like sidebar blocks, and everything in between
+ * Version 1.1.1
+ * Copyright (C) 2006-2007 Dan Fuhry
+ * Installation package
+ * login.php - Installer login information stage
+ *
+ * This program is Free Software; you can redistribute and/or modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.
+ *
+ * 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.
+ */
+
+if ( !defined('IN_ENANO_INSTALL') )
+  die();
+
+// AES functions required
+require_once( ENANO_ROOT . '/includes/rijndael.php' );
+require_once( ENANO_ROOT . '/includes/constants.php' );
+require_once( ENANO_ROOT . '/includes/dbal.php' );
+
+// Write our temporary password key to the database
+require( ENANO_ROOT . '/config.new.php' );
+if ( !defined('ENANO_INSTALL_HAVE_CONFIG') )
+{
+  die('Config file is corrupt');
+}
+$db = new $dbdriver();
+$result = $db->connect(true, $dbhost, $dbuser, $dbpasswd, $dbname);
+if ( !$result )
+  die('DB privileges were revoked');
+
+// Is the key in the database?
+$q = $db->sql_query('SELECT config_value FROM ' . table_prefix . 'config WHERE config_name = \'install_aes_key\';');
+if ( !$q )
+  $db->_die();
+if ( $db->numrows() > 0 )
+{
+  list($install_aes_key) = $db->fetchrow_num();
+}
+else
+{
+  $aes = AESCrypt::singleton(AES_BITS, AES_BLOCKSIZE);
+  $install_aes_key = $aes->gen_readymade_key();
+  
+  if ( ! $db->sql_query('INSERT INTO ' . table_prefix . 'config ( config_name, config_value ) VALUES ( \'install_aes_key\', \'' . $install_aes_key .'\' ); ') )
+    $db->_die();
+}
+$db->free_result($q);
+
+$ui->add_header('<script type="text/javascript" src="includes/js/formutils.js"></script>');
+$ui->show_header();
+
+// FIXME: l10n
+?>
+<h3><?php echo $lang->get('login_welcome_title'); ?></h3>
+<?php echo $lang->get('login_welcome_body'); ?>
+
+<script type="text/javascript">
+
+  // <![CDATA[
+  
+  function verify(target)
+  {
+    var frm = document.forms [ 'install_login' ];
+    var undefined;
+    var passed = true;
+    
+    var data = {
+      username: frm.username.value,
+      password: frm.password.value,
+      password_confirm: frm.password_confirm.value,
+      email: frm.email.value
+    };
+    
+    if ( !target )
+      target = { name: undefined };
+    
+    if ( target.name == undefined || target.name == 'username' )
+    {
+      var matches = validateUsername(data.username);
+      document.getElementById('s_username').src = ( matches ) ? img_good : img_bad;
+      if ( !matches )
+        passed = false;
+    }
+    
+    if ( target.name == undefined || target.name == 'password' || target.name == 'password_confirm' )
+    {
+      var matches = ( data.password.length >= 6 && data.password == data.password_confirm ) ;
+      document.getElementById('s_password').src = ( matches ) ? img_good : img_bad;
+      if ( !matches )
+        passed = false;
+    }
+    
+    if ( target.name == undefined || target.name == 'email' )
+    {
+      var matches = validateEmail(data.email);
+      document.getElementById('s_email').src = ( matches ) ? img_good : img_bad;
+      if ( !matches )
+        passed = false;
+    }
+    
+    return passed;
+  }
+  
+  function verify_submit()
+  {
+    if ( verify() )
+      return true;
+    alert($lang.get('login_err_verify_failure'));
+    return false;
+  }
+  
+  function submit_encrypt()
+  {
+    var frm = document.forms [ 'install_login' ];
+    var password = frm.password.value;
+    var pass_conf = frm.password_confirm.value;
+    var crypt_key = frm.crypt_key.value;
+    
+    if ( password != pass_conf )
+      return false;
+    
+    if ( !aes_self_test() )
+      // Return true to prevent form from failing
+      return true;
+      
+    if ( frm.crypt_key.KeyBak )
+    {
+      crypt_key = frm.crypt_key.KeyBak;
+    }
+    frm.crypt_key.KeyBak = crypt_key;
+    
+    password = stringToByteArray(password);
+    crypt_key = hexToByteArray(crypt_key);
+    
+    var crypt_data = rijndaelEncrypt(password, crypt_key, 'ECB');
+    
+    if ( !crypt_data )
+    {
+      alert($lang.get('login_err_rijndael_failed'));
+      return false;
+    }
+  
+    crypt_data = byteArrayToHex(crypt_data);
+    
+    frm.password.value = '';
+    frm.password_confirm.value = '';
+    frm.crypt_key.value = '';
+    frm.crypt_data.value = crypt_data;
+    
+    return true;
+  }
+  
+  // ]]>
+
+</script>
+
+<form action="install.php?stage=confirm" method="post" name="install_login" onsubmit="return ( verify_submit() && submit_encrypt() );"><?php
+  foreach ( $_POST as $key => &$value )
+  {
+    if ( !preg_match('/^[a-z0-9_]+$/', $key) )
+      die('You idiot hacker...');
+    if ( $key == '_cont' )
+      continue;
+    $value_clean = str_replace(array('\\', '"', '<', '>'), array('\\\\', '\\"', '&lt;', '&gt;'), $value);
+    echo "\n  <input type=\"hidden\" name=\"$key\" value=\"$value_clean\" />";
+  }
+  
+  $https = ( isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] != 'off' );
+  $scriptpath_full = 'http' . ( $https ? 's' : '' ) . '://' . $_SERVER['HTTP_HOST'] . scriptPath . '/';
+  ?>
+  
+  <input type="hidden" name="crypt_key" value="<?php echo $install_aes_key; ?>" />
+  <input type="hidden" name="crypt_data" value="" />
+  
+  <table border="0" cellspacing="0" cellpadding="10" style="width: 100%;">
+  
+    <tr>
+      <td style="width: 50%;">
+        <b><?php echo $lang->get('login_field_username'); ?></b>
+      </td>
+      <td style="width: 50%;">
+        <input type="text" tabindex="1" name="username" size="15" onkeyup="verify(this);" />
+      </td>
+      <td>
+        <img id="s_username" alt="Good/bad icon" src="../images/checkbad.png" />
+      </td>
+    </tr>
+    
+    <tr>
+      <td>
+        <b><?php echo $lang->get('login_field_password'); ?></b><br />
+        <?php echo $lang->get('login_aes_blurb'); ?>
+      </td>
+      <td>
+        <input type="password" tabindex="2" name="password" size="15" onkeyup="password_score_field(this); verify(this);" /><br />
+        <br />
+        <div id="pwmeter"></div>
+        <br />
+        <input type="password" tabindex="3" name="password_confirm" size="15" onkeyup="verify(this);" /> <small><?php echo $lang->get('login_field_password_confirm'); ?></small>
+      </td>
+      <td>
+        <img id="s_password" alt="Good/bad icon" src="../images/checkbad.png" />
+      </td>
+    </tr>
+    
+    <tr>
+      <td style="width: 50%;">
+        <b><?php echo $lang->get('login_field_email'); ?></b>
+      </td>
+      <td style="width: 50%;">
+        <input type="text" tabindex="4" name="email" size="30" onkeyup="verify(this);" />
+      </td>
+      <td>
+        <img id="s_email" alt="Good/bad icon" src="../images/checkbad.png" />
+      </td>
+    </tr>
+  
+  </table>
+  
+  <div style="text-align: center;">
+    <input type="submit" name="_cont" value="<?php echo $lang->get('meta_btn_continue'); ?>" />
+  </div>
+</form>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/install/includes/stages/sysreqs.php	Fri Feb 22 12:51:53 2008 -0500
@@ -0,0 +1,147 @@
+<?php
+
+/*
+ * Enano - an open-source CMS capable of wiki functions, Drupal-like sidebar blocks, and everything in between
+ * Version 1.1.1
+ * Copyright (C) 2006-2007 Dan Fuhry
+ * Installation package
+ * sysreqs.php - Installer system-requirements page
+ *
+ * This program is Free Software; you can redistribute and/or modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.
+ *
+ * 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.
+ */
+
+if ( !defined('IN_ENANO_INSTALL') )
+  die();
+
+global $failed, $warned;
+
+$failed = false;
+$warned = false;
+
+function not($var)
+{
+  if($var)
+  {
+    return false;
+  } 
+  else
+  {
+    return true;
+  }
+}
+
+function run_test($code, $desc, $extended_desc, $warn = false)
+{
+  global $failed, $warned;
+  static $cv = true;
+  $cv = not($cv);
+  $val = eval($code);
+  if($val)
+  {
+    if($cv) $color='CCFFCC'; else $color='AAFFAA';
+    echo "<tr><td style='background-color: #$color; width: 500px; padding: 5px;'>$desc</td><td style='padding-left: 10px;'><img alt='Test passed' src='../images/check.png' /></td></tr>";
+  } elseif(!$val && $warn) {
+    if($cv) $color='FFFFCC'; else $color='FFFFAA';
+    echo "<tr><td style='background-color: #$color; width: 500px; padding: 5px;'>$desc<br /><b>$extended_desc</b></td><td style='padding-left: 10px;'><img alt='Test passed with warning' src='../images/checkunk.png' /></td></tr>";
+    $warned = true;
+  } else {
+    if($cv) $color='FFCCCC'; else $color='FFAAAA';
+    echo "<tr><td style='background-color: #$color; width: 500px; padding: 5px;'>$desc<br /><b>$extended_desc</b></td><td style='padding-left: 10px;'><img alt='Test failed' src='../images/checkbad.png' /></td></tr>";
+    $failed = true;
+  }
+}
+function is_apache()
+{
+  $r = strstr($_SERVER['SERVER_SOFTWARE'], 'Apache') ? true : false;
+  return $r;
+}
+
+function config_write_test()
+{
+  if ( !is_writable(ENANO_ROOT.'/config.new.php') )
+    return false;
+  // We need to actually _open_ the file to make sure it can be written, because sometimes this fails even when is_writable() returns
+  // true on Windows/IIS servers. Don't ask me why.
+  $h = @fopen( ENANO_ROOT . '/config.new.php', 'a+' );
+  if ( !$h )
+    return false;
+  fclose($h);
+  return true;
+}
+
+?>
+<h3><?php echo $lang->get('sysreqs_heading'); ?></h3>
+ <p><?php echo $lang->get('sysreqs_blurb'); ?></p>
+ 
+<table border="0" cellspacing="0" cellpadding="0">
+
+<?php
+run_test('return version_compare(\'5.2.0\', PHP_VERSION, \'<=\');', $lang->get('sysreqs_req_php5'), $lang->get('sysreqs_req_desc_php5'), true);
+run_test('return function_exists(\'mysql_connect\');', $lang->get('sysreqs_req_mysql'), $lang->get('sysreqs_req_desc_mysql') );
+run_test('return function_exists(\'pg_connect\');', $lang->get('sysreqs_req_postgres'), $lang->get('sysreqs_req_desc_postgres'), true);
+run_test('return @ini_get(\'file_uploads\');', $lang->get('sysreqs_req_uploads'), $lang->get('sysreqs_req_desc_uploads') );
+run_test('return is_apache();', $lang->get('sysreqs_req_apache'), $lang->get('sysreqs_req_desc_apache'), true);
+run_test('return config_write_test();', $lang->get('sysreqs_req_config'), $lang->get('sysreqs_req_desc_config') );
+run_test('return file_exists(\'/usr/bin/convert\');', $lang->get('sysreqs_req_magick'), $lang->get('sysreqs_req_desc_magick'), true);
+run_test('return is_writable(ENANO_ROOT.\'/cache/\');', $lang->get('sysreqs_req_cachewriteable'), $lang->get('sysreqs_req_desc_cachewriteable'), true);
+run_test('return is_writable(ENANO_ROOT.\'/files/\');', $lang->get('sysreqs_req_fileswriteable'), $lang->get('sysreqs_req_desc_fileswriteable'), true);
+if ( !function_exists('mysql_connect') && !function_exists('pg_connect') )
+{
+  // FIXME: l10n
+  run_test('return false;', 'No database drivers are available.', 'You need to have at least one database driver working to install Enano. See the warnings on MySQL and PostgreSQL above for more information on installing these database drivers.', false);
+}
+echo '</table>';
+echo '<br />';
+if(!$failed)
+{
+  ?>
+  
+  <div class="pagenav">
+  <?php
+  if($warned) {
+    echo '<table border="0" cellspacing="0" cellpadding="0">';
+    run_test('return false;', $lang->get('sysreqs_summary_warn_title'), $lang->get('sysreqs_summary_warn_body'), true);
+    echo '</table>';
+  } else {
+    echo '<table border="0" cellspacing="0" cellpadding="0">';
+    run_test('return true;', '<b>' . $lang->get('sysreqs_summary_success_title') . '</b><br />' . $lang->get('sysreqs_summary_success_body'), 'You should never see this text. Congratulations for being an Enano hacker!');
+    echo '</table>';
+  }
+  ?>
+  <form action="install.php?stage=database" method="post">
+    <?php
+      echo '<input type="hidden" name="language" value="' . $lang_id . '" />';
+    ?>
+    <table border="0">
+    <tr>
+      <td>
+        <input type="submit" value="<?php echo $lang->get('meta_btn_continue'); ?>" />
+      </td>
+      <td>
+        <p>
+          <span style="font-weight: bold;"><?php echo $lang->get('meta_lbl_before_continue'); ?></span><br />
+          &bull; <?php echo $lang->get('sysreqs_objective_scalebacks'); ?><br />
+          &bull; <?php echo $lang->get('license_objective_have_db_info'); ?>
+        </p>
+      </td>
+    </tr>
+    </table>
+  </form>
+  </div>
+<?php
+}
+else
+{
+  if ( $failed )
+  {
+    echo '<div class="pagenav"><table border="0" cellspacing="0" cellpadding="0">';
+    run_test('return false;', $lang->get('sysreqs_summary_fail_title'), $lang->get('sysreqs_summary_fail_body'));
+    echo '</table></div>';
+  }
+}
+    
+?>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/install/includes/stages/website.php	Fri Feb 22 12:51:53 2008 -0500
@@ -0,0 +1,256 @@
+<?php
+
+/*
+ * Enano - an open-source CMS capable of wiki functions, Drupal-like sidebar blocks, and everything in between
+ * Version 1.1.1
+ * Copyright (C) 2006-2007 Dan Fuhry
+ * Installation package
+ * website.php - Installer website-settings stage
+ *
+ * This program is Free Software; you can redistribute and/or modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.
+ *
+ * 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.
+ */
+
+if ( !defined('IN_ENANO_INSTALL') )
+  die();
+
+// Note: this is called from database_*.php, not directly from install.php
+
+$ui->add_header('<script type="text/javascript" src="includes/js/formutils.js"></script>');
+$ui->show_header();
+
+?>
+
+<script type="text/javascript">
+  // <![CDATA[
+  function ajaxMrwTest()
+  {
+    install_set_ajax_loading();
+    // Send a series of tests to the server, and if we get an "expected" response
+    setTimeout("ajaxGet(scriptPath + '/install/rewrite', __ajaxMrwTest_chain_rewrite);", 750);
+  }
+  var __ajaxMrwTest_chain_rewrite = function()
+  {
+    if ( ajax.readyState == 4 && ajax.status == 200 )
+    {
+      if ( ajax.responseText == 'good_rewrite' )
+      {
+        ajaxMrwSet('rewrite');
+      }
+      else
+      {
+        ajaxGet(scriptPath + '/install/install.php/shortened?do=modrewrite_test', __ajaxMrwTest_chain_shortened);
+      }
+    }
+  }
+  var __ajaxMrwTest_chain_shortened = function()
+  {
+    if ( ajax.readyState == 4 && ajax.status == 200 )
+    {
+      if ( ajax.responseText == 'good_shortened' )
+      {
+        ajaxMrwSet('standard');
+      }
+      else
+      {
+        ajaxGet(scriptPath + '/install/install.php?do=modrewrite_test&str=standard', __ajaxMrwTest_chain_standard);
+      }
+    }
+  }
+  var __ajaxMrwTest_chain_standard = function()
+  {
+    if ( ajax.readyState == 4 && ajax.status == 200 )
+    {
+      if ( ajax.responseText == 'good_standard' )
+      {
+        ajaxMrwSet('standard');
+      }
+      else
+      {
+        install_unset_ajax_loading();
+        new messagebox(MB_OK | MB_ICONSTOP, $lang.get('website_msg_ajax_test_fail_title'), $lang.get('website_msg_ajax_test_fail_body'));
+      }
+    }
+  }
+  function ajaxMrwSet(level)
+  {
+    install_unset_ajax_loading();
+    if ( !in_array(level, ['rewrite', 'shortened', 'standard']) )
+      return false;
+    
+    document.getElementById('url_radio_rewrite').checked = false;
+    document.getElementById('url_radio_shortened').checked = false;
+    document.getElementById('url_radio_standard').checked = false;
+    document.getElementById('url_radio_' + level).checked = true;
+    document.getElementById('url_radio_' + level).focus();
+    
+    switch ( level )
+    {
+      case 'rewrite':
+        var str = $lang.get('website_msg_bestmethod_rewrite');
+        break;
+      case 'shortened':
+        var str = $lang.get('website_msg_bestmethod_shortened');
+        break;
+      case 'standard':
+        var str = $lang.get('website_msg_bestmethod_standard');
+        break;
+    }
+    document.getElementById('mrw_report').className = 'info-box-mini';
+    document.getElementById('mrw_report').innerHTML = str;
+  }
+  
+  function verify()
+  {
+    var frm = document.forms['install_website'];
+    var fail = false;
+    if ( frm.site_name.value == '' )
+    {
+      fail = true;
+      new Spry.Effect.Shake($(frm.site_name).object, {duration: 750}).start();
+      frm.site_name.focus();
+    }
+    if ( frm.site_desc.value == '' )
+    {
+      new Spry.Effect.Shake($(frm.site_desc).object, {duration: 750}).start();
+      if ( !fail )
+        frm.site_desc.focus();
+      fail = true;
+    }
+    if ( frm.copyright.value == '' )
+    {
+      new Spry.Effect.Shake($(frm.copyright).object, {duration: 750}).start();
+      if ( !fail )
+        frm.copyright.focus();
+      fail = true;
+    }
+    return ( !fail );
+  }
+  // ]]>
+</script>
+
+<form action="install.php?stage=login" method="post" name="install_website" onsubmit="return verify();"><?php
+  foreach ( $_POST as $key => &$value )
+  {
+    if ( !preg_match('/^[a-z0-9_]+$/', $key) )
+      die('You idiot hacker...');
+    if ( $key == '_cont' )
+      continue;
+    $value_clean = str_replace(array('\\', '"', '<', '>'), array('\\\\', '\\"', '&lt;', '&gt;'), $value);
+    echo "\n  <input type=\"hidden\" name=\"$key\" value=\"$value_clean\" />";
+  }
+  
+  $https = ( isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] != 'off' );
+  $scriptpath_full = 'http' . ( $https ? 's' : '' ) . '://' . $_SERVER['HTTP_HOST'] . scriptPath . '/';
+  ?>
+  
+  <table border="0" cellspacing="0" cellpadding="10">
+  
+    <tr>
+      <td>
+        <b><?php echo $lang->get('website_field_name'); ?></b><br />
+        <span id="hint_site_name" class="fieldtip"><?php echo $lang->get('website_field_name_hint'); ?></span>
+      </td>
+      <td style="width: 50%;">
+        <input type="text" name="site_name" size="50" tabindex="1" />
+      </td>
+    </tr>
+    
+    <tr>
+      <td>
+        <b><?php echo $lang->get('website_field_desc'); ?></b><br />
+        <span id="hint_site_desc" class="fieldtip"><?php echo $lang->get('website_field_desc_hint'); ?></span>
+      </td>
+      <td>
+        <input type="text" name="site_desc" size="50" tabindex="2" />
+      </td>
+    </tr>
+    
+    <tr>
+      <td>
+        <b><?php echo $lang->get('website_field_copyright'); ?></b><br />
+        <span id="hint_copyright" class="fieldtip"><?php echo $lang->get('website_field_copyright_hint'); ?></span>
+      </td>
+      <td>
+        <input type="text" name="copyright" size="50" tabindex="3" />
+      </td>
+    </tr>
+    
+    <tr>
+      <td valign="top">
+        <b><?php echo $lang->get('website_field_urlscheme'); ?></b><br />
+        <?php echo $lang->get('website_field_urlscheme_hint'); ?>
+      </td>
+      <td>
+      
+        <table border="0" cellpadding="10" cellspacing="0">
+          <tr>
+            <td valign="top">
+              <input type="radio" name="url_scheme" value="standard" id="url_radio_standard" tabindex="5" />
+            </td>
+            <td>
+              <label for="url_radio_standard">
+                <b><?php echo $lang->get('website_field_urlscheme_opt_standard'); ?></b>
+              </label>
+              <span class="fieldtip" id="hint_url_scheme_standard">
+                <p><?php echo $lang->get('website_field_urlscheme_opt_standard_hint'); ?></p>
+                <p><small><b><?php echo $lang->get('website_field_urlscheme_lbl_example'); ?></b> <tt><?php echo $scriptpath_full . 'index.php?title=Page'; ?></tt></small></p>
+              </span>
+            </td>
+          </tr>
+        </table>
+        
+        <table border="0" cellpadding="10" cellspacing="0">
+          <tr>
+            <td valign="top">
+              <input type="radio" checked="checked" name="url_scheme" value="shortened" id="url_radio_shortened" tabindex="5" />
+            </td>
+            <td>
+              <label for="url_radio_shortened">
+                <b><?php echo $lang->get('website_field_urlscheme_opt_shortened'); ?></b>
+              </label>
+              <span class="fieldtip" id="hint_url_scheme_shortened">
+                <p><?php echo $lang->get('website_field_urlscheme_opt_shortened_hint'); ?></p>
+                <p><small><b><?php echo $lang->get('website_field_urlscheme_lbl_example'); ?></b> <tt><?php echo $scriptpath_full . 'index.php/Page'; ?></tt></small></p>
+              </span>
+            </td>
+          </tr>
+        </table>
+        
+        <table border="0" cellpadding="10" cellspacing="0">
+          <tr>
+            <td valign="top">
+              <input type="radio" name="url_scheme" value="rewrite" id="url_radio_rewrite" tabindex="5" />
+            </td>
+            <td>
+              <label for="url_radio_rewrite">
+                <b><?php echo $lang->get('website_field_urlscheme_opt_rewrite'); ?></b>
+              </label>
+              <span id="hint_url_scheme_rewrite" class="fieldtip">
+                <p><?php echo $lang->get('website_field_urlscheme_opt_rewrite_hint'); ?></p>
+                <p><small><b><?php echo $lang->get('website_field_urlscheme_lbl_example'); ?></b> <tt><?php echo $scriptpath_full . 'Page'; ?></tt></small></p>
+              </span>
+            </td>
+          </tr>
+        </table>
+        
+        <p>
+          <a href="#mrw_scan" onclick="ajaxMrwTest(); return false;" tabindex="4"><?php echo $lang->get('website_btn_urlscheme_detect'); ?></a>
+        </p>
+        
+        <div id="mrw_report"></div>
+        
+      </td>
+    </tr>
+    
+  </table>
+  
+  <div style="text-align: center;">
+    <input type="submit" name="_cont" value="<?php echo $lang->get('meta_btn_continue'); ?>" tabindex="6" />
+  </div>
+  
+</form>
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/install/includes/ui.php	Fri Feb 22 12:51:53 2008 -0500
@@ -0,0 +1,243 @@
+<?php
+
+/*
+ * Enano - an open-source CMS capable of wiki functions, Drupal-like sidebar blocks, and everything in between
+ * Version 1.1.1
+ * Copyright (C) 2006-2007 Dan Fuhry
+ * Installation package
+ * ui.php - User interface for installations and upgrades
+ *
+ * This program is Free Software; you can redistribute and/or modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.
+ *
+ * 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 class for drawing and managing UI components.
+ * @package Enano
+ * @subpackage Installer
+ * @author Dan Fuhry
+ */
+
+class Enano_Installer_UI
+{
+  /**
+   * The list of installer stages.
+   * @var array
+   */
+  
+  var $stages = array();
+  
+  /**
+   * The GUID of the active stage
+   * @var string
+   */
+  
+  var $current_stage = '';
+  
+  /**
+   * The application name, or the name displayed after the stage name in the title bar. Should be localized.
+   * @var string
+   */
+  
+  var $app_name = '';
+  
+  /**
+   * If the header should be simplified (stripped of the Enano logo and top heading), this will be true.
+   * @var bool
+   */
+  
+  var $simple = false;
+  
+  /**
+   * Text inserted into the header on the right.
+   * @var string
+   */
+  
+  var $step = '';
+  
+  /**
+   * Extra text to add to the HTML <head> section
+   * @var array Will be implode()'ed
+   */
+  
+  var $additional_headers = array();
+  
+  /**
+   * Constructor.
+   * @param string The name displayed in the <title> tag
+   * @param bool If true, the simplified header format is displayed.
+   */
+  
+  function __construct($app_name, $simple_header)
+  {
+    $this->stages = array(
+        'main' => array(),
+        'hide' => array()
+      );
+    $this->app_name = $app_name;
+    $this->simple = ( $simple_header ) ? true : false;
+  }
+  
+  /**
+   * Adds more text to the HTML header.
+   * @param string
+   */
+  
+  function add_header($html)
+  {
+    $this->additional_headers[] = $html;
+  }
+  
+  /**
+   * Adds a stage to the installer.
+   * @param string Title of the stage, should be already put through $lang->get()
+   * @param bool If true, the stage is shown among possible stages at the top of the window. If false, acts as a hidden stage
+   * @return string Unique identifier for stage, used later on set_visible_stage()
+   */
+  
+  function add_stage($stage, $visible = true)
+  {
+    $key = ( $visible ) ? 'main' : 'hide';
+    $guid = md5(microtime() . mt_rand());
+    $this->stages[$key][$guid] = $stage;
+    if ( empty($this->current_stage) )
+      $this->current_stage = $guid;
+    return $guid;
+  }
+  
+  /**
+   * Resets the active stage of installation. This is for the UI only; it doesn't actually change how the backend works.
+   * @param string GUID of stage, returned from add_stage()
+   * @return bool true on success, false if stage GUID not found
+   */
+  
+  function set_visible_stage($guid)
+  {
+    foreach ( $this->stages['main'] as $key => $stage_name )
+    {
+      if ( $key == $guid )
+      {
+        $this->current_stage = $guid;
+        return true;
+      }
+    }
+    foreach ( $this->stages['hide'] as $key => $stage_name )
+    {
+      if ( $key == $guid )
+      {
+        $this->current_stage = $guid;
+        return true;
+      }
+    }
+    return false;
+  }
+  
+  /**
+   * Outputs the HTML headers and start of the <body>, including stage indicator
+   */
+  
+  function show_header()
+  {
+    // Determine the name of the current stage
+    $stage_name = false;
+    
+    if ( isset($this->stages['main'][$this->current_stage]) )
+      $stage_name = $this->stages['main'][$this->current_stage];
+    else if ( isset($this->stages['hide'][$this->current_stage]) )
+      $stage_name = $this->stages['hide'][$this->current_stage];
+    else
+      // Can't determine name of stage
+      return false;
+      
+    $this->app_name = htmlspecialchars($this->app_name);
+    $stage_name = htmlspecialchars($stage_name);
+    
+    global $lang;
+    if ( is_object($lang) && isset($GLOBALS['lang_uri']) )
+    {
+      $lang_uri = sprintf($GLOBALS['lang_uri'], $lang->lang_code);
+      $this->add_header('<script type="text/javascript" src="' . $lang_uri . '"></script>');
+    }
+    
+    $additional_headers = implode("\n    ", $this->additional_headers);
+    $title = addslashes(str_replace(' ', '_', $stage_name));
+    $js_dynamic = '<script type="text/javascript">
+        var title="' . $title . '";
+        var scriptPath="'.scriptPath.'";
+        var ENANO_SID="";
+        var AES_BITS='.AES_BITS.';
+        var AES_BLOCKSIZE=' . AES_BLOCKSIZE . ';
+        var pagepass=\'\';
+        var ENANO_LANG_ID = 1;
+        var DISABLE_MCE = true;
+      </script>';
+    
+    echo <<<EOF
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+  <head>
+    <title>{$stage_name} &bull; {$this->app_name}</title>
+    <meta http-equiv="Content-type" content="text/html; charset=utf-8" />
+    <link rel="stylesheet" type="text/css" href="../includes/clientside/css/enano-shared.css" />
+    <link rel="stylesheet" type="text/css" href="images/css/installer.css" id="mdgCss" />
+    $js_dynamic
+    <script type="text/javascript" src="../includes/clientside/static/enano-lib-basic.js"></script>
+    $additional_headers
+  </head>
+  <body>
+    <div id="enano">
+
+EOF;
+    if ( !$this->simple )
+    {
+      $step = ( !empty($this->step) ) ? '<div id="step">' . htmlspecialchars($this->step) . '</div>' : '';
+      echo <<<EOF
+      <div id="header">
+        $step
+        <img alt="Enano logo" src="images/enano-artwork/installer-header-blue.png" />
+      </div>
+
+EOF;
+    }
+    $stages_class = ( $this->simple ) ? 'stages' : 'stages stages-fixed';
+    echo <<<EOF
+      <div class="stages-holder">
+        <ul class="$stages_class">
+    
+EOF;
+    foreach ( $this->stages['main'] as $guid => $stage )
+    {
+      $class = ( $guid == $this->current_stage ) ? 'stage stage-active' : 'stage';
+      $stage = htmlspecialchars($stage);
+      echo "      <li class=\"$class\">$stage</li>\n    ";
+    }
+    echo "    </ul>\n      <div style=\"clear: both;\"></div>\n      </div>\n";
+    echo "      <div id=\"enano-fill\">\n      ";
+    echo "  <div id=\"enano-body\">\n            ";
+  }
+  
+  /**
+   * Displays the page footer.
+   */
+  
+  function show_footer()
+  {
+    echo <<<EOF
+          <div id="copyright">
+            Enano and its various components, related documentation, and artwork are copyright &copy; 2006-2008 Dan Fuhry.<br />
+            This program is Free Software; see the file "GPL" included with this package for details.
+          </div>
+        </div> <!-- div#enano-body -->
+      </div> <!-- div#enano-fill -->
+    </div> <!-- div#enano -->
+  </body>
+</html>
+EOF;
+  }
+  
+}
+ 
+?>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/install/index.php	Fri Feb 22 12:51:53 2008 -0500
@@ -0,0 +1,128 @@
+<?php
+
+/*
+ * Enano - an open-source CMS capable of wiki functions, Drupal-like sidebar blocks, and everything in between
+ * Version 1.1.2
+ * Copyright (C) 2006-2007 Dan Fuhry
+ * Installation package
+ * welcome.php - Portal to upgrade, readme, and install pages
+ *
+ * This program is Free Software; you can redistribute and/or modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.
+ *
+ * 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.
+ */
+
+require_once('includes/common.php');
+
+$ui = new Enano_Installer_UI('Enano installation', true);
+if ( version_compare(PHP_VERSION, '5.0.0', '<') )
+{
+  $ui->__construct('Enano installation', true);
+}
+$ui->add_stage('Welcome', true);
+$ui->add_stage('Installation', true);
+$ui->add_stage('Upgrade', true);
+$ui->add_stage('Readme', true);
+
+$ui->show_header();
+
+if ( defined('ENANO_INSTALLED') )
+{
+  // Is Enano installed? If so, load the config and check version info
+  define('IN_ENANO_UPGRADE', 'true');
+  // common.php above calls chdir() to the ENANO_ROOT, so this loads the full Enano API.
+  require('includes/common.php');
+}
+
+?>
+
+          <div id="installnotice">
+          <?php
+            if ( !defined('ENANO_INSTALLED') ):
+            ?>
+            <div class="info-box-mini">
+              <b>Enano hasn't been installed yet!</b><br />
+              You'll need to install the Enano database before you can use your site. To get started, click the Install button below.
+            </div>
+          <?php
+            if ( file_exists('./config.php') )
+            {
+            ?>
+            <div class="warning-box-mini">
+              <b>A configuration file (config.php) exists but doesn't set the ENANO_INSTALLED constant.</b><br />
+              <p>Didn't expect to see this message?
+              It's possible that your configuration file has become corrupted and no longer sets information that Enano needs to connect
+              to the database. You should have a look at your config.php by downloading it with FTP or viewing it over SSH.
+              If the file appears to have been tampered with, please <a href="http://forum.enanocms.org/">contact the Enano team</a>
+              for support immediately.</p>
+              <p><b>Most importantly, if you suspect a security breach, you should contact the Enano team
+                 <a href="http://enanocms.org/Contact_us">via e-mail</a>. If you have the capability to use PGP encryption, you should do
+                 so; our public key is available <a href="http://enanocms.org/bin/enanocms-signkey.asc">here</a>.</b></p>
+            </div>
+            <?php
+            }
+            endif;
+            ?></div>
+          <table border="0" cellspacing="10" cellpadding="0" width="100%" id="installmenu">
+            <tr>
+              <td style="text-align: right; width: 50%;">
+                <!-- Enano logo -->
+                <img alt="Enano CMS" src="images/enano-artwork/installer-greeting.png" />
+              </td>
+              <td class="balancer">
+              </td>
+              <td>
+                <ul class="icons">
+                  <li><a href="readme.php" class="readme icon">Readme</a></li>
+                  <?php
+                  if ( !defined('ENANO_INSTALLED') ):
+                  ?>
+                  <li><a href="install.php" class="install icon">Install</a></li>
+                  <li>
+                    <a class="upgrade-disabled icon icon-disabled" title="You need to install Enano before you can do this.">
+                      Upgrade
+                      <small>
+                        Enano isn't installed yet. You can use this option when you want to upgrade to a newer release of Enano.
+                      </small>
+                    </a>
+                  </li>
+                  <?php
+                  else:
+                  ?>
+                  <li>
+                    <a class="install-disabled icon icon-disabled" title="Enano is already installed.">
+                      Install
+                      <small>Enano is already installed.</small> <!-- CSS takes care of making this position properly -->
+                    </a>
+                  </li>
+                  <?php
+                  if ( installer_enano_version() == enano_version(true) )
+                  {
+                    echo '<li>
+                    <a class="upgrade-disabled icon icon-disabled">
+                      Upgrade
+                      <small>
+                        You\'re already running the version of Enano included in this installer. Use the administration panel to check
+                        for updates.
+                      </small> <!-- CSS takes care of making this position properly -->
+                    </a>
+                  </li>';
+                  }
+                  else
+                  {
+                    echo '<li><a href="upgrade.php" class="upgrade icon">Upgrade</a></li>';
+                  }
+                  endif;
+                  ?>
+                </ul>
+              </td>
+            </tr>
+          </table>
+
+<?php
+
+$ui->show_footer();
+
+?>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/install/install.php	Fri Feb 22 12:51:53 2008 -0500
@@ -0,0 +1,282 @@
+<?php
+
+/*
+ * Enano - an open-source CMS capable of wiki functions, Drupal-like sidebar blocks, and everything in between
+ * Version 1.1.1
+ * Copyright (C) 2006-2007 Dan Fuhry
+ * Installation package
+ * install.php - Main installation interface
+ *
+ * This program is Free Software; you can redistribute and/or modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.
+ *
+ * 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.
+ * 
+ * Thanks to Stephan for helping out with l10n in the installer (his work is in includes/stages/*.php).
+ */
+
+define('IN_ENANO', 1);
+// DEFINE THIS BEFORE RELEASE!
+define('ENANO_DANGEROUS', 1);
+
+require_once('includes/common.php');
+@ini_set('display_errors', 'on');
+
+$stages = array('language', 'license', 'sysreqs', 'database', 'website', 'login', 'confirm', 'install', 'finish');
+$stage_ids = array();
+
+if ( isset($_POST['language']) )
+{
+  // Include language lib and additional PHP5-only JSON functions
+  require_once( ENANO_ROOT . '/includes/json2.php' );
+  require_once( ENANO_ROOT . '/includes/lang.php' );
+  
+  // We have a language ID - init language
+  $lang_id = $_POST['language'];
+  if ( !isset($languages[$lang_id]) )
+  {
+    die('Invalid language selection - can\'t load metadata');
+  }
+  
+  $language_dir = $languages[$lang_id]['dir'];
+  
+  // Initialize language support
+  $lang = new Language($lang_id);
+  $lang->load_file(ENANO_ROOT . '/language/' . $language_dir . '/install.json');
+  $lang_uri = 'install.php?do=lang_js&language=%s';
+  
+  // Init UI
+  $ui = new Enano_Installer_UI($lang->get('meta_site_name'), false);
+  
+  // Add stages
+  foreach ( $stages as $stage )
+  {
+    $stage_ids[$stage] = $ui->add_stage($lang->get("{$stage}_modetitle"), true);
+  }
+  
+  // Determine stage
+  if ( isset($_REQUEST['stage']) && isset($stage_ids[$_REQUEST['stage']]) )
+  {
+    $ui->set_visible_stage($stage_ids[$_REQUEST['stage']]);
+    $stage = $_REQUEST['stage'];
+  }
+  else
+  {
+    $stage = 'license';
+  }
+  
+  $stage_num = array_search($stage, $stages);
+  if ( $stage_num )
+  {
+    $stage_num++;
+    $ui->step = $lang->get('meta_step', array('step' => $stage_num, 'title' => $lang->get("{$stage}_modetitle_long")));
+  }
+}
+else
+{
+  $ui = new Enano_Installer_UI('Enano installation', false);
+  
+  if ( version_compare(PHP_VERSION, '5.0.0', '<') )
+  {
+    $ui->__construct('Enano installation', false);
+  }
+  
+  $ui->step = 'Step 1: Choose language';
+  
+  $stage = 'language';
+  $stage_ids['language'] = $ui->add_stage('Language', true);
+  $stage_ids['license'] = $ui->add_stage('License', true);
+  $stage_ids['sysreqs'] = $ui->add_stage('Requirements', true);
+  $stage_ids['database'] = $ui->add_stage('Database', true);
+  $stage_ids['website'] = $ui->add_stage('Site info', true);
+  $stage_ids['login'] = $ui->add_stage('Admin login', true);
+  $stage_ids['confirm'] = $ui->add_stage('Review', true);
+  $stage_ids['install'] = $ui->add_stage('Install', true);
+  $stage_ids['finish'] = $ui->add_stage('Finish', true);
+}
+
+// If we don't have PHP 5, show a friendly error message and bail out
+if ( version_compare(PHP_VERSION, '5.0.0', '<') || isset($_GET['debug_warn_php4']) )
+{
+  $ui->set_visible_stage(
+    $ui->add_stage('PHP compatibility notice', false)
+  );
+  $ui->step = '';
+  $ui->show_header();
+
+  // This isn't localized because all localization code is dependent on
+  // PHP 5 (loading lang.php will throw a parser error under PHP4). This
+  // one message probably doesn't need to be localized anyway.
+  
+  ?>
+  <h2 class="heading-error">
+    Your server doesn't have support for PHP 5.
+  </h2>
+  <p>
+    PHP 5 is the latest version of the language on which Enano was built. Its many new features have been available since early 2004, yet
+    many web hosts have not migrated to it because of the work involved. In 2007, Zend Corporation announced that support for the aging
+    PHP 4.x would be discontinued at the end of the year. An initiative called <a href="http://gophp5.org/">GoPHP5</a> was started to
+    encourage web hosts to migrate to PHP 5.
+  </p>
+  <p>
+    Because of the industry's decision to not support PHP 4 any longer, the Enano team decided that it was time to begin using the powerful
+    features of PHP 5 at the expense of PHP 4 compatibility. Therefore, this version of Enano cannot be installed on your server until it
+    is upgraded to at least PHP 5.0.0, and preferably the latest available version.
+    <!-- No, not even removing the check in this installer script will help. As soon as the PHP4 check is passed, the installer shows the
+         language selection page, after which the language code is loaded. The language code and libjson2 will trigger parse errors under
+         PHP <5.0.0. -->
+  </p>
+  <p>
+    If you need to use Enano but can't upgrade your PHP because you're on a shared or reseller hosting service, you can use the
+    <a href="http://enanocms.org/download?series=1.0">1.0.x series of Enano</a> on your site. While the Enano team attempts to make this
+    older series work on PHP 4, official support is not provided for installations of Enano on PHP 4.
+  </p>
+  <?php
+  
+  $ui->show_footer();
+  exit();
+}
+
+if ( isset($_SERVER['PATH_INFO']) && !isset($_GET['str']) && isset($_GET['do']) )
+{
+  $_GET['str'] = substr($_SERVER['PATH_INFO'], 1);
+}
+
+if ( isset($_GET['do']) )
+{
+  switch ( $_GET['do'] )
+  {
+    case 'lang_js':
+      if ( !isset($_GET['language']) )
+        die();
+      $lang_id = $_GET['language'];
+      header('Content-type: text/javascript');
+      if ( !isset($languages[$lang_id]) )
+      {
+        die('// Bad language ID');
+      }
+      $language_dir = $languages[$lang_id]['dir'];
+      
+      // Include language lib and additional PHP5-only JSON functions
+      require_once( ENANO_ROOT . '/includes/json2.php' );
+      require_once( ENANO_ROOT . '/includes/lang.php' );
+  
+      // Initialize language support
+      $lang = new Language($lang_id);
+      $lang->load_file(ENANO_ROOT . '/language/' . $language_dir . '/install.json');
+      $lang->load_file(ENANO_ROOT . '/language/' . $language_dir . '/core.json');
+      $lang->load_file(ENANO_ROOT . '/language/' . $language_dir . '/user.json');
+      
+      $time_now = microtime_float();
+      $test = "if ( typeof(enano_lang) != 'object' )
+{
+  var enano_lang = new Object();
+  var enano_lang_code = new Object();
+}
+
+enano_lang[{$lang->lang_id}] = " . enano_json_encode($lang->strings) . ";
+enano_lang_code[{$lang->lang_id}] = '{$lang->lang_code}';";
+      $time_total = round(microtime_float() - $time_now, 4);
+      echo "// Generated in $time_total seconds\n";
+      echo $test;
+
+      exit();
+    case 'modrewrite_test':
+      // Include language lib and additional PHP5-only JSON functions
+      require_once( ENANO_ROOT . '/includes/json2.php' );
+      
+      if ( isset($_GET['str']) && in_array($_GET['str'], array('standard', 'shortened', 'rewrite')) )
+      {
+        echo 'good_' . $_GET['str'];
+      }
+      else
+      {
+        echo 'bad';
+      }
+      exit();
+  }
+}
+
+switch ( $stage )
+{
+  default:
+    $ui->show_header();
+    echo '<p>Invalid stage.</p>';
+    break;
+  case 'language':
+    $ui->show_header();
+    ?>
+    <h2>Welcome to Enano.</h2>
+    <h3>Bienvenido a Enano /
+       Wilkommen in Enano /
+       Bienvenue à Enano /
+       Benvenuti a Enano /
+       欢迎 Enano /
+       Enano ã¸ã‚ˆã†ã“ã。
+       </h3>
+    <p>
+       <b>Please select a language:</b> /
+       Por favor, seleccione un idioma: /
+       Bitte wählen Sie eine Sprache: /
+       S’il vous plaît choisir une langue: /
+       Selezionare una lingua: /
+       请选择一ç§è¯­è¨€ï¼š /
+       言語をé¸æŠžã—ã¦ãã ã•ã„:</p>
+    <form action="install.php?stage=license" method="post">
+      <select name="language" style="width: 200px;" tabindex="1">
+        <?php
+        foreach ( $languages as $code => $meta )
+        {
+          $sel = ( $code == 'eng' ) ? ' selected="selected"' : '';
+          echo '<option value="' . $code . '"' . $sel . '>' . $meta['name'] . '</option>';
+        }
+        ?>
+      </select>
+      <input tabindex="2" type="submit" value="&gt;&gt;" />
+    </form>
+    <?php
+    break;
+  case 'license':
+    $ui->show_header();
+    require( ENANO_ROOT . '/includes/wikiformat.php' );
+    require( ENANO_ROOT . '/install/includes/stages/license.php' );
+    break;
+  case 'sysreqs':
+    $ui->show_header();
+    require( ENANO_ROOT . '/install/includes/stages/sysreqs.php' );
+    break;
+  case 'database':
+    if ( isset($_POST['driver']) && in_array($_POST['driver'], $supported_drivers) )
+    {
+      // This is SAFE! It's validated against the array in in_array() above.
+      $driver = $_POST['driver'];
+      require( ENANO_ROOT . "/install/includes/stages/database_{$driver}.php" );
+    }
+    else
+    {
+      $ui->show_header();
+      // No driver selected - give the DB drive selection page
+      require( ENANO_ROOT . '/install/includes/stages/database.php' );
+    }
+    break;
+  case 'website':
+    require( ENANO_ROOT . '/install/includes/stages/website.php' );
+    break;
+  case 'login':
+    require( ENANO_ROOT . '/install/includes/stages/login.php' );
+    break;
+  case 'confirm':
+    require( ENANO_ROOT . '/install/includes/stages/confirm.php' );
+    break;
+  case 'install':
+    require( ENANO_ROOT . '/install/includes/stages/install.php' );
+    break;
+  case 'finish':
+    require( ENANO_ROOT . '/install/includes/stages/finish.php' );
+    break;
+}
+
+$ui->show_footer();
+
+?>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/install/readme.php	Fri Feb 22 12:51:53 2008 -0500
@@ -0,0 +1,41 @@
+<?php
+
+/*
+ * Enano - an open-source CMS capable of wiki functions, Drupal-like sidebar blocks, and everything in between
+ * Version 1.1.1
+ * Copyright (C) 2006-2007 Dan Fuhry
+ * Installation package
+ * install.php - Main installation interface
+ *
+ * This program is Free Software; you can redistribute and/or modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.
+ *
+ * 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.
+ */
+
+require_once('includes/common.php');
+
+$ui = new Enano_Installer_UI('Enano installation', false);
+
+$stg_readme = $ui->add_stage('Readme and important information', true);
+
+$ui->set_visible_stage($stg_readme);
+
+$ui->show_header();
+
+?>
+<h2>Readme</h2>
+<p>This document contains important information you'll want to know before you install Enano. For installation instructions, please
+   see the <a href="http://docs.enanocms.org/Help:2.1">Enano installation guide</a>. <a href="index.php">Return to welcome menu &raquo;</a></p>
+<pre class="scroller"><?php
+
+$readme = @file_get_contents('./README');
+echo htmlspecialchars($readme);
+
+?></pre>
+<?php
+
+$ui->show_footer();
+
+?>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/install/schemas/mysql_stage1.sql	Fri Feb 22 12:51:53 2008 -0500
@@ -0,0 +1,17 @@
+-- Enano - an open-source CMS capable of wiki functions, Drupal-like sidebar blocks, and everything in between
+-- Version 1.1.1
+-- Copyright (C) 2006-2007 Dan Fuhry
+
+-- This program is Free Software; you can redistribute and/or modify it under the terms of the GNU General Public License
+-- as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.
+
+-- 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.
+
+-- mysql_stage1.sql - MySQL installation schema, early stage
+
+CREATE TABLE {{TABLE_PREFIX}}config(
+  config_name varchar(63),
+  config_value text
+) CHARACTER SET `utf8` COLLATE `utf8_bin`;
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/install/schemas/mysql_stage2.sql	Fri Feb 22 12:51:53 2008 -0500
@@ -0,0 +1,389 @@
+-- Enano - an open-source CMS capable of wiki functions, Drupal-like sidebar blocks, and everything in between
+-- Version 1.1.1
+-- Copyright (C) 2006-2007 Dan Fuhry
+
+-- This program is Free Software; you can redistribute and/or modify it under the terms of the GNU General Public License
+-- as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.
+
+-- 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.
+
+-- mysql_stage2.sql - MySQL installation schema, main payload
+
+CREATE TABLE {{TABLE_PREFIX}}categories(
+  page_id varchar(64),
+  namespace varchar(64),
+  category_id varchar(64)
+) CHARACTER SET `utf8` COLLATE `utf8_bin`;
+
+CREATE TABLE {{TABLE_PREFIX}}comments(
+  comment_id int(12) NOT NULL auto_increment,
+  page_id text,
+  namespace text,
+  subject text,
+  comment_data text,
+  name text,
+  approved tinyint(1) default 1,
+  user_id mediumint(8) NOT NULL DEFAULT -1,
+  time int(12) NOT NULL DEFAULT 0,
+  ip_address varchar(39),
+  PRIMARY KEY ( comment_id )
+) CHARACTER SET `utf8` COLLATE `utf8_bin`;
+
+CREATE TABLE {{TABLE_PREFIX}}logs(
+  log_id int(15) NOT NULL auto_increment,
+  log_type varchar(16),
+  action varchar(16),
+  time_id int(12) NOT NULL DEFAULT '0',
+  date_string varchar(63),
+  page_id text,
+  namespace text,
+  page_text text,
+  char_tag varchar(40),
+  author varchar(63),
+  edit_summary text,
+  minor_edit tinyint(1),
+  is_draft tinyint(1) NOT NULL DEFAULT 0,
+  PRIMARY KEY ( log_id )
+) CHARACTER SET `utf8` COLLATE `utf8_bin`;
+
+CREATE TABLE {{TABLE_PREFIX}}page_text(
+  page_id varchar(255),
+  namespace varchar(16) NOT NULL DEFAULT 'Article',
+  page_text text,
+  char_tag varchar(63),
+  FULLTEXT KEY {{TABLE_PREFIX}}page_search_idx (page_id, namespace, page_text)
+) ENGINE = MYISAM CHARACTER SET `utf8`;
+
+CREATE TABLE {{TABLE_PREFIX}}pages(
+  page_order int(8),
+  name varchar(255),
+  urlname varchar(255),
+  namespace varchar(16) NOT NULL DEFAULT 'Article',
+  special tinyint(1) default '0',
+  visible tinyint(1) default '1',
+  comments_on tinyint(1) default '1',
+  protected tinyint(1) NOT NULL DEFAULT 0,
+  wiki_mode tinyint(1) NOT NULL DEFAULT 2,
+  delvotes int(10) NOT NULL DEFAULT 0,
+  password varchar(40) NOT NULL DEFAULT '',
+  delvote_ips text DEFAULT NULL
+) CHARACTER SET `utf8` COLLATE `utf8_bin`;
+
+CREATE TABLE {{TABLE_PREFIX}}session_keys(
+  session_key varchar(32),
+  salt varchar(32),
+  user_id mediumint(8),
+  auth_level tinyint(1) NOT NULL DEFAULT '0',
+  source_ip varchar(10) default '0x7f000001',
+  time bigint(15) default '0'
+) CHARACTER SET `utf8` COLLATE `utf8_bin`;
+
+CREATE TABLE {{TABLE_PREFIX}}themes(
+  theme_id varchar(63),
+  theme_name text,
+  theme_order smallint(5) NOT NULL DEFAULT '1',
+  default_style varchar(63) NOT NULL DEFAULT '',
+  enabled tinyint(1) NOT NULL DEFAULT '1',
+  group_list text DEFAULT NULL,
+  group_policy ENUM('allow', 'deny') NOT NULL DEFAULT 'deny'
+) CHARACTER SET `utf8` COLLATE `utf8_bin`;
+
+CREATE TABLE {{TABLE_PREFIX}}users(
+  user_id mediumint(8) NOT NULL auto_increment,
+  username text,
+  password varchar(255),
+  email text,
+  real_name text,
+  user_level tinyint(1) NOT NULL DEFAULT 2,
+  theme varchar(64) NOT NULL DEFAULT 'bleu.css',
+  style varchar(64) NOT NULL DEFAULT 'default',
+  signature text,
+  reg_time int(11) NOT NULL DEFAULT 0,
+  account_active tinyint(1) NOT NULL DEFAULT 0,
+  activation_key varchar(40) NOT NULL DEFAULT 0,
+  old_encryption tinyint(1) NOT NULL DEFAULT 0,
+  temp_password text,
+  temp_password_time int(12) NOT NULL DEFAULT 0,
+  user_coppa tinyint(1) NOT NULL DEFAULT 0,
+  user_lang smallint(5) NOT NULL DEFAULT 1,
+  user_has_avatar tinyint(1) NOT NULL DEFAULT 0,
+  avatar_type ENUM('jpg', 'png', 'gif') NOT NULL DEFAULT 'png',
+  user_registration_ip varchar(39),
+  user_rank int(12) UNSIGNED NOT NULL DEFAULT 1,
+  user_timezone int(12) UNSIGNED NOT NULL DEFAULT 0,
+  PRIMARY KEY  (user_id)
+) CHARACTER SET `utf8` COLLATE `utf8_bin`;
+
+CREATE TABLE {{TABLE_PREFIX}}users_extra(
+  user_id mediumint(8) NOT NULL,
+  user_aim varchar(63),
+  user_yahoo varchar(63),
+  user_msn varchar(255),
+  user_xmpp varchar(255),
+  user_homepage text,
+  user_location text,
+  user_job text,
+  user_hobbies text,
+  email_public tinyint(1) NOT NULL DEFAULT 0,
+  PRIMARY KEY ( user_id ) 
+) CHARACTER SET `utf8` COLLATE `utf8_bin`;
+
+CREATE TABLE {{TABLE_PREFIX}}banlist(
+  ban_id mediumint(8) NOT NULL auto_increment,
+  ban_type tinyint(1),
+  ban_value varchar(64),
+  is_regex tinyint(1) DEFAULT 0,
+  reason text,
+  PRIMARY KEY ( ban_id ) 
+) CHARACTER SET `utf8` COLLATE `utf8_bin`;
+
+CREATE TABLE {{TABLE_PREFIX}}files(
+  file_id int(12) NOT NULL auto_increment,
+  time_id int(12) NOT NULL,
+  page_id varchar(63) NOT NULL,
+  filename varchar(127) default NULL,
+  size bigint(15) NOT NULL,
+  mimetype varchar(63) default NULL,
+  file_extension varchar(8) default NULL,
+  file_key varchar(32) NOT NULL,
+  PRIMARY KEY (file_id) 
+) CHARACTER SET `utf8` COLLATE `utf8_bin`;
+
+CREATE TABLE {{TABLE_PREFIX}}buddies(
+  buddy_id int(15) NOT NULL auto_increment,
+  user_id mediumint(8),
+  buddy_user_id mediumint(8),
+  is_friend tinyint(1) NOT NULL DEFAULT '1',
+  PRIMARY KEY  (buddy_id) 
+) CHARACTER SET `utf8` COLLATE `utf8_bin`;
+
+CREATE TABLE {{TABLE_PREFIX}}privmsgs(
+  message_id int(15) NOT NULL auto_increment,
+  message_from varchar(63),
+  message_to varchar(255),
+  date int(12),
+  subject varchar(63),
+  message_text text,
+  folder_name varchar(63),
+  message_read tinyint(1) NOT NULL DEFAULT 0,
+  PRIMARY KEY  (message_id) 
+) CHARACTER SET `utf8` COLLATE `utf8_bin`;
+
+CREATE TABLE {{TABLE_PREFIX}}sidebar(
+  item_id smallint(3) NOT NULL auto_increment,
+  item_order smallint(3) NOT NULL DEFAULT 0,
+  item_enabled tinyint(1) NOT NULL DEFAULT 1,
+  sidebar_id smallint(3) NOT NULL DEFAULT 1,
+  block_name varchar(63) NOT NULL,
+  block_type tinyint(1) NOT NULL DEFAULT 0,
+  block_content text,
+  PRIMARY KEY ( item_id )
+) CHARACTER SET `utf8` COLLATE `utf8_bin`;
+
+CREATE TABLE {{TABLE_PREFIX}}hits(
+  hit_id bigint(20) NOT NULL auto_increment,
+  username varchar(63) NOT NULL,
+  time int(12) NOT NULL DEFAULT 0,
+  page_id varchar(63),
+  namespace varchar(63),
+  PRIMARY KEY ( hit_id ) 
+) CHARACTER SET `utf8` COLLATE `utf8_bin`;
+
+CREATE TABLE {{TABLE_PREFIX}}search_index(
+  word varchar(64) NOT NULL,
+  page_names text,
+  PRIMARY KEY ( word ) 
+) CHARACTER SET `utf8` COLLATE `utf8_bin`;
+
+CREATE TABLE {{TABLE_PREFIX}}groups(
+  group_id mediumint(5) UNSIGNED NOT NULL auto_increment,
+  group_name varchar(64),
+  group_type tinyint(1) NOT NULL DEFAULT 1,
+  PRIMARY KEY ( group_id ),
+  system_group tinyint(1) NOT NULL DEFAULT 0 
+) CHARACTER SET `utf8` COLLATE `utf8_bin`;
+
+CREATE TABLE {{TABLE_PREFIX}}group_members(
+  member_id int(12) UNSIGNED NOT NULL auto_increment,
+  group_id mediumint(5) UNSIGNED NOT NULL,
+  user_id int(12) NOT NULL,
+  is_mod tinyint(1) NOT NULL DEFAULT 0,
+  pending tinyint(1) NOT NULL DEFAULT 0,
+  PRIMARY KEY ( member_id ) 
+) CHARACTER SET `utf8` COLLATE `utf8_bin`;
+
+CREATE TABLE {{TABLE_PREFIX}}acl(
+  rule_id int(12) UNSIGNED NOT NULL auto_increment,
+  target_type tinyint(1) UNSIGNED NOT NULL,
+  target_id int(12) UNSIGNED NOT NULL,
+  page_id varchar(255),
+  namespace varchar(24),
+  rules text,
+  PRIMARY KEY ( rule_id ) 
+) CHARACTER SET `utf8` COLLATE `utf8_bin`;
+
+-- Added in 1.0.1
+
+CREATE TABLE {{TABLE_PREFIX}}page_groups(
+  pg_id mediumint(8) NOT NULL auto_increment,
+  pg_type tinyint(2) NOT NULL DEFAULT 1,
+  pg_name varchar(255) NOT NULL DEFAULT '',
+  pg_target varchar(255) DEFAULT NULL,
+  PRIMARY KEY ( pg_id )
+) CHARACTER SET `utf8` COLLATE `utf8_bin`;
+
+-- Added in 1.0.1
+
+CREATE TABLE {{TABLE_PREFIX}}page_group_members(
+  pg_member_id int(12) NOT NULL auto_increment,
+  pg_id mediumint(8) NOT NULL,
+  page_id varchar(63) NOT NULL,
+  namespace varchar(63) NOT NULL DEFAULT 'Article',
+  PRIMARY KEY ( pg_member_id )
+) CHARACTER SET `utf8` COLLATE `utf8_bin`;
+
+-- Added in 1.0.1
+
+CREATE TABLE {{TABLE_PREFIX}}tags(
+  tag_id int(12) NOT NULL auto_increment,
+  tag_name varchar(63) NOT NULL DEFAULT 'bla',
+  page_id varchar(255) NOT NULL,
+  namespace varchar(255) NOT NULL,
+  user_id mediumint(8) NOT NULL DEFAULT 1,
+  PRIMARY KEY ( tag_id )
+) CHARACTER SET `utf8` COLLATE `utf8_bin`;
+
+-- Added in 1.1.1
+
+CREATE TABLE {{TABLE_PREFIX}}lockout(
+  id int(12) NOT NULL auto_increment,
+  ipaddr varchar(40) NOT NULL,
+  action ENUM('credential', 'level') NOT NULL DEFAULT 'credential',
+  timestamp int(12) NOT NULL DEFAULT 0,
+  PRIMARY KEY ( id )
+) CHARACTER SET `utf8` COLLATE `utf8_bin`;
+
+-- Added in 1.1.1
+
+CREATE TABLE {{TABLE_PREFIX}}language(
+  lang_id smallint(5) NOT NULL auto_increment,
+  lang_code varchar(16) NOT NULL,
+  lang_name_default varchar(64) NOT NULL,
+  lang_name_native varchar(64) NOT NULL,
+  last_changed int(12) NOT NULL DEFAULT 0,
+  PRIMARY KEY ( lang_id )
+) CHARACTER SET `utf8` COLLATE `utf8_bin`;
+
+-- Added in 1.1.1
+
+CREATE TABLE {{TABLE_PREFIX}}language_strings(
+  string_id bigint(15) NOT NULL auto_increment,
+  lang_id smallint(5) NOT NULL,
+  string_category varchar(32) NOT NULL,
+  string_name varchar(64) NOT NULL,
+  string_content longtext NOT NULL,
+  PRIMARY KEY ( string_id )
+) CHARACTER SET `utf8` COLLATE `utf8_bin`;
+
+-- Added in 1.1.1
+
+CREATE TABLE {{TABLE_PREFIX}}ranks(
+  rank_id int(12) NOT NULL auto_increment,
+  rank_title varchar(63) NOT NULL DEFAULT '',
+  rank_style varchar(255) NOT NULL DEFAULT '',
+  PRIMARY KEY ( rank_id )
+) CHARACTER SET `utf8` COLLATE `utf8_bin`;
+
+-- Added in 1.1.1
+
+CREATE TABLE {{TABLE_PREFIX}}captcha(
+  code_id int(12) NOT NULL auto_increment,
+  session_id varchar(40) NOT NULL DEFAULT '',
+  code varchar(64) NOT NULL DEFAULT '',
+  session_data text,
+  source_ip varchar(39),
+  user_id int(12),
+  PRIMARY KEY ( code_id )
+) CHARACTER SET `utf8` COLLATE `utf8_bin`;
+
+-- Added in 1.1.3
+-- Storing obscenely huge integers as strings since that's how php processes them.
+
+CREATE TABLE {{TABLE_PREFIX}}diffiehellman (
+  key_id int(12) NOT NULL auto_increment,
+  private_key text,
+  public_key text,
+  PRIMARY KEY ( key_id )
+) CHARACTER SET `utf8` COLLATE `utf8_bin`;
+
+INSERT INTO {{TABLE_PREFIX}}config(config_name, config_value) VALUES
+  ('site_name', '{{SITE_NAME}}'),
+  ('main_page', 'Main_Page'),
+  ('site_desc', '{{SITE_DESC}}'),
+  ('wiki_mode', '{{WIKI_MODE}}'),
+  ('wiki_edit_notice', '0'),
+  ('sflogo_enabled', '0'),
+  ('sflogo_groupid', ''),
+  ('sflogo_type', '1'),
+  ('w3c_vh32', '0'),
+  ('w3c_vh40', '0'),
+  ('w3c_vh401', '0'),
+  ('w3c_vxhtml10', '0'),
+  ('w3c_vxhtml11', '0'),
+  ('w3c_vcss', '0'),
+  ('approve_comments', '0'),
+  ('enable_comments', '1'),
+  ('plugin_SpecialAdmin.php', '1'),
+  ('plugin_SpecialPageFuncs.php', '1'),
+  ('plugin_SpecialUserFuncs.php', '1'),
+  ('plugin_SpecialCSS.php', '1'),
+  ('copyright_notice', '{{COPYRIGHT}}'),
+  ('wiki_edit_notice_text', '== Why can I edit this page? ==\n\nEveryone can edit almost any page in this website. This concept is called a wiki. It gives everyone the opportunity to make a change for the best. While some spam and vandalism may occur, it is believed that most contributions will be legitimate and helpful.\n\nFor security purposes, a history of all page edits is kept, and administrators are able to restore vandalized or spammed pages with just a few clicks.'),
+  ('cache_thumbs', '{{ENABLE_CACHE}}'),
+  ('max_file_size', '256000'),('enano_version', '{{VERSION}}'),( 'allowed_mime_types', 'cbf:len=185;crc=55fb6f14;data=0[1],1[4],0[3],1[1],0[22],1[1],0[16],1[3],0[16],1[1],0[1],1[2],0[6],1[1],0[1],1[1],0[4],1[2],0[3],1[1],0[48],1[2],0[2],1[1],0[4],1[1],0[37]|end' ),
+  ('contact_email', '{{ADMIN_EMAIL}}'),
+  ('powered_btn', '1');
+
+INSERT INTO {{TABLE_PREFIX}}page_text(page_id, namespace, page_text, char_tag) VALUES
+  ('Main_Page', 'Article', '{{MAIN_PAGE_CONTENT}}', '');
+  
+INSERT INTO {{TABLE_PREFIX}}logs(time_id, date_string, log_type, action, page_id, namespace, author, page_text) VALUES
+  ({{UNIX_TIME}}, 'DEPRECATED', 'page', 'edit', 'Main_Page', 'Article', '{{ADMIN_USER}}', '{{MAIN_PAGE_CONTENT}}');
+
+INSERT INTO {{TABLE_PREFIX}}pages(page_order, name, urlname, namespace, special, visible, comments_on, protected, delvotes, delvote_ips) VALUES
+  (NULL, 'Main Page', 'Main_Page', 'Article', 0, 1, 1, 1, 0, '');
+
+INSERT INTO {{TABLE_PREFIX}}themes(theme_id, theme_name, theme_order, default_style, enabled) VALUES
+  ('oxygen', 'Oxygen', 1, 'bleu.css', 1),
+  ('stpatty', 'St. Patty', 2, 'shamrock.css', 1);
+
+INSERT INTO {{TABLE_PREFIX}}users(user_id, username, password, email, real_name, user_level, theme, style, signature, reg_time, account_active, user_registration_ip) VALUES
+  (1, 'Anonymous', 'invalid-pass-hash', 'anonspam@enanocms.org', 'None', 1, 'oxygen', 'bleu', '', 0, 0, '{{IP_ADDRESS}}'),
+  (2, '{{ADMIN_USER}}', '{{ADMIN_PASS}}', '{{ADMIN_EMAIL}}', '{{REAL_NAME}}', 9, 'oxygen', 'bleu', '', UNIX_TIMESTAMP(), 1, '{{IP_ADDRESS}}');
+  
+INSERT INTO {{TABLE_PREFIX}}users_extra(user_id) VALUES
+  (2);
+  
+INSERT INTO {{TABLE_PREFIX}}ranks(rank_id, rank_title, rank_style) VALUES
+  (1, 'user_rank_member', ''),
+  (2, 'user_rank_mod', 'font-weight: bold; color: #00AA00;'),
+  (3, 'user_rank_admin', 'font-weight: bold; color: #AA0000;');
+
+INSERT INTO {{TABLE_PREFIX}}groups(group_id,group_name,group_type,system_group) VALUES(1, 'Everyone', 3, 1),
+  (2,'Administrators',3,1),
+  (3,'Moderators',3,1);
+
+INSERT INTO {{TABLE_PREFIX}}group_members(group_id,user_id,is_mod) VALUES(2, 2, 1);
+
+INSERT INTO {{TABLE_PREFIX}}acl(target_type,target_id,page_id,namespace,rules) VALUES
+  (1,2,NULL,NULL,'read=4;post_comments=4;edit_comments=4;edit_page=4;view_source=4;mod_comments=4;history_view=4;history_rollback=4;history_rollback_extra=4;protect=4;rename=4;clear_logs=4;vote_delete=4;vote_reset=4;delete_page=4;tag_create=4;tag_delete_own=4;tag_delete_other=4;set_wiki_mode=4;password_set=4;password_reset=4;mod_misc=4;edit_cat=4;even_when_protected=4;upload_files=4;upload_new_version=4;create_page=4;html_in_pages=4;php_in_pages={{ADMIN_EMBED_PHP}};edit_acl=4;'),
+  (1,3,NULL,NULL,'read=4;post_comments=4;edit_comments=4;edit_page=4;view_source=4;mod_comments=4;history_view=4;history_rollback=4;history_rollback_extra=4;protect=4;rename=3;clear_logs=2;vote_delete=4;vote_reset=4;delete_page=4;set_wiki_mode=2;password_set=2;password_reset=2;mod_misc=2;edit_cat=4;even_when_protected=4;upload_files=2;upload_new_version=3;create_page=3;php_in_pages=2;edit_acl=2;');
+
+INSERT INTO {{TABLE_PREFIX}}sidebar(item_id, item_order, sidebar_id, block_name, block_type, block_content) VALUES
+  (1, 1, 1, '{lang:sidebar_title_navigation}', 1, '[[Main_Page|{lang:sidebar_btn_home}]]'),
+  (2, 2, 1, '{lang:sidebar_title_tools}', 1, '[[$NS_SPECIAL$CreatePage|{lang:sidebar_btn_createpage}]]\n[[$NS_SPECIAL$UploadFile|{lang:sidebar_btn_uploadfile}]]\n[[$NS_SPECIAL$SpecialPages|{lang:sidebar_btn_specialpages}]]\n{if auth_admin}\n$ADMIN_LINK$\n[[$NS_SPECIAL$EditSidebar|{lang:sidebar_btn_editsidebar}]]\n{/if}'),
+  (3, 3, 1, '$USERNAME$', 1, '[[$NS_USER$$USERNAME$|{lang:sidebar_btn_userpage}]]\n[[$NS_SPECIAL$Contributions/$USERNAME$|{lang:sidebar_btn_mycontribs}]]\n{if user_logged_in}\n[[$NS_SPECIAL$Preferences|{lang:sidebar_btn_preferences}]]\n[[$NS_SPECIAL$PrivateMessages|{lang:sidebar_btn_privatemessages}]]\n[[$NS_SPECIAL$Usergroups|{lang:sidebar_btn_groupcp}]]\n$THEME_LINK$\n{/if}\n{if user_logged_in}\n$LOGOUT_LINK$\n{else}\n[[$NS_SPECIAL$Register|{lang:sidebar_btn_register}]]\n$LOGIN_LINK$\n[[$NS_SPECIAL$Login/$NS_SPECIAL$PrivateMessages|{lang:sidebar_btn_privatemessages}]]\n{/if}'),
+  (4, 4, 1, '{lang:sidebar_title_search}', 1, '<div class="slideblock2" style="padding: 0px;"><form action="$CONTENTPATH$$NS_SPECIAL$Search" method="get" style="padding: 0; margin: 0;"><p><input type="hidden" name="title" value="$NS_SPECIAL$Search" />$INPUT_AUTH$<input name="q" alt="Search box" type="text" size="10" style="width: 70%" /> <input type="submit" value="{lang:sidebar_btn_search_go}" style="width: 20%" /></p></form></div>'),
+  (5, 2, 2, '{lang:sidebar_title_links}', 4, 'Links');
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/install/schemas/postgresql_stage1.sql	Fri Feb 22 12:51:53 2008 -0500
@@ -0,0 +1,17 @@
+-- Enano - an open-source CMS capable of wiki functions, Drupal-like sidebar blocks, and everything in between
+-- Version 1.1.1
+-- Copyright (C) 2006-2007 Dan Fuhry
+
+-- This program is Free Software; you can redistribute and/or modify it under the terms of the GNU General Public License
+-- as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.
+
+-- 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.
+
+-- mysql_stage1.sql - MySQL installation schema, early stage
+
+CREATE TABLE {{TABLE_PREFIX}}config(
+  config_name varchar(63),
+  config_value text
+);
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/install/schemas/postgresql_stage2.sql	Fri Feb 22 12:51:53 2008 -0500
@@ -0,0 +1,386 @@
+-- Enano - an open-source CMS capable of wiki functions, Drupal-like sidebar blocks, and everything in between
+-- Version 1.1.1
+-- Copyright (C) 2006-2007 Dan Fuhry
+
+-- This program is Free Software; you can redistribute and/or modify it under the terms of the GNU General Public License
+-- as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.
+
+-- 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.
+
+-- postgresql_stage2.sql - PostgreSQL installation schema, main payload
+
+CREATE TABLE {{TABLE_PREFIX}}categories(
+  page_id varchar(64),
+  namespace varchar(64),
+  category_id varchar(64)
+);
+
+CREATE TABLE {{TABLE_PREFIX}}comments(
+  comment_id SERIAL,
+  page_id text,
+  namespace text,
+  subject text,
+  comment_data text,
+  name text,
+  approved smallint DEFAULT 1,
+  user_id int NOT NULL DEFAULT -1,
+  time int NOT NULL DEFAULT 0,
+  ip_address varchar(39),
+  PRIMARY KEY ( comment_id )
+);
+
+CREATE TABLE {{TABLE_PREFIX}}logs(
+  log_id SERIAL,
+  log_type varchar(16),
+  action varchar(16),
+  time_id int NOT NULL DEFAULT '0',
+  date_string varchar(63),
+  page_id text,
+  namespace text,
+  page_text text,
+  char_tag varchar(40),
+  author varchar(63),
+  edit_summary text,
+  minor_edit smallint,
+  is_draft smallint NOT NULL DEFAULT 0,
+  PRIMARY KEY ( log_id )
+);
+
+CREATE TABLE {{TABLE_PREFIX}}page_text(
+  page_id varchar(255),
+  namespace varchar(16) NOT NULL DEFAULT 'Article',
+  page_text text,
+  char_tag varchar(63)
+);
+
+CREATE TABLE {{TABLE_PREFIX}}pages(
+  page_order int,
+  name varchar(255),
+  urlname varchar(255),
+  namespace varchar(16) NOT NULL DEFAULT 'Article',
+  special smallint DEFAULT '0',
+  visible smallint DEFAULT '1',
+  comments_on smallint DEFAULT '1',
+  protected smallint NOT NULL DEFAULT 0,
+  wiki_mode smallint NOT NULL DEFAULT 2,
+  delvotes int NOT NULL DEFAULT 0,
+  password varchar(40) NOT NULL DEFAULT '',
+  delvote_ips text DEFAULT NULL
+);
+
+CREATE TABLE {{TABLE_PREFIX}}session_keys(
+  session_key varchar(32),
+  salt varchar(32),
+  user_id int,
+  auth_level smallint NOT NULL DEFAULT '0',
+  source_ip varchar(10) DEFAULT '0x7f000001',
+  time bigint DEFAULT '0'
+);
+
+CREATE TABLE {{TABLE_PREFIX}}themes(
+  theme_id varchar(63),
+  theme_name text,
+  theme_order smallint NOT NULL DEFAULT '1',
+  default_style varchar(63) NOT NULL DEFAULT '',
+  enabled smallint NOT NULL DEFAULT '1',
+  group_list text DEFAULT NULL,
+  group_policy varchar(5) NOT NULL DEFAULT 'deny',
+  CHECK (group_policy IN ('allow', 'deny'))
+);
+
+CREATE TABLE {{TABLE_PREFIX}}users(
+  user_id SERIAL,
+  username text,
+  password varchar(255),
+  email text,
+  real_name text,
+  user_level smallint NOT NULL DEFAULT 2,
+  theme varchar(64) NOT NULL DEFAULT 'bleu.css',
+  style varchar(64) NOT NULL DEFAULT 'DEFAULT',
+  signature text,
+  reg_time int NOT NULL DEFAULT 0,
+  account_active smallint NOT NULL DEFAULT 0,
+  activation_key varchar(40) NOT NULL DEFAULT 0,
+  old_encryption smallint NOT NULL DEFAULT 0,
+  temp_password text,
+  temp_password_time int NOT NULL DEFAULT 0,
+  user_coppa smallint NOT NULL DEFAULT 0,
+  user_lang smallint NOT NULL,
+  user_has_avatar smallint NOT NULL,
+  avatar_type varchar(3) NOT NULL,
+  user_registration_ip varchar(39),
+  user_rank int NOT NULL DEFAULT 1,
+  user_timezone int NOT NULL DEFAULT 0,
+  CHECK (avatar_type IN ('jpg', 'png', 'gif')),
+  PRIMARY KEY  (user_id)
+);
+
+CREATE TABLE {{TABLE_PREFIX}}users_extra(
+  user_id int NOT NULL,
+  user_aim varchar(63),
+  user_yahoo varchar(63),
+  user_msn varchar(255),
+  user_xmpp varchar(255),
+  user_homepage text,
+  user_location text,
+  user_job text,
+  user_hobbies text,
+  email_public smallint NOT NULL DEFAULT 0,
+  PRIMARY KEY ( user_id ) 
+);
+
+CREATE TABLE {{TABLE_PREFIX}}banlist(
+  ban_id SERIAL,
+  ban_type smallint,
+  ban_value varchar(64),
+  is_regex smallint DEFAULT 0,
+  reason text,
+  PRIMARY KEY ( ban_id ) 
+);
+
+CREATE TABLE {{TABLE_PREFIX}}files(
+  file_id SERIAL,
+  time_id int NOT NULL,
+  page_id varchar(63) NOT NULL,
+  filename varchar(127) DEFAULT NULL,
+  size bigint NOT NULL,
+  mimetype varchar(63) DEFAULT NULL,
+  file_extension varchar(8) DEFAULT NULL,
+  file_key varchar(32) NOT NULL,
+  PRIMARY KEY (file_id) 
+);
+
+CREATE TABLE {{TABLE_PREFIX}}buddies(
+  buddy_id SERIAL,
+  user_id int,
+  buddy_user_id int,
+  is_friend smallint NOT NULL DEFAULT '1',
+  PRIMARY KEY  (buddy_id) 
+);
+
+CREATE TABLE {{TABLE_PREFIX}}privmsgs(
+  message_id SERIAL,
+  message_from varchar(63),
+  message_to varchar(255),
+  date int,
+  subject varchar(63),
+  message_text text,
+  folder_name varchar(63),
+  message_read smallint NOT NULL DEFAULT 0,
+  PRIMARY KEY  (message_id) 
+);
+
+CREATE TABLE {{TABLE_PREFIX}}sidebar(
+  item_id SERIAL,
+  item_order smallint NOT NULL DEFAULT 0,
+  item_enabled smallint NOT NULL DEFAULT 1,
+  sidebar_id smallint NOT NULL DEFAULT 1,
+  block_name varchar(63) NOT NULL,
+  block_type smallint NOT NULL DEFAULT 0,
+  block_content text,
+  PRIMARY KEY ( item_id )
+);
+
+CREATE TABLE {{TABLE_PREFIX}}hits(
+  hit_id SERIAL,
+  username varchar(63) NOT NULL,
+  time int NOT NULL DEFAULT 0,
+  page_id varchar(63),
+  namespace varchar(63),
+  PRIMARY KEY ( hit_id ) 
+);
+
+CREATE TABLE {{TABLE_PREFIX}}search_index(
+  word varchar(64) NOT NULL,
+  page_names text,
+  PRIMARY KEY ( word )
+);
+
+CREATE TABLE {{TABLE_PREFIX}}groups(
+  group_id SERIAL,
+  group_name varchar(64),
+  group_type smallint NOT NULL DEFAULT 1,
+  PRIMARY KEY ( group_id ),
+  system_group smallint NOT NULL DEFAULT 0 
+);
+
+CREATE TABLE {{TABLE_PREFIX}}group_members(
+  member_id SERIAL,
+  group_id int NOT NULL,
+  user_id int NOT NULL,
+  is_mod smallint NOT NULL DEFAULT 0,
+  pending smallint NOT NULL DEFAULT 0,
+  PRIMARY KEY ( member_id ) 
+);
+
+CREATE TABLE {{TABLE_PREFIX}}acl(
+  rule_id SERIAL,
+  target_type smallint NOT NULL,
+  target_id int NOT NULL,
+  page_id varchar(255),
+  namespace varchar(24),
+  rules text,
+  PRIMARY KEY ( rule_id ) 
+);
+
+-- Added in 1.0.1
+
+CREATE TABLE {{TABLE_PREFIX}}page_groups(
+  pg_id SERIAL,
+  pg_type smallint NOT NULL DEFAULT 1,
+  pg_name varchar(255) NOT NULL DEFAULT '',
+  pg_target varchar(255) DEFAULT NULL,
+  PRIMARY KEY ( pg_id )
+);
+
+-- Added in 1.0.1
+
+CREATE TABLE {{TABLE_PREFIX}}page_group_members(
+  pg_member_id SERIAL,
+  pg_id int NOT NULL,
+  page_id varchar(63) NOT NULL,
+  namespace varchar(63) NOT NULL DEFAULT 'Article',
+  PRIMARY KEY ( pg_member_id )
+);
+
+-- Added in 1.0.1
+
+CREATE TABLE {{TABLE_PREFIX}}tags(
+  tag_id SERIAL,
+  tag_name varchar(63) NOT NULL DEFAULT 'bla',
+  page_id varchar(255) NOT NULL,
+  namespace varchar(255) NOT NULL,
+  user_id int NOT NULL DEFAULT 1,
+  PRIMARY KEY ( tag_id )
+);
+
+-- Added in 1.1.1
+
+CREATE TABLE {{TABLE_PREFIX}}lockout(
+  id SERIAL,
+  ipaddr varchar(40) NOT NULL,
+  action varchar(20) NOT NULL DEFAULT 'credential',
+  timestamp int NOT NULL DEFAULT 0,
+  CHECK ( action IN ('credential', 'level') )
+);
+
+-- Added in 1.1.1
+
+CREATE TABLE {{TABLE_PREFIX}}language(
+  lang_id SERIAL,
+  lang_code varchar(16) NOT NULL,
+  lang_name_DEFAULT varchar(64) NOT NULL,
+  lang_name_native varchar(64) NOT NULL,
+  last_changed int NOT NULL DEFAULT 0
+);
+
+-- Added in 1.1.1
+
+CREATE TABLE {{TABLE_PREFIX}}language_strings(
+  string_id SERIAL,
+  lang_id int NOT NULL,
+  string_category varchar(32) NOT NULL,
+  string_name varchar(64) NOT NULL,
+  string_content text NOT NULL
+);
+
+-- Added in 1.1.1
+
+CREATE TABLE {{TABLE_PREFIX}}ranks(
+  rank_id SERIAL,
+  rank_title varchar(63) NOT NULL DEFAULT '',
+  rank_style varchar(255) NOT NULL DEFAULT ''
+);
+
+-- Added in 1.1.1
+
+CREATE TABLE {{TABLE_PREFIX}}captcha(
+  code_id SERIAL,
+  session_id varchar(40) NOT NULL DEFAULT '',
+  code varchar(64) NOT NULL DEFAULT '',
+  session_data text,
+  source_ip varchar(39),
+  user_id int
+);
+
+-- Added in 1.1.3
+-- Storing obscenely huge integers as strings since that's how php processes them.
+
+CREATE TABLE {{TABLE_PREFIX}}diffiehellman (
+  key_id SERIAL,
+  private_key text,
+  public_key text,
+  PRIMARY KEY ( key_id )
+);
+
+INSERT INTO {{TABLE_PREFIX}}config(config_name, config_value) VALUES
+  ('site_name', '{{SITE_NAME}}'),
+  ('main_page', 'Main_Page'),
+  ('site_desc', '{{SITE_DESC}}'),
+  ('wiki_mode', '{{WIKI_MODE}}'),
+  ('wiki_edit_notice', '0'),
+  ('sflogo_enabled', '0'),
+  ('sflogo_groupid', ''),
+  ('sflogo_type', '1'),
+  ('w3c_vh32', '0'),
+  ('w3c_vh40', '0'),
+  ('w3c_vh401', '0'),
+  ('w3c_vxhtml10', '0'),
+  ('w3c_vxhtml11', '0'),
+  ('w3c_vcss', '0'),
+  ('approve_comments', '0'),
+  ('enable_comments', '1'),
+  ('plugin_SpecialAdmin.php', '1'),
+  ('plugin_SpecialPageFuncs.php', '1'),
+  ('plugin_SpecialUserFuncs.php', '1'),
+  ('plugin_SpecialCSS.php', '1'),
+  ('copyright_notice', '{{COPYRIGHT}}'),
+  ('wiki_edit_notice_text', '== Why can I edit this page? ==\n\nEveryone can edit almost any page in this website. This concept is called a wiki. It gives everyone the opportunity to make a change for the best. While some spam and vandalism may occur, it is believed that most contributions will be legitimate and helpful.\n\nFor security purposes, a history of all page edits is kept, and administrators are able to restore vandalized or spammed pages with just a few clicks.'),
+  ('cache_thumbs', '{{ENABLE_CACHE}}'),
+  ('max_file_size', '256000'),('enano_version', '{{VERSION}}'),( 'allowed_mime_types', 'cbf:len=185;crc=55fb6f14;data=0[1],1[4],0[3],1[1],0[22],1[1],0[16],1[3],0[16],1[1],0[1],1[2],0[6],1[1],0[1],1[1],0[4],1[2],0[3],1[1],0[48],1[2],0[2],1[1],0[4],1[1],0[37]|end' ),
+  ('contact_email', '{{ADMIN_EMAIL}}'),
+  ('powered_btn', '1');
+
+INSERT INTO {{TABLE_PREFIX}}page_text(page_id, namespace, page_text, char_tag) VALUES
+  ('Main_Page', 'Article', '{{MAIN_PAGE_CONTENT}}', '');
+  
+INSERT INTO {{TABLE_PREFIX}}logs(time_id, date_string, log_type, action, page_id, namespace, author, page_text) VALUES
+  ({{UNIX_TIME}}, 'DEPRECATED', 'page', 'edit', 'Main_Page', 'Article', '{{ADMIN_USER}}', '{{MAIN_PAGE_CONTENT}}');
+
+INSERT INTO {{TABLE_PREFIX}}pages(page_order, name, urlname, namespace, special, visible, comments_on, protected, delvotes, delvote_ips) VALUES
+  (NULL, 'Main Page', 'Main_Page', 'Article', 0, 1, 1, 1, 0, '');
+
+INSERT INTO {{TABLE_PREFIX}}themes(theme_id, theme_name, theme_order, DEFAULT_style, enabled) VALUES
+  ('oxygen', 'Oxygen', 1, 'bleu.css', 1),
+  ('stpatty', 'St. Patty', 2, 'shamrock.css', 1);
+
+INSERT INTO {{TABLE_PREFIX}}users(user_id, username, password, email, real_name, user_level, theme, style, signature, reg_time, account_active, user_registration_ip, user_lang, user_has_avatar, avatar_type) VALUES
+  (1, 'Anonymous', 'invalid-pass-hash', 'anonspam@enanocms.org', 'None', 1, 'oxygen', 'bleu', '', 0, 0, '', 0, 0, 'png'),
+  (2, '{{ADMIN_USER}}', '{{ADMIN_PASS}}', '{{ADMIN_EMAIL}}', '{{REAL_NAME}}', 9, 'oxygen', 'bleu', '', {{UNIX_TIME}}, 1, '{{IP_ADDRESS}}', 0, 0, 'png');
+  
+INSERT INTO {{TABLE_PREFIX}}users_extra(user_id) VALUES
+  (2);
+  
+INSERT INTO {{TABLE_PREFIX}}ranks(rank_id, rank_title, rank_style) VALUES
+  (1, 'user_rank_member', ''),
+  (2, 'user_rank_mod', 'font-weight: bold; color: #00AA00;'),
+  (3, 'user_rank_admin', 'font-weight: bold; color: #AA0000;');
+
+INSERT INTO {{TABLE_PREFIX}}groups(group_id,group_name,group_type,system_group) VALUES(1, 'Everyone', 3, 1),
+  (2,'Administrators',3,1),
+  (3,'Moderators',3,1);
+
+INSERT INTO {{TABLE_PREFIX}}group_members(group_id,user_id,is_mod) VALUES(2, 2, 1);
+
+INSERT INTO {{TABLE_PREFIX}}acl(target_type,target_id,page_id,namespace,rules) VALUES
+  (1,2,NULL,NULL,'read=4;post_comments=4;edit_comments=4;edit_page=4;view_source=4;mod_comments=4;history_view=4;history_rollback=4;history_rollback_extra=4;protect=4;rename=4;clear_logs=4;vote_delete=4;vote_reset=4;delete_page=4;tag_create=4;tag_delete_own=4;tag_delete_other=4;set_wiki_mode=4;password_set=4;password_reset=4;mod_misc=4;edit_cat=4;even_when_protected=4;upload_files=4;upload_new_version=4;create_page=4;html_in_pages=4;php_in_pages={{ADMIN_EMBED_PHP}};edit_acl=4;'),
+  (1,3,NULL,NULL,'read=4;post_comments=4;edit_comments=4;edit_page=4;view_source=4;mod_comments=4;history_view=4;history_rollback=4;history_rollback_extra=4;protect=4;rename=3;clear_logs=2;vote_delete=4;vote_reset=4;delete_page=4;set_wiki_mode=2;password_set=2;password_reset=2;mod_misc=2;edit_cat=4;even_when_protected=4;upload_files=2;upload_new_version=3;create_page=3;php_in_pages=2;edit_acl=2;');
+
+INSERT INTO {{TABLE_PREFIX}}sidebar(item_id, item_order, sidebar_id, block_name, block_type, block_content) VALUES
+  (1, 1, 1, '{lang:sidebar_title_navigation}', 1, '[[Main_Page|{lang:sidebar_btn_home}]]'),
+  (2, 2, 1, '{lang:sidebar_title_tools}', 1, '[[$NS_SPECIAL$CreatePage|{lang:sidebar_btn_createpage}]]\n[[$NS_SPECIAL$UploadFile|{lang:sidebar_btn_uploadfile}]]\n[[$NS_SPECIAL$SpecialPages|{lang:sidebar_btn_specialpages}]]\n{if auth_admin}\n$ADMIN_LINK$\n[[$NS_SPECIAL$EditSidebar|{lang:sidebar_btn_editsidebar}]]\n{/if}'),
+  (3, 3, 1, '$USERNAME$', 1, '[[$NS_USER$$USERNAME$|{lang:sidebar_btn_userpage}]]\n[[$NS_SPECIAL$Contributions/$USERNAME$|{lang:sidebar_btn_mycontribs}]]\n{if user_logged_in}\n[[$NS_SPECIAL$Preferences|{lang:sidebar_btn_preferences}]]\n[[$NS_SPECIAL$PrivateMessages|{lang:sidebar_btn_privatemessages}]]\n[[$NS_SPECIAL$Usergroups|{lang:sidebar_btn_groupcp}]]\n$THEME_LINK$\n{/if}\n{if user_logged_in}\n$LOGOUT_LINK$\n{else}\n[[$NS_SPECIAL$Register|{lang:sidebar_btn_register}]]\n$LOGIN_LINK$\n[[$NS_SPECIAL$Login/$NS_SPECIAL$PrivateMessages|{lang:sidebar_btn_privatemessages}]]\n{/if}'),
+  (4, 4, 1, '{lang:sidebar_title_search}', 1, '<div class="slideblock2" style="padding: 0px;"><form action="$CONTENTPATH$$NS_SPECIAL$Search" method="get" style="padding: 0; margin: 0;"><p><input type="hidden" name="title" value="$NS_SPECIAL$Search" />$INPUT_AUTH$<input name="q" alt="Search box" type="text" size="10" style="width: 70%" /> <input type="submit" value="{lang:sidebar_btn_search_go}" style="width: 20%" /></p></form></div>'),
+  (5, 2, 2, '{lang:sidebar_title_links}', 4, 'Links');
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/install/schemas/upgrade/1.1.1-1.1.2-mysql.sql	Fri Feb 22 12:51:53 2008 -0500
@@ -0,0 +1,36 @@
+-- Enano CMS
+-- Upgrade schema - Enano 1.1.1 - 1.1.2
+
+ALTER TABLE {{TABLE_PREFIX}}logs ADD COLUMN log_id int(15) NOT NULL auto_increment, ADD PRIMARY KEY ( log_id );
+ALTER TABLE {{TABLE_PREFIX}}logs ADD COLUMN is_draft tinyint(1) NOT NULL DEFAULT 0;
+
+ALTER TABLE {{TABLE_PREFIX}}users ADD COLUMN user_rank int(12) UNSIGNED NOT NULL DEFAULT 1,
+                                  ADD COLUMN user_timezone int(12) UNSIGNED NOT NULL DEFAULT 0;
+
+ALTER TABLE {{TABLE_PREFIX}}tags CHANGE user user_id mediumint(8) NOT NULL DEFAULT 1;
+ALTER TABLE {{TABLE_PREFIX}}themes
+  ADD COLUMN group_list text DEFAULT NULL,
+  ADD COLUMN group_policy ENUM('allow', 'deny') NOT NULL DEFAULT 'deny';
+
+CREATE TABLE {{TABLE_PREFIX}}ranks(
+  rank_id int(12) NOT NULL auto_increment,
+  rank_title varchar(63) NOT NULL DEFAULT '',
+  rank_style varchar(255) NOT NULL DEFAULT '',
+  PRIMARY KEY ( rank_id )
+) CHARACTER SET `utf8` COLLATE `utf8_bin`;
+
+CREATE TABLE {{TABLE_PREFIX}}captcha(
+  code_id int(12) NOT NULL auto_increment,
+  session_id varchar(40) NOT NULL DEFAULT '',
+  code varchar(64) NOT NULL DEFAULT '',
+  session_data text,
+  source_ip varchar(39),
+  user_id int(12),
+  PRIMARY KEY ( code_id )
+) CHARACTER SET `utf8` COLLATE `utf8_bin`;
+
+INSERT INTO {{TABLE_PREFIX}}ranks(rank_id, rank_title, rank_style) VALUES
+  (1, 'user_rank_member', ''),
+  (2, 'user_rank_mod', 'font-weight: bold; color: #00AA00;'),
+  (3, 'user_rank_admin', 'font-weight: bold; color: #AA0000;');
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/install/schemas/upgrade/1.1.1-1.1.2-postgresql.sql	Fri Feb 22 12:51:53 2008 -0500
@@ -0,0 +1,35 @@
+-- Enano CMS
+-- Upgrade schema - Enano 1.1.1 - 1.1.2
+
+ALTER TABLE {{TABLE_PREFIX}}logs ADD COLUMN log_id SERIAL, ADD PRIMARY KEY ( log_id );
+ALTER TABLE {{TABLE_PREFIX}}logs ADD COLUMN is_draft smallint NOT NULL DEFAULT 0;
+
+ALTER TABLE {{TABLE_PREFIX}}users ADD COLUMN user_rank int NOT NULL DEFAULT 1,
+                                  ADD COLUMN user_timezone int NOT NULL DEFAULT 0;
+ALTER TABLE {{TABLE_PREFIX}}themes
+  ADD COLUMN group_list text DEFAULT NULL,
+  ADD COLUMN group_policy varchar(5) NOT NULL DEFAULT 'deny',
+  ADD CHECK (group_policy IN ('allow', 'deny'));
+
+CREATE TABLE {{TABLE_PREFIX}}ranks(
+  rank_id SERIAL,
+  rank_title varchar(63) NOT NULL DEFAULT '',
+  rank_style varchar(255) NOT NULL DEFAULT '',
+  PRIMARY KEY ( rank_id )
+);
+
+CREATE TABLE {{TABLE_PREFIX}}captcha(
+  code_id SERIAL,
+  session_id varchar(40) NOT NULL DEFAULT '',
+  code varchar(64) NOT NULL DEFAULT '',
+  session_data text,
+  source_ip varchar(39),
+  user_id int(12),
+  PRIMARY KEY ( code_id )
+);
+
+INSERT INTO {{TABLE_PREFIX}}ranks(rank_id, rank_title, rank_style) VALUES
+  (1, 'user_rank_member', ''),
+  (2, 'user_rank_mod', 'font-weight: bold; color: #00AA00;'),
+  (3, 'user_rank_admin', 'font-weight: bold; color: #AA0000;');
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/install/schemas/upgrade/1.1.2-1.1.3-mysql.sql	Fri Feb 22 12:51:53 2008 -0500
@@ -0,0 +1,11 @@
+-- Enano CMS
+-- Upgrade schema: 1.1.2 - 1.1.3
+
+-- Storing obscenely huge integers as strings since that's how php processes them.
+
+CREATE TABLE {{TABLE_PREFIX}}diffiehellman (
+  key_id int(12) NOT NULL auto_increment,
+  private_key text,
+  public_key text,
+  PRIMARY KEY ( key_id )
+) CHARACTER SET `utf8` COLLATE `utf8_bin`;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/install/schemas/upgrade/1.1.2-1.1.3-postgresql.sql	Fri Feb 22 12:51:53 2008 -0500
@@ -0,0 +1,11 @@
+-- Enano CMS
+-- Upgrade schema: 1.1.2 - 1.1.3
+
+-- Storing obscenely huge integers as strings since that's how php processes them.
+
+CREATE TABLE {{TABLE_PREFIX}}diffiehellman (
+  key_id SERIAL,
+  private_key text,
+  public_key text,
+  PRIMARY KEY ( key_id )
+);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/install/schemas/upgrade/migration/1.0-1.1-mysql.sql	Fri Feb 22 12:51:53 2008 -0500
@@ -0,0 +1,51 @@
+-- Enano - an open-source CMS capable of wiki functions, Drupal-like sidebar blocks, and everything in between
+-- Version 1.1.1
+-- Copyright (C) 2006-2007 Dan Fuhry
+
+-- This program is Free Software; you can redistribute and/or modify it under the terms of the GNU General Public License
+-- as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.
+
+-- 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.
+
+-- 1.0-1.1-mysql.sql - Enano 1.0.x to 1.1.x migration queries, MySQL
+
+ALTER TABLE {{TABLE_PREFIX}}users ADD COLUMN user_lang smallint(5) NOT NULL;
+ALTER TABLE {{TABLE_PREFIX}}users ADD COLUMN user_has_avatar tinyint(1) NOT NULL;
+ALTER TABLE {{TABLE_PREFIX}}users ADD COLUMN avatar_type ENUM('jpg', 'png', 'gif') NOT NULL;
+ALTER TABLE {{TABLE_PREFIX}}users ADD COLUMN user_registration_ip varchar(39);
+ALTER TABLE {{TABLE_PREFIX}}users ADD COLUMN user_timezone int(12) NOT NULL DEFAULT 0;
+ALTER TABLE {{TABLE_PREFIX}}comments ADD COLUMN ip_address varchar(39);
+
+CREATE TABLE {{TABLE_PREFIX}}lockout(
+  id int(12) NOT NULL auto_increment,
+  ipaddr varchar(40) NOT NULL,
+  action ENUM('credential', 'level') NOT NULL DEFAULT 'credential',
+  timestamp int(12) NOT NULL DEFAULT 0,
+  PRIMARY KEY ( id )
+) CHARACTER SET `utf8`;
+
+CREATE TABLE {{TABLE_PREFIX}}language(
+  lang_id smallint(5) NOT NULL auto_increment,
+  lang_code varchar(16) NOT NULL,
+  lang_name_default varchar(64) NOT NULL,
+  lang_name_native varchar(64) NOT NULL,
+  last_changed int(12) NOT NULL DEFAULT 0,
+  PRIMARY KEY ( lang_id )
+) CHARACTER SET `utf8`;
+
+CREATE TABLE {{TABLE_PREFIX}}language_strings(
+  string_id bigint(15) NOT NULL auto_increment,
+  lang_id smallint(5) NOT NULL,
+  string_category varchar(32) NOT NULL,
+  string_name varchar(64) NOT NULL,
+  string_content longtext NOT NULL,
+  PRIMARY KEY ( string_id )
+);
+
+UPDATE {{TABLE_PREFIX}}sidebar SET block_name = '{lang:sidebar_title_navigation}', block_type = 1, block_content = '[[Main_Page|{lang:sidebar_btn_home}]]' WHERE item_id = 1;
+UPDATE {{TABLE_PREFIX}}sidebar SET block_name = '{lang:sidebar_title_tools}',      block_type = 1, block_content = '[[$NS_SPECIAL$CreatePage|{lang:sidebar_btn_createpage}]]\n[[$NS_SPECIAL$UploadFile|{lang:sidebar_btn_uploadfile}]]\n[[$NS_SPECIAL$SpecialPages|{lang:sidebar_btn_specialpages}]]\n{if auth_admin}\n$ADMIN_LINK$\n[[$NS_SPECIAL$EditSidebar|{lang:sidebar_btn_editsidebar}]]\n{/if}' WHERE item_id = 2;
+UPDATE {{TABLE_PREFIX}}sidebar SET block_name = '$USERNAME$',                      block_type = 1, block_content = '[[$NS_USER$$USERNAME$|{lang:sidebar_btn_userpage}]]\n[[$NS_SPECIAL$Contributions/$USERNAME$|{lang:sidebar_btn_mycontribs}]]\n{if user_logged_in}\n[[$NS_SPECIAL$Preferences|{lang:sidebar_btn_preferences}]]\n[[$NS_SPECIAL$PrivateMessages|{lang:sidebar_btn_privatemessages}]]\n[[$NS_SPECIAL$Usergroups|{lang:sidebar_btn_groupcp}]]\n$THEME_LINK$\n{/if}\n{if user_logged_in}\n$LOGOUT_LINK$\n{else}\n[[$NS_SPECIAL$Register|{lang:sidebar_btn_register}]]\n$LOGIN_LINK$\n[[$NS_SPECIAL$Login/$NS_SPECIAL$PrivateMessages|{lang:sidebar_btn_privatemessages}]]\n{/if}' WHERE item_id = 3;
+UPDATE {{TABLE_PREFIX}}sidebar SET block_name = '{lang:sidebar_title_search}',     block_type = 1, block_content = '<div class="slideblock2" style="padding: 0px;"><form action="$CONTENTPATH$$NS_SPECIAL$Search" method="get" style="padding: 0; margin: 0;"><p><input type="hidden" name="title" value="$NS_SPECIAL$Search" />$INPUT_AUTH$<input name="q" alt="Search box" type="text" size="10" style="width: 70%" /> <input type="submit" value="{lang:sidebar_btn_search_go}" style="width: 20%" /></p></form></div>' WHERE item_id = 4;
+UPDATE {{TABLE_PREFIX}}sidebar SET block_name = '{lang:sidebar_title_links}',      block_type = 4, block_content = 'Links' WHERE item_id = 5;
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/install/schemas/upgrade/migration/1.0-1.1.php	Fri Feb 22 12:51:53 2008 -0500
@@ -0,0 +1,50 @@
+<?php
+
+function MIGRATE()
+{
+  global $languages;
+  global $db, $dbdriver;
+  
+  // Database upgrade
+  try
+  {
+    $sql_parser = new SQL_Parser('install/schemas/upgrade/migration/1.0-1.1-' . $dbdriver . '.sql');
+  }
+  catch ( Exception $e )
+  {
+    die("<pre>$e</pre>");
+  }
+  
+  $sql_parser->assign_vars(array(
+      'TABLE_PREFIX' => table_prefix
+    ));
+  
+  $sql_list = $sql_parser->parse();
+  foreach ( $sql_list as $sql )
+  {
+    if ( !$db->sql_query($sql) )
+      $db->_die();
+  }
+  
+  // Install default language
+  $lang_id = 'eng';
+  $lang_data =& $languages[$lang_id];
+  $lang_dir = ENANO_ROOT . "/language/{$lang_data['dir']}/";
+  // function install_language($lang_code, $lang_name_neutral, $lang_name_local, $lang_file = false)
+  install_language($lang_id, $lang_data['name_eng'], $lang_data['name'], $lang_dir . 'core.json');
+  $lang_local = new Language($lang_id);
+  $lang_local->import($lang_dir . "tools.json");
+  $lang_local->import($lang_dir . "user.json");
+  $lang_local->import($lang_dir . "admin.json");
+  
+  // This doesn't set to installer_enano_version() because it only
+  // migrates the database from 1.0.x to 1.1.x status and runs the
+  // core logic required to transform a 1.0.x installation into
+  // a 1.1.x installation. Thus, when upgrading, the upgrade script
+  // still needs to run all later upgrade schema files in addition
+  // to this migration code.
+  setConfig('enano_version', '1.1.1');
+  
+  return true;
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/install/upgrade.php	Fri Feb 22 12:51:53 2008 -0500
@@ -0,0 +1,262 @@
+<?php
+
+/*
+ * Enano - an open-source CMS capable of wiki functions, Drupal-like sidebar blocks, and everything in between
+ * Version 1.1.1
+ * Copyright (C) 2006-2007 Dan Fuhry
+ * Installation package
+ * upgrade.php - Upgrade interface
+ *
+ * This program is Free Software; you can redistribute and/or modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.
+ *
+ * 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.
+ */
+
+define('IN_ENANO', 1);
+
+// The list of versions in THIS BRANCH, in chronological order.
+$enano_versions = array('1.1.1', '1.1.2', '1.1.3');
+
+// Turn on every imaginable API hack to make common load on older databases
+define('IN_ENANO_UPGRADE', 1);
+define('IN_ENANO_MIGRATION', 1);
+define('ENANO_ALLOW_LOAD_NOLANG', 1);
+@ini_set('display_errors', 'on');
+
+require('includes/sql_parse.php');
+
+require_once('includes/common.php');
+// when the installer's common is loaded, it runs chdir() to the ENANO_ROOT, thus making this Enano's common.php
+require_once('includes/common.php');
+@ini_set('display_errors', 'on');
+
+$ui = new Enano_Installer_UI('Enano upgrader', false);
+if ( version_compare(PHP_VERSION, '5.0.0', '<') )
+{
+  $ui->__construct('Enano upgrader', false);
+}
+$stg_welcome = $ui->add_stage('Welcome', true);
+$stg_confirm = $ui->add_stage('Confirmation', true);
+$stg_upgrade = $ui->add_stage('Perform upgrade', true);
+$stg_finish  = $ui->add_stage('Finish', true);
+$stg_php4 = $ui->add_stage('PHP4 compatibility notice', false);
+
+if ( version_compare(PHP_VERSION, '5.0.0', '<') || isset($_GET['debug_warn_php4']) )
+{
+  $ui->set_visible_stage($stg_php4);
+  $ui->step = '';
+  
+  $ui->show_header();
+  
+  // This isn't localized because all localization code is dependent on
+  // PHP 5 (loading lang.php will throw a parser error under PHP4). This
+  // one message probably doesn't need to be localized anyway.
+  
+  ?>
+  <h2 class="heading-error">
+    Your server doesn't have support for PHP 5.
+  </h2>
+  <p>
+    PHP 5 is the latest version of the language on which Enano was built. Its many new features have been available since early 2004, yet
+    many web hosts have not migrated to it because of the work involved. In 2007, Zend Corporation announced that support for the aging
+    PHP 4.x would be discontinued at the end of the year. An initiative called <a href="http://gophp5.org/">GoPHP5</a> was started to
+    encourage web hosts to migrate to PHP 5.
+  </p>
+  <p>
+    Because of the industry's decision to not support PHP 4 any longer, the Enano team decided that it was time to begin using the powerful
+    features of PHP 5 at the expense of PHP 4 compatibility. Therefore, this version of Enano cannot be installed on your server until it
+    is upgraded to at least PHP 5.0.0, and preferably the latest available version.
+    <!-- No, not even removing the check in this installer script will help. As soon as the PHP4 check is passed, the installer shows the
+         language selection page, after which the language code is loaded. The language code and libjson2 will trigger parse errors under
+         PHP <5.0.0. -->
+  </p>
+  <p>
+    If you need to use Enano but can't upgrade your PHP because you're on a shared or reseller hosting service, you can use the
+    <a href="http://enanocms.org/download?series=1.0">1.0.x series of Enano</a> on your site. While the Enano team attempts to make this
+    older series work on PHP 4, official support is not provided for installations of Enano on PHP 4.
+  </p>
+  <?php
+  
+  $ui->show_footer();
+  exit(0);
+}
+
+// Version check
+if ( enano_version() == installer_enano_version() )
+{
+  $ui->show_header();
+  echo '<h3>Already upgraded</h3>' . '<p>You don\'t need to migrate, you\'re already on <del>crack</del> the 1.1 platform.</p>';
+  $ui->show_footer();
+  exit();
+}
+
+// Start session manager
+$session->start();
+if ( !$session->user_logged_in || ( $session->user_logged_in && $session->auth_level < USER_LEVEL_ADMIN ) )
+{
+  if ( isset($_POST['do_login']) )
+  {
+    if ( !$session->user_logged_in )
+    {
+      $result = $session->login_without_crypto($_POST['username'], $_POST['password'], false, USER_LEVEL_MEMBER);
+    }
+    $result = $session->login_without_crypto($_POST['username'], $_POST['password'], false, USER_LEVEL_ADMIN);
+    if ( $result['success'] )
+    {
+      header('HTTP/1.1 302 Some kind of redirect with implied no content');
+      header('Location: ' . scriptPath . '/install/' . $session->append_sid('upgrade.php'));
+      exit();
+    }
+  }
+  
+  $ui->show_header();
+  
+  ?>
+  <h3>Authentication needed</h3>
+  <?php
+  
+  echo '<form action="upgrade.php" method="post">';
+  
+  if ( isset($result) )
+  {
+    echo '<b>Session manager returned error: ' . $result['error'] . '</b>';
+  }
+  
+  ?>
+  <p>You need an active admin session to continue.</p>
+  <p>
+    Username:&nbsp;&nbsp;&nbsp;<input type="text" name="username" /><br />
+    Password:&nbsp;&nbsp;&nbsp;<input type="password" name="password" /><br />
+    <input type="submit" name="do_login" value="Log in" />
+  </p>
+  <?php
+  
+  echo '</form>';
+  
+  $ui->show_footer();
+  exit();
+}
+
+if ( isset($_GET['stage']) && @$_GET['stage'] == 'pimpmyenano' )
+{
+  $ui->set_visible_stage($stg_upgrade);
+}
+else
+{
+  $ui->set_visible_stage($stg_confirm);
+}
+
+// The real migration code
+$ui->show_header();
+
+if ( isset($_GET['stage']) && @$_GET['stage'] == 'pimpmyenano' )
+{
+  // Do we need to run the migration first?
+  if ( substr(enano_version(), 0, 4) != '1.1.' )
+  {
+    require(ENANO_ROOT . '/install/upgrade/migration/1.0-1.1.php');
+    $result = MIGRATE();
+    if ( !$result )
+    {
+      echo 'Migration failed, there should be an error message above.';
+      $ui->show_footer();
+      exit;
+    }
+  }
+  // Main upgrade stage
+  
+  // Init vars
+  $version_flipped = array_flip($enano_versions);
+  $version_curr = enano_version();
+  $version_target = installer_enano_version();
+  
+  // Calculate which scripts to run
+  if ( !isset($version_flipped[$version_curr]) )
+  {
+    echo '<p>ERROR: Unsupported version</p>';
+    $ui->show_footer();
+    exit;
+  }
+  if ( !isset($version_flipped[$version_target]) )
+  {
+    echo '<p>ERROR: Upgrader doesn\'t support its own version</p>';
+    $ui->show_footer();
+    exit;
+  }
+  $upg_queue = array();
+  for ( $i = $version_flipped[$version_curr]; $i < $version_flipped[$version_target]; $i++ )
+  {
+    if ( !isset($enano_versions[$i + 1]) )
+    {
+      echo '<p>ERROR: Unsupported intermediate version</p>';
+      $ui->show_footer();
+      exit;
+    }
+    $ver_this = $enano_versions[$i];
+    $ver_next = $enano_versions[$i + 1];
+    $upg_queue[] = array($ver_this, $ver_next);
+  }
+  
+  // Verify that all upgrade scripts are usable
+  foreach ( $upg_queue as $verset )
+  {
+    $file = ENANO_ROOT . "/install/schemas/upgrade/{$verset[0]}-{$verset[1]}-$dbdriver.sql";
+    if ( !file_exists($file) )
+    {
+      echo "<p>ERROR: Couldn't find required schema file: $file</p>";
+      $ui->show_footer();
+      exit;
+    }
+  }
+  // Perform upgrade
+  foreach ( $upg_queue as $verset )
+  {
+    $file = ENANO_ROOT . "/install/schemas/upgrade/{$verset[0]}-{$verset[1]}-$dbdriver.sql";
+    try
+    {
+      $parser = new SQL_Parser($file);
+    }
+    catch(Exception $e)
+    {
+      die("<pre>$e</pre>");
+    }
+    
+    $parser->assign_vars(array(
+      'TABLE_PREFIX' => table_prefix
+    ));
+  
+    $sql_list = $parser->parse();
+  
+    foreach ( $sql_list as $sql )
+    {
+      if ( !$db->sql_query($sql) )
+        $db->_die();
+    }
+    
+    // Is there an additional script (logic) to be run after the schema?
+    $postscript = ENANO_ROOT . "/install/schemas/upgrade/{$verset[0]}-{$verset[1]}.php";
+    if ( file_exists($postscript) )
+      @include($postscript);
+    
+    // The advantage of calling setConfig on the system version here?
+    // Simple. If the upgrade fails, it will pick up from the last
+    // version, not try to start again from the beginning. This will
+    // still cause errors in most cases though. Eventually we probably
+    // need some sort of query-numbering system that tracks in-progress
+    // upgrades.
+    
+    setConfig('enano_version', $verset[1]);
+  }
+  echo '<p>All done!</p>';
+}
+else
+{
+  ?>
+  <p>Nothing's really implemented for now except the actual migration code, which is not very smart. Just <a href="<?php echo $session->append_sid('upgrade.php?stage=pimpmyenano'); ?>">do the upgrade and get it over with</a>.</p>
+  <?php
+}
+
+$ui->show_footer();
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/language/english/admin.json	Fri Feb 22 12:51:53 2008 -0500
@@ -0,0 +1,913 @@
+/*
+ * Enano - an open-source CMS capable of wiki functions, Drupal-like sidebar blocks, and everything in between
+ * Version 1.1.1
+ * Copyright (C) 2006-2007 Dan Fuhry
+ *
+ * This program is Free Software; you can redistribute and/or modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.
+ *
+ * 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.
+ */
+
+var enano_lang = {
+  categories: [
+    'meta', 'adm', 'acl', 'adminusers',
+    'acphome', 'acpgc', 'acpup', 'acpft', 'acppl', 'acppm', 'acped', 'acpdb', 'acplm', 'acppg', 'acpum', 'acpug', 'acpcp', 'acpmm', 'acpsl',
+    'acpbc', 'acplo', 'acptm', 'sbedit',
+  ],
+  strings: {
+    meta: {
+      adm: 'Administration panel nav menu',
+      acl: 'Access control list editor',
+      acphome: 'ACP: Home',
+      acpgc: 'ACP: General configuration',
+      acpup: 'ACP: File uploads',
+      acpft: 'ACP: Allowed file types',
+      acppl: 'ACP: Manage plugins',
+      acpdb: 'ACP: Database backup',
+      acplm: 'ACP: Language manager',
+      acppm: 'ACP: Manage pages',
+      acped: 'ACP: Edit page content',
+      acptm: 'ACP: Theme manager',
+      acppg: 'ACP: Page groups',
+      acpum: 'ACP: User management',
+      acpug: 'ACP: User group management',
+      acpcp: 'ACP: COPPA support',
+      acpmm: 'ACP: Mass e-mail',
+      acpsl: 'ACP: Security log',
+      acpbc: 'ACP: Ban control',
+      acplo: 'ACP: Logout page',
+      sbedit: 'Sidebar editor',
+    },
+    adm: {
+      page_tagline: 'Administer your Enano website.',
+      
+      cat_general: 'General',
+      cat_content: 'Content',
+      cat_appearance: 'Appearance',
+      cat_users: 'Users',
+      cat_security: 'Security',
+      cat_plugins: 'Plugin configuration',
+      
+      page_general_config: 'General configuration',
+      page_file_uploads: 'File uploads',
+      page_file_types: 'Allowed file types',
+      page_plugins: 'Manage plugins',
+      page_db_backup: 'Backup database',
+      page_lang_manager: 'Language manager',
+      
+      page_manager: 'Manage pages',
+      page_editor: 'Edit page content',
+      page_pg_groups: 'Manage page groups',
+      
+      page_themes: 'Manage themes',
+      
+      page_users: 'Manage users',
+      page_user_groups: 'Edit user groups',
+      page_coppa: 'COPPA support',
+      page_mass_email: 'Mass e-mail',
+      
+      page_security_log: 'Security log',
+      page_ban_control: 'Ban control',
+      
+      btn_home: 'Administration panel home',
+      btn_logout: 'Log out of admin panel',
+      btn_keepalive_off: 'Turn on keep-alive',
+      btn_keepalive_on: 'Turn off keep-alive',
+      btn_keepalive_about: 'About keep-alive',
+      btn_keepalive_loading: 'Loading keep-alive button...',
+      
+      err_not_auth_title: 'Error: Not authenticated',
+      err_not_auth_body: 'It looks like your administration session is invalid or you are not authorized to access this administration page. Please <a href="%login_link%">re-authenticate</a> to continue.',
+    },
+    acl: {
+      err_access_denied: 'You are not authorized to view or edit access control lists.',
+      err_missing_template: 'It seems that (a) the file acledit.tpl is missing from this theme, and (b) the JSON response is working.',
+      err_user_not_found: 'The username you entered was not found.',
+      err_bad_group_id: 'The group ID you submitted is not valid.',
+      err_demo: 'Editing access control lists is disabled in the administration demo.',
+      err_zero_list: 'Supplied rule list has a length of zero',
+      err_pleaseselect_targettype: 'Please select a target type.',
+      err_pleaseselect_username: 'Please enter a username.',
+      
+      radio_usergroup: 'A usergroup',
+      radio_user: 'A specific user',
+      radio_scope_thispage: 'Only this page',
+      radio_scope_wholesite: 'The entire website',
+      radio_scope_pagegroup: 'A group of pages',
+      
+      lbl_scope: 'What should this access rule control?',
+      lbl_welcome_title: 'Manage page access',
+      lbl_welcome_body: 'Please select who should be affected by this access rule.',
+      lbl_editwin_title_create: 'Create access rule',
+      lbl_editwin_title_edit: 'Editing permissions',
+      lbl_editwin_body: 'This panel allows you to edit what the %target_type% "<b>%target%</b>" can do on <b>%scope_type%</b>. Unless you set a permission to "Deny", these permissions may be overridden by other rules.',
+      lbl_deleterule: 'Delete this rule',
+      lbl_save_success_title: 'Permissions updated',
+      lbl_save_success_body: 'The permissions for %target_name% on this page have been updated successfully. If you changed permissions that affect your user account, you may not see changes until you reload the page.',
+      lbl_delete_success_title: 'Rule deleted',
+      lbl_delete_success_body: 'The access rules for %target_name% on this page have been deleted.',
+      lbl_field_inherit: 'Inherit',
+      lbl_field_deny: 'Deny',
+      lbl_field_disallow: 'Disallow',
+      lbl_field_wikimode: 'Wiki mode',
+      lbl_field_allow: 'Allow',
+      lbl_help: '<p>
+                   <b>Permission types:</b>
+                 </p>
+                 <ul>
+                   <li><b>Allow</b> means that the user is allowed to access the item</li>
+                   <li><b>Wiki mode</b> means the user can access the item if wiki mode is active (per-page wiki mode is taken into account)</li>
+                   <li><b>Disallow</b> means the user is denied access unless something allows it.</li>
+                   <li><b>Deny</b> means that the user is denied access to the item. This setting overrides all other permissions.</li>
+                   <li><b>Inherit</b> forces the permission to be unset and thus inherited from the defaults. Setting every permission to Inherit is the same as deleting the rule.</li>
+                 </ul>',
+      
+      scope_type_wholesite: 'this entire site',
+      scope_type_thispage: 'this page',
+      scope_type_pagegroup: 'this group of pages',
+      
+      target_type_user: 'user',
+      target_type_group: 'group',
+      
+      msg_guest_howto: 'To edit permissions for guests, select "a specific user", and enter Anonymous as the username.',
+      msg_deleterule_confirm: 'Do you really want to delete this rule?',
+      msg_closeacl_confirm: 'Do you really want to close the ACL manager?',
+      
+      btn_success_dismiss: 'dismiss',
+      btn_success_close: 'close manager',
+      btn_deleterule: 'Delete rule',
+      btn_createrule: 'Create rule',
+      btn_returnto_editor: 'Return to ACL editor',
+      btn_returnto_userscope: 'Return to user/scope selection',
+    },
+    acphome: {
+      heading_main: 'Welcome to Runt, the Enano administration panel.',
+      welcome_line1: 'Thank you for choosing Enano as your CMS. This screen allows you to see some information about your website, plus some details about how your site is doing statistically.',
+      welcome_line2: 'Using the links on the left you can control every aspect of your website\'s look and feel, plus you can manage users, work with pages, and install plugins to make your Enano installation even better.',
+      msg_demo_title: 'Enano is running in demo mode.',
+      msg_demo_body: 'If you borked something up, or if you\'re done testing, you can <a href="%reset_url%">reset this site</a>. The site is reset automatically once every two hours. When a reset is performed, all custom modifications to the site are lost and replaced with default values.',
+      msg_install_files: '<b>NOTE:</b> It appears that your install.php and/or schema.sql files still exist. It is HIGHLY RECOMMENDED that you delete or rename these files, to prevent getting your server hacked.',
+      heading_updates: 'Check for updates',
+      msg_updates_info: 'Periodically, new releases of Enano will be made available. Click the button below to check for updates to Enano. During this process, a request will be sent to the Enano CMS server (germantown.enanocms.org) over HTTP for an <a href="%updates_url%">XML file</a> containing a list of the latest releases. No information about your Enano installation will be transmitted.',
+      btn_check_updates: 'Check for updates',
+      msg_inactive_users_one: 'It appears that 1 user is awaiting account activation. You can activate the account by going to the <a %um_flags%>User Manager</a>.',
+      msg_inactive_users_plural: 'It appears that %num_users% users are awaiting account activation. You can activate those accounts by going to the <a %um_flags%>User Manager</a>.',
+      heading_top_pages: 'Most requested pages',
+      th_toppages_page: 'Page',
+      th_toppages_hits: 'Hits',
+      heading_seclog: 'Security log',
+      msg_seclog_info: 'This list shows the 5 most recent actions/attempted actions performed by administrators on this site. This also includes attempts to view blocked pages and use the administration panel without appropriate privileges. You can view a complete list using the link below.',
+      btn_seclog_full: 'Full security log',
+    },
+    acpgc: {
+      err_avatar_dir_invalid: 'You have entered an invalid avatar directory.',
+      msg_save_success: 'Your changes to the site configuration have been saved.',
+      
+      // Section: global site options
+      heading_main: 'Global site options',
+      heading_submain: 'These options control the entire site.',
+      field_site_name: 'Site name:',
+      field_site_desc: 'Site description:',
+      field_main_page: 'Main page:',
+      field_copyright: 'Copyright notice shown on pages:',
+      field_copyright_hint: 'Hint: If you\'re using Windows, you can make a "&copy;" symbol by holding ALT and pressing 0169 on the numeric keypad.',
+      field_contactemail: 'Contact e-mail',
+      field_contactemail_hint: 'All e-mail sent from this site will appear to have come from the address shown here.',
+      
+      // Section: wiki mode
+      heading_wikimode: 'Wiki mode',
+      field_wikimode_intro: 'Enano can also act as a wiki, meaning anyone can edit and create pages. To enable Wiki Mode, check the box to the right.',
+      field_wikimode_info_sanitize: 'In Wiki Mode, certain HTML tags such as &lt;script&gt; and &lt;object&gt; are disabled, and all PHP code is disabled, except if the person editing the page is an administrator.',
+      field_wikimode_info_history: 'Also, Enano keeps complete page history, which makes restoring vandalized pages easy. You can also protect pages so that they cannot be edited.',
+      field_wikimode: 'Enable Wiki Mode',
+      field_editnotice_title: 'Edit page notice',
+      field_editnotice_info: 'When Wiki Mode is enabled, anyone can edit pages. Check the box below and enter a message to display it whenever the page editor is opened. Administrators often use this field to display a legal disclaimer or a notice of what license the user agrees to submit their content under.',
+      field_editnotice: 'Show a message whenever pages are edited',
+      field_edit_require_captcha_title: 'Require visual confirmation for guests editing pages',
+      field_edit_require_captcha_hint: 'If this is enabled, guests will be asked to enter a visual confirmation code before saving changes to a page.',
+      field_edit_require_captcha: 'Require guests to complete a CAPTCHA when editing pages',
+      
+      // Section: statistics and hit counting
+      heading_stats: 'Statistics and hit counting',
+      stats_intro: 'Enano has the ability to show statistics for every page on the site. This allows you to keep very close track of who is visiting your site, and from where.',
+      stats_hint_privacy: 'Unfortunately, some users don\'t like being logged. For this reason, you should state clearly what is logged (usually the username or IP address, current time, page name, and referer URL) in your privacy policy. If your site is primarily geared towards children, and you are a United States citizen, you are required to have a privacy policy stating exactly what is being logged under the terms of the Childrens\' Online Privacy Protection Act.',
+      field_stats_enable: 'Log all page hits',
+      field_stats_hint: 'This excludes special and administration pages.',
+      
+      // Section: comment system
+      heading_comments: 'Comment system',
+      field_enable_comments: 'Enable the comment system',
+      field_approve_comments: 'Require approval before article comments can be shown',
+      field_comment_allow_guests: 'Allow guests to post comments',
+      field_comment_allow_guests_yes: 'Yes',
+      field_comment_allow_guests_captcha: 'Require visual confirmation',
+      field_comment_allow_guests_no: 'No (require login)',
+      
+      // Section: disable site
+      heading_disablesite: 'Disable all site access',
+      field_disablesite_hint: 'Disabling the site allows you to work on the site without letting non-administrators see or use it.',
+      field_disablesite: 'Disable this site',
+      field_disablesite_message: 'Message to show to users:',
+      
+      // Main section: users and communication
+      heading_users: 'Users and communication',
+      
+      // Section: account activation
+      heading_activate: 'User account activation',
+      activate_intro_line1: 'If you would like to require users to confirm their e-mail addresses by way of account activation, you can enable this behavior here. If this option is set to "None", users will be able to register and use this site without confirming their e-mail addresses. If this option is set to "User", users will automatically be sent e-mails upon registration with a link to activate their accounts. And lastly, if this option is set to "Admin", users\' accounts will not be active until an administrator activates the account.',
+      activate_intro_line2: 'You may also disable registration completely if needed.',
+      activate_intro_sfnet_warning: 'Note: because of abuse by project administrators, sending account activation e-mails will not work on SourceForge.net servers.',
+      field_activate: 'Account activation:',
+      field_activate_disable: 'Disable registration',
+      field_activate_none: 'None',
+      field_activate_user: 'User',
+      field_activate_admin: 'Admin',
+      
+      // Section: terms of use (TOU)
+      heading_tou: 'Registration agreement/Terms of Use',
+      field_tou: 'Registration agreement',
+      field_tou_hint: 'The text you enter here will be displayed to users upon any attempt to create an account on this site.',
+      
+      // Section: account lockouts
+      heading_lockout: 'Account lockouts',
+      lockout_intro: 'Configure Enano to prevent or restrict logins for a specified period of time if a user enters an incorrect password a specific number of times.',
+      field_lockout_threshold: 'Lockout threshold:',
+      field_lockout_threshold_hint: 'How many times can a user enter wrong credentials before a lockout goes into effect?',
+      field_lockout_duration: 'Lockout duration:',
+      field_lockout_duration_hint: 'This is how long an account lockout should last, in minutes.',
+      field_lockout_policy: 'Lockout policy:',
+      field_lockout_policy_hint: 'What should be done when a lockout goes into effect?',
+      field_lockout_policy_nothing: 'Don\'t do anything',
+      field_lockout_policy_captcha: 'Require visual confirmation',
+      field_lockout_policy_lockout: 'Prevent all login attempts',
+      
+      // Section: password strength
+      heading_passstrength: 'Password strength',
+      field_passstrength_title: 'Enable password strength analysis',
+      field_passstrength_hint: 'This should be enabled in most cases. When this is enabled, a strength meter and a numerical score will be displayed wherever a password can be changed.',
+      field_passstrength: 'Enabled',
+      field_passminimum_title: 'Minimum strength score',
+      field_passminimum_hint: 'This is the lowest score a password will be allowed to have. -10 will allow any password. A score of under -3 is considered weak, under 1 is fair, under 4 is good, under 10 is strong, and 10 and above are very strong. The scale is open-ended. This only has an effect if the meter is enabled above.',
+      
+      // Section: e-mail
+      heading_email: 'E-mail sent from the site',
+      field_email_method: 'E-mail sending method:',
+      field_email_method_hint: 'Try using the built-in e-mail method first. If that doesn\'t work, you will need to enter valid SMTP information here.',
+      field_email_method_builtin: 'PHP\'s built-in mail() function',
+      field_email_method_smtp: 'Use an external SMTP server',
+      field_email_smtp_hostname: 'SMTP hostname:',
+      field_email_smtp_hostname_hint: 'This option only applies to the external SMTP mode.',
+      field_email_smtp_auth: 'SMTP credentials:',
+      field_email_smtp_username: 'Username:',
+      field_email_smtp_password: 'Password:',
+      
+      // Section: avatars
+      heading_avatars: 'Avatars',
+      avatars_intro: 'Avatars are small images that users can display on their profiles and in comments.',
+      field_avatar_enable: 'Enable avatar support:',
+      field_avatar_enable_hint: 'Supported formats are JPEG, PNG, and GIF&trade;.',
+      field_avatar_enable_label: 'Enabled',
+      field_avatar_max_filesize: 'Maximum avatar file size:',
+      field_avatar_max_filesize_hint: 'For smaller sites, the highest value for this should be about 50KB, 51200. Larger sites with more visitors will likely want to use something much smaller, such as 10KB.',
+      field_avatar_max_dimensions: 'Maximum avatar dimensions:',
+      field_avatar_max_dimensions_hint: 'The format is width &#215; height. Typically you want to have this square (the same width and height). These are only maximum dimensions; users are not prevented from having smaller images.',
+      field_avatar_allow_anim_title: 'Allow animated avatars:',
+      field_avatar_allow_anim_hint: 'If this is checked, users can upload APNG and Animated GIF&trade; avatars. Sometimes such images can be specifically made to be distracting, like rapidly flashing images. If this is unchecked, these formats will be blocked, and only still PNGs and GIFs will be allowed.',
+      field_avatar_allow_anim: 'Don\'t block animated images',
+      field_avatar_upload_methods: 'Allowed upload methods:',
+      field_avatar_upload_file: 'Allow users to upload image files from their computers',
+      field_avatar_upload_http: 'Allow users to enter a URL to their desired avatar',
+      field_avatar_directory: 'Avatar storage directory:',
+      field_avatar_directory_hint: 'This should be relative to your Enano root and should contain only alphanumeric characters and forward slashes, even if your server runs Windows.',
+      
+      // Main section: sidebar links
+      heading_sidebar: 'Sidebar links',
+      
+      // Section: promote Enano
+      heading_promoteenano: 'Promote Enano',
+      field_enano_link_title: 'If you think Enano is nice, or if you want to show your support for the Enano team, you can do so by placing a link to the Enano homepage in your Links sidebar block. You absolutely don\'t have to do this, and you won\'t get degraded support if you don\'t. Because Enano is still relatively new in the CMS world, it needs all the attention it can get - and you can easily help to spread the word using this link. Note that this is different from the "Powered by Enano" link in the footer of the page - our philosophy and guidelines regarding the About Enano page and its associated link on every page are discussed on the <a href="http://enanocms.org/Licensing_specifics">Enano website</a>.',
+      field_enano_link: 'Place a link to enanocms.org on the sidebar',
+      
+      // Section: SF.net logo
+      heading_sfnet_logo: 'SourceForge.net logo',
+      sfnet_intro: 'All projects hosted by SourceForge.net are required to display an official SourceForge.net logo on their pages.  If you want to display a SourceForge.net logo on the sidebar, check the box below, enter your group ID, and select an image type.',
+      field_sfnet_display: 'Display the SourceForge.net logo on the right sidebar',
+      field_sfnet_group_id: 'Group ID:',
+      field_sfnet_logo_style: 'Logo style:',
+      field_sfnet_logo_style_1: '88x31%this.etc_unit_pixels_short%, white',
+      field_sfnet_logo_style_2: '125x37%this.etc_unit_pixels_short%, white',
+      field_sfnet_logo_style_3: '125x37%this.etc_unit_pixels_short%, black',
+      field_sfnet_logo_style_4: '125x37%this.etc_unit_pixels_short%, blue',
+      field_sfnet_logo_style_5: '210x62%this.etc_unit_pixels_short%, white',
+      field_sfnet_logo_style_6: '210x62%this.etc_unit_pixels_short%, black',
+      field_sfnet_logo_style_7: '210x62%this.etc_unit_pixels_short%, blue',
+      
+      // Section: W3C validation buttons
+      heading_w3clogos: 'W3C compliance logos',
+      w3clogos_intro: 'Enano generates (by default) Valid XHTML 1.1 code, plus valid CSS.  If you want to show this off, check the appropriate boxes below.',
+      w3clogos_btn_html32: 'HTML 3.2',
+      w3clogos_btn_html40: 'HTML 4.0',
+      w3clogos_btn_html401: 'HTML 4.01',
+      w3clogos_btn_xhtml10: 'XHTML 1.0',
+      w3clogos_btn_xhtml11: 'XHTML 1.1',
+      w3clogos_btn_css: 'CSS',
+      
+      // Section Defective By Design link
+      heading_dbd: 'Defective By Design Anti-DRM button',
+      dbd_intro: 'The Enano project is strongly against Digital Restrictions Management.',
+      dbd_explain: 'DRM removes the freedoms that every consumer should have: to freely copy and use digital media items they legally purchased to their own devices. Showing your opposition to DRM is as easy as checking the box below to place a link to <a href="http://www.defectivebydesign.org">DefectiveByDesign.org</a> on your sidebar.',
+      field_stopdrm: 'Help stop DRM by placing a link to DBD on the sidebar!',
+      
+      // Save button
+      btn_save_changes: 'Save changes'
+    },
+    acpup: {
+      heading_main: 'File upload configuration',
+      intro: 'Enano supports the ability to upload files to your website and store the files in the database. This enables you to embed images and such into pages without manually writing the HTML. However, the upload feature can sometimes pose a risk to your site, as viruses and executable files can sometimes be uploaded.',
+      field_enable: 'Enable file uploads',
+      field_max_size: 'Maximum file size:',
+      info_magick: 'You can allow Enano to generate thumbnails of images automatically. This feature requires ImageMagick to work properly. If your server does not have ImageMagick on it, Enano will try to use the GD library (if available) to scale images. This can be slower, but it works on a wider range of servers. If even that does not work, Enano will simply make your users\' browsers scale the images. In most cases this is fine, but if you are uploading large (>100KB) images and embedding them inside of pages, you should try to enable ImageMagick or configure GD because transferring these large images many times can cost you quite a lot of bandwidth.',
+      field_magick_enable: 'Use ImageMagick to scale images',
+      field_magick_path: 'Path to ImageMagick:',
+      err_magick_not_found: '<b>Warning:</b> the file "%magick_path%" was not found, and the ImageMagick file path was not updated.',
+      // Translators: for the path here, please be sure to use a double-backslash in the Windows path. Avoid translating the file paths
+      // anyway since they're generally the same even on non-English Windows systems.
+      field_magick_path_hint: 'On Linux and Unix servers, the most likely options here are /usr/bin/convert and /usr/local/bin/convert. If you server runs Windows, then ImageMagick is most likely to be C:\\Windows\\Convert.exe or C:\\Windows\\System32\\Convert.exe.',
+      info_cache: 'If you use ImageMagick to scale images, your server will be very busy constantly scaling images if your website is busy, and your site may experience slowdowns. You can dramatically speed up this scaling process if you use a directory to cache thumbnail images.',
+      info_cache_chmod: '<b>Please note:</b> the cache/ directory on your server <u>must</u> be writable by the server. While this is not usually a problem on Windows servers, most Linux/Unix servers will require you to CHMOD the cache/ directory to 777. See your FTP client\'s user guide for more information on how to do this.',
+      msg_cache_not_writable: ' <b>At present, it seems that the cache directory is not writable. The checkbox below has been disabled to maintain the stability of Enano.</b>',
+      field_cache: 'Cache thumbnailed images',
+      info_history: 'Lastly, you can choose whether file history will be saved. If this option is turned on, you will be able to roll back any malicious changes made to uploaded files, but this requires a significant amount of filesystem storage. You should probably leave this option enabled unless you have less than 250MB of disk space on your hosting account or server.',
+      field_history: 'Keep a history of uploaded files',
+      btn_save: 'Save changes',
+    },
+    acpft: {
+      // Nope. There isn't anything else. Sorry to disappoint.
+      heading_main: 'Allowed file types',
+      hint: 'Using the form below, you can decide which file types are allowed to be uploaded to this site.',
+      msg_saved: 'Your changes have been saved.',
+      msg_demo_mode: 'Hmm, enabling executables, are we? Tsk tsk. I\'d love to know what\'s in that EXE file you want to upload. OK, maybe you didn\'t enable EXEs. But nevertheless, changing allowed filetypes is disabled in the demo.',
+    },
+    acppl: {
+      err_heading: 'Error disabling plugin',
+      err_demo_plugin: 'The demo lockdown plugin cannot be disabled in demo mode.',
+      err_system_plugin: 'The plugin you selected cannot be disabled because it is a system plugin.',
+      err_open_dir: 'The plugins/ directory could not be opened.',
+      err_missing_dir: 'The plugins/ directory is missing from your Enano installation.',
+      col_filename: 'Plugin filename',
+      col_name: 'Plugin name',
+      col_description: 'Description',
+      col_author: 'Author',
+      col_version: 'Version',
+      btn_enable: 'Enable',
+      btn_disable: 'Disable',
+      btn_hide_system: 'Hide system plugins',
+      btn_show_system: 'Show system plugins',
+      lbl_system_plugin: '[System]',
+    },
+    acppm: {
+      heading_main: 'Edit page properties',
+      hint: 'This panel allows you to edit various properties of pages that aren\'t visible anywhere else. In addition to renaming pages, you can also change their <a href="http://docs.enanocms.org/Help:2.3">URL string</a> and options such as whether to index the page for searching or bypass Enano\'s template engine.',
+      err_page_not_found: 'No pages matching that search string could be found.',
+      msg_results_ambiguous_title: 'Ambiguous search results',
+      msg_results_ambiguous_body: 'Multiple pages that matched your search terms were found. Please select the page you wish to modify:',
+      ambig_btn_viewpage: 'View',
+      err_ambig_absolute: 'Your database is corrupt as it contains multiple pages with the same urlname and namespace.',
+      lbl_field_search: 'Search for a page title or URL string:',
+      heading_select_page_from_list: 'Select page from a list',
+      hint_select_page_from_list: 'You can also select the page you want to modify from the list below. The list is broken into sections of 100 pages, so if you have a lot of pages on your site, you can click the pagination control below to view more pages.',
+      
+      // Edit form
+      heading_editing: 'Editing page:',
+      lbl_page_name: 'Page\'s title:',
+      lbl_page_urlname: 'URL string:',
+      lbl_page_urlname_hint: 'No spaces, and don\'t enter the namespace prefix (e.g. User:). Changing this value is usually not a good idea, especially for templates and project pages, because it will invalidate the page\'s current URL.',
+      lbl_namespace: 'Namespace (URL prefix):',
+      ns_article: '[No prefix, default Article namespace]',
+      heading_advanced: 'Advanced options',
+      lbl_enable_comments_title: 'Allow comments to be posted on this page?',
+      lbl_enable_comments_hint: 'This option has no effect if comments are disabled globally in the administration panel. This option is enabled by default.',
+      lbl_enable_comments: 'Enable comments on this page',
+      lbl_special_title: 'Mark page as self-contained?',
+      lbl_special_hint: 'This option enables you to use your own HTML headers and other code. If you enable this, only the raw contents of the page will be displayed instead of Enano\'s full page formatting and styles. It is recommended that only advanced users enable this feature. As with other Enano pages, you may use PHP code in your pages (dependent on permissions), meaning you can use Enano\'s API on the page.',
+      lbl_special: 'Bypass the template engine for this page',
+      lbl_visible_title: 'Make page publicly listed?',
+      lbl_visible_hint: 'If you enable this option, this page will be indexed for searching and will appear in public page lists such as Special:AllPages. This option is enabled by default. Disabling this does not protect the page from unauthorized access. If you want to keep this page from being accessed without authorization, you should create abstract new ACL rule or password-protect the page.',
+      lbl_visible: 'Allow page to be indexed and listed',
+      lbl_protected_title: 'Protect page from edits?',
+      lbl_protected_off: 'Unprotected',
+      lbl_protected_on: 'Fully protected',
+      lbl_protected_semi: 'Semi-protected',
+      lbl_protected_hint: 'This option only has an effect if Wiki Mode is enabled. Selecting Unprotected means that any user (unless specifically blacklisted) can edit this page. Fully protected means that only administrators can edit the page. Semi-protected restricts editing to administrators and users that have been registered for at least four days.<br /><br /><b>Above all, no users except administrators can edit this page unless an ACL specifically allows it or Wiki Mode is enabled.</b>',
+      lbl_wikimode_title: 'Enable Wiki Mode for this page?',
+      lbl_wikimode_on: 'Enabled',
+      lbl_wikimode_off: 'Disabled',
+      lbl_wikimode_global: 'Inherit global setting',
+      lbl_wikimode_hint: 'By default, all pages use the Wiki Mode setting defined in General Configuration. You can override that using this field. Be aware that there are advantages and disadvantages to Wiki Mode. For example, Wiki Mode encourages collaboration, but also permits vandalism. See the <a href="http://docs.enanocms.org/Help:2.5">Enano Documentation article on Wiki Mode</a> for more information.',
+      lbl_delete_title: 'Delete this page?',
+      lbl_delete_hint: 'Remember that deleting pages is always reversible unless you clear the page\'s logs after deleting it.',
+      lbl_delete: 'Delete this page when I click Save',
+      
+      err_invalid_page_name: 'Please enter a name for the page.',
+      err_invalid_url_string: 'Please enter a URL string for the page.',
+      err_invalid_namespace: 'The namespace you selected is, for whatever reason, not valid.',
+      err_invalid_protection: 'The protection level selected is invalid.',
+      err_invalid_wiki_mode: 'The Wiki Mode level selected is invalid.',
+      err_header: 'There were one or more problems that prevented the page from being saved:',
+      delete_reason: 'Administrative deletion from admin CP; contact webmaster for details',
+      
+      msg_save_success: 'Your changes to the page have been saved. <a href="%viewpage_url%">View page &raquo;</a>',
+    },
+    acped: {
+      heading_main: 'Edit page content',
+      hint: 'This panel allows you to edit the contents of pages that are stored in the database.',
+      // The rest of this section is identical to the first parts of the acppm category by default (you can copy and paste).
+      err_page_not_found: 'No pages matching that search string could be found.',
+      msg_results_ambiguous_title: 'Ambiguous search results',
+      msg_results_ambiguous_body: 'Multiple pages that matched your search terms were found. Please select the page you wish to edit:',
+      ambig_btn_viewpage: 'View',
+      err_ambig_absolute: 'Your database is corrupt as it contains multiple pages with the same urlname and namespace.',
+      lbl_field_search: 'Search for a page title or URL string:',
+      heading_select_page_from_list: 'Select page from a list',
+      hint_select_page_from_list: 'You can also select the page you want to edit from the list below. The list is broken into sections of 100 pages, so if you have a lot of pages on your site, you can click the pagination control below to view more pages.',
+    },
+    acptm: {
+      heading_edit_themes: 'Installed themes',
+      btn_system_themes_show: '&raquo; Show system themes',
+      btn_system_themes_hide: '&raquo; Hide system themes',
+      btn_theme_edit: 'Edit',
+      btn_theme_system: 'System theme',
+      heading_install_themes: 'Themes available for installation',
+      btn_theme_install: 'Install',
+      
+      // Editor
+      heading_theme_edit: 'Editing theme: %theme_name%',
+      field_theme_name: 'Theme name:',
+      field_default_style: 'Select a default style:',
+      field_default_theme: 'Site-wide default theme:',
+      field_default_msg_current: 'This is the current default',
+      field_default_btn_make_default: 'Make this the default theme when I click Save',
+      heading_theme_groups: 'User and group policy',
+    },
+    acpdb: {
+      err_not_supported_title: 'Not supported',
+      err_not_supported_desc: 'This function is only supported under the MySQL database driver.',
+      err_demo_mode_title: 'Access denied',
+      err_demo_mode_desc: 'Since you\'re using the Enano demo, we can\'t allow database backups. Sorry.',
+      
+      intro: 'This page allows you to back up your Enano database should something go miserably wrong.',
+      lbl_system_tables: 'Export tables that are part of the Enano core',
+      lbl_additional_tables: 'Additional tables to export:',
+      lbl_include_structure: 'Include table structure',
+      lbl_include_data: 'Include table data',
+      btn_create_backup: 'Create backup',
+    },
+    acplm: {
+      // Language installation
+      heading_install: 'Languages available for installation',
+      col_lang_id: 'ID',
+      col_lang_code: 'Shorthand code',
+      col_lang_name: 'Language name (native)',
+      col_lang_name_eng: 'Language name (English)',
+      btn_install_language: 'Install',
+      err_lang_install_demo: 'Modifying, installing, and uninstalling languages is disabled in the demo for security reasons.',
+      msg_lang_install_success: 'The language pack %lang_name% has been installed.',
+      
+      // Editor portal
+      heading_editor_portal: 'Edit installed languages',
+      portal_btn_edit: 'Modify',
+      portal_btn_unin: 'Uninstall',
+      
+      // Properties table
+      heading_modify: 'Edit language info',
+      th_lang_basic: 'Basic language properties',
+      field_lang_name_native: 'Language name (native):',
+      field_lang_name_english: 'Language name (in English):',
+      field_lang_code: 'Shorthand code:',
+      field_lang_code_hint: 'You can\'t change this because it needs to be compliant with <a onclick="window.open(this.href); return false;" href="http://en.wikipedia.org/wiki/ISO_639-3">ISO 639-3</a>.',
+      msg_basic_save_success: 'Changes saved.',
+      
+      // String editor portal
+      heading_edit_strings_portal: 'Edit strings',
+      msg_edit_strings_portal_intro: 'You can edit the actual language strings used in this language. Be sure to preserve any variables (in the format of %variable_name%) even if you\'re translating a language. If you\'re translating all of Enano into a new language, you should edit the JSON files instead of using this console, so that comments in the language files can be preserved.',
+      btn_edit_strings_portal: 'Edit strings &raquo;',
+      
+      // Re-import button and explanation
+      heading_reimport_portal: 'Re-import this language',
+      msg_reimport_portal_intro: 'If you accidentally changed a lot of strings, you can re-import this language from the original language files. This will <b>destroy</b> any modifications you have made to the default set of strings, but any strings you\'ve added will be preserved. This is almost the same effect as re-installing the language. Don\'t stop this process while it\'s running, the re-import can take a long time.',
+      btn_reimport: 'Re-import language',
+      msg_reimport_success: 'The language was re-imported successfully. All Enano preset strings for this language have been restored.',
+      
+      // String editor
+      editor_heading: 'Editing category: %cat_name%',
+      editor_col_string_name: 'String name',
+      editor_col_string_content: 'String',
+      editor_btn_revert: 'Revert',
+      editor_btn_cancel: 'Cancel',
+      msg_string_save_success: 'Your changes have been saved.',
+      
+      // Backup interface
+      heading_backup: 'Backup language',
+      backup_intro: 'You can back up this language to make preserving custom strings easier if you ever migrate your Enano installation or re-install. Backed-up language files can be restored by using FTP or equivalent to copy the backup file to the language\'s folder, renaming it to "backup.json", and re-importing the language.',
+      btn_create_backup: 'Download backup',
+      
+      // Uninstaller
+      uninstall_confirm_title: 'Confirm uninstallation of language',
+      uninstall_confirm_body: 'Do you really want to uninstall this language? If you continue, all users that have selected this language will be reset to use the default. It is recommended that you create a backup of this language before you uninstall it if you have changed any strings.',
+      btn_uninstall_confirm: 'Confirm uninstallation',
+      btn_uninstall_cancel: 'Cancel',
+      err_cant_uninstall_default: 'You cannot uninstall the default language.',
+      msg_uninstall_success: 'The language has been uninstalled.',
+    },
+    acppg: {
+      // Main menu
+      heading_main: 'Manage page groups',
+      hint_intro: 'Enano\'s page grouping system allows you to build sets of pages that can be controlled by a single ACL rule. This makes managing features such as a members-only section of your site a lot easier. If you don\'t use the ACL system, you probably don\'t need to use page groups.',
+      col_group_name: 'Group name',
+      col_type: 'Type',
+      col_target: 'Target',
+      col_actions: 'Actions',
+      gtype_catlink: 'Link to category',
+      gtype_tagged: 'Group of pages with one tag',
+      gtype_static: 'Static group of pages',
+      gtype_regex: 'Regular expression match',
+      gtype_regex_long: 'Perl-compatible regular expression (advanced)',
+      lbl_tag: 'Tag:',
+      lbl_category: 'Category:',
+      lbl_regex: 'Expression:',
+      btn_edit: 'Edit',
+      btn_delete: 'Delete',
+      msg_no_groups: 'No page groups defined.',
+      btn_create_new: 'Create new group',
+      
+      // Creation form
+      err_no_cats: 'There aren\'t any categories on this site.',
+      th_create: 'Create page group',
+      field_group_name: 'Group name:',
+      field_group_name_hint: 'This should be short, descriptive, and human-readable.',
+      field_group_type: 'Group type:',
+      
+      field_member_pages: 'Member pages:',
+      field_member_pages_hint: 'Click the "plus" button to add more fields.',
+      field_target_category: 'Include pages in this category:',
+      field_target_category_hint: 'Pages in subcategories are <u>not</u> included, however subcategory pages themselves are.',
+      field_target_category_hint2: '<b>Reminder:</b> Enano does not automatically place any access controls on the category. If you don\'t want users to be able to freely add and remove pages from the category (assuming Wiki Mode is enabled for the category) then you need to enable protection on the category using the button on the more options menu.',
+      field_target_tag: 'Include pages with this tag:',
+      field_target_regex: 'Regular expression:',
+      field_target_regex_hint: 'Be sure to include the starting and ending delimiters and any flags you might need.<br />
+                                These pages might help: <a href="http://us.php.net/manual/en/reference.pcre.pattern.modifiers.php">Pattern modifiers</a> &bull; <a href="http://us.php.net/manual/en/reference.pcre.pattern.syntax.php">Pattern syntax</a><br />
+                                Examples: <tt>/^(Special|Admin):/i</tt> &bull; <tt>/^Image:([0-9]+)$/</tt><br />
+                                Developers, remember that this will be matched against the full page identifier string. This means that <tt>/^About_Enano$/</tt> will NOT match the page Special:About_Enano.',
+      btn_create_finish: 'Create page group',
+      
+      err_need_name: 'Please enter a name for the page group.',
+      err_need_tag: 'Please enter a page tag.',
+      err_need_cat: 'Please create a category page before linking a page group to a category.',
+      err_need_page: 'Please specify at least one page to place in this group.',
+      err_need_regex: 'Please specify a regular expression to match page IDs against.',
+      msg_create_success: 'The page group "%group_name%" has been created.',
+      
+      // Delete form
+      th_delete_confirm: 'Confirm deletion',
+      msg_delete_confirm: 'Are you sure you want to delete this page group?',
+      btn_delete_confirm: 'Yes, delete group',
+      msg_delete_success: 'The group "%pg_name%" has been deleted.',
+      
+      // Editor
+      th_editing_group: 'Editing page group:',
+      btn_save_name: 'Save group name',
+      th_remove_selected: 'Remove pages from this group',
+      field_remove: '<b>Remove</b> pages:',
+      btn_do_remove: 'Remove selected',
+      btn_save_update: 'Save and update',
+      btn_cancel_all: 'Cancel all changes',
+      th_onthefly: 'On-the-fly tools',
+      field_add_page: 'Add page:',
+      field_add_page_hint: 'You can add multiple pages by entering part of a page title, and it will be auto-completed. Press Enter to quickly add the page. This only works if you a really up-to-date browser.',
+      
+      // Validation messages and errors
+      err_ajaxadd_need_title: 'Please enter a page title.',
+      err_ajaxadd_already_in: 'The page you are trying to add is already in this group.',
+      ajaxadd_success: 'The page has been added to the specified group.',
+      err_save_need_name: 'Please enter a valid name for this group.',
+      msg_save_name_updated: 'The group name was updated successfully.',
+      err_save_need_tag: 'Please enter a valid tag.',
+      msg_save_tag_updated: 'The affecting tag was updated.',
+      err_save_need_regex: 'Please enter an expression to match against.',
+      msg_save_regex_updated: 'The expression to match against was updated.',
+      err_save_bad_category: 'No category ID specified on POST URI.',
+      msg_save_cat_updated: 'The affecting category was updated.',
+      err_save_no_pages: 'No pages were selected for deletion, and thus none were deleted.',
+      msg_save_pages_deleted: 'The requested page group members have been deleted.',
+    },
+    acpum: {
+      heading_main: 'User administration panel',
+      hint_intro: 'From this panel you can modify or delete user accounts.',
+      field_search_user: 'Search for user:',
+      field_search_user_hint: 'If your browser supports AJAX, this will provide suggestions for you.',
+      btn_search_user_go: 'Go',
+      heading_clear_sessions: 'Clear session key table',
+      hint_clear_sessions: 'It\'s a good idea to clean out your session keys table every once in a while, since this helps to reduce database size. During this process you will be logged off and (hopefully) logged back on automatically. If you do this, all users besides you will be logged off, so be sure to do this at a time when traffic is low.',
+      btn_clear_sessions: 'Clear session keys',
+      
+      heading_activation_one: '1 user is awaiting account activation',
+      heading_activation_plural: '%count% users are awaiting account activation',
+      col_activate_timestamp: 'Date of request',
+      col_activate_requestedby: 'Requested by',
+      col_activate_requestedfor: 'Requested for',
+      col_activate_coppauser: 'COPPA user',
+      col_activate_actions: 'Actions',
+      coppauser_yes: 'Yes',
+      coppauser_no: 'No',
+      btn_activate_now: 'Activate now',
+      btn_send_email: 'Send activation e-mail',
+      btn_activate_deny: 'Deny request',
+      msg_activate_success: 'The user account "%username%" has been activated.',
+      err_activate_fail: 'The user account %username% has NOT been activated, possibly because the account is already active.',
+      msg_activate_email_success: 'The user %username% has been sent an e-mail with an activation link.',
+      err_activate_email_fail: 'The user account %username% has not been activated, probably because of a bad SMTP configuration.',
+      msg_activate_deny_success: 'All activation requests for the user %username% have been deleted.',
+      
+      msg_sessionclear_success: 'The session key table has been cleared. Your database should be a little bit smaller now.',
+      err_sessionclear_demo: 'Sorry Charlie, no can do. You might mess up other people logged into the demo site.',
+      
+      // VALIDATION ERRORS
+      err_bad_username: 'The username you entered could not be found.',
+      err_validation_fail: 'Your request could not be processed due to the following validation errors:',
+      err_nosave_demo: 'Users cannot be modified or deleted in demo mode.',
+      msg_delete_success: 'The user account has been deleted.',
+      // Note the difference between this and err_bad_username. err_bad_username is shown when the username entered
+      // doesn't match any usernames in the database (e.g. no search results); err_illegal_username is shown when
+      // the admin tries to change the username to one that has illegal characters in it.
+      err_illegal_username: 'The username you entered contains invalid characters.',
+      err_no_aes_key: 'Session manager denied public encryption key lookup request',
+      err_illegal_email: 'You have entered an invalid e-mail address.',
+      msg_save_success: 'Your changes have been saved.',
+      
+      // EDITOR SMARTFORM
+      heading_editing_user: 'Editing user:',
+      heading_basic_options: 'Basic options',
+      
+      field_username: 'Username:',
+      field_username_hint: 'Must be at least 2 characters in length',
+      msg_same_user_username: 'You cannot change your own username. To change your username you must log into a different administrative account.',
+      
+      field_password: 'Password:',
+      field_password_hint: 'Password strength requirements are not enforced here.',
+      msg_password_unchanged: 'Password will be left unchanged.',
+      btn_reset_password: 'Reset password...',
+      msg_same_user_password: 'To change your password, please use the user preferences panel.',
+      field_password_title: 'Change password to:',
+      field_newpassword: 'New password:',
+      field_newpassword_confirm: 'Confirm:',
+      
+      field_email: 'E-mail address:',
+      msg_same_user_email: 'To change your e-mail address, please use the user preferences panel.',
+      
+      field_realname: 'Real name:',
+      msg_same_user_realname: 'To change your real name on file, please use the user preferences panel.',
+      
+      field_signature: 'Signature:',
+      
+      heading_imcontact: 'Instant messenger contact information',
+      
+      field_aim: 'AIM handle:',
+      field_wlm: '<acronym title="Windows&trade; Live Messenger">WLM</acronym> handle:',
+      field_wlm_hint: 'If you don\'t specify the domain (@whatever.com), "@hotmail.com" will be assumed.',
+      field_yim: 'Yahoo! IM handle:',
+      field_xmpp: 'Jabber&trade;/XMPP handle:',
+      
+      heading_contact_extra: 'Extra contact information',
+      
+      field_homepage: 'Homepage:',
+      field_homepage_hint: 'Please remember the http:// prefix.',
+      field_location: 'Location:',
+      field_job: 'Job:',
+      field_hobbies: 'Hobbies:',
+      field_email_public: 'E-mail address is public',
+      field_email_public_hint: 'If this is checked, the user\'s e-mail address will be displayed on your the page. To protect the address from spambots, it will be encrypted.',
+      
+      avatar_heading: 'Avatar settings',
+      avatar_image_none: 'This user does not currently have an avatar.',
+      avatar_lbl_change: 'Change avatar:',
+      avatar_lbl_keep: 'Keep current setting',
+      avatar_lbl_remove: 'Delete this user\'s avatar',
+      avatar_lbl_set_http: 'Replace avatar using a new image from a URL',
+      avatar_lbl_set_file: 'Replace avatar using a new image from my computer',
+      
+      heading_adminonly: 'Administrator-only options',
+      
+      field_active_title: 'User account is active',
+      field_active_hint: 'If this is unchecked, the existing activation key will be overwritten in the database, thus invalidating any activation e-mails sent to the user.',
+      field_active: 'Account is active and enabled',
+      field_userlevel: 'User\'s site access level',
+      field_userlevel_hint: 'If this is changed, the relevant group memberships will be updated accordingly.',
+      field_reg_ip: 'Registered from IP:',
+      
+      field_deleteaccount_title: 'Delete user account',
+      field_deleteaccount: 'Permanently delete this user account when I click Save',
+      msg_delete_own_account: '<blink style="color: red;">WARNING!</blink> This will delete your own user account!',
+      field_deleteaccount_hint: 'Even if you delete this user account, the username will be shown in page edit history, comments, and other areas of the site. Deleting a user account CANNOT BE UNDONE and should only be done in extreme circumstances. If the user has violated the site policy, deleting the account will not prevent him from using the site or creating a new account, for that you need to add a new ban rule.',
+      
+      btn_save: 'Save changes',
+    },
+    acpug: {
+      heading_main: 'Manage Usergroups',
+      heading_edit_existing: 'Edit an existing group',
+      btn_edit_stage1: 'Edit group',
+      heading_create_new: 'Create a new group',
+      field_group_name: 'Group name:',
+      btn_create_stage1: 'Continue',
+      
+      // Edit form
+      heading_edit_name: 'Edit group name',
+      btn_cant_delete: 'Can\'t delete system group',
+      btn_delete_group: 'Delete this group',
+      btn_save_name: 'Save name',
+      heading_edit_members: 'Edit group members',
+      msg_no_members: 'This group has no members.',
+      lbl_member_mod: 'Mod',
+      btn_remove_member: 'Remove member',
+      heading_add_member: 'Add a new member',
+      field_username: 'Username:',
+      field_make_mod: 'Is a group moderator',
+      field_make_mod_hint: '(can add and delete other members)',
+      btn_add_user: 'Add user to group',
+      
+      // Create form
+      err_group_name_invalid: 'The group name you chose is invalid.',
+      heading_creating_group: 'Creating group:',
+      field_group_mod: 'Group moderator',
+      field_group_type: 'Group status',
+      btn_create_stage2: 'Create group',
+      err_already_exist: 'The group name you entered already exists.',
+      err_bad_username: 'The username you entered could not be found.',
+      err_bad_insert_id: 'The group ID could not be looked up.',
+      heading_info: 'Information',
+      msg_create_success: 'The group %g_name% has been created successfully.',
+      
+      // More editor bits, validation messages
+      err_nodelete_system_group: 'The group "%g_name%" could not be deleted because it is a system group required for site functionality.',
+      msg_delete_success: 'The group "%g_name%" has been deleted. Return to the <a %a_flags%>group manager</a>.',
+      msg_name_update_success: 'The group name has been updated.',
+      msg_user_added: 'The user "%username%" has been added to this usergroup.',
+      err_username_not_exist: '<b>The user "%username%" could not be added.</b><br />This username does not exist.',
+    },
+    acpcp: {
+      heading_main: 'Background information',
+      intro: 'The United States Childrens\' Online Privacy Protection Act (COPPA) was a law passed in 2001 that requires sites oriented towards children under 13 years old or with a significant amount of under-13 children clearly state what information is being collected in a privacy policy and obtain authorization from a parent or legal guardian before allowing children to use the site. Enano provides an easy way to allow you, as the website administrator, to obtain this authorization.',
+      msg_save_success: 'Your changes have been saved.',
+      th_form: 'COPPA support',
+      field_enable_title: 'Enable COPPA support:',
+      field_enable: 'COPPA enabled',
+      field_enable_hint: 'If this is checked, users will be asked if they are under 13 years of age before registering',
+      field_address: 'Your mailing address:',
+      field_address_hint: 'This is the address to which parents will send authorization forms.',
+    },
+    acpmm: {
+      heading_main: 'Send mass e-mail',
+      err_need_subject: 'Please enter a subject.',
+      err_need_message: 'Please enter a message.',
+      msg_send_success: 'Your message has been sent.',
+      err_send_fail: 'Could not send message for the following reason(s):',
+      err_demo: 'This function is disabled in the demo. You think demo@enanocms.org likes getting "test" mass e-mails?',
+      field_group_to: 'Send message to:',
+      field_group_to_hint: 'By default, this message will be sent to the group selected here. You may instead send the message to a specific list of users by entering them in the second row, with usernames separated by a single comma (no space).',
+      field_username: 'Usernames:',
+      field_subject: 'Subject:',
+      field_message: 'Message:',
+      btn_send: 'Send message',
+      msg_send_takeawhile: 'Please be warned: it may take a LONG time to send this message. <b>Please do not stop the script until the process is finished.</b>',
+    },
+    acpsl: {
+      heading_main: 'System security log',
+      col_type: 'Type',
+      col_date: 'Date',
+      col_username: 'Username',
+      col_ip: 'IP Address',
+      entry_admin_auth_good: 'Successful elevated authentication<br /><small>Authentication level: %level%</small>',
+      entry_admin_auth_bad: 'Failed elevated authentication<br /><small>Attempted auth level: %level%</small>',
+      entry_activ_good: 'Successful account activation',
+      entry_auth_good: 'Successful regular user logon',
+      entry_activ_bad: 'Failed account activation',
+      entry_auth_bad: 'Failed regular user logon',
+      entry_sql_inject: 'SQL injection attempt<div style="max-width: 90%; clip: rect(0px,auto,auto,0px); overflow: auto; display: block; font-size: smaller;">Offending query: %query%</div>',
+      entry_db_backup: 'Database backup created<br /><small>Tables: %tables%</small>',
+      entry_install_enano: 'Installed Enano version %version%',
+      entry_upgrade_enano: 'Upgraded Enano to version %version%',
+      entry_illegal_page: 'Unauthorized viewing attempt<br /><small>Page: %illegal_link%</small>',
+      entry_upload_enable: 'Enabled file uploads',
+      entry_upload_disable: 'Disabled file uploads',
+      entry_magick_enable: 'Enabled ImageMagick for uploaded images',
+      entry_magick_disable: 'Disabled ImageMagick for uploaded images',
+      entry_filehist_enable: 'Enabled revision tracking for uploaded files',
+      entry_filehist_disable: 'Disabled revision tracking for uploaded files',
+      entry_magick_path: 'Changed path to ImageMagick executable',
+      entry_plugin_disable: 'Disabled plugin: %plugin%',
+      entry_plugin_enable: 'Enabled plugin:  %plugin%',
+      entry_seclog_unauth: 'Unauthorized attempt to call security log fetcher',
+      entry_u_from_admin: 'User %username% demoted from Administrators group',
+      entry_u_from_mod: 'User %username% demoted from Moderators group',
+      entry_u_to_admin: 'User %username% added to Administrators group',
+      entry_u_to_mod: 'User %username% added to Moderators group',
+      entry_view_comment_ip: 'IP address viewed on comment by %username%',
+      tip_reverse_dns: 'Click for reverse DNS info',
+    },
+    acpbc: {
+      err_empty: 'Please enter something to ban.',
+      err_invalid_ip_range: 'The IP address range you entered is invalid.',
+      err_demo: 'This function is disabled in the demo. Just because <i>you</i> don\'t like %ban_target% doesn\'t mean <i>we</i> don\'t like %ban_target%.',
+      col_type: 'Type',
+      col_value: 'Value',
+      col_regex: 'Regular Expression',
+      msg_no_rules: 'No ban rules yet.',
+      ban_type_ip: 'IP address',
+      ban_type_username: 'Username',
+      ban_type_email: 'E-mail address',
+      btn_delete: 'Delete',
+      // Some languages like Chinese don't literally have the word "yes", so this would be something
+      // along the lines of "This is a regular expression" / "This is not..." in Chinese. Hence the
+      // separation of this from a generic "yes" string.
+      ban_regex_yes: 'Yes',
+      ban_regex_no: 'No',
+      heading_create_new: 'Create new ban rule',
+      field_type: 'Type:',
+      field_rule: 'Rule:',
+      field_rule_hint: 'You can ban multiple IP addresses, users, or e-mail addresses by separating entries with a single comma (User1,User2). Do not put a space after the comma. For IP addresses, you may specify ranges like 172|192.168.4-30|90-167.1-90, which will turn into 172 and 192 . 168 . 4-30 and 90-167 . 1 - 90, which matches 18,899 IP addresses.',
+      field_reason: 'Reason to show to the banned user:',
+      field_regex: 'This rule is a regular expression',
+      field_regex_hint: '(advanced users only)',
+      btn_create: 'Create new ban rule',
+    },
+    acplo: {
+      heading_main: 'You have now been logged out of the administration panel.',
+      msg_logout_complete: 'You will continue to be logged into the website, but you will need to re-authenticate before you can access the administration panel again.</p><p>Return to the <a href="%mainpage_link%">Main Page</a>.',
+    },
+    sbedit: {
+      msg_order_update_success: 'The sidebar order information was updated successfully.',
+      err_demo_php_disable: 'Adding PHP code blocks in the Enano administration demo has been disabled for security reasons.',
+      msg_item_added: 'The item was added.',
+      
+      create_intro: 'What type of block should this be?',
+      block_type_wiki: 'Wiki-formatted block',
+      block_type_tpl: 'Template-formatted block (old pre-beta 3 behavior)',
+      block_type_html: 'Raw HTML block',
+      block_type_php: 'PHP code block (danger, Will Robinson!)',
+      block_type_plugin: 'Use code from a plugin',
+      field_block_title: 'Block title:',
+      field_block_sidebar: 'Which sidebar:',
+      field_block_sidebar_left: 'Left',
+      field_block_sidebar_right: 'Right',
+      field_wikitext: 'Wikitext:',
+      field_tplcode: 'Template code:',
+      field_html: 'HTML to place inside the sidebar:',
+      field_php_disabled: 'Creating PHP blocks in demo mode is disabled for security reasons.',
+      field_php: '<p>
+                    <b>WARNING:</b> If you don\'t know what you\'re doing, or if you are not fluent in PHP, stop now and choose a different block type. You will brick your Enano installation if you are not careful here.
+                    ALWAYS remember to write secure code! The Enano team is not responsible if someone drops all your tables because of an SQL injection vulnerability in your sidebar code. You are probably better off using the template-formatted block type.
+                  </p>
+                  <p>
+                    <span style="color: red;">
+                      It is especially important to note that this code is NOT checked for errors! If there is a syntax error in your code here, it will prevent any pages from loading AT ALL. So you need to use an external PHP editor (like <a href="http://www.jedit.org">jEdit</a>) to check your syntax before you hit save.
+                    </span> You have been warned.
+                  </p>
+                  <p>
+                    Also, you should avoid using output buffering functions (ob_[start|end|get_contents|clean]) here, because Enano uses those to track output from this script.
+                  </p>
+                  <p>
+                    The standard &lt;?php and ?&gt; tags work here. Don\'t use an initial "&lt;?php" or it will cause a parse error.
+                  </p>
+                  <p>
+                    PHP code:
+                  </p>',
+      field_plugin: 'Plugin:',
+      btn_create_block: 'Create new block',
+      
+      msg_block_moved: 'Item moved.',
+      msg_block_deleted: 'Item deleted.',
+      msg_plugin_not_loaded: 'Plugin isn\'t loaded',
+      note_block_unnamed: 'Unnamed',
+      hint_rename: 'Double-click to rename this block',
+      note_block_disabled: '(disabled)',
+      tip_disenable: 'Enable or disable this block',
+      tip_edit: 'Edit the contents of this block',
+      tip_delete: 'Permanently delete this block',
+      tip_move: 'Move this block to the other sidebar',
+      msg_delete_confirm: 'Do you really want to delete this block?',
+      btn_revert: 'Revert',
+      btn_create_new_stage1: 'Create new block',
+      btn_main_page: 'Main Page',
+      msg_cant_edit_plugin_title: 'This block cannot be edited.',
+      msg_cant_edit_plugin_body: 'This is a plugin block, and cannot be edited. <%close_link%>Close</a>',
+      btn_edit_save: 'save',
+      btn_edit_cancel: 'cancel',
+      msg_discard_confirm: 'Do you really want to discard your changes?',
+      msg_discard_order_confirm: 'Do you really want to revert your changes?\nNote: this does not revert edits or deletions, those are saved as soon as you confirm the action.',
+    }
+  }
+};
+
+// All done! :-)
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/language/english/core.json	Fri Feb 22 12:51:53 2008 -0500
@@ -0,0 +1,690 @@
+/*
+ * Enano - an open-source CMS capable of wiki functions, Drupal-like sidebar blocks, and everything in between
+ * Version 1.1.1
+ * Copyright (C) 2006-2007 Dan Fuhry
+ *
+ * This program is Free Software; you can redistribute and/or modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.
+ *
+ * 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.
+ */
+
+// This is the main language file for Enano. Feel free to use it as a base for your own translations.
+// All text in this file before the first left curly brace and all text after the last curly brace will
+// be trimmed. So you can use a limited amount of Javascript in this so that the language can be imported
+// via Javascript as well.
+
+var enano_lang = {
+  categories: [
+    'meta', 'page', 'comment', 'onpage', 'etc', 'editor', 'history', 'catedit', 'tags', 'delvote', 'ajax', 'sidebar', 'perm', 'plugin', 'paginate', 'upload', 'tz',
+  ],
+  strings: {
+    meta: {
+      meta: 'Category names and basic metadata',
+      page: 'Page creation and control',
+      comment: 'Comment display',
+      onpage: 'On-page buttons and controls',
+      etc: 'Miscellaneous strings',
+      editor: 'Page editor interface',
+      history: 'Page history and log viewer',
+      catedit: 'Categorization box and editor',
+      tags: 'Page tagging interface',
+      delvote: 'Page deletion vote interface',
+      ajax: 'On-page AJAX applets',
+      sidebar: 'Default sidebar blocks and buttons',
+      perm: 'Page actions (for ACLs)',
+      plugin: 'Plugin names and descriptions',
+      paginate: 'Pagination widget',
+      upload: 'File upload interface',
+      tz: 'Time zones',
+      plural: 's',
+      enano_about_th: 'About the Enano Content Management System',
+      enano_about_poweredby: '<p>This website is powered by <a href="http://enanocms.org/">Enano</a>, the lightweight and open source CMS that everyone can use. Enano is copyright &copy; 2006-2007 Dan Fuhry. For legal information, along with a list of libraries that Enano uses, please see <a href="http://enanocms.org/Legal_information">Legal Information</a>.</p><p>The developers and maintainers of Enano strongly believe that software should not only be free to use, but free to be modified, distributed, and used to create derivative works. For more information about Free Software, check out the <a href="http://en.wikipedia.org/wiki/Free_Software" onclick="window.open(this.href); return false;">Wikipedia page</a> or the <a href="http://www.fsf.org/" onclick="window.open(this.href); return false;">Free Software Foundation\'s</a> homepage.</p>',
+      enano_about_gpl: '<p>This program is Free Software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.</p><p>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.</p><p>You should have received <a href="%gpl_link%">a copy of the GNU General Public License</a> along with this program; if not, write to:</p><p style="margin-left 2em;">Free Software Foundation, Inc.,<br />51 Franklin Street, Fifth Floor<br />Boston, MA 02110-1301, USA</p><p>Alternatively, you can <a href="http://www.gnu.org/licenses/old-licenses/gpl-2.0.html">read it online</a>.</p>',
+      enano_about_lbl_enanoversion: '<a href="http://enanocms.org">Enano</a> version:',
+      enano_about_lbl_webserver: 'Web server:',
+      enano_about_lbl_serverplatform: 'Server platform:',
+      enano_about_lbl_phpversion: '<a href="http://www.php.net/">PHP</a> version:',
+      enano_about_lbl_mysqlversion: '<a href="http://www.mysql.com/">MySQL</a> version:',
+      enano_about_lbl_pgsqlversion: '<a href="http://www.postgresql.org/">PostgreSQL</a> version:',
+    },
+    page: {
+      sitedisabled_admin_msg_title: 'The site is currently disabled and thus is only accessible to administrators.',
+      sitedisabled_admin_msg_body: 'You can re-enable the site through the <a href="%admin_link%">administration panel</a>.',
+      
+      heading_sql_list: 'Query list as requested on URI',
+      
+      msg_stats_gentime_long: 'Generated in %time%sec',
+      msg_stats_gentime_short: 'Time: %time%s',
+      msg_stats_sql: '%nq% SQL',
+      
+      w3c_valid_html32: 'Valid HTML 3.2',
+      w3c_valid_html40: 'Valid HTML 4.0',
+      w3c_valid_html401: 'Valid HTML 4.01',
+      w3c_valid_html50: 'Valid HTML 5.0',
+      w3c_valid_xhtml10: 'Valid XHTML 1.0',
+      w3c_valid_xhtml11: 'Valid XHTML 1.1',
+      w3c_valid_css: 'Valid CSS',
+      enano_powered: 'Powered by <a href="%about_uri%">Enano</a>',
+      enano_powered_long: 'Website engine powered by <a href="%about_uri%">Enano</a>',
+      
+      protect_lbl_success_title: 'Page protected',
+      protect_lbl_success_body: 'The protection setting has been applied. <a href="%page_link%">Return to the page</a>.',
+      protect_err_need_reason: 'Error: you must enter a reason for protecting this page.',
+      protect_lbl_reason: 'Reason for protecting the page:',
+      protect_lbl_level: 'Protecion level to be applied:',
+      protect_lbl_level_none: 'No protection',
+      protect_lbl_level_semi: 'Semi-protection',
+      protect_lbl_level_full: 'Full protection',
+      protect_btn_submit: 'Protect page',
+      
+      rename_err_need_name: 'Error: you must enter a new name for this page.',
+      rename_lbl: 'Please enter a new name for this page:',
+      rename_btn_submit: 'Rename page',
+      rename_success_title: 'Page renamed',
+      
+      flushlogs_warning_stern: '<h3>You are about to <span style="color: red;">destroy</span> all logged edits and actions on this page.</h3><p>Unlike deleting or editing this page, this action is <u>not reversible</u>! You should only do this if you are desparate for database space.</p><p>Do you really want to continue?</p>',
+      flushlogs_btn_submit: 'Flush logs',
+      
+      delvote_warning_stern: '<h3>Your vote counts.</h3><p>If you think that this page is not relavent to the content on this site, or if it looks like this page was only created in an attempt to spam the site, you can request that this page be deleted by an administrator.</p><p>After you vote, you should leave a comment explaining the reason for your vote, especially if you are the first person to vote against this page.</p>',
+      
+      delvote_count_zero: 'So far, no one has voted for the deletion of this page.',
+      delvote_count_one: 'So far, one person has voted to delete this page.',
+      delvote_count_plural: 'So far, %delvotes% people have voted to delete this page.',
+      delvote_btn_submit: 'Vote to delete this page',
+      delvote_reset_btn_submit: 'Reset votes',
+      
+      delete_warning_stern: '<h3>You are about to <span style="color: red;">destroy</span> this page.</h3><p>While the deletion of the page itself is completely reversible, it is impossible to recover any comments or category information on this page. If this is a file page, the file along with all older revisions of it will be permanently deleted. Also, any custom information that this page is tagged with, such as a custom name, protection status, or additional settings such as whether to allow comments, will be permanently lost.</p><p>Are you <u>absolutely sure</u> that you want to continue?<br />You will not be asked again.</p>',
+      delete_err_need_reason: 'Please enter a reason for deleting this page.',
+      delete_btn_submit: 'Delete this page',
+      delete_lbl_reason: 'Reason for deleting:',
+      
+      wikimode_success_redirect: 'Wiki mode for this page has been set. Redirecting you to the page...',
+      wikimode_level_on: 'Wiki features will be enabled.',
+      wikimode_level_off: 'Wiki features will be disabled.',
+      wikimode_level_global: 'Wiki features will be synchronized to the global setting.',
+      wikimode_heading: 'You are changing wiki mode for this page.',
+      wikimode_warning: 'If you want to continue, please click the button below.',
+      wikimode_blurb_disable: 'Because this will disable the wiki behavior on this page, several features, most notably the ability for users to vote to have this page deleted, will be disabled as they are not relevant to non-wiki pages. In addition, users will not be able to edit this page unless an ACL rule specifically permits them.',
+      wikimode_blurb_enable: 'Because this will enable the wiki behavior on this page, users will gain the ability to freely edit this page unless an ACL rule specifically denies them. If your site is public and gets good traffic, you should be aware of the possiblity of vandalism, and you need to be ready to revert malicious edits to this page.',
+      wikimode_btn_submit: 'Set wiki mode',
+      
+      detag_err_page_exists: 'The detag action is only valid for pages that have been deleted in the past.',
+      detag_success_title: 'Page detagged',
+      detag_success_body: 'All stale tags have been removed from this page.',
+      
+      err_custompage_function_missing_title: 'Page backend not found',
+      err_custompage_function_missing_body: 'The administration page you are looking for was properly registered using the page API, but the backend function (<tt>%function_name%</tt>) was not found. If this is a plugin page, then this is almost certainly a bug with the plugin.',
+      err_redirects_exceeded: 'The maximum number of internal redirects has been exceeded.',
+      err_redirect_to_nonexistent: 'This page redirects to another page that doesn\'t exist.',
+      err_redirect_infinite_loop: 'This page infinitely redirects with another page (or another series of pages), and the infinite redirect was trapped.',
+      err_redirect_to_special: 'This page redirects to a Special or Administration page, which is not allowed.',
+      err_access_denied_title: 'You don\'t have permission to view this page.',
+      err_access_denied_body: '<p>Your user account doesn\'t have the necessary permission to view this page. There are a number of possible reasons for this:</p>
+                               <ul>
+                                 <li>You aren\'t logged in. Some pages are restricted to logged-in users.</li>
+                                 <li>The page you\'re trying to view is protected so that only members of a specific usergroup are allowed to read it.</li>
+                               </ul>
+                               <p>If you would like to inquire further about this message, you may contact the %site_administration%.</p>',
+      err_access_denied_siteadmin: 'site administrator',
+      msg_this_is_a_redirector: '<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" onclick="window.open(this.href); return false;">Wiki formatting guide</a>.<br /><br />
+                    This page redirects to %redirect_target%.',
+      msg_redirected_from: '(Redirected from %from%)',
+      msg_redirected_from_to: '(Redirected from %from% to %to%)',
+      
+      msg_passrequired: 'Access to this page requires a password. Please enter the password for this page below:',
+      msg_pass_wrong: 'The password you entered for this page was incorrect. Please enter the password for this page below:',
+      lbl_password: 'Password:',
+      
+      msg_404_title: 'There is no page with this title yet.',
+      msg_404_body_userpage: 'This user has not created his or her user page yet.',
+      msg_404_body: 'You have requested a page that doesn\'t exist yet.',
+      msg_404_create: 'You can <a %create_flags%>create this page</a>, or return to the <a href="%mainpage_link%">homepage</a>.',
+      msg_404_gohome: 'Return to the <a href="%mainpage_link%">homepage</a>.',
+      msg_404_was_deleted: '<b>This page was deleted on %delete_time%.</b> The stated reason was:</p><blockquote>%delete_reason%</blockquote><p>You can probably <a %rollback_flags%>roll back</a> the deletion.',
+      msg_404_admin_opts: 'Additional admin options: <a href="%detag_link%" title="Remove any tags on this page">detag page</a>',
+      msg_404_http_response: 'HTTP Error: 404 Not Found',
+      
+      msg_archived_title: 'Notice:',
+      msg_archived_body: 'The page you are viewing was archived on %archive_date% at %archive_time%.<br /><a href="%current_link%" onclick="ajaxReset(); return false;">View current version</a>  |  <a href="%restore_link%" onclick="%restore_onclick%">Restore this version</a>',
+      
+      msg_special_404_title: 'Can\'t load special page',
+      msg_special_404_body: 'The special page you requested could not be found. This may be due to a plugin failing to load. A list of all special pages on this website can be viewed <a href="%sp_link%">here</a>. You will be redirected to the main page in 15 seconds.',
+      msg_admin_404_title: 'Administration page not found',
+      msg_admin_404_body: '<p>You\'ve requested an administration page, but the function <tt>%func_name%</tt> doesn\'t exist, so the page can\'t be loaded.</p>
+                             <h3>Plugin developer?</h3>
+                              <p>Create a function called <tt>%func_name%</tt> - it should be loaded when you refresh this page.</p>
+                             <h3>Otherwise...</h3>
+                              <p>If you\'re trying to use a plugin\'s administration page, contact the developer of the plugin. If you\'re trying to use a function that is built into Enano (not added by a plugin), then please contact the Enano development team.</p>',
+      
+      msg_general_error: 'General error in page fetcher',
+                    
+      autosuggest_heading: 'Page name matches',
+      autosuggest_col_name: 'Page title',
+      autosuggest_col_page_id: 'Page ID',
+    },
+    comment: {
+      lbl_subject: 'Subject',
+      lbl_mod_options: 'Moderator options:',
+      heading: 'Article comments',
+      btn_send_privmsg: 'Send private message',
+      btn_add_buddy: 'Add to buddy list',
+      btn_edit: 'edit',
+      btn_delete: 'delete',
+      btn_mod_approve: 'Approve',
+      btn_mod_unapprove: 'Unapprove',
+      btn_mod_delete: 'Delete',
+      btn_mod_ip_logged: 'View IP',
+      btn_mod_ip_missing: 'IP not logged',
+      btn_mod_ip_notimplemented: 'Use AJAX interface to view IPs',
+      btn_save: 'save',
+      
+      msg_comment_posted: 'Your comment has been posted. If it does not appear right away, it is probably awaiting approval.',
+      
+      msg_count_zero: 'There are <span id="comment_count_inner">no</span> comments on this %page_type%.',
+      msg_count_one: 'There is <span id="comment_count_inner">1</span> comment on this %page_type%.',
+      msg_count_plural: 'There are <span id="comment_count_inner">%num_comments%</span> comments on this %page_type%.',
+      
+      msg_count_unapp_mod: '<span id="comment_count_unapp_inner">%num_unapp%</span> of those are unapproved.',
+      msg_count_unapp_one: 'However, there is <span id="comment_count_unapp_inner">1</span> additional comment awaiting approval.',
+      msg_count_unapp_plural: 'However, there are <span id="comment_count_unapp_inner">%num_unapp%</span> additional comments awaiting approval.',
+      
+      msg_note_unapp: '(Unapproved)',
+      
+      msg_ip_address: 'IP address:',
+      
+      msg_delete_confirm: 'Do you really want to delete this comment?',
+      
+      postform_title: 'Got something to say?',
+      postform_blurb: 'If you have comments or suggestions on this article, you can shout it out here.',
+      postform_blurb_unapp: 'Before your post will be visible to the public, a moderator will have to approve it.',
+      postform_blurb_captcha: 'Because you are not logged in, you will need to enter a visual confirmation before your comment will be posted.',
+      postform_blurb_link: 'Leave a comment...',
+      postform_field_name: 'Your name/screen name:',
+      postform_field_subject: 'Comment subject:',
+      postform_field_comment: 'Comment:',
+      postform_field_captcha_title: 'Visual confirmation:',
+      postform_field_captcha_blurb: 'Please enter the confirmation code seen in the image on the right into the box. If you cannot read the code, please click on the image to generate a new one. This helps to prevent automated bot posting.',
+      postform_field_captcha_label: 'Confirmation code:',
+      postform_field_captcha_cantread_js: 'If you can\'t read the code, click on the image to generate a new one.',
+      postform_field_captcha_cantread_nojs: 'If you can\'t read the code, please refresh this page to generate a new one.',
+      postform_btn_submit: 'Submit comment',
+      
+      on_friend_list: 'On your friend list',
+      on_foe_list: 'On your foe list',
+    },
+    onpage: {
+      lbl_pagetools: 'Page tools',
+      lbl_page_article: 'article',
+      lbl_page_admin: 'administration page',
+      lbl_page_system: 'system message',
+      lbl_page_file: 'uploaded file',
+      lbl_page_help: 'documentation page',
+      lbl_page_user: 'user page',
+      lbl_page_special: 'special page',
+      lbl_page_template: 'template',
+      lbl_page_project: 'project page',
+      lbl_page_category: 'category',
+      
+      btn_discussion: 'discussion (%num_comments%)',
+      btn_discussion_unapp: 'discussion (%num_comments% total, %num_unapp% unapp.)',
+      btn_edit: 'edit this page',
+      btn_viewsource: 'view source',
+      btn_history: 'history',
+      btn_moreoptions: 'more options',
+      
+      btn_rename: 'rename',
+      btn_printable: 'view printable version',
+      btn_votedelete: 'vote to delete this page',
+      btn_votedelete_reset: 'reset deletion votes',
+      lbl_wikimode: 'page wiki mode:',
+      btn_wikimode_on: 'on',
+      btn_wikimode_off: 'off',
+      btn_wikimode_global: 'global',
+      lbl_protect: 'protection:',
+      btn_protect_on: 'on',
+      btn_protect_off: 'off',
+      btn_protect_semi: 'semi',
+      btn_clearlogs: 'clear page logs',
+      btn_deletepage: 'delete this page',
+      btn_deletepage_votes: ' (<b>%num_votes%</b> vote%plural%)',
+      lbl_password: 'page password:',
+      btn_password_set: 'set',
+      btn_acl: 'manage page access',
+      btn_admin: 'administrative options',
+      
+      tip_article: 'View the page contents, all of the page contents, and nothing but the page contents (alt-a)',
+      tip_comments: 'View the comments that other users have posted about this page (alt-c)',
+      tip_edit: 'Edit the contents of this page (alt-e)',
+      tip_viewsource: 'View the source code (wiki markup) that this page uses (alt-e)',
+      tip_history: 'View a log of actions taken on this page (alt-h)',
+      tip_rename: 'Change the display name of this page (alt-r)',
+      tip_delvote: 'Vote to have this page deleted (alt-d)',
+      tip_resetvotes: 'Clear the list of votes for deletion against this page (alt-y)',
+      tip_printable: 'View a version of this page that is suitable for printing',
+      tip_protect_on: 'Prevents all non-administrators from editing this page. [alt-i]',
+      tip_protect_off: 'Allows everyone to edit this page. [alt-o]',
+      tip_protect_semi: 'Allows only users who have been registered for 4 days to edit this page. [alt-p]',
+      tip_flushlogs: 'Remove all edit and action logs for this page from the database. IRREVERSIBLE! (alt-l)',
+      tip_deletepage: 'Delete this page. This is always reversible unless the logs are cleared. (alt-k)',
+      tip_adminoptions: 'Administrative options for this page',
+      tip_moreoptions: 'Additional options for working with this page',
+      tip_password: 'Require a password in order for this page to be viewed',
+      tip_aclmanager: 'Manage who can do what with this page (alt-m)',
+      
+      cat_heading_subcategories: 'Subcategories',
+      cat_msg_no_subcategories: 'No subcategories.',
+      cat_heading_pages: 'Pages',
+      cat_msg_no_pages: 'No pages in this category.',
+      
+      filebox_heading: 'Uploaded file',
+      filebox_msg_not_found: 'There are no files uploaded with this name yet. <a href="%upload_link%">Upload a file...</a>',
+      filebox_lbl_type: 'Type:',
+      filebox_lbl_size: 'Size: %size%',
+      filebox_lbl_uploaded: 'Uploaded:',
+      filebox_msg_virus_warning: 'This file type may contain viruses or other code that could harm your computer. You should exercise caution if you download it.',
+      filebox_btn_download: 'Download this file',
+      filebox_btn_upload_new: 'Upload new version',
+      filebox_heading_history: 'File history',
+      filebox_btn_this_version: 'this ver',
+      filebox_btn_revert: 'revert',
+      
+    },
+    editor: {
+      err_server: 'There was a problem starting the editor',
+      err_access_denied_title: 'Not authorized to view source',
+      err_access_denied_body: 'You are not authorized to edit or view the source of this page.',
+      err_save_title: 'There was a problem saving the page.',
+      err_save_body: 'A few problems were encountered while your page was being saved:',
+      err_obsolete_title: 'Someone else modified this page while you were editing it',
+      err_obsolete_body: 'While you were editing this page, %author% modified this page. The edit took place on %timestamp%. You can <a href="%page_url%" onclick="window.open(this.href); return false;">view the latest version of the page</a>, or click %this.editor_btn_save% again to replace the page with your revision.',
+      err_need_captcha_title: 'Missing confirmation code',
+      err_need_captcha_body: 'Please enter the confirmation code in the box labeled "%this.editor_lbl_field_captcha_code%". %this.editor_msg_captcha_blind%',
+      err_no_text_title: 'No text entered',
+      err_no_text_body: 'Please enter the text that will be in this page.',
+      // Server-side errors
+      err_no_rows: 'Page doesn\'t exist in the database',
+      err_no_permission: 'You do not have permission to edit this page.',
+      err_page_protected: 'This page is protected, and you do not have permission to edit protected pages.',
+      err_captcha_wrong: 'The confirmation code you entered is incorrect.',
+      
+      msg_editor_heading: 'Editing page',
+      msg_saved: 'Your changes to this page have been saved.',
+      msg_revert_confirm: 'Do you really want to revert your changes?',
+      msg_discard_confirm: 'Do you really want to discard your changes?',
+      msg_confirm_ajax: 'Do you really want to do this?\nYour changes to this page have not been saved. If you continue, your changes will be lost.',
+      msg_unload: 'If you do, any changes that you have made to this page will be lost.',
+      msg_revert_confirm_title: 'Do you really want to revert your changes?',
+      msg_revert_confirm_body: 'If you choose to continue, all of the changes you have made to this page will be lost, and the editor will be set with the latest published (not draft) copy of the page.',
+      msg_cancel_confirm_title: 'Do you want to cancel your changes?',
+      msg_cancel_confirm_body: 'Are you sure you want to discard the changes you made? If you continue, your changes cannot be recovered.',
+      msg_diff: 'Below is a summarization of the differences between the current revision of the page (left), and your version (right).',
+      msg_diff_empty: 'There are no differences between the text in the editor and the current revision of the page.',
+      msg_editing_old_revision: 'You are editing an old revision of this page. If you click Save, newer revisions of this page will be undone.',
+      msg_have_draft_title: 'A draft copy of this page is available.',
+      msg_have_draft_body: '%author% saved a draft version of this page on %time%. You can <a href="#use_draft" onclick="ajaxEditorUseDraft(); return false;">use the draft copy</a>, or edit the current published version (below). If you edit the published version, the draft copy will remain available, but will not reflect your changes. It is recommended that you edit the draft version instead of editing the published version.',
+      btn_graphical: 'graphical editor',
+      btn_wikitext: 'wikitext editor',
+      lbl_edit_summary: 'Brief summary of your changes:',
+      lbl_edit_summary_explain: 'Please summarize and briefly explain what you changed on the page.',
+      lbl_minor_edit: 'Mark revision as trivial:',
+      lbl_minor_edit_field: 'This is a minor edit',
+      lbl_minor_edit_explain: 'Select this if you\'re only making a minor change to the page',
+      btn_save: 'Save',
+      btn_savedraft: 'Save draft',
+      btn_preview: 'Preview',
+      btn_revert: 'Revert',
+      btn_cancel: 'Cancel',
+      btn_diff: 'Show changes',
+      btn_closeviewer: 'Close viewer',
+      msg_draft_saving: 'Saving...',
+      msg_draft_saved: 'Saved at %time%',
+      preview_blurb: '<b>Reminder:</b> This is only a preview - your changes to this page have not yet been saved.',
+      msg_save_success_title: 'Changes saved',
+      msg_save_success_body: 'Your changes to this page have been saved. Redirecting...',
+      reversion_edit_summary: 'Undid %undo_count% revision(s) by %current_author% to revision %last_rev_id% by %old_author%',
+      
+      msg_captcha_pleaseenter: 'Please enter the code shown in the image to the right into the text box. This process helps to ensure that this page is not being edited by an automated bot. If the image to the right is illegible, you can regenerate it by clicking on the image (only works if your browser supports Javascript).',
+      msg_captcha_blind: 'If you are visually impaired or otherwise cannot read the text shown to the right, please contact the site management and they will be able to make your requested edits.',
+      lbl_field_captcha: 'Visual confirmation',
+      lbl_field_captcha_code: 'Code:',
+    },
+    history: {
+      summary_clearlogs: 'Automatic backup created when logs were purged',
+      page_subtitle: 'History of edits and actions',
+      heading_edits: 'Edits:',
+      heading_other: 'Other changes:',
+      no_entries: 'No history entries in this category.',
+      btn_compare: 'Compare selected revisions',
+      col_diff: 'Diff',
+      col_datetime: 'Date/time',
+      col_user: 'User',
+      col_page: 'Page',
+      col_summary: 'Edit summary',
+      col_minor: 'Minor',
+      col_actions: 'Actions',
+      col_action_taken: 'Action taken',
+      col_extra: 'Extra info',
+      extra_reason: 'Reason:',
+      extra_oldtitle: 'Old title:',
+      tip_rdns: 'Click cell background for reverse DNS info',
+      action_view: 'View',
+      action_contrib: 'User contribs',
+      action_restore: 'Restore',
+      action_revert: 'Revert action',
+      log_protect: 'Protected page',
+      log_unprotect: 'Unprotected page',
+      log_semiprotect: 'Semi-protected page',
+      log_rename: 'Renamed page',
+      log_create: 'Created page',
+      log_delete: 'Deleted page',
+      log_uploadnew: 'Uploaded new file version',
+      lbl_comparingrevisions: 'Comparing revisions:',
+      summary_none_given: 'No edit summary provided.',
+    },
+    catedit: {
+      title: 'Select which categories this page should be included in.',
+      no_categories: 'There are no categories on this site yet.',
+      catbox_lbl_categories: 'Categories:',
+      catbox_lbl_uncategorized: '(Uncategorized)',
+      catbox_link_edit: 'edit categorization',
+      catbox_link_showcategorization: 'show page categorization',
+    },
+    tags: {
+      catbox_link: 'show page tags',
+      lbl_page_tags: 'Page tags:',
+      lbl_no_tags: 'No tags on this page',
+      btn_add_tag: '(add a tag)',
+      lbl_add_tag: 'Add a tag:',
+      btn_add: '+ Add',
+    },
+    delvote: {
+      lbl_votes_one: 'There is one user that thinks this page should be deleted.',
+      lbl_votes_plural: 'There are %num_users% users that think this page should be deleted.',
+      lbl_users_that_voted: 'Users that voted:',
+      btn_deletepage: 'Delete page',
+      btn_resetvotes: 'Reset votes',
+    },
+    ajax: {
+      // Client-side messages
+      protect_prompt_reason: 'Reason for (un)protecting:',
+      rename_prompt: 'What title should this page be renamed to?\nNote: This does not and will never change the URL of this page, that must be done from the admin panel.',
+      delete_prompt_reason: 'Please enter your reason for deleting this page.',
+      delete_confirm: 'You are about to REVERSIBLY delete this page. Do you REALLY want to do this?\n\n(Comments and categorization data, as well as any attached files, will be permanently lost)',
+      delvote_confirm: 'Are you sure that you want to vote that this page be deleted?',
+      delvote_reset_confirm: 'This action will reset the number of votes against this page to zero. Do you really want to do this?',
+      clearlogs_confirm: 'You are about to DESTROY all log entries for this page. As opposed to (example) deleting this page, this action is completely IRREVERSIBLE and should not be used except in dire circumstances. Do you REALLY want to do this?',
+      clearlogs_confirm_nag: 'You\'re ABSOLUTELY sure???',
+      changestyle_select: '[Select]',
+      changestyle_title: 'Change your theme',
+      changestyle_pleaseselect_theme: 'Please select a theme from the list.',
+      changestyle_lbl_theme: 'Theme:',
+      changestyle_lbl_style: 'Style:',
+      changestyle_success: 'Your theme preference has been changed.\nWould you like to reload the page now to see the changes?',
+      killphp_confirm: 'Are you really sure you want to do this? Some pages might not function if this emergency-only feature is activated.',
+      killphp_success: 'Embedded PHP in pages has been disabled.',
+      lbl_moreoptions_nojs: 'More options for this page',
+      
+      // Server-side responses
+      rename_too_short: 'The name you entered is too short. Please enter a longer name for this page.',
+      rename_success: 'The page "%page_name_old%" has been renamed to "%page_name_new%". You are encouraged to leave a comment explaining your action.\n\nYou will see the change take effect the next time you reload this page.',
+      clearlogs_success: 'The logs for this page have been cleared. A backup of this page has been added to the logs table so that this page can be restored in case of vandalism or spam later.',
+      delete_need_reason: 'Invalid reason for deletion passed. Please enter a reason for deleting this page.',
+      delete_success: 'This page has been deleted. Note that there is still a log of edits and actions in the database, and anyone with admin rights can raise this page from the dead unless the log is cleared. If the deleted file is an image, there may still be cached thumbnails of it in the cache/ directory, which is inaccessible to users.',
+      delvote_success: 'Your vote to have this page deleted has been cast.\nYou are encouraged to leave a comment explaining the reason for your vote.',
+      delvote_already_voted: 'It appears that you have already voted to have this page deleted.',
+      delvote_reset_success: 'The number of votes for having this page deleted has been reset to zero.',
+      password_success: 'The password for this page has been set.',
+      password_disable_success: 'The password for this page has been disabled.',
+      
+    },
+    sidebar: {
+      title_navigation: 'Navigation',
+      title_tools: 'Tools',
+      title_search: 'Search',
+      title_links: 'Links',
+      
+      btn_home: 'Home',
+      btn_createpage: 'Create a page',
+      btn_uploadfile: 'Upload file',
+      btn_specialpages: 'Special pages',
+      btn_administration: 'Administration',
+      btn_editsidebar: 'Edit the sidebar',
+      btn_search_go: 'Go',
+      
+      btn_userpage: 'User page',
+      btn_mycontribs: 'My contributions',
+      btn_preferences: 'Preferences',
+      btn_privatemessages: 'Private messages',
+      btn_groupcp: 'Group control panel',
+      btn_register: 'Create an account',
+      btn_login: 'Log in',
+      btn_logout: 'Log out',
+      btn_changestyle: 'Change theme',
+      btn_recent_changes: 'Recent edits',
+    },
+    perm: {
+      read: 'Read page(s)',
+      post_comments: 'Post comments',
+      edit_comments: 'Edit own comments',
+      edit_page: 'Edit page',
+      view_source: 'View source',
+      edit_wysiwyg: 'Use graphical editor (<a href="http://docs.enanocms.org/Help:4.1#toc4">WEAK</a>)',
+      mod_comments: 'Moderate comments',
+      history_view: 'View history/diffs',
+      history_rollback: 'Rollback history',
+      history_rollback_extra: 'Undelete page(s)',
+      protect: 'Protect page(s)',
+      rename: 'Rename page(s)',
+      clear_logs: 'Clear page logs (dangerous)',
+      vote_delete: 'Vote to delete',
+      vote_reset: 'Reset delete votes',
+      delete_page: 'Delete page(s)',
+      tag_create: 'Tag page(s)',
+      tag_delete_own: 'Remove own page tags',
+      tag_delete_other: 'Remove others\' page tags',
+      set_wiki_mode: 'Set per-page wiki mode',
+      password_set: 'Set password',
+      password_reset: 'Disable/reset password',
+      mod_misc: 'Super moderator (generate SQL backtraces, view IP addresses, and send large numbers of private messages)',
+      edit_cat: 'Edit categorization',
+      even_when_protected: 'Allow editing, renaming, and categorization even when protected',
+      upload_files: 'Upload files',
+      upload_new_version: 'Upload new versions of files',
+      create_page: 'Create pages',
+      html_in_pages: 'Embed unrestricted HTML in pages',
+      php_in_pages: 'Embed PHP code in pages',
+      edit_acl: 'Edit access control lists',
+    },
+    plugin: {
+      specialadmin_title: 'Runt - the Enano administration panel',
+      specialadmin_desc: 'Provides the page Special:Administration, which is the AJAX frontend to the various Admin pagelets. This plugin cannot be disabled.',
+      privatemessages_title: 'Private Message frontend',
+      privatemessages_desc: 'Provides the page Special:PrivateMessages, which is used to manage private message functions. Also handles buddy lists.',
+      specialcss_title: 'CSS Backend',
+      specialcss_desc: 'Provides the page Special:CSS, which is used in template files to reference the style sheet. Disabling or deleting this plugin will result in site instability.',
+      specialgroups_title: 'Group control panel',
+      specialgroups_desc: 'Provides group moderators and site administrators with the ability to control who is part of their groups.',
+      specialpagefuncs_title: 'Special page-related pages',
+      specialpagefuncs_desc: 'Provides the page Special:CreatePage, which can be used to create new pages. Also adds the About Enano and GNU General Public License pages.',
+      specialsearch_title: 'Search UI/frontend',
+      specialsearch_desc: 'Provides the page Special:Search, which is a frontend to the Enano search engine.',
+      specialupdownload_title: 'Upload/download frontend',
+      specialupdownload_desc: 'Provides the pages Special:UploadFile and Special:DownloadFile. UploadFile is used to upload files to the site, and DownloadFile fetches the file from the database, creates thumbnails if necessary, and sends the file to the user.',
+      specialuserfuncs_title: 'Special user/login-related pages',
+      specialuserfuncs_desc: 'Provides the pages Special:Login, Special:Logout, Special:Register, and Special:Preferences.',
+      specialuserprefs_title: 'User control panel',
+      specialuserprefs_desc: 'Provides the page Special:Preferences.',
+    },
+    paginate: {
+      lbl_page: 'Page:',
+      btn_first: 'First',
+      btn_last: 'Last',
+      btn_prev: 'Prev',
+      btn_next: 'Next',
+      lbl_goto_page: 'Go to page:',
+      err_bad_page_title: 'Invalid entry',
+      err_bad_page_body: 'Please enter a page number between 1 and %max%.',
+    },
+    upload: {
+      err_disabled_site: 'File uploads are disabled this website.',
+      err_disabled_acl: 'File uploads are disabled for your user account or group.',
+      
+      err_title: 'Upload failed',
+      err_cant_get_file_meta: 'The server could not retrieve the array $_FILES[\'data\'].',
+      err_too_big_or_small: 'The file you uploaded is either too large or 0 bytes in length.',
+      err_banned_ext: 'The file type ".%ext%" is not allowed.',
+      err_banned_chars: 'The filename contains invalid characters.',
+      err_already_exists: 'The file already exists. You can <a href="%upload_link%">upload a new version of this file</a>.',
+      err_replace_protected: 'Either the file does not exist (and therefore cannot be updated) or the file is protected.',
+      err_move_failed: 'Could not move uploaded file to the new location.',
+      err_replace_denied: 'Uploading new versions of files has been disabled for your user account or group.',
+      
+      success_title: 'Upload complete',
+      success_body: 'Your file has been uploaded successfully. View the <a href="%file_link%">file\'s page</a>.',
+      
+      intro: 'Using this form you can upload a file to the %config.site_name% site.',
+      max_filesize: 'The maximum file size is %config.max_file_size% %this.etc_unit_bytes% (%size%).',
+      field_file: 'File:',
+      field_renameto: 'Rename to:',
+      field_comments: 'Comments:<br />(can be wiki-formatted)',
+      field_reason: 'Reason for uploading the new version:',
+      btn_upload: 'Upload file',
+      
+      err_not_found_title: 'File not found',
+      err_not_found_body: 'The file "%filename%" cannot be found.',
+    },
+    tz: {
+      // Thanks to phpBB for this timezone data.
+      // Do not add or remove from this list - contact the core team to have changes made to this list.
+      hrs_n12: 'UTC - 12 hours',
+      hrs_n11: 'UTC - 11 hours',
+      hrs_n10: 'UTC - 10 hours',
+      hrs_n9p5: 'UTC - 9:30 hours',
+      hrs_n9: 'UTC - 9 hours',
+      hrs_n8: 'UTC - 8 hours',
+      hrs_n7: 'UTC - 7 hours',
+      hrs_n6: 'UTC - 6 hours',
+      hrs_n5: 'UTC - 5 hours',
+      hrs_n4: 'UTC - 4 hours',
+      hrs_n3p5: 'UTC - 3:30 hours',
+      hrs_n3: 'UTC - 3 hours',
+      hrs_n2: 'UTC - 2 hours',
+      hrs_n1: 'UTC - 1 hour',
+      hrs_0: 'UTC',
+      hrs_1: 'UTC + 1 hour',
+      hrs_2: 'UTC + 2 hours',
+      hrs_3: 'UTC + 3 hours',
+      hrs_3p5: 'UTC + 3:30 hours',
+      hrs_4: 'UTC + 4 hours',
+      hrs_4p5: 'UTC + 4:30 hours',
+      hrs_5: 'UTC + 5 hours',
+      hrs_5p5: 'UTC + 5:30 hours',
+      hrs_5p75: 'UTC + 5:45 hours',
+      hrs_6: 'UTC + 6 hours',
+      hrs_6p5: 'UTC + 6:30 hours',
+      hrs_7: 'UTC + 7 hours',
+      hrs_8: 'UTC + 8 hours',
+      hrs_8p75: 'UTC + 8:45 hours',
+      hrs_9: 'UTC + 9 hours',
+      hrs_9p5: 'UTC + 9:30 hours',
+      hrs_10: 'UTC + 10 hours',
+      hrs_10p5: 'UTC + 10:30 hours',
+      hrs_11: 'UTC + 11 hours',
+      hrs_11p5: 'UTC + 11:30 hours',
+      hrs_12: 'UTC + 12 hours',
+      hrs_12p75: 'UTC + 12:45 hours',
+      hrs_13: 'UTC + 13 hours',
+      hrs_14: 'UTC + 14 hours',
+      title_n12: '[UTC - 12] Baker Island Time',
+      title_n11: '[UTC - 11] Niue Time, Samoa Standard Time',
+      title_n10: '[UTC - 10] Hawaii-Aleutian Standard Time, Cook Island Time',
+      title_n9p5: '[UTC - 9:30] Marquesas Islands Time',
+      title_n9: '[UTC - 9] Alaska Standard Time, Gambier Island Time',
+      title_n8: '[UTC - 8] Pacific Standard Time',
+      title_n7: '[UTC - 7] Mountain Standard Time',
+      title_n6: '[UTC - 6] Central Standard Time',
+      title_n5: '[UTC - 5] Eastern Standard Time',
+      title_n4: '[UTC - 4] Atlantic Standard Time',
+      title_n3p5: '[UTC - 3:30] Newfoundland Standard Time',
+      title_n3: '[UTC - 3] Amazon Standard Time, Central Greenland Time',
+      title_n2: '[UTC - 2] Fernando de Noronha Time, South Georgia &amp; the South Sandwich Islands Time',
+      title_n1: '[UTC - 1] Azores Standard Time, Cape Verde Time, Eastern Greenland Time',
+      title_0: '[UTC] Western European Time, Greenwich Mean Time',
+      title_1: '[UTC + 1] Central European Time, West African Time',
+      title_2: '[UTC + 2] Eastern European Time, Central African Time',
+      title_3: '[UTC + 3] Moscow Standard Time, Eastern African Time',
+      title_3p5: '[UTC + 3:30] Iran Standard Time',
+      title_4: '[UTC + 4] Gulf Standard Time, Samara Standard Time',
+      title_4p5: '[UTC + 4:30] Afghanistan Time',
+      title_5: '[UTC + 5] Pakistan Standard Time, Yekaterinburg Standard Time',
+      title_5p5: '[UTC + 5:30] Indian Standard Time, Sri Lanka Time',
+      title_5p75: '[UTC + 5:45] Nepal Time',
+      title_6: '[UTC + 6] Bangladesh Time, Bhutan Time, Novosibirsk Standard Time',
+      title_6p5: '[UTC + 6:30] Cocos Islands Time, Myanmar Time',
+      title_7: '[UTC + 7] Indochina Time, Krasnoyarsk Standard Time',
+      title_8: '[UTC + 8] Chinese Standard Time, Australian Western Standard Time, Irkutsk Standard Time',
+      title_8p75: '[UTC + 8:45] Southeastern Western Australia Standard Time',
+      title_9: '[UTC + 9] Japan Standard Time, Korea Standard Time, Chita Standard Time',
+      title_9p5: '[UTC + 9:30] Australian Central Standard Time',
+      title_10: '[UTC + 10] Australian Eastern Standard Time, Vladivostok Standard Time',
+      title_10p5: '[UTC + 10:30] Lord Howe Standard Time',
+      title_11: '[UTC + 11] Solomon Island Time, Magadan Standard Time',
+      title_11p5: '[UTC + 11:30] Norfolk Island Time',
+      title_12: '[UTC + 12] New Zealand Time, Fiji Time, Kamchatka Standard Time',
+      title_12p75: '[UTC + 12:45] Chatham Islands Time',
+      title_13: '[UTC + 13] Tonga Time, Phoenix Islands Time',
+      title_14: '[UTC + 14] Line Island Time',
+      // This is a JSON string that lists all the timezones that are defined here.
+      list: '{"n12":-12,"n11":-11,"n10":-10,"n9p5":-9.5,"n9":-9,"n8":-8,"n7":-7,"n6":-6,"n5":-5,"n4":-4,"n3p5":-3.5,"n3":-3,"n2":-2,"n1":-1,"0":0,"1":1,"2":2,"3":3,"3p5":3.5,"4":4,"4p5":4.5,"5":5,"5p5":5.5,"5p75":5.75,"6":6,"6p5":6.5,"7":7,"8":8,"8p75":8.75,"9":9,"9p5":9.5,"10":10,"10p5":10.5,"11":11,"11p5":11.5,"12":12,"12p75":12.75,"13":13,"14":14}',
+    },
+    etc: {
+      redirect_title: 'Redirecting...',
+      redirect_body: 'Please wait while you are redirected.',
+      redirect_timeout: 'If you are not redirected within %timeout% seconds, please <a href="%redirect_url%">click here</a>.',
+      // Generic "Save Changes" button
+      save_changes: 'Save changes',
+      // Generic "Cancel changes" button
+      cancel_changes: 'Cancel changes',
+      // Generic wizard buttons
+      wizard_next: 'Next >',
+      wizard_back: '< Back',
+      wizard_previous: '< Previous',
+      // Generic link to main page
+      btn_main_page: 'Main page',
+      // Generic switchable editor buttons
+      tinymce_btn_text: 'text editor',
+      tinymce_btn_graphical: 'graphical editor',
+      // Generic "Notice:" label
+      lbl_notice: 'Notice:',
+      // Generic "Access denied"
+      access_denied: 'Access to the specified file, resource, or action is denied.',
+      access_denied_short: 'Access denied',
+      return_to_page: 'Return to the page',
+      invalid_request_short: 'Invalid request',
+      // Message box buttons
+      ok: 'OK',
+      cancel: 'Cancel',
+      yes: 'Yes',
+      no: 'No',
+      unit_bytes: 'bytes',
+      unit_kilobytes: 'kilobytes',
+      unit_megabytes: 'megabytes',
+      unit_gigabytes: 'gigabytes',
+      unit_terabytes: 'terabytes',
+      unit_kilobytes_short: 'KB',
+      unit_megabytes_short: 'MB',
+      unit_gigabytes_short: 'GB',
+      unit_terabytes_short: 'TB',
+      unit_pixels: 'pixels',
+      unit_pixels_short: 'px',
+    }
+  }
+};
+
+// All done! :-)
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/language/english/install.json	Fri Feb 22 12:51:53 2008 -0500
@@ -0,0 +1,365 @@
+/*
+ * Enano - an open-source CMS capable of wiki functions, Drupal-like sidebar blocks, and everything in between
+ * Version 1.1.1
+ * Copyright (C) 2006-2007 Dan Fuhry
+ *
+ * This program is Free Software; you can redistribute and/or modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.
+ *
+ * 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.
+ */
+
+// Enano installer strings
+// Language: ISO-639-3 eng (English)
+
+var enano_lang_install = {
+  categories: [
+    'meta', 'language', 'welcome', 'license', 'sysreqs', 'database', 'dbmysql', 'dbpgsql', 'website', 'login', 'confirm', 'install', 'finish', 'pophelp',
+  ],
+  strings: {
+    meta: {
+      site_name: 'Enano installation',
+      site_desc: 'Install Enano on your server.',
+      enano_copyright: 'Enano and its various components, related documentation, and artwork are copyright &copy; 2006 Dan Fuhry.<br />This program is Free Software; see the file "GPL" included with this package for details.',
+      sidebar_heading: 'Installation progress',
+      btn_article: 'installation page',
+      btn_continue: 'Continue',
+      lbl_before_continue: 'Before continuing:',
+      step: 'Step %step%: %title%',
+      
+      msg_err_verification: 'One or more of the form fields is incorrect. Please correct any information in the form that has an "X" next to it.',
+      
+      msg_err_stagefailed_title: 'Enano installation failed.',
+      msg_err_stagefailed_body: 'When you have corrected the error, click the button below to attempt to continue the installation.',
+      msg_err_stagefailed_mysqlerror: 'The error returned from MySQL was:',
+      btn_retry_installation: 'Retry installation',
+    },
+    language: {
+      modetitle: 'Language',
+    },
+    welcome: {
+      modetitle: 'Welcome',
+      heading: 'Welcome to Enano',
+      version: 'version',
+      branch_stable: 'stable',
+      branch_unstable: 'unstable',
+      aka: 'also affectionately known as "%codename%" <tt>:)</tt>',
+      btn_start: 'Start installation',
+    },
+    license: {
+      modetitle: 'License',
+      modetitle_long: 'License agreement',
+      heading: 'Welcome to the Enano installer.',
+      blurb_thankyou: 'Thank you for choosing Enano as your CMS. You\'ve selected the finest in design, the strongest in security, and the latest in Web 2.0 toys. Trust us, you\'ll like it.',
+      blurb_pleaseread: 'To get started, please read and accept the following license agreement. You\'ve probably seen it before.',
+      info_unstable_title: 'Notice for prerelease versions',
+      info_unstable_body: 'This version of Enano is designed only for testing and evaluation purposes. <b>It is not yet completely stable, and should not be used on production websites.</b> As with any Enano version, Dan Fuhry and the Enano team cannot be responsible for any damage, physical or otherwise, to any property as a result of the use of Enano. While security is a number one priority, sometimes things slip through.',
+      section_gpl_heading: 'Lawyer-readable version',
+      btn_i_agree: 'I agree to the license terms',
+      objective_ensure_agree: 'Ensure that you agree with the terms of the license',
+      objective_have_db_info: 'Have your database host, name, username, and password available',
+      gpl_blurb_inenglish: 'You may view a copy of the GNU General Public License in English in the file GPL-EN included with this package.',
+    },
+    sysreqs: {
+      modetitle: 'Requirements',
+      modetitle_long: 'Server requirements',
+      heading: 'Checking your server',
+      blurb: 'Enano has several requirements that must be met before it can be installed. If all is good then note any warnings and click Continue below.',
+      req_php: 'PHP Version >=4.3.0',
+      req_php5: 'PHP 5.2.0 or later',
+      req_postgres: 'PostgreSQL extension for PHP',
+      req_mysql: 'MySQL extension for PHP',
+      req_uploads: 'File upload support',
+      req_apache: 'Apache HTTP Server',
+      req_config: 'Configuration file writable',
+      req_magick: 'ImageMagick support',
+      req_cachewriteable: 'Cache directory writable',
+      req_fileswriteable: 'File uploads directory writable',
+      
+      req_desc_php: 'It seems that the version of PHP that your server is running is too old to support Enano properly. If this is your server, please upgrade to the most recent version of PHP, remembering to use the --with-mysql configure option if you compile it yourself. If this is not your server, please contact your webhost and ask them if it would be possible to upgrade PHP. If this is not possible, you will need to switch to a different webhost in order to use Enano.',
+      req_desc_php5: 'Your server does not have support for PHP 5.2.0. While you may continue installing Enano, please be warned that as of December 31, 2007, all support for Enano on PHP 4 servers is discontinued. If you have at least PHP 5.0.0, support will still be available, but there are many security problems in PHP versions under 5.2.0 that Enano cannot effectively prevent.',
+      req_desc_postgres: 'It seems that your PHP installation does not have the PostgreSQL extension enabled. Because of this, you won\'t be able to use the PostgreSQL database driver. This is OK in the majority of cases. If you want to use PostgreSQL support, you\'ll need to either compile the PHP extension for Postgres or install the extension with your distribution\'s package manager. Windows administrators will need enable php_pgsql.dll in their php.ini.',
+      req_desc_mysql: 'It seems that your PHP installation does not have the MySQL extension enabled. If this is your own server, you may need to just enable the "libmysql.so" extension in php.ini. If you do not have the MySQL extension installed, you will need to either use your distribution\'s package manager to install it, or you will have to compile PHP from source. If you compile PHP from source, please remember to use the "--with-mysql" configure option, and you will have to have the MySQL development files installed (they usually are). If this is not your server, please contact your hosting company and ask them to install the PHP MySQL extension.',
+      req_desc_uploads: 'It seems that your server does not support uploading files. Enano *requires* this functionality in order to work properly. Please ask your server administrator to set the "file_uploads" option in php.ini to "On".',
+      req_desc_apache: 'Apparently your server is running a web server other than Apache. Enano will work nontheless, but there are some known bugs with non-Apache servers, and the "fancy" URLs will not work properly. The "Standard URLs" option will be set on the website configuration page, only change it if you are absolutely certain that your server is running Apache.',
+      req_desc_config: 'It looks like the configuration file, config.new.php, is not writable. Enano needs to be able to write to this file in order to install.<br /><br /><b>If you are installing Enano on a SourceForge web site:</b><br />SourceForge mounts the web partitions read-only now, so you will need to use the project shell service to symlink config.php to a file in the /tmp/persistent directory.',
+      req_desc_magick: 'Enano uses ImageMagick to scale images into thumbnails. Because ImageMagick was not found on your server, Enano will use the width= and height= attributes on the &lt;img&gt; tag to scale images. This can cause somewhat of a performance increase, but bandwidth usage will be higher, especially if you use high-resolution images on your site.<br /><br />If you are sure that you have ImageMagick, you can set the location of the "convert" program using the administration panel after installation is complete.',
+      req_desc_cachewriteable: 'Apparently the cache/ directory is not writable. Enano will still work, but you will not be able to cache thumbnails, meaning the server will need to re-render them each time they are requested. In some cases, this can cause a significant slowdown.',
+      req_desc_fileswriteable: 'It seems that the directory where uploaded files are stored (%enano_root%/files) cannot be written by the server. Enano will still function, but file uploads will not function, and will be disabled by default.',
+      
+      summary_success_title: 'Your server meets all the requirements for running Enano.',
+      summary_success_body: 'Click the button below to continue the installation.',
+      
+      summary_warn_title: 'Some of the features of Enano have been turned off to accommodate your server.',
+      summary_warn_body: 'Enano has detected that some of the features or configuration settings on your server are not optimal for the best behavior and/or performance for Enano. As a result, Enano has disabled these features as a precaution to prevent errors and potential security issues.',
+      
+      summary_fail_title: 'Your server does not meet the requirements for Enano to run.',
+      summary_fail_body: 'As a precaution, Enano will not install until the above requirements have been met. Contact your server administrator or hosting company and convince them to upgrade. Good luck.',
+      
+      objective_scalebacks: 'Review the list above to ensure that you are satisfied with any of Enano\'s workarounds for your server. If you need a particular feature and that feature is listed as disabled above, you should take the opportunity now to correct the problem.'
+    },
+    database: {
+      modetitle: 'Database',
+      modetitle_long: 'Database information',
+      heading_optionalinfo: 'Optional information',
+      
+      driver_heading: 'Choose a database driver',
+      driver_intro: 'The next step is to choose the database driver that Enano will use. In most cases this is MySQL, but there are certain advantages to PostgreSQL, which is made available only experimentally.',
+      driver_msg_virt_appliance: '<b>You\'re using the Enano virtual appliance.</b><br />Unless you configured the appliance manually, PostgreSQL support is not available. In 99% of cases you\'ll want to click MySQL below.',
+      driver_err_no_mysql: 'You don\'t have the MySQL PHP extension installed.',
+      driver_err_no_pgsql: 'You don\'t have the PostgreSQL PHP extensnion installed.',
+      driver_mysql: 'MySQL',
+      driver_mysql_intro: 'Click this button to use MySQL as the database backend for your site. Most web hosts support MySQL, and if you have administrative access to your MySQL server, you can create a new database and user during this installation process if you haven\'t done so already.',
+      driver_pgsql: 'PostgreSQL',
+      driver_pgsql_intro: 'Click this button to use PostgreSQL as the database backend for your site. While not as widely supported, PostgreSQL has more liberal licensing conditions and when properly configured is faster than MySQL. Some plugins may not work with the PostgreSQL driver.',
+      
+      objective_test: 'Check your MySQL connection using the "Test Connection" button.',
+      objective_uncrypt: 'Be aware that your database information will be transmitted unencrypted several times.',
+      
+      // database_post module
+      btn_go_back: 'Go back',
+      msg_success_title: 'Connection successful',
+      msg_success_body: 'The database has been contacted and initial tables created successfully. Redirecting...',
+      msg_success_redirect: 'Click if you\'re not redirected within 2 seconds',
+      
+      msg_post_fail_title: 'Database connection failed',
+      msg_post_fail_body: 'The installer couldn\'t connect to the database because something went wrong while the connection attempt was being made. Please press your browser\'s back button and correct your database information.',
+      msg_post_fail_desc: 'Error description:',
+      
+      msg_sql_fail_title: 'Database operation failed',
+      msg_sql_fail_body: 'The installer couldn\'t create one of the tables used for installation.',
+    },
+    dbmysql: {
+      msg_err_mysql_connect: '<b>Error:</b> The database server "%db_host%" couldn\'t be contacted.<br />%mysql_error%',
+      msg_err_mysql_auth: '<b>Error:</b> Access to MySQL under the specified credentials was denied.<br />%mysql_error%',
+      msg_err_mysql_dbperm: '<b>Error:</b> Access to the specified database using those login credentials was denied.<br />%mysql_error%',
+      msg_err_mysql_dbexist: '<b>Error:</b> The specified database does not exist<br />%mysql_error%',
+      msg_err_mysql_version: '<b>Error:</b> Your version of MySQL (%mysql_version%) is older than 4.1.17. Enano will still work, but there is a known bug with the comment system and MySQL 4.1.11 that involves some comments not being displayed, due to an issue with the PHP function mysql_fetch_row().',
+      
+      msg_warn_creating_db: '<b>Warning:</b> The database you specified does not exist. It will be created during installation.',
+      msg_warn_creating_user: '<b>Warning:</b> The specified regular user does not exist or the password is incorrect. The user will be created during installation. If the user already exists, the password will be reset.',
+      msg_warn_mysql_version: 'The MySQL version that your server is running could not be determined.',
+      
+      msg_info_mysql_good: 'Your version of MySQL meets Enano requirements.',
+      msg_test_success: 'All checks passed! You can use this database configuration with Enano.',
+      
+      blurb_needdb: 'Now we need some information that will allow Enano to contact your database server. Enano uses MySQL as a data storage backend, and we need to have access to a MySQL server in order to continue.',
+      blurb_howtomysql: 'If you do not have access to a MySQL server, and you are using your own server, you can download MySQL for free from <a href="http://www.mysql.com/">MySQL.com</a>. <b>Please note that, like Enano, MySQL is licensed under the GNU GPL.</b> If you need to modify MySQL and then distribute your modifications, you must either distribute them under the terms of the GPL or purchase a proprietary license.',
+      
+      vm_login_info: '<b>MySQL login information for this virtual appliance:</b><br /><br />Database hostname: %host%<br />Database login: username "%user%", password: "%pass%" (without quotes)<br />Database name: %name%',
+      
+      table_title: 'Database information',
+      
+      field_hostname_title: 'Database hostname',
+      field_hostname_body: 'This is the hostname (or sometimes the IP address) of your MySQL server. In many cases, this is "localhost".',
+      field_dbname_title: 'Database name',
+      field_dbname_body: 'The name of the actual database. If you don\'t already have a database, you can create one here, if you have the username and password of a MySQL user with administrative rights.',
+      field_dbauth_title: 'Database login',
+      field_dbauth_body: 'These fields should be the username and password of a user with "select", "insert", "update", "delete", "create table", and "replace" privileges for your database.',
+      field_tableprefix_title: 'Table prefix',
+      field_tableprefix_body: 'The value that you enter here will be added to the beginning of the name of each Enano table. You may use lowercase letters (a-z), numbers (0-9), and underscores (_).',
+      field_rootauth_title: 'Database administrative login',
+      field_rootauth_body: 'If the MySQL database or username that you entered above does not exist yet, you can create them here, assuming that you have the login information for an administrative user (such as root). Leave these fields blank unless you need to use them.',
+      field_mysqlversion_title: 'MySQL version',
+      field_mysqlversion_blurb_willbechecked: 'MySQL version information will be checked when you click "Test Connection".',
+      field_droptables_title: 'Delete existing tables?',
+      field_droptables_body: 'If this option is checked, all the tables that will be used by Enano will be dropped (deleted) before the schema is executed. Do NOT use this option unless specifically instructed to.',
+      field_droptables_lbl: 'Drop existing tables',
+      
+      btn_testconnection: 'Test connection',
+    },
+    dbpgsql: {
+      msg_err_connect: 'There was a problem connecting to PostgreSQL. Please check your connection information above.',
+      msg_err_version: '<b>Error:</b> Your version of PostgreSQL (%pg_version%) is older than 8.2.5. Enano cannot be installed.',
+      
+      msg_warn_pg_version: 'The PostgreSQL version that your server is running could not be determined.',
+      msg_err_auth: 'Access to the database was denied. Ensure that your database exists and that your username and password are correct.',
+      
+      msg_info_version_good: 'Your version of PostgreSQL meets Enano requirements.',
+      msg_test_success: 'All checks passed! You can use this database configuration with Enano.',
+      
+      blurb_needdb: 'Now we need some information that will allow Enano to contact your database server. Enano uses PostgreSQL as a data storage backend, and we need to have access to a PostgreSQL server in order to continue.',
+      blurb_howtomysql: 'If you do not have access to a PostgreSQL server, and you are using your own server, you can download PostgreSQL for free from <a href="http://www.mysql.com/">PostgreSQL.com</a>. <b>Please note that, like Enano, PostgreSQL is licensed under the GNU GPL.</b> If you need to modify PostgreSQL and then distribute your modifications, you must either distribute them under the terms of the GPL or purchase a proprietary license.',
+      
+      vm_login_info: '<b>PostgreSQL login information for this virtual appliance:</b><br /><br />Database hostname: %host%<br />Database login: username "%user%", password: "%pass%" (without quotes)<br />Database name: %name%',
+      
+      table_title: 'Database information',
+      
+      field_hostname_title: 'Database hostname',
+      field_hostname_body: 'This is the hostname (or sometimes the IP address) of your PostgreSQL server. In many cases, this is "localhost".',
+      field_dbname_title: 'Database name',
+      field_dbname_body: 'The name of the actual database. If you don\'t already have a database, you can create one here, if you have the username and password of a PostgreSQL user with administrative rights.',
+      field_dbauth_title: 'Database login',
+      field_dbauth_body: 'These fields should be the username and password of a user with "select", "insert", "update", "delete", "create table", and "replace" privileges for your database.',
+      field_tableprefix_title: 'Table prefix',
+      field_tableprefix_body: 'The value that you enter here will be added to the beginning of the name of each Enano table. You may use lowercase letters (a-z), numbers (0-9), and underscores (_).',
+      field_rootauth_title: 'Database administrative login',
+      field_rootauth_body: 'If the PostgreSQL database or username that you entered above does not exist yet, you can create them here, assuming that you have the login information for an administrative user (such as root). Leave these fields blank unless you need to use them.',
+      field_pgsqlversion_title: 'PostgreSQL version',
+      field_pgsqlversion_blurb_willbechecked: 'PostgreSQL version information will be checked when you click "Test Connection".',
+      field_droptables_title: 'Delete existing tables?',
+      field_droptables_body: 'If this option is checked, all the tables that will be used by Enano will be dropped (deleted) before the schema is executed. Do NOT use this option unless specifically instructed to.',
+      field_droptables_lbl: 'Drop existing tables',
+      
+      btn_testconnection: 'Test connection',
+    },
+    website: {
+      modetitle: 'Site info',
+      modetitle_long: 'Website information',
+      header_blurb: 'The next step is to enter some information about your website. You can always change this information later, using the administration panel.',
+      
+      msg_ajax_test_fail_title: 'All tests failed',
+      msg_ajax_test_fail_body: 'None of the URL handling tests worked; you may have problems using Enano on your server.',
+      msg_bestmethod_rewrite: 'The installer has detected that using rewritten URLs is the best level that will work.',
+      msg_bestmethod_shortened: 'The installer has detected that using shortened URLs is the best level that will work.',
+      msg_bestmethod_standard: 'The installer has detected that using standard URLs is the only level that will work.',
+      
+      field_name: 'Pick a name',
+      field_name_hint: 'Now for the fun part - it\'s time to name your website. Try to pick something that doesn\'t include any special characters, since this can make project-page URLs look botched.',
+      field_desc: 'Enter a short description',
+      field_desc_hint: 'Here you should enter a very short description of your site. Sometimes this is a slogan or, depending on the theme you\'ve chosen, a set of keywords that can go into a META description tag.',
+      field_copyright: 'Copyright info',
+      field_copyright_hint: 'The text you enter here will be shown at the bottom of most pages. Typically this is where a copyright notice would go. Keep it short and sweet; you can use <a href="http://docs.enanocms.org/Help:3.1">internal links</a> to link to project pages you\'ll create later.',
+      field_urlscheme: 'URL formatting',
+      field_urlscheme_hint: 'This lets you choose how URLs within your site will be formatted. If the setting you pick doesn\'t work, you can change it by editing config.php after installation.',
+      field_urlscheme_lbl_example: 'Example:',
+      field_urlscheme_opt_standard: 'Standard URLs',
+      field_urlscheme_opt_standard_hint: 'Compatible with all servers. This is the default option and should be used unless you\'re sure that one of the other options below will work.',
+      field_urlscheme_opt_shortened: 'Shortened URLs',
+      field_urlscheme_opt_shortened_hint: 'This eliminates the "?title=" portion of your URL, and instead uses a slash. This is occasionally more friendly to search engines.',
+      field_urlscheme_opt_rewrite: 'Rewritten URLs',
+      field_urlscheme_opt_rewrite_hint: 'Using this option, you can completely eliminate the "index.php" from URLs. This is the most friendly option to search engines and looks very professional, but requires support for URL rewriting on your server. If you\'re running Apache and have the right permissions, Enano can configure this automatically. Otherwise, you\'ll need to configure your server manually and have a knowledge of regular expressions for this option to work.',
+      btn_urlscheme_detect: 'Auto-detect the best formatting scheme',
+      
+      objective_verify: 'Verify that your site information is correct. Again, all of the above settings can be changed from the administration panel.',
+    },
+    login: {
+      modetitle: 'Admin login',
+      header_blurb: 'Next, enter your desired username and password. The account you create here will be used to administer your site.',
+      modetitle_long: 'Administration login',
+      
+      welcome_title: 'Administration account',
+      welcome_body: '<p>Now it\'s time to create the account you\'ll use to administer your site. The e-mail address you enter here will also be used for the global contact address; you can change this after installation is finished if need be.</p>
+                     <p>Do not forget the information you enter here. Otherwise you will be unable to administer your site.</p>',
+      err_verify_failure: 'One or more of the form fields contains an incorrect value. Please correct any fields that have an X next to them.',
+      err_rijndael_failed: 'Received a bad response from rijndaelEncrypt(). Shift-click "reload" or "refresh" (depending on your browser) and try again.',
+      field_username: 'Username',
+      field_password: 'Password',
+      aes_blurb: 'This will be encrypted with AES before it\'s sent to the server.',
+      field_password_confirm: '(confirm)',
+      field_email: 'E-mail',
+      
+      objective_remember: 'Remember the username and password you enter here! You will not be able to administer your site without the information you enter on this page.',
+    },
+    confirm: {
+      modetitle: 'Review',
+      modetitle_long: 'Confirm installation',
+      
+      title: 'Enano is ready to install.',
+      body: 'Almost there! You\'ve entered all the information we need for now. Click the button below to install the Enano database.',
+      info_aes_title: 'A note on AES encryption:',
+      info_aes_body: 'Enano is currently configured to use %aes_bits%-bit AES encryption. While the default value of 192 bits is perfectly acceptable for most sites, those in need of extreme security will want to change this value to 256 bits (the maximum available strength). If you need to change the cipher strength, please edit the file includes/constants.php and then <u>restart</u> this installation. Do not click Continue below until you redo the installation process up until this point, or you will experience severe problems with logging into your site.',
+      
+      btn_install_enano: 'Install Enano!',
+    },
+    install: {
+      modetitle: 'Install',
+      modetitle_long: 'Database installation',
+      
+      title: 'Installing Enano',
+      body: 'Please wait while Enano creates its database and initial content on your server.',
+      heading_progress: 'Installation progress',
+      
+      stg_load_title: 'Load installer files',
+      stg_load_body: 'One of the files needed for installation couldn\'t be loaded. Please check your Enano directory.',
+      stg_setpass_title: 'Retrieve administrator password',
+      stg_setpass_body: 'The administrator password couldn\'t be decrypted. This really shouldn\'t happen.',
+      stg_genaes_title: 'Generate private key',
+      stg_genaes_body: 'Couldn\'t generate a private key for the site. This really shouldn\'t happen.',
+      stg_sqlparse_title: 'Prepare database schema',
+      stg_sqlparse_body: 'Couldn\'t load or parse the schema file. This really shouldn\'t happen.',
+      stg_payload_title: 'Install database',
+      stg_payload_body: 'There was a problem with an SQL query. Details are above.',
+      stg_writeconfig_title: 'Write configuration files',
+      stg_writeconfig_body: 'Enano was unable to write the configuration file with your site\'s database credentials. This is almost always because your configuration file does not have the correct permissions. On Windows servers, you may see this message even if the check on the System Requirements page passed. Temporarily running IIS as the Administrator user may help.',
+      
+      stg_startapi_title: 'Start the Enano API',
+      stg_startapi_body: 'The Enano API could not be started. This is an error that should never occur; please contact the Enano team for support.',
+      stg_importlang_title: 'Import default language',
+      stg_importlang_body: 'Enano couldn\'t import the English language file.',
+      stg_initlogs_title: 'Initialize logs',
+      stg_initlogs_body: '<b>The session manager denied the request to flush logs for the main page.</b><br />
+                           While under most circumstances you can still <a href="install.php?mode=finish">finish the installation</a>, you should be aware that some servers cannot
+                           properly set cookies due to limitations with PHP. These limitations are exposed primarily when this issue is encountered during installation. If you choose
+                           to finish the installation, please be aware that you may be unable to log into your site.',
+      
+      stg_cleanup_title: 'Clean up encryption keys',
+      stg_cleanup_body: 'There was a database error while removing the temporary encryption keys from the database. For maximum site security you should delete the config entries install_aes_key and site_aes_key manually.',
+      stg_rename_title: 'Rename configuration files',
+      stg_rename_body: 'Enano couldn\'t rename the configuration files to their correct production names. <span style="font-weight: bold; color: red;">Please perform the following rename operations and then follow the instructions to finish the installation below.</span>
+                          <ul>
+                            <li>Rename config.new.php to config.php</li>
+                            <li>Rename .htaccess.new to .htaccess (only if you selected the Rewrite URL scheme)</li>
+                          </ul>
+                        %this.finish_body%
+                        %this.finish_link_mainpage%',
+      stg_buildindex_title: 'Initialize search index',
+      stg_buildindex_body: 'Something went wrong while the page manager was attempting to build a search index.',
+    },
+    finish: {
+      modetitle: 'Finish',
+      modetitle_long: 'Complete installation',
+      
+      heading_progress: 'Performing final installation steps',
+      msg_progress: 'Enano is cleaning up and performing some final installation tasks. Please wait...',
+      msg_success_title: 'Congratulations! You\'ve finished installing Enano.',
+      msg_success_body: 'Enano has finished setting up on your server. Now you can go to your <a href="%mainpage_link%">new website</a> and start creating content!',
+      
+      body: '<h3>Wait... Now what?</h3>
+             <p>Click the link below to see the main page for your website. Where to go from here:</p>
+             <ul>
+               <li>The first thing you should do is log into your site using the Log in link on the sidebar.</li>
+               <li>Go into the Administration panel, expand General, and click General Configuration. There you will be able to configure some basic information about your site.</li>
+               <li>Visit the <a href="http://enanocms.org/Category:Plugins" onclick="window.open(this.href); return false;">Enano Plugin Gallery</a> to download and use plugins on your site.</li>
+               <li>Periodically create a backup of your database and filesystem, in case something goes wrong. This should be done at least once a week &ndash; more for wiki-based sites.</li>
+               <li>Hire some moderators, to help you keep rowdy users tame.</li>
+               <li>Tell the <a href="http://enanocms.org/Contact_us">Enano team</a> what you think.</li>
+               <li><b>Spread the word about Enano by adding a link to the Enano homepage on your sidebar!</b> You can enable this option in the General Configuration section of the administration panel.</li>
+             </ul>',
+      link_mainpage: '<a href="%mainpage_link%">Go to your website...</a>',
+    },
+    pophelp: {
+      admin_embed_php_title: 'Allow administrators to embed PHP',
+      admin_embed_php_body: '<p>This option allows you to control whether anything between the standard &lt;?php and ?&gt; tags will be treated as
+                                PHP code by Enano. If this option is enabled, and members of the Administrators group use these tags, Enano will
+                                execute that code when the page is loaded. There are obvious potential security implications here, which should
+                                be carefully considered before enabling this option.</p>
+                             <p>If you are the only administrator of this site, or if you have a high level of trust for those will be administering
+                                the site with you, you should enable this to allow extreme customization of pages.</p>
+                             <p>Leave this option off if you are at all concerned about security – if your account is compromised and PHP embedding
+                                is enabled, an attacker can run arbitrary code on your server! Enabling this will also allow administrators to
+                                embed Javascript and arbitrary HTML and CSS.</p>
+                             <p>If you don\'t have experience coding in PHP, you can safely disable this option. You may change this at any time
+                                using the ACL editor by selecting the Administrators group and This Entire Website under the scope selection.</p>',
+      url_schemes_title: 'URL schemes',
+      url_schemes_body: '<p>The URL scheme allows you to decide how the URLs to your Enano pages will look.</p>
+                         <p>The first option (Standard URLs) works on any web server. You should select it if your server doesn\'t run Apache, or
+                            if you are at all unsure of your server\'s configuration. With this scheme, URLs at your site will look like <tt>
+                            http://yoursite.com/path-to-enano/index.php/Main_Page</tt>.</p>
+                         <p>The second option, Small URLs, will be selected by default if Enano detects Apache. Small URLs are more friendly towards
+                            search engines, but they don\'t work on very many non-Apache servers, or if PHP is set up through CGI on your server. Many
+                            free and low-cost web hosts will configure PHP through CGI in order to keep your user account as the owner of any files that
+                            Enano generates. With this scheme, URLs at your site will look like <tt>http://yoursite.com/path-to-enano/index.php/Main_Page</tt>.
+                            </p>
+                         <p>The last option, Tiny URLs, is the most friendly URL scheme for search engines, because your URLs won\'t have any special characters
+                            at all in them. However, this only works if your webhost has configured Apache with support for mod_rewrite. Most of the time if your
+                            host supports this you will see a listing for it in their feature matrix. None of the popular Linux distributions (such as Ubuntu,
+                            Debian, Red Hat Enterprise Linux&trade;, Fedora, openSUSE&trade;, or CentOS) come with mod_rewrite enabled, so if you run a
+                            home-brew server, you should consult your distribution\'s documentation for enabling mod_rewrite before selecting this option.
+                            With this scheme, URLs at your site will look like <tt>http://yoursite.com/path-to-enano/Main_Page</tt>.</p>
+                            </p>',
+      btn_close_window: 'Close window',
+    }
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/language/english/install/license-deed.html	Fri Feb 22 12:51:53 2008 -0500
@@ -0,0 +1,25 @@
+<h2>GNU General Public License</h2>
+
+<h3>Declaration of license usage</h3>
+
+<p>Enano is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.</p>
+<p>This program is distributed in the hope that it will be useful, but <u>without any warranty</u>; without even the implied warranty of <u>merchantability</u> or <u>fitness for a particular purpose</u>. See the GNU General Public License (below) for more details.</p>
+<p><b>By clicking the button below or otherwise continuing the installation, you indicate your acceptance of this license agreement.</b></p>
+
+<h3>Human-readable version</h3>
+<p>Enano is distributed under certain licensing terms that we believe make it of the greatest possible use to the public. The license we distribute it under, the GNU General Public License, provides certain terms and conditions that, rather than limit your use of Enano, allow you to get the most out of it. If you would like to read the full text, it can be found below. Here is a human-readable version that we think is a little easier to understand.</p>
+<ul>
+  <li>You may to run Enano for any purpose.</li>
+  <li>You may study how Enano works and adapt it to your needs.</li>
+  <li>You may redistribute copies so you can help your neighbor.</li>
+  <li>You may improve Enano and release your improvements to the public, so that the whole community benefits.</li>
+</ul>
+<p>You may exercise the freedoms specified here provided that you comply with the express conditions of this license. The principal conditions are:</p>
+<ul>
+  <li>You must conspicuously and appropriately publish on each copy distributed an appropriate copyright notice and disclaimer of warranty and keep intact all the notices that refer to this License and to the absence of any warranty; and give any other recipients of Enano a copy of the GNU General Public License along with Enano. Any translation of the GNU General Public License must be accompanied by the GNU General Public License.</li>
+  <li>If you modify your copy or copies of Enano or any portion of it, or develop a program based upon it, you may distribute the resulting work provided you do so under the GNU General Public License. Any translation of the GNU General Public License must be accompanied by the GNU General Public License.</li>
+  <li>If you copy or distribute Enano, you must accompany it with the complete corresponding machine-readable source code or with a written offer, valid for at least three years, to furnish the complete corresponding machine-readable source code.</li>
+</ul>
+<p>
+  <b>Disclaimer</b>: The above text is not a license. It is simply a handy reference for understanding the Legal Code (the full license) &ndash; it is a human-readable expression of some of its key terms. Think of it as the user-friendly interface to the Legal Code beneath. The above text itself has no legal value, and its contents do not appear in the actual license.<br /><span style="color: #CCC">Text copied from the <a href="http://creativecommons.org/licenses/GPL/2.0/">Creative Commons GPL Deed page</a></span>
+</p>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/language/english/install/mainpage-default.wkt	Fri Feb 22 12:51:53 2008 -0500
@@ -0,0 +1,11 @@
+=== Enano has been successfully installed and is working. ===
+
+If you can see this message, it means that you've finished the Enano setup process and are ready to start building your website. Congratulations!
+
+To edit this front page, click the Log In button to the left, enter the credentials you provided during the installation, and click the Edit This Page button that appears on the blue toolbar just above this text. You can also [http://docs.enanocms.org/Help:2.4 learn more] about editing pages.
+
+To create more pages, use the Create a Page button to the left. If you enabled wiki mode, you don't have to log in first, however your IP address will be shown in the page history.
+
+Visit the [http://docs.enanocms.org/Help:Contents Enano documentation project website] to learn more about administering your site effectively and keeping things secure.
+
+'''NOTE:''' You have just installed an unstable version of Enano. This release is completely unsupported and may contain security issues or serious usability bugs. You should not use this release on a production website. The Enano team will not provide any type of support at all for this experimental release.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/language/english/meta.json	Fri Feb 22 12:51:53 2008 -0500
@@ -0,0 +1,6 @@
+{
+  // Language metadata
+  lang_name_english: 'English',
+  lang_name_native: 'English',
+  lang_code: 'eng'
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/language/english/tools.json	Fri Feb 22 12:51:53 2008 -0500
@@ -0,0 +1,149 @@
+/*
+ * Enano - an open-source CMS capable of wiki functions, Drupal-like sidebar blocks, and everything in between
+ * Version 1.1.1
+ * Copyright (C) 2006-2007 Dan Fuhry
+ *
+ * This program is Free Software; you can redistribute and/or modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.
+ *
+ * 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.
+ */
+
+var enano_lang = {
+  categories: [
+    'meta', 'search', 'specialpage', 'pagetools'
+  ],
+  strings: {
+    meta: {
+      search: 'Search page',
+      specialpage: 'Special pages',
+      pagetools: 'Userspace page-management tools',
+    },
+    specialpage: {
+      administration: 'Administration',
+      manage_sidebar: 'Manage the Sidebar',
+      css: 'Templated style sheet generator',
+      groupcp: 'Group Membership',
+      create_page: 'Create page',
+      all_pages: 'All pages',
+      special_pages: 'List of special pages',
+      about_enano: 'About Enano',
+      gnu_gpl: 'GNU General Public License',
+      tag_cloud: 'Tag cloud',
+      search_rebuild: 'Rebuild search index',
+      search: 'Search',
+      upload_file: 'Upload file',
+      download_file: 'Download file',
+      log_in: 'Log in',
+      log_out: 'Log out',
+      register: 'Register',
+      preferences: 'Edit Profile',
+      contributions: 'User contributions',
+      change_theme: 'Change my preferred theme',
+      activate_account: 'Activate user account',
+      captcha: 'CAPTCHA image generator',
+      password_reset: 'Reset forgotten password',
+      member_list: 'Member list',
+      language_export: 'Language exporter',
+      private_messages: 'Private Messages',
+      recent_changes: 'Recent changes',
+    },
+    search: {
+      th_advanced_search: 'Advanced Search',
+      
+      err_query_title: 'Some problems were encountered during your search.',
+      err_query_body: 'There was a problem with your search query, and as a result there may be a reduced number of search results.',
+      err_query_too_many_terms: 'Some of your search terms were excluded because searches are limited to 20 terms to prevent excessive server load.',
+      err_query_has_stopwords: 'One or more of your search terms was excluded because either it was less than 2 characters in length or is a common word (a stopword) that is typically found on a large number of pages. Examples of stopwords include "the", "this", "which", "with", etc.',
+      err_query_dup_terms: 'One or more of your search terms was excluded because duplicate terms were encountered.',
+      err_query_term_too_short: 'One or more of your search terms was excluded because terms must be at least 4 characters in length.',
+      err_query_no_positive: 'You need to have at least one keyword in your search query. Searching only for pages not containing a term is not allowed.',
+      
+      btn_search: 'Search',
+      // note the case difference with th_advanced_search
+      btn_advanced_search: 'Advanced search',
+      
+      msg_no_results: 'No results.',
+      msg_result_detail: 'Results <b>%start_string%</b> - <b>%per_string%</b> of about <b>%num_results%</b> for <b>%q_trim%</b> in %search_time%s.',
+      body_no_results_title: 'Your search for <b>"%query%"</b> didn\'t turn up any results.',
+      body_no_results_body: '<p>There are a few things you can try:</p>
+                             <ul>
+                               <li>Were you looking for a specific Special page? Special pages are not searchable. You may want to see a <a href="%special_url%">list of special pages</a>.</li>
+                               <li>If you have the appropriate permissions, you can <a href="%create_url%">start the %query% page</a>.</li>
+                               <li>Try using fewer keywords. You can get broader results if you remove quotes from your search query.</li>
+                               <li>Did your search trigger any warnings? Sometimes a search can be cancelled if there aren\'t any terms in a search query that are 4 characters or greater in length.</li>
+                             </ul>',
+      
+      lbl_site_search: 'Site search',
+      lbl_relevance: 'Relevance:',
+      lbl_field_any: 'Search for pages with <b>any of these words</b>:',
+      lbl_field_exact: 'with <b>this exact phrase</b>:',
+      lbl_field_none: 'with <b>none of these words</b>:',
+      lbl_field_all: 'with <b>all of these words</b>:',
+      lbl_field_casesensitive: 'Case-sensitive search:',
+      
+      result_tag_special: 'Special page',
+    },
+    pagetools: {
+      
+      // Create a page
+      create_err_invalid_namespace: 'You have selected an invalid page type.',
+      create_err_invalid_urlname: 'Please enter a title for your page and a custom URL if desired.',
+      create_err_already_exists: 'A page with that URL already exists. Please enter another title or enter a custom URL. (You can have two pages with the same name, but not two pages with the same URL.)',
+      create_err_no_permission: 'You don\'t have permission to create this page. Try another URL or title; if that does not work, please contact the site administration for permission to create pages.',
+      create_err_nodb_namespace: 'You cannot create Special or Admin pages - they can\'t be stored in the database.',
+      create_err_reserved_prefix: 'The prefix "Project:" is reserved for internal links and can\'t be used on a page name.',
+      
+      create_blurb: 'Add a new page to the site.',
+      create_field_title: 'Page title:',
+      create_field_namespace: 'Page type:',
+      create_group_advanced: 'Advanced options',
+      create_field_url_auto: 'Generate a URL based on the title',
+      create_field_url_manual: 'Enter a custom page URL',
+      create_field_url: 'Page ID:',
+      create_field_preview: 'Preview of URL:',
+      create_field_preview_hint: '(Requires Javascript support)',
+      create_btn_create: 'Create page',
+      
+      // All pages
+      allpages_blurb: 'Below is a list of all of the pages on this website.',
+      
+      // Special pages
+      specialpages_blurb: 'Below is a list of all of the special pages on this website.',
+      
+      // GPL page
+      gpl_blurb: 'The following text represents the license that the <a href="%about_url%">Enano</a> content management system is under. To make it easier to read, the text has been wiki-formatted; in no other way has it been changed.',
+      // The following three strings will be used only in non-English languages. A Spanish example is provided here.
+      
+      // "Version in Spanish"
+      gpl_title_native: 'Versión en español',
+      // "Version in English"
+      gpl_title_english: 'Versión en inglés',
+      // "View the license in English"
+      gpl_link_to_english: 'Vea la licencia en inglés',
+      
+      gpl_err_file_missing: 'It appears that the file "GPL" is missing from your Enano installation. You may find a wiki-formatted copy of the GPL at: <a href="http://enanocms.org/GPL">http://enanocms.org/GPL</a>. In the mean time, you may wish to contact the site administration and ask them to replace the GPL file.',
+      
+      // Tag cloud
+      tagcloud_pagelist_th: 'Pages tagged "%tag%"',
+      tagcloud_blurb: 'Summary of page tagging',
+      tagcloud_msg_no_tags: 'No pages are tagged yet.',
+      tagcloud_btn_return: 'Return to tag cloud',
+      tagcloud_instructions: 'Hover your mouse over a tag to see how many pages have the tag. Click on a tag to see a list of the pages that have it.',
+      tagcloud_sidebar_title: 'Tag cloud',
+      tagcloud_sidebar_btn_larger: 'Larger version',
+      tagcloug_tip_popularity_one: '1 page',
+      tagcloug_tip_popularity_plural: '%popularity% pages',
+      
+      // Recent changes
+      rc_btn_diff: 'diff',
+      rc_btn_hist: 'hist',
+      rc_btn_pm: 'PM',
+      rc_btn_usertalk: 'comment',
+    },
+  }
+};
+
+// All done! :-)
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/language/english/user.json	Fri Feb 22 12:51:53 2008 -0500
@@ -0,0 +1,609 @@
+/*
+ * Enano - an open-source CMS capable of wiki functions, Drupal-like sidebar blocks, and everything in between
+ * Version 1.1.1
+ * Copyright (C) 2006-2007 Dan Fuhry
+ *
+ * This program is Free Software; you can redistribute and/or modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.
+ *
+ * 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.
+ */
+
+var enano_lang = {
+  categories: [
+    'meta', 'user', 'usercp', 'groupcp', 'privmsgs', 'userfuncs', 'userpage',
+  ],
+  strings: {
+    meta: {
+      user: 'Login, logout, and authentication',
+      usercp: 'User control panel',
+      groupcp: 'Group control panel',
+      privmsgs: 'Private message and buddy list CP',
+      userfuncs: 'User management pages',
+      userpage: 'User pages',
+    },
+    user: {
+      login_message_short: 'Please enter your username and password to log in.',
+      login_message_short_elev: 'Please re-enter your login details',
+      login_body: 'Logging in enables you to use your preferences and access member information. If you don\'t have a username and password here, you can <a href="%reg_link%">create an account</a>.',
+      login_body_elev: 'You are requesting that a sensitive operation be performed. To continue, please re-enter your password to confirm your identity.',
+      login_field_username: 'Username',
+      login_field_password: 'Password',
+      login_forgotpass_blurb: 'Forgot your password? <a href="%forgotpass_link%">No problem.</a>',
+      login_createaccount_blurb: 'Maybe you need to <a href="%reg_link%">create an account</a>.',
+      login_field_captcha: 'Code in image',
+      login_nocrypt_title: 'Important note regarding cryptography:',
+      login_nocrypt_body: 'Some countries do not allow the import or use of cryptographic technology. If you live in one of the countries listed below, you should <a href="%nocrypt_link%">log in without using encryption</a>.',
+      login_nocrypt_countrylist: 'This restriction applies to the following countries: Belarus, China, India, Israel, Kazakhstan, Mongolia, Pakistan, Russia, Saudi Arabia, Singapore, Tunisia, Venezuela, and Vietnam.',
+      login_usecrypt_title: 'Encryption is currently turned off.',
+      login_usecrypt_body: 'If you are not in one of the countries listed below, you should <a href="%usecrypt_link%">enable encryption</a> to secure the logon process.',
+      login_usecrypt_countrylist: 'The cryptography restriction applies to the following countries: Belarus, China, India, Israel, Kazakhstan, Mongolia, Pakistan, Russia, Saudi Arabia, Singapore, Tunisia, Venezuela, and Vietnam.',
+      login_success_title: 'Login successful',
+      login_success_body: 'You have successfully logged into the %config.site_name% site as "%username%". Redirecting to %redir_target%...',
+      login_success_body_mainpage: 'the main page',
+      login_success_short: 'Success.',
+      
+      login_noact_title: 'Account error',
+      login_noact_msg_intro: 'It appears that your user account has not yet been activated.',
+      login_noact_solution_none: 'Your account was most likely deactivated by an administrator. Please contact the site administration for further assistance.',
+      login_noact_solution_user: 'Please check your e-mail; you should have been sent a message with instructions on how to activate your account. If you do not receive an e-mail from this site within 24 hours, please contact the site administration for further assistance.',
+      login_noact_solution_admin: 'This website has been configured so that all user accounts must be activated by the administrator before they can be used, so your account will most likely be activated the next time an administrator visits the site.',
+      login_noact_msg_logout_success_title: 'Logged out',
+      login_noact_msg_logout_success_body: 'You have successfully been logged out. All cookies cleared.',
+      login_noact_msg_ask_admins: 'If you are having trouble or did not receive the e-mail, you can request account activation from the administrators of this site.',
+      login_noact_msg_admins_just_asked: 'A request has just been sent to the administrators of this site. They will be able to activate your account or send you another activation e-mail if needed.',
+      login_noact_msg_admins_asked: 'There is an active request in the administrators\' control panel for your account to be activated.',
+      login_noact_btn_request_activation: 'Request account activation',
+      login_noact_btn_log_out: 'Log out',
+      
+      login_ajax_fetching_key: 'Fetching an encryption key...',
+      login_ajax_generating_key: 'Performing Diffie-Hellman key generation...',
+      login_ajax_prompt_title: 'Please enter your username and password to continue.',
+      login_ajax_prompt_title_elev: 'You are requesting a sensitive operation.',
+      login_ajax_prompt_body_elev: 'Please re-enter your login details to verify your identity.',
+      login_ajax_link_fullform: 'Trouble logging in? Try the <a href="%link_full_form%">full login form</a>.',
+      login_ajax_link_fullform_dh: 'Don\'t stop this process even if your browser asks you to. If this takes more than 10 seconds, you might want to try the <a href="%link_full_form%">full login form</a>.',
+      login_ajax_link_forgotpass: 'Did you <a href="%forgotpass_link%">forget your password</a>?',
+      login_ajax_loggingin: 'Logging in...',
+      login_ajax_msg_used_temp_pass: 'You have logged in using a temporary password. Before you can log in, you must finish resetting your password. Do you want to reset your real password now?',
+      login_ajax_check_dh: 'Enable strong encryption during logon? <a href="http://docs.enanocms.org/Help:Appendix_B#dh" onclick="window.open(this.href); return false;">Learn more</a>',
+      
+      err_key_not_found: 'Enano couldn\'t look up the encryption key used to encrypt your password. This most often happens if a cache rotation occurred during your login attempt, or if you refreshed the login page.',
+      err_key_not_found_cleared: 'It seems that the list of encryption keys used for login information has reached its maximum length, thus preventing new keys from being inserted. The list has been automatically cleared. Please try logging in again; if you are still unable to log in, please contact the site administration.',
+      err_key_wrong_length: 'The encryption key was the wrong length.',
+      err_too_big_for_britches: 'You are trying to authenticate at a level that your user account does not permit.',
+      err_invalid_credentials: 'You have entered an invalid username or password. Please enter your login details again.',
+      err_invalid_credentials_lockout: ' You have used up %fails% out of %config.lockout_threshold% login attempts. After you have used up all %config.lockout_threshold% login attempts, you will be locked out from logging in for %config.lockout_duration% minutes.',
+      err_invalid_credentials_lockout_captcha: ' You have used up %fails% out of %config.lockout_threshold% login attempts. After you have used up all %config.lockout_threshold% login attempts, you will have to enter a visual confirmation code while logging in, effective for %config.lockout_duration% minutes.',
+      err_backend_fail: 'You entered the right credentials and everything was validated, but for some reason Enano couldn\'t register your session. This is an internal problem with the site and you are encouraged to contact site administration.',
+      err_locked_out: 'You have used up all %config.lockout_threshold% allowed login attempts. Please wait %time_rem% minute%plural% before attempting to log in again%captcha_blurb%.',
+      err_locked_out_captcha_blurb: ', or enter the visual confirmation code shown above in the appropriate box',
+      
+      logout_success_title: 'Logged out',
+      logout_success_body: 'You have been successfully logged out, and all cookies have been cleared. You will now be transferred to the main page.',
+      logout_confirm_title: 'Are you sure you want to log out?',
+      logout_confirm_body: 'If you log out, you will no longer be able to access your user preferences, your private messages, or certain areas of this site until you log in again.',
+      logout_confirm_title_elev: 'Are you sure you want to de-authenticate?',
+      logout_confirm_body_elev: 'If you de-authenticate, you will no longer be able to use the administration panel until you re-authenticate again. You may do so at any time using the Administration button on the sidebar.',
+      logout_err_title: 'An error occurred during the logout process.',
+      // Unused at this point
+      logout_err_not_loggedin: 'You don\'t seem to be logged in.',
+      
+      // User levels
+      level_short_guest: 'Guest',
+      level_short_member: 'Member',
+      level_short_chpref: 'Sensitive preferences changeable',
+      level_short_mod: 'Moderator',
+      level_short_admin: 'Administrative',
+      level_long_guest: 'Low - guest privileges',
+      level_long_member: 'Standard - normal member level',
+      level_long_chpref: 'Medium - user can change his/her own e-mail address and password',
+      level_long_mod: 'High - moderator privileges',
+      level_long_admin: 'Highest - administrative privileges',
+      
+      ban_msg_title: 'Ban notice',
+      ban_msg_body: 'You have been banned from this website. Please contact the site administrator for more information.',
+      ban_lbl_reason: 'Reason:',
+      
+      keepalive_info_title: 'About the keep-alive feature',
+      keepalive_info_body: 'Keep-alive is a new Enano feature that keeps your administrative session from timing out while you are using the administration panel. This feature can be useful if you are editing a large page or doing something in the administration interface that will take longer than 15 minutes.<br /><br />For security reasons, Enano mandates that high-privilege logins last only 15 minutes, with the time being reset each time a page is loaded (or, more specifically, each time the session API is started). The consequence of this is that if you are performing an action in the administration panel that takes more than 15 minutes, your session may be terminated. The keep-alive feature attempts to relieve this by sending a "ping" to the server every 10 minutes.<br /><br />Please note that keep-alive state is determined by a cookie. Thus, if you log out and then back in as a different administrator, keep-alive will use the same setting that was used when you were logged in as the first administrative user. In the same way, if you log into the administration panel under your account from another computer, keep-alive will be set to "off".<br /><br /><b>For more information:</b><br /><a href="http://docs.enanocms.org/Help:Appendix_B" onclick="window.open(this.href); return false;">Overview of Enano\'s security model</a>',
+      
+      type_guest: 'Guest',
+      type_member: 'Member',
+      type_mod: 'Moderator',
+      type_admin: 'Administrator',
+      
+      msg_elev_timed_out: '<b>Your administrative session has timed out.</b> <a href="%login_link%">Log in again</a>',
+      
+      reg_err_captcha: 'The confirmation code you entered was incorrect.',
+      reg_err_disabled_title: 'Registration disabled',
+      reg_err_disabled_body: 'The administrator has disabled the registration of new accounts on this site.',
+      reg_err_disabled_body_adminblurb: 'Oops...it seems that you <em>are</em> the administrator...hehe...you can also <a href="%reg_link%">force account registration to work</a>.',
+      reg_err_username_invalid: 'Your username must be at least two characters in length and may not contain any of the following characters: &lt; &gt; _ &amp; ? \' " % / \\.',
+      // Not exactly an error
+      reg_err_password_good: 'The password you entered is valid.',
+      reg_err_alert_password_tooshort: 'Your password must be 6 characters or greater in length.',
+      reg_err_alert_password_nomatch: 'The passwords you entered do not match.',
+      reg_err_missing_key: 'Couldn\'t look up public encryption key',
+      reg_err_accept_tou: 'Please read and accept the Terms of Use before creating your account.',
+      reg_err_username_banned_chars: 'The username you chose contains invalid characters.',
+      reg_err_dupe_username: 'The username you selected is already in use by another user.',
+      reg_err_dupe_username_email: 'The username and e-mail address you selected are already in use by another user.',
+      reg_err_dupe_username_email_realname: 'The username, e-mail address, and real name you selected are already in use by another user.',
+      reg_err_dupe_email: 'The e-mail address you selected is already in use by another user.',
+      reg_err_dupe_email_realname: 'The e-mail address and real name you selected are already in use by another user.',
+      reg_err_dupe_realname: 'The real name you selected is already in use by another user.',
+      reg_err_password_too_weak: 'The password you entered did not meet the complexity requirements for this site. Please choose a stronger password.',
+      reg_err_actmail_failed: 'The activation e-mail could not be sent due to an internal error. This could possibly be due to an incorrect SMTP configuration. A request has been sent to the administrator to activate your account for you.',
+      
+      reg_msg_greatercontrol: 'A user account enables you to have greater control over your browsing experience.',
+      reg_msg_table_title: 'Create a user account',
+      reg_msg_table_subtitle: 'Please tell us a little bit about yourself.',
+      reg_msg_username_checking: 'Checking availability...',
+      reg_msg_username_available: 'This username is available.',
+      reg_msg_username_unavailable: 'This username is already taken.',
+      reg_msg_password_length: 'Your password must be at least six characters in length.',
+      reg_msg_password_score: 'It needs to score at least <b>%config.pw_strength_minimum%</b> for your registration to be accepted.',
+      reg_msg_password_needmatch: 'The passwords you entered do not match.',
+      reg_msg_email_activuser: 'An e-mail with an account activation key will be sent to this address, so please ensure that it is correct.',
+      reg_msg_realname_optional: 'Giving your real name is totally optional. If you choose to provide your real name, it will be used to provide attribution for any edits or contributions you may make to this site.',
+      reg_msg_captcha_pleaseenter: 'Please enter the code shown in the image to the right into the text box. The code is case-insensitive and the numeral zero is never used. This process helps to ensure that this registration is not being performed by an automated bot. If the image to the right is illegible, you can <a %regen_flags%>generate a new image</a>.',
+      reg_msg_captcha_blind: 'If you are visually impaired or otherwise cannot read the text shown to the right, please contact the site management and they will create an account for you.',
+      reg_msg_please_read_tou:'Please read and agree to the following terms before registering. By continuing to create an account you agree to be legally bound by the terms below.',
+      reg_msg_success_title: 'Registration successful',
+      reg_msg_success_body: 'Thank you for registering, your user account has been created.',
+      reg_msg_success_activ_none: 'You may now <a href="%login_link%">log in</a> with the username and password that you created.',
+      reg_msg_success_activ_user: 'Because this site requires account activation, you have been sent an e-mail with further instructions. Please follow the instructions in that e-mail to continue your registration.',
+      reg_msg_success_activ_admin: 'Because this site requires administrative account activation, you cannot use your account at the moment. A notice has been sent to the site administration team that will alert them that your account has been created.',
+      reg_msg_success_activ_coppa: 'However, in compliance with the Childrens\' Online Privacy Protection Act, you must have your parent or legal guardian activate your account. Please ask them to check their e-mail for further information.',
+      
+      reg_lbl_field_username: 'Preferred username:',
+      reg_lbl_field_password: 'Password:',
+      reg_lbl_field_password_confirm: 'Enter your password again to confirm.',
+      reg_lbl_field_email: 'E-mail address:',
+      reg_lbl_field_email_coppa: 'Your parent or guardian\'s e-mail address:',
+      reg_lbl_field_realname: 'Real name:',
+      reg_lbl_field_captcha: 'Visual confirmation',
+      reg_lbl_field_captcha_code: 'Code:',
+      reg_lbl_field_tou: 'I agree to abide by the terms and conditions stated above',
+      
+      reg_btn_create_account: 'Create my account',
+      
+      reg_coppa_title: 'Before you can register, please tell us your age.',
+      reg_coppa_link_atleast13: 'I was born <b>on or before</b> %yo13_date% and am <b>at least</b> 13 years of age',
+      reg_coppa_link_not13: 'I was born <b>after</b> %yo13_date% and am <b>less than</b> 13 years of age',
+      
+      reg_activation_email_subject: '%config.site_name% website account activation',
+      reg_activation_email: 'Dear %username%,
+Thank you for registering on %config.site_name%. Your account creation is almost complete. To complete the registration process, please click the following link or paste it into your web browser:
+
+  %activation_link%
+  
+Sincerely yours,
+%admin_user% and the %config.site_name% administration team',
+
+      reg_activation_email_coppa: 'Dear parent or legal guardian,
+A child under the username %username% recently registered on our website. The child provided your e-mail address as the one of his or her authorized parent or legal guardian, and to comply with the United States Childrens\' Online Privacy Protection act, we ask that all parents of children ages 13 or under please mail us a written form authorizing their child\'s use of our website.
+
+If you wish for your child to be allowed access to our website, please print and fill out the form below, and mail it to this address:
+
+%config.coppa_address%
+
+If you do NOT wish for your child to be allowed access to our site, you do not need to do anything - your child will not be able to access our site as a registered user unless you authorize their account activation.
+
+Authorization form:
+-------------------------------- Cut here --------------------------------
+
+I, _______________________________________, the legal parent or guardian of the child registered on the website "%config.site_name%" as %username%, hereby give my authorization for the child\'s e-mail address, instant messaging information, location, and real name, to be collected and stored in a database owned and maintained by %config.site_name% at the child\'s option, and for the administrators of this website to use this information according to the privacy policy displayed on their website <%site_link%>.
+
+Child\'s name:               _____________________________________
+
+Child\'s e-mail address:     _____________________________________
+(optional - if you don\'t provide this, we\'ll just send site-related e-mails to your e-mail address)
+
+Signature of parent or guardian:
+
+____________________________________________________
+
+Date (YYYY-MM-DD): ______ / _____ / _____
+
+-------------------------------- Cut here --------------------------------
+
+Sincerely yours,
+%admin_user% and the %config.site_name% administration team',
+      
+      autofill_heading_suggestions: 'Username suggestions',
+      autofill_msg_no_suggestions: 'No suggestions',
+    },
+    usercp: {
+      // Meta
+      sec_profile: 'Profile/membership',
+      sec_pm: 'Private messages',
+      
+      sec_profile_emailpassword: 'Edit e-mail address and password',
+      sec_profile_signature: 'Edit signature',
+      sec_profile_publicinfo: 'Edit public profile',
+      sec_profile_usergroups: 'Group memberships',
+      sec_profile_avatar: 'Avatar settings',
+      
+      sec_pm_inbox: 'Inbox',
+      sec_pm_outbox: 'Outbox',
+      sec_pm_sent: 'Sent items',
+      sec_pm_drafts: 'Drafts',
+      sec_pm_archive: 'Archive',
+      
+      btn_memberlist: 'list of registered members',
+      
+      // CP home
+      intro_heading_main: '%username%, welcome to your control panel',
+      intro_para1: 'Here you can make changes to your profile, view statistics on yourself on this site, and set your preferences.',
+      intro_para2: 'Your <a href="%userpage_link%">user page</a> <sup>(<a href="%userpage_link%#do:comments">comments</a>)</sup> is your free writing space. You can use it to tell the other members of this site a little bit about yourself. If you haven\'t already made a user page, why not <a href="%userpage_link%#do:edit">make one now</a>?',
+      intro_para3: 'Use the menu at the top to navigate around. If you have any questions, you may contact the %admin_contact_link%.',
+      intro_para3_admin_link: 'administrator',
+      
+      // E-mail / password change form
+      emailpassword_title: 'Change E-mail Address or Password',
+      emailpassword_err_email_no_match: 'The e-mail addresses you entered did not match.',
+      emailpassword_err_list: 'The following errors were encountered while saving your e-mail address:',
+      emailpassword_err_title: 'Error updating e-mail address',
+      emailpassword_err_demo: 'You can\'t change your password in demo mode.',
+      emailpassword_err_password_too_short: 'The new password must be 6 characters or greater in length.',
+      emailpassword_err_password_too_weak: 'Your password did not meet the complexity score requirement for this site. Your password scored %score%, while a score of at least %config.pw_strength_minimum% is needed.',
+      emailpassword_msg_profile_success: 'Profile changed',
+      emailpassword_msg_pass_success: 'Password changed',
+      emailpassword_msg_need_activ_user: 'Your password and e-mail address have been changed. Since e-mail activation is required on this site, you will need to re-activate your account to continue. An e-mail has been sent to the new e-mail address with an activation link. You must click that link in order to log in again.',
+      emailpassword_msg_need_activ_admin: 'Your password and e-mail address have been changed. Since administrative activation is requires on this site, a request has been sent to the administrators to activate your account for you. You will not be able to use your account until it is activated by an administrator.',
+      emailpassword_msg_password_changed: 'Your password has been changed, and you will now be redirected back to the user control panel.',
+      emailpassword_err_password_no_match: 'The passwords you entered do not match.',
+      emailpassword_grp_chpasswd: 'Change password',
+      emailpassword_field_newpass: 'Type a new password:',
+      emailpassword_field_newpass_confirm: 'Type the password again to confirm:',
+      emailpassword_msg_password_min_score: 'Your password needs to score at least <b>%config.pw_strength_minimum%</b> in order to be accepted.',
+      // The following is NOT an in-joke. ;-)
+      emailpassword_grp_chemail: 'Change e-mail address',
+      emailpassword_field_newemail: 'New e-mail address:',
+      emailpassword_field_newemail_confirm: 'Confirm e-mail address:',
+      
+      // Signature editor
+      signature_title: 'Editing signature',
+      signature_msg_saved: 'Your signature has been saved.',
+      signature_btn_save: 'Save signature',
+      
+      // Additional profile info
+      publicinfo_title: 'Editing public profile',
+      publicinfo_msg_save_success: 'Your profile has been updated.',
+      publicinfo_heading_main: 'Your public profile',
+      publicinfo_note_optional: 'Please note that all of the information you enter here will be <b>publicly viewable.</b> All of the fields on this page are optional and may be left blank if you so desire.',
+      publicinfo_field_realname: 'Real name:',
+      publicinfo_field_language: 'Preferred language:',
+      publicinfo_field_language_hint: 'Select the language special pages and page controls should appear in.',
+      publicinfo_field_changetheme_title: 'Change theme:',
+      publicinfo_field_changetheme_hint: 'If you don\'t like the look of the site, need a visual break, or are just curious, we might have some different themes for you to try out!',
+      publicinfo_field_changetheme: 'Change my theme...',
+      publicinfo_field_timezone: 'Time zone:',
+      publicinfo_field_timezone_hint: 'Select the time zone you live in and when Daylight Savings Time occurs, if at all.',
+      publicinfo_th_im: 'Instant messenger contact information',
+      publicinfo_field_aim: 'AIM handle:',
+      publicinfo_field_wlm: '<acronym title="Windows&trade; Live Messenger">WLM</acronym> handle:<br /><small>If you don\'t specify the domain (@whatever.com), "@hotmail.com" will be assumed.</small>',
+      publicinfo_field_yim: 'Yahoo! IM handle:',
+      publicinfo_field_xmpp: 'Jabber&trade;/XMPP handle:',
+      publicinfo_th_contact: 'Extra contact information',
+      publicinfo_field_homepage: 'Your homepage:<br /><small>Please remember the http:// prefix.</small>',
+      publicinfo_field_location: 'Your location:',
+      publicinfo_field_job: 'Your job:',
+      publicinfo_field_hobbies: 'Your hobbies:',
+      publicinfo_field_email_public: 'E-mail address is public',
+      publicinfo_field_email_public_hint: 'If this is checked, your e-mail address will be displayed on your user page. To protect your address from spambots, your e-mail address will be encrypted.',
+      publicinfo_btn_save: 'Save profile',
+      
+      // Avatar management
+      avatar_err_disabled_title: 'Avatar support is disabled.',
+      avatar_err_disabled_body: 'The administrator has not enabled avatar support for this site.',
+      avatar_table_title: 'Avatar settings',
+      avatar_label_current: 'Current avatar:',
+      avatar_image_alt: '%username%\'s avatar',
+      avatar_image_none: 'You don\'t have an avatar currently.',
+      avatar_lbl_change: 'Change your avatar:',
+      avatar_lbl_keep: 'Keep my current avatar',
+      avatar_lbl_remove: 'Delete my avatar',
+      avatar_lbl_set_http: 'Upload a new avatar from the Web',
+      avatar_lbl_set_file: 'Upload a new avatar from my computer',
+      avatar_lbl_url: 'URL to image:',
+      avatar_lbl_url_desc: 'This must start with the <tt>http://</tt> prefix and must be a valid URL. The image will be copied from the existing URL to this server - dynamic avatars are not supported.',
+      avatar_lbl_file: 'Upload file:',
+      avatar_lbl_file_desc: 'Your browser needs to support file uploads for this option to work.',
+      avatar_limits: 'The image cannot be more than %config.avatar_max_size% bytes in size. The maximum dimensions are %config.avatar_max_width% &#215; %config.avatar_max_height% pixels. Allowed formats are PNG, GIF, and JPEG.',
+      avatar_delete_success: 'Your avatar has been deleted.',
+      avatar_bad_write: 'Either the remote server had trouble finding the image, or your image exceeded the allowed file size.',
+      avatar_bad_filetype: 'The file you selected is invalid. You must choose a file in PNG, JPEG, or GIF format.',
+      avatar_disallowed_animation: 'You have chosen an animated image, which is not allowed. Please choose a non-animated image.',
+      avatar_corrupt_image: 'The image you selected is corrupt. Please choose another image.',
+      avatar_too_large: 'The image you uploaded exceeds the maximum dimensions (%config.avatar_max_width% &#215; %config.avatar_max_height%px) allowed on this site. Please choose another image.',
+      avatar_move_failed: 'Your image was accepted, but there was a problem moving the image file to the correct location.',
+      avatar_upload_success: 'Your avatar has been updated.',
+      avatar_file_too_large: 'The image you uploaded exceeds the maximum file size allowed for avatars on this site.',
+      
+      // Password strength widget
+      pwstrength_score_verystrong: 'Very strong (score: %score%)',
+      pwstrength_score_strong: 'Strong (score: %score%)',
+      pwstrength_score_good: 'Good (score: %score%)',
+      pwstrength_score_fair: 'Fair (score: %score%)',
+      pwstrength_score_weak: 'Weak (score: %score%)',
+    },
+    groupcp: {
+      status_mod: 'You are a moderator of this group.',
+      status_member: 'You are a member of this group.',
+      status_not_member: 'You are not a member of this group.',
+      
+      err_state_system_group: 'Because this is a system group, you can\'t make it open or allow membership requests.',
+      err_user_not_found: 'The username you entered could not be found.',
+      
+      type_hidden: 'Hidden group',
+      type_closed: 'Closed group',
+      type_request: 'Members can request to join',
+      type_open: 'Anyone can join',
+      
+      lbl_current_memberships: 'Current group memberships:',
+      lbl_non_memberships: 'Groups you are outside of:',
+      lbl_group_name: 'Group name:',
+      lbl_status: 'Membership status:',
+      lbl_state: 'Group state:',
+      lbl_make_mod: 'User is a group moderator',
+      lbl_username: 'Username:',
+      lbl_moderator: 'Group moderator:',
+      
+      msg_membership_requested: 'A request has been sent to the moderator(s) of this group to add you.',
+      msg_status_pending: '(Your request to join is awaiting approval)',
+      msg_no_mods: 'This group has no moderators.',
+      msg_no_members: 'This group has no members.',
+      msg_system_group: '(system group)',
+      msg_pending_updated: 'Pending members status updated successfully.',
+      msg_state_updated: 'The group state was updated.',
+      msg_user_already_in_mod_updated: 'The user "%username%" is already in this group, so their moderator status was updated.',
+      msg_user_already_in: 'The user "%username%" is already in this group.',
+      msg_user_added: 'The user "%username%" has been added to this usergroup.',
+      msg_self_added: 'You have been added to this group.',
+      
+      btn_view: 'View information',
+      btn_request_join: 'Request membership',
+      btn_join: 'Join this group',
+      btn_approve_pending: 'Approve membership',
+      btn_reject_pending: 'Reject membership',
+      btn_remove_selected: 'Remove selected users',
+      btn_add_member: 'Add member',
+      
+      grp_administrators: 'Administrators',
+      grp_moderators: 'Moderators',
+      
+      th_select_group: 'Group membership details',
+      th_group_info: 'Group information',
+      th_pending_memberships: 'Pending memberships',
+      th_group_members: 'Group members',
+      th_group_mods: 'Group moderators',
+      th_add_member: 'Add a new member to this group',
+      th_username: 'Username',
+      th_email: 'E-mail',
+      th_reg_time: 'Registered',
+      th_comments: 'Total comments',
+      th_select: 'Select',
+      th_remove: 'Remove?',
+    },
+    privmsgs: {
+      err_need_login: 'You need to be <a href="%login_link%">logged in</a> to view private messages.',
+      err_not_authorized_read: 'You are not authorized to view this message.',
+      err_not_authorized_edit: 'You are not authorized to alter this message.',
+      err_send_submit: 'Your message could not be sent because the following problems were encountered:',
+      err_need_username: 'Please enter the username to which you want to send your message.',
+      err_need_subject: 'Please enter a subject for your message.',
+      err_need_message: 'Please enter a message to send.',
+      err_limit_exceeded_title: 'Recipient limit exceeded',
+      err_limit_exceeded_body: 'You can only send this message to a maximum of %limit% users.',
+      err_folder_not_exist: 'The folder "%folder_name%" does not exist. Return to your <a href="%inbox_url%">inbox</a>.',
+      
+      msg_message_status: 'Message status',
+      msg_message_moved: 'Your message has been moved to the folder "%folder%".',
+      msg_message_deleted: 'The message has been deleted.',
+      msg_message_sent: 'Your message has been sent. You may edit the message if you wish; one copy for each recipient will be in your outbox until each recipient has read it. Return to your <a href="%inbox_link%">inbox</a>.',
+      msg_draft_saved: 'Your message has been saved to your Drafts folder.',
+      msg_no_messages: 'No messages in this folder.',
+      
+      lbl_message_from: 'Private message from %sender%',
+      lbl_subject: 'Subject:',
+      lbl_date: 'Date:',
+      lbl_message: 'Message:',
+      lbl_compose_th: 'Compose new private message',
+      lbl_compose_to: 'To:',
+      lbl_compose_to_max: 'Separate multiple names with a single comma; you may send this message to up to <b>%limit%</b> users.',
+      lbl_edit_th: 'Edit draft',
+      
+      btn_send_reply: 'Send reply',
+      btn_archive: 'Archive message',
+      btn_return_to_inbox: 'Return to inbox',
+      btn_send: 'Send message',
+      btn_savedraft: 'Save as draft',
+      btn_archive_selected: 'Archive selected',
+      btn_delete_selected: 'Delete selected',
+      btn_delete_all: 'Delete all',
+      btn_compose: 'New message',
+      
+      sidebar_th_privmsgs: 'Private messages',
+      folder_inbox: 'Inbox',
+      folder_outbox: 'Outbox',
+      folder_sent: 'Sent items',
+      folder_drafts: 'Drafts',
+      folder_archive: 'Archive',
+      sidebar_th_buddies: 'Buddies',
+      sidebar_friend_list: 'Friend list',
+      sidebar_foe_list: 'Foe list',
+      
+      folder_th_foldername: 'Folder:',
+      folder_th_to: 'To',
+      folder_th_from: 'From',
+      folder_th_subject: 'Subject',
+      folder_th_date: 'Date',
+      folder_th_mark: 'Mark',
+      
+      // Buddy / foe lists
+      th_buddy_list: 'Buddy list for %username%',
+      msg_no_buddies: 'No buddies in your list.',
+      btn_pm_all_buddies: 'Send a PM to all buddies',
+      heading_add_buddy: 'Add a new friend',
+      btn_add: 'Add',
+      lbl_username: 'Username:',
+      btn_buddy_remove: 'Remove',
+      btn_buddy_send_pm: 'Send private message',
+      
+      th_foe_list: 'Foe list for %username%',
+      msg_no_foes: 'No foes in your list.',
+      heading_add_foe: 'Add a new foe',
+      
+      // AJAX interface (up and coming)
+      ajax_err_need_js: 'It looks like your browser doesn\'t have support for Javascript. You\'ll need to have Javascript support in order to use the new Private Message interface. You can also switch to the <a href="%basic_link%">old interface</a>, which doesn\'t require Javascript support.',
+      ajax_err_json: 'The server had a problem processing your request.',
+      
+      ajax_btn_compose: 'Compose message',
+      ajax_btn_archive: 'Archive',
+      ajax_btn_unarchive: 'Restore to inbox',
+      ajax_btn_mark_read: 'Mark as read',
+      ajax_btn_mark_unread: 'Mark as unread',
+      ajax_btn_delete: 'Move to trash',
+      ajax_btn_delete_forever: 'Delete forever',
+      ajax_btn_refresh: 'Refresh',
+      ajax_btn_reply: 'Reply',
+      
+      ajax_folder_inbox: 'Inbox',
+      ajax_folder_starred: 'Starred',
+      ajax_folder_sent: 'Sent messages',
+      ajax_folder_drafts: 'Drafts',
+      ajax_folder_archive: 'Archive',
+      ajax_folder_trash: 'Trash',
+      
+      ajax_msg_loading: 'Loading...',
+      
+      ajax_lbl_sender: '%sender% to %recipient%',
+      ajax_me: 'me',
+      
+      ajax_teaser_inbox: 'No new mail.',
+      ajax_teaser_starred: 'You haven\'t starred any messages yet. Starring a message lets you give it a special status that separates it from the rest of your mail so it\'s easier to find. You can star a message by clicking the small gray star next to a message in your inbox or archive.',
+      ajax_teaser_sent: 'You haven\'t sent any messages yet. When you send a message, a copy of it will appear here.',
+      
+      ajax_no_subject: '[No subject]',
+    },
+    userfuncs: {
+      
+      // Special:Contributions
+      contribs_err_no_user: 'You need to select a user to view contributions for.',
+      contribs_heading_edits: 'Page edits',
+      contribs_msg_no_edits: 'This user has not made any edits.',
+      contribs_heading_other: 'Other changes made by this user',
+      contribs_msg_no_other: 'This user has not made any non-editing changes.',
+      
+      // Special:ChangeStyle
+      changetheme_heading_theme: 'Please select a new theme:',
+      changetheme_heading_style: 'Please select a stylesheet:',
+      changetheme_btn_continue: 'Continue',
+      changetheme_btn_allclear: 'Change style',
+      changetheme_success_title: 'Theme changed',
+      changetheme_success_body: 'Your theme preferences have been updated. Redirecting you to the last viewed page...',
+      
+      // Special:ActivateAccount
+      activate_err_badlink_title: 'Account activation error',
+      activate_err_badlink_body: 'This page can only be accessed using links sent to users via e-mail.',
+      activate_err_bad_key: 'The activation key was probably incorrect, or the account is already active.',
+      activate_success_title: 'Activation successful',
+      activate_success_body: 'Your account is now active. Thank you for registering.',
+      
+      // Special:PasswordReset
+      passreset_blurb_line1: 'Don\'t worry, it happens to the best of us.',
+      passreset_blurb_line2: 'To reset your password, just enter your username below, and a new password will be e-mailed to you.',
+      passreset_lbl_username: 'Username:',
+      passreset_btn_mailpasswd: 'Mail new password',
+      passreset_email: "Dear %username%,
+    
+Someone (hopefully you) on the %site_name% website requested that a new password be created.
+
+The request was sent from the IP address %remote_addr%.
+
+If you did not request the new password, then you do not need to do anything; the password will be invalidated after 24 hours.
+
+If you did request this password, then please log in using the password shown below:
+
+  Password: %temp_pass%
+  
+After you log in using this password, you will be able to reset your real password. You can only log in using this temporary password once.
+
+Sincerely yours,
+The %site_name% administration team
+",
+      passreset_stage1_success: 'An e-mail has been sent to the e-mail address on file for your username with a new password in it. Please check your e-mail for further instructions.',
+      passreset_stage1_error: 'Error occured, your new password was not sent.',
+      passreset_stage2_th: 'Reset password',
+      passreset_stage2_lbl_password: 'Password:',
+      passreset_stage2_lbl_confirm: 'Confirm:',
+      passreset_stage2_lbl_strength: 'Password strength rating:',
+      passreset_stage2_blurb_strength: 'Your password needs to have a score of at least <b>%config.pw_strength_minimum%</b>.',
+      passreset_stage2_btn_submit: 'Reset password',
+      passreset_stage2_success: 'Your password has been reset. Return to the <a href="%url_mainpage%">main page</a>.',
+      
+      passreset_err_no_match: 'The passwords you entered do not match.',
+      passreset_err_too_short: 'The new password must be 6 characters or greater in length.',
+      passreset_err_failed_score: 'ERROR: Your password did not pass the complexity score requirement. You need %config.pw_strength_minimum% points to pass; your password received a score of %inp_score%. <a href="%url%">Go back</a>',
+      passreset_err_pass_expired: 'Your temporary password has expired. Please <a href="%reset_url%">request another one</a>.',
+      
+      // Special:Memberlist
+      ml_column_username: 'Username',
+      ml_column_userlevel: 'Title',
+      ml_column_email: 'E-mail',
+      ml_column_regtime: 'Registered',
+      ml_level_guest: 'Guest',
+      ml_level_member: 'Member',
+      ml_level_mod: 'Moderator',
+      ml_level_admin: 'Site administrator',
+      ml_level_unknown: 'Unknown (level %level%)',
+      ml_email_nonpublic: 'Non-public',
+      ml_date_daysago: '%days_ago% days ago',
+      ml_date_today: 'Today',
+      ml_date_yesterday: 'Yesterday',
+      ml_btn_adminuser: 'Administer user',
+      ml_tip_userpage: 'Click to view this user\'s userpage',
+      ml_tip_nouserpage: 'This user hasn\'t created a userpage yet, but you can still view profile details by clicking this link.',
+      ml_lbl_finduser: 'Find a member:',
+      ml_btn_go: 'Go',
+      ml_tip_wildcard: 'You may use the following wildcards: * to match multiple characters, ? to match a single character.',
+      ml_err_nousers_find: 'Sorry - no users that matched your query could be found. Please try some different search terms.',
+      ml_err_nousers: 'Sorry - no users with usernames that start with that letter could be found.',
+      ml_msg_matches_zero: 'Search returned no matches',
+      ml_msg_matches_one: 'Search returned 1 match',
+      ml_msg_matches: 'Search returned %matches% matches',
+    },
+    userpage: {
+      page_title: '%username%\'s user page',
+      heading_basics: 'All about %username%',
+      lbl_joined: 'Joined:',
+      lbl_num_comments: 'Total comments:',
+      lbl_real_name: 'Real name:',
+      btn_administer_user: 'Administer user',
+      heading_comments: '%username%\'s latest comments',
+      comments_lbl_posted: 'Posted',
+      msg_no_comments: 'This user has not posted any comments.',
+      heading_contact: 'Get in touch',
+      lbl_email: 'E-mail address:',
+      btn_send_pm: 'Send %username% a <a href="%pm_link%">Private Message!</a>',
+      btn_send_pm_guest: 'You could send %username% a Private Message if you were <a %login_flags%>logged in</a>.',
+      lbl_aim: 'AIM:',
+      lbl_yim: 'Yahoo! IM:',
+      lbl_wlm: 'WLM:',
+      lbl_xmpp: 'XMPP/Jabber&trade;:',
+      heading_real_life: '%username% in real life',
+      lbl_location: 'Location:',
+      lbl_job: 'Job/occupation:',
+      lbl_hobbies: 'Enjoys:',
+      msg_no_contact_info: '%username% hasn\'t posted any real-life contact information.',
+      msg_user_not_exist: 'Additional information: user "%username%" does not exist.',
+    }
+  }
+};
+
+// All done! :-)
+
--- a/licenses/index.html	Fri Feb 22 12:46:51 2008 -0500
+++ b/licenses/index.html	Fri Feb 22 12:51:53 2008 -0500
@@ -106,12 +106,13 @@
 <ul>
   <li><a href="http://pajhome.org.uk/">Paul Johnston</a>'s implementations of the MD5 and SHA1 algorithms in Javascript</li>
   <li><a href="http://labs.adobe.com/technologies/spry/">Adobe Spry</a>, used for some Javascript effects</li>
+  <li><a href="http://framework.zend.com/">Zend Framework</a>, for the majority of JSON operations</li>
 </ul>
 
 <h2>The MIT/X License</h2>
 <p><a href="mitlic.html">View the text of this license</a></p>
 <ul>
-  <li><a href="http://www.3site.it/">FastJSON</a> - a JSON encoder/decoder. Copyright &copy; 2006 - 2007 Andrea Giammarchi.</li>
+  <li><a href="http://www.3site.it/">FastJSON</a> - a JSON encoder/decoder. Only used when PHP4 compatibility is a must (early in the installer). Copyright &copy; 2006 - 2007 Andrea Giammarchi.</li>
 </ul>
 
 <h2>Unknown license</h2>
--- a/plugins/PrivateMessages.php	Fri Feb 22 12:46:51 2008 -0500
+++ b/plugins/PrivateMessages.php	Fri Feb 22 12:51:53 2008 -0500
@@ -1,16 +1,16 @@
 <?php
 /*
-Plugin Name: Private Message frontend
+Plugin Name: plugin_privatemessages_title
 Plugin URI: http://enanocms.org/
-Description: Provides the page Special:PrivateMessages, which is used to manage private message functions. Also handles buddy lists.
+Description: plugin_privatemessages_desc
 Author: Dan Fuhry
-Version: 1.0.3
+Version: 1.1.1
 Author URI: http://enanocms.org/
 */
 
 /*
  * Enano - an open-source CMS capable of wiki functions, Drupal-like sidebar blocks, and everything in between
- * Version 1.0.3
+ * Version 1.1.2 (Caoineag alpha 2)
  * Copyright (C) 2006-2007 Dan Fuhry
  *
  * This program is Free Software; you can redistribute and/or modify it under the terms of the GNU General Public License
@@ -22,10 +22,10 @@
  
 global $db, $session, $paths, $template, $plugins; // Common objects
 
-$plugins->attachHook('base_classes_initted', '
+$plugins->attachHook('session_started', '
   global $paths;
     $paths->add_page(Array(
-      \'name\'=>\'Private Messages\',
+      \'name\'=>\'specialpage_private_messages\',
       \'urlname\'=>\'PrivateMessages\',
       \'namespace\'=>\'Special\',
       \'special\'=>0,\'visible\'=>1,\'comments_on\'=>0,\'protected\'=>1,\'delvotes\'=>0,\'delvote_ips\'=>\'\',
@@ -35,12 +35,19 @@
 function page_Special_PrivateMessages()
 {
   global $db, $session, $paths, $template, $plugins; // Common objects
-  if(!$session->user_logged_in) die_friendly('Access denied', '<p>You need to <a href="'.makeUrlNS('Special', 'Login/'.$paths->page).'">log in</a> to view your private messages.</p>');
+  global $lang;
+  if ( !$session->user_logged_in )
+  {
+    die_friendly($lang->get('etc_access_denied_short'), '<p>' . $lang->get('privmsgs_err_need_login', array('login_link' => makeUrlNS('Special', 'Login/' . $paths->page))) . '</p>');
+  }
   $argv = Array();
   $argv[] = $paths->getParam(0);
   $argv[] = $paths->getParam(1);
   $argv[] = $paths->getParam(2);
-  if(!$argv[0]) $argv[0] = 'InVaLiD';
+  if ( !$argv[0] )
+  {
+    $argv[0] = 'InVaLiD';
+  }
   switch($argv[0])
   {
     default:
@@ -48,112 +55,195 @@
       break;
     case 'View':
       $id = $argv[1];
-      if(!preg_match('#^([0-9]+)$#', $id)) die_friendly('Message error', '<p>Invalid message ID</p>');
+      if ( !preg_match('#^([0-9]+)$#', $id) )
+      {
+        die_friendly('Message error', '<p>Invalid message ID</p>');
+      }
       $q = $db->sql_query('SELECT p.message_from, p.message_to, p.subject, p.message_text, p.date, p.folder_name, u.signature FROM '.table_prefix.'privmsgs AS p LEFT JOIN '.table_prefix.'users AS u ON (p.message_from=u.username) WHERE message_id='.$id.'');
-      if(!$q) $db->_die('The message data could not be selected.');
+      if ( !$q )
+      {
+        $db->_die('The message data could not be selected.');
+      }
       $r = $db->fetchrow();
       $db->free_result();
-      if( ($r['message_to'] != $session->username && $r['message_from'] != $session->username ) || $r['folder_name']=='drafts' ) die_friendly('Access denied', '<p>You are not authorized to view this message.</p>');
-      if($r['message_to'] == $session->username)
+      if ( ($r['message_to'] != $session->username && $r['message_from'] != $session->username ) || $r['folder_name']=='drafts' )
+      {
+        die_friendly($lang->get('etc_access_denied_short'), '<p>' . $lang->get('privmsgs_err_not_authorized_read') . '</p>');
+      }
+      if ( $r['message_to'] == $session->username )
       {
         $q = $db->sql_query('UPDATE '.table_prefix.'privmsgs SET message_read=1 WHERE message_id='.$id.'');
         $db->free_result();
-        if(!$q) $db->_die('Could not mark message as read');
+        if ( !$q )
+        {
+          $db->_die('Could not mark message as read');
+        }
       }
       $template->header();
       userprefs_show_menu();
       ?>
         <br />
         <div class="tblholder"><table border="0" width="100%" cellspacing="1" cellpadding="4">
-          <tr><th colspan="2">Private message from <?php echo $r['message_from']; ?></th></tr>
-          <tr><td class="row1">Subject:</td><td class="row1"><?php echo $r['subject']; ?></td></tr>
-          <tr><td class="row2">Date:</td><td class="row2"><?php echo date('M j, Y G:i', $r['date']); ?></td></tr>
-          <tr><td class="row1">Message:</td><td class="row1"><?php echo RenderMan::render($r['message_text']);
-          if($r['signature'] != '')
+          <tr><th colspan="2"><?php echo $lang->get('privmsgs_lbl_message_from', array('sender' => htmlspecialchars($r['message_from']))); ?></th></tr>
+          <tr><td class="row1"><?php echo $lang->get('privmsgs_lbl_subject') ?></td><td class="row1"><?php echo $r['subject']; ?></td></tr>
+          <tr><td class="row2"><?php echo $lang->get('privmsgs_lbl_date') ?></td><td class="row2"><?php echo enano_date('M j, Y G:i', $r['date']); ?></td></tr>
+          <tr><td class="row1"><?php echo $lang->get('privmsgs_lbl_message') ?></td><td class="row1"><?php echo RenderMan::render($r['message_text']);
+          if ( $r['signature'] != '' )
           {
             echo '<hr style="margin-left: 1em; width: 200px;" />';
             echo RenderMan::render($r['signature']);
           }
           ?></td></tr>
-          <tr><td colspan="2" class="row3"><a href="<?php echo makeUrlNS('Special', 'PrivateMessages/Compose/ReplyTo/'.$id); ?>">Send reply</a>  |  <a href="<?php echo makeUrlNS('Special', 'PrivateMessages/Delete/'.$id); ?>">Delete message</a>  |  <?php if($r['folder_name'] != 'archive') { ?><a href="<?php echo makeUrlNS('Special', 'PrivateMessages/Move/'.$id.'/Archive'); ?>">Archive message</a>  |  <?php } ?><a href="<?php echo makeUrlNS('Special', 'PrivateMessages/Folder/Inbox') ?>">Return to inbox</a></td></tr>
+          <tr><td colspan="2" class="row3"><a href="<?php echo makeUrlNS('Special', 'PrivateMessages/Compose/ReplyTo/'.$id); ?>"><?php echo $lang->get('privmsgs_btn_send_reply'); ?></a>  |  <a href="<?php echo makeUrlNS('Special', 'PrivateMessages/Delete/'.$id); ?>">Delete message</a>  |  <?php if($r['folder_name'] != 'archive') { ?><a href="<?php echo makeUrlNS('Special', 'PrivateMessages/Move/'.$id.'/Archive'); ?>"><?php echo $lang->get('privmsgs_btn_archive'); ?></a>  |  <?php } ?><a href="<?php echo makeUrlNS('Special', 'PrivateMessages/Folder/Inbox') ?>"><?php echo $lang->get('privmsgs_btn_return_to_inbox'); ?></a></td></tr>
         </table></div>
       <?php
       $template->footer();              
       break;
     case 'Move':
       $id = $argv[1];
-      if(!preg_match('#^([0-9]+)$#', $id)) die_friendly('Message error', '<p>Invalid message ID</p>');
+      if ( !preg_match('#^([0-9]+)$#', $id) )
+      {
+        die_friendly('Message error', '<p>Invalid message ID</p>');
+      }
       $q = $db->sql_query('SELECT message_to FROM '.table_prefix.'privmsgs WHERE message_id='.$id.'');
-      if(!$q) $db->_die('The message data could not be selected.');
+      if ( !$q )
+      {
+        $db->_die('The message data could not be selected.');
+      }
       $r = $db->fetchrow();
       $db->free_result();
-      if($r['message_to'] != $session->username) die_friendly('Access denied', '<p>You are not authorized to alter this message.</p>');
+      if ( $r['message_to'] != $session->username )
+      {
+        die_friendly($lang->get('etc_access_denied_short'), '<p>' . $lang->get('privmsgs_err_not_authorized_edit') . '</p>');
+      }
       $fname = $argv[2];
-      if(!$fname || ( $fname != 'Inbox' && $fname != 'Outbox' && $fname != 'Sent' && $fname != 'Drafts' && $fname != 'Archive' ) ) die_friendly('Invalid request', '<p>The folder name "'.$fname.'" is invalid.</p>');
+      if ( !$fname || ( $fname != 'Inbox' && $fname != 'Outbox' && $fname != 'Sent' && $fname != 'Drafts' && $fname != 'Archive' ) )
+      {
+        die_friendly('Invalid request', '<p>The folder name "'.$fname.'" is invalid.</p>');
+      }
       $q = $db->sql_query('UPDATE '.table_prefix.'privmsgs SET folder_name=\''.strtolower($fname).'\' WHERE message_id='.$id.';');
       $db->free_result();
-      if(!$q) $db->_die('The message was not successfully moved.');
-      die_friendly('Message status', '<p>Your message has been moved to the folder "'.$fname.'".</p><p><a href="'.makeUrlNS('Special', 'PrivateMessages/Folder/Inbox').'">Return to inbox</a></p>');
+      if ( !$q )
+      {
+        $db->_die('The message was not successfully moved.');
+      }
+      die_friendly($lang->get('privmsgs_msg_message_status'), '<p>' . $lang->get('privmsgs_msg_message_moved', array('folder' => $fname)) . '</p><p><a href="'.makeUrlNS('Special', 'PrivateMessages/Folder/Inbox').'">' . $lang->get('privmsgs_btn_return_to_inbox') . '</a></p>');
       break;
     case 'Delete':
       $id = $argv[1];
-      if(!preg_match('#^([0-9]+)$#', $id)) die_friendly('Message error', '<p>Invalid message ID</p>');
+      if ( !preg_match('#^([0-9]+)$#', $id) )
+      {
+        die_friendly('Message error', '<p>Invalid message ID</p>');
+      }
       $q = $db->sql_query('SELECT message_to FROM '.table_prefix.'privmsgs WHERE message_id='.$id.'');
-      if(!$q) $db->_die('The message data could not be selected.');
+      if ( !$q )
+      {
+        $db->_die('The message data could not be selected.');
+      }
       $r = $db->fetchrow();
-      if($r['message_to'] != $session->username) die_friendly('Access denied', '<p>You are not authorized to delete this message.</p>');
+      if ( $r['message_to'] != $session->username )
+      {
+        die_friendly($lang->get('etc_access_denied_short'), '<p>You are not authorized to delete this message.</p>');
+      }
       $q = $db->sql_query('DELETE FROM '.table_prefix.'privmsgs WHERE message_id='.$id.';');
-      if(!$q) $db->_die('The message was not successfully deleted.');
+      if ( !$q )
+      {
+        $db->_die('The message was not successfully deleted.');
+      }
       $db->free_result();
-      die_friendly('Message status', '<p>The message has been deleted.</p><p><a href="'.makeUrlNS('Special', 'PrivateMessages/Folder/Inbox').'">Return to inbox</a></p>');
+      die_friendly($lang->get('privmsgs_msg_message_status'), '<p>' . $lang->get('privmsgs_msg_message_deleted') . '</p><p><a href="'.makeUrlNS('Special', 'PrivateMessages/Folder/Inbox').'">' . $lang->get('privmsgs_btn_return_to_inbox') . '</a></p>');
       break;
     case 'Compose':
-      if($argv[1]=='Send' && isset($_POST['_send']))
+      if ( $argv[1]=='Send' && isset($_POST['_send']) )
       {
         // Check each POST DATA parameter...
-        if(!isset($_POST['to']) || ( isset($_POST['to']) && $_POST['to'] == '')) die_friendly('Sending of message failed', '<p>Please enter the username to which you want to send your message.</p>');
-        if(!isset($_POST['subject']) || ( isset($_POST['subject']) && $_POST['subject'] == '')) die_friendly('Sending of message failed', '<p>Please enter a subject for your message.</p>');
-        if(!isset($_POST['message']) || ( isset($_POST['message']) && $_POST['message'] == '')) die_friendly('Sending of message failed', '<p>Please enter a message to send.</p>');
-        $namelist = $_POST['to'];
-        $namelist = str_replace(', ', ',', $namelist);
-        $namelist = explode(',', $namelist);
-        foreach($namelist as $n) { $n = $db->escape($n); }
-        $subject = RenderMan::preprocess_text($_POST['subject']);
-        $message = RenderMan::preprocess_text($_POST['message']);
-        $base_query = 'INSERT INTO '.table_prefix.'privmsgs(message_from,message_to,date,subject,message_text,folder_name,message_read) VALUES';
-        foreach($namelist as $n)
+        $errors = array();
+        if(!isset($_POST['to']) || ( isset($_POST['to']) && $_POST['to'] == ''))
+        {
+          $errors[] = $lang->get('privmsgs_err_need_username');
+        }
+        if(!isset($_POST['subject']) || ( isset($_POST['subject']) && $_POST['subject'] == ''))
+        {
+          $errors[] = $lang->get('privmsgs_err_need_subject');
+        }
+        if(!isset($_POST['message']) || ( isset($_POST['message']) && $_POST['message'] == ''))
+        {
+          $errors[] = $lang->get('privmsgs_err_need_message');
+        }
+        if ( count($errors) < 1 )
         {
-          $base_query .= '(\''.$session->username.'\', \''.$n.'\', '.time().', \''.$subject.'\', \''.$message.'\', \'inbox\', 0),';
+          $namelist = $_POST['to'];
+          $namelist = str_replace(', ', ',', $namelist);
+          $namelist = explode(',', $namelist);
+          foreach($namelist as $n) { $n = $db->escape($n); }
+          $subject = RenderMan::preprocess_text($_POST['subject']);
+          $message = RenderMan::preprocess_text($_POST['message']);
+          $base_query = 'INSERT INTO '.table_prefix.'privmsgs(message_from,message_to,date,subject,message_text,folder_name,message_read) VALUES';
+          foreach($namelist as $n)
+          {
+            $base_query .= '(\''.$session->username.'\', \''.$n.'\', '.time().', \''.$subject.'\', \''.$message.'\', \'inbox\', 0),';
+          }
+          $base_query = substr($base_query, 0, strlen($base_query)-1) . ';';
+          $result = $db->sql_query($base_query);
+          $db->free_result();
+          if ( !$result )
+          {
+            $db->_die('The message could not be sent.');
+          }
+          else
+          {
+            die_friendly($lang->get('privmsgs_msg_message_status'), '<p>' . $lang->get('privmsgs_msg_message_sent', array('inbox_link' => makeUrlNS('Special', 'PrivateMessages/Folder/Inbox'))) . '</p>');
+          }
+          return;
         }
-        $base_query = substr($base_query, 0, strlen($base_query)-1) . ';';
-        $result = $db->sql_query($base_query);
-        $db->free_result();
-        if(!$result) $db->_die('The message could not be sent.');
-        else die_friendly('Message status', '<p>Your message has been sent. You may edit the message if you wish; one copy for each recipient will be in your outbox until each recipient has read it. Return to your <a href="'.makeUrlNS('Special', 'PrivateMessages/Folder/Inbox').'">inbox</a>.</p>');
-        return;
-      } elseif($argv[1]=='Send' && isset($_POST['_savedraft'])) {
-        // Check each POST DATA parameter...
-        if(!isset($_POST['to']) || ( isset($_POST['to']) && $_POST['to'] == '')) die_friendly('Sending of message failed', '<p>Please enter the username to which you want to send your message.</p>');
-        if(!isset($_POST['subject']) || ( isset($_POST['subject']) && $_POST['subject'] == '')) die_friendly('Sending of message failed', '<p>Please enter a subject for your message.</p>');
-        if(!isset($_POST['message']) || ( isset($_POST['message']) && $_POST['message'] == '')) die_friendly('Sending of message failed', '<p>Please enter a message to send.</p>');
-        $namelist = $_POST['to'];
-        $namelist = str_replace(', ', ',', $namelist);
-        $namelist = explode(',', $namelist);
-        foreach($namelist as $n) { $n = $db->escape($n); }
-        if(count($namelist) > MAX_PMS_PER_BATCH && $session->get_permssions('mod_misc')) die_friendly('Limit exceeded', '<p>You can only send this message to a maximum of '.MAX_PMS_PER_BATCH.' users.</p>');
-        $subject = $db->escape($_POST['subject']);
-        $message = RenderMan::preprocess_text($_POST['message']);
-        $base_query = 'INSERT INTO '.table_prefix.'privmsgs(message_from,message_to,date,subject,message_text,folder_name,message_read) VALUES';
-        foreach($namelist as $n)
+      }
+      else if ( $argv[1] == 'Send' && isset($_POST['_savedraft'] ) )
+      {
+        $errors = array();
+        if ( !isset($_POST['to']) || ( isset($_POST['to']) && $_POST['to'] == '') )
+        {
+          $errors[] = $lang->get('privmsgs_err_need_username');
+        }
+        if ( !isset($_POST['subject']) || ( isset($_POST['subject']) && $_POST['subject'] == '') )
+        {
+          $errors[] = $lang->get('privmsgs_err_need_subject');
+        }
+        if ( !isset($_POST['message']) || ( isset($_POST['message']) && $_POST['message'] == '') )
+        {
+          $errors[] = $lang->get('privmsgs_err_need_message');
+        }
+        if ( count($errors) < 1 )
         {
-          $base_query .= '(\''.$session->username.'\', \''.$n.'\', '.time().', \''.$subject.'\', \''.$message.'\', \'drafts\', 0),';
+          $namelist = $_POST['to'];
+          $namelist = str_replace(', ', ',', $namelist);
+          $namelist = explode(',', $namelist);
+          foreach($namelist as $n)
+          {
+            $n = $db->escape($n);
+          }
+          if ( count($namelist) > MAX_PMS_PER_BATCH && !$session->get_permssions('mod_misc') )
+          {
+            die_friendly($lang->get('privmsgs_err_limit_exceeded_title'), '<p>' . $lang->get('privmsgs_err_limit_exceeded_body', array('limit' => MAX_PMS_PER_BATCH)) . '</p>');
+          }
+          $subject = $db->escape($_POST['subject']);
+          $message = RenderMan::preprocess_text($_POST['message']);
+          $base_query = 'INSERT INTO '.table_prefix.'privmsgs(message_from,message_to,date,subject,message_text,folder_name,message_read) VALUES';
+          foreach($namelist as $n)
+          {
+            $base_query .= '(\''.$session->username.'\', \''.$n.'\', '.time().', \''.$subject.'\', \''.$message.'\', \'drafts\', 0),';
+          }
+          $base_query = substr($base_query, 0, strlen($base_query) - 1) . ';';
+          $result = $db->sql_query($base_query);
+          $db->free_result();
+          if ( !$result )
+          {
+            $db->_die('The message could not be saved.');
+          }
         }
-        $base_query = substr($base_query, 0, strlen($base_query)-1) . ';';
-        $result = $db->sql_query($base_query);
-        $db->free_result();
-        if(!$result) $db->_die('The message could not be saved.');
-      } elseif(isset($_POST['_inbox'])) {
-        header('Location: '.makeUrlNS('Special', 'PrivateMessages/Folder/Inbox'));
+      }
+      else if(isset($_POST['_inbox']))
+      {
+        redirect(makeUrlNS('Special', 'PrivateMessages/Folder/Inbox'), '', '', 0);
       }
       if($argv[1] == 'ReplyTo' && preg_match('#^([0-9]+)$#', $argv[2]))
       {
@@ -162,12 +252,17 @@
         $subj = '';
         $id = $argv[2];
         $q = $db->sql_query('SELECT p.message_from, p.message_to, p.subject, p.message_text, p.date, p.folder_name, u.signature FROM '.table_prefix.'privmsgs AS p LEFT JOIN '.table_prefix.'users AS u ON (p.message_from=u.username) WHERE message_id='.$id.';');
-        if(!$q) $db->_die('The message data could not be selected.');
+        if ( !$q )
+          $db->_die('The message data could not be selected.');
+        
         $r = $db->fetchrow();
         $db->free_result();
-        if( ($r['message_to'] != $session->username && $r['message_from'] != $session->username ) || $r['folder_name']=='drafts' ) die_friendly('Access denied', '<p>You are not authorized to view the contents of this message.</p>');
+        if ( ($r['message_to'] != $session->username && $r['message_from'] != $session->username ) || $r['folder_name'] == 'drafts' )
+        {
+          die_friendly($lang->get('etc_access_denied_short'), '<p>You are not authorized to view the contents of this message.</p>');
+        }
         $subj = 'Re: ' . $r['subject'];
-        $text = "\n\n\nOn ".date('M j, Y G:i', $r['date']).", ".$r['message_from']." wrote:\n> ".str_replace("\n", "\n> ", $r['message_text']); // Way less complicated than using a regex ;-)
+        $text = "\n\n\nOn " . enano_date('M j, Y G:i', $r['date']) . ", " . $r['message_from'] . " wrote:\n> " . str_replace("\n", "\n> ", $r['message_text']); // Way less complicated than using a regex ;-)
         
         $tbuf = $text;
         while( preg_match("/\n([\> ]*?)\> \>/", $text) )
@@ -179,23 +274,85 @@
         }
         
         $to = $r['message_from'];
-      } else {
-        if(( $argv[1]=='to' || $argv[1]=='To' ) && $argv[2]) $to = $argv[2];
-        else $to = '';
+      }
+      else
+      {
+        if ( ( $argv[1]=='to' || $argv[1]=='To' ) && $argv[2] )
+        {
+          $to = htmlspecialchars($argv[2]);
+        }
+        else
+        {
+          $to = '';
+        }
         $text = '';
         $subj = '';
       }
         $template->header();
         userprefs_show_menu();
-        echo '<form action="'.makeUrlNS('Special', 'PrivateMessages/Compose/Send').'" method="post" onsubmit="if(!submitAuthorized) return false;">';
+        if ( isset($errors) && count($errors) > 0 )
+        {
+          echo '<div class="warning-box">
+                  ' . $lang->get('privmsgs_err_send_submit') . '
+                  <ul>
+                    <li>' . implode('</li><li>', $errors) . '</li>
+                  </ul>
+                </div>';
+        }
+        echo '<form action="'.makeUrlNS('Special', 'PrivateMessages/Compose/Send').'" method="post">';
+        
+        if ( isset($_POST['_savedraft']) )
+        {
+          echo '<div class="info-box">' . $lang->get('privmsgs_msg_draft_saved') . '</div>';
+        }
         ?>
         <br />
         <div class="tblholder"><table border="0" width="100%" cellspacing="1" cellpadding="4">
-          <tr><th colspan="2">Compose new private message</th></tr>
-          <tr><td class="row1">To:<br /><small>Separate multiple names with a single comma; you<br />can send this message to up to <b><?php echo (string)MAX_PMS_PER_BATCH; ?></b> users.</small></td><td class="row1"><?php echo $template->username_field('to', (isset($_POST['_savedraft'])) ? $_POST['to'] : $to ); ?></td></tr>
-          <tr><td class="row2">Subject:</td><td class="row2"><input name="subject" type="text" size="30" value="<?php if(isset($_POST['_savedraft'])) echo $_POST['subject']; else echo $subj; ?>" /></td></tr>
-          <tr><td class="row1">Message:</td><td class="row1" style="min-width: 80%;"><textarea rows="20" cols="40" name="message" style="width: 100%;"><?php if(isset($_POST['_savedraft'])) echo $_POST['message']; else echo $text; ?></textarea></td></tr>
-          <tr><th colspan="2"><input type="submit" name="_send" value="Send message" />  <input type="submit" name="_savedraft" value="Save as draft" /> <input type="submit" name="_inbox" value="Back to Inbox" /></th></tr>
+          <tr>
+            <th colspan="2"><?php echo $lang->get('privmsgs_lbl_compose_th'); ?></th>
+          </tr>
+          <tr>
+            <td class="row1">
+              <?php echo $lang->get('privmsgs_lbl_compose_to'); ?><br />
+              <small><?php echo $lang->get('privmsgs_lbl_compose_to_max', array('limit' => MAX_PMS_PER_BATCH)); ?></small>
+            </td>
+            <td class="row1">
+              <?php echo $template->username_field('to', (isset($_POST['_savedraft'])) ? $_POST['to'] : $to ); ?>
+            </td>
+          </tr>
+          <tr>
+            <td class="row2">
+              <?php echo $lang->get('privmsgs_lbl_subject'); ?>
+            </td>
+            <td class="row2">
+              <input name="subject" type="text" size="30" value="<?php if(isset($_POST['_savedraft'])) echo htmlspecialchars($_POST['subject']); else echo $subj; ?>" />
+            </td>
+          </tr>
+          <tr>
+            <td class="row1">
+              <?php echo $lang->get('privmsgs_lbl_message'); ?>
+            </td>
+            <td class="row1" style="min-width: 80%;">
+              <?php
+                if ( isset($_POST['_savedraft']) )
+                {
+                  $content = htmlspecialchars($_POST['message']);
+                }
+                else
+                {
+                  $content =& $text;
+                }
+                echo $template->tinymce_textarea('message', $content, 20, 40);
+              ?>
+            </td>
+          </tr>
+          <tr>
+            <th class="subhead" colspan="2">
+              <input type="submit" name="_send" value="<?php echo $lang->get('privmsgs_btn_send'); ?>" />
+              <input type="submit" name="_savedraft" value="<?php echo $lang->get('privmsgs_btn_savedraft'); ?>" />
+              <input type="submit" name="_inbox" value="<?php echo $lang->get('privmsgs_btn_return_to_inbox'); ?>" />
+            </th>
+          </tr>
         </table></div>
         <?php
         echo '</form>';
@@ -203,61 +360,162 @@
       break;
     case 'Edit':
       $id = $argv[1];
-      if(!preg_match('#^([0-9]+)$#', $id)) die_friendly('Message error', '<p>Invalid message ID</p>');
+      if ( !preg_match('#^([0-9]+)$#', $id) )
+      {
+        die_friendly('Message error', '<p>Invalid message ID</p>');
+      }
       $q = $db->sql_query('SELECT message_from, message_to, subject, message_text, date, folder_name, message_read FROM '.table_prefix.'privmsgs WHERE message_id='.$id.'');
-      if(!$q) $db->_die('The message data could not be selected.');
+      if ( !$q )
+      {
+        $db->_die('The message data could not be selected.');
+      }
       $r = $db->fetchrow();
       $db->free_result();
-      if($r['message_from'] != $session->username || $r['message_read'] == 1 ) die_friendly('Access denied', '<p>You are not authorized to edit this message.</p>');
+      if ( $r['message_from'] != $session->username || $r['message_read'] == 1 )
+      {
+        die_friendly($lang->get('etc_access_denied_short'), '<p>You are not authorized to edit this message.</p>');
+      }
       $fname = $argv[2];
       
       if(isset($_POST['_send']))
       {
         // Check each POST DATA parameter...
-        if(!isset($_POST['to']) || ( isset($_POST['to']) && $_POST['to'] == '')) die_friendly('Sending of message failed', '<p>Please enter the username to which you want to send your message.</p>');
-        if(!isset($_POST['subject']) || ( isset($_POST['subject']) && $_POST['subject'] == '')) die_friendly('Sending of message failed', '<p>Please enter a subject for your message.</p>');
-        if(!isset($_POST['message']) || ( isset($_POST['message']) && $_POST['message'] == '')) die_friendly('Sending of message failed', '<p>Please enter a message to send.</p>');
-        $namelist = $_POST['to'];
-        $namelist = str_replace(', ', ',', $namelist);
-        $namelist = explode(',', $namelist);
-        foreach($namelist as $n) { $n = $db->escape($n); }
-        $subject = RenderMan::preprocess_text($_POST['subject']);
-        $message = RenderMan::preprocess_text($_POST['message']);
-        $base_query = 'UPDATE '.table_prefix.'privmsgs SET subject=\''.$subject.'\',message_to=\''.$namelist[0].'\',message_text=\''.$message.'\',folder_name=\'inbox\' WHERE message_id='.$id.';';
-        $result = $db->sql_query($base_query);
-        $db->free_result();
-        if(!$result) $db->_die('The message could not be sent.');
-        else die_friendly('Message status', '<p>Your message has been sent. You may edit the message if you wish; one copy for each recipient will be in your outbox until each recipient has read it. Return to your <a href="'.makeUrlNS('Special', 'PrivateMessages/Folder/Inbox').'">inbox</a>.</p>');
-        return;
-      } elseif(isset($_POST['_savedraft'])) {
+        $errors = array();
+        if(!isset($_POST['to']) || ( isset($_POST['to']) && $_POST['to'] == ''))
+        {
+          $errors[] = $lang->get('privmsgs_err_need_username');
+        }
+        if(!isset($_POST['subject']) || ( isset($_POST['subject']) && $_POST['subject'] == ''))
+        {
+          $errors[] = $lang->get('privmsgs_err_need_subject');
+        }
+        if(!isset($_POST['message']) || ( isset($_POST['message']) && $_POST['message'] == ''))
+        {
+          $errors[] = $lang->get('privmsgs_err_need_message');
+        }
+        if ( count($errors) < 1 )
+        {
+          $namelist = $_POST['to'];
+          $namelist = str_replace(', ', ',', $namelist);
+          $namelist = explode(',', $namelist);
+          foreach ($namelist as $n)
+          {
+            $n = $db->escape($n);
+          }
+          $subject = RenderMan::preprocess_text($_POST['subject']);
+          $message = RenderMan::preprocess_text($_POST['message']);
+          $base_query = 'UPDATE '.table_prefix.'privmsgs SET subject=\''.$subject.'\',message_to=\''.$namelist[0].'\',message_text=\''.$message.'\',folder_name=\'inbox\' WHERE message_id='.$id.';';
+          $result = $db->sql_query($base_query);
+          $db->free_result();
+          if ( !$result )
+          {
+            $db->_die('The message could not be sent.');
+          }
+          else
+          {
+            die_friendly($lang->get('privmsgs_msg_message_status'), '<p>' . $lang->get('privmsgs_msg_message_sent', array('inbox_link' => makeUrlNS('Special', 'PrivateMessages/Folder/Inbox'))) . '</p>');
+          }
+          return;
+        }
+      }
+      else if ( isset($_POST['_savedraft']) )
+      {
         // Check each POST DATA parameter...
-        if(!isset($_POST['to']) || ( isset($_POST['to']) && $_POST['to'] == '')) die_friendly('Sending of message failed', '<p>Please enter the username to which you want to send your message.</p>');
-        if(!isset($_POST['subject']) || ( isset($_POST['subject']) && $_POST['subject'] == '')) die_friendly('Sending of message failed', '<p>Please enter a subject for your message.</p>');
-        if(!isset($_POST['message']) || ( isset($_POST['message']) && $_POST['message'] == '')) die_friendly('Sending of message failed', '<p>Please enter a message to send.</p>');
-        $namelist = $_POST['to'];
-        $namelist = str_replace(', ', ',', $namelist);
-        $namelist = explode(',', $namelist);
-        foreach($namelist as $n) { $n = $db->escape($n); }
-        $subject = $db->escape($_POST['subject']);
-        $message = RenderMan::preprocess_text($_POST['message']);
-        $base_query = 'UPDATE '.table_prefix.'privmsgs SET subject=\''.$subject.'\',message_to=\''.$namelist[0].'\',message_text=\''.$message.'\' WHERE message_id='.$id.';';
-        $result = $db->sql_query($base_query);
-        $db->free_result();
-        if(!$result) $db->_die('The message could not be saved.');
+        $errors = array();
+        if(!isset($_POST['to']) || ( isset($_POST['to']) && $_POST['to'] == ''))
+        {
+          $errors[] = $lang->get('privmsgs_err_need_username');
+        }
+        if(!isset($_POST['subject']) || ( isset($_POST['subject']) && $_POST['subject'] == ''))
+        {
+          $errors[] = $lang->get('privmsgs_err_need_subject');
+        }
+        if(!isset($_POST['message']) || ( isset($_POST['message']) && $_POST['message'] == ''))
+        {
+          $errors[] = $lang->get('privmsgs_err_need_message');
+        }
+        if ( count($errors) < 1 )
+        {
+          $namelist = $_POST['to'];
+          $namelist = str_replace(', ', ',', $namelist);
+          $namelist = explode(',', $namelist);
+          foreach ( $namelist as $n )
+          {
+            $n = $db->escape($n);
+          }
+          $subject = $db->escape($_POST['subject']);
+          $message = RenderMan::preprocess_text($_POST['message']);
+          $base_query = 'UPDATE '.table_prefix.'privmsgs SET subject=\''.$subject.'\',message_to=\''.$namelist[0].'\',message_text=\''.$message.'\' WHERE message_id='.$id.';';
+          $result = $db->sql_query($base_query);
+          $db->free_result();
+          if ( !$result )
+          {
+            $db->_die('The message could not be saved.');
+          }
+        }
       }
-        if($argv[1]=='to' && $argv[2]) $to = $argv[2];
-        else $to = '';
+        if ( $argv[1]=='to' && $argv[2] )
+        {
+          $to = htmlspecialchars($argv[2]);
+        }
+        else
+        {
+          $to = '';
+        }
         $template->header();
         userprefs_show_menu();
         echo '<form action="'.makeUrlNS('Special', 'PrivateMessages/Edit/'.$id).'" method="post">';
+        
+        if ( isset($_POST['_savedraft']) )
+        {
+          echo '<div class="info-box">' . $lang->get('privmsgs_msg_draft_saved') . '</div>';
+        }
         ?>
         <br />
         <div class="tblholder"><table border="0" width="100%" cellspacing="1" cellpadding="4">
-          <tr><th colspan="2">Edit draft</th></tr>
-          <tr><td class="row1">To:<br /><small>Separate multiple names with a single comma</small></td><td class="row1"><input name="to" type="text" size="30" value="<?php if(isset($_POST['_savedraft'])) echo $_POST['to']; else echo $r['message_to']; ?>" /></td></tr>
-          <tr><td class="row2">Subject:</td><td class="row2"><input name="subject" type="text" size="30" value="<?php if(isset($_POST['_savedraft'])) echo $_POST['subject']; else echo $r['subject']; ?>" /></td></tr>
-          <tr><td class="row1">Message:</td><td class="row1"><textarea rows="20" cols="40" name="message" style="width: 100%;"><?php if(isset($_POST['_savedraft'])) echo $_POST['message']; else echo $r['message_text']; ?></textarea></td></tr>
-          <tr><th colspan="2"><input type="submit" name="_send" value="Send message" />  <input type="submit" name="_savedraft" value="Save as draft" /></th></tr>
+          <tr><th colspan="2"><?php echo $lang->get('privmsgs_lbl_edit_th'); ?></th></tr>
+          <tr>
+            <td class="row1">
+              <?php echo $lang->get('privmsgs_lbl_compose_to'); ?><br />
+              <small><?php echo $lang->get('privmsgs_lbl_compose_to_max', array('limit' => MAX_PMS_PER_BATCH)); ?></small>
+            </td>
+            <td class="row1">
+              <?php echo $template->username_field('to', (isset($_POST['_savedraft'])) ? $_POST['to'] : $r['message_to'] ); ?>
+            </td>
+          </tr>
+          <tr>
+            <td class="row2">
+              <?php echo $lang->get('privmsgs_lbl_subject'); ?>
+            </td>
+            <td class="row2">
+              <input name="subject" type="text" size="30" value="<?php if(isset($_POST['_savedraft'])) echo htmlspecialchars($_POST['subject']); else echo $r['subject']; ?>" />
+            </td>
+          </tr>
+          <tr>
+            <td class="row1">
+              <?php echo $lang->get('privmsgs_lbl_message'); ?>
+            </td>
+            <td class="row1" style="min-width: 80%;">
+              <?php
+                if ( isset($_POST['_savedraft']) )
+                {
+                  $content = htmlspecialchars($_POST['message']);
+                }
+                else
+                {
+                  $content =& $r['message_text'];
+                }
+                echo $template->tinymce_textarea('message', $content, 20, 40);
+              ?>
+            </td>
+          </tr>
+          
+          <tr>
+            <th class="subhead" colspan="2">
+              <input type="submit" name="_send" value="<?php echo $lang->get('privmsgs_btn_send'); ?>" />
+              <input type="submit" name="_savedraft" value="<?php echo $lang->get('privmsgs_btn_savedraft'); ?>" />
+            </th>
+          </tr>
         </table></div>
         <?php
         echo '</form>';
@@ -269,7 +527,10 @@
       switch($argv[1])
       {
         default:
-          echo '<p>The folder "'.$argv[1].'" does not exist. Return to your <a href="'.makeUrlNS('Special', 'PrivateMessages/Folder/Inbox').'">inbox</a>.</p>';
+          echo '<p>' . $lang->get('privmsgs_err_folder_not_exist', array(
+              'folder_name' => htmlspecialchars($argv[1]),
+              'inbox_url' => makeUrlNS('Special', 'PrivateMessages/Folder/Inbox')
+            )) . '</p>';
           break;
         case 'Inbox':
         case 'Outbox':
@@ -281,15 +542,15 @@
           <tr>
           <td style="padding: 0px; width: 120px;" valign="top"  >
           <div class="tblholder" style="width: 120px;"><table border="0" width="120" cellspacing="1" cellpadding="4">
-          <tr><th><small>Private messages</small></th></tr>
-          <tr><td class="row1"><small><a href="<?php echo $session->append_sid('Inbox'); ?>">Inbox</a>    </small></td></tr>
-          <tr><td class="row2"><small><a href="<?php echo $session->append_sid('Outbox'); ?>">Outbox</a>  </small></td></tr>
-          <tr><td class="row1"><small><a href="<?php echo $session->append_sid('Sent'); ?>">Sent Items</a></small></td></tr>
-          <tr><td class="row2"><small><a href="<?php echo $session->append_sid('Drafts'); ?>">Drafts</a>  </small></td></tr>
-          <tr><td class="row1"><small><a href="<?php echo $session->append_sid('Archive'); ?>">Archive</a></small></td></tr>
-          <tr><th><small>Buddies</small></th></tr>
-          <tr><td class="row2"><small><a href="<?php echo makeUrlNS('Special', 'PrivateMessages/FriendList'); ?>">Friend list</a></small></td></tr>
-          <tr><td class="row1"><small><a href="<?php echo makeUrlNS('Special', 'PrivateMessages/FoeList'); ?>">Foe list</a></small></td></tr>
+          <tr><th><small><?php echo $lang->get('privmsgs_sidebar_th_privmsgs'); ?></small></th></tr>
+          <tr><td class="row1"><small><a href="<?php echo makeUrlNS('Special', 'PrivateMessages/Folder/Inbox'); ?>"><?php echo $lang->get('privmsgs_folder_inbox'); ?></a></small></td></tr>
+          <tr><td class="row2"><small><a href="<?php echo makeUrlNS('Special', 'PrivateMessages/Folder/Outbox'); ?>"><?php echo $lang->get('privmsgs_folder_outbox'); ?></a></small></td></tr>
+          <tr><td class="row1"><small><a href="<?php echo makeUrlNS('Special', 'PrivateMessages/Folder/Sent'); ?>"><?php echo $lang->get('privmsgs_folder_sent'); ?></a></small></td></tr>
+          <tr><td class="row2"><small><a href="<?php echo makeUrlNS('Special', 'PrivateMessages/Folder/Drafts'); ?>"><?php echo $lang->get('privmsgs_folder_drafts'); ?></a></small></td></tr>
+          <tr><td class="row1"><small><a href="<?php echo makeUrlNS('Special', 'PrivateMessages/Folder/Archive'); ?>"><?php echo $lang->get('privmsgs_folder_archive'); ?></a></small></td></tr>
+          <tr><th><small><?php echo $lang->get('privmsgs_sidebar_th_buddies'); ?></small></th></tr>
+          <tr><td class="row2"><small><a href="<?php echo makeUrlNS('Special', 'PrivateMessages/FriendList'); ?>"><?php echo $lang->get('privmsgs_sidebar_friend_list'); ?></a></small></td></tr>
+          <tr><td class="row1"><small><a href="<?php echo makeUrlNS('Special', 'PrivateMessages/FoeList'); ?>"><?php echo $lang->get('privmsgs_sidebar_foe_list'); ?></a></small></td></tr>
           </table></div>
           </td>
           <td valign="top">
@@ -312,36 +573,88 @@
               $q = $db->sql_query('SELECT p.message_id, p.message_from, p.message_to, p.date, p.subject, p.message_read FROM '.table_prefix.'privmsgs AS p WHERE p.folder_name=\''.$fname.'\' AND p.message_from=\''.$session->username.'\' ORDER BY date DESC;');
               break;
           }
-          if($argv[1] == 'Drafts' || $argv[1] == 'Outbox') $act = 'Edit';
-          else $act = 'View';
-          if(!$q) $db->_die('The private message data could not be selected.');
-          echo '<form action="'.makeUrlNS('Special', 'PrivateMessages/PostHandler').'" method="post"><div class="tblholder"><table border="0" width="100%" cellspacing="1" cellpadding="4"><tr><th colspan="4" style="text-align: left;">Folder: '.$argv[1].'</th></tr><tr><th class="subhead">';
-          if($fname == 'drafts' || $fname == 'Outbox') echo 'To'; else echo 'From';
-          echo '</th><th class="subhead">Subject</th><th class="subhead">Date</th><th class="subhead">Mark</th></tr>';
+          if ( !$q )
+          {
+            $db->_die('The private message data could not be selected.');
+          }
+          if ( $argv[1] == 'Drafts' || $argv[1] == 'Outbox' )
+          {
+            $act = 'Edit';
+          }
+          else
+          {
+            $act = 'View';
+          }
+          echo '<form action="'.makeUrlNS('Special', 'PrivateMessages/PostHandler').'" method="post">
+                  <div class="tblholder">
+                    <table border="0" width="100%" cellspacing="1" cellpadding="4">
+                      <tr>
+                        <th colspan="4" style="text-align: left;">' . $lang->get('privmsgs_folder_th_foldername') . ' ' . $lang->get('privmsgs_folder_' . strtolower($argv[1])) . '</th>
+                      </tr>
+                    <tr>
+                      <th class="subhead">';
+          if ( $fname == 'drafts' || $fname == 'Outbox' )
+          {
+            echo $lang->get('privmsgs_folder_th_to');
+          }
+          else
+          {
+            echo $lang->get('privmsgs_folder_th_from');
+          }
+          echo '</th>
+                <th class="subhead">' . $lang->get('privmsgs_folder_th_subject') . '</th>
+                <th class="subhead">' . $lang->get('privmsgs_folder_th_date') . '</th>
+                <th class="subhead">' . $lang->get('privmsgs_folder_th_mark') . '</th>
+              </tr>';
           if($db->numrows() < 1)
-            echo '<tr><td style="text-align: center;" class="row1" colspan="4">No messages in this folder.</td></tr>';
-          else {
+          {
+            echo '<tr><td style="text-align: center;" class="row1" colspan="4">' . $lang->get('privmsgs_msg_no_messages') . '</td></tr>';
+          }
+          else
+          {
             $cls = 'row2';
-            while($r = $db->fetchrow())
+            while ( $r = $db->fetchrow() )
             {
               if($cls == 'row2') $cls='row1';
               else $cls = 'row2';
               $mto = str_replace(' ', '_', $r['message_to']);
               $mfr = str_replace(' ', '_', $r['message_from']);
               echo '<tr><td class="'.$cls.'"><a href="'.makeUrlNS('User', ( $fname == 'drafts') ? $mto : $mfr).'">';
-              if($fname == 'drafts' || $fname == 'outbox') echo $r['message_to']; else echo $r['message_from'];
+              if ( $fname == 'drafts' || $fname == 'outbox' )
+              {
+                echo $r['message_to'];
+              }
+              else
+              {
+                echo $r['message_from'];
+              }
+              
               echo '</a></td><td class="'.$cls.'"><a href="'.makeUrlNS('Special', 'PrivateMessages/'.$act.'/'.$r['message_id']).'">';
-              if($r['message_read'] == 0) echo '<b>';
+              
+              if ( $r['message_read'] == 0 )
+              {
+                echo '<b>';
+              }
               echo $r['subject'];
-              if($r['message_read'] == 0) echo '</b>';
-              echo '</a></td><td class="'.$cls.'">'.date('M j, Y G:i', $r['date']).'</td><td class="'.$cls.'" style="text-align: center;"><input name="marked_'.$r['message_id'].'" type="checkbox" /></td></tr>';
+              if ( $r['message_read'] == 0 )
+              {
+                echo '</b>';
+              }
+              echo '</a></td><td class="'.$cls.'">'.enano_date('M j, Y G:i', $r['date']).'</td><td class="'.$cls.'" style="text-align: center;"><input name="marked_'.$r['message_id'].'" type="checkbox" /></td></tr>';
             }
             $db->free_result();
           }
-          echo '<tr><th style="text-align: right;" colspan="4"><input type="hidden" name="folder" value="'.$fname.'" /><input type="submit" name="archive" value="Archive selected" /> <input type="submit" name="delete" value="Delete selected" /> <input type="submit" name="deleteall" value="Delete all" /></th></tr>';
+          echo '<tr>
+                  <th style="text-align: right;" colspan="4">
+                    <input type="hidden" name="folder" value="'.$fname.'" />
+                    <input type="submit" name="archive" value="' . $lang->get('privmsgs_btn_archive_selected') . '" />
+                    <input type="submit" name="delete" value="' . $lang->get('privmsgs_btn_delete_selected') . '" />
+                    <input type="submit" name="deleteall" value="' . $lang->get('privmsgs_btn_delete_all') . '" />
+                  </th>
+                </tr>';
           echo '</table></div></form>
           <br />
-          <a href="'.makeUrlNS('Special', 'PrivateMessages/Compose/').'">New message</a>
+          <a href="'.makeUrlNS('Special', 'PrivateMessages/Compose/').'">' . $lang->get('privmsgs_btn_compose') . '</a>
           </td></tr></table>';
           break;
       }
@@ -406,14 +719,14 @@
           $r = $db->fetchrow();
           $db->free_result();
           $q = $db->sql_query('INSERT INTO '.table_prefix.'buddies(user_id,buddy_user_id,is_friend) VALUES('.$session->user_id.', '.$r['user_id'].', 1);');
-          if(!$q) echo '<h3>Warning:</h3><p>Buddy could not be added: '.mysql_error().'</p>';
+          if(!$q) echo '<h3>Warning:</h3><p>Buddy could not be added: '.$db->get_error().'</p>';
           $db->free_result();
         }
       } elseif($argv[1] == 'Remove' && preg_match('#^([0-9]+)$#', $argv[2])) {
         // Using WHERE user_id prevents users from deleting others' buddies
         $q = $db->sql_query('DELETE FROM '.table_prefix.'buddies WHERE user_id='.$session->user_id.' AND buddy_id='.$argv[2].';');
         $db->free_result();
-        if(!$q) echo '<h3>Warning:</h3><p>Buddy could not be deleted: '.mysql_error().'</p>';
+        if(!$q) echo '<h3>Warning:</h3><p>Buddy could not be deleted: '.$db->get_error().'</p>';
         if(mysql_affected_rows() < 1) echo '<h3>Warning:</h3><p>No rows were affected. Either the selected buddy ID does not exist or you tried to delete someone else\'s buddy.</p>';
       }
       $template->header();
@@ -423,15 +736,15 @@
           <tr>
           <td style="padding: 0px; width: 120px;" valign="top"  >
           <div class="tblholder" style="width: 120px;"><table border="0" width="120" cellspacing="1" cellpadding="4">
-          <tr><th><small>Private messages</small></th></tr>
-          <tr><td class="row1"><small><a href="<?php echo $session->append_sid('Inbox'); ?>">Inbox</a>    </small></td></tr>
-          <tr><td class="row2"><small><a href="<?php echo $session->append_sid('Outbox'); ?>">Outbox</a>  </small></td></tr>
-          <tr><td class="row1"><small><a href="<?php echo $session->append_sid('Sent'); ?>">Sent Items</a></small></td></tr>
-          <tr><td class="row2"><small><a href="<?php echo $session->append_sid('Drafts'); ?>">Drafts</a>  </small></td></tr>
-          <tr><td class="row1"><small><a href="<?php echo $session->append_sid('Archive'); ?>">Archive</a></small></td></tr>
-          <tr><th><small>Buddies</small></th></tr>
-          <tr><td class="row2"><small><a href="<?php echo makeUrlNS('Special', 'PrivateMessages/FriendList'); ?>">Friend list</a></small></td></tr>
-          <tr><td class="row1"><small><a href="<?php echo makeUrlNS('Special', 'PrivateMessages/FoeList'); ?>">Foe list</a></small></td></tr>
+          <tr><th><small><?php echo $lang->get('privmsgs_sidebar_th_privmsgs'); ?></small></th></tr>
+          <tr><td class="row1"><small><a href="<?php echo makeUrlNS('Special', 'PrivateMessages/Folder/Inbox'); ?>"><?php echo $lang->get('privmsgs_folder_inbox'); ?></a></small></td></tr>
+          <tr><td class="row2"><small><a href="<?php echo makeUrlNS('Special', 'PrivateMessages/Folder/Outbox'); ?>"><?php echo $lang->get('privmsgs_folder_outbox'); ?></a></small></td></tr>
+          <tr><td class="row1"><small><a href="<?php echo makeUrlNS('Special', 'PrivateMessages/Folder/Sent'); ?>"><?php echo $lang->get('privmsgs_folder_sent'); ?></a></small></td></tr>
+          <tr><td class="row2"><small><a href="<?php echo makeUrlNS('Special', 'PrivateMessages/Folder/Drafts'); ?>"><?php echo $lang->get('privmsgs_folder_drafts'); ?></a></small></td></tr>
+          <tr><td class="row1"><small><a href="<?php echo makeUrlNS('Special', 'PrivateMessages/Folder/Archive'); ?>"><?php echo $lang->get('privmsgs_folder_archive'); ?></a></small></td></tr>
+          <tr><th><small><?php echo $lang->get('privmsgs_sidebar_th_buddies'); ?></small></th></tr>
+          <tr><td class="row2"><small><a href="<?php echo makeUrlNS('Special', 'PrivateMessages/FriendList'); ?>"><?php echo $lang->get('privmsgs_sidebar_friend_list'); ?></a></small></td></tr>
+          <tr><td class="row1"><small><a href="<?php echo makeUrlNS('Special', 'PrivateMessages/FoeList'); ?>"><?php echo $lang->get('privmsgs_sidebar_foe_list'); ?></a></small></td></tr>
           </table></div>
           </td>
           <td valign="top">
@@ -441,26 +754,26 @@
         else 
         {
           $allbuds = '';
-          echo '<br /><div class="tblholder"><table border="0" width="100%" cellspacing="1" cellpadding="4"><tr><th colspan="3">Buddy list for '.$session->username.'</th></tr>';
-          if($db->numrows() < 1) echo '<tr><td class="row3">No buddies in your list.</td></tr>';
+          echo '<br /><div class="tblholder"><table border="0" width="100%" cellspacing="1" cellpadding="4"><tr><th colspan="3">' . $lang->get('privmsgs_th_buddy_list', array('username' => htmlspecialchars($session->username))) . '</th></tr>';
+          if($db->numrows() < 1) echo '<tr><td class="row3">' . $lang->get('privmsgs_msg_no_buddies') . '</td></tr>';
           $cls = 'row2';
           while ( $row = $db->fetchrow() )
           {
             if($cls=='row2') $cls = 'row1';
             else $cls = 'row2';
-            echo '<tr><td class="'.$cls.'"><a href="'.makeUrlNS('User', str_replace(' ', '_', $row['username'])).'" '. ( isPage($paths->nslist['User'].str_replace(' ', '_', $row['username'])) ? '' : 'class="wikilink-nonexistent" ' ) .'>'.$row['username'].'</a></td><td class="'.$cls.'"><a href="'.makeUrlNS('Special', 'PrivateMessages/Compose/to/'.str_replace(' ', '_', $row['username'])).'">Send private message</a></td><td class="'.$cls.'"><a onclick="return confirm(\'Are you sure you want to delete this user from your buddy list?\')" href="'.makeUrlNS('Special', 'PrivateMessages/FriendList/Remove/'.$row['buddy_id']).'">Remove</a></td></tr>';
+            echo '<tr><td class="'.$cls.'"><a href="'.makeUrlNS('User', str_replace(' ', '_', $row['username'])).'" '. ( isPage($paths->nslist['User'].str_replace(' ', '_', $row['username'])) ? '' : 'class="wikilink-nonexistent" ' ) .'>'.$row['username'].'</a></td><td class="'.$cls.'"><a href="'.makeUrlNS('Special', 'PrivateMessages/Compose/to/'.str_replace(' ', '_', $row['username'])).'">' . $lang->get('privmsgs_btn_buddy_send_pm') . '</a></td><td class="'.$cls.'"><a href="'.makeUrlNS('Special', 'PrivateMessages/FriendList/Remove/'.$row['buddy_id']).'">' . $lang->get('privmsgs_btn_buddy_remove') . '</a></td></tr>';
             $allbuds .= str_replace(' ', '_', $row['username']).',';
           }
           $db->free_result();
           $allbuds = substr($allbuds, 0, strlen($allbuds)-1);
           if($cls=='row2') $cls = 'row1';
           else $cls = 'row2';
-          echo '<tr><td colspan="3" class="'.$cls.'" style="text-align: center;"><a href="'.makeUrlNS('Special', 'PrivateMessages/Compose/to/'.$allbuds).'">Send a PM to all buddies</a></td></tr>';
+          echo '<tr><td colspan="3" class="'.$cls.'" style="text-align: center;"><a href="'.makeUrlNS('Special', 'PrivateMessages/Compose/to/'.$allbuds).'">' . $lang->get('privmsgs_btn_pm_all_buddies') . '</a></td></tr>';
           echo '</table></div>';
         }
         echo '<form action="'.makeUrlNS('Special', 'PrivateMessages/FriendList/Add').'" method="post" onsubmit="if(!submitAuthorized) return false;">
-              <h3>Add a new friend</h3>';
-        echo '<p>Username: '.$template->username_field('buddyname').'  <input type="submit" name="_go" value="Add" /></p>';
+              <h3>' . $lang->get('privmsgs_heading_add_buddy') . '</h3>';
+        echo '<p>' . $lang->get('privmsgs_lbl_username') . ' '.$template->username_field('buddyname').'  <input type="submit" name="_go" value="' . $lang->get('privmsgs_btn_add') . '" /></p>';
         echo '</form>';
         ?>
         </td>
@@ -478,61 +791,60 @@
         {
           $r = $db->fetchrow();
           $q = $db->sql_query('INSERT INTO '.table_prefix.'buddies(user_id,buddy_user_id,is_friend) VALUES('.$session->user_id.', '.$r['user_id'].', 0);');
-          if(!$q) echo '<h3>Warning:</h3><p>Buddy could not be added: '.mysql_error().'</p>';
+          if(!$q) echo '<h3>Warning:</h3><p>Buddy could not be added: '.$db->get_error().'</p>';
         }
         $db->free_result();
       } elseif($argv[1] == 'Remove' && preg_match('#^([0-9]+)$#', $argv[2])) {
         // Using WHERE user_id prevents users from deleting others' buddies
         $q = $db->sql_query('DELETE FROM '.table_prefix.'buddies WHERE user_id='.$session->user_id.' AND buddy_id='.$argv[2].';');
         $db->free_result();
-        if(!$q) echo '<h3>Warning:</h3><p>Buddy could not be deleted: '.mysql_error().'</p>';
+        if(!$q) echo '<h3>Warning:</h3><p>Buddy could not be deleted: '.$db->get_error().'</p>';
         if(mysql_affected_rows() < 1) echo '<h3>Warning:</h3><p>No rows were affected. Either the selected buddy ID does not exist or you tried to delete someone else\'s buddy.</p>';
       }
       $template->header();
       userprefs_show_menu();
       ?>
-      <table border="0" width="100%" cellspacing="10" cellpadding="0">
-          <tr>
-          <td style="padding: 0px; width: 120px;" valign="top"  >
-          <div class="tblholder" style="width: 120px;"><table border="0" width="120" cellspacing="1" cellpadding="4">
-          <tr><th><small>Private messages</small></th></tr>
-          <tr><td class="row1"><small><a href="<?php echo $session->append_sid('Inbox'); ?>">Inbox</a>    </small></td></tr>
-          <tr><td class="row2"><small><a href="<?php echo $session->append_sid('Outbox'); ?>">Outbox</a>  </small></td></tr>
-          <tr><td class="row1"><small><a href="<?php echo $session->append_sid('Sent'); ?>">Sent Items</a></small></td></tr>
-          <tr><td class="row2"><small><a href="<?php echo $session->append_sid('Drafts'); ?>">Drafts</a>  </small></td></tr>
-          <tr><td class="row1"><small><a href="<?php echo $session->append_sid('Archive'); ?>">Archive</a></small></td></tr>
-          <tr><th><small>Buddies</small></th></tr>
-          <tr><td class="row2"><small><a href="<?php echo makeUrlNS('Special', 'PrivateMessages/FriendList'); ?>">Friend list</a></small></td></tr>
-          <tr><td class="row1"><small><a href="<?php echo makeUrlNS('Special', 'PrivateMessages/FoeList'); ?>">Foe list</a></small></td></tr>
-          </table></div>
-          </td>
-          <td valign="top">
+        <table border="0" width="100%" cellspacing="10" cellpadding="0">
+        <tr>
+        <td style="padding: 0px; width: 120px;" valign="top"  >
+        <div class="tblholder" style="width: 120px;"><table border="0" width="120" cellspacing="1" cellpadding="4">
+        <tr><th><small><?php echo $lang->get('privmsgs_sidebar_th_privmsgs'); ?></small></th></tr>
+        <tr><td class="row1"><small><a href="<?php echo makeUrlNS('Special', 'PrivateMessages/Folder/Inbox'); ?>"><?php echo $lang->get('privmsgs_folder_inbox'); ?></a></small></td></tr>
+        <tr><td class="row2"><small><a href="<?php echo makeUrlNS('Special', 'PrivateMessages/Folder/Outbox'); ?>"><?php echo $lang->get('privmsgs_folder_outbox'); ?></a></small></td></tr>
+        <tr><td class="row1"><small><a href="<?php echo makeUrlNS('Special', 'PrivateMessages/Folder/Sent'); ?>"><?php echo $lang->get('privmsgs_folder_sent'); ?></a></small></td></tr>
+        <tr><td class="row2"><small><a href="<?php echo makeUrlNS('Special', 'PrivateMessages/Folder/Drafts'); ?>"><?php echo $lang->get('privmsgs_folder_drafts'); ?></a></small></td></tr>
+        <tr><td class="row1"><small><a href="<?php echo makeUrlNS('Special', 'PrivateMessages/Folder/Archive'); ?>"><?php echo $lang->get('privmsgs_folder_archive'); ?></a></small></td></tr>
+        <tr><th><small><?php echo $lang->get('privmsgs_sidebar_th_buddies'); ?></small></th></tr>
+        <tr><td class="row2"><small><a href="<?php echo makeUrlNS('Special', 'PrivateMessages/FriendList'); ?>"><?php echo $lang->get('privmsgs_sidebar_friend_list'); ?></a></small></td></tr>
+        <tr><td class="row1"><small><a href="<?php echo makeUrlNS('Special', 'PrivateMessages/FoeList'); ?>"><?php echo $lang->get('privmsgs_sidebar_foe_list'); ?></a></small></td></tr>
+        </table></div>
+        </td>
+        <td valign="top">
         <?php
         $q = $db->sql_query('SELECT u.username,b.buddy_id FROM '.table_prefix.'buddies AS b LEFT JOIN '.table_prefix.'users AS u ON ( u.user_id=b.buddy_user_id ) WHERE b.user_id='.$session->user_id.' AND is_friend=0;');
         if(!$q) $db->_die('The buddy list could not be selected.');
         else 
         {
           $allbuds = '';
-          echo '<br /><div class="tblholder"><table border="0" width="100%" cellspacing="1" cellpadding="4"><tr><th colspan="3">Foe list for '.$session->username.'</th></tr>';
-          if($db->numrows() < 1) echo '<tr><td class="row2">No foes in your list.</td></tr>';
+          echo '<br /><div class="tblholder"><table border="0" width="100%" cellspacing="1" cellpadding="4"><tr><th colspan="3">' . $lang->get('privmsgs_th_foe_list', array('username' => htmlspecialchars($session->username))) . '</th></tr>';
+          if($db->numrows() < 1) echo '<tr><td class="row3">' . $lang->get('privmsgs_msg_no_foes') . '</td></tr>';
           $cls = 'row2';
           while ( $row = $db->fetchrow() )
           {
             if($cls=='row2') $cls = 'row1';
             else $cls = 'row2';
-            echo '<tr><td class="'.$cls.'"><a href="'.makeUrlNS('User', str_replace(' ', '_', $row['username'])).'" '. ( isPage($paths->nslist['User'].str_replace(' ', '_', $row['username'])) ? '' : 'class="wikilink-nonexistent" ' ) .'>'.$row['username'].'</a></td><td class="'.$cls.'"><a href="'.makeUrlNS('Special', 'PrivateMessages/Compose/to/'.str_replace(' ', '_', $row['username'])).'">Send private message</a></td><td class="'.$cls.'"><a onclick="return confirm(\'Are you sure you want to delete this user from your buddy list?\')" href="'.makeUrlNS('Special', 'PrivateMessages/FriendList/Remove/'.$row['buddy_id']).'">Remove</a></td></tr>';
+            echo '<tr><td class="'.$cls.'"><a href="'.makeUrlNS('User', str_replace(' ', '_', $row['username'])).'" '. ( isPage($paths->nslist['User'].str_replace(' ', '_', $row['username'])) ? '' : 'class="wikilink-nonexistent" ' ) .'>'.$row['username'].'</a></td><td class="'.$cls.'"><a href="'.makeUrlNS('Special', 'PrivateMessages/Compose/to/'.str_replace(' ', '_', $row['username'])).'">' . $lang->get('privmsgs_btn_buddy_send_pm') . '</a></td><td class="'.$cls.'"><a href="'.makeUrlNS('Special', 'PrivateMessages/FoeList/Remove/'.$row['buddy_id']).'">' . $lang->get('privmsgs_btn_buddy_remove') . '</a></td></tr>';
             $allbuds .= str_replace(' ', '_', $row['username']).',';
           }
+          $db->free_result();
           $allbuds = substr($allbuds, 0, strlen($allbuds)-1);
           if($cls=='row2') $cls = 'row1';
           else $cls = 'row2';
-          //echo '<tr><td colspan="3" class="'.$cls.'" style="text-align: center;"><a href="'.makeUrlNS('Special', 'PrivateMessages/Compose/to/'.$allbuds).'">Send a PM to all buddies</a></td></tr>';
           echo '</table></div>';
         }
-        $db->free_result();
         echo '<form action="'.makeUrlNS('Special', 'PrivateMessages/FoeList/Add').'" method="post" onsubmit="if(!submitAuthorized) return false;">
-              <h3>Add a new foe</h3>';
-        echo '<p>Username: '.$template->username_field('buddyname').'  <input type="submit" name="_go" value="Add" /></p>';
+              <h3>' . $lang->get('privmsgs_heading_add_foe') . '</h3>';
+        echo '<p>' . $lang->get('privmsgs_lbl_username') . ' '.$template->username_field('buddyname').'  <input type="submit" name="_go" value="' . $lang->get('privmsgs_btn_add') . '" /></p>';
         echo '</form>';
         ?>
         </td>
--- a/plugins/SpecialAdmin.php	Fri Feb 22 12:46:51 2008 -0500
+++ b/plugins/SpecialAdmin.php	Fri Feb 22 12:51:53 2008 -0500
@@ -1,16 +1,16 @@
 <?php
 /*
-Plugin Name: Runt - the Enano administration panel
+Plugin Name: plugin_specialadmin_title
 Plugin URI: http://enanocms.org/
-Description: Provides the page Special:Administration, which is the AJAX frontend to the various Admin pagelets. This plugin cannot be disabled.
+Description: plugin_specialadmin_desc
 Author: Dan Fuhry
-Version: 1.0.3
+Version: 1.1.1
 Author URI: http://enanocms.org/
 */
 
 /*
  * Enano - an open-source CMS capable of wiki functions, Drupal-like sidebar blocks, and everything in between
- * Version 1.0.3 (Dyrad)
+ * Version 1.1.2 (Caoineag alpha 2)
  * Copyright (C) 2006-2007 Dan Fuhry
  *
  * This program is Free Software; you can redistribute and/or modify it under the terms of the GNU General Public License
@@ -22,17 +22,17 @@
  
 global $db, $session, $paths, $template, $plugins; // Common objects
 
-$plugins->attachHook('base_classes_initted', '
+$plugins->attachHook('session_started', '
   global $paths;
     $paths->add_page(Array(
-      \'name\'=>\'Administration\',
+      \'name\'=>\'specialpage_administration\',
       \'urlname\'=>\'Administration\',
       \'namespace\'=>\'Special\',
       \'special\'=>0,\'visible\'=>1,\'comments_on\'=>0,\'protected\'=>1,\'delvotes\'=>0,\'delvote_ips\'=>\'\',
       ));
     
     $paths->add_page(Array(
-      \'name\'=>\'Manage the Sidebar\',
+      \'name\'=>\'specialpage_manage_sidebar\',
       \'urlname\'=>\'EditSidebar\',
       \'namespace\'=>\'Special\',
       \'special\'=>0,\'visible\'=>1,\'comments_on\'=>0,\'protected\'=>1,\'delvotes\'=>0,\'delvote_ips\'=>\'\',
@@ -40,67 +40,108 @@
   ');
 
 // Admin pages that were too enormous to be in this file were split off into the plugins/admin/ directory in 1.0.1
+require(ENANO_ROOT . '/plugins/admin/PageManager.php');
+require(ENANO_ROOT . '/plugins/admin/PageEditor.php');
 require(ENANO_ROOT . '/plugins/admin/PageGroups.php');
+require(ENANO_ROOT . '/plugins/admin/GroupManager.php');
 require(ENANO_ROOT . '/plugins/admin/SecurityLog.php');
 require(ENANO_ROOT . '/plugins/admin/UserManager.php');
+require(ENANO_ROOT . '/plugins/admin/LangManager.php');
+require(ENANO_ROOT . '/plugins/admin/ThemeManager.php');
+
+// For convenience and nothing more.
+function acp_start_form()
+{
+  global $db, $session, $paths, $template, $plugins; // Common objects
+  echo '<form action="'.makeUrl($paths->nslist['Special'].'Administration', ( isset($_GET['sqldbg']) ? 'sqldbg&' : '' ) . ( isset($_GET['nocompress']) ? 'nocompress&' : '' ) . 'module='.$paths->cpage['module']).'" method="post" enctype="multipart/form-data">';
+}
 
 // function names are IMPORTANT!!! The name pattern is: page_<namespace ID>_<page URLname, without namespace>
 
 function page_Admin_Home() {
   global $db, $session, $paths, $template, $plugins; // Common objects
+  global $lang;
   if ( $session->auth_level < USER_LEVEL_ADMIN || $session->user_level < USER_LEVEL_ADMIN )
   {
-    echo '<h3>Error: Not authenticated</h3><p>It looks like your administration session is invalid or you are not authorized to access this administration page. Please <a href="' . makeUrlNS('Special', 'Login/' . $paths->nslist['Special'] . 'Administration', 'level=' . USER_LEVEL_ADMIN, true) . '">re-authenticate</a> to continue.</p>';
+    $login_link = makeUrlNS('Special', 'Login/' . $paths->nslist['Special'] . 'Administration', 'level=' . USER_LEVEL_ADMIN, true);
+    echo '<h3>' . $lang->get('adm_err_not_auth_title') . '</h3>';
+    echo '<p>' . $lang->get('adm_err_not_auth_body', array( 'login_link' => $login_link )) . '</p>';
+    return;
+  }
+  
+  if ( $paths->getParam(0) == 'updates.xml' )
+  {
+    require_once(ENANO_ROOT . '/includes/http.php');
+    $req = new Request_HTTP('germantown.enanocms.org', '/meta/updates.xml');
+    $response = $req->get_response_body();
+    header('Content-type: application/xml');
+    if ( $req->response_code != HTTP_OK )
+    {
+      // Error in response
+      echo '<enano><latest><error><![CDATA[
+Did not properly receive response from server. Response code: ' . $req->response_code . ' ' . $req->response_string . '
+]]></error></latest></enano>';
+    }
+    else
+    {
+      // Retrieve first update
+      $first_update = preg_match('/<release tag="([^"]+)" version="([^"]+)" (codename="([^"]+)" )?relnotes="([^"]+)" ?\/>/', $response, $match);
+      if ( !$first_update )
+      {
+        echo '<enano><latest><error><![CDATA[
+Received invalid XML response.
+]]></error></latest></enano>';
+      }
+      if ( version_compare(enano_version(true), $match[2], '<') )
+      {
+        $response = str_replace_once('</latest>', "  <haveupdates />\n  </latest>", $response);
+      }
+      echo $response;
+    }
     return;
   }
   
   // Basic information
-  echo RenderMan::render(
-'== Welcome to Runt, the Enano administration panel. ==
-
-Thank you for choosing Enano as your CMS. This screen allows you to see some information about your website, plus some details about how your site is doing statistically.
-
-Using the links on the left you can control every aspect of your website\'s look and feel, plus you can manage users, work with pages, and install plugins to make your Enano installation even better.');
+  echo '<h2>' . $lang->get('acphome_heading_main') . '</h2>';
+  echo '<p>' . $lang->get('acphome_welcome_line1') . '</p>';
+  echo '<p>' . $lang->get('acphome_welcome_line2') . '</p>';
   
   // Demo mode
   if ( defined('ENANO_DEMO_MODE') )
   {
-    echo '<h3>Enano is running in demo mode.</h3>
-          <p>If you borked something up, or if you\'re done testing, you can <a href="' . makeUrlNS('Special', 'DemoReset', false, true) . '">reset this site</a>. The site is reset automatically once every two hours. When a reset is performed, all custom modifications to the site are lost and replaced with default values.</p>';
-  }
-  
-  // If we're on PHP4, warn the user
-  // Enano is not supported on PHP4 after December 31, 2007.
-  if ( version_compare(PHP_VERSION, '5.0.0', '<') )
-  {
-    echo '<div class="warning-box">
-            <b>Your server is running PHP ' . PHP_VERSION . '.</b><br />
-            As of December 31, 2007, servers running the PHP 4.x interpreter are not eligible for support on the Enano forums. While you
-            may be able to obtain support elsewhere, all official Enano support channels do not provide any type of support for servers
-            running this outdated and vulnerable version of PHP.<br />
-            <br />
-            This notice will not show if PHP 5.0.0 or later is detected. You may want to ask your web host to upgrade their PHP
-            installation. If you\'re refused, point them to <a href="http://gophp5.org/">GoPHP5.org</a> and explain that they are opening
-            themselves to security problems by not upgrading.
-          </div>';
+    echo '<h3>' . $lang->get('acphome_msg_demo_title') . '</h3>
+          <p>' . $lang->get('acphome_msg_demo_body', array('reset_url' => makeUrlNS('Special', 'DemoReset', false, true))) . '</p>';
   }
   
   // Check for the installer scripts
   if( ( file_exists(ENANO_ROOT.'/install.php') || file_exists(ENANO_ROOT.'/schema.sql') ) && !defined('ENANO_DEMO_MODE') )
   {
-    echo '<div class="error-box"><b>NOTE:</b> It appears that your install.php and/or schema.sql files still exist. It is HIGHLY RECOMMENDED that you delete or rename these files, to prevent getting your server hacked.</div>';
+    echo '<div class="error-box">
+            ' . $lang->get('acphome_msg_install_files') . '
+          </div>';
   }
   
+  echo '<h3>' . $lang->get('acphome_heading_updates') . '</h3>';
+  echo '<p>' . $lang->get('acphome_msg_updates_info', array('updates_url' => 'http://germantown.enanocms.org/meta/updates.xml')) . '</p>';
+  echo '<div id="update_check_container"><input type="button" onclick="ajaxUpdateCheck(this.parentNode.id);" value="' . $lang->get('acphome_btn_check_updates') . '" /></div>';
+  
   // Inactive users
-  $q = $db->sql_query('SELECT * FROM '.table_prefix.'logs WHERE log_type=\'admin\' AND action=\'activ_req\';');
-  if($q)
-    if($db->numrows() > 0)
+  $q = $db->sql_query('SELECT time_id FROM '.table_prefix.'logs WHERE log_type=\'admin\' AND action=\'activ_req\';');
+  if ( $q )
+  {
+    if ( $db->numrows() > 0 )
     {
       $n = $db->numrows();
-      if($n == 1) $s = $n . ' user is';
-      else $s = $n . ' users are';
-      echo '<div class="warning-box">It appears that '.$s.' awaiting account activation. You can activate those accounts by going to the <a href="#" onclick="ajaxPage(\''.$paths->nslist['Admin'].'UserManager\'); return false;">User Manager</a>.</div>';
+      $um_flags = 'href="#" onclick="ajaxPage(\''.$paths->nslist['Admin'].'UserManager\'); return false;"';
+      if ( $n == 1 )
+        $s = $lang->get('acphome_msg_inactive_users_one', array('um_flags' => $um_flags));
+      else
+        $s = $lang->get('acphome_msg_inactive_users_plural', array('um_flags' => $um_flags));
+      echo '<div class="warning-box">
+              ' . $s . '
+            </div>';
     }
+  }
   $db->free_result();
   // Stats
   if(getConfig('log_hits') == '1')
@@ -109,31 +150,44 @@
     //die('<pre>'.print_r($stats,true).'</pre>');
     $c = 0;
     $cls = 'row2';
-    echo '<h3>Most requested pages</h3><div class="tblholder"><table style="width: 100%;" border="0" cellspacing="1" cellpadding="4"><tr><th>Page</th><th>Hits</th></tr>';
+    echo '<h3>' . $lang->get('acphome_heading_top_pages') . '</h3>
+          <div class="tblholder">
+            <table style="width: 100%;" border="0" cellspacing="1" cellpadding="4">
+              <tr>
+                <th>' . $lang->get('acphome_th_toppages_page') . '</th>
+                <th>' . $lang->get('acphome_th_toppages_hits') . '</th>
+              </tr>';
     foreach($stats as $data)
     {
-      echo '<tr>';
+      echo   '<tr>';
       $cls = ( $cls == 'row1' ) ? 'row2' : 'row1';
-      echo '<td class="'.$cls.'"><a href="'.makeUrl($data['page_urlname']).'">'.$data['page_title'].'</a></td><td style="text-align: center;" class="'.$cls.'">'.$data['num_hits'].'</td>';
-      echo '</tr>';
+      echo     '<td class="'.$cls.'">
+                  <a href="'.makeUrl($data['page_urlname']).'">'.$data['page_title'].'</a></td><td style="text-align: center;" class="'.$cls.'">'.$data['num_hits']
+             . '</td>';
+      echo   '</tr>';
     }
-    echo '</table></div>';
+    echo '  </table>
+          </div>';
   }
   
   // Security log
-  echo '<h3>Security log</h3>';
+  echo '<h3>' . $lang->get('acphome_heading_seclog') . '</h3>';
+  echo '<p>' . $lang->get('acphome_msg_seclog_info') . '</p>';
   $seclog = get_security_log(5);
   echo $seclog;
   
-  echo '<p><a href="#" onclick="ajaxPage(\''.$paths->nslist['Admin'].'SecurityLog\'); return false;">Full security log</a></p>';
+  echo '<p><a href="#" onclick="ajaxPage(\''.$paths->nslist['Admin'].'SecurityLog\'); return false;">' . $lang->get('acphome_btn_seclog_full') . '</a></p>';
   
 }
 
 function page_Admin_GeneralConfig() {
   global $db, $session, $paths, $template, $plugins; // Common objects
+  global $lang;
   if ( $session->auth_level < USER_LEVEL_ADMIN || $session->user_level < USER_LEVEL_ADMIN )
   {
-    echo '<h3>Error: Not authenticated</h3><p>It looks like your administration session is invalid or you are not authorized to access this administration page. Please <a href="' . makeUrlNS('Special', 'Login/' . $paths->nslist['Special'] . 'Administration', 'level=' . USER_LEVEL_ADMIN, true) . '">re-authenticate</a> to continue.</p>';
+    $login_link = makeUrlNS('Special', 'Login/' . $paths->nslist['Special'] . 'Administration', 'level=' . USER_LEVEL_ADMIN, true);
+    echo '<h3>' . $lang->get('adm_err_not_auth_title') . '</h3>';
+    echo '<p>' . $lang->get('adm_err_not_auth_body', array( 'login_link' => $login_link )) . '</p>';
     return;
   }
   
@@ -155,6 +209,8 @@
     if(isset($_POST['editmsg']))                 setConfig('wiki_edit_notice', '1');
     else                                         setConfig('wiki_edit_notice', '0');
     setConfig('wiki_edit_notice_text', $_POST['editmsg_text']);
+    if(isset($_POST['guest_edit_require_captcha'])) setConfig('guest_edit_require_captcha', '1');
+    else                                         setConfig('guest_edit_require_captcha', '0');
     
     // Stats
     if(isset($_POST['log_hits']))                setConfig('log_hits', '1');
@@ -219,7 +275,48 @@
       setConfig('pw_strength_minimum', $strength);
     }
     
-    echo '<div class="info-box">Your changes to the site configuration have been saved.</div><br />';
+    setConfig('register_tou', RenderMan::preprocess_text($_POST['register_tou'], true, false));
+    
+    // Account lockout policy
+    if ( preg_match('/^[0-9]+$/', $_POST['lockout_threshold']) )
+      setConfig('lockout_threshold', $_POST['lockout_threshold']);
+    
+    if ( preg_match('/^[0-9]+$/', $_POST['lockout_duration']) )
+      setConfig('lockout_duration', $_POST['lockout_duration']);
+    
+    if ( in_array($_POST['lockout_policy'], array('disable', 'captcha', 'lockout')) )
+      setConfig('lockout_policy', $_POST['lockout_policy']);
+    
+    // Avatar settings
+    setConfig('avatar_enable', ( isset($_POST['avatar_enable']) ? '1' : '0' ));
+    // for these next three values, set the config value if it's a valid integer; this is
+    // done by using strval(intval($foo)) === $foo, which flattens $foo to an integer and
+    // then converts it back to a string. This effectively verifies that var $foo is both
+    // set and that it's a valid string representing an integer.
+    setConfig('avatar_max_size', ( strval(intval($_POST['avatar_max_size'])) === $_POST['avatar_max_size'] ? $_POST['avatar_max_size'] : '10240' ));
+    setConfig('avatar_max_width', ( strval(intval($_POST['avatar_max_width'])) === $_POST['avatar_max_width'] ? $_POST['avatar_max_width'] : '96' ));
+    setConfig('avatar_max_height', ( strval(intval($_POST['avatar_max_height'])) === $_POST['avatar_max_height'] ? $_POST['avatar_max_height'] : '96' ));
+    setConfig('avatar_enable_anim', ( isset($_POST['avatar_enable_anim']) ? '1' : '0' ));
+    setConfig('avatar_upload_file', ( isset($_POST['avatar_upload_file']) ? '1' : '0' ));
+    setConfig('avatar_upload_http', ( isset($_POST['avatar_upload_http']) ? '1' : '0' ));
+    
+    if ( is_dir(ENANO_ROOT . '/' . $_POST['avatar_directory']) )
+    {
+      if ( preg_match('/^([A-z0-9_-]+)(\/([A-z0-9_-]+))*$/', $_POST['avatar_directory']) )
+      {
+        setConfig('avatar_directory', $_POST['avatar_directory']);
+      }
+      else
+      {
+        echo '<div class="error-box">' . $lang->get('acpgc_err_avatar_dir_invalid') . '</div>';
+      }
+    }
+    else
+    {
+      echo '<div class="error-box">' . $lang->get('acpgc_err_avatar_dir_invalid') . '</div>';
+    }
+    
+    echo '<div class="info-box">' . $lang->get('acpgc_msg_save_success') . '</div><br />';
     
   }
   else if ( isset($_POST['submit']) && defined('ENANO_DEMO_MODE') )
@@ -233,28 +330,28 @@
       
     <!-- Global options -->
     
-      <tr><th colspan="2">Global site options</th></tr>
-      <tr><th colspan="2" class="subhead">These options control the entire site.</th></tr>
+      <tr><th colspan="2"><?php echo $lang->get('acpgc_heading_main'); ?></th></tr>
+      <tr><th colspan="2" class="subhead"><?php echo $lang->get('acpgc_heading_submain'); ?></th></tr>
       
-      <tr><td class="row1" style="width: 50%;">Site name:</td>  <td class="row1" style="width: 50%;"><input type="text" name="site_name" size="30" value="<?php echo htmlspecialchars(getConfig('site_name')); ?>" /></td></tr>
-      <tr><td class="row2">Site description:</td>               <td class="row2"><input type="text" name="site_desc" size="30" value="<?php echo htmlspecialchars(getConfig('site_desc')); ?>" /></td></tr>
-      <tr><td class="row1">Main page:</td>                      <td class="row1"><?php echo $template->pagename_field('main_page', htmlspecialchars(str_replace('_', ' ', getConfig('main_page')))); ?></td></tr>
-      <tr><td class="row2">Copyright notice shown on pages:</td><td class="row2"><input type="text" name="copyright" size="30" value="<?php echo htmlspecialchars(getConfig('copyright_notice')); ?>" /></td></tr>
-      <tr><td class="row1" colspan="2">Hint: If you're using Windows, you can make a "&copy;" symbol by holding ALT and pressing 0169 on the numeric keypad.</td></tr>
-      <tr><td class="row2">Contact e-mail<br /><small>All e-mail sent from this site will appear to have come from the address shown here.</small></td><td class="row2"><input name="contact_email" type="text" size="40" value="<?php echo htmlspecialchars(getConfig('contact_email')); ?>" /></td></tr>
+      <tr><td class="row1" style="width: 50%;"><?php echo $lang->get('acpgc_field_site_name'); ?></td>  <td class="row1" style="width: 50%;"><input type="text" name="site_name" size="30" value="<?php echo htmlspecialchars(getConfig('site_name')); ?>" /></td></tr>
+      <tr><td class="row2"><?php echo $lang->get('acpgc_field_site_desc'); ?></td>               <td class="row2"><input type="text" name="site_desc" size="30" value="<?php echo htmlspecialchars(getConfig('site_desc')); ?>" /></td></tr>
+      <tr><td class="row1"><?php echo $lang->get('acpgc_field_main_page'); ?></td>                      <td class="row1"><?php echo $template->pagename_field('main_page', htmlspecialchars(str_replace('_', ' ', getConfig('main_page')))); ?></td></tr>
+      <tr><td class="row2"><?php echo $lang->get('acpgc_field_copyright'); ?></td><td class="row2"><input type="text" name="copyright" size="30" value="<?php echo htmlspecialchars(getConfig('copyright_notice')); ?>" /></td></tr>
+      <tr><td class="row1" colspan="2"><?php echo $lang->get('acpgc_field_copyright_hint'); ?></td></tr>
+      <tr><td class="row2"><?php echo $lang->get('acpgc_field_contactemail'); ?><br /><small><?php echo $lang->get('acpgc_field_contactemail_hint'); ?></small></td><td class="row2"><input name="contact_email" type="text" size="40" value="<?php echo htmlspecialchars(getConfig('contact_email')); ?>" /></td></tr>
       
     <!-- Wiki mode -->
       
-      <tr><th colspan="2">Wiki mode</th></tr>
+      <tr><th class="subhead" colspan="2"><?php echo $lang->get('acpgc_heading_wikimode'); ?></th></tr>
       
       <tr>
         <td class="row3" rowspan="2">
-          Enano can also act as a wiki, meaning anyone can edit and create pages. To enable Wiki Mode, check the box to the right.<br /><br />
-          In Wiki Mode, certain HTML tags such as &lt;script&gt; and &lt;object&gt; are disabled, and all PHP code is disabled, except if the person editing the page is an administrator.<br /><br />
-          Also, Enano keeps complete page history, which makes restoring vandalized pages easy. You can also protect pages so that they cannot be edited.
+          <?php echo $lang->get('acpgc_field_wikimode_intro'); ?><br /><br />
+          <?php echo $lang->get('acpgc_field_wikimode_info_sanitize'); ?><br /><br />
+          <?php echo $lang->get('acpgc_field_wikimode_info_history'); ?>
         </td>
         <td class="row1">
-          <input type="checkbox" name="wikimode" id="wikimode" <?php if(getConfig('wiki_mode')=='1') echo('CHECKED '); ?> /><label for="wikimode">Enable Wiki Mode</label>
+          <input type="checkbox" name="wikimode" id="wikimode" <?php if(getConfig('wiki_mode')=='1') echo('CHECKED '); ?> /><label for="wikimode"><?php echo $lang->get('acpgc_field_wikimode'); ?></label>
         </td>
       </tr>
       
@@ -262,11 +359,12 @@
       
       <tr>
         <td class="row3" rowspan="2">
-          <b>Edit page notice</b><br />
-          When Wiki Mode is enabled, anyone can edit pages. Check the box below and enter a message to display it whenever the page editor is opened.
+          <b><?php echo $lang->get('acpgc_field_editnotice_title'); ?></b><br />
+          <?php echo $lang->get('acpgc_field_editnotice_info'); ?>
         </td>
         <td class="row1">
-          <input onclick="if(this.checked) document.getElementById('editmsg_text').style.display='block'; else document.getElementById('editmsg_text').style.display='none';" type="checkbox" name="editmsg" id="editmsg" <?php if(getConfig('wiki_edit_notice')=='1') echo('CHECKED '); ?>/> <label for="editmsg">Show a message whenever pages are edited</label>
+          <input onclick="if(this.checked) document.getElementById('editmsg_text').style.display='block'; else document.getElementById('editmsg_text').style.display='none';" type="checkbox" name="editmsg" id="editmsg" <?php if(getConfig('wiki_edit_notice')=='1') echo('CHECKED '); ?>/>
+          <label for="editmsg"><?php echo $lang->get('acpgc_field_editnotice'); ?></label>
         </td>
       </tr>
       
@@ -276,23 +374,88 @@
         </td>
       </tr>
       
+      <tr>
+        <td class="row1">
+          <b><?php echo $lang->get('acpgc_field_edit_require_captcha_title'); ?></b><br />
+          <?php echo $lang->get('acpgc_field_edit_require_captcha_hint'); ?>
+        </td>
+        <td class="row1">
+          <label>
+            <input type="checkbox" name="guest_edit_require_captcha" <?php if ( getConfig('guest_edit_require_captcha') == '1' ) echo 'checked="checked" '; ?>/>
+            <?php echo $lang->get('acpgc_field_edit_require_captcha'); ?>
+          </label>
+        </td>
+      </tr>
+      
     <!-- Site statistics -->
     
-      <tr><th colspan="2">Statistics and hit counting</th></tr>
+      <tr><th class="subhead" colspan="2"><?php echo $lang->get('acpgc_heading_stats'); ?></th></tr>
       
       <tr>
-        <td class="row1">Enano has the ability to show statistics for every page on the site. This allows you to keep very close track of who is visiting your site, and from where.<br /><br />Unfortunately, some users don't like being logged. For this reason, you should state clearly what is logged (usually the username or IP address, current time, page name, and referer URL) in your privacy policy. If your site is primarily geared towards children, and you are a United States citizen, you are required to have a privacy policy stating exactly what is being logged under the terms of the Childrens' Online Privacy Protection Act.</td>
-        <td class="row1"><label><input type="checkbox" name="log_hits" <?php if(getConfig('log_hits') == '1') echo 'checked="checked" '; ?>/>  Log all page hits</label><br /><small>This excludes special and administration pages.</small></td>
+        <td class="row1">
+          <?php echo $lang->get('acpgc_stats_intro'); ?><br /><br />
+          <?php echo $lang->get('acpgc_stats_hint_privacy'); ?>
+        </td>
+        <td class="row1">
+          <label>
+            <input type="checkbox" name="log_hits" <?php if(getConfig('log_hits') == '1') echo 'checked="checked" '; ?>/>
+            <?php echo $lang->get('acpgc_field_stats_enable'); ?>
+          </label><br />
+          <small><?php echo $lang->get('acpgc_field_stats_hint'); ?></small>
+        </td>
       </tr>
       
     <!-- Comment options -->
       
-      <tr><th colspan="2">Comment system</th></tr>
-      <tr><td class="row1"><label for="enable-comments"><b>Enable the comment system</b></label>                      </td><td class="row1"><input name="enable-comments"  id="enable-comments"  type="checkbox" <?php if(getConfig('enable_comments')=='1')  echo('CHECKED '); ?>/></td></tr>
-      <tr><td class="row2"><label for="comment-approval">Require approval before article comments can be shown</label></td><td class="row2"><input name="comment-approval" id="comment-approval" type="checkbox" <?php if(getConfig('approve_comments')=='1') echo('CHECKED '); ?>/></td></tr>
-      <tr><td class="row1">Guest comment posting allowed                                                              </td><td class="row1"><label><input name="comments_need_login" type="radio" value="0" <?php if(getConfig('comments_need_login')=='0') echo 'CHECKED '; ?>/> Yes</label>
-                                                                                                                                            <label><input name="comments_need_login" type="radio" value="1" <?php if(getConfig('comments_need_login')=='1') echo 'CHECKED '; ?>/> Require visual confirmation</label>
-    <!-- Default permissions -->                                                                                                            <label><input name="comments_need_login" type="radio" value="2" <?php if(getConfig('comments_need_login')=='2') echo 'CHECKED '; ?>/> No (require login)</label></td></tr>
+      <tr>
+        <th class="subhead" colspan="2">
+          <?php echo $lang->get('acpgc_heading_comments'); ?>
+        </th>
+      </tr>
+      
+      <tr>
+        <td class="row1">
+          <label for="enable-comments">
+            <b><?php echo $lang->get('acpgc_field_enable_comments'); ?></b>
+          </label>
+        </td>
+        <td class="row1">
+          <input name="enable-comments"  id="enable-comments"  type="checkbox" <?php if(getConfig('enable_comments')=='1')  echo('CHECKED '); ?>/>
+        </td>
+      </tr>
+      
+      <tr>
+        <td class="row2">
+          <label for="comment-approval">
+            <?php echo $lang->get('acpgc_field_approve_comments'); ?>
+          </label>
+        </td>
+        <td class="row2">
+          <input name="comment-approval" id="comment-approval" type="checkbox" <?php if(getConfig('approve_comments')=='1') echo('CHECKED '); ?>/>
+        </td>
+      </tr>
+      
+      <tr>
+        <td class="row1">
+          <?php echo $lang->get('acpgc_field_comment_allow_guests'); ?>
+        </td>
+        <td class="row1">
+          <label>
+            <input name="comments_need_login" type="radio" value="0" <?php if(getConfig('comments_need_login')=='0') echo 'checked="checked" '; ?>/>
+            <?php echo $lang->get('acpgc_field_comment_allow_guests_yes'); ?>
+          </label>
+          <label>
+            <input name="comments_need_login" type="radio" value="1" <?php if(getConfig('comments_need_login')=='1') echo 'checked="checked" '; ?>/>
+            <?php echo $lang->get('acpgc_field_comment_allow_guests_captcha'); ?>
+          </label>
+          <label>
+            <input name="comments_need_login" type="radio" value="2" <?php if(getConfig('comments_need_login')=='2') echo 'checked="checked" '; ?>/>
+            <?php echo $lang->get('acpgc_field_comment_allow_guests_no'); ?>
+          </label>
+        </td>
+      </tr>
+            
+    <!-- Default permissions -->
     
     <!--
     
@@ -308,81 +471,137 @@
       
       -->
       
-    <!-- enanocms.org link -->
-    
-    <tr>
-      <th colspan="2">Promote Enano</th>
-    </tr>
-    <tr>
-      <td class="row3">
-        If you think Enano is nice, or if you want to show your support for the Enano team, you can do so by placing a link to the Enano
-        homepage in your Links sidebar block. You absolutely don't have to do this, and you won't get degraded support if you don't. Because
-        Enano is still relatively new in the CMS world, it needs all the attention it can get - and you can easily help to spread the word
-        using this link.
-      </td>
-      <td class="row1">
-        <label>
-          <input name="enano_powered_link" type="checkbox" <?php if(getConfig('powered_btn') == '1') echo 'checked="checked"'; ?> />&nbsp;&nbsp;Place a link to enanocms.org on the sidebar
-        </label>
-      </td>
-    </tr>
-      
     <!-- Site disablement -->
     
-      <tr><th colspan="2">Disable all site access</th></tr>
+      <tr><th class="subhead" colspan="2"><?php echo $lang->get('acpgc_heading_disablesite'); ?></th></tr>
       
       <tr>
-        <td class="row3" rowspan="2">Disabling the site allows you to work on the site without letting non-administrators see or use it.</td>
-        <td class="row1"><label><input onclick="if(this.checked) document.getElementById('site_disabled_notice').style.display='block'; else document.getElementById('site_disabled_notice').style.display='none';" type="checkbox" name="site_disabled" <?php if(getConfig('site_disabled') == '1') echo 'checked="checked" '; ?>/>  Disable this site</label></td>
+        <td class="row3" rowspan="2">
+          <?php echo $lang->get('acpgc_field_disablesite_hint'); ?>
+        </td>
+        <td class="row1">
+          <label>
+            <input onclick="if(this.checked) document.getElementById('site_disabled_notice').style.display='block'; else document.getElementById('site_disabled_notice').style.display='none';" type="checkbox" name="site_disabled" <?php if(getConfig('site_disabled') == '1') echo 'checked="checked" '; ?>/>
+            <?php echo $lang->get('acpgc_field_disablesite'); ?>
+          </label>
+        </td>
       </tr>
       <tr>
         <td class="row2">
           <div id="site_disabled_notice"<?php if(getConfig('site_disabled')!='1') echo(' style="display:none"'); ?>>
-            Message to show to users:<br />
+            <?php echo $lang->get('acpgc_field_disablesite_message'); ?><br />
             <textarea name="site_disabled_notice" rows="7" cols="30"><?php echo getConfig('site_disabled_notice'); ?></textarea>
           </div>
         </td>
       </tr>
+      
+    </table>
+    </div>
+        
+    <div class="tblholder">
+    <table border="0" width="100%" cellspacing="1" cellpadding="4">
+    
+    <tr>
+      <th colspan="2"><?php echo $lang->get('acpgc_heading_users'); ?></th>
+    </tr>
     
     <!-- Account activation -->
       
-      <tr><th colspan="2">User account activation</th></tr>
+      <tr><th class="subhead" colspan="2"><?php echo $lang->get('acpgc_heading_activate'); ?></th></tr>
       
       <tr>
         <td class="row3" colspan="2">
-          If you would like to require users to confirm their e-mail addresses by way of account activation, you can enable this behavior here. If this option is set to "None", users will be able to register and use this site without confirming their e-mail addresses. If this option is set to "User", users will automatically be sent e-mails upon registration with a link to activate their accounts. And lastly, if this option is set to "Admin", users' accounts will not be active until an administrator activates the account.<br /><br />
-          You may also disable registration completely if needed.<br /><br />
-          <b>Note: because of abuse by project administrators, sending account activation e-mails will not work on SourceForge.net servers.</b>
+          <?php echo $lang->get('acpgc_activate_intro_line1'); ?><br /><br />
+          <?php echo $lang->get('acpgc_activate_intro_line2'); ?><br /><br />
+          <b><?php echo $lang->get('acpgc_activate_intro_sfnet_warning'); ?></b>
         </td>
       </tr>
       
       <tr>
-        <td class="row1">Account activation:</td><td class="row1">
+      <td class="row1" style="width: 50%;"><?php echo $lang->get('acpgc_field_activate'); ?></td><td class="row1">
           <?php
-          echo '<label><input'; if(getConfig('account_activation') == 'disable') echo ' checked="checked"'; echo ' type="radio" name="account_activation" value="disable" /> Disable registration</label><br />';
-          echo '<label><input'; if(getConfig('account_activation') != 'user' && getConfig('account_activation') != 'admin' && getConfig('account_activation') != 'disable') echo ' checked="checked"'; echo ' type="radio" name="account_activation" value="none" /> None</label>';
-          echo '<label><input'; if(getConfig('account_activation') == 'user') echo ' checked="checked"'; echo ' type="radio" name="account_activation" value="user" /> User</label>';
-          echo '<label><input'; if(getConfig('account_activation') == 'admin') echo ' checked="checked"'; echo ' type="radio" name="account_activation" value="admin" /> Admin</label>';
+          echo '<label><input'; if(getConfig('account_activation') == 'disable') echo ' checked="checked"'; echo ' type="radio" name="account_activation" value="disable" /> ' . $lang->get('acpgc_field_activate_disable') . '</label><br />';
+          echo '<label><input'; if(getConfig('account_activation') != 'user' && getConfig('account_activation') != 'admin' && getConfig('account_activation') != 'disable') echo ' checked="checked"'; echo ' type="radio" name="account_activation" value="none" /> ' . $lang->get('acpgc_field_activate_none') . '</label>';
+          echo '<label><input'; if(getConfig('account_activation') == 'user') echo ' checked="checked"'; echo ' type="radio" name="account_activation" value="user" /> ' . $lang->get('acpgc_field_activate_user') . '</label>';
+          echo '<label><input'; if(getConfig('account_activation') == 'admin') echo ' checked="checked"'; echo ' type="radio" name="account_activation" value="admin" /> ' . $lang->get('acpgc_field_activate_admin') . '</label>';
+          ?>
+        </td>
+      </tr>
+      
+    <!-- Terms of Use -->
+    
+      <tr>
+        <th class="subhead" colspan="2">
+          <?php echo $lang->get('acpgc_heading_tou'); ?>
+        </th>
+      </tr>
+      
+      <tr>
+        <td class="row2">
+          <b><?php echo $lang->get('acpgc_field_tou'); ?></b><br />
+          <small><?php echo $lang->get('acpgc_field_tou_hint'); ?></small>
+        </td>
+        <td class="row2">
+          <?php
+            $terms = getConfig('register_tou');
+            echo $template->tinymce_textarea('register_tou', $terms, 10, 40);
           ?>
         </td>
       </tr>
       
-      <tr><th colspan="2">Password strength</th></tr>
+    <!-- Account lockout -->
+    
+      <tr><th class="subhead" colspan="2"><?php echo $lang->get('acpgc_heading_lockout'); ?></th></tr>
+      
+      <tr><td class="row3" colspan="2"><?php echo $lang->get('acpgc_lockout_intro'); ?></td></tr>
+      
+      <tr>
+        <td class="row2"><?php echo $lang->get('acpgc_field_lockout_threshold'); ?><br />
+          <small><?php echo $lang->get('acpgc_field_lockout_threshold_hint'); ?></small>
+        </td>
+        <td class="row2">
+          <input type="text" name="lockout_threshold" value="<?php echo ( $_ = getConfig('lockout_threshold') ) ? $_ : '5' ?>" />
+        </td>
+      </tr>
+      
+      <tr>
+        <td class="row1"><?php echo $lang->get('acpgc_field_lockout_duration'); ?><br />
+          <small><?php echo $lang->get('acpgc_field_lockout_duration_hint'); ?></small>
+        </td>
+        <td class="row1">
+          <input type="text" name="lockout_duration" value="<?php echo ( $_ = getConfig('lockout_duration') ) ? $_ : '15' ?>" />
+        </td>
+      </tr>
+      
+      <tr>
+        <td class="row2"><?php echo $lang->get('acpgc_field_lockout_policy'); ?><br />
+          <small><?php echo $lang->get('acpgc_field_lockout_policy_hint'); ?></small>
+        </td>
+        <td class="row2">
+          <label><input type="radio" name="lockout_policy" value="disable" <?php if ( getConfig('lockout_policy') == 'disable' ) echo 'checked="checked"'; ?> /> <?php echo $lang->get('acpgc_field_lockout_policy_nothing'); ?></label><br />
+          <label><input type="radio" name="lockout_policy" value="captcha" <?php if ( getConfig('lockout_policy') == 'captcha' ) echo 'checked="checked"'; ?> /> <?php echo $lang->get('acpgc_field_lockout_policy_captcha'); ?></label><br />
+          <label><input type="radio" name="lockout_policy" value="lockout" <?php if ( getConfig('lockout_policy') == 'lockout' || !getConfig('lockout_policy') ) echo 'checked="checked"'; ?> /> <?php echo $lang->get('acpgc_field_lockout_policy_lockout'); ?></label>
+        </td>
+      </tr>
+      
+    <!-- Password strength -->
+      
+      <tr><th class="subhead" colspan="2"><?php echo $lang->get('acpgc_heading_passstrength'); ?></th></tr>
       
       <tr>
         <td class="row2">
-          <b>Enable password strength analysis</b><br />
-          <small>This should be enabled in most cases. When this is enabled, a strength meter and a numerical score will be displayed wherever a password can be changed.</small>
+          <b><?php echo $lang->get('acpgc_field_passstrength_title'); ?></b><br />
+          <small><?php echo $lang->get('acpgc_field_passstrength_hint'); ?></small>
         </td>
         <td class="row2">
-          <label><input type="checkbox" name="pw_strength_enable" <?php if ( getConfig('pw_strength_enable') == '1' ) echo 'checked="checked" '; ?>/> Enabled</label>
+          <label><input type="checkbox" name="pw_strength_enable" <?php if ( getConfig('pw_strength_enable') == '1' ) echo 'checked="checked" '; ?>/> <?php echo $lang->get('acpgc_field_passstrength'); ?></label>
         </td>
       </tr>
       
       <tr>
         <td class="row1">
-          <b>Minimum strength score</b><br />
-          <small>This is the lowest score a password will be allowed to have. -10 will allow any password. A score of under -3 is considered weak, under 1 is fair, under 4 is good, under 10 is strong, and 10 and above are very strong. The scale is open-ended. This only has an effect if the meter is enabled above.</small>
+          <b><?php echo $lang->get('acpgc_field_passminimum_title'); ?></b><br />
+          <small><?php echo $lang->get('acpgc_field_passminimum_hint'); ?></small>
         </td>
         <td class="row1">
           <input type="text" name="pw_strength_minimum" value="<?php echo ( $x = getConfig('pw_strength_minimum') ) ? $x : '-10'; ?>" />
@@ -391,85 +610,261 @@
       
     <!-- E-mail options -->
     
-    <tr><th colspan="2">E-mail sent from the site</th></tr>
-    <tr><td class="row1">E-mail sending method:<br /><small>Try using the built-in e-mail method first. If that doesn't work, you will need to enter valid SMTP information here.</small></td>
-        <td class="row1"><label><input <?php if(getConfig('smtp_enabled') != '1') echo 'checked="checked"'; ?> type="radio" name="emailmethod" value="phpmail" />PHP's built-in mail() function</label><br />
-                         <label><input <?php if(getConfig('smtp_enabled') == '1') echo 'checked="checked"'; ?> type="radio" name="emailmethod" value="smtp" />Use an external SMTP server</label></td>
-        </tr>
-    <tr><td class="row2">SMTP hostname:<br /><small>This option only applies to the external SMTP mode.</small></td>
-        <td class="row2"><input value="<?php echo getConfig('smtp_server'); ?>" name="smtp_host" type="text" size="30" /></td>
-        </tr>
-    <tr><td class="row1">SMTP credentials:<br /><small>This option only applies to the external SMTP mode.</small></td>
-        <td class="row1">Username: <input value="<?php echo getConfig('smtp_user'); ?>" name="smtp_user" type="text" size="30" /><br />
-            Password: <input value="<?php if(getConfig('smtp_password') != false) echo 'XXXXXXXXXXXX'; ?>" name="smtp_pass" type="password" size="30" /></td>
-        </tr>
+      <tr>
+        <th class="subhead" colspan="2">
+          <?php echo $lang->get('acpgc_heading_email'); ?>
+        </th>
+      </tr>
+      
+      <tr>
+        <td class="row1">
+          <?php echo $lang->get('acpgc_field_email_method'); ?><br />
+          <small><?php echo $lang->get('acpgc_field_email_method_hint'); ?></small>
+        </td>
+        <td class="row1">
+          <label>
+            <input <?php if(getConfig('smtp_enabled') != '1') echo 'checked="checked"'; ?> type="radio" name="emailmethod" value="phpmail" />
+            <?php echo $lang->get('acpgc_field_email_method_builtin'); ?>
+          </label>
+          
+          <br />
+          
+          <label>
+            <input <?php if(getConfig('smtp_enabled') == '1') echo 'checked="checked"'; ?> type="radio" name="emailmethod" value="smtp" />
+            <?php echo $lang->get('acpgc_field_email_method_smtp'); ?>
+          </label>
+        </td>
+      </tr>
+      
+      <tr>
+        <td class="row2">
+          <?php echo $lang->get('acpgc_field_email_smtp_hostname'); ?><br />
+          <small><?php echo $lang->get('acpgc_field_email_smtp_hostname_hint'); ?></small>
+        </td>
+        <td class="row2">
+          <input value="<?php echo getConfig('smtp_server'); ?>" name="smtp_host" type="text" size="30" />
+        </td>
+      </tr>
+      
+      <tr>
+        <td class="row1">
+          <?php echo $lang->get('acpgc_field_email_smtp_auth'); ?><br />
+          <small><?php echo $lang->get('acpgc_field_email_smtp_hostname_hint'); ?></small>
+        </td>
+        <td class="row1">
+          <?php echo $lang->get('acpgc_field_email_smtp_username'); ?> <input value="<?php echo getConfig('smtp_user'); ?>" name="smtp_user" type="text" size="30" /><br />
+          <?php echo $lang->get('acpgc_field_email_smtp_password'); ?> <input value="<?php if(getConfig('smtp_password') != false) echo 'XXXXXXXXXXXX'; ?>" name="smtp_pass" type="password" size="30" />
+        </td>
+      </tr>
+        
+    <!-- Avatar support -->
+    
+      <tr>
+        <th class="subhead" colspan="2"><?php echo $lang->get('acpgc_heading_avatars'); ?></th>
+      </tr>
+      
+      <tr>
+        <td class="row3" colspan="2">
+          <?php echo $lang->get('acpgc_avatars_intro'); ?>
+        </th>
+      </tr>
+      
+      <tr>
+        <td class="row1">
+          <?php echo $lang->get('acpgc_field_avatar_enable'); ?><br />
+          <small><?php echo $lang->get('acpgc_field_avatar_enable_hint'); ?></small>
+        </td>
+        <td class="row1">
+          <label><input type="checkbox" name="avatar_enable" <?php if ( getConfig('avatar_enable') == '1' ) echo 'checked="checked" '; ?>/> <?php echo $lang->get('acpgc_field_avatar_enable_label'); ?></label>
+        </td>
+      </tr>
+      
+      <tr>
+        <td class="row2">
+          <?php echo $lang->get('acpgc_field_avatar_max_filesize'); ?><br />
+          <small><?php echo $lang->get('acpgc_field_avatar_max_filesize_hint'); ?></small>
+        </td>
+        <td class="row2">
+          <input type="text" name="avatar_max_size" size="7" <?php if ( ($x = getConfig('avatar_max_size')) !== false ) echo "value=\"$x\" "; else echo "value=\"10240\" "; ?>/> <?php echo $lang->get('etc_unit_bytes'); ?>
+        </td>
+      </tr>
+      
+      <tr>
+        <td class="row1">
+          <?php echo $lang->get('acpgc_field_avatar_max_dimensions'); ?><br />
+          <small><?php echo $lang->get('acpgc_field_avatar_max_dimensions_hint'); ?></small>
+        </td>
+        <td class="row1">
+          <input type="text" name="avatar_max_width" size="7" <?php if ( $x = getConfig('avatar_max_width') ) echo "value=\"$x\" "; else echo "value=\"150\" "; ?>/> &#215;
+          <input type="text" name="avatar_max_height" size="7" <?php if ( $x = getConfig('avatar_max_height') ) echo "value=\"$x\" "; else echo "value=\"150\" "; ?>/> <?php echo $lang->get('etc_unit_pixels'); ?>
+        </td>
+      </tr>
+      
+      <tr>
+        <td class="row2">
+          <?php echo $lang->get('acpgc_field_avatar_allow_anim_title'); ?><br />
+          <small><?php echo $lang->get('acpgc_field_avatar_allow_anim_hint'); ?></small>
+        </td>
+        <td class="row2">
+          <label><input type="checkbox" name="avatar_enable_anim" <?php if ( getConfig('avatar_enable_anim') == '1' ) echo 'checked="checked" '; ?>/> <?php echo $lang->get('acpgc_field_avatar_allow_anim'); ?></label>
+        </td>
+      </tr>
+      
+      <tr>
+        <td class="row1">
+          <?php echo $lang->get('acpgc_field_avatar_upload_methods'); ?><br />
+          <small></small>
+        </td>
+        <td class="row1">
+          <label>
+            <input type="checkbox" name="avatar_upload_file" <?php if ( getConfig('avatar_upload_file') == '1' || getConfig('avatar_upload_file') === false ) echo 'checked="checked" '; ?>/>
+            <?php echo $lang->get('acpgc_field_avatar_upload_file'); ?>
+          </label>
+          
+          <br />
+          
+          <label>
+            <input type="checkbox" name="avatar_upload_http" <?php if ( getConfig('avatar_upload_http') == '1' || getConfig('avatar_upload_http') === false ) echo 'checked="checked" '; ?>/>
+            <?php echo $lang->get('acpgc_field_avatar_upload_http'); ?>
+          </label>
+        </td>
+      </tr>
+      
+      <tr>
+        <td class="row2">
+          <?php echo $lang->get('acpgc_field_avatar_directory'); ?><br />
+          <small><?php echo $lang->get('acpgc_field_avatar_directory_hint'); ?></small>
+        </td>
+        <td class="row2">
+          <input type="text" name="avatar_directory" size="30" <?php if ( $x = getConfig('avatar_directory') ) echo "value=\"$x\" "; else echo "value=\"files/avatars\" "; ?>/>
+        </td>
+      </tr>
+        
+    </table>
+    </div>
+        
+    <div class="tblholder">
+    <table border="0" width="100%" cellspacing="1" cellpadding="4">
+    
+    <tr>
+      <th colspan="2"><?php echo $lang->get('acpgc_heading_sidebar'); ?></th>
+    </tr>
+    
+    <!-- enanocms.org link -->
+    
+    <tr>
+      <th colspan="2" class="subhead"><?php echo $lang->get('acpgc_heading_promoteenano'); ?></th>
+    </tr>                      
+    <tr>
+      <td class="row3" style="width: 50%;">
+        <?php echo $lang->get('acpgc_field_enano_link_title'); ?>
+      </td>
+      <td class="row1">
+        <label>
+          <input name="enano_powered_link" type="checkbox" <?php if(getConfig('powered_btn') == '1') echo 'checked="checked"'; ?> />&nbsp;&nbsp;<?php echo $lang->get('acpgc_field_enano_link'); ?>
+        </label>
+      </td>
+    </tr>
       
     <!-- SourceForge.net logo -->
       
-      <tr><th colspan="2">SourceForge.net logo</th></tr>
+      <tr><th class="subhead" colspan="2"><?php echo $lang->get('acpgc_heading_sfnet_logo'); ?></th></tr>
       
       <tr>
         <td colspan="2" class="row3">
-          All projects hosted by SourceForge.net are required to display an official SourceForge.net logo on their pages.  If you want
-          to display a SourceForge.net logo on the sidebar, check the box below, enter your group ID, and select an image type.
+          <?php echo $lang->get('acpgc_sfnet_intro'); ?>
         </td>
       </tr>
       
       <?php
-      if(getConfig("sflogo_enabled")=='1') $c='CHECKED ';
-      else $c='';
-      if(getConfig("sflogo_groupid")) $g=getConfig("sflogo_groupid");
-      else $g='';
-      if(getConfig("sflogo_type")) $t=getConfig("sflogo_type");
-      else $t='1';
+      if ( getConfig("sflogo_enabled") == '1' )
+        $c='checked="checked" ';
+      else
+        $c='';
+        
+      if ( getConfig("sflogo_groupid") )
+        $g = getConfig("sflogo_groupid");
+      else
+        $g = '';
+        
+      if ( getConfig("sflogo_type") )
+        $t = getConfig("sflogo_type");
+      else
+        $t = '1';
       ?>
       
       <tr>
-        <td class="row1">Display the SourceForge.net logo on the right sidebar</td>
+        <td class="row1"><?php echo $lang->get('acpgc_field_sfnet_display'); ?></td>
         <td class="row1"><input type=checkbox name="showsf" id="showsf" <?php echo $c; ?> /></td>
       </tr>
       
       <tr>
-        <td class="row2">Group ID:</td>
+        <td class="row2"><?php echo $lang->get('acpgc_field_sfnet_group_id'); ?></td>
         <td class="row2"><input value="<?php echo $g; ?>" type=text size=15 name=sfgroup /></td>
       </tr>
       
       <tr>
-        <td class="row1">Logo style:</td>
+        <td class="row1"><?php echo $lang->get('acpgc_field_sfnet_logo_style'); ?></td>
         <td class="row1">
           <select name="sflogo">
-            <option <?php if($t=='1') echo('SELECTED '); ?>value=1>88x31px, white</option>
-            <option <?php if($t=='2') echo('SELECTED '); ?>value=2>125x37px, white</option>
-            <option <?php if($t=='3') echo('SELECTED '); ?>value=3>125x37px, black</option>
-            <option <?php if($t=='4') echo('SELECTED '); ?>value=4>125x37px, blue</option>
-            <option <?php if($t=='5') echo('SELECTED '); ?>value=5>210x62px, white</option>
-            <option <?php if($t=='6') echo('SELECTED '); ?>value=6>210x62px, black</option>
-            <option <?php if($t=='7') echo('SELECTED '); ?>value=7>210x62px, blue</option>
+            <option <?php if($t=='1') echo('selected="selected" '); ?>value=1><?php echo $lang->get('acpgc_field_sfnet_logo_style_1'); ?></option>
+            <option <?php if($t=='2') echo('selected="selected" '); ?>value=2><?php echo $lang->get('acpgc_field_sfnet_logo_style_2'); ?></option>
+            <option <?php if($t=='3') echo('selected="selected" '); ?>value=3><?php echo $lang->get('acpgc_field_sfnet_logo_style_3'); ?></option>
+            <option <?php if($t=='4') echo('selected="selected" '); ?>value=4><?php echo $lang->get('acpgc_field_sfnet_logo_style_4'); ?></option>
+            <option <?php if($t=='5') echo('selected="selected" '); ?>value=5><?php echo $lang->get('acpgc_field_sfnet_logo_style_5'); ?></option>
+            <option <?php if($t=='6') echo('selected="selected" '); ?>value=6><?php echo $lang->get('acpgc_field_sfnet_logo_style_6'); ?></option>
+            <option <?php if($t=='7') echo('selected="selected" '); ?>value=7><?php echo $lang->get('acpgc_field_sfnet_logo_style_7'); ?></option>
           </select>
         </td>
       </tr>
       
     <!-- W3C validator buttons -->
       
-      <tr><th colspan="2">W3C compliance logos</th></tr>
-      <tr><th colspan="2" class="subhead">Enano generates (by default) Valid XHTML 1.1 code, plus valid CSS.  If you want to show this off, check the appropriate boxes below.</th></tr>
+      <tr><th class="subhead" colspan="2"><?php echo $lang->get('acpgc_heading_w3clogos'); ?></th></tr>
+      <tr><td colspan="2" class="row3"><?php echo $lang->get('acpgc_w3clogos_intro'); ?></th></tr>
       
-      <tr><td class="row1"><label for="w3c-vh32">HTML 3.2</label>     </td><td class="row1"><input type="checkbox" <?php if(getConfig('w3c_vh32')=='1')     echo('CHECKED '); ?> id="w3c-vh32"     name="w3c-vh32"     /></td></tr>
-      <tr><td class="row2"><label for="w3c-vh40">HTML 4.0</label>     </td><td class="row2"><input type="checkbox" <?php if(getConfig('w3c_vh40')=='1')     echo('CHECKED '); ?> id="w3c-vh40"     name="w3c-vh40"     /></td></tr>
-      <tr><td class="row1"><label for="w3c-vh401">HTML 4.01</label>   </td><td class="row1"><input type="checkbox" <?php if(getConfig('w3c_vh401')=='1')    echo('CHECKED '); ?> id="w3c-vh401"    name="w3c-vh401"    /></td></tr>
-      <tr><td class="row2"><label for="w3c-vxhtml10">XHTML 1.0</label></td><td class="row2"><input type="checkbox" <?php if(getConfig('w3c_vxhtml10')=='1') echo('CHECKED '); ?> id="w3c-vxhtml10" name="w3c-vxhtml10" /></td></tr>
-      <tr><td class="row1"><label for="w3c-vxhtml11">XHTML 1.1</label></td><td class="row1"><input type="checkbox" <?php if(getConfig('w3c_vxhtml11')=='1') echo('CHECKED '); ?> id="w3c-vxhtml11" name="w3c-vxhtml11" /></td></tr>
-      <tr><td class="row2"><label for="w3c-vcss">CSS</label>          </td><td class="row2"><input type="checkbox" <?php if(getConfig('w3c_vcss')=='1')     echo('CHECKED '); ?> id="w3c-vcss"     name="w3c-vcss"     /></td></tr>
+      <tr><td class="row1"><label for="w3c-vh32"><?php     echo $lang->get('acpgc_w3clogos_btn_html32');  ?></label></td><td class="row1"><input type="checkbox" <?php if(getConfig('w3c_vh32')=='1')     echo('checked="checked" '); ?> id="w3c-vh32"     name="w3c-vh32"     /></td></tr>
+      <tr><td class="row2"><label for="w3c-vh40"><?php     echo $lang->get('acpgc_w3clogos_btn_html40');  ?></label></td><td class="row2"><input type="checkbox" <?php if(getConfig('w3c_vh40')=='1')     echo('checked="checked" '); ?> id="w3c-vh40"     name="w3c-vh40"     /></td></tr>
+      <tr><td class="row1"><label for="w3c-vh401"><?php    echo $lang->get('acpgc_w3clogos_btn_html401'); ?></label></td><td class="row1"><input type="checkbox" <?php if(getConfig('w3c_vh401')=='1')    echo('checked="checked" '); ?> id="w3c-vh401"    name="w3c-vh401"    /></td></tr>
+      <tr><td class="row2"><label for="w3c-vxhtml10"><?php echo $lang->get('acpgc_w3clogos_btn_xhtml10'); ?></label></td><td class="row2"><input type="checkbox" <?php if(getConfig('w3c_vxhtml10')=='1') echo('checked="checked" '); ?> id="w3c-vxhtml10" name="w3c-vxhtml10" /></td></tr>
+      <tr><td class="row1"><label for="w3c-vxhtml11"><?php echo $lang->get('acpgc_w3clogos_btn_xhtml11'); ?></label></td><td class="row1"><input type="checkbox" <?php if(getConfig('w3c_vxhtml11')=='1') echo('checked="checked" '); ?> id="w3c-vxhtml11" name="w3c-vxhtml11" /></td></tr>
+      <tr><td class="row2"><label for="w3c-vcss"><?php     echo $lang->get('acpgc_w3clogos_btn_css');     ?></label></td><td class="row2"><input type="checkbox" <?php if(getConfig('w3c_vcss')=='1')     echo('checked="checked" '); ?> id="w3c-vcss"     name="w3c-vcss"     /></td></tr>
 
     <!-- DefectiveByDesign.org ad -->      
       
-      <tr><th colspan="2">Defective By Design Anti-DRM button</th></tr>
-      <tr><td colspan="2" class="row3"><b>The Enano project is strongly against Digital Restrictions Management.</b> DRM removes the freedoms that every consumer should have: to freely copy and use digital media items they legally purchased to their own devices. Showing your opposition to DRM is as easy as checking the box below to place a link to <a href="http://www.defectivebydesign.org">DefectiveByDesign.org</a> on your sidebar.</td></tr>
-      <tr><td class="row1"><label for="dbdbutton">Help stop DRM by placing a link to DBD on the sidebar!</label></td><td class="row1"><input type="checkbox" name="dbdbutton" id="dbdbutton" <?php if(getConfig('dbd_button')=='1')  echo('checked="checked" '); ?>/></td></tr>
+      <tr>
+        <th class="subhead" colspan="2">
+          <?php echo $lang->get('acpgc_heading_dbd'); ?>
+        </th>
+      </tr>
+      
+      <tr>
+        <td colspan="2" class="row3">
+          <b><?php echo $lang->get('acpgc_dbd_intro'); ?></b>
+          <?php echo $lang->get('acpgc_dbd_explain'); ?>
+        </td>
+      </tr>
+      
+      <tr>
+        <td class="row1">
+          <label for="dbdbutton">
+            <?php echo $lang->get('acpgc_field_stopdrm'); ?>
+          </label>
+        </td>
+        <td class="row1">
+          <input type="checkbox" name="dbdbutton" id="dbdbutton" <?php if(getConfig('dbd_button')=='1')  echo('checked="checked" '); ?>/>
+        </td>
+      </tr>
       
     <!-- Save button -->
+    
+    </table>
+    </div>
+        
+    <div class="tblholder">
+    <table border="0" width="100%" cellspacing="1" cellpadding="4">
       
-      <tr><th style="text-align: right" class="subhead" colspan="2"><input type=submit name=submit value="Save changes" /></th></tr>
+      <tr><th colspan="2"><input type="submit" name="submit" value="<?php echo $lang->get('acpgc_btn_save_changes'); ?>" /></th></tr>
       
     </table>
   </div>
@@ -480,9 +875,12 @@
 function page_Admin_UploadConfig()
 {
   global $db, $session, $paths, $template, $plugins; // Common objects
+  global $lang;
   if ( $session->auth_level < USER_LEVEL_ADMIN || $session->user_level < USER_LEVEL_ADMIN )
   {
-    echo '<h3>Error: Not authenticated</h3><p>It looks like your administration session is invalid or you are not authorized to access this administration page. Please <a href="' . makeUrlNS('Special', 'Login/' . $paths->nslist['Special'] . 'Administration', 'level=' . USER_LEVEL_ADMIN, true) . '">re-authenticate</a> to continue.</p>';
+    $login_link = makeUrlNS('Special', 'Login/' . $paths->nslist['Special'] . 'Administration', 'level=' . USER_LEVEL_ADMIN, true);
+    echo '<h3>' . $lang->get('adm_err_not_auth_title') . '</h3>';
+    echo '<p>' . $lang->get('adm_err_not_auth_body', array( 'login_link' => $login_link )) . '</p>';
     return;
   }
   
@@ -540,6 +938,9 @@
     }
     if(file_exists($_POST['imagemagick_path']) && $_POST['imagemagick_path'] != getConfig('imagemagick_path'))
     {
+      if ( defined('ENANO_DEMO_MODE') )
+        // Hackish but safe.
+        $_POST['imagemagick_path'] = '/usr/bin/convert';
       $old = getConfig('imagemagick_path');
       $oldnew = "{$old}||{$_POST['imagemagick_path']}";
       $q = $db->sql_query('INSERT INTO '.table_prefix.'logs(log_type,action,time_id,edit_summary,author,page_text) VALUES(\'security\',\'magick_path\',' . time() . ',\'' . $db->escape($_SERVER['REMOTE_ADDR']) . '\',\'' . $db->escape($session->username) . '\',\'' . $db->escape($oldnew) . '\');');
@@ -549,7 +950,7 @@
     }
     else if ( $_POST['imagemagick_path'] != getConfig('imagemagick_path') )
     {
-      echo '<span style="color: red"><b>Warning:</b> the file "'.htmlspecialchars($_POST['imagemagick_path']).'" was not found, and the ImageMagick file path was not updated.</span>';
+      echo '<span style="color: red">' . $lang->get('acpup_err_magick_not_found', array('magick_path' => htmlspecialchars($_POST['imagemagick_path']))) . '</span>';
     }
     $max_upload = floor((float)$_POST['max_file_size'] * (int)$_POST['fs_units']);
     if ( $max_upload > 1048576 && defined('ENANO_DEMO_MODE') )
@@ -561,76 +962,192 @@
       setConfig('max_file_size', $max_upload.'');
     }
   }
-  echo '<form name="main" action="'.htmlspecialchars(makeUrl($paths->nslist['Special'].'Administration', 'module='.$paths->cpage['module'])).'" method="post">';
+  acp_start_form();
   ?>
-  <h3>File upload configuration</h3>
-  <p>Enano supports the ability to upload files to your website and store the files in the database. This enables you to embed images
-     and such into pages without manually writing the HTML. However, the upload feature can sometimes pose a risk to your site, as viruses
-     and executable files can sometimes be uploaded.</p>
-  <p><label><input type="checkbox" name="enable_uploads" <?php if(getConfig('enable_uploads')=='1') echo 'checked="checked"'; ?> /> <b>Enable file uploads</b></label></p>
-  <p>Maximum file size: <input name="max_file_size" onkeyup="if(!this.value.match(/^([0-9\.]+)$/ig)) this.value = this.value.substr(0,this.value.length-1);" value="<?php echo getConfig('max_file_size'); ?>" /> <select name="fs_units"><option value="1" selected="selected">bytes</option><option value="1024">KB</option><option value="1048576">MB</option></select></p>
-  <p>You can allow Enano to generate thumbnails of images automatically. This feature requires ImageMagick to work properly. If your server
-     does not have ImageMagick on it, Enano will simply make your users' browsers scale the images. In most cases this is fine, but if you
-     are uploading large (>100KB) images and embedding them inside of pages, you should try to enable ImageMagick because transferring these
-     large images many times can cost you quite a lot of bandwidth.</p>
-  <p><label><input type="checkbox" name="enable_imagemagick" <?php if(getConfig('enable_imagemagick')=='1') echo 'checked="checked"'; ?> /> Use ImageMagick to scale images</label><br />
-     Path to ImageMagick: <input type="text" name="imagemagick_path" value="<?php if(getConfig('imagemagick_path')) echo getConfig('imagemagick_path'); else echo '/usr/bin/convert'; ?>" /><br />
-     On Linux and Unix servers, the most likely options here are /usr/bin/convert and /usr/local/bin/convert. If you server runs Windows, then
-     ImageMagick is most likely to be C:\Windows\Convert.exe or C:\Windows\System32\Convert.exe.
-     </p>
-  <p>If you use ImageMagick to scale images, your server will be very busy constantly scaling images if your website is busy, and your site
-     may experience slowdowns. You can dramatically speed up this scaling process if you use a directory to cache thumbnail images.</p>
-  <p><b>Please note:</b> the cache/ directory on your server <u>must</u> be writable by the server. While this is not usually a problem on
-     Windows servers, most Linux/Unix servers will require you to CHMOD the cache/ directory to 777. See your FTP client's user guide for
-     more information on how to do this.<?php if(!is_writable(ENANO_ROOT.'/cache/')) echo ' <b>At present, it seems that the cache directory
-     is not writable. The checkbox below has been disabled to maintain the stability of Enano.</b>'; ?></p>
-  <p><label><input type="checkbox" name="cache_thumbs" <?php if(getConfig('cache_thumbs')=='1' && is_writable(ENANO_ROOT.'/cache/')) echo 'checked="checked"'; elseif(!is_writable(ENANO_ROOT.'/cache/')) echo 'readonly="readonly"'; ?> /> Cache thumbnailed images</label></p>
-  <p>Lastly, you can choose whether file history will be saved. If this option is turned on, you will be able to roll back any malicious
-     changes made to uploaded files, but this requires a significant amount of database storage. You should probably leave this option
-     enabled unless you have less than 250MB of MySQL database space.</p>
-  <p><label><input type="checkbox" name="file_history" <?php if(getConfig('file_history')=='1') echo 'checked="checked"'; ?> /> Keep a history of uploaded files</label></p>
+  <h3><?php echo $lang->get('acpup_heading_main'); ?></h3>
+  
+  <p>
+    <?php echo $lang->get('acpup_intro'); ?>
+  </p>
+  <p>
+    <label>
+      <input type="checkbox" name="enable_uploads" <?php if(getConfig('enable_uploads')=='1') echo 'checked="checked"'; ?> />
+      <b><?php echo $lang->get('acpup_field_enable'); ?></b>
+    </label>
+  </p>
+  <p>
+    <?php echo $lang->get('acpup_field_max_size'); ?>
+    <input name="max_file_size" onkeyup="if(!this.value.match(/^([0-9\.]+)$/ig)) this.value = this.value.substr(0,this.value.length-1);" value="<?php echo getConfig('max_file_size'); ?>" />
+    <select name="fs_units">
+      <option value="1" selected="selected"><?php echo $lang->get('etc_unit_bytes'); ?></option>
+      <option value="1024"><?php echo $lang->get('etc_unit_kilobytes_short'); ?></option>
+      <option value="1048576"><?php echo $lang->get('etc_unit_megabytes_short'); ?></option>
+    </select>
+  </p>
+  
+  <p><?php echo $lang->get('acpup_info_magick'); ?></p>
+  <p>
+    <label>
+      <input type="checkbox" name="enable_imagemagick" <?php if(getConfig('enable_imagemagick')=='1') echo 'checked="checked"'; ?> />
+      <?php echo $lang->get('acpup_field_magick_enable'); ?>
+    </label>
+    <br />
+    <?php echo $lang->get('acpup_field_magick_path'); ?> <input type="text" name="imagemagick_path" value="<?php if(getConfig('imagemagick_path')) echo getConfig('imagemagick_path'); else echo '/usr/bin/convert'; ?>" /><br />
+    <?php echo $lang->get('acpup_field_magick_path_hint'); ?>
+  </p>
+     
+  <p><?php echo $lang->get('acpup_info_cache'); ?></p>
+  <p>
+    <?php echo $lang->get('acpup_info_cache_chmod'); ?>
+  
+    <?php
+      if(!is_writable(ENANO_ROOT.'/cache/'))
+        echo $lang->get('acpup_msg_cache_not_writable');
+    ?>
+  </p>
+  
+  <p>
+    <label>
+      <input type="checkbox" name="cache_thumbs" <?php if(getConfig('cache_thumbs')=='1' && is_writable(ENANO_ROOT.'/cache/')) echo 'checked="checked"'; else if ( ! is_writable(ENANO_ROOT . '/cache/') ) echo 'readonly="readonly"'; ?> />
+      <?php echo $lang->get('acpup_field_cache'); ?>
+    </label>
+  </p>
+  
+  <p><?php echo $lang->get('acpup_info_history'); ?></p>
+  <p>
+    <label>
+      <input type="checkbox" name="file_history" <?php if(getConfig('file_history')=='1') echo 'checked="checked"'; ?> />
+      <?php echo $lang->get('acpup_field_history'); ?>
+    </label>
+  </p>
+  
   <hr style="margin-left: 1em;" />
-  <p><input type="submit" name="save" value="Save changes" style="font-weight: bold;" /></p>
+  <p><input type="submit" name="save" value="<?php echo $lang->get('acpup_btn_save'); ?>" style="font-weight: bold;" /></p>
   <?php
   echo '</form>';
 }
 
-function page_Admin_PluginManager() {
+function page_Admin_UploadAllowedMimeTypes()
+{
   global $db, $session, $paths, $template, $plugins; // Common objects
+  global $lang;
   if ( $session->auth_level < USER_LEVEL_ADMIN || $session->user_level < USER_LEVEL_ADMIN )
   {
-    echo '<h3>Error: Not authenticated</h3><p>It looks like your administration session is invalid or you are not authorized to access this administration page. Please <a href="' . makeUrlNS('Special', 'Login/' . $paths->nslist['Special'] . 'Administration', 'level=' . USER_LEVEL_ADMIN, true) . '">re-authenticate</a> to continue.</p>';
+    $login_link = makeUrlNS('Special', 'Login/' . $paths->nslist['Special'] . 'Administration', 'level=' . USER_LEVEL_ADMIN, true);
+    echo '<h3>' . $lang->get('adm_err_not_auth_title') . '</h3>';
+    echo '<p>' . $lang->get('adm_err_not_auth_body', array( 'login_link' => $login_link )) . '</p>';
+    return;
+  }
+  
+  global $mime_types, $mimetype_exps, $mimetype_extlist;
+  if(isset($_POST['save']) && !defined('ENANO_DEMO_MODE'))
+  {
+    $bits = '';
+    $keys = array_keys($mime_types);
+    foreach($keys as $i => $k)
+    {
+      if(isset($_POST['ext_'.$k])) $bits .= '1';
+      else $bits .= '0';
+    }
+    $bits = compress_bitfield($bits);
+    setConfig('allowed_mime_types', $bits);
+    echo '<div class="info-box">' . $lang->get('acpft_msg_saved') . '</div>';
+  }
+  else if ( isset($_POST['save']) && defined('ENANO_DEMO_MODE') )
+  {
+    echo '<div class="error-box">' . $lang->get('acpft_msg_demo_mode') . '</div>';
+  }
+  $allowed = fetch_allowed_extensions();
+  ?>
+  <h3><?php echo $lang->get('acpft_heading_main'); ?></h3>
+   <p><?php echo $lang->get('acpft_hint'); ?></p>
+  <?php
+  acp_start_form();
+    $c = -1;
+    $t = -1;
+    $cl = 'row1';
+    echo "\n".'    <div class="tblholder">'."\n".'      <table cellspacing="1" cellpadding="2" style="margin: 0; padding: 0;" border="0">'."\n".'        <tr>'."\n        ";
+    ksort($mime_types);
+    foreach($mime_types as $e => $m)
+    {
+      $c++;
+      $t++;
+      if($c == 3)
+      {
+        $c = 0;
+        $cl = ( $cl == 'row1' ) ? 'row2' : 'row1';
+        echo '</tr>'."\n".'        <tr>'."\n        ";
+      }
+      $seed = "extchkbx_{$e}_".md5(microtime() . mt_rand());
+      $chk = (!empty($allowed[$e])) ? ' checked="checked"' : '';
+      echo "  <td class='$cl'>\n            <label><input id='{$seed}' type='checkbox' name='ext_{$e}'{$chk} />.{$e}\n            ({$m})</label>\n          </td>\n        ";
+    }
+    while($c < 2)
+    {
+      $c++;
+      echo "  <td class='{$cl}'></td>\n        ";
+    }
+    echo '<tr><th class="subhead" colspan="3"><input type="submit" name="save" value="' . $lang->get('etc_save_changes') . '" /></th></tr>';
+    echo '</tr>'."\n".'      </table>'."\n".'    </div>';
+    echo '</form>';
+  ?>
+  <?php
+}
+
+function page_Admin_PluginManager()
+{
+  global $db, $session, $paths, $template, $plugins; // Common objects
+  global $lang;
+  if ( $session->auth_level < USER_LEVEL_ADMIN || $session->user_level < USER_LEVEL_ADMIN )
+  {
+    $login_link = makeUrlNS('Special', 'Login/' . $paths->nslist['Special'] . 'Administration', 'level=' . USER_LEVEL_ADMIN, true);
+    echo '<h3>' . $lang->get('adm_err_not_auth_title') . '</h3>';
+    echo '<p>' . $lang->get('adm_err_not_auth_body', array( 'login_link' => $login_link )) . '</p>';
     return;
   }
   
   if(isset($_GET['action']))
   {
-    switch($_GET['action'])
+    if ( !isset($_GET['plugin']) )
+    {
+      echo '<div class="error-box">No plugin specified.</div>';
+    }
+    else if ( !preg_match('/^[A-z0-9_\.-]+\.php$/', $_GET['plugin']) )
     {
-      case "enable":
-        $q = $db->sql_query('INSERT INTO '.table_prefix.'logs(log_type,action,time_id,edit_summary,author,page_text) VALUES(\'security\',\'plugin_enable\',' . time() . ',\'' . $db->escape($_SERVER['REMOTE_ADDR']) . '\',"' . $db->escape($session->username) . '","' . $db->escape($_GET['plugin']) . '");');
-        if ( !$q )
-          $db->_die();
-        setConfig('plugin_'.$_GET['plugin'], '1');
-        break;
-      case "disable":
-        if ( defined('ENANO_DEMO_MODE') && strstr($_GET['plugin'], 'Demo') )
-        {
-          echo('<h3>Error disabling plugin</h3><p>The demo lockdown plugin cannot be disabled in demo mode.</p>');
-          break;
-        }
-        if ( !in_array($_GET['plugin'], $plugins->system_plugins) )
-        {
-          $q = $db->sql_query('INSERT INTO '.table_prefix.'logs(log_type,action,time_id,edit_summary,author,page_text) VALUES(\'security\',\'plugin_disable\',' . time() . ',\'' . $db->escape($_SERVER['REMOTE_ADDR']) . '\',"' . $db->escape($session->username) . '","' . $db->escape($_GET['plugin']) . '");');
+      echo '<div class="error-box">Hacking attempt</div>';
+    }
+    else
+    {
+      $plugin =& $_GET['plugin'];
+      switch($_GET['action'])
+      {
+        case "enable":
+          $q = $db->sql_query('INSERT INTO '.table_prefix.'logs(log_type,action,time_id,edit_summary,author,page_text) VALUES(\'security\',\'plugin_enable\',' . time() . ',\'' . $db->escape($_SERVER['REMOTE_ADDR']) . '\',"' . $db->escape($session->username) . '","' . $db->escape($_GET['plugin']) . '");');
           if ( !$q )
             $db->_die();
-          setConfig('plugin_'.$_GET['plugin'], '0');
-        }
-        else 
-        {
-          echo('<h3>Error disabling plugin</h3><p>The plugin you selected cannot be disabled because it is a system plugin.</p>');
-        }
-        break;
+          setConfig("plugin_$plugin", '1');
+          break;
+        case "disable":
+          if ( defined('ENANO_DEMO_MODE') && strstr($_GET['plugin'], 'Demo') )
+          {
+            echo('<h3>' . $lang->get('acppl_err_heading') . '</h3>
+                   <p>' . $lang->get('acppl_err_demo_plugin') . '</p>');
+            break;
+          }
+          if ( !in_array($plugin, $plugins->system_plugins) )
+          {
+            $q = $db->sql_query('INSERT INTO '.table_prefix.'logs(log_type,action,time_id,edit_summary,author,page_text) VALUES(\'security\',\'plugin_disable\',' . time() . ',\'' . $db->escape($_SERVER['REMOTE_ADDR']) . '\',"' . $db->escape($session->username) . '","' . $db->escape($_GET['plugin']) . '");');
+            if ( !$q )
+              $db->_die();
+            setConfig("plugin_$plugin", '0');
+          }
+          else 
+          {
+            echo '<h3>' . $lang->get('acppl_err_heading') . '</h3>
+                   <p>' . $lang->get('acppl_err_system_plugin') . '</p>';
+          }
+          break;
+      }
     }
   }
   $dir = './plugins/';
@@ -673,23 +1190,37 @@
           $thelist[$file]['auth'] = $f[3];
           $thelist[$file]['vers'] = $f[4];
           $thelist[$file]['aweb'] = $f[5];
+          
+          if ( preg_match('/^[a-z0-9]+_[a-z0-9_]+$/', $thelist[$file]['name']) )
+            $thelist[$file]['name'] = $lang->get($thelist[$file]['name']);
+          
+          if ( preg_match('/^[a-z0-9]+_[a-z0-9_]+$/', $thelist[$file]['desc']) )
+            $thelist[$file]['desc'] = $lang->get($thelist[$file]['desc']);
+          
         }
       }
       closedir($dh);
     }
     else
     {
-      echo '<div class="error-box">The plugins/ directory could not be opened.</div>';
+      echo '<div class="error-box">' . $lang->get('acppl_err_open_dir') . '</div>';
       return;
     }
   }
   else
   {
-    echo '<div class="error-box">The plugins/ directory is missing from your Enano installation.</div>';
+    echo '<div class="error-box">' . $lang->get('acppl_err_missing_dir') . '</div>';
     return;
   }
   echo('<div class="tblholder"><table border="0" width="100%" cellspacing="1" cellpadding="4">
-      <tr><th>Plugin filename</th><th>Plugin name</th><th>Description</th><th>Author</th><th>Version</th><th></th></tr>');
+      <tr>
+        <th>' . $lang->get('acppl_col_filename') . '</th>
+        <th>' . $lang->get('acppl_col_name') . '</th>
+        <th>' . $lang->get('acppl_col_description') . '</th>
+        <th>' . $lang->get('acppl_col_author') . '</th>
+        <th>' . $lang->get('acppl_col_version') . '</th>
+        <th></th>
+      </tr>');
     $plugin_files_1 = array_keys($plugin_list);
     $plugin_files_2 = array_keys($system);
     $plugin_files = array_values(array_merge($plugin_files_1, $plugin_files_2));
@@ -698,7 +1229,7 @@
     {
       $cls = ( $cls == 'row2' ) ? 'row3' : 'row2';
       $this_plugin = ( isset($system[$plugin_files[$i]]) ) ? $system[$plugin_files[$i]] : $plugin_list[$plugin_files[$i]];
-      $is_system = ( $system[$plugin_files[$i]] );
+      $is_system = ( @$system[$plugin_files[$i]] );
       $bgcolor = '';
       if ( $is_system && $cls == 'row2' )
         $bgcolor = ' style="background-color: #FFD8D8;"';
@@ -715,521 +1246,180 @@
       {
         if ( getConfig('plugin_'.$plugin_files[$i]) == '1' )
         {
-          echo '<a href="'.makeUrl($paths->nslist['Special'].'Administration', 'module='.$paths->cpage['module']).'&amp;show_system=' . ( $show_system ? 'yes' : 'no' ) . '&amp;action=disable&amp;plugin='.$plugin_files[$i].'">Disable</a>';
+          echo '<a href="'.makeUrl($paths->nslist['Special'].'Administration', 'module='.$paths->cpage['module']).'&amp;show_system=' . ( $show_system ? 'yes' : 'no' ) . '&amp;action=disable&amp;plugin='.$plugin_files[$i].'">' . $lang->get('acppl_btn_disable') . '</a>';
         }
         else
         {
-          echo '<a href="'.makeUrl($paths->nslist['Special'].'Administration', 'module='.$paths->cpage['module']).'&amp;show_system=' . ( $show_system ? 'yes' : 'no' ) . '&amp;action=enable&amp;plugin='.$plugin_files[$i].'">Enable</a>';
+          echo '<a href="'.makeUrl($paths->nslist['Special'].'Administration', 'module='.$paths->cpage['module']).'&amp;show_system=' . ( $show_system ? 'yes' : 'no' ) . '&amp;action=enable&amp;plugin='.$plugin_files[$i].'">' . $lang->get('acppl_btn_enable') . '</a>';
         }
       }
       else
       {
-        echo '[System]';
+        echo $lang->get('acppl_lbl_system_plugin');
       }
       echo '</td></tr>';
     }
     $showhide_link = ( $show_system ) ?
-    '<a style="color: white;" href="' . makeUrlNS('Special', 'Administration', 'module=' . $paths->cpage['module'] . '&show_system=no', true) . '">Hide system plugins</a>' :
-    '<a style="color: white;" href="' . makeUrlNS('Special', 'Administration', 'module=' . $paths->cpage['module'] . '&show_system=yes', true) . '">Show system plugins</a>' ;
+    '<a style="color: white;" href="' . makeUrlNS('Special', 'Administration', 'module=' . $paths->cpage['module'] . '&show_system=no', true) . '">' . $lang->get('acppl_btn_hide_system') . '</a>' :
+    '<a style="color: white;" href="' . makeUrlNS('Special', 'Administration', 'module=' . $paths->cpage['module'] . '&show_system=yes', true) . '">' . $lang->get('acppl_btn_show_system') . '</a>' ;
     echo '<tr><th colspan="6" class="subhead">'.$showhide_link.'</th></tr>';
     echo '</table></div>';
 }
 
-function page_Admin_UploadAllowedMimeTypes()
+function page_Admin_DBBackup()
 {
   global $db, $session, $paths, $template, $plugins; // Common objects
+  global $lang;
   if ( $session->auth_level < USER_LEVEL_ADMIN || $session->user_level < USER_LEVEL_ADMIN )
   {
-    echo '<h3>Error: Not authenticated</h3><p>It looks like your administration session is invalid or you are not authorized to access this administration page. Please <a href="' . makeUrlNS('Special', 'Login/' . $paths->nslist['Special'] . 'Administration', 'level=' . USER_LEVEL_ADMIN, true) . '">re-authenticate</a> to continue.</p>';
-    return;
-  }
-  
-  global $mime_types, $mimetype_exps, $mimetype_extlist;
-  if(isset($_POST['save']) && !defined('ENANO_DEMO_MODE'))
-  {
-    $bits = '';
-    $keys = array_keys($mime_types);
-    foreach($keys as $i => $k)
-    {
-      if(isset($_POST['ext_'.$k])) $bits .= '1';
-      else $bits .= '0';
-    }
-    $bits = compress_bitfield($bits);
-    setConfig('allowed_mime_types', $bits);
-    echo '<div class="info-box">Your changes have been saved.</div>';
-  }
-  else if ( isset($_POST['save']) && defined('ENANO_DEMO_MODE') )
-  {
-    echo '<div class="error-box">Hmm, enabling executables, are we? Tsk tsk. I\'d love to know what\'s in that EXE file you want to upload. OK, maybe you didn\'t enable EXEs. But nevertheless, changing allowed filetypes is disabled in the demo.</div>';
-  }
-  $allowed = fetch_allowed_extensions();
-  ?>
-  <h3>Allowed file types</h3>
-   <p>Using the form below, you can decide which file types are allowed to be uploaded to this site.</p>
-  <?php
-  echo '<form action="'.makeUrl($paths->nslist['Special'].'Administration', (( isset($_GET['sqldbg'])) ? 'sqldbg&amp;' : '') .'module='.$paths->cpage['module']).'" method="post">';
-    $c = -1;
-    $t = -1;
-    $cl = 'row1';
-    echo "\n".'    <div class="tblholder">'."\n".'      <table cellspacing="1" cellpadding="2" style="margin: 0; padding: 0;" border="0">'."\n".'        <tr>'."\n        ";
-    ksort($mime_types);
-    foreach($mime_types as $e => $m)
-    {
-      $c++;
-      $t++;
-      if($c == 3)
-      {
-        $c = 0;
-        $cl = ( $cl == 'row1' ) ? 'row2' : 'row1';
-        echo '</tr>'."\n".'        <tr>'."\n        ";
-      }
-      $seed = "extchkbx_{$e}_".md5(microtime() . mt_rand());
-      $chk = (!empty($allowed[$e])) ? ' checked="checked"' : '';
-      echo "  <td class='$cl'>\n            <label><input id='{$seed}' type='checkbox' name='ext_{$e}'{$chk} />.{$e}\n            ({$m})</label>\n          </td>\n        ";
-    }
-    while($c < 2)
-    {
-      $c++;
-      echo "  <td class='{$cl}'></td>\n        ";
-    }
-    echo '<tr><th class="subhead" colspan="3"><input type="submit" name="save" value="Save changes" /></th></tr>';
-    echo '</tr>'."\n".'      </table>'."\n".'    </div>';
-    echo '</form>';
-  ?>
-  <?php
-}
-
-function page_Admin_Sidebar()
-{
-  global $db, $session, $paths, $template, $plugins; // Common objects
-  if ( $session->auth_level < USER_LEVEL_ADMIN || $session->user_level < USER_LEVEL_ADMIN )
-  {
-    echo '<h3>Error: Not authenticated</h3><p>It looks like your administration session is invalid or you are not authorized to access this administration page. Please <a href="' . makeUrlNS('Special', 'Login/' . $paths->nslist['Special'] . 'Administration', 'level=' . USER_LEVEL_ADMIN, true) . '">re-authenticate</a> to continue.</p>';
-    return;
-  }
-  
-  ?>
-  <h2>Editing and managing the Enano sidebar</h2>
-   <p>The Enano sidebar is a versatile tool when scripted correctly. You don't have to be a programmer to enjoy the features the Sidebar
-      provides; however, editing the sidebar requires a small bit of programming knowledge and an understanding of Enano's system message
-      markup language.
-      </p>
-   <p>The Enano system markup language is somewhat similar to HTML, in that it uses tags (&lt;example&gt;like this&lt;/example&gt;) for the
-      main syntax. However, Enano uses curly brackets ({ and }) as opposed to less-than and greater-than signs (&lt; and &gt;).</p>
-   <p>Programming the Enano sidebar requires the use of two tags: {slider} and {if}. The {slider} tag is used to create a new heading
-      on the sidebar, and all text enclosed in that tag will be collapsed when the heading is clicked. To specify the text on the heading,
-      use an equals sign (=) after the "slider" text. Then insert any links (they should be wiki-formatted) to internal Enano pages and
-      external sites.</p>
-   <p>So here is what the language for the default sidebar's "Navigation" heading looks like:</p>
-   <pre>{slider=Navigation}
-  [[Main Page|Home]]
-  [[Enano:Sidebar|Edit the sidebar]]
-{/slider}</pre>
-   <p>Pretty simple, huh? Good, now we're going to learn another common aspect of Enano programming: conditionals. The {if} tag allows you
-      to decide whether a portion of the sidebar will be displayed based on a template variable. Currently the only available conditions are
-      "user_logged_in" and "auth_admin", but more will be added soon. To use a conditional, enter {if conditional_name}, and then the
-      wiki-formatted text that you want to be under that condition, and then close the tag with {/if}. In the same way, you can reverse the
-      effect with {!if}. With {!if}, the closing tag is still {/if}, so keep that in mind. An {else} tag will be supported soon.</p>
-   <p>Now it's time for some real fun: variables. All template variables can be accessed from the sidebar. A variable is simply the
-      variable name, prefixed by a dollar sign ($). Some of the most common variables are $USERNAME, $SITE_NAME, $SITE_DESC, and $PAGE_NAME.
-      The sidebar also has some special variables that it uses for some of its links. The logout link can be added with $LOGOUT_LINK, and
-      the "change theme" button can be added with $STYLE_LINK.</p>
-   <p>So here is the Enano markup for the portion of the sidebar that contains the user tools:</p>
-   <pre>{slider=$USERNAME}
-  [[User:$USERNAME|User page]]
-  [[Special:Contributions?user=$USERNAME|My Contributions]]
-  {if user_logged_in}
-    [[Special:Preferences|Preferences]]
-    $THEME_LINK
-  {/if}
-  {if auth_admin}
-    [[Special:Administration|Administration]]
-  {/if}
-  {if user_logged_in}
-    $LOGOUT_LINK
-  {/if}
-  {!if user_logged_in}
-    Create an account
-    Log in
-  {/if}
-{/slider}</pre>
-  <?php
-}
-
-function page_Admin_GroupManager()
-{
-  global $db, $session, $paths, $template, $plugins; // Common objects
-  if ( $session->auth_level < USER_LEVEL_ADMIN || $session->user_level < USER_LEVEL_ADMIN )
-  {
-    echo '<h3>Error: Not authenticated</h3><p>It looks like your administration session is invalid or you are not authorized to access this administration page. Please <a href="' . makeUrlNS('Special', 'Login/' . $paths->nslist['Special'] . 'Administration', 'level=' . USER_LEVEL_ADMIN, true) . '">re-authenticate</a> to continue.</p>';
+    $login_link = makeUrlNS('Special', 'Login/' . $paths->nslist['Special'] . 'Administration', 'level=' . USER_LEVEL_ADMIN, true);
+    echo '<h3>' . $lang->get('adm_err_not_auth_title') . '</h3>';
+    echo '<p>' . $lang->get('adm_err_not_auth_body', array( 'login_link' => $login_link )) . '</p>';
     return;
   }
   
-  if(isset($_POST['do_create_stage1']))
+  if ( ENANO_DBLAYER != 'MYSQL' )
+    die('<h3>' . $lang->get('acpdb_err_not_supported_title') . '</h3>
+          <p>' . $lang->get('acpdb_err_not_supported_desc') . '</p>');
+  
+  if(isset($_GET['submitting']) && $_GET['submitting'] == 'yes' && defined('ENANO_DEMO_MODE') )
+  {
+    redirect(makeUrlComplete('Special', 'Administration'), $lang->get('acpdb_err_demo_mode_title'), $lang->get('acpdb_err_demo_mode_desc'), 5);
+  }
+  
+  global $system_table_list;
+  if(isset($_GET['submitting']) && $_GET['submitting'] == 'yes')
   {
-    if(!preg_match('/^([A-z0-9 -]+)$/', $_POST['create_group_name']))
-    {
-      echo '<p>The group name you chose is invalid.</p>';
-      return;
-    }
-    echo '<form action="'.makeUrl($paths->nslist['Special'].'Administration', 'module='.$paths->cpage['module']).'" method="post" onsubmit="if(!submitAuthorized) return false;" enctype="multipart/form-data">';
-    echo '<div class="tblholder">
-          <table border="0" style="width:100%;" cellspacing="1" cellpadding="4">
-          <tr><th colspan="2">Creating group: '.$_POST['create_group_name'].'</th></tr>
-          <tr>
-            <td class="row1">Group moderator</td><td class="row1">' . $template->username_field('group_mod') . '</td>
-          </tr>
-          <tr><td class="row2">Group status</td><td class="row2">
-            <label><input type="radio" name="group_status" value="'.GROUP_CLOSED.'" checked="checked" /> Closed to new members</label><br />
-            <label><input type="radio" name="group_status" value="'.GROUP_REQUEST.'" /> Members can ask to be added</label><br />
-            <label><input type="radio" name="group_status" value="'.GROUP_OPEN.'" /> Members can join freely</label><br />
-            <label><input type="radio" name="group_status" value="'.GROUP_HIDDEN.'" /> Group is hidden</label>
-          </td></tr>
-          <tr>
-            <th class="subhead" colspan="2">
-              <input type="hidden" name="create_group_name" value="'.$_POST['create_group_name'].'" />
-              <input type="submit" name="do_create_stage2" value="Create group" />
-            </th>
-          </tr>
-          </table>
-          </div>';
-    echo '</form>';
-    return;
-  }
-  elseif(isset($_POST['do_create_stage2']))
-  {
-    if(!preg_match('/^([A-z0-9 -]+)$/', $_POST['create_group_name']))
+    
+    if(defined('SQL_BACKUP_CRYPT'))
+      // Try to increase our time limit
+      @set_time_limit(0);
+    // Do the actual export
+    $aesext = ( defined('SQL_BACKUP_CRYPT') ) ? '.tea' : '';
+    $filename = 'enano_backup_' . enano_date('ymd') . '.sql' . $aesext;
+    ob_start();
+    // Spew some headers
+    $headdate = enano_date('F d, Y \a\t h:i a');
+    echo <<<HEADER
+-- Enano CMS SQL backup
+-- Generated on {$headdate} by {$session->username}
+
+HEADER;
+    // build the table list
+    $base = ( isset($_POST['do_system_tables']) ) ? $system_table_list : Array();
+    $add  = ( isset($_POST['additional_tables'])) ? $_POST['additional_tables'] : Array();
+    $tables = array_merge($base, $add);
+    
+    // Log it!
+    $e = $db->sql_query('INSERT INTO '.table_prefix.'logs(log_type,action,time_id,date_string,author,edit_summary,page_text) VALUES(\'security\', \'db_backup\', '.time().', \''.enano_date('d M Y h:i a').'\', \''.$db->escape($session->username).'\', \''.$db->escape($_SERVER['REMOTE_ADDR']).'\', \'' . $db->escape(implode(', ', $tables)) . '\')');
+    if ( !$e )
+      $db->_die();
+    
+    foreach($tables as $i => $t)
     {
-      echo '<p>The group name you chose is invalid.</p>';
-      return;
-    }
-    if(!in_array(intval($_POST['group_status']), Array(GROUP_CLOSED, GROUP_OPEN, GROUP_HIDDEN, GROUP_REQUEST)))
-    {
-      echo '<p>Hacking attempt</p>';
-      return;
-    }
-    $e = $db->sql_query('SELECT group_id FROM '.table_prefix.'groups WHERE group_name=\''.$db->escape($_POST['create_group_name']).'\';');
-    if(!$e)
-    {
-      echo $db->get_error();
-      return;
-    }
-    if($db->numrows() > 0)
-    {
-      echo '<p>The group name you entered already exists.</p>';
-      return;
-    }
-    $db->free_result();
-    $q = $db->sql_query('INSERT INTO '.table_prefix.'groups(group_name,group_type) VALUES( \''.$db->escape($_POST['create_group_name']).'\', ' . intval($_POST['group_status']) . ' )');
-    if(!$q)
-    {
-      echo $db->get_error();
-      return;
-    }
-    $e = $db->sql_query('SELECT user_id FROM '.table_prefix.'users WHERE username=\''.$db->escape($_POST['group_mod']).'\';');
-    if(!$e)
-    {
-      echo $db->get_error();
-      return;
-    }
-    if($db->numrows() < 1)
-    {
-      echo '<p>The username you entered could not be found.</p>';
-      return;
+      if(!preg_match('#^([a-z0-9_]+)$#i', $t))
+        die('Hacking attempt');
+      // if($t == table_prefix.'files' && isset($_POST['do_data']))
+      //   unset($tables[$i]);
     }
-    $row = $db->fetchrow();
-    $id = $row['user_id'];
-    $db->free_result();
-    $e = $db->sql_query('SELECT group_id FROM '.table_prefix.'groups WHERE group_name=\''.$db->escape($_POST['create_group_name']).'\';');
-    if(!$e)
-    {
-      echo $db->get_error();
-      return;
-    }
-    if($db->numrows() < 1)
-    {
-      echo '<p>The group ID could not be looked up.</p>';
-      return;
-    }
-    $row = $db->fetchrow();
-    $gid = $row['group_id'];
-    $db->free_result();
-    $e = $db->sql_query('INSERT INTO '.table_prefix.'group_members(group_id,user_id,is_mod) VALUES('.$gid.', '.$id.', 1);');
-    if(!$e)
-    {
-      echo $db->get_error();
-      return;
-    }
-    echo "<div class='info-box'>
-            <b>Information</b><br />
-            The group {$_POST['create_group_name']} has been created successfully.
-          </div>";
-  }
-  if(isset($_POST['do_edit']) || isset($_POST['edit_do']))
-  {
-    // Fetch the group name
-    $q = $db->sql_query('SELECT group_name,system_group FROM '.table_prefix.'groups WHERE group_id='.intval($_POST['group_edit_id']).';');
-    if(!$q)
+    foreach($tables as $t)
     {
-      echo $db->get_error();
-      return;
-    }
-    if($db->numrows() < 1)
-    {
-      echo '<p>Error: couldn\'t look up group name</p>';
-    }
-    $row = $db->fetchrow();
-    $name = $row['group_name'];
-    $db->free_result();
-    if(isset($_POST['edit_do']))
-    {
-      if(isset($_POST['edit_do']['del_group']))
-      {
-        if ( $row['system_group'] == 1 )
-        {
-          echo '<div class="error-box">The group "' . $name . '" could not be deleted because it is a system group required for site functionality.</div>';
-        }
-        else
-        {
-          $q = $db->sql_query('DELETE FROM '.table_prefix.'group_members WHERE group_id='.intval($_POST['group_edit_id']).';');
-          if(!$q)
-          {
-            echo $db->get_error();
-            return;
-          }
-          $q = $db->sql_query('DELETE FROM '.table_prefix.'groups WHERE group_id='.intval($_POST['group_edit_id']).';');
-          if(!$q)
-          {
-            echo $db->get_error();
-            return;
-          }
-          echo '<div class="info-box">The group "'.$name.'" has been deleted. Return to the <a href="javascript:ajaxPage(\'Admin:GroupManager\');">group manager</a>.</div>';
-          return;
-        }
-      }
-      if(isset($_POST['edit_do']['save_name']))
+      // THE FOLLOWING COMMENT DOES NOT APPLY AS OF 1.0.
+      // Sorry folks - this script CAN'T backup enano_files and enano_search_index due to the sheer size of the tables.
+      // If encryption is enabled the log data will be excluded too.
+      $result = export_table(
+        $t,
+        isset($_POST['do_struct']),
+        ( isset($_POST['do_data']) ),
+        false
+        ) . "\n";
+      if ( !$result )
       {
-        if(!preg_match('/^([A-z0-9 -]+)$/', $_POST['group_name']))
-        {
-          echo '<p>The group name you chose is invalid.</p>';
-          return;
-        }
-        $q = $db->sql_query('UPDATE '.table_prefix.'groups SET group_name=\''.$db->escape($_POST['group_name']).'\'
-            WHERE group_id='.intval($_POST['group_edit_id']).';');
-        if(!$q)
-        {
-          echo $db->get_error();
-          return;
-        }
-        else
-        {
-          echo '<div class="info-box" style="margin: 0 0 10px 0;"">
-                  The group name has been updated.
-                </div>';
-        }
-        $name = $_POST['group_name'];
-        
-      }
-      $q = $db->sql_query('SELECT member_id FROM '.table_prefix.'group_members
-                             WHERE group_id='.intval($_POST['group_edit_id']).';');
-      if(!$q)
-      {
-        echo $db->get_error();
-        return;
+        $db->_die();
       }
-      if($db->numrows() > 0)
-      {
-        while($row = $db->fetchrow($q))
-        {
-          if(isset($_POST['edit_do']['del_' . $row['member_id']]))
-          {
-            $e = $db->sql_query('DELETE FROM '.table_prefix.'group_members WHERE member_id='.$row['member_id']);
-            if(!$e)
-            {
-              echo $db->get_error();
-              return;
-            }
-          }
-        }
-      }
-      $db->free_result();
-      if(isset($_POST['edit_do']['add_member']))
-      {
-        $q = $db->sql_query('SELECT user_id FROM '.table_prefix.'users WHERE username=\''.$db->escape($_POST['edit_add_username']).'\';');
-        if(!$q)
-        {
-          echo $db->get_error();
-          return;
-        }
-        if($db->numrows() > 0)
-        {
-          $row = $db->fetchrow();
-          $user_id = $row['user_id'];
-          $is_mod = ( isset( $_POST['add_mod'] ) ) ? '1' : '0';
-          $q = $db->sql_query('INSERT INTO '.table_prefix.'group_members(group_id,user_id,is_mod) VALUES('.intval($_POST['group_edit_id']).','.$user_id.','.$is_mod.');');
-          if(!$q)
-          {
-            echo $db->get_error();
-            return;
-          }
-          else
-          {
-            echo '<div class="info-box" style="margin: 0 0 10px 0;"">
-                    The user "'.$_POST['edit_add_username'].'" has been added to this usergroup.
-                  </div>';
-          }
-        }
-        else
-          echo '<div class="warning-box"><b>The user "'.$_POST['edit_add_username'].'" could not be added.</b><br />This username does not exist.</div>';
-      }
+      echo $result;
     }
-    $sg_disabled = ( $row['system_group'] == 1 ) ? ' value="Can\'t delete system group" disabled="disabled" style="color: #FF9773" ' : ' value="Delete this group" style="color: #FF3713" ';
-    echo '<form action="'.makeUrl($paths->nslist['Special'].'Administration', 'module='.$paths->cpage['module']).'" method="post" onsubmit="if(!submitAuthorized) return false;" enctype="multipart/form-data">';
-    echo '<div class="tblholder">
-          <table border="0" style="width:100%;" cellspacing="1" cellpadding="4">
-          <tr><th>Edit group name</th></tr>
-          <tr>
-            <td class="row1">
-              Group name: <input type="text" name="group_name" value="'.$name.'" />
-            </td>
-          </tr>
-          <tr>
-            <th class="subhead">
-              <input type="submit" name="edit_do[save_name]" value="Save name" />
-              <input type="submit" name="edit_do[del_group]" '.$sg_disabled.' />
-            </th>
-          </tr>
-          </table>
-          </div>
-          <input type="hidden" name="group_edit_id" value="'.$_POST['group_edit_id'].'" />';
-    echo '</form>';
-    echo '<form action="'.makeUrl($paths->nslist['Special'].'Administration', 'module='.$paths->cpage['module']).'" method="post" onsubmit="if(!submitAuthorized) return false;" enctype="multipart/form-data">';
-    echo '<div class="tblholder">
-          <table border="0" style="width:100%;" cellspacing="1" cellpadding="4">
-          <tr><th colspan="3">Edit group members</th></tr>';
-    $q = $db->sql_query('SELECT m.member_id,m.is_mod,u.username FROM '.table_prefix.'group_members AS m
-                           LEFT JOIN '.table_prefix.'users AS u
-                             ON u.user_id=m.user_id
-                             WHERE m.group_id='.intval($_POST['group_edit_id']).'
-                           ORDER BY m.is_mod DESC, u.username ASC;');
-    if(!$q)
-    {
-      echo $db->get_error();
-      return;
-    }
-    if($db->numrows() < 1)
-    {
-      echo '<tr><td colspan="3" class="row1">This group has no members.</td></tr>';
-    }
-    else
+    $data = ob_get_contents();
+    ob_end_clean();
+    if(defined('SQL_BACKUP_CRYPT'))
     {
-      $cls = 'row2';
-      while($row = $db->fetchrow())
-      {
-        $cls = ( $cls == 'row1' ) ? 'row2' : 'row1';
-        $mod = ( $row['is_mod'] == 1 ) ? 'Mod' : '';
-        echo '<tr>
-                <td class="'.$cls.'" style="width: 100%;">
-                  ' . $row['username'] . '
-                </td>
-                <td class="'.$cls.'">
-                  '.$mod.'
-                </td>
-                <td class="'.$cls.'">
-                  <input type="submit" name="edit_do[del_'.$row['member_id'].']" value="Remove member" />
-                </td>
-              </tr>';
-      }
+      // Free some memory, we don't need this stuff any more
+      $db->close();
+      unset($paths, $db, $template, $plugins);
+      $tea = new TEACrypt();
+      $data = $tea->encrypt($data, $session->private_key);
     }
-    $db->free_result();
-    echo '</table>
-          </div>
-          <input type="hidden" name="group_edit_id" value="'.$_POST['group_edit_id'].'" />';
-    echo '</form>';
-    echo '<form action="'.makeUrl($paths->nslist['Special'].'Administration', 'module='.$paths->cpage['module']).'" method="post" onsubmit="if(!submitAuthorized) return false;" enctype="multipart/form-data">';
-    echo '<div class="tblholder">
-          <table border="0" style="width:100%;" cellspacing="1" cellpadding="4">
-            <tr>
-              <th>Add a new member</th>
-            </tr>
-            <tr>
-              <td class="row1">
-                Username: ' . $template->username_field('edit_add_username') . '
-              </td>
-            </tr>
-            <tr>
-              <td class="row2">
-                <label><input type="checkbox" name="add_mod" /> Is a group moderator</label> (can add and delete other members)
-              </td>
-            </tr>
-            <tr>
-              <th class="subhead">
-                <input type="submit" name="edit_do[add_member]" value="Add user to group" />
-              </th>
-            </tr>
-          </table>
-          </div>
-          <input type="hidden" name="group_edit_id" value="'.$_POST['group_edit_id'].'" />';
-    echo '</form>';
-    return;
-  }
-  echo '<h3>Manage Usergroups</h3>';
-  echo '<form action="'.makeUrl($paths->nslist['Special'].'Administration', 'module='.$paths->cpage['module']).'" method="post" onsubmit="if(!submitAuthorized) return false;" enctype="multipart/form-data">';
-  $q = $db->sql_query('SELECT group_id,group_name FROM '.table_prefix.'groups ORDER BY group_name ASC;');
-  if(!$q)
-  {
-    echo $db->get_error();
+    header('Content-disposition: attachment; filename='.$filename.'');
+    header('Content-type: application/octet-stream');
+    header('Content-length: '.strlen($data));
+    echo $data;
+    exit;
   }
   else
   {
-    echo '<div class="tblholder">
-          <table border="0" cellspacing="1" cellpadding="4" style="width: 100%;">
-          <tr>
-          <th>Edit an existing group</th>
-          </tr>';
-    echo '<tr><td class="row2"><select name="group_edit_id">';
-    while ( $row = $db->fetchrow() )
-    {
-      if ( $row['group_name'] != 'Everyone' )
-      {
-        echo '<option value="' . $row['group_id'] . '">' . htmlspecialchars( $row['group_name'] ) . '</option>';
-      }
-    }
-    $db->free_result();
-    echo '</select></td></tr>';
-    echo '<tr><td class="row1" style="text-align: center;"><input type="submit" name="do_edit" value="Edit group" /></td></tr>
-          </table>
-          </div>
-          </form><br />';
+    // Show the UI
+    echo '<form action="'.makeUrlNS('Admin', 'DBBackup', 'submitting=yes', true).'" method="post" enctype="multipart/form-data">';
+    ?>
+    <p><?php echo $lang->get('acpdb_intro'); ?></p>
+    <p><label><input type="checkbox" name="do_system_tables" checked="checked" /> <?php echo $lang->get('acpdb_lbl_system_tables'); ?></label><p>
+    <p><?php echo $lang->get('acpdb_lbl_additional_tables'); ?></p>
+    <p><select name="additional_tables[]" multiple="multiple">
+       <?php
+         if ( ENANO_DBLAYER == 'MYSQL' )
+         {
+           $q = $db->sql_query('SHOW TABLES;') or $db->_die('Somehow we were denied the request to get the list of tables.');
+         }
+         else if ( ENANO_DBLAYER == 'PGSQL' )
+         {
+           $q = $db->sql_query('SELECT relname FROM pg_stat_user_tables ORDER BY relname;') or $db->_die('Somehow we were denied the request to get the list of tables.');
+         }
+         while($row = $db->fetchrow_num())
+         {
+           if(!in_array($row[0], $system_table_list)) echo '<option value="'.$row[0].'">'.$row[0].'</option>';
+         }
+       ?>
+       </select>
+       </p>
+    <p><label><input type="checkbox" name="do_struct" checked="checked" /> <?php echo $lang->get('acpdb_lbl_include_structure'); ?></label><br />
+       <label><input type="checkbox" name="do_data"   checked="checked" /> <?php echo $lang->get('acpdb_lbl_include_data'); ?></label>
+       </p>
+    <p><input type="submit" value="<?php echo $lang->get('acpdb_btn_create_backup'); ?>" /></p>
+    <?php
+    echo '</form>';
   }
-  echo '<form action="'.makeUrl($paths->nslist['Special'].'Administration', 'module='.$paths->cpage['module']).'" method="post" onsubmit="if(!submitAuthorized) return false;" enctype="multipart/form-data">';
-  echo '<div class="tblholder">
-        <table border="0" cellspacing="1" cellpadding="4" style="width: 100%;">
-        <tr>
-        <th colspan="2">Create a new group</th>
-        </tr>';
-  echo '<tr><td class="row2">Group name:</td><td class="row2"><input type="text" name="create_group_name" /></td></tr>';
-  echo '<tr><td colspan="2" class="row1" style="text-align: center;"><input type="submit" name="do_create_stage1" value="Continue >" /></td></tr>
-        </table>
-        </div>';
-  echo '</form>';
 }
 
+/*
+ * Admin:PageManager sources are in /plugins/admin/PageManager.php.
+ */
+
+/*
+ * Admin:PageEditor sources are in /plugins/admin/PageEditor.php.
+ */
+
+/*
+ * Admin:ThemeManager sources are in /plugins/admin/ThemeManager.php.
+ */
+
+/*
+ * Admin:GroupManager sources are in /plugins/admin/GroupManager.php.
+ */
+
 function page_Admin_COPPA()
 {
   global $db, $session, $paths, $template, $plugins; // Common objects
+  global $lang;
   if ( $session->auth_level < USER_LEVEL_ADMIN || $session->user_level < USER_LEVEL_ADMIN )
   {
-    echo '<h3>Error: Not authenticated</h3><p>It looks like your administration session is invalid or you are not authorized to access this administration page. Please <a href="' . makeUrlNS('Special', 'Login/' . $paths->nslist['Special'] . 'Administration', 'level=' . USER_LEVEL_ADMIN, true) . '">re-authenticate</a> to continue.</p>';
+    $login_link = makeUrlNS('Special', 'Login/' . $paths->nslist['Special'] . 'Administration', 'level=' . USER_LEVEL_ADMIN, true);
+    echo '<h3>' . $lang->get('adm_err_not_auth_title') . '</h3>';
+    echo '<p>' . $lang->get('adm_err_not_auth_body', array( 'login_link' => $login_link )) . '</p>';
     return;
   }
   
-  echo '<h2>Background information</h2>';
+  echo '<h2>' . $lang->get('acpcp_heading_main') . '</h2>';
   echo '<p>
-          The United States Childrens\' Online Privacy Protection Act (COPPA) was a law passed in 2001 that requires sites oriented towards
-          children under 13 years old or with a significant amount of under-13 children clearly state what information is being collected
-          in a privacy policy and obtain authorization from a parent or legal guardian before allowing children to use the site. Enano 
-          provides an easy way to allow you, as the website administrator, to obtain this authorization.
+          ' . $lang->get('acpcp_intro') . '
         </p>';
   
   // Start form
@@ -1243,33 +1433,33 @@
     $address = $_POST['coppa_address']; // RenderMan::preprocess_text($_POST['coppa_address'], true, false);
     setConfig('coppa_address', $address);
     
-    echo '<div class="info-box">Your changes have been saved.</div>';
+    echo '<div class="info-box">' . $lang->get('acpcp_msg_save_success') . '</div>';
   }
   
-  echo '<form action="'.makeUrl($paths->nslist['Special'].'Administration', (( isset($_GET['sqldbg'])) ? 'sqldbg&amp;' : '') .'module='.$paths->cpage['module']).'" method="post">';
+  acp_start_form();
   
   echo '<div class="tblholder">';
   echo '<table border="0" cellspacing="1" cellpadding="4">';
   echo '<tr>
           <th colspan="2">
-            COPPA support
+            ' . $lang->get('acpcp_th_form') . '
           </th>
         </tr>';
         
   echo '<tr>
           <td class="row1">
-            Enable COPPA support:
+            ' . $lang->get('acpcp_field_enable_title') . '
           </td>
           <td class="row2">
-            <label><input type="checkbox" name="enable_coppa" ' . ( ( getConfig('enable_coppa') == '1' ) ? 'checked="checked"' : '' ) . ' /> COPPA enabled</label><br />
-            <small>If this is checked, users will be asked if they are under 13 years of age before registering</small>
+            <label><input type="checkbox" name="enable_coppa" ' . ( ( getConfig('enable_coppa') == '1' ) ? 'checked="checked"' : '' ) . ' /> ' . $lang->get('acpcp_field_enable') . '</label><br />
+            <small>' . $lang->get('acpcp_field_enable_hint') . '</small>
           </td>
         </tr>';
         
   echo '<tr>
           <td class="row1">
-            Your mailing address:<br />
-            <small>This is the address to which parents will send authorization forms.</small>
+            ' . $lang->get('acpcp_field_address') . '<br />
+            <small>' . $lang->get('acpcp_field_address_hint') . '</small>
           </td>
           <td class="row2">
             <textarea name="coppa_address" rows="7" cols="40">' . getConfig('coppa_address') . '</textarea>
@@ -1278,7 +1468,7 @@
         
   echo '<tr>
           <th colspan="2" class="subhead">
-            <input type="submit" value="Save changes" />
+            <input type="submit" value="' . $lang->get('etc_save_changes') . '" />
           </th>
         </tr>';
         
@@ -1288,680 +1478,15 @@
   
 }
 
-function page_Admin_PageManager()
-{
-  global $db, $session, $paths, $template, $plugins; // Common objects
-  if ( $session->auth_level < USER_LEVEL_ADMIN || $session->user_level < USER_LEVEL_ADMIN )
-  {
-    echo '<h3>Error: Not authenticated</h3><p>It looks like your administration session is invalid or you are not authorized to access this administration page. Please <a href="' . makeUrlNS('Special', 'Login/' . $paths->nslist['Special'] . 'Administration', 'level=' . USER_LEVEL_ADMIN, true) . '">re-authenticate</a> to continue.</p>';
-    return;
-  }
-  
-  
-  echo '<h2>Page management</h2>';
-  
-  if(isset($_POST['search']) || isset($_POST['select']) || ( isset($_GET['source']) && $_GET['source'] == 'ajax' )) {
-    // The object of the game: using only the text a user entered, guess the page ID and namespace. *sigh* I HATE writing search algorithms...
-    $source = ( isset($_GET['source']) ) ? $_GET['source'] : false;
-    if ( $source == 'ajax' )
-    {
-      $_POST['search'] = true;
-      $_POST['page_url'] = $_GET['page_id'];
-    }
-    if(isset($_POST['search'])) $pid = $_POST['page_url'];
-    elseif(isset($_POST['select'])) $pid = $_POST['page_force_url'];
-    else { echo 'Internal error selecting page search terms'; return false; }
-    // Look for a namespace prefix in the urlname, and assign a different namespace, if necessary
-    $k = array_keys($paths->nslist);
-    for($i=0;$i<sizeof($paths->nslist);$i++)
-    {
-      $ln = strlen($paths->nslist[$k[$i]]);
-      if(substr($pid, 0, $ln) == $paths->nslist[$k[$i]])
-      {
-        $ns = $k[$i];
-        $page_id = substr($pid, $ln, strlen($pid));
-      }
-    }
-    // The namespace is in $ns and the page name or ID (we don't know which yet) is in $page_id
-    // Now, iterate through $paths->pages searching for a page with this name or ID
-    for($i=0;$i<sizeof($paths->pages)/2;$i++)
-    {
-      if(!isset($final_pid))
-      {
-        if    ($paths->pages[$i]['urlname_nons'] == str_replace(' ', '_', $page_id)) $final_pid = str_replace(' ', '_', $page_id);
-        elseif($paths->pages[$i]['name'] == $page_id) $final_pid = $paths->pages[$i]['urlname_nons'];
-        elseif(strtolower($paths->pages[$i]['urlname_nons']) == strtolower(str_replace(' ', '_', $page_id))) $final_pid = $paths->pages[$i]['urlname_nons'];
-        elseif(strtolower($paths->pages[$i]['name']) == strtolower(str_replace('_', ' ', $page_id))) $final_pid = $paths->pages[$i]['urlname_nons'];
-        if(isset($final_pid)) { $_POST['name'] = $paths->pages[$i]['name']; $_POST['urlname'] = $paths->pages[$i]['urlname_nons']; }
-      }
-    }
-    if(!isset($final_pid)) { echo 'The page you searched for cannot be found. <a href="#" onclick="ajaxPage(\''.$paths->nslist['Admin'].'PageManager\'); return false;">Back</a>'; return false; }
-    $_POST['namespace'] = $ns;
-    $_POST['old_namespace'] = $ns;
-    $_POST['page_id'] = $final_pid;
-    $_POST['old_page_id'] = $final_pid;
-    if(!isset($paths->pages[$paths->nslist[$_POST['namespace']].$_POST['urlname']])) { echo 'The page you searched for cannot be found. <a href="#" onclick="ajaxPage(\''.$paths->nslist['Admin'].'PageManager\'); return false;">Back</a>'; return false; }
-  }
-  
-  if(isset($_POST['page_id']) && isset($_POST['namespace']) && !isset($_POST['cancel']))
-  {
-    $cpage = $paths->pages[$paths->nslist[$_POST['old_namespace']].$_POST['old_page_id']];
-    if(isset($_POST['submit']))
-    {
-      switch(true)
-      {
-        case true:
-          // Create a list of things to update
-          $page_info = Array(
-              'name'=>$_POST['name'],
-              'urlname'=>sanitize_page_id($_POST['page_id']),
-              'namespace'=>$_POST['namespace'],
-              'special'=>isset($_POST['special']) ? '1' : '0',
-              'visible'=>isset($_POST['visible']) ? '1' : '0',
-              'comments_on'=>isset($_POST['comments_on']) ? '1' : '0',
-              'protected'=>isset($_POST['protected']) ? '1' : '0'
-            );
-          
-          $updating_urlname_or_namespace = ( $page_info['namespace'] != $cpage['namespace'] || $page_info['urlname'] != $cpage['urlname_nons'] );
-          
-          if ( !isset($paths->nslist[ $page_info['namespace'] ]) )
-          {
-            echo '<div class="error-box">The namespace you selected is not properly registered.</div>';
-            break;
-          }
-          if ( isset($paths->pages[ $paths->nslist[$page_info['namespace']] . $page_info[ 'urlname' ] ]) && $updating_urlname_or_namespace )
-          {
-            echo '<div class="error-box">There is already a page that exists with that URL string and namespace.</div>';
-            break;
-          }
-          // Build the query
-          $q = 'UPDATE '.table_prefix.'pages SET ';
-          $k = array_keys($page_info);
-          foreach($k as $c)
-          {
-            $q .= $c.'=\''.$db->escape($page_info[$c]).'\',';
-          }
-          $q = substr($q, 0, strlen($q)-1);
-          // Build the WHERE statements
-          $q .= ' WHERE ';
-          $k = array_keys($cpage);
-          if ( !isset($cpage) )
-            die('[internal] no cpage');
-          foreach($k as $c)
-          {
-            if($c != 'urlname_nons' && $c != 'urlname' && $c != 'really_protected')
-            {
-              $q .= $c.'=\''.$db->escape($cpage[$c]).'\' AND ';
-            }
-            else if($c == 'urlname')
-            {
-              $q .= $c.'=\''.$db->escape($cpage['urlname_nons']).'\' AND ';
-            }
-          }
-          // Trim off the last " AND " and append a semicolon
-          $q = substr($q, 0, strlen($q)-5) . ';';
-          // Send the completed query to MySQL
-          $e = $db->sql_query($q);
-          if(!$e) $db->_die('The page data could not be updated.');
-          // Update any additional tables
-          $q = Array(
-            'UPDATE '.table_prefix.'categories SET page_id=\''.$page_info['urlname'].'\',namespace=\''.$page_info['namespace'].'\' WHERE page_id=\'' . $db->escape($_POST['old_page_id']) . '\' AND namespace=\'' . $db->escape($_POST['old_namespace']) . '\';',
-            'UPDATE '.table_prefix.'comments   SET page_id=\''.$page_info['urlname'].'\',namespace=\''.$page_info['namespace'].'\' WHERE page_id=\'' . $db->escape($_POST['old_page_id']) . '\' AND namespace=\'' . $db->escape($_POST['old_namespace']) . '\';',
-            'UPDATE '.table_prefix.'logs       SET page_id=\''.$page_info['urlname'].'\',namespace=\''.$page_info['namespace'].'\' WHERE page_id=\'' . $db->escape($_POST['old_page_id']) . '\' AND namespace=\'' . $db->escape($_POST['old_namespace']) . '\';',
-            'UPDATE '.table_prefix.'page_text  SET page_id=\''.$page_info['urlname'].'\',namespace=\''.$page_info['namespace'].'\' WHERE page_id=\'' . $db->escape($_POST['old_page_id']) . '\' AND namespace=\'' . $db->escape($_POST['old_namespace']) . '\';',
-            'UPDATE '.table_prefix.'acl        SET page_id=\''.$page_info['urlname'].'\',namespace=\''.$page_info['namespace'].'\' WHERE page_id=\'' . $db->escape($_POST['old_page_id']) . '\' AND namespace=\'' . $db->escape($_POST['old_namespace']) . '\';'
-            );
-          foreach($q as $cq)
-          {
-            $e = $db->sql_query($cq);
-            if(!$e) $db->_die('Some of the additional tables containing page information could not be updated.');
-          }
-          // Update $cpage
-          $cpage = $page_info;
-          $cpage['urlname_nons'] = $cpage['urlname'];
-          $cpage['urlname'] = $paths->nslist[$cpage['namespace']].$cpage['urlname'];
-          $_POST['old_page_id'] = $page_info['urlname'];
-          $_POST['old_namespace'] = $page_info['namespace'];
-          echo '<div class="info-box">Your changes have been saved.</div>';
-          break;
-      }
-    } elseif(isset($_POST['delete'])) {
-      $q = Array(
-        'DELETE FROM '.table_prefix.'categories WHERE page_id=\'' . $db->escape($_POST['old_page_id']) . '\' AND namespace=\'' . $db->escape($_POST['old_namespace']) . '\';',
-        'DELETE FROM '.table_prefix.'comments   WHERE page_id=\'' . $db->escape($_POST['old_page_id']) . '\' AND namespace=\'' . $db->escape($_POST['old_namespace']) . '\';',
-        'DELETE FROM '.table_prefix.'logs       WHERE page_id=\'' . $db->escape($_POST['old_page_id']) . '\' AND namespace=\'' . $db->escape($_POST['old_namespace']) . '\';',
-        'DELETE FROM '.table_prefix.'page_text  WHERE page_id=\'' . $db->escape($_POST['old_page_id']) . '\' AND namespace=\'' . $db->escape($_POST['old_namespace']) . '\';',
-        );
-      foreach($q as $cq)
-      {
-        $e = $db->sql_query($cq);
-        if(!$e) $db->_die('Some of the additional tables containing page information could not be updated.');
-      }
-      
-      if(!$db->sql_query(
-        'DELETE FROM '.table_prefix.'pages WHERE urlname="'.$db->escape($_POST['old_page_id']).'" AND namespace="'.$db->escape($_POST['old_namespace']).'";'
-      )) $db->_die('The page could not be deleted.');
-      echo '<div class="info-box">This page has been deleted.</p><p><a href="javascript:ajaxPage(\''.$paths->nslist['Admin'].'PageManager\');">Return to Page manager</a><br /><a href="javascript:ajaxPage(\''.$paths->nslist['Admin'].'Home\');">Admin home</a></div>';
-      return;
-    }
-    $url = makeUrlNS('Special', 'Administration', 'module='.$paths->cpage['module'], true);
-    echo '<form action="'.$url.'" method="post">';
-    ?>
-    <h3>Modify page: <?php echo htmlspecialchars($_POST['name']); ?></h3>
-     <table border="0">
-       <tr><td>Namespace:</td><td><select name="namespace"><?php $nm = array_keys($paths->nslist); foreach($nm as $ns) { if($ns != 'Special' && $ns != 'Admin') { echo '<option '; if($_POST['namespace']==$ns) echo 'selected="selected" '; echo 'value="'.$ns.'">'; if($paths->nslist[$ns] == '') echo '[No prefix]'; else echo $paths->nslist[$ns]; echo '</option>'; } } ?></select></td></tr>
-       <tr><td>Page title:</td><td><input type="text" name="name" value="<?php echo htmlspecialchars($cpage['name']); ?>" /></td></tr>
-       <tr><td>Page URL string:<br /><small>No spaces, and don't enter the namespace prefix (e.g. User:).<br />Changing this value is usually not a good idea, especially for templates and project pages.</small></td><td><input type="text" name="page_id" value="<?php echo htmlspecialchars(dirtify_page_id($cpage['urlname_nons'])); ?>" /></td></tr>
-       <tr><td></td><td><input <?php if($cpage['comments_on']) echo 'checked="checked"'; ?> name="comments_on" type="checkbox" id="cmt" />  <label for="cmt">Enable comments for this page</label></td></tr>
-       <tr><td></td><td><input <?php if($cpage['special']) echo 'checked="checked"'; ?> name="special" type="checkbox" id="spc" />  <label for="spc">Bypass the template engine for this page</label><br /><small>This option enables you to use your own HTML headers and other code. It is recommended that only advanced users enable this feature. As with other Enano pages, you may use PHP code in your pages, meaning you can use Enano's API on the page.</small></td></tr>
-       <tr><td></td><td><input <?php if($cpage['visible']) echo 'checked="checked"'; ?> name="visible" type="checkbox" id="vis" />  <label for="vis">Allow this page to be shown in page lists</label><br /><small>Unchecking this checkbox prevents the page for being indexed for searching. The index is rebuilt each time a page is saved, and you can force an index rebuild by going to the page <?php echo $paths->nslist['Special']; ?>SearchRebuild.</small></td></tr>
-       <tr><td></td><td><input <?php if($cpage['protected']) echo 'checked="checked"'; ?> name="protected" type="checkbox" id="prt" />  <label for="prt">Prevent non-administrators from editing this page</label><br /><small>This option only has an effect when Wiki Mode is enabled.</small></td></tr>
-       <tr><td></td><td><input type="submit" name="delete" value="Delete page" style="color: red" onclick="return confirm('Do you REALLY want to delete this page?')" /></td></tr>
-       <tr><td colspan="2" style="text-align: center;"><hr /></td></tr>
-       <tr><td colspan="2" style="text-align: right;">
-       <input type="hidden" name="old_page_id" value="<?php echo $_POST['old_page_id']; ?>" />
-       <input type="hidden" name="old_namespace" value="<?php echo $_POST['old_namespace']; ?>" />
-       <input type="Submit" name="submit" value="Save changes" style="font-weight: bold;" />  <input type="submit" name="cancel" value="Cancel changes" /></td></tr>
-     </table>
-    <?php
-    echo '</form>';
-  } else {
-    echo '<h3>Please select a page</h3>';
-    echo '<form action="'.makeUrl($paths->nslist['Special'].'Administration', 'module='.$paths->cpage['module']).'" method="post" onsubmit="if(!submitAuthorized) return false;" enctype="multipart/form-data">';
-    ?>
-      <p>Search for page title (remember prefixes like User: and File:) <?php echo $template->pagename_field('page_url'); ?>  <input type="submit" style="font-weight: bold;" name="search" value="Search" /></p>
-      <p>Select page title from a list: <select name="page_force_url">
-      <?php
-        for($i=0;$i<sizeof($paths->pages)/2;$i++)
-        {
-          if($paths->pages[$i]['namespace'] != 'Admin' && $paths->pages[$i]['namespace'] != 'Special') echo '<option value="'.$paths->nslist[$paths->pages[$i]['namespace']].$paths->pages[$i]['urlname_nons'].'">'.htmlspecialchars($paths->nslist[$paths->pages[$i]['namespace']].$paths->pages[$i]['name']).'</option>'."\n";
-        }
-      ?>
-      </select>  <input type="submit" name="select" value="Select" /></p>
-    <?php
-    echo '</form>';
-    
-  }
-}
-
-function page_Admin_PageEditor()
-{
-  global $db, $session, $paths, $template, $plugins; // Common objects
-  if ( $session->auth_level < USER_LEVEL_ADMIN || $session->user_level < USER_LEVEL_ADMIN )
-  {
-    echo '<h3>Error: Not authenticated</h3><p>It looks like your administration session is invalid or you are not authorized to access this administration page. Please <a href="' . makeUrlNS('Special', 'Login/' . $paths->nslist['Special'] . 'Administration', 'level=' . USER_LEVEL_ADMIN, true) . '">re-authenticate</a> to continue.</p>';
-    return;
-  }
-  
-  
-  echo '<h2>Edit page content</h2>';
-  
-  if(isset($_POST['search']) || isset($_POST['select'])) {
-    // The object of the game: using only the text a user entered, guess the page ID and namespace. *sigh* I HATE writing search algorithms...
-    if(isset($_POST['search'])) $pid = $_POST['page_url'];
-    elseif(isset($_POST['select'])) $pid = $_POST['page_force_url'];
-    else { echo 'Internal error selecting page search terms'; return false; }
-    // Look for a namespace prefix in the urlname, and assign a different namespace, if necessary
-    $k = array_keys($paths->nslist);
-    for($i=0;$i<sizeof($paths->nslist);$i++)
-    {
-      $ln = strlen($paths->nslist[$k[$i]]);
-      if(substr($pid, 0, $ln) == $paths->nslist[$k[$i]])
-      {
-        $ns = $k[$i];
-        $page_id = substr($pid, $ln, strlen($pid));
-      }
-    }
-    // The namespace is in $ns and the page name or ID (we don't know which yet) is in $page_id
-    // Now, iterate through $paths->pages searching for a page with this name or ID
-    for($i=0;$i<sizeof($paths->pages)/2;$i++)
-    {
-      if(!isset($final_pid))
-      {
-        if    ($paths->pages[$i]['urlname_nons'] == str_replace(' ', '_', $page_id)) $final_pid = str_replace(' ', '_', $page_id);
-        elseif($paths->pages[$i]['name'] == $page_id) $final_pid = $paths->pages[$i]['urlname_nons'];
-        elseif(strtolower($paths->pages[$i]['urlname_nons']) == strtolower(str_replace(' ', '_', $page_id))) $final_pid = $paths->pages[$i]['urlname_nons'];
-        elseif(strtolower($paths->pages[$i]['name']) == strtolower(str_replace('_', ' ', $page_id))) $final_pid = $paths->pages[$i]['urlname_nons'];
-        if(isset($final_pid)) { $_POST['name'] = $paths->pages[$i]['name']; $_POST['urlname'] = $paths->pages[$i]['urlname_nons']; }
-      }
-    }
-    if(!isset($final_pid)) { echo 'The page you searched for cannot be found. <a href="#" onclick="ajaxPage(\''.$paths->nslist['Admin'].'PageManager\'); return false;">Back</a>'; return false; }
-    $_POST['namespace'] = $ns;
-    $_POST['page_id'] = $final_pid;
-    if(!isset($paths->pages[$paths->nslist[$_POST['namespace']].$_POST['urlname']])) { echo 'The page you searched for cannot be found. <a href="#" onclick="ajaxPage(\''.$paths->nslist['Admin'].'PageManager\'); return false;">Back</a>'; return false; }
-  }
-  
-  if(isset($_POST['page_id']) && !isset($_POST['cancel']))
-  {
-    echo '<form name="main" action="'.makeUrl($paths->nslist['Special'].'Administration', 'module='.$paths->cpage['module']).'" method="post">';
-    if(!isset($_POST['content']) || isset($_POST['revert'])) $content = RenderMan::getPage($_POST['page_id'], $_POST['namespace'], 0, false, false, false, false);
-    else $content = $_POST['content'];
-    if(isset($_POST['save']))
-    {
-      $data = $content;
-      $id = md5( microtime() . mt_rand() );
-      
-      $minor = isset($_POST['minor']) ? 'true' : 'false';
-      $q='INSERT INTO '.table_prefix.'logs(log_type,action,time_id,date_string,page_id,namespace,page_text,char_tag,author,edit_summary,minor_edit) VALUES(\'page\', \'edit\', '.time().', \''.date('d M Y h:i a').'\', \'' . $db->escape($_POST['page_id']) . '\', \'' . $db->escape($_POST['namespace']) . '\', \''.$db->escape($data).'\', \''.$id.'\', \''.$session->username.'\', \''.$db->escape(htmlspecialchars($_POST['summary'])).'\', '.$minor.');';
-      if(!$db->sql_query($q)) $db->_die('The history (log) entry could not be inserted into the logs table.');
-      
-      $query = 'UPDATE '.table_prefix.'page_text SET page_text=\''.$db->escape($data).'\',char_tag=\''.$id.'\' WHERE page_id=\'' . $db->escape($_POST['page_id']) . '\' AND namespace=\'' . $db->escape($_POST['namespace']) . '\';';
-      $e = $db->sql_query($query);
-      if(!$e) echo '<div class="warning-box">The page data could not be saved. MySQL said: '.mysql_error().'<br /><br />Query:<br /><pre>'.$query.'</pre></div>';
-      else echo '<div class="info-box">Your page has been saved. <a href="'.makeUrlNS($_POST['namespace'], $_POST['page_id']).'">View page...</a></div>';
-    } elseif(isset($_POST['preview'])) {
-      echo '<h3>Preview</h3><p><b>Reminder:</b> This is only a preview; your changes to this page have not yet been saved.</p><div style="margin: 1em; padding: 10px; border: 1px dashed #606060; background-color: #F8F8F8; max-height: 200px; overflow: auto;">'.RenderMan::render($content).'</div>';
-    }
-    ?>
-    <p>
-    <textarea name="content" rows="20" cols="60" style="width: 100%;"><?php echo htmlspecialchars($content); ?></textarea><br />
-    Edit summary: <input name="summary" value="<?php if(isset($_POST['summary'])) echo htmlspecialchars($_POST['summary']); ?>" size="40" /><br />
-    <label><input type="checkbox" name="minor" <?php if(isset($_POST['minor'])) echo 'checked="checked" '; ?>/>  This is a minor edit</label>
-    </p>
-    <p>
-    <input type="hidden" name="page_id" value="<?php echo htmlspecialchars($_POST['page_id']); ?>" />
-    <input type="hidden" name="namespace" value="<?php echo htmlspecialchars($_POST['namespace']); ?>" />
-    <input type="submit" name="save" value="Save changes" style="font-weight: bold;" />&nbsp;&nbsp;<input type="submit" name="preview" value="Show preview" />&nbsp;&nbsp;<input type="submit" name="revert" value="Revert changes" onclick="return confirm('Do you really want to revert your changes?');" />&nbsp;&nbsp;<input type="submit" name="cancel" value="Cancel" onclick="return confirm('Do you really want to cancel your changes?');" />
-    </p>
-    <?php
-    echo '</form>';
-  } else {
-    echo '<h3>Please select a page</h3>';
-    echo '<form action="'.makeUrl($paths->nslist['Special'].'Administration', 'module='.$paths->cpage['module']).'" method="post" onsubmit="if(!submitAuthorized) return false;" enctype="multipart/form-data">';
-    ?>
-      <p>Search for page title (remember prefixes like User: and File:) <?php echo $template->pagename_field('page_url'); ?>  <input type="submit" style="font-weight: bold;" name="search" value="Search" /></p>
-      <p>Select page title from a list: <select name="page_force_url">
-      <?php
-        for ( $i = 0; $i < sizeof($paths->pages) / 2; $i++ )
-        {
-          if($paths->pages[$i]['namespace'] != 'Admin' && $paths->pages[$i]['namespace'] != 'Special') echo '<option value="'.$paths->nslist[$paths->pages[$i]['namespace']].$paths->pages[$i]['urlname_nons'].'">'.$paths->nslist[$paths->pages[$i]['namespace']].$paths->pages[$i]['name'].'</option>'."\n";
-        }
-      ?>
-      </select>  <input type="submit" name="select" value="Select" /></p>
-    <?php
-    echo '</form>';
-  }
-}
-
-function page_Admin_ThemeManager() 
-{
-  
-  global $db, $session, $paths, $template, $plugins; // Common objects
-  if ( $session->auth_level < USER_LEVEL_ADMIN || $session->user_level < USER_LEVEL_ADMIN )
-  {
-    echo '<h3>Error: Not authenticated</h3><p>It looks like your administration session is invalid or you are not authorized to access this administration page. Please <a href="' . makeUrlNS('Special', 'Login/' . $paths->nslist['Special'] . 'Administration', 'level=' . USER_LEVEL_ADMIN, true) . '">re-authenticate</a> to continue.</p>';
-    return;
-  }
-  
-  
-  // Get the list of styles in the themes/ dir
-  $h = opendir('./themes');
-  $l = Array();
-  if(!$h) die('Error opening directory "./themes" for reading.');
-  while(false !== ($n = readdir($h))) {
-    if($n != '.' && $n != '..' && is_dir('./themes/'.$n))
-      $l[] = $n;
-  }
-  closedir($h);
-  echo('
-  <h3>Theme Management</h3>
-   <p>Install, uninstall, and manage Enano themes.</p>
-  ');
-  if(isset($_POST['disenable'])) {
-    $q = 'SELECT enabled FROM '.table_prefix.'themes WHERE theme_id=\'' . $db->escape($_POST['theme_id']) . '\'';
-    $s = $db->sql_query($q);
-    if(!$s) die('Error selecting enabled/disabled state value: '.mysql_error().'<br /><u>SQL:</u><br />'.$q);
-    $r = $db->fetchrow_num($s);
-    $db->free_result();
-    if($r[0] == 1) $e = 0;
-    else $e = 1;
-    $s=true;
-    if($e==0)
-    {
-      $c = $db->sql_query('SELECT * FROM '.table_prefix.'themes WHERE enabled=1');
-      if(!$c) $db->_die('The backup check for having at least on theme enabled failed.');
-      if($db->numrows() <= 1) { echo '<div class="warning-box">You cannot disable the last remaining theme.</div>'; $s=false; }
-    }
-    $db->free_result();
-    if($s) {
-    $q = 'UPDATE '.table_prefix.'themes SET enabled='.$e.' WHERE theme_id=\'' . $db->escape($_POST['theme_id']) . '\'';
-    $a = $db->sql_query($q);
-    if(!$a) die('Error updating enabled/disabled state value: '.mysql_error().'<br /><u>SQL:</u><br />'.$q);
-    else echo('<div class="info-box">The theme "'.$_POST['theme_id'].'" has been  '. ( ( $e == '1' ) ? 'enabled' : 'disabled' ).'.</div>');
-    }
-  }
-  elseif(isset($_POST['edit'])) {
-    
-    $dir = './themes/'.$_POST['theme_id'].'/css/';
-    $list = Array();
-    // Open a known directory, and proceed to read its contents
-    if (is_dir($dir)) {
-      if ($dh = opendir($dir)) {
-        while (($file = readdir($dh)) !== false) {
-          if(preg_match('#^(.*?)\.css$#is', $file) && $file != '_printable.css') {
-            $list[$file] = capitalize_first_letter(substr($file, 0, strlen($file)-4));
-          }
-        }
-        closedir($dh);
-      }
-    }
-    $lk = array_keys($list);
-    
-    $q = 'SELECT theme_name,default_style FROM '.table_prefix.'themes WHERE theme_id=\''.$db->escape($_POST['theme_id']).'\'';
-    $s = $db->sql_query($q);
-    if(!$s) die('Error selecting name value: '.mysql_error().'<br /><u>SQL:</u><br />'.$q);
-    $r = $db->fetchrow_num($s);
-    $db->free_result();
-    echo('<form action="'.makeUrl($paths->nslist['Special'].'Administration', 'module='.$paths->cpage['module']).'" method="post">');
-    echo('<div class="question-box">
-          Theme name displayed to users: <input type="text" name="name" value="'.$r[0].'" /><br /><br />
-          Default stylesheet: <select name="defaultcss">');
-    foreach ($lk as $l)
-    {
-      if($r[1] == $l) $v = ' selected="selected"';
-      else $v = '';
-      echo "<option value='{$l}'$v>{$list[$l]}</option>";
-    }
-    echo('</select><br /><br />
-          <input type="submit" name="editsave" value="OK" /><input type="hidden" name="theme_id" value="'.$_POST['theme_id'].'" />
-          </div>');
-    echo('</form>');
-  }
-  elseif(isset($_POST['editsave'])) {
-    $q = 'UPDATE '.table_prefix.'themes SET theme_name=\'' . $db->escape($_POST['name']) . '\',default_style=\''.$db->escape($_POST['defaultcss']).'\' WHERE theme_id=\'' . $db->escape($_POST['theme_id']) . '\'';
-    $s = $db->sql_query($q);
-    if(!$s) die('Error updating name value: '.mysql_error().'<br /><u>SQL:</u><br />'.$q);
-    else echo('<div class="info-box">Theme data updated.</div>');
-  }
-  elseif(isset($_POST['up'])) {
-    // If there is only one theme or if the selected theme is already at the top, do nothing
-    $q = 'SELECT theme_order FROM '.table_prefix.'themes ORDER BY theme_order;';
-    $s = $db->sql_query($q);
-    if(!$s) die('Error selecting order information: '.mysql_error().'<br /><u>SQL:</u><br />'.$q);
-    $q = 'SELECT theme_order FROM '.table_prefix.'themes WHERE theme_id=\''.$db->escape($_POST['theme_id']).'\'';
-    $sn = $db->sql_query($q);
-    if(!$sn) die('Error selecting order information: '.mysql_error().'<br /><u>SQL:</u><br />'.$q);
-    $r = $db->fetchrow_num($sn);
-    if( /* check for only one theme... */ $db->numrows($s) < 2 || $r[0] == 1 /* ...and check if this theme is already at the top */ ) { echo('<div class="warning-box">This theme is already at the top of the list, or there is only one theme installed.</div>'); } else {
-      // Get the order IDs of the selected theme and the theme before it
-      $q = 'SELECT theme_order FROM '.table_prefix.'themes WHERE theme_id=\'' . $db->escape($_POST['theme_id']) . '\'';
-      $s = $db->sql_query($q);
-      if(!$s) die('Error selecting order information: '.mysql_error().'<br /><u>SQL:</u><br />'.$q);
-      $r = $db->fetchrow_num($s);
-      $r = $r[0];
-      $rb = $r - 1;
-      // Thank God for jEdit's rectangular selection and the ablity to edit multiple lines at the same time ;)
-      $q = 'UPDATE '.table_prefix.'themes SET theme_order=0 WHERE theme_order='.$rb.'';      /* Check for errors... <sigh> */ $s = $db->sql_query($q); if(!$s) die('Error updating order information: '.mysql_error().'<br /><u>SQL:</u><br />'.$q);
-      $q = 'UPDATE '.table_prefix.'themes SET theme_order='.$rb.' WHERE theme_order='.$r.''; /* Check for errors... <sigh> */ $s = $db->sql_query($q); if(!$s) die('Error updating order information: '.mysql_error().'<br /><u>SQL:</u><br />'.$q);
-      $q = 'UPDATE '.table_prefix.'themes SET theme_order='.$r.' WHERE theme_order=0';       /* Check for errors... <sigh> */ $s = $db->sql_query($q); if(!$s) die('Error updating order information: '.mysql_error().'<br /><u>SQL:</u><br />'.$q);
-      echo('<div class="info-box">Theme moved up.</div>');
-    }
-    $db->free_result($s);
-    $db->free_result($sn);
-  }
-  elseif(isset($_POST['down'])) {
-    // If there is only one theme or if the selected theme is already at the top, do nothing
-    $q = 'SELECT theme_order FROM '.table_prefix.'themes ORDER BY theme_order;';
-    $s = $db->sql_query($q);
-    if(!$s) die('Error selecting order information: '.mysql_error().'<br /><u>SQL:</u><br />'.$q);
-    $r = $db->fetchrow_num($s);
-    if( /* check for only one theme... */ $db->numrows($s) < 2 || $r[0] == $db->numrows($s) /* ...and check if this theme is already at the bottom */ ) { echo('<div class="warning-box">This theme is already at the bottom of the list, or there is only one theme installed.</div>'); } else {
-      // Get the order IDs of the selected theme and the theme before it
-      $q = 'SELECT theme_order FROM '.table_prefix.'themes WHERE theme_id=\''.$db->escape($_POST['theme_id']).'\'';
-      $s = $db->sql_query($q);
-      if(!$s) die('Error selecting order information: '.mysql_error().'<br /><u>SQL:</u><br />'.$q);
-      $r = $db->fetchrow_num($s);
-      $r = $r[0];
-      $rb = $r + 1;
-      // Thank God for jEdit's rectangular selection and the ablity to edit multiple lines at the same time ;)
-      $q = 'UPDATE '.table_prefix.'themes SET theme_order=0 WHERE theme_order='.$rb.'';      /* Check for errors... <sigh> */ $s = $db->sql_query($q); if(!$s) die('Error updating order information: '.mysql_error().'<br /><u>SQL:</u><br />'.$q);
-      $q = 'UPDATE '.table_prefix.'themes SET theme_order='.$rb.' WHERE theme_order='.$r.''; /* Check for errors... <sigh> */ $s = $db->sql_query($q); if(!$s) die('Error updating order information: '.mysql_error().'<br /><u>SQL:</u><br />'.$q);
-      $q = 'UPDATE '.table_prefix.'themes SET theme_order='.$r.' WHERE theme_order=0';       /* Check for errors... <sigh> */ $s = $db->sql_query($q); if(!$s) die('Error updating order information: '.mysql_error().'<br /><u>SQL:</u><br />'.$q);
-      echo('<div class="info-box">Theme moved down.</div>');
-    }
-  }
-  else if(isset($_POST['uninstall'])) 
-  {
-    $q = 'SELECT * FROM '.table_prefix.'themes;';
-    $s = $db->sql_query($q);
-    if ( !$s )
-    {
-      die('Error getting theme count: '.mysql_error().'<br /><u>SQL:</u><br />'.$q);
-    }
-    $n = $db->numrows($s);
-    $db->free_result();
-    
-    if ( $_POST['theme_id'] == 'oxygen' )
-    {
-      echo '<div class="error-box">The Oxygen theme is used by Enano for installation, upgrades, and error messages, and cannot be uninstalled.</div>';
-    }
-    else
-    {
-      if($n < 2)
-      {
-        echo '<div class="error-box">The theme could not be uninstalled because it is the only theme left.</div>';
-      }
-      else
-      {
-        $q = 'DELETE FROM '.table_prefix.'themes WHERE theme_id=\''.$db->escape($_POST['theme_id']).'\' LIMIT 1;';
-        $s = $db->sql_query($q);
-        if ( !$s )
-        {
-          die('Error deleting theme data: '.mysql_error().'<br /><u>SQL:</u><br />'.$q);
-        }
-        else
-        {
-          echo('<div class="info-box">Theme uninstalled.</div>');
-        }
-      }
-    }
-  }
-  elseif(isset($_POST['install'])) {
-    $q = 'SELECT theme_id FROM '.table_prefix.'themes;';
-    $s = $db->sql_query($q);
-    if(!$s) die('Error getting theme count: '.mysql_error().'<br /><u>SQL:</u><br />'.$q);
-    $n = $db->numrows($s);
-    $n++;
-    $theme_id = $_POST['theme_id'];
-    $theme = Array();
-    include('./themes/'.$theme_id.'/theme.cfg');
-    if ( !isset($theme['theme_id']) )
-    {
-      echo '<div class="error-box">Could not load theme.cfg (theme metadata file)</div>';
-    }
-    else
-    {
-      $default_style = false;
-      if ( $dh = opendir('./themes/' . $theme_id . '/css') )
-      {
-        while ( $file = readdir($dh) )
-        {
-          if ( $file != '_printable.css' && preg_match('/\.css$/i', $file) )
-          {
-            $default_style = $file;
-            break;
-          }
-        }
-        closedir($dh);
-      }
-      else
-      {
-        die('The /css subdirectory could not be located in the theme\'s directory');
-      }
-      
-      if ( $default_style )
-      {
-        $q = 'INSERT INTO '.table_prefix.'themes(theme_id,theme_name,theme_order,enabled,default_style) VALUES(\''.$db->escape($theme['theme_id']).'\', \''.$db->escape($theme['theme_name']).'\', '.$n.', 1, \'' . $db->escape($default_style) . '\')';
-        $s = $db->sql_query($q);
-        if(!$s) die('Error inserting theme data: '.mysql_error().'<br /><u>SQL:</u><br />'.$q);
-        else echo('<div class="info-box">Theme "'.$theme['theme_name'].'" installed.</div>');
-      }
-      else
-      {
-        echo '<div class="error-box">Could not determine the default style for the theme.</div>';
-      }
-    }
-  }
-  echo('
-  <h3>Currently installed themes</h3>
-    <form action="'.makeUrl($paths->nslist['Special'].'Administration', 'module='.$paths->cpage['module']).'" method="post">
-    <p>
-      <select name="theme_id">
-        ');
-        $q = 'SELECT theme_id,theme_name,enabled FROM '.table_prefix.'themes ORDER BY theme_order';
-        $s = $db->sql_query($q);
-        if(!$s) die('Error selecting theme data: '.mysql_error().'<br /><u>Attempted SQL:</u><br />'.$q);
-        while ( $r = $db->fetchrow_num($s) ) {
-          if($r[2] < 1) $r[1] .= ' (disabled)';
-          echo('<option value="'.$r[0].'">'.$r[1].'</option>');
-        }
-        $db->free_result();
-        echo('
-        </select> <input type="submit" name="disenable" value="Enable/Disable" /> <input type="submit" name="edit" value="Change settings" /> <input type="submit" name="up" value="Move up" /> <input type="submit" name="down" value="Move down" /> <input type="submit" name="uninstall" value="Uninstall" style="color: #DD3300; font-weight: bold;" />
-      </p>
-    </form>
-    <h3>Install a new theme</h3>
-  ');
-    $theme = Array();
-    $obb = '';
-    for($i=0;$i<sizeof($l);$i++) {
-      if(is_file('./themes/'.$l[$i].'/theme.cfg') && file_exists('./themes/'.$l[$i].'/theme.cfg')) {
-        include('./themes/'.$l[$i].'/theme.cfg');
-        $q = 'SELECT * FROM '.table_prefix.'themes WHERE theme_id=\''.$theme['theme_id'].'\'';
-        $s = $db->sql_query($q);
-        if(!$s) die('Error selecting list of currently installed themes: '.mysql_error().'<br /><u>Attempted SQL:</u><br />'.$q);
-        if($db->numrows($s) < 1) {
-          $obb .= '<option value="'.$theme['theme_id'].'">'.$theme['theme_name'].'</option>';
-        }
-        $db->free_result();
-      }
-    }
-    if($obb != '') {
-      echo('<form action="'.makeUrl($paths->nslist['Special'].'Administration', 'module='.$paths->cpage['module']).'" method="post"><p>');
-      echo('<select name="theme_id">');
-      echo($obb);
-      echo('</select>');
-      echo('
-      <input type="submit" name="install" value="Install this theme" />
-      </p></form>');
-    } else echo('<p>All themes are currently installed.</p>');
-}
-
-function page_Admin_BanControl()
-{
-  global $db, $session, $paths, $template, $plugins; // Common objects
-  if ( $session->auth_level < USER_LEVEL_ADMIN || $session->user_level < USER_LEVEL_ADMIN )
-  {
-    echo '<h3>Error: Not authenticated</h3><p>It looks like your administration session is invalid or you are not authorized to access this administration page. Please <a href="' . makeUrlNS('Special', 'Login/' . $paths->nslist['Special'] . 'Administration', 'level=' . USER_LEVEL_ADMIN, true) . '">re-authenticate</a> to continue.</p>';
-    return;
-  }
-  
-  if(isset($_GET['action']) && $_GET['action'] == 'delete' && isset($_GET['id']) && $_GET['id'] != '')
-  {
-    $e = $db->sql_query('DELETE FROM '.table_prefix.'banlist WHERE ban_id=' . $db->escape($_GET['id']) . '');
-    if(!$e) $db->_die('The ban list entry was not deleted.');
-  }
-  if(isset($_POST['create']) && !defined('ENANO_DEMO_MODE'))
-  {
-    $type = intval($_POST['type']);
-    $value = trim($_POST['value']);
-    if ( !in_array($type, array(BAN_IP, BAN_USER, BAN_EMAIL)) )
-    {
-      echo '<div class="error-box">Hacking attempt.</div>';
-    }
-    else if ( empty($value) )
-    {
-      echo '<div class="error-box">Please enter something to ban.</div>';
-    }
-    else
-    {
-      $entries = array();
-      $input = explode(',', $_POST['value']);
-      $error = false;
-      foreach ( $input as $entry )
-      {
-        $entry = trim($entry);
-        if ( empty($entry) )
-        {
-          echo '<div class="error-box">Malformed entry.</div>';
-          $error = true;
-          break;
-        }
-        if ( $type == BAN_IP )
-        {
-          if ( !isset($_POST['regex']) )
-          {
-            // as of 1.0.2 parsing is done at runtime
-            $entries[] = $entry;
-          }
-          else
-          {
-            $entries[] = $entry;
-          }
-        }
-        else
-        {
-          $entries[] = $entry;
-        }
-      }
-      if ( !$error )
-      {
-        $regex = ( isset($_POST['regex']) ) ? '1' : '0';
-        $to_insert = array();                                                         
-        $reason = $db->escape($_POST['reason']);
-        foreach ( $entries as $entry )
-        {
-          $entry = $db->escape($entry);
-          $to_insert[] = "($type, '$entry', '$reason', $regex)";
-        }
-        $q = 'INSERT INTO '.table_prefix."banlist(ban_type, ban_value, reason, is_regex)\n  VALUES" . implode(",\n  ", $to_insert) . ';';
-        @set_time_limit(0);
-        $e = $db->sql_query($q);
-        if(!$e) $db->_die('The banlist could not be updated.');
-      }
-    }
-  }
-  else if ( isset($_POST['create']) && defined('ENANO_DEMO_MODE') )
-  {
-    echo '<div class="error-box">This function is disabled in the demo. Just because <i>you</i> don\'t like ' . htmlspecialchars($_POST['value']) . ' doesn\'t mean <i>we</i> don\'t like ' . htmlspecialchars($_POST['value']) . '.</div>';
-  }
-  $q = $db->sql_query('SELECT ban_id,ban_type,ban_value,is_regex FROM '.table_prefix.'banlist ORDER BY ban_type;');
-  if(!$q) $db->_die('The banlist data could not be selected.');
-  echo '<div class="tblholder" style="max-height: 800px; clip: rect(0px,auto,auto,0px); overflow: auto;">
-          <table border="0" cellspacing="1" cellpadding="4">';
-  echo '<tr><th>Type</th><th>Value</th><th>Regular Expression</th><th></th></tr>';
-  if($db->numrows() < 1) echo '<td class="row1" colspan="4">No ban rules yet.</td>';
-  $cls = 'row2';
-  while($r = $db->fetchrow())
-  {
-    $cls = ( $cls == 'row1' ) ? 'row2' : 'row1';
-    if($r['ban_type']==BAN_IP) $t = 'IP address';
-    elseif($r['ban_type']==BAN_USER) $t = 'Username';
-    elseif($r['ban_type']==BAN_EMAIL) $t = 'E-mail address';
-    if($r['is_regex']) $g = 'Yes'; else $g = 'No';
-    echo '<tr><td class="'.$cls.'">'.$t.'</td><td class="'.$cls.'">'.$r['ban_value'].'</td><td class="'.$cls.'">'.$g.'</td><td class="'.$cls.'"><a href="'.makeUrlNS('Special', 'Administration', 'module='.$paths->nslist['Admin'].'BanControl&amp;action=delete&amp;id='.$r['ban_id']).'">Delete</a></td></tr>';
-  }
-  $db->free_result();
-  echo '</table></div>';
-  echo '<h3>Create new ban rule</h3>';
-  echo '<form action="'.makeUrl($paths->nslist['Special'].'Administration', 'module='.$paths->cpage['module']).'" method="post">';
-  ?>
-  Type: <select name="type"><option value="<?php echo BAN_IP; ?>">IP address</option><option value="<?php echo BAN_USER; ?>">Username</option><option value="<?php echo BAN_EMAIL; ?>">E-mail address</option></select><br />
-  Rule: <input type="text" name="value" size="30" /><br />
-  <small>You can ban multiple IP addresses, users, or e-mail addresses by separating entries with a single comma (User1,User2). Do not put a space after the comma. For IP addresses, you may specify ranges like 172|192.168.4-30|90-167.1-90, which will turn into 172 and 192 . 168 . 4-30 and 90-167 . 1 - 90, which matches 18,899 IP addresses.</small><br />
-  Reason to show to the banned user: <textarea name="reason" rows="7" cols="40"></textarea><br />
-  <input type="checkbox" name="regex" id="regex" />  <label for="regex">This rule is a regular expression</label> (advanced users only)<br />
-  <input type="submit" style="font-weight: bold;" name="create" value="Create new ban rule" />
-  <?php
-  echo '</form>';
-}
-
 function page_Admin_MassEmail()
 {
   global $db, $session, $paths, $template, $plugins; // Common objects
+  global $lang;
   if ( $session->auth_level < USER_LEVEL_ADMIN || $session->user_level < USER_LEVEL_ADMIN )
   {
-    echo '<h3>Error: Not authenticated</h3><p>It looks like your administration session is invalid or you are not authorized to access this administration page. Please <a href="' . makeUrlNS('Special', 'Login/' . $paths->nslist['Special'] . 'Administration', 'level=' . USER_LEVEL_ADMIN, true) . '">re-authenticate</a> to continue.</p>';
+    $login_link = makeUrlNS('Special', 'Login/' . $paths->nslist['Special'] . 'Administration', 'level=' . USER_LEVEL_ADMIN, true);
+    echo '<h3>' . $lang->get('adm_err_not_auth_title') . '</h3>';
+    echo '<p>' . $lang->get('adm_err_not_auth_body', array( 'login_link' => $login_link )) . '</p>';
     return;
   }
   
@@ -1991,9 +1516,9 @@
     $message = stripslashes(trim($_POST['message']));
     
     if ( empty($subject) )
-      $errors[] = 'Please enter a subject.';
+      $errors[] = $lang->get('acpmm_err_need_subject');
     if ( empty($message) )
-      $errors[] = 'Please enter a message.';
+      $errors[] = $lang->get('acpmm_err_need_message');
     
     // Get list of members
     if ( !empty($_POST['userlist']) )
@@ -2073,6 +1598,7 @@
       
       $mail->extra_headers($email_headers);
       
+      // FIXME: how to handle l10n with this?
       $tpl = 'The following message was mass-mailed by {SENDER}, one of the administrators from {SITE_NAME}. If this message contains spam or any comments which you find abusive or offensive, please contact the administration team at:
   
 {CONTACT_EMAIL}
@@ -2096,32 +1622,31 @@
       $mail->send();
       $mail->reset();
       
-      echo '<div class="info-box">Your message has been sent.</div>';
+      echo '<div class="info-box">' . $lang->get('acpmm_msg_send_success') . '</div>';
       
     }
     else
     {
-      echo '<div class="warning-box">Could not send message for the following reason(s):<ul><li>' . implode('</li><li>', $errors) . '</li></ul></div>';
+      echo '<div class="warning-box">' . $lang->get('acpmm_err_send_fail') . '<ul><li>' . implode('</li><li>', $errors) . '</li></ul></div>';
     }
     
   }
   else if ( isset($_POST['do_send']) && defined('ENANO_DEMO_MODE') )
   {
-    echo '<div class="error-box">This function is disabled in the demo. You think demo@enanocms.org likes getting "test" mass e-mails?</div>';
+    echo '<div class="error-box">' . $lang->get('acpmm_err_demo') . '</div>';
   }
-  echo '<form action="'.makeUrl($paths->nslist['Special'].'Administration', 'module='.$paths->cpage['module']).'" method="post">';
+  acp_start_form();
   ?>
   <div class="tblholder">
     <table border="0" cellspacing="1" cellpadding="4">
       <tr>
-        <th colspan="2">Send mass e-mail</th>
+        <th colspan="2"><?php echo $lang->get('acpmm_heading_main'); ?></th>
       </tr>
       <tr>
         <td class="row2" rowspan="2" style="width: 30%; min-width: 200px;">
-          Send message to:<br />
+          <?php echo $lang->get('acpmm_field_group_to'); ?><br />
           <small>
-            By default, this message will be sent to the group selected here. You may instead send the message to a specific
-            list of users by entering them in the second row, with usernames separated by a single comma (no space).
+            <?php echo $lang->get('acpmm_field_group_to_hint'); ?>
           </small>
         </td>
         <td class="row1">
@@ -2132,7 +1657,13 @@
               $db->_die();
             while ( $row = $db->fetchrow() )
             {
-              echo '<option value="' . $row['group_id'] . '">' . $row['group_name'] . '</option>';
+              list($g_name) = array_values($row);
+              $g_name_langstr = 'groupcp_grp_' . strtolower($g_name);
+              if ( ($g_langstr = $lang->get($g_name_langstr)) != $g_name_langstr )
+              {
+                $g_name = $g_langstr;
+              }
+              echo '<option value="' . $row['group_id'] . '">' . htmlspecialchars($g_name) . '</option>';
             }
             ?>
           </select>
@@ -2140,12 +1671,12 @@
       </tr>
       <tr>
         <td class="row1">
-          Usernames: <input type="text" name="userlist" size="50" />
+          <?php echo $lang->get('acpmm_field_username'); ?> <input type="text" name="userlist" size="50" />
         </td>
       </tr>
       <tr>
         <td class="row2" style="width: 30%; min-width: 200px;">
-          Subject:
+          <?php echo $lang->get('acpmm_field_subject'); ?>
         </td>
         <td class="row1">
           <input name="subject" type="text" size="50" />
@@ -2153,7 +1684,7 @@
       </tr>
       <tr>
         <td class="row2"  style="width: 30%; min-width: 200px;">
-          Message:
+          <?php echo $lang->get('acpmm_field_message'); ?>
         </td>
         <td class="row1">
           <textarea name="message" rows="30" cols="60" style="width: 100%;"></textarea>
@@ -2161,8 +1692,8 @@
       </tr>
       <tr>
         <th class="subhead" colspan="2" style="text-align: left;" valign="middle">
-          <div style="float: right;"><input type="submit" name="do_send" value="Send message" /></div>
-          <small style="font-weight: normal;">Please be warned: it may take a LONG time to send this message. <b>Please do not stop the script until the process is finished.</b></small>
+          <div style="float: right;"><input type="submit" name="do_send" value="<?php echo $lang->get('acpmm_btn_send'); ?>" /></div>
+          <small style="font-weight: normal;"><?php echo $lang->get('acpmm_msg_send_takeawhile'); ?></small>
         </th>
       </tr>
       
@@ -2172,142 +1703,171 @@
   echo '</form>';
 }
 
-function page_Admin_DBBackup()
+function page_Admin_BanControl()
 {
   global $db, $session, $paths, $template, $plugins; // Common objects
+  global $lang;
   if ( $session->auth_level < USER_LEVEL_ADMIN || $session->user_level < USER_LEVEL_ADMIN )
   {
-    echo '<h3>Error: Not authenticated</h3><p>It looks like your administration session is invalid or you are not authorized to access this administration page. Please <a href="' . makeUrlNS('Special', 'Login/' . $paths->nslist['Special'] . 'Administration', 'level=' . USER_LEVEL_ADMIN, true) . '">re-authenticate</a> to continue.</p>';
+    $login_link = makeUrlNS('Special', 'Login/' . $paths->nslist['Special'] . 'Administration', 'level=' . USER_LEVEL_ADMIN, true);
+    echo '<h3>' . $lang->get('adm_err_not_auth_title') . '</h3>';
+    echo '<p>' . $lang->get('adm_err_not_auth_body', array( 'login_link' => $login_link )) . '</p>';
     return;
   }
   
-  if ( ENANO_DBLAYER != 'MYSQL' )
-    die('<h3>Not supported</h3>
-          <p>This function is only supported under the MySQL database driver.</p>');
-  
-  if(isset($_GET['submitting']) && $_GET['submitting'] == 'yes' && defined('ENANO_DEMO_MODE') )
+  if(isset($_GET['action']) && $_GET['action'] == 'delete' && isset($_GET['id']) && $_GET['id'] != '')
   {
-    redirect(makeUrlComplete('Special', 'Administration'), 'Access denied', 'You\'ve got to be kidding me. Forget it, kid.', 4 );
+    $e = $db->sql_query('DELETE FROM '.table_prefix.'banlist WHERE ban_id=' . intval($_GET['id']) . '');
+    if ( !$e )
+      $db->_die('The ban list entry was not deleted.');
   }
-  
-  global $system_table_list;
-  if(isset($_GET['submitting']) && $_GET['submitting'] == 'yes')
+  if(isset($_POST['create']) && !defined('ENANO_DEMO_MODE'))
   {
-    
-    if(defined('SQL_BACKUP_CRYPT'))
-      // Try to increase our time limit
-      @set_time_limit(0);
-    // Do the actual export
-    $aesext = ( defined('SQL_BACKUP_CRYPT') ) ? '.tea' : '';
-    $filename = 'enano_backup_' . date('ymd') . '.sql' . $aesext;
-    ob_start();
-    // Spew some headers
-    $headdate = date('F d, Y \a\t h:i a');
-    echo <<<HEADER
--- Enano CMS SQL backup
--- Generated on {$headdate} by {$session->username}
-
-HEADER;
-    // build the table list
-    $base = ( isset($_POST['do_system_tables']) ) ? $system_table_list : Array();
-    $add  = ( isset($_POST['additional_tables'])) ? $_POST['additional_tables'] : Array();
-    $tables = array_merge($base, $add);
-    
-    // Log it!
-    $e = $db->sql_query('INSERT INTO '.table_prefix.'logs(log_type,action,time_id,date_string,author,edit_summary,page_text) VALUES(\'security\', \'db_backup\', '.time().', \''.date('d M Y h:i a').'\', \''.$db->escape($session->username).'\', \''.$db->escape($_SERVER['REMOTE_ADDR']).'\', \'' . $db->escape(implode(', ', $tables)) . '\')');
-    if ( !$e )
-      $db->_die();
-    
-    foreach($tables as $i => $t)
+    $type = intval($_POST['type']);
+    $value = trim($_POST['value']);
+    if ( !in_array($type, array(BAN_IP, BAN_USER, BAN_EMAIL)) )
     {
-      if(!preg_match('#^([a-z0-9_]+)$#i', $t))
-        die('Hacking attempt');
-      // if($t == table_prefix.'files' && isset($_POST['do_data']))
-      //   unset($tables[$i]);
+      echo '<div class="error-box">Hacking attempt.</div>';
     }
-    foreach($tables as $t)
+    else if ( empty($value) )
+    {
+      echo '<div class="error-box">' . $lang->get('acpbc_err_empty') . '</div>';
+    }
+    else
     {
-      // THE FOLLOWING COMMENT DOES NOT APPLY AS OF 1.0.
-      // Sorry folks - this script CAN'T backup enano_files and enano_search_index due to the sheer size of the tables.
-      // If encryption is enabled the log data will be excluded too.
-      $result = export_table(
-        $t,
-        isset($_POST['do_struct']),
-        ( isset($_POST['do_data']) ),
-        false
-        ) . "\n";
-      if ( !$result )
+      $entries = array();
+      $input = explode(',', $_POST['value']);
+      $error = false;
+      foreach ( $input as $entry )
       {
-        $db->_die();
+        $entry = trim($entry);
+        if ( empty($entry) )
+        {
+          echo '<div class="error-box">' . $lang->get('acpbc_err_invalid_ip_range') . '</div>';
+          $error = true;
+          break;
+        }
+        if ( $type == BAN_IP )
+        {
+          if ( !isset($_POST['regex']) )
+          {
+            // as of 1.0.2 parsing is done at runtime
+            $entries[] = $entry;
+          }
+          else
+          {
+            $entries[] = $entry;
+          }
+        }
+        else
+        {
+          $entries[] = $entry;
+        }
       }
-      echo $result;
+      if ( !$error )
+      {
+        $regex = ( isset($_POST['regex']) ) ? '1' : '0';
+        $to_insert = array();                                                         
+        $reason = $db->escape($_POST['reason']);
+        foreach ( $entries as $entry )
+        {
+          $entry = $db->escape($entry);
+          $to_insert[] = "($type, '$entry', '$reason', $regex)";
+        }
+        $q = 'INSERT INTO '.table_prefix."banlist(ban_type, ban_value, reason, is_regex)\n  VALUES" . implode(",\n  ", $to_insert) . ';';
+        @set_time_limit(0);
+        $e = $db->sql_query($q);
+        if(!$e) $db->_die('The banlist could not be updated.');
+      }
     }
-    $data = ob_get_contents();
-    ob_end_clean();
-    if(defined('SQL_BACKUP_CRYPT'))
-    {
-      // Free some memory, we don't need this stuff any more
-      $db->close();
-      unset($paths, $db, $template, $plugins);
-      $tea = new TEACrypt();
-      $data = $tea->encrypt($data, $session->private_key);
-    }
-    header('Content-disposition: attachment, filename="'.$filename.'";');
-    header('Content-type: application/transact-sql');
-    header('Content-length: '.strlen($data));
-    echo $data;
-    exit;
+  }
+  else if ( isset($_POST['create']) && defined('ENANO_DEMO_MODE') )
+  {
+    echo '<div class="error-box">' . $lang->get('acpbc_err_demo', array('ban_target' => htmlspecialchars($_POST['value']))) . '</div>';
   }
-  else
+  $q = $db->sql_query('SELECT ban_id,ban_type,ban_value,is_regex FROM '.table_prefix.'banlist ORDER BY ban_type;');
+  if ( !$q )
+    $db->_die('The banlist data could not be selected.');
+  echo '<div class="tblholder" style="max-height: 800px; clip: rect(0px,auto,auto,0px); overflow: auto;">
+          <table border="0" cellspacing="1" cellpadding="4">';
+  echo '<tr>
+          <th>' . $lang->get('acpbc_col_type') . '</th>
+          <th>' . $lang->get('acpbc_col_value') . '</th>
+          <th>' . $lang->get('acpbc_col_regex') . '</th>
+          <th></th>
+        </tr>';
+  if ( $db->numrows() < 1 )
+  {
+    echo '<td class="row1" colspan="4">' . $lang->get('acpbc_msg_no_rules') . '</td>';
+  }
+  $cls = 'row2';
+  while ( $r = $db->fetchrow() )
   {
-    // Show the UI
-    echo '<form action="'.makeUrlNS('Admin', 'DBBackup', 'submitting=yes', true).'" method="post" enctype="multipart/form-data">';
-    ?>
-    <p>This page allows you to back up your Enano database should something go miserably wrong.</p>
-    <p><label><input type="checkbox" name="do_system_tables" checked="checked" />  Export tables that are part of the Enano core</label><p>
-    <p>Additional tables to export:</p>
-    <p><select name="additional_tables[]" multiple="multiple">
-       <?php
-         if ( ENANO_DBLAYER == 'MYSQL' )
-         {
-           $q = $db->sql_query('SHOW TABLES;') or $db->_die('Somehow we were denied the request to get the list of tables.');
-         }
-         else if ( ENANO_DBLAYER == 'PGSQL' )
-         {
-           $q = $db->sql_query('SELECT relname FROM pg_stat_user_tables ORDER BY relname;') or $db->_die('Somehow we were denied the request to get the list of tables.');
-         }
-         while($row = $db->fetchrow_num())
-         {
-           if(!in_array($row[0], $system_table_list)) echo '<option value="'.$row[0].'">'.$row[0].'</option>';
-         }
-       ?>
-       </select>
-       </p>
-    <p><label><input type="checkbox" name="do_struct" checked="checked" /> Include table structure</label><br />
-       <label><input type="checkbox" name="do_data"   checked="checked" /> Include table data</label>
-       </p>
-    <p><input type="submit" value="Create backup" /></p>
-    <?php
-    echo '</form>';
+    $cls = ( $cls == 'row1' ) ? 'row2' : 'row1';
+    if ( $r['ban_type'] == BAN_IP )
+      $t = $lang->get('acpbc_ban_type_ip');
+    else if ( $r['ban_type'] == BAN_USER )
+      $t = $lang->get('acpbc_ban_type_username');
+    else if ( $r['ban_type'] == BAN_EMAIL )
+      $t = $lang->get('acpbc_ban_type_email');
+    $g = ( $r['is_regex'] ) ? '<b>' . $lang->get('acpbc_ban_regex_yes') . '</b>' : $lang->get('acpbc_ban_regex_no');
+    echo '<tr>
+            <td class="'.$cls.'">'.$t.'</td>
+            <td class="'.$cls.'">'.htmlspecialchars($r['ban_value']).'</td>
+            <td class="'.$cls.'">'.$g.'</td>
+            <td class="'.$cls.'"><a href="'.makeUrlNS('Special', 'Administration', 'module='.$paths->nslist['Admin'].'BanControl&amp;action=delete&amp;id='.$r['ban_id']).'">' . $lang->get('acpbc_btn_delete') . '</a></td>
+          </tr>';
   }
+  $db->free_result();
+  echo '</table></div>';
+  echo '<h3>' . $lang->get('acpbc_heading_create_new') . '</h3>';
+  acp_start_form();
+  ?>
+  
+  <?php echo $lang->get('acpbc_field_type'); ?>
+    <select name="type">
+      <option value="<?php echo BAN_IP; ?>"><?php echo $lang->get('acpbc_ban_type_ip'); ?></option>
+      <option value="<?php echo BAN_USER; ?>"><?php echo $lang->get('acpbc_ban_type_username'); ?></option>
+      <option value="<?php echo BAN_EMAIL; ?>"><?php echo $lang->get('acpbc_ban_type_email'); ?></option>
+    </select>
+    <br />
+    
+  <?php echo $lang->get('acpbc_field_rule'); ?>
+    <input type="text" name="value" size="30" /><br />
+    <small><?php echo $lang->get('acpbc_field_rule_hint'); ?></small><br />
+    
+  <?php echo $lang->get('acpbc_field_reason'); ?>
+    <textarea name="reason" rows="7" cols="40"></textarea><br />
+    
+  <label><input type="checkbox" name="regex" id="regex" /> <?php echo $lang->get('acpbc_field_regex'); ?></label>
+    <?php echo $lang->get('acpbc_field_regex_hint'); ?><br />
+    
+  <input type="submit" style="font-weight: bold;" name="create" value="<?php echo $lang->get('acpbc_btn_create'); ?>" />
+  <?php
+  echo '</form>';
 }
 
 function page_Admin_AdminLogout()
 {
   global $db, $session, $paths, $template, $plugins; // Common objects
+  global $lang;
   if ( $session->auth_level < USER_LEVEL_ADMIN || $session->user_level < USER_LEVEL_ADMIN )
   {
-    echo '<h3>Error: Not authenticated</h3><p>It looks like your administration session is invalid or you are not authorized to access this administration page. Please <a href="' . makeUrlNS('Special', 'Login/' . $paths->nslist['Special'] . 'Administration', 'level=' . USER_LEVEL_ADMIN, true) . '">re-authenticate</a> to continue.</p>';
+    $login_link = makeUrlNS('Special', 'Login/' . $paths->nslist['Special'] . 'Administration', 'level=' . USER_LEVEL_ADMIN, true);
+    echo '<h3>' . $lang->get('adm_err_not_auth_title') . '</h3>';
+    echo '<p>' . $lang->get('adm_err_not_auth_body', array( 'login_link' => $login_link )) . '</p>';
     return;
   }
   
   $session->logout(USER_LEVEL_ADMIN);
-  echo '<h3>You have now been logged out of the administration panel.</h3><p>You will continue to be logged into the website, but you will need to re-authenticate before you can access the administration panel again.</p><p>Return to the <a href="'.makeUrl(getConfig('main_page')).'">Main Page</a>.</p>';
+  echo '<h3>' . $lang->get('acplo_heading_main') . '</h3>
+         <p>' . $lang->get('acplo_msg_logout_complete', array('mainpage_link' => makeUrl(getConfig('main_page')))) . '</p>';
 }
 
 function page_Special_Administration()
 {
   global $db, $session, $paths, $template, $plugins; // Common objects
+  global $lang;
   
   if($session->auth_level < USER_LEVEL_ADMIN) {
     redirect(makeUrlNS('Special', 'Login/'.$paths->page, 'level='.USER_LEVEL_ADMIN), 'Not authorized', 'You need an authorization level of '.USER_LEVEL_ADMIN.' to use this page, your auth level is: ' . $session->auth_level, 0);
@@ -2321,7 +1881,7 @@
     {
       $template->header();
     }
-    echo 'Administer your Enano website.';
+    echo $lang->get('adm_page_tagline');
     ?>
     <script type="text/javascript">
     function ajaxPage(t)
@@ -2333,7 +1893,7 @@
       }
       if ( t == namespace_list.Admin + 'AdminLogout' )
       {
-        var mb = new messagebox(MB_YESNO|MB_ICONQUESTION, 'Are you sure you want to de-authenticate?', 'If you de-authenticate, you will no longer be able to use the administration panel until you re-authenticate again. You may do so at any time using the Administration button on the sidebar.');
+        var mb = new messagebox(MB_YESNO|MB_ICONQUESTION, $lang.get('user_logout_confirm_title_elev'), $lang.get('user_logout_confirm_body_elev'));
         mb.onclick['Yes'] = function() {
           var tigraentry = document.getElementById('i_div0_0').parentNode;
           var tigraobj = $(tigraentry);
@@ -2367,7 +1927,7 @@
       }
       document.getElementById('ajaxPageContainer').innerHTML = '<div class="wait-box">Loading page...</div>';
       ajaxGet('<?php echo scriptPath; ?>/ajax.php?title='+t+'&_mode=getpage&noheaders&auth=<?php echo $session->sid_super; ?>', function() {
-          if(ajax.readyState == 4) {
+          if ( ajax.readyState == 4 && ajax.status == 200 ) {
             document.getElementById('ajaxPageContainer').innerHTML = ajax.responseText;
             fadeInfoBoxes();
           }
@@ -2445,7 +2005,7 @@
           } 
           else 
           {
-            echo '<div class="wait-box">Please wait while the administration panel loads. You need to be using a recent browser with AJAX support in order to use Runt.</div>';
+            echo '<script type="text/javascript">document.write(\'<div class="wait-box">Please wait while the administration panel loads. You need to be using a recent browser with AJAX support in order to use Runt.</div>\');</script><noscript><div class="error-box">It looks like Javascript isn\'t enabled in your browser. Please enable Javascript or use a different browser to continue.</div></noscript>';
           }
           ?>
           </div>
@@ -2470,6 +2030,7 @@
 function page_Special_EditSidebar()
 {
   global $db, $session, $paths, $template, $plugins; // Common objects
+  global $lang;
   
   if($session->auth_level < USER_LEVEL_ADMIN) 
   {
@@ -2484,10 +2045,6 @@
     $template->add_header('<script type="text/javascript" src="'.scriptPath.'/includes/clientside/sbedit.js"></script>');
     $template->add_header('<link rel="stylesheet" type="text/css" href="'.scriptPath.'/includes/clientside/dbx.css" />');
     
-    // Knock the sidebars dead to keep javascript in plugins from interfering
-    $template->tpl_strings['SIDEBAR_LEFT']  = '';
-    $template->tpl_strings['SIDEBAR_RIGHT'] = '';
-    
     $template->load_theme('oxygen', 'bleu');
     $template->init_vars();
     
@@ -2522,7 +2079,7 @@
       $queries = Array();
       foreach($orders as $k => $v)
       {
-        $queries[] = 'UPDATE '.table_prefix.'sidebar SET item_order='.$om[$k].' WHERE item_id='.$v[1].';';
+        $queries[] = 'UPDATE '.table_prefix.'sidebar SET item_order='.intval($om[$k]).' WHERE item_id='.intval($v[1]).';';
       }
       foreach($queries as $sql)
       {
@@ -2535,7 +2092,7 @@
           exit;
         }
       }
-      echo '<div class="info-box" style="margin: 10px 0;">The sidebar order information was updated successfully.</div>';
+      echo '<div class="info-box" style="margin: 10px 0;">' . $lang->get('sbedit_msg_order_update_success') . '</div>';
     }
     elseif(isset($_POST['create']))
     {
@@ -2566,14 +2123,14 @@
       
       if ( defined('ENANO_DEMO_MODE') && intval($_POST['type']) == BLOCK_PHP )
       {
-        echo '<div class="error-box" style="margin: 10px 0 10px 0;">Adding PHP code blocks in the Enano administration demo has been disabled for security reasons.</div>';
+        echo '<div class="error-box" style="margin: 10px 0 10px 0;">' . $lang->get('sbedit_err_demo_php_disable') . '</div>';
         $_POST['php_content'] = '?>&lt;Nulled&gt;';
         $content = $_POST['php_content'];
       }
       
       // Get the value of item_order
       
-      $q = $db->sql_query('SELECT * FROM '.table_prefix.'sidebar WHERE sidebar_id='.$db->escape($_POST['sidebar_id']).';');
+      $q = $db->sql_query('SELECT * FROM '.table_prefix.'sidebar WHERE sidebar_id='.intval($_POST['sidebar_id']).';');
       if(!$q) $db->_die('The order number could not be selected');
       $io = $db->numrows();
       
@@ -2588,7 +2145,7 @@
         exit;
       }
       
-      echo '<div class="info-box" style="margin: 10px 0;">The item was added.</div>';
+      echo '<div class="info-box" style="margin: 10px 0;">' . $lang->get('sbedit_msg_item_added') . '</div>';
       
     }
     
@@ -2622,28 +2179,32 @@
           <form action="<?php echo makeUrl($paths->page); ?>" method="post">
           
             <p>
-              What type of block should this be?
+              <?php echo $lang->get('sbedit_create_intro'); ?>
             </p>
             <p>
               <select name="type" onchange="setType(this)"> <?php /* (NOT WORKING, at least in firefox 2) onload="var thingy = this; setTimeout('setType(thingy)', 500);" */ ?>
-                <option value="<?php echo BLOCK_WIKIFORMAT; ?>">Wiki-formatted block</option>
-                <option value="<?php echo BLOCK_TEMPLATEFORMAT; ?>">Template-formatted block (old pre-beta 3 behavior)</option>
-                <option value="<?php echo BLOCK_HTML; ?>">Raw HTML block</option>
-                <option value="<?php echo BLOCK_PHP; ?>">PHP code block (danger, Will Robinson!)</option>
-                <option value="<?php echo BLOCK_PLUGIN; ?>">Use code from a plugin</option>
+                <option value="<?php echo BLOCK_WIKIFORMAT; ?>"><?php echo $lang->get('sbedit_block_type_wiki'); ?></option>
+                <option value="<?php echo BLOCK_TEMPLATEFORMAT; ?>"><?php echo $lang->get('sbedit_block_type_tpl'); ?></option>
+                <option value="<?php echo BLOCK_HTML; ?>"><?php echo $lang->get('sbedit_block_type_html'); ?></option>
+                <option value="<?php echo BLOCK_PHP; ?>"><?php echo $lang->get('sbedit_block_type_php'); ?></option>
+                <option value="<?php echo BLOCK_PLUGIN; ?>"><?php echo $lang->get('sbedit_block_type_plugin'); ?></option>
               </select>
             </p>
             
             <p>
             
-              Block title: <input name="title" type="text" size="40" /><br />
-              Which sidebar: <select name="sidebar_id"><option value="<?php echo SIDEBAR_LEFT; ?>">Left</option><option value="<?php echo SIDEBAR_RIGHT; ?>">Right</option></select>
+              <?php echo $lang->get('sbedit_field_block_title'); ?> <input name="title" type="text" size="40" /><br />
+              <?php echo $lang->get('sbedit_field_block_sidebar'); ?>
+                <select name="sidebar_id">
+                  <option value="<?php echo SIDEBAR_LEFT; ?>"><?php echo $lang->get('sbedit_field_block_sidebar_left'); ?></option>
+                  <option value="<?php echo SIDEBAR_RIGHT; ?>"><?php echo $lang->get('sbedit_field_block_sidebar_right'); ?></option>
+                </select>
             
             </p>
             
             <div class="sbadd_block" id="blocktype_<?php echo BLOCK_WIKIFORMAT; ?>">
               <p>
-                Wikitext:
+                <?php echo $lang->get('sbedit_field_wikitext'); ?>
               </p>
               <p>
                 <textarea style="width: 98%;" name="wikiformat_content" rows="15" cols="50"></textarea>
@@ -2652,7 +2213,7 @@
             
             <div class="sbadd_block" id="blocktype_<?php echo BLOCK_TEMPLATEFORMAT; ?>">
               <p>
-                Template code:
+                <?php echo $lang->get('sbedit_field_tplcode'); ?>
               </p>
               <p>
                 <textarea style="width: 98%;" name="templateformat_content" rows="15" cols="50"></textarea>
@@ -2661,7 +2222,7 @@
             
             <div class="sbadd_block" id="blocktype_<?php echo BLOCK_HTML; ?>">
               <p>
-                HTML to place inside the sidebar:
+                <?php echo $lang->get('sbedit_field_html'); ?>
               </p>
               <p>
                 <textarea style="width: 98%;" name="html_content" rows="15" cols="50"></textarea>
@@ -2670,26 +2231,10 @@
             
             <div class="sbadd_block" id="blocktype_<?php echo BLOCK_PHP; ?>">
               <?php if ( defined('ENANO_DEMO_MODE') ) { ?>
-                <p>Creating PHP blocks in demo mode is disabled for security reasons.</p>
+                <p><?php echo $lang->get('sbedit_field_php_disabled'); ?></p>
               <?php } else { ?>
-              <p>
-                <b>WARNING:</b> If you don't know what you're doing, or if you are not fluent in PHP, stop now and choose a different block type. You will brick your Enano installation if you are not careful here.
-                ALWAYS remember to write secure code! The Enano team is not responsible if someone drops all your tables because of an SQL injection vulnerability in your sidebar code. You are probably better off using the template-formatted block type.
-              </p>
-              <p>
-                <span style="color: red;">
-                  It is especially important to note that this code is NOT checked for errors! If there is a syntax error in your code here, it will prevent any pages from loading AT ALL. So you need to use an external PHP editor (like <a href="http://www.jedit.org">jEdit</a>) to check your syntax before you hit save.
-                </span> You have been warned.
-              </p>
-              <p>
-                Also, you should avoid using output buffering functions (ob_[start|end|get_contents|clean]) here, because Enano uses those to track output from this script.
-              </p>
-              <p>
-                The standard &lt;?php and ?&gt; tags work here. Don't use an initial "&lt;?php" or it will cause a parse error.
-              </p>
-              <p>
-                PHP code:
-              </p>
+              <?php echo $lang->get('sbedit_field_php'); ?>
+              
               <p>
                 <textarea style="width: 98%;" name="php_content" rows="15" cols="50"></textarea>
               </p>
@@ -2698,7 +2243,7 @@
             
             <div class="sbadd_block" id="blocktype_<?php echo BLOCK_PLUGIN; ?>">
               <p>
-                Plugin:
+                <?php echo $lang->get('sbedit_field_plugin'); ?>
               </p>
               <p>
                 <select name="plugin_id">
@@ -2714,8 +2259,8 @@
             
             <p>
             
-              <input type="submit" name="create" value="Create new block" style="font-weight: bold;" />&nbsp;
-              <input type="submit" name="cancel" value="Cancel" />
+              <input type="submit" name="create" value="<?php echo $lang->get('sbedit_btn_create_block'); ?>" style="font-weight: bold;" />&nbsp;
+              <input type="submit" name="cancel" value="<?php echo $lang->get('etc_cancel'); ?>" />
             
             </p>
             
@@ -2746,7 +2291,7 @@
             $template->footer();
             exit;
           }
-          echo '<div class="info-box" style="margin: 10px 0;">Item moved.</div>';
+          echo '<div class="info-box" style="margin: 10px 0;">' . $lang->get('sbedit_msg_block_moved') . '</div>';
           break;
         case 'delete':
           $query = $db->sql_query('DELETE FROM '.table_prefix.'sidebar WHERE item_id=' . intval($_GET['id']) . ';'); // Already checked for injection attempts ;-)
@@ -2761,7 +2306,7 @@
             ob_end_clean();
             die('GOOD');
           }
-          echo '<div class="error-box" style="margin: 10px 0;">Item deleted.</div>';
+          echo '<div class="error-box" style="margin: 10px 0;">' . $lang->get('sbedit_msg_block_deleted') . '</div>';
           break;
         case 'disenable';
           $q = $db->sql_query('SELECT item_enabled FROM '.table_prefix.'sidebar WHERE item_id=' . intval($_GET['id']) . ';');
@@ -2871,7 +2416,7 @@
               $c = preg_replace('#<a (.*?)>(.*?)</a>#is', '<a href="#" onclick="return false;">\\2</a>', $c);
               break;
             case BLOCK_PLUGIN:
-              $c = ($template->fetch_block($row['block_content'])) ? $template->fetch_block($row['block_content']) : 'Can\'t find plugin block';
+              $c = ($template->fetch_block($row['block_content'])) ? $template->fetch_block($row['block_content']) : $lang->get('sbedit_msg_plugin_not_loaded');
               break;
           }
           die('var status = \'GOOD\'; var content = unescape(\''.hexencode($c).'\');');
@@ -2888,11 +2433,11 @@
     $parser->assign_vars(Array(
         'HREF'=>'#',
         'FLAGS'=>'onclick="return false;"',
-        'TEXT'=>'Change theme'
+        'TEXT' => $lang->get('sidebar_btn_changestyle')
       ));
     $template->tpl_strings['THEME_LINK'] = $parser->run();
     $parser->assign_vars(Array(
-        'TEXT'=>'Log out',
+        'TEXT' => $lang->get('sidebar_btn_logout'),
       ));
     $template->tpl_strings['LOGOUT_LINK'] = $parser->run();
     
@@ -2951,20 +2496,20 @@
           break;
         case BLOCK_PLUGIN:
           $parser = $template->makeParserText($vars['sidebar_section_raw']);
-          $c = ($template->fetch_block($row['block_content'])) ? $template->fetch_block($row['block_content']) : 'Can\'t find plugin block';
+          $c = ($template->fetch_block($row['block_content'])) ? $template->fetch_block($row['block_content']) : $lang->get('sbedit_msg_plugin_not_loaded');
           break;
       }
-      $block_name = $template->tplWikiFormat($row['block_name']);
+      $block_name = $row['block_name']; // $template->tplWikiFormat($row['block_name']);
       if ( empty($block_name) )
-        $block_name = '&lt;Unnamed&gt;';
-      $t = '<span title="Double-click to rename this block" id="sbrename_' . $row['item_id'] . '" ondblclick="ajaxRenameSidebarStage1(this, \''.$row['item_id'].'\'); return false;">' . $block_name . '</span>';
-      if($row['item_enabled'] == 0) $t .= ' <span id="disabled_'.$row['item_id'].'" style="color: red;">(disabled)</span>';
-      else           $t .= ' <span id="disabled_'.$row['item_id'].'" style="color: red; display: none;">(disabled)</span>';
+        $block_name = '&lt;' . $lang->get('sbedit_note_block_unnamed') . '&gt;';
+      $t = '<span title="' . $lang->get('sbedit_hint_rename') . '" id="sbrename_' . $row['item_id'] . '" ondblclick="ajaxRenameSidebarStage1(this, \''.$row['item_id'].'\'); return false;">' . $block_name . '</span>';
+      if($row['item_enabled'] == 0) $t .= ' <span id="disabled_'.$row['item_id'].'" style="color: red;">' . $lang->get('sbedit_note_block_disabled') . '</span>';
+      else           $t .= ' <span id="disabled_'.$row['item_id'].'" style="color: red; display: none;">' . $lang->get('sbedit_note_block_disabled') . '</span>';
       $side = ( $row['sidebar_id'] == SIDEBAR_LEFT ) ? SIDEBAR_RIGHT : SIDEBAR_LEFT;
-      $tb = '<a title="Enable or disable this block"    href="'.makeUrl($paths->page, 'action=disenable&id='.$row['item_id'].''       , true).'" onclick="ajaxDisenableBlock(\''.$row['item_id'].'\'); return false;"   ><img alt="Enable/disable this block" style="border-width: 0;" src="'.scriptPath.'/images/disenable.png" /></a>
-             <a title="Edit the contents of this block" href="'.makeUrl($paths->page, 'action=edit&id='.$row['item_id'].''            , true).'" onclick="ajaxEditBlock(\''.$row['item_id'].'\', this); return false;"><img alt="Edit this block" style="border-width: 0;" src="'.scriptPath.'/images/edit.png" /></a>
-             <a title="Permanently delete this block"   href="'.makeUrl($paths->page, 'action=delete&id='.$row['item_id'].''          , true).'" onclick="if(confirm(\'Do you really want to delete this block?\')) { ajaxDeleteBlock(\''.$row['item_id'].'\', this); } return false;"><img alt="Delete this block" style="border-width: 0;" src="'.scriptPath.'/images/delete.png" /></a>
-             <a title="Move this block to the other sidebar" href="'.makeUrl($paths->page, 'action=move&id='.$row['item_id'].'&side='.$side, true).'"><img alt="Move this block" style="border-width: 0;" src="'.scriptPath.'/images/move.png" /></a>';
+      $tb = '<a title="' . $lang->get('sbedit_tip_disenable') . '" href="'.makeUrl($paths->page, 'action=disenable&id='.$row['item_id'].''       , true).'" onclick="ajaxDisenableBlock(\''.$row['item_id'].'\'); return false;"   ><img alt="' . $lang->get('sbedit_tip_disenable') . '" style="border-width: 0;" src="'.scriptPath.'/images/disenable.png" /></a>
+             <a title="' . $lang->get('sbedit_tip_edit') . '"      href="'.makeUrl($paths->page, 'action=edit&id='.$row['item_id'].''            , true).'" onclick="ajaxEditBlock(\''.$row['item_id'].'\', this); return false;"><img alt="' . $lang->get('sbedit_tip_edit') . '" style="border-width: 0;" src="'.scriptPath.'/images/edit.png" /></a>
+             <a title="' . $lang->get('sbedit_tip_delete') . '"    href="'.makeUrl($paths->page, 'action=delete&id='.$row['item_id'].''          , true).'" onclick="if(confirm(\'' . $lang->get('sbedit_msg_delete_confirm') . '\')) { ajaxDeleteBlock(\''.$row['item_id'].'\', this); } return false;"><img alt="' . $lang->get('sbedit_tip_delete') . '" style="border-width: 0;" src="'.scriptPath.'/images/delete.png" /></a>
+             <a title="' . $lang->get('sbedit_tip_move') . '"      href="'.makeUrl($paths->page, 'action=move&id='.$row['item_id'].'&side='.$side, true).'"><img alt="' . $lang->get('sbedit_tip_move') . '" style="border-width: 0;" src="'.scriptPath.'/images/move.png" /></a>';
       $as = '';
       $ae = '&nbsp;&nbsp;'.$tb;
       $parser->assign_vars(Array('CONTENT'=>$c,'TITLE'=>$t,'ADMIN_START'=>$as,'ADMIN_END'=>$ae));
@@ -2982,10 +2527,10 @@
     echo "<input type='hidden' id='divOrder_Right' name='order_right' value='{$order}' />";
     echo '
           <div style="margin: 0 auto 0 auto; text-align: center;">
-            <input type="submit" name="save" style="font-weight: bold;" value="Save changes" />
-            <input type="submit" name="revert" style="font-weight: normal;" value="Revert" onclick="return confirm(\'Do you really want to revert your changes?\nNote: this does not revert edits or deletions, those are saved as soon as you confirm the action.\')" />
+            <input type="submit" name="save" style="font-weight: bold;" value="' . $lang->get('etc_save_changes') . '" />
+            <input type="submit" name="revert" style="font-weight: normal;" value="' . $lang->get('sbedit_btn_revert') . '" onclick="return confirm($lang.get(\'sbedit_msg_discard_order_confirm\'))" />
             <br />
-            <a href="'.makeUrl($paths->page, 'action=new&id=0', true).'">Create new block</a>  |  <a href="'.makeUrl(getConfig('main_page'), false, true).'">Main Page</a>
+            <a href="'.makeUrl($paths->page, 'action=new&id=0', true).'">' . $lang->get('sbedit_btn_create_new_stage1') . '</a>  |  <a href="'.makeUrl(getConfig('main_page'), false, true).'">' . $lang->get('sbedit_btn_main_page') . '</a>
           </div>
         </form>
          ';
--- a/plugins/SpecialCSS.php	Fri Feb 22 12:46:51 2008 -0500
+++ b/plugins/SpecialCSS.php	Fri Feb 22 12:51:53 2008 -0500
@@ -1,16 +1,16 @@
 <?php
 /*
-Plugin Name: CSS Backend
+Plugin Name: plugin_specialcss_title
 Plugin URI: http://enanocms.org/
-Description: Provides the page Special:CSS, which is used in template files to reference the style sheet. Disabling or deleting this plugin will result in site instability.
+Description: plugin_specialcss_desc
 Author: Dan Fuhry
-Version: 1.0.3
+Version: 1.1.1
 Author URI: http://enanocms.org/
 */
 
 /*
  * Enano - an open-source CMS capable of wiki functions, Drupal-like sidebar blocks, and everything in between
- * Version 1.0.3
+ * Version 1.1.2 (Caoineag alpha 2)
  * Copyright (C) 2006-2007 Dan Fuhry
  *
  * This program is Free Software; you can redistribute and/or modify it under the terms of the GNU General Public License
@@ -22,10 +22,10 @@
  
 global $db, $session, $paths, $template, $plugins; // Common objects
 
-$plugins->attachHook('base_classes_initted', '
+$plugins->attachHook('session_started', '
   global $paths;
     $paths->add_page(Array(
-      \'name\'=>\'CSS\',
+      \'name\'=>\'specialpage_css\',
       \'urlname\'=>\'CSS\',
       \'namespace\'=>\'Special\',
       \'special\'=>0,\'visible\'=>0,\'comments_on\'=>0,\'protected\'=>1,\'delvotes\'=>0,\'delvote_ips\'=>\'\',
--- a/plugins/SpecialGroups.php	Fri Feb 22 12:46:51 2008 -0500
+++ b/plugins/SpecialGroups.php	Fri Feb 22 12:51:53 2008 -0500
@@ -1,16 +1,16 @@
 <?php
 /*
-Plugin Name: Group control panel
+Plugin Name: plugin_specialgroups_title
 Plugin URI: http://enanocms.org/
-Description: Provides group moderators and site administrators with the ability to control who is part of their groups. 
+Description: plugin_specialgroups_desc
 Author: Dan Fuhry
-Version: 1.0.3
+Version: 1.1.1
 Author URI: http://enanocms.org/
 */
 
 /*
  * Enano - an open-source CMS capable of wiki functions, Drupal-like sidebar blocks, and everything in between
- * Version 1.0.3
+ * Version 1.1.2 (Caoineag alpha 2)
  * Copyright (C) 2007 Dan Fuhry
  *
  * This program is Free Software; you can redistribute and/or modify it under the terms of the GNU General Public License
@@ -20,10 +20,10 @@
  * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for details.
  */
 
-$plugins->attachHook('base_classes_initted', '
+$plugins->attachHook('session_started', '
   global $paths;
     $paths->add_page(Array(
-      \'name\'=>\'Group Membership\',
+      \'name\'=>\'specialpage_groupcp\',
       \'urlname\'=>\'Usergroups\',
       \'namespace\'=>\'Special\',
       \'special\'=>0,\'visible\'=>1,\'comments_on\'=>0,\'protected\'=>1,\'delvotes\'=>0,\'delvote_ips\'=>\'\',
@@ -34,6 +34,7 @@
 {
   global $db, $session, $paths, $template, $plugins; // Common objects
   global $email; // Import e-mail encryption functions
+  global $lang;
   
   if ( !$session->user_logged_in )
   {
@@ -43,6 +44,7 @@
   }
   
   $template->header();
+  userprefs_show_menu();
   if ( isset($_POST['do_view']) || isset($_POST['do_view_n']) || ( isset($_GET['act']) && isset($_POST['group_id']) ) )
   {
     $gid = ( isset ( $_POST['do_view_n'] ) ) ? intval($_POST['group_id_n']) : intval($_POST['group_id']);
@@ -102,20 +104,20 @@
     }
     
     $status = ( $is_member && $is_mod )
-      ? 'You are a moderator of this group.'
+      ? $lang->get('groupcp_status_mod')
       : ( ( $is_member && !$is_mod ) 
-        ? 'You are a member of this group.'
-        : 'You are not a member of this group.'
+        ? $lang->get('groupcp_status_member')
+        : $lang->get('groupcp_status_not_member')
         );
       
     $can_do_admin_stuff = ( $is_mod || $session->user_level >= USER_LEVEL_ADMIN );
       
     switch ( $row['group_type'] )
     {
-      case GROUP_HIDDEN:  $g_state = 'Hidden group';                break;
-      case GROUP_CLOSED:  $g_state = 'Closed group';                break;
-      case GROUP_REQUEST: $g_state = 'Members can request to join'; break;
-      case GROUP_OPEN:    $g_state = 'Anyone can join';             break;
+      case GROUP_HIDDEN:  $g_state = $lang->get('groupcp_type_hidden'); break;
+      case GROUP_CLOSED:  $g_state = $lang->get('groupcp_type_closed'); break;
+      case GROUP_REQUEST: $g_state = $lang->get('groupcp_type_request'); break;
+      case GROUP_OPEN:    $g_state = $lang->get('groupcp_type_open'); break;
     }
     
     if ( isset($_GET['act']) && $can_do_admin_stuff )
@@ -139,7 +141,7 @@
           $r = $db->fetchrow();
           if ( $r['system_group'] == 1 && ( intval($_POST['group_state']) == GROUP_OPEN || intval($_POST['group_state']) == GROUP_REQUEST ) )
           {
-            echo '<div class="error-box" style="margin-left: 0;">Because this is a system group, you can\'t make it open or allow membership requests.</div>';
+            echo '<div class="error-box" style="margin-left: 0;">' . $lang->get('groupcp_err_state_system_group') . '</div>';
             $error = true;
           }
           if ( !$error )
@@ -148,7 +150,7 @@
             if (!$q)
               $db->_die('SpecialGroups.php, line ' . __LINE__);
             $row['group_type'] = $_POST['group_state'];
-            echo '<div class="info-box" style="margin-left: 0;">The group state was updated.</div>';
+            echo '<div class="info-box" style="margin-left: 0;">' . $lang->get('groupcp_msg_state_updated') . '</div>';
           }
           break;
         case 'adduser':
@@ -160,7 +162,7 @@
             $db->_die('SpecialGroups.php, line ' . __LINE__);
           if ($db->numrows() < 1)
           {
-            echo '<div class="error-box">The username you entered could not be found.</div>';
+            echo '<div class="error-box">' . $lang->get('groupcp_err_user_not_found') . '</div>';
             break;
           }
           $r = $db->fetchrow();
@@ -184,11 +186,11 @@
                 if ( $member['member_id'] == $r['member_id'] )
                   $members[$i]['is_mod'] = (int)$mod;
               }
-              echo '<div class="info-box">The user "' . $username . '" is already in this group, so their moderator status was updated.</div>';
+              echo '<div class="info-box">' . $lang->get('groupcp_msg_user_already_in_mod_updated', array('username' => $username)) . '</div>';
             }
             else
             {
-              echo '<div class="info-box">The user "' . $username . '" is already in this group.</div>';
+              echo '<div class="info-box">' . $lang->get('groupcp_msg_user_already_in', array('username' => $username)) . '</div>';
             }
             break;
           }
@@ -198,7 +200,7 @@
           $q = $db->sql_query('INSERT INTO '.table_prefix.'group_members(group_id,user_id,is_mod) VALUES(' . intval($_POST['group_id']) . ', ' . $uid . ', ' . $mod . ');');
           if (!$q)
             $db->_die('SpecialGroups.php, line ' . __LINE__);
-          echo '<div class="info-box">The user "' . $username . '" has been added to this usergroup.</div>';
+          echo '<div class="info-box">' . $lang->get('groupcp_msg_user_added', array('username' => $username)) . '</div>';
           
           $q = $db->sql_query('SELECT u.username,u.email,u.reg_time,m.member_id,m.user_id,m.is_mod,COUNT(c.comment_id) AS num_comments
                                  FROM '.table_prefix.'users AS u
@@ -255,17 +257,17 @@
               }
             }
           }
-          echo '<div class="info-box">Pending members status updated successfully.</div>';
+          echo '<div class="info-box">' . $lang->get('groupcp_msg_pending_updated') . '</div>';
           break;
       }
     }
     
-    if ( isset($_GET['act']) && $_GET['act'] == 'update' && !$is_member && $row['group_type'] == GROUP_OPEN )
+    if ( isset($_GET['act']) && $_GET['act'] == 'update' && !$is_member && $row['group_type'] == GROUP_OPEN && !$can_do_admin_stuff )
     {
       $q = $db->sql_query('INSERT INTO '.table_prefix.'group_members(group_id,user_id) VALUES(' . $gid . ', ' . $session->user_id . ');');
       if (!$q)
         $db->_die('SpecialGroups.php, line ' . __LINE__);
-      echo '<div class="info-box">You have been added to this group.</div>';
+      echo '<div class="info-box">' . $lang->get('groupcp_msg_self_added') . '</div>';
       
       $q = $db->sql_query('SELECT u.username,u.email,u.reg_time,m.member_id,m.user_id,m.is_mod,COUNT(c.comment_id) AS num_comments
                              FROM '.table_prefix.'users AS u
@@ -288,55 +290,60 @@
       
     }
     
-    if ( isset($_GET['act']) && $_GET['act'] == 'update' && !$is_member && $row['group_type'] == GROUP_REQUEST && !$is_pending )
+    if ( isset($_GET['act']) && $_GET['act'] == 'update' && !$is_member && $row['group_type'] == GROUP_REQUEST && !$is_pending && !$can_do_admin_stuff )
     {
       $q = $db->sql_query('INSERT INTO '.table_prefix.'group_members(group_id,user_id,pending) VALUES(' . $gid . ', ' . $session->user_id . ', 1);');
       if (!$q)
         $db->_die('SpecialGroups.php, line ' . __LINE__);
-      echo '<div class="info-box">A request has been sent to the moderator(s) of this group to add you.</div>';
+      echo '<div class="info-box">' . $lang->get('groupcp_msg_membership_requested') . '</div>';
     }
     
     $state_btns = ( $can_do_admin_stuff ) ?
-                  '<label><input type="radio" name="group_state" value="' . GROUP_HIDDEN . '" ' . (( $row['group_type'] == GROUP_HIDDEN ) ? 'checked="checked"' : '' ) . ' /> Hidden group</label>
-                   <label><input type="radio" name="group_state" value="' . GROUP_CLOSED . '" ' . (( $row['group_type'] == GROUP_CLOSED ) ? 'checked="checked"' : '' ) . ' /> Closed group</label>
-                   <label><input type="radio" name="group_state" value="' . GROUP_REQUEST. '" ' . (( $row['group_type'] == GROUP_REQUEST) ? 'checked="checked"' : '' ) . ' /> Members can request to join</label>
-                   <label><input type="radio" name="group_state" value="' . GROUP_OPEN   . '" ' . (( $row['group_type'] == GROUP_OPEN   ) ? 'checked="checked"' : '' ) . ' /> Anybody can join</label>'
+                  '<label><input type="radio" name="group_state" value="' . GROUP_HIDDEN . '" ' . (( $row['group_type'] == GROUP_HIDDEN ) ? 'checked="checked"' : '' ) . ' /> ' . $lang->get('groupcp_type_hidden') . '</label>
+                   <label><input type="radio" name="group_state" value="' . GROUP_CLOSED . '" ' . (( $row['group_type'] == GROUP_CLOSED ) ? 'checked="checked"' : '' ) . ' /> ' . $lang->get('groupcp_type_closed') . '</label>
+                   <label><input type="radio" name="group_state" value="' . GROUP_REQUEST. '" ' . (( $row['group_type'] == GROUP_REQUEST) ? 'checked="checked"' : '' ) . ' /> ' . $lang->get('groupcp_type_request') . '</label>
+                   <label><input type="radio" name="group_state" value="' . GROUP_OPEN   . '" ' . (( $row['group_type'] == GROUP_OPEN   ) ? 'checked="checked"' : '' ) . ' /> ' . $lang->get('groupcp_type_open') . '</label>'
                    : $g_state;
     if ( !$can_do_admin_stuff && $row['group_type'] == GROUP_REQUEST && !$is_member )
     {
       if ( $is_pending )
-        $state_btns .= ' (Your request to join is awaiting approval)';
+        $state_btns .= ' ' . $lang->get('groupcp_msg_status_pending');
       else
-        $state_btns .= ' <input type="submit" value="Request membership" />';
+        $state_btns .= ' <input type="submit" value="' . $lang->get('groupcp_btn_request_join') . '" />';
     }
     
     if ( !$can_do_admin_stuff && $row['group_type'] == GROUP_OPEN && !$is_member )
     {
-      $state_btns .= ' <input type="submit" value="Join this group" />';
+      $state_btns .= ' <input type="submit" value="' . $lang->get('groupcp_btn_join') . '" />';
     }
     
+    $g_name_local = 'groupcp_grp_' . strtolower($row['group_name']);
+    $str = $lang->get($g_name_local);
+    if ( $str != $g_name_local )
+      $row['group_name'] = $str;
+    
     echo '<form action="' . makeUrl($paths->page, 'act=update') . '" method="post" enctype="multipart/form-data">
           <div class="tblholder">
             <table border="0" cellspacing="1" cellpadding="4">
               <tr>
-                <th colspan="2">Group information</th>
+                <th colspan="2">' . $lang->get('groupcp_th_group_info') . '</th>
               </tr>
               <tr>
-                <td class="row2">Group name:</td>
-                <td class="row1">' . $row['group_name'] . ( $row['system_group'] == 1 ? ' (system group)' : '' ) . '</td>
+                <td class="row2">' . $lang->get('groupcp_lbl_group_name') . '</td>
+                <td class="row1">' . $row['group_name'] . ( $row['system_group'] == 1 ? ' ' . $lang->get('groupcp_msg_system_group') : '' ) . '</td>
               </tr>
               <tr>
-                <td class="row2">Membership status:</td>
+                <td class="row2">' . $lang->get('groupcp_lbl_status') . '</td>
                 <td class="row1">' . $status . '</td>
               </tr>
               <tr>
-                <td class="row2">Group state:</td>
+                <td class="row2">' . $lang->get('groupcp_lbl_state') . '</td>
                 <td class="row1">' . $state_btns . '</td>
               </tr>   
               ' . ( ( $is_mod || $session->user_level >= USER_LEVEL_ADMIN ) ? '
               <tr>
                 <th class="subhead" colspan="2">
-                  <input type="submit" value="Save changes" />
+                  <input type="submit" value="' . $lang->get('etc_save_changes') . '" />
                 </th>
               </tr>
               ' : '' ) . '
@@ -348,21 +355,21 @@
     {
       echo '<form action="' . makeUrl($paths->page, 'act=pending') . '" method="post" enctype="multipart/form-data">
             <input name="group_id" value="' . $gid . '" type="hidden" />
-            <h2>Pending memberships</h2>
+            <h2>' . $lang->get('groupcp_th_pending_memberships') . '</h2>
             <div class="tblholder">
             <table border="0" cellspacing="1" cellpadding="4">
               <tr>
-                <th>Username</th>
-                <th>E-mail</th>
-                <th>Registered</th>
-                <th>Total comments</th>
-                <th>Select</th>
+                <th>' . $lang->get('groupcp_th_username') . '</th>
+                <th>' . $lang->get('groupcp_th_email') . '</th>
+                <th>' . $lang->get('groupcp_th_reg_time') . '</th>
+                <th>' . $lang->get('groupcp_th_comments') . '</th>
+                <th>' . $lang->get('groupcp_th_select') . '</th>
               </tr>';
       $cls = 'row2';
       foreach ( $pending as $member )
       {
         
-        $date = date('F d, Y', $member['reg_time']);
+        $date = enano_date('F d, Y', $member['reg_time']);
         $cls = ( $cls == 'row2' ) ? 'row1' : 'row2';
         $addy = $email->encryptEmail($member['email']);
         
@@ -378,26 +385,26 @@
             </div>
             <div style="margin: 10px 0 0 auto;">
               With selected: 
-              <input type="submit" name="do_appr_pending" value="Approve membership" />
-              <input type="submit" name="do_reject_pending" value="Reject membership" />
+              <input type="submit" name="do_appr_pending" value="' . $lang->get('groupcp_btn_approve_pending') . '" />
+              <input type="submit" name="do_reject_pending" value="' . $lang->get('groupcp_btn_reject_pending') . '" />
             </div>
             </form>';
     }
     echo '<form action="' . makeUrl($paths->page, 'act=del_users') . '" method="post" enctype="multipart/form-data">
-          <h2>Group members</h2>
+          <h2>' . $lang->get('groupcp_th_group_members') . '</h2>
           <div class="tblholder">
             <table border="0" cellspacing="1" cellpadding="4">
               <tr>
-                <th>Username</th>
-                <th>E-mail</th>
-                <th>Registered</th>
-                <th>Total comments</th>
-                ' . ( ( $can_do_admin_stuff ) ? "
-                <th>Remove?</th>
-                " : '' ) . '
+                <th>' . $lang->get('groupcp_th_username') . '</th>
+                <th>' . $lang->get('groupcp_th_email') . '</th>
+                <th>' . $lang->get('groupcp_th_reg_time') . '</th>
+                <th>' . $lang->get('groupcp_th_comments') . '</th>
+                ' . ( ( $can_do_admin_stuff ) ? '
+                <th>' . $lang->get('groupcp_th_remove') . '</th>
+                ' : '' ) . '
               </tr>
               <tr>
-                <th colspan="5" class="subhead">Group moderators</th>
+                <th colspan="5" class="subhead">' . $lang->get('groupcp_th_group_mods') . '</th>
               </tr>';
     $mod_printed = false;
     $mem_printed = false;
@@ -408,7 +415,7 @@
       if ( $member['is_mod'] != 1 )
         break;
       
-      $date = date('F d, Y', $member['reg_time']);
+      $date = enano_date('F d, Y', $member['reg_time']);
       $cls = ( $cls == 'row2' ) ? 'row1' : 'row2';
       $addy = $email->encryptEmail($member['email']);
       
@@ -425,14 +432,14 @@
             </tr>";
     }
     if (!$mod_printed)
-      echo '<tr><td class="' . $cls . '" colspan="5">This group has no moderators.</td></th>';
-    echo '<tr><th class="subhead" colspan="5">Group members</th></tr>';
+      echo '<tr><td class="' . $cls . '" colspan="5">' . $lang->get('groupcp_msg_no_mods') . '</td></th>';
+    echo '<tr><th class="subhead" colspan="5">' . $lang->get('groupcp_th_group_members') . '</th></tr>';
     foreach ( $members as $member )
     {
       if ( $member['is_mod'] == 1 )
         continue;
       
-      $date = date('F d, Y', $member['reg_time']);
+      $date = enano_date('F d, Y', $member['reg_time']);
       $cls = ( $cls == 'row2' ) ? 'row1' : 'row2';
       $addy = $email->encryptEmail($member['email']);
       
@@ -449,12 +456,12 @@
             </tr>";
     }
     if (!$mem_printed)
-      echo '<tr><td class="' . $cls . '" colspan="5">This group has no members.</td></th>';
+      echo '<tr><td class="' . $cls . '" colspan="5">' . $lang->get('groupcp_msg_no_members') . '</td></th>';
     echo '  </table>
           </div>';
     if ( $can_do_admin_stuff )
     {
-      echo "<div style='margin: 10px 0 0 auto;'><input type='submit' name='do_del_user' value='Remove selected users' /></div>";
+      echo "<div style='margin: 10px 0 0 auto;'><input type='submit' name='do_del_user' value=\"" . $lang->get('groupcp_btn_remove_selected') . "\" /></div>";
     }
     echo '<input name="group_id" value="' . $gid . '" type="hidden" />
           </form>';
@@ -464,17 +471,17 @@
               <div class="tblholder">
                 <table border="0" cellspacing="1" cellpadding="4">
                   <tr>
-                    <th colspan="2">Add a new member to this group</th>
+                    <th colspan="2">' . $lang->get('groupcp_th_add_member') . '</th>
                   </tr>
                   <tr>
-                    <td class="row2">Username:</td><td class="row1">' . $template->username_field('add_username') . '</td>
+                    <td class="row2">' . $lang->get('groupcp_lbl_username') . '</td><td class="row1">' . $template->username_field('add_username') . '</td>
                   </tr>
                   <tr>
-                    <td class="row2">Group moderator:</td><td class="row1"><label><input type="checkbox" name="add_mod" /> User is a group moderator</label></td>
+                    <td class="row2">' . $lang->get('groupcp_lbl_moderator') . '</td><td class="row1"><label><input type="checkbox" name="add_mod" /> ' . $lang->get('groupcp_lbl_make_mod') . '</label></td>
                   </tr>
                   <tr>
                     <th class="subhead" colspan="2">
-                      <input type="submit" value="Add member" />
+                      <input type="submit" value="' . $lang->get('groupcp_btn_add_member') . '" />
                     </th>
                   </tr>
                 </table>
@@ -489,11 +496,11 @@
     echo '<div class="tblholder">
           <table border="0" style="width: 100%;" cellspacing="1" cellpadding="4">
             <tr>
-              <th colspan="2">Group membership details</th>
+              <th colspan="2">' . $lang->get('groupcp_th_select_group') . '</th>
             </tr>
             <tr>
               <td class="row2" style="text-align: right; width: 50%;">
-                Current group memberships:
+                ' . $lang->get('groupcp_lbl_current_memberships') . '
               </td>
               <td class="row1" style="width: 50%;">';
     $taboo = Array('Everyone');
@@ -506,11 +513,15 @@
         $group = htmlspecialchars($group);
         if ( $group != 'Everyone' )
         {
+          $g_name_local = 'groupcp_grp_' . strtolower($group);
+          $str = $lang->get($g_name_local);
+          if ( $str != $g_name_local )
+            $group = $str;
           echo '<option value="' . $id . '">' . $group . '</option>';
         }
       }
       echo '</select>
-            <input type="submit" name="do_view" value="View information" />';
+            <input type="submit" name="do_view" value="' . $lang->get('groupcp_btn_view') . '" />';
     }
     else
     {
@@ -531,7 +542,7 @@
     {
       echo '<tr>
               <td class="row2" style="text-align: right;">
-                Non-memberships:
+                ' . $lang->get('groupcp_lbl_non_memberships') . '
               </td>
               <td class="row1">
               <select name="group_id_n">';
@@ -539,11 +550,11 @@
       {
         if ( $row['group_name'] != 'Everyone' )
         {
-          echo '<option value="' . $row['group_id'] . '">' . $row['group_name'] . '</option>';
+          echo '<option value="' . $row['group_id'] . '">' . htmlspecialchars($row['group_name']) . '</option>';
         }
       }
       echo '</select>
-            <input type="submit" name="do_view_n" value="View information" />
+            <input type="submit" name="do_view_n" value="' . $lang->get('groupcp_btn_view') . '" />
           </td>
         </tr>
       ';
--- a/plugins/SpecialPageFuncs.php	Fri Feb 22 12:46:51 2008 -0500
+++ b/plugins/SpecialPageFuncs.php	Fri Feb 22 12:51:53 2008 -0500
@@ -1,16 +1,16 @@
 <?php
 /*
-Plugin Name: Special page-related pages
+Plugin Name: plugin_specialpagefuncs_title
 Plugin URI: http://enanocms.org/
-Description: Provides the page Special:CreatePage, which can be used to create new pages. Also adds the About Enano and GNU General Public License pages.
+Description: plugin_specialpagefuncs_desc
 Author: Dan Fuhry
-Version: 1.0.3
+Version: 1.1.1
 Author URI: http://enanocms.org/
 */
 
 /*
  * Enano - an open-source CMS capable of wiki functions, Drupal-like sidebar blocks, and everything in between
- * Version 1.0.3
+ * Version 1.1.2 (Caoineag alpha 2)
  * Copyright (C) 2006-2007 Dan Fuhry
  *
  * This program is Free Software; you can redistribute and/or modify it under the terms of the GNU General Public License
@@ -22,45 +22,45 @@
  
 global $db, $session, $paths, $template, $plugins; // Common objects
 
-$plugins->attachHook('base_classes_initted', '
+$plugins->attachHook('session_started', '
   global $paths;
     $paths->add_page(Array(
-      \'name\'=>\'Create page\',
+      \'name\'=>\'specialpage_create_page\',
       \'urlname\'=>\'CreatePage\',
       \'namespace\'=>\'Special\',
       \'special\'=>0,\'visible\'=>1,\'comments_on\'=>0,\'protected\'=>1,\'delvotes\'=>0,\'delvote_ips\'=>\'\',
       ));
     
     $paths->add_page(Array(
-      \'name\'=>\'All pages\',
+      \'name\'=>\'specialpage_all_pages\',
       \'urlname\'=>\'AllPages\',
       \'namespace\'=>\'Special\',
       \'special\'=>0,\'visible\'=>1,\'comments_on\'=>0,\'protected\'=>1,\'delvotes\'=>0,\'delvote_ips\'=>\'\',
       ));
     
     $paths->add_page(Array(
-      \'name\'=>\'List of special pages\',
+      \'name\'=>\'specialpage_special_pages\',
       \'urlname\'=>\'SpecialPages\',
       \'namespace\'=>\'Special\',
       \'special\'=>0,\'visible\'=>1,\'comments_on\'=>0,\'protected\'=>1,\'delvotes\'=>0,\'delvote_ips\'=>\'\',
       ));
     
     $paths->add_page(Array(
-      \'name\'=>\'About Enano\',
+      \'name\'=>\'specialpage_about_enano\',
       \'urlname\'=>\'About_Enano\',
       \'namespace\'=>\'Special\',
       \'special\'=>0,\'visible\'=>1,\'comments_on\'=>0,\'protected\'=>1,\'delvotes\'=>0,\'delvote_ips\'=>\'\',
       ));
     
     $paths->add_page(Array(
-      \'name\'=>\'GNU General Public License\',
+      \'name\'=>\'specialpage_gnu_gpl\',
       \'urlname\'=>\'GNU_General_Public_License\',
       \'namespace\'=>\'Special\',
       \'special\'=>0,\'visible\'=>1,\'comments_on\'=>0,\'protected\'=>1,\'delvotes\'=>0,\'delvote_ips\'=>\'\',
       ));
     
     $paths->add_page(Array(
-      \'name\'=>\'Tag cloud\',
+      \'name\'=>\'specialpage_tag_cloud\',
       \'urlname\'=>\'TagCloud\',
       \'namespace\'=>\'Special\',
       \'special\'=>0,\'visible\'=>1,\'comments_on\'=>0,\'protected\'=>1,\'delvotes\'=>0,\'delvote_ips\'=>\'\',
@@ -72,6 +72,185 @@
 function page_Special_CreatePage()
 {
   global $db, $session, $paths, $template, $plugins; // Common objects
+  global $lang;
+  
+  $whitelist_ns = array('Article', 'User', 'Help', 'Template', 'Category', 'Project');
+  $code = $plugins->setHook('page_create_ns_whitelist');
+  foreach ( $code as $cmd )
+  {
+    eval($cmd);
+  }
+  
+  $errors = array();
+  
+  switch ( isset($_POST['page_title']) )
+  {
+    case true:
+      // "Create page" was clicked
+      
+      //
+      // VALIDATION CODE
+      //
+      
+      // Check namespace
+      $namespace = ( isset($_POST['namespace']) ) ? $_POST['namespace'] : 'Article';
+      if ( !in_array($namespace, $whitelist_ns) )
+      {
+        $errors[] = $lang->get('pagetools_create_err_invalid_namespace');
+      }
+      
+      // Check title and figure out urlname
+      $title = $_POST['page_title'];
+      $urlname = $_POST['page_title'];
+      if ( @$_POST['custom_url'] === 'yes' && isset($_POST['urlname']) )
+      {
+        $urlname = $_POST['urlname'];
+      }
+      $urlname = sanitize_page_id($urlname);
+      if ( $urlname == '.00' || empty($urlname) )
+      {
+        $errors[] = $lang->get('pagetools_create_err_invalid_urlname');
+      }
+      
+      // Validate page existence
+      $pathskey = $paths->nslist[$namespace] . $urlname;
+      if ( isPage($pathskey) )
+      {
+        $errors[] = $lang->get('pagetools_create_err_already_exists');
+      }
+      
+      // Validate permissions
+      $perms = $session->fetch_page_acl($urlname, $namespace);
+      if ( !$perms->get_permissions('create_page') )
+      {
+        $errors[] = $lang->get('pagetools_create_err_no_permission');
+      }
+      
+      // Run hooks
+      $code = $plugins->setHook('page_create_request');
+      foreach ( $code as $cmd )
+      {
+        eval($cmd);
+      }
+      
+      // Create the page
+      if ( count($errors) < 1 )
+      {
+        $page = new PageProcessor($urlname, $namespace);
+        $page->create_page($title);
+        if ( $error = $page->pop_error() )
+        {
+          do
+          {
+            $errors[] = $error;
+          }
+          while ( $error = $page->pop_error() );
+        }
+        else
+        {
+          redirect(makeUrlNS($namespace, $urlname) . '#do:edit', '', '', 0);
+          return true;
+        }
+      }
+      
+      break;
+  }
+  
+  $template->header();
+  
+  echo $lang->get('pagetools_create_blurb');
+  
+  if ( count($errors) > 0 )
+  {
+    echo '<div class="error-box">' . implode("<br />\n        ", $errors) . '</div>';
+  }
+  
+  ?>
+  <enano:no-opt>
+  <script type="text/javascript">
+    function cpGenPreviewUrl()
+    {
+      var frm = document.forms['create_form'];
+      var radio_custom = frm.getElementsByTagName('input')[2];
+      var use_custom_url = radio_custom.checked;
+      if ( use_custom_url )
+      {
+        var title_src = frm.urlname.value;
+      }
+      else
+      {
+        var title_src = frm.page_title.value;
+      }
+      var url = window.location.protocol + '//' + window.location.hostname + contentPath + namespace_list[frm.namespace.value] + sanitize_page_id(title_src);
+      document.getElementById('createpage_url_preview').firstChild.nodeValue = url;
+    }
+  </script>
+  </enano:no-opt>
+  <?php
+  
+  echo '<form action="' . makeUrlNS('Special', 'CreatePage') . '" method="post" name="create_form">';
+  
+  echo '<p>';
+    echo $lang->get('pagetools_create_field_title');
+    echo ' <input onkeyup="cpGenPreviewUrl();" type="text" name="page_title" size="40" tabindex="1" />';
+    echo '</p>';
+    
+  echo '<p>';
+    echo $lang->get('pagetools_create_field_namespace');
+    echo ' <select onchange="cpGenPreviewUrl();" name="namespace" tabindex="2">';
+    foreach ( $paths->nslist as $ns => $ns_prefix )
+    {
+      if ( !in_array($ns, $whitelist_ns) )
+        continue;
+      $lang_string = 'onpage_lbl_page_' . strtolower($ns);
+      $str = $lang->get($lang_string);
+      if ( $str == $lang_string )
+        $str = $ns;
+      
+      echo '<option value="' . $ns . '">' . ucwords($str) . '</option>';
+    }
+    echo '</select>';
+    echo '</p>';
+    
+  echo '<fieldset>';
+  echo '<legend>' . $lang->get('pagetools_create_group_advanced') . '</legend>';
+  
+  echo '<p>';
+    echo '<label><input tabindex="3" type="radio" name="custom_url" value="no" checked="checked" onclick="cpGenPreviewUrl(); document.getElementById(\'createpage_custom_url\').style.display = \'none\';" /> ' . $lang->get('pagetools_create_field_url_auto') . '</label>';
+    echo '</p>';
+  
+  echo '<p>';
+    echo '<label><input tabindex="3" type="radio" name="custom_url" value="yes" onclick="cpGenPreviewUrl(); document.getElementById(\'createpage_custom_url\').style.display = \'block\';" /> ' . $lang->get('pagetools_create_field_url_manual') . '</label>';
+    echo '</p>';
+  
+  echo '<p id="createpage_custom_url" style="display: none; margin-left: 2em;">';
+    echo $lang->get('pagetools_create_field_url');
+    echo ' <input onkeyup="cpGenPreviewUrl();" tabindex="4" type="text" name="urlname" value="" size="40" />';
+    echo '</p>';
+    
+  echo '<p>';
+    echo $lang->get('pagetools_create_field_preview') . ' <tt id="createpage_url_preview"> </tt><br />';
+    echo '<small>' . $lang->get('pagetools_create_field_preview_hint') . '</small>';
+    echo '</p>';
+  
+  echo '</fieldset>';
+  
+  echo '<p>';
+    echo '<input tabindex="5" type="submit" value="' . $lang->get('pagetools_create_btn_create') . '" />';
+    echo '</p>';
+    
+  echo '</form>';
+  
+  echo '<script type="text/javascript">cpGenPreviewUrl();</script>';
+  
+  $template->footer();
+}
+
+function page_Special_CreatePage_Old()
+{
+  global $db, $session, $paths, $template, $plugins; // Common objects
+  global $lang;
+  
   if ( isset($_POST['do']) )
   {
     $p = $_POST['pagename'];
@@ -88,7 +267,8 @@
     {
       $template->header();
       
-      echo '<h3>The page could not be created.</h3><p>The name "'.$p.'" is invalid.</p>';
+      echo '<h3>' . $lang->get('pagetools_create_err_title') . '</h3>
+             <p>' . $lang->get('pagetools_create_err_name_invalid', array('page_name' => htmlspecialchars($p))) . '</p>';
       
       $template->footer();
       $db->close();
@@ -102,7 +282,8 @@
     {
       $template->header();
       
-      echo '<h3>The page could not be created.</h3><p>The name "'.$paths->nslist[$namespace].$p.'" is invalid.</p>';
+      echo '<h3>' . $lang->get('pagetools_create_err_title') . '</h3>
+             <p>' . $lang->get('pagetools_create_err_name_invalid', array('page_name' => htmlspecialchars($paths->nslist[$namespace].$p))) . '</p>';
       
       $template->footer();
       $db->close();
@@ -118,7 +299,8 @@
     {
       $template->header();
       
-      echo '<h3>The page could not be created.</h3><p>The page title can\'t start with "Project:" because this prefix is reserved for a parser shortcut.</p>';
+      echo '<h3>' . $lang->get('pagetools_create_err_title') . '</h3>
+             <p>' . $lang->get('pagetools_create_err_project_shortcut', array('page_name' => htmlspecialchars($p))) . '</p>';
       
       $template->footer();
       $db->close();
@@ -129,7 +311,7 @@
     $tn = $paths->nslist[$_POST['namespace']] . $urlname;
     if ( isset($paths->pages[$tn]) )
     {
-      die_friendly('Error creating page', '<p>The page already exists.</p>');
+      die_friendly($lang->get('pagetools_create_err_title'), '<p>' . $lang->get('pagetools_create_err_already_exist') . '</p>');
     }
     
     if ( $paths->nslist[$namespace] == substr($urlname, 0, strlen($paths->nslist[$namespace]) ) )
@@ -154,9 +336,9 @@
     
     $perms = $session->fetch_page_acl($urlname, $namespace);
     if ( !$perms->get_permissions('create_page') )
-      die_friendly('Error creating page', '<p>An access control rule is preventing you from creating pages.</p>');
+      die_friendly($lang->get('pagetools_create_err_title'), '<p>An access control rule is preventing you from creating pages.</p>');
     
-    $q = $db->sql_query('INSERT INTO '.table_prefix.'logs(time_id,date_string,log_type,action,author,page_id,namespace) VALUES('.time().', \''.date('d M Y h:i a').'\', \'page\', \'create\', \''.$session->username.'\', \''.$urlname.'\', \''.$_POST['namespace'].'\');');
+    $q = $db->sql_query('INSERT INTO '.table_prefix.'logs(time_id,date_string,log_type,action,author,page_id,namespace) VALUES('.time().', \''.enano_date('d M Y h:i a').'\', \'page\', \'create\', \''.$session->username.'\', \''.$urlname.'\', \''.$_POST['namespace'].'\');');
     if ( !$q )
     {
       $db->_die('The page log could not be updated.');
@@ -188,7 +370,7 @@
     exit;
   }
   */
-  echo RenderMan::render('Using the form below you can create a page.');
+  echo '<p>' . $lang->get('pagetools_create_blurb') . '</p>';
   ?>
   <form action="" method="post">
     <p>
@@ -199,7 +381,7 @@
         {
           if ( $paths->nslist[$k[$i]] == '' )
           {
-            $s = '[No prefix]';
+            $s = $lang->get('pagetools_create_namespace_none');
           }
           else
           {
@@ -212,7 +394,7 @@
         }
         ?>
       </select> <input type="text" name="pagename" /></p>
-      <p><input type="submit" name="do" value="Create Page" /></p>
+      <p><input type="submit" name="do" value="<?php echo $lang->get('pagetools_create_btn_create'); ?>" /></p>
   </form>
   <?php
   $template->footer();
@@ -263,9 +445,11 @@
 {
   // This should be an easy one
   global $db, $session, $paths, $template, $plugins; // Common objects
+  global $lang;
+  
   $template->header();
   $sz = sizeof( $paths->pages ) / 2;
-  echo '<p>Below is a list of all of the pages on this website.</p>';
+  echo '<p>' . $lang->get('pagetools_allpages_blurb') . '</p>';
   
   $q = $db->sql_query('SELECT COUNT(urlname) FROM '.table_prefix.'pages WHERE visible!=0;');
   if ( !$q )
@@ -326,9 +510,11 @@
 {
   // This should be an easy one
   global $db, $session, $paths, $template, $plugins; // Common objects
+  global $lang;
+  
   $template->header();
   $sz = sizeof($paths->pages) / 2;
-  echo '<p>Below is a list of all of the special pages on this website.</p><div class="tblholder"><table border="0" width="100%" cellspacing="1" cellpadding="4">';
+  echo '<p>' . $lang->get('pagetools_specialpages_blurb') . '</p><div class="tblholder"><table border="0" width="100%" cellspacing="1" cellpadding="4">';
   $cclass='row1';
   for ( $i = 0; $i < $sz; $i = $i)
   {
@@ -365,6 +551,8 @@
 function page_Special_About_Enano()
 {
   global $db, $session, $paths, $template, $plugins; // Common objects
+  global $lang;
+  
   $platform = 'Unknown';
   $uname = @file_get_contents('/proc/sys/kernel/ostype');
   if($uname == "Linux\n")
@@ -384,24 +572,53 @@
   <br />
   <div class="tblholder">
     <table border="0" cellspacing="1" cellpadding="4">
-      <tr><th colspan="2" style="text-align: left;">About the Enano Content Management System</th></tr>
-      <tr><td colspan="2" class="row3"><p>This website is powered by <a href="http://enanocms.org/">Enano</a>, the lightweight and open source
-      CMS that everyone can use. Enano is copyright &copy; 2006-2007 Dan Fuhry. For legal information, along with a list of libraries that Enano
-      uses, please see <a href="http://enanocms.org/Legal_information">Legal Information</a>.</p>
-      <p>The developers and maintainers of Enano strongly believe that software should not only be free to use, but free to be modified,
-         distributed, and used to create derivative works. For more information about Free Software, check out the
-         <a href="http://en.wikipedia.org/wiki/Free_Software" onclick="window.open(this.href); return false;">Wikipedia page</a> or
-         the <a href="http://www.fsf.org/" onclick="window.open(this.href); return false;">Free Software Foundation's</a> homepage.</p>
-      <p>This program is Free Software; you can redistribute it and/or modify it under the terms of the GNU General Public License
-      as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.</p>
-      <p>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.</p>
-      <p>You should have received <a href="<?php echo makeUrlNS('Special', 'GNU_General_Public_License'); ?>">a copy of
-         the GNU General Public License</a> along with this program; if not, write to:</p>
-      <p style="margin-left 2em;">Free Software Foundation, Inc.,<br />
-         51 Franklin Street, Fifth Floor<br />
-         Boston, MA 02110-1301, USA</p>
-      <p>Alternatively, you can <a href="http://www.gnu.org/licenses/old-licenses/gpl-2.0.html">read it online</a>.</p>
+      <tr><th colspan="2" style="text-align: left;"><?php echo $lang->get('meta_enano_about_th'); ?></th></tr>
+      <tr><td colspan="2" class="row3">
+        <?php
+        echo $lang->get('meta_enano_about_poweredby');
+        $subst = array(
+            'gpl_link' => makeUrlNS('Special', 'GNU_General_Public_License')
+          );
+        echo $lang->get('meta_enano_about_gpl', $subst);
+        if ( $lang->lang_code != 'eng' ):
+        // Do not remove this block of code. Doing so is a violation of the GPL. (A copy of the GPL in other languages
+        // must be accompanied by a copy of the English GPL.)
+        ?>
+        <h3>(English)</h3>
+        <p>
+          This website is powered by <a href="http://enanocms.org/">Enano</a>, the lightweight and open source CMS that everyone can use.
+          Enano is copyright &copy; 2006-2007 Dan Fuhry. For legal information, along with a list of libraries that Enano uses, please
+          see <a href="http://enanocms.org/Legal_information">Legal Information</a>.
+        </p>
+        <p>
+          The developers and maintainers of Enano strongly believe that software should not only be free to use, but free to be modified,
+          distributed, and used to create derivative works. For more information about Free Software, check out the
+          <a href="http://en.wikipedia.org/wiki/Free_Software" onclick="window.open(this.href); return false;">Wikipedia page</a> or
+          the <a href="http://www.fsf.org/" onclick="window.open(this.href); return false;">Free Software Foundation's</a> homepage.
+        </p>
+        <p>
+          This program is Free Software; you can redistribute it and/or modify it under the terms of the GNU General Public License
+          as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.
+        </p>
+        <p>
+          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.
+        </p>
+        <p>
+          You should have received <a href="<?php echo makeUrlNS('Special', 'GNU_General_Public_License'); ?>">a copy of
+          the GNU General Public License</a> along with this program; if not, write to:
+        </p>
+        <p style="margin-left 2em;">
+          Free Software Foundation, Inc.,<br />
+          51 Franklin Street, Fifth Floor<br />
+          Boston, MA 02110-1301, USA
+        </p>
+        <p>
+          Alternatively, you can <a href="http://www.gnu.org/licenses/old-licenses/gpl-2.0.html">read it online</a>.
+        </p>
+        <?php
+        endif;
+        ?>
       </td></tr>
       <tr>
         <td class="row2" colspan="2">
@@ -440,23 +657,23 @@
           </table>
         </td>
       </tr>
-      <tr><td style="width: 100px;" class="row1"><a href="http://enanocms.org">Enano</a> version:</td><td class="row1"><?php echo enano_version(true) . ' (' . enano_codename() . ')'; ?></td></tr>
-      <tr><td style="width: 100px;" class="row2">Web server:</td><td class="row2"><?php if(isset($_SERVER['SERVER_SOFTWARE'])) echo $_SERVER['SERVER_SOFTWARE']; else echo 'Unable to determine web server software.'; ?></td></tr>
-      <tr><td style="width: 100px;" class="row1">Server platform:</td><td class="row1"><?php echo $platform; ?></td></tr>
-      <tr><td style="width: 100px;" class="row2"><a href="http://www.php.net/">PHP</a> version:</td><td class="row2"><?php echo PHP_VERSION; ?></td></tr>
+      <tr><td style="width: 100px;" class="row1"><?php echo $lang->get('meta_enano_about_lbl_enanoversion'); ?></td><td class="row1"><?php echo enano_version(true) . ' (' . enano_codename() . ')'; ?></td></tr>
+      <tr><td style="width: 100px;" class="row2"><?php echo $lang->get('meta_enano_about_lbl_webserver'); ?></td><td class="row2"><?php if(isset($_SERVER['SERVER_SOFTWARE'])) echo $_SERVER['SERVER_SOFTWARE']; else echo 'Unable to determine web server software.'; ?></td></tr>
+      <tr><td style="width: 100px;" class="row1"><?php echo $lang->get('meta_enano_about_lbl_serverplatform'); ?></td><td class="row1"><?php echo $platform; ?></td></tr>
+      <tr><td style="width: 100px;" class="row2"><?php echo $lang->get('meta_enano_about_lbl_phpversion'); ?></td><td class="row2"><?php echo PHP_VERSION; ?></td></tr>
       <?php
       switch(ENANO_DBLAYER)
       {
         case 'MYSQL':
           ?>
-          <tr><td style="width: 100px;" class="row1"><a href="http://www.mysql.com/">MySQL</a> version:</td><td class="row1"><?php echo mysql_get_server_info($db->_conn); ?></td></tr>
+          <tr><td style="width: 100px;" class="row1"><?php echo $lang->get('meta_enano_about_lbl_mysqlversion'); ?></td><td class="row1"><?php echo mysql_get_server_info($db->_conn); ?></td></tr>
           <?php
           break;
         case 'PGSQL':
           $pg_serverdata = pg_version($db->_conn);
           $pg_version = $pg_serverdata['server'];
           ?>
-          <tr><td style="width: 100px;" class="row1"><a href="http://www.postgresql.org/">PostgreSQL</a> version:</td><td class="row1"><?php echo $pg_version; ?></td></tr>
+          <tr><td style="width: 100px;" class="row1"><?php echo $lang->get('meta_enano_about_lbl_pgsqlversion'); ?></td><td class="row1"><?php echo $pg_version; ?></td></tr>
           <?php
           break;
       }
@@ -470,15 +687,36 @@
 function page_Special_GNU_General_Public_License()
 {
   global $db, $session, $paths, $template, $plugins; // Common objects
+  global $lang;
+  
   $template->header();
-  if(file_exists(ENANO_ROOT.'/GPL'))
+  if(file_exists(ENANO_ROOT . '/GPL'))
   {
+    echo '<p>' . $lang->get('pagetools_gpl_blurb', array('about_url' => makeUrlNS('Special', 'About_Enano'))) . '</p>';
+    
+    if ( $lang->lang_code != 'eng' ):
+    // Do not remove this block of code. Doing so is a violation of the GPL. (A copy of the GPL in other languages
+    // must be accompanied by a copy of the English GPL.)
     echo '<p>The following text represents the license that the <a href="'.makeUrlNS('Special', 'About_Enano').'">Enano</a> content management system is under. To make it easier to read, the text has been wiki-formatted; in no other way has it been changed.</p>';
+    endif;
+    
+    if ( file_exists(ENANO_ROOT . "/GPL_{$lang->lang_code}") )
+    {
+      echo '<h2>' . $lang->get('pagetools_gpl_title_native') . '</h2>';
+      echo '<p><a href="#gpl_english">' . $lang->get('pagetools_gpl_link_to_english') . ' / View the license in English' . '</a></p>';
+      echo RenderMan::render( file_get_contents ( ENANO_ROOT . "/GPL_{$lang->lang_code}" ) );
+      echo '<h2>' . $lang->get('pagetools_gpl_title_english') . ' / English version<a name="gpl_english" id="gpl_english"></a></h2>';
+    }
+    
     echo RenderMan::render( file_get_contents ( ENANO_ROOT . '/GPL' ) );
   }
   else
   {
-    echo '<p>It appears that the file "GPL" is missing from your Enano installation. You may find a wiki-formatted copy of the GPL at: <a href="http://enanocms.org/GPL">http://enanocms.org/GPL</a>.</p>';
+    echo '<p>' . $lang->get('pagetools_gpl_err_file_missing') . '</p>';
+    if ( $lang->lang_code != 'eng')
+      // Also print out English version
+      // Do not remove the following line of code; doing so would be a violation of the GPL.
+      echo '<p>It appears that the file "GPL" is missing from your Enano installation. You may find a wiki-formatted copy of the GPL at: <a href="http://enanocms.org/GPL">http://enanocms.org/GPL</a>. In the mean time, you may wish to contact the site administration and ask them to replace the GPL file.</p>';
   }
   $template->footer();
 }
@@ -486,6 +724,7 @@
 function page_Special_TagCloud()
 {
   global $db, $session, $paths, $template, $plugins; // Common objects
+  global $lang;
   
   $template->header();
   
@@ -499,7 +738,7 @@
     {
       echo '<div class="tblholder">
               <table border="0" cellspacing="1" cellpadding="4">';
-      echo '<tr><th colspan="2">Pages tagged "' . htmlspecialchars($tag) . '"</th></tr>';
+      echo '<tr><th colspan="2">' . $lang->get('pagetools_tagcloud_pagelist_th', array('tag' => htmlspecialchars($tag))) . '</th></tr>';
       echo '<tr>';
       $i = 0;
       $td_class = 'row1';
@@ -528,7 +767,7 @@
       }
       // " workaround for jEdit highlighting bug
       echo '<tr>
-              <th colspan="2" class="subhead"><a href="' . makeUrlNS('Special', 'TagCloud') . '" style="color: white;">&laquo; Return to tag cloud</a></th>
+              <th colspan="2" class="subhead"><a href="' . makeUrlNS('Special', 'TagCloud') . '">&laquo; ' . $lang->get('pagetools_tagcloud_btn_return') . '</a></th>
             </tr>';
       echo '</table>';
       echo '</div>';
@@ -543,17 +782,17 @@
       $db->_die();
     if ( $db->numrows() < 1 )
     {
-      echo '<p>No pages are tagged yet.</p>';
+      echo '<p>' . $lang->get('pagetools_tagcloud_msg_no_tags') . '</p>';
     }
     else
     {
-      echo '<h3>Summary of page tagging</h3>';
+      echo '<h3>' . $lang->get('pagetools_tagcloud_blurb') . '</h3>';
       while ( $row = $db->fetchrow() )
       {
         $cloud->add_word($row['tag_name']);
       }
       echo $cloud->make_html('normal');
-      echo '<p>Hover your mouse over a tag to see how many pages have the tag. Click on a tag to see a list of the pages that have it.</p>';
+      echo '<p>' . $lang->get('pagetools_tagcloud_instructions') . '</p>';
     }
   }
   
@@ -564,6 +803,7 @@
 function sidebar_add_tag_cloud()
 {
   global $db, $session, $paths, $template, $plugins; // Common objects
+  global $lang;
   $cloud = new TagCloud();
     
   $q = $db->sql_query('SELECT tag_name FROM '.table_prefix.'tags;');
@@ -571,7 +811,7 @@
     $db->_die();
   if ( $db->numrows() < 1 )
   {
-    $sb_html = 'No pages are tagged yet.';
+    $sb_html = $lang->get('pagetools_tagcloud_msg_no_tags');
   }
   else
   {
@@ -579,9 +819,9 @@
     {
       $cloud->add_word($row['tag_name']);
     }
-    $sb_html = $cloud->make_html('small', 'justify') . '<br /><a style="text-align: center;" href="' . makeUrlNS('Special', 'TagCloud') . '">Larger version</a>';
+    $sb_html = $cloud->make_html('small', 'justify') . '<br /><a style="text-align: center;" href="' . makeUrlNS('Special', 'TagCloud') . '">' . $lang->get('pagetools_tagcloud_sidebar_btn_larger') . '</a>';
   }
-  $template->sidebar_widget('Tag cloud', "<div style='padding: 5px;'>$sb_html</div>");
+  $template->sidebar_widget($lang->get('pagetools_tagcloud_sidebar_title'), "<div style='padding: 5px;'>$sb_html</div>");
 }
 
 $plugins->attachHook('compile_template', 'sidebar_add_tag_cloud();');
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/plugins/SpecialRecentChanges.php	Fri Feb 22 12:51:53 2008 -0500
@@ -0,0 +1,206 @@
+<?php
+/*
+Plugin Name: plugin_specialrecentchanges_title
+Plugin URI: http://enanocms.org/
+Description: plugin_specialrecentchanges_desc
+Author: Dan Fuhry
+Version: 1.1.1
+Author URI: http://enanocms.org/
+*/
+
+/*
+ * Enano - an open-source CMS capable of wiki functions, Drupal-like sidebar blocks, and everything in between
+ * Version 1.1.2 (Caoineag alpha 2)
+ * Copyright (C) 2006-2007 Dan Fuhry
+ *
+ * This program is Free Software; you can redistribute and/or modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.
+ *
+ * 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.
+ */
+ 
+global $db, $session, $paths, $template, $plugins; // Common objects
+
+$plugins->attachHook('session_started', '
+  global $paths;
+    $paths->add_page(Array(
+      \'name\'=>\'specialpage_recent_changes\',
+      \'urlname\'=>\'RecentChanges\',
+      \'namespace\'=>\'Special\',
+      \'special\'=>0,\'visible\'=>1,\'comments_on\'=>0,\'protected\'=>1,\'delvotes\'=>0,\'delvote_ips\'=>\'\',
+      ));
+    ');
+
+function page_Special_RecentChanges()
+{
+  global $db, $session, $paths, $template, $plugins; // Common objects
+  global $lang;
+  
+  // One super-loaded SQL query to fetch all the info we need:
+  // (theoretical)
+  //   SELECT ( CHAR_LENGTH(l1.page_text) - CHAR_LENGTH(l2.page_text) ) AS size_change, l1.author, l1.page_id, l1.namespace, l1.edit_summary,
+  //       l1.time_id AS currev_time, l2.time_id AS oldrev_time
+  //     FROM logs AS l1
+  //     LEFT JOIN logs AS l2                                                    
+  //       ON ( l1.log_type = l2.log_type AND l1.action = 'edit' AND l1.action = l2.action AND l2.time_id < l1.time_id AND l1.page_id = l2.page_id AND l1.namespace = l2.namespace )
+  //     WHERE l2.time_id IS NOT NULL
+  //     GROUP BY l1.page_id, l1.namespace
+  //     ORDER BY l2.time_id DESC, l1.time_id DESC;
+  // (the actual query is generated based on filter criteria)
+  // How it works:
+  //  * Join the logs table with itself
+  //  * Select the size_change virtual column, which is based on current_rev_length - old_rev_length
+  //  * Use GROUP BY to group rows from the same page together
+  //  * Make sure that the time_id in the second instance (l2) of enano_logs is LESS than the time_id in the first instance (l1)
+  //  * Use ORDER BY to ensure that the latest revision before current is selected
+  
+  $where_extra = '';
+  if ( isset($_GET['filter_author']) && is_array($_GET['filter_author']) )
+  {
+    $f_author = $_GET['filter_author'];
+    foreach ( $f_author as &$author )
+    {
+      $author = $db->escape($author);
+    }
+    $f_author = "\n    AND (\n      l1.author = '" . implode("'\n      OR l1.author = '", $f_author) . "'\n    )";
+    $where_extra .= $f_author;
+  }
+  
+  if ( ENANO_DBLAYER == 'MYSQL' )
+  {
+    $sql = 'SELECT ( CHAR_LENGTH(l1.page_text) - CHAR_LENGTH(l2.page_text) ) AS size_change, l1.author, l1.page_id, l1.namespace, l1.edit_summary,
+    l1.time_id AS currev_time, l2.time_id AS oldrev_time
+  FROM ' . table_prefix . 'logs AS l1
+  LEFT JOIN ' . table_prefix . 'logs AS l2                                                    
+    ON ( l1.log_type = l2.log_type AND l1.action = \'edit\' AND l1.action = l2.action AND l2.time_id < l1.time_id AND l1.page_id = l2.page_id AND l1.namespace = l2.namespace AND l2.is_draft != 1 )
+  WHERE l2.time_id IS NOT NULL' . $where_extra . '
+        AND l1.is_draft != 1
+  GROUP BY oldrev_time
+  ORDER BY l1.time_id DESC, l2.time_id DESC;';
+  }
+  else
+  {
+    $sql = 'SELECT DISTINCT ON (l1.time_id) ( CHAR_LENGTH(l1.page_text) - CHAR_LENGTH(l2.page_text) ) AS size_change, l1.author, l1.page_id, l1.namespace, l1.edit_summary,
+    l1.time_id AS currev_time, l2.time_id AS oldrev_time
+  FROM ' . table_prefix . 'logs AS l1
+  LEFT JOIN ' . table_prefix . 'logs AS l2                                                    
+    ON ( l1.log_type = l2.log_type AND l1.action = \'edit\' AND l1.action = l2.action AND l2.time_id < l1.time_id AND l1.page_id = l2.page_id AND l1.namespace = l2.namespace )
+  WHERE l2.time_id IS NOT NULL' . $where_extra . '
+  GROUP BY l1.time_id, l1.page_id, l1.namespace, l1.author, l1.edit_summary, l2.time_id, l1.page_text, l2.page_text
+  ORDER BY l1.time_id DESC, l2.time_id DESC;';
+  }
+  
+  $template->header();
+  
+  $q = $db->sql_unbuffered_query($sql);
+  if ( !$q )
+    $db->_die();
+  
+  if ( $row = $db->fetchrow($q) )
+  {
+    echo '<p>';
+    do
+    {
+      $css = rch_get_css($row['size_change']);
+      $pagekey = ( isset($paths->nslist[$row['namespace']]) ) ? $paths->nslist[$row['namespace']] . $row['page_id'] : $row['namespace'] . ':' . $row['page_id'];
+      $pagekey = sanitize_page_id($pagekey);
+      
+      // diff button
+      echo '(';
+      if ( isPage($pagekey) )
+      {
+        echo '<a href="' . makeUrlNS($row['namespace'], $row['page_id'], "do=diff&diff1={$row['oldrev_time']}&diff2={$row['currev_time']}", true) . '">';
+      }
+      echo $lang->get('pagetools_rc_btn_diff');
+      if ( isPage($pagekey) )
+      {
+        echo '</a>';
+      }
+      echo ') ';
+      
+      // hist button
+      echo '(';
+      if ( isPage($pagekey) )
+      {
+        echo '<a href="' . makeUrlNS($row['namespace'], $row['page_id'], "do=history", true) . '">';
+      }
+      echo $lang->get('pagetools_rc_btn_hist');
+      if ( isPage($pagekey) )
+      {
+        echo '</a>';
+      }
+      echo ') . . ';
+      
+      // link to the page
+      $cls = ( isPage($pagekey) ) ? '' : ' class="wikilink-nonexistent"';
+      echo '<a href="' . makeUrlNS($row['namespace'], $row['page_id']) . '"' . $cls . '>' . htmlspecialchars(get_page_title_ns($row['page_id'], $row['namespace'])) . '</a>; ';
+      
+      // date
+      $today = time() - ( time() % 86400 );
+      $date = ( $row['currev_time'] > $today ) ? '' : MemberlistFormatter::format_date($row['currev_time']) . ' ';
+      $date .= date('h:i s', $row['currev_time']);
+      echo "$date . . ";
+      
+      // size counter
+      $size_change = number_format($row['size_change']);
+      if ( substr($size_change, 0, 1) != '-' )
+        $size_change = "+$size_change";
+      
+      echo "<span style=\"$css\">({$size_change})</span>";
+      
+      // link to userpage
+      echo ' . . ';
+      $cls = ( isPage($paths->nslist['User'] . $row['author']) ) ? '' : ' class="wikilink-nonexistent"';
+      echo '<a href="' . makeUrlNS('User', sanitize_page_id($row['author']), false, true) . '"' . $cls . '>' . htmlspecialchars($row['author']) . '</a> ';
+      echo '(';
+      echo '<a href="' . makeUrlNS('Special', 'PrivateMessages/Compose/To/' . sanitize_page_id($row['author']), false, true) . '">';
+      echo $lang->get('pagetools_rc_btn_pm');
+      echo '</a>, ';
+      echo '<a href="' . makeUrlNS('User', sanitize_page_id($row['author']), false, true) . '#do:comments">';
+      echo $lang->get('pagetools_rc_btn_usertalk');
+      echo '</a>';
+      echo ') . . ';
+      
+      // Edit summary
+      echo '<i>(';
+      if ( empty($row['edit_summary']) )
+      {
+        echo '<span style="color: #808080;">' . $lang->get('history_summary_none_given') . '</span>';
+      }
+      else
+      {
+        echo RenderMan::parse_internal_links(htmlspecialchars($row['edit_summary']));
+      }
+      echo ')</i>';
+      
+      echo '<br />';
+    }
+    while ( $row = $db->fetchrow($q) );
+    echo '</p>';
+  }
+  
+  $template->footer();
+}
+
+function rch_get_css($change_size)
+{
+  // Hardly changed at all? Return a gray
+  if ( $change_size <= 5 && $change_size >= -5 )
+    return 'color: #808080;';
+  // determine saturation based on size of change (1-500 bytes)
+  $change_abs = abs($change_size);
+  $index = 0x70 * ( $change_abs / 500 );
+  if ( $index > 0x70 )
+    $index = 0x70;
+  $index = $index + 0x40;
+  $index = dechex($index);
+  if ( strlen($index) < 2 )
+    $index = "0$index";
+  $css = ( $change_size > 0 ) ? "color: #00{$index}00;" : "color: #{$index}0000;";
+  if ( $change_abs > 500 )
+    $css .= ' font-weight: bold;';
+  return $css;
+}
+
+?>
--- a/plugins/SpecialSearch.php	Fri Feb 22 12:46:51 2008 -0500
+++ b/plugins/SpecialSearch.php	Fri Feb 22 12:51:53 2008 -0500
@@ -1,16 +1,16 @@
 <?php
 /*
-Plugin Name: Search UI/frontend
+Plugin Name: plugin_specialsearch_title
 Plugin URI: http://enanocms.org/
-Description: Provides the page Special:Search, which is a frontend to the Enano search engine.
+Description: plugin_specialsearch_desc
 Author: Dan Fuhry
-Version: 1.0.3
+Version: 1.1.1
 Author URI: http://enanocms.org/
 */
 
 /*
  * Enano - an open-source CMS capable of wiki functions, Drupal-like sidebar blocks, and everything in between
- * Version 1.0.3
+ * Version 1.1.2 (Caoineag alpha 2)
  * Copyright (C) 2006-2007 Dan Fuhry
  *
  * This program is Free Software; you can redistribute and/or modify it under the terms of the GNU General Public License
@@ -20,17 +20,17 @@
  * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for details.
  */
 
-$plugins->attachHook('base_classes_initted', '
+$plugins->attachHook('session_started', '
   global $paths;
     $paths->add_page(Array(
-      \'name\'=>\'Rebuild search index\',
+      \'name\'=>\'specialpage_search_rebuild\',
       \'urlname\'=>\'SearchRebuild\',
       \'namespace\'=>\'Special\',
       \'special\'=>0,\'visible\'=>1,\'comments_on\'=>0,\'protected\'=>1,\'delvotes\'=>0,\'delvote_ips\'=>\'\',
       ));
     
     $paths->add_page(Array(
-      \'name\'=>\'Search\',
+      \'name\'=>\'specialpage_search\',
       \'urlname\'=>\'Search\',
       \'namespace\'=>\'Special\',
       \'special\'=>0,\'visible\'=>1,\'comments_on\'=>0,\'protected\'=>1,\'delvotes\'=>0,\'delvote_ips\'=>\'\',
@@ -40,7 +40,10 @@
 function page_Special_SearchRebuild()
 {
   global $db, $session, $paths, $template, $plugins; // Common objects
-  if(!$session->get_permissions('mod_misc')) die_friendly('Unauthorized', '<p>You need to be an administrator to rebuild the search index</p>');
+  if ( !$session->get_permissions('mod_misc') )
+  {
+    die_friendly('Unauthorized', '<p>You need to be an administrator to rebuild the search index</p>');
+  }
   $template->header();
   @set_time_limit(0);
   if($paths->rebuild_search_index(true))
@@ -54,6 +57,8 @@
 {
   global $db, $session, $paths, $template, $plugins; // Common objects
   global $aggressive_optimize_html;
+  global $lang;
+  
   $aggressive_optimize_html = false;
   
   if ( !$q = $paths->getParam(0) )
@@ -95,7 +100,7 @@
   
   $qin = ( isset($q) ) ? str_replace('"', '\"', htmlspecialchars($q)) : '';
   $search_form = '<form action="' . makeUrlNS('Special', 'Search') . '">
-  <input type="text" tabindex="1" name="q" size="50" value="' . $qin . '" />&nbsp;<input tabindex="2" type="submit" value="Search" />&nbsp;<a href="' . makeUrlNS('Special', 'Search') . '">Advanced search</a>
+  <input type="text" tabindex="1" name="q" size="50" value="' . $qin . '" />&nbsp;<input tabindex="2" type="submit" value="' . $lang->get('search_btn_search') . '" />&nbsp;<a href="' . makeUrlNS('Special', 'Search') . '">' . $lang->get('search_btn_advanced_search') . '</a>
   ' . ( $session->auth_level > USER_LEVEL_MEMBER ? '<input type="hidden" name="auth" value="' . $session->sid_super . '" />' : '' ) . '
   </form>';
   
@@ -103,7 +108,7 @@
   {
     $search_start = microtime_float();
     
-    $results = perform_search($q, $warn, ( isset($_GET['match_case']) ));
+    $results = perform_search($q, $warn, ( isset($_GET['match_case']) ), $word_list);
     $warn = array_unique($warn);
     
     if ( file_exists( ENANO_ROOT . '/themes/' . $template->theme . '/search-result.tpl' ) )
@@ -122,7 +127,7 @@
           {PAGE_TEXT}
           <span class="search-result-url">{PAGE_URL}</span> - 
           <!-- BEGINNOT special_page --><span class="search-result-info">{PAGE_LENGTH} {PAGE_LENGTH_UNIT}</span> -<!-- END special_page --> 
-          <span class="search-result-info">Relevance: {RELEVANCE_SCORE}%</span>
+          <span class="search-result-info">{lang:search_lbl_relevance} {RELEVANCE_SCORE}%</span>
         </p>
       </div>
       
@@ -138,22 +143,25 @@
       if ( !empty($result['page_text']) )
         $result['page_text'] .= '<br />';
       $result['page_name'] = str_replace(array('<highlight>', '</highlight>'), array('<span class="title-search-term">', '</span>'), $result['page_name']);
+      $result['url_highlight'] = str_replace(array('<highlight>', '</highlight>'), array('<span class="url-search-term">', '</span>'), $result['url_highlight']);
       if ( $result['page_length'] >= 1048576 )
       {
         $result['page_length'] = round($result['page_length'] / 1048576, 1);
-        $length_unit = 'MB';
+        $length_unit = $lang->get('etc_unit_megabytes_short');
       }
       else if ( $result['page_length'] >= 1024 )
       {
         $result['page_length'] = round($result['page_length'] / 1024, 1);
-        $length_unit = 'KB';
+        $length_unit = $lang->get('etc_unit_kilobytes_short');
       }
       else
       {
-        $length_unit = 'bytes';
+        $length_unit = $lang->get('etc_unit_bytes');
       }
-      $url = makeUrlComplete($result['namespace'], $result['page_id']);
-      $url = preg_replace('/\?.+$/', '', $url);
+      //$url = makeUrlComplete($result['namespace'], $result['page_id']);
+      //$url = preg_replace('/\?.+$/', '', $url);
+      $url = $result['url_highlight'];
+      
       $parser->assign_vars(array(
          'PAGE_TITLE' => $result['page_name'],
          'PAGE_TEXT' => $result['page_text'],
@@ -193,13 +201,20 @@
     $q_trim = ( strlen($q) > 30 ) ? substr($q, 0, 27) . '...' : $q;
     $q_trim = htmlspecialchars($q_trim);
     
-    $result_string = ( count($results) > 0 ) ? "Results <b>$start_string</b> - <b>$per_string</b> of about <b>$num_results</b> for <b>" . $q_trim . "</b> in {$search_time}s." : 'No results.';
+    $result_detail = $lang->get('search_msg_result_detail', array(
+        'start_string' => $start_string,
+        'per_string' => $per_string,
+        'q_trim' => $q_trim,
+        'num_results' => $num_results,
+        'search_time' => $search_time
+      ));
+    $result_string = ( count($results) > 0 ) ? $result_detail : $lang->get('search_msg_no_results');
     
     echo '<div class="search-hibar">
             <div style="float: right;">
               ' . $result_string . '
             </div>
-            <b>Site search</b>
+            <b>' . $lang->get('search_lbl_site_search') . '</b>
           </div>
           <div class="search-lobar">
             ' . $search_form . '
@@ -208,8 +223,8 @@
     if ( count($warn) > 0 )
     {
       echo '<div class="warning-box" style="margin: 10px 0 0 0;">';
-      echo '<b>Some problems were encountered during your search.</b><br />
-            There was a problem with your search query, and as a result there may be a reduced number of search results.';
+      echo '<b>' . $lang->get('search_err_query_title') . '</b><br />
+            ' . $lang->get('search_err_query_body');
       echo '<ul><li>' . implode('</li><li>', $warn) . '</li></ul>';
       echo '</div>';
     }
@@ -228,14 +243,12 @@
     else
     {
       // No results for the search
-      echo '<h3 style="font-weight: normal;">Your search for <b>"' . htmlspecialchars($q) . '"</b> didn\'t turn up any results.</h3>';
-      echo '<p>There are a few things you can try:</p>';
-      echo '<ul>
-              <li>Were you looking for a specific Special page? Special pages are not searchable. You may want to see a <a href="' . makeUrlNS('Special', 'SpecialPages') . '">list of special pages</a>.</li>
-              <li>If you have the appropriate permissions, you can <a href="' . makeUrl($q) . '#do:edit">start the ' . htmlspecialchars($q) . ' page</a>.</li>
-              <li>Try using fewer keywords. You can get broader results if you remove quotes from your search query.</li>
-              <li>Did your search trigger any warnings? Sometimes a search can be cancelled if there aren\'t any terms in a search query that are 4 characters or greater in length.</li>
-            </ul>';
+      echo '<h3 style="font-weight: normal;">' . $lang->get('search_body_no_results_title', array('query' => htmlspecialchars($q))) . '</h3>';
+      echo $lang->get('search_body_no_results_body', array(
+          'query' => htmlspecialchars($q),
+          'create_url' => makeUrl($q),
+          'special_url' => makeUrlNS('Special', 'SpecialPages'),
+        ));
     }
     $code = $plugins->setHook('search_results');
     foreach ( $code as $cmd )
@@ -254,26 +267,26 @@
       endif; ?>
       <div class="tblholder">
         <table border="0" style="width: 100%;" cellspacing="1" cellpadding="4">
-          <tr><th colspan="2">Advanced Search</th></tr>
+          <tr><th colspan="2"><?php echo $lang->get('search_th_advanced_search'); ?></th></tr>
           <tr>
-            <td class="row1">Search for pages with <b>any of these words</b>:</td>
+            <td class="row1"><?php echo $lang->get('search_lbl_field_any'); ?></td>
             <td class="row1"><input type="text" name="words_any" size="40" /></td>
           </tr>
           <tr>
-            <td class="row2">with <b>this exact phrase</b>:</td>
+            <td class="row2"><?php echo $lang->get('search_lbl_field_exact'); ?></td>
             <td class="row2"><input type="text" name="exact_phrase" size="40" /></td>
           </tr>
           <tr>
-            <td class="row1">with <b>none of these words</b>:</td>
+            <td class="row1"><?php echo $lang->get('search_lbl_field_none'); ?></td>
             <td class="row1"><input type="text" name="exclude_words" size="40" /></td>
           </tr>
           <tr>
-            <td class="row2">with <b>all of these words</b>:</td>
+            <td class="row2"><?php echo $lang->get('search_lbl_field_all'); ?></td>
             <td class="row2"><input type="text" name="require_words" size="40" /></td>
           </tr>
           <tr>
             <td class="row1">
-              <label for="chk_case">Case-sensitive search:</label>
+              <label for="chk_case"><?php echo $lang->get('search_lbl_field_casesensitive'); ?></label>
             </td>
             <td class="row1">
               <input type="checkbox" name="match_case" id="chk_case" />
@@ -281,7 +294,7 @@
           </tr>
           <tr>
             <th colspan="2" class="subhead">
-              <input type="submit" name="do_search" value="Search" />
+              <input type="submit" name="do_search" value="<?php echo $lang->get('search_btn_search'); ?>" />
             </td>
           </tr>
         </table>
--- a/plugins/SpecialUpdownload.php	Fri Feb 22 12:46:51 2008 -0500
+++ b/plugins/SpecialUpdownload.php	Fri Feb 22 12:51:53 2008 -0500
@@ -1,16 +1,16 @@
 <?php
 /*
-Plugin Name: Upload/download frontend
+Plugin Name: plugin_specialupdownload_title
 Plugin URI: http://enanocms.org/
-Description: Provides the pages Special:UploadFile and Special:DownloadFile. UploadFile is used to upload files to the site, and DownloadFile fetches the file from the database, creates thumbnails if necessary, and sends the file to the user.
+Description: plugin_specialupdownload_desc
 Author: Dan Fuhry
-Version: 1.0.3
+Version: 1.1.1
 Author URI: http://enanocms.org/
 */
 
 /*
  * Enano - an open-source CMS capable of wiki functions, Drupal-like sidebar blocks, and everything in between
- * Version 1.0.3
+ * Version 1.1.2 (Caoineag alpha 2)
  * Copyright (C) 2006-2007 Dan Fuhry
  * SpecialUpdownload.php - handles uploading and downloading of user-uploaded files - possibly the most rigorously security-enforcing script in all of Enano, although sessions.php comes in a close second
  *
@@ -23,17 +23,17 @@
  
 global $db, $session, $paths, $template, $plugins; // Common objects
 
-$plugins->attachHook('base_classes_initted', '
+$plugins->attachHook('session_started', '
   global $paths;
     $paths->add_page(Array(
-      \'name\'=>\'Upload file\',
+      \'name\'=>\'specialpage_upload_file\',
       \'urlname\'=>\'UploadFile\',
       \'namespace\'=>\'Special\',
       \'special\'=>0,\'visible\'=>1,\'comments_on\'=>0,\'protected\'=>1,\'delvotes\'=>0,\'delvote_ips\'=>\'\',
       ));
     
     $paths->add_page(Array(
-      \'name\'=>\'Download file\',
+      \'name\'=>\'specialpage_download_file\',
       \'urlname\'=>\'DownloadFile\',
       \'namespace\'=>\'Special\',
       \'special\'=>0,\'visible\'=>1,\'comments_on\'=>0,\'protected\'=>1,\'delvotes\'=>0,\'delvote_ips\'=>\'\',
@@ -43,11 +43,12 @@
 function page_Special_UploadFile()
 {
   global $db, $session, $paths, $template, $plugins; // Common objects
+  global $lang;
   global $mime_types;
-  if(getConfig('enable_uploads')!='1') { die_friendly('Access denied', '<p>File uploads are disabled this website.</p>'); }
+  if(getConfig('enable_uploads')!='1') { die_friendly($lang->get('etc_access_denied_short'), '<p>' . $lang->get('upload_err_disabled_site') . '</p>'); }
   if ( !$session->get_permissions('upload_files') )
   {
-    die_friendly('Access denied', '<p>File uploads are disabled for your user account or group.<p>');
+    die_friendly($lang->get('etc_access_denied_short'), '<p>' . $lang->get('upload_err_disabled_acl') . '</p>');
   }
   if(isset($_POST['doit']))
   {
@@ -61,42 +62,18 @@
     }
     if ( !is_array($file) )
     {
-      die_friendly('Upload failed', '<p>The server could not retrieve the array $_FILES[\'data\'].</p>');
+      die_friendly($lang->get('upload_err_title'), '<p>' . $lang->get('upload_err_cant_get_file_meta') . '</p>');
     }
     if ( $file['size'] == 0 || $file['size'] > (int)getConfig('max_file_size') )
     {
-      die_friendly('Upload failed', '<p>The file you uploaded is either too large or 0 bytes in length.</p>');
+      die_friendly($lang->get('upload_err_title'), '<p>' . $lang->get('upload_err_too_big_or_small') . '</p>');
     }
-    /*
-    $allowed_mime_types = Array(
-        'text/plain',
-        'image/png',
-        'image/jpeg',
-        'image/tiff',
-        'image/gif',
-        'text/html', // Safe because the file is stashed in the database
-        'application/x-bzip2',
-        'application/x-gzip',
-        'text/x-c++'
-      );
-    if(function_exists('finfo_open') && $fi = finfo_open(FILEINFO_MIME, ENANO_ROOT.'/includes/magic')) // First try to use the fileinfo extension, this is the best way to determine the mimetype
-    {
-      if(!$fi) die_friendly('Upload failed', '<p>Enano was unable to determine the format of the uploaded file.</p><p>'.@finfo_file($fi, $file['tmp_name']).'</p>');
-      $type = @finfo_file($fi, $file['tmp_name']);
-      @finfo_close($fi);
-    }
-    elseif(function_exists('mime_content_type'))
-      $type = mime_content_type($file['tmp_name']); // OK, no fileinfo function. Use a (usually) built-in PHP function
-    elseif(isset($file['type']))
-      $type = $file['type']; // LAST RESORT: use the mimetype the browser sent us, though this is likely to be spoofed
-    else // DANG! Not even the browser told us. Bail out.
-      die_friendly('Upload failed', '<p>Enano was unable to determine the format of the uploaded file.</p>');
-    */
+    
     $types = fetch_allowed_extensions();
     $ext = strtolower(substr($file['name'], strrpos($file['name'], '.')+1, strlen($file['name'])));
     if ( !isset($types[$ext]) || ( isset($types[$ext]) && !$types[$ext] ) )
     {
-      die_friendly('Upload failed', '<p>The file type ".'.$ext.'" is not allowed.</p>');
+      die_friendly($lang->get('upload_err_title'), '<p>' . $lang->get('upload_err_banned_ext', array('ext' => htmlspecialchars($ext))) . '</p>');
     }
     $type = $mime_types[$ext];
     //$type = explode(';', $type); $type = $type[0];
@@ -112,12 +89,16 @@
     $bad_chars = Array(':', '\\', '/', '<', '>', '|', '*', '?', '"', '#', '+');
     foreach($bad_chars as $ch)
     {
-      if(strstr($filename, $ch) || preg_match('/^([ ]+)$/is', $filename)) die_friendly('Upload failed', '<p>The filename contains invalid characters.</p>');
+      if(strstr($filename, $ch) || preg_match('/^([ ]+)$/is', $filename))
+      {
+        die_friendly($lang->get('upload_err_title'), '<p>' . $lang->get('upload_err_banned_chars') . '</p>');
+      }
     }
     
     if ( isset ( $paths->pages[ $paths->nslist['File'] . $filename ] ) && !isset ( $_POST['update'] ) )
     {
-      die_friendly('Upload failed', '<p>The file already exists. You can <a href="'.makeUrlNS('Special', 'UploadFile/'.$filename).'">upload a new version of this file</a>.</p>');
+      $upload_link = makeUrlNS('Special', 'UploadFile/'.$filename);
+      die_friendly($lang->get('upload_err_title'), '<p>' . $lang->get('upload_err_already_exists', array('upload_link' => $upload_link)) . '</p>');
     }
     else if ( isset($_POST['update']) && 
             ( !isset($paths->pages[$paths->nslist['File'].$filename]) ||
@@ -126,7 +107,7 @@
              )
            )
     {
-      die_friendly('Upload failed', '<p>Either the file does not exist (and therefore cannot be updated) or the file is protected.</p>');
+      die_friendly($lang->get('upload_err_title'), '<p>' . $lang->get('upload_err_replace_protected') . '</p>');
     }
     
     $utime = time();
@@ -144,7 +125,7 @@
     
     if(!@move_uploaded_file($file['tmp_name'], $targetname))
     {
-      die_friendly('Upload failed', '<p>Could not move uploaded file to the new location.</p>');
+      die_friendly($lang->get('upload_err_title'), '<p>' . $lang->get('upload_err_move_failed') . '</p>');
     }
     
     if(getConfig('file_history') != '1')
@@ -154,15 +135,15 @@
     if(!$db->sql_query('INSERT INTO '.table_prefix.'files(time_id,page_id,filename,size,mimetype,file_extension,file_key) VALUES('.$utime.', \''.$urln.'\', \''.$filename.'\', '.$flen.', \''.$type.'\', \''.$ext.'\', \''.$key.'\')')) $db->_die('The file data entry could not be inserted.');
     if(!isset($_POST['update']))
     {
-      if(!$db->sql_query('INSERT INTO '.table_prefix.'logs(time_id,date_string,log_type,action,author,page_id,namespace) VALUES('.$utime.', \''.date('d M Y h:i a').'\', \'page\', \'create\', \''.$session->username.'\', \''.$filename.'\', \''.'File'.'\');')) $db->_die('The page log could not be updated.');
+      if(!$db->sql_query('INSERT INTO '.table_prefix.'logs(time_id,date_string,log_type,action,author,page_id,namespace) VALUES('.$utime.', \''.enano_date('d M Y h:i a').'\', \'page\', \'create\', \''.$session->username.'\', \''.$filename.'\', \''.'File'.'\');')) $db->_die('The page log could not be updated.');
       if(!$db->sql_query('INSERT INTO '.table_prefix.'pages(name,urlname,namespace,protected,delvotes,delvote_ips) VALUES(\''.$filename.'\', \''.$urln.'\', \'File\', 0, 0, \'\')')) $db->_die('The page listing entry could not be inserted.');
       if(!$db->sql_query('INSERT INTO '.table_prefix.'page_text(page_id,namespace,page_text,char_tag) VALUES(\''.$urln.'\', \'File\', \''.$comments.'\', \''.$chartag.'\')')) $db->_die('The page text entry could not be inserted.');
     }
     else
     {
-      if(!$db->sql_query('INSERT INTO '.table_prefix.'logs(time_id,date_string,log_type,action,author,page_id,namespace,edit_summary) VALUES('.$utime.', \''.date('d M Y h:i a').'\', \'page\', \'reupload\', \''.$session->username.'\', \''.$filename.'\', \''.'File'.'\', \''.$comments.'\');')) $db->_die('The page log could not be updated.');
+      if(!$db->sql_query('INSERT INTO '.table_prefix.'logs(time_id,date_string,log_type,action,author,page_id,namespace,edit_summary) VALUES('.$utime.', \''.enano_date('d M Y h:i a').'\', \'page\', \'reupload\', \''.$session->username.'\', \''.$filename.'\', \''.'File'.'\', \''.$comments.'\');')) $db->_die('The page log could not be updated.');
     }
-    die_friendly('Upload complete', '<p>Your file has been uploaded successfully. View the <a href="'.makeUrlNS('File', $filename).'">file\'s page</a>.</p>');
+    die_friendly($lang->get('upload_success_title'), '<p>' . $lang->get('upload_success_body', array('file_link' => makeUrlNS('File', $filename))) . '</p>');
   }
   else
   {
@@ -170,51 +151,56 @@
     $fn = $paths->getParam(0);
     if ( $fn && !$session->get_permissions('upload_new_version') )
     {
-      die_friendly('Access denied', '<p>Uploading new versions of files has been disabled for your user account or group.<p>');
+      die_friendly($lang->get('etc_access_denied_short'), '<p>' . $lang->get('upload_err_replace_denied') . '<p>');
     }
     ?>
-    <p>Using this form you can upload a file to the <?php echo getConfig('site_name'); ?> site.</p>
-    <p>The maximum file size is <?php 
+    <p><?php echo $lang->get('upload_intro'); ?></p>
+    <p><?php 
       // Get the max file size, and format it in a way that is user-friendly
+      
       $fs = getConfig('max_file_size');
-      echo commatize($fs).' bytes';
       $fs = (int)$fs;
       if($fs >= 1048576)
       {
         $fs = round($fs / 1048576, 1);
-        echo ' ('.$fs.' MB)';
+        $unitized = $fs . ' ' . $lang->get('etc_unit_megabytes_short');
       }
       elseif($fs >= 1024)
       {
         $fs = round($fs / 1024, 1);
-        echo ' ('.$fs.' KB)';
+        $unitized = $fs . ' ' . $lang->get('etc_unit_kilobytes_short');
       }
-    ?>.</p>
+      
+      echo $lang->get('upload_max_filesize', array(
+          'size' => $unitized
+        ));
+    ?></p>
     <form action="<?php echo makeUrl($paths->page); ?>" method="post" enctype="multipart/form-data">
       <table border="0" cellspacing="1" cellpadding="4">
-        <tr><td>File:</td><td><input name="data" type="file" size="40" /></td></tr>
-        <tr><td>Rename to:</td><td><input name="rename" type="text" size="40"<?php if($fn) echo ' value="'.$fn.'" readonly="readonly"'; ?> /></td></tr>
+        <tr><td><?php echo $lang->get('upload_field_file'); ?></td><td><input name="data" type="file" size="40" /></td></tr>
+        <tr><td><?php echo $lang->get('upload_field_renameto'); ?></td><td><input name="rename" type="text" size="40"<?php if($fn) echo ' value="'.$fn.'" readonly="readonly"'; ?> /></td></tr>
         <?php
-        if(!$fn) echo '<tr><td>Comments:<br />(can be wiki-formatted)</td><td><textarea name="comments" rows="20" cols="60"></textarea></td></tr>';
-        else echo '<tr><td>Reason for uploading the new version: </td><td><input name="comments" size="50" /></td></tr>';
+        if(!$fn) echo '<tr><td>' . $lang->get('upload_field_comments') . '</td><td><textarea name="comments" rows="20" cols="60"></textarea></td></tr>';
+        else echo '<tr><td>' . $lang->get('upload_field_reason') . '</td><td><input name="comments" size="50" /></td></tr>';
         ?>
         <tr><td colspan="2" style="text-align: center">
           <?php
           if($fn)
             echo '<input type="hidden" name="update" value="true" />';
           ?>
-          <input type="submit" name="doit" value="Upload file" />
+          <input type="submit" name="doit" value="<?php echo $lang->get('upload_btn_upload'); ?>" />
         </td></tr>
       </table>
     </form>
     <?php
     $template->footer();
   }
-}                                                                                                                                                          
+}                                                     
 
 function page_Special_DownloadFile()
 {
   global $db, $session, $paths, $template, $plugins; // Common objects
+  global $lang;
   global $do_gzip;
   $filename = rawurldecode($paths->getParam(0));
   $timeid = $paths->getParam(1);
@@ -235,7 +221,7 @@
   if ( $db->numrows() < 1 )
   {
     header('HTTP/1.1 404 Not Found');
-    die_friendly('File not found', '<p>The file "'.$filename.'" cannot be found.</p>');
+    die_friendly($lang->get('upload_err_not_found_title'), '<p>' . $lang->get('upload_err_not_found_body', array('filename' => htmlspecialchars($filename))) . '</p>');
   }
   $row = $db->fetchrow();
   $db->free_result();
@@ -244,7 +230,7 @@
   $perms = $session->fetch_page_acl($row['page_id'], 'File');
   if ( !$perms->get_permissions('read') )
   {
-    die_friendly('Access denied', '<p>Access to the specified file is denied.</p>');
+    die_friendly($lang->get('etc_access_denied_short'), '<p>' . $lang->get('etc_access_denied') . '</p>');
   }
   
   $fname = ENANO_ROOT . '/files/' . $row['file_key'] . '_' . $row['time_id'] . $row['file_extension'];
@@ -307,7 +293,7 @@
     header('Content-disposition: attachment, filename="' . $filename . '";');
   }
   header('Content-length: '.$len);
-  header('Last-Modified: '.date('r', $row['time_id']));
+  header('Last-Modified: '.enano_date('r', $row['time_id']));
   
   // using this method limits RAM consumption
   while ( !feof($handle) )
--- a/plugins/SpecialUserFuncs.php	Fri Feb 22 12:46:51 2008 -0500
+++ b/plugins/SpecialUserFuncs.php	Fri Feb 22 12:51:53 2008 -0500
@@ -1,16 +1,16 @@
 <?php
 /*
-Plugin Name: Special user/login-related pages
+Plugin Name: plugin_specialuserfuncs_title
 Plugin URI: http://enanocms.org/
-Description: Provides the pages Special:Login, Special:Logout, Special:Register, and Special:Preferences.
+Description: plugin_specialuserfuncs_desc
 Author: Dan Fuhry
-Version: 1.0.3
+Version: 1.1.1
 Author URI: http://enanocms.org/
 */
 
 /*
  * Enano - an open-source CMS capable of wiki functions, Drupal-like sidebar blocks, and everything in between
- * Version 1.0.3
+ * Version 1.1.2 (Caoineag alpha 2)
  * Copyright (C) 2006-2007 Dan Fuhry
  *
  * This program is Free Software; you can redistribute and/or modify it under the terms of the GNU General Public License
@@ -22,74 +22,82 @@
  
 global $db, $session, $paths, $template, $plugins; // Common objects
 
-$plugins->attachHook('base_classes_initted', '
+$plugins->attachHook('session_started', '
   global $paths;
     $paths->add_page(Array(
-      \'name\'=>\'Log in\',
+      \'name\'=>\'specialpage_log_in\',
       \'urlname\'=>\'Login\',
       \'namespace\'=>\'Special\',
       \'special\'=>0,\'visible\'=>1,\'comments_on\'=>0,\'protected\'=>1,\'delvotes\'=>0,\'delvote_ips\'=>\'\',
       ));
     $paths->add_page(Array(
-      \'name\'=>\'Log out\',
+      \'name\'=>\'specialpage_log_out\',
       \'urlname\'=>\'Logout\',
       \'namespace\'=>\'Special\',
       \'special\'=>0,\'visible\'=>1,\'comments_on\'=>0,\'protected\'=>1,\'delvotes\'=>0,\'delvote_ips\'=>\'\',
       ));
     $paths->add_page(Array(
-      \'name\'=>\'Register\',
+      \'name\'=>\'specialpage_register\',
       \'urlname\'=>\'Register\',
       \'namespace\'=>\'Special\',
       \'special\'=>0,\'visible\'=>1,\'comments_on\'=>0,\'protected\'=>1,\'delvotes\'=>0,\'delvote_ips\'=>\'\',
       ));
     $paths->add_page(Array(
-      \'name\'=>\'Edit Profile\',
+      \'name\'=>\'specialpage_preferences\',
       \'urlname\'=>\'Preferences\',
       \'namespace\'=>\'Special\',
       \'special\'=>0,\'visible\'=>1,\'comments_on\'=>0,\'protected\'=>1,\'delvotes\'=>0,\'delvote_ips\'=>\'\',
       ));
     
     $paths->add_page(Array(
-      \'name\'=>\'Contributions\',
+      \'name\'=>\'specialpage_contributions\',
       \'urlname\'=>\'Contributions\',
       \'namespace\'=>\'Special\',
       \'special\'=>0,\'visible\'=>1,\'comments_on\'=>0,\'protected\'=>1,\'delvotes\'=>0,\'delvote_ips\'=>\'\',
       ));
     
     $paths->add_page(Array(
-      \'name\'=>\'Change style\',
+      \'name\'=>\'specialpage_change_theme\',
       \'urlname\'=>\'ChangeStyle\',
       \'namespace\'=>\'Special\',
       \'special\'=>0,\'visible\'=>1,\'comments_on\'=>0,\'protected\'=>1,\'delvotes\'=>0,\'delvote_ips\'=>\'\',
       ));
     
     $paths->add_page(Array(
-      \'name\'=>\'Activate user account\',
+      \'name\'=>\'specialpage_activate_account\',
       \'urlname\'=>\'ActivateAccount\',
       \'namespace\'=>\'Special\',
       \'special\'=>0,\'visible\'=>1,\'comments_on\'=>0,\'protected\'=>1,\'delvotes\'=>0,\'delvote_ips\'=>\'\',
       ));
     
     $paths->add_page(Array(
-      \'name\'=>\'Captcha\',
+      \'name\'=>\'specialpage_captcha\',
       \'urlname\'=>\'Captcha\',
       \'namespace\'=>\'Special\',
       \'special\'=>0,\'visible\'=>1,\'comments_on\'=>0,\'protected\'=>1,\'delvotes\'=>0,\'delvote_ips\'=>\'\',
       ));
     
     $paths->add_page(Array(
-      \'name\'=>\'Forgot password\',
+      \'name\'=>\'specialpage_password_reset\',
       \'urlname\'=>\'PasswordReset\',
       \'namespace\'=>\'Special\',
       \'special\'=>0,\'visible\'=>1,\'comments_on\'=>0,\'protected\'=>1,\'delvotes\'=>0,\'delvote_ips\'=>\'\',
       ));
     
     $paths->add_page(Array(
-      \'name\'=>\'Member list\',
+      \'name\'=>\'specialpage_member_list\',
       \'urlname\'=>\'Memberlist\',
       \'namespace\'=>\'Special\',
       \'special\'=>0,\'visible\'=>1,\'comments_on\'=>0,\'protected\'=>1,\'delvotes\'=>0,\'delvote_ips\'=>\'\',
       ));
+      
+    $paths->add_page(Array(
+      \'name\'=>\'specialpage_language_export\',
+      \'urlname\'=>\'LangExportJSON\',
+      \'namespace\'=>\'Special\',
+      \'special\'=>0,\'visible\'=>0,\'comments_on\'=>0,\'protected\'=>1,\'delvotes\'=>0,\'delvote_ips\'=>\'\',
+      ));
+      
     ');
 
 // function names are IMPORTANT!!! The name pattern is: page_<namespace ID>_<page URLname, without namespace>
@@ -100,21 +108,84 @@
 {
   global $db, $session, $paths, $template, $plugins; // Common objects
   global $__login_status;
+  global $lang;
   
   $pubkey = $session->rijndael_genkey();
   $challenge = $session->dss_rand();
   
+  $locked_out = false;
+  // are we locked out?
+  $threshold = ( $_ = getConfig('lockout_threshold') ) ? intval($_) : 5;
+  $duration  = ( $_ = getConfig('lockout_duration') ) ? intval($_) : 15;
+  // convert to minutes
+  $duration  = $duration * 60;
+  $policy = ( $x = getConfig('lockout_policy') && in_array(getConfig('lockout_policy'), array('lockout', 'disable', 'captcha')) ) ? getConfig('lockout_policy') : 'lockout';
+  if ( $policy != 'disable' )
+  {
+    $ipaddr = $db->escape($_SERVER['REMOTE_ADDR']);
+    $timestamp_cutoff = time() - $duration;
+    $q = $session->sql('SELECT timestamp FROM '.table_prefix.'lockout WHERE timestamp > ' . $timestamp_cutoff . ' AND ipaddr = \'' . $ipaddr . '\' ORDER BY timestamp DESC;');
+    $fails = $db->numrows();
+    if ( $fails >= $threshold )
+    {
+      $row = $db->fetchrow();
+      $locked_out = true;
+      $lockdata = array(
+          'locked_out' => true,
+          'lockout_threshold' => $threshold,
+          'lockout_duration' => ( $duration / 60 ),
+          'lockout_fails' => $fails,
+          'lockout_policy' => $policy,
+          'lockout_last_time' => $row['timestamp'],
+          'time_rem' => ( $duration / 60 ) - round( ( time() - $row['timestamp'] ) / 60 ),
+          'captcha' => ''
+        );
+      if ( $policy == 'captcha' )
+      {
+        $lockdata['captcha'] = $session->make_captcha();
+      }
+    }
+    $db->free_result();
+  }
+  
   if ( isset($_GET['act']) && $_GET['act'] == 'getkey' )
   {
-    header('Content-type: application/json');
+    header('Content-type: text/javascript');
     $username = ( $session->user_logged_in ) ? $session->username : false;
     $response = Array(
       'username' => $username,
       'key' => $pubkey,
-      'challenge' => $challenge
+      'challenge' => $challenge,
+      'locked_out' => false
       );
-    $json = new Services_JSON(SERVICES_JSON_LOOSE_TYPE);
-    $response = $json->encode($response);
+    
+    if ( $locked_out )
+    {
+      foreach ( $lockdata as $x => $y )
+      {
+        $response[$x] = $y;
+      }
+      unset($x, $y);
+    }
+    
+    // 1.1.3: generate diffie hellman key
+    global $dh_supported, $_math;
+    
+    $response['dh_supported'] = $dh_supported;
+    if ( $dh_supported )
+    {
+      $dh_key_priv = dh_gen_private();
+      $dh_key_pub = dh_gen_public($dh_key_priv);
+      $dh_key_priv = $_math->str($dh_key_priv);
+      $dh_key_pub = $_math->str($dh_key_pub);
+      $response['dh_public_key'] = $dh_key_pub;
+      // store the keys in the DB
+      $q = $db->sql_query('INSERT INTO ' . table_prefix . "diffiehellman( public_key, private_key ) VALUES ( '$dh_key_pub', '$dh_key_priv' );");
+      if ( !$q )
+        $db->die_json();
+    }
+    
+    $response = enano_json_encode($response);
     echo $response;
     return null;
   }
@@ -136,10 +207,53 @@
     $paths->main_page();
   $template->header();
   echo '<form action="'.makeUrl($paths->nslist['Special'].'Login').'" method="post" name="loginform" onsubmit="runEncryption();">';
-  $header = ( $level > USER_LEVEL_MEMBER ) ? 'Please re-enter your login details' : 'Please enter your username and password to log in.';
+  $header = ( $level > USER_LEVEL_MEMBER ) ? $lang->get('user_login_message_short_elev') : $lang->get('user_login_message_short');
   if ( isset($_POST['login']) )
   {
-    echo '<p>'.$__login_status.'</p>';
+    $errstring = $__login_status['error'];
+    switch($__login_status['error'])
+    {
+      case 'key_not_found':
+        $errstring = $lang->get('user_err_key_not_found');
+        break;
+      case 'key_wrong_length':
+        $errstring = $lang->get('user_err_key_wrong_length');
+        break;
+      case 'too_big_for_britches':
+        $errstring = $lang->get('user_err_too_big_for_britches');
+        break;
+      case 'invalid_credentials':
+        $errstring = $lang->get('user_err_invalid_credentials');
+        if ( $__login_status['lockout_policy'] == 'lockout' )
+        {
+          $errstring .= $lang->get('err_invalid_credentials_lockout', array('lockout_fails' => $__login_status['lockout_fails']));
+        }
+        else if ( $__login_status['lockout_policy'] == 'captcha' )
+        {
+          $errstring .= $lang->get('user_err_invalid_credentials_lockout_captcha', array('lockout_fails' => $__login_status['lockout_fails']));
+        }
+        break;
+      case 'backend_fail':
+        $errstring = $lang->get('user_err_backend_fail');
+        break;
+      case 'locked_out':
+        $attempts = intval($__login_status['lockout_fails']);
+        if ( $attempts > $__login_status['lockout_threshold'])
+          $attempts = $__login_status['lockout_threshold'];
+        
+        $server_time = time();
+        $time_rem = ( $__login_status['lockout_last_time'] == time() ) ? $__login_status['lockout_duration'] : $__login_status['lockout_duration'] - round( ( $server_time - $__login_status['lockout_last_time'] ) / 60 );
+        if ( $time_rem < 1 )
+          $time_rem = $__login_status['lockout_duration'];
+        
+        $s = ( $time_rem == 1 ) ? '' : $lang->get('meta_plural');
+        
+        $captcha_string = ( $__login_status['lockout_policy'] == 'captcha' ) ? $lang->get('err_locked_out_captcha_blurb') : '';
+        $errstring = $lang->get('user_err_locked_out', array('plural' => $s, 'captcha_blurb' => $captcha_string, 'time_rem' => $time_rem));
+        
+        break;
+    }
+    echo '<div class="error-box-mini">'.$errstring.'</div>';
   }
   if ( $p = $paths->getAllParams() )
   {
@@ -160,18 +274,18 @@
             <?php
             if ( $level <= USER_LEVEL_MEMBER )
             {
-              echo '<p>Logging in enables you to use your preferences and access member information. If you don\'t have a username and password here, you can <a href="'.makeUrl($paths->nslist['Special'].'Register').'">create an account</a>.</p>';
+              echo '<p>' . $lang->get('user_login_body', array('reg_link' => makeUrlNS('Special', 'Register'))) . '</p>';
             }
             else
             {
-              echo '<p>You are requesting that a sensitive operation be performed. To continue, please re-enter your password to confirm your identity.</p>';
+              echo '<p>' . $lang->get('user_login_body_elev') . '</p>';
             }
             ?>
           </td>
         </tr>
         <tr>
           <td class="row2">
-            Username:
+            <?php echo $lang->get('user_login_field_username'); ?>:
           </td>
           <td class="row1">
             <input name="username" size="25" type="text" <?php
@@ -190,29 +304,52 @@
               ?> />
           </td>
           <?php if ( $level <= USER_LEVEL_MEMBER ) { ?>
-          <td rowspan="2" class="row3">
-            <small>Forgot your password? <a href="<?php echo makeUrlNS('Special', 'PasswordReset'); ?>">No problem.</a><br />
-            Maybe you need to <a href="<?php echo makeUrlNS('Special', 'Register'); ?>">create an account</a>.</small>
+          <td rowspan="<?php echo ( ( $locked_out && $lockdata['lockout_policy'] == 'captcha' ) ) ? '4' : '2'; ?>" class="row3">
+            <small><?php echo $lang->get('user_login_forgotpass_blurb', array('forgotpass_link' => makeUrlNS('Special', 'PasswordReset'))); ?><br />
+            <?php echo $lang->get('user_login_createaccount_blurb', array('reg_link' => makeUrlNS('Special', 'Register'))); ?></small>
           </td>
           <?php } ?>
         </tr>
         <tr>
-          <td class="row2">Password:<br /></td><td class="row1"><input name="pass" size="25" type="password" tabindex="<?php echo ( $level <= USER_LEVEL_MEMBER ) ? '2' : '1'; ?>" /></td>
+          <td class="row2">
+            <?php echo $lang->get('user_login_field_password'); ?>:
+          </td><td class="row1"><input name="pass" size="25" type="password" tabindex="<?php echo ( $level <= USER_LEVEL_MEMBER ) ? '2' : '1'; ?>" /></td>
          </tr>
-         <?php if ( $level <= USER_LEVEL_MEMBER && ( !isset($_GET['use_crypt']) || ( isset($_GET['use_crypt']) && $_GET['use_crypt'] != '0' ) ) ) { ?>
+         <?php
+         if ( $locked_out && $lockdata['lockout_policy'] == 'captcha' )
+         {
+           ?>
+           <tr>
+             <td class="row2" rowspan="2"><?php echo $lang->get('user_login_field_captcha'); ?>:<br /></td><td class="row1"><input type="hidden" name="captcha_hash" value="<?php echo $lockdata['captcha']; ?>" /><input name="captcha_code" size="25" type="text" tabindex="<?php echo ( $level <= USER_LEVEL_MEMBER ) ? '3' : '4'; ?>" /></td>
+           </tr>
+           <tr>
+             <td class="row3">
+               <img src="<?php echo makeUrlNS('Special', 'Captcha/' . $lockdata['captcha']) ?>" onclick="this.src=this.src+'/a';" style="cursor: pointer;" />
+             </td>
+           </tr>
+           <?php
+         }
+         ?>
          <tr>
            <td class="row3" colspan="3">
-             <p><b>Important note regarding cryptography:</b> Some countries do not allow the import or use of cryptographic technology. If you live in one of the countries listed below, you should <a href="<?php if($p=$paths->getParam(0))$u='/'.$p;else $u='';echo makeUrl($paths->page.$u, 'level='.$level.'&use_crypt=0', true); ?>">log in without using encryption</a>.</p>
-             <p>This restriction applies to the following countries: Belarus, China, India, Israel, Kazakhstan, Mongolia, Pakistan, Russia, Saudi Arabia, Singapore, Tunisia, Venezuela, and Vietnam.</p>
+             <?php
+             if ( $level <= USER_LEVEL_MEMBER && ( !isset($_GET['use_crypt']) || ( isset($_GET['use_crypt']) && $_GET['use_crypt']!='0' ) ) )
+             {
+               $returnpage_link = ( $return = $paths->getAllParams() ) ? '/' . $return : '';
+               $nocrypt_link = makeUrlNS('Special', "Login$returnpage_link", "level=$level&use_crypt=0", true);
+               echo '<p><b>' . $lang->get('user_login_nocrypt_title') . '</b> ' . $lang->get('user_login_nocrypt_body', array('nocrypt_link' => $nocrypt_link)) . '</p>';
+               echo '<p>' . $lang->get('user_login_nocrypt_countrylist') . '</p>';
+             }
+             else if ( $level <= USER_LEVEL_MEMBER && ( isset($_GET['use_crypt']) && $_GET['use_crypt']=='0' ) )
+             {
+               $returnpage_link = ( $return = $paths->getAllParams() ) ? '/' . $return : '';
+               $usecrypt_link = makeUrlNS('Special', "Login$returnpage_link", "level=$level&use_crypt=1", true);
+               echo '<p><b>' . $lang->get('user_login_usecrypt_title') . '</b> ' . $lang->get('user_login_usecrypt_body', array('usecrypt_link' => $usecrypt_link)) . '</p>';
+               echo '<p>' . $lang->get('user_login_usecrypt_countrylist') . '</p>';
+             }
+             ?>
            </td>
          </tr>
-         <?php } else if ( isset($_GET['use_crypt']) && $_GET['use_crypt'] == '0' && $level <= USER_LEVEL_MEMBER ) { ?>
-         <tr>
-           <td class="row3" colspan="3">
-             <p><b>Encrypted logon has been disabled.</b> Unless you live in a country where encryption technology is illegal, you should <a href="<?php if($p=$paths->getParam(0))$u='/'.$p;else $u='';echo makeUrl($paths->page.$u, 'level='.$level.'&use_crypt=1', true); ?>">use encryption when you log on</a> to help protect against password sniffing.</p>
-           </td>
-         </tr>
-         <?php } ?>
          <tr>
            <th colspan="3" style="text-align: center" class="subhead"><input type="submit" name="login" value="Log in" tabindex="<?php echo ( $level <= USER_LEVEL_MEMBER ) ? '3' : '2'; ?>" /></th>
          </tr>
@@ -244,17 +381,98 @@
 {
   global $db, $session, $paths, $template, $plugins; // Common objects
   global $__login_status;
+  global $lang;
+  if ( $paths->getParam(0) === 'action.json' )
+  {
+    if ( !isset($_POST['r']) )
+      die('No request.');
+    
+    $request = $_POST['r'];
+    try
+    {
+      $request = enano_json_decode($request);
+    }
+    catch ( Exception $e )
+    {
+      die(enano_json_encode(array(
+          'mode' => 'error',
+          'error' => 'ERR_JSON_PARSE_FAILED'
+        )));
+    }
+    
+    echo enano_json_encode($session->process_login_request($request));
+    
+    $db->close();
+    exit;
+  }
   if ( isset($_GET['act']) && $_GET['act'] == 'ajaxlogin' )
   {
     $plugins->attachHook('login_password_reset', 'SpecialLogin_SendResponse_PasswordReset($row[\'user_id\'], $row[\'temp_password\']);');
-    $json = new Services_JSON(SERVICES_JSON_LOOSE_TYPE);
-    $data = $json->decode($_POST['params']);
+    $data = enano_json_decode($_POST['params']);
+    $captcha_hash = ( isset($data['captcha_hash']) ) ? $data['captcha_hash'] : false;
+    $captcha_code = ( isset($data['captcha_code']) ) ? $data['captcha_code'] : false;
     $level = ( isset($data['level']) ) ? intval($data['level']) : USER_LEVEL_MEMBER;
-    $result = $session->login_with_crypto($data['username'], $data['crypt_data'], $data['crypt_key'], $data['challenge'], $level);
-    $session->start();
-    //echo "$result\n$session->sid_super";
-    //exit;
-    if ( $result == 'success' )
+    
+    // 1.1.3: Diffie Hellman
+    global $dh_supported;
+    global $_math;
+    if ( $data['diffiehellman'] && isset($data['publickey_client']) && isset($data['publickey_server']) && isset($data['crypt_key_check']) )
+    {
+      if ( !$dh_supported )
+      {
+        die('Special:Login: Illegal request for Diffie Hellman exchange');
+      }
+      // retrieve our public key
+      if ( !preg_match('/^[0-9]+$/', $data['publickey_server']) )
+      {
+        die('Special:Login: Illegal request for Diffie Hellman exchange');
+      }
+      $pubkey_server =& $data['publickey_server'];
+      
+      // retrieve our private key
+      $q = $db->sql_query('SELECT private_key, key_id FROM ' . table_prefix . "diffiehellman WHERE public_key = '$pubkey_server';");
+      if ( !$q )
+        $db->die_json();
+      
+      if ( $db->numrows() < 1 )
+      {
+        die('Special:Login: Couldn\'t lookup Diffie Hellman key: ' . $pubkey_server);
+      }
+      list($privkey_server, $key_id) = $db->fetchrow_num();
+      $db->free_result();
+      
+      // get shared secret
+      $dh_secret = dh_gen_shared_secret($privkey_server, $data['publickey_client']);
+      $dh_secret = $_math->str($dh_secret);
+      $secret_check = sha1($dh_secret);
+      if ( $secret_check !== $data['crypt_key_check'] )
+      {
+        die(enano_json_encode(array(
+            'mode' => 'error',
+            'error' => 'Diffie Hellman redundancy check failed, couldn\'t rebuild the AES key.',
+            'debug' => array(
+              'server private key' => $privkey_server,
+              'client public key' => $data['publickey_client'],
+              'expected sha1' => $data['crypt_key_check'],
+              'actual sha1' => $secret_check
+              )
+          )));
+      }
+      // we have the secret, now get the sha256 hash
+      $crypt_key = substr(sha256($dh_secret), 0, ( AES_BITS / 4 ));
+    }
+    else if ( !$data['diffiehellman'] && isset($data['crypt_key']) && isset($data['crypt_data']) )
+    {
+      $crypt_key = $data['crypt_key'];
+    }
+    else
+    {
+      die('Special:Login: Illegal request');
+    }
+    
+    $result = $session->login_with_crypto($data['username'], $data['crypt_data'], $crypt_key, $data['challenge'], $level, $captcha_hash, $captcha_code, !$dh_supported);
+    
+    if ( $result['success'] )
     {
       $response = Array(
           'result' => 'success',
@@ -263,38 +481,56 @@
     }
     else
     {
+      $captcha = '';
+      if ( $result['error'] == 'locked_out' && $result['lockout_policy'] == 'captcha' )
+      {
+        $session->kill_captcha();
+        $captcha = $session->make_captcha();
+      }
       $response = Array(
           'result' => 'error',
-          'error' => $result
+          'data' => $result,
+          'captcha' => $captcha
         );
     }
-    $response = $json->encode($response);
+    $response = enano_json_encode($response);
     echo $response;
     $db->close();
     exit;
   }
   if(isset($_POST['login'])) {
+    $captcha_hash = ( isset($_POST['captcha_hash']) ) ? $_POST['captcha_hash'] : false;
+    $captcha_code = ( isset($_POST['captcha_code']) ) ? $_POST['captcha_code'] : false;
     if($_POST['use_crypt'] == 'yes')
     {
-      $result = $session->login_with_crypto($_POST['username'], $_POST['crypt_data'], $_POST['crypt_key'], $_POST['challenge_data'], intval($_POST['auth_level']));
+      $result = $session->login_with_crypto($_POST['username'], $_POST['crypt_data'], $_POST['crypt_key'], $_POST['challenge_data'], intval($_POST['auth_level']), $captcha_hash, $captcha_code);
     }
     else
     {
-      $result = $session->login_without_crypto($_POST['username'], $_POST['pass'], false, intval($_POST['auth_level']));
+      $result = $session->login_without_crypto($_POST['username'], $_POST['pass'], false, intval($_POST['auth_level']), $captcha_hash, $captcha_code);
     }
-    $session->start();
-    $paths->init();
-    if($result == 'success')
+   
+    if($result['success'])
     {
+      $session->start();
+      
       $template->load_theme($session->theme, $session->style);
       if(isset($_POST['return_to']))
       {
         $name = ( isset($paths->pages[$_POST['return_to']]['name']) ) ? $paths->pages[$_POST['return_to']]['name'] : $_POST['return_to'];
-        redirect( makeUrl($_POST['return_to'], false, true), 'Login successful', 'You have successfully logged into the '.getConfig('site_name').' site as "'.$session->username.'". Redirecting to ' . $name . '...' );
+        $subst = array(
+            'username' => $session->username,
+            'redir_target' => $name
+          );
+        redirect( makeUrl($_POST['return_to'], false, true), $lang->get('user_login_success_title'), $lang->get('user_login_success_body', $subst) );
       }
       else
       {
-        redirect( makeUrl(getConfig('main_page'), false, true), 'Login successful', 'You have successfully logged into the '.getConfig('site_name').' site as "'.$session->username.'". Redirecting to the main page...' );
+        $subst = array(
+            'username' => $session->username,
+            'redir_target' => $lang->get('user_login_success_body_mainpage')
+          );
+        redirect( makeUrl(getConfig('main_page'), false, true), $lang->get('user_login_success_title'), $lang->get('user_login_success_body', $subst) );
       }
     }
     else
@@ -306,7 +542,6 @@
 
 function SpecialLogin_SendResponse_PasswordReset($user_id, $passkey)
 {
-  $json = new Services_JSON(SERVICES_JSON_LOOSE_TYPE);
   
   $response = Array(
       'result' => 'success_reset',
@@ -314,7 +549,7 @@
       'temppass' => $passkey
     );
   
-  $response = $json->encode($response);
+  $response = enano_json_encode($response);
   echo $response;
   
   $db->close();
@@ -324,32 +559,47 @@
 
 function page_Special_Logout() {
   global $db, $session, $paths, $template, $plugins; // Common objects
+  global $lang;
   if ( !$session->user_logged_in )
     $paths->main_page();
   
   $l = $session->logout();
   if ( $l == 'success' )
   {
-    redirect(makeUrl(getConfig('main_page'), false, true), 'Logged out', 'You have been successfully logged out, and all cookies have been cleared. You will now be transferred to the main page.', 4);
+    $url = makeUrl(getConfig('main_page'), false, true);
+    if ( $pi = $paths->getAllParams() )
+    {
+      list($pid, $ns) = RenderMan::strToPageID($pi);
+      $perms = $session->fetch_page_acl($pid, $ns);
+      if ( $perms->get_permissions('read') )
+      {
+        $url = makeUrl($pi, false, true);
+      }
+    }
+    redirect($url, $lang->get('user_logout_success_title'), $lang->get('user_logout_success_body'), 4);
   }
   $template->header();
-  echo '<h3>An error occurred during the logout process.</h3><p>'.$l.'</p>';
+  echo '<h3>' . $lang->get('user_logout_err_title') . '</h3>';
+  echo '<p>' . $l . '</p>';
   $template->footer();
 }
 
 function page_Special_Register()
 {
   global $db, $session, $paths, $template, $plugins; // Common objects
+  global $lang;
   
   // form field trackers
   $username = '';
   $email = '';
   $realname = '';
   
+  $terms = getConfig('register_tou');
+  
   if(getConfig('account_activation') == 'disable' && ( ( $session->user_level >= USER_LEVEL_ADMIN && !isset($_GET['IWannaPlayToo']) ) || $session->user_level < USER_LEVEL_ADMIN || !$session->user_logged_in ))
   {
-    $s = ($session->user_level >= USER_LEVEL_ADMIN) ? '<p>Oops...it seems that you <em>are</em> the administrator...hehe...you can also <a href="'.makeUrl($paths->page, 'IWannaPlayToo', true).'">force account registration to work</a>.</p>' : '';
-    die_friendly('Registration disabled', '<p>The administrator has disabled new user registration on this site.</p>' . $s);
+    $s = ($session->user_level >= USER_LEVEL_ADMIN) ? '<p>' . $lang->get('user_reg_err_disabled_body_adminblurb', array( 'reg_link' => makeUrl($paths->page, 'IWannaPlayToo&coppa=no', true) )) . '</p>' : '';
+    die_friendly($lang->get('user_reg_err_disabled_title'), '<p>' . $lang->get('user_reg_err_disabled_body') . '</p>' . $s);
   }
   if ( $session->user_level < USER_LEVEL_ADMIN && $session->user_logged_in )
   {
@@ -361,9 +611,9 @@
     
     $captcharesult = $session->get_captcha($_POST['captchahash']);
     $session->kill_captcha();
-    if(strtolower($captcharesult) != strtolower($_POST['captchacode']))
+    if ( strtolower($captcharesult) != strtolower($_POST['captchacode']) )
     {
-      $s = 'The confirmation code you entered was incorrect.';
+      $s = $lang->get('user_reg_err_captcha');
     }
     else
     {
@@ -371,6 +621,10 @@
       {
         $s = 'Invalid COPPA input';
       }
+      else if ( !empty($terms) && !isset($_POST['tou_agreed']) )
+      {
+        $s = $lang->get('user_reg_err_accept_tou');
+      }
       else
       {
         $coppa = ( isset($_POST['coppa']) && $_POST['coppa'] == 'yes' );
@@ -387,7 +641,7 @@
           $crypt_key = $session->fetch_public_key($_POST['crypt_key']);
           if ( !$crypt_key )
           {
-            $s = 'Couldn\'t look up public encryption key';
+            $s = $lang->get('user_reg_err_missing_key');
           }
           else
           {
@@ -414,28 +668,28 @@
       {
         case "none":
         default:
-          $str = 'You may now <a href="'.makeUrlNS('Special', 'Login').'">log in</a> with the username and password that you created.';
+          $str = $lang->get('user_reg_msg_success_activ_none', array('login_link' => makeUrlNS('Special', 'Login', false, true)));
           break;
         case "user":
-          $str = 'Because this site requires account activation, you have been sent an e-mail with further instructions. Please follow the instructions in that e-mail to continue your registration.';
+          $str = $lang->get('user_reg_msg_success_activ_user');
           break;
         case "admin":
-          $str = 'Because this site requires administrative account activation, you cannot use your account at the moment. A notice has been sent to the site administration team that will alert them that your account has been created.';
+          $str = $lang->get('user_reg_msg_success_activ_admin');
           break;
       }
-      die_friendly('Registration successful', '<p>Thank you for registering, your user account has been created. '.$str.'</p>');
+      die_friendly($lang->get('user_reg_msg_success_title'), '<p>' . $lang->get('user_reg_msg_success_body') . ' ' . $str . '</p>');
     }
     else if ( $s == 'success' && $coppa )
     {
-      $str = 'However, in compliance with the Childrens\' Online Privacy Protection Act, you must have your parent or legal guardian activate your account. Please ask them to check their e-mail for further information.';
-      die_friendly('Registration successful', '<p>Thank you for registering, your user account has been created. '.$str.'</p>');
+      $str = $lang->get('user_reg_msg_success_activ_coppa');
+      die_friendly($lang->get('user_reg_msg_success_title'), '<p>' . $lang->get('user_reg_msg_success_body') . ' ' . $str . '</p>');
     }
     $username = htmlspecialchars($_POST['username']);
     $email    = htmlspecialchars($_POST['email']);
     $realname = htmlspecialchars($_POST['real_name']);
   }
   $template->header();
-  echo 'A user account enables you to have greater control over your browsing experience.';
+  echo $lang->get('user_reg_msg_greatercontrol');
   
   if ( getConfig('enable_coppa') != '1' || ( isset($_GET['coppa']) && in_array($_GET['coppa'], array('yes', 'no')) ) )
   {
@@ -447,49 +701,49 @@
     $challenge = $session->dss_rand();
     
     ?>
-      <h3>Create a user account</h3>
-      <form name="regform" action="<?php echo makeUrl($paths->page); ?>" method="post" onsubmit="runEncryption();">
+      <h3><?php echo $lang->get('user_reg_msg_table_title'); ?></h3>
+      <form name="regform" action="<?php echo makeUrl($paths->page); ?>" method="post" onsubmit="return runEncryption();">
         <div class="tblholder">
           <table border="0" width="100%" cellspacing="1" cellpadding="4">
-            <tr><th class="subhead" colspan="3">Please tell us a little bit about yourself.</th></tr>
+            <tr><th class="subhead" colspan="3"><?php echo $lang->get('user_reg_msg_table_subtitle'); ?></th></tr>
             
             <?php if(isset($_POST['submit'])) echo '<tr><td colspan="3" class="row2" style="color: red;">'.$s.'</td></tr>'; ?>
             
             <!-- FIELD: Username -->
             <tr>
               <td class="row1" style="width: 50%;">
-                Preferred username:
+                <?php echo $lang->get('user_reg_lbl_field_username'); ?>
                 <span id="e_username"></span>
               </td>
               <td class="row1" style="width: 50%;">
-                <input tabindex="1" type="text" name="username" size="30" value="<?php echo $username; ?>" onkeyup="namegood = false; validateForm();" onblur="checkUsername();" />
+                <input tabindex="1" type="text" name="username" size="30" value="<?php echo $username; ?>" onkeyup="namegood = false; validateForm(this);" onblur="checkUsername();" />
               </td>
-              <td class="row1" style="max-width: 24px;">
-                <img alt="Good/bad icon" src="<?php echo scriptPath; ?>/images/bad.gif" id="s_username" />
+              <td class="row1" style="width: 1px;">
+                <img alt="Good/bad icon" src="<?php echo scriptPath; ?>/images/checkbad.png" id="s_username" />
               </td>
             </tr>
             
             <!-- FIELD: Password -->
             <tr>
               <td class="row3" style="width: 50%;" rowspan="<?php echo ( getConfig('pw_strength_enable') == '1' ) ? '3' : '2'; ?>">
-                Password:
+                <?php echo $lang->get('user_reg_lbl_field_password'); ?>
                 <span id="e_password"></span>
                 <?php if ( getConfig('pw_strength_enable') == '1' && getConfig('pw_strength_minimum') > -10 ): ?>
-                <small>It needs to score at least <b><?php echo getConfig('pw_strength_minimum'); ?></b> for your registration to be accepted.</small>
+                <small><?php echo $lang->get('user_reg_msg_password_score'); ?></small>
                 <?php endif; ?>
               </td>
               <td class="row3" style="width: 50%;">
-                <input tabindex="2" type="password" name="password" size="15" onkeyup="<?php if ( getConfig('pw_strength_enable') == '1' ): ?>password_score_field(this); <?php endif; ?>validateForm();" /><?php if ( getConfig('pw_strength_enable') == '1' ): ?><span class="password-checker" style="font-weight: bold; color: #aaaaaa;"> Loading...</span><?php endif; ?>
+                <input tabindex="2" type="password" name="password" size="15" onkeyup="<?php if ( getConfig('pw_strength_enable') == '1' ): ?>password_score_field(this); <?php endif; ?>validateForm(this);" /><?php if ( getConfig('pw_strength_enable') == '1' ): ?><span class="password-checker" style="font-weight: bold; color: #aaaaaa;"> Loading...</span><?php endif; ?>
               </td>
               <td rowspan="<?php echo ( getConfig('pw_strength_enable') == '1' ) ? '3' : '2'; ?>" class="row3" style="max-width: 24px;">
-                <img alt="Good/bad icon" src="<?php echo scriptPath; ?>/images/bad.gif" id="s_password" />
+                <img alt="Good/bad icon" src="<?php echo scriptPath; ?>/images/checkbad.png" id="s_password" />
               </td>
             </tr>
             
             <!-- FIELD: Password confirmation -->
             <tr>
               <td class="row3" style="width: 50%;">
-                <input tabindex="3" type="password" name="password_confirm" size="15" onkeyup="validateForm();" /> <small>Enter your password again to confirm.</small>
+                <input tabindex="3" type="password" name="password_confirm" size="15" onkeyup="validateForm(this);" /> <small><?php echo $lang->get('user_reg_lbl_field_password_confirm'); ?></small>
               </td>
             </tr>
             
@@ -507,29 +761,35 @@
             <tr>
               <td class="row1" style="width: 50%;">
                 <?php
-                  if ( $coppa ) echo 'Your parent or guardian\'s e'; 
-                  else echo 'E';
-                ?>-mail address:
+                  if ( $coppa )
+                  {
+                    echo $lang->get('user_reg_lbl_field_email_coppa');
+                  }
+                  else
+                  {
+                    echo $lang->get('user_reg_lbl_field_email');
+                  }
+                ?>
                 <?php
                   if ( ( $x = getConfig('account_activation') ) == 'user' )
                   {
-                    echo '<br /><small>An e-mail with an account activation key will be sent to this address, so please ensure that it is correct.</small>';
+                    echo '<br /><small>' . $lang->get('user_reg_msg_email_activuser') . '</small>';
                   }
                 ?>
               </td>
               <td class="row1" style="width: 50%;">
-                <input tabindex="4" type="text" name="email" size="30" value="<?php echo $email; ?>" onkeyup="validateForm();" />
+                <input tabindex="4" type="text" name="email" size="30" value="<?php echo $email; ?>" onkeyup="validateForm(this);" />
               </td>
               <td class="row1" style="max-width: 24px;">
-                <img alt="Good/bad icon" src="<?php echo scriptPath; ?>/images/bad.gif" id="s_email" />
+                <img alt="Good/bad icon" src="<?php echo scriptPath; ?>/images/checkbad.png" id="s_email" />
               </td>
             </tr>
             
             <!-- FIELD: Real name -->
             <tr>
               <td class="row3" style="width: 50%;">
-                Real name:<br />
-                <small>Giving your real name is totally optional. If you choose to provide your real name, it will be used to provide attribution for any edits or contributions you may make to this site.</small>
+                <?php echo $lang->get('user_reg_lbl_field_realname'); ?><br />
+                <small><?php echo $lang->get('user_reg_msg_realname_optional'); ?></small>
               </td>
               <td class="row3" style="width: 50%;">
                 <input tabindex="5" type="text" name="real_name" size="30" value="<?php echo $realname; ?>" /></td><td class="row3" style="max-width: 24px;">
@@ -539,11 +799,11 @@
             <!-- FIELD: CAPTCHA image -->
             <tr>
               <td class="row1" style="width: 50%;" rowspan="2">
-                Visual confirmation<br />
+                <?php echo $lang->get('user_reg_lbl_field_captcha'); ?><br />
                 <small>
-                  Please enter the code shown in the image to the right into the text box. This process helps to ensure that this registration is not being performed by an automated bot. If the image to the right is illegible, you can <a href="#" onclick="regenCaptcha(); return false;">generate a new image</a>.<br />
+                  <?php echo $lang->get('user_reg_msg_captcha_pleaseenter', array('regen_flags' => 'href="#" onclick="regenCaptcha(); return false;"')); ?><br />
                   <br />
-                  If you are visually impaired or otherwise cannot read the text shown to the right, please contact the site management and they will create an account for you.
+                  <?php echo $lang->get('user_reg_msg_captcha_blind'); ?>
                 </small>
               </td>
               <td colspan="2" class="row1">
@@ -555,16 +815,50 @@
             <!-- FIELD: CAPTCHA input field -->
             <tr>
               <td class="row1" colspan="2">
-                Code:
+                <?php echo $lang->get('user_reg_lbl_field_captcha_code'); ?>
                 <input tabindex="6" name="captchacode" type="text" size="10" />
                 <input type="hidden" name="captchahash" value="<?php echo $captchacode; ?>" />
               </td>
             </tr>
             
+            <!-- FIELD: TOU -->
+            
+            <?php
+            if ( !empty($terms) ):
+            ?>
+            
+            <tr>
+              <td class="row1" colspan="3">
+                <?php
+                echo $lang->get('user_reg_msg_please_read_tou');
+                ?>
+              </td>
+            </tr>
+            
+            <tr>
+              <td class="row3" colspan="3">
+                <div style="border: 1px solid #000000; height: 75px; width: 60%; clip: rect(0px,auto,auto,0px); overflow: auto; background-color: #FFF; margin: 0 auto; padding: 4px;">
+                  <?php
+                  echo RenderMan::render($terms);
+                  ?>
+                </div>
+                <p style="text-align: center;">
+                  <label>
+                    <input tabindex="7" type="checkbox" name="tou_agreed" />
+                    <b><?php echo $lang->get('user_reg_lbl_field_tou'); ?></b>
+                  </label>
+                </p>
+              </td>
+            </tr>
+            
+            <?php
+            endif;
+            ?>
+            
             <!-- FIELD: submit button -->
             <tr>
               <th class="subhead" colspan="3" style="text-align: center;">
-                <input tabindex="7" type="submit" name="submit" value="Create my account" />
+                <input tabindex="8" type="submit" name="submit" value="<?php echo $lang->get('user_reg_btn_create_account'); ?>" />
               </td>
             </tr>
             
@@ -605,6 +899,18 @@
           var frm = document.forms.regform;
           if ( frm.password.value.length < 1 )
             return true;
+          pass1 = frm.password.value;
+          pass2 = frm.password_confirm.value;
+          if ( pass1 != pass2 )
+          {
+            alert($lang.get('user_reg_err_alert_password_nomatch'));
+            return false;
+          }
+          if ( pass1.length < 6 && pass1.length > 0 )
+          {
+            alert($lang.get('user_reg_err_alert_password_tooshort'));
+            return false;
+          }
           if(aes_testpassed)
           {
             frm.use_crypt.value = 'yes';
@@ -617,21 +923,6 @@
               len = ( typeof cryptkey == 'string' || typeof cryptkey == 'object' ) ? '\nLen: '+cryptkey.length : '';
               alert('The key is messed up\nType: '+typeof(cryptkey)+len);
             }
-          }
-          pass1 = frm.password.value;
-          pass2 = frm.password_confirm.value;
-          if ( pass1 != pass2 )
-          {
-            alert('The passwords you entered do not match.');
-            return false;
-          }
-          if ( pass1.length < 6 && pass1.length > 0 )
-          {
-            alert('The new password must be 6 characters or greater in length.');
-            return false;
-          }
-          if(aes_testpassed)
-          {
             pass = frm.password.value;
             pass = stringToByteArray(pass);
             cryptstring = rijndaelEncrypt(pass, cryptkey, 'ECB');
@@ -653,24 +944,37 @@
         <script type="text/javascript">
           // <![CDATA[
           var namegood = false;
-          function validateForm()
+          function validateForm(field)
           {
+            if ( typeof(field) != 'object' )
+            {
+              field = {
+                name: '_nil',
+                value: '_nil',
+              }
+            }
+            // wait until $lang is initted
+            if ( typeof($lang) != 'object' )
+            {
+              setTimeout('validateForm();', 200);
+              return false;
+            }
             var frm = document.forms.regform;
             failed = false;
             
             // Username
-            if(!namegood)
+            if(!namegood && ( field.name == 'username' || field.name == '_nil' ) ) 
             {
               //if(frm.username.value.match(/^([A-z0-9 \!@\-\(\)]+){2,}$/ig))
               var regex = new RegExp('^([^<>&\?]+){2,}$', 'ig');
               if ( frm.username.value.match(regex) )
               {
-                document.getElementById('s_username').src='<?php echo scriptPath; ?>/images/unknown.gif';
-                document.getElementById('e_username').innerHTML = ''; // '<br /><small><b>Checking availability...</b></small>';
+                document.getElementById('s_username').src='<?php echo scriptPath; ?>/images/checkunk.png';
+                document.getElementById('e_username').innerHTML = '&nbsp;';
               } else {
                 failed = true;
-                document.getElementById('s_username').src='<?php echo scriptPath; ?>/images/bad.gif';
-                document.getElementById('e_username').innerHTML = '<br /><small>Your username must be at least two characters in length and may contain only alphanumeric characters (A-Z and 0-9), spaces, and the following characters: :, !, @, #, *.</small>';
+                document.getElementById('s_username').src='<?php echo scriptPath; ?>/images/checkbad.png';
+                document.getElementById('e_username').innerHTML = '<br /><small>' + $lang.get('user_reg_err_username_invalid') + '</small>';
               }
             }
             document.getElementById('b_username').innerHTML = '';
@@ -680,36 +984,39 @@
             }
             
             // Password
-            if(frm.password.value.match(/^(.+){6,}$/ig) && frm.password_confirm.value.match(/^(.+){6,}$/ig) && frm.password.value == frm.password_confirm.value)
+            if ( field.name == 'password' || field.name == 'password_confirm' || field.name == '_nil' )
             {
-              document.getElementById('s_password').src='<?php echo scriptPath; ?>/images/good.gif';
-              document.getElementById('e_password').innerHTML = '<br /><small>The password you entered is valid.</small>';
-            } else {
-              failed = true;
-              if(frm.password.value.length < 6)
+              if(frm.password.value.match(/^(.+){6,}$/ig) && frm.password_confirm.value.match(/^(.+){6,}$/ig) && frm.password.value == frm.password_confirm.value )
               {
-                document.getElementById('e_password').innerHTML = '<br /><small>Your password must be at least six characters in length.</small>';
+                document.getElementById('s_password').src='<?php echo scriptPath; ?>/images/check.png';
+                document.getElementById('e_password').innerHTML = '<br /><small>' + $lang.get('user_reg_err_password_good') + '</small>';
+              } else {
+                failed = true;
+                if(frm.password.value.length < 6)
+                {
+                  document.getElementById('e_password').innerHTML = '<br /><small>' + $lang.get('user_reg_msg_password_length') + '</small>';
+                }
+                else if(frm.password.value != frm.password_confirm.value)
+                {
+                  document.getElementById('e_password').innerHTML = '<br /><small>' + $lang.get('user_reg_msg_password_needmatch') + '</small>';
+                }
+                else
+                {
+                  document.getElementById('e_password').innerHTML = '';
+                }
+                document.getElementById('s_password').src='<?php echo scriptPath; ?>/images/checkbad.png';
               }
-              else if(frm.password.value != frm.password_confirm.value)
-              {
-                document.getElementById('e_password').innerHTML = '<br /><small>The passwords you entered do not match.</small>';
-              }
-              else
-              {
-                document.getElementById('e_password').innerHTML = '';
-              }
-              document.getElementById('s_password').src='<?php echo scriptPath; ?>/images/bad.gif';
             }
             
             // E-mail address
             
             // workaround for idiot jEdit bug
-            if ( validateEmail(frm.email.value) )
+            if ( validateEmail(frm.email.value) && ( field.name == 'email' || field.name == '_nil' ) )
             {
-              document.getElementById('s_email').src='<?php echo scriptPath; ?>/images/good.gif';
+              document.getElementById('s_email').src='<?php echo scriptPath; ?>/images/check.png';
             } else {
               failed = true;
-              document.getElementById('s_email').src='<?php echo scriptPath; ?>/images/bad.gif';
+              document.getElementById('s_email').src='<?php echo scriptPath; ?>/images/checkbad.png';
             }
             if(failed)
             {
@@ -727,26 +1034,26 @@
               var regex = new RegExp('^([^<>&\?]+){2,}$', 'ig');
               if ( frm.username.value.match(regex) )
               {
-                document.getElementById('s_username').src='<?php echo scriptPath; ?>/images/unknown.gif';
-                document.getElementById('e_username').innerHTML = '';
+                document.getElementById('s_username').src='<?php echo scriptPath; ?>/images/checkunk.png';
+                document.getElementById('e_username').innerHTML = '&nbsp;';
               } else {
-                document.getElementById('s_username').src='<?php echo scriptPath; ?>/images/bad.gif';
-                document.getElementById('e_username').innerHTML = '<br /><small>Your username must be at least two characters in length and may contain only alphanumeric characters (A-Z and 0-9), spaces, and the following characters: :, !, @, #, *.</small>';
+                document.getElementById('s_username').src='<?php echo scriptPath; ?>/images/checkbad.png';
+                document.getElementById('e_username').innerHTML = '<br /><small>' + $lang.get('user_reg_err_username_invalid') + '</small>';
                 return false;
               }
             }
             
-            document.getElementById('e_username').innerHTML = '<br /><small><b>Checking availability...</b></small>';
+            document.getElementById('e_username').innerHTML = '<br /><small><b>' + $lang.get('user_reg_msg_username_checking') + '</b></small>';
             ajaxGet('<?php echo scriptPath; ?>/ajax.php?title=null&_mode=checkusername&name='+escape(frm.username.value), function() {
-              if(ajax.readyState == 4)
+              if ( ajax.readyState == 4 && ajax.status == 200 )
                 if(ajax.responseText == 'good')
                 {
-                  document.getElementById('s_username').src='<?php echo scriptPath; ?>/images/good.gif';
-                  document.getElementById('e_username').innerHTML = '<br /><small><b>This username is available.</b></small>';
+                  document.getElementById('s_username').src='<?php echo scriptPath; ?>/images/check.png';
+                  document.getElementById('e_username').innerHTML = '<br /><small><b>' + $lang.get('user_reg_msg_username_available') + '</b></small>';
                   namegood = true;
                 } else if(ajax.responseText == 'bad') {
-                  document.getElementById('s_username').src='<?php echo scriptPath; ?>/images/bad.gif';
-                  document.getElementById('e_username').innerHTML = '<br /><small><b>Error: that username is already taken.</b></small>';
+                  document.getElementById('s_username').src='<?php echo scriptPath; ?>/images/checkbad.png';
+                  document.getElementById('e_username').innerHTML = '<br /><small><b>' + $lang.get('user_reg_msg_username_unavailable') + '</b></small>';
                   namegood = false;
                 } else {
                   document.getElementById('e_username').innerHTML = ajax.responseText;
@@ -772,10 +1079,10 @@
   }
   else
   {
-    $year = intval( date('Y') );
+    $year = intval( enano_date('Y') );
     $year = $year - 13;
-    $month = date('F');
-    $day = date('d');
+    $month = enano_date('F');
+    $day = enano_date('d');
     
     $yo13_date = "$month $day, $year";
     $link_coppa_yes = makeUrlNS('Special', 'Register', 'coppa=yes', true);
@@ -786,13 +1093,13 @@
     echo '<table border="0" cellspacing="1" cellpadding="4">';
     echo '<tr>
             <td class="row1">
-              Before you can register, please tell us your age.
+              ' . $lang->get('user_reg_coppa_title') . '
             </td>
           </tr>
           <tr>
             <td class="row3">
-              <a href="' . $link_coppa_no  . '">I was born <b>on or before</b> ' . $yo13_date . ' and am <b>at least</b> 13 years of age</a><br />
-              <a href="' . $link_coppa_yes . '">I was born <b>after</b> ' . $yo13_date . ' and am <b>less than</b> 13 years of age</a>
+              <a href="' . $link_coppa_no  . '">' . $lang->get('user_reg_coppa_link_atleast13', array( 'yo13_date' => $yo13_date )) . '</a><br />
+              <a href="' . $link_coppa_yes . '">' . $lang->get('user_reg_coppa_link_not13', array( 'yo13_date' => $yo13_date )) . '</a>
             </td>
           </tr>';
     echo '</table>';
@@ -801,89 +1108,175 @@
   $template->footer();
 }
 
-/*
-If you want the old preferences page back, be my guest.
-function page_Special_Preferences() {
-  global $db, $session, $paths, $template, $plugins; // Common objects
-  $template->header();
-  if(isset($_POST['submit'])) {
-    $data = $session->update_user($session->user_id, $_POST['username'], $_POST['current_pass'], $_POST['new_pass'], $_POST['email'], $_POST['real_name'], $_POST['sig']);
-    if($data == 'success') echo '<h3>Information</h3><p>Your profile has been updated. <a href="'.scriptPath.'/">Return to the index page</a>.</p>';
-    else echo $data;
-  } else {
-    echo '
-    <h3>Edit your profile</h3>
-    <form action="'.makeUrl($paths->nslist['Special'].'Preferences').'" method="post">
-      <table border="0" style="margin-left: 0.2in;">   
-        <tr><td>Username:</td><td><input type="text" name="username" value="'.$session->username.'" /></td></tr>
-        <tr><td>Current Password:</td><td><input type="password" name="current_pass" /></td></tr>
-        <tr><td colspan="2"><small>You only need to enter your current password if you are changing your e-mail address or changing your password.</small></td></tr>
-        <tr><td>New Password:</td><td><input type="password" name="new_pass" /></td></tr>
-        <tr><td>E-mail:</td><td><input type="text" name="email" value="'.$session->email.'" /></td></tr>
-        <tr><td>Real Name:</td><td><input type="text" name="real_name" value="'.$session->real_name.'" /></td></tr>
-        <tr><td>Signature:<br /><small>Your signature appears<br />below your comment posts.</small></td><td><textarea rows="10" cols="40" name="sig">'.$session->signature.'</textarea></td></tr>
-        <tr><td colspan="2">
-        <input type="submit" name="submit" value="Save Changes" /></td></tr>
-      </table>
-    </form>
-    ';
-  }
-  $template->footer();
-}
-*/
-
 function page_Special_Contributions() {
   global $db, $session, $paths, $template, $plugins; // Common objects
+  global $lang;
+  
+  // This is a vast improvement over the old Special:Contributions in 1.0.x.
+  
   $template->header();
   $user = $paths->getParam();
-  if(!$user && isset($_GET['user']))
+  if ( !$user && isset($_GET['user']) )
   {
     $user = $_GET['user'];
   }
-  elseif(!$user && !isset($_GET['user']))
+  else if ( !$user && !isset($_GET['user']) )
   {
-    echo 'No user selected!';
+    echo '<p>' . $lang->get('userfuncs_contribs_err_no_user') . '</p>';
     $template->footer();
     return;
   }
   
   $user = $db->escape($user);
+  $q = 'SELECT log_type, time_id, action, date_string, page_id, namespace, author, edit_summary, minor_edit, page_id, namespace, ( action = \'edit\' ) AS is_edit FROM '.table_prefix.'logs WHERE author=\''.$user.'\' AND log_type=\'page\' AND is_draft != 1 ORDER BY is_edit DESC, time_id DESC;';
+  $q = $db->sql_query($q);
+  if ( !$q )
+    $db->_die('SpecialUserFuncs selecting contribution data');
   
-  $q = 'SELECT time_id,date_string,page_id,namespace,author,edit_summary,minor_edit,page_id,namespace FROM '.table_prefix.'logs WHERE author=\''.$user.'\' AND action=\'edit\' ORDER BY time_id DESC;';
-  if(!$db->sql_query($q)) $db->_die('The history data for the page "'.$paths->cpage['name'].'" could not be selected.');
-  echo 'History of edits and actions<h3>Edits:</h3>';
-  if($db->numrows() < 1) echo 'No history entries in this category.';
-  while($r = $db->fetchrow())
+  echo '<h3>' . $lang->get('userfuncs_contribs_heading_edits') . '</h3>';
+  
+  $cnt_edits = 0;
+  $cnt_other = 0;
+  $current = 'cnt_edits';
+  $cls = 'row2';
+  
+  while ( $row = $db->fetchrow($q) )
   {
-    $title = get_page_title($r['page_id'], $r['namespace']);    
-    echo '<a href="' . makeUrlNS($r['namespace'], $r['page_id'], "oldid={$r['time_id']}", true) . '" onclick="ajaxHistView(\''.$r['time_id'].'\', \''.$paths->nslist[$r['namespace']].$r['page_id'].'\'); return false;"><i>'.$r['date_string'].'</i></a> (<a href="#" onclick="ajaxRollback(\''.$r['time_id'].'\'); return false;">revert to</a>) <a href="'.makeUrl($paths->nslist[$r['namespace']].$r['page_id']).'">'.htmlspecialchars($title).'</a>: '.$r['edit_summary'];
-    if($r['minor_edit']) echo '<b> - minor edit</b>';
-    echo '<br />';
-  }
-  $db->free_result();
-  echo '<h3>Other changes:</h3>';
-  $q = 'SELECT log_type,time_id,action,date_string,page_id,namespace,author,edit_summary,minor_edit,page_id,namespace FROM '.table_prefix.'logs WHERE author=\''.$user.'\' AND action!=\'edit\' ORDER BY time_id DESC;';
-  if(!$db->sql_query($q)) $db->_die('The history data for the page "'.$paths->cpage['name'].'" could not be selected.');
-  if($db->numrows() < 1) echo 'No history entries in this category.';
-  while($r = $db->fetchrow()) 
-  {
-    if ( $r['log_type'] == 'page' )
+    if ( $current == 'cnt_edits' && $row['is_edit'] != 1 )
+    {
+      // No longer processing page edits - split the table
+      if ( $cnt_edits == 0 )
+      {
+        echo '<p>' . $lang->get('userfuncs_contribs_msg_no_edits') . '</p>';
+      }
+      else
+      {
+        echo '</table></div>';
+        echo '<h3>' . $lang->get('userfuncs_contribs_heading_other') . '</h3>';
+      }
+      $current = 'cnt_other';
+      $cls = 'row2';
+    }
+    if ( $$current == 0 )
+    {
+      echo '<div class="tblholder">
+              <table border="0" cellspacing="1" cellpadding="4">';
+      echo '  <tr>
+                <th>' . $lang->get('history_col_datetime') . '</th>';
+      echo '    <th>' . $lang->get('history_col_page') . '</th>';
+      if ( $current == 'cnt_edits' )
+      {
+        echo '  <th>' . $lang->get('history_col_summary') . '</th>';
+      }
+      echo '    <th>' . $lang->get('history_col_minor') . '</th>';
+      if ( $current == 'cnt_other' )
+      {
+        echo '  <th>' . $lang->get('history_col_action_taken') . '</th>
+                <th>' . $lang->get('history_col_extra') . '</th>
+             ';
+      }
+      echo '    <th>' . $lang->get('history_col_actions') . '</th>
+              </tr>';
+    }
+    $$current++;
+    $cls = ( $cls == 'row1' ) ? 'row2' : 'row1';
+    
+    echo '<tr>';
+    
+    // date & time
+    echo '  <td class="' . $cls . '">' . enano_date('d M Y h:i a', $row['time_id']) . '</td>';
+    
+    // page & link to said page
+    echo '  <td class="' . $cls . '"><a href="' . makeUrlNS($row['namespace'], $row['page_id']) . '">' . get_page_title_ns($row['page_id'], $row['namespace']) . '</a></td>';
+    
+    switch ( $row['action'] )
     {
-      $title = get_page_title($r['page_id'], $r['namespace']);
-      echo '(<a href="#" onclick="ajaxRollback(\''.$r['time_id'].'\'); return false;">rollback</a>) <i>'.$r['date_string'].'</i> <a href="'.makeUrl($paths->nslist[$r['namespace']].$r['page_id']).'">'.htmlspecialchars($title).'</a>: ';
-      if      ( $r['action'] == 'prot'   ) echo 'Protected page; reason: '.$r['edit_summary'];
-      else if ( $r['action'] == 'unprot' ) echo 'Unprotected page; reason: '.$r['edit_summary'];
-      else if ( $r['action'] == 'rename' ) echo 'Renamed page; old title was: '.htmlspecialchars($r['edit_summary']);
-      else if ( $r['action'] == 'create' ) echo 'Created page';
-      else if ( $r['action'] == 'delete' ) echo 'Deleted page';
-      if ( $r['minor_edit'] ) echo '<b> - minor edit</b>';
-      echo '<br />';
+      case 'edit':
+        if ( $row['edit_summary'] == 'Automatic backup created when logs were purged' )
+        {
+          $row['edit_summary'] = $lang->get('history_summary_clearlogs');
+        }
+        else if ( empty($row['edit_summary']) )
+        {
+          $row['edit_summary'] = '<span style="color: #808080">' . $lang->get('history_summary_none_given') . '</span>';
+        }
+        echo '  <td class="' . $cls . '">' . $row['edit_summary'] . '</td>';
+        if ( $row['minor_edit'] == 1 )
+        {
+          echo '<td class="' . $cls . '"><b>M</b></td>';
+        }
+        else
+        {
+          echo '<td class="' . $cls . '"></td>';
+        }
+        break;
+      case 'prot':
+        echo '  <td class="' . $cls . '"></td>';
+        echo '  <td class="' . $cls . '">' . $lang->get('history_log_protect') . '</td>';
+        echo '  <td class="' . $cls . '">' . $lang->get('history_extra_reason') . ' ' . $row['edit_summary'] . '</td>';
+        break;
+      case 'unprot':
+        echo '  <td class="' . $cls . '"></td>';
+        echo '  <td class="' . $cls . '">' . $lang->get('history_log_unprotect') . '</td>';
+        echo '  <td class="' . $cls . '">' . $lang->get('history_extra_reason') . ' ' . $row['edit_summary'] . '</td>';
+        break;
+      case 'semiprot':
+        echo '  <td class="' . $cls . '"></td>';
+        echo '  <td class="' . $cls . '">' . $lang->get('history_log_semiprotect') . '</td>';
+        echo '  <td class="' . $cls . '">' . $lang->get('history_extra_reason') . ' ' . $row['edit_summary'] . '</td>';
+        break;
+      case 'rename':
+        echo '  <td class="' . $cls . '"></td>';
+        echo '  <td class="' . $cls . '">' . $lang->get('history_log_rename') . '</td>';
+        echo '  <td class="' . $cls . '">' . $lang->get('history_extra_oldtitle') . ' ' . htmlspecialchars($row['edit_summary']) . '</td>';
+        break;
+      case 'create':
+        echo '  <td class="' . $cls . '"></td>';
+        echo '  <td class="' . $cls . '">' . $lang->get('history_log_create') . '</td>';
+        echo '  <td class="' . $cls . '"></td>';
+        break;
+      case 'delete':
+        echo '  <td class="' . $cls . '"></td>';
+        echo '  <td class="' . $cls . '">' . $lang->get('history_log_delete') . '</td>';
+        echo '  <td class="' . $cls . '">' . $lang->get('history_extra_reason') . ' ' . $row['edit_summary'] . '</td>';
+        break;
+      case 'reupload':
+        echo '  <td class="' . $cls . '"></td>';
+        echo '  <td class="' . $cls . '">' . $lang->get('history_log_uploadnew') . '</td>';
+        echo '  <td class="' . $cls . '">' . $lang->get('history_extra_reason') . ' ' . $row['edit_summary'] . '</td>';
+        break;
     }
-    else if($r['log_type']=='security') 
+    
+    // actions column
+    echo '    <td class="' . $cls . '" style="text-align: center;">';
+    if ( $row['is_edit'] == 1 )
     {
-      // Not implemented, and when it is, it won't be public
+      echo '    <a href="' . makeUrlNS($row['namespace'], $row['page_id'], "oldid={$row['time_id']}", true) . '">' . $lang->get('history_action_view') . '</a> | ';
+      echo '      <a href="' . makeUrlNS($row['namespace'], $row['page_id'], "do=rollback&id={$row['time_id']}", true) . '">' . $lang->get('history_action_restore') . '</a>';
+    }
+    else
+    {
+      echo '      <a href="' . makeUrlNS($row['namespace'], $row['page_id'], "do=rollback&id={$row['time_id']}", true) . '">' . $lang->get('history_action_revert') . '</a>';
+    }
+    echo '    </td>';
+    
+    if ( $current == 'cnt_other' && $cnt_edits + $cnt_other >= $db->numrows($q) )
+    {
+      echo '</table></div>';
     }
   }
+  
+  if ( $current == 'cnt_edits' )
+  {
+    // no "other" edits, close the table
+    if ( $cnt_edits > 0 )
+      echo '</table></div>';
+    else
+      echo '<p>' . $lang->get('userfuncs_contribs_msg_no_edits') . '</p>';
+    echo '<h3>' . $lang->get('userfuncs_contribs_heading_other') . '</h3>';
+    echo '<p>' . $lang->get('userfuncs_contribs_msg_no_other') . '</p>';
+  }
+  
   $db->free_result();
   $template->footer();
 }
@@ -891,7 +1284,12 @@
 function page_Special_ChangeStyle()
 {
   global $db, $session, $paths, $template, $plugins; // Common objects
-  if(!$session->user_logged_in) die_friendly('Access denied', '<p>You must be logged in to change your style. Spoofer.</p>');
+  global $lang;
+  
+  if ( !$session->user_logged_in )
+  {
+    die_friendly('Access denied', '<p>You must be logged in to change your style. Spoofer.</p>');
+  }
   if(isset($_POST['theme']) && isset($_POST['style']) && isset($_POST['return_to']))
   {
     if ( !preg_match('/^([a-z0-9_-]+)$/i', $_POST['theme']) )
@@ -900,51 +1298,64 @@
       die('Hacking attempt');
     $d = ENANO_ROOT . '/themes/' . $_POST['theme'];
     $f = ENANO_ROOT . '/themes/' . $_POST['theme'] . '/css/' . $_POST['style'] . '.css';
-    if(!file_exists($d) || !is_dir($d)) die('The directory "'.$d.'" does not exist.');
-    if(!file_exists($f)) die('The file "'.$f.'" does not exist.');
+    if ( !file_exists($d) || !is_dir($d) )
+    {
+      die('The directory "'.$d.'" does not exist.');
+    }
+    if ( !file_exists($f) )
+    {
+      die('The file "'.$f.'" does not exist.');
+    }
     $d = $db->escape($_POST['theme']);
     $f = $db->escape($_POST['style']);
     $q = 'UPDATE '.table_prefix.'users SET theme=\''.$d.'\',style=\''.$f.'\' WHERE username=\''.$session->username.'\'';
-    if(!$db->sql_query($q))
+    if ( !$db->sql_query($q) )
     {
       $db->_die('Your theme/style preferences were not updated.');
     }
     else
     {
-      redirect(makeUrl($_POST['return_to']), '', '', 0);
+      redirect(makeUrl($_POST['return_to']), $lang->get('userfuncs_changetheme_success_title'), $lang->get('userfuncs_changetheme_success_body'), 3);
     }
   }
   else
   {
     $template->header();
       $ret = ( isset($_POST['return_to']) ) ? $_POST['return_to'] : $paths->getParam(0);
-      if(!$ret) $ret = getConfig('main_page');
+      if ( !$ret )
+      {
+        $ret = getConfig('main_page');
+      }
       ?>
         <form action="<?php echo makeUrl($paths->page); ?>" method="post">
-          <?php if(!isset($_POST['themeselected'])) { ?>
-            <h3>Please select a new theme:</h3>
+          <?php if ( !isset($_POST['themeselected']) ) { ?>
+            <h3><?php echo $lang->get('userfuncs_changetheme_heading_theme'); ?></h3>
             <p>
               <select name="theme">
                <?php
-                foreach($template->theme_list as $t) {
-                  if($t['enabled'])
+                foreach ( $template->theme_list as $t )
+                {
+                  if ( $t['enabled'] )
                   {
                     echo '<option value="'.$t['theme_id'].'"';
-                    if($t['theme_id'] == $session->theme) echo ' selected="selected"';
-                    echo '>'.$t['theme_name'].'</option>';
+                    if ( $t['theme_id'] == $session->theme )
+                    {
+                      echo ' selected="selected"';
+                    }
+                    echo '>' . $t['theme_name'] . '</option>';
                   }
                 }
                ?>
               </select>
             </p>
             <p><input type="hidden" name="return_to" value="<?php echo $ret; ?>" />
-               <input type="submit" name="themeselected" value="Continue" /></p>
+               <input type="submit" name="themeselected" value="<?php echo $lang->get('userfuncs_changetheme_btn_continue'); ?>" /></p>
           <?php } else { 
             $theme = $_POST['theme'];
             if ( !preg_match('/^([0-9A-z_-]+)$/i', $theme ) )
               die('Hacking attempt');
             ?>
-            <h3>Please select a stylesheet:</h3>
+            <h3><?php echo $lang->get('userfuncs_changetheme_heading_style'); ?></h3>
             <p>
               <select name="style">
                 <?php
@@ -970,7 +1381,7 @@
             </p>
             <p><input type="hidden" name="return_to" value="<?php echo $ret; ?>" />
                <input type="hidden" name="theme" value="<?php echo $theme; ?>" />
-               <input type="submit" name="allclear" value="Change style" /></p>
+               <input type="submit" name="allclear" value="<?php echo $lang->get('userfuncs_changetheme_btn_allclear'); ?>" /></p>
           <?php } ?>
         </form>
       <?php
@@ -981,13 +1392,27 @@
 function page_Special_ActivateAccount()
 {
   global $db, $session, $paths, $template, $plugins; // Common objects
+  global $lang;
+  
   $user = $paths->getParam(0);
-  if(!$user) die_friendly('Account activation error', '<p>This page can only be accessed using links sent to users via e-mail.</p>');
+  if ( !$user )
+  {
+    die_friendly($lang->get('userfuncs_activate_err_badlink_title'), '<p>' . $lang->get('userfuncs_activate_err_badlink_body') . '</p>');
+  }
   $key = $paths->getParam(1);
-  if(!$key) die_friendly('Account activation error', '<p>This page can only be accessed using links sent to users via e-mail.</p>');
+  if ( !$key )
+  {
+    die_friendly($lang->get('userfuncs_activate_err_badlink_title'), '<p>' . $lang->get('userfuncs_activate_err_badlink_body') . '</p>');
+  }
   $s = $session->activate_account(str_replace('_', ' ', $user), $key);
-  if($s > 0) die_friendly('Activation successful', '<p>Your account is now active. Thank you for registering.</p>');
-  else die_friendly('Activation failed', '<p>The activation key was probably incorrect.</p>');
+  if ( $s > 0 )
+  {
+    die_friendly($lang->get('userfuncs_activate_success_title'), '<p>' . $lang->get('userfuncs_activate_success_body') . '</p>');
+  }
+  else
+  {
+    die_friendly($lang->get('userfuncs_activate_err_badlink_title'), '<p>' . $lang->get('userfuncs_activate_err_bad_key') . '</p>');
+  }
 }
 
 function page_Special_Captcha()
@@ -1001,43 +1426,30 @@
   }
   
   $hash = $paths->getParam(0);
-  if ( !$hash || !preg_match('#^([0-9a-f]*){32,32}$#i', $hash) )
+  if ( !$hash || !preg_match('#^([0-9a-f]*){32,40}$#i', $hash) )
   {
     $paths->main_page();
   }
-  
-  // Determine code length
-  $ip = ip2hex($_SERVER['REMOTE_ADDR']);
-  if ( !$ip )
-    die('(very desperate) Hacking attempt');
-  $q = $db->sql_query('SELECT CHAR_LENGTH(salt) AS len FROM ' . table_prefix . 'session_keys WHERE session_key = \'' . $db->escape($hash) . '\' AND source_ip = \'' . $db->escape($ip) . '\';');
+
+  $session->make_captcha(7, $hash);  
+  $code = $session->generate_captcha_code();
+  $q = $db->sql_query('UPDATE ' . table_prefix . "captcha SET code = '$code' WHERE session_id = '$hash';");
   if ( !$q )
-    $db->_die('SpecialUserFuncs selecting CAPTCHA code');
-  if ( $db->numrows() < 1 )
-    die('Invalid hash or hacking attempt by IP');
-  
-  // Generate code
-  $row = $db->fetchrow();
-  $db->free_result();
-  $len = intval($row['len']);
-  if ( $len < 4 )
-    $len = 7;
-  $code = $session->generate_captcha_code($len);
-  
-  // Update database with new code
-  $q = $db->sql_query('UPDATE ' . table_prefix . 'session_keys SET salt = \'' . $code . '\' WHERE session_key = \'' . $db->escape($hash) . '\' AND source_ip = \'' . $db->escape($ip) . '\';');
-  if ( !$q )
-    $db->_die('SpecialUserFuncs generating new CAPTCHA confirmation code');
+    $db->_die();
   
   require ( ENANO_ROOT.'/includes/captcha.php' );
-  $captcha = new captcha($code);
+  $captcha = captcha_object($hash, 'freecap');
+  $captcha->debug = true;
   $captcha->make_image();
+  
   exit;
 }
 
 function page_Special_PasswordReset()
 {
   global $db, $session, $paths, $template, $plugins; // Common objects
+  global $lang;
+  
   $template->header();
   if($paths->getParam(0) == 'stage2')
   {
@@ -1068,7 +1480,7 @@
     
     if ( ( intval($row['temp_password_time']) + ( 3600 * 24 ) ) < time() )
     {
-      echo '<p>Your temporary password has expired. Please <a href="' . makeUrlNS('Special', 'PasswordReset') . '">request another one</a>.</p>';
+      echo '<p>' . $lang->get('userfuncs_passreset_err_pass_expired', array('reset_url' => makeUrlNS('Special', 'PasswordReset'))) . '</p>';
       $template->footer();
       return false;
     }
@@ -1081,7 +1493,7 @@
         $crypt_key = $session->fetch_public_key($_POST['crypt_key']);
         if(!$crypt_key)
         {
-          echo 'ERROR: Couldn\'t look up public key for decryption.';
+          echo $lang->get('user_err_key_not_found');
           $template->footer();
           return false;
         }
@@ -1089,7 +1501,7 @@
         $data = $aes->decrypt($_POST['crypt_data'], $crypt_key, ENC_HEX);
         if(strlen($data) < 6)
         {
-          echo 'ERROR: Your password must be six characters or greater in length.';
+          echo $lang->get('userfuncs_passreset_err_too_short');
           $template->footer();
           return false;
         }
@@ -1100,13 +1512,13 @@
         $conf = $_POST['pass_confirm'];
         if($data != $conf)
         {
-          echo 'ERROR: The passwords you entered do not match.';
+          echo $lang->get('userfuncs_passreset_err_no_match');
           $template->footer();
           return false;
         }
         if(strlen($data) < 6)
         {
-          echo 'ERROR: Your password must be six characters or greater in length.';
+          echo $lang->get('userfuncs_passreset_err_too_short');
           $template->footer();
           return false;
         }
@@ -1124,7 +1536,7 @@
         if ( $inp_score < $min_score )
         {
           $url = makeUrl($paths->fullpage);
-          echo "<p>ERROR: Your password did not pass the complexity score requirement. You need $min_score points to pass; your password received a score of $inp_score. <a href=\"$url\">Go back</a></p>";
+          echo "<p>" . $lang->get('userfuncs_passreset_err_failed_score', array('inp_score' => $inp_score, 'url' => $url)) . "</p>";
           $template->footer();
           return false;
         }
@@ -1135,7 +1547,7 @@
       if($q)
       {
         $session->login_without_crypto($row['username'], $data);
-        echo '<p>Your password has been reset. Return to the <a href="' . makeUrl(getConfig('main_page')) . '">main page</a>.</p>';
+        echo '<p>' . $lang->get('userfuncs_passreset_stage2_success', array('url_mainpage' => makeUrl(getConfig('main_page')))) . '</p>';
       }
       else
       {
@@ -1150,24 +1562,24 @@
     $pubkey = $session->rijndael_genkey();
     
     $evt_get_score = ( getConfig('pw_strength_enable') == '1' ) ? 'onkeyup="password_score_field(this);" ' : '';
-    $pw_meter =      ( getConfig('pw_strength_enable') == '1' ) ? '<tr><td class="row1">Password strength rating:</td><td class="row1"><div id="pwmeter"></div><script type="text/javascript">password_score_field(document.forms.resetform.pass);</script></td></tr>' : '';
-    $pw_blurb =      ( getConfig('pw_strength_enable') == '1' && intval(getConfig('pw_strength_minimum')) > -10 ) ? '<br /><small>Your password needs to have a score of at least <b>'.getConfig('pw_strength_minimum').'</b>.</small>' : '';
+    $pw_meter =      ( getConfig('pw_strength_enable') == '1' ) ? '<tr><td class="row1">' . $lang->get('userfuncs_passreset_stage2_lbl_strength') . '</td><td class="row1"><div id="pwmeter"></div><script type="text/javascript">password_score_field(document.forms.resetform.pass);</script></td></tr>' : '';
+    $pw_blurb =      ( getConfig('pw_strength_enable') == '1' && intval(getConfig('pw_strength_minimum')) > -10 ) ? '<br /><small>' . $lang->get('userfuncs_passreset_stage2_blurb_strength') . '</small>' : '';
     
     ?>
     <form action="<?php echo makeUrl($paths->fullpage); ?>" method="post" name="resetform" onsubmit="return runEncryption();">
       <br />
       <div class="tblholder">
         <table border="0" style="width: 100%;" cellspacing="1" cellpadding="4">
-          <tr><th colspan="2">Reset password</th></tr>
-          <tr><td class="row1">Password:<?php echo $pw_blurb; ?></td><td class="row1"><input name="pass" type="password" <?php echo $evt_get_score; ?>/></td></tr>
-          <tr><td class="row2">Confirm: </td><td class="row2"><input name="pass_confirm" type="password" /></td></tr>
+          <tr><th colspan="2"><?php echo $lang->get('userfuncs_passreset_stage2_th'); ?></th></tr>
+          <tr><td class="row1"><?php echo $lang->get('userfuncs_passreset_stage2_lbl_password'); ?> <?php echo $pw_blurb; ?></td><td class="row1"><input name="pass" type="password" <?php echo $evt_get_score; ?>/></td></tr>
+          <tr><td class="row2"><?php echo $lang->get('userfuncs_passreset_stage2_lbl_confirm'); ?> </td><td class="row2"><input name="pass_confirm" type="password" /></td></tr>
           <?php echo $pw_meter; ?>
           <tr>
-            <td colspan="2" class="row1" style="text-align: center;">
+            <td colspan="2" class="row3" style="text-align: center;">
               <input type="hidden" name="use_crypt" value="no" />
               <input type="hidden" name="crypt_key" value="<?php echo $pubkey; ?>" />
               <input type="hidden" name="crypt_data" value="" />
-              <input type="submit" name="do_stage2" value="Reset password" />
+              <input type="submit" name="do_stage2" value="<?php echo $lang->get('userfuncs_passreset_stage2_btn_submit'); ?>" />
             </td>
           </tr>
         </table>
@@ -1217,12 +1629,12 @@
         pass2 = frm.pass_confirm.value;
         if ( pass1 != pass2 )
         {
-          alert('The passwords you entered do not match.');
+          alert($lang.get('userfuncs_passreset_err_no_match'));
           return false;
         }
         if ( pass1.length < 6 )
         {
-          alert('The new password must be 6 characters or greater in length.');
+          alert($lang.get('userfuncs_passreset_err_too_short'));
           return false;
         }
         if(testpassed)
@@ -1251,20 +1663,20 @@
   {
     if($session->mail_password_reset($_POST['username']))
     {
-      echo '<p>An e-mail has been sent to the e-mail address on file for your username with a new password in it. Please check your e-mail for further instructions.</p>';
+      echo '<p>' . $lang->get('userfuncs_passreset_stage1_success') . '</p>';
     }
     else
     {
-      echo '<p>Error occured, your new password was not sent.</p>';
+      echo '<p>' . $lang->get('userfuncs_passreset_stage1_error') . '</p>';
     }
     $template->footer();
     return true;
   }
-  echo '<p>Don\'t worry, it happens to the best of us.</p>
-        <p>To reset your password, just enter your username below, and a new password will be e-mailed to you.</p>
+  echo '<p>' . $lang->get('userfuncs_passreset_blurb_line1') . '</p>
+        <p>' . $lang->get('userfuncs_passreset_blurb_line2') . '</p>
         <form action="'.makeUrl($paths->page).'" method="post" onsubmit="if(!submitAuthorized) return false;">
-          <p>Username:  '.$template->username_field('username').'</p>
-          <p><input type="submit" name="do_reset" value="Mail new password" /></p>
+          <p>' . $lang->get('userfuncs_passreset_lbl_username') . '  '.$template->username_field('username').'</p>
+          <p><input type="submit" name="do_reset" value="' . $lang->get('userfuncs_passreset_btn_mailpasswd') . '" /></p>
         </form>';
   $template->footer();
 }
@@ -1272,6 +1684,8 @@
 function page_Special_Memberlist()
 {
   global $db, $session, $paths, $template, $plugins; // Common objects
+  global $lang;
+  
   $template->header();
   
   $startletters = 'abcdefghijklmnopqrstuvwxyz';
@@ -1362,16 +1776,16 @@
                    <a href="' . makeUrlNS('Special', 'Memberlist', $finduser_url . 'letter=' . $startletter . '&sort=uid&orderby=' . $sortorders['uid'], true) . '">#</a>
                  </th>
                  <th>
-                   <a href="' . makeUrlNS('Special', 'Memberlist', $finduser_url . 'letter=' . $startletter . '&sort=username&orderby=' . $sortorders['username'], true) . '">Username</a>
+                   <a href="' . makeUrlNS('Special', 'Memberlist', $finduser_url . 'letter=' . $startletter . '&sort=username&orderby=' . $sortorders['username'], true) . '">' . $lang->get('userfuncs_ml_column_username') . '</a>
                  </th>
                  <th>
-                   Title
+                   ' . $lang->get('userfuncs_ml_column_userlevel') . '
                  </th>
                  <th>
-                   <a href="' . makeUrlNS('Special', 'Memberlist', $finduser_url . 'letter=' . $startletter . '&sort=email&orderby=' . $sortorders['email'], true) . '">E-mail</a>
+                   <a href="' . makeUrlNS('Special', 'Memberlist', $finduser_url . 'letter=' . $startletter . '&sort=email&orderby=' . $sortorders['email'], true) . '">' . $lang->get('userfuncs_ml_column_email') . '</a>
                  </th>
                  <th>
-                   <a href="' . makeUrlNS('Special', 'Memberlist', $finduser_url . 'letter=' . $startletter . '&sort=regist&orderby=' . $sortorders['regist'], true) . '">Registered</a>
+                   <a href="' . makeUrlNS('Special', 'Memberlist', $finduser_url . 'letter=' . $startletter . '&sort=regist&orderby=' . $sortorders['regist'], true) . '">' . $lang->get('userfuncs_ml_column_regtime') . '</a>
                  </th>
                </tr>';
                
@@ -1385,8 +1799,16 @@
   
   if ( !empty($finduser_url) )
   {
-    $s = ( $num_rows == 1 ) ? '' : 'es';
-    echo "<h3 style='float: left;'>Search returned $num_rows match$s</h3>";
+    switch ( $num_rows )
+    {
+      case 0:
+        $str = $lang->get('userfuncs_ml_msg_matches_zero'); break;
+      case 1:
+        $str = $lang->get('userfuncs_ml_msg_matches_one'); break;
+      default:
+        $str = $lang->get('userfuncs_ml_msg_matches', array('matches' => $num_rows)); break;
+    }
+    echo "<h3>$str</h3>";
   }
   
   // main selector
@@ -1425,14 +1847,16 @@
                 <form action="' . makeUrlNS('Special', 'Memberlist') . '" method="get" onsubmit="if ( !submitAuthorized ) return false;">'
                . ( urlSeparator == '&' ? '<input type="hidden" name="title" value="' . htmlspecialchars( $paths->page ) . '" />' : '' )
                . ( $session->sid_super ? '<input type="hidden" name="auth"  value="' . $session->sid_super . '" />' : '')
-               . '<p>Find a member: ' . $template->username_field('finduser') . ' <input type="submit" value="Go" /><br /><small>You may use the following wildcards: * to match multiple characters, ? to match a single character.</small></p>'
+               . '<p>' . $lang->get('userfuncs_ml_lbl_finduser') . ' ' . $template->username_field('finduser') . ' <input type="submit" value="' . $lang->get('userfuncs_ml_btn_go') . '" /><br />
+                  <small>' . $lang->get('userfuncs_ml_tip_wildcard') . '</small></p>'
                . '</form>
                </div>'                                                                                                // Footer (printed after rows)
           );
   
   if ( $num_rows < 1 )
   {
-    echo ( isset($_GET['finduser']) ) ? '<p>Sorry - no users that matched your query could be found. Please try some different search terms.</p>' : '<p>Sorry - no users with usernames that start with that letter could be found.</p>';
+    echo ( isset($_GET['finduser']) ) ? '<p>' . $lang->get('userfuncs_ml_err_nousers_find') . '</p>' :
+                                        '<p>' . $lang->get('userfuncs_ml_err_nousers') . '</p>';
   }
   else
   {
@@ -1452,37 +1876,41 @@
   function username($username, $row)
   {
     global $db, $session, $paths, $template, $plugins; // Common objects
+    global $lang;
+    
     $userpage = $paths->nslist['User'] . sanitize_page_id($username);
-    $class = ( isPage($userpage) ) ? ' title="Click to view this user\'s userpage"' : ' class="wikilink-nonexistent" title="This user hasn\'t created a userpage yet, but you can still view profile details by clicking this link."';
+    $class = ( isPage($userpage) ) ? ' title="' . $lang->get('userfuncs_ml_tip_userpage') . '"' : ' class="wikilink-nonexistent" title="' . $lang->get('userfuncs_ml_tip_nouserpage') . '"';
     $anchor = '<a href="' . makeUrlNS('User', sanitize_page_id($username)) . '"' . $class . '>' . htmlspecialchars($username) . '</a>';
     if ( $session->user_level >= USER_LEVEL_ADMIN )
     {
       $anchor .= ' <small>- <a href="' . makeUrlNS('Special', 'Administration', 'module=' . $paths->nslist['Admin'] . 'UserManager&src=get&username=' . urlencode($username), true) . '"
-                               onclick="ajaxAdminUser(\'' . addslashes(htmlspecialchars($username)) . '\'); return false;">Administer user</a></small>';
+                               onclick="ajaxAdminUser(\'' . addslashes(htmlspecialchars($username)) . '\'); return false;">' . $lang->get('userfuncs_ml_btn_adminuser') . '</a></small>';
     }
     return $anchor;
   }
   function user_level($level, $row)
   {
     global $db, $session, $paths, $template, $plugins; // Common objects
+    global $lang;
     switch ( $level )
     {
       case USER_LEVEL_GUEST:
-        $s_level = 'Guest'; break;
+        $s_level = $lang->get('userfuncs_ml_level_guest'); break;
       case USER_LEVEL_MEMBER:
       case USER_LEVEL_CHPREF:
-        $s_level = 'Member'; break;
+        $s_level = $lang->get('userfuncs_ml_level_member'); break;
       case USER_LEVEL_MOD:
-        $s_level = 'Moderator'; break;
+        $s_level = $lang->get('userfuncs_ml_level_mod'); break;
       case USER_LEVEL_ADMIN:
-        $s_level = 'Site administrator'; break;
+        $s_level = $lang->get('userfuncs_ml_level_admin'); break;
       default:
-        $s_level = 'Unknown (level ' . $level . ')';
+        $s_level = $lang->get('userfuncs_ml_level_unknown', array( 'level' => $level ));
     }
     return $s_level;
   }
   function email($addy, $row)
   {
+    global $lang;
     if ( $row['email_public'] == '1' )
     {
       global $email;
@@ -1491,7 +1919,7 @@
     }
     else
     {
-      return '<small>&lt;Non-public&gt;</small>';
+      return '<small>&lt;' . $lang->get('userfuncs_ml_email_nonpublic') . '&gt;</small>';
     }
   }
   /**
@@ -1502,35 +1930,36 @@
   
   function format_date($time)
   {
-    // Our formattting string to pass to date()
+    global $lang;
+    // Our formattting string to pass to enano_date()
     // This should not include minute/second info, only today's date in whatever format suits your fancy
     $formatstring = 'F j, Y';
     // Today's date
-    $today = date($formatstring);
+    $today = enano_date($formatstring);
     // Yesterday's date
-    $yesterday = date($formatstring, (time() - (24*60*60)));
+    $yesterday = enano_date($formatstring, (time() - (24*60*60)));
     // Date on the input
-    $then = date($formatstring, $time);
+    $then = enano_date($formatstring, $time);
     // "X days ago" logic
     for ( $i = 2; $i <= 6; $i++ )
     {
       // hours_in_day * minutes_in_hour * seconds_in_minute * num_days
       $offset = 24 * 60 * 60 * $i;
-      $days_ago = date($formatstring, (time() - $offset));
+      $days_ago = enano_date($formatstring, (time() - $offset));
       // so does the input timestamp match the date from $i days ago?
       if ( $then == $days_ago )
       {
         // yes, return $i
-        return "$i days ago";
+        return $lang->get('userfuncs_ml_date_daysago', array('days_ago' => $i));
       }
     }
     // either yesterday, today, or before 6 days ago
     switch($then)
     {
       case $today:
-        return 'Today';
+        return $lang->get('userfuncs_ml_date_today');
       case $yesterday:
-        return 'Yesterday';
+        return $lang->get('userfuncs_ml_date_yesterday');
       default:
         return $then;
     }
@@ -1549,4 +1978,30 @@
   }
 }
 
+function page_Special_LangExportJSON()
+{
+  global $db, $session, $paths, $template, $plugins; // Common objects
+  global $lang;
+  
+  $lang_id = ( $x = $paths->getParam(0) ) ? intval($x) : $lang->lang_id;
+  
+  if ( $lang->lang_id == $lang_id )
+    $lang_local =& $lang;
+  else
+    $lang_local = new Language($lang_id);
+  
+  
+  $timestamp = enano_date('D, j M Y H:i:s T', $lang_local->lang_timestamp);
+  header("Last-Modified: $timestamp");
+  header("Date: $timestamp");
+  header('Content-type: text/javascript');
+  
+  $lang_local->fetch();
+  echo "if ( typeof(enano_lang) != 'object' )
+  var enano_lang = new Object();
+
+enano_lang[{$lang->lang_id}] = " . enano_json_encode($lang_local->strings) . ";";
+  
+}
+
 ?>
\ No newline at end of file
--- a/plugins/SpecialUserPrefs.php	Fri Feb 22 12:46:51 2008 -0500
+++ b/plugins/SpecialUserPrefs.php	Fri Feb 22 12:51:53 2008 -0500
@@ -1,16 +1,16 @@
 <?php
 /*
-Plugin Name: User control panel
+Plugin Name: plugin_specialuserprefs_title
 Plugin URI: http://enanocms.org/
-Description: Provides the page Special:Preferences.
+Description: plugin_specialuserprefs_desc
 Author: Dan Fuhry
-Version: 1.0.3
+Version: 1.1.1
 Author URI: http://enanocms.org/
 */
 
 /*
  * Enano - an open-source CMS capable of wiki functions, Drupal-like sidebar blocks, and everything in between
- * Version 1.0.3
+ * Version 1.1.2 (Caoineag alpha 2)
  * Copyright (C) 2006-2007 Dan Fuhry
  *
  * This program is Free Software; you can redistribute it and/or modify it under the terms of the GNU General Public License
@@ -46,6 +46,7 @@
 function userprefs_jbox_setup(&$button, &$tb, &$menubtn)
 {
   global $db, $session, $paths, $template, $plugins; // Common objects
+  global $lang;
   
   if ( $paths->namespace != 'Special' || $paths->page_id != 'Preferences' )
     return false;
@@ -54,7 +55,7 @@
   $template->toolbar_menu = '';
   
   $button->assign_vars(array(
-      'TEXT' => 'list of registered members',
+      'TEXT' => $lang->get('usercp_btn_memberlist'),
       'FLAGS' => '',
       'PARENTFLAGS' => '',
       'HREF' => makeUrlNS('Special', 'Memberlist')
@@ -67,17 +68,28 @@
 {
   global $userprefs_menu;
   global $userprefs_menu_links;
+  global $lang;
   
   $html = '';
   $quot = '"';
   
   foreach ( $userprefs_menu as $section => $buttons )
   {
-    $html .= ( isset($userprefs_menu_links[$section]) ) ? "<a href={$quot}{$userprefs_menu_links[$section]}{$quot}>{$section}</a>\n        " : "<a>{$section}</a>\n        ";
+    $section_name = $section;
+    if ( preg_match('/^[a-z]+_[a-z_]+$/', $section) )
+    {
+      $section_name = $lang->get($section_name);
+    }
+    $html .= ( isset($userprefs_menu_links[$section]) ) ? "<a href={$quot}{$userprefs_menu_links[$section]}{$quot}>{$section_name}</a>\n        " : "<a>{$section_name}</a>\n        ";
     $html .= "<ul>\n          ";
     foreach ( $buttons as $button )
     {
-      $html .= "  <li><a href={$quot}{$button['link']}{$quot}>{$button['text']}</a></li>\n          ";
+      $buttontext = $button['text'];
+      if ( preg_match('/^[a-z]+_[a-z_]+$/', $buttontext) )
+      {
+        $buttontext = $lang->get($buttontext);
+      }
+      $html .= "  <li><a href={$quot}{$button['link']}{$quot}>{$buttontext}</a></li>\n          ";
     }
     $html .= "</ul>\n        ";
   }
@@ -100,14 +112,29 @@
   global $db, $session, $paths, $template, $plugins; // Common objects
   global $userprefs_menu_links;
   
-  userprefs_menu_add('Profile/membership', 'Edit e-mail address and password', makeUrlNS('Special', 'Preferences/EmailPassword') . '" onclick="ajaxLoginNavTo(\'Special\', \'Preferences/EmailPassword\', '.USER_LEVEL_CHPREF.'); return false;');
-  userprefs_menu_add('Profile/membership', 'Edit signature', makeUrlNS('Special', 'Preferences/Signature'));
-  userprefs_menu_add('Profile/membership', 'Edit public profile', makeUrlNS('Special', 'Preferences/Profile'));
-  userprefs_menu_add('Private messages', 'Inbox', makeUrlNS('Special', 'PrivateMessages/Folder/Inbox'));
-  userprefs_menu_add('Private messages', 'Outbox', makeUrlNS('Special', 'PrivateMessages/Folder/Outbox'));
-  userprefs_menu_add('Private messages', 'Sent items', makeUrlNS('Special', 'PrivateMessages/Folder/Sent'));
-  userprefs_menu_add('Private messages', 'Drafts', makeUrlNS('Special', 'PrivateMessages/Folder/Drafts'));
-  userprefs_menu_add('Private messages', 'Archive', makeUrlNS('Special', 'PrivateMessages/Folder/Archive'));
+  userprefs_menu_add('usercp_sec_profile', 'usercp_sec_profile_emailpassword', makeUrlNS('Special', 'Preferences/EmailPassword') . '" onclick="ajaxLoginNavTo(\'Special\', \'Preferences/EmailPassword\', '.USER_LEVEL_CHPREF.'); return false;');
+  userprefs_menu_add('usercp_sec_profile', 'usercp_sec_profile_signature', makeUrlNS('Special', 'Preferences/Signature'));
+  userprefs_menu_add('usercp_sec_profile', 'usercp_sec_profile_publicinfo', makeUrlNS('Special', 'Preferences/Profile'));
+  userprefs_menu_add('usercp_sec_profile', 'usercp_sec_profile_usergroups', makeUrlNS('Special', 'Usergroups'));
+  if ( getConfig('avatar_enable') == '1' )
+  {
+    userprefs_menu_add('usercp_sec_profile', 'usercp_sec_profile_avatar', makeUrlNS('Special', 'Preferences/Avatar'));
+  }
+  userprefs_menu_add('usercp_sec_pm', 'usercp_sec_pm_inbox', makeUrlNS('Special', 'PrivateMessages/Folder/Inbox'));
+  userprefs_menu_add('usercp_sec_pm', 'usercp_sec_pm_outbox', makeUrlNS('Special', 'PrivateMessages/Folder/Outbox'));
+  userprefs_menu_add('usercp_sec_pm', 'usercp_sec_pm_sent', makeUrlNS('Special', 'PrivateMessages/Folder/Sent'));
+  userprefs_menu_add('usercp_sec_pm', 'usercp_sec_pm_drafts', makeUrlNS('Special', 'PrivateMessages/Folder/Drafts'));
+  userprefs_menu_add('usercp_sec_pm', 'usercp_sec_pm_archive', makeUrlNS('Special', 'PrivateMessages/Folder/Archive'));
+  
+  /*
+  // Reserved for Enano's Next Big Innovation.(TM)
+  userprefs_menu_add('Private messages', 'Inbox', makeUrlNS('Special',      'Private_Messages#folder:inbox'));
+  userprefs_menu_add('Private messages', 'Starred', makeUrlNS('Special',     'Private_Messages#folder:starred'));
+  userprefs_menu_add('Private messages', 'Sent items', makeUrlNS('Special', 'Private_Messages#folder:sent'));
+  userprefs_menu_add('Private messages', 'Drafts', makeUrlNS('Special',     'Private_Messages#folder:drafts'));
+  userprefs_menu_add('Private messages', 'Archive', makeUrlNS('Special',    'Private_Messages#folder:archive'));
+  userprefs_menu_add('Private messages', 'Trash', makeUrlNS('Special',    'Private_Messages#folder:trash'));
+  */
   
   $userprefs_menu_links['Profile/membership'] = makeUrlNS('Special', 'Preferences');
   $userprefs_menu_links['Private messages']  = makeUrlNS('Special', 'PrivateMessages');
@@ -119,11 +146,13 @@
   }
 }
 
-$plugins->attachHook('session_started', 'userprefs_menu_init();');
+$plugins->attachHook('common_post', 'userprefs_menu_init();');
 
 function page_Special_Preferences()
 {
   global $db, $session, $paths, $template, $plugins; // Common objects
+  global $lang;
+  global $timezone;
   
   // We need a login to continue
   if ( !$session->user_logged_in )
@@ -171,7 +200,7 @@
             case 'foo':
               if ( $_POST['newemail'] != $_POST['newemail_conf'] )
               {
-                $errors .= '<div class="error-box">The e-mail addresses you entered did not match.</div>';
+                $errors .= '<div class="error-box">' . $lang->get('usercp_emailpassword_err_email_no_match') . '</div>';
                 break;
               }
           }
@@ -187,9 +216,9 @@
           $result = $session->update_user($session->user_id, false, $old_pass, false, $new_email);
           if ( $result != 'success' )
           {
-            $message = '<p>The following errors were encountered while saving your e-mail address:</p>';
+            $message = '<p>' . $lang->get('usercp_emailpassword_err_list') . '</p>';
             $message .= '<ul><li>' . implode("</li>\n<li>", $result) . '</li></ul>';
-            die_friendly('Error updating e-mail address', $message);
+            die_friendly($lang->get('usercp_emailpassword_err_title'), $message);
           }
           $email_changed = true;
         }
@@ -213,16 +242,15 @@
           if ( strlen($newpass) > 0 )
           {
             if ( defined('ENANO_DEMO_MODE') )
-              $errors .= '<div class="error-box" style="margin: 0 0 10px 0;">You can\'t change your password in demo mode.</div>';
+              $errors .= '<div class="error-box" style="margin: 0 0 10px 0;">' . $lang->get('usercp_emailpassword_err_demo') . '</div>';
             // Perform checks
             if ( strlen($newpass) < 6 )
-              $errors .= '<div class="error-box" style="margin: 0 0 10px 0;">Password must be at least 6 characters. You hacked my script, darn you!</div>';
+              $errors .= '<div class="error-box" style="margin: 0 0 10px 0;">' . $lang->get('usercp_emailpassword_err_password_too_short') . '</div>';
             if ( getConfig('pw_strength_enable') == '1' )
             {
               $score_inp = password_score($newpass);
-              $score_min = intval( getConfig('pw_strength_minimum') );
               if ( $score_inp < $score_min )
-                $errors .= '<div class="error-box" style="margin: 0 0 10px 0;">Your password did not meet the complexity score requirement for this site. Your password scored '. $score_inp .', while a score of at least '. $score_min .' is needed.</div>';
+                $errors .= '<div class="error-box" style="margin: 0 0 10px 0;">' . $lang->get('usercp_emailpassword_err_password_too_weak', array('score' => $score_inp)) . '</div>';
             }
             // Encrypt new password
             if ( empty($errors) )
@@ -239,15 +267,15 @@
               {
                 if ( getConfig('account_activation') == 'user' )
                 {
-                  redirect(makeUrl(getConfig('main_page')), 'Profile changed', 'Your password and e-mail address have been changed. Since e-mail activation is required on this site, you will need to re-activate your account to continue. An e-mail has been sent to the new e-mail address with an activation link. You must click that link in order to log in again.', 19);
+                  redirect(makeUrl(getConfig('main_page')), $lang->get('usercp_emailpassword_msg_profile_success'), $lang->get('usercp_emailpassword_msg_need_activ_user'), 20);
                 }
                 else if ( getConfig('account_activation') == 'admin' )
                 {
-                  redirect(makeUrl(getConfig('main_page')), 'Profile changed', 'Your password and e-mail address have been changed. Since administrative activation is requires on this site, a request has been sent to the administrators to activate your account for you. You will not be able to use your account until it is activated by an administrator.', 19);
+                  redirect(makeUrl(getConfig('main_page')), $lang->get('usercp_emailpassword_msg_profile_success'), $lang->get('usercp_emailpassword_msg_need_activ_admin'), 20);
                 }
               }
               $session->login_without_crypto($session->username, $newpass);
-              redirect(makeUrlNS('Special', 'Preferences'), 'Password changed', 'Your password has been changed, and you will now be redirected back to the user control panel.', 4);
+              redirect(makeUrlNS('Special', 'Preferences'), $lang->get('usercp_emailpassword_msg_pass_success'), $lang->get('usercp_emailpassword_msg_password_changed'), 5);
             }
           }
         }
@@ -259,37 +287,39 @@
               $pass = $_POST['newpass'];
               if ( $pass != $_POST['newpass_conf'] )
               {
-                $errors .= '<div class="error-box">The passwords you entered did not match</div>';
+                $errors .= '<div class="error-box">' . $lang->get('usercp_emailpassword_err_password_no_match') . '</div>';
                 break;
               }
               
+              $session->logout();
               if ( $email_changed )
               {
                 if ( getConfig('account_activation') == 'user' )
                 {
-                  redirect(makeUrl(getConfig('main_page')), 'Profile changed', 'Your e-mail address has been changed. Since e-mail activation is required on this site, you will need to re-activate your account to continue. An e-mail has been sent to the new e-mail address with an activation link. You must click that link in order to log in again.', 19);
+                  redirect(makeUrl(getConfig('main_page')), $lang->get('usercp_emailpassword_msg_profile_success'), $lang->get('usercp_emailpassword_msg_need_activ_user'), 20);
                 }
                 else if ( getConfig('account_activation') == 'admin' )
                 {
-                  redirect(makeUrl(getConfig('main_page')), 'Profile changed', 'Your e-mail address has been changed. Since administrative activation is requires on this site, a request has been sent to the administrators to activate your account for you. You will not be able to use your account until it is activated by an administrator.', 19);
+                  redirect(makeUrl(getConfig('main_page')), $lang->get('usercp_emailpassword_msg_profile_success'), $lang->get('usercp_emailpassword_msg_need_activ_admin'), 20);
                 }
-                else
-                {
-                  redirect(makeUrlNS('Special', 'Preferences'), 'Password changed', 'Your e-mail address has been changed, and you will now be redirected back to the user control panel.', 4);
-                }
+              }
+              else
+              {
+                $session->login_without_crypto($session->username, $newpass);
+                redirect(makeUrlNS('Special', 'Preferences'), $lang->get('usercp_emailpassword_msg_pass_success'), $lang->get('usercp_emailpassword_msg_password_changed'), 5);
               }
               
               return;
           }
         }
       }
-      $template->tpl_strings['PAGE_NAME'] = 'Change E-mail Address or Password';
+      $template->tpl_strings['PAGE_NAME'] = $lang->get('usercp_emailpassword_title');
       break;
     case 'Signature':
-      $template->tpl_strings['PAGE_NAME'] = 'Editing signature';
+      $template->tpl_strings['PAGE_NAME'] = $lang->get('usercp_signature_title');
       break;
     case 'Profile':
-      $template->tpl_strings['PAGE_NAME'] = 'Editing public profile';
+      $template->tpl_strings['PAGE_NAME'] = $lang->get('usercp_publicinfo_title');
       break;
   }
   
@@ -306,13 +336,14 @@
       global $email;
       $userpage_id = $paths->nslist['User'] . sanitize_page_id($session->username);
       $userpage_exists = ( isPage($userpage_id) ) ? '' : ' class="wikilink-nonexistent"';
-      $user_page = '<a href="' . makeUrlNS('User', sanitize_page_id($session->username)) . '"' . $userpage_exists . '>user page</a> <sup>(<a href="' . makeUrlNS('User', str_replace(' ', '_', $session->username)) . '#do:comments">comments</a>)</sup>';
-      $site_admin = $email->encryptEmail(getConfig('contact_email'), '', '', 'administrator');
-      $make_one_now = '<a href="' . makeUrlNS('User', sanitize_page_id($session->username)) . '">make one now</a>';
-      echo "<h3 style='margin-top: 0;'>$session->username, welcome to your control panel</h3>";
-      echo "<p>Here you can make changes to your profile, view statistics on yourself on this site, and set your preferences.</p>
-            <p>Your $user_page is your free writing space. You can use it to tell the other members of this site a little bit about yourself. If you haven't already made a user page, why not $make_one_now?</p>
-            <p>Use the menu at the top to navigate around. If you have any questions, you may contact the $site_admin.";
+      $user_page = makeUrlNS('User', sanitize_page_id($session->username));
+      $site_admin = $email->encryptEmail(getConfig('contact_email'), '', '', $lang->get('usercp_intro_para3_admin_link'));
+      
+      echo '<h3 style="margin-top: 0;">' . $lang->get('usercp_intro_heading_main', array('username' => $session->username)) . '</h3>';
+      
+      echo '<p>' . $lang->get('usercp_intro_para1') . '</p>
+            <p>' . $lang->get('usercp_intro_para2', array('userpage_link' => $user_page)) . '</p>
+            <p>' . $lang->get('usercp_intro_para3', array('admin_contact_link' => $site_admin)) . '</p>';
       break;
     case 'EmailPassword':
       
@@ -328,30 +359,30 @@
       $pubkey = $session->rijndael_genkey();
       
       echo '<fieldset>
-        <legend>Change password</legend>
-        Type a new password:<br />
+        <legend>' . $lang->get('usercp_emailpassword_grp_chpasswd') . '</legend>
+        ' . $lang->get('usercp_emailpassword_field_newpass') . '<br />
           <input type="password" name="newpass" size="30" tabindex="1" ' . ( getConfig('pw_strength_enable') == '1' ? 'onkeyup="password_score_field(this);" ' : '' ) . '/>' . ( getConfig('pw_strength_enable') == '1' ? '<span class="password-checker" style="font-weight: bold; color: #aaaaaa;"> Loading...</span>' : '' ) . '
         <br />
         <br />
-        Type the password again to confirm:<br />
+        ' . $lang->get('usercp_emailpassword_field_newpass_confirm') . '<br />
         <input type="password" name="newpass_conf" size="30" tabindex="2" />
         ' . ( getConfig('pw_strength_enable') == '1' ? '<br /><br /><div id="pwmeter"></div>
-        <small>Your password needs to score at least <b>'.getConfig('pw_strength_minimum').'</b> in order to be accepted.</small>' : '' ) . '
+        <small>' . $lang->get('usercp_emailpassword_msg_password_min_score') . '</small>' : '' ) . '
       </fieldset><br />
       <fieldset>
-        <legend>Change e-mail address</legend>
-        New e-mail address:<br />
+        <legend>' . $lang->get('usercp_emailpassword_grp_chemail') . '</legend>
+        ' . $lang->get('usercp_emailpassword_field_newemail') . '<br />
           <input type="text" value="' . ( isset($_POST['newemail']) ? htmlspecialchars($_POST['newemail']) : '' ) . '" name="newemail" size="30" tabindex="3" />
         <br />
         <br />
-        Confirm e-mail address:<br />
+        ' . $lang->get('usercp_emailpassword_field_newemail_confirm') . '<br />
           <input type="text" value="' . ( isset($_POST['newemail']) ? htmlspecialchars($_POST['newemail']) : '' ) . '" name="newemail_conf" size="30" tabindex="4" />
       </fieldset>
       <input type="hidden" name="use_crypt" value="no" />
       <input type="hidden" name="crypt_key" value="' . $pubkey . '" />
       <input type="hidden" name="crypt_data" value="" />
       <br />
-      <div style="text-align: right;"><input type="submit" name="submit" value="Save Changes" tabindex="5" /></div>';
+      <div style="text-align: right;"><input type="submit" name="submit" value="' . $lang->get('etc_save_changes') . '" tabindex="5" /></div>';
       
       echo '</form>';
       
@@ -386,6 +417,20 @@
           var frm = document.forms.empwform;
           if ( frm.newpass.value.length < 1 )
             return true;
+          
+          pass1 = frm.newpass.value;
+          pass2 = frm.newpass_conf.value;
+          if ( pass1 != pass2 )
+          {
+            alert($lang.get('usercp_emailpassword_err_password_no_match'));
+            return false;
+          }
+          if ( pass1.length < 6 && pass1.length > 0 )
+          {
+            alert($lang.get('usercp_emailpassword_err_password_too_short'));
+            return false;
+          }
+          
           if(aes_testpassed)
           {
             frm.use_crypt.value = 'yes';
@@ -398,21 +443,6 @@
               len = ( typeof cryptkey == 'string' || typeof cryptkey == 'object' ) ? '\nLen: '+cryptkey.length : '';
               alert('The key is messed up\nType: '+typeof(cryptkey)+len);
             }
-          }
-          pass1 = frm.newpass.value;
-          pass2 = frm.newpass_conf.value;
-          if ( pass1 != pass2 )
-          {
-            alert('The passwords you entered do not match.');
-            return false;
-          }
-          if ( pass1.length < 6 && pass1.length > 0 )
-          {
-            alert('The new password must be 6 characters or greater in length.');
-            return false;
-          }
-          if(aes_testpassed)
-          {
             pass = frm.newpass.value;
             pass = stringToByteArray(pass);
             cryptstring = rijndaelEncrypt(pass, cryptkey, 'ECB');
@@ -441,11 +471,11 @@
         if ( !$q )
           $db->_die();
         $session->signature = $sig;
-        echo '<div class="info-box" style="margin: 0 0 10px 0;">Your signature has been saved.</div>';
+        echo '<div class="info-box" style="margin: 0 0 10px 0;">' . $lang->get('usercp_signature_msg_saved') . '</div>';
       }
       echo '<form action="'.makeUrl($paths->fullpage).'" method="post">';
       echo $template->tinymce_textarea('new_sig', htmlspecialchars($session->signature));
-      echo '<input type="submit" value="Save signature" />';
+      echo '<input type="submit" value="' . $lang->get('usercp_signature_btn_save') . '" />';
       echo '</form>';
       break;
     case "Profile":
@@ -454,6 +484,9 @@
         $real_name = htmlspecialchars($_POST['real_name']);
         $real_name = $db->escape($real_name);
         
+        $timezone = intval($_POST['timezone']);
+        $tz_local = $timezone + 1440;
+        
         $imaddr_aim = htmlspecialchars($_POST['imaddr_aim']);
         $imaddr_aim = $db->escape($imaddr_aim);
         
@@ -507,7 +540,7 @@
         $session->user_extra['user_hobbies'] = $hobbies;
         $session->user_extra['email_public'] = intval($email_public);
         
-        $q = $db->sql_query('UPDATE '.table_prefix."users SET real_name='$real_name' WHERE user_id=$session->user_id;");
+        $q = $db->sql_query('UPDATE '.table_prefix."users SET real_name='$real_name', user_timezone = $tz_local WHERE user_id=$session->user_id;");
         if ( !$q )
           $db->_die();
         
@@ -519,74 +552,144 @@
         if ( !$q )
           $db->_die();
         
-        echo '<div class="info-box" style="margin: 0 0 10px 0;">Your profile has been updated.</div>';
+        // verify language id
+        $lang_id = strval(intval($_POST['lang_id']));
+        $q = $db->sql_query('SELECT 1 FROM ' . table_prefix . 'language WHERE lang_id = ' . $lang_id . ';');
+        if ( !$q )
+          $db->_die();
+        
+        if ( $db->numrows() > 0 )
+        {
+          $db->free_result();
+          
+          // unload / reload $lang, this verifies that the selected language works
+          unset($GLOBALS['lang']);
+          unset($lang);
+          $lang_id = intval($lang_id);
+          $GLOBALS['lang'] = new Language($lang_id);
+          global $lang;
+          
+          $q = $db->sql_query('UPDATE ' . table_prefix . 'users SET user_lang = ' . $lang_id . " WHERE user_id = {$session->user_id};");
+          if ( !$q )
+            $db->_die();
+        }
+        else
+        {
+          $db->free_result();
+        }
+        
+        echo '<div class="info-box" style="margin: 0 0 10px 0;">' . $lang->get('usercp_publicinfo_msg_save_success') . '</div>';
       }
+      
+      $lang_box = '<select name="lang_id">';
+      $q = $db->sql_query('SELECT lang_id, lang_name_native FROM ' . table_prefix . "language;");
+      if ( !$q )
+        $db->_die();
+      
+      while ( $row = $db->fetchrow_num() )
+      {
+        list($lang_id, $lang_name) = $row;
+        $lang_name = htmlspecialchars($lang_name);
+        $selected = ( $lang->lang_id == $lang_id ) ? ' selected="selected"' : '';
+        $lang_box .= "<option value=\"$lang_id\"$selected>$lang_name</option>";
+      }
+      
+      $lang_box .= '</select>';
+      
+      $tz_select = '<select name="timezone">';
+      $tz_list = $lang->get('tz_list');
+      try
+      {
+        $tz_list = enano_json_decode($tz_list);
+      }
+      catch(Exception $e)
+      {
+        die("Caught exception decoding timezone data: <pre>$e</pre>");
+      }
+      foreach ( $tz_list as $key => $i )
+      {
+        $i = ($i * 60);
+        $title = $lang->get("tz_title_{$key}");
+        $hrs = $lang->get("tz_hrs_{$key}");
+        $selected = ( $i == $timezone ) ? ' selected="selected"' : '';
+        $tz_select .= "<option value=\"$i\"$selected>$title</option>";
+      }
+      $tz_select .= '</select>';
+      
       echo '<form action="'.makeUrl($paths->fullpage).'" method="post">';
       ?>
       <div class="tblholder">
         <table border="0" cellspacing="1" cellpadding="4">
           <tr>
-            <th colspan="2">Your public profile</th>
+            <th colspan="2"><?php echo $lang->get('usercp_publicinfo_heading_main'); ?></th>
           </tr>
           <tr>
-            <td colspan="2" class="row3">Please note that all of the information you enter here will be <b>publicly viewable.</b> All of the fields on this page are optional and may be left blank if you so desire.</td>
+            <td colspan="2" class="row3"><?php echo $lang->get('usercp_publicinfo_note_optional'); ?></td>
           </tr>
           <tr>
-            <td class="row2" style="width: 50%;">Real name:</td>
+            <td class="row2" style="width: 50%;"><?php echo $lang->get('usercp_publicinfo_field_realname'); ?></td>
             <td class="row1" style="width: 50%;"><input type="text" name="real_name" value="<?php echo $session->real_name; ?>" size="30" /></td>
           </tr>
           <tr>
-            <td class="row2">Change theme:</td>
-            <td class="row1">If you don't like the look of the site, need a visual break, or are just curious, we might have some different themes for you to try out! <a href="<?php echo makeUrlNS('Special', 'ChangeStyle/' . $paths->page); ?>" onclick="ajaxChangeStyle(); return false;">Change my theme...</a></td>
+            <td class="row2"><?php echo $lang->get('usercp_publicinfo_field_language') . '<br /><small>' . $lang->get('usercp_publicinfo_field_language_hint') . '</small>'; ?></td>
+            <td class="row1"><?php echo $lang_box; ?></td>
+          </tr>
+          <tr>
+            <td class="row2"><?php echo $lang->get('usercp_publicinfo_field_changetheme_title'); ?></td>
+            <td class="row1"><?php echo $lang->get('usercp_publicinfo_field_changetheme_hint'); ?> <a href="<?php echo makeUrlNS('Special', 'ChangeStyle/' . $paths->page); ?>" onclick="ajaxChangeStyle(); return false;"><?php echo $lang->get('usercp_publicinfo_field_changetheme'); ?></a></td>
+          </tr>
+          <tr>
+            <td class="row2"><?php echo $lang->get('usercp_publicinfo_field_timezone'); ?><br /><small><?php echo $lang->get('usercp_publicinfo_field_timezone_hint'); ?></small></td>
+            <td class="row1"><?php echo $tz_select; ?></td>
           </tr>
           <tr>
             <th class="subhead" colspan="2">
-              Instant messenger contact information
+              <?php echo $lang->get('usercp_publicinfo_th_im'); ?>
             </th>
           <tr>
-            <td class="row2" style="width: 50%;">AIM handle:</td>
+            <td class="row2" style="width: 50%;"><?php echo $lang->get('usercp_publicinfo_field_aim'); ?></td>
             <td class="row1" style="width: 50%;"><input type="text" name="imaddr_aim" value="<?php echo $session->user_extra['user_aim']; ?>" size="30" /></td>
           </tr>
           <tr>
-            <td class="row2" style="width: 50%;"><acronym title="Windows&trade; Live Messenger">WLM</acronym> handle:<br /><small>If you don't specify the domain (@whatever.com), "@hotmail.com" will be assumed.</small></td>
+            <td class="row2" style="width: 50%;"><?php echo $lang->get('usercp_publicinfo_field_wlm'); ?></td>
             <td class="row1" style="width: 50%;"><input type="text" name="imaddr_msn" value="<?php echo $session->user_extra['user_msn']; ?>" size="30" /></td>
           </tr>
           <tr>
-            <td class="row2" style="width: 50%;">Yahoo! IM handle:</td>
+            <td class="row2" style="width: 50%;"><?php echo $lang->get('usercp_publicinfo_field_yim'); ?></td>
             <td class="row1" style="width: 50%;"><input type="text" name="imaddr_yahoo" value="<?php echo $session->user_extra['user_yahoo']; ?>" size="30" /></td>
           </tr>
           <tr>
-            <td class="row2" style="width: 50%;">Jabber/XMPP handle:</td>
+            <td class="row2" style="width: 50%;"><?php echo $lang->get('usercp_publicinfo_field_xmpp'); ?></td>
             <td class="row1" style="width: 50%;"><input type="text" name="imaddr_xmpp" value="<?php echo $session->user_extra['user_xmpp']; ?>" size="30" /></td>
           </tr>
           <tr>
             <th class="subhead" colspan="2">
-              Extra contact information
+              <?php echo $lang->get('usercp_publicinfo_th_contact'); ?>
             </th>
           </tr>
           <tr>
-            <td class="row2" style="width: 50%;">Your homepage:<br /><small>Please remember the http:// prefix.</small></td>
+            <td class="row2" style="width: 50%;"><?php echo $lang->get('usercp_publicinfo_field_homepage'); ?></td>
             <td class="row1" style="width: 50%;"><input type="text" name="homepage" value="<?php echo $session->user_extra['user_homepage']; ?>" size="30" /></td>
           </tr>
           <tr>
-            <td class="row2" style="width: 50%;">Your location:</td>
+            <td class="row2" style="width: 50%;"><?php echo $lang->get('usercp_publicinfo_field_location'); ?></td>
             <td class="row1" style="width: 50%;"><input type="text" name="location" value="<?php echo $session->user_extra['user_location']; ?>" size="30" /></td>
           </tr>
           <tr>
-            <td class="row2" style="width: 50%;">Your job:</td>
+            <td class="row2" style="width: 50%;"><?php echo $lang->get('usercp_publicinfo_field_job'); ?></td>
             <td class="row1" style="width: 50%;"><input type="text" name="occupation" value="<?php echo $session->user_extra['user_job']; ?>" size="30" /></td>
           </tr>
           <tr>
-            <td class="row2" style="width: 50%;">Your hobbies:</td>
+            <td class="row2" style="width: 50%;"><?php echo $lang->get('usercp_publicinfo_field_hobbies'); ?></td>
             <td class="row1" style="width: 50%;"><input type="text" name="hobbies" value="<?php echo $session->user_extra['user_hobbies']; ?>" size="30" /></td>
           </tr>
           <tr>
-            <td class="row2" style="width: 50%;"><label for="chk_email_public">E-mail address is public</label><br /><small>If this is checked, your e-mail address will be displayed on your user page. To protect your address from spambots, your e-mail address will be encrypted.</small></td>
+            <td class="row2" style="width: 50%;"><label for="chk_email_public"><?php echo $lang->get('usercp_publicinfo_field_email_public'); ?></label><br /><small><?php echo $lang->get('usercp_publicinfo_field_email_public_hint'); ?></small></td>
             <td class="row1" style="width: 50%;"><input type="checkbox" id="chk_email_public" name="email_public" <?php if ($session->user_extra['email_public'] == 1) echo 'checked="checked"'; ?> size="30" /></td>
           </tr>
           <tr>
             <th class="subhead" colspan="2">
-              <input type="submit" name="submit" value="Save profile" />
+              <input type="submit" name="submit" value="<?php echo $lang->get('usercp_publicinfo_btn_save'); ?>" />
             </th>
           </tr>
         </table>
@@ -594,6 +697,276 @@
       <?php
       echo '</form>';
       break;
+    case 'Avatar':
+      if ( getConfig('avatar_enable') != '1' )
+      {
+        echo '<div class="error-box"><b>' . $lang->get('usercp_avatar_err_disabled_title') . '</b><br />' . $lang->get('usercp_avatar_err_disabled_body') . '</div>';
+      }
+      
+      // Determine current avatar
+      $q = $db->sql_query('SELECT user_has_avatar, avatar_type FROM ' . table_prefix . 'users WHERE user_id = ' . $session->user_id . ';');
+      if ( !$q )
+        $db->_die('Avatar CP selecting user\'s avatar data');
+      
+      list($has_avi, $avi_type) = $db->fetchrow_num();
+      
+      if ( isset($_POST['submit']) )
+      {
+        $action = ( isset($_POST['avatar_action']) ) ? $_POST['avatar_action'] : 'keep';
+        $avi_path = ENANO_ROOT . '/' . getConfig('avatar_directory') . '/' . $session->user_id . '.' . $avi_type;
+        switch($action)
+        {
+          case 'keep':
+          default:
+            break;
+          case 'remove':
+            if ( $has_avi )
+            {
+              // First switch the avatar off
+              $q = $db->sql_query('UPDATE ' . table_prefix . 'users SET user_has_avatar = 0 WHERE user_id = ' . $session->user_id . ';');
+              if ( !$q )
+                $db->_die('Avatar CP switching user avatar off');
+              
+              if ( @unlink($avi_path) )
+              {
+                echo '<div class="info-box">' . $lang->get('usercp_avatar_delete_success') . '</div>';
+              }
+              $has_avi = 0;
+            }
+            break;
+          case 'set_http':
+          case 'set_file':
+            // Hackish way to preserve the UNIX philosophy of reusing as much code as possible
+            if ( $action == 'set_http' )
+            {
+              // Check if this action is enabled
+              if ( getConfig('avatar_upload_http') !== '1' )
+              {
+                // non-localized, only appears on hack attempt
+                echo '<div class="error-box">Uploads over HTTP are disabled.</div>';
+                break;
+              }
+              // Download the file
+              require_once( ENANO_ROOT . '/includes/http.php' );
+              
+              if ( !preg_match('/^http:\/\/([a-z0-9-\.]+)(:([0-9]+))?\/(.+)$/', $_POST['avatar_http_url'], $match) )
+              {
+                echo '<div class="error-box">' . $lang->get('usercp_avatar_invalid_url') . '</div>';
+                break;
+              }
+              
+              $hostname = $match[1];
+              $uri = '/' . $match[4];
+              $port = ( $match[3] ) ? intval($match[3]) : 80;
+              $max_size = intval(getConfig('avatar_max_size'));
+              
+              // Get temporary file
+              $tempfile = tempnam(false, "enanoavatar_{$session->user_id}");
+              if ( !$tempfile )
+                echo '<div class="error-box">Error getting temp file.</div>';
+              
+              @unlink($tempfile);
+              $request = new Request_HTTP($hostname, $uri, 'GET', $port);
+              $result = $request->write_response_to_file($tempfile, 50, $max_size);
+              if ( !$result || $request->response_code != HTTP_OK )
+              {
+                @unlink($tempfile);
+                echo '<div class="error-box">' . $lang->get('usercp_avatar_bad_write') . '</div>';
+                break;
+              }
+              
+              // Response written. Proceed to validation...
+            }
+            else
+            {
+              // Check if this action is enabled
+              if ( getConfig('avatar_upload_file') !== '1' )
+              {
+                // non-localized, only appears on hack attempt
+                echo '<div class="error-box">Uploads from the browser are disabled.</div>';
+                break;
+              }
+              
+              $max_size = intval(getConfig('avatar_max_size'));
+              
+              $file =& $_FILES['avatar_file'];
+              $tempfile =& $file['tmp_name'];
+              if ( filesize($tempfile) > $max_size )
+              {
+                @unlink($tempfile);
+                echo '<div class="error-box">' . $lang->get('usercp_avatar_file_too_large') . '</div>';
+                break;
+              }
+            }
+            $file_type = get_image_filetype($tempfile);
+            if ( !$file_type )
+            {
+              unlink($tempfile);
+              echo '<div class="error-box">' . $lang->get('usercp_avatar_bad_filetype') . '</div>';
+              break;
+            }
+            
+            $avi_path_new = ENANO_ROOT . '/' . getConfig('avatar_directory') . '/' . $session->user_id . '.' . $file_type;
+            
+            // The file type is good - validate dimensions and animation
+            switch($file_type)
+            {
+              case 'png':
+                $is_animated = is_png_animated($tempfile);
+                $dimensions = png_get_dimensions($tempfile);
+                break;
+              case 'gif':
+                $is_animated = is_gif_animated($tempfile);
+                $dimensions = gif_get_dimensions($tempfile);
+                break;
+              case 'jpg':
+                $is_animated = false;
+                $dimensions = jpg_get_dimensions($tempfile);
+                break;
+              default:
+                echo '<div class="error-box">API mismatch</div>';
+                break 2;
+            }
+            // Did we get invalid size data? If so the image is probably corrupt.
+            if ( !$dimensions )
+            {
+              @unlink($tempfile);
+              echo '<div class="error-box">' . $lang->get('usercp_avatar_corrupt_image') . '</div>';
+              break;
+            }
+            // Is the image animated?
+            if ( $is_animated && getConfig('avatar_enable_anim') !== '1' )
+            {
+              @unlink($tempfile);
+              echo '<div class="error-box">' . $lang->get('usercp_avatar_disallowed_animation') . '</div>';
+              break;
+            }
+            // Check image dimensions
+            list($image_x, $image_y) = $dimensions;
+            $max_x = intval(getConfig('avatar_max_width'));
+            $max_y = intval(getConfig('avatar_max_height'));
+            if ( $image_x > $max_x || $image_y > $max_y )
+            {
+              @unlink($tempfile);
+              echo '<div class="error-box">' . $lang->get('usercp_avatar_too_large') . '</div>';
+              break;
+            }
+            // All good!
+            @unlink($avi_path);
+            if ( rename($tempfile, $avi_path_new) )
+            {
+              $q = $db->sql_query('UPDATE ' . table_prefix . "users SET user_has_avatar = 1, avatar_type = '$file_type' WHERE user_id = {$session->user_id};");
+              if ( !$q )
+                $db->_die('Avatar CP updating users table after successful avatar upload');
+              $has_avi = 1;
+              $avi_type = $file_type;
+              echo '<div class="info-box">' . $lang->get('usercp_avatar_upload_success') . '</div>';
+            }
+            else
+            {
+              echo '<div class="error-box">' . $lang->get('usercp_avatar_move_failed') . '</div>';
+            }
+            break;
+        }
+      }
+      
+      ?>
+      <script type="text/javascript">
+      
+        function avatar_select_field(elParent)
+        {
+          switch(elParent.value)
+          {
+            case 'keep':
+            case 'remove':
+              $('avatar_upload_http').object.style.display = 'none';
+              $('avatar_upload_file').object.style.display = 'none';
+              break;
+            case 'set_http':
+              $('avatar_upload_http').object.style.display = 'block';
+              $('avatar_upload_file').object.style.display = 'none';
+              break;
+            case 'set_file':
+              $('avatar_upload_http').object.style.display = 'none';
+              $('avatar_upload_file').object.style.display = 'block';
+              break;
+          }
+        }
+      
+      </script>
+      <?php
+      
+      echo '<form action="' . makeUrl($paths->fullpage) . '" method="post" enctype="multipart/form-data">';
+      echo '<div class="tblholder">';
+      echo '<table border="0" cellspacing="1" cellpadding="4">';
+      echo '<tr>
+              <th colspan="2">
+                ' . $lang->get('usercp_avatar_table_title') . '
+              </th>
+            </tr>';
+            
+      echo '<tr>
+              <td class="row2" style="width: 50%;">
+                ' . $lang->get('usercp_avatar_label_current') . '
+              </td>
+              <td class="row1" style="text-align: center;">';
+              
+      if ( $has_avi == 1 )
+      {
+        echo '<img alt="' . $lang->get('usercp_avatar_image_alt', array('username' => $session->username)) . '" src="' . make_avatar_url($session->user_id, $avi_type) . '" />';
+      }
+      else
+      {
+        echo $lang->get('usercp_avatar_image_none');
+      }
+      
+      echo '    </td>
+              </tr>';
+              
+      echo '  <tr>
+                <td class="row2">
+                  ' . $lang->get('usercp_avatar_lbl_change') . '
+                </td>
+                <td class="row1">
+                  <label><input type="radio" name="avatar_action" value="keep" onclick="avatar_select_field(this);" checked="checked" /> ' . $lang->get('usercp_avatar_lbl_keep') . '</label><br />
+                  <label><input type="radio" name="avatar_action" value="remove" onclick="avatar_select_field(this);" /> ' . $lang->get('usercp_avatar_lbl_remove') . '</label><br />';
+      if ( getConfig('avatar_upload_http') == '1' )
+      {
+        echo '    <label><input type="radio" name="avatar_action" value="set_http" onclick="avatar_select_field(this);" /> ' . $lang->get('usercp_avatar_lbl_set_http') . '</label><br />
+                  <div id="avatar_upload_http" style="display: none; margin: 10px 0 0 2.2em;">
+                    ' . $lang->get('usercp_avatar_lbl_url') . ' <input type="text" name="avatar_http_url" size="40" value="http://" /><br />
+                    <small>' . $lang->get('usercp_avatar_lbl_url_desc') . ' ' . $lang->get('usercp_avatar_limits') . '</small>
+                  </div>';
+      }
+      else
+      {
+        echo '    <div id="avatar_upload_http" style="display: none;"></div>';
+      }
+      if ( getConfig('avatar_upload_file') == '1' )
+      {
+        echo '    <label><input type="radio" name="avatar_action" value="set_file" onclick="avatar_select_field(this);" /> ' . $lang->get('usercp_avatar_lbl_set_file') . '</label>
+                  <div id="avatar_upload_file" style="display: none; margin: 10px 0 0 2.2em;">
+                    ' . $lang->get('usercp_avatar_lbl_file') . ' <input type="file" name="avatar_file" size="40" /><br />
+                    <small>' . $lang->get('usercp_avatar_lbl_file_desc') . ' ' . $lang->get('usercp_avatar_limits') . '</small>
+                  </div>';
+      }
+      else
+      {
+        echo '    <div id="avatar_upload_file" style="display: none;"></div>';
+      }
+      echo '    </td>
+              </tr>';
+              
+      echo '  <tr>
+                <th class="subhead" colspan="2">
+                  <input type="submit" name="submit" value="' . $lang->get('etc_save_changes') . '" />
+                </th>
+              </tr>';
+              
+      echo '</table>
+            </div>';
+      
+      break;
     default:
       $good = false;
       $code = $plugins->setHook('userprefs_body');
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/plugins/admin/GroupManager.php	Fri Feb 22 12:51:53 2008 -0500
@@ -0,0 +1,383 @@
+<?php
+
+/*
+ * Enano - an open-source CMS capable of wiki functions, Drupal-like sidebar blocks, and everything in between
+ * Version 1.1.2 (Caoineag alpha 2)
+ * Copyright (C) 2006-2007 Dan Fuhry
+ *
+ * This program is Free Software; you can redistribute and/or modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.
+ *
+ * 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.
+ */
+
+// Usergroup editor
+
+function page_Admin_GroupManager()
+{
+  global $db, $session, $paths, $template, $plugins; // Common objects
+  global $lang;
+  if ( $session->auth_level < USER_LEVEL_ADMIN || $session->user_level < USER_LEVEL_ADMIN )
+  {
+    $login_link = makeUrlNS('Special', 'Login/' . $paths->nslist['Special'] . 'Administration', 'level=' . USER_LEVEL_ADMIN, true);
+    echo '<h3>' . $lang->get('adm_err_not_auth_title') . '</h3>';
+    echo '<p>' . $lang->get('adm_err_not_auth_body', array( 'login_link' => $login_link )) . '</p>';
+    return;
+  }
+  
+  if(isset($_POST['do_create_stage1']))
+  {
+    if(!preg_match('/^([A-z0-9 -]+)$/', $_POST['create_group_name']))
+    {
+      echo '<p>' . $lang->get('acpug_err_group_name_invalid') . '</p>';
+      return;
+    }
+    echo '<form action="'.makeUrl($paths->nslist['Special'].'Administration', 'module='.$paths->cpage['module']).'" method="post" onsubmit="if(!submitAuthorized) return false;" enctype="multipart/form-data">';
+    echo '<div class="tblholder">
+          <table border="0" style="width:100%;" cellspacing="1" cellpadding="4">
+          <tr><th colspan="2">' . $lang->get('acpug_heading_creating_group') . ' '.htmlspecialchars($_POST['create_group_name']).'</th></tr>
+          <tr>
+            <td class="row1">' . $lang->get('acpug_field_group_mod') . '</td><td class="row1">' . $template->username_field('group_mod') . '</td>
+          </tr>
+          <tr><td class="row2">' . $lang->get('acpug_field_group_type') . '</td><td class="row2">
+            <label><input type="radio" name="group_status" value="'.GROUP_CLOSED.'" checked="checked" /> ' . $lang->get('groupcp_type_hidden') . '</label><br />
+            <label><input type="radio" name="group_status" value="'.GROUP_REQUEST.'" /> ' . $lang->get('groupcp_type_closed') . '</label><br />
+            <label><input type="radio" name="group_status" value="'.GROUP_OPEN.'" /> ' . $lang->get('groupcp_type_request') . '</label><br />
+            <label><input type="radio" name="group_status" value="'.GROUP_HIDDEN.'" /> ' . $lang->get('groupcp_type_open') . '</label>
+          </td></tr>
+          <tr>
+            <th class="subhead" colspan="2">
+              <input type="hidden" name="create_group_name" value="'.htmlspecialchars($_POST['create_group_name']).'" />
+              <input type="submit" name="do_create_stage2" value="' . $lang->get('acpug_btn_create_stage2') . '" />
+            </th>
+          </tr>
+          </table>
+          </div>';
+    echo '</form>';
+    return;
+  }
+  elseif(isset($_POST['do_create_stage2']))
+  {
+    if(!preg_match('/^([A-z0-9 -]+)$/', $_POST['create_group_name']))
+    {
+      echo '<p>' . $lang->get('acpug_err_group_name_invalid') . '</p>';
+      return;
+    }
+    if(!in_array(intval($_POST['group_status']), Array(GROUP_CLOSED, GROUP_OPEN, GROUP_HIDDEN, GROUP_REQUEST)))
+    {
+      echo '<p>Hacking attempt</p>';
+      return;
+    }
+    $e = $db->sql_query('SELECT group_id FROM '.table_prefix.'groups WHERE group_name=\''.$db->escape($_POST['create_group_name']).'\';');
+    if(!$e)
+    {
+      echo $db->get_error();
+      return;
+    }
+    if($db->numrows() > 0)
+    {
+      echo '<p>' . $lang->get('acpug_err_already_exist') . '</p>';
+      return;
+    }
+    $db->free_result();
+    $q = $db->sql_query('INSERT INTO '.table_prefix.'groups(group_name,group_type) VALUES( \''.$db->escape($_POST['create_group_name']).'\', ' . intval($_POST['group_status']) . ' )');
+    if(!$q)
+    {
+      echo $db->get_error();
+      return;
+    }
+    $e = $db->sql_query('SELECT user_id FROM '.table_prefix.'users WHERE username=\''.$db->escape($_POST['group_mod']).'\';');
+    if(!$e)
+    {
+      echo $db->get_error();
+      return;
+    }
+    if($db->numrows() < 1)
+    {
+      echo '<p>' . $lang->get('acpug_err_bad_username') . '</p>';
+      return;
+    }
+    $row = $db->fetchrow();
+    $id = $row['user_id'];
+    $db->free_result();
+    $e = $db->sql_query('SELECT group_id FROM '.table_prefix.'groups WHERE group_name=\''.$db->escape($_POST['create_group_name']).'\';');
+    if(!$e)
+    {
+      echo $db->get_error();
+      return;
+    }
+    if($db->numrows() < 1)
+    {
+      echo '<p>' . $lang->get('acpug_err_bad_insert_id') . '</p>';
+      return;
+    }
+    $row = $db->fetchrow();
+    $gid = $row['group_id'];
+    $db->free_result();
+    $e = $db->sql_query('INSERT INTO '.table_prefix.'group_members(group_id,user_id,is_mod) VALUES('.$gid.', '.$id.', 1);');
+    if(!$e)
+    {
+      echo $db->get_error();
+      return;
+    }
+    $g_name = htmlspecialchars($_POST['create_group_name']);
+    echo "<div class='info-box'>
+            <b>" . $lang->get('acpug_heading_info') . "</b><br />
+            " . $lang->get('acpug_msg_create_success', array('g_name' => $g_name)) . "
+          </div>";
+  }
+  if(isset($_POST['do_edit']) || isset($_POST['edit_do']))
+  {
+    // Fetch the group name
+    $q = $db->sql_query('SELECT group_name,system_group FROM '.table_prefix.'groups WHERE group_id='.intval($_POST['group_edit_id']).';');
+    if(!$q)
+    {
+      echo $db->get_error();
+      return;
+    }
+    if($db->numrows() < 1)
+    {
+      echo '<p>Error: couldn\'t look up group name</p>';
+    }
+    $row = $db->fetchrow();
+    $name = htmlspecialchars($row['group_name']);
+    $db->free_result();
+    if(isset($_POST['edit_do']))
+    {
+      if(isset($_POST['edit_do']['del_group']))
+      {
+        if ( $row['system_group'] == 1 )
+        {
+          echo '<div class="error-box">' . $lang->get('acpug_err_nodelete_system_group', array('g_name' => $name)) . '</div>';
+        }
+        else
+        {
+          $q = $db->sql_query('DELETE FROM '.table_prefix.'group_members WHERE group_id='.intval($_POST['group_edit_id']).';');
+          if(!$q)
+          {
+            echo $db->get_error();
+            return;
+          }
+          $q = $db->sql_query('DELETE FROM '.table_prefix.'groups WHERE group_id='.intval($_POST['group_edit_id']).';');
+          if(!$q)
+          {
+            echo $db->get_error();
+            return;
+          }
+          echo '<div class="info-box">' . $lang->get('acpug_msg_delete_success', array('g_name' => $name, 'a_flags' => 'href="javascript:ajaxPage(\'' . $paths->nslist['Admin'] . 'GroupManager\');"')) . '</div>';
+          return;
+        }
+      }
+      if(isset($_POST['edit_do']['save_name']))
+      {
+        if(!preg_match('/^([A-z0-9 -]+)$/', $_POST['group_name']))
+        {
+          echo '<p>' . $lang->get('acpug_err_group_name_invalid') . '</p>';
+          return;
+        }
+        $q = $db->sql_query('UPDATE '.table_prefix.'groups SET group_name=\''.$db->escape($_POST['group_name']).'\'
+            WHERE group_id='.intval($_POST['group_edit_id']).';');
+        if(!$q)
+        {
+          echo $db->get_error();
+          return;
+        }
+        else
+        {
+          echo '<div class="info-box" style="margin: 0 0 10px 0;"">
+                  ' . $lang->get('acpug_msg_name_update_success') . '
+                </div>';
+        }
+        $name = htmlspecialchars($_POST['group_name']);
+        
+      }
+      $q = $db->sql_query('SELECT member_id FROM '.table_prefix.'group_members
+                             WHERE group_id='.intval($_POST['group_edit_id']).';');
+      if(!$q)
+      {
+        echo $db->get_error();
+        return;
+      }
+      if($db->numrows() > 0)
+      {
+        while($row = $db->fetchrow($q))
+        {
+          if(isset($_POST['edit_do']['del_' . $row['member_id']]))
+          {
+            $e = $db->sql_query('DELETE FROM '.table_prefix.'group_members WHERE member_id='.$row['member_id']);
+            if(!$e)
+            {
+              echo $db->get_error();
+              return;
+            }
+          }
+        }
+      }
+      $db->free_result();
+      if(isset($_POST['edit_do']['add_member']))
+      {
+        $q = $db->sql_query('SELECT user_id FROM '.table_prefix.'users WHERE username=\''.$db->escape($_POST['edit_add_username']).'\';');
+        if(!$q)
+        {
+          echo $db->get_error();
+          return;
+        }
+        if($db->numrows() > 0)
+        {
+          $row = $db->fetchrow();
+          $user_id = $row['user_id'];
+          $is_mod = ( isset( $_POST['add_mod'] ) ) ? '1' : '0';
+          $q = $db->sql_query('INSERT INTO '.table_prefix.'group_members(group_id,user_id,is_mod) VALUES('.intval($_POST['group_edit_id']).','.$user_id.','.$is_mod.');');
+          if(!$q)
+          {
+            echo $db->get_error();
+            return;
+          }
+          else
+          {
+            echo '<div class="info-box" style="margin: 0 0 10px 0;"">
+                    ' . $lang->get('acpug_msg_user_added', array('username' => htmlspecialchars($_POST['edit_add_username']))) . '
+                  </div>';
+          }
+        }
+        else
+          echo '<div class="warning-box">' . $lang->get('acpug_err_username_not_exist', array('username' => htmlspecialchars($_POST['edit_add_username']))) . '</div>';
+      }
+    }
+    $sg_disabled = ( $row['system_group'] == 1 ) ?
+             ' value="' . $lang->get('acpug_btn_cant_delete') . '" disabled="disabled" style="color: #FF9773" ' :
+             ' value="' . $lang->get('acpug_btn_delete_group') . '" style="color: #FF3713" ';
+    echo '<form action="'.makeUrl($paths->nslist['Special'].'Administration', 'module='.$paths->cpage['module']).'" method="post" onsubmit="if(!submitAuthorized) return false;" enctype="multipart/form-data">';
+    echo '<div class="tblholder">
+          <table border="0" style="width:100%;" cellspacing="1" cellpadding="4">
+          <tr><th>' . $lang->get('acpug_heading_edit_name') . '</th></tr>
+          <tr>
+            <td class="row1">
+              ' . $lang->get('acpug_field_group_name') . ' <input type="text" name="group_name" value="'.$name.'" />
+            </td>
+          </tr>
+          <tr>
+            <th class="subhead">
+              <input type="submit" name="edit_do[save_name]" value="' . $lang->get('acpug_btn_save_name') . '" />
+              <input type="submit" name="edit_do[del_group]" '.$sg_disabled.' />
+            </th>
+          </tr>
+          </table>
+          </div>
+          <input type="hidden" name="group_edit_id" value="'.htmlspecialchars($_POST['group_edit_id']).'" />';
+    echo '</form>';
+    echo '<form action="'.makeUrl($paths->nslist['Special'].'Administration', 'module='.$paths->cpage['module']).'" method="post" onsubmit="if(!submitAuthorized) return false;" enctype="multipart/form-data">';
+    echo '<div class="tblholder">
+          <table border="0" style="width:100%;" cellspacing="1" cellpadding="4">
+          <tr><th colspan="3">' . $lang->get('acpug_heading_edit_members') . '</th></tr>';
+    $q = $db->sql_query('SELECT m.member_id,m.is_mod,u.username FROM '.table_prefix.'group_members AS m
+                           LEFT JOIN '.table_prefix.'users AS u
+                             ON u.user_id=m.user_id
+                             WHERE m.group_id='.intval($_POST['group_edit_id']).'
+                           ORDER BY m.is_mod DESC, u.username ASC;');
+    if(!$q)
+    {
+      echo $db->get_error();
+      return;
+    }
+    if($db->numrows() < 1)
+    {
+      echo '<tr><td colspan="3" class="row1">' . $lang->get('acpug_msg_no_members') . '</td></tr>';
+    }
+    else
+    {
+      $cls = 'row2';
+      while($row = $db->fetchrow())
+      {
+        $cls = ( $cls == 'row1' ) ? 'row2' : 'row1';
+        $mod = ( $row['is_mod'] == 1 ) ? $lang->get('acpug_lbl_member_mod') : '';
+        echo '<tr>
+                <td class="'.$cls.'" style="width: 100%;">
+                  ' . $row['username'] . '
+                </td>
+                <td class="'.$cls.'">
+                  '.$mod.'
+                </td>
+                <td class="'.$cls.'">
+                  <input type="submit" name="edit_do[del_'.$row['member_id'].']" value="' . $lang->get('acpug_btn_remove_member') . '" />
+                </td>
+              </tr>';
+      }
+    }
+    $db->free_result();
+    echo '</table>
+          </div>
+          <input type="hidden" name="group_edit_id" value="'.htmlspecialchars($_POST['group_edit_id']).'" />';
+    echo '</form>';
+    echo '<form action="'.makeUrl($paths->nslist['Special'].'Administration', 'module='.$paths->cpage['module']).'" method="post" onsubmit="if(!submitAuthorized) return false;" enctype="multipart/form-data">';
+    echo '<div class="tblholder">
+          <table border="0" style="width:100%;" cellspacing="1" cellpadding="4">
+            <tr>
+              <th>' . $lang->get('acpug_heading_add_member') . '</th>
+            </tr>
+            <tr>
+              <td class="row1">
+                ' . $lang->get('acpug_field_username') . ' ' . $template->username_field('edit_add_username') . '
+              </td>
+            </tr>
+            <tr>
+              <td class="row2">
+                <label><input type="checkbox" name="add_mod" /> ' . $lang->get('acpug_field_make_mod') . '</label>
+                ' . $lang->get('acpug_field_make_mod_hint') . '
+              </td>
+            </tr>
+            <tr>
+              <th class="subhead">
+                <input type="submit" name="edit_do[add_member]" value="' . $lang->get('acpug_btn_add_user') . '" />
+              </th>
+            </tr>
+          </table>
+          </div>
+          <input type="hidden" name="group_edit_id" value="'.htmlspecialchars($_POST['group_edit_id']).'" />';
+    echo '</form>';
+    return;
+  }
+  echo '<h3>' . $lang->get('acpug_heading_main') . '</h3>';
+  echo '<form action="'.makeUrl($paths->nslist['Special'].'Administration', 'module='.$paths->cpage['module']).'" method="post" onsubmit="if(!submitAuthorized) return false;" enctype="multipart/form-data">';
+  $q = $db->sql_query('SELECT group_id,group_name FROM '.table_prefix.'groups ORDER BY group_name ASC;');
+  if(!$q)
+  {
+    echo $db->get_error();
+  }
+  else
+  {
+    echo '<div class="tblholder">
+          <table border="0" cellspacing="1" cellpadding="4" style="width: 100%;">
+          <tr>
+          <th>' . $lang->get('acpug_heading_edit_existing') . '</th>
+          </tr>';
+    echo '<tr><td class="row2"><select name="group_edit_id">';
+    while ( $row = $db->fetchrow() )
+    {
+      if ( $row['group_name'] != 'Everyone' )
+      {
+        echo '<option value="' . $row['group_id'] . '">' . htmlspecialchars( $row['group_name'] ) . '</option>';
+      }
+    }
+    $db->free_result();
+    echo '</select></td></tr>';
+    echo '<tr><td class="row1" style="text-align: center;"><input type="submit" name="do_edit" value="' . $lang->get('acpug_btn_edit_stage1') . '" /></td></tr>
+          </table>
+          </div>
+          </form><br />';
+  }
+  echo '<form action="'.makeUrl($paths->nslist['Special'].'Administration', 'module='.$paths->cpage['module']).'" method="post" onsubmit="if(!submitAuthorized) return false;" enctype="multipart/form-data">';
+  echo '<div class="tblholder">
+        <table border="0" cellspacing="1" cellpadding="4" style="width: 100%;">
+        <tr>
+        <th colspan="2">' . $lang->get('acpug_heading_create_new') . '</th>
+        </tr>';
+  echo '<tr><td class="row2">' . $lang->get('acpug_field_group_name') . '</td><td class="row2"><input type="text" name="create_group_name" /></td></tr>';
+  echo '<tr><td colspan="2" class="row1" style="text-align: center;"><input type="submit" name="do_create_stage1" value="' . $lang->get('acpug_btn_create_stage1') . ' &raquo;" /></td></tr>
+        </table>
+        </div>';
+  echo '</form>';
+}
+
+?>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/plugins/admin/LangManager.php	Fri Feb 22 12:51:53 2008 -0500
@@ -0,0 +1,630 @@
+<?php
+
+/*
+ * Enano - an open-source CMS capable of wiki functions, Drupal-like sidebar blocks, and everything in between
+ * Version 1.1.2 (Caoineag alpha 2)
+ * Copyright (C) 2006-2007 Dan Fuhry
+ *
+ * This program is Free Software; you can redistribute and/or modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.
+ *
+ * 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.
+ */
+
+function page_Admin_LangManager()
+{
+  global $db, $session, $paths, $template, $plugins; // Common objects
+  global $lang;
+  if ( $session->auth_level < USER_LEVEL_ADMIN || $session->user_level < USER_LEVEL_ADMIN )
+  {
+    $login_link = makeUrlNS('Special', 'Login/' . $paths->nslist['Special'] . 'Administration', 'level=' . USER_LEVEL_ADMIN, true);
+    echo '<h3>' . $lang->get('adm_err_not_auth_title') . '</h3>';
+    echo '<p>' . $lang->get('adm_err_not_auth_body', array( 'login_link' => $login_link )) . '</p>';
+    return;
+  }
+  if ( isset($_POST['action']) )
+  {
+    $action =& $_POST['action'];
+    // Parse parameters
+    if ( strpos($action, ';') )
+    {
+      // Parameter section
+      $parms = substr($action, strpos($action, ';') + 1);
+      
+      // Action name section
+      $action = substr($action, 0, strpos($action, ';'));
+      
+      // Match all parameters
+      preg_match_all('/([a-z0-9_]+)=(.+?)(;|$)/', $parms, $matches);
+      $parms = array();
+      
+      // For each full parameter, assign $parms an associative value
+      foreach ( $matches[0] as $i => $_ )
+      {
+        $parm = $matches[2][$i];
+        
+        // Is this parameter in the form of an integer?
+        // (designed to ease validation later)
+        if ( preg_match('/^[0-9]+$/', $parm) )
+          // Yes, run intval(), this enabling is_int()-ish checks
+          $parm = intval($parm);
+        
+        $parms[$matches[1][$i]] = $parm;
+      }
+    }
+    switch ( $action )
+    {
+      case 'install_language':
+        
+        if ( defined('ENANO_DEMO_MODE') )
+        {
+          echo '<div class="error-box">' . $lang->get('acplm_err_lang_install_demo') . '</div>';
+          break;
+        }
+        
+        $lang_list = list_available_languages();
+        // Verify that we have this language's metadata
+        if ( isset($lang_list[@$parms['iso639']]) )
+        {
+          // From here it's all downhill :-)
+          $lang_code =& $parms['iso639'];
+          $lang_data =& $lang_list[$lang_code];
+          
+          $result = install_language($lang_code, $lang_data['name_eng'], $lang_data['name']);
+          if ( $result )
+          {
+            // Language installed. Import the language files.
+            $lang_local = new Language($lang_code);
+            if ( file_exists(ENANO_ROOT . "/language/{$lang_data['dir']}/backup.json") )
+            {
+              $lang_local->import(ENANO_ROOT . "/language/{$lang_data['dir']}/backup.json");
+            }
+            else
+            {
+              foreach ( array('core', 'admin', 'tools', 'user') as $file )
+              {
+                $lang_local->import(ENANO_ROOT . "/language/{$lang_data['dir']}/$file.json");
+              }
+            }
+            unset($lang_local);
+            
+            echo '<div class="info-box">' . $lang->get('acplm_msg_lang_install_success', array('lang_name' => htmlspecialchars($lang_data['name_eng']))) . '</div>';
+          }
+        }
+        break;
+      case 'modify_language':
+        
+        $lang_id =& $parms['lang_id'];
+        if ( !is_int($lang_id) )
+        {
+          echo 'Hacking attempt';
+          break;
+        }
+        
+        if ( isset($parms['finish']) && !empty($_POST['lang_name_native']) && !empty($_POST['lang_name_english']) && !defined('ENANO_DEMO_MODE') )
+        {
+          // We just did validation above, it's safe to save.
+          $name_native = $db->escape($_POST['lang_name_native']);
+          $name_english = $db->escape($_POST['lang_name_english']);
+          
+          $q = $db->sql_query('UPDATE ' . table_prefix . "language SET lang_name_native = '$name_native', lang_name_default = '$name_english' WHERE lang_id = $lang_id;");
+          if ( !$q )
+            $db->_die();
+          
+          echo '<div class="info-box">' . $lang->get('acplm_msg_basic_save_success') . '</div>';
+        }
+        else if ( isset($parms['finish']) && defined('ENANO_DEMO_MODE') )
+        {
+          echo '<div class="error-box">' . $lang->get('acplm_err_lang_install_demo') . '</div>';
+        }
+        
+        // Select language data
+        $q = $db->sql_query('SELECT lang_name_native, lang_name_default, lang_code FROM ' . table_prefix . "language WHERE lang_id = $lang_id;");
+        if ( !$q )
+          $db->_die();
+        
+        list($name_native, $name_english, $lang_code) = $db->fetchrow_num();
+        
+        // Output properties table
+        echo '<h3>' . $lang->get('acplm_heading_modify') . '</h3>';
+        
+        acp_start_form();
+        
+        ?>
+          <div class="tblholder">
+            <table border="0" cellspacing="1" cellpadding="4">
+              <tr>
+                <th colspan="2">
+                  <?php
+                    echo $lang->get('acplm_th_lang_basic');
+                  ?>
+                </th>
+              </tr>
+              <tr>
+              <td class="row2" style="width: 50%;">
+                  <?php
+                    echo str_replace('"', '', $lang->get('acplm_field_lang_name_native'));
+                  ?>
+                </td>
+                <td class="row1">
+                  <input type="text" name="lang_name_native" value="<?php echo htmlspecialchars($name_native); ?>" />
+                </td>
+              </tr>
+              <tr>
+                <td class="row2">
+                  <?php
+                    echo $lang->get('acplm_field_lang_name_english');
+                  ?>
+                </td>
+                <td class="row1">
+                  <input type="text" name="lang_name_english" value="<?php echo htmlspecialchars($name_english); ?>" />
+                </td>
+              </tr>
+              <tr>
+                <td class="row2">
+                  <?php
+                    echo $lang->get('acplm_field_lang_code') . '<br />'
+                       . '<small>' . $lang->get('acplm_field_lang_code_hint') . '</small>';
+                  ?>
+                </td>
+                <td class="row1">
+                  <?php
+                    echo $lang_code;
+                  ?>
+                </td>
+              </tr>
+              <tr>
+                <th class="subhead" colspan="2">
+                  <button name="action" value="modify_language;finish=1;lang_id=<?php echo $lang_id; ?>"><?php echo $lang->get('etc_save_changes'); ?></button>
+                </th>
+              </tr>
+            </table>
+          </div>
+        </form>
+        
+        <?php
+        acp_start_form();
+        ?>
+        
+        <h3><?php echo $lang->get('acplm_heading_edit_strings_portal'); ?></h3>
+        <p><?php echo $lang->get('acplm_msg_edit_strings_portal_intro'); ?></p>
+        
+        <p>
+        
+        <?php
+        
+        // Grab a Language object
+        if ( $lang->lang_id == $lang_id )
+        {
+          $lang_local =& $lang;
+        }
+        else
+        {
+          $lang_local = new Language($lang_id);
+          $lang_local->fetch();
+        }
+        
+        $categories_loc = array();
+        
+        // Using the & here ensures that a reference is created, thus avoiding wasting memory
+        foreach ( $lang_local->strings as $cat => &$_ )
+        {
+          unset($_);
+          $categories_loc[$cat] = htmlspecialchars($lang->get("meta_$cat"));
+        }
+        
+        asort($categories_loc);
+        
+        echo '<select name="cat_id">';
+        foreach ( $categories_loc as $cat_id => $cat_name)
+        {
+          echo "<option value=\"$cat_id\">$cat_name</option>";
+        }
+        echo '</select>';
+        
+        ?>
+        <button name="action" value="edit_strings;lang_id=<?php echo $lang_id; ?>">
+          <?php echo $lang->get('acplm_btn_edit_strings_portal'); ?>
+        </button>
+        </p>
+        
+        <h3><?php echo $lang->get('acplm_heading_reimport_portal'); ?></h3>
+        <p><?php echo $lang->get('acplm_msg_reimport_portal_intro'); ?></p>
+        
+        <p>
+          <button name="action" value="reimport;iso639=<?php echo $lang_code; ?>;lang_id=<?php echo $lang_id; ?>">
+            <?php echo $lang->get('acplm_btn_reimport'); ?>
+          </button>
+        </p>
+        
+        </form>
+        
+        <?php
+        
+        echo '<h3>' . $lang->get('acplm_heading_backup') . '</h3>';
+        echo '<p>' . $lang->get('acplm_backup_intro') . '</p>';
+        
+        echo '<form action="' . makeUrlNS('Admin', 'LangManager') . '" method="post">';
+        echo '<button name="action" value="backup_language;lang_id=' . $lang_id . '">' . $lang->get('acplm_btn_create_backup') . '</button>';
+        echo '</form>';
+        
+        return true;
+      case 'edit_strings':
+        
+        $cat_id = @$_POST['cat_id'];
+        if ( !preg_match('/^[a-z0-9]+$/', $cat_id) || !is_int(@$parms['lang_id']) )
+          break;
+        
+        $lang_id =& $parms['lang_id'];
+        
+        if ( isset($parms['save']) && !defined('ENANO_DEMO_MODE') )
+        {
+          // Grab a Language object
+          if ( $lang->lang_id == $lang_id )
+          {
+            $lang_local =& $lang;
+          }
+          else
+          {
+            $lang_local = new Language($lang_id);
+          }
+          // Main save loop
+          // Trying to minimize queries as much as possible here, but you know how that goes.
+          $count_upd = 0;
+          foreach ( $_POST['string'] as $string_id => $user_content )
+          {
+            $curr_content = $lang_local->get_uncensored("{$cat_id}_{$string_id}");
+            if ( $curr_content != $user_content )
+            {
+              $count_upd++;
+              $user_content = $db->escape($user_content);
+              $string_id = $db->escape($string_id);
+              $q = $db->sql_query('UPDATE ' . table_prefix . "language_strings SET string_content = '$user_content' WHERE lang_id = $lang_id AND string_category = '$cat_id' AND string_name = '$string_id';");
+              if ( !$q )
+                $db->_die();
+            }
+          }
+          if ( $count_upd > 0 )
+          {
+            // Update the cache
+            $lang_local->regen_caches();
+            
+            // Update modification time
+            $q = $db->sql_query('UPDATE ' . table_prefix . "language SET last_changed = " . time() . " WHERE lang_id = $lang_id;");
+            if ( !$q )
+              $db->_die();
+          }
+          
+          echo '<div class="info-box">' . $lang->get('acplm_msg_string_save_success') . '</div>';
+        }
+        else if ( isset($parms['save']) && defined('ENANO_DEMO_MODE') )
+        {
+          echo '<div class="error-box">' . $lang->get('acplm_err_lang_install_demo') . '</div>';
+        }
+        
+        acp_start_form();
+        
+        $cat_name = $lang->get("meta_$cat_id");
+        echo '<h3>' . $lang->get('acplm_editor_heading', array('cat_name' => $cat_name)) . '</h3>';
+        
+        // Fetch all strings
+        // This is more efficient than iterating through $lang->strings, I think.
+        $q = $db->sql_query('SELECT string_id, string_name, string_content FROM ' . table_prefix . "language_strings WHERE string_category = '$cat_id' AND lang_id = $lang_id;");
+        if ( !$q )
+          $db->_die();
+        
+        ?>
+        <div class="tblholder">
+          <table border="0" cellspacing="1" cellpadding="4">
+            <tr>
+              <th style="width: 3%;"><?php echo $lang->get('acplm_editor_col_string_name'); ?></th>
+              <th><?php echo $lang->get('acplm_editor_col_string_content'); ?></th>
+            </tr>
+        <?php
+        
+        while ( $row = $db->fetchrow_num() )
+        {
+          list($string_id, $string_name, $string_content) = $row;
+          unset($row);
+          
+          echo '<tr>';
+          
+          if ( strpos($string_content, "\n") )
+          {
+            $editor = '<textarea rows="' . get_line_count($string_content) . '" cols="50" style="width: 99%;" ';
+            $editor .= 'name="string[' . htmlspecialchars($string_name) . ']" ';
+            $editor .= '>' . htmlspecialchars($string_content);
+            $editor .= '</textarea>';
+          }
+          else
+          {
+            $editor = '<input type="text" size="50" style="width: 99%;" ';
+            $editor .= 'name="string[' . htmlspecialchars($string_name) . ']" ';
+            $editor .= 'value="' . htmlspecialchars($string_content) . '" ';
+            $editor .= '/>';
+          }
+          
+          echo '<td class="row2">' . htmlspecialchars($string_name) . '</td>';
+          echo '<td class="row1">' . $editor . '</td>';
+          
+          
+          echo '</tr>';
+          echo "\n";
+        }
+        
+        echo '<tr>
+                <th class="subhead" colspan="2">';
+                
+        echo '<input type="hidden" name="cat_id" value="' . $cat_id . '" />';
+                
+        // Button: save
+        echo '<button name="action" value="edit_strings;lang_id=' . $lang_id . ';save=1" style="font-weight: bold;">' . $lang->get('etc_save_changes') . '</button> ';
+        // Button: revert
+        echo '<button name="action" value="edit_strings;lang_id=' . $lang_id . '" style="font-weight: normal;">' . $lang->get('acplm_editor_btn_revert') . '</button> ';
+        // Button: cancel
+        echo '<button name="action" value="modify_language;lang_id=' . $lang_id . '" style="font-weight: normal;">' . $lang->get('acplm_editor_btn_cancel') . '</button>';
+                
+        echo '  </th>
+              </tr>';
+        
+        ?>
+          </table>
+        </div>
+        <?php
+        echo '</form>';
+        
+        return true;
+      case 'reimport':
+        if ( !isset($parms['iso639']) || !is_int(@$parms['lang_id']) )
+          break;
+        
+        if ( defined('ENANO_DEMO_MODE') )
+        {
+          echo '<div class="error-box">' . $lang->get('acplm_err_lang_install_demo') . '</div>';
+          break;
+        }
+        
+        $lang_code =& $parms['iso639'];
+        $lang_id =& $parms['lang_id'];
+        
+        $lang_list = list_available_languages();
+        
+        if ( !isset($lang_list[$lang_code]) )
+          break;
+        
+        // Grab a Language object
+        if ( $lang->lang_id == $lang_id )
+        {
+          $lang_local =& $lang;
+        }
+        else
+        {
+          $lang_local = new Language($lang_id);
+        }
+        
+        $lang_data =& $lang_list[$lang_code];
+        
+        // This is the big re-import loop
+        if ( file_exists(ENANO_ROOT . "/language/{$lang_data['dir']}/backup.json") )
+        {
+          $lang_local->import(ENANO_ROOT . "/language/{$lang_data['dir']}/backup.json");
+        }
+        else
+        {
+          foreach ( array('core', 'admin', 'tools', 'user') as $file )
+          {
+            $lang_local->import(ENANO_ROOT . "/language/{$lang_data['dir']}/$file.json");
+          }
+        }
+        
+        echo '<div class="info-box">' . $lang->get('acplm_msg_reimport_success') . '</div>';
+        
+        break;
+      case 'backup_language':
+        if ( !is_int(@$parms['lang_id']) )
+          break;
+        
+        $lang_id =& $parms['lang_id'];
+        
+        // Grab a Language object
+        if ( $lang->lang_id == $lang_id )
+        {
+          $lang_local =& $lang;
+        }
+        else
+        {
+          $lang_local = new Language($lang_id);
+        }
+        
+        $filename = 'enano_lang_' . $lang_local->lang_code . '_' . enano_date('ymd') . '.json';
+        
+        // Free as much memory as possible
+        $db->close();
+        unset($GLOBALS['session'], $GLOBALS['paths'], $GLOBALS['template'], $GLOBALS['plugins']);
+        
+        // HTTP headers
+        header('Content-type: application/json');
+        header('Content-disposition: attachment; filename=' . $filename);
+        
+        // Export to JSON
+        $lang_struct = array(
+            'categories' => array_keys($lang_local->strings),
+            'strings' => $lang_local->strings
+          );
+        
+        $lang_struct = enano_json_encode($lang_struct);
+        
+        header('Content-length: ' . strlen($lang_struct));
+        echo $lang_struct;
+        
+        exit;
+        
+      case 'uninstall_language':
+        if ( !is_int(@$parms['lang_id']) )
+          break;
+        
+        if ( defined('ENANO_DEMO_MODE') )
+        {
+          echo '<div class="error-box">' . $lang->get('acplm_err_lang_install_demo') . '</div>';
+          break;
+        }
+        
+        $lang_id =& $parms['lang_id'];
+        
+        if ( isset($parms['confirm']) )
+        {
+          $lang_default = intval(getConfig('default_language'));
+          if ( $lang_default == $lang_id )
+          {
+            echo '<div class="error-box">' . $lang->get('acplm_err_cant_uninstall_default') . '</div>';
+            break;
+          }
+          if ( $lang_id == $lang->lang_id )
+          {
+            // Unload the current language since it's about to be uninstalled
+            unset($lang, $GLOBALS['lang']);
+            $GLOBALS['lang'] = new Language($lang_default);
+            global $lang;
+          }
+          // We're clear
+          
+          // Remove cache files
+          $cache_file = ENANO_ROOT . "/cache/lang_{$lang_id}.php";
+          if ( file_exists($cache_file) )
+            @unlink($cache_file);
+          
+          // Remove strings
+          $q = $db->sql_query('DELETE FROM ' . table_prefix . "language_strings WHERE lang_id = $lang_id;");
+          if ( !$q )
+            $db->_die();
+          
+          // Delete the language
+          $q = $db->sql_query('DELETE FROM ' . table_prefix . "language WHERE lang_id = $lang_id;");
+          if ( !$q )
+            $db->_die();
+          
+          echo '<div class="info-box">' . $lang->get('acplm_msg_uninstall_success') . '</div>';
+          break;
+        }
+        
+        acp_start_form();
+        
+        echo '<h3>' . $lang->get('acplm_uninstall_confirm_title') . '</h3>';
+        echo '<p>' . $lang->get('acplm_uninstall_confirm_body') . '</p>';
+        
+        echo '<p><button name="action" style="font-weight: bold;" value="uninstall_language;lang_id=' . $lang_id . ';confirm=1">' . $lang->get('acplm_btn_uninstall_confirm') . '</button> ';
+        echo '<button name="action" value="home">' . $lang->get('acplm_btn_uninstall_cancel') . '</button></p>';
+        
+        echo '</form>';
+        return true;
+    }
+  }
+  
+  acp_start_form();
+  
+  // Select current languages
+  $q = $db->sql_query('SELECT lang_code, lang_name_native, lang_name_default, lang_id FROM ' . table_prefix . "language ORDER BY lang_id ASC;");
+  if ( !$q )
+    $db->_die();
+  
+  // Language properties/edit/delete portal table
+  echo '<h3>' . $lang->get('acplm_heading_editor_portal') . '</h3>';
+  
+  echo '<div class="tblholder">';
+  echo '<table border="0" cellspacing="1" cellpadding="4">';
+  echo '<tr>
+          <th>' . $lang->get('acplm_col_lang_id') . '</th>
+          <th>' . $lang->get('acplm_col_lang_code') . '</th>
+          <th>' . $lang->get('acplm_col_lang_name') . '</th>
+          <th>' . $lang->get('acplm_col_lang_name_eng') . '</th>
+          <th></th>
+        </tr>';
+  
+  $cls = 'row2';
+  
+  $btn_edit = $lang->get('acplm_portal_btn_edit');
+  $btn_unin = $lang->get('acplm_portal_btn_unin');
+  
+  while ( $row = $db->fetchrow($q) )
+  {
+    $cls = ( $cls == 'row1' ) ? 'row2' : 'row1';
+    
+    echo '<tr>';
+    
+    $lang_code = htmlspecialchars($row['lang_code']);
+    $lang_name_native  = htmlspecialchars($row['lang_name_native']);
+    $lang_name_english = htmlspecialchars($row['lang_name_default']);
+    
+    echo "<td class=\"$cls\" style=\"text-align: center;\">{$row['lang_id']}</td>";
+    echo "<td class=\"$cls\" style=\"text-align: center;\">{$lang_code}</td>";
+    echo "<td class=\"$cls\" style=\"text-align: center;\">{$lang_name_native}</td>";
+    echo "<td class=\"$cls\" style=\"text-align: center;\">{$lang_name_english}</td>";
+    echo "<td class=\"$cls\" style=\"text-align: center;\"><button name=\"action\" value=\"modify_language;lang_id={$row['lang_id']}\">$btn_edit</button> <button name=\"action\" value=\"uninstall_language;lang_id={$row['lang_id']}\">$btn_unin</button></td>";
+    
+    echo '</tr>';
+  }
+  
+  echo '</table></div>';
+  
+  // Reset the result pointer to zero so we can fetch that list of languages again
+  if ( !$db->sql_data_seek(0, $q) )
+  {
+    $db->_die('LangManager doing seek back to zero for installation blacklist');
+  }
+  
+  // $lang_list is fetched by the posthandler sometimes
+  if ( !isset($lang_list) )
+  {
+    // Build a list of languages in the languages/ directory, then
+    // eliminate the ones that are already installed.
+    $lang_list = list_available_languages();
+  }
+  
+  while ( $row = $db->fetchrow($q) )
+  {
+    $lang_code =& $row['lang_code'];
+    if ( isset($lang_list[$lang_code]) )
+    {
+      unset($lang_list[$lang_code]);
+      unset($lang_list[$lang_code]); // PHP <5.1.4 Zend bug
+    }
+  }
+  
+  if ( count($lang_list) > 0 )
+  {
+    echo '<h3>' . $lang->get('acplm_heading_install') . '</h3>';
+    echo '<div class="tblholder">
+            <table border="0" cellspacing="1" cellpadding="4">
+              <tr>
+                <th>' . $lang->get('acplm_col_lang_code') . '</th>
+                <th>' . $lang->get('acplm_col_lang_name') . '</th>
+                <th>' . $lang->get('acplm_col_lang_name_eng') . '</th>
+                <th></th>
+              </tr>';
+              
+    $cls = 'row2';
+    foreach ( $lang_list as $lang_code => $lang_data )
+    {
+      $cls = ( $cls == 'row1' ) ? 'row2' : 'row1';
+      
+      echo '<tr>';
+      
+      $lang_code = htmlspecialchars($lang_code);
+      $lang_data['name'] = htmlspecialchars($lang_data['name']);
+      $lang_data['name_eng'] = htmlspecialchars($lang_data['name_eng']);
+      
+      echo "<td class=\"$cls\" style=\"text-align: center;\">$lang_code</td>";
+      echo "<td class=\"$cls\" style=\"text-align: center;\">{$lang_data['name']}</td>";
+      echo "<td class=\"$cls\" style=\"text-align: center;\">{$lang_data['name_eng']}</td>";
+      echo "<td class=\"$cls\" style=\"text-align: center;\"><button name=\"action\" value=\"install_language;iso639=$lang_code\">" . $lang->get('acplm_btn_install_language') . "</button></td>";
+      
+      echo '</tr>';
+    }
+    echo '    </tr>
+            </table>
+          </div>';
+  }
+  echo '</form>';
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/plugins/admin/PageEditor.php	Fri Feb 22 12:51:53 2008 -0500
@@ -0,0 +1,177 @@
+<?php
+
+/*
+ * Enano - an open-source CMS capable of wiki functions, Drupal-like sidebar blocks, and everything in between
+ * Version 1.1.2 (Caoineag alpha 2)
+ * Copyright (C) 2006-2007 Dan Fuhry
+ *
+ * This program is Free Software; you can redistribute and/or modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.
+ *
+ * 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.
+ */
+
+// Page editing portal
+
+function page_Admin_PageEditor()
+{
+  global $db, $session, $paths, $template, $plugins; // Common objects
+  global $lang;
+  if ( $session->auth_level < USER_LEVEL_ADMIN || $session->user_level < USER_LEVEL_ADMIN )
+  {
+    $login_link = makeUrlNS('Special', 'Login/' . $paths->nslist['Special'] . 'Administration', 'level=' . USER_LEVEL_ADMIN, true);
+    echo '<h3>' . $lang->get('adm_err_not_auth_title') . '</h3>';
+    echo '<p>' . $lang->get('adm_err_not_auth_body', array( 'login_link' => $login_link )) . '</p>';
+    return;
+  }
+  
+  echo '<h3>' . $lang->get('acped_heading_main') . '</h3>';
+  $show_select = true;
+  
+  if ( isset($_REQUEST['action']) || isset($_REQUEST['source']) )
+  {
+    if ( isset($_REQUEST['action']) )
+    {
+      $act =& $_REQUEST['action'];
+      $act = strtolower($act);
+    }
+    else if ( isset($_REQUEST['source']) && $_REQUEST['source'] == 'ajax' )
+    {
+      $act = 'select';
+    }
+    switch ( $act )
+    {
+      case 'save':
+      case 'select':
+        // First step is to determine the page ID and namespace
+        
+        if ( isset($_REQUEST['pid_search']) )
+        {
+          list($page_id, $namespace) = RenderMan::strToPageID($_REQUEST['page_id']);
+          $name = $db->escape(dirtify_page_id($page_id));
+          $page_id = $db->escape(sanitize_page_id($page_id));
+          $namespace = $db->escape($namespace);
+          $name = strtolower($name);
+          $page_id = strtolower($page_id);
+          $sql = "SELECT * FROM " . table_prefix . "pages WHERE ( " . ENANO_SQLFUNC_LOWERCASE . "(urlname) LIKE '%$page_id%' OR " . ENANO_SQLFUNC_LOWERCASE . "(name) LIKE '%$name%' ) ORDER BY name ASC;";
+        }
+        else
+        {
+          // pid_search was not set, assume absolute page ID
+          list($page_id, $namespace) = RenderMan::strToPageID($_REQUEST['page_id']);
+          $page_id = $db->escape(sanitize_page_id($page_id));
+          $namespace = $db->escape($namespace);
+          
+          $sql = "SELECT * FROM " . table_prefix . "pages WHERE urlname = '$page_id' AND namespace = '$namespace';";
+        }
+        
+        if ( !($q = $db->sql_query($sql)) )
+        {
+          $db->_die('PageManager selecting dataset for page');
+        }
+        
+        if ( $db->numrows() < 1 )
+        {
+          echo '<div class="error-box">
+                  ' . $lang->get('acped_err_page_not_found') . '
+                </div>';
+          break;
+        }
+        
+        if ( $db->numrows() > 1 )
+        {
+          // Ambiguous results
+          if ( isset($_REQUEST['pid_search']) )
+          {
+            echo '<h3>' . $lang->get('acped_msg_results_ambiguous_title') . '</h3>';
+            echo '<p>' . $lang->get('acped_msg_results_ambiguous_body') . '</p>';
+            echo '<ul>';
+            while ( $row = $db->fetchrow($q) )
+            {
+              echo '<li>';
+              $pathskey = $paths->nslist[$row['namespace']] . $row['urlname'];
+              $edit_url = makeUrlNS($row['namespace'], $row['urlname']) . '#do:edit';
+              $view_url = makeUrlNS($row['namespace'], $row['urlname']);
+              $page_name = htmlspecialchars(get_page_title_ns( $row['urlname'], $row['namespace'] ));
+              $view_link = $lang->get('acped_ambig_btn_viewpage');
+              echo "<a href=\"$edit_url\">$page_name</a> (<a onclick=\"window.open(this.href); return false;\" href=\"$view_url\">$view_link</a>)";
+              echo '</li>';
+            }
+            echo '</ul>';
+            $show_select = false;
+            break;
+          }
+          else
+          {
+            echo '<p>' . $lang->get('acped_err_ambig_absolute') . '</p>';
+            break;
+          }
+        }
+        
+        // From this point on we can assume that exactly one matching page was found.
+        $dataset = $db->fetchrow();
+        $page_id = $dataset['urlname'];
+        $namespace = $dataset['namespace'];
+        $url = makeUrlNS($namespace, $page_id, false, true) . '#do:edit';
+        $url = addslashes($url);
+        echo '<script type="text/javascript">
+                window.location = \'' . $url . '\';
+              </script>';
+        
+        $show_select = false;
+        break;
+    }
+  }
+  
+  if ( $show_select )
+  {
+    echo '<p>' . $lang->get('acped_hint') . '</p>';
+    
+    // Show the search form
+    
+    $form_action = makeUrlNS('Special', 'Administration', "module={$paths->nslist['Admin']}PageEditor", true);
+    echo "<form action=\"$form_action\" method=\"post\">";
+    echo $lang->get('acped_lbl_field_search') . ' ';
+    echo $template->pagename_field('page_id') . ' ';
+    echo '<input type="hidden" name="action" value="select" />';
+    echo '<input type="submit" name="pid_search" value="' . $lang->get('search_btn_search') . '" />';
+    echo "</form>";
+    
+    // Grab all pages from the database and show a list of pages on the site
+    
+    echo '<h3>' . $lang->get('acped_heading_select_page_from_list') . '</h3>';
+    echo '<p>' . $lang->get('acped_hint_select_page_from_list') . '</p>';
+    
+    $q = $db->sql_query('SELECT COUNT(name) AS num_pages FROM ' . table_prefix . 'pages;');
+    if ( !$q )
+      $db->_die('PageManager doing initial page count');
+    list($num_pages) = $db->fetchrow_num();
+    $db->free_result();
+    
+    $pg_start = ( isset($_GET['offset']) ) ? intval($_GET['offset']) : 0;
+    
+    $q = $db->sql_unbuffered_query('SELECT urlname, name, namespace, ' . $num_pages . ' AS num_pages, ' . $pg_start . ' AS offset, \'edit\' AS mode FROM ' . table_prefix . 'pages ORDER BY name ASC;');
+    if ( !$q )
+      $db->_die('PageManager doing main select query for page list');
+    
+    // Paginate results
+    $html = paginate(
+        $q,
+        '{urlname}',
+        $num_pages,
+        makeUrlNS('Special', 'Administration', "module={$paths->nslist['Admin']}PageEditor&offset=%s", false),
+        $pg_start,
+        99,
+        array('urlname' => 'admin_pagemanager_format_listing'),
+        '<div class="tblholder" style="height: 300px; clip: rect(0px, auto, auto, 0px); overflow: auto;">
+        <table border="0" cellspacing="1" cellpadding="4">',
+        '  </table>
+         </div>'
+      );
+    echo $html;
+  }
+  
+}
+
+?>
--- a/plugins/admin/PageGroups.php	Fri Feb 22 12:46:51 2008 -0500
+++ b/plugins/admin/PageGroups.php	Fri Feb 22 12:51:53 2008 -0500
@@ -2,7 +2,7 @@
 
 /*
  * Enano - an open-source CMS capable of wiki functions, Drupal-like sidebar blocks, and everything in between
- * Version 1.0.3 (Dyrad)
+ * Version 1.1.2 (Caoineag alpha 2)
  * Copyright (C) 2006-2007 Dan Fuhry
  *
  * This program is Free Software; you can redistribute and/or modify it under the terms of the GNU General Public License
@@ -15,9 +15,12 @@
 function page_Admin_PageGroups()
 {
   global $db, $session, $paths, $template, $plugins; // Common objects
+  global $lang;
   if ( $session->auth_level < USER_LEVEL_ADMIN || $session->user_level < USER_LEVEL_ADMIN )
   {
-    echo '<h3>Error: Not authenticated</h3><p>It looks like your administration session is invalid or you are not authorized to access this administration page. Please <a href="' . makeUrlNS('Special', 'Login/' . $paths->nslist['Special'] . 'Administration', 'level=' . USER_LEVEL_ADMIN, true) . '">re-authenticate</a> to continue.</p>';
+    $login_link = makeUrlNS('Special', 'Login/' . $paths->nslist['Special'] . 'Administration', 'level=' . USER_LEVEL_ADMIN, true);
+    echo '<h3>' . $lang->get('adm_err_not_auth_title') . '</h3>';
+    echo '<p>' . $lang->get('adm_err_not_auth_body', array( 'login_link' => $login_link )) . '</p>';
     return;
   }
   
@@ -30,27 +33,27 @@
         case true:
           if ( empty($_POST['pg_name']) || empty($_POST['group_type']) )
           {
-            echo '<div class="error-box">Please enter a name for the page group.</div>';
+            echo '<div class="error-box">' . $lang->get('acppg_err_need_name') . '</div>';
             return;
           }
           if ( $_POST['group_type'] == PAGE_GRP_TAGGED && empty($_POST['member_tag']) )
           {
-            echo '<div class="error-box">Please enter a page tag.</div>';
+            echo '<div class="error-box">' . $lang->get('acppg_err_need_tag') . '</div>';
             return;
           }
           if ( $_POST['group_type'] == PAGE_GRP_CATLINK && empty($_POST['member_cat']) )
           {
-            echo '<div class="error-box">Please create a category page before linking a page group to a category.</div>';
+            echo '<div class="error-box">' . $lang->get('acppg_err_need_cat') . '</div>';
             return;
           }
           if ( $_POST['group_type'] == PAGE_GRP_NORMAL && empty($_POST['member_page_0']) )
           {
-            echo '<div class="error-box">Please specify at least one page to place in this group.</div>';
+            echo '<div class="error-box">' . $lang->get('acppg_err_need_page') . '</div>';
             return;
           }
           if ( $_POST['group_type'] == PAGE_GRP_REGEX && empty($_POST['regex']) )
           {
-            echo '<div class="error-box">Please specify a regular expression to match page IDs against.</div>';
+            echo '<div class="error-box">' . $lang->get('acppg_err_need_regex') . '</div>';
             return;
           }
           if ( $_POST['group_type'] != PAGE_GRP_TAGGED && $_POST['group_type'] != PAGE_GRP_CATLINK && $_POST['group_type'] != PAGE_GRP_NORMAL && $_POST['group_type'] != PAGE_GRP_REGEX )
@@ -117,7 +120,7 @@
                 $db->_die();
               break;
           }
-          echo '<div class="info-box">The page group "' . htmlspecialchars($_POST['pg_name']) . '" has been created.</div>';
+          echo '<div class="info-box">' . $lang->get('acppg_msg_create_success', array('group_name' => htmlspecialchars($_POST['pg_name']))) . '</div>';
           break;
       }
       // A little Javascript magic
@@ -295,7 +298,7 @@
       
       if ( $db->numrows() < 1 )
       {
-        $catlist = 'There aren\'t any categories on this site.';
+        $catlist = $lang->get('acppg_err_no_cats');
       }
       else
       {
@@ -316,14 +319,14 @@
       echo '<div class="tblholder">
             <table border="0" cellspacing="1" cellpadding="4">
               <tr>
-              <th colspan="2">Create page group</th>
+              <th colspan="2">' . $lang->get('acppg_th_create') . '</th>
               </tr>';
       
       // Name
       echo '<tr>
               <td class="row2">
-              Group name:<br />
-              <small>This should be short, descriptive, and human-readable.</small>
+              ' . $lang->get('acppg_field_group_name') . '<br />
+              <small>' . $lang->get('acppg_field_group_name_hint') . '</small>
               </td>
               <td class="row1">
               <input type="text" name="pg_name" size="30" />
@@ -333,14 +336,14 @@
       // Group type
       echo '<tr>
               <td class="row2">
-              Group type:
+              ' . $lang->get('acppg_field_group_type') . '
               </td>
               <td class="row1">
               <select name="group_type" onchange="pg_create_typeset(this);">
-                <option value="' . PAGE_GRP_NORMAL  . '" selected="selected">Static group of pages</option>
-                <option value="' . PAGE_GRP_TAGGED  . '">Group of pages with one tag</option>
-                <option value="' . PAGE_GRP_CATLINK . '">Link to category</option>
-                <option value="' . PAGE_GRP_REGEX   . '">Perl-compatible regular expression (advanced)</option>
+                <option value="' . PAGE_GRP_NORMAL  . '" selected="selected">' . $lang->get('acppg_gtype_static') . '</option>
+                <option value="' . PAGE_GRP_TAGGED  . '">' . $lang->get('acppg_gtype_tagged') . '</option>
+                <option value="' . PAGE_GRP_CATLINK . '">' . $lang->get('acppg_gtype_catlink') . '</option>
+                <option value="' . PAGE_GRP_REGEX   . '">' . $lang->get('acppg_gtype_regex_long') . '</option>
               </select>
               </td>
             </tr>';
@@ -349,16 +352,16 @@
       echo '<tr>
               <th colspan="2">
                 <span id="pg_create_title_normal">
-                  Static group of pages
+                  ' . $lang->get('acppg_gtype_static') . '
                 </span>
                 <span id="pg_create_title_tagged">
-                  Group of commonly tagged pages
+                  ' . $lang->get('acppg_gtype_tagged') . '
                 </span>
                 <span id="pg_create_title_catlink">
-                  Mirror a category
+                  ' . $lang->get('acppg_gtype_catlink') . '
                 </span>
                 <span id="pg_create_title_regex">
-                  Filter through a regular expression
+                  ' . $lang->get('acppg_gtype_regex') . '
                 </span>
               </th>
             </tr>';
@@ -366,24 +369,19 @@
       echo '<tr>
               <td class="row2">
                 <div id="pg_create_normal_1">
-                  Member pages:<br />
-                  <small>Click the "plus" button to add more fields.</small>
+                  ' . $lang->get('acppg_field_member_pages') . '<br />
+                  <small>' . $lang->get('acppg_field_member_pages_hint') . '</small>
                 </div>
                 <div id="pg_create_catlink_1">
-                  Include pages in this category:<br />
-                  <small>Pages in subcategories are <u>not</u> included, however subcategory pages themselves are.</small>
+                  ' . $lang->get('acppg_field_target_category') . '<br />
+                  <small>' . $lang->get('acppg_field_target_category_hint') . '</small>
                 </div>
                 <div id="pg_create_tagged_1">
-                  Include pages with this tag:
+                  ' . $lang->get('acppg_field_target_tag') . '
                 </div>
                 <div id="pg_create_regex_1">
-                  Regular expression:<br />
-                  <small>Be sure to include the starting and ending delimiters and any flags you might need.<br />
-                         These pages might help: <a href="http://us.php.net/manual/en/reference.pcre.pattern.modifiers.php">Pattern modifiers</a> &bull;
-                         <a href="http://us.php.net/manual/en/reference.pcre.pattern.syntax.php">Pattern syntax</a><br />
-                         Examples: <tt>/^(Special|Admin):/i</tt> &bull; <tt>/^Image:([0-9]+)$/</tt><br />
-                         Developers, remember that this will be matched against the full page identifier string. This means that <tt>/^About_Enano$/</tt>
-                         will NOT match the page Special:About_Enano.</small>
+                  ' . $lang->get('acppg_field_target_regex') . '<br />
+                  <small>' . $lang->get('acppg_field_target_regex_hint') . '</small>
               </td>';
             
       echo '  <td class="row1">
@@ -409,7 +407,7 @@
             
       // Submit button
       echo '<tr>
-              <th class="subhead" colspan="2"><input type="submit" name="action[create_stage2]" value="Create page group" style="font-weight: bold;" /> <input type="submit" name="action[noop]" value="Cancel" style="font-weight: normal;" /></th>
+              <th class="subhead" colspan="2"><input type="submit" name="action[create_stage2]" value="' . $lang->get('acppg_btn_create_finish') . '" style="font-weight: bold;" /> <input type="submit" name="action[noop]" value="' . $lang->get('etc_cancel') . '" style="font-weight: normal;" /></th>
             </tr>';
             
       echo '</table>
@@ -427,18 +425,18 @@
       
       if ( !empty($delete_id) )
       {
-        echo '<form action="'.makeUrl($paths->nslist['Special'].'Administration', 'module='.$paths->cpage['module']).'" method="post" onsubmit="if(!submitAuthorized) return false;" enctype="multipart/form-data">';
-        echo '<input type="hidden" name="delete_id" value="' . $delete_id . '" />';
-        echo '<div class="tblholder">';
-        echo '  <table border="0" cellspacing="1" cellpadding="4">';
-        echo '    <tr><th>Confirm deletion</th></tr>';
-        echo '    <tr><td class="row2" style="text-align: center; padding: 20px 0;">Are you sure you want to delete this page group?</td></tr>';
-        echo '    <tr><td class="row1" style="text-align: center;">';
-        echo '        <input type="submit" name="action[del_confirm]" value="Yes, delete group" style="font-weight: bold;" />';
-        echo '        <input type="submit" name="action[noop]" value="Cancel" style="font-weight: normal;" />';
-        echo '        </td></tr>';
-        echo '  </table>';
-        echo '</form>';
+        echo '<form action="'.makeUrl($paths->nslist['Special'].'Administration', 'module='.$paths->cpage['module']).'" method="post" onsubmit="if(!submitAuthorized) return false;" enctype="multipart/form-data">' . "\n";
+        echo '<input type="hidden" name="delete_id" value="' . $delete_id . '" />' . "\n";
+        echo '<div class="tblholder">' . "\n";
+        echo '  <table border="0" cellspacing="1" cellpadding="4">' . "\n";
+        echo '    <tr><th>' . $lang->get('acppg_th_delete_confirm') . '</th></tr>' . "\n";
+        echo '    <tr><td class="row2" style="text-align: center; padding: 20px 0;">' . $lang->get('acppg_msg_delete_confirm') . '</td></tr>' . "\n";
+        echo '    <tr><td class="row1" style="text-align: center;">' . "\n";
+        echo '        <input type="submit" name="action[del_confirm]" value="' . $lang->get('acppg_btn_delete_confirm') . '" style="font-weight: bold;" />' . "\n";
+        echo '        <input type="submit" name="action[noop]" value="' . $lang->get('etc_cancel') . '" style="font-weight: normal;" />' . "\n";
+        echo '        </td></tr>' . "\n";
+        echo '  </table>' . "\n";
+        echo '</form>' . "\n";
         
         return;
       }
@@ -471,7 +469,9 @@
       $q = $db->sql_query('DELETE FROM '.table_prefix.'page_group_members WHERE pg_id=' . $delete_id . ';');
       if ( !$q )
         $db->_die();
-      echo "<div class='info-box'>The group ".'"'.htmlspecialchars("$pg_name").'"'." has been deleted.</div>";
+      
+      $del_msg = $lang->get('acppg_msg_delete_success', array('pg_name' => htmlspecialchars($pg_name)));
+      echo "<div class=\"info-box\">$del_msg</div>";
     }
     else if ( isset($_POST['action']['edit']) && !isset($_POST['action']['noop']) )
     {
@@ -481,7 +481,6 @@
      
       if ( isset($_POST['action']['edit']['add_page']) && isset($_GET['src']) && $_GET['src'] == 'ajax' )
       {
-        $json = new Services_JSON(SERVICES_JSON_LOOSE_TYPE);
         $return = array('successful' => false);
         
         //
@@ -493,7 +492,7 @@
         if ( !$edit_id )
         {
           $return = array('mode' => 'error', 'text' => 'Hack attempt');
-          echo $json->encode($return);
+          echo enano_json_encode($return);
           return;
         }
         
@@ -501,8 +500,8 @@
         $page = $_POST['new_page'];
         if ( empty($page) )
         {
-          $return = array('mode' => 'error', 'text' => 'Please enter a page title.');
-          echo $json->encode($return);
+          $return = array('mode' => 'error', 'text' => $lang->get('acppg_err_ajaxadd_need_title'));
+          echo enano_json_encode($return);
           return;
         }
         
@@ -511,7 +510,7 @@
         if ( !isPage($page) )
         {
           $return = array('mode' => 'error', 'text' => 'The page you are trying to add (' . htmlspecialchars($page) . ') does not exist.');
-          echo $json->encode($return);
+          echo enano_json_encode($return);
           return;
         }
         */
@@ -522,7 +521,7 @@
         if ( !isset($paths->namespace[$namespace]) )
         {
           $return = array('mode' => 'error', 'text' => 'Invalid namespace return from RenderMan::strToPageID()');
-          echo $json->encode($return);
+          echo enano_json_encode($return);
           return;
         }
         
@@ -530,13 +529,13 @@
         if ( !$q )
         {
           $return = array('mode' => 'error', 'text' => $db->get_error());
-          echo $json->encode($return);
+          echo enano_json_encode($return);
           return;
         }
         if ( $db->numrows() > 0 )
         {
-          $return = array('mode' => 'error', 'text' => 'The page you are trying to add is already in this group.');
-          echo $json->encode($return);
+          $return = array('mode' => 'error', 'text' => $lang->get('acppg_err_ajaxadd_already_in'));
+          echo enano_json_encode($return);
           return;
         }
         
@@ -544,15 +543,15 @@
         if ( !$q )
         {
           $return = array('mode' => 'error', 'text' => $db->get_error());
-          echo $json->encode($return);
+          echo enano_json_encode($return);
           return;
         }
         
         $title = "($namespace) " . get_page_title($paths->nslist[$namespace] . $page_id);
         
-        $return = array('mode' => 'info', 'text' => 'The page has been added to the specified group.', 'successful' => true, 'title' => $title, 'member_id' => $db->insert_id());
+        $return = array('mode' => 'info', 'text' => $lang->get('acppg_ajaxadd_success'), 'successful' => true, 'title' => $title, 'member_id' => $db->insert_id());
         
-        echo $json->encode($return);
+        echo enano_json_encode($return);
         return;
       }
       
@@ -566,7 +565,7 @@
           $new_name = $_POST['pg_name'];
           if ( empty($new_name) )
           {
-            echo '<div class="error-box">Please enter a valid name for this group.</div>';
+            echo '<div class="error-box">' . $lang->get('acppg_err_save_need_name') . '</div>';
           }
           else
           {
@@ -582,7 +581,7 @@
               if ( !$q )
                 $db->_die();
               else
-                echo '<div class="info-box">The group name was updated successfully.</div>';
+                echo '<div class="info-box">' . $lang->get('acppg_msg_save_name_updated') . '</div>';
             }
             if ( $_POST['pg_type'] == PAGE_GRP_TAGGED )
             {
@@ -590,7 +589,7 @@
               $target = sanitize_tag($target);
               if ( empty($target) )
               {
-                echo '<div class="error-box">Please enter a valid tag.</div>';
+                echo '<div class="error-box">' . $lang->get('acppg_err_save_need_tag') . '</div>';
               }
               else
               {
@@ -599,7 +598,7 @@
                 if ( !$q )
                   $db->_die();
                 else
-                  echo '<div class="info-box">The affecting tag was updated.</div>';
+                  echo '<div class="info-box">' . $lang->get('acppg_msg_save_tag_updated') . '</div>';
               }
             }
             else if ( $_POST['pg_type'] == PAGE_GRP_REGEX )
@@ -607,7 +606,7 @@
               $target = $_POST['pg_target'];
               if ( empty($target) )
               {
-                echo '<div class="error-box">Please enter an expression to match against..</div>';
+                echo '<div class="error-box">' . $lang->get('acppg_err_save_need_regex') . '</div>';
               }
               else
               {
@@ -616,7 +615,7 @@
                 if ( !$q )
                   $db->_die();
                 else
-                  echo '<div class="info-box">The expression to match against was updated.</div>';
+                  echo '<div class="info-box">' . $lang->get('acppg_msg_save_regex_updated') . '</div>';
               }
             }
             else if ( $_POST['pg_type'] == PAGE_GRP_CATLINK )
@@ -624,7 +623,7 @@
               $target = $_POST['pg_target'];
               if ( empty($target) )
               {
-                echo '<div class="error-box">No category ID specified on POST URI.</div>';
+                echo '<div class="error-box">' . $lang->get('acppg_err_save_bad_category') . '</div>';
               }
               else
               {
@@ -633,7 +632,7 @@
                 if ( !$q )
                   $db->_die();
                 else
-                  echo '<div class="info-box">The affecting category was updated.</div>';
+                  echo '<div class="info-box">' . $lang->get('acppg_msg_save_cat_updated') . '</div>';
               }
             }
           }
@@ -668,7 +667,7 @@
         $subquery = ( count($good) > 0 ) ? 'pg_member_id=' . implode(' OR pg_member_id=', $good) : "'foo'='bar'";
         if ( $subquery == "'foo'='bar'" )
         {
-          echo '<div class="warning-box">No pages were selected for deletion, and thus none were deleted.</div>';
+          echo '<div class="warning-box">' . $lang->get('acppg_err_save_no_pages') . '</div>';
         }
         else
         {
@@ -677,7 +676,7 @@
           {
             $db->_die();
           }
-          echo '<div class="info-box">The requested page group members have been deleted.</div>';
+          echo '<div class="info-box">' . $lang->get('acppg_msg_save_pages_deleted') . '</div>';
         }
       }
       
@@ -701,12 +700,12 @@
       echo '<div class="tblholder">
               <table border="0" cellspacing="1" cellpadding="4">
                 <tr>
-                  <th colspan="3">Editing page group: ' . htmlspecialchars($row['pg_name']) . '</th>
+                  <th colspan="3">' . $lang->get('acppg_th_editing_group') . ' ' . htmlspecialchars($row['pg_name']) . '</th>
                 </tr>';
       // Group name
       
       echo '    <tr>
-                  <td class="row2">Group name:</td>
+                  <td class="row2">' . $lang->get('acppg_field_group_name') . '</td>
                   <td class="row1" colspan="2"><input type="text" name="pg_name" value="' . htmlspecialchars($row['pg_name']) . '" size="30" /></td>
                 </tr>';
       
@@ -726,7 +725,7 @@
           // You have guessed correct.
           // *Sits in chair for 10 minutes listening to the radio in an effort to put off writing the code you see below*
           
-          echo '<tr><th colspan="3" class="subhead"><input type="submit" name="action[edit_save]" value="Save group name" /></th></tr>';
+          echo '<tr><th colspan="3" class="subhead"><input type="submit" name="action[edit_save]" value="' . $lang->get('acppg_btn_save_name') . '" /></th></tr>';
           echo '</table></div>';
           echo '</form>';
           echo '<form name="pg_static_rm_frm" action="'.makeUrl($paths->nslist['Special'].'Administration', 'module='.$paths->cpage['module']).'" method="post" enctype="multipart/form-data">';
@@ -734,7 +733,7 @@
           echo '<div class="tblholder">
                   <table border="0" cellspacing="1" cellpadding="4">
                     <tr>
-                      <th colspan="3">Remove pages from this group</th>
+                      <th colspan="3">' . $lang->get('acppg_th_remove_selected') . '</th>
                     </tr>';
           
           $q = $db->sql_query('SELECT m.pg_member_id,m.page_id,m.namespace FROM '.table_prefix.'page_group_members AS m
@@ -745,11 +744,11 @@
           if ( !$q )
             $db->_die();
           
-          $delim = ceil( $db->numrows() / 2 );
+          $delim = ceil( $db->numrows($q) / 2 );
           if ( $delim < 5 )
           {
             $delim = 0xFFFFFFFE;
-            // stupid hack
+            // stupid hack. I'm XSSing my own code.
             $colspan = '2" id="pg_edit_tackon2me';
           }
           else
@@ -757,10 +756,10 @@
             $colspan = "1";
           }
           
-          echo '<tr><td class="row2" rowspan="2"><b>Remove</b> pages:</td><td class="row1" colspan="' . $colspan . '">';
+          echo '<tr><td class="row2" rowspan="2">' . $lang->get('acppg_field_remove') . '</td><td class="row1" colspan="' . $colspan . '">';
           $i = 0;
           
-          while ( $row = $db->fetchrow() )
+          while ( $row = $db->fetchrow($q) )
           {
             $i++;
             if ( $i == $delim )
@@ -772,7 +771,7 @@
           }
           
           echo '</td></tr>';
-          echo '<tr><th colspan="2" class="subhead" style="width: 70%;"><input type="submit" name="action[edit_save][do_rm]" value="Remove selected" /></th></tr>';
+          echo '<tr><th colspan="2" class="subhead" style="width: 70%;"><input type="submit" name="action[edit_save][do_rm]" value="' . $lang->get('acppg_btn_do_remove') . '" /></th></tr>';
           
           // More javascript magic!
           ?>
@@ -782,7 +781,10 @@
             {
               var input = document.getElementById('inptext_pg_add_member');
               input.onkeyup = function(e) { ajaxPageNameComplete(this); };
-              input.onkeypress = function(e) { if ( e.keyCode == 13 ) { setTimeout('__pg_edit_ajaxadd(document.getElementById(\'' + this.id + '\'));', 500); } };
+              <?php
+              // stupid jEdit hack
+              echo "input.onkeypress = function(e) { if ( e.keyCode == 13 ) { setTimeout('__pg_edit_ajaxadd(document.getElementById(\'' + this.id + '\'));', 500); } };";
+              ?>
             }
             addOnloadHook(__ol_pg_edit_setup);
             var __pg_edit_objcache = false;
@@ -870,7 +872,7 @@
         case PAGE_GRP_TAGGED:
           echo '<tr>
                   <td class="row2">
-                    Include pages with this tag:
+                    ' . $lang->get('acppg_field_target_tag') . '
                   </td>
                   <td class="row1">
                     <input type="text" name="pg_target" value="' . htmlspecialchars($row['pg_target']) . '" size="30" />
@@ -880,13 +882,8 @@
         case PAGE_GRP_REGEX:
           echo '<tr>
                   <td class="row2">
-                    Regular expression to use:<br />
-                    <small>Be sure to include the starting and ending delimiters and any flags you might need.<br />
-                           These pages might help: <a href="http://us.php.net/manual/en/reference.pcre.pattern.modifiers.php">Pattern modifiers</a> &bull;
-                           <a href="http://us.php.net/manual/en/reference.pcre.pattern.syntax.php">Pattern syntax</a><br />
-                           Examples: <tt>/^(Special|Admin):/i</tt> &bull; <tt>/^Image:([0-9]+)$/</tt><br />
-                           Developers, remember that this will be matched against the full page identifier string. This means that <tt>/^About_Enano$/</tt>
-                           will NOT match the page Special:About_Enano.</small>
+                    ' . $lang->get('acppg_field_target_regex') . '<br />
+                    <small>' . $lang->get('acppg_field_target_regex_hint') . '</small>
                   </td>
                   <td class="row1">
                     <input type="text" name="pg_target" value="' . htmlspecialchars($row['pg_target']) . '" size="30" />
@@ -917,11 +914,8 @@
           
           echo '<tr>
                   <td class="row2">
-                    Include pages that are in this category:<br />
-                    <small><b>Reminder:</b> Enano does not automatically place any access controls on the category. If you
-                           don\'t want users to be able to freely add and remove pages from the category (assuming Wiki Mode is enabled
-                           for the category) then you need to enable protection on the category using the button on the more options menu.
-                           </small>
+                    ' . $lang->get('acppg_field_target_category') . '<br />
+                    <small>' . $lang->get('acppg_field_target_category_hint2') . '</small>
                   </td>
                   <td class="row1">
                     ' . $catlist . '
@@ -933,13 +927,13 @@
       
       if ( $ajax_page_add )
       {
-        echo '<tr><th colspan="3"><input type="submit" name="action[noop]" value="Cancel all changes" /></th></tr>';
+        echo '<tr><th colspan="3"><input type="submit" name="action[noop]" value="' . $lang->get('acppg_btn_cancel_all') . '" /></th></tr>';
       }
       else
       {
         echo '<tr><th colspan="3" class="subhead">
-                <input type="submit" name="action[edit_save]" value="Save and update" />
-                <input type="submit" name="action[noop]" value="Cancel all changes" />
+                <input type="submit" name="action[edit_save]" value="' . $lang->get('acppg_btn_save_update') . '" />
+                <input type="submit" name="action[noop]" value="' . $lang->get('acppg_btn_cancel_all') . '" />
               </th></tr>';
       }
       
@@ -951,10 +945,10 @@
       {
         // This needs to be outside of the form.
         echo '<div class="tblholder"><table border="0" cellspacing="1" cellpadding="4"><tr>';
-        echo '<th colspan="2">On-the-fly tools</th></tr>';
+        echo '<th colspan="2">' . $lang->get('acppg_th_onthefly') . '</th></tr>';
         echo '<tr>';
         // Add pages AJAX form
-        echo '<td class="row2">Add page:<br /><small>You can add multiple pages by entering part of a page title, and it will be auto-completed. Press Enter to quickly add the page. This only works if you a really up-to-date browser.</small></td>';
+        echo '<td class="row2">' . $lang->get('acppg_field_add_page') . '<br /><small>' . $lang->get('acppg_field_add_page_hint') . '</small></td>';
         echo '<td class="row1"><input type="text" size="30" name="pg_add_member" id="inptext_pg_add_member" /></td>';
         echo '</tr></table></div>';
       }
@@ -972,8 +966,8 @@
   }
   // No action defined - show default menu
   
-  echo '<h2>Manage page groups</h2>';
-  echo '<p>Enano\'s page grouping system allows you to build sets of pages that can be controlled by a single ACL rule. This makes managing features such as a members-only section of your site a lot easier. If you don\'t use the ACL system, you probably don\'t need to use page groups.</p>';
+  echo '<h2>' . $lang->get('acppg_heading_main') . '</h2>';
+  echo '<p>' . $lang->get('acppg_hint_intro') . '</p>';
   
   $q = $db->sql_query('SELECT pg_id, pg_type, pg_name, pg_target FROM '.table_prefix.'page_groups;');
   if ( !$q )
@@ -984,13 +978,13 @@
   echo '<div class="tblholder">
           <table border="0" cellspacing="1" cellpadding="4">
             <tr>
-              <th>Group name</th>
-              <th>Type</th>
-              <th>Target</th>
-              <th colspan="2">Actions</th>
+              <th>' . $lang->get('acppg_col_group_name') . '</th>
+              <th>' . $lang->get('acppg_col_type') . '</th>
+              <th>' . $lang->get('acppg_col_target') . '</th>
+              <th colspan="2">' . $lang->get('acppg_col_actions') . '</th>
             </tr>';
   
-  if ( $row = $db->fetchrow() )
+  if ( $row = $db->fetchrow($q) )
   {
     do
     {
@@ -999,53 +993,51 @@
       switch ( $row['pg_type'] )
       {
         case PAGE_GRP_CATLINK:
-          $type = 'Link to category';
+          $type = $lang->get('acppg_gtype_catlink');
           break;
         case PAGE_GRP_TAGGED:
-          $type = 'Set of tagged pages';
+          $type = $lang->get('acppg_gtype_tagged');
           break;
         case PAGE_GRP_NORMAL:
-          $type = 'Static set of pages';
+          $type = $lang->get('acppg_gtype_static');
           break;
         case PAGE_GRP_REGEX:
-          $type = 'Regular expression match';
+          $type = $lang->get('acppg_gtype_regex');
           break;
       }
       $target = '';
       if ( $row['pg_type'] == PAGE_GRP_TAGGED )
       {
-        $target = 'Tag: ' . htmlspecialchars($row['pg_target']);
+        $target = $lang->get('acppg_lbl_tag') . ' ' . htmlspecialchars($row['pg_target']);
       }
       else if ( $row['pg_type'] == PAGE_GRP_CATLINK )
       {
-        $target = 'Category: ' . htmlspecialchars(get_page_title($paths->nslist['Category'] . sanitize_page_id($row['pg_target'])));
+        $target = $lang->get('acppg_lbl_category') . ' ' . htmlspecialchars(get_page_title($paths->nslist['Category'] . sanitize_page_id($row['pg_target'])));
       }
       else if ( $row['pg_type'] == PAGE_GRP_REGEX )
       {
-        $target = 'Expression: <tt>' . htmlspecialchars($row['pg_target']) . '</tt>';
+        $target = $lang->get('acppg_lbl_regex') . ' <tt>' . htmlspecialchars($row['pg_target']) . '</tt>';
       }
-      $btn_edit = '<input type="submit" name="action[edit][' . $row['pg_id'] . ']" value="Edit" />';
-      $btn_del = '<input type="submit" name="action[del][' . $row['pg_id'] . ']" value="Delete" />';
-      // stupid jEdit bug/hack
-      $quot = '"';
+      $btn_edit = '<input type="submit" name="action[edit][' . $row['pg_id'] . ']" value="' . $lang->get('acppg_btn_edit') . '" />';
+      $btn_del = '<input type="submit" name="action[del][' . $row['pg_id'] . ']" value="' . $lang->get('acppg_btn_delete') . '" />';
       echo "<tr>
-              <td class={$quot}row1{$quot}>$name</td>
-              <td class={$quot}row2{$quot}>$type</td>
-              <td class={$quot}row1{$quot}>$target</td>
-              <td class={$quot}row3{$quot} style={$quot}text-align: center;{$quot}>$btn_edit</td>
-              <td class={$quot}row3{$quot} style={$quot}text-align: center;{$quot}>$btn_del</td>
+              <td class=\"row1\">$name</td>
+              <td class=\"row2\">$type</td>
+              <td class=\"row1\">$target</td>
+              <td class=\"row3\" style=\"text-align: center;\">$btn_edit</td>
+              <td class=\"row3\" style=\"text-align: center;\">$btn_del</td>
             </tr>";
     }
-    while ( $row = $db->fetchrow() );
+    while ( $row = $db->fetchrow($q) );
   }
   else
   {
-    echo '  <tr><td class="row3" colspan="5" style="text-align: center;">No page groups defined.</td></tr>';
+    echo '  <tr><td class="row3" colspan="5" style="text-align: center;">' . $lang->get('acppg_msg_no_groups') . '</td></tr>';
   }
   
   echo '    <tr>
               <th class="subhead" colspan="5">
-                <input type="submit" name="action[create]" value="Create new group" />
+                <input type="submit" name="action[create]" value="' . $lang->get('acppg_btn_create_new') . '" />
               </th>
             </tr>';
   
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/plugins/admin/PageManager.php	Fri Feb 22 12:51:53 2008 -0500
@@ -0,0 +1,601 @@
+<?php
+
+/*
+ * Enano - an open-source CMS capable of wiki functions, Drupal-like sidebar blocks, and everything in between
+ * Version 1.1.2 (Caoineag alpha 2)
+ * Copyright (C) 2006-2007 Dan Fuhry
+ *
+ * This program is Free Software; you can redistribute and/or modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.
+ *
+ * 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.
+ */
+
+// Page management smart form
+
+function page_Admin_PageManager()
+{
+  global $db, $session, $paths, $template, $plugins; // Common objects
+  global $lang;
+  if ( $session->auth_level < USER_LEVEL_ADMIN || $session->user_level < USER_LEVEL_ADMIN )
+  {
+    $login_link = makeUrlNS('Special', 'Login/' . $paths->nslist['Special'] . 'Administration', 'level=' . USER_LEVEL_ADMIN, true);
+    echo '<h3>' . $lang->get('adm_err_not_auth_title') . '</h3>';
+    echo '<p>' . $lang->get('adm_err_not_auth_body', array( 'login_link' => $login_link )) . '</p>';
+    return;
+  }
+  
+  echo '<h3>' . $lang->get('acppm_heading_main') . '</h3>';
+  $show_select = true;
+  
+  if ( isset($_REQUEST['action']) || isset($_REQUEST['source']) )
+  {
+    if ( isset($_REQUEST['action']) )
+    {
+      $act =& $_REQUEST['action'];
+      $act = strtolower($act);
+    }
+    else if ( isset($_REQUEST['source']) && $_REQUEST['source'] == 'ajax' )
+    {
+      $act = 'select';
+    }
+    switch ( $act )
+    {
+      case 'save':
+      case 'select':
+        // First step is to determine the page ID and namespace
+        
+        if ( isset($_REQUEST['pid_search']) )
+        {
+          list($page_id, $namespace) = RenderMan::strToPageID($_REQUEST['page_id']);
+          $name = $db->escape(dirtify_page_id($page_id));
+          $page_id = $db->escape(sanitize_page_id($page_id));
+          $namespace = $db->escape($namespace);
+          $name = strtolower($name);
+          $page_id = strtolower($page_id);
+          $sql = "SELECT * FROM " . table_prefix . "pages WHERE ( " . ENANO_SQLFUNC_LOWERCASE . "(urlname) LIKE '%$page_id%' OR " . ENANO_SQLFUNC_LOWERCASE . "(name) LIKE '%$name%' ) ORDER BY name ASC;";
+        }
+        else
+        {
+          // pid_search was not set, assume absolute page ID
+          list($page_id, $namespace) = RenderMan::strToPageID($_REQUEST['page_id']);
+          $page_id = $db->escape(sanitize_page_id($page_id));
+          $namespace = $db->escape($namespace);
+          
+          $sql = "SELECT * FROM " . table_prefix . "pages WHERE urlname = '$page_id' AND namespace = '$namespace';";
+        }
+        
+        if ( !($q = $db->sql_query($sql)) )
+        {
+          $db->_die('PageManager selecting dataset for page');
+        }
+        
+        if ( $db->numrows() < 1 )
+        {
+          echo '<div class="error-box">
+                  ' . $lang->get('acppm_err_page_not_found') . '
+                </div>';
+          break;
+        }
+        
+        if ( $db->numrows() > 1 )
+        {
+          // Ambiguous results
+          if ( isset($_REQUEST['pid_search']) )
+          {
+            echo '<h3>' . $lang->get('acppm_msg_results_ambiguous_title') . '</h3>';
+            echo '<p>' . $lang->get('acppm_msg_results_ambiguous_body') . '</p>';
+            echo '<ul>';
+            while ( $row = $db->fetchrow($q) )
+            {
+              echo '<li>';
+              $pathskey = $paths->nslist[$row['namespace']] . $row['urlname'];
+              $edit_url = makeUrlNS('Special', 'Administration', "module={$paths->nslist['Admin']}PageManager&action=select&page_id=$pathskey", true);
+              $view_url = makeUrlNS($row['namespace'], $row['urlname']);
+              $page_name = htmlspecialchars(get_page_title_ns( $row['urlname'], $row['namespace'] ));
+              $view_link = $lang->get('acppm_ambig_btn_viewpage');
+              echo "<a href=\"$edit_url\">$page_name</a> (<a onclick=\"window.open(this.href); return false;\" href=\"$view_url\">$view_link</a>)";
+              echo '</li>';
+            }
+            echo '</ul>';
+            $show_select = false;
+            break;
+          }
+          else
+          {
+            echo '<p>' . $lang->get('acppm_err_ambig_absolute') . '</p>';
+            break;
+          }
+        }
+        
+        // From this point on we can assume that exactly one matching page was found.
+        $dataset = $db->fetchrow();
+        $page_id = $dataset['urlname'];
+        $namespace = $dataset['namespace'];
+        
+        // This is used to re-determine the page ID after submit.
+        $pathskey = $paths->nslist[$namespace] . sanitize_page_id($page_id);
+        
+        // The extra switch allows us to break out of the save routine if needed
+        switch ( $act )
+        {
+          case 'save':
+            
+            $errors = array();
+            $page_id_changed = false;
+            $namespace_changed = false;
+            
+            // Backup the dataset to avoid redundantly updating values
+            $dataset_backup = $dataset;
+            
+            // We've elected to save the page. The angle of attack here is to validate each form field,
+            // and if the field validates successfully, change the value in $dataset accordingly.
+            
+            // Field: page name
+            $page_name = $_POST['page_name'];
+            $page_name = trim($page_name);
+            if ( empty($page_name) )
+            {
+              $errors[] = $lang->get('acppm_err_invalid_page_name');
+            }
+            else
+            {
+              $dataset['name'] = $page_name;
+            }
+            
+            // Field: page URL string
+            $page_urlname = $_POST['page_urlname'];
+            $page_urlname = trim($_POST['page_urlname']);
+            if ( empty($page_urlname) && getConfig('main_page') !== '' )
+            {
+              $errors[] = $lang->get('acppm_err_invalid_url_string');
+            }
+            else
+            {
+              $page_id_changed = ( $_POST['page_urlname'] !== $dataset['urlname'] );
+              $dataset['urlname'] = sanitize_page_id($page_urlname);
+            }
+            
+            // Field: namespace
+            $namespace = $_POST['page_namespace'];
+            if ( !isset($paths->nslist[ $namespace ]) )
+            {
+              $errors[] = $lang->get('acppm_err_invalid_namespace');
+            }
+            else
+            {
+              $namespace_changed = ( $_POST['page_namespace'] !== $dataset['namespace'] );
+              $dataset['namespace'] = $namespace;
+            }
+            
+            // Field: comments enabled
+            $dataset['comments_on'] = ( isset($_POST['comments_on']) ) ? 1 : 0;
+            
+            // Field: page visible
+            $dataset['visible'] = ( isset($_POST['visible']) ) ? 1 : 0;
+            
+            // Field: standalone page
+            $dataset['special'] = ( isset($_POST['special']) ) ? 1 : 0;
+            
+            // Field: page protection
+            $protect_level = $_POST['protected'];
+            if ( !in_array($protect_level, array('0', '1', '2')) )
+            {
+              $errors[] = $lang->get('acppm_err_invalid_protection');
+            }
+            else
+            {
+              $dataset['protected'] = intval($protect_level);
+            }
+            
+            // Field: wiki mode
+            $wiki_mode = $_POST['wikimode'];
+            if ( !in_array($wiki_mode, array('0', '1', '2')) )
+            {
+              $errors[] = $lang->get('acppm_err_invalid_wiki_mode');
+            }
+            else
+            {
+              $dataset['wiki_mode'] = intval($wiki_mode);
+            }
+            
+            if ( count($errors) < 1 )
+            {
+              // We're free of errors. Build a SQL query to update the page table.
+              $particles = array();
+              
+              foreach ( $dataset as $key => $value )
+              {
+                if ( $value === $dataset_backup[$key] || ( is_int($value) && $value === intval($dataset_backup[$key]) ) )
+                  continue;
+                if ( is_int($value) )
+                {
+                  $particle = "$key = $value";
+                }
+                else
+                {
+                  $value = $db->escape($value);
+                  $particle = "$key = '$value'";
+                }
+                $particles[] = $particle;
+                unset($particle);
+              }
+              
+              $page_id_new = $db->escape($dataset['urlname']);
+              $namespace_new = $db->escape($dataset['namespace']);
+              
+              // Only run the update query if at least one field was changed.
+              if ( count($particles) > 0 )
+              {
+                $particles = implode(', ', $particles);
+                $page_id_db = $db->escape($page_id);
+                $namespace_db = $db->escape($namespace);
+                $sql = 'UPDATE ' . table_prefix . "pages SET $particles WHERE urlname = '$page_id_db' AND namespace = '$namespace_db';";
+                
+                if ( !$db->sql_query($sql) )
+                  $db->_die('PageManager running primary update query');
+                
+                // Did we change the page ID or namespace? If so we need to also change logs, comments, tags, etc.
+                if ( $page_id_changed || $namespace_changed )
+                {
+                  $sql = array(
+                      'UPDATE ' . table_prefix . "logs SET page_id = '$page_id_new', namespace = '$namespace_new' WHERE page_id = '$page_id_db' AND namespace = '$namespace_db';",
+                      'UPDATE ' . table_prefix . "tags SET page_id = '$page_id_new', namespace = '$namespace_new' WHERE page_id = '$page_id_db' AND namespace = '$namespace_db';",
+                      'UPDATE ' . table_prefix . "comments SET page_id = '$page_id_new', namespace = '$namespace_new' WHERE page_id = '$page_id_db' AND namespace = '$namespace_db';",
+                      'UPDATE ' . table_prefix . "page_text SET page_id = '$page_id_new', namespace = '$namespace_new' WHERE page_id = '$page_id_db' AND namespace = '$namespace_db';",
+                      'UPDATE ' . table_prefix . "categories SET page_id = '$page_id_new', namespace = '$namespace_new' WHERE page_id = '$page_id_db' AND namespace = '$namespace_db';"
+                    );
+                  foreach ( $sql as $q )
+                  {
+                    if ( !$db->sql_query($q) )
+                      $db->_die('PageManager running slave update query after page ID/namespace change');
+                  }
+                }
+                
+                // Did we change the name of the page? If so, make PageUtils log it
+                if ( $dataset_backup['name'] != $dataset['name'] )
+                {
+                  PageUtils::rename($page_id_new, $namespace_new, $dataset['name']);
+                }
+              }
+              
+              // Did the user ask to delete the page?
+              if ( isset($_POST['delete']) )
+              {
+                PageUtils::deletepage($page_id_new, $namespace_new, $lang->get('acppm_delete_reason'));
+              }
+              
+              echo '<div class="info-box">' . $lang->get('acppm_msg_save_success', array( 'viewpage_url' => makeUrlNS($dataset['namespace'], $dataset['urlname']) )) . '</div>';
+              break 2;
+            }
+            
+            break;
+        }
+        $tpl_code = <<<TPLCODE
+        <div class="tblholder">
+          <table border="0" cellspacing="1" cellpadding="4">
+            <tr>
+              <th colspan="2">
+                {lang:acppm_heading_editing} "{PAGE_NAME}"
+              </th>
+            </tr>
+            
+            <tr>
+              <td class="row2">
+                {lang:acppm_lbl_page_name}
+              </td>
+              <td class="row1">
+                <input type="text" name="page_name" value="{PAGE_NAME}" size="40" />
+              </td>
+            </tr>
+            
+            <tr>
+              <td class="row2">
+                {lang:acppm_lbl_page_urlname}<br />
+                <small>{lang:acppm_lbl_page_urlname_hint}</small>
+              </td>
+              <td class="row1">
+                <input type="text" name="page_urlname" value="{PAGE_URLNAME}" size="40" />
+              </td>
+            </tr>
+            
+            <tr>
+              <td class="row2">
+                {lang:acppm_lbl_namespace}
+              </td>
+              <td class="row1">
+                <select name="page_namespace">
+                {NAMESPACE_LIST}</select>
+              </td>
+            </tr>
+            
+            <tr>
+              <th colspan="2" class="subhead">
+                {lang:acppm_heading_advanced}
+              </th>
+            </tr>
+            
+            <tr>
+              <td class="row2">
+                {lang:acppm_lbl_enable_comments_title}
+              </td>
+              <td class="row1">
+                <label>
+                  <input type="checkbox" name="comments_on" <!-- BEGIN comments_enabled -->checked="checked" <!-- END comments_enabled -->/>
+                  {lang:acppm_lbl_enable_comments}
+                </label>
+                <br />
+                <small>{lang:acppm_lbl_enable_comments_hint}</small>
+              </td>
+            </tr>
+            
+            <tr>
+              <td class="row2">
+                {lang:acppm_lbl_special_title}
+              </td>
+              <td class="row1">
+                <label>
+                  <input type="checkbox" name="special" <!-- BEGIN special -->checked="checked" <!-- END special -->/>
+                  {lang:acppm_lbl_special}
+                </label>
+                <br />
+                <small>{lang:acppm_lbl_special_hint}</small>
+              </td>
+            </tr>
+            
+            <tr>
+              <td class="row2">
+                {lang:acppm_lbl_visible_title}
+              </td>
+              <td class="row1">
+                <label>
+                  <input type="checkbox" name="visible" <!-- BEGIN visible -->checked="checked" <!-- END visible -->/>
+                  {lang:acppm_lbl_visible}
+                </label>
+                <br />
+                <small>{lang:acppm_lbl_visible_hint}</small>
+              </td>
+            </tr>
+            
+            <tr>
+              <td class="row2">
+                {lang:acppm_lbl_protected_title}
+              </td>
+              <td class="row1">
+                <label>
+                  <input type="radio" name="protected" value="0" <!-- BEGIN protected_off -->checked="checked" <!-- END protected_off -->/>
+                  {lang:acppm_lbl_protected_off}
+                </label>
+                <br />
+                <label>
+                  <input type="radio" name="protected" value="1" <!-- BEGIN protected_on -->checked="checked" <!-- END protected_on -->/>
+                  {lang:acppm_lbl_protected_on}
+                </label>
+                <br />
+                <label>
+                  <input type="radio" name="protected" value="2" <!-- BEGIN protected_semi -->checked="checked" <!-- END protected_semi -->/>
+                  {lang:acppm_lbl_protected_semi}
+                </label>
+                <br />
+                <small>{lang:acppm_lbl_protected_hint}</small>
+              </td>
+            </tr>
+            
+            <tr>
+              <td class="row2">
+                {lang:acppm_lbl_wikimode_title}
+              </td>
+              <td class="row1">
+                <label>
+                  <input type="radio" name="wikimode" value="0" <!-- BEGIN wikimode_off -->checked="checked" <!-- END wikimode_off -->/>
+                  {lang:acppm_lbl_wikimode_off}
+                </label>
+                <br />
+                <label>
+                  <input type="radio" name="wikimode" value="1" <!-- BEGIN wikimode_on -->checked="checked" <!-- END wikimode_on -->/>
+                  {lang:acppm_lbl_wikimode_on}
+                </label>
+                <br />
+                <label>
+                  <input type="radio" name="wikimode" value="2" <!-- BEGIN wikimode_global -->checked="checked" <!-- END wikimode_global -->/>
+                  {lang:acppm_lbl_wikimode_global}
+                </label>
+                <br />
+                <small>{lang:acppm_lbl_wikimode_hint}</small>
+              </td>
+            </tr>
+            
+            <tr>
+              <td class="row2">
+                {lang:acppm_lbl_delete_title}
+              </td>
+              <td class="row1">
+                <label>
+                  <input type="checkbox" name="delete" />
+                  {lang:acppm_lbl_delete}
+                </label>
+                <br />
+                <small>{lang:acppm_lbl_delete_hint}</small>
+              </td>
+            </tr>
+            
+            <tr>
+              <th colspan="2" class="subhead">
+                <button name="action" value="save">
+                  <b>{lang:etc_save_changes}</b>
+                </button>
+                <button name="action" value="nil">
+                  <b>{lang:etc_cancel}</b>
+                </button>
+              </th>
+            </tr>
+            
+          </table>
+        </div>
+        
+        <input type="hidden" name="page_id" value="{PATHS_KEY}" />
+TPLCODE;
+        $parser = $template->makeParserText($tpl_code);
+        
+        $ns_list = '';
+        foreach ( $paths->nslist as $ns => $prefix ) 
+        {
+          // FIXME: Plugins need to specify whether they want Enano's regular PageProcessor
+          // to handle these pages, and whether such pages from namespaces created by plugins
+          // can be stored in the database or not.
+          if ( $ns == 'Special' || $ns == 'Admin' || $ns == 'Anonymous' )
+            continue;
+          $ns = htmlspecialchars($ns);
+          $prefix = htmlspecialchars($prefix);
+          if ( empty($prefix) )
+            $prefix = $lang->get('acppm_ns_article');
+          $sel = ( $dataset['namespace'] == $ns ) ? ' selected="selected"' : '';
+          $ns_list .= "  <option value=\"$ns\"$sel>$prefix</option>\n                ";
+        }
+        
+        $parser->assign_vars(array(
+            'PAGE_NAME' => htmlspecialchars($dataset['name']),
+            'PAGE_URLNAME' => htmlspecialchars($dataset['urlname']),
+            'NAMESPACE_LIST' => $ns_list,
+            'PATHS_KEY' => $pathskey
+          ));
+        
+        $parser->assign_bool(array(
+            'comments_enabled' => ( $dataset['comments_on'] == 1 ),
+            'special' => ( $dataset['special'] == 1 ),
+            'visible' => ( $dataset['visible'] == 1 ),
+            'protected_off'   => ( $dataset['protected'] == 0 ),
+            'protected_on'    => ( $dataset['protected'] == 1 ),
+            'protected_semi'  => ( $dataset['protected'] == 2 ),
+            'wikimode_off'    => ( $dataset['wiki_mode'] == 0 ),
+            'wikimode_on'     => ( $dataset['wiki_mode'] == 1 ),
+            'wikimode_global' => ( $dataset['wiki_mode'] == 2 )
+          ));
+        
+        if ( isset($errors) )
+        {
+          echo '<div class="error-box">';
+          echo $lang->get('acppm_err_header');
+          echo '<ul>';
+          echo '<li>' . implode('</li><li>', $errors) . '</li>';
+          echo '</ul>';
+          echo '</div>';
+        }
+        
+        $form_action = makeUrlNS('Special', 'Administration', "module={$paths->nslist['Admin']}PageManager", true);
+        
+        echo "<form action=\"$form_action\" method=\"post\">";
+        echo $parser->run();
+        echo "</form>";
+        
+        $show_select = false;
+        break;
+    }
+  }
+  
+  if ( $show_select )
+  {
+    echo '<p>' . $lang->get('acppm_hint') . '</p>';
+    
+    // Show the search form
+    
+    $form_action = makeUrlNS('Special', 'Administration', "module={$paths->nslist['Admin']}PageManager", true);
+    echo "<form action=\"$form_action\" method=\"post\">";
+    echo $lang->get('acppm_lbl_field_search') . ' ';
+    echo $template->pagename_field('page_id') . ' ';
+    echo '<input type="hidden" name="action" value="select" />';
+    echo '<input type="submit" name="pid_search" value="' . $lang->get('search_btn_search') . '" />';
+    echo "</form>";
+    
+    // Grab all pages from the database and show a list of pages on the site
+    
+    echo '<h3>' . $lang->get('acppm_heading_select_page_from_list') . '</h3>';
+    echo '<p>' . $lang->get('acppm_hint_select_page_from_list') . '</p>';
+    
+    $q = $db->sql_query('SELECT COUNT(name) AS num_pages FROM ' . table_prefix . 'pages;');
+    if ( !$q )
+      $db->_die('PageManager doing initial page count');
+    list($num_pages) = $db->fetchrow_num();
+    $db->free_result();
+    
+    $pg_start = ( isset($_GET['offset']) ) ? intval($_GET['offset']) : 0;
+    
+    $q = $db->sql_unbuffered_query('SELECT urlname, name, namespace, ' . $num_pages . ' AS num_pages, ' . $pg_start . ' AS offset FROM ' . table_prefix . 'pages ORDER BY name ASC;');
+    if ( !$q )
+      $db->_die('PageManager doing main select query for page list');
+    
+    // Paginate results
+    $html = paginate(
+        $q,
+        '{urlname}',
+        $num_pages,
+        makeUrlNS('Special', 'Administration', "module={$paths->nslist['Admin']}PageManager&offset=%s", false),
+        $pg_start,
+        99,
+        array('urlname' => 'admin_pagemanager_format_listing'),
+        '<div class="tblholder" style="height: 300px; clip: rect(0px, auto, auto, 0px); overflow: auto;">
+        <table border="0" cellspacing="1" cellpadding="4">',
+        '  </table>
+         </div>'
+      );
+    echo $html;
+  }
+  
+}
+
+function admin_pagemanager_format_listing($_, $row)
+{
+  global $db, $session, $paths, $template, $plugins; // Common objects
+  
+  static $cell_count = 0;
+  static $td_class = 'row1';
+  static $run_count = 0;
+  static $num_pages_floor = false;
+  if ( !$num_pages_floor )
+  {
+    $num_pages_floor = $row['num_pages'];
+    while ( $num_pages_floor % 99 > 0 )
+      $num_pages_floor--;
+  }
+  $return = '';
+  $run_count++;
+  
+  $last_page = ( $row['offset'] == $num_pages_floor );
+  $last_run = ( ( $last_page && $run_count == $row['num_pages'] % 99 ) || $run_count == 99 );
+  if ( $cell_count == 0 )
+  {
+    $return .= "<tr>\n";
+  }
+  $title = get_page_title_ns($row['urlname'], $row['namespace']);
+  $pathskey = $paths->nslist[$row['namespace']] . $row['urlname'];
+  if ( isset($row['mode']) && $row['mode'] == 'edit' )
+  {
+    $url = makeUrlNS($row['namespace'], $row['urlname'], false, true) . '#do:edit';
+  }
+  else
+  {
+    $url = makeUrlNS('Special', 'Administration', "module={$paths->nslist['Admin']}PageManager&action=select&page_id=$pathskey", true);
+  }
+  $url = '<a href="' . $url . '">' . htmlspecialchars($title) . '</a>';
+  $return .= '  <td class="' . $td_class . '" style="width: 33%;">' . $url . '</td>' . "\n";
+  $cell_count++;
+  if ( $cell_count == 3 && !$last_run )
+  {
+    $cell_count = 0;
+    $td_class = ( $td_class == 'row2' ) ? 'row1' : 'row2';
+    $return .= "</tr>\n";
+  }
+  else if ( $last_run )
+  {
+    while ( $cell_count < 3 )
+    {
+      $return .= "  <td class=\"{$td_class}\"></td>\n";
+      $cell_count++;
+    }
+    $return .= "</tr>\n";
+  }
+  return $return;
+}
+
+?>
--- a/plugins/admin/SecurityLog.php	Fri Feb 22 12:46:51 2008 -0500
+++ b/plugins/admin/SecurityLog.php	Fri Feb 22 12:51:53 2008 -0500
@@ -2,7 +2,7 @@
 
 /*
  * Enano - an open-source CMS capable of wiki functions, Drupal-like sidebar blocks, and everything in between
- * Version 1.0.3 (Dyrad)
+ * Version 1.1.2 (Caoineag alpha 2)
  * Copyright (C) 2006-2007 Dan Fuhry
  *
  * This program is Free Software; you can redistribute and/or modify it under the terms of the GNU General Public License
@@ -15,9 +15,12 @@
 function page_Admin_SecurityLog()
 {
   global $db, $session, $paths, $template, $plugins; // Common objects
+  global $lang;
   if ( $session->auth_level < USER_LEVEL_ADMIN || $session->user_level < USER_LEVEL_ADMIN )
   {
-    echo '<h3>Error: Not authenticated</h3><p>It looks like your administration session is invalid or you are not authorized to access this administration page. Please <a href="' . makeUrlNS('Special', 'Login/' . $paths->nslist['Special'] . 'Administration', 'level=' . USER_LEVEL_ADMIN, true) . '">re-authenticate</a> to continue.</p>';
+    $login_link = makeUrlNS('Special', 'Login/' . $paths->nslist['Special'] . 'Administration', 'level=' . USER_LEVEL_ADMIN, true);
+    echo '<h3>' . $lang->get('adm_err_not_auth_title') . '</h3>';
+    echo '<p>' . $lang->get('adm_err_not_auth_body', array( 'login_link' => $login_link )) . '</p>';
     return;
   }
   
@@ -26,7 +29,7 @@
   //   die('Security log is disabled in demo mode.');
   // }
   
-  echo '<h3>System security log</h3>';
+  echo '<h3>' . $lang->get('acpsl_heading_main') . '</h3>';
   
   // Not calling the real fetcher because we have to paginate the results
   $offset = ( isset($_GET['offset']) ) ? intval($_GET['offset']) : 0;
@@ -49,7 +52,12 @@
       50,
       array('time_id' => 'seclog_format_inner'),
       '<div class="tblholder" style="/* max-height: 500px; clip: rect(0px,auto,auto,0px); overflow: auto; */"><table border="0" cellspacing="1" cellpadding="4" width="100%">
-       <tr><th style="width: 60%;">Type</th><th>Date</th><th>Username</th><th>IP Address</th></tr>',
+       <tr>
+         <th style="width: 60%;">' . $lang->get('acpsl_col_type') . '</th>
+         <th>' . $lang->get('acpsl_col_date') . '</th>
+         <th>' . $lang->get('acpsl_col_username') . '</th>
+         <th>' . $lang->get('acpsl_col_ip') . '</th>
+       </tr>',
       '</table></div>'
     );
   
@@ -94,7 +102,7 @@
       $l = 'SELECT action,date_string,author,edit_summary,time_id,page_text FROM '.table_prefix.'logs WHERE log_type=\'security\' ORDER BY time_id DESC, action ASC;';
     }
     $q = $db->sql_query($l);
-    while($r = $db->fetchrow())
+    while($r = $db->fetchrow($q))
     {
       $return .= seclog_format_inner($r);
     }
@@ -113,6 +121,7 @@
     $r =& $f;
   }
   global $db, $session, $paths, $template, $plugins; // Common objects
+  global $lang;
   $return = '';
   static $cls = 'row2';
   if ( substr($_SERVER['REMOTE_ADDR'], 0, 8) != '192.168.' && defined('ENANO_DEMO_MODE') )
@@ -135,33 +144,34 @@
   $return .= '<tr><td class="'.$cls.'">';
   switch($r['action'])
   {
-    case "admin_auth_good":  $return .= 'Successful elevated authentication'; if ( !empty($r['page_text']) ) { $level = $session->userlevel_to_string( intval($r['page_text']) ); $return .= "<br /><small>Authentication level: $level</small>"; } break;
-    case "admin_auth_bad":   $return .= 'Failed elevated authentication'; if ( !empty($r['page_text']) ) { $level = $session->userlevel_to_string( intval($r['page_text']) ); $return .= "<br /><small>Attempted auth level: $level</small>"; } break;
-    case "activ_good":       $return .= 'Successful account activation'; break;
-    case "auth_good":        $return .= 'Successful regular user logon'; break;
-    case "activ_bad":        $return .= 'Failed account activation'; break;
-    case "auth_bad":         $return .= 'Failed regular user logon'; break;
-    case "sql_inject":       $return .= 'SQL injection attempt<div style="max-width: 90%; clip: rect(0px,auto,auto,0px); overflow: auto; display: block; font-size: smaller;">Offending query: ' . htmlspecialchars($r['page_text']) . '</div>'; break;
-    case "db_backup":        $return .= 'Database backup created<br /><small>Tables: ' . $r['page_text'] . '</small>'; break;
-    case "install_enano":    $return .= "Installed Enano version {$r['page_text']}"; break;
-    case "upgrade_enano":    $return .= "Upgraded Enano to version {$r['page_text']}"; break;
-    case "illegal_page":     $return .= "Unauthorized viewing attempt<br /><small>Page: {$illegal_link}</small>"; break;
-    case "upload_enable":    $return .= "Enabled file uploads"; break;
-    case "upload_disable":   $return .= "Disabled file uploads"; break;
-    case "magick_enable":    $return .= "Enabled ImageMagick for uploaded images"; break;
-    case "magick_disable":   $return .= "Disabled ImageMagick for uploaded images"; break;
-    case "filehist_enable":  $return .= "Enabled revision tracking for uploaded files"; break;
-    case "filehist_disable": $return .= "Disabled revision tracking for uploaded files"; break;
-    case "magick_path":      $return .= "Changed path to ImageMagick executable"; break;
-    case "plugin_disable":   $return .= "Disabled plugin: {$r['page_text']}"; break;
-    case "plugin_enable":    $return .= "Enabled plugin: {$r['page_text']}"; break;
-    case "seclog_unauth":    $return .= "Unauthorized attempt to call security log fetcher"; break;
-    case "u_from_admin":     $return .= "User {$r['page_text']} demoted from Administrators group"; break;
-    case "u_from_mod":       $return .= "User {$r['page_text']} demoted from Moderators group"; break;
-    case "u_to_admin":       $return .= "User {$r['page_text']} added to Administrators group"; break;
-    case "u_to_mod":         $return .= "User {$r['page_text']} added to Moderators group"; break;
+    case "admin_auth_good" : $return .= $lang->get('acpsl_entry_admin_auth_good'  , array('level' => $session->userlevel_to_string( intval($r['page_text']) ))); break;
+    case "admin_auth_bad"  : $return .= $lang->get('acpsl_entry_admin_auth_bad'   , array('level' => $session->userlevel_to_string( intval($r['page_text']) ))); break;
+    case "activ_good"      : $return .= $lang->get('acpsl_entry_activ_good')      ; break;
+    case "auth_good"       : $return .= $lang->get('acpsl_entry_auth_good')       ; break;
+    case "activ_bad"       : $return .= $lang->get('acpsl_entry_activ_bad')       ; break;
+    case "auth_bad"        : $return .= $lang->get('acpsl_entry_auth_bad')        ; break;
+    case "sql_inject"      : $return .= $lang->get('acpsl_entry_sql_inject'       , array('query' => htmlspecialchars($r['page_text']))); break;
+    case "db_backup"       : $return .= $lang->get('acpsl_entry_db_backup'        , array('tables' => $r['page_text']))       ; break;
+    case "install_enano"   : $return .= $lang->get('acpsl_entry_install_enano'    , array('version' => $r['page_text'])); break; // version is in $r['page_text']
+    case "upgrade_enano"   : $return .= $lang->get('acpsl_entry_upgrade_enano'    , array('version' => $r['page_text'])); break; // version is in $r['page_text']
+    case "illegal_page"    : $return .= $lang->get('acpsl_entry_illegal_page'     , array('illegal_link' => $illegal_link))    ; break;
+    case "upload_enable"   : $return .= $lang->get('acpsl_entry_upload_enable')   ; break;
+    case "upload_disable"  : $return .= $lang->get('acpsl_entry_upload_disable')  ; break;
+    case "magick_enable"   : $return .= $lang->get('acpsl_entry_magick_enable')   ; break;
+    case "magick_disable"  : $return .= $lang->get('acpsl_entry_magick_disable')  ; break;
+    case "filehist_enable" : $return .= $lang->get('acpsl_entry_filehist_enable') ; break;
+    case "filehist_disable": $return .= $lang->get('acpsl_entry_filehist_disable'); break;
+    case "magick_path"     : $return .= $lang->get('acpsl_entry_magick_path')     ; break;
+    case "plugin_disable"  : $return .= $lang->get('acpsl_entry_plugin_disable'   , array('plugin' => $r['page_text'])); break;
+    case "plugin_enable"   : $return .= $lang->get('acpsl_entry_plugin_enable'    , array('plugin' => $r['page_text'])); break;
+    case "seclog_unauth"   : $return .= $lang->get('acpsl_entry_seclog_unauth')   ; break;
+    case "u_from_admin"    : $return .= $lang->get('acpsl_entry_u_from_admin'     , array('username' => $r['page_text'])); break;
+    case "u_from_mod"      : $return .= $lang->get('acpsl_entry_u_from_mod'       , array('username' => $r['page_text'])); break;
+    case "u_to_admin"      : $return .= $lang->get('acpsl_entry_u_to_admin'       , array('username' => $r['page_text'])); break;
+    case "u_to_mod"        : $return .= $lang->get('acpsl_entry_u_to_mod'         , array('username' => $r['page_text'])); break;
+    case "view_comment_ip" : $return .= $lang->get('acpsl_entry_view_comment_ip'  , array('username' => htmlspecialchars($r['page_text']))); break;
   }
-  $return .= '</td><td class="'.$cls.'">'.date('d M Y h:i a', $r['time_id']).'</td><td class="'.$cls.'">'.$r['author'].'</td><td class="'.$cls.'" style="cursor: pointer;" onclick="ajaxReverseDNS(this);" title="Click for reverse DNS info">'.$r['edit_summary'].'</td></tr>';
+  $return .= '</td><td class="'.$cls.'">'.enano_date('d M Y h:i a', $r['time_id']).'</td><td class="'.$cls.'">'.$r['author'].'</td><td class="'.$cls.'" style="cursor: pointer;" onclick="ajaxReverseDNS(this);" title="' . $lang->get('acpsl_tip_reverse_dns') . '">'.$r['edit_summary'].'</td></tr>';
   return $return;
 }
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/plugins/admin/ThemeManager.php	Fri Feb 22 12:51:53 2008 -0500
@@ -0,0 +1,498 @@
+<?php
+
+/*
+ * Enano - an open-source CMS capable of wiki functions, Drupal-like sidebar blocks, and everything in between
+ * Version 1.1.2 (Caoineag alpha 2)
+ * Copyright (C) 2006-2007 Dan Fuhry
+ *
+ * This program is Free Software; you can redistribute and/or modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.
+ *
+ * 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.
+ */
+
+function page_Admin_ThemeManager()
+{
+  global $db, $session, $paths, $template, $plugins; // Common objects
+  global $lang;
+  if ( $session->auth_level < USER_LEVEL_ADMIN || $session->user_level < USER_LEVEL_ADMIN )
+  {
+    $login_link = makeUrlNS('Special', 'Login/' . $paths->nslist['Special'] . 'Administration', 'level=' . USER_LEVEL_ADMIN, true);
+    echo '<h3>' . $lang->get('adm_err_not_auth_title') . '</h3>';
+    echo '<p>' . $lang->get('adm_err_not_auth_body', array( 'login_link' => $login_link )) . '</p>';
+    return;
+  }
+  
+  $system_themes = array('admin', 'printable');
+  
+  // Obtain the list of themes (both available and already installed) and the styles available for each
+  $dh = @opendir(ENANO_ROOT . '/themes');
+  if ( !$dh )
+    die('Couldn\'t open themes directory');
+  $themes = array();
+  while ( $dr = @readdir($dh) )
+  {
+    if ( $dr == '.' || $dr == '..' )
+      continue;
+    if ( !is_dir(ENANO_ROOT . "/themes/$dr") )
+      continue;
+    if ( !file_exists(ENANO_ROOT . "/themes/$dr/theme.cfg") || !is_dir(ENANO_ROOT . "/themes/$dr/css") )
+      continue;
+    $cdh = @opendir(ENANO_ROOT . "/themes/$dr/css");
+    if ( !$cdh )
+      continue;
+    
+    require(ENANO_ROOT . "/themes/$dr/theme.cfg");
+    global $theme;
+    
+    $themes[$dr] = array(
+        'css' => array(),
+        'theme_name' => $theme['theme_name']
+      );
+    while ( $cdr = @readdir($cdh) )
+    {
+      if ( $cdr == '.' || $cdr == '..' )
+        continue;
+      if ( preg_match('/\.css$/i', $cdr) )
+        $themes[$dr]['css'][] = substr($cdr, 0, -4);
+    }
+  }
+  
+  // Decide which themes are not installed
+  $installable = array_flip(array_keys($themes));
+  // FIXME: sanitize directory names or check with preg_match()
+  $where_clause = 'theme_id = \'' . implode('\' OR theme_id = \'', array_flip($installable)) . '\'';
+  $q = $db->sql_query('SELECT theme_id, theme_name, enabled FROM ' . table_prefix . "themes WHERE $where_clause;");
+  if ( !$q )
+    $db->_die();
+  
+  while ( $row = $db->fetchrow() )
+  {
+    $tid =& $row['theme_id'];
+    unset($installable[$tid]);
+    $themes[$tid]['theme_name'] = $row['theme_name'];
+    $themes[$tid]['enabled'] = ( $row['enabled'] == 1 );
+  }
+  
+  foreach ( $system_themes as $st )
+  {
+    unset($installable[$st]);
+  }
+  
+  $installable = array_flip($installable);
+  
+  // AJAX code
+  if ( $paths->getParam(0) === 'action.json' )
+  {
+    return ajaxServlet_Admin_ThemeManager($themes);
+  }
+  
+  // List installed themes
+  ?>
+  <div style="float: right;">
+    <a href="#" id="systheme_toggler" onclick="ajaxToggleSystemThemes(); return false;"><?php echo $lang->get('acptm_btn_system_themes_show'); ?></a>
+  </div>
+  <?php
+  echo '<h3>' . $lang->get('acptm_heading_edit_themes') . '</h3>';
+  echo '<div id="theme_list_edit">';
+  foreach ( $themes as $theme_id => $theme_data )
+  {
+    if ( in_array($theme_id, $installable) )
+      continue;
+    if ( file_exists(ENANO_ROOT . "/themes/$theme_id/preview.png") )
+    {
+      $preview_path = scriptPath . "/themes/$theme_id/preview.png";
+    }
+    else
+    {
+      $preview_path = scriptPath . "/images/themepreview.png";
+    }
+    $d = ( @$theme_data['enabled'] ) ? '' : ' themebutton_theme_disabled';
+    $st = ( in_array($theme_id, $system_themes) ) ? ' themebutton_theme_system' : '';
+    echo '<div class="themebutton' . $st . '' . $d . '" id="themebtn_edit_' . $theme_id . '" style="background-image: url(' . $preview_path . ');">';
+    if ( in_array($theme_id, $system_themes) )
+    {
+      echo   '<a class="tb-inner" href="#" onclick="return false;">
+                ' . $lang->get('acptm_btn_theme_system') . '
+                <span class="themename">' . htmlspecialchars($theme_data['theme_name']) . '</span>
+              </a>';
+    }
+    else
+    {
+      echo   '<a class="tb-inner" href="#" onclick="ajaxEditTheme(\'' . $theme_id . '\'); return false;">
+                ' . $lang->get('acptm_btn_theme_edit') . '
+                <span class="themename">' . htmlspecialchars($theme_data['theme_name']) . '</span>
+              </a>';
+    }
+    echo '</div>';
+  }
+  echo '</div>';
+  echo '<span class="menuclear"></span>';
+  
+  if ( count($installable) > 0 )
+  {
+    echo '<h3>' . $lang->get('acptm_heading_install_themes') . '</h3>';
+  
+    echo '<div id="theme_list_install">';
+    foreach ( $installable as $i => $theme_id )
+    {
+      if ( file_exists(ENANO_ROOT . "/themes/$theme_id/preview.png") )
+      {
+        $preview_path = scriptPath . "/themes/$theme_id/preview.png";
+      }
+      else
+      {
+        $preview_path = scriptPath . "/images/themepreview.png";
+      }
+      echo '<div class="themebutton" id="themebtn_install_' . $theme_id . '" enano:themename="' . htmlspecialchars($themes[$theme_id]['theme_name']) . '" style="background-image: url(' . $preview_path . ');">';
+      echo   '<a class="tb-inner" href="#" onclick="ajaxInstallTheme(\'' . $theme_id . '\'); return false;">
+                ' . $lang->get('acptm_btn_theme_install') . '
+                <span class="themename">' . htmlspecialchars($themes[$theme_id]['theme_name']) . '</span>
+              </a>';
+      echo '</div>';
+    }
+    echo '</div>';
+    echo '<span class="menuclear"></span>';
+  }
+}
+
+function ajaxServlet_Admin_ThemeManager(&$themes)
+{
+  global $db, $session, $paths, $template, $plugins; // Common objects
+  global $lang;
+  if ( $session->auth_level < USER_LEVEL_ADMIN || $session->user_level < USER_LEVEL_ADMIN )
+  {
+    $login_link = makeUrlNS('Special', 'Login/' . $paths->nslist['Special'] . 'Administration', 'level=' . USER_LEVEL_ADMIN, true);
+    echo '<h3>' . $lang->get('adm_err_not_auth_title') . '</h3>';
+    echo '<p>' . $lang->get('adm_err_not_auth_body', array( 'login_link' => $login_link )) . '</p>';
+    return;
+  }
+  
+  if ( !isset($_POST['r']) )
+    return false;
+  
+  try
+  {
+    $request = enano_json_decode($_POST['r']);
+  }
+  catch ( Exception $e )
+  {
+    die('Exception in JSON parser, probably invalid input.');
+  }
+  
+  if ( !isset($request['mode']) )
+  {
+    die('No mode specified in JSON request.');
+  }
+  
+  switch ( $request['mode'] )
+  {
+    case 'fetch_theme':
+      $theme_id = $db->escape($request['theme_id']);
+      if ( empty($theme_id) )
+        die('Invalid theme_id');
+      
+      $q = $db->sql_query("SELECT theme_id, theme_name, default_style, enabled, group_policy, group_list FROM " . table_prefix . "themes WHERE theme_id = '$theme_id';");
+      if ( !$q )
+        $db->die_json();
+      
+      if ( $db->numrows() < 1 )
+        die('BUG: no theme with that theme_id installed.');
+      
+      $row = $db->fetchrow();
+      $row['enabled'] = ( $row['enabled'] == 1 );
+      $row['css'] = @$themes[$theme_id]['css'];
+      $row['default_style'] = preg_replace('/\.css$/', '', $row['default_style']);
+      $row['is_default'] = ( getConfig('theme_default') === $theme_id );
+      $row['group_list'] = ( empty($row['group_list']) ) ? array() : enano_json_decode($row['group_list']);
+      
+      // Build a list of group names
+      $row['group_names'] = array();
+      foreach ( $row['group_list'] as $group_id )
+      {
+        $row['group_names'][$group_id] = '';
+      }
+      if ( count($row['group_names']) > 0 )
+      {
+        $idlist = 'group_id = ' . implode(' OR group_id = ', array_keys($row['group_names']));
+        $q = $db->sql_query('SELECT group_id, group_name FROM ' . table_prefix . "groups WHERE $idlist;");
+        if ( !$q )
+          $db->die_json();
+        while ( $gr = $db->fetchrow_num() )
+        {
+          list($group_id, $group_name) = $gr;
+          $row['group_names'][$group_id] = $group_name;
+        }
+      }
+      
+      echo enano_json_encode($row);
+      break;
+  }
+}
+
+function page_Admin_ThemeManagerOld() 
+{
+  global $db, $session, $paths, $template, $plugins; // Common objects
+  global $lang;
+  if ( $session->auth_level < USER_LEVEL_ADMIN || $session->user_level < USER_LEVEL_ADMIN )
+  {
+    $login_link = makeUrlNS('Special', 'Login/' . $paths->nslist['Special'] . 'Administration', 'level=' . USER_LEVEL_ADMIN, true);
+    echo '<h3>' . $lang->get('adm_err_not_auth_title') . '</h3>';
+    echo '<p>' . $lang->get('adm_err_not_auth_body', array( 'login_link' => $login_link )) . '</p>';
+    return;
+  }
+  
+  
+  // Get the list of styles in the themes/ dir
+  $h = opendir('./themes');
+  $l = Array();
+  if(!$h) die('Error opening directory "./themes" for reading.');
+  while(false !== ($n = readdir($h))) {
+    if($n != '.' && $n != '..' && is_dir('./themes/'.$n))
+      $l[] = $n;
+  }
+  closedir($h);
+  echo('
+  <h3>Theme Management</h3>
+   <p>Install, uninstall, and manage Enano themes.</p>
+  ');
+  if(isset($_POST['disenable'])) {
+    $q = 'SELECT enabled FROM '.table_prefix.'themes WHERE theme_id=\'' . $db->escape($_POST['theme_id']) . '\'';
+    $s = $db->sql_query($q);
+    if(!$s) die('Error selecting enabled/disabled state value: '.$db->get_error().'<br /><u>SQL:</u><br />'.$q);
+    $r = $db->fetchrow_num($s);
+    $db->free_result();
+    if($r[0] == 1) $e = 0;
+    else $e = 1;
+    $s=true;
+    if($e==0)
+    {
+      $c = $db->sql_query('SELECT * FROM '.table_prefix.'themes WHERE enabled=1');
+      if(!$c) $db->_die('The backup check for having at least on theme enabled failed.');
+      if($db->numrows() <= 1) { echo '<div class="warning-box">You cannot disable the last remaining theme.</div>'; $s=false; }
+    }
+    $db->free_result();
+    if($s) {
+    $q = 'UPDATE '.table_prefix.'themes SET enabled='.$e.' WHERE theme_id=\'' . $db->escape($_POST['theme_id']) . '\'';
+    $a = $db->sql_query($q);
+    if(!$a) die('Error updating enabled/disabled state value: '.$db->get_error().'<br /><u>SQL:</u><br />'.$q);
+    else echo('<div class="info-box">The theme "'.$_POST['theme_id'].'" has been  '. ( ( $e == '1' ) ? 'enabled' : 'disabled' ).'.</div>');
+    }
+  }
+  elseif(isset($_POST['edit'])) {
+    
+    $dir = './themes/'.$_POST['theme_id'].'/css/';
+    $list = Array();
+    // Open a known directory, and proceed to read its contents
+    if (is_dir($dir)) {
+      if ($dh = opendir($dir)) {
+        while (($file = readdir($dh)) !== false) {
+          if(preg_match('#^(.*?)\.css$#is', $file) && $file != '_printable.css') {
+            $list[$file] = capitalize_first_letter(substr($file, 0, strlen($file)-4));
+          }
+        }
+        closedir($dh);
+      }
+    }
+    $lk = array_keys($list);
+    
+    $q = 'SELECT theme_name,default_style FROM '.table_prefix.'themes WHERE theme_id=\''.$db->escape($_POST['theme_id']).'\'';
+    $s = $db->sql_query($q);
+    if(!$s) die('Error selecting name value: '.$db->get_error().'<br /><u>SQL:</u><br />'.$q);
+    $r = $db->fetchrow_num($s);
+    $db->free_result();
+    acp_start_form();
+    echo('<div class="question-box">
+          Theme name displayed to users: <input type="text" name="name" value="'.$r[0].'" /><br /><br />
+          Default stylesheet: <select name="defaultcss">');
+    foreach ($lk as $l)
+    {
+      if($r[1] == $l) $v = ' selected="selected"';
+      else $v = '';
+      echo "<option value='{$l}'$v>{$list[$l]}</option>";
+    }
+    echo('</select><br /><br />
+          <input type="submit" name="editsave" value="OK" /><input type="hidden" name="theme_id" value="'.$_POST['theme_id'].'" />
+          </div>');
+    echo('</form>');
+  }
+  elseif(isset($_POST['editsave'])) {
+    $q = 'UPDATE '.table_prefix.'themes SET theme_name=\'' . $db->escape($_POST['name']) . '\',default_style=\''.$db->escape($_POST['defaultcss']).'\' WHERE theme_id=\'' . $db->escape($_POST['theme_id']) . '\'';
+    $s = $db->sql_query($q);
+    if(!$s) die('Error updating name value: '.$db->get_error().'<br /><u>SQL:</u><br />'.$q);
+    else echo('<div class="info-box">Theme data updated.</div>');
+  }
+  elseif(isset($_POST['up'])) {
+    // If there is only one theme or if the selected theme is already at the top, do nothing
+    $q = 'SELECT theme_order FROM '.table_prefix.'themes ORDER BY theme_order;';
+    $s = $db->sql_query($q);
+    if(!$s) die('Error selecting order information: '.$db->get_error().'<br /><u>SQL:</u><br />'.$q);
+    $q = 'SELECT theme_order FROM '.table_prefix.'themes WHERE theme_id=\''.$db->escape($_POST['theme_id']).'\'';
+    $sn = $db->sql_query($q);
+    if(!$sn) die('Error selecting order information: '.$db->get_error().'<br /><u>SQL:</u><br />'.$q);
+    $r = $db->fetchrow_num($sn);
+    if( /* check for only one theme... */ $db->numrows($s) < 2 || $r[0] == 1 /* ...and check if this theme is already at the top */ ) { echo('<div class="warning-box">This theme is already at the top of the list, or there is only one theme installed.</div>'); } else {
+      // Get the order IDs of the selected theme and the theme before it
+      $q = 'SELECT theme_order FROM '.table_prefix.'themes WHERE theme_id=\'' . $db->escape($_POST['theme_id']) . '\'';
+      $s = $db->sql_query($q);
+      if(!$s) die('Error selecting order information: '.$db->get_error().'<br /><u>SQL:</u><br />'.$q);
+      $r = $db->fetchrow_num($s);
+      $r = $r[0];
+      $rb = $r - 1;
+      // Thank God for jEdit's rectangular selection and the ablity to edit multiple lines at the same time ;)
+      $q = 'UPDATE '.table_prefix.'themes SET theme_order=0 WHERE theme_order='.$rb.'';      /* Check for errors... <sigh> */ $s = $db->sql_query($q); if(!$s) die('Error updating order information: '.$db->get_error().'<br /><u>SQL:</u><br />'.$q);
+      $q = 'UPDATE '.table_prefix.'themes SET theme_order='.$rb.' WHERE theme_order='.$r.''; /* Check for errors... <sigh> */ $s = $db->sql_query($q); if(!$s) die('Error updating order information: '.$db->get_error().'<br /><u>SQL:</u><br />'.$q);
+      $q = 'UPDATE '.table_prefix.'themes SET theme_order='.$r.' WHERE theme_order=0';       /* Check for errors... <sigh> */ $s = $db->sql_query($q); if(!$s) die('Error updating order information: '.$db->get_error().'<br /><u>SQL:</u><br />'.$q);
+      echo('<div class="info-box">Theme moved up.</div>');
+    }
+    $db->free_result($s);
+    $db->free_result($sn);
+  }
+  elseif(isset($_POST['down'])) {
+    // If there is only one theme or if the selected theme is already at the top, do nothing
+    $q = 'SELECT theme_order FROM '.table_prefix.'themes ORDER BY theme_order;';
+    $s = $db->sql_query($q);
+    if(!$s) die('Error selecting order information: '.$db->get_error().'<br /><u>SQL:</u><br />'.$q);
+    $r = $db->fetchrow_num($s);
+    if( /* check for only one theme... */ $db->numrows($s) < 2 || $r[0] == $db->numrows($s) /* ...and check if this theme is already at the bottom */ ) { echo('<div class="warning-box">This theme is already at the bottom of the list, or there is only one theme installed.</div>'); } else {
+      // Get the order IDs of the selected theme and the theme before it
+      $q = 'SELECT theme_order FROM '.table_prefix.'themes WHERE theme_id=\''.$db->escape($_POST['theme_id']).'\'';
+      $s = $db->sql_query($q);
+      if(!$s) die('Error selecting order information: '.$db->get_error().'<br /><u>SQL:</u><br />'.$q);
+      $r = $db->fetchrow_num($s);
+      $r = $r[0];
+      $rb = $r + 1;
+      // Thank God for jEdit's rectangular selection and the ablity to edit multiple lines at the same time ;)
+      $q = 'UPDATE '.table_prefix.'themes SET theme_order=0 WHERE theme_order='.$rb.'';      /* Check for errors... <sigh> */ $s = $db->sql_query($q); if(!$s) die('Error updating order information: '.$db->get_error().'<br /><u>SQL:</u><br />'.$q);
+      $q = 'UPDATE '.table_prefix.'themes SET theme_order='.$rb.' WHERE theme_order='.$r.''; /* Check for errors... <sigh> */ $s = $db->sql_query($q); if(!$s) die('Error updating order information: '.$db->get_error().'<br /><u>SQL:</u><br />'.$q);
+      $q = 'UPDATE '.table_prefix.'themes SET theme_order='.$r.' WHERE theme_order=0';       /* Check for errors... <sigh> */ $s = $db->sql_query($q); if(!$s) die('Error updating order information: '.$db->get_error().'<br /><u>SQL:</u><br />'.$q);
+      echo('<div class="info-box">Theme moved down.</div>');
+    }
+  }
+  else if(isset($_POST['uninstall'])) 
+  {
+    $q = 'SELECT * FROM '.table_prefix.'themes;';
+    $s = $db->sql_query($q);
+    if ( !$s )
+    {
+      die('Error getting theme count: '.$db->get_error().'<br /><u>SQL:</u><br />'.$q);
+    }
+    $n = $db->numrows($s);
+    $db->free_result();
+    
+    if ( $_POST['theme_id'] == 'oxygen' )
+    {
+      echo '<div class="error-box">The Oxygen theme is used by Enano for installation, upgrades, and error messages, and cannot be uninstalled.</div>';
+    }
+    else
+    {
+      if($n < 2)
+      {
+        echo '<div class="error-box">The theme could not be uninstalled because it is the only theme left.</div>';
+      }
+      else
+      {
+        $q = 'DELETE FROM '.table_prefix.'themes WHERE theme_id=\''.$db->escape($_POST['theme_id']).'\' LIMIT 1;';
+        $s = $db->sql_query($q);
+        if ( !$s )
+        {
+          die('Error deleting theme data: '.$db->get_error().'<br /><u>SQL:</u><br />'.$q);
+        }
+        else
+        {
+          echo('<div class="info-box">Theme uninstalled.</div>');
+        }
+      }
+    }
+  }
+  elseif(isset($_POST['install'])) {
+    $q = 'SELECT theme_id FROM '.table_prefix.'themes;';
+    $s = $db->sql_query($q);
+    if(!$s) die('Error getting theme count: '.$db->get_error().'<br /><u>SQL:</u><br />'.$q);
+    $n = $db->numrows($s);
+    $n++;
+    $theme_id = $_POST['theme_id'];
+    $theme = Array();
+    include('./themes/'.$theme_id.'/theme.cfg');
+    if ( !isset($theme['theme_id']) )
+    {
+      echo '<div class="error-box">Could not load theme.cfg (theme metadata file)</div>';
+    }
+    else
+    {
+      $default_style = false;
+      if ( $dh = opendir('./themes/' . $theme_id . '/css') )
+      {
+        while ( $file = readdir($dh) )
+        {
+          if ( $file != '_printable.css' && preg_match('/\.css$/i', $file) )
+          {
+            $default_style = $file;
+            break;
+          }
+        }
+        closedir($dh);
+      }
+      else
+      {
+        die('The /css subdirectory could not be located in the theme\'s directory');
+      }
+      
+      if ( $default_style )
+      {
+        $q = 'INSERT INTO '.table_prefix.'themes(theme_id,theme_name,theme_order,enabled,default_style) VALUES(\''.$db->escape($theme['theme_id']).'\', \''.$db->escape($theme['theme_name']).'\', '.$n.', 1, \'' . $db->escape($default_style) . '\')';
+        $s = $db->sql_query($q);
+        if(!$s) die('Error inserting theme data: '.$db->get_error().'<br /><u>SQL:</u><br />'.$q);
+        else echo('<div class="info-box">Theme "'.$theme['theme_name'].'" installed.</div>');
+      }
+      else
+      {
+        echo '<div class="error-box">Could not determine the default style for the theme.</div>';
+      }
+    }
+  }
+  echo('
+  <h3>Currently installed themes</h3>
+    <form action="'.makeUrl($paths->nslist['Special'].'Administration', 'module='.$paths->cpage['module']).'" method="post">
+    <p>
+      <select name="theme_id">
+        ');
+        $q = 'SELECT theme_id,theme_name,enabled FROM '.table_prefix.'themes ORDER BY theme_order';
+        $s = $db->sql_query($q);
+        if(!$s) die('Error selecting theme data: '.$db->get_error().'<br /><u>Attempted SQL:</u><br />'.$q);
+        while ( $r = $db->fetchrow_num($s) ) {
+          if($r[2] < 1) $r[1] .= ' (disabled)';
+          echo('<option value="'.$r[0].'">'.$r[1].'</option>');
+        }
+        $db->free_result();
+        echo('
+        </select> <input type="submit" name="disenable" value="Enable/Disable" /> <input type="submit" name="edit" value="Change settings" /> <input type="submit" name="up" value="Move up" /> <input type="submit" name="down" value="Move down" /> <input type="submit" name="uninstall" value="Uninstall" style="color: #DD3300; font-weight: bold;" />
+      </p>
+    </form>
+    <h3>Install a new theme</h3>
+  ');
+    $theme = Array();
+    $obb = '';
+    for($i=0;$i<sizeof($l);$i++) {
+      if(is_file('./themes/'.$l[$i].'/theme.cfg') && file_exists('./themes/'.$l[$i].'/theme.cfg')) {
+        include('./themes/'.$l[$i].'/theme.cfg');
+        $q = 'SELECT * FROM '.table_prefix.'themes WHERE theme_id=\''.$theme['theme_id'].'\'';
+        $s = $db->sql_query($q);
+        if(!$s) die('Error selecting list of currently installed themes: '.$db->get_error().'<br /><u>Attempted SQL:</u><br />'.$q);
+        if($db->numrows($s) < 1) {
+          $obb .= '<option value="'.$theme['theme_id'].'">'.$theme['theme_name'].'</option>';
+        }
+        $db->free_result();
+      }
+    }
+    if($obb != '') {
+      echo('<form action="'.makeUrl($paths->nslist['Special'].'Administration', 'module='.$paths->cpage['module']).'" method="post"><p>');
+      echo('<select name="theme_id">');
+      echo($obb);
+      echo('</select>');
+      echo('
+      <input type="submit" name="install" value="Install this theme" />
+      </p></form>');
+    } else echo('<p>All themes are currently installed.</p>');
+}
--- a/plugins/admin/UserManager.php	Fri Feb 22 12:46:51 2008 -0500
+++ b/plugins/admin/UserManager.php	Fri Feb 22 12:51:53 2008 -0500
@@ -2,7 +2,7 @@
 
 /*
  * Enano - an open-source CMS capable of wiki functions, Drupal-like sidebar blocks, and everything in between
- * Version 1.0.3 (Dyrad)
+ * Version 1.1.2 (Caoineag alpha 2)
  * Copyright (C) 2006-2007 Dan Fuhry
  *
  * This program is Free Software; you can redistribute and/or modify it under the terms of the GNU General Public License
@@ -15,9 +15,12 @@
 function page_Admin_UserManager()
 {
   global $db, $session, $paths, $template, $plugins; // Common objects
+  global $lang;
   if ( $session->auth_level < USER_LEVEL_ADMIN || $session->user_level < USER_LEVEL_ADMIN )
   {
-    echo '<h3>Error: Not authenticated</h3><p>It looks like your administration session is invalid or you are not authorized to access this administration page. Please <a href="' . makeUrlNS('Special', 'Login/' . $paths->nslist['Special'] . 'Administration', 'level=' . USER_LEVEL_ADMIN, true) . '">re-authenticate</a> to continue.</p>';
+    $login_link = makeUrlNS('Special', 'Login/' . $paths->nslist['Special'] . 'Administration', 'level=' . USER_LEVEL_ADMIN, true);
+    echo '<h3>' . $lang->get('adm_err_not_auth_title') . '</h3>';
+    echo '<p>' . $lang->get('adm_err_not_auth_body', array( 'login_link' => $login_link )) . '</p>';
     return;
   }
   
@@ -33,7 +36,7 @@
     
     if ( defined('ENANO_DEMO_MODE') )
     {
-      $errors[] = 'Users cannot be modified or deleted in demo mode.';
+      $errors[] = $lang->get('acpum_err_nosave_demo');
     }
     
     $user_id = intval($_POST['user_id']);
@@ -48,7 +51,7 @@
       $q = $db->sql_query('DELETE FROM '.table_prefix."users WHERE user_id=$user_id;");
       if ( !$q )
         $db->_die();
-      echo '<div class="info-box">The user account has been deleted.</div>';
+      echo '<div class="info-box">' . $lang->get('acpum_msg_delete_success') . '</div>';
     }
     else
     {
@@ -63,7 +66,7 @@
       {
         $username = $_POST['username'];
         if ( !preg_match('#^'.$session->valid_username.'$#', $username) )
-          $errors[] = 'The username you entered contains invalid characters.';
+          $errors[] = $lang->get('acpum_err_illegal_username');
         
         $password = false;
         if ( $_POST['changing_pw'] == 'yes' )
@@ -79,13 +82,13 @@
           }
           else
           {
-            $errors[] = 'Session manager denied public encryption key lookup request';
+            $errors[] = $lang->get('acpum_err_no_aes_key');
           }
         }
         
         $email = $_POST['email'];
         if ( !preg_match('/^(?:[\w\d]+\.?)+@((?:(?:[\w\d]\-?)+\.)+\w{2,4}|localhost)$/', $email) )
-          $errors[] = 'You have entered an invalid e-mail address.';
+          $errors[] = $lang->get('acpum_err_illegal_email');
         
         $real_name = $_POST['real_name'];
       }
@@ -123,7 +126,7 @@
       
       if ( count($errors) < 1 )
       {
-        $q = $db->sql_query('SELECT u.user_level FROM '.table_prefix.'users AS u WHERE u.user_id = ' . $user_id . ';');
+        $q = $db->sql_query('SELECT u.user_level, u.user_has_avatar, u.avatar_type FROM '.table_prefix.'users AS u WHERE u.user_id = ' . $user_id . ';');
         if ( !$q )
           $db->_die();
         
@@ -134,8 +137,10 @@
         
         $row = $db->fetchrow();
         $existing_level =& $row['user_level'];
+        $avi_type =& $row['avatar_type'];
+        $has_avi = ( $row['user_has_avatar'] == 1 );
         $db->free_result();
-      
+        
         $to_update_users = array();
         if ( $user_id != $session->user_id )
         {
@@ -161,87 +166,238 @@
           $to_update_users['activation_key'] = sha1($session->dss_rand());
         }
         
-        $to_update_users_extra = array();
-        $to_update_users_extra['user_aim'] = $imaddr_aim;
-        $to_update_users_extra['user_msn'] = $imaddr_msn;
-        $to_update_users_extra['user_yahoo'] = $imaddr_yahoo;
-        $to_update_users_extra['user_xmpp'] = $imaddr_xmpp;
-        $to_update_users_extra['user_homepage'] = $homepage;
-        $to_update_users_extra['user_location'] = $location;
-        $to_update_users_extra['user_job'] = $occupation;
-        $to_update_users_extra['user_hobbies'] = $hobbies;
-        $to_update_users_extra['email_public'] = ( $email_public ) ? '1' : '0';
-        
-        $update_sql = '';
-        
-        foreach ( $to_update_users as $key => $unused_crap )
+        // Avatar validation
+        $action = ( isset($_POST['avatar_action']) ) ? $_POST['avatar_action'] : 'keep';
+        $avi_path = ENANO_ROOT . '/' . getConfig('avatar_directory') . '/' . $user_id . '.' . $avi_type;
+        switch($action)
         {
-          $value =& $to_update_users[$key];
-          $value = $db->escape($value);
-          $update_sql .= ( empty($update_sql) ? '' : ',' ) . "$key='$value'";
-        }
-        
-        $update_sql = 'UPDATE '.table_prefix."users SET $update_sql WHERE user_id=$user_id;";
-        
-        $update_sql_extra = '';
-        
-        foreach ( $to_update_users_extra as $key => $unused_crap )
-        {
-          $value =& $to_update_users_extra[$key];
-          $value = $db->escape($value);
-          $update_sql_extra .= ( empty($update_sql_extra) ? '' : ',' ) . "$key='$value'";
+          case 'keep':
+          default:
+            break;
+          case 'remove':
+            if ( $has_avi )
+            {
+              // First switch the avatar off
+              $to_update_users['user_has_avatar'] = '0';
+              @unlink($avi_path);
+            }
+            break;
+          case 'set_http':
+          case 'set_file':
+            // Hackish way to preserve the UNIX philosophy of reusing as much code as possible
+            if ( $action == 'set_http' )
+            {
+              // Check if this action is enabled
+              if ( getConfig('avatar_upload_http') !== '1' )
+              {
+                // non-localized, only appears on hack attempt
+                $errors[] = 'Uploads over HTTP are disabled.';
+                break;
+              }
+              // Download the file
+              require_once( ENANO_ROOT . '/includes/http.php' );
+              
+              if ( !preg_match('/^http:\/\/([a-z0-9-\.]+)(:([0-9]+))?\/(.+)$/', $_POST['avatar_http_url'], $match) )
+              {
+                $errors[] = $lang->get('usercp_avatar_invalid_url');
+                break;
+              }
+              
+              $hostname = $match[1];
+              $uri = '/' . $match[4];
+              $port = ( $match[3] ) ? intval($match[3]) : 80;
+              $max_size = intval(getConfig('avatar_max_size'));
+              
+              // Get temporary file
+              $tempfile = tempnam(false, "enanoavatar_{$user_id}");
+              if ( !$tempfile )
+                $errors[] = 'Error getting temp file.';
+              
+              @unlink($tempfile);
+              $request = new Request_HTTP($hostname, $uri, 'GET', $port);
+              $result = $request->write_response_to_file($tempfile, 50, $max_size);
+              if ( !$result || $request->response_code != HTTP_OK )
+              {
+                @unlink($tempfile);
+                $errors[] = $lang->get('usercp_avatar_bad_write');
+                break;
+              }
+              
+              // Response written. Proceed to validation...
+            }
+            else
+            {
+              // Check if this action is enabled
+              if ( getConfig('avatar_upload_file') !== '1' )
+              {
+                // non-localized, only appears on hack attempt
+                $errors[] = 'Uploads from the browser are disabled.';
+                break;
+              }
+              
+              $max_size = intval(getConfig('avatar_max_size'));
+              
+              $file =& $_FILES['avatar_file'];
+              $tempfile =& $file['tmp_name'];
+              if ( filesize($tempfile) > $max_size )
+              {
+                @unlink($tempfile);
+                $errors[] = $lang->get('usercp_avatar_file_too_large');
+                break;
+              }
+            }
+            $file_type = get_image_filetype($tempfile);
+            if ( !$file_type )
+            {
+              unlink($tempfile);
+              $errors[] = $lang->get('usercp_avatar_bad_filetype');
+              break;
+            }
+            
+            $avi_path_new = ENANO_ROOT . '/' . getConfig('avatar_directory') . '/' . $user_id . '.' . $file_type;
+            
+            // The file type is good - validate dimensions and animation
+            switch($file_type)
+            {
+              case 'png':
+                $is_animated = is_png_animated($tempfile);
+                $dimensions = png_get_dimensions($tempfile);
+                break;
+              case 'gif':
+                $is_animated = is_gif_animated($tempfile);
+                $dimensions = gif_get_dimensions($tempfile);
+                break;
+              case 'jpg':
+                $is_animated = false;
+                $dimensions = jpg_get_dimensions($tempfile);
+                break;
+              default:
+                $errors[] = 'API mismatch';
+                break 2;
+            }
+            // Did we get invalid size data? If so the image is probably corrupt.
+            if ( !$dimensions )
+            {
+              @unlink($tempfile);
+              $errors[] = $lang->get('usercp_avatar_corrupt_image');
+              break;
+            }
+            // Is the image animated?
+            if ( $is_animated && getConfig('avatar_enable_anim') !== '1' )
+            {
+              @unlink($tempfile);
+              $errors[] = $lang->get('usercp_avatar_disallowed_animation');
+              break;
+            }
+            // Check image dimensions
+            list($image_x, $image_y) = $dimensions;
+            $max_x = intval(getConfig('avatar_max_width'));
+            $max_y = intval(getConfig('avatar_max_height'));
+            if ( $image_x > $max_x || $image_y > $max_y )
+            {
+              @unlink($tempfile);
+              $errors[] = $lang->get('usercp_avatar_too_large');
+              break;
+            }
+            // All good!
+            @unlink($avi_path);
+            if ( rename($tempfile, $avi_path_new) )
+            {
+              $to_update_users['user_has_avatar'] = '1';
+              $to_update_users['avatar_type'] = $file_type;
+            }
+            else
+            {
+              // move failed - turn avatar off
+              $to_update_users['user_has_avatar'] = '0';
+            }
+            break;
         }
         
-        $update_sql_extra = 'UPDATE '.table_prefix."users_extra SET $update_sql_extra WHERE user_id=$user_id;";
-        
-        if ( !$db->sql_query($update_sql) )
-          $db->_die();
-        
-        if ( !$db->sql_query($update_sql_extra) )
-          $db->_die();
-        
-        if ( $existing_level != $user_level )
+        if ( count($errors) < 1 )
         {
-          // We need to update group memberships
-          if ( $existing_level == USER_LEVEL_ADMIN ) 
+          $to_update_users_extra = array();
+          $to_update_users_extra['user_aim'] = $imaddr_aim;
+          $to_update_users_extra['user_msn'] = $imaddr_msn;
+          $to_update_users_extra['user_yahoo'] = $imaddr_yahoo;
+          $to_update_users_extra['user_xmpp'] = $imaddr_xmpp;
+          $to_update_users_extra['user_homepage'] = $homepage;
+          $to_update_users_extra['user_location'] = $location;
+          $to_update_users_extra['user_job'] = $occupation;
+          $to_update_users_extra['user_hobbies'] = $hobbies;
+          $to_update_users_extra['email_public'] = ( $email_public ) ? '1' : '0';
+          
+          $update_sql = '';
+          
+          foreach ( $to_update_users as $key => $unused_crap )
           {
-            $q = $db->sql_query('INSERT INTO '.table_prefix.'logs(log_type,action,time_id,edit_summary,author,page_text) VALUES(\'security\',\'u_from_admin\',' . time() . ',"' . $db->escape($_SERVER['REMOTE_ADDR']) . '","' . $db->escape($session->username) . '","' . $db->escape($username) . '");');
-            if ( !$q )
-              $db->_die();
-            $session->remove_user_from_group($user_id, GROUP_ID_ADMIN);
+            $value =& $to_update_users[$key];
+            $value = $db->escape($value);
+            $update_sql .= ( empty($update_sql) ? '' : ',' ) . "$key='$value'";
           }
-          else if ( $existing_level == USER_LEVEL_MOD ) 
+          
+          $update_sql = 'UPDATE '.table_prefix."users SET $update_sql WHERE user_id=$user_id;";
+          
+          $update_sql_extra = '';
+          
+          foreach ( $to_update_users_extra as $key => $unused_crap )
           {
-            $q = $db->sql_query('INSERT INTO '.table_prefix.'logs(log_type,action,time_id,edit_summary,author,page_text) VALUES(\'security\',\'u_from_mod\',' . time() . ',"' . $db->escape($_SERVER['REMOTE_ADDR']) . '","' . $db->escape($session->username) . '","' . $db->escape($username) . '");');
-            if ( !$q )
-              $db->_die();
-            $session->remove_user_from_group($user_id, GROUP_ID_MOD);
+            $value =& $to_update_users_extra[$key];
+            $value = $db->escape($value);
+            $update_sql_extra .= ( empty($update_sql_extra) ? '' : ',' ) . "$key='$value'";
           }
           
-          if ( $user_level == USER_LEVEL_ADMIN )
-          {
-            $q = $db->sql_query('INSERT INTO '.table_prefix.'logs(log_type,action,time_id,edit_summary,author,page_text) VALUES(\'security\',\'u_to_admin\',' . time() . ',"' . $db->escape($_SERVER['REMOTE_ADDR']) . '","' . $db->escape($session->username) . '","' . $db->escape($username) . '");');
-            if ( !$q )
-              $db->_die();
-            $session->add_user_to_group($user_id, GROUP_ID_ADMIN, false);
-          }
-          else if ( $user_level == USER_LEVEL_MOD )
+          $update_sql_extra = 'UPDATE '.table_prefix."users_extra SET $update_sql_extra WHERE user_id=$user_id;";
+          
+          if ( !$db->sql_query($update_sql) )
+            $db->_die();
+          
+          if ( !$db->sql_query($update_sql_extra) )
+            $db->_die();
+          
+          if ( $existing_level != $user_level )
           {
-            $q = $db->sql_query('INSERT INTO '.table_prefix.'logs(log_type,action,time_id,edit_summary,author,page_text) VALUES(\'security\',\'u_to_mod\',' . time() . ',"' . $db->escape($_SERVER['REMOTE_ADDR']) . '","' . $db->escape($session->username) . '","' . $db->escape($username) . '");');
-            if ( !$q )
-              $db->_die();
-            $session->add_user_to_group($user_id, GROUP_ID_MOD, false);
+            // We need to update group memberships
+            if ( $existing_level == USER_LEVEL_ADMIN ) 
+            {
+              $q = $db->sql_query('INSERT INTO '.table_prefix.'logs(log_type,action,time_id,edit_summary,author,page_text) VALUES(\'security\',\'u_from_admin\',' . time() . ',"' . $db->escape($_SERVER['REMOTE_ADDR']) . '","' . $db->escape($session->username) . '","' . $db->escape($username) . '");');
+              if ( !$q )
+                $db->_die();
+              $session->remove_user_from_group($user_id, GROUP_ID_ADMIN);
+            }
+            else if ( $existing_level == USER_LEVEL_MOD ) 
+            {
+              $q = $db->sql_query('INSERT INTO '.table_prefix.'logs(log_type,action,time_id,edit_summary,author,page_text) VALUES(\'security\',\'u_from_mod\',' . time() . ',"' . $db->escape($_SERVER['REMOTE_ADDR']) . '","' . $db->escape($session->username) . '","' . $db->escape($username) . '");');
+              if ( !$q )
+                $db->_die();
+              $session->remove_user_from_group($user_id, GROUP_ID_MOD);
+            }
+            
+            if ( $user_level == USER_LEVEL_ADMIN )
+            {
+              $q = $db->sql_query('INSERT INTO '.table_prefix.'logs(log_type,action,time_id,edit_summary,author,page_text) VALUES(\'security\',\'u_to_admin\',' . time() . ',"' . $db->escape($_SERVER['REMOTE_ADDR']) . '","' . $db->escape($session->username) . '","' . $db->escape($username) . '");');
+              if ( !$q )
+                $db->_die();
+              $session->add_user_to_group($user_id, GROUP_ID_ADMIN, false);
+            }
+            else if ( $user_level == USER_LEVEL_MOD )
+            {
+              $q = $db->sql_query('INSERT INTO '.table_prefix.'logs(log_type,action,time_id,edit_summary,author,page_text) VALUES(\'security\',\'u_to_mod\',' . time() . ',"' . $db->escape($_SERVER['REMOTE_ADDR']) . '","' . $db->escape($session->username) . '","' . $db->escape($username) . '");');
+              if ( !$q )
+                $db->_die();
+              $session->add_user_to_group($user_id, GROUP_ID_MOD, false);
+            }
           }
+          
+          echo '<div class="info-box">' . $lang->get('acpum_msg_save_success') . '</div>';
         }
-        
-        echo '<div class="info-box">Your changes have been saved.</div>';
       }
     }
     
     if ( count($errors) > 0 )
     {
       echo '<div class="error-box">
-              <b>Your request could not be processed due to the following validation errors:</b>
+              <b>' . $lang->get('acpum_err_validation_fail') . '</b>
               <ul>
                 <li>' . implode("</li>\n        <li>", $errors) . '</li>
               </ul>
@@ -267,6 +423,10 @@
         );
       $form->email_public = ( isset($_POST['email_public']) );
       $form->account_active = ( isset($_POST['account_active']) );
+      // This is SAFE. The smartform calls is_valid_ip() on this value, thus preventing XSS
+      // attempts from making it into the form HTML. Badly coded templates may still be
+      // affected, but if have_reg_ip is checked for, then you're fine.
+      $form->reg_ip_addr = $_POST['user_registration_ip'];
       echo $form->render();
       return false;
     }
@@ -290,7 +450,7 @@
       echo 'No username provided';
       return false;
     }
-    $q = $db->sql_query('SELECT u.user_id AS authoritative_uid, u.username, u.email, u.real_name, u.signature, u.account_active, u.user_level, x.* FROM '.table_prefix.'users AS u
+    $q = $db->sql_query('SELECT u.user_id AS authoritative_uid, u.username, u.email, u.real_name, u.signature, u.account_active, u.user_level, u.user_has_avatar, u.avatar_type, u.user_registration_ip, x.* FROM '.table_prefix.'users AS u
                            LEFT JOIN '.table_prefix.'users_extra AS x
                              ON ( u.user_id = x.user_id OR x.user_id IS NULL )
                            WHERE ( ' . ENANO_SQLFUNC_LOWERCASE . '(u.username) = \'' . $db->escape(strtolower($username)) . '\' OR u.username = \'' . $db->escape($username) . '\' ) AND u.user_id != 1;');
@@ -299,7 +459,7 @@
     
     if ( $db->numrows() < 1 )
     {
-      echo '<div class="error-box">The username you entered could not be found.</div>';
+      echo '<div class="error-box">' . $lang->get('acpum_err_bad_username') . '</div>';
     }
     else
     {
@@ -314,6 +474,8 @@
       $form->user_level= $row['user_level'];
       $form->account_active = ( $row['account_active'] == 1 );
       $form->email_public   = ( $row['email_public'] == 1 );
+      $form->has_avatar     = ( $row['user_has_avatar'] == 1 );
+      $form->avi_type       = $row['avatar_type'];
       $form->im = array(
           'aim' => $row['user_aim'],
           'yahoo' => $row['user_yahoo'],
@@ -327,6 +489,7 @@
           'hobbies'  => $row['user_hobbies'],
         );
       $form->email_public = ( $row['email_public'] == 1 );
+      $form->reg_ip_addr = ( $row['user_registration_ip'] ) ? $row['user_registration_ip'] : '';
       $html = $form->render();
       if ( !$html )
       {
@@ -343,7 +506,7 @@
   {
     if ( defined('ENANO_DEMO_MODE') )
     {
-      echo '<div class="error-box">Sorry Charlie, no can do. You might mess up other people logged into the demo site.</div>';
+      echo '<div class="error-box">' . $lang->get('acpum_err_sessionclear_demo') . '</div>';
     }
     else
     {
@@ -376,27 +539,27 @@
       $db->sql_query('DELETE FROM '.table_prefix.'session_keys;');
       $db->sql_query('INSERT INTO '.table_prefix.'session_keys( session_key,salt,user_id,auth_level,source_ip,time ) VALUES( \''.$ra['session_key'].'\', \''.$ra['salt'].'\', \''.$session->user_id.'\', \''.$ra['auth_level'].'\', \''.$ra['source_ip'].'\', '.$ra['time'].' ),( \''.$rb['session_key'].'\', \''.$rb['salt'].'\', \''.$session->user_id.'\', \''.$rb['auth_level'].'\', \''.$rb['source_ip'].'\', '.$rb['time'].' )');
       
-      echo '<div class="info-box">The session key table has been cleared. Your database should be a little bit smaller now.</div>';
+      echo '<div class="info-box">' . $lang->get('acpum_msg_sessionclear_success') . '</div>';
     }
   }
   echo '<form action="' . makeUrlNS('Special', 'Administration', 'module=' . $paths->cpage['module'], true) . '" method="post" enctype="multipart/form-data" onsubmit="if ( !submitAuthorized ) return false;">';
-  echo '<h3>User administration panel</h3>';
-  echo '<p>From this panel you can modify or delete user accounts.</p>';
+  echo '<h3>' . $lang->get('acpum_heading_main') . '</h3>';
+  echo '<p>' . $lang->get('acpum_hint_intro') . '</p>';
   echo '<table border="0">
           <tr>
-            <td><b>Search for user:</b><br />
-                <small>If your browser supports AJAX, this will provide suggestions for you.</small>
+            <td><b>' . $lang->get('acpum_field_search_user') . '</b><br />
+                <small>' . $lang->get('acpum_field_search_user_hint') . '</small>
                 </td>
             <td style="width: 10px;"></td>
             <td>' . $template->username_field('username') . '</td>
             <td>
-              <input type="submit" name="action[go]" value="Go &raquo;" />
+              <input type="submit" name="action[go]" value="' . $lang->get('acpum_btn_search_user_go') . ' &raquo;" />
             </td>
           </tr>
         </table>';
-  echo '<h3>Clear session key table</h3>';
-  echo '<p>It\'s a good idea to clean out your session keys table every once in a while, since this helps to reduce database size. During this process you will be logged off and (hopefully) logged back on automatically. If you do this, all users besides you will be logged off, so be sure to do this at a time when traffic is low.</p>';
-  echo '<p><input type="submit" name="action[clear_sessions]" value="Clear session keys" /></p>';
+  echo '<h3>' . $lang->get('acpum_heading_clear_sessions') . '</h3>';
+  echo '<p>' . $lang->get('acpum_hint_clear_sessions') . '</p>';
+  echo '<p><input type="submit" name="action[clear_sessions]" value="' . $lang->get('acpum_btn_clear_sessions') . '" /></p>';
   echo '</form>';
   
   if(isset($_GET['action']) && isset($_GET['user']))
@@ -405,22 +568,47 @@
     {
       case "activate":
         $e = $db->sql_query('SELECT activation_key FROM '.table_prefix.'users WHERE username=\'' . $db->escape($_GET['user']) . '\'');
-        if($e)
+        if ( $e )
         {
+          // attempt to activate the account
           $row = $db->fetchrow();
           $db->free_result();
-          if($session->activate_account($_GET['user'], $row['activation_key'])) { echo '<div class="info-box">The user account "'.$_GET['user'].'" has been activated.</div>'; $db->sql_query('DELETE FROM '.table_prefix.'logs WHERE time_id=' . $db->escape($_GET['logid'])); }
-          else echo '<div class="warning-box">The user account "'.$_GET['user'].'" has NOT been activated, possibly because the account is already active.</div>';
-        } else echo '<div class="error-box">Error activating account: '.mysql_error().'</div>';
+          if ( $session->activate_account($_GET['user'], $row['activation_key']) )
+          {
+            echo '<div class="info-box">' . $lang->get('acpum_msg_activate_success', array('username' => htmlspecialchars($_GET['user']))) . '</div>';
+            $db->sql_query('DELETE FROM '.table_prefix.'logs WHERE time_id=' . $db->escape($_GET['logid']));
+          }
+          else
+          {
+            echo '<div class="warning-box">' . $lang->get('acpum_err_activate_fail', array('username' => htmlspecialchars($_GET['user']))) . '</div>';
+          }
+        }
+        else
+        {
+          echo '<div class="error-box">Error activating account: '.$db->get_error().'</div>';
+        }
         break;
       case "sendemail":
-        if($session->send_activation_mail($_GET['user'])) { echo '<div class="info-box">The user "'.$_GET['user'].'" has been sent an e-mail with an activation link.</div>'; $db->sql_query('DELETE FROM '.table_prefix.'logs WHERE time_id=' . $db->escape($_GET['logid'])); }
-        else echo '<div class="error-box">The user account "'.$_GET['user'].'" has not been activated, probably because of a bad SMTP configuration.</div>';
+        if ( $session->send_activation_mail($_GET['user'] ) )
+        {
+          echo '<div class="info-box">' . $lang->get('acpum_msg_activate_email_success', array('username' => htmlspecialchars($_GET['user']))) . '</div>';
+          $db->sql_query('DELETE FROM '.table_prefix.'logs WHERE time_id=' . $db->escape($_GET['logid']));
+        }
+        else
+        {
+          echo '<div class="error-box">' . $lang->get('acpum_err_activate_email_fail', array('username' => htmlspecialchars($_GET['user']))) . '</div>';
+        }
         break;
       case "deny":
-        $e = $db->sql_query('DELETE FROM '.table_prefix.'logs WHERE log_type=\'admin\' AND action=\'activ_req\' AND edit_summary=\'' . $db->escape($_GET['user']) . '\';');
-        if(!$e) echo '<div class="error-box">Error during row deletion: '.mysql_error().'</div>';
-        else echo '<div class="info-box">All activation requests for the user "'.$_GET['user'].'" have been deleted.</div>';
+        $e = $db->sql_query('DELETE FROM '.table_prefix.'logs WHERE log_type=\'admin\' AND action=\'activ_req\' AND time_id=\'' . $db->escape($_GET['logid']) . '\';');
+        if ( !$e )
+        {
+          echo '<div class="error-box">Error during row deletion: '.$db->get_error().'</div>';
+        }
+        else
+        {
+          echo '<div class="info-box">' . $lang->get('acpum_msg_activate_deny_success', array('username' => htmlspecialchars($_GET['user']))) . '</div>';
+        }
         break;
     }
   }
@@ -433,19 +621,42 @@
     if($db->numrows() > 0)
     {
       $n = $db->numrows();
-      if($n == 1) $s = $n . ' user is';
-      else $s = $n . ' users are';
-      echo '<h3>'.$s . ' awaiting account activation</h3>';
+      $str = ( $n == 1 ) ?
+        $lang->get('acpum_heading_activation_one') :
+        $lang->get('acpum_heading_activation_plural', array('count' => strval($n)));
+        
+      echo '<h3>' . $str . '</h3>';
+        
       echo '<div class="tblholder">
-            <table border="0" cellspacing="1" cellpadding="4" width="100%">
-            <tr><th>Date of request</th><th>Requested by</th><th>Requested for</th><th>COPPA user</th><th colspan="3">Actions</th></tr>';
+              <table border="0" cellspacing="1" cellpadding="4" width="100%">
+                <tr>
+                  <th>' . $lang->get('acpum_col_activate_timestamp') . '</th>
+                  <th>' . $lang->get('acpum_col_activate_requestedby') . '</th>
+                  <th>' . $lang->get('acpum_col_activate_requestedfor') . '</th>
+                  <th>' . $lang->get('acpum_col_activate_coppauser') . '</th>
+                  <th colspan="3">' . $lang->get('acpum_col_activate_actions') . '</th>
+                </tr>';
       $cls = 'row2';
       while($row = $db->fetchrow())
       {
         if($cls == 'row2') $cls = 'row1';
         else $cls = 'row2';
-        $coppa = ( $row['user_coppa'] == '1' ) ? '<b>Yes</b>' : 'No';
-        echo '<tr><td class="'.$cls.'">'.date('F d, Y h:i a', $row['time_id']).'</td><td class="'.$cls.'">'.$row['author'].'</td><td class="'.$cls.'">'.$row['edit_summary'].'</td><td style="text-align: center;" class="' . $cls . '">' . $coppa . '</td><td class="'.$cls.'" style="text-align: center;"><a href="'.makeUrlNS('Special', 'Administration', 'module='.$paths->nslist['Admin'].'UserManager&amp;action=activate&amp;user='.$row['edit_summary'].'&amp;logid='.$row['time_id']).'">Activate now</a></td><td class="'.$cls.'" style="text-align: center;"><a href="'.makeUrlNS('Special', 'Administration', 'module='.$paths->nslist['Admin'].'UserManager&amp;action=sendemail&amp;user='.$row['edit_summary'].'&amp;logid='.$row['time_id']).'">Send activation e-mail</a></td><td class="'.$cls.'" style="text-align: center;"><a href="'.makeUrlNS('Special', 'Administration', 'module='.$paths->nslist['Admin'].'UserManager&amp;action=deny&amp;user='.$row['edit_summary'].'&amp;logid='.$row['time_id']).'">Deny request</a></td></tr>';
+        $coppa = ( $row['user_coppa'] == '1' ) ? '<b>' . $lang->get('acpum_coppauser_yes') . '</b>' : $lang->get('acpum_coppauser_no');
+        echo '<tr>
+                <td class="'.$cls.'">'.enano_date('F d, Y h:i a', $row['time_id']).'</td>
+                <td class="'.$cls.'">'.$row['author'].'</td>
+                <td class="'.$cls.'">'.$row['edit_summary'].'</td>
+                <td style="text-align: center;" class="' . $cls . '">' . $coppa . '</td>
+                <td class="'.$cls.'" style="text-align: center;">
+                  <a href="'.makeUrlNS('Special', 'Administration', 'module='.$paths->nslist['Admin'].'UserManager&action=activate&user='.rawurlencode($row['edit_summary']).'&logid='.$row['time_id'], true).'">' . $lang->get('acpum_btn_activate_now') . '</a>
+                </td>
+                <td class="'.$cls.'" style="text-align: center;">
+                  <a href="'.makeUrlNS('Special', 'Administration', 'module='.$paths->nslist['Admin'].'UserManager&action=sendemail&user='.rawurlencode($row['edit_summary']).'&logid='.$row['time_id'], true).'">' . $lang->get('acpum_btn_send_email') . '</a>
+                </td>
+                <td class="'.$cls.'" style="text-align: center;">
+                  <a href="'.makeUrlNS('Special', 'Administration', 'module='.$paths->nslist['Admin'].'UserManager&action=deny&user='.rawurlencode($row['edit_summary']).'&logid='.$row['time_id'], true).'">' . $lang->get('acpum_btn_activate_deny') . '</a>
+                </td>
+              </tr>';
       }
       echo '</table>';
     }
@@ -541,6 +752,27 @@
   var $email_public = false;
   
   /**
+   * Whether the user has an avatar or not.
+   * @var bool
+   */
+  
+  var $has_avatar = false;
+  
+  /**
+   * The type of avatar the user has. One of "jpg", "png", or "gif".
+   * @var string
+   */
+  
+  var $avi_type = 'png';
+  
+  /**
+   * The IP address of the user during registration
+   * @var string
+   */
+  
+  var $reg_ip_addr = '';
+  
+  /**
    * Constructor.
    */
   
@@ -557,6 +789,7 @@
   function render()
   {
     global $db, $session, $paths, $template, $plugins; // Common objects
+    global $lang;
     if ( file_exists( ENANO_ROOT . "/themes/$template->theme/admin_usermanager_form.tpl" ) )
     {
       $parser = $template->makeParser('admin_usermanager_form.tpl');
@@ -595,7 +828,7 @@
             {
               if ( form.new_password.value != form.new_password_confirm.value )
               {
-                alert('The passwords you entered did not match.');
+                alert(\$lang.get('user_reg_err_alert_password_nomatch'));
                 return false;
               }
               form.new_password_confirm.value = '';
@@ -617,7 +850,7 @@
             
               <tr>
                 <th colspan="2">
-                  Editing user: {USERNAME}
+                  {lang:acpum_heading_editing_user} {USERNAME}
                 </th>
               </tr>
               
@@ -625,35 +858,36 @@
               
                 <tr>
                   <th colspan="2" class="subhead">
-                    Basic options
+                    {lang:acpum_heading_basic_options}
                   </th>
                 </tr>
                 
                 <tr>
                   <td class="row2" style="width: 25%;">
-                    Username:<br />
-                    <small>Must be at least 2 characters in length</small>
+                    {lang:acpum_field_username}<br />
+                    <small>{lang:acpum_field_username_hint}</small>
                   </td>
                   <td class="row1" style="width: 75%;">
-                    <input type="text" name="username" value="{USERNAME}" size="40" <!-- BEGIN same_user -->disabled="disabled" <!-- END same_user -->/><!-- BEGIN same_user --> <small>You cannot change your own username. To change your username you must log into a different administrative account.</small><!-- END same_user -->
+                    <input type="text" name="username" value="{USERNAME}" size="40" <!-- BEGIN same_user -->disabled="disabled" <!-- END same_user -->/>
+                    <!-- BEGIN same_user --><small>{lang:acpum_msg_same_user_username}</small><!-- END same_user -->
                   </td>
                 </tr>
                 
                 <tr>
                   <td class="row2">
-                    Password:
+                    {lang:acpum_field_password}
                     <!-- BEGIN password_meter -->
                     <br />
-                    <small>Password strength requirements are not enforced here.</small>
+                    <small>{lang:acpum_field_password_hint}</small>
                     <!-- END password_meter -->
                   </td>
                   <td class="row1">
                     <div id="userform_{UUID}_pwlink">
-                      <b>Password will be left unchanged.</b> <a href="#" onclick="userform_{UUID}_chpasswd(); return false;">Reset password...</a>
+                      <b>{lang:acpum_msg_password_unchanged}</b> <a href="#" onclick="userform_{UUID}_chpasswd(); return false;">{lang:acpum_btn_reset_password}</a>
                     </div>
                     <div id="userform_{UUID}_pwform" style="display: none;">
                       <!-- BEGIN same_user -->
-                      To change your password, please use the user preferences panel. <a href="#" onclick="userform_{UUID}_chpasswd_cancel(); return false;">Cancel</a>
+                        {lang:acpum_msg_same_user_password} <a href="#" onclick="userform_{UUID}_chpasswd_cancel(); return false;">{lang:etc_cancel}</a>
                       <!-- BEGINELSE same_user -->
                       <input type="hidden" name="changing_pw" value="no" />
                       <input type="hidden" name="challenge_data" value="{MD5_CHALLENGE}" />
@@ -663,24 +897,24 @@
                       <table border="0" style="background-color: transparent;" cellspacing="0" cellpadding="0">
                         <tr>
                           <td colspan="2">
-                            <b>Change password to:</b>
+                            <b>{lang:acpum_field_password_title}</b>
                           </td>
                         </tr>
                         <tr>
-                          <td>New password:</td>
-                          <td><input type="password" name="new_password" value="" <!-- BEGIN password_meter -->onkeyup="password_score_field(this);" /><span class="password-checker" style="font-weight: bold; color: #AA0000"> Weak (score: -10)</span><!-- BEGINELSE password_meter --> /><!-- END password_meter -->
+                          <td>{lang:acpum_field_newpassword}</td>
+                          <td><input type="password" name="new_password" value="" <!-- BEGIN password_meter -->onkeyup="password_score_field(this);" /><span class="password-checker" style="font-weight: bold; color: #A0A0A0"> Waiting for l10n init</span><!-- BEGINELSE password_meter --> /><!-- END password_meter -->
                             <!-- BEGIN password_meter -->
                               <div id="pwmeter" style="margin: 4px 0; height: 8px;"></div>
                             <!-- END password_meter -->
                           </td>
                         </tr>
                         <tr>
-                          <td>Confirm:</td>
+                          <td>{lang:acpum_field_newpassword_confirm}</td>
                           <td><input type="password" name="new_password_confirm" value="" /></td>
                         </tr>
                         <tr>
                           <td colspan="2">
-                            <a href="#" onclick="userform_{UUID}_chpasswd_cancel(); return false;">Cancel</a>
+                            <a href="#" onclick="userform_{UUID}_chpasswd_cancel(); return false;">{lang:etc_cancel}</a>
                           </td>
                         </tr>
                       </table>
@@ -691,25 +925,27 @@
                 
                 <tr>
                   <td class="row2" style="width: 25%;">
-                    E-mail address:
+                    {lang:acpum_field_email}
                   </td>
                   <td class="row1" style="width: 75%;">
-                    <input type="text" name="email" value="{EMAIL}" size="40" <!-- BEGIN same_user -->disabled="disabled" <!-- END same_user -->/><!-- BEGIN same_user --> <small>To change your e-mail address, please use the user preferences panel.</small><!-- END same_user -->
+                    <input type="text" name="email" value="{EMAIL}" size="40" <!-- BEGIN same_user -->disabled="disabled" <!-- END same_user -->/>
+                    <!-- BEGIN same_user --><small>{lang:acpum_msg_same_user_email}</small><!-- END same_user -->
                   </td>
                 </tr>
                 
                 <tr>
                   <td class="row2" style="width: 25%;">
-                    Real name:
+                    {lang:acpum_field_realname}
                   </td>
                   <td class="row1" style="width: 75%;">
-                    <input type="text" name="real_name" value="{REAL_NAME}" size="40" <!-- BEGIN same_user -->disabled="disabled" <!-- END same_user -->/><!-- BEGIN same_user --> <small>To change your real name on file, please use the user preferences panel.</small><!-- END same_user -->
+                    <input type="text" name="real_name" value="{REAL_NAME}" size="40" <!-- BEGIN same_user -->disabled="disabled" <!-- END same_user -->/>
+                    <!-- BEGIN same_user --><small>{lang:acpum_msg_same_user_realname}</small><!-- END same_user -->
                   </td>
                 </tr>
                 
                 <tr>
                   <td class="row2" style="width: 25%;">
-                    Signature:
+                    {lang:acpum_field_signature}
                   </td>
                   <td class="row1" style="width: 75%;">
                     {SIGNATURE_FIELD}
@@ -722,94 +958,171 @@
               
                 <tr>
                   <th class="subhead" colspan="2">
-                    Instant messenger contact information
+                    {lang:acpum_heading_imcontact}
                   </th>
                 <tr>
-                  <td class="row2">AIM handle:</td>
+                  <td class="row2">{lang:acpum_field_aim}</td>
                   <td class="row1"><input type="text" name="imaddr_aim" value="{IM_AIM}" size="30" /></td>
                 </tr>
                 <tr>
-                  <td class="row2"><acronym title="Windows&trade; Live Messenger">WLM</acronym> handle:<br /><small>If you don't specify the domain (@whatever.com), "@hotmail.com" will be assumed.</small></td>
+                  <td class="row2">{lang:acpum_field_wlm}<br /><small>{lang:acpum_field_wlm_hint}</small></td>
                   <td class="row1"><input type="text" name="imaddr_msn" value="{IM_WLM}" size="30" /></td>
                 </tr>
                 <tr>
-                  <td class="row2">Yahoo! IM handle:</td>
+                  <td class="row2">{lang:acpum_field_yim}</td>
                   <td class="row1"><input type="text" name="imaddr_yahoo" value="{IM_YAHOO}" size="30" /></td>
                 </tr>
                 <tr>
-                  <td class="row2">Jabber/XMPP handle:</td>
+                  <td class="row2">{lang:acpum_field_xmpp}</td>
                   <td class="row1"><input type="text" name="imaddr_xmpp" value="{IM_XMPP}" size="30" /></td>
                 </tr>
                 <tr>
                   <th class="subhead" colspan="2">
-                    Extra contact information
+                    {lang:acpum_heading_contact_extra}
                   </th>
                 </tr>
                 <tr>
-                  <td class="row2">Homepage:<br /><small>Please remember the http:// prefix.</small></td>
+                  <td class="row2">{lang:acpum_field_homepage}<br /><small>{lang:acpum_field_homepage_hint}</small></td>
                   <td class="row1"><input type="text" name="homepage" value="{HOMEPAGE}" size="30" /></td>
                 </tr>
                 <tr>
-                  <td class="row2">Location:</td>
+                  <td class="row2">{lang:acpum_field_location}</td>
                   <td class="row1"><input type="text" name="location" value="{LOCATION}" size="30" /></td>
                 </tr>
                 <tr>
-                  <td class="row2">Job:</td>
+                  <td class="row2">{lang:acpum_field_job}</td>
                   <td class="row1"><input type="text" name="occupation" value="{JOB}" size="30" /></td>
                 </tr>
                 <tr>
-                  <td class="row2">Hobbies:</td>
+                  <td class="row2">{lang:acpum_field_hobbies}</td>
                   <td class="row1"><input type="text" name="hobbies" value="{HOBBIES}" size="30" /></td>
                 </tr>
                 <tr>
-                  <td class="row2"><label for="chk_email_public_{UUID}">E-mail address is public</label><br /><small>If this is checked, the user's e-mail address will be displayed on your the page. To protect the address from spambots, it will be encrypted.</small></td>
+                  <td class="row2"><label for="chk_email_public_{UUID}">{lang:acpum_field_email_public}</label><br /><small>{lang:acpum_field_email_public_hint}</small></td>
                   <td class="row1"><input type="checkbox" id="chk_email_public_{UUID}" name="email_public" <!-- BEGIN email_public -->checked="checked" <!-- END email_public -->size="30" /></td>
                 </tr>
               
               <!-- / Extended options -->
               
-              <!-- Administrator-only options -->
+              <!-- Avatar settings -->
               
                 <tr>
                   <th class="subhead" colspan="2">
-                    Administrator-only options
+                    {lang:acpum_avatar_heading}
                   </th>
                 </tr>
                 
                 <tr>
-                  <td class="row2">User account is active<br />
-                                   <small>If this is unchecked, the existing activation key will be overwritten in the database, thus invalidating any activation e-mails sent to the user.</small>
-                                   </td>
-                  <td class="row1"><label><input type="checkbox" name="account_active" <!-- BEGIN account_active -->checked="checked" <!-- END account_active -->/> Account is active and enabled</label></td>
-                </tr>
-                
-                <tr>
                   <td class="row2">
-                    User's site access level<br />
-                    <small>If this is changed, the relevant group memberships will be updated accordingly.</small>
+                    {lang:usercp_avatar_label_current}
                   </td>
                   <td class="row1">
-                    <select name="user_level">
-                      <option value="{USER_LEVEL_MEMBER}"<!-- BEGIN ul_member --> selected="selected"<!-- END ul_member -->>Normal member</option>
-                      <option value="{USER_LEVEL_MOD}"<!-- BEGIN ul_mod --> selected="selected"<!-- END ul_mod -->>Moderator</option>
-                      <option value="{USER_LEVEL_ADMIN}"<!-- BEGIN ul_admin --> selected="selected"<!-- END ul_admin -->>Site administrator</option>
-                    </select>
+                    <!-- BEGIN user_has_avatar -->
+                      <img alt="{AVATAR_ALT}" src="{AVATAR_SRC}" />
+                    <!-- BEGINELSE user_has_avatar -->
+                      {lang:acpum_avatar_image_none}
+                    <!-- END user_has_avatar -->
                   </td>
                 </tr>
                 
                 <tr>
                   <td class="row2">
-                    Delete user account
+                    {lang:acpum_avatar_lbl_change}
                   </td>
                   <td class="row1">
-                    <label><input type="checkbox" name="delete_account" onclick="var d = (this.checked) ? 'block' : 'none'; document.getElementById('delete_blurb_{UUID}').style.display = d;" /> Permanently delete this user account when I click Save</label>
+                    <script type="text/javascript">
+                      function admincp_users_avatar_set_{UUID}(obj)
+                      {
+                        switch(obj.value)
+                        {
+                          case 'keep':
+                          case 'remove':
+                            $('avatar_upload_http_{UUID}').object.style.display = 'none';
+                            $('avatar_upload_file_{UUID}').object.style.display = 'none';
+                            break;
+                          case 'set_http':
+                            $('avatar_upload_http_{UUID}').object.style.display = 'block';
+                            $('avatar_upload_file_{UUID}').object.style.display = 'none';
+                            break;
+                          case 'set_file':
+                            $('avatar_upload_http_{UUID}').object.style.display = 'none';
+                            $('avatar_upload_file_{UUID}').object.style.display = 'block';
+                            break;
+                        }
+                      }
+                    </script>
+                    <label><input onclick="admincp_users_avatar_set_{UUID}(this);" type="radio" name="avatar_action" value="keep" checked="checked" /> {lang:acpum_avatar_lbl_keep}</label><br />
+                    <label><input onclick="admincp_users_avatar_set_{UUID}(this);" type="radio" name="avatar_action" value="remove" /> {lang:acpum_avatar_lbl_remove}</label><br />
+                    <label><input onclick="admincp_users_avatar_set_{UUID}(this);" type="radio" name="avatar_action" value="set_http" /> {lang:acpum_avatar_lbl_set_http}</label><br />
+                      <div id="avatar_upload_http_{UUID}" style="display: none; margin: 10px 0 0 2.2em;">
+                        {lang:usercp_avatar_lbl_url} <input type="text" name="avatar_http_url" size="40" value="http://" /><br />
+                        <small>{lang:usercp_avatar_lbl_url_desc} {lang:usercp_avatar_limits}</small>
+                      </div>
+                    <label><input onclick="admincp_users_avatar_set_{UUID}(this);" type="radio" name="avatar_action" value="set_file" /> {lang:acpum_avatar_lbl_set_file}</label>
+                      <div id="avatar_upload_file_{UUID}" style="display: none; margin: 10px 0 0 2.2em;">
+                        {lang:usercp_avatar_lbl_file} <input type="file" name="avatar_file" size="40" value="http://" /><br />
+                        <small>{lang:usercp_avatar_lbl_file_desc} {lang:usercp_avatar_limits}</small>
+                      </div>
+                  </td>
+                </tr>
+                
+              <!-- / Avatar settings -->
+              
+              <!-- Administrator-only options -->
+              
+                <tr>
+                  <th class="subhead" colspan="2">
+                    {lang:acpum_heading_adminonly}
+                  </th>
+                </tr>
+                
+                <tr>
+                  <td class="row2">{lang:acpum_field_active_title}<br />
+                                   <small>{lang:acpum_field_active_hint}</small>
+                                   </td>
+                  <td class="row1"><label><input type="checkbox" name="account_active" <!-- BEGIN account_active -->checked="checked" <!-- END account_active -->/> {lang:acpum_field_active}</label></td>
+                </tr>
+                
+                <tr>
+                  <td class="row2">
+                    {lang:acpum_field_userlevel}<br />
+                    <small>{lang:acpum_field_userlevel_hint}</small>
+                  </td>
+                  <td class="row1">
+                    <select name="user_level">
+                      <option value="{USER_LEVEL_MEMBER}"<!-- BEGIN ul_member --> selected="selected"<!-- END ul_member -->>{lang:userfuncs_ml_level_member}</option>
+                      <option value="{USER_LEVEL_MOD}"<!-- BEGIN ul_mod --> selected="selected"<!-- END ul_mod -->>{lang:userfuncs_ml_level_mod}</option>
+                      <option value="{USER_LEVEL_ADMIN}"<!-- BEGIN ul_admin --> selected="selected"<!-- END ul_admin -->>{lang:userfuncs_ml_level_admin}</option>
+                    </select>
+                  </td>
+                </tr>
+                
+                <!-- BEGIN have_reg_ip -->
+                <tr>
+                  <td class="row2">
+                    {lang:acpum_field_reg_ip}
+                  </td>
+                  <td class="row1">
+                    {REG_IP_ADDR}
+                    <input type="hidden" name="user_registration_ip" value="{REG_IP_ADDR}" />
+                  </td>
+                </tr>
+                <!-- BEGINELSE have_reg_ip -->
+                <input type="hidden" name="user_registration_ip" value="" />
+                <!-- END have_reg_ip -->
+                
+                <tr>
+                  <td class="row2">
+                    {lang:acpum_field_deleteaccount_title}
+                  </td>
+                  <td class="row1">
+                  <label><input type="checkbox" name="delete_account" onclick="var d = (this.checked) ? 'block' : 'none'; document.getElementById('delete_blurb_{UUID}').style.display = d;" /> {lang:acpum_field_deleteaccount}</label>
                     <div id="delete_blurb_{UUID}" style="display: none;">
                       <!-- BEGIN same_user -->
-                      <p><b><blink style="color: red;">WARNING!</blink> This will delete your own user account!</b></p>
+                      <!-- Obnoxious I know, but it's needed. -->
+                      <p><b>{lang:acpum_msg_delete_own_account}</b></p>
                       <!-- END same_user -->
-                      <p><small>Even if you delete this user account, the username will be shown in page edit history, comments, and other areas of the site.
-                      Deleting a user account CANNOT BE UNDONE and should only be done in extreme circumstances.
-                      If the user has violated the site policy, deleting the account will not prevent him from using the site or creating a new account, for that you need to add a new ban rule.</small></p>
+                      <p><small>{lang:acpum_field_deleteaccount_hint}</small></p>
                     </div>
                   </td>
                 </tr>
@@ -818,8 +1131,8 @@
               <!-- Save button -->
               <tr>
                 <th colspan="2">
-                  <input type="submit" name="action[save]" value="Save changes" style="font-weight: bold;" />
-                  <input type="submit" name="action[noop]" value="Cancel" style="font-weight: normal;" />
+                  <input type="submit" name="action[save]" value="{lang:acpum_btn_save}" style="font-weight: bold;" />
+                  <input type="submit" name="action[noop]" value="{lang:etc_cancel}" style="font-weight: normal;" />
                 </th>
               </tr>
             
@@ -827,6 +1140,11 @@
           </div>
         
         </form>
+        
+        <script type="text/javascript">
+        password_score_field(document.forms['useredit_{UUID}'].new_password);
+        </script>
+        
         {AES_JAVASCRIPT}
       <!-- Conclusion of user edit form -->
 EOF;
@@ -892,9 +1210,18 @@
         'LOCATION' => $location,
         'JOB' => $job,
         'HOBBIES' => $hobbies,
-        'FORM_ACTION' => $form_action
+        'FORM_ACTION' => $form_action,
+        'REG_IP_ADDR' => $this->reg_ip_addr
       ));
     
+    if ( $this->has_avatar )
+    {
+      $parser->assign_vars(array(
+          'AVATAR_SRC' => make_avatar_url($this->user_id, $this->avi_type),
+          'AVATAR_ALT' => $lang->get('usercp_avatar_image_alt', array('username' => $this->username))
+        ));
+    }
+    
     $parser->assign_bool(array(
         'password_meter' => ( getConfig('pw_strength_enable') == '1' ),
         'ul_member' => ( $this->user_level == USER_LEVEL_CHPREF ),
@@ -902,7 +1229,9 @@
         'ul_admin' => ( $this->user_level == USER_LEVEL_ADMIN ),
         'account_active' => ( $this->account_active === true ),
         'email_public' => ( $this->email_public === true ),
-        'same_user' => ( $this->user_id == $session->user_id )
+        'same_user' => ( $this->user_id == $session->user_id ),
+        'user_has_avatar' => ( $this->has_avatar ),
+        'have_reg_ip' => ( intval(@strlen($this->reg_ip_addr)) > 0 && is_valid_ip($this->reg_ip_addr) )
       ));
     
     $parsed = $parser->run();
--- a/schema.sql	Fri Feb 22 12:46:51 2008 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,310 +0,0 @@
--- Enano - an open-source CMS capable of wiki functions, Drupal-like sidebar blocks, and everything in between
--- Version 1.0.2 (Coblynau)
--- Copyright (C) 2006-2007 Dan Fuhry
-
--- This program is Free Software; you can redistribute and/or modify it under the terms of the GNU General Public License
--- as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.
-
--- 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.
-
--- schema.sql - MySQL installation schema. Firebird version in development.
-
-CREATE TABLE {{TABLE_PREFIX}}categories(
-  page_id varchar(64),
-  namespace varchar(64),
-  category_id varchar(64)
-) CHARACTER SET `utf8` COLLATE `utf8_bin`;
-
-CREATE TABLE {{TABLE_PREFIX}}comments(
-  comment_id int(12) NOT NULL auto_increment,
-  page_id text,
-  namespace text,
-  subject text,
-  comment_data text,
-  name text,
-  approved tinyint(1) default 1,
-  user_id mediumint(8) NOT NULL DEFAULT -1,
-  time int(12) NOT NULL DEFAULT 0,
-  PRIMARY KEY ( comment_id )
-) CHARACTER SET `utf8` COLLATE `utf8_bin`;
-
-CREATE TABLE {{TABLE_PREFIX}}config(
-  config_name varchar(63),
-  config_value text
-) CHARACTER SET `utf8` COLLATE `utf8_bin`;
-
-CREATE TABLE {{TABLE_PREFIX}}logs(
-  log_type varchar(16),
-  action varchar(16),
-  time_id int(12) NOT NULL default '0',
-  date_string varchar(63),
-  page_id text,
-  namespace text,
-  page_text text,
-  char_tag varchar(40),
-  author varchar(63),
-  edit_summary text,
-  minor_edit tinyint(1)
-) CHARACTER SET `utf8` COLLATE `utf8_bin`;
-
-CREATE TABLE {{TABLE_PREFIX}}page_text(
-  page_id varchar(255),
-  namespace varchar(16) NOT NULL default 'Article',
-  page_text text,
-  char_tag varchar(63),
-  FULLTEXT KEY {{TABLE_PREFIX}}page_search_idx (page_id, namespace, page_text)
-) ENGINE = MYISAM CHARACTER SET `utf8`;
-
-CREATE TABLE {{TABLE_PREFIX}}pages(
-  page_order int(8),
-  name varchar(255),
-  urlname varchar(255),
-  namespace varchar(16) NOT NULL default 'Article',
-  special tinyint(1) default '0',
-  visible tinyint(1) default '1',
-  comments_on tinyint(1) default '1',
-  protected tinyint(1) NOT NULL DEFAULT 0,
-  wiki_mode tinyint(1) NOT NULL DEFAULT 2,
-  delvotes int(10) NOT NULL default 0,
-  password varchar(40) NOT NULL DEFAULT '',
-  delvote_ips text DEFAULT NULL
-) CHARACTER SET `utf8` COLLATE `utf8_bin`;
-
-CREATE TABLE {{TABLE_PREFIX}}session_keys(
-  session_key varchar(32),
-  salt varchar(32),
-  user_id mediumint(8),
-  auth_level tinyint(1) NOT NULL default '0',
-  source_ip varchar(10) default '0x7f000001',
-  time bigint(15) default '0'
-) CHARACTER SET `utf8` COLLATE `utf8_bin`;
-
-CREATE TABLE {{TABLE_PREFIX}}themes(
-  theme_id varchar(63),
-  theme_name text,
-  theme_order smallint(5) NOT NULL default '1',
-  default_style varchar(63) NOT NULL DEFAULT '',
-  enabled tinyint(1) NOT NULL default '1'
-) CHARACTER SET `utf8` COLLATE `utf8_bin`;
-
-CREATE TABLE {{TABLE_PREFIX}}users(
-  user_id mediumint(8) NOT NULL auto_increment,
-  username text,
-  password varchar(255),
-  email text,
-  real_name text,
-  user_level tinyint(1) NOT NULL default 2,
-  theme varchar(64) NOT NULL default 'bleu.css',
-  style varchar(64) NOT NULL default 'default',
-  signature text,
-  reg_time int(11) NOT NULL DEFAULT 0,
-  account_active tinyint(1) NOT NULL DEFAULT 0,
-  activation_key varchar(40) NOT NULL DEFAULT 0,
-  old_encryption tinyint(1) NOT NULL DEFAULT 0,
-  temp_password text,
-  temp_password_time int(12) NOT NULL DEFAULT 0,
-  user_coppa tinyint(1) NOT NULL DEFAULT 0,
-  PRIMARY KEY  (user_id)
-) CHARACTER SET `utf8` COLLATE `utf8_bin`;
-
-CREATE TABLE {{TABLE_PREFIX}}users_extra(
-  user_id mediumint(8) NOT NULL,
-  user_aim varchar(63),
-  user_yahoo varchar(63),
-  user_msn varchar(255),
-  user_xmpp varchar(255),
-  user_homepage text,
-  user_location text,
-  user_job text,
-  user_hobbies text,
-  email_public tinyint(1) NOT NULL DEFAULT 0,
-  PRIMARY KEY ( user_id ) 
-) CHARACTER SET `utf8` COLLATE `utf8_bin`;
-
-CREATE TABLE {{TABLE_PREFIX}}banlist(
-  ban_id mediumint(8) NOT NULL auto_increment,
-  ban_type tinyint(1),
-  ban_value varchar(64),
-  is_regex tinyint(1) DEFAULT 0,
-  reason text,
-  PRIMARY KEY ( ban_id ) 
-) CHARACTER SET `utf8` COLLATE `utf8_bin`;
-
-CREATE TABLE {{TABLE_PREFIX}}files(
-  file_id int(12) NOT NULL auto_increment,
-  time_id int(12) NOT NULL,
-  page_id varchar(63) NOT NULL,
-  filename varchar(127) default NULL,
-  size bigint(15) NOT NULL,
-  mimetype varchar(63) default NULL,
-  file_extension varchar(8) default NULL,
-  file_key varchar(32) NOT NULL,
-  PRIMARY KEY (file_id) 
-) CHARACTER SET `utf8` COLLATE `utf8_bin`;
-
-CREATE TABLE {{TABLE_PREFIX}}buddies(
-  buddy_id int(15) NOT NULL auto_increment,
-  user_id mediumint(8),
-  buddy_user_id mediumint(8),
-  is_friend tinyint(1) NOT NULL default '1',
-  PRIMARY KEY  (buddy_id) 
-) CHARACTER SET `utf8` COLLATE `utf8_bin`;
-
-CREATE TABLE {{TABLE_PREFIX}}privmsgs(
-  message_id int(15) NOT NULL auto_increment,
-  message_from varchar(63),
-  message_to varchar(255),
-  date int(12),
-  subject varchar(63),
-  message_text text,
-  folder_name varchar(63),
-  message_read tinyint(1) NOT NULL DEFAULT 0,
-  PRIMARY KEY  (message_id) 
-) CHARACTER SET `utf8` COLLATE `utf8_bin`;
-
-CREATE TABLE {{TABLE_PREFIX}}sidebar(
-  item_id smallint(3) NOT NULL auto_increment,
-  item_order smallint(3) NOT NULL DEFAULT 0,
-  item_enabled tinyint(1) NOT NULL DEFAULT 1,
-  sidebar_id smallint(3) NOT NULL DEFAULT 1,
-  block_name varchar(63) NOT NULL,
-  block_type tinyint(1) NOT NULL DEFAULT 0,
-  block_content text,
-  PRIMARY KEY ( item_id )
-) CHARACTER SET `utf8` COLLATE `utf8_bin`;
-
-CREATE TABLE {{TABLE_PREFIX}}hits(
-  hit_id bigint(20) NOT NULL auto_increment,
-  username varchar(63) NOT NULL,
-  time int(12) NOT NULL DEFAULT 0,
-  page_id varchar(63),
-  namespace varchar(63),
-  PRIMARY KEY ( hit_id ) 
-) CHARACTER SET `utf8` COLLATE `utf8_bin`;
-
-CREATE TABLE {{TABLE_PREFIX}}search_index(
-  word varchar(64) NOT NULL,
-  page_names text,
-  PRIMARY KEY ( word ) 
-) CHARACTER SET `utf8` COLLATE `utf8_bin`;
-
-CREATE TABLE {{TABLE_PREFIX}}groups(
-  group_id mediumint(5) UNSIGNED NOT NULL auto_increment,
-  group_name varchar(64),
-  group_type tinyint(1) NOT NULL DEFAULT 1,
-  PRIMARY KEY ( group_id ),
-  system_group tinyint(1) NOT NULL DEFAULT 0 
-) CHARACTER SET `utf8` COLLATE `utf8_bin`;
-
-CREATE TABLE {{TABLE_PREFIX}}group_members(
-  member_id int(12) UNSIGNED NOT NULL auto_increment,
-  group_id mediumint(5) UNSIGNED NOT NULL,
-  user_id int(12) NOT NULL,
-  is_mod tinyint(1) NOT NULL DEFAULT 0,
-  pending tinyint(1) NOT NULL DEFAULT 0,
-  PRIMARY KEY ( member_id ) 
-) CHARACTER SET `utf8` COLLATE `utf8_bin`;
-
-CREATE TABLE {{TABLE_PREFIX}}acl(
-  rule_id int(12) UNSIGNED NOT NULL auto_increment,
-  target_type tinyint(1) UNSIGNED NOT NULL,
-  target_id int(12) UNSIGNED NOT NULL,
-  page_id varchar(255),
-  namespace varchar(24),
-  rules text,
-  PRIMARY KEY ( rule_id ) 
-) CHARACTER SET `utf8` COLLATE `utf8_bin`;
-
--- Added in 1.0.1
-
-CREATE TABLE {{TABLE_PREFIX}}page_groups(
-  pg_id mediumint(8) NOT NULL auto_increment,
-  pg_type tinyint(2) NOT NULL DEFAULT 1,
-  pg_name varchar(255) NOT NULL DEFAULT '',
-  pg_target varchar(255) DEFAULT NULL,
-  PRIMARY KEY ( pg_id )
-) CHARACTER SET `utf8` COLLATE `utf8_bin`;
-
--- Added in 1.0.1
-
-CREATE TABLE {{TABLE_PREFIX}}page_group_members(
-  pg_member_id int(12) NOT NULL auto_increment,
-  pg_id mediumint(8) NOT NULL,
-  page_id varchar(63) NOT NULL,
-  namespace varchar(63) NOT NULL DEFAULT 'Article',
-  PRIMARY KEY ( pg_member_id )
-) CHARACTER SET `utf8` COLLATE `utf8_bin`;
-
--- Added in 1.0.1
-
-CREATE TABLE {{TABLE_PREFIX}}tags(
-  tag_id int(12) NOT NULL auto_increment,
-  tag_name varchar(63) NOT NULL DEFAULT 'bla',
-  page_id varchar(255) NOT NULL,
-  namespace varchar(255) NOT NULL,
-  user mediumint(8) NOT NULL DEFAULT 1,
-  PRIMARY KEY ( tag_id )
-) CHARACTER SET `utf8` COLLATE `utf8_bin`;
-
-INSERT INTO {{TABLE_PREFIX}}config(config_name, config_value) VALUES
-  ('site_name', '{{SITE_NAME}}'),
-  ('main_page', 'Main_Page'),
-  ('site_desc', '{{SITE_DESC}}'),
-  ('wiki_mode', '{{WIKI_MODE}}'),
-  ('wiki_edit_notice', '0'),
-  ('sflogo_enabled', '0'),
-  ('sflogo_groupid', ''),
-  ('sflogo_type', '1'),
-  ('w3c_vh32', '0'),
-  ('w3c_vh40', '0'),
-  ('w3c_vh401', '0'),
-  ('w3c_vxhtml10', '0'),
-  ('w3c_vxhtml11', '0'),
-  ('w3c_vcss', '0'),
-  ('approve_comments', '0'),
-  ('enable_comments', '1'),
-  ('plugin_SpecialAdmin.php', '1'),
-  ('plugin_SpecialPageFuncs.php', '1'),
-  ('plugin_SpecialUserFuncs.php', '1'),
-  ('plugin_SpecialCSS.php', '1'),
-  ('copyright_notice', '{{COPYRIGHT}}'),
-  ('wiki_edit_notice_text', '== Why can I edit this page? ==\n\nEveryone can edit almost any page in this website. This concept is called a wiki. It gives everyone the opportunity to make a change for the best. While some spam and vandalism may occur, it is believed that most contributions will be legitimate and helpful.\n\nFor security purposes, a history of all page edits is kept, and administrators are able to restore vandalized or spammed pages with just a few clicks.'),
-  ('cache_thumbs', '{{ENABLE_CACHE}}'),
-  ('max_file_size', '256000'),('enano_version', '{{VERSION}}'),( 'allowed_mime_types', 'cbf:len=185;crc=55fb6f14;data=0[1],1[4],0[3],1[1],0[22],1[1],0[16],1[3],0[16],1[1],0[1],1[2],0[6],1[1],0[1],1[1],0[4],1[2],0[3],1[1],0[48],1[2],0[2],1[1],0[4],1[1],0[37]|end' ),
-  ('contact_email', '{{ADMIN_EMAIL}}'),
-  ('powered_btn', '1');
-
-INSERT INTO {{TABLE_PREFIX}}page_text(page_id, namespace, page_text, char_tag) VALUES
-  ('Main_Page', 'Article', '=== Enano has been successfully installed and is working. ===\n\nIf you can see this message, it means that you\'ve finished the Enano setup process and are ready to start building your website. Congratulations!\n\nTo edit this front page, click the Log In button to the left, enter the credentials you provided during the installation, and click the Edit This Page button that appears on the blue toolbar just above this text. You can also [http://docs.enanocms.org/Help:2.4 learn more] about editing pages.\n\nTo create more pages, use the Create a Page button to the left. If you enabled wiki mode, you don\'t have to log in first, however your IP address will be shown in the page history.\n\nVisit the [http://docs.enanocms.org/Help:Contents Enano documentation project website] to learn more about administering your site effectively and keeping things secure.', '');
-
-INSERT INTO {{TABLE_PREFIX}}pages(page_order, name, urlname, namespace, special, visible, comments_on, protected, delvotes, delvote_ips) VALUES
-  (NULL, 'Main Page', 'Main_Page', 'Article', 0, 1, 1, 1, 0, '');
-
-INSERT INTO {{TABLE_PREFIX}}themes(theme_id, theme_name, theme_order, default_style, enabled) VALUES
-  ('oxygen', 'Oxygen', 1, 'bleu.css', 1),
-  ('stpatty', 'St. Patty', 2, 'shamrock.css', 1);
-
-INSERT INTO {{TABLE_PREFIX}}users(user_id, username, password, email, real_name, user_level, theme, style, signature, reg_time, account_active) VALUES
-  (1, 'Anonymous', 'invalid-pass-hash', 'anonspam@enanocms.org', 'None', 1, 'oxygen', 'bleu', '', 0, 0),
-  (2, '{{ADMIN_USER}}', '{{ADMIN_PASS}}', '{{ADMIN_EMAIL}}', '{{REAL_NAME}}', 9, 'oxygen', 'bleu', '', UNIX_TIMESTAMP(), 1);
-  
-INSERT INTO {{TABLE_PREFIX}}users_extra(user_id) VALUES
-  (2);
-
-INSERT INTO {{TABLE_PREFIX}}groups(group_id,group_name,group_type,system_group) VALUES(1, 'Everyone', 3, 1),
-  (2,'Administrators',3,1),
-  (3,'Moderators',3,1);
-
-INSERT INTO {{TABLE_PREFIX}}group_members(group_id,user_id,is_mod) VALUES(2, 2, 1);
-
-INSERT INTO {{TABLE_PREFIX}}acl(target_type,target_id,page_id,namespace,rules) VALUES(1,2,NULL,NULL,'read=4;post_comments=4;edit_comments=4;edit_page=4;view_source=4;mod_comments=4;history_view=4;history_rollback=4;history_rollback_extra=4;protect=4;rename=4;clear_logs=4;vote_delete=4;vote_reset=4;delete_page=4;tag_create=4;tag_delete_own=4;tag_delete_other=4;set_wiki_mode=4;password_set=4;password_reset=4;mod_misc=4;edit_cat=4;even_when_protected=4;upload_files=4;upload_new_version=4;create_page=4;php_in_pages={{ADMIN_EMBED_PHP}};edit_acl=4;'),
-  (1,3,NULL,NULL,'read=4;post_comments=4;edit_comments=4;edit_page=4;view_source=4;mod_comments=4;history_view=4;history_rollback=4;history_rollback_extra=4;protect=4;rename=3;clear_logs=2;vote_delete=4;vote_reset=4;delete_page=4;set_wiki_mode=2;password_set=2;password_reset=2;mod_misc=2;edit_cat=4;even_when_protected=4;upload_files=2;upload_new_version=3;create_page=3;php_in_pages=2;edit_acl=2;');
-
-INSERT INTO {{TABLE_PREFIX}}sidebar(item_id, item_order, sidebar_id, block_name, block_type, block_content) VALUES
-  (1, 1, 1, 'Navigation', 1, '[[Main Page|Home]]'),
-  (2, 2, 1, 'Tools', 1, '[[$NS_SPECIAL$CreatePage|Create a page]]\n[[$NS_SPECIAL$UploadFile|Upload file]]\n[[$NS_SPECIAL$SpecialPages|Special pages]]\n{if auth_admin}\n[[$NS_SPECIAL$EditSidebar|Edit the sidebar]]\n$ADMIN_LINK$\n{/if}'),
-  (3, 3, 1, '$USERNAME$', 1, '[[$NS_USER$$USERNAME$|User page]]\n[[$NS_SPECIAL$Contributions/$USERNAME$|My Contributions]]\n{if user_logged_in}\n[[$NS_SPECIAL$Preferences|Preferences]]\n[[$NS_SPECIAL$PrivateMessages|Private messages]]\n[[$NS_SPECIAL$Usergroups|Group control panel]]\n$THEME_LINK$\n{/if}\n{if user_logged_in}\n$LOGOUT_LINK$\n{else}\n[[$NS_SPECIAL$Register|Create an account]]\n$LOGIN_LINK$\n[[$NS_SPECIAL$Login/$NS_SPECIAL$PrivateMessages|Private messages]]\n{/if}'),
-  (4, 4, 1, 'Search', 1, '<div class="slideblock2" style="padding: 0px;"><form action="$CONTENTPATH$$NS_SPECIAL$Search" method="get" style="padding: 0; margin: 0;"><p><input type="hidden" name="title" value="$NS_SPECIAL$Search" />$INPUT_AUTH$<input name="q" alt="Search box" type="text" size="10" style="width: 70%" /> <input type="submit" value="Go" style="width: 20%" /></p></form></div>'),
-  (5, 2, 2, 'Links', 4, 'Links');
-
--- a/themes/admin/acledit.tpl	Fri Feb 22 12:46:51 2008 -0500
+++ b/themes/admin/acledit.tpl	Fri Feb 22 12:51:53 2008 -0500
@@ -3,15 +3,17 @@
   <table border="0" cellspacing="1" cellpadding="4" style="width: 100%;">
     <tr>
       <th></th>
-      <th style='cursor: pointer;' title="Click to change all columns" onclick="__aclSetAllRadios('1');">Deny</th>
-      <th style='cursor: pointer;' title="Click to change all columns" onclick="__aclSetAllRadios('2');">Disallow</th>
-      <th style='cursor: pointer;' title="Click to change all columns" onclick="__aclSetAllRadios('3');">Wiki mode</th>
-      <th style='cursor: pointer;' title="Click to change all columns" onclick="__aclSetAllRadios('4');">Allow</th>
+      <th style='cursor: pointer;' title="Click to change all columns" onclick="__aclSetAllRadios('i');">{lang:acl_lbl_field_inherit}</th>
+      <th style='cursor: pointer;' title="Click to change all columns" onclick="__aclSetAllRadios('1');">{lang:acl_lbl_field_deny}</th>
+      <th style='cursor: pointer;' title="Click to change all columns" onclick="__aclSetAllRadios('2');">{lang:acl_lbl_field_disallow}</th>
+      <th style='cursor: pointer;' title="Click to change all columns" onclick="__aclSetAllRadios('3');">{lang:acl_lbl_field_wikimode}</th>
+      <th style='cursor: pointer;' title="Click to change all columns" onclick="__aclSetAllRadios('4');">{lang:acl_lbl_field_allow}</th>
     </tr>
 <!-- ENDVAR acl_field_begin -->
 <!-- VAR acl_field_item -->
     <tr>
       <td class="{ROW_CLASS}">{FIELD_DESC}</td>
+      <td class="{ROW_CLASS}" style="text-align: center;"><input type="radio" value="i" name="{FIELD_NAME}" {FIELD_INHERIT_CHECKED} /></td>
       <td class="{ROW_CLASS}" style="text-align: center;"><input type="radio" value="1" name="{FIELD_NAME}" {FIELD_DENY_CHECKED} /></td>
       <td class="{ROW_CLASS}" style="text-align: center;"><input type="radio" value="2" name="{FIELD_NAME}" {FIELD_DISALLOW_CHECKED} /></td>
       <td class="{ROW_CLASS}" style="text-align: center;"><input type="radio" value="3" name="{FIELD_NAME}" {FIELD_WIKIMODE_CHECKED} /></td>
@@ -20,14 +22,8 @@
 <!-- ENDVAR acl_field_item -->
 <!-- VAR acl_field_end -->
     <tr>
-      <td colspan="5" class="row3">
-        <p><b>Permission types:</b></p>
-        <ul>
-          <li><b>Allow</b> means that the user is allowed to access the item</li>
-          <li><b>Wiki mode</b> means the user can access the item if wiki mode is active (per-page wiki mode is taken into account)</li>
-          <li><b>Disallow</b> means the user is denied access unless something allows it.</li>
-          <li><b>Deny</b> means that the user is denied access to the item. This setting overrides all other permissions.</li>
-        </ul>
+      <td colspan="6" class="row3">
+        {lang:acl_lbl_help}
       </td>
     </tr>
   </table>
--- a/themes/admin/comment.tpl	Fri Feb 22 12:46:51 2008 -0500
+++ b/themes/admin/comment.tpl	Fri Feb 22 12:51:53 2008 -0500
@@ -4,23 +4,30 @@
       <th colspan="2" style="text-align: left;">{DATETIME}</th>
     </tr>
     <tr>
-      <td style="width: 120px; height: 100%;" rowspan="4" valign="top" class="row1">
+      <td style="width: 120px; height: 100%;" rowspan="4" valign="top" class="row1<!-- BEGIN is_friend --> row1_green<!-- END is_friend --><!-- BEGIN is_foe --> row1_red<!-- END is_foe -->">
         <table border="0" width="100%" style="height: 100%;" cellspacing="0" cellpadding="0">
           <tr>
-            <td valign="top" class="row1">
+            <td valign="top" class="row1<!-- BEGIN is_friend --> row1_green<!-- END is_friend --><!-- BEGIN is_foe --> row1_red<!-- END is_foe -->">
               <b>{NAME}</b><br />
               <small>{USER_LEVEL}</small>
+              <!-- BEGIN user_has_avatar -->
+              <div class="avatar">
+                <a href="{USERPAGE_LINK}">
+                  <img alt="{AVATAR_ALT}" src="{AVATAR_URL}" style="border-width: 0px;" />
+                </a>
+              </div>
+              <!-- END user_has_avatar -->
             </td>
           </tr>
           <tr>
-            <td valign="bottom" class="row1">
+            <td valign="bottom" class="row1<!-- BEGIN is_friend --> row1_green<!-- END is_friend --><!-- BEGIN is_foe --> row1_red<!-- END is_foe -->">
               {SEND_PM_LINK} {ADD_BUDDY_LINK}
             </td>
           </tr>
         </table>
       </td>
       <td class="row2">
-        <b>Subject:</b> <span id="subject_{ID}">{SUBJECT}</span>
+        <b>{lang:comment_lbl_subject}</b> <span id="subject_{ID}">{SUBJECT}</span>
       </td>
     </tr>
     <tr>
@@ -42,7 +49,7 @@
     <!-- BEGIN auth_mod -->
     <tr>
       <td class="row1">
-        <b>Moderation options:</b> {MOD_APPROVE_LINK} {MOD_DELETE_LINK}
+        <b>{lang:comment_lbl_mod_options}</b> {MOD_APPROVE_LINK} {MOD_DELETE_LINK} | {MOD_IP_LINK}
       </td>
     </tr>
     <!-- END auth_mod -->
--- a/themes/admin/footer.tpl	Fri Feb 22 12:46:51 2008 -0500
+++ b/themes/admin/footer.tpl	Fri Feb 22 12:51:53 2008 -0500
@@ -1,6 +1,6 @@
           </div>
           <div class="footer">
-            {COPYRIGHT}<br />Powered by <a href="<!-- BEGIN stupid_mode -->http://enanocms.org/<!-- BEGINELSE stupid_mode -->{URL_ABOUT_ENANO}<!-- END stupid_mode -->">Enano</a> &bull; Copyright &copy; 2007 Dan Fuhry
+            {COPYRIGHT}<br />Powered by <a href="{URL_ABOUT_ENANO}">Enano</a> &bull; Copyright &copy; 2006-2008 Dan Fuhry
           </div>
         </td>
         <td class="right"></td>
@@ -38,16 +38,5 @@
     </tr>
     </table>
     
-    <div style="display: none;">
-    <h2>Your browser does not support CSS.</h2>
-     <p>If you can see this text, it means that your browser does not support Cascading Style Sheets (CSS). CSS is a fundemental aspect of XHTML, and as a result it is becoming very widely adopted by websites, including this one. You should consider switching to a more modern web browser, such as Mozilla Firefox or Opera 9.</p>
-     <p>Because of this, there are a few minor issues that you may experience while browsing this site, not the least of which is some visual elements below that would normally be hidden in most browsers. Please excuse these minor inconveniences.</p>
-    </div>
-    <div id="root3" class="jswindow" style="display: none;">
-      <div id="tb3" class="titlebar">Wiki formatting help</div>
-      <div class="content" id="cn3">
-        Loading...
-      </div>
-    </div>
   </body>
 </html>
--- a/themes/admin/header.tpl	Fri Feb 22 12:46:51 2008 -0500
+++ b/themes/admin/header.tpl	Fri Feb 22 12:51:53 2008 -0500
@@ -9,7 +9,8 @@
     <link id="mdgCss" rel="stylesheet" type="text/css" href="{SCRIPTPATH}/themes/{THEME_ID}/css-ie/iefixes.css" />
     <![endif]-->
     {JS_DYNAMIC_VARS}
-    <script type="text/javascript" src="{SCRIPTPATH}/includes/clientside/static/enano-lib-basic.js"></script>
+    <!-- jsres.php is a wrapper script that compresses and caches single JS files to minimize requests -->
+    <script type="text/javascript" src="{SCRIPTPATH}/includes/clientside/jsres.php"></script>
     <script type="text/javascript" src="{SCRIPTPATH}/themes/admin/js/menu.js"></script>
     {ADDITIONAL_HEADERS}
     </head>
@@ -17,10 +18,10 @@
     <div id="header">
       <div class="sitename">{SITE_NAME}</div>
       <!-- div class="menulink"><a href="#" onclick="adminOpenMenu('sidebar', this); return false;">expand menu</a></div -->
-      [&nbsp;<a href="{SCRIPTPATH}/{ADMIN_SID_QUES}">Main page &#0187;</a>&nbsp;]
+      [&nbsp;<a href="{SCRIPTPATH}/{ADMIN_SID_QUES}">{lang:etc_btn_main_page} &#0187;</a>&nbsp;]
     </div>
     <div class="menu_nojs" id="pagebar_main">
-      <div class="label">Page tools</div>
+      <div class="label">{lang:onpage_lbl_pagetools}</div>
       {TOOLBAR}
       <ul>
         {TOOLBAR_EXTRAS}
Binary file themes/admin/preview.png has changed
--- a/themes/admin/simple-footer.tpl	Fri Feb 22 12:46:51 2008 -0500
+++ b/themes/admin/simple-footer.tpl	Fri Feb 22 12:51:53 2008 -0500
@@ -1,6 +1,6 @@
           </div>
           <div class="footer">
-            {COPYRIGHT}<br />Powered by <a href="{CONTENTPATH}{NS_SPECIAL}About_Enano{ADMIN_SID_AUTO}">Enano</a> &bull; Copyright &copy; 2007 Dan Fuhry
+            {COPYRIGHT}<br />Powered by <a href="{URL_ABOUT_ENANO}">Enano</a> &bull; Copyright &copy; 2007 Dan Fuhry
           </div>
         </td>
         <td class="right"></td>
@@ -9,28 +9,40 @@
         <td class="bottom-left"></td><td class="bottom"></td><td class="bottom-right"></td>
       </tr>
     </table>
+    
+    </td>
+    <td id="td-sidebar" valign="top">
+    
+      <table border="0" cellspacing="0" cellpadding="0" class="wrapper" id="sidebar-show">
+        <tr>
+          <td class="top-left"></td><td class="top">&nbsp;</td><td class="top-right"></td>
+        </tr>
+        <tr>
+          <td class="left"></td>
+          <td class="main">
+            <div id="sidebar">
+              {SIDEBAR_LEFT}
+              {SIDEBAR_RIGHT}
+            </div>
+          </td>
+          <td class="right"></td>
+        </tr>
+        <tr>
+          <td class="bottom-left"></td><td class="bottom"></td><td class="bottom-right"></td>
+        </tr>
+      </table>
+      
+      <div id="sidebar-hide" onclick="admin_expand();" class="collapsed" title="Click to expand the sidebar"></div>
+    
+    </td>
+    </tr>
+    </table>
+    
     <div style="display: none;">
     <h2>Your browser does not support CSS.</h2>
      <p>If you can see this text, it means that your browser does not support Cascading Style Sheets (CSS). CSS is a fundemental aspect of XHTML, and as a result it is becoming very widely adopted by websites, including this one. You should consider switching to a more modern web browser, such as Mozilla Firefox or Opera 9.</p>
      <p>Because of this, there are a few minor issues that you may experience while browsing this site, not the least of which is some visual elements below that would normally be hidden in most browsers. Please excuse these minor inconveniences.</p>
     </div>
-    <div id="root1" class="jswindow" style="display: none;">
-      <div id="tb1" class="titlebar">Confirm Logout</div>
-      <div class="content" id="cn1">
-        <form action="{CONTENTPATH}Special:Logout" method="get">
-          <div style="text-align: center">
-            <h3>Are you sure you want to log out?</h3>
-            <input type="submit" value="Log out" style="font-weight: bold;" />  <input type="button" onclick="jws.closeWin('root1');" value="Cancel" />
-          </div>
-        </form>
-      </div>  
-    </div>
-    <div id="root2" class="jswindow" style="display: none;">
-      <div id="tb2" class="titlebar">Change style</div>
-      <div class="content" id="cn2">
-        
-      </div>
-    </div>
     <div id="root3" class="jswindow" style="display: none;">
       <div id="tb3" class="titlebar">Wiki formatting help</div>
       <div class="content" id="cn3">
--- a/themes/admin/simple-header.tpl	Fri Feb 22 12:46:51 2008 -0500
+++ b/themes/admin/simple-header.tpl	Fri Feb 22 12:51:53 2008 -0500
@@ -1,20 +1,23 @@
 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
-<html>
+<html xmlns="http://www.w3.org/1999/xhtml">
   <head>
     <title>{PAGE_NAME} &bull; {SITE_NAME}</title>
     <meta http-equiv="Content-type" content="text/html; charset=utf-8" />
     <link rel="stylesheet" type="text/css" href="{SCRIPTPATH}/includes/clientside/css/enano-shared.css" />
     <link id="mdgCss" rel="stylesheet" type="text/css" href="{SCRIPTPATH}/themes/{THEME_ID}/css/{STYLE_ID}.css" />
+    <!--[if IE]>
+    <link id="mdgCss" rel="stylesheet" type="text/css" href="{SCRIPTPATH}/themes/{THEME_ID}/css-ie/iefixes.css" />
+    <![endif]-->
     {JS_DYNAMIC_VARS}
+    <script type="text/javascript" src="{SCRIPTPATH}/includes/clientside/static/enano-lib-basic.js"></script>
     <script type="text/javascript" src="{SCRIPTPATH}/themes/admin/js/menu.js"></script>
-    <script type="text/javascript" src="{SCRIPTPATH}/includes/clientside/static/enano-lib-basic.js"></script>
     {ADDITIONAL_HEADERS}
     </head>
   <body>
     <div id="header">
       <div class="sitename">{SITE_NAME}</div>
-      <div class="menulink"><a href="#" onclick="adminOpenMenu('sidebar', this); return false;">expand menu</a></div>
-      [&nbsp;<a href="{SCRIPTPATH}/{ADMIN_SID_AUTO}">Main page &#0187;</a>&nbsp;]
+      <!-- div class="menulink"><a href="#" onclick="adminOpenMenu('sidebar', this); return false;">expand menu</a></div -->
+      [&nbsp;<a href="{SCRIPTPATH}/{ADMIN_SID_QUES}">Main page &#0187;</a>&nbsp;]
     </div>
     <div class="menu_nojs" id="pagebar_main">
       <div class="label">Page tools</div>
@@ -24,11 +27,11 @@
       </ul>
       <span class="menuclear">&nbsp;</span>
     </div>
-    <div id="sidebar">
-      {SIDEBAR_LEFT}
-      {SIDEBAR_RIGHT}
-    </div>
-    <table border="0" cellspacing="0" cellpadding="0" id="wrapper">
+    <table border="0" cellspacing="0" cellpadding="0" id="sidebarholder">
+    <tr>
+    <td valign="top">
+    
+    <table border="0" cellspacing="0" cellpadding="0" class="wrapper">
       <tr>
         <td class="top-left"></td><td class="top">&nbsp;</td><td class="top-right"></td>
       </tr>
--- a/themes/oxygen/acledit.tpl	Fri Feb 22 12:46:51 2008 -0500
+++ b/themes/oxygen/acledit.tpl	Fri Feb 22 12:51:53 2008 -0500
@@ -3,15 +3,17 @@
   <table border="0" cellspacing="1" cellpadding="4" style="width: 100%;">
     <tr>
       <th></th>
-      <th style='cursor: pointer;' title="Click to change all columns" onclick="__aclSetAllRadios('1');">Deny</th>
-      <th style='cursor: pointer;' title="Click to change all columns" onclick="__aclSetAllRadios('2');">Disallow</th>
-      <th style='cursor: pointer;' title="Click to change all columns" onclick="__aclSetAllRadios('3');">Wiki mode</th>
-      <th style='cursor: pointer;' title="Click to change all columns" onclick="__aclSetAllRadios('4');">Allow</th>
+      <th style='cursor: pointer;' title="Click to change all columns" onclick="__aclSetAllRadios('i');">{lang:acl_lbl_field_inherit}</th>
+      <th style='cursor: pointer;' title="Click to change all columns" onclick="__aclSetAllRadios('1');">{lang:acl_lbl_field_deny}</th>
+      <th style='cursor: pointer;' title="Click to change all columns" onclick="__aclSetAllRadios('2');">{lang:acl_lbl_field_disallow}</th>
+      <th style='cursor: pointer;' title="Click to change all columns" onclick="__aclSetAllRadios('3');">{lang:acl_lbl_field_wikimode}</th>
+      <th style='cursor: pointer;' title="Click to change all columns" onclick="__aclSetAllRadios('4');">{lang:acl_lbl_field_allow}</th>
     </tr>
 <!-- ENDVAR acl_field_begin -->
 <!-- VAR acl_field_item -->
     <tr>
       <td class="{ROW_CLASS}">{FIELD_DESC}</td>
+      <td class="{ROW_CLASS}" style="text-align: center;"><input type="radio" value="i" name="{FIELD_NAME}" {FIELD_INHERIT_CHECKED} /></td>
       <td class="{ROW_CLASS}" style="text-align: center;"><input type="radio" value="1" name="{FIELD_NAME}" {FIELD_DENY_CHECKED} /></td>
       <td class="{ROW_CLASS}" style="text-align: center;"><input type="radio" value="2" name="{FIELD_NAME}" {FIELD_DISALLOW_CHECKED} /></td>
       <td class="{ROW_CLASS}" style="text-align: center;"><input type="radio" value="3" name="{FIELD_NAME}" {FIELD_WIKIMODE_CHECKED} /></td>
@@ -20,14 +22,8 @@
 <!-- ENDVAR acl_field_item -->
 <!-- VAR acl_field_end -->
     <tr>
-      <td colspan="5" class="row3">
-        <p><b>Permission types:</b></p>
-        <ul>
-          <li><b>Allow</b> means that the user is allowed to access the item</li>
-          <li><b>Wiki mode</b> means the user can access the item if wiki mode is active (per-page wiki mode is taken into account)</li>
-          <li><b>Disallow</b> means the user is denied access unless something allows it.</li>
-          <li><b>Deny</b> means that the user is denied access to the item. This setting overrides all other permissions.</li>
-        </ul>
+      <td colspan="6" class="row3">
+        {lang:acl_lbl_help}
       </td>
     </tr>
   </table>
--- a/themes/oxygen/comment.tpl	Fri Feb 22 12:46:51 2008 -0500
+++ b/themes/oxygen/comment.tpl	Fri Feb 22 12:51:53 2008 -0500
@@ -10,6 +10,13 @@
             <td valign="top" class="row1<!-- BEGIN is_friend --> row1_green<!-- END is_friend --><!-- BEGIN is_foe --> row1_red<!-- END is_foe -->">
               <b>{NAME}</b><br />
               <small>{USER_LEVEL}</small>
+              <!-- BEGIN user_has_avatar -->
+              <div class="avatar">
+                <a href="{USERPAGE_LINK}">
+                  <img alt="{AVATAR_ALT}" src="{AVATAR_URL}" style="border-width: 0px;" />
+                </a>
+              </div>
+              <!-- END user_has_avatar -->
             </td>
           </tr>
           <tr>
@@ -20,7 +27,7 @@
         </table>
       </td>
       <td class="row2">
-        <b>Subject:</b> <span id="subject_{ID}">{SUBJECT}</span>
+        <b>{lang:comment_lbl_subject}</b> <span id="subject_{ID}">{SUBJECT}</span>
       </td>
     </tr>
     <tr>
@@ -42,7 +49,7 @@
     <!-- BEGIN auth_mod -->
     <tr>
       <td class="row1">
-        <b>Moderation options:</b> {MOD_APPROVE_LINK} {MOD_DELETE_LINK}
+        <b>{lang:comment_lbl_mod_options}</b> {MOD_APPROVE_LINK} {MOD_DELETE_LINK} | {MOD_IP_LINK}
       </td>
     </tr>
     <!-- END auth_mod -->
--- a/themes/oxygen/css/bleu.css	Fri Feb 22 12:46:51 2008 -0500
+++ b/themes/oxygen/css/bleu.css	Fri Feb 22 12:51:53 2008 -0500
@@ -7,6 +7,7 @@
 /* The basics */
 html,body                          { height: 100%; }
 body                               { /* color added in 1.0.2 to fix light text in dark desktop themes */ color: #202020; margin: 0; padding: 0; background: url(../images/bleu/bg.png); font-family: trebuchet ms, verdana, arial, helvetica, sans-serif; font-size: 9pt; }
+body#tinymce                       { background-color: white; background-image: none; }
 .holder                            { border: 1px solid #CCCCCC; padding: 1px; background-color: #FFFFFF; color: #444444 }
 div.pad                            { padding: 10px; }                         
 table#title                        { margin: 0; padding: 0; height: 100px; background-color: #90B0D0; text-align: center; }
@@ -172,6 +173,10 @@
 div.menu a.current, div.menu a.current:hover, div.menu a.selected, div.menu a.selected:hover, div.menu_nojs a.current, div.menu_nojs a.current:hover, div.menu_nojs a.selected, div.menu_nojs a.selected:hover {
   color: #000040;
   background-color: #FFFFFF;
+  /*
+  Some people like this. Most people don't.
+  -moz-border-radius: 5px 5px 0 0;
+  */
 }
 div.menu ul, div.menu_nojs ul {
   display: none;
@@ -251,6 +256,12 @@
   filter: alpha(opacity=50);
 }
 
+input[type ^="button"][disabled ^="disabled"], input[type ^="submit"][disabled ^="disabled"], button[disabled ^="disabled"], .btn-disabled {
+  color: #808080 !important;
+  background-image: none !important;
+  background-color: #e0e0e0 !important;
+}
+
 /* JWS window theming */
 div.jswindow                      { border: 2px solid #7090B0; border-top: 5px solid #7090B0; padding: 0px; font-family: Trebuchet MS, tahoma, verdana, arial, sans-serif; font-size: 9pt; display: none; position: absolute; background-color: #FFFFFF; }
 div.titlebar                      { background-color: #7090B0; color: #FFFFFF; font-family: Trebuchet MS, tahoma, verdana, arial, sans-serif; font-size: 9pt; padding-bottom: 4px; cursor: default; }
@@ -264,11 +275,11 @@
 .catCheck:hover                   { padding: 3px; background-color: #F0F0F0; }
 
 /* Information, warning, question, error, and wait boxes */
-div.error-box                     { background-image: url(../../../images/error.png);    background-position: 8px 8px; background-repeat: no-repeat; background-color: #FFF4F4; border: 1px dashed #406080; padding: 10px 10px 10px 50px; margin: 1em 0 0 1em; min-height: 25px; }
-div.info-box                      { background-image: url(../../../images/info.png);     background-position: 8px 8px; background-repeat: no-repeat; background-color: #F4F4FF; border: 1px dashed #406080; padding: 10px 10px 10px 50px; margin: 1em 0 0 1em; min-height: 25px; }
-div.warning-box                   { background-image: url(../../../images/warning.png);  background-position: 8px 8px; background-repeat: no-repeat; background-color: #FFFFF4; border: 1px dashed #406080; padding: 10px 10px 10px 50px; margin: 1em 0 0 1em; min-height: 25px; }
-div.question-box                  { background-image: url(../../../images/question.png); background-position: 8px 8px; background-repeat: no-repeat; background-color: #F4FFF4; border: 1px dashed #406080; padding: 10px 10px 10px 50px; margin: 1em 0 0 1em; min-height: 25px; }
-div.wait-box                      { background-image: url(../../../images/wait.png);     background-position: 8px 8px; background-repeat: no-repeat; background-color: #FFF4FF; border: 1px dashed #406080; padding: 10px 10px 10px 50px; margin: 1em 0 0 1em; min-height: 25px; }
+div.error-box                     { background-image: url(../../../images/error.png);    background-position: 8px 8px; background-repeat: no-repeat; background-color: #FFF4F4; border: 1px dashed #406080; padding: 10px 10px 10px 50px; margin: 0.5em 0 0 0; min-height: 25px; }
+div.info-box                      { background-image: url(../../../images/info.png);     background-position: 8px 8px; background-repeat: no-repeat; background-color: #F4F4FF; border: 1px dashed #406080; padding: 10px 10px 10px 50px; margin: 0.5em 0 0 0; min-height: 25px; }
+div.warning-box                   { background-image: url(../../../images/warning.png);  background-position: 8px 8px; background-repeat: no-repeat; background-color: #FFFFF4; border: 1px dashed #406080; padding: 10px 10px 10px 50px; margin: 0.5em 0 0 0; min-height: 25px; }
+div.question-box                  { background-image: url(../../../images/question.png); background-position: 8px 8px; background-repeat: no-repeat; background-color: #F4FFF4; border: 1px dashed #406080; padding: 10px 10px 10px 50px; margin: 0.5em 0 0 0; min-height: 25px; }
+div.wait-box                      { background-image: url(../../../images/wait.png);     background-position: 8px 8px; background-repeat: no-repeat; background-color: #FFF4FF; border: 1px dashed #406080; padding: 10px 10px 10px 50px; margin: 0.5em 0 0 0; min-height: 25px; }
 
 /* This stuff is mostly unused, left in for compatibility */
 div#ajaxEditContainer table       { border: 0px solid #FFFFFF; }
@@ -278,9 +289,10 @@
 
 /* toolbar */
 div.toolbar {
-  border-bottom: 1px solid #909090;
+  border: 1px solid #3b619c;
   background-color: #D0D0D0;
-  padding: 2px 0;
+  background-image: url(../images/tb-bkg.gif);
+  padding: 1px 0;
   height: 22px;
   font-family: arial, sans-serif;
   font-size: 8pt;
@@ -298,7 +310,7 @@
   opacity: 0.6;
   /*filter: alpha(opacity=60);*/
 }
-div.toolbar a:hover img {
+div.toolbar a:hover img, div.toolbar a:focus img {
   opacity: 1;
   /*filter: alpha(opacity=100);*/
 }
@@ -313,15 +325,16 @@
   max-height: 16px;
   text-decoration: none;
 }
-div.toolbar a:hover {
-  border: 1px solid #202090;
+div.toolbar a:hover, div.toolbar a:focus {
+  border: 1px solid #000080;
   background-color: #ceceed;
+  background-image: url(../images/tb-frg.gif);
   color: #000000;
   text-decoration: none;
 }
 div.toolbar a:active {
-  border: 1px solid #A0A0A0;
   background-color: #E0E0E0;
+  background-image: url(../images/tb-psh.gif);
 }
 div.toolbar img {
   margin: 0;
@@ -331,11 +344,20 @@
 }
 div.toolbar a span {
   position: relative;
-  top: -4px;
+  top: -3px !important;
+}
+div.toolbar a span.noimage {
+  position: relative;
+  top: 0px !important;
+  height: 16px !important;
+  display: block;
+  padding-left: 2px !important;
 }
 div.toolbar li span {
-  padding-left: 2px;
-  padding-right: 5px;
+  padding-left: 4px;
+  padding-right: 2px;
+  position: relative;
+  top: 4px;
 }
 
 /* vertical toolbar */
--- a/themes/oxygen/footer.tpl	Fri Feb 22 12:46:51 2008 -0500
+++ b/themes/oxygen/footer.tpl	Fri Feb 22 12:51:53 2008 -0500
@@ -12,7 +12,7 @@
                  -->
             <div id="credits">
               <b>{COPYRIGHT}</b><br />
-              Website engine powered by <a href="<!-- BEGIN stupid_mode -->http://enanocms.org/<!-- BEGINELSE stupid_mode -->{URL_ABOUT_ENANO}<!-- END stupid_mode -->">Enano</a>&nbsp;&nbsp;|&nbsp;&nbsp;<a href="http://validator.w3.org/check?uri=referer">Valid XHTML 1.1</a>&nbsp;&nbsp;|&nbsp;&nbsp;<a href="http://jigsaw.w3.org/css-validator/validator?uri=referer">Valid CSS</a>&nbsp;&nbsp;|&nbsp;&nbsp;Generated in [[GenTime]]sec<!-- BEGIN auth_admin -->&nbsp;&nbsp;|&nbsp;&nbsp;<a href="{REPORT_URI}">[[NumQueries]] SQL</a><!-- END auth_admin -->
+              [[EnanoPoweredLinkLong]]&nbsp;&nbsp;|&nbsp;&nbsp;<!-- BEGINNOT stupid_mode --><a href="http://validator.w3.org/check?uri=referer">{lang:page_w3c_valid_xhtml11}</a>&nbsp;&nbsp;|&nbsp;&nbsp;<a href="http://jigsaw.w3.org/css-validator/validator?uri=referer">{lang:page_w3c_valid_css}</a>&nbsp;&nbsp;|&nbsp;&nbsp;<!-- END stupid_mode -->[[StatsLong]]
               <!-- Do not remove this line or scheduled tasks will not run. -->
               <img alt=" " src="{SCRIPTPATH}/cron.php" width="1" height="1" />
             </div>
--- a/themes/oxygen/header.tpl	Fri Feb 22 12:46:51 2008 -0500
+++ b/themes/oxygen/header.tpl	Fri Feb 22 12:51:53 2008 -0500
@@ -6,8 +6,13 @@
     <link rel="stylesheet" type="text/css" href="{SCRIPTPATH}/includes/clientside/css/enano-shared.css" />
     <link id="mdgCss" rel="stylesheet" href="{SCRIPTPATH}/themes/{THEME_ID}/css/{STYLE_ID}.css" type="text/css" />
     {JS_DYNAMIC_VARS}
-    <!-- This script automatically loads the other 15 JS files -->
-    <script type="text/javascript" src="{SCRIPTPATH}/includes/clientside/static/enano-lib-basic.js"></script>
+    
+    <script type="text/javascript">
+      var tinymce_skin = 'o2k7';
+    </script>
+    
+    <!-- jsres.php is a wrapper script that compresses and caches single JS files to minimize requests -->
+    <script type="text/javascript" src="{SCRIPTPATH}/includes/clientside/jsres.php"></script>
     {ADDITIONAL_HEADERS}
     
     <script type="text/javascript">
@@ -154,7 +159,13 @@
           <td id="mdg-bl"></td>
           <td class="menu_bg">
           <div class="menu_nojs" id="pagebar_main">
-            <div class="label">Page tools</div>
+            <div class="label">
+              <!-- BEGIN stupid_mode -->
+              Page tools
+              <!-- BEGINELSE stupid_mode -->
+              {lang:onpage_lbl_pagetools}
+              <!-- END stupid_mode -->
+            </div>
             {TOOLBAR}
             <ul>
               {TOOLBAR_EXTRAS}
Binary file themes/oxygen/images/tb-bkg.gif has changed
Binary file themes/oxygen/images/tb-frg.gif has changed
Binary file themes/oxygen/images/tb-psh.gif has changed
Binary file themes/oxygen/preview.png has changed
--- a/themes/oxygen/toolbar.tpl	Fri Feb 22 12:46:51 2008 -0500
+++ b/themes/oxygen/toolbar.tpl	Fri Feb 22 12:51:53 2008 -0500
@@ -1,5 +1,6 @@
 <!-- Stuff related to toolbars and clickable buttons.
-     Used mostly in the page toolbar on most pages.
+     The plan was to use this on the toolbar for most pages. Never made it into the release,
+     but still provided as an otherwise-unused component for plugins to make use of.
      -->
 
 <!-- VAR toolbar_start -->
@@ -9,9 +10,15 @@
 <!-- VAR toolbar_button -->
   <li>
     <a title="{TITLE}" {FLAGS}>
+      <!-- BEGINNOT no_image -->
       <img alt="{TITLE}" src="{IMAGE}" />
+      <!-- END no_image -->
       <!-- BEGIN show_title -->
-      <span>{TITLE}</span>
+        <!-- BEGIN no_image -->
+        <span class="noimage">{TITLE}</span>
+        <!-- BEGINELSE no_image -->
+        <span>{TITLE}</span>
+        <!-- END no_image -->
       <!-- END show_title -->
     </a>
   </li>
--- a/themes/printable/acledit.tpl	Fri Feb 22 12:46:51 2008 -0500
+++ b/themes/printable/acledit.tpl	Fri Feb 22 12:51:53 2008 -0500
@@ -3,15 +3,17 @@
   <table border="0" cellspacing="1" cellpadding="4" style="width: 100%;">
     <tr>
       <th></th>
-      <th style='cursor: pointer;' title="Click to change all columns" onclick="__aclSetAllRadios('1');">Deny</th>
-      <th style='cursor: pointer;' title="Click to change all columns" onclick="__aclSetAllRadios('2');">Disallow</th>
-      <th style='cursor: pointer;' title="Click to change all columns" onclick="__aclSetAllRadios('3');">Wiki mode</th>
-      <th style='cursor: pointer;' title="Click to change all columns" onclick="__aclSetAllRadios('4');">Allow</th>
+      <th style='cursor: pointer;' title="Click to change all columns" onclick="__aclSetAllRadios('i');">{lang:acl_lbl_field_inherit}</th>
+      <th style='cursor: pointer;' title="Click to change all columns" onclick="__aclSetAllRadios('1');">{lang:acl_lbl_field_deny}</th>
+      <th style='cursor: pointer;' title="Click to change all columns" onclick="__aclSetAllRadios('2');">{lang:acl_lbl_field_disallow}</th>
+      <th style='cursor: pointer;' title="Click to change all columns" onclick="__aclSetAllRadios('3');">{lang:acl_lbl_field_wikimode}</th>
+      <th style='cursor: pointer;' title="Click to change all columns" onclick="__aclSetAllRadios('4');">{lang:acl_lbl_field_allow}</th>
     </tr>
 <!-- ENDVAR acl_field_begin -->
 <!-- VAR acl_field_item -->
     <tr>
       <td class="{ROW_CLASS}">{FIELD_DESC}</td>
+      <td class="{ROW_CLASS}" style="text-align: center;"><input type="radio" value="i" name="{FIELD_NAME}" {FIELD_INHERIT_CHECKED} /></td>
       <td class="{ROW_CLASS}" style="text-align: center;"><input type="radio" value="1" name="{FIELD_NAME}" {FIELD_DENY_CHECKED} /></td>
       <td class="{ROW_CLASS}" style="text-align: center;"><input type="radio" value="2" name="{FIELD_NAME}" {FIELD_DISALLOW_CHECKED} /></td>
       <td class="{ROW_CLASS}" style="text-align: center;"><input type="radio" value="3" name="{FIELD_NAME}" {FIELD_WIKIMODE_CHECKED} /></td>
@@ -20,14 +22,8 @@
 <!-- ENDVAR acl_field_item -->
 <!-- VAR acl_field_end -->
     <tr>
-      <td colspan="5" class="row3">
-        <p><b>Permission types:</b></p>
-        <ul>
-          <li><b>Allow</b> means that the user is allowed to access the item</li>
-          <li><b>Wiki mode</b> means the user can access the item if wiki mode is active (per-page wiki mode is taken into account)</li>
-          <li><b>Disallow</b> means the user is denied access unless something allows it.</li>
-          <li><b>Deny</b> means that the user is denied access to the item. This setting overrides all other permissions.</li>
-        </ul>
+      <td colspan="6" class="row3">
+        {lang:acl_lbl_help}
       </td>
     </tr>
   </table>
--- a/themes/printable/comment.tpl	Fri Feb 22 12:46:51 2008 -0500
+++ b/themes/printable/comment.tpl	Fri Feb 22 12:51:53 2008 -0500
@@ -4,23 +4,30 @@
       <th colspan="2" style="text-align: left;">{DATETIME}</th>
     </tr>
     <tr>
-      <td style="width: 120px; height: 100%;" rowspan="4" valign="top" class="row1">
+      <td style="width: 120px; height: 100%;" rowspan="4" valign="top" class="row1<!-- BEGIN is_friend --> row1_green<!-- END is_friend --><!-- BEGIN is_foe --> row1_red<!-- END is_foe -->">
         <table border="0" width="100%" style="height: 100%;" cellspacing="0" cellpadding="0">
           <tr>
-            <td valign="top" class="row1">
+            <td valign="top" class="row1<!-- BEGIN is_friend --> row1_green<!-- END is_friend --><!-- BEGIN is_foe --> row1_red<!-- END is_foe -->">
               <b>{NAME}</b><br />
               <small>{USER_LEVEL}</small>
+              <!-- BEGIN user_has_avatar -->
+              <div class="avatar">
+                <a href="{USERPAGE_LINK}">
+                  <img alt="{AVATAR_ALT}" src="{AVATAR_URL}" style="border-width: 0px;" />
+                </a>
+              </div>
+              <!-- END user_has_avatar -->
             </td>
           </tr>
           <tr>
-            <td valign="bottom" class="row1">
+            <td valign="bottom" class="row1<!-- BEGIN is_friend --> row1_green<!-- END is_friend --><!-- BEGIN is_foe --> row1_red<!-- END is_foe -->">
               {SEND_PM_LINK} {ADD_BUDDY_LINK}
             </td>
           </tr>
         </table>
       </td>
       <td class="row2">
-        <b>Subject:</b> <span id="subject_{ID}">{SUBJECT}</span>
+        <b>{lang:comment_lbl_subject}</b> <span id="subject_{ID}">{SUBJECT}</span>
       </td>
     </tr>
     <tr>
@@ -42,7 +49,7 @@
     <!-- BEGIN auth_mod -->
     <tr>
       <td class="row1">
-        <b>Moderation options:</b> {MOD_APPROVE_LINK} {MOD_DELETE_LINK}
+        <b>{lang:comment_lbl_mod_options}</b> {MOD_APPROVE_LINK} {MOD_DELETE_LINK} | {MOD_IP_LINK}
       </td>
     </tr>
     <!-- END auth_mod -->
--- a/themes/printable/header.tpl	Fri Feb 22 12:46:51 2008 -0500
+++ b/themes/printable/header.tpl	Fri Feb 22 12:51:53 2008 -0500
@@ -7,8 +7,8 @@
     <link id="mdgCss" rel="stylesheet" href="{SCRIPTPATH}/themes/{THEME_ID}/css/{STYLE_ID}.css" type="text/css" />
     <link rel="stylesheet" media="print" href="{SCRIPTPATH}/themes/{THEME_ID}/css-simple/printbits.css" type="text/css" />
     {JS_DYNAMIC_VARS}
-    <!-- This script automatically loads the other 15 JS files -->
-    <script type="text/javascript" src="{SCRIPTPATH}/includes/clientside/static/enano-lib-basic.js"></script>
+    <!-- jsres.php is a wrapper script that compresses and caches single JS files to minimize requests -->
+    <script type="text/javascript" src="{SCRIPTPATH}/includes/clientside/jsres.php"></script>
     {ADDITIONAL_HEADERS}
     
   </head>
Binary file themes/printable/preview.png has changed
--- a/themes/printable/theme.cfg	Fri Feb 22 12:46:51 2008 -0500
+++ b/themes/printable/theme.cfg	Fri Feb 22 12:51:53 2008 -0500
@@ -12,7 +12,7 @@
  */
 
 global $theme; 
-$theme['theme_id'] = 'oxygen';
-$theme['theme_name'] = 'Oxygen Bleu';
+$theme['theme_id'] = 'printable';
+$theme['theme_name'] = 'Printable page view';
 
 ?>
--- a/themes/stpatty/acledit.tpl	Fri Feb 22 12:46:51 2008 -0500
+++ b/themes/stpatty/acledit.tpl	Fri Feb 22 12:51:53 2008 -0500
@@ -3,15 +3,17 @@
   <table border="0" cellspacing="1" cellpadding="4" style="width: 100%;">
     <tr>
       <th></th>
-      <th style='cursor: pointer;' title="Click to change all columns" onclick="__aclSetAllRadios('1');">Deny</th>
-      <th style='cursor: pointer;' title="Click to change all columns" onclick="__aclSetAllRadios('2');">Disallow</th>
-      <th style='cursor: pointer;' title="Click to change all columns" onclick="__aclSetAllRadios('3');">Wiki mode</th>
-      <th style='cursor: pointer;' title="Click to change all columns" onclick="__aclSetAllRadios('4');">Allow</th>
+      <th style='cursor: pointer;' title="Click to change all columns" onclick="__aclSetAllRadios('i');">{lang:acl_lbl_field_inherit}</th>
+      <th style='cursor: pointer;' title="Click to change all columns" onclick="__aclSetAllRadios('1');">{lang:acl_lbl_field_deny}</th>
+      <th style='cursor: pointer;' title="Click to change all columns" onclick="__aclSetAllRadios('2');">{lang:acl_lbl_field_disallow}</th>
+      <th style='cursor: pointer;' title="Click to change all columns" onclick="__aclSetAllRadios('3');">{lang:acl_lbl_field_wikimode}</th>
+      <th style='cursor: pointer;' title="Click to change all columns" onclick="__aclSetAllRadios('4');">{lang:acl_lbl_field_allow}</th>
     </tr>
 <!-- ENDVAR acl_field_begin -->
 <!-- VAR acl_field_item -->
     <tr>
       <td class="{ROW_CLASS}">{FIELD_DESC}</td>
+      <td class="{ROW_CLASS}" style="text-align: center;"><input type="radio" value="i" name="{FIELD_NAME}" {FIELD_INHERIT_CHECKED} /></td>
       <td class="{ROW_CLASS}" style="text-align: center;"><input type="radio" value="1" name="{FIELD_NAME}" {FIELD_DENY_CHECKED} /></td>
       <td class="{ROW_CLASS}" style="text-align: center;"><input type="radio" value="2" name="{FIELD_NAME}" {FIELD_DISALLOW_CHECKED} /></td>
       <td class="{ROW_CLASS}" style="text-align: center;"><input type="radio" value="3" name="{FIELD_NAME}" {FIELD_WIKIMODE_CHECKED} /></td>
@@ -20,14 +22,8 @@
 <!-- ENDVAR acl_field_item -->
 <!-- VAR acl_field_end -->
     <tr>
-      <td colspan="5" class="row3">
-        <p><b>Permission types:</b></p>
-        <ul>
-          <li><b>Allow</b> means that the user is allowed to access the item</li>
-          <li><b>Wiki mode</b> means the user can access the item if wiki mode is active (per-page wiki mode is taken into account)</li>
-          <li><b>Disallow</b> means the user is denied access unless something allows it.</li>
-          <li><b>Deny</b> means that the user is denied access to the item. This setting overrides all other permissions.</li>
-        </ul>
+      <td colspan="6" class="row3">
+        {lang:acl_lbl_help}
       </td>
     </tr>
   </table>
--- a/themes/stpatty/comment.tpl	Fri Feb 22 12:46:51 2008 -0500
+++ b/themes/stpatty/comment.tpl	Fri Feb 22 12:51:53 2008 -0500
@@ -4,23 +4,30 @@
       <th colspan="2" style="text-align: left;">{DATETIME}</th>
     </tr>
     <tr>
-      <td style="width: 120px; height: 100%;" rowspan="4" valign="top" class="row1">
+      <td style="width: 120px; height: 100%;" rowspan="4" valign="top" class="row1<!-- BEGIN is_friend --> row1_green<!-- END is_friend --><!-- BEGIN is_foe --> row1_red<!-- END is_foe -->">
         <table border="0" width="100%" style="height: 100%;" cellspacing="0" cellpadding="0">
           <tr>
-            <td valign="top" class="row1">
+            <td valign="top" class="row1<!-- BEGIN is_friend --> row1_green<!-- END is_friend --><!-- BEGIN is_foe --> row1_red<!-- END is_foe -->">
               <b>{NAME}</b><br />
               <small>{USER_LEVEL}</small>
+              <!-- BEGIN user_has_avatar -->
+              <div class="avatar">
+                <a href="{USERPAGE_LINK}">
+                  <img alt="{AVATAR_ALT}" src="{AVATAR_URL}" style="border-width: 0px;" />
+                </a>
+              </div>
+              <!-- END user_has_avatar -->
             </td>
           </tr>
           <tr>
-            <td valign="bottom" class="row1">
+            <td valign="bottom" class="row1<!-- BEGIN is_friend --> row1_green<!-- END is_friend --><!-- BEGIN is_foe --> row1_red<!-- END is_foe -->">
               {SEND_PM_LINK} {ADD_BUDDY_LINK}
             </td>
           </tr>
         </table>
       </td>
       <td class="row2">
-        <b>Subject:</b> <span id="subject_{ID}">{SUBJECT}</span>
+        <b>{lang:comment_lbl_subject}</b> <span id="subject_{ID}">{SUBJECT}</span>
       </td>
     </tr>
     <tr>
@@ -42,7 +49,7 @@
     <!-- BEGIN auth_mod -->
     <tr>
       <td class="row1">
-        <b>Moderation options:</b> {MOD_APPROVE_LINK} {MOD_DELETE_LINK}
+        <b>{lang:comment_lbl_mod_options}</b> {MOD_APPROVE_LINK} {MOD_DELETE_LINK} | {MOD_IP_LINK}
       </td>
     </tr>
     <!-- END auth_mod -->
--- a/themes/stpatty/css/shamrock.css	Fri Feb 22 12:46:51 2008 -0500
+++ b/themes/stpatty/css/shamrock.css	Fri Feb 22 12:51:53 2008 -0500
@@ -23,6 +23,10 @@
   font-family: "Lucida Sans Unicode", sans-serif;
   font-size: 75%;
 }
+body#tinymce {
+  background-color: white;
+  background-image: none;
+}
 div#bg {
   min-height: 500px;
   width: 100%;
--- a/themes/stpatty/footer.tpl	Fri Feb 22 12:46:51 2008 -0500
+++ b/themes/stpatty/footer.tpl	Fri Feb 22 12:51:53 2008 -0500
@@ -10,7 +10,7 @@
                  -Dan
                  -->
           <b>{COPYRIGHT}</b><br />
-          Powered by <a href="<!-- BEGIN stupid_mode -->http://enanocms.org/<!-- BEGINELSE stupid_mode -->{URL_ABOUT_ENANO}<!-- END stupid_mode -->">Enano</a>&nbsp;&nbsp;|&nbsp;&nbsp;<a href="http://validator.w3.org/check?uri=referer">Valid XHTML 1.1</a>&nbsp;&nbsp;|&nbsp;&nbsp;<a href="http://jigsaw.w3.org/css-validator/validator?uri=referer">Valid CSS</a>&nbsp;&nbsp;|&nbsp;&nbsp;Time: [[GenTime]]s<!-- BEGIN auth_admin -->&nbsp;&nbsp;|&nbsp;&nbsp;<a href="{REPORT_URI}">[[NumQueries]] SQL</a><!-- END auth_admin -->
+          Powered by <a href="{URL_ABOUT_ENANO}">Enano</a>&nbsp;&nbsp;|&nbsp;&nbsp;<a href="http://validator.w3.org/check?uri=referer">Valid XHTML 1.1</a>&nbsp;&nbsp;|&nbsp;&nbsp;<a href="http://jigsaw.w3.org/css-validator/validator?uri=referer">Valid CSS</a>&nbsp;&nbsp;|&nbsp;&nbsp;Time: [[GenTime]]s<!-- BEGIN auth_admin -->&nbsp;&nbsp;|&nbsp;&nbsp;<a href="{REPORT_URI}">[[NumQueries]] SQL</a><!-- END auth_admin -->
           <!-- Do not remove this line or scheduled tasks will not run. -->
           <img alt=" " src="{SCRIPTPATH}/cron.php" width="1" height="1" />
         </div>
--- a/themes/stpatty/header.tpl	Fri Feb 22 12:46:51 2008 -0500
+++ b/themes/stpatty/header.tpl	Fri Feb 22 12:51:53 2008 -0500
@@ -6,8 +6,8 @@
     {JS_DYNAMIC_VARS}
     <link rel="stylesheet" type="text/css" href="{SCRIPTPATH}/includes/clientside/css/enano-shared.css" />
     <link id="mdgCss" rel="stylesheet" type="text/css" href="{SCRIPTPATH}/themes/{THEME_ID}/css/{STYLE_ID}.css" />
-    <!-- This script automatically loads the other 15 JS files -->
-    <script type="text/javascript" src="{SCRIPTPATH}/includes/clientside/static/enano-lib-basic.js"></script>
+    <!-- jsres.php is a wrapper script that compresses and caches single JS files to minimize requests -->
+    <script type="text/javascript" src="{SCRIPTPATH}/includes/clientside/jsres.php"></script>
     <!--[if lt IE 7]>
     <link rel="stylesheet" type="text/css" href="{SCRIPTPATH}/themes/{THEME_ID}/css-extra/ie-fixes-{STYLE_ID}.css" />
     <![endif]-->
@@ -82,7 +82,7 @@
           <h2>{SITE_DESC}</h2>
         </div>
         <div class="menu_nojs" id="pagebar_main">
-          <div class="label">Page tools</div>
+          <div class="label">{lang:onpage_lbl_pagetools}</div>
           {TOOLBAR}
           <ul>
             {TOOLBAR_EXTRAS}
Binary file themes/stpatty/preview.png has changed
--- a/upgrade.php	Fri Feb 22 12:46:51 2008 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,808 +0,0 @@
-<?php
-
-/*
- * Enano - an open-source CMS capable of wiki functions, Drupal-like sidebar blocks, and everything in between
- * Version 1.0.3 (Dyrad)
- * upgrade.php - upgrade script
- * Copyright (C) 2006-2007 Dan Fuhry
- *
- * This program is Free Software; you can redistribute and/or modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.
- *
- * 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.
- */
-
-define('IN_ENANO_INSTALL', 'true');
-define('IN_ENANO_UPGRADE', 'true');
-
-if(!defined('scriptPath')) {
-  $sp = dirname($_SERVER['REQUEST_URI']);
-  if($sp == '/' || $sp == '\\') $sp = '';
-  define('scriptPath', $sp);
-}
-
-if(!defined('contentPath')) {
-  $sp = dirname($_SERVER['REQUEST_URI']);
-  if($sp == '/' || $sp == '\\') $sp = '';
-  define('contentPath', $sp);
-}
-
-global $this_page, $sideinfo;
-
-function microtime_float()
-{
-  list($usec, $sec) = explode(" ", microtime());
-  return ((float)$usec + (float)$sec);
-}
-
-global $_starttime;
-$_starttime = microtime_float();
-
-// Determine directory (special case for development servers)
-if ( strpos(__FILE__, '/repo/') && file_exists('.enanodev') )
-{
-  $filename = str_replace('/repo/', '/', __FILE__);
-}
-else
-{
-  $filename = __FILE__;
-}
-
-define('ENANO_ROOT', dirname($filename));
-
-require(ENANO_ROOT.'/includes/constants.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; }
-}
-
-// SCRIPT CONFIGURATION
-// Everything related to versions goes here!
-
-// Valid versions to upgrade from
-$valid_versions = Array('1.0b1', '1.0b2', '1.0b3', '1.0b4', '1.0RC1', '1.0RC2', '1.0RC3', '1.0', '1.0.1', '1.0.1.1', '1.0.2b1', '1.0.2');
-
-// Basically a list of dependencies, which should be resolved automatically
-// If, for example, upgrading from 1.0b1 to 1.0RC1 requires one extra query that would not
-// normally be required (for whatever reason) then you would add a custom version number to the array under key '1.0b1'.
-$deps_list = Array(
-    '1.0b1' => Array('1.0b2'),
-    '1.0b2' => Array('1.0b3'),
-    '1.0b3' => Array('1.0b4'),
-    '1.0b4' => Array('1.0RC1'),
-    '1.0RC1' => Array('1.0RC2'),
-    '1.0RC2' => Array('1.0RC3'),
-    '1.0RC3' => Array('1.0'),
-    '1.0' => Array('1.0.1'),
-    '1.0.1' => Array('1.0.1.1'),
-    '1.0.1.1' => Array('1.0.2b1')
-  );
-$this_version   = '1.0.3';
-$func_list = Array(
-    '1.0' => Array('u_1_0_1_update_del_votes'),
-    '1.0b4' => Array('u_1_0_RC1_update_user_ids', 'u_1_0_RC1_add_admins_to_group', 'u_1_0_RC1_alter_files_table', 'u_1_0_RC1_destroy_session_cookie', 'u_1_0_RC1_set_contact_email', 'u_1_0_RC1_update_page_text'), // ,
-    // '1.0RC2' => Array('u_1_0_populate_userpage_comments')
-    '1.0RC3' => Array('u_1_0_RC3_make_users_extra'),
-    '1.0.2b1' => Array('u_1_0_2_nuke_template_cache', 'u_1_0_2_rebuild_search_index')
-  );
-
-if(!isset($_GET['mode'])) 
-{
-  $_GET['mode'] = 'login';
-}
-
-function err($t)
-{
-  global $template;
-  echo $t;
-  $template->footer(); 
-  exit;
-}
-
-require(ENANO_ROOT.'/includes/template.php');
-
-// Initialize the session manager
-require(ENANO_ROOT.'/includes/functions.php');
-require(ENANO_ROOT.'/includes/dbal.php');
-require(ENANO_ROOT.'/includes/paths.php');
-require(ENANO_ROOT.'/includes/sessions.php');
-require(ENANO_ROOT.'/includes/plugins.php');
-require(ENANO_ROOT.'/includes/rijndael.php');
-require(ENANO_ROOT.'/includes/render.php');
-require(ENANO_ROOT.'/includes/search.php');
-$db = new mysql();
-$db->connect();
-
-$plugins = new pluginLoader();
-
-if(!defined('ENANO_CONFIG_FETCHED'))
-{
-  // Select and fetch the site configuration
-  $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
-  }
-  
-  $enano_config = Array();
-  while($r = $db->fetchrow())
-  {
-    $enano_config[$r['config_name']] = $r['config_value'];
-  }
-  $db->free_result();
-}
-
-$v = enano_version();
-if(in_array($v, Array(false, '', '1.0b3', '1.0b4')))
-{
-  $ul_admin  = 2;
-  $ul_mod    = 1;
-  $ul_member = 0;
-  $ul_guest  = -1;
-}
-else
-{
-  $ul_admin  = USER_LEVEL_ADMIN;
-  $ul_mod    = USER_LEVEL_MOD;
-  $ul_member = USER_LEVEL_MEMBER;
-  $ul_guest  = USER_LEVEL_GUEST;
-}
-
-$_GET['title'] = 'unset';
-
-$session = new sessionManager();
-$paths = new pathManager();
-$session->start();
-
-$template = new template_nodb();
-$template->load_theme('oxygen', 'bleu', false);
-
-$modestrings = Array(
-              'login'      => 'Administrative login',
-              'welcome'    => 'Welcome',
-              'setversion' => 'Select Enano version',
-              'confirm'    => 'Confirm upgrade',
-              'upgrade'    => 'Database installation',
-              'finish'     => 'Upgrade complete'
-            );
-
-$sideinfo = '';
-$vars = $template->extract_vars('elements.tpl');
-$p = $template->makeParserText($vars['sidebar_button']);
-foreach ( $modestrings as $id => $str )
-{
-  if ( $_GET['mode'] == $id )
-  {
-    $flags = 'style="font-weight: bold; text-decoration: underline;"';
-    $this_page = $str;
-  }
-  else
-  {
-    $flags = '';
-  }
-  $p->assign_vars(Array(
-      'HREF' => '#',
-      'FLAGS' => $flags . ' onclick="return false;"',
-      'TEXT' => $str
-    ));
-  $sideinfo .= $p->run();
-}
-
-$template->init_vars();
-
-function upg_assign_vars($schema)
-{
-  $schema = str_replace('{{SITE_NAME}}',   mysql_real_escape_string(getConfig('site_name')), $schema);
-  $schema = str_replace('{{SITE_DESC}}',   mysql_real_escape_string(getConfig('site_desc')), $schema);
-  $schema = str_replace('{{COPYRIGHT}}',   mysql_real_escape_string(getConfig('copyright_notice')), $schema);
-  $schema = str_replace('{{TABLE_PREFIX}}', table_prefix, $schema);
-  if(getConfig('wiki_mode')=='1') $schema = str_replace('{{WIKI_MODE}}', '1', $schema);
-  else $schema = str_replace('{{WIKI_MODE}}', '0', $schema);
-  return $schema;
-}
-
-/* Version-specific functions */
-
-function u_1_0_RC1_update_user_ids()
-{
-  global $db;
-  // First, make sure this hasn't already been done
-  $q = $db->sql_query('SELECT username FROM '.table_prefix.'users WHERE user_id=1;');
-  if ( !$q )
-    $db->_die();
-  $row = $db->fetchrow();
-  if ( $row['username'] == 'Anonymous' )
-    return true;
-  // Find the first unused user ID
-  $used = Array();
-  $q = $db->sql_query('SELECT user_id FROM '.table_prefix.'users;');
-  if ( !$q )
-    $db->_die();
-  $notfirst = false;
-  while ( $row = $db->fetchrow() )
-  {
-    $i = intval($row['user_id']);
-    $used[$i] = true;
-    if ( !isset($used[$i - 1]) && $notfirst )
-    {
-      $id = $i - 1;
-      break;
-    }
-    $notfirst = true;
-  }
-  if ( !isset($id) )
-    $id = $i + 1;
-  if ( $id == 0 )
-    $id = 2;
-  $db->free_result();
-  
-  $q = $db->sql_query('UPDATE '.table_prefix.'users SET user_id=' . $id . ' WHERE user_id=1;');
-  if(!$q)
-    $db->_die();
-  $q = $db->sql_query('UPDATE '.table_prefix.'users SET user_id=1 WHERE user_id=-1 AND username=\'Anonymous\';');
-  if(!$q)
-    $db->_die();
-  
-}
-
-function u_1_0_RC1_add_admins_to_group()
-{
-  global $db;
-  $q = $db->sql_query('SELECT user_id FROM '.table_prefix.'users WHERE user_level=' . USER_LEVEL_ADMIN . ';');
-  if ( !$q )
-    $db->_die();
-  $base = 'INSERT INTO '.table_prefix.'group_members(group_id,user_id) VALUES';
-  $blocks = Array();
-  while ( $row = $db->fetchrow($q) )
-  {
-    $blocks[] = '(2,' . $row['user_id'] . ')';
-  }
-  $blocks = implode(',', $blocks);
-  $sql = $base . $blocks . ';';
-  if(!$db->sql_query($sql))
-    $db->_die();
-}
-
-function u_1_0_RC1_alter_files_table()
-{
-  global $db;
-  if(!is_dir(ENANO_ROOT.'/files'))
-    @mkdir(ENANO_ROOT . '/files');
-  if(!is_dir(ENANO_ROOT.'/files'))
-    die('ERROR: Couldn\'t create files directory');
-  $q = $db->sql_unbuffered_query('SELECT * FROM '.table_prefix.'files;', $db->_conn);
-  if(!$q) $db->_die();
-  while ( $row = $db->fetchrow() )
-  {
-    $file_data = base64_decode($row['data']);
-    $path = ENANO_ROOT . '/files/' . md5( $row['filename'] . '_' . $file_data ) . '_' . $row['time_id'] . $row['file_extension'];
-    @unlink($path);
-    $handle = @fopen($path, 'w');
-    if(!$handle)
-      die('fopen failed');
-    fwrite($handle, $file_data);
-    fclose($handle);
-    
-  }
-  
-  $q = $db->sql_query('ALTER TABLE '.table_prefix.'files DROP PRIMARY KEY, ADD COLUMN file_id int(12) NOT NULL auto_increment FIRST, ADD PRIMARY KEY (file_id), ADD COLUMN file_key varchar(32) NOT NULL;');
-  if(!$q) $db->_die();
-  
-  $list = Array();
-  $q = $db->sql_unbuffered_query('SELECT * FROM '.table_prefix.'files;', $db->_conn);
-  if(!$q) $db->_die();
-  while ( $row = $db->fetchrow($q) )
-  {
-    $file_data = base64_decode($row['data']);
-    $key = md5( $row['filename'] . '_' . $file_data );
-    $list[] = 'UPDATE '.table_prefix.'files SET file_key=\'' . $key . '\' WHERE file_id=' . $row['file_id'] . ';';
-  }
-  
-  foreach ( $list as $sql )
-  {
-    if(!$db->sql_query($sql)) $db->_die();
-  }
-  
-  if(!$db->sql_query('ALTER TABLE '.table_prefix.'files DROP data')) $db->_die();
-  
-}
-
-function u_1_0_RC1_destroy_session_cookie()
-{
-  unset($_COOKIE['sid']);
-  setcookie('sid', '', time()-3600*24, scriptPath);
-  setcookie('sid', '', time()-3600*24, scriptPath.'/');
-}
-
-function u_1_0_RC1_set_contact_email()
-{
-  global $db;
-  $q = $db->sql_query('SELECT email FROM '.table_prefix.'users WHERE user_level='.USER_LEVEL_ADMIN.' ORDER BY user_level ASC LIMIT 1;');
-  if(!$q)
-    $db->_die();
-  $row = $db->fetchrow();
-  setConfig('contact_email', $row['email']);
-}
-
-function u_1_0_RC1_update_page_text()
-{
-  global $db;
-  $q = $db->sql_unbuffered_query('SELECT page_id,namespace,page_text,char_tag FROM '.table_prefix.'page_text');
-  if (!$q)
-    $db->_die();
-  
-  $qs = array();
-  
-  while ( $row = $db->fetchrow($q) )
-  {
-    $row['page_text'] = str_replace(Array(
-      "{QUOT:{$row['char_tag']}}",
-      "{APOS:{$row['char_tag']}}",
-      "{SLASH:{$row['char_tag']}}"
-      ), Array(
-      '"', "'", '\\'
-      ), $row['page_text']);
-    $qs[] = 'UPDATE '.table_prefix.'page_text SET page_text=\'' . mysql_real_escape_string($row['page_text']) . '\'
-      WHERE page_id=\'' . mysql_real_escape_string($row['page_id']) . '\' AND
-            namespace=\'' . mysql_real_escape_string($row['namespace']) . '\';';
-  }
-  
-  foreach($qs as $query)
-  {
-    if(!$db->sql_query($query))
-      $db->_die();
-  }
-}
-
-function u_1_0_1_update_del_votes()
-{
-  global $db;
-  $q = $db->sql_query('SELECT urlname, namespace, delvote_ips FROM '.table_prefix.'pages;');
-  if ( !$q )
-    $db->_die();
-  
-  while ( $row = $db->fetchrow($q) )
-  {
-    $ips = strval($row['delvote_ips']);
-    if ( is_array( @unserialize($ips) ) )
-      continue;
-    $ips = explode('|', $ips);
-    $new = array(
-      'ip' => array(),
-      'u' => array()
-      );
-    $i = 0;
-    $prev = '';
-    $prev_is_ip = false;
-    foreach ( $ips as $ip )
-    {
-      $i++;
-      $current_is_ip = is_valid_ip($ip);
-      if ( $current_is_ip && $prev_is_ip )
-      {
-        $i++;
-        $new['u'][] = $prev;
-      }
-      if ( $current_is_ip )
-      {
-        $new['ip'][] = $ip;
-      }
-      else
-      {
-        $new['u'][] = $ip;
-      }
-      $prev = $ip;
-      $prev_is_ip = $current_is_ip;
-    }
-    if ( $i % 2 == 1 && $prev_is_ip )
-    {
-      $new['u'][] = $ip;
-    }
-    $new = serialize($new);
-    $e = $db->sql_query('UPDATE '.table_prefix.'pages SET delvote_ips=\'' . $db->escape($new) . '\' WHERE urlname=\'' . $db->escape($row['urlname']) . '\' AND namespace=\'' . $db->escape($row['namespace']) . '\';');
-    if ( !$e )
-      $db->_die();
-  }
-  $db->free_result($q);
-}
-
-function u_1_0_RC3_make_users_extra()
-{
-  global $db;
-  $q = $db->sql_query('SELECT user_id FROM '.table_prefix.'users WHERE user_id > 0;');
-  if ( !$q )
-    $db->_die();
-  
-  $ids = array();
-  while ( $row = $db->fetchrow() )
-  {
-    $ids[] = intval($row['user_id']);
-  }
-  
-  $ids = '(' . implode('),(', $ids) . ')';
-  if ( $ids == '' )
-    return false;
-  $sql = "INSERT INTO " . table_prefix . "users_extra(user_id) VALUES$ids;";
-  
-  if ( !$db->sql_query($sql) )
-    $db->_die();
-}
-
-function u_1_0_2_nuke_template_cache()
-{
-  $dir = @opendir(ENANO_ROOT . '/cache');
-  if ( !$dir )
-  {
-    return false;
-  }
-  while ( ($fname = @readdir($dir)) )
-  {
-    if ( preg_match('/\.tpl\.php$/', $fname) )
-    {
-      unlink( ENANO_ROOT . '/cache/' . $fname );
-    }
-  }
-}
-
-function u_1_0_2_rebuild_search_index()
-{
-  global $paths;
-  @set_time_limit(0);
-  $paths->rebuild_search_index();
-}
-
-switch($_GET['mode'])
-{
-  case "login":
-    if ( $session->user_logged_in && $session->user_level < $ul_admin )
-    {
-      $template->header();
-      echo '<p>Your user account does not have permission to perform an upgrade of Enano. Return to the <a href="index.php">index page</a>.</p>';
-      $template->footer();
-      exit;
-    }
-    if($session->user_logged_in && $session->user_level >= $ul_admin)
-    {
-      if(isset($_POST['login']))
-      {
-        $session->login_without_crypto($_POST['username'], $_POST['password'], false, $ul_admin);
-        if($session->sid_super)
-        {
-          header('Location: upgrade.php?mode=welcome&auth='.$session->sid_super);
-          exit;
-        }
-      }
-      $template->header();
-      ?>
-      <form action="upgrade.php?mode=login" method="post">
-      <table border="0" style="margin-left: auto; margin-right: auto; margin-top: 5px;" cellspacing="1" cellpadding="4">
-        <tr>
-          <th colspan="2">You must re-authenticate to perform this upgrade.</th>
-        </tr>
-        <?php
-        if(isset($_POST['login']))
-        {
-          echo '<tr><td colspan="2"><p style="color: red;">Login failed. Bad password?</p></td></tr>';
-        }
-        ?>
-        <tr>
-          <td>Username:</td><td><input type="text" name="username" size="30" /></td>
-        </tr>
-        <tr>
-          <td>Password:</td><td><input type="password" name="password" size="30" /></td>
-        </tr>
-        <tr>
-          <td colspan="2" style="text-align: center;"><input type="submit" name="login" value="Log in" />
-        </tr>
-      </table>
-      </form>
-      <?php
-    }
-    else
-    {
-      if(isset($_POST['login']))
-      {
-        $result = $session->login_without_crypto($_POST['username'], $_POST['password'], false, $ul_member);
-        if($result == 'success')
-        {
-          header('Location: upgrade.php');
-          exit;
-        }
-      }
-      $template->header();
-      ?>
-      <form action="upgrade.php?mode=login" method="post">
-      <table border="0" style="margin-left: auto; margin-right: auto; margin-top: 5px;" cellspacing="1" cellpadding="4">
-        <tr>
-          <th colspan="2">Please log in to continue with this upgrade.</th>
-        </tr>
-        <?php
-        if(isset($_POST['login']))
-        {
-          echo '<tr><td colspan="2"><p style="color: red;">Login failed. Bad password?</p></td></tr>';
-        }
-        ?>
-        <tr>
-          <td>Username:</td><td><input type="text" name="username" size="30" /></td>
-        </tr>
-        <tr>
-          <td>Password:</td><td><input type="password" name="password" size="30" /></td>
-        </tr>
-        <tr>
-          <td colspan="2" style="text-align: center;"><input type="submit" name="login" value="Log in" />
-        </tr>
-      </table>
-      </form>
-      <?php
-    }
-    break;
-  case "welcome":
-    if(!$session->sid_super) { $template->header(); echo '<p>No admin session found! Please <a href="upgrade.php">restart the upgrade</a>.</p>'; $template->footer(); exit; }
-    
-    // Just show a simple welcome page to display version information
-    $template->header();
-    require('config.php');
-    
-    ?>
-    
-    <div style="text-align: center; margin-top: 10px;">
-      <img alt="[ Enano CMS Project logo ]" src="images/enano-artwork/installer-greeting-blue.png" style="display: block; margin: 0 auto; padding-left: 134px;" />
-      <h2>Welcome to the Enano upgrade wizard</h2>
-      <?php
-      if ( file_exists('./_nightly.php') )
-      {
-        echo '<div class="warning-box" style="text-align: left; margin: 10px auto; display: table; width: 60%;"><b>You are about to upgrade to a NIGHTLY BUILD of Enano.</b><br />Nightly builds CANNOT be re-upgraded to the final release. They may also contain serious flaws, security problems, or extraneous debugging information. Continuing this process on a production site is NOT recommended.</div>';
-      }
-      ?>
-    </div>
-    <div style="display: table; margin: 0 auto;">
-      <p>You are about to upgrade Enano to version <b><?php echo $this_version; ?></b>. Before you continue, please ensure that:</p>
-      <ul>
-        <li>You have completely backed up your database (<b><?php echo "$dbhost:$dbname"; ?></b>)</li>
-        <li>You have backed up the entire Enano directory (<b><?php echo ENANO_ROOT; ?></b>)</li>
-        <li>You have reviewed the release notes for this version, and you<br />are comfortable with any known bugs or issues</li>
-        <li>If you've configured Enano to work using a MySQL user with restricted<br />privileges, you need to enable ALTER, CREATE TABLE, and CREATE INDEX privileges<br />for this upgrade to work.</li>
-      </ul>
-    </div>
-    <div style="text-align: center; margin-top: 10px;">
-      <form action="upgrade.php?mode=setversion&amp;auth=<?php echo $session->sid_super; ?>" method="post">
-        <input type="submit" value="Continue with upgrade" />
-      </form>
-    </div>
-    
-    <?php
-    
-    break;
-  case "setversion":
-    if(!$session->sid_super) { $template->header(); echo '<p>No admin session found! Please <a href="upgrade.php">restart the upgrade</a>.</p>'; $template->footer(); exit; }
-    $v = ( function_exists('enano_version') ) ? enano_version() : '';
-    if(!in_array($v, $valid_versions) && $v != '')
-    {
-      $template->header();
-      ?>
-      <p>Your version of Enano (<?php echo $v; ?>) can't be upgraded to this version (<?php echo $this_version; ?>).</p>
-      <?php
-      break;
-    } 
-    else if($v == '')
-    {
-      // OK, we don't know which version he's running. So we'll cheat ;-)
-      $template->header();
-      echo "<form action='upgrade.php?mode=confirm&amp;auth={$session->sid_super}' method='post'>";
-      ?>
-      <p>Sorry, we couldn't detect which version of Enano you're running on your server. Please select which version of Enano you have below, and make absolutely sure that you're correct.</p>
-      <p><select name="version"><?php
-        foreach($valid_versions as $c)
-        {
-          echo "<option value='{$c}'>{$c}</option>";
-        }
-      ?></select></p>
-      <p>
-        <input type="submit" value="Continue" />
-      </p>
-      <?php
-      echo `</form>`;
-      break;
-    }
-    else
-    {
-      header('Location: upgrade.php?mode=confirm&auth='.$session->sid_super);
-    }
-    break;
-  case "confirm":
-    $enano_version = ( isset($_POST['version']) ) ? $_POST['version'] : enano_version();
-    
-    $template->header();
-    if(!$session->sid_super) { echo '<p>No admin session found! Please <a href="upgrade.php">restart the upgrade</a>.</p>'; $template->footer(); exit; }
-    ?>
-      <form action="upgrade.php?mode=upgrade&amp;auth=<?php echo $session->sid_super; ?>" method="post">
-        <table border="0" style="margin-left: auto; margin-right: auto; margin-top: 5px;" cellspacing="1" cellpadding="4">
-          <tr>
-            <td colspan="2"><p><b>Are you sure you want to perform this upgrade?</b></p><p>You can still cancel the upgrade process now. If<br />the upgrade fails, you will need to roll back<br />any actions made using manual SQL queries.</p><p><b>Please clear your browser cache or<br />shift-reload after the upgrade.</b><br />If you fail to do so, some page elements may<br />be broken.</td>
-          </tr>
-          <tr>
-            <td colspan="2" style="text-align: center;">
-              <input type="hidden" name="enano_version" value="<?php echo $enano_version; ?>" />
-              <input type="submit" name="doit" value="Upgrade Enano!" />
-            </td>
-          </tr>
-        </table>
-      </form>
-    <?php
-    break;
-  case "upgrade":
-    $template->header();
-    if(!$session->sid_super) { echo '<p>No admin session found! Please <a href="upgrade.php">restart the upgrade</a>.</p>'; $template->footer(); exit; }
-    if(!isset($_POST['enano_version'])) { echo '<p>Can\'t find the version information on the POST query, are you trying to do this upgrade directly? Please <a href="upgrade.php">restart the upgrade</a>.</p>'; break; }
-    $enano_version = $_POST['enano_version'];
-    echo '<p>Preparing for schema execution...';
-      // Build an array of queries
-      $schema = file_get_contents('upgrade.sql');
-      
-      // Strip out and process version blocks
-      preg_match_all('#---BEGIN ([0-9A-z\.\-]*?)---'."\n".'((.*?)'."\n)?".'---END \\1---#is', $schema, $matches);
-      
-      $from_list  =& $matches[1];
-      $query_list =& $matches[3];
-      
-      foreach($matches[0] as $m)
-      {
-        $schema = str_replace($m, '', $schema);
-      }
-      $schema = explode("\n", $schema);
-      foreach($schema as $k => $q)
-      {
-        if(substr($q, 0, 2) == '--' || $q == '')
-        {
-          unset($schema[$k]);
-          //die('<pre>'.htmlspecialchars(print_r($schema, true)).'</pre>');
-        }
-        else
-        {
-          $schema[$k] = upg_assign_vars($schema[$k]);
-        }
-      }
-      
-      foreach($query_list as $k => $q)
-      {
-        $query_list[$k] = explode("\n", $query_list[$k]);
-        foreach($query_list[$k] as $i => $s)
-        {
-          $tq =& $query_list[$k][$i];
-          if(substr($s, 0, 2) == '--' || $s == '')
-          {
-            unset($query_list[$k][$i]);
-            //die('<pre>'.htmlspecialchars(print_r($schema, true)).'</pre>');
-          }
-          else
-          {
-            $query_list[$k][$i] = upg_assign_vars($query_list[$k][$i]);
-          }
-        }
-        $query_list[$k] = array_values($query_list[$k]);
-      }
-      
-      $assoc_list = Array();
-      
-      foreach($from_list as $i => $v)
-      {
-        $assoc_list[$v] = $query_list[$i];
-      }
-      
-      $schema = array_values($schema);
-      
-      $deps_resolved = false;
-      $installing_versions = Array($enano_version);
-      
-      while(true)
-      {
-        $v = array_keys($deps_list);
-        foreach($v as $i => $ver)
-        {
-          if(in_array($ver, $installing_versions))
-          {
-            // $ver is on the list of versions to be installed. Add its dependencies to the list of versions to install.
-            foreach($deps_list[$ver] as $dep)
-            {
-              if(!in_array($dep, $installing_versions))
-              {
-                $installing_versions[] = $dep;
-              }
-            }
-          }
-          if($i == count($deps_list) - 1)
-          {
-            break 2;
-          }
-        }
-      }
-      
-      foreach($installing_versions as $this_ver)
-      {
-        $schema = array_merge($schema, $assoc_list[$this_ver]);
-      }
-      
-      // Time for some proper SQL syntax!
-      // Also check queries for so-called injection attempts to make
-      // sure that it doesn't fail during the upgrade process and
-      // leave the user with a half-upgraded database
-      foreach($schema as $s => $q)
-      {
-        if(substr($q, strlen($q)-1, 1) != ';') 
-        {
-          $schema[$s] .= ';';
-        }
-        if ( !$db->check_query($schema[$s]) )
-        {
-          // Uh-oh, the check failed, bail out
-          // The DBAL runs sanity checks on all queries for safety,
-          // so if the check fails in mid-upgrade we are in deep
-          // dodo doo-doo.
-          echo 'Query failed sanity check, this should never happen and is a bug.</p><p>Query was:</p><pre>'.$schema[$s].'</pre>';
-          break 2;
-        }
-      }
-      
-      $schema = array_values($schema);
-      
-      // Used extensively for debugging
-      // echo '<pre>'.htmlspecialchars(print_r($schema, true)).'</pre>';
-      // break;
-      
-      echo 'done!<br />Executing upgrade schema...';
-      
-      // OK, do the loop, baby!!!
-      foreach($schema as $q)
-      {
-        if ( substr($q, 0, 1) == '@' )
-        {
-          // if the first character is @, don't fail on error
-          $db->sql_query(substr($q, 1));
-        }
-        else
-        {
-          if ( !$db->sql_query($q) )
-          {
-            echo $db->get_error();
-            break 2;
-          }
-        }
-      }
-      
-      // Call any custom functions
-      foreach ( $installing_versions as $ver )
-      {
-        if ( isset($func_list[$ver]) )
-        {
-          foreach($func_list[$ver] as $function)
-          {
-            @call_user_func($function);
-          }
-        }
-      }
-      
-      // Log the upgrade
-      $q = $db->sql_query('INSERT INTO '.table_prefix.'logs(log_type,action,time_id,date_string,author,page_text,edit_summary) VALUES(\'security\', \'upgrade_enano\', ' . time() . ', \'' . date('d M Y h:i a') . '\', \'' . mysql_real_escape_string($session->username) . '\', \'' . mysql_real_escape_string($this_version) . '\', \'' . mysql_real_escape_string($_SERVER['REMOTE_ADDR']) . '\');');
-      
-      echo 'done!</p>';
-      echo '<p>You will be redirected shortly. If you aren\'t redirected, <a href="index.php">click here</a>.</p>
-            <script type="text/javascript">setTimeout("window.location=\'index.php\'", 2000)</script>';
-    break;
-}
-$template->footer();
-
-?>
--- a/upgrade.sql	Fri Feb 22 12:46:51 2008 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,137 +0,0 @@
--- Enano CMS - upgrade SQL
--- Variables are in the format {{VAR_NAME}}
--- ALL NON-SQL LINES, even otherwise blank lines, must start with "--" or they will get sent to MySQL!
--- Common tasks (version numbers)
-DELETE FROM {{TABLE_PREFIX}}config WHERE config_name='enano_version' OR config_name='enano_beta_version' OR config_name='enano_alpha_version' OR config_name='enano_rc_version';
-INSERT INTO {{TABLE_PREFIX}}config (config_name, config_value) VALUES( 'enano_version', '1.0.3' );
----BEGIN 1.0.2---
--- No DB changes in this release
----END 1.0.2---
----BEGIN 1.0.2b1---
--- This is really optional, but could reduce confusion if regex page groups get truncated for no apparent reason.
-ALTER TABLE {{TABLE_PREFIX}}page_groups MODIFY COLUMN pg_target text DEFAULT NULL;
--- I have no idea how or why, but the f'ing index didn't get created for who-knows-how-many releases.
--- We'll attempt to create it here, but don't die if it fails
-@ALTER TABLE {{TABLE_PREFIX}}page_text ENGINE = MYISAM, COLLATE = utf8_bin, CHARSET = utf8;
-ALTER TABLE {{TABLE_PREFIX}}search_index CHARSET = utf8, COLLATE = utf8_bin, MODIFY COLUMN word varchar(64) NOT NULL;
--- The search cache is no longer needed because of the new unified search engine (it's too f'ing fast to need a cache :-D)
-@DROP TABLE {{TABLE_PREFIX}}search_cache;
--- Yes, it appears we need pages with names this long after all
-ALTER TABLE {{TABLE_PREFIX}}pages MODIFY COLUMN urlname varchar(255), MODIFY COLUMN name varchar(255);
-ALTER TABLE {{TABLE_PREFIX}}page_text MODIFY COLUMN page_id varchar(255), MODIFY COLUMN namespace varchar(63), MODIFY COLUMN page_text longtext;
-@CREATE FULLTEXT INDEX {{TABLE_PREFIX}}page_search_idx ON {{TABLE_PREFIX}}page_text(page_id, namespace, page_text);
-UPDATE {{TABLE_PREFIX}}config SET config_value='cbf:len=185;crc=55fb6f14;data=0[1],1[4],0[3],1[1],0[22],1[1],0[16],1[3],0[16],1[1],0[1],1[2],0[6],1[1],0[1],1[1],0[4],1[2],0[3],1[1],0[48],1[2],0[2],1[1],0[4],1[1],0[37]|end' WHERE config_name = 'allowed_mime_types' AND config_value='cbf:len=168;crc=c3dcad3f;data=0[1],1[4],0[3],1[1],0[2],1[1],0[11],1[1],0[7],1[1],0[9],1[1],0[6],1[3],0[10],1[1],0[2],1[2],0[1],1[1],0[1],1[2],0[6],1[3],0[1],1[1],0[2],1[4],0[1],1[2],0[3],1[1],0[4],1[2],0[26],1[5],0[6],1[2],0[2],1[1],0[4],1[1],0[10],1[2],0[1],1[1],0[6]|end';
-@UPDATE {{TABLE_PREFIX}}users SET theme='oxygen',style='bleu' WHERE user_id = 2;
----END 1.0.2b1---
----BEGIN 1.0.1.1---
----END 1.0.1.1---
----BEGIN 1.0.1---
----END 1.0.1---
----BEGIN 1.0---
--- Fix for obnoxious $_GET issue
-UPDATE {{TABLE_PREFIX}}sidebar SET block_type=1,block_content='<div class="slideblock2" style="padding: 0px;"><form action="$CONTENTPATH$$NS_SPECIAL$Search" method="get" style="padding: 0; margin: 0;"><p><input type="hidden" name="title" value="$NS_SPECIAL$Search" />$INPUT_AUTH$<input name="q" alt="Search box" type="text" size="10" style="width: 70%" /> <input type="submit" value="Go" style="width: 20%" /></p></form></div>' WHERE block_name='Search' AND item_id=4;
--- Added on advice from Neal
--- Remember that 1 = AUTH_DENY.
-INSERT INTO {{TABLE_PREFIX}}acl(target_type,target_id,page_id,namespace,rules) VALUES(2,1,'Memberlist','Special','read=1;mod_misc=1;upload_files=1;upload_new_version=1;create_page=1;edit_acl=1;');
--- Bugfix for MySQL 5.0.45, see http://forum.enanocms.org/viewtopic.php?f=5&t=8
-ALTER TABLE {{TABLE_PREFIX}}pages MODIFY COLUMN delvote_ips text DEFAULT NULL;
-CREATE TABLE {{TABLE_PREFIX}}page_groups( pg_id mediumint(8) NOT NULL auto_increment, pg_type tinyint(2) NOT NULL DEFAULT 1, pg_name varchar(255) NOT NULL DEFAULT '', pg_target varchar(255) DEFAULT NULL, PRIMARY KEY ( pg_id ) ) CHARACTER SET `utf8` COLLATE `utf8_bin`;
-CREATE TABLE {{TABLE_PREFIX}}page_group_members( pg_member_id int(12) NOT NULL auto_increment, pg_id mediumint(8) NOT NULL, page_id varchar(63) NOT NULL, namespace varchar(63) NOT NULL DEFAULT 'Article', PRIMARY KEY ( pg_member_id ) ) CHARACTER SET `utf8` COLLATE `utf8_bin`;
-CREATE TABLE {{TABLE_PREFIX}}tags( tag_id int(12) NOT NULL auto_increment, tag_name varchar(63) NOT NULL DEFAULT 'bla', page_id varchar(255) NOT NULL, namespace varchar(255) NOT NULL, user mediumint(8) NOT NULL DEFAULT 1, PRIMARY KEY ( tag_id ) ) CHARACTER SET `utf8` COLLATE `utf8_bin`;
-UPDATE {{TABLE_PREFIX}}acl SET rules=CONCAT(rules,'tag_create=4;tag_delete_own=4;tag_delete_other=4;') WHERE target_type=1 AND target_id=2;
-DELETE FROM {{TABLE_PREFIX}}search_cache;
----END 1.0---
----BEGIN 1.0RC3---
-ALTER TABLE {{TABLE_PREFIX}}users ADD COLUMN user_coppa tinyint(1) NOT NULL DEFAULT 0;
-UPDATE {{TABLE_PREFIX}}sidebar SET block_content='[[$NS_SPECIAL$CreatePage|Create a page]]\n[[$NS_SPECIAL$UploadFile|Upload file]]\n[[$NS_SPECIAL$SpecialPages|Special pages]]\n{if auth_admin}\n[[$NS_SPECIAL$EditSidebar|Edit the sidebar]]\n$ADMIN_LINK$\n{/if}' WHERE item_id=2;
-UPDATE {{TABLE_PREFIX}}sidebar SET block_content='[[User:$USERNAME$|User page]]\n[[Special:Contributions/$USERNAME$|My Contributions]]\n{if user_logged_in}\n[[$NS_SPECIAL$Preferences|Preferences]]\n[[Special:PrivateMessages|Private messages ($UNREAD_PMS$)]]\n[[Special:Usergroups|Group control panel]]\n$THEME_LINK$\n{/if}\n{if user_logged_in}\n$LOGOUT_LINK$\n{else}\n[[Special:Register|Create an account]]\n$LOGIN_LINK$\n[[Special:Login/Special:PrivateMessages|Private messages]]\n{/if}' WHERE item_id=3;
--- Updated PHP-ized search box
--- block_type=3: 3 = BLOCK_PHP
-UPDATE {{TABLE_PREFIX}}sidebar SET block_content='?><div class=\"slideblock2\" style=\"padding: 0px;\"><form action=\"<?php echo makeUrlNS(\'Special\', \'Search\'); ?>\" method=\"get\"><input name=\"q\" alt=\"Search box\" type=\"text\" size=\"10\" style=\"width: 70%\" /> <input type=\"submit\" value=\"Go\" style=\"width: 20%\" /></form></div>',block_type=3 WHERE block_name='Search';
----END 1.0RC3---
----BEGIN 1.0RC2---
--- Add the "Moderators" group
-UPDATE {{TABLE_PREFIX}}groups SET group_id=9999 WHERE group_id=3;
-UPDATE {{TABLE_PREFIX}}group_members SET group_id=9999 WHERE group_id=3;
-ALTER TABLE {{TABLE_PREFIX}}groups ADD COLUMN system_group tinyint(1) NOT NULL DEFAULT 0;
-UPDATE {{TABLE_PREFIX}}groups SET system_group=1 WHERE group_id=1 OR group_id=2;
-INSERT INTO {{TABLE_PREFIX}}groups(group_id,group_name,group_type,system_group) VALUES(3, 'Moderators', 3, 1);
--- ...and add the associated ACL rule
-INSERT INTO {{TABLE_PREFIX}}acl(target_type,target_id,page_id,namespace,rules) VALUES(1,3,NULL,NULL,'read=4;post_comments=4;edit_comments=4;edit_page=4;view_source=4;mod_comments=4;history_view=4;history_rollback=4;history_rollback_extra=4;protect=4;rename=3;clear_logs=2;vote_delete=4;vote_reset=4;delete_page=4;set_wiki_mode=2;password_set=2;password_reset=2;mod_misc=2;edit_cat=4;even_when_protected=4;upload_files=2;upload_new_version=3;create_page=3;php_in_pages=2;edit_acl=2;');
--- Reset default user's theme to Oxygen, to emphasize stable release
-UPDATE {{TABLE_PREFIX}}users SET theme='oxygen',style='bleu' WHERE user_id=1 OR user_id=2;
--- Create table with extra user information
-CREATE TABLE {{TABLE_PREFIX}}users_extra( user_id mediumint(8) NOT NULL, user_aim varchar(63) default NULL, user_yahoo varchar(63) default NULL, user_msn varchar(255) default NULL, user_xmpp varchar(255) default NULL, user_homepage text, user_location text, user_job text, user_hobbies text, email_public tinyint(1) NOT NULL default '0', userpage_comments smallint(5) NOT NULL default '0', PRIMARY KEY ( user_id ) );
--- Turn on the Enano button on the sidebar
-INSERT INTO {{TABLE_PREFIX}}config(config_name,config_value) VALUES('powered_btn', '1');
----END 1.0RC2---
----BEGIN 1.0RC1---
--- Not too many DB changes in this release - that's a good sign ;-)
-ALTER TABLE {{TABLE_PREFIX}}search_index MODIFY COLUMN word varbinary(64) NOT NULL;
--- This is to correct an issue encountered upgrading a stock Win2k3 + IIS setup
-ALTER TABLE {{TABLE_PREFIX}}page_text ENGINE = MYISAM;
-CREATE FULLTEXT INDEX {{TABLE_PREFIX}}page_search_idx ON {{TABLE_PREFIX}}page_text(page_id,namespace,page_text);
-UPDATE {{TABLE_PREFIX}}users SET user_level=3 WHERE user_level=2;
-UPDATE {{TABLE_PREFIX}}sidebar SET block_content='[[$NS_USER$$USERNAME$|User page]]\n[[$NS_SPECIAL$Contributions/$USERNAME$|My Contributions]]\n{if user_logged_in}\n[[$NS_SPECIAL$Preferences|Preferences]]\n[[$NS_SPECIAL$PrivateMessages|Private messages]]\n[[$NS_SPECIAL$Usergroups|Group control panel]]\n$THEME_LINK$\n{/if}\n{if user_logged_in}\n$LOGOUT_LINK$\n{else}\n[[$NS_SPECIAL$Register|Create an account]]\n$LOGIN_LINK$\n[[$NS_SPECIAL$Login/$NS_SPECIAL$PrivateMessages|Private messages]]\n{/if}',block_name='$USERNAME$' WHERE ( block_name='$USERNAME' OR block_name='$USERNAME$' ) AND item_id=3;
----END 1.0RC1---
----BEGIN 1.0b4---
-CREATE TABLE {{TABLE_PREFIX}}hits( hit_id bigint(20) NOT NULL auto_increment, username varchar(63) NOT NULL, time int(12) NOT NULL DEFAULT 0, page_id varchar(63), namespace varchar(63), PRIMARY KEY ( hit_id ) );
-CREATE TABLE {{TABLE_PREFIX}}search_index( word binary(32) NOT NULL, page_names text, PRIMARY KEY ( word ) );
-CREATE TABLE {{TABLE_PREFIX}}search_cache( search_id int(15) NOT NULL auto_increment, search_time int(11) NOT NULL, query text, results longblob, PRIMARY KEY ( search_id ));
-CREATE TABLE {{TABLE_PREFIX}}acl( rule_id int(12) UNSIGNED NOT NULL auto_increment, target_type tinyint(1) UNSIGNED NOT NULL, target_id int(12) UNSIGNED NOT NULL, page_id varchar(255), namespace varchar(24), rules text, PRIMARY KEY ( rule_id ) );
-ALTER TABLE  {{TABLE_PREFIX}}users ADD COLUMN old_encryption tinyint(1) NOT NULL DEFAULT 0;
-ALTER TABLE  {{TABLE_PREFIX}}users MODIFY COLUMN password text;
-ALTER TABLE  {{TABLE_PREFIX}}users ADD COLUMN temp_password text, ADD COLUMN temp_password_time int(12) NOT NULL DEFAULT 0;
-UPDATE {{TABLE_PREFIX}}users SET old_encryption=1;
-UPDATE {{TABLE_PREFIX}}users SET user_level=9 WHERE user_level=2;
-UPDATE {{TABLE_PREFIX}}users SET user_level=5 WHERE user_level=1;
-UPDATE {{TABLE_PREFIX}}users SET user_level=2 WHERE user_level=0;
-UPDATE {{TABLE_PREFIX}}users SET user_level=1 WHERE user_level=-1;
-INSERT INTO {{TABLE_PREFIX}}acl(target_type,target_id,page_id,namespace,rules) VALUES(1,2,NULL,NULL,'read=4;post_comments=4;edit_comments=4;edit_page=4;view_source=4;mod_comments=4;history_view=4;history_rollback=4;history_rollback_extra=4;protect=4;rename=4;clear_logs=4;vote_delete=4;vote_reset=4;delete_page=4;tag_create=4;tag_delete_own=4;tag_delete_other=4;set_wiki_mode=4;password_set=4;password_reset=4;mod_misc=4;edit_cat=4;even_when_protected=4;upload_files=4;upload_new_version=4;create_page=4;php_in_pages={{ADMIN_EMBED_PHP}};edit_acl=4;');
--- Group system
-CREATE TABLE {{TABLE_PREFIX}}groups( group_id mediumint(5) UNSIGNED NOT NULL auto_increment, group_name varchar(64), group_type tinyint(1) NOT NULL DEFAULT 1, PRIMARY KEY ( group_id ) );
-CREATE TABLE {{TABLE_PREFIX}}group_members( member_id int(12) UNSIGNED NOT NULL auto_increment, group_id mediumint(5) UNSIGNED NOT NULL, user_id int(12) NOT NULL, is_mod tinyint(1) NOT NULL DEFAULT 0, pending tinyint(1) NOT NULL DEFAULT 0, PRIMARY KEY ( member_id ) );
-INSERT INTO {{TABLE_PREFIX}}groups(group_id,group_name,group_type) VALUES(1, 'Everyone', 3),(2,'Administrators',3);
--- Sidebar updates
-DELETE FROM {{TABLE_PREFIX}}sidebar WHERE item_id=5 AND block_name='Links';
-INSERT INTO {{TABLE_PREFIX}}sidebar(item_order, sidebar_id, block_name, block_type, block_content) VALUES(2, 2, 'Links', 4, 'Links');
-UPDATE {{TABLE_PREFIX}}sidebar SET block_content='[[$NS_USER$$USERNAME$|User page]]\n[[$NS_SPECIAL$Contributions/$USERNAME$|My Contributions]]\n{if user_logged_in}\n[[$NS_SPECIAL$Preferences|Preferences]]\n[[$NS_SPECIAL$PrivateMessages|Private messages]]\n[[$NS_SPECIAL$Usergroups|Group control panel]]\n$THEME_LINK$\n{/if}\n{if user_logged_in}\n$LOGOUT_LINK$\n{else}\n[[$NS_SPECIAL$Register|Create an account]]\n[[$NS_SPECIAL$Login/$PAGE_URLNAME$|Log in]]\n[[$NS_SPECIAL$Login/$NS_SPECIAL$PrivateMessages|Private messages]]\n{/if}' WHERE block_name='$USERNAME$' AND item_id=3;
-UPDATE {{TABLE_PREFIX}}sidebar SET block_name='$USERNAME$' WHERE block_name='$USERNAME';
--- Set the default theme
-INSERT INTO {{TABLE_PREFIX}}themes(theme_id,theme_name,theme_order,default_style,enabled) VALUES('stpatty', 'St. Patty', 1, 'shamrock.css', 1);
-UPDATE {{TABLE_PREFIX}}themes SET theme_order=2 WHERE theme_id='oxygen';
-UPDATE {{TABLE_PREFIX}}users SET theme='stpatty',style='shamrock';
----END 1.0b4---
----BEGIN 1.0b3---
-INSERT INTO {{TABLE_PREFIX}}config(config_name, config_value) VALUES( 'allowed_mime_types', 'cbf:len=168;crc=c3dcad3f;data=0[1],1[4],0[3],1[1],0[2],1[1],0[11],1[1],0[7],1[1],0[9],1[1],0[6],1[3],0[10],1[1],0[2],1[2],0[1],1[1],0[1],1[2],0[6],1[3],0[1],1[1],0[2],1[4],0[1],1[2],0[3],1[1],0[4],1[2],0[26],1[5],0[6],1[2],0[2],1[1],0[4],1[1],0[10],1[2],0[1],1[1],0[6]|end' );
-ALTER TABLE {{TABLE_PREFIX}}privmsgs ADD COLUMN message_read tinyint(1) NOT NULL DEFAULT 0;
----END 1.0b3---
----BEGIN 1.0b2---
--- 10/1: Removed alterations to users table, moved to upgrade.php, to allow the session manager to work
-CREATE TABLE {{TABLE_PREFIX}}privmsgs( message_id int(15) NOT NULL auto_increment, message_from varchar(63), message_to varchar(255), date int(12), subject varchar(63), message_text text, folder_name varchar(63), PRIMARY KEY (message_id) );
-CREATE TABLE {{TABLE_PREFIX}}buddies( buddy_id int(15) NOT NULL auto_increment, user_id mediumint(8), buddy_user_id mediumint(8), is_friend tinyint(1) NOT NULL DEFAULT 1, PRIMARY KEY (buddy_id) );
--- Fill 'em up with a basic sidebar - sometime there will be a migration script that will convert the old sidebar format to the new
-CREATE TABLE {{TABLE_PREFIX}}sidebar( item_id smallint(3) NOT NULL auto_increment, item_order smallint(3) NOT NULL DEFAULT 0, sidebar_id smallint(3) NOT NULL DEFAULT 1, block_name varchar(63) NOT NULL, block_type tinyint(1) NOT NULL DEFAULT 0, item_enabled tinyint(1) NOT NULL DEFAULT 1, block_content text, PRIMARY KEY ( item_id ));
-INSERT INTO {{TABLE_PREFIX}}sidebar(item_id, item_order, sidebar_id, block_name, block_type, block_content) VALUES (1, 1, 1, 'Navigation', 1, '[[Main Page|Home]]'),(2, 2, 1, 'Tools', 1, '[[Special:CreatePage|Create a page]]\n[[Special:UploadFile|Upload file]]\n[[Special:SpecialPages|Special pages]]\n{if auth_admin}\n[[Special:EditSidebar|Edit the sidebar]]\n[[Special:Administration|Administration]]\n{/if}'),(3, 3, 1, '$USERNAME$', 1, '[[User:$USERNAME$|User page]]\n[[Special:Contributions/$USERNAME$|My Contributions]]\n{if user_logged_in}\n[[Special:Preferences|Preferences]]\n[[Special:PrivateMessages|Private messages]]\n$THEME_LINK$\n{/if}\n{if user_logged_in}\n$LOGOUT_LINK$\n{else}\n[[Special:Register|Create an account]]\n[[Special:Login/$PAGE_URLNAME$|Log in]]\n[[Special:Login/Special:PrivateMessages|Private messages]]\n{/if}'),(4, 4, 1, 'Search', 1, '<div class="slideblock2" style="padding: 3px;"><form action="$SCRIPTPATH$/Special:Search" method="get" style="padding: 0; margin: 0;"><p><input name="q" alt="Search box" type="text" size="10" style="width: 70%" /> <input type="submit" value="Go" style="width: 20%" /></p></form></div>'),(5, 2, 2, 'Links', 3, '$ob = Array();\nif(getConfig(''sflogo_enabled'')==''1'')\n{\n  $ob[] = ''<a style="text-align: center;" href="http://sourceforge.net/" onclick="window.open(this.href);return false;"><img border="0" alt="SourceForge.net Logo" src="http://sflogo.sourceforge.net/sflogo.php?group_id=''.getConfig(''sflogo_groupid'').''&type=''.getConfig(''sflogo_type'').''" /></a>'';\n}\nif(getConfig(''w3c_v32'')     ==''1'') $ob[] = ''<a style="text-align: center;" href="http://validator.w3.org/check?uri=referer" onclick="window.open(this.href);return false;"><img style="border: 0px solid #FFFFFF;" alt="Valid HTML 3.2" src="http://validator.w3.org/images/v32" /></a>'';\nif(getConfig(''w3c_v40'')     ==''1'') $ob[] = ''<a style="text-align: center;" href="http://validator.w3.org/check?uri=referer" onclick="window.open(this.href);return false;"><img style="border: 0px solid #FFFFFF;" alt="Valid HTML 4.0" src="http://validator.w3.org/images/v40" /></a>'';\nif(getConfig(''w3c_v401'')    ==''1'') $ob[] = ''<a style="text-align: center;" href="http://validator.w3.org/check?uri=referer" onclick="window.open(this.href);return false;"><img style="border: 0px solid #FFFFFF;" alt="Valid HTML 4.01" src="http://validator.w3.org/images/v401" /></a>'';\nif(getConfig(''w3c_vxhtml10'')==''1'') $ob[] = ''<a style="text-align: center;" href="http://validator.w3.org/check?uri=referer" onclick="window.open(this.href);return false;"><img style="border: 0px solid #FFFFFF;" alt="Valid XHTML 1.0" src="http://validator.w3.org/images/vxhtml10" /></a>'';\nif(getConfig(''w3c_vxhtml11'')==''1'') $ob[] = ''<a style="text-align: center;" href="http://validator.w3.org/check?uri=referer" onclick="window.open(this.href);return false;"><img style="border: 0px solid #FFFFFF;" alt="Valid XHTML 1.1" src="http://validator.w3.org/images/vxhtml11" /></a>'';\nif(getConfig(''w3c_vcss'')    ==''1'') $ob[] = ''<a style="text-align: center;" href="http://validator.w3.org/check?uri=referer" onclick="window.open(this.href);return false;"><img style="border: 0px solid #FFFFFF;" alt="Valid CSS" src="http://validator.w3.org/images/vcss" /></a>'';\nif(getConfig(''dbd_button'')  ==''1'') $ob[] = ''<a style="text-align: center;" href="http://www.defectivebydesign.org/join/button" onclick="window.open(this.href);return false;"><img style="border: 0px solid #FFFFFF;" alt="DRM technology restricts what you can do with your computer" src="http://defectivebydesign.org/sites/nodrm.civicactions.net/files/images/dbd_sm_btn.gif" /><br /><small>Protect your freedom &gt;&gt;</small></a>'';\nif(count($ob) > 0) echo ''<div style="text-align: center; padding: 5px;">''.implode(''<br />'', $ob).''</div>'';');
-ALTER TABLE {{TABLE_PREFIX}}banlist ADD COLUMN reason text;
--- Here's a tricky one for ya :-/ what we're trying to do is add an auto-increment primary key to a table, this was a first for me but it seemed to work, tested on MySQL 4.1.20
-ALTER TABLE {{TABLE_PREFIX}}comments ADD COLUMN comment_id int(12) NOT NULL auto_increment FIRST, ADD PRIMARY KEY ( comment_id );
--- Session manager stuff
-ALTER TABLE {{TABLE_PREFIX}}themes ADD COLUMN default_style varchar(63) NOT NULL DEFAULT '';
-ALTER TABLE {{TABLE_PREFIX}}users ADD COLUMN signature text;
-ALTER TABLE {{TABLE_PREFIX}}users ADD COLUMN reg_time int(11) NOT NULL DEFAULT 0;
-ALTER TABLE {{TABLE_PREFIX}}users ADD COLUMN account_active tinyint(1) NOT NULL DEFAULT 0;
-ALTER TABLE {{TABLE_PREFIX}}users ADD COLUMN activation_key varchar(40) NOT NULL DEFAULT 0;
-UPDATE {{TABLE_PREFIX}}users SET account_active=1;
-UPDATE {{TABLE_PREFIX}}themes SET default_style='bleu.css' WHERE theme_id='oxygen';
----END 1.0b2---
----BEGIN 1.0b1---
-CREATE TABLE {{TABLE_PREFIX}}files( time_id int(12) NOT NULL, page_id varchar(63) NOT NULL, filename varchar(127), size bigint(15) NOT NULL, mimetype varchar(63), file_extension varchar(8), data longblob, PRIMARY KEY (time_id) );
-ALTER TABLE {{TABLE_PREFIX}}pages MODIFY COLUMN protected tinyint(1) NOT NULL DEFAULT 0;
-ALTER TABLE {{TABLE_PREFIX}}pages ADD COLUMN wiki_mode tinyint(1) NOT NULL DEFAULT 2 AFTER protected;
-ALTER TABLE {{TABLE_PREFIX}}pages ADD COLUMN password varchar(40) NOT NULL DEFAULT '' AFTER wiki_mode;
-ALTER TABLE {{TABLE_PREFIX}}comments ADD COLUMN user_id mediumint(8) NOT NULL DEFAULT -1;
-ALTER TABLE {{TABLE_PREFIX}}comments ADD COLUMN time int(12) NOT NULL default 0;
-UPDATE {{TABLE_PREFIX}}pages SET wiki_mode=2;
-UPDATE {{TABLE_PREFIX}}comments SET user_id=-1;
----END 1.0b1---