includes/template.php
changeset 1 fe660c52c48f
child 13 fdd6b9dd42c3
equal deleted inserted replaced
0:902822492a68 1:fe660c52c48f
       
     1 <?php
       
     2 
       
     3 /*
       
     4  * Enano - an open-source CMS capable of wiki functions, Drupal-like sidebar blocks, and everything in between
       
     5  * Version 1.0 (Banshee)
       
     6  * Copyright (C) 2006-2007 Dan Fuhry
       
     7  *
       
     8  * This program is Free Software; you can redistribute and/or modify it under the terms of the GNU General Public License
       
     9  * as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.
       
    10  *
       
    11  * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied
       
    12  * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for details.
       
    13  */
       
    14  
       
    15 class template {
       
    16   var $tpl_strings, $tpl_bool, $theme, $style, $no_headers, $additional_headers, $sidebar_extra, $sidebar_widgets, $toolbar_menu, $theme_list, $named_theme_list, $default_theme, $default_style, $plugin_blocks, $namespace_string, $style_list, $theme_loaded;
       
    17   function __construct()
       
    18   {
       
    19     global $db, $session, $paths, $template, $plugins; // Common objects
       
    20     dc_here('template: initializing all class variables');
       
    21     $this->tpl_bool    = Array();
       
    22     $this->tpl_strings = Array();
       
    23     $this->sidebar_extra = '';
       
    24     $this->toolbar_menu = '';
       
    25     $this->additional_headers = '';
       
    26     $this->plugin_blocks = Array();
       
    27     $this->theme_loaded = false;
       
    28     
       
    29     $this->theme_list = Array();
       
    30     $this->named_theme_list = Array();
       
    31     $e = $db->sql_query('SELECT theme_id,theme_name,enabled,default_style FROM '.table_prefix.'themes WHERE enabled=1 ORDER BY theme_order;');
       
    32     if(!$e) $db->_die('The list of themes could not be selected.');
       
    33     for($i=0;$i < $db->numrows(); $i++)
       
    34     {
       
    35       $this->theme_list[$i] = $db->fetchrow();
       
    36       $this->named_theme_list[$this->theme_list[$i]['theme_id']] = $this->theme_list[$i];
       
    37     }
       
    38     $db->free_result();
       
    39     $this->default_theme = $this->theme_list[0]['theme_id'];
       
    40     $dir = ENANO_ROOT.'/themes/'.$this->default_theme.'/css/';
       
    41     $list = Array();
       
    42     // Open a known directory, and proceed to read its contents
       
    43     if (is_dir($dir)) {
       
    44       if ($dh = opendir($dir)) {
       
    45         while (($file = readdir($dh)) !== false) {
       
    46           if(preg_match('#^(.*?)\.css$#i', $file) && $file != '_printable.css') {
       
    47             $list[] = substr($file, 0, strlen($file)-4);
       
    48           }
       
    49         }
       
    50         closedir($dh);
       
    51       }
       
    52     }
       
    53     
       
    54     $def = ENANO_ROOT.'/themes/'.$this->default_theme.'/css/'.$this->named_theme_list[$this->default_theme]['default_style'];
       
    55     if(file_exists($def))
       
    56     {
       
    57       $this->default_style = substr($this->named_theme_list[$this->default_theme]['default_style'], 0, strlen($this->named_theme_list[$this->default_theme]['default_style'])-4);
       
    58     } else {
       
    59       $this->default_style = $list[0];
       
    60     }
       
    61     
       
    62     $this->style_list = $list;
       
    63     
       
    64   }
       
    65   function template()
       
    66   {
       
    67     $this->__construct();
       
    68   }
       
    69   function sidebar_widget($t, $h)
       
    70   {
       
    71     global $db, $session, $paths, $template, $plugins; // Common objects
       
    72     if(!defined('ENANO_TEMPLATE_LOADED'))
       
    73     {
       
    74       $this->load_theme($session->theme, $session->style);
       
    75     }
       
    76     if(!$this->sidebar_widgets)
       
    77       $this->sidebar_widgets = '';
       
    78     $tplvars = $this->extract_vars('elements.tpl');
       
    79     $parser = $this->makeParserText($tplvars['sidebar_section_raw']);
       
    80     $parser->assign_vars(Array('TITLE'=>$t,'CONTENT'=>$h));
       
    81     $this->plugin_blocks[$t] = $h;
       
    82     $this->sidebar_widgets .= $parser->run();
       
    83   }
       
    84   function add_header($html)
       
    85   {
       
    86     $this->additional_headers .= "\n" . $html;
       
    87   }
       
    88   function get_css($s = false)
       
    89   {
       
    90     global $db, $session, $paths, $template, $plugins; // Common objects
       
    91     if(!defined('ENANO_TEMPLATE_LOADED'))
       
    92       $this->load_theme($session->theme, $session->style);
       
    93     $path = ( $s ) ? 'css/'.$s : 'css/'.$this->style.'.css';
       
    94     if ( !file_exists(ENANO_ROOT . '/themes/' . $this->theme . '/' . $path) )
       
    95     {
       
    96       echo "/* WARNING: Falling back to default file because file $path does not exist */\n";
       
    97       $path = 'css/' . $this->style_list[0] . '.css';
       
    98     }
       
    99     return $this->process_template($path);
       
   100   }
       
   101   function load_theme($name = false, $css = false)
       
   102   {
       
   103     global $db, $session, $paths, $template, $plugins; // Common objects
       
   104     $this->theme = ( $name ) ? $name : $session->theme;
       
   105     $this->style = ( $css ) ? $css : $session->style;
       
   106     if ( !$this->theme )
       
   107     {
       
   108       $this->theme = $this->theme_list[0]['theme_id'];
       
   109       $this->style = substr($this->theme_list[0]['default_style'], 0, strlen($this->theme_list[0]['default_style'])-4);
       
   110     }
       
   111     $this->theme_loaded = true;
       
   112   }
       
   113   
       
   114   function init_vars()
       
   115   {
       
   116     global $db, $session, $paths, $template, $plugins; // Common objects
       
   117     global $email;
       
   118     
       
   119     dc_here("template: initializing all variables");
       
   120     
       
   121     if(!$this->theme || !$this->style)
       
   122     {
       
   123       $this->load_theme();
       
   124     }
       
   125     
       
   126     if(defined('ENANO_TEMPLATE_LOADED'))
       
   127     {
       
   128       dc_here('template: access denied to call template::init_vars(), bailing out');
       
   129       die_semicritical('Illegal call', '<p>$template->load_theme was called multiple times, this is not supposed to happen. Exiting with fatal error.</p>');
       
   130     }
       
   131     
       
   132     define('ENANO_TEMPLATE_LOADED', '');
       
   133     
       
   134     $tplvars = $this->extract_vars('elements.tpl');
       
   135     
       
   136     dc_here('template: setting all template vars');
       
   137     
       
   138     if(isset($_SERVER['HTTP_USER_AGENT']) && strstr($_SERVER['HTTP_USER_AGENT'], 'MSIE'))
       
   139     {
       
   140       $this->add_header('
       
   141         <!--[if lt IE 7]>
       
   142         <script language="JavaScript">
       
   143         function correctPNG() // correctly handle PNG transparency in Win IE 5.5 & 6.
       
   144         {
       
   145            var arVersion = navigator.appVersion.split("MSIE")
       
   146            var version = parseFloat(arVersion[1])
       
   147            if (version >= 5.5 && typeof(document.body.filters) == "object")
       
   148            {
       
   149               for(var i=0; i<document.images.length; i++)
       
   150               {
       
   151                  var img = document.images[i];
       
   152                  continue;
       
   153                  var imgName = img.src.toUpperCase();
       
   154                  if (imgName.substring(imgName.length-3, imgName.length) == "PNG")
       
   155                  {
       
   156                     var imgID = (img.id) ? "id=\'" + img.id + "\' " : "";
       
   157                     var imgClass = (img.className) ? "class=\'" + img.className + "\' " : "";
       
   158                     var imgTitle = (img.title) ? "title=\'" + img.title + "\' " : "title=\'" + img.alt + "\' ";
       
   159                     var imgStyle = "display:inline-block;" + img.style.cssText;
       
   160                     if (img.align == "left") imgStyle = "float:left;" + imgStyle;
       
   161                     if (img.align == "right") imgStyle = "float:right;" + imgStyle;
       
   162                     if (img.parentElement.href) imgStyle = "cursor:hand;" + imgStyle;
       
   163                     var strNewHTML = "<span " + imgID + imgClass + imgTitle + " style=\\"" + "width:" + img.width + "px; height:" + img.height + "px;" + imgStyle + ";" + "filter:progid:DXImageTransform.Microsoft.AlphaImageLoader" + "(src=\\\'" + img.src + "\\\', sizingMethod=\'scale\');\\"></span>";
       
   164                     img.outerHTML = strNewHTML;
       
   165                     i = i-1;
       
   166                  }
       
   167               }
       
   168            }   
       
   169         }
       
   170         window.attachEvent("onload", correctPNG);
       
   171         </script>
       
   172         <![endif]-->
       
   173         ');
       
   174     }
       
   175     
       
   176     // Get the "article" button text (depends on namespace)
       
   177     switch($paths->namespace) {
       
   178       case "Article":
       
   179       default:
       
   180         $ns = 'article';
       
   181         break;
       
   182       case "Admin":
       
   183         $ns = 'administration page';
       
   184         break;
       
   185       case "System":
       
   186         $ns = 'system message';
       
   187         break;
       
   188       case "File":
       
   189         $ns = 'uploaded file';
       
   190         break;
       
   191       case "Help":
       
   192         $ns = 'documentation page';
       
   193         break;
       
   194       case "User":
       
   195         $ns = 'user page';
       
   196         break;
       
   197       case "Special":
       
   198         $ns = 'special page';
       
   199         break;
       
   200       case "Template":
       
   201         $ns = 'template';
       
   202         break;
       
   203       case "Project":
       
   204         $ns = 'project page';
       
   205         break;
       
   206       case "Category":
       
   207         $ns = 'category';
       
   208         break;
       
   209     }
       
   210     $this->namespace_string = $ns;
       
   211     $code = $plugins->setHook('page_type_string_set');
       
   212     foreach ( $code as $cmd )
       
   213     {
       
   214       eval($cmd);
       
   215     }
       
   216     $ns =& $this->namespace_string;
       
   217     
       
   218     // Initialize the toolbar
       
   219     $tb = '';
       
   220     
       
   221     // Create "xx page" button
       
   222     
       
   223     $btn_selected = ( isset($tplvars['toolbar_button_selected'])) ? $tplvars['toolbar_button_selected'] : $tplvars['toolbar_button'];
       
   224     $parser = $this->makeParserText($btn_selected);
       
   225     
       
   226     $parser->assign_vars(array(
       
   227         'FLAGS' => 'onclick="void(ajaxReset()); return false;" title="View the page contents, all of the page contents, and nothing but the page contents (alt-a)" accesskey="a"',
       
   228         'PARENTFLAGS' => 'id="mdgToolbar_article"',
       
   229         'HREF' => makeUrl($paths->page, null, true),
       
   230         'TEXT' => $this->namespace_string
       
   231       ));
       
   232     
       
   233     $tb .= $parser->run();
       
   234     
       
   235     $button = $this->makeParserText($tplvars['toolbar_button']);
       
   236     
       
   237     // Page toolbar
       
   238     // Comments button
       
   239     if ( $session->get_permissions('read') && getConfig('enable_comments')=='1' && $paths->namespace != 'Special' && $paths->namespace != 'Admin' && $paths->cpage['comments_on'] == 1 )
       
   240     {
       
   241       
       
   242       $e = $db->sql_query('SELECT approved FROM '.table_prefix.'comments WHERE page_id=\''.$paths->cpage['urlname_nons'].'\' AND namespace=\''.$paths->namespace.'\';');
       
   243       if ( !$e )
       
   244       {
       
   245         $db->_die();
       
   246       }
       
   247       $nc = $db->numrows();
       
   248       $nu = 0;
       
   249       $na = 0;
       
   250       
       
   251       while ( $r = $db->fetchrow() )
       
   252       {  
       
   253         if ( !$r['approved'] )
       
   254         {
       
   255           $nu++;
       
   256         }
       
   257         else
       
   258         {
       
   259           $na++;
       
   260         }
       
   261       }
       
   262       
       
   263       $db->free_result();
       
   264       $n = ( $session->get_permissions('mod_comments') ) ? (string)$nc : (string)$na;
       
   265       if ( $session->get_permissions('mod_comments') && $nu > 0 )
       
   266       {
       
   267         $n .= ' total/'.$nu.' unapp.';
       
   268       }
       
   269       
       
   270       $button->assign_vars(array(
       
   271           'FLAGS' => 'onclick="void(ajaxComments()); return false;" title="View the comments that other users have posted about this page (alt-c)" accesskey="c"',
       
   272           'PARENTFLAGS' => 'id="mdgToolbar_discussion"',
       
   273           'HREF' => makeUrl($paths->page, 'do=comments', true),
       
   274           'TEXT' => 'discussion ('.$n.')',
       
   275         ));
       
   276       
       
   277       $tb .= $button->run();
       
   278     }
       
   279     // Edit button
       
   280     if($session->get_permissions('read') && ($paths->namespace != 'Special' && $paths->namespace != 'Admin') && ( $session->get_permissions('edit_page') && ( ( $paths->page_protected && $session->get_permissions('even_when_protected') ) || !$paths->page_protected ) ) )
       
   281     {
       
   282       $button->assign_vars(array(
       
   283         'FLAGS' => 'onclick="void(ajaxEditor()); return false;" title="Edit the contents of this page (alt-e)" accesskey="e"',
       
   284         'PARENTFLAGS' => 'id="mdgToolbar_edit"',
       
   285         'HREF' => makeUrl($paths->page, 'do=edit', true),
       
   286         'TEXT' => 'edit this page'
       
   287         ));
       
   288       $tb .= $button->run();
       
   289     // View source button
       
   290     }
       
   291     else if($session->get_permissions('view_source') && ( !$session->get_permissions('edit_page') || !$session->get_permissions('even_when_protected') && $paths->page_protected ) && $paths->namespace != 'Special' && $paths->namespace != 'Admin') 
       
   292     {
       
   293       $button->assign_vars(array(
       
   294         'FLAGS' => 'onclick="void(ajaxViewSource()); return false;" title="View the source code (wiki markup) that this page uses (alt-e)" accesskey="e"',
       
   295         'PARENTFLAGS' => 'id="mdgToolbar_edit"',
       
   296         'HREF' => makeUrl($paths->page, 'do=viewsource', true),
       
   297         'TEXT' => 'view source'
       
   298         ));
       
   299       $tb .= $button->run();
       
   300     }
       
   301     // History button
       
   302     if ( $session->get_permissions('read') /* && $paths->wiki_mode */ && $paths->page_exists && $paths->namespace != 'Special' && $paths->namespace != 'Admin' && $session->get_permissions('history_view') )
       
   303     {
       
   304       $button->assign_vars(array(
       
   305         'FLAGS'       => 'onclick="void(ajaxHistory()); return false;" title="View a log of actions taken on this page (alt-h)" accesskey="h"',
       
   306         'PARENTFLAGS' => 'id="mdgToolbar_history"',
       
   307         'HREF'        => makeUrl($paths->page, 'do=history', true),
       
   308         'TEXT'        => 'history'
       
   309         ));
       
   310       $tb .= $button->run();
       
   311     }
       
   312     
       
   313     $menubtn = $this->makeParserText($tplvars['toolbar_menu_button']);
       
   314     
       
   315     // Additional actions menu
       
   316     // Rename button
       
   317     if ( $session->get_permissions('read') && $paths->page_exists && ( $session->get_permissions('rename') && ( $paths->page_protected && $session->get_permissions('even_when_protected') || !$paths->page_protected ) ) && $paths->namespace != 'Special' && $paths->namespace != 'Admin' )
       
   318     {
       
   319       $menubtn->assign_vars(array(
       
   320           'FLAGS' => 'onclick="void(ajaxRename()); return false;" title="Change the display name of this page (alt-r)" accesskey="r"',
       
   321           'HREF'  => makeUrl($paths->page, 'do=rename', true),
       
   322           'TEXT'  => 'rename',
       
   323         ));
       
   324       $this->toolbar_menu .= $menubtn->run();
       
   325     }
       
   326     
       
   327     // Vote-to-delete button
       
   328     if ( $paths->wiki_mode && $session->get_permissions('vote_delete') && $paths->page_exists && $paths->namespace != 'Special' && $paths->namespace != 'Admin')
       
   329     {
       
   330       $menubtn->assign_vars(array(
       
   331           'FLAGS' => 'onclick="void(ajaxDelVote()); return false;" title="Vote to have this page deleted (alt-d)" accesskey="d"',
       
   332           'HREF'  => makeUrl($paths->page, 'do=delvote', true),
       
   333           'TEXT'  => 'vote to delete this page',
       
   334         ));
       
   335       $this->toolbar_menu .= $menubtn->run();
       
   336     }
       
   337     
       
   338     // Clear-votes button
       
   339     if ( $session->get_permissions('read') && $paths->wiki_mode && $paths->page_exists && $paths->namespace != 'Special' && $paths->namespace != 'Admin' && $session->get_permissions('vote_reset') && $paths->cpage['delvotes'] > 0)
       
   340     {
       
   341       $menubtn->assign_vars(array(
       
   342           'FLAGS' => 'onclick="void(ajaxResetDelVotes()); return false;" title="Vote to have this page deleted (alt-y)" accesskey="y"',
       
   343           'HREF'  => makeUrl($paths->page, 'do=resetvotes', true),
       
   344           'TEXT'  => 'reset deletion votes',
       
   345         ));
       
   346       $this->toolbar_menu .= $menubtn->run();
       
   347     }
       
   348     
       
   349     // Printable page button
       
   350     if ( $paths->page_exists && $paths->namespace != 'Special' && $paths->namespace != 'Admin' )
       
   351     {
       
   352       $menubtn->assign_vars(array(
       
   353           'FLAGS' => 'title="View a version of this page that is suitable for printing"',
       
   354           'HREF'  => makeUrl($paths->page, 'printable=yes', true),
       
   355           'TEXT'  => 'view printable version',
       
   356         ));
       
   357       $this->toolbar_menu .= $menubtn->run();
       
   358     }
       
   359     
       
   360     // Protect button
       
   361     if($session->get_permissions('read') && $paths->wiki_mode && $paths->page_exists && $paths->namespace != 'Special' && $paths->namespace != 'Admin' && $session->get_permissions('protect'))
       
   362     {
       
   363       
       
   364       $label = $this->makeParserText($tplvars['toolbar_label']);
       
   365       $label->assign_vars(array('TEXT' => 'protection:'));
       
   366       $t0 = $label->run();
       
   367       
       
   368       $ctmp = ''; 
       
   369       if ( $paths->cpage['protected'] == 1 )
       
   370       {
       
   371         $ctmp=' style="text-decoration: underline;"';
       
   372       }
       
   373       $menubtn->assign_vars(array(
       
   374           'FLAGS' => 'accesskey="i" onclick="ajaxProtect(1); return false;" id="protbtn_1" title="Prevents all non-administrators from editing this page. [alt-i]"'.$ctmp,
       
   375           'HREF'  => makeUrl($paths->page, 'do=protect&level=1', true),
       
   376           'TEXT'  => 'on'
       
   377         ));
       
   378       $t1 = $menubtn->run();
       
   379       
       
   380       $ctmp = '';
       
   381       if ( $paths->cpage['protected'] == 0 )
       
   382       {
       
   383         $ctmp=' style="text-decoration: underline;"';
       
   384       }
       
   385       $menubtn->assign_vars(array(
       
   386           'FLAGS' => 'accesskey="o" onclick="ajaxProtect(0); return false;" id="protbtn_0" title="Allows everyone to edit this page. [alt-o]"'.$ctmp,
       
   387           'HREF'  => makeUrl($paths->page, 'do=protect&level=0', true),
       
   388           'TEXT'  => 'off'
       
   389         ));
       
   390       $t2 = $menubtn->run();
       
   391       
       
   392       $ctmp = '';
       
   393       if ( $paths->cpage['protected'] == 2 )
       
   394       {
       
   395         $ctmp = ' style="text-decoration: underline;"';
       
   396       }
       
   397       $menubtn->assign_vars(array(
       
   398           'FLAGS' => 'accesskey="p" onclick="ajaxProtect(2); return false;" id="protbtn_2" title="Allows only users who have been registered for 4 days to edit this page. [alt-p]"'.$ctmp,
       
   399           'HREF'  => makeUrl($paths->page, 'do=protect&level=2', true),
       
   400           'TEXT'  => 'semi'
       
   401         ));
       
   402       $t3 = $menubtn->run();
       
   403       
       
   404       $this->toolbar_menu .= '        <table border="0" cellspacing="0" cellpadding="0">
       
   405           <tr>
       
   406             <td>'.$t0.'</td>
       
   407             <td>'.$t1.'</td>
       
   408             <td>'.$t2.'</td>
       
   409             <td>'.$t3.'</td>
       
   410           </tr>
       
   411         </table>';
       
   412     }
       
   413     
       
   414     // Wiki mode button
       
   415     if($session->get_permissions('read') && $paths->page_exists && $session->get_permissions('set_wiki_mode') && $paths->namespace != 'Special' && $paths->namespace != 'Admin')
       
   416     {
       
   417       // label at start
       
   418       $label = $this->makeParserText($tplvars['toolbar_label']);
       
   419       $label->assign_vars(array('TEXT' => 'page wiki mode:'));
       
   420       $t0 = $label->run();
       
   421       
       
   422       // on button
       
   423       $ctmp = '';
       
   424       if ( $paths->cpage['wiki_mode'] == 1 )
       
   425       {
       
   426         $ctmp = ' style="text-decoration: underline;"';
       
   427       }
       
   428       $menubtn->assign_vars(array(
       
   429           'FLAGS' => 'onclick="ajaxSetWikiMode(1); return false;" id="wikibtn_1" title="Forces wiki functions to be allowed on this page."'.$ctmp,
       
   430           'HREF' => makeUrl($paths->page, 'do=setwikimode&level=1', true),
       
   431           'TEXT' => 'on'
       
   432         ));
       
   433       $t1 = $menubtn->run();
       
   434       
       
   435       // off button
       
   436       $ctmp = '';
       
   437       if ( $paths->cpage['wiki_mode'] == 0 )
       
   438       {
       
   439         $ctmp=' style="text-decoration: underline;"';
       
   440       }
       
   441       $menubtn->assign_vars(array(
       
   442           'FLAGS' => 'onclick="ajaxSetWikiMode(0); return false;" id="wikibtn_0" title="Forces wiki functions to be disabled on this page."'.$ctmp,
       
   443           'HREF' => makeUrl($paths->page, 'do=setwikimode&level=0', true),
       
   444           'TEXT' => 'off'
       
   445         ));
       
   446       $t2 = $menubtn->run();
       
   447       
       
   448       // global button
       
   449       $ctmp = ''; 
       
   450       if ( $paths->cpage['wiki_mode'] == 2 )
       
   451       {
       
   452         $ctmp=' style="text-decoration: underline;"';
       
   453       }
       
   454       $menubtn->assign_vars(array(
       
   455           'FLAGS' => 'onclick="ajaxSetWikiMode(2); return false;" id="wikibtn_2" title="Causes this page to use the global wiki mode setting (default)"'.$ctmp,
       
   456           'HREF' => makeUrl($paths->page, 'do=setwikimode&level=2', true),
       
   457           'TEXT' => 'global'
       
   458         ));
       
   459       $t3 = $menubtn->run();
       
   460       
       
   461       // Tack it onto the list of buttons that are already there...
       
   462       $this->toolbar_menu .= '        <table border="0" cellspacing="0" cellpadding="0">
       
   463           <tr>
       
   464             <td>'.$t0.'</td>
       
   465             <td>'.$t1.'</td>
       
   466             <td>'.$t2.'</td>
       
   467             <td>'.$t3.'</td>
       
   468           </tr>
       
   469         </table>';
       
   470     }
       
   471     
       
   472     // Clear logs button
       
   473     if ( $session->get_permissions('read') && $session->get_permissions('clear_logs') && $paths->wiki_mode && $paths->namespace != 'Special' && $paths->namespace != 'Admin' )
       
   474     {
       
   475       $menubtn->assign_vars(array(
       
   476           'FLAGS' => 'onclick="void(ajaxClearLogs()); return false;" title="Remove all edit and action logs for this page from the database. IRREVERSIBLE! (alt-l)" accesskey="l"',
       
   477           'HREF'  => makeUrl($paths->page, 'do=flushlogs', true),
       
   478           'TEXT'  => 'clear page logs',
       
   479         ));
       
   480       $this->toolbar_menu .= $menubtn->run();
       
   481     }
       
   482     
       
   483     // Delete page button
       
   484     if ( $session->get_permissions('read') && $session->get_permissions('delete_page') && $paths->page_exists && $paths->namespace != 'Special' && $paths->namespace != 'Admin' )
       
   485     {
       
   486       $s = 'delete this page';
       
   487       if ( $paths->cpage['delvotes'] == 1 )
       
   488       {
       
   489         $s .= ' (<b>'.$paths->cpage['delvotes'].'</b> vote)';
       
   490       }
       
   491       else if ( $paths->cpage['delvotes'] > 1 )
       
   492       {
       
   493         $s .= ' (<b>'.$paths->cpage['delvotes'].'</b> votes)';
       
   494       }
       
   495       
       
   496       $menubtn->assign_vars(array(
       
   497           'FLAGS' => 'onclick="void(ajaxDeletePage()); return false;" title="Delete this page. This is always reversible unless the logs are cleared. (alt-k)" accesskey="k"',
       
   498           'HREF'  => makeUrl($paths->page, 'do=deletepage', true),
       
   499           'TEXT'  => $s,
       
   500         ));
       
   501       $this->toolbar_menu .= $menubtn->run();
       
   502       
       
   503     }
       
   504     
       
   505     // Password-protect button
       
   506     if(isset($paths->cpage['password']))
       
   507     {
       
   508       if ( $paths->cpage['password'] == '' )
       
   509       {
       
   510         $a = $session->get_permissions('password_set');
       
   511       }
       
   512       else
       
   513       {
       
   514         $a = $session->get_permissions('password_reset');
       
   515       }
       
   516     }
       
   517     else
       
   518     {
       
   519       $a = $session->get_permissions('password_set');
       
   520     }
       
   521     if ( $a && $session->get_permissions('read') && $paths->page_exists && $paths->namespace != 'Special' && $paths->namespace != 'Admin' )
       
   522     {
       
   523       // label at start
       
   524       $label = $this->makeParserText($tplvars['toolbar_label']);
       
   525       $label->assign_vars(array('TEXT' => 'password:'));
       
   526       $t0 = $label->run();
       
   527       
       
   528       $menubtn->assign_vars(array(
       
   529           'FLAGS' => 'onclick="void(ajaxSetPassword()); return false;" title="Require a password in order for this page to be viewed"',
       
   530           'HREF'  => '#',
       
   531           'TEXT'  => 'set',
       
   532         ));
       
   533       $t = $menubtn->run();
       
   534       
       
   535       $this->toolbar_menu .= '<table border="0" cellspacing="0" cellpadding="0"><tr><td>'.$t0.'</td><td><input type="password" id="mdgPassSetField" size="10" /></td><td>'.$t.'</td></tr></table>';
       
   536     }
       
   537     
       
   538     // Manage ACLs button
       
   539     if($session->get_permissions('edit_acl') || $session->user_level >= USER_LEVEL_ADMIN)
       
   540     {
       
   541       $menubtn->assign_vars(array(
       
   542           'FLAGS' => 'onclick="return ajaxOpenACLManager();" title="Manage who can do what with this page (alt-m)" accesskey="m"',
       
   543           'HREF'  => makeUrl($paths->page, 'do=aclmanager', true),
       
   544           'TEXT'  => 'manage page access',
       
   545         ));
       
   546       $this->toolbar_menu .= $menubtn->run();
       
   547     }
       
   548     
       
   549     // Administer page button
       
   550     if ( $session->user_level >= USER_LEVEL_ADMIN && $paths->page_exists && $paths->namespace != 'Special' && $paths->namespace != 'Admin' )
       
   551     {
       
   552       $menubtn->assign_vars(array(
       
   553           'FLAGS' => 'onclick="void(ajaxAdminPage()); return false;" title="Administrative options for this page" accesskey="g"',
       
   554           'HREF'  => makeUrlNS('Special', 'Administration', 'module='.$paths->nslist['Admin'].'PageManager', true),
       
   555           'TEXT'  => 'administrative options',
       
   556         ));
       
   557       $this->toolbar_menu .= $menubtn->run();
       
   558     }
       
   559     
       
   560     if ( strlen($this->toolbar_menu) > 0 )
       
   561     {
       
   562       $button->assign_vars(array(
       
   563         'FLAGS'       => 'id="mdgToolbar_moreoptions" onclick="return false;" title="Additional options for working with this page"',
       
   564         'PARENTFLAGS' => '',
       
   565         'HREF'        => makeUrl($paths->page, 'do=moreoptions', true),
       
   566         'TEXT'        => 'more options'
       
   567         ));
       
   568       $tb .= $button->run();
       
   569     }
       
   570     
       
   571     $is_opera = (isset($_SERVER['HTTP_USER_AGENT']) && strstr($_SERVER['HTTP_USER_AGENT'], 'Opera')) ? true : false;
       
   572     
       
   573     $this->tpl_bool = Array(
       
   574       'auth_admin'=>$session->user_level >= USER_LEVEL_ADMIN ? true : false,
       
   575       'user_logged_in'=>$session->user_logged_in,
       
   576       'opera'=>$is_opera,
       
   577       );
       
   578     
       
   579     if($session->sid_super) { $ash = '&amp;auth='.$session->sid_super; $asq = "?auth=".$session->sid_super; $asa = "&auth=".$session->sid_super; $as2 = htmlspecialchars(urlSeparator).'auth='.$session->sid_super; }
       
   580     else { $asq=''; $asa=''; $as2 = ''; $ash = ''; }
       
   581     
       
   582     $code = $plugins->setHook('compile_template');
       
   583     foreach ( $code as $cmd )
       
   584     {
       
   585       eval($cmd);
       
   586     }
       
   587     
       
   588     // Some additional sidebar processing
       
   589     if($this->sidebar_extra != '') {
       
   590       $se = $this->sidebar_extra;
       
   591       $parser = $this->makeParserText($tplvars['sidebar_section_raw']);
       
   592       $parser->assign_vars(Array('TITLE'=>'Links','CONTENT'=>$se));
       
   593       $this->sidebar_extra = $parser->run();
       
   594     }
       
   595     
       
   596     $this->sidebar_extra = $this->sidebar_extra.$this->sidebar_widgets;
       
   597     
       
   598     $this->tpl_bool['fixed_menus'] = false;
       
   599     /* if($this->sidebar_extra == '') $this->tpl_bool['right_sidebar'] = false;
       
   600     else */ $this->tpl_bool['right_sidebar'] = true;
       
   601     
       
   602     $this->tpl_bool['auth_rename'] = ( $paths->page_exists && ( $session->get_permissions('rename') && ( $paths->page_protected && $session->get_permissions('even_when_protected') || !$paths->page_protected ) ) && $paths->namespace != 'Special' && $paths->namespace != 'Admin');
       
   603     
       
   604     $this->tpl_bool['enable_uploads'] = ( getConfig('enable_uploads') == '1' && $session->get_permissions('upload_files') ) ? true : false;
       
   605     
       
   606     $this->tpl_bool['stupid_mode'] = false;
       
   607     
       
   608     if($paths->page == $paths->nslist['Special'].'Administration') $this->tpl_bool['in_admin'] = true;
       
   609     else $this->tpl_bool['in_admin'] = false;
       
   610     
       
   611     $p = ( isset($_GET['printable']) ) ? '/printable' : '';
       
   612     
       
   613     // Add the e-mail address client code to the header
       
   614     $this->add_header($email->jscode());
       
   615     
       
   616     // Generate the code for the Log out and Change theme sidebar buttons
       
   617     // Once again, the new template parsing system can be used here
       
   618     
       
   619     $parser = $this->makeParserText($tplvars['sidebar_button']);
       
   620     
       
   621     $parser->assign_vars(Array(
       
   622         'HREF'=>makeUrlNS('Special', 'Logout'),
       
   623         'FLAGS'=>'onclick="mb_logout(); return false;"',
       
   624         'TEXT'=>'Log out',
       
   625       ));
       
   626     
       
   627     $logout_link = $parser->run();
       
   628     
       
   629     $parser->assign_vars(Array(
       
   630         'HREF'=>makeUrlNS('Special', 'Login/' . $paths->page),
       
   631         'FLAGS'=>'onclick="ajaxStartLogin(); return false;"',
       
   632         'TEXT'=>'Log in',
       
   633       ));
       
   634     
       
   635     $login_link = $parser->run();
       
   636     
       
   637     $parser->assign_vars(Array(
       
   638         'HREF'=>makeUrlNS('Special', 'ChangeStyle/'.$paths->page),
       
   639         'FLAGS'=>'onclick="ajaxChangeStyle(); return false;"',
       
   640         'TEXT'=>'Change theme',
       
   641       ));
       
   642     
       
   643     $theme_link = $parser->run();
       
   644     
       
   645     $SID = ($session->sid_super) ? $session->sid_super : '';
       
   646     
       
   647     // Generate the dynamic javascript vars
       
   648     $js_dynamic = '    <script type="text/javascript">// <![CDATA[
       
   649       // This section defines some basic and very important variables that are used later in the static Javascript library.
       
   650       // SKIN DEVELOPERS: The template variable for this code block is {JS_DYNAMIC_VARS}. This MUST be inserted BEFORE the tag that links to the main Javascript lib.
       
   651       var title=\''. str_replace('\'', '\\\'', str_replace('\\', '\\\\', $paths->fullpage)) .'\';
       
   652       var page_exists='. ( ( $paths->page_exists) ? 'true' : 'false' ) .';
       
   653       var scriptPath=\''. scriptPath .'\';
       
   654       var contentPath=\''.contentPath.'\';
       
   655       var ENANO_SID =\'' . $SID . '\';
       
   656       var auth_level=' . $session->auth_level . ';
       
   657       var USER_LEVEL_GUEST = ' . USER_LEVEL_GUEST . ';
       
   658       var USER_LEVEL_MEMBER = ' . USER_LEVEL_MEMBER . ';
       
   659       var USER_LEVEL_CHPREF = ' . USER_LEVEL_CHPREF . ';
       
   660       var USER_LEVEL_MOD = ' . USER_LEVEL_MOD . ';
       
   661       var USER_LEVEL_ADMIN = ' . USER_LEVEL_ADMIN . ';
       
   662       var editNotice = \'' . ( (getConfig('wiki_edit_notice')=='1') ? str_replace("\n", "\\\n", RenderMan::render(getConfig('wiki_edit_notice_text'))) : '' ) . '\';
       
   663       var prot = ' . ( ($paths->page_protected && !$session->get_permissions('even_when_protected')) ? 'true' : 'false' ) .'; // No, hacking this var won\'t work, it\'s re-checked on the server
       
   664       var ENANO_SPECIAL_CREATEPAGE = \''. makeUrl($paths->nslist['Special'].'CreatePage') .'\';
       
   665       var ENANO_CREATEPAGE_PARAMS = \'_do=&pagename='. addslashes($paths->cpage['name']) .'&namespace=' . $paths->namespace . '\';
       
   666       var ENANO_SPECIAL_CHANGESTYLE = \''. makeUrlNS('Special', 'ChangeStyle') .'\';
       
   667       var namespace_list = new Array();
       
   668       var AES_BITS = '.AES_BITS.';
       
   669       var AES_BLOCKSIZE = '.AES_BLOCKSIZE.';
       
   670       var pagepass = \''. ( ( isset($_REQUEST['pagepass']) ) ? sha1($_REQUEST['pagepass']) : '' ) .'\';
       
   671       var ENANO_THEME_LIST = \'';
       
   672           foreach($this->theme_list as $t) {
       
   673             if($t['enabled'])
       
   674             {
       
   675               $js_dynamic .= '<option value="'.$t['theme_id'].'"';
       
   676               if($t['theme_id'] == $session->theme) $js_dynamic .= ' selected="selected"';
       
   677               $js_dynamic .= '>'.$t['theme_name'].'</option>';
       
   678             }
       
   679           }
       
   680       $js_dynamic .= '\';
       
   681       var ENANO_CURRENT_THEME = \''. $session->theme .'\';';
       
   682       foreach($paths->nslist as $k => $c)
       
   683       {
       
   684         $js_dynamic .= "namespace_list['{$k}'] = '$c';";
       
   685       }
       
   686       $js_dynamic .= "\n    //]]>\n    </script>";
       
   687     
       
   688     $tpl_strings = Array(
       
   689       'PAGE_NAME'=>$paths->cpage['name'],
       
   690       'PAGE_URLNAME'=>$paths->cpage['urlname'],
       
   691       'SITE_NAME'=>getConfig('site_name'),
       
   692       'USERNAME'=>$session->username,
       
   693       'SITE_DESC'=>getConfig('site_desc'),
       
   694       'TOOLBAR'=>$tb,
       
   695       'SCRIPTPATH'=>scriptPath,
       
   696       'CONTENTPATH'=>contentPath,
       
   697       'ADMIN_SID_QUES'=>$asq,
       
   698       'ADMIN_SID_AMP'=>$asa,
       
   699       'ADMIN_SID_AMP_HTML'=>$ash,
       
   700       'ADMIN_SID_AUTO'=>$as2,
       
   701       'ADDITIONAL_HEADERS'=>$this->additional_headers,
       
   702       'COPYRIGHT'=>getConfig('copyright_notice'),
       
   703       'TOOLBAR_EXTRAS'=>$this->toolbar_menu,
       
   704       'REQUEST_URI'=>$_SERVER['HTTP_HOST'].$_SERVER['REQUEST_URI'],
       
   705       'STYLE_LINK'=>makeUrlNS('Special', 'CSS'.$p, null, true), //contentPath.$paths->nslist['Special'].'CSS' . $p,
       
   706       'LOGIN_LINK'=>$login_link,
       
   707       'LOGOUT_LINK'=>$logout_link,
       
   708       'THEME_LINK'=>$theme_link,
       
   709       'TEMPLATE_DIR'=>scriptPath.'/themes/'.$this->theme,
       
   710       'THEME_ID'=>$this->theme,
       
   711       'STYLE_ID'=>$this->style,
       
   712       'JS_DYNAMIC_VARS'=>$js_dynamic,
       
   713       'UNREAD_PMS'=>$session->unread_pms
       
   714       );
       
   715     
       
   716     foreach ( $paths->nslist as $ns_id => $ns_prefix )
       
   717     {
       
   718       $tpl_strings[ 'NS_' . strtoupper($ns_id) ] = $ns_prefix;
       
   719     }
       
   720     
       
   721     $this->tpl_strings = array_merge($tpl_strings, $this->tpl_strings);
       
   722     list($this->tpl_strings['SIDEBAR_LEFT'], $this->tpl_strings['SIDEBAR_RIGHT'], $min) = $this->fetch_sidebar();
       
   723     $this->tpl_bool['sidebar_left']  = ( $this->tpl_strings['SIDEBAR_LEFT']  != $min) ? true : false;
       
   724     $this->tpl_bool['sidebar_right'] = ( $this->tpl_strings['SIDEBAR_RIGHT'] != $min) ? true : false;
       
   725     $this->tpl_bool['right_sidebar'] = $this->tpl_bool['sidebar_right']; // backward compatibility
       
   726   }
       
   727   
       
   728   function header($simple = false) 
       
   729   {
       
   730     global $db, $session, $paths, $template, $plugins; // Common objects
       
   731     ob_start();
       
   732     
       
   733     if(!$this->theme_loaded)
       
   734     {
       
   735       $this->load_theme($session->theme, $session->style);
       
   736     }
       
   737     
       
   738     $headers_sent = true;
       
   739     dc_here('template: generating and sending the page header');
       
   740     if(!defined('ENANO_HEADERS_SENT'))
       
   741       define('ENANO_HEADERS_SENT', '');
       
   742     if(!$this->no_headers) echo ( $simple ) ? $this->process_template('simple-header.tpl') : $this->process_template('header.tpl');
       
   743     if ( !$simple && $session->user_logged_in && $session->unread_pms > 0 )
       
   744     {
       
   745       echo $this->notify_unread_pms();
       
   746     }
       
   747     if ( !$simple && $session->sw_timed_out )
       
   748     {
       
   749       $login_link = makeUrlNS('Special', 'Login/' . $paths->fullpage, 'level=' . $session->user_level, true);
       
   750       echo '<div class="usermessage">';
       
   751       echo '<b>Your administrative session has timed out.</b> <a href="' . $login_link . '">Log in again</a>';
       
   752       echo '</div>';
       
   753     }
       
   754   }
       
   755   function footer($simple = false)
       
   756   {
       
   757     global $db, $session, $paths, $template, $plugins; // Common objects
       
   758     dc_here('template: generating and sending the page footer');
       
   759     if(!$this->no_headers) {
       
   760       
       
   761       if(!defined('ENANO_HEADERS_SENT'))
       
   762         $this->header();
       
   763       
       
   764       global $_starttime;
       
   765       if(isset($_GET['sqldbg']) && $session->get_permissions('mod_misc'))
       
   766       {
       
   767         echo '<h3>Query list as requested on URI</h3><pre style="margin-left: 1em">';
       
   768         echo $db->sql_backtrace();
       
   769         echo '</pre>';
       
   770       }
       
   771       
       
   772       $f = microtime_float();
       
   773       $f = $f - $_starttime;
       
   774       $f = round($f, 4);
       
   775       $dbg = 'Time: '.$f.'s  |  Queries: '.$db->num_queries;
       
   776       $t = ( $simple ) ? $this->process_template('simple-footer.tpl') : $this->process_template('footer.tpl');
       
   777       $t = str_replace('[[Stats]]', $dbg, $t);
       
   778       $t = str_replace('[[NumQueries]]', (string)$db->num_queries, $t);
       
   779       $t = str_replace('[[GenTime]]', (string)$f, $t);
       
   780       echo $t;
       
   781       
       
   782       ob_end_flush();
       
   783     }
       
   784     else return '';
       
   785   }
       
   786   function getHeader()
       
   787   {
       
   788     $headers_sent = true;
       
   789     dc_here('template: generating and sending the page header');
       
   790     if(!defined('ENANO_HEADERS_SENT'))
       
   791       define('ENANO_HEADERS_SENT', '');
       
   792     if(!$this->no_headers) return $this->process_template('header.tpl');
       
   793   }
       
   794   function getFooter()
       
   795   {
       
   796     global $db, $session, $paths, $template, $plugins; // Common objects
       
   797     dc_here('template: generating and sending the page footer');
       
   798     if(!$this->no_headers) {
       
   799       global $_starttime;
       
   800       $t = '';
       
   801       
       
   802       if(isset($_GET['sqldbg']) && $session->get_permissions('mod_misc'))
       
   803       {
       
   804         $t .= '<h3>Query list as requested on URI</h3><pre style="margin-left: 1em">';
       
   805         $t .= $db->sql_backtrace();
       
   806         $t .= '</pre>';
       
   807       }
       
   808       
       
   809       $f = microtime_float();
       
   810       $f = $f - $_starttime;
       
   811       $f = round($f, 4);
       
   812       $dbg = 'Time: '.$f.'s  |  Queries: '.$db->num_queries;
       
   813       $t.= $this->process_template('footer.tpl');
       
   814       $t = str_replace('[[Stats]]', $dbg, $t);
       
   815       $t = str_replace('[[NumQueries]]', (string)$db->num_queries, $t);
       
   816       $t = str_replace('[[GenTime]]', (string)$f, $t);
       
   817       return $t;
       
   818     }
       
   819     else return '';
       
   820   }
       
   821   
       
   822   function process_template($file) {
       
   823     global $db, $session, $paths, $template, $plugins; // Common objects
       
   824     if(!defined('ENANO_TEMPLATE_LOADED'))
       
   825     {
       
   826       $this->load_theme();
       
   827       $this->init_vars();
       
   828     }
       
   829     eval($this->compile_template($file));
       
   830     return $tpl_code;
       
   831   }
       
   832   
       
   833   function extract_vars($file) {
       
   834     global $db, $session, $paths, $template, $plugins; // Common objects
       
   835     if(!$this->theme)
       
   836     {
       
   837       die('$template->extract_vars(): theme not yet loaded, so we can\'t open template files yet...this is a bug and should be reported.<br /><br />Backtrace, most recent call first:<pre>'.enano_debug_print_backtrace(true).'</pre>');
       
   838     }
       
   839     if(!is_file(ENANO_ROOT . '/themes/'.$this->theme.'/'.$file)) die('Cannot find '.$file.' file for style "'.$this->theme.'", exiting');
       
   840     $text = file_get_contents(ENANO_ROOT . '/themes/'.$this->theme.'/'.$file);
       
   841     preg_match_all('#<\!-- VAR ([A-z0-9_-]*) -->(.*?)<\!-- ENDVAR \\1 -->#is', $text, $matches);
       
   842     $tplvars = Array();
       
   843     for($i=0;$i<sizeof($matches[1]);$i++)
       
   844     {
       
   845       $tplvars[$matches[1][$i]] = $matches[2][$i];
       
   846     }
       
   847     return $tplvars;
       
   848   }
       
   849   function compile_template($text) {
       
   850     global $db, $session, $paths, $template, $plugins; // Common objects
       
   851     if(!is_file(ENANO_ROOT . '/themes/'.$this->theme.'/'.$text)) die('Cannot find '.$text.' file for style, exiting');
       
   852     $n = $text;
       
   853     $tpl_filename = ENANO_ROOT . '/cache/' . $this->theme . '-' . str_replace('/', '-', $n) . '.php';
       
   854     if(!is_file(ENANO_ROOT . '/themes/'.$this->theme.'/'.$text)) die('Cannot find '.$text.' file for style, exiting');
       
   855     if(file_exists($tpl_filename) && getConfig('cache_thumbs')=='1')
       
   856     {
       
   857       include($tpl_filename);
       
   858       $text = file_get_contents(ENANO_ROOT . '/themes/'.$this->theme.'/'.$text);
       
   859       if(isset($md5) && $md5 == md5($text)) {
       
   860         return str_replace('\\"', '"', $tpl_text);
       
   861       }
       
   862     }
       
   863     $text = file_get_contents(ENANO_ROOT . '/themes/'.$this->theme.'/'.$n);
       
   864     
       
   865     $md5 = md5($text);
       
   866     
       
   867     $seed = md5 ( microtime() . mt_rand() );
       
   868     preg_match_all("/<\?php(.*?)\?>/is", $text, $m);
       
   869     //die('<pre>'.htmlspecialchars(print_r($m, true)).'</pre>');
       
   870     for($i = 0; $i < sizeof($m[1]); $i++)
       
   871     {
       
   872       $text = str_replace("<?php{$m[1][$i]}?>", "{PHPCODE:{$i}:{$seed}}", $text);
       
   873     }
       
   874     //die('<pre>'.htmlspecialchars($text).'</pre>');
       
   875     $text = 'ob_start(); echo \''.str_replace('\'', '\\\'', $text).'\'; $tpl_code = ob_get_contents(); ob_end_clean();';
       
   876     $text = preg_replace('#<!-- BEGIN (.*?) -->#is', '\'; if(isset($this->tpl_bool[\'\\1\']) && $this->tpl_bool[\'\\1\']) { echo \'', $text);
       
   877     $text = preg_replace('#<!-- IFSET (.*?) -->#is', '\'; if(isset($this->tpl_strings[\'\\1\'])) { echo \'', $text);
       
   878     $text = preg_replace('#<!-- IFPLUGIN (.*?) -->#is', '\'; if(getConfig(\'plugin_\\1\')==\'1\') { echo \'', $text);
       
   879     $text = preg_replace('#<!-- SYSMSG (.*?) -->#is', '\'; echo $template->tplWikiFormat($paths->sysMsg(\'\\1\')); echo \'', $text);
       
   880     $text = preg_replace('#<!-- BEGINNOT (.*?) -->#is', '\'; if(!$this->tpl_bool[\'\\1\']) { echo \'', $text);
       
   881     $text = preg_replace('#<!-- BEGINELSE (.*?) -->#is', '\'; } else { echo \'', $text);
       
   882     $text = preg_replace('#<!-- END (.*?) -->#is', '\'; } echo \'', $text);
       
   883     $text = preg_replace('#\{([A-z0-9]*)\}#is', '\'.$this->tpl_strings[\'\\1\'].\'', $text);
       
   884     for($i = 0; $i < sizeof($m[1]); $i++)
       
   885     {
       
   886       $text = str_replace("{PHPCODE:{$i}:{$seed}}", "'; {$m[1][$i]} echo '", $text);
       
   887     }
       
   888     if(is_writable(ENANO_ROOT.'/cache/') && getConfig('cache_thumbs')=='1')
       
   889     {
       
   890       //die($tpl_filename);
       
   891       $h = fopen($tpl_filename, 'w');
       
   892       if(!$h) return $text;
       
   893       $t = addslashes($text);
       
   894       fwrite($h, '<?php $md5 = \''.$md5.'\'; $tpl_text = \''.$t.'\'; ?>');
       
   895       fclose($h);
       
   896     }
       
   897     return $text; //('<pre>'.htmlspecialchars($text).'</pre>');
       
   898   }
       
   899   
       
   900   function compile_template_text($text) {
       
   901     $seed = md5 ( microtime() . mt_rand() );
       
   902     preg_match_all("/<\?php(.*?)\?>/is", $text, $m);
       
   903     //die('<pre>'.htmlspecialchars(print_r($m, true)).'</pre>');
       
   904     for($i = 0; $i < sizeof($m[1]); $i++)
       
   905     {
       
   906       $text = str_replace("<?php{$m[1][$i]}?>", "{PHPCODE:{$i}:{$seed}}", $text);
       
   907     }
       
   908     //die('<pre>'.htmlspecialchars($text).'</pre>');
       
   909     $text = 'ob_start(); echo \''.str_replace('\'', '\\\'', $text).'\'; $tpl_code = ob_get_contents(); ob_end_clean(); return $tpl_code;';
       
   910     $text = preg_replace('#<!-- BEGIN (.*?) -->#is', '\'; if(isset($this->tpl_bool[\'\\1\']) && $this->tpl_bool[\'\\1\']) { echo \'', $text);
       
   911     $text = preg_replace('#<!-- IFSET (.*?) -->#is', '\'; if(isset($this->tpl_strings[\'\\1\'])) { echo \'', $text);
       
   912     $text = preg_replace('#<!-- IFPLUGIN (.*?) -->#is', '\'; if(getConfig(\'plugin_\\1\')==\'1\') { echo \'', $text);
       
   913     $text = preg_replace('#<!-- SYSMSG (.*?) -->#is', '\'; echo $template->tplWikiFormat($paths->sysMsg(\'\\1\')); echo \'', $text);
       
   914     $text = preg_replace('#<!-- BEGINNOT (.*?) -->#is', '\'; if(!$this->tpl_bool[\'\\1\']) { echo \'', $text);
       
   915     $text = preg_replace('#<!-- BEGINELSE (.*?) -->#is', '\'; } else { echo \'', $text);
       
   916     $text = preg_replace('#<!-- END (.*?) -->#is', '\'; } echo \'', $text);
       
   917     $text = preg_replace('#\{([A-z0-9]*)\}#is', '\'.$this->tpl_strings[\'\\1\'].\'', $text);
       
   918     for($i = 0; $i < sizeof($m[1]); $i++)
       
   919     {
       
   920       $text = str_replace("{PHPCODE:{$i}:{$seed}}", "'; {$m[1][$i]} echo '", $text);
       
   921     }
       
   922     return $text; //('<pre>'.htmlspecialchars($text).'</pre>');
       
   923   }
       
   924   
       
   925   function parse($text)
       
   926   {
       
   927     $text = $this->compile_template_text($text);
       
   928     return eval($text);
       
   929   }
       
   930   
       
   931   // Steps to turn this:
       
   932   //   [[Project:Community Portal]]
       
   933   // into this:
       
   934   //   <a href="/Project:Community_Portal">Community Portal</a>
       
   935   // Must be done WITHOUT creating eval'ed code!!!
       
   936   
       
   937   // 1. preg_replace \[\[([a-zA-Z0-9 -_:]*?)\]\] with <a href="'.contentPath.'\\1">\\1</a>
       
   938   // 2. preg_match_all <a href="'.preg_quote(contentPath).'([a-zA-Z0-9 -_:]*?)">
       
   939   // 3. For each match, replace matches with identifiers
       
   940   // 4. For each match, str_replace ' ' with '_'
       
   941   // 5. For each match, str_replace match_id:random_val with $matches[$match_id]
       
   942   
       
   943   // The template language is really a miniature programming language; with variables, conditionals, everything!
       
   944   // So you can implement custom logic into your sidebar if you wish.
       
   945   // "Real" PHP support coming soon :-D
       
   946   
       
   947   function tplWikiFormat($message, $filter_links = false, $filename = 'elements.tpl') {
       
   948     global $db, $session, $paths, $template, $plugins; // Common objects
       
   949     $filter_links = false;
       
   950     $tplvars = $this->extract_vars($filename);
       
   951     if($session->sid_super) $as = htmlspecialchars(urlSeparator).'auth='.$session->sid_super;
       
   952     else $as = '';
       
   953     error_reporting(E_ALL);
       
   954     $random_id = sha1(microtime().''); // A temp value
       
   955     
       
   956     /*
       
   957      * PREPROCESSOR
       
   958      */
       
   959     
       
   960     // Variables
       
   961     
       
   962     preg_match_all('#\$([A-Z_-]+)\$#', $message, $links);
       
   963     $links = $links[1];
       
   964     
       
   965     for($i=0;$i<sizeof($links);$i++)
       
   966     {
       
   967       $message = str_replace('$'.$links[$i].'$', $this->tpl_strings[$links[$i]], $message);
       
   968     }
       
   969     
       
   970     // Conditionals
       
   971     
       
   972     preg_match_all('#\{if ([A-Za-z0-9_ &\|\!-]*)\}(.*?)\{\/if\}#is', $message, $links);
       
   973     
       
   974     for($i=0;$i<sizeof($links[1]);$i++)
       
   975     {
       
   976       $message = str_replace('{if '.$links[1][$i].'}'.$links[2][$i].'{/if}', '{CONDITIONAL:'.$i.':'.$random_id.'}', $message);
       
   977       
       
   978       // Time for some manual parsing...
       
   979       $chk = false;
       
   980       $current_id = '';
       
   981       $prn_level = 0;
       
   982       // Used to keep track of where we are in the conditional
       
   983       // Object of the game: turn {if this && ( that OR !something_else )} ... {/if} into if( ( isset($this->tpl_bool['that']) && $this->tpl_bool['that'] ) && ...
       
   984       // Method of attack: escape all variables, ignore all else. Non-valid code is filtered out by a regex above.
       
   985       $in_var_now = true;
       
   986       $in_var_last = false;
       
   987       $current_var = '';
       
   988       $current_var_start_pos = 0;
       
   989       $current_var_end_pos   = 0;
       
   990       $j = -1;
       
   991       $links[1][$i] = $links[1][$i] . ' ';
       
   992       $d = strlen($links[1][$i]);
       
   993       while($j < $d)
       
   994       {
       
   995         $j++;
       
   996         $in_var_last = $in_var_now;
       
   997         
       
   998         $char = substr($links[1][$i], $j, 1);
       
   999         $in_var_now = ( preg_match('#^([A-z0-9_]*){1}$#', $char) ) ? true : false;
       
  1000         if(!$in_var_last && $in_var_now)
       
  1001         {
       
  1002           $current_var_start_pos = $j;
       
  1003         }
       
  1004         if($in_var_last && !$in_var_now)
       
  1005         {
       
  1006           $current_var_end_pos = $j;
       
  1007         }
       
  1008         if($in_var_now)
       
  1009         {
       
  1010           $current_var .= $char;
       
  1011           continue;
       
  1012         }
       
  1013         // OK we are not inside of a variable. That means that we JUST hit the end because the counter ($j) will be advanced to the beginning of the next variable once processing here is complete.
       
  1014         if($char != ' ' && $char != '(' && $char != ')' && $char != 'A' && $char != 'N' && $char != 'D' && $char != 'O' && $char != 'R' && $char != '&' && $char != '|' && $char != '!' && $char != '<' && $char != '>' && $char != '0' && $char != '1' && $char != '2' && $char != '3' && $char != '4' && $char != '5' && $char != '6' && $char != '7' && $char != '8' && $char != '9')
       
  1015         {
       
  1016           // XSS attack! Bail out
       
  1017           echo '<p><b>Error:</b> Syntax error (possibly XSS attack) caught in template code:</p>';
       
  1018           echo '<pre>';
       
  1019           echo '{if '.$links[1][$i].'}';
       
  1020           echo "\n    ";
       
  1021           for($k=0;$k<$j;$k++) echo " ";
       
  1022           echo '<span style="color: red;">^</span>';
       
  1023           echo '</pre>';
       
  1024           continue 2;
       
  1025         }
       
  1026         if($current_var != '')
       
  1027         {
       
  1028           $cd = '( isset($this->tpl_bool[\''.$current_var.'\']) && $this->tpl_bool[\''.$current_var.'\'] )';
       
  1029           $cvt = substr($links[1][$i], 0, $current_var_start_pos) . $cd . substr($links[1][$i], $current_var_end_pos, strlen($links[1][$i]));
       
  1030           $j = $j + strlen($cd) - strlen($current_var);
       
  1031           $current_var = '';
       
  1032           $links[1][$i] = $cvt;
       
  1033           $d = strlen($links[1][$i]);
       
  1034         }
       
  1035       }
       
  1036       $links[1][$i] = substr($links[1][$i], 0, strlen($links[1][$i])-1);
       
  1037       $links[1][$i] = '$chk = ( '.$links[1][$i].' ) ? true : false;';
       
  1038       eval($links[1][$i]);
       
  1039       
       
  1040       if($chk) { // isset($this->tpl_bool[$links[1][$i]]) && $this->tpl_bool[$links[1][$i]]
       
  1041         if(strstr($links[2][$i], '{else}')) $c = substr($links[2][$i], 0, strpos($links[2][$i], '{else}'));
       
  1042         else $c = $links[2][$i];
       
  1043         $message = str_replace('{CONDITIONAL:'.$i.':'.$random_id.'}', $c, $message);
       
  1044       } else {
       
  1045         if(strstr($links[2][$i], '{else}')) $c = substr($links[2][$i], strpos($links[2][$i], '{else}')+6, strlen($links[2][$i]));
       
  1046         else $c = '';
       
  1047         $message = str_replace('{CONDITIONAL:'.$i.':'.$random_id.'}', $c, $message);
       
  1048       }
       
  1049     }
       
  1050     
       
  1051     preg_match_all('#\{!if ([A-Za-z_-]*)\}(.*?)\{\/if\}#is', $message, $links);
       
  1052     
       
  1053     for($i=0;$i<sizeof($links[1]);$i++)
       
  1054     {
       
  1055       $message = str_replace('{!if '.$links[1][$i].'}'.$links[2][$i].'{/if}', '{CONDITIONAL:'.$i.':'.$random_id.'}', $message);
       
  1056       if(isset($this->tpl_bool[$links[1][$i]]) && $this->tpl_bool[$links[1][$i]]) {
       
  1057         if(strstr($links[2][$i], '{else}')) $c = substr($links[2][$i], strpos($links[2][$i], '{else}')+6, strlen($links[2][$i]));
       
  1058         else $c = '';
       
  1059         $message = str_replace('{CONDITIONAL:'.$i.':'.$random_id.'}', $c, $message);
       
  1060       } else {
       
  1061         if(strstr($links[2][$i], '{else}')) $c = substr($links[2][$i], 0, strpos($links[2][$i], '{else}'));
       
  1062         else $c = $links[2][$i];
       
  1063         $message = str_replace('{CONDITIONAL:'.$i.':'.$random_id.'}', $c, $message);
       
  1064       }
       
  1065     }
       
  1066     
       
  1067     /*
       
  1068      * HTML RENDERER
       
  1069      */
       
  1070      
       
  1071     // Images
       
  1072     $j = preg_match_all('#\[\[:'.$paths->nslist['File'].'([\w\s0-9_\(\)!@%\^\+\|\.-]+?)\]\]#is', $message, $matchlist);
       
  1073     $matches = Array();
       
  1074     $matches['images'] = $matchlist[1];
       
  1075     for($i=0;$i<sizeof($matchlist[1]);$i++)
       
  1076     {
       
  1077       if(isPage($paths->nslist['File'].$matches['images'][$i]))
       
  1078       {
       
  1079         $message = str_replace('[[:'.$paths->nslist['File'].$matches['images'][$i].']]',
       
  1080                                '<img alt="'.$matches['images'][$i].'" style="border: 0" src="'.makeUrlNS('Special', 'DownloadFile/'.$matches['images'][$i]).'" />',
       
  1081                                $message);
       
  1082       }
       
  1083     }
       
  1084     
       
  1085     // Internal links
       
  1086     
       
  1087     $text_parser = $this->makeParserText($tplvars['sidebar_button']);
       
  1088     
       
  1089     preg_match_all('#\[\[([a-zA-Z0-9 -_]*?)\]\]#is', $message, $il);
       
  1090     for($i=0;$i<sizeof($il[1]);$i++)
       
  1091     {
       
  1092       $href = makeUrl(str_replace(' ', '_', $il[1][$i]), null, true);
       
  1093       $text_parser->assign_vars(Array(
       
  1094           'HREF'  => $href,
       
  1095           'FLAGS' => '',
       
  1096           'TEXT'  => $il[1][$i]
       
  1097         ));
       
  1098       $message = str_replace("[[{$il[1][$i]}]]", $text_parser->run(), $message);
       
  1099     }
       
  1100     
       
  1101     preg_match_all('#\[\[([a-zA-Z0-9 -_]*?)\|([a-zA-Z0-9!@\#\$%\^&\*\(\)\{\} -_]*?)\]\]#is', $message, $il);
       
  1102     for($i=0;$i<sizeof($il[1]);$i++)
       
  1103     {
       
  1104       $href = makeUrl(str_replace(' ', '_', $il[1][$i]), null, true);
       
  1105       $text_parser->assign_vars(Array(
       
  1106           'HREF'  => $href,
       
  1107           'FLAGS' => '',
       
  1108           'TEXT'  => $il[2][$i]
       
  1109         ));
       
  1110       $message = str_replace("[[{$il[1][$i]}|{$il[2][$i]}]]", $text_parser->run(), $message);
       
  1111     }
       
  1112     
       
  1113     // External links
       
  1114     $message = preg_replace('#\[(http|ftp|irc):\/\/([a-z0-9\/:_\.\?&%\#@_\\\\-]+?)\\ ([^\]]+)]#', '<a href="\\1://\\2">\\3</a><br style="display: none;" />', $message);
       
  1115     $message = preg_replace('#\[(http|ftp|irc):\/\/([a-z0-9\/:_\.\?&%\#@_\\\\-]+?)\\]#', '<a href="\\1://\\2">\\1://\\2</a><br style="display: none;" />', $message);
       
  1116     
       
  1117     $parser1 = $this->makeParserText($tplvars['sidebar_section']);
       
  1118     $parser2 = $this->makeParserText($tplvars['sidebar_section_raw']);
       
  1119                             
       
  1120     preg_match_all('#\{slider(2|)=(.*?)\}(.*?)\{\/slider(2|)\}#is',  $message, $sb);
       
  1121     
       
  1122     // Modified to support the sweet new template var system
       
  1123     for($i=0;$i<sizeof($sb[1]);$i++)
       
  1124     {
       
  1125       $p = ($sb[1][$i] == '2') ? $parser2 : $parser1;
       
  1126       $p->assign_vars(Array('TITLE'=>$sb[2][$i],'CONTENT'=>$sb[3][$i]));
       
  1127       $message = str_replace("{slider{$sb[1][$i]}={$sb[2][$i]}}{$sb[3][$i]}{/slider{$sb[4][$i]}}", $p->run(), $message);
       
  1128     }
       
  1129     
       
  1130     /*
       
  1131     Extras ;-)
       
  1132     $message = preg_replace('##is', '', $message);
       
  1133     $message = preg_replace('##is', '', $message);
       
  1134     $message = preg_replace('##is', '', $message);
       
  1135     $message = preg_replace('##is', '', $message);
       
  1136     $message = preg_replace('##is', '', $message);
       
  1137     */
       
  1138     
       
  1139     //die('<pre>'.htmlspecialchars($message).'</pre>');
       
  1140     //eval($message); exit;
       
  1141     return $message;
       
  1142   }
       
  1143   
       
  1144   /**
       
  1145    * Print a text field that auto-completes a username entered into it.
       
  1146    * @param string $name - the name of the form field
       
  1147    * @return string
       
  1148    */
       
  1149    
       
  1150   function username_field($name, $value = false)
       
  1151   {
       
  1152     $randomid = md5( time() . microtime() . mt_rand() );
       
  1153     $text = '<input name="'.$name.'" onkeyup="ajaxUserNameComplete(this)" autocomplete="off" type="text" size="30" id="userfield_'.$randomid.'"';
       
  1154     if($value) $text .= ' value="'.$value.'"';
       
  1155     $text .= ' />';
       
  1156     return $text;
       
  1157   }
       
  1158   
       
  1159   /**
       
  1160    * Print a text field that auto-completes a page name entered into it.
       
  1161    * @param string $name - the name of the form field
       
  1162    * @return string
       
  1163    */
       
  1164    
       
  1165   function pagename_field($name, $value = false)
       
  1166   {
       
  1167     $randomid = md5( time() . microtime() . mt_rand() );
       
  1168     $text = '<input name="'.$name.'" onkeyup="ajaxPageNameComplete(this)" type="text" size="30" id="pagefield_'.$randomid.'"';
       
  1169     if($value) $text .= ' value="'.$value.'"';
       
  1170     $text .= ' />';
       
  1171     $text .= '<script type="text/javascript">
       
  1172         var inp = document.getElementById(\'pagefield_' . $randomid . '\');
       
  1173         var f = get_parent_form(inp);
       
  1174         if ( f )
       
  1175         {
       
  1176           if ( typeof(f.onsubmit) != \'function\' )
       
  1177           {
       
  1178             f.onsubmit = function() {
       
  1179               if ( !submitAuthorized )
       
  1180               {
       
  1181                 return false;
       
  1182               }
       
  1183             }
       
  1184           }
       
  1185         }</script>';
       
  1186     return $text;
       
  1187   }
       
  1188   
       
  1189   /**
       
  1190    * Sends a textarea that can be converted to and from a TinyMCE widget on the fly.
       
  1191    * @param string The name of the form element
       
  1192    * @param string The initial content. Optional, defaults to blank
       
  1193    * @param int Rows in textarea
       
  1194    * @param int Columns in textarea
       
  1195    * @return string HTML and Javascript code.
       
  1196    */
       
  1197   
       
  1198   function tinymce_textarea($name, $content = '', $rows = 20, $cols = 60)
       
  1199   {
       
  1200     $randomid = md5(microtime() . mt_rand());
       
  1201     $html = '';
       
  1202     $html .= '<textarea name="' . $name . '" rows="'.$rows.'" cols="'.$cols.'" style="width: 100%;" id="toggleMCEroot_'.$randomid.'">' . $content . '</textarea>';
       
  1203     $html .= '<div style="float: right; display: table;" id="mceSwitchAgent_' . $randomid . '">text editor&nbsp;&nbsp;|&nbsp;&nbsp;<a href="#" onclick="toggleMCE_'.$randomid.'(); return false;">graphical editor</a></div>';
       
  1204     $html .= '<script type="text/javascript">
       
  1205                 // <![CDATA[
       
  1206                 function toggleMCE_'.$randomid.'()
       
  1207                 {
       
  1208                   var the_obj = document.getElementById(\'toggleMCEroot_' . $randomid . '\');
       
  1209                   var panel = document.getElementById(\'mceSwitchAgent_' . $randomid . '\');
       
  1210                   if ( the_obj.dnIsMCE == "yes" )
       
  1211                   {
       
  1212                     $dynano(the_obj).destroyMCE();
       
  1213                     panel.innerHTML = \'text editor&nbsp;&nbsp;|&nbsp;&nbsp;<a href="#" onclick="toggleMCE_'.$randomid.'(); return false;">graphical editor</a>\';
       
  1214                   }
       
  1215                   else
       
  1216                   {
       
  1217                     $dynano(the_obj).switchToMCE();
       
  1218                     panel.innerHTML = \'<a href="#" onclick="toggleMCE_'.$randomid.'(); return false;">text editor</a>&nbsp;&nbsp;|&nbsp;&nbsp;graphical editor\';
       
  1219                   }
       
  1220                 }
       
  1221                 // ]]>
       
  1222               </script>';
       
  1223     return $html;
       
  1224   }
       
  1225   
       
  1226   /**
       
  1227    * Allows individual parsing of template files. Similar to phpBB but follows the spirit of object-oriented programming ;)
       
  1228    * Returns on object of class templateIndividual. Usage instructions can be found in the inline docs for that class.
       
  1229    * @param $filename the filename of the template to be parsed
       
  1230    * @return object
       
  1231    */
       
  1232    
       
  1233   function makeParser($filename)
       
  1234   {
       
  1235     global $db, $session, $paths, $template, $plugins; // Common objects
       
  1236     $filename = ENANO_ROOT.'/themes/'.$template->theme.'/'.$filename;
       
  1237     if(!file_exists($filename)) die('templateIndividual: file '.$filename.' does not exist');
       
  1238     $code = file_get_contents($filename);
       
  1239     $parser = new templateIndividual($code);
       
  1240     return $parser;
       
  1241   }
       
  1242   
       
  1243   /**
       
  1244    * Same as $template->makeParser(), but takes a string instead of a filename.
       
  1245    * @param $text the text to parse
       
  1246    * @return object
       
  1247    */
       
  1248    
       
  1249   function makeParserText($code)
       
  1250   {
       
  1251     $parser = new templateIndividual($code);
       
  1252     return $parser;
       
  1253   }
       
  1254   
       
  1255   /**
       
  1256    * Fetch the HTML for a plugin-added sidebar block
       
  1257    * @param $name the plugin name
       
  1258    * @return string
       
  1259    */
       
  1260    
       
  1261   function fetch_block($id)
       
  1262   {
       
  1263     if(isset($this->plugin_blocks[$id])) return $this->plugin_blocks[$id];
       
  1264     else return false;
       
  1265   }
       
  1266   
       
  1267   /**
       
  1268    * Fetches the contents of both sidebars.
       
  1269    * @return array - key 0 is left, key 1 is right
       
  1270    * @example list($left, $right) = $template->fetch_sidebar();
       
  1271    */
       
  1272    
       
  1273   function fetch_sidebar()
       
  1274   {
       
  1275     global $db, $session, $paths, $template, $plugins; // Common objects
       
  1276     
       
  1277     $left = '';
       
  1278     $right = '';
       
  1279     
       
  1280     if ( !$this->fetch_block('Links') )
       
  1281       $this->initLinksWidget();
       
  1282     
       
  1283     $q = $db->sql_query('SELECT item_id,sidebar_id,block_name,block_type,block_content FROM '.table_prefix.'sidebar WHERE item_enabled=1 ORDER BY sidebar_id ASC, item_order ASC;');
       
  1284     if(!$q) $db->_die('The sidebar text data could not be selected.');
       
  1285     
       
  1286     $vars = $this->extract_vars('elements.tpl');
       
  1287     
       
  1288     if(isset($vars['sidebar_top'])) 
       
  1289     {
       
  1290       $left  .= $this->parse($vars['sidebar_top']);
       
  1291       $right .= $this->parse($vars['sidebar_top']);
       
  1292     }
       
  1293     while($row = $db->fetchrow())
       
  1294     {
       
  1295       switch($row['block_type'])
       
  1296       {
       
  1297         case BLOCK_WIKIFORMAT:
       
  1298         default:
       
  1299           $parser = $this->makeParserText($vars['sidebar_section']);
       
  1300           $c = RenderMan::render($row['block_content']);
       
  1301           break;
       
  1302         case BLOCK_TEMPLATEFORMAT:
       
  1303           $parser = $this->makeParserText($vars['sidebar_section']);
       
  1304           $c = $this->tplWikiFormat($row['block_content']);
       
  1305           break;
       
  1306         case BLOCK_HTML:
       
  1307           $parser = $this->makeParserText($vars['sidebar_section_raw']);
       
  1308           $c = $row['block_content'];
       
  1309           break;
       
  1310         case BLOCK_PHP:
       
  1311           $parser = $this->makeParserText($vars['sidebar_section_raw']);
       
  1312           ob_start();
       
  1313           @eval($row['block_content']);
       
  1314           $c = ob_get_contents();
       
  1315           ob_end_clean();
       
  1316           break;
       
  1317         case BLOCK_PLUGIN:
       
  1318           $parser = $this->makeParserText($vars['sidebar_section_raw']);
       
  1319           $c = (gettype($this->fetch_block($row['block_content'])) == 'string') ? $this->fetch_block($row['block_content']) : 'Can\'t find plugin block';
       
  1320           break;
       
  1321       }
       
  1322       $parser->assign_vars(Array( 'TITLE'=>$this->tplWikiFormat($row['block_name']), 'CONTENT'=>$c ));
       
  1323       if    ($row['sidebar_id'] == SIDEBAR_LEFT ) $left  .= $parser->run();
       
  1324       elseif($row['sidebar_id'] == SIDEBAR_RIGHT) $right .= $parser->run();
       
  1325       unset($parser);
       
  1326     }
       
  1327     $db->free_result();
       
  1328     if(isset($vars['sidebar_bottom'])) 
       
  1329     {
       
  1330       $left  .= $this->parse($vars['sidebar_bottom']);
       
  1331       $right .= $this->parse($vars['sidebar_bottom']);
       
  1332     }
       
  1333     $min = '';
       
  1334     if(isset($vars['sidebar_top'])) 
       
  1335     {
       
  1336       $min .= $this->parse($vars['sidebar_top']);
       
  1337     }
       
  1338     if(isset($vars['sidebar_bottom']))
       
  1339     {
       
  1340       $min .= $this->parse($vars['sidebar_bottom']);
       
  1341     }
       
  1342     return Array($left, $right, $min);
       
  1343   }
       
  1344   
       
  1345   function initLinksWidget()
       
  1346   {
       
  1347     global $db, $session, $paths, $template, $plugins; // Common objects
       
  1348     // SourceForge/W3C buttons
       
  1349     $ob = Array();
       
  1350     if(getConfig('powered_btn') =='1') $ob[] = '<a style="text-align: center;" href="http://www.enanocms.org/"                  onclick="window.open(this.href);return false;"><img alt="Powered by Enano" src="'.scriptPath.'/images/about-powered-enano.png" onmouseover="this.src=\''.scriptPath.'/images/about-powered-enano-hover.png\';" onmouseout="this.src=\''.scriptPath.'/images/about-powered-enano.png\';" style="border-width: 0px;" width="88" height="31" /></a>';
       
  1351     if(getConfig('sflogo_enabled')=='1')
       
  1352     {
       
  1353       $ob[] = '<a style="text-align: center;" href="http://sourceforge.net/" onclick="window.open(this.href);return false;"><img style="border-width: 0px;" alt="SourceForge.net Logo" src="http://sflogo.sourceforge.net/sflogo.php?group_id='.getConfig('sflogo_groupid').'&amp;type='.getConfig('sflogo_type').'" /></a>';
       
  1354     }
       
  1355     if(getConfig('w3c_v32')     =='1') $ob[] = '<a style="text-align: center;" href="http://validator.w3.org/check?uri=referer" onclick="window.open(this.href);return false;"><img style="border: 0px solid #FFFFFF;" alt="Valid HTML 3.2"  src="http://www.w3.org/Icons/valid-html32" /></a>';
       
  1356     if(getConfig('w3c_v40')     =='1') $ob[] = '<a style="text-align: center;" href="http://validator.w3.org/check?uri=referer" onclick="window.open(this.href);return false;"><img style="border: 0px solid #FFFFFF;" alt="Valid HTML 4.0"  src="http://www.w3.org/Icons/valid-html40" /></a>';
       
  1357     if(getConfig('w3c_v401')    =='1') $ob[] = '<a style="text-align: center;" href="http://validator.w3.org/check?uri=referer" onclick="window.open(this.href);return false;"><img style="border: 0px solid #FFFFFF;" alt="Valid HTML 4.01" src="http://www.w3.org/Icons/valid-html401" /></a>';
       
  1358     if(getConfig('w3c_vxhtml10')=='1') $ob[] = '<a style="text-align: center;" href="http://validator.w3.org/check?uri=referer" onclick="window.open(this.href);return false;"><img style="border: 0px solid #FFFFFF;" alt="Valid XHTML 1.0" src="http://www.w3.org/Icons/valid-xhtml10" /></a>';
       
  1359     if(getConfig('w3c_vxhtml11')=='1') $ob[] = '<a style="text-align: center;" href="http://validator.w3.org/check?uri=referer" onclick="window.open(this.href);return false;"><img style="border: 0px solid #FFFFFF;" alt="Valid XHTML 1.1" src="http://www.w3.org/Icons/valid-xhtml11" /></a>';
       
  1360     if(getConfig('w3c_vcss')    =='1') $ob[] = '<a style="text-align: center;" href="http://validator.w3.org/check?uri=referer" onclick="window.open(this.href);return false;"><img style="border: 0px solid #FFFFFF;" alt="Valid CSS"       src="http://www.w3.org/Icons/valid-css" /></a>';
       
  1361     if(getConfig('dbd_button')  =='1') $ob[] = '<a style="text-align: center;" href="http://www.defectivebydesign.org/join/button" onclick="window.open(this.href);return false;"><img style="border: 0px solid #FFFFFF;" alt="DRM technology restricts what you can do with your computer" src="http://defectivebydesign.org/sites/nodrm.civicactions.net/files/images/dbd_sm_btn.gif" /><br /><small>Protect your freedom >></small></a>';
       
  1362     
       
  1363     $code = $plugins->setHook('links_widget');
       
  1364     foreach ( $code as $cmd )
       
  1365     {
       
  1366       eval($cmd);
       
  1367     }
       
  1368     
       
  1369     if(count($ob) > 0) $sb_links = '<div style="text-align: center; padding: 5px 0;">'.implode('<br />', $ob).'</div>';
       
  1370     else $sb_links = '';
       
  1371     
       
  1372     $this->sidebar_widget('Links', $sb_links);
       
  1373   }
       
  1374   
       
  1375   /**
       
  1376    * Builds a box showing unread private messages.
       
  1377    */
       
  1378   
       
  1379   function notify_unread_pms()
       
  1380   {
       
  1381     global $db, $session, $paths, $template, $plugins; // Common objects
       
  1382     if ( ( $paths->cpage['urlname_nons'] == 'PrivateMessages' || $paths->cpage['urlname_nons'] == 'Preferences' ) && $paths->namespace == 'Special' )
       
  1383     {
       
  1384       return '';
       
  1385     }
       
  1386     $ob = '<div class="usermessage">'."\n";
       
  1387     $s = ( $session->unread_pms == 1 ) ? '' : 's';
       
  1388     $ob .= "  <b>You have $session->unread_pms <a href=" . '"' . makeUrlNS('Special', 'PrivateMessages' ) . '"' . ">unread private message$s</a>.</b><br />\n  Messages: ";
       
  1389     $q = $db->sql_query('SELECT message_id,message_from,subject,date FROM '.table_prefix.'privmsgs WHERE message_to=\'' . $session->username . '\' AND message_read=0 ORDER BY date DESC;');
       
  1390     if ( !$q )
       
  1391       $db->_die();
       
  1392     $messages = array();
       
  1393     while ( $row = $db->fetchrow() )
       
  1394     {
       
  1395       $messages[] = '<a href="' . makeUrlNS('Special', 'PrivateMessages/View/' . $row['message_id']) . '" title="Sent ' . date('F d, Y h:i a', $row['date']) . ' by ' . $row['message_from'] . '">' . $row['subject'] . '</a>';
       
  1396     }
       
  1397     $ob .= implode(",\n    " , $messages)."\n";
       
  1398     $ob .= '</div>'."\n";
       
  1399     return $ob;
       
  1400   }
       
  1401   
       
  1402 } // class template
       
  1403 
       
  1404 /**
       
  1405  * Handles parsing of an individual template file. Instances should only be created through $template->makeParser(). To use:
       
  1406  *   - Call $template->makeParser(template file name) - file name should be something.tpl, css/whatever.css, etc.
       
  1407  *   - Make an array of strings you want the template to access. $array['STRING'] would be referenced in the template like {STRING}
       
  1408  *   - Make an array of boolean values. These can be used for conditionals in the template (<!-- IF something --> whatever <!-- ENDIF something -->)
       
  1409  *   - Call assign_vars() to pass the strings to the template parser. Same thing with assign_bool().
       
  1410  *   - Call run() to parse the template and get your fully compiled HTML.
       
  1411  * @access private
       
  1412  */
       
  1413 
       
  1414 class templateIndividual extends template {
       
  1415   var $tpl_strings, $tpl_bool, $tpl_code;
       
  1416   var $compiled = false;
       
  1417   /**
       
  1418    * Constructor.
       
  1419    */
       
  1420   function __construct($text)
       
  1421   {
       
  1422     global $db, $session, $paths, $template, $plugins; // Common objects
       
  1423     $this->tpl_code = $text;
       
  1424     $this->tpl_strings = $template->tpl_strings;
       
  1425     $this->tpl_bool = $template->tpl_bool;
       
  1426   }
       
  1427   /**
       
  1428    * PHP 4 constructor.
       
  1429    */
       
  1430   function templateIndividual($text)
       
  1431   {
       
  1432     $this->__construct($text);
       
  1433   }
       
  1434   /**
       
  1435    * Assigns an array of string values to the template. Strings can be accessed from the template by inserting {KEY_NAME} in the template file.
       
  1436    * @param $vars array
       
  1437    */
       
  1438   function assign_vars($vars)
       
  1439   {
       
  1440     $this->tpl_strings = array_merge($this->tpl_strings, $vars);
       
  1441   }
       
  1442   /**
       
  1443    * Assigns an array of boolean values to the template. These can be used for <!-- IF ... --> statements.
       
  1444    * @param $vars array
       
  1445    */
       
  1446   function assign_bool($vars)
       
  1447   {
       
  1448     $this->tpl_bool = array_merge($this->tpl_bool, $vars);
       
  1449   }
       
  1450   /**
       
  1451    * Compiles and executes the template code.
       
  1452    * @return string
       
  1453    */
       
  1454   function run()
       
  1455   {
       
  1456     global $db, $session, $paths, $template, $plugins; // Common objects
       
  1457     if(!$this->compiled)
       
  1458     {
       
  1459       $this->tpl_code = $this->compile_template_text($this->tpl_code);
       
  1460       $this->compiled = true;
       
  1461     }
       
  1462     return eval($this->tpl_code);
       
  1463   }
       
  1464 }
       
  1465 
       
  1466 /**
       
  1467  * A version of the template compiler that does not rely at all on the other parts of Enano. Used during installation and for showing
       
  1468  * "critical error" messages. ** REQUIRES ** the Oxygen theme.
       
  1469  */
       
  1470 
       
  1471 class template_nodb {
       
  1472   var $tpl_strings, $tpl_bool, $theme, $style, $no_headers, $additional_headers, $sidebar_extra, $sidebar_widgets, $toolbar_menu, $theme_list;
       
  1473   function __construct() {
       
  1474     
       
  1475     $this->tpl_bool    = Array();
       
  1476     $this->tpl_strings = Array();
       
  1477     $this->sidebar_extra = '';
       
  1478     $this->sidebar_widgets = '';
       
  1479     $this->toolbar_menu = '';
       
  1480     $this->additional_headers = '';
       
  1481     
       
  1482     $this->theme_list = Array(Array(
       
  1483       'theme_id'=>'oxygen',
       
  1484       'theme_name'=>'Oxygen',
       
  1485       'theme_order'=>1,
       
  1486       'enabled'=>1,
       
  1487       ));
       
  1488   }
       
  1489   function template() {
       
  1490     $this->__construct();
       
  1491   }
       
  1492   function get_css($s = false) {
       
  1493     if($s)
       
  1494       return $this->process_template('css/'.$s);
       
  1495     else
       
  1496       return $this->process_template('css/'.$this->style.'.css');
       
  1497   }
       
  1498   function load_theme($name, $css, $auto_init = true) {
       
  1499     $this->theme = $name;
       
  1500     $this->style = $css;
       
  1501     
       
  1502     $this->tpl_strings['SCRIPTPATH'] = scriptPath;
       
  1503     if ( $auto_init )
       
  1504       $this->init_vars();
       
  1505   }
       
  1506   function init_vars()
       
  1507   {
       
  1508     global $sideinfo;
       
  1509     global $this_page;
       
  1510     global $db, $session, $paths, $template, $plugins; // Common objects
       
  1511     $tplvars = $this->extract_vars('elements.tpl');
       
  1512     $tb = '';
       
  1513     // Get the "article" button text (depends on namespace)
       
  1514     if(defined('IN_ENANO_INSTALL')) $ns = 'installation page';
       
  1515     else $ns = 'system error page';
       
  1516     $t = str_replace('{FLAGS}', 'onclick="return false;" title="Hey! A button that doesn\'t do anything. Clever..." accesskey="a"', $tplvars['toolbar_button']);
       
  1517     $t = str_replace('{HREF}', '#', $t);
       
  1518     $t = str_replace('{TEXT}', $ns, $t);
       
  1519     $tb .= $t;
       
  1520     
       
  1521     // Page toolbar
       
  1522     
       
  1523     $this->tpl_bool = Array(
       
  1524       'auth_admin'=>true,
       
  1525       'user_logged_in'=>true,
       
  1526       'right_sidebar'=>false,
       
  1527       );
       
  1528     $this->tpl_bool['in_sidebar_admin'] = false;
       
  1529     
       
  1530     $this->tpl_bool['auth_rename'] = false;
       
  1531     
       
  1532     $asq = $asa = '';
       
  1533     
       
  1534     $this->tpl_bool['fixed_menus'] = false;
       
  1535     $slink = defined('IN_ENANO_INSTALL') ? scriptPath.'/install.php?mode=css' : makeUrlNS('Special', 'CSS');
       
  1536     
       
  1537     $title = ( is_object($paths) ) ? $paths->page : 'Critical error';
       
  1538     
       
  1539     // The rewritten template engine will process all required vars during the load_template stage instead of (cough) re-processing everything each time around.
       
  1540     $tpl_strings = Array(
       
  1541       'PAGE_NAME'=>$this_page,
       
  1542       'PAGE_URLNAME'=>'Null',
       
  1543       'SITE_NAME'=>'Enano Installation',
       
  1544       'USERNAME'=>'admin',
       
  1545       'SITE_DESC'=>'Install Enano on your server.',
       
  1546       'TOOLBAR'=>$tb,
       
  1547       'SCRIPTPATH'=>scriptPath,
       
  1548       'CONTENTPATH'=>contentPath,
       
  1549       'ADMIN_SID_QUES'=>$asq,
       
  1550       'ADMIN_SID_AMP'=>$asa,
       
  1551       'ADMIN_SID_AMP_HTML'=>'',
       
  1552       'ADDITIONAL_HEADERS'=>'<style type="text/css">div.pagenav { border-top: 1px solid #CCC; padding-top: 7px; margin-top: 10px; }</style>',
       
  1553       'SIDEBAR_EXTRA'=>'',
       
  1554       'COPYRIGHT'=>'Enano and all of its code, graphics, and more code is copyright &copy; 2006 Dan Fuhry.<br />This program is Free Software; see the file "GPL" included with this package for details.',
       
  1555       'TOOLBAR_EXTRAS'=>'',
       
  1556       'REQUEST_URI'=>$_SERVER['HTTP_HOST'].$_SERVER['REQUEST_URI'],
       
  1557       'STYLE_LINK'=>$slink,
       
  1558       'LOGOUT_LINK'=>'',
       
  1559       'THEME_LINK'=>'',
       
  1560       'TEMPLATE_DIR'=>scriptPath.'/themes/'.$this->theme,
       
  1561       'THEME_ID'=>$this->theme,
       
  1562       'STYLE_ID'=>$this->style,
       
  1563       'JS_DYNAMIC_VARS'=>'<script type="text/javascript">var title="'. $title .'"; var scriptPath="'.scriptPath.'"; var ENANO_SID=""; var AES_BITS='.AES_BITS.'; var AES_BLOCKSIZE=' . AES_BLOCKSIZE . '; var pagepass=\'\';</script>',
       
  1564       'SIDEBAR_RIGHT'=>'',
       
  1565       );
       
  1566     $this->tpl_strings = array_merge($tpl_strings, $this->tpl_strings);
       
  1567     
       
  1568     $sidebar = ( gettype($sideinfo) == 'string' ) ? $sideinfo : '';
       
  1569     if($sidebar != '')
       
  1570     {
       
  1571       if(isset($tplvars['sidebar_top']))
       
  1572       {
       
  1573         $text = $this->makeParserText($tplvars['sidebar_top']);
       
  1574         $top = $text->run();
       
  1575       } else {
       
  1576         $top = '';
       
  1577       }
       
  1578       $p = $this->makeParserText($tplvars['sidebar_section']);
       
  1579       $p->assign_vars(Array(
       
  1580           'TITLE'=>'Installation progress',
       
  1581           'CONTENT'=>$sidebar,
       
  1582         ));
       
  1583       $sidebar = $p->run();
       
  1584       if(isset($tplvars['sidebar_bottom']))
       
  1585       {
       
  1586         $text = $this->makeParserText($tplvars['sidebar_bottom']);
       
  1587         $bottom = $text->run();
       
  1588       } else {
       
  1589         $bottom = '';
       
  1590       }
       
  1591       $sidebar = $top . $sidebar . $bottom;
       
  1592     }
       
  1593     $this->tpl_strings['SIDEBAR_LEFT'] = $sidebar;
       
  1594     
       
  1595     $this->tpl_bool['sidebar_left']  = ( $this->tpl_strings['SIDEBAR_LEFT']  != '') ? true : false;
       
  1596     $this->tpl_bool['sidebar_right'] = ( $this->tpl_strings['SIDEBAR_RIGHT'] != '') ? true : false;
       
  1597     $this->tpl_bool['right_sidebar'] = $this->tpl_bool['sidebar_right']; // backward compatibility
       
  1598     $this->tpl_bool['stupid_mode'] = true;
       
  1599   }
       
  1600   function header() 
       
  1601   {
       
  1602     if(!$this->no_headers) echo $this->process_template('header.tpl');
       
  1603   }
       
  1604   function footer()
       
  1605   {
       
  1606     global $db, $session, $paths, $template, $plugins; // Common objects
       
  1607     if(!$this->no_headers) {
       
  1608       global $_starttime;
       
  1609       $f = microtime(true);
       
  1610       $f = $f - $_starttime;
       
  1611       $f = round($f, 4);
       
  1612       if(defined('IN_ENANO_INSTALL')) $nq = 'N/A';
       
  1613       else $nq = $db->num_queries;
       
  1614       if($nq == 0) $nq = 'N/A';
       
  1615       $dbg = 'Time: '.$f.'s  |  Queries: '.$nq;
       
  1616       $t = $this->process_template('footer.tpl');
       
  1617       $t = str_replace('[[Stats]]', $dbg, $t);
       
  1618       echo $t;
       
  1619     }
       
  1620     else return '';
       
  1621   }
       
  1622   function getHeader()
       
  1623   {
       
  1624     if(!$this->no_headers) return $this->process_template('header.tpl');
       
  1625     else return '';
       
  1626   }
       
  1627   function getFooter()
       
  1628   {
       
  1629     global $db, $session, $paths, $template, $plugins; // Common objects
       
  1630     if(!$this->no_headers) {
       
  1631       global $_starttime;
       
  1632       $f = microtime(true);
       
  1633       $f = $f - $_starttime;
       
  1634       $f = round($f, 4);
       
  1635       if(defined('IN_ENANO_INSTALL')) $nq = 'N/A';
       
  1636       else $nq = $db->num_queries;
       
  1637       if($nq == 0) $nq = 'N/A';
       
  1638       $dbg = 'Time: '.$f.'s  |  Queries: '.$nq;
       
  1639       if($nq == 0) $nq = 'N/A';
       
  1640       $t = $this->process_template('footer.tpl');
       
  1641       $t = str_replace('[[Stats]]', $dbg, $t);
       
  1642       return $t;
       
  1643     }
       
  1644     else return '';
       
  1645   }
       
  1646   
       
  1647   function process_template($file) {
       
  1648     
       
  1649     eval($this->compile_template($file));
       
  1650     return $tpl_code;
       
  1651   }
       
  1652   
       
  1653   function extract_vars($file) {
       
  1654     global $db, $session, $paths, $template, $plugins; // Common objects
       
  1655     if(!is_file(ENANO_ROOT . '/themes/'.$this->theme.'/'.$file)) die('Cannot find '.$file.' file for style "'.$this->theme.'", exiting');
       
  1656     $text = file_get_contents(ENANO_ROOT . '/themes/'.$this->theme.'/'.$file);
       
  1657     preg_match_all('#<\!-- VAR ([A-z0-9_-]*) -->(.*?)<\!-- ENDVAR \\1 -->#is', $text, $matches);
       
  1658     $tplvars = Array();
       
  1659     for($i=0;$i<sizeof($matches[1]);$i++)
       
  1660     {
       
  1661       $tplvars[$matches[1][$i]] = $matches[2][$i];
       
  1662     }
       
  1663     return $tplvars;
       
  1664   }
       
  1665   function compile_template($text) {
       
  1666     global $sideinfo;
       
  1667     $text = file_get_contents(ENANO_ROOT . '/themes/'.$this->theme.'/'.$text);
       
  1668     $text = str_replace('<script type="text/javascript" src="{SCRIPTPATH}/ajax.php?title={PAGE_URLNAME}&amp;_mode=jsres"></script>', '', $text); // Remove the AJAX code - we don't need it, and it requires a database connection
       
  1669     $text = '$tpl_code = \''.str_replace('\'', '\\\'', $text).'\'; return $tpl_code;';
       
  1670     $text = preg_replace('#<!-- BEGIN (.*?) -->#is', '\'; if($this->tpl_bool[\'\\1\']) { $tpl_code .= \'', $text);
       
  1671     $text = preg_replace('#<!-- IFPLUGIN (.*?) -->#is', '\'; if(getConfig(\'plugin_\\1\')==\'1\') { $tpl_code .= \'', $text);
       
  1672     if(defined('IN_ENANO_INSTALL')) $text = str_replace('<!-- SYSMSG Sidebar -->', '<div class="slider"><div class="heading"><a class="head">Installation progress</a></div><div class="slideblock">'.$sideinfo.'</div></div>', $text);
       
  1673     else $text = str_replace('<!-- SYSMSG Sidebar -->', '<div class="slider"><div class="heading"><a class="head">System error</a></div><div class="slideblock"><a href="#" onclick="return false;">Enano critical error page</a></div></div>', $text);
       
  1674     $text = preg_replace('#<!-- SYSMSG (.*?) -->#is', '', $text);
       
  1675     $text = preg_replace('#<!-- BEGINNOT (.*?) -->#is', '\'; if(!$this->tpl_bool[\'\\1\']) { $tpl_code .= \'', $text);
       
  1676     $text = preg_replace('#<!-- BEGINELSE (.*?) -->#is', '\'; } else { $tpl_code .= \'', $text);
       
  1677     $text = preg_replace('#<!-- END (.*?) -->#is', '\'; } $tpl_code .= \'', $text);
       
  1678     $text = preg_replace('#{([A-z0-9]*)}#is', '\'.$this->tpl_strings[\'\\1\'].\'', $text);
       
  1679     return $text; //('<pre>'.htmlspecialchars($text).'</pre>');
       
  1680   }
       
  1681   
       
  1682   function compile_template_text($text) {
       
  1683     global $sideinfo;
       
  1684     $text = str_replace('<script type="text/javascript" src="{SCRIPTPATH}/ajax.php?title={PAGE_URLNAME}&amp;_mode=jsres"></script>', '', $text); // Remove the AJAX code - we don't need it, and it requires a database connection
       
  1685     $text = '$tpl_code = \''.str_replace('\'', '\\\'', $text).'\'; return $tpl_code;';
       
  1686     $text = preg_replace('#<!-- BEGIN (.*?) -->#is', '\'; if($this->tpl_bool[\'\\1\']) { $tpl_code .= \'', $text);
       
  1687     $text = preg_replace('#<!-- IFPLUGIN (.*?) -->#is', '\'; if(getConfig(\'plugin_\\1\')==\'1\') { $tpl_code .= \'', $text);
       
  1688     if(defined('IN_ENANO_INSTALL')) $text = str_replace('<!-- SYSMSG Sidebar -->', '<div class="slider"><div class="heading"><a class="head">Installation progress</a></div><div class="slideblock">'.$sideinfo.'</div></div>', $text);
       
  1689     else $text = str_replace('<!-- SYSMSG Sidebar -->', '<div class="slider"><div class="heading"><a class="head">System error</a></div><div class="slideblock"><a href="#" onclick="return false;">Enano critical error page</a></div></div>', $text);
       
  1690     $text = preg_replace('#<!-- SYSMSG (.*?) -->#is', '', $text);
       
  1691     $text = preg_replace('#<!-- BEGINNOT (.*?) -->#is', '\'; if(!$this->tpl_bool[\'\\1\']) { $tpl_code .= \'', $text);
       
  1692     $text = preg_replace('#<!-- BEGINELSE (.*?) -->#is', '\'; } else { $tpl_code .= \'', $text);
       
  1693     $text = preg_replace('#<!-- END (.*?) -->#is', '\'; } $tpl_code .= \'', $text);
       
  1694     $text = preg_replace('#{([A-z0-9]*)}#is', '\'.$this->tpl_strings[\'\\1\'].\'', $text);
       
  1695     return $text; //('<pre>'.htmlspecialchars($text).'</pre>');
       
  1696   }
       
  1697   
       
  1698   /**
       
  1699    * Allows individual parsing of template files. Similar to phpBB but follows the spirit of object-oriented programming ;)
       
  1700    * Returns on object of class templateIndividual. Usage instructions can be found in the inline docs for that class.
       
  1701    * @param $filename the filename of the template to be parsed
       
  1702    * @return object
       
  1703    */
       
  1704    
       
  1705   function makeParser($filename)
       
  1706   {
       
  1707     $filename = ENANO_ROOT.'/themes/'.$this->theme.'/'.$filename;
       
  1708     if(!file_exists($filename)) die('templateIndividual: file '.$filename.' does not exist');
       
  1709     $code = file_get_contents($filename);
       
  1710     $parser = new templateIndividualSafe($code, $this);
       
  1711     return $parser;
       
  1712   }
       
  1713   
       
  1714   /**
       
  1715    * Same as $template->makeParser(), but takes a string instead of a filename.
       
  1716    * @param $text the text to parse
       
  1717    * @return object
       
  1718    */
       
  1719    
       
  1720   function makeParserText($code)
       
  1721   {
       
  1722     $parser = new templateIndividualSafe($code, $this);
       
  1723     return $parser;
       
  1724   }
       
  1725    
       
  1726 } // class template_nodb
       
  1727 
       
  1728 /**
       
  1729  * Identical to templateIndividual, except extends template_nodb instead of template
       
  1730  * @see class template
       
  1731  */
       
  1732  
       
  1733 class templateIndividualSafe extends template_nodb {
       
  1734   var $tpl_strings, $tpl_bool, $tpl_code;
       
  1735   var $compiled = false;
       
  1736   /**
       
  1737    * Constructor.
       
  1738    */
       
  1739   function __construct($text, $parent)
       
  1740   {
       
  1741     global $db, $session, $paths, $template, $plugins; // Common objects
       
  1742     $this->tpl_code = $text;
       
  1743     $this->tpl_strings = $parent->tpl_strings;
       
  1744     $this->tpl_bool = $parent->tpl_bool;
       
  1745   }
       
  1746   /**
       
  1747    * PHP 4 constructor.
       
  1748    */
       
  1749   function templateIndividual($text)
       
  1750   {
       
  1751     $this->__construct($text);
       
  1752   }
       
  1753   /**
       
  1754    * Assigns an array of string values to the template. Strings can be accessed from the template by inserting {KEY_NAME} in the template file.
       
  1755    * @param $vars array
       
  1756    */
       
  1757   function assign_vars($vars)
       
  1758   {
       
  1759     if(is_array($this->tpl_strings))
       
  1760       $this->tpl_strings = array_merge($this->tpl_strings, $vars);
       
  1761     else
       
  1762       $this->tpl_strings = $vars;
       
  1763   }
       
  1764   /**
       
  1765    * Assigns an array of boolean values to the template. These can be used for <!-- IF ... --> statements.
       
  1766    * @param $vars array
       
  1767    */
       
  1768   function assign_bool($vars)
       
  1769   {
       
  1770     $this->tpl_bool = array_merge($this->tpl_bool, $vars);
       
  1771   }
       
  1772   /**
       
  1773    * Compiles and executes the template code.
       
  1774    * @return string
       
  1775    */
       
  1776   function run()
       
  1777   {
       
  1778     global $db, $session, $paths, $template, $plugins; // Common objects
       
  1779     if(!$this->compiled)
       
  1780     {
       
  1781       $this->tpl_code = $this->compile_template_text($this->tpl_code);
       
  1782       $this->compiled = true;
       
  1783     }
       
  1784     return eval($this->tpl_code);
       
  1785   }
       
  1786 }
       
  1787 
       
  1788 ?>