|
12 | 12 | use League\Flysystem\Adapter\Local as LocalAdapter;
|
13 | 13 | use League\Flysystem\FileExistsException;
|
14 | 14 | use League\Flysystem\FileNotFoundException;
|
| 15 | +use yii\validators\InlineValidator; |
15 | 16 |
|
16 | 17 | /**
|
17 | 18 | * The local volume class. Handles the implementation of the local filesystem as a volume in
|
@@ -58,9 +59,61 @@ protected function defineRules(): array
|
58 | 59 | {
|
59 | 60 | $rules = parent::defineRules();
|
60 | 61 | $rules[] = [['path'], 'required'];
|
| 62 | + $rules[] = [['path'], 'validatePath']; |
61 | 63 | return $rules;
|
62 | 64 | }
|
63 | 65 |
|
| 66 | + /** |
| 67 | + * @param string $attribute |
| 68 | + * @param array|null $params |
| 69 | + * @param InlineValidator $validator |
| 70 | + * @param string $path |
| 71 | + * @return void |
| 72 | + * @since 3.6.7 |
| 73 | + */ |
| 74 | + public function validatePath(string $attribute, ?array $params, InlineValidator $validator, string $path): void |
| 75 | + { |
| 76 | + if ($created = !file_exists($path)) { |
| 77 | + FileHelper::createDirectory($path); |
| 78 | + } |
| 79 | + |
| 80 | + $path = realpath($this->getRootPath()); |
| 81 | + |
| 82 | + if ($path === false) { |
| 83 | + return; |
| 84 | + } |
| 85 | + |
| 86 | + // Make sure it’s not within any of the system directories |
| 87 | + $pathService = Craft::$app->getPath(); |
| 88 | + $systemDirs = [ |
| 89 | + Craft::getAlias('@contentMigrations'), |
| 90 | + Craft::getAlias('@lib'), |
| 91 | + $pathService->getComposerBackupsPath(false), |
| 92 | + $pathService->getConfigBackupPath(false), |
| 93 | + $pathService->getConfigDeltaPath(false), |
| 94 | + $pathService->getConfigPath(), |
| 95 | + $pathService->getDbBackupPath(false), |
| 96 | + $pathService->getLogPath(false), |
| 97 | + $pathService->getRebrandPath(false), |
| 98 | + $pathService->getRuntimePath(false), |
| 99 | + $pathService->getSiteTemplatesPath(), |
| 100 | + $pathService->getSiteTranslationsPath(), |
| 101 | + $pathService->getTestsPath(), |
| 102 | + $pathService->getVendorPath(), |
| 103 | + ]; |
| 104 | + |
| 105 | + foreach ($systemDirs as $dir) { |
| 106 | + $dir = realpath($dir); |
| 107 | + if ($dir !== false && strpos($path . DIRECTORY_SEPARATOR, $dir . DIRECTORY_SEPARATOR) === 0) { |
| 108 | + $validator->addError($this, $attribute, Craft::t('app', 'Local volumes cannot be located within system directories.')); |
| 109 | + if ($created) { |
| 110 | + FileHelper::removeDirectory($path); |
| 111 | + } |
| 112 | + break; |
| 113 | + } |
| 114 | + } |
| 115 | + } |
| 116 | + |
64 | 117 | /**
|
65 | 118 | * @inheritdoc
|
66 | 119 | */
|
|
0 commit comments