MediaWiki r91976 - Code Review

Jump to: navigation, search
Repository:MediaWiki
Revision:r91975‎ | r91976 (on ViewVC)‎ | r91977 >
Date:17:26, 12 July 2011
Author:yaron
Status:reverted (Comments)
Tags:
Comment:
New "Asirra" module, from the Asirra extension by Bachsau
Modified paths:

Diff [purge]

Index: trunk/extensions/ConfirmEdit/Asirra.i18n.php
@@ -0,0 +1,35 @@
 2+<?php
 3+/**
 4+ * Internationalisation file for the Asirra module of the ConfirmEdit
 5+ * extension.
 6+ *
 7+ * @file
 8+ * @ingroup Extensions
 9+ */
 10+
 11+$messages = array();
 12+
 13+/* English */
 14+$messages['en'] = array(
 15+ 'asirra-desc' => 'Asirra module for ConfirmEdit',
 16+ 'asirra-edit' => 'To help protect against automated edit spam, please select just the cat photos in the box below:',
 17+ 'asirra-addurl' => 'Your edit includes new external links. To help protect against automated spam, please select just the cat photos in the box below:',
 18+ 'asirra-badpass' => 'To help protect against automated password cracking, please select just the cat photos in the box below:',
 19+ 'asirra-createaccount' => 'To help protect against automated account creation, please select just the cat photos in the box below:',
 20+ 'asirra-createaccount-fail' => "Please correctly identify the cats.",
 21+ 'asirra-create' => 'To help protect against automated page creation, please select just the cat photos in the box below:',
 22+ 'asirra-nojs' => '\'\'\'Please enable JavaScript and resubmit the page.\'\'\''
 23+);
 24+
 25+
 26+/** German (Deutsch) */
 27+$messages['de'] = array(
 28+ 'asirra-desc' => 'Asirra-Modul für ConfirmEdit',
 29+ 'asirra-edit' => 'Zum Schutz vor automatisiertem Spam, wähle bitte nur die Katzen im untenstehenden Feld aus:',
 30+ 'asirra-addurl' => 'Deine Bearbeitung enthält neue externe Links. Zum Schutz vor automatisiertem Spam wähle bitte nur die Katzen im untenstehenden Feld aus:',
 31+ 'asirra-badpass' => 'Zum Schutz gegen automatisiertes Knacken von Passwörtern, wähle bitte nur die Katzen im untenstehenden Feld aus:',
 32+ 'asirra-createaccount' => 'Zum Schutz gegen automatisierte Erstellung von Benutzerkonten wähle bitte nur die Katzen im untenstehenden Feld aus:',
 33+ 'asirra-createaccount-fail' => 'Bitte wähle nur Katzen aus.',
 34+ 'asirra-create' => 'Zum Schutz gegen automatisierte Erstellung von Seiten, wähle bitte nur die Katzen im untenstehenden Feld aus:',
 35+ 'asirra-nojs' => '\'\'\'Bitte aktiviere JavaScript und sende die Seite noch einmal ab.\'\'\''
 36+);
Index: trunk/extensions/ConfirmEdit/asirra_contentloaded.js
@@ -0,0 +1,50 @@
 2+/*!
 3+ * contentloaded.js
 4+ *
 5+ * Author: Diego Perini (diego.perini at gmail.com)
 6+ * Summary: cross-browser wrapper for DOMContentLoaded
 7+ * Updated: 20101020
 8+ * License: MIT
 9+ * Version: 1.2
 10+ *
 11+ * URL:
 12+ * http://javascript.nwbox.com/ContentLoaded/
 13+ * http://javascript.nwbox.com/ContentLoaded/MIT-LICENSE
 14+ *
 15+ */
 16+
 17+// @win window reference
 18+// @fn function reference
 19+function contentLoaded(win, fn) {
 20+
 21+ var done = false, top = true,
 22+
 23+ doc = win.document, root = doc.documentElement,
 24+
 25+ add = doc.addEventListener ? 'addEventListener' : 'attachEvent',
 26+ rem = doc.addEventListener ? 'removeEventListener' : 'detachEvent',
 27+ pre = doc.addEventListener ? '' : 'on',
 28+
 29+ init = function(e) {
 30+ if (e.type == 'readystatechange' && doc.readyState != 'complete') return;
 31+ (e.type == 'load' ? win : doc)[rem](pre + e.type, init, false);
 32+ if (!done && (done = true)) fn.call(win, e.type || e);
 33+ },
 34+
 35+ poll = function() {
 36+ try { root.doScroll('left'); } catch(e) { setTimeout(poll, 50); return; }
 37+ init('poll');
 38+ };
 39+
 40+ if (doc.readyState == 'complete') fn.call(win, 'lazy');
 41+ else {
 42+ if (doc.createEventObject && root.doScroll) {
 43+ try { top = !win.frameElement; } catch(e) { }
 44+ if (top) poll();
 45+ }
 46+ doc[add](pre + 'DOMContentLoaded', init, false);
 47+ doc[add](pre + 'readystatechange', init, false);
 48+ win[add](pre + 'load', init, false);
 49+ }
 50+
 51+}
Index: trunk/extensions/ConfirmEdit/Asirra.php
@@ -0,0 +1,43 @@
 2+<?php
 3+/**
 4+ * Asirra CAPTCHA module for the ConfirmEdit MediaWiki extension.
 5+ * @author Bachsau
 6+ *
 7+ * Makes use of the Asirra (Animal Species Image Recognition for
 8+ * Restricting Access) CAPTCHA service, developed by John Douceur, Jeremy
 9+ * Elson and Jon Howell at Microsoft Research.
 10+ *
 11+ * Asirra uses a large set of images from http://petfinder.com.
 12+ *
 13+ * For more information about Asirra, see:
 14+ * http://research.microsoft.com/en-us/um/redmond/projects/asirra/
 15+ *
 16+ * This MediaWiki code is released into the public domain, without any
 17+ * warranty. YOU CAN DO WITH IT WHATEVER YOU LIKE!
 18+ *
 19+ * @file
 20+ * @ingroup Extensions
 21+ */
 22+
 23+if ( !defined( 'MEDIAWIKI' ) ) {
 24+ exit;
 25+}
 26+
 27+require_once dirname( __FILE__ ) . '/ConfirmEdit.php';
 28+$wgCaptchaClass = 'Asirra';
 29+
 30+// Default Asirra options.
 31+// Use LocalSettings.php for any changes
 32+$wgAsirraEnlargedPosition = 'bottom';
 33+$wgAsirraCellsPerRow = '6';
 34+$wgAsirraScriptPath = '';
 35+
 36+// AsirraXmlParser initial values
 37+$wgAsirra = array
 38+(
 39+ 'inResult' => 0,
 40+ 'passed' => 0
 41+);
 42+
 43+$wgExtensionMessagesFiles['Asirra'] = dirname( __FILE__ ) . '/Asirra.i18n.php';
 44+$wgAutoloadClasses['Asirra'] = dirname( __FILE__ ) . '/Asirra.class.php';
Index: trunk/extensions/ConfirmEdit/asirra_humanverify.js
@@ -0,0 +1,62 @@
 2+/*======================================================================*\
 3+|| #################################################################### ||
 4+|| # Asirra module for ConfirmEdit by Bachsau # ||
 5+|| # ---------------------------------------------------------------- # ||
 6+|| # This code is released into public domain, in the hope that it # ||
 7+|| # will be useful, but without any warranty. # ||
 8+|| # ------------ YOU CAN DO WITH IT WHATEVER YOU LIKE! ------------- # ||
 9+|| #################################################################### ||
 10+\*======================================================================*/
 11+
 12+var asirra_js_failed = "Please correctly identify the cats.";
 13+var asirraform = document.forms[document.forms.length - 1];
 14+var submitButtonClicked = document.createElement("input");
 15+var passThroughFormSubmit = false;
 16+
 17+function PrepareSubmit()
 18+{
 19+ submitButtonClicked.type = "hidden";
 20+ var inputFields = asirraform.getElementsByTagName("input");
 21+ for (var i=0; i<inputFields.length; i++)
 22+ {
 23+ if (inputFields[i].type == "submit")
 24+ {
 25+ inputFields[i].onclick = function(event)
 26+ {
 27+ submitButtonClicked.name = this.name;
 28+ submitButtonClicked.value = this.value;
 29+ }
 30+ }
 31+ }
 32+
 33+ asirraform.onsubmit = function(event)
 34+ {
 35+ return MySubmitForm();
 36+ }
 37+}
 38+
 39+function MySubmitForm()
 40+{
 41+ if (passThroughFormSubmit)
 42+ {
 43+ return true;
 44+ }
 45+ Asirra_CheckIfHuman(HumanCheckComplete);
 46+ return false;
 47+}
 48+
 49+function HumanCheckComplete(isHuman)
 50+{
 51+ if (!isHuman)
 52+ {
 53+ alert(asirra_js_failed);
 54+ }
 55+ else
 56+ {
 57+ asirraform.appendChild(submitButtonClicked);
 58+ passThroughFormSubmit = true;
 59+ asirraform.submit();
 60+ }
 61+}
 62+
 63+contentLoaded(window,PrepareSubmit);
Index: trunk/extensions/ConfirmEdit/Asirra.class.php
@@ -0,0 +1,118 @@
 2+<?php
 3+/**
 4+ * @author Bachsau
 5+ */
 6+
 7+class Asirra extends SimpleCaptcha
 8+{
 9+ // Asirra URLs
 10+ public $asirra_localpath = '';
 11+ public $asirra_clientscript = 'http://challenge.asirra.com/js/AsirraClientSide.js';
 12+ public $asirra_apiscript = 'http://challenge.asirra.com/cgi/Asirra';
 13+
 14+ // As we don't have to store anything but some other things to do,
 15+ // we're going to replace that constructor completely.
 16+ function __construct()
 17+ {
 18+ global $wgScriptPath, $wgAsirraScriptPath;
 19+
 20+ // WTF isn't this in ConfirmEdit_body.php?
 21+ wfLoadExtensionMessages('ConfirmEdit');
 22+ wfLoadExtensionMessages('Asirra');
 23+
 24+ // Try to find $asirra_localpath if not set
 25+ if (!$this -> asirra_localpath = $wgAsirraScriptPath)
 26+ {
 27+ if (strpos(__FILE__, $_SERVER['DOCUMENT_ROOT']) === 0)
 28+ {
 29+ $this -> asirra_localpath = preg_replace('/^' . preg_quote($_SERVER['DOCUMENT_ROOT'], '/') . '(\\/*)/s', '/', dirname(__FILE__));
 30+ }
 31+ else
 32+ {
 33+ $this -> asirra_localpath = $wgScriptPath . '/extensions/ConfirmEdit';
 34+ }
 35+ }
 36+ }
 37+
 38+ function getForm()
 39+ {
 40+ global $wgAsirraEnlargedPosition, $wgAsirraCellsPerRow, $wgOut;
 41+
 42+ return '
 43+ <script type="text/javascript" src="' . $this -> asirra_clientscript . '"></script>
 44+ <script type="text/javascript" src="' . $this -> asirra_localpath . '/asirra_contentloaded.js"></script>
 45+ <script type="text/javascript" src="' . $this -> asirra_localpath . '/asirra_humanverify.js"></script>
 46+ <script type="text/javascript">
 47+ asirraState.SetEnlargedPosition("' . $wgAsirraEnlargedPosition . '");
 48+ asirraState.SetCellsPerRow(' . $wgAsirraCellsPerRow . ');
 49+ var asirra_js_failed = "' . $this -> getMessage('createaccount-fail') . '"
 50+ </script>
 51+ <noscript>' . $wgOut -> parse($this -> getMessage('nojs')) . '</noscript>
 52+ ';
 53+ }
 54+
 55+ function getMessage( $action )
 56+ {
 57+ $name = 'asirra-' . $action;
 58+ $text = wfMsg($name);
 59+ // Obtain a more tailored message, if possible, otherwise, fall back to
 60+ // the default for edits
 61+ return wfEmptyMsg($name, $text) ? wfMsg('asirra-edit') : $text;
 62+ }
 63+
 64+ // This is where the party goes on...
 65+ function passCaptcha()
 66+ {
 67+ global $wgRequest, $wgAsirra;
 68+
 69+ $ticket = $wgRequest -> getVal('Asirra_Ticket');
 70+ $url = $this -> asirra_apiscript . '?action=ValidateTicket&ticket=' . $ticket;
 71+
 72+ $ch = curl_init();
 73+ curl_setopt($ch, CURLOPT_URL, $url);
 74+ curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
 75+ curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 5);
 76+ $resultXml = curl_exec($ch);
 77+ curl_close($ch);
 78+
 79+ $xml_parser = xml_parser_create();
 80+ xml_set_element_handler($xml_parser, 'AsirraXmlParser::startElement', 'AsirraXmlParser::endElement');
 81+ xml_set_character_data_handler($xml_parser, 'AsirraXmlParser::characterData');
 82+ xml_parse($xml_parser, $resultXml, 1);
 83+ xml_parser_free($xml_parser);
 84+
 85+ if ($wgAsirra['passed'])
 86+ {
 87+ return true;
 88+
 89+ }
 90+ return false;
 91+ }
 92+}
 93+
 94+class AsirraXmlParser
 95+{
 96+ static function startElement($parser, $name, $attrs)
 97+ {
 98+ global $wgAsirra;
 99+
 100+ $wgAsirra['inResult'] = ($name=="RESULT");
 101+ }
 102+
 103+ static function endElement($name)
 104+ {
 105+ global $wgAsirra;
 106+
 107+ $wgAsirra['inResult'] = 0;
 108+ }
 109+
 110+ static function characterData($parer, $data)
 111+ {
 112+ global $wgAsirra;
 113+
 114+ if ($wgAsirra['inResult'] && $data == "Pass")
 115+ {
 116+ $wgAsirra['passed'] = 1;
 117+ }
 118+ }
 119+}

Follow-up revisions

Rev.Commit summaryAuthorDate
r91988Register new module from r91976 for Translatewikiraymond19:34, 12 July 2011
r96929Revert r91976: Adding new Asirra module to ConfirmEdit. Multiple issues point...demon00:04, 13 September 2011
r96931Revert r91976, r91977 in REL1_18reedy00:21, 13 September 2011
r105675Re-committing Asirra module after cleanup....nikerabbit16:10, 9 December 2011

Comments

#Comment by ^demon (Talk | contribs)   21:49, 22 July 2011
  • Should not use cURL directly, use the Http wrappers in MediaWiki
  • Passing data around via the global $wgAsirra isn't very elegant
  • The stuff with DOCUMENT_ROOT to determine asirra_localpath is kind of ugly and looks easily broken. Should just use $wgExtensionAssetsPath?
#Comment by Brion VIBBER (Talk | contribs)   21:56, 22 July 2011

The JavaScript looks like it can replace some bits with $.ready().

The 'asirra_localpath' thingy should not be using DOCUMENT_ROOT or $wgScriptPath, but rather $wgExtensionAssetsPath.

No escaping is done on data exported through JS vars -- danger!

#Comment by Bachsau (Talk | contribs)   22:56, 25 July 2011

I couldn't find any data which is exported through JS and input by a user, so that it would need escaping.

#Comment by Bachsau (Talk | contribs)   22:52, 25 July 2011

Thank you for commenting. Please note I'm doing this in my free time and updates are coming when I've time for it. When I started to code Asirra on 1.15 there was no $wgExtensionAssetsPath and I also tried to find information about http wrappers and even xml parsers in MediaWiki, but without success. Documentation on MediaWiki is horrible.

#Comment by ^demon (Talk | contribs)   22:59, 25 July 2011

The HTTP wrappers are in includes/HttpFunctions.php. You probably can just use Http::get().

Status & tagging log

  • 00:04, 13 September 2011 ^demon (Talk | contribs) changed the status of r91976 [removed: fixme added: reverted]
  • 21:49, 22 July 2011 ^demon (Talk | contribs) changed the status of r91976 [removed: new added: fixme]
Personal tools
Namespaces

Variants
Views
Actions
Navigation
Support
Download
Development
Communication
Toolbox