/** * Forks processes to scan the originating IP for an open proxy server * MemCached can be used to skip IPs that have already been scanned */ function wfProxyCheck() { global $wgBlockOpenProxies, $wgProxyPorts, $wgProxyScriptPath; global $wgMemc, $wgProxyMemcExpiry, $wgRequest; global $wgProxyKey; if (!$wgBlockOpenProxies) { return; } $ip = $wgRequest->getIP(); # Get MemCached key $mcKey = wfMemcKey('proxy', 'ip', $ip); $mcValue = $wgMemc->get($mcKey); $skip = (bool) $mcValue; # Fork the processes if (!$skip) { $title = SpecialPage::getTitleFor('Blockme'); $iphash = md5($ip . $wgProxyKey); $url = wfExpandUrl($title->getFullURL('ip=' . $iphash), PROTO_HTTP); foreach ($wgProxyPorts as $port) { $params = implode(' ', array(escapeshellarg($wgProxyScriptPath), escapeshellarg($ip), escapeshellarg($port), escapeshellarg($url))); exec("php {$params} >" . wfGetNull() . " 2>&1 &"); } # Set MemCached key $wgMemc->set($mcKey, 1, $wgProxyMemcExpiry); } }
/** * @param string $file * @return string */ function setup7zCommand($file) { $command = "7za a -bd -si -mx="; $command .= wfEscapeShellArg($this->compressionLevel) . ' '; $command .= wfEscapeShellArg($file); // Suppress annoying useless crap from p7zip // Unfortunately this could suppress real error messages too $command .= ' >' . wfGetNull() . ' 2>&1'; return $command; }
function __construct($engine, $options) { if ($options['errorFile'] === null) { $options['errorFile'] = wfGetNull(); } if ($options['luaPath'] === null) { $path = false; if (PHP_OS == 'Linux') { if (PHP_INT_SIZE == 4) { $path = 'lua5_1_5_linux_32_generic/lua'; } elseif (PHP_INT_SIZE == 8) { $path = 'lua5_1_5_linux_64_generic/lua'; } } elseif (PHP_OS == 'Windows' || PHP_OS == 'WINNT' || PHP_OS == 'Win32') { if (PHP_INT_SIZE == 4) { $path = 'lua5_1_4_Win32_bin/lua5.1.exe'; } elseif (PHP_INT_SIZE == 8) { $path = 'lua5_1_4_Win64_bin/lua5.1.exe'; } } elseif (PHP_OS == 'Darwin') { $path = 'lua5_1_5_mac_lion_fat_generic/lua'; } if ($path === false) { throw new Scribunto_LuaInterpreterNotFoundError('No Lua interpreter was given in the configuration, ' . 'and no bundled binary exists for this platform.'); } $options['luaPath'] = dirname(__FILE__) . "/binaries/{$path}"; } $this->engine = $engine; $this->enableDebug = !empty($options['debug']); $pipes = null; $cmd = wfEscapeShellArg($options['luaPath'], dirname(__FILE__) . '/mw_main.lua', dirname(dirname(dirname(__FILE__)))); if (php_uname('s') == 'Linux') { // Limit memory and CPU $cmd = wfEscapeShellArg('/bin/sh', dirname(__FILE__) . '/lua_ulimit.sh', $options['cpuLimit'], $options['cpuLimit'] + 1, intval($options['memoryLimit'] / 1024), $cmd); } if (php_uname('s') == 'Windows NT') { // Like the passthru() in older versions of PHP, // PHP's invokation of cmd.exe in proc_open() is broken: // http://news.php.net/php.internals/21796 // Unlike passthru(), it is not fixed in any PHP version, // so we use the fix similar to one in wfShellExec() $cmd = '"' . $cmd . '"'; } wfDebug(__METHOD__ . ": creating interpreter: {$cmd}\n"); $this->proc = proc_open($cmd, array(array('pipe', 'r'), array('pipe', 'w'), array('file', $options['errorFile'], 'a')), $pipes); if (!$this->proc) { throw $this->engine->newException('scribunto-luastandalone-proc-error'); } $this->writePipe = $pipes[0]; $this->readPipe = $pipes[1]; }
/** * Spawn an external HTML tidy process and get corrected markup back from it. * Also called in OutputHandler.php for full page validation * * @param $text String: HTML to check * @param $stderr Boolean: Whether to read from STDERR rather than STDOUT * @param &$retval Exit code (-1 on internal error) * @retrun mixed String or null */ private static function execExternalTidy($text, $stderr = false, &$retval = null) { global $wgTidyConf, $wgTidyBin, $wgTidyOpts; wfProfileIn(__METHOD__); $cleansource = ''; $opts = ' -utf8'; if ($stderr) { $descriptorspec = array(0 => array('pipe', 'r'), 1 => array('file', wfGetNull(), 'a'), 2 => array('pipe', 'w')); } else { $descriptorspec = array(0 => array('pipe', 'r'), 1 => array('pipe', 'w'), 2 => array('file', wfGetNull(), 'a')); } $readpipe = $stderr ? 2 : 1; $pipes = array(); if (function_exists('proc_open')) { $process = proc_open("{$wgTidyBin} -config {$wgTidyConf} {$wgTidyOpts}{$opts}", $descriptorspec, $pipes); if (is_resource($process)) { // Theoretically, this style of communication could cause a deadlock // here. If the stdout buffer fills up, then writes to stdin could // block. This doesn't appear to happen with tidy, because tidy only // writes to stdout after it's finished reading from stdin. Search // for tidyParseStdin and tidySaveStdout in console/tidy.c fwrite($pipes[0], $text); fclose($pipes[0]); while (!feof($pipes[$readpipe])) { $cleansource .= fgets($pipes[$readpipe], 1024); } fclose($pipes[$readpipe]); $retval = proc_close($process); } else { $retval = -1; } } else { $retval = -1; } wfProfileOut(__METHOD__); if (!$stderr && $cleansource == '' && $text != '') { // Some kind of error happened, so we couldn't get the corrected text. // Just give up; we'll use the source text and append a warning. return null; } else { return $cleansource; } }
/** * Spawn an external HTML tidy process and get corrected markup back from it. * Also called in OutputHandler.php for full page validation * * @param string $text HTML to check * @param bool $stderr Whether to read result from STDERR rather than STDOUT * @param int &$retval Exit code (-1 on internal error) * @return string|null */ protected function cleanWrapped($text, $stderr = false, &$retval = null) { $cleansource = ''; $opts = ' -utf8'; if ($stderr) { $descriptorspec = [0 => ['pipe', 'r'], 1 => ['file', wfGetNull(), 'a'], 2 => ['pipe', 'w']]; } else { $descriptorspec = [0 => ['pipe', 'r'], 1 => ['pipe', 'w'], 2 => ['file', wfGetNull(), 'a']]; } $readpipe = $stderr ? 2 : 1; $pipes = []; $process = proc_open("{$this->config['tidyBin']} -config {$this->config['tidyConfigFile']} " . $this->config['tidyCommandLine'] . $opts, $descriptorspec, $pipes); // NOTE: At least on linux, the process will be created even if tidy is not installed. // This means that missing tidy will be treated as a validation failure. if (is_resource($process)) { // Theoretically, this style of communication could cause a deadlock // here. If the stdout buffer fills up, then writes to stdin could // block. This doesn't appear to happen with tidy, because tidy only // writes to stdout after it's finished reading from stdin. Search // for tidyParseStdin and tidySaveStdout in console/tidy.c fwrite($pipes[0], $text); fclose($pipes[0]); while (!feof($pipes[$readpipe])) { $cleansource .= fgets($pipes[$readpipe], 1024); } fclose($pipes[$readpipe]); $retval = proc_close($process); } else { wfWarn("Unable to start external tidy process"); $retval = -1; } if (!$stderr && $cleansource == '' && $text != '') { // Some kind of error happened, so we couldn't get the corrected text. // Just give up; we'll use the source text and append a warning. $cleansource = null; } return $cleansource; }
function Dump7ZipOutput($file) { $command = "7za a -bd -si " . wfEscapeShellArg($file); // Suppress annoying useless crap from p7zip // Unfortunately this could suppress real error messages too $command .= ' >' . wfGetNull() . ' 2>&1'; parent::DumpPipeOutput($command); }
/** * @param Scribunto_LuaStandaloneEngine $engine * @param array $options * @throws MWException * @throws Scribunto_LuaInterpreterNotFoundError * @throws ScribuntoException */ function __construct($engine, array $options) { $this->id = self::$nextInterpreterId++; if ($options['errorFile'] === null) { $options['errorFile'] = wfGetNull(); } if ($options['luaPath'] === null) { $path = false; // Note, if you alter these, also alter getLuaVersion() below if (PHP_OS == 'Linux') { if (PHP_INT_SIZE == 4) { $path = 'lua5_1_5_linux_32_generic/lua'; } elseif (PHP_INT_SIZE == 8) { $path = 'lua5_1_5_linux_64_generic/lua'; } } elseif (PHP_OS == 'Windows' || PHP_OS == 'WINNT' || PHP_OS == 'Win32') { if (PHP_INT_SIZE == 4) { $path = 'lua5_1_4_Win32_bin/lua5.1.exe'; } elseif (PHP_INT_SIZE == 8) { $path = 'lua5_1_4_Win64_bin/lua5.1.exe'; } } elseif (PHP_OS == 'Darwin') { $path = 'lua5_1_5_mac_lion_fat_generic/lua'; } if ($path === false) { throw new Scribunto_LuaInterpreterNotFoundError('No Lua interpreter was given in the configuration, ' . 'and no bundled binary exists for this platform.'); } $options['luaPath'] = dirname(__FILE__) . "/binaries/{$path}"; if (!is_executable($options['luaPath'])) { throw new MWException(sprintf('The lua binary (%s) is not executable.', $options['luaPath'])); } } $this->engine = $engine; $this->enableDebug = !empty($options['debug']); $pipes = null; $cmd = wfEscapeShellArg($options['luaPath'], dirname(__FILE__) . '/mw_main.lua', dirname(dirname(dirname(__FILE__))), $this->id); if (php_uname('s') == 'Linux') { // Limit memory and CPU $cmd = wfEscapeShellArg('/bin/sh', dirname(__FILE__) . '/lua_ulimit.sh', $options['cpuLimit'], $options['cpuLimit'] + 1, intval($options['memoryLimit'] / 1024), $cmd); } if (php_uname('s') == 'Windows NT') { // Like the passthru() in older versions of PHP, // PHP's invokation of cmd.exe in proc_open() is broken: // http://news.php.net/php.internals/21796 // Unlike passthru(), it is not fixed in any PHP version, // so we use the fix similar to one in wfShellExec() $cmd = '"' . $cmd . '"'; } wfDebug(__METHOD__ . ": creating interpreter: {$cmd}\n"); // Check whether proc_open is available before trying to call it (e.g. // PHP's disable_functions may have removed it) if (!function_exists('proc_open')) { throw $this->engine->newException('scribunto-luastandalone-proc-error-proc-open'); } // Clear the "last error", so if proc_open fails we can know any // warning was generated by that. @trigger_error(''); $this->proc = proc_open($cmd, array(array('pipe', 'r'), array('pipe', 'w'), array('file', $options['errorFile'], 'a')), $pipes); if (!$this->proc) { $err = error_get_last(); if (!empty($err['message'])) { throw $this->engine->newException('scribunto-luastandalone-proc-error-msg', array('args' => array($err['message']))); } elseif (wfIniGetBool('safe_mode')) { /** @todo: Remove this case once we no longer support PHP 5.3 */ throw $this->engine->newException('scribunto-luastandalone-proc-error-safe-mode'); } else { throw $this->engine->newException('scribunto-luastandalone-proc-error'); } } $this->writePipe = $pipes[0]; $this->readPipe = $pipes[1]; }
/** * 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 ); } } }
/** * Converts a public ssh key to openssh format, using ssh-keygen. * @param $keydata string SSH public/private key in some format * @return mixed Public key in openssh format or false */ static function opensshFormatKeySshKeygen($keydata) { global $wgSshKeygen; if (wfIsWindows() || !$wgSshKeygen) { return false; } if (substr_compare($keydata, 'PuTTY-User-Key-File-2:', 0, 22) == 0) { $keydata = explode("\nPrivate-Lines:", $keydata, 2); $keydata = $keydata[0] . "\n"; } $descriptorspec = array(0 => array("pipe", "r"), 1 => array("pipe", "w"), 2 => array("file", wfGetNull(), "a")); $process = proc_open(escapeshellcmd($wgSshKeygen) . ' -i -f /dev/stdin', $descriptorspec, $pipes); if ($process === false) { return false; } fwrite($pipes[0], $keydata); fclose($pipes[0]); $data = stream_get_contents($pipes[1]); fclose($pipes[1]); proc_close($process); if ($data === false || !preg_match('/(^| )ssh-(rsa|dss) /', $data)) { return false; } return $data; }
/** * Runs a certain process in the background. * * @param $path string The physical path of the program to run. * @param $exe string The name of the program to run. * @param $args mixed The arguments to pass to the child process. */ private function execInBackground($path, $exe, $args = "") { global $conf, $IP; chdir(realpath($path)); if (is_array($args)) { explode(" ", $args); } if (wfIsWindows()) { $command = "start \"MediaWiki\"" . escapeshellcmd($exe) . " {$args} > " . wfGetNull(); } else { $command = "./" . escapeshellcmd($exe) . " " . escapeshellcmd($args) . " > " . wfGetNull() . " &"; } pclose(popen($command, "r")); }