diff --git a/extension.json b/extension.json index 4c6a1fdac..042e0bd14 100644 --- a/extension.json +++ b/extension.json @@ -58,6 +58,16 @@ "CaptchaAuthenticationRequest": "includes/auth/CaptchaAuthenticationRequest.php" }, "callback": "ConfirmEditHooks::onRegistration", + "ResourceModules": { + "ext.confirmEdit.editPreview.ipwhitelist.styles": { + "position": "top", + "styles": "ext.confirmEdit.editPreview.ipwhitelist.styles.css" + } + }, + "ResourceFileModulePaths": { + "localBasePath": "resources", + "remoteExtPath": "ConfirmEdit/resources" + }, "Hooks": { "EditPageBeforeEditButtons": "ConfirmEditHooks::confirmEditPage", "EmailUserForm": "ConfirmEditHooks::injectEmailUser", @@ -67,7 +77,8 @@ "EditFilterMergedContent": "ConfirmEditHooks::confirmEditMerged", "APIGetAllowedParams": "ConfirmEditHooks::APIGetAllowedParams", "APIGetParamDescription": "ConfirmEditHooks::APIGetParamDescription", - "TitleReadWhitelist": "ConfirmEditHooks::onTitleReadWhitelist" + "TitleReadWhitelist": "ConfirmEditHooks::onTitleReadWhitelist", + "AlternateEditPreview": "ConfirmEditHooks::onAlternateEditPreview" }, "config": { "_prefix": "", diff --git a/i18n/en.json b/i18n/en.json index 605ae2767..99018dee3 100644 --- a/i18n/en.json +++ b/i18n/en.json @@ -26,5 +26,11 @@ "captcha-addurl-whitelist": " #
\n# Syntax is as follows:\n# * Everything from a \"#\" character to the end of the line is a comment\n# * Every non-blank line is a regex fragment which will only match hosts inside URLs\n #", "right-skipcaptcha": "Perform CAPTCHA-triggering actions without having to go through the CAPTCHA", "captcha-apihelp-param-captchaword": "Answer to the CAPTCHA", - "captcha-apihelp-param-captchaid": "CAPTCHA ID from previous request" + "captcha-apihelp-param-captchaid": "CAPTCHA ID from previous request", + "confirmedit-preview-line": "Line number", + "confirmedit-preview-content": "Content", + "confirmedit-preview-validity": "Validity", + "confirmedit-preview-valid": "valid", + "confirmedit-preview-invalid": "invalid", + "confirmedit-preview-description": "The following table shows the list of lines on this page and whether it's a valid IP address or IP address range. If the line is a valid IP address or IP address range, it will be whitelisted from CAPTCHA but invalid lines will be ignored. An example of a valid IP address range would be: 69.208.0.0/16 which goes from 69.208.0.0 to 69.208.255.255. [https://www.mediawiki.org/wiki/Special:MyLanguage/Help:Range_blocks#Calculating_the_CIDR_suffix More information] about calculating an IP address range." } diff --git a/i18n/qqq.json b/i18n/qqq.json index 8ad7a9b56..819523404 100644 --- a/i18n/qqq.json +++ b/i18n/qqq.json @@ -38,5 +38,11 @@ "captcha-addurl-whitelist": "See also: [[MediaWiki:Spam-blacklist]] and [[MediaWiki:Spam-whitelist]].\n\nLeave all the wiki markup, including the spaces, as is.\nYou can translate the text, including 'Leave this line exactly as it is'.\nThe first line of this messages has one (1) leading space.\n\n\"regex\" stands for \"regular expression\".", "right-skipcaptcha": "{{doc-right|skipcaptcha}}", "captcha-apihelp-param-captchaword": "{{doc-apihelp-param|description=the \"captchaword\" parameter added by [[mw:Extension:ConfirmEdit]]|noseealso=1}}\nSee also {{msg-mw|captcha-apihelp-param-captchaid}}", - "captcha-apihelp-param-captchaid": "{{doc-apihelp-param|description=the \"captchaid\" parameter added by [[mw:Extension:ConfirmEdit]]|noseealso=1}}\nSee also {{msg-mw|captcha-apihelp-param-captchaword}}" + "captcha-apihelp-param-captchaid": "{{doc-apihelp-param|description=the \"captchaid\" parameter added by [[mw:Extension:ConfirmEdit]]|noseealso=1}}\nSee also {{msg-mw|captcha-apihelp-param-captchaword}}", + "confirmedit-preview-line": "Used as a table heading for the edit preview of [[MediaWiki:Captcha-ip-whitelist]] to indicate the line number (1, 2, 3, ...).", + "confirmedit-preview-content": "Used as a table heading for the edit preview of [[MediaWiki:Captcha-ip-whitelist]] to indicate the content of a line.", + "confirmedit-preview-validity": "Used as a table heading for the edit preview of [[MediaWiki:Captcha-ip-whitelist]] to indicate the validity of a content of a line (if it's an IP address or not).", + "confirmedit-preview-valid": "Used to indicate a valid IP address in the edit preview of [[MediaWiki:Captcha-ip-whitelist]].", + "confirmedit-preview-invalid": "Used to indicate an invalid IP address in the edit preview of [[MediaWiki:Captcha-ip-whitelist]].", + "confirmedit-preview-description": "Explains the edit preview of [[MediaWiki:Captcha-ip-whitelist]]." } diff --git a/includes/ConfirmEditHooks.php b/includes/ConfirmEditHooks.php index ebff507dd..80e25d227 100644 --- a/includes/ConfirmEditHooks.php +++ b/includes/ConfirmEditHooks.php @@ -211,4 +211,85 @@ class ConfirmEditHooks { htmlentities( recaptcha_get_signup_url( $wgServerName, "mediawiki" ) ) . "'>here." ); } } + + /** + * AlternateEditPreview hook handler. + * + * Replaces the preview with a check of all lines for the [[MediaWiki:Captcha-ip-whitelist]] + * interface message, if it validates as an IP address. + * + * @param EditPage $editor + * @param Content &$content + * @param string &$html + * @param ParserOutput &$po + * @return bool + */ + public static function onAlternateEditPreview( EditPage $editor, &$content, &$html, &$po ) { + $title = $editor->getTitle(); + $exceptionTitle = Title::makeTitle( NS_MEDIAWIKI, 'Captcha-ip-whitelist' ); + + if ( !$title->equals( $exceptionTitle ) ) { + return true; + } + + $ctx = $editor->getArticle()->getContext(); + $out = $ctx->getOutput(); + $lang = $ctx->getLanguage(); + + $lines = explode( "\n", $content->getNativeData() ); + $html .= Html::rawElement( + 'div', + [ 'class' => 'warningbox' ], + $ctx->msg( 'confirmedit-preview-description' )->parse() + ) . + Html::openElement( + 'table', + [ 'class' => 'wikitable sortable' ] + ) . + Html::openElement( 'thead' ) . + Html::element( 'th', [], $ctx->msg( 'confirmedit-preview-line' )->text() ) . + Html::element( 'th', [], $ctx->msg( 'confirmedit-preview-content' )->text() ) . + Html::element( 'th', [], $ctx->msg( 'confirmedit-preview-validity' )->text() ) . + Html::closeElement( 'thead' ); + + foreach ( $lines as $count => $line ) { + $ip = trim( $line ); + if ( $ip === '' || strpos( $ip, '#' ) !== false ) { + continue; + } + if ( IP::isIPAddress( $ip ) ) { + $validity = $ctx->msg( 'confirmedit-preview-valid' )->escaped(); + $css = 'valid'; + } else { + $validity = $ctx->msg( 'confirmedit-preview-invalid' )->escaped(); + $css = 'notvalid'; + } + $html .= Html::openElement( 'tr' ) . + Html::element( + 'td', + [], + $lang->formatNum( $count + 1 ) + ) . + Html::element( + 'td', + [], + // IPv6 max length: 8 groups * 4 digits + 7 delimiter = 39 + // + 11 chars for safety + $lang->truncate( $ip, 50 ) + ) . + Html::rawElement( + 'td', + // possible values: + // mw-confirmedit-ip-valid + // mw-confirmedit-ip-notvalid + [ 'class' => 'mw-confirmedit-ip-' . $css ], + $validity + ) . + Html::closeElement( 'tr' ); + } + $html .= Html::closeElement( 'table' ); + $out->addModuleStyles( 'ext.confirmEdit.editPreview.ipwhitelist.styles' ); + + return false; + } } diff --git a/resources/ext.confirmEdit.editPreview.ipwhitelist.styles.css b/resources/ext.confirmEdit.editPreview.ipwhitelist.styles.css new file mode 100644 index 000000000..9fc808041 --- /dev/null +++ b/resources/ext.confirmEdit.editPreview.ipwhitelist.styles.css @@ -0,0 +1,7 @@ +.mw-confirmedit-ip-notvalid { + background-color: #FF6C6C; +} + +.mw-confirmedit-ip-valid { + background-color: #90EE90; +}