Index: skins/MonoBook.php
===================================================================
--- skins/MonoBook.php	(revision 47852)
+++ skins/MonoBook.php	(working copy)
@@ -115,7 +115,7 @@
 	<div id="content">
 		<a name="top" id="top"></a>
 		<?php if($this->data['sitenotice']) { ?><div id="siteNotice"><?php $this->html('sitenotice') ?></div><?php } ?>
-		<h1 id="firstHeading" class="firstHeading"><?php $this->data['displaytitle']!=""?$this->html('title'):$this->text('title') ?></h1>
+		<h1 id="firstHeading" class="firstHeading"><?php $this->html('title') ?></h1>
 		<div id="bodyContent">
 			<h3 id="siteSub"><?php $this->msg('tagline') ?></h3>
 			<div id="contentSub"><?php $this->html('subtitle') ?></div>
Index: skins/Modern.php
===================================================================
--- skins/Modern.php	(revision 47852)
+++ skins/Modern.php	(working copy)
@@ -102,7 +102,7 @@
  class="mediawiki <?php $this->text('dir') ?> <?php $this->text('pageclass') ?> <?php $this->text('skinnameclass') ?>">
 
 	<!-- heading -->
-	<div id="mw_header"><h1 id="firstHeading"><?php $this->data['displaytitle']!=""?$this->html('title'):$this->text('title') ?></h1></div>
+	<div id="mw_header"><h1 id="firstHeading"><?php $this->html('title') ?></h1></div>
 
 	<div id="mw_main">
 	<div id="mw_contentwrapper">
Index: includes/GlobalFunctions.php
===================================================================
--- includes/GlobalFunctions.php	(revision 47852)
+++ includes/GlobalFunctions.php	(working copy)
@@ -558,7 +558,7 @@
  * @param $forContent Boolean
  * @return String: the requested message.
  */
-function wfMsgReal( $key, $args, $useDB = true, $forContent=false, $transform = true ) {
+function wfMsgReal( $key, $args, $useDB = true, $forContent = false, $transform = true ) {
 	wfProfileIn( __METHOD__ );
 	$message = wfMsgGetKey( $key, $useDB, $forContent, $transform );
 	$message = wfMsgReplaceArgs( $message, $args );
@@ -570,7 +570,7 @@
  * This function provides the message source for messages to be edited which are *not* stored in the database.
  * @param $key String:
  */
-function wfMsgWeirdKey ( $key ) {
+function wfMsgWeirdKey( $key ) {
 	$source = wfMsgGetKey( $key, false, true, false );
 	if ( wfEmptyMsg( $key, $source ) )
 		return "";
Index: includes/parser/CoreParserFunctions.php
===================================================================
--- includes/parser/CoreParserFunctions.php	(revision 47852)
+++ includes/parser/CoreParserFunctions.php	(working copy)
@@ -205,17 +205,15 @@
 	 * @param string $text Desired title text
 	 * @return string
 	 */
-	static function displaytitle( $parser, $text = '' ) {
-		global $wgRestrictDisplayTitle;
-		$text = trim( Sanitizer::decodeCharReferences( $text ) );
+	static function displaytitle( $parser, $displayTitle = '' ) {
+		#only requested titles that normalize to the actual title are allowed through
+		#mimick the escaping process that occurs in OutputPage::setPageTitle
+		$title = Title::newFromText( Sanitizer::stripAllTags( Sanitizer::normalizeCharReferences( Sanitizer::removeHTMLtags( $displayTitle ) ) ) );
 
-		if ( !$wgRestrictDisplayTitle ) {
-			$parser->mOutput->setDisplayTitle( $text );
-		} else {
-			$title = Title::newFromText( $text );
-			if( $title instanceof Title && $title->getFragment() == '' && $title->equals( $parser->mTitle ) )
-				$parser->mOutput->setDisplayTitle( $text );
+		if ( $title instanceof Title && $title->getFragment() == '' && $title->equals( $parser->mTitle ) ) {
+			$parser->mOutput->setDisplayTitle( $displayTitle );
 		}
+
 		return '';
 	}
 
Index: includes/OutputPage.php
===================================================================
--- includes/OutputPage.php	(revision 47852)
+++ includes/OutputPage.php	(working copy)
@@ -310,18 +310,34 @@
 		}
 	}
 
-	public function setHTMLTitle( $name ) { $this->mHTMLtitle = $name; }
+	/**
+	 * "HTML title" means the contents of <title>. It is stored as plain, unescaped text and will be run through htmlspecialchars in the skin file.
+	 */
+	public function setHTMLTitle( $name ) {
+		$this->mHTMLtitle = $name;
+	}
+
+	/**
+	 * "Page title" means the contents of <h1>. It is stored as a valid HTML fragment.
+	 * This function allows good tags like <sup> in the <h1> tag, but not bad tags like <script>.
+	 * This function automatically sets <title> to the same content as <h1> but with all tags removed.
+	 * Bad tags that were escaped in <h1> will still be escaped in <title>, and good tags like <i> will be dropped entirely.
+         */
 	public function setPageTitle( $name ) {
 		global $wgContLang;
 		$name = $wgContLang->convert( $name, true );
-		$this->mPagetitle = $name;
+		# change "<script>foo&bar</script>" to "&lt;script&gt;foo&amp;bar&lt;/script&gt;"
+		# but leave "<i>foobar</i>" alone
+		$nameWithTags = Sanitizer::normalizeCharReferences( Sanitizer::removeHTMLtags( $name ) );
+		$this->mPagetitle = $nameWithTags;
 
 		$taction =  $this->getPageTitleActionText();
 		if( !empty( $taction ) ) {
 			$name .= ' - '.$taction;
 		}
 
-		$this->setHTMLTitle( wfMsg( 'pagetitle', $name ) );
+		# change "<i>foo&amp;bar</i>" to "foo&bar"
+		$this->setHTMLTitle( wfMsg( 'pagetitle', Sanitizer::stripAllTags( $nameWithTags ) ) );
 	}
 
 	public function getHTMLTitle() { return $this->mHTMLtitle; }
