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 );
$instance = ConfirmEditHooks::getInstance();
switch( $par ) {
case "image":
- return $instance->showImage();
+ if( method_exists($instance,'showImage') )
+ return $instance->showImage();
case "help":
default:
return $instance->showHelp();
$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']['mime'] = 'text/plain';
+ $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;
* @return string HTML
*/
function getForm() {
- $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);
-
- $index = $this->storeCaptcha( array( 'answer' => $answer ) );
+ $captcha = $this->getCaptcha();
+ $index = $this->storeCaptcha( $captcha );
- return "<p><label for=\"wpCaptchaWord\">$test</label> = " .
- wfElement( 'input', array(
+ return "<p><label for=\"wpCaptchaWord\">{$captcha['question']}</label> = " .
+ Xml::element( 'input', array(
'name' => 'wpCaptchaWord',
'id' => 'wpCaptchaWord',
'tabindex' => 1 ) ) . // tab in before the edit textarea
"</p>\n" .
- wfElement( 'input', array(
+ Xml::element( 'input', array(
'type' => 'hidden',
'name' => 'wpCaptchaId',
'id' => 'wpCaptchaId',
* @return bool true to keep running callbacks
*/
function injectUserCreate( &$template ) {
- global $wgCaptchaTriggers, $wgOut;
+ global $wgCaptchaTriggers, $wgOut, $wgUser;
if( $wgCaptchaTriggers['createaccount'] ) {
+ if( $wgUser->isAllowed( 'skipcaptcha' ) ) {
+ wfDebug( "ConfirmEdit: user group allows skipping captcha on account creation\n" );
+ return true;
+ }
$template->set( 'header',
"<div class='captcha'>" .
$wgOut->parse( $this->getMessage( 'createaccount' ) ) .
* @access private
*/
function isBadLoginTriggered() {
- global $wgMemc;
- return intval( $wgMemc->get( $this->badLoginKey() ) ) > 0;
+ global $wgMemc, $wgCaptchaBadLoginAttempts;
+ return intval( $wgMemc->get( $this->badLoginKey() ) ) >= $wgCaptchaBadLoginAttempts;
+ }
+
+ /**
+ * Check if the IP is allowed to skip captchas
+ */
+ function isIPWhitelisted() {
+ global $wgCaptchaWhitelistIP;
+ if( $wgCaptchaWhitelistIP ) {
+ $ip = wfGetIp();
+ foreach ( $wgCaptchaWhitelistIP as $range ) {
+ if ( IP::isInRange( $ip, $range ) ) {
+ return true;
+ }
+ }
+ }
+ return false;
}
/**
*
* Override this!
*
- * @param WebRequest $request
+ * @param string $answer
* @param array $info
* @return bool
*/
- function keyMatch( $request, $info ) {
- return $request->getVal( 'wpCaptchaWord' ) == $info['answer'];
+ function keyMatch( $answer, $info ) {
+ return $answer == $info['answer'];
}
// ----------------------------------
wfDebug( "ConfirmEdit: user group allows skipping captcha\n" );
return false;
}
- global $wgCaptchaWhitelistIP;
- if( !empty( $wgCaptchaWhitelistIP ) ) {
- $ip = wfGetIp();
- foreach ( $wgCaptchaWhitelistIP as $range ) {
- if ( IP::isInRange( $ip, $range ) ) {
- return false;
- }
- }
- }
+ if( $this->isIPWhitelisted() )
+ return false;
global $wgEmailAuthentication, $ceAllowConfirmedEmail;
} else {
// Get link changes in the slowest way known to man
$oldtext = $this->loadText( $editPage, $section );
- $oldLinks = $this->findLinks( $oldtext );
- $newLinks = $this->findLinks( $newtext );
+ $oldLinks = $this->findLinks( $editPage, $oldtext );
+ $newLinks = $this->findLinks( $editPage, $newtext );
}
$unknownLinks = array_filter( $newLinks, array( &$this, 'filterLink' ) );
}
global $wgCaptchaRegexes;
- if( !empty( $wgCaptchaRegexes ) ) {
+ if( $wgCaptchaRegexes ) {
// Custom regex checks
$oldtext = $this->loadText( $editPage, $section );
//$regex = 'http://+[a-z0-9_\-.]*(' . implode( '|', $lines ) . ')';
//return '/' . str_replace( '/', '\/', preg_replace('|\\\*/|', '/', $regex) ) . '/Si';
$regexes = '';
- $regexStart = '/http:\/\/+[a-z0-9_\-.]*(';
+ $regexStart = '/^https?:\/\/+[a-z0-9_\-.]*(';
$regexEnd = ')/Si';
$regexMax = 4096;
$build = false;
$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 {
}
}
+ /**
+ * 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 ) {
+ if( defined('MW_API') ) {
+ # 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
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.
* @return bool true to continue, false to abort user creation
*/
function confirmUserCreate( $u, &$message ) {
- global $wgCaptchaTriggers;
+ global $wgCaptchaTriggers, $wgUser;
if( $wgCaptchaTriggers['createaccount'] ) {
+ if( $wgUser->isAllowed( 'skipcaptcha' ) ) {
+ wfDebug( "ConfirmEdit: user group allows skipping captcha on account creation\n" );
+ return true;
+ }
+ if( $this->isIPWhitelisted() )
+ return true;
+
$this->trigger = "new account '" . $u->getName() . "'";
if( !$this->passCaptcha() ) {
$message = wfMsg( 'captcha-createaccount-fail' );
*/
function confirmUserLogin( $u, $pass, &$retval ) {
if( $this->isBadLoginTriggered() ) {
+ if( $this->isIPWhitelisted() )
+ return true;
+
$this->trigger = "post-badlogin login '" . $u->getName() . "'";
if( !$this->passCaptcha() ) {
$message = wfMsg( 'captcha-badlogin-fail' );
$info = $this->retrieveCaptcha();
if( $info ) {
global $wgRequest;
- if( $this->keyMatch( $wgRequest, $info ) ) {
+ if( $this->keyMatch( $wgRequest->getVal('wpCaptchaWord'), $info ) ) {
$this->log( "passed" );
$this->clearCaptcha( $info );
return true;
* @param string $text
* @return array of strings
*/
- function findLinks( $text ) {
- global $wgParser, $wgTitle, $wgUser;
+ function findLinks( &$editpage, $text ) {
+ global $wgParser, $wgUser;
$options = new ParserOptions();
- $text = $wgParser->preSaveTransform( $text, $wgTitle, $wgUser, $options );
- $out = $wgParser->parse( $text, $wgTitle, $options );
+ $text = $wgParser->preSaveTransform( $text, $editpage->mTitle, $wgUser, $options );
+ $out = $wgParser->parse( $text, $editpage->mTitle, $options );
return array_keys( $out->getExternalLinks() );
}