use MediaWiki\MediaWikiServices;
use Wikimedia\ScopedCallback;
use MediaWiki\Logger\LoggerFactory;
+use Wikimedia\Rdbms\Database;
/**
* MediaWiki message cache structure version.
// either.
$po = ParserOptions::newFromAnon();
$po->setEditSection( false );
+ $po->setAllowUnsafeRawHtml( false );
+ $po->setWrapOutputClass( false );
return $po;
}
$this->mParserOptions = new ParserOptions;
$this->mParserOptions->setEditSection( false );
+ // Messages may take parameters that could come
+ // from malicious sources. As a precaution, disable
+ // the <html> parser tag when parsing messages.
+ $this->mParserOptions->setAllowUnsafeRawHtml( false );
+ // Wrapping messages in an extra <div> is probably not expected. If
+ // they're outside the content area they probably shouldn't be
+ // targeted by CSS that's targeting the parser output, and if
+ // they're inside they already are from the outer div.
+ $this->mParserOptions->setWrapOutputClass( false );
}
return $this->mParserOptions;
} else {
# Effectively disallows use of '/' character in NS_MEDIAWIKI for uses
# other than language code.
- $conds[] = 'page_title NOT' . $dbr->buildLike( $dbr->anyString(), '/', $dbr->anyString() );
+ $conds[] = 'page_title NOT' .
+ $dbr->buildLike( $dbr->anyString(), '/', $dbr->anyString() );
}
# Conditions to fetch oversized pages to ignore them
$res = $dbr->select(
[ 'page', 'revision', 'text' ],
- [ 'page_title', 'old_text', 'old_flags' ],
+ [ 'page_title', 'old_id', 'old_text', 'old_flags' ],
$smallConds,
__METHOD__ . "($code)-small"
);
/**
* Updates cache as necessary when message page is changed
*
- * @param string $title Message cache key with initial uppercase letter.
+ * @param string $title Message cache key with initial uppercase letter
* @param string|bool $text New contents of the page (false if deleted)
*/
public function replace( $title, $text ) {
return;
}
// Load the messages from the master DB to avoid race conditions
- $this->loadFromDB( $code, self::FOR_UPDATE );
+ $cache = $this->loadFromDB( $code, self::FOR_UPDATE );
+ $this->mCache[$code] = $cache;
// Load the process cache values and set the per-title cache keys
$page = WikiPage::factory( Title::makeTitle( NS_MEDIAWIKI, $title ) );
$page->loadPageData( $page::READ_LATEST );
$text = $this->getMessageTextFromContent( $page->getContent() );
// Check if an individual cache key should exist and update cache accordingly
- $titleKey = $this->wanCache->makeKey(
- 'messages-big', $this->mCache[$code]['HASH'], $title );
if ( is_string( $text ) && strlen( $text ) > $wgMaxMsgCacheEntrySize ) {
+ $titleKey = $this->bigMessageCacheKey( $this->mCache[$code]['HASH'], $title );
$this->wanCache->set( $titleKey, ' ' . $text, $this->mExpiry );
}
// Mark this cache as definitely being "latest" (non-volatile) so
* some callers require this behavior. LanguageConverter::parseCachedTable()
* and self::get() are some examples in core.
*
- * @param string $title Message cache key with initial uppercase letter.
- * @param string $code Code denoting the language to try.
+ * @param string $title Message cache key with initial uppercase letter
+ * @param string $code Code denoting the language to try
* @return string|bool The message, or false if it does not exist or on error
*/
public function getMsgFromNamespace( $title, $code ) {
return false;
}
- // Try the individual message cache
- $titleKey = $this->wanCache->makeKey( 'messages-big', $this->mCache[$code]['HASH'], $title );
+ // Individual message cache key
+ $titleKey = $this->bigMessageCacheKey( $this->mCache[$code]['HASH'], $title );
if ( $this->mCacheVolatile[$code] ) {
$entry = false;
__METHOD__ . ': loading volatile key \'{titleKey}\'',
[ 'titleKey' => $titleKey, 'code' => $code ] );
} else {
+ // Try the individual message cache
$entry = $this->wanCache->get( $titleKey );
}
$message = false; // negative caching
}
- if ( $message === false ) { // negative caching
+ if ( $message === false ) {
+ // Negative caching in case a "too big" message is no longer available (deleted)
$this->mCache[$code][$title] = '!NONEXISTENT';
$this->wanCache->set( $titleKey, '!NONEXISTENT', $this->mExpiry, $cacheOpts );
}
return $msgText;
}
+
+ /**
+ * @param string $hash Hash for this version of the entire key/value overrides map
+ * @param string $title Message cache key with initial uppercase letter
+ * @return string
+ */
+ private function bigMessageCacheKey( $hash, $title ) {
+ return $this->wanCache->makeKey( 'messages-big', $hash, $title );
+ }
}