'AuthPluginUser' => 'includes/AuthPlugin.php',
'Autopromote' => 'includes/Autopromote.php',
'Block' => 'includes/Block.php',
+ 'BloomCache' => 'includes/cache/bloom/BloomCache.php',
+ 'BloomCacheRedis' => 'includes/cache/bloom/BloomCacheRedis.php',
+ 'BloomFilterTitleHasLogs' => 'includes/cache/bloom/BloomFilters.php',
+ 'CacheHelper' => 'includes/CacheHelper.php',
'Category' => 'includes/Category.php',
- 'Categoryfinder' => 'includes/Categoryfinder.php',
+ 'CategoryFinder' => 'includes/CategoryFinder.php',
'CategoryViewer' => 'includes/CategoryViewer.php',
'ChangeTags' => 'includes/ChangeTags.php',
'ChannelFeed' => 'includes/Feed.php',
'DumpOutput' => 'includes/Export.php',
'DumpPipeOutput' => 'includes/Export.php',
'EditPage' => 'includes/EditPage.php',
- 'EmailNotification' => 'includes/UserMailer.php',
+ 'EmptyBloomCache' => 'includes/cache/bloom/BloomCache.php',
'Fallback' => 'includes/Fallback.php',
'FauxRequest' => 'includes/WebRequest.php',
'FauxResponse' => 'includes/WebResponse.php',
'LinkFilter' => 'includes/LinkFilter.php',
'MagicWord' => 'includes/MagicWord.php',
'MagicWordArray' => 'includes/MagicWord.php',
- 'MailAddress' => 'includes/UserMailer.php',
'MediaWiki' => 'includes/MediaWiki.php',
'MediaWikiVersionFetcher' => 'includes/MediaWikiVersionFetcher.php',
'Message' => 'includes/Message.php',
'MessageBlobStore' => 'includes/MessageBlobStore.php',
'MimeMagic' => 'includes/MimeMagic.php',
+ 'MovePage' => 'includes/MovePage.php',
'MWHookException' => 'includes/Hooks.php',
'MWHttpRequest' => 'includes/HttpFunctions.php',
'MWNamespace' => 'includes/MWNamespace.php',
'User' => 'includes/User.php',
'UserArray' => 'includes/UserArray.php',
'UserArrayFromResult' => 'includes/UserArrayFromResult.php',
- 'UserMailer' => 'includes/UserMailer.php',
'UserRightsProxy' => 'includes/UserRightsProxy.php',
'WatchedItem' => 'includes/WatchedItem.php',
'WebRequest' => 'includes/WebRequest.php',
# includes/api
'ApiBase' => 'includes/api/ApiBase.php',
'ApiBlock' => 'includes/api/ApiBlock.php',
+ 'ApiClearHasMsg' => 'includes/api/ApiClearHasMsg.php',
'ApiComparePages' => 'includes/api/ApiComparePages.php',
'ApiCreateAccount' => 'includes/api/ApiCreateAccount.php',
'ApiDelete' => 'includes/api/ApiDelete.php',
'ApiQueryAllPages' => 'includes/api/ApiQueryAllPages.php',
'ApiQueryAllUsers' => 'includes/api/ApiQueryAllUsers.php',
'ApiQueryBacklinks' => 'includes/api/ApiQueryBacklinks.php',
+ 'ApiQueryBacklinksprop' => 'includes/api/ApiQueryBacklinksprop.php',
'ApiQueryBase' => 'includes/api/ApiQueryBase.php',
'ApiQueryBlocks' => 'includes/api/ApiQueryBlocks.php',
'ApiQueryCategories' => 'includes/api/ApiQueryCategories.php',
'ApiQueryRandom' => 'includes/api/ApiQueryRandom.php',
'ApiQueryRecentChanges' => 'includes/api/ApiQueryRecentChanges.php',
'ApiQueryFileRepoInfo' => 'includes/api/ApiQueryFileRepoInfo.php',
- 'ApiQueryRedirects' => 'includes/api/ApiQueryRedirects.php',
'ApiQueryRevisions' => 'includes/api/ApiQueryRevisions.php',
'ApiQuerySearch' => 'includes/api/ApiQuerySearch.php',
'ApiQuerySiteinfo' => 'includes/api/ApiQuerySiteinfo.php',
'HTMLFileCache' => 'includes/cache/HTMLFileCache.php',
'ICacheHelper' => 'includes/cache/CacheHelper.php',
'LCStore' => 'includes/cache/LocalisationCache.php',
- 'LCStoreAccel' => 'includes/cache/LocalisationCache.php',
'LCStoreCDB' => 'includes/cache/LocalisationCache.php',
'LCStoreDB' => 'includes/cache/LocalisationCache.php',
'LCStoreNull' => 'includes/cache/LocalisationCache.php',
'ConfigException' => 'includes/config/ConfigException.php',
'ConfigFactory' => 'includes/config/ConfigFactory.php',
'GlobalVarConfig' => 'includes/config/GlobalVarConfig.php',
+ 'HashConfig' => 'includes/config/HashConfig.php',
+ 'MultiConfig' => 'includes/config/MultiConfig.php',
+ 'MutableConfig' => 'includes/config/MutableConfig.php',
# includes/content
'AbstractContent' => 'includes/content/AbstractContent.php',
- 'ContentHandler' => 'includes/content/ContentHandler.php',
+ 'CodeContentHandler' => 'includes/content/CodeContentHandler.php',
'Content' => 'includes/content/Content.php',
- 'CssContentHandler' => 'includes/content/CssContentHandler.php',
+ 'ContentHandler' => 'includes/content/ContentHandler.php',
'CssContent' => 'includes/content/CssContent.php',
- 'JavaScriptContentHandler' => 'includes/content/JavaScriptContentHandler.php',
+ 'CssContentHandler' => 'includes/content/CssContentHandler.php',
'JavaScriptContent' => 'includes/content/JavaScriptContent.php',
- 'JSONContentHandler' => 'includes/content/JSONContentHandler.php',
- 'JSONContent' => 'includes/content/JSONContent.php',
+ 'JavaScriptContentHandler' => 'includes/content/JavaScriptContentHandler.php',
+ 'JsonContent' => 'includes/content/JsonContent.php',
+ 'JsonContentHandler' => 'includes/content/JsonContentHandler.php',
'MessageContent' => 'includes/content/MessageContent.php',
'MWContentSerializationException' => 'includes/content/ContentHandler.php',
- 'TextContentHandler' => 'includes/content/TextContentHandler.php',
'TextContent' => 'includes/content/TextContent.php',
- 'WikitextContentHandler' => 'includes/content/WikitextContentHandler.php',
+ 'TextContentHandler' => 'includes/content/TextContentHandler.php',
'WikitextContent' => 'includes/content/WikitextContent.php',
+ 'WikitextContentHandler' => 'includes/content/WikitextContentHandler.php',
# includes/context
'ContextSource' => 'includes/context/ContextSource.php',
'UploadFromUrlJob' => 'includes/jobqueue/jobs/UploadFromUrlJob.php',
'AssembleUploadChunksJob' => 'includes/jobqueue/jobs/AssembleUploadChunksJob.php',
'PublishStashedFileJob' => 'includes/jobqueue/jobs/PublishStashedFileJob.php',
+ 'ThumbnailRenderJob' => 'includes/jobqueue/jobs/ThumbnailRenderJob.php',
# includes/jobqueue/utils
'BacklinkJobUtils' => 'includes/jobqueue/utils/BacklinkJobUtils.php',
'PackedHoverImageGallery' => 'includes/gallery/PackedOverlayImageGallery.php',
'PackedOverlayImageGallery' => 'includes/gallery/PackedOverlayImageGallery.php',
+ # includes/mail
+ 'EmailNotification' => 'includes/mail/EmailNotification.php',
+ 'MailAddress' => 'includes/mail/MailAddress.php',
+ 'UserMailer' => 'includes/mail/UserMailer.php',
+
# includes/media
'BitmapHandler' => 'includes/media/Bitmap.php',
'BitmapHandler_ClientOnly' => 'includes/media/Bitmap_ClientOnly.php',
'SVGReader' => 'includes/media/SVGMetadataExtractor.php',
'ThumbnailImage' => 'includes/media/MediaTransformOutput.php',
'TiffHandler' => 'includes/media/Tiff.php',
+ 'TransformationalImageHandler' => 'includes/media/TransformationalImageHandler.php',
'TransformParameterError' => 'includes/media/MediaTransformOutput.php',
'XCFHandler' => 'includes/media/XCF.php',
'XMPInfo' => 'includes/media/XMPInfo.php',
'includes/resourceloader/DerivativeResourceLoaderContext.php',
'ResourceLoader' => 'includes/resourceloader/ResourceLoader.php',
'ResourceLoaderContext' => 'includes/resourceloader/ResourceLoaderContext.php',
+ 'ResourceLoaderEditToolbarModule' => 'includes/resourceloader/ResourceLoaderEditToolbarModule.php',
'ResourceLoaderFileModule' => 'includes/resourceloader/ResourceLoaderFileModule.php',
'ResourceLoaderFilePageModule' => 'includes/resourceloader/ResourceLoaderFilePageModule.php',
'ResourceLoaderFilePath' => 'includes/resourceloader/ResourceLoaderFilePath.php',
- 'ResourceLoaderLESSFunctions' => 'includes/resourceloader/ResourceLoaderLESSFunctions.php',
'ResourceLoaderModule' => 'includes/resourceloader/ResourceLoaderModule.php',
'ResourceLoaderNoscriptModule' => 'includes/resourceloader/ResourceLoaderNoscriptModule.php',
'ResourceLoaderSiteModule' => 'includes/resourceloader/ResourceLoaderSiteModule.php',
'SiteStore' => 'includes/site/SiteStore.php',
# includes/skins
- 'BaseTemplate' => 'includes/skins/SkinTemplate.php',
- 'MediaWikiI18N' => 'includes/skins/SkinTemplate.php',
- 'QuickTemplate' => 'includes/skins/SkinTemplate.php',
+ 'BaseTemplate' => 'includes/skins/BaseTemplate.php',
+ 'MediaWikiI18N' => 'includes/skins/MediaWikiI18N.php',
+ 'QuickTemplate' => 'includes/skins/QuickTemplate.php',
'Skin' => 'includes/skins/Skin.php',
+ 'SkinApi' => 'includes/skins/SkinApi.php',
+ 'SkinApiTemplate' => 'includes/skins/SkinApiTemplate.php',
'SkinException' => 'includes/skins/SkinException.php',
'SkinFactory' => 'includes/skins/SkinFactory.php',
'SkinFallback' => 'includes/skins/SkinFallback.php',
'LoginForm' => 'includes/specials/SpecialUserlogin.php',
'LonelyPagesPage' => 'includes/specials/SpecialLonelypages.php',
'LongPagesPage' => 'includes/specials/SpecialLongpages.php',
+ 'MediaStatisticsPage' => 'includes/specials/SpecialMediaStatistics.php',
'MergeHistoryPager' => 'includes/specials/SpecialMergeHistory.php',
'MIMEsearchPage' => 'includes/specials/SpecialMIMEsearch.php',
'MostcategoriesPage' => 'includes/specials/SpecialMostcategories.php',
* MediaWiki version number
* @since 1.2
*/
-$wgVersion = '1.24alpha';
+$wgVersion = '1.25alpha';
/**
* Name of the site. It must be changed in LocalSettings.php
/**
* The URL path of the wiki logo. The logo size should be 135x135 pixels.
- * Defaults to "{$wgStylePath}/common/images/wiki.png".
+ * Defaults to "$wgResourceBasePath/resources/assets/wiki.png".
*/
$wgLogo = false;
// dumb version, no syntax highlighting
CONTENT_MODEL_JAVASCRIPT => 'JavaScriptContentHandler',
// simple implementation, for use by extensions, etc.
- CONTENT_MODEL_JSON => 'JSONContentHandler',
+ CONTENT_MODEL_JSON => 'JsonContentHandler',
// dumb version, no syntax highlighting
CONTENT_MODEL_CSS => 'CssContentHandler',
// plain text, for use by extensions, etc.
* Sets an external MIME detector program. The command must print only
* the MIME type to standard output.
* The name of the file to process will be appended to the command given here.
- * If not set or NULL, mime_content_type will be used if available.
+ * If not set or NULL, PHP's fileinfo extension will be used if available.
*
* @par Example:
* @code
*/
$wgThumbnailMinimumBucketDistance = 50;
+ /**
+ * When defined, is an array of thumbnail widths to be rendered at upload time. The idea is to
+ * prerender common thumbnail sizes, in order to avoid the necessity to render them on demand, which
+ * has a performance impact for the first client to view a certain size.
+ *
+ * This obviously means that more disk space is needed per upload upfront.
+ *
+ * @since 1.24
+ */
+
+ $wgUploadThumbnailRenderMap = array();
+
+ /**
+ * The method through which the thumbnails will be prerendered for the entries in
+ * $wgUploadThumbnailRenderMap
+ *
+ * The method can be either "http" or "jobqueue". The former uses an http request to hit the
+ * thumbnail's URL.
+ * This method only works if thumbnails are configured to be rendered by a 404 handler. The latter
+ * option uses the job queue to render the thumbnail.
+ *
+ * @since 1.24
+ */
+ $wgUploadThumbnailRenderMethod = 'jobqueue';
+
+ /**
+ * When using the "http" wgUploadThumbnailRenderMethod, lets one specify a custom Host HTTP header.
+ *
+ * @since 1.24
+ */
+ $wgUploadThumbnailRenderHttpCustomHost = false;
+
+ /**
+ * When using the "http" wgUploadThumbnailRenderMethod, lets one specify a custom domain to send the
+ * HTTP request to.
+ *
+ * @since 1.24
+ */
+ $wgUploadThumbnailRenderHttpCustomDomain = false;
+
/**
* Default parameters for the "<gallery>" tag
*/
'hash' => array( 'class' => 'HashBagOStuff' ),
);
+/**
+ * Map of bloom filter store names to configuration arrays.
+ *
+ * Example:
+ * $wgBloomFilterStores['main'] = array(
+ * 'cacheId' => 'main-v1',
+ * 'class' => 'BloomCacheRedis',
+ * 'redisServers' => array( '127.0.0.1:6379' ),
+ * 'redisConfig' => array( 'connectTimeout' => 2 )
+ * );
+ *
+ * A primary bloom filter must be created manually.
+ * Example in eval.php:
+ * <code>
+ * BloomCache::get( 'main' )->init( 'shared', 1000000000, .001 );
+ * </code>
+ * The size should be as large as practical given wiki size and resources.
+ *
+ * @since 1.24
+ */
+$wgBloomFilterStores = array();
+
/**
* The expiry time for the parser cache, in seconds.
* The default is 86400 (one day).
),
"poweredby" => array(
"mediawiki" => array(
- "src" => null, // Defaults to "$wgStylePath/common/images/poweredby_mediawiki_88x31.png"
+ "src" => null, // Defaults to "$wgResourceBasePath/resources/assets/poweredby_mediawiki_88x31.png"
"url" => "//www.mediawiki.org/",
"alt" => "Powered by MediaWiki",
)
*
* @par Example:
* @code
- * $wgResourceLoaderSources['foo'] = array(
- * 'loadScript' => 'http://example.org/w/load.php',
- * 'apiScript' => 'http://example.org/w/api.php'
- * );
+ * $wgResourceLoaderSources['foo'] = 'http://example.org/w/load.php';
* @endcode
*/
$wgResourceLoaderSources = array();
* Changes to LESS functions do not trigger cache invalidation.
*
* @since 1.22
+ * @deprecated since 1.24 Questionable usefulness and problematic to support,
+ * will be removed in the future.
*/
-$wgResourceLoaderLESSFunctions = array(
- 'embeddable' => 'ResourceLoaderLESSFunctions::embeddable',
- 'embed' => 'ResourceLoaderLESSFunctions::embed',
-);
+$wgResourceLoaderLESSFunctions = array();
/**
* Default import paths for LESS modules. LESS files referenced in @import
/**
* URL schemes that should be recognized as valid by wfParseUrl().
+ *
+ * WARNING: Do not add 'file:' to this or internal file links will be broken.
+ * Instead, if you want to support file links, add 'file://'. The same applies
+ * to any other protocols with the same name as a namespace. See bug #44011 for
+ * more information.
+ *
* @see wfParseUrl
*/
$wgUrlProtocols = array(
*
* @par Advanced example:
* @code
- * $wgDebugLogGroups['memcached'] = (
+ * $wgDebugLogGroups['memcached'] = array(
* 'destination' => '/var/log/mediawiki/memcached.log',
* 'sample' => 1000, // log 1 message out of every 1,000.
* );
$wgValidSkinNames = array();
/**
- * Special page list.
- * See the top of SpecialPage.php for documentation.
+ * Special page list. This is an associative array mapping the (canonical) names of
+ * special pages to either a class name to be instantiated, or a callback to use for
+ * creating the special page object. In both cases, the result must be an instance of
+ * SpecialPage.
*/
$wgSpecialPages = array();
'uploadFromUrl' => 'UploadFromUrlJob',
'AssembleUploadChunks' => 'AssembleUploadChunksJob',
'PublishStashedFile' => 'PublishStashedFileJob',
+ 'ThumbnailRender' => 'ThumbnailRenderJob',
'null' => 'NullJob'
);
);
}
wfRunHooks( 'UploadComplete', array( &$this ) );
+
+ $this->postProcessUpload();
}
wfProfileOut( __METHOD__ );
return $status;
}
+ /**
+ * Perform extra steps after a successful upload.
+ */
+ public function postProcessUpload() {
+ global $wgUploadThumbnailRenderMap;
+
+ $jobs = array();
+
+ $sizes = $wgUploadThumbnailRenderMap;
+ rsort( $sizes );
+
+ foreach ( $sizes as $size ) {
+ $jobs []= new ThumbnailRenderJob( $this->getLocalFile()->getTitle(), array(
+ 'transformParams' => array( 'width' => $size ),
+ ) );
+ }
+
+ JobQueueGroup::singleton()->push( $jobs );
+ }
+
/**
* Returns the title of the file to be uploaded. Sets mTitleError in case
* the name was illegal.
* @param array $attribs
* @return bool
*/
- public function checkSvgScriptCallback( $element, $attribs ) {
+ public function checkSvgScriptCallback( $element, $attribs, $data = null ) {
+
list( $namespace, $strippedElement ) = $this->splitXmlNamespace( $element );
// We specifically don't include:
return true;
}
+ # Check <style> css
+ if ( $strippedElement == 'style'
+ && self::checkCssFragment( Sanitizer::normalizeCss( $data ) )
+ ) {
+ wfDebug( __METHOD__ . ": hostile css in style element.\n" );
+ return true;
+ }
+
foreach ( $attribs as $attrib => $value ) {
$stripped = $this->stripXmlNamespace( $attrib );
$value = strtolower( $value );
return true;
}
+ # Change href with animate from (http://html5sec.org/#137). This doesn't seem
+ # possible without embedding the svg, but filter here in case.
+ if ( $stripped == 'from'
+ && $strippedElement === 'animate'
+ && !preg_match( '!^https?://!im', $value )
+ ) {
+ wfDebug( __METHOD__ . ": Found animate that might be changing href using from "
+ . "\"<$strippedElement '$attrib'='$value'...\" in uploaded file.\n" );
+
+ return true;
+ }
+
# use set/animate to add event-handler attribute to parent
if ( ( $strippedElement == 'set' || $strippedElement == 'animate' )
&& $stripped == 'attributename'
}
# use CSS styles to bring in remote code
- # catch url("http:..., url('http:..., url(http:..., but not url("#..., url('#..., url(#....
- $tagsList = "font|clip-path|fill|filter|marker|marker-end|marker-mid|marker-start|mask|stroke";
if ( $stripped == 'style'
- && preg_match_all(
- '!((?:' . $tagsList . ')\s*:\s*url\s*\(\s*["\']?\s*[^#]+.*?\))!sim',
- $value,
- $matches
- )
+ && self::checkCssFragment( Sanitizer::normalizeCss( $value ) )
) {
- foreach ( $matches[1] as $match ) {
- if ( !preg_match( '!(?:' . $tagsList . ')\s*:\s*url\s*\(\s*(#|\'#|"#)!sim', $match ) ) {
- wfDebug( __METHOD__ . ": Found svg setting a style with "
- . "remote url '$attrib'='$value' in uploaded file.\n" );
+ wfDebug( __METHOD__ . ": Found svg setting a style with "
+ . "remote url '$attrib'='$value' in uploaded file.\n" );
+ return true;
+ }
- return true;
- }
- }
+ # Several attributes can include css, css character escaping isn't allowed
+ $cssAttrs = array( 'font', 'clip-path', 'fill', 'filter', 'marker',
+ 'marker-end', 'marker-mid', 'marker-start', 'mask', 'stroke' );
+ if ( in_array( $stripped, $cssAttrs )
+ && self::checkCssFragment( $value )
+ ) {
+ wfDebug( __METHOD__ . ": Found svg setting a style with "
+ . "remote url '$attrib'='$value' in uploaded file.\n" );
+ return true;
}
# image filters can pull in url, which could be svg that executes scripts
return false; //No scripts detected
}
+ /**
+ * Check a block of CSS or CSS fragment for anything that looks like
+ * it is bringing in remote code.
+ * @param string $value a string of CSS
+ * @param bool $propOnly only check css properties (start regex with :)
+ * @return bool true if the CSS contains an illegal string, false if otherwise
+ */
+ private static function checkCssFragment( $value ) {
+
+ # Forbid external stylesheets, for both reliability and to protect viewer's privacy
+ if ( strpos( $value, '@import' ) !== false ) {
+ return true;
+ }
+
+ # We allow @font-face to embed fonts with data: urls, so we snip the string
+ # 'url' out so this case won't match when we check for urls below
+ $pattern = '!(@font-face\s*{[^}]*src:)url(\("data:;base64,)!im';
+ $value = preg_replace( $pattern, '$1$2', $value );
+
+ # Check for remote and executable CSS. Unlike in Sanitizer::checkCss, the CSS
+ # properties filter and accelerator don't seem to be useful for xss in SVG files.
+ # Expression and -o-link don't seem to work either, but filtering them here in case.
+ # Additionally, we catch remote urls like url("http:..., url('http:..., url(http:...,
+ # but not local ones such as url("#..., url('#..., url(#....
+ if ( preg_match( '!expression
+ | -o-link\s*:
+ | -o-link-source\s*:
+ | -o-replace\s*:!imx', $value ) ) {
+ return true;
+ }
+
+ if ( preg_match_all(
+ "!(\s*(url|image|image-set)\s*\(\s*[\"']?\s*[^#]+.*?\))!sim",
+ $value,
+ $matches
+ ) !== 0
+ ) {
+ # TODO: redo this in one regex. Until then, url("#whatever") matches the first
+ foreach ( $matches[1] as $match ) {
+ if ( !preg_match( "!\s*(url|image|image-set)\s*\(\s*(#|'#|\"#)!im", $match ) ) {
+ return true;
+ }
+ }
+ }
+
+ if ( preg_match( '/[\000-\010\013\016-\037\177]/', $value ) ) {
+ return true;
+ }
+
+ return false;
+ }
+
/**
* Divide the element name passed by the xml parser to the callback into URI and prifix.
* @param string $element