}
Civi::$statics[__CLASS__]['file_extensions'] = $extensions;
}
+ $restricted = CRM_Utils_Constant::value('CIVICRM_RESTRICTED_UPLOADS', '/(php|php\d|phtml|phar|pl|py|cgi|asp|js|sh|exe|pcgi\d)/i');
// support lower and uppercase file extensions
- return (bool) isset(Civi::$statics[__CLASS__]['file_extensions'][strtolower($ext)]);
+ return (bool) isset(Civi::$statics[__CLASS__]['file_extensions'][strtolower($ext)]) && !preg_match($restricted, strtolower($ext));
}
/**
*/
class CRM_Utils_FileTest extends CiviUnitTestCase {
+ public function tearDown(): void {
+ $this->callAPISuccess('OptionValue', 'get', ['option_group_id' => 'safe_file_extension', 'value' => 17, 'api.option_value.delete' => ['id' => "\$value.id"]]);
+ }
+
/**
* Test is child path.
*/
}
}
+ /**
+ * Generate examples to test the safe file extension
+ * @return array
+ */
+ public static function safeFileExtensionExamples(): array {
+ $cases = [
+ 'PDF File Extension' => ['pdf', TRUE, TRUE],
+ 'PHP File Extension' => ['php', FALSE, FALSE],
+ 'PHAR' => ['phar', FALSE, FALSE],
+ 'PHP5 File Extension' => ['php5', FALSE, FALSE],
+ ];
+ return $cases;
+ }
+
+ /**
+ * Test that modifying the safe File Extension option group still ensures some are blocked
+ * @dataProvider safeFileExtensionExamples
+ */
+ public function testSafeFileExtensionValidation($extension, $standardInstallCheck, $afterModificationCheck): void {
+ $this->assertEquals($standardInstallCheck, CRM_Utils_File::isExtensionSafe($extension));
+ $optionValue = $this->callAPISuccess('OptionValue', 'create', [
+ 'option_group_id' => 'safe_file_extension',
+ 'label' => $extension,
+ 'name' => $extension,
+ 'value' => 17,
+ ]);
+ unset(Civi::$statics['CRM_Utils_File']['file_extensions']);
+ $this->assertEquals($standardInstallCheck, CRM_Utils_File::isExtensionSafe($extension));
+ }
+
}