LukeCarrier /
moodle-componentmgr
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 | /** |
||
| 4 | * Moodle component manager. |
||
| 5 | * |
||
| 6 | * @author Luke Carrier <[email protected]> |
||
| 7 | * @copyright 2016 Luke Carrier |
||
| 8 | * @license GPL-3.0+ |
||
| 9 | */ |
||
| 10 | |||
| 11 | namespace ComponentManager\Step; |
||
| 12 | |||
| 13 | use ComponentManager\Exception\InstallationFailureException; |
||
| 14 | use ComponentManager\Exception\RetryablePackageFailureException; |
||
| 15 | use ComponentManager\Exception\UnsatisfiedVersionException; |
||
| 16 | use ComponentManager\Moodle; |
||
| 17 | use ComponentManager\Platform\Platform; |
||
| 18 | use ComponentManager\Project\Project; |
||
| 19 | use ComponentManager\Task\InstallTask; |
||
| 20 | use Psr\Log\LoggerInterface; |
||
| 21 | use Symfony\Component\Filesystem\Exception\IOException; |
||
| 22 | use Symfony\Component\Filesystem\Filesystem; |
||
| 23 | |||
| 24 | class InstallComponentsStep implements Step { |
||
| 25 | /** |
||
| 26 | * Project. |
||
| 27 | * |
||
| 28 | * @var Project |
||
| 29 | */ |
||
| 30 | protected $project; |
||
| 31 | |||
| 32 | /** |
||
| 33 | * Moodle. |
||
| 34 | * |
||
| 35 | * @var Moodle |
||
| 36 | */ |
||
| 37 | protected $moodle; |
||
| 38 | |||
| 39 | /** |
||
| 40 | * Filesystem. |
||
| 41 | * |
||
| 42 | * @var Filesystem |
||
| 43 | */ |
||
| 44 | protected $filesystem; |
||
| 45 | |||
| 46 | /** |
||
| 47 | * Platform support library. |
||
| 48 | * |
||
| 49 | * @var Platform |
||
| 50 | */ |
||
| 51 | protected $platform; |
||
| 52 | |||
| 53 | /** |
||
| 54 | * Process timeout. |
||
| 55 | * |
||
| 56 | * @var integer|null |
||
| 57 | */ |
||
| 58 | protected $timeout; |
||
| 59 | |||
| 60 | /** |
||
| 61 | * Number of retries. |
||
| 62 | * |
||
| 63 | * @var integer |
||
| 64 | */ |
||
| 65 | protected $attempts; |
||
| 66 | |||
| 67 | /** |
||
| 68 | * Initialiser. |
||
| 69 | * |
||
| 70 | * @param Project $project |
||
| 71 | * @param Moodle $moodle |
||
| 72 | * @param Platform $platform |
||
| 73 | * @param Filesystem $filesystem |
||
| 74 | * @param integer|null $timeout |
||
| 75 | * @param integer $attempts |
||
| 76 | */ |
||
| 77 | public function __construct(Project $project, Moodle $moodle, |
||
| 78 | Platform $platform, Filesystem $filesystem, |
||
| 79 | $timeout, $attempts) { |
||
| 80 | $this->project = $project; |
||
| 81 | $this->moodle = $moodle; |
||
| 82 | |||
| 83 | $this->filesystem = $filesystem; |
||
| 84 | $this->platform = $platform; |
||
| 85 | |||
| 86 | $this->timeout = $timeout; |
||
| 87 | $this->attempts = $attempts; |
||
| 88 | } |
||
| 89 | |||
| 90 | /** |
||
| 91 | * @inheritdoc Step |
||
| 92 | * |
||
| 93 | * @param InstallTask $task |
||
| 94 | */ |
||
| 95 | public function execute($task, LoggerInterface $logger) { |
||
| 96 | $resolvedComponentVersions = $task->getResolvedComponentVersions(); |
||
| 97 | |||
| 98 | foreach ($resolvedComponentVersions as $resolvedComponentVersion) { |
||
| 99 | $obtained = false; |
||
| 100 | $remainingAttempts = $this->attempts; |
||
| 101 | |||
| 102 | $logger->info('Installing component', [ |
||
| 103 | 'component' => $resolvedComponentVersion->getComponent()->getName(), |
||
| 104 | 'packageRepository' => $resolvedComponentVersion->getPackageRepository()->getName(), |
||
| 105 | 'version' => $resolvedComponentVersion->getVersion()->getVersion(), |
||
| 106 | 'release' => $resolvedComponentVersion->getVersion()->getRelease(), |
||
| 107 | ]); |
||
| 108 | |||
| 109 | $projectLockFile = $this->project->getProjectLockFile(); |
||
| 110 | $component = $resolvedComponentVersion->getComponent(); |
||
| 111 | $packageSource = $this->project->getPackageSource( |
||
| 112 | $resolvedComponentVersion->getSpecification()->getPackageSource()); |
||
| 113 | |||
| 114 | $typeDirectory = $this->moodle->getPluginTypeDirectory( |
||
| 115 | $component->getPluginType()); |
||
| 116 | if (!$typeDirectory) { |
||
| 117 | throw new InstallationFailureException( |
||
| 118 | sprintf( |
||
| 119 | 'Target directory for component "%s" unknown; is its parent installed?', |
||
| 120 | $component->getName()), |
||
| 121 | InstallationFailureException::CODE_UNKNOWN_TARGET_DIRECTORY); |
||
| 122 | } |
||
| 123 | |||
| 124 | $targetDirectory = $this->platform->joinPaths([ |
||
| 125 | $typeDirectory, |
||
| 126 | $component->getPluginName(), |
||
| 127 | ]); |
||
| 128 | $tempDirectory = $this->platform->createTempDirectory(); |
||
| 129 | |||
| 130 | do { |
||
| 131 | try { |
||
| 132 | $sourceDirectory = $packageSource->obtainPackage( |
||
| 133 | $tempDirectory, $this->timeout, $resolvedComponentVersion, |
||
| 134 | $this->filesystem, $logger); |
||
| 135 | $obtained = true; |
||
| 136 | } catch (RetryablePackageFailureException $e) { |
||
| 137 | $remainingAttempts--; |
||
| 138 | $logger->warning('Failed to obtain package', [ |
||
| 139 | 'attempt' => $this->attempts - $remainingAttempts, |
||
| 140 | 'attempts' => $this->attempts, |
||
| 141 | 'exception' => $e->getPrevious(), |
||
| 142 | ]); |
||
| 143 | } |
||
| 144 | } while ($remainingAttempts > 0 && !$obtained); |
||
| 145 | |||
| 146 | if (!$obtained) { |
||
| 147 | throw new UnsatisfiedVersionException( |
||
| 148 | sprintf( |
||
| 149 | 'Package source "%s" unable to obtain component "%s"', |
||
| 150 | $packageSource->getId(), |
||
| 151 | $resolvedComponentVersion->getComponent()->getName()), |
||
| 152 | UnsatisfiedVersionException::CODE_PACKAGE_SOURCE_FAILED); |
||
| 153 | } |
||
| 154 | |||
| 155 | if ($resolvedComponentVersion->getFinalVersion() === null) { |
||
| 156 | $logger->warning('Package source did not indicate final version; defaulting to desired version', [ |
||
| 157 | 'version' => $resolvedComponentVersion->getVersion()->getVersion(), |
||
| 158 | ]); |
||
| 159 | |||
| 160 | $resolvedComponentVersion->setFinalVersion( |
||
| 161 | $resolvedComponentVersion->getVersion()->getVersion()); |
||
| 162 | } |
||
| 163 | |||
| 164 | $logger->debug('Downloaded component source', [ |
||
| 165 | 'packageSource' => $packageSource->getName(), |
||
| 166 | 'sourceDirectory' => $sourceDirectory, |
||
| 167 | ]); |
||
| 168 | |||
| 169 | if ($this->filesystem->exists($targetDirectory)) { |
||
| 170 | $logger->warning('Component directory already exists; removing', [ |
||
| 171 | 'targetDirectory' => $targetDirectory, |
||
| 172 | ]); |
||
| 173 | |||
| 174 | $this->filesystem->remove($targetDirectory); |
||
| 175 | } |
||
| 176 | |||
| 177 | $logger->info('Copying component source to Moodle directory', [ |
||
| 178 | 'sourceDirectory' => $sourceDirectory, |
||
| 179 | 'targetDirectory' => $targetDirectory, |
||
| 180 | ]); |
||
| 181 | $this->filesystem->mirror($sourceDirectory, $targetDirectory); |
||
| 182 | |||
| 183 | $logger->info('Pinning component at installed final version', [ |
||
| 184 | 'finalVersion' => $resolvedComponentVersion->getFinalVersion(), |
||
| 185 | ]); |
||
| 186 | $projectLockFile->addResolvedComponentVersion($resolvedComponentVersion); |
||
| 187 | |||
| 188 | $logger->info('Cleaning up after component installation', [ |
||
| 189 | 'tempDirectory' => $tempDirectory, |
||
| 190 | ]); |
||
| 191 | try { |
||
| 192 | $this->filesystem->chmod([$tempDirectory], 0750, 0000, true); |
||
|
0 ignored issues
–
show
|
|||
| 193 | $this->filesystem->remove([$tempDirectory]); |
||
|
0 ignored issues
–
show
array($tempDirectory) is of type array<integer,string,{"0":"string"}>, but the function expects a string|object<Symfony\Co...nt\Filesystem\iterable>.
It seems like the type of the argument is not accepted by the function/method which you are calling. In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug. We suggest to add an explicit type cast like in the following example: function acceptsInteger($int) { }
$x = '123'; // string "123"
// Instead of
acceptsInteger($x);
// we recommend to use
acceptsInteger((integer) $x);
Loading history...
|
|||
| 194 | } catch (IOException $e) { |
||
| 195 | $logger->warning('Unable to clean up temporary directory', [ |
||
| 196 | 'code' => $e->getCode(), |
||
| 197 | 'message' => $e->getMessage(), |
||
| 198 | 'tempDirectory' => $tempDirectory, |
||
| 199 | ]); |
||
| 200 | } |
||
| 201 | } |
||
| 202 | } |
||
| 203 | } |
||
| 204 |
It seems like the type of the argument is not accepted by the function/method which you are calling.
In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.
We suggest to add an explicit type cast like in the following example: