/** * Return an appropriately formatted LIKE query and the clause */ static function mungeQuery($query, $prot) { $field = 'el_index'; $rv = LinkFilter::makeLike($query, $prot); if ($rv === false) { //makeLike doesn't handle wildcard in IP, so we'll have to munge here. if (preg_match('/^(:?[0-9]{1,3}\\.)+\\*\\s*$|^(:?[0-9]{1,3}\\.){3}[0-9]{1,3}:[0-9]*\\*\\s*$/', $query)) { $rv = $prot . rtrim($query, " \t*") . '%'; $field = 'el_to'; } } return array($rv, $field); }
} } //------------------------------------------------------------------------------ $username = wfMsg('spambot_username'); $fname = $username; $wgUser = User::newFromName($username); // Create the user if necessary if (!$wgUser->getID()) { $wgUser->addToDatabase(); } if (!isset($args[0])) { print "Usage: php cleanupSpam.php <hostname>\n"; exit(1); } $spec = $args[0]; $like = LinkFilter::makeLike($spec); if (!$like) { print "Not a valid hostname specification: {$spec}\n"; exit(1); } $dbr =& wfGetDB(DB_SLAVE); if ($options['all']) { // Clean up spam on all wikis $dbr =& wfGetDB(DB_SLAVE); print "Finding spam on " . count($wgLocalDatabases) . " wikis\n"; $found = false; foreach ($wgLocalDatabases as $db) { $count = $dbr->selectField("`{$db}`.externallinks", 'COUNT(*)', array('el_index LIKE ' . $dbr->addQuotes($like)), $fname); if ($count) { $found = true; passthru("php cleanupSpam.php {$db} {$spec} | sed s/^/{$db}: /");
private function run($resultPageSet = null) { $params = $this->extractRequestParams(); $protocol = $params['protocol']; $query = $params['query']; if (is_null($query)) { $this->dieUsage('Missing required query parameter', 'params'); } // Find the right prefix global $wgUrlProtocols; foreach ($wgUrlProtocols as $p) { if (substr($p, 0, strlen($protocol)) === $protocol) { $protocol = $p; break; } } $likeQuery = LinkFilter::makeLike($query, $protocol); if (!$likeQuery) { $this->dieUsage('Invalid query', 'bad_query'); } $likeQuery = substr($likeQuery, 0, strpos($likeQuery, '%') + 1); $this->addTables(array('page', 'externallinks')); // must be in this order for 'USE INDEX' $this->addOption('USE INDEX', 'el_index'); $db = $this->getDB(); $this->addWhere('page_id=el_from'); $this->addWhere('el_index LIKE ' . $db->addQuotes($likeQuery)); $this->addWhereFld('page_namespace', $params['namespace']); $prop = array_flip($params['prop']); $fld_ids = isset($prop['ids']); $fld_title = isset($prop['title']); $fld_url = isset($prop['url']); if (is_null($resultPageSet)) { $this->addFields(array('page_id', 'page_namespace', 'page_title')); $this->addFieldsIf('el_to', $fld_url); } else { $this->addFields($resultPageSet->getPageTableFields()); } $limit = $params['limit']; $offset = $params['offset']; $this->addOption('LIMIT', $limit + 1); if (isset($offset)) { $this->addOption('OFFSET', $offset); } $res = $this->select(__METHOD__); $data = array(); $count = 0; while ($row = $db->fetchObject($res)) { if (++$count > $limit) { // We've reached the one extra which shows that there are additional pages to be had. Stop here... $this->setContinueEnumParameter('offset', $offset + $limit + 1); break; } if (is_null($resultPageSet)) { $vals = array(); if ($fld_ids) { $vals['pageid'] = intval($row->page_id); } if ($fld_title) { $title = Title::makeTitle($row->page_namespace, $row->page_title); $vals['ns'] = intval($title->getNamespace()); $vals['title'] = $title->getPrefixedText(); } if ($fld_url) { $vals['url'] = $row->el_to; } $data[] = $vals; } else { $resultPageSet->processDbRow($row); } } $db->freeResult($res); if (is_null($resultPageSet)) { $result = $this->getResult(); $result->setIndexedTagName($data, $this->getModulePrefix()); $result->addValue('query', $this->getModuleName(), $data); } }
function cleanUp($phrase, $database) { global $wgOut, $wgUser; if (!isset($phrase) || "" == $phrase) { $this->showForm(wfMsg('cleanupspam_error_empty')); return; } /* do a check whether something actually _is_ inside $wgLocalDatabases */ if (!is_array($wgLocalDatabases) && 'local' == $this->mMode) { $this->showForm(wfMsg('cleanupspam_no_local')); return; } $like = LinkFilter::makeLike($phrase); if (!$like) { $this->showForm(wfMsg('cleanupspam_error_not_valid') . ": " . $phrase); return; } $like = $phrase; $dbr =& wfGetDB(DB_SLAVE); switch ($this->mMode) { case 'this': /* Clean up spam just on this wiki */ $res = $dbr->select('externallinks', array('DISTINCT el_from'), array('el_to LIKE ' . $dbr->addQuotes("%//{$phrase}%")), $fname); $count = $dbr->numRows($res); if ($count) { $wgOut->addWikiText("Found {$count} article(s) containing links to '''{$phrase}'''.\n"); while ($row = $dbr->fetchObject($res)) { if ('revert' == $this->mDo) { /* have eyes on this */ $this->cleanupArticle($row->el_from, $phrase); } else { /* just add more data and that should be fine */ $this->writeupArticle($row->el_from, $phrase, $row->el_to); } } } else { $wgOut->addWikiText(wfMsg('cleanupspam_count_zero', "'''" . $phrase . "'''.")); } break; case 'all': /* todo check for no wikis in city_list */ $wikis = $this->fetchWikias(); if (!is_array($wikis)) { return; } $wgOut->addWikiText("Finding spam on all (" . count($wikis) . ") wikis.\n"); foreach ($wikis as $db) { $count = $dbr->selectField("`" . $db->city_dbname . "`.externallinks", 'COUNT(*)', array('el_to LIKE ' . $dbr->addQuotes("%//{$phrase}%")), $fname); if ($count) { $found = true; $this->cleanUp($phrase, $db->city_dbname); } } if ('revert' == $this->mDo) { if ($found) { $wgOut->addWikiText(wfMsg('cleanupspam_cleanup_finished')); } else { $wgOut->addWikiText(wfMsg('cleanupspam_none_found', $phrase)); } } break; } if ('revert' == $this->mDo) { $wgOut->addWikiText(wfMsg('cleanupspam_cleanup_finished')); } $sk = $wgUser->getSkin(); $titleObj = Title::makeTitle(NS_SPECIAL, 'Cleanupspam'); $link_back = $sk->makeKnownLinkObj($titleObj, '<b>here</b>'); $wgOut->addHtml("<br/>" . wfMsg('cleanupspam_link_back') . " " . $link_back . "."); }
/** * Return an appropriately formatted LIKE query */ static function mungeQuery($query, $prot) { return LinkFilter::makeLike($query, $prot); }