diff --git a/FancyCaptcha/FancyCaptcha.class.php b/FancyCaptcha/FancyCaptcha.class.php index 64c15ad4c..ebdf17b0d 100755 --- a/FancyCaptcha/FancyCaptcha.class.php +++ b/FancyCaptcha/FancyCaptcha.class.php @@ -88,19 +88,20 @@ class FancyCaptcha extends SimpleCaptcha { /** * Insert the captcha prompt into the edit form. + * @param OutputPage $out */ - function getForm() { + function getForm( OutputPage $out ) { global $wgOut, $wgEnableAPI; // Uses addModuleStyles so it is loaded when JS is disabled. - $wgOut->addModuleStyles( 'ext.confirmEdit.fancyCaptcha.styles' ); + $out->addModuleStyles( 'ext.confirmEdit.fancyCaptcha.styles' ); $title = SpecialPage::getTitleFor( 'Captcha', 'image' ); $index = $this->getCaptchaIndex(); if ( $wgEnableAPI ) { // Loaded only if JS is enabled - $wgOut->addModules( 'ext.confirmEdit.fancyCaptcha' ); + $out->addModules( 'ext.confirmEdit.fancyCaptcha' ); $captchaReload = Html::element( 'small', diff --git a/MathCaptcha/MathCaptcha.class.php b/MathCaptcha/MathCaptcha.class.php index d3e4af69c..4eba6e408 100644 --- a/MathCaptcha/MathCaptcha.class.php +++ b/MathCaptcha/MathCaptcha.class.php @@ -16,8 +16,11 @@ class MathCaptcha extends SimpleCaptcha { $resultArr['captcha']['question'] = $sum; } - /** Produce a nice little form */ - function getForm() { + /** + * Produce a nice little form + * @param OutputPage $out + */ + function getForm( OutputPage $out ) { list( $sum, $answer ) = $this->pickSum(); $index = $this->storeCaptcha( array( 'answer' => $answer ) ); diff --git a/QuestyCaptcha/QuestyCaptcha.class.php b/QuestyCaptcha/QuestyCaptcha.class.php index 7f0f3565c..e07dc5dc6 100644 --- a/QuestyCaptcha/QuestyCaptcha.class.php +++ b/QuestyCaptcha/QuestyCaptcha.class.php @@ -41,7 +41,7 @@ class QuestyCaptcha extends SimpleCaptcha { return array( 'question' => $question, 'answer' => $answer ); } - function getForm() { + function getForm( OutputPage $out ) { $captcha = $this->getCaptcha(); if ( !$captcha ) { die( "No questions found; set some in LocalSettings.php using the format from QuestyCaptcha.php." ); diff --git a/ReCaptcha/ReCaptcha.class.php b/ReCaptcha/ReCaptcha.class.php index cd274a970..90dc4f656 100644 --- a/ReCaptcha/ReCaptcha.class.php +++ b/ReCaptcha/ReCaptcha.class.php @@ -7,9 +7,9 @@ class ReCaptcha extends SimpleCaptcha { /** * Displays the reCAPTCHA widget. * If $this->recaptcha_error is set, it will display an error in the widget. - * + * @param OutputPage $out */ - function getForm() { + function getForm( OutputPage $out ) { global $wgReCaptchaPublicKey, $wgReCaptchaTheme; $useHttps = ( isset( $_SERVER['HTTPS'] ) && $_SERVER['HTTPS'] == 'on' ); diff --git a/ReCaptchaNoCaptcha.php b/ReCaptchaNoCaptcha.php new file mode 100644 index 000000000..17796e578 --- /dev/null +++ b/ReCaptchaNoCaptcha.php @@ -0,0 +1,2 @@ +addHeadItem( + 'g-recaptchascript', + '' + ); + $output = Html::element( 'div', array( + 'class' => array( + 'g-recaptcha', + 'mw-confirmedit-captcha-fail' => !!$this->error, + ), + 'data-sitekey' => $wgReCaptchaSiteKey + ) ); + $htmlUrlencoded = htmlspecialchars( urlencode( $wgReCaptchaSiteKey ) ); + $output .= << +
+
+
+ +
+
+ +
+
+
+ +HTML; + return $output; + } + + protected function logCheckError( $info ) { + if ( $info instanceof Status ) { + $errors = $status->getErrorsArray(); + $error = $errors[0][0]; + } elseif ( is_array( $info ) ) { + $error = implode( ',', $info ); + } else { + $error = $info; + } + wfDebugLog( 'captcha', 'Unable to validate response: ' . $error ); + } + + /** + * Check, if the user solved the captcha. + * + * Based on reference implementation: + * https://github.com/google/recaptcha#php + * + * @return boolean + */ + function passCaptcha() { + global $wgRequest, $wgReCaptchaSecretKey, $wgReCaptchaSendRemoteIP; + + $url = 'https://www.google.com/recaptcha/api/siteverify'; + // Build data to append to request + $data = array( + 'secret' => $wgReCaptchaSecretKey, + 'response' => $wgRequest->getVal( 'g-recaptcha-response' ), + ); + if ( $wgReCaptchaSendRemoteIP ) { + $data['remoteip'] = $wgRequest->getIP(); + } + $url = wfAppendQuery( $url, $data ); + $request = MWHttpRequest::factory( $url, array( 'method' => 'GET' ) ); + $status = $request->execute(); + if ( !$status->isOK() ) { + $this->error = 'http'; + $this->logStatusError( $status ); + return false; + } + $response = FormatJson::decode( $request->getContent(), true ); + if ( !$response ) { + $this->error = 'json'; + $this->logStatusError( $this->error ); + return false; + } + if ( isset( $response['error-codes'] ) ) { + $this->error = 'recaptcha-api'; + $this->logCheckError( $response['error-codes'] ); + return false; + } + + return $response['success']; + } + + function addCaptchaAPI( &$resultArr ) { + global $wgReCaptchaSiteKey; + + $resultArr['captcha']['type'] = 'recaptchanocaptcha'; + $resultArr['captcha']['mime'] = 'image/png'; + $resultArr['captcha']['key'] = $wgReCaptchaSiteKey; + $resultArr['captcha']['error'] = $this->error; + } + + /** + * Show a message asking the user to enter a captcha on edit + * The result will be treated as wiki text + * + * @param $action string Action being performed + * @return string Wikitext + */ + function getMessage( $action ) { + $name = 'renocaptcha-' . $action; + $msg = wfMessage( $name ); + + $text = $msg->isDisabled() ? wfMessage( 'renocaptcha-edit' )->text() : $msg->text(); + if ( $this->error ) { + $text = '
' . $text . '
'; + } + return $text; + } + + public function APIGetAllowedParams( &$module, &$params, $flags ) { + if ( $flags && $this->isAPICaptchaModule( $module ) ) { + $params['g-recaptcha-response'] = null; + } + + return true; + } + + public function APIGetParamDescription( &$module, &$desc ) { + if ( $this->isAPICaptchaModule( $module ) ) { + $desc['g-recaptcha-response'] = 'Field from the ReCaptcha widget'; + } + + return true; + } +} diff --git a/ReCaptchaNoCaptcha/ReCaptchaNoCaptcha.php b/ReCaptchaNoCaptcha/ReCaptchaNoCaptcha.php new file mode 100644 index 000000000..e7528b7ac --- /dev/null +++ b/ReCaptchaNoCaptcha/ReCaptchaNoCaptcha.php @@ -0,0 +1,13 @@ +getCaptcha(); $index = $this->storeCaptcha( $captcha ); @@ -87,7 +87,7 @@ class SimpleCaptcha { $this->shouldCheck( $page, '', '', false ) ) { $out->addWikiText( $this->getMessage( $this->action ) ); - $out->addHTML( $this->getForm() ); + $out->addHTML( $this->getForm( $out ) ); } unset( $page->ConfirmEdit_ActivateCaptcha ); } @@ -124,7 +124,7 @@ class SimpleCaptcha { $form->addFooterText( "
" . $wgOut->parse( $this->getMessage( 'sendemail' ) ) . - $this->getForm() . + $this->getForm( $wgOut ) . "
\n" ); } return true; @@ -146,7 +146,7 @@ class SimpleCaptcha { } $captcha = "
" . $wgOut->parse( $this->getMessage( 'createaccount' ) ) . - $this->getForm() . + $this->getForm( $wgOut ) . "
\n"; // for older MediaWiki versions if ( is_callable( array( $template, 'extend' ) ) ) { @@ -172,7 +172,7 @@ class SimpleCaptcha { $this->action = 'badlogin'; $captcha = "
" . $wgOut->parse( $this->getMessage( 'badlogin' ) ) . - $this->getForm() . + $this->getForm( $wgOut ) . "
\n"; // for older MediaWiki versions if ( is_callable( array( $template, 'extend' ) ) ) {