Code Coverage
 
Classes and Traits
Functions and Methods
Lines
Total
0.00% covered (danger)
0.00%
0 / 1
66.67% covered (warning)
66.67%
4 / 6
CRAP
91.67% covered (success)
91.67%
44 / 48
ShellAction
0.00% covered (danger)
0.00%
0 / 1
66.67% covered (warning)
66.67%
4 / 6
12.08
91.67% covered (success)
91.67%
44 / 48
 execute
100.00% covered (success)
100.00%
1 / 1
3
100.00% covered (success)
100.00%
15 / 15
 getActionName
100.00% covered (success)
100.00%
1 / 1
1
100.00% covered (success)
100.00%
1 / 1
 createExecutor
100.00% covered (success)
100.00%
1 / 1
1
100.00% covered (success)
100.00%
14 / 14
 createCommand
100.00% covered (success)
100.00%
1 / 1
2
100.00% covered (success)
100.00%
7 / 7
 validateInputFiles
0.00% covered (danger)
0.00%
0 / 1
2.09
71.43% covered (warning)
71.43%
5 / 7
 validateRoute
0.00% covered (danger)
0.00%
0 / 1
4.12
50.00% covered (danger)
50.00%
2 / 4
<?php
namespace Shellbox\Action;
use Shellbox\Command\BoxedCommand;
use Shellbox\Command\ServerBoxedExecutor;
use Shellbox\Command\ServerUnboxedExecutor;
use Shellbox\ShellboxError;
/**
 * Shell command handler
 */
class ShellAction extends MultipartAction {
    /**
     * @param string[] $pathParts
     */
    protected function execute( $pathParts ) {
        $commandData = $this->getRequiredParam( 'command' );
        $command = $this->createCommand( $commandData );
        $this->validateInputFiles( array_keys( $command->getInputFiles() ) );
        $this->validateRoute( $command->getRouteName(), $pathParts );
        $result = $command->execute();
        $binaryData = [];
        if ( $result->getStdout() !== null ) {
            $binaryData['stdout'] = $result->getStdout();
        }
        if ( $result->getStderr() !== null ) {
            $binaryData['stderr'] = $result->getStderr();
        }
        $this->writeResult(
            [ 'exitCode' => $result->getExitCode() ],
            $binaryData,
            $result->getFileNames()
        );
    }
    protected function getActionName() {
        return 'shell';
    }
    /**
     * @return ServerBoxedExecutor
     */
    private function createExecutor() {
        $unboxedExecutor = new ServerUnboxedExecutor( $this->tempDirManager );
        $unboxedExecutor->setLogger( $this->logger );
        $unboxedExecutor->addWrappersFromConfiguration( [
            'useSystemd' => $this->getConfig( 'useSystemd' ),
            'useBashWrapper' => $this->getConfig( 'useBashWrapper' ),
            'useFirejail' => $this->getConfig( 'useFirejail' ),
            'firejailPath' => $this->getConfig( 'firejailPath' ),
            'firejailProfile' => $this->getConfig( 'firejailProfile' )
        ] );
        $executor = new ServerBoxedExecutor( $unboxedExecutor, $this->tempDirManager );
        $executor->setLogger( $this->logger );
        $executor->setValidationConfig( [
            'allowedRoutes' => $this->getConfig( 'allowedRoutes' ),
            'routeSpecs' => $this->getConfig( 'routeSpecs' )
        ] );
        return $executor;
    }
    /**
     * @param array $commandData
     * @return BoxedCommand
     */
    private function createCommand( $commandData ) {
        $executor = $this->createExecutor();
        $command = $executor->createCommand();
        $command->setClientData( $commandData );
        $stdin = $this->getParam( 'stdin' );
        if ( $stdin !== null ) {
            $command->stdin( $stdin );
        }
        return $command;
    }
    /**
     * Confirm that the received input file list matches the one in the command
     * client data. This ensures that the input file list will be correctly
     * validated by Validator.
     *
     * @param string[] $files
     * @throws ShellboxError
     */
    private function validateInputFiles( $files ) {
        $received = $this->getReceivedFileNames();
        sort( $received );
        sort( $files );
        if ( $files !== $received ) {
            throw new ShellboxError(
                "The received file list does not match the command client data" );
        }
    }
    /**
     * Confirm that the path route matches the command parameter route
     *
     * @param string $commandRoute
     * @param string[] $pathParts
     * @throws ShellboxError
     */
    private function validateRoute( $commandRoute, $pathParts ) {
        if ( count( $pathParts ) !== 1 || $pathParts[0] !== $commandRoute ) {
            throw new ShellboxError(
                "The request path does not match the route in the command" );
        }
    }
}