Extension:VisualMathCaptcha

From MediaWiki.org
Jump to: navigation, search
MediaWiki extensions manual
Crystal Clear action run.png
VisualMathCaptcha

Release status: unmaintained

Special VisualMathCaptcha.png
Implementation Special page
Description Visual (image) and math captcha
Author(s) Cchanteptalk
Latest version 1.0-SNAPSHOT
MediaWiki 1.11.x-1.16.0
License No license specified
Download here
Example example 1,
example 2
Parameters

$wgVisualMathCaptchaItemMax, $wgVisualMathCaptchaItemNum, $wgVisualMathCaptchaOperators

Translate the VisualMathCaptcha extension if it is available at translatewiki.net

Check usage and version matrix; code metrics

The VisualMathCaptcha extension gave wikis an (at-best) moderately strong captcha with a math operation generated as image. It did not stop all spam, but did reduce the amount of rubbish which got through.

The extension is now abandoned. It was working up to MW 1.20 and PHP 5.3 or so, but on new MediaWiki installations is now failing with:

  • PHP Fatal error: Call to undefined method SpecialPage::SpecialPage() in extensions/VisualMathCaptcha/VisualMathCaptcha.body.php on line 16

Source code[edit | edit source]

README

* Put VisualMathCaptcha in your extensions directory
* Copy LocalSettings.part content into your LocalSettings.php

== Use with ConfirmEdit extension ==

* open ConfirmEdit.php and change $wgCaptchaClass value to 'VisualMathConfirmCaptcha'
* add following in LocalSettings.php after content copied from LocalSettings.par :
  $wgAutoloadClasses['VisualMathConfirmCaptcha'] = "$IP/extensions/VisualMathCaptcha/VisualMathConfirmCaptcha.class.php";

LocalSettings.part

require_once( "$IP/extensions/VisualMathCaptcha/VisualMathCaptcha.setup.php" );

//$wgVisualMathCaptchaItemMax = [int] max value (included) for each number in operation
// default: 9

//$wgVisualMathCaptchaItemNum = [int] count of number in generated operator
// default: 2

//$wgVisualMathCaptchaOperators = [array] operators allowed for generation
// default: { '+', '-' }

VisualMathCaptcha.body.php

<?php
/**
 * Special:VisualMathCaptcha, a piclens gallery display.
 * 
 * @addtogroup SpecialPage
 */
/**
 * Generate captcha
 */
class SpecialVisualMathCaptcha extends SpecialPage {
    
    /**
     * Constructor
     */
    function __construct() {
        SpecialPage::SpecialPage( 'VisualMathCaptcha', '', true );
    }
    
    /**
     * Main execution function
     * @param $par Parameters passed to the page
     */
    function execute( $par ) {
      global $wgOut;

      $wgOut->disable();

      // Settings
      global $wgVisualMathCaptchaItemMax, $wgVisualMathCaptchaItemNum, $wgVisualMathCaptchaOperators;

      if (!isset($wgVisualMathCaptchaItemMax)) {
        $wgVisualMathCaptchaItemMax = 9;
      }

      if (!isset($wgVisualMathCaptchaItemNum)) {
        $wgVisualMathCaptchaItemNum = 2;
      }

      if ($wgVisualMathCaptchaItemNum < 2) {
        echo '$wgVisualMathCaptchaItemNum is invalid: ' . $wgVisualMathCaptchaItemNum;
        return;
      }

      if (!isset($wgVisualMathCaptchaOperators)) {
        $wgVisualMathCaptchaOperators = array('+', '-');
      }

      // Generate
      $mexpr = "";

      $opi = -1;
      $opm = count($wgVisualMathCaptchaOperators)-1;
      for ($i = 0; $i < $wgVisualMathCaptchaItemNum; $i++) {
        if ($i > 0) { // add operator
          $opi = rand(0, $opm);

          $mexpr .= $wgVisualMathCaptchaOperators[$opi];
        }

        $mexpr .= rand(0, $wgVisualMathCaptchaItemMax);
      }

      // Store result
      $captchaRes = -1;

      eval("\$captchaRes = $mexpr;");
      $captchaLength = strlen($mexpr);
      $width = $captchaLength * 10+10;
      $height = 37;

      @session_start();
      $_SESSION['vmathCaptchaQuestion'] = $mexpr;
      $_SESSION['vmathCaptchaAnswer'] = $captchaRes;
 
      $image = imagecreatetruecolor($width, $height);
      $bgCol = imagecolorallocate($image, rand(128, 255), 
	rand(128, 255), rand(0, 255));

      imagefilledrectangle($image, 0, 0, $width, $height, $bgCol);
		
      for($c = 0; $c < $captchaLength * 2; $c++) {
	  $bgCol = imagecolorallocate($image, 
		rand(10,255), rand(10,255), rand(0,255));

	  $x = rand(0, $width);
	  $y = rand(0, $height);
	  $w = rand(5, $width/2);
	  $h = rand(5, $height/2);

	  imagefilledrectangle($image, $x, $y, $x+$w, $y+$h, $bgCol);
	  imagecolordeallocate($image, $bgCol);
      }

      for($c = 0; $c < $captchaLength; $c++) {
	  $txtCol = imagecolorallocate($image, rand(0,192), 
		rand(0,128), rand(0,255));

	  imagestring($image, 5, 5+10*$c, 
		rand(0,$height-15), substr($mexpr, $c, 1), $txtCol);

	  imagecolordeallocate($image, $txtCol);
      }

      $date = date("D, d M Y H:i:s e");

      header("Content-type: image/png");
      header("Date: $date");
      header("Last-Modified: $date");
      header("Expires: $date");
      header("Pragma: no-cache");
      header("Cache-Control: no-cache");
      header("ETag: $mexpr");

      imagepng($image);
      imagedestroy($image);
    }
}
?>


VisualMathCaptcha.class.php

<?php
class VisualMathCaptcha {
    var $trigger = NULL;
    var $action = NULL;

    function getForm() {
	global $wgScript, $wgVisualMathCaptchaLength;

        if (!isset($wgVisualMathCaptchaLength)) {
          $wgVisualMathCaptchaLength = 7;
        }

	$title = Title::makeTitle( NS_SPECIAL, 'VisualMathCaptcha' );
        $mtime = microtime();
	$url = $title->getLocalUrl();

	return "<span class=\"vmathCaptchaAnswerVisual\">" 
           . "<img src=\"$url?$mtime\" alt=\"captcha\" /></span>"
           . "<span class=\"vmathCaptchaAnswerField\">"
           . "<input type=\"text\" name=\"wpCaptcha\" "
	   . "maxlength=\"$wgVisualMathCaptchaLength\" id=\"wpCaptcha\" />"
           . "</span>";
    }

    /**
     * Check captcha.
     */
    function passCaptcha() {
	global $wgRequest;

	$result = NULL;
	$answer = $wgRequest->getText('wpCaptcha');

	if (isset($_SESSION['vmathCaptchaAnswer'])) {
	    $result = $_SESSION['vmathCaptchaAnswer'];
	}

	if ($answer == NULL && $result == NULL) {
	    return false;
	}

	return ($answer == $result);
    }
}

// Settings
global $wgCaptcha;

$wgCaptcha = new VisualMathCaptcha();
?>

VisualMathCaptcha.setup.php

<?php
if( !defined( 'MEDIAWIKI' ) ) {
    echo( "This file is an extension to the MediaWiki software and cannot be used standalone.\n" );
    die( 1 );
}

$wgExtensionCredits['specialpage'][] = array( 
    'name' => 'VisualMathCaptcha', 
    'author' => 'Cedric Chantepie', 
    'description' => 'Visual math captcha generator',
);

$wgAutoloadClasses['SpecialVisualMathCaptcha'] = dirname( __FILE__ ) . '/VisualMathCaptcha.body.php';
$wgSpecialPages['VisualMathCaptcha'] = 'SpecialVisualMathCaptcha';

include( dirname( __FILE__ ) . '/VisualMathCaptcha.class.php' );
?>


VisualMathConfirmCaptcha.class.php

<?php
class VisualMathConfirmCaptcha extends SimpleCaptcha {
    var $trigger = NULL;
    var $action = NULL;

    function getCaptcha() {
	return array(
	    'question' => $_SESSION['vmathCaptchaQuestion'],
	    'answer' => $_SESSION['vmathCaptchaAnswer']
	);
    }

    function getForm() {
	global $wgScript, $wgVisualMathCaptchaLength;

        if (!isset($wgVisualMathCaptchaLength)) {
          $wgVisualMathCaptchaLength = 7;
        }

	$title = Title::makeTitle( NS_SPECIAL, 'VisualMathCaptcha' );
	$mtime = microtime();
	$url = $title->getLocalUrl();

	return "<span class=\"vmathCaptchaAnswerVisual\">" 
           . "<img src=\"$url?$mtime\" alt=\"captcha\" /></span>"
           . "<span class=\"vmathCaptchaAnswerField\">"
           . "<input type=\"text\" name=\"wpCatcha\" "
	   . "maxlength=\"$wgVisualMathCaptchaLength\" id=\"wpCatcha\" />"
           . "</span>";
    }

    /**
     * Check captcha.
     */
    function passCaptcha() {
	global $wgRequest;

	$result = NULL;
	$answer = $wgRequest->getText('wpCatcha');

	if (isset($_SESSION['vmathCaptchaAnswer'])) {
	    $result = $_SESSION['vmathCaptchaAnswer'];
	}

	if ($answer == NULL && $result == NULL) {
	    return false;
	}

	return ($answer == $result);
    }

    /**
     * Check if the submitted form matches the captcha session data provided
     * by the plugin when the form was generated.
     *
     * @param string $answer
     * @param array $info
     * @return bool
     */
    function keyMatch( $answer, $info ) {
	return $answer == $info['answer'];
    }

    function addCaptchaAPI(&$resultArr) {
        $captcha = $this->getCaptcha();
        $index = $this->storeCaptcha( $captcha );
        $resultArr['captcha']['type'] = 'image';
        $resultArr['captcha']['mime'] = 'image/png';
        $resultArr['captcha']['id'] = $index;
        $resultArr['captcha']['question'] = $captcha['question'];
    }
}

// Settings
global $wgCaptcha;

$wgCaptcha = new VisualMathConfirmCaptcha();
?>


Installation[edit | edit source]

This extension requires you have GD module for PHP.

Download VisualMathExtension from here (this is not a direct link; extension can't be located by clicking this link).

To install this extension, add the following to LocalSettings.php:

require_once( "$IP/extensions/VisualMathCaptcha/VisualMathCaptcha.setup.php" );

Configuration parameters[edit | edit source]

  • $wgVisualMathCaptchaItemMax : [int] max value (included) for each number in operation ; Defaulted to 9. Needs to be increased as a trivial single-digit challenge will let 10% of the spam through.
  • $wgVisualMathCaptchaItemNum : [int] count of number in generated operator; Defaulted to 2.
  • $wgVisualMathCaptchaOperators : [array] operators allowed for generation; Defaulted to { '+', '-' }.

To adjust the minimum/maximum brightness of both the text characters and the random background, one must edit VisualMathCaptcha.body.php as these are not assigned parameters. The $bgCol = imagecolorallocate(...) and $txtCol = imagecolorallocate(...) lines control background and text colour, respectively.

The last three parameters of each contain a random function for brightness, where each controls one primary colour. The maximum range of each must be within 0 to 255, so (for example) rand(0,255) would allow any random intensity, rand(0,127) would be between black and grey, rand(128,255) between grey and white.

Adjust the foreground and background intensity to the lowest contrast which is still human-readable.

With other extensions[edit | edit source]

With ConfirmEdit[edit | edit source]

This captcha can be used instead of standard captcha of ConfirmEdit extension. To do so :

  1. Open ConfirmEdit.php, in ConfirmEdit extension directory, and change $wgCaptchaClass value to VisualMathConfirmCaptcha.
  2. Add following line in LocalSettings.php, after content copied from provided file LocalSettings.part :
  $wgAutoloadClasses['VisualMathConfirmCaptcha'] = "$IP/extensions/VisualMathCaptcha/VisualMathConfirmCaptcha.class.php";

With Lockdown extension[edit | edit source]

VisualMathCaptcha uses a special page: SpecialPage:VisualMathCaptcha.

Add in LocalSettings.php

$wgSpecialPageLockdown['VisualMathCaptcha'] = array('*');

With CorporateContact[edit | edit source]