Issues (62)

Security Analysis    no request data  

This project does not seem to handle request data directly as such no vulnerable execution paths were found.

  Cross-Site Scripting
Cross-Site Scripting enables an attacker to inject code into the response of a web-request that is viewed by other users. It can for example be used to bypass access controls, or even to take over other users' accounts.
  File Exposure
File Exposure allows an attacker to gain access to local files that he should not be able to access. These files can for example include database credentials, or other configuration files.
  File Manipulation
File Manipulation enables an attacker to write custom data to files. This potentially leads to injection of arbitrary code on the server.
  Object Injection
Object Injection enables an attacker to inject an object into PHP code, and can lead to arbitrary code execution, file exposure, or file manipulation attacks.
  Code Injection
Code Injection enables an attacker to execute arbitrary code on the server.
  Response Splitting
Response Splitting can be used to send arbitrary responses.
  File Inclusion
File Inclusion enables an attacker to inject custom files into PHP's file loading mechanism, either explicitly passed to include, or for example via PHP's auto-loading mechanism.
  Command Injection
Command Injection enables an attacker to inject a shell command that is execute with the privileges of the web-server. This can be used to expose sensitive data, or gain access of your server.
  SQL Injection
SQL Injection enables an attacker to execute arbitrary SQL code on your database server gaining access to user data, or manipulating user data.
  XPath Injection
XPath Injection enables an attacker to modify the parts of XML document that are read. If that XML document is for example used for authentication, this can lead to further vulnerabilities similar to SQL Injection.
  LDAP Injection
LDAP Injection enables an attacker to inject LDAP statements potentially granting permission to run unauthorized queries, or modify content inside the LDAP tree.
  Header Injection
  Other Vulnerability
This category comprises other attack vectors such as manipulating the PHP runtime, loading custom extensions, freezing the runtime, or similar.
  Regex Injection
Regex Injection enables an attacker to execute arbitrary code in your PHP process.
  XML Injection
XML Injection enables an attacker to read files on your local filesystem including configuration files, or can be abused to freeze your web-server process.
  Variable Injection
Variable Injection enables an attacker to overwrite program variables with custom data, and can lead to further vulnerabilities.
Unfortunately, the security analysis is currently not available for your project. If you are a non-commercial open-source project, please contact support to gain access.

src/Handler/ModuleCommandHandler.php (3 issues)

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

1
<?php
2
3
/*
4
 * This file is part of the puli/cli package.
5
 *
6
 * (c) Bernhard Schussek <[email protected]>
7
 *
8
 * For the full copyright and license information, please view the LICENSE
9
 * file that was distributed with this source code.
10
 */
11
12
namespace Puli\Cli\Handler;
13
14
use Puli\Cli\Style\PuliTableStyle;
15
use Puli\Cli\Util\StringUtil;
16
use Puli\Manager\Api\Environment;
17
use Puli\Manager\Api\Module\Module;
18
use Puli\Manager\Api\Module\ModuleList;
19
use Puli\Manager\Api\Module\ModuleManager;
20
use Puli\Manager\Api\Module\ModuleState;
21
use RuntimeException;
22
use Webmozart\Console\Api\Args\Args;
23
use Webmozart\Console\Api\IO\IO;
24
use Webmozart\Console\UI\Component\Table;
25
use Webmozart\Expression\Expr;
26
use Webmozart\PathUtil\Path;
27
28
/**
29
 * Handles the "module" command.
30
 *
31
 * @since  1.0
32
 *
33
 * @author Bernhard Schussek <[email protected]>
34
 */
35
class ModuleCommandHandler
36
{
37
    /**
38
     * @var array
39
     */
40
    private static $stateStrings = array(
41
        ModuleState::ENABLED => 'enabled',
42
        ModuleState::NOT_FOUND => 'not-found',
43
        ModuleState::NOT_LOADABLE => 'not-loadable',
44
    );
45
46
    /**
47
     * @var ModuleManager
48
     */
49
    private $moduleManager;
50
51
    /**
52
     * Creates the handler.
53
     *
54
     * @param ModuleManager $moduleManager The module manager
55
     */
56 20
    public function __construct(ModuleManager $moduleManager)
57
    {
58 20
        $this->moduleManager = $moduleManager;
59 20
    }
60
61
    /**
62
     * Handles the "module --list" command.
63
     *
64
     * @param Args $args The console arguments
65
     * @param IO   $io   The I/O
66
     *
67
     * @return int The status code
68
     */
69 11
    public function handleList(Args $args, IO $io)
70
    {
71 11
        $modules = $this->getSelectedModules($args);
72
73 11
        if ($args->isOptionSet('format')) {
74 1
            $this->printModulesWithFormat($io, $modules, $args->getOption('format'));
75
        } else {
76 10
            $this->printModulesByState($io, $modules, $this->getSelectedStates($args));
77
        }
78
79 11
        return 0;
80
    }
81
82
    /**
83
     * Handles the "module --install" command.
84
     *
85
     * @param Args $args The console arguments
86
     *
87
     * @return int The status code
88
     */
89 5
    public function handleInstall(Args $args)
90
    {
91 5
        $moduleName = $args->getArgument('name');
92 5
        $installPath = Path::makeAbsolute($args->getArgument('path'), getcwd());
93 5
        $installer = $args->getOption('installer');
94 5
        $env = $args->isOptionSet('dev') ? Environment::DEV : Environment::PROD;
95
96 5
        $this->moduleManager->installModule($installPath, $moduleName, $installer, $env);
97
98 5
        return 0;
99
    }
100
101
    /**
102
     * Handles the "module --rename" command.
103
     *
104
     * @param Args $args The console arguments
105
     *
106
     * @return int The status code
107
     */
108 1
    public function handleRename(Args $args)
109
    {
110 1
        $moduleName = $args->getArgument('name');
111 1
        $newName = $args->getArgument('new-name');
112
113 1
        $this->moduleManager->renameModule($moduleName, $newName);
114
115 1
        return 0;
116
    }
117
118
    /**
119
     * Handles the "module --delete" command.
120
     *
121
     * @param Args $args The console arguments
122
     *
123
     * @return int The status code
124
     */
125 2
    public function handleDelete(Args $args)
126
    {
127 2
        $moduleName = $args->getArgument('name');
128
129 2
        if (!$this->moduleManager->hasModule($moduleName)) {
130 1
            throw new RuntimeException(sprintf(
131 1
                'The module "%s" is not installed.',
132
                $moduleName
133
            ));
134
        }
135
136 1
        $this->moduleManager->removeModule($moduleName);
137
138 1
        return 0;
139
    }
140
141
    /**
142
     * Handles the "module --clean" command.
143
     *
144
     * @param Args $args The console arguments
145
     * @param IO   $io   The I/O
146
     *
147
     * @return int The status code
148
     */
149 1
    public function handleClean(Args $args, IO $io)
0 ignored issues
show
The parameter $args is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
150
    {
151 1
        $expr = Expr::method('getState', Expr::same(ModuleState::NOT_FOUND));
152
153 1
        foreach ($this->moduleManager->findModules($expr) as $module) {
154 1
            $io->writeLine('Removing '.$module->getName());
155 1
            $this->moduleManager->removeModule($module->getName());
156
        }
157
158 1
        return 0;
159
    }
160
161
    /**
162
     * Returns the module states that should be displayed for the given
163
     * console arguments.
164
     *
165
     * @param Args $args The console arguments
166
     *
167
     * @return int[] A list of {@link ModuleState} constants
168
     */
169 11
    private function getSelectedStates(Args $args)
170
    {
171 11
        $states = array();
172
173 11
        if ($args->isOptionSet('enabled')) {
174 3
            $states[] = ModuleState::ENABLED;
175
        }
176
177 11
        if ($args->isOptionSet('not-found')) {
178 2
            $states[] = ModuleState::NOT_FOUND;
179
        }
180
181 11
        if ($args->isOptionSet('not-loadable')) {
182 1
            $states[] = ModuleState::NOT_LOADABLE;
183
        }
184
185 11
        return $states ?: ModuleState::all();
186
    }
187
188
    /**
189
     * Returns the modules that should be displayed for the given console
190
     * arguments.
191
     *
192
     * @param Args $args The console arguments
193
     *
194
     * @return ModuleList The modules
195
     */
196 11
    private function getSelectedModules(Args $args)
197
    {
198 11
        $states = $this->getSelectedStates($args);
199 11
        $expr = Expr::true();
200 11
        $envs = array();
201
202 11
        if ($states !== ModuleState::all()) {
203 5
            $expr = $expr->andMethod('getState', Expr::in($states));
204
        }
205
206 11
        if ($args->isOptionSet('installer')) {
207 2
            $expr = $expr->andMethod('getInstallInfo', Expr::method('getInstallerName', Expr::same($args->getOption('installer'))));
208
        }
209
210 11
        if ($args->isOptionSet('prod')) {
211 2
            $envs[] = Environment::PROD;
212
        }
213
214 11
        if ($args->isOptionSet('dev')) {
215 2
            $envs[] = Environment::DEV;
216
        }
217
218 11
        if (count($envs) > 0) {
219 3
            $expr = $expr->andMethod('getInstallInfo', Expr::method('getEnvironment', Expr::in($envs)));
220
        }
221
222 11
        return $this->moduleManager->findModules($expr);
223
    }
224
225
    /**
226
     * Prints modules with intermediate headers for the module states.
227
     *
228
     * @param IO         $io      The I/O
229
     * @param ModuleList $modules The modules to print
230
     * @param int[]      $states  The states to print
231
     */
232 10
    private function printModulesByState(IO $io, ModuleList $modules, array $states)
233
    {
234 10
        $printStates = count($states) > 1;
235
236 10
        foreach ($states as $state) {
237 10
            $filteredModules = array_filter($modules->toArray(), function (Module $module) use ($state) {
238 10
                return $state === $module->getState();
239 10
            });
240
241 10
            if (0 === count($filteredModules)) {
242 2
                continue;
243
            }
244
245 10
            if ($printStates) {
246 6
                $this->printModuleState($io, $state);
247
            }
248
249 10
            if (ModuleState::NOT_LOADABLE === $state) {
250 5
                $this->printNotLoadableModules($io, $filteredModules, $printStates);
251
            } else {
252 9
                $styleTag = ModuleState::ENABLED === $state ? null : 'bad';
253 9
                $this->printModuleTable($io, $filteredModules, $styleTag, $printStates);
254
            }
255
256 10
            if ($printStates) {
257 10
                $io->writeLine('');
258
            }
259
        }
260 10
    }
261
262
    /**
263
     * Prints modules using the given format.
264
     *
265
     * @param IO         $io      The I/O
266
     * @param ModuleList $modules The modules to print
267
     * @param string     $format  The format string
268
     */
269 1
    private function printModulesWithFormat(IO $io, ModuleList $modules, $format)
270
    {
271
        /** @var Module $module */
272 1
        foreach ($modules as $module) {
273 1
            $installInfo = $module->getInstallInfo();
274
275 1
            $io->writeLine(strtr($format, array(
276 1
                '%name%' => $module->getName(),
277 1
                '%installer%' => $installInfo ? $installInfo->getInstallerName() : '',
278 1
                '%install_path%' => $module->getInstallPath(),
279 1
                '%state%' => self::$stateStrings[$module->getState()],
280 1
                '%env%' => $installInfo ? $installInfo->getEnvironment() : Environment::PROD,
281
            )));
282
        }
283 1
    }
284
285
    /**
286
     * Prints the heading for a given module state.
287
     *
288
     * @param IO  $io          The I/O
289
     * @param int $ModuleState The {@link ModuleState} constant
290
     */
291 6
    private function printModuleState(IO $io, $ModuleState)
0 ignored issues
show
Coding Style Naming introduced by
The parameter $ModuleState is not named in camelCase.

This check marks parameter names that have not been written in camelCase.

In camelCase names are written without any punctuation, the start of each new word being marked by a capital letter. Thus the name database connection string becomes databaseConnectionString.

Loading history...
292
    {
293 View Code Duplication
        switch ($ModuleState) {
0 ignored issues
show
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
294 6
            case ModuleState::ENABLED:
295 6
                $io->writeLine('The following modules are currently enabled:');
296 6
                $io->writeLine('');
297
298 6
                return;
299 5
            case ModuleState::NOT_FOUND:
300 4
                $io->writeLine('The following modules could not be found:');
301 4
                $io->writeLine(' (use "puli module --clean" to remove)');
302 4
                $io->writeLine('');
303
304 4
                return;
305 4
            case ModuleState::NOT_LOADABLE:
306 4
                $io->writeLine('The following modules could not be loaded:');
307 4
                $io->writeLine('');
308
309 4
                return;
310
        }
311
    }
312
313
    /**
314
     * Prints a list of modules in a table.
315
     *
316
     * @param IO          $io       The I/O
317
     * @param Module[]    $modules  The modules
318
     * @param string|null $styleTag The tag used to style the output. If `null`,
319
     *                              the default colors are used
320
     * @param bool        $indent   Whether to indent the output
321
     */
322 9
    private function printModuleTable(IO $io, array $modules, $styleTag = null, $indent = false)
323
    {
324 9
        $table = new Table(PuliTableStyle::borderless());
325 9
        $table->setHeaderRow(array('Module Name', 'Installer', 'Env', 'Install Path'));
326
327 9
        $installerTag = $styleTag ?: 'c1';
328 9
        $envTag = $styleTag ?: 'c1';
329 9
        $pathTag = $styleTag ?: 'c2';
330
331 9
        ksort($modules);
332
333 9
        foreach ($modules as $module) {
334 9
            $moduleName = $module->getName();
335 9
            $installInfo = $module->getInstallInfo();
336 9
            $installPath = $installInfo ? $installInfo->getInstallPath() : '.';
337 9
            $installer = $installInfo ? $installInfo->getInstallerName() : '';
338 9
            $env = $installInfo ? $installInfo->getEnvironment() : Environment::PROD;
339
340 9
            $table->addRow(array(
341 9
                $styleTag ? sprintf('<%s>%s</%s>', $styleTag, $moduleName, $styleTag) : $moduleName,
342 9
                $installer ? sprintf('<%s>%s</%s>', $installerTag, $installer, $installerTag) : '',
343 9
                sprintf('<%s>%s</%s>', $envTag, $env, $envTag),
344 9
                sprintf('<%s>%s</%s>', $pathTag, $installPath, $pathTag),
345
            ));
346
        }
347
348 9
        $table->render($io, $indent ? 4 : 0);
349 9
    }
350
351
    /**
352
     * Prints not-loadable modules in a table.
353
     *
354
     * @param IO       $io      The I/O
355
     * @param Module[] $modules The not-loadable modules
356
     * @param bool     $indent  Whether to indent the output
357
     */
358 5
    private function printNotLoadableModules(IO $io, array $modules, $indent = false)
359
    {
360 5
        $rootDir = $this->moduleManager->getContext()->getRootDirectory();
361 5
        $table = new Table(PuliTableStyle::borderless());
362 5
        $table->setHeaderRow(array('Module Name', 'Error'));
363
364 5
        ksort($modules);
365
366 5
        foreach ($modules as $module) {
367 5
            $moduleName = $module->getName();
368 5
            $loadErrors = $module->getLoadErrors();
369 5
            $errorMessage = '';
370
371 5
            foreach ($loadErrors as $loadError) {
372 5
                $errorMessage .= StringUtil::getShortClassName(get_class($loadError)).': '.$loadError->getMessage()."\n";
373
            }
374
375 5
            $errorMessage = rtrim($errorMessage);
376
377 5
            if (!$errorMessage) {
378
                $errorMessage = 'Unknown error.';
379
            }
380
381
            // Remove root directory
382 5
            $errorMessage = str_replace($rootDir.'/', '', $errorMessage);
383
384 5
            $table->addRow(array(
385 5
                sprintf('<bad>%s</bad>', $moduleName),
386 5
                sprintf('<bad>%s</bad>', $errorMessage),
387
            ));
388
        }
389
390 5
        $table->render($io, $indent ? 4 : 0);
391 5
    }
392
}
393