MediaWiki: namespace update bug fix
[lhc/web/wiklou.git] / includes / Article.php
index 7e2188b..50af8bf 100644 (file)
@@ -150,7 +150,7 @@ class Article {
                                        $rid = $rt->getArticleID();
                                        if ( 0 != $rid ) {
                                                $sql = "SELECT cur_text,cur_timestamp,cur_user," .
-                                                 "cur_counter,cur_touched FROM cur WHERE cur_id={$rid}";
+                                                 "cur_counter,cur_restrictions,cur_touched FROM cur WHERE cur_id={$rid}";
                                                $res = wfQuery( $sql, DB_READ, $fname );
 
                                                if ( 0 != wfNumRows( $res ) ) {
@@ -186,7 +186,13 @@ class Article {
                $this->mContentLoaded = true;
        }
 
-       function getID() { return $this->mTitle->getArticleID(); }
+       function getID() {
+               if( $this->mTitle ) {
+                       return $this->mTitle->getArticleID();
+               } else {
+                       return 0;
+               }
+       }
 
        function getCount()
        {
@@ -282,7 +288,6 @@ class Article {
                # diff page instead of the article.
 
                if ( isset( $diff ) ) {
-                       include_once( "$IP/DifferenceEngine.php" );
                        $wgOut->setPageTitle( $this->mTitle->getPrefixedText() );
                        $de = new DifferenceEngine( $oldid, $diff );
                        $de->showDiffPage();
@@ -312,11 +317,9 @@ class Article {
                        $sk = $wgUser->getSkin();
                        $redir = $sk->makeKnownLink( $this->mRedirectedFrom, "",
                          "redirect=no" );
-                       $s = str_replace( "$1", $redir, wfMsg( "redirectedfrom" ) );
+                       $s = wfMsg( "redirectedfrom", $redir );
                        $wgOut->setSubtitle( $s );
                }
-               $wgOut->checkLastModified( $this->mTouched );
-               $this->tryFileCache();
                $wgLinkCache->preFill( $this->mTitle );
                $wgOut->addWikiText( $text );
 
@@ -324,308 +327,6 @@ class Article {
                wfProfileOut( $fname );
        }
 
-       # This is the function that gets called for "action=edit".
-
-       function edit()
-       {
-               global $wgOut, $wgUser;
-               global $wpTextbox1, $wpSummary, $wpSave, $wpPreview;
-               global $wpMinoredit, $wpEdittime, $wpTextbox2;
-
-               $fields = array( "wpTextbox1", "wpSummary", "wpTextbox2" );
-               wfCleanFormFields( $fields );
-
-               if ( ! $this->mTitle->userCanEdit() ) {
-                       $wgOut->readOnlyPage( $this->getContent(), true );
-                       return;
-               }
-               if ( $wgUser->isBlocked() ) {
-                       $this->blockedIPpage();
-                       return;
-               }
-               if ( wfReadOnly() ) {
-                       if( isset( $wpSave ) or isset( $wpPreview ) ) {
-                               $this->editForm( "preview" );
-                       } else {
-                               $wgOut->readOnlyPage( $this->getContent() );
-                       }
-                       return;
-               }
-               if ( $_SERVER['REQUEST_METHOD'] != "POST" ) unset( $wpSave );
-               if ( isset( $wpSave ) ) {
-                       $this->editForm( "save" );
-               } else if ( isset( $wpPreview ) ) {
-                       $this->editForm( "preview" );
-               } else { # First time through
-                       $this->editForm( "initial" );
-               }
-       }
-
-       # Since there is only one text field on the edit form,
-       # pressing <enter> will cause the form to be submitted, but
-       # the submit button value won't appear in the query, so we
-       # Fake it here before going back to edit().  This is kind of
-       # ugly, but it helps some old URLs to still work.
-
-       function submit()
-       {
-               global $wpSave, $wpPreview;
-               if ( ! isset( $wpPreview ) ) { $wpSave = 1; }
-
-               $this->edit();
-       }
-
-       # The edit form is self-submitting, so that when things like
-       # preview and edit conflicts occur, we get the same form back
-       # with the extra stuff added.  Only when the final submission
-       # is made and all is well do we actually save and redirect to
-       # the newly-edited page.
-
-       function editForm( $formtype )
-       {
-               global $wgOut, $wgUser;
-               global $wpTextbox1, $wpSummary, $wpWatchthis;
-               global $wpSave, $wpPreview;
-               global $wpMinoredit, $wpEdittime, $wpTextbox2, $wpSection;
-               global $oldid, $redirect, $section;
-               global $wgLang;
-
-               if(isset($wpSection)) { $section=$wpSection; } else { $wpSection=$section; }
-
-               $sk = $wgUser->getSkin();
-               $isConflict = false;
-               $wpTextbox1 = rtrim ( $wpTextbox1 ) ; # To avoid text getting longer on each preview
-
-               if(!$this->mTitle->getArticleID()) { # new article
-
-                       $wgOut->addWikiText(wfmsg("newarticletext"));
-
-               }
-
-               # Attempt submission here.  This will check for edit conflicts,
-               # and redundantly check for locked database, blocked IPs, etc.
-               # that edit() already checked just in case someone tries to sneak
-               # in the back door with a hand-edited submission URL.
-
-               if ( "save" == $formtype ) {
-                       if ( $wgUser->isBlocked() ) {
-                               $this->blockedIPpage();
-                               return;
-                       }
-                       if ( wfReadOnly() ) {
-                               $wgOut->readOnlyPage();
-                               return;
-                       }
-                       # If article is new, insert it.
-                       
-                       $aid = $this->mTitle->getArticleID();                   
-                       if ( 0 == $aid ) {
-                               # we need to strip Windoze linebreaks because some browsers 
-                               # append them and the string comparison fails
-                               if ( ( "" == $wpTextbox1 ) ||
-                                 ( wfMsg( "newarticletext" ) == rtrim( preg_replace("/\r/","",$wpTextbox1) ) ) ) {
-                                       $wgOut->redirect(  wfLocalUrl(
-                                         $this->mTitle->getPrefixedURL() ) );
-                                       return;
-                               }
-                               $this->mCountAdjustment = $this->isCountable( $wpTextbox1 );
-                               $this->insertNewArticle( $wpTextbox1, $wpSummary, $wpMinoredit, $wpWatchthis );
-                               return;
-                       }
-                       # Article exists. Check for edit conflict.
-                       # Don't check for conflict when appending a comment - this should always work
-
-                       $this->clear(); # Force reload of dates, etc.
-                       if ( $section!="new" && ( $this->getTimestamp() != $wpEdittime ) ) { 
-                               $isConflict = true;             
-                       }
-                       $u = $wgUser->getID();
-
-                       # Supress edit conflict with self
-
-                       if ( ( 0 != $u ) && ( $this->getUser() == $u ) ) {
-                               $isConflict = false;
-                       } else {
-                               # switch from section editing to normal editing in edit conflict
-                               if($isConflict) {
-                                       $section="";$wpSection="";
-                               }
-
-                       }
-                       if ( ! $isConflict ) {
-                               # All's well: update the article here
-                               if($this->updateArticle( $wpTextbox1, $wpSummary, $wpMinoredit, $wpWatchthis, $wpSection ))
-                                       return;
-                               else
-                                       $isConflict = true;
-                       }
-               }
-               # First time through: get contents, set time for conflict
-               # checking, etc.
-
-               if ( "initial" == $formtype ) {
-                       $wpEdittime = $this->getTimestamp();
-                       $wpTextbox1 = $this->getContent(true);
-                       $wpSummary = "";
-               }
-               $wgOut->setRobotpolicy( "noindex,nofollow" );
-               $wgOut->setArticleFlag( false );
-
-               if ( $isConflict ) {
-                       $s = str_replace( "$1", $this->mTitle->getPrefixedText(),
-                         wfMsg( "editconflict" ) );
-                       $wgOut->setPageTitle( $s );
-                       $wgOut->addHTML( wfMsg( "explainconflict" ) );
-
-                       $wpTextbox2 = $wpTextbox1;
-                       $wpTextbox1 = $this->getContent(true);
-                       $wpEdittime = $this->getTimestamp();
-               } else {
-                       $s = str_replace( "$1", $this->mTitle->getPrefixedText(),
-                         wfMsg( "editing" ) );
-
-                       if($section!="") { 
-                               if($section=="new") {
-                                       $s.=wfMsg("commentedit");
-                               } else {
-                                       $s.=wfMsg("sectionedit");
-                               }
-                       }
-                       $wgOut->setPageTitle( $s );
-                       if ( $oldid ) {
-                               $this->setOldSubtitle();
-                               $wgOut->addHTML( wfMsg( "editingold" ) );
-                       }
-               }
-
-               if( wfReadOnly() ) {
-                       $wgOut->addHTML( "<strong>" .
-                               wfMsg( "readonlywarning" ) .
-                               "</strong>" );
-               }
-               if( $this->mTitle->isProtected() ) {
-                       $wgOut->addHTML( "<strong>" . wfMsg( "protectedpagewarning" ) .
-                         "</strong><br />\n" );
-               }
-
-               $kblength = (int)(strlen( $wpTextbox1 ) / 1024);
-               if( $kblength > 29 ) {
-                       $wgOut->addHTML( "<strong>" . 
-                               str_replace( '$1', $kblength , wfMsg( "longpagewarning" ) )
-                               . "</strong>" );
-               }
-               
-               $rows = $wgUser->getOption( "rows" );
-               $cols = $wgUser->getOption( "cols" );
-
-               $ew = $wgUser->getOption( "editwidth" );
-               if ( $ew ) $ew = " style=\"width:100%\"";
-               else $ew = "" ;
-
-               $q = "action=submit";
-               if ( "no" == $redirect ) { $q .= "&redirect=no"; }
-               $action = wfEscapeHTML( wfLocalUrl( $this->mTitle->getPrefixedURL(), $q ) );
-
-               $summary = wfMsg( "summary" );          
-               $subject = wfMsg("subject");
-               $minor = wfMsg( "minoredit" );
-               $watchthis = wfMsg ("watchthis");
-               $save = wfMsg( "savearticle" );
-               $prev = wfMsg( "showpreview" );
-
-               $cancel = $sk->makeKnownLink( $this->mTitle->getPrefixedURL(),
-                 wfMsg( "cancel" ) );
-               $edithelp = $sk->makeKnownLink( wfMsg( "edithelppage" ),
-                 wfMsg( "edithelp" ) );
-               $copywarn = str_replace( "$1", $sk->makeKnownLink(
-                 wfMsg( "copyrightpage" ) ), wfMsg( "copyrightwarning" ) );
-
-               $wpTextbox1 = wfEscapeHTML( $wpTextbox1 );
-               $wpTextbox2 = wfEscapeHTML( $wpTextbox2 );
-               $wpSummary = wfEscapeHTML( $wpSummary );
-               
-               // activate checkboxes if user wants them to be always active
-               if (!$wpPreview && $wgUser->getOption("watchdefault")) $wpWatchthis=1;
-               if (!$wpPreview && $wgUser->getOption("minordefault")) $wpMinoredit=1;          
-               
-               // activate checkbox also if user is already watching the page,
-               // require wpWatchthis to be unset so that second condition is not
-               // checked unnecessarily
-               if (!$wpWatchthis && !$wpPreview && $this->mTitle->userIsWatching()) $wpWatchthis=1;
-               
-               if ( 0 != $wgUser->getID() ) {
-                       $checkboxhtml=
-                       "<input tabindex=3 type=checkbox value=1 name='wpMinoredit'".($wpMinoredit?" checked":"").">{$minor}".
-                       "<input tabindex=4 type=checkbox name='wpWatchthis'".($wpWatchthis?" checked":"").">{$watchthis}<br>";
-                       
-               } else {
-                       $checkboxhtml="";
-               }
-
-
-               if ( "preview" == $formtype) {
-               
-                       $previewhead="<h2>" . wfMsg( "preview" ) . "</h2>\n<p><large><center><font color=\"#cc0000\">" . 
-                       wfMsg( "note" ) . wfMsg( "previewnote" ) . "</font></center></large><P>\n";
-                       if ( $isConflict ) {
-                               $previewhead.="<h2>" . wfMsg( "previewconflict" ) .
-                                 "</h2>\n";
-                       }
-                       $previewtext = wfUnescapeHTML( $wpTextbox1 );
-                       
-                       if($wgUser->getOption("previewontop")) {
-                               $wgOut->addHTML($previewhead);
-                               $wgOut->addWikiText( $this->preSaveTransform( $previewtext ) ."\n\n");
-                       }
-                       $wgOut->addHTML( "<br clear=\"all\" />\n" );
-               }
-
-               # if this is a comment, show a subject line at the top, which is also the edit summary.
-               # Otherwise, show a summary field at the bottom
-               if($section=="new") {
-
-                       $commentsubject="{$subject}: <input tabindex=1 type=text value=\"{$wpSummary}\" name=\"wpSummary\" maxlength=200 size=60><br>";
-               } else {
-
-                       $editsummary="{$summary}: <input tabindex=3 type=text value=\"{$wpSummary}\" name=\"wpSummary\" maxlength=200 size=60><br>";
-               }
-
-               $wgOut->addHTML( "
-<form id=\"editform\" name=\"editform\" method=\"post\" action=\"$action\"
-enctype=\"application/x-www-form-urlencoded\">
-{$commentsubject}
-<textarea tabindex=2 name=\"wpTextbox1\" rows={$rows}
-cols={$cols}{$ew} wrap=\"virtual\">" .
-$wgLang->recodeForEdit( $wpTextbox1 ) .
-"
-</textarea>
-<br>{$editsummary}
-{$checkboxhtml}
-<input tabindex=5 type=submit value=\"{$save}\" name=\"wpSave\">
-<input tabindex=6 type=submit value=\"{$prev}\" name=\"wpPreview\">
-<em>{$cancel}</em> | <em>{$edithelp}</em>
-<br><br>{$copywarn}
-<input type=hidden value=\"{$section}\" name=\"wpSection\">
-<input type=hidden value=\"{$wpEdittime}\" name=\"wpEdittime\">\n" );
-
-               if ( $isConflict ) {
-                       $wgOut->addHTML( "<h2>" . wfMsg( "yourdiff" ) . "</h2>\n" );
-                       DifferenceEngine::showDiff( $wpTextbox2, $wpTextbox1,
-                         wfMsg( "yourtext" ), wfMsg( "storedversion" ) );
-
-                       $wgOut->addHTML( "<h2>" . wfMsg( "yourtext" ) . "</h2>
-<textarea tabindex=6 name=\"wpTextbox2\" rows={$rows} cols={$cols} wrap=virtual>"
-. $wgLang->recodeForEdit( $wpTextbox2 ) .
-"
-</textarea>" );
-               }
-               $wgOut->addHTML( "</form>\n" );
-               if($formtype =="preview" && !$wgUser->getOption("previewontop")) {
-                       $wgOut->addHTML($previewhead);
-                       $wgOut->addWikiText( $this->preSaveTransform( $previewtext ) );
-               }
-       }
-
        # Theoretically we could defer these whole insert and update
        # functions for after display, but that's taking a big leap
        # of faith, and we want to be able to report database
@@ -638,6 +339,8 @@ $wgLang->recodeForEdit( $wpTextbox1 ) .
                
                $fname = "Article::insertNewArticle";
 
+               $this->mCountAdjustment = $this->isCountable( $text );
+
                $ns = $this->mTitle->getNamespace();
                $ttl = $this->mTitle->getDBkey();
                $text = $this->preSaveTransform( $text );
@@ -686,6 +389,11 @@ $wgLang->recodeForEdit( $wpTextbox1 ) .
                        }
                }
                
+               # The talk page isn't in the regular link tables, so we need to update manually:
+               $talkns = $ns ^ 1; # talk -> normal; normal -> talk
+               $sql = "UPDATE cur set cur_touched='$now' WHERE cur_namespace=$talkns AND cur_title='" . wfStrencode( $ttl ) . "'";
+               wfQuery( $sql, DB_WRITE );
+               
                $this->showArticle( $text, wfMsg( "newarticle" ) );
        }
 
@@ -785,14 +493,15 @@ $wgLang->recodeForEdit( $wpTextbox1 ) .
                        $sql = "UPDATE recentchanges SET rc_cur_time='{$now}' " .
                          "WHERE rc_cur_id=" . $this->getID();
                        wfQuery( $sql, DB_WRITE, $fname );
-                       
-                       // Purge related entries in link cache when a page change
-                       // (probably just affects anything when article changes stub state)
-                       $pageid=$this->getID();
-                       wfQuery("DELETE linkscc FROM linkscc,links ".
-                               "WHERE lcc_title=links.l_from AND l_to={$pageid}", DB_WRITE);
 
+                       global $wgEnablePersistentLC;
+                       if ( $wgEnablePersistentLC ) {
+                               // Purge link cache for this page
+                               $pageid=$this->getID();
+                               wfQuery("DELETE FROM linkscc WHERE lcc_pageid='{$pageid}'", DB_WRITE);
+                       }                       
                }
+
                if( $wgDBtransactions ) {
                        $sql = "COMMIT";
                        wfQuery( $sql, DB_WRITE );
@@ -972,6 +681,12 @@ $wgLang->recodeForEdit( $wpTextbox1 ) .
                        "cur_restrictions='{$limit}' WHERE cur_id={$id}";
                wfQuery( $sql, DB_WRITE, "Article::protect" );
 
+               $log = new LogPage( wfMsg( "protectlogpage" ), wfMsg( "protectlogtext" ) );
+               if ( $limit === "" ) {
+                       $log->addEntry( wfMsg( "unprotectedarticle", $this->mTitle->getPrefixedText() ), "" );          
+               } else {
+                       $log->addEntry( wfMsg( "protectedarticle", $this->mTitle->getPrefixedText() ), "" );
+               }
                $wgOut->redirect( wfLocalUrl( $this->mTitle->getPrefixedURL() ) );
        }
 
@@ -1004,18 +719,26 @@ $wgLang->recodeForEdit( $wpTextbox1 ) .
                        return;
                }
 
+               if ( $_POST["wpConfirm"] ) {
+                       $this->doDelete();
+                       return;
+               }
+
                # determine whether this page has earlier revisions
                # and insert a warning if it does
                # we select the text because it might be useful below
-               $sql="SELECT old_text FROM old WHERE old_namespace=0 and old_title='" . wfStrencode($this->mTitle->getPrefixedDBkey())."' ORDER BY inverse_timestamp LIMIT 1";
-               $res=wfQuery($sql, DB_READ, $fname);
+               $ns = $this->mTitle->getNamespace();
+               $title = $this->mTitle->getDBkey();
+               $etitle = wfStrencode( $title );
+               $sql = "SELECT old_text FROM old WHERE old_namespace=$ns and old_title='$etitle' ORDER BY inverse_timestamp LIMIT 1";
+               $res = wfQuery( $sql, DB_READ, $fname );
                if( ($old=wfFetchObject($res)) && !$wpConfirm ) {
                        $skin=$wgUser->getSkin();
                        $wgOut->addHTML("<B>".wfMsg("historywarning"));
                        $wgOut->addHTML( $skin->historyLink() ."</B><P>");
                }
 
-               $sql="SELECT cur_text FROM cur WHERE cur_namespace=0 and cur_title='" . wfStrencode($this->mTitle->getPrefixedDBkey())."'";
+               $sql="SELECT cur_text FROM cur WHERE cur_namespace=$ns and cur_title='$etitle'";
                $res=wfQuery($sql, DB_READ, $fname);
                if( ($s=wfFetchObject($res))) {
 
@@ -1065,6 +788,9 @@ $wgLang->recodeForEdit( $wpTextbox1 ) .
        function confirmDelete( $par = "" )
        {
                global $wgOut;
+               global $wpReason;
+
+               wfDebug( "Article::confirmDelete\n" );
                
                $sub = htmlspecialchars( $this->mTitle->getPrefixedText() );
                $wgOut->setSubtitle( wfMsg( "deletesub", $sub ) );
@@ -1082,7 +808,7 @@ $wgLang->recodeForEdit( $wpTextbox1 ) .
 <form id=\"deleteconfirm\" method=\"post\" action=\"{$formaction}\">
 <table border=0><tr><td align=right>
 {$delcom}:</td><td align=left>
-<input type=text size=60 name=\"wpReason\" value=\"{$wpReason}\">
+<input type=text size=60 name=\"wpReason\" value=\"" . htmlspecialchars( $wpReason ) . "\">
 </td></tr><tr><td>&nbsp;</td></tr>
 <tr><td align=right>
 <input type=checkbox name=\"wpConfirm\" value='1' id=\"wpConfirm\">
@@ -1099,6 +825,7 @@ $wgLang->recodeForEdit( $wpTextbox1 ) .
                global $wgOut, $wgUser, $wgLang;
                global $wpReason;
                $fname = "Article::doDelete";
+               wfDebug( "$fname\n" );
 
                $this->doDeleteArticle( $this->mTitle );
                $deleted = $this->mTitle->getPrefixedText();
@@ -1111,8 +838,7 @@ $wgLang->recodeForEdit( $wpTextbox1 ) .
                  Namespace::getWikipedia() ) .
                  ":" . wfMsg( "dellogpage" ), wfMsg( "deletionlog" ) );
 
-               $text = str_replace( "$1" , $deleted, wfMsg( "deletedtext" ) );
-               $text = str_replace( "$2", $loglink, $text );
+               $text = wfMsg( "deletedtext", $deleted, $loglink );
 
                $wgOut->addHTML( "<p>" . $text );
                $wgOut->returnToMain( false );
@@ -1120,9 +846,12 @@ $wgLang->recodeForEdit( $wpTextbox1 ) .
 
        function doDeleteArticle( $title )
        {
-               global $wgUser, $wgOut, $wgLang, $wpReason, $wgDeferredUpdateList;
+               global $wgUser, $wgOut, $wgLang, $wpReason, $wgDeferredUpdateList, 
+                       $wgEnablePersistentLC;
 
                $fname = "Article::doDeleteArticle";
+               wfDebug( "$fname\n" );
+
                $ns = $title->getNamespace();
                $t = wfStrencode( $title->getDBkey() );
                $id = $title->getArticleID();
@@ -1162,23 +891,26 @@ $wgLang->recodeForEdit( $wpTextbox1 ) .
                
                $sql = "DELETE FROM recentchanges WHERE rc_namespace={$ns} AND " .
                  "rc_title='{$t}'";
-        wfQuery( $sql, DB_WRITE, $fname );
+                       wfQuery( $sql, DB_WRITE, $fname );
 
                # Finally, clean up the link tables
 
                if ( 0 != $id ) {
 
-                        // Purge related entries in links cache on delete,
-                        wfQuery("DELETE linkscc FROM linkscc,links ".
-                                "WHERE lcc_title=links.l_from AND l_to={$id}", DB_WRITE);
-                        wfQuery("DELETE FROM linkscc WHERE lcc_title='{$t}'", DB_WRITE);
-
                        $t = wfStrencode( $title->getPrefixedDBkey() );
+
+                       if ( $wgEnablePersistentLC ) {
+                               // Purge related entries in links cache on delete,
+                               wfQuery("DELETE linkscc FROM linkscc,links ".
+                                       "WHERE lcc_title=links.l_from AND l_to={$id}", DB_WRITE);
+                               wfQuery("DELETE FROM linkscc WHERE lcc_title='{$t}'", DB_WRITE);
+                       }
+
                        $sql = "SELECT l_from FROM links WHERE l_to={$id}";
                        $res = wfQuery( $sql, DB_READ, $fname );
 
                        $sql = "INSERT INTO brokenlinks (bl_from,bl_to) VALUES ";
-            $now = wfTimestampNow();
+                       $now = wfTimestampNow();
                        $sql2 = "UPDATE cur SET cur_touched='{$now}' WHERE cur_id IN (";
                        $first = true;
 
@@ -1214,7 +946,7 @@ $wgLang->recodeForEdit( $wpTextbox1 ) .
                $log = new LogPage( wfMsg( "dellogpage" ), wfMsg( "dellogpagetext" ) );
                $art = $title->getPrefixedText();
                $wpReason = wfCleanQueryVar( $wpReason );
-               $log->addEntry( str_replace( "$1", $art, wfMsg( "deletedarticle" ) ), $wpReason );
+               $log->addEntry( wfMsg( "deletedarticle", $art ), $wpReason );
 
                # Clear the cached article id so the interface doesn't act like we exist
                $this->mTitle->resetArticleID( 0 );
@@ -1278,12 +1010,17 @@ $wgLang->recodeForEdit( $wpTextbox1 ) .
                $s = wfFetchObject( $res );
        
                # Save it!
-               $newcomment = str_replace( "$1", $s->old_user_text, wfMsg( "revertpage" ) );
+               $newcomment = wfMsg( "revertpage", $s->old_user_text );
                $wgOut->setPagetitle( wfMsg( "actioncomplete" ) );
                $wgOut->setRobotpolicy( "noindex,nofollow" );
                $wgOut->addHTML( "<h2>" . $newcomment . "</h2>\n<hr>\n" );
                $this->updateArticle( $s->old_text, $newcomment, 1, $this->mTitle->userIsWatching() );
 
+               global $wgEnablePersistentLC;
+               if ( $wgEnablePersistentLC ) {
+                       wfQuery("DELETE FROM linkscc WHERE lcc_pageid='{$pid}'", DB_WRITE);
+               }
+       
                $wgOut->returnToMain( false );
        }
        
@@ -1337,7 +1074,7 @@ $wgLang->recodeForEdit( $wpTextbox1 ) .
                          $this->mTitle->getDBkey() );
                        array_push( $wgDeferredUpdateList, $u );
 
-                       if ( $this->getNamespace == NS_MEDIAWIKI ) {
+                       if ( $this->mTitle->getNamespace() == NS_MEDIAWIKI ) {
                                $messageCache = $wgMemc->get( "$wgDBname:messages" );
                                if (!$messageCache) {
                                        $messageCache = wfLoadAllMessages();
@@ -1353,32 +1090,10 @@ $wgLang->recodeForEdit( $wpTextbox1 ) .
                global $wgLang, $wgOut;
 
                $td = $wgLang->timeanddate( $this->mTimestamp, true );
-               $r = str_replace( "$1", "{$td}", wfMsg( "revisionasof" ) );
+               $r = wfMsg( "revisionasof", $td );
                $wgOut->setSubtitle( "({$r})" );
        }
 
-       function blockedIPpage()
-       {
-               global $wgOut, $wgUser, $wgLang;
-
-               $wgOut->setPageTitle( wfMsg( "blockedtitle" ) );
-               $wgOut->setRobotpolicy( "noindex,nofollow" );
-               $wgOut->setArticleFlag( false );
-
-               $id = $wgUser->blockedBy();
-               $reason = $wgUser->blockedFor();
-
-               $name = User::whoIs( $id );
-               $link = "[[" . $wgLang->getNsText( Namespace::getUser() ) .
-                 ":{$name}|{$name}]]";
-
-               $text = str_replace( "$1", $link, wfMsg( "blockedtext" ) );
-               $text = str_replace( "$2", $reason, $text );
-               $text = str_replace( "$3", getenv( "REMOTE_ADDR" ), $text );
-               $wgOut->addWikiText( $text );
-               $wgOut->returnToMain( false );
-       }
-
        # This function is called right before saving the wikitext,
        # so we can do things like signatures and links-in-context.
 
@@ -1425,12 +1140,13 @@ $wgLang->recodeForEdit( $wpTextbox1 ) .
                #
                $tc = "[&;%\\-,.\\(\\)' _0-9A-Za-z\\/:\\x80-\\xff]";
                $np = "[&;%\\-,.' _0-9A-Za-z\\/:\\x80-\\xff]"; # No parens
+               $namespacechar = '[ _0-9A-Za-z\x80-\xff]'; # Namespaces can use non-ascii!
                $conpat = "/^({$np}+) \\(({$tc}+)\\)$/";
 
                $p1 = "/\[\[({$np}+) \\(({$np}+)\\)\\|]]/";             # [[page (context)|]]
                $p2 = "/\[\[\\|({$tc}+)]]/";                                    # [[|page]]
-               $p3 = "/\[\[([A-Za-z _]+):({$np}+)\\|]]/";              # [[namespace:page|]]
-               $p4 = "/\[\[([A-Aa-z _]+):({$np}+) \\(({$np}+)\\)\\|]]/";
+               $p3 = "/\[\[($namespacechar+):({$np}+)\\|]]/";          # [[namespace:page|]]
+               $p4 = "/\[\[($namespacechar+):({$np}+) \\(({$np}+)\\)\\|]]/";
                                                                                                                # [[ns:page (cont)|]]
                $context = "";
                $t = $this->mTitle->getText();
@@ -1458,6 +1174,12 @@ $wgLang->recodeForEdit( $wpTextbox1 ) .
        /* Caching functions */
        
        function tryFileCache() {
+               static $called = false;
+               if( $called ) {
+                       wfDebug( " tryFileCache() -- called twice!?\n" );
+                       return;
+               }
+               $called = true;
                if($this->isFileCacheable()) {
                        $touched = $this->mTouched;
                        if( strpos( $this->mContent, "{{" ) !== false ) {