public function execute() { global $IP, $wgLocalDatabases, $wgUser; $username = wfMessage('spambot_username')->text(); $wgUser = User::newFromName($username); if (!$wgUser) { $this->error("Invalid username specified in 'spambot_username' message: {$username}", true); } // Create the user if necessary if (!$wgUser->getId()) { $wgUser->addToDatabase(); } $spec = $this->getArg(); $like = LinkFilter::makeLikeArray($spec); if (!$like) { $this->error("Not a valid hostname specification: {$spec}", true); } if ($this->hasOption('all')) { // Clean up spam on all wikis $this->output("Finding spam on " . count($wgLocalDatabases) . " wikis\n"); $found = false; foreach ($wgLocalDatabases as $wikiID) { $dbr = wfGetDB(DB_SLAVE, array(), $wikiID); $count = $dbr->selectField('externallinks', 'COUNT(*)', array('el_index' . $dbr->buildLike($like)), __METHOD__); if ($count) { $found = true; $cmd = wfShellWikiCmd("{$IP}/maintenance/cleanupSpam.php", array('--wiki', $wikiID, $spec)); passthru("{$cmd} | sed 's/^/{$wikiID}: /'"); } } if ($found) { $this->output("All done\n"); } else { $this->output("None found\n"); } } else { // Clean up spam on this wiki $dbr = wfGetDB(DB_SLAVE); $res = $dbr->select('externallinks', array('DISTINCT el_from'), array('el_index' . $dbr->buildLike($like)), __METHOD__); $count = $dbr->numRows($res); $this->output("Found {$count} articles containing {$spec}\n"); foreach ($res as $row) { $this->cleanupArticle($row->el_from, $spec); } if ($count) { $this->output("Done\n"); } } }
protected function init() { global $IP; $this->doxygen = $this->getOption('doxygen', 'doxygen'); $this->mwVersion = $this->getOption('version', 'master'); $this->input = ''; $inputs = explode(',', $this->getOption('file', '')); foreach ($inputs as $input) { # Doxygen inputs are space separted and double quoted $this->input .= " \"{$IP}/{$input}\""; } $this->output = $this->getOption('output', "{$IP}/docs"); $this->inputFilter = wfShellWikiCmd($IP . '/maintenance/mwdoc-filter.php'); $this->template = $IP . '/maintenance/Doxyfile'; $this->excludes = array('vendor', 'node_modules', 'images', 'static'); $this->excludePatterns = array(); if ($this->hasOption('no-extensions')) { $this->excludePatterns[] = 'extensions'; } $this->doDot = `which dot`; $this->doMan = $this->hasOption('generate-man'); }
/** * Do a job from the job queue */ private function doJobs() { global $wgJobRunRate, $wgPhpCli, $IP; if ($wgJobRunRate <= 0 || wfReadOnly()) { return; } if ($wgJobRunRate < 1) { $max = mt_getrandmax(); if (mt_rand(0, $max) > $max * $wgJobRunRate) { return; // the higher $wgJobRunRate, the less likely we return here } $n = 1; } else { $n = intval($wgJobRunRate); } if (!wfShellExecDisabled() && is_executable($wgPhpCli)) { // Start a background process to run some of the jobs. // This will be asynchronous on *nix though not on Windows. wfProfileIn(__METHOD__ . '-exec'); $retVal = 1; $cmd = wfShellWikiCmd("{$IP}/maintenance/runJobs.php", array('--maxjobs', $n)); wfShellExec("{$cmd} &", $retVal); wfProfileOut(__METHOD__ . '-exec'); } else { // Fallback to running the jobs here while the user waits $group = JobQueueGroup::singleton(); do { $job = $group->pop(JobQueueGroup::USE_CACHE); // job from any queue if ($job) { $output = $job->toString() . "\n"; $t = -microtime(true); wfProfileIn(__METHOD__ . '-' . get_class($job)); $success = $job->run(); wfProfileOut(__METHOD__ . '-' . get_class($job)); $group->ack($job); // done $t += microtime(true); $t = round($t * 1000); if ($success === false) { $output .= "Error: " . $job->getLastError() . ", Time: {$t} ms\n"; } else { $output .= "Success, Time: {$t} ms\n"; } wfDebugLog('jobqueue', $output); } } while (--$n && $job); } }
/** * @dataProvider provideWfShellWikiCmdList * @covers ::wfShellWikiCmd */ public function testWfShellWikiCmd($script, $parameters, $options, $expected, $description) { if (wfIsWindows()) { // Approximation that's good enough for our purposes just now $expected = str_replace("'", '"', $expected); } $actual = wfShellWikiCmd($script, $parameters, $options); $this->assertEquals($expected, $actual, $description); }
/** * Get the resolved (post-setup) configuration of a potentially foreign wiki. * For foreign wikis, this is expensive, and only works if maintenance * scripts are setup to handle the --wiki parameter such as in wiki farms. * * @param string $wiki * @param array|string $settings A setting name or array of setting names * @return mixed|mixed[] Array if $settings is an array, otherwise the value * @throws MWException * @since 1.21 */ public function getConfig($wiki, $settings) { global $IP; $multi = is_array($settings); $settings = (array) $settings; if ($wiki === wfWikiID()) { // $wiki is this wiki $res = []; foreach ($settings as $name) { if (!preg_match('/^wg[A-Z]/', $name)) { throw new MWException("Variable '{$name}' does start with 'wg'."); } elseif (!isset($GLOBALS[$name])) { throw new MWException("Variable '{$name}' is not set."); } $res[$name] = $GLOBALS[$name]; } } else { // $wiki is a foreign wiki if (isset($this->cfgCache[$wiki])) { $res = array_intersect_key($this->cfgCache[$wiki], array_flip($settings)); if (count($res) == count($settings)) { return $multi ? $res : current($res); // cache hit } } elseif (!in_array($wiki, $this->wikis)) { throw new MWException("No such wiki '{$wiki}'."); } else { $this->cfgCache[$wiki] = []; } $retVal = 1; $cmd = wfShellWikiCmd("{$IP}/maintenance/getConfiguration.php", ['--wiki', $wiki, '--settings', implode(' ', $settings), '--format', 'PHP']); // ulimit5.sh breaks this call $data = trim(wfShellExec($cmd, $retVal, [], ['memory' => 0])); if ($retVal != 0 || !strlen($data)) { throw new MWException("Failed to run getConfiguration.php."); } $res = unserialize($data); if (!is_array($res)) { throw new MWException("Failed to unserialize configuration array."); } $this->cfgCache[$wiki] = $this->cfgCache[$wiki] + $res; } return $multi ? $res : current($res); }
/** * Alias to wfShellWikiCmd() * * @see wfShellWikiCmd() */ function wfShellMaintenanceCmd($script, array $parameters = array(), array $options = array()) { return wfShellWikiCmd($script, $parameters, $options); }
/** * Do a job from the job queue */ private function doJobs() { global $wgJobRunRate, $wgPhpCli, $IP; if ( $wgJobRunRate <= 0 || wfReadOnly() ) { return; } if ( $wgJobRunRate < 1 ) { $max = mt_getrandmax(); if ( mt_rand( 0, $max ) > $max * $wgJobRunRate ) { return; // the higher $wgJobRunRate, the less likely we return here } $n = 1; } else { $n = intval( $wgJobRunRate ); } if ( !wfShellExecDisabled() && is_executable( $wgPhpCli ) ) { // Start a background process to run some of the jobs wfProfileIn( __METHOD__ . '-exec' ); $retVal = 1; $cmd = wfShellWikiCmd( "$IP/maintenance/runJobs.php", array( '--maxjobs', $n ) ); $cmd .= " >" . wfGetNull() . " 2>&1"; // don't hang PHP on pipes if ( wfIsWindows() ) { // Using START makes this async and also works around a bug where using // wfShellExec() with a quoted script name causes a filename syntax error. $cmd = "START /B \"bg\" $cmd"; } else { $cmd = "$cmd &"; } wfShellExec( $cmd, $retVal ); wfProfileOut( __METHOD__ . '-exec' ); } else { try { // Fallback to running the jobs here while the user waits $group = JobQueueGroup::singleton(); do { $job = $group->pop( JobQueueGroup::USE_CACHE ); // job from any queue if ( $job ) { $output = $job->toString() . "\n"; $t = - microtime( true ); wfProfileIn( __METHOD__ . '-' . get_class( $job ) ); $success = $job->run(); wfProfileOut( __METHOD__ . '-' . get_class( $job ) ); $group->ack( $job ); // done $t += microtime( true ); $t = round( $t * 1000 ); if ( $success === false ) { $output .= "Error: " . $job->getLastError() . ", Time: $t ms\n"; } else { $output .= "Success, Time: $t ms\n"; } wfDebugLog( 'jobqueue', $output ); } } while ( --$n && $job ); } catch ( MWException $e ) { // We don't want exceptions thrown during job execution to // be reported to the user since the output is already sent. // Instead we just log them. MWExceptionHandler::logException( $e ); } } }