diff --git a/lib/.xmlregistry/channels/channel-phpsavant.com.xml b/lib/.xmlregistry/channels/channel-phpsavant.com.xml
new file mode 100644
index 0000000000000000000000000000000000000000..3e15ed16539b2a2b2f112bac0618a27b92fc035e
--- /dev/null
+++ b/lib/.xmlregistry/channels/channel-phpsavant.com.xml
@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<channel version="1.0" xmlns="http://pear.php.net/channel-1.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://pear.php.net/channel-1.0 http://pear.php.net/dtd/channel-1.0.xsd">
+ <name>phpsavant.com</name>
+ <suggestedalias>savant</suggestedalias>
+ <summary>Savant</summary>
+ <servers>
+  <primary>
+   <rest>
+    <baseurl type="REST1.0">http://phpsavant.com/rest/</baseurl>
+    <baseurl type="REST1.1">http://phpsavant.com/rest/</baseurl>
+    <baseurl type="REST1.3">http://phpsavant.com/rest/</baseurl>
+   </rest>
+  </primary>
+ </servers>
+</channel>
diff --git a/lib/.xmlregistry/channels/channelalias-savant.txt b/lib/.xmlregistry/channels/channelalias-savant.txt
new file mode 100644
index 0000000000000000000000000000000000000000..50601c9682e9872207fe30fb369ab5c6f62087f6
--- /dev/null
+++ b/lib/.xmlregistry/channels/channelalias-savant.txt
@@ -0,0 +1 @@
+phpsavant.com
\ No newline at end of file
diff --git a/lib/.xmlregistry/packages/phpsavant.com/Savvy/0.7.3-info.xml b/lib/.xmlregistry/packages/phpsavant.com/Savvy/0.7.3-info.xml
new file mode 100644
index 0000000000000000000000000000000000000000..a9e535f7792a1a0dd14bfb3c885a6a6efb9457f1
--- /dev/null
+++ b/lib/.xmlregistry/packages/phpsavant.com/Savvy/0.7.3-info.xml
@@ -0,0 +1,100 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<package xmlns="http://pear.php.net/dtd/package-2.1" xmlns:tasks="http://pear.php.net/dtd/tasks-1.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="2.1" xsi:schemaLocation="http://pear.php.net/dtd/tasks-1.0     http://pear.php.net/dtd/tasks-1.0.xsd     http://pear.php.net/dtd/package-2.1     http://pear.php.net/dtd/package-2.1.xsd" packagerversion="2.0.0">
+ <name>Savvy</name>
+ <channel>phpsavant.com</channel>
+ <summary>Savvy is a powerful but lightweight object-oriented template system for PHP.
+</summary>
+ <description>
+Unlike other template systems, Savvy by default does not compile your
+templates into PHP; instead, it uses PHP itself as its template language so you
+don't need to learn a new markup system.</description>
+ <lead>
+  <name>Brett Bieber</name>
+  <user>saltybeagle</user>
+  <email>saltybeagle@php.net</email>
+  <active>yes</active>
+ </lead>
+ <lead>
+  <name>Gregory Beaver</name>
+  <user>cellog</user>
+  <email>cellog@php.net</email>
+  <active>yes</active>
+ </lead>
+ <date>2013-04-29</date>
+ <time>14:29:53</time>
+ <version>
+  <release>0.7.3</release>
+  <api>0.1.0</api>
+ </version>
+ <stability>
+  <release>alpha</release>
+  <api>alpha</api>
+ </stability>
+ <license uri="http://www.opensource.org/licenses/bsd-license.php">New BSD License</license>
+ <notes>Improve support for proxying arrays:
+
+* Objects which implement ArrayIterator are now proxied using a compatible object
+* Ensure keys are proxied when returned from ArrayObject
+
+
+Package Savvy API release notes for version 0.1.0.</notes>
+ <contents>
+  <dir name="/">
+   <file role="test" name="tests/test_framework.php.inc" md5sum="d7b66614eef48d4945901a43a9568b14"/>
+   <file role="test" name="tests/render/string.phpt" md5sum="1a60e68f87d277aa9c653472b8c0ef76"/>
+   <file role="test" name="tests/render/object.phpt" md5sum="5555262b6c42f604b38f3e3aaf77e974"/>
+   <file role="test" name="tests/render/Foo.tpl.php" md5sum="2af7ae28b4d35227c53921eaabfaeaad"/>
+   <file role="test" name="tests/render/fastcompile.phpt" md5sum="923e958a495177f4be567abd6d7d37f6"/>
+   <file role="test" name="tests/render/echostring.tpl.php" md5sum="138231e0b170c36ff602c09eaaa1690f"/>
+   <file role="test" name="tests/render/array.phpt" md5sum="3f284e6ec2d710398f4b67378f373de4"/>
+   <file role="test" name="tests/globals/escape.phpt" md5sum="d1b9276341877c681e62ddad93d2d1dc"/>
+   <file role="test" name="tests/globals/escape.nestedarrays.phpt" md5sum="7f1e04a1302995ed6c0a43d525ebd73d"/>
+   <file role="test" name="tests/globals/escape.arrays.phpt" md5sum="20312ab95ea7901b79e21fdd61f5dca4"/>
+   <file role="test" name="tests/globals/basic.tpl.php" md5sum="7898705f5a0a5792a191cca28501e22e"/>
+   <file role="test" name="tests/globals/basic.phpt" md5sum="ac2ae80d9f5344694e6f2d90c0417b2c"/>
+   <file role="test" name="tests/escape/string.phpt" md5sum="4fd594fef7e7621e79cefa341c2439a0"/>
+   <file role="test" name="tests/escape/raw.tpl.php" md5sum="2e7b87c466f106a575d6740258356109"/>
+   <file role="test" name="tests/escape/object.phpt" md5sum="7012a6b97c7cb20391bde8243b582e1b"/>
+   <file role="test" name="tests/escape/Foo.tpl.php" md5sum="d960fd1fa4867a04702db10cda65d772"/>
+   <file role="test" name="tests/escape/echostring.tpl.php" md5sum="a45c7c6b67b56e43935d844f358f080b"/>
+   <file role="php" name="src/Savvy/UnexpectedValueException.php" md5sum="bc88ee83b651bea0cb3190c4785be447"/>
+   <file role="php" name="src/Savvy/TemplateException.php" md5sum="0dcf725a67d3db2457f4f9793654e8d1"/>
+   <file role="php" name="src/Savvy/ObjectProxy/Traversable.php" md5sum="d8ecfde88e9de6d70e051ac27c1f5952"/>
+   <file role="php" name="src/Savvy/ObjectProxy/ArrayObject.php" md5sum="e8e70b5189d19163132d07292233fa87"/>
+   <file role="php" name="src/Savvy/ObjectProxy/ArrayIterator.php" md5sum="6e3b437bb6f98b38b309e82ea9c0c3de"/>
+   <file role="php" name="src/Savvy/ObjectProxy/ArrayAccess.php" md5sum="eadebc4221a22f59b14c31c19af03638"/>
+   <file role="php" name="src/Savvy/ObjectProxy.php" md5sum="9990f3eae842039b9e3d2570d859afd2"/>
+   <file role="php" name="src/Savvy/MapperInterface.php" md5sum="127c43a259b071872044a492d101faca"/>
+   <file role="php" name="src/Savvy/FilterAbstract.php" md5sum="dc9abe43fa8f2a7ec038d8bc4e2fd0da"/>
+   <file role="php" name="src/Savvy/FastCompilerInterface.php" md5sum="213b589107a0b18d2074167f2d0fe864"/>
+   <file role="php" name="src/Savvy/Exception.php" md5sum="1e05784e2648c5daf2bf8848f302290d"/>
+   <file role="php" name="src/Savvy/CompilerInterface.php" md5sum="45622fa0a1eea84981eb8265b43ce2da"/>
+   <file role="php" name="src/Savvy/CompilerException.php" md5sum="05e9107fb803c7f54d512a4daee8cd30"/>
+   <file role="php" name="src/Savvy/ClassToTemplateMapper.php" md5sum="fd04a4a3f7bb2e2317bc32e5451b56a3"/>
+   <file role="php" name="src/Savvy/BasicFastCompiler.php" md5sum="313d6d9ac280509c7f0e072e6841d80d"/>
+   <file role="php" name="src/Savvy/BadMethodCallException.php" md5sum="e5d06612d101d72bc82709df7ae0426e"/>
+   <file role="php" name="src/Savvy/Autoload.php" md5sum="c0ee9b9628bed191991bc641721a39d8"/>
+   <file role="php" name="src/Savvy.php" md5sum="15a9925335b9d9e2065526d89f7a6660"/>
+   <file role="doc" name="examples/templates/StringView.tpl.php" md5sum="b4746d9c4e29624cb75c4bbf74600371"/>
+   <file role="doc" name="examples/templates/stdClass.tpl.php" md5sum="ecb083ab102eac7b1bc6d5306092b36d"/>
+   <file role="doc" name="examples/templates/MyTemplate.tpl.php" md5sum="b7004c1f5eed19602e5c7afe97dbbd27"/>
+   <file role="doc" name="examples/basic.php" md5sum="74ae4c065f1920ecfb59e9a9ad6e3746"/>
+   <file role="doc" name="examples/baseball/PartialSeason.tpl.php" md5sum="028f2aa4e14931455bf1c2b89407def3"/>
+   <file role="doc" name="examples/baseball/ListItem.tpl.php" md5sum="606d5c6b9e5987776d70f5eb4431783d"/>
+   <file role="doc" name="examples/baseball/index.php" md5sum="3a7e6408b0fc2ad9a2ff6fcbeee4a43a"/>
+   <file role="doc" name="examples/baseball/BaseballTeam.tpl.php" md5sum="dd3d25e88626d358a05050b3a5b22f78"/>
+   <file role="doc" name="examples/baseball/BaseballPlayer.tpl.php" md5sum="ff0ddb3f097ac934f71c442d6893bece"/>
+  </dir>
+ </contents>
+ <dependencies>
+  <required>
+   <php>
+    <min>5.2.0</min>
+   </php>
+   <pearinstaller>
+    <min>1.4.0</min>
+   </pearinstaller>
+  </required>
+ </dependencies>
+ <phprelease/>
+</package>
diff --git a/lib/docs/phpsavant.com/Savvy/examples/baseball/BaseballPlayer.tpl.php b/lib/docs/phpsavant.com/Savvy/examples/baseball/BaseballPlayer.tpl.php
new file mode 100644
index 0000000000000000000000000000000000000000..b19f414fa7038c2d711081074f059a3cc2bd86d1
--- /dev/null
+++ b/lib/docs/phpsavant.com/Savvy/examples/baseball/BaseballPlayer.tpl.php
@@ -0,0 +1,5 @@
+<h2>Player :: <?php echo $context->name; ?></h2>
+<p>Years on team:</p>
+<ul>
+    <?php echo $savvy->render($context->years_on_team, 'ListItem.tpl.php'); ?>
+</ul>
\ No newline at end of file
diff --git a/lib/docs/phpsavant.com/Savvy/examples/baseball/BaseballTeam.tpl.php b/lib/docs/phpsavant.com/Savvy/examples/baseball/BaseballTeam.tpl.php
new file mode 100644
index 0000000000000000000000000000000000000000..f95a97bbeddf25479dcd093ef5f70b3afe1d3dfc
--- /dev/null
+++ b/lib/docs/phpsavant.com/Savvy/examples/baseball/BaseballTeam.tpl.php
@@ -0,0 +1,9 @@
+<html>
+<head>
+    <title><?php echo $context->name; ?></title>
+</head>
+<body>
+    <h1><?php echo $context->name; ?></h1>
+    <?php echo $savvy->render($context->output); ?>
+</body>
+</html>
\ No newline at end of file
diff --git a/lib/docs/phpsavant.com/Savvy/examples/baseball/ListItem.tpl.php b/lib/docs/phpsavant.com/Savvy/examples/baseball/ListItem.tpl.php
new file mode 100644
index 0000000000000000000000000000000000000000..23604d5edaad4a04a710f7b7c2dc18571f46bbd2
--- /dev/null
+++ b/lib/docs/phpsavant.com/Savvy/examples/baseball/ListItem.tpl.php
@@ -0,0 +1 @@
+<li><?php echo $savvy->render($context); ?></li>
\ No newline at end of file
diff --git a/lib/docs/phpsavant.com/Savvy/examples/baseball/PartialSeason.tpl.php b/lib/docs/phpsavant.com/Savvy/examples/baseball/PartialSeason.tpl.php
new file mode 100644
index 0000000000000000000000000000000000000000..1eb04a091234ab493df7e30a69651942663a2f7e
--- /dev/null
+++ b/lib/docs/phpsavant.com/Savvy/examples/baseball/PartialSeason.tpl.php
@@ -0,0 +1 @@
+<?php echo $context->start; ?>&mdash;<?php echo $context->end; ?>
\ No newline at end of file
diff --git a/lib/docs/phpsavant.com/Savvy/examples/baseball/index.php b/lib/docs/phpsavant.com/Savvy/examples/baseball/index.php
new file mode 100644
index 0000000000000000000000000000000000000000..fcfef095a2b55f7ace2b49b93cf9e778cdf83c61
--- /dev/null
+++ b/lib/docs/phpsavant.com/Savvy/examples/baseball/index.php
@@ -0,0 +1,58 @@
+<?php
+ini_set('display_errors',true);
+error_reporting(E_ALL^E_STRICT);
+require_once dirname(__FILE__).'/../../src/Savvy/Autoload.php';
+$classLoader = new Savvy_Autoload();
+$classLoader->register();
+
+class BaseballTeam
+{
+    protected $view = 'player';
+
+    protected $view_map = array(
+        'player' => 'BaseballPlayer'
+        );
+
+    public $name;
+
+    public $output;
+
+    function __construct($options = array())
+    {
+        if (isset($options['view'], $this->view_map[$options['view']])) {
+            $this->view = $options['view'];
+        }
+        $this->output = new $this->view_map[$this->view]();
+    }
+}
+
+class BaseballPlayer
+{
+    public $name = 'Joseph Baseball <AKA: Joey B>';
+    public $years_on_team = array(2005, 2008);
+    function __construct()
+    {
+        $this->years_on_team[] = new PartialSeason(date('Y'));
+    }
+}
+
+class PartialSeason
+{
+    public $start;
+    public $end;
+    
+    function __construct($start, $end = null)
+    {
+        $this->start = $start;
+        if ($end) {
+            $this->end = $end;
+        }
+    }
+}
+
+$team = new BaseballTeam();
+$team->name = 'Phillies';
+
+$savvy = new Savvy();
+$savvy->setEscape('htmlspecialchars');
+echo $savvy->render($team);
\ No newline at end of file
diff --git a/lib/docs/phpsavant.com/Savvy/examples/basic.php b/lib/docs/phpsavant.com/Savvy/examples/basic.php
new file mode 100644
index 0000000000000000000000000000000000000000..0f4b21a78ed75ca6a59ac558ce3983116e720795
--- /dev/null
+++ b/lib/docs/phpsavant.com/Savvy/examples/basic.php
@@ -0,0 +1,40 @@
+<?php
+ini_set('display_errors',true);
+error_reporting(E_ALL^E_STRICT);
+require_once dirname(__FILE__).'/../src/Savvy/Autoload.php';
+$classLoader = new Savvy_Autoload();
+$classLoader->register();
+
+// Set up a view object we'd like to display
+$class = new stdClass();
+$class->var1 = '<p>This is var1 inside a standard class</p>';
+
+$savvy = new Savvy();
+$savvy->addTemplatePath(__DIR__ . '/templates');
+
+// Display a simple string
+echo $savvy->render('<h1>Welcome to the Savvy Demo</h1>');
+
+// Display a string, in a custom template
+echo $savvy->render('mystring', 'StringView.tpl.php');
+
+// Display an array
+echo $savvy->render(array('<ul>', '<li>This is an array</li>', '</ul>'));
+
+// Display an object using a default class name to template mapping function
+echo $savvy->render($class);
+
+// Display the object using a specific template
+echo $savvy->render($class, 'MyTemplate.tpl.php');
+
+echo $savvy->render('<h2>Output Filtering</h2>');
+$savvy->addFilters('htmlspecialchars');
+
+// Now show an entire template with htmlspecialchars
+echo $savvy->render($class);
+
+// Ok, now remove the output filters
+$savvy->setFilters();
+
+highlight_file(__FILE__);
+
diff --git a/lib/docs/phpsavant.com/Savvy/examples/templates/MyTemplate.tpl.php b/lib/docs/phpsavant.com/Savvy/examples/templates/MyTemplate.tpl.php
new file mode 100644
index 0000000000000000000000000000000000000000..23e7ad593ac73289dcaebf0c25b6fdf8087aa563
--- /dev/null
+++ b/lib/docs/phpsavant.com/Savvy/examples/templates/MyTemplate.tpl.php
@@ -0,0 +1,2 @@
+<h2>This is MyTemplate.tpl.php</h2>
+<p>This represents using a custom output template for an object.</p>
diff --git a/lib/docs/phpsavant.com/Savvy/examples/templates/StringView.tpl.php b/lib/docs/phpsavant.com/Savvy/examples/templates/StringView.tpl.php
new file mode 100644
index 0000000000000000000000000000000000000000..36d1493312e1d7be129759545e6cbb097a349004
--- /dev/null
+++ b/lib/docs/phpsavant.com/Savvy/examples/templates/StringView.tpl.php
@@ -0,0 +1 @@
+<p>We're in the string view template, the data is: <?php echo $context; ?></p>
\ No newline at end of file
diff --git a/lib/docs/phpsavant.com/Savvy/examples/templates/stdClass.tpl.php b/lib/docs/phpsavant.com/Savvy/examples/templates/stdClass.tpl.php
new file mode 100644
index 0000000000000000000000000000000000000000..1f649fe6fd9981b815acee679a6d34c220b76419
--- /dev/null
+++ b/lib/docs/phpsavant.com/Savvy/examples/templates/stdClass.tpl.php
@@ -0,0 +1,6 @@
+<h2>This is stdClass.tpl.php</h2>
+<p>This represents the default mapping of class name to template.</p>
+<p>The class of this context is: <?php echo get_class($context); ?></p>
+<p>The $context object contains the stdClass object with access to all the member
+variables and functions, such as $context->var1</p>
+<?php echo $context->var1; ?>
\ No newline at end of file
diff --git a/lib/php/Savvy.php b/lib/php/Savvy.php
new file mode 100644
index 0000000000000000000000000000000000000000..484bdc884b30d68a6897d05911eac040e2ca741f
--- /dev/null
+++ b/lib/php/Savvy.php
@@ -0,0 +1,986 @@
+<?php
+/**
+ * Savvy
+ *
+ * PHP version 5
+ *
+ * @category  Templates
+ * @package   Savvy
+ * @author    Brett Bieber <saltybeagle@php.net>
+ * @copyright 2010 Brett Bieber
+ * @license   http://www.opensource.org/licenses/bsd-license.php New BSD License
+ * @version   SVN: $Id$
+ * @link      http://svn.php.net/repository/pear2/Savvy
+ */
+
+/**
+ * Main class for Savvy
+ *
+ * @category  Templates
+ * @package   Savvy
+ * @author    Brett Bieber <saltybeagle@php.net>
+ * @copyright 2010 Brett Bieber
+ * @license   http://www.opensource.org/licenses/bsd-license.php New BSD License
+ * @link      http://svn.php.net/repository/pear2/Savvy
+ */
+class Savvy
+{
+    /**
+    * 
+    * Array of configuration parameters.
+    * 
+    * @access protected
+    * 
+    * @var array
+    * 
+    */
+    
+    protected $__config = array(
+        'compiler'      => null,
+        'filters'       => array(),
+        'escape'        => null,
+    );
+    
+    /**
+     * Parameters for escaping.
+     * 
+     * @var array
+     */
+    protected $_escape = array(
+        'quotes'  => ENT_COMPAT,
+        'charset' => 'UTF-8',
+        );
+    
+    /**
+     * The output template to render using
+     * 
+     * @var string
+     */
+    protected $template;
+
+    /**
+     * stack of templates, so we can access the parent template
+     * 
+     * @var array
+     */
+    protected $templateStack = array();
+
+    /**
+     * To avoid stats on locating templates, populate this array with
+     * full path => 1 for any existing templates
+     * 
+     * @var array
+     */
+    protected $templateMap = array();
+    
+    /**
+     * An array of paths to look for template files in.
+     * 
+     * @var array
+     */
+    protected $template_path = array('./');
+
+    /**
+     * The current controller to use
+     * 
+     * @var string
+     */
+    protected $selected_controller;
+    
+    /**
+     * How class names are translated to templates
+     * 
+     * @var MapperInterface
+     */
+    protected $class_to_template;
+
+    /**
+     * Array of globals available within every template
+     * 
+     * @var array
+     */
+    protected $globals = array();
+    // -----------------------------------------------------------------
+    //
+    // Constructor and magic methods
+    //
+    // -----------------------------------------------------------------
+    
+    
+    /**
+    * 
+    * Constructor.
+    * 
+    * @access public
+    * 
+    * @param array $config An associative array of configuration keys for
+    * the Main object.  Any, or none, of the keys may be set.
+    * 
+    * @return Savvy A Savvy instance.
+    * 
+    */
+    
+    public function __construct($config = null)
+    {
+        $savvy = $this;
+
+        $this->selected_controller = 'basic';
+        
+        // set the default template search path
+        if (isset($config['template_path'])) {
+            // user-defined dirs
+            $this->setTemplatePath($config['template_path']);
+        }
+        
+        // set the output escaping callbacks
+        if (isset($config['escape'])) {
+            $this->setEscape($config['escape']);
+        }
+        
+        // set the default filter callbacks
+        if (isset($config['filters'])) {
+            $this->addFilters($config['filters']);
+        }
+    }
+
+    /**
+     * Basic output controller
+     * 
+     * @param mixed $context The context passed to the template
+     * @param mixed $parent  Parent template with context and parents $parent->context
+     * @param mixed $file    The filename to include
+     * @param Savvy $savvy   The Savvy templating system
+     * 
+     * @return string
+     */
+    protected static function basicOutputController($context, $parent, $file, $savvy)
+    {
+        foreach ($savvy->getGlobals() as $__name => $__value) {
+            $$__name = $__value;
+        }
+        unset($__name, $__value);
+        ob_start();
+        include $file;
+        return ob_get_clean();
+    }
+
+    /**
+     * Basic output controller
+     * 
+     * @param mixed $context The context passed to the template
+     * @param mixed $parent  Parent template with context and parents $parent->context
+     * @param mixed $file    The filename to include
+     * @param Savvy $savvy   The Savvy templating system
+     * 
+     * @return string
+     */
+    protected static function filterOutputController($context, $parent, $file, $savvy)
+    {
+        foreach ($savvy->getGlobals() as $__name => $__value) {
+            $$__name = $__value;
+        }
+        unset($__name, $__value);
+        ob_start();
+        include $file;
+        return $savvy->applyFilters(ob_get_clean());
+    }
+
+    /**
+     * Basic output controller
+     * 
+     * @param mixed $context The context passed to the template
+     * @param mixed $parent  Parent template with context and parents $parent->context
+     * @param mixed $file    The filename to include
+     * @param Savvy $savvy   The Savvy templating system
+     * 
+     * @return string
+     */
+    protected static function basicCompiledOutputController($context, $parent, $file, $savvy)
+    {
+        foreach ($savvy->getGlobals() as $__name => $__value) {
+            $$__name = $__value;
+        }
+        unset($__name, $__value);
+        ob_start();
+        include $savvy->template($file);
+        return ob_get_clean();
+    }
+
+    /**
+     * Basic output controller
+     * 
+     * @param mixed $context The context passed to the template
+     * @param mixed $parent  Parent template with context and parents $parent->context
+     * @param mixed $file    The filename to include
+     * @param Savvy $savvy   The Savvy templating system
+     * 
+     * @return string
+     */
+    protected static function filterCompiledOutputController($context, $parent, $file, $savvy)
+    {
+        foreach ($savvy->getGlobals() as $__name => $__value) {
+            $$__name = $__value;
+        }
+        unset($__name, $__value);
+        ob_start();
+        include $savvy->template($file);
+        return $savvy->applyFilters(ob_get_clean());
+    }
+
+    /**
+     * Basic output controller
+     * 
+     * @param mixed $context The context passed to the template
+     * @param mixed $parent  Parent template with context and parents $parent->context
+     * @param mixed $file    The filename to include
+     * @param Savvy $savvy   The Savvy templating system
+     * 
+     * @return string
+     */
+    protected static function basicFastCompiledOutputController($context, $parent, $file, $savvy)
+    {
+        return include $savvy->template($file);
+    }
+
+    /**
+     * Basic output controller
+     * 
+     * @param mixed $context The context passed to the template
+     * @param mixed $parent  Parent template with context and parents $parent->context
+     * @param mixed $file    The filename to include
+     * @param Savvy $savvy   The Savvy templating system
+     * 
+     * @return string
+     */
+    protected static function filterFastCompiledOutputController($context, $parent, $file, $savvy)
+    {
+        return $savvy->applyFilters(include $savvy->template($file));
+    }
+
+    /**
+     * Add a global variable which will be available inside every template
+     * 
+     * @param string $var   The global variable name
+     * @param mixed  $value The value
+     * 
+     * @return void
+     */
+    function addGlobal($name, $value)
+    {
+        switch ($name) {
+            case 'context':
+            case 'parent':
+            case 'template':
+            case 'savvy':
+            case 'this':
+                throw new Savvy_BadMethodCallException('Invalid global variable name');
+        }
+
+        if ($this->__config['escape']) {
+            switch (gettype($value)) {
+                case 'object':
+                    if (!$value instanceof Savvy_ObjectProxy) {
+                        $value = Savvy_ObjectProxy::factory($value, $this);
+                    }
+                    break;
+                case 'string':
+                case 'int':
+                case 'double':
+                    $value = $this->escape($value);
+                    break;
+                case 'array':
+                    $value = new Savvy_ObjectProxy_ArrayIterator($value, $this);
+                    break;
+            }
+        }
+
+        $this->globals[$name] = $value;
+    }
+
+    /**
+     * Get the array of assigned globals
+     * 
+     * @return array
+     */
+    function getGlobals()
+    {
+        return $this->globals;
+    }
+
+    /**
+     * Return the current template set (if any)
+     * 
+     * @return string
+     */
+    function getTemplate()
+    {
+        return $this->template;
+    }
+    
+    
+    // -----------------------------------------------------------------
+    //
+    // Public configuration management (getters and setters).
+    // 
+    // -----------------------------------------------------------------
+    
+    
+    /**
+    *
+    * Returns a copy of the Savvy configuration parameters.
+    *
+    * @access public
+    * 
+    * @param string $key The specific configuration key to return.  If null,
+    * returns the entire configuration array.
+    * 
+    * @return mixed A copy of the $this->__config array.
+    * 
+    */
+    
+    public function getConfig($key = null)
+    {
+        if (is_null($key)) {
+            // no key requested, return the entire config array
+            return $this->__config;
+        } elseif (empty($this->__config[$key])) {
+            // no such key
+            return null;
+        } else {
+            // return the requested key
+            return $this->__config[$key];
+        }
+    }
+    
+    
+    /**
+    * 
+    * Sets a custom compiler/pre-processor callback for template sources.
+    * 
+    * By default, Savvy does not use a compiler; use this to set your
+    * own custom compiler (pre-processor) for template sources.
+    * 
+    * @access public
+    * 
+    * @param mixed $compiler A compiler callback value suitable for the
+    * first parameter of call_user_func().  Set to null/false/empty to
+    * use PHP itself as the template markup (i.e., no compiling).
+    * 
+    * @return void
+    * 
+    */
+    
+    public function setCompiler(Savvy_CompilerInterface $compiler)
+    {
+        $this->__config['compiler'] = $compiler;
+        if ($compiler instanceof Savvy_FastCompilerInterface) {
+            switch ($this->selected_controller) {
+                case 'basic' :
+                case 'basiccompiled';
+                    $this->selected_controller = 'basicfastcompiled';
+                    break;
+                case 'filter' :
+                case 'filtercompiled' :
+                    $this->selected_controller = 'filterfastcompiled';
+                    break;
+            }
+            return;
+        }
+        if (!strpos($this->selected_controller, 'compiled')) {
+            $this->selected_controller .= 'compiled';
+        }
+    }
+    
+    /**
+     * Set the class to template mapper.
+     * 
+     * @see MapperInterface
+     * 
+     * @param MapperInterface $mapper The mapper interface to use 
+     * 
+     * @return Main
+     */
+    function setClassToTemplateMapper(Savvy_MapperInterface $mapper)
+    {
+        $this->class_to_template = $mapper;
+        return $this;
+    }
+    
+    /**
+     * Get the class to template mapper.
+     * 
+     * @return MapperInterface
+     */
+    function getClassToTemplateMapper()
+    {
+        if (!isset($this->class_to_template)) {
+            $this->setClassToTemplateMapper(new Savvy_ClassToTemplateMapper());
+        }
+        return $this->class_to_template;
+    }
+    
+    
+    // -----------------------------------------------------------------
+    //
+    // Output escaping and management.
+    //
+    // -----------------------------------------------------------------
+    
+    
+    /**
+    * 
+    * Clears then sets the callbacks to use when calling $this->escape().
+    * 
+    * Each parameter passed to this function is treated as a separate
+    * callback.  For example:
+    * 
+    * <code>
+    * $savvy->setEscape(
+    *     'stripslashes',
+    *     'htmlspecialchars',
+    *     array('StaticClass', 'method'),
+    *     array($object, $method)
+    * );
+    * </code>
+    * 
+    * @access public
+    *
+    * @return Main
+    *
+    */
+    
+    public function setEscape()
+    {
+        $this->__config['escape'] = @func_get_args();
+        return $this;
+    }
+    
+    
+    /**
+    *
+    * Gets the array of output-escaping callbacks.
+    *
+    * @access public
+    *
+    * @return array The array of output-escaping callbacks.
+    *
+    */
+    
+    public function getEscape()
+    {
+        return $this->__config['escape'];
+    }
+    
+    
+    /**
+     * Escapes a value for output in a view script.
+     *
+     * If escaping mechanism is one of htmlspecialchars or htmlentities, uses
+     * {@link $_encoding} setting.
+     *
+     * @param mixed $var The output to escape.
+     * 
+     * @return mixed The escaped value.
+     */
+    public function escape($var)
+    {
+        foreach ($this->__config['escape'] as $escape) {
+            if (in_array($escape,
+                    array('htmlspecialchars', 'htmlentities'), true)) {
+                $var = call_user_func($escape,
+                                      $var,
+                                      $this->_escape['quotes'],
+                                      $this->_escape['charset']);
+            } else {
+                $var = call_user_func($escape, $var);
+            }
+        }
+        return $var;
+    }
+    
+    
+    // -----------------------------------------------------------------
+    //
+    // File management
+    //
+    // -----------------------------------------------------------------
+    
+    /**
+     * Get the template path.
+     * 
+     * @return array
+     */
+    function getTemplatePath()
+    {
+        return $this->template_path;
+    }
+    
+    /**
+    *
+    * Sets an entire array of search paths for templates or resources.
+    *
+    * @access public
+    * 
+    * @param string|array $path The new set of search paths.  If null or
+    * false, resets to the current directory only.
+    *
+    * @return Main
+    *
+    */
+    
+    public function setTemplatePath($path = null)
+    {
+        // clear out the prior search dirs, add default
+        $this->template_path = array('./');
+        
+        // actually add the user-specified directories
+        $this->addTemplatePath($path);
+        return $this;
+    }
+    
+    
+    /**
+    *
+    * Adds to the search path for templates and resources.
+    *
+    * @access public
+    *
+    * @param string|array $path The directory or stream to search.
+    *
+    * @return Main
+    *
+    */
+    
+    public function addTemplatePath($path)
+    {
+        // convert from path string to array of directories
+        if (is_string($path) && !strpos($path, '://')) {
+        
+            // the path config is a string, and it's not a stream
+            // identifier (the "://" piece). add it as a path string.
+            $path = explode(PATH_SEPARATOR, $path);
+            
+            // typically in path strings, the first one is expected
+            // to be searched first. however, Savvy uses a stack,
+            // so the first would be last.  reverse the path string
+            // so that it behaves as expected with path strings.
+            $path = array_reverse($path);
+            
+        } else {
+        
+            // just force to array
+            settype($path, 'array');
+            
+        }
+        
+        // loop through the path directories
+        foreach ($path as $dir) {
+        
+            // no surrounding spaces allowed!
+            $dir = trim($dir);
+            
+            // add trailing separators as needed
+            if (strpos($dir, '://')) {
+                if (substr($dir, -1) != '/') {
+                    // stream
+                    $dir .= '/';
+                }
+            } elseif (substr($dir, -1) != DIRECTORY_SEPARATOR) {
+                if (false !== strpos($dir, '..')) {
+                    // checking for weird paths here removes directory traversal threat
+                    throw new Savvy_UnexpectedValueException('upper directory reference .. cannot be used in template path');
+                }
+                // directory
+                $dir .= DIRECTORY_SEPARATOR;
+            }
+
+            // add to the top of the search dirs
+            array_unshift(
+                $this->template_path,
+                $dir
+            );
+        }
+    }
+    
+    
+    /**
+    * 
+    * Searches the directory paths for a given file.
+    * 
+    * @param string $file The file name to look for.
+    * 
+    * @return string|bool The full path and file name for the target file,
+    * or boolean false if the file is not found in any of the paths.
+    *
+    */
+    
+    public function findTemplateFile($file)
+    {
+        if (false !== strpos($file, '..')) {
+            // checking for weird path here removes directory traversal threat
+            throw new Savvy_UnexpectedValueException('upper directory reference .. cannot be used in template filename');
+        }
+        
+        // start looping through the path set
+        foreach ($this->template_path as $path) {
+            // get the path to the file
+            $fullname = $path . $file;
+
+            if (isset($this->templateMap[$fullname])) {
+                return $fullname;
+            }
+
+            if (!@is_readable($fullname)) {
+                continue;
+            }
+
+            return $fullname;
+        }
+
+        // could not find the file in the set of paths
+        throw new Savvy_TemplateException('Could not find the template ' . $file);
+    }
+    
+    
+    // -----------------------------------------------------------------
+    //
+    // Template processing
+    //
+    // -----------------------------------------------------------------
+    
+    /**
+     * Render context data through a template.
+     * 
+     * This method allows you to render data through a template. Typically one
+     * will pass the model they wish to display through an optional template.
+     * If no template is specified, the ClassToTemplateMapper::map() method
+     * will be called which should return the name of a template to render.
+     * 
+     * Arrays will be looped over and rendered through the template specified.
+     * 
+     * Strings, ints, and doubles will returned if no template parameter is 
+     * present.
+     * 
+     * Within templates, two variables will be available, $context and $savvy.
+     * The $context variable will contain the data passed to the render method,
+     * the $savvy object will be an instance of the Main class with which you
+     * can render nested data through partial templates.
+     * 
+     * @param mixed $mixed     Data to display through the template.
+     * @param string $template A template to display data in.
+     * 
+     * @return string The template output
+     */
+    function render($mixed = null, $template = null)
+    {
+        $method = 'render'.gettype($mixed);
+        return $this->$method($mixed, $template);
+    }
+    
+    /**
+     * Called when a resource is rendered
+     * 
+     * @param resource $resouce  The resources
+     * @param string   $template Template
+     * 
+     * @return void
+     * 
+     * @throws UnexpectedValueException
+     */
+    protected function renderResource($resouce, $template = null)
+    {
+        throw new Savvy_UnexpectedValueException('No way to render a resource!');
+    }
+    
+    protected function renderBoolean($bool, $template = null)
+    {
+        return $this->renderString((string)$bool, $template);
+    }
+    
+    protected function renderDouble($double, $template = null)
+    {
+        return $this->renderString($double, $template);
+    }
+    
+    protected function renderInteger($int, $template = null)
+    {
+        return $this->renderString($int, $template);
+    }
+    
+    /**
+     * Render string of data
+     * 
+     * @param string $string   String of data
+     * @param string $template A template to display the string in
+     * 
+     * @return string
+     */
+    protected function renderString($string, $template = null)
+    {
+        if ($this->__config['escape']) {
+            $string = $this->escape($string);
+        }
+        
+        if ($template) {
+            return $this->fetch($string, $template);
+        }
+
+        if (!$this->__config['filters']) {
+            return $string;
+        }
+        return $this->applyFilters($string);
+    }
+    
+    /**
+     * Used to render context array
+     * 
+     * @param array  $array    Data to render
+     * @param string $template Template to render
+     * 
+     * @return string Rendered output
+     */
+    protected function renderArray(array $array, $template = null)
+    {
+        $output = '';
+        foreach ($array as $mixed) {
+            $output .= $this->render($mixed, $template);
+        }
+        return $output;
+    }
+
+    /**
+     * Render an associative array of data through a template.
+     * 
+     * Three parameters will be passed to the closure, the array key, value,
+     * and selective third parameter.
+     * 
+     * @param array   $array    Associative array of data
+     * @param mixed   $selected Optional parameter to pass
+     * @param Closure $template A closure that will be called
+     * 
+     * @return string
+     */
+    public function renderAssocArray(array $array, $selected = false, Closure $template)
+    {
+        $ret = '';
+        foreach ($array as $key => $element) {
+            $ret .= $template($key, $element, $selected);
+        }
+        return $ret;
+    }
+
+    protected function renderArrayAccess(ArrayAccess $array, $template = null)
+    {
+        $ret = '';
+        foreach ($array as $key => $element) {
+            $ret .= $this->render($element, $template);
+        }
+        return $ret;
+    }
+
+    /**
+     * Render an if else conditional template output.
+     * 
+     * @param mixed  $condition      The conditional to evaluate
+     * @param mixed  $render         Context data to render if condition is true
+     * @param mixed  $else           Context data to render if condition is false
+     * @param string $rendertemplate If true, render using this template
+     * @param string $elsetemplate   If false, render using this template
+     * 
+     * @return string
+     */
+    public function renderElse($condition, $render, $else, $rendertemplate = null, $elsetemplate = null)
+    {
+        if ($condition) {
+            $this->render($render, $rendertemplate);
+        } else {
+            $this->render($else, $elsetemplate);
+        }
+    }
+    
+    /**
+     * Used to render an object through a template.
+     * 
+     * @param object $object   Model containing data
+     * @param string $template Template to render data through
+     * 
+     * @return string Rendered output
+     */
+    protected function renderObject($object, $template = null)
+    {
+        if ($this->__config['escape']) {
+
+            if (!$object instanceof Savvy_ObjectProxy) {
+                $object = Savvy_ObjectProxy::factory($object, $this);
+            }
+
+            if ($object instanceof Savvy_ObjectProxy_ArrayIterator) {
+                return $this->renderArrayAccess($object);
+            }
+        }
+        return $this->fetch($object, $template);
+    }
+    
+    /**
+     * Used to render null through an optional template
+     * 
+     * @param null   $null     The null var
+     * @param string $template Template to render null through
+     * 
+     * @return string Rendered output
+     */
+    protected function renderNULL($null, $template = null)
+    {
+        if ($template) {
+            return $this->fetch(null, $template);
+        }
+    }
+    
+    protected function fetch($mixed, $template = null)
+    {
+        if ($template) {
+            $this->template = $template;
+        } else {
+            if ($mixed instanceof Savvy_ObjectProxy) {
+                $class = $mixed->__getClass();
+            } else {
+                $class = get_class($mixed);
+            }
+            $this->template = $this->getClassToTemplateMapper()->map($class);
+        }
+        $current          = new stdClass;
+        $current->file    = $this->findTemplateFile($this->template);
+        $current->context = $mixed;
+        $current->parent  = null;
+        if (count($this->templateStack)) {
+            $current->parent = $this->templateStack[count($this->templateStack)-1];
+        }
+        $this->templateStack[] = $current;
+        $ret = call_user_func(array($this, $this->selected_controller.'OutputController'), $current->context, $current->parent, $current->file, $this);
+        array_pop($this->templateStack);
+        return $ret;
+    }
+    
+    /**
+    *
+    * Compiles a template and returns path to compiled script.
+    * 
+    * By default, Savvy does not compile templates, it uses PHP as the
+    * markup language, so the "compiled" template is the same as the source
+    * template.
+    *
+    * If a compiler is specific, this method is used to look up the compiled
+    * template script name
+    *
+    * @param string $tpl The template source name to look for.
+    * 
+    * @return string The full path to the compiled template script.
+    * 
+    * @throws Savvy_UnexpectedValueException
+    * @throws Savvy_Exception
+    * 
+    */
+    
+    public function template($tpl = null)
+    {
+        // find the template source.
+        $file = $this->findTemplateFile($tpl);
+        
+        // are we compiling source into a script?
+        if ($this->__config['compiler']) {
+            // compile the template source and get the path to the
+            // compiled script (will be returned instead of the
+            // source path)
+            $result = $this->__config['compiler']->compile($file, $this);
+        } else {
+            // no compiling requested, use the source path
+            $result = $file;
+        }
+        
+        // is there a script from the compiler?
+        if (!$result) {
+            // return an error, along with any error info
+            // generated by the compiler.
+            throw new Savvy_TemplateException('Compiler error for template '.$tpl.'. '.$result );
+            
+        } else {
+            // no errors, the result is a path to a script
+            return $result;
+        }
+    }
+    
+    
+    // -----------------------------------------------------------------
+    //
+    // Filter management and processing
+    //
+    // -----------------------------------------------------------------
+    
+    
+    /**
+    * 
+    * Resets the filter stack to the provided list of callbacks.
+    * 
+    * @access protected
+    * 
+    * @param array An array of filter callbacks.
+    * 
+    * @return void
+    * 
+    */
+    
+    public function setFilters()
+    {
+        $this->__config['filters'] = (array) @func_get_args();
+        if (!$this->__config['filters']) {
+            $this->selected_controller = 'basic';
+        } else {
+            $this->selected_controller = 'filter';
+        }
+    }
+    
+    
+    /**
+    * 
+    * Adds filter callbacks to the stack of filters.
+    * 
+    * @access protected
+    * 
+    * @param array An array of filter callbacks.
+    * 
+    * @return void
+    * 
+    */
+    
+    public function addFilters()
+    {
+        // add the new filters to the static config variable
+        // via the reference
+        foreach ((array) @func_get_args() as $callback) {
+            $this->__config['filters'][] = $callback;
+            $this->selected_controller = 'filter';
+        }
+    }
+    
+    
+    /**
+    * 
+    * Runs all filter callbacks on buffered output.
+    * 
+    * @access protected
+    * 
+    * @param string The template output.
+    * 
+    * @return void
+    * 
+    */
+    
+    public function applyFilters($buffer)
+    {
+        foreach ($this->__config['filters'] as $callback) {
+            $buffer = call_user_func($callback, $buffer);
+        }
+        return $buffer;
+    }
+    
+}
diff --git a/lib/php/Savvy/Autoload.php b/lib/php/Savvy/Autoload.php
new file mode 100644
index 0000000000000000000000000000000000000000..a3ab8d26f98f01eb3ab0d2833d39d1c3f4342294
--- /dev/null
+++ b/lib/php/Savvy/Autoload.php
@@ -0,0 +1,139 @@
+<?php
+/**
+* SplClassLoader implementation that implements the technical interoperability
+* standards for PHP 5.3 namespaces and class names.
+*
+* http://groups.google.com/group/php-standards/web/final-proposal
+*
+* // Example which loads classes for the Doctrine Common package in the
+* // Doctrine\Common namespace.
+* $classLoader = new SplClassLoader('Doctrine\Common', '/path/to/doctrine');
+* $classLoader->register();
+*
+* @author Jonathan H. Wage <jonwage@gmail.com>
+* @author Roman S. Borschel <roman@code-factory.org>
+* @author Matthew Weier O'Phinney <matthew@zend.com>
+* @author Kris Wallsmith <kris.wallsmith@gmail.com>
+* @author Fabien Potencier <fabien.potencier@symfony-project.org>
+*/
+class Savvy_Autoload
+{
+    private $_fileExtension = '.php';
+    private $_namespace;
+    private $_includePath;
+    private $_namespaceSeparator = '\\';
+ 
+    /**
+     * Creates a new <tt>SplClassLoader</tt> that loads classes of the
+     * specified namespace.
+     *
+     * @param string $ns The namespace to use.
+     */
+    public function __construct($ns = null, $includePath = null)
+    {
+        $this->_namespace = $ns;
+        if ($includePath) {
+            $this->_includePath = $includePath;
+        } else {
+            $this->_includePath = dirname(dirname(__FILE__));
+        }
+    }
+ 
+    /**
+     * Sets the namespace separator used by classes in the namespace of this class loader.
+     *
+     * @param string $sep The separator to use.
+     */
+    public function setNamespaceSeparator($sep)
+    {
+        $this->_namespaceSeparator = $sep;
+    }
+ 
+    /**
+     * Gets the namespace seperator used by classes in the namespace of this class loader.
+     *
+     * @return void
+     */
+    public function getNamespaceSeparator()
+    {
+        return $this->_namespaceSeparator;
+    }
+ 
+    /**
+     * Sets the base include path for all class files in the namespace of this class loader.
+     *
+     * @param string $includePath
+     */
+    public function setIncludePath($includePath)
+    {
+        $this->_includePath = $includePath;
+    }
+ 
+    /**
+     * Gets the base include path for all class files in the namespace of this class loader.
+     *
+     * @return string $includePath
+     */
+    public function getIncludePath()
+    {
+        return $this->_includePath;
+    }
+ 
+    /**
+     * Sets the file extension of class files in the namespace of this class loader.
+     *
+     * @param string $fileExtension
+     */
+    public function setFileExtension($fileExtension)
+    {
+        $this->_fileExtension = $fileExtension;
+    }
+ 
+    /**
+     * Gets the file extension of class files in the namespace of this class loader.
+     *
+     * @return string $fileExtension
+     */
+    public function getFileExtension()
+    {
+        return $this->_fileExtension;
+    }
+ 
+    /**
+     * Installs this class loader on the SPL autoload stack.
+     */
+    public function register()
+    {
+        spl_autoload_register(array($this, 'loadClass'));
+    }
+ 
+    /**
+     * Uninstalls this class loader from the SPL autoloader stack.
+     */
+    public function unregister()
+    {
+        spl_autoload_unregister(array($this, 'loadClass'));
+    }
+ 
+    /**
+     * Loads the given class or interface.
+     *
+     * @param string $className The name of the class to load.
+     * @return void
+     */
+    public function loadClass($className)
+    {
+        if (null === $this->_namespace || $this->_namespace.$this->_namespaceSeparator === substr($className, 0, strlen($this->_namespace.$this->_namespaceSeparator))) {
+            $fileName = '';
+            $namespace = '';
+            if (false !== ($lastNsPos = strripos($className, $this->_namespaceSeparator))) {
+                $namespace = substr($className, 0, $lastNsPos);
+                $className = substr($className, $lastNsPos + 1);
+                $fileName = str_replace($this->_namespaceSeparator, DIRECTORY_SEPARATOR, $namespace) . DIRECTORY_SEPARATOR;
+            }
+            $fileName .= str_replace('_', DIRECTORY_SEPARATOR, $className) . $this->_fileExtension;
+
+            require ($this->_includePath !== null ? $this->_includePath . DIRECTORY_SEPARATOR : '') . $fileName;
+        }
+    }
+}
diff --git a/lib/php/Savvy/BadMethodCallException.php b/lib/php/Savvy/BadMethodCallException.php
new file mode 100644
index 0000000000000000000000000000000000000000..1722ba7194d94435763527461df5e5cdf7983be0
--- /dev/null
+++ b/lib/php/Savvy/BadMethodCallException.php
@@ -0,0 +1,2 @@
+<?php
+class Savvy_BadMethodCallException extends BadMethodCallException implements Savvy_Exception {}
\ No newline at end of file
diff --git a/lib/php/Savvy/BasicFastCompiler.php b/lib/php/Savvy/BasicFastCompiler.php
new file mode 100644
index 0000000000000000000000000000000000000000..227850870c949d83dcc2451922d8f73419fb8479
--- /dev/null
+++ b/lib/php/Savvy/BasicFastCompiler.php
@@ -0,0 +1,51 @@
+<?php
+class Savvy_BasicFastCompiler implements Savvy_FastCompilerInterface
+{
+    /**
+     * Directory where compiled templates will be stored
+     * 
+     * @var string
+     */
+    protected $compiledtemplatedir;
+
+    /**
+     * Constructor for the BasicFastCompiler
+     * 
+     * @param string $compiledtemplatedir Where to store compiled templates
+     * 
+     * @throws UnexpectedValueException
+     */
+    function __construct($compiledtemplatedir)
+    {
+        $this->compiledtemplatedir = realpath($compiledtemplatedir);
+        if (!$this->compiledtemplatedir && !is_writable($this->compiledtemplatedir)) {
+            throw new Savvy_UnexpectedValueException('Unable to compile templates into ' .
+                                               $compiledtemplatedir . ', directory does not exist ' .
+                                               'or is unwritable');
+        }
+        $this->compiledtemplatedir .= DIRECTORY_SEPARATOR;
+    }
+
+    /**
+     * Compile a template.
+     * 
+     * @param string $name   Template to compile
+     * @param Main   $savvy Savvy main object
+     *
+     * @return string Name of the compiled template file.
+     */
+    function compile($name, $savvy)
+    {
+        $cname = $this->compiledtemplatedir . md5($name);
+        if (file_exists($cname)) {
+            if (filemtime($name) == filemtime($cname)) {
+                return $cname;
+            }
+        }
+        $a = file_get_contents($name);
+        $a = "<?php return '" . str_replace(array('<?php echo', '?>'), array('\' . ', ' . \''), $a) . "';";
+        file_put_contents($cname, $a);
+        touch($cname, filemtime($name));
+        return $cname;
+    }
+}
\ No newline at end of file
diff --git a/lib/php/Savvy/ClassToTemplateMapper.php b/lib/php/Savvy/ClassToTemplateMapper.php
new file mode 100644
index 0000000000000000000000000000000000000000..b8d8c92243a26315d452cb537eb83fd5a77cb85a
--- /dev/null
+++ b/lib/php/Savvy/ClassToTemplateMapper.php
@@ -0,0 +1,101 @@
+<?php
+/**
+ * Savvy_ClassToTemplateMapper
+ *
+ * PHP version 5
+ *
+ * @category  Templates
+ * @package   Savvy
+ * @author    Brett Bieber <saltybeagle@php.net>
+ * @copyright 2010 Brett Bieber
+ * @license   http://www.opensource.org/licenses/bsd-license.php New BSD License
+ * @version   SVN: $Id$
+ * @link      http://svn.php.net/repository/pear2/Savvy
+ */
+
+/**
+ * Savvy_ClassToTemplateMapper class for Savvy
+ * 
+ * This class allows class names to be mapped to template names though a simple
+ * scheme.
+ *
+ * @category  Templates
+ * @package   Savvy
+ * @author    Brett Bieber <saltybeagle@php.net>
+ * @copyright 2010 Brett Bieber
+ * @license   http://www.opensource.org/licenses/bsd-license.php New BSD License
+ * @link      http://svn.php.net/repository/pear2/Savvy
+ */
+class Savvy_ClassToTemplateMapper implements Savvy_MapperInterface
+{
+    /**
+     * Default template mapping can be temporarily overridden by 
+     * assigning a direct template name.
+     * 
+     * ClassToTemplateMapper::$output_template['My_Class'] = 'My/Class_rss.tpl.php';
+     * 
+     * @var array
+     */
+    static $output_template       = array();
+    
+    /**
+     * What character to use as a directory separator when mapping class names
+     * to templates.
+     * 
+     * @var string
+     */
+    static $directory_separator   = '_';
+    
+    /**
+     * Strip something out of class names before mapping them to templates.
+     * 
+     * This can be useful if your class names are very long, and you don't
+     * want empty subdirectories within your templates directory.
+     * 
+     * @var string
+     */
+    static $classname_replacement = '';
+    
+    /**
+     * The file extension to use
+     * 
+     * @var string
+     */
+    static $template_extension = '.tpl.php';
+    
+    /**
+     * Maps class names to template filenames.
+     * 
+     * Underscores and namespace separators in class names are replaced with 
+     * directory separators.
+     * 
+     * Examples:
+     * Class           => Class.tpl.php
+     * Other_Class     => Other/Class.tpl.php
+     * namespace\Class => namespace/Class.tpl.php
+     *
+     * @param string $class Class name to map to a template
+     * 
+     * @return string Template file name
+     */
+    function map($class)
+    {
+        if (isset(self::$output_template[$class])) {
+            $class = self::$output_template[$class];
+        }
+        
+        $class = str_replace(array(self::$classname_replacement,
+                                   self::$directory_separator,
+                                   '\\'),
+                             array('',
+                                   DIRECTORY_SEPARATOR,
+                                   DIRECTORY_SEPARATOR),
+                             $class);
+        
+        $templatefile = $class . self::$template_extension;
+        
+        return $templatefile;
+    }
+    
+}
+?>
\ No newline at end of file
diff --git a/lib/php/Savvy/CompilerException.php b/lib/php/Savvy/CompilerException.php
new file mode 100644
index 0000000000000000000000000000000000000000..1489a2b50e41c9ce15011238ad6e19845adebd87
--- /dev/null
+++ b/lib/php/Savvy/CompilerException.php
@@ -0,0 +1,3 @@
+<?php
+class Savvy_CompilerException extends Exception implements Savvy_Exception {}
+?>
\ No newline at end of file
diff --git a/lib/php/Savvy/CompilerInterface.php b/lib/php/Savvy/CompilerInterface.php
new file mode 100644
index 0000000000000000000000000000000000000000..29b1c07fc472423f4030bb5b1c76d37cd7dce019
--- /dev/null
+++ b/lib/php/Savvy/CompilerInterface.php
@@ -0,0 +1,6 @@
+<?php
+
+interface Savvy_CompilerInterface
+{
+    function compile($savvy, $name);
+}
\ No newline at end of file
diff --git a/lib/php/Savvy/Exception.php b/lib/php/Savvy/Exception.php
new file mode 100644
index 0000000000000000000000000000000000000000..1aac0b7dc0230c06cd826e2f6c7776d7bccb1c13
--- /dev/null
+++ b/lib/php/Savvy/Exception.php
@@ -0,0 +1,6 @@
+<?php
+interface Savvy_Exception
+{
+
+}
+?>
\ No newline at end of file
diff --git a/lib/php/Savvy/FastCompilerInterface.php b/lib/php/Savvy/FastCompilerInterface.php
new file mode 100644
index 0000000000000000000000000000000000000000..49cace38837e0e7a68242673a4ace91d864a479c
--- /dev/null
+++ b/lib/php/Savvy/FastCompilerInterface.php
@@ -0,0 +1,5 @@
+<?php
+
+interface Savvy_FastCompilerInterface extends Savvy_CompilerInterface
+{
+}
\ No newline at end of file
diff --git a/lib/php/Savvy/FilterAbstract.php b/lib/php/Savvy/FilterAbstract.php
new file mode 100644
index 0000000000000000000000000000000000000000..c1a0be689eee13137671356ca51342a4dd324ff7
--- /dev/null
+++ b/lib/php/Savvy/FilterAbstract.php
@@ -0,0 +1,85 @@
+<?php
+
+/**
+* 
+* Abstract Savvy_Filter class.
+* 
+* @package Savvy
+* 
+* @author Paul M. Jones <pmjones@ciaweb.net>
+* 
+* @license http://www.gnu.org/copyleft/lesser.html LGPL
+* 
+* @version $Id: Filter.php,v 1.5 2005/04/29 16:23:50 pmjones Exp $
+*
+*/
+
+/**
+* 
+* Abstract Savvy_Filter class.
+*
+* You have to extend this class for it to be useful; e.g., "class
+* Savvy_Filter_example extends Savvy_Filter".
+* 
+* @package Savvy
+* 
+* @author Paul M. Jones <pmjones@ciaweb.net>
+* 
+*/
+abstract class Savvy_FilterAbstract
+{
+    
+    
+    /**
+    * 
+    * Optional reference to the calling Savvy object.
+    * 
+    * @access protected
+    * 
+    * @var object
+    * 
+    */
+    
+    protected $savvy = null;
+    
+    
+    /**
+    * 
+    * Constructor.
+    * 
+    * @access public
+    * 
+    * @param array $conf An array of configuration keys and values for
+    * this filter.
+    * 
+    * @return void
+    * 
+    */
+    
+    public function __construct($conf = null)
+    {
+        settype($conf, 'array');
+        foreach ($conf as $key => $val) {
+            $this->$key = $val;
+        }
+    }
+    
+    
+    /**
+    * 
+    * Stub method for extended behaviors.
+    *
+    * @access public
+    * 
+    * @param string $text The text buffer to filter.
+    *
+    * @return string The text buffer after it has been filtered.
+    *
+    */
+    
+    public static function filter($text)
+    {
+        return $text;
+    }
+}
+?>
\ No newline at end of file
diff --git a/lib/php/Savvy/MapperInterface.php b/lib/php/Savvy/MapperInterface.php
new file mode 100644
index 0000000000000000000000000000000000000000..82d6b86be505a59b5dfff7837cbfbf165fa5ff93
--- /dev/null
+++ b/lib/php/Savvy/MapperInterface.php
@@ -0,0 +1,6 @@
+<?php
+
+interface Savvy_MapperInterface
+{
+    function map($name);
+}
\ No newline at end of file
diff --git a/lib/php/Savvy/ObjectProxy.php b/lib/php/Savvy/ObjectProxy.php
new file mode 100644
index 0000000000000000000000000000000000000000..a9803d046327c05357d96e50d43422867273a457
--- /dev/null
+++ b/lib/php/Savvy/ObjectProxy.php
@@ -0,0 +1,222 @@
+<?php
+/**
+ * Savvy_ObjectProxy
+ *
+ * PHP version 5
+ *
+ * @category  Templates
+ * @package   Savvy
+ * @author    Brett Bieber <saltybeagle@php.net>
+ * @copyright 2010 Brett Bieber
+ * @license   http://www.opensource.org/licenses/bsd-license.php New BSD License
+ * @version   SVN: $Id$
+ * @link      http://svn.php.net/repository/pear2/Savvy
+ */
+
+/**
+ * ObjectProxy class for Savvy
+ *
+ * The ObjectProxy acts as an intermediary between an object and a template.
+ * The $context variable will be an ObjectProxy which proxies member variable
+ * access so escaping can be applied.
+ *
+ * @category  Templates
+ * @package   Savvy
+ * @author    Brett Bieber <saltybeagle@php.net>
+ * @copyright 2010 Brett Bieber
+ * @license   http://www.opensource.org/licenses/bsd-license.php New BSD License
+ * @link      https://github.com/saltybeagle/Savvy
+ */
+class Savvy_ObjectProxy implements Countable
+{
+    /**
+     * The internal object
+     *
+     * @var mixed
+     */
+    protected $object;
+
+    /**
+     * The savvy templating system
+     *
+     * @var Savvy
+     */
+    protected $savvy;
+    
+    /**
+     * Construct a new object proxy
+     *
+     * @param mixed $object The object
+     * @param Main  $savvy The savvy templating system
+     */
+    function __construct($object, $savvy)
+    {
+        $this->object = $object;
+        $this->savvy  = $savvy;
+    }
+
+    /**
+     * Magic method for retrieving data.
+     *
+     * String data will be escaped with $savvy->escape() before it is returned
+     *
+     * @return mixed
+     */
+    function __get($var)
+    {
+        return $this->filterVar($this->object->$var);
+    }
+    
+    /**
+     * Returns a variable, after it has been filtered.
+     * 
+     * @param mixed $var
+     * 
+     * @return string|Savvy_ObjectProxy
+     */
+    protected function filterVar($var)
+    {
+        switch(gettype($var)) {
+        case 'object':
+            if ($var instanceof ArrayIterator) {
+                return new Savvy_ObjectProxy_ArrayIterator($var, $this->savvy);
+            }
+            if ($var instanceof ArrayAccess) {
+                return new Savvy_ObjectProxy_ArrayAccess($var, $this->savvy);
+            }
+            return self::factory($var, $this->savvy);
+        case 'string':
+        case 'int':
+        case 'double':
+            return $this->savvy->escape($var);
+        case 'array':
+            return new Savvy_ObjectProxy_ArrayObject(
+                new \ArrayObject($var),
+                $this->savvy
+            );
+        }
+        return $var;
+    }
+
+    /**
+     * Allows direct access to the entire object for situations where the proxy
+     * interferes.
+     *
+     * @return mixed The raw object
+     */
+    function getRawObject()
+    {
+        return $this->object;
+    }
+
+    /**
+     * Allows access to the raw member variables of the internal object.
+     *
+     * @return mixed
+     */
+    function getRaw($var)
+    {
+        return $this->object->$var;
+    }
+
+    function __set($var, $value)
+    {
+        $this->object->$var = $value;
+    }
+
+    /**
+     * Magic method for checking if a property is set.
+     *
+     * @param string $var The var
+     *
+     * @return bool
+     */
+    function __isset($var)
+    {
+        return isset($this->object->$var);
+    }
+
+    /**
+     * Unset a property.
+     *
+     * @param string $var The var
+     *
+     * @return void
+     */
+    function __unset($var)
+    {
+        unset($this->object->$var);
+    }
+
+    /**
+     * Magic method which will call methods on the object.
+     *
+     * @return mixed
+     */
+    function __call($name, $arguments)
+    {
+        return $this->filterVar(
+            call_user_func_array(
+                array($this->object, $name),
+                $arguments
+            )
+        );
+    }
+
+    /**
+     * Gets the class of the internal object
+     *
+     * When using the ClassToTemplateMapper this method will be called to
+     * determine the class of the object.
+     *
+     * @return string
+     */
+    function __getClass()
+    {
+        return get_class($this->object);
+    }
+
+    /**
+     * Constructs an ObjectProxy for the given object.
+     *
+     * @param mixed $object The object to proxy
+     * @param Main  $savvy The main savvy instance
+     *
+     * @return Savvy_ObjectProxy
+     */
+    public static function factory($object, $savvy)
+    {
+        if ($object instanceof Traversable) {
+            return new Savvy_ObjectProxy_Traversable($object, $savvy);
+        }
+        if ($object instanceof ArrayAccess) {
+            return new Savvy_ObjectProxy_ArrayAccess($object, $savvy);
+        }
+        if ($object instanceof ArrayIterator) {
+            return new Savvy_ObjectProxy_ArrayIterator($object, $savvy);
+        }
+        return new self($object, $savvy);
+    }
+
+    function __toString()
+    {
+        if (method_exists($this->object, '__toString')) {
+            return $this->savvy->escape($this->object->__toString());
+        }
+        throw new Savvy_BadMethodCallException(
+            'Object of class ' . $this->__getClass()
+            . ' could not be converted to string'
+        );
+    }
+
+    /**
+     * Returns the number of elements if the object has implemented Countable,
+     * otherwise 1 is returned.
+     *
+     * @return int
+     */
+    function count()
+    {
+        return count($this->object);
+    }
+}
diff --git a/lib/php/Savvy/ObjectProxy/ArrayAccess.php b/lib/php/Savvy/ObjectProxy/ArrayAccess.php
new file mode 100644
index 0000000000000000000000000000000000000000..71109eac757345fd880ed6cfd32bc42f104a11e5
--- /dev/null
+++ b/lib/php/Savvy/ObjectProxy/ArrayAccess.php
@@ -0,0 +1,23 @@
+<?php
+class Savvy_ObjectProxy_ArrayAccess extends Savvy_ObjectProxy implements ArrayAccess 
+{
+    function offsetExists($offset)
+    {
+        return $this->object->offsetExists($offset);
+    }
+    
+    function offsetGet($offset)
+    {
+        return $this->filterVar($this->object->offsetGet($offset));
+    }
+    
+    function offsetSet($offset, $value)
+    {
+        $this->object->offsetSet($offset, $value);
+    }
+    
+    function offsetUnset($offset)
+    {
+        $this->object->offsetUnset($offset);
+    }
+}
diff --git a/lib/php/Savvy/ObjectProxy/ArrayIterator.php b/lib/php/Savvy/ObjectProxy/ArrayIterator.php
new file mode 100644
index 0000000000000000000000000000000000000000..22e5d12cba785185449f091966ff46b28ffcc7fa
--- /dev/null
+++ b/lib/php/Savvy/ObjectProxy/ArrayIterator.php
@@ -0,0 +1,68 @@
+<?php
+class Savvy_ObjectProxy_ArrayIterator extends Savvy_ObjectProxy implements Iterator, ArrayAccess, SeekableIterator, Countable
+{
+
+    /**
+     * Construct a new object proxy
+     *
+     * @param array $array  The array
+     * @param Main  $savant The savant templating system
+     */
+    function __construct($array, $savvy)
+    {
+        if (!($array instanceof ArrayIterator)) {
+            $array = new ArrayIterator($array);
+        }
+        parent::__construct($array, $savvy);
+    }
+
+    function current()
+    {
+        return $this->filterVar($this->object->current());
+    }
+
+    function next()
+    {
+        return $this->object->next();
+    }
+
+    function key()
+    {
+        return $this->filterVar($this->object->key());
+    }
+
+    function valid()
+    {
+        return $this->object->valid();
+    }
+
+    function rewind()
+    {
+        return $this->object->rewind();
+    }
+
+    function seek($offset)
+    {
+        return $this->object->seek($offset);
+    }
+
+    function offsetExists($offset)
+    {
+        return $this->object->offsetExists($offset);
+    }
+
+    function offsetGet($offset)
+    {
+        return $this->filterVar($this->object->offsetGet($offset));
+    }
+
+    function offsetSet($offset, $value)
+    {
+        $this->object->offsetSet($offset, $value);
+    }
+
+    function offsetUnset($offset)
+    {
+        $this->object->offsetUnset($offset);
+    }
+}
diff --git a/lib/php/Savvy/ObjectProxy/ArrayObject.php b/lib/php/Savvy/ObjectProxy/ArrayObject.php
new file mode 100644
index 0000000000000000000000000000000000000000..f4792639176656b9b9c28af10cbd5745d790e7a6
--- /dev/null
+++ b/lib/php/Savvy/ObjectProxy/ArrayObject.php
@@ -0,0 +1,82 @@
+<?php
+
+/**
+ * Savvy_ObjectProxy_ArrayObject
+ *
+ * PHP version 5
+ *
+ * @category  Templates
+ * @package   Savvy
+ * @author    Brett Bieber <saltybeagle@php.net>
+ * @author    Michael Gauthier <mike@silverorange.com>
+ * @copyright 2009 Brett Bieber, 2011 Michael Gauthier
+ * @license   http://www.opensource.org/licenses/bsd-license.php New BSD License
+ * @version   SVN: $Id$
+ * @link      https://github.com/saltybeagle/Savvy
+ */
+
+/**
+ * Proxies ArrayObject objects
+ *
+ * Filters on array access or on traversal.
+ *
+ * @category  Templates
+ * @package   Savvy
+ * @author    Brett Bieber <saltybeagle@php.net>
+ * @author    Michael Gauthier <mike@silverorange.com>
+ * @copyright 2009 Brett Bieber, 2011 Michael Gauthier
+ * @license   http://www.opensource.org/licenses/bsd-license.php New BSD License
+ * @link      https://github.com/saltybeagle/Savvy
+ */
+class Savvy_ObjectProxy_ArrayObject
+    extends Savvy_ObjectProxy_ArrayAccess
+    implements ArrayAccess, Countable, Serializable, IteratorAggregate
+{
+    public function getIterator()
+    {
+        return $this->object->getIterator();
+    }
+
+    public function next()
+    {
+        $this->object->next();
+    }
+
+    public function key()
+    {
+        return $this->filterVar($this->object->key());
+    }
+
+    public function valid()
+    {
+        return $this->object->valid();
+    }
+
+    public function rewind()
+    {
+        $this->object->rewind();
+    }
+
+    public function current()
+    {
+        return $this->filterVar($this->object->current());
+    }
+
+    public function count()
+    {
+        return count($this->object);
+    }
+
+    public function serialize()
+    {
+        return serialize($this->object);
+    }
+
+    public function unserialize($string)
+    {
+        $object = unserialize($string);
+        if ($object !== false) {
+            $this->object = $object;
+        }
+    }
+}
diff --git a/lib/php/Savvy/ObjectProxy/Traversable.php b/lib/php/Savvy/ObjectProxy/Traversable.php
new file mode 100644
index 0000000000000000000000000000000000000000..56c7608c4b28a937bc6401d2bc1f417c5891a8db
--- /dev/null
+++ b/lib/php/Savvy/ObjectProxy/Traversable.php
@@ -0,0 +1,34 @@
+<?php
+class Savvy_ObjectProxy_Traversable extends Savvy_ObjectProxy implements Iterator
+{
+
+    function getIterator()
+    {
+        return $this->object;
+    }
+
+    function next()
+    {
+        $this->object->next();
+    }
+
+    function key()
+    {
+        return $this->object->key();
+    }
+
+    function valid()
+    {
+        return $this->object->valid();
+    }
+
+    function rewind()
+    {
+        $this->object->rewind();
+    }
+
+    function current()
+    {
+        return $this->filterVar($this->object->current());
+    }
+}
\ No newline at end of file
diff --git a/lib/php/Savvy/TemplateException.php b/lib/php/Savvy/TemplateException.php
new file mode 100644
index 0000000000000000000000000000000000000000..fb44d2e8ae6fd96ae8625e250354a1f5390db0d7
--- /dev/null
+++ b/lib/php/Savvy/TemplateException.php
@@ -0,0 +1,3 @@
+<?php
+class Savvy_TemplateException extends Exception implements Savvy_Exception {}
+?>
\ No newline at end of file
diff --git a/lib/php/Savvy/UnexpectedValueException.php b/lib/php/Savvy/UnexpectedValueException.php
new file mode 100644
index 0000000000000000000000000000000000000000..c8c0174a0f08d6070b57ba47c0b2cf259273c14d
--- /dev/null
+++ b/lib/php/Savvy/UnexpectedValueException.php
@@ -0,0 +1,5 @@
+<?php
+class Savvy_UnexpectedValueException extends UnexpectedValueException implements Savvy_Exception
+{
+
+}
diff --git a/lib/tests/phpsavant.com/Savvy/escape/Foo.tpl.php b/lib/tests/phpsavant.com/Savvy/escape/Foo.tpl.php
new file mode 100644
index 0000000000000000000000000000000000000000..48c5e528a1ec7f8ea2671d3ed73c003995b00679
--- /dev/null
+++ b/lib/tests/phpsavant.com/Savvy/escape/Foo.tpl.php
@@ -0,0 +1,3 @@
+<?php
+echo $context->var1;
+?>
\ No newline at end of file
diff --git a/lib/tests/phpsavant.com/Savvy/escape/echostring.tpl.php b/lib/tests/phpsavant.com/Savvy/escape/echostring.tpl.php
new file mode 100644
index 0000000000000000000000000000000000000000..7833ffb8b27e6b43e4c282ce4ca7a951b86f7fd7
--- /dev/null
+++ b/lib/tests/phpsavant.com/Savvy/escape/echostring.tpl.php
@@ -0,0 +1,3 @@
+<?php
+echo $context;
+?>
\ No newline at end of file
diff --git a/lib/tests/phpsavant.com/Savvy/escape/object.phpt b/lib/tests/phpsavant.com/Savvy/escape/object.phpt
new file mode 100644
index 0000000000000000000000000000000000000000..f0e37efac8112e330b1a3a4ec70c9512aa4b5bd9
--- /dev/null
+++ b/lib/tests/phpsavant.com/Savvy/escape/object.phpt
@@ -0,0 +1,24 @@
+--TEST--
+Savvy::addEscape() object variable escaping test
+--FILE--
+<?php
+require dirname(__FILE__) . '/../test_framework.php.inc';
+chdir(__DIR__);
+$savvy = new Savvy();
+$savvy->setEscape('htmlspecialchars');
+
+class Foo
+{
+    public $var1;
+}
+
+$object = new Foo();
+$object->var1  = '<p></p>';
+
+$test->assertEquals(htmlspecialchars($object->var1), $savvy->render($object), 'render object with variable escaping');
+
+$test->assertEquals($object->var1, $savvy->render($object, 'raw.tpl.php'), 'render object with raw variable access');
+?>
+===DONE===
+--EXPECT--
+===DONE===
\ No newline at end of file
diff --git a/lib/tests/phpsavant.com/Savvy/escape/raw.tpl.php b/lib/tests/phpsavant.com/Savvy/escape/raw.tpl.php
new file mode 100644
index 0000000000000000000000000000000000000000..d020c83bbf9158afb2adbb27eb84ab735461d279
--- /dev/null
+++ b/lib/tests/phpsavant.com/Savvy/escape/raw.tpl.php
@@ -0,0 +1,3 @@
+<?php
+echo $context->getRaw('var1');
+?>
\ No newline at end of file
diff --git a/lib/tests/phpsavant.com/Savvy/escape/string.phpt b/lib/tests/phpsavant.com/Savvy/escape/string.phpt
new file mode 100644
index 0000000000000000000000000000000000000000..80abcc09c3aabc0d6d49d201566be30c4a6e1c68
--- /dev/null
+++ b/lib/tests/phpsavant.com/Savvy/escape/string.phpt
@@ -0,0 +1,19 @@
+--TEST--
+Savvy::render() string with addEscape() test
+--FILE--
+<?php
+require dirname(__FILE__) . '/../test_framework.php.inc';
+chdir(__DIR__);
+$savvy = new Savvy();
+$savvy->setEscape('htmlspecialchars');
+
+$string = 'test';
+$test->assertEquals($string, $savvy->escape($string), 'render');
+
+$string = '<p></p>';
+$test->assertEquals(htmlspecialchars($string), $savvy->escape($string), 'render string with special chars');
+
+?>
+===DONE===
+--EXPECT--
+===DONE===
\ No newline at end of file
diff --git a/lib/tests/phpsavant.com/Savvy/globals/basic.phpt b/lib/tests/phpsavant.com/Savvy/globals/basic.phpt
new file mode 100644
index 0000000000000000000000000000000000000000..2cb2f6cef3507a8a65cf83f332ac1d2cae43f3c4
--- /dev/null
+++ b/lib/tests/phpsavant.com/Savvy/globals/basic.phpt
@@ -0,0 +1,15 @@
+--TEST--
+Savvy::addGlobal() basic test
+--FILE--
+<?php
+require dirname(__FILE__) . '/../test_framework.php.inc';
+chdir(__DIR__);
+$savvy = new Savvy();
+
+$savvy->addGlobal('foo', true);
+
+echo $savvy->render(null, 'basic.tpl.php');
+
+?>
+--EXPECT--
+===DONE===
\ No newline at end of file
diff --git a/lib/tests/phpsavant.com/Savvy/globals/basic.tpl.php b/lib/tests/phpsavant.com/Savvy/globals/basic.tpl.php
new file mode 100644
index 0000000000000000000000000000000000000000..5df37bdc279a53291d1adecf40b3cd4da930d011
--- /dev/null
+++ b/lib/tests/phpsavant.com/Savvy/globals/basic.tpl.php
@@ -0,0 +1,6 @@
+<?php
+    if (isset($foo)
+        && true === $foo) {
+        echo '===DONE===';
+    }
+?>
\ No newline at end of file
diff --git a/lib/tests/phpsavant.com/Savvy/globals/escape.arrays.phpt b/lib/tests/phpsavant.com/Savvy/globals/escape.arrays.phpt
new file mode 100644
index 0000000000000000000000000000000000000000..a34ac672c8a260f0cae8d4da1eb8492af8464f4e
--- /dev/null
+++ b/lib/tests/phpsavant.com/Savvy/globals/escape.arrays.phpt
@@ -0,0 +1,23 @@
+--TEST--
+Savvy::addGlobal() Escape added global array
+--FILE--
+<?php
+require dirname(__FILE__) . '/../test_framework.php.inc';
+chdir(__DIR__);
+$savvy = new Savvy();
+
+$savvy->setEscape('htmlspecialchars');
+
+$unescaped = array(
+    '<a href="Blah">Blah</a>'
+);
+
+$savvy->addGlobal('foo', $unescaped);
+
+$escaped = $savvy->getGlobals();
+
+echo $escaped['foo'][0];
+
+?>
+--EXPECT--
+&lt;a href=&quot;Blah&quot;&gt;Blah&lt;/a&gt;
\ No newline at end of file
diff --git a/lib/tests/phpsavant.com/Savvy/globals/escape.nestedarrays.phpt b/lib/tests/phpsavant.com/Savvy/globals/escape.nestedarrays.phpt
new file mode 100644
index 0000000000000000000000000000000000000000..b50b6528d84300c92cdb46838883844579f596ae
--- /dev/null
+++ b/lib/tests/phpsavant.com/Savvy/globals/escape.nestedarrays.phpt
@@ -0,0 +1,23 @@
+--TEST--
+Savvy::addGlobal() Escape added global array
+--FILE--
+<?php
+require dirname(__FILE__) . '/../test_framework.php.inc';
+chdir(__DIR__);
+$savvy = new Savvy();
+
+$savvy->setEscape('htmlspecialchars');
+
+$unescaped = array(
+    '<a href="Blah">Blah</a>'
+);
+
+$savvy->addGlobal('foo', array($unescaped));
+
+$escaped = $savvy->getGlobals();
+
+echo $escaped['foo'][0][0];
+
+?>
+--EXPECT--
+&lt;a href=&quot;Blah&quot;&gt;Blah&lt;/a&gt;
\ No newline at end of file
diff --git a/lib/tests/phpsavant.com/Savvy/globals/escape.phpt b/lib/tests/phpsavant.com/Savvy/globals/escape.phpt
new file mode 100644
index 0000000000000000000000000000000000000000..c8190bc2222cd30a0efe62051c3e24cdaa1dedfc
--- /dev/null
+++ b/lib/tests/phpsavant.com/Savvy/globals/escape.phpt
@@ -0,0 +1,21 @@
+--TEST--
+Savvy::addGlobal() Escape added globals test
+--FILE--
+<?php
+require dirname(__FILE__) . '/../test_framework.php.inc';
+chdir(__DIR__);
+$savvy = new Savvy();
+
+function myEscape($var)
+{
+    echo '===DONE===';
+    return $var;
+}
+
+$savvy->setEscape('myEscape');
+
+$savvy->addGlobal('foo', 'lalalala');
+
+?>
+--EXPECT--
+===DONE===
\ No newline at end of file
diff --git a/lib/tests/phpsavant.com/Savvy/render/Foo.tpl.php b/lib/tests/phpsavant.com/Savvy/render/Foo.tpl.php
new file mode 100644
index 0000000000000000000000000000000000000000..83c9b5f0f2bc819bf1028d81dbfc98dc95dd9f32
--- /dev/null
+++ b/lib/tests/phpsavant.com/Savvy/render/Foo.tpl.php
@@ -0,0 +1,2 @@
+<?php echo get_class($context) ?>
+<?php echo $context->var1 ?>
\ No newline at end of file
diff --git a/lib/tests/phpsavant.com/Savvy/render/array.phpt b/lib/tests/phpsavant.com/Savvy/render/array.phpt
new file mode 100644
index 0000000000000000000000000000000000000000..a049a9330242f049725daa353904709cb43c99c2
--- /dev/null
+++ b/lib/tests/phpsavant.com/Savvy/render/array.phpt
@@ -0,0 +1,18 @@
+--TEST--
+Savvy::render() array test
+--FILE--
+<?php
+require dirname(__FILE__) . '/../test_framework.php.inc';
+chdir(__DIR__);
+$savvy = new Savvy();
+
+$array = array(1,2,3);
+$test->assertEquals('123', $savvy->render($array), 'render array');
+
+$array = array(1,2,3);
+$test->assertEquals('123', $savvy->render($array, 'echostring.tpl.php'), 'render array through custom template');
+
+?>
+===DONE===
+--EXPECT--
+===DONE===
\ No newline at end of file
diff --git a/lib/tests/phpsavant.com/Savvy/render/echostring.tpl.php b/lib/tests/phpsavant.com/Savvy/render/echostring.tpl.php
new file mode 100644
index 0000000000000000000000000000000000000000..8bad12826e19a8978bbef856df16e7091b42d332
--- /dev/null
+++ b/lib/tests/phpsavant.com/Savvy/render/echostring.tpl.php
@@ -0,0 +1 @@
+<?php echo $context ?>
\ No newline at end of file
diff --git a/lib/tests/phpsavant.com/Savvy/render/fastcompile.phpt b/lib/tests/phpsavant.com/Savvy/render/fastcompile.phpt
new file mode 100644
index 0000000000000000000000000000000000000000..1025ef2a17050768190e058393d3ff0f099d0e21
--- /dev/null
+++ b/lib/tests/phpsavant.com/Savvy/render/fastcompile.phpt
@@ -0,0 +1,49 @@
+--TEST--
+Savvy::render() fast compiler test
+--FILE--
+<?php
+require dirname(__FILE__) . '/../test_framework.php.inc';
+chdir(__DIR__);
+$savvy = new Savvy();
+
+class Foo
+{
+    public $var1;
+    function __toString()
+    {
+        return 'test';
+    }
+}
+
+$object = new Foo();
+$object->var1  = ' is my class';
+
+$savvy->setEscape();
+mkdir(__DIR__ . '/compiled');
+$compiler = new Savvy_BasicFastCompiler(__DIR__ . DIRECTORY_SEPARATOR . 'compiled');
+$savvy->setCompiler($compiler);
+
+$test->assertEquals(__DIR__ . DIRECTORY_SEPARATOR . 'compiled' . DIRECTORY_SEPARATOR .
+                    md5('.' . DIRECTORY_SEPARATOR . 'Foo.tpl.php'), $savvy->template('Foo.tpl.php'),
+                    'verify compiler is called');
+$test->assertEquals("<?php return '' .  get_class(\$context)  . '
+' .  \$context->var1  . '';", file_get_contents(__DIR__ . DIRECTORY_SEPARATOR . 'compiled' . DIRECTORY_SEPARATOR .
+                    md5('.' . DIRECTORY_SEPARATOR . 'Foo.tpl.php')), 'compiled template');
+
+$test->assertEquals('Foo is my class', $savvy->render($object), 'render object');
+
+$test->assertEquals('test', $savvy->render($object, 'echostring.tpl.php'), 'render object with custom template');
+
+?>
+===DONE===
+--CLEAN--
+<?php
+$a = opendir(__DIR__ . '/compiled');
+while (false !== ($b = readdir($a))) {
+    if (is_dir(__DIR__ . '/compiled/' . $b)) continue;
+    unlink(__DIR__ . '/compiled/' . $b);
+}
+rmdir(__DIR__ . '/compiled');
+?>
+--EXPECT--
+===DONE===
\ No newline at end of file
diff --git a/lib/tests/phpsavant.com/Savvy/render/object.phpt b/lib/tests/phpsavant.com/Savvy/render/object.phpt
new file mode 100644
index 0000000000000000000000000000000000000000..d7d11d5abb75d4e890cb27e405ab4983c65b7338
--- /dev/null
+++ b/lib/tests/phpsavant.com/Savvy/render/object.phpt
@@ -0,0 +1,30 @@
+--TEST--
+Savvy::render() object test
+--FILE--
+<?php
+require dirname(__FILE__) . '/../test_framework.php.inc';
+chdir(__DIR__);
+$savvy = new Savvy();
+
+class Foo
+{
+    public $var1;
+    function __toString()
+    {
+        return 'test';
+    }
+}
+
+$object = new Foo();
+$object->var1  = ' is my class';
+
+$savvy->setEscape();
+
+$test->assertEquals('Foo is my class', $savvy->render($object), 'render object');
+
+$test->assertEquals('test', $savvy->render($object, 'echostring.tpl.php'), 'render object with custom template');
+
+?>
+===DONE===
+--EXPECT--
+===DONE===
\ No newline at end of file
diff --git a/lib/tests/phpsavant.com/Savvy/render/string.phpt b/lib/tests/phpsavant.com/Savvy/render/string.phpt
new file mode 100644
index 0000000000000000000000000000000000000000..1fee2313cd0afd9630547cfd7509061e20943630
--- /dev/null
+++ b/lib/tests/phpsavant.com/Savvy/render/string.phpt
@@ -0,0 +1,24 @@
+--TEST--
+Savvy::render() string test
+--FILE--
+<?php
+require dirname(__FILE__) . '/../test_framework.php.inc';
+chdir(__DIR__);
+$savvy = new Savvy();
+$savvy->setEscape('htmlspecialchars');
+
+$string = 'test';
+$test->assertEquals($string, $savvy->render($string), 'render');
+
+$string = '<p></p>';
+$test->assertEquals(htmlspecialchars($string), $savvy->render($string), 'render string with special chars');
+
+$string = 'test';
+$test->assertEquals($string, $savvy->render($string, 'echostring.tpl.php'), 'render string through template');
+
+$string = '<p></p>';
+$test->assertEquals(htmlspecialchars($string), $savvy->render($string, 'echostring.tpl.php'), 'render string with special chars through template');
+?>
+===DONE===
+--EXPECT--
+===DONE===
\ No newline at end of file
diff --git a/lib/tests/phpsavant.com/Savvy/test_framework.php.inc b/lib/tests/phpsavant.com/Savvy/test_framework.php.inc
new file mode 100644
index 0000000000000000000000000000000000000000..c072c9d6ec1f6eae23de09a5a6b7fa915389b714
--- /dev/null
+++ b/lib/tests/phpsavant.com/Savvy/test_framework.php.inc
@@ -0,0 +1,212 @@
+<?php
+$__e = error_reporting();
+error_reporting(E_ERROR|E_NOTICE|E_WARNING);
+require_once dirname(__FILE__) . '/../src/Savvy/Autoload.php';
+$classLoader = new Savvy_Autoload();
+$classLoader->register();
+@include_once 'Text/Diff.php';
+@include_once 'Text/Diff/Renderer.php';
+@include_once 'Text/Diff/Renderer/unified.php';
+error_reporting($__e);
+class PEAR2_PHPT
+{
+    var $_diffonly;
+    function __construct($diffonly = false)
+    {
+        $this->_diffonly = $diffonly;
+        $this->_errors = array();
+    }
+
+    function assertTrue($test, $message)
+    {
+        if ($test === true) {
+            return true;
+        }
+        $this->_failTest(debug_backtrace(), $message);
+        echo "Unexpected non-true value: \n";
+        var_export($test);
+        echo "\n'$message'\n";
+        return false;
+    }
+
+    function assertIsa($control, $test, $message)
+    {
+        if (is_a($test, $control)) {
+            return true;
+        }
+        $this->_failTest(debug_backtrace(), $message);
+        echo "Unexpected non-$control object: \n";
+        var_export($test);
+        echo "\n'$message'\n";
+        return false;
+    }
+
+    function assertNull($test, $message)
+    {
+        if ($test === null) {
+            return true;
+        }
+        $this->_failTest(debug_backtrace(), $message);
+        echo "Unexpected non-null value: \n";
+        var_export($test);
+        echo "\n'$message'\n";
+        return false;
+    }
+
+    function assertNotNull($test, $message)
+    {
+        if ($test !== null) {
+            return true;
+        }
+        $this->_failTest(debug_backtrace(), $message);
+        echo "Unexpected null: \n";
+        var_export($test);
+        echo "\n'$message'\n";
+        return false;
+    }
+
+    function assertSame($test, $test1, $message)
+    {
+        if ($test === $test1) {
+            return true;
+        }
+        $this->_failTest(debug_backtrace(), $message);
+        echo "Unexpectedly two vars are not the same thing: \n";
+        echo "\n'$message'\n";
+        return false;
+    }
+
+    function assertNotSame($test, $test1, $message)
+    {
+        if ($test !== $test1) {
+            return true;
+        }
+        $this->_failTest(debug_backtrace(), $message);
+        echo "Unexpectedly two vars are the same thing: \n";
+        echo "\n'$message'\n";
+        return false;
+    }
+
+    function assertFalse($test, $message)
+    {
+        if ($test === false) {
+            return true;
+        }
+        $this->_failTest(debug_backtrace(), $message);
+        echo "Unexpected non-false value: \n";
+        var_export($test);
+        echo "\n'$message'\n";
+        return false;
+    }
+
+    function assertNotTrue($test, $message)
+    {
+        if (!$test) {
+            return true;
+        }
+        $this->_failTest(debug_backtrace(), $message);
+        echo "Unexpected loose true value: \n";
+        var_export($test);
+        echo "\n'$message'\n";
+        return false;
+    }
+
+    function assertNotFalse($test, $message)
+    {
+        if ($test) {
+            return true;
+        }
+        $this->_failTest(debug_backtrace(), $message);
+        echo "Unexpected loose false value: \n";
+        var_export($test);
+        echo "\n'$message'\n";
+        return false;
+    }
+
+    function assertRegex($regex, $test, $message)
+    {
+        if (!preg_match($regex, $test)) {
+            $this->_failTest(debug_backtrace(), $message);
+            echo "Expecting:\nText Matching Regular Expression $regex\n";
+            echo "\nReceived:\n";
+            var_export($test);
+            echo "\n";
+            return false;
+        }
+        return true;
+    }
+
+    function assertException($exception, $class, $emessage, $message)
+    {
+        if (!($exception instanceof $class)) {
+            $this->_failTest(debug_backtrace(), $message);
+            echo "Expecting class $class, got ", get_class($exception);
+        }
+        $this->assertEquals($emessage, $exception->getMessage(), $message, debug_backtrace());
+    }
+
+    function assertEquals($control, $test, $message, $trace = null)
+    {
+        if (!$trace) {
+            $trace = debug_backtrace();
+        }
+        if (str_replace(array("\r", "\n"), array('', ''),
+            var_export($control, true)) != str_replace(array("\r", "\n"), array('', ''),
+            var_export($test, true))) {
+            $this->_failTest($trace, $message);
+            if (class_exists('Text_Diff', false)) {
+                echo "Diff of expecting/received:\n";
+                $diff = new Text_Diff(
+                    explode("\n", var_export($control, true)),
+                    explode("\n", var_export($test, true)));
+
+                // Output the diff in unified format.
+                $renderer = new Text_Diff_Renderer_unified();
+                echo $renderer->render($diff);
+                if ($this->_diffonly) {
+                    return false;
+                }
+            }
+            echo "Expecting:\n";
+            var_export($control);
+            echo "\nReceived:\n";
+            var_export($test);
+            echo "\n";
+            return false;
+        }
+        return true;
+    }
+
+    function assertFileExists($fname, $message)
+    {
+        if (!@file_exists($fname)) {
+            $this->_failTest(debug_backtrace(), $message);
+            echo "File '$fname' does not exist, and should\n";
+            return false;
+        }
+        return true;
+    }
+
+    function assertFileNotExists($fname, $message)
+    {
+        if (@file_exists($fname)) {
+            $this->_failTest(debug_backtrace(), $message);
+            echo "File '$fname' exists, and should not\n";
+            return false;
+        }
+        return true;
+    }
+
+    function _failTest($trace, $message)
+    {
+        echo 'Test Failure: "' . $message  . "\"\n in " . $trace[0]['file'] . ' line ' .
+            $trace[0]['line'] . "\n";
+    }
+
+    function showAll()
+    {
+        $this->_diffonly = false;
+    }
+}
+$test = new PEAR2_PHPT();
+?>