--- Makefile	(revision 0)
+++ Makefile	(working copy)
@@ -0,0 +1,15 @@
+.PHONY: hphp-build clean-cache clean-hphp clean
+
+hphp-build:
+	mkdir -p hphp/build/
+	find common/ www/ eval/ hphp/ config.php -name "*.php" > hphp/build/filelist
+	hphp --input-list=hphp/build/filelist -o hphp/build/ --program infoarena -l 3 --cluster-count 8
+
+clean-cache:
+	find cache/ -type f -exec rm {} +
+	rm -rf www/static/images/{latex,tmp}/*
+
+clean-hphp:
+	rm -rf hphp/build/*
+
+clean: clean-cache clean-hphp
Index: common/cache.php
===================================================================
--- common/cache.php	(revision 1163)
+++ common/cache.php	(working copy)
@@ -143,7 +143,6 @@ function disk_cache_purge() {
 //
 //      mem_cache_purge deletes everything from the cache. Try to avoid calling it.
 //
-// FIXME: cache is not logged. See IA_LOG_MEM_CACHE.
 if (IA_MEM_CACHE_METHOD == 'none') {
 
     // Fake cache implementation/
@@ -258,6 +257,47 @@ if (IA_MEM_CACHE_METHOD == 'none') {
             log_print("MEM CACHE: purge");
         }
     }
+
+} else if (IA_MEM_CACHE_METHOD == 'apc') {
+    // APC cache implementation
+    function mem_cache_get($cache_id) {
+        $res = apc_fetch($cache_id);
+        if ($res === false) {
+            if (IA_LOG_MEM_CACHE) {
+                log_print("MEM CACHE: miss on $cache_id");
+            }
+            return false;
+        } else {
+            if (IA_LOG_MEM_CACHE) {
+                log_print("MEM CACHE: hit on $cache_id");
+            }
+            return unserialize($res);
+        }
+    }
+
+    function mem_cache_set($cache_id, $object, $ttl = IA_MEM_CACHE_EXPIRATION) {
+        log_assert($object !== 'false', "Can't cache false values");
+        apc_store($cache_id, serialize($object), $ttl);
+
+        if (IA_LOG_MEM_CACHE) {
+            log_print("MEM CACHE: store $cache_id");
+        }
+        return $object;
+    }
+
+    function mem_cache_delete($cache_id) {
+        apc_delete($cache_id);
+        if (IA_LOG_MEM_CACHE) {
+            log_print("MEM CACHE: delete $cache_id");
+        }
+    }
+
+    function mem_cache_purge() {
+        if (IA_LOG_MEM_CACHE) {
+            log_print("MEM CACHE: purge");
+        }
+        apc_clear_cache();
+    }
 }
 
 ?>
Index: common/common.php
===================================================================
--- common/common.php	(revision 1163)
+++ common/common.php	(working copy)
@@ -331,7 +331,7 @@ function check_requirements()
     }
 
     // Check for retarded php.ini settings.
-    if (IA_HTTP_ENV) {
+    if (IA_HTTP_ENV && !defined('IA_HPHP_ENV')) {
         log_assert(!ini_get("session.auto_start"),
                    "Please disable session.auto_start. It kills babies!");
         log_assert(ini_get("session.use_cookies"),
Index: common/db/attachment.php
===================================================================
--- common/db/attachment.php	(revision 1163)
+++ common/db/attachment.php	(working copy)
@@ -150,8 +150,8 @@ function attachment_delete_by_id($attid) {
 //
 // You may use % as a wildcard
 function attachment_get_all($page, $name='%', $start = 0, $count = 99999999) {
-    assert(is_whole_number($start));
-    assert(is_whole_number($count));
+    log_assert(is_whole_number($start));
+    log_assert(is_whole_number($count));
     $query = sprintf("SELECT ia_file.*, ia_user.username, ia_user.full_name as user_fullname
                       FROM ia_file
                       LEFT JOIN ia_user ON ia_user.id = ia_file.user_id
@@ -164,8 +164,8 @@ function attachment_get_all($page, $name='%', $start = 0, $count = 99999999) {
 
 // _count for the above.
 function attachment_get_count($page, $name='%', $start = 0, $count = 99999999) {
-    assert(is_whole_number($start));
-    assert(is_whole_number($count));
+    log_assert(is_whole_number($start));
+    log_assert(is_whole_number($count));
     $query = sprintf("SELECT COUNT(*)
                       FROM ia_file
                       LEFT JOIN ia_user ON ia_user.id = ia_file.user_id
@@ -183,7 +183,7 @@ function attachment_get_count($page, $name='%', $start = 0, $count = 99999999) {
 // with the judge since it`s dependent on the www server setup.
 // FIXME: does this belong here?
 function attachment_get_filepath($attach) {
-    assert(is_array($attach));
+    log_assert(is_array($attach));
     return IA_ROOT_DIR.'attach/'.
             strtolower(preg_replace('/[^a-z0-9\.\-_]/i', '_', $attach['page'])) . '_' .
             preg_replace('/[^a-z0-9\.\-_]/i', '_', $attach['name']) . '_' .
Index: common/textblock.php
===================================================================
--- common/textblock.php	(revision 1163)
+++ common/textblock.php	(working copy)
@@ -151,9 +151,10 @@ function textblock_validate($tb) {
 // Use this like textblock_copy_replace('template/newtask', 'problema/capsuni');
 function textblock_copy_replace($srcprefix, $dstprefix, $replace, $security,
         $user_id, $remote_ip_info = null) {
-    assert($srcprefix != $dstprefix);
-    assert($security === null || is_textblock_security_descriptor($security));
-    assert(is_whole_number($user_id));
+    log_assert($srcprefix != $dstprefix);
+    log_assert($security === null ||
+               is_textblock_security_descriptor($security));
+    log_assert(is_whole_number($user_id));
 
     $textblocks = textblock_get_by_prefix($srcprefix, true, false);
     foreach ($textblocks as $textblock) {
Index: hphp/config.hdf.sample
new file mode 100644
===================================================================
--- hphp/config.hdf.sample	(revision 0)
+++ hphp/config.hdf.sample	(working copy)
@@ -0,0 +1,84 @@
+PidFile = /var/infoarena/hphp_pid
+
+Log {
+  Level = Info
+
+  UseLogFile = true
+  File = /var/infoarena/hphp_error_log
+
+  Access {
+    * {
+      File = /var/infoarena/hphp_access_log
+    }
+  }
+}
+
+Server {
+  Port = 8000
+  ThreadCount = 50
+
+  SourceRoot = --write-me-IA_ROOT_DIR--
+  IncludeSearchPaths {
+    * = --write-me-IA_ROOT_DIR--www/
+  }
+
+  RequestTimeoutSeconds = 30
+  RequestMemoryMaxBytes = 67108864
+  EnableMemoryManager = true
+  MaxPostSize = 65
+
+  FatalErrorMessage = Something went terribly wrong... Check back :)
+
+  GzipCompressionLevel = 3
+  EnableKeepAlive = true
+  EnableEarlyFlush = true
+  ForceChunkedEncoding = false
+  APC {
+    EnableApc = true
+  }
+}
+
+VirtualHost {
+  default {
+    PathTranslation = hphp/endpoint/
+
+    RewriteRules {
+      news_redirect {
+        pattern = ^/stiri/(.*)$
+        to = /blog/$1
+        qsa = true
+        redirect = 301
+      }
+
+      news_feed_redirect {
+        pattern = ^/news_feed$
+        to = /blog?action=rss
+        qsa = true
+        redirect = 301
+      }
+
+      www {
+        pattern = ^/(.*)$
+        to = index.php?page=$1
+        qsa = true
+
+        conditions {
+          static_files {
+            pattern = ^/static/.*$
+            negate = true
+          }
+
+          robots {
+            pattern = ^/robots\.txt$
+            negate = true
+          }
+
+          favicon {
+            pattern = ^/favicon\.ico$
+            negate = true
+          }
+        }
+      }
+    }
+  }
+}
Index: hphp/endpoint/index.php
new file mode 100644
===================================================================
--- hphp/endpoint/index.php	(revision 0)
+++ hphp/endpoint/index.php	(working copy)
@@ -0,0 +1,7 @@
+<?php
+
+define('IA_HPHP_ENV', true);
+
+require_once($_SERVER['DOCUMENT_ROOT'] . '/../../config.php');
+
+require_once(IA_ROOT_DIR . 'www/index.php');
Index: www/config.php
===================================================================
--- www/config.php	(revision 1163)
+++ www/config.php	(working copy)
@@ -15,7 +15,7 @@ define("IA_CLIENT_CACHE_ENABLE", true);
 define("IA_CLIENT_CACHE_AGE", 604800);
 
 // maximum attachment size for wiki pages
-define("IA_ATTACH_MAXSIZE", 70*1024*1024);
+define("IA_ATTACH_MAXSIZE", 64*1024*1024);
 
 // maximum jobs to reeval
 define("IA_REEVAL_MAXJOBS", 512);
Index: www/format/pager.php
===================================================================
--- www/format/pager.php	(revision 1163)
+++ www/format/pager.php	(working copy)
@@ -126,9 +126,9 @@ function format_standard_pager($options)
     $surround_pages = getattr($options, 'surround_pages', 5);
     $access_keys = getattr($options, 'use_digit_access_keys', true);
 
-    assert(is_whole_number($display_entries));
-    assert(is_whole_number($first_entry));
-    assert(is_whole_number($total_entries));
+    log_assert(is_whole_number($display_entries));
+    log_assert(is_whole_number($first_entry));
+    log_assert(is_whole_number($total_entries));
 
     $curpage = (int)($first_entry / $display_entries);
     $totpages = (int)(($total_entries + $display_entries - 1) / $display_entries);
Index: www/htaccess.sample
===================================================================
--- www/htaccess.sample	(revision 1163)
+++ www/htaccess.sample	(working copy)
@@ -33,7 +33,6 @@ php_value error_reporting 65535
 php_value display_errors true
 php_value log_errors true
 php_value html_errors false
-php_value memory_limit "16M"
-php_value post_max_size "71M"
-php_value upload_max_filesize "70M"
-
+php_value memory_limit "64M"
+php_value post_max_size "65M"
+php_value upload_max_filesize "64M"
Index: www/identity.php
===================================================================
--- www/identity.php	(revision 1163)
+++ www/identity.php	(working copy)
@@ -114,7 +114,13 @@ function init_php_session($remember_user = false) {
     } else {
         session_set_cookie_params(0, '/', IA_COOKIE_DOMAIN);
     }
-    session_start();
+    if (defined('IA_HPHP_ENV')) {
+        // FIXME: Raises PHP Warning: Constant SID already defined when
+        // init_php_session is called a second time.
+        @session_start();
+    } else {
+        session_start();
+    }
 }
 
 // identity information from cookie-based session
Index: www/index.php
===================================================================
--- www/index.php	(revision 1163)
+++ www/index.php	(working copy)
@@ -1,5 +1,7 @@
 <?php
-require_once("../config.php");
+if (!defined('IA_HPHP_ENV')) {
+    require_once("../config.php");
+}
 require_once(IA_ROOT_DIR."www/config.php");
 require_once(IA_ROOT_DIR."common/log.php");
 require_once(IA_ROOT_DIR."common/common.php");
Index: www/macros/macro_rankings.php
===================================================================
--- www/macros/macro_rankings.php	(revision 1163)
+++ www/macros/macro_rankings.php	(working copy)
@@ -66,15 +66,15 @@ function macro_rankings($args) {
     $column_infos = array(
         array(
             'title' => 'Pozitie',
-            'key' => 'pos',
-            'rowform' => create_function_cached('$row', 'return $row["ranking"];'),
+            'key' => 'ranking',
             'css_class' => 'number rank'
         ),
         array(
             'title' => 'Nume',
             'key' => 'user_full',
-            'rowform' => create_function_cached('$row',
-                'return format_user_normal($row["user_name"], $row["user_full"], $row["user_rating"]);'),
+            'rowform' => function($row) {
+                return format_user_normal($row['user_name'], $row['user_full'], $row['user_rating']);
+            },
         ),
     );
 
@@ -110,7 +110,9 @@ function macro_rankings($args) {
         array_push($column_infos, array(
             'title' => $column['title'],
             'key' => $column['name'],
-            'rowform' => create_function_cached('$row', 'return round($row[\''.$column['name'].'\']);'),
+            'rowform' => function($row) {
+                return round($row[$column['name']]);
+            },
             'css_class' => 'number score'
         ));
     }
@@ -122,7 +124,9 @@ function macro_rankings($args) {
     array_push($column_infos, array(
         'title' => $total,
         'key' => 'score',
-        'rowform' => create_function_cached('$row', 'return round($row[\'score\']);'),
+        'rowform' => function($row) {
+            return round($row['score']);
+        },
         'css_class' => 'number score'
     ));
 
Index: www/macros/macro_tasks.php
===================================================================
--- www/macros/macro_tasks.php	(revision 1163)
+++ www/macros/macro_tasks.php	(working copy)
@@ -175,8 +175,9 @@ function macro_tasks($args) {
         $column_infos[] = array(
                 'title' => 'Număr',
                 'css_class' => 'number',
-                'rowform' => create_function_cached('$row',
-                        'return str_pad($row["order"] - 1, 3, \'0\', STR_PAD_LEFT);'),
+                'rowform' => function($row) {
+                    return str_pad($row["order"] - 1, 3, '0', STR_PAD_LEFT);
+                },
         );
     }
     $column_infos[] = array(
Index: www/macros/macro_toprated.php
===================================================================
--- www/macros/macro_toprated.php	(revision 1163)
+++ www/macros/macro_toprated.php	(working copy)
@@ -31,13 +31,16 @@ function macro_toprated($args) {
         array(
             'title' => 'Nume',
             'key' => 'full_name',
-            'rowform' => create_function_cached('$row',
-                                         'return format_user_normal($row["username"], $row["full_name"], $row["rating_cache"]);'),
+            'rowform' => function($row) {
+                return format_user_normal($row['username'], $row['full_name'], $row['rating_cache']);
+            },
         ),
         array(
             'title' => 'Rating',
             'key' => 'rating_cache',
-            'rowform' => create_function_cached('$row', 'return rating_scale($row[\'rating_cache\']);'),
+            'rowform' => function($row) {
+                return rating_scale($row['rating_cache']);
+            },
             'css_class' => 'number rating',
         ),
     );
Index: www/utilities.php
===================================================================
--- www/utilities.php	(revision 1163)
+++ www/utilities.php	(working copy)
@@ -241,7 +241,6 @@ function execute_view($view_file_name, $view) {
     // NOTE: no includes here, unless you want to get
     // warnings about function redeclaration.
     include($view_file_name);
-    //include('views/vardump.php');
 }
 
 // Execute view and then die.
Index: www/views/json.php
===================================================================
--- www/views/json.php	(revision 1163)
+++ www/views/json.php	(working copy)
@@ -4,7 +4,7 @@ require_once(IA_ROOT_DIR.'www/JSON.php');
 
 // encode JSON
 $json = new Services_JSON();
-assert($view['json']);
+log_assert($view['json']);
 $output = $json->encode($view['json']);
 
 // serve JSON
Index: www/views/listattach.php
===================================================================
--- www/views/listattach.php	(revision 1163)
+++ www/views/listattach.php	(working copy)
@@ -1,17 +1,17 @@
-<?php 
+<?php
 include('header.php');
 require_once(IA_ROOT_DIR . "www/format/table.php");
 require_once(IA_ROOT_DIR . "www/format/format.php");
 
 ?>
-    
+
 <script type="text/javascript">
     function rename_form(id) {
         if (document.getElementById("rename_"+id).style.display == "none") {
             document.getElementById("rename_"+id).style.display = "inline";
             document.getElementById("link_"+id).style.display = "none";
             document.getElementById("rename_link_"+id).textContent = "Anuleaza";
-        } 
+        }
         else {
             document.getElementById("rename_"+id).style.display = "none";
             document.getElementById("link_"+id).style.display = "inline";
@@ -72,7 +72,7 @@ function format_ip($row) {
 
 function format_operations($row) {
     global $page_name;
-    
+
     $delurl = format_post_link(url_attachment_delete($page_name, $row['name']),
                                "Sterge", array(), true,
                                array("onclick" => "return confirm('Aceasta actiune este ireversibila! Doresti sa continui?')"));
@@ -102,8 +102,9 @@ $column_infos = array(
     array(
         'title' => 'Utilizator',
         'key' => 'username',
-        'rowform' => create_function_cached('$row',
-                'return format_user_tiny($row["username"], $row["user_fullname"]);'),
+        'rowform' => function($row) {
+            return format_user_tiny($row['username'], $row['user_fullname']);
+        },
     ),
     array(
         'title' => 'Marime',
Index: www/views/monitor.php
===================================================================
--- www/views/monitor.php	(revision 1163)
+++ www/views/monitor.php	(working copy)
@@ -151,8 +151,9 @@ if (!$jobs) {
         array(
             'title' => 'Utilizator',
             'key' => 'username',
-            'rowform' => create_function_cached('$row',
-                 'return format_user_tiny($row["user_name"], $row["user_fullname"]);'),
+            'rowform' => function($row) {
+                return format_user_tiny($row['user_name'], $row['user_fullname']);
+            },
         ),
         array(
             'title' => 'Problema',
Index: www/views/projector.php
===================================================================
--- www/views/projector.php	(revision 1163)
+++ www/views/projector.php	(working copy)
@@ -88,8 +88,9 @@ if (!$jobs) {
         array(
             'title' => 'Utilizator',
             'key' => 'username',
-            'rowform' => create_function_cached('$row',
-                 'return format_user_tiny($row["user_name"], $row["user_fullname"]);'),
+            'rowform' => function($row) {
+                 return format_user_tiny($row['user_name'], $row['user_fullname']);
+            },
         ),
         array(
             'title' => 'Problema',
Index: www/views/round_edit.php
===================================================================
--- www/views/round_edit.php	(revision 1163)
+++ www/views/round_edit.php	(working copy)
@@ -11,13 +11,13 @@ $view['head'] .= "<script type=\"text/javascript\" src=\"" . html_escape(url_sta
 require_once(IA_ROOT_DIR."common/round.php");
 require_once(IA_ROOT_DIR."www/format/form.php");
 require_once(IA_ROOT_DIR."www/views/round_edit_header.php");
-include('views/header.php');
+include('header.php');
 
 echo round_edit_tabs($view['round_id'], 'round-edit-params');
 
 $can_tag = identity_can('round-tag', $round);
 if ($can_tag) {
-    include('views/tags_header.php');
+    include('tags_header.php');
 }
 
 // Validate $view values.
Index: www/views/round_register.php
===================================================================
--- www/views/round_register.php	(revision 1163)
+++ www/views/round_register.php	(working copy)
@@ -1,5 +1,5 @@
 <?php
-include('views/header.php');
+include('header.php');
 ?>
 
 <h1>Inregistrare la <?= format_link(url_textblock($round['page_name']), $round['title']) ?></h1>
Index: www/views/round_register_view.php
===================================================================
--- www/views/round_register_view.php	(revision 1163)
+++ www/views/round_register_view.php	(working copy)
@@ -14,17 +14,20 @@ else {
     $column_infos = array(
         array(
             'title' => 'Pozitie',
-            'rowform' => create_function_cached('$row', 'return $row["position"];'),
+            'key' => 'position',
             'css_class' => 'number rank',
         ),
         array(
             'title' => 'Nume',
-            'rowform' => create_function_cached('$row',
-                                         'return format_user_normal($row["username"], $row["fullname"], $row["rating"]);'),
+            'rowform' => function($row) {
+                return format_user_normal($row['username'], $row['fullname'], $row['rating']);
+            },
         ),
         array(
             'title' => 'Rating',
-            'rowform' => create_function_cached('$row', 'return rating_scale($row["rating"]);'),
+            'rowform' => function($row) {
+                return rating_scale($row['rating']);
+            },
             'css_class' => 'number rating'
         ),
     );
Index: www/views/round_task_order.php
===================================================================
--- www/views/round_task_order.php	(revision 1163)
+++ www/views/round_task_order.php	(working copy)
@@ -3,7 +3,7 @@ require_once(IA_ROOT_DIR."common/round.php");
 require_once(IA_ROOT_DIR."www/format/form.php");
 require_once(IA_ROOT_DIR."www/views/round_edit_header.php");
 require_once(IA_ROOT_DIR."www/macros/macro_tasks.php");
-include("views/header.php");
+include('header.php');
 
 echo round_edit_tabs($view['round_id'], 'round-edit-task-order');
 ?>
Index: www/views/round_unregister.php
===================================================================
--- www/views/round_unregister.php	(revision 1163)
+++ www/views/round_unregister.php	(working copy)
@@ -1,5 +1,5 @@
 <?php
-include('views/header.php');
+include('header.php');
 ?>
 
 <h1>Deinregistrare de la <?= format_link(url_textblock($round['page_name']), $round['title']) ?></h1>
Index: www/views/task_edit.php
===================================================================
--- www/views/task_edit.php	(revision 1163)
+++ www/views/task_edit.php	(working copy)
@@ -7,8 +7,8 @@ require_once(IA_ROOT_DIR."www/views/task_edit_header.php");
 $view['head'] = getattr($view, 'head').
     "<script type=\"text/javascript\" src=\"" . html_escape(url_static("js/parameditor.js")) . "\"></script>";
 
-include('views/header.php');
-include('views/tags_header.php');
+include('header.php');
+include('tags_header.php');
 
 echo task_edit_tabs($view['task_id'], request("action"));
 
Index: www/views/task_filter_results.php
===================================================================
--- www/views/task_filter_results.php	(revision 1163)
+++ www/views/task_filter_results.php	(working copy)
@@ -108,8 +108,9 @@ $column_infos = array();
 $column_infos[] = array(
         'title' => 'Număr',
         'css_class' => 'number',
-        'rowform' => create_function_cached('$row',
-        'return str_pad($row["order"] - 1, 3, \'0\', STR_PAD_LEFT);'));
+        'rowform' => function($row) {
+            return str_pad($row["order"] - 1, 3, '0', STR_PAD_LEFT);
+        });
 
 $column_infos[] = array(
         'title' => 'Titlul problemei',
Index: www/views/task_rating_edit.php
===================================================================
--- www/views/task_rating_edit.php	(revision 1163)
+++ www/views/task_rating_edit.php	(working copy)
@@ -3,7 +3,7 @@
 require_once(IA_ROOT_DIR . "www/format/form.php");
 require_once(IA_ROOT_DIR . "www/views/task_edit_header.php");
 
-include('views/header.php');
+include('header.php');
 
 echo task_edit_tabs($view['task_id'], request("action"));
 
@@ -52,4 +52,4 @@ $form_fields = array(
 </div>
 </form>
 
-<?php include('views/footer.php');
+<?php include('footer.php');
Index: www/views/textblock_edit.php
===================================================================
--- www/views/textblock_edit.php	(revision 1163)
+++ www/views/textblock_edit.php	(working copy)
@@ -3,8 +3,8 @@
 // link JS
 $view['head'] = getattr($view, 'head')."<script type=\"text/javascript\" src=\"" . html_escape(url_static("js/wikiedit.js")) . "\"></script>";
 
-include('views/header.php');
-include('views/tags_header.php');
+include('header.php');
+include('tags_header.php');
 
 // insert task edit tabs
 if (($task_id = textblock_security_is_task($page['security'])) &&
Index: www/views/textblock_history.php
===================================================================
--- www/views/textblock_history.php	(revision 1163)
+++ www/views/textblock_history.php	(working copy)
@@ -83,8 +83,9 @@ $column_infos = array(
     array(
         'title' => 'Utilizator',
         'key' => 'username',
-        'rowform' => create_function_cached('$row',
-                'return format_user_tiny($row["user_name"], $row["user_fullname"], $row["rating_cache"]);'),
+        'rowform' => function($row) {
+            return format_user_tiny($row['user_name'], $row['user_fullname'], $row['rating_cache']);
+        },
     ),
     array(
         'title' => 'Data',
@@ -118,7 +119,7 @@ $options = array(
     'surround_pages' => 3,
 );
 
-?>                                                         
+?>
 
 <form
     action = "<?php echo html_escape(url_textblock_diff($page_name, null, null)); ?>"
@@ -152,4 +153,4 @@ echo format_table($revisions, $column_infos, $options);
 </div>
 </form>
 
-<?php include('footer.php'); ?> 
+<?php include('footer.php'); ?>
Index: www/wiki/Textile.php
===================================================================
--- www/wiki/Textile.php	(revision 1163)
+++ www/wiki/Textile.php	(working copy)
@@ -772,20 +772,31 @@ class Textile {
     if ($this->options['trim_spaces']) { $str = preg_replace('/ +$/m', '', $str); }
 
     // preserve contents of the '==', 'pre', 'blockcode' sections
+    $me =& $this;
     $str = preg_replace_callback('/( (?<=\n\n)== | (?<=^)== )  (.+?)  ( ==(?=\n\n) | ==(?=$) )  /sx',
-                                 $this->_cb('$me->_repl($me->repl[0], $me->format_block(array("text" => $m[2])))'), $str);
+                                 function($m) use ($me) {
+                                   return $me->_repl($me->repl[0], $me->format_block(array("text" => $m[2])));
+                                 }, $str);
 
     if (!$this->disable_html()) {
       // preserve style, script tag contents
-      $str = preg_replace_callback('!(<(style|script)(?:>| .+?>).*?</\2>)!s', $this->_cb('$me->_repl($me->repl[0], $m[1])'), $str);
+      $str = preg_replace_callback('!(<(style|script)(?:>| .+?>).*?</\2>)!s',
+                                   function($m) use ($me) {
+                                     return $me->_repl($me->repl[0], $m[1]);
+                                   }, $str);
 
       // preserve HTML comments
-      $str = preg_replace_callback('|(<!--.+?-->)|s', $this->_cb('$me->_repl($me->repl[0], $m[1])'), $str);
+      $str = preg_replace_callback('|(<!--.+?-->)|s',
+                                   function($m) use ($me) {
+                                     return $me->_repl($me->repl[0], $m[1]);
+                                   }, $str);
 
       // preserve pre block contents, encode contents by default
       $pre_start = count($this->repl[0]);
       $str = preg_replace_callback('{(<pre(?: [^>]*)?>)(.+?)(</pre>)}s',
-                                   $this->_cb('"\n\n" . $me->_repl($me->repl[0], $m[1] . $me->encode_html($m[2], 1) . $m[3]) . "\n\n"'), $str);
+                                   function($m) use ($me) {
+                                     return "\n\n" . $me->_repl($me->repl[0], $m[1] . $me->encode_html($m[2], 1) . $m[3]) . "\n\n";
+                                   }, $str);
       // fix code tags within pre blocks we just saved.
       for ($i = $pre_start; $i < count($this->repl[0]); $i++) {
         $this->repl[0][$i] = preg_replace('|&lt;(/?)code(.*?)&gt;|s', '<$1code$2>', $this->repl[0][$i]);
@@ -793,16 +804,23 @@ class Textile {
 
       // preserve code blocks by default, encode contents
       $str = preg_replace_callback('{(<code(?: [^>]+)?>)(.+?)(</code>)}s',
-                                   $this->_cb('$me->_repl($me->repl[0], $m[1] . $me->encode_html($m[2], 1) . $m[3])'), $str);
+                                   function($m) use ($me) {
+                                     return $me->_repl($me->repl[0], $m[1] . $me->encode_html($m[2], 1) . $m[3]);
+                                   }, $str);
 
       // encode blockcode tag (an XHTML 2 tag) and encode it's
       // content by default
       $str = preg_replace_callback('{(<blockcode(?: [^>]+)?>)(.+?)(</blockcode>)}s',
-                                   $this->_cb('"\n\n" . $me->_repl($me->repl[0], $m[1] . $me->encode_html($m[2], 1) . $m[3]) . "\n\n"'), $str);
+                                   function($m) use ($me) {
+                                     return "\n\n" . $me->_repl($me->repl[0], $m[1] . $me->encode_html($m[2], 1) . $m[3]) . "\n\n";
+                                   }, $str);
     }
 
     // LaTeX code
-    $str = preg_replace_callback('!((<tex>)(.*?)(<\/tex>))!s', $this->_cb('$me->_repl($me->repl[0], $me->format_latex(array("text" => $m[3])))'), $str);
+    $str = preg_replace_callback('!((<tex>)(.*?)(<\/tex>))!s',
+                                 function($m) use ($me) {
+                                   return $me->_repl($me->repl[0], $me->format_latex(array("text" => $m[3])));
+                                 }, $str);
 
     // pass through and remove links that follow this format
     // [id_without_spaces (optional title text)]url
@@ -810,7 +828,9 @@ class Textile {
     // referred to using the "link text":id_without_spaces syntax
     //$links = array();
     $str = preg_replace_callback('{(?:\n|^) [ ]* \[ ([^ ]+?) [ ]*? (?:\( (.+?) \) )?  \] ((?:(?:ftp|https?|telnet|nntp)://|/)[^ ]+?) [ ]* (\n|$)}mx',
-                                 $this->_cb('($me->links[$m[1]] = array("url" => $m[3], "title" => $m[2])) ? $m[4] : $m[4]'), $str);
+                                 function($m) use ($me) {
+                                   return ($me->links[$m[1]] = array("url" => $m[3], "title" => $m[2])) ? $m[4] : $m[4];
+                                 }, $str);
     //$this->links = $links;
 
     // eliminate starting/ending blank lines
@@ -1031,7 +1051,9 @@ class Textile {
         //$para = preg_replace_callback('{(?:^|(?<=[\s>])|([{[]))
         //                                ==(.+?)==
         //                                (?:$|([\]}])|(?=' . $this->punct . '{1,2}|\s))}sx',
-        //                              $this->_cb('$me->_repl($me->repl[0], $me->format_block(array("text" => $m[2], "inline" => 1, "pre" => $m[1], "post" => $m[3])))'), $para);
+        //                              function($m) use ($me) {
+        //                                return $me->_repl($me->repl[0], $me->format_block(array("text" => $m[2], "inline" => 1, "pre" => $m[1], "post" => $m[3])));
+        //                              }, $para);
         $buffer .= $this->encode_html_basic($para, 1);
         $buffer = preg_replace('/&lt;textile#(\d+)&gt;/', '<textile#$1>', $buffer);
         if ($sticky == 0) {
@@ -1208,10 +1230,13 @@ class Textile {
     $buffer = (isset($args['text']) ? $args['text'] : '');
 
     array_unshift($this->repl, array());
+    $me =& $this;
     $buffer = preg_replace_callback('{(?:^|(?<=[\s>])|([{[]))
                                       ==(.+?)==
                                       (?:$|([\]}])|(?=' . $this->punct . '{1,2}|\s))}sx',
-                                    $this->_cb('$me->_repl($me->repl[0], $me->format_block(array("text" => $m[2], "inline" => 1, "pre" => $m[1], "post" => $m[3])))'), $buffer);
+                                    function($m) use ($me) {
+                                      return $me->_repl($me->repl[0], $me->format_block(array("text" => $m[2], "inline" => 1, "pre" => $m[1], "post" => $m[3])));
+                                    }, $buffer);
 
     unset($tokens);
     if (preg_match('/</', $buffer)) {  // optimization -- no point in tokenizing if we
@@ -1316,7 +1341,11 @@ class Textile {
 
     array_unshift($this->repl, array());
 
-    $text = preg_replace_callback('{' . $this->codere . '}mx', $this->_cb('$me->_repl($me->repl[0], $me->format_code(array("text" => $m[2] . $m[4], "lang" => $m[1] . $m[3])))'), $text);
+    $me =& $this;
+    $text = preg_replace_callback('{' . $this->codere . '}mx',
+                                  function($m) use ($me) {
+                                    return $me->_repl($me->repl[0], $me->format_code(array("text" => $m[2] . $m[4], "lang" => $m[1] . $m[3])));
+                                  }, $text);
 
     // images must be processed before encoding the text since they might
     // have the <, > alignment specifiers...
@@ -1333,7 +1362,10 @@ class Textile {
                                     !                            # closing
                                     (?::(\d+|' . $this->urlre . '))? # $7: optional URL
                                     (?:$|([\]}])|(?=' . $this->punct . '{1,2}|\s)) # $8: closing brace/bracket
-                                   }mx', $this->_cb('$me->_repl($me->repl[0], $me->format_image(array("pre" => $m[1], "src" => $m[5], "align" => ($m[2] ? $m[2] : $m[4]), "extra" => $m[6], "url" => $m[7], "clsty" => $m[3], "post" => $m[8])))'), $text);
+                                   }mx',
+                                  function($m) use ($me) {
+                                    return $me->_repl($me->repl[0], $me->format_image(array("pre" => $m[1], "src" => $m[5], "align" => ($m[2] ? $m[2] : $m[4]), "extra" => $m[6], "url" => $m[7], "clsty" => $m[3], "post" => $m[8])));
+                                  }, $text);
 
     $text = preg_replace_callback('{(?:^|(?<=[\s>])|([{[]))     # $1: open brace/bracket
                                     %                           # opening
@@ -1345,7 +1377,10 @@ class Textile {
                                     %                           # closing
                                     (?::(\d+|' . $this->urlre . '))? # $6: optional URL
                                     (?:$|([]}])|(?=' . $this->punct . '{1,2}|\s)) # $7: closing brace/bracket
-                                   }mx', $this->_cb('$me->_repl($me->repl[0], $me->format_span(array("pre" => $m[1], "text" => $m[5], "align" => ($m[2] ? $m[2] : $m[4]), "cite" => $m[6], "clsty" => $m[3], "post" => $m[7])))'), $text);
+                                   }mx',
+                                  function($m) use ($me) {
+                                    return $me->_repl($me->repl[0], $me->format_span(array("pre" => $m[1], "text" => $m[5], "align" => ($m[2] ? $m[2] : $m[4]), "cite" => $m[6], "clsty" => $m[3], "post" => $m[7])));
+                                  }, $text);
 
     $text = $this->encode_html($text);
     $text = preg_replace('!&lt;textile#(\d+)&gt;!', '<textile#$1>', $text);
@@ -1377,7 +1412,10 @@ class Textile {
                                     :(.+?)                                           # $8: URL suffix
                                     [\]}]
                                    )
-                                   }mx', $this->_cb('$me->_repl($me->repl[0], $me->format_link(array("text" => $m[1], "linktext" => $m[3] . $m[6], "title" => $me->encode_html_basic($m[4] . $m[7]), "url" => $m[8], "clsty" => $m[2] . $m[5])))'), $text);
+                                   }mx',
+                                  function($m) use ($me) {
+                                    return $me->_repl($me->repl[0], $me->format_link(array("text" => $m[1], "linktext" => $m[3] . $m[6], "title" => $me->encode_html_basic($m[4] . $m[7]), "url" => $m[8], "clsty" => $m[2] . $m[5])));
+                                  }, $text);
 
     $text = preg_replace_callback('{((?:^|(?<=[\s>\(]))                              # $1: open brace/bracket
                                     (?: (?:"                                         # quote character "
@@ -1396,7 +1434,10 @@ class Textile {
                                     )
                                     :(\d+|' . $this->urlre . ')                      # $8: URL suffix
                                     (?:$|(?=' . $this->punct . '{1,2}|\s)))          # $9: closing brace/bracket
-                                   }mx', $this->_cb('$me->_repl($me->repl[0], $me->format_link(array("text" => $m[1], "linktext" => $m[3] . $m[6], "title" => $me->encode_html_basic($m[4] . $m[7]), "url" => $m[8], "clsty" => $m[2] . $m[5])))'), $text);
+                                   }mx',
+                                  function($m) use ($me) {
+                                    return $me->_repl($me->repl[0], $me->format_link(array("text" => $m[1], "linktext" => $m[3] . $m[6], "title" => $me->encode_html_basic($m[4] . $m[7]), "url" => $m[8], "clsty" => $m[2] . $m[5])));
+                                  }, $text);
 
     if (preg_match('/^xhtml2/', $this->flavor())) {
       // citation with cite link
@@ -1406,7 +1447,10 @@ class Textile {
                                       \?\?                                           # closing \'??\'
                                       :(\d+|' . $this->urlre . ')                    # $3: optional citation URL
                                       (?:$|([\]}])|(?=' . $this->punct . '{1,2}|\s)) # $4: closing brace/bracket
-                                     }mx', $this->_cb('$me->_repl($me->repl[0], $me->format_cite(array("pre" => $m[1], "text" => $m[2], "cite" => $m[3], "post" => $m[4])))'), $text);
+                                     }mx',
+                                    function($m) use ($me) {
+                                      return $me->_repl($me->repl[0], $me->format_cite(array("pre" => $m[1], "text" => $m[2], "cite" => $m[3], "post" => $m[4])));
+                                    }, $text);
     }
 
     // footnotes
@@ -1419,7 +1463,9 @@ class Textile {
 
     // translate macros:
     $text = preg_replace_callback('{(\{)(.+?)(\})}x',
-                                  $this->_cb('$me->format_macro(array("pre" => $m[1], "post" => $m[3], "macro" => $m[2]))'), $text);
+                                  function($m) use ($me) {
+                                    return $me->format_macro(array("pre" => $m[1], "post" => $m[3], "macro" => $m[2]));
+                                  }, $text);
 
     // these were present with textile 1 and are common enough
     // to not require macro braces...
@@ -1449,7 +1495,10 @@ class Textile {
                                                       ([^' . $cls . '\s].*?)                         # $3 - content
                                                       (?<=\S)' . $qf . '                             #
                                                       (?:$|([\]}])|(?=' . $this->punct . '{1,2}|\s)) # $4 - post
-                                                     }mx', $this->_cb('$me->format_tag(array("tag" => end($me->tmp["r"]), "marker" => end($me->tmp["f"]), "pre" => $m[1], "text" => $m[3], "clsty" => $m[2], "post" => $m[4]))'), $text))) {
+                                                     }mx',
+                                                    function($m) use ($me) {
+                                                      return $me->format_tag(array("tag" => end($me->tmp["r"]), "marker" => end($me->tmp["f"]), "pre" => $m[1], "text" => $m[3], "clsty" => $m[2], "post" => $m[4]));
+                                                    }, $text))) {
           $redo = ($redo || ($last != $text));
           $last = $text;
         }
@@ -1462,14 +1511,19 @@ class Textile {
 
     // ABC(Aye Bee Cee) -> acronym
     $text = preg_replace_callback('{\b([A-Z][A-Za-z0-9]*?[A-Z0-9]+?)\b(?:[(]([^)]*)[)])}',
-                                  $this->_cb('$me->_repl($me->repl[0],"<acronym title=\"" . $me->encode_html_basic($m[2]) . "\">$m[1]</acronym>")'), $text);
+                                  function($m) use ($me) {
+                                    return $me->_repl($me->repl[0],"<acronym title=\"" . $me->encode_html_basic($m[2]) . "\">$m[1]</acronym>");
+                                  }, $text);
 
     // ABC -> 'capped' span
     if ($this->tmp['caps'][] = $this->options['css']['class_caps']) {
       $text = preg_replace_callback('/(^|[^"][>\s])  # "
                                       ((?:[A-Z](?:[A-Z0-9\.,\']|\&amp;){2,}\ *)+?) # \'
                                       (?=[^A-Z\.0-9]|$)
-                                     /mx', $this->_cb('$m[1] . $me->_repl($me->repl[0], "<span class=\"" . end($me->tmp["caps"]) . "\">$m[2]</span>")'), $text);
+                                     /mx',
+                                    function($m) use ($me) {
+                                      return $m[1] . $me->_repl($me->repl[0], "<span class=\"" . end($me->tmp["caps"]) . "\">$m[2]</span>");
+                                    }, $text);
     }
     array_pop($this->tmp['caps']);
 
@@ -2101,7 +2155,11 @@ class Textile {
     }
     $url = preg_replace('/&(?!amp;)/', '&amp;', $url);
     $url = preg_replace('/\ /', '+', $url);
-    $url = preg_replace_callback('/^((?:.+?)\?)(.+)$/', $this->_cb('$m[1] . $me->encode_url($m[2])'), $url);
+    $me =& $this;
+    $url = preg_replace_callback('/^((?:.+?)\?)(.+)$/',
+                                 function($m) use ($me) {
+                                   return $m[1] . $me->encode_url($m[2]);
+                                 }, $url);
     return $url;
   } // function format_url
 
@@ -2628,6 +2686,8 @@ class Textile {
    * @private
    */
   function apply_filters($args) {
+    log_error("Filters are not supported in infoarena's fork of Textile.php " .
+              "because they use old-style anonymous functions.");
     $text = $args['text'];
     if (!$text) { return ''; }
     $list = $args['filters'];
@@ -2638,7 +2698,7 @@ class Textile {
     foreach ($list as $filter) {
       if (!isset($filters[$filter])) { continue; }
       if (is_string($filters[$filter])) {
-        $text = (($f = create_function_cached('$text, $param', $filters[$filter])) ? $f($text, $param) : $text);
+        $text = (($f = create_function('$text, $param', $filters[$filter])) ? $f($text, $param) : $text);
       }
     }
     return $text;
@@ -2768,9 +2828,11 @@ class Textile {
    * @private
    */
   function encode_url($str) {
+    $me =& $this;
     $str = preg_replace_callback('!([^A-Za-z0-9_\.\-\+\&=%;])!x',
-                            $this->_cb('ord($m[1]) > 255 ? \'%u\' . sprintf("%04X", ord($m[1]))
-                                                       : \'%\'  . sprintf("%02X", ord($m[1]))'), $str);
+                                 function($m) use ($me) {
+                                   return ord($m[1]) > 255 ? '%u' . sprintf("%04X", ord($m[1])) : '%'  . sprintf("%02X", ord($m[1]));
+                                 }, $str);
     return $str;
   } // function encode_url
 
@@ -2785,9 +2847,11 @@ class Textile {
    */
   function mail_encode($addr) {
     // granted, this is simple, but it gives off warm fuzzies
+    $me =& $this;
     $addr = preg_replace_callback('!([^\$])!x',
-                             $this->_cb('ord($m[1]) > 255 ? \'%u\' . sprintf("%04X", ord($m[1]))
-                                                        : \'%\'  . sprintf("%02X", ord($m[1]))'), $addr);
+                                  function($m) use ($me) {
+                                    return ord($m[1]) > 255 ? '%u' . sprintf("%04X", ord($m[1])) : '%'  . sprintf("%02X", ord($m[1]));
+                                  }, $addr);
     return $addr;
   } // function mail_encode
 
@@ -3240,64 +3304,6 @@ class Textile {
      */
     return array("text" => "2.0.8", "build" => 2005032100);
   } // function version
-
-/**
-   * Creates a custom callback function from the provided PHP
-   * code. The result is used as the callback in
-   * @c preg_replace_callback calls. *JHR*
-   *
-   * @param $function A @c string specifying the PHP code for the
-   *        function body.
-   *
-   * @return A @c function to be used for the callback.
-   *
-   * @private
-   */
-  function _cb($function) {
-    $current =& Textile::_current_store($this);
-    return create_function_cached('$m',
-            '$me =& Textile::_current(); return '.$function .';');
-  } // function _cb
-
-  /**
-   * Stores a static variable for the Textile class. This helper
-   * function is used by @c _current to simulate a static
-   * class variable in PHP. *JHR*
-   *
-   * @param $new If a non-@c NULL object reference, the Textile object
-   *        to be set as the current object.
-   *
-   * @return The @c array containing a reference to the current
-   *         Textile object at index 0. An array is used because PHP
-   *         does not allow static variables to be references.
-   *
-   * @static
-   * @private
-   */
- /* static */ function &_current_store(&$new) {
-   static $current = array();
-
-   if ($new != NULL) {
-     $current = array(&$new);
-   }
-
-   return $current;
- } // function _current_store
-
-  /**
-   * Returns the "current" Textile object. This is used within
-   * anonymous callback functions which cannot have the scope of a
-   * specific object. *JHR*
-   *
-   * @return An @c object reference to the current Textile object.
-   *
-   * @static
-   * @private
-   */
- /* static */ function &_current() {
-   $current =& Textile::_current_store($null = NULL);
-   return $current[0];
- } // function _current
 } // class Textile
 
 /**
@@ -3463,7 +3469,7 @@ class MTLikeTextile extends Textile {
  *
  * A pre-formatted block of text. Textile will not add any
  * HTML tags for individual lines. Whitespace is also preserved.
- * 
+ *
  * Note that within a "pre" block, \< and \> are
  * translated into HTML entities automatically.</li>
  *
@@ -3473,7 +3479,7 @@ class MTLikeTextile extends Textile {
  * a preformatted section like the 'pre' block, but it also
  * gets a \<code\> tag (or for XHTML 2, a \<blockcode\>
  * tag is used instead).
- * 
+ *
  * Note that within a "bc" block, \< and \> are
  * translated into HTML entities automatically.</li>
  *
