addMessage('captcha-short', "Your edit includes new URL links; as a protection against automated spam, you'll need to enter the answer to this simple arithmetic test:" ); SpecialPage::addPage( new SpecialPage( 'Captcha', false, /*listed*/ false, /*function*/ false, /*file*/ false ) ); $wgCaptcha = new $wgCaptchaClass(); $wgHooks['EditFilter'][] = array( &$wgCaptcha, 'confirmEdit' ); } /** * Entry point for Special:Captcha */ function wfSpecialCaptcha( $par = null ) { global $wgCaptcha; switch( $par ) { case "image": return $wgCaptcha->showImage(); case "help": default: return $wgCaptcha->showHelp(); } } class SimpleCaptcha { /** * @param EditPage $editPage * @param string $newtext * @param string $section * @return bool true if the captcha should run */ function shouldCheck( &$editPage, $newtext, $section ) { global $wgUser; if( $wgUser->isAllowed( 'skipcaptcha' ) ) { wfDebug( "SimpleCaptcha: user group allows skipping captcha\n" ); return false; } global $wgEmailAuthentication, $ceAllowConfirmedEmail; if( $wgEmailAuthentication && $ceAllowConfirmedEmail && $wgUser->isEmailConfirmed() ) { wfDebug( "SimpleCaptcha: user has confirmed mail, skipping captcha\n" ); return false; } global $wgCaptchaTriggers; if( !empty( $wgCaptchaTriggers['edit'] ) ) { // Check on all edits wfDebug( "SimpleCaptcha: checking all edits...\n" ); return true; } if( !empty( $wgCaptchaTriggers['addurl'] ) ) { // Only check edits that add URLs $oldtext = $this->loadText( $editPage, $section ); $oldLinks = $this->findLinks( $oldtext ); $newLinks = $this->findLinks( $newtext ); $addedLinks = array_diff( $newLinks, $oldLinks ); $numLinks = count( $addedLinks ); if( $numLinks > 0 ) { wfDebug( "SimpleCaptcha: found $numLinks new links; triggered...\n" ); return true; } } return false; } function confirmEdit( &$editPage, $newtext, $section ) { if( $this->shouldCheck( $editPage, $newtext, $section ) ) { if( $this->keyMatch() ) { wfDebug( "ConfirmEdit given proper key from form, passing.\n" ); return true; } else { wfDebug( "ConfirmEdit missing form key, prompting.\n" ); $editPage->showEditForm( array( &$this, 'formCallback' ) ); return false; } } else { wfDebug( "ConfirmEdit: no new links.\n" ); return true; } } function keyMatch() { if( !isset( $_SESSION['ceAnswerVar'] ) ) { wfDebug( "ConfirmEdit no session captcha key set, this is new visitor.\n" ); return false; } global $wgRequest; return $wgRequest->getVal( $_SESSION['ceAnswerVar'] ) == $_SESSION['ceAnswer']; } function formCallback( &$out ) { $source = 'ceSource' . mt_rand(); $dest = 'ceConfirm' . mt_rand(); $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); $_SESSION['ceAnswer'] = $answer; $_SESSION['ceAnswerVar'] = $dest; $out->addWikiText( wfMsg( "captcha-short" ) ); $out->addHTML( << =

END ); } function loadText( $editPage, $section ) { $rev = Revision::newFromTitle( $editPage->mTitle ); if( is_null( $rev ) ) { return ""; } else { $text = $rev->getText(); if( $section != '' ) { return Article::getSection( $text, $section ); } else { return $text; } } } function findLinks( $text ) { $regex = '/((?:' . HTTP_PROTOCOLS . ')' . EXT_LINK_URL_CLASS . '+)/'; if( preg_match_all( $regex, $text, $matches, PREG_PATTERN_ORDER ) ) { return $matches[1]; } else { return array(); } } function showHelp() { global $wgOut, $ceAllowConfirmedEmail; $wgOut->setPageTitle( 'Captcha help' ); $wgOut->addWikiText( <<