2008-06-27 06:18:51 +00:00
|
|
|
<?php
|
|
|
|
if ( ! defined( 'MEDIAWIKI' ) )
|
|
|
|
die();
|
|
|
|
|
|
|
|
class SpecialAbuseLog extends SpecialPage {
|
|
|
|
|
|
|
|
function __construct() {
|
|
|
|
wfLoadExtensionMessages('AbuseFilter');
|
|
|
|
parent::__construct( 'AbuseLog', 'abusefilter-log' );
|
|
|
|
}
|
|
|
|
|
|
|
|
function execute( $parameter ) {
|
|
|
|
global $wgUser,$wgOut,$wgRequest;
|
|
|
|
|
|
|
|
$this->setHeaders();
|
|
|
|
$this->loadParameters();
|
|
|
|
|
|
|
|
$wgOut->setPageTitle( wfMsg( 'abusefilter-log' ) );
|
2008-07-23 19:33:28 +00:00
|
|
|
$wgOut->setRobotPolicy( "noindex,nofollow" );
|
2008-06-27 06:18:51 +00:00
|
|
|
$wgOut->setArticleRelated( false );
|
|
|
|
$wgOut->enableClientCache( false );
|
2009-01-26 19:23:27 +00:00
|
|
|
|
|
|
|
global $wgScriptPath;
|
|
|
|
$wgOut->addExtensionStyle( $wgScriptPath."/extensions/AbuseFilter/abusefilter.css" );
|
2008-06-27 06:18:51 +00:00
|
|
|
|
|
|
|
// Are we allowed?
|
|
|
|
if ( count( $errors = $this->getTitle()->getUserPermissionsErrors( 'abusefilter-log', $wgUser, true, array( 'ns-specialprotected' ) ) ) ) {
|
|
|
|
// Go away.
|
|
|
|
$wgOut->showPermissionsErrorPage( $errors, 'abusefilter-log' );
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Show the search form.
|
|
|
|
$this->searchForm();
|
|
|
|
|
|
|
|
// Show the log itself.
|
|
|
|
$this->showList();
|
|
|
|
}
|
|
|
|
|
|
|
|
function loadParameters() {
|
|
|
|
global $wgRequest;
|
|
|
|
|
|
|
|
$this->mSearchUser = $wgRequest->getText( 'wpSearchUser' );
|
|
|
|
$this->mSearchTitle = $wgRequest->getText( 'wpSearchTitle' );
|
|
|
|
if ($this->canSeeDetails())
|
|
|
|
$this->mSearchFilter = $wgRequest->getIntOrNull( 'wpSearchFilter' );
|
|
|
|
|
|
|
|
$detailsid = $wgRequest->getIntOrNull( 'details' );
|
|
|
|
|
|
|
|
if ($detailsid) {
|
|
|
|
$this->showDetails( $detailsid );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
function searchForm() {
|
|
|
|
global $wgOut, $wgUser;
|
|
|
|
|
|
|
|
$output = Xml::element( 'legend', null, wfMsg( 'abusefilter-log-search' ) );
|
|
|
|
$fields = array();
|
|
|
|
|
|
|
|
// Search conditions
|
2008-12-20 09:32:47 +00:00
|
|
|
$fields['abusefilter-log-search-user'] = Xml::input( 'wpSearchUser', 45, $this->mSearchUser );
|
2008-06-27 06:18:51 +00:00
|
|
|
if ($this->canSeeDetails())
|
2008-12-20 09:32:47 +00:00
|
|
|
$fields['abusefilter-log-search-filter'] = Xml::input( 'wpSearchFilter', 45, $this->mSearchFilter );
|
|
|
|
$fields['abusefilter-log-search-title'] = Xml::input( 'wpSearchTitle', 45, $this->mSearchTitle );
|
2008-06-27 06:18:51 +00:00
|
|
|
|
|
|
|
$form = Xml::hidden( 'title', $this->getTitle()->getPrefixedText() );
|
|
|
|
|
|
|
|
$form .= Xml::buildForm( $fields, 'abusefilter-log-search-submit' );
|
|
|
|
$output .= Xml::tags( 'form', array( 'method' => 'GET', 'action' => $this->getTitle()->getLocalURL() ), $form );
|
|
|
|
$output = Xml::tags( 'fieldset', null, $output );
|
|
|
|
|
2008-11-06 22:20:29 +00:00
|
|
|
$wgOut->addHTML( $output );
|
2008-06-27 06:18:51 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
function showList() {
|
|
|
|
global $wgOut;
|
|
|
|
|
|
|
|
// Generate conditions list.
|
|
|
|
$conds = array();
|
|
|
|
|
2008-09-18 13:33:39 +00:00
|
|
|
if (!empty($this->mSearchUser))
|
2008-06-27 06:18:51 +00:00
|
|
|
$conds['afl_user_text'] = $this->mSearchUser;
|
2008-09-18 13:33:39 +00:00
|
|
|
if (!empty($this->mSearchFilter))
|
2008-06-27 06:18:51 +00:00
|
|
|
$conds['afl_filter'] = $this->mSearchFilter;
|
|
|
|
|
|
|
|
$searchTitle = Title::newFromText( $this->mSearchTitle );
|
|
|
|
if ($this->mSearchTitle && $searchTitle) {
|
|
|
|
$conds['afl_namespace'] = $searchTitle->getNamespace();
|
2008-11-06 22:38:42 +00:00
|
|
|
$conds['afl_title'] = $searchTitle->getDBKey();
|
2008-06-27 06:18:51 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
$pager = new AbuseLogPager( $this, $conds );
|
|
|
|
|
2008-11-06 22:20:29 +00:00
|
|
|
$wgOut->addHTML( $pager->getNavigationBar() .
|
2008-06-27 06:18:51 +00:00
|
|
|
Xml::tags( 'ul', null, $pager->getBody() ) .
|
|
|
|
$pager->getNavigationBar() );
|
|
|
|
}
|
|
|
|
|
|
|
|
function showDetails( $id ) {
|
|
|
|
if (!$this->canSeeDetails()) {
|
|
|
|
return;
|
|
|
|
}
|
2009-01-26 19:23:27 +00:00
|
|
|
|
|
|
|
// I don't want to change the names of the pre-existing messages
|
|
|
|
// describing the variables, nor do I want to rewrite them, so I'm just
|
|
|
|
// mapping the variable names to builder messages with a pre-existing array.
|
|
|
|
$variableMessageMappings = 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', 'ARTICLE_RECENT_CONTRIBUTORS' => 'recent-contributors', 'ALL_LINKS' => 'all-links', 'ADDED_LINKS' => 'added-links', 'REMOVED_LINKS' => 'removed-links');
|
2008-06-27 06:18:51 +00:00
|
|
|
|
|
|
|
$dbr = wfGetDB( DB_SLAVE );
|
|
|
|
|
|
|
|
$row = $dbr->selectRow( array('abuse_filter_log','abuse_filter'), '*', array( 'afl_id' => $id, 'af_id=afl_filter' ), __METHOD__ );
|
|
|
|
|
|
|
|
if (!$row)
|
|
|
|
return;
|
|
|
|
|
|
|
|
$output = '';
|
|
|
|
|
|
|
|
$output .= Xml::element( 'legend', null, wfMsg( 'abusefilter-log-details-legend', $id ) );
|
2008-10-21 15:14:30 +00:00
|
|
|
$output .= Xml::tags( 'p', null, $this->formatRow( $row, false ) );
|
2008-06-27 06:18:51 +00:00
|
|
|
$output .= Xml::element( 'h3', null, wfMsg( 'abusefilter-log-details-vars' ) );
|
|
|
|
|
|
|
|
// Build a table.
|
|
|
|
$vars = unserialize( $row->afl_var_dump );
|
|
|
|
|
2009-01-26 19:23:27 +00:00
|
|
|
$output .= Xml::openElement( 'table', array( 'class' => 'mw-abuselog-details', 'style' => "width: 80%;" ) ) . Xml::openElement( 'tbody' );
|
2008-06-27 06:18:51 +00:00
|
|
|
|
|
|
|
$header = Xml::element( 'th', null, wfMsg( 'abusefilter-log-details-var' ) ) . Xml::element( 'th', null, wfMsg( 'abusefilter-log-details-val' ) );
|
|
|
|
$output .= Xml::tags( 'tr', null, $header );
|
|
|
|
|
|
|
|
// Now, build the body of the table.
|
|
|
|
foreach( $vars as $key => $value ) {
|
2009-01-26 19:23:27 +00:00
|
|
|
if ( !empty($variableMessageMappings[$key]) ) {
|
|
|
|
$mapping = $variableMessageMappings[$key];
|
|
|
|
$keyDisplay = wfMsgExt( "abusefilter-edit-builder-vars-$mapping", 'parseinline' ) . ' (' . Xml::element( 'tt', null, $key ) . ')';
|
|
|
|
} else {
|
|
|
|
$keyDisplay = Xml::element( 'tt', null, $key );
|
|
|
|
}
|
|
|
|
|
|
|
|
$trow = Xml::tags( 'td', array( 'class' => 'mw-abuselog-var', 'style' => 'width: 30%;' ), $keyDisplay ) . Xml::element( 'td', array( 'class' => 'mw-abuselog-var-value', 'style' => "white-space: pre; font-family: monospace;" ), $value );
|
2008-07-17 13:40:45 +00:00
|
|
|
$output .= Xml::tags( 'tr', array( 'class' => "mw-abuselog-details-$key" ), $trow );
|
2008-06-27 06:18:51 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
$output .= Xml::closeElement( 'tbody' ) . Xml::closeElement( 'table' );
|
|
|
|
|
2008-06-27 08:11:09 +00:00
|
|
|
if ($this->canSeePrivate()) {
|
|
|
|
// Private stuff, like IPs.
|
|
|
|
$output .= Xml::element( 'h3', null, wfMsg( 'abusefilter-log-details-private' ) );
|
2008-07-17 13:40:45 +00:00
|
|
|
$output .= Xml::openElement( 'table', array( 'class' => 'wikitable mw-abuselog-private', 'style' => "width: 80%;" ) ) . Xml::openElement( 'tbody' );
|
2008-06-27 08:11:09 +00:00
|
|
|
$output .= $header;
|
|
|
|
|
|
|
|
// IP address
|
2008-07-17 13:40:45 +00:00
|
|
|
$output .= Xml::tags( 'tr', null, Xml::element( 'td', array( 'style' => 'width: 30%;' ), wfMsg('abusefilter-log-details-ip' ) ) . Xml::element( 'td', null, $row->afl_ip ) );
|
2008-06-27 08:11:09 +00:00
|
|
|
|
|
|
|
$output .= Xml::closeElement( 'tbody' ) . Xml::closeElement( 'table' );
|
|
|
|
}
|
2008-06-27 06:18:51 +00:00
|
|
|
|
|
|
|
$output = Xml::tags( 'fieldset', null, $output );
|
|
|
|
|
|
|
|
global $wgOut;
|
|
|
|
$wgOut->addHTML( $output );
|
|
|
|
}
|
|
|
|
|
|
|
|
function canSeeDetails() {
|
|
|
|
global $wgUser;
|
|
|
|
return !count($this->getTitle()->getUserPermissionsErrors( 'abusefilter-log-detail', $wgUser, true, array( 'ns-specialprotected' ) ));
|
|
|
|
}
|
|
|
|
|
2008-06-27 08:11:09 +00:00
|
|
|
function canSeePrivate() {
|
|
|
|
global $wgUser;
|
|
|
|
return !count($this->getTitle()->getUserPermissionsErrors( 'abusefilter-private', $wgUser, true, array( 'ns-specialprotected' ) ));
|
|
|
|
}
|
|
|
|
|
2008-10-21 15:14:30 +00:00
|
|
|
function formatRow( $row, $li = true ) {
|
2008-06-27 06:18:51 +00:00
|
|
|
global $wgLang,$wgUser;
|
|
|
|
|
|
|
|
## One-time setup
|
|
|
|
static $sk=null;
|
|
|
|
|
|
|
|
if (is_null($sk)) {
|
|
|
|
$sk = $wgUser->getSkin();
|
|
|
|
}
|
|
|
|
|
|
|
|
$title = Title::makeTitle( $row->afl_namespace, $row->afl_title );
|
|
|
|
|
|
|
|
$user = $sk->userLink( $row->afl_user, $row->afl_user_text ) .
|
|
|
|
$sk->userToolLinks( $row->afl_user, $row->afl_user_text );
|
|
|
|
|
|
|
|
$description = '';
|
|
|
|
|
|
|
|
$timestamp = $wgLang->timeanddate( $row->afl_timestamp );
|
|
|
|
|
|
|
|
$actions_taken = $row->afl_actions;
|
|
|
|
if (!strlen(trim($actions_taken))) {
|
|
|
|
$actions_taken = wfMsg( 'abusefilter-log-noactions' );
|
|
|
|
}
|
|
|
|
|
|
|
|
if ($this->canSeeDetails()) {
|
|
|
|
$detailsLink = $sk->makeKnownLinkObj( $this->getTitle( ), wfMsg( 'abusefilter-log-detailslink' ), 'details='.$row->afl_id );
|
|
|
|
|
2008-10-21 13:43:05 +00:00
|
|
|
$description = wfMsgExt( 'abusefilter-log-detailedentry', array( 'parseinline', 'replaceafter' ), array( $timestamp, $user, $row->afl_filter, $row->afl_action, $sk->makeKnownLinkObj( $title ), $actions_taken, $row->af_public_comments, $detailsLink ) );
|
2008-06-27 06:18:51 +00:00
|
|
|
} else {
|
2008-10-21 13:43:05 +00:00
|
|
|
$description = wfMsgExt( 'abusefilter-log-entry', array( 'parseinline', 'replaceafter' ), array( $timestamp, $user, $row->afl_action, $sk->makeKnownLinkObj( $title ), $actions_taken, $row->af_public_comments ) );
|
2008-06-27 06:18:51 +00:00
|
|
|
}
|
|
|
|
|
2008-10-21 15:14:30 +00:00
|
|
|
return $li ? Xml::tags( 'li', null, $description ) : $description;
|
2008-06-27 06:18:51 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
class AbuseLogPager extends ReverseChronologicalPager {
|
|
|
|
public $mForm, $mConds;
|
|
|
|
|
|
|
|
function __construct( $form, $conds = array(), $details = false ) {
|
|
|
|
$this->mForm = $form;
|
|
|
|
$this->mConds = $conds;
|
|
|
|
parent::__construct();
|
|
|
|
}
|
|
|
|
|
|
|
|
function formatRow( $row ) {
|
|
|
|
return $this->mForm->formatRow( $row );
|
|
|
|
}
|
|
|
|
|
|
|
|
function getQueryInfo() {
|
|
|
|
$conds = $this->mConds;
|
|
|
|
|
|
|
|
$conds[] = 'af_id=afl_filter';
|
|
|
|
|
|
|
|
return array(
|
|
|
|
'tables' => array('abuse_filter_log','abuse_filter'),
|
|
|
|
'fields' => '*',
|
|
|
|
'conds' => $conds,
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
function getIndexField() {
|
|
|
|
return 'afl_timestamp';
|
|
|
|
}
|
2008-12-20 09:32:47 +00:00
|
|
|
}
|