function show() { $user = $this->getUser(); $out = $this->getOutput(); $request = $this->getRequest(); $out->setPageTitle($this->msg('abusefilter-edit')); $filter = $this->mFilter; $history_id = $this->mHistoryID; // Add default warning messages $this->exposeWarningMessages(); if ($filter == 'new' && !$user->isAllowed('abusefilter-modify')) { $out->addWikiMsg('abusefilter-edit-notallowed'); return; } $editToken = $request->getVal('wpEditToken'); $didEdit = $this->canEdit() && $user->matchEditToken($editToken, array('abusefilter', $filter)); if ($didEdit) { // Check syntax $syntaxerr = AbuseFilter::checkSyntax($request->getVal('wpFilterRules')); if ($syntaxerr !== true) { $out->addHTML($this->buildFilterEditor($this->msg('abusefilter-edit-badsyntax', array($syntaxerr[0]))->parseAsBlock(), $filter, $history_id)); return; } $dbw = wfGetDB(DB_MASTER); list($newRow, $actions) = $this->loadRequest($filter); $differences = AbuseFilter::compareVersions(array($newRow, $actions), array($newRow->mOriginalRow, $newRow->mOriginalActions)); // Don't allow adding a new global rule, or updating a // rule that is currently global, without permissions. if (!$this->canEditFilter($newRow) || !$this->canEditFilter($newRow->mOriginalRow)) { $out->addWikiMsg('abusefilter-edit-notallowed-global'); return; } // Don't allow custom messages on global rules if ($newRow->af_global == 1 && $request->getVal('wpFilterWarnMessage') !== 'abusefilter-warning') { $out->addWikiMsg('abusefilter-edit-notallowed-global-custom-msg'); return; } $origActions = $newRow->mOriginalActions; unset($newRow->mOriginalRow); unset($newRow->mOriginalActions); // Check for non-changes if (!count($differences)) { $out->redirect($this->getTitle()->getLocalURL()); return; } // Check for restricted actions global $wgAbuseFilterRestrictedActions; $allActions = array_keys(array_merge(array_filter($actions), array_filter($origActions))); if (count(array_intersect($wgAbuseFilterRestrictedActions, $allActions)) && !$user->isAllowed('abusefilter-modify-restricted')) { $out->addHTML($this->buildFilterEditor($this->msg('abusefilter-edit-restricted')->parseAsBlock(), $this->mFilter, $history_id)); return; } // If we've activated the 'tag' option, check the arguments for validity. if (!empty($actions['tag'])) { $bad = false; foreach ($actions['tag']['parameters'] as $tag) { $t = Title::makeTitleSafe(NS_MEDIAWIKI, 'tag-' . $tag); if (!$t) { $bad = true; } if ($bad) { $out->addHTML($this->buildFilterEditor($this->msg('abusefilter-edit-bad-tags')->parseAsBlock(), $this->mFilter, $history_id)); return; } } } $newRow = get_object_vars($newRow); // Convert from object to array // Set last modifier. $newRow['af_timestamp'] = $dbw->timestamp(wfTimestampNow()); $newRow['af_user'] = $user->getId(); $newRow['af_user_text'] = $user->getName(); $dbw->begin(__METHOD__); // Insert MAIN row. if ($filter == 'new') { $new_id = $dbw->nextSequenceValue('abuse_filter_af_id_seq'); $is_new = true; } else { $new_id = $this->mFilter; $is_new = false; } // Reset throttled marker, if we're re-enabling it. $newRow['af_throttled'] = $newRow['af_throttled'] && !$newRow['af_enabled']; $newRow['af_id'] = $new_id; // ID. $dbw->replace('abuse_filter', array('af_id'), $newRow, __METHOD__); if ($is_new) { $new_id = $dbw->insertId(); } // Actions global $wgAbuseFilterAvailableActions; $deadActions = array(); $actionsRows = array(); foreach ($wgAbuseFilterAvailableActions as $action) { // Check if it's set $enabled = isset($actions[$action]) && (bool) $actions[$action]; if ($enabled) { $parameters = $actions[$action]['parameters']; $thisRow = array('afa_filter' => $new_id, 'afa_consequence' => $action, 'afa_parameters' => implode("\n", $parameters)); $actionsRows[] = $thisRow; } else { $deadActions[] = $action; } } // Create a history row $afh_row = array(); foreach (AbuseFilter::$history_mappings as $af_col => $afh_col) { $afh_row[$afh_col] = $newRow[$af_col]; } // Actions $displayActions = array(); foreach ($actions as $action) { $displayActions[$action['action']] = $action['parameters']; } $afh_row['afh_actions'] = serialize($displayActions); $afh_row['afh_changed_fields'] = implode(',', $differences); // Flags $flags = array(); if ($newRow['af_hidden']) { $flags[] = 'hidden'; } if ($newRow['af_enabled']) { $flags[] = 'enabled'; } if ($newRow['af_deleted']) { $flags[] = 'deleted'; } if ($newRow['af_global']) { $flags[] = 'global'; } $afh_row['afh_flags'] = implode(',', $flags); $afh_row['afh_filter'] = $new_id; $afh_row['afh_id'] = $dbw->nextSequenceValue('abuse_filter_af_id_seq'); // Do the update $dbw->insert('abuse_filter_history', $afh_row, __METHOD__); $history_id = $dbw->insertId(); if ($filter != 'new') { $dbw->delete('abuse_filter_action', array('afa_filter' => $filter), __METHOD__); } $dbw->insert('abuse_filter_action', $actionsRows, __METHOD__); $dbw->commit(__METHOD__); // Reset Memcache if this was a global rule if ($newRow['af_global']) { global $wgMemc; $group = 'default'; if (isset($newRow['af_group']) && $newRow['af_group'] != '') { $group = $newRow['af_group']; } $memcacheRules = array(); $res = $dbw->select('abuse_filter', '*', array('af_enabled' => 1, 'af_deleted' => 0, 'af_global' => 1, 'af_group' => $group), __METHOD__); foreach ($res as $row) { $memcacheRules[] = $row; } $wgMemc->set(AbuseFilter::getGlobalRulesKey($group), $memcacheRules); } // Logging $lp = new LogPage('abusefilter'); $lp->addEntry('modify', $this->getTitle($new_id), '', array($history_id, $new_id)); // Special-case stuff for tags -- purge the tag list cache. if (isset($actions['tag'])) { global $wgMemc; $wgMemc->delete(wfMemcKey('valid-tags')); } AbuseFilter::resetFilterProfile($new_id); $out->redirect($this->getTitle()->getLocalURL(array('result' => 'success', 'changedfilter' => $new_id, 'changeid' => $history_id))); } else { if ($history_id) { $out->addWikiMsg('abusefilter-edit-oldwarning', $this->mHistoryID, $this->mFilter); } $out->addHTML($this->buildFilterEditor(null, $this->mFilter, $history_id)); if ($history_id) { $out->addWikiMsg('abusefilter-edit-oldwarning', $this->mHistoryID, $this->mFilter); } } }