[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Bug#689156: unblock: mediawiki/1:1.19.2-1



Package: release.debian.org
Severity: normal
User: release.debian.org@packages.debian.org
Usertags: unblock

Please unblock package mediawiki

This upload follows on both the threads for better MW 1.19 support
http://article.gmane.org/gmane.linux.debian.devel.release/56559
and the multiple security issues (Debian #686330) part:
http://thread.gmane.org/gmane.linux.debian.devel.secure-testing.general/5325

The changes can be split into multiple parts. The security issues
were fixed by the new upstream version, which I’ll detail below.
First are the changes inside debian/ which I’ll show as diffs
between the _patched_ sources again (like with mksh) because
diffs between "3.0 (quilt)" diffs are harder to read, except:

The file debian/patches/texvc_location.patch was removed, but it
was already not used in 1.19.1-1. The following patches were added
and have been attached to this message and removed from the diff:
fix_invalid_xhtml.patch, fix_warnings.patch

First, the packaging changes: add myself to Uploaders; do not
replace the jquery-tablesorter shipped with MW by the one in
Debian again because the MW one is a different/patched codebase
(fixes #687519); update Breaks wrt. the isochronal uploads of
src:fusionforge and src:mediawiki-exensions (for which I’ll also
file an unblock request); and Jonathan had added two Recommends.
I added a few “chmod +x” to quieten lintian and removed a COPYING
file from the .deb file after verifying its contents were already
in debian/copyright (which they were).

--- mediawiki-1.19.2-0/debian/changelog	2012-06-18 17:17:26.000000000 +0200
+++ mediawiki-1.19.2-1/debian/changelog	2012-09-20 13:45:26.000000000 +0200
@@ -1,3 +1,26 @@
+mediawiki (1:1.19.2-1) unstable; urgency=low
+
+  [ Thorsten Glaser ]
+  * New upstream: security fixes for CVE-2012-4377, CVE-2012-4378,
+    CVE-2012-4379, CVE-2012-4380, CVE-2012-4381, CVE-2012-4382
+    (Closes: #686330)
+  * Prevent <table></table> without any <tr /> inside, globally
+  * Fix more cases of not checking $wgHtml5
+  * MW’s ID (XML) sanitiser is there for a reason, use it!
+  * Prevent <ul></ul> without any <li /> inside in MonoBook
+  * Fix invalid XHTML caused by code not honouring $wgHtml5
+  * Quell some PHP warnings from sloppy code
+  * Do the wfSuppressWarnings patch used with FusionForge right
+  * Add myself to Uploaders and quieten lintian a bit
+  * Do not replace patched jquery-tablesorter with unpatched one;
+    unbreaks sortable tables (Closes: #687519)
+  * Update versioned Breaks against fusionforge and mw-extensions
+
+  [ Jonathan Wiltshire ]
+  * Add Recommends on mediawiki-extensions-base and php-wikidiff2
+
+ -- Thorsten Glaser <tg@mirbsd.de>  Thu, 20 Sep 2012 13:40:12 +0200
+
 mediawiki (1:1.19.1-1) unstable; urgency=low
 
   * New upstream bug fix release
--- mediawiki-1.19.2-0/debian/control	2012-06-18 16:31:31.000000000 +0200
+++ mediawiki-1.19.2-1/debian/control	2012-09-20 13:45:26.000000000 +0200
@@ -2,7 +2,7 @@ Source: mediawiki
 Section: web
 Priority: optional
 Maintainer: Mediawiki Maintenance Team <pkg-mediawiki-devel@lists.alioth.debian.org>
-Uploaders: Romain Beauxis <toots@rastageeks.org>, Jonathan Wiltshire <jmw@debian.org>
+Uploaders: Romain Beauxis <toots@rastageeks.org>, Jonathan Wiltshire <jmw@debian.org>, Thorsten Glaser <tg@mirbsd.de>
 Build-Depends: debhelper (>= 9),
  dh-buildinfo,
  ocaml-nox | ocaml, xsltproc, docbook-xml, docbook-xsl, po-debconf
@@ -13,10 +13,19 @@ Vcs-Browser: http://svn.debian.org/views
 
 Package: mediawiki
 Architecture: all
-Depends: apache2 | httpd, php5, php5-mysql | php5-pgsql | php5-sqlite, mime-support, libjs-jquery, libjs-jquery-tipsy, libjs-jquery-cookie, libjs-jquery-form, libjs-jquery-tablesorter, ${misc:Depends} 
-Recommends: mysql-server | postgresql-contrib, php5-cli, python
+Depends: apache2 | httpd, php5, php5-mysql | php5-pgsql | php5-sqlite, mime-support, libjs-jquery, libjs-jquery-tipsy, libjs-jquery-cookie, libjs-jquery-form, ${misc:Depends}
+Recommends: mysql-server | postgresql-contrib, php5-cli, python, php-wikidiff2,  mediawiki-extensions-base
 Suggests: imagemagick | php5-gd, mediawiki-math, memcached, clamav
-Breaks: fusionforge-plugin-mediawiki (<< 5.2~rc1-4~)
+Breaks: fusionforge-plugin-mediawiki (<< 5.2~rc1+1~),
+ mediawiki-extensions-base (<< 2.8~),
+ mediawiki-extensions-geshi (<< 2.8~),
+ mediawiki-extensions-ldapauth (<< 2.8~),
+ mediawiki-extensions-openid (<< 2.8~),
+ mediawiki-extensions-confirmedit (<< 2.8~),
+ mediawiki-extensions-fckeditor (<< 2.8~),
+ mediawiki-extensions-collection (<< 2.8~),
+ mediawiki-extensions-graphviz (<< 2.8~),
+ mediawiki-extensions (<< 2.8~)
 Description: website engine for collaborative work
  MediaWiki is a wiki engine (a program for creating a collaboratively
  edited website). It is designed to handle heavy websites containing
--- mediawiki-1.19.2-0/debian/rules	2012-06-18 16:51:36.000000000 +0200
+++ mediawiki-1.19.2-1/debian/rules	2012-09-20 13:45:26.000000000 +0200
@@ -6,9 +6,14 @@ DEB_UPSTREAM_VERSION ?= $(shell echo $(D
 
 override_dh_install:
 	dh_install
+	# Ugh. This is easier than patching, though.
+	chmod a+x debian/mediawiki/usr/share/mediawiki/includes/normal/UtfNormalTest2.php
 	# Now some tidying up is required
 	chmod a+x debian/mediawiki/usr/share/mediawiki/maintenance/postgres/compare_schemas.pl
 	chmod a+x debian/mediawiki/usr/share/mediawiki/maintenance/postgres/mediawiki_mysql2postgres.pl
+	chmod a+x debian/mediawiki/var/lib/mediawiki/extensions/ConfirmEdit/captcha.py
+	chmod a-x debian/mediawiki/usr/share/mediawiki/resources/jquery/images/marker.png
+	chmod a-x debian/mediawiki/var/lib/mediawiki/extensions/WikiEditor/modules/jquery.wikiEditor.toolbar.config.js
 	find debian/mediawiki/usr/share/mediawiki -maxdepth 1 -mindepth 1 | grep -v "\(LocalSettings.php\|AdminSettings.php\|debian-scripts\|images\|extensions\|config\)" | \
 	while read i; do \
 		dh_link "`echo "$$i" | sed -e s#debian/mediawiki/##`" \
@@ -19,7 +24,7 @@ override_dh_install:
 	rm debian/mediawiki/usr/share/mediawiki/resources/jquery.tipsy/jquery.tipsy.js
 	dh_link usr/share/javascript/jquery/jquery.min.js usr/share/mediawiki/resources/jquery/jquery.js
 	dh_link usr/share/javascript/jquery-tipsy/jquery.tipsy.min.js usr/share/mediawiki/resources/jquery.tipsy/jquery.tipsy.js; \
-	for lib in cookie form tablesorter; do \
+	for lib in cookie form; do \
 		rm debian/mediawiki/usr/share/mediawiki/resources/jquery/jquery.$$lib.js; \
 		dh_link usr/share/javascript/jquery-$$lib/jquery.$$lib.min.js usr/share/mediawiki/resources/jquery/jquery.$$lib.js; \
 		echo $$lib; \
@@ -33,6 +38,7 @@ override_dh_install:
 	rm -f debian/mediawiki/usr/share/mediawiki/maintenance/cssjanus/COPYING
 	rm -f debian/mediawiki/usr/share/mediawiki/maintenance/cssjanus/LICENSE
 	rm -f debian/mediawiki/var/lib/mediawiki/extensions/ParserFunctions/COPYING
+	rm -f debian/mediawiki/var/lib/mediawiki/extensions/Nuke/COPYING
 	# Put debian version for mediawiki version..
 	sed -e "s#$(DEB_UPSTREAM_VERSION)#$(DEB_NOEPOCH_VERSION)#" \
 			-i debian/mediawiki/usr/share/mediawiki/includes/DefaultSettings.php
--- mediawiki-1.19.2-0/debian/watch	2012-01-15 00:44:13.000000000 +0100
+++ mediawiki-1.19.2-1/debian/watch	2012-09-20 13:45:26.000000000 +0200
@@ -1,8 +1,3 @@
-# Example watch control file for uscan
-# Rename this file to "watch" and then you can run the "uscan" command
-# to check for upstream updates and more.
-# See uscan(1) for format
-
 # Compulsory line, this is a version 3 file
 version=3
 

This change lets FusionForge, which has a “developer mode” in which
it does things to error reporting so a developer knows when they make
a mistake, know whether we are in a “sloppy” section of MW code: the
MediaWiki way of doing things is to temporarily disable warnings when
they know they do something that produces one, and these clutter the
FF debug mode enormously. While FusionForge was removed from testing,
I hereby ask that this change still be considered, so we can use all
“other” packages straight from the then-to-be release, including its
security fixes. (This can also be used by others…)

--- mediawiki-1.19.2-0/includes/GlobalFunctions.php	2012-09-29 17:19:21.000000000 +0200
+++ mediawiki-1.19.2-1/includes/GlobalFunctions.php	2012-09-29 17:21:13.000000000 +0200
@@ -2199,7 +2199,9 @@ function wfNegotiateType( $cprefs, $spre
  *
  * @param $end Bool
  */
+$wf__warnings_suppressed = false;
 function wfSuppressWarnings( $end = false ) {
+	global $wf__warnings_suppressed;
 	static $suppressCount = 0;
 	static $originalLevel = false;
 
@@ -2208,6 +2210,7 @@ function wfSuppressWarnings( $end = fals
 			--$suppressCount;
 			if ( !$suppressCount ) {
 				error_reporting( $originalLevel );
+				$wf__warnings_suppressed = false;
 			}
 		}
 	} else {
@@ -2217,6 +2220,7 @@ function wfSuppressWarnings( $end = fals
 				define( 'E_DEPRECATED', 8192 );
 			}
 			$originalLevel = error_reporting( E_ALL & ~( E_WARNING | E_NOTICE | E_USER_WARNING | E_USER_NOTICE | E_DEPRECATED ) );
+			$wf__warnings_suppressed = true;
 		}
 		++$suppressCount;
 	}

fix_invalid_xhtml.patch mostly fixes some sloppy coding on the
MediaWiki side as well as places where they forgot to check
whether HTML5 or XHTML was requested. fix_warnings.patch comes
in similar spirit to the $wf__warnings_suppressed change.

Now, the changes between upstream 1.19.1 and 1.19.2 can also
be separated in translation and other changes. The translation
changes are all in languages/messages/ but the diff between
them is 10.2 MB, which is a tad large for this message, so I
politely ask that you look at that part yourselves or trust in
upstream they really only included translation changes.

All other changes boil down to upstream removing the .gitignore
files from the .orig.tar.gz and the file mw-1-19-2.diff attached,
which are release notes and what I hope are only the fixes for
the security issues mentioned (the changes look okay-ish to me,
but I’m not capable of analysing them fully, since I normally
don’t hang that deep inside MW source code).

unblock mediawiki/1:1.19.2-1

-- System Information:
Debian Release: wheezy/sid
  APT prefers unstable
  APT policy: (500, 'unstable'), (500, 'testing')
Architecture: i386 (i686)

Kernel: Linux 3.2.0-3-686-pae (SMP w/1 CPU core)
Locale: LANG=C, LC_CTYPE=en_GB.UTF-8 (charmap=UTF-8)
Shell: /bin/sh linked to /bin/mksh-static
$Id: fix_invalid_xhtml.patch 379 2012-09-20 11:45:26Z tg $

Fix invalid XHTML:
• prevent <table></table> without any <tr /> inside
• someone forgot to check whether HTML5 was enabled before toying around
• sanitise XML IDs (a space is *not* allowed, and "Main Page" contains one)
• let makeLink and all its callers remove HTML5-only attributes from
  hyperlinks if someone else was not careful (rather, several someones)
• prevent <ul></ul> without any <li /> inside

--- a/includes/HTMLForm.php
+++ b/includes/HTMLForm.php
@@ -803,6 +803,9 @@ class HTMLForm extends ContextSource {
 			$attribs['id'] = Sanitizer::escapeId( "mw-htmlform-$sectionName" );
 		}
 
+		if (!$tableHtml)
+			$tableHtml = '<tr><td><!-- empty to prevent invalid XHTML --></td></tr>';
+
 		$tableHtml = Html::rawElement( 'table', $attribs,
 			Html::rawElement( 'tbody', array(), "\n$tableHtml\n" ) ) . "\n";
 
@@ -1206,6 +1209,8 @@ class HTMLTextField extends HTMLFormFiel
 	}
 
 	function getInputHTML( $value ) {
+		global $wgHtml5;
+
 		$attribs = array(
 			'id' => $this->mID,
 			'name' => $this->mName,
@@ -1229,6 +1234,8 @@ class HTMLTextField extends HTMLFormFiel
 		# well
 		foreach ( array( 'min', 'max', 'pattern', 'title', 'step',
 		'placeholder' ) as $param ) {
+			if ( !$wgHtml5 && $param != 'title' )
+				continue;
 			if ( isset( $this->mParams[$param] ) ) {
 				$attribs[$param] = $this->mParams[$param];
 			}
@@ -1625,13 +1632,14 @@ class HTMLMultiSelectField extends HTMLF
 				$html .= Html::rawElement( 'h1', array(), $label ) . "\n";
 				$html .= $this->formatOptions( $info, $value );
 			} else {
-				$thisAttribs = array( 'id' => "{$this->mID}-$info", 'value' => $info );
+				$info_id = Sanitizer::escapeId($this->mID . '-' . $info);
+				$thisAttribs = array( 'id' => $info_id, 'value' => $info );
 
 				$checkbox = Xml::check(
 					$this->mName . '[]',
 					in_array( $info, $value, true ),
 					$attribs + $thisAttribs );
-				$checkbox .= '&#160;' . Html::rawElement( 'label', array( 'for' => "{$this->mID}-$info" ), $label );
+				$checkbox .= '&#160;' . Html::rawElement( 'label', array( 'for' => $info_id ), $label );
 
 				$html .= ' ' . Html::rawElement( 'div', array( 'class' => 'mw-htmlform-flatlist-item' ), $checkbox );
 			}
--- a/includes/SkinTemplate.php
+++ b/includes/SkinTemplate.php
@@ -1613,6 +1613,8 @@ abstract class BaseTemplate extends Quic
 	 *   output a <span> instead of just text.
 	 */
 	function makeLink( $key, $item, $options = array() ) {
+		global $wgHtml5;
+
 		if ( isset( $item['text'] ) ) {
 			$text = $item['text'];
 		} else {
@@ -1664,6 +1666,11 @@ abstract class BaseTemplate extends Quic
 					$attrs['class'] = $options['link-class'];
 				}
 			}
+			if ( !$wgHtml5 ) {
+				foreach ( array( 'context', 'primary' ) as $k ) {
+					unset( $attrs[$k] );
+				}
+			}
 			$html = Html::rawElement( isset( $attrs['href'] ) ? 'a' : $options['link-fallback'], $attrs, $html );
 		}
 
--- a/skins/MonoBook.php
+++ b/skins/MonoBook.php
@@ -60,6 +60,8 @@ class MonoBookTemplate extends BaseTempl
 	 * @access private
 	 */
 	function execute() {
+		global $wgHtml5;
+
 		// Suppress warnings to prevent notices about missing indexes in $this->data
 		wfSuppressWarnings();
 
@@ -69,7 +71,7 @@ class MonoBookTemplate extends BaseTempl
 	<a id="top"></a>
 	<?php if($this->data['sitenotice']) { ?><div id="siteNotice"><?php $this->html('sitenotice') ?></div><?php } ?>
 
-	<h1 id="firstHeading" class="firstHeading"><span dir="auto"><?php $this->html('title') ?></span></h1>
+	<h1 id="firstHeading" class="firstHeading"><span<?php if ($wgHtml5) echo ' dir="auto"'; ?>><?php $this->html('title') ?></span></h1>
 	<div id="bodyContent" class="mw-body">
 		<div id="siteSub"><?php $this->msg('tagline') ?></div>
 		<div id="contentSub"<?php $this->html('userlangattributes') ?>><?php $this->html('subtitle') ?></div>
@@ -93,12 +95,21 @@ class MonoBookTemplate extends BaseTempl
 	<div class="portlet" id="p-personal">
 		<h5><?php $this->msg('personaltools') ?></h5>
 		<div class="pBody">
+<?php
+	$ul_shown = false;
+	foreach ($this->getPersonalTools() as $key => $item) {
+		if (!$ul_shown) {
+?>
 			<ul<?php $this->html('userlangattributes') ?>>
-<?php		foreach($this->getPersonalTools() as $key => $item) { ?>
-				<?php echo $this->makeListItem($key, $item); ?>
-
-<?php		} ?>
-			</ul>
+<?php
+			$ul_shown = true;
+		}
+		echo "\n" . $this->makeListItem($key, $item);
+	}
+	if ($ul_shown) {
+		echo "\n</ul>\n";
+	}
+?>
 		</div>
 	</div>
 	<div class="portlet" id="p-logo">
--- a/includes/Linker.php
+++ b/includes/Linker.php
@@ -1148,7 +1148,7 @@ class Linker {
 	 * @return string
 	 */
 	private static function formatAutocommentsCallback( $match ) {
-		global $wgLang;
+		global $wgLang, $wgHtml5;
 		$title = self::$autocommentTitle;
 		$local = self::$autocommentLocal;
 
@@ -1189,7 +1189,9 @@ class Linker {
 			$auto .= wfMsgExt( 'colon-separator', array( 'escapenoentities', 'content' ) );
 		}
 		$auto = '<span class="autocomment">' . $auto . '</span>';
-		$comment = $pre . $link . $wgLang->getDirMark() . '<span dir="auto">' . $auto . $post . '</span>';
+		$comment = $pre . $link . $wgLang->getDirMark() .
+		    '<span' . ($wgHtml5 ? ' dir="auto"' : '') . '>' . $auto .
+		    $post . '</span>';
 		return $comment;
 	}
 
@@ -1381,6 +1383,8 @@ class Linker {
 	 * @return string
 	 */
 	public static function commentBlock( $comment, $title = null, $local = false ) {
+		global $wgHtml5;
+
 		// '*' used to be the comment inserted by the software way back
 		// in antiquity in case none was provided, here for backwards
 		// compatability, acc. to brion -ævar
@@ -1388,7 +1392,9 @@ class Linker {
 			return '';
 		} else {
 			$formatted = self::formatComment( $comment, $title, $local );
-			return " <span class=\"comment\" dir=\"auto\">($formatted)</span>";
+			return " <span class=\"comment\"" .
+			    ($wgHtml5 ? " dir=\"auto\"" : "") .
+			    ">($formatted)</span>";
 		}
 	}
 
$Id: fix_warnings.patch 379 2012-09-20 11:45:26Z tg $

Fix code:
• array_merge expects at least one argument
• apparently, checking for syntax with unserialize() needs an extra

--- a/includes/SkinTemplate.php
+++ b/includes/SkinTemplate.php
@@ -1808,7 +1808,7 @@ abstract class BaseTemplate extends Quic
 			}
 		}
 
-		if ( $option == 'flat' ) {
+		if ( $option == 'flat' && $validFooterLinks ) {
 			// fold footerlinks into a single array using a bit of trickery
 			$validFooterLinks = call_user_func_array(
 				'array_merge',
--- a/includes/media/PNG.php
+++ b/includes/media/PNG.php
@@ -78,7 +78,7 @@ class PNGHandler extends BitmapHandler {
 		}
 
 		wfSuppressWarnings();
-		$data = unserialize( $metadata );
+		$data = @unserialize( $metadata );
 		wfRestoreWarnings();
 
 		if ( !$data || !is_array( $data ) ) {
--- mediawiki-1.19.1/RELEASE-NOTES-1.19	2012-06-13 20:22:38.000000000 +0200
+++ mediawiki-1.19.2/RELEASE-NOTES-1.19	2012-08-31 00:25:34.000000000 +0200
@@ -3,6 +3,19 @@
 Security reminder: MediaWiki does not require PHP's register_globals
 setting since version 1.2.0. If you have it on, turn it '''off''' if you can.
 
+== MediaWiki 1.19.2 ==
+2012-08-30
+
+This is a security release of the MediaWiki 1.19 branch
+
+=== Changes since 1.19.1 ===
+* (bug 39700) File: link to non-existing file can inject html
+* (bug 35839) Hidden block text leaking to admins
+* (bug 39184) LDAP password leakage
+* (bug 39180) Disallow framing of api results
+* (bug 37587) Enforce language codes to be html safe
+* (bug 38333) Check global blocks on account creation
+
 == MediaWiki 1.19 ==
 
 MediaWiki 1.19 is a large release that contains many new features and bug
@@ -13,6 +26,9 @@ this version.
 Our thanks go to everyone who helped to improve MediaWiki by testing the beta
 release and submitting bug reports.
 
+=== Changes since 1.19.1 ===
+* (bug 38406) Properly quote table names in DatabaseBase::tableName()
+
 === Changes since 1.19.0 ===
 * (bug 36568) Fixed "Illegal string offset 'LIMIT'" warnings in updater
 * (bug 36938) Correctly escape uselang attribute to prevent xss
--- mediawiki-1.19.1/includes/AuthPlugin.php	2012-06-13 20:22:38.000000000 +0200
+++ mediawiki-1.19.2/includes/AuthPlugin.php	2012-08-31 00:25:34.000000000 +0200
@@ -157,6 +157,15 @@ class AuthPlugin {
 	}
 
 	/**
+	 * Should MediaWiki store passwords in its local database?
+	 *
+	 * @return bool
+	 */
+	public function allowSetLocalPassword() {
+		return true;
+	}
+
+	/**
 	 * Set the given password in the authentication database.
 	 * As a special case, the password may be set to null to request
 	 * locking the password to an unusable value, with the expectation
--- mediawiki-1.19.1/includes/DefaultSettings.php	2012-06-13 20:22:38.000000000 +0200
+++ mediawiki-1.19.2/includes/DefaultSettings.php	2012-08-31 00:25:34.000000000 +0200
@@ -33,7 +33,7 @@ $wgConf = new SiteConfiguration;
 /** @endcond */
 
 /** MediaWiki version number */
-$wgVersion = '1.19.1';
+$wgVersion = '1.19.2';
 
 /** Name of the site. It must be changed in LocalSettings.php */
 $wgSitename = 'MediaWiki';
@@ -2420,6 +2420,18 @@ $wgBreakFrames = false;
 $wgEditPageFrameOptions = 'DENY';
 
 /**
+ * Disallow framing of API pages directly, by setting the X-Frame-Options
+ * header. Since the API returns CSRF tokens, allowing the results to be
+ * framed can compromise your user's account security.
+ * Options are:
+ *   - 'DENY': Do not allow framing. This is recommended for most wikis.
+ *   - 'SAMEORIGIN': Allow framing by pages on the same domain.
+ *   - false: Allow all framing.
+ */
+
+$wgApiFrameOptions = 'DENY';
+
+/**
  * Disable output compression (enabled by default if zlib is available)
  */
 $wgDisableOutputCompression = false;
--- mediawiki-1.19.1/includes/Linker.php	2012-06-13 20:22:38.000000000 +0200
+++ mediawiki-1.19.2/includes/Linker.php	2012-08-31 00:25:34.000000000 +0200
@@ -768,31 +768,31 @@ class Linker {
 	 * Make a "broken" link to an image
 	 *
 	 * @param $title Title object
-	 * @param $html String: link label in htmlescaped text form
+	 * @param $label String: link label (plain text)
 	 * @param $query String: query string
-	 * @param $trail String: link trail (HTML fragment)
-	 * @param $prefix String: link prefix (HTML fragment)
+	 * @param $unused1 Unused parameter kept for b/c
+	 * @param $unused2 Unused parameter kept for b/c
 	 * @param $time Boolean: a file of a certain timestamp was requested
 	 * @return String
 	 */
-	public static function makeBrokenImageLinkObj( $title, $html = '', $query = '', $trail = '', $prefix = '', $time = false ) {
+	public static function makeBrokenImageLinkObj( $title, $label = '', $query = '', $unused1 = '', $unused2 = '', $time = false ) {
 		global $wgEnableUploads, $wgUploadMissingFileUrl, $wgUploadNavigationUrl;
 		if ( ! $title instanceof Title ) {
-			return "<!-- ERROR -->{$prefix}{$html}{$trail}";
+			return "<!-- ERROR -->" . htmlspecialchars( $label );
 		}
 		wfProfileIn( __METHOD__ );
+		if ( $label == '' ) {
+			$label = $title->getPrefixedText();
+		}
+		$encLabel = htmlspecialchars( $label );
 		$currentExists = $time ? ( wfFindFile( $title ) != false ) : false;
 
-		list( $inside, $trail ) = self::splitTrail( $trail );
-		if ( $html == '' )
-			$html = htmlspecialchars( $title->getPrefixedText() );
-
 		if ( ( $wgUploadMissingFileUrl || $wgUploadNavigationUrl || $wgEnableUploads ) && !$currentExists ) {
 			$redir = RepoGroup::singleton()->getLocalRepo()->checkRedirect( $title );
 
 			if ( $redir ) {
 				wfProfileOut( __METHOD__ );
-				return self::linkKnown( $title, "$prefix$html$inside", array(), $query ) . $trail;
+				return self::linkKnown( $title, $encLabel, array(), wfCgiToArray( $query ) );
 			}
 
 			$href = self::getUploadUrl( $title, $query );
@@ -800,10 +800,10 @@ class Linker {
 			wfProfileOut( __METHOD__ );
 			return '<a href="' . htmlspecialchars( $href ) . '" class="new" title="' .
 				htmlspecialchars( $title->getPrefixedText(), ENT_QUOTES ) . '">' .
-				"$prefix$html$inside</a>$trail";
+				$encLabel . '</a>';
 		} else {
 			wfProfileOut( __METHOD__ );
-			return self::linkKnown( $title, "$prefix$html$inside", array(), $query ) . $trail;
+			return self::linkKnown( $title, $encLabel, array(), wfCgiToArray( $query ) );
 		}
 	}
 
--- mediawiki-1.19.1/includes/User.php	2012-06-13 20:22:38.000000000 +0200
+++ mediawiki-1.19.2/includes/User.php	2012-08-31 00:25:34.000000000 +0200
@@ -2812,11 +2812,16 @@ class User {
 	 * @todo Only rarely do all these fields need to be set!
 	 */
 	public function saveSettings() {
+		global $wgAuth;
+
 		$this->load();
 		if ( wfReadOnly() ) { return; }
 		if ( 0 == $this->mId ) { return; }
 
 		$this->mTouched = self::newTouchedTimestamp();
+		if ( !$wgAuth->allowSetLocalPassword() ) {
+			$this->mPassword = '';
+		}
 
 		$dbw = wfGetDB( DB_MASTER );
 		$dbw->update( 'user',
--- mediawiki-1.19.1/includes/api/ApiFormatBase.php	2012-06-13 20:22:38.000000000 +0200
+++ mediawiki-1.19.2/includes/api/ApiFormatBase.php	2012-08-31 00:25:34.000000000 +0200
@@ -143,6 +143,12 @@ abstract class ApiFormatBase extends Api
 
 		$this->getMain()->getRequest()->response()->header( "Content-Type: $mime; charset=utf-8" );
 
+		//Set X-Frame-Options API results (bug 39180)
+		global $wgApiFrameOptions;
+		if ( $wgApiFrameOptions ) {
+			$this->getMain()->getRequest()->response()->header( "X-Frame-Options: $wgApiFrameOptions" );
+		}
+
 		if ( $isHtml ) {
 ?>
 <!DOCTYPE HTML>
--- mediawiki-1.19.1/includes/db/Database.php	2012-06-13 20:22:38.000000000 +0200
+++ mediawiki-1.19.2/includes/db/Database.php	2012-08-31 00:25:34.000000000 +0200
@@ -1973,7 +1973,9 @@ abstract class DatabaseBase implements D
 
 		# Quote the $database and $table and apply the prefix if not quoted.
 		if ( isset( $database ) ) {
-			$database = ( $format == 'quoted' || $this->isQuotedIdentifier( $database ) ? $database : $this->addIdentifierQuotes( $database ) );
+			if ( $format == 'quoted' && !$this->isQuotedIdentifier( $database ) ) {
+				$database = $this->addIdentifierQuotes( $database );
+			}
 		}
 
 		$table = "{$prefix}{$table}";
--- mediawiki-1.19.1/includes/installer/OracleUpdater.php	2012-06-13 20:22:39.000000000 +0200
+++ mediawiki-1.19.2/includes/installer/OracleUpdater.php	2012-08-31 00:25:34.000000000 +0200
@@ -40,17 +40,16 @@ class OracleUpdater extends DatabaseUpda
 
 			//1.19
 			array( 'addIndex', 'logging',       'i05',      'patch-logging_type_action_index.sql'),
-			array( 'addTable', 'globaltemplatelinks', 'patch-globaltemplatelinks.sql' ),
-			array( 'addTable', 'globalnamespaces', 'patch-globalnamespaces.sql' ),
-			array( 'addTable', 'globalinterwiki', 'patch-globalinterwiki.sql' ),
 			array( 'addField', 'revision', 'rev_sha1', 'patch-rev_sha1_field.sql' ),
 			array( 'addField', 'archive', 'ar_sha1', 'patch-ar_sha1_field.sql' ),
 			array( 'doRemoveNotNullEmptyDefaults2' ),
 			array( 'addIndex', 'page', 'i03', 'patch-page_redirect_namespace_len.sql' ),
-			array( 'modifyField', 'user', 'ug_group', 'patch-ug_group-length-increase.sql' ),
+			array( 'modifyField', 'user_groups', 'ug_group', 'patch-ug_group-length-increase.sql' ),
 			array( 'addField', 'uploadstash', 'us_chunk_inx', 'patch-us_chunk_inx_field.sql' ),
 			array( 'addField', 'job', 'job_timestamp', 'patch-job_timestamp_field.sql' ),
 			array( 'addIndex', 'job', 'i02', 'patch-job_timestamp_index.sql' ),
+			array( 'doPageRestrictionsPKUKFix' ),
+			array( 'modifyField', 'user_former_groups', 'ufg_group', 'patch-ufg_group-length-increase.sql' ),
 
 			// KEEP THIS AT THE BOTTOM!!
 			array( 'doRebuildDuplicateFunction' ),
@@ -179,6 +178,23 @@ class OracleUpdater extends DatabaseUpda
 		$this->output( "ok\n" );
 	}
 
+	/**
+	 * Fixed wrong PK, UK definition
+	 */
+	protected function doPageRestrictionsPKUKFix() {
+		$this->output( "Altering PAGE_RESTRICTIONS keys ... " );
+
+		$meta = $this->db->query( 'SELECT column_name FROM all_cons_columns WHERE owner = \''.strtoupper($this->db->getDBname()).'\' AND constraint_name = \'MW_PAGE_RESTRICTIONS_PK\' AND rownum = 1' );
+		$row = $meta->fetchRow();
+		if ( $row['column_name'] == 'PR_ID' ) {
+			$this->output( "seems to be up to date.\n" );
+			return;
+		}
+
+		$this->applyPatch( 'patch-page_restrictions_pkuk_fix.sql', false );
+		$this->output( "ok\n" );
+	}
+
 	/**
 	 * rebuilding of the function that duplicates tables for tests
 	 */
--- mediawiki-1.19.1/includes/specials/SpecialBlock.php	2012-06-13 20:22:39.000000000 +0200
+++ mediawiki-1.19.2/includes/specials/SpecialBlock.php	2012-08-31 00:25:34.000000000 +0200
@@ -257,7 +257,13 @@ class SpecialBlock extends FormSpecialPa
 				$fields['DisableUTEdit']['default'] = $block->prevents( 'editownusertalk' );
 			}
 
+			// If the username was hidden (ipb_deleted == 1), don't show the reason
+			// unless this user also has rights to hideuser: Bug 35839
+			if ( !$block->mHideName || $this->getUser()->isAllowed( 'hideuser' ) ) {
 			$fields['Reason']['default'] = $block->mReason;
+			} else {
+				$fields['Reason']['default'] = '';
+			}
 
 			if( $this->getRequest()->wasPosted() ){
 				# Ok, so we got a POST submission asking us to reblock a user.  So show the
--- mediawiki-1.19.1/includes/specials/SpecialUserlogin.php	2012-06-13 20:22:39.000000000 +0200
+++ mediawiki-1.19.2/includes/specials/SpecialUserlogin.php	2012-08-31 00:25:34.000000000 +0200
@@ -326,6 +326,12 @@ class LoginForm extends SpecialPage {
 			return false;
 		}
 
+		# Include checks that will include GlobalBlocking (Bug 38333)
+		$permErrors = $this->getTitle()->getUserPermissionsErrors( 'createaccount', $currentUser, true );
+		if ( count( $permErrors ) ) {
+				throw new PermissionsError( 'createaccount', $permErrors );
+		}
+
 		$ip = $this->getRequest()->getIP();
 		if ( $currentUser->isDnsBlacklisted( $ip, true /* check $wgProxyWhitelist */ ) ) {
 			$this->mainLoginForm( $this->msg( 'sorbs_create_account_reason' )->text() . ' (' . htmlspecialchars( $ip ) . ')' );
--- mediawiki-1.19.1/languages/Language.php	2012-06-13 20:22:39.000000000 +0200
+++ mediawiki-1.19.2/languages/Language.php	2012-08-31 00:25:34.000000000 +0200
@@ -210,7 +210,11 @@ class Language {
 	 */
 	public static function isValidCode( $code ) {
 		return
-			strcspn( $code, ":/\\\000" ) === strlen( $code )
+			// People think language codes are html safe, so enforce it.
+			// Ideally we should only allow a-zA-Z0-9-
+			// but, .+ and other chars are often used for {{int:}} hacks
+			// see bugs 37564, 37587, 36938
+			strcspn( $code, ":/\\\000&<>'\"" ) === strlen( $code )
 			&& !preg_match( Title::getTitleInvalidRegex(), $code );
 	}
 
--- mediawiki-1.19.1/maintenance/language/messages.inc	2012-06-13 20:22:39.000000000 +0200
+++ mediawiki-1.19.2/maintenance/language/messages.inc	2012-08-31 00:25:35.000000000 +0200
@@ -1230,6 +1230,7 @@ $wgMessageStructure = array(
 		'newsectionsummary',
 		'rc-enhanced-expand',
 		'rc-enhanced-hide',
+		'rc-old-title',
 	),
 	'recentchangeslinked' => array(
 		'recentchangeslinked',
--- mediawiki-1.19.1/maintenance/oracle/archives/patch-page_restrictions_pkuk_fix.sql	1970-01-01 01:00:00.000000000 +0100
+++ mediawiki-1.19.2/maintenance/oracle/archives/patch-page_restrictions_pkuk_fix.sql	2012-08-31 00:25:34.000000000 +0200
@@ -0,0 +1,7 @@
+define mw_prefix='{$wgDBprefix}';
+
+ALTER TABLE &mw_prefix.page_restrictions DROP CONSTRAINT &mw_prefix.page_restrictions_pk;
+
+ALTER TABLE &mw_prefix.page_restrictions ADD CONSTRAINT &mw_prefix.page_restrictions_pk PRIMARY KEY (pr_id);
+
+CREATE UNIQUE INDEX &mw_prefix.page_restrictions_u01 ON &mw_prefix.page_restrictions (pr_page,pr_type);
--- mediawiki-1.19.1/maintenance/oracle/archives/patch-ufg_group-length-increase.sql	1970-01-01 01:00:00.000000000 +0100
+++ mediawiki-1.19.2/maintenance/oracle/archives/patch-ufg_group-length-increase.sql	2012-08-31 00:25:34.000000000 +0200
@@ -0,0 +1,9 @@
+define mw_prefix='{$wgDBprefix}';
+
+/*$mw$*/
+BEGIN
+	EXECUTE IMMEDIATE 'ALTER TABLE &mw_prefix.user_former_groups MODIFY ufg_group VARCHAR2(32) NOT NULL';
+EXCEPTION WHEN OTHERS THEN
+	IF (SQLCODE = -01442) THEN NULL; ELSE RAISE; END IF;
+END;
+/*$mw$*/
--- mediawiki-1.19.1/maintenance/oracle/archives/patch-ug_group-length-increase.sql	2012-06-13 20:22:38.000000000 +0200
+++ mediawiki-1.19.2/maintenance/oracle/archives/patch-ug_group-length-increase.sql	2012-08-31 00:25:34.000000000 +0200
@@ -1,3 +1,9 @@
 define mw_prefix='{$wgDBprefix}';
 
-ALTER TABLE &mw_prefix.user_groups MODIFY ug_group VARCHAR2(32) NOT NULL;
+/*$mw$*/
+BEGIN
+	EXECUTE IMMEDIATE 'ALTER TABLE &mw_prefix.user_groups MODIFY ug_group VARCHAR2(32) NOT NULL';
+EXCEPTION WHEN OTHERS THEN
+	IF (SQLCODE = -01442) THEN NULL; ELSE RAISE; END IF;
+END;
+/*$mw$*/
--- mediawiki-1.19.1/maintenance/oracle/tables.sql	2012-06-13 20:22:39.000000000 +0200
+++ mediawiki-1.19.2/maintenance/oracle/tables.sql	2012-08-31 00:25:35.000000000 +0200
@@ -39,7 +39,7 @@ CREATE INDEX &mw_prefix.user_groups_i01
 
 CREATE TABLE &mw_prefix.user_former_groups (
   ufg_user   NUMBER      DEFAULT 0 NOT NULL,
-  ufg_group  VARCHAR2(16)     NOT NULL
+  ufg_group  VARCHAR2(32)     NOT NULL
 );
 ALTER TABLE &mw_prefix.user_former_groups ADD CONSTRAINT &mw_prefix.user_former_groups_fk1 FOREIGN KEY (ufg_user) REFERENCES &mw_prefix.mwuser(user_id) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED;
 CREATE UNIQUE INDEX &mw_prefix.user_former_groups_u01 ON &mw_prefix.user_former_groups (ufg_user,ufg_group);
@@ -564,8 +564,9 @@ CREATE TABLE &mw_prefix.page_restriction
   pr_user    NUMBER          NULL,
   pr_expiry  TIMESTAMP(6) WITH TIME ZONE      NULL
 );
-ALTER TABLE &mw_prefix.page_restrictions ADD CONSTRAINT &mw_prefix.page_restrictions_pk PRIMARY KEY (pr_page,pr_type);
+ALTER TABLE &mw_prefix.page_restrictions ADD CONSTRAINT &mw_prefix.page_restrictions_pk PRIMARY KEY (pr_id);
 ALTER TABLE &mw_prefix.page_restrictions ADD CONSTRAINT &mw_prefix.page_restrictions_fk1 FOREIGN KEY (pr_page) REFERENCES &mw_prefix.page(page_id) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED;
+CREATE UNIQUE INDEX &mw_prefix.page_restrictions_u01 ON &mw_prefix.page_restrictions (pr_page,pr_type);
 CREATE INDEX &mw_prefix.page_restrictions_i01 ON &mw_prefix.page_restrictions (pr_type,pr_level);
 CREATE INDEX &mw_prefix.page_restrictions_i02 ON &mw_prefix.page_restrictions (pr_level);
 CREATE INDEX &mw_prefix.page_restrictions_i03 ON &mw_prefix.page_restrictions (pr_cascade);
--- mediawiki-1.19.1/tests/parser/parserTests.txt	2012-06-13 20:22:39.000000000 +0200
+++ mediawiki-1.19.2/tests/parser/parserTests.txt	2012-08-31 00:25:35.000000000 +0200
@@ -1733,6 +1733,21 @@ Link with double quotes in title part (l
 !! end
 
 !! test
+Broken image links with HTML captions (bug 39700)
+!! input
+[[File:Nonexistent|<script></script>]]
+[[File:Nonexistent|100px|<script></script>]]
+[[File:Nonexistent|&lt;]]
+[[File:Nonexistent|a<i>b</i>c]]
+!! result
+<p><a href="/index.php?title=Special:Upload&amp;wpDestFile=Nonexistent" class="new" title="File:Nonexistent">&lt;script&gt;&lt;/script&gt;</a>
+<a href="/index.php?title=Special:Upload&amp;wpDestFile=Nonexistent" class="new" title="File:Nonexistent">&lt;script&gt;&lt;/script&gt;</a>
+<a href="/index.php?title=Special:Upload&amp;wpDestFile=Nonexistent" class="new" title="File:Nonexistent">&lt;</a>
+<a href="/index.php?title=Special:Upload&amp;wpDestFile=Nonexistent" class="new" title="File:Nonexistent">abc</a>
+</p>
+!! end
+
+!! test
 Plain link to URL
 !! input
 [[http://www.example.com]]
--- mediawiki-1.19.1/tests/phpunit/includes/db/DatabaseTest.php	2012-06-13 20:22:38.000000000 +0200
+++ mediawiki-1.19.2/tests/phpunit/includes/db/DatabaseTest.php	2012-08-31 00:25:34.000000000 +0200
@@ -57,6 +57,98 @@ class DatabaseTest extends MediaWikiTest
 			$this->db->addQuotes( "string's cause trouble" ) );
 	}
 
+	private function getSharedTableName( $table, $database, $prefix, $format = 'quoted' ) {
+		global $wgSharedDB, $wgSharedTables, $wgSharedPrefix;
+
+		$oldName = $wgSharedDB;
+		$oldTables = $wgSharedTables;
+		$oldPrefix = $wgSharedPrefix;
+
+		$wgSharedDB = $database;
+		$wgSharedTables = array( $table );
+		$wgSharedPrefix = $prefix;
+
+		$ret = $this->db->tableName( $table, $format );
+
+		$wgSharedDB = $oldName;
+		$wgSharedTables = $oldTables;
+		$wgSharedPrefix = $oldPrefix;
+
+		return $ret;
+	}
+
+	private function prefixAndQuote( $table, $database = null, $prefix = null, $format = 'quoted' ) {
+		if ( $this->db->getType() === 'sqlite' || $format !== 'quoted' ) {
+			$quote = '';
+		} elseif ( $this->db->getType() === 'mysql' ) {
+			$quote = '`';
+		} else {
+			$quote = '"';
+		}
+
+		if ( $database !== null ) {
+			$database = $quote . $database . $quote . '.';
+		}
+
+		if ( $prefix === null ) {
+			$prefix = $this->dbPrefix();
+		}
+
+		return $database . $quote . $prefix . $table . $quote;
+	}
+
+	function testTableNameLocal() {
+		$this->assertEquals(
+			$this->prefixAndQuote( 'tablename' ),
+			$this->db->tableName( 'tablename' )
+		);
+	}
+
+	function testTableNameRawLocal() {
+		$this->assertEquals(
+			$this->prefixAndQuote( 'tablename', null, null, 'raw' ),
+			$this->db->tableName( 'tablename', 'raw' )
+		);
+	}
+
+	function testTableNameShared() {
+		$this->assertEquals(
+			$this->prefixAndQuote( 'tablename', 'sharedatabase', 'sh_' ),
+			$this->getSharedTableName( 'tablename', 'sharedatabase', 'sh_' )
+		);
+
+		$this->assertEquals(
+			$this->prefixAndQuote( 'tablename', 'sharedatabase', null ),
+			$this->getSharedTableName( 'tablename', 'sharedatabase', null )
+		);
+	}
+
+	function testTableNameRawShared() {
+		$this->assertEquals(
+			$this->prefixAndQuote( 'tablename', 'sharedatabase', 'sh_', 'raw' ),
+			$this->getSharedTableName( 'tablename', 'sharedatabase', 'sh_', 'raw' )
+		);
+
+		$this->assertEquals(
+			$this->prefixAndQuote( 'tablename', 'sharedatabase', null, 'raw' ),
+			$this->getSharedTableName( 'tablename', 'sharedatabase', null, 'raw' )
+		);
+	}
+
+	function testTableNameForeign() {
+		$this->assertEquals(
+			$this->prefixAndQuote( 'tablename', 'databasename', '' ),
+			$this->db->tableName( 'databasename.tablename' )
+		);
+	}
+
+	function testTableNameRawForeign() {
+		$this->assertEquals(
+			$this->prefixAndQuote( 'tablename', 'databasename', '', 'raw' ),
+			$this->db->tableName( 'databasename.tablename', 'raw' )
+		);
+	}
+
 	function testFillPreparedEmpty() {
 		$sql = $this->db->fillPrepared(
 			'SELECT * FROM interwiki', array() );

Reply to: