# HG changeset patch # User Dan # Date 1241985173 14400 # Node ID b572ce1114f11dc5a4a7ca8ed03f3e29a31baeeb # Parent ceeecb160aecd0a59732ad2082a37b3b6c4e14aa Wikitext redirects should work again + get_redirect() added to Namespace_* to allow plugins to extend diff -r ceeecb160aec -r b572ce1114f1 ajax.php --- a/ajax.php Sun May 10 14:47:14 2009 -0400 +++ b/ajax.php Sun May 10 15:52:53 2009 -0400 @@ -175,6 +175,7 @@ $pagepass = ( isset($_REQUEST['pagepass']) ) ? $_REQUEST['pagepass'] : ''; $page->password = $pagepass; + $page->allow_redir = ( !isset($_GET['redirect']) || (isset($_GET['redirect']) && $_GET['redirect'] !== 'no') ); $page->send(); break; diff -r ceeecb160aec -r b572ce1114f1 includes/functions.php --- a/includes/functions.php Sun May 10 14:47:14 2009 -0400 +++ b/includes/functions.php Sun May 10 15:52:53 2009 -0400 @@ -921,6 +921,44 @@ } /** + * Show the "this is a redirector" notice + * @param string Target Page ID + * @param string Target Namespace + */ + +function display_redirect_notice($page_id, $namespace) +{ + global $db, $session, $paths, $template, $plugins; // Common objects + global $lang, $output; + + $url = makeUrlNS($namespace, $page_id, false, true); + $ns = namespace_factory($page_id, $namespace); + $page_data = $ns->get_cdata(); + + $title = $page_data['name']; + + $cls = $ns->exists() ? '' : 'class="wikilink-nonexistent" '; + + $a = '' . $title . ''; + $redir_html = '
+ + + + + +
+ Cute wet-floor icon + + ' . $lang->get('page_msg_this_is_a_redirector', array( 'redirect_target' => $a )) . ' +
+
+
+
'; + + $output->add_after_header($redir_html); +} + +/** * Essentially an return code reader for a socket. Don't use this unless you're writing mail code and smtp_send_email doesn't cut it. Ported from phpBB's smtp.php. * @param socket A socket resource * @param string The expected response from the server, this needs to be exactly three characters. diff -r ceeecb160aec -r b572ce1114f1 includes/namespaces/default.php --- a/includes/namespaces/default.php Sun May 10 14:47:14 2009 -0400 +++ b/includes/namespaces/default.php Sun May 10 15:52:53 2009 -0400 @@ -324,6 +324,25 @@ } } } + + /** + * Get a redirect, if there is one. + * @return mixed Array: Page ID and namespace, associative; bool: false (no redirect) + */ + + public function get_redirect() + { + $text = $this->fetch_text(); + if ( preg_match('/^#redirect \[\[([^\]]+?)\]\]/i', $text, $match ) ) + { + list($page_id, $namespace) = RenderMan::strToPageID($match[1]); + return array( + 'page_id' => $page_id, + 'namespace' => $namespace + ); + } + return false; + } /** * The "real" send-the-page function. The reason for this is so other namespaces can re-use the code @@ -342,44 +361,7 @@ $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_data = $paths->get_cdata($oldtarget[0], $oldtarget[1]); - $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); - } + $text = preg_replace('/^#redirect \[\[.+?\]\]\s*/i', '', $text); if ( $send_headers ) { @@ -433,11 +415,6 @@ $page_format = $this->cdata['page_format']; } - if ( $redir_enabled ) - { - echo $redir_html; - } - $code = $plugins->setHook('pageprocess_render_head'); foreach ( $code as $cmd ) { diff -r ceeecb160aec -r b572ce1114f1 includes/pageprocess.php --- a/includes/pageprocess.php Sun May 10 14:47:14 2009 -0400 +++ b/includes/pageprocess.php Sun May 10 15:52:53 2009 -0400 @@ -104,6 +104,13 @@ var $allow_redir = true; /** + * Holds any error message from redirection code. Defaults to false (no error). + * @var mixed + */ + + var $redir_error = false; + + /** * If this is set to true, this will call the header and footer funcs on $template when render() is called. * @var bool */ @@ -175,7 +182,7 @@ function send( $do_stats = false ) { global $db, $session, $paths, $template, $plugins; // Common objects - global $lang; + global $lang, $output; profiler_log('PageProcessor: send() called'); @@ -278,6 +285,40 @@ // We are all done. Ship off the page. + if ( !$this->allow_redir ) + { + if ( method_exists($this->ns, 'get_redirect') ) + { + if ( $result = $this->ns->get_redirect() ) + display_redirect_notice($result['page_id'], $result['namespace']); + } + } + else + { + $this->process_redirects(); + + if ( count($this->redirect_stack) > 0 ) + { + $stack = array_reverse($this->redirect_stack); + foreach ( $stack as $stackel ) + { + $url = makeUrlNS($stackel['old_namespace'], $stackel['old_page_id'], 'redirect=no', true); + $page_data = $this->ns->get_cdata(); + $title = $stackel['old_title']; + $a = '' . htmlspecialchars($title) . ''; + $output->add_after_header('' . $lang->get('page_msg_redirected_from', array('from' => $a)) . '
'); + } + $template->set_page($this); + } + + if ( $this->redir_error ) + { + $output->add_after_header('
' . $this->redir_error . '
'); + $result = $this->ns->get_redirect(); + display_redirect_notice($result['page_id'], $result['namespace']); + } + } + $this->ns->send(); } @@ -942,15 +983,15 @@ $page_id_cleaned = sanitize_page_id($page_id); - $this->page_id = $page_id_cleaned; - $this->namespace = $namespace; $this->revision_id = $revision_id; $this->page_id_unclean = dirtify_page_id($page_id); - $this->perms = $session->fetch_page_acl( $page_id, $namespace ); + // resolve namespace + $this->ns = namespace_factory($page_id, $namespace, $this->revision_id); + $this->page_id =& $this->ns->page_id; + $this->namespace =& $this->ns->namespace; - // resolve namespace - $this->ns = namespace_factory($this->page_id, $this->namespace, $this->revision_id); + $this->perms = $session->fetch_page_acl( $page_id, $namespace ); $this->page_exists = $this->ns->exists(); $this->title = get_page_title_ns($this->page_id, $this->namespace); @@ -959,30 +1000,85 @@ } /** - * Renders it all in one go, and echoes it out. This assumes that the text is in the DB. + * Processes any redirects. * @access private */ - function render($incl_inner_headers = true, $_errormsg = false) + function process_redirects() { global $db, $session, $paths, $template, $plugins; // Common objects global $output, $lang; - if ( count($this->redirect_stack) > 0 ) + $this->redirect_stack = array(); + + if ( !method_exists($this->ns, 'get_redirect') ) + return true; + + if ( !$this->allow_redir ) + return true; + + $redirect_count = 0; + + while ( $result = $this->ns->get_redirect() ) { - $stack = array_reverse($this->redirect_stack); - foreach ( $stack as $oldtarget ) + if ( $result['namespace'] == 'Special' || $result['namespace'] == 'Admin' ) + { + // Can't redirect to special/admin page + $this->redir_error = $lang->get('page_err_redirect_to_special'); + break; + } + if ( $redirect_count == 3 ) + { + // max of 3 internal redirects exceeded + $this->redir_error = $lang->get('page_err_redirects_exceeded'); + break; + } + + $loop = false; + foreach ( $this->redirect_stack as $stackel ) { - $url = makeUrlNS($oldtarget[1], $oldtarget[0], 'redirect=no', true); - $page_data = $this->ns->get_cdata(); - $title = ( isset($page_data['name']) ) ? $page_data['name'] : $paths->nslist[$oldtarget[1]] . htmlspecialchars( str_replace('_', ' ', dirtify_page_id( $oldtarget[0] ) ) ); - $a = '' . $title . ''; - $output->add_after_header('' . $lang->get('page_msg_redirected_from', array('from' => $a)) . '
'); + if ( $result['page_id'] == $stackel['old_page_id'] && $result['namespace'] == $stackel['old_namespace'] ) + { + $loop = true; + break; + } + } + + if ( $loop ) + { + // redirect loop + $this->redir_error = $lang->get('page_err_redirect_infinite_loop'); + break; + } + $new_ns = namespace_factory($result['page_id'], $result['namespace']); + if ( !$new_ns->exists() ) + { + // new page doesn't exist + $this->redir_error = $lang->get('page_err_redirect_to_nonexistent'); + break; } + + // build stack entry + $stackel = array( + 'page_id' => $result['page_id'], + 'namespace' => $result['namespace'], + 'old_page_id' => $this->page_id, + 'old_namespace' => $this->namespace, + 'old_title' => $this->ns->title + ); + + // replace everything (perform the actual redirect) + $this->ns = $new_ns; + + $this->page_id =& $this->ns->page_id; + $this->namespace =& $this->ns->namespace; + + $this->redirect_stack[] = $stackel; + + $redirect_count++; } - $this->ns->send($incl_inner_headers, $_errormsg); } - + /** * Sends the page header, dependent on, of course, whether we're supposed to. */ @@ -1032,6 +1128,7 @@ * @access private */ + /* function _handle_redirect($page_id, $namespace) { global $db, $session, $paths, $template, $plugins; // Common objects @@ -1039,7 +1136,7 @@ $arr_pid = array($this->page_id, $this->namespace); if ( $namespace == 'Special' || $namespace == 'Admin' ) { - return $lang->get('page_err_redirect_to_special'); + return ; } $looped = false; foreach ( $this->redirect_stack as $page ) @@ -1052,7 +1149,7 @@ } if ( $looped ) { - return $lang->get('page_err_redirect_infinite_loop'); + return ; } $page_id_key = $paths->nslist[ $namespace ] . sanitize_page_id($page_id); if ( !isPage($page_id_key) ) @@ -1068,6 +1165,7 @@ $this->send(); return true; } + */ /** * Send the error message to the user that the access to this page is denied. diff -r ceeecb160aec -r b572ce1114f1 index.php --- a/index.php Sun May 10 14:47:14 2009 -0400 +++ b/index.php Sun May 10 15:52:53 2009 -0400 @@ -75,6 +75,7 @@ // PageProcessor when we already have one going. $template->set_page($page); $page->send_headers = true; + $page->allow_redir = ( !isset($_GET['redirect']) || (isset($_GET['redirect']) && $_GET['redirect'] !== 'no') ); $pagepass = ( isset($_REQUEST['pagepass']) ) ? sha1($_REQUEST['pagepass']) : ''; $page->password = $pagepass; $page->send(true);