diff -r 902822492a68 -r fe660c52c48f includes/template.php
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/includes/template.php Wed Jun 13 16:07:17 2007 -0400
@@ -0,0 +1,1788 @@
+tpl_bool = Array();
+ $this->tpl_strings = Array();
+ $this->sidebar_extra = '';
+ $this->toolbar_menu = '';
+ $this->additional_headers = '';
+ $this->plugin_blocks = Array();
+ $this->theme_loaded = false;
+
+ $this->theme_list = Array();
+ $this->named_theme_list = Array();
+ $e = $db->sql_query('SELECT theme_id,theme_name,enabled,default_style FROM '.table_prefix.'themes WHERE enabled=1 ORDER BY theme_order;');
+ if(!$e) $db->_die('The list of themes could not be selected.');
+ for($i=0;$i < $db->numrows(); $i++)
+ {
+ $this->theme_list[$i] = $db->fetchrow();
+ $this->named_theme_list[$this->theme_list[$i]['theme_id']] = $this->theme_list[$i];
+ }
+ $db->free_result();
+ $this->default_theme = $this->theme_list[0]['theme_id'];
+ $dir = ENANO_ROOT.'/themes/'.$this->default_theme.'/css/';
+ $list = Array();
+ // Open a known directory, and proceed to read its contents
+ if (is_dir($dir)) {
+ if ($dh = opendir($dir)) {
+ while (($file = readdir($dh)) !== false) {
+ if(preg_match('#^(.*?)\.css$#i', $file) && $file != '_printable.css') {
+ $list[] = substr($file, 0, strlen($file)-4);
+ }
+ }
+ closedir($dh);
+ }
+ }
+
+ $def = ENANO_ROOT.'/themes/'.$this->default_theme.'/css/'.$this->named_theme_list[$this->default_theme]['default_style'];
+ if(file_exists($def))
+ {
+ $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);
+ } else {
+ $this->default_style = $list[0];
+ }
+
+ $this->style_list = $list;
+
+ }
+ function template()
+ {
+ $this->__construct();
+ }
+ function sidebar_widget($t, $h)
+ {
+ global $db, $session, $paths, $template, $plugins; // Common objects
+ if(!defined('ENANO_TEMPLATE_LOADED'))
+ {
+ $this->load_theme($session->theme, $session->style);
+ }
+ if(!$this->sidebar_widgets)
+ $this->sidebar_widgets = '';
+ $tplvars = $this->extract_vars('elements.tpl');
+ $parser = $this->makeParserText($tplvars['sidebar_section_raw']);
+ $parser->assign_vars(Array('TITLE'=>$t,'CONTENT'=>$h));
+ $this->plugin_blocks[$t] = $h;
+ $this->sidebar_widgets .= $parser->run();
+ }
+ function add_header($html)
+ {
+ $this->additional_headers .= "\n" . $html;
+ }
+ function get_css($s = false)
+ {
+ global $db, $session, $paths, $template, $plugins; // Common objects
+ if(!defined('ENANO_TEMPLATE_LOADED'))
+ $this->load_theme($session->theme, $session->style);
+ $path = ( $s ) ? 'css/'.$s : 'css/'.$this->style.'.css';
+ if ( !file_exists(ENANO_ROOT . '/themes/' . $this->theme . '/' . $path) )
+ {
+ echo "/* WARNING: Falling back to default file because file $path does not exist */\n";
+ $path = 'css/' . $this->style_list[0] . '.css';
+ }
+ return $this->process_template($path);
+ }
+ function load_theme($name = false, $css = false)
+ {
+ global $db, $session, $paths, $template, $plugins; // Common objects
+ $this->theme = ( $name ) ? $name : $session->theme;
+ $this->style = ( $css ) ? $css : $session->style;
+ if ( !$this->theme )
+ {
+ $this->theme = $this->theme_list[0]['theme_id'];
+ $this->style = substr($this->theme_list[0]['default_style'], 0, strlen($this->theme_list[0]['default_style'])-4);
+ }
+ $this->theme_loaded = true;
+ }
+
+ function init_vars()
+ {
+ global $db, $session, $paths, $template, $plugins; // Common objects
+ global $email;
+
+ dc_here("template: initializing all variables");
+
+ if(!$this->theme || !$this->style)
+ {
+ $this->load_theme();
+ }
+
+ if(defined('ENANO_TEMPLATE_LOADED'))
+ {
+ dc_here('template: access denied to call template::init_vars(), bailing out');
+ die_semicritical('Illegal call', '
$template->load_theme was called multiple times, this is not supposed to happen. Exiting with fatal error.
');
+ }
+
+ define('ENANO_TEMPLATE_LOADED', '');
+
+ $tplvars = $this->extract_vars('elements.tpl');
+
+ dc_here('template: setting all template vars');
+
+ if(isset($_SERVER['HTTP_USER_AGENT']) && strstr($_SERVER['HTTP_USER_AGENT'], 'MSIE'))
+ {
+ $this->add_header('
+
+ ');
+ }
+
+ // Get the "article" button text (depends on namespace)
+ switch($paths->namespace) {
+ case "Article":
+ default:
+ $ns = 'article';
+ break;
+ case "Admin":
+ $ns = 'administration page';
+ break;
+ case "System":
+ $ns = 'system message';
+ break;
+ case "File":
+ $ns = 'uploaded file';
+ break;
+ case "Help":
+ $ns = 'documentation page';
+ break;
+ case "User":
+ $ns = 'user page';
+ break;
+ case "Special":
+ $ns = 'special page';
+ break;
+ case "Template":
+ $ns = 'template';
+ break;
+ case "Project":
+ $ns = 'project page';
+ break;
+ case "Category":
+ $ns = 'category';
+ break;
+ }
+ $this->namespace_string = $ns;
+ $code = $plugins->setHook('page_type_string_set');
+ foreach ( $code as $cmd )
+ {
+ eval($cmd);
+ }
+ $ns =& $this->namespace_string;
+
+ // Initialize the toolbar
+ $tb = '';
+
+ // Create "xx page" button
+
+ $btn_selected = ( isset($tplvars['toolbar_button_selected'])) ? $tplvars['toolbar_button_selected'] : $tplvars['toolbar_button'];
+ $parser = $this->makeParserText($btn_selected);
+
+ $parser->assign_vars(array(
+ '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"',
+ 'PARENTFLAGS' => 'id="mdgToolbar_article"',
+ 'HREF' => makeUrl($paths->page, null, true),
+ 'TEXT' => $this->namespace_string
+ ));
+
+ $tb .= $parser->run();
+
+ $button = $this->makeParserText($tplvars['toolbar_button']);
+
+ // Page toolbar
+ // Comments button
+ if ( $session->get_permissions('read') && getConfig('enable_comments')=='1' && $paths->namespace != 'Special' && $paths->namespace != 'Admin' && $paths->cpage['comments_on'] == 1 )
+ {
+
+ $e = $db->sql_query('SELECT approved FROM '.table_prefix.'comments WHERE page_id=\''.$paths->cpage['urlname_nons'].'\' AND namespace=\''.$paths->namespace.'\';');
+ if ( !$e )
+ {
+ $db->_die();
+ }
+ $nc = $db->numrows();
+ $nu = 0;
+ $na = 0;
+
+ while ( $r = $db->fetchrow() )
+ {
+ if ( !$r['approved'] )
+ {
+ $nu++;
+ }
+ else
+ {
+ $na++;
+ }
+ }
+
+ $db->free_result();
+ $n = ( $session->get_permissions('mod_comments') ) ? (string)$nc : (string)$na;
+ if ( $session->get_permissions('mod_comments') && $nu > 0 )
+ {
+ $n .= ' total/'.$nu.' unapp.';
+ }
+
+ $button->assign_vars(array(
+ 'FLAGS' => 'onclick="void(ajaxComments()); return false;" title="View the comments that other users have posted about this page (alt-c)" accesskey="c"',
+ 'PARENTFLAGS' => 'id="mdgToolbar_discussion"',
+ 'HREF' => makeUrl($paths->page, 'do=comments', true),
+ 'TEXT' => 'discussion ('.$n.')',
+ ));
+
+ $tb .= $button->run();
+ }
+ // Edit button
+ 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 ) ) )
+ {
+ $button->assign_vars(array(
+ 'FLAGS' => 'onclick="void(ajaxEditor()); return false;" title="Edit the contents of this page (alt-e)" accesskey="e"',
+ 'PARENTFLAGS' => 'id="mdgToolbar_edit"',
+ 'HREF' => makeUrl($paths->page, 'do=edit', true),
+ 'TEXT' => 'edit this page'
+ ));
+ $tb .= $button->run();
+ // View source button
+ }
+ 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')
+ {
+ $button->assign_vars(array(
+ 'FLAGS' => 'onclick="void(ajaxViewSource()); return false;" title="View the source code (wiki markup) that this page uses (alt-e)" accesskey="e"',
+ 'PARENTFLAGS' => 'id="mdgToolbar_edit"',
+ 'HREF' => makeUrl($paths->page, 'do=viewsource', true),
+ 'TEXT' => 'view source'
+ ));
+ $tb .= $button->run();
+ }
+ // History button
+ if ( $session->get_permissions('read') /* && $paths->wiki_mode */ && $paths->page_exists && $paths->namespace != 'Special' && $paths->namespace != 'Admin' && $session->get_permissions('history_view') )
+ {
+ $button->assign_vars(array(
+ 'FLAGS' => 'onclick="void(ajaxHistory()); return false;" title="View a log of actions taken on this page (alt-h)" accesskey="h"',
+ 'PARENTFLAGS' => 'id="mdgToolbar_history"',
+ 'HREF' => makeUrl($paths->page, 'do=history', true),
+ 'TEXT' => 'history'
+ ));
+ $tb .= $button->run();
+ }
+
+ $menubtn = $this->makeParserText($tplvars['toolbar_menu_button']);
+
+ // Additional actions menu
+ // Rename button
+ 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' )
+ {
+ $menubtn->assign_vars(array(
+ 'FLAGS' => 'onclick="void(ajaxRename()); return false;" title="Change the display name of this page (alt-r)" accesskey="r"',
+ 'HREF' => makeUrl($paths->page, 'do=rename', true),
+ 'TEXT' => 'rename',
+ ));
+ $this->toolbar_menu .= $menubtn->run();
+ }
+
+ // Vote-to-delete button
+ if ( $paths->wiki_mode && $session->get_permissions('vote_delete') && $paths->page_exists && $paths->namespace != 'Special' && $paths->namespace != 'Admin')
+ {
+ $menubtn->assign_vars(array(
+ 'FLAGS' => 'onclick="void(ajaxDelVote()); return false;" title="Vote to have this page deleted (alt-d)" accesskey="d"',
+ 'HREF' => makeUrl($paths->page, 'do=delvote', true),
+ 'TEXT' => 'vote to delete this page',
+ ));
+ $this->toolbar_menu .= $menubtn->run();
+ }
+
+ // Clear-votes button
+ 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)
+ {
+ $menubtn->assign_vars(array(
+ 'FLAGS' => 'onclick="void(ajaxResetDelVotes()); return false;" title="Vote to have this page deleted (alt-y)" accesskey="y"',
+ 'HREF' => makeUrl($paths->page, 'do=resetvotes', true),
+ 'TEXT' => 'reset deletion votes',
+ ));
+ $this->toolbar_menu .= $menubtn->run();
+ }
+
+ // Printable page button
+ if ( $paths->page_exists && $paths->namespace != 'Special' && $paths->namespace != 'Admin' )
+ {
+ $menubtn->assign_vars(array(
+ 'FLAGS' => 'title="View a version of this page that is suitable for printing"',
+ 'HREF' => makeUrl($paths->page, 'printable=yes', true),
+ 'TEXT' => 'view printable version',
+ ));
+ $this->toolbar_menu .= $menubtn->run();
+ }
+
+ // Protect button
+ if($session->get_permissions('read') && $paths->wiki_mode && $paths->page_exists && $paths->namespace != 'Special' && $paths->namespace != 'Admin' && $session->get_permissions('protect'))
+ {
+
+ $label = $this->makeParserText($tplvars['toolbar_label']);
+ $label->assign_vars(array('TEXT' => 'protection:'));
+ $t0 = $label->run();
+
+ $ctmp = '';
+ if ( $paths->cpage['protected'] == 1 )
+ {
+ $ctmp=' style="text-decoration: underline;"';
+ }
+ $menubtn->assign_vars(array(
+ 'FLAGS' => 'accesskey="i" onclick="ajaxProtect(1); return false;" id="protbtn_1" title="Prevents all non-administrators from editing this page. [alt-i]"'.$ctmp,
+ 'HREF' => makeUrl($paths->page, 'do=protect&level=1', true),
+ 'TEXT' => 'on'
+ ));
+ $t1 = $menubtn->run();
+
+ $ctmp = '';
+ if ( $paths->cpage['protected'] == 0 )
+ {
+ $ctmp=' style="text-decoration: underline;"';
+ }
+ $menubtn->assign_vars(array(
+ 'FLAGS' => 'accesskey="o" onclick="ajaxProtect(0); return false;" id="protbtn_0" title="Allows everyone to edit this page. [alt-o]"'.$ctmp,
+ 'HREF' => makeUrl($paths->page, 'do=protect&level=0', true),
+ 'TEXT' => 'off'
+ ));
+ $t2 = $menubtn->run();
+
+ $ctmp = '';
+ if ( $paths->cpage['protected'] == 2 )
+ {
+ $ctmp = ' style="text-decoration: underline;"';
+ }
+ $menubtn->assign_vars(array(
+ '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,
+ 'HREF' => makeUrl($paths->page, 'do=protect&level=2', true),
+ 'TEXT' => 'semi'
+ ));
+ $t3 = $menubtn->run();
+
+ $this->toolbar_menu .= '
+
+ '.$t0.'
+ '.$t1.'
+ '.$t2.'
+ '.$t3.'
+
+
';
+ }
+
+ // Wiki mode button
+ if($session->get_permissions('read') && $paths->page_exists && $session->get_permissions('set_wiki_mode') && $paths->namespace != 'Special' && $paths->namespace != 'Admin')
+ {
+ // label at start
+ $label = $this->makeParserText($tplvars['toolbar_label']);
+ $label->assign_vars(array('TEXT' => 'page wiki mode:'));
+ $t0 = $label->run();
+
+ // on button
+ $ctmp = '';
+ if ( $paths->cpage['wiki_mode'] == 1 )
+ {
+ $ctmp = ' style="text-decoration: underline;"';
+ }
+ $menubtn->assign_vars(array(
+ 'FLAGS' => 'onclick="ajaxSetWikiMode(1); return false;" id="wikibtn_1" title="Forces wiki functions to be allowed on this page."'.$ctmp,
+ 'HREF' => makeUrl($paths->page, 'do=setwikimode&level=1', true),
+ 'TEXT' => 'on'
+ ));
+ $t1 = $menubtn->run();
+
+ // off button
+ $ctmp = '';
+ if ( $paths->cpage['wiki_mode'] == 0 )
+ {
+ $ctmp=' style="text-decoration: underline;"';
+ }
+ $menubtn->assign_vars(array(
+ 'FLAGS' => 'onclick="ajaxSetWikiMode(0); return false;" id="wikibtn_0" title="Forces wiki functions to be disabled on this page."'.$ctmp,
+ 'HREF' => makeUrl($paths->page, 'do=setwikimode&level=0', true),
+ 'TEXT' => 'off'
+ ));
+ $t2 = $menubtn->run();
+
+ // global button
+ $ctmp = '';
+ if ( $paths->cpage['wiki_mode'] == 2 )
+ {
+ $ctmp=' style="text-decoration: underline;"';
+ }
+ $menubtn->assign_vars(array(
+ 'FLAGS' => 'onclick="ajaxSetWikiMode(2); return false;" id="wikibtn_2" title="Causes this page to use the global wiki mode setting (default)"'.$ctmp,
+ 'HREF' => makeUrl($paths->page, 'do=setwikimode&level=2', true),
+ 'TEXT' => 'global'
+ ));
+ $t3 = $menubtn->run();
+
+ // Tack it onto the list of buttons that are already there...
+ $this->toolbar_menu .= '
+
+ '.$t0.'
+ '.$t1.'
+ '.$t2.'
+ '.$t3.'
+
+
';
+ }
+
+ // Clear logs button
+ if ( $session->get_permissions('read') && $session->get_permissions('clear_logs') && $paths->wiki_mode && $paths->namespace != 'Special' && $paths->namespace != 'Admin' )
+ {
+ $menubtn->assign_vars(array(
+ 'FLAGS' => 'onclick="void(ajaxClearLogs()); return false;" title="Remove all edit and action logs for this page from the database. IRREVERSIBLE! (alt-l)" accesskey="l"',
+ 'HREF' => makeUrl($paths->page, 'do=flushlogs', true),
+ 'TEXT' => 'clear page logs',
+ ));
+ $this->toolbar_menu .= $menubtn->run();
+ }
+
+ // Delete page button
+ if ( $session->get_permissions('read') && $session->get_permissions('delete_page') && $paths->page_exists && $paths->namespace != 'Special' && $paths->namespace != 'Admin' )
+ {
+ $s = 'delete this page';
+ if ( $paths->cpage['delvotes'] == 1 )
+ {
+ $s .= ' ('.$paths->cpage['delvotes'].' vote)';
+ }
+ else if ( $paths->cpage['delvotes'] > 1 )
+ {
+ $s .= ' ('.$paths->cpage['delvotes'].' votes)';
+ }
+
+ $menubtn->assign_vars(array(
+ 'FLAGS' => 'onclick="void(ajaxDeletePage()); return false;" title="Delete this page. This is always reversible unless the logs are cleared. (alt-k)" accesskey="k"',
+ 'HREF' => makeUrl($paths->page, 'do=deletepage', true),
+ 'TEXT' => $s,
+ ));
+ $this->toolbar_menu .= $menubtn->run();
+
+ }
+
+ // Password-protect button
+ if(isset($paths->cpage['password']))
+ {
+ if ( $paths->cpage['password'] == '' )
+ {
+ $a = $session->get_permissions('password_set');
+ }
+ else
+ {
+ $a = $session->get_permissions('password_reset');
+ }
+ }
+ else
+ {
+ $a = $session->get_permissions('password_set');
+ }
+ if ( $a && $session->get_permissions('read') && $paths->page_exists && $paths->namespace != 'Special' && $paths->namespace != 'Admin' )
+ {
+ // label at start
+ $label = $this->makeParserText($tplvars['toolbar_label']);
+ $label->assign_vars(array('TEXT' => 'password:'));
+ $t0 = $label->run();
+
+ $menubtn->assign_vars(array(
+ 'FLAGS' => 'onclick="void(ajaxSetPassword()); return false;" title="Require a password in order for this page to be viewed"',
+ 'HREF' => '#',
+ 'TEXT' => 'set',
+ ));
+ $t = $menubtn->run();
+
+ $this->toolbar_menu .= '';
+ }
+
+ // Manage ACLs button
+ if($session->get_permissions('edit_acl') || $session->user_level >= USER_LEVEL_ADMIN)
+ {
+ $menubtn->assign_vars(array(
+ 'FLAGS' => 'onclick="return ajaxOpenACLManager();" title="Manage who can do what with this page (alt-m)" accesskey="m"',
+ 'HREF' => makeUrl($paths->page, 'do=aclmanager', true),
+ 'TEXT' => 'manage page access',
+ ));
+ $this->toolbar_menu .= $menubtn->run();
+ }
+
+ // Administer page button
+ if ( $session->user_level >= USER_LEVEL_ADMIN && $paths->page_exists && $paths->namespace != 'Special' && $paths->namespace != 'Admin' )
+ {
+ $menubtn->assign_vars(array(
+ 'FLAGS' => 'onclick="void(ajaxAdminPage()); return false;" title="Administrative options for this page" accesskey="g"',
+ 'HREF' => makeUrlNS('Special', 'Administration', 'module='.$paths->nslist['Admin'].'PageManager', true),
+ 'TEXT' => 'administrative options',
+ ));
+ $this->toolbar_menu .= $menubtn->run();
+ }
+
+ if ( strlen($this->toolbar_menu) > 0 )
+ {
+ $button->assign_vars(array(
+ 'FLAGS' => 'id="mdgToolbar_moreoptions" onclick="return false;" title="Additional options for working with this page"',
+ 'PARENTFLAGS' => '',
+ 'HREF' => makeUrl($paths->page, 'do=moreoptions', true),
+ 'TEXT' => 'more options'
+ ));
+ $tb .= $button->run();
+ }
+
+ $is_opera = (isset($_SERVER['HTTP_USER_AGENT']) && strstr($_SERVER['HTTP_USER_AGENT'], 'Opera')) ? true : false;
+
+ $this->tpl_bool = Array(
+ 'auth_admin'=>$session->user_level >= USER_LEVEL_ADMIN ? true : false,
+ 'user_logged_in'=>$session->user_logged_in,
+ 'opera'=>$is_opera,
+ );
+
+ if($session->sid_super) { $ash = '&auth='.$session->sid_super; $asq = "?auth=".$session->sid_super; $asa = "&auth=".$session->sid_super; $as2 = htmlspecialchars(urlSeparator).'auth='.$session->sid_super; }
+ else { $asq=''; $asa=''; $as2 = ''; $ash = ''; }
+
+ $code = $plugins->setHook('compile_template');
+ foreach ( $code as $cmd )
+ {
+ eval($cmd);
+ }
+
+ // Some additional sidebar processing
+ if($this->sidebar_extra != '') {
+ $se = $this->sidebar_extra;
+ $parser = $this->makeParserText($tplvars['sidebar_section_raw']);
+ $parser->assign_vars(Array('TITLE'=>'Links','CONTENT'=>$se));
+ $this->sidebar_extra = $parser->run();
+ }
+
+ $this->sidebar_extra = $this->sidebar_extra.$this->sidebar_widgets;
+
+ $this->tpl_bool['fixed_menus'] = false;
+ /* if($this->sidebar_extra == '') $this->tpl_bool['right_sidebar'] = false;
+ else */ $this->tpl_bool['right_sidebar'] = true;
+
+ $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');
+
+ $this->tpl_bool['enable_uploads'] = ( getConfig('enable_uploads') == '1' && $session->get_permissions('upload_files') ) ? true : false;
+
+ $this->tpl_bool['stupid_mode'] = false;
+
+ if($paths->page == $paths->nslist['Special'].'Administration') $this->tpl_bool['in_admin'] = true;
+ else $this->tpl_bool['in_admin'] = false;
+
+ $p = ( isset($_GET['printable']) ) ? '/printable' : '';
+
+ // Add the e-mail address client code to the header
+ $this->add_header($email->jscode());
+
+ // Generate the code for the Log out and Change theme sidebar buttons
+ // Once again, the new template parsing system can be used here
+
+ $parser = $this->makeParserText($tplvars['sidebar_button']);
+
+ $parser->assign_vars(Array(
+ 'HREF'=>makeUrlNS('Special', 'Logout'),
+ 'FLAGS'=>'onclick="mb_logout(); return false;"',
+ 'TEXT'=>'Log out',
+ ));
+
+ $logout_link = $parser->run();
+
+ $parser->assign_vars(Array(
+ 'HREF'=>makeUrlNS('Special', 'Login/' . $paths->page),
+ 'FLAGS'=>'onclick="ajaxStartLogin(); return false;"',
+ 'TEXT'=>'Log in',
+ ));
+
+ $login_link = $parser->run();
+
+ $parser->assign_vars(Array(
+ 'HREF'=>makeUrlNS('Special', 'ChangeStyle/'.$paths->page),
+ 'FLAGS'=>'onclick="ajaxChangeStyle(); return false;"',
+ 'TEXT'=>'Change theme',
+ ));
+
+ $theme_link = $parser->run();
+
+ $SID = ($session->sid_super) ? $session->sid_super : '';
+
+ // Generate the dynamic javascript vars
+ $js_dynamic = ' ";
+
+ $tpl_strings = Array(
+ 'PAGE_NAME'=>$paths->cpage['name'],
+ 'PAGE_URLNAME'=>$paths->cpage['urlname'],
+ 'SITE_NAME'=>getConfig('site_name'),
+ 'USERNAME'=>$session->username,
+ 'SITE_DESC'=>getConfig('site_desc'),
+ 'TOOLBAR'=>$tb,
+ 'SCRIPTPATH'=>scriptPath,
+ 'CONTENTPATH'=>contentPath,
+ 'ADMIN_SID_QUES'=>$asq,
+ 'ADMIN_SID_AMP'=>$asa,
+ 'ADMIN_SID_AMP_HTML'=>$ash,
+ 'ADMIN_SID_AUTO'=>$as2,
+ 'ADDITIONAL_HEADERS'=>$this->additional_headers,
+ 'COPYRIGHT'=>getConfig('copyright_notice'),
+ 'TOOLBAR_EXTRAS'=>$this->toolbar_menu,
+ 'REQUEST_URI'=>$_SERVER['HTTP_HOST'].$_SERVER['REQUEST_URI'],
+ 'STYLE_LINK'=>makeUrlNS('Special', 'CSS'.$p, null, true), //contentPath.$paths->nslist['Special'].'CSS' . $p,
+ 'LOGIN_LINK'=>$login_link,
+ 'LOGOUT_LINK'=>$logout_link,
+ 'THEME_LINK'=>$theme_link,
+ 'TEMPLATE_DIR'=>scriptPath.'/themes/'.$this->theme,
+ 'THEME_ID'=>$this->theme,
+ 'STYLE_ID'=>$this->style,
+ 'JS_DYNAMIC_VARS'=>$js_dynamic,
+ 'UNREAD_PMS'=>$session->unread_pms
+ );
+
+ foreach ( $paths->nslist as $ns_id => $ns_prefix )
+ {
+ $tpl_strings[ 'NS_' . strtoupper($ns_id) ] = $ns_prefix;
+ }
+
+ $this->tpl_strings = array_merge($tpl_strings, $this->tpl_strings);
+ list($this->tpl_strings['SIDEBAR_LEFT'], $this->tpl_strings['SIDEBAR_RIGHT'], $min) = $this->fetch_sidebar();
+ $this->tpl_bool['sidebar_left'] = ( $this->tpl_strings['SIDEBAR_LEFT'] != $min) ? true : false;
+ $this->tpl_bool['sidebar_right'] = ( $this->tpl_strings['SIDEBAR_RIGHT'] != $min) ? true : false;
+ $this->tpl_bool['right_sidebar'] = $this->tpl_bool['sidebar_right']; // backward compatibility
+ }
+
+ function header($simple = false)
+ {
+ global $db, $session, $paths, $template, $plugins; // Common objects
+ ob_start();
+
+ if(!$this->theme_loaded)
+ {
+ $this->load_theme($session->theme, $session->style);
+ }
+
+ $headers_sent = true;
+ dc_here('template: generating and sending the page header');
+ if(!defined('ENANO_HEADERS_SENT'))
+ define('ENANO_HEADERS_SENT', '');
+ if(!$this->no_headers) echo ( $simple ) ? $this->process_template('simple-header.tpl') : $this->process_template('header.tpl');
+ if ( !$simple && $session->user_logged_in && $session->unread_pms > 0 )
+ {
+ echo $this->notify_unread_pms();
+ }
+ if ( !$simple && $session->sw_timed_out )
+ {
+ $login_link = makeUrlNS('Special', 'Login/' . $paths->fullpage, 'level=' . $session->user_level, true);
+ echo '';
+ echo '
Your administrative session has timed out. Log in again ';
+ echo '
';
+ }
+ }
+ function footer($simple = false)
+ {
+ global $db, $session, $paths, $template, $plugins; // Common objects
+ dc_here('template: generating and sending the page footer');
+ if(!$this->no_headers) {
+
+ if(!defined('ENANO_HEADERS_SENT'))
+ $this->header();
+
+ global $_starttime;
+ if(isset($_GET['sqldbg']) && $session->get_permissions('mod_misc'))
+ {
+ echo 'Query list as requested on URI ';
+ echo $db->sql_backtrace();
+ echo ' ';
+ }
+
+ $f = microtime_float();
+ $f = $f - $_starttime;
+ $f = round($f, 4);
+ $dbg = 'Time: '.$f.'s | Queries: '.$db->num_queries;
+ $t = ( $simple ) ? $this->process_template('simple-footer.tpl') : $this->process_template('footer.tpl');
+ $t = str_replace('[[Stats]]', $dbg, $t);
+ $t = str_replace('[[NumQueries]]', (string)$db->num_queries, $t);
+ $t = str_replace('[[GenTime]]', (string)$f, $t);
+ echo $t;
+
+ ob_end_flush();
+ }
+ else return '';
+ }
+ function getHeader()
+ {
+ $headers_sent = true;
+ dc_here('template: generating and sending the page header');
+ if(!defined('ENANO_HEADERS_SENT'))
+ define('ENANO_HEADERS_SENT', '');
+ if(!$this->no_headers) return $this->process_template('header.tpl');
+ }
+ function getFooter()
+ {
+ global $db, $session, $paths, $template, $plugins; // Common objects
+ dc_here('template: generating and sending the page footer');
+ if(!$this->no_headers) {
+ global $_starttime;
+ $t = '';
+
+ if(isset($_GET['sqldbg']) && $session->get_permissions('mod_misc'))
+ {
+ $t .= 'Query list as requested on URI ';
+ $t .= $db->sql_backtrace();
+ $t .= ' ';
+ }
+
+ $f = microtime_float();
+ $f = $f - $_starttime;
+ $f = round($f, 4);
+ $dbg = 'Time: '.$f.'s | Queries: '.$db->num_queries;
+ $t.= $this->process_template('footer.tpl');
+ $t = str_replace('[[Stats]]', $dbg, $t);
+ $t = str_replace('[[NumQueries]]', (string)$db->num_queries, $t);
+ $t = str_replace('[[GenTime]]', (string)$f, $t);
+ return $t;
+ }
+ else return '';
+ }
+
+ function process_template($file) {
+ global $db, $session, $paths, $template, $plugins; // Common objects
+ if(!defined('ENANO_TEMPLATE_LOADED'))
+ {
+ $this->load_theme();
+ $this->init_vars();
+ }
+ eval($this->compile_template($file));
+ return $tpl_code;
+ }
+
+ function extract_vars($file) {
+ global $db, $session, $paths, $template, $plugins; // Common objects
+ if(!$this->theme)
+ {
+ die('$template->extract_vars(): theme not yet loaded, so we can\'t open template files yet...this is a bug and should be reported. Backtrace, most recent call first:'.enano_debug_print_backtrace(true).' ');
+ }
+ if(!is_file(ENANO_ROOT . '/themes/'.$this->theme.'/'.$file)) die('Cannot find '.$file.' file for style "'.$this->theme.'", exiting');
+ $text = file_get_contents(ENANO_ROOT . '/themes/'.$this->theme.'/'.$file);
+ preg_match_all('#<\!-- VAR ([A-z0-9_-]*) -->(.*?)<\!-- ENDVAR \\1 -->#is', $text, $matches);
+ $tplvars = Array();
+ for($i=0;$itheme.'/'.$text)) die('Cannot find '.$text.' file for style, exiting');
+ $n = $text;
+ $tpl_filename = ENANO_ROOT . '/cache/' . $this->theme . '-' . str_replace('/', '-', $n) . '.php';
+ if(!is_file(ENANO_ROOT . '/themes/'.$this->theme.'/'.$text)) die('Cannot find '.$text.' file for style, exiting');
+ if(file_exists($tpl_filename) && getConfig('cache_thumbs')=='1')
+ {
+ include($tpl_filename);
+ $text = file_get_contents(ENANO_ROOT . '/themes/'.$this->theme.'/'.$text);
+ if(isset($md5) && $md5 == md5($text)) {
+ return str_replace('\\"', '"', $tpl_text);
+ }
+ }
+ $text = file_get_contents(ENANO_ROOT . '/themes/'.$this->theme.'/'.$n);
+
+ $md5 = md5($text);
+
+ $seed = md5 ( microtime() . mt_rand() );
+ preg_match_all("/<\?php(.*?)\?>/is", $text, $m);
+ //die(''.htmlspecialchars(print_r($m, true)).' ');
+ for($i = 0; $i < sizeof($m[1]); $i++)
+ {
+ $text = str_replace("", "{PHPCODE:{$i}:{$seed}}", $text);
+ }
+ //die(''.htmlspecialchars($text).' ');
+ $text = 'ob_start(); echo \''.str_replace('\'', '\\\'', $text).'\'; $tpl_code = ob_get_contents(); ob_end_clean();';
+ $text = preg_replace('##is', '\'; if(isset($this->tpl_bool[\'\\1\']) && $this->tpl_bool[\'\\1\']) { echo \'', $text);
+ $text = preg_replace('##is', '\'; if(isset($this->tpl_strings[\'\\1\'])) { echo \'', $text);
+ $text = preg_replace('##is', '\'; if(getConfig(\'plugin_\\1\')==\'1\') { echo \'', $text);
+ $text = preg_replace('##is', '\'; echo $template->tplWikiFormat($paths->sysMsg(\'\\1\')); echo \'', $text);
+ $text = preg_replace('##is', '\'; if(!$this->tpl_bool[\'\\1\']) { echo \'', $text);
+ $text = preg_replace('##is', '\'; } else { echo \'', $text);
+ $text = preg_replace('##is', '\'; } echo \'', $text);
+ $text = preg_replace('#\{([A-z0-9]*)\}#is', '\'.$this->tpl_strings[\'\\1\'].\'', $text);
+ for($i = 0; $i < sizeof($m[1]); $i++)
+ {
+ $text = str_replace("{PHPCODE:{$i}:{$seed}}", "'; {$m[1][$i]} echo '", $text);
+ }
+ if(is_writable(ENANO_ROOT.'/cache/') && getConfig('cache_thumbs')=='1')
+ {
+ //die($tpl_filename);
+ $h = fopen($tpl_filename, 'w');
+ if(!$h) return $text;
+ $t = addslashes($text);
+ fwrite($h, '');
+ fclose($h);
+ }
+ return $text; //(''.htmlspecialchars($text).' ');
+ }
+
+ function compile_template_text($text) {
+ $seed = md5 ( microtime() . mt_rand() );
+ preg_match_all("/<\?php(.*?)\?>/is", $text, $m);
+ //die(''.htmlspecialchars(print_r($m, true)).' ');
+ for($i = 0; $i < sizeof($m[1]); $i++)
+ {
+ $text = str_replace("", "{PHPCODE:{$i}:{$seed}}", $text);
+ }
+ //die(''.htmlspecialchars($text).' ');
+ $text = 'ob_start(); echo \''.str_replace('\'', '\\\'', $text).'\'; $tpl_code = ob_get_contents(); ob_end_clean(); return $tpl_code;';
+ $text = preg_replace('##is', '\'; if(isset($this->tpl_bool[\'\\1\']) && $this->tpl_bool[\'\\1\']) { echo \'', $text);
+ $text = preg_replace('##is', '\'; if(isset($this->tpl_strings[\'\\1\'])) { echo \'', $text);
+ $text = preg_replace('##is', '\'; if(getConfig(\'plugin_\\1\')==\'1\') { echo \'', $text);
+ $text = preg_replace('##is', '\'; echo $template->tplWikiFormat($paths->sysMsg(\'\\1\')); echo \'', $text);
+ $text = preg_replace('##is', '\'; if(!$this->tpl_bool[\'\\1\']) { echo \'', $text);
+ $text = preg_replace('##is', '\'; } else { echo \'', $text);
+ $text = preg_replace('##is', '\'; } echo \'', $text);
+ $text = preg_replace('#\{([A-z0-9]*)\}#is', '\'.$this->tpl_strings[\'\\1\'].\'', $text);
+ for($i = 0; $i < sizeof($m[1]); $i++)
+ {
+ $text = str_replace("{PHPCODE:{$i}:{$seed}}", "'; {$m[1][$i]} echo '", $text);
+ }
+ return $text; //(''.htmlspecialchars($text).' ');
+ }
+
+ function parse($text)
+ {
+ $text = $this->compile_template_text($text);
+ return eval($text);
+ }
+
+ // Steps to turn this:
+ // [[Project:Community Portal]]
+ // into this:
+ // Community Portal
+ // Must be done WITHOUT creating eval'ed code!!!
+
+ // 1. preg_replace \[\[([a-zA-Z0-9 -_:]*?)\]\] with \\1
+ // 2. preg_match_all
+ // 3. For each match, replace matches with identifiers
+ // 4. For each match, str_replace ' ' with '_'
+ // 5. For each match, str_replace match_id:random_val with $matches[$match_id]
+
+ // The template language is really a miniature programming language; with variables, conditionals, everything!
+ // So you can implement custom logic into your sidebar if you wish.
+ // "Real" PHP support coming soon :-D
+
+ function tplWikiFormat($message, $filter_links = false, $filename = 'elements.tpl') {
+ global $db, $session, $paths, $template, $plugins; // Common objects
+ $filter_links = false;
+ $tplvars = $this->extract_vars($filename);
+ if($session->sid_super) $as = htmlspecialchars(urlSeparator).'auth='.$session->sid_super;
+ else $as = '';
+ error_reporting(E_ALL);
+ $random_id = sha1(microtime().''); // A temp value
+
+ /*
+ * PREPROCESSOR
+ */
+
+ // Variables
+
+ preg_match_all('#\$([A-Z_-]+)\$#', $message, $links);
+ $links = $links[1];
+
+ for($i=0;$itpl_strings[$links[$i]], $message);
+ }
+
+ // Conditionals
+
+ preg_match_all('#\{if ([A-Za-z0-9_ &\|\!-]*)\}(.*?)\{\/if\}#is', $message, $links);
+
+ for($i=0;$itpl_bool['that']) && $this->tpl_bool['that'] ) && ...
+ // Method of attack: escape all variables, ignore all else. Non-valid code is filtered out by a regex above.
+ $in_var_now = true;
+ $in_var_last = false;
+ $current_var = '';
+ $current_var_start_pos = 0;
+ $current_var_end_pos = 0;
+ $j = -1;
+ $links[1][$i] = $links[1][$i] . ' ';
+ $d = strlen($links[1][$i]);
+ while($j < $d)
+ {
+ $j++;
+ $in_var_last = $in_var_now;
+
+ $char = substr($links[1][$i], $j, 1);
+ $in_var_now = ( preg_match('#^([A-z0-9_]*){1}$#', $char) ) ? true : false;
+ if(!$in_var_last && $in_var_now)
+ {
+ $current_var_start_pos = $j;
+ }
+ if($in_var_last && !$in_var_now)
+ {
+ $current_var_end_pos = $j;
+ }
+ if($in_var_now)
+ {
+ $current_var .= $char;
+ continue;
+ }
+ // 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.
+ 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')
+ {
+ // XSS attack! Bail out
+ echo 'Error: Syntax error (possibly XSS attack) caught in template code:
';
+ echo '';
+ echo '{if '.$links[1][$i].'}';
+ echo "\n ";
+ for($k=0;$k<$j;$k++) echo " ";
+ echo '^ ';
+ echo ' ';
+ continue 2;
+ }
+ if($current_var != '')
+ {
+ $cd = '( isset($this->tpl_bool[\''.$current_var.'\']) && $this->tpl_bool[\''.$current_var.'\'] )';
+ $cvt = substr($links[1][$i], 0, $current_var_start_pos) . $cd . substr($links[1][$i], $current_var_end_pos, strlen($links[1][$i]));
+ $j = $j + strlen($cd) - strlen($current_var);
+ $current_var = '';
+ $links[1][$i] = $cvt;
+ $d = strlen($links[1][$i]);
+ }
+ }
+ $links[1][$i] = substr($links[1][$i], 0, strlen($links[1][$i])-1);
+ $links[1][$i] = '$chk = ( '.$links[1][$i].' ) ? true : false;';
+ eval($links[1][$i]);
+
+ if($chk) { // isset($this->tpl_bool[$links[1][$i]]) && $this->tpl_bool[$links[1][$i]]
+ if(strstr($links[2][$i], '{else}')) $c = substr($links[2][$i], 0, strpos($links[2][$i], '{else}'));
+ else $c = $links[2][$i];
+ $message = str_replace('{CONDITIONAL:'.$i.':'.$random_id.'}', $c, $message);
+ } else {
+ if(strstr($links[2][$i], '{else}')) $c = substr($links[2][$i], strpos($links[2][$i], '{else}')+6, strlen($links[2][$i]));
+ else $c = '';
+ $message = str_replace('{CONDITIONAL:'.$i.':'.$random_id.'}', $c, $message);
+ }
+ }
+
+ preg_match_all('#\{!if ([A-Za-z_-]*)\}(.*?)\{\/if\}#is', $message, $links);
+
+ for($i=0;$itpl_bool[$links[1][$i]]) && $this->tpl_bool[$links[1][$i]]) {
+ if(strstr($links[2][$i], '{else}')) $c = substr($links[2][$i], strpos($links[2][$i], '{else}')+6, strlen($links[2][$i]));
+ else $c = '';
+ $message = str_replace('{CONDITIONAL:'.$i.':'.$random_id.'}', $c, $message);
+ } else {
+ if(strstr($links[2][$i], '{else}')) $c = substr($links[2][$i], 0, strpos($links[2][$i], '{else}'));
+ else $c = $links[2][$i];
+ $message = str_replace('{CONDITIONAL:'.$i.':'.$random_id.'}', $c, $message);
+ }
+ }
+
+ /*
+ * HTML RENDERER
+ */
+
+ // Images
+ $j = preg_match_all('#\[\[:'.$paths->nslist['File'].'([\w\s0-9_\(\)!@%\^\+\|\.-]+?)\]\]#is', $message, $matchlist);
+ $matches = Array();
+ $matches['images'] = $matchlist[1];
+ for($i=0;$inslist['File'].$matches['images'][$i]))
+ {
+ $message = str_replace('[[:'.$paths->nslist['File'].$matches['images'][$i].']]',
+ ' ',
+ $message);
+ }
+ }
+
+ // Internal links
+
+ $text_parser = $this->makeParserText($tplvars['sidebar_button']);
+
+ preg_match_all('#\[\[([a-zA-Z0-9 -_]*?)\]\]#is', $message, $il);
+ for($i=0;$iassign_vars(Array(
+ 'HREF' => $href,
+ 'FLAGS' => '',
+ 'TEXT' => $il[1][$i]
+ ));
+ $message = str_replace("[[{$il[1][$i]}]]", $text_parser->run(), $message);
+ }
+
+ preg_match_all('#\[\[([a-zA-Z0-9 -_]*?)\|([a-zA-Z0-9!@\#\$%\^&\*\(\)\{\} -_]*?)\]\]#is', $message, $il);
+ for($i=0;$iassign_vars(Array(
+ 'HREF' => $href,
+ 'FLAGS' => '',
+ 'TEXT' => $il[2][$i]
+ ));
+ $message = str_replace("[[{$il[1][$i]}|{$il[2][$i]}]]", $text_parser->run(), $message);
+ }
+
+ // External links
+ $message = preg_replace('#\[(http|ftp|irc):\/\/([a-z0-9\/:_\.\?&%\#@_\\\\-]+?)\\ ([^\]]+)]#', '\\3 ', $message);
+ $message = preg_replace('#\[(http|ftp|irc):\/\/([a-z0-9\/:_\.\?&%\#@_\\\\-]+?)\\]#', '\\1://\\2 ', $message);
+
+ $parser1 = $this->makeParserText($tplvars['sidebar_section']);
+ $parser2 = $this->makeParserText($tplvars['sidebar_section_raw']);
+
+ preg_match_all('#\{slider(2|)=(.*?)\}(.*?)\{\/slider(2|)\}#is', $message, $sb);
+
+ // Modified to support the sweet new template var system
+ for($i=0;$iassign_vars(Array('TITLE'=>$sb[2][$i],'CONTENT'=>$sb[3][$i]));
+ $message = str_replace("{slider{$sb[1][$i]}={$sb[2][$i]}}{$sb[3][$i]}{/slider{$sb[4][$i]}}", $p->run(), $message);
+ }
+
+ /*
+ Extras ;-)
+ $message = preg_replace('##is', '', $message);
+ $message = preg_replace('##is', '', $message);
+ $message = preg_replace('##is', '', $message);
+ $message = preg_replace('##is', '', $message);
+ $message = preg_replace('##is', '', $message);
+ */
+
+ //die(''.htmlspecialchars($message).' ');
+ //eval($message); exit;
+ return $message;
+ }
+
+ /**
+ * Print a text field that auto-completes a username entered into it.
+ * @param string $name - the name of the form field
+ * @return string
+ */
+
+ function username_field($name, $value = false)
+ {
+ $randomid = md5( time() . microtime() . mt_rand() );
+ $text = ' ';
+ return $text;
+ }
+
+ /**
+ * Sends a textarea that can be converted to and from a TinyMCE widget on the fly.
+ * @param string The name of the form element
+ * @param string The initial content. Optional, defaults to blank
+ * @param int Rows in textarea
+ * @param int Columns in textarea
+ * @return string HTML and Javascript code.
+ */
+
+ function tinymce_textarea($name, $content = '', $rows = 20, $cols = 60)
+ {
+ $randomid = md5(microtime() . mt_rand());
+ $html = '';
+ $html .= '';
+ $html .= '';
+ $html .= '';
+ return $html;
+ }
+
+ /**
+ * Allows individual parsing of template files. Similar to phpBB but follows the spirit of object-oriented programming ;)
+ * Returns on object of class templateIndividual. Usage instructions can be found in the inline docs for that class.
+ * @param $filename the filename of the template to be parsed
+ * @return object
+ */
+
+ function makeParser($filename)
+ {
+ global $db, $session, $paths, $template, $plugins; // Common objects
+ $filename = ENANO_ROOT.'/themes/'.$template->theme.'/'.$filename;
+ if(!file_exists($filename)) die('templateIndividual: file '.$filename.' does not exist');
+ $code = file_get_contents($filename);
+ $parser = new templateIndividual($code);
+ return $parser;
+ }
+
+ /**
+ * Same as $template->makeParser(), but takes a string instead of a filename.
+ * @param $text the text to parse
+ * @return object
+ */
+
+ function makeParserText($code)
+ {
+ $parser = new templateIndividual($code);
+ return $parser;
+ }
+
+ /**
+ * Fetch the HTML for a plugin-added sidebar block
+ * @param $name the plugin name
+ * @return string
+ */
+
+ function fetch_block($id)
+ {
+ if(isset($this->plugin_blocks[$id])) return $this->plugin_blocks[$id];
+ else return false;
+ }
+
+ /**
+ * Fetches the contents of both sidebars.
+ * @return array - key 0 is left, key 1 is right
+ * @example list($left, $right) = $template->fetch_sidebar();
+ */
+
+ function fetch_sidebar()
+ {
+ global $db, $session, $paths, $template, $plugins; // Common objects
+
+ $left = '';
+ $right = '';
+
+ if ( !$this->fetch_block('Links') )
+ $this->initLinksWidget();
+
+ $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;');
+ if(!$q) $db->_die('The sidebar text data could not be selected.');
+
+ $vars = $this->extract_vars('elements.tpl');
+
+ if(isset($vars['sidebar_top']))
+ {
+ $left .= $this->parse($vars['sidebar_top']);
+ $right .= $this->parse($vars['sidebar_top']);
+ }
+ while($row = $db->fetchrow())
+ {
+ switch($row['block_type'])
+ {
+ case BLOCK_WIKIFORMAT:
+ default:
+ $parser = $this->makeParserText($vars['sidebar_section']);
+ $c = RenderMan::render($row['block_content']);
+ break;
+ case BLOCK_TEMPLATEFORMAT:
+ $parser = $this->makeParserText($vars['sidebar_section']);
+ $c = $this->tplWikiFormat($row['block_content']);
+ break;
+ case BLOCK_HTML:
+ $parser = $this->makeParserText($vars['sidebar_section_raw']);
+ $c = $row['block_content'];
+ break;
+ case BLOCK_PHP:
+ $parser = $this->makeParserText($vars['sidebar_section_raw']);
+ ob_start();
+ @eval($row['block_content']);
+ $c = ob_get_contents();
+ ob_end_clean();
+ break;
+ case BLOCK_PLUGIN:
+ $parser = $this->makeParserText($vars['sidebar_section_raw']);
+ $c = (gettype($this->fetch_block($row['block_content'])) == 'string') ? $this->fetch_block($row['block_content']) : 'Can\'t find plugin block';
+ break;
+ }
+ $parser->assign_vars(Array( 'TITLE'=>$this->tplWikiFormat($row['block_name']), 'CONTENT'=>$c ));
+ if ($row['sidebar_id'] == SIDEBAR_LEFT ) $left .= $parser->run();
+ elseif($row['sidebar_id'] == SIDEBAR_RIGHT) $right .= $parser->run();
+ unset($parser);
+ }
+ $db->free_result();
+ if(isset($vars['sidebar_bottom']))
+ {
+ $left .= $this->parse($vars['sidebar_bottom']);
+ $right .= $this->parse($vars['sidebar_bottom']);
+ }
+ $min = '';
+ if(isset($vars['sidebar_top']))
+ {
+ $min .= $this->parse($vars['sidebar_top']);
+ }
+ if(isset($vars['sidebar_bottom']))
+ {
+ $min .= $this->parse($vars['sidebar_bottom']);
+ }
+ return Array($left, $right, $min);
+ }
+
+ function initLinksWidget()
+ {
+ global $db, $session, $paths, $template, $plugins; // Common objects
+ // SourceForge/W3C buttons
+ $ob = Array();
+ if(getConfig('powered_btn') =='1') $ob[] = ' ';
+ if(getConfig('sflogo_enabled')=='1')
+ {
+ $ob[] = ' ';
+ }
+ if(getConfig('w3c_v32') =='1') $ob[] = ' ';
+ if(getConfig('w3c_v40') =='1') $ob[] = ' ';
+ if(getConfig('w3c_v401') =='1') $ob[] = ' ';
+ if(getConfig('w3c_vxhtml10')=='1') $ob[] = ' ';
+ if(getConfig('w3c_vxhtml11')=='1') $ob[] = ' ';
+ if(getConfig('w3c_vcss') =='1') $ob[] = ' ';
+ if(getConfig('dbd_button') =='1') $ob[] = 'Protect your freedom >> ';
+
+ $code = $plugins->setHook('links_widget');
+ foreach ( $code as $cmd )
+ {
+ eval($cmd);
+ }
+
+ if(count($ob) > 0) $sb_links = ''.implode(' ', $ob).'
';
+ else $sb_links = '';
+
+ $this->sidebar_widget('Links', $sb_links);
+ }
+
+ /**
+ * Builds a box showing unread private messages.
+ */
+
+ function notify_unread_pms()
+ {
+ global $db, $session, $paths, $template, $plugins; // Common objects
+ if ( ( $paths->cpage['urlname_nons'] == 'PrivateMessages' || $paths->cpage['urlname_nons'] == 'Preferences' ) && $paths->namespace == 'Special' )
+ {
+ return '';
+ }
+ $ob = ''."\n";
+ $s = ( $session->unread_pms == 1 ) ? '' : 's';
+ $ob .= "
You have $session->unread_pms unread private message$s . \n Messages: ";
+ $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;');
+ if ( !$q )
+ $db->_die();
+ $messages = array();
+ while ( $row = $db->fetchrow() )
+ {
+ $messages[] = '
' . $row['subject'] . ' ';
+ }
+ $ob .= implode(",\n " , $messages)."\n";
+ $ob .= '
'."\n";
+ return $ob;
+ }
+
+} // class template
+
+/**
+ * Handles parsing of an individual template file. Instances should only be created through $template->makeParser(). To use:
+ * - Call $template->makeParser(template file name) - file name should be something.tpl, css/whatever.css, etc.
+ * - Make an array of strings you want the template to access. $array['STRING'] would be referenced in the template like {STRING}
+ * - Make an array of boolean values. These can be used for conditionals in the template ( whatever )
+ * - Call assign_vars() to pass the strings to the template parser. Same thing with assign_bool().
+ * - Call run() to parse the template and get your fully compiled HTML.
+ * @access private
+ */
+
+class templateIndividual extends template {
+ var $tpl_strings, $tpl_bool, $tpl_code;
+ var $compiled = false;
+ /**
+ * Constructor.
+ */
+ function __construct($text)
+ {
+ global $db, $session, $paths, $template, $plugins; // Common objects
+ $this->tpl_code = $text;
+ $this->tpl_strings = $template->tpl_strings;
+ $this->tpl_bool = $template->tpl_bool;
+ }
+ /**
+ * PHP 4 constructor.
+ */
+ function templateIndividual($text)
+ {
+ $this->__construct($text);
+ }
+ /**
+ * Assigns an array of string values to the template. Strings can be accessed from the template by inserting {KEY_NAME} in the template file.
+ * @param $vars array
+ */
+ function assign_vars($vars)
+ {
+ $this->tpl_strings = array_merge($this->tpl_strings, $vars);
+ }
+ /**
+ * Assigns an array of boolean values to the template. These can be used for statements.
+ * @param $vars array
+ */
+ function assign_bool($vars)
+ {
+ $this->tpl_bool = array_merge($this->tpl_bool, $vars);
+ }
+ /**
+ * Compiles and executes the template code.
+ * @return string
+ */
+ function run()
+ {
+ global $db, $session, $paths, $template, $plugins; // Common objects
+ if(!$this->compiled)
+ {
+ $this->tpl_code = $this->compile_template_text($this->tpl_code);
+ $this->compiled = true;
+ }
+ return eval($this->tpl_code);
+ }
+}
+
+/**
+ * A version of the template compiler that does not rely at all on the other parts of Enano. Used during installation and for showing
+ * "critical error" messages. ** REQUIRES ** the Oxygen theme.
+ */
+
+class template_nodb {
+ var $tpl_strings, $tpl_bool, $theme, $style, $no_headers, $additional_headers, $sidebar_extra, $sidebar_widgets, $toolbar_menu, $theme_list;
+ function __construct() {
+
+ $this->tpl_bool = Array();
+ $this->tpl_strings = Array();
+ $this->sidebar_extra = '';
+ $this->sidebar_widgets = '';
+ $this->toolbar_menu = '';
+ $this->additional_headers = '';
+
+ $this->theme_list = Array(Array(
+ 'theme_id'=>'oxygen',
+ 'theme_name'=>'Oxygen',
+ 'theme_order'=>1,
+ 'enabled'=>1,
+ ));
+ }
+ function template() {
+ $this->__construct();
+ }
+ function get_css($s = false) {
+ if($s)
+ return $this->process_template('css/'.$s);
+ else
+ return $this->process_template('css/'.$this->style.'.css');
+ }
+ function load_theme($name, $css, $auto_init = true) {
+ $this->theme = $name;
+ $this->style = $css;
+
+ $this->tpl_strings['SCRIPTPATH'] = scriptPath;
+ if ( $auto_init )
+ $this->init_vars();
+ }
+ function init_vars()
+ {
+ global $sideinfo;
+ global $this_page;
+ global $db, $session, $paths, $template, $plugins; // Common objects
+ $tplvars = $this->extract_vars('elements.tpl');
+ $tb = '';
+ // Get the "article" button text (depends on namespace)
+ if(defined('IN_ENANO_INSTALL')) $ns = 'installation page';
+ else $ns = 'system error page';
+ $t = str_replace('{FLAGS}', 'onclick="return false;" title="Hey! A button that doesn\'t do anything. Clever..." accesskey="a"', $tplvars['toolbar_button']);
+ $t = str_replace('{HREF}', '#', $t);
+ $t = str_replace('{TEXT}', $ns, $t);
+ $tb .= $t;
+
+ // Page toolbar
+
+ $this->tpl_bool = Array(
+ 'auth_admin'=>true,
+ 'user_logged_in'=>true,
+ 'right_sidebar'=>false,
+ );
+ $this->tpl_bool['in_sidebar_admin'] = false;
+
+ $this->tpl_bool['auth_rename'] = false;
+
+ $asq = $asa = '';
+
+ $this->tpl_bool['fixed_menus'] = false;
+ $slink = defined('IN_ENANO_INSTALL') ? scriptPath.'/install.php?mode=css' : makeUrlNS('Special', 'CSS');
+
+ $title = ( is_object($paths) ) ? $paths->page : 'Critical error';
+
+ // The rewritten template engine will process all required vars during the load_template stage instead of (cough) re-processing everything each time around.
+ $tpl_strings = Array(
+ 'PAGE_NAME'=>$this_page,
+ 'PAGE_URLNAME'=>'Null',
+ 'SITE_NAME'=>'Enano Installation',
+ 'USERNAME'=>'admin',
+ 'SITE_DESC'=>'Install Enano on your server.',
+ 'TOOLBAR'=>$tb,
+ 'SCRIPTPATH'=>scriptPath,
+ 'CONTENTPATH'=>contentPath,
+ 'ADMIN_SID_QUES'=>$asq,
+ 'ADMIN_SID_AMP'=>$asa,
+ 'ADMIN_SID_AMP_HTML'=>'',
+ 'ADDITIONAL_HEADERS'=>'',
+ 'SIDEBAR_EXTRA'=>'',
+ 'COPYRIGHT'=>'Enano and all of its code, graphics, and more code is copyright © 2006 Dan Fuhry. This program is Free Software; see the file "GPL" included with this package for details.',
+ 'TOOLBAR_EXTRAS'=>'',
+ 'REQUEST_URI'=>$_SERVER['HTTP_HOST'].$_SERVER['REQUEST_URI'],
+ 'STYLE_LINK'=>$slink,
+ 'LOGOUT_LINK'=>'',
+ 'THEME_LINK'=>'',
+ 'TEMPLATE_DIR'=>scriptPath.'/themes/'.$this->theme,
+ 'THEME_ID'=>$this->theme,
+ 'STYLE_ID'=>$this->style,
+ 'JS_DYNAMIC_VARS'=>'',
+ 'SIDEBAR_RIGHT'=>'',
+ );
+ $this->tpl_strings = array_merge($tpl_strings, $this->tpl_strings);
+
+ $sidebar = ( gettype($sideinfo) == 'string' ) ? $sideinfo : '';
+ if($sidebar != '')
+ {
+ if(isset($tplvars['sidebar_top']))
+ {
+ $text = $this->makeParserText($tplvars['sidebar_top']);
+ $top = $text->run();
+ } else {
+ $top = '';
+ }
+ $p = $this->makeParserText($tplvars['sidebar_section']);
+ $p->assign_vars(Array(
+ 'TITLE'=>'Installation progress',
+ 'CONTENT'=>$sidebar,
+ ));
+ $sidebar = $p->run();
+ if(isset($tplvars['sidebar_bottom']))
+ {
+ $text = $this->makeParserText($tplvars['sidebar_bottom']);
+ $bottom = $text->run();
+ } else {
+ $bottom = '';
+ }
+ $sidebar = $top . $sidebar . $bottom;
+ }
+ $this->tpl_strings['SIDEBAR_LEFT'] = $sidebar;
+
+ $this->tpl_bool['sidebar_left'] = ( $this->tpl_strings['SIDEBAR_LEFT'] != '') ? true : false;
+ $this->tpl_bool['sidebar_right'] = ( $this->tpl_strings['SIDEBAR_RIGHT'] != '') ? true : false;
+ $this->tpl_bool['right_sidebar'] = $this->tpl_bool['sidebar_right']; // backward compatibility
+ $this->tpl_bool['stupid_mode'] = true;
+ }
+ function header()
+ {
+ if(!$this->no_headers) echo $this->process_template('header.tpl');
+ }
+ function footer()
+ {
+ global $db, $session, $paths, $template, $plugins; // Common objects
+ if(!$this->no_headers) {
+ global $_starttime;
+ $f = microtime(true);
+ $f = $f - $_starttime;
+ $f = round($f, 4);
+ if(defined('IN_ENANO_INSTALL')) $nq = 'N/A';
+ else $nq = $db->num_queries;
+ if($nq == 0) $nq = 'N/A';
+ $dbg = 'Time: '.$f.'s | Queries: '.$nq;
+ $t = $this->process_template('footer.tpl');
+ $t = str_replace('[[Stats]]', $dbg, $t);
+ echo $t;
+ }
+ else return '';
+ }
+ function getHeader()
+ {
+ if(!$this->no_headers) return $this->process_template('header.tpl');
+ else return '';
+ }
+ function getFooter()
+ {
+ global $db, $session, $paths, $template, $plugins; // Common objects
+ if(!$this->no_headers) {
+ global $_starttime;
+ $f = microtime(true);
+ $f = $f - $_starttime;
+ $f = round($f, 4);
+ if(defined('IN_ENANO_INSTALL')) $nq = 'N/A';
+ else $nq = $db->num_queries;
+ if($nq == 0) $nq = 'N/A';
+ $dbg = 'Time: '.$f.'s | Queries: '.$nq;
+ if($nq == 0) $nq = 'N/A';
+ $t = $this->process_template('footer.tpl');
+ $t = str_replace('[[Stats]]', $dbg, $t);
+ return $t;
+ }
+ else return '';
+ }
+
+ function process_template($file) {
+
+ eval($this->compile_template($file));
+ return $tpl_code;
+ }
+
+ function extract_vars($file) {
+ global $db, $session, $paths, $template, $plugins; // Common objects
+ if(!is_file(ENANO_ROOT . '/themes/'.$this->theme.'/'.$file)) die('Cannot find '.$file.' file for style "'.$this->theme.'", exiting');
+ $text = file_get_contents(ENANO_ROOT . '/themes/'.$this->theme.'/'.$file);
+ preg_match_all('#<\!-- VAR ([A-z0-9_-]*) -->(.*?)<\!-- ENDVAR \\1 -->#is', $text, $matches);
+ $tplvars = Array();
+ for($i=0;$itheme.'/'.$text);
+ $text = str_replace('', '', $text); // Remove the AJAX code - we don't need it, and it requires a database connection
+ $text = '$tpl_code = \''.str_replace('\'', '\\\'', $text).'\'; return $tpl_code;';
+ $text = preg_replace('##is', '\'; if($this->tpl_bool[\'\\1\']) { $tpl_code .= \'', $text);
+ $text = preg_replace('##is', '\'; if(getConfig(\'plugin_\\1\')==\'1\') { $tpl_code .= \'', $text);
+ if(defined('IN_ENANO_INSTALL')) $text = str_replace('', '', $text);
+ else $text = str_replace('', '', $text);
+ $text = preg_replace('##is', '', $text);
+ $text = preg_replace('##is', '\'; if(!$this->tpl_bool[\'\\1\']) { $tpl_code .= \'', $text);
+ $text = preg_replace('##is', '\'; } else { $tpl_code .= \'', $text);
+ $text = preg_replace('##is', '\'; } $tpl_code .= \'', $text);
+ $text = preg_replace('#{([A-z0-9]*)}#is', '\'.$this->tpl_strings[\'\\1\'].\'', $text);
+ return $text; //(''.htmlspecialchars($text).' ');
+ }
+
+ function compile_template_text($text) {
+ global $sideinfo;
+ $text = str_replace('', '', $text); // Remove the AJAX code - we don't need it, and it requires a database connection
+ $text = '$tpl_code = \''.str_replace('\'', '\\\'', $text).'\'; return $tpl_code;';
+ $text = preg_replace('##is', '\'; if($this->tpl_bool[\'\\1\']) { $tpl_code .= \'', $text);
+ $text = preg_replace('##is', '\'; if(getConfig(\'plugin_\\1\')==\'1\') { $tpl_code .= \'', $text);
+ if(defined('IN_ENANO_INSTALL')) $text = str_replace('', '', $text);
+ else $text = str_replace('', '', $text);
+ $text = preg_replace('##is', '', $text);
+ $text = preg_replace('##is', '\'; if(!$this->tpl_bool[\'\\1\']) { $tpl_code .= \'', $text);
+ $text = preg_replace('##is', '\'; } else { $tpl_code .= \'', $text);
+ $text = preg_replace('##is', '\'; } $tpl_code .= \'', $text);
+ $text = preg_replace('#{([A-z0-9]*)}#is', '\'.$this->tpl_strings[\'\\1\'].\'', $text);
+ return $text; //(''.htmlspecialchars($text).' ');
+ }
+
+ /**
+ * Allows individual parsing of template files. Similar to phpBB but follows the spirit of object-oriented programming ;)
+ * Returns on object of class templateIndividual. Usage instructions can be found in the inline docs for that class.
+ * @param $filename the filename of the template to be parsed
+ * @return object
+ */
+
+ function makeParser($filename)
+ {
+ $filename = ENANO_ROOT.'/themes/'.$this->theme.'/'.$filename;
+ if(!file_exists($filename)) die('templateIndividual: file '.$filename.' does not exist');
+ $code = file_get_contents($filename);
+ $parser = new templateIndividualSafe($code, $this);
+ return $parser;
+ }
+
+ /**
+ * Same as $template->makeParser(), but takes a string instead of a filename.
+ * @param $text the text to parse
+ * @return object
+ */
+
+ function makeParserText($code)
+ {
+ $parser = new templateIndividualSafe($code, $this);
+ return $parser;
+ }
+
+} // class template_nodb
+
+/**
+ * Identical to templateIndividual, except extends template_nodb instead of template
+ * @see class template
+ */
+
+class templateIndividualSafe extends template_nodb {
+ var $tpl_strings, $tpl_bool, $tpl_code;
+ var $compiled = false;
+ /**
+ * Constructor.
+ */
+ function __construct($text, $parent)
+ {
+ global $db, $session, $paths, $template, $plugins; // Common objects
+ $this->tpl_code = $text;
+ $this->tpl_strings = $parent->tpl_strings;
+ $this->tpl_bool = $parent->tpl_bool;
+ }
+ /**
+ * PHP 4 constructor.
+ */
+ function templateIndividual($text)
+ {
+ $this->__construct($text);
+ }
+ /**
+ * Assigns an array of string values to the template. Strings can be accessed from the template by inserting {KEY_NAME} in the template file.
+ * @param $vars array
+ */
+ function assign_vars($vars)
+ {
+ if(is_array($this->tpl_strings))
+ $this->tpl_strings = array_merge($this->tpl_strings, $vars);
+ else
+ $this->tpl_strings = $vars;
+ }
+ /**
+ * Assigns an array of boolean values to the template. These can be used for statements.
+ * @param $vars array
+ */
+ function assign_bool($vars)
+ {
+ $this->tpl_bool = array_merge($this->tpl_bool, $vars);
+ }
+ /**
+ * Compiles and executes the template code.
+ * @return string
+ */
+ function run()
+ {
+ global $db, $session, $paths, $template, $plugins; // Common objects
+ if(!$this->compiled)
+ {
+ $this->tpl_code = $this->compile_template_text($this->tpl_code);
+ $this->compiled = true;
+ }
+ return eval($this->tpl_code);
+ }
+}
+
+?>