MediaWiki REL1_32
Shell.php
Go to the documentation of this file.
1<?php
23namespace MediaWiki\Shell;
24
25use Hooks;
27
44class Shell {
45
52 const NO_ROOT = 1;
53
60 const SECCOMP = 2;
61
67 const PRIVATE_DEV = 4;
68
75 const NO_NETWORK = 8;
76
83 const NO_EXECVE = 16;
84
90 const NO_LOCALSETTINGS = 32;
91
100 const RESTRICT_DEFAULT = self::NO_ROOT | self::SECCOMP | self::PRIVATE_DEV |
102
108 const RESTRICT_NONE = 0;
109
119 public static function command( ...$commands ) {
120 if ( count( $commands ) === 1 && is_array( reset( $commands ) ) ) {
121 // If only one argument has been passed, and that argument is an array,
122 // treat it as a list of arguments
123 $commands = reset( $commands );
124 }
126 ->getShellCommandFactory()
127 ->create();
128
129 return $command->params( $commands );
130 }
131
137 public static function isDisabled() {
138 static $disabled = null;
139
140 if ( is_null( $disabled ) ) {
141 if ( !function_exists( 'proc_open' ) ) {
142 wfDebug( "proc_open() is disabled\n" );
143 $disabled = true;
144 } else {
145 $disabled = false;
146 }
147 }
148
149 return $disabled;
150 }
151
163 public static function escape( ...$args ) {
164 if ( count( $args ) === 1 && is_array( reset( $args ) ) ) {
165 // If only one argument has been passed, and that argument is an array,
166 // treat it as a list of arguments
167 $args = reset( $args );
168 }
169
170 $first = true;
171 $retVal = '';
172 foreach ( $args as $arg ) {
173 if ( $arg === null ) {
174 continue;
175 }
176 if ( !$first ) {
177 $retVal .= ' ';
178 } else {
179 $first = false;
180 }
181
182 if ( wfIsWindows() ) {
183 // Escaping for an MSVC-style command line parser and CMD.EXE
184 // Refs:
185 // * https://web.archive.org/web/20020708081031/http://mailman.lyra.org/pipermail/scite-interest/2002-March/000436.html
186 // * https://technet.microsoft.com/en-us/library/cc723564.aspx
187 // * T15518
188 // * CR r63214
189 // Double the backslashes before any double quotes. Escape the double quotes.
190 $tokens = preg_split( '/(\\\\*")/', $arg, -1, PREG_SPLIT_DELIM_CAPTURE );
191 $arg = '';
192 $iteration = 0;
193 foreach ( $tokens as $token ) {
194 if ( $iteration % 2 == 1 ) {
195 // Delimiter, a double quote preceded by zero or more slashes
196 $arg .= str_replace( '\\', '\\\\', substr( $token, 0, -1 ) ) . '\\"';
197 } elseif ( $iteration % 4 == 2 ) {
198 // ^ in $token will be outside quotes, need to be escaped
199 $arg .= str_replace( '^', '^^', $token );
200 } else { // $iteration % 4 == 0
201 // ^ in $token will appear inside double quotes, so leave as is
202 $arg .= $token;
203 }
204 $iteration++;
205 }
206 // Double the backslashes before the end of the string, because
207 // we will soon add a quote
208 $m = [];
209 if ( preg_match( '/^(.*?)(\\\\+)$/', $arg, $m ) ) {
210 $arg = $m[1] . str_replace( '\\', '\\\\', $m[2] );
211 }
212
213 // Add surrounding quotes
214 $retVal .= '"' . $arg . '"';
215 } else {
216 $retVal .= escapeshellarg( $arg );
217 }
218 }
219 return $retVal;
220 }
221
235 public static function makeScriptCommand( $script, $parameters, $options = [] ) {
236 global $wgPhpCli;
237 // Give site config file a chance to run the script in a wrapper.
238 // The caller may likely want to call wfBasename() on $script.
239 Hooks::run( 'wfShellWikiCmd', [ &$script, &$parameters, &$options ] );
240 $cmd = isset( $options['php'] ) ? [ $options['php'] ] : [ $wgPhpCli ];
241 if ( isset( $options['wrapper'] ) ) {
242 $cmd[] = $options['wrapper'];
243 }
244 $cmd[] = $script;
245
246 return self::command( $cmd )
247 ->params( $parameters )
248 ->restrict( self::RESTRICT_DEFAULT & ~self::NO_LOCALSETTINGS );
249 }
250}
$wgPhpCli
Executable path of the PHP cli binary.
wfDebug( $text, $dest='all', array $context=[])
Sends a line to the debug log if enabled or, optionally, to a comment in output.
wfIsWindows()
Check if the operating system is Windows.
$command
Definition cdb.php:65
if( $line===false) $args
Definition cdb.php:64
Hooks class.
Definition Hooks.php:34
MediaWikiServices is the service locator for the application scope of MediaWiki.
static getInstance()
Returns the global default instance of the top level service locator.
Executes shell commands.
Definition Shell.php:44
const NO_EXECVE
Deny execve syscall with seccomp.
Definition Shell.php:83
const SECCOMP
Use seccomp to block dangerous syscalls.
Definition Shell.php:60
static escape(... $args)
Version of escapeshellarg() that works better on Windows.
Definition Shell.php:163
const NO_NETWORK
Restrict the request to have no network access.
Definition Shell.php:75
const PRIVATE_DEV
Create a private /dev.
Definition Shell.php:67
static command(... $commands)
Returns a new instance of Command class.
Definition Shell.php:119
const NO_ROOT
Disallow any root access.
Definition Shell.php:52
static makeScriptCommand( $script, $parameters, $options=[])
Generate a Command object to run a MediaWiki CLI script.
Definition Shell.php:235
const RESTRICT_DEFAULT
Apply a default set of restrictions for improved security out of the box.
Definition Shell.php:100
const RESTRICT_NONE
Don't apply any restrictions.
Definition Shell.php:108
const NO_LOCALSETTINGS
Deny access to LocalSettings.php (MW_CONFIG_FILE)
Definition Shell.php:90
static isDisabled()
Check if this class is effectively disabled via php.ini config.
Definition Shell.php:137
null means default in associative array with keys and values unescaped Should be merged with default with a value of false meaning to suppress the attribute in associative array with keys and values unescaped & $options
Definition hooks.txt:2050
$tokens
Copyright (C) 2017 Kunal Mehta legoktm@member.fsf.org
Definition Command.php:21