Modifying ConfirmEdit extension to make it API-friendly:

* Hooking into the APIEditBeforeSave hook (which will appear in the ApiEdit_Vodafone branch in the next revision)
* Moved general CAPTCHA generation in SimpleCaptcha to getCaptcha()
* Moved general confirmEdit() functionality to doConfirmEdit() to facilitate differtiating between UI and API handling
* Adding SimpleCaptcha::addCaptchaAPI() method that adds CAPTCHA information to an API result array. Other CAPTCHA implementations should override this method with a function that does the same (did this for FancyCaptcha and MathCaptcha)
This commit is contained in:
Roan Kattouw 2008-02-28 17:42:23 +00:00
parent 50b0cf3c05
commit c112c24f54
4 changed files with 84 additions and 19 deletions

View file

@ -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']

View file

@ -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 "<p><label for=\"wpCaptchaWord\">$test</label> = " .
return "<p><label for=\"wpCaptchaWord\">{$captcha['question']}</label> = " .
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.

View file

@ -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.
*/

View file

@ -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() {