Fo0bar has submitted this change and it was merged. Change subject: Convert to 1.25+ extension.json ......................................................................
Convert to 1.25+ extension.json Backwards compatible with 1.23. Change-Id: I15a312662917ddb9c9743fd129e3737f4973cfd6 --- M README A SecureHTML.hooks.php D SecureHTML.i18n.php M SecureHTML.php A extension.json 5 files changed, 124 insertions(+), 115 deletions(-) Approvals: Fo0bar: Verified; Looks good to me, approved jenkins-bot: Checked diff --git a/README b/README index d8ac7d2..3296c90 100644 --- a/README +++ b/README @@ -1,5 +1,5 @@ Secure HTML -Copyright (C) 2012 Ryan Finnie +Copyright (C) 2012-2016 Ryan Finnie Lets you include arbitrary HTML in an authorized and secure way http://www.mediawiki.org/wiki/Extension:Secure_HTML diff --git a/SecureHTML.hooks.php b/SecureHTML.hooks.php new file mode 100644 index 0000000..762e383 --- /dev/null +++ b/SecureHTML.hooks.php @@ -0,0 +1,62 @@ +<?php +class SecureHTML { + + static function parserInit( $parser ) { + global $wgSecureHTMLTag; + $parser->setHook( $wgSecureHTMLTag, array( __CLASS__, 'secureHTMLRender' ) ); + } + + function secureHTMLRender( $input, $argv, $parser, $frame ) { + global $wgSecureHTMLSecrets; + + # The hash attribute is required. + if ( !isset( $argv['hash'] ) ) { + return( Html::rawElement( 'div', array( 'class' => 'error' ), wfMessage( 'securehtml-hashrequired' ) ) ); + } + + # If the array is empty, there is no possible way this will work. + if ( count( $wgSecureHTMLSecrets ) === 0 ) { + return( Html::rawElement( 'div', array( 'class' => 'error' ), wfMessage( 'securehtml-nokeys' ) ) ); + } + + # Get a list of key names. + $keynames = array_keys( $wgSecureHTMLSecrets ); + + # If the desired key name is not available, assume the first one. + $keyname = ( isset( $argv['keyname'] ) ? $argv['keyname'] : $keynames[0] ); + + # Key secret configuration. + $keyalgorithm = 'sha256'; + if ( !array_key_exists( $keyname, $wgSecureHTMLSecrets ) ) { + # To avoid leaking the existence of a key name by unauthorized users, + # perform a dummy HMAC SHA256 (mitigate timing attacks), then + # respond with "invalid hash", instead of something like "invalid key + # name". + $testhash = hash_hmac( 'sha256', $input, '' ); + return( Html::rawElement( 'div', array( 'class' => 'error' ), wfMessage( 'securehtml-invalidhash' ) ) ); + } + if ( is_array( $wgSecureHTMLSecrets[$keyname] ) ) { + if ( array_key_exists( 'secret', $wgSecureHTMLSecrets[$keyname] ) ) { + $keysecret = $wgSecureHTMLSecrets[$keyname]['secret']; + } else { + return( Html::rawElement( 'div', array( 'class' => 'error' ), wfMessage( 'securehtml-invalidhash' ) ) ); + } + if ( array_key_exists( 'algorithm', $wgSecureHTMLSecrets[$keyname] ) ) { + $keyalgorithm = $wgSecureHTMLSecrets[$keyname]['algorithm']; + } + } else { + $keysecret = $wgSecureHTMLSecrets[$keyname]; + } + + # Compute a test hash. + $testhash = hash_hmac( $keyalgorithm, $input, $keysecret ); + + # If the test hash matches the supplied hash, return the raw HTML. Otherwise, error. + if ( $testhash === $argv['hash'] ) { + return( array( $input, 'markerType' => 'nowiki' ) ); + } else { + return( Html::rawElement( 'div', array( 'class' => 'error' ), wfMessage( 'securehtml-invalidhash' ) ) ); + } + } + +} diff --git a/SecureHTML.i18n.php b/SecureHTML.i18n.php deleted file mode 100644 index 7d6faac..0000000 --- a/SecureHTML.i18n.php +++ /dev/null @@ -1,35 +0,0 @@ -<?php -/** - * This is a backwards-compatibility shim, generated by: - * https://git.wikimedia.org/blob/mediawiki%2Fcore.git/HEAD/maintenance%2FgenerateJsonI18n.php - * - * Beginning with MediaWiki 1.23, translation strings are stored in json files, - * and the EXTENSION.i18n.php file only exists to provide compatibility with - * older releases of MediaWiki. For more information about this migration, see: - * https://www.mediawiki.org/wiki/Requests_for_comment/Localisation_format - * - * This shim maintains compatibility back to MediaWiki 1.17. - */ -$messages = array(); -if ( !function_exists( 'wfJsonI18nShim2c9b1ded6737f38f' ) ) { - function wfJsonI18nShim2c9b1ded6737f38f( $cache, $code, &$cachedData ) { - $codeSequence = array_merge( array( $code ), $cachedData['fallbackSequence'] ); - foreach ( $codeSequence as $csCode ) { - $fileName = dirname( __FILE__ ) . "/i18n/$csCode.json"; - if ( is_readable( $fileName ) ) { - $data = FormatJson::decode( file_get_contents( $fileName ), true ); - foreach ( array_keys( $data ) as $key ) { - if ( $key === '' || $key[0] === '@' ) { - unset( $data[$key] ); - } - } - $cachedData['messages'] = array_merge( $data, $cachedData['messages'] ); - } - - $cachedData['deps'][] = new FileDependency( $fileName ); - } - return true; - } - - $GLOBALS['wgHooks']['LocalisationCacheRecache'][] = 'wfJsonI18nShim2c9b1ded6737f38f'; -} diff --git a/SecureHTML.php b/SecureHTML.php index c043b0c..a893de6 100644 --- a/SecureHTML.php +++ b/SecureHTML.php @@ -24,22 +24,29 @@ * http://www.gnu.org/copyleft/gpl.html */ -# Not a valid entry point, skip unless MEDIAWIKI is defined -if ( !defined( 'MEDIAWIKI' ) ) { - echo <<<EOT -To install my extension, put the following line in LocalSettings.php: -require_once( "$IP/extensions/SecureHTML/SecureHTML.php" ); -EOT; - exit( 1 ); +if ( function_exists( 'wfLoadExtension' ) ) { + wfLoadExtension( 'SecureHTML' ); + // Keep i18n globals so mergeMessageFileList.php doesn't break + $wgMessagesDirs['SecureHTML'] = __DIR__ . '/i18n'; + $wgExtensionMessagesFiles['SecureHTMLAlias'] = __DIR__ . '/SecureHTML.alias.php'; + wfWarn( + 'Deprecated PHP entry point used for SecureHTML extension. ' . + 'Please use wfLoadExtension instead, ' . + 'see https://www.mediawiki.org/wiki/Extension_registration for more details.' + ); + return; } -$wgExtensionCredits['parserhook'][] = $wgExtensionCredits['specialpage'][] = array( +$extensionJsonFilename = dirname( __FILE__ ) . '/extension.json'; +$extensionJsonData = FormatJson::decode( file_get_contents( $extensionJsonFilename ), true ); +$wgExtensionCredits[$extensionJsonData['type']][] = array( 'path' => __FILE__, - 'name' => 'Secure HTML', - 'author' => 'Ryan Finnie', - 'url' => 'https://www.mediawiki.org/wiki/Extension:Secure_HTML', - 'descriptionmsg' => 'securehtml-desc', - 'version' => '2.4.1', + 'name' => $extensionJsonData['name'], + 'author' => $extensionJsonData['author'], + 'url' => $extensionJsonData['url'], + 'descriptionmsg' => $extensionJsonData['descriptionmsg'], + 'version' => $extensionJsonData['version'], + 'license-name' => $extensionJsonData['license-name'], ); # Default configuration globals @@ -56,76 +63,14 @@ $wgSecureHTMLTag = 'shtml'; } -$dir = dirname( __FILE__ ) . '/'; - # Define Special page -$wgAutoloadClasses['SpecialSecureHTML'] = $dir . 'SpecialSecureHTML.php'; +$wgAutoloadClasses['SpecialSecureHTML'] = __DIR__ . '/SpecialSecureHTML.php'; $wgSpecialPages['SecureHTML'] = 'SpecialSecureHTML'; # Define internationalizations $wgMessagesDirs['SecureHTML'] = __DIR__ . '/i18n'; -$wgExtensionMessagesFiles['SecureHTML'] = $dir . 'SecureHTML.i18n.php'; -$wgExtensionMessagesFiles['SecureHTMLAlias'] = $dir . 'SecureHTML.alias.php'; +$wgExtensionMessagesFiles['SecureHTMLAlias'] = __DIR__ . '/SecureHTML.alias.php'; # Define extension hooks -$wgExtensionFunctions[] = "secureHTMLSetup"; - -function secureHTMLSetup() { - global $wgParser; - global $wgSecureHTMLTag; - $wgParser->setHook( $wgSecureHTMLTag, "secureHTMLRender" ); -} - -function secureHTMLRender( $input, $argv ) { - global $wgSecureHTMLSecrets; - - # The hash attribute is required. - if ( !isset( $argv['hash'] ) ) { - return( Html::rawElement( 'div', array( 'class' => 'error' ), wfMessage( 'securehtml-hashrequired' ) ) ); - } - - # If the array is empty, there is no possible way this will work. - if ( count( $wgSecureHTMLSecrets ) === 0 ) { - return( Html::rawElement( 'div', array( 'class' => 'error' ), wfMessage( 'securehtml-nokeys' ) ) ); - } - - # Get a list of key names. - $keynames = array_keys( $wgSecureHTMLSecrets ); - - # If the desired key name is not available, assume the first one. - $keyname = ( isset( $argv['keyname'] ) ? $argv['keyname'] : $keynames[0] ); - - # Key secret configuration. - $keyalgorithm = 'sha256'; - if ( !array_key_exists( $keyname, $wgSecureHTMLSecrets ) ) { - # To avoid leaking the existence of a key name by unauthorized users, - # perform a dummy HMAC SHA256 (mitigate timing attacks), then - # respond with "invalid hash", instead of something like "invalid key - # name". - $testhash = hash_hmac( 'sha256', $input, '' ); - return( Html::rawElement( 'div', array( 'class' => 'error' ), wfMessage( 'securehtml-invalidhash' ) ) ); - } - if ( is_array( $wgSecureHTMLSecrets[$keyname] ) ) { - if ( array_key_exists( 'secret', $wgSecureHTMLSecrets[$keyname] ) ) { - $keysecret = $wgSecureHTMLSecrets[$keyname]['secret']; - } else { - return( Html::rawElement( 'div', array( 'class' => 'error' ), wfMessage( 'securehtml-invalidhash' ) ) ); - } - if ( array_key_exists( 'algorithm', $wgSecureHTMLSecrets[$keyname] ) ) { - $keyalgorithm = $wgSecureHTMLSecrets[$keyname]['algorithm']; - } - } else { - $keysecret = $wgSecureHTMLSecrets[$keyname]; - } - - # Compute a test hash. - $testhash = hash_hmac( $keyalgorithm, $input, $keysecret ); - - # If the test hash matches the supplied hash, return the raw HTML. Otherwise, error. - if ( $testhash === $argv['hash'] ) { - return( array( $input, 'markerType' => 'nowiki' ) ); - } else { - return( Html::rawElement( 'div', array( 'class' => 'error' ), wfMessage( 'securehtml-invalidhash' ) ) ); - } - -} +$wgAutoloadClasses['SecureHTML'] = __DIR__ . '/SecureHTML.hooks.php'; +$wgHooks['ParserFirstCallInit'][] = 'SecureHTML::parserInit'; diff --git a/extension.json b/extension.json new file mode 100644 index 0000000..27cac32 --- /dev/null +++ b/extension.json @@ -0,0 +1,37 @@ +{ + "name": "Secure HTML", + "version": "2.4.1", + "author": "Ryan Finnie", + "url": "https://www.mediawiki.org/wiki/Extension:Secure_HTML", + "descriptionmsg": "securehtml-desc", + "type": "parserhook", + "license-name": "GPL-2.0+", + "SpecialPages": { + "SecureHTML": "SpecialSecureHTML" + }, + "MessagesDirs": { + "SecureHTML": [ + "i18n" + ] + }, + "ExtensionMessagesFiles": { + "SecureHTMLAlias": "SecureHTML.alias.php" + }, + "AutoloadClasses": { + "SpecialSecureHTML": "SpecialSecureHTML.php", + "SecureHTML": "SecureHTML.hooks.php" + }, + "Hooks": { + "ParserFirstCallInit": "SecureHTML::parserInit" + }, + "config": { + "SecureHTMLSecrets": {}, + "SecureHTMLSpecialRight": "edit", + "SecureHTMLSpecialDropdown": true, + "SecureHTMLTag": "shtml" + }, + "requires": { + "MediaWiki": ">= 1.23.0" + }, + "manifest_version": 1 +} -- To view, visit https://gerrit.wikimedia.org/r/300803 To unsubscribe, visit https://gerrit.wikimedia.org/r/settings Gerrit-MessageType: merged Gerrit-Change-Id: I15a312662917ddb9c9743fd129e3737f4973cfd6 Gerrit-PatchSet: 1 Gerrit-Project: mediawiki/extensions/SecureHTML Gerrit-Branch: master Gerrit-Owner: Fo0bar <r...@finnie.org> Gerrit-Reviewer: Fo0bar <r...@finnie.org> Gerrit-Reviewer: jenkins-bot <> _______________________________________________ MediaWiki-commits mailing list MediaWiki-commits@lists.wikimedia.org https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits