diff --git a/ConfirmEdit.php b/ConfirmEdit.php index 722a3c7ed..2faac7f03 100644 --- a/ConfirmEdit.php +++ b/ConfirmEdit.php @@ -166,7 +166,6 @@ $wgCaptchaWhitelist = false; $wgCaptchaRegexes = array(); /** Register special page */ -global $wgSpecialPages; $wgSpecialPages['Captcha'] = array( /*class*/'CaptchaSpecialPage', /*name*/'Captcha' ); $wgConfirmEditIP = dirname( __FILE__ ); @@ -182,6 +181,8 @@ $wgHooks['AbortNewAccount'][] = 'ConfirmEditHooks::confirmUserCreate'; $wgHooks['LoginAuthenticateAudit'][] = 'ConfirmEditHooks::triggerUserLogin'; $wgHooks['UserLoginForm'][] = 'ConfirmEditHooks::injectUserLogin'; $wgHooks['AbortLogin'][] = 'ConfirmEditHooks::confirmUserLogin'; +# Register API hook +$wgHooks['APIEditBeforeSave'][] = 'ConfirmEditHooks::confirmEditAPI'; $wgAutoloadClasses['ConfirmEditHooks'] = $wgAutoloadClasses['SimpleCaptcha'] diff --git a/ConfirmEdit_body.php b/ConfirmEdit_body.php index 1755183a1..e905640cf 100644 --- a/ConfirmEdit_body.php +++ b/ConfirmEdit_body.php @@ -22,6 +22,10 @@ class ConfirmEditHooks { static function confirmEditMerged( &$editPage, $newtext ) { return self::getInstance()->confirmEditMerged( $editPage, $newtext ); } + + static function confirmEditAPI( &$editPage, $newtext, &$resultArr ) { + return self::getInstance()->confirmEditAPI( $editPage, $newtext, $resultArr ); + } static function injectUserCreate( &$template ) { return self::getInstance()->injectUserCreate( $template ); @@ -65,6 +69,24 @@ class SimpleCaptcha { $this->storage = new $wgCaptchaStorageClass; } + function getCaptcha() { + $a = mt_rand(0, 100); + $b = mt_rand(0, 10); + $op = mt_rand(0, 1) ? '+' : '-'; + + $test = "$a $op $b"; + $answer = ($op == '+') ? ($a + $b) : ($a - $b); + return array('question' => $test, 'answer' => $answer); + } + + function addCaptchaAPI(&$resultArr) { + $captcha = $this->getCaptcha(); + $index = $this->storeCaptcha( $captcha ); + $resultArr['captcha']['type'] = 'simple'; + $resultArr['captcha']['id'] = $index; + $resultArr['captcha']['question'] = $captcha['question']; + } + /** * Insert a captcha prompt into the edit form. * This sample implementation generates a simple arithmetic operation; @@ -75,16 +97,10 @@ class SimpleCaptcha { * @return string HTML */ function getForm() { - $a = mt_rand(0, 100); - $b = mt_rand(0, 10); - $op = mt_rand(0, 1) ? '+' : '-'; + $captcha = $this->getCaptcha(); + $index = $this->storeCaptcha( $captcha ); - $test = "$a $op $b"; - $answer = ($op == '+') ? ($a + $b) : ($a - $b); - - $index = $this->storeCaptcha( array( 'answer' => $answer ) ); - - return "

= " . + return "

= " . wfElement( 'input', array( 'name' => 'wpCaptchaWord', 'id' => 'wpCaptchaWord', @@ -430,21 +446,17 @@ class SimpleCaptcha { $links[] = $row->el_to; } return $links; - } - + } + /** - * The main callback run on edit attempts. - * @param EditPage $editPage - * @param string $newtext - * @param string $section - * @param bool true to continue saving, false to abort and show a captcha form + * Backend function for confirmEdit() and confirmEditAPI() + * @return bool false if the CAPTCHA is rejected, true otherwise */ - function confirmEdit( &$editPage, $newtext, $section, $merged = false ) { + private function doConfirmEdit( &$editPage, $newtext, $section, $merged = false ) { if( $this->shouldCheck( $editPage, $newtext, $section, $merged ) ) { if( $this->passCaptcha() ) { return true; } else { - $editPage->showEditForm( array( &$this, 'editCallback' ) ); return false; } } else { @@ -453,6 +465,28 @@ class SimpleCaptcha { } } + /** + * The main callback run on edit attempts. + * @param EditPage $editPage + * @param string $newtext + * @param string $section + * @param bool $merged + * @return bool true to continue saving, false to abort and show a captcha form + */ + function confirmEdit( &$editPage, $newtext, $section, $merged = false ) { + global $wgTitle; + if( is_null( $wgTitle ) ) { + # API mode + # The CAPTCHA was already checked and approved + return true; + } + if( !$this->doConfirmEdit( $editPage, $newtext, $section, $merged ) ) { + $editPage->showEditForm( array( &$this, 'editCallback' ) ); + return false; + } + return true; + } + /** * A more efficient edit filter callback based on the text after section merging * @param EditPage $editPage @@ -461,6 +495,15 @@ class SimpleCaptcha { function confirmEditMerged( &$editPage, $newtext ) { return $this->confirmEdit( $editPage, $newtext, false, true ); } + + + function confirmEditAPI( &$editPage, $newtext, &$resultArr) { + if( !$this->doConfirmEdit( $editPage, $newtext, false, false ) ) { + $this->addCaptchaAPI($resultArr); + return false; + } + return true; + } /** * Hook for user creation form submissions. diff --git a/FancyCaptcha.class.php b/FancyCaptcha.class.php index abdb2f884..b560e712e 100644 --- a/FancyCaptcha.class.php +++ b/FancyCaptcha.class.php @@ -24,6 +24,19 @@ class FancyCaptcha extends SimpleCaptcha { } } + function addCaptchaAPI(&$resultArr) { + $info = $this->pickImage(); + if( !$info ) { + $resultArr['captcha']['error'] = 'Out of images'; + return; + } + $index = $this->storeCaptcha( $info ); + $title = Title::makeTitle( NS_SPECIAL, 'Captcha/image' ); + $resultArr['captcha']['type'] = 'image'; + $resultArr['captcha']['id'] = $index; + $resultArr['captcha']['url'] = $title->getLocalUrl( 'wpCaptchaId=' . urlencode( $index ) ); + } + /** * Insert the captcha prompt into the edit form. */ diff --git a/MathCaptcha.class.php b/MathCaptcha.class.php index adf1663b8..a51e7fae6 100644 --- a/MathCaptcha.class.php +++ b/MathCaptcha.class.php @@ -6,6 +6,14 @@ class MathCaptcha extends SimpleCaptcha { function keyMatch( $answer, $info ) { return (int)$answer == (int)$info['answer']; } + + function addCaptchaAPI(&$resultArr) { + list( $sum, $answer ) = $this->pickSum(); + $index = $this->storeCaptcha( array('answer' => $answer ) ); + $resultArr['captcha']['type'] = 'math'; + $resultArr['captcha']['id'] = $index; + $resultArr['captcha']['sum'] = $sum; + } /** Produce a nice little form */ function getForm() {