function showStatus() { global $wgMemc, $wgAbuseFilterConditionLimit, $wgOut, $wgLang; $overflow_count = (int) $wgMemc->get(AbuseFilter::filterLimitReachedKey()); $match_count = (int) $wgMemc->get(AbuseFilter::filterMatchesKey()); $total_count = (int) $wgMemc->get(AbuseFilter::filterUsedKey()); if ($total_count > 0) { $overflow_percent = sprintf("%.2f", 100 * $overflow_count / $total_count); $match_percent = sprintf("%.2f", 100 * $match_count / $total_count); $status = wfMsgExt('abusefilter-status', array('parseinline'), $wgLang->formatNum($total_count), $wgLang->formatNum($overflow_count), $wgLang->formatNum($overflow_percent), $wgLang->formatNum($wgAbuseFilterConditionLimit), $wgLang->formatNum($match_count), $wgLang->formatNum($match_percent)); $status = Xml::tags('div', array('class' => 'mw-abusefilter-status'), $status); $wgOut->addHTML($status); } }
function showStatus() { global $wgMemc, $wgAbuseFilterConditionLimit, $wgAbuseFilterValidGroups; $overflow_count = (int) $wgMemc->get(AbuseFilter::filterLimitReachedKey()); $match_count = (int) $wgMemc->get(AbuseFilter::filterMatchesKey()); $total_count = 0; foreach ($wgAbuseFilterValidGroups as $group) { $total_count += (int) $wgMemc->get(AbuseFilter::filterUsedKey($group)); } if ($total_count > 0) { $overflow_percent = sprintf("%.2f", 100 * $overflow_count / $total_count); $match_percent = sprintf("%.2f", 100 * $match_count / $total_count); $status = $this->msg('abusefilter-status')->numParams($total_count, $overflow_count, $overflow_percent, $wgAbuseFilterConditionLimit, $match_count, $match_percent)->parse(); $status = Xml::tags('div', array('class' => 'mw-abusefilter-status'), $status); $this->getOutput()->addHTML($status); } }
/** * @param $actions_taken * @param $log_template * @param $action * @param $vars AbuseFilterVariableHolder * @param string $group * @return mixed */ public static function addLogEntries($actions_taken, $log_template, $action, $vars, $group = 'default') { wfProfileIn(__METHOD__); $dbw = wfGetDB(DB_MASTER); $central_log_template = array('afl_wiki' => wfWikiID()); $log_rows = array(); $central_log_rows = array(); $logged_local_filters = array(); $logged_global_filters = array(); foreach ($actions_taken as $filter => $actions) { $globalIndex = self::decodeGlobalName($filter); $thisLog = $log_template; $thisLog['afl_filter'] = $filter; $thisLog['afl_action'] = $action; $thisLog['afl_actions'] = implode(',', $actions); // Don't log if we were only throttling. if ($thisLog['afl_actions'] != 'throttle') { $log_rows[] = $thisLog; if (!$globalIndex) { $logged_local_filters[] = $filter; } // Global logging if ($globalIndex) { $title = Title::makeTitle($thisLog['afl_namespace'], $thisLog['afl_title']); $centralLog = $thisLog + $central_log_template; $centralLog['afl_filter'] = $globalIndex; $centralLog['afl_title'] = $title->getPrefixedText(); $centralLog['afl_namespace'] = 0; $central_log_rows[] = $centralLog; $logged_global_filters[] = $globalIndex; } } } if (!count($log_rows)) { wfProfileOut(__METHOD__); return; } // Only store the var dump if we're actually going to add log rows. $var_dump = self::storeVarDump($vars); $var_dump = "stored-text:{$var_dump}"; // To distinguish from stuff stored directly wfProfileIn(__METHOD__ . '-hitstats'); global $wgMemc; // Increment trigger counter $wgMemc->incr(self::filterMatchesKey()); $local_log_ids = array(); global $wgAbuseFilterNotifications, $wgAbuseFilterNotificationsPrivate; foreach ($log_rows as $data) { $data['afl_var_dump'] = $var_dump; $data['afl_id'] = $dbw->nextSequenceValue('abuse_filter_log_afl_id_seq'); $dbw->insert('abuse_filter_log', $data, __METHOD__); $local_log_ids[] = $dbw->insertId(); if ($data['afl_id'] === null) { $data['afl_id'] = $dbw->insertId(); } $entry = new ManualLogEntry('abusefilter', 'hit'); // Construct a user object $user = User::newFromId($data['afl_user']); $user->setName($data['afl_user_text']); $entry->setPerformer($user); // Set action target $entry->setTarget(Title::makeTitle($data['afl_namespace'], $data['afl_title'])); // Additional info $entry->setParameters(array('action' => $data['afl_action'], 'filter' => $data['afl_filter'], 'actions' => $data['afl_actions'], 'log' => $data['afl_id'])); // Send data to CheckUser if installed and we // aren't already sending a notification to recentchanges // Requires MW 1.23+ if (is_callable('CheckUserHooks::updateCheckUserData') && is_callable('ManualLogEntry::getRecentChange') && strpos($wgAbuseFilterNotifications, 'rc') === false) { $rc = $entry->getRecentChange(); CheckUserHooks::updateCheckUserData($rc); } if ($wgAbuseFilterNotifications !== false) { if (self::filterHidden($data['afl_filter']) && !$wgAbuseFilterNotificationsPrivate) { continue; } $entry->publish(0, $wgAbuseFilterNotifications); } } $method = __METHOD__; if (count($logged_local_filters)) { // Update hit-counter. $dbw->onTransactionPreCommitOrIdle(function () use($dbw, $logged_local_filters, $method) { $dbw->update('abuse_filter', array('af_hit_count=af_hit_count+1'), array('af_id' => $logged_local_filters), $method); }); } $global_log_ids = array(); // Global stuff if (count($logged_global_filters)) { $vars->computeDBVars(); $global_var_dump = self::storeVarDump($vars, true); $global_var_dump = "stored-text:{$global_var_dump}"; foreach ($central_log_rows as $index => $data) { $central_log_rows[$index]['afl_var_dump'] = $global_var_dump; } global $wgAbuseFilterCentralDB; $fdb = wfGetDB(DB_MASTER, array(), $wgAbuseFilterCentralDB); foreach ($central_log_rows as $row) { $fdb->insert('abuse_filter_log', $row, __METHOD__); $global_log_ids[] = $dbw->insertId(); } $fdb->onTransactionPreCommitOrIdle(function () use($fdb, $logged_global_filters, $method) { $fdb->update('abuse_filter', array('af_hit_count=af_hit_count+1'), array('af_id' => $logged_global_filters), $method); }); } $vars->setVar('global_log_ids', $global_log_ids); $vars->setVar('local_log_ids', $local_log_ids); // Check for emergency disabling. $total = $wgMemc->get(AbuseFilter::filterUsedKey($group)); self::checkEmergencyDisable($group, $logged_local_filters, $total); wfProfileOut(__METHOD__ . '-hitstats'); wfProfileOut(__METHOD__); }
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; }
public static function addLogEntries($actions_taken, $log_template, $action, $vars) { wfProfileIn(__METHOD__); $dbw = wfGetDB(DB_MASTER); $central_log_template = array('afl_wiki' => wfWikiID()); $log_rows = array(); $central_log_rows = array(); $logged_local_filters = array(); $logged_global_filters = array(); foreach ($actions_taken as $filter => $actions) { $globalIndex = self::decodeGlobalName($filter); $thisLog = $log_template; $thisLog['afl_filter'] = $filter; $thisLog['afl_action'] = $action; $thisLog['afl_actions'] = implode(',', $actions); // Don't log if we were only throttling. if ($thisLog['afl_actions'] != 'throttle') { $log_rows[] = $thisLog; if (!$globalIndex) { $logged_local_filters[] = $filter; } // Global logging if ($globalIndex) { $title = Title::makeTitle($thisLog['afl_namespace'], $thisLog['afl_title']); $centralLog = $thisLog + $central_log_template; $centralLog['afl_filter'] = $globalIndex; $centralLog['afl_title'] = $title->getPrefixedText(); $centralLog['afl_namespace'] = 0; $central_log_rows[] = $centralLog; $logged_global_filters[] = $globalIndex; } } } if (!count($log_rows)) { wfProfileOut(__METHOD__); return; } // Only store the var dump if we're actually going to add log rows. $var_dump = self::storeVarDump($vars); $var_dump = "stored-text:{$var_dump}"; // To distinguish from stuff stored directly foreach ($log_rows as $index => $data) { $log_rows[$index]['afl_var_dump'] = $var_dump; } wfProfileIn(__METHOD__ . '-hitstats'); global $wgMemc; // Increment trigger counter $wgMemc->incr(self::filterMatchesKey()); $dbw->insert('abuse_filter_log', $log_rows, __METHOD__); if (count($logged_local_filters)) { // Update hit-counter. $dbw->update('abuse_filter', array('af_hit_count=af_hit_count+1'), array('af_id' => $logged_local_filters), __METHOD__); } // Global stuff if (count($logged_global_filters)) { $vars->computeDBVars(); $global_var_dump = self::storeVarDump($vars, 'global'); $global_var_dump = "stored-text:{$global_var_dump}"; foreach ($central_log_rows as $index => $data) { $central_log_rows[$index]['afl_var_dump'] = $global_var_dump; } global $wgAbuseFilterCentralDB; $fdb = wfGetDB(DB_MASTER, array(), $wgAbuseFilterCentralDB); $fdb->insert('abuse_filter_log', $central_log_rows, __METHOD__); $fdb->update('abuse_filter', array('af_hit_count=af_hit_count+1'), array('af_id' => $logged_global_filters), __METHOD__); } // Check for emergency disabling. $total = $wgMemc->get(AbuseFilter::filterUsedKey()); self::checkEmergencyDisable($logged_local_filters, $total); wfProfileOut(__METHOD__ . '-hitstats'); wfProfileOut(__METHOD__); }