function doTransform($image, $dstPath, $dstUrl, $params, $flags = 0) { global $wgFLVConverters, $wgFLVConverter, $wgFLVConverterPath; if (!$this->normaliseParams($image, $params)) { return new TransformParameterError($params); } $clientWidth = $params['width']; $clientHeight = $params['height']; $physicalWidth = $params['physicalWidth']; $physicalHeight = $params['physicalHeight']; $srcPath = $image->getPath(); if ($flags & self::TRANSFORM_LATER) { return new ThumbnailImage($image, $dstUrl, $clientWidth, $clientHeight, $dstPath); } if (!wfMkdirParents(dirname($dstPath), null, __METHOD__)) { return new MediaTransformError('thumbnail_error', $clientWidth, $clientHeight, wfMsg('thumbnail_dest_directory')); } $err = false; if (isset($wgFLVConverters[$wgFLVConverter])) { $cmd = str_replace(array('$path/', '$width', '$height', '$input', '$output'), array($wgFLVConverterPath ? wfEscapeShellArg("{$wgFLVConverterPath}/") : "", intval($physicalWidth), intval($physicalHeight), wfEscapeShellArg($srcPath), wfEscapeShellArg($dstPath)), $wgFLVConverters[$wgFLVConverter]) . " 2>&1"; wfProfileIn('rsvg'); wfDebug(__METHOD__ . ": {$cmd}\n"); $err = wfShellExec($cmd, $retval); wfProfileOut('rsvg'); } $removed = $this->removeBadFile($dstPath, $retval); if ($retval != 0 || $removed) { wfDebugLog('thumbnail', sprintf('thumbnail failed on %s: error %d "%s" from "%s"', wfHostname(), $retval, trim($err), $cmd)); return new MediaTransformError('thumbnail_error', $clientWidth, $clientHeight, $err); } else { return new ThumbnailImage($image, $dstUrl, $clientWidth, $clientHeight, $dstPath); } }
function addWatermark($srcPath, $dstPath, $width, $height) { global $IP, $wgImageMagickConvertCommand, $wgImageMagickCompositeCommand; // do not add a watermark if the image is too small if (WatermarkSupport::validImageSize($width, $height) == false) { return; } $wm = $IP . '/skins/WikiHow/images/watermark.svg'; $watermarkWidth = 1074.447; $targetWidth = $width / 8; $density = 72 * $targetWidth / $watermarkWidth; // we have a lower limit on density so the watermark is readable if ($density < 4.0) { $density = 4.0; } $cmd = ""; // make sure image is rgb format so the watermark applies correctly if (WatermarkSupport::isCMYK($srcPath)) { $cmd = wfEscapeShellArg($wgImageMagickConvertCommand) . " " . wfEscapeShellArg($srcPath) . " " . "-colorspace RGB " . wfEscapeShellArg($dstPath) . ";"; $srcPath = $dstPath; } $cmd = $cmd . wfEscapeShellArg($wgImageMagickConvertCommand) . " -density {$density} -background none " . wfEscapeShellArg($wm) . " miff:- | " . wfEscapeShellArg($wgImageMagickCompositeCommand) . " -gravity southeast -quality 100 -geometry +8+10 - " . wfEscapeShellArg($srcPath) . " " . wfEscapeShellArg($dstPath) . " 2>&1"; $beforeExists = file_exists($dstPath); wfDebug(__METHOD__ . ": running ImageMagick: {$cmd}\n"); $err = wfShellExec($cmd, $retval); $afterExists = file_exists($dstPath); $currentDate = `date`; wfErrorLog(trim($currentDate) . " {$cmd} b:" . ($beforeExists ? 't' : 'f') . " a:" . ($afterExists ? 't' : 'f') . "\n", '/tmp/watermark.log'); wfProfileOut('watermark'); }
public function onSubmit(array $formData) { global $IP, $wgCreateWikiSQLfiles; $DBname = $formData['dbname']; $founderName = $formData['founder']; $siteName = $formData['sitename']; $language = $formData['language']; $private = $formData['private']; $reason = $formData['reason']; $dbw = wfGetDB(DB_MASTER); $farmerLogEntry = new ManualLogEntry('farmer', 'createwiki'); $farmerLogEntry->setPerformer($this->getUser()); $farmerLogEntry->setTarget($this->getTitle()); $farmerLogEntry->setComment($reason); $farmerLogEntry->setParameters(array('4::wiki' => $DBname)); $farmerLogID = $farmerLogEntry->insert(); $farmerLogEntry->publish($farmerLogID); $dbw->query('SET storage_engine=InnoDB;'); $dbw->query('CREATE DATABASE ' . $dbw->addIdentifierQuotes($DBname) . ';'); $dbw->selectDB($DBname); foreach ($wgCreateWikiSQLfiles as $sqlfile) { $dbw->sourceFile($sqlfile); } $this->writeToDBlist($DBname, $siteName, $language, $private); $this->createMainPage($language); $shcreateaccount = exec("/usr/bin/php " . "{$IP}/extensions/CentralAuth/maintenance/createLocalAccount.php " . wfEscapeShellArg($founderName) . " --wiki " . wfEscapeShellArg($DBname)); if (!strpos($shcreateaccount, 'created')) { wfDebugLog('CreateWiki', 'Failed to create local account for founder. - error: ' . $shcreateaccount); return wfMessage('createwiki-error-usernotcreated')->escaped(); } $shpromoteaccount = exec("/usr/bin/php " . "{$IP}/maintenance/createAndPromote.php " . wfEscapeShellArg($founderName) . " --bureaucrat --sysop --force --wiki " . wfEscapeShellArg($DBname)); $this->getOutput()->addHTML('<div class="successbox">' . wfMessage('createwiki-success')->escaped() . '</div>'); return true; }
/** * @param array $params * @param Config $mainConfig * @return array */ public static function applyDefaultParameters(array $params, Config $mainConfig) { $logger = LoggerFactory::getInstance('Mime'); $params += ['typeFile' => $mainConfig->get('MimeTypeFile'), 'infoFile' => $mainConfig->get('MimeInfoFile'), 'xmlTypes' => $mainConfig->get('XMLMimeTypes'), 'guessCallback' => function ($mimeAnalyzer, &$head, &$tail, $file, &$mime) use($logger) { // Also test DjVu $deja = new DjVuImage($file); if ($deja->isValid()) { $logger->info(__METHOD__ . ": detected {$file} as image/vnd.djvu\n"); $mime = 'image/vnd.djvu'; return; } // Some strings by reference for performance - assuming well-behaved hooks Hooks::run('MimeMagicGuessFromContent', [$mimeAnalyzer, &$head, &$tail, $file, &$mime]); }, 'extCallback' => function ($mimeAnalyzer, $ext, &$mime) { // Media handling extensions can improve the MIME detected Hooks::run('MimeMagicImproveFromExtension', [$mimeAnalyzer, $ext, &$mime]); }, 'initCallback' => function ($mimeAnalyzer) { // Allow media handling extensions adding MIME-types and MIME-info Hooks::run('MimeMagicInit', [$mimeAnalyzer]); }, 'logger' => $logger]; if ($params['infoFile'] === 'includes/mime.info') { $params['infoFile'] = __DIR__ . "/libs/mime/mime.info"; } if ($params['typeFile'] === 'includes/mime.types') { $params['typeFile'] = __DIR__ . "/libs/mime/mime.types"; } $detectorCmd = $mainConfig->get('MimeDetectorCommand'); if ($detectorCmd) { $params['detectCallback'] = function ($file) use($detectorCmd) { return wfShellExec("{$detectorCmd} " . wfEscapeShellArg($file)); }; } return $params; }
protected static function callFontConfig($code) { if (ini_get('open_basedir')) { wfDebugLog('fcfont', 'Disabled because of open_basedir is active'); // Most likely we can't access any fonts we might find return false; } $cache = self::getCache(); $cachekey = wfMemckey('fcfont', $code); $timeout = 60 * 60 * 12; $cached = $cache->get($cachekey); if (is_array($cached)) { return $cached; } elseif ($cached === 'NEGATIVE') { return false; } $code = wfEscapeShellArg(":lang={$code}"); $ok = 0; $cmd = "fc-match {$code}"; $suggestion = wfShellExec($cmd, $ok); wfDebugLog('fcfont', "{$cmd} returned {$ok}"); if ($ok !== 0) { wfDebugLog('fcfont', "fc-match error output: {$suggestion}"); $cache->set($cachekey, 'NEGATIVE', $timeout); return false; } $pattern = '/^(.*?): "(.*)" "(.*)"$/'; $matches = array(); if (!preg_match($pattern, $suggestion, $matches)) { wfDebugLog('fcfont', "fc-match: return format not understood: {$suggestion}"); $cache->set($cachekey, 'NEGATIVE', $timeout); return false; } list(, $file, $family, $type) = $matches; wfDebugLog('fcfont', "fc-match: got {$file}: {$family} {$type}"); $file = wfEscapeShellArg($file); $family = wfEscapeShellArg($family); $type = wfEscapeShellArg($type); $cmd = "fc-list {$family} {$type} {$code} file | grep {$file}"; $candidates = trim(wfShellExec($cmd, $ok)); wfDebugLog('fcfont', "{$cmd} returned {$ok}"); if ($ok !== 0) { wfDebugLog('fcfont', "fc-list error output: {$candidates}"); $cache->set($cachekey, 'NEGATIVE', $timeout); return false; } # trim spaces $files = array_map('trim', explode("\n", $candidates)); $count = count($files); if (!$count) { wfDebugLog('fcfont', "fc-list got zero canditates: {$candidates}"); } # remove the trailing ":" $chosen = substr($files[0], 0, -1); wfDebugLog('fcfont', "fc-list got {$count} candidates; using {$chosen}"); $data = array('family' => $family, 'type' => $type, 'file' => $chosen); $cache->set($cachekey, $data, $timeout); return $data; }
public function execute() { global $wgCaptchaSecret, $wgCaptchaDirectoryLevels; $instance = ConfirmEditHooks::getInstance(); if (!$instance instanceof FancyCaptcha) { $this->error("\$wgCaptchaClass is not FancyCaptcha.\n", 1); } $backend = $instance->getBackend(); $countAct = $instance->estimateCaptchaCount(); $this->output("Estimated number of captchas is {$countAct}.\n"); $countGen = (int) $this->getOption('fill') - $countAct; if ($countGen <= 0) { $this->output("No need to generate anymore captchas.\n"); return; } $tmpDir = wfTempDir() . '/mw-fancycaptcha-' . time() . '-' . wfRandomString(6); if (!wfMkdirParents($tmpDir)) { $this->error("Could not create temp directory.\n", 1); } $e = null; // exception try { $cmd = sprintf("python %s --key %s --output %s --count %s --dirs %s", wfEscapeShellArg(__DIR__ . '/../captcha.py'), wfEscapeShellArg($wgCaptchaSecret), wfEscapeShellArg($tmpDir), wfEscapeShellArg($countGen), wfEscapeShellArg($wgCaptchaDirectoryLevels)); foreach (array('wordlist', 'font', 'font-size', 'blacklist', 'verbose') as $par) { if ($this->hasOption($par)) { $cmd .= " --{$par} " . wfEscapeShellArg($this->getOption($par)); } } $this->output("Generating {$countGen} new captchas...\n"); $retVal = 1; wfShellExec($cmd, $retVal, array(), array('time' => 0)); if ($retVal != 0) { wfRecursiveRemoveDir($tmpDir); $this->error("Could not run generation script.\n", 1); } $flags = FilesystemIterator::SKIP_DOTS; $iter = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($tmpDir, $flags), RecursiveIteratorIterator::CHILD_FIRST); $this->output("Copying the new captchas to storage...\n"); foreach ($iter as $fileInfo) { if (!$fileInfo->isFile()) { continue; } list($salt, $hash) = $instance->hashFromImageName($fileInfo->getBasename()); $dest = $instance->imagePath($salt, $hash); $backend->prepare(array('dir' => dirname($dest))); $status = $backend->quickStore(array('src' => $fileInfo->getPathname(), 'dst' => $dest)); if (!$status->isOK()) { $this->error("Could not save file '{$fileInfo->getPathname()}'.\n"); } } } catch (Exception $e) { wfRecursiveRemoveDir($tmpDir); throw $e; } $this->output("Removing temporary files...\n"); wfRecursiveRemoveDir($tmpDir); $this->output("Done.\n"); }
public function doDBUpdates() { $method = $this->getOption('method', 'normal'); $file = $this->getOption('file'); $t = -microtime(true); $dbw = wfGetDB(DB_MASTER); if ($file) { $res = $dbw->select('image', array('img_name'), array('img_name' => $file), __METHOD__); if (!$res) { $this->error("No such file: {$file}", true); return false; } $this->output("Populating img_sha1 field for specified files\n"); } else { $res = $dbw->select('image', array('img_name'), array('img_sha1' => ''), __METHOD__); $this->output("Populating img_sha1 field\n"); } $imageTable = $dbw->tableName('image'); if ($method == 'pipe') { // @todo FIXME: Kill this and replace with a second unbuffered DB connection. global $wgDBuser, $wgDBserver, $wgDBpassword, $wgDBname; $cmd = 'mysql -u' . wfEscapeShellArg($wgDBuser) . ' -h' . wfEscapeShellArg($wgDBserver) . ' -p' . wfEscapeShellArg($wgDBpassword, $wgDBname); $this->output("Using pipe method\n"); $pipe = popen($cmd, 'w'); } $numRows = $res->numRows(); $i = 0; foreach ($res as $row) { if ($i % $this->mBatchSize == 0) { $this->output(sprintf("Done %d of %d, %5.3f%% \r", $i, $numRows, $i / $numRows * 100)); wfWaitForSlaves(); } $file = wfLocalFile($row->img_name); if (!$file) { continue; } $sha1 = $file->getRepo()->getFileSha1($file->getPath()); if (strval($sha1) !== '') { $sql = "UPDATE {$imageTable} SET img_sha1=" . $dbw->addQuotes($sha1) . " WHERE img_name=" . $dbw->addQuotes($row->img_name); if ($method == 'pipe') { fwrite($pipe, "{$sql};\n"); } else { $dbw->query($sql, __METHOD__); } } $i++; } if ($method == 'pipe') { fflush($pipe); pclose($pipe); } $t += microtime(true); $this->output(sprintf("\nDone %d files in %.1f seconds\n", $numRows, $t)); return !$file; // we only updated *some* files, don't log }
/** * @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; }
public function testMultipleArgsAsArray() { if (wfIsWindows()) { $expected = '"foo" "bar" "baz"'; } else { $expected = "'foo' 'bar' 'baz'"; } $actual = wfEscapeShellArg(['foo', 'bar', 'baz']); $this->assertEquals($expected, $actual); }
function renderGnuplot($gnuplotsrc) { global $wgGnuplotDefaultTerminal, $wgGnuplotDefaultSize, $wgGnuplotCommand; global $wgUploadDirectory, $wgUploadPath; // filter out harmfull system commands to close a security hole $replaces = array("`" => "", "system" => "", "shell" => ""); $gnuplotsrc = strtr($gnuplotsrc, $replaces); // create directory for storing the plot $gnuplotDir = "/gnuplot/"; $dest = $wgUploadDirectory . $gnuplotDir; if (!is_dir($dest)) { mkdir($dest, 0777); chmod($dest, 0777); } // get the name of the graph to be produced $name = getOutputName($gnuplotsrc); $graphname = $dest . $name; $fname = $graphname . ".tmp"; // write the default settings and the input code from wiki into a // temporary file to be executed by gnuplot, then execute the command if (!(file_exists($fname) || file_exists($fname . '.err'))) { $handle = fopen($fname, 'x'); if ($handle === FALSE) { // not sure what to do here, this shouldn't happen return '<p><b><img src="' . htmlspecialchars($wgUploadPath . $gnuplotDir . $name) . '" alt="Gnuplot Plot"></b></p>'; } // if terminal and size are not set in the gnuplot source we do it here if (strpos($gnuplotsrc, 'set terminal ') === false) { fwrite($handle, $wgGnuplotDefaultTerminal . "\n"); } if (strpos($gnuplotsrc, 'set size ') === false) { fwrite($handle, $wgGnuplotDefaultSize . "\n"); } // Need to find each occurance of src:<FILE NAME> and replace it // with the complete file path while (strpos($gnuplotsrc, 'src:') != false) { $srcStartPosition = strpos($gnuplotsrc, 'src:') + strlen("src:"); $srcEndPosition = strpos($gnuplotsrc, ' ', $srcStartPosition); $tmpString = substr($gnuplotsrc, $srcStartPosition, $srcEndPosition - $srcStartPosition - 1); $srcFileNamePath = getSourceDataPath($tmpString); $gnuplotsrc = str_replace("src:{$tmpString}", $srcFileNamePath, $gnuplotsrc); } fwrite($handle, "\nset output '" . $graphname . "'\n"); // Remove the 'set output' command from the source as we will set it. $gnuplotsrc = preg_replace('/^set output.*$/m', '', $gnuplotsrc); fwrite($handle, $gnuplotsrc . "\n"); fclose($handle); $cmdlinePlot = wfEscapeShellArg($wgGnuplotCommand) . ' ' . wfEscapeShellArg($fname); shell_exec($cmdlinePlot); // some cleanup unlink($fname); } return '<p><b><img src="' . htmlspecialchars($wgUploadPath . $gnuplotDir . $name) . '" alt="Gnuplot Plot"></b></p>'; }
public function execute() { $method = $this->getOption('method', 'normal'); $file = $this->getOption('file'); $t = -microtime(true); $dbw = wfGetDB(DB_MASTER); if ($file) { $res = $dbw->selectRow('image', array('img_name'), array('img_name' => $dbw->addQuotes($file)), __METHOD__); if (!$res) { $this->error("No such file: {$file}", true); return; } } else { $res = $dbw->select('image', array('img_name'), array('img_sha1' => ''), __METHOD__); } $imageTable = $dbw->tableName('image'); $oldimageTable = $dbw->tableName('oldimage'); $batch = array(); if ($method == 'pipe') { // @fixme kill this and replace with a second unbuffered DB connection. global $wgDBuser, $wgDBserver, $wgDBpassword, $wgDBname; $cmd = 'mysql -u' . wfEscapeShellArg($wgDBuser) . ' -h' . wfEscapeShellArg($wgDBserver) . ' -p' . wfEscapeShellArg($wgDBpassword, $wgDBname); $this->output("Using pipe method\n"); $pipe = popen($cmd, 'w'); } $numRows = $res->numRows(); $i = 0; foreach ($res as $row) { if ($i % 100 == 0) { $this->output(sprintf("Done %d of %d, %5.3f%% \r", $i, $numRows, $i / $numRows * 100)); wfWaitForSlaves(5); } $file = wfLocalFile($row->img_name); if (!$file) { continue; } $sha1 = File::sha1Base36($file->getPath()); if (strval($sha1) !== '') { $sql = "UPDATE {$imageTable} SET img_sha1=" . $dbw->addQuotes($sha1) . " WHERE img_name=" . $dbw->addQuotes($row->img_name); if ($method == 'pipe') { fwrite($pipe, "{$sql};\n"); } else { $dbw->query($sql, __METHOD__); } } $i++; } if ($method == 'pipe') { fflush($pipe); pclose($pipe); } $t += microtime(true); $this->output(sprintf("\nDone %d files in %.1f seconds\n", $numRows, $t)); }
function renderGraphviz($timelinesrc) { global $wgUploadDirectory, $wgUploadPath, $IP, $wgGraphVizSettings, $wgArticlePath, $wgTmpDirectory; $hash = md5($timelinesrc); $dest = $wgUploadDirectory . "/graphviz/"; if (!is_dir($dest)) { mkdir($dest, 0777); } if (!is_dir($wgTmpDirectory)) { mkdir($wgTmpDirectory, 0777); } $fname = $dest . $hash; // echo $fname; if (!(file_exists($fname . ".png") || file_exists($fname . ".err"))) { $handle = fopen($fname, "w"); fwrite($handle, $timelinesrc); fclose($handle); $cmdline = wfEscapeShellArg($wgGraphVizSettings->dotCommand) . " -Tpng -o " . wfEscapeShellArg($fname . ".png") . " " . wfEscapeShellArg($fname); $cmdlinemap = wfEscapeShellArg($wgGraphVizSettings->dotCommand) . " -Tcmapx -o " . wfEscapeShellArg($fname . ".map") . " " . wfEscapeShellArg($fname); // echo $cmdline; // exit; // break; // echo "ADIOS"; $ret = `{$cmdline}`; $ret = `{$cmdlinemap}`; unlink($fname); /* if ( $ret == "" ) { // Message not localized, only relevant during install return "<div id=\"toc\"><tt>Timeline error: Executable not found. Command line was: {$cmdline}</tt></div>"; } */ } @($err = file_get_contents($fname . ".err")); if ($err != "") { $txt = "<div id=\"toc\"><tt>{$err}</tt></div>"; } else { //echo $fname.".map"; @($map = file_get_contents($fname . ".map")); //echo "mapa-antes:".$map; $map = preg_replace("#<ma(.*)>#", " ", $map); $map = str_replace("</map>", "", $map); //echo "mapa:".$map; if (substr(php_uname(), 0, 7) == "Windows") { $ext = "gif"; } else { $ext = "png"; } $txt = "<map name=\"{$hash}\">{$map}</map>" . "<img usemap=\"#{$hash}\" src=\"{$wgUploadPath}/graphviz/{$hash}.{$ext}\">"; } return $txt; }
function renderTimeline($timelinesrc) { global $wgUploadDirectory, $wgUploadPath, $IP, $wgTimelineSettings, $wgArticlePath, $wgTmpDirectory; $hash = md5($timelinesrc); $dest = $wgUploadDirectory . "/timeline/"; if (!is_dir($dest)) { mkdir($dest, 0777); } if (!is_dir($wgTmpDirectory)) { mkdir($wgTmpDirectory, 0777); } $fname = $dest . $hash; $previouslyFailed = file_exists($fname . ".err"); $previouslyRendered = file_exists($fname . ".png"); $expired = $previouslyRendered && filemtime($fname . ".png") < wfTimestamp(TS_UNIX, $wgTimelineSettings->epochTimestamp); if ($expired || !$previouslyRendered && !$previouslyFailed) { $handle = fopen($fname, "w"); fwrite($handle, $timelinesrc); fclose($handle); $cmdline = wfEscapeShellArg($wgTimelineSettings->perlCommand, $wgTimelineSettings->timelineFile) . " -i " . wfEscapeShellArg($fname) . " -m -P " . wfEscapeShellArg($wgTimelineSettings->ploticusCommand) . " -T " . wfEscapeShellArg($wgTmpDirectory) . " -A " . wfEscapeShellArg($wgArticlePath); $ret = `{$cmdline}`; unlink($fname); if ($ret == "") { // Message not localized, only relevant during install return "<div id=\"toc\"><tt>Timeline error: Executable not found. Command line was: {$cmdline}</tt></div>"; } } @($err = file_get_contents($fname . ".err")); if ($err != "") { $txt = "<div id=\"toc\"><tt>{$err}</tt></div>"; } else { @($map = file_get_contents($fname . ".map")); if (substr(php_uname(), 0, 7) == "Windows") { $ext = "gif"; } else { $ext = "png"; } $url = "{$wgUploadPath}/timeline/{$hash}.{$ext}"; $txt = "<map name=\"{$hash}\">{$map}</map>" . "<img usemap=\"#{$hash}\" src=\"{$url}\">"; if ($expired) { // Replacing an older file, we may need to purge the old one. global $wgUseSquid; if ($wgUseSquid) { $u = new SquidUpdate(array($url)); $u->doUpdate(); } } } return $txt; }
static function tryFfmpegThumb( $options ){ global $wgFFmpegLocation; $cmd = wfEscapeShellArg( $wgFFmpegLocation ); $offset = intval( self::getThumbTime( $options ) ); /* This is a workaround until ffmpegs ogg demuxer properly seeks to keyframes. Seek 2 seconds before offset and seek in decoded stream after that. -ss before input seeks without decode -ss after input seeks in decoded stream */ if($offset > 2) { $cmd .= ' -ss ' . ($offset - 2); $offset = 2; } $srcPath = $options['file']->getLocalRefPath(); $cmd .= ' -y -i ' . wfEscapeShellArg( $srcPath ); $cmd .= ' -ss ' . $offset . ' '; // Set the output size if set in options: if( isset( $options['width'] ) && isset( $options['height'] ) ){ $cmd.= ' -s '. intval( $options['width'] ) . 'x' . intval( $options['height'] ); } # MJPEG, that's the same as JPEG except it's supported by the windows build of ffmpeg # No audio, one frame $cmd .= ' -f mjpeg -an -vframes 1 ' . wfEscapeShellArg( $options['dstPath'] ) . ' 2>&1'; $retval = 0; $returnText = wfShellExec( $cmd, $retval ); // Check if it was successful if ( !$options['file']->getHandler()->removeBadFile( $options['dstPath'], $retval ) ) { return true; } // Filter nonsense $lines = explode( "\n", str_replace( "\r\n", "\n", $returnText ) ); if ( substr( $lines[0], 0, 6 ) == 'FFmpeg' ) { for ( $i = 1; $i < count( $lines ); $i++ ) { if ( substr( $lines[$i], 0, 2 ) != ' ' ) { break; } } $lines = array_slice( $lines, $i ); } // Return error box return new MediaTransformError( 'thumbnail_error', $options['width'], $options['height'], implode( "\n", $lines ) ); }
public function execute() { $max_words = intval( $this->getOption( 'maxwords', 10000 ) ); $indexer = wfEscapeShellArg( $this->getOption( 'indexer', 'indexer' ) ); $index = wfEscapeShellArg( $this->getOption( 'useindex', 'wiki_main' ) ); $conf = wfEscapeShellArg( $this->getOption( 'spinxconf' ) ); $cmd = "$indexer --config $conf $index --buildstops sphinx.dic $max_words"; $this->output( wfShellExec( $cmd, $retval ) ); if ( file_exists( 'sphinx.dic' ) ) { $words = file('sphinx.dic'); $cnt = count($words); if ($cnt) { file_put_contents( 'sphinx.dic', $cnt . "\n" . join( '', $words ) ); file_put_contents( 'sphinx.aff', "SET UTF-8\n" ); } } }
function runLatex($text, $command, $ext) { global $wgOut, $IP; // Filter out obvious insecure control sequences $text = preg_replace("/\\\\(input|openin|openout|read|write|escapechar)/", '\\begin{math}\\backslash\\end{math}\\1', $text); // Get path if (!is_dir($this->workingDir)) { if (!mkdir($this->workingDir, 0777)) { $wgOut->addWikiText(wfMsg('latexdoc_cant_create_dir', $this->workingDir)); return; } } $hash = md5($text); $fn = $this->workingDir . '/' . 'ltd_' . $hash; $url = $this->workingPath . '/' . 'ltd_' . $hash; if (!file_exists("{$fn}.{$ext}")) { // Write input file $inFile = fopen("{$fn}.tex", 'w'); if (!$inFile) { $wgOut->addWikiText(wfMsg('latexdoc_cant_write', "{$fn}.tex")); return; } fwrite($inFile, $text); fclose($inFile); // Run LaTeX $cmd = $command . ' -interaction=batchmode -quiet ' . '\\input ' . wfEscapeShellArg("{$fn}.tex") . ' 2>&1'; chdir($this->workingDir); $errorText = shell_exec($cmd); chdir($IP); // Report errors if (!file_exists("{$fn}.{$ext}")) { wfSuppressWarnings(); $log = '<pre>' . file_get_contents("{$fn}.log") . '</pre>'; wfRestoreWarnings(); $wgOut->addWikiText(wfMsg('latexdoc_error', $cmd, $errorText, $log)); return; } } // Redirect to output file $wgOut->redirect("{$url}.{$ext}"); // Delete temporary files @unlink("{$fn}.tex"); @unlink("{$fn}.aux"); @unlink("{$fn}.log"); }
public function rasterize($srcPath, $dstPath, $width, $height) { global $wgSVGConverters, $wgSVGConverter, $wgSVGConverterPath; $err = false; if (isset($wgSVGConverters[$wgSVGConverter])) { $cmd = str_replace(array('$path/', '$width', '$height', '$input', '$output'), array($wgSVGConverterPath ? wfEscapeShellArg("{$wgSVGConverterPath}/") : "", intval($width), intval($height), wfEscapeShellArg($srcPath), wfEscapeShellArg($dstPath)), $wgSVGConverters[$wgSVGConverter]) . " 2>&1"; wfProfileIn('rsvg'); wfDebug(__METHOD__ . ": {$cmd}\n"); $err = wfShellExec($cmd, $retval); wfProfileOut('rsvg'); } $removed = $this->removeBadFile($dstPath, $retval); if ($retval != 0 || $removed) { wfDebugLog('thumbnail', sprintf('thumbnail failed on %s: error %d "%s" from "%s"', wfHostname(), $retval, trim($err), $cmd)); return new MediaTransformError('thumbnail_error', $width, $height, $err); } return true; }
function stream_open($path, $mode, $options, &$opened_path) { if ($mode[0] == 'r') { $options = 'e -bd -so'; } elseif ($mode[0] == 'w') { $options = 'a -bd -si'; } else { return false; } $arg = wfEscapeShellArg($this->stripPath($path)); $command = "7za {$options} {$arg}"; if (!wfIsWindows()) { // Suppress the stupid messages on stderr $command .= ' 2>/dev/null'; } $this->stream = popen($command, $mode); return $this->stream !== false; }
/** * Execute a shell command to obtain the parse tree of a string of wikitext * * @param String wikitext * @return Array ret Array of two keys, 'contents' with script output, 'errors' with errors if any. */ public function getParseTree($text) { global $wgVisualEditorParserCmd, $wgServer, $wgScriptPath; // TODO This is probably not very portable to non-Unix OS. There's a lot of code in wfShellExec to make // that portable and secure on Windows etc. In any case the existing PHP-based parser calls out to an external script to do // HTML-tidy anyway, in a similar manner, without any shell escapes... $cmd = join(" ", array($wgVisualEditorParserCmd, '--wgScriptPath', wfEscapeShellArg($wgServer . $wgScriptPath))); $parserIn = 0; $parserOut = 1; $parserErr = 2; $descriptorSpec = array($parserIn => array('pipe', 'r'), $parserOut => array('pipe', 'w'), $parserErr => array('pipe', 'w')); $pipes = array(); $process = proc_open($cmd, $descriptorSpec, $pipes); $ret = array('contents' => null); 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. // // TODO This might be an opportune time to give the parser all the subtemplates it's going to need, // such that we can. The DB does have a mapping of title to templates used. // Would need a convention for indicating multiple files in the text we write to the parser, like mime multipart fwrite($pipes[$parserIn], $text); fclose($pipes[$parserIn]); $ret['contents'] = FormatJson::decode(self::readFilehandle($pipes[$parserOut])); $errors = self::readFilehandle($pipes[$parserErr]); if ($errors != '' and $errors != null) { $ret['errors'] = $errors; } $retval = proc_close($process); if ($retval != 0) { wfWarn("Parser process returned {$retval}"); if (!$ret['errors']) { $ret['errors'] = 'External parser process returned error code, check server logs'; } } } else { wfWarn("Unable to start external parser process"); $ret['errors'] = "Unable to start external parser process, check server logs"; } return $ret; }
/** * @param $file File * @param array $params Rotate parameters. * 'rotation' clockwise rotation in degrees, allowed are multiples of 90 * @since 1.21 * @return bool */ public function rotate($file, $params) { global $wgJpegTran; $rotation = ($params['rotation'] + $this->getRotation($file)) % 360; if ($wgJpegTran && is_file($wgJpegTran)) { $cmd = wfEscapeShellArg($wgJpegTran) . " -rotate " . wfEscapeShellArg($rotation) . " -outfile " . wfEscapeShellArg($params['dstPath']) . " " . wfEscapeShellArg($params['srcPath']) . " 2>&1"; wfDebug(__METHOD__ . ": running jpgtran: {$cmd}\n"); wfProfileIn('jpegtran'); $retval = 0; $err = wfShellExec($cmd, $retval, $env); wfProfileOut('jpegtran'); if ($retval !== 0) { $this->logErrorForExternalProcess($retval, $err, $cmd); return new MediaTransformError('thumbnail_error', 0, 0, $err); } return false; } else { return parent::rotate($file, $params); } }
/** * Return an XML string describing the DjVu image * @return string|bool */ function retrieveMetaData() { global $wgDjvuToXML, $wgDjvuDump, $wgDjvuTxt; if (!$this->isValid()) { return false; } if (isset($wgDjvuDump)) { # djvudump is faster as of version 3.5 # http://sourceforge.net/tracker/index.php?func=detail&aid=1704049&group_id=32953&atid=406583 $cmd = wfEscapeShellArg($wgDjvuDump) . ' ' . wfEscapeShellArg($this->mFilename); $dump = wfShellExec($cmd); $xml = $this->convertDumpToXML($dump); } elseif (isset($wgDjvuToXML)) { $cmd = wfEscapeShellArg($wgDjvuToXML) . ' --without-anno --without-text ' . wfEscapeShellArg($this->mFilename); $xml = wfShellExec($cmd); } else { $xml = null; } # Text layer if (isset($wgDjvuTxt)) { $cmd = wfEscapeShellArg($wgDjvuTxt) . ' --detail=page ' . wfEscapeShellArg($this->mFilename); wfDebug(__METHOD__ . ": {$cmd}\n"); $retval = ''; $txt = wfShellExec($cmd, $retval, [], ['memory' => self::DJVUTXT_MEMORY_LIMIT]); if ($retval == 0) { # Strip some control characters $txt = preg_replace("/[\v]/", "", $txt); $reg = <<<EOR \t\t\t\t\t/\\(page\\s[\\d-]*\\s[\\d-]*\\s[\\d-]*\\s[\\d-]*\\s*" \t\t\t\t\t((?> # Text to match is composed of atoms of either: \t\t\t\t\t \\\\. # - any escaped character \t\t\t\t\t | # - any character different from " and \\ \t\t\t\t\t [^"\\\\]+ \t\t\t\t\t)*?) \t\t\t\t\t"\\s*\\) \t\t\t\t\t| # Or page can be empty ; in this case, djvutxt dumps () \t\t\t\t\t\\(\\s*()\\)/sx EOR; $txt = preg_replace_callback($reg, [$this, 'pageTextCallback'], $txt); $txt = "<DjVuTxt>\n<HEAD></HEAD>\n<BODY>\n" . $txt . "</BODY>\n</DjVuTxt>\n"; $xml = preg_replace("/<DjVuXML>/", "<mw-djvu><DjVuXML>", $xml, 1); $xml = $xml . $txt . '</mw-djvu>'; } } return $xml; }
/** * Generate a diff, no caching * * @param $otext String: old text, must be already segmented * @param $ntext String: new text, must be already segmented */ function generateDiffBody($otext, $ntext) { global $wgExternalDiffEngine, $wgContLang; wfProfileIn(__METHOD__); $otext = str_replace("\r\n", "\n", $otext); $ntext = str_replace("\r\n", "\n", $ntext); $this->initDiffEngines(); if ($wgExternalDiffEngine == 'wikidiff' && function_exists('wikidiff_do_diff')) { # For historical reasons, external diff engine expects # input text to be HTML-escaped already $otext = htmlspecialchars($wgContLang->segmentForDiff($otext)); $ntext = htmlspecialchars($wgContLang->segmentForDiff($ntext)); wfProfileOut(__METHOD__); return $wgContLang->unsegmentForDiff(wikidiff_do_diff($otext, $ntext, 2)) . $this->debug('wikidiff1'); } if ($wgExternalDiffEngine == 'wikidiff2' && function_exists('wikidiff2_do_diff')) { # Better external diff engine, the 2 may some day be dropped # This one does the escaping and segmenting itself wfProfileIn('wikidiff2_do_diff'); $text = wikidiff2_do_diff($otext, $ntext, 2); $text .= $this->debug('wikidiff2'); wfProfileOut('wikidiff2_do_diff'); wfProfileOut(__METHOD__); return $text; } if ($wgExternalDiffEngine != 'wikidiff3' && $wgExternalDiffEngine !== false) { # Diff via the shell global $wgTmpDirectory; $tempName1 = tempnam($wgTmpDirectory, 'diff_'); $tempName2 = tempnam($wgTmpDirectory, 'diff_'); $tempFile1 = fopen($tempName1, "w"); if (!$tempFile1) { wfProfileOut(__METHOD__); return false; } $tempFile2 = fopen($tempName2, "w"); if (!$tempFile2) { wfProfileOut(__METHOD__); return false; } fwrite($tempFile1, $otext); fwrite($tempFile2, $ntext); fclose($tempFile1); fclose($tempFile2); $cmd = wfEscapeShellArg($wgExternalDiffEngine, $tempName1, $tempName2); wfProfileIn(__METHOD__ . "-shellexec"); $difftext = wfShellExec($cmd); $difftext .= $this->debug("external {$wgExternalDiffEngine}"); wfProfileOut(__METHOD__ . "-shellexec"); unlink($tempName1); unlink($tempName2); wfProfileOut(__METHOD__); return $difftext; } # Native PHP diff $ota = explode("\n", $wgContLang->segmentForDiff($otext)); $nta = explode("\n", $wgContLang->segmentForDiff($ntext)); $diffs = new Diff($ota, $nta); $formatter = new TableDiffFormatter(); $difftext = $wgContLang->unsegmentForDiff($formatter->format($diffs)) . wfProfileOut(__METHOD__); return $difftext; }
/** Generic wrapper function for a virus scanner program. * This relies on the $wgAntivirus and $wgAntivirusSetup variables. * $wgAntivirusRequired may be used to deny upload if the scan fails. * * @param string $file Pathname to the temporary upload file * @return mixed false if not virus is found, NULL if the scan fails or is disabled, * or a string containing feedback from the virus scanner if a virus was found. * If textual feedback is missing but a virus was found, this function returns true. */ function detectVirus($file) { global $wgAntivirus, $wgAntivirusSetup, $wgAntivirusRequired, $wgOut; $fname = "SpecialUpload::detectVirus"; if (!$wgAntivirus) { #disabled? wfDebug("{$fname}: virus scanner disabled\n"); return NULL; } if (!$wgAntivirusSetup[$wgAntivirus]) { wfDebug("{$fname}: unknown virus scanner: {$wgAntivirus}\n"); $wgOut->addHTML("<div class='error'>Bad configuration: unknown virus scanner: <i>{$wgAntivirus}</i></div>\n"); #LOCALIZE return "unknown antivirus: {$wgAntivirus}"; } #look up scanner configuration $virus_scanner = $wgAntivirusSetup[$wgAntivirus]["command"]; #command pattern $virus_scanner_codes = $wgAntivirusSetup[$wgAntivirus]["codemap"]; #exit-code map $msg_pattern = $wgAntivirusSetup[$wgAntivirus]["messagepattern"]; #message pattern $scanner = $virus_scanner; #copy, so we can resolve the pattern if (strpos($scanner, "%f") === false) { $scanner .= " " . wfEscapeShellArg($file); } else { $scanner = str_replace("%f", wfEscapeShellArg($file), $scanner); } #complex pattern: replace "%f" with file to scan wfDebug("{$fname}: running virus scan: {$scanner} \n"); #execute virus scanner $code = false; #NOTE: there's a 50 line workaround to make stderr redirection work on windows, too. # that does not seem to be worth the pain. # Ask me (Duesentrieb) about it if it's ever needed. if (wfIsWindows()) { exec("{$scanner}", $output, $code); } else { exec("{$scanner} 2>&1", $output, $code); } $exit_code = $code; #remeber for user feedback if ($virus_scanner_codes) { #map exit code to AV_xxx constants. if (isset($virus_scanner_codes[$code])) { $code = $virus_scanner_codes[$code]; } else { if (isset($virus_scanner_codes["*"])) { $code = $virus_scanner_codes["*"]; } } #fallback mapping } if ($code === AV_SCAN_FAILED) { #scan failed (code was mapped to false by $virus_scanner_codes) wfDebug("{$fname}: failed to scan {$file} (code {$exit_code}).\n"); if ($wgAntivirusRequired) { return "scan failed (code {$exit_code})"; } else { return NULL; } } else { if ($code === AV_SCAN_ABORTED) { #scan failed because filetype is unknown (probably imune) wfDebug("{$fname}: unsupported file type {$file} (code {$exit_code}).\n"); return NULL; } else { if ($code === AV_NO_VIRUS) { wfDebug("{$fname}: file passed virus scan.\n"); return false; #no virus found } else { $output = join("\n", $output); $output = trim($output); if (!$output) { $output = true; } else { if ($msg_pattern) { $groups = array(); if (preg_match($msg_pattern, $output, $groups)) { if ($groups[1]) { $output = $groups[1]; } } } } wfDebug("{$fname}: FOUND VIRUS! scanner feedback: {$output}"); return $output; } } } }
/** * Start the worker processes. * These processes will listen on stdin for commands. * This necessary because text recompression is slow: loading, compressing and * writing are all slow. */ function startSlaveProcs() { $cmd = 'php ' . wfEscapeShellArg(__FILE__); foreach (self::$cmdLineOptionMap as $cmdOption => $classOption) { if ($cmdOption == 'slave-id') { continue; } elseif (in_array($cmdOption, self::$optionsWithArgs) && isset($this->{$classOption})) { $cmd .= " --{$cmdOption} " . wfEscapeShellArg($this->{$classOption}); } elseif ($this->{$classOption}) { $cmd .= " --{$cmdOption}"; } } $cmd .= ' --child' . ' --wiki ' . wfEscapeShellArg(wfWikiID()) . ' ' . call_user_func_array('wfEscapeShellArg', $this->destClusters); $this->slavePipes = $this->slaveProcs = array(); for ($i = 0; $i < $this->numProcs; $i++) { $pipes = false; $spec = array(array('pipe', 'r'), array('file', 'php://stdout', 'w'), array('file', 'php://stderr', 'w')); wfSuppressWarnings(); $proc = proc_open("{$cmd} --slave-id {$i}", $spec, $pipes); wfRestoreWarnings(); if (!$proc) { $this->critical("Error opening slave process: {$cmd}"); exit(1); } $this->slaveProcs[$i] = $proc; $this->slavePipes[$i] = $pipes[0]; } $this->prevSlaveId = -1; }
/** * Retrieve the version of the installed ImageMagick * You can use PHPs version_compare() to use this value * Value is cached for one hour. * @return String representing the IM version. */ protected function getMagickVersion() { global $wgMemc; $cache = $wgMemc->get("imagemagick-version"); if (!$cache) { global $wgImageMagickConvertCommand; $cmd = wfEscapeShellArg($wgImageMagickConvertCommand) . ' -version'; wfDebug(__METHOD__ . ": Running convert -version\n"); $retval = ''; $return = wfShellExec($cmd, $retval); $x = preg_match('/Version: ImageMagick ([0-9]*\\.[0-9]*\\.[0-9]*)/', $return, $matches); if ($x != 1) { wfDebug(__METHOD__ . ": ImageMagick version check failed\n"); return null; } $wgMemc->set("imagemagick-version", $matches[1], 3600); return $matches[1]; } return $cache; }
/** * Search a path for any of the given executable names. Returns the * executable name if found. Also checks the version string returned * by each executable. * * Used only by environment checks. * * @param $path String: path to search * @param $names Array of executable names * @param $versionInfo Boolean false or array with two members: * 0 => Command to run for version check, with $1 for the full executable name * 1 => String to compare the output with * * If $versionInfo is not false, only executables with a version * matching $versionInfo[1] will be returned. */ public static function locateExecutable($path, $names, $versionInfo = false) { if (!is_array($names)) { $names = array($names); } foreach ($names as $name) { $command = $path . DIRECTORY_SEPARATOR . $name; wfSuppressWarnings(); $file_exists = file_exists($command); wfRestoreWarnings(); if ($file_exists) { if (!$versionInfo) { return $command; } $file = str_replace('$1', wfEscapeShellArg($command), $versionInfo[0]); if (strstr(wfShellExec($file), $versionInfo[1]) !== false) { return $command; } } } return false; }
/** * @param File $file * @param array $params Rotate parameters. * 'rotation' clockwise rotation in degrees, allowed are multiples of 90 * @since 1.21 * @return bool */ public function rotate($file, $params) { global $wgImageMagickConvertCommand; $rotation = ($params['rotation'] + $this->getRotation($file)) % 360; $scene = false; $scaler = $this->getScalerType(null, false); switch ($scaler) { case 'im': $cmd = wfEscapeShellArg($wgImageMagickConvertCommand) . " " . wfEscapeShellArg($this->escapeMagickInput($params['srcPath'], $scene)) . " -rotate " . wfEscapeShellArg("-{$rotation}") . " " . wfEscapeShellArg($this->escapeMagickOutput($params['dstPath'])); wfDebug(__METHOD__ . ": running ImageMagick: {$cmd}\n"); $retval = 0; $err = wfShellExecWithStderr($cmd, $retval); if ($retval !== 0) { $this->logErrorForExternalProcess($retval, $err, $cmd); return new MediaTransformError('thumbnail_error', 0, 0, $err); } return false; case 'imext': $im = new Imagick(); $im->readImage($params['srcPath']); if (!$im->rotateImage(new ImagickPixel('white'), 360 - $rotation)) { return new MediaTransformError('thumbnail_error', 0, 0, "Error rotating {$rotation} degrees"); } $result = $im->writeImage($params['dstPath']); if (!$result) { return new MediaTransformError('thumbnail_error', 0, 0, "Unable to write image to {$params['dstPath']}"); } return false; default: return new MediaTransformError('thumbnail_error', 0, 0, "{$scaler} rotation not implemented"); } }
/** * Internal mime type detection. Detection is done using an external * program, if $wgMimeDetectorCommand is set. Otherwise, the fileinfo * extension and mime_content_type are tried (in this order), if they * are available. If the dections fails and $ext is not false, the mime * type is guessed from the file extension, using guessTypesForExtension. * * If the mime type is still unknown, getimagesize is used to detect the * mime type if the file is an image. If no mime type can be determined, * this function returns 'unknown/unknown'. * * @param $file String: the file to check * @param $ext Mixed: the file extension, or true (default) to extract it from the filename. * Set it to false to ignore the extension. DEPRECATED! Set to false, use * improveTypeFromExtension($mime, $ext) later to improve mime type. * * @return string the mime type of $file */ private function detectMimeType($file, $ext = true) { global $wgMimeDetectorCommand; if ($ext) { # TODO: make $ext default to false. Or better, remove it. wfDebug(__METHOD__ . ": WARNING: use of the \$ext parameter is deprecated. Use improveTypeFromExtension(\$mime, \$ext) instead.\n"); } $m = null; if ($wgMimeDetectorCommand) { // @todo FIXME: Use wfShellExec $fn = wfEscapeShellArg($file); $m = `{$wgMimeDetectorCommand} {$fn}`; } elseif (function_exists("finfo_open") && function_exists("finfo_file")) { # This required the fileinfo extension by PECL, # see http://pecl.php.net/package/fileinfo # This must be compiled into PHP # # finfo is the official replacement for the deprecated # mime_content_type function, see below. # # If you may need to load the fileinfo extension at runtime, set # $wgLoadFileinfoExtension in LocalSettings.php $mime_magic_resource = finfo_open(FILEINFO_MIME); /* return mime type ala mimetype extension */ if ($mime_magic_resource) { $m = finfo_file($mime_magic_resource, $file); finfo_close($mime_magic_resource); } else { wfDebug(__METHOD__ . ": finfo_open failed on " . FILEINFO_MIME . "!\n"); } } elseif (function_exists("mime_content_type")) { # NOTE: this function is available since PHP 4.3.0, but only if # PHP was compiled with --with-mime-magic or, before 4.3.2, with --enable-mime-magic. # # On Windows, you must set mime_magic.magicfile in php.ini to point to the mime.magic file bundeled with PHP; # sometimes, this may even be needed under linus/unix. # # Also note that this has been DEPRECATED in favor of the fileinfo extension by PECL, see above. # see http://www.php.net/manual/en/ref.mime-magic.php for details. $m = mime_content_type($file); } else { wfDebug(__METHOD__ . ": no magic mime detector found!\n"); } if ($m) { # normalize $m = preg_replace('![;, ].*$!', '', $m); #strip charset, etc $m = trim($m); $m = strtolower($m); if (strpos($m, 'unknown') !== false) { $m = null; } else { wfDebug(__METHOD__ . ": magic mime type of {$file}: {$m}\n"); return $m; } } // If desired, look at extension as a fallback. if ($ext === true) { $i = strrpos($file, '.'); $ext = strtolower($i ? substr($file, $i + 1) : ''); } if ($ext) { if ($this->isRecognizableExtension($ext)) { wfDebug(__METHOD__ . ": refusing to guess mime type for .{$ext} file, we should have recognized it\n"); } else { $m = $this->guessTypesForExtension($ext); if ($m) { wfDebug(__METHOD__ . ": extension mime type of {$file}: {$m}\n"); return $m; } } } // Unknown type wfDebug(__METHOD__ . ": failed to guess mime type for {$file}!\n"); return 'unknown/unknown'; }
/** * Returns a string of extra arguments to be passed into the shell commands */ private function getExtraArgs() { global $wgSubversionOptions, $wgSubversionUser, $wgSubversionPassword; $args = $wgSubversionOptions; if ($wgSubversionUser) { $args .= ' --username ' . wfEscapeShellArg($wgSubversionUser) . ' --password ' . wfEscapeShellArg($wgSubversionPassword); } return $args; }
/** * Check a file for syntax errors using php -l * @param $file String Path to a file to check for syntax errors * @return boolean */ private function checkFileWithCli($file) { $res = exec('php -l ' . wfEscapeShellArg($file)); if (strpos($res, 'No syntax errors detected') === false) { $this->mFailures[$file] = $res; $this->output($res . "\n"); return false; } return true; }