This project does not seem to handle request data directly as such no vulnerable execution paths were found.
include
, or for example
via PHP's auto-loading mechanism.
These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more
1 | <?php |
||
2 | /** |
||
3 | * See class comment |
||
4 | * |
||
5 | * PHP Version 5 |
||
6 | * |
||
7 | * @category Netresearch |
||
8 | * @package Netresearch\Kite |
||
9 | * @subpackage Console |
||
10 | * @author Christian Opitz <[email protected]> |
||
11 | * @license http://www.netresearch.de Netresearch Copyright |
||
12 | * @link http://www.netresearch.de |
||
13 | */ |
||
14 | |||
15 | namespace Netresearch\Kite\Console; |
||
16 | use Netresearch\Kite\Console\Command\LogCommand; |
||
17 | use Netresearch\Kite\Console\Output\ConsoleOutput; |
||
18 | use Netresearch\Kite\Console\Output\Output; |
||
19 | use Netresearch\Kite\Exception; |
||
20 | use Netresearch\Kite\Service\Config; |
||
21 | use Netresearch\Kite\Console\Command\JobCommand; |
||
22 | use Netresearch\Kite\Service\Factory; |
||
23 | use Symfony\Component\Console\Command\Command; |
||
24 | use Symfony\Component\Console\Input\InputInterface; |
||
25 | use Symfony\Component\Console\Input\InputOption; |
||
26 | use Symfony\Component\Console\Input\StringInput; |
||
27 | use Symfony\Component\Console\Output\OutputInterface; |
||
28 | use Symfony\Component\Process\Process; |
||
29 | |||
30 | /** |
||
31 | * Kite application |
||
32 | * |
||
33 | * @category Netresearch |
||
34 | * @package Netresearch\Kite |
||
35 | * @subpackage Console |
||
36 | * @author Christian Opitz <[email protected]> |
||
37 | * @license http://www.netresearch.de Netresearch Copyright |
||
38 | * @link http://www.netresearch.de |
||
39 | */ |
||
40 | class Application extends \Symfony\Component\Console\Application |
||
41 | { |
||
42 | /** |
||
43 | * @var \Netresearch\Kite\Service\Config |
||
44 | */ |
||
45 | protected $config; |
||
46 | |||
47 | /** |
||
48 | * @var Output |
||
49 | */ |
||
50 | protected $output; |
||
51 | |||
52 | /** |
||
53 | * Application constructor. |
||
54 | */ |
||
55 | public function __construct() |
||
56 | { |
||
57 | $this->output = new ConsoleOutput(); |
||
58 | $this->output->setTerminalDimensions($this->getTerminalDimensions()); |
||
59 | |||
60 | $this->loadConfig(); |
||
61 | |||
62 | parent::__construct('Kite'); |
||
63 | } |
||
64 | |||
65 | /** |
||
66 | * Load the configuration |
||
67 | * |
||
68 | * @return void |
||
69 | */ |
||
70 | protected function loadConfig() |
||
71 | { |
||
72 | $this->config = new Config(); |
||
73 | |||
74 | $expectedFile = 'kite.php'; |
||
75 | $app = null; |
||
76 | $indicators = [ |
||
77 | 'TYPO3' => ['typo3conf', 'Kite.php'], |
||
78 | 'Magento' => ['app/etc', 'kite.php'], |
||
79 | ]; |
||
80 | foreach ($indicators as $appName => $dirAndFile) { |
||
81 | list($dir, $file) = $dirAndFile; |
||
82 | if (is_dir($dir)) { |
||
83 | $app = $appName; |
||
84 | $expectedFile = $dir . '/' . $file; |
||
85 | break; |
||
86 | } |
||
87 | } |
||
88 | |||
89 | try { |
||
90 | $this->config->loadConfigFile($expectedFile); |
||
91 | } catch (\Exception $e) { |
||
92 | if ($app) { |
||
0 ignored issues
–
show
|
|||
93 | $message = [ |
||
94 | 'You appear to be in a ' . $app . ' root directory but', |
||
95 | 'there is no kite config file at the expected', |
||
96 | 'location (' . $expectedFile . ').' |
||
97 | ]; |
||
98 | } else { |
||
99 | $message = [ |
||
100 | 'You are either not in an application root directory or', |
||
101 | 'you have no appropriate config file yet.', |
||
102 | '', |
||
103 | 'The config file path is expected to be:', |
||
104 | ]; |
||
105 | foreach ($indicators as $appName => $dirAndFile) { |
||
106 | $message[] = ' - "' . implode('/', $dirAndFile) . '" for ' . $appName . ' applications or'; |
||
107 | } |
||
108 | $message[] = ' - "' . $expectedFile . '" for any other application'; |
||
109 | } |
||
110 | $lMax = 0; |
||
111 | foreach ($message as $line) { |
||
112 | if (($l = strlen($line)) > $lMax) { |
||
113 | $lMax = $l; |
||
114 | } |
||
115 | } |
||
116 | $this->output->writeln('<warning>' . str_repeat(' ', $lMax + 4) . '</warning>'); |
||
117 | foreach ($message as $line) { |
||
118 | $line = str_pad($line, $lMax + 2); |
||
119 | $this->output->writeln("<warning> $line</warning>"); |
||
120 | } |
||
121 | $this->output->writeln('<warning>' . str_repeat(' ', $lMax + 4) . '</warning>'); |
||
122 | } |
||
123 | } |
||
124 | |||
125 | /** |
||
126 | * Gets the help message. |
||
127 | * |
||
128 | * @return string A help message. |
||
129 | */ |
||
130 | public function getHelp() |
||
131 | { |
||
132 | $help |
||
133 | = " _ ___ _ \n" |
||
134 | . "| |/ /_| |_ ___\n" |
||
135 | . "| ' /| | __/ _ \\\n" |
||
136 | . "| . \\| | |_| __/\n" |
||
137 | . "|_|\\_|_|\\__\\___|\n\n" |
||
138 | . $this->getLongVersion() . "\n\n" |
||
139 | . $this->getSelfPackage()->description; |
||
140 | |||
141 | return $help; |
||
142 | } |
||
143 | |||
144 | /** |
||
145 | * Returns the long version of the application. |
||
146 | * |
||
147 | * @return string The long application version |
||
148 | */ |
||
149 | public function getLongVersion() |
||
150 | { |
||
151 | $package = $this->getSelfPackage(); |
||
152 | $v = "<info>Kite</info> version <comment>{$package->version}</comment>"; |
||
153 | if (isset($package->source)) { |
||
154 | $v .= " <comment>({$package->source->reference})</comment>"; |
||
155 | } |
||
156 | $v .= ' ' . $package->time; |
||
157 | return $v; |
||
158 | } |
||
159 | |||
160 | /** |
||
161 | * Get package info from composer.lock |
||
162 | * |
||
163 | * @return object |
||
164 | */ |
||
165 | protected function getSelfPackage() |
||
166 | { |
||
167 | static $package = null; |
||
168 | if (!$package) { |
||
169 | $files = [__DIR__ . '/../../../../composer/installed.json', __DIR__ . '/vendor/composer/installed.json']; |
||
170 | foreach ($files as $file) { |
||
171 | if (file_exists($file)) { |
||
172 | $installed = json_decode(file_get_contents($file)); |
||
173 | foreach ($installed as $candidate) { |
||
174 | if (substr($candidate->name, -5) === '/kite') { |
||
175 | $package = $candidate; |
||
176 | break 2; |
||
177 | } |
||
178 | } |
||
179 | } |
||
180 | } |
||
181 | if (!$package) { |
||
182 | $kitePath = dirname(dirname(__DIR__)); |
||
183 | $process = new Process('git symbolic-ref -q --short HEAD || git describe --tags --exact-match; git rev-parse HEAD; git show -s --format=%ct HEAD', $kitePath); |
||
184 | $process->run(); |
||
185 | if ($output = $process->getOutput()) { |
||
186 | $package = json_decode(file_get_contents($kitePath . '/composer.json')); |
||
187 | list($name, $revision, $tstamp) = explode("\n", trim($output), 3); |
||
188 | $package->version = preg_match('/^v?[0-9]+\.[0-9]+\.[0-9]+(-[a-z0-9]+)?$/i', $name) ? $name : 'dev-' . $name; |
||
189 | $package->source = (object) ['reference' => $revision]; |
||
190 | $package->time = date('Y-m-d H:i:s', $tstamp); |
||
191 | } else { |
||
192 | throw new Exception('Could not determine self version'); |
||
193 | } |
||
194 | } |
||
195 | } |
||
196 | return $package; |
||
197 | } |
||
198 | |||
199 | /** |
||
200 | * Add workflow option |
||
201 | * |
||
202 | * @return \Symfony\Component\Console\Input\InputDefinition |
||
203 | */ |
||
204 | protected function getDefaultInputDefinition() |
||
0 ignored issues
–
show
getDefaultInputDefinition uses the super-global variable $_SERVER which is generally not recommended.
Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable: // Bad
class Router
{
public function generate($path)
{
return $_SERVER['HOST'].$path;
}
}
// Better
class Router
{
private $host;
public function __construct($host)
{
$this->host = $host;
}
public function generate($path)
{
return $this->host.$path;
}
}
class Controller
{
public function myAction(Request $request)
{
// Instead of
$page = isset($_GET['page']) ? intval($_GET['page']) : 1;
// Better (assuming you use the Symfony2 request)
$page = $request->query->get('page', 1);
}
}
![]() |
|||
205 | { |
||
206 | $definition = parent::getDefaultInputDefinition(); |
||
207 | $definition->addOption(new InputOption('workflow', null, InputOption::VALUE_OPTIONAL, 'Run a workflow on the fly')); |
||
208 | |||
209 | if (isset($_SERVER['HOME']) && is_writable($_SERVER['HOME'])) { |
||
210 | $debugDir = $_SERVER['HOME'] . '/.kite/log'; |
||
211 | } else { |
||
212 | $debugDir = false; |
||
213 | } |
||
214 | $definition->addOption( |
||
215 | new InputOption( |
||
216 | 'debug-dir', null, InputOption::VALUE_OPTIONAL, |
||
217 | "Path to directory to which to dump the debug output file", |
||
218 | $debugDir |
||
219 | ) |
||
220 | ); |
||
221 | return $definition; |
||
222 | } |
||
223 | |||
224 | /** |
||
225 | * Runs the current application. |
||
226 | * |
||
227 | * @param InputInterface $input An Input instance |
||
228 | * |
||
229 | * @return int 0 if everything went fine, or an error code |
||
230 | */ |
||
231 | public function run(InputInterface $input = null) |
||
232 | { |
||
233 | return parent::run($input, $this->output); |
||
234 | } |
||
235 | |||
236 | |||
237 | /** |
||
238 | * Create job on the fly when workflow option is present |
||
239 | * |
||
240 | * @param InputInterface $input The input |
||
241 | * @param OutputInterface $output The output |
||
242 | * |
||
243 | * @return int |
||
244 | */ |
||
245 | public function doRun(InputInterface $input, OutputInterface $output) |
||
246 | { |
||
247 | if ($input->hasParameterOption('--workflow')) { |
||
248 | $strInput = (string) $input; |
||
249 | if ($this->getCommandName($input) === 'help') { |
||
250 | $strInput = str_replace('help ', '', $strInput); |
||
251 | $strInput .= ' --help'; |
||
252 | } |
||
253 | $workflow = $input->getParameterOption('--workflow'); |
||
254 | $jobName = 'generic:workflow:' . $workflow; |
||
255 | $this->config->configureJob($jobName, array('workflow' => $workflow)); |
||
0 ignored issues
–
show
The call to the method
Netresearch\Kite\Service\Config::configureJob() seems un-needed as the method has no side-effects.
PHP Analyzer performs a side-effects analysis of your code. A side-effect is basically anything that might be visible after the scope of the method is left. Let’s take a look at an example: class User
{
private $email;
public function getEmail()
{
return $this->email;
}
public function setEmail($email)
{
$this->email = $email;
}
}
If we look at the $user = new User();
$user->getEmail(); // This line could safely be removed as it has no effect.
On the hand, if we look at the $user = new User();
$user->setEmail('email@domain'); // This line has a side-effect (it changes an
// instance variable).
![]() |
|||
256 | $command = new JobCommand($jobName, $this->config); |
||
257 | $this->add($command); |
||
258 | |||
259 | $parameterOption = '--workflow=' . $workflow; |
||
260 | $input = new StringInput( |
||
261 | rtrim( |
||
262 | $jobName . ' ' . |
||
263 | str_replace( |
||
264 | array( |
||
265 | $parameterOption . ' ', |
||
266 | ' ' . $parameterOption, |
||
267 | $parameterOption |
||
268 | ), '', $strInput |
||
269 | ) |
||
270 | ) |
||
271 | ); |
||
272 | } |
||
273 | return parent::doRun($input, $output); |
||
274 | } |
||
275 | |||
276 | |||
277 | /** |
||
278 | * Gets the default commands that should always be available. |
||
279 | * |
||
280 | * @return Command[] An array of default Command instances |
||
281 | */ |
||
282 | protected function getDefaultCommands() |
||
283 | { |
||
284 | $commands = parent::getDefaultCommands(); |
||
285 | $commands[] = new LogCommand(); |
||
286 | |||
287 | foreach ($this->config->getJobConfiguration() as $name => $configuration) { |
||
288 | $commands[] = new JobCommand($name, $this->config); |
||
289 | } |
||
290 | |||
291 | return $commands; |
||
0 ignored issues
–
show
The expression
return $commands; seems to be an array , but some of its elements' types (Netresearch\Kite\Console...sole\Command\JobCommand ) are incompatible with the return type of the parent method Symfony\Component\Consol...ion::getDefaultCommands of type array<Symfony\Component\...le\Command\ListCommand> .
If you return a value from a function or method, it should be a sub-type of the type that is given by the parent type f.e. an interface, or abstract method. This is more formally defined by the Lizkov substitution principle, and guarantees that classes that depend on the parent type can use any instance of a child type interchangably. This principle also belongs to the SOLID principles for object oriented design. Let’s take a look at an example: class Author {
private $name;
public function __construct($name) {
$this->name = $name;
}
public function getName() {
return $this->name;
}
}
abstract class Post {
public function getAuthor() {
return new Author('Johannes');
}
}
class BlogPost extends Post {
public function getAuthor() {
return 'Johannes';
}
}
class ForumPost extends Post { /* ... */ }
function my_function(Post $post) {
echo strtoupper($post->getAuthor());
}
Our function ![]() |
|||
292 | } |
||
293 | } |
||
294 | ?> |
||
295 |
In PHP, under loose comparison (like
==
, or!=
, orswitch
conditions), values of different types might be equal.For
string
values, the empty string''
is a special case, in particular the following results might be unexpected: