spatie /
image
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 | namespace Spatie\Image; |
||
| 4 | |||
| 5 | use Exception; |
||
| 6 | use FilesystemIterator; |
||
| 7 | use League\Glide\Server; |
||
| 8 | use League\Glide\ServerFactory; |
||
| 9 | use Spatie\Image\Exceptions\CouldNotConvert; |
||
| 10 | use Spatie\Image\Exceptions\InvalidTemporaryDirectory; |
||
| 11 | |||
| 12 | final class GlideConversion |
||
| 13 | { |
||
| 14 | /** @var string */ |
||
| 15 | private $inputImage; |
||
| 16 | |||
| 17 | /** @var string */ |
||
| 18 | private $imageDriver = 'gd'; |
||
| 19 | |||
| 20 | /** @var string */ |
||
| 21 | private $conversionResult = null; |
||
| 22 | |||
| 23 | /** @var string */ |
||
| 24 | private $temporaryDirectory = null; |
||
| 25 | |||
| 26 | public static function create(string $inputImage): self |
||
| 27 | { |
||
| 28 | return new self($inputImage); |
||
| 29 | } |
||
| 30 | |||
| 31 | public function setTemporaryDirectory(string $temporaryDirectory) |
||
| 32 | { |
||
| 33 | if (! isset($temporaryDirectory)) { |
||
| 34 | return $this; |
||
| 35 | } |
||
| 36 | |||
| 37 | if (! is_dir($temporaryDirectory)) { |
||
| 38 | try { |
||
| 39 | mkdir($temporaryDirectory); |
||
| 40 | } catch (Exception $exception) { |
||
| 41 | throw InvalidTemporaryDirectory::temporaryDirectoryNotCreatable($temporaryDirectory); |
||
| 42 | } |
||
| 43 | } |
||
| 44 | |||
| 45 | if (! is_writable($temporaryDirectory)) { |
||
| 46 | throw InvalidTemporaryDirectory::temporaryDirectoryNotWritable($temporaryDirectory); |
||
| 47 | } |
||
| 48 | |||
| 49 | $this->temporaryDirectory = $temporaryDirectory; |
||
| 50 | |||
| 51 | return $this; |
||
| 52 | } |
||
| 53 | |||
| 54 | public function getTemporaryDirectory(): string |
||
| 55 | { |
||
| 56 | return $this->temporaryDirectory; |
||
| 57 | } |
||
| 58 | |||
| 59 | public function __construct(string $inputImage) |
||
| 60 | { |
||
| 61 | $this->temporaryDirectory = sys_get_temp_dir(); |
||
| 62 | |||
| 63 | $this->inputImage = $inputImage; |
||
| 64 | } |
||
| 65 | |||
| 66 | public function useImageDriver(string $imageDriver): self |
||
| 67 | { |
||
| 68 | $this->imageDriver = $imageDriver; |
||
| 69 | |||
| 70 | return $this; |
||
| 71 | } |
||
| 72 | |||
| 73 | public function performManipulations(Manipulations $manipulations) |
||
| 74 | { |
||
| 75 | foreach ($manipulations->getManipulationSequence() as $manipulationGroup) { |
||
| 76 | $inputFile = $this->conversionResult ?? $this->inputImage; |
||
| 77 | |||
| 78 | $watermarkPath = $this->extractWatermarkPath($manipulationGroup); |
||
| 79 | |||
| 80 | $glideServer = $this->createGlideServer($inputFile, $watermarkPath); |
||
| 81 | |||
| 82 | $glideServer->setGroupCacheInFolders(false); |
||
| 83 | |||
| 84 | $manipulatedImage = $this->temporaryDirectory.DIRECTORY_SEPARATOR.$glideServer->makeImage( |
||
| 85 | pathinfo($inputFile, PATHINFO_BASENAME), |
||
| 86 | $this->prepareManipulations($manipulationGroup) |
||
| 87 | ); |
||
| 88 | |||
| 89 | if ($this->conversionResult) { |
||
| 90 | unlink($this->conversionResult); |
||
| 91 | } |
||
| 92 | |||
| 93 | $this->conversionResult = $manipulatedImage; |
||
| 94 | } |
||
| 95 | |||
| 96 | return $this; |
||
| 97 | } |
||
| 98 | |||
| 99 | /** |
||
| 100 | * Removes the watermark path from the manipulationGroup and returns it. This way it can be injected into the Glide |
||
| 101 | * server as the `watermarks` path. |
||
| 102 | * |
||
| 103 | * @param $manipulationGroup |
||
| 104 | * |
||
| 105 | * @return null|string |
||
| 106 | */ |
||
| 107 | private function extractWatermarkPath(&$manipulationGroup) |
||
| 108 | { |
||
| 109 | if (array_key_exists('watermark', $manipulationGroup)) { |
||
| 110 | $watermarkPath = dirname($manipulationGroup['watermark']); |
||
| 111 | |||
| 112 | $manipulationGroup['watermark'] = basename($manipulationGroup['watermark']); |
||
| 113 | |||
| 114 | return $watermarkPath; |
||
| 115 | } |
||
| 116 | } |
||
| 117 | |||
| 118 | private function createGlideServer($inputFile, string $watermarkPath = null): Server |
||
| 119 | { |
||
| 120 | $config = [ |
||
| 121 | 'source' => dirname($inputFile), |
||
| 122 | 'cache' => $this->temporaryDirectory, |
||
| 123 | 'driver' => $this->imageDriver, |
||
| 124 | ]; |
||
| 125 | |||
| 126 | if ($watermarkPath) { |
||
|
0 ignored issues
–
show
|
|||
| 127 | $config['watermarks'] = $watermarkPath; |
||
| 128 | } |
||
| 129 | |||
| 130 | return ServerFactory::create($config); |
||
| 131 | } |
||
| 132 | |||
| 133 | public function save(string $outputFile) |
||
| 134 | { |
||
| 135 | if ($this->conversionResult == '') { |
||
| 136 | copy($this->inputImage, $outputFile); |
||
| 137 | |||
| 138 | return; |
||
| 139 | } |
||
| 140 | |||
| 141 | $conversionResultDirectory = pathinfo($this->conversionResult, PATHINFO_DIRNAME); |
||
| 142 | |||
| 143 | copy($this->conversionResult, $outputFile); |
||
| 144 | |||
| 145 | unlink($this->conversionResult); |
||
| 146 | |||
| 147 | if ($this->directoryIsEmpty($conversionResultDirectory) && $conversionResultDirectory !== '/tmp') { |
||
| 148 | rmdir($conversionResultDirectory); |
||
| 149 | } |
||
| 150 | } |
||
| 151 | |||
| 152 | private function prepareManipulations(array $manipulationGroup): array |
||
| 153 | { |
||
| 154 | $glideManipulations = []; |
||
| 155 | |||
| 156 | foreach ($manipulationGroup as $name => $argument) { |
||
| 157 | if ($name !== 'optimize') { |
||
| 158 | $glideManipulations[$this->convertToGlideParameter($name)] = $argument; |
||
| 159 | } |
||
| 160 | } |
||
| 161 | |||
| 162 | return $glideManipulations; |
||
| 163 | } |
||
| 164 | |||
| 165 | private function convertToGlideParameter(string $manipulationName): string |
||
| 166 | { |
||
| 167 | $conversions = [ |
||
| 168 | 'width' => 'w', |
||
| 169 | 'height' => 'h', |
||
| 170 | 'blur' => 'blur', |
||
| 171 | 'pixelate' => 'pixel', |
||
| 172 | 'crop' => 'fit', |
||
| 173 | 'manualCrop' => 'crop', |
||
| 174 | 'orientation' => 'or', |
||
| 175 | 'flip' => 'flip', |
||
| 176 | 'fit' => 'fit', |
||
| 177 | 'devicePixelRatio' => 'dpr', |
||
| 178 | 'brightness' => 'bri', |
||
| 179 | 'contrast' => 'con', |
||
| 180 | 'gamma' => 'gam', |
||
| 181 | 'sharpen' => 'sharp', |
||
| 182 | 'filter' => 'filt', |
||
| 183 | 'background' => 'bg', |
||
| 184 | 'border' => 'border', |
||
| 185 | 'quality' => 'q', |
||
| 186 | 'format' => 'fm', |
||
| 187 | 'watermark' => 'mark', |
||
| 188 | 'watermarkWidth' => 'markw', |
||
| 189 | 'watermarkHeight' => 'markh', |
||
| 190 | 'watermarkFit' => 'markfit', |
||
| 191 | 'watermarkPaddingX' => 'markx', |
||
| 192 | 'watermarkPaddingY' => 'marky', |
||
| 193 | 'watermarkPosition' => 'markpos', |
||
| 194 | 'watermarkOpacity' => 'markalpha', |
||
| 195 | ]; |
||
| 196 | |||
| 197 | if (! isset($conversions[$manipulationName])) { |
||
| 198 | throw CouldNotConvert::unknownManipulation($manipulationName); |
||
| 199 | } |
||
| 200 | |||
| 201 | return $conversions[$manipulationName]; |
||
| 202 | } |
||
| 203 | |||
| 204 | private function directoryIsEmpty(string $directory): bool |
||
| 205 | { |
||
| 206 | $iterator = new FilesystemIterator($directory); |
||
| 207 | |||
| 208 | return ! $iterator->valid(); |
||
| 209 | } |
||
| 210 | } |
||
| 211 |
In PHP, under loose comparison (like
==, or!=, orswitchconditions), values of different types might be equal.For
stringvalues, the empty string''is a special case, in particular the following results might be unexpected: