Index: skins/common/shared.css
===================================================================
--- skins/common/shared.css	(revision 86942)
+++ skins/common/shared.css	(working copy)
@@ -24,6 +24,11 @@
 	font-size: 95%;
 }
 
+/* Safe unicode embedding */
+.unicode-embed {
+	unicode-bidi: embed;
+}
+
 /* Math */
 .texvc {
 	direction: ltr;
@@ -677,4 +682,4 @@
 	/* version numbers are always ltr (and otherwise an RLE can be inserted) */
 	/* @noflip */
 	direction: ltr;
-}
\ No newline at end of file
+}
Index: includes/Linker.php
===================================================================
--- includes/Linker.php	(revision 86942)
+++ includes/Linker.php	(working copy)
@@ -977,8 +977,8 @@
 		if ( $rev->isDeleted( Revision::DELETED_USER ) && $isPublic ) {
 			$link = wfMsgHtml( 'rev-deleted-user' );
 		} else if ( $rev->userCan( Revision::DELETED_USER ) ) {
-			$link = self::userLink( $rev->getUser( Revision::FOR_THIS_USER ),
-				$rev->getUserText( Revision::FOR_THIS_USER ) );
+			$link = Sanitizer::safeBiDi( self::userLink( $rev->getUser( Revision::FOR_THIS_USER ),
+				$rev->getUserText( Revision::FOR_THIS_USER ) ) );
 		} else {
 			$link = wfMsgHtml( 'rev-deleted-user' );
 		}
@@ -1000,7 +1000,7 @@
 		} else if ( $rev->userCan( Revision::DELETED_USER ) ) {
 			$userId = $rev->getUser( Revision::FOR_THIS_USER );
 			$userText = $rev->getUserText( Revision::FOR_THIS_USER );
-			$link = self::userLink( $userId, $userText ) .
+			$link =  Sanitizer::safeBiDi( self::userLink( $userId, $userText ) ) .
 				' ' . self::userToolLinks( $userId, $userText );
 		} else {
 			$link = wfMsgHtml( 'rev-deleted-user' );
Index: includes/EditPage.php
===================================================================
--- includes/EditPage.php	(revision 86942)
+++ includes/EditPage.php	(working copy)
@@ -1255,7 +1255,7 @@
 			$wgOut->setPageTitle( wfMsg( 'editconflict', $this->getContextTitle()->getPrefixedText() ) );
 		} elseif ( $this->section != '' ) {
 			$msg = $this->section == 'new' ? 'editingcomment' : 'editingsection';
-			$wgOut->setPageTitle( wfMsg( $msg, $this->getContextTitle()->getPrefixedText() ) );
+			$wgOut->setPageTitle( wfMsg( $msg, Sanitizer::safeBiDi( $this->getContextTitle()->getPrefixedText() ) ) );
 		} else {
 			# Use the title defined by DISPLAYTITLE magic word when present
 			if ( isset( $this->mParserOutput )
Index: includes/HistoryPage.php
===================================================================
--- includes/HistoryPage.php	(revision 86942)
+++ includes/HistoryPage.php	(working copy)
@@ -546,7 +546,7 @@
 			$s .= ' ' . $this->getSkin()->formatRevisionSize( $size );
 		}
 
-		$s .= $this->getSkin()->revComment( $rev, false, true );
+		$s .= Sanitizer::safeBiDi( $this->getSkin()->revComment( $rev, false, true ) );
 
 		if ( $notificationtimestamp && ( $row->rev_timestamp >= $notificationtimestamp ) ) {
 			$s .= ' <span class="updatedmarker">' .  wfMsgHtml( 'updatedmarker' ) . '</span>';
Index: includes/Sanitizer.php
===================================================================
--- includes/Sanitizer.php	(revision 86942)
+++ includes/Sanitizer.php	(working copy)
@@ -1619,4 +1619,21 @@
 
 		return (bool) preg_match( $HTML5_email_regexp, $addr );
 	}
+	
+	/**
+	 * Wraps text in a span which creates a new Unicode bidirectional
+	 * level. This means that RTL text inside can safely be used among
+	 * LTR text (and vice versa), without causing trouble with so-called
+	 * neutral characters (like punctuation), which depend on the context
+	 * whether they behave as LTR or RTL characters.
+	 *
+	 * This should be used in all places where a piece of text potentially
+	 * has another direction than the surrounding text.
+	 *
+	 * @param $content string Text to wrap
+	 * @return string Wrapped text
+	 */
+	public static function safeBiDi( $content ) {
+		return '<span class="unicode-embed">' . $content . '</span>';
+	}
 }
Index: includes/specials/SpecialCategories.php
===================================================================
--- includes/specials/SpecialCategories.php	(revision 86942)
+++ includes/specials/SpecialCategories.php	(working copy)
@@ -116,7 +116,8 @@
 	function formatRow($result) {
 		global $wgLang;
 		$title = Title::makeTitle( NS_CATEGORY, $result->cat_title );
-		$titleText = $this->getSkin()->link( $title, htmlspecialchars( $title->getText() ) );
+		$titleText = Sanitizer::safeBiDi( $this->getSkin()->link( 
+				$title, htmlspecialchars( $title->getText() ) ) );
 		$count = wfMsgExt( 'nmembers', array( 'parsemag', 'escape' ),
 				$wgLang->formatNum( $result->cat_pages ) );
 		return Xml::tags('li', null, "$titleText ($count)" ) . "\n";
Index: includes/specials/SpecialWhatlinkshere.php
===================================================================
--- includes/specials/SpecialWhatlinkshere.php	(revision 86942)
+++ includes/specials/SpecialWhatlinkshere.php	(working copy)
@@ -277,12 +277,12 @@
 			$query = array();
 		}
 
-		$link = Linker::linkKnown(
+		$link = Sanitizer::safeBiDi( Linker::linkKnown(
 			$nt,
 			null,
 			array(),
 			$query
-		);
+		));
 
 		// Display properties (redirect or template)
 		$propsText = '';
