Skip to content

Commit ef47d8b

Browse files
authored
Merge pull request composer#6486 from WilHall/feature/htaccess-protect-option
Add htaccess-protect option for disabling the creation of .htaccess files
2 parents 91a4e76 + 69282de commit ef47d8b

File tree

7 files changed

+37
-9
lines changed

7 files changed

+37
-9
lines changed

doc/03-cli.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -898,4 +898,9 @@ If set to 1, this env changes the default path repository strategy to `mirror` i
898898
of `symlink`. As it is the default strategy being set it can still be overwritten by
899899
repository options.
900900
901+
### COMPOSER_HTACCESS_PROTECT
902+
903+
Defaults to `1`. If set to `0`, Composer will not create `.htaccess` files in the
904+
composer home, cache, and data directories.
905+
901906
← [Libraries](02-libraries.md) | [Schema](04-schema.md) →

doc/06-config.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -265,4 +265,9 @@ Example:
265265
}
266266
```
267267

268+
## htaccess-protect
269+
270+
Defaults to `true`. If set to `false`, Composer will not create `.htaccess` files
271+
in the composer home, cache, and data directories.
272+
268273
← [Repositories](05-repositories.md) | [Community](07-community.md) →

res/composer-schema.json

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -274,6 +274,10 @@
274274
"archive-dir": {
275275
"type": "string",
276276
"description": "The default archive path when not provided on cli, defaults to \".\"."
277+
},
278+
"htaccess-protect": {
279+
"type": "boolean",
280+
"description": "Defaults to true. If set to false, Composer will not create .htaccess files in the composer home, cache, and data directories."
277281
}
278282
}
279283
},

src/Composer/Command/ConfigCommand.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -402,6 +402,7 @@ function ($val) {
402402
},
403403
),
404404
'github-expose-hostname' => array($booleanValidator, $booleanNormalizer),
405+
'htaccess-protect' => array($booleanValidator, $booleanNormalizer),
405406
);
406407
$multiConfigValues = array(
407408
'github-protocols' => array(

src/Composer/Config.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@ class Config
6060
'platform' => array(),
6161
'archive-format' => 'tar',
6262
'archive-dir' => '.',
63+
'htaccess-protect' => true,
6364
// valid keys without defaults (auth config stuff):
6465
// bitbucket-oauth
6566
// github-oauth
@@ -215,6 +216,7 @@ public function get($key, $flags = 0)
215216
case 'cache-vcs-dir':
216217
case 'cafile':
217218
case 'capath':
219+
case 'htaccess-protect':
218220
// convert foo-bar to COMPOSER_FOO_BAR and check if it exists since it overrides the local config
219221
$env = 'COMPOSER_' . strtoupper(strtr($key, '-', '_'));
220222

src/Composer/Factory.php

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -164,16 +164,19 @@ public static function createConfig(IOInterface $io = null, $cwd = null)
164164
'data-dir' => self::getDataDir($home),
165165
)));
166166

167-
// Protect directory against web access. Since HOME could be
168-
// the www-data's user home and be web-accessible it is a
169-
// potential security risk
170-
$dirs = array($config->get('home'), $config->get('cache-dir'), $config->get('data-dir'));
171-
foreach ($dirs as $dir) {
172-
if (!file_exists($dir . '/.htaccess')) {
173-
if (!is_dir($dir)) {
174-
Silencer::call('mkdir', $dir, 0777, true);
167+
$htaccessProtect = (bool) $config->get('htaccess-protect');
168+
if ($htaccessProtect) {
169+
// Protect directory against web access. Since HOME could be
170+
// the www-data's user home and be web-accessible it is a
171+
// potential security risk
172+
$dirs = array($config->get('home'), $config->get('cache-dir'), $config->get('data-dir'));
173+
foreach ($dirs as $dir) {
174+
if (!file_exists($dir . '/.htaccess')) {
175+
if (!is_dir($dir)) {
176+
Silencer::call('mkdir', $dir, 0777, true);
177+
}
178+
Silencer::call('file_put_contents', $dir . '/.htaccess', 'Deny from all');
175179
}
176-
Silencer::call('file_put_contents', $dir . '/.htaccess', 'Deny from all');
177180
}
178181
}
179182

tests/Composer/Test/ConfigTest.php

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -310,4 +310,12 @@ public function testProcessTimeout()
310310
$this->assertEquals(0, $config->get('process-timeout'));
311311
putenv('COMPOSER_PROCESS_TIMEOUT');
312312
}
313+
314+
public function testHtaccessProtect()
315+
{
316+
putenv('COMPOSER_HTACCESS_PROTECT=0');
317+
$config = new Config(true);
318+
$this->assertEquals(0, $config->get('htaccess-protect'));
319+
putenv('COMPOSER_HTACCESS_PROTECT');
320+
}
313321
}

0 commit comments

Comments
 (0)