-
Notifications
You must be signed in to change notification settings - Fork 132
/
Copy pathcommand.php
133 lines (118 loc) · 4.34 KB
/
command.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
<?php
/**
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/
require_once __DIR__ . '/../../../../app/bootstrap.php';
if (!empty($_POST['token']) && !empty($_POST['command'])) {
$magentoObjectManagerFactory = \Magento\Framework\App\Bootstrap::createObjectManagerFactory(BP, $_SERVER);
$magentoObjectManager = $magentoObjectManagerFactory->create($_SERVER);
$tokenModel = $magentoObjectManager->get(\Magento\Integration\Model\Oauth\Token::class);
$tokenPassedIn = urldecode($_POST['token'] ?? '');
$command = urldecode($_POST['command'] ?? '');
$arguments = urldecode($_POST['arguments'] ?? '');
$timeout = floatval(urldecode($_POST['timeout'] ?? 60));
// Token returned will be null if the token we passed in is invalid
$tokenFromMagento = $tokenModel->loadByToken($tokenPassedIn)->getToken();
if (!empty($tokenFromMagento) && ($tokenFromMagento === $tokenPassedIn)) {
$php = PHP_BINDIR ? PHP_BINDIR . '/php' : 'php';
$magentoBinary = $php . ' -f ../../../../bin/magento';
$valid = validateCommand($magentoBinary, $command);
if ($valid) {
$fullCommand = escapeshellcmd($magentoBinary . " $command" . " $arguments");
$process = Symfony\Component\Process\Process::fromShellCommandline($fullCommand);
$process->setIdleTimeout($timeout);
$process->setTimeout(0);
$idleTimeout = false;
try {
$process->run();
$output = $process->getOutput();
if (!$process->isSuccessful()) {
$failureOutput = $process->getErrorOutput();
if (!empty($failureOutput)) {
$output = $failureOutput;
}
}
if (empty($output)) {
$output = "CLI did not return output.";
}
} catch (Symfony\Component\Process\Exception\ProcessTimedOutException $exception) {
$output = "CLI command timed out, no output available.";
$idleTimeout = true;
}
$exitCode = $process->getExitCode();
if ($process->isSuccessful() || $idleTimeout) {
http_response_code(202);
} else {
http_response_code(500);
}
// Suppress file paths from output
echo suppressFilePaths($output);
} else {
http_response_code(403);
echo "Given command not found valid in Magento CLI Command list.";
}
} else {
http_response_code(401);
echo("Command not unauthorized.");
}
} else {
http_response_code(412);
echo("Required parameters are not set.");
}
/**
* Returns escaped command.
*
* @param string $command
* @return string
*/
function escapeCommand($command)
{
$escapeExceptions = [
'> /dev/null &' => '--dev-null-amp--'
];
$command = escapeshellcmd(
str_replace(array_keys($escapeExceptions), array_values($escapeExceptions), $command)
);
return str_replace(array_values($escapeExceptions), array_keys($escapeExceptions), $command);
}
/**
* Checks magento list of CLI commands for given $command. Does not check command parameters, just base command.
* @param string $magentoBinary
* @param string $command
* @return bool
*/
function validateCommand($magentoBinary, $command)
{
exec($magentoBinary . ' list', $commandList);
// Trim list of commands after first whitespace
$commandList = array_map("trimAfterWhitespace", $commandList);
return in_array(trimAfterWhitespace($command), $commandList);
}
/**
* Returns given string trimmed of everything after the first found whitespace.
* @param string $string
* @return string
*/
function trimAfterWhitespace($string)
{
return strtok($string, ' ');
}
/**
* Suppress file paths in string.
* @param string $string
* @return string
*/
function suppressFilePaths(string $string): string
{
// Match file paths on both *nix and Windows system
$filePathPattern = '~(?:[A-Za-z]:[\\\/]|\\\\|\/)\S+~';
$replacement = '[suppressed_path]';
preg_match_all($filePathPattern, $string, $matches);
if (!empty($matches)) {
foreach ($matches[0] as $match) {
$string = str_replace($match, $replacement, $string);
}
}
return $string;
}