Page Menu
Home
WickedGov Phorge
Search
Configure Global Search
Log In
Files
F4134671
CommandFactory.php
No One
Temporary
Actions
Download File
Edit File
Delete File
View Transforms
Subscribe
Flag For Later
Award Token
Size
5 KB
Referenced Files
None
Subscribers
None
CommandFactory.php
View Options
<?php
/**
* @license GPL-2.0-or-later
* @file
*/
namespace
MediaWiki\Shell
;
use
ExecutableFinder
;
use
Psr\Log\LoggerAwareTrait
;
use
Psr\Log\NullLogger
;
use
Shellbox\Command\BoxedCommand
;
use
Shellbox\Command\RemoteBoxedExecutor
;
use
Shellbox\Shellbox
;
/**
* Factory facilitating dependency injection for Command
*
* @since 1.30
*/
class
CommandFactory
{
use
LoggerAwareTrait
;
/** @var array */
private
$limits
;
/** @var string|bool */
private
$cgroup
;
/** @var bool */
private
$doLogStderr
=
false
;
/**
* @var string|bool
*/
private
$restrictionMethod
;
/**
* @var string|bool|null
*/
private
$firejail
;
/** @var bool */
private
$useAllUsers
;
/** @var ShellboxClientFactory */
private
$shellboxClientFactory
;
/**
* @param ShellboxClientFactory $shellboxClientFactory
* @param array $limits See {@see Command::limits()}
* @param string|bool $cgroup
* @param string|bool $restrictionMethod
*/
public
function
__construct
(
ShellboxClientFactory
$shellboxClientFactory
,
array
$limits
,
$cgroup
,
$restrictionMethod
)
{
$this
->
shellboxClientFactory
=
$shellboxClientFactory
;
$this
->
limits
=
$limits
;
$this
->
cgroup
=
$cgroup
;
if
(
$restrictionMethod
===
'autodetect'
)
{
// On Linux systems check for firejail
if
(
PHP_OS
===
'Linux'
&&
$this
->
findFirejail
()
)
{
$this
->
restrictionMethod
=
'firejail'
;
}
else
{
$this
->
restrictionMethod
=
false
;
}
}
else
{
$this
->
restrictionMethod
=
$restrictionMethod
;
}
$this
->
setLogger
(
new
NullLogger
()
);
}
/**
* @return bool|string
*/
protected
function
findFirejail
()
{
if
(
$this
->
firejail
===
null
)
{
$this
->
firejail
=
ExecutableFinder
::
findInDefaultPaths
(
'firejail'
);
}
return
$this
->
firejail
;
}
/**
* When enabled, text sent to stderr will be logged with a level of 'error'.
*
* @param bool $yesno
* @see Command::logStderr
*/
public
function
logStderr
(
bool
$yesno
=
true
):
void
{
$this
->
doLogStderr
=
$yesno
;
}
/**
* Get the options which will be used for local unboxed execution.
* Shellbox should be configured to act in an approximately backwards
* compatible way, equivalent to the pre-Shellbox MediaWiki shell classes.
*
* @return array
*/
private
function
getLocalShellboxOptions
()
{
$options
=
[
'tempDir'
=>
wfTempDir
(),
'useBashWrapper'
=>
file_exists
(
'/bin/bash'
),
'cgroup'
=>
$this
->
cgroup
];
if
(
$this
->
restrictionMethod
===
'firejail'
)
{
$firejailPath
=
$this
->
findFirejail
();
if
(
!
$firejailPath
)
{
throw
new
\RuntimeException
(
'firejail is enabled, but cannot be found'
);
}
$options
[
'useFirejail'
]
=
true
;
$options
[
'firejailPath'
]
=
$firejailPath
;
$options
[
'firejailProfile'
]
=
__DIR__
.
'/firejail.profile'
;
}
return
$options
;
}
/**
* Instantiates a new Command
*/
public
function
create
():
Command
{
$allUsers
=
false
;
if
(
$this
->
restrictionMethod
===
'firejail'
)
{
if
(
$this
->
useAllUsers
===
null
)
{
global
$IP
;
// In case people are doing funny things with symlinks
// or relative paths, resolve them all.
$realIP
=
realpath
(
$IP
);
$currentUser
=
posix_getpwuid
(
posix_geteuid
()
);
$this
->
useAllUsers
=
str_starts_with
(
$realIP
,
'/home/'
)
&&
!
str_starts_with
(
$realIP
,
$currentUser
[
'dir'
]
);
if
(
$this
->
useAllUsers
)
{
$this
->
logger
->
warning
(
'firejail: MediaWiki is located '
.
'in a home directory that does not belong to the '
.
'current user, so allowing access to all home '
.
'directories (--allusers)'
);
}
}
$allUsers
=
$this
->
useAllUsers
;
}
$executor
=
Shellbox
::
createUnboxedExecutor
(
$this
->
getLocalShellboxOptions
(),
$this
->
logger
);
$command
=
new
Command
(
$executor
);
$command
->
setLogger
(
$this
->
logger
);
if
(
$allUsers
)
{
$command
->
allowPath
(
'/home'
);
}
return
$command
->
limits
(
$this
->
limits
)
->
logStderr
(
$this
->
doLogStderr
);
}
/**
* Instantiates a new BoxedCommand.
*
* @since 1.36
* @param ?string $service Name of Shellbox (as configured in
* $wgShellboxUrls) that should be used
* @param int|float|null $wallTimeLimit The wall time limit, or null to use the default.
* This needs to be set early so that the HTTP timeout is configured correctly.
* @return BoxedCommand
*/
public
function
createBoxed
(
?
string
$service
=
null
,
$wallTimeLimit
=
null
):
BoxedCommand
{
$wallTimeLimit
??=
$this
->
limits
[
'walltime'
];
if
(
$this
->
shellboxClientFactory
->
isEnabled
(
$service
)
)
{
$client
=
$this
->
shellboxClientFactory
->
getClient
(
[
'timeout'
=>
$wallTimeLimit
+
1
,
'service'
=>
$service
,
]
);
$executor
=
new
RemoteBoxedExecutor
(
$client
);
$executor
->
setLogger
(
$this
->
logger
);
}
else
{
$executor
=
Shellbox
::
createBoxedExecutor
(
$this
->
getLocalShellboxOptions
(),
$this
->
logger
);
}
return
$executor
->
createCommand
()
->
cpuTimeLimit
(
$this
->
limits
[
'time'
]
)
->
wallTimeLimit
(
$wallTimeLimit
)
->
memoryLimit
(
$this
->
limits
[
'memory'
]
*
1024
)
->
fileSizeLimit
(
$this
->
limits
[
'filesize'
]
*
1024
)
->
logStderr
(
$this
->
doLogStderr
);
}
}
File Metadata
Details
Attached
Mime Type
text/x-php
Expires
Wed, Aug 19, 12:45 (3 w, 2 d ago)
Storage Engine
local-disk
Storage Format
Raw Data
Storage Handle
82/cd/8a58f749939db121291dc8969288
Default Alt Text
CommandFactory.php (5 KB)
Attached To
Mode
rMWPROD MediaWiki Production
Attached
Detach File
Event Timeline
Log In to Comment