diff -r 4629ad98ee88 -r 9cdfe82c56cd includes/namespaces/default.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/includes/namespaces/default.php Sat Jan 03 18:11:18 2009 -0500 @@ -0,0 +1,735 @@ + + * @license GNU General Public License + */ + +class Namespace_Default +{ + /** + * Page ID + * @var string + */ + + public $page_id; + + /** + * Namespace + * @var string + */ + + public $namespace; + + /** + * Local copy of the page text + */ + + public $text_cache; + + /** + * Revision ID to send. If 0, the latest revision. + * @var int + */ + + public $revision_id = 0; + + /** + * Tracks whether the page exists + * @var bool + */ + + public $exists = false; + + /** + * Page title + * @var string + */ + + public $title = ''; + + /** + * Constructor. + */ + + public function __construct($page_id, $namespace, $revision_id = 0) + { + global $db, $session, $paths, $template, $plugins; // Common objects + + $this->page_id = sanitize_page_id($page_id); + $this->namespace = $namespace; + $this->revision_id = intval($revision_id); + + // only do this if calling from the (very heavily feature filled) abstract + // this will still be called if you're using your own handler but not replacing the constructor + if ( __CLASS__ == 'Namespace_Default' ) + { + $this->exists = false; + // NOTE! These should already be WELL sanitized before we reach this stage. + $q = $db->sql_query('SELECT name FROM ' . table_prefix . "pages WHERE urlname = '$this->page_id' AND namespace = '$this->namespace';"); + if ( !$q ) + $db->_die(); + + if ( $db->numrows() < 1 ) + { + // we still have a chance... some older databases don't do dots in the page title right + if ( strstr(dirtify_page_id($this->page_id), '.') ) + { + $page_id = str_replace('.', '.2e', $page_id); + + $q = $db->sql_query('SELECT name FROM ' . table_prefix . "pages WHERE urlname = '$page_id' AND namespace = '$this->namespace';"); + if ( !$q ) + $db->_die(); + + if ( $db->numrows() < 1 ) + { + $this->title = $paths->nslist[$namespace] . dirtify_page_id($page_id); + } + else + { + list($this->title) = $db->fetchrow_num(); + $this->exists = true; + $this->page_id = $page_id; + } + } + else + { + $this->title = $paths->nslist[$namespace] . dirtify_page_id($page_id); + } + } + else + { + list($this->title) = $db->fetchrow_num(); + $this->exists = true; + } + $db->free_result(); + } + } + + /** + * Pulls the page's actual text from the database. + */ + + function fetch_text() + { + global $db, $session, $paths, $template, $plugins; // Common objects + + if ( !empty($this->text_cache) ) + { + return $this->text_cache; + } + + if ( $this->revision_id > 0 && is_int($this->revision_id) ) + { + + $q = $db->sql_query('SELECT page_text, char_tag, time_id FROM '.table_prefix.'logs WHERE log_type=\'page\' AND action=\'edit\' AND page_id=\'' . $this->page_id . '\' AND namespace=\'' . $this->namespace . '\' AND log_id=' . $this->revision_id . ';'); + if ( !$q ) + { + $this->send_error('Error during SQL query.', true); + } + if ( $db->numrows() < 1 ) + { + // Compatibility fix for old pages with dots in the page ID + if ( strstr($this->page_id, '.2e') ) + { + $db->free_result(); + $page_id = str_replace('.2e', '.', $this->page_id); + $q = $db->sql_query('SELECT page_text, char_tag, time_id FROM '.table_prefix.'logs WHERE log_type=\'page\' AND action=\'edit\' AND page_id=\'' . $page_id . '\' AND namespace=\'' . $this->namespace . '\' AND log_id=' . $this->revision_id . ';'); + if ( !$q ) + { + $this->send_error('Error during SQL query.', true); + } + if ( $db->numrows() < 1 ) + { + $this->page_exists = false; + return 'err_no_text_rows'; + } + } + else + { + $this->page_exists = false; + return 'err_no_text_rows'; + } + } + else + { + $row = $db->fetchrow(); + } + + $db->free_result(); + + } + else + { + $q = $db->sql_query('SELECT t.page_text, t.char_tag, l.time_id FROM '.table_prefix."page_text AS t\n" + . " LEFT JOIN " . table_prefix . "logs AS l\n" + . " ON ( l.page_id = t.page_id AND l.namespace = t.namespace )\n" + . " WHERE t.page_id='$this->page_id' AND t.namespace='$this->namespace'\n" + . " ORDER BY l.time_id DESC LIMIT 1;"); + if ( !$q ) + { + $this->send_error('Error during SQL query.', true); + } + if ( $db->numrows() < 1 ) + { + // Compatibility fix for old pages with dots in the page ID + if ( strstr($this->page_id, '.2e') ) + { + $db->free_result(); + $page_id = str_replace('.2e', '.', $this->page_id); + $q = $db->sql_query('SELECT page_text, char_tag FROM '.table_prefix.'page_text WHERE page_id=\'' . $page_id . '\' AND namespace=\'' . $this->namespace . '\';'); + if ( !$q ) + { + $this->send_error('Error during SQL query.', true); + } + if ( $db->numrows() < 1 ) + { + $this->page_exists = false; + return 'err_no_text_rows'; + } + } + else + { + $this->page_exists = false; + return 'err_no_text_rows'; + } + } + + $row = $db->fetchrow(); + $db->free_result(); + + } + + if ( !empty($row['char_tag']) ) + { + // This page text entry uses the old text-escaping format + $from = array( + "{APOS:{$row['char_tag']}}", + "{QUOT:{$row['char_tag']}}", + "{SLASH:{$row['char_tag']}}" + ); + $to = array("'", '"', '\\'); + $row['page_text'] = str_replace($from, $to, $row['page_text']); + } + + $this->text_cache = $row['page_text']; + + if ( isset($row['time_id']) ) + { + $this->revision_time = intval($row['time_id']); + } + + return $row['page_text']; + } + + /** + * Send the page. + */ + + public function send() + { + global $db, $session, $paths, $template, $plugins; // Common objects + global $output; + + $output->add_before_footer($this->display_categories()); + + if ( $this->exists ) + $this->send_from_db(); + else + { + // This is the DEPRECATED way to extend namespaces. It's left in only for compatibility with older plugins. + ob_start(); + $code = $plugins->setHook('page_not_found'); + foreach ( $code as $cmd ) + { + eval($cmd); + } + $c = ob_get_contents(); + if ( !empty($c) ) + { + ob_end_clean(); + echo $c; + } + else + { + $output->header(); + $this->error_404(); + $output->footer(); + } + } + } + + /** + * The "real" send-the-page function. The reason for this is so other namespaces can re-use the code + * to fetch the page from the DB while being able to install their own wrappers. + */ + + public function send_from_db($incl_inner_headers = true, $send_headers = true) + { + global $db, $session, $paths, $template, $plugins; // Common objects + global $lang; + global $output; + + $text = $this->fetch_text(); + + $text = preg_replace('/([\s]*)__NOBREADCRUMBS__([\s]*)/', '', $text); + $text = preg_replace('/([\s]*)__NOTOC__([\s]*)/', '', $text); + + $redir_enabled = false; + if ( preg_match('/^#redirect \[\[([^\]]+?)\]\]/i', $text, $match ) ) + { + $redir_enabled = true; + + $oldtarget = RenderMan::strToPageID($match[1]); + $oldtarget[0] = sanitize_page_id($oldtarget[0]); + + $url = makeUrlNS($oldtarget[1], $oldtarget[0], false, true); + $page_id_key = $paths->nslist[ $oldtarget[1] ] . $oldtarget[0]; + $page_data = $paths->pages[$page_id_key]; + $title = ( isset($page_data['name']) ) ? $page_data['name'] : $paths->nslist[$oldtarget[1]] . htmlspecialchars( str_replace('_', ' ', dirtify_page_id( $oldtarget[0] ) ) ); + if ( !isset($page_data['name']) ) + { + $cls = 'class="wikilink-nonexistent"'; + } + else + { + $cls = ''; + } + $a = '' . $title . ''; + $redir_html = '
+ + + + + +
+ Cute wet-floor icon + + ' . $lang->get('page_msg_this_is_a_redirector', array( 'redirect_target' => $a )) . ' +
+
+
+
'; + $text = str_replace($match[0], '', $text); + $text = trim($text); + } + + if ( $send_headers ) + { + $output->set_title($this->title); + $output->header(); + } + $this->do_breadcrumbs(); + + if ( $incl_inner_headers ) + { + display_page_headers(); + } + + if ( $this->revision_id ) + { + echo '
+ ' . $lang->get('page_msg_archived_title') . '
+ ' . $lang->get('page_msg_archived_body', array( + 'archive_date' => enano_date('F d, Y', $this->revision_time), + 'archive_time' => enano_date('h:i a', $this->revision_time), + 'current_link' => makeUrlNS($this->namespace, $this->page_id), + 'restore_link' => makeUrlNS($this->namespace, $this->page_id, 'do=edit&revid='.$this->revision_id), + 'restore_onclick' => 'ajaxEditor(\''.$this->revision_id.'\'); return false;', + )) . ' +
'; + } + + if ( $redir_enabled ) + { + echo $redir_html; + } + + $code = $plugins->setHook('pageprocess_render_head'); + foreach ( $code as $cmd ) + { + eval($cmd); + } + + if ( $incl_inner_headers ) + { + $text = '?>' . RenderMan::render($text); + } + else + { + $text = '?>' . $text; + $text = preg_replace('/(.*?)<\/nowiki>/s', '\\1', $text); + } + + eval ( $text ); + + $code = $plugins->setHook('pageprocess_render_tail'); + foreach ( $code as $cmd ) + { + eval($cmd); + } + + if ( $incl_inner_headers ) + { + display_page_footers(); + } + + if ( $send_headers ) + $output->footer(); + } + + /** + * Echoes out breadcrumb data, if appropriate. + * @access private + */ + + function do_breadcrumbs() + { + global $db, $session, $paths, $template, $plugins; // Common objects + global $lang; + + if ( strpos($this->text_cache, '__NOBREADCRUMBS__') !== false ) + return false; + + $mode = getConfig('breadcrumb_mode'); + + if ( $mode == 'never' ) + // Breadcrumbs are disabled + return true; + + // Minimum depth for breadcrumb display + $threshold = ( $mode == 'always' ) ? 0 : 1; + + $breadcrumb_data = explode('/', $this->page_id); + if ( count($breadcrumb_data) > $threshold ) + { + // If we're not on a subpage of the main page, add "Home" to the list + $show_home = false; + if ( $mode == 'always' ) + { + $show_home = true; + } + echo ' + + + '; + } + } + + public function error_404($userpage = false) + { + global $db, $session, $paths, $template, $plugins; // Common objects + global $lang, $output; + + @header('HTTP/1.1 404 Not Found'); + + $msg = ( $pp = $paths->sysmsg('Page_not_found') ) ? $pp : '{STANDARD404}'; + + $standard_404 = ''; + + if ( $userpage ) + { + $standard_404 .= '

' . $lang->get('page_msg_404_title_userpage') . '

+

' . $lang->get('page_msg_404_body_userpage'); + } + else + { + $standard_404 .= '

' . $lang->get('page_msg_404_title') . '

+

' . $lang->get('page_msg_404_body'); + } + if ( $session->get_permissions('create_page') ) + { + $standard_404 .= ' ' . $lang->get('page_msg_404_create', array( + 'create_flags' => 'href="'.makeUrlNS($this->namespace, $this->page_id, 'do=edit', true).'" onclick="ajaxEditor(); return false;"', + 'mainpage_link' => makeUrl(get_main_page(), false, true) + )); + } + else + { + $standard_404 .= ' ' . $lang->get('page_msg_404_gohome', array( + 'mainpage_link' => makeUrl(get_main_page(), false, true) + )); + } + $standard_404 .= '

'; + if ( $session->get_permissions('history_rollback') ) + { + $e = $db->sql_query('SELECT * FROM ' . table_prefix . 'logs WHERE action=\'delete\' AND page_id=\'' . $this->page_id . '\' AND namespace=\'' . $this->namespace . '\' ORDER BY time_id DESC;'); + if ( !$e ) + { + $db->_die('The deletion log could not be selected.'); + } + if ( $db->numrows() > 0 ) + { + $r = $db->fetchrow(); + $standard_404 .= '

' . $lang->get('page_msg_404_was_deleted', array( + 'delete_time' => enano_date('d M Y h:i a', $r['time_id']), + 'delete_reason' => htmlspecialchars($r['edit_summary']), + 'rollback_flags' => 'href="'.makeUrl($paths->page, 'do=rollback&id='.$r['log_id']).'" onclick="ajaxRollback(\''.$r['log_id'].'\'); return false;"' + )) + . '

'; + if ( $session->user_level >= USER_LEVEL_ADMIN ) + { + $standard_404 .= '

' . $lang->get('page_msg_404_admin_opts', array( + 'detag_link' => makeUrl($paths->page, 'do=detag', true) + )) + . '

'; + } + } + $db->free_result(); + } + $standard_404 .= '

+ ' . $lang->get('page_msg_404_http_response') . ' +

'; + + $parser = $template->makeParserText($msg); + $parser->assign_vars(array( + 'STANDARD404' => $standard_404 + )); + + $msg = RenderMan::render($parser->run()); + eval( '?>' . $msg ); + } + + /** + * Display the categories a page is in. If the current page is a category, its contents will also be printed. + */ + + function display_categories() + { + global $db, $session, $paths, $template, $plugins; // Common objects + global $lang; + + $html = ''; + + if ( $this->namespace == 'Category' ) + { + // Show member pages and subcategories + $q = $db->sql_query('SELECT p.urlname, p.namespace, p.name, p.namespace=\'Category\' AS is_category FROM '.table_prefix.'categories AS c + LEFT JOIN '.table_prefix.'pages AS p + ON ( p.urlname = c.page_id AND p.namespace = c.namespace ) + WHERE c.category_id=\'' . $db->escape($this->page_id) . '\' + ORDER BY is_category DESC, p.name ASC;'); + if ( !$q ) + { + $db->_die(); + } + $html .= '

' . $lang->get('onpage_cat_heading_subcategories') . '

'; + $html .= '
'; + $html .= ''; + $html .= ''; + $ticker = 0; + $counter = 0; + $switched = false; + $class = 'row1'; + while ( $row = $db->fetchrow() ) + { + if ( $row['is_category'] == 0 && !$switched ) + { + if ( $counter > 0 ) + { + // Fill-in + while ( $ticker < 3 ) + { + $ticker++; + $html .= ''; + } + } + else + { + $html .= ''; + } + $html .= '
' . $lang->get('onpage_cat_msg_no_subcategories') . '
' . "\n\n"; + $html .= '

' . $lang->get('onpage_cat_heading_pages') . '

'; + $html .= '
'; + $html .= ''; + $html .= ''; + $counter = 0; + $ticker = -1; + $switched = true; + } + $counter++; + $ticker++; + if ( $ticker == 3 ) + { + $html .= ''; + $ticker = 0; + $class = ( $class == 'row3' ) ? 'row1' : 'row3'; + } + $html .= ""; + } + if ( !$switched ) + { + if ( $counter > 0 ) + { + // Fill-in + while ( $ticker < 2 ) + { + $ticker++; + $html .= ''; + } + } + else + { + $html .= ''; + } + $html .= '
"; // " to workaround stupid jEdit bug + + $link = makeUrlNS($row['namespace'], sanitize_page_id($row['urlname'])); + $html .= 'nslist[$row['namespace']] . sanitize_page_id($row['urlname']); + if ( !isPage( $key ) ) + { + $html .= ' class="wikilink-nonexistent"'; + } + $html .= '>'; + $title = get_page_title_ns($row['urlname'], $row['namespace']); + $html .= htmlspecialchars($title); + $html .= ''; + + $html .= "' . $lang->get('onpage_cat_msg_no_subcategories') . '
' . "\n\n"; + $html .= '

' . $lang->get('onpage_cat_heading_pages') . '

'; + $html .= '
'; + $html .= ''; + $html .= ''; + $counter = 0; + $ticker = 0; + $switched = true; + } + if ( $counter > 0 ) + { + // Fill-in + while ( $ticker < 2 ) + { + $ticker++; + $html .= ''; + } + } + else + { + $html .= ''; + } + $html .= '
' . $lang->get('onpage_cat_msg_no_pages') . '
' . "\n\n"; + } + + if ( $this->namespace != 'Special' && $this->namespace != 'Admin' ) + { + $html .= '
'; + $html .= '
'; + $html .= '(' . $lang->get('tags_catbox_link') . ')'; + $html .= '
'; + $html .= '
' . $lang->get('catedit_catbox_lbl_categories') . ' '; + + $where = '( c.page_id=\'' . $db->escape($this->page_id) . '\' AND c.namespace=\'' . $db->escape($this->namespace) . '\' )'; + $prefix = table_prefix; + $sql = <<sql_query($sql); + if ( !$q ) + $db->_die(); + + if ( $row = $db->fetchrow() ) + { + $list = array(); + do + { + $cid = sanitize_page_id($row['category_id']); + $title = get_page_title_ns($cid, 'Category'); + $link = makeUrlNS('Category', $cid); + $list[] = '' . htmlspecialchars($title) . ''; + } + while ( $row = $db->fetchrow() ); + $html .= implode(', ', $list); + } + else + { + $html .= $lang->get('catedit_catbox_lbl_uncategorized'); + } + + $can_edit = ( $session->get_permissions('edit_cat') && ( !$paths->page_protected || $session->get_permissions('even_when_protected') ) ); + if ( $can_edit ) + { + $edit_link = '' . $lang->get('catedit_catbox_link_edit') . ''; + $html .= ' [ ' . $edit_link . ' ]'; + } + + $html .= '
'; + } + return $html; + } + /** + * Just tell us if the current page exists or not. + * @return bool + */ + + function exists() + { + return $this->exists; + } +} + +/** + * The namespaces that use the default handler. + */ + +class Namespace_Article extends Namespace_Default +{ +} + +class Namespace_Project extends Namespace_Default +{ +} + +class Namespace_Help extends Namespace_Default +{ +} +