add cms, add todo
authorMart Lubbers <mart@martlubbers.net>
Mon, 10 Oct 2016 12:05:42 +0000 (14:05 +0200)
committerMart Lubbers <mart@martlubbers.net>
Mon, 10 Oct 2016 12:05:42 +0000 (14:05 +0200)
111 files changed:
testcms-final-anon/.gitignore [new file with mode: 0644]
testcms-final-anon/Installation Instructions.txt [new file with mode: 0644]
testcms-final-anon/config.default.php [new file with mode: 0644]
testcms-final-anon/htaccess.txt [new file with mode: 0644]
testcms-final-anon/index.php [new file with mode: 0644]
testcms-final-anon/install/assets/css/app.css [new file with mode: 0644]
testcms-final-anon/install/assets/img/logo.gif [new file with mode: 0644]
testcms-final-anon/install/assets/js/app.js [new file with mode: 0644]
testcms-final-anon/install/assets/js/jquery.js [new file with mode: 0644]
testcms-final-anon/install/diagnose.php [new file with mode: 0644]
testcms-final-anon/install/index.php [new file with mode: 0644]
testcms-final-anon/install/installer.php [new file with mode: 0644]
testcms-final-anon/install/test.sql [new file with mode: 0644]
testcms-final-anon/system/admin/controllers/comments.php [new file with mode: 0644]
testcms-final-anon/system/admin/controllers/metadata.php [new file with mode: 0644]
testcms-final-anon/system/admin/controllers/pages.php [new file with mode: 0644]
testcms-final-anon/system/admin/controllers/posts.php [new file with mode: 0644]
testcms-final-anon/system/admin/controllers/users.php [new file with mode: 0644]
testcms-final-anon/system/admin/theme/assets/css/admin.css [new file with mode: 0644]
testcms-final-anon/system/admin/theme/assets/css/popup.css [new file with mode: 0644]
testcms-final-anon/system/admin/theme/assets/img/active.png [new file with mode: 0644]
testcms-final-anon/system/admin/theme/assets/img/bg.gif [new file with mode: 0644]
testcms-final-anon/system/admin/theme/assets/img/logo.png [new file with mode: 0644]
testcms-final-anon/system/admin/theme/assets/js/comments.js [new file with mode: 0644]
testcms-final-anon/system/admin/theme/assets/js/custom_fields.js [new file with mode: 0644]
testcms-final-anon/system/admin/theme/assets/js/helpers.js [new file with mode: 0644]
testcms-final-anon/system/admin/theme/assets/js/mootools.js [new file with mode: 0644]
testcms-final-anon/system/admin/theme/assets/js/popup.js [new file with mode: 0644]
testcms-final-anon/system/admin/theme/assets/js/tabs.js [new file with mode: 0644]
testcms-final-anon/system/admin/theme/error_500.php [new file with mode: 0644]
testcms-final-anon/system/admin/theme/error_config.php [new file with mode: 0644]
testcms-final-anon/system/admin/theme/error_php.php [new file with mode: 0644]
testcms-final-anon/system/admin/theme/functions.php [new file with mode: 0644]
testcms-final-anon/system/admin/theme/includes/footer.php [new file with mode: 0644]
testcms-final-anon/system/admin/theme/includes/header.php [new file with mode: 0644]
testcms-final-anon/system/admin/theme/metadata/index.php [new file with mode: 0644]
testcms-final-anon/system/admin/theme/pages/add.php [new file with mode: 0644]
testcms-final-anon/system/admin/theme/pages/edit.php [new file with mode: 0644]
testcms-final-anon/system/admin/theme/pages/index.php [new file with mode: 0644]
testcms-final-anon/system/admin/theme/posts/add.php [new file with mode: 0644]
testcms-final-anon/system/admin/theme/posts/edit.php [new file with mode: 0644]
testcms-final-anon/system/admin/theme/posts/index.php [new file with mode: 0644]
testcms-final-anon/system/admin/theme/users/add.php [new file with mode: 0644]
testcms-final-anon/system/admin/theme/users/amnesia.php [new file with mode: 0644]
testcms-final-anon/system/admin/theme/users/edit.php [new file with mode: 0644]
testcms-final-anon/system/admin/theme/users/index.php [new file with mode: 0644]
testcms-final-anon/system/admin/theme/users/login.php [new file with mode: 0644]
testcms-final-anon/system/admin/theme/users/reset.php [new file with mode: 0644]
testcms-final-anon/system/bootstrap.php [new file with mode: 0644]
testcms-final-anon/system/classes/autoload.php [new file with mode: 0644]
testcms-final-anon/system/classes/comments.php [new file with mode: 0644]
testcms-final-anon/system/classes/config.php [new file with mode: 0644]
testcms-final-anon/system/classes/cookie.php [new file with mode: 0644]
testcms-final-anon/system/classes/curl.php [new file with mode: 0644]
testcms-final-anon/system/classes/db.php [new file with mode: 0644]
testcms-final-anon/system/classes/email.php [new file with mode: 0644]
testcms-final-anon/system/classes/error.php [new file with mode: 0644]
testcms-final-anon/system/classes/events.php [new file with mode: 0644]
testcms-final-anon/system/classes/helpers.php [new file with mode: 0644]
testcms-final-anon/system/classes/input.php [new file with mode: 0644]
testcms-final-anon/system/classes/ioc.php [new file with mode: 0644]
testcms-final-anon/system/classes/items.php [new file with mode: 0644]
testcms-final-anon/system/classes/log.php [new file with mode: 0644]
testcms-final-anon/system/classes/metadata.php [new file with mode: 0644]
testcms-final-anon/system/classes/notifications.php [new file with mode: 0644]
testcms-final-anon/system/classes/pages.php [new file with mode: 0644]
testcms-final-anon/system/classes/posts.php [new file with mode: 0644]
testcms-final-anon/system/classes/request.php [new file with mode: 0644]
testcms-final-anon/system/classes/response.php [new file with mode: 0644]
testcms-final-anon/system/classes/routes.php [new file with mode: 0644]
testcms-final-anon/system/classes/rss.php [new file with mode: 0644]
testcms-final-anon/system/classes/session.php [new file with mode: 0644]
testcms-final-anon/system/classes/template.php [new file with mode: 0644]
testcms-final-anon/system/classes/testcms.php [new file with mode: 0644]
testcms-final-anon/system/classes/themes.php [new file with mode: 0644]
testcms-final-anon/system/classes/url.php [new file with mode: 0644]
testcms-final-anon/system/classes/users.php [new file with mode: 0644]
testcms-final-anon/system/functions/articles.php [new file with mode: 0644]
testcms-final-anon/system/functions/comments.php [new file with mode: 0644]
testcms-final-anon/system/functions/helpers.php [new file with mode: 0644]
testcms-final-anon/system/functions/menus.php [new file with mode: 0644]
testcms-final-anon/system/functions/metadata.php [new file with mode: 0644]
testcms-final-anon/system/functions/pages.php [new file with mode: 0644]
testcms-final-anon/system/functions/posts.php [new file with mode: 0644]
testcms-final-anon/system/functions/search.php [new file with mode: 0644]
testcms-final-anon/system/functions/users.php [new file with mode: 0644]
testcms-final-anon/themes/default/404.php [new file with mode: 0644]
testcms-final-anon/themes/default/about.txt [new file with mode: 0644]
testcms-final-anon/themes/default/article.php [new file with mode: 0644]
testcms-final-anon/themes/default/css/reset.css [new file with mode: 0644]
testcms-final-anon/themes/default/css/style.css [new file with mode: 0644]
testcms-final-anon/themes/default/functions.php [new file with mode: 0644]
testcms-final-anon/themes/default/img/attribution.gif [new file with mode: 0644]
testcms-final-anon/themes/default/img/close.gif [new file with mode: 0644]
testcms-final-anon/themes/default/img/search.gif [new file with mode: 0644]
testcms-final-anon/themes/default/includes/comment_form.php [new file with mode: 0644]
testcms-final-anon/themes/default/includes/footer.php [new file with mode: 0644]
testcms-final-anon/themes/default/includes/header.php [new file with mode: 0644]
testcms-final-anon/themes/default/js/main.js [new file with mode: 0644]
testcms-final-anon/themes/default/page.php [new file with mode: 0644]
testcms-final-anon/themes/default/posts.php [new file with mode: 0644]
testcms-final-anon/themes/default/search.php [new file with mode: 0644]
testcms-final-anon/upgrade/assets/css/app.css [new file with mode: 0644]
testcms-final-anon/upgrade/assets/img/logo.gif [new file with mode: 0644]
testcms-final-anon/upgrade/classes/migrations.php [new file with mode: 0644]
testcms-final-anon/upgrade/classes/schema.php [new file with mode: 0644]
testcms-final-anon/upgrade/complete.php [new file with mode: 0644]
testcms-final-anon/upgrade/index.php [new file with mode: 0644]
testcms-final-anon/upgrade/migrations.php [new file with mode: 0644]
testcms-final-anon/upgrade/run.php [new file with mode: 0644]
todo.txt [new file with mode: 0644]

diff --git a/testcms-final-anon/.gitignore b/testcms-final-anon/.gitignore
new file mode 100644 (file)
index 0000000..d40e4dc
--- /dev/null
@@ -0,0 +1,14 @@
+# ignore os/app generated files\r
+Thumbs.db\r
+.DS_Store\r
+*.esproj\r
+\r
+# ignore generated config\r
+/config.php\r
+\r
+# ignore user mod_rewrite\r
+/.htaccess\r
+\r
+# ignore debug and custom themes\r
+/themes/*\r
+!/themes/default\r
diff --git a/testcms-final-anon/Installation Instructions.txt b/testcms-final-anon/Installation Instructions.txt
new file mode 100644 (file)
index 0000000..e5b3c5d
--- /dev/null
@@ -0,0 +1,10 @@
+Installation Instructions:\r
+\r
+Extract the testcms.zip to your desired folder.\r
+Change the file permissions to allow all users write access to the folder you extracted testcms to.\r
+Create a database in MySQL for TestCMS.\r
+Register that folder with your webserver of choice.\r
+Assure that htaccess.txt or .htaccess is accessable for Apache on your webserver.\r
+Go to a web browser and go to the index page of testcms and follow the further instructions to finish your setup.\r
+\r
+If you have any questions, email wagnertrust2012@gmail.com.\r
diff --git a/testcms-final-anon/config.default.php b/testcms-final-anon/config.default.php
new file mode 100644 (file)
index 0000000..49fe3f0
--- /dev/null
@@ -0,0 +1,48 @@
+<?php defined('IN_CMS') or die('No direct access allowed.');\r
+\r
+/*\r
+       TestCMS - Default configuration\r
+*/\r
+return array(\r
+       //  MySQL database details\r
+       'database' => array(\r
+               'host' => '127.0.0.1',\r
+               'username' => 'root',\r
+               'password' => '',\r
+               'name' => 'testcms'\r
+       ),\r
+       \r
+       // Application settings\r
+       'application' => array(\r
+               // url paths\r
+               'base_url' => '/',\r
+               'index_page' => 'index.php',\r
+\r
+               // your time zone\r
+               'timezone' => 'UTC',\r
+\r
+               // access to admin\r
+               'admin_folder' => 'admin',\r
+\r
+               // your unique application key used for signing passwords\r
+               'key' => ''\r
+       ),\r
+       \r
+       // Session details\r
+       'session' => array(\r
+               'name' => 'testcms',\r
+               'expire' => 3600,\r
+               'path' => '/',\r
+               'domain' => ''\r
+       ),\r
+\r
+       // Error handling\r
+       'error' => array(\r
+               'ignore' => array(E_NOTICE, E_USER_NOTICE, E_DEPRECATED, E_USER_DEPRECATED),\r
+               'detail' => false,\r
+               'log' => false\r
+       ),\r
+\r
+       // Show database profile\r
+       'debug' => false\r
+);\r
diff --git a/testcms-final-anon/htaccess.txt b/testcms-final-anon/htaccess.txt
new file mode 100644 (file)
index 0000000..3b425b8
--- /dev/null
@@ -0,0 +1,15 @@
+<IfModule mod_rewrite.c>\r
+       RewriteEngine On\r
+       # RewriteBase /\r
+\r
+       # Allow any files or directories that exist to be displayed directly\r
+       RewriteCond %{REQUEST_FILENAME} !-f\r
+       RewriteCond %{REQUEST_FILENAME} !-d\r
+\r
+       # Rewrite all other URLs to index.php/URL\r
+       RewriteRule ^(.*)$ index.php?/$1 [L,QSA]\r
+</IfModule>\r
+\r
+<IfModule !mod_rewrite.c> \r
+       ErrorDocument 404 index.php\r
+</IfModule>\r
diff --git a/testcms-final-anon/index.php b/testcms-final-anon/index.php
new file mode 100644 (file)
index 0000000..e92d81c
--- /dev/null
@@ -0,0 +1,16 @@
+<?php\r
+\r
+// benchmark\r
+define('START', microtime(true));\r
+\r
+//  Set the include path\r
+define('PATH', pathinfo(__FILE__, PATHINFO_DIRNAME) . '/');\r
+\r
+//  Block direct access to any PHP files\r
+define('IN_CMS', true);\r
+\r
+//  TestCMS version\r
+define('VERSION', 0.6);\r
+\r
+// Lets bootstrap our application and get it ready to run\r
+require PATH . 'system/bootstrap.php';\r
diff --git a/testcms-final-anon/install/assets/css/app.css b/testcms-final-anon/install/assets/css/app.css
new file mode 100644 (file)
index 0000000..da354e8
--- /dev/null
@@ -0,0 +1,171 @@
+body {\r
+    background: #f4f8fa;\r
+    \r
+    font: 13px/22px "Helvetica Neue", sans-serif;\r
+    color: #6c7f85;\r
+    text-shadow: 0 1px 0 #fff;\r
+    \r
+    width: 720px;\r
+    margin: 50px auto 40px;\r
+}\r
+\r
+h1 {\r
+    text-align: center;\r
+    margin-bottom: 60px;\r
+}\r
+\r
+h2 {\r
+    font-size: 32px;\r
+    font-weight: 300;\r
+    color: #57829e;\r
+}\r
+\r
+a {\r
+       color: #57829e;\r
+}\r
+\r
+.content {\r
+    padding: 20px 40px;\r
+    \r
+    background: #fff;\r
+    box-shadow: 0 1px 1px #c8d3da, inset 0 -2px 1px #f6f9fb;\r
+    border-radius: 4px;\r
+}\r
+\r
+small {\r
+    font-size: 11px;\r
+    line-height: 18px;\r
+    \r
+    display: block;\r
+    padding: 8px 12px;\r
+    \r
+    background: #ffe;\r
+    color: #775;\r
+    border: 1px solid #eed;\r
+    border-radius: 3px;\r
+}\r
+\r
+p.error, p.success {\r
+       color: #fff;\r
+       text-shadow: 0 1px 1px rgba(0,0,0,.3);\r
+       text-align: center;\r
+       padding: 10px;\r
+\r
+       border-radius: 3px;\r
+}\r
+\r
+p.error {\r
+       background: #900;\r
+}\r
+    \r
+p.success {\r
+       background: #757e0e;\r
+}\r
+    \r
+    \r
+form {\r
+    overflow: hidden;\r
+    width: 720px;\r
+}\r
+\r
+fieldset {\r
+    border: 1px solid #d5e4eb;\r
+    border-radius: 3px;\r
+    \r
+    margin: 30px 36px 30px 0;\r
+    padding: 5px 25px;\r
+    \r
+    float: left;\r
+    overflow: hidden;\r
+    position: relative;\r
+    \r
+    width: 250px;\r
+}\r
+    legend {\r
+        font-weight: bold;\r
+    }\r
+    \r
+    label {\r
+        display: block;\r
+        font-size: 12px;\r
+        font-weight: bold;\r
+        cursor: pointer;\r
+    }\r
+    \r
+    input, textarea {\r
+        font: 13px "Helvetica Neue", sans-serif;\r
+        padding: 5px 8px;\r
+        width: 230px;\r
+    }\r
+        textarea {\r
+            min-height: 70px;\r
+            max-height: 250px;\r
+            resize: vertical;\r
+        }\r
+    select {\r
+        width: 245px;\r
+        padding: 4px 8px;\r
+    }\r
+    \r
+button, .button {\r
+    font: bold 13px "Helvetica Neue", sans-serif;\r
+    color: #fff;\r
+    text-shadow: 0 1px 1px rgba(0,0,0,.3);\r
+    text-decoration: none;\r
+    \r
+    display: block;\r
+    width: auto;\r
+    float: right;\r
+    cursor: pointer;\r
+    \r
+    margin-bottom: 20px;\r
+    padding: 6px 9px;\r
+    \r
+    border: 1px solid #2f4a57;\r
+    border-radius: 3px;\r
+    \r
+    background-color: #587786;\r
+    background-image: -webkit-gradient(linear, left top, left bottom, from(#6c8894), to(#486472));\r
+    background-image: -webkit-linear-gradient(top, #6c8894, #486472);\r
+    background-image: -moz-linear-gradient(top, #6c8894, #486472);\r
+    background-image: -o-linear-gradient(top, #6c8894, #486472);\r
+    background-image: -ms-linear-gradient(top, #6c8894, #486472);\r
+    background-image: linear-gradient(top, #6c8894, #486472);\r
+    filter: progid:DXImageTransform.Microsoft.gradient(GradientType=0,StartColorStr='#6c8894', EndColorStr='#486472');\r
+    \r
+    box-shadow: inset 0 1px 0 rgba(255,255,255,.15), 0 1px 1px rgba(0,0,0,.05);\r
+}\r
+\r
+    form > button, form > p {\r
+        margin-right: 75px;\r
+    }\r
+\r
+    button:hover, .button:hover {\r
+        opacity: .9;\r
+    }\r
+    button:active, .button:active {\r
+        opacity: 1;\r
+        \r
+        background-color: #3a5968;\r
+        background-image: -webkit-gradient(linear, left top, left bottom, from(#365361), to(#587684));\r
+        background-image: -webkit-linear-gradient(top, #365361, #587684);\r
+        background-image: -moz-linear-gradient(top, #365361, #587684);\r
+        background-image: -o-linear-gradient(top, #365361, #587684);\r
+        background-image: -ms-linear-gradient(top, #365361, #587684);\r
+        background-image: linear-gradient(top, #365361, #587684);\r
+        filter: progid:DXImageTransform.Microsoft.gradient(GradientType=0,StartColorStr='#365361', EndColorStr='#587684');\r
+        \r
+        box-shadow: inset 0 1px 1px rgba(0,0,0,.15), 0 -1px 1px rgba(0,0,0,.1);\r
+        \r
+        border-color: #192e39;\r
+    }\r
+    \r
+p.footer {\r
+    font-size: 12px;\r
+    text-align: center;\r
+    \r
+    padding-top: 40px;\r
+}\r
+    p.footer a {\r
+        color: #587684;\r
+    }\r
diff --git a/testcms-final-anon/install/assets/img/logo.gif b/testcms-final-anon/install/assets/img/logo.gif
new file mode 100644 (file)
index 0000000..1f876bf
Binary files /dev/null and b/testcms-final-anon/install/assets/img/logo.gif differ
diff --git a/testcms-final-anon/install/assets/js/app.js b/testcms-final-anon/install/assets/js/app.js
new file mode 100644 (file)
index 0000000..2ed7fa3
--- /dev/null
@@ -0,0 +1,96 @@
+$(function() {\r
+    var body = $('body'), form = $('form'), notes = $('.notes');\r
+        \r
+    // remove no js error\r
+    body.find('.nojs').remove();\r
+        \r
+    // Do some fancy fading in, and get rid of that damn error.\r
+    body.hide().fadeIn()\r
+    \r
+       // remove previous notifications\r
+       var remove_notes = function() {\r
+       notes.find('p').remove();\r
+               notes.hide();\r
+       };\r
+    \r
+    // Check when the MySQL form has been submitted, and AJAX a request off.\r
+    var check = function() {  \r
+       // remove previous notifications\r
+       remove_notes();\r
+       \r
+       // dim fieldset\r
+       $('#diagnose').animate({'opacity': 0.5}, 250, function() {\r
+                   $.ajax({\r
+                       'type': 'POST',\r
+                       'url': 'diagnose.php',\r
+                       'data': form.serialize(),\r
+                       'success': check_result\r
+                   });\r
+       });\r
+            \r
+        return false;\r
+    };\r
+    \r
+       var check_result = function(data) {\r
+               $('#diagnose').animate({'opacity': 1});\r
+\r
+               if(data == 'good') {\r
+                       notes.show().append('<p class="success">&#10003; Database test successful.</p>').fadeIn();\r
+               } else {\r
+                       notes.show().append('<p class="error">' + data + '</p>').fadeIn();\r
+               }\r
+       };\r
+    \r
+    var submit = function() {\r
+               $.ajax({\r
+                       'type': 'POST',\r
+                       'url': 'installer.php',\r
+                       'data': form.serialize(),\r
+                       'dataType': 'json',\r
+                       'success': submit_result\r
+               });\r
+\r
+               return false;\r
+    };\r
+    \r
+    var submit_result = function(data) {\r
+       // remove previous notifications\r
+       remove_notes();\r
+\r
+               if(data.installed) {\r
+                       var content = $('.content');\r
+                       \r
+                       content.animate({'opacity': 0}, function() {\r
+                               var btn_text = 'Continue to your site.';\r
+\r
+                               var html = '<h2>Thanks for installing!</h2>';\r
+                               html += '<p>We created an account for you.<br>The username is <b>admin</b>, and the password is <strong>' + data.password + '</strong>.</p>';\r
+\r
+                               if(data.warnings.length) {\r
+                                       btn_text = 'OK, I understand, Continue to your site.';\r
+\r
+                                       html += '<ul style="padding-bottom: 1em;">';\r
+\r
+                                       for(var i = 0; i < data.warnings.length; i++) {\r
+                                               var warn = data.warnings[i];\r
+                                               html += '<li>' + warn + '</li>';\r
+                                       }\r
+\r
+                                       html += '</ul>';\r
+                               }\r
+\r
+                               html += '<p><a href="../" class="button" style="float: none; display: inline-block;">' + btn_text + '</a></p>';\r
+\r
+                               content.html(html).animate({'opacity': 1});\r
+                       });\r
+               } else {\r
+                       notes.show().append('<p class="error">' + data.errors.join(', ') + '</p>').fadeIn();\r
+               }\r
+    };\r
+    \r
+    // Bind normal form submit\r
+    form.bind('submit', submit);\r
+    \r
+    // Bind db check\r
+    $('a[href$=#check]').bind('click', check);\r
+});\r
diff --git a/testcms-final-anon/install/assets/js/jquery.js b/testcms-final-anon/install/assets/js/jquery.js
new file mode 100644 (file)
index 0000000..308f628
--- /dev/null
@@ -0,0 +1,4 @@
+/*! jQuery v1.7.1 jquery.com | jquery.org/license */\r
+(function(a,b){function cy(a){return f.isWindow(a)?a:a.nodeType===9?a.defaultView||a.parentWindow:!1}function cv(a){if(!ck[a]){var b=c.body,d=f("<"+a+">").appendTo(b),e=d.css("display");d.remove();if(e==="none"||e===""){cl||(cl=c.createElement("iframe"),cl.frameBorder=cl.width=cl.height=0),b.appendChild(cl);if(!cm||!cl.createElement)cm=(cl.contentWindow||cl.contentDocument).document,cm.write((c.compatMode==="CSS1Compat"?"<!doctype html>":"")+"<html><body>"),cm.close();d=cm.createElement(a),cm.body.appendChild(d),e=f.css(d,"display"),b.removeChild(cl)}ck[a]=e}return ck[a]}function cu(a,b){var c={};f.each(cq.concat.apply([],cq.slice(0,b)),function(){c[this]=a});return c}function ct(){cr=b}function cs(){setTimeout(ct,0);return cr=f.now()}function cj(){try{return new a.ActiveXObject("Microsoft.XMLHTTP")}catch(b){}}function ci(){try{return new a.XMLHttpRequest}catch(b){}}function cc(a,c){a.dataFilter&&(c=a.dataFilter(c,a.dataType));var d=a.dataTypes,e={},g,h,i=d.length,j,k=d[0],l,m,n,o,p;for(g=1;g<i;g++){if(g===1)for(h in a.converters)typeof h=="string"&&(e[h.toLowerCase()]=a.converters[h]);l=k,k=d[g];if(k==="*")k=l;else if(l!=="*"&&l!==k){m=l+" "+k,n=e[m]||e["* "+k];if(!n){p=b;for(o in e){j=o.split(" ");if(j[0]===l||j[0]==="*"){p=e[j[1]+" "+k];if(p){o=e[o],o===!0?n=p:p===!0&&(n=o);break}}}}!n&&!p&&f.error("No conversion from "+m.replace(" "," to ")),n!==!0&&(c=n?n(c):p(o(c)))}}return c}function cb(a,c,d){var e=a.contents,f=a.dataTypes,g=a.responseFields,h,i,j,k;for(i in g)i in d&&(c[g[i]]=d[i]);while(f[0]==="*")f.shift(),h===b&&(h=a.mimeType||c.getResponseHeader("content-type"));if(h)for(i in e)if(e[i]&&e[i].test(h)){f.unshift(i);break}if(f[0]in d)j=f[0];else{for(i in d){if(!f[0]||a.converters[i+" "+f[0]]){j=i;break}k||(k=i)}j=j||k}if(j){j!==f[0]&&f.unshift(j);return d[j]}}function ca(a,b,c,d){if(f.isArray(b))f.each(b,function(b,e){c||bE.test(a)?d(a,e):ca(a+"["+(typeof e=="object"||f.isArray(e)?b:"")+"]",e,c,d)});else if(!c&&b!=null&&typeof b=="object")for(var e in b)ca(a+"["+e+"]",b[e],c,d);else d(a,b)}function b_(a,c){var d,e,g=f.ajaxSettings.flatOptions||{};for(d in c)c[d]!==b&&((g[d]?a:e||(e={}))[d]=c[d]);e&&f.extend(!0,a,e)}function b$(a,c,d,e,f,g){f=f||c.dataTypes[0],g=g||{},g[f]=!0;var h=a[f],i=0,j=h?h.length:0,k=a===bT,l;for(;i<j&&(k||!l);i++)l=h[i](c,d,e),typeof l=="string"&&(!k||g[l]?l=b:(c.dataTypes.unshift(l),l=b$(a,c,d,e,l,g)));(k||!l)&&!g["*"]&&(l=b$(a,c,d,e,"*",g));return l}function bZ(a){return function(b,c){typeof b!="string"&&(c=b,b="*");if(f.isFunction(c)){var d=b.toLowerCase().split(bP),e=0,g=d.length,h,i,j;for(;e<g;e++)h=d[e],j=/^\+/.test(h),j&&(h=h.substr(1)||"*"),i=a[h]=a[h]||[],i[j?"unshift":"push"](c)}}}function bC(a,b,c){var d=b==="width"?a.offsetWidth:a.offsetHeight,e=b==="width"?bx:by,g=0,h=e.length;if(d>0){if(c!=="border")for(;g<h;g++)c||(d-=parseFloat(f.css(a,"padding"+e[g]))||0),c==="margin"?d+=parseFloat(f.css(a,c+e[g]))||0:d-=parseFloat(f.css(a,"border"+e[g]+"Width"))||0;return d+"px"}d=bz(a,b,b);if(d<0||d==null)d=a.style[b]||0;d=parseFloat(d)||0;if(c)for(;g<h;g++)d+=parseFloat(f.css(a,"padding"+e[g]))||0,c!=="padding"&&(d+=parseFloat(f.css(a,"border"+e[g]+"Width"))||0),c==="margin"&&(d+=parseFloat(f.css(a,c+e[g]))||0);return d+"px"}function bp(a,b){b.src?f.ajax({url:b.src,async:!1,dataType:"script"}):f.globalEval((b.text||b.textContent||b.innerHTML||"").replace(bf,"/*$0*/")),b.parentNode&&b.parentNode.removeChild(b)}function bo(a){var b=c.createElement("div");bh.appendChild(b),b.innerHTML=a.outerHTML;return b.firstChild}function bn(a){var b=(a.nodeName||"").toLowerCase();b==="input"?bm(a):b!=="script"&&typeof a.getElementsByTagName!="undefined"&&f.grep(a.getElementsByTagName("input"),bm)}function bm(a){if(a.type==="checkbox"||a.type==="radio")a.defaultChecked=a.checked}function bl(a){return typeof a.getElementsByTagName!="undefined"?a.getElementsByTagName("*"):typeof a.querySelectorAll!="undefined"?a.querySelectorAll("*"):[]}function bk(a,b){var c;if(b.nodeType===1){b.clearAttributes&&b.clearAttributes(),b.mergeAttributes&&b.mergeAttributes(a),c=b.nodeName.toLowerCase();if(c==="object")b.outerHTML=a.outerHTML;else if(c!=="input"||a.type!=="checkbox"&&a.type!=="radio"){if(c==="option")b.selected=a.defaultSelected;else if(c==="input"||c==="textarea")b.defaultValue=a.defaultValue}else a.checked&&(b.defaultChecked=b.checked=a.checked),b.value!==a.value&&(b.value=a.value);b.removeAttribute(f.expando)}}function bj(a,b){if(b.nodeType===1&&!!f.hasData(a)){var c,d,e,g=f._data(a),h=f._data(b,g),i=g.events;if(i){delete h.handle,h.events={};for(c in i)for(d=0,e=i[c].length;d<e;d++)f.event.add(b,c+(i[c][d].namespace?".":"")+i[c][d].namespace,i[c][d],i[c][d].data)}h.data&&(h.data=f.extend({},h.data))}}function bi(a,b){return f.nodeName(a,"table")?a.getElementsByTagName("tbody")[0]||a.appendChild(a.ownerDocument.createElement("tbody")):a}function U(a){var b=V.split("|"),c=a.createDocumentFragment();if(c.createElement)while(b.length)c.createElement(b.pop());return c}function T(a,b,c){b=b||0;if(f.isFunction(b))return f.grep(a,function(a,d){var e=!!b.call(a,d,a);return e===c});if(b.nodeType)return f.grep(a,function(a,d){return a===b===c});if(typeof b=="string"){var d=f.grep(a,function(a){return a.nodeType===1});if(O.test(b))return f.filter(b,d,!c);b=f.filter(b,d)}return f.grep(a,function(a,d){return f.inArray(a,b)>=0===c})}function S(a){return!a||!a.parentNode||a.parentNode.nodeType===11}function K(){return!0}function J(){return!1}function n(a,b,c){var d=b+"defer",e=b+"queue",g=b+"mark",h=f._data(a,d);h&&(c==="queue"||!f._data(a,e))&&(c==="mark"||!f._data(a,g))&&setTimeout(function(){!f._data(a,e)&&!f._data(a,g)&&(f.removeData(a,d,!0),h.fire())},0)}function m(a){for(var b in a){if(b==="data"&&f.isEmptyObject(a[b]))continue;if(b!=="toJSON")return!1}return!0}function l(a,c,d){if(d===b&&a.nodeType===1){var e="data-"+c.replace(k,"-$1").toLowerCase();d=a.getAttribute(e);if(typeof d=="string"){try{d=d==="true"?!0:d==="false"?!1:d==="null"?null:f.isNumeric(d)?parseFloat(d):j.test(d)?f.parseJSON(d):d}catch(g){}f.data(a,c,d)}else d=b}return d}function h(a){var b=g[a]={},c,d;a=a.split(/\s+/);for(c=0,d=a.length;c<d;c++)b[a[c]]=!0;return b}var c=a.document,d=a.navigator,e=a.location,f=function(){function J(){if(!e.isReady){try{c.documentElement.doScroll("left")}catch(a){setTimeout(J,1);return}e.ready()}}var e=function(a,b){return new e.fn.init(a,b,h)},f=a.jQuery,g=a.$,h,i=/^(?:[^#<]*(<[\w\W]+>)[^>]*$|#([\w\-]*)$)/,j=/\S/,k=/^\s+/,l=/\s+$/,m=/^<(\w+)\s*\/?>(?:<\/\1>)?$/,n=/^[\],:{}\s]*$/,o=/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g,p=/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g,q=/(?:^|:|,)(?:\s*\[)+/g,r=/(webkit)[ \/]([\w.]+)/,s=/(opera)(?:.*version)?[ \/]([\w.]+)/,t=/(msie) ([\w.]+)/,u=/(mozilla)(?:.*? rv:([\w.]+))?/,v=/-([a-z]|[0-9])/ig,w=/^-ms-/,x=function(a,b){return(b+"").toUpperCase()},y=d.userAgent,z,A,B,C=Object.prototype.toString,D=Object.prototype.hasOwnProperty,E=Array.prototype.push,F=Array.prototype.slice,G=String.prototype.trim,H=Array.prototype.indexOf,I={};e.fn=e.prototype={constructor:e,init:function(a,d,f){var g,h,j,k;if(!a)return this;if(a.nodeType){this.context=this[0]=a,this.length=1;return this}if(a==="body"&&!d&&c.body){this.context=c,this[0]=c.body,this.selector=a,this.length=1;return this}if(typeof a=="string"){a.charAt(0)!=="<"||a.charAt(a.length-1)!==">"||a.length<3?g=i.exec(a):g=[null,a,null];if(g&&(g[1]||!d)){if(g[1]){d=d instanceof e?d[0]:d,k=d?d.ownerDocument||d:c,j=m.exec(a),j?e.isPlainObject(d)?(a=[c.createElement(j[1])],e.fn.attr.call(a,d,!0)):a=[k.createElement(j[1])]:(j=e.buildFragment([g[1]],[k]),a=(j.cacheable?e.clone(j.fragment):j.fragment).childNodes);return e.merge(this,a)}h=c.getElementById(g[2]);if(h&&h.parentNode){if(h.id!==g[2])return f.find(a);this.length=1,this[0]=h}this.context=c,this.selector=a;return this}return!d||d.jquery?(d||f).find(a):this.constructor(d).find(a)}if(e.isFunction(a))return f.ready(a);a.selector!==b&&(this.selector=a.selector,this.context=a.context);return e.makeArray(a,this)},selector:"",jquery:"1.7.1",length:0,size:function(){return this.length},toArray:function(){return F.call(this,0)},get:function(a){return a==null?this.toArray():a<0?this[this.length+a]:this[a]},pushStack:function(a,b,c){var d=this.constructor();e.isArray(a)?E.apply(d,a):e.merge(d,a),d.prevObject=this,d.context=this.context,b==="find"?d.selector=this.selector+(this.selector?" ":"")+c:b&&(d.selector=this.selector+"."+b+"("+c+")");return d},each:function(a,b){return e.each(this,a,b)},ready:function(a){e.bindReady(),A.add(a);return this},eq:function(a){a=+a;return a===-1?this.slice(a):this.slice(a,a+1)},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},slice:function(){return this.pushStack(F.apply(this,arguments),"slice",F.call(arguments).join(","))},map:function(a){return this.pushStack(e.map(this,function(b,c){return a.call(b,c,b)}))},end:function(){return this.prevObject||this.constructor(null)},push:E,sort:[].sort,splice:[].splice},e.fn.init.prototype=e.fn,e.extend=e.fn.extend=function(){var a,c,d,f,g,h,i=arguments[0]||{},j=1,k=arguments.length,l=!1;typeof i=="boolean"&&(l=i,i=arguments[1]||{},j=2),typeof i!="object"&&!e.isFunction(i)&&(i={}),k===j&&(i=this,--j);for(;j<k;j++)if((a=arguments[j])!=null)for(c in a){d=i[c],f=a[c];if(i===f)continue;l&&f&&(e.isPlainObject(f)||(g=e.isArray(f)))?(g?(g=!1,h=d&&e.isArray(d)?d:[]):h=d&&e.isPlainObject(d)?d:{},i[c]=e.extend(l,h,f)):f!==b&&(i[c]=f)}return i},e.extend({noConflict:function(b){a.$===e&&(a.$=g),b&&a.jQuery===e&&(a.jQuery=f);return e},isReady:!1,readyWait:1,holdReady:function(a){a?e.readyWait++:e.ready(!0)},ready:function(a){if(a===!0&&!--e.readyWait||a!==!0&&!e.isReady){if(!c.body)return setTimeout(e.ready,1);e.isReady=!0;if(a!==!0&&--e.readyWait>0)return;A.fireWith(c,[e]),e.fn.trigger&&e(c).trigger("ready").off("ready")}},bindReady:function(){if(!A){A=e.Callbacks("once memory");if(c.readyState==="complete")return setTimeout(e.ready,1);if(c.addEventListener)c.addEventListener("DOMContentLoaded",B,!1),a.addEventListener("load",e.ready,!1);else if(c.attachEvent){c.attachEvent("onreadystatechange",B),a.attachEvent("onload",e.ready);var b=!1;try{b=a.frameElement==null}catch(d){}c.documentElement.doScroll&&b&&J()}}},isFunction:function(a){return e.type(a)==="function"},isArray:Array.isArray||function(a){return e.type(a)==="array"},isWindow:function(a){return a&&typeof a=="object"&&"setInterval"in a},isNumeric:function(a){return!isNaN(parseFloat(a))&&isFinite(a)},type:function(a){return a==null?String(a):I[C.call(a)]||"object"},isPlainObject:function(a){if(!a||e.type(a)!=="object"||a.nodeType||e.isWindow(a))return!1;try{if(a.constructor&&!D.call(a,"constructor")&&!D.call(a.constructor.prototype,"isPrototypeOf"))return!1}catch(c){return!1}var d;for(d in a);return d===b||D.call(a,d)},isEmptyObject:function(a){for(var b in a)return!1;return!0},error:function(a){throw new Error(a)},parseJSON:function(b){if(typeof b!="string"||!b)return null;b=e.trim(b);if(a.JSON&&a.JSON.parse)return a.JSON.parse(b);if(n.test(b.replace(o,"@").replace(p,"]").replace(q,"")))return(new Function("return "+b))();e.error("Invalid JSON: "+b)},parseXML:function(c){var d,f;try{a.DOMParser?(f=new DOMParser,d=f.parseFromString(c,"text/xml")):(d=new ActiveXObject("Microsoft.XMLDOM"),d.async="false",d.loadXML(c))}catch(g){d=b}(!d||!d.documentElement||d.getElementsByTagName("parsererror").length)&&e.error("Invalid XML: "+c);return d},noop:function(){},globalEval:function(b){b&&j.test(b)&&(a.execScript||function(b){a.eval.call(a,b)})(b)},camelCase:function(a){return a.replace(w,"ms-").replace(v,x)},nodeName:function(a,b){return a.nodeName&&a.nodeName.toUpperCase()===b.toUpperCase()},each:function(a,c,d){var f,g=0,h=a.length,i=h===b||e.isFunction(a);if(d){if(i){for(f in a)if(c.apply(a[f],d)===!1)break}else for(;g<h;)if(c.apply(a[g++],d)===!1)break}else if(i){for(f in a)if(c.call(a[f],f,a[f])===!1)break}else for(;g<h;)if(c.call(a[g],g,a[g++])===!1)break;return a},trim:G?function(a){return a==null?"":G.call(a)}:function(a){return a==null?"":(a+"").replace(k,"").replace(l,"")},makeArray:function(a,b){var c=b||[];if(a!=null){var d=e.type(a);a.length==null||d==="string"||d==="function"||d==="regexp"||e.isWindow(a)?E.call(c,a):e.merge(c,a)}return c},inArray:function(a,b,c){var d;if(b){if(H)return H.call(b,a,c);d=b.length,c=c?c<0?Math.max(0,d+c):c:0;for(;c<d;c++)if(c in b&&b[c]===a)return c}return-1},merge:function(a,c){var d=a.length,e=0;if(typeof c.length=="number")for(var f=c.length;e<f;e++)a[d++]=c[e];else while(c[e]!==b)a[d++]=c[e++];a.length=d;return a},grep:function(a,b,c){var d=[],e;c=!!c;for(var f=0,g=a.length;f<g;f++)e=!!b(a[f],f),c!==e&&d.push(a[f]);return d},map:function(a,c,d){var f,g,h=[],i=0,j=a.length,k=a instanceof e||j!==b&&typeof j=="number"&&(j>0&&a[0]&&a[j-1]||j===0||e.isArray(a));if(k)for(;i<j;i++)f=c(a[i],i,d),f!=null&&(h[h.length]=f);else for(g in a)f=c(a[g],g,d),f!=null&&(h[h.length]=f);return h.concat.apply([],h)},guid:1,proxy:function(a,c){if(typeof c=="string"){var d=a[c];c=a,a=d}if(!e.isFunction(a))return b;var f=F.call(arguments,2),g=function(){return a.apply(c,f.concat(F.call(arguments)))};g.guid=a.guid=a.guid||g.guid||e.guid++;return g},access:function(a,c,d,f,g,h){var i=a.length;if(typeof c=="object"){for(var j in c)e.access(a,j,c[j],f,g,d);return a}if(d!==b){f=!h&&f&&e.isFunction(d);for(var k=0;k<i;k++)g(a[k],c,f?d.call(a[k],k,g(a[k],c)):d,h);return a}return i?g(a[0],c):b},now:function(){return(new Date).getTime()},uaMatch:function(a){a=a.toLowerCase();var b=r.exec(a)||s.exec(a)||t.exec(a)||a.indexOf("compatible")<0&&u.exec(a)||[];return{browser:b[1]||"",version:b[2]||"0"}},sub:function(){function a(b,c){return new a.fn.init(b,c)}e.extend(!0,a,this),a.superclass=this,a.fn=a.prototype=this(),a.fn.constructor=a,a.sub=this.sub,a.fn.init=function(d,f){f&&f instanceof e&&!(f instanceof a)&&(f=a(f));return e.fn.init.call(this,d,f,b)},a.fn.init.prototype=a.fn;var b=a(c);return a},browser:{}}),e.each("Boolean Number String Function Array Date RegExp Object".split(" "),function(a,b){I["[object "+b+"]"]=b.toLowerCase()}),z=e.uaMatch(y),z.browser&&(e.browser[z.browser]=!0,e.browser.version=z.version),e.browser.webkit&&(e.browser.safari=!0),j.test(" ")&&(k=/^[\s\xA0]+/,l=/[\s\xA0]+$/),h=e(c),c.addEventListener?B=function(){c.removeEventListener("DOMContentLoaded",B,!1),e.ready()}:c.attachEvent&&(B=function(){c.readyState==="complete"&&(c.detachEvent("onreadystatechange",B),e.ready())});return e}(),g={};f.Callbacks=function(a){a=a?g[a]||h(a):{};var c=[],d=[],e,i,j,k,l,m=function(b){var d,e,g,h,i;for(d=0,e=b.length;d<e;d++)g=b[d],h=f.type(g),h==="array"?m(g):h==="function"&&(!a.unique||!o.has(g))&&c.push(g)},n=function(b,f){f=f||[],e=!a.memory||[b,f],i=!0,l=j||0,j=0,k=c.length;for(;c&&l<k;l++)if(c[l].apply(b,f)===!1&&a.stopOnFalse){e=!0;break}i=!1,c&&(a.once?e===!0?o.disable():c=[]:d&&d.length&&(e=d.shift(),o.fireWith(e[0],e[1])))},o={add:function(){if(c){var a=c.length;m(arguments),i?k=c.length:e&&e!==!0&&(j=a,n(e[0],e[1]))}return this},remove:function(){if(c){var b=arguments,d=0,e=b.length;for(;d<e;d++)for(var f=0;f<c.length;f++)if(b[d]===c[f]){i&&f<=k&&(k--,f<=l&&l--),c.splice(f--,1);if(a.unique)break}}return this},has:function(a){if(c){var b=0,d=c.length;for(;b<d;b++)if(a===c[b])return!0}return!1},empty:function(){c=[];return this},disable:function(){c=d=e=b;return this},disabled:function(){return!c},lock:function(){d=b,(!e||e===!0)&&o.disable();return this},locked:function(){return!d},fireWith:function(b,c){d&&(i?a.once||d.push([b,c]):(!a.once||!e)&&n(b,c));return this},fire:function(){o.fireWith(this,arguments);return this},fired:function(){return!!e}};return o};var i=[].slice;f.extend({Deferred:function(a){var b=f.Callbacks("once memory"),c=f.Callbacks("once memory"),d=f.Callbacks("memory"),e="pending",g={resolve:b,reject:c,notify:d},h={done:b.add,fail:c.add,progress:d.add,state:function(){return e},isResolved:b.fired,isRejected:c.fired,then:function(a,b,c){i.done(a).fail(b).progress(c);return this},always:function(){i.done.apply(i,arguments).fail.apply(i,arguments);return this},pipe:function(a,b,c){return f.Deferred(function(d){f.each({done:[a,"resolve"],fail:[b,"reject"],progress:[c,"notify"]},function(a,b){var c=b[0],e=b[1],g;f.isFunction(c)?i[a](function(){g=c.apply(this,arguments),g&&f.isFunction(g.promise)?g.promise().then(d.resolve,d.reject,d.notify):d[e+"With"](this===i?d:this,[g])}):i[a](d[e])})}).promise()},promise:function(a){if(a==null)a=h;else for(var b in h)a[b]=h[b];return a}},i=h.promise({}),j;for(j in g)i[j]=g[j].fire,i[j+"With"]=g[j].fireWith;i.done(function(){e="resolved"},c.disable,d.lock).fail(function(){e="rejected"},b.disable,d.lock),a&&a.call(i,i);return i},when:function(a){function m(a){return function(b){e[a]=arguments.length>1?i.call(arguments,0):b,j.notifyWith(k,e)}}function l(a){return function(c){b[a]=arguments.length>1?i.call(arguments,0):c,--g||j.resolveWith(j,b)}}var b=i.call(arguments,0),c=0,d=b.length,e=Array(d),g=d,h=d,j=d<=1&&a&&f.isFunction(a.promise)?a:f.Deferred(),k=j.promise();if(d>1){for(;c<d;c++)b[c]&&b[c].promise&&f.isFunction(b[c].promise)?b[c].promise().then(l(c),j.reject,m(c)):--g;g||j.resolveWith(j,b)}else j!==a&&j.resolveWith(j,d?[a]:[]);return k}}),f.support=function(){var b,d,e,g,h,i,j,k,l,m,n,o,p,q=c.createElement("div"),r=c.documentElement;q.setAttribute("className","t"),q.innerHTML="   <link/><table></table><a href='/a' style='top:1px;float:left;opacity:.55;'>a</a><input type='checkbox'/>",d=q.getElementsByTagName("*"),e=q.getElementsByTagName("a")[0];if(!d||!d.length||!e)return{};g=c.createElement("select"),h=g.appendChild(c.createElement("option")),i=q.getElementsByTagName("input")[0],b={leadingWhitespace:q.firstChild.nodeType===3,tbody:!q.getElementsByTagName("tbody").length,htmlSerialize:!!q.getElementsByTagName("link").length,style:/top/.test(e.getAttribute("style")),hrefNormalized:e.getAttribute("href")==="/a",opacity:/^0.55/.test(e.style.opacity),cssFloat:!!e.style.cssFloat,checkOn:i.value==="on",optSelected:h.selected,getSetAttribute:q.className!=="t",enctype:!!c.createElement("form").enctype,html5Clone:c.createElement("nav").cloneNode(!0).outerHTML!=="<:nav></:nav>",submitBubbles:!0,changeBubbles:!0,focusinBubbles:!1,deleteExpando:!0,noCloneEvent:!0,inlineBlockNeedsLayout:!1,shrinkWrapBlocks:!1,reliableMarginRight:!0},i.checked=!0,b.noCloneChecked=i.cloneNode(!0).checked,g.disabled=!0,b.optDisabled=!h.disabled;try{delete q.test}catch(s){b.deleteExpando=!1}!q.addEventListener&&q.attachEvent&&q.fireEvent&&(q.attachEvent("onclick",function(){b.noCloneEvent=!1}),q.cloneNode(!0).fireEvent("onclick")),i=c.createElement("input"),i.value="t",i.setAttribute("type","radio"),b.radioValue=i.value==="t",i.setAttribute("checked","checked"),q.appendChild(i),k=c.createDocumentFragment(),k.appendChild(q.lastChild),b.checkClone=k.cloneNode(!0).cloneNode(!0).lastChild.checked,b.appendChecked=i.checked,k.removeChild(i),k.appendChild(q),q.innerHTML="",a.getComputedStyle&&(j=c.createElement("div"),j.style.width="0",j.style.marginRight="0",q.style.width="2px",q.appendChild(j),b.reliableMarginRight=(parseInt((a.getComputedStyle(j,null)||{marginRight:0}).marginRight,10)||0)===0);if(q.attachEvent)for(o in{submit:1,change:1,focusin:1})n="on"+o,p=n in q,p||(q.setAttribute(n,"return;"),p=typeof q[n]=="function"),b[o+"Bubbles"]=p;k.removeChild(q),k=g=h=j=q=i=null,f(function(){var a,d,e,g,h,i,j,k,m,n,o,r=c.getElementsByTagName("body")[0];!r||(j=1,k="position:absolute;top:0;left:0;width:1px;height:1px;margin:0;",m="visibility:hidden;border:0;",n="style='"+k+"border:5px solid #000;padding:0;'",o="<div "+n+"><div></div></div>"+"<table "+n+" cellpadding='0' cellspacing='0'>"+"<tr><td></td></tr></table>",a=c.createElement("div"),a.style.cssText=m+"width:0;height:0;position:static;top:0;margin-top:"+j+"px",r.insertBefore(a,r.firstChild),q=c.createElement("div"),a.appendChild(q),q.innerHTML="<table><tr><td style='padding:0;border:0;display:none'></td><td>t</td></tr></table>",l=q.getElementsByTagName("td"),p=l[0].offsetHeight===0,l[0].style.display="",l[1].style.display="none",b.reliableHiddenOffsets=p&&l[0].offsetHeight===0,q.innerHTML="",q.style.width=q.style.paddingLeft="1px",f.boxModel=b.boxModel=q.offsetWidth===2,typeof q.style.zoom!="undefined"&&(q.style.display="inline",q.style.zoom=1,b.inlineBlockNeedsLayout=q.offsetWidth===2,q.style.display="",q.innerHTML="<div style='width:4px;'></div>",b.shrinkWrapBlocks=q.offsetWidth!==2),q.style.cssText=k+m,q.innerHTML=o,d=q.firstChild,e=d.firstChild,h=d.nextSibling.firstChild.firstChild,i={doesNotAddBorder:e.offsetTop!==5,doesAddBorderForTableAndCells:h.offsetTop===5},e.style.position="fixed",e.style.top="20px",i.fixedPosition=e.offsetTop===20||e.offsetTop===15,e.style.position=e.style.top="",d.style.overflow="hidden",d.style.position="relative",i.subtractsBorderForOverflowNotVisible=e.offsetTop===-5,i.doesNotIncludeMarginInBodyOffset=r.offsetTop!==j,r.removeChild(a),q=a=null,f.extend(b,i))});return b}();var j=/^(?:\{.*\}|\[.*\])$/,k=/([A-Z])/g;f.extend({cache:{},uuid:0,expando:"jQuery"+(f.fn.jquery+Math.random()).replace(/\D/g,""),noData:{embed:!0,object:"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000",applet:!0},hasData:function(a){a=a.nodeType?f.cache[a[f.expando]]:a[f.expando];return!!a&&!m(a)},data:function(a,c,d,e){if(!!f.acceptData(a)){var g,h,i,j=f.expando,k=typeof c=="string",l=a.nodeType,m=l?f.cache:a,n=l?a[j]:a[j]&&j,o=c==="events";if((!n||!m[n]||!o&&!e&&!m[n].data)&&k&&d===b)return;n||(l?a[j]=n=++f.uuid:n=j),m[n]||(m[n]={},l||(m[n].toJSON=f.noop));if(typeof c=="object"||typeof c=="function")e?m[n]=f.extend(m[n],c):m[n].data=f.extend(m[n].data,c);g=h=m[n],e||(h.data||(h.data={}),h=h.data),d!==b&&(h[f.camelCase(c)]=d);if(o&&!h[c])return g.events;k?(i=h[c],i==null&&(i=h[f.camelCase(c)])):i=h;return i}},removeData:function(a,b,c){if(!!f.acceptData(a)){var d,e,g,h=f.expando,i=a.nodeType,j=i?f.cache:a,k=i?a[h]:h;if(!j[k])return;if(b){d=c?j[k]:j[k].data;if(d){f.isArray(b)||(b in d?b=[b]:(b=f.camelCase(b),b in d?b=[b]:b=b.split(" ")));for(e=0,g=b.length;e<g;e++)delete d[b[e]];if(!(c?m:f.isEmptyObject)(d))return}}if(!c){delete j[k].data;if(!m(j[k]))return}f.support.deleteExpando||!j.setInterval?delete j[k]:j[k]=null,i&&(f.support.deleteExpando?delete a[h]:a.removeAttribute?a.removeAttribute(h):a[h]=null)}},_data:function(a,b,c){return f.data(a,b,c,!0)},acceptData:function(a){if(a.nodeName){var b=f.noData[a.nodeName.toLowerCase()];if(b)return b!==!0&&a.getAttribute("classid")===b}return!0}}),f.fn.extend({data:function(a,c){var d,e,g,h=null;if(typeof a=="undefined"){if(this.length){h=f.data(this[0]);if(this[0].nodeType===1&&!f._data(this[0],"parsedAttrs")){e=this[0].attributes;for(var i=0,j=e.length;i<j;i++)g=e[i].name,g.indexOf("data-")===0&&(g=f.camelCase(g.substring(5)),l(this[0],g,h[g]));f._data(this[0],"parsedAttrs",!0)}}return h}if(typeof a=="object")return this.each(function(){f.data(this,a)});d=a.split("."),d[1]=d[1]?"."+d[1]:"";if(c===b){h=this.triggerHandler("getData"+d[1]+"!",[d[0]]),h===b&&this.length&&(h=f.data(this[0],a),h=l(this[0],a,h));return h===b&&d[1]?this.data(d[0]):h}return this.each(function(){var b=f(this),e=[d[0],c];b.triggerHandler("setData"+d[1]+"!",e),f.data(this,a,c),b.triggerHandler("changeData"+d[1]+"!",e)})},removeData:function(a){return this.each(function(){f.removeData(this,a)})}}),f.extend({_mark:function(a,b){a&&(b=(b||"fx")+"mark",f._data(a,b,(f._data(a,b)||0)+1))},_unmark:function(a,b,c){a!==!0&&(c=b,b=a,a=!1);if(b){c=c||"fx";var d=c+"mark",e=a?0:(f._data(b,d)||1)-1;e?f._data(b,d,e):(f.removeData(b,d,!0),n(b,c,"mark"))}},queue:function(a,b,c){var d;if(a){b=(b||"fx")+"queue",d=f._data(a,b),c&&(!d||f.isArray(c)?d=f._data(a,b,f.makeArray(c)):d.push(c));return d||[]}},dequeue:function(a,b){b=b||"fx";var c=f.queue(a,b),d=c.shift(),e={};d==="inprogress"&&(d=c.shift()),d&&(b==="fx"&&c.unshift("inprogress"),f._data(a,b+".run",e),d.call(a,function(){f.dequeue(a,b)},e)),c.length||(f.removeData(a,b+"queue "+b+".run",!0),n(a,b,"queue"))}}),f.fn.extend({queue:function(a,c){typeof a!="string"&&(c=a,a="fx");if(c===b)return f.queue(this[0],a);return this.each(function(){var b=f.queue(this,a,c);a==="fx"&&b[0]!=="inprogress"&&f.dequeue(this,a)})},dequeue:function(a){return this.each(function(){f.dequeue(this,a)})},delay:function(a,b){a=f.fx?f.fx.speeds[a]||a:a,b=b||"fx";return this.queue(b,function(b,c){var d=setTimeout(b,a);c.stop=function(){clearTimeout(d)}})},clearQueue:function(a){return this.queue(a||"fx",[])},promise:function(a,c){function m(){--h||d.resolveWith(e,[e])}typeof a!="string"&&(c=a,a=b),a=a||"fx";var d=f.Deferred(),e=this,g=e.length,h=1,i=a+"defer",j=a+"queue",k=a+"mark",l;while(g--)if(l=f.data(e[g],i,b,!0)||(f.data(e[g],j,b,!0)||f.data(e[g],k,b,!0))&&f.data(e[g],i,f.Callbacks("once memory"),!0))h++,l.add(m);m();return d.promise()}});var o=/[\n\t\r]/g,p=/\s+/,q=/\r/g,r=/^(?:button|input)$/i,s=/^(?:button|input|object|select|textarea)$/i,t=/^a(?:rea)?$/i,u=/^(?:autofocus|autoplay|async|checked|controls|defer|disabled|hidden|loop|multiple|open|readonly|required|scoped|selected)$/i,v=f.support.getSetAttribute,w,x,y;f.fn.extend({attr:function(a,b){return f.access(this,a,b,!0,f.attr)},removeAttr:function(a){return this.each(function(){f.removeAttr(this,a)})},prop:function(a,b){return f.access(this,a,b,!0,f.prop)},removeProp:function(a){a=f.propFix[a]||a;return this.each(function(){try{this[a]=b,delete this[a]}catch(c){}})},addClass:function(a){var b,c,d,e,g,h,i;if(f.isFunction(a))return this.each(function(b){f(this).addClass(a.call(this,b,this.className))});if(a&&typeof a=="string"){b=a.split(p);for(c=0,d=this.length;c<d;c++){e=this[c];if(e.nodeType===1)if(!e.className&&b.length===1)e.className=a;else{g=" "+e.className+" ";for(h=0,i=b.length;h<i;h++)~g.indexOf(" "+b[h]+" ")||(g+=b[h]+" ");e.className=f.trim(g)}}}return this},removeClass:function(a){var c,d,e,g,h,i,j;if(f.isFunction(a))return this.each(function(b){f(this).removeClass(a.call(this,b,this.className))});if(a&&typeof a=="string"||a===b){c=(a||"").split(p);for(d=0,e=this.length;d<e;d++){g=this[d];if(g.nodeType===1&&g.className)if(a){h=(" "+g.className+" ").replace(o," ");for(i=0,j=c.length;i<j;i++)h=h.replace(" "+c[i]+" "," ");g.className=f.trim(h)}else g.className=""}}return this},toggleClass:function(a,b){var c=typeof a,d=typeof b=="boolean";if(f.isFunction(a))return this.each(function(c){f(this).toggleClass(a.call(this,c,this.className,b),b)});return this.each(function(){if(c==="string"){var e,g=0,h=f(this),i=b,j=a.split(p);while(e=j[g++])i=d?i:!h.hasClass(e),h[i?"addClass":"removeClass"](e)}else if(c==="undefined"||c==="boolean")this.className&&f._data(this,"__className__",this.className),this.className=this.className||a===!1?"":f._data(this,"__className__")||""})},hasClass:function(a){var b=" "+a+" ",c=0,d=this.length;for(;c<d;c++)if(this[c].nodeType===1&&(" "+this[c].className+" ").replace(o," ").indexOf(b)>-1)return!0;return!1},val:function(a){var c,d,e,g=this[0];{if(!!arguments.length){e=f.isFunction(a);return this.each(function(d){var g=f(this),h;if(this.nodeType===1){e?h=a.call(this,d,g.val()):h=a,h==null?h="":typeof h=="number"?h+="":f.isArray(h)&&(h=f.map(h,function(a){return a==null?"":a+""})),c=f.valHooks[this.nodeName.toLowerCase()]||f.valHooks[this.type];if(!c||!("set"in c)||c.set(this,h,"value")===b)this.value=h}})}if(g){c=f.valHooks[g.nodeName.toLowerCase()]||f.valHooks[g.type];if(c&&"get"in c&&(d=c.get(g,"value"))!==b)return d;d=g.value;return typeof d=="string"?d.replace(q,""):d==null?"":d}}}}),f.extend({valHooks:{option:{get:function(a){var b=a.attributes.value;return!b||b.specified?a.value:a.text}},select:{get:function(a){var b,c,d,e,g=a.selectedIndex,h=[],i=a.options,j=a.type==="select-one";if(g<0)return null;c=j?g:0,d=j?g+1:i.length;for(;c<d;c++){e=i[c];if(e.selected&&(f.support.optDisabled?!e.disabled:e.getAttribute("disabled")===null)&&(!e.parentNode.disabled||!f.nodeName(e.parentNode,"optgroup"))){b=f(e).val();if(j)return b;h.push(b)}}if(j&&!h.length&&i.length)return f(i[g]).val();return h},set:function(a,b){var c=f.makeArray(b);f(a).find("option").each(function(){this.selected=f.inArray(f(this).val(),c)>=0}),c.length||(a.selectedIndex=-1);return c}}},attrFn:{val:!0,css:!0,html:!0,text:!0,data:!0,width:!0,height:!0,offset:!0},attr:function(a,c,d,e){var g,h,i,j=a.nodeType;if(!!a&&j!==3&&j!==8&&j!==2){if(e&&c in f.attrFn)return f(a)[c](d);if(typeof a.getAttribute=="undefined")return f.prop(a,c,d);i=j!==1||!f.isXMLDoc(a),i&&(c=c.toLowerCase(),h=f.attrHooks[c]||(u.test(c)?x:w));if(d!==b){if(d===null){f.removeAttr(a,c);return}if(h&&"set"in h&&i&&(g=h.set(a,d,c))!==b)return g;a.setAttribute(c,""+d);return d}if(h&&"get"in h&&i&&(g=h.get(a,c))!==null)return g;g=a.getAttribute(c);return g===null?b:g}},removeAttr:function(a,b){var c,d,e,g,h=0;if(b&&a.nodeType===1){d=b.toLowerCase().split(p),g=d.length;for(;h<g;h++)e=d[h],e&&(c=f.propFix[e]||e,f.attr(a,e,""),a.removeAttribute(v?e:c),u.test(e)&&c in a&&(a[c]=!1))}},attrHooks:{type:{set:function(a,b){if(r.test(a.nodeName)&&a.parentNode)f.error("type property can't be changed");else if(!f.support.radioValue&&b==="radio"&&f.nodeName(a,"input")){var c=a.value;a.setAttribute("type",b),c&&(a.value=c);return b}}},value:{get:function(a,b){if(w&&f.nodeName(a,"button"))return w.get(a,b);return b in a?a.value:null},set:function(a,b,c){if(w&&f.nodeName(a,"button"))return w.set(a,b,c);a.value=b}}},propFix:{tabindex:"tabIndex",readonly:"readOnly","for":"htmlFor","class":"className",maxlength:"maxLength",cellspacing:"cellSpacing",cellpadding:"cellPadding",rowspan:"rowSpan",colspan:"colSpan",usemap:"useMap",frameborder:"frameBorder",contenteditable:"contentEditable"},prop:function(a,c,d){var e,g,h,i=a.nodeType;if(!!a&&i!==3&&i!==8&&i!==2){h=i!==1||!f.isXMLDoc(a),h&&(c=f.propFix[c]||c,g=f.propHooks[c]);return d!==b?g&&"set"in g&&(e=g.set(a,d,c))!==b?e:a[c]=d:g&&"get"in g&&(e=g.get(a,c))!==null?e:a[c]}},propHooks:{tabIndex:{get:function(a){var c=a.getAttributeNode("tabindex");return c&&c.specified?parseInt(c.value,10):s.test(a.nodeName)||t.test(a.nodeName)&&a.href?0:b}}}}),f.attrHooks.tabindex=f.propHooks.tabIndex,x={get:function(a,c){var d,e=f.prop(a,c);return e===!0||typeof e!="boolean"&&(d=a.getAttributeNode(c))&&d.nodeValue!==!1?c.toLowerCase():b},set:function(a,b,c){var d;b===!1?f.removeAttr(a,c):(d=f.propFix[c]||c,d in a&&(a[d]=!0),a.setAttribute(c,c.toLowerCase()));return c}},v||(y={name:!0,id:!0},w=f.valHooks.button={get:function(a,c){var d;d=a.getAttributeNode(c);return d&&(y[c]?d.nodeValue!=="":d.specified)?d.nodeValue:b},set:function(a,b,d){var e=a.getAttributeNode(d);e||(e=c.createAttribute(d),a.setAttributeNode(e));return e.nodeValue=b+""}},f.attrHooks.tabindex.set=w.set,f.each(["width","height"],function(a,b){f.attrHooks[b]=f.extend(f.attrHooks[b],{set:function(a,c){if(c===""){a.setAttribute(b,"auto");return c}}})}),f.attrHooks.contenteditable={get:w.get,set:function(a,b,c){b===""&&(b="false"),w.set(a,b,c)}}),f.support.hrefNormalized||f.each(["href","src","width","height"],function(a,c){f.attrHooks[c]=f.extend(f.attrHooks[c],{get:function(a){var d=a.getAttribute(c,2);return d===null?b:d}})}),f.support.style||(f.attrHooks.style={get:function(a){return a.style.cssText.toLowerCase()||b},set:function(a,b){return a.style.cssText=""+b}}),f.support.optSelected||(f.propHooks.selected=f.extend(f.propHooks.selected,{get:function(a){var b=a.parentNode;b&&(b.selectedIndex,b.parentNode&&b.parentNode.selectedIndex);return null}})),f.support.enctype||(f.propFix.enctype="encoding"),f.support.checkOn||f.each(["radio","checkbox"],function(){f.valHooks[this]={get:function(a){return a.getAttribute("value")===null?"on":a.value}}}),f.each(["radio","checkbox"],function(){f.valHooks[this]=f.extend(f.valHooks[this],{set:function(a,b){if(f.isArray(b))return a.checked=f.inArray(f(a).val(),b)>=0}})});var z=/^(?:textarea|input|select)$/i,A=/^([^\.]*)?(?:\.(.+))?$/,B=/\bhover(\.\S+)?\b/,C=/^key/,D=/^(?:mouse|contextmenu)|click/,E=/^(?:focusinfocus|focusoutblur)$/,F=/^(\w*)(?:#([\w\-]+))?(?:\.([\w\-]+))?$/,G=function(a){var b=F.exec(a);b&&(b[1]=(b[1]||"").toLowerCase(),b[3]=b[3]&&new RegExp("(?:^|\\s)"+b[3]+"(?:\\s|$)"));return b},H=function(a,b){var c=a.attributes||{};return(!b[1]||a.nodeName.toLowerCase()===b[1])&&(!b[2]||(c.id||{}).value===b[2])&&(!b[3]||b[3].test((c["class"]||{}).value))},I=function(a){return f.event.special.hover?a:a.replace(B,"mouseenter$1 mouseleave$1")};\r
+f.event={add:function(a,c,d,e,g){var h,i,j,k,l,m,n,o,p,q,r,s;if(!(a.nodeType===3||a.nodeType===8||!c||!d||!(h=f._data(a)))){d.handler&&(p=d,d=p.handler),d.guid||(d.guid=f.guid++),j=h.events,j||(h.events=j={}),i=h.handle,i||(h.handle=i=function(a){return typeof f!="undefined"&&(!a||f.event.triggered!==a.type)?f.event.dispatch.apply(i.elem,arguments):b},i.elem=a),c=f.trim(I(c)).split(" ");for(k=0;k<c.length;k++){l=A.exec(c[k])||[],m=l[1],n=(l[2]||"").split(".").sort(),s=f.event.special[m]||{},m=(g?s.delegateType:s.bindType)||m,s=f.event.special[m]||{},o=f.extend({type:m,origType:l[1],data:e,handler:d,guid:d.guid,selector:g,quick:G(g),namespace:n.join(".")},p),r=j[m];if(!r){r=j[m]=[],r.delegateCount=0;if(!s.setup||s.setup.call(a,e,n,i)===!1)a.addEventListener?a.addEventListener(m,i,!1):a.attachEvent&&a.attachEvent("on"+m,i)}s.add&&(s.add.call(a,o),o.handler.guid||(o.handler.guid=d.guid)),g?r.splice(r.delegateCount++,0,o):r.push(o),f.event.global[m]=!0}a=null}},global:{},remove:function(a,b,c,d,e){var g=f.hasData(a)&&f._data(a),h,i,j,k,l,m,n,o,p,q,r,s;if(!!g&&!!(o=g.events)){b=f.trim(I(b||"")).split(" ");for(h=0;h<b.length;h++){i=A.exec(b[h])||[],j=k=i[1],l=i[2];if(!j){for(j in o)f.event.remove(a,j+b[h],c,d,!0);continue}p=f.event.special[j]||{},j=(d?p.delegateType:p.bindType)||j,r=o[j]||[],m=r.length,l=l?new RegExp("(^|\\.)"+l.split(".").sort().join("\\.(?:.*\\.)?")+"(\\.|$)"):null;for(n=0;n<r.length;n++)s=r[n],(e||k===s.origType)&&(!c||c.guid===s.guid)&&(!l||l.test(s.namespace))&&(!d||d===s.selector||d==="**"&&s.selector)&&(r.splice(n--,1),s.selector&&r.delegateCount--,p.remove&&p.remove.call(a,s));r.length===0&&m!==r.length&&((!p.teardown||p.teardown.call(a,l)===!1)&&f.removeEvent(a,j,g.handle),delete o[j])}f.isEmptyObject(o)&&(q=g.handle,q&&(q.elem=null),f.removeData(a,["events","handle"],!0))}},customEvent:{getData:!0,setData:!0,changeData:!0},trigger:function(c,d,e,g){if(!e||e.nodeType!==3&&e.nodeType!==8){var h=c.type||c,i=[],j,k,l,m,n,o,p,q,r,s;if(E.test(h+f.event.triggered))return;h.indexOf("!")>=0&&(h=h.slice(0,-1),k=!0),h.indexOf(".")>=0&&(i=h.split("."),h=i.shift(),i.sort());if((!e||f.event.customEvent[h])&&!f.event.global[h])return;c=typeof c=="object"?c[f.expando]?c:new f.Event(h,c):new f.Event(h),c.type=h,c.isTrigger=!0,c.exclusive=k,c.namespace=i.join("."),c.namespace_re=c.namespace?new RegExp("(^|\\.)"+i.join("\\.(?:.*\\.)?")+"(\\.|$)"):null,o=h.indexOf(":")<0?"on"+h:"";if(!e){j=f.cache;for(l in j)j[l].events&&j[l].events[h]&&f.event.trigger(c,d,j[l].handle.elem,!0);return}c.result=b,c.target||(c.target=e),d=d!=null?f.makeArray(d):[],d.unshift(c),p=f.event.special[h]||{};if(p.trigger&&p.trigger.apply(e,d)===!1)return;r=[[e,p.bindType||h]];if(!g&&!p.noBubble&&!f.isWindow(e)){s=p.delegateType||h,m=E.test(s+h)?e:e.parentNode,n=null;for(;m;m=m.parentNode)r.push([m,s]),n=m;n&&n===e.ownerDocument&&r.push([n.defaultView||n.parentWindow||a,s])}for(l=0;l<r.length&&!c.isPropagationStopped();l++)m=r[l][0],c.type=r[l][1],q=(f._data(m,"events")||{})[c.type]&&f._data(m,"handle"),q&&q.apply(m,d),q=o&&m[o],q&&f.acceptData(m)&&q.apply(m,d)===!1&&c.preventDefault();c.type=h,!g&&!c.isDefaultPrevented()&&(!p._default||p._default.apply(e.ownerDocument,d)===!1)&&(h!=="click"||!f.nodeName(e,"a"))&&f.acceptData(e)&&o&&e[h]&&(h!=="focus"&&h!=="blur"||c.target.offsetWidth!==0)&&!f.isWindow(e)&&(n=e[o],n&&(e[o]=null),f.event.triggered=h,e[h](),f.event.triggered=b,n&&(e[o]=n));return c.result}},dispatch:function(c){c=f.event.fix(c||a.event);var d=(f._data(this,"events")||{})[c.type]||[],e=d.delegateCount,g=[].slice.call(arguments,0),h=!c.exclusive&&!c.namespace,i=[],j,k,l,m,n,o,p,q,r,s,t;g[0]=c,c.delegateTarget=this;if(e&&!c.target.disabled&&(!c.button||c.type!=="click")){m=f(this),m.context=this.ownerDocument||this;for(l=c.target;l!=this;l=l.parentNode||this){o={},q=[],m[0]=l;for(j=0;j<e;j++)r=d[j],s=r.selector,o[s]===b&&(o[s]=r.quick?H(l,r.quick):m.is(s)),o[s]&&q.push(r);q.length&&i.push({elem:l,matches:q})}}d.length>e&&i.push({elem:this,matches:d.slice(e)});for(j=0;j<i.length&&!c.isPropagationStopped();j++){p=i[j],c.currentTarget=p.elem;for(k=0;k<p.matches.length&&!c.isImmediatePropagationStopped();k++){r=p.matches[k];if(h||!c.namespace&&!r.namespace||c.namespace_re&&c.namespace_re.test(r.namespace))c.data=r.data,c.handleObj=r,n=((f.event.special[r.origType]||{}).handle||r.handler).apply(p.elem,g),n!==b&&(c.result=n,n===!1&&(c.preventDefault(),c.stopPropagation()))}}return c.result},props:"attrChange attrName relatedNode srcElement altKey bubbles cancelable ctrlKey currentTarget eventPhase metaKey relatedTarget shiftKey target timeStamp view which".split(" "),fixHooks:{},keyHooks:{props:"char charCode key keyCode".split(" "),filter:function(a,b){a.which==null&&(a.which=b.charCode!=null?b.charCode:b.keyCode);return a}},mouseHooks:{props:"button buttons clientX clientY fromElement offsetX offsetY pageX pageY screenX screenY toElement".split(" "),filter:function(a,d){var e,f,g,h=d.button,i=d.fromElement;a.pageX==null&&d.clientX!=null&&(e=a.target.ownerDocument||c,f=e.documentElement,g=e.body,a.pageX=d.clientX+(f&&f.scrollLeft||g&&g.scrollLeft||0)-(f&&f.clientLeft||g&&g.clientLeft||0),a.pageY=d.clientY+(f&&f.scrollTop||g&&g.scrollTop||0)-(f&&f.clientTop||g&&g.clientTop||0)),!a.relatedTarget&&i&&(a.relatedTarget=i===a.target?d.toElement:i),!a.which&&h!==b&&(a.which=h&1?1:h&2?3:h&4?2:0);return a}},fix:function(a){if(a[f.expando])return a;var d,e,g=a,h=f.event.fixHooks[a.type]||{},i=h.props?this.props.concat(h.props):this.props;a=f.Event(g);for(d=i.length;d;)e=i[--d],a[e]=g[e];a.target||(a.target=g.srcElement||c),a.target.nodeType===3&&(a.target=a.target.parentNode),a.metaKey===b&&(a.metaKey=a.ctrlKey);return h.filter?h.filter(a,g):a},special:{ready:{setup:f.bindReady},load:{noBubble:!0},focus:{delegateType:"focusin"},blur:{delegateType:"focusout"},beforeunload:{setup:function(a,b,c){f.isWindow(this)&&(this.onbeforeunload=c)},teardown:function(a,b){this.onbeforeunload===b&&(this.onbeforeunload=null)}}},simulate:function(a,b,c,d){var e=f.extend(new f.Event,c,{type:a,isSimulated:!0,originalEvent:{}});d?f.event.trigger(e,null,b):f.event.dispatch.call(b,e),e.isDefaultPrevented()&&c.preventDefault()}},f.event.handle=f.event.dispatch,f.removeEvent=c.removeEventListener?function(a,b,c){a.removeEventListener&&a.removeEventListener(b,c,!1)}:function(a,b,c){a.detachEvent&&a.detachEvent("on"+b,c)},f.Event=function(a,b){if(!(this instanceof f.Event))return new f.Event(a,b);a&&a.type?(this.originalEvent=a,this.type=a.type,this.isDefaultPrevented=a.defaultPrevented||a.returnValue===!1||a.getPreventDefault&&a.getPreventDefault()?K:J):this.type=a,b&&f.extend(this,b),this.timeStamp=a&&a.timeStamp||f.now(),this[f.expando]=!0},f.Event.prototype={preventDefault:function(){this.isDefaultPrevented=K;var a=this.originalEvent;!a||(a.preventDefault?a.preventDefault():a.returnValue=!1)},stopPropagation:function(){this.isPropagationStopped=K;var a=this.originalEvent;!a||(a.stopPropagation&&a.stopPropagation(),a.cancelBubble=!0)},stopImmediatePropagation:function(){this.isImmediatePropagationStopped=K,this.stopPropagation()},isDefaultPrevented:J,isPropagationStopped:J,isImmediatePropagationStopped:J},f.each({mouseenter:"mouseover",mouseleave:"mouseout"},function(a,b){f.event.special[a]={delegateType:b,bindType:b,handle:function(a){var c=this,d=a.relatedTarget,e=a.handleObj,g=e.selector,h;if(!d||d!==c&&!f.contains(c,d))a.type=e.origType,h=e.handler.apply(this,arguments),a.type=b;return h}}}),f.support.submitBubbles||(f.event.special.submit={setup:function(){if(f.nodeName(this,"form"))return!1;f.event.add(this,"click._submit keypress._submit",function(a){var c=a.target,d=f.nodeName(c,"input")||f.nodeName(c,"button")?c.form:b;d&&!d._submit_attached&&(f.event.add(d,"submit._submit",function(a){this.parentNode&&!a.isTrigger&&f.event.simulate("submit",this.parentNode,a,!0)}),d._submit_attached=!0)})},teardown:function(){if(f.nodeName(this,"form"))return!1;f.event.remove(this,"._submit")}}),f.support.changeBubbles||(f.event.special.change={setup:function(){if(z.test(this.nodeName)){if(this.type==="checkbox"||this.type==="radio")f.event.add(this,"propertychange._change",function(a){a.originalEvent.propertyName==="checked"&&(this._just_changed=!0)}),f.event.add(this,"click._change",function(a){this._just_changed&&!a.isTrigger&&(this._just_changed=!1,f.event.simulate("change",this,a,!0))});return!1}f.event.add(this,"beforeactivate._change",function(a){var b=a.target;z.test(b.nodeName)&&!b._change_attached&&(f.event.add(b,"change._change",function(a){this.parentNode&&!a.isSimulated&&!a.isTrigger&&f.event.simulate("change",this.parentNode,a,!0)}),b._change_attached=!0)})},handle:function(a){var b=a.target;if(this!==b||a.isSimulated||a.isTrigger||b.type!=="radio"&&b.type!=="checkbox")return a.handleObj.handler.apply(this,arguments)},teardown:function(){f.event.remove(this,"._change");return z.test(this.nodeName)}}),f.support.focusinBubbles||f.each({focus:"focusin",blur:"focusout"},function(a,b){var d=0,e=function(a){f.event.simulate(b,a.target,f.event.fix(a),!0)};f.event.special[b]={setup:function(){d++===0&&c.addEventListener(a,e,!0)},teardown:function(){--d===0&&c.removeEventListener(a,e,!0)}}}),f.fn.extend({on:function(a,c,d,e,g){var h,i;if(typeof a=="object"){typeof c!="string"&&(d=c,c=b);for(i in a)this.on(i,c,d,a[i],g);return this}d==null&&e==null?(e=c,d=c=b):e==null&&(typeof c=="string"?(e=d,d=b):(e=d,d=c,c=b));if(e===!1)e=J;else if(!e)return this;g===1&&(h=e,e=function(a){f().off(a);return h.apply(this,arguments)},e.guid=h.guid||(h.guid=f.guid++));return this.each(function(){f.event.add(this,a,e,d,c)})},one:function(a,b,c,d){return this.on.call(this,a,b,c,d,1)},off:function(a,c,d){if(a&&a.preventDefault&&a.handleObj){var e=a.handleObj;f(a.delegateTarget).off(e.namespace?e.type+"."+e.namespace:e.type,e.selector,e.handler);return this}if(typeof a=="object"){for(var g in a)this.off(g,c,a[g]);return this}if(c===!1||typeof c=="function")d=c,c=b;d===!1&&(d=J);return this.each(function(){f.event.remove(this,a,d,c)})},bind:function(a,b,c){return this.on(a,null,b,c)},unbind:function(a,b){return this.off(a,null,b)},live:function(a,b,c){f(this.context).on(a,this.selector,b,c);return this},die:function(a,b){f(this.context).off(a,this.selector||"**",b);return this},delegate:function(a,b,c,d){return this.on(b,a,c,d)},undelegate:function(a,b,c){return arguments.length==1?this.off(a,"**"):this.off(b,a,c)},trigger:function(a,b){return this.each(function(){f.event.trigger(a,b,this)})},triggerHandler:function(a,b){if(this[0])return f.event.trigger(a,b,this[0],!0)},toggle:function(a){var b=arguments,c=a.guid||f.guid++,d=0,e=function(c){var e=(f._data(this,"lastToggle"+a.guid)||0)%d;f._data(this,"lastToggle"+a.guid,e+1),c.preventDefault();return b[e].apply(this,arguments)||!1};e.guid=c;while(d<b.length)b[d++].guid=c;return this.click(e)},hover:function(a,b){return this.mouseenter(a).mouseleave(b||a)}}),f.each("blur focus focusin focusout load resize scroll unload click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select submit keydown keypress keyup error contextmenu".split(" "),function(a,b){f.fn[b]=function(a,c){c==null&&(c=a,a=null);return arguments.length>0?this.on(b,null,a,c):this.trigger(b)},f.attrFn&&(f.attrFn[b]=!0),C.test(b)&&(f.event.fixHooks[b]=f.event.keyHooks),D.test(b)&&(f.event.fixHooks[b]=f.event.mouseHooks)}),function(){function x(a,b,c,e,f,g){for(var h=0,i=e.length;h<i;h++){var j=e[h];if(j){var k=!1;j=j[a];while(j){if(j[d]===c){k=e[j.sizset];break}if(j.nodeType===1){g||(j[d]=c,j.sizset=h);if(typeof b!="string"){if(j===b){k=!0;break}}else if(m.filter(b,[j]).length>0){k=j;break}}j=j[a]}e[h]=k}}}function w(a,b,c,e,f,g){for(var h=0,i=e.length;h<i;h++){var j=e[h];if(j){var k=!1;j=j[a];while(j){if(j[d]===c){k=e[j.sizset];break}j.nodeType===1&&!g&&(j[d]=c,j.sizset=h);if(j.nodeName.toLowerCase()===b){k=j;break}j=j[a]}e[h]=k}}}var a=/((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^\[\]]*\]|['"][^'"]*['"]|[^\[\]'"]+)+\]|\\.|[^ >+~,(\[\\]+)+|[>+~])(\s*,\s*)?((?:.|\r|\n)*)/g,d="sizcache"+(Math.random()+"").replace(".",""),e=0,g=Object.prototype.toString,h=!1,i=!0,j=/\\/g,k=/\r\n/g,l=/\W/;[0,0].sort(function(){i=!1;return 0});var m=function(b,d,e,f){e=e||[],d=d||c;var h=d;if(d.nodeType!==1&&d.nodeType!==9)return[];if(!b||typeof b!="string")return e;var i,j,k,l,n,q,r,t,u=!0,v=m.isXML(d),w=[],x=b;do{a.exec(""),i=a.exec(x);if(i){x=i[3],w.push(i[1]);if(i[2]){l=i[3];break}}}while(i);if(w.length>1&&p.exec(b))if(w.length===2&&o.relative[w[0]])j=y(w[0]+w[1],d,f);else{j=o.relative[w[0]]?[d]:m(w.shift(),d);while(w.length)b=w.shift(),o.relative[b]&&(b+=w.shift()),j=y(b,j,f)}else{!f&&w.length>1&&d.nodeType===9&&!v&&o.match.ID.test(w[0])&&!o.match.ID.test(w[w.length-1])&&(n=m.find(w.shift(),d,v),d=n.expr?m.filter(n.expr,n.set)[0]:n.set[0]);if(d){n=f?{expr:w.pop(),set:s(f)}:m.find(w.pop(),w.length===1&&(w[0]==="~"||w[0]==="+")&&d.parentNode?d.parentNode:d,v),j=n.expr?m.filter(n.expr,n.set):n.set,w.length>0?k=s(j):u=!1;while(w.length)q=w.pop(),r=q,o.relative[q]?r=w.pop():q="",r==null&&(r=d),o.relative[q](k,r,v)}else k=w=[]}k||(k=j),k||m.error(q||b);if(g.call(k)==="[object Array]")if(!u)e.push.apply(e,k);else if(d&&d.nodeType===1)for(t=0;k[t]!=null;t++)k[t]&&(k[t]===!0||k[t].nodeType===1&&m.contains(d,k[t]))&&e.push(j[t]);else for(t=0;k[t]!=null;t++)k[t]&&k[t].nodeType===1&&e.push(j[t]);else s(k,e);l&&(m(l,h,e,f),m.uniqueSort(e));return e};m.uniqueSort=function(a){if(u){h=i,a.sort(u);if(h)for(var b=1;b<a.length;b++)a[b]===a[b-1]&&a.splice(b--,1)}return a},m.matches=function(a,b){return m(a,null,null,b)},m.matchesSelector=function(a,b){return m(b,null,null,[a]).length>0},m.find=function(a,b,c){var d,e,f,g,h,i;if(!a)return[];for(e=0,f=o.order.length;e<f;e++){h=o.order[e];if(g=o.leftMatch[h].exec(a)){i=g[1],g.splice(1,1);if(i.substr(i.length-1)!=="\\"){g[1]=(g[1]||"").replace(j,""),d=o.find[h](g,b,c);if(d!=null){a=a.replace(o.match[h],"");break}}}}d||(d=typeof b.getElementsByTagName!="undefined"?b.getElementsByTagName("*"):[]);return{set:d,expr:a}},m.filter=function(a,c,d,e){var f,g,h,i,j,k,l,n,p,q=a,r=[],s=c,t=c&&c[0]&&m.isXML(c[0]);while(a&&c.length){for(h in o.filter)if((f=o.leftMatch[h].exec(a))!=null&&f[2]){k=o.filter[h],l=f[1],g=!1,f.splice(1,1);if(l.substr(l.length-1)==="\\")continue;s===r&&(r=[]);if(o.preFilter[h]){f=o.preFilter[h](f,s,d,r,e,t);if(!f)g=i=!0;else if(f===!0)continue}if(f)for(n=0;(j=s[n])!=null;n++)j&&(i=k(j,f,n,s),p=e^i,d&&i!=null?p?g=!0:s[n]=!1:p&&(r.push(j),g=!0));if(i!==b){d||(s=r),a=a.replace(o.match[h],"");if(!g)return[];break}}if(a===q)if(g==null)m.error(a);else break;q=a}return s},m.error=function(a){throw new Error("Syntax error, unrecognized expression: "+a)};var n=m.getText=function(a){var b,c,d=a.nodeType,e="";if(d){if(d===1||d===9){if(typeof a.textContent=="string")return a.textContent;if(typeof a.innerText=="string")return a.innerText.replace(k,"");for(a=a.firstChild;a;a=a.nextSibling)e+=n(a)}else if(d===3||d===4)return a.nodeValue}else for(b=0;c=a[b];b++)c.nodeType!==8&&(e+=n(c));return e},o=m.selectors={order:["ID","NAME","TAG"],match:{ID:/#((?:[\w\u00c0-\uFFFF\-]|\\.)+)/,CLASS:/\.((?:[\w\u00c0-\uFFFF\-]|\\.)+)/,NAME:/\[name=['"]*((?:[\w\u00c0-\uFFFF\-]|\\.)+)['"]*\]/,ATTR:/\[\s*((?:[\w\u00c0-\uFFFF\-]|\\.)+)\s*(?:(\S?=)\s*(?:(['"])(.*?)\3|(#?(?:[\w\u00c0-\uFFFF\-]|\\.)*)|)|)\s*\]/,TAG:/^((?:[\w\u00c0-\uFFFF\*\-]|\\.)+)/,CHILD:/:(only|nth|last|first)-child(?:\(\s*(even|odd|(?:[+\-]?\d+|(?:[+\-]?\d*)?n\s*(?:[+\-]\s*\d+)?))\s*\))?/,POS:/:(nth|eq|gt|lt|first|last|even|odd)(?:\((\d*)\))?(?=[^\-]|$)/,PSEUDO:/:((?:[\w\u00c0-\uFFFF\-]|\\.)+)(?:\((['"]?)((?:\([^\)]+\)|[^\(\)]*)+)\2\))?/},leftMatch:{},attrMap:{"class":"className","for":"htmlFor"},attrHandle:{href:function(a){return a.getAttribute("href")},type:function(a){return a.getAttribute("type")}},relative:{"+":function(a,b){var c=typeof b=="string",d=c&&!l.test(b),e=c&&!d;d&&(b=b.toLowerCase());for(var f=0,g=a.length,h;f<g;f++)if(h=a[f]){while((h=h.previousSibling)&&h.nodeType!==1);a[f]=e||h&&h.nodeName.toLowerCase()===b?h||!1:h===b}e&&m.filter(b,a,!0)},">":function(a,b){var c,d=typeof b=="string",e=0,f=a.length;if(d&&!l.test(b)){b=b.toLowerCase();for(;e<f;e++){c=a[e];if(c){var g=c.parentNode;a[e]=g.nodeName.toLowerCase()===b?g:!1}}}else{for(;e<f;e++)c=a[e],c&&(a[e]=d?c.parentNode:c.parentNode===b);d&&m.filter(b,a,!0)}},"":function(a,b,c){var d,f=e++,g=x;typeof b=="string"&&!l.test(b)&&(b=b.toLowerCase(),d=b,g=w),g("parentNode",b,f,a,d,c)},"~":function(a,b,c){var d,f=e++,g=x;typeof b=="string"&&!l.test(b)&&(b=b.toLowerCase(),d=b,g=w),g("previousSibling",b,f,a,d,c)}},find:{ID:function(a,b,c){if(typeof b.getElementById!="undefined"&&!c){var d=b.getElementById(a[1]);return d&&d.parentNode?[d]:[]}},NAME:function(a,b){if(typeof b.getElementsByName!="undefined"){var c=[],d=b.getElementsByName(a[1]);for(var e=0,f=d.length;e<f;e++)d[e].getAttribute("name")===a[1]&&c.push(d[e]);return c.length===0?null:c}},TAG:function(a,b){if(typeof b.getElementsByTagName!="undefined")return b.getElementsByTagName(a[1])}},preFilter:{CLASS:function(a,b,c,d,e,f){a=" "+a[1].replace(j,"")+" ";if(f)return a;for(var g=0,h;(h=b[g])!=null;g++)h&&(e^(h.className&&(" "+h.className+" ").replace(/[\t\n\r]/g," ").indexOf(a)>=0)?c||d.push(h):c&&(b[g]=!1));return!1},ID:function(a){return a[1].replace(j,"")},TAG:function(a,b){return a[1].replace(j,"").toLowerCase()},CHILD:function(a){if(a[1]==="nth"){a[2]||m.error(a[0]),a[2]=a[2].replace(/^\+|\s*/g,"");var b=/(-?)(\d*)(?:n([+\-]?\d*))?/.exec(a[2]==="even"&&"2n"||a[2]==="odd"&&"2n+1"||!/\D/.test(a[2])&&"0n+"+a[2]||a[2]);a[2]=b[1]+(b[2]||1)-0,a[3]=b[3]-0}else a[2]&&m.error(a[0]);a[0]=e++;return a},ATTR:function(a,b,c,d,e,f){var g=a[1]=a[1].replace(j,"");!f&&o.attrMap[g]&&(a[1]=o.attrMap[g]),a[4]=(a[4]||a[5]||"").replace(j,""),a[2]==="~="&&(a[4]=" "+a[4]+" ");return a},PSEUDO:function(b,c,d,e,f){if(b[1]==="not")if((a.exec(b[3])||"").length>1||/^\w/.test(b[3]))b[3]=m(b[3],null,null,c);else{var g=m.filter(b[3],c,d,!0^f);d||e.push.apply(e,g);return!1}else if(o.match.POS.test(b[0])||o.match.CHILD.test(b[0]))return!0;return b},POS:function(a){a.unshift(!0);return a}},filters:{enabled:function(a){return a.disabled===!1&&a.type!=="hidden"},disabled:function(a){return a.disabled===!0},checked:function(a){return a.checked===!0},selected:function(a){a.parentNode&&a.parentNode.selectedIndex;return a.selected===!0},parent:function(a){return!!a.firstChild},empty:function(a){return!a.firstChild},has:function(a,b,c){return!!m(c[3],a).length},header:function(a){return/h\d/i.test(a.nodeName)},text:function(a){var b=a.getAttribute("type"),c=a.type;return a.nodeName.toLowerCase()==="input"&&"text"===c&&(b===c||b===null)},radio:function(a){return a.nodeName.toLowerCase()==="input"&&"radio"===a.type},checkbox:function(a){return a.nodeName.toLowerCase()==="input"&&"checkbox"===a.type},file:function(a){return a.nodeName.toLowerCase()==="input"&&"file"===a.type},password:function(a){return a.nodeName.toLowerCase()==="input"&&"password"===a.type},submit:function(a){var b=a.nodeName.toLowerCase();return(b==="input"||b==="button")&&"submit"===a.type},image:function(a){return a.nodeName.toLowerCase()==="input"&&"image"===a.type},reset:function(a){var b=a.nodeName.toLowerCase();return(b==="input"||b==="button")&&"reset"===a.type},button:function(a){var b=a.nodeName.toLowerCase();return b==="input"&&"button"===a.type||b==="button"},input:function(a){return/input|select|textarea|button/i.test(a.nodeName)},focus:function(a){return a===a.ownerDocument.activeElement}},setFilters:{first:function(a,b){return b===0},last:function(a,b,c,d){return b===d.length-1},even:function(a,b){return b%2===0},odd:function(a,b){return b%2===1},lt:function(a,b,c){return b<c[3]-0},gt:function(a,b,c){return b>c[3]-0},nth:function(a,b,c){return c[3]-0===b},eq:function(a,b,c){return c[3]-0===b}},filter:{PSEUDO:function(a,b,c,d){var e=b[1],f=o.filters[e];if(f)return f(a,c,b,d);if(e==="contains")return(a.textContent||a.innerText||n([a])||"").indexOf(b[3])>=0;if(e==="not"){var g=b[3];for(var h=0,i=g.length;h<i;h++)if(g[h]===a)return!1;return!0}m.error(e)},CHILD:function(a,b){var c,e,f,g,h,i,j,k=b[1],l=a;switch(k){case"only":case"first":while(l=l.previousSibling)if(l.nodeType===1)return!1;if(k==="first")return!0;l=a;case"last":while(l=l.nextSibling)if(l.nodeType===1)return!1;return!0;case"nth":c=b[2],e=b[3];if(c===1&&e===0)return!0;f=b[0],g=a.parentNode;if(g&&(g[d]!==f||!a.nodeIndex)){i=0;for(l=g.firstChild;l;l=l.nextSibling)l.nodeType===1&&(l.nodeIndex=++i);g[d]=f}j=a.nodeIndex-e;return c===0?j===0:j%c===0&&j/c>=0}},ID:function(a,b){return a.nodeType===1&&a.getAttribute("id")===b},TAG:function(a,b){return b==="*"&&a.nodeType===1||!!a.nodeName&&a.nodeName.toLowerCase()===b},CLASS:function(a,b){return(" "+(a.className||a.getAttribute("class"))+" ").indexOf(b)>-1},ATTR:function(a,b){var c=b[1],d=m.attr?m.attr(a,c):o.attrHandle[c]?o.attrHandle[c](a):a[c]!=null?a[c]:a.getAttribute(c),e=d+"",f=b[2],g=b[4];return d==null?f==="!=":!f&&m.attr?d!=null:f==="="?e===g:f==="*="?e.indexOf(g)>=0:f==="~="?(" "+e+" ").indexOf(g)>=0:g?f==="!="?e!==g:f==="^="?e.indexOf(g)===0:f==="$="?e.substr(e.length-g.length)===g:f==="|="?e===g||e.substr(0,g.length+1)===g+"-":!1:e&&d!==!1},POS:function(a,b,c,d){var e=b[2],f=o.setFilters[e];if(f)return f(a,c,b,d)}}},p=o.match.POS,q=function(a,b){return"\\"+(b-0+1)};for(var r in o.match)o.match[r]=new RegExp(o.match[r].source+/(?![^\[]*\])(?![^\(]*\))/.source),o.leftMatch[r]=new RegExp(/(^(?:.|\r|\n)*?)/.source+o.match[r].source.replace(/\\(\d+)/g,q));var s=function(a,b){a=Array.prototype.slice.call(a,0);if(b){b.push.apply(b,a);return b}return a};try{Array.prototype.slice.call(c.documentElement.childNodes,0)[0].nodeType}catch(t){s=function(a,b){var c=0,d=b||[];if(g.call(a)==="[object Array]")Array.prototype.push.apply(d,a);else if(typeof a.length=="number")for(var e=a.length;c<e;c++)d.push(a[c]);else for(;a[c];c++)d.push(a[c]);return d}}var u,v;c.documentElement.compareDocumentPosition?u=function(a,b){if(a===b){h=!0;return 0}if(!a.compareDocumentPosition||!b.compareDocumentPosition)return a.compareDocumentPosition?-1:1;return a.compareDocumentPosition(b)&4?-1:1}:(u=function(a,b){if(a===b){h=!0;return 0}if(a.sourceIndex&&b.sourceIndex)return a.sourceIndex-b.sourceIndex;var c,d,e=[],f=[],g=a.parentNode,i=b.parentNode,j=g;if(g===i)return v(a,b);if(!g)return-1;if(!i)return 1;while(j)e.unshift(j),j=j.parentNode;j=i;while(j)f.unshift(j),j=j.parentNode;c=e.length,d=f.length;for(var k=0;k<c&&k<d;k++)if(e[k]!==f[k])return v(e[k],f[k]);return k===c?v(a,f[k],-1):v(e[k],b,1)},v=function(a,b,c){if(a===b)return c;var d=a.nextSibling;while(d){if(d===b)return-1;d=d.nextSibling}return 1}),function(){var a=c.createElement("div"),d="script"+(new Date).getTime(),e=c.documentElement;a.innerHTML="<a name='"+d+"'/>",e.insertBefore(a,e.firstChild),c.getElementById(d)&&(o.find.ID=function(a,c,d){if(typeof c.getElementById!="undefined"&&!d){var e=c.getElementById(a[1]);return e?e.id===a[1]||typeof e.getAttributeNode!="undefined"&&e.getAttributeNode("id").nodeValue===a[1]?[e]:b:[]}},o.filter.ID=function(a,b){var c=typeof a.getAttributeNode!="undefined"&&a.getAttributeNode("id");return a.nodeType===1&&c&&c.nodeValue===b}),e.removeChild(a),e=a=null}(),function(){var a=c.createElement("div");a.appendChild(c.createComment("")),a.getElementsByTagName("*").length>0&&(o.find.TAG=function(a,b){var c=b.getElementsByTagName(a[1]);if(a[1]==="*"){var d=[];for(var e=0;c[e];e++)c[e].nodeType===1&&d.push(c[e]);c=d}return c}),a.innerHTML="<a href='#'></a>",a.firstChild&&typeof a.firstChild.getAttribute!="undefined"&&a.firstChild.getAttribute("href")!=="#"&&(o.attrHandle.href=function(a){return a.getAttribute("href",2)}),a=null}(),c.querySelectorAll&&function(){var a=m,b=c.createElement("div"),d="__sizzle__";b.innerHTML="<p class='TEST'></p>";if(!b.querySelectorAll||b.querySelectorAll(".TEST").length!==0){m=function(b,e,f,g){e=e||c;if(!g&&!m.isXML(e)){var h=/^(\w+$)|^\.([\w\-]+$)|^#([\w\-]+$)/.exec(b);if(h&&(e.nodeType===1||e.nodeType===9)){if(h[1])return s(e.getElementsByTagName(b),f);if(h[2]&&o.find.CLASS&&e.getElementsByClassName)return s(e.getElementsByClassName(h[2]),f)}if(e.nodeType===9){if(b==="body"&&e.body)return s([e.body],f);if(h&&h[3]){var i=e.getElementById(h[3]);if(!i||!i.parentNode)return s([],f);if(i.id===h[3])return s([i],f)}try{return s(e.querySelectorAll(b),f)}catch(j){}}else if(e.nodeType===1&&e.nodeName.toLowerCase()!=="object"){var k=e,l=e.getAttribute("id"),n=l||d,p=e.parentNode,q=/^\s*[+~]/.test(b);l?n=n.replace(/'/g,"\\$&"):e.setAttribute("id",n),q&&p&&(e=e.parentNode);try{if(!q||p)return s(e.querySelectorAll("[id='"+n+"'] "+b),f)}catch(r){}finally{l||k.removeAttribute("id")}}}return a(b,e,f,g)};for(var e in a)m[e]=a[e];b=null}}(),function(){var a=c.documentElement,b=a.matchesSelector||a.mozMatchesSelector||a.webkitMatchesSelector||a.msMatchesSelector;if(b){var d=!b.call(c.createElement("div"),"div"),e=!1;try{b.call(c.documentElement,"[test!='']:sizzle")}catch(f){e=!0}m.matchesSelector=function(a,c){c=c.replace(/\=\s*([^'"\]]*)\s*\]/g,"='$1']");if(!m.isXML(a))try{if(e||!o.match.PSEUDO.test(c)&&!/!=/.test(c)){var f=b.call(a,c);if(f||!d||a.document&&a.document.nodeType!==11)return f}}catch(g){}return m(c,null,null,[a]).length>0}}}(),function(){var a=c.createElement("div");a.innerHTML="<div class='test e'></div><div class='test'></div>";if(!!a.getElementsByClassName&&a.getElementsByClassName("e").length!==0){a.lastChild.className="e";if(a.getElementsByClassName("e").length===1)return;o.order.splice(1,0,"CLASS"),o.find.CLASS=function(a,b,c){if(typeof b.getElementsByClassName!="undefined"&&!c)return b.getElementsByClassName(a[1])},a=null}}(),c.documentElement.contains?m.contains=function(a,b){return a!==b&&(a.contains?a.contains(b):!0)}:c.documentElement.compareDocumentPosition?m.contains=function(a,b){return!!(a.compareDocumentPosition(b)&16)}:m.contains=function(){return!1},m.isXML=function(a){var b=(a?a.ownerDocument||a:0).documentElement;return b?b.nodeName!=="HTML":!1};var y=function(a,b,c){var d,e=[],f="",g=b.nodeType?[b]:b;while(d=o.match.PSEUDO.exec(a))f+=d[0],a=a.replace(o.match.PSEUDO,"");a=o.relative[a]?a+"*":a;for(var h=0,i=g.length;h<i;h++)m(a,g[h],e,c);return m.filter(f,e)};m.attr=f.attr,m.selectors.attrMap={},f.find=m,f.expr=m.selectors,f.expr[":"]=f.expr.filters,f.unique=m.uniqueSort,f.text=m.getText,f.isXMLDoc=m.isXML,f.contains=m.contains}();var L=/Until$/,M=/^(?:parents|prevUntil|prevAll)/,N=/,/,O=/^.[^:#\[\.,]*$/,P=Array.prototype.slice,Q=f.expr.match.POS,R={children:!0,contents:!0,next:!0,prev:!0};f.fn.extend({find:function(a){var b=this,c,d;if(typeof a!="string")return f(a).filter(function(){for(c=0,d=b.length;c<d;c++)if(f.contains(b[c],this))return!0});var e=this.pushStack("","find",a),g,h,i;for(c=0,d=this.length;c<d;c++){g=e.length,f.find(a,this[c],e);if(c>0)for(h=g;h<e.length;h++)for(i=0;i<g;i++)if(e[i]===e[h]){e.splice(h--,1);break}}return e},has:function(a){var b=f(a);return this.filter(function(){for(var a=0,c=b.length;a<c;a++)if(f.contains(this,b[a]))return!0})},not:function(a){return this.pushStack(T(this,a,!1),"not",a)},filter:function(a){return this.pushStack(T(this,a,!0),"filter",a)},is:function(a){return!!a&&(typeof a=="string"?Q.test(a)?f(a,this.context).index(this[0])>=0:f.filter(a,this).length>0:this.filter(a).length>0)},closest:function(a,b){var c=[],d,e,g=this[0];if(f.isArray(a)){var h=1;while(g&&g.ownerDocument&&g!==b){for(d=0;d<a.length;d++)f(g).is(a[d])&&c.push({selector:a[d],elem:g,level:h});g=g.parentNode,h++}return c}var i=Q.test(a)||typeof a!="string"?f(a,b||this.context):0;for(d=0,e=this.length;d<e;d++){g=this[d];while(g){if(i?i.index(g)>-1:f.find.matchesSelector(g,a)){c.push(g);break}g=g.parentNode;if(!g||!g.ownerDocument||g===b||g.nodeType===11)break}}c=c.length>1?f.unique(c):c;return this.pushStack(c,"closest",a)},index:function(a){if(!a)return this[0]&&this[0].parentNode?this.prevAll().length:-1;if(typeof a=="string")return f.inArray(this[0],f(a));return f.inArray(a.jquery?a[0]:a,this)},add:function(a,b){var c=typeof a=="string"?f(a,b):f.makeArray(a&&a.nodeType?[a]:a),d=f.merge(this.get(),c);return this.pushStack(S(c[0])||S(d[0])?d:f.unique(d))},andSelf:function(){return this.add(this.prevObject)}}),f.each({parent:function(a){var b=a.parentNode;return b&&b.nodeType!==11?b:null},parents:function(a){return f.dir(a,"parentNode")},parentsUntil:function(a,b,c){return f.dir(a,"parentNode",c)},next:function(a){return f.nth(a,2,"nextSibling")},prev:function(a){return f.nth(a,2,"previousSibling")},nextAll:function(a){return f.dir(a,"nextSibling")},prevAll:function(a){return f.dir(a,"previousSibling")},nextUntil:function(a,b,c){return f.dir(a,"nextSibling",c)},prevUntil:function(a,b,c){return f.dir(a,"previousSibling",c)},siblings:function(a){return f.sibling(a.parentNode.firstChild,a)},children:function(a){return f.sibling(a.firstChild)},contents:function(a){return f.nodeName(a,"iframe")?a.contentDocument||a.contentWindow.document:f.makeArray(a.childNodes)}},function(a,b){f.fn[a]=function(c,d){var e=f.map(this,b,c);L.test(a)||(d=c),d&&typeof d=="string"&&(e=f.filter(d,e)),e=this.length>1&&!R[a]?f.unique(e):e,(this.length>1||N.test(d))&&M.test(a)&&(e=e.reverse());return this.pushStack(e,a,P.call(arguments).join(","))}}),f.extend({filter:function(a,b,c){c&&(a=":not("+a+")");return b.length===1?f.find.matchesSelector(b[0],a)?[b[0]]:[]:f.find.matches(a,b)},dir:function(a,c,d){var e=[],g=a[c];while(g&&g.nodeType!==9&&(d===b||g.nodeType!==1||!f(g).is(d)))g.nodeType===1&&e.push(g),g=g[c];return e},nth:function(a,b,c,d){b=b||1;var e=0;for(;a;a=a[c])if(a.nodeType===1&&++e===b)break;return a},sibling:function(a,b){var c=[];for(;a;a=a.nextSibling)a.nodeType===1&&a!==b&&c.push(a);return c}});var V="abbr|article|aside|audio|canvas|datalist|details|figcaption|figure|footer|header|hgroup|mark|meter|nav|output|progress|section|summary|time|video",W=/ jQuery\d+="(?:\d+|null)"/g,X=/^\s+/,Y=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/ig,Z=/<([\w:]+)/,$=/<tbody/i,_=/<|&#?\w+;/,ba=/<(?:script|style)/i,bb=/<(?:script|object|embed|option|style)/i,bc=new RegExp("<(?:"+V+")","i"),bd=/checked\s*(?:[^=]|=\s*.checked.)/i,be=/\/(java|ecma)script/i,bf=/^\s*<!(?:\[CDATA\[|\-\-)/,bg={option:[1,"<select multiple='multiple'>","</select>"],legend:[1,"<fieldset>","</fieldset>"],thead:[1,"<table>","</table>"],tr:[2,"<table><tbody>","</tbody></table>"],td:[3,"<table><tbody><tr>","</tr></tbody></table>"],col:[2,"<table><tbody></tbody><colgroup>","</colgroup></table>"],area:[1,"<map>","</map>"],_default:[0,"",""]},bh=U(c);bg.optgroup=bg.option,bg.tbody=bg.tfoot=bg.colgroup=bg.caption=bg.thead,bg.th=bg.td,f.support.htmlSerialize||(bg._default=[1,"div<div>","</div>"]),f.fn.extend({text:function(a){if(f.isFunction(a))return this.each(function(b){var c=f(this);c.text(a.call(this,b,c.text()))});if(typeof a!="object"&&a!==b)return this.empty().append((this[0]&&this[0].ownerDocument||c).createTextNode(a));return f.text(this)},wrapAll:function(a){if(f.isFunction(a))return this.each(function(b){f(this).wrapAll(a.call(this,b))});if(this[0]){var b=f(a,this[0].ownerDocument).eq(0).clone(!0);this[0].parentNode&&b.insertBefore(this[0]),b.map(function(){var a=this;while(a.firstChild&&a.firstChild.nodeType===1)a=a.firstChild;return a}).append(this)}return this},wrapInner:function(a){if(f.isFunction(a))return this.each(function(b){f(this).wrapInner(a.call(this,b))});return this.each(function(){var b=f(this),c=b.contents();c.length?c.wrapAll(a):b.append(a)})},wrap:function(a){var b=f.isFunction(a);return this.each(function(c){f(this).wrapAll(b?a.call(this,c):a)})},unwrap:function(){return this.parent().each(function(){f.nodeName(this,"body")||f(this).replaceWith(this.childNodes)}).end()},append:function(){return this.domManip(arguments,!0,function(a){this.nodeType===1&&this.appendChild(a)})},prepend:function(){return this.domManip(arguments,!0,function(a){this.nodeType===1&&this.insertBefore(a,this.firstChild)})},before:function(){if(this[0]&&this[0].parentNode)return this.domManip(arguments,!1,function(a){this.parentNode.insertBefore(a,this)});if(arguments.length){var a=f.clean(arguments);a.push.apply(a,this.toArray());return this.pushStack(a,"before",arguments)}},after:function(){if(this[0]&&this[0].parentNode)return this.domManip(arguments,!1,function(a){this.parentNode.insertBefore(a,this.nextSibling)});if(arguments.length){var a=this.pushStack(this,"after",arguments);a.push.apply(a,f.clean(arguments));return a}},remove:function(a,b){for(var c=0,d;(d=this[c])!=null;c++)if(!a||f.filter(a,[d]).length)!b&&d.nodeType===1&&(f.cleanData(d.getElementsByTagName("*")),f.cleanData([d])),d.parentNode&&d.parentNode.removeChild(d);return this},empty:function()\r
+{for(var a=0,b;(b=this[a])!=null;a++){b.nodeType===1&&f.cleanData(b.getElementsByTagName("*"));while(b.firstChild)b.removeChild(b.firstChild)}return this},clone:function(a,b){a=a==null?!1:a,b=b==null?a:b;return this.map(function(){return f.clone(this,a,b)})},html:function(a){if(a===b)return this[0]&&this[0].nodeType===1?this[0].innerHTML.replace(W,""):null;if(typeof a=="string"&&!ba.test(a)&&(f.support.leadingWhitespace||!X.test(a))&&!bg[(Z.exec(a)||["",""])[1].toLowerCase()]){a=a.replace(Y,"<$1></$2>");try{for(var c=0,d=this.length;c<d;c++)this[c].nodeType===1&&(f.cleanData(this[c].getElementsByTagName("*")),this[c].innerHTML=a)}catch(e){this.empty().append(a)}}else f.isFunction(a)?this.each(function(b){var c=f(this);c.html(a.call(this,b,c.html()))}):this.empty().append(a);return this},replaceWith:function(a){if(this[0]&&this[0].parentNode){if(f.isFunction(a))return this.each(function(b){var c=f(this),d=c.html();c.replaceWith(a.call(this,b,d))});typeof a!="string"&&(a=f(a).detach());return this.each(function(){var b=this.nextSibling,c=this.parentNode;f(this).remove(),b?f(b).before(a):f(c).append(a)})}return this.length?this.pushStack(f(f.isFunction(a)?a():a),"replaceWith",a):this},detach:function(a){return this.remove(a,!0)},domManip:function(a,c,d){var e,g,h,i,j=a[0],k=[];if(!f.support.checkClone&&arguments.length===3&&typeof j=="string"&&bd.test(j))return this.each(function(){f(this).domManip(a,c,d,!0)});if(f.isFunction(j))return this.each(function(e){var g=f(this);a[0]=j.call(this,e,c?g.html():b),g.domManip(a,c,d)});if(this[0]){i=j&&j.parentNode,f.support.parentNode&&i&&i.nodeType===11&&i.childNodes.length===this.length?e={fragment:i}:e=f.buildFragment(a,this,k),h=e.fragment,h.childNodes.length===1?g=h=h.firstChild:g=h.firstChild;if(g){c=c&&f.nodeName(g,"tr");for(var l=0,m=this.length,n=m-1;l<m;l++)d.call(c?bi(this[l],g):this[l],e.cacheable||m>1&&l<n?f.clone(h,!0,!0):h)}k.length&&f.each(k,bp)}return this}}),f.buildFragment=function(a,b,d){var e,g,h,i,j=a[0];b&&b[0]&&(i=b[0].ownerDocument||b[0]),i.createDocumentFragment||(i=c),a.length===1&&typeof j=="string"&&j.length<512&&i===c&&j.charAt(0)==="<"&&!bb.test(j)&&(f.support.checkClone||!bd.test(j))&&(f.support.html5Clone||!bc.test(j))&&(g=!0,h=f.fragments[j],h&&h!==1&&(e=h)),e||(e=i.createDocumentFragment(),f.clean(a,i,e,d)),g&&(f.fragments[j]=h?e:1);return{fragment:e,cacheable:g}},f.fragments={},f.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(a,b){f.fn[a]=function(c){var d=[],e=f(c),g=this.length===1&&this[0].parentNode;if(g&&g.nodeType===11&&g.childNodes.length===1&&e.length===1){e[b](this[0]);return this}for(var h=0,i=e.length;h<i;h++){var j=(h>0?this.clone(!0):this).get();f(e[h])[b](j),d=d.concat(j)}return this.pushStack(d,a,e.selector)}}),f.extend({clone:function(a,b,c){var d,e,g,h=f.support.html5Clone||!bc.test("<"+a.nodeName)?a.cloneNode(!0):bo(a);if((!f.support.noCloneEvent||!f.support.noCloneChecked)&&(a.nodeType===1||a.nodeType===11)&&!f.isXMLDoc(a)){bk(a,h),d=bl(a),e=bl(h);for(g=0;d[g];++g)e[g]&&bk(d[g],e[g])}if(b){bj(a,h);if(c){d=bl(a),e=bl(h);for(g=0;d[g];++g)bj(d[g],e[g])}}d=e=null;return h},clean:function(a,b,d,e){var g;b=b||c,typeof b.createElement=="undefined"&&(b=b.ownerDocument||b[0]&&b[0].ownerDocument||c);var h=[],i;for(var j=0,k;(k=a[j])!=null;j++){typeof k=="number"&&(k+="");if(!k)continue;if(typeof k=="string")if(!_.test(k))k=b.createTextNode(k);else{k=k.replace(Y,"<$1></$2>");var l=(Z.exec(k)||["",""])[1].toLowerCase(),m=bg[l]||bg._default,n=m[0],o=b.createElement("div");b===c?bh.appendChild(o):U(b).appendChild(o),o.innerHTML=m[1]+k+m[2];while(n--)o=o.lastChild;if(!f.support.tbody){var p=$.test(k),q=l==="table"&&!p?o.firstChild&&o.firstChild.childNodes:m[1]==="<table>"&&!p?o.childNodes:[];for(i=q.length-1;i>=0;--i)f.nodeName(q[i],"tbody")&&!q[i].childNodes.length&&q[i].parentNode.removeChild(q[i])}!f.support.leadingWhitespace&&X.test(k)&&o.insertBefore(b.createTextNode(X.exec(k)[0]),o.firstChild),k=o.childNodes}var r;if(!f.support.appendChecked)if(k[0]&&typeof (r=k.length)=="number")for(i=0;i<r;i++)bn(k[i]);else bn(k);k.nodeType?h.push(k):h=f.merge(h,k)}if(d){g=function(a){return!a.type||be.test(a.type)};for(j=0;h[j];j++)if(e&&f.nodeName(h[j],"script")&&(!h[j].type||h[j].type.toLowerCase()==="text/javascript"))e.push(h[j].parentNode?h[j].parentNode.removeChild(h[j]):h[j]);else{if(h[j].nodeType===1){var s=f.grep(h[j].getElementsByTagName("script"),g);h.splice.apply(h,[j+1,0].concat(s))}d.appendChild(h[j])}}return h},cleanData:function(a){var b,c,d=f.cache,e=f.event.special,g=f.support.deleteExpando;for(var h=0,i;(i=a[h])!=null;h++){if(i.nodeName&&f.noData[i.nodeName.toLowerCase()])continue;c=i[f.expando];if(c){b=d[c];if(b&&b.events){for(var j in b.events)e[j]?f.event.remove(i,j):f.removeEvent(i,j,b.handle);b.handle&&(b.handle.elem=null)}g?delete i[f.expando]:i.removeAttribute&&i.removeAttribute(f.expando),delete d[c]}}}});var bq=/alpha\([^)]*\)/i,br=/opacity=([^)]*)/,bs=/([A-Z]|^ms)/g,bt=/^-?\d+(?:px)?$/i,bu=/^-?\d/,bv=/^([\-+])=([\-+.\de]+)/,bw={position:"absolute",visibility:"hidden",display:"block"},bx=["Left","Right"],by=["Top","Bottom"],bz,bA,bB;f.fn.css=function(a,c){if(arguments.length===2&&c===b)return this;return f.access(this,a,c,!0,function(a,c,d){return d!==b?f.style(a,c,d):f.css(a,c)})},f.extend({cssHooks:{opacity:{get:function(a,b){if(b){var c=bz(a,"opacity","opacity");return c===""?"1":c}return a.style.opacity}}},cssNumber:{fillOpacity:!0,fontWeight:!0,lineHeight:!0,opacity:!0,orphans:!0,widows:!0,zIndex:!0,zoom:!0},cssProps:{"float":f.support.cssFloat?"cssFloat":"styleFloat"},style:function(a,c,d,e){if(!!a&&a.nodeType!==3&&a.nodeType!==8&&!!a.style){var g,h,i=f.camelCase(c),j=a.style,k=f.cssHooks[i];c=f.cssProps[i]||i;if(d===b){if(k&&"get"in k&&(g=k.get(a,!1,e))!==b)return g;return j[c]}h=typeof d,h==="string"&&(g=bv.exec(d))&&(d=+(g[1]+1)*+g[2]+parseFloat(f.css(a,c)),h="number");if(d==null||h==="number"&&isNaN(d))return;h==="number"&&!f.cssNumber[i]&&(d+="px");if(!k||!("set"in k)||(d=k.set(a,d))!==b)try{j[c]=d}catch(l){}}},css:function(a,c,d){var e,g;c=f.camelCase(c),g=f.cssHooks[c],c=f.cssProps[c]||c,c==="cssFloat"&&(c="float");if(g&&"get"in g&&(e=g.get(a,!0,d))!==b)return e;if(bz)return bz(a,c)},swap:function(a,b,c){var d={};for(var e in b)d[e]=a.style[e],a.style[e]=b[e];c.call(a);for(e in b)a.style[e]=d[e]}}),f.curCSS=f.css,f.each(["height","width"],function(a,b){f.cssHooks[b]={get:function(a,c,d){var e;if(c){if(a.offsetWidth!==0)return bC(a,b,d);f.swap(a,bw,function(){e=bC(a,b,d)});return e}},set:function(a,b){if(!bt.test(b))return b;b=parseFloat(b);if(b>=0)return b+"px"}}}),f.support.opacity||(f.cssHooks.opacity={get:function(a,b){return br.test((b&&a.currentStyle?a.currentStyle.filter:a.style.filter)||"")?parseFloat(RegExp.$1)/100+"":b?"1":""},set:function(a,b){var c=a.style,d=a.currentStyle,e=f.isNumeric(b)?"alpha(opacity="+b*100+")":"",g=d&&d.filter||c.filter||"";c.zoom=1;if(b>=1&&f.trim(g.replace(bq,""))===""){c.removeAttribute("filter");if(d&&!d.filter)return}c.filter=bq.test(g)?g.replace(bq,e):g+" "+e}}),f(function(){f.support.reliableMarginRight||(f.cssHooks.marginRight={get:function(a,b){var c;f.swap(a,{display:"inline-block"},function(){b?c=bz(a,"margin-right","marginRight"):c=a.style.marginRight});return c}})}),c.defaultView&&c.defaultView.getComputedStyle&&(bA=function(a,b){var c,d,e;b=b.replace(bs,"-$1").toLowerCase(),(d=a.ownerDocument.defaultView)&&(e=d.getComputedStyle(a,null))&&(c=e.getPropertyValue(b),c===""&&!f.contains(a.ownerDocument.documentElement,a)&&(c=f.style(a,b)));return c}),c.documentElement.currentStyle&&(bB=function(a,b){var c,d,e,f=a.currentStyle&&a.currentStyle[b],g=a.style;f===null&&g&&(e=g[b])&&(f=e),!bt.test(f)&&bu.test(f)&&(c=g.left,d=a.runtimeStyle&&a.runtimeStyle.left,d&&(a.runtimeStyle.left=a.currentStyle.left),g.left=b==="fontSize"?"1em":f||0,f=g.pixelLeft+"px",g.left=c,d&&(a.runtimeStyle.left=d));return f===""?"auto":f}),bz=bA||bB,f.expr&&f.expr.filters&&(f.expr.filters.hidden=function(a){var b=a.offsetWidth,c=a.offsetHeight;return b===0&&c===0||!f.support.reliableHiddenOffsets&&(a.style&&a.style.display||f.css(a,"display"))==="none"},f.expr.filters.visible=function(a){return!f.expr.filters.hidden(a)});var bD=/%20/g,bE=/\[\]$/,bF=/\r?\n/g,bG=/#.*$/,bH=/^(.*?):[ \t]*([^\r\n]*)\r?$/mg,bI=/^(?:color|date|datetime|datetime-local|email|hidden|month|number|password|range|search|tel|text|time|url|week)$/i,bJ=/^(?:about|app|app\-storage|.+\-extension|file|res|widget):$/,bK=/^(?:GET|HEAD)$/,bL=/^\/\//,bM=/\?/,bN=/<script\b[^<]*(?:(?!<\/script>)<[^<]*)*<\/script>/gi,bO=/^(?:select|textarea)/i,bP=/\s+/,bQ=/([?&])_=[^&]*/,bR=/^([\w\+\.\-]+:)(?:\/\/([^\/?#:]*)(?::(\d+))?)?/,bS=f.fn.load,bT={},bU={},bV,bW,bX=["*/"]+["*"];try{bV=e.href}catch(bY){bV=c.createElement("a"),bV.href="",bV=bV.href}bW=bR.exec(bV.toLowerCase())||[],f.fn.extend({load:function(a,c,d){if(typeof a!="string"&&bS)return bS.apply(this,arguments);if(!this.length)return this;var e=a.indexOf(" ");if(e>=0){var g=a.slice(e,a.length);a=a.slice(0,e)}var h="GET";c&&(f.isFunction(c)?(d=c,c=b):typeof c=="object"&&(c=f.param(c,f.ajaxSettings.traditional),h="POST"));var i=this;f.ajax({url:a,type:h,dataType:"html",data:c,complete:function(a,b,c){c=a.responseText,a.isResolved()&&(a.done(function(a){c=a}),i.html(g?f("<div>").append(c.replace(bN,"")).find(g):c)),d&&i.each(d,[c,b,a])}});return this},serialize:function(){return f.param(this.serializeArray())},serializeArray:function(){return this.map(function(){return this.elements?f.makeArray(this.elements):this}).filter(function(){return this.name&&!this.disabled&&(this.checked||bO.test(this.nodeName)||bI.test(this.type))}).map(function(a,b){var c=f(this).val();return c==null?null:f.isArray(c)?f.map(c,function(a,c){return{name:b.name,value:a.replace(bF,"\r\n")}}):{name:b.name,value:c.replace(bF,"\r\n")}}).get()}}),f.each("ajaxStart ajaxStop ajaxComplete ajaxError ajaxSuccess ajaxSend".split(" "),function(a,b){f.fn[b]=function(a){return this.on(b,a)}}),f.each(["get","post"],function(a,c){f[c]=function(a,d,e,g){f.isFunction(d)&&(g=g||e,e=d,d=b);return f.ajax({type:c,url:a,data:d,success:e,dataType:g})}}),f.extend({getScript:function(a,c){return f.get(a,b,c,"script")},getJSON:function(a,b,c){return f.get(a,b,c,"json")},ajaxSetup:function(a,b){b?b_(a,f.ajaxSettings):(b=a,a=f.ajaxSettings),b_(a,b);return a},ajaxSettings:{url:bV,isLocal:bJ.test(bW[1]),global:!0,type:"GET",contentType:"application/x-www-form-urlencoded",processData:!0,async:!0,accepts:{xml:"application/xml, text/xml",html:"text/html",text:"text/plain",json:"application/json, text/javascript","*":bX},contents:{xml:/xml/,html:/html/,json:/json/},responseFields:{xml:"responseXML",text:"responseText"},converters:{"* text":a.String,"text html":!0,"text json":f.parseJSON,"text xml":f.parseXML},flatOptions:{context:!0,url:!0}},ajaxPrefilter:bZ(bT),ajaxTransport:bZ(bU),ajax:function(a,c){function w(a,c,l,m){if(s!==2){s=2,q&&clearTimeout(q),p=b,n=m||"",v.readyState=a>0?4:0;var o,r,u,w=c,x=l?cb(d,v,l):b,y,z;if(a>=200&&a<300||a===304){if(d.ifModified){if(y=v.getResponseHeader("Last-Modified"))f.lastModified[k]=y;if(z=v.getResponseHeader("Etag"))f.etag[k]=z}if(a===304)w="notmodified",o=!0;else try{r=cc(d,x),w="success",o=!0}catch(A){w="parsererror",u=A}}else{u=w;if(!w||a)w="error",a<0&&(a=0)}v.status=a,v.statusText=""+(c||w),o?h.resolveWith(e,[r,w,v]):h.rejectWith(e,[v,w,u]),v.statusCode(j),j=b,t&&g.trigger("ajax"+(o?"Success":"Error"),[v,d,o?r:u]),i.fireWith(e,[v,w]),t&&(g.trigger("ajaxComplete",[v,d]),--f.active||f.event.trigger("ajaxStop"))}}typeof a=="object"&&(c=a,a=b),c=c||{};var d=f.ajaxSetup({},c),e=d.context||d,g=e!==d&&(e.nodeType||e instanceof f)?f(e):f.event,h=f.Deferred(),i=f.Callbacks("once memory"),j=d.statusCode||{},k,l={},m={},n,o,p,q,r,s=0,t,u,v={readyState:0,setRequestHeader:function(a,b){if(!s){var c=a.toLowerCase();a=m[c]=m[c]||a,l[a]=b}return this},getAllResponseHeaders:function(){return s===2?n:null},getResponseHeader:function(a){var c;if(s===2){if(!o){o={};while(c=bH.exec(n))o[c[1].toLowerCase()]=c[2]}c=o[a.toLowerCase()]}return c===b?null:c},overrideMimeType:function(a){s||(d.mimeType=a);return this},abort:function(a){a=a||"abort",p&&p.abort(a),w(0,a);return this}};h.promise(v),v.success=v.done,v.error=v.fail,v.complete=i.add,v.statusCode=function(a){if(a){var b;if(s<2)for(b in a)j[b]=[j[b],a[b]];else b=a[v.status],v.then(b,b)}return this},d.url=((a||d.url)+"").replace(bG,"").replace(bL,bW[1]+"//"),d.dataTypes=f.trim(d.dataType||"*").toLowerCase().split(bP),d.crossDomain==null&&(r=bR.exec(d.url.toLowerCase()),d.crossDomain=!(!r||r[1]==bW[1]&&r[2]==bW[2]&&(r[3]||(r[1]==="http:"?80:443))==(bW[3]||(bW[1]==="http:"?80:443)))),d.data&&d.processData&&typeof d.data!="string"&&(d.data=f.param(d.data,d.traditional)),b$(bT,d,c,v);if(s===2)return!1;t=d.global,d.type=d.type.toUpperCase(),d.hasContent=!bK.test(d.type),t&&f.active++===0&&f.event.trigger("ajaxStart");if(!d.hasContent){d.data&&(d.url+=(bM.test(d.url)?"&":"?")+d.data,delete d.data),k=d.url;if(d.cache===!1){var x=f.now(),y=d.url.replace(bQ,"$1_="+x);d.url=y+(y===d.url?(bM.test(d.url)?"&":"?")+"_="+x:"")}}(d.data&&d.hasContent&&d.contentType!==!1||c.contentType)&&v.setRequestHeader("Content-Type",d.contentType),d.ifModified&&(k=k||d.url,f.lastModified[k]&&v.setRequestHeader("If-Modified-Since",f.lastModified[k]),f.etag[k]&&v.setRequestHeader("If-None-Match",f.etag[k])),v.setRequestHeader("Accept",d.dataTypes[0]&&d.accepts[d.dataTypes[0]]?d.accepts[d.dataTypes[0]]+(d.dataTypes[0]!=="*"?", "+bX+"; q=0.01":""):d.accepts["*"]);for(u in d.headers)v.setRequestHeader(u,d.headers[u]);if(d.beforeSend&&(d.beforeSend.call(e,v,d)===!1||s===2)){v.abort();return!1}for(u in{success:1,error:1,complete:1})v[u](d[u]);p=b$(bU,d,c,v);if(!p)w(-1,"No Transport");else{v.readyState=1,t&&g.trigger("ajaxSend",[v,d]),d.async&&d.timeout>0&&(q=setTimeout(function(){v.abort("timeout")},d.timeout));try{s=1,p.send(l,w)}catch(z){if(s<2)w(-1,z);else throw z}}return v},param:function(a,c){var d=[],e=function(a,b){b=f.isFunction(b)?b():b,d[d.length]=encodeURIComponent(a)+"="+encodeURIComponent(b)};c===b&&(c=f.ajaxSettings.traditional);if(f.isArray(a)||a.jquery&&!f.isPlainObject(a))f.each(a,function(){e(this.name,this.value)});else for(var g in a)ca(g,a[g],c,e);return d.join("&").replace(bD,"+")}}),f.extend({active:0,lastModified:{},etag:{}});var cd=f.now(),ce=/(\=)\?(&|$)|\?\?/i;f.ajaxSetup({jsonp:"callback",jsonpCallback:function(){return f.expando+"_"+cd++}}),f.ajaxPrefilter("json jsonp",function(b,c,d){var e=b.contentType==="application/x-www-form-urlencoded"&&typeof b.data=="string";if(b.dataTypes[0]==="jsonp"||b.jsonp!==!1&&(ce.test(b.url)||e&&ce.test(b.data))){var g,h=b.jsonpCallback=f.isFunction(b.jsonpCallback)?b.jsonpCallback():b.jsonpCallback,i=a[h],j=b.url,k=b.data,l="$1"+h+"$2";b.jsonp!==!1&&(j=j.replace(ce,l),b.url===j&&(e&&(k=k.replace(ce,l)),b.data===k&&(j+=(/\?/.test(j)?"&":"?")+b.jsonp+"="+h))),b.url=j,b.data=k,a[h]=function(a){g=[a]},d.always(function(){a[h]=i,g&&f.isFunction(i)&&a[h](g[0])}),b.converters["script json"]=function(){g||f.error(h+" was not called");return g[0]},b.dataTypes[0]="json";return"script"}}),f.ajaxSetup({accepts:{script:"text/javascript, application/javascript, application/ecmascript, application/x-ecmascript"},contents:{script:/javascript|ecmascript/},converters:{"text script":function(a){f.globalEval(a);return a}}}),f.ajaxPrefilter("script",function(a){a.cache===b&&(a.cache=!1),a.crossDomain&&(a.type="GET",a.global=!1)}),f.ajaxTransport("script",function(a){if(a.crossDomain){var d,e=c.head||c.getElementsByTagName("head")[0]||c.documentElement;return{send:function(f,g){d=c.createElement("script"),d.async="async",a.scriptCharset&&(d.charset=a.scriptCharset),d.src=a.url,d.onload=d.onreadystatechange=function(a,c){if(c||!d.readyState||/loaded|complete/.test(d.readyState))d.onload=d.onreadystatechange=null,e&&d.parentNode&&e.removeChild(d),d=b,c||g(200,"success")},e.insertBefore(d,e.firstChild)},abort:function(){d&&d.onload(0,1)}}}});var cf=a.ActiveXObject?function(){for(var a in ch)ch[a](0,1)}:!1,cg=0,ch;f.ajaxSettings.xhr=a.ActiveXObject?function(){return!this.isLocal&&ci()||cj()}:ci,function(a){f.extend(f.support,{ajax:!!a,cors:!!a&&"withCredentials"in a})}(f.ajaxSettings.xhr()),f.support.ajax&&f.ajaxTransport(function(c){if(!c.crossDomain||f.support.cors){var d;return{send:function(e,g){var h=c.xhr(),i,j;c.username?h.open(c.type,c.url,c.async,c.username,c.password):h.open(c.type,c.url,c.async);if(c.xhrFields)for(j in c.xhrFields)h[j]=c.xhrFields[j];c.mimeType&&h.overrideMimeType&&h.overrideMimeType(c.mimeType),!c.crossDomain&&!e["X-Requested-With"]&&(e["X-Requested-With"]="XMLHttpRequest");try{for(j in e)h.setRequestHeader(j,e[j])}catch(k){}h.send(c.hasContent&&c.data||null),d=function(a,e){var j,k,l,m,n;try{if(d&&(e||h.readyState===4)){d=b,i&&(h.onreadystatechange=f.noop,cf&&delete ch[i]);if(e)h.readyState!==4&&h.abort();else{j=h.status,l=h.getAllResponseHeaders(),m={},n=h.responseXML,n&&n.documentElement&&(m.xml=n),m.text=h.responseText;try{k=h.statusText}catch(o){k=""}!j&&c.isLocal&&!c.crossDomain?j=m.text?200:404:j===1223&&(j=204)}}}catch(p){e||g(-1,p)}m&&g(j,k,m,l)},!c.async||h.readyState===4?d():(i=++cg,cf&&(ch||(ch={},f(a).unload(cf)),ch[i]=d),h.onreadystatechange=d)},abort:function(){d&&d(0,1)}}}});var ck={},cl,cm,cn=/^(?:toggle|show|hide)$/,co=/^([+\-]=)?([\d+.\-]+)([a-z%]*)$/i,cp,cq=[["height","marginTop","marginBottom","paddingTop","paddingBottom"],["width","marginLeft","marginRight","paddingLeft","paddingRight"],["opacity"]],cr;f.fn.extend({show:function(a,b,c){var d,e;if(a||a===0)return this.animate(cu("show",3),a,b,c);for(var g=0,h=this.length;g<h;g++)d=this[g],d.style&&(e=d.style.display,!f._data(d,"olddisplay")&&e==="none"&&(e=d.style.display=""),e===""&&f.css(d,"display")==="none"&&f._data(d,"olddisplay",cv(d.nodeName)));for(g=0;g<h;g++){d=this[g];if(d.style){e=d.style.display;if(e===""||e==="none")d.style.display=f._data(d,"olddisplay")||""}}return this},hide:function(a,b,c){if(a||a===0)return this.animate(cu("hide",3),a,b,c);var d,e,g=0,h=this.length;for(;g<h;g++)d=this[g],d.style&&(e=f.css(d,"display"),e!=="none"&&!f._data(d,"olddisplay")&&f._data(d,"olddisplay",e));for(g=0;g<h;g++)this[g].style&&(this[g].style.display="none");return this},_toggle:f.fn.toggle,toggle:function(a,b,c){var d=typeof a=="boolean";f.isFunction(a)&&f.isFunction(b)?this._toggle.apply(this,arguments):a==null||d?this.each(function(){var b=d?a:f(this).is(":hidden");f(this)[b?"show":"hide"]()}):this.animate(cu("toggle",3),a,b,c);return this},fadeTo:function(a,b,c,d){return this.filter(":hidden").css("opacity",0).show().end().animate({opacity:b},a,c,d)},animate:function(a,b,c,d){function g(){e.queue===!1&&f._mark(this);var b=f.extend({},e),c=this.nodeType===1,d=c&&f(this).is(":hidden"),g,h,i,j,k,l,m,n,o;b.animatedProperties={};for(i in a){g=f.camelCase(i),i!==g&&(a[g]=a[i],delete a[i]),h=a[g],f.isArray(h)?(b.animatedProperties[g]=h[1],h=a[g]=h[0]):b.animatedProperties[g]=b.specialEasing&&b.specialEasing[g]||b.easing||"swing";if(h==="hide"&&d||h==="show"&&!d)return b.complete.call(this);c&&(g==="height"||g==="width")&&(b.overflow=[this.style.overflow,this.style.overflowX,this.style.overflowY],f.css(this,"display")==="inline"&&f.css(this,"float")==="none"&&(!f.support.inlineBlockNeedsLayout||cv(this.nodeName)==="inline"?this.style.display="inline-block":this.style.zoom=1))}b.overflow!=null&&(this.style.overflow="hidden");for(i in a)j=new f.fx(this,b,i),h=a[i],cn.test(h)?(o=f._data(this,"toggle"+i)||(h==="toggle"?d?"show":"hide":0),o?(f._data(this,"toggle"+i,o==="show"?"hide":"show"),j[o]()):j[h]()):(k=co.exec(h),l=j.cur(),k?(m=parseFloat(k[2]),n=k[3]||(f.cssNumber[i]?"":"px"),n!=="px"&&(f.style(this,i,(m||1)+n),l=(m||1)/j.cur()*l,f.style(this,i,l+n)),k[1]&&(m=(k[1]==="-="?-1:1)*m+l),j.custom(l,m,n)):j.custom(l,h,""));return!0}var e=f.speed(b,c,d);if(f.isEmptyObject(a))return this.each(e.complete,[!1]);a=f.extend({},a);return e.queue===!1?this.each(g):this.queue(e.queue,g)},stop:function(a,c,d){typeof a!="string"&&(d=c,c=a,a=b),c&&a!==!1&&this.queue(a||"fx",[]);return this.each(function(){function h(a,b,c){var e=b[c];f.removeData(a,c,!0),e.stop(d)}var b,c=!1,e=f.timers,g=f._data(this);d||f._unmark(!0,this);if(a==null)for(b in g)g[b]&&g[b].stop&&b.indexOf(".run")===b.length-4&&h(this,g,b);else g[b=a+".run"]&&g[b].stop&&h(this,g,b);for(b=e.length;b--;)e[b].elem===this&&(a==null||e[b].queue===a)&&(d?e[b](!0):e[b].saveState(),c=!0,e.splice(b,1));(!d||!c)&&f.dequeue(this,a)})}}),f.each({slideDown:cu("show",1),slideUp:cu("hide",1),slideToggle:cu("toggle",1),fadeIn:{opacity:"show"},fadeOut:{opacity:"hide"},fadeToggle:{opacity:"toggle"}},function(a,b){f.fn[a]=function(a,c,d){return this.animate(b,a,c,d)}}),f.extend({speed:function(a,b,c){var d=a&&typeof a=="object"?f.extend({},a):{complete:c||!c&&b||f.isFunction(a)&&a,duration:a,easing:c&&b||b&&!f.isFunction(b)&&b};d.duration=f.fx.off?0:typeof d.duration=="number"?d.duration:d.duration in f.fx.speeds?f.fx.speeds[d.duration]:f.fx.speeds._default;if(d.queue==null||d.queue===!0)d.queue="fx";d.old=d.complete,d.complete=function(a){f.isFunction(d.old)&&d.old.call(this),d.queue?f.dequeue(this,d.queue):a!==!1&&f._unmark(this)};return d},easing:{linear:function(a,b,c,d){return c+d*a},swing:function(a,b,c,d){return(-Math.cos(a*Math.PI)/2+.5)*d+c}},timers:[],fx:function(a,b,c){this.options=b,this.elem=a,this.prop=c,b.orig=b.orig||{}}}),f.fx.prototype={update:function(){this.options.step&&this.options.step.call(this.elem,this.now,this),(f.fx.step[this.prop]||f.fx.step._default)(this)},cur:function(){if(this.elem[this.prop]!=null&&(!this.elem.style||this.elem.style[this.prop]==null))return this.elem[this.prop];var a,b=f.css(this.elem,this.prop);return isNaN(a=parseFloat(b))?!b||b==="auto"?0:b:a},custom:function(a,c,d){function h(a){return e.step(a)}var e=this,g=f.fx;this.startTime=cr||cs(),this.end=c,this.now=this.start=a,this.pos=this.state=0,this.unit=d||this.unit||(f.cssNumber[this.prop]?"":"px"),h.queue=this.options.queue,h.elem=this.elem,h.saveState=function(){e.options.hide&&f._data(e.elem,"fxshow"+e.prop)===b&&f._data(e.elem,"fxshow"+e.prop,e.start)},h()&&f.timers.push(h)&&!cp&&(cp=setInterval(g.tick,g.interval))},show:function(){var a=f._data(this.elem,"fxshow"+this.prop);this.options.orig[this.prop]=a||f.style(this.elem,this.prop),this.options.show=!0,a!==b?this.custom(this.cur(),a):this.custom(this.prop==="width"||this.prop==="height"?1:0,this.cur()),f(this.elem).show()},hide:function(){this.options.orig[this.prop]=f._data(this.elem,"fxshow"+this.prop)||f.style(this.elem,this.prop),this.options.hide=!0,this.custom(this.cur(),0)},step:function(a){var b,c,d,e=cr||cs(),g=!0,h=this.elem,i=this.options;if(a||e>=i.duration+this.startTime){this.now=this.end,this.pos=this.state=1,this.update(),i.animatedProperties[this.prop]=!0;for(b in i.animatedProperties)i.animatedProperties[b]!==!0&&(g=!1);if(g){i.overflow!=null&&!f.support.shrinkWrapBlocks&&f.each(["","X","Y"],function(a,b){h.style["overflow"+b]=i.overflow[a]}),i.hide&&f(h).hide();if(i.hide||i.show)for(b in i.animatedProperties)f.style(h,b,i.orig[b]),f.removeData(h,"fxshow"+b,!0),f.removeData(h,"toggle"+b,!0);d=i.complete,d&&(i.complete=!1,d.call(h))}return!1}i.duration==Infinity?this.now=e:(c=e-this.startTime,this.state=c/i.duration,this.pos=f.easing[i.animatedProperties[this.prop]](this.state,c,0,1,i.duration),this.now=this.start+(this.end-this.start)*this.pos),this.update();return!0}},f.extend(f.fx,{tick:function(){var a,b=f.timers,c=0;for(;c<b.length;c++)a=b[c],!a()&&b[c]===a&&b.splice(c--,1);b.length||f.fx.stop()},interval:13,stop:function(){clearInterval(cp),cp=null},speeds:{slow:600,fast:200,_default:400},step:{opacity:function(a){f.style(a.elem,"opacity",a.now)},_default:function(a){a.elem.style&&a.elem.style[a.prop]!=null?a.elem.style[a.prop]=a.now+a.unit:a.elem[a.prop]=a.now}}}),f.each(["width","height"],function(a,b){f.fx.step[b]=function(a){f.style(a.elem,b,Math.max(0,a.now)+a.unit)}}),f.expr&&f.expr.filters&&(f.expr.filters.animated=function(a){return f.grep(f.timers,function(b){return a===b.elem}).length});var cw=/^t(?:able|d|h)$/i,cx=/^(?:body|html)$/i;"getBoundingClientRect"in c.documentElement?f.fn.offset=function(a){var b=this[0],c;if(a)return this.each(function(b){f.offset.setOffset(this,a,b)});if(!b||!b.ownerDocument)return null;if(b===b.ownerDocument.body)return f.offset.bodyOffset(b);try{c=b.getBoundingClientRect()}catch(d){}var e=b.ownerDocument,g=e.documentElement;if(!c||!f.contains(g,b))return c?{top:c.top,left:c.left}:{top:0,left:0};var h=e.body,i=cy(e),j=g.clientTop||h.clientTop||0,k=g.clientLeft||h.clientLeft||0,l=i.pageYOffset||f.support.boxModel&&g.scrollTop||h.scrollTop,m=i.pageXOffset||f.support.boxModel&&g.scrollLeft||h.scrollLeft,n=c.top+l-j,o=c.left+m-k;return{top:n,left:o}}:f.fn.offset=function(a){var b=this[0];if(a)return this.each(function(b){f.offset.setOffset(this,a,b)});if(!b||!b.ownerDocument)return null;if(b===b.ownerDocument.body)return f.offset.bodyOffset(b);var c,d=b.offsetParent,e=b,g=b.ownerDocument,h=g.documentElement,i=g.body,j=g.defaultView,k=j?j.getComputedStyle(b,null):b.currentStyle,l=b.offsetTop,m=b.offsetLeft;while((b=b.parentNode)&&b!==i&&b!==h){if(f.support.fixedPosition&&k.position==="fixed")break;c=j?j.getComputedStyle(b,null):b.currentStyle,l-=b.scrollTop,m-=b.scrollLeft,b===d&&(l+=b.offsetTop,m+=b.offsetLeft,f.support.doesNotAddBorder&&(!f.support.doesAddBorderForTableAndCells||!cw.test(b.nodeName))&&(l+=parseFloat(c.borderTopWidth)||0,m+=parseFloat(c.borderLeftWidth)||0),e=d,d=b.offsetParent),f.support.subtractsBorderForOverflowNotVisible&&c.overflow!=="visible"&&(l+=parseFloat(c.borderTopWidth)||0,m+=parseFloat(c.borderLeftWidth)||0),k=c}if(k.position==="relative"||k.position==="static")l+=i.offsetTop,m+=i.offsetLeft;f.support.fixedPosition&&k.position==="fixed"&&(l+=Math.max(h.scrollTop,i.scrollTop),m+=Math.max(h.scrollLeft,i.scrollLeft));return{top:l,left:m}},f.offset={bodyOffset:function(a){var b=a.offsetTop,c=a.offsetLeft;f.support.doesNotIncludeMarginInBodyOffset&&(b+=parseFloat(f.css(a,"marginTop"))||0,c+=parseFloat(f.css(a,"marginLeft"))||0);return{top:b,left:c}},setOffset:function(a,b,c){var d=f.css(a,"position");d==="static"&&(a.style.position="relative");var e=f(a),g=e.offset(),h=f.css(a,"top"),i=f.css(a,"left"),j=(d==="absolute"||d==="fixed")&&f.inArray("auto",[h,i])>-1,k={},l={},m,n;j?(l=e.position(),m=l.top,n=l.left):(m=parseFloat(h)||0,n=parseFloat(i)||0),f.isFunction(b)&&(b=b.call(a,c,g)),b.top!=null&&(k.top=b.top-g.top+m),b.left!=null&&(k.left=b.left-g.left+n),"using"in b?b.using.call(a,k):e.css(k)}},f.fn.extend({position:function(){if(!this[0])return null;var a=this[0],b=this.offsetParent(),c=this.offset(),d=cx.test(b[0].nodeName)?{top:0,left:0}:b.offset();c.top-=parseFloat(f.css(a,"marginTop"))||0,c.left-=parseFloat(f.css(a,"marginLeft"))||0,d.top+=parseFloat(f.css(b[0],"borderTopWidth"))||0,d.left+=parseFloat(f.css(b[0],"borderLeftWidth"))||0;return{top:c.top-d.top,left:c.left-d.left}},offsetParent:function(){return this.map(function(){var a=this.offsetParent||c.body;while(a&&!cx.test(a.nodeName)&&f.css(a,"position")==="static")a=a.offsetParent;return a})}}),f.each(["Left","Top"],function(a,c){var d="scroll"+c;f.fn[d]=function(c){var e,g;if(c===b){e=this[0];if(!e)return null;g=cy(e);return g?"pageXOffset"in g?g[a?"pageYOffset":"pageXOffset"]:f.support.boxModel&&g.document.documentElement[d]||g.document.body[d]:e[d]}return this.each(function(){g=cy(this),g?g.scrollTo(a?f(g).scrollLeft():c,a?c:f(g).scrollTop()):this[d]=c})}}),f.each(["Height","Width"],function(a,c){var d=c.toLowerCase();f.fn["inner"+c]=function(){var a=this[0];return a?a.style?parseFloat(f.css(a,d,"padding")):this[d]():null},f.fn["outer"+c]=function(a){var b=this[0];return b?b.style?parseFloat(f.css(b,d,a?"margin":"border")):this[d]():null},f.fn[d]=function(a){var e=this[0];if(!e)return a==null?null:this;if(f.isFunction(a))return this.each(function(b){var c=f(this);c[d](a.call(this,b,c[d]()))});if(f.isWindow(e)){var g=e.document.documentElement["client"+c],h=e.document.body;return e.document.compatMode==="CSS1Compat"&&g||h&&h["client"+c]||g}if(e.nodeType===9)return Math.max(e.documentElement["client"+c],e.body["scroll"+c],e.documentElement["scroll"+c],e.body["offset"+c],e.documentElement["offset"+c]);if(a===b){var i=f.css(e,d),j=parseFloat(i);return f.isNumeric(j)?j:i}return this.css(d,typeof a=="string"?a:a+"px")}}),a.jQuery=a.$=f,typeof define=="function"&&define.amd&&define.amd.jQuery&&define("jquery",[],function(){return f})})(window);\r
diff --git a/testcms-final-anon/install/diagnose.php b/testcms-final-anon/install/diagnose.php
new file mode 100644 (file)
index 0000000..7a7e13c
--- /dev/null
@@ -0,0 +1,40 @@
+<?php\r
+\r
+/*\r
+       Database connection test\r
+*/\r
+\r
+$fields = array('host', 'user', 'pass', 'db');\r
+$post = array();\r
+\r
+foreach($fields as $field) {\r
+       $post[$field] = isset($_POST[$field]) ? $_POST[$field] : false;\r
+}\r
+\r
+if(empty($post['db'])) {\r
+       $errors[] = 'Please specify a database name';\r
+}\r
+\r
+if(empty($post['host'])) {\r
+       $errors[] = 'Please specify a database host';\r
+}\r
+\r
+// test database\r
+if(empty($errors)) {\r
+       try {\r
+               $dsn = 'mysql:dbname=' . $post['db'] . ';host=' . $post['host'];\r
+               new PDO($dsn, $post['user'], $post['pass']);\r
+       } catch(PDOException $e) {\r
+               $errors[] = $e->getMessage();\r
+       }\r
+}\r
+\r
+// output response\r
+header('Content-Type: text/plain');\r
+\r
+if(empty($errors)) {\r
+       //no errors we're all gooood\r
+       echo 'good';\r
+} else {\r
+       echo implode(', ', $errors);\r
+}\r
diff --git a/testcms-final-anon/install/index.php b/testcms-final-anon/install/index.php
new file mode 100644 (file)
index 0000000..4e640d1
--- /dev/null
@@ -0,0 +1,165 @@
+<!doctype html>\r
+<html lang="en-gb">\r
+    <head>\r
+        <meta charset="utf-8">\r
+        <title>Install Test CMS CMS</title>\r
+        <mate name="robots" content="noindex, nofollow">\r
+        \r
+        <link rel="stylesheet" href="assets/css/app.css">\r
+        \r
+        <script src="//ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js"></script>\r
+        <script>window.jQuery || document.write('<script src="assets/js/jquery.js"><\/script>');</script>\r
+        <script src="assets/js/app.js"></script>\r
+    </head>\r
+    <body>\r
+    \r
+       <h1><img src="assets/img/logo.gif" alt="Test CMS install logo"></h1>\r
+       \r
+       <?php\r
+       \r
+       /*\r
+               Compatibility checks\r
+       */\r
+       $compat = array();\r
+       \r
+       // php\r
+       if(version_compare(PHP_VERSION, '5.3.0', '<')) {\r
+               $compat[] = 'Test CMS requires PHP 5.3 or newer.<br><em>Your current environment is running PHP ' . PHP_VERSION . '</em>';\r
+       }\r
+       \r
+       // PDO\r
+       if(class_exists('PDO') === false) {\r
+               $compat[] = 'Test CMS requires PDO (PHP Data Objects)<br>\r
+               <em>You can find more about <a href="//php.net/manual/en/book.pdo.php">installing and setting up PHP Data Objects</a> \r
+               on the php.net website</em>';\r
+       } else {\r
+               if(in_array('mysql', PDO::getAvailableDrivers()) === false) {\r
+                       $compat[] = 'Test CMS requires the MySQL PDO Driver<br>\r
+                               <em>You can find more about <a href="//php.net/manual/en/ref.pdo-mysql.php">installing and setting up MySQL PDO Driver</a> \r
+                               on the php.net website</em>';\r
+               }\r
+       }\r
+\r
+        // can we write a config file?\r
+        // note: on win the only way to really test is to try and write a new file to disk.\r
+        if(@file_put_contents('../test.php', '<?php //test') === false) {\r
+            $compat[] = 'It looks like the root directory is not writable, we may not be able to automatically create your config.php file. \r
+                Please make the root directory writable until the installation is complete.';\r
+        } else {\r
+            unlink('../test.php');\r
+        }\r
+\r
+       ?>\r
+       \r
+       <?php if(count($compat)): ?>\r
+    \r
+       <div class="content">\r
+               <h2>Woops.</h2>\r
+               \r
+               <p>Test CMS is missing some requirements:</p>\r
+               \r
+               <ul style="padding-bottom: 1em;">\r
+                       <?php foreach($compat as $item): ?>\r
+                       <li><?php echo $item; ?></li>\r
+                       <?php endforeach; ?>\r
+               </ul>\r
+               \r
+               <p><a href="." class="button" style="float: none; display: inline-block;">Ok, I've fixed these, run the installer.</a></p>\r
+       </div>\r
+    \r
+       <?php elseif(file_exists('../config.php')): ?>\r
+       \r
+       <div class="content">\r
+               <h2>Woops.</h2>\r
+               \r
+               <p>Test CMS is already installed. You should really delete this folder!</p>\r
+               \r
+               <p><a href="../" class="button" style="float: none; display: inline-block;">Return to the main site.</a></p>\r
+       </div>\r
+       \r
+       <?php else: ?>\r
+    \r
+        <p class="nojs error">You will need Javascript enabled for this installation. <em>Sorry :(</em></p>\r
+\r
+        <div class="content">\r
+            <h2>Welcome to Test CMS.</h2>\r
+\r
+            <p>If you were looking for a truly lightweight blogging experience, you&rsquo;ve \r
+            found the right place. Simply fill in the details below, and you&rsquo;ll have your \r
+            new blog set up in no time.</p>\r
+            \r
+            <small>If you want a more custom install, feel free to edit <code>config.default.php</code> \r
+            (before or after this installation, it doesn't really matter, as long as you rename it to \r
+            <code>config.php</code>).</small>\r
+            \r
+            <div class="notes"></div>\r
+            \r
+            <form method="get" novalidate>\r
+                <fieldset id="diagnose">\r
+                    <legend>Your database details</legend>\r
+                    \r
+                    <p>\r
+                        <label for="host">Your database host:</label>\r
+                        <input id="host" name="host" value="localhost">\r
+                    </p>\r
+                    <p>\r
+                        <label for="user">Your database username:</label>\r
+                        <input id="user" autocapitalize="off" name="user" placeholder="root">\r
+                    </p>\r
+                    <p>\r
+                        <label for="pass">Your database password:</label>\r
+                        <input id="pass" autocapitalize="off" name="pass" placeholder="password">\r
+                    </p>\r
+                    <p>\r
+                        <label for="db">Your database name:</label>\r
+                        <input id="db" autocapitalize="off" name="db" placeholder="Test CMS">\r
+                    </p>\r
+                    \r
+                    <a href="#check" class="button">Check database details</a>\r
+                </fieldset>\r
+                \r
+                <fieldset>\r
+                    <legend>About your site</legend>\r
+                    \r
+                    <p>\r
+                        <label for="name">Site name:</label>\r
+                        <input id="name" name="name" placeholder="My awesome Test CMS site">\r
+                    </p>\r
+                    \r
+                    <p>\r
+                        <label for="description">Site description:</label>\r
+                        <textarea id="description" name="description"></textarea>\r
+                    </p>\r
+\r
+                    <p>\r
+                        <label for="theme">Theme:</label>\r
+                        <select id="theme" name="theme">\r
+                            <?php foreach(glob('../themes/*') as $theme): $name = basename($theme); ?>\r
+                            <?php if(file_exists($theme . '/about.txt')): ?>\r
+                            <option value="<?php echo $name; ?>" <?php if($name === 'default') echo 'selected'; ?>><?php echo ucwords($name); ?></option>\r
+                            <?php endif; ?>\r
+                            <?php endforeach; ?>\r
+                        </select>\r
+                    </p>\r
+                    \r
+                    <p>\r
+                        <label for="email">Your Email Address:</label>\r
+                        <input id="email" name="email">\r
+                    </p>\r
+                    \r
+                    <p>\r
+                        <label for="path">Site path:</label>\r
+                        <input id="path" name="path" value="<?php echo dirname(dirname($_SERVER['SCRIPT_NAME'])); ?>">\r
+                    </p>\r
+                    \r
+                </fieldset>\r
+                \r
+                <br style="clear: both;">\r
+                <button type="submit">Install Test CMS</button>\r
+            </form>\r
+        </div>\r
+        \r
+        <?php endif; ?>\r
+\r
+    </body>\r
+</html>\r
diff --git a/testcms-final-anon/install/installer.php b/testcms-final-anon/install/installer.php
new file mode 100644 (file)
index 0000000..cc94b94
--- /dev/null
@@ -0,0 +1,159 @@
+<?php\r
+\r
+/*\r
+       Helper functions\r
+*/\r
+function random($length = 16) {\r
+       $pool = str_split('0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ', 1);\r
+       $value = '';\r
+\r
+       for ($i = 0; $i < $length; $i++)  {\r
+               $value .= $pool[mt_rand(0, 61)];\r
+       }\r
+\r
+       return $value;\r
+}\r
+       \r
+/*\r
+       Installer\r
+*/\r
+\r
+$fields = array('host', 'user', 'pass', 'db', 'name', 'description', 'theme', 'email', 'path', 'clean_urls');\r
+$post = array();\r
+$warnings = array();\r
+$errors = array();\r
+\r
+foreach($fields as $field) {\r
+       $post[$field] = isset($_POST[$field]) ? $_POST[$field] : false;\r
+}\r
+\r
+if(empty($post['db'])) {\r
+       $errors[] = 'Please specify a database name';\r
+}\r
+\r
+if(empty($post['host'])) {\r
+       $errors[] = 'Please specify a database host';\r
+}\r
+\r
+if(empty($post['name'])) {\r
+       $errors[] = 'Please enter a site name';\r
+}\r
+\r
+if(empty($post['theme'])) {\r
+       $errors[] = 'Please select a theme';\r
+}\r
+\r
+if(filter_var($post['email'], FILTER_VALIDATE_EMAIL) === false) {\r
+       $errors[] = 'Please enter a valid email address';\r
+}\r
+\r
+if(version_compare(PHP_VERSION, '5.3.0', '<')) {\r
+       $errors[] = 'TestCMS requires PHP 5.3 or newer, your current environment is running PHP ' . PHP_VERSION;\r
+}\r
+\r
+// test database\r
+if(empty($errors)) {\r
+       try {\r
+               $dsn = 'mysql:dbname=' . $post['db'] . ';host=' . $post['host'];\r
+               $dbh = new PDO($dsn, $post['user'], $post['pass']);\r
+       } catch(PDOException $e) {\r
+               $errors[] = $e->getMessage();\r
+       }\r
+}\r
+\r
+// create config file\r
+if(empty($errors)) {\r
+       $template = file_get_contents('../config.default.php');\r
+       \r
+       $base_url = ($path = trim($post['path'], '/')) == '' ? '' : $path . '/';\r
+       $index_page = ($post['clean_urls'] === false ? 'index.php' : '');\r
+\r
+       $search = array(\r
+               "'host' => 'localhost'",\r
+               "'username' => 'root'",\r
+               "'password' => ''",\r
+               "'name' => 'testcms'",\r
+               \r
+               // apllication paths\r
+               "'base_url' => '/'",\r
+               "'index_page' => 'index.php'",\r
+               "'key' => ''"\r
+       );\r
+       $replace = array(\r
+               "'host' => '" . $post['host'] . "'",\r
+               "'username' => '" . $post['user'] . "'",\r
+               "'password' => '" . $post['pass'] . "'",\r
+               "'name' => '" . $post['db'] . "'",\r
+\r
+               // apllication paths\r
+               "'base_url' => '/" . $base_url . "'",\r
+               "'index_page' => '" . $index_page . "'",\r
+               "'key' => '" . random(32) . "'"\r
+       );\r
+       $config = str_replace($search, $replace, $template);\r
+\r
+       if(file_put_contents('../config.php', $config) === false) {\r
+               $errors[] = 'Failed to create config file';\r
+       }\r
+       \r
+       // if we have clean urls enabled let setup a \r
+       // basic htaccess file is there isnt one\r
+       if($post['clean_urls']) {\r
+               // dont overwrite existing htaccess file\r
+               if(file_exists('../.htaccess') === false) {\r
+                       $htaccess = file_get_contents('../htaccess.txt');       \r
+                       $htaccess = str_replace('# RewriteBase /', 'RewriteBase /' . $base_url, $htaccess);\r
+       \r
+                       if(file_put_contents('../.htaccess', $htaccess) === false) {\r
+                               $errors[] = 'Unable to create .htaccess file. Make to create one to enable clean urls.';\r
+                       }\r
+               } else {\r
+                       $warnings[] = 'It looks like you already have a htaccess file in place, to use clean URLs please copy and paste our sample htaccess.txt file, remember to update the RewriteBase option if you have installed TestCMS in a subfolder.';\r
+               }\r
+       }\r
+}\r
+\r
+// create db\r
+if(empty($errors)) {\r
+       // create a unique password for our installation\r
+       $password = random(8);\r
+\r
+       $sql = str_replace('[[now]]', time(), file_get_contents('test.sql'));\r
+       $sql = str_replace('[[password]]', crypt($password), $sql);\r
+       $sql = str_replace('[[email]]', strtolower(trim($post['email'])), $sql);\r
+       \r
+       try {\r
+               $dbh->beginTransaction();\r
+               $dbh->exec($sql);\r
+               \r
+               $sql= "INSERT INTO `meta` (`key`, `value`) VALUES ('sitename', ?), ('description', ?), ('theme', ?);";\r
+               $statement = $dbh->prepare($sql);\r
+               $statement->execute(array($post['name'], $post['description'], $post['theme']));\r
+\r
+               $dbh->commit();\r
+       } catch(PDOException $e) {\r
+               $errors[] = $e->getMessage();\r
+               \r
+               // rollback any changes\r
+               if($dbh->inTransaction()) {\r
+                       $dbh->rollBack();\r
+               }\r
+       }\r
+}\r
+\r
+// output response\r
+header('Content-Type: application/json');\r
+\r
+if(empty($errors)) {\r
+       //no errors we're all gooood\r
+       $response['installed'] = true;\r
+       $response['password'] = $password;\r
+       $response['warnings'] = $warnings;\r
+} else {\r
+       $response['installed'] = false;\r
+       $response['errors'] = $errors;\r
+       $response['warnings'] = $warnings;\r
+}\r
+\r
+// output json formatted string\r
+echo json_encode($response);\r
diff --git a/testcms-final-anon/install/test.sql b/testcms-final-anon/install/test.sql
new file mode 100644 (file)
index 0000000..f307f02
--- /dev/null
@@ -0,0 +1,94 @@
+\r
+DROP TABLE IF EXISTS `comments`;\r
+\r
+CREATE TABLE IF NOT EXISTS `comments` (\r
+       `id` int(6) NOT NULL AUTO_INCREMENT,\r
+       `post` int(6) NOT NULL,\r
+       `status` enum('pending','published','spam') NOT NULL,\r
+       `date` int(11) NOT NULL,\r
+       `name` varchar(140) NOT NULL,\r
+       `email` varchar(140) NOT NULL,\r
+       `text` text NOT NULL,\r
+       PRIMARY KEY (`id`),\r
+       KEY `post` (`post`),\r
+       KEY `status` (`status`)\r
+) ENGINE=MyISAM CHARSET=utf8 COLLATE=utf8_general_ci;\r
+\r
+DROP TABLE IF EXISTS `meta`;\r
+\r
+CREATE TABLE `meta` (\r
+       `key` varchar(140) NOT NULL,\r
+       `value` text NOT NULL,\r
+       PRIMARY KEY (`key`)\r
+) ENGINE=MyISAM CHARSET=utf8 COLLATE=utf8_general_ci;\r
+\r
+INSERT INTO `meta` (`key`, `value`) VALUES ('posts_page', '1'), ('home_page', '1'), ('twitter', ''), ('date_format', 'jS M, Y'), ('auto_published_comments', '1'), ('posts_per_page', '10');\r
+\r
+DROP TABLE IF EXISTS `pages`;\r
+\r
+CREATE TABLE `pages` (\r
+       `id` int(6) NOT NULL AUTO_INCREMENT,\r
+       `slug` varchar(150) NOT NULL,\r
+       `name` varchar(64) NOT NULL,\r
+       `title` varchar(150) NOT NULL,\r
+       `content` text NOT NULL,\r
+       `status` enum('draft','published','archived') NOT NULL,\r
+       PRIMARY KEY (`id`),\r
+       KEY `status` (`status`),\r
+       KEY `slug` (`slug`)\r
+) ENGINE=MyISAM CHARSET=utf8 COLLATE=utf8_general_ci;\r
+\r
+INSERT INTO `pages` (`slug`, `name`, `title`, `content`, `status`) VALUES\r
+('posts', 'Posts', 'My posts and thoughts', '<p>Welcome!</p>', 'published'),\r
+('about', 'About', 'A little bit about me', '<p>This is a little bit of text about me.</p>', 'published');\r
+\r
+DROP TABLE IF EXISTS `posts`;\r
+\r
+CREATE TABLE `posts` (\r
+       `id` int(6) NOT NULL AUTO_INCREMENT,\r
+       `title` varchar(150) NOT NULL,\r
+       `slug` varchar(150) NOT NULL,\r
+       `description` text NOT NULL,\r
+       `html` text NOT NULL,\r
+       `css` text NOT NULL,\r
+       `js` text NOT NULL,\r
+       `custom_fields` text,\r
+       `created` int(11) NOT NULL,\r
+       `author` int(6) NOT NULL,\r
+       `status` enum('draft','published','archived') NOT NULL,\r
+       `comments` TINYINT( 1 ) NOT NULL,\r
+       PRIMARY KEY (`id`),\r
+       KEY `status` (`status`),\r
+       KEY `slug` (`slug`)\r
+) ENGINE=MyISAM CHARSET=utf8 COLLATE=utf8_general_ci;\r
+\r
+INSERT INTO `posts` (`title`, `slug`, `description`, `html`, `css`, `js`, `created`, `author`, `status`, `comments`) VALUES\r
+('Hello World', 'hello', 'Hello World.', '<p>My first post.</p>', '', '', '[[now]]', 1, 'published', 1);\r
+\r
+DROP TABLE IF EXISTS `users`;\r
+\r
+CREATE TABLE `users` (\r
+       `id` int(6) NOT NULL AUTO_INCREMENT,\r
+       `username` varchar(100) NOT NULL,\r
+       `password` varchar(140) NOT NULL,\r
+       `email` varchar(140) NOT NULL,\r
+       `real_name` varchar(140) NOT NULL,\r
+       `bio` text NOT NULL,\r
+       `status` enum('inactive','active') NOT NULL,\r
+       `role` enum('administrator','editor','user') NOT NULL,\r
+       PRIMARY KEY (`id`)\r
+) ENGINE=MyISAM CHARSET=utf8 COLLATE=utf8_general_ci;\r
+\r
+INSERT INTO `users` (`username`, `password`, `email`, `real_name`, `bio`, `status`, `role`) VALUES\r
+('admin', '[[password]]', '[[email]]', 'Administrator', 'Default account for TestCMS\r
+.', 'active', 'administrator');\r
+\r
+DROP TABLE IF EXISTS `sessions`;\r
+\r
+CREATE TABLE IF NOT EXISTS `sessions` (\r
+       `id` CHAR( 32 ) NOT NULL ,\r
+       `date` DATETIME NOT NULL ,\r
+       `ip` VARCHAR( 15 ) NOT NULL ,\r
+       `ua` TEXT NOT NULL ,\r
+       `data` TEXT NOT NULL\r
+) ENGINE=InnoDB CHARSET=utf8 COLLATE=utf8_general_ci;\r
diff --git a/testcms-final-anon/system/admin/controllers/comments.php b/testcms-final-anon/system/admin/controllers/comments.php
new file mode 100644 (file)
index 0000000..2d4da93
--- /dev/null
@@ -0,0 +1,32 @@
+<?php defined('IN_CMS') or die('No direct access allowed.');\r
+\r
+class Comments_controller {\r
+\r
+       public function status() {\r
+               Response::header('Content-Type', 'application/json');\r
+\r
+               // process post request\r
+               if(Input::method() == 'POST') {\r
+                       Comments::update_status();\r
+               }\r
+       }\r
+       \r
+       public function update() {\r
+               Response::header('Content-Type', 'application/json');\r
+\r
+               // process post request\r
+               if(Input::method() == 'POST') {\r
+                       Comments::update();\r
+               }\r
+       }\r
+\r
+       public function remove() {\r
+               Response::header('Content-Type', 'application/json');\r
+\r
+               // process post request\r
+               if(Input::method() == 'POST') {\r
+                       Comments::remove();\r
+               }\r
+       }\r
+       \r
+}\r
diff --git a/testcms-final-anon/system/admin/controllers/metadata.php b/testcms-final-anon/system/admin/controllers/metadata.php
new file mode 100644 (file)
index 0000000..ec4d838
--- /dev/null
@@ -0,0 +1,29 @@
+<?php defined('IN_CMS') or die('No direct access allowed.');\r
+\r
+class Metadata_controller {\r
+\r
+    public function __construct() {\r
+        $this->admin_url = Config::get('application.admin_folder');\r
+    }\r
+\r
+       public function index() {\r
+       if(Input::method() == 'POST') {\r
+               if(Metadata::update()) {\r
+                       return Response::redirect($this->admin_url . '/metadata');\r
+               }\r
+       }\r
+\r
+       // provide a list to set for our home page and posts page\r
+       $pages = Pages::list_all(array('status' => 'published'));\r
+\r
+        // list valid themes\r
+        $themes = Themes::list_all();\r
+\r
+       Template::render('metadata/index', array(\r
+            'pages' => $pages, \r
+            'themes' => $themes,\r
+            'metadata' => (object) Config::get('metadata')\r
+        ));\r
+       }\r
+       \r
+}\r
diff --git a/testcms-final-anon/system/admin/controllers/pages.php b/testcms-final-anon/system/admin/controllers/pages.php
new file mode 100644 (file)
index 0000000..15a65ca
--- /dev/null
@@ -0,0 +1,40 @@
+<?php defined('IN_CMS') or die('No direct access allowed.');\r
+\r
+class Pages_controller {\r
+\r
+       public function __construct() {\r
+               $this->admin_url = Config::get('application.admin_folder');\r
+       }\r
+\r
+       public function index() {\r
+               $pages = Pages::list_all();\r
+               Template::render('pages/index', array('pages' => $pages));\r
+       }\r
+       \r
+       public function add() {\r
+               if(Input::method() == 'POST') {\r
+                       if(Pages::add()) {\r
+                               return Response::redirect($this->admin_url . '/pages/edit/' . Db::insert_id());\r
+                       }\r
+               }\r
+               Template::render('pages/add');\r
+       }\r
+       \r
+       public function edit($id) {\r
+               // find page\r
+               if(($page = Pages::find(array('id' => $id))) === false) {\r
+                       return Response::redirect($this->admin_url . '/pages');\r
+               }\r
+\r
+               // process post request\r
+               if(Input::method() == 'POST') {\r
+                       if(Pages::update($id)) {\r
+                               // redirect path\r
+                               return Response::redirect($this->admin_url . '/pages/edit/' . $id);\r
+                       }\r
+               }\r
+\r
+               Template::render('pages/edit', array('page' => $page));\r
+       }\r
+       \r
+}\r
diff --git a/testcms-final-anon/system/admin/controllers/posts.php b/testcms-final-anon/system/admin/controllers/posts.php
new file mode 100644 (file)
index 0000000..3e173e3
--- /dev/null
@@ -0,0 +1,56 @@
+<?php defined('IN_CMS') or die('No direct access allowed.');\r
+\r
+class Posts_controller {\r
+\r
+       public function __construct() {\r
+               $this->admin_url = Config::get('application.admin_folder');\r
+       }\r
+\r
+       public function index() {\r
+               $data['posts'] = Posts::list_all(array('sortby' => 'id', 'sortmode' => 'desc'));\r
+               Template::render('posts/index', $data);\r
+       }\r
+       \r
+       public function add() {\r
+               if(Input::method() == 'POST') {\r
+                       if(Posts::add()) {\r
+                               return Response::redirect($this->admin_url . '/posts/edit/' . Db::insert_id());\r
+                       }\r
+               }\r
+\r
+               Template::render('posts/add');\r
+       }\r
+       \r
+       public function edit($id) {\r
+               // find article\r
+               if(($article = Posts::find(array('id' => $id))) === false) {\r
+                       return Response::redirect($this->admin_url . '/posts');\r
+               }\r
+\r
+               // process post request\r
+               if(Input::method() == 'POST') {\r
+                       if(Posts::update($id)) {\r
+                               // redirect path\r
+                               return Response::redirect($this->admin_url . '/posts/edit/' . $id);\r
+                       }\r
+               }\r
+               \r
+               // get comments\r
+               $comments = Comments::list_all(array('post' => $id));\r
+               $pending = array();\r
+               \r
+               foreach($comments as $comment) {\r
+                   if($comment->status == 'pending') {\r
+                       $pending[] = $comment->id;\r
+                   }\r
+               }\r
+               \r
+               $pending = count($pending);\r
+\r
+               // get posts page\r
+               $page = Pages::find(array('id' => Config::get('metadata.posts_page')));\r
+\r
+               Template::render('posts/edit', array('article' => $article, 'comments' => $comments, 'page' => $page, 'pending' => $pending));\r
+       }\r
+       \r
+}\r
diff --git a/testcms-final-anon/system/admin/controllers/users.php b/testcms-final-anon/system/admin/controllers/users.php
new file mode 100644 (file)
index 0000000..c43db55
--- /dev/null
@@ -0,0 +1,79 @@
+<?php defined('IN_CMS') or die('No direct access allowed.');\r
+\r
+class Users_controller {\r
+\r
+       public function __construct() {\r
+               $this->admin_url = Config::get('application.admin_folder');\r
+       }\r
+\r
+       public function index() {\r
+               $users = Users::list_all();\r
+               Template::render('users/index', array('users' => $users));\r
+       }\r
+       \r
+       public function login() {\r
+               if(Input::method() == 'POST') {\r
+                       if(Users::login()) {\r
+                               return Response::redirect($this->admin_url . '/posts');\r
+                       }\r
+               }\r
+               Template::render('users/login');\r
+       }\r
+       \r
+       public function logout() {\r
+               Users::logout();\r
+               return Response::redirect($this->admin_url . '/login');\r
+       }\r
+       \r
+       public function amnesia() {\r
+               if(Input::method() == 'POST') {\r
+                       if(Users::recover_password()) {\r
+                               return Response::redirect($this->admin_url . '/users/login');\r
+                       }\r
+               }\r
+               Template::render('users/amnesia');\r
+       }\r
+       \r
+       public function reset($hash) {\r
+               // find user\r
+               if(($user = Users::find(array('hash' => $hash))) === false) {\r
+                       Notifications::set('error', 'User not found');\r
+                       return Response::redirect($this->admin_url . '/users');\r
+               }\r
+\r
+               if(Input::method() == 'POST') {\r
+                       if(Users::reset_password($user->id)) {\r
+                               return Response::redirect($this->admin_url);\r
+                       }\r
+               }\r
+\r
+               Template::render('users/reset', array('user' => $user));\r
+       }\r
+       \r
+       public function add() {\r
+               if(Input::method() == 'POST') {\r
+                       if(Users::add()) {\r
+                               return Response::redirect($this->admin_url . '/users/edit/' . Db::insert_id());\r
+                       }\r
+               }\r
+               Template::render('users/add');\r
+       }\r
+       \r
+       public function edit($id) {\r
+               // find user\r
+               if(($user = Users::find(array('id' => $id))) === false) {\r
+                       return Response::redirect($this->admin_url . '/users');\r
+               }\r
+\r
+               // process post request\r
+               if(Input::method() == 'POST') {\r
+                       if(Users::update($id)) {\r
+                               // redirect path\r
+                               return Response::redirect($this->admin_url . '/users/edit/' . $id);\r
+                       }\r
+               }\r
+\r
+               Template::render('users/edit', array('user' => $user));\r
+       }\r
+       \r
+}\r
diff --git a/testcms-final-anon/system/admin/theme/assets/css/admin.css b/testcms-final-anon/system/admin/theme/assets/css/admin.css
new file mode 100644 (file)
index 0000000..f7a9fc0
--- /dev/null
@@ -0,0 +1,585 @@
+* {\r
+    margin: 0;\r
+    padding: 0;\r
+    \r
+    list-style: none;\r
+}\r
+\r
+::selection {\r
+    color: #fff;\r
+    background: rgba(57,115,169,.7);\r
+    \r
+    text-shadow: 0 1px 1px rgba(0,0,0,.3);\r
+}\r
+    ::-webkit-selection {\r
+        background: rgba(57,115,169,.7);\r
+        color: #fff;\r
+        \r
+        text-shadow: 0 1px 1px rgba(0,0,0,.3);\r
+    }\r
+    ::-moz-selection {\r
+        background: rgba(57,115,169,.7);\r
+        color: #fff;\r
+        \r
+        text-shadow: 0 1px 1px rgba(0,0,0,.3);\r
+    }\r
+\r
+body {\r
+    background: #e7f0f9 url('../img/bg.gif') repeat-x 0 0;\r
+    \r
+    font: 13px/22px "Helvetica Neue", sans-serif;\r
+    color: #75818c;\r
+    \r
+    width: 900px;\r
+    margin: 0 auto;\r
+}\r
+\r
+a {\r
+    -webkit-transition: color .25s;\r
+    -moz-transition: color .25s;\r
+    -ms-transition: color .25s;\r
+    -o-transition: color .25s;\r
+    transition: color .25s;\r
+}\r
+\r
+i, em {\r
+    font-family: Georgia, serif;\r
+}\r
+\r
+header#top {\r
+    height: 61px;\r
+    line-height: 61px;\r
+}\r
+    header#top a#logo {\r
+        display: block;\r
+        float: left;\r
+        \r
+        margin: 20px 0 0;\r
+        height: 24px;\r
+    }\r
+        header#top a#logo img {\r
+            display: block;\r
+        }\r
+        header#top a#logo:hover {\r
+            opacity: .8;\r
+        }\r
+    header#top nav {\r
+        float: left;\r
+        padding-left: 20px;\r
+    }\r
+        header#top nav li {\r
+            display: inline-block;\r
+            float: left;\r
+        }\r
+        header#top nav li a {\r
+            color: #909eab;\r
+            \r
+            font-weight: bold;\r
+            text-decoration: none;\r
+            \r
+            display: block;\r
+            padding: 0 20px;\r
+            \r
+            text-shadow: 0 1px 0 rgba(0,0,0,.3);\r
+        }\r
+            header#top nav li a:hover {\r
+                color: #b7cbdf;\r
+            }\r
+            header#top nav li.active a {\r
+                color: #fff;\r
+                \r
+                background: url('../img/active.png') no-repeat 50% 0;\r
+            }\r
+    header#top p {\r
+        color: #91969c;  \r
+        float: right;          \r
+    }\r
+        header#top p a {\r
+            color: #d7dfe7;\r
+            padding-left: 15px;\r
+        }\r
+        header#top p a:hover {\r
+            color: #fff;\r
+        }\r
+    \r
+h1 {\r
+    height: 86px;\r
+    line-height: 86px;\r
+    \r
+    font-weight: lighter;\r
+    color: #304355;\r
+    text-shadow: 0 1px 0 rgba(255,255,255,.25);\r
+    \r
+    position: relative;\r
+}\r
+    h1 a, button {\r
+        background-color: #4375a7;\r
+        background-image: -webkit-gradient(linear, left top, left bottom, from(#5e92be), to(#285890));\r
+        background-image: -webkit-linear-gradient(top, #5e92be, #285890);\r
+        background-image: -moz-linear-gradient(top, #5e92be, #285890);\r
+        background-image: -o-linear-gradient(top, #5e92be, #285890);\r
+        background-image: -ms-linear-gradient(top, #5e92be, #285890);\r
+        background-image: linear-gradient(top, #5e92be, #285890);\r
+        filter: progid:DXImageTransform.Microsoft.gradient(GradientType=0,StartColorStr='#5e92be', EndColorStr='#285890');\r
+        \r
+        border: 1px solid #164773;\r
+        \r
+        border-radius: 4px;\r
+        \r
+        -webkit-box-shadow: inset 0 1px 0 rgba(255,255,255,.25),0 1px 1px rgba(0,0,0,.05), inset 0 -1px 1px rgba(0,0,0,.1);\r
+        -moz-box-shadow: inset 0 1px 0 rgba(255,255,255,.25),0 1px 1px rgba(0,0,0,.05), inset 0 -1px 1px rgba(0,0,0,.1);\r
+        box-shadow: inset 0 1px 0 rgba(255,255,255,.25),0 1px 1px rgba(0,0,0,.05), inset 0 -1px 1px rgba(0,0,0,.1);\r
+        \r
+        font: bold 13px "Helvetica Neue", sans-serif;\r
+        color: #fff;\r
+        text-shadow: 0 1px 1px rgba(0,0,0,.3);\r
+        text-decoration: none;\r
+        \r
+        float: right;\r
+        padding: 8px 14px;\r
+        margin-top: 28px;\r
+        \r
+        cursor: pointer;\r
+    }\r
+        h1 a:active, button:active, section.content nav.tabs ul li a.active {\r
+            -webkit-box-shadow: inset 0 1px 1px rgba(0,0,0,.3), inset 0 -1px 1px rgba(0,0,0,.2),0 1px 1px rgba(0,0,0,.1);\r
+            -moz-box-shadow: inset 0 1px 1px rgba(0,0,0,.3), inset 0 -1px 1px rgba(0,0,0,.2),0 1px 1px rgba(0,0,0,.1);\r
+            box-shadow: inset 0 1px 1px rgba(0,0,0,.3), inset 0 -1px 1px rgba(0,0,0,.2),0 1px 1px rgba(0,0,0,.1);\r
+            \r
+            background-color: #2d5d8a;\r
+            background-image: -webkit-gradient(linear, left top, left bottom, from(#386c98), to(#224f7d));\r
+            background-image: -webkit-linear-gradient(top, #386c98, #224f7d);\r
+            background-image: -moz-linear-gradient(top, #386c98, #224f7d);\r
+            background-image: -o-linear-gradient(top, #386c98, #224f7d);\r
+            background-image: -ms-linear-gradient(top, #386c98, #224f7d);\r
+            background-image: linear-gradient(top, #386c98, #224f7d);\r
+            filter: progid:DXImageTransform.Microsoft.gradient(GradientType=0,StartColorStr='#386c98', EndColorStr='#224f7d');\r
+            \r
+            border: 1px solid #0d3355;\r
+        }\r
+    button[name=delete] {\r
+        border-color: #681a1c;\r
+    \r
+        background-color: #b04e51;\r
+        background-image: -webkit-gradient(linear, left top, left bottom, from(#c86a6d), to(#983336));\r
+        background-image: -webkit-linear-gradient(top, #c86a6d, #983336);\r
+        background-image: -moz-linear-gradient(top, #c86a6d, #983336);\r
+        background-image: -o-linear-gradient(top, #c86a6d, #983336);\r
+        background-image: -ms-linear-gradient(top, #c86a6d, #983336);\r
+        background-image: linear-gradient(top, #c86a6d, #983336);\r
+        filter: progid:DXImageTransform.Microsoft.gradient(GradientType=0,StartColorStr='#c86a6d', EndColorStr='#983336');\r
+    }\r
+        button[name=delete]:active {\r
+            border-color: #501314;\r
+            \r
+            background-color: #802d30;\r
+            background-image: -webkit-gradient(linear, left top, left bottom, from(#984447), to(#69171a));\r
+            background-image: -webkit-linear-gradient(top, #984447, #69171a);\r
+            background-image: -moz-linear-gradient(top, #984447, #69171a);\r
+            background-image: -o-linear-gradient(top, #984447, #69171a);\r
+            background-image: -ms-linear-gradient(top, #984447, #69171a);\r
+            background-image: linear-gradient(top, #984447, #69171a);\r
+            filter: progid:DXImageTransform.Microsoft.gradient(GradientType=0,StartColorStr='#984447', EndColorStr='#69171a');\r
+        }\r
+        \r
+button#create {\r
+       float: left;\r
+       margin-bottom: 30px;\r
+       margin-left: 120px;\r
+}\r
+    \r
+section.content {\r
+    background: #fff;\r
+    \r
+    -webkit-border-radius: 5px;\r
+    -moz-border-radius: 5px;\r
+    border-radius: 5px;\r
+    \r
+    -webkit-box-shadow: inset 0 -1px 1px #f5f5f5,0 1px 1px rgba(0,0,0,.1);\r
+    -moz-box-shadow: inset 0 -1px 1px #f5f5f5,0 1px 1px rgba(0,0,0,.1);\r
+    box-shadow: inset 0 -1px 1px #f5f5f5,0 1px 1px rgba(0,0,0,.1);\r
+    \r
+    margin: 40px 0;\r
+    padding: 30px 40px;\r
+    \r
+    width: 550px;\r
+    float: left;\r
+}\r
+\r
+    section.content nav.tabs {\r
+        margin-bottom: 2em;\r
+    }\r
+        section.content nav.tabs ul {\r
+            margin: 0;\r
+            padding: 0 0 1em 0;\r
+            border-bottom: 1px solid #ebf0f3;\r
+        }\r
+            section.content nav.tabs ul li {\r
+                display: inline-block;\r
+                margin-right: 15px;\r
+            }\r
+                section.content nav.tabs ul li a {\r
+                    display: inline-block;\r
+                    padding: 5px 12px;\r
+                    \r
+                    position: relative;\r
+                    text-decoration: none;\r
+                    font-weight: bold;\r
+                    \r
+                    background: #f2f4f5;\r
+\r
+                    -webkit-border-radius: 4px;\r
+                    -moz-border-radius: 4px;\r
+                    border-radius: 4px;\r
+                    \r
+                    -webkit-box-shadow: inset 0 -1px 1px rgba(0,0,0,.05);\r
+                    -moz-box-shadow: inset 0 -1px 1px rgba(0,0,0,.05);\r
+                    box-shadow: inset 0 -1px 1px rgba(0,0,0,.05);\r
+                }\r
+                    section.content nav.tabs ul li a.active {\r
+                        color: #fff;\r
+                    }\r
+                section.content nav.tabs ul li span {\r
+                    display: inline-block;\r
+                    position: relative;\r
+                    top: -10px;\r
+                    \r
+                    margin-right: -24px;\r
+    \r
+                    padding: 6px;\r
+                    min-width: 10px;\r
+                    height: 10px;\r
+                    \r
+                    font-weight: bold;\r
+                    font-size: 10px;\r
+                    line-height: 10px;\r
+                    \r
+                    color: #fff;\r
+\r
+                    text-align: center;\r
+                    text-shadow: 0 1px 1px rgba(0,0,0,.4);\r
+                    text-decoration: none;\r
+                    \r
+                    background-color: #b63538;\r
+                    background-image: -webkit-gradient(linear, left top, left bottom, from(#ca4d4f), to(#a31d21));\r
+                    background-image: -webkit-linear-gradient(top, #ca4d4f, #a31d21);\r
+                    background-image: -moz-linear-gradient(top, #ca4d4f, #a31d21);\r
+                    background-image: -o-linear-gradient(top, #ca4d4f, #a31d21);\r
+                    background-image: -ms-linear-gradient(top, #ca4d4f, #a31d21);\r
+                    background-image: linear-gradient(top, #ca4d4f, #a31d21);\r
+                    filter: progid:DXImageTransform.Microsoft.gradient(GradientType=0,StartColorStr='#ca4d4f', EndColorStr='#a31d21');\r
+                    \r
+                    -webkit-border-radius: 20px;\r
+                    -moz-border-radius: 20px;\r
+                    border-radius: 20px;\r
+                    \r
+                    border: 1px solid #730707;\r
+                    \r
+                    box-shadow: inset 0 1px 0 rgba(255,255,255,.25), 0 1px 1px rgba(0,0,0,.05);\r
+                }\r
+\r
+    section.content a, .popup_wrapper a {\r
+        color: #527ba5;\r
+    }\r
+        section.content a:hover, .popup_wrapper a:hover {\r
+            color: #3b444d;\r
+        }\r
+        \r
+    section.content ul.list {\r
+        list-style: none;\r
+    }\r
+        section.content ul.list li {\r
+            position: relative;\r
+            border-bottom: 1px solid #f5f7f8;\r
+        }\r
+            section.content ul.list li:last-child {\r
+                border-bottom: none;\r
+            }\r
+        section.content ul.list a {\r
+            display: block;\r
+            \r
+            padding: 15px 0;\r
+            \r
+            text-decoration: none;\r
+        }\r
+            section.content ul.list strong {\r
+                display: block;\r
+                padding-bottom: 3px;\r
+\r
+                font-size: 20px;\r
+            }\r
+            section.content ul.list span {\r
+                display: block;\r
+                opacity: .6;\r
+            }\r
+            section.content ul.list i {\r
+                position: absolute;\r
+                right: 0;\r
+                top: 18px;\r
+            }\r
+            \r
+p.notification {\r
+    position: relative;\r
+    \r
+    margin: 20px 0 -20px;\r
+    padding: 10px 20px;\r
+    \r
+    color: #fff;\r
+    text-shadow: 0 1px 0 rgba(0,0,0,.3);\r
+    \r
+    -webkit-box-shadow: inset 0 2px 1px rgba(0,0,0,.15), inset 0 1px 1px rgba(0,0,0,.05),0 1px 1px rgba(0,0,0,.05);\r
+    -moz-box-shadow: inset 0 2px 1px rgba(0,0,0,.15), inset 0 1px 1px rgba(0,0,0,.05),0 1px 1px rgba(0,0,0,.05);\r
+    box-shadow: inset 0 2px 1px rgba(0,0,0,.15), inset 0 1px 1px rgba(0,0,0,.05),0 1px 1px rgba(0,0,0,.05);\r
+    \r
+    -webkit-border-radius: 5px;\r
+    -moz-border-radius: 5px;\r
+    border-radius: 5px;\r
+    \r
+    background-image: -webkit-gradient(linear, left top, left bottom, from(rgba(0,0,0,.15)), to(transparent));\r
+    background-image: -webkit-linear-gradient(top, rgba(0,0,0,.15), transparent);\r
+    background-image: -moz-linear-gradient(top, rgba(0,0,0,.15), transparent);\r
+    background-image: -o-linear-gradient(top, rgba(0,0,0,.15), transparent);\r
+    background-image: -ms-linear-gradient(top, rgba(0,0,0,.15), transparent);\r
+    background-image: linear-gradient(top, rgba(0,0,0,.15), transparent);\r
+}\r
+    p.notification.error {\r
+       background-color: #911;\r
+    }\r
+    p.notification.success {\r
+       background-color: #757e0e;\r
+    }\r
+    p.notification.notice {\r
+        background-color: #FFC800;\r
+    }\r
+    \r
+fieldset {\r
+    position: relative;\r
+    border: none;\r
+}\r
+    fieldset + fieldset {\r
+        margin-top: 40px;\r
+    }\r
+    legend {\r
+        font-size: 18px;\r
+        font-weight: bold;\r
+        \r
+        color: #284769;\r
+        \r
+        padding-left: 120px;\r
+    }\r
+        legend + em {\r
+            display: block;\r
+            padding: 5px 0 25px 120px;\r
+        }\r
+    \r
+    fieldset p {\r
+        padding-bottom: 20px;\r
+        clear: both;\r
+        overflow: hidden;\r
+    }\r
+        fieldset p em {\r
+            display: block;\r
+            clear: both;\r
+            \r
+            padding-top: 5px;\r
+            padding-left: 120px;\r
+        }\r
+    \r
+    fieldset label {\r
+        display: block;\r
+        float: left;\r
+        \r
+        width: 100px;\r
+        text-align: right;\r
+        \r
+        padding: 6px 0;\r
+        padding-right: 20px;\r
+        \r
+        cursor: pointer;\r
+\r
+        font-weight: bold;\r
+        color: #5e6c7b;        \r
+    }\r
+    fieldset input, fieldset textarea {\r
+        display: block;\r
+        float: left;\r
+        \r
+        width: 404px;\r
+        padding: 8px 12px;\r
+        \r
+        border: 1px solid #a8acb1;\r
+        \r
+        -webkit-box-shadow: inset 0 1px 1px rgba(0,0,0,.1), 0 1px 1px #f5f7f8;\r
+        -moz-box-shadow: inset 0 1px 1px #ebeef1, 0 1px 1px #f5f7f8;\r
+        box-shadow: inset 0 1px 1px rgba(0,0,0,.1), 0 1px 1px #f5f7f8;\r
+        \r
+        font: 13px "Helvetica Neue", sans-serif;\r
+        color: #50575d;\r
+    }\r
+        fieldset .key {\r
+            width: 128px;\r
+            margin-right: -1px;\r
+            \r
+            margin-bottom: 10px;\r
+        }\r
+        fieldset .value {\r
+            width: 250px;\r
+            margin-bottom: 10px;\r
+        }\r
+        fieldset textarea, input[type=url] {\r
+            font: 13px/16px "Anonymous Pro", monospace;\r
+        }\r
+        fieldset textarea {\r
+            line-height: 24px;\r
+        \r
+            resize: vertical;            \r
+            min-height: 150px;\r
+            max-height: 500px;\r
+        }\r
+        fieldset input:focus, fieldset textarea:focus {\r
+            background: #f3f7fc;\r
+            outline: none;\r
+        }\r
+    fieldset select {\r
+        margin-top: 9px;\r
+        min-width: 150px;\r
+    }\r
+        fieldset select + em {\r
+            position: relative;\r
+            top: -8px;\r
+            \r
+            margin-bottom: -8px;\r
+        }\r
+        \r
+        \r
+p.buttons {\r
+    overflow: hidden;\r
+    padding-top: 20px;\r
+    \r
+    border-top: 1px solid #f5f7f8;\r
+}\r
+    p.buttons a {\r
+        float: left;\r
+        line-height: 34px;\r
+    }\r
+    p.buttons button {\r
+        margin-top: 0;\r
+        margin-left: 25px;\r
+    }\r
+   \r
+aside#sidebar {\r
+    float: right;\r
+    width: 200px;\r
+    \r
+    margin-top: 40px;\r
+    padding: 20px;\r
+    \r
+    background: #d6e3f0;\r
+    color: #667a8e;\r
+    \r
+    text-shadow: 0 1px 0 rgba(255,255,255,.3);\r
+    \r
+    -webkit-border-radius: 5px;\r
+    -moz-border-radius: 5px;\r
+    border-radius: 5px;\r
+    \r
+    -webkit-box-shadow: inset 0 -1px 1px rgba(0,0,0,.02), 0 1px 0 #eff6fc;\r
+    -moz-box-shadow: inset 0 -1px 1px rgba(0,0,0,.02), 0 1px 0 #eff6fc;\r
+    box-shadow: inset 0 -1px 1px rgba(0,0,0,.02), 0 1px 0 #eff6fc;\r
+}\r
+    aside#sidebar h2 {\r
+        color: #384f66;\r
+        padding-bottom: 8px;\r
+    }\r
+    aside#sidebar ul {\r
+        margin: 15px 18px -5px;\r
+    }\r
+        aside#sidebar li {\r
+            list-style: square;\r
+            padding-bottom: 5px;\r
+            \r
+            font-size: 12px;\r
+            line-height: 20px;\r
+        }\r
+    aside#sidebar a {\r
+        color: #244f7c;\r
+    }\r
+        aside#sidebar a:hover {\r
+            color: #102e4d;\r
+        }\r
+        \r
+ul#comments {\r
+    position: relative;\r
+    overflow: hidden;\r
+}\r
+    ul#comments li {\r
+        border-top: 1px solid #f2f4f5;\r
+        padding: 20px 0;\r
+        \r
+        overflow: hidden;\r
+    }\r
+        ul#comments li header {\r
+            width: 100px;\r
+            float: left;\r
+        }\r
+            ul#comments li header strong {\r
+                color: #506171;\r
+                display: block;\r
+            }\r
+            ul#comments li header em {\r
+                padding: 10px 0 0;\r
+                \r
+                font-size: 12px;\r
+            }\r
+        ul#comments li p.comment {\r
+            width: 430px;\r
+\r
+            float: left;\r
+            clear: none;\r
+            \r
+            padding-left: 20px;\r
+            padding-bottom: 20px;\r
+        }\r
+        ul#comments li ul {\r
+            position: relative;\r
+            left: 20px;\r
+        }\r
+            ul#comments li li {\r
+                border: none;\r
+                overflow: auto;\r
+                float: left;\r
+                \r
+                padding: 0 15px 0 0;\r
+            }\r
+\r
+footer#bottom {\r
+    clear: both;\r
+    padding: 20px 0 60px;\r
+    margin-top: 20px;\r
+    \r
+    border-top: 1px solid #dde7f0;    \r
+    \r
+    text-shadow: 0 1px 0 #f7fbff;\r
+}\r
+    footer#bottom a {\r
+        color: #474e56;\r
+    }\r
+        footer#bottom a:hover {\r
+            color: #2d353d;\r
+        }\r
+    footer#bottom small {\r
+        float: left;\r
+        font-size: 13px;\r
+    }\r
+    \r
+    footer#bottom em {\r
+        float: right;\r
+        font-size: 11px;\r
+        \r
+        color: #93a8bd;\r
+    }\r
+\r
+.debug {display: none; font-size: 13px; margin-bottom: 1em;}\r
+.debug td, .debug th {padding: 4px 6px; border-bottom: 1px solid #ddd;}\r
+.debug th {font-weight: bold; text-align: center;}\r
+.debug tfoot td:first-child {text-align: right;}
\ No newline at end of file
diff --git a/testcms-final-anon/system/admin/theme/assets/css/popup.css b/testcms-final-anon/system/admin/theme/assets/css/popup.css
new file mode 100644 (file)
index 0000000..8d7395b
--- /dev/null
@@ -0,0 +1,32 @@
+\r
+.popup_overlay {\r
+       background: #173553;\r
+       \r
+       position: fixed;\r
+       top: 0;\r
+       left: 0;\r
+       bottom: 0;\r
+       right: 0;\r
+       z-index: 1000;\r
+\r
+       opacity: .6;\r
+       filter: alpha(opacity=60);\r
+}\r
+\r
+.popup_box {\r
+       background: #fff;\r
+       position: absolute;\r
+       z-index: 1001;\r
+       \r
+       -webkit-border-radius: 3px;\r
+       -moz-border-radius: 3px;\r
+       border-radius: 3px;\r
+       \r
+       -webkit-box-shadow: 0 1px 2px rgba(0,0,0,.3);\r
+       -moz-box-shadow: 0 1px 2px rgba(0,0,0,.3);\r
+       box-shadow: 0 1px 2px rgba(0,0,0,.3);\r
+}\r
+\r
+.popup_wrapper {\r
+       padding: 20px;\r
+}
\ No newline at end of file
diff --git a/testcms-final-anon/system/admin/theme/assets/img/active.png b/testcms-final-anon/system/admin/theme/assets/img/active.png
new file mode 100644 (file)
index 0000000..62977a2
Binary files /dev/null and b/testcms-final-anon/system/admin/theme/assets/img/active.png differ
diff --git a/testcms-final-anon/system/admin/theme/assets/img/bg.gif b/testcms-final-anon/system/admin/theme/assets/img/bg.gif
new file mode 100644 (file)
index 0000000..a213440
Binary files /dev/null and b/testcms-final-anon/system/admin/theme/assets/img/bg.gif differ
diff --git a/testcms-final-anon/system/admin/theme/assets/img/logo.png b/testcms-final-anon/system/admin/theme/assets/img/logo.png
new file mode 100644 (file)
index 0000000..6811df1
Binary files /dev/null and b/testcms-final-anon/system/admin/theme/assets/img/logo.png differ
diff --git a/testcms-final-anon/system/admin/theme/assets/js/comments.js b/testcms-final-anon/system/admin/theme/assets/js/comments.js
new file mode 100644 (file)
index 0000000..092b3e3
--- /dev/null
@@ -0,0 +1,146 @@
+(function(base_url) {\r
+\r
+       var p = new Popup();\r
+\r
+       var publish = function() {\r
+               var a = this, li = a.getParent();\r
+               var url = base_url + 'comments/status';\r
+               var id = a.getParent('li[data-id]').get('data-id');\r
+               \r
+               new Request.JSON({\r
+                       'url': url,\r
+                       'method': 'post',\r
+                       'data': {'id': id, 'status': 'published'},\r
+                       'onRequest': function() {\r
+                               li.setStyle('opacity', 0.5);\r
+                               a.removeEvent('click', publish);\r
+                       },\r
+                       'onSuccess': function() {\r
+                               li.dispose();\r
+                               $$('[data-status=' + id + ']').set('html', 'Published');\r
+                       }\r
+               }).send();\r
+\r
+               return false;\r
+       };\r
+       \r
+       var edit = function() {\r
+               var a = this;\r
+               var url = base_url + 'comments/update';\r
+               var id = a.getParent('li[data-id]').get('data-id');\r
+               var text = $$('[data-text=' + id + ']').get('html');\r
+               var status = $$('[data-status=' + id + ']').get('html');\r
+\r
+               var html = '<fieldset><legend>Edit Comment</legend><em>Update the comment text here.</em>';\r
+               html +='<p><label>Text</label><textarea name="comment_text">' + text + '</textarea></p>';\r
+               html +='<p><label>Status</label><select name="comment_status">';\r
+\r
+                       html += '<option value="published"' + (status == 'published' ? ' selected' : '') + '>Published</option>';\r
+                       html += '<option value="pending"' + (status == 'pending' ? ' selected' : '') + '>Pending</option>';\r
+                       html += '<option value="spam"' + (status == 'spam' ? ' selected' : '') + '>Spam</option>';\r
+\r
+               html += '</select></p>';\r
+               html += '</fieldset>';\r
+               html +='<p class="buttons"><button name="update" type="button">Update</button> <a href="#close">Close</a></p>';\r
+               \r
+               var content = new Element('div', {\r
+                       'class': 'popup_wrapper',\r
+                       'html': html                    \r
+               });\r
+\r
+               p.open({\r
+                       'content': content\r
+               });\r
+\r
+               // bind functions\r
+               $$('button[name=update]').addEvent('click', function() {\r
+                       update(id);\r
+               });\r
+               $$('a[href$=#close]').addEvent('click', function() {\r
+                       p.close();\r
+                       return false;\r
+               });\r
+\r
+               return false;\r
+       };\r
+\r
+       var update = function(id) {\r
+               var url = base_url + 'comments/update', \r
+                       comment_text_input = $$('textarea[name=comment_text]').pop(),\r
+                       comment_status_input = $$('select[name=comment_status]').pop();\r
+\r
+               // get values\r
+               var text = comment_text_input.get('value'),\r
+                       status = comment_status_input.get('value');\r
+\r
+               // get elements\r
+               var     comment_text_output = $$('[data-text=' + id + ']').pop(),\r
+                       comment_status_output = $$('[data-status=' + id + ']').pop(),\r
+                       li = $$('li[data-id=' + id + ']').pop();\r
+               \r
+               new Request.JSON({\r
+                       'url': url,\r
+                       'method': 'post',\r
+                       'data': {'id': id, 'text': text, 'status': status},\r
+                       'onRequest': function() {\r
+                               li.setStyle('opacity', 0.5);\r
+                       },\r
+                       'onSuccess': function() {\r
+                               li.setStyle('opacity', 1);\r
+                               comment_text_output.set('html', text);\r
+                               comment_status_output.set('html', status);\r
+\r
+                               // get publish button if it exists\r
+                               var btn = li.getElement('a[href$=#publish]');\r
+\r
+                               // hide publish button\r
+                               if(btn) {\r
+                                       if(status == 'published') {\r
+                                               btn.dispose();\r
+                                       }\r
+                               } else {\r
+                                       if(status == 'pending') {\r
+                                               var ul = li.getElement('ul');\r
+                                               btn = new Element('li');\r
+                                               btn.grab(new Element('a', {\r
+                                                       'html': 'Publish',\r
+                                                       'href': '#publish',\r
+                                                       'events': {\r
+                                                               'click': publish\r
+                                                       }\r
+                                               }));\r
+                                               ul.grab(btn, 'top');\r
+                                       }\r
+                               }\r
+\r
+                               p.close();\r
+                       }\r
+               }).send();\r
+       };\r
+       \r
+       var remove = function() {\r
+               var a = this, li = a.getParent('li[data-id]');\r
+               var url = base_url + 'comments/remove';\r
+               var id = li.get('data-id');\r
+               \r
+               new Request.JSON({\r
+                       'url': url,\r
+                       'method': 'post',\r
+                       'data': {'id': id},\r
+                       'onRequest': function() {\r
+                               li.setStyle('opacity', 0.5);\r
+                       },\r
+                       'onSuccess': function() {\r
+                               li.dispose();\r
+                       }\r
+               }).send();\r
+\r
+               return false;\r
+       };\r
+\r
+       // bindings\r
+       $$('#comments a[href$=publish]').addEvent('click', publish);\r
+       $$('#comments a[href$=edit]').addEvent('click', edit);\r
+       $$('#comments a[href$=delete]').addEvent('click', remove);\r
+\r
+}('../../'));\r
diff --git a/testcms-final-anon/system/admin/theme/assets/js/custom_fields.js b/testcms-final-anon/system/admin/theme/assets/js/custom_fields.js
new file mode 100644 (file)
index 0000000..2e5d71b
--- /dev/null
@@ -0,0 +1,78 @@
+\r
+(function() {\r
+       var a = $('create'), fields = $('fields');\r
+       \r
+       var p = new Popup();\r
+       \r
+       var create_field = function(key, label) {\r
+               var p = new Element('p', {\r
+                               'id': 'field_' + key\r
+                       }), \r
+                       l = new Element('label', {\r
+                               'html': label + ':'\r
+                       }), \r
+                       i = new Element('input', {\r
+                               'name': 'field[' + key + ':' + label + ']',\r
+                               'type': 'text'\r
+                       });\r
+\r
+               p.grab(l);\r
+               p.grab(i);\r
+               \r
+               fields.grab(p);\r
+       };\r
+       \r
+       var add_field = function() {\r
+               // get data\r
+               var label = $$('input[name=field_label]').pop().get('value'),\r
+                       key = $$('input[name=field_key]').pop().get('value'),\r
+                       errors = [];\r
+                       \r
+               if(label.length == 0) {\r
+                       errors.push('Please enter a field label');\r
+               }\r
+               \r
+               if(key.length == 0) {\r
+                       errors.push('Please enter a field key');\r
+               }\r
+               \r
+               if(errors.length) {\r
+                       // show errors\r
+                       return false;\r
+               }\r
+               \r
+               create_field(key, label);\r
+               \r
+               p.close();\r
+       };\r
+\r
+       var show_add_field = function() {\r
+               var html = '<fieldset><legend>Custom Field</legend><em>Please enter the label and the key for your field.</em>';\r
+               html +='<p><label>Label</label><input name="field_label" type="text"></p>';\r
+               html +='<p><label>Key</label><input name="field_key" type="text"></p>';\r
+               html += '</fieldset>';\r
+               html +='<p class="buttons"><button name="create" type="button">Create</button> <a href="#close">Close</a></p>';\r
+               \r
+               var box = new Element('div', {\r
+                       'class': 'popup_wrapper', \r
+                       'html': html\r
+               });\r
+               \r
+               p.open({\r
+                       'content': box\r
+               });\r
+               \r
+               // bind popup events\r
+               $$('button[name=create]').addEvent('click', add_field);\r
+               $$('a[href$=#close]').addEvent('click', function() {\r
+                       p.close();\r
+                       return false;\r
+               });\r
+               \r
+               return false;\r
+       };\r
+\r
+       // bind create method\r
+       a.addEvent('click', show_add_field);\r
+}());\r
+\r
diff --git a/testcms-final-anon/system/admin/theme/assets/js/helpers.js b/testcms-final-anon/system/admin/theme/assets/js/helpers.js
new file mode 100644 (file)
index 0000000..2407e5c
--- /dev/null
@@ -0,0 +1,25 @@
+function formatSlug(slug, output) {\r
+       var val = slug.get('value');\r
+\r
+       // replace spaces\r
+       val = val.replace(/\s+/, '-');\r
+\r
+       // replace crazy characters\r
+       val = val.replace(/[^0-9a-z\-]/i, '');\r
+       \r
+       // convert to lower case \r
+       val = val.toLowerCase();\r
+\r
+       output.set('html', (val.length ? val : 'slug'));\r
+       slug.set('value', val);\r
+}\r
+\r
+function formatTwitter(tweet, output) {\r
+       var val = tweet.get('value');\r
+\r
+       // replace crazy characters\r
+       val = val.replace(/[^0-9a-z\_]/i, '');\r
+\r
+       output.set('html', (val.length ? val : 'example'));\r
+       tweet.set('value', val);\r
+}\r
diff --git a/testcms-final-anon/system/admin/theme/assets/js/mootools.js b/testcms-final-anon/system/admin/theme/assets/js/mootools.js
new file mode 100644 (file)
index 0000000..1313a50
--- /dev/null
@@ -0,0 +1,515 @@
+/*\r
+---\r
+MooTools: the javascript framework\r
+\r
+web build:\r
+ - http://mootools.net/core/76bf47062d6c1983d66ce47ad66aa0e0\r
+\r
+packager build:\r
+ - packager build Core/Core Core/Array Core/String Core/Number Core/Function Core/Object Core/Event Core/Browser Core/Class Core/Class.Extras Core/Slick.Parser Core/Slick.Finder Core/Element Core/Element.Style Core/Element.Event Core/Element.Delegation Core/Element.Dimensions Core/Fx Core/Fx.CSS Core/Fx.Tween Core/Fx.Morph Core/Fx.Transitions Core/Request Core/Request.HTML Core/Request.JSON Core/Cookie Core/JSON Core/DOMReady Core/Swiff\r
+\r
+copyrights:\r
+  - [MooTools](http://mootools.net)\r
+\r
+licenses:\r
+  - [MIT License](http://mootools.net/license.txt)\r
+...\r
+*/\r
+(function(){this.MooTools={version:"1.4.1",build:"d1fb25710e3c5482a219ab9dc675a4e0ad2176b6"};var e=this.typeOf=function(i){if(i==null){return"null";}if(i.$family){return i.$family();\r
+}if(i.nodeName){if(i.nodeType==1){return"element";}if(i.nodeType==3){return(/\S/).test(i.nodeValue)?"textnode":"whitespace";}}else{if(typeof i.length=="number"){if(i.callee){return"arguments";\r
+}if("item" in i){return"collection";}}}return typeof i;};var u=this.instanceOf=function(w,i){if(w==null){return false;}var v=w.$constructor||w.constructor;\r
+while(v){if(v===i){return true;}v=v.parent;}return w instanceof i;};var f=this.Function;var r=true;for(var q in {toString:1}){r=null;}if(r){r=["hasOwnProperty","valueOf","isPrototypeOf","propertyIsEnumerable","toLocaleString","toString","constructor"];\r
+}f.prototype.overloadSetter=function(v){var i=this;return function(x,w){if(x==null){return this;}if(v||typeof x!="string"){for(var y in x){i.call(this,y,x[y]);\r
+}if(r){for(var z=r.length;z--;){y=r[z];if(x.hasOwnProperty(y)){i.call(this,y,x[y]);}}}}else{i.call(this,x,w);}return this;};};f.prototype.overloadGetter=function(v){var i=this;\r
+return function(x){var y,w;if(v||typeof x!="string"){y=x;}else{if(arguments.length>1){y=arguments;}}if(y){w={};for(var z=0;z<y.length;z++){w[y[z]]=i.call(this,y[z]);\r
+}}else{w=i.call(this,x);}return w;};};f.prototype.extend=function(i,v){this[i]=v;}.overloadSetter();f.prototype.implement=function(i,v){this.prototype[i]=v;\r
+}.overloadSetter();var o=Array.prototype.slice;f.from=function(i){return(e(i)=="function")?i:function(){return i;};};Array.from=function(i){if(i==null){return[];\r
+}return(k.isEnumerable(i)&&typeof i!="string")?(e(i)=="array")?i:o.call(i):[i];};Number.from=function(v){var i=parseFloat(v);return isFinite(i)?i:null;\r
+};String.from=function(i){return i+"";};f.implement({hide:function(){this.$hidden=true;return this;},protect:function(){this.$protected=true;return this;\r
+}});var k=this.Type=function(x,w){if(x){var v=x.toLowerCase();var i=function(y){return(e(y)==v);};k["is"+x]=i;if(w!=null){w.prototype.$family=(function(){return v;\r
+}).hide();w.type=i;}}if(w==null){return null;}w.extend(this);w.$constructor=k;w.prototype.$constructor=w;return w;};var p=Object.prototype.toString;k.isEnumerable=function(i){return(i!=null&&typeof i.length=="number"&&p.call(i)!="[object Function]");\r
+};var b={};var d=function(i){var v=e(i.prototype);return b[v]||(b[v]=[]);};var h=function(w,A){if(A&&A.$hidden){return;}var v=d(this);for(var x=0;x<v.length;\r
+x++){var z=v[x];if(e(z)=="type"){h.call(z,w,A);}else{z.call(this,w,A);}}var y=this.prototype[w];if(y==null||!y.$protected){this.prototype[w]=A;}if(this[w]==null&&e(A)=="function"){t.call(this,w,function(i){return A.apply(i,o.call(arguments,1));\r
+});}};var t=function(i,w){if(w&&w.$hidden){return;}var v=this[i];if(v==null||!v.$protected){this[i]=w;}};k.implement({implement:h.overloadSetter(),extend:t.overloadSetter(),alias:function(i,v){h.call(this,i,this.prototype[v]);\r
+}.overloadSetter(),mirror:function(i){d(this).push(i);return this;}});new k("Type",k);var c=function(v,z,x){var w=(z!=Object),D=z.prototype;if(w){z=new k(v,z);\r
+}for(var A=0,y=x.length;A<y;A++){var E=x[A],C=z[E],B=D[E];if(C){C.protect();}if(w&&B){delete D[E];D[E]=B.protect();}}if(w){z.implement(D);}return c;};c("String",String,["charAt","charCodeAt","concat","indexOf","lastIndexOf","match","quote","replace","search","slice","split","substr","substring","trim","toLowerCase","toUpperCase"])("Array",Array,["pop","push","reverse","shift","sort","splice","unshift","concat","join","slice","indexOf","lastIndexOf","filter","forEach","every","map","some","reduce","reduceRight"])("Number",Number,["toExponential","toFixed","toLocaleString","toPrecision"])("Function",f,["apply","call","bind"])("RegExp",RegExp,["exec","test"])("Object",Object,["create","defineProperty","defineProperties","keys","getPrototypeOf","getOwnPropertyDescriptor","getOwnPropertyNames","preventExtensions","isExtensible","seal","isSealed","freeze","isFrozen"])("Date",Date,["now"]);\r
+Object.extend=t.overloadSetter();Date.extend("now",function(){return +(new Date);});new k("Boolean",Boolean);Number.prototype.$family=function(){return isFinite(this)?"number":"null";\r
+}.hide();Number.extend("random",function(v,i){return Math.floor(Math.random()*(i-v+1)+v);});var l=Object.prototype.hasOwnProperty;Object.extend("forEach",function(i,w,x){for(var v in i){if(l.call(i,v)){w.call(x,i[v],v,i);\r
+}}});Object.each=Object.forEach;Array.implement({forEach:function(x,y){for(var w=0,v=this.length;w<v;w++){if(w in this){x.call(y,this[w],w,this);}}},each:function(i,v){Array.forEach(this,i,v);\r
+return this;}});var s=function(i){switch(e(i)){case"array":return i.clone();case"object":return Object.clone(i);default:return i;}};Array.implement("clone",function(){var v=this.length,w=new Array(v);\r
+while(v--){w[v]=s(this[v]);}return w;});var a=function(v,i,w){switch(e(w)){case"object":if(e(v[i])=="object"){Object.merge(v[i],w);}else{v[i]=Object.clone(w);\r
+}break;case"array":v[i]=w.clone();break;default:v[i]=w;}return v;};Object.extend({merge:function(C,y,x){if(e(y)=="string"){return a(C,y,x);}for(var B=1,w=arguments.length;\r
+B<w;B++){var z=arguments[B];for(var A in z){a(C,A,z[A]);}}return C;},clone:function(i){var w={};for(var v in i){w[v]=s(i[v]);}return w;},append:function(z){for(var y=1,w=arguments.length;\r
+y<w;y++){var v=arguments[y]||{};for(var x in v){z[x]=v[x];}}return z;}});["Object","WhiteSpace","TextNode","Collection","Arguments"].each(function(i){new k(i);\r
+});var j=Date.now();String.extend("uniqueID",function(){return(j++).toString(36);});var g=this.Hash=new k("Hash",function(i){if(e(i)=="hash"){i=Object.clone(i.getClean());\r
+}for(var v in i){this[v]=i[v];}return this;});g.implement({forEach:function(i,v){Object.forEach(this,i,v);},getClean:function(){var v={};for(var i in this){if(this.hasOwnProperty(i)){v[i]=this[i];\r
+}}return v;},getLength:function(){var v=0;for(var i in this){if(this.hasOwnProperty(i)){v++;}}return v;}});g.alias("each","forEach");Object.type=k.isObject;\r
+var n=this.Native=function(i){return new k(i.name,i.initialize);};n.type=k.type;n.implement=function(x,v){for(var w=0;w<x.length;w++){x[w].implement(v);\r
+}return n;};var m=Array.type;Array.type=function(i){return u(i,Array)||m(i);};this.$A=function(i){return Array.from(i).slice();};this.$arguments=function(v){return function(){return arguments[v];\r
+};};this.$chk=function(i){return !!(i||i===0);};this.$clear=function(i){clearTimeout(i);clearInterval(i);return null;};this.$defined=function(i){return(i!=null);\r
+};this.$each=function(w,v,x){var i=e(w);((i=="arguments"||i=="collection"||i=="array"||i=="elements")?Array:Object).each(w,v,x);};this.$empty=function(){};\r
+this.$extend=function(v,i){return Object.append(v,i);};this.$H=function(i){return new g(i);};this.$merge=function(){var i=Array.slice(arguments);i.unshift({});\r
+return Object.merge.apply(null,i);};this.$lambda=f.from;this.$mixin=Object.merge;this.$random=Number.random;this.$splat=Array.from;this.$time=Date.now;\r
+this.$type=function(i){var v=e(i);if(v=="elements"){return"array";}return(v=="null")?false:v;};this.$unlink=function(i){switch(e(i)){case"object":return Object.clone(i);\r
+case"array":return Array.clone(i);case"hash":return new g(i);default:return i;}};})();Array.implement({every:function(c,d){for(var b=0,a=this.length>>>0;\r
+b<a;b++){if((b in this)&&!c.call(d,this[b],b,this)){return false;}}return true;},filter:function(d,e){var c=[];for(var b=0,a=this.length>>>0;b<a;b++){if((b in this)&&d.call(e,this[b],b,this)){c.push(this[b]);\r
+}}return c;},indexOf:function(c,d){var b=this.length>>>0;for(var a=(d<0)?Math.max(0,b+d):d||0;a<b;a++){if(this[a]===c){return a;}}return -1;},map:function(c,e){var d=this.length>>>0,b=Array(d);\r
+for(var a=0;a<d;a++){if(a in this){b[a]=c.call(e,this[a],a,this);}}return b;},some:function(c,d){for(var b=0,a=this.length>>>0;b<a;b++){if((b in this)&&c.call(d,this[b],b,this)){return true;\r
+}}return false;},clean:function(){return this.filter(function(a){return a!=null;});},invoke:function(a){var b=Array.slice(arguments,1);return this.map(function(c){return c[a].apply(c,b);\r
+});},associate:function(c){var d={},b=Math.min(this.length,c.length);for(var a=0;a<b;a++){d[c[a]]=this[a];}return d;},link:function(c){var a={};for(var e=0,b=this.length;\r
+e<b;e++){for(var d in c){if(c[d](this[e])){a[d]=this[e];delete c[d];break;}}}return a;},contains:function(a,b){return this.indexOf(a,b)!=-1;},append:function(a){this.push.apply(this,a);\r
+return this;},getLast:function(){return(this.length)?this[this.length-1]:null;},getRandom:function(){return(this.length)?this[Number.random(0,this.length-1)]:null;\r
+},include:function(a){if(!this.contains(a)){this.push(a);}return this;},combine:function(c){for(var b=0,a=c.length;b<a;b++){this.include(c[b]);}return this;\r
+},erase:function(b){for(var a=this.length;a--;){if(this[a]===b){this.splice(a,1);}}return this;},empty:function(){this.length=0;return this;},flatten:function(){var d=[];\r
+for(var b=0,a=this.length;b<a;b++){var c=typeOf(this[b]);if(c=="null"){continue;}d=d.concat((c=="array"||c=="collection"||c=="arguments"||instanceOf(this[b],Array))?Array.flatten(this[b]):this[b]);\r
+}return d;},pick:function(){for(var b=0,a=this.length;b<a;b++){if(this[b]!=null){return this[b];}}return null;},hexToRgb:function(b){if(this.length!=3){return null;\r
+}var a=this.map(function(c){if(c.length==1){c+=c;}return c.toInt(16);});return(b)?a:"rgb("+a+")";},rgbToHex:function(d){if(this.length<3){return null;}if(this.length==4&&this[3]==0&&!d){return"transparent";\r
+}var b=[];for(var a=0;a<3;a++){var c=(this[a]-0).toString(16);b.push((c.length==1)?"0"+c:c);}return(d)?b:"#"+b.join("");}});Array.alias("extend","append");\r
+var $pick=function(){return Array.from(arguments).pick();};String.implement({test:function(a,b){return((typeOf(a)=="regexp")?a:new RegExp(""+a,b)).test(this);\r
+},contains:function(a,b){return(b)?(b+this+b).indexOf(b+a+b)>-1:String(this).indexOf(a)>-1;},trim:function(){return String(this).replace(/^\s+|\s+$/g,"");\r
+},clean:function(){return String(this).replace(/\s+/g," ").trim();},camelCase:function(){return String(this).replace(/-\D/g,function(a){return a.charAt(1).toUpperCase();\r
+});},hyphenate:function(){return String(this).replace(/[A-Z]/g,function(a){return("-"+a.charAt(0).toLowerCase());});},capitalize:function(){return String(this).replace(/\b[a-z]/g,function(a){return a.toUpperCase();\r
+});},escapeRegExp:function(){return String(this).replace(/([-.*+?^${}()|[\]\/\\])/g,"\\$1");},toInt:function(a){return parseInt(this,a||10);},toFloat:function(){return parseFloat(this);\r
+},hexToRgb:function(b){var a=String(this).match(/^#?(\w{1,2})(\w{1,2})(\w{1,2})$/);return(a)?a.slice(1).hexToRgb(b):null;},rgbToHex:function(b){var a=String(this).match(/\d{1,3}/g);\r
+return(a)?a.rgbToHex(b):null;},substitute:function(a,b){return String(this).replace(b||(/\\?\{([^{}]+)\}/g),function(d,c){if(d.charAt(0)=="\\"){return d.slice(1);\r
+}return(a[c]!=null)?a[c]:"";});}});Number.implement({limit:function(b,a){return Math.min(a,Math.max(b,this));},round:function(a){a=Math.pow(10,a||0).toFixed(a<0?-a:0);\r
+return Math.round(this*a)/a;},times:function(b,c){for(var a=0;a<this;a++){b.call(c,a,this);}},toFloat:function(){return parseFloat(this);},toInt:function(a){return parseInt(this,a||10);\r
+}});Number.alias("each","times");(function(b){var a={};b.each(function(c){if(!Number[c]){a[c]=function(){return Math[c].apply(null,[this].concat(Array.from(arguments)));\r
+};}});Number.implement(a);})(["abs","acos","asin","atan","atan2","ceil","cos","exp","floor","log","max","min","pow","sin","sqrt","tan"]);Function.extend({attempt:function(){for(var b=0,a=arguments.length;\r
+b<a;b++){try{return arguments[b]();}catch(c){}}return null;}});Function.implement({attempt:function(a,c){try{return this.apply(c,Array.from(a));}catch(b){}return null;\r
+},bind:function(e){var a=this,b=arguments.length>1?Array.slice(arguments,1):null,d=function(){};var c=function(){var g=e,h=arguments.length;if(this instanceof c){d.prototype=a.prototype;\r
+g=new d;}var f=(!b&&!h)?a.call(g):a.apply(g,b&&h?b.concat(Array.slice(arguments)):b||arguments);return g==e?f:g;};return c;},pass:function(b,c){var a=this;\r
+if(b!=null){b=Array.from(b);}return function(){return a.apply(c,b||arguments);};},delay:function(b,c,a){return setTimeout(this.pass((a==null?[]:a),c),b);\r
+},periodical:function(c,b,a){return setInterval(this.pass((a==null?[]:a),b),c);}});delete Function.prototype.bind;Function.implement({create:function(b){var a=this;\r
+b=b||{};return function(d){var c=b.arguments;c=(c!=null)?Array.from(c):Array.slice(arguments,(b.event)?1:0);if(b.event){c=[d||window.event].extend(c);}var e=function(){return a.apply(b.bind||null,c);\r
+};if(b.delay){return setTimeout(e,b.delay);}if(b.periodical){return setInterval(e,b.periodical);}if(b.attempt){return Function.attempt(e);}return e();};\r
+},bind:function(c,b){var a=this;if(b!=null){b=Array.from(b);}return function(){return a.apply(c,b||arguments);};},bindWithEvent:function(c,b){var a=this;\r
+if(b!=null){b=Array.from(b);}return function(d){return a.apply(c,(b==null)?arguments:[d].concat(b));};},run:function(a,b){return this.apply(b,Array.from(a));\r
+}});if(Object.create==Function.prototype.create){Object.create=null;}var $try=Function.attempt;(function(){var a=Object.prototype.hasOwnProperty;Object.extend({subset:function(d,g){var f={};\r
+for(var e=0,b=g.length;e<b;e++){var c=g[e];if(c in d){f[c]=d[c];}}return f;},map:function(b,e,f){var d={};for(var c in b){if(a.call(b,c)){d[c]=e.call(f,b[c],c,b);\r
+}}return d;},filter:function(b,e,g){var d={};for(var c in b){var f=b[c];if(a.call(b,c)&&e.call(g,f,c,b)){d[c]=f;}}return d;},every:function(b,d,e){for(var c in b){if(a.call(b,c)&&!d.call(e,b[c],c)){return false;\r
+}}return true;},some:function(b,d,e){for(var c in b){if(a.call(b,c)&&d.call(e,b[c],c)){return true;}}return false;},keys:function(b){var d=[];for(var c in b){if(a.call(b,c)){d.push(c);\r
+}}return d;},values:function(c){var b=[];for(var d in c){if(a.call(c,d)){b.push(c[d]);}}return b;},getLength:function(b){return Object.keys(b).length;},keyOf:function(b,d){for(var c in b){if(a.call(b,c)&&b[c]===d){return c;\r
+}}return null;},contains:function(b,c){return Object.keyOf(b,c)!=null;},toQueryString:function(b,c){var d=[];Object.each(b,function(h,g){if(c){g=c+"["+g+"]";\r
+}var f;switch(typeOf(h)){case"object":f=Object.toQueryString(h,g);break;case"array":var e={};h.each(function(k,j){e[j]=k;});f=Object.toQueryString(e,g);\r
+break;default:f=g+"="+encodeURIComponent(h);}if(h!=null){d.push(f);}});return d.join("&");}});})();Hash.implement({has:Object.prototype.hasOwnProperty,keyOf:function(a){return Object.keyOf(this,a);\r
+},hasValue:function(a){return Object.contains(this,a);},extend:function(a){Hash.each(a||{},function(c,b){Hash.set(this,b,c);},this);return this;},combine:function(a){Hash.each(a||{},function(c,b){Hash.include(this,b,c);\r
+},this);return this;},erase:function(a){if(this.hasOwnProperty(a)){delete this[a];}return this;},get:function(a){return(this.hasOwnProperty(a))?this[a]:null;\r
+},set:function(a,b){if(!this[a]||this.hasOwnProperty(a)){this[a]=b;}return this;},empty:function(){Hash.each(this,function(b,a){delete this[a];},this);\r
+return this;},include:function(a,b){if(this[a]==null){this[a]=b;}return this;},map:function(a,b){return new Hash(Object.map(this,a,b));},filter:function(a,b){return new Hash(Object.filter(this,a,b));\r
+},every:function(a,b){return Object.every(this,a,b);},some:function(a,b){return Object.some(this,a,b);},getKeys:function(){return Object.keys(this);},getValues:function(){return Object.values(this);\r
+},toQueryString:function(a){return Object.toQueryString(this,a);}});Hash.extend=Object.append;Hash.alias({indexOf:"keyOf",contains:"hasValue"});(function(){var l=this.document;\r
+var j=l.window=this;var b=1;this.$uid=(j.ActiveXObject)?function(e){return(e.uid||(e.uid=[b++]))[0];}:function(e){return e.uid||(e.uid=b++);};$uid(j);$uid(l);\r
+var a=navigator.userAgent.toLowerCase(),c=navigator.platform.toLowerCase(),k=a.match(/(opera|ie|firefox|chrome|version)[\s\/:]([\w\d\.]+)?.*?(safari|version[\s\/:]([\w\d\.]+)|$)/)||[null,"unknown",0],g=k[1]=="ie"&&l.documentMode;\r
+var p=this.Browser={extend:Function.prototype.extend,name:(k[1]=="version")?k[3]:k[1],version:g||parseFloat((k[1]=="opera"&&k[4])?k[4]:k[2]),Platform:{name:a.match(/ip(?:ad|od|hone)/)?"ios":(a.match(/(?:webos|android)/)||c.match(/mac|win|linux/)||["other"])[0]},Features:{xpath:!!(l.evaluate),air:!!(j.runtime),query:!!(l.querySelector),json:!!(j.JSON)},Plugins:{}};\r
+p[p.name]=true;p[p.name+parseInt(p.version,10)]=true;p.Platform[p.Platform.name]=true;p.Request=(function(){var r=function(){return new XMLHttpRequest();\r
+};var q=function(){return new ActiveXObject("MSXML2.XMLHTTP");};var e=function(){return new ActiveXObject("Microsoft.XMLHTTP");};return Function.attempt(function(){r();\r
+return r;},function(){q();return q;},function(){e();return e;});})();p.Features.xhr=!!(p.Request);var i=(Function.attempt(function(){return navigator.plugins["Shockwave Flash"].description;\r
+},function(){return new ActiveXObject("ShockwaveFlash.ShockwaveFlash").GetVariable("$version");})||"0 r0").match(/\d+/g);p.Plugins.Flash={version:Number(i[0]||"0."+i[1])||0,build:Number(i[2])||0};\r
+p.exec=function(q){if(!q){return q;}if(j.execScript){j.execScript(q);}else{var e=l.createElement("script");e.setAttribute("type","text/javascript");e.text=q;\r
+l.head.appendChild(e);l.head.removeChild(e);}return q;};String.implement("stripScripts",function(q){var e="";var r=this.replace(/<script[^>]*>([\s\S]*?)<\/script>/gi,function(s,t){e+=t+"\n";\r
+return"";});if(q===true){p.exec(e);}else{if(typeOf(q)=="function"){q(e,r);}}return r;});p.extend({Document:this.Document,Window:this.Window,Element:this.Element,Event:this.Event});\r
+this.Window=this.$constructor=new Type("Window",function(){});this.$family=Function.from("window").hide();Window.mirror(function(e,q){j[e]=q;});this.Document=l.$constructor=new Type("Document",function(){});\r
+l.$family=Function.from("document").hide();Document.mirror(function(e,q){l[e]=q;});l.html=l.documentElement;if(!l.head){l.head=l.getElementsByTagName("head")[0];\r
+}if(l.execCommand){try{l.execCommand("BackgroundImageCache",false,true);}catch(h){}}if(this.attachEvent&&!this.addEventListener){var d=function(){this.detachEvent("onunload",d);\r
+l.head=l.html=l.window=null;};this.attachEvent("onunload",d);}var n=Array.from;try{n(l.html.childNodes);}catch(h){Array.from=function(q){if(typeof q!="string"&&Type.isEnumerable(q)&&typeOf(q)!="array"){var e=q.length,r=new Array(e);\r
+while(e--){r[e]=q[e];}return r;}return n(q);};var m=Array.prototype,o=m.slice;["pop","push","reverse","shift","sort","splice","unshift","concat","join","slice"].each(function(e){var q=m[e];\r
+Array[e]=function(r){return q.apply(Array.from(r),o.call(arguments,1));};});}if(p.Platform.ios){p.Platform.ipod=true;}p.Engine={};var f=function(q,e){p.Engine.name=q;\r
+p.Engine[q+e]=true;p.Engine.version=e;};if(p.ie){p.Engine.trident=true;switch(p.version){case 6:f("trident",4);break;case 7:f("trident",5);break;case 8:f("trident",6);\r
+}}if(p.firefox){p.Engine.gecko=true;if(p.version>=3){f("gecko",19);}else{f("gecko",18);}}if(p.safari||p.chrome){p.Engine.webkit=true;switch(p.version){case 2:f("webkit",419);\r
+break;case 3:f("webkit",420);break;case 4:f("webkit",525);}}if(p.opera){p.Engine.presto=true;if(p.version>=9.6){f("presto",960);}else{if(p.version>=9.5){f("presto",950);\r
+}else{f("presto",925);}}}if(p.name=="unknown"){switch((a.match(/(?:webkit|khtml|gecko)/)||[])[0]){case"webkit":case"khtml":p.Engine.webkit=true;break;case"gecko":p.Engine.gecko=true;\r
+}}this.$exec=p.exec;})();(function(){var b={};var a=this.DOMEvent=new Type("DOMEvent",function(c,g){if(!g){g=window;}c=c||g.event;if(c.$extended){return c;\r
+}this.event=c;this.$extended=true;this.shift=c.shiftKey;this.control=c.ctrlKey;this.alt=c.altKey;this.meta=c.metaKey;var i=this.type=c.type;var h=c.target||c.srcElement;\r
+while(h&&h.nodeType==3){h=h.parentNode;}this.target=document.id(h);if(i.indexOf("key")==0){var d=this.code=(c.which||c.keyCode);this.key=b[d]||Object.keyOf(Event.Keys,d);\r
+if(i=="keydown"){if(d>111&&d<124){this.key="f"+(d-111);}else{if(d>95&&d<106){this.key=d-96;}}}if(this.key==null){this.key=String.fromCharCode(d).toLowerCase();\r
+}}else{if(i=="click"||i=="dblclick"||i=="contextmenu"||i=="DOMMouseScroll"||i.indexOf("mouse")==0){var j=g.document;j=(!j.compatMode||j.compatMode=="CSS1Compat")?j.html:j.body;\r
+this.page={x:(c.pageX!=null)?c.pageX:c.clientX+j.scrollLeft,y:(c.pageY!=null)?c.pageY:c.clientY+j.scrollTop};this.client={x:(c.pageX!=null)?c.pageX-g.pageXOffset:c.clientX,y:(c.pageY!=null)?c.pageY-g.pageYOffset:c.clientY};\r
+if(i=="DOMMouseScroll"||i=="mousewheel"){this.wheel=(c.wheelDelta)?c.wheelDelta/120:-(c.detail||0)/3;}this.rightClick=(c.which==3||c.button==2);if(i=="mouseover"||i=="mouseout"){var k=c.relatedTarget||c[(i=="mouseover"?"from":"to")+"Element"];\r
+while(k&&k.nodeType==3){k=k.parentNode;}this.relatedTarget=document.id(k);}}else{if(i.indexOf("touch")==0||i.indexOf("gesture")==0){this.rotation=c.rotation;\r
+this.scale=c.scale;this.targetTouches=c.targetTouches;this.changedTouches=c.changedTouches;var f=this.touches=c.touches;if(f&&f[0]){var e=f[0];this.page={x:e.pageX,y:e.pageY};\r
+this.client={x:e.clientX,y:e.clientY};}}}}if(!this.client){this.client={};}if(!this.page){this.page={};}});a.implement({stop:function(){return this.preventDefault().stopPropagation();\r
+},stopPropagation:function(){if(this.event.stopPropagation){this.event.stopPropagation();}else{this.event.cancelBubble=true;}return this;},preventDefault:function(){if(this.event.preventDefault){this.event.preventDefault();\r
+}else{this.event.returnValue=false;}return this;}});a.defineKey=function(d,c){b[d]=c;return this;};a.defineKeys=a.defineKey.overloadSetter(true);a.defineKeys({"38":"up","40":"down","37":"left","39":"right","27":"esc","32":"space","8":"backspace","9":"tab","46":"delete","13":"enter"});\r
+})();var Event=DOMEvent;Event.Keys={};Event.Keys=new Hash(Event.Keys);(function(){var a=this.Class=new Type("Class",function(h){if(instanceOf(h,Function)){h={initialize:h};\r
+}var g=function(){e(this);if(g.$prototyping){return this;}this.$caller=null;var i=(this.initialize)?this.initialize.apply(this,arguments):this;this.$caller=this.caller=null;\r
+return i;}.extend(this).implement(h);g.$constructor=a;g.prototype.$constructor=g;g.prototype.parent=c;return g;});var c=function(){if(!this.$caller){throw new Error('The method "parent" cannot be called.');\r
+}var g=this.$caller.$name,h=this.$caller.$owner.parent,i=(h)?h.prototype[g]:null;if(!i){throw new Error('The method "'+g+'" has no parent.');}return i.apply(this,arguments);\r
+};var e=function(g){for(var h in g){var j=g[h];switch(typeOf(j)){case"object":var i=function(){};i.prototype=j;g[h]=e(new i);break;case"array":g[h]=j.clone();\r
+break;}}return g;};var b=function(g,h,j){if(j.$origin){j=j.$origin;}var i=function(){if(j.$protected&&this.$caller==null){throw new Error('The method "'+h+'" cannot be called.');\r
+}var l=this.caller,m=this.$caller;this.caller=m;this.$caller=i;var k=j.apply(this,arguments);this.$caller=m;this.caller=l;return k;}.extend({$owner:g,$origin:j,$name:h});\r
+return i;};var f=function(h,i,g){if(a.Mutators.hasOwnProperty(h)){i=a.Mutators[h].call(this,i);if(i==null){return this;}}if(typeOf(i)=="function"){if(i.$hidden){return this;\r
+}this.prototype[h]=(g)?i:b(this,h,i);}else{Object.merge(this.prototype,h,i);}return this;};var d=function(g){g.$prototyping=true;var h=new g;delete g.$prototyping;\r
+return h;};a.implement("implement",f.overloadSetter());a.Mutators={Extends:function(g){this.parent=g;this.prototype=d(g);},Implements:function(g){Array.from(g).each(function(j){var h=new j;\r
+for(var i in h){f.call(this,i,h[i],true);}},this);}};})();(function(){this.Chain=new Class({$chain:[],chain:function(){this.$chain.append(Array.flatten(arguments));\r
+return this;},callChain:function(){return(this.$chain.length)?this.$chain.shift().apply(this,arguments):false;},clearChain:function(){this.$chain.empty();\r
+return this;}});var a=function(b){return b.replace(/^on([A-Z])/,function(c,d){return d.toLowerCase();});};this.Events=new Class({$events:{},addEvent:function(d,c,b){d=a(d);\r
+if(c==$empty){return this;}this.$events[d]=(this.$events[d]||[]).include(c);if(b){c.internal=true;}return this;},addEvents:function(b){for(var c in b){this.addEvent(c,b[c]);\r
+}return this;},fireEvent:function(e,c,b){e=a(e);var d=this.$events[e];if(!d){return this;}c=Array.from(c);d.each(function(f){if(b){f.delay(b,this,c);}else{f.apply(this,c);\r
+}},this);return this;},removeEvent:function(e,d){e=a(e);var c=this.$events[e];if(c&&!d.internal){var b=c.indexOf(d);if(b!=-1){delete c[b];}}return this;\r
+},removeEvents:function(d){var e;if(typeOf(d)=="object"){for(e in d){this.removeEvent(e,d[e]);}return this;}if(d){d=a(d);}for(e in this.$events){if(d&&d!=e){continue;\r
+}var c=this.$events[e];for(var b=c.length;b--;){if(b in c){this.removeEvent(e,c[b]);}}}return this;}});this.Options=new Class({setOptions:function(){var b=this.options=Object.merge.apply(null,[{},this.options].append(arguments));\r
+if(this.addEvent){for(var c in b){if(typeOf(b[c])!="function"||!(/^on[A-Z]/).test(c)){continue;}this.addEvent(c,b[c]);delete b[c];}}return this;}});})();\r
+(function(){var k,n,l,g,a={},c={},m=/\\/g;var e=function(q,p){if(q==null){return null;}if(q.Slick===true){return q;}q=(""+q).replace(/^\s+|\s+$/g,"");g=!!p;\r
+var o=(g)?c:a;if(o[q]){return o[q];}k={Slick:true,expressions:[],raw:q,reverse:function(){return e(this.raw,true);}};n=-1;while(q!=(q=q.replace(j,b))){}k.length=k.expressions.length;\r
+return o[k.raw]=(g)?h(k):k;};var i=function(o){if(o==="!"){return" ";}else{if(o===" "){return"!";}else{if((/^!/).test(o)){return o.replace(/^!/,"");}else{return"!"+o;\r
+}}}};var h=function(u){var r=u.expressions;for(var p=0;p<r.length;p++){var t=r[p];var q={parts:[],tag:"*",combinator:i(t[0].combinator)};for(var o=0;o<t.length;\r
+o++){var s=t[o];if(!s.reverseCombinator){s.reverseCombinator=" ";}s.combinator=s.reverseCombinator;delete s.reverseCombinator;}t.reverse().push(q);}return u;\r
+};var f=function(o){return o.replace(/[-[\]{}()*+?.\\^$|,#\s]/g,function(p){return"\\"+p;});};var j=new RegExp("^(?:\\s*(,)\\s*|\\s*(<combinator>+)\\s*|(\\s+)|(<unicode>+|\\*)|\\#(<unicode>+)|\\.(<unicode>+)|\\[\\s*(<unicode1>+)(?:\\s*([*^$!~|]?=)(?:\\s*(?:([\"']?)(.*?)\\9)))?\\s*\\](?!\\])|(:+)(<unicode>+)(?:\\((?:(?:([\"'])([^\\13]*)\\13)|((?:\\([^)]+\\)|[^()]*)+))\\))?)".replace(/<combinator>/,"["+f(">+~`!@$%^&={}\\;</")+"]").replace(/<unicode>/g,"(?:[\\w\\u00a1-\\uFFFF-]|\\\\[^\\s0-9a-f])").replace(/<unicode1>/g,"(?:[:\\w\\u00a1-\\uFFFF-]|\\\\[^\\s0-9a-f])"));\r
+function b(x,s,D,z,r,C,q,B,A,y,u,F,G,v,p,w){if(s||n===-1){k.expressions[++n]=[];l=-1;if(s){return"";}}if(D||z||l===-1){D=D||" ";var t=k.expressions[n];\r
+if(g&&t[l]){t[l].reverseCombinator=i(D);}t[++l]={combinator:D,tag:"*"};}var o=k.expressions[n][l];if(r){o.tag=r.replace(m,"");}else{if(C){o.id=C.replace(m,"");\r
+}else{if(q){q=q.replace(m,"");if(!o.classList){o.classList=[];}if(!o.classes){o.classes=[];}o.classList.push(q);o.classes.push({value:q,regexp:new RegExp("(^|\\s)"+f(q)+"(\\s|$)")});\r
+}else{if(G){w=w||p;w=w?w.replace(m,""):null;if(!o.pseudos){o.pseudos=[];}o.pseudos.push({key:G.replace(m,""),value:w,type:F.length==1?"class":"element"});\r
+}else{if(B){B=B.replace(m,"");u=(u||"").replace(m,"");var E,H;switch(A){case"^=":H=new RegExp("^"+f(u));break;case"$=":H=new RegExp(f(u)+"$");break;case"~=":H=new RegExp("(^|\\s)"+f(u)+"(\\s|$)");\r
+break;case"|=":H=new RegExp("^"+f(u)+"(-|$)");break;case"=":E=function(I){return u==I;};break;case"*=":E=function(I){return I&&I.indexOf(u)>-1;};break;\r
+case"!=":E=function(I){return u!=I;};break;default:E=function(I){return !!I;};}if(u==""&&(/^[*$^]=$/).test(A)){E=function(){return false;};}if(!E){E=function(I){return I&&H.test(I);\r
+};}if(!o.attributes){o.attributes=[];}o.attributes.push({key:B,operator:A,value:u,test:E});}}}}}return"";}var d=(this.Slick||{});d.parse=function(o){return e(o);\r
+};d.escapeRegExp=f;if(!this.Slick){this.Slick=d;}}).apply((typeof exports!="undefined")?exports:this);(function(){var k={},m={},d=Object.prototype.toString;\r
+k.isNativeCode=function(c){return(/\{\s*\[native code\]\s*\}/).test(""+c);};k.isXML=function(c){return(!!c.xmlVersion)||(!!c.xml)||(d.call(c)=="[object XMLDocument]")||(c.nodeType==9&&c.documentElement.nodeName!="HTML");\r
+};k.setDocument=function(x){var u=x.nodeType;if(u==9){}else{if(u){x=x.ownerDocument;}else{if(x.navigator){x=x.document;}else{return;}}}if(this.document===x){return;\r
+}this.document=x;var z=x.documentElement,v=this.getUIDXML(z),p=m[v],B;if(p){for(B in p){this[B]=p[B];}return;}p=m[v]={};p.root=z;p.isXMLDocument=this.isXML(x);\r
+p.brokenStarGEBTN=p.starSelectsClosedQSA=p.idGetsName=p.brokenMixedCaseQSA=p.brokenGEBCN=p.brokenCheckedQSA=p.brokenEmptyAttributeQSA=p.isHTMLDocument=p.nativeMatchesSelector=false;\r
+var n,o,y,r,s;var t,c="slick_uniqueid";var A=x.createElement("div");var q=x.body||x.getElementsByTagName("body")[0]||z;q.appendChild(A);try{A.innerHTML='<a id="'+c+'"></a>';\r
+p.isHTMLDocument=!!x.getElementById(c);}catch(w){}if(p.isHTMLDocument){A.style.display="none";A.appendChild(x.createComment(""));o=(A.getElementsByTagName("*").length>1);\r
+try{A.innerHTML="foo</foo>";t=A.getElementsByTagName("*");n=(t&&!!t.length&&t[0].nodeName.charAt(0)=="/");}catch(w){}p.brokenStarGEBTN=o||n;try{A.innerHTML='<a name="'+c+'"></a><b id="'+c+'"></b>';\r
+p.idGetsName=x.getElementById(c)===A.firstChild;}catch(w){}if(A.getElementsByClassName){try{A.innerHTML='<a class="f"></a><a class="b"></a>';A.getElementsByClassName("b").length;\r
+A.firstChild.className="b";r=(A.getElementsByClassName("b").length!=2);}catch(w){}try{A.innerHTML='<a class="a"></a><a class="f b a"></a>';y=(A.getElementsByClassName("a").length!=2);\r
+}catch(w){}p.brokenGEBCN=r||y;}if(A.querySelectorAll){try{A.innerHTML="foo</foo>";t=A.querySelectorAll("*");p.starSelectsClosedQSA=(t&&!!t.length&&t[0].nodeName.charAt(0)=="/");\r
+}catch(w){}try{A.innerHTML='<a class="MiX"></a>';p.brokenMixedCaseQSA=!A.querySelectorAll(".MiX").length;}catch(w){}try{A.innerHTML='<select><option selected="selected">a</option></select>';\r
+p.brokenCheckedQSA=(A.querySelectorAll(":checked").length==0);}catch(w){}try{A.innerHTML='<a class=""></a>';p.brokenEmptyAttributeQSA=(A.querySelectorAll('[class*=""]').length!=0);\r
+}catch(w){}}try{A.innerHTML='<form action="s"><input id="action"/></form>';s=(A.firstChild.getAttribute("action")!="s");}catch(w){}p.nativeMatchesSelector=z.matchesSelector||z.mozMatchesSelector||z.webkitMatchesSelector;\r
+if(p.nativeMatchesSelector){try{p.nativeMatchesSelector.call(z,":slick");p.nativeMatchesSelector=null;}catch(w){}}}try{z.slick_expando=1;delete z.slick_expando;\r
+p.getUID=this.getUIDHTML;}catch(w){p.getUID=this.getUIDXML;}q.removeChild(A);A=t=q=null;p.getAttribute=(p.isHTMLDocument&&s)?function(E,C){var F=this.attributeGetters[C];\r
+if(F){return F.call(E);}var D=E.getAttributeNode(C);return(D)?D.nodeValue:null;}:function(D,C){var E=this.attributeGetters[C];return(E)?E.call(D):D.getAttribute(C);\r
+};p.hasAttribute=(z&&this.isNativeCode(z.hasAttribute))?function(D,C){return D.hasAttribute(C);}:function(D,C){D=D.getAttributeNode(C);return !!(D&&(D.specified||D.nodeValue));\r
+};p.contains=(z&&this.isNativeCode(z.contains))?function(C,D){return C.contains(D);}:(z&&z.compareDocumentPosition)?function(C,D){return C===D||!!(C.compareDocumentPosition(D)&16);\r
+}:function(C,D){if(D){do{if(D===C){return true;}}while((D=D.parentNode));}return false;};p.documentSorter=(z.compareDocumentPosition)?function(D,C){if(!D.compareDocumentPosition||!C.compareDocumentPosition){return 0;\r
+}return D.compareDocumentPosition(C)&4?-1:D===C?0:1;}:("sourceIndex" in z)?function(D,C){if(!D.sourceIndex||!C.sourceIndex){return 0;}return D.sourceIndex-C.sourceIndex;\r
+}:(x.createRange)?function(F,D){if(!F.ownerDocument||!D.ownerDocument){return 0;}var E=F.ownerDocument.createRange(),C=D.ownerDocument.createRange();E.setStart(F,0);\r
+E.setEnd(F,0);C.setStart(D,0);C.setEnd(D,0);return E.compareBoundaryPoints(Range.START_TO_END,C);}:null;z=null;for(B in p){this[B]=p[B];}};var f=/^([#.]?)((?:[\w-]+|\*))$/,h=/\[.+[*$^]=(?:""|'')?\]/,g={};\r
+k.search=function(U,z,H,s){var p=this.found=(s)?null:(H||[]);if(!U){return p;}else{if(U.navigator){U=U.document;}else{if(!U.nodeType){return p;}}}var F,O,V=this.uniques={},I=!!(H&&H.length),y=(U.nodeType==9);\r
+if(this.document!==(y?U:U.ownerDocument)){this.setDocument(U);}if(I){for(O=p.length;O--;){V[this.getUID(p[O])]=true;}}if(typeof z=="string"){var r=z.match(f);\r
+simpleSelectors:if(r){var u=r[1],v=r[2],A,E;if(!u){if(v=="*"&&this.brokenStarGEBTN){break simpleSelectors;}E=U.getElementsByTagName(v);if(s){return E[0]||null;\r
+}for(O=0;A=E[O++];){if(!(I&&V[this.getUID(A)])){p.push(A);}}}else{if(u=="#"){if(!this.isHTMLDocument||!y){break simpleSelectors;}A=U.getElementById(v);\r
+if(!A){return p;}if(this.idGetsName&&A.getAttributeNode("id").nodeValue!=v){break simpleSelectors;}if(s){return A||null;}if(!(I&&V[this.getUID(A)])){p.push(A);\r
+}}else{if(u=="."){if(!this.isHTMLDocument||((!U.getElementsByClassName||this.brokenGEBCN)&&U.querySelectorAll)){break simpleSelectors;}if(U.getElementsByClassName&&!this.brokenGEBCN){E=U.getElementsByClassName(v);\r
+if(s){return E[0]||null;}for(O=0;A=E[O++];){if(!(I&&V[this.getUID(A)])){p.push(A);}}}else{var T=new RegExp("(^|\\s)"+e.escapeRegExp(v)+"(\\s|$)");E=U.getElementsByTagName("*");\r
+for(O=0;A=E[O++];){className=A.className;if(!(className&&T.test(className))){continue;}if(s){return A;}if(!(I&&V[this.getUID(A)])){p.push(A);}}}}}}if(I){this.sort(p);\r
+}return(s)?null:p;}querySelector:if(U.querySelectorAll){if(!this.isHTMLDocument||g[z]||this.brokenMixedCaseQSA||(this.brokenCheckedQSA&&z.indexOf(":checked")>-1)||(this.brokenEmptyAttributeQSA&&h.test(z))||(!y&&z.indexOf(",")>-1)||e.disableQSA){break querySelector;\r
+}var S=z,x=U;if(!y){var C=x.getAttribute("id"),t="slickid__";x.setAttribute("id",t);S="#"+t+" "+S;U=x.parentNode;}try{if(s){return U.querySelector(S)||null;\r
+}else{E=U.querySelectorAll(S);}}catch(Q){g[z]=1;break querySelector;}finally{if(!y){if(C){x.setAttribute("id",C);}else{x.removeAttribute("id");}U=x;}}if(this.starSelectsClosedQSA){for(O=0;\r
+A=E[O++];){if(A.nodeName>"@"&&!(I&&V[this.getUID(A)])){p.push(A);}}}else{for(O=0;A=E[O++];){if(!(I&&V[this.getUID(A)])){p.push(A);}}}if(I){this.sort(p);\r
+}return p;}F=this.Slick.parse(z);if(!F.length){return p;}}else{if(z==null){return p;}else{if(z.Slick){F=z;}else{if(this.contains(U.documentElement||U,z)){(p)?p.push(z):p=z;\r
+return p;}else{return p;}}}}this.posNTH={};this.posNTHLast={};this.posNTHType={};this.posNTHTypeLast={};this.push=(!I&&(s||(F.length==1&&F.expressions[0].length==1)))?this.pushArray:this.pushUID;\r
+if(p==null){p=[];}var M,L,K;var B,J,D,c,q,G,W;var N,P,o,w,R=F.expressions;search:for(O=0;(P=R[O]);O++){for(M=0;(o=P[M]);M++){B="combinator:"+o.combinator;\r
+if(!this[B]){continue search;}J=(this.isXMLDocument)?o.tag:o.tag.toUpperCase();D=o.id;c=o.classList;q=o.classes;G=o.attributes;W=o.pseudos;w=(M===(P.length-1));\r
+this.bitUniques={};if(w){this.uniques=V;this.found=p;}else{this.uniques={};this.found=[];}if(M===0){this[B](U,J,D,q,G,W,c);if(s&&w&&p.length){break search;\r
+}}else{if(s&&w){for(L=0,K=N.length;L<K;L++){this[B](N[L],J,D,q,G,W,c);if(p.length){break search;}}}else{for(L=0,K=N.length;L<K;L++){this[B](N[L],J,D,q,G,W,c);\r
+}}}N=this.found;}}if(I||(F.expressions.length>1)){this.sort(p);}return(s)?(p[0]||null):p;};k.uidx=1;k.uidk="slick-uniqueid";k.getUIDXML=function(n){var c=n.getAttribute(this.uidk);\r
+if(!c){c=this.uidx++;n.setAttribute(this.uidk,c);}return c;};k.getUIDHTML=function(c){return c.uniqueNumber||(c.uniqueNumber=this.uidx++);};k.sort=function(c){if(!this.documentSorter){return c;\r
+}c.sort(this.documentSorter);return c;};k.cacheNTH={};k.matchNTH=/^([+-]?\d*)?([a-z]+)?([+-]\d+)?$/;k.parseNTHArgument=function(q){var o=q.match(this.matchNTH);\r
+if(!o){return false;}var p=o[2]||false;var n=o[1]||1;if(n=="-"){n=-1;}var c=+o[3]||0;o=(p=="n")?{a:n,b:c}:(p=="odd")?{a:2,b:1}:(p=="even")?{a:2,b:0}:{a:0,b:n};\r
+return(this.cacheNTH[q]=o);};k.createNTHPseudo=function(p,n,c,o){return function(s,q){var u=this.getUID(s);if(!this[c][u]){var A=s.parentNode;if(!A){return false;\r
+}var r=A[p],t=1;if(o){var z=s.nodeName;do{if(r.nodeName!=z){continue;}this[c][this.getUID(r)]=t++;}while((r=r[n]));}else{do{if(r.nodeType!=1){continue;\r
+}this[c][this.getUID(r)]=t++;}while((r=r[n]));}}q=q||"n";var v=this.cacheNTH[q]||this.parseNTHArgument(q);if(!v){return false;}var y=v.a,x=v.b,w=this[c][u];\r
+if(y==0){return x==w;}if(y>0){if(w<x){return false;}}else{if(x<w){return false;}}return((w-x)%y)==0;};};k.pushArray=function(p,c,r,o,n,q){if(this.matchSelector(p,c,r,o,n,q)){this.found.push(p);\r
+}};k.pushUID=function(q,c,s,p,n,r){var o=this.getUID(q);if(!this.uniques[o]&&this.matchSelector(q,c,s,p,n,r)){this.uniques[o]=true;this.found.push(q);}};\r
+k.matchNode=function(n,o){if(this.isHTMLDocument&&this.nativeMatchesSelector){try{return this.nativeMatchesSelector.call(n,o.replace(/\[([^=]+)=\s*([^'"\]]+?)\s*\]/g,'[$1="$2"]'));\r
+}catch(u){}}var t=this.Slick.parse(o);if(!t){return true;}var r=t.expressions,s=0,q;for(q=0;(currentExpression=r[q]);q++){if(currentExpression.length==1){var p=currentExpression[0];\r
+if(this.matchSelector(n,(this.isXMLDocument)?p.tag:p.tag.toUpperCase(),p.id,p.classes,p.attributes,p.pseudos)){return true;}s++;}}if(s==t.length){return false;\r
+}var c=this.search(this.document,t),v;for(q=0;v=c[q++];){if(v===n){return true;}}return false;};k.matchPseudo=function(q,c,p){var n="pseudo:"+c;if(this[n]){return this[n](q,p);\r
+}var o=this.getAttribute(q,c);return(p)?p==o:!!o;};k.matchSelector=function(o,v,c,p,q,s){if(v){var t=(this.isXMLDocument)?o.nodeName:o.nodeName.toUpperCase();\r
+if(v=="*"){if(t<"@"){return false;}}else{if(t!=v){return false;}}}if(c&&o.getAttribute("id")!=c){return false;}var r,n,u;if(p){for(r=p.length;r--;){u=o.getAttribute("class")||o.className;\r
+if(!(u&&p[r].regexp.test(u))){return false;}}}if(q){for(r=q.length;r--;){n=q[r];if(n.operator?!n.test(this.getAttribute(o,n.key)):!this.hasAttribute(o,n.key)){return false;\r
+}}}if(s){for(r=s.length;r--;){n=s[r];if(!this.matchPseudo(o,n.key,n.value)){return false;}}}return true;};var j={" ":function(q,w,n,r,s,u,p){var t,v,o;\r
+if(this.isHTMLDocument){getById:if(n){v=this.document.getElementById(n);if((!v&&q.all)||(this.idGetsName&&v&&v.getAttributeNode("id").nodeValue!=n)){o=q.all[n];\r
+if(!o){return;}if(!o[0]){o=[o];}for(t=0;v=o[t++];){var c=v.getAttributeNode("id");if(c&&c.nodeValue==n){this.push(v,w,null,r,s,u);break;}}return;}if(!v){if(this.contains(this.root,q)){return;\r
+}else{break getById;}}else{if(this.document!==q&&!this.contains(q,v)){return;}}this.push(v,w,null,r,s,u);return;}getByClass:if(r&&q.getElementsByClassName&&!this.brokenGEBCN){o=q.getElementsByClassName(p.join(" "));\r
+if(!(o&&o.length)){break getByClass;}for(t=0;v=o[t++];){this.push(v,w,n,null,s,u);}return;}}getByTag:{o=q.getElementsByTagName(w);if(!(o&&o.length)){break getByTag;\r
+}if(!this.brokenStarGEBTN){w=null;}for(t=0;v=o[t++];){this.push(v,w,n,r,s,u);}}},">":function(p,c,r,o,n,q){if((p=p.firstChild)){do{if(p.nodeType==1){this.push(p,c,r,o,n,q);\r
+}}while((p=p.nextSibling));}},"+":function(p,c,r,o,n,q){while((p=p.nextSibling)){if(p.nodeType==1){this.push(p,c,r,o,n,q);break;}}},"^":function(p,c,r,o,n,q){p=p.firstChild;\r
+if(p){if(p.nodeType==1){this.push(p,c,r,o,n,q);}else{this["combinator:+"](p,c,r,o,n,q);}}},"~":function(q,c,s,p,n,r){while((q=q.nextSibling)){if(q.nodeType!=1){continue;\r
+}var o=this.getUID(q);if(this.bitUniques[o]){break;}this.bitUniques[o]=true;this.push(q,c,s,p,n,r);}},"++":function(p,c,r,o,n,q){this["combinator:+"](p,c,r,o,n,q);\r
+this["combinator:!+"](p,c,r,o,n,q);},"~~":function(p,c,r,o,n,q){this["combinator:~"](p,c,r,o,n,q);this["combinator:!~"](p,c,r,o,n,q);},"!":function(p,c,r,o,n,q){while((p=p.parentNode)){if(p!==this.document){this.push(p,c,r,o,n,q);\r
+}}},"!>":function(p,c,r,o,n,q){p=p.parentNode;if(p!==this.document){this.push(p,c,r,o,n,q);}},"!+":function(p,c,r,o,n,q){while((p=p.previousSibling)){if(p.nodeType==1){this.push(p,c,r,o,n,q);\r
+break;}}},"!^":function(p,c,r,o,n,q){p=p.lastChild;if(p){if(p.nodeType==1){this.push(p,c,r,o,n,q);}else{this["combinator:!+"](p,c,r,o,n,q);}}},"!~":function(q,c,s,p,n,r){while((q=q.previousSibling)){if(q.nodeType!=1){continue;\r
+}var o=this.getUID(q);if(this.bitUniques[o]){break;}this.bitUniques[o]=true;this.push(q,c,s,p,n,r);}}};for(var i in j){k["combinator:"+i]=j[i];}var l={empty:function(c){var n=c.firstChild;\r
+return !(n&&n.nodeType==1)&&!(c.innerText||c.textContent||"").length;},not:function(c,n){return !this.matchNode(c,n);},contains:function(c,n){return(c.innerText||c.textContent||"").indexOf(n)>-1;\r
+},"first-child":function(c){while((c=c.previousSibling)){if(c.nodeType==1){return false;}}return true;},"last-child":function(c){while((c=c.nextSibling)){if(c.nodeType==1){return false;\r
+}}return true;},"only-child":function(o){var n=o;while((n=n.previousSibling)){if(n.nodeType==1){return false;}}var c=o;while((c=c.nextSibling)){if(c.nodeType==1){return false;\r
+}}return true;},"nth-child":k.createNTHPseudo("firstChild","nextSibling","posNTH"),"nth-last-child":k.createNTHPseudo("lastChild","previousSibling","posNTHLast"),"nth-of-type":k.createNTHPseudo("firstChild","nextSibling","posNTHType",true),"nth-last-of-type":k.createNTHPseudo("lastChild","previousSibling","posNTHTypeLast",true),index:function(n,c){return this["pseudo:nth-child"](n,""+c+1);\r
+},even:function(c){return this["pseudo:nth-child"](c,"2n");},odd:function(c){return this["pseudo:nth-child"](c,"2n+1");},"first-of-type":function(c){var n=c.nodeName;\r
+while((c=c.previousSibling)){if(c.nodeName==n){return false;}}return true;},"last-of-type":function(c){var n=c.nodeName;while((c=c.nextSibling)){if(c.nodeName==n){return false;\r
+}}return true;},"only-of-type":function(o){var n=o,p=o.nodeName;while((n=n.previousSibling)){if(n.nodeName==p){return false;}}var c=o;while((c=c.nextSibling)){if(c.nodeName==p){return false;\r
+}}return true;},enabled:function(c){return !c.disabled;},disabled:function(c){return c.disabled;},checked:function(c){return c.checked||c.selected;},focus:function(c){return this.isHTMLDocument&&this.document.activeElement===c&&(c.href||c.type||this.hasAttribute(c,"tabindex"));\r
+},root:function(c){return(c===this.root);},selected:function(c){return c.selected;}};for(var b in l){k["pseudo:"+b]=l[b];}var a=k.attributeGetters={"class":function(){return this.getAttribute("class")||this.className;\r
+},"for":function(){return("htmlFor" in this)?this.htmlFor:this.getAttribute("for");},href:function(){return("href" in this)?this.getAttribute("href",2):this.getAttribute("href");\r
+},style:function(){return(this.style)?this.style.cssText:this.getAttribute("style");},tabindex:function(){var c=this.getAttributeNode("tabindex");return(c&&c.specified)?c.nodeValue:null;\r
+},type:function(){return this.getAttribute("type");},maxlength:function(){var c=this.getAttributeNode("maxLength");return(c&&c.specified)?c.nodeValue:null;\r
+}};a.MAXLENGTH=a.maxLength=a.maxlength;var e=k.Slick=(this.Slick||{});e.version="1.1.6";e.search=function(n,o,c){return k.search(n,o,c);};e.find=function(c,n){return k.search(c,n,null,true);\r
+};e.contains=function(c,n){k.setDocument(c);return k.contains(c,n);};e.getAttribute=function(n,c){k.setDocument(n);return k.getAttribute(n,c);};e.hasAttribute=function(n,c){k.setDocument(n);\r
+return k.hasAttribute(n,c);};e.match=function(n,c){if(!(n&&c)){return false;}if(!c||c===n){return true;}k.setDocument(n);return k.matchNode(n,c);};e.defineAttributeGetter=function(c,n){k.attributeGetters[c]=n;\r
+return this;};e.lookupAttributeGetter=function(c){return k.attributeGetters[c];};e.definePseudo=function(c,n){k["pseudo:"+c]=function(p,o){return n.call(p,o);\r
+};return this;};e.lookupPseudo=function(c){var n=k["pseudo:"+c];if(n){return function(o){return n.call(this,o);};}return null;};e.override=function(n,c){k.override(n,c);\r
+return this;};e.isXML=k.isXML;e.uidOf=function(c){return k.getUIDHTML(c);};if(!this.Slick){this.Slick=e;}}).apply((typeof exports!="undefined")?exports:this);\r
+var Element=function(b,g){var h=Element.Constructors[b];if(h){return h(g);}if(typeof b!="string"){return document.id(b).set(g);}if(!g){g={};}if(!(/^[\w-]+$/).test(b)){var e=Slick.parse(b).expressions[0][0];\r
+b=(e.tag=="*")?"div":e.tag;if(e.id&&g.id==null){g.id=e.id;}var d=e.attributes;if(d){for(var a,f=0,c=d.length;f<c;f++){a=d[f];if(g[a.key]!=null){continue;\r
+}if(a.value!=null&&a.operator=="="){g[a.key]=a.value;}else{if(!a.value&&!a.operator){g[a.key]=true;}}}}if(e.classList&&g["class"]==null){g["class"]=e.classList.join(" ");\r
+}}return document.newElement(b,g);};if(Browser.Element){Element.prototype=Browser.Element.prototype;}new Type("Element",Element).mirror(function(a){if(Array.prototype[a]){return;\r
+}var b={};b[a]=function(){var h=[],e=arguments,j=true;for(var g=0,d=this.length;g<d;g++){var f=this[g],c=h[g]=f[a].apply(f,e);j=(j&&typeOf(c)=="element");\r
+}return(j)?new Elements(h):h;};Elements.implement(b);});if(!Browser.Element){Element.parent=Object;Element.Prototype={"$family":Function.from("element").hide()};\r
+Element.mirror(function(a,b){Element.Prototype[a]=b;});}Element.Constructors={};Element.Constructors=new Hash;var IFrame=new Type("IFrame",function(){var e=Array.link(arguments,{properties:Type.isObject,iframe:function(f){return(f!=null);\r
+}});var c=e.properties||{},b;if(e.iframe){b=document.id(e.iframe);}var d=c.onload||function(){};delete c.onload;c.id=c.name=[c.id,c.name,b?(b.id||b.name):"IFrame_"+String.uniqueID()].pick();\r
+b=new Element(b||"iframe",c);var a=function(){d.call(b.contentWindow);};if(window.frames[c.id]){a();}else{b.addListener("load",a);}return b;});var Elements=this.Elements=function(a){if(a&&a.length){var e={},d;\r
+for(var c=0;d=a[c++];){var b=Slick.uidOf(d);if(!e[b]){e[b]=true;this.push(d);}}}};Elements.prototype={length:0};Elements.parent=Array;new Type("Elements",Elements).implement({filter:function(a,b){if(!a){return this;\r
+}return new Elements(Array.filter(this,(typeOf(a)=="string")?function(c){return c.match(a);}:a,b));}.protect(),push:function(){var d=this.length;for(var b=0,a=arguments.length;\r
+b<a;b++){var c=document.id(arguments[b]);if(c){this[d++]=c;}}return(this.length=d);}.protect(),unshift:function(){var b=[];for(var c=0,a=arguments.length;\r
+c<a;c++){var d=document.id(arguments[c]);if(d){b.push(d);}}return Array.prototype.unshift.apply(this,b);}.protect(),concat:function(){var b=new Elements(this);\r
+for(var c=0,a=arguments.length;c<a;c++){var d=arguments[c];if(Type.isEnumerable(d)){b.append(d);}else{b.push(d);}}return b;}.protect(),append:function(c){for(var b=0,a=c.length;\r
+b<a;b++){this.push(c[b]);}return this;}.protect(),empty:function(){while(this.length){delete this[--this.length];}return this;}.protect()});Elements.alias("extend","append");\r
+(function(){var g=Array.prototype.splice,b={"0":0,"1":1,length:2};g.call(b,1,1);if(b[1]==1){Elements.implement("splice",function(){var h=this.length;var e=g.apply(this,arguments);\r
+while(h>=this.length){delete this[h--];}return e;}.protect());}Elements.implement(Array.prototype);Array.mirror(Elements);var f;try{var a=document.createElement("<input name=x>");\r
+f=(a.name=="x");}catch(c){}var d=function(e){return(""+e).replace(/&/g,"&amp;").replace(/"/g,"&quot;");};Document.implement({newElement:function(e,h){if(h&&h.checked!=null){h.defaultChecked=h.checked;\r
+}if(f&&h){e="<"+e;if(h.name){e+=' name="'+d(h.name)+'"';}if(h.type){e+=' type="'+d(h.type)+'"';}e+=">";delete h.name;delete h.type;}return this.id(this.createElement(e)).set(h);\r
+}});})();Document.implement({newTextNode:function(a){return this.createTextNode(a);},getDocument:function(){return this;},getWindow:function(){return this.window;\r
+},id:(function(){var a={string:function(d,c,b){d=Slick.find(b,"#"+d.replace(/(\W)/g,"\\$1"));return(d)?a.element(d,c):null;},element:function(b,c){$uid(b);\r
+if(!c&&!b.$family&&!(/^(?:object|embed)$/i).test(b.tagName)){Object.append(b,Element.Prototype);}return b;},object:function(c,d,b){if(c.toElement){return a.element(c.toElement(b),d);\r
+}return null;}};a.textnode=a.whitespace=a.window=a.document=function(b){return b;};return function(c,e,d){if(c&&c.$family&&c.uid){return c;}var b=typeOf(c);\r
+return(a[b])?a[b](c,e,d||document):null;};})()});if(window.$==null){Window.implement("$",function(a,b){return document.id(a,b,this.document);});}Window.implement({getDocument:function(){return this.document;\r
+},getWindow:function(){return this;}});[Document,Element].invoke("implement",{getElements:function(a){return Slick.search(this,a,new Elements);},getElement:function(a){return document.id(Slick.find(this,a));\r
+}});var contains={contains:function(a){return Slick.contains(this,a);}};if(!document.contains){Document.implement(contains);}if(!document.createElement("div").contains){Element.implement(contains);\r
+}Element.implement("hasChild",function(a){return this!==a&&this.contains(a);});(function(b,d,a){this.Selectors={};var e=this.Selectors.Pseudo=new Hash();\r
+var c=function(){for(var f in e){if(e.hasOwnProperty(f)){Slick.definePseudo(f,e[f]);delete e[f];}}};Slick.search=function(g,h,f){c();return b.call(this,g,h,f);\r
+};Slick.find=function(f,g){c();return d.call(this,f,g);};Slick.match=function(g,f){c();return a.call(this,g,f);};})(Slick.search,Slick.find,Slick.match);\r
+var injectCombinator=function(d,c){if(!d){return c;}d=Object.clone(Slick.parse(d));var b=d.expressions;for(var a=b.length;a--;){b[a][0].combinator=c;}return d;\r
+};Object.forEach({getNext:"~",getPrevious:"!~",getParent:"!"},function(a,b){Element.implement(b,function(c){return this.getElement(injectCombinator(c,a));\r
+});});Object.forEach({getAllNext:"~",getAllPrevious:"!~",getSiblings:"~~",getChildren:">",getParents:"!"},function(a,b){Element.implement(b,function(c){return this.getElements(injectCombinator(c,a));\r
+});});Element.implement({getFirst:function(a){return document.id(Slick.search(this,injectCombinator(a,">"))[0]);},getLast:function(a){return document.id(Slick.search(this,injectCombinator(a,">")).getLast());\r
+},getWindow:function(){return this.ownerDocument.window;},getDocument:function(){return this.ownerDocument;},getElementById:function(a){return document.id(Slick.find(this,"#"+(""+a).replace(/(\W)/g,"\\$1")));\r
+},match:function(a){return !a||Slick.match(this,a);}});if(window.$$==null){Window.implement("$$",function(a){var f=new Elements;if(arguments.length==1&&typeof a=="string"){return Slick.search(this.document,a,f);\r
+}var c=Array.flatten(arguments);for(var d=0,b=c.length;d<b;d++){var e=c[d];switch(typeOf(e)){case"element":f.push(e);break;case"string":Slick.search(this.document,e,f);\r
+}}return f;});}if(window.$$==null){Window.implement("$$",function(a){if(arguments.length==1){if(typeof a=="string"){return Slick.search(this.document,a,new Elements);\r
+}else{if(Type.isEnumerable(a)){return new Elements(a);}}}return new Elements(arguments);});}(function(){var b={before:function(n,m){var o=m.parentNode;\r
+if(o){o.insertBefore(n,m);}},after:function(n,m){var o=m.parentNode;if(o){o.insertBefore(n,m.nextSibling);}},bottom:function(n,m){m.appendChild(n);},top:function(n,m){m.insertBefore(n,m.firstChild);\r
+}};b.inside=b.bottom;Object.each(b,function(n,o){o=o.capitalize();var m={};m["inject"+o]=function(p){n(this,document.id(p,true));return this;};m["grab"+o]=function(p){n(document.id(p,true),this);\r
+return this;};Element.implement(m);});var k={},d={};var i={};Array.forEach(["type","value","defaultValue","accessKey","cellPadding","cellSpacing","colSpan","frameBorder","readOnly","rowSpan","tabIndex","useMap"],function(m){i[m.toLowerCase()]=m;\r
+});Object.append(i,{html:"innerHTML",text:(function(){var m=document.createElement("div");return(m.textContent==null)?"innerText":"textContent";})()});\r
+Object.forEach(i,function(n,m){d[m]=function(o,p){o[n]=p;};k[m]=function(o){return o[n];};});var a=["compact","nowrap","ismap","declare","noshade","checked","disabled","readOnly","multiple","selected","noresize","defer","defaultChecked","autofocus","controls","autoplay","loop"];\r
+var h={};Array.forEach(a,function(m){var n=m.toLowerCase();h[n]=m;d[n]=function(o,p){o[m]=!!p;};k[n]=function(o){return !!o[m];};});Object.append(d,{"class":function(m,n){("className" in m)?m.className=n:m.setAttribute("class",n);\r
+},"for":function(m,n){("htmlFor" in m)?m.htmlFor=n:m.setAttribute("for",n);},style:function(m,n){(m.style)?m.style.cssText=n:m.setAttribute("style",n);\r
+}});Element.implement({setProperty:function(n,o){var m=n.toLowerCase();if(o==null){if(!h[m]){this.removeAttribute(n);return this;}o=false;}var p=d[m];if(p){p(this,o);\r
+}else{this.setAttribute(n,o);}return this;},setProperties:function(m){for(var n in m){this.setProperty(n,m[n]);}return this;},getProperty:function(o){var n=k[o.toLowerCase()];\r
+if(n){return n(this);}var m=Slick.getAttribute(this,o);return(!m&&!Slick.hasAttribute(this,o))?null:m;},getProperties:function(){var m=Array.from(arguments);\r
+return m.map(this.getProperty,this).associate(m);},removeProperty:function(m){return this.setProperty(m,null);},removeProperties:function(){Array.each(arguments,this.removeProperty,this);\r
+return this;},set:function(o,n){var m=Element.Properties[o];(m&&m.set)?m.set.call(this,n):this.setProperty(o,n);}.overloadSetter(),get:function(n){var m=Element.Properties[n];\r
+return(m&&m.get)?m.get.apply(this):this.getProperty(n);}.overloadGetter(),erase:function(n){var m=Element.Properties[n];(m&&m.erase)?m.erase.apply(this):this.removeProperty(n);\r
+return this;},hasClass:function(m){return this.className.clean().contains(m," ");},addClass:function(m){if(!this.hasClass(m)){this.className=(this.className+" "+m).clean();\r
+}return this;},removeClass:function(m){this.className=this.className.replace(new RegExp("(^|\\s)"+m+"(?:\\s|$)"),"$1");return this;},toggleClass:function(m,n){if(n==null){n=!this.hasClass(m);\r
+}return(n)?this.addClass(m):this.removeClass(m);},adopt:function(){var p=this,m,r=Array.flatten(arguments),q=r.length;if(q>1){p=m=document.createDocumentFragment();\r
+}for(var o=0;o<q;o++){var n=document.id(r[o],true);if(n){p.appendChild(n);}}if(m){this.appendChild(m);}return this;},appendText:function(n,m){return this.grab(this.getDocument().newTextNode(n),m);\r
+},grab:function(n,m){b[m||"bottom"](document.id(n,true),this);return this;},inject:function(n,m){b[m||"bottom"](this,document.id(n,true));return this;},replaces:function(m){m=document.id(m,true);\r
+m.parentNode.replaceChild(this,m);return this;},wraps:function(n,m){n=document.id(n,true);return this.replaces(n).grab(n,m);},getSelected:function(){this.selectedIndex;\r
+return new Elements(Array.from(this.options).filter(function(m){return m.selected;}));},toQueryString:function(){var m=[];this.getElements("input, select, textarea").each(function(o){var n=o.type;\r
+if(!o.name||o.disabled||n=="submit"||n=="reset"||n=="file"||n=="image"){return;}var p=(o.get("tag")=="select")?o.getSelected().map(function(q){return document.id(q).get("value");\r
+}):((n=="radio"||n=="checkbox")&&!o.checked)?null:o.get("value");Array.from(p).each(function(q){if(typeof q!="undefined"){m.push(encodeURIComponent(o.name)+"="+encodeURIComponent(q));\r
+}});});return m.join("&");}});var j={},e={};var c=function(m){return(e[m]||(e[m]={}));};var g=function(n){var m=n.uid;if(n.removeEvents){n.removeEvents();\r
+}if(n.clearAttributes){n.clearAttributes();}if(m!=null){delete j[m];delete e[m];}return n;};var l={input:"checked",option:"selected",textarea:"value"};\r
+Element.implement({destroy:function(){var m=g(this).getElementsByTagName("*");Array.each(m,g);Element.dispose(this);return null;},empty:function(){Array.from(this.childNodes).each(Element.dispose);\r
+return this;},dispose:function(){return(this.parentNode)?this.parentNode.removeChild(this):this;},clone:function(r,p){r=r!==false;var w=this.cloneNode(r),o=[w],q=[this],u;\r
+if(r){o.append(Array.from(w.getElementsByTagName("*")));q.append(Array.from(this.getElementsByTagName("*")));}for(u=o.length;u--;){var s=o[u],v=q[u];if(!p){s.removeAttribute("id");\r
+}if(s.clearAttributes){s.clearAttributes();s.mergeAttributes(v);s.removeAttribute("uid");if(s.options){var z=s.options,m=v.options;for(var t=z.length;t--;\r
+){z[t].selected=m[t].selected;}}}var n=l[v.tagName.toLowerCase()];if(n&&v[n]){s[n]=v[n];}}if(Browser.ie){var x=w.getElementsByTagName("object"),y=this.getElementsByTagName("object");\r
+for(u=x.length;u--;){x[u].outerHTML=y[u].outerHTML;}}return document.id(w);}});[Element,Window,Document].invoke("implement",{addListener:function(p,o){if(p=="unload"){var m=o,n=this;\r
+o=function(){n.removeListener("unload",o);m();};}else{j[$uid(this)]=this;}if(this.addEventListener){this.addEventListener(p,o,!!arguments[2]);}else{this.attachEvent("on"+p,o);\r
+}return this;},removeListener:function(n,m){if(this.removeEventListener){this.removeEventListener(n,m,!!arguments[2]);}else{this.detachEvent("on"+n,m);\r
+}return this;},retrieve:function(n,m){var p=c($uid(this)),o=p[n];if(m!=null&&o==null){o=p[n]=m;}return o!=null?o:null;},store:function(n,m){var o=c($uid(this));\r
+o[n]=m;return this;},eliminate:function(m){var n=c($uid(this));delete n[m];return this;}});if(window.attachEvent&&!window.addEventListener){window.addListener("unload",function(){Object.each(j,g);\r
+if(window.CollectGarbage){CollectGarbage();}});}Element.Properties={};Element.Properties=new Hash;Element.Properties.style={set:function(m){this.style.cssText=m;\r
+},get:function(){return this.style.cssText;},erase:function(){this.style.cssText="";}};Element.Properties.tag={get:function(){return this.tagName.toLowerCase();\r
+}};Element.Properties.html=(function(){var s=Function.attempt(function(){var u=document.createElement("table");u.innerHTML="<tr><td></td></tr>";});var t=document.createElement("div");\r
+var o={table:[1,"<table>","</table>"],select:[1,"<select>","</select>"],tbody:[2,"<table><tbody>","</tbody></table>"],tr:[3,"<table><tbody><tr>","</tr></tbody></table>"]};\r
+o.thead=o.tfoot=o.tbody;t.innerHTML="<nav></nav>";var n=t.childNodes.length==1;if(!n){var q="abbr article aside audio canvas datalist details figcaption figure footer header hgroup mark meter nav output progress section summary time video".split(" "),p=document.createDocumentFragment(),m=q.length;\r
+while(m--){p.createElement(q[m]);}p.appendChild(t);}var r={set:function(v){if(typeOf(v)=="array"){v=v.join("");}var w=(!s&&o[this.get("tag")]);if(!w&&!n){w=[0,"",""];\r
+}if(w){var x=t;x.innerHTML=w[1]+v+w[2];for(var u=w[0];u--;){x=x.firstChild;}this.empty().adopt(x.childNodes);}else{this.innerHTML=v;}}};r.erase=r.set;return r;\r
+})();var f=document.createElement("form");f.innerHTML="<select><option>s</option></select>";if(f.firstChild.value!="s"){Element.Properties.value={set:function(r){var n=this.get("tag");\r
+if(n!="select"){return this.setProperty("value",r);}var o=this.getElements("option");for(var p=0;p<o.length;p++){var q=o[p],m=q.getAttributeNode("value"),s=(m&&m.specified)?q.value:q.get("text");\r
+if(s==r){return q.selected=true;}}},get:function(){var o=this,n=o.get("tag");if(n!="select"&&n!="option"){return this.getProperty("value");}if(n=="select"&&!(o=o.getSelected()[0])){return"";\r
+}var m=o.getAttributeNode("value");return(m&&m.specified)?o.value:o.get("text");}};}})();(function(){var f=document.html;Element.Properties.styles={set:function(i){this.setStyles(i);\r
+}};var h=(f.style.opacity!=null),a=(f.style.filter!=null),g=/alpha\(opacity=([\d.]+)\)/i;var b=function(j,i){j.store("$opacity",i);j.style.visibility=i>0?"visible":"hidden";\r
+};var d=(h?function(j,i){j.style.opacity=i;}:(a?function(j,i){if(!j.currentStyle||!j.currentStyle.hasLayout){j.style.zoom=1;}i=(i*100).limit(0,100).round();\r
+i=(i==100)?"":"alpha(opacity="+i+")";var k=j.style.filter||j.getComputedStyle("filter")||"";j.style.filter=g.test(k)?k.replace(g,i):k+i;}:b));var e=(h?function(j){var i=j.style.opacity||j.getComputedStyle("opacity");\r
+return(i=="")?1:i.toFloat();}:(a?function(j){var k=(j.style.filter||j.getComputedStyle("filter")),i;if(k){i=k.match(g);}return(i==null||k==null)?1:(i[1]/100);\r
+}:function(j){var i=j.retrieve("$opacity");if(i==null){i=(j.style.visibility=="hidden"?0:1);}return i;}));var c=(f.style.cssFloat==null)?"styleFloat":"cssFloat";\r
+Element.implement({getComputedStyle:function(k){if(this.currentStyle){return this.currentStyle[k.camelCase()];}var j=Element.getDocument(this).defaultView,i=j?j.getComputedStyle(this,null):null;\r
+return(i)?i.getPropertyValue((k==c)?"float":k.hyphenate()):null;},setStyle:function(j,i){if(j=="opacity"){d(this,parseFloat(i));return this;}j=(j=="float"?c:j).camelCase();\r
+if(typeOf(i)!="string"){var k=(Element.Styles[j]||"@").split(" ");i=Array.from(i).map(function(m,l){if(!k[l]){return"";}return(typeOf(m)=="number")?k[l].replace("@",Math.round(m)):m;\r
+}).join(" ");}else{if(i==String(Number(i))){i=Math.round(i);}}this.style[j]=i;return this;},getStyle:function(o){if(o=="opacity"){return e(this);}o=(o=="float"?c:o).camelCase();\r
+var i=this.style[o];if(!i||o=="zIndex"){i=[];for(var n in Element.ShortStyles){if(o!=n){continue;}for(var m in Element.ShortStyles[n]){i.push(this.getStyle(m));\r
+}return i.join(" ");}i=this.getComputedStyle(o);}if(i){i=String(i);var k=i.match(/rgba?\([\d\s,]+\)/);if(k){i=i.replace(k[0],k[0].rgbToHex());}}if(Browser.opera||(Browser.ie&&isNaN(parseFloat(i)))){if((/^(height|width)$/).test(o)){var j=(o=="width")?["left","right"]:["top","bottom"],l=0;\r
+j.each(function(p){l+=this.getStyle("border-"+p+"-width").toInt()+this.getStyle("padding-"+p).toInt();},this);return this["offset"+o.capitalize()]-l+"px";\r
+}if(Browser.opera&&String(i).indexOf("px")!=-1){return i;}if((/^border(.+)Width|margin|padding/).test(o)){return"0px";}}return i;},setStyles:function(j){for(var i in j){this.setStyle(i,j[i]);\r
+}return this;},getStyles:function(){var i={};Array.flatten(arguments).each(function(j){i[j]=this.getStyle(j);},this);return i;}});Element.Styles={left:"@px",top:"@px",bottom:"@px",right:"@px",width:"@px",height:"@px",maxWidth:"@px",maxHeight:"@px",minWidth:"@px",minHeight:"@px",backgroundColor:"rgb(@, @, @)",backgroundPosition:"@px @px",color:"rgb(@, @, @)",fontSize:"@px",letterSpacing:"@px",lineHeight:"@px",clip:"rect(@px @px @px @px)",margin:"@px @px @px @px",padding:"@px @px @px @px",border:"@px @ rgb(@, @, @) @px @ rgb(@, @, @) @px @ rgb(@, @, @)",borderWidth:"@px @px @px @px",borderStyle:"@ @ @ @",borderColor:"rgb(@, @, @) rgb(@, @, @) rgb(@, @, @) rgb(@, @, @)",zIndex:"@",zoom:"@",fontWeight:"@",textIndent:"@px",opacity:"@"};\r
+Element.implement({setOpacity:function(i){d(this,i);return this;},getOpacity:function(){return e(this);}});Element.Properties.opacity={set:function(i){d(this,i);\r
+b(this,i);},get:function(){return e(this);}};Element.Styles=new Hash(Element.Styles);Element.ShortStyles={margin:{},padding:{},border:{},borderWidth:{},borderStyle:{},borderColor:{}};\r
+["Top","Right","Bottom","Left"].each(function(o){var n=Element.ShortStyles;var j=Element.Styles;["margin","padding"].each(function(p){var q=p+o;n[p][q]=j[q]="@px";\r
+});var m="border"+o;n.border[m]=j[m]="@px @ rgb(@, @, @)";var l=m+"Width",i=m+"Style",k=m+"Color";n[m]={};n.borderWidth[l]=n[m][l]=j[l]="@px";n.borderStyle[i]=n[m][i]=j[i]="@";\r
+n.borderColor[k]=n[m][k]=j[k]="rgb(@, @, @)";});})();(function(){Element.Properties.events={set:function(b){this.addEvents(b);}};[Element,Window,Document].invoke("implement",{addEvent:function(f,h){var i=this.retrieve("events",{});\r
+if(!i[f]){i[f]={keys:[],values:[]};}if(i[f].keys.contains(h)){return this;}i[f].keys.push(h);var g=f,b=Element.Events[f],d=h,j=this;if(b){if(b.onAdd){b.onAdd.call(this,h,f);\r
+}if(b.condition){d=function(k){if(b.condition.call(this,k,f)){return h.call(this,k);}return true;};}if(b.base){g=Function.from(b.base).call(this,f);}}var e=function(){return h.call(j);\r
+};var c=Element.NativeEvents[g];if(c){if(c==2){e=function(k){k=new DOMEvent(k,j.getWindow());if(d.call(j,k)===false){k.stop();}};}this.addListener(g,e,arguments[2]);\r
+}i[f].values.push(e);return this;},removeEvent:function(e,d){var c=this.retrieve("events");if(!c||!c[e]){return this;}var h=c[e];var b=h.keys.indexOf(d);\r
+if(b==-1){return this;}var g=h.values[b];delete h.keys[b];delete h.values[b];var f=Element.Events[e];if(f){if(f.onRemove){f.onRemove.call(this,d,e);}if(f.base){e=Function.from(f.base).call(this,e);\r
+}}return(Element.NativeEvents[e])?this.removeListener(e,g,arguments[2]):this;},addEvents:function(b){for(var c in b){this.addEvent(c,b[c]);}return this;\r
+},removeEvents:function(b){var d;if(typeOf(b)=="object"){for(d in b){this.removeEvent(d,b[d]);}return this;}var c=this.retrieve("events");if(!c){return this;\r
+}if(!b){for(d in c){this.removeEvents(d);}this.eliminate("events");}else{if(c[b]){c[b].keys.each(function(e){this.removeEvent(b,e);},this);delete c[b];\r
+}}return this;},fireEvent:function(e,c,b){var d=this.retrieve("events");if(!d||!d[e]){return this;}c=Array.from(c);d[e].keys.each(function(f){if(b){f.delay(b,this,c);\r
+}else{f.apply(this,c);}},this);return this;},cloneEvents:function(e,d){e=document.id(e);var c=e.retrieve("events");if(!c){return this;}if(!d){for(var b in c){this.cloneEvents(e,b);\r
+}}else{if(c[d]){c[d].keys.each(function(f){this.addEvent(d,f);},this);}}return this;}});Element.NativeEvents={click:2,dblclick:2,mouseup:2,mousedown:2,contextmenu:2,mousewheel:2,DOMMouseScroll:2,mouseover:2,mouseout:2,mousemove:2,selectstart:2,selectend:2,keydown:2,keypress:2,keyup:2,orientationchange:2,touchstart:2,touchmove:2,touchend:2,touchcancel:2,gesturestart:2,gesturechange:2,gestureend:2,focus:2,blur:2,change:2,reset:2,select:2,submit:2,paste:2,input:2,load:2,unload:1,beforeunload:2,resize:1,move:1,DOMContentLoaded:1,readystatechange:1,error:1,abort:1,scroll:1};\r
+var a=function(b){var c=b.relatedTarget;if(c==null){return true;}if(!c){return false;}return(c!=this&&c.prefix!="xul"&&typeOf(this)!="document"&&!this.contains(c));\r
+};Element.Events={mouseenter:{base:"mouseover",condition:a},mouseleave:{base:"mouseout",condition:a},mousewheel:{base:(Browser.firefox)?"DOMMouseScroll":"mousewheel"}};\r
+if(!window.addEventListener){Element.NativeEvents.propertychange=2;Element.Events.change={base:function(){var b=this.type;return(this.get("tag")=="input"&&(b=="radio"||b=="checkbox"))?"propertychange":"change";\r
+},condition:function(b){return !!(this.type!="radio"||this.checked);}};}Element.Events=new Hash(Element.Events);})();(function(){var c=!!window.addEventListener;\r
+Element.NativeEvents.focusin=Element.NativeEvents.focusout=2;var k=function(l,m,n,o,p){while(p&&p!=l){if(m(p,o)){return n.call(p,o,p);}p=document.id(p.parentNode);\r
+}};var a={mouseenter:{base:"mouseover"},mouseleave:{base:"mouseout"},focus:{base:"focus"+(c?"":"in"),capture:true},blur:{base:c?"blur":"focusout",capture:true}};\r
+var b="$delegation:";var i=function(l){return{base:"focusin",remove:function(m,o){var p=m.retrieve(b+l+"listeners",{})[o];if(p&&p.forms){for(var n=p.forms.length;\r
+n--;){p.forms[n].removeEvent(l,p.fns[n]);}}},listen:function(x,r,v,n,t,s){var o=(t.get("tag")=="form")?t:n.target.getParent("form");if(!o){return;}var u=x.retrieve(b+l+"listeners",{}),p=u[s]||{forms:[],fns:[]},m=p.forms,w=p.fns;\r
+if(m.indexOf(o)!=-1){return;}m.push(o);var q=function(y){k(x,r,v,y,t);};o.addEvent(l,q);w.push(q);u[s]=p;x.store(b+l+"listeners",u);}};};var d=function(l){return{base:"focusin",listen:function(m,n,p,q,r){var o={blur:function(){this.removeEvents(o);\r
+}};o[l]=function(s){k(m,n,p,s,r);};q.target.addEvents(o);}};};if(!c){Object.append(a,{submit:i("submit"),reset:i("reset"),change:d("change"),select:d("select")});\r
+}var h=Element.prototype,f=h.addEvent,j=h.removeEvent;var e=function(l,m){return function(r,q,n){if(r.indexOf(":relay")==-1){return l.call(this,r,q,n);\r
+}var o=Slick.parse(r).expressions[0][0];if(o.pseudos[0].key!="relay"){return l.call(this,r,q,n);}var p=o.tag;o.pseudos.slice(1).each(function(s){p+=":"+s.key+(s.value?"("+s.value+")":"");\r
+});l.call(this,r,q);return m.call(this,p,o.pseudos[0].value,q);};};var g={addEvent:function(v,q,x){var t=this.retrieve("$delegates",{}),r=t[v];if(r){for(var y in r){if(r[y].fn==x&&r[y].match==q){return this;\r
+}}}var p=v,u=q,o=x,n=a[v]||{};v=n.base||p;q=function(B){return Slick.match(B,u);};var w=Element.Events[p];if(w&&w.condition){var l=q,m=w.condition;q=function(C,B){return l(C,B)&&m.call(C,B,v);\r
+};}var z=this,s=String.uniqueID();var A=n.listen?function(B,C){if(!C&&B&&B.target){C=B.target;}if(C){n.listen(z,q,x,B,C,s);}}:function(B,C){if(!C&&B&&B.target){C=B.target;\r
+}if(C){k(z,q,x,B,C);}};if(!r){r={};}r[s]={match:u,fn:o,delegator:A};t[p]=r;return f.call(this,v,A,n.capture);},removeEvent:function(r,n,t,u){var q=this.retrieve("$delegates",{}),p=q[r];\r
+if(!p){return this;}if(u){var m=r,w=p[u].delegator,l=a[r]||{};r=l.base||m;if(l.remove){l.remove(this,u);}delete p[u];q[m]=p;return j.call(this,r,w);}var o,v;\r
+if(t){for(o in p){v=p[o];if(v.match==n&&v.fn==t){return g.removeEvent.call(this,r,n,t,o);}}}else{for(o in p){v=p[o];if(v.match==n){g.removeEvent.call(this,r,n,v.fn,o);\r
+}}}return this;}};[Element,Window,Document].invoke("implement",{addEvent:e(f,g.addEvent),removeEvent:e(j,g.removeEvent)});})();(function(){var h=document.createElement("div"),e=document.createElement("div");\r
+h.style.height="0";h.appendChild(e);var d=(e.offsetParent===h);h=e=null;var l=function(m){return k(m,"position")!="static"||a(m);};var i=function(m){return l(m)||(/^(?:table|td|th)$/i).test(m.tagName);\r
+};Element.implement({scrollTo:function(m,n){if(a(this)){this.getWindow().scrollTo(m,n);}else{this.scrollLeft=m;this.scrollTop=n;}return this;},getSize:function(){if(a(this)){return this.getWindow().getSize();\r
+}return{x:this.offsetWidth,y:this.offsetHeight};},getScrollSize:function(){if(a(this)){return this.getWindow().getScrollSize();}return{x:this.scrollWidth,y:this.scrollHeight};\r
+},getScroll:function(){if(a(this)){return this.getWindow().getScroll();}return{x:this.scrollLeft,y:this.scrollTop};},getScrolls:function(){var n=this.parentNode,m={x:0,y:0};\r
+while(n&&!a(n)){m.x+=n.scrollLeft;m.y+=n.scrollTop;n=n.parentNode;}return m;},getOffsetParent:d?function(){var m=this;if(a(m)||k(m,"position")=="fixed"){return null;\r
+}var n=(k(m,"position")=="static")?i:l;while((m=m.parentNode)){if(n(m)){return m;}}return null;}:function(){var m=this;if(a(m)||k(m,"position")=="fixed"){return null;\r
+}try{return m.offsetParent;}catch(n){}return null;},getOffsets:function(){if(this.getBoundingClientRect&&!Browser.Platform.ios){var r=this.getBoundingClientRect(),o=document.id(this.getDocument().documentElement),q=o.getScroll(),t=this.getScrolls(),s=(k(this,"position")=="fixed");\r
+return{x:r.left.toInt()+t.x+((s)?0:q.x)-o.clientLeft,y:r.top.toInt()+t.y+((s)?0:q.y)-o.clientTop};}var n=this,m={x:0,y:0};if(a(this)){return m;}while(n&&!a(n)){m.x+=n.offsetLeft;\r
+m.y+=n.offsetTop;if(Browser.firefox){if(!c(n)){m.x+=b(n);m.y+=g(n);}var p=n.parentNode;if(p&&k(p,"overflow")!="visible"){m.x+=b(p);m.y+=g(p);}}else{if(n!=this&&Browser.safari){m.x+=b(n);\r
+m.y+=g(n);}}n=n.offsetParent;}if(Browser.firefox&&!c(this)){m.x-=b(this);m.y-=g(this);}return m;},getPosition:function(p){var q=this.getOffsets(),n=this.getScrolls();\r
+var m={x:q.x-n.x,y:q.y-n.y};if(p&&(p=document.id(p))){var o=p.getPosition();return{x:m.x-o.x-b(p),y:m.y-o.y-g(p)};}return m;},getCoordinates:function(o){if(a(this)){return this.getWindow().getCoordinates();\r
+}var m=this.getPosition(o),n=this.getSize();var p={left:m.x,top:m.y,width:n.x,height:n.y};p.right=p.left+p.width;p.bottom=p.top+p.height;return p;},computePosition:function(m){return{left:m.x-j(this,"margin-left"),top:m.y-j(this,"margin-top")};\r
+},setPosition:function(m){return this.setStyles(this.computePosition(m));}});[Document,Window].invoke("implement",{getSize:function(){var m=f(this);return{x:m.clientWidth,y:m.clientHeight};\r
+},getScroll:function(){var n=this.getWindow(),m=f(this);return{x:n.pageXOffset||m.scrollLeft,y:n.pageYOffset||m.scrollTop};},getScrollSize:function(){var o=f(this),n=this.getSize(),m=this.getDocument().body;\r
+return{x:Math.max(o.scrollWidth,m.scrollWidth,n.x),y:Math.max(o.scrollHeight,m.scrollHeight,n.y)};},getPosition:function(){return{x:0,y:0};},getCoordinates:function(){var m=this.getSize();\r
+return{top:0,left:0,bottom:m.y,right:m.x,height:m.y,width:m.x};}});var k=Element.getComputedStyle;function j(m,n){return k(m,n).toInt()||0;}function c(m){return k(m,"-moz-box-sizing")=="border-box";\r
+}function g(m){return j(m,"border-top-width");}function b(m){return j(m,"border-left-width");}function a(m){return(/^(?:body|html)$/i).test(m.tagName);\r
+}function f(m){var n=m.getDocument();return(!n.compatMode||n.compatMode=="CSS1Compat")?n.html:n.body;}})();Element.alias({position:"setPosition"});[Window,Document,Element].invoke("implement",{getHeight:function(){return this.getSize().y;\r
+},getWidth:function(){return this.getSize().x;},getScrollTop:function(){return this.getScroll().y;},getScrollLeft:function(){return this.getScroll().x;\r
+},getScrollHeight:function(){return this.getScrollSize().y;},getScrollWidth:function(){return this.getScrollSize().x;},getTop:function(){return this.getPosition().y;\r
+},getLeft:function(){return this.getPosition().x;}});(function(){var f=this.Fx=new Class({Implements:[Chain,Events,Options],options:{fps:60,unit:false,duration:500,frames:null,frameSkip:true,link:"ignore"},initialize:function(g){this.subject=this.subject||this;\r
+this.setOptions(g);},getTransition:function(){return function(g){return -(Math.cos(Math.PI*g)-1)/2;};},step:function(g){if(this.options.frameSkip){var h=(this.time!=null)?(g-this.time):0,i=h/this.frameInterval;\r
+this.time=g;this.frame+=i;}else{this.frame++;}if(this.frame<this.frames){var j=this.transition(this.frame/this.frames);this.set(this.compute(this.from,this.to,j));\r
+}else{this.frame=this.frames;this.set(this.compute(this.from,this.to,1));this.stop();}},set:function(g){return g;},compute:function(i,h,g){return f.compute(i,h,g);\r
+},check:function(){if(!this.isRunning()){return true;}switch(this.options.link){case"cancel":this.cancel();return true;case"chain":this.chain(this.caller.pass(arguments,this));\r
+return false;}return false;},start:function(k,j){if(!this.check(k,j)){return this;}this.from=k;this.to=j;this.frame=(this.options.frameSkip)?0:-1;this.time=null;\r
+this.transition=this.getTransition();var i=this.options.frames,h=this.options.fps,g=this.options.duration;this.duration=f.Durations[g]||g.toInt();this.frameInterval=1000/h;\r
+this.frames=i||Math.round(this.duration/this.frameInterval);this.fireEvent("start",this.subject);b.call(this,h);return this;},stop:function(){if(this.isRunning()){this.time=null;\r
+d.call(this,this.options.fps);if(this.frames==this.frame){this.fireEvent("complete",this.subject);if(!this.callChain()){this.fireEvent("chainComplete",this.subject);\r
+}}else{this.fireEvent("stop",this.subject);}}return this;},cancel:function(){if(this.isRunning()){this.time=null;d.call(this,this.options.fps);this.frame=this.frames;\r
+this.fireEvent("cancel",this.subject).clearChain();}return this;},pause:function(){if(this.isRunning()){this.time=null;d.call(this,this.options.fps);}return this;\r
+},resume:function(){if((this.frame<this.frames)&&!this.isRunning()){b.call(this,this.options.fps);}return this;},isRunning:function(){var g=e[this.options.fps];\r
+return g&&g.contains(this);}});f.compute=function(i,h,g){return(h-i)*g+i;};f.Durations={"short":250,normal:500,"long":1000};var e={},c={};var a=function(){var h=Date.now();\r
+for(var j=this.length;j--;){var g=this[j];if(g){g.step(h);}}};var b=function(h){var g=e[h]||(e[h]=[]);g.push(this);if(!c[h]){c[h]=a.periodical(Math.round(1000/h),g);\r
+}};var d=function(h){var g=e[h];if(g){g.erase(this);if(!g.length&&c[h]){delete e[h];c[h]=clearInterval(c[h]);}}};})();Fx.CSS=new Class({Extends:Fx,prepare:function(c,d,b){b=Array.from(b);\r
+if(b[1]==null){b[1]=b[0];b[0]=c.getStyle(d);}var a=b.map(this.parse);return{from:a[0],to:a[1]};},parse:function(a){a=Function.from(a)();a=(typeof a=="string")?a.split(" "):Array.from(a);\r
+return a.map(function(c){c=String(c);var b=false;Object.each(Fx.CSS.Parsers,function(f,e){if(b){return;}var d=f.parse(c);if(d||d===0){b={value:d,parser:f};\r
+}});b=b||{value:c,parser:Fx.CSS.Parsers.String};return b;});},compute:function(d,c,b){var a=[];(Math.min(d.length,c.length)).times(function(e){a.push({value:d[e].parser.compute(d[e].value,c[e].value,b),parser:d[e].parser});\r
+});a.$family=Function.from("fx:css:value");return a;},serve:function(c,b){if(typeOf(c)!="fx:css:value"){c=this.parse(c);}var a=[];c.each(function(d){a=a.concat(d.parser.serve(d.value,b));\r
+});return a;},render:function(a,d,c,b){a.setStyle(d,this.serve(c,b));},search:function(a){if(Fx.CSS.Cache[a]){return Fx.CSS.Cache[a];}var c={},b=new RegExp("^"+a.escapeRegExp()+"$");\r
+Array.each(document.styleSheets,function(f,e){var d=f.href;if(d&&d.contains("://")&&!d.contains(document.domain)){return;}var g=f.rules||f.cssRules;Array.each(g,function(k,h){if(!k.style){return;\r
+}var j=(k.selectorText)?k.selectorText.replace(/^\w+/,function(i){return i.toLowerCase();}):null;if(!j||!b.test(j)){return;}Object.each(Element.Styles,function(l,i){if(!k.style[i]||Element.ShortStyles[i]){return;\r
+}l=String(k.style[i]);c[i]=((/^rgb/).test(l))?l.rgbToHex():l;});});});return Fx.CSS.Cache[a]=c;}});Fx.CSS.Cache={};Fx.CSS.Parsers={Color:{parse:function(a){if(a.match(/^#[0-9a-f]{3,6}$/i)){return a.hexToRgb(true);\r
+}return((a=a.match(/(\d+),\s*(\d+),\s*(\d+)/)))?[a[1],a[2],a[3]]:false;},compute:function(c,b,a){return c.map(function(e,d){return Math.round(Fx.compute(c[d],b[d],a));\r
+});},serve:function(a){return a.map(Number);}},Number:{parse:parseFloat,compute:Fx.compute,serve:function(b,a){return(a)?b+a:b;}},String:{parse:Function.from(false),compute:function(b,a){return a;\r
+},serve:function(a){return a;}}};Fx.CSS.Parsers=new Hash(Fx.CSS.Parsers);Fx.Tween=new Class({Extends:Fx.CSS,initialize:function(b,a){this.element=this.subject=document.id(b);\r
+this.parent(a);},set:function(b,a){if(arguments.length==1){a=b;b=this.property||this.options.property;}this.render(this.element,b,a,this.options.unit);\r
+return this;},start:function(c,e,d){if(!this.check(c,e,d)){return this;}var b=Array.flatten(arguments);this.property=this.options.property||b.shift();var a=this.prepare(this.element,this.property,b);\r
+return this.parent(a.from,a.to);}});Element.Properties.tween={set:function(a){this.get("tween").cancel().setOptions(a);return this;},get:function(){var a=this.retrieve("tween");\r
+if(!a){a=new Fx.Tween(this,{link:"cancel"});this.store("tween",a);}return a;}};Element.implement({tween:function(a,c,b){this.get("tween").start(a,c,b);\r
+return this;},fade:function(c){var d=this.get("tween"),f,e,a;if(c==null){c="toggle";}switch(c){case"in":f="start";e=1;break;case"out":f="start";e=0;break;\r
+case"show":f="set";e=1;break;case"hide":f="set";e=0;break;case"toggle":var b=this.retrieve("fade:flag",this.getStyle("opacity")==1);f="start";e=b?0:1;this.store("fade:flag",!b);\r
+a=true;break;default:f="start";e=c;}if(!a){this.eliminate("fade:flag");}d[f]("opacity",e);if(f=="set"||e!=0){this.setStyle("visibility",e==0?"hidden":"visible");\r
+}else{d.chain(function(){this.element.setStyle("visibility","hidden");});}return this;},highlight:function(c,a){if(!a){a=this.retrieve("highlight:original",this.getStyle("background-color"));\r
+a=(a=="transparent")?"#fff":a;}var b=this.get("tween");b.start("background-color",c||"#ffff88",a).chain(function(){this.setStyle("background-color",this.retrieve("highlight:original"));\r
+b.callChain();}.bind(this));return this;}});Fx.Morph=new Class({Extends:Fx.CSS,initialize:function(b,a){this.element=this.subject=document.id(b);this.parent(a);\r
+},set:function(a){if(typeof a=="string"){a=this.search(a);}for(var b in a){this.render(this.element,b,a[b],this.options.unit);}return this;},compute:function(e,d,c){var a={};\r
+for(var b in e){a[b]=this.parent(e[b],d[b],c);}return a;},start:function(b){if(!this.check(b)){return this;}if(typeof b=="string"){b=this.search(b);}var e={},d={};\r
+for(var c in b){var a=this.prepare(this.element,c,b[c]);e[c]=a.from;d[c]=a.to;}return this.parent(e,d);}});Element.Properties.morph={set:function(a){this.get("morph").cancel().setOptions(a);\r
+return this;},get:function(){var a=this.retrieve("morph");if(!a){a=new Fx.Morph(this,{link:"cancel"});this.store("morph",a);}return a;}};Element.implement({morph:function(a){this.get("morph").start(a);\r
+return this;}});Fx.implement({getTransition:function(){var a=this.options.transition||Fx.Transitions.Sine.easeInOut;if(typeof a=="string"){var b=a.split(":");\r
+a=Fx.Transitions;a=a[b[0]]||a[b[0].capitalize()];if(b[1]){a=a["ease"+b[1].capitalize()+(b[2]?b[2].capitalize():"")];}}return a;}});Fx.Transition=function(c,b){b=Array.from(b);\r
+var a=function(d){return c(d,b);};return Object.append(a,{easeIn:a,easeOut:function(d){return 1-c(1-d,b);},easeInOut:function(d){return(d<=0.5?c(2*d,b):(2-c(2*(1-d),b)))/2;\r
+}});};Fx.Transitions={linear:function(a){return a;}};Fx.Transitions=new Hash(Fx.Transitions);Fx.Transitions.extend=function(a){for(var b in a){Fx.Transitions[b]=new Fx.Transition(a[b]);\r
+}};Fx.Transitions.extend({Pow:function(b,a){return Math.pow(b,a&&a[0]||6);},Expo:function(a){return Math.pow(2,8*(a-1));},Circ:function(a){return 1-Math.sin(Math.acos(a));\r
+},Sine:function(a){return 1-Math.cos(a*Math.PI/2);},Back:function(b,a){a=a&&a[0]||1.618;return Math.pow(b,2)*((a+1)*b-a);},Bounce:function(f){var e;for(var d=0,c=1;\r
+1;d+=c,c/=2){if(f>=(7-4*d)/11){e=c*c-Math.pow((11-6*d-11*f)/4,2);break;}}return e;},Elastic:function(b,a){return Math.pow(2,10*--b)*Math.cos(20*b*Math.PI*(a&&a[0]||1)/3);\r
+}});["Quad","Cubic","Quart","Quint"].each(function(b,a){Fx.Transitions[b]=new Fx.Transition(function(c){return Math.pow(c,a+2);});});(function(){var d=function(){},a=("onprogress" in new Browser.Request);\r
+var c=this.Request=new Class({Implements:[Chain,Events,Options],options:{url:"",data:"",headers:{"X-Requested-With":"XMLHttpRequest",Accept:"text/javascript, text/html, application/xml, text/xml, */*"},async:true,format:false,method:"post",link:"ignore",isSuccess:null,emulation:true,urlEncoded:true,encoding:"utf-8",evalScripts:false,evalResponse:false,timeout:0,noCache:false},initialize:function(e){this.xhr=new Browser.Request();\r
+this.setOptions(e);this.headers=this.options.headers;},onStateChange:function(){var e=this.xhr;if(e.readyState!=4||!this.running){return;}this.running=false;\r
+this.status=0;Function.attempt(function(){var f=e.status;this.status=(f==1223)?204:f;}.bind(this));e.onreadystatechange=d;if(a){e.onprogress=e.onloadstart=d;\r
+}clearTimeout(this.timer);this.response={text:this.xhr.responseText||"",xml:this.xhr.responseXML};if(this.options.isSuccess.call(this,this.status)){this.success(this.response.text,this.response.xml);\r
+}else{this.failure();}},isSuccess:function(){var e=this.status;return(e>=200&&e<300);},isRunning:function(){return !!this.running;},processScripts:function(e){if(this.options.evalResponse||(/(ecma|java)script/).test(this.getHeader("Content-type"))){return Browser.exec(e);\r
+}return e.stripScripts(this.options.evalScripts);},success:function(f,e){this.onSuccess(this.processScripts(f),e);},onSuccess:function(){this.fireEvent("complete",arguments).fireEvent("success",arguments).callChain();\r
+},failure:function(){this.onFailure();},onFailure:function(){this.fireEvent("complete").fireEvent("failure",this.xhr);},loadstart:function(e){this.fireEvent("loadstart",[e,this.xhr]);\r
+},progress:function(e){this.fireEvent("progress",[e,this.xhr]);},timeout:function(){this.fireEvent("timeout",this.xhr);},setHeader:function(e,f){this.headers[e]=f;\r
+return this;},getHeader:function(e){return Function.attempt(function(){return this.xhr.getResponseHeader(e);}.bind(this));},check:function(){if(!this.running){return true;\r
+}switch(this.options.link){case"cancel":this.cancel();return true;case"chain":this.chain(this.caller.pass(arguments,this));return false;}return false;},send:function(o){if(!this.check(o)){return this;\r
+}this.options.isSuccess=this.options.isSuccess||this.isSuccess;this.running=true;var l=typeOf(o);if(l=="string"||l=="element"){o={data:o};}var h=this.options;\r
+o=Object.append({data:h.data,url:h.url,method:h.method},o);var j=o.data,f=String(o.url),e=o.method.toLowerCase();switch(typeOf(j)){case"element":j=document.id(j).toQueryString();\r
+break;case"object":case"hash":j=Object.toQueryString(j);}if(this.options.format){var m="format="+this.options.format;j=(j)?m+"&"+j:m;}if(this.options.emulation&&!["get","post"].contains(e)){var k="_method="+e;\r
+j=(j)?k+"&"+j:k;e="post";}if(this.options.urlEncoded&&["post","put"].contains(e)){var g=(this.options.encoding)?"; charset="+this.options.encoding:"";this.headers["Content-type"]="application/x-www-form-urlencoded"+g;\r
+}if(!f){f=document.location.pathname;}var i=f.lastIndexOf("/");if(i>-1&&(i=f.indexOf("#"))>-1){f=f.substr(0,i);}if(this.options.noCache){f+=(f.contains("?")?"&":"?")+String.uniqueID();\r
+}if(j&&e=="get"){f+=(f.contains("?")?"&":"?")+j;j=null;}var n=this.xhr;if(a){n.onloadstart=this.loadstart.bind(this);n.onprogress=this.progress.bind(this);\r
+}n.open(e.toUpperCase(),f,this.options.async,this.options.user,this.options.password);if(this.options.user&&"withCredentials" in n){n.withCredentials=true;\r
+}n.onreadystatechange=this.onStateChange.bind(this);Object.each(this.headers,function(q,p){try{n.setRequestHeader(p,q);}catch(r){this.fireEvent("exception",[p,q]);\r
+}},this);this.fireEvent("request");n.send(j);if(!this.options.async){this.onStateChange();}if(this.options.timeout){this.timer=this.timeout.delay(this.options.timeout,this);\r
+}return this;},cancel:function(){if(!this.running){return this;}this.running=false;var e=this.xhr;e.abort();clearTimeout(this.timer);e.onreadystatechange=d;\r
+if(a){e.onprogress=e.onloadstart=d;}this.xhr=new Browser.Request();this.fireEvent("cancel");return this;}});var b={};["get","post","put","delete","GET","POST","PUT","DELETE"].each(function(e){b[e]=function(g){var f={method:e};\r
+if(g!=null){f.data=g;}return this.send(f);};});c.implement(b);Element.Properties.send={set:function(e){var f=this.get("send").cancel();f.setOptions(e);\r
+return this;},get:function(){var e=this.retrieve("send");if(!e){e=new c({data:this,link:"cancel",method:this.get("method")||"post",url:this.get("action")});\r
+this.store("send",e);}return e;}};Element.implement({send:function(e){var f=this.get("send");f.send({data:this,url:e||f.options.url});return this;}});})();\r
+Request.HTML=new Class({Extends:Request,options:{update:false,append:false,evalScripts:true,filter:false,headers:{Accept:"text/html, application/xml, text/xml, */*"}},success:function(f){var e=this.options,c=this.response;\r
+c.html=f.stripScripts(function(h){c.javascript=h;});var d=c.html.match(/<body[^>]*>([\s\S]*?)<\/body>/i);if(d){c.html=d[1];}var b=new Element("div").set("html",c.html);\r
+c.tree=b.childNodes;c.elements=b.getElements(e.filter||"*");if(e.filter){c.tree=c.elements;}if(e.update){var g=document.id(e.update).empty();if(e.filter){g.adopt(c.elements);\r
+}else{g.set("html",c.html);}}else{if(e.append){var a=document.id(e.append);if(e.filter){c.elements.reverse().inject(a);}else{a.adopt(b.getChildren());}}}if(e.evalScripts){Browser.exec(c.javascript);\r
+}this.onSuccess(c.tree,c.elements,c.html,c.javascript);}});Element.Properties.load={set:function(a){var b=this.get("load").cancel();b.setOptions(a);return this;\r
+},get:function(){var a=this.retrieve("load");if(!a){a=new Request.HTML({data:this,link:"cancel",update:this,method:"get"});this.store("load",a);}return a;\r
+}};Element.implement({load:function(){this.get("load").send(Array.link(arguments,{data:Type.isObject,url:Type.isString}));return this;}});if(typeof JSON=="undefined"){this.JSON={};\r
+}JSON=new Hash({stringify:JSON.stringify,parse:JSON.parse});(function(){var special={"\b":"\\b","\t":"\\t","\n":"\\n","\f":"\\f","\r":"\\r",'"':'\\"',"\\":"\\\\"};\r
+var escape=function(chr){return special[chr]||"\\u"+("0000"+chr.charCodeAt(0).toString(16)).slice(-4);};JSON.validate=function(string){string=string.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g,"@").replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g,"]").replace(/(?:^|:|,)(?:\s*\[)+/g,"");\r
+return(/^[\],:{}\s]*$/).test(string);};JSON.encode=JSON.stringify?function(obj){return JSON.stringify(obj);}:function(obj){if(obj&&obj.toJSON){obj=obj.toJSON();\r
+}switch(typeOf(obj)){case"string":return'"'+obj.replace(/[\x00-\x1f\\"]/g,escape)+'"';case"array":return"["+obj.map(JSON.encode).clean()+"]";case"object":case"hash":var string=[];\r
+Object.each(obj,function(value,key){var json=JSON.encode(value);if(json){string.push(JSON.encode(key)+":"+json);}});return"{"+string+"}";case"number":case"boolean":return""+obj;\r
+case"null":return"null";}return null;};JSON.decode=function(string,secure){if(!string||typeOf(string)!="string"){return null;}if(secure||JSON.secure){if(JSON.parse){return JSON.parse(string);\r
+}if(!JSON.validate(string)){throw new Error("JSON could not decode the input; security is enabled and the value is not secure.");}}return eval("("+string+")");\r
+};})();Request.JSON=new Class({Extends:Request,options:{secure:true},initialize:function(a){this.parent(a);Object.append(this.headers,{Accept:"application/json","X-Request":"JSON"});\r
+},success:function(c){var b;try{b=this.response.json=JSON.decode(c,this.options.secure);}catch(a){this.fireEvent("error",[c,a]);return;}if(b==null){this.onFailure();\r
+}else{this.onSuccess(b,c);}}});var Cookie=new Class({Implements:Options,options:{path:"/",domain:false,duration:false,secure:false,document:document,encode:true},initialize:function(b,a){this.key=b;\r
+this.setOptions(a);},write:function(b){if(this.options.encode){b=encodeURIComponent(b);}if(this.options.domain){b+="; domain="+this.options.domain;}if(this.options.path){b+="; path="+this.options.path;\r
+}if(this.options.duration){var a=new Date();a.setTime(a.getTime()+this.options.duration*24*60*60*1000);b+="; expires="+a.toGMTString();}if(this.options.secure){b+="; secure";\r
+}this.options.document.cookie=this.key+"="+b;return this;},read:function(){var a=this.options.document.cookie.match("(?:^|;)\\s*"+this.key.escapeRegExp()+"=([^;]*)");\r
+return(a)?decodeURIComponent(a[1]):null;},dispose:function(){new Cookie(this.key,Object.merge({},this.options,{duration:-1})).write("");return this;}});\r
+Cookie.write=function(b,c,a){return new Cookie(b,a).write(c);};Cookie.read=function(a){return new Cookie(a).read();};Cookie.dispose=function(b,a){return new Cookie(b,a).dispose();\r
+};(function(i,k){var l,f,e=[],c,b,d=k.createElement("div");var g=function(){clearTimeout(b);if(l){return;}Browser.loaded=l=true;k.removeListener("DOMContentLoaded",g).removeListener("readystatechange",a);\r
+k.fireEvent("domready");i.fireEvent("domready");};var a=function(){for(var m=e.length;m--;){if(e[m]()){g();return true;}}return false;};var j=function(){clearTimeout(b);\r
+if(!a()){b=setTimeout(j,10);}};k.addListener("DOMContentLoaded",g);var h=function(){try{d.doScroll();return true;}catch(m){}return false;};if(d.doScroll&&!h()){e.push(h);\r
+c=true;}if(k.readyState){e.push(function(){var m=k.readyState;return(m=="loaded"||m=="complete");});}if("onreadystatechange" in k){k.addListener("readystatechange",a);\r
+}else{c=true;}if(c){j();}Element.Events.domready={onAdd:function(m){if(l){m.call(this);}}};Element.Events.load={base:"load",onAdd:function(m){if(f&&this==i){m.call(this);\r
+}},condition:function(){if(this==i){g();delete Element.Events.load;}return true;}};i.addEvent("load",function(){f=true;});})(window,document);(function(){var Swiff=this.Swiff=new Class({Implements:Options,options:{id:null,height:1,width:1,container:null,properties:{},params:{quality:"high",allowScriptAccess:"always",wMode:"window",swLiveConnect:true},callBacks:{},vars:{}},toElement:function(){return this.object;\r
+},initialize:function(path,options){this.instance="Swiff_"+String.uniqueID();this.setOptions(options);options=this.options;var id=this.id=options.id||this.instance;\r
+var container=document.id(options.container);Swiff.CallBacks[this.instance]={};var params=options.params,vars=options.vars,callBacks=options.callBacks;\r
+var properties=Object.append({height:options.height,width:options.width},options.properties);var self=this;for(var callBack in callBacks){Swiff.CallBacks[this.instance][callBack]=(function(option){return function(){return option.apply(self.object,arguments);\r
+};})(callBacks[callBack]);vars[callBack]="Swiff.CallBacks."+this.instance+"."+callBack;}params.flashVars=Object.toQueryString(vars);if(Browser.ie){properties.classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000";\r
+params.movie=path;}else{properties.type="application/x-shockwave-flash";}properties.data=path;var build='<object id="'+id+'"';for(var property in properties){build+=" "+property+'="'+properties[property]+'"';\r
+}build+=">";for(var param in params){if(params[param]){build+='<param name="'+param+'" value="'+params[param]+'" />';}}build+="</object>";this.object=((container)?container.empty():new Element("div")).set("html",build).firstChild;\r
+},replaces:function(element){element=document.id(element,true);element.parentNode.replaceChild(this.toElement(),element);return this;},inject:function(element){document.id(element,true).appendChild(this.toElement());\r
+return this;},remote:function(){return Swiff.remote.apply(Swiff,[this.toElement()].append(arguments));}});Swiff.CallBacks={};Swiff.remote=function(obj,fn){var rs=obj.CallFunction('<invoke name="'+fn+'" returntype="javascript">'+__flash__argumentsToXML(arguments,2)+"</invoke>");\r
+return eval(rs);};})();
\ No newline at end of file
diff --git a/testcms-final-anon/system/admin/theme/assets/js/popup.js b/testcms-final-anon/system/admin/theme/assets/js/popup.js
new file mode 100644 (file)
index 0000000..37d76c9
--- /dev/null
@@ -0,0 +1,90 @@
+\r
+var Popup = function() {\r
+\r
+       var $id = Number.random(100, 1000);\r
+       \r
+       var overlay = new Element('div', {\r
+               'id': 'popup_overlay_' + $id,\r
+               'class': 'popup_overlay'\r
+       });\r
+       \r
+       var box = new Element('div', {\r
+               'id': 'popup_box_' + $id,\r
+               'class': 'popup_box',\r
+               'styles': {\r
+                       'opacity': 0\r
+               }\r
+       });\r
+       \r
+       var position = function() {\r
+               var body = $$('body').pop(), \r
+                       offset = body.getScroll(), \r
+                       screen = body.getScrollSize(), \r
+                       size = box.getSize();\r
+       \r
+               return {\r
+                       'left': (screen.x / 2) - (size.x / 2),\r
+                       'top': offset.y + 50\r
+               };\r
+       };\r
+       \r
+       var open = function() {\r
+               var body = $$('body'), options = arguments[0] || {};\r
+               \r
+               // default options\r
+               var defaults = {\r
+                       'content': new Element('p'),\r
+                       'handle': false,\r
+                       'width': 600\r
+               }\r
+               \r
+               for(var key in defaults) {\r
+                       options[key] = (options[key] === undefined) ? defaults[key] : options[key];\r
+               }\r
+               \r
+               // append overlay\r
+               body.grab(overlay);\r
+               \r
+               // apply box styles\r
+               box.setStyles({\r
+                       'width': options.width\r
+               });\r
+               \r
+               // append box\r
+               body.grab(box);\r
+               \r
+               // add content\r
+               box.empty();\r
+               box.grab(options.content);\r
+\r
+               // position box and show\r
+               var pos = position();\r
+\r
+               box.setStyles({\r
+                       'top': pos.top,\r
+                       'left': pos.left\r
+               });\r
+               \r
+               box.fade('in');\r
+               \r
+               // bind events\r
+               overlay.addEvent('click', close);\r
+               \r
+               if(options.handle.addEvent) {\r
+                       options.handle.addEvent('click', close);\r
+               }\r
+       };\r
+       \r
+       var close = function() {\r
+               overlay.dispose();\r
+               box.dispose();\r
+               return false;\r
+       };\r
+       \r
+       return {\r
+               'open': open,\r
+               'close': close\r
+       };\r
+       \r
+};\r
+\r
diff --git a/testcms-final-anon/system/admin/theme/assets/js/tabs.js b/testcms-final-anon/system/admin/theme/assets/js/tabs.js
new file mode 100644 (file)
index 0000000..49ddc84
--- /dev/null
@@ -0,0 +1,34 @@
+(function() {\r
+       var hide = function() {\r
+               $$('.tab').setStyles({\r
+                       'display': 'none'\r
+               });\r
+\r
+               $$('.tabs a').removeClass('active');\r
+       };\r
+\r
+       var show = function(id) {\r
+               $$('[data-tab=' + id + ']').setStyles({\r
+                       'display': 'block'\r
+               });\r
+\r
+               $$('a[href$=#' + id + ']').addClass('active');\r
+       };\r
+\r
+       var tab = function() {\r
+               var id = this.get('href').split('#').pop();\r
+\r
+               hide();\r
+               show(id);\r
+       };\r
+\r
+       // hide all\r
+       hide();\r
+\r
+       // show first\r
+       var hash = window.location.hash, first = hash.length ? hash.split('#').pop() : 'post';\r
+       show(first);\r
+\r
+       // bind to menu\r
+       $$('.tabs a').addEvent('click', tab);\r
+}());
\ No newline at end of file
diff --git a/testcms-final-anon/system/admin/theme/error_500.php b/testcms-final-anon/system/admin/theme/error_500.php
new file mode 100644 (file)
index 0000000..eed38ea
--- /dev/null
@@ -0,0 +1,29 @@
+<!DOCTYPE html>\r
+<html>\r
+       <head>\r
+               <meta charset="utf-8">\r
+               <title>500 - Internal Server Error</title>\r
+\r
+               <style>\r
+                       body {\r
+                               background: #fff;\r
+                               font-family: sans-serif;\r
+                               color: #3f3f3f;\r
+                               margin: 0;\r
+                               padding: 40px;\r
+                       }\r
+                       h1 {\r
+                               padding: 0;\r
+                               margin: 0;\r
+                       }\r
+                       a {\r
+                               color: #57829e;\r
+                       }\r
+               </style>\r
+       </head>\r
+       <body>\r
+               <h1>Internal Server Error</h1>\r
+\r
+               <p>An error occured while we were processing your request.</p>\r
+       </body>\r
+</html>\r
diff --git a/testcms-final-anon/system/admin/theme/error_config.php b/testcms-final-anon/system/admin/theme/error_config.php
new file mode 100644 (file)
index 0000000..ef33814
--- /dev/null
@@ -0,0 +1,38 @@
+<!DOCTYPE html>\r
+<html>\r
+       <head>\r
+               <meta charset="utf-8">\r
+               <title>Missing config file</title>\r
+               \r
+               <style>\r
+                       body {\r
+                               background: #fff;\r
+                               font-family: sans-serif;\r
+                               color: #3f3f3f;\r
+                               padding: 10px;\r
+                       }\r
+                       h1, h3 {\r
+                               margin: 0 0 1em 0;\r
+                               padding: 0;\r
+                       }\r
+                       pre {\r
+                               font-size: 14px;\r
+                               margin: 0;\r
+                               padding: 0;\r
+                       }\r
+                       a {\r
+                               color: #57829e;\r
+                       }\r
+                       .content {\r
+                               padding: 10px;\r
+                               background: #eee;\r
+                               margin-bottom: 10px;\r
+                       }\r
+               </style>\r
+       </head>\r
+       <body>\r
+               <p>It looks like the config file is missing or unreadable.</p>\r
+\r
+               <p><a href="./install">Run the installer</a></p>\r
+       </body>\r
+</html>\r
diff --git a/testcms-final-anon/system/admin/theme/error_php.php b/testcms-final-anon/system/admin/theme/error_php.php
new file mode 100644 (file)
index 0000000..98ed703
--- /dev/null
@@ -0,0 +1,71 @@
+<!DOCTYPE html>\r
+<html>\r
+       <head>\r
+               <meta charset="utf-8">\r
+               <title>Error</title>\r
+\r
+               <style>\r
+                       body {\r
+                               background: #fff;\r
+                               font-family: sans-serif;\r
+                               color: #3f3f3f;\r
+                               padding: 10px;\r
+                       }\r
+                       h1, h3 {\r
+                               margin: 0 0 1em 0;\r
+                               padding: 0;\r
+                       }\r
+                       pre {\r
+                               font-size: 14px;\r
+                               margin: 0;\r
+                               padding: 0;\r
+                       }\r
+                       a {\r
+                               color: #57829e;\r
+                       }\r
+                       .content {\r
+                               padding: 10px;\r
+                               background: #eee;\r
+                               margin-bottom: 10px;\r
+                       }\r
+               </style>\r
+       </head>\r
+       <body>\r
+               <h1>Unhandled Exception</h1>\r
+\r
+               <div class="content">\r
+                       <h3>Message:</h3>\r
+                       <?php echo $message; ?> in <strong><?php echo str_replace(PATH, '', $file); ?></strong> on line <strong><?php echo $line; ?></strong>.\r
+               </div>\r
+\r
+               <div class="content">\r
+                       <h3>Stack Trace:</h3>\r
+\r
+                       <pre><?php echo $trace; ?></pre>\r
+               </div>\r
+\r
+               <div class="content">\r
+                       <h3>Context:</h3>\r
+\r
+                       <?php if(count($contexts)): ?>\r
+                               <?php foreach ($contexts as $num => $context): ?>\r
+                                       <pre><?php echo htmlentities($num.' '.$context); ?></pre>\r
+                               <?php endforeach; ?>\r
+                       <?php else: ?>\r
+                               Context unavailable.\r
+                       <?php endif; ?>\r
+               </div>\r
+               \r
+               <div class="content">\r
+                       <h3>Additional information</h3>\r
+                       \r
+                       <ul>\r
+                               <li>PHP Version: <?php echo phpversion(); ?></li>\r
+                               <li>Operating System: <?php echo php_uname(); ?></li>\r
+                               <li>Server Software: <?php echo $_SERVER['SERVER_SOFTWARE']; ?></li>\r
+                               <li>User Agent: <?php echo $_SERVER['HTTP_USER_AGENT']; ?></li>\r
+                               <li>Request Uri: <?php echo $_SERVER['REQUEST_URI']; ?></li>\r
+                       </ul>\r
+               </div>\r
+       </body>\r
+</html>\r
diff --git a/testcms-final-anon/system/admin/theme/functions.php b/testcms-final-anon/system/admin/theme/functions.php
new file mode 100644 (file)
index 0000000..6504d17
--- /dev/null
@@ -0,0 +1,127 @@
+<?php defined('IN_CMS') or die('No direct access allowed.');\r
+\r
+/**\r
+       Main menu\r
+*/\r
+function admin_menu() {\r
+\r
+    $prefix = Config::get('application.admin_folder');\r
+\r
+       $pages = array(\r
+               'Posts' => $prefix . '/posts',\r
+               'Pages' => $prefix . '/pages',\r
+               'Users' => $prefix . '/users',\r
+               'Metadata' => $prefix . '/metadata'\r
+       );\r
+\r
+       return $pages;\r
+}\r
+\r
+/**\r
+       Custom fields\r
+*/\r
+function parse_fields($str) {\r
+       $data = json_decode($str, true);\r
+       return is_array($data) ? $data : array();\r
+}\r
+\r
+/**\r
+       Url helpers\r
+*/\r
+function theme_url($file = '') {\r
+       return Config::get('application.base_url') . 'system/admin/theme/' . ltrim($file, '/');\r
+}\r
+\r
+function admin_url($url = '') {\r
+       return Url::make(Config::get('application.admin_folder') . '/' . ltrim($url, '/'));\r
+}\r
+\r
+/**\r
+       String helpers\r
+*/\r
+function pluralise($amount, $str, $alt = '') {\r
+    return $amount === 1 ? $str : $str . ($alt !== '' ? $alt : 's');\r
+}\r
+\r
+function truncate($str, $limit = 10, $elipse = ' [...]') {\r
+       $words = preg_split('/\s+/', $str);\r
+\r
+       if(count($words) <= $limit) {\r
+               return $str;\r
+       }\r
+\r
+       return implode(' ', array_slice($words, 0, $limit)) . $elipse;\r
+}\r
+       \r
+/**\r
+    Error checking\r
+*/\r
+function latest_version() {\r
+       // check we have curl support\r
+       if(Curl::support() === false) {\r
+               return 0;\r
+       }\r
+\r
+       // only run the version check once per session\r
+       if(($version = Session::get('latest_version')) === false) {\r
+               // returns plain text string with version number or 0 on failure.\r
+               $version = "0.6";\r
+               Session::set('latest_version', $version);\r
+       }\r
+\r
+       return $version;\r
+}\r
+\r
+function error_check() {\r
+    $errors = array();\r
+\r
+    //  Check for older versions\r
+    if(version_compare(VERSION, ($version = latest_version()), '<')) {\r
+        $errors[] = 'Your version of Test CMS is out of date. Please <a href="http://google.com">download the latest version</a>.';\r
+    }\r
+\r
+    // do something useful with it\r
+    return count($errors) ? $errors : false;\r
+}\r
+\r
+/**\r
+       Benchmarking\r
+*/\r
+function execution_time() {\r
+       $miliseconds = microtime(true) - START;\r
+       return round($miliseconds, 4);\r
+}\r
+\r
+// return in mb\r
+function memory_usage() {\r
+       return memory_get_peak_usage(true) / 1024;\r
+}\r
+\r
+// database profile information\r
+function db_profile() {\r
+       // total query time\r
+       $total = 0;\r
+\r
+       $html = '';\r
+       $html .= '<table id="debug_table" class="debug">';\r
+       $html .= '<thead><tr><th>SQL</th><th>Bindings</th><th>Rows</th><th>Time</th></th></thead>';\r
+\r
+       $html .= '<tbody>';\r
+\r
+       foreach(Db::profile() as $row) {\r
+               $html .= '<tr><td>' . $row['sql'] . '</td><td>' . implode(', ', $row['binds']) . '</td><td>' . $row['rows'] . '</td><td>' . $row['time'] . '</td></tr>';\r
+               $total += $row['time'];\r
+       }\r
+\r
+       $html .= '</tbody>';\r
+\r
+       $html .= '<tfoot>';\r
+       $html .= '<tr><td colspan="3"><strong>Query Time</strong></td><td>' . round($total, 4) . '</td></tr>';\r
+       $html .= '<tr><td colspan="3"><strong>Execution Time</strong></td><td>' . execution_time() . '</td></tr>';\r
+       $html .= '<tr><td colspan="3"><strong>Memory Usage</strong></td><td>' . memory_usage() . 'Kb</td></tr>';\r
+       $html .= '</tfoot>';\r
+\r
+       $html .= '</table>';\r
+\r
+       return $html;\r
+}\r
diff --git a/testcms-final-anon/system/admin/theme/includes/footer.php b/testcms-final-anon/system/admin/theme/includes/footer.php
new file mode 100644 (file)
index 0000000..ad4749b
--- /dev/null
@@ -0,0 +1,61 @@
+\r
+       <?php if(($user = Users::authed()) !== false): ?>\r
+       <aside id="sidebar">\r
+               <h2>Status check</h2>\r
+               \r
+               <?php if(error_check() !== false): ?>\r
+               <p>Oh no, we found <?php echo count(error_check()) === 1 ? 'a problem' : 'some problems'; ?>!</p>\r
+               \r
+               <ul>\r
+                   <?php foreach(error_check() as $error): ?>\r
+                   <li><?php echo $error; ?></li>\r
+                   <?php endforeach; ?>\r
+               </ul>\r
+               <?php else: ?>\r
+                   <p>Nice job, keep on going!</p>        \r
+               <?php endif; ?>\r
+       </aside>\r
+       <?php endif; ?>\r
+\r
+    <footer id="bottom">\r
+        <small>Powered by Test CMS, version <?php echo VERSION; ?>. \r
+        <a href="<?php echo Url::make(); ?>">Visit your site</a>.\r
+        <?php if(Config::get('debug', false)): ?>\r
+        <br><a id="debug_toggle" href="#debug">Show database profile</a>\r
+        <?php endif; ?></small>\r
+        \r
+        <em>Make blogging beautiful.</em>\r
+    </footer>\r
+\r
+       <?php if(Config::get('debug', false)): ?>\r
+       <?php echo db_profile(); ?>\r
+       <script>\r
+               (function() {\r
+                       var g = function(i) {\r
+                               var e = document.getElementById(i);\r
+                               e.s = function(p, v) {\r
+                                       this.style[p] = v;\r
+                               };\r
+                               e.g = function(p) {\r
+                                       return this.style[p];\r
+                               };\r
+\r
+                               return e;\r
+                       };\r
+\r
+                       var a = g('debug_toggle'), t = g('debug_table');\r
+\r
+                       var b = function(e) {\r
+                               var d = (t.g('display') == '' || t.g('display') == 'none') ? 'block' : 'none';\r
+                               t.s('display', d);\r
+                               e.preventDefault();\r
+                               e.stopPropagation();\r
+                       };\r
+\r
+                       a.addEventListener('click', b, false);\r
+               }());\r
+       </script>\r
+       <?php endif; ?>\r
+       \r
+       </body>\r
+</html>\r
diff --git a/testcms-final-anon/system/admin/theme/includes/header.php b/testcms-final-anon/system/admin/theme/includes/header.php
new file mode 100644 (file)
index 0000000..e1e9d46
--- /dev/null
@@ -0,0 +1,32 @@
+<!doctype html>\r
+<html lang="en">\r
+       <head>\r
+               <meta charset="utf-8">\r
+               <title>Manage <?php echo Config::get('metadata.sitename'); ?></title>\r
+\r
+               <link rel="stylesheet" href="<?php echo theme_url('assets/css/admin.css'); ?>">\r
+               <link rel="stylesheet" href="<?php echo theme_url('assets/css/popup.css'); ?>">\r
+       </head>\r
+       <body>\r
+\r
+               <header id="top">\r
+                       <a id="logo" href="<?php echo Url::make(Config::get('application.admin_folder')); ?>">\r
+                               <img src="<?php echo theme_url('assets/img/logo.png'); ?>" alt="Test CMS">\r
+                       </a>\r
+\r
+                       <?php if(($user = Users::authed()) !== false): ?>\r
+                       <nav>\r
+                               <ul>\r
+                                       <?php foreach(admin_menu() as $title => $url): ?>\r
+                                       <li <?php if(strpos(Url::current(), $url) !== false) echo 'class="active"'; ?>>\r
+                                               <a href="<?php echo Url::make($url); ?>"><?php echo $title; ?></a>\r
+                                       </li>\r
+                                       <?php endforeach; ?>\r
+                               </ul>\r
+                       </nav>\r
+\r
+                       <p>Logged in as <strong><?php echo $user->real_name; ?></strong>. \r
+                       <a href="<?php echo admin_url('users/logout'); ?>">Logout</a></li>\r
+                       <?php endif; ?>\r
+               </header>\r
+\r
diff --git a/testcms-final-anon/system/admin/theme/metadata/index.php b/testcms-final-anon/system/admin/theme/metadata/index.php
new file mode 100644 (file)
index 0000000..1f54bc0
--- /dev/null
@@ -0,0 +1,107 @@
+<h1>Site metadata</h1>\r
+\r
+<?php echo Notifications::read(); ?>\r
+\r
+<section class="content">\r
+\r
+       <form method="post" action="<?php echo Url::current(); ?>" novalidate>\r
+               <fieldset>\r
+                       <p>\r
+                       <label for="sitename">Site name:</label>\r
+                       <input id="sitename" name="sitename" value="<?php echo Input::post('name', $metadata->sitename); ?>">\r
+                       \r
+                       <em>Your site&rsquo;s name.</em>\r
+               </p>\r
+\r
+                       <p>\r
+                           <label for="description">Site description:</label>\r
+                           <textarea id="description" name="description"><?php echo Input::post('description', $metadata->description); ?></textarea>\r
+                           \r
+                           <em>A short paragraph to describe your site.</em>\r
+                       </p>\r
+\r
+                       <p>\r
+                           <label>Home Page:</label>\r
+                       <select id="home_page" name="home_page">\r
+                               <?php foreach($pages as $page): ?>\r
+                               <?php $selected = (Input::post('home_page', $metadata->home_page) == $page->id) ? ' selected' : ''; ?>\r
+                               <option value="<?php echo $page->id; ?>"<?php echo $selected; ?>>\r
+                                       <?php echo $page->name; ?>\r
+                               </option>\r
+                               <?php endforeach; ?>\r
+                       </select>\r
+                       \r
+                       <em>Your current home page.</em>\r
+                       </p>\r
+\r
+                       <p>\r
+                           <label>Posts Page:</label>\r
+                       <select id="posts_page" name="posts_page">\r
+                               <?php foreach($pages as $page): ?>\r
+                               <?php $selected = (Input::post('posts_page', $metadata->posts_page) == $page->id) ? ' selected' : ''; ?>\r
+                               <option value="<?php echo $page->id; ?>"<?php echo $selected; ?>>\r
+                                       <?php echo $page->name; ?>\r
+                               </option>\r
+                               <?php endforeach; ?>\r
+                       </select>\r
+                       \r
+                       <em>Your page that will show your posts.</em>\r
+                       </p>\r
+\r
+                       <p>\r
+                               <label for="posts_per_page">Posts per page:</label>\r
+                               <input id="posts_per_page" name="posts_per_page" value="<?php echo Input::post('posts_per_page', $metadata->posts_per_page); ?>">\r
+                               \r
+                               <em>The number of posts to display per page.</em>\r
+                       </p>\r
+                       \r
+                       <p>\r
+                               <label>Current theme:</label>\r
+                               <select id="theme" name="theme">\r
+                                       <?php foreach($themes as $theme => $about): ?>\r
+                                       <?php $selected = (Input::post('theme', $metadata->theme) == $theme) ? ' selected' : ''; ?>\r
+                                       <option value="<?php echo $theme; ?>"<?php echo $selected; ?>>\r
+                                               <?php echo $about['name']; ?> by <?php echo $about['author']; ?>\r
+                                       </option>\r
+                                       <?php endforeach; ?>\r
+                               </select>\r
+\r
+                               <em>Your current theme.</em>\r
+                       </p>\r
+\r
+                       <p>\r
+                               <label for="auto_published_comments">Auto publish comments:</label>\r
+                               <?php $checked = Input::post('auto_published_comments', $metadata->auto_published_comments) ? ' checked' : ''; ?>\r
+                               <input name="auto_published_comments" type="checkbox" value="1"<?php echo $checked; ?>>\r
+                       </p>\r
+\r
+                       <p>\r
+                               <label for="twitter">Twitter:</label>\r
+                               <input id="twitter" name="twitter" value="<?php echo Input::post('twitter', $metadata->twitter); ?>">\r
+                               \r
+                               <em>Your twitter account. Displayed as @<span id="output"><?php echo $metadata->twitter; ?></span>.</em>\r
+                       </p>\r
+               </fieldset>\r
+                       \r
+               <p class="buttons">\r
+                       <button name="save" type="submit">Save changes</button>\r
+               </p>\r
+       </form>\r
+\r
+</section>\r
+\r
+<script src="//ajax.googleapis.com/ajax/libs/mootools/1.4.1/mootools-yui-compressed.js"></script>\r
+<script>window.MooTools || document.write('<script src="<?php echo theme_url('assets/js/mootools.js'); ?>"><\/script>');</script>\r
+<script src="<?php echo theme_url('assets/js/helpers.js'); ?>"></script>\r
+<script>\r
+       (function() {\r
+               var tweet = $('twitter'), output = $('output');\r
+\r
+               // call the function to init the input text\r
+               formatTwitter(tweet, output);\r
+\r
+               // bind to input\r
+               tweet.addEvent('keyup', function() {formatTwitter(tweet, output)});\r
+       }());\r
+</script>\r
+\r
diff --git a/testcms-final-anon/system/admin/theme/pages/add.php b/testcms-final-anon/system/admin/theme/pages/add.php
new file mode 100644 (file)
index 0000000..63b0d12
--- /dev/null
@@ -0,0 +1,77 @@
+\r
+<h1>Add a Page</h1>\r
+\r
+<?php echo Notifications::read(); ?>\r
+\r
+<section class="content">\r
+\r
+       <form method="post" action="<?php echo Url::current(); ?>" novalidate>\r
+               <fieldset>\r
+                       <p>\r
+                       <label for="name">Name:</label>\r
+                       <input id="name" name="name" value="<?php echo Input::post('name'); ?>">\r
+                       \r
+                       <em>The name of your page. This gets shown in the navigation.</em>\r
+               </p>\r
+                       \r
+                       <p>\r
+                           <label>Title:</label>\r
+                           <input id="title" name="title" value="<?php echo Input::post('title'); ?>">\r
+                           \r
+                           <em>The title of your page, which gets shown in the <code>&lt;title&gt;</code>.</em>\r
+                       </p>\r
+                       \r
+                       <p>\r
+                           <label for="slug">Slug:</label>\r
+                           <input id="slug" autocomplete="off" name="slug" value="<?php echo Input::post('slug'); ?>">\r
+                           \r
+                           <em>The slug for your post (<code><?php echo $_SERVER['HTTP_HOST']; ?>/<span id="output">slug</span></code>).</em>\r
+                       </p>\r
+                       \r
+                       <p>\r
+                           <label for="content">Content:</label>\r
+                           <textarea id="content" name="content"><?php echo Input::post('content'); ?></textarea>\r
+                           \r
+                           <em>Your page's content. Accepts valid HTML.</em>\r
+                       </p>\r
+                       \r
+                       <p>\r
+                           <label>Status:</label>\r
+                       <select id="status" name="status">\r
+                               <?php foreach(array('draft', 'archived', 'published') as $status): ?>\r
+                               <option value="<?php echo $status; ?>" <?php if(Input::post('status') == $status) echo 'selected'; ?>>\r
+                                       <?php echo ucwords($status); ?>\r
+                               </option>\r
+                               <?php endforeach; ?>\r
+                       </select>\r
+                       \r
+                       <em>Do you want your page to be live (published), pending (draft), or hidden (archived)?</em>\r
+                       </p>\r
+               </fieldset>\r
+                       \r
+               <p class="buttons">\r
+                       <button type="submit">Create</button>\r
+                       <a href="<?php echo admin_url('pages'); ?>">Return to pages</a>\r
+               </p>\r
+       </form>\r
+\r
+</section>\r
+\r
+<script src="//ajax.googleapis.com/ajax/libs/mootools/1.4.1/mootools-yui-compressed.js"></script>\r
+<script>window.MooTools || document.write('<script src="<?php echo theme_url('assets/js/mootools.js'); ?>"><\/script>');</script>\r
+\r
+<script src="<?php echo theme_url('assets/js/helpers.js'); ?>"></script>\r
+\r
+<script>\r
+       (function() {\r
+               var slug = $('slug'), output = $('output');\r
+\r
+               // call the function to init the input text\r
+               formatSlug(slug, output);\r
+\r
+               // bind to input\r
+               slug.addEvent('keyup', function() {formatSlug(slug, output)});\r
+       }());\r
+</script>\r
+\r
+\r
diff --git a/testcms-final-anon/system/admin/theme/pages/edit.php b/testcms-final-anon/system/admin/theme/pages/edit.php
new file mode 100644 (file)
index 0000000..7e61f30
--- /dev/null
@@ -0,0 +1,89 @@
+<h1>Editing &ldquo;<?php echo truncate($page->name, 4); ?>&rdquo;</h1>\r
+\r
+<?php echo Notifications::read(); ?>\r
+\r
+<section class="content">\r
+\r
+       <form method="post" action="<?php echo Url::current(); ?>" novalidate>\r
+               <fieldset>\r
+                       <p>\r
+                       <label for="name">Name:</label>\r
+                       <input id="name" name="name" value="<?php echo Input::post('name', $page->name); ?>">\r
+                       \r
+                       <em>The name of your page. This gets shown in the navigation.</em>\r
+               </p>\r
+                       \r
+                       <p>\r
+                           <label>Title:</label>\r
+                           <input id="title" name="title" value="<?php echo Input::post('title', $page->title); ?>">\r
+                           \r
+                           <em>The title of your page, which gets shown in the <code>&lt;title&gt;</code>.</em>\r
+                       </p>\r
+                       \r
+                       <p>\r
+                           <label for="slug">Slug:</label>\r
+                           <input id="slug" autocomplete="off" name="slug" value="<?php echo Input::post('slug', $page->slug); ?>">\r
+                           \r
+                           <em>The slug for your page (<code id="output">slug</code>).</em>\r
+                       </p>\r
+                       \r
+                       <p>\r
+                           <label for="content">Content:</label>\r
+                           <textarea id="content" name="content"><?php echo Input::post('content', $page->content); ?></textarea>\r
+                           \r
+                           <em>Your page's content. Accepts valid HTML.</em>\r
+                       </p>\r
+                       \r
+                       <p>\r
+                           <label>Status:</label>\r
+                       <select id="status" name="status">\r
+                               <?php foreach(array('draft', 'archived', 'published') as $status): ?>\r
+                               <?php $selected = (Input::post('status', $page->status) == $status) ? 'selected' : ''; ?>\r
+                               <option value="<?php echo $status; ?>"<?php echo $selected; ?>>\r
+                                       <?php echo ucwords($status); ?>\r
+                               </option>\r
+                               <?php endforeach; ?>\r
+                       </select>\r
+                       \r
+                       <em>Do you want your page to be live (published), pending (draft), or hidden (archived)?</em>\r
+                       </p>\r
+               </fieldset>\r
+                       \r
+               <p class="buttons">\r
+\r
+                       <button name="save" type="submit">Save</button>\r
+                       <?php \r
+                       // Dont delete our posts page or home page\r
+                       if(in_array($page->id, array(Config::get('metadata.home_page'), Config::get('metadata.posts_page'))) === false): ?>\r
+                       <button name="delete" type="submit">Delete</button>\r
+                       <?php endif; ?>\r
+                       \r
+                       <a href="<?php echo admin_url('pages'); ?>">Return to pages</a>\r
+               </p>\r
+       </form>\r
+\r
+</section>\r
+\r
+<aside id="sidebar">\r
+       <h2>Editing</h2>\r
+       <em>Some useful links.</em>\r
+       <ul>\r
+               <li><a href="<?php echo Url::make($page->slug); ?>">View this page on your site</a></li>\r
+       </ul>\r
+</aside>\r
+\r
+<script src="//ajax.googleapis.com/ajax/libs/mootools/1.4.1/mootools-yui-compressed.js"></script>\r
+<script>window.MooTools || document.write('<script src="<?php echo theme_url('assets/js/mootools.js'); ?>"><\/script>');</script>\r
+<script src="<?php echo theme_url('assets/js/helpers.js'); ?>"></script>\r
+<script>\r
+       (function() {\r
+               var slug = $('slug'), output = $('output');\r
+\r
+               // call the function to init the input text\r
+               formatSlug(slug, output);\r
+\r
+               // bind to input\r
+               slug.addEvent('keyup', function() {formatSlug(slug, output)});\r
+       }());\r
+</script>\r
+\r
diff --git a/testcms-final-anon/system/admin/theme/pages/index.php b/testcms-final-anon/system/admin/theme/pages/index.php
new file mode 100644 (file)
index 0000000..4fabbbd
--- /dev/null
@@ -0,0 +1,20 @@
+<h1>Pages <a href="<?php echo admin_url('pages/add'); ?>">Create a new page</a></h1>\r
+\r
+<?php echo Notifications::read(); ?>\r
+       \r
+<section class="content">\r
+       <?php if($pages->length()): ?>\r
+       <ul class="list">\r
+           <?php foreach($pages as $page): ?>\r
+           <li>\r
+               <a href="<?php echo admin_url('pages/edit/' . $page->id); ?>">\r
+                   <strong><?php echo truncate($page->name, 4); ?></strong>\r
+                   <i class="status"><?php echo ucwords($page->status); ?></i>\r
+               </a>\r
+           </li>\r
+           <?php endforeach; ?>\r
+       </ul>\r
+       <?php else: ?>\r
+       <p>No pages just yet. Why not <a href="<?php echo admin_url('pages/add'); ?>">write a new one</a>?</p>\r
+       <?php endif; ?>\r
+</section>\r
diff --git a/testcms-final-anon/system/admin/theme/posts/add.php b/testcms-final-anon/system/admin/theme/posts/add.php
new file mode 100644 (file)
index 0000000..cc16c58
--- /dev/null
@@ -0,0 +1,136 @@
+\r
+<h1>Add a Post</h1>\r
+\r
+<?php echo Notifications::read(); ?>\r
+\r
+<section class="content">\r
+       <nav class="tabs">\r
+               <ul>\r
+                       <li><a href="#post">Post</a></li>\r
+                       <li><a href="#customise">Customise</a></li>\r
+                       <li><a href="#fields">Custom Fields</a></li>\r
+                       <li><a href="#comments">Comments</a></li>\r
+               </ul>\r
+       </nav>\r
+       <form method="post" action="<?php echo Url::current(); ?>" novalidate>\r
+               <div data-tab="post" class="tab">\r
+\r
+                       <fieldset>\r
+                               <p>\r
+                               <label for="title">Title:</label>\r
+                               <input id="title" name="title" value="<?php echo Input::post('title'); ?>">\r
+                               \r
+                               <em>Your post&rsquo;s title.</em>\r
+                       </p>\r
+                               \r
+                               <p>\r
+                                   <label for="slug">Slug:</label>\r
+                                   <input id="slug" autocomplete="off" name="slug" value="<?php echo Input::post('slug'); ?>">\r
+                                   \r
+                                   <em>The slug for your post (<code id="output">slug</code>).</em>\r
+                               </p>\r
+                               \r
+                   <p>\r
+                       <label for="description">Description:</label>\r
+                       <textarea id="description" name="description"><?php echo Input::post('description'); ?></textarea>\r
+                       \r
+                       <em>A brief outline of what your post is about. Used in the post introduction, RSS feed, and <code>&lt;meta name="description" /&gt;</code>.</em>\r
+                   </p>\r
+                   \r
+                               <p>\r
+                                   <label for="html">Content:</label>\r
+                                   <textarea id="html" name="html"><?php echo Input::post('html'); ?></textarea>\r
+                                   \r
+                                   <em>Your post's main content. Enjoys a healthy dose of valid HTML.</em>\r
+                               </p>\r
+                               \r
+                               <p>\r
+                                   <label>Status:</label>\r
+                               <select id="status" name="status">\r
+                                       <?php foreach(array('draft', 'archived', 'published') as $status): ?>\r
+                                       <?php $selected = (Input::post('status') == $status) ? ' selected' : ''; ?>\r
+                                       <option value="<?php echo $status; ?>"<?php echo $selected; ?>>\r
+                                               <?php echo ucwords($status); ?>\r
+                                       </option>\r
+                                       <?php endforeach; ?>\r
+                               </select>\r
+                               \r
+                               <em>Statuses: live (published), pending (draft), or hidden (archived).</em>\r
+                               </p>\r
+                               \r
+                               <p>\r
+                                   <label for="comments">Allow Comments:</label>\r
+                                   <input id="comments" name="comments" type="checkbox" value="1"<?php if(Input::post('comments')) echo ' checked'; ?>>\r
+                                   <em>This will allow users to comment on your posts.</em>\r
+                               </p>\r
+                       </fieldset>\r
+               \r
+               </div>\r
+               <div data-tab="customise" class="tab">\r
+\r
+                       <fieldset>\r
+                           <legend>Customise</legend>\r
+                           <em>Here, you can customise your posts. This section is optional.</em>\r
+                           \r
+                           <p>\r
+                               <label for="css">Custom CSS:</label>\r
+                               <textarea id="css" name="css"><?php echo Input::post('css'); ?></textarea>\r
+                               \r
+                               <em>Custom CSS. Will be wrapped in a <code>&lt;style&gt;</code> block.</em>\r
+                           </p>\r
+\r
+                   <p>\r
+                       <label for="js">Custom JS:</label>\r
+                       <textarea id="js" name="js"><?php echo Input::post('js'); ?></textarea>\r
+                       \r
+                       <em>Custom Javascript. Will be wrapped in a <code>&lt;script&gt;</code> block.</em>\r
+                   </p>\r
+                       </fieldset>\r
+               \r
+               </div>\r
+               <div data-tab="fields" class="tab">\r
+\r
+                       <fieldset>\r
+                           <legend>Custom fields</legend>\r
+                           <em>Create custom fields here.</em>\r
+\r
+                               <div id="fields">\r
+                                       <!-- Re-Populate post data -->\r
+                                       <?php foreach(Input::post('field', array()) as $data => $value): ?>\r
+                                       <?php list($key, $label) = explode(':', $data); ?>\r
+                                       <p>\r
+                                               <label><?php echo $label; ?></label>\r
+                                               <input name="field[<?php echo $key; ?>:<?php echo $label; ?>]" value="<?php echo $value; ?>">\r
+                                       </p>\r
+                                       <?php endforeach; ?>\r
+                               </div>\r
+                       </fieldset>\r
+\r
+                       <button id="create" type="button">Create a custom field</button>\r
+               </div>\r
+                       \r
+               <p class="buttons">\r
+                       <button type="submit">Create</button>\r
+                       <a href="<?php echo admin_url('posts'); ?>">Return to posts</a>\r
+               </p>\r
+       </form>\r
+\r
+</section>\r
+\r
+<script src="//ajax.googleapis.com/ajax/libs/mootools/1.4.1/mootools-yui-compressed.js"></script>\r
+<script>window.MooTools || document.write('<script src="<?php echo theme_url('assets/js/mootools.js'); ?>"><\/script>');</script>\r
+<script src="<?php echo theme_url('assets/js/helpers.js'); ?>"></script>\r
+<script src="<?php echo theme_url('assets/js/popup.js'); ?>"></script>\r
+<script src="<?php echo theme_url('assets/js/custom_fields.js'); ?>"></script>\r
+<script src="<?php echo theme_url('assets/js/tabs.js'); ?>"></script>\r
+<script>\r
+       (function() {\r
+               var slug = $('slug'), output = $('output');\r
+\r
+               // call the function to init the input text\r
+               formatSlug(slug, output);\r
+\r
+               // bind to input\r
+               slug.addEvent('keyup', function() {formatSlug(slug, output)});\r
+       }());\r
+</script>
\ No newline at end of file
diff --git a/testcms-final-anon/system/admin/theme/posts/edit.php b/testcms-final-anon/system/admin/theme/posts/edit.php
new file mode 100644 (file)
index 0000000..958f8d7
--- /dev/null
@@ -0,0 +1,197 @@
+\r
+<h1>Editing &ldquo;<?php echo truncate($article->title, 4); ?>&rdquo;</h1>\r
+\r
+<?php echo Notifications::read(); ?>\r
+\r
+<section class="content">\r
+       <nav class="tabs">\r
+               <ul>\r
+                       <li><a href="#post">Post</a></li>\r
+                       <li><a href="#customise">Customise</a></li>\r
+                       <li><a href="#fields">Custom Fields</a></li>\r
+                       <li>\r
+                           <a href="#comments">Comments                            \r
+                           <?php if($pending > 0): ?>\r
+                               <span title="You have <?php echo $pending; ?> comments"><?php echo $pending; ?></span>\r
+                           <?php endif; ?>\r
+                   </a>\r
+               </li>\r
+               </ul>\r
+       </nav>\r
+       <form method="post" action="<?php echo Url::current(); ?>" novalidate>\r
+\r
+               <div data-tab="post" class="tab">\r
+\r
+                       <fieldset>\r
+                               <p>\r
+                               <label for="title">Title:</label>\r
+                               <input id="title" name="title" value="<?php echo Input::post('title', $article->title); ?>">\r
+                               \r
+                               <em>Your post&rsquo;s title.</em>\r
+                       </p>\r
+                               \r
+                               <p>\r
+                                   <label for="slug">Slug:</label>\r
+                                   <input type="url" id="slug" autocomplete="off" name="slug" value="<?php echo Input::post('slug', $article->slug); ?>">\r
+                                   \r
+                                   <em>The slug for your post (<code id="output">slug</code>).</em>\r
+                               </p>\r
+                               \r
+                   <p>\r
+                       <label for="description">Description:</label>\r
+                       <textarea id="description" name="description"><?php echo Input::post('description', $article->description); ?></textarea>\r
+                       \r
+                       <em>A brief outline of what your post is about. Used in the post introduction, RSS feed, and <code>&lt;meta name="description" /&gt;</code>.</em>\r
+                   </p>\r
+                   \r
+                               <p>\r
+                                   <label for="html">Content:</label>\r
+                                   <textarea id="html" name="html"><?php echo Input::post('html', $article->html); ?></textarea>\r
+                                   \r
+                                   <em>Your post's main content. Enjoys a healthy dose of valid HTML.</em>\r
+                               </p>\r
+                               \r
+                               <p>\r
+                                   <label>Status:</label>\r
+                               <select id="status" name="status">\r
+                                       <?php foreach(array('draft', 'archived', 'published') as $status): ?>\r
+                                       <?php $selected = (Input::post('status', $article->status) == $status) ? ' selected' : ''; ?>\r
+                                       <option value="<?php echo $status; ?>"<?php echo $selected; ?>>\r
+                                               <?php echo ucwords($status); ?>\r
+                                       </option>\r
+                                       <?php endforeach; ?>\r
+                               </select>\r
+                               \r
+                               <em>Statuses: live (published), pending (draft), or hidden (archived).</em>\r
+                               </p>\r
+                               \r
+                               <p>\r
+                                   <label for="comments">Allow Comments:</label>\r
+                                   <input id="comments" name="comments" type="checkbox" value="1"<?php if(Input::post('comments', $article->comments)) echo ' checked'; ?>>\r
+                                   <em>This will allow users to comment on your posts.</em>\r
+                               </p>\r
+                       </fieldset>\r
+               \r
+               </div>\r
+               <div data-tab="customise" class="tab">\r
+\r
+                       <fieldset>\r
+                           <legend>Customise</legend>\r
+                           <em>Here, you can customise your posts. This section is optional.</em>\r
+                           \r
+                           <p>\r
+                               <label for="css">Custom CSS:</label>\r
+                               <textarea id="css" name="css"><?php echo Input::post('css', $article->css); ?></textarea>\r
+                               \r
+                               <em>Custom CSS. Will be wrapped in a <code>&lt;style&gt;</code> block.</em>\r
+                           </p>\r
+\r
+                   <p>\r
+                       <label for="js">Custom JS:</label>\r
+                       <textarea id="js" name="js"><?php echo Input::post('js', $article->js); ?></textarea>\r
+                       \r
+                       <em>Custom Javascript. Will be wrapped in a <code>&lt;script&gt;</code> block.</em>\r
+                   </p>\r
+                       </fieldset>\r
+               \r
+               </div>\r
+               <div data-tab="fields" class="tab">\r
+\r
+                       <fieldset>\r
+                           <legend>Custom fields</legend>\r
+                           <em>Create custom fields here.</em>\r
+\r
+                               <div id="fields">\r
+                                       <!-- Re-Populate data -->\r
+                                       <?php foreach(parse_fields($article->custom_fields) as $key => $data): ?>\r
+                                       <p>\r
+                                               <label><?php echo $data['label']; ?></label>\r
+                                               <input name="field[<?php echo $key; ?>:<?php echo $data['label']; ?>]" value="<?php echo $data['value']; ?>">\r
+                                       </p>\r
+                                       <?php endforeach; ?>\r
+                                       \r
+                                       <!-- Re-Populate post data -->\r
+                                       <?php foreach(Input::post('field', array()) as $data => $value): ?>\r
+                                       <?php list($key, $label) = explode(':', $data); ?>\r
+                                       <p>\r
+                                               <label><?php echo $label; ?></label>\r
+                                               <input name="field[<?php echo $key; ?>:<?php echo $label; ?>]" value="<?php echo $value; ?>">\r
+                                       </p>\r
+                                       <?php endforeach; ?>\r
+                               </div>\r
+                               \r
+                               \r
+                               <button id="create" type="button">Create a custom field</button>\r
+                       </fieldset>\r
+               \r
+               </div>\r
+               <div data-tab="comments" class="tab">\r
+\r
+                       <fieldset>\r
+                           <legend>Comments</legend>\r
+                           <em>Here, you can moderate your comments.</em>\r
+\r
+                           <?php if(count($comments)): ?>\r
+                           <ul id="comments">\r
+                           <?php foreach($comments as $comment):?>\r
+                           <li data-id="<?php echo $comment->id; ?>">\r
+                               <header>\r
+                               <p><strong><?php echo $comment->name; ?></strong> \r
+                               <?php echo date(Config::get('metadata.date_format'), $comment->date); ?><br>\r
+                               <em>Status: <span data-status="<?php echo $comment->id; ?>"><?php echo $comment->status; ?></span></em></p>\r
+                           </header>\r
+                           \r
+                               <p class="comment" data-text="<?php echo $comment->id; ?>"><?php echo $comment->text; ?></p>\r
+                               \r
+                               <ul class="options">\r
+                                       <?php if($comment->status == 'pending'): ?>\r
+                                       <li><a href="#publish">Publish</a></li>\r
+                                       <?php endif; ?>\r
+                                       <li><a href="#edit">Edit</a></li>\r
+                                       <li><a href="#delete">Delete</a></li>\r
+                               </ul>\r
+                           </li>\r
+                           <?php endforeach; ?>\r
+                           </ul>\r
+                           <?php else: ?>\r
+                           <p>No comments yet.</p>\r
+                           <?php endif; ?>\r
+                       </fieldset>\r
+               \r
+               </div>\r
+\r
+               <p class="buttons">\r
+                       <button name="save" type="submit">Save</button>\r
+                       <button name="delete" type="submit">Delete</button>\r
+                       <a href="<?php echo admin_url('posts'); ?>">Return to posts</a>\r
+               </p>\r
+               \r
+       </form>\r
+</section>\r
+\r
+<aside id="sidebar">\r
+       <h2>Editing</h2>\r
+       <em>Some useful links.</em>\r
+       <ul>\r
+               <li><a href="<?php echo Url::make($page->slug . '/' . $article->slug); ?>">View this post on your site</a></li>\r
+       </ul>\r
+</aside>\r
+\r
+<script src="//ajax.googleapis.com/ajax/libs/mootools/1.4.1/mootools-yui-compressed.js"></script>\r
+<script>window.MooTools || document.write('<script src="<?php echo theme_url('assets/js/mootools.js'); ?>"><\/script>');</script>\r
+<script src="<?php echo theme_url('assets/js/helpers.js'); ?>"></script>\r
+<script src="<?php echo theme_url('assets/js/popup.js'); ?>"></script>\r
+<script src="<?php echo theme_url('assets/js/custom_fields.js'); ?>"></script>\r
+<script src="<?php echo theme_url('assets/js/comments.js'); ?>"></script>\r
+<script src="<?php echo theme_url('assets/js/tabs.js'); ?>"></script>\r
+<script>\r
+       (function() {\r
+               var slug = $('slug'), output = $('output');\r
+\r
+               // call the function to init the input text\r
+               formatSlug(slug, output);\r
+\r
+               // bind to input\r
+               slug.addEvent('keyup', function() {formatSlug(slug, output)});\r
+       }());\r
+</script>
\ No newline at end of file
diff --git a/testcms-final-anon/system/admin/theme/posts/index.php b/testcms-final-anon/system/admin/theme/posts/index.php
new file mode 100644 (file)
index 0000000..074239f
--- /dev/null
@@ -0,0 +1,23 @@
+<h1>Posts <a href="<?php echo admin_url('posts/add'); ?>">Create a new post</a></h1>\r
+\r
+<?php echo Notifications::read(); ?>\r
+\r
+<section class="content">\r
+       <?php if($posts->length()): ?>\r
+       <ul class="list">\r
+           <?php foreach($posts as $article): ?>\r
+           <li>\r
+               <a href="<?php echo admin_url('posts/edit/' . $article->id); ?>">\r
+                   <strong><?php echo truncate($article->title, 4); ?></strong>\r
+                   <span>Created <time><?php echo date(Config::get('metadata.date_format'), $article->created); ?></time> \r
+                   by <?php echo $article->author; ?></span>\r
+                   \r
+                   <i class="status"><?php echo $article->status; ?></i>\r
+               </a>\r
+           </li>\r
+           <?php endforeach; ?>\r
+       </ul>\r
+       <?php else: ?>\r
+       <p>No posts just yet. Why not <a href="<?php echo admin_url('posts/add'); ?>">write a new one</a>?</p>\r
+       <?php endif; ?>\r
+</section>\r
diff --git a/testcms-final-anon/system/admin/theme/users/add.php b/testcms-final-anon/system/admin/theme/users/add.php
new file mode 100644 (file)
index 0000000..4707ecc
--- /dev/null
@@ -0,0 +1,86 @@
+<h1>Add a new user</h1>\r
+\r
+<?php echo Notifications::read(); ?>\r
+\r
+<section class="content">\r
+\r
+       <form method="post" action="<?php echo Url::current(); ?>" novalidate autocomplete="off">\r
+               <fieldset>\r
+                       <p>\r
+                       <label for="real_name">Real name:</label>\r
+                       <input id="real_name" name="real_name" value="<?php echo Input::post('real_name'); ?>">\r
+                       \r
+                       <em>The user&rsquo;s real name. Used in author bylines (visible to public).</em>\r
+               </p>\r
+                                               \r
+            <p>\r
+                <label for="bio">Biography:</label>\r
+                <textarea id="bio" name="bio"><?php echo Input::post('bio'); ?></textarea>\r
+                \r
+                <em>A short biography for your user. Accepts valid HTML.</em>\r
+            </p>\r
+                       \r
+                       <p>\r
+                           <label for="status">Status:</label>\r
+                       <select id="status" name="status">\r
+                               <?php foreach(array('inactive','active') as $status): ?>\r
+                               <?php $selected = (Input::post('status') == $status) ? ' selected' : ''; ?>\r
+                               <option value="<?php echo $status; ?>"<?php echo $selected; ?>>\r
+                                       <?php echo ucwords($status); ?>\r
+                               </option>\r
+                               <?php endforeach; ?>\r
+                       </select>\r
+                       \r
+                       <em>If inactive, the user will not be able to log in.</em>\r
+                       </p>\r
+                       \r
+                       <p>\r
+                           <label for="role">Role:</label>\r
+                       <select id="role" name="role">\r
+                               <?php foreach(array('administrator', 'editor', 'user') as $role): ?>\r
+                               <?php $selected = (Input::post('role') == $role) ? ' selected' : ''; ?>\r
+                               <option value="<?php echo $role; ?>"<?php echo $selected; ?>>\r
+                                       <?php echo ucwords($role); ?>\r
+                               </option>\r
+                               <?php endforeach; ?>\r
+                       </select>\r
+                       \r
+                       <em>The user&rsquo;s role. See <a href="//google.com">here</a> for more info.</em>\r
+                       </p>\r
+               </fieldset>\r
+               \r
+               <fieldset>\r
+               \r
+                   <legend>User details</legend>\r
+                   <em>Create the details for your new user to log in to TestCMS.</em>\r
+               \r
+                   <p>\r
+                       <label for="username">Username:</label>\r
+                       <input id="username" name="username" value="<?php echo Input::post('username'); ?>">\r
+                       \r
+                       <em>The desired username. Can be changed later.</em>\r
+                   </p>\r
+\r
+            <p>\r
+                <label for="password">Password:</label>\r
+                <input id="password" type="password" name="password">\r
+                \r
+                <em>And the matching password. Can be changed later.</em>\r
+            </p>\r
+            \r
+                   <p>\r
+                       <label for="email">Email:</label>\r
+                       <input id="email" name="email" value="<?php echo Input::post('email'); ?>">\r
+                       \r
+                       <em>The user&rsquo;s email address. Needed if the user forgets their password.</em>\r
+                   </p>\r
+               </fieldset>\r
+                       \r
+               <p class="buttons">\r
+                       <button type="submit">Create</button>\r
+                       <a href="<?php echo admin_url('users'); ?>">Return to users</a>\r
+               </p>\r
+       </form>\r
+\r
+</section>\r
+\r
diff --git a/testcms-final-anon/system/admin/theme/users/amnesia.php b/testcms-final-anon/system/admin/theme/users/amnesia.php
new file mode 100644 (file)
index 0000000..1686470
--- /dev/null
@@ -0,0 +1,23 @@
+<h1>Recover Password</h1>\r
+\r
+<?php echo Notifications::read(); ?>\r
+\r
+<section class="content">\r
+\r
+       <form method="post" action="<?php echo Url::current(); ?>" >\r
+               <fieldset>\r
+                       \r
+                       <p>\r
+                           <label for="email">Email:</label>\r
+                           <input autocapitalize="off" name="email" id="email" value="<?php echo Input::post('email'); ?>">\r
+                       </p>\r
+\r
+                       <p class="buttons">\r
+                           <button type="submit">Recover</button>\r
+                           <a href="<?php echo Url::make(); ?>">Back to <?php echo Config::get('metadata.sitename'); ?></a>\r
+                       </p>\r
+               </fieldset>\r
+       </form>\r
+\r
+</section>\r
+\r
diff --git a/testcms-final-anon/system/admin/theme/users/edit.php b/testcms-final-anon/system/admin/theme/users/edit.php
new file mode 100644 (file)
index 0000000..c6f9e99
--- /dev/null
@@ -0,0 +1,89 @@
+<h1>Editing <?php echo $user->username; ?>&rsquo;s profile</h1>\r
+\r
+<?php echo Notifications::read(); ?>\r
+\r
+<section class="content">\r
+\r
+       <form method="post" action="<?php echo Url::current(); ?>" novalidate autocomplete="off">\r
+               <fieldset>\r
+                       <p>\r
+                       <label for="real_name">Real name:</label>\r
+                       <input id="real_name" name="real_name" value="<?php echo Input::post('real_name', $user->real_name); ?>">\r
+                       \r
+                       <em>The user&rsquo;s real name. Used in author bylines (visible to public).</em>\r
+               </p>\r
+                                               \r
+            <p>\r
+                <label for="bio">Biography:</label>\r
+                <textarea id="bio" name="bio"><?php echo Input::post('bio', $user->bio); ?></textarea>\r
+                \r
+                <em>A short biography for your user. Accepts valid HTML.</em>\r
+            </p>\r
+                       \r
+                       <p>\r
+                           <label for="status">Status:</label>\r
+                       <select id="status" name="status">\r
+                               <?php foreach(array('inactive','active') as $status): ?>\r
+                               <?php $selected = (Input::post('status', $user->status) == $status) ? ' selected' : ''; ?>\r
+                               <option value="<?php echo $status; ?>"<?php echo $selected; ?>>\r
+                                       <?php echo ucwords($status); ?>\r
+                               </option>\r
+                               <?php endforeach; ?>\r
+                       </select>\r
+                       \r
+                       <em>If inactive, the user will not be able to log in.</em>\r
+                       </p>\r
+                       \r
+                       <p>\r
+                           <label for="role">Role:</label>\r
+                       <select id="role" name="role">\r
+                               <?php foreach(array('administrator', 'editor', 'user') as $role): ?>\r
+                               <?php $selected = (Input::post('role', $user->role) == $role) ? ' selected' : ''; ?>\r
+                               <option value="<?php echo $role; ?>"<?php echo $selected; ?>>\r
+                                       <?php echo ucwords($role); ?>\r
+                               </option>\r
+                               <?php endforeach; ?>\r
+                       </select>\r
+                       \r
+                       <em>The user&rsquo;s role. See <a href="//google.com">here</a> for more info.</em>\r
+                       </p>\r
+               </fieldset>\r
+               \r
+               <fieldset>\r
+               \r
+                   <legend>User details</legend>\r
+                   <em>Create the details for your new user to log in to Test CMS.</em>\r
+               \r
+                   <p>\r
+                       <label for="username">Username:</label>\r
+                       <input id="username" name="username" value="<?php echo Input::post('username', $user->username); ?>">\r
+                       \r
+                       <em>The desired username. Can be changed later.</em>\r
+                   </p>\r
+\r
+            <p>\r
+                <label for="password">Password:</label>\r
+                <input id="password" type="password" name="password">\r
+                \r
+                <em>Leave blank for no change.</em>\r
+            </p>\r
+            \r
+                   <p>\r
+                       <label for="email">Email:</label>\r
+                       <input id="email" name="email" value="<?php echo Input::post('email', $user->email); ?>">\r
+\r
+                <em>The user&rsquo;s email address. Needed if the user forgets their password.</em>\r
+                   </p>\r
+               </fieldset>\r
+                       \r
+               <p class="buttons">\r
+                       <button type="submit">Update</button>\r
+                       <?php if(Users::authed()->id !== $user->id): ?>\r
+                       <button name="delete" type="submit">Delete</button>\r
+                       <?php endif; ?>\r
+                       \r
+                       <a href="<?php echo admin_url('users'); ?>">Return to users</a>\r
+               </p>\r
+       </form>\r
+\r
+</section>\r
diff --git a/testcms-final-anon/system/admin/theme/users/index.php b/testcms-final-anon/system/admin/theme/users/index.php
new file mode 100644 (file)
index 0000000..2eded72
--- /dev/null
@@ -0,0 +1,18 @@
+<h1>Users <a href="<?php echo admin_url('users/add'); ?>">Create a new user</a></h1>\r
+\r
+<?php echo Notifications::read(); ?>\r
+\r
+<section class="content">\r
+       <ul class="list">\r
+           <?php foreach($users as $user): ?>\r
+           <li>\r
+               <a href="<?php echo admin_url('users/edit/' . $user->id); ?>">\r
+                   <strong><?php echo $user->real_name; ?></strong>\r
+                   <span>Username: <?php echo $user->username; ?></span>\r
+                   \r
+                   <i class="role"><?php echo ucwords($user->role); ?></i>\r
+               </a>\r
+           </li>\r
+           <?php endforeach; ?>\r
+       </ul>\r
+</section>\r
diff --git a/testcms-final-anon/system/admin/theme/users/login.php b/testcms-final-anon/system/admin/theme/users/login.php
new file mode 100644 (file)
index 0000000..c5c94de
--- /dev/null
@@ -0,0 +1,29 @@
+<h1>Log in</h1>\r
+\r
+<?php echo Notifications::read(); ?>\r
+\r
+<section class="content">\r
+\r
+       <form method="post" action="<?php echo Url::current(); ?>" >\r
+               <fieldset>\r
+                       \r
+                       <p>\r
+                           <label for="user">Username:</label>\r
+                           <input autocapitalize="off" name="user" id="user" value="<?php echo Input::post('user'); ?>">\r
+                       </p>\r
+                       \r
+                       <p>\r
+                       <label for="pass">Password:</label>\r
+                       <input type="password" name="pass" id="pass">\r
+                       \r
+                       <em><a href="<?php echo admin_url('users/amnesia'); ?>">Forgotten your password?</a></em>\r
+                       </p>\r
+\r
+                       <p class="buttons">\r
+                           <button type="submit">Login</button>\r
+                           <a href="<?php echo Url::make(); ?>">Back to <?php echo Config::get('metadata.sitename'); ?></a>\r
+                       </p>\r
+               </fieldset>\r
+       </form>\r
+\r
+</section>
\ No newline at end of file
diff --git a/testcms-final-anon/system/admin/theme/users/reset.php b/testcms-final-anon/system/admin/theme/users/reset.php
new file mode 100644 (file)
index 0000000..3367907
--- /dev/null
@@ -0,0 +1,24 @@
+<h1>Reset Password</h1>\r
+\r
+<?php echo Notifications::read(); ?>\r
+\r
+<section class="content">\r
+\r
+       <form method="post" action="<?php echo Url::current(); ?>" >\r
+               <fieldset>\r
+                       <legend>Password reset for <?php echo $user->real_name; ?></legend>\r
+                       <em>Please enter a new password that you won&rsquo;t forget this time.</em>\r
+                       \r
+                       <p>\r
+                           <label for="password">Password:</label>\r
+                           <input name="password" id="password" type="password" value="<?php echo Input::post('password'); ?>">\r
+                       </p>\r
+\r
+                       <p class="buttons">\r
+                           <button type="submit">Submit</button>\r
+                           <a href="<?php echo Url::make(); ?>">Back to <?php echo Config::get('metadata.sitename'); ?></a>\r
+                       </p>\r
+               </fieldset>\r
+       </form>\r
+\r
+</section>
\ No newline at end of file
diff --git a/testcms-final-anon/system/bootstrap.php b/testcms-final-anon/system/bootstrap.php
new file mode 100644 (file)
index 0000000..d4f43e3
--- /dev/null
@@ -0,0 +1,101 @@
+<?php defined('IN_CMS') or die('No direct access allowed.');\r
+\r
+/**\r
+       Check our environment\r
+*/\r
+if(version_compare(PHP_VERSION, '5.3.0', '<')) {\r
+       // echo and exit with some usful information\r
+       echo 'Test CMS requires PHP 5.3 or newer, your current environment is running PHP ' . PHP_VERSION;\r
+       exit(1);\r
+}\r
+\r
+// get our autoloader\r
+require PATH . 'system/classes/helpers.php';\r
+require PATH . 'system/classes/autoload.php';\r
+\r
+// directly map classes for super fast loading\r
+Autoloader::map(array(\r
+       'Config' => PATH . 'system/classes/config.php',\r
+       'Error' => PATH . 'system/classes/error.php',\r
+       'Session' => PATH . 'system/classes/session.php',\r
+       'TestCMS' => PATH . 'system/classes/testcms.php',\r
+       'Template' => PATH . 'system/classes/template.php',\r
+       'Request' => PATH . 'system/classes/request.php',\r
+       'Response' => PATH . 'system/classes/response.php',\r
+       'Log' => PATH . 'system/classes/log.php',\r
+       'Db' => PATH . 'system/classes/db.php',\r
+       'IoC' => PATH . 'system/classes/ioc.php',\r
+       'Url' => PATH . 'system/classes/url.php'\r
+));\r
+\r
+// tell the autoloader where to find classes\r
+Autoloader::directory(array(\r
+       PATH . 'system/classes/'\r
+));\r
+\r
+// register the auto loader\r
+Autoloader::register();\r
+\r
+/**\r
+       Report all errors let our error class decide which to display\r
+*/\r
+error_reporting(-1);\r
+\r
+/**\r
+       Error display will be handled by our error class\r
+*/\r
+ini_safe_set('display_errors', false);\r
+\r
+/**\r
+       Disable magic quotes\r
+       note: magic quotes is deprecated in PHP 5.3\r
+       src: php.net/manual/en/security.magicquotes.disabling.php\r
+*/\r
+if(function_exists('get_magic_quotes_gpc')) {\r
+       if(get_magic_quotes_gpc()) {\r
+               ini_safe_set('magic_quotes_gpc', false);\r
+               ini_safe_set('magic_quotes_runtime', false);\r
+               ini_safe_set('magic_quotes_sybase', false);\r
+       }\r
+}\r
+\r
+/**\r
+       Check our installation\r
+*/\r
+if(Config::load(PATH . 'config.php') === false) {\r
+       // looks like we are missing a config file\r
+       echo file_get_contents(PATH . 'system/admin/theme/error_config.php');\r
+       exit(1);\r
+}\r
+\r
+// Register the default timezone for the application.\r
+date_default_timezone_set(Config::get('application.timezone'));\r
+\r
+// Register the PHP exception handler.\r
+set_exception_handler(array('Error', 'exception'));\r
+\r
+// Register the PHP error handler.\r
+set_error_handler(array('Error', 'native'));\r
+\r
+// Register the shutdown handler.\r
+register_shutdown_function(array('Error', 'shutdown'));\r
+\r
+/**\r
+       Start session handler\r
+*/\r
+Session::start();\r
+\r
+/**\r
+       Handle routing\r
+*/\r
+TestCMS::run();\r
+\r
+/**\r
+       Close and end session\r
+*/\r
+Session::end();\r
+\r
+/**\r
+       Output awesomeness!\r
+*/\r
+Response::send();\r
diff --git a/testcms-final-anon/system/classes/autoload.php b/testcms-final-anon/system/classes/autoload.php
new file mode 100644 (file)
index 0000000..5893972
--- /dev/null
@@ -0,0 +1,67 @@
+<?php defined('IN_CMS') or die('No direct access allowed.');\r
+\r
+class Autoloader {\r
+\r
+       private static $mappings = array();\r
+       private static $directories = array();\r
+\r
+       public static function register() {\r
+               spl_autoload_register(array('Autoloader', 'load'));\r
+       }\r
+       \r
+       public static function unregister() {\r
+               spl_autoload_unregister(array('Autoloader', 'load'));\r
+       }\r
+\r
+       public static function map($map) {\r
+               static::$mappings = array_merge(static::$mappings, $map);\r
+       }\r
+\r
+       public static function directory($dir) {\r
+               static::$directories = array_merge(static::$directories, $dir);\r
+       }\r
+       \r
+       public static function load($class) {\r
+               // does the class have a direct map\r
+               if(isset(static::$mappings[$class])) {\r
+                       // load class\r
+                       require static::$mappings[$class];\r
+\r
+                       return true;\r
+               }\r
+\r
+               // search directories\r
+               $file = str_replace(array('//', '\\'), '/', trim(strtolower($class), '/'));\r
+\r
+               // get file path\r
+               if(($path = static::find($file)) === false) {\r
+                       return false;\r
+               }\r
+\r
+               require $path;\r
+\r
+               return true;\r
+       }\r
+       \r
+       public static function find($file) {\r
+               // search controllers\r
+               if(strpos($file, '_controller') !== false) {\r
+                       $file = rtrim($file, '_controller');\r
+                       $path = PATH . 'system/admin/controllers/';\r
+\r
+                       if(file_exists($path . $file . '.php')) {\r
+                               return $path . $file . '.php';\r
+                       }\r
+               }\r
+\r
+               // search application classes\r
+               foreach(static::$directories as $path) {\r
+                       if(file_exists($path . $file . '.php')) {\r
+                               return $path . $file . '.php';\r
+                       }\r
+               }\r
+               \r
+               return false;\r
+       }\r
+\r
+}\r
diff --git a/testcms-final-anon/system/classes/comments.php b/testcms-final-anon/system/classes/comments.php
new file mode 100644 (file)
index 0000000..60dc924
--- /dev/null
@@ -0,0 +1,158 @@
+<?php defined('IN_CMS') or die('No direct access allowed.');\r
+\r
+class Comments {\r
+\r
+       public static function list_all($params = array()) {\r
+               $sql = "select * from comments where 1 = 1";\r
+               $args = array();\r
+               \r
+               if(isset($params['post'])) {\r
+                       $sql .= " and post = ?";\r
+                       $args[] = $params['post'];\r
+               }\r
+               \r
+               if(isset($params['sortby'])) {\r
+                       $sql .= " order by " . $params['sortby'];\r
+                       \r
+                       if(isset($params['sortmode'])) {\r
+                               $sql .= " " . $params['sortmode'];\r
+                       }\r
+               }\r
+               \r
+               if(isset($params['limit'])) {\r
+                       $sql .= " limit " . $params['limit'];\r
+                       \r
+                       if(isset($params['offset'])) {\r
+                               $sql .= " offset " . $params['offset'];\r
+                       }\r
+               }\r
+\r
+               $result = Db::results($sql, $args);\r
+               \r
+               return new Items($result);\r
+       }\r
+\r
+       public static function add($post_id) {\r
+               $post = Input::post(array('name', 'email', 'text'));\r
+               $errors = array();\r
+\r
+               if(empty($post['name'])) {\r
+                       $errors[] = 'Please enter your name';\r
+               }\r
+               \r
+               if(filter_var($post['email'], FILTER_VALIDATE_EMAIL) === false) {\r
+                       $errors[] = 'Please enter a valid email address';\r
+               }\r
+               \r
+               if(empty($post['text'])) {\r
+                       $errors[] = 'Please enter your comments';\r
+               }\r
+               \r
+               if(count($errors)) {\r
+                       Notifications::set('error', $errors);\r
+                       return false;\r
+               }\r
+               \r
+               $post['date'] = time();\r
+               $post['status'] = Config::get('metadata.auto_published_comments', 0) ? 'published' : 'pending';\r
+               $post['post'] = $post_id;\r
+               \r
+               $keys = array();\r
+               $values = array();\r
+               $args = array();\r
+               \r
+               foreach($post as $key => $value) {\r
+                       $keys[] = '`' . $key . '`';\r
+                       $values[] = '\'' . $value . '\'';\r
+               }\r
+               \r
+               $sql = "insert into comments (" . implode(', ', $keys) . ") values (" . implode(', ', $values) . ")";   \r
+                       \r
+               Db::query($sql, $args);\r
+               \r
+               Notifications::set('success', 'Your comment has been sent');\r
+               \r
+               return true;\r
+       }\r
+       \r
+       public static function update() {\r
+               $post = Input::post(array('id', 'text', 'status'));\r
+               $errors = array();\r
+               \r
+               if(empty($post['text'])) {\r
+                       $errors[] = 'Please enter comment text';\r
+               }\r
+\r
+               if(count($errors)) {\r
+                       $output = json_encode(array('result' => false, 'errors' => $errors));\r
+                       Response::content($output);\r
+                       return false;\r
+               }\r
+               \r
+               $id = $post['id'];\r
+               unset($post['id']);\r
+               \r
+               $updates = array();\r
+               $args = array();\r
+\r
+               foreach($post as $key => $value) {\r
+                       $updates[] = '`' . $key . '` = ?';\r
+                       $args[] = $value;\r
+               }\r
+               \r
+               $sql = "update comments set " . implode(', ', $updates) . " where id = ?";\r
+               $args[] = $id;          \r
+               \r
+               Db::query($sql, $args);\r
+\r
+               $output = json_encode(array('result' => true));\r
+               Response::content($output);\r
+       }\r
+       \r
+       public static function update_status() {\r
+               $post = Input::post(array('id', 'status'));\r
+               $errors = array();\r
+               \r
+               if(in_array($post['status'], array('published', 'pending', 'spam')) === false) {\r
+                       $errors[] = 'Invalid comment status';\r
+               }\r
+\r
+               if(count($errors)) {\r
+                       $output = json_encode(array('result' => false, 'errors' => $errors));\r
+                       Response::content($output);\r
+                       return false;\r
+               }\r
+               \r
+               $id = $post['id'];\r
+               unset($post['id']);\r
+               \r
+               $updates = array();\r
+               $args = array();\r
+\r
+               foreach($post as $key => $value) {\r
+                       $updates[] = '`' . $key . '` = ?';\r
+                       $args[] = $value;\r
+               }\r
+               \r
+               $sql = "update comments set " . implode(', ', $updates) . " where id = ?";\r
+               $args[] = $id;          \r
+               \r
+               Db::query($sql, $args);\r
+\r
+               $output = json_encode(array('result' => true));\r
+               Response::content($output);\r
+       }\r
+       \r
+       public static function remove() {\r
+               $id = Input::post('id');\r
+\r
+               $sql = "delete from comments where id = ?";\r
+               $args = array($id);\r
+               \r
+               Db::query($sql, $args);\r
+\r
+               $output = json_encode(array('result' => true));\r
+               Response::content($output);\r
+       }\r
+\r
+}\r
diff --git a/testcms-final-anon/system/classes/config.php b/testcms-final-anon/system/classes/config.php
new file mode 100644 (file)
index 0000000..c0337d2
--- /dev/null
@@ -0,0 +1,132 @@
+<?php defined('IN_CMS') or die('No direct access allowed.');\r
+\r
+/*\r
+       A static config class to manage all of \r
+       our config params\r
+*/\r
+class Config {\r
+\r
+       private static $items = array();\r
+       private static $cache = array();\r
+\r
+       /*\r
+               Load the default config file\r
+       */\r
+       public static function load($file) {\r
+               if(file_exists($file) === false) {\r
+                       return false;\r
+               }\r
+               \r
+               static::$items = array_merge(static::$items, require $file);\r
+               \r
+               return true;\r
+       }\r
+\r
+       public static function write($file, $array) {\r
+               $php = '<?php defined(\'IN_CMS\') or die(\'No direct access allowed.\');' . PHP_EOL . PHP_EOL;\r
+               $php .= '/**' . PHP_EOL . "\t" . 'Auto generated config' . PHP_EOL . '*/' . PHP_EOL . PHP_EOL;\r
+\r
+               $php .= 'return array(' . PHP_EOL;\r
+\r
+               foreach($array as $key => $value) {\r
+                       $php .= "\t'" . $key . "' => ";\r
+\r
+                       if(is_array($value)) {\r
+                               $php .= 'array(' . PHP_EOL;\r
+                               foreach($value as $k => $v) {\r
+                                       $php .= "\t\t'" . $k . "' => " . static::format($v) . "," .PHP_EOL;\r
+                               }\r
+                               $php .= "\t)," . PHP_EOL;\r
+                       } else {\r
+                               $php .= static::format($value) . ',' .PHP_EOL;\r
+                       }\r
+               }\r
+\r
+               $php .= ');';\r
+\r
+               return file_put_contents(PATH . 'config.php', $php);\r
+       }\r
+\r
+       public static function format($value) {\r
+               if(is_int($value)) {\r
+                       return $value;\r
+               }\r
+               if(is_bool($value)) {\r
+                       return $value ? 'true' : 'false';\r
+               }\r
+               if(is_array($value)) {\r
+                       $var = array_map(function($itm) {\r
+                               return Config::format($itm);\r
+                       }, $value);\r
+\r
+                       return "array("  . implode(",", $var) . ")";\r
+               }\r
+               return "'" . (string) $value . "'";\r
+       }\r
+       \r
+       /*\r
+               Set a config item\r
+       */\r
+       public static function set($key, $value) {\r
+               // array pointer for search\r
+               $array =& static::$items;\r
+\r
+               $keys = explode('.', $key);\r
+\r
+               while(count($keys) > 1) {\r
+                       $key = array_shift($keys);\r
+\r
+                       if(!isset($array[$key]) or !is_array($array[$key])) {\r
+                               $array[$key] = array();\r
+                       }\r
+\r
+                       $array =& $array[$key];\r
+               }\r
+\r
+               $array[array_shift($keys)] = $value;\r
+       }\r
+       \r
+       /*\r
+               Retrive a config param\r
+       */\r
+       public static function get($key = null, $default = false) {\r
+               // return all items\r
+               if(is_null($key)) return static::$items;\r
+\r
+               // copy array for search\r
+               $array = static::$items;\r
+\r
+               // search array\r
+               foreach(explode('.', $key) as $segment) {\r
+                       if (!is_array($array) or array_key_exists($segment, $array) === false) {\r
+                               return $default;\r
+                       }\r
+\r
+                       $array = $array[$segment];\r
+               }\r
+\r
+               return $array;\r
+       }\r
+\r
+       /*\r
+               Remove a config param\r
+       */\r
+       public static function forget($key) {\r
+               // array pointer for search\r
+               $array =& static::$items;\r
+\r
+               $keys = explode('.', $key);\r
+\r
+               while(count($keys) > 1) {\r
+                       $key = array_shift($keys);\r
+\r
+                       if(!isset($array[$key]) or !is_array($array[$key])) {\r
+                               return;\r
+                       }\r
+\r
+                       $array =& $array[$key];\r
+               }\r
+\r
+               unset($array[array_shift($keys)]);\r
+       }\r
+}\r
diff --git a/testcms-final-anon/system/classes/cookie.php b/testcms-final-anon/system/classes/cookie.php
new file mode 100644 (file)
index 0000000..923fafd
--- /dev/null
@@ -0,0 +1,25 @@
+<?php defined('IN_CMS') or die('No direct access allowed.');\r
+\r
+class Cookie {\r
+\r
+       public static function has($key) {\r
+               return isset($_COOKIE[$key]);\r
+       }\r
+       \r
+       public static function get($key, $default = false) {\r
+               if(static::has($key)) {\r
+                       return $_COOKIE[$key];\r
+               }\r
+               \r
+               return ($default instanceof \Closure) ? call_user_func($default) : $default;\r
+       }\r
+       \r
+       public static function write($name, $data, $expire, $path, $domain) {\r
+               if(headers_sent() === false) {\r
+                       return setcookie($name, $data, $expire, $path, $domain, false);\r
+               }\r
+\r
+               return false;\r
+       }\r
+\r
+}\r
diff --git a/testcms-final-anon/system/classes/curl.php b/testcms-final-anon/system/classes/curl.php
new file mode 100644 (file)
index 0000000..43ab988
--- /dev/null
@@ -0,0 +1,87 @@
+<?php defined('IN_CMS') or die('No direct access allowed.');\r
+\r
+class Curl {\r
+\r
+       private $session, $error, $info;\r
+\r
+       public function __construct() {\r
+               $this->session = curl_init();\r
+       }\r
+       \r
+       public static function support() {\r
+               return function_exists('curl_init');\r
+       }\r
+\r
+       public function set_options($options) {\r
+               curl_setopt_array($this->session, $options);\r
+       }\r
+       \r
+       public function get_error() {\r
+               return $this->error;\r
+       }\r
+       \r
+       public function get_info() {\r
+               return $this->info;\r
+       }\r
+       \r
+       public function send() {\r
+               if(($response = curl_exec($this->session)) === false) {\r
+                       $this->error = curl_errno($this->session) . ': ' . curl_error($this->session);\r
+               }\r
+               \r
+               $this->info = curl_getinfo($this->session);\r
+                               \r
+               return $response;\r
+       }\r
+       \r
+       public function close() {\r
+               curl_close($this->session);\r
+       }\r
+       \r
+       public static function post($url, $data = array(), $headers = array()) {\r
+               $session = new static;\r
+               \r
+               $options = array(\r
+                       CURLOPT_URL => $url,\r
+                       CURLOPT_POST => true,\r
+                       CURLOPT_POSTFIELDS => http_build_query($data),\r
+                       CURLOPT_HEADER => false,\r
+                       CURLOPT_RETURNTRANSFER => true\r
+               );\r
+               \r
+               if(count($headers)) {\r
+                       $options[CURLOPT_HTTPHEADER] = $headers;\r
+               }\r
+       \r
+               $session->set_options($options);\r
+               \r
+               $response = $session->send();\r
+               \r
+               $session->close();\r
+               \r
+               return $response;\r
+       }\r
+       \r
+       public static function get($url, $headers = array()) {\r
+               $session = new static;\r
+               \r
+               $options = array(\r
+                       CURLOPT_URL => $url,\r
+                       CURLOPT_HEADER => false,\r
+                       CURLOPT_RETURNTRANSFER => true\r
+               );\r
+               \r
+               if(count($headers)) {\r
+                       $options[CURLOPT_HTTPHEADER] = $headers;\r
+               }\r
+       \r
+               $session->set_options($options);\r
+               \r
+               $response = $session->send();\r
+               \r
+               $session->close();\r
+               \r
+               return $response;\r
+       }\r
+\r
+}\r
diff --git a/testcms-final-anon/system/classes/db.php b/testcms-final-anon/system/classes/db.php
new file mode 100644 (file)
index 0000000..1ab826a
--- /dev/null
@@ -0,0 +1,227 @@
+<?php defined('IN_CMS') or die('No direct access allowed.');\r
+\r
+class Db {\r
+\r
+       private static $driver = 'mysql';\r
+       private static $hostname, $username, $password, $database;\r
+       private static $driver_options = array();\r
+\r
+       private static $dbh = null;\r
+       private static $debug = false;\r
+       private static $affected_rows = 0;\r
+       private static $profile = array();\r
+\r
+       public static function connect() {\r
+               // config\r
+               $params = Config::get('database');\r
+\r
+               // set debug mode\r
+               static::$debug = Config::get('debug', false);\r
+               \r
+               // build dns string\r
+               $dsn = 'mysql:dbname=' . $params['name'] . ';host=' . $params['host'];\r
+\r
+               // try connection\r
+               static::$dbh = new PDO($dsn, $params['username'], $params['password']);\r
+               \r
+               // set error handling to exceptions\r
+               static::$dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);\r
+\r
+               return true;\r
+       }\r
+\r
+       public static function close() {\r
+               static::$dbh = null;\r
+       }\r
+\r
+       private static function profiling($statement, $binds, $start) {\r
+               static::$profile[] = array(\r
+                       'sql' => $statement->queryString,\r
+                       'binds' => $binds,\r
+                       'time' => round(microtime(true) - $start, 4),\r
+                       'rows' => $statement->rowCount()\r
+               );\r
+       }\r
+\r
+       public static function profile() {\r
+               return static::$profile;\r
+       }\r
+\r
+       /*\r
+        * Querying\r
+        */\r
+       public static function query($sql, $binds = array()) {\r
+               // make sure we have a connection\r
+               if(is_null(static::$dbh)) {\r
+                       static::connect();\r
+               }\r
+       \r
+               // check binds\r
+               if(!is_array($binds)) {\r
+                       $binds = array($binds);\r
+               }\r
+\r
+               // profile in debug mode\r
+               if(static::$debug) {\r
+                       $start = microtime(true);\r
+               }\r
+\r
+               // prepare\r
+               $sth = static::$dbh->prepare($sql);\r
+\r
+               // bind params\r
+               $reflector = new ReflectionMethod('PDOStatement', 'bindValue');\r
+\r
+               foreach($binds as $index => $value) {\r
+                       $key = is_int($index) ? $index + 1 : $index;\r
+                       $type = is_bool($value) ? PDO::PARAM_BOOL : (is_int($value) ? PDO::PARAM_INT : PDO::PARAM_STR);\r
+                       $reflector->invokeArgs($sth, array($key, $value, $type));\r
+               }\r
+\r
+               // get results\r
+               $sth->execute();\r
+\r
+               // profile in debug mode\r
+               if(static::$debug) {\r
+                       static::profiling($sth, $binds, $start);\r
+               }\r
+\r
+               // update affected rows\r
+               static::$affected_rows = $sth->rowCount();\r
+\r
+               // return statement\r
+               return $sth;\r
+       }\r
+\r
+       /*\r
+        * Simple query, returns TRUE or FALSE\r
+        */\r
+       public static function exec($sql, $binds = array()) {\r
+               // make sure we have a connection\r
+               if(is_null(static::$dbh)) {\r
+                       static::connect();\r
+               }\r
+\r
+               // check binds\r
+               if(!is_array($binds)) {\r
+                       $binds = array($binds);\r
+               }\r
+\r
+               // profile in debug mode\r
+               if(static::$debug) {\r
+                       $start = microtime(true);\r
+               }\r
+\r
+               // prepare\r
+               $sth = static::$dbh->prepare($sql);\r
+\r
+               // bind params\r
+               $reflector = new ReflectionMethod('PDOStatement', 'bindValue');\r
+\r
+               foreach($binds as $index => $value) {\r
+                       $key = is_int($index) ? $index + 1 : $index;\r
+                       $type = is_bool($value) ? PDO::PARAM_BOOL : (is_int($value) ? PDO::PARAM_INT : PDO::PARAM_STR);\r
+                       $reflector->invokeArgs($sth, array($key, $value, $type));\r
+               }\r
+\r
+               // get results\r
+               $result = $sth->execute();\r
+\r
+               // profile in debug mode\r
+               if(static::$debug) {\r
+                       static::profiling($sth, $binds, $start);\r
+               }\r
+\r
+               // update affected rows\r
+               static::$affected_rows = $sth->rowCount();\r
+\r
+               // return result\r
+               return $result;\r
+       }\r
+       \r
+       /*\r
+        * Shortcuts\r
+        */\r
+       public static function update($table, $columns = array(), $condition = array()) {\r
+               $updates = array();\r
+               $args = array();\r
+\r
+               foreach($columns as $key => $value) {\r
+                       $updates[] = '`' . $key . '` = ?';\r
+                       $args[] = $value;\r
+               }\r
+               \r
+               $sql = "update `" . $table . "` set " . implode(', ', $updates);\r
+               \r
+               if(count($condition)) {\r
+                       $where = array();\r
+\r
+                       foreach($condition as $key => $value) {\r
+                               $where[] = '`' . $key . '` = ?';\r
+                               $args[] = $value;\r
+                       }\r
+\r
+                       $sql .= " where " . implode(' and ', $where);\r
+               }       \r
+               \r
+               return Db::exec($sql, $args);\r
+       }\r
+\r
+       public static function insert($table, $row = array()) {\r
+               $keys = array();\r
+               $values = array();\r
+               $args = array();\r
+               \r
+               foreach($row as $key => $value) {\r
+                       $keys[] = '`' . $key . '`';\r
+                       $values[] = '?';\r
+                       $args[] = $value;\r
+               }\r
+               \r
+               $sql = "insert into `" . $table . "` (" . implode(', ', $keys) . ") values (" . implode(', ', $values) . ")";   \r
+\r
+               return Db::exec($sql, $args);\r
+       }\r
+\r
+       public static function delete($table, $condition = array()) {\r
+               $sql = "delete from `" . $table . "`";\r
+               \r
+               if(count($condition)) {\r
+                       $where = array();\r
+\r
+                       foreach($condition as $key => $value) {\r
+                               $where[] = '`' . $key . '` = ?';\r
+                               $args[] = $value;\r
+                       }\r
+\r
+                       $sql .= " where " . implode(' and ', $where);\r
+               }       \r
+               \r
+               return Db::exec($sql, $args);\r
+       }\r
+\r
+       public static function row($sql, $binds = array(), $fetch_style = \PDO::FETCH_OBJ) {\r
+               // get statement\r
+               $stm = static::query($sql, $binds);\r
+\r
+               // return data\r
+               return $stm->fetch($fetch_style);\r
+       }\r
+\r
+       public static function results($sql, $binds = array(), $fetch_style = \PDO::FETCH_OBJ) {\r
+               // get statement\r
+               $stm = static::query($sql, $binds);\r
+\r
+               // return data array\r
+               return $stm->fetchAll($fetch_style);\r
+       }\r
+\r
+       public static function insert_id() {\r
+               return static::$dbh->lastInsertId();\r
+       }\r
+\r
+       public static function affected_rows() {\r
+               return static::$affected_rows;\r
+       }\r
+\r
+}\r
diff --git a/testcms-final-anon/system/classes/email.php b/testcms-final-anon/system/classes/email.php
new file mode 100644 (file)
index 0000000..e302e4b
--- /dev/null
@@ -0,0 +1,19 @@
+<?php defined('IN_CMS') or die('No direct access allowed.');\r
+\r
+class Email {\r
+\r
+       private static function headers($headers) {\r
+               $str = '';\r
+               \r
+               foreach($headers as $key => $value) {\r
+                       $str .= $key . ': ' . $value . PHP_EOL;\r
+               }\r
+               \r
+               return $str;\r
+       }\r
+\r
+       public static function send($to, $subject, $message, $headers = array()) {\r
+               return mail($to, $subject, $message, static::headers($headers));\r
+       }\r
+\r
+}\r
diff --git a/testcms-final-anon/system/classes/error.php b/testcms-final-anon/system/classes/error.php
new file mode 100644 (file)
index 0000000..c28cfa6
--- /dev/null
@@ -0,0 +1,88 @@
+<?php defined('IN_CMS') or die('No direct access allowed.');\r
+\r
+class Error {\r
+\r
+       public static function native($code, $error, $file, $line) {\r
+               // no error reporting nothing to do\r
+               if(error_reporting() === 0) {\r
+                       return;\r
+               }\r
+\r
+               $exception = new ErrorException($error, $code, 0, $file, $line);\r
+\r
+               if(in_array($code, Config::get('error.ignore', array()))) {\r
+                       return static::log($exception);\r
+               }\r
+\r
+               static::exception($exception);\r
+       }\r
+       \r
+       public static function shutdown() {\r
+               if(!is_null($error = error_get_last())) {\r
+                       extract($error, EXTR_SKIP);\r
+                       static::exception(new ErrorException($message, $type, 0, $file, $line));\r
+               }\r
+       }\r
+\r
+       public static function exception($e) {\r
+               // Clean the output buffer.\r
+               if(ob_get_level() > 0) {\r
+                       ob_clean();\r
+               }\r
+\r
+               // log exception\r
+               static::log($e);\r
+\r
+               // Display error\r
+               if(Config::get('error.detail', true)) {\r
+                       // Get the error file.\r
+                       $file = $e->getFile();\r
+\r
+                       // Trim the period off of the error message.\r
+                       $message = rtrim($e->getMessage(), '.');\r
+\r
+                       $line = $e->getLine();\r
+                       $trace = $e->getTraceAsString();\r
+                       $contexts = static::context($file, $e->getLine());\r
+\r
+                       require PATH . 'system/admin/theme/error_php.php';\r
+               } else {\r
+                       require PATH . 'system/admin/theme/error_500.php';\r
+               }\r
+\r
+               exit(1);\r
+       }\r
+\r
+       private static function context($path, $line, $padding = 5) {\r
+               if(file_exists($path)) {\r
+                       $file = file($path, FILE_IGNORE_NEW_LINES);\r
+\r
+                       array_unshift($file, '');\r
+\r
+                       // Calculate the starting position.\r
+                       $start = $line - $padding;\r
+\r
+                       if($start < 0) {\r
+                               $start = 0;\r
+                       }\r
+\r
+                       // Calculate the context length.\r
+                       $length = ($line - $start) + $padding + 1;\r
+\r
+                       if(($start + $length) > count($file) - 1) {\r
+                               $length = null;\r
+                       }\r
+\r
+                       return array_slice($file, $start, $length, true);\r
+               }\r
+\r
+               return array();\r
+       }\r
+\r
+       public static function log($e) {\r
+               if(Config::get('error.log')) {\r
+                       Log::exception($e);\r
+               }\r
+       }\r
+\r
+}\r
diff --git a/testcms-final-anon/system/classes/events.php b/testcms-final-anon/system/classes/events.php
new file mode 100644 (file)
index 0000000..a1b7c25
--- /dev/null
@@ -0,0 +1,41 @@
+<?php defined('IN_CMS') or die('No direct access allowed.');\r
+\r
+class Events {\r
+\r
+       private static $stack = array();\r
+\r
+       private static function parse($page) {\r
+               $name = 'main';\r
+\r
+               if(strpos($page, '.') !== false) {\r
+                       list($page, $name) = explode('.', $page);\r
+               }\r
+\r
+               return array($page, $name);\r
+       }\r
+\r
+       public static function bind($page, $fn) {\r
+               list($page, $name) = static::parse($page);\r
+\r
+               if(!isset(static::$stack[$page])) {\r
+                       static::$stack[$page] = array();\r
+               }\r
+\r
+               static::$stack[$page][$name] = $fn;\r
+       }\r
+\r
+       public static function call($name = '') {\r
+               $page = basename(Request::uri());\r
+\r
+               if(empty($name)) {\r
+                       $name = 'main';\r
+               }\r
+\r
+               if($func = isset(static::$stack[$page][$name]) ? static::$stack[$page][$name] : false) {\r
+                       return is_callable($func) ? $func() : '';\r
+               }\r
+\r
+               return '';\r
+       }\r
+\r
+}
\ No newline at end of file
diff --git a/testcms-final-anon/system/classes/helpers.php b/testcms-final-anon/system/classes/helpers.php
new file mode 100644 (file)
index 0000000..5ab7e8f
--- /dev/null
@@ -0,0 +1,18 @@
+<?php defined('IN_CMS') or die('No direct access allowed.');\r
+\r
+/*\r
+       Helper for setting php settings\r
+*/\r
+function ini_safe_set($key, $value) {\r
+       // some hosts disable ini_set for security \r
+       // lets check so see if its disabled\r
+       if(($disable_functions = ini_get('disable_functions')) !== false) {\r
+               // if it is disabled then return as there is nothing we can do\r
+               if(strpos($disable_functions, 'ini_set') !== false) {\r
+                       return false;\r
+               }\r
+       }\r
+\r
+       // lets set it because we can!\r
+       return ini_set($key, $value);\r
+}
\ No newline at end of file
diff --git a/testcms-final-anon/system/classes/input.php b/testcms-final-anon/system/classes/input.php
new file mode 100644 (file)
index 0000000..4fa7d2f
--- /dev/null
@@ -0,0 +1,92 @@
+<?php defined('IN_CMS') or die('No direct access allowed.');\r
+\r
+class Input {\r
+\r
+       public static function clean($str) {\r
+               // handle magic quotes for people who cant turn it off\r
+               if(function_exists('get_magic_quotes_gpc')) {\r
+                       if(get_magic_quotes_gpc()) {\r
+                               return is_array($str) ? array_map(array('Input', 'clean'), $str) : stripslashes($str);\r
+                       }\r
+               }\r
+\r
+               return $str;\r
+       }\r
+\r
+       private static function fetch_array($array, $key, $default = false) {\r
+               if(is_array($key)) {\r
+                       $data = array();\r
+\r
+                       foreach($key as $k) {\r
+                               $data[$k] = static::fetch_array($array, $k, $default);\r
+                       }\r
+\r
+                       return $data;\r
+               }\r
+               \r
+               if(array_key_exists($key, $array)) {\r
+                       return static::clean($array[$key]);\r
+               }\r
+\r
+               return ($default instanceof \Closure) ? call_user_func($default) : $default;\r
+       }\r
+\r
+       public static function post($key, $default = false) {\r
+               return static::fetch_array($_POST, $key, $default);\r
+       }\r
+\r
+       public static function get($key, $default = false) {\r
+               return static::fetch_array($_GET, $key, $default);\r
+       }\r
+\r
+       public static function put($key, $default = false) {\r
+               return static::fetch_array(parse_str(file_get_contents('php://input')), $key, $default);\r
+       }\r
+\r
+       public static function delete($key, $default = false) {\r
+               return static::fetch_array(parse_str(file_get_contents('php://input')), $key, $default);\r
+       }\r
+\r
+       public static function cookie($key, $default = false) {\r
+               return static::fetch_array($_COOKIE, $key, $default);\r
+       }\r
+\r
+       public static function server($key, $default = false) {\r
+               return static::fetch_array($_SERVER, strtoupper($key), $default);\r
+       }\r
+\r
+       public static function file($key, $default = false) {\r
+               return static::fetch_array($_FILES, $key, $default);\r
+       }\r
+\r
+       public static function method() {\r
+               return static::server('REQUEST_METHOD');\r
+       }\r
+\r
+       public static function ip_address() {\r
+                // IP from share internet\r
+               if (static::server('REMOTE_ADDR') and static::server('HTTP_CLIENT_IP')) {\r
+                       return static::server('HTTP_CLIENT_IP');\r
+               }\r
+\r
+               if(static::server('REMOTE_ADDR')) {\r
+                       return static::server('REMOTE_ADDR');\r
+               }\r
+\r
+               if(static::server('HTTP_CLIENT_IP')) {\r
+                       return static::server('HTTP_CLIENT_IP');\r
+               }\r
+\r
+               // Proxy detection\r
+               if(static::server('HTTP_X_FORWARDED_FOR')) {\r
+                       return static::server('HTTP_X_FORWARDED_FOR');\r
+               }\r
+\r
+               return '0.0.0.0';\r
+       }\r
+\r
+       public static function user_agent() {\r
+               return static::server('HTTP_USER_AGENT');\r
+       }\r
+\r
+}\r
diff --git a/testcms-final-anon/system/classes/ioc.php b/testcms-final-anon/system/classes/ioc.php
new file mode 100644 (file)
index 0000000..781ea5e
--- /dev/null
@@ -0,0 +1,33 @@
+<?php defined('IN_CMS') or die('No direct access allowed.');\r
+\r
+class IoC {\r
+\r
+       private static $registry = array();\r
+       private static $instances = array();\r
+\r
+       public static function register($name, $resolver, $singleton = false) {\r
+               static::$registry[$name] = array('resolver' => $resolver, 'singleton' => $singleton);\r
+       }\r
+       \r
+       public static function instance($name, $instance) {\r
+               static::$instances[$name] = $instance;\r
+       }\r
+\r
+       public static function resolve($name) {\r
+               if(isset(static::$instances[$name])) {\r
+                       return static::$instances[$name];\r
+               }\r
+               \r
+               if(isset(static::$registry[$name])) {\r
+                       $object = call_user_func(static::$registry[$name]['resolver']);\r
+                       \r
+                       if(isset(static::$registry[$name]['singleton']) and static::$registry[$name]['singleton']) {\r
+                               static::$instances[$name] = $object;\r
+                       }\r
+\r
+                       return $object;\r
+               }\r
+               \r
+               return false;\r
+       }\r
+}\r
diff --git a/testcms-final-anon/system/classes/items.php b/testcms-final-anon/system/classes/items.php
new file mode 100644 (file)
index 0000000..b6714ac
--- /dev/null
@@ -0,0 +1,46 @@
+<?php defined('IN_CMS') or die('No direct access allowed.');\r
+\r
+class Items implements Iterator {\r
+\r
+       private $position = 0;\r
+       private $items = array();   \r
+\r
+       public function __construct($array) {\r
+               $this->position = 0;\r
+               $this->items = $array;\r
+       }\r
+\r
+       public function rewind() {\r
+               $this->position = 0;\r
+       }\r
+\r
+       public function current() {\r
+               return $this->items[$this->position];\r
+       }\r
+\r
+       public function key() {\r
+               return $this->position;\r
+       }\r
+\r
+       public function next() {\r
+               ++$this->position;\r
+       }\r
+\r
+       public function valid() {\r
+               return isset($this->items[$this->position]);\r
+       }\r
+       \r
+       public function length() {\r
+               return count($this->items);\r
+       }\r
+\r
+       public function first() {\r
+               return isset($this->items[0]) ? $this->items[0] : false;\r
+       }\r
+\r
+       public function last() {\r
+               $index = count($this->items) - 1;\r
+               return isset($this->items[$index]) ? $this->items[$index] : false;\r
+       }\r
+\r
+}\r
diff --git a/testcms-final-anon/system/classes/log.php b/testcms-final-anon/system/classes/log.php
new file mode 100644 (file)
index 0000000..e7aa921
--- /dev/null
@@ -0,0 +1,30 @@
+<?php defined('IN_CMS') or die('No direct access allowed.');\r
+\r
+class Log {\r
+\r
+       public static function write($severity, $message) {\r
+               if(Config::get('error.log') === false) {\r
+                       return;\r
+               }\r
+\r
+               $line = '[' . $severity . '] --> ' . $message . PHP_EOL;\r
+\r
+               if($fp = @fopen(PATH . 'system/logs/' . date("Y-m-d") . '.log', 'a+')) {\r
+                       fwrite($fp, $line);\r
+                       fclose($fp);\r
+               }\r
+       }\r
+\r
+       public static function __callStatic($severity, $parameters) {\r
+               static::write($severity, $parameters[0]);\r
+       }\r
+\r
+       public static function exception($e) {\r
+               static::write('error', static::format($e));\r
+       }\r
+\r
+       private static function format($e) {\r
+               return $e->getMessage().' in '.$e->getFile().' on line '.$e->getLine();\r
+       }\r
+\r
+}
\ No newline at end of file
diff --git a/testcms-final-anon/system/classes/metadata.php b/testcms-final-anon/system/classes/metadata.php
new file mode 100644 (file)
index 0000000..462e649
--- /dev/null
@@ -0,0 +1,41 @@
+<?php defined('IN_CMS') or die('No direct access allowed.');\r
+\r
+class Metadata {\r
+\r
+       public static function update() {\r
+               $post = Input::post(array('sitename', 'description', 'theme', 'twitter', 'home_page', 'posts_page', 'auto_published_comments', 'posts_per_page'));\r
+               $errors = array();\r
+               \r
+               if(empty($post['sitename'])) {\r
+                       $errors[] = 'You need a site sitename';\r
+               }\r
+               \r
+               if(empty($post['description'])) {\r
+                       $errors[] = 'You need a site description';\r
+               }\r
+               \r
+               if(empty($post['theme'])) {\r
+                       $errors[] = 'You need a theme';\r
+               }\r
+\r
+               // auto publish comments\r
+               $post['auto_published_comments'] = $post['auto_published_comments'] ? 1 : 0;\r
+\r
+               // format posts per page, must be a whole number above 1 defaults to 10 if a invalid number is entered\r
+               $post['posts_per_page'] = ($posts_per_page = intval($post['posts_per_page'])) > 0 ? $posts_per_page : 10;\r
+               \r
+               if(count($errors)) {\r
+                       Notifications::set('error', $errors);\r
+                       return false;\r
+               }\r
+\r
+               foreach($post as $key => $value) {\r
+                   Db::update('meta', array('value' => $value), array('key' => $key));\r
+               }\r
+                               \r
+               Notifications::set('success', 'Your metadata has been updated');\r
+               \r
+               return true;\r
+       }\r
+\r
+}
\ No newline at end of file
diff --git a/testcms-final-anon/system/classes/notifications.php b/testcms-final-anon/system/classes/notifications.php
new file mode 100644 (file)
index 0000000..da058ba
--- /dev/null
@@ -0,0 +1,37 @@
+<?php defined('IN_CMS') or die('No direct access allowed.');\r
+\r
+/*\r
+       Handle error, notice and success messages in the admin\r
+*/\r
+class Notifications {\r
+\r
+       public static function set($type, $message) {\r
+               $data = Session::get('notifications', array());\r
+               \r
+               if(!isset($data[$type])) {\r
+                       $data[$type] = array();\r
+               }\r
+               \r
+               if(!is_array($message)) {\r
+                       $message = array($message);\r
+               }\r
+               \r
+               $data[$type] = array_merge($data[$type], $message);\r
+               \r
+               Session::set('notifications', $data);\r
+       }\r
+\r
+       public static function read() {\r
+               $data = Session::get('notifications', array());\r
+               $html = '';\r
+               \r
+               foreach($data as $type => $messages) {\r
+                       $html .= '<p class="notification ' . $type . '">' . implode('<br>', $messages) . '</p>';\r
+               }\r
+               \r
+               Session::forget('notifications');\r
+               \r
+               return $html;\r
+       }\r
+\r
+}\r
diff --git a/testcms-final-anon/system/classes/pages.php b/testcms-final-anon/system/classes/pages.php
new file mode 100644 (file)
index 0000000..5446449
--- /dev/null
@@ -0,0 +1,166 @@
+<?php defined('IN_CMS') or die('No direct access allowed.');\r
+\r
+class Pages {\r
+\r
+       public static function extend($page) {\r
+               if(is_array($page)) {\r
+                       $pages = array();\r
+\r
+                       foreach($page as $itm) {\r
+                               $pages[] = static::extend($itm);\r
+                       }\r
+                       \r
+                       return $pages;\r
+               }\r
+       \r
+               if(is_object($page)) {\r
+                       $uri = Request::uri();\r
+                       $page->url = Url::make($page->slug);\r
+\r
+                       $page->active = false;\r
+                       \r
+                       if($current = IoC::resolve('page')) {\r
+                               if($current->id == $page->id) {\r
+                                       $page->active = true;\r
+                               }\r
+                       }\r
+\r
+                       return $page;\r
+               }\r
+               \r
+               return false;\r
+       }\r
+\r
+       public static function list_all($params = array()) {\r
+               $sql = "select * from pages where 1 = 1";\r
+               $args = array();\r
+               \r
+               if(isset($params['status'])) {\r
+                       $sql .= " and status = ?";\r
+                       $args[] = $params['status'];\r
+               }\r
+               \r
+               if(isset($params['sortby'])) {\r
+                       $sql .= " order by " . $params['sortby'];\r
+                       \r
+                       if(isset($params['sortmode'])) {\r
+                               $sql .= " " . $params['sortmode'];\r
+                       }\r
+               }\r
+\r
+               // extend data set\r
+               $pages = static::extend(Db::results($sql, $args));\r
+\r
+               // create iterable object\r
+               return new Items($pages);\r
+       }\r
+\r
+       public static function count($params = array()) {\r
+               $sql = "select count(*) from pages where 1 = 1";\r
+               $args = array();\r
+\r
+               if(isset($params['status'])) {\r
+                       $sql .= " and pages.status = ?";\r
+                       $args[] = $params['status'];\r
+               }\r
+\r
+               // get total\r
+               return Db::query($sql, $args)->fetchColumn();\r
+       }\r
+\r
+       public static function find($where = array()) {\r
+               $sql = "select * from pages";\r
+               $args = array();\r
+               \r
+               if(count($where)) {\r
+                       $clause = array();\r
+                       foreach($where as $key => $value) {\r
+                               $clause[] = '`' . $key . '` = ?';\r
+                               $args[] = $value;\r
+                       }\r
+                       $sql .= " where " . implode(' and ', $clause);\r
+               }\r
+\r
+               // extend page object\r
+               return static::extend(Db::row($sql, $args));\r
+       }\r
+       \r
+       public static function delete($id) {\r
+               Db::delete('pages', array('id' => $id));\r
+               \r
+               Notifications::set('success', 'Your page has been deleted');\r
+               \r
+               return true;\r
+       }\r
+       \r
+       public static function update($id) {\r
+               $post = Input::post(array('slug', 'name', 'title', 'content', 'status', 'delete'));\r
+               $errors = array();\r
+\r
+               // delete\r
+               if($post['delete'] !== false) {\r
+                       // prevent the deletion of the posts page and home page\r
+                       if(in_array($id, array(Config::get('metadata.home_page'), Config::get('metadata.posts_page'))) === false) {\r
+                               return static::delete($id);\r
+                       } else {\r
+                               Notifications::set('error', 'Sorry, you can not delete you home page or posts page.');\r
+                               return false;\r
+                       }\r
+               } else {\r
+                       // remove it frm array\r
+                       unset($post['delete']);\r
+               }\r
+               \r
+               if(empty($post['name'])) {\r
+                       $errors[] = 'Please enter a name';\r
+               }\r
+               \r
+               if(empty($post['title'])) {\r
+                       $errors[] = 'Please enter a title';\r
+               }\r
+               \r
+               if(count($errors)) {\r
+                       Notifications::set('error', $errors);\r
+                       return false;\r
+               }\r
+               \r
+               if(empty($post['slug'])) {\r
+                       $post['slug'] = preg_replace('/\W+/', '-', trim(strtolower($post['name'])));\r
+               }\r
+               \r
+               Db::update('pages', $post, array('id' => $id));\r
+               \r
+               Notifications::set('success', 'Your page has been updated');\r
+               \r
+               return true;\r
+       }\r
+       \r
+       public static function add() {\r
+               $post = Input::post(array('slug', 'name', 'title', 'content', 'status'));\r
+               $errors = array();\r
+               \r
+               if(empty($post['name'])) {\r
+                       $errors[] = 'Please enter a name';\r
+               }\r
+               \r
+               if(empty($post['title'])) {\r
+                       $errors[] = 'Please enter a title';\r
+               }\r
+               \r
+               if(count($errors)) {\r
+                       Notifications::set('error', $errors);\r
+                       return false;\r
+               }\r
+               \r
+               if(empty($post['slug'])) {\r
+                       $post['slug'] = preg_replace('/\W+/', '-', trim(strtolower($post['name'])));\r
+               }\r
+\r
+               Db::insert('pages', $post);\r
+               \r
+               Notifications::set('success', 'Your new page has been added');\r
+               \r
+               return true;\r
+       }\r
+\r
+}\r
diff --git a/testcms-final-anon/system/classes/posts.php b/testcms-final-anon/system/classes/posts.php
new file mode 100644 (file)
index 0000000..fa07c9b
--- /dev/null
@@ -0,0 +1,326 @@
+\r
+<?php defined('IN_CMS') or die('No direct access allowed.');\r
+\r
+class Posts {\r
+\r
+       public static function extend($post) {\r
+               if(is_array($post)) {\r
+                       $posts = array();\r
+\r
+                       foreach($post as $itm) {\r
+                               $posts[] = static::extend($itm);\r
+                       }\r
+                       \r
+                       return $posts;\r
+               }\r
+       \r
+               if(is_object($post)) {\r
+                       $page = IoC::resolve('posts_page');\r
+                       $post->url = Url::make($page->slug . '/' . $post->slug);\r
+                       return $post;\r
+               }\r
+               \r
+               return false;\r
+       }\r
+       \r
+       public static function list_all($params = array()) {\r
+               $sql = "\r
+                       select\r
+\r
+                               posts.id,\r
+                               posts.title,\r
+                               posts.slug,\r
+                               posts.description,\r
+                               posts.html,\r
+                               posts.css,\r
+                               posts.js,\r
+                               posts.created,\r
+                               posts.custom_fields,\r
+                               coalesce(users.real_name, posts.author) as author,\r
+                               coalesce(comments.total, 0) as total_comments,\r
+                               posts.status\r
+\r
+                       from posts \r
+                       left join users on (users.id = posts.author) \r
+                       left join (\r
+                               select \r
+                                       count(comments.id) as total, comments.post \r
+                               from comments \r
+                               where status = 'published' \r
+                               group by comments.post\r
+                       ) as comments on (posts.id = comments.post)\r
+                       where 1 = 1\r
+               ";\r
+               $args = array();\r
+               \r
+               if(isset($params['status'])) {\r
+                       $sql .= " and posts.status = ?";\r
+                       $args[] = $params['status'];\r
+               }\r
+               \r
+               if(isset($params['sortby'])) {\r
+                       $sql .= " order by posts." . $params['sortby'];\r
+                       \r
+                       if(isset($params['sortmode'])) {\r
+                               $sql .= " " . $params['sortmode'];\r
+                       }\r
+               }\r
+               \r
+               if(isset($params['limit'])) {\r
+                       $sql .= " limit " . $params['limit'];\r
+                       \r
+                       if(isset($params['offset'])) {\r
+                               $sql .= " offset " . $params['offset'];\r
+                       }\r
+               }\r
+\r
+               $results = Db::results($sql, $args);\r
+               \r
+               // extend result set with post url\r
+               $results = static::extend($results);\r
+\r
+               // return items obj\r
+               return new Items($results);\r
+       }\r
+       \r
+       public static function count($params = array()) {\r
+               $sql = "select count(*) from posts where 1 = 1";\r
+               $args = array();\r
+\r
+               if(isset($params['status'])) {\r
+                       $sql .= " and posts.status = ?";\r
+                       $args[] = $params['status'];\r
+               }\r
+\r
+               // return total\r
+               return Db::query($sql, $args)->fetchColumn();\r
+       }\r
+       \r
+       public static function find($where = array()) {\r
+               $sql = "\r
+                       select\r
+\r
+                               posts.id,\r
+                               posts.title,\r
+                               posts.slug,\r
+                               posts.description,\r
+                               posts.html,\r
+                               posts.css,\r
+                               posts.js,\r
+                               posts.created,\r
+                               posts.custom_fields,\r
+                               coalesce(users.real_name, posts.author) as author,\r
+                               coalesce(users.bio, '') as bio,\r
+                               posts.status,\r
+                               posts.comments\r
+\r
+                       from posts \r
+                       left join users on (users.id = posts.author) \r
+               ";\r
+               $args = array();\r
+               \r
+               if(count($where)) {\r
+                       $clause = array();\r
+                       foreach($where as $key => $value) {\r
+                               $clause[] = 'posts.' . $key . ' = ?';\r
+                               $args[] = $value;\r
+                       }\r
+                       $sql .= " where " . implode(' and ', $clause);\r
+               }\r
+\r
+               return static::extend(Db::row($sql, $args));\r
+       }\r
+       \r
+       public static function search($term, $params = array()) {\r
+               $sql = "\r
+                       select\r
+\r
+                               posts.id,\r
+                               posts.title,\r
+                               posts.slug,\r
+                               posts.description,\r
+                               posts.html,\r
+                               posts.css,\r
+                               posts.js,\r
+                               posts.created,\r
+                               posts.custom_fields,\r
+                               coalesce(users.real_name, posts.author) as author,\r
+                               posts.status\r
+\r
+                       from posts \r
+                       left join users on (users.id = posts.author) \r
+\r
+                       where (posts.title like :term or posts.description like :term or posts.html like :term)\r
+               ";\r
+               $args = array('term' => '%' . $term . '%');\r
+               \r
+               if(isset($params['status'])) {\r
+                       $sql .= " and posts.status = :status";\r
+                       $args['status'] = $params['status'];\r
+               }\r
+\r
+               if(isset($params['limit'])) {\r
+                       $sql .= " limit " . $params['limit'];\r
+                       \r
+                       if(isset($params['offset'])) {\r
+                               $sql .= " offset " . $params['offset'];\r
+                       }\r
+               }\r
+\r
+               $results = Db::results($sql, $args);\r
+               \r
+               // extend result set with post url\r
+               $results = static::extend($results);\r
+\r
+               // return items obj\r
+               return new Items($results);\r
+       }\r
+\r
+       public static function search_count($term, $params = array()) {\r
+               $sql = "\r
+                       select count(*) from posts \r
+                       where (posts.title like :term or posts.description like :term or posts.html like :term)\r
+               ";\r
+               $args = array('term' => '%' . $term . '%');\r
+\r
+               if(isset($params['status'])) {\r
+                       $sql .= " and posts.status = :status";\r
+                       $args['status'] = $params['status'];\r
+               }\r
+\r
+               // return total\r
+               return Db::query($sql, $args)->fetchColumn();\r
+       }\r
+       \r
+       public static function delete($id) {\r
+               Db::delete('posts', array('id' => $id));\r
+               Db::delete('comments', array('post' => $id));\r
+               \r
+               Notifications::set('success', 'Your post has been deleted');\r
+               \r
+               return true;\r
+       }\r
+       \r
+       public static function update($id) {\r
+               $post = Input::post(array('title', 'slug', 'description', 'html', \r
+                       'css', 'js', 'status', 'delete', 'field', 'comments'));\r
+               $errors = array();\r
+\r
+               // delete\r
+               if($post['delete'] !== false) {\r
+                       return static::delete($id);\r
+               } else {\r
+                       // remove it frm array\r
+                       unset($post['delete']);\r
+               }\r
+               \r
+               if(empty($post['title'])) {\r
+                       $errors[] = 'Please enter a title';\r
+               }\r
+               \r
+               if(empty($post['description'])) {\r
+                       $errors[] = 'Please enter a description';\r
+               }\r
+               \r
+               if(empty($post['html'])) {\r
+                       $errors[] = 'Please enter your html';\r
+               }\r
+               \r
+               if(empty($post['slug'])) {\r
+                       $post['slug'] = preg_replace('/\W+/', '-', trim(strtolower($post['title'])));\r
+               }\r
+\r
+               // check for duplicate slug\r
+               $sql = "select id from posts where slug = ? and id <> ?";\r
+               if(Db::row($sql, array($post['slug'], $id))) {\r
+                       $errors[] = 'A post with the same slug already exists, please change your post slug.';\r
+               }\r
+\r
+               if(count($errors)) {\r
+                       Notifications::set('error', $errors);\r
+                       return false;\r
+               }\r
+\r
+               $custom = array();\r
+               \r
+               if(is_array($post['field'])) {\r
+                       foreach($post['field'] as $keylabel => $value) {\r
+                               list($key, $label) = explode(':', $keylabel);\r
+                               $custom[$key] = array('label' => $label, 'value' => $value);\r
+                       }\r
+               }\r
+               \r
+               // remove from update\r
+               unset($post['field']);\r
+               \r
+               $post['custom_fields'] = json_encode($custom);\r
+\r
+               // update row\r
+               Db::update('posts', $post, array('id' => $id));\r
+\r
+               Notifications::set('success', 'Your post has been updated.');\r
+               \r
+               return true;\r
+       }\r
+       \r
+       public static function add() {\r
+               $post = Input::post(array('title', 'slug', 'description', 'html', \r
+                       'css', 'js', 'status', 'field', 'comments'));\r
+               $errors = array();\r
+               \r
+               if(empty($post['title'])) {\r
+                       $errors[] = 'Please enter a title';\r
+               }\r
+               \r
+               if(empty($post['description'])) {\r
+                       $errors[] = 'Please enter a description';\r
+               }\r
+               \r
+               if(empty($post['html'])) {\r
+                       $errors[] = 'Please enter your html';\r
+               }\r
+               \r
+               if(empty($post['slug'])) {\r
+                       $post['slug'] = preg_replace('/\W+/', '-', trim(strtolower($post['title'])));\r
+               }\r
+\r
+               // check for duplicate slug\r
+               $sql = "select id from posts where slug = ?";\r
+               if(Db::row($sql, array($post['slug']))) {\r
+                       $errors[] = 'A post with the same slug already exists, please change your post slug.';\r
+               }\r
+\r
+               if(count($errors)) {\r
+                       Notifications::set('error', $errors);\r
+                       return false;\r
+               }\r
+\r
+               $custom = array();\r
+               \r
+               if(is_array($post['field'])) {\r
+                       foreach($post['field'] as $keylabel => $value) {\r
+                               list($key, $label) = explode(':', $keylabel);\r
+                               $custom[$key] = array('label' => $label, 'value' => $value);\r
+                       }\r
+               }\r
+               \r
+               // remove from update\r
+               unset($post['field']);\r
+               \r
+               $post['custom_fields'] = json_encode($custom);\r
+               \r
+               // set creation date\r
+               $post['created'] = time();\r
+               \r
+               // set author\r
+               $user = Users::authed();\r
+               $post['author'] = $user->id;\r
+\r
+               Db::insert('posts', $post);\r
+               \r
+               Notifications::set('success', 'Your new post has been added');\r
+               \r
+               return true;\r
+       }\r
+       \r
+}\r
diff --git a/testcms-final-anon/system/classes/request.php b/testcms-final-anon/system/classes/request.php
new file mode 100644 (file)
index 0000000..48ca6e1
--- /dev/null
@@ -0,0 +1,46 @@
+<?php defined('IN_CMS') or die('No direct access allowed.');\r
+\r
+class Request {\r
+\r
+       public static function uri_segment($index, $default = false) {\r
+               $index--;\r
+               $segments = explode('/', static::uri());\r
+               return isset($segments[$index]) ? $segments[$index] : $default;\r
+       }\r
+       \r
+       public static function uri() {\r
+               if(isset($_SERVER['PATH_INFO'])) {\r
+                       $uri = $_SERVER['PATH_INFO'];\r
+               }\r
+               // try request uri\r
+               elseif(isset($_SERVER['REQUEST_URI'])) {\r
+                       // make sure we can parse URI\r
+                       if(($uri = parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH)) === false) {\r
+                               throw new Exception('Malformed request URI');\r
+                       }\r
+               }\r
+               // cannot process request\r
+               else {\r
+                       throw new Exception('Unable to determine the request URI');\r
+               }\r
+\r
+               // remove base url\r
+               $base_url = parse_url(Config::get('application.base_url'), PHP_URL_PATH);\r
+\r
+               if(strlen($base_url)) {\r
+                       if(strpos($uri, $base_url) === 0) {\r
+                               $uri = substr($uri, strlen($base_url));\r
+                       }\r
+               }\r
+\r
+               // remove index file\r
+               $index = '/' . Config::get('application.index_page');\r
+\r
+               if(strpos($uri, $index) === 0) {\r
+                       $uri = substr($uri, strlen($index));\r
+               }\r
+\r
+               return trim($uri, '/');\r
+       }       \r
+       \r
+}\r
diff --git a/testcms-final-anon/system/classes/response.php b/testcms-final-anon/system/classes/response.php
new file mode 100644 (file)
index 0000000..ea725dc
--- /dev/null
@@ -0,0 +1,109 @@
+<?php defined('IN_CMS') or die('No direct access allowed.');\r
+\r
+class Response {\r
+       \r
+       private static $content = '';\r
+       private static $headers = array();\r
+       private static $status = 200;\r
+       \r
+       private static $statuses = array(\r
+               100 => 'Continue',\r
+               101 => 'Switching Protocols',\r
+               200 => 'OK',\r
+               201 => 'Created',\r
+               202 => 'Accepted',\r
+               203 => 'Non-Authoritative Information',\r
+               204 => 'No Content',\r
+               205 => 'Reset Content',\r
+               206 => 'Partial Content',\r
+               207 => 'Multi-Status',\r
+               300 => 'Multiple Choices',\r
+               301 => 'Moved Permanently',\r
+               302 => 'Found',\r
+               303 => 'See Other',\r
+               304 => 'Not Modified',\r
+               305 => 'Use Proxy',\r
+               307 => 'Temporary Redirect',\r
+               400 => 'Bad Request',\r
+               401 => 'Unauthorized',\r
+               402 => 'Payment Required',\r
+               403 => 'Forbidden',\r
+               404 => 'Not Found',\r
+               405 => 'Method Not Allowed',\r
+               406 => 'Not Acceptable',\r
+               407 => 'Proxy Authentication Required',\r
+               408 => 'Request Timeout',\r
+               409 => 'Conflict',\r
+               410 => 'Gone',\r
+               411 => 'Length Required',\r
+               412 => 'Precondition Failed',\r
+               413 => 'Request Entity Too Large',\r
+               414 => 'Request-URI Too Long',\r
+               415 => 'Unsupported Media Type',\r
+               416 => 'Requested Range Not Satisfiable',\r
+               417 => 'Expectation Failed',\r
+               422 => 'Unprocessable Entity',\r
+               423 => 'Locked',\r
+               424 => 'Failed Dependency',\r
+               500 => 'Internal Server Error',\r
+               501 => 'Not Implemented',\r
+               502 => 'Bad Gateway',\r
+               503 => 'Service Unavailable',\r
+               504 => 'Gateway Timeout',\r
+               505 => 'HTTP Version Not Supported',\r
+               507 => 'Insufficient Storage',\r
+               509 => 'Bandwidth Limit Exceeded'\r
+       );\r
+       \r
+       public static function header($name, $value) {\r
+               static::$headers[$name] = $value;\r
+       }\r
+       \r
+       public static function content($str) {\r
+               static::$content = $str;\r
+       }\r
+       \r
+       public static function append($str) {\r
+               static::$content .= $str;\r
+       }\r
+       \r
+       public static function error($code = 500) {\r
+               if(isset(static::$statuses[$code])) {\r
+                       static::$status = $code;\r
+               }\r
+\r
+               switch($code) {\r
+                       case 404:\r
+                               Template::render(404);\r
+               }\r
+       }\r
+       \r
+       public static function send() {\r
+               // set content type\r
+               if(array_key_exists('Content-Type', static::$headers) === false) {\r
+                       static::$headers['Content-Type'] = 'text/html; charset=UTF-8';\r
+               }\r
+\r
+               // send headers\r
+               if(headers_sent() === false) {\r
+               \r
+                       $protocol = Input::server('server_protocol', 'HTTP/1.1');\r
+\r
+                       header($protocol . ' ' . static::$status . ' ' . static::$statuses[static::$status]);\r
+\r
+                       foreach(static::$headers as $name => $value) {\r
+                               header($name . ': ' . $value, true);\r
+                       }\r
+               }\r
+\r
+               // Send it to the browser!\r
+               echo static::$content;\r
+       }\r
+       \r
+       public static function redirect($url) {\r
+               static::header('Location', Url::make($url));\r
+               static::$status = 302;\r
+               static::$content = '';\r
+       }\r
+       \r
+}\r
diff --git a/testcms-final-anon/system/classes/routes.php b/testcms-final-anon/system/classes/routes.php
new file mode 100644 (file)
index 0000000..860d7a9
--- /dev/null
@@ -0,0 +1,102 @@
+<?php defined('IN_CMS') or die('No direct access allowed.');\r
+\r
+/*\r
+       This class contains all routing details\r
+*/\r
+class Routes {\r
+\r
+       public function article($slug = '') {\r
+               // find article\r
+               $params = array('slug' => $slug);\r
+\r
+               // allow admin to view unpublished posts\r
+               if(Users::authed() === false) {\r
+                       $params['status'] = 'published';\r
+               }\r
+\r
+               if(($article = Posts::find($params)) === false) {\r
+                       Log::warning('Article connot be found: ' . $slug);\r
+                       return Response::error(404);\r
+               }\r
+               \r
+               // add comment\r
+               if(Input::method() == 'POST') {\r
+                       if(Comments::add($article->id)) {\r
+                               $page = IoC::resolve('posts_page');\r
+                               return Response::redirect($page->slug . '/' . $article->slug);\r
+                       }\r
+               }\r
+               \r
+               // register single item for templating functions\r
+               IoC::instance('article', $article, true);\r
+\r
+               Template::render('article');\r
+       }\r
+       \r
+       public function page($slug = '') {\r
+               // allow admin to view unpublished posts\r
+               if(Users::authed() === false) {\r
+                       $params['status'] = 'published';\r
+               }\r
+\r
+               // if no slug is set we will use our default page\r
+               if(empty($slug)) {\r
+                       $params['id'] = Config::get('metadata.home_page');\r
+               } else {\r
+                       $params['slug'] = $slug;\r
+               }\r
+\r
+               // if we cant find either it looks like we're barney rubble (in trouble)\r
+               if(($page = Pages::find($params)) === false) {\r
+                       Log::warning('Page connot be found: ' . $slug);\r
+                       return Response::error(404);\r
+               }\r
+\r
+               // store our page for template functions\r
+               IoC::instance('page', $page, true);\r
+\r
+               // does the current page host our posts?\r
+               if($page->id == Config::get('metadata.posts_page')) {\r
+                       // render our posts template\r
+                       return Template::render('posts');\r
+               }\r
+\r
+               // render our page template\r
+               Template::render('page');\r
+       }\r
+       \r
+       public function rss() {\r
+               // set headers\r
+               Rss::headers();\r
+               \r
+               // set content\r
+               Rss::generate();\r
+       }\r
+       \r
+       public function search($term = '') {\r
+               if(Input::method() == 'POST') {\r
+                       if(Input::post('term') !== false) {\r
+                               return Response::redirect('search/' . rawurlencode(Input::post('term')));\r
+                       }\r
+               }\r
+               \r
+               $search = Posts::search($term, array(\r
+                       'status' => 'published', \r
+                       'limit' => Config::get('metadata.posts_per_page', 10),\r
+                       'offset' => Input::get('offset', 0)\r
+               ));\r
+               IoC::instance('search', $search, true);\r
+\r
+               $total = Posts::search_count($term, array(\r
+                       'status' => 'published'\r
+               ));\r
+               IoC::instance('total_search', $total, true);\r
+               \r
+               $page = new StdClass;\r
+               $page->id = -1;\r
+               $page->title = 'Search';\r
+               IoC::instance('page', $page, true);\r
+               Template::render('search');\r
+       }\r
+\r
+}\r
diff --git a/testcms-final-anon/system/classes/rss.php b/testcms-final-anon/system/classes/rss.php
new file mode 100644 (file)
index 0000000..0a19c8c
--- /dev/null
@@ -0,0 +1,80 @@
+<?php defined('IN_CMS') or die('No direct access allowed.');\r
+\r
+class Rss {\r
+\r
+       private static $document;\r
+\r
+       public static function headers() {\r
+               // set headers\r
+               Response::header('Content-Type', 'application/xml');\r
+       }\r
+       \r
+       private static function element($name, $value = null, $attributes = array()) {\r
+               $element = static::$document->createElement($name);\r
+               \r
+               if(is_null($value) === false) {\r
+                       $text = static::$document->createTextNode($value);\r
+                       $element->appendChild($text);\r
+               }\r
+               \r
+               foreach($attributes as $key => $val) {\r
+                       $element->setAttribute($key, $val);\r
+               }\r
+               \r
+               return $element;\r
+       }\r
+\r
+       public static function generate() {     \r
+               // create a dom xml object\r
+               static::$document = new DOMDocument('1.0', 'UTF-8');\r
+               \r
+               // create our rss feed\r
+               $rss = static::element('rss', null, array('version' => '2.0'));\r
+               static::$document->appendChild($rss);\r
+               \r
+               // create channel\r
+               $channel = static::element('channel');\r
+               $rss->appendChild($channel);\r
+               \r
+                       // title\r
+                       $title = static::element('title', Config::get('metadata.sitename'));\r
+                       $channel->appendChild($title);\r
+               \r
+                       // link\r
+                       $link = static::element('link', 'http://' . $_SERVER['HTTP_HOST']);\r
+                       $channel->appendChild($link);\r
+                       \r
+                       // description\r
+                       $description = static::element('description', Config::get('metadata.description'));\r
+                       $channel->appendChild($description);\r
+               \r
+               \r
+               // articles\r
+               $params = array('status' => 'published', 'sortby' => 'id', 'sortmode' => 'desc');\r
+\r
+               foreach(Posts::list_all($params) as $post) {\r
+                       $item = static::element('item');\r
+                       $channel->appendChild($item);\r
+                       \r
+                               // title\r
+                               $title = static::element('title', $post->title);\r
+                               $item->appendChild($title);\r
+               \r
+                               // link\r
+                               $url = 'http://' . $_SERVER['HTTP_HOST'] . Url::make(IoC::resolve('posts_page')->slug . '/' . $post->slug);\r
+                               $link = static::element('link', $url);\r
+                               $item->appendChild($link);\r
+                       \r
+                               // description\r
+                               $description = static::element('description', $post->description);\r
+                               $item->appendChild($description);\r
+                               \r
+                               // date\r
+                               $date = static::element('pubDate', date(DATE_RSS, $post->created));\r
+                               $item->appendChild($date);\r
+               }\r
+               \r
+               // dump xml tree\r
+               Response::content(static::$document->saveXML());\r
+       }\r
+}\r
diff --git a/testcms-final-anon/system/classes/session.php b/testcms-final-anon/system/classes/session.php
new file mode 100644 (file)
index 0000000..0124d3c
--- /dev/null
@@ -0,0 +1,34 @@
+<?php defined('IN_CMS') or die('No direct access allowed.');\r
+\r
+/*\r
+       This will handle our native sessions for now \r
+       but provides somes flexibility in the future \r
+       if we decide to use other methods for \r
+       session management\r
+*/\r
+\r
+class Session {\r
+       \r
+       public static function start() {\r
+               session_start();\r
+       }\r
+       \r
+       public static function end() {\r
+               session_write_close();\r
+       }\r
+       \r
+       public static function get($key, $default = false) {\r
+               return isset($_SESSION[$key]) ? $_SESSION[$key] : $default;\r
+       }\r
+       \r
+       public static function set($key, $value) {\r
+               $_SESSION[$key] = $value;\r
+       }\r
+       \r
+       public static function forget($key) {\r
+               if(isset($_SESSION[$key])) {\r
+                       unset($_SESSION[$key]);\r
+               }\r
+       }\r
+       \r
+}\r
diff --git a/testcms-final-anon/system/classes/template.php b/testcms-final-anon/system/classes/template.php
new file mode 100644 (file)
index 0000000..b663bb2
--- /dev/null
@@ -0,0 +1,63 @@
+<?php defined('IN_CMS') or die('No direct access allowed.');\r
+\r
+class Template {\r
+\r
+       private static $path;\r
+\r
+       public static function path($path = '') {\r
+               if(empty($path)) {\r
+                       return static::$path;\r
+               }\r
+\r
+               static::$path = $path;\r
+       }\r
+\r
+       private static function parse($file, $data) {\r
+               // render content into response\r
+               ob_start();\r
+               \r
+               // extract vars\r
+               extract($data, EXTR_SKIP);\r
+               \r
+               require $file;\r
+               \r
+               Response::append(ob_get_contents());\r
+               \r
+               ob_end_clean();\r
+       }\r
+       \r
+       public static function render($template, $data = array()) {\r
+               // get default theme\r
+               $theme = Config::get('metadata.theme');\r
+               \r
+               // load global theming functions but not for the admin template\r
+               if(strpos(static::$path, 'system/admin/theme') === false) {\r
+                       require PATH . 'system/functions/articles.php';\r
+                       require PATH . 'system/functions/comments.php';\r
+                       require PATH . 'system/functions/helpers.php';\r
+                       require PATH . 'system/functions/menus.php';\r
+                       require PATH . 'system/functions/metadata.php';\r
+                       require PATH . 'system/functions/pages.php';\r
+                       require PATH . 'system/functions/posts.php';\r
+                       require PATH . 'system/functions/search.php';\r
+                       require PATH . 'system/functions/users.php';\r
+               }\r
+               \r
+               // load theme functions\r
+               if(file_exists(static::$path . 'functions.php')) {\r
+                       require static::$path . 'functions.php';\r
+               }\r
+\r
+               // render files\r
+               foreach(array('includes/header', $template, 'includes/footer') as $file) {\r
+                       $filepath = static::$path . $file . '.php';\r
+\r
+                       if(file_exists($filepath) === false) {\r
+                               throw new ErrorException('Theme file <strong>themes/' . $theme . '/' . $file . '.php</strong> not found.');\r
+                       }\r
+                       \r
+                       static::parse($filepath, $data);\r
+               }\r
+       }\r
+       \r
+}\r
diff --git a/testcms-final-anon/system/classes/testcms.php b/testcms-final-anon/system/classes/testcms.php
new file mode 100644 (file)
index 0000000..46c111d
--- /dev/null
@@ -0,0 +1,152 @@
+<?php defined('IN_CMS') or die('No direct access allowed.');\r
+\r
+/*\r
+       This is the front controller that \r
+       will route all incoming requests\r
+*/\r
+class TestCMS {\r
+\r
+       private static function setup() {\r
+               // Query metadata and store into our config\r
+               $sql = "select `key`, `value` from meta";\r
+               $meta = array();\r
+\r
+               foreach(Db::results($sql) as $row) {\r
+                       $meta[$row->key] = $row->value;\r
+               }\r
+\r
+               Config::set('metadata', $meta);\r
+\r
+               // look up which page has our posts\r
+               $page = Pages::find(array('id' => Config::get('metadata.posts_page')));\r
+               IoC::instance('posts_page', $page, true);\r
+       }\r
+\r
+       public static function run() {\r
+               // run setup and prepare env\r
+               static::setup();\r
+               \r
+               // handle the requested uri\r
+               $uri = static::parse();\r
+               $segments = array();\r
+               \r
+               if(strlen($uri)) {\r
+                       $segments = explode('/', $uri);\r
+               }\r
+\r
+               // lets log our translated uri\r
+               Log::info('Translated URI: ' . $uri);\r
+\r
+               // set our action or our default if none is set\r
+               $action = count($segments) ? array_shift($segments) : 'page';\r
+               \r
+               // default to our front end router\r
+               $controller = 'Routes';\r
+               \r
+               // set the template path\r
+               $theme = Config::get('metadata.theme');\r
+               Template::path(PATH . 'themes/' . $theme . '/');\r
+               \r
+               // remove admin as an argument and set the default action if there isnt one\r
+               if($action == 'admin') {\r
+                       // set default controller for the admin\r
+                       $controller = (count($segments) ? array_shift($segments) : 'posts') . '_controller';\r
+\r
+                       // set default action\r
+                       $action = count($segments) ? array_shift($segments) : 'index';\r
+\r
+                       // public admin actions\r
+                       $public = array('users/login', 'users/amnesia', 'users/reset');\r
+                       \r
+                       // redirect to login\r
+                       if(Users::authed() === false and in_array(trim($controller, '_controller') . '/' . $action, $public) === false) {\r
+                               return Response::redirect(Config::get('application.admin_folder') . '/users/login');\r
+                       }\r
+\r
+                       // set template path for admin\r
+                       Template::path(PATH . 'system/admin/theme/');\r
+               }\r
+\r
+               // log the controller we are going to use and the action\r
+               Log::info('Controller action: ' . $controller . '/' . $action);\r
+               \r
+               // check we can find a action\r
+               $reflector = new ReflectionClass($controller);\r
+\r
+               if($reflector->isInstantiable() === false or $reflector->hasMethod($action) === false) {\r
+                       // default back to front end template for 404 page\r
+                       Template::path(PATH . 'themes/' . $theme . '/');\r
+                       \r
+                       // report error\r
+                       Log::warning(($reflector->isInstantiable() === false ? 'Controller was not Instantiable' : 'Action does not exist'));\r
+\r
+                       // method not found in controller\r
+                       return Response::error(404);\r
+               }\r
+\r
+               $reflector->getMethod($action)->invokeArgs(new $controller, $segments);\r
+       }\r
+       \r
+       private static function parse() {\r
+               // get uri\r
+               $uri = Request::uri();\r
+\r
+               // lets log our initial uri\r
+               Log::info('Requested URI: ' . $uri);\r
+\r
+               // if htaccess is not enabled and the file exists ignore the request\r
+               if(file_exists($uri)) {\r
+                       return '';\r
+               }\r
+\r
+               // route definitions\r
+               $routes = array();\r
+               \r
+               // posts host page\r
+               if($page = IoC::resolve('posts_page')) {\r
+                       $routes[$page->slug . '/(:any)'] = 'article/$1';\r
+               }\r
+               \r
+               // fallback to 'admin'\r
+               $admin_folder = Config::get('application.admin_folder', 'admin');\r
+\r
+               // static routes\r
+               $routes = array_merge($routes, array(\r
+                       $admin_folder . '/(:any)/(:any)/(:any)' => 'admin/$1/$2/$3',\r
+                       $admin_folder . '/(:any)/(:any)' => 'admin/$1/$2',\r
+                       $admin_folder . '/(:any)' => 'admin/$1',\r
+                       $admin_folder => 'admin',\r
+\r
+                       'search/(:any)' => 'search/$1',\r
+                       'search' => 'search',\r
+                       \r
+                       'rss' => 'rss',\r
+\r
+                       '(:any)' => 'page/$1'\r
+               ));\r
+               \r
+               // define wild-cards\r
+               $search = array(':any', ':num');\r
+               $replace = array('[0-9a-zA-Z~%\.:_\\-]+', '[0-9]+');\r
+               \r
+               // parse routes\r
+               foreach($routes as $route => $translated) {\r
+                       // replace wildcards\r
+                       $route = str_replace($search, $replace, $route);\r
+\r
+                       // look for matches\r
+                       if(preg_match('#^' . $route . '#', $uri, $matches)) {\r
+                               // replace matched values\r
+                               foreach($matches as $k => $match) {\r
+                                       $translated = str_replace('$' . $k, $match, $translated);\r
+                               }\r
+\r
+                               // return on first match\r
+                               return $translated;\r
+                       }\r
+               }\r
+               \r
+               return $uri;\r
+       }\r
+\r
+}
\ No newline at end of file
diff --git a/testcms-final-anon/system/classes/themes.php b/testcms-final-anon/system/classes/themes.php
new file mode 100644 (file)
index 0000000..a0f2506
--- /dev/null
@@ -0,0 +1,60 @@
+<?php defined('IN_CMS') or die('No direct access allowed.');\r
+\r
+class Themes {\r
+       \r
+       public static function list_all() {\r
+               $themes = array();\r
+\r
+               foreach(glob(PATH . 'themes/*') as $folder) {\r
+                       $theme = basename($folder);\r
+\r
+                       if($about = static::parse($theme)) {\r
+                               $themes[$theme] = $about;\r
+                       }\r
+               }\r
+\r
+               return $themes;\r
+       }\r
+\r
+       public static function parse($theme) {\r
+               $file = PATH . 'themes/' . $theme . '/about.txt';\r
+\r
+               if(file_exists($file) === false) {\r
+                       return false;\r
+               }\r
+\r
+               // read file into a array\r
+               $contents = explode("\n", trim(file_get_contents($file)));\r
+               $about = array();\r
+\r
+               foreach(array('name', 'description', 'author', 'site', 'license') as $index => $key) {\r
+                       // temp value\r
+                       $about[$key] = '';\r
+\r
+                       // find line if exists\r
+                       if(!isset($contents[$index])) {\r
+                               continue;\r
+                       }\r
+\r
+                       $line = $contents[$index];\r
+\r
+                       // skip if not separated by a colon character\r
+                       if(strpos($line, ":") === false) {\r
+                               continue;\r
+                       }\r
+\r
+                       $parts = explode(":", $line);\r
+                       \r
+                       // remove the key part\r
+                       array_shift($parts);\r
+\r
+                       // in case there was a colon in our value part glue it back together\r
+                       $value = implode('', $parts);\r
+\r
+                       $about[$key] = trim($value);\r
+               }\r
+\r
+               return $about;\r
+       }\r
+\r
+}
\ No newline at end of file
diff --git a/testcms-final-anon/system/classes/url.php b/testcms-final-anon/system/classes/url.php
new file mode 100644 (file)
index 0000000..d83028d
--- /dev/null
@@ -0,0 +1,104 @@
+<?php defined('IN_CMS') or die('No direct access allowed.');\r
+\r
+class Url {\r
+\r
+       private static $base_url, $index_page;\r
+\r
+       public static function make($uri = '') {\r
+               if(empty(static::$base_url)) {\r
+                       static::$base_url = Config::get('application.base_url');\r
+               }\r
+               \r
+               if(empty(static::$index_page)) {\r
+                       static::$index_page = Config::get('application.index_page') ? Config::get('application.index_page') . '/' : '';\r
+               }\r
+\r
+               return static::$base_url . static::$index_page . ltrim($uri, '/');\r
+       }\r
+       \r
+       public static function build($segments = array()) {\r
+               // make sure we have all the fragments\r
+               foreach(array('scheme', 'host', 'port', 'user', 'pass', 'path', 'query', 'fragment') as $fragment) {\r
+                       if(isset($segments[$fragment]) === false) {\r
+                               // set missing default\r
+                               switch($fragment) {\r
+                                       case 'scheme':\r
+                                               $segments[$fragment] = 'http';\r
+                                               break;\r
+                                       case 'host':\r
+                                               $segments[$fragment] = Input::server('http_host');\r
+                                               break;\r
+                                       default:\r
+                                               $segments[$fragment] = '';\r
+                               }\r
+                       }\r
+               }\r
+\r
+               $url = $segments['scheme'] . '://';\r
+\r
+               if($segments['user']) {\r
+                       $url .= $segments['user'];\r
+\r
+                       if($segments['pass']) {\r
+                               $url .= ':' . $segments['pass'];\r
+                       }\r
+\r
+                       $url .= '@';\r
+               }\r
+\r
+               $url .= trim($segments['host'], '/');\r
+               \r
+               if($segments['port']) {\r
+                       $url .= ':' . $segments['port'];\r
+               }\r
+\r
+               if($segments['path']) {\r
+                       $url .= '/' . ltrim($segments['path'], '/');\r
+               }\r
+\r
+               if($segments['query']) {\r
+                       if(is_array($segments['query'])) {\r
+                               $segments['query'] = http_build_query($segments['query']);\r
+                       }\r
+\r
+                       $url .= '?' . htmlentities($segments['query'], ENT_COMPAT, 'UTF-8', false);\r
+               }\r
+\r
+               if($segments['fragment']) {\r
+                       $url .= '#' . urlencode($segments['fragment']);\r
+               }\r
+\r
+               return $url;\r
+       }\r
+\r
+       public static function current() {\r
+               return parse_url(Input::server('REQUEST_URI'), PHP_URL_PATH);\r
+       }\r
+\r
+       public static function title($str) {\r
+               $search = '_';\r
+               $replace = '-';\r
+\r
+               $trans = array(\r
+                       '&\#\d+?;' => '',\r
+                       '&\S+?;' => '',\r
+                       '\s+' => $replace,\r
+                       '[^a-z0-9\-\._]' => '',\r
+                       $replace.'+' => $replace,\r
+                       $replace.'$' => '',\r
+                       '^'.$replace => '',\r
+                       '\.+$' => ''\r
+               );\r
+\r
+               $str = strip_tags($str);\r
+\r
+               foreach($trans as $key => $val) {\r
+                       $str = preg_replace("#" . $key . "#i", $val, $str);\r
+               }\r
+\r
+               $str = strtolower($str);\r
+\r
+               return trim(stripslashes($str));\r
+       }\r
+\r
+}\r
diff --git a/testcms-final-anon/system/classes/users.php b/testcms-final-anon/system/classes/users.php
new file mode 100644 (file)
index 0000000..9b0e2e9
--- /dev/null
@@ -0,0 +1,260 @@
+<?php defined('IN_CMS') or die('No direct access allowed.');\r
+\r
+class Users {\r
+\r
+       public static function authed() {\r
+               return Session::get('user');\r
+       }\r
+       \r
+       public static function list_all($params = array()) {\r
+               $sql = "select * from users where 1 = 1";\r
+               $args = array();\r
+               \r
+               if(isset($params['status'])) {\r
+                       $sql .= " and status = ?";\r
+                       $args[] = $params['status'];\r
+               }\r
+               \r
+               if(isset($params['sortby'])) {\r
+                       $sql .= " order by " . $params['sortby'];\r
+                       \r
+                       if(isset($params['sortmode'])) {\r
+                               $sql .= " " . $params['sortmode'];\r
+                       }\r
+               }\r
+\r
+               return new Items(Db::results($sql, $args));\r
+       }\r
+       \r
+       public static function find($where = array()) {\r
+               $sql = "select * from users";\r
+               $args = array();\r
+               \r
+               if(isset($where['hash'])) {\r
+                       $sql .= " where md5(concat(`id`, `email`, `password`)) = " . $where['hash'] . " limit 1";\r
+                       \r
+                       // reset clause\r
+                       $where = array();\r
+               }\r
+               \r
+               if(count($where)) {\r
+                       $clause = array();\r
+                       foreach($where as $key => $value) {\r
+                               $clause[] = '`' . $key . '` = "' . $value . '"';\r
+                       }\r
+                       $sql .= " where " . implode(' and ', $clause);\r
+                       \r
+               }\r
+               \r
+               return Db::row($sql, $args);\r
+       }\r
+\r
+\r
+       public static function login() {\r
+               // get posted data\r
+               $post = Input::post(array('user', 'pass', 'remember'));\r
+               $errors = array();\r
+\r
+               // remove white space\r
+               $post = array_map('trim', $post);\r
+               \r
+               if(empty($post['user'])) {\r
+                       $errors[] = 'Please enter your username';\r
+               }\r
+               \r
+               if(empty($post['pass'])) {\r
+                       $errors[] = 'Please enter your password';\r
+               }\r
+\r
+               if(empty($errors)) {\r
+                       // find user\r
+                       if($user = Users::find(array('username' => $post['user']))) {\r
+                               // check password\r
+                               if(crypt($post['pass'], $user->password) != $user->password) {\r
+                                       $errors[] = 'Incorrect details';\r
+                               }\r
+                       } else {\r
+                               $errors[] = 'Incorrect details';\r
+                       }\r
+               }\r
+               \r
+               if(count($errors)) {\r
+                       Notifications::set('error', $errors);\r
+                       return false;\r
+               }\r
+               \r
+               // if we made it this far that means we have a winner\r
+               Session::set('user', $user);\r
+               \r
+               return true;\r
+       }\r
+\r
+       public static function logout() {\r
+               Session::forget('user');\r
+       }\r
+       \r
+       public static function recover_password() {\r
+               $post = Input::post(array('email'));\r
+               $errors = array();\r
+\r
+               if(filter_var($post['email'], FILTER_VALIDATE_EMAIL) === false) {\r
+                       $errors[] = 'Please enter a valid email address';\r
+               } else {\r
+                       if(($user = static::find(array('email' => $post['email']))) === false) {\r
+                               $errors[] = 'Account not found';\r
+                       }\r
+               }\r
+               \r
+               if(count($errors)) {\r
+                       Notifications::set('error', $errors);\r
+                       return false;\r
+               }\r
+               \r
+               $hash = hash('md5', $user->id . $user->email . $user->password);\r
+               $link = Url::build(array(\r
+                       'path' => Url::make('admin/users/reset/' . $hash)\r
+               ));\r
+               \r
+               $subject = '[' . Config::get('metadata.sitename') . '] Password Reset';\r
+               $plain = 'You have requested to reset your password. To continue follow the link below. ' . $link;\r
+               $headers = array('From' => 'no-reply@' . Input::server('http_host'));\r
+               \r
+               Email::send($user->email, $subject, $plain, $headers);\r
+               \r
+               Notifications::set('notice', 'We have sent you an email to confirm your password change.');\r
+               \r
+               return true;\r
+       }\r
+       \r
+       public static function reset_password($id) {\r
+               $post = Input::post(array('password'));\r
+               $errors = array();\r
+\r
+               if(empty($post['password'])) {\r
+                       $errors[] = 'Please enter a password';\r
+               }\r
+               \r
+               if(count($errors)) {\r
+                       Notifications::set('error', $errors);\r
+                       return false;\r
+               }\r
+               \r
+               $password = crypt($post['password']);\r
+               \r
+               $sql = "update users set `password` = ? where id = ?";\r
+               Db::query($sql, array($password, $id));\r
+               \r
+               Notifications::set('success', 'Your new password has been set');\r
+               \r
+               return true;\r
+       }\r
+       \r
+       public static function delete($id) {\r
+               Db::delete('users', array('id' => $id));\r
+               \r
+               Notifications::set('success', 'User has been deleted');\r
+               \r
+               return true;\r
+       }\r
+       \r
+       public static function update($id) {\r
+               $post = Input::post(array('username', 'password', 'email', 'real_name', 'bio', 'status', 'role', 'delete'));\r
+               $errors = array();\r
+\r
+               // delete\r
+               if($post['delete'] !== false) {\r
+                       return static::delete($id);\r
+               } else {\r
+                       // remove it frm array\r
+                       unset($post['delete']);\r
+               }\r
+               \r
+               if(empty($post['username'])) {\r
+                       $errors[] = 'Please enter a username';\r
+               } else {\r
+                       if(($user = static::find(array('username' => $post['username']))) and $user->id != $id) {\r
+                               $errors[] = 'Username is already being used';\r
+                       }\r
+               }\r
+\r
+               if(filter_var($post['email'], FILTER_VALIDATE_EMAIL) === false) {\r
+                       $errors[] = 'Please enter a valid email address';\r
+               }\r
+\r
+               if(empty($post['real_name'])) {\r
+                       $errors[] = 'Please enter a display name';\r
+               }\r
+               \r
+               if(strlen($post['password'])) {\r
+                       // encrypt new password\r
+                       $post['password'] = crypt($post['password']);\r
+               } else {\r
+                       // remove it and leave it unchanged\r
+                       unset($post['password']);\r
+               }\r
+               \r
+               if(count($errors)) {\r
+                       Notifications::set('error', $errors);\r
+                       return false;\r
+               }\r
+\r
+               // format email\r
+               $post['email'] = strtolower(trim($post['email']));\r
+               \r
+               // update record\r
+               Db::update('users', $post, array('id' => $id));\r
+               \r
+               // update user session?\r
+               if(Users::authed()->id == $id) {\r
+                       Session::set('user', static::find(array('id' => $id)));\r
+               }\r
+               \r
+               Notifications::set('success', 'User has been updated');\r
+               \r
+               return true;\r
+       }\r
+\r
+       public static function add() {\r
+               $post = Input::post(array('username', 'password', 'email', 'real_name', 'bio', 'status', 'role'));\r
+               $errors = array();\r
+               \r
+               if(empty($post['username'])) {\r
+                       $errors[] = 'Please enter a username';\r
+               } else {\r
+                       if(static::find(array('username' => $post['username']))) {\r
+                               $errors[] = 'Username is already being used';\r
+                       }\r
+               }\r
+               \r
+               if(empty($post['password'])) {\r
+                       $errors[] = 'Please enter a password';\r
+               }\r
+\r
+               if(filter_var($post['email'], FILTER_VALIDATE_EMAIL) === false) {\r
+                       $errors[] = 'Please enter a valid email address';\r
+               }\r
+\r
+               if(empty($post['real_name'])) {\r
+                       $errors[] = 'Please enter a display name';\r
+               }\r
+               \r
+               if(count($errors)) {\r
+                       Notifications::set('error', $errors);\r
+                       return false;\r
+               }\r
+               \r
+               // encrypt password\r
+               $post['password'] = crypt($post['password']);\r
+               \r
+               // format email\r
+               $post['email'] = strtolower(trim($post['email']));\r
+               \r
+               // add record\r
+               Db::insert('users', $post);\r
+               \r
+               Notifications::set('success', 'A new user has been added');\r
+               \r
+               return true;\r
+       }\r
+\r
+}\r
diff --git a/testcms-final-anon/system/functions/articles.php b/testcms-final-anon/system/functions/articles.php
new file mode 100644 (file)
index 0000000..3c398a1
--- /dev/null
@@ -0,0 +1,142 @@
+<?php defined('IN_CMS') or die('No direct access allowed.');\r
+\r
+/**\r
+       Theme functions for articles\r
+*/\r
+function article_id() {\r
+       if($itm = IoC::resolve('article')) {\r
+               return $itm->id;\r
+       }\r
+       \r
+       return '';\r
+}\r
+\r
+function article_title() {\r
+       if($itm = IoC::resolve('article')) {\r
+               return $itm->title;\r
+       }\r
+       \r
+       return '';\r
+}\r
+\r
+function article_slug() {\r
+       if($itm = IoC::resolve('article')) {\r
+               return $itm->slug;\r
+       }\r
+       \r
+       return '';\r
+}\r
+\r
+function article_url() {\r
+       if($itm = IoC::resolve('article')) {\r
+               $page = IoC::resolve('posts_page');\r
+               return Url::make($page->slug . '/' . $itm->slug);\r
+       }\r
+       \r
+       return '';\r
+}\r
+\r
+function article_description() {\r
+       if($itm = IoC::resolve('article')) {\r
+               return $itm->description;\r
+       }\r
+       \r
+       return '';\r
+}\r
+\r
+function article_html() {\r
+       if($itm = IoC::resolve('article')) {\r
+               return $itm->html;\r
+       }\r
+       \r
+       return '';\r
+}\r
+\r
+function article_css() {\r
+       if($itm = IoC::resolve('article')) {\r
+               return $itm->css;\r
+       }\r
+       \r
+       return '';\r
+}\r
+\r
+function article_js() {\r
+       if($itm = IoC::resolve('article')) {\r
+               return $itm->js;\r
+       }\r
+       \r
+       return '';\r
+}\r
+\r
+function article_time() {\r
+       if($itm = IoC::resolve('article')) {\r
+               return $itm->created;\r
+       }\r
+       \r
+       return '';\r
+}\r
+\r
+function article_date() {\r
+       if(article_time() !== '') {\r
+           return date(Config::get('metadata.date_format'), article_time());\r
+       }\r
+       \r
+       return '';\r
+}\r
+\r
+function article_status() {\r
+       if($itm = IoC::resolve('article')) {\r
+               return $itm->status;\r
+       }\r
+       \r
+       return '';\r
+}\r
+\r
+function article_total_comments() {\r
+       if($itm = IoC::resolve('article')) {\r
+               return $itm->total_comments;\r
+       }\r
+       \r
+       return 0;\r
+}\r
+\r
+function article_author() {\r
+       if($itm = IoC::resolve('article')) {\r
+               return $itm->author;\r
+       }\r
+       \r
+       return '';\r
+}\r
+\r
+function article_author_bio() {\r
+       if($itm = IoC::resolve('article')) {\r
+               return $itm->bio;\r
+       }\r
+       \r
+       return '';\r
+}\r
+\r
+function article_custom_fields() {\r
+    if($itm = IoC::resolve('article')) {\r
+       if(isset($itm->custom_fields)) {\r
+           // get associative array\r
+           $data = json_decode($itm->custom_fields, true);\r
+           return is_array($data) ? $data : array();\r
+       }\r
+    }\r
+    \r
+    return array();\r
+}\r
+\r
+function article_custom_field($key, $default = '') {\r
+    $fields = article_custom_fields();\r
+    return isset($fields[$key]) ? $fields[$key]['value'] : $default;\r
+}\r
+\r
+function customised() {\r
+       if($itm = IoC::resolve('article')) {\r
+               return strlen($itm->css) > 0 or strlen($itm->js) > 0;\r
+       }\r
+       \r
+       return false;\r
+}\r
diff --git a/testcms-final-anon/system/functions/comments.php b/testcms-final-anon/system/functions/comments.php
new file mode 100644 (file)
index 0000000..9045511
--- /dev/null
@@ -0,0 +1,116 @@
+<?php defined('IN_CMS') or die('No direct access allowed.');\r
+\r
+/**\r
+       Theme functions for comments\r
+*/\r
+\r
+function has_comments() {\r
+       if(($itm = IoC::resolve('article')) === false) {\r
+               return false;\r
+       }\r
+               \r
+       if(($items = IoC::resolve('comments')) === false) {\r
+               $items = Comments::list_all(array('status' => 'published', 'post' => $itm->id));\r
+               IoC::instance('comments', $items, true);\r
+       }\r
+       \r
+       return $items->length() > 0;\r
+}\r
+\r
+function total_comments() {\r
+       if(has_comments() === false) {\r
+               return 0;\r
+       }\r
+       \r
+       $items = IoC::resolve('comments');\r
+       return $items->length();\r
+}\r
+\r
+// loop comments\r
+function comments() {\r
+       if(has_comments() === false) {\r
+               return false;\r
+       }\r
+\r
+       $items = IoC::resolve('comments');\r
+\r
+       if($result = $items->valid()) { \r
+               // register single comment\r
+               IoC::instance('comment', $items->current(), true);\r
+               \r
+               // move to next\r
+               $items->next();\r
+       }\r
+\r
+       return $result;\r
+}\r
+\r
+// single comments\r
+function comment_id() {\r
+       if($itm = IoC::resolve('comment')) {\r
+               return $itm->id;\r
+       }\r
+       \r
+       return '';\r
+}\r
+\r
+function comment_time() {\r
+       if($itm = IoC::resolve('comment')) {\r
+               return $itm->date;\r
+       }\r
+       \r
+       return '';\r
+}\r
+\r
+function comment_date() {\r
+       if($itm = IoC::resolve('comment')) {\r
+               return date(Config::get('metadata.date_format'), $itm->date);\r
+       }\r
+       \r
+       return '';\r
+}\r
+\r
+function comment_name() {\r
+       if($itm = IoC::resolve('comment')) {\r
+               return $itm->name;\r
+       }\r
+       \r
+       return '';\r
+}\r
+\r
+function comment_text() {\r
+       if($itm = IoC::resolve('comment')) {\r
+               return $itm->text;\r
+       }\r
+       \r
+       return '';\r
+}\r
+\r
+function comments_open() {\r
+       if($itm = IoC::resolve('article')) {\r
+               return $itm->comments ? true : false;\r
+       }\r
+       \r
+       return false;\r
+}\r
+\r
+// form elements\r
+function comment_form_notifications() {\r
+       return Notifications::read();\r
+}\r
+\r
+function comment_form_input_name($extra = '') {\r
+       return '<input name="name" id="name" type="text" ' . $extra . '>';\r
+}\r
+\r
+function comment_form_input_email($extra = '') {\r
+       return '<input name="email" id="email" type="email" ' . $extra . '>';\r
+}\r
+\r
+function comment_form_input_text($extra = '') {\r
+       return '<textarea name="text" id="text" ' . $extra . '></textarea>';\r
+}\r
+\r
+function comment_form_button($text = 'Post Comment', $extra = '') {\r
+       return '<button class="btn" type="submit" ' . $extra . '>' . $text . '</button>';\r
+}
\ No newline at end of file
diff --git a/testcms-final-anon/system/functions/helpers.php b/testcms-final-anon/system/functions/helpers.php
new file mode 100644 (file)
index 0000000..fe6a2ba
--- /dev/null
@@ -0,0 +1,107 @@
+<?php defined('IN_CMS') or die('No direct access allowed.');\r
+\r
+/**\r
+       Theme helpers functions\r
+*/\r
+\r
+\r
+// Url helpers\r
+function base_url($url = '') {\r
+    return Url::make($url);\r
+}\r
+\r
+function theme_url($file = '') {\r
+       return Config::get('application.base_url') . 'themes/' . Config::get('metadata.theme') . '/' . ltrim($file, '/');\r
+}\r
+\r
+function current_url() {\r
+       return Url::make(Request::uri());\r
+}\r
+\r
+function admin_url($url = '') {\r
+    return Url::make(Config::get('application.admin_folder') . '/' . ltrim($url, '/'));\r
+}\r
+\r
+function search_url() {\r
+       return Url::make('search');\r
+}\r
+\r
+function rss_url() {\r
+    return Url::make('rss');\r
+}\r
+\r
+//  Custom function helpers\r
+function bind($page, $fn) {\r
+       Events::bind($page, $fn);\r
+}\r
+\r
+function recieve($name = '') {\r
+       return Events::call($name);\r
+}\r
+\r
+// page type helpers\r
+function is_homepage() {\r
+       if($itm = IoC::resolve('page')) {\r
+               return $itm->id == Config::get('metadata.home_page');\r
+       }\r
+\r
+       return false;\r
+}\r
+\r
+function is_postspage() {\r
+       if($itm = IoC::resolve('page')) {\r
+               return $itm->id == Config::get('metadata.posts_page');\r
+       }\r
+\r
+       return false;\r
+}\r
+\r
+function is_debug() {\r
+       return Config::get('debug', false);\r
+}\r
+\r
+// benchmarking\r
+function execution_time() {\r
+       $miliseconds = microtime(true) - START;\r
+       return round($miliseconds, 4);\r
+}\r
+\r
+// return in mb\r
+function memory_usage() {\r
+       return memory_get_peak_usage(true) / 1024;\r
+}\r
+\r
+// database profile information\r
+function db_profile() {\r
+       // total query time\r
+       $total = 0;\r
+\r
+       $html = '<style>';\r
+       $html .= '.debug {display: none;font-size: 13px; margin-bottom: 1em;}';\r
+       $html .= '.debug td, .debug th {padding: 4px 6px; border-bottom: 1px solid #ddd;}';\r
+       $html .= '.debug th {font-weight: bold; text-align: center;}';\r
+       $html .= '.debug tfoot td:first-child {text-align: right;}';\r
+       $html .= '</style>';\r
+\r
+       $html .= '<table id="debug_table" class="debug">';\r
+       $html .= '<thead><tr><th>SQL</th><th>Bindings</th><th>Rows</th><th>Time</th></th></thead>';\r
+\r
+       $html .= '<tbody>';\r
+\r
+       foreach(Db::profile() as $row) {\r
+               $html .= '<tr><td>' . $row['sql'] . '</td><td>' . implode(', ', $row['binds']) . '</td><td>' . $row['rows'] . '</td><td>' . $row['time'] . '</td></tr>';\r
+               $total += $row['time'];\r
+       }\r
+\r
+       $html .= '</tbody>';\r
+\r
+       $html .= '<tfoot>';\r
+       $html .= '<tr><td colspan="3"><strong>Query Time</strong></td><td>' . round($total, 4) . '</td></tr>';\r
+       $html .= '<tr><td colspan="3"><strong>Execution Time</strong></td><td>' . execution_time() . '</td></tr>';\r
+       $html .= '<tr><td colspan="3"><strong>Memory Usage</strong></td><td>' . memory_usage() . 'Kb</td></tr>';\r
+       $html .= '</tfoot>';\r
+\r
+       $html .= '</table>';\r
+\r
+       return $html;\r
+}\r
diff --git a/testcms-final-anon/system/functions/menus.php b/testcms-final-anon/system/functions/menus.php
new file mode 100644 (file)
index 0000000..0c48c81
--- /dev/null
@@ -0,0 +1,74 @@
+<?php defined('IN_CMS') or die('No direct access allowed.');\r
+\r
+/**\r
+       Theme functions for menus\r
+*/\r
+function has_menu_items() {\r
+       if(($total = IoC::resolve('total_menu_items')) === false) {\r
+               $total = Pages::count(array('status' => 'published'));\r
+               IoC::instance('total_menu_items', $total, true);\r
+       }\r
+       return $total;\r
+}\r
+\r
+function menu_items($params = array()) {\r
+       if(!has_menu_items()) {\r
+               return false;\r
+       }\r
+\r
+       if(($pages = IoC::resolve('menu')) === false) {\r
+               $params['status'] = 'published';\r
+               $pages = Pages::list_all($params);\r
+               IoC::instance('menu', $pages, true);\r
+       }\r
+\r
+       if($result = $pages->valid()) { \r
+               // register single post\r
+               IoC::instance('menu_item', $pages->current(), true);\r
+               \r
+               // move to next\r
+               $pages->next();\r
+       }\r
+\r
+       return $result;\r
+}\r
+\r
+function menu_id() {\r
+       if($itm = IoC::resolve('menu_item')) {\r
+               return $itm->id;\r
+       }\r
+       \r
+       return '';\r
+}\r
+\r
+function menu_url() {\r
+       if($itm = IoC::resolve('menu_item')) {\r
+               return $itm->url;\r
+       }\r
+       \r
+       return '';\r
+}\r
+\r
+function menu_name() {\r
+       if($itm = IoC::resolve('menu_item')) {\r
+               return $itm->name;\r
+       }\r
+       \r
+       return '';\r
+}\r
+\r
+function menu_title() {\r
+       if($itm = IoC::resolve('menu_item')) {\r
+               return $itm->title;\r
+       }\r
+\r
+       return $default;\r
+}\r
+\r
+function menu_active() {\r
+       if($itm = IoC::resolve('menu_item')) {\r
+               return $itm->active;\r
+       }\r
+       \r
+       return '';\r
+}\r
diff --git a/testcms-final-anon/system/functions/metadata.php b/testcms-final-anon/system/functions/metadata.php
new file mode 100644 (file)
index 0000000..5b3c125
--- /dev/null
@@ -0,0 +1,24 @@
+<?php defined('IN_CMS') or die('No direct access allowed.');\r
+\r
+/**\r
+       Theme functions for metadata\r
+*/\r
+function site_name() {\r
+       return Config::get('metadata.sitename');\r
+}\r
+\r
+function site_description() {\r
+       return Config::get('metadata.description');\r
+}\r
+\r
+/*\r
+       Twitter\r
+*/\r
+function twitter_account() {\r
+       return Config::get('metadata.twitter');\r
+}\r
+\r
+function twitter_url() {\r
+    return 'http://twitter.com/' . twitter_account();\r
+}\r
+\r
diff --git a/testcms-final-anon/system/functions/pages.php b/testcms-final-anon/system/functions/pages.php
new file mode 100644 (file)
index 0000000..7de6153
--- /dev/null
@@ -0,0 +1,64 @@
+<?php defined('IN_CMS') or die('No direct access allowed.');\r
+\r
+/**\r
+       Theme functions for pages\r
+*/\r
+function page_id() {\r
+       if($itm = IoC::resolve('page')) {\r
+               return $itm->id;\r
+       }\r
+       \r
+       return '';\r
+}\r
+\r
+function page_url() {\r
+       if($itm = IoC::resolve('page')) {\r
+               return $itm->url;\r
+       }\r
+       \r
+       return '';\r
+}\r
+\r
+function page_name() {\r
+       if($itm = IoC::resolve('page')) {\r
+               return $itm->name;\r
+       }\r
+       \r
+       return '';\r
+}\r
+\r
+function page_title($default = '') {\r
+       if($itm = IoC::resolve('page')) {\r
+               return $itm->title;\r
+       }\r
+       if($itm = IoC::resolve('article')) {\r
+               return $itm->title;\r
+       }\r
+\r
+       return $default;\r
+}\r
+\r
+function page_content() {\r
+       if($itm = IoC::resolve('page')) {\r
+               return $itm->content;\r
+       }\r
+       \r
+       return '';\r
+}\r
+\r
+\r
+function page_active() {\r
+       if($itm = IoC::resolve('page')) {\r
+               return $itm->active;\r
+       }\r
+       \r
+       return '';\r
+}\r
+\r
+function page_status() {\r
+       if($itm = IoC::resolve('page')) {\r
+               return $itm->status;\r
+       }\r
+       \r
+       return '';\r
+}
\ No newline at end of file
diff --git a/testcms-final-anon/system/functions/posts.php b/testcms-final-anon/system/functions/posts.php
new file mode 100644 (file)
index 0000000..e4e5fb7
--- /dev/null
@@ -0,0 +1,71 @@
+<?php defined('IN_CMS') or die('No direct access allowed.');\r
+\r
+/**\r
+       Theme functions for posts\r
+*/\r
+function has_posts() {\r
+       if(($posts = IoC::resolve('posts')) === false) {\r
+               $params = array(\r
+                       'status' => 'published', \r
+                       'sortby' => 'id', \r
+                       'sortmode' => 'desc', \r
+                       'limit' => Config::get('metadata.posts_per_page', 10), \r
+                       'offset' => Input::get('offset', 0)\r
+               );\r
+               $posts = Posts::list_all($params);\r
+               IoC::instance('posts', $posts, true);\r
+\r
+               $total_posts = Posts::count(array('status' => 'published'));\r
+               IoC::instance('total_posts', $total_posts, true);\r
+       }\r
+       \r
+       return $posts->length() > 0;\r
+}\r
+\r
+function posts() {\r
+       if(has_posts() === false) {\r
+               return false;\r
+       }\r
+       \r
+       $posts = IoC::resolve('posts');\r
+\r
+       if($result = $posts->valid()) { \r
+               // register single post\r
+               IoC::instance('article', $posts->current(), true);\r
+               \r
+               // move to next\r
+               $posts->next();\r
+       }\r
+\r
+       return $result;\r
+}\r
+\r
+function posts_next($text = 'Next', $default = '') {\r
+       $per_page = Config::get('metadata.posts_per_page');\r
+       $offset = Input::get('offset', 0);\r
+       $total = IoC::resolve('total_posts');\r
+\r
+       $pages = floor($total / $per_page);\r
+       $page = $offset / $per_page;\r
+\r
+       if($page < $pages) {\r
+               return '<a href="' . current_url() . '?offset=' . ($offset + $per_page) . '">' . $text . '</a>';\r
+       }\r
+\r
+       return $default;\r
+}\r
+\r
+function posts_prev($text = 'Previous', $default = '') {\r
+       $per_page = Config::get('metadata.posts_per_page');\r
+       $offset = Input::get('offset', 0);\r
+       $total = IoC::resolve('total_posts');\r
+\r
+       $pages = ceil($total / $per_page);\r
+       $page = $offset / $per_page;\r
+\r
+       if($offset > 0) {\r
+               return '<a href="' . current_url() . '?offset=' . ($offset - $per_page) . '">' . $text . '</a>';\r
+       }\r
+\r
+       return $default;\r
+}
\ No newline at end of file
diff --git a/testcms-final-anon/system/functions/search.php b/testcms-final-anon/system/functions/search.php
new file mode 100644 (file)
index 0000000..58258ee
--- /dev/null
@@ -0,0 +1,68 @@
+<?php defined('IN_CMS') or die('No direct access allowed.');\r
+\r
+/**\r
+       Theme functions for search\r
+*/\r
+function has_search_results() {\r
+       if($items = IoC::resolve('search')) {\r
+               return $items->length() > 0;\r
+       }\r
+       \r
+       return false;\r
+}\r
+\r
+function total_search_results() {\r
+       if($total = IoC::resolve('total_search')) {\r
+               return $total;\r
+       }\r
+       \r
+       return 0;\r
+}\r
+\r
+function search_results() {\r
+       $posts = IoC::resolve('search');\r
+\r
+       if($result = $posts->valid()) { \r
+               // register single post\r
+               IoC::instance('article', $posts->current(), true);\r
+               \r
+               // move to next\r
+               $posts->next();\r
+       }\r
+\r
+       return $result;\r
+}\r
+\r
+function search_term() {\r
+       return (Request::uri_segment(1) == 'search' ? Request::uri_segment(2) : '');\r
+}\r
+\r
+function search_next($text = 'Next', $default = '') {\r
+       $per_page = Config::get('metadata.posts_per_page');\r
+       $offset = Input::get('offset', 0);\r
+       $total = IoC::resolve('total_search');\r
+\r
+       $pages = floor($total / $per_page);\r
+       $page = $offset / $per_page;\r
+\r
+       if($page < $pages) {\r
+               return '<a href="' . current_url() . '?offset=' . ($offset + $per_page) . '">' . $text . '</a>';\r
+       }\r
+\r
+       return $default;\r
+}\r
+\r
+function search_prev($text = 'Previous', $default = '') {\r
+       $per_page = Config::get('metadata.posts_per_page');\r
+       $offset = Input::get('offset', 0);\r
+       $total = IoC::resolve('total_search');\r
+\r
+       $pages = ceil($total / $per_page);\r
+       $page = $offset / $per_page;\r
+\r
+       if($offset > 0) {\r
+               return '<a href="' . current_url() . '?offset=' . ($offset - $per_page) . '">' . $text . '</a>';\r
+       }\r
+\r
+       return $default;\r
+}
\ No newline at end of file
diff --git a/testcms-final-anon/system/functions/users.php b/testcms-final-anon/system/functions/users.php
new file mode 100644 (file)
index 0000000..6c54bda
--- /dev/null
@@ -0,0 +1,48 @@
+<?php defined('IN_CMS') or die('No direct access allowed.');\r
+\r
+/**\r
+       Theme functions for users\r
+*/\r
+function user_authed() {\r
+       return Users::authed() !== false;\r
+}\r
+\r
+function user_authed_id() {\r
+       if($user = Users::authed()) {\r
+               return $user->id;\r
+       }\r
+\r
+       return '';\r
+}\r
+\r
+function user_authed_name() {\r
+       if($user = Users::authed()) {\r
+               return $user->username;\r
+       }\r
+\r
+       return '';\r
+}\r
+\r
+function user_authed_email() {\r
+       if($user = Users::authed()) {\r
+               return $user->email;\r
+       }\r
+\r
+       return '';\r
+}\r
+\r
+function user_authed_role() {\r
+       if($user = Users::authed()) {\r
+               return $user->role;\r
+       }\r
+\r
+       return '';\r
+}\r
+\r
+function user_authed_real_name() {\r
+       if($user = Users::authed()) {\r
+               return $user->real_name;\r
+       }\r
+\r
+       return '';\r
+}
\ No newline at end of file
diff --git a/testcms-final-anon/themes/default/404.php b/testcms-final-anon/themes/default/404.php
new file mode 100644 (file)
index 0000000..3573af5
--- /dev/null
@@ -0,0 +1,9 @@
+\r
+<section class="content">\r
+    <h1>Oh no, this page can&rsquo;t be found.</h1>\r
+\r
+    <p>Unfortunately, the page at <code><?php echo current_url(); ?></code> \r
+    can't be found, but don't give up hope yet! You can always try going back to \r
+    the homepage, or searching.</p>\r
+</section>\r
+\r
diff --git a/testcms-final-anon/themes/default/about.txt b/testcms-final-anon/themes/default/about.txt
new file mode 100644 (file)
index 0000000..56b0b66
--- /dev/null
@@ -0,0 +1,5 @@
+Theme name:    Default\r
+Description:   Default Theme\r
+Author name:   Test CMS\r
+Author site:   http://google.com\r
+License:       WTFPL (http://sam.zoy.org/wtfpl/COPYING)\r
diff --git a/testcms-final-anon/themes/default/article.php b/testcms-final-anon/themes/default/article.php
new file mode 100644 (file)
index 0000000..ffbf5c5
--- /dev/null
@@ -0,0 +1,15 @@
+<section class="content" id="article-<?php echo article_id(); ?>">\r
+    <h1><?php echo article_title(); ?></h1>\r
+       \r
+       <article>\r
+           <?php echo article_html(); ?>\r
+       </article>\r
+</section>\r
+\r
+<?php include 'includes/comment_form.php'; ?>\r
+\r
+<section class="footnote">\r
+       <p>This article is my <?php echo numeral(article_id()); ?> oldest. It is <?php echo count_words(article_html()); ?> words long. \r
+       <?php echo article_custom_field('attribution'); ?></p>\r
+</section>\r
+\r
diff --git a/testcms-final-anon/themes/default/css/reset.css b/testcms-final-anon/themes/default/css/reset.css
new file mode 100644 (file)
index 0000000..9341f6f
--- /dev/null
@@ -0,0 +1,58 @@
+* { margin: 0; padding: 0; -webkit-font-smoothing: antialiased; }\r
+\r
+html { min-height: 100.01%; }\r
+body { text-align: center; }\r
+\r
+img { border: none; -ms-interpolation-mode: bicubic; image-rendering: optimizeQuality; display: block; }\r
+\r
+table { border-collapse: separate; border-spacing: 0; vertical-align: top; }\r
+caption, th, td { text-align: left; font-weight: normal; vertical-align: top; }\r
+\r
+fieldset { border: none; }\r
+textarea { resize: vertical; }\r
+label[for] { font-weight: bold; cursor: pointer; }\r
+button { cursor: pointer; }\r
+\r
+input { -webkit-border-radius: 0; }\r
+       input[type=search], input[type=number]::-webkit-inner-spin-button, input[type=number]::-webkit-outer-spin-button, ::-webkit-search-cancel-button, input[type=search]::-webkit-search-decoration, input[type=search]::-webkit-search-results-button, input[type=search]::-webkit-search-results-decoration  { -webkit-appearance: none !important; margin: 0; }\r
+\r
+article, aside, details, figcaption, figure, footer, header, hgroup, menu, nav, section { display: block; }\r
+       nav ul { list-style: none; }\r
+\r
+.transition { -webkit-transition-duration: .5s; -webkit-transition-timing-function: ease-in-out; -moz-transition-duration: .5s; -moz-transition-timing-function: ease-in-out; transition-duration: .5s; transition-timing-function: ease-in-out; -o-transition-duration: .5s; -o-transition-timing-function: ease-in-out; }\r
+       .transition.opacity { -webkit-transition-property: opacity; -moz-transition-property: opacity; transition-property: opacity; -o-transition-property: opacity; }\r
+       .transition.color { -webkit-transition-property: color; -moz-transition-property: color; transition-property: color; -o-transition-property: color; }\r
+       .transition.background { -webkit-transition-property: background; -moz-transition-property: background; transition-property: background; -o-transition-property: background; }\r
+       .transition.border { -webkit-transition-property: border; -moz-transition-property: border; transition-property: border; -o-transition-property: border; }\r
+       .transition.all { -webkit-transition-property: all; -moz-transition-property: all; transition-property: all; -o-transition-property: all; }\r
+.notransition { -webkit-transition: none; -moz-transition: none; transition: none; -o-transition: none; }\r
+\r
+.hidden { text-indent: -999em; }\r
+       .block.hidden, nav#skip-links { position: absolute; left: -999em; top: -999em; }\r
+       \r
+.wrap { text-align: left; margin: 0 auto; }\r
+       \r
+.radius { -moz-border-radius: 5px; -webkit-border-radius: 5px; border-radius: 5px; -khtml-border-radius: 5px; -moz-background-clip: padding; -webkit-background-clip: padding-box; background-clip: padding-box; }\r
+\r
+.clear { zoom: 1; overflow: auto; clear: both; }\r
+       .clear:before, .clear:after { content: ''; display: table; }\r
+       .group:after { clear: both; }\r
+       \r
+.ghost, .disabled { opacity: .5; filter: alpha(opacity=50); }\r
+       .ghost.super { opacity: .2; filter: alpha(opacity=20); }\r
+       .ghost.sub { opacity: .8; filter: alpha(opacity=80); }\r
+       \r
+.align { margin: 0 auto; }\r
+       .align.text { text-align: center; }\r
+       .align.vertical { vertical-align: center; position: absolute; left: 50%; top: 50%; }\r
+       \r
+dl { position: relative; }\r
+    dt { font-weight: bold; }\r
+    dd { opacity: .7; }\r
+\r
+.float { float: inherit; }\r
+       .float.left { float: left; }\r
+       .float.right { float: right; }\r
+       \r
+.hidden { display: none; }\r
+.hide { position: absolute; left: -999em; top: -999em; }
\ No newline at end of file
diff --git a/testcms-final-anon/themes/default/css/style.css b/testcms-final-anon/themes/default/css/style.css
new file mode 100644 (file)
index 0000000..fb02058
--- /dev/null
@@ -0,0 +1,551 @@
+/**\r
+ *    TestCMS' default theme\r
+ */\r
\r
+::-webkit-selection {\r
+       background: #ffc;\r
+       color: #222;\r
+}\r
+::-moz-selection {\r
+       background: #ffc;\r
+       color: #222;\r
+}\r
+::selection {\r
+       background: #ffc;\r
+       color: #222;\r
+}\r
+\r
+html {\r
+    min-height: 100%;\r
+}\r
+\r
+body, input, textarea, button {\r
+       color: #777;\r
+       font: 16px/26px "Helvetica Neue", sans-serif;\r
+}\r
+\r
+h1 {\r
+    font-size: 40px;\r
+    line-height: 48px;\r
+    font-weight: bold;\r
+    \r
+    color: #333;\r
+\r
+    margin-bottom: 30px;\r
+}\r
+\r
+a, a * {\r
+    -webkit-transition: color .25s;\r
+    -moz-transition: color .25s;\r
+    -ms-transition: color .25s;\r
+    -o-transition: color .25s;\r
+    transition: color .25s;\r
+}\r
+    a:active {\r
+        -webkit-transform: translateY(1px);\r
+    }\r
+    \r
+.content a, .comments a {\r
+    color: #2082ab;\r
+}\r
+    .content a:hover, .comments a:hover {\r
+        color: #222;\r
+    }\r
+\r
+.wrap, .content {\r
+       width: 900px;\r
+       margin: 0 auto;\r
+       \r
+       text-align: left;\r
+}\r
+    .content {        \r
+        width: 730px;\r
+        margin: 60px auto 80px;\r
+    \r
+        padding-left: 170px;\r
+    }\r
+        .content img, .content .items {\r
+            margin-left: -170px;\r
+            \r
+            width: 900px;\r
+            height: auto;\r
+        }\r
+        .content p {\r
+            padding-bottom: 15px;\r
+        }\r
+\r
+form#search {\r
+       position: relative;\r
+       background: #ddd;\r
+       \r
+       padding: 10px 0;\r
+}\r
+       form#search input {\r
+               padding: 8px 12px;\r
+               color: #333;\r
+               \r
+               border: none;\r
+               width: 900px;\r
+       }\r
+       \r
+button {\r
+    background: #2082ab;\r
+\r
+    color: #fff;\r
+    font-weight: bold;\r
+\r
+    border: none;\r
+    \r
+    padding: 8px 15px;\r
+    \r
+    -webkit-border-radius: 3px;\r
+    -moz-border-radius: 3px;\r
+    border-radius: 3px;\r
+}\r
+\r
+header#top {\r
+       background: #f3f3f3;\r
+       padding: 50px 0 20px;\r
+}\r
+       header#top div {\r
+               position: relative;\r
+       }\r
+       header#top a#logo {\r
+               color: #444;\r
+               font-size: 18px;\r
+               line-height: 21px;\r
+               \r
+               text-decoration: none;\r
+               \r
+               display: block;\r
+               width: 130px;\r
+               \r
+               padding-bottom: 4px;\r
+       }\r
+           header#top a#logo:hover, header#top nav li.active a, header#top nav li.active a:hover {\r
+               color: #2082ab;\r
+           }\r
+       header#top nav {\r
+               position: absolute;\r
+               left: 170px;\r
+               bottom: 0;\r
+       }\r
+               header#top nav li {\r
+                       float: left;\r
+                       position: relative;\r
+                       \r
+                       margin-right: 50px;\r
+               }\r
+                   header#top nav li.active:after {\r
+                       content: '';\r
+                       display: block;\r
+\r
+                       position: absolute;\r
+                       left: 50%;\r
+                       bottom: -20px;\r
+                       \r
+                       width: 0;\r
+                       height: 0;\r
+                       \r
+                       border-left: 8px solid transparent;\r
+                       border-right: 8px solid transparent;\r
+                       border-bottom: 8px solid #fff;\r
+                       \r
+                       margin-left: -8px;\r
+                   }\r
+               header#top nav li a {\r
+                       color: #888;\r
+                       \r
+                       font-weight: bold;\r
+                       font-size: 14px;\r
+                       \r
+                       text-decoration: none;\r
+                       \r
+                       display: block;\r
+               }\r
+                   header#top nav li a:hover {\r
+                       color: #444;\r
+                   }\r
+       header#top img#search {\r
+               cursor: pointer;\r
+               \r
+               position: absolute;\r
+               right: 0;\r
+               bottom: 0;\r
+       }\r
+       \r
+ul.items {\r
+    list-style: none;\r
+    \r
+    padding: 60px 0 80px;\r
+}\r
+    ul.items li {\r
+        clear: both;\r
+        overflow: hidden;\r
+        \r
+        padding-bottom: 20px;\r
+    }\r
+    ul.items li a {\r
+        display: block;\r
+        text-decoration: none;\r
+    }\r
+        ul.items li a time {\r
+            display: block;\r
+            float: left;\r
+            \r
+            color: #aaa;\r
+            font-size: 13px;\r
+            line-height: 34px;\r
+            \r
+            width: 130px;\r
+            padding-right: 40px;\r
+            text-align: right;\r
+        }\r
+            ul.items li a:hover time {\r
+                color: #7ac1df;\r
+            }\r
+        ul.items li a h2 {\r
+            font-size: 28px;\r
+            line-height: 30px;\r
+            \r
+            color: #555;\r
+            \r
+            display: block;\r
+            float: left;\r
+            \r
+            width: 730px;\r
+        }\r
+            ul.items li a:hover h2 {\r
+                color: #2082ab;\r
+            }\r
+            \r
+section.comments {\r
+    width: 900px;\r
+    margin: 0 auto 50px;\r
+    padding-top: 30px;\r
+    \r
+    text-align: left;\r
+    \r
+    border-top: 1px solid #eee;\r
+}\r
+    section.comments h1, section.comments form.commentform legend {\r
+        font-weight: bold;\r
+        font-size: 22px;\r
+        \r
+        color: #555;\r
+    }\r
+        section.comments h1 a {\r
+            float: right;\r
+            font-size: 15px;\r
+        }\r
+    section.comments ul {\r
+        list-style: none;\r
+        overflow: hidden;\r
+        \r
+        padding-left: 170px;\r
+        padding-bottom: 30px;\r
+    }\r
+        section.comments ul li {\r
+            float: left;\r
+            width: 670px;\r
+            \r
+            margin-bottom: 30px;\r
+            padding: 30px;\r
+            \r
+            background: #fafafa;\r
+        }\r
+        section.comments h2 {\r
+            color: #555;\r
+            font-size: 18px;\r
+            line-height: 30px;\r
+            \r
+            float: left;\r
+            width: 250px;\r
+        }\r
+        section.comments time {\r
+            float: right;\r
+            \r
+            font: italic 13px/30px Georgia, serif;\r
+        }\r
+        section.comments div.content {\r
+            clear: both;\r
+            width: auto;\r
+\r
+            margin: 0;\r
+            padding: 20px 0 0;\r
+            \r
+            font-size: 15px;\r
+            line-height: 25px;\r
+        }\r
+        \r
+    section.comments form.commentform {\r
+        clear: both;\r
+        padding-left: 170px;\r
+        padding-top: 40px;\r
+        \r
+        border-top: 1px solid #eee;\r
+    }\r
+        section.comments form.commentform p.notification {\r
+            clear: both;\r
+            float: none;\r
+            padding-bottom: 25px;\r
+            \r
+            font-weight: bold;            \r
+        }\r
+            section.comments form.commentform p.notification.error {\r
+                color: #c22a0a;\r
+            }\r
+        section.comments form.commentform legend {\r
+            margin-left: -170px;\r
+            margin-bottom: 20px;\r
+        }\r
+        section.comments form.commentform p {\r
+            float: left;\r
+            width: 365px;\r
+            \r
+            position: relative;\r
+        }\r
+            section.comments form.commentform p.email {\r
+                position: relative;\r
+                right: -15px;\r
+            }\r
+            section.comments form.commentform p.textarea {\r
+                width: 630px;\r
+            }\r
+            section.comments form.commentform p em {\r
+                font: italic 13px Georgia, serif;\r
+                \r
+                position: absolute;\r
+                top: 5px;\r
+                right: 15px;\r
+                \r
+                color: #aaa;\r
+            }\r
+        section.comments form.commentform label {\r
+            display: block;\r
+            font-size: 15px;\r
+            \r
+            padding-bottom: 8px;\r
+        }\r
+        section.comments form.commentform input, section.comments form.commentform textarea {\r
+            width: 320px;\r
+            padding: 8px 14px;\r
+            margin-bottom: 20px;\r
+            \r
+            border: 1px solid #bbb;\r
+        }\r
+            section.comments form.commentform textarea {\r
+                width: 700px;\r
+                min-height: 150px;\r
+                max-height: 400px;\r
+                resize: vertical;\r
+            }\r
+        section.comments form.commentform button {\r
+            margin-bottom: 50px;\r
+        }\r
+            \r
+section.footnote {\r
+    clear: both;\r
+    width: 730px;\r
+\r
+    font: italic 12px/19px Georgia, serif;\r
+    text-align: left;\r
+    color: #aaa;\r
+    \r
+    margin: 0 auto 60px;\r
+    padding-left: 170px;\r
+}\r
+            \r
+footer#bottom {\r
+    width: 130px;\r
+    height: 80px;\r
+    \r
+    border-top: 1px solid #f5f5f5;\r
+    padding-top: 20px;\r
+    \r
+    text-align: left;\r
+    position: relative;\r
+}\r
+    footer#bottom small {\r
+        width: 730px;\r
+        display: block;\r
+        float: left;\r
+        \r
+        font-size: 13px;\r
+        color: #999;\r
+    }\r
+        footer#bottom small a {\r
+            color: #666;\r
+        }\r
+        footer#bottom small a:hover {\r
+            color: #333;\r
+        }\r
+    footer#bottom ul {\r
+        clear: both;\r
+        list-style: none;\r
+        \r
+        position: relative;\r
+        top: -8px;\r
+        \r
+        width: 730px;\r
+    }\r
+        footer#bottom ul li {\r
+            display: inline-block;\r
+            float: left;\r
+        }\r
+        footer#bottom ul a {\r
+            color: #aaa;\r
+            font-size: 11px;\r
+            line-height: 11px;\r
+            \r
+            padding-right: 15px;\r
+        }\r
+            footer#bottom ul a:hover {\r
+                color: #777;\r
+            }\r
+    footer#bottom a#attribution {\r
+        display: block;\r
+        \r
+        position: absolute;\r
+        left: 876px;\r
+        top: 18px;\r
+        \r
+        width: 24px;\r
+        height: 22px;\r
+        \r
+        background: url('../img/attribution.gif');\r
+        text-indent: -999em;\r
+    \r
+        opacity: .5;\r
+        \r
+        -webkit-transition: opacity .25s;\r
+        -moz-transition: opacity .25s;\r
+        -ms-transition: opacity .25s;\r
+        -o-transition: opacity .25s;\r
+        transition: opacity .25s;\r
+    }\r
+        footer#bottom a#attribution:hover {\r
+            opacity: 1;\r
+        }\r
+    \r
+@media only screen and (max-width: 900px), only screen and (max-device-width: 480px) {\r
+\r
+    .wrap, .content {\r
+        width: 90%;\r
+        margin: 0 5%;\r
+        padding-left: 0;\r
+    }\r
+        .content h1 {\r
+            padding-top: 50px;\r
+        }\r
+    \r
+    form#search {\r
+        padding: 10px 5%;\r
+    }\r
+        form#search input {\r
+            width: 100%;\r
+        }\r
+\r
+    header#top {\r
+        overflow: hidden;\r
+        padding-top: 40px;\r
+    }\r
+        header#top a#logo {\r
+            width: 100%;\r
+            padding-bottom: 15px;\r
+        }\r
+        header#top nav {\r
+            position: static;\r
+        }\r
+            header#top nav li {\r
+                margin-right: 30px;\r
+            }\r
+        header#top img#search {\r
+            bottom: -20px;\r
+        }\r
+        \r
+    ul.items {\r
+        padding-bottom: 20px;\r
+    }\r
+        ul.items li a {\r
+            overflow: hidden;\r
+            padding-bottom: 20px;\r
+        }\r
+            ul.items li a time, ul.items li a h2 {\r
+                float: none;\r
+                clear: both;\r
+                \r
+                width: 100%;\r
+            }\r
+            ul.items li a time {\r
+                line-height: 22px;\r
+                text-align: left;\r
+            }\r
+            \r
+    section.comments {\r
+        margin-top: 40px;\r
+        width: auto;\r
+    }\r
+    section.comments h1 {\r
+        padding: 0 20px;\r
+        line-height: 20px;\r
+    }\r
+    section.comments ul {\r
+        padding: 0;\r
+    }\r
+        section.comments ul li {\r
+            width: 90%;\r
+            padding: 20px 5%;\r
+            margin-bottom: 0;\r
+            border-bottom: 1px solid #ddd;\r
+            \r
+            position: relative;\r
+        }\r
+            section.comments ul li:last-child {\r
+                border-bottom: none;\r
+            }\r
+            section.comments ul li time {\r
+                position: absolute;\r
+                right: 20px;\r
+                top: 20px;\r
+            }\r
+        section.comments div.content {\r
+            width: auto;\r
+            padding-top: 0;\r
+        }\r
+    section.comments form.commentform {\r
+        padding: 20px 20px;\r
+        position: relative;\r
+    }\r
+        section.comments form.commentform legend {\r
+            margin-left: 0;\r
+        }\r
+        section.comments form.commentform p, section.comments form.commentform p.textarea {\r
+            float: none;            \r
+            width: 100%;\r
+        }\r
+            section.comments form.commentform p.email {\r
+                right: 0;\r
+            }\r
+            \r
+        section.comments form.commentform input, section.comments form.commentform textarea {\r
+            width: 93%;\r
+        }\r
+            \r
+    section.footnote {\r
+        width: 90%;\r
+\r
+        margin: 30px 5%;\r
+        padding: 0;\r
+    }\r
+            \r
+    footer#bottom, footer#bottom small, footer#bottom ul {\r
+        width: 100%;\r
+    }\r
+        footer#bottom a#attribution {\r
+            left: auto;\r
+            right: 0;\r
+            \r
+            top: 30px;\r
+        }\r
+}
\ No newline at end of file
diff --git a/testcms-final-anon/themes/default/functions.php b/testcms-final-anon/themes/default/functions.php
new file mode 100644 (file)
index 0000000..a7da7d8
--- /dev/null
@@ -0,0 +1,59 @@
+<?php defined('IN_CMS') or die('No direct access allowed.');\r
+\r
+/**\r
+       Custom theme functions\r
+       \r
+       Note: we recommend you prefix all your functions to avoid any naming \r
+       collisions or wrap your functions with if function_exists braces.\r
+*/\r
+\r
+function numeral($number) {\r
+       $test = abs($number) % 10;\r
+       $ext = ((abs($number) % 100 < 21 and abs($number) % 100 > 4) ? 'th' : (($test < 4) ? ($test < 3) ? ($test < 2) ? ($test < 1) ? 'th' : 'st' : 'nd' : 'rd' : 'th'));\r
+       return $number . $ext; \r
+}\r
+\r
+function count_words($str) {\r
+       return count(preg_split('/\s+/', strip_tags($str), null, PREG_SPLIT_NO_EMPTY));\r
+}\r
+\r
+function pluralise($amount, $str, $alt = '') {\r
+       return intval($amount) === 1 ? $str : $str . ($alt !== '' ? $alt : 's');\r
+}\r
+\r
+function relative_time($date) {\r
+       $elapsed = time() - $date;\r
+       \r
+       if($elapsed <= 1) {\r
+               return 'Just now';\r
+       }\r
+       \r
+       $times = array(\r
+               31104000 => 'year',\r
+               2592000 => 'month',\r
+               604800 => 'week',\r
+               86400 => 'day',\r
+               3600 => 'hour',\r
+               60 => 'minute',\r
+               1 => 'second'\r
+       );\r
+       \r
+       foreach($times as $seconds => $title) {\r
+               $rounded = $elapsed / $seconds;\r
+               \r
+               if($rounded > 1) {\r
+                       $rounded = round($rounded);\r
+                       return $rounded . ' ' . pluralise($rounded, $title) . ' ago';\r
+               }\r
+       }\r
+}\r
+\r
+\r
+/**\r
+       Binding custom functions\r
+       This is just an example of what can be done\r
+\r
+       bind('about', function() {\r
+               return 'about page';\r
+       });\r
+*/
\ No newline at end of file
diff --git a/testcms-final-anon/themes/default/img/attribution.gif b/testcms-final-anon/themes/default/img/attribution.gif
new file mode 100644 (file)
index 0000000..1f876bf
Binary files /dev/null and b/testcms-final-anon/themes/default/img/attribution.gif differ
diff --git a/testcms-final-anon/themes/default/img/close.gif b/testcms-final-anon/themes/default/img/close.gif
new file mode 100644 (file)
index 0000000..8b3cc05
Binary files /dev/null and b/testcms-final-anon/themes/default/img/close.gif differ
diff --git a/testcms-final-anon/themes/default/img/search.gif b/testcms-final-anon/themes/default/img/search.gif
new file mode 100644 (file)
index 0000000..b4b7966
Binary files /dev/null and b/testcms-final-anon/themes/default/img/search.gif differ
diff --git a/testcms-final-anon/themes/default/includes/comment_form.php b/testcms-final-anon/themes/default/includes/comment_form.php
new file mode 100644 (file)
index 0000000..ac2ce18
--- /dev/null
@@ -0,0 +1,48 @@
+<?php if(comments_open()): ?>\r
+    <section class="comments">\r
+    \r
+        <h1><?php echo total_comments() . pluralise(total_comments(), ' comment'); ?> <a href="#comment" title="Contribute to the discussion!">Add your own</a></h1>\r
+    \r
+        <?php if(has_comments()): ?>\r
+        <ul class="commentlist">\r
+            <?php while(comments()): ?>\r
+            <li class="comment" id="comment-<?php echo comment_id(); ?>">\r
+                <h2><?php echo comment_name(); ?></h2>\r
+                <time><?php echo relative_time(comment_time()); ?></time> \r
+                \r
+                <div class="content">\r
+                    <?php echo comment_text(); ?>\r
+                </div>\r
+            </li>\r
+            <?php endwhile; ?>\r
+        </ul>\r
+        <?php endif; ?>\r
+        \r
+        <form id="comment" class="commentform" method="post" action="<?php echo current_url(); ?>#comment">\r
+            <legend>Add your comments</legend>\r
+            \r
+            <?php echo comment_form_notifications(); ?>\r
+            \r
+            <p class="name">\r
+                <label for="name">Your name:</label>\r
+                <?php echo comment_form_input_name(); ?>\r
+            </p>\r
+            \r
+            <p class="email">\r
+                <label for="email">Your email address:</label>\r
+                <em>Will never be published.</em>\r
+                <?php echo comment_form_input_email(); ?>                \r
+            </p>\r
+            \r
+            <p class="textarea">\r
+                <label for="text">Your comment:</label>\r
+                <?php echo comment_form_input_text(); ?>\r
+            </p>\r
+            \r
+            <p class="submit">\r
+                <?php echo comment_form_button(); ?>\r
+            </p>\r
+        </form>\r
+    \r
+    </section>\r
+<?php endif; ?>
\ No newline at end of file
diff --git a/testcms-final-anon/themes/default/includes/footer.php b/testcms-final-anon/themes/default/includes/footer.php
new file mode 100644 (file)
index 0000000..f7d30f2
--- /dev/null
@@ -0,0 +1,51 @@
+        <div class="wrap">\r
+            <footer id="bottom">\r
+                <small>&copy; <?php echo date('Y'); ?> <?php echo site_name(); ?>. All rights reserved.</small>\r
+                    \r
+                <ul role="navigation">\r
+                    <li><a href="<?php echo rss_url(); ?>">RSS</a></li>\r
+                    <?php if(twitter_account()): ?>\r
+                    <li><a href="<?php echo twitter_url(); ?>">@<?php echo twitter_account(); ?></a></li>\r
+                    <?php endif; ?>\r
+                    \r
+                    <li><a href="<?php echo admin_url(); ?>" title="Administer your site!">Admin area</a></li>\r
+                   \r
+                    <li><a href="/" title="Return to my website.">Home</a></li>\r
+\r
+                    <?php if(is_debug()): ?><a id="debug_toggle" href="#debug">Show database profile</a><?php endif; ?>\r
+                </ul>\r
+                \r
+            </footer>\r
+\r
+            <?php if(is_debug()): ?>\r
+            <?php echo db_profile(); ?>\r
+            <script>\r
+                (function() {\r
+                    var g = function(i) {\r
+                        var e = document.getElementById(i);\r
+                        e.s = function(p, v) {\r
+                            this.style[p] = v;\r
+                        };\r
+                        e.g = function(p) {\r
+                            return this.style[p];\r
+                        };\r
+\r
+                        return e;\r
+                    };\r
+\r
+                    var a = g('debug_toggle'), t = g('debug_table');\r
+\r
+                    var b = function(e) {\r
+                        var d = (t.g('display') == '' || t.g('display') == 'none') ? 'block' : 'none';\r
+                        t.s('display', d);\r
+                        e.preventDefault();\r
+                        e.stopPropagation();\r
+                    };\r
+\r
+                    a.addEventListener('click', b, false);\r
+                }());\r
+            </script>\r
+            <?php endif; ?>\r
+        </div>\r
+    </body>\r
+</html>\r
diff --git a/testcms-final-anon/themes/default/includes/header.php b/testcms-final-anon/themes/default/includes/header.php
new file mode 100644 (file)
index 0000000..f58087f
--- /dev/null
@@ -0,0 +1,57 @@
+<!doctype html>\r
+<html lang="en">\r
+       <head>\r
+               <meta charset="utf-8">\r
+               <title><?php echo page_title('Page can’t be found'); ?> - <?php echo site_name(); ?></title>\r
+\r
+               <meta name="description" content="<?php echo site_description(); ?>">\r
+\r
+               <link rel="stylesheet" href="<?php echo theme_url('/css/reset.css'); ?>">\r
+               <link rel="stylesheet" href="<?php echo theme_url('/css/style.css'); ?>">\r
+               \r
+               <link rel="alternate" type="application/rss+xml" title="RSS" href="<?php echo rss_url(); ?>">\r
+\r
+               <!--[if lt IE 9]>\r
+                       <script src="//html5shiv.googlecode.com/svn/trunk/html5.js"></script>\r
+               <![endif]-->\r
+\r
+               <script src="//code.jquery.com/jquery-latest.min.js"></script>\r
+               <script>var base = '<?php echo theme_url(); ?>';</script>\r
+               <script src="<?php echo theme_url('/js/main.js'); ?>"></script>\r
+               \r
+           <meta name="viewport" content="width=device-width">\r
+               \r
+               <?php if(customised()): ?>\r
+                   <!-- Custom CSS -->\r
+               <style><?php echo article_css(); ?></style>\r
+               \r
+               <!--  Custom Javascript -->\r
+               <script><?php echo article_js(); ?></script>\r
+               <?php endif; ?>\r
+       </head>\r
+       <body>\r
+       \r
+               <form id="search" action="<?php echo search_url(); ?>" method="post">\r
+                       <input type="search" name="term" placeholder="To search, type and hit enter&hellip;" value="<?php echo search_term(); ?>">\r
+               </form>\r
+       \r
+               <header id="top">\r
+                       <div class="wrap">\r
+                               \r
+                               <a id="logo" href="<?php echo base_url(); ?>"><?php echo site_name(); ?></a>\r
+       \r
+                               <?php if(has_menu_items()): ?>\r
+                               <nav id="main" role="navigation">\r
+                                       <ul>\r
+                                               <?php while(menu_items()): ?>\r
+                                               <li <?php echo (menu_active() ? 'class="active"' : ''); ?>>\r
+                                                       <a href="<?php echo menu_url(); ?>" title="<?php echo menu_title(); ?>">\r
+                                                               <?php echo menu_name(); ?>\r
+                                                       </a>\r
+                                               </li>\r
+                                               <?php endwhile; ?>\r
+                                       </ul>\r
+                               </nav>\r
+                               <?php endif; ?>\r
+                       </div>\r
+               </header>\r
diff --git a/testcms-final-anon/themes/default/js/main.js b/testcms-final-anon/themes/default/js/main.js
new file mode 100644 (file)
index 0000000..190ee8e
--- /dev/null
@@ -0,0 +1,52 @@
+$(function() {\r
+\r
+       var viewport = $(window),\r
+               body = $('body'),\r
+               \r
+               header = $('#top div.wrap'),\r
+               search = $('#search');\r
+               \r
+       //  Give a CSS hook\r
+       body.addClass('js');\r
+       \r
+       //  A neat little \r
+       if(window.location.pathname === '/') {\r
+           body.css({position: 'relative', top: -50, opacity: 0})\r
+               .animate({ top: 0, opacity: 1 });\r
+       }\r
+               \r
+       /**\r
+               Search box\r
+       */\r
+               \r
+       //  Hide the search\r
+       search.css('margin-top', -(search.outerHeight() - 4));\r
+       \r
+       //  Append some way of making it come back\r
+       var clicked = 1,\r
+               marginTop = search.css('margin-top');\r
+       \r
+       header.append('<img src="' + base + 'img/search.gif" id="search">').children('#search').click(function() {\r
+               \r
+               //  Move the \r
+               search.animate({marginTop: clicked % 2 === 0 ? marginTop : 0});\r
+               \r
+               if(clicked % 2 === 0) {\r
+                       $(this).animate({opacity: 0}, 200, function() {\r
+                               $(this).attr('src', base + 'img/search.gif').animate({opacity: 1}, 200);\r
+                       });\r
+                       \r
+                       search.animate({marginTop: marginTop});\r
+               } else {\r
+               \r
+                       $(this).animate({opacity: 0}, 200, function() {\r
+                               $(this).attr('src', base + 'img/close.gif').animate({opacity: 1}, 200);\r
+                       });\r
+               \r
+                       search.animate({marginTop: 0});\r
+               }\r
+               \r
+               //  Increment counter\r
+               clicked++;\r
+       });\r
+});
\ No newline at end of file
diff --git a/testcms-final-anon/themes/default/page.php b/testcms-final-anon/themes/default/page.php
new file mode 100644 (file)
index 0000000..256ffae
--- /dev/null
@@ -0,0 +1,12 @@
+\r
+<section class="content">\r
+       <h1><?php echo page_title(); ?></h1>\r
+\r
+       <?php echo page_content(); ?>\r
+       \r
+       <!--\r
+               If you want to add custom functionality per-page, you can do so by using the bind() function, which is stored in the functions.php of your theme.\r
+               Then, if you want to echo out your custom function, you just add a recieve() function. Here's an example: "<?php echo recieve(); ?>".\r
+        -->\r
+</section>\r
+\r
diff --git a/testcms-final-anon/themes/default/posts.php b/testcms-final-anon/themes/default/posts.php
new file mode 100644 (file)
index 0000000..d2bb6b2
--- /dev/null
@@ -0,0 +1,21 @@
+<section class="content">\r
+\r
+       <?php if(has_posts()): ?>\r
+               <ul class="items wrap">\r
+                       <?php while(posts()): ?>\r
+                       <li>\r
+                               <a href="<?php echo article_url(); ?>" title="<?php echo article_title(); ?>">\r
+                                       <time datetime="<?php echo date(DATE_W3C, article_time()); ?>"><?php echo relative_time(article_time()); ?></time>\r
+                                       <h2><?php echo article_title(); ?></h2>\r
+                               </a>\r
+                       </li>\r
+                       <?php endwhile; ?>\r
+               </ul>\r
+\r
+               <p><?php echo posts_prev(); ?> <?php echo posts_next(); ?></p>\r
+\r
+       <?php else: ?>\r
+               <p>Looks like you have some writing to do!</p>\r
+       <?php endif; ?>\r
+\r
+</section>
\ No newline at end of file
diff --git a/testcms-final-anon/themes/default/search.php b/testcms-final-anon/themes/default/search.php
new file mode 100644 (file)
index 0000000..313d333
--- /dev/null
@@ -0,0 +1,25 @@
+<section class="content">\r
+    \r
+    <h1>You searched for &ldquo;<?php echo search_term(); ?>&rdquo;.</h1>\r
+    \r
+    <?php if(has_search_results()): ?>\r
+        <p>We found <?php echo total_search_results(); ?> <?php echo pluralise(total_search_results(), 'result'); ?> for &ldquo;<?php echo search_term(); ?>&rdquo;</p>\r
+        <ul class="items wrap">\r
+                       <?php while(search_results()): ?>\r
+                       <li>\r
+                               <a href="<?php echo article_url(); ?>" title="<?php echo article_title(); ?>">\r
+                                   <time datetime="<?php echo date(DATE_W3C, article_time()); ?>"><?php echo relative_time(article_time()); ?></time>\r
+                                   <h2><?php echo article_title(); ?></h2>\r
+                               </a>\r
+                       </li>\r
+                       <?php endwhile; ?>\r
+        </ul>\r
+\r
+        <p><?php echo search_prev(); ?> <?php echo search_next(); ?></p>\r
+\r
+    <?php else: ?>\r
+        <p>Unfortunately, there's no results for &ldquo;<?php echo search_term(); ?>&rdquo;. Did you spell everything correctly?</p>\r
+    <?php endif; ?>\r
+    \r
+</section>\r
+\r
diff --git a/testcms-final-anon/upgrade/assets/css/app.css b/testcms-final-anon/upgrade/assets/css/app.css
new file mode 100644 (file)
index 0000000..da354e8
--- /dev/null
@@ -0,0 +1,171 @@
+body {\r
+    background: #f4f8fa;\r
+    \r
+    font: 13px/22px "Helvetica Neue", sans-serif;\r
+    color: #6c7f85;\r
+    text-shadow: 0 1px 0 #fff;\r
+    \r
+    width: 720px;\r
+    margin: 50px auto 40px;\r
+}\r
+\r
+h1 {\r
+    text-align: center;\r
+    margin-bottom: 60px;\r
+}\r
+\r
+h2 {\r
+    font-size: 32px;\r
+    font-weight: 300;\r
+    color: #57829e;\r
+}\r
+\r
+a {\r
+       color: #57829e;\r
+}\r
+\r
+.content {\r
+    padding: 20px 40px;\r
+    \r
+    background: #fff;\r
+    box-shadow: 0 1px 1px #c8d3da, inset 0 -2px 1px #f6f9fb;\r
+    border-radius: 4px;\r
+}\r
+\r
+small {\r
+    font-size: 11px;\r
+    line-height: 18px;\r
+    \r
+    display: block;\r
+    padding: 8px 12px;\r
+    \r
+    background: #ffe;\r
+    color: #775;\r
+    border: 1px solid #eed;\r
+    border-radius: 3px;\r
+}\r
+\r
+p.error, p.success {\r
+       color: #fff;\r
+       text-shadow: 0 1px 1px rgba(0,0,0,.3);\r
+       text-align: center;\r
+       padding: 10px;\r
+\r
+       border-radius: 3px;\r
+}\r
+\r
+p.error {\r
+       background: #900;\r
+}\r
+    \r
+p.success {\r
+       background: #757e0e;\r
+}\r
+    \r
+    \r
+form {\r
+    overflow: hidden;\r
+    width: 720px;\r
+}\r
+\r
+fieldset {\r
+    border: 1px solid #d5e4eb;\r
+    border-radius: 3px;\r
+    \r
+    margin: 30px 36px 30px 0;\r
+    padding: 5px 25px;\r
+    \r
+    float: left;\r
+    overflow: hidden;\r
+    position: relative;\r
+    \r
+    width: 250px;\r
+}\r
+    legend {\r
+        font-weight: bold;\r
+    }\r
+    \r
+    label {\r
+        display: block;\r
+        font-size: 12px;\r
+        font-weight: bold;\r
+        cursor: pointer;\r
+    }\r
+    \r
+    input, textarea {\r
+        font: 13px "Helvetica Neue", sans-serif;\r
+        padding: 5px 8px;\r
+        width: 230px;\r
+    }\r
+        textarea {\r
+            min-height: 70px;\r
+            max-height: 250px;\r
+            resize: vertical;\r
+        }\r
+    select {\r
+        width: 245px;\r
+        padding: 4px 8px;\r
+    }\r
+    \r
+button, .button {\r
+    font: bold 13px "Helvetica Neue", sans-serif;\r
+    color: #fff;\r
+    text-shadow: 0 1px 1px rgba(0,0,0,.3);\r
+    text-decoration: none;\r
+    \r
+    display: block;\r
+    width: auto;\r
+    float: right;\r
+    cursor: pointer;\r
+    \r
+    margin-bottom: 20px;\r
+    padding: 6px 9px;\r
+    \r
+    border: 1px solid #2f4a57;\r
+    border-radius: 3px;\r
+    \r
+    background-color: #587786;\r
+    background-image: -webkit-gradient(linear, left top, left bottom, from(#6c8894), to(#486472));\r
+    background-image: -webkit-linear-gradient(top, #6c8894, #486472);\r
+    background-image: -moz-linear-gradient(top, #6c8894, #486472);\r
+    background-image: -o-linear-gradient(top, #6c8894, #486472);\r
+    background-image: -ms-linear-gradient(top, #6c8894, #486472);\r
+    background-image: linear-gradient(top, #6c8894, #486472);\r
+    filter: progid:DXImageTransform.Microsoft.gradient(GradientType=0,StartColorStr='#6c8894', EndColorStr='#486472');\r
+    \r
+    box-shadow: inset 0 1px 0 rgba(255,255,255,.15), 0 1px 1px rgba(0,0,0,.05);\r
+}\r
+\r
+    form > button, form > p {\r
+        margin-right: 75px;\r
+    }\r
+\r
+    button:hover, .button:hover {\r
+        opacity: .9;\r
+    }\r
+    button:active, .button:active {\r
+        opacity: 1;\r
+        \r
+        background-color: #3a5968;\r
+        background-image: -webkit-gradient(linear, left top, left bottom, from(#365361), to(#587684));\r
+        background-image: -webkit-linear-gradient(top, #365361, #587684);\r
+        background-image: -moz-linear-gradient(top, #365361, #587684);\r
+        background-image: -o-linear-gradient(top, #365361, #587684);\r
+        background-image: -ms-linear-gradient(top, #365361, #587684);\r
+        background-image: linear-gradient(top, #365361, #587684);\r
+        filter: progid:DXImageTransform.Microsoft.gradient(GradientType=0,StartColorStr='#365361', EndColorStr='#587684');\r
+        \r
+        box-shadow: inset 0 1px 1px rgba(0,0,0,.15), 0 -1px 1px rgba(0,0,0,.1);\r
+        \r
+        border-color: #192e39;\r
+    }\r
+    \r
+p.footer {\r
+    font-size: 12px;\r
+    text-align: center;\r
+    \r
+    padding-top: 40px;\r
+}\r
+    p.footer a {\r
+        color: #587684;\r
+    }\r
diff --git a/testcms-final-anon/upgrade/assets/img/logo.gif b/testcms-final-anon/upgrade/assets/img/logo.gif
new file mode 100644 (file)
index 0000000..1f876bf
Binary files /dev/null and b/testcms-final-anon/upgrade/assets/img/logo.gif differ
diff --git a/testcms-final-anon/upgrade/classes/migrations.php b/testcms-final-anon/upgrade/classes/migrations.php
new file mode 100644 (file)
index 0000000..fc5d9f7
--- /dev/null
@@ -0,0 +1,23 @@
+<?php\r
+\r
+class Migrations {\r
+\r
+       private $queries = array();\r
+       \r
+       /*\r
+               Database changes\r
+       */\r
+       public function query($sql) {\r
+               $this->queries[] = $sql;\r
+       }\r
+\r
+       /*\r
+               Execute\r
+       */\r
+       public function apply() {\r
+               foreach($this->queries as $sql) {\r
+                       Db::query($sql);\r
+               }\r
+       }\r
+\r
+}
\ No newline at end of file
diff --git a/testcms-final-anon/upgrade/classes/schema.php b/testcms-final-anon/upgrade/classes/schema.php
new file mode 100644 (file)
index 0000000..41edc39
--- /dev/null
@@ -0,0 +1,16 @@
+<?php\r
+\r
+class Schema {\r
+       \r
+       public static function has($table, $column = '', $value = '') {\r
+               if($value) {\r
+                       $sql = "select * from `" . $table . "` where `" . $column . "` = '" . $value . "'";\r
+               } elseif($column) {\r
+                       $sql = "show columns from `" . $table . "` like '" . $column . "'";\r
+               } else {\r
+                       $sql = "show tables like `" . $table . "`";\r
+               }\r
+               return Db::query($sql)->rowCount() > 0;\r
+       }\r
+\r
+}
\ No newline at end of file
diff --git a/testcms-final-anon/upgrade/complete.php b/testcms-final-anon/upgrade/complete.php
new file mode 100644 (file)
index 0000000..0510748
--- /dev/null
@@ -0,0 +1,22 @@
+<!doctype html>\r
+<html lang="en-gb">\r
+    <head>\r
+        <meta charset="utf-8">\r
+        <title>Upgrade Test CMS</title>\r
+        <mate name="robots" content="noindex, nofollow">\r
+        <link rel="stylesheet" href="assets/css/app.css">\r
+    </head>\r
+    <body>\r
+    \r
+       <h1><img src="assets/img/logo.gif" alt="Test CMS install logo"></h1>\r
+       \r
+       <div class="content">\r
+               <h2>Upgrade Complete.</h2>\r
+               \r
+               <p>Enjoy.</p>\r
+               \r
+               <p><a href="../" class="button" style="float: none; display: inline-block;">Continue to your site</a></p>\r
+       </div>\r
+\r
+    </body>\r
+</html>\r
diff --git a/testcms-final-anon/upgrade/index.php b/testcms-final-anon/upgrade/index.php
new file mode 100644 (file)
index 0000000..7289c11
--- /dev/null
@@ -0,0 +1,62 @@
+<!doctype html>\r
+<html lang="en-gb">\r
+    <head>\r
+        <meta charset="utf-8">\r
+        <title>Upgrade Test CMS</title>\r
+        <mate name="robots" content="noindex, nofollow">\r
+        <link rel="stylesheet" href="assets/css/app.css">\r
+    </head>\r
+    <body>\r
+    \r
+       <h1><img src="assets/img/logo.gif" alt="Test CMS install logo"></h1>\r
+       \r
+       <?php\r
+       \r
+       $errors = array();\r
+       \r
+       if(file_exists('../config.php') === false) {\r
+               $errors[] = 'Please run the install';\r
+       } else {\r
+                       // note: on win the only way to really test is to try and write a new file to disk.\r
+                       if(@file_put_contents('../test.php', '<?php //test') === false) {\r
+                               $errors[] = 'It looks like the root directory is not writable, Please make the root directory writable until the upgrade is complete.';\r
+                       } else {\r
+                               unlink('../test.php');\r
+                       }\r
+       }\r
+       \r
+       ?>\r
+\r
+       <?php if(count($errors)): ?>\r
+       \r
+       <div class="content">\r
+               <h2>Woops.</h2>\r
+               \r
+               <p>Looks like we've hit a problem.</p>\r
+               \r
+               <ul>\r
+                       <?php foreach($errors as $error): ?>\r
+                       <li><?php echo $error; ?></li>\r
+                       <?php endforeach; ?>\r
+               </ul>\r
+               \r
+               <p><a href="index.php" class="button" style="float: none; display: inline-block;">Ok ive fixed these, start migration</a></p>\r
+       </div>\r
+       \r
+       <?php else: ?>\r
+\r
+        <div class="content">\r
+            <h2>Upgrading Test CMS.</h2>\r
+\r
+                       <p>Thank you for downloading the latest version of Test CMS. \r
+                       To get you up and running we need to make a few changes to bring you up to date.</p>\r
+\r
+            <form action="run.php" method="post">\r
+                <button type="submit">Start migration</button>\r
+            </form>\r
+        </div>\r
+        \r
+        <?php endif; ?>\r
+\r
+    </body>\r
+</html>\r
diff --git a/testcms-final-anon/upgrade/migrations.php b/testcms-final-anon/upgrade/migrations.php
new file mode 100644 (file)
index 0000000..69d92e7
--- /dev/null
@@ -0,0 +1,97 @@
+<?php\r
+\r
+/*\r
+       0.4 --> 0.5\r
+*/\r
+$migration = new Migrations;\r
+\r
+if(Schema::has('users', 'email') === false) {\r
+       $sql = "alter table `users` add `email` varchar( 140 ) not null after `password`";\r
+       $migration->query($sql);\r
+}\r
+\r
+if(Schema::has('posts', 'comments') === false) {\r
+       $sql = "alter table `posts` add `comments` tinyint( 1 ) not null";\r
+       $migration->query($sql);\r
+}\r
+\r
+if(Schema::has('posts', 'custom_fields') === false) {\r
+       $sql = "alter table `posts` add `custom_fields` text not null after `js`";\r
+       $migration->query($sql);\r
+}\r
+\r
+$sql = "create table if not exists `comments` (\r
+       `id` int(6) not null auto_increment,\r
+       `post` int(6) not null,\r
+       `status` enum('pending','published','spam') not null,\r
+       `date` int(11) not null,\r
+       `name` varchar(140) not null,\r
+       `email` varchar(140) not null,\r
+       `text` text not null,\r
+       primary key (`id`),\r
+       key `post` (`post`),\r
+       key `status` (`status`)\r
+) engine=myisam charset=utf8 collate=utf8_general_ci";\r
+$migration->query($sql);\r
+\r
+// rename show_posts\r
+$sql = "update `meta` set `value` = 'posts_page' where `value` = 'show_posts'";\r
+$migration->query($sql);\r
+\r
+// make posts_page the home page\r
+if(Schema::has('meta', 'key', 'home_page') === false) {\r
+       $posts_page = Db::query("select `value` from meta where `key` = 'show_posts'")->fetchColumn();\r
+\r
+       $sql = "insert into `meta` (`key`, `value`) values ('home_page', '" . $posts_page . "')";\r
+       $migration->query($sql);\r
+}\r
+\r
+// [BUGFIX] make sure the password field is big enough\r
+$sql = "alter table `users` change `password` `password` text character set utf8 COLLATE utf8_general_ci not null";\r
+$migration->query($sql);\r
+\r
+// apply changes\r
+$migration->apply();\r
+\r
+// update config\r
+Config::set('application.admin_folder', 'admin');\r
+Config::set('application.key', random(32));\r
+\r
+/*\r
+       0.5 --> 0.6\r
+*/\r
+$migration = new Migrations;\r
+\r
+$sql = "create table if not exists `sessions` (\r
+       `id` char( 32 ) not null ,\r
+       `date` datetime not null ,\r
+       `ip` varchar( 15 ) not null ,\r
+       `ua` varchar( 140 ) not null ,\r
+       `data` text not null\r
+) engine=innodb charset=utf8 collate=utf8_general_ci;";\r
+$migration->query($sql);\r
+\r
+// comments auto published option\r
+if(Schema::has('meta', 'key', 'auto_published_comments') === false) {\r
+       $sql = "insert into `meta` (`key`, `value`) values ('auto_published_comments', '0')";\r
+       $migration->query($sql);\r
+}\r
+\r
+// pagination\r
+if(Schema::has('meta', 'key', 'posts_per_page') === false) {\r
+       $sql = "insert into `meta` (`key`, `value`) values ('posts_per_page', '10')";\r
+       $migration->query($sql);\r
+}\r
+\r
+// apply changes\r
+$migration->apply();\r
+\r
+// update config\r
+Config::set('session.name', 'testcms');\r
+Config::set('session.expire', 3600);\r
+Config::set('session.path', '/');\r
+Config::set('session.domain', '');\r
+\r
+Config::set('error.ignore', array(E_NOTICE, E_USER_NOTICE, E_DEPRECATED, E_USER_DEPRECATED));\r
+Config::set('error.detail', true);\r
+Config::set('error.log', false);\r
diff --git a/testcms-final-anon/upgrade/run.php b/testcms-final-anon/upgrade/run.php
new file mode 100644 (file)
index 0000000..d4b2e54
--- /dev/null
@@ -0,0 +1,81 @@
+<?php\r
+\r
+// report all errors\r
+error_reporting(E_ALL);\r
+\r
+// show all error uncaught\r
+ini_set('display_errors', true);\r
+\r
+/*\r
+       Define some paths and get current config\r
+*/\r
+define('IN_CMS', true);\r
+define('PATH', pathinfo(dirname(__FILE__), PATHINFO_DIRNAME) . '/');\r
+\r
+/*\r
+       Helper functions\r
+*/\r
+function random($length = 16) {\r
+       $pool = str_split('0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ', 1);\r
+       $value = '';\r
+\r
+       for ($i = 0; $i < $length; $i++)  {\r
+               $value .= $pool[mt_rand(0, 61)];\r
+       }\r
+\r
+       return $value;\r
+}\r
+\r
+/*\r
+       Include some files.\r
+*/\r
+require PATH . 'system/classes/autoload.php';\r
+require PATH . 'system/classes/helpers.php';\r
+\r
+// map classes\r
+Autoloader::map(array(\r
+       'Schema' => PATH . 'upgrade/classes/schema.php',\r
+       'Migrations' => PATH . 'upgrade/classes/migrations.php'\r
+));\r
+\r
+// tell the autoloader where to find classes\r
+Autoloader::directory(array(\r
+       PATH . 'system/classes/'\r
+));\r
+\r
+// register the auto loader\r
+Autoloader::register();\r
+\r
+/**\r
+       Report all errors let our error class decide which to display\r
+*/\r
+error_reporting(-1);\r
+\r
+/**\r
+       Error display will be handled by our error class\r
+*/\r
+ini_safe_set('display_errors', false);\r
+\r
+// Register the default timezone for the application.\r
+date_default_timezone_set(Config::get('application.timezone'));\r
+\r
+// Register the PHP exception handler.\r
+set_exception_handler(array('Error', 'exception'));\r
+\r
+// Register the PHP error handler.\r
+set_error_handler(array('Error', 'native'));\r
+\r
+// Register the shutdown handler.\r
+register_shutdown_function(array('Error', 'shutdown'));\r
+\r
+// load current config file\r
+Config::load(PATH . 'config.php');\r
+\r
+// add and apply migrations\r
+require PATH . 'upgrade/migrations.php';\r
+\r
+// write any config changes\r
+Config::write(PATH . 'config.php', Config::get());\r
+\r
+// redirect\r
+header('Location: complete.php');
\ No newline at end of file
diff --git a/todo.txt b/todo.txt
new file mode 100644 (file)
index 0000000..b1a840f
--- /dev/null
+++ b/todo.txt
@@ -0,0 +1,10 @@
+V2.  Authentication
+V3.  Session Management
+V4.  Access Control
+V5.  Input Validation
+V6.  Output Encoding/Escaping
+V7.  Cryptography at rest
+V8.  Error Handling & logging
+V9.  Data Protection
+V11. HTTP Security
+V16. Files and Recourses