Index: smf/Themes/default/index.template.php
===================================================================
--- smf/Themes/default/index.template.php	(revision 1164)
+++ smf/Themes/default/index.template.php	(working copy)
@@ -29,7 +29,7 @@
 	http://www.simplemachines.org/
 */
 
-require_once(IA_ROOT_DIR.'www/views/sitewide.php');
+require_once(IA_ROOT_DIR . 'www/xhp/ia/sitewide.php');
 
 // Initialize the template... mainly little settings.
 function template_init()
@@ -209,7 +209,7 @@ function template_main_above()
 </div>
 
 <?php*/
-	ia_template_header();
+	echo <ia:header user={identity_get_user()} />;
 
 	// Show the menu here, according to the menu sub template.
 	template_menu();
@@ -255,7 +255,7 @@ function template_main_below()
 		<span class="smalltext">', $txt['smf301'], $context['load_time'], $txt['smf302'], $context['load_queries'], $txt['smf302b'], '</span>';
 
 	// throw in infoarena footer
-	ia_template_footer();
+	echo <ia:footer />;
 
 	// This is an interesting bug in Internet Explorer AND Safari. Rather annoying, it makes overflows just not tall enough.
 	if (($context['browser']['is_ie'] && !$context['browser']['is_ie4']) || $context['browser']['is_mac_ie'] || $context['browser']['is_safari'] || $context['browser']['is_firefox'])
@@ -388,7 +388,10 @@ function template_menu() {
 	$smf_admin = $context['allow_admin'];
 
 	// display menu
-	ia_template_topnav($current_action, $smf_admin);
+	echo <ia:top-navbar
+		user={identity_get_user()} selected={$current_action}
+		user_pm_count={identity_is_anonymous() ? null :
+		               smf_get_pm_count(identity_get_username())} />;
 	if ($context['user']['is_logged']) {
 		echo '<div style="float: right; padding: 3pt">',
 			 '<a href="', $scripturl, '?action=search', '"><strong>Cauta in forum</strong></a> | ',
Index: www/format/format.php
===================================================================
--- www/format/format.php	(revision 1164)
+++ www/format/format.php	(working copy)
@@ -104,6 +104,13 @@ function format_post_link($url, $content, $post_data = array(), $escape = true,
 // FIXME: Improve this logic.
 function format_highlight_access_key($string, $key) {
     if (($pos = stripos($string, $key)) !== false) {
+        require_once(IA_ROOT_DIR . 'www/xhp/base/init.php');
+        return
+            <x:frag>
+                {substr($string, 0, $pos)}
+                <span class="access-key">{$string[$pos]}</span>
+                {substr($string, $pos + 1)}
+            </x:frag>;
         return substr_replace($string,
                 '<span class="access-key">'.$string[$pos].'</span>', $pos, 1);
     } else {
Index: www/static/css/screen.css
===================================================================
--- www/static/css/screen.css	(revision 1164)
+++ www/static/css/screen.css	(working copy)
@@ -158,7 +158,7 @@ The basic layout of the homepage is as follows:
 #main {
     /*float:right;*/
     background: #fff url(../images/main_tile.jpg) repeat-x top;
-    padding: 15px;
+    padding: 8px 16px;
     margin-left: 191px;
     border-left: 1px solid #d0d0d0;
 }
@@ -452,19 +452,17 @@ The basic layout of the homepage is as follows:
 }
 
 /* Breadcrumbs */
-#breadcrumbs {
-    font-size:11px;
-    line-height:2;
-    margin: 0;
-    margin-top: -10px;
+.breadcrumbs {
+    font-size: 11px;
+    line-height: 2;
     border-bottom: 1px solid #f0f0f0;
 }
 
-#breadcrumbs a {
+.breadcrumbs a {
     font-style: italic;
 }
 
-#breadcrumbs .separator {
+.breadcrumbs .separator {
     color: silver;
 }
 
@@ -1266,7 +1264,6 @@ td.rating, th.rating {
     margin-left: 1.2em;
     text-align: left;
     color:#6A6A6B;
-
 }
 
 /* task enumeration */
Index: www/static/js/default.js
===================================================================
--- www/static/js/default.js	(revision 1164)
+++ www/static/js/default.js	(working copy)
@@ -5,10 +5,10 @@
 
 function Page_Init() {
     // fade away flash message
-    var flash = $('flash');
-    if (flash && !hasElementClass(flash, 'flashError')) {
+    var flash = $$('.flash');
+    if (flash[0] && !hasElementClass(flash[0], 'flashError')) {
         var callback = function() {
-            hideElement(flash);
+            hideElement(flash[0]);
         }
         setTimeout(callback, 13000);
     }
Index: www/utilities.php
===================================================================
--- www/utilities.php	(revision 1164)
+++ www/utilities.php	(working copy)
@@ -1,6 +1,17 @@
 <?php
 
-require_once(IA_ROOT_DIR."www/url.php");
+require_once(IA_ROOT_DIR . 'www/url.php');
+
+require_once(IA_ROOT_DIR . 'www/xhp/base/init.php');
+require_once(IA_ROOT_DIR . 'www/xhp/ia/base.php');
+require_once(IA_ROOT_DIR . 'www/xhp/ia/sitewide.php');
+require_once(IA_ROOT_DIR . 'www/xhp/ia/sidebar.php');
+require_once(IA_ROOT_DIR . 'www/xhp/ia/calendar.php');
+require_once(IA_ROOT_DIR . 'www/xhp/ia/google_search.php');
+require_once(IA_ROOT_DIR . 'www/xhp/ia/user_count.php');
+require_once(IA_ROOT_DIR . 'www/xhp/ia/server_time.php');
+require_once(IA_ROOT_DIR . 'www/xhp/ui/breadcrumbs.php');
+require_once(IA_ROOT_DIR . 'www/xhp/ui/flash_message.php');
 
 // Wrapper around htmlentities which defaults charset to UTF-8
 function html_escape($string, $quote_style = ENT_COMPAT, $charset = "UTF-8")
@@ -22,7 +33,7 @@ function xml_escape($string, $quote_style = ENT_COMPAT, $charset = "UTF-8")
         '&#226;','&#227;','&#228;','&#229;','&#230;','&#231;','&#232;','&#233;',
         '&#234;','&#235;','&#236;','&#237;','&#238;','&#239;','&#240;','&#241;',
         '&#242;','&#243;','&#244;','&#245;','&#246;','&#247;','&#248;','&#249;',
-        '&#250;','&#251;','&#252;','&#253;','&#254;','&#255;', '&#8221;', 
+        '&#250;','&#251;','&#252;','&#253;','&#254;','&#255;', '&#8221;',
         '&#8222;',
     );
     $html = array('&quot;','&amp;','&amp;','&lt;','&gt;','&nbsp;','&iexcl;',
@@ -152,7 +163,7 @@ function http_serve($disk_file_name, $http_file_name, $mime_type = null, $cache_
         }
     }
 
-    // HTTP headers.  
+    // HTTP headers.
     header("Content-Type: {$mime_type}");
     header("Content-Disposition: {$disposition}; filename="
            .urlencode($http_file_name).";");
@@ -193,61 +204,156 @@ function flash_error($message) {
     flash($message, 'flashError');
 }
 
-// Execute a view. Variables in $view are placed in the
-// local namespace as variables. This is the preffered
-// way of calling a template, because globals are not
-// easily accessible.
-function execute_view($view_file_name, $view) {
-    global $identity_user;
-
-    // retrieve recent page history
-    // some pages display it as navigation breadcrumbs
+/**
+ * Composes a XHP object that provides the page frame, containing the default
+ * header, footer, navigation bars, breadcrumbs and flash messages. The object
+ * expects a <ia:content> child containg the main page content to be appended
+ * before rendering.
+ *
+ * @param   string  $title
+ * @param   string  $top_navbar_selected
+ * @param   bool    $hide_sidebar_login_form
+ * @param   string  $charset
+ * @return  :ia:page
+ */
+function default_view_compose($title = null,
+                              $top_navbar_selected = "infoarena",
+                              $hide_sidebar_login_form = false,
+                              $charset = "UTF-8") {
+    // Retrieve recent page history to display as navigation breadcrumbs
     $recent_pages = getattr($_SESSION, '_ia_recent_pages', array());
 
-    // update recent page history
-    $query = url_from_args($_GET);
-    if (!preg_match('/\/(json|plot|changes)\//', $query) && !request_is_post()) {
-        $hashkey = strtolower($query);
-        $recent_pages[$hashkey] = array($query, getattr($view, 'title', $query)); 
+    // Update recent page history
+    $current_page = url_from_args($_GET);
+    if (!request_is_post() &&
+        !preg_match('/\/(json|plot|changes)\//', $current_page)) {
+        $current_page_key = strtolower($current_page);
+        $recent_pages[$current_page_key] =
+            array($current_page, is_null($title) ? $current_page : $title);
         if (5 < count($recent_pages)) {
             array_shift($recent_pages);
         }
         $_SESSION['_ia_recent_pages'] = $recent_pages;
+    } else {
+        $current_page_key = null;
     }
 
-    // let view access recent_pages
-    $view['current_url_key'] = strtolower($query);
-    $view['recent_pages'] = $recent_pages;
+    // Display flash message if it exists.
+    if (isset($_SESSION['_ia_flash'])) {
+        $flash_message =
+          <ui:flash-message class={getattr($_SESSION, '_ia_flash_class')}>
+            {$_SESSION['_ia_flash']}
+          </ui:flash-message>;
+
+        // Clear flash message.
+        unset($_SESSION['_ia_flash']);
+        if (isset($_SESSION['_ia_flash_class'])) {
+            unset($_SESSION['_ia_flash_class']);
+        }
+    } else {
+        $flash_message = <x:frag />;
+    }
 
-    // give access to request statistics
-    if (IA_DEVELOPMENT_MODE) {
-        global $execution_stats;
-        $view['execution_stats'] = $execution_stats;
+    // Add google custom search bar only if not in development mode
+    if (!IA_DEVELOPMENT_MODE) {
+        $google_search = <ia:google-search />;
+    } else {
+        $google_search = <x:frag />;
+    }
+    // Show the login form in the sidebar only if user is not authenticated.
+    // Get the user's unread personal message count if he is.
+    if (identity_is_anonymous()) {
+        $sidebar_login =
+          <ia:sidebar-login
+            show_login_form={!$hide_sidebar_login_form}/>;
+        $user = null;
+        $user_pm_count = null;
+    } else {
+        $sidebar_login = <x:frag />;
+        $user = identity_get_user();
+        $user_pm_count = smf_get_pm_count(identity_get_username());
     }
 
-    // expand $view members into global scope
-    $GLOBALS['view'] = $view;
+    // Compose and return the page.
+    return
+      <ia:page title={$title} user={$user} charset={$charset}>
+        <ia:header />
+        <ia:top-navbar selected={$top_navbar_selected}
+          user_pm_count={$user_pm_count} />
+
+        <ia:left-col>
+          <ia:left-navbar />
+          {$google_search}
+          <ia:calendar />
+          {$sidebar_login}
+          <ia:user-count />
+          <ia:server-time />
+          <ia:sidebar-ad />
+        </ia:left-col>
+
+        <ui:breadcrumbs entries={$recent_pages} current={$current_page_key} />
+        {$flash_message}
+
+        <ia:footer />
+      </ia:page>;
+}
 
+/*
+ * DEPRECATED: Please use XHP based views.
+ *
+ * Execute as view. Variables in $view are placed in the local namespace as
+ * variables. This is the preffered way of calling a template, because globals
+ * are not easily accessible.
+ *
+ * @param   string  $view_file_name
+ * @param   array   $view
+ */
+function execute_view($view_file_name, $view) {
+    $_xhp_page = default_view_compose(
+        getattr($view, 'title'),
+        getattr($view, 'topnav_select', 'infoarena'),
+        getattr($view, 'no_sidebar_login', false),
+        getattr($view, 'charset', 'UTF-8'));
+
+    require_once(IA_ROOT_DIR . 'www/views/utilities.php');
+    // Expand $view members into global scope
+    $GLOBALS['view'] = $view;
     foreach ($view as $view_hash_key => $view_hash_value) {
         if ($view_hash_key == 'view_hash_key') continue;
         if ($view_hash_key == 'view_hash_value') continue;
         if ($view_hash_key == 'view_file_name') continue;
         if ($view_hash_key == 'view') continue;
-        //echo "added $view_hash_key = $view_hash_value into globals";
         $GLOBALS[$view_hash_key] = $view_hash_value;
         $$view_hash_key = $view_hash_value;
     }
 
-    // NOTE: no includes here, unless you want to get
-    // warnings about function redeclaration.
+    ob_start();
     include($view_file_name);
+    $rendered = ob_get_clean();
+
+    $_xhp_page->appendChild(
+      <ia:content>
+        {HTML($rendered)}
+      </ia:content>);
+    echo $_xhp_page;
 }
 
-// Execute view and then die.
+/*
+ * DEPRECATED: Please use XHP based views.
+ *
+ * Executes view and then dies.
+ */
 function execute_view_die($view_file_name, $view) {
     execute_view($view_file_name, $view);
     if (IA_DEVELOPMENT_MODE) {
+        // Development mode: display current page's log in site footer
+        global $execution_stats;
         log_execution_stats();
+        $buffer = $execution_stats['log_copy'];
+        echo
+          <textarea id="log" rows="50" cols="80">
+            {$buffer}
+          </textarea>;
     }
     session_write_close();
     die();
Index: www/views/footer.php
===================================================================
--- www/views/footer.php	(revision 1164)
+++ www/views/footer.php	(working copy)
@@ -1,12 +1 @@
 <?php
-require_once(IA_ROOT_DIR.'www/views/sitewide.php');
-?>
-</div>
-</div>
-</div>
-
-<?php ia_template_footer(); ?>
-
-</body>
-</html>
-
Index: www/views/form_login.php
deleted file mode 100644
===================================================================
--- www/views/form_login.php	(revision 1164)
+++ /dev/null	(working copy)
@@ -1,26 +0,0 @@
-<form action="<?= html_escape(url_login()) ?>" method="post" class="login">
-<fieldset>
-    <legend><img src="<?= html_escape(url_static('images/icons/login.png')) ?>" alt="!" /> Autentificare</legend>
-    <ul class="form">
-<?= view_form_field_li(array(
-        'name' => 'Cont de utilizator',
-        'type' => 'string',
-        'access_key' => 'c',
-), 'username') ?>
-<?= view_form_field_li(array(
-        'name' => 'Parola',
-        'type' => 'string',
-        'is_password' => true,
-        'access_key' => 'p',
-), 'password') ?>
-        <li>
-            <input type="checkbox" value="on" id="form_remember" name="remember" class="checkbox"<?= fval('remember') ? ' checked="checked"' : '' ?>/>
-            <label class="checkbox" for="form_remember">Pastreaza-ma autentificat 5 zile</label>
-        </li>
-        <li>
-            <input type="submit" value="Autentificare" id="form_submit" class="button important" />
-        </li>
-    </ul>
-</fieldset>
-</form>
-
Index: www/views/google_search.php
deleted file mode 100644
===================================================================
--- www/views/google_search.php	(revision 1164)
+++ /dev/null	(working copy)
@@ -1,12 +0,0 @@
-<!-- Google CSE Search Box Begins -->
-  <form id="searchbox_010130381492294265836:kw-fmmvpxco" action="http://infoarena.ro/search">
-  <fieldset>
-  <legend><img src="<?= html_escape(url_static('images/icons/search.png')) ?>" alt="!" /> Cautare</legend>
-    <input type="hidden" name="cx" value="010130381492294265836:kw-fmmvpxco" />
-    <input type="hidden" name="cof" value="FORID:9" />
-    <input name="q" type="text" size="22" />
-    <input type="submit" name="sa" value="Cauta" class="button important"/>
-  </fieldset>
-  </form>
-  <script type="text/javascript" src="http://www.google.com/coop/cse/brand?form=searchbox_010130381492294265836%3Akw-fmmvpxco"></script>
-<!-- Google CSE Search Box Ends -->
Index: www/views/header.php
===================================================================
--- www/views/header.php	(revision 1164)
+++ www/views/header.php	(working copy)
@@ -1,188 +1 @@
 <?php
-
-require_once(IA_ROOT_DIR.'www/views/sitewide.php');
-require_once(IA_ROOT_DIR.'www/views/utilities.php');
-require_once(IA_ROOT_DIR.'www/macros/macro_calendar.php');
-
-// Basic view checks.
-log_assert(is_array($view));
-log_assert(is_string($view['title']));
-
-// Check forms.
-if (isset($form_errors) || isset($form_values)) {
-    log_assert(is_array($view['form_errors']));
-    log_assert(is_array($view['form_values']));
-    foreach ($form_values as $k => $v) {
-        if (html_escape($k) != $k) {
-            log_error("Form field $k contains special html chars.");
-        }
-    }
-}
-
-header("Content-type: text/html; charset=utf-8");
-?>
-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
-<html xmlns="http://www.w3.org/1999/xhtml">
-<head>
-    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
-<?php
-    // Hack to insert meta description and keywords for home page.
-    // Description should get us a better snippet for keywords that hit our
-    // home page. If this proves to be effective we should find a way to
-    // include meta descriptions for the most visited pages (can we do it with
-    // a macro?).
-    if (getattr($view, 'page_name') == "home") {
-?>
-    <meta name="Description" content="Concursuri de programare, Stiri si articole de informatica, Comunitate online. Arhiva de probleme, Evaluare 24/24, Forum, Resurse educationale, Pregatire pentru olimpiada." />
-    <meta name="keywords" content="Cocursuri, Informatica, Programare, Comunitate, Algoritmi, Articole, Evaluare, Pregatire" />
-    <meta name="verify-v1" content="j9UCDYvsDL2pLtkJDDkE4HnHVmXakgvz30vOyIJ+6cI=" />
-    <meta name="verify-v1" content="ac36ilLp6y4xp71sJgZEjFMgow6YCLkyQLrG/b2iT/Q=" />
-    <meta name="verify-v1" content="PQDTb5Advw297iADXVUYuxh0z+iQKfq1wtYWnfHCb1Y=" />
-    <meta name="verify-v1" content="GUKPcDm0TzwAR7r5xbagq576p/YWH9su/Ca4o8YlYBg=" /> <!--bogdan2412-->
-    <meta name="google-site-verification" content="T_HFYNIO3S70696yFC5rkbPn339gjnfVwMqYPmU866I" /> <!--devilkind-->
-<?php
-    }
-?>
-    <title><?= html_escape(getattr($view, 'title')) ?></title>
-
-    <link type="text/css" rel="stylesheet" href="<?= html_escape(url_static('css/sitewide.css')) ?>"/>
-    <link type="text/css" rel="stylesheet" href="<?= html_escape(url_static('css/iconize.css')) ?>"/>
-    <link type="text/css" rel="stylesheet" href="<?= html_escape(url_static('css/screen.css')) ?>"/>
-    <link type="text/css" rel="stylesheet" href="<?= html_escape(url_static('css/tabber.css')) ?>"/>
-    <link type="text/css" rel="stylesheet" href="<?= html_escape(url_static('css/sh/shCore.css')) ?>"/>
-    <link type="text/css" rel="stylesheet" href="<?= html_escape(url_static('css/sh/shThemeDefault.css')) ?>"/>
-    <link type="text/css" rel="stylesheet" href="<?= html_escape(url_static('css/print.css')) ?>" media="print" />
-    <link rel="icon" href="<?= IA_URL."favicon.ico" ?>" type="image/vnd.microsoft.icon" />
-    <script type="text/javascript" src="<?= html_escape(url_static('js/config.js.php')) ?>"></script>
-    <script type="text/javascript" src="<?= html_escape(url_static('js/MochiKit.js')) ?>"></script>
-    <script type="text/javascript" src="<?= html_escape(url_static('js/default.js')) ?>"></script>
-    <script type="text/javascript" src="<?= html_escape(url_static('js/tabber-minimized.js')) ?>"></script>
-    <script type="text/javascript" src="<?= html_escape(url_static('js/submit.js')) ?>"></script>
-    <script type="text/javascript" src="<?= html_escape(url_static('js/remotebox.js')) ?>"></script>
-    <script type="text/javascript" src="<?= html_escape(url_static('js/postdata.js')) ?>"></script>
-    <script type="text/javascript" src="<?= html_escape(url_static('js/sh/shCore.js')) ?>"></script>
-    <script type="text/javascript" src="<?= html_escape(url_static('js/sh/shBrushCpp.js')) ?>"></script>
-    <script type="text/javascript" src="<?= html_escape(url_static('js/sh/shBrushDelphi.js')) ?>"></script>
-    <script type="text/javascript" src="<?= html_escape(url_static('js/sh/shBrushJava.js')) ?>"></script>
-    <script type="text/javascript" src="<?= html_escape(url_static('js/sh/shBrushPython.js')) ?>"></script>
-    <script type="text/javascript" src="<?= html_escape(url_static('js/sh/shInit.js')) ?>"></script>
-    <script type="text/javascript" src="<?= html_escape(url_static('js/tags.js')) ?>"></script>
-    <script type="text/javascript" src="<?= html_escape(url_static('js/roundtimer.js')) ?>"></script>
-    <script type="text/javascript" src="<?= html_escape(url_static('js/restoreparity.js')) ?>"></script>
-    <script type="text/javascript" src="<?= html_escape(url_static('js/foreach.js')) ?>"></script>
-    <script type="text/javascript" src="<?= html_escape(url_static('js/sorttable.js')) ?>"></script>
-    <script type="text/javascript" src="<?= html_escape(url_static('js/tablednd.js')) ?>"></script>
-
-    <script type="text/javascript">Sh_Init("<?= html_escape(url_static('swf/clipboard.swf')) ?>")</script>
-
-<?php
-    if (request("action") == 'rating') {
-?>
-    <script type="text/javascript" src="<?= html_escape(url_static('js/swfobject.js')) ?>"></script>
-<?php
-    }
-?>
-
-    <?= getattr($view, 'head') ?>
-</head>
-<body id="infoarena" <?= getattr($view, 'body_onload') ? ' onload="' . html_escape(getattr($view, 'body_onload')) . '"' : '' ?>>
-<div id="page">
-
-<?php
-if (!isset($topnav_select)) {
-    $topnav_select = 'infoarena';
-}
-ia_template_header();
-$smf_admin = ('admin' == getattr($identity_user, 'security_level'));
-ia_template_topnav($topnav_select, $smf_admin);
-?>
-
-<div id="content_small" class="clear">
-<div id="sidebar">
-    <ul id="nav" class="clear">
-        <li><a href="<?= html_escape(url_home()) ?>">Home</a></li>
-        <li><?= format_link_access(url_textblock('arhiva'), "Arhiva de probleme", 'a') ?></li>
-        <li><a href="<?= html_escape(url_textblock('arhiva-educationala')) ?>">Arhiva educatională</a></li>
-        <li><a href="<?= html_escape(url_textblock('concursuri')) ?>">Concursuri</a></li>
-        <li><a href="<?= html_escape(url_textblock('concursuri-virtuale')) ?>">Concursuri virtuale</a></li> 
-        <li><a href="<?= html_escape(url_textblock('clasament-rating')) ?>">Clasament</a></li>
-        <li><a href="<?= html_escape(url_textblock('articole')) ?>">Articole</a></li>
-        <li><a href="<?= html_escape(url_textblock('downloads')) ?>">Downloads</a></li>
-        <li><a href="<?= html_escape(url_textblock('links')) ?>">Links</a></li>
-        <li><a href="<?= html_escape(url_textblock('documentatie')) ?>">Documentaţie</a></li>
-        <li><a href="<?= html_escape(url_textblock('despre-infoarena')) ?>">Despre infoarena</a></li>
-        <li class="separator"><hr/></li>
-        <li><?= format_link_access(url_monitor(array('user' => identity_get_username())), "Monitorul de evaluare", 'm') ?></li>
-        <?php if (!identity_is_anonymous()) { ?>
-        <li><a href="<?= html_escape(url_submit()) ?>"><strong>Trimite soluţii</strong></a></li>
-        <li><?= format_link_access(url_account(), "Contul meu", 'c') ?></li>
-        <?php } ?>
-        </ul>
-
-    <?php if (!IA_DEVELOPMENT_MODE) { ?>
-    <div id="google-search">
-        <?php include(IA_ROOT_DIR.'www/views/google_search.php'); ?>
-    </div>
-    <?php } ?>
-
-    <div id="calendar">
-        <?= macro_calendar(array()) ?>
-    </div>
-
-    <?php if (identity_is_anonymous()) { ?>
-    <div id="login">
-        <?php if (!isset($no_sidebar_login)) include(IA_ROOT_DIR.'www/views/form_login.php') ?>
-        <p>
-        <?= format_link(url_register(), "Ma inregistrez!" ) ?><br/>
-        <?= format_link(url_resetpass(), "Mi-am uitat parola..." ) ?>
-        </p>
-    </div>
-    <?php } ?>
-    <p class="user-count"><?php echo user_count(); ?> membri inregistrati</p>
-    <div id="srv_time" class="user-count" align="center"></div>
-    <script type="text/javascript" src="<?= html_escape(url_static('js/time.js')) ?>"></script>
-    <script type="text/javascript">loadTime(<?= format_date(null, "%H, %M, %S");?>);</script>
-
-    <?php include(IA_ROOT_DIR.'www/views/sidebar_ad.php'); ?>
-</div>
-
-<div id="main">
-<?php
-
-// breadcrumbs with recent pages
-if (isset($recent_pages) && (1 < count($recent_pages))) {
-    $bstring = '';
-    foreach ($recent_pages as $rec_key => $rec_entry) {
-        list($rec_url, $rec_title) = $rec_entry;
-
-        $rec_title = html_escape($rec_title);
-
-        if ($bstring) {
-            $bstring .= ' <span class="separator">|</span> ';
-        }
-        if ($current_url_key == $rec_key) {
-            $bstring .= "<strong>{$rec_title}</strong>";
-        }
-        else {
-            $bstring .= "<a href=\"" . html_escape($rec_url) . "\">{$rec_title}</a>";
-        }
-    }
-    echo '<p id="breadcrumbs">Pagini recente &raquo; ' . $bstring . '</p>';
-}
-
-?>
-
-<?php
-    // display flash message
-    if (isset($_SESSION['_ia_flash'])) { ?>
-
-<div id="flash" class="flash <?= html_escape(getattr($_SESSION, '_ia_flash_class')) ?>"><?= html_escape($_SESSION['_ia_flash']) ?></div>
-
-<?php
-        // clear flash message
-        unset($_SESSION['_ia_flash']);
-        if (isset($_SESSION['_ia_flash_class'])) {
-            unset($_SESSION['_ia_flash_class']);
-        }
-    }
-?>
Index: www/views/login.php
===================================================================
--- www/views/login.php	(revision 1164)
+++ www/views/login.php	(working copy)
@@ -6,7 +6,7 @@
 <?= format_link(url_register(), "inregistra aici") ?>;
 daca ti-ai uitat parola, o poti <a href="<?= html_escape(url_resetpass()) ?>">reseta aici</a>.</p>
 
-<?php include(IA_ROOT_DIR.'www/views/form_login.php'); ?>
+<?php echo <ia:login_form />; ?>
 
 <?php wiki_include('template/login'); ?>
 
Index: www/views/projector.php
===================================================================
--- www/views/projector.php	(revision 1164)
+++ www/views/projector.php	(working copy)
@@ -1,6 +1,5 @@
 <?php
 
-require_once(IA_ROOT_DIR.'www/views/sitewide.php');
 require_once(IA_ROOT_DIR.'www/format/table.php');
 require_once(IA_ROOT_DIR.'www/format/format.php');
 require_once(IA_ROOT_DIR.'www/format/list.php');
Index: www/views/sidebar_ad.php
deleted file mode 100644
===================================================================
--- www/views/sidebar_ad.php	(revision 1164)
+++ /dev/null	(working copy)
@@ -1,10 +0,0 @@
-<div class="ad">
-<?php
-$sidebar = textblock_get_revision(IA_SIDEBAR_PAGE);
-if ($sidebar) {
-    echo '<div class="wiki_text_block">';
-    echo wiki_process_textblock($sidebar);
-    echo '</div>';
-}
-?>
-</div>
Index: www/views/sitewide.php
deleted file mode 100644
===================================================================
--- www/views/sitewide.php	(revision 1164)
+++ /dev/null	(working copy)
@@ -1,167 +0,0 @@
-<?php
-
-require_once(IA_ROOT_DIR."www/format/format.php");
-
-// site-wide templates (templates shared with SMF / search)
-//
-// This file may be included from different environments
-// (currently SMF and infoarena website) so it can use only
-// limited application logic.
-
-// display site header
-function ia_template_header() {
-    global $identity_user;
-?>
-<div id="header" class="clear">
-    <?php if (!identity_is_anonymous()) { $username = $identity_user['username']; ?>
-        <div id="userbox">
-        <?= format_link(url_user_profile($username, true), format_user_avatar($username, "normal", true), false) ?>
-            <div class="user">
-                <strong><?= html_escape($identity_user['full_name']) ?></strong><br/>
-                <?= format_user_ratingbadge($username, $identity_user['rating_cache']) ?>
-                <?= format_link_access(url_user_profile($username, true), $username, 'p') ?><br/>
-                <?= format_post_link(url_logout(), "logout", array(), true, array('class' => 'logout')) ?> |
-                <?= format_link_access(url_account(), 'contul meu', 'c') ?>
-            </div>
-        </div>
-    <?php } ?>
-    <?php if (IA_DEVELOPMENT_MODE) { ?>
-        <div id="dev_warning">
-            Bravely working in development mode&hellip;<br/>Keep it up!
-        </div>
-    <?php } ?>
-
-    <h1><?= format_link(url_home(), "infoarena informatica de performanta") ?></h1>
-</div>
-<?php
-}
-
-// display main navigation bar
-function ia_template_topnav($selected = 'infoarena', $smf_admin = false) {
-    global $identity_user;
-
-    $pre = array($selected => '<strong>');
-    $post = array($selected => '</strong>');
-?>
-<div id="topnav">
-<ul>
-    <li>
-        <?= getattr($pre, 'infoarena') ?>
-        <?= format_link(url_home(), 'info<em>arena</em>', false) ?>
-        <?= getattr($post, 'infoarena') ?>
-    </li>
-    <li>
-        <?= getattr($pre, 'blog') ?>
-        <?= format_link_access(url_blog(), "blog", 'b') ?>
-        <?= getattr($post, 'blog') ?>
-    </li>
-    <li>
-        <?= getattr($pre, 'forum') ?>
-        <?= format_link_access(url_forum(), "forum", 'f') ?>
-        <?= getattr($post, 'forum') ?>
-    </li>
-    <li>
-        <?= getattr($pre, 'calendar') ?>
-        <?= format_link(url_forum() . "?action=calendar", "calendar") ?>
-        <?= getattr($post, 'calendar') ?>
-    </li>
-<?php if (identity_is_anonymous()) { ?>
-    <li>
-        <?= getattr($pre, 'login')?>
-        <?= format_link(url_login(), "autentificare") ?>
-        <?= getattr($post, 'login') ?>
-    </li>
-    <li>
-        <?= getattr($pre, 'register')?>
-        <?= format_link(url_register(), "inregistrare") ?>
-        <?= getattr($post, 'register') ?>
-    </li>
-<?php } else { ?>
-    <li>
-        <?= getattr($pre, 'profile') ?>
-        <?= format_link_access(url_user_profile($identity_user['username']), 'profilul meu', 'p') ?>
-        <?= getattr($post, 'profile') ?></li>
-    <li>
-        <?= getattr($pre, 'pm') ?>
-	<?php
-        $new_pm_count = smf_get_pm_count($identity_user['username']);
-        if ($new_pm_count) { ?>
-            <?= format_link(url_forum() . "?action=pm", "<b>mesaje (".$new_pm_count.")</b>", false) ?>
-	<?php } else { ?>
-            <?= format_link(url_forum() . "?action=pm", "mesaje") ?>
-	<?php } ?>
-        <?= getattr($post, 'pm') ?>
-    </li>
-<?php if ($smf_admin) { ?>
-    <li>
-        <?= getattr($pre, 'smf_admin') ?>
-        <?= format_link(url_forum() . "?action=admin", "forum admin") ?>
-        <?= getattr($post, 'smf_admin') ?>
-    </li>
-<?php } ?>
-<?php } ?>
-</ul>
-</div>
-
-<?php
-}
-
-function ia_template_footer() {
-?>
-<div id="footer">
-    <ul class="clear">
-        <li class="copyright">&copy;&nbsp;2004-<?= date("Y") ?>&nbsp;<?= format_link(url_textblock('Asociatia-infoarena'), "Asociatia infoarena") ?></li>
-        <li class="separate"><?= format_link(url_home(), "Prima pagina") ?></li>
-        <li><?= format_link(url_textblock("despre-infoarena"), "Despre infoarena") ?></li>
-        <li><?= format_link(url_textblock("termeni-si-conditii"), "Termeni si conditii") ?></li>
-        <li><?= format_link(url_textblock("contact"), "Contact") ?></li>
-        <li class="top"><a href="#header">Sari la inceputul paginii &uarr;</a></li>
-    </ul>
-<?php if (!IA_DEVELOPMENT_MODE) { ?>
-    <p class="cc">
-    <!--Creative Commons License-->
-    <a class="badge" rel="license" href="http://creativecommons.org/licenses/by-nc/2.5/"><img alt="Creative Commons License" src="<?= url_static('images/CreativeCommonsBadge.png') ?>"/></a>
-    Cu exceptia cazurilor in care se specifica altfel, continutul site-ului infoarena<br/>este publicat sub licenta <a rel="license" href="http://creativecommons.org/licenses/by-nc/2.5/">Creative Commons Attribution-NonCommercial 2.5</a>.
-    <!--/Creative Commons License-->
-    <rdf:RDF xmlns="http://web.resource.org/cc/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:rdfs="http://www.w3.org/2000/01/rdf-schema#">
-        <Work rdf:about="">
-            <license rdf:resource="http://creativecommons.org/licenses/by-nc/2.5/" />
-        </Work>
-        <License rdf:about="http://creativecommons.org/licenses/by-nc/2.5/">
-            <permits rdf:resource="http://web.resource.org/cc/Reproduction"/>
-            <permits rdf:resource="http://web.resource.org/cc/Distribution"/>
-            <requires rdf:resource="http://web.resource.org/cc/Notice"/>
-            <requires rdf:resource="http://web.resource.org/cc/Attribution"/>
-            <prohibits rdf:resource="http://web.resource.org/cc/CommercialUse"/>
-            <permits rdf:resource="http://web.resource.org/cc/DerivativeWorks"/>
-        </License>
-    </rdf:RDF>
-    </p>
-<?php
-    }
-    else {
-        // Development mode: display current page's log in site footer
-        global $execution_stats;
-        log_execution_stats();
-        $buffer = $execution_stats['log_copy'];
-        echo '<textarea id="log" rows="50" cols="80">';
-        echo html_escape($buffer);
-        echo '</textarea>';
-    }
-?>
-</div>
-
-<?php if (!IA_DEVELOPMENT_MODE) { ?>
-    <script src="http://www.google-analytics.com/urchin.js" type="text/javascript">
-    </script>
-    <script type="text/javascript">
-    _uacct = "UA-113289-8";
-    _udn = "infoarena.ro";
-    urchinTracker();
-    </script>
-<?php } ?>
-
-<?php
-}
-
-?>
Index: www/xhp/base/core.php
new file mode 100644
===================================================================
--- www/xhp/base/core.php	(revision 0)
+++ www/xhp/base/core.php	(working copy)
@@ -0,0 +1,767 @@
+<?php
+/*
+  +----------------------------------------------------------------------+
+  | XHP                                                                  |
+  +----------------------------------------------------------------------+
+  | Copyright (c) 2009 - 2010 Facebook, Inc. (http://www.facebook.com)          |
+  +----------------------------------------------------------------------+
+  | This source file is subject to version 3.01 of the PHP license,      |
+  | that is bundled with this package in the file LICENSE.PHP, and is    |
+  | available through the world-wide-web at the following url:           |
+  | http://www.php.net/license/3_01.txt                                  |
+  | If you did not receive a copy of the PHP license and are unable to   |
+  | obtain it through the world-wide-web, please send a note to          |
+  | license@php.net so we can mail you a copy immediately.               |
+  +----------------------------------------------------------------------+
+*/
+
+abstract class :x:base {
+  abstract public function __construct();
+  abstract public function appendChild($child);
+  abstract public function getAttribute($attr);
+  abstract public function setAttribute($attr, $val);
+  abstract public function categoryOf($cat);
+  abstract public function __toString();
+  abstract protected static function &__xhpAttributeDeclaration();
+  abstract protected function &__xhpCategoryDeclaration();
+  abstract protected function &__xhpChildrenDeclaration();
+
+  /**
+   * Enabling validation will give you stricter documents; you won't be able to
+   * do many things that violate the XHTML 1.0 Strict spec. It is recommend that
+   * you leave this on because otherwise things like the `children` keyword will
+   * do nothing. This validation comes at some CPU cost, however, so if you are
+   * running a high-traffic site you will probably want to disable this in
+   * production. You should still leave it on while developing new features,
+   * though.
+   */
+  public static $ENABLE_VALIDATION = true;
+
+  final protected static function renderChild($child) {
+    if ($child instanceof :x:base) {
+      return $child->__toString();
+    } else if ($child instanceof HTML) {
+      return $child->render();
+    } else if (is_array($child)) {
+      throw new XHPRenderArrayException('Can not render array!');
+    } else {
+      return htmlspecialchars((string)$child);
+    }
+  }
+
+  public static function element2class($element) {
+    return 'xhp_'.str_replace(array(':', '-'), array('__', '_'), $element);
+  }
+
+  public static function class2element($class) {
+    return str_replace(array('__', '_'), array(':', '-'), preg_replace('#^xhp_#i', '', $class));
+  }
+}
+
+abstract class :x:composable-element extends :x:base {
+  private
+    $attributes,
+    $children;
+
+  // Private constants indicating the declared types of attributes
+  const TYPE_STRING = 1;
+  const TYPE_BOOL   = 2;
+  const TYPE_NUMBER = 3;
+  const TYPE_ARRAY  = 4;
+  const TYPE_OBJECT = 5;
+  const TYPE_VAR    = 6;
+  const TYPE_ENUM   = 7;
+  const TYPE_FLOAT  = 8;
+
+  protected function init() {}
+
+  /**
+   * A new :x:composable-element is instantiated for every literal tag
+   * expression in the script.
+   *
+   * The following code:
+   * $foo = <foo attr="val">bar</foo>;
+   *
+   * will execute something like:
+   * $foo = new xhp_foo(array('attr' => 'val'), array('bar'));
+   *
+   * @param $attributes    map of attributes to values
+   * @param $children      list of children
+   */
+  final public function __construct($attributes, $children) {
+    if ($attributes) {
+      foreach ($attributes as $key => &$val) {
+        $this->validateAttributeValue($key, $val);
+      }
+      unset($val);
+    }
+    $this->attributes = $attributes;
+    $this->children = array();
+    foreach ($children as $child) {
+      $this->appendChild($child);
+    }
+    if (:x:base::$ENABLE_VALIDATION) {
+      // There is some cost to having defaulted unused arguments on a function
+      // so we leave these out and get them with func_get_args().
+      $args = func_get_args();
+      if (isset($args[2])) {
+        $this->source = "$args[2]:$args[3]";
+      } else {
+        $this->source =
+          'You have ENABLE_VALIDATION on, but debug information is not being ' .
+          'passed to XHP objects correctly. Ensure xhp.include_debug is on ' .
+          'in your PHP configuration. Without this option enabled, ' .
+          'validation errors will be painful to debug at best.';
+      }
+    }
+    $this->init();
+  }
+
+  /**
+   * Adds a child to the end of this node. If you give an array to this method
+   * then it will behave like a DocumentFragment.
+   *
+   * @param $child     single child or array of children
+   */
+  final public function appendChild($child) {
+    if (is_array($child)) {
+      foreach ($child as $c) {
+        $this->appendChild($c);
+      }
+    } else if ($child instanceof :x:frag) {
+      $this->children = array_merge($this->children, $child->children);
+    } else if ($child !== null) {
+      $this->children[] = $child;
+    }
+    return $this;
+  }
+
+  /**
+   * Fetches all direct children of this element that match a particular tag
+   * name (or all children if no tag is given)
+   *
+   * @param $tag_name   tag name (optional)
+   * @return array
+   */
+   final protected function getChildren($tag_name = null) {
+     if (!$tag_name) {
+       return $this->children;
+     }
+
+     $tag_name = :x:base::element2class($tag_name);
+     $ret = array();
+     foreach ($this->children as $child) {
+       if ($child instanceof $tag_name) {
+         $ret[] = $child;
+       }
+     }
+     return $ret;
+   }
+
+  /**
+   * Fetches an attribute from this elements attribute store. If $attr is not
+   * defined in the store, and $default is null an exception will be thrown. An
+   * exception will also be thrown if $attr is not supported -- see
+   * `supportedAttributes`
+   *
+   * @param $attr      attribute to fetch
+   * @return           value
+   */
+  final public function getAttribute($attr) {
+
+    // Return attribute if it's there, otherwise default or exception.
+    if (isset($this->attributes[$attr])) {
+      return $this->attributes[$attr];
+    }
+
+    // Get the declaration on miss
+    $decl = $this->__xhpAttributeDeclaration();
+
+    if (!isset($decl[$attr])) {
+      throw new XHPAttributeNotSupportedException($this, $attr);
+    } else if (!empty($decl[$attr][3])) {
+      throw new XHPAttributeRequiredException($this, $attr);
+    } else {
+      $decl = $this->__xhpAttributeDeclaration();
+      return $decl[$attr][2];
+    }
+  }
+
+  final protected function getAttributes() {
+    return $this->attributes;
+  }
+
+  /**
+   * Sets an attribute in this element's attribute store. An exception will be
+   * thrown if $attr is not supported -- see `supportedAttributes`.
+   *
+   * @param $attr      attribute to set
+   * @param $val       value
+   */
+  final public function setAttribute($attr, $val) {
+    $this->validateAttributeValue($attr, $val);
+    $this->attributes[$attr] = $val;
+    return $this;
+  }
+
+  final protected function __flushElementChildren() {
+
+    // Flush all :x:base elements to x:primitive's
+    $ln = count($this->children);
+    for ($ii = 0; $ii < $ln; ++$ii) {
+      $child = $this->children[$ii];
+      if ($child instanceof :x:element) {
+        do {
+          if (:x:base::$ENABLE_VALIDATION) {
+            $child->validateChildren();
+          }
+          $child = $child->render();
+        } while ($child instanceof :x:element);
+
+        if (!($child instanceof :x:primitive)) {
+          throw new XHPCoreRenderException($this->children[$ii], $child);
+        }
+
+        if ($child instanceof :x:frag) {
+          array_splice($this->children, $ii, 1, $child->children);
+          $ln = count($this->children);
+          --$ii;
+        } else {
+          $this->children[$ii] = $child;
+        }
+      }
+    }
+  }
+
+  /**
+   * Defined in elements by the `attribute` keyword. The declaration is simple.
+   * There is a keyed array, with each key being an attribute. Each value is
+   * an array with 4 elements. The first is the attribute type. The second is
+   * meta-data about the attribute. The third is a default value (null for
+   * none). And the fourth is whether or not this value is required.
+   *
+   * Attribute types are suggested by the TYPE_* constants.
+   */
+  protected static function &__xhpAttributeDeclaration() {
+    static $_ = array();
+    return $_;
+  }
+
+  /**
+   * Defined in elements by the `category` keyword. This is just a list of all
+   * categories an element belongs to. Each category is a key with value 1.
+   */
+  protected function &__xhpCategoryDeclaration() {
+    static $_ = array();
+    return $_;
+  }
+
+  /**
+   * Defined in elements by the `children` keyword. This returns a pattern of
+   * allowed children. The return value is potentially very complicated. The
+   * two simplest are 0 and 1 which mean no children and any children,
+   * respectively. Otherwise you're dealing with an array which is just the
+   * biggest mess you've ever seen.
+   */
+  protected function &__xhpChildrenDeclaration() {
+    static $_ = 1;
+    return $_;
+  }
+
+  /**
+   * Throws an exception if $val is not a valid value for the attribute $attr
+   * on this element.
+   */
+  final protected function validateAttributeValue($attr, &$val) {
+    $decl = $this->__xhpAttributeDeclaration();
+    if (!isset($decl[$attr])) {
+      throw new XHPAttributeNotSupportedException($this, $attr);
+    }
+    if ($val === null) {
+      return;
+    }
+    switch ($decl[$attr][0]) {
+      case self::TYPE_STRING:
+        $val = (string)$val;
+        return;
+
+      case self::TYPE_BOOL:
+        if (!is_bool($val)) {
+          if ($val === "false") {
+            $val = false;
+          } else {
+            $val = (bool)$val;
+          }
+        }
+        return;
+
+      case self::TYPE_NUMBER:
+        if (!is_int($val)) {
+          $val = (int)$val;
+        }
+        return;
+
+      case self::TYPE_FLOAT:
+        if (!is_numeric($val)) {
+          $val = (float)$val;
+        }
+        return;
+
+      case self::TYPE_ARRAY:
+        if (!is_array($val)) {
+          throw new XHPInvalidAttributeException($this, 'array', $attr, $val);
+        }
+        return;
+
+      case self::TYPE_OBJECT:
+        if (!($val instanceof $decl[$attr][1])) {
+          throw new XHPInvalidAttributeException(
+            $this, $decl[$attr][1], $attr, $val
+          );
+        }
+        return;
+
+      // case self::TYPE_VAR: `var` (any type)
+
+      case self::TYPE_ENUM:
+        foreach ($decl[$attr][1] as $enum) {
+          if ($enum === $val) {
+            return;
+          }
+        }
+        $enums = 'enum("' . implode('","', $decl[$attr][1]) . '")';
+        throw new XHPInvalidAttributeException($this, $enums, $attr, $val);
+    }
+  }
+
+  /**
+   * Validates that this element's children match its children descriptor, and
+   * throws an exception if that's not the case.
+   */
+  final protected function validateChildren() {
+    $decl = $this->__xhpChildrenDeclaration();
+    if ($decl === 1) { // Any children allowed
+      return;
+    }
+    if ($decl === 0) { // No children allowed
+      if ($this->children) {
+        throw new XHPInvalidChildrenException($this, 0);
+      } else {
+        return;
+      }
+    }
+    $ii = 0;
+    if (!$this->validateChildrenExpression($decl, $ii) ||
+        $ii < count($this->children)) {
+      // Use of HTML() breaks the content model definition.
+      // Lesson: Don't use HTML().
+      if (isset($this->children[$ii]) && $this->children[$ii] instanceof HTML) {
+        return;
+      }
+      throw new XHPInvalidChildrenException($this, $ii);
+    }
+  }
+
+  final private function validateChildrenExpression($decl, &$index) {
+    switch ($decl[0]) {
+      case 0: // Exactly once -- :fb-thing
+        if ($this->validateChildrenRule($decl[1], $decl[2], $index)) {
+          return true;
+        }
+        return false;
+
+      case 1: // Zero or more times -- :fb-thing*
+        while ($this->validateChildrenRule($decl[1], $decl[2], $index));
+        return true;
+
+      case 2: // Zero or one times -- :fb-thing?
+        if ($this->validateChildrenRule($decl[1], $decl[2], $index));
+        return true;
+
+      case 3: // One or more times -- :fb-thing+
+        if (!$this->validateChildrenRule($decl[1], $decl[2], $index)) {
+          return false;
+        }
+        while ($this->validateChildrenRule($decl[1], $decl[2], $index));
+        return true;
+
+      case 4: // Specific order -- :fb-thing, :fb-other-thing
+        $oindex = $index;
+        if ($this->validateChildrenExpression($decl[1], $index) &&
+            $this->validateChildrenExpression($decl[2], $index)) {
+          return true;
+        }
+        $index = $oindex;
+        return false;
+
+      case 5: // Either or -- :fb-thing | :fb-other-thing
+        if ($this->validateChildrenExpression($decl[1], $index) ||
+            $this->validateChildrenExpression($decl[2], $index)) {
+          return true;
+        }
+        return false;
+    }
+  }
+
+  final private function validateChildrenRule($type, $rule, &$index) {
+    switch ($type) {
+      case 1: // any element -- any
+        if (isset($this->children[$index])) {
+          ++$index;
+          return true;
+        }
+        return false;
+
+      case 2: // pcdata -- pcdata
+        if (isset($this->children[$index]) &&
+            !($this->children[$index] instanceof :x:base)) {
+          ++$index;
+          return true;
+        }
+        return false;
+
+      case 3: // specific element -- :fb-thing
+        if (isset($this->children[$index]) &&
+            $this->children[$index] instanceof $rule) {
+          ++$index;
+          return true;
+        }
+        return false;
+
+      case 4: // element category -- %block
+        if (!isset($this->children[$index]) ||
+            !($this->children[$index] instanceof :x:base)) {
+          return false;
+        }
+        $categories = $this->children[$index]->__xhpCategoryDeclaration();
+        if (empty($categories[$rule])) {
+          return false;
+        }
+        ++$index;
+        return true;
+
+      case 5: // nested rule -- ((:fb-thing, :fb-other-thing)*, :fb:thing-footer)
+        return $this->validateChildrenExpression($rule, $index);
+    }
+  }
+
+  /**
+   * Returns the human-readable `children` declaration as seen in this class's
+   * source code.
+   */
+  final public function __getChildrenDeclaration() {
+    $decl = $this->__xhpChildrenDeclaration();
+    if ($decl === 1) {
+      return 'any';
+    }
+    if ($decl === 0) {
+      return 'empty';
+    }
+    return $this->renderChildrenDeclaration($decl);
+  }
+
+  final private function renderChildrenDeclaration($decl) {
+    switch ($decl[0]) {
+      case 0:
+        return $this->renderChildrenRule($decl[1], $decl[2]);
+
+      case 1:
+        return $this->renderChildrenRule($decl[1], $decl[2]) . '*';
+
+      case 2:
+        return $this->renderChildrenRule($decl[1], $decl[2]) . '?';
+
+      case 3:
+        return $this->renderChildrenRule($decl[1], $decl[2]) . '+';
+
+      case 4:
+        return $this->renderChildrenDeclaration($decl[1]) . ',' .
+          $this->renderChildrenDeclaration($decl[2]);
+
+      case 5:
+        return $this->renderChildrenDeclaration($decl[1]) . '|' .
+          $this->renderChildrenDeclaration($decl[2]);
+    }
+  }
+
+  final private function renderChildrenRule($type, $rule) {
+    switch ($type) {
+      case 1:
+        return 'any';
+
+      case 2:
+        return 'pcdata';
+
+      case 3:
+        return ':' . :x:base::class2element($rule);
+
+      case 4:
+        return '%' . $rule;
+
+      case 5:
+        return '(' . $this->renderChildrenDeclaration($rule) . ')';
+    }
+  }
+
+  /**
+   * Returns a description of the current children in this element. Maybe
+   * something like this:
+   * <div><span>foo</span>bar</div> ->
+   * :span[%inline],pcdata
+   */
+  final public function __getChildrenDescription() {
+    $desc = array();
+    foreach ($this->children as $child) {
+      if ($child instanceof :x:base) {
+        $tmp = ':' . :x:base::class2element(get_class($child));
+        if ($categories = $child->__xhpCategoryDeclaration()) {
+          $tmp .= '[%'. implode(',%', array_keys($categories)) . ']';
+        }
+        $desc[] = $tmp;
+      } else {
+        $desc[] = 'pcdata';
+      }
+    }
+    return implode(',', $desc);
+  }
+
+  final public function categoryOf($c) {
+    $categories = $this->__xhpCategoryDeclaration();
+    return isset($categories[$c]);
+  }
+}
+
+/**
+ * :x:primitive lays down the foundation for very low-level elements. You
+ * should directly :x:primitive only if you are creating a core element that
+ * needs to directly implement stringify(). All other elements should subclass
+ * from :x:element.
+ */
+abstract class :x:primitive extends :x:composable-element {
+  abstract protected function stringify();
+
+  /**
+   *  This isn't __toString() because throwing an exception out of __toString()
+   *  produces a useless, immediate fatal, and allowing XHP to seamlessly cast
+   *  into strings encourages bad practices, like this real snippet:
+   *
+   *    $links .= <a>...</a>;
+   *    $links .= <a>...</a>;
+   *    return HTML($links);
+   *
+   */
+  final public function __toString() {
+
+    // Validate our children
+    $this->__flushElementChildren();
+    if (:x:base::$ENABLE_VALIDATION) {
+      $this->validateChildren();
+    }
+
+    // Render to string
+    return $this->stringify();
+  }
+}
+
+/**
+ * :x:element defines an interface that all user-land elements should subclass
+ * from. The main difference between :x:element and :x:primitive is that
+ * subclasses of :x:element should implement `render()` instead of `stringify`.
+ * This is important because most elements should not be dealing with strings
+ * of markup.
+ */
+abstract class :x:element extends :x:composable-element {
+  final public function __toString() {
+    $that = $this;
+
+    if (:x:base::$ENABLE_VALIDATION) {
+      // Validate the current object
+      $that->validateChildren();
+
+      // And each intermediary object it returns
+      while (($that = $that->render()) instanceof :x:element) {
+        $that->validateChildren();
+      }
+
+      // render() must always return XHPPrimitives
+      if (!($that instanceof :x:composable-element)) {
+        throw new XHPCoreRenderException($this, $that);
+      }
+    } else {
+      // Skip the above checks when not validating
+      while (($that = $that->render()) instanceof :x:element);
+    }
+
+    return $that->__toString();
+  }
+}
+
+/**
+ * :x:composite is a special class which allows you to pass around a node that
+ * acts on another node, but any `appendChild()` calls will append to one of its
+ * children.
+ *
+ * This can be useful if you want to pass around an object that will later be
+ * wrapped on the inside.
+ *
+ * For instance, you can define an :x:composite like this:
+ * $parent = <div><p>{$anchor = <span />}</p></div>;
+ * $composite = new :x:composite($parent, $anchor);
+ *
+ * Then if another client wants to wrap the contents of your composite node,
+ * he would do so by:
+ * $composite->appendChild($anchor = <b />);
+ * $composite = new :x:composite($composite, $anchor);
+ *
+ * Note that we create another composite from the old one so that later down the
+ * line we can wrap again with another tag.
+ *
+ * IMPORTANT: I think this class is broken right now. If you want to use it you
+ * should try to fix it.
+ */
+class :x:composite extends :x:base {
+  private
+    $parent,
+    $anchor;
+
+  public function __construct(:x:base $parent, :x:base $anchor) {
+    $this->parent = $parent;
+    $this->anchor = $anchor;
+  }
+
+  public function appendChild($child) {
+    return $this->anchor->appendChild($child);
+  }
+
+  public function getAttribute($attr) {
+    return $this->parent->getAttribute($attr);
+  }
+
+  public function setAttribute($attr, $val) {
+    return $this->parent->setAttribute($attr, $val);
+  }
+
+  public function categoryOf($cat) {
+    return $this->parent->categoryOf($cat);
+  }
+
+  public function __toString() {
+    return $this->parent->__toString();
+  }
+
+  protected static function &__xhpAttributeDeclaration() {
+    return $this->parent->__xhpAttributeDeclaration();
+  }
+
+  protected function &__xhpCategoryDeclaration() {
+    return $this->parent->__xhpCategoryDeclaration();
+  }
+
+  protected function &__xhpChildrenDeclaration() {
+    return $this->parent->__xhpChildrenDeclaration();
+  }
+}
+
+/**
+ * An <x:frag /> is a transparent wrapper around any number of elements. When
+ * you render it just the children will be rendered. When you append it to an
+ * element the <x:frag /> will disappear and each child will be sequentially
+ * appended to the element.
+ */
+class :x:frag extends :x:primitive {
+  protected function stringify() {
+    $buf = '';
+    foreach ($this->getChildren() as $child) {
+      $buf .= :x:base::renderChild($child);
+    }
+    return $buf;
+  }
+}
+
+/**
+ * Exceptions are neat.
+ */
+class XHPException extends Exception {
+  protected static function getElementName($that) {
+    $name = get_class($that);
+    if (substr($name, 0, 4) !== 'xhp_') {
+      return $name;
+    } else {
+      return :x:base::class2element($name);
+    }
+  }
+}
+
+class XHPClassException extends XHPException {
+  public function __construct($that, $msg) {
+    parent::__construct(
+      'Exception in class `' . XHPException::getElementName($that) . "`\n\n".
+      "$that->source\n\n".
+      $msg
+    );
+  }
+}
+
+class XHPCoreRenderException extends XHPException {
+  public function __construct($that, $rend) {
+    parent::__construct(
+      ':x:element::render must reduce an object to an :x:primitive, but `'.
+      :x:base::class2element(get_class($that)).'` reduced into `'.gettype($rend)."`.\n\n".
+      $that->source
+    );
+  }
+}
+
+class XHPRenderArrayException extends XHPException {
+}
+
+class XHPAttributeNotSupportedException extends XHPException {
+  public function __construct($that, $attr) {
+    parent::__construct(
+      'Attribute `'.$attr.'` is not supported in class '.
+      '`'.XHPException::getElementName($that)."`.\n\n".
+      "$that->source\n\n".
+      'Please check for typos in your attribute. If you are creating a new '.
+      'attribute on this element please add your attribute to the '.
+      "`supportedAttributes` method.\n\n"
+    );
+  }
+}
+
+class XHPAttributeRequiredException extends XHPException {
+  public function __construct($that, $attr) {
+    parent::__construct(
+      'Required attribute `'.$attr.'` was not specified in element '.
+      '`'.XHPException::getElementName($that)."`.\n\n".
+      $that->source
+    );
+  }
+}
+
+class XHPInvalidAttributeException extends XHPException {
+  public function __construct($that, $type, $attr, $val) {
+    if (is_object($val)) {
+      $val_type = get_class($val);
+    } else {
+      $val_type = gettype($val);
+    }
+    parent::__construct(
+      "Invalid attribute `$attr` of type `$val_type` supplied to element `".
+      :x:base::class2element(get_class($that))."`, expected `$type`.\n\n".
+      $that->source
+    );
+  }
+}
+
+class XHPInvalidChildrenException extends XHPException {
+  public function __construct($that, $index) {
+    parent::__construct(
+      'Element `'.XHPException::getElementName($that).'` was rendered with '.
+      "invalid children.\n\n".
+      "$that->source\n\n".
+      "Verified $index children before failing.\n\n".
+      "Children expected:\n".$that->__getChildrenDeclaration()."\n\n".
+      "Children received:\n".$that->__getChildrenDescription()
+    );
+  }
+}
Index: www/xhp/base/html.php
new file mode 100644
===================================================================
--- www/xhp/base/html.php	(revision 0)
+++ www/xhp/base/html.php	(working copy)
@@ -0,0 +1,741 @@
+<?php
+/*
+  +----------------------------------------------------------------------+
+  | XHP                                                                  |
+  +----------------------------------------------------------------------+
+  | Copyright (c) 2009 - 2010 Facebook, Inc. (http://www.facebook.com)          |
+  +----------------------------------------------------------------------+
+  | This source file is subject to version 3.01 of the PHP license,      |
+  | that is bundled with this package in the file LICENSE.PHP, and is    |
+  | available through the world-wide-web at the following url:           |
+  | http://www.php.net/license/3_01.txt                                  |
+  | If you did not receive a copy of the PHP license and are unable to   |
+  | obtain it through the world-wide-web, please send a note to          |
+  | license@php.net so we can mail you a copy immediately.               |
+  +----------------------------------------------------------------------+
+*/
+
+/**
+ * This is the base library of HTML elements for use in XHP. This includes all
+ * non-deprecated tags and attributes. Elements in this file should stay as
+ * close to spec as possible. Facebook-specific extensions should go into their
+ * own elements.
+ */
+abstract class :xhp:html-element extends :x:primitive {
+
+  // TODO: Break these out into abstract elements so that elements that need
+  // them can steal the definition. Right now this is an overloaded list of
+  // attributes.
+  attribute
+    // HTML attributes
+    string accesskey, string class, string dir, string id, string lang,
+    string style, string tabindex, string title,
+
+    // Javascript events
+    string onabort, string onblur, string onchange, string onclick,
+    string ondblclick, string onerror, string onfocus, string onkeydown,
+    string onkeypress, string onkeyup, string onload, string onmousedown,
+    string onmousemove, string onmouseout, string onmouseover, string onmouseup,
+    string onreset, string onresize, string onselect, string onsubmit,
+    string onunload,
+
+    // IE only
+    string onmouseenter, string onmouseleave,
+
+    // Joe Hewitt!!
+    // TODO:
+    string selected, string otherButtonLabel, string otherButtonHref,
+    string otherButtonClass, string type, string replaceCaret,
+    string replaceChildren;
+
+
+  protected
+    $tagName;
+
+  public function requireUniqueId() {
+    // TODO: Implement something on AsyncRequest that returns the number of
+    //       requests sent so far so we can remove the microtime(true) thing.
+    if (!($id = $this->getAttribute('id'))) {
+      $this->setAttribute('id', $id = substr(md5(mt_rand(0, 100000)), 0, 10));
+    }
+    return $id;
+  }
+
+  protected final function renderBaseAttrs() {
+    $buf = '<'.$this->tagName;
+    foreach ($this->getAttributes() as $key => $val) {
+      if ($val !== null && $val !== false) {
+        $buf .= ' ' . htmlspecialchars($key) . '="' . htmlspecialchars($val, true) . '"';
+      }
+    }
+    return $buf;
+  }
+
+  public function addClass($class) {
+    $class = trim($class);
+
+    $currentClasses = $this->getAttribute('class');
+    $has = strpos(' '.$currentClasses.' ', ' '.$class.' ') !== false;
+    if ($has) {
+      return $this;
+    }
+
+    $this->setAttribute('class', trim($currentClasses.' '.$class));
+    return $this;
+  }
+
+  protected function stringify() {
+    $buf = $this->renderBaseAttrs() . '>';
+    foreach ($this->getChildren() as $child) {
+      $buf .= :x:base::renderChild($child);
+    }
+    $buf .= '</'.$this->tagName.'>';
+    return $buf;
+  }
+}
+
+/**
+ * Subclasses of :xhp:html-singleton may not contain children. When rendered they
+ * will be in singleton (<img />, <br />) form.
+ */
+abstract class :xhp:html-singleton extends :xhp:html-element {
+  children empty;
+
+  protected function stringify() {
+    return $this->renderBaseAttrs() . ' />';
+  }
+}
+
+/**
+ * Subclasses of :xhp:pseudo-singleton may contain exactly zero or one
+ * children. When rendered they will be in full open\close form, no matter how
+ * many children there are.
+ */
+abstract class :xhp:pseudo-singleton extends :xhp:html-element {
+  children (pcdata)*;
+
+  protected function escape($txt) {
+    return htmlspecialchars($txt);
+  }
+
+  protected function stringify() {
+    $buf = $this->renderBaseAttrs() . '>';
+    if ($children = $this->getChildren()) {
+      $buf .= :x:base::renderChild($children[0]);
+    }
+    return $buf . '</'.$this->tagName.'>';
+  }
+}
+
+/**
+ * Below is a big wall of element definitions. These are the basic building
+ * blocks of XHP pages.
+ */
+class :a extends :xhp:html-element {
+  attribute
+    string href, string name, string rel, string target;
+  category %flow, %phrase, %interactive;
+  // transparent
+  // may not contain %interactive
+  children (pcdata | %flow)*;
+  protected $tagName = 'a';
+}
+
+class :abbr extends :xhp:html-element {
+  category %flow, %phrase;
+  children (pcdata | %phrase)*;
+  protected $tagName = 'abbr';
+}
+
+class :acronym extends :xhp:html-element {
+  category %flow, %phrase;
+  children (pcdata | %phrase)*;
+  protected $tagName = 'acronym';
+}
+
+class :address extends :xhp:html-element {
+  category %flow;
+  // may not contain h1-h6
+  children (pcdata | %flow)*;
+  protected $tagName = 'address';
+}
+
+class :area extends :xhp:html-singleton {
+  attribute string alt, string coords, string href, bool nohref, string target;
+  protected $tagName = 'area';
+}
+
+class :b extends :xhp:html-element {
+  category %flow, %phrase;
+  children (pcdata | %phrase)*;
+  protected $tagName = 'b';
+}
+
+class :base extends :xhp:html-singleton {
+  attribute string href, string target;
+  // also a member of "metadata", but is not listed here. see comments in :head
+  // for more information
+  protected $tagName = 'base';
+}
+
+class :big extends :xhp:html-element {
+  category %flow, %phrase;
+  children (pcdata | %phrase)*;
+  protected $tagName = 'big';
+}
+
+class :blockquote extends :xhp:html-element {
+  attribute string cite;
+  category %flow;
+  children (pcdata | %flow)*;
+  protected $tagName = 'blockquote';
+}
+
+class :body extends :xhp:html-element {
+  children (pcdata | %flow)*;
+  protected $tagName = 'body';
+}
+
+class :br extends :xhp:html-singleton {
+  category %flow, %phrase;
+  protected $tagName = 'br';
+}
+
+class :button extends :xhp:html-element {
+  attribute
+    bool disabled, string name, enum { "submit", "button", "reset" } type, string value;
+  category %flow, %phrase, %interactive;
+  // may not contain interactive
+  children (pcdata | %phrase)*;
+  protected $tagName = 'button';
+}
+
+class :caption extends :xhp:html-element {
+  // may not contain table
+  children (pcdata | %flow)*;
+  protected $tagName = 'caption';
+}
+
+class :cite extends :xhp:html-element {
+  category %flow, %phrase;
+  children (pcdata | %phrase)*;
+  protected $tagName = 'cite';
+}
+
+class :code extends :xhp:html-element {
+  category %flow, %phrase;
+  children (pcdata | %phrase)*;
+  protected $tagName = 'code';
+}
+
+class :col extends :xhp:html-singleton {
+  attribute
+    enum { "left", "right", "center", "justify", "char" } align, string char,
+    int charoff, int span,
+    enum { "top", "middle", "bottom", "baseline" } valign, string width;
+  protected $tagName = 'col';
+}
+
+class :colgroup extends :xhp:html-element {
+  attribute
+    enum { "left", "right", "center", "justify", "char" } align, string char,
+    int charoff, int span,
+    enum { "top", "middle", "bottom", "baseline" } valign, string width;
+  children (:col)*;
+  protected $tagName = 'colgroup';
+}
+
+class :dd extends :xhp:html-element {
+  children (pcdata | %flow)*;
+  protected $tagName = 'dd';
+}
+
+class :del extends :xhp:html-element {
+  attribute string cite, string datetime;
+  category %flow, %phrase;
+  // transparent
+  children (pcdata | %flow)*;
+  protected $tagName = 'del';
+}
+
+class :div extends :xhp:html-element {
+  category %flow;
+  children (pcdata | %flow)*;
+  protected $tagName = 'div';
+}
+
+class :dfn extends :xhp:html-element {
+  category %flow, %phrase;
+  children (pcdata | %phrase)*;
+  protected $tagName = 'dfn';
+}
+
+class :dl extends :xhp:html-element {
+  category %flow;
+  children (:dt+, :dd+)*;
+  protected $tagName = 'dl';
+}
+
+class :dt extends :xhp:html-element {
+  children (pcdata | %phrase)*;
+  protected $tagName = 'dt';
+}
+
+class :em extends :xhp:html-element {
+  category %flow, %phrase;
+  children (pcdata | %phrase)*;
+  protected $tagName = 'em';
+}
+
+class :fieldset extends :xhp:html-element {
+  category %flow;
+  children (:legend?, (pcdata | %flow)*);
+  protected $tagName = 'fieldset';
+}
+
+class :form extends :xhp:html-element {
+  attribute
+    string action, string accept, string accept-charset, string enctype,
+    enum { "get", "post" } method, string name, string target, bool ajaxify;
+  category %flow;
+  // may not contain form
+  children (pcdata | %flow)*;
+  protected $tagName = 'form';
+}
+
+class :frame extends :xhp:html-singleton {
+  attribute
+    bool frameborder, string longdesc, int marginheight, int marginwidth,
+    string name, bool noresize, enum { "yes", "no", "auto" } scrolling,
+    string src;
+  protected $tagName = 'frame';
+}
+
+class :frameset extends :xhp:html-element {
+  children (:frame | :frameset | :noframes)*;
+  protected $tagName = 'frameset';
+}
+
+class :h1 extends :xhp:html-element {
+  category %flow;
+  children (pcdata | %phrase)*;
+  protected $tagName = 'h1';
+}
+
+class :h2 extends :xhp:html-element {
+  category %flow;
+  children (pcdata | %phrase)*;
+  protected $tagName = 'h2';
+}
+
+class :h3 extends :xhp:html-element {
+  category %flow;
+  children (pcdata | %phrase)*;
+  protected $tagName = 'h3';
+}
+
+class :h4 extends :xhp:html-element {
+  category %flow;
+  children (pcdata | %phrase)*;
+  protected $tagName = 'h4';
+}
+
+class :h5 extends :xhp:html-element {
+  category %flow;
+  children (pcdata | %phrase)*;
+  protected $tagName = 'h5';
+}
+
+class :h6 extends :xhp:html-element {
+  category %flow;
+  children (pcdata | %phrase)*;
+  protected $tagName = 'h6';
+}
+
+class :head extends :xhp:html-element {
+  attribute string profile;
+  children (%metadata*, :title, %metadata*, :base?, %metadata*);
+  // Note: html/xhtml spec says that there should be exactly 1 <title />, and at
+  // most 1 <base />. These elements can occur in any order, and can be
+  // surrounded by any number of other elements (in %metadata). The problem
+  // here is that XHP's validation does not backtrack, so there's no way to
+  // accurately implement the spec. This is the closest we can get. The only
+  // difference between this and the spec is that in XHP the <title /> must
+  // appear before the <base />.
+  protected $tagName = 'head';
+}
+
+class :hr extends :xhp:html-singleton {
+  category %flow;
+  protected $tagName = 'hr';
+}
+
+class :html extends :xhp:html-element {
+  attribute string xmlns;
+  children (:head, :body);
+  protected $tagName = 'html';
+}
+
+class :i extends :xhp:html-element {
+  category %flow, %phrase;
+  children (pcdata | %phrase)*;
+  protected $tagName = 'i';
+}
+
+class :iframe extends :xhp:pseudo-singleton {
+  attribute
+    enum {"1", "0"} frameborder,
+    string height, string longdesc, int marginheight,
+    int marginwidth, string name, enum { "yes", "no", "auto" } scrolling,
+    string src, string width;
+  category %flow, %phrase, %interactive;
+  children empty;
+  protected $tagName = 'iframe';
+}
+
+class :img extends :xhp:html-singleton {
+  attribute
+    // Lite
+    string staticsrc,
+    // HTML
+    string alt, string src, string height, bool ismap, string longdesc,
+    string usemap, string width;
+  category %flow, %phrase;
+  protected $tagName = 'img';
+}
+
+class :input extends :xhp:html-singleton {
+  attribute
+    // Non-standard
+    enum { "on", "off" } autocomplete,
+    string placeholder,
+    // HTML
+    string accept, enum { "left", "right", "top", "middle", "bottom" } align,
+    string alt, bool checked, bool disabled, int maxlength, string name,
+    bool readonly, int size, string src,
+    enum {
+      "button", "checkbox", "file", "hidden", "image", "password", "radio",
+      "reset", "submit", "text"
+    } type,
+    string value;
+  category %flow, %phrase, %interactive;
+  protected $tagName = 'input';
+}
+
+class :ins extends :xhp:html-element {
+  attribute string cite, string datetime;
+  category %flow, %phrase;
+  // transparent
+  children (pcdata | %flow)*;
+  protected $tagName = 'ins';
+}
+
+class :kbd extends :xhp:html-element {
+  category %flow, %phrase;
+  children (pcdata | %phrase)*;
+  protected $tagName = 'kbd';
+}
+
+class :label extends :xhp:html-element {
+  attribute string for;
+  category %flow, %phrase, %interactive;
+  // may not contain label
+  children (pcdata | %phrase)*;
+  protected $tagName = 'label';
+}
+
+class :legend extends :xhp:html-element {
+  children (pcdata | %phrase)*;
+  protected $tagName = 'legend';
+}
+
+class :li extends :xhp:html-element {
+  children (pcdata | %flow)*;
+  protected $tagName = 'li';
+}
+
+class :link extends :xhp:html-singleton {
+  attribute
+    string charset, string href, string hreflang, string media, string rel,
+    string rev, string target, string type;
+  category %metadata;
+  protected $tagName = 'link';
+}
+
+class :map extends :xhp:html-element {
+  attribute string name;
+  category %flow, %phrase;
+  // transparent
+  children ((pcdata | %flow)+ | :area+);
+  protected $tagName = 'map';
+}
+
+class :meta extends :xhp:html-singleton {
+  attribute
+    string content @required,
+    enum {
+      "content-type", "content-style-type", "expires", "refresh", "set-cookie"
+    } http-equiv,
+    string http-equiv, string name, string scheme;
+  category %metadata;
+  protected $tagName = 'meta';
+}
+
+class :noframes extends :xhp:html-element {
+  children (%html-body);
+  protected $tagName = 'noframes';
+}
+
+class :noscript extends :xhp:html-element {
+  // transparent
+  category %flow, %phrase;
+  protected $tagName = 'noscript';
+}
+
+class :object extends :xhp:html-element {
+  attribute
+    enum { "left", "right", "top", "bottom" } align, string archive, int border,
+    string classid, string codebase, string codetype, string data, bool declare,
+    int height, int hspace, string name, string standby, string type,
+    string usemap, int vspace, int width;
+  category %flow, %phrase;
+  // transparent, after the params
+  children (:param*, (pcdata | %flow)*);
+  protected $tagName = 'object';
+}
+
+class :ol extends :xhp:html-element {
+  category %flow;
+  children (:li)*;
+  protected $tagName = 'ol';
+}
+
+class :optgroup extends :xhp:html-element {
+  attribute string label, bool disabled;
+  children (:option)*;
+  protected $tagName = 'optgroup';
+}
+
+class :option extends :xhp:pseudo-singleton {
+  attribute bool disabled, string label, bool selected, string value;
+  protected $tagName = 'option';
+}
+
+class :p extends :xhp:html-element {
+  category %flow;
+  children (pcdata | %phrase)*;
+  protected $tagName = 'p';
+}
+
+class :param extends :xhp:pseudo-singleton {
+  attribute
+    string name, string type, string value,
+    enum { "data", "ref", "object" } valuetype;
+  protected $tagName = 'param';
+}
+
+class :pre extends :xhp:html-element {
+  category %flow;
+  children (pcdata | %phrase)*;
+  protected $tagName = 'pre';
+}
+
+class :q extends :xhp:html-element {
+  attribute string cite;
+  category %flow, %phrase;
+  children (pcdata | %phrase)*;
+  protected $tagName = 'q';
+}
+
+// deprecated
+class :s extends :xhp:html-element {
+  category %flow, %phrase;
+  children (pcdata | %phrase)*;
+  protected $tagName = 's';
+}
+
+class :samp extends :xhp:html-element {
+  category %flow, %phrase;
+  children (pcdata | %phrase)*;
+  protected $tagName = 'samp';
+}
+
+class :script extends :xhp:pseudo-singleton {
+  attribute string charset, bool defer, string src, string type;
+  category %flow, %phrase, %metadata;
+  protected $tagName = 'script';
+}
+
+class :select extends :xhp:html-element {
+  attribute bool disabled, bool multiple, string name, int size;
+  category %flow, %phrase, %interactive;
+  children (:option | :optgroup)*;
+  protected $tagName = 'select';
+}
+
+class :small extends :xhp:html-element {
+  category %flow, %phrase;
+  children (pcdata | %phrase)*;
+  protected $tagName = 'small';
+}
+
+class :span extends :xhp:html-element {
+  category %flow, %phrase;
+  children (pcdata | %phrase)*;
+  protected $tagName = 'span';
+}
+
+class :strong extends :xhp:html-element {
+  category %flow, %phrase;
+  children (pcdata | %phrase)*;
+  protected $tagName = 'strong';
+}
+
+class :style extends :xhp:pseudo-singleton {
+  attribute
+    enum {
+      "screen", "tty", "tv", "projection", "handheld", "print", "braille",
+      "aural", "all"
+    } media, string type;
+  category %metadata;
+  protected $tagName = 'style';
+}
+
+class :sub extends :xhp:html-element {
+  category %flow, %phrase;
+  children (pcdata | %phrase);
+  protected $tagName = 'sub';
+}
+
+class :sup extends :xhp:html-element {
+  category %flow, %phrase;
+  children (pcdata | %phrase);
+  protected $tagName = 'sup';
+}
+
+class :table extends :xhp:html-element {
+  attribute
+    int border, int cellpadding, int cellspacing,
+    enum {
+      "void", "above", "below", "hsides", "lhs", "rhs", "vsides", "box",
+      "border"
+    } frame,
+    enum { "none", "groups", "rows", "cols", "all" } rules,
+    string summary, string width;
+  category %flow;
+  children (
+    :caption?, :colgroup*,
+    :thead?,
+    (
+      (:tfoot, (:tbody+ | :tr*)) |
+      ((:tbody+ | :tr*), :tfoot?)
+    )
+  );
+  protected $tagName = 'table';
+}
+
+class :tbody extends :xhp:html-element {
+  attribute
+    enum { "right", "left", "center", "justify", "char" } align, string char,
+    int charoff, enum { "top", "middle", "bottom", "baseline" } valign;
+  children (:tr)*;
+  protected $tagName = 'tbody';
+}
+
+
+class :td extends :xhp:html-element {
+  attribute
+    string abbr, enum { "left", "right", "center", "justify", "char" } align,
+    string axis, string char, int charoff, int colspan, string headers,
+    int rowspan, enum { "col", "colgroup", "row", "rowgroup" } scope,
+    enum { "top", "middle", "bottom", "baseline" } valign;
+  children (pcdata | %flow)*;
+  protected $tagName = 'td';
+}
+
+class :textarea extends :xhp:pseudo-singleton {
+  attribute int cols, int rows, bool disabled, string name, bool readonly;
+  category %flow, %phrase, %interactive;
+  protected $tagName = 'textarea';
+}
+
+class :tfoot extends :xhp:html-element {
+  attribute
+    enum { "left", "right", "center", "justify", "char" } align, string char,
+    int charoff, enum { "top", "middle", "bottom", "baseline" } valign;
+  children (:tr)*;
+  protected $tagName = 'tfoot';
+}
+
+class :th extends :xhp:html-element {
+  attribute
+    string abbr, enum { "left", "right", "center", "justify", "char" } align,
+    string axis, string char, int charoff, int colspan, int rowspan,
+    enum { "col", "colgroup", "row", "rowgroup" } scope,
+    enum { "top", "middle", "bottom", "baseline" } valign;
+  children (pcdata | %flow)*;
+  protected $tagName = 'th';
+}
+
+class :thead extends :xhp:html-element {
+  attribute
+    enum { "left", "right", "center", "justify", "char" } align, string char,
+    int charoff, enum { "top", "middle", "bottom", "baseline" } valign;
+  children (:tr)*;
+  protected $tagName = 'thead';
+}
+
+class :title extends :xhp:pseudo-singleton {
+  // also a member of "metadata", but is not listed here. see comments in :head
+  // for more information.
+  protected $tagName = 'title';
+}
+
+class :tr extends :xhp:html-element {
+  attribute
+    enum { "left", "right", "center", "justify", "char" } align, string char,
+    int charoff, enum { "top", "middle", "bottom", "baseline" } valign;
+  children (:th | :td)*;
+  protected $tagName = 'tr';
+}
+
+class :tt extends :xhp:html-element {
+  category %flow, %phrase;
+  children (pcdata | %phrase)*;
+  protected $tagName = 'tt';
+}
+
+// deprecated
+class :u extends :xhp:html-element {
+  category %flow, %phrase;
+  children (pcdata | %phrase)*;
+  protected $tagName = 'u';
+}
+
+class :ul extends :xhp:html-element {
+  category %flow;
+  children (:li)*;
+  protected $tagName = 'ul';
+}
+
+class :var extends :xhp:html-element {
+  category %flow, %phrase;
+  children (pcdata | %phrase)*;
+  protected $tagName = 'var';
+}
+
+/**
+ * Render an <html /> element with a DOCTYPE, great for dumping a page to a
+ * browser. Choose from a wide variety of flavors like XHTML 1.0 Strict, HTML
+ * 4.01 Transitional, and new and improved HTML 5!
+ *
+ * Note: Some flavors may not be available in your area.
+ */
+class :x:doctype extends :x:primitive {
+  children (:html);
+
+  protected function stringify() {
+    $children = $this->getChildren();
+    return '<!DOCTYPE html>' . (:x:base::renderChild($children[0]));
+  }
+}
Index: www/xhp/base/init.php
new file mode 100644
===================================================================
--- www/xhp/base/init.php	(revision 0)
+++ www/xhp/base/init.php	(working copy)
@@ -0,0 +1,20 @@
+<?php
+require_once 'core.php';
+require_once 'html.php';
+
+// Infoarena-only hack. The XHP codebase allows one to disable escaping of a
+// string by using something like HTML('...'), but that was not defined
+// anywhere. This makes it work, but is extremely limited.
+function HTML($str) {
+  return new HTML($str);
+}
+
+class HTML {
+  function __construct($str) {
+    $this->str = $str;
+  }
+
+  function render() {
+    return $this->str;
+  }
+}
Index: www/xhp/ia/base.php
new file mode 100644
===================================================================
--- www/xhp/ia/base.php	(revision 0)
+++ www/xhp/ia/base.php	(working copy)
@@ -0,0 +1,133 @@
+<?php
+// Contains the base ia:page XHP object that is used as a platform for
+// rendering all pages on the main website.
+
+require_once(IA_ROOT_DIR . 'www/xhp/ia/sitewide.php');
+
+class :ia:page extends :x:element {
+    attribute
+        array user,
+        string title = "infoarena",
+        string charset = "UTF-8";
+    /*
+     * The ia:page XHP object can have meta, link and script children that are
+     * added to the <head> of the rendered page in addition to the default one.
+     *
+     * The website's header, top navigation bar, left column and footer are all
+     * optional and can be ommited. The main content of the website should be
+     * enclosed in a <ia:content> tag.
+     */
+    children ((:meta | :link | :script)*,
+              :ia:header?, :ia:top-navbar?, :ia:left-col?,
+              :ui:breadcrumbs?, :ui:flash-message?, :ia:footer?,
+              :ia:content);
+
+    protected function render() {
+        $default_css = array(
+            'sitewide.css', 'screen.css',
+            'iconize.css', 'sh/shCore.css', 'sh/shThemeDefault.css',
+            <link type="text/css" rel="stylesheet"
+              href={url_static('css/print.css')} media="print" />,
+        );
+        // FIXME: infoarena's javascript is a horrible mess.
+        $default_js = array(
+            'config.js.php',
+            'MochiKit.js',
+            'default.js',
+            'submit.js',
+            'remotebox.js',
+            'postdata.js',
+            'sh/shCore.js',
+            'sh/shBrushCpp.js',
+            'sh/shBrushDelphi.js',
+            'sh/shBrushJava.js',
+            'sh/shBrushPython.js',
+            'sh/shInit.js',
+            'tags.js',
+            'roundtimer.js',
+            'restoreparity.js',
+            'foreach.js',
+            'sorttable.js',
+            'tablednd.js',
+            <script type="text/javascript">
+              {"Sh_Init('" . url_static('swf/clipboard.swf') . "')"}
+            </script>,
+        );
+
+        // Add the default CSS and JS files to the page's children.
+        foreach ($default_css as $css_element) {
+            if (is_string($css_element)) {
+                $this->appendChild(
+                  <link type="text/css" rel="stylesheet"
+                    href={url_static('css/' . $css_element)} />);
+            } else {
+                $this->appendChild($css_element);
+            }
+        }
+        foreach ($default_js as $js_element) {
+            if (is_string($js_element)) {
+                $this->appendChild(
+                  <script type="text/javascript"
+                    src={url_static('js/' . $js_element)} />);
+            } else {
+                $this->appendChild($js_element);
+            }
+        }
+
+        // Forward the user attribute down to the children that require it.
+        $user = $this->getAttribute('user');
+        foreach ($this->getChildren() as $child) {
+            $child_attributes = $child->__xhpAttributeDeclaration();
+            if (array_key_exists('user', $child_attributes)) {
+                $child->setAttribute('user', $user);
+            }
+        }
+
+        // Render the document
+        $content_type = 'text/html; charset=' . $this->getAttribute('charset');
+        $head =
+          <head>
+            <meta http-equiv="Content-Type" content={$content_type} />
+            {$this->getChildren('meta')}
+
+            <title>{$this->getAttribute('title')}</title>
+
+            {$this->getChildren('link')}
+            <link rel="icon" href={IA_URL . 'favicon.ico'}
+              type="image/vnd.microsoft.icon" />
+
+            {$this->getChildren('script')}
+          </head>;
+
+        $body =
+          <body id="infoarena">
+            <div id="page">
+              {$this->getChildren('ia:header')}
+              {$this->getChildren('ia:top-navbar')}
+              <div id="content_small" class="clear">
+                {$this->getChildren('ia:left-col')}
+                <div id="main">
+                  {$this->getChildren('ui:breadcrumbs')}
+                  {$this->getChildren('ui:flash-message')}
+                  {$this->getChildren('ia:content')}
+                </div>
+              </div>
+            </div>
+            {$this->getChildren('ia:footer')}
+          </body>;
+
+        return
+          <x:doctype>
+            <html>
+              {$head}
+              {$body}
+            </html>
+          </x:doctype>;
+    }
+}
+
+class :ia:content extends :x:element {
+    protected function render() {
+        return <x:frag>{$this->getChildren()}</x:frag>;
+    }
+}
Index: www/xhp/ia/calendar.php
new file mode 100644
===================================================================
--- www/xhp/ia/calendar.php	(revision 0)
+++ www/xhp/ia/calendar.php	(working copy)
@@ -0,0 +1,15 @@
+<?php
+
+require_once(IA_ROOT_DIR . 'www/macros/macro_calendar.php');
+
+class :ia:calendar extends :x:element {
+    children empty;
+
+    protected function render() {
+        // FIXME: This should not be done like this.
+        return
+          <div id="calendar">
+            {HTML(macro_calendar(array()))}
+          </div>;
+    }
+}
Index: www/xhp/ia/google_search.php
new file mode 100644
===================================================================
--- www/xhp/ia/google_search.php	(revision 0)
+++ www/xhp/ia/google_search.php	(working copy)
@@ -0,0 +1,21 @@
+<?php
+
+class :ia:google-search extends :x:element {
+    children empty;
+
+    protected function render() {
+        return
+          <div id="google-search">
+            <form id="searchbox_010130381492294265836:kw-fmmvpxco" action="http://infoarena.ro/search">
+              <fieldset>
+                <legend><img src={url_static('images/icons/search.png')} alt="!" /> Cautare</legend>
+                <input type="hidden" name="cx" value="010130381492294265836:kw-fmmvpxco" />
+                <input type="hidden" name="cof" value="FORID:9" />
+                <input name="q" type="text" size="22" />
+                <input type="submit" name="sa" value="Cauta" class="button important"/>
+              </fieldset>
+            </form>
+            <script type="text/javascript" src="http://www.google.com/coop/cse/brand?form=searchbox_010130381492294265836%3Akw-fmmvpxco"></script>
+          </div>;
+    }
+}
Index: www/xhp/ia/login_form.php
new file mode 100644
===================================================================
--- www/xhp/ia/login_form.php	(revision 0)
+++ www/xhp/ia/login_form.php	(working copy)
@@ -0,0 +1,36 @@
+<?php
+
+class :ia:login-form extends :x:element {
+    children empty;
+
+    protected function render() {
+        // FIXME: remove old style global form_values and form_errors
+        // FIXME: implement new XHP based way of displaying form fields.
+        return
+          <form action={url_login()} method="post" class="login">
+            <fieldset>
+              <legend><img src={url_static('images/icons/login.png')} alt="!" /> Autentificare</legend>
+              <ul class="form">
+                {HTML(view_form_field_li(array(
+                  'name' => 'Cont de utilizator',
+                  'type' => 'string',
+                  'access_key' => 'c',
+                ), 'username'))}
+                {HTML(view_form_field_li(array(
+                  'name' => 'Parola',
+                  'type' => 'string',
+                  'is_password' => true,
+                  'access_key' => 'p',
+                ), 'password'))}
+                <li>
+                  <input type="checkbox" value="on" id="form_remember" name="remember" class="checkbox" checked={fval('remember') ? 'checked' : null} />
+                  <label class="checkbox" for="form_remember">Pastreaza-ma autentificat 5 zile</label>
+                </li>
+                <li>
+                  <input type="submit" value="Autentificare" id="form_submit" class="button important" />
+                </li>
+              </ul>
+            </fieldset>
+          </form>;
+    }
+}
Index: www/xhp/ia/server_time.php
new file mode 100644
===================================================================
--- www/xhp/ia/server_time.php	(revision 0)
+++ www/xhp/ia/server_time.php	(working copy)
@@ -0,0 +1,14 @@
+<?php
+
+class :ia:server-time extends :x:element {
+    children empty;
+
+    protected function render() {
+        return
+          <x:frag>
+            <div id="srv_time" class="user-count"  />
+            <script type="text/javascript" src={url_static('js/time.js')} />
+            <script type="text/javascript">{'loadTime(' . format_date(null, "%H, %M, %S") . ');'}</script>
+           </x:frag>;
+    }
+}
Index: www/xhp/ia/sidebar.php
new file mode 100644
===================================================================
--- www/xhp/ia/sidebar.php	(revision 0)
+++ www/xhp/ia/sidebar.php	(working copy)
@@ -0,0 +1,136 @@
+<?php
+// Contains XHP objects for the site's left side bar.
+
+require_once(IA_ROOT_DIR . 'www/xhp/ia/login_form.php');
+
+class :ia:left-col extends :x:element {
+    attribute
+        array user;
+
+    protected function render() {
+        $user = $this->getAttribute('user');
+        foreach ($this->getChildren('ia:left-navbar') as $child) {
+            $child->setAttribute('user', $user);
+        }
+        return
+          <div id="sidebar">
+            {$this->getChildren()}
+          </div>;
+    }
+}
+
+class :ia:left-navbar extends :x:element {
+    attribute
+        array user;
+    children empty;
+
+    protected function render() {
+        $user = $this->getAttribute('user');
+        $list =
+          <ul id="nav" class="clear">
+            <li><a href={url_home()}>Home</a></li>
+            <li>
+              <ui:link href={url_textblock('arhiva')} accesskey="a">
+                Arhiva de probleme
+              </ui:link>
+            </li>
+            <li>
+              <a href={url_textblock('arhiva-educationala')}>
+                Arhiva educatională
+              </a>
+            </li>
+            <li><a href={url_textblock('concursuri')}>Concursuri</a></li>
+            <li>
+              <a href={url_textblock('concursuri-virtuale')}>
+                Concursuri virtuale
+              </a>
+            </li>
+            <li><a href={url_textblock('clasament-rating')}>Clasament</a></li>
+            <li><a href={url_textblock('articole')}>Articole</a></li>
+            <li><a href={url_textblock('downloads')}>Downloads</a></li>
+            <li><a href={url_textblock('links')}>Links</a></li>
+            <li><a href={url_textblock('documentatie')}>Documentaţie</a></li>
+            <li>
+              <a href={url_textblock('despre-infoarena')}>Despre infoarena</a>
+            </li>
+            <li class="separator"><hr/></li>
+          </ul>;
+
+        if ($user) {
+            $list->appendChild(
+              <li>
+                <ui:link
+                  href={url_monitor(array('user' => $user['username']))}
+                  accesskey="m">
+                  Monitorul de evaluare
+                </ui:link>
+              </li>);
+            $list->appendChild(
+              <li>
+                <a href={url_submit()}>
+                  <strong>Trimite soluţii</strong>
+                </a>
+              </li>);
+            $list->appendChild(
+              <li>
+                <ui:link href={url_account()} accesskey="c">
+                  Contul meu
+                </ui:link>
+              </li>);
+        } else {
+            $list->appendChild(
+              <li>
+                <ui:link href={url_monitor()} accesskey="m">
+                  Monitorul de evaluare
+                </ui:link>
+              </li>);
+        }
+
+        return $list;
+    }
+}
+
+class :ia:sidebar-ad extends :x:element {
+    children empty;
+
+    protected function render() {
+        $sidebar = textblock_get_revision(IA_SIDEBAR_PAGE);
+        if (!$sidebar) {
+            return <x:frag />;
+        }
+
+        return
+          <div class="ad">
+            <div class="wiki_text_block">
+              {HTML(wiki_process_textblock($sidebar))}
+            </div>
+          </div>;
+    }
+}
+
+class :ia:sidebar-login extends :x:element {
+    attribute
+        bool show_login_form = true;
+    children empty;
+
+    protected function render() {
+        if ($this->getAttribute('show_login_form')) {
+            $form = <ia:login-form />;
+        } else {
+            $form = <x:frag />;
+        }
+
+        $extra =
+          <p>
+            <ui:link href={url_register()}>Mă înregistrez!</ui:link>
+            <br />
+            <ui:link href={url_resetpass()}>Mi-am uitat parola...</ui:link>
+          </p>;
+
+        return
+          <div id="login">
+            {$form}
+            {$extra}
+          </div>;
+    }
+}
Index: www/xhp/ia/sitewide.php
new file mode 100644
===================================================================
--- www/xhp/ia/sitewide.php	(revision 0)
+++ www/xhp/ia/sitewide.php	(working copy)
@@ -0,0 +1,191 @@
+<?php
+// Contains important XHP objects that are needed to render the website's
+// frame, such as the website header, footer and navigation bar.
+
+require_once(IA_ROOT_DIR . 'www/xhp/ui/link.php');
+
+class :ia:header:userbox extends :x:element {
+    attribute
+        array user      @required;
+    children empty;
+
+    protected function render() {
+        $user = $this->getAttribute('user');
+        $username = $user['username'];
+
+        return
+          <div id="userbox">
+            <ui:link href={url_user_profile($username, true)}>
+              {HTML(format_user_avatar($username, "normal", true))}
+            </ui:link>
+            <div class="user">
+              <strong>{$user['full_name']}</strong><br />
+              {HTML(format_user_ratingbadge($username, $user['rating_cache']))}&nbsp;<ui:link href={url_user_profile($username, true)} accesskey="p">{$username}</ui:link><br />
+              {HTML(format_post_link(url_logout(), "logout", array(), true, array('class' => 'logout')))} |
+              <ui:link href={url_account()} accesskey="c">contul meu</ui:link>
+            </div>
+          </div>;
+    }
+}
+
+class :ia:header extends :x:element {
+    attribute
+        array user;
+    children empty;
+
+    protected function render() {
+        $header = <div id="header" class="clear" />;
+
+        $user = $this->getAttribute('user');
+        if ($user) {
+            $header->appendChild(<ia:header:userbox user={$user} />);
+        }
+
+        if (IA_DEVELOPMENT_MODE) {
+            $header->appendChild(
+              <div id="dev_warning">
+                Bravely working in development mode&hellip;<br/>Keep it up!
+              </div>);
+        }
+
+        $header->appendChild(
+          <h1>
+            <ui:link href={url_home()}>
+              infoarena informatica de performanta
+            </ui:link>
+          </h1>);
+
+        return $header;
+    }
+}
+
+class :ia:top-navbar extends :x:element {
+    attribute
+        array user,
+        int user_pm_count = 0,
+        string selected = "infoarena";
+    children empty;
+
+    protected function render() {
+        $fields = array(
+          'infoarena' =>
+            <ui:link href={url_home()}>info<em>arena</em></ui:link>,
+          'blog' => <ui:link href={url_blog()} accesskey="b">blog</ui:link>,
+          'forum' => <ui:link href={url_forum()} accesskey="f">forum</ui:link>,
+          'calendar' =>
+            <ui:link href={url_forum() . '?action=calendar'}>
+              calendar
+            </ui:link>,
+        );
+
+        $user = $this->getAttribute('user');
+        if (!$user) {
+            $fields['login'] =
+              <ui:link href={url_login()}>autentificare</ui:link>;
+            $fields['register'] =
+              <ui:link href={url_login()}>inregistrare</ui:link>;
+        } else {
+            $fields['profile'] =
+              <ui:link href={url_user_profile($user['username'])}
+                accesskey="p">profilul meu</ui:link>;
+
+            $user_pm_count = $this->getAttribute('user_pm_count');
+            if ($user_pm_count) {
+                $pm_content = <strong>mesaje ({$user_pm_count})</strong>;
+            } else {
+                $pm_content = 'mesaje';
+            }
+            $fields['pm'] =
+              <ui:link href={url_forum() . '?action=pm'}>
+                {$pm_content}
+              </ui:link>;
+
+            if ($user['security_level'] === 'admin') {
+                $fields['smf_admin'] =
+                  <ui:link href={url_forum() . '?action=admin'}>
+                    forum admin
+                  </ui:link>;
+            }
+        }
+
+        $selected = $this->getAttribute('selected');
+        $list = <ul />;
+        foreach ($fields as $name => $content) {
+            if ($selected === $name) {
+                $content = <strong>{$content}</strong>;
+            }
+            $list->appendChild(<li>{$content}</li>);
+        }
+
+        return
+          <div id="topnav">
+            {$list}
+          </div>;
+    }
+}
+
+class :ia:footer extends :x:element {
+    children empty;
+
+    protected function render() {
+        $elem =
+          <div id="footer">
+            <ul class="clear">
+              <li class="copyright">&copy;&nbsp;2004-{date("Y")}&nbsp;<ui:link href={url_textblock('Asociatia-infoarena')}>Asociatia infoarena</ui:link></li>
+              <li class="separate">
+                <ui:link href={url_home()}>Prima pagina</ui:link>
+              </li>
+              <li>
+                <ui:link href={url_textblock('despre-infoarena')}>
+                  Despre infoarena
+                </ui:link>
+              </li>
+              <li>
+                <ui:link href={url_textblock('termeni-si-conditii')}>
+                  Termeni si conditii
+                </ui:link>
+              </li>
+              <li>
+                <ui:link href={url_textblock('contact')}>Contact</ui:link>
+              </li>
+              <li class="top">
+                <a href="#header">Sari la inceputul paginii &uarr;</a>
+              </li>
+            </ul>
+          </div>;
+
+        if (!IA_DEVELOPMENT_MODE) {
+            $elem->appendChild(
+            <p class="cc">
+              {HTML('<!--Creative Commons License-->')}
+              <a class="badge" rel="license" href="http://creativecommons.org/licenses/by-nc/2.5/"><img alt="Creative Commons License" src={url_static('images/CreativeCommonsBadge.png')} /></a>
+              Cu exceptia cazurilor in care se specifica altfel, continutul site-ului infoarena<br/>este publicat sub licenta <a rel="license" href="http://creativecommons.org/licenses/by-nc/2.5/">Creative Commons Attribution-NonCommercial 2.5</a>.
+              {HTML('<!--/Creative Commons License-->
+                <rdf:RDF xmlns="http://web.resource.org/cc/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:rdfs="http://www.w3.org/2000/01/rdf-schema#">
+                  <Work rdf:about="">
+                    <license rdf:resource="http://creativecommons.org/licenses/by-nc/2.5/" />
+                  </Work>
+                  <License rdf:about="http://creativecommons.org/licenses/by-nc/2.5/">
+                    <permits rdf:resource="http://web.resource.org/cc/Reproduction"/>
+                    <permits rdf:resource="http://web.resource.org/cc/Distribution"/>
+                    <requires rdf:resource="http://web.resource.org/cc/Notice"/>
+                    <requires rdf:resource="http://web.resource.org/cc/Attribution"/>
+                    <prohibits rdf:resource="http://web.resource.org/cc/CommercialUse"/>
+                    <permits rdf:resource="http://web.resource.org/cc/DerivativeWorks"/>
+                  </License>
+                </rdf:RDF>')}
+            </p>);
+
+            $elem->appendChild(
+              <script src="http://www.google-analytics.com/urchin.js" type="text/javascript" />);
+            $elem->appendChild(
+              <script type="text/javascript">
+                _uacct = 'UA-113289-8';
+                _udn = 'infoarena.ro';
+                urchinTracker();
+              </script>);
+        }
+
+        return $elem;
+    }
+}
Index: www/xhp/ia/user_count.php
new file mode 100644
===================================================================
--- www/xhp/ia/user_count.php	(revision 0)
+++ www/xhp/ia/user_count.php	(working copy)
@@ -0,0 +1,12 @@
+<?php
+
+class :ia:user-count extends :x:element {
+    children empty;
+
+    protected function render() {
+        return
+          <p class="user-count">
+            {user_count()} membri înregistraţi
+          </p>;
+    }
+}
Index: www/xhp/ui/base.php
new file mode 100644
===================================================================
--- www/xhp/ui/base.php	(revision 0)
+++ www/xhp/ui/base.php	(working copy)
@@ -0,0 +1,6 @@
+<?php
+
+class :ui:element extends :x:element {
+    // TODO: facebook was doing cool stuff with CSS margin and padding in ui
+    // elements
+}
Index: www/xhp/ui/breadcrumbs.php
new file mode 100644
===================================================================
--- www/xhp/ui/breadcrumbs.php	(revision 0)
+++ www/xhp/ui/breadcrumbs.php	(working copy)
@@ -0,0 +1,42 @@
+<?php
+
+require_once(IA_ROOT_DIR . 'www/xhp/ui/base.php');
+
+class :ui:breadcrumbs extends :ui:element {
+    attribute
+        array entries,
+        string current,
+        string title = "Pagini recente";
+    children empty;
+
+    protected function render() {
+        $entries = $this->getAttribute('entries');
+        $current = $this->getAttribute('current');
+
+        if (count($entries) <= 1) {
+            return <x:frag />;
+        }
+
+        $elem =
+          <div class="breadcrumbs">
+            {$this->getAttribute('title')} &raquo;
+          </div>;
+        $first = true;
+        foreach ($entries as $key => $entry) {
+            list($url, $title) = $entry;
+
+            if (!$first) {
+                $elem->appendChild(<span class="separator"> | </span>);
+            } else {
+                $first = false;
+            }
+
+            if ($current == $key) {
+                $elem->appendChild(<strong>{$title}</strong>);
+            } else {
+                $elem->appendChild(<a href={$url}>{$title}</a>);
+            }
+        }
+        return $elem;
+    }
+}
Index: www/xhp/ui/flash_message.php
new file mode 100644
===================================================================
--- www/xhp/ui/flash_message.php	(revision 0)
+++ www/xhp/ui/flash_message.php	(working copy)
@@ -0,0 +1,15 @@
+<?php
+
+require_once(IA_ROOT_DIR . 'www/xhp/ui/base.php');
+
+class :ui:flash-message extends :ui:element {
+    attribute
+        string class;
+
+    protected function render() {
+        return
+          <div class={'flash ' . $this->getAttribute('class')}>
+            {$this->getChildren()}
+          </div>;
+    }
+}
Index: www/xhp/ui/link.php
new file mode 100644
===================================================================
--- www/xhp/ui/link.php	(revision 0)
+++ www/xhp/ui/link.php	(working copy)
@@ -0,0 +1,27 @@
+<?php
+
+require_once(IA_ROOT_DIR . 'www/xhp/ui/base.php');
+
+class :ui:link extends :ui:element {
+    attribute
+        bool highlight_accesskey = true,    // Whether or not to highlight the
+                                            // link's accesskey if specified.
+        :a;
+
+    protected function render() {
+        $elem = <a>{$this->getChildren()}</a>;
+
+        $accesskey = $this->getAttribute('accesskey');
+        if ($accesskey && $this->getAttribute('highlight_accesskey')) {
+            // This assumes that no HTML tags are present inside the link.
+            // If these are present, they will be escaped.
+            $content = (string)<x:frag>{$this->getChildren()}</x:frag>;
+            $elem = <a>{format_highlight_access_key($content, $accesskey)}</a>;
+        }
+
+        foreach ($this->getAttributes() as $key => $value) {
+            $elem->setAttribute($key, $value);
+        }
+        return $elem;
+    }
+}
