function loadData() { $oldSpec = $this->mParams[3]; $newSpec = $this->mParams[4]; $this->mFilter = $this->mParams[1]; if (AbuseFilter::filterHidden($this->mFilter) && !$this->getUser()->isAllowed('abusefilter-modify')) { $this->getOutput()->addWikiMsg('abusefilter-history-error-hidden'); return false; } $this->mOldVersion = $this->loadSpec($oldSpec, $newSpec); $this->mNewVersion = $this->loadSpec($newSpec, $oldSpec); if (is_null($this->mOldVersion) || is_null($this->mNewVersion)) { $this->getOutput()->addWikiMsg('abusefilter-diff-invalid'); return false; } return true; }
function loadSpec($spec, $otherSpec) { static $dependentSpecs = array('prev', 'next'); static $cache = array(); global $wgUser; if (AbuseFilter::filterHidden($this->mFilter) && !$wgUser->isAllowed('abusefilter-modify')) { return null; } if (isset($cache[$spec])) { return $cache[$spec]; } $dbr = wfGetDB(DB_SLAVE); if (is_numeric($spec)) { $row = $dbr->selectRow('abuse_filter_history', '*', array('afh_id' => $spec, 'afh_filter' => $this->mFilter), __METHOD__); } elseif ($spec == 'cur') { $row = $dbr->selectRow('abuse_filter_history', '*', array('afh_filter' => $this->mFilter), __METHOD__, array('ORDER BY' => 'afh_timestamp desc')); } elseif ($spec == 'prev' && !in_array($otherSpec, $dependentSpecs)) { // cached $other = $this->loadSpec($otherSpec, $spec); $row = $dbr->selectRow('abuse_filter_history', '*', array('afh_filter' => $this->mFilter, 'afh_id<' . $dbr->addQuotes($other['meta']['history_id'])), __METHOD__, array('ORDER BY' => 'afh_timestamp desc')); if ($other && !$row) { $t = $this->getTitle('history/' . $this->mFilter . '/item/' . $other['meta']['history_id']); global $wgOut; $wgOut->redirect($t->getFullURL()); return; } } elseif ($spec == 'next' && !in_array($otherSpec, $dependentSpecs)) { // cached $other = $this->loadSpec($otherSpec, $spec); $row = $dbr->selectRow('abuse_filter_history', '*', array('afh_filter' => $this->mFilter, 'afh_id>' . $dbr->addQuotes($other['meta']['history_id'])), __METHOD__, array('ORDER BY' => 'afh_timestamp DESC')); if ($other && !$row) { $t = $this->getTitle('history/' . $this->mFilter . '/item/' . $other['meta']['history_id']); global $wgOut; $wgOut->redirect($t->getFullURL()); return; } } if (!$row) { return null; } $data = $this->loadFromHistoryRow($row); $cache[$spec] = $data; return $data; }
function show() { global $wgRequest, $wgOut, $wgLang, $wgUser; $filter = $this->mFilter; if ($filter) { $wgOut->setPageTitle(wfMsg('abusefilter-history', $filter)); } else { $wgOut->setPageTitle(wfMsg('abusefilter-filter-log')); } # Check perms if ($filter && !$wgUser->isAllowed('abusefilter-modify') && AbuseFilter::filterHidden($filter)) { $wgOut->addWikiMsg('abusefilter-history-error-hidden'); return; } # Useful links $sk = $wgUser->getSkin(); $links = array(); if ($filter) { $links['abusefilter-history-backedit'] = $this->getTitle($filter); } foreach ($links as $msg => $title) { $links[$msg] = $sk->link($title, wfMsgExt($msg, 'parseinline')); } $backlinks = $wgLang->pipeList($links); $wgOut->addHTML(Xml::tags('p', null, $backlinks)); # For user $user = $wgRequest->getText('user'); if ($user) { $wgOut->setSubtitle(wfMsg('abusefilter-history-foruser', $sk->userLink(1, $user), $user)); } // Add filtering of changes et al. $fields['abusefilter-history-select-user'] = Xml::input('user', 45, $user); $filterForm = Xml::buildForm($fields, 'abusefilter-history-select-submit'); $filterForm .= "\n" . Xml::hidden('title', $this->getTitle("history/{$filter}")); $filterForm = Xml::tags('form', array('action' => $this->getTitle("history/{$filter}")->getLocalURL(), 'method' => 'get'), $filterForm); $filterForm = Xml::fieldset(wfMsg('abusefilter-history-select-legend'), $filterForm); $wgOut->addHTML($filterForm); $pager = new AbuseFilterHistoryPager($filter, $this, $user); $table = $pager->getBody(); $wgOut->addHTML($pager->getNavigationBar() . $table . $pager->getNavigationBar()); }
function show() { $out = $this->getOutput(); $filter = $this->mFilter; if ($filter) { $out->setPageTitle($this->msg('abusefilter-history', $filter)); } else { $out->setPageTitle($this->msg('abusefilter-filter-log')); } # Check perms if ($filter && !$this->getUser()->isAllowed('abusefilter-modify') && AbuseFilter::filterHidden($filter)) { $out->addWikiMsg('abusefilter-history-error-hidden'); return; } # Useful links $links = array(); if ($filter) { $links['abusefilter-history-backedit'] = $this->getTitle($filter); } foreach ($links as $msg => $title) { $links[$msg] = Linker::link($title, $this->msg($msg)->parse()); } $backlinks = $this->getLanguage()->pipeList($links); $out->addHTML(Xml::tags('p', null, $backlinks)); # For user $user = User::getCanonicalName($this->getRequest()->getText('user'), 'valid'); if ($user) { $out->addSubtitle($this->msg('abusefilter-history-foruser', Linker::userLink(1, $user), $user)->text()); } // Add filtering of changes et al. $fields['abusefilter-history-select-user'] = Xml::input('user', 45, $user); $filterForm = Xml::buildForm($fields, 'abusefilter-history-select-submit'); $filterForm .= "\n" . Html::hidden('title', $this->getTitle("history/{$filter}")); $filterForm = Xml::tags('form', array('action' => $this->getTitle("history/{$filter}")->getLocalURL(), 'method' => 'get'), $filterForm); $filterForm = Xml::fieldset($this->msg('abusefilter-history-select-legend')->text(), $filterForm); $out->addHTML($filterForm); $pager = new AbuseFilterHistoryPager($filter, $this, $user); $table = $pager->getBody(); $out->addHTML($pager->getNavigationBar() . $table . $pager->getNavigationBar()); }
public function execute() { $user = $this->getUser(); $errors = $this->getTitle()->getUserPermissionsErrors('abusefilter-log', $user); if (count($errors)) { $this->dieUsageMsg($errors[0]); return; } $params = $this->extractRequestParams(); $prop = array_flip($params['prop']); $fld_ids = isset($prop['ids']); $fld_filter = isset($prop['filter']); $fld_user = isset($prop['user']); $fld_ip = isset($prop['ip']); $fld_title = isset($prop['title']); $fld_action = isset($prop['action']); $fld_details = isset($prop['details']); $fld_result = isset($prop['result']); $fld_timestamp = isset($prop['timestamp']); $fld_hidden = isset($prop['hidden']); $fld_revid = isset($prop['revid']); if ($fld_ip && !$user->isAllowed('abusefilter-private')) { $this->dieUsage('You don\'t have permission to view IP addresses', 'permissiondenied'); } if ($fld_details && !$user->isAllowed('abusefilter-log-detail')) { $this->dieUsage('You don\'t have permission to view detailed abuse log entries', 'permissiondenied'); } // Match permissions for viewing events on private filters to SpecialAbuseLog (bug 42814) if ($params['filter'] && !(AbuseFilterView::canViewPrivate() || $user->isAllowed('abusefilter-log-private'))) { // A specific filter parameter is set but the user isn't allowed to view all filters if (!is_array($params['filter'])) { $params['filter'] = array($params['filter']); } foreach ($params['filter'] as $filter) { if (AbuseFilter::filterHidden($filter)) { $this->dieUsage('You don\'t have permission to view log entries for private filters', 'permissiondenied'); } } } $result = $this->getResult(); $this->addTables('abuse_filter_log'); $this->addFields('afl_timestamp'); $this->addFields('afl_rev_id'); $this->addFields('afl_deleted'); $this->addFields('afl_filter'); $this->addFieldsIf('afl_id', $fld_ids); $this->addFieldsIf('afl_user_text', $fld_user); $this->addFieldsIf('afl_ip', $fld_ip); $this->addFieldsIf(array('afl_namespace', 'afl_title'), $fld_title); $this->addFieldsIf('afl_action', $fld_action); $this->addFieldsIf('afl_var_dump', $fld_details); $this->addFieldsIf('afl_actions', $fld_result); if ($fld_filter) { $this->addTables('abuse_filter'); $this->addFields('af_public_comments'); $this->addJoinConds(array('abuse_filter' => array('LEFT JOIN', 'af_id=afl_filter'))); } $this->addOption('LIMIT', $params['limit'] + 1); $this->addWhereRange('afl_timestamp', $params['dir'], $params['start'], $params['end']); $db = $this->getDB(); $notDeletedCond = SpecialAbuseLog::getNotDeletedCond($db); if (isset($params['user'])) { $u = User::newFromName($params['user']); if ($u) { // Username normalisation $params['user'] = $u->getName(); $userId = $u->getId(); } elseif (IP::isIPAddress($params['user'])) { // It's an IP, sanitize it $params['user'] = IP::sanitizeIP($params['user']); $userId = 0; } if (isset($userId)) { // Only add the WHERE for user in case it's either a valid user (but not necessary an existing one) or an IP $this->addWhere(array('afl_user' => $userId, 'afl_user_text' => $params['user'])); } } $this->addWhereIf(array('afl_filter' => $params['filter']), isset($params['filter'])); $this->addWhereIf($notDeletedCond, !SpecialAbuseLog::canSeeHidden($user)); $title = $params['title']; if (!is_null($title)) { $titleObj = Title::newFromText($title); if (is_null($titleObj)) { $this->dieUsageMsg(array('invalidtitle', $title)); } $this->addWhereFld('afl_namespace', $titleObj->getNamespace()); $this->addWhereFld('afl_title', $titleObj->getDBkey()); } $res = $this->select(__METHOD__); $count = 0; foreach ($res as $row) { if (++$count > $params['limit']) { // We've had enough $ts = new MWTimestamp($row->afl_timestamp); $this->setContinueEnumParameter('start', $ts->getTimestamp(TS_ISO_8601)); break; } if (SpecialAbuseLog::isHidden($row) && !SpecialAbuseLog::canSeeHidden($user)) { continue; } $canSeeDetails = SpecialAbuseLog::canSeeDetails($row->afl_filter); $entry = array(); if ($fld_ids) { $entry['id'] = intval($row->afl_id); $entry['filter_id'] = ''; if ($canSeeDetails) { $entry['filter_id'] = $row->afl_filter; } } if ($fld_filter) { $entry['filter'] = $row->af_public_comments; } if ($fld_user) { $entry['user'] = $row->afl_user_text; } if ($fld_ip) { $entry['ip'] = $row->afl_ip; } if ($fld_title) { $title = Title::makeTitle($row->afl_namespace, $row->afl_title); ApiQueryBase::addTitleInfo($entry, $title); } if ($fld_action) { $entry['action'] = $row->afl_action; } if ($fld_result) { $entry['result'] = $row->afl_actions; } if ($fld_revid && !is_null($row->afl_rev_id)) { $entry['revid'] = ''; if ($canSeeDetails) { $entry['revid'] = $row->afl_rev_id; } } if ($fld_timestamp) { $ts = new MWTimestamp($row->afl_timestamp); $entry['timestamp'] = $ts->getTimestamp(TS_ISO_8601); } if ($fld_details) { $entry['details'] = array(); if ($canSeeDetails) { $vars = AbuseFilter::loadVarDump($row->afl_var_dump); if ($vars instanceof AbuseFilterVariableHolder) { $entry['details'] = $vars->exportAllVars(); } else { $entry['details'] = array_change_key_case($vars, CASE_LOWER); } } } if ($fld_hidden) { $val = SpecialAbuseLog::isHidden($row); if ($val) { $entry['hidden'] = $val; } } if ($entry) { $fit = $result->addValue(array('query', $this->getModuleName()), null, $entry); if (!$fit) { $ts = new MWTimestamp($row->afl_timestamp); $this->setContinueEnumParameter('start', $ts->getTimestamp(TS_ISO_8601)); break; } } } $result->setIndexedTagName_internal(array('query', $this->getModuleName()), 'item'); }
function buildFilterEditor($error, $filter, $history_id = null) { if ($filter === null) { return false; } // Build the edit form $out = $this->getOutput(); $lang = $this->getLanguage(); $user = $this->getUser(); $sk = $this->getSkin(); // Load from request OR database. list($row, $actions) = $this->loadRequest($filter, $history_id); if (!$row) { $out->addWikiMsg('abusefilter-edit-badfilter'); $out->addHTML($sk->link($this->getTitle(), wfMsg('abusefilter-return'))); return; } $out->setSubtitle(wfMsg('abusefilter-edit-subtitle', $filter, $history_id)); // Hide hidden filters. if ((isset($row->af_hidden) && $row->af_hidden || AbuseFilter::filterHidden($filter)) && !$this->canViewPrivate()) { return wfMsg('abusefilter-edit-denied'); } $output = ''; if ($error) { $out->addHTML("<span class=\"error\">{$error}</span>"); } // Read-only attribute $readOnlyAttrib = array(); $cbReadOnlyAttrib = array(); // For checkboxes if (!$this->canEdit()) { $readOnlyAttrib['readonly'] = 'readonly'; $cbReadOnlyAttrib['disabled'] = 'disabled'; } $fields = array(); $fields['abusefilter-edit-id'] = $this->mFilter == 'new' ? wfMsg('abusefilter-edit-new') : $lang->formatNum($filter); $fields['abusefilter-edit-description'] = Xml::input('wpFilterDescription', 45, isset($row->af_public_comments) ? $row->af_public_comments : '', $readOnlyAttrib); // Hit count display if (!empty($row->af_hit_count)) { $count = (int) $row->af_hit_count; $count_display = wfMsgExt('abusefilter-hitcount', array('parseinline'), $lang->formatNum($count)); $hitCount = $sk->makeKnownLinkObj(SpecialPage::getTitleFor('AbuseLog'), $count_display, 'wpSearchFilter=' . $row->af_id); $fields['abusefilter-edit-hitcount'] = $hitCount; } if ($filter !== 'new') { // Statistics global $wgMemc; $matches_count = $wgMemc->get(AbuseFilter::filterMatchesKey($filter)); $total = $wgMemc->get(AbuseFilter::filterUsedKey()); if ($total > 0) { $matches_percent = sprintf('%.2f', 100 * $matches_count / $total); list($timeProfile, $condProfile) = AbuseFilter::getFilterProfile($filter); $fields['abusefilter-edit-status-label'] = wfMsgExt('abusefilter-edit-status', array('parsemag', 'escape'), array($lang->formatNum($total), $lang->formatNum($matches_count), $lang->formatNum($matches_percent), $lang->formatNum($timeProfile), $lang->formatNum($condProfile))); } } $fields['abusefilter-edit-rules'] = AbuseFilter::buildEditBox($row->af_pattern, 'wpFilterRules', true, $this->canEdit()); $fields['abusefilter-edit-notes'] = Xml::textarea('wpFilterNotes', isset($row->af_comments) ? $row->af_comments . "\n" : "\n", 40, 5, $readOnlyAttrib); // Build checkboxen $checkboxes = array('hidden', 'enabled', 'deleted'); $flags = ''; global $wgAbuseFilterIsCentral; if ($wgAbuseFilterIsCentral) { $checkboxes[] = 'global'; } if (isset($row->af_throttled) && $row->af_throttled) { global $wgAbuseFilterEmergencyDisableThreshold; $threshold_percent = sprintf('%.2f', $wgAbuseFilterEmergencyDisableThreshold * 100); $flags .= $out->parse(wfMsg('abusefilter-edit-throttled', $lang->formatNum($threshold_percent))); } foreach ($checkboxes as $checkboxId) { $message = "abusefilter-edit-{$checkboxId}"; $dbField = "af_{$checkboxId}"; $postVar = 'wpFilter' . ucfirst($checkboxId); $checkbox = Xml::checkLabel(wfMsg($message), $postVar, $postVar, isset($row->{$dbField}) ? $row->{$dbField} : false, $cbReadOnlyAttrib); $checkbox = Xml::tags('p', null, $checkbox); $flags .= $checkbox; } $fields['abusefilter-edit-flags'] = $flags; $tools = ''; if ($filter != 'new' && $user->isAllowed('abusefilter-revert')) { $tools .= Xml::tags('p', null, $sk->link($this->getTitle('revert/' . $filter), wfMsg('abusefilter-edit-revert'))); } if ($filter != 'new') { // Test link $tools .= Xml::tags('p', null, $sk->link($this->getTitle("test/{$filter}"), wfMsgExt('abusefilter-edit-test-link', 'parseinline'))); // Last modification details $userLink = $sk->userLink($row->af_user, $row->af_user_text) . $sk->userToolLinks($row->af_user, $row->af_user_text); $userName = $row->af_user_text; $fields['abusefilter-edit-lastmod'] = wfMsgExt('abusefilter-edit-lastmod-text', array('parseinline', 'replaceafter'), array($lang->timeanddate($row->af_timestamp, true), $userLink, $lang->date($row->af_timestamp, true), $lang->time($row->af_timestamp, true), $userName)); $history_display = wfMsgExt('abusefilter-edit-viewhistory', array('parseinline')); $fields['abusefilter-edit-history'] = $sk->makeKnownLinkObj($this->getTitle('history/' . $filter), $history_display); } // Add export $exportText = json_encode(array('row' => $row, 'actions' => $actions)); $tools .= Xml::tags('a', array('href' => '#', 'id' => 'mw-abusefilter-export-link'), wfMsgExt('abusefilter-edit-export', 'parseinline')); $tools .= Xml::element('textarea', array('readonly' => 'readonly', 'id' => 'mw-abusefilter-export'), $exportText); $fields['abusefilter-edit-tools'] = $tools; $form = Xml::buildForm($fields); $form = Xml::fieldset(wfMsg('abusefilter-edit-main'), $form); $form .= Xml::fieldset(wfMsg('abusefilter-edit-consequences'), $this->buildConsequenceEditor($row, $actions)); if ($this->canEdit()) { $form .= Xml::submitButton(wfMsg('abusefilter-edit-save'), array('accesskey' => 's')); $form .= Html::hidden('wpEditToken', $user->getEditToken(array('abusefilter', $filter))); } $form = Xml::tags('form', array('action' => $this->getTitle($filter)->getFullURL(), 'method' => 'post'), $form); $output .= $form; return $output; }
/** * @param $filter_id null * @param $filter_hidden null * @return bool */ static function canSeeDetails($filter_id = null, $filter_hidden = null) { global $wgUser; if ($filter_id !== null) { if ($filter_hidden === null) { $filter_hidden = AbuseFilter::filterHidden($filter_id); } if ($filter_hidden) { return $wgUser->isAllowed('abusefilter-log-detail') && (AbuseFilterView::canViewPrivate() || $wgUser->isAllowed('abusefilter-log-private')); } } return $wgUser->isAllowed('abusefilter-log-detail'); }