r38867 MediaWiki - Code Review archive

Repository:MediaWiki
Revision:r38866‎ | r38867 | r38868 >
Date:09:37, 8 August 2008
Author:werdna
Status:old
Tags:
Comment:
Abuse Filter:
* Add power operator.
* Add filter builder (very simple, just a drop-down box with commonly-used constructs)
Modified paths:
  • /trunk/extensions/AbuseFilter/AbuseFilter.i18n.php (modified) (history)
  • /trunk/extensions/AbuseFilter/SpecialAbuseFilter.php (modified) (history)
  • /trunk/extensions/AbuseFilter/edit.js (added) (history)
  • /trunk/extensions/AbuseFilter/parser_native/aftypes.cpp (modified) (history)
  • /trunk/extensions/AbuseFilter/parser_native/aftypes.h (modified) (history)
  • /trunk/extensions/AbuseFilter/parser_native/parser.cpp (modified) (history)

Diff [purge]

Index: trunk/extensions/AbuseFilter/edit.js
@@ -0,0 +1,47 @@
 2+function doSyntaxCheck()
 3+{
 4+ var filter = document.getElementById('wpFilterRules').value;
 5+ injectSpinner( document.getElementById( 'mw-abusefilter-syntaxcheck' ), 'abusefilter-syntaxcheck' );
 6+ sajax_do_call( 'AbuseFilter::ajaxCheckSyntax', [filter], processSyntaxResult );
 7+}
 8+function processSyntaxResult( request ) {
 9+ var response = request.responseText;
 10+
 11+ removeSpinner( 'abusefilter-syntaxcheck' );
 12+
 13+ if (response.match( /OK/ )) {
 14+ // Successful
 15+ jsMsg( 'No syntax errors.', 'mw-abusefilter-syntaxresult' );
 16+ } else {
 17+ var error = response.substr(4);
 18+ jsMsg( 'Syntax error: '+error, 'mw-abusefilter-syntaxresult' );
 19+ }
 20+}
 21+function addText() {
 22+ if (document.getElementById('wpFilterBuilder').selectedIndex == 0) {
 23+ return;
 24+ }
 25+
 26+ insertAtCursor(document.getElementById('wpFilterRules'), document.getElementById('wpFilterBuilder').value);
 27+ document.getElementById('wpFilterBuilder').selectedIndex = 0;
 28+}
 29+
 30+//From http://clipmarks.com/clipmark/CEFC94CB-94D6-4495-A7AA-791B7355E284/
 31+function insertAtCursor(myField, myValue) {
 32+ //IE support
 33+ if (document.selection) {
 34+ myField.focus();
 35+ sel = document.selection.createRange();
 36+ sel.text = myValue;
 37+ }
 38+ //MOZILLA/NETSCAPE support
 39+ else if (myField.selectionStart || myField.selectionStart == '0') {
 40+ var startPos = myField.selectionStart;
 41+ var endPos = myField.selectionEnd;
 42+ myField.value = myField.value.substring(0, startPos)
 43+ + myValue
 44+ + myField.value.substring(endPos, myField.value.length);
 45+ } else {
 46+ myField.value += myValue;
 47+ }
 48+}
\ No newline at end of file
Property changes on: trunk/extensions/AbuseFilter/edit.js
___________________________________________________________________
Added: svn:eol-style
149 + native
Index: trunk/extensions/AbuseFilter/parser_native/aftypes.cpp
@@ -201,6 +201,13 @@
202202 }
203203 };
204204
 205+template<typename T>
 206+struct afppower {
 207+ T operator() (T const &a, T const &b) const {
 208+ return std::pow(a,b);
 209+ }
 210+};
 211+
205212 /*
206213 * A visitor that performs an arithmetic operation on its arguments,
207214 * after doing appropriate int->double promotion.
@@ -343,6 +350,13 @@
344351 return datum(a) %= b;
345352 }
346353
 354+datum
 355+pow(datum const &a, datum const &b) {
 356+ datum result = datum(pow(a.toFloat(),b.toFloat()));
 357+
 358+ return result;
 359+}
 360+
347361 bool
348362 operator==(datum const &a, datum const &b) {
349363 return a.compare(b);
Index: trunk/extensions/AbuseFilter/parser_native/aftypes.h
@@ -110,6 +110,8 @@
111111 bool operator<=(datum const &a, datum const &b);
112112 bool operator>=(datum const &a, datum const &b);
113113
 114+datum pow(datum const &a, datum const &b);
 115+
114116 template<typename char_type, typename traits>
115117 std::basic_ostream<char_type, traits> &
116118 operator<<(std::basic_ostream<char_type, traits> &s, datum const &d) {
Index: trunk/extensions/AbuseFilter/parser_native/parser.cpp
@@ -166,6 +166,7 @@
167167 '*' >> in_expr[mult_expr.val *= arg1]
168168 | '/' >> in_expr[mult_expr.val /= arg1]
169169 | '%' >> in_expr[mult_expr.val %= arg1]
 170+ | "**" >> in_expr[mult_expr.val = bind(&afp::pow)(mult_expr.val,arg1)]
170171 )
171172 ;
172173
Index: trunk/extensions/AbuseFilter/AbuseFilter.i18n.php
@@ -139,6 +139,69 @@
140140 'abusefilter-edit-history' => 'History',
141141 'abusefilter-edit-check' => 'Check syntax',
142142
 143+ // Filter editing helpers
 144+ 'abusefilter-edit-builder-select' => 'Select an option to add it at the cursor',
 145+ 'abusefilter-edit-builder-group-op-arithmetic' => 'Arithmetic operators',
 146+ 'abusefilter-edit-builder-op-arithmetic-addition' => 'Addition (+)',
 147+ 'abusefilter-edit-builder-op-arithmetic-subtraction' => 'Subtraction (-)',
 148+ 'abusefilter-edit-builder-op-arithmetic-multiplication' => 'Multiplication (*)',
 149+ 'abusefilter-edit-builder-op-arithmetic-divide' => 'Division (/)',
 150+ 'abusefilter-edit-builder-op-arithmetic-modulo' => 'Modulo (%)',
 151+ 'abusefilter-edit-builder-op-arithmetic-pow' => 'Power (**)',
 152+ 'abusefilter-edit-builder-group-op-comparison' => 'Comparison operators',
 153+ 'abusefilter-edit-builder-op-comparison-equal' => 'Equal to (==)',
 154+ 'abusefilter-edit-builder-op-comparison-notequal' => 'Not equal to (!=)',
 155+ 'abusefilter-edit-builder-op-comparison-lt' => 'Less than (<)',
 156+ 'abusefilter-edit-builder-op-comparison-gt' => 'Greater than (>)',
 157+ 'abusefilter-edit-builder-op-comparison-lte' => 'Less than or equal to (<=)',
 158+ 'abusefilter-edit-builder-op-comparison-gte' => 'Greater than or equal to (>=)',
 159+ 'abusefilter-edit-builder-group-op-bool' => 'Boolean operators',
 160+ 'abusefilter-edit-builder-op-bool-not' => 'Not (!)',
 161+ 'abusefilter-edit-builder-op-bool-and' => 'And (&)',
 162+ 'abusefilter-edit-builder-op-bool-or' => 'Or (|)',
 163+ 'abusefilter-edit-builder-op-bool-xor' => 'XOR (^)',
 164+ 'abusefilter-edit-builder-group-misc' => 'Miscellaneous',
 165+ 'abusefilter-edit-builder-misc-ternery' => 'Ternery operator (1 ? 2 : 3)',
 166+ 'abusefilter-edit-builder-misc-in' => 'contained in string (in)',
 167+ 'abusefilter-edit-builder-misc-like' => 'Matches regex (like)',
 168+ 'abusefilter-edit-builder-group-funcs' => 'Functions',
 169+ 'abusefilter-edit-builder-funcs-length' => 'String length (length)',
 170+ 'abusefilter-edit-builder-funcs-lcase' => 'To lower case (lcase)',
 171+ 'abusefilter-edit-builder-funcs-ccnorm' => 'Normalise confusable characters (ccnorm)',
 172+ 'abusefilter-edit-builder-funcs-rmdoubles' => 'Remove double-characters (rmdoubles)',
 173+ 'abusefilter-edit-builder-funcs-specialratio' => 'Special ratio (specialratio)',
 174+ 'abusefilter-edit-builder-funcs-norm' => 'Normalise (norm)',
 175+ 'abusefilter-edit-builder-funcs-count' => 'Number of times string X appears in string Y (count)',
 176+ 'abusefilter-edit-builder-group-vars' => 'Variables',
 177+ 'abusefilter-edit-builder-vars-accountname' => 'Account name (on account creation)',
 178+ 'abusefilter-edit-builder-vars-action' => 'Action',
 179+ 'abusefilter-edit-builder-vars-addedlines' => 'Lines added in edit',
 180+ 'abusefilter-edit-builder-vars-delta' => 'Size change in edit',
 181+ 'abusefilter-edit-builder-vars-diff' => 'Unified diff of changes made by edit',
 182+ 'abusefilter-edit-builder-vars-newsize' => 'New page size',
 183+ 'abusefilter-edit-builder-vars-oldsize' => 'Old page size',
 184+ 'abusefilter-edit-builder-vars-removedlines' => 'Lines removed in edit',
 185+ 'abusefilter-edit-builder-vars-summary' => 'Edit summary/reason',
 186+ 'abusefilter-edit-builder-vars-article-id' => 'Article ID',
 187+ 'abusefilter-edit-builder-vars-article-ns' => 'Article namespace',
 188+ 'abusefilter-edit-builder-vars-article-text' => 'Article title (without namespace)',
 189+ 'abusefilter-edit-builder-vars-article-prefixedtext' => 'Full article title',
 190+ 'abusefilter-edit-builder-vars-movedfrom-id' => 'Article ID of move source page',
 191+ 'abusefilter-edit-builder-vars-movedfrom-ns' => 'Namespace of move source page',
 192+ 'abusefilter-edit-builder-vars-movedfrom-text' => 'Title of move source page',
 193+ 'abusefilter-edit-builder-vars-movedfrom-prefixedtext' => 'Full title of move source page',
 194+ 'abusefilter-edit-builder-vars-movedto-id' => 'Article ID of move destination page',
 195+ 'abusefilter-edit-builder-vars-movedto-ns' => 'Namespace of move destination page',
 196+ 'abusefilter-edit-builder-vars-movedto-text' => 'Title of move destination page',
 197+ 'abusefilter-edit-builder-vars-movedto-prefixedtext' => 'Full title of move destination page',
 198+ 'abusefilter-edit-builder-vars-user-editcount' => 'Edit count of user',
 199+ 'abusefilter-edit-builder-vars-user-age' => 'Age of user account',
 200+ 'abusefilter-edit-builder-vars-user-name' => 'Name of user account',
 201+ 'abusefilter-edit-builder-vars-user-groups' => 'Groups (including implicit) user is in',
 202+ 'abusefilter-edit-builder-vars-user-emailconfirm' => 'Time email address was confirmed',
 203+
 204+
 205+
143206 // Filter history
144207 'abusefilter-history' => 'History for filter $1',
145208 'abusefilter-history-hidden' => 'hidden',
Index: trunk/extensions/AbuseFilter/SpecialAbuseFilter.php
@@ -306,34 +306,8 @@
307307 );
308308 }
309309 }
310 -
311 - $rules = Xml::textarea( 'wpFilterRules', ( isset( $row->af_pattern ) ? $row->af_pattern."\n" : "\n" ) );
312 - $rules .= Xml::element( 'input', array( 'type' => 'button', 'onclick' => 'doSyntaxCheck()', 'value' => wfMsg( 'abusefilter-edit-check' ), 'id' => 'mw-abusefilter-syntaxcheck' ) );
313 -
314 - // Add syntax-checking script
315 - $scScript = "function doSyntaxCheck()
316 - {
317 - var filter = document.getElementById('wpFilterRules').value;
318 - injectSpinner( document.getElementById( 'mw-abusefilter-syntaxcheck' ), 'abusefilter-syntaxcheck' );
319 - sajax_do_call( 'AbuseFilter::ajaxCheckSyntax', [filter], processSyntaxResult );
320 - }
321 - function processSyntaxResult( request ) {
322 - var response = request.responseText;
323 -
324 - removeSpinner( 'abusefilter-syntaxcheck' );
325 -
326 - if (response.match( /OK/ )) {
327 - // Successful
328 - jsMsg( 'No syntax errors.', 'mw-abusefilter-syntaxresult' );
329 - } else {
330 - var error = response.substr(4);
331 - jsMsg( 'Syntax error: '+error, 'mw-abusefilter-syntaxresult' );
332 - }
333 - }";
334 -
335 - $wgOut->addInlineScript( $scScript );
336310
337 - $fields['abusefilter-edit-rules'] = $rules;
 311+ $fields['abusefilter-edit-rules'] = $this->buildEditBox($row);
338312 $fields['abusefilter-edit-notes'] = Xml::textarea( 'wpFilterNotes', ( isset( $row->af_comments ) ? $row->af_comments."\n" : "\n" ) );
339313
340314 // Build checkboxen
@@ -381,6 +355,48 @@
382356 return $output;
383357 }
384358
 359+ function buildEditBox( $row ) {
 360+ global $wgOut;
 361+
 362+ $rules = Xml::textarea( 'wpFilterRules', ( isset( $row->af_pattern ) ? $row->af_pattern."\n" : "\n" ) );
 363+
 364+ $dropDown = array(
 365+ 'op-arithmetic' => array('+' => 'addition', '-' => 'subtraction', '*' => 'multiplication', '/' => 'divide', '%' => 'modulo', '**' => 'pow'),
 366+ 'op-comparison' => array('==' => 'equal', '!=' => 'notequal', '<' => 'lt', '>' => 'gt', '<=' => 'lte', '>=' => 'gte'),
 367+ 'op-bool' => array( '!' => 'not', '&' => 'and', '|' => 'or', '^' => 'xor' ),
 368+ 'misc' => array( 'val1 ? iftrue : iffalse' => 'ternery', 'in' => 'in', 'like' => 'like' ),
 369+ 'funcs' => array( 'length(string)' => 'length', 'lcase(string)' => 'lcase', 'ccnorm(string)' => 'ccnorm', 'rmdoubles(string)' => 'rmdoubles', 'specialratio(string)' => 'specialratio', 'norm(string)' => 'norm', 'count(needle,haystack)' => 'count' ),
 370+ 'vars' => array( 'ACCOUNTNAME' => 'accountname', 'ACTION' => 'action', 'ADDED_LINES' => 'addedlines', 'EDIT_DELTA' => 'delta', 'EDIT_DIFF' => 'diff', 'NEW_SIZE' => 'newsize', 'OLD_SIZE' => 'oldsize', 'REMOVED_LINES' => 'removedlines', 'SUMMARY' => 'summary', 'ARTICLE_ARTICLEID' => 'article-id', 'ARTICLE_NAMESPACE' => 'article-ns', 'ARTICLE_TEXT' => 'article-text', 'ARTICLE_PREFIXEDTEXT' => 'article-prefixedtext', 'MOVED_FROM_ARTICLEID' => 'movedfrom-id', 'MOVED_FROM_NAMESPACE' => 'movedfrom-ns', 'MOVED_FROM_TEXT' => 'movedfrom-text', 'MOVED_FROM_PREFIXEDTEXT' => 'movedfrom-prefixedtext', 'MOVED_TO_ARTICLEID' => 'movedto-id', 'MOVED_TO_NAMESPACE' => 'movedto-ns', 'MOVED_TO_TEXT' => 'movedto-text', 'MOVED_TO_PREFIXEDTEXT' => 'movedto-prefixedtext', 'USER_EDITCOUNT' => 'user-editcount', 'USER_AGE' => 'user-age', 'USER_NAME' => 'user-name', 'USER_GROUPS' => 'user-groups', 'USER_EMAILCONFIRM' => 'user-emailconfirm'),
 371+ );
 372+
 373+ // Generate builder drop-down
 374+ $builder = '';
 375+
 376+ $builder .= Xml::option( wfMsg( "abusefilter-edit-builder-select") );
 377+
 378+ foreach( $dropDown as $group => $values ) {
 379+ $builder .= Xml::openElement( 'optgroup', array( 'label' => wfMsg( "abusefilter-edit-builder-group-$group" ) ) ) . "\n";
 380+
 381+ foreach( $values as $content => $name ) {
 382+ $builder .= Xml::option( wfMsg( "abusefilter-edit-builder-$group-$name" ), $content ) . "\n";
 383+ }
 384+
 385+ $builder .= Xml::closeElement( 'optgroup' ) . "\n";
 386+ }
 387+
 388+ $rules .= Xml::tags( 'select', array( 'id' => 'wpFilterBuilder', 'onchange' => 'addText();' ), $builder );
 389+
 390+ // Add syntax checking
 391+ $rules .= Xml::element( 'input', array( 'type' => 'button', 'onclick' => 'doSyntaxCheck()', 'value' => wfMsg( 'abusefilter-edit-check' ), 'id' => 'mw-abusefilter-syntaxcheck' ) );
 392+
 393+ // Add script
 394+ $scScript = file_get_contents(dirname(__FILE__)."/edit.js");
 395+
 396+ $wgOut->addInlineScript( $scScript );
 397+
 398+ return $rules;
 399+ }
 400+
385401 function buildConsequenceEditor( $row, $actions ) {
386402 global $wgAbuseFilterAvailableActions;
387403 $setActions = array();

Status & tagging log