*/
function ceSetup() {
global $wgMessageCache, $wgHooks, $wgCaptcha, $wgCaptchaClass;
- $wgMessageCache->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:" );
+ $wgMessageCache->addMessages( array(
+ 'captcha-short' =>
+ "Your edit includes new URL links; as a protection against automated " .
+ "spam, you'll need to type in the words that appear in this image:\n" .
+ "<br />([[Special:Captcha/help|What is this?]])",
+ 'captchahelp-title' =>
+ 'Captcha help',
+ 'captchahelp-text' =>
+ "Web sites that accept postings from the public, like this wiki, " .
+ "are often abused by spammers who use automated tools to post their " .
+ "links to many sites. While these spam links can be removed, they " .
+ "are a significant nuisance." .
+ "\n\n" .
+ "Sometimes, especially when adding new web links to a page, " .
+ "the wiki may show you an image of colored or distorted text and " .
+ "ask you to type the words shown. Since this is a task that's hard " .
+ "to automate, it will allow most real humans to make their posts " .
+ "while stopping most spammers and other robotic attackers." .
+ "\n\n" .
+ "Unfortunately this may inconvenience users with limited vision or " .
+ "using text-based or speech-based browsers. At the moment we do not " .
+ "have an audio alternative available. Please contact the site " .
+ "administrators for assistance if this is unexpectedly preventing " .
+ "you from making legitimate posts." .
+ "\n\n" .
+ "Hit the 'back' button in your browser to return to the page editor." ) );
SpecialPage::addPage( new SpecialPage( 'Captcha', false,
/*listed*/ false, /*function*/ false, /*file*/ false ) );
$numLinks = count( $addedLinks );
if( $numLinks > 0 ) {
- wfDebug( "SimpleCaptcha: found $numLinks new links; triggered...\n" );
+ global $wgUser, $wgTitle;
+ wfDebugLog( "captcha", sprintf( "ConfirmEdit: %dx url trigger by %s at [[%s]]: %s",
+ $numLinks,
+ $wgUser->getName(),
+ $wgTitle->getPrefixedText(),
+ implode( ", ", $addedLinks ) ) );
return true;
}
}
function showHelp() {
global $wgOut, $ceAllowConfirmedEmail;
- $wgOut->setPageTitle( 'Captcha help' );
- $wgOut->addWikiText( <<<END
- So what's this wacky captcha thing about?
-
- It's your enemy. It's here to kill you. RUN WHILE YOU STILL CAN
-END
- );
+ $wgOut->setPageTitle( wfMsg( 'captchahelp-title' ) );
+ $wgOut->addWikiText( wfMsg( 'captchahelp-text' ) );
}
}
return false;
}
- $var = $_SESSION['ceAnswerVar'];
- $salt = $_SESSION['captchaSalt'];
- $hash = $_SESSION['captchaHash'];
+ $var = @$_SESSION['ceAnswerVar'];
+ $salt = @$_SESSION['captchaSalt'];
+ $hash = @$_SESSION['captchaHash'];
$answer = $wgRequest->getVal( $var );
$digest = $wgCaptchaSecret . $salt . $answer . $wgCaptchaSecret . $salt;
}
}
+ /**
+ * Insert the captcha prompt into the edit form.
+ */
function formCallback( &$out ) {
$dest = 'wpCaptchaWord' . mt_rand();
$img = $this->pickImage();
if( !$img ) {
- die( 'aaargh' );
+ die( "out of captcha images; this shouldn't happen" );
}
$_SESSION['ceAnswerVar'] = $dest;
wfDebug( "Picked captcha with hash ${img['hash']}, salt ${img['salt']}.\n" );
$title = Title::makeTitle( NS_SPECIAL, 'Captcha/image' );
- $url = $title->getLocalUrl();
-
$out->addWikiText( wfMsg( "captcha-short" ) );
- $out->addHTML( <<<END
- <p><img src="$url" alt="Oh noes" /></p>
- <p><input name="$dest" id="$dest" /></p>
-END
- );
+ $out->addHTML( "<p>" .
+ wfElement( 'img', array(
+ 'src' => $title->getLocalUrl(),
+ 'width' => $img['width'],
+ 'height' => $img['height'],
+ 'alt' => '' ) ) .
+ "</p>\n" .
+ "<p><input name=\"$dest\" id=\"$dest\" tabindex=\"1\" /></p>" );
}
+ /**
+ * Select a previously generated captcha image from the queue.
+ * @fixme subject to race conditions if lots of files vanish
+ * @return mixed tuple of (salt key, text hash) or false if no image to find
+ */
function pickImage() {
global $wgCaptchaDirectory;
+ $pick = mt_rand( 0, $this->countFiles( $wgCaptchaDirectory ) );
$dir = opendir( $wgCaptchaDirectory );
$n = mt_rand( 0, 16 );
$count = 0;
$entry = readdir( $dir );
+ $pick = false;
while( false !== $entry ) {
$entry = readdir( $dir );
if( preg_match( '/^image_([0-9a-f]+)_([0-9a-f]+)\\.png$/', $entry, $matches ) ) {
- if( $count++ % 16 == $n ) {
- return array(
- 'salt' => $matches[1],
- 'hash' => $matches[2],
- );
+ $size = getimagesize( "$wgCaptchaDirectory/$entry" );
+ $pick = array(
+ 'salt' => $matches[1],
+ 'hash' => $matches[2],
+ 'width' => $size[0],
+ 'height' => $size[1]
+ );
+ if( $count++ == $n ) {
+ break;
}
}
}
- return false;
+ closedir( $dir );
+ return $pick;
+ }
+
+ /**
+ * Count the number of files in a directory.
+ * @return int
+ */
+ function countFiles( $dirname ) {
+ $dir = opendir( $dirname );
+ $count = 0;
+ while( false !== ($entry = readdir( $dir ) ) ) {
+ if( $dir != '.' && $dir != '..' ) {
+ $count++;
+ }
+ }
+ closedir( $dir );
+ return $count;
}
function showImage() {