diff --git a/application/Espo/Core/Utils/File/Manager.php b/application/Espo/Core/Utils/File/Manager.php
index 8296acc189..5d2c623628 100644
--- a/application/Espo/Core/Utils/File/Manager.php
+++ b/application/Espo/Core/Utils/File/Manager.php
@@ -44,7 +44,6 @@ class Manager
if (isset($config)) {
$params = array(
'defaultPermissions' => $config->get('defaultPermissions'),
- 'permissionMap' => $config->get('permissionMap'),
);
}
@@ -381,11 +380,11 @@ class Manager
{
$fullPath = $this->concatPaths($path);
- if (file_exists($fullPath) && is_dir($path)) {
+ if (file_exists($fullPath) && is_dir($fullPath)) {
return true;
}
- $defaultPermissions = $this->getPermissionUtils()->getDefaultPermissions();
+ $defaultPermissions = $this->getPermissionUtils()->getRequiredPermissions($fullPath);
if (!isset($permission)) {
$permission = (string) $defaultPermissions['dir'];
@@ -393,7 +392,11 @@ class Manager
}
try {
+ $umask = @umask(0);
$result = mkdir($fullPath, $permission, true);
+ if ($umask) {
+ @umask($umask);
+ }
if (!empty($defaultPermissions['user'])) {
$this->getPermissionUtils()->chown($fullPath);
@@ -484,11 +487,11 @@ class Manager
*/
public function checkCreateFile($filePath)
{
- $defaultPermissions = $this->getPermissionUtils()->getDefaultPermissions();
+ $defaultPermissions = $this->getPermissionUtils()->getRequiredPermissions($filePath);
if (file_exists($filePath)) {
if (!is_writable($filePath) && !in_array($this->getPermissionUtils()->getCurrentPermission($filePath), array($defaultPermissions['file'], $defaultPermissions['dir']))) {
- return $this->getPermissionUtils()->setDefaultPermissions($filePath, true);
+ return $this->getPermissionUtils()->setDefaultPermissions($filePath);
}
return true;
}
@@ -504,7 +507,7 @@ class Manager
}
if (touch($filePath)) {
- return $this->getPermissionUtils()->setDefaultPermissions($filePath, true);
+ return $this->getPermissionUtils()->setDefaultPermissions($filePath);
}
return false;
diff --git a/application/Espo/Core/Utils/File/Permission.php b/application/Espo/Core/Utils/File/Permission.php
index 41ee2a1109..1c260c1a57 100644
--- a/application/Espo/Core/Utils/File/Permission.php
+++ b/application/Espo/Core/Utils/File/Permission.php
@@ -28,8 +28,9 @@
************************************************************************/
namespace Espo\Core\Utils\File;
-use Espo\Core\Utils,
- Espo\Core\Exceptions\Error;
+
+use Espo\Core\Utils;
+use Espo\Core\Exceptions\Error;
class Permission
{
@@ -44,47 +45,45 @@ class Permission
protected $permissionErrorRules = null;
- protected $params = array(
- 'defaultPermissions' => array (
- 'dir' => '0775',
- 'file' => '0664',
- 'user' => '',
- 'group' => '',
- ),
- 'permissionMap' => array(
+ protected $writableMap = [
+ 'data' => [
+ 'recursive' => true,
+ ],
+ 'application/Espo/Modules' => [
+ 'recursive' => false,
+ ],
+ 'client/modules' => [
+ 'recursive' => false,
+ ],
+ 'custom/Espo/Custom' => [
+ 'recursive' => true,
+ ],
+ ];
- /** array('0664', '0775') */
- 'writable' => array(
- 'data',
- 'custom',
- ),
-
- /** array('0644', '0755') */
- 'readable' => array(
- 'api',
- 'application',
- 'client',
- 'vendor',
- 'index.php',
- 'cron.php',
- 'rebuild.php',
- 'main.html',
- 'reset.html',
- ),
- ),
- );
-
- protected $permissionRules = array(
- 'writable' => array('0664', '0775'),
- 'readable' => array('0644', '0755'),
- );
+ protected $defaultPermissions = [
+ 'dir' => '0755',
+ 'file' => '0644',
+ 'user' => null,
+ 'group' => null,
+ ];
+ protected $writablePermissions = [
+ 'file' => '0664',
+ 'dir' => '0775',
+ ];
public function __construct(Manager $fileManager, array $params = null)
{
$this->fileManager = $fileManager;
- if (isset($params)) {
- $this->params = $params;
+
+ if ($params) {
+ foreach ($params as $paramName => $paramValue) {
+ switch ($paramName) {
+ case 'defaultPermissions':
+ $this->defaultPermissions = array_merge($this->defaultPermissions, $paramValue);
+ break;
+ }
+ }
}
}
@@ -93,11 +92,6 @@ class Permission
return $this->fileManager;
}
- protected function getParams()
- {
- return $this->params;
- }
-
/**
* Get default settings
*
@@ -105,14 +99,34 @@ class Permission
*/
public function getDefaultPermissions()
{
- $params = $this->getParams();
- return $params['defaultPermissions'];
+ return $this->defaultPermissions;
}
-
- public function getPermissionRules()
+ public function getWritableMap()
{
- return $this->permissionRules;
+ return $this->writableMap;
+ }
+
+ public function getWritableList()
+ {
+ return array_keys($this->writableMap);
+ }
+
+ public function getRequiredPermissions($path)
+ {
+ $permission = $this->getDefaultPermissions();
+
+ foreach ($this->getWritableMap() as $writablePath => $writableOptions) {
+ if (!$writableOptions['recursive'] && $path == $writablePath) {
+ return array_merge($permission, $this->writablePermissions);
+ }
+
+ if ($writableOptions['recursive'] && substr($path, 0, strlen($writablePath)) == $writablePath) {
+ return array_merge($permission, $this->writablePermissions);
+ }
+ }
+
+ return $permission;
}
/**
@@ -129,7 +143,7 @@ class Permission
return false;
}
- $permission = $this->getDefaultPermissions();
+ $permission = $this->getRequiredPermissions($path);
$result = $this->chmod($path, array($permission['file'], $permission['dir']), $recurse);
if (!empty($permission['user'])) {
@@ -342,8 +356,8 @@ class Permission
*
* @return bool
*/
- protected function chgrpRecurse($path, $group) {
-
+ protected function chgrpRecurse($path, $group)
+ {
if (!file_exists($path)) {
return false;
}
@@ -461,60 +475,38 @@ class Permission
*
* @return bool
*/
- public function setMapPermission($mode = null)
+ public function setMapPermission()
{
$this->permissionError = array();
$this->permissionErrorRules = array();
- $params = $this->getParams();
-
- $permissionRules = $this->permissionRules;
- if (isset($mode)) {
- foreach ($permissionRules as &$value) {
- $value = $mode;
- }
- }
-
$result = true;
- foreach ($params['permissionMap'] as $type => $items) {
- $permission = $permissionRules[$type];
+ foreach ($this->getWritableMap() as $path => $options) {
+ if (!file_exists($path)) continue;
- foreach ($items as $item) {
+ try {
+ $this->chmod($path, $this->writablePermissions, $options['recursive']);
+ } catch (\Throwable $e) {}
- if (file_exists($item)) {
+ /** check is writable */
+ $res = is_writable($path);
- try {
- $this->chmod($item, $permission, true);
- } catch (\Exception $e) {
- }
-
- $res = is_readable($item);
-
- /** check is wtitable */
- if ($type == 'writable') {
-
- $res &= is_writable($item);
-
- if (is_dir($item)) {
- $name = uniqid();
-
- try {
- $res &= $this->getFileManager()->putContents(array($item, $name), 'test');
- $res &= $this->getFileManager()->removeFile($name, $item);
- } catch (\Exception $e) {
- $res = false;
- }
- }
- }
-
- if (!$res) {
- $result = false;
- $this->permissionError[] = $item;
- $this->permissionErrorRules[$item] = $permission;
- }
+ if (is_dir($path)) {
+ try {
+ $name = uniqid();
+ $res &= $this->getFileManager()->putContents([$path, $name], 'test');
+ $res &= $this->getFileManager()->removeFile($name, $path);
+ } catch (\Throwable $e) {
+ $res = false;
}
}
+
+ if (!$res) {
+ $result = false;
+ $this->permissionError[] = $path;
+ $this->permissionErrorRules[$path] = $this->writablePermissions;
+ }
}
return $result;
@@ -607,4 +599,3 @@ class Permission
}
}
-
diff --git a/application/Espo/Core/Utils/SystemRequirements.php b/application/Espo/Core/Utils/SystemRequirements.php
index 943fe4e8ec..30d2347fea 100644
--- a/application/Espo/Core/Utils/SystemRequirements.php
+++ b/application/Espo/Core/Utils/SystemRequirements.php
@@ -159,11 +159,12 @@ class SystemRequirements
{
return $this->getRequiredList('permissionRequirements', [
'permissionMap.writable',
- 'permissionMap.readable',
- ], $additionalData);
+ ], $additionalData, [
+ 'permissionMap.writable' => $this->getFileManager()->getPermissionUtils()->getWritableList(),
+ ]);
}
- protected function getRequiredList($type, $checkList, array $additionalData = null)
+ protected function getRequiredList($type, $checkList, array $additionalData = null, array $predefinedData = [])
{
$config = $this->getConfig();
@@ -172,7 +173,8 @@ class SystemRequirements
foreach ($checkList as $itemName) {
$methodName = 'check' . ucfirst($type);
if (method_exists($this, $methodName)) {
- $result = $this->$methodName($itemName, $config->get($itemName), $additionalData);
+ $itemValue = isset($predefinedData[$itemName]) ? $predefinedData[$itemName] : $config->get($itemName);
+ $result = $this->$methodName($itemName, $itemValue, $additionalData);
$list = array_merge($list, $result);
}
}
diff --git a/application/Espo/Core/defaults/systemConfig.php b/application/Espo/Core/defaults/systemConfig.php
index 2aae5c290e..49c8133bdc 100644
--- a/application/Espo/Core/defaults/systemConfig.php
+++ b/application/Espo/Core/defaults/systemConfig.php
@@ -29,31 +29,9 @@
return [
'defaultPermissions' => [
- 'dir' => '0775',
- 'file' => '0664',
'user' => '',
'group' => ''
],
- 'permissionMap' => [
- /** array('0664', '0775') */
- 'writable' => [
- 'data',
- 'custom',
- 'application/Espo/Modules',
- 'client/modules'
- ],
- /** array('0644', '0755') */
- 'readable' => [
- 'api',
- 'application',
- 'client',
- 'vendor',
- 'index.php',
- 'cron.php',
- 'rebuild.php',
- 'clear_cache.php'
- ],
- ],
'jobMaxPortion' => 15, /** Max number of jobs per one execution. */
'jobPeriod' => 7800, /** Max execution time (in seconds) allocated for a sinle job. If exceeded then set to Failed.*/
'jobPeriodForActiveProcess' => 36000, /** Max execution time (in seconds) allocated for a sinle job with active process. If exceeded then set to Failed.*/
@@ -89,10 +67,8 @@ return [
'crud',
'logger',
'isInstalled',
- 'defaultPermissions',
'systemUser',
- 'permissionMap',
- 'permissionRules',
+ 'defaultPermissions',
'passwordSalt',
'cryptKey',
'apiSecretKeys',
diff --git a/install/core/Installer.php b/install/core/Installer.php
index 550441ed9f..6c5ef0bb4d 100644
--- a/install/core/Installer.php
+++ b/install/core/Installer.php
@@ -45,8 +45,6 @@ class Installer
protected $isAuth = false;
- protected $permissionMap;
-
protected $permissionError;
private $passwordHash;
@@ -88,10 +86,6 @@ class Installer
require_once('install/core/SystemHelper.php');
$this->systemHelper = new SystemHelper();
- $configPath = $this->getConfig()->getConfigPath();
- $this->permissionMap = $this->getConfig()->get('permissionMap');
- $this->permissionMap['writable'][] = $configPath;
-
$this->databaseHelper = new \Espo\Core\Utils\Database\Helper($this->getConfig());
}
diff --git a/install/core/SystemHelper.php b/install/core/SystemHelper.php
index 44577fa78e..682cbf3d04 100644
--- a/install/core/SystemHelper.php
+++ b/install/core/SystemHelper.php
@@ -41,6 +41,8 @@ class SystemHelper extends \Espo\Core\Utils\System
protected $combineOperator = '&&';
+ protected $writableMap;
+
public function __construct()
{
$this->config = include('config.php');
@@ -50,6 +52,9 @@ class SystemHelper extends \Espo\Core\Utils\System
}
$this->apiPath = $this->config['apiPath'];
+
+ $permission = new \Espo\Core\Utils\File\Permission(new \Espo\Core\Utils\File\Manager());
+ $this->writableMap = $permission->getWritableMap();
}
protected function getMainConfig($optionName, $returns = null)
@@ -124,7 +129,7 @@ class SystemHelper extends \Espo\Core\Utils\System
return $cd.$sudoStr.'chown -R '.$owner.':'.$group.' '.$path;
}
- public function getChmodCommand($path, $permissions = array('755'), $isSudo = false, $isFile = null, $isCd = true)
+ public function getChmodCommand($path, $permissions = ['755'], $isRecursive = true, $isSudo = false, $isFile = null)
{
$path = empty($path) ? '.' : $path;
if (is_array($path)) {
@@ -133,27 +138,32 @@ class SystemHelper extends \Espo\Core\Utils\System
$sudoStr = $isSudo ? 'sudo ' : '';
- $cd = $isCd ? $this->getCd(true) : '';
-
if (is_string($permissions)) {
$permissions = (array) $permissions;
}
if (!isset($isFile) && count($permissions) == 1) {
- return $cd. $sudoStr . 'find '.$path.' -type d -exec ' . $sudoStr . 'chmod '.$permissions[0].' {} +';
+ if ($isRecursive) {
+ return $sudoStr . 'find '. $path .' -type d -exec ' . $sudoStr . 'chmod '. $permissions[0] .' {} +';
+ }
+ return $sudoStr . 'chmod '. $permissions[0] .' '. $path;
}
$bufPerm = (count($permissions) == 1) ? array_fill(0, 2, $permissions[0]) : $permissions;
$commands = array();
- if ($isCd) {
- $commands[] = $this->getCd();
+ if ($isRecursive) {
+ $commands[] = $sudoStr. 'find '.$path.' -type f -exec ' .$sudoStr.'chmod '.$bufPerm[0].' {} +';
+ $commands[] = $sudoStr . 'find '.$path.' -type d -exec ' .$sudoStr. 'chmod '.$bufPerm[1].' {} +';
+ } else {
+ if (file_exists($path) && is_file($path)) {
+ $commands[] = $sudoStr. 'chmod '. $bufPerm[0] .' '. $path;
+ } else {
+ $commands[] = $sudoStr. 'chmod '. $bufPerm[1] .' '. $path;
+ }
}
- $commands[] = $sudoStr. 'find '.$path.' -type f -exec ' .$sudoStr.'chmod '.$bufPerm[0].' {} +';//.'chmod '.$bufPerm[0].' $(find '.$path.' -type f)';
- $commands[] = $sudoStr . 'find '.$path.' -type d -exec ' .$sudoStr. 'chmod '.$bufPerm[1].' {} +';//.'chmod '.$bufPerm[1].' $(find '.$path.' -type d)';
-
if (count($permissions) >= 2) {
return implode(' ' . $this->combineOperator . ' ', $commands);
}
@@ -187,7 +197,7 @@ class SystemHelper extends \Espo\Core\Utils\System
* @param bool $isFile
* @return string
*/
- public function getPermissionCommands($path, $permissions = array('644', '755'), $isSudo = false, $isFile = null, $changeOwner = true)
+ public function getPermissionCommands($path, $permissions = ['644', '755'], $isSudo = false, $isFile = null, $changeOwner = true, $isCd = true)
{
if (is_string($path)) {
$path = array_fill(0, 2, $path);
@@ -195,7 +205,30 @@ class SystemHelper extends \Espo\Core\Utils\System
list($chmodPath, $chownPath) = $path;
$commands = array();
- $commands[] = $this->getChmodCommand($chmodPath, $permissions, $isSudo, $isFile);
+
+ if ($isCd) {
+ $commands[] = $this->getCd();
+ }
+
+ $chmodPath = (array) $chmodPath;
+
+ $pathList = [];
+ $recursivePathList = [];
+ foreach ($chmodPath as $pathItem) {
+ if (isset($this->writableMap[$pathItem]) && !$this->writableMap[$pathItem]['recursive']) {
+ $pathList[] = $pathItem;
+ continue;
+ }
+ $recursivePathList[] = $pathItem;
+ }
+
+ if (!empty($pathList)) {
+ $commands[] = $this->getChmodCommand($pathList, $permissions, false, $isSudo, $isFile);
+ }
+
+ if (!empty($recursivePathList)) {
+ $commands[] = $this->getChmodCommand($recursivePathList, $permissions, true, $isSudo, $isFile);
+ }
if ($changeOwner) {
$chown = $this->getChownCommand($chownPath, $isSudo, false);
diff --git a/install/core/actions/checkPermission.php b/install/core/actions/checkPermission.php
index d544791449..90f0ff6c58 100644
--- a/install/core/actions/checkPermission.php
+++ b/install/core/actions/checkPermission.php
@@ -50,7 +50,7 @@ if (!$installer->checkPermission()) {
$changeOwner = false;
}
}
- $result['errorMsg'] = $langs['messages']['Permission denied to'] . ':
/'.implode('
/', $urls).'';
+ $result['errorMsg'] = $langs['messages']['Permission denied to'] . ':'.implode('
', $urls).'';
$result['errorFixInstruction'] = str_replace( '"{C}"' , $instruction, $langs['messages']['permissionInstruction']) . "