r108778 MediaWiki - Code Review archive

Repository:MediaWiki
Revision:r108777‎ | r108778 | r108779 >
Date:23:16, 12 January 2012
Author:rsterbin
Status:resolved (Comments)
Tags:aft 
Comment:
Added spam and abuse filtering:
* NB: AbuseFilter setup tested with a simple filter using action=feedback.
* AbuseFilter consequences are not used.
* Existing AbuseFilter edit filters are not triggered on new feedback.
- ArticleFeedbackv5.i18n.php:
- Added messages 'articlefeedbackv5-error-abuse',
'articlefeedbackv5-error-abuse-linktext', and
'articlefeedbackv5-error-abuse-link'
- ArticleFeedbackv5.hooks.php:
- Updated module messages to include the new ones
- modules/jquery.articleFeedbackv5/jquery.articleFeedbackv5.js:
- Updated the error handler on submitForm() to create the abuse
feedback link
- ApiArticleFeedbackv5:
- Removed call to abuse stub from validateParam() and replaced it with
just the length check
- Removed method validateText()
- New method findAbuse()
- Added a call to findAbuse() immediately after param validation
Modified paths:
  • /trunk/extensions/ArticleFeedbackv5/ArticleFeedbackv5.hooks.php (modified) (history)
  • /trunk/extensions/ArticleFeedbackv5/ArticleFeedbackv5.i18n.php (modified) (history)
  • /trunk/extensions/ArticleFeedbackv5/api/ApiArticleFeedbackv5.php (modified) (history)
  • /trunk/extensions/ArticleFeedbackv5/modules/jquery.articleFeedbackv5/jquery.articleFeedbackv5.js (modified) (history)

Diff [purge]

Index: trunk/extensions/ArticleFeedbackv5/ArticleFeedbackv5.i18n.php
@@ -33,6 +33,9 @@
3434 'articlefeedbackv5-error' => 'An error has occured. Please try again later.',
3535 'articlefeedbackv5-error-email' => 'That e-mail address is not valid.',
3636 'articlefeedbackv5-error-validation' => 'Validation error.',
 37+ 'articlefeedbackv5-error-abuse' => 'Your comment violates the $1. Please revise it.',
 38+ 'articlefeedbackv5-error-abuse-linktext' => 'feedback abuse policy',
 39+ 'articlefeedbackv5-error-abuse-link' => '#', // TODO: Build page and set link here
3740 'articlefeedbackv5-error-unknown' => 'Unknown error.',
3841 'articlefeedbackv5-error-submit' => 'Form submission error.',
3942 'articlefeedbackv5-error-nofeedback' => 'Please enter your feedback.',
@@ -304,6 +307,9 @@
305308 'articlefeedbackv5-cta2-button-text' => 'The text for the button on the learn more CTA',
306309 'articlefeedbackv5-error' => 'This error message will be displayed in a grey box replacing the form if there was an unrecoverable error.',
307310 'articlefeedbackv5-error-nofeedback' => 'This error message will be displayed above the form (but below the title) if the user has attempted to submit a blank form.',
 311+ 'articlefeedbackv5-error-abuse' => 'This error message will be displayed above the form if the comment matched the spam or abuse filters. $1 is the link to the abuse policy.',
 312+ 'articlefeedbackv5-error-abuse-linktext' => 'The text for the abuse policy link.',
 313+ 'articlefeedbackv5-error-abuse-link' => 'The abuse policy link.',
308314 'articlefeedbackv5-form-tools-label' => '{{Identical|Tools}}',
309315 'articlefeedbackv5-special-filter-all' => '{{Identical|All}}',
310316 'articlefeedbackv5-special-more' => '{{Identical|More}}',
Index: trunk/extensions/ArticleFeedbackv5/modules/jquery.articleFeedbackv5/jquery.articleFeedbackv5.js
@@ -2571,6 +2571,12 @@
25722572 if ( 'error' in data ) {
25732573 if ( typeof( data.error ) == 'object' ) {
25742574 msg = data.error;
 2575+ } else if ( 'articlefeedbackv5-error-abuse' == data.error ) {
 2576+ msg = $.articleFeedbackv5.buildLink( data.error, {
 2577+ href: mw.msg( 'articleFeedbackv5-error-abuse-link' ),
 2578+ text: 'articleFeedbackv5-error-abuse-linktext',
 2579+ target: '_blank'
 2580+ });
25752581 } else {
25762582 msg = mw.msg( data.error );
25772583 }
Index: trunk/extensions/ArticleFeedbackv5/api/ApiArticleFeedbackv5.php
@@ -54,6 +54,7 @@
5555 'bucketId' => $bucket
5656 );
5757
 58+ // Validate the response data
5859 foreach ( $fields as $field ) {
5960 $field_name = $field['afi_name'];
6061 if ( $field['afi_bucket_id'] != $bucket ) {
@@ -65,34 +66,35 @@
6667 if ( $value === '' ) {
6768 continue;
6869 }
69 - if ( $this->validateParam( $value, $type, $field['afi_id'], $pageId ) ) {
70 - $data = array(
71 - 'aa_field_id' => $field['afi_id'],
72 - );
73 - foreach ( array( 'rating', 'text', 'boolean', 'option_id' ) as $t ) {
74 - $data["aa_response_$t"] = $t == $type ? $value : null;
75 - }
76 - $user_answers[] = $data;
77 - $email_data['ratingData'][$field_name] = $value;
78 - } else {
 70+ if ( !$this->validateParam( $value, $type, $field['afi_id'], $pageId ) ) {
7971 $error = 'articlefeedbackv5-error-validation';
 72+ break;
8073 }
 74+ if ( 'text' == $type && $this->findAbuse( $value, $pageId ) ) {
 75+ $error = 'articlefeedbackv5-error-abuse';
 76+ break;
 77+ }
 78+ $data = array( 'aa_field_id' => $field['afi_id'] );
 79+ foreach ( array( 'rating', 'text', 'boolean', 'option_id' ) as $t ) {
 80+ $data["aa_response_$t"] = $t == $type ? $value : null;
 81+ }
 82+ $user_answers[] = $data;
 83+ $email_data['ratingData'][$field_name] = $value;
8184 }
8285 }
83 -
8486 if ( $error ) {
85 - $this->getResult()->addValue(
86 - null, 'error', $error
87 - );
 87+ $this->getResult()->addValue( null, 'error', $error );
8888 return;
8989 }
 90+
 91+ // Save the response data
9092 $ratingIds = $this->saveUserRatings( $user_answers, $bucket, $params );
9193 $ctaId = $ratingIds['cta_id'];
9294 $feedbackId = $ratingIds['feedback_id'];
93 -
9495 $this->saveUserProperties( $feedbackId );
9596 $this->updateRollupTables( $pageId, $revisionId, $user_answers );
9697
 98+ // If we have an email address, capture it
9799 if ( $params['email'] ) {
98100 $this->captureEmail ( $params['email'], FormatJson::encode(
99101 $email_data
@@ -124,6 +126,12 @@
125127 );
126128 }
127129
 130+ /**
 131+ * Option 5 only: Capture the user's email address
 132+ *
 133+ * @param $email string the email address
 134+ * @param $json string the info to send with it, as JSON
 135+ */
128136 protected function captureEmail( $email, $json ) {
129137 # http://www.mediawiki.org/wiki/API:Calling_internally
130138 $params = new FauxRequest( array(
@@ -174,7 +182,15 @@
175183 }
176184 break;
177185 case 'text':
178 - return $this->validateText( $value, $pageId );
 186+ # Not actually a requirement, but I can see this being a thing,
 187+ # not letting people post the entire text of 1984 in a comment
 188+ # or something like that.
 189+ global $wgArticleFeedbackv5MaxCommentLength;
 190+ if ( $wgArticleFeedbackv5MaxCommentLength > 0
 191+ && strlen( $value ) > $wgArticleFeedbackv5MaxCommentLength ) {
 192+ return false;
 193+ }
 194+ return true;
179195 default:
180196 return false;
181197 }
@@ -182,38 +198,51 @@
183199 }
184200
185201 /**
186 - * Run the text through the AbuseFilter and SpamBlacklist extensions.
187 - * Should we check length as well? What's a reasonable max length?
 202+ * Check for abusive or spammy content
188203 *
 204+ * Check the following in sequence (cheapest processing to most expensive,
 205+ * returning if we get a hit):
 206+ * 1) Respect $wgSpamRegex
 207+ * 2) Check SpamBlacklist
 208+ * 3) Check AbuseFilter
 209+ *
 210+ * @param $value string the text to check
 211+ * @param $pageId int the page ID
189212 */
190 - private function validateText( &$value, $pageId ) {
191 - global $wgArticleFeedbackv5MaxCommentLength;
192 - $title = Title::newFromID( $pageId );
193 - $filter_error = 0; # TODO
194 - $spam_error = 0; # TODO
195 - $length_error = 0;
 213+ private function findAbuse( &$value, $pageId ) {
 214+ // Respect $wgSpamRegex
 215+ global $wgSpamRegex;
 216+ // In older versions, $wgSpamRegex may be a single string rather than
 217+ // an array of regexes, so make it compatible.
 218+ $regexes = ( array ) $wgSpamRegex;
 219+ foreach ( $regexes as $regex ) {
 220+ if ( preg_match( $regex, $value ) ) {
 221+ return true;
 222+ }
 223+ }
196224
197 - # Apparently this returns either true or an error message?
198 - # http://svn.wikimedia.org/viewvc/mediawiki/trunk/extensions/AbuseFilter/AbuseFilter.class.php?view=markup
199 - # (line 715-721). So normalize this.
200 - $vars = array(
201 - );
202 -# $filter_error = AbuseFilter::filterAction( $vars, $title );
203 -# $filter_error = ( $filter_error === true ? 1 : 0 );
 225+ // Create a fake title so we can pretend this is an article edit
 226+ $title = Title::newFromText( '__article_feedback_5__' );
204227
205 - # SpamBlacklist filtering goes here. (TODO)
206 -
207 - # Not actually a requirement, but I can see this being a thing,
208 - # not letting people post the entire text of 1984 in a comment
209 - # or something like that.
210 - if ( $wgArticleFeedbackv5MaxCommentLength > 0
211 - && strlen( $value ) > $wgArticleFeedbackv5MaxCommentLength ) {
212 - $length_error = 1;
 228+ // Check SpamBlacklist
 229+ $spam = wfSpamBlacklistObject();
 230+ $ret = $spam->filter( $title, $value, '' );
 231+ if ( $ret !== false ) {
 232+ return true;
213233 }
214234
215 - $has_error = $filter_error + $spam_error + $length_error;
216 -
217 - return $has_error ? false : true;
 235+ // Check the abuse filter
 236+ global $wgUser;
 237+ $vars = new AbuseFilterVariableHolder;
 238+ $vars->addHolder( AbuseFilter::generateUserVars( $wgUser ) );
 239+ $vars->addHolder( AbuseFilter::generateTitleVars( $title, 'FEEDBACK' ) );
 240+ $vars->setVar( 'SUMMARY', 'Article Feedback 5' );
 241+ $vars->setVar( 'ACTION', 'feedback' );
 242+ $vars->setVar( 'old_wikitext', '' );
 243+ $vars->setVar( 'new_wikitext', $value );
 244+ $vars->addHolder( AbuseFilter::getEditVars( $title ) );
 245+ $filter_result = AbuseFilter::filterAction( $vars, $title );
 246+ return $filter_result != '' && $filter_result !== true;
218247 }
219248
220249 /**
Index: trunk/extensions/ArticleFeedbackv5/ArticleFeedbackv5.hooks.php
@@ -62,6 +62,9 @@
6363 'articlefeedbackv5-error-unknown',
6464 'articlefeedbackv5-error-submit',
6565 'articlefeedbackv5-cta-thanks',
 66+ 'articlefeedbackv5-error-abuse',
 67+ 'articleFeedbackv5-error-abuse-link',
 68+ 'articleFeedbackv5-error-abuse-linktext',
6669 'articlefeedbackv5-cta-confirmation-followup',
6770 'articlefeedbackv5-cta1-confirmation-title',
6871 'articlefeedbackv5-cta1-confirmation-call',

Follow-up revisions

RevisionCommit summaryAuthorDate
r108812Do the , SpamBlacklist, and AbuseFilter checks only when those are set up (fo...rsterbin15:04, 13 January 2012
r110011Add FIXME comment about wfSpamBlacklistObject(), see r108778 CRcatrope18:31, 25 January 2012

Comments

#Comment by Reedy (talk | contribs)   23:21, 12 January 2012

You should probably conditionalise the usage of AbuseFilter (based on whether the classes exist).

Chances are someone is going to come along and want to use it on a wiki with no AbuseFilter

#Comment by Rsterbin (talk | contribs)   15:05, 13 January 2012

Good point, thanks. Fixed in r108812.

#Comment by Catrope (talk | contribs)   23:38, 24 January 2012
+		$spam = wfSpamBlacklistObject();

Where is this function defined? I can't find it anywhere.

#Comment by Rsterbin (talk | contribs)   01:22, 25 January 2012

It's in the SpamBlacklist extension. (Which is why I should have thought of doing what Reedy suggested.)

#Comment by Catrope (talk | contribs)   18:32, 25 January 2012

Ah, I see, it's in the 1.18wmf1 version of SpamBlacklist but not in the trunk version. Clarified in r110011

Status & tagging log