improved check permission in installation
This commit is contained in:
@@ -76,9 +76,7 @@ class Container
|
||||
private function loadFileManager()
|
||||
{
|
||||
return new \Espo\Core\Utils\File\Manager(
|
||||
array(
|
||||
'defaultPermissions' => $this->get('config')->get('defaultPermissions'),
|
||||
)
|
||||
$this->get('config')
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -29,9 +29,17 @@ class Manager
|
||||
{
|
||||
private $permission;
|
||||
|
||||
public function __construct(array $params = null)
|
||||
public function __construct(\Espo\Core\Utils\Config $config = null)
|
||||
{
|
||||
$this->permission = new Permission($params);
|
||||
$params = null;
|
||||
if (isset($config)) {
|
||||
$params = array(
|
||||
'defaultPermissions' => $config->get('defaultPermissions'),
|
||||
'permissionMap' => $config->get('permissionMap'),
|
||||
);
|
||||
}
|
||||
|
||||
$this->permission = new Permission($this, $params);
|
||||
}
|
||||
|
||||
public function getPermissionUtils()
|
||||
@@ -39,8 +47,6 @@ class Manager
|
||||
return $this->permission;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Get a list of files in specified directory
|
||||
*
|
||||
@@ -173,7 +179,12 @@ class Manager
|
||||
throw new Error('Permission denied in '. $path);
|
||||
}
|
||||
|
||||
return (file_put_contents($fullPath, $data, $flags, $context) !== FALSE);
|
||||
$res = (file_put_contents($fullPath, $data, $flags, $context) !== FALSE);
|
||||
if ($res && function_exists('opcache_invalidate')) {
|
||||
opcache_invalidate($fullPath);
|
||||
}
|
||||
|
||||
return $res;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with EspoCRM. If not, see http://www.gnu.org/licenses/.
|
||||
************************************************************************/
|
||||
************************************************************************/
|
||||
|
||||
namespace Espo\Core\Utils\File;
|
||||
|
||||
@@ -27,71 +27,121 @@ use Espo\Core\Utils,
|
||||
|
||||
class Permission
|
||||
{
|
||||
private $fileManager;
|
||||
|
||||
/**
|
||||
* Last permission error
|
||||
*
|
||||
* @var array | string
|
||||
*/
|
||||
protected $permissionError = null;
|
||||
|
||||
protected $permissionErrorRules = null;
|
||||
|
||||
protected $params = array(
|
||||
'defaultPermissions' => array (
|
||||
'dir' => '0775',
|
||||
'file' => '0664',
|
||||
'user' => '',
|
||||
'group' => '',
|
||||
'dir' => '0775',
|
||||
'file' => '0664',
|
||||
'user' => '',
|
||||
'group' => '',
|
||||
),
|
||||
'permissionMap' => array(
|
||||
|
||||
/** 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'),
|
||||
);
|
||||
|
||||
public function __construct(array $params = null)
|
||||
|
||||
public function __construct(Manager $fileManager, array $params = null)
|
||||
{
|
||||
$this->fileManager = $fileManager;
|
||||
if (isset($params)) {
|
||||
$this->params = $params;
|
||||
}
|
||||
}
|
||||
|
||||
protected function getFileManager()
|
||||
{
|
||||
return $this->fileManager;
|
||||
}
|
||||
|
||||
protected function getParams()
|
||||
{
|
||||
return $this->params;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get default settings
|
||||
/**
|
||||
* Get default settings
|
||||
*
|
||||
* @return object
|
||||
*/
|
||||
public function getDefaultPermissions()
|
||||
public function getDefaultPermissions()
|
||||
{
|
||||
$params = $this->getParams();
|
||||
return $params['defaultPermissions'];
|
||||
}
|
||||
|
||||
|
||||
public function getPermissionRules()
|
||||
{
|
||||
return $this->permissionRules;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Set default permission
|
||||
* Set default permission
|
||||
*
|
||||
* @param string $path
|
||||
* @param bool $recurse
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function setDefaultPermissions($path, $recurse = false)
|
||||
public function setDefaultPermissions($path, $recurse = false)
|
||||
{
|
||||
if (!file_exists($path)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$permission = $this->getDefaultPermissions();
|
||||
$permission = $this->getDefaultPermissions();
|
||||
|
||||
$result = $this->chmod($path, array($permission['file'], $permission['dir']), $recurse);
|
||||
$result = $this->chmod($path, array($permission['file'], $permission['dir']), $recurse);
|
||||
if (!empty($permission['user'])) {
|
||||
$result &= $this->chown($path, $permission['user'], $recurse);
|
||||
$result &= $this->chown($path, $permission['user'], $recurse);
|
||||
}
|
||||
if (!empty($permission['group'])) {
|
||||
$result &= $this->chgrp($path, $permission['group'], $recurse);
|
||||
$result &= $this->chgrp($path, $permission['group'], $recurse);
|
||||
}
|
||||
|
||||
return $result;
|
||||
return $result;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get current permissions
|
||||
* Get current permissions
|
||||
*
|
||||
* @param string $filename
|
||||
* @return string | bool
|
||||
@@ -108,7 +158,7 @@ class Permission
|
||||
}
|
||||
|
||||
/**
|
||||
* Change permissions
|
||||
* Change permissions
|
||||
*
|
||||
* @param string $filename
|
||||
* @param int | array $octal - ex. 0755, array(0644, 0755), array('file'=>0644, 'dir'=>0755)
|
||||
@@ -118,7 +168,7 @@ class Permission
|
||||
*/
|
||||
public function chmod($path, $octal, $recurse = false)
|
||||
{
|
||||
if (!file_exists($path)) {
|
||||
if (!file_exists($path)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -130,17 +180,17 @@ class Permission
|
||||
foreach ($octal as $key => $val) {
|
||||
$pKey= strval($key);
|
||||
if (!in_array($pKey, $rule)) {
|
||||
$pKey= $rule[$count];
|
||||
$pKey= $rule[$count];
|
||||
}
|
||||
|
||||
if (!empty($pKey)) {
|
||||
$permission[$pKey]= $val;
|
||||
$permission[$pKey]= $val;
|
||||
}
|
||||
$count++;
|
||||
$count++;
|
||||
}
|
||||
}
|
||||
elseif (is_int((int)$octal)) {
|
||||
$permission= array(
|
||||
$permission= array(
|
||||
'file' => $octal,
|
||||
'dir' => $octal,
|
||||
);
|
||||
@@ -152,25 +202,25 @@ class Permission
|
||||
//conver to octal value
|
||||
foreach($permission as $key => $val) {
|
||||
if (is_string($val)) {
|
||||
$permission[$key]= base_convert($val,8,10);
|
||||
$permission[$key]= base_convert($val,8,10);
|
||||
}
|
||||
}
|
||||
|
||||
//Set permission for non-recursive request
|
||||
if (!$recurse) {
|
||||
if (is_dir($path)) {
|
||||
return $this->chmodReal($path, $permission['dir']);
|
||||
return $this->chmodReal($path, $permission['dir']);
|
||||
}
|
||||
return $this->chmodReal($path, $permission['file']);
|
||||
return $this->chmodReal($path, $permission['file']);
|
||||
}
|
||||
|
||||
//Recursive permission
|
||||
return $this->chmodRecurse($path, $permission['file'], $permission['dir']);
|
||||
return $this->chmodRecurse($path, $permission['file'], $permission['dir']);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Change permissions recursive
|
||||
/**
|
||||
* Change permissions recursive
|
||||
*
|
||||
* @param string $filename
|
||||
* @param int $fileOctal - ex. 0644
|
||||
@@ -189,8 +239,7 @@ class Permission
|
||||
}
|
||||
|
||||
if (is_dir($path)) {
|
||||
$allFiles = scandir($path);
|
||||
$items = array_slice($allFiles, 2);
|
||||
$allFiles = $this->getFileManager()->getFileList($path);
|
||||
|
||||
foreach ($items as $item) {
|
||||
$this->chmodRecurse($path. Utils\Util::getSeparator() .$item, $fileOctal, $dirOctal);
|
||||
@@ -203,11 +252,11 @@ class Permission
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Change owner permission
|
||||
* Change owner permission
|
||||
*
|
||||
* @param string $path
|
||||
* @param int | string $user
|
||||
@@ -217,7 +266,7 @@ class Permission
|
||||
*/
|
||||
public function chown($path, $user='', $recurse=false)
|
||||
{
|
||||
if (!file_exists($path)) {
|
||||
if (!file_exists($path)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -227,15 +276,15 @@ class Permission
|
||||
|
||||
//Set chown for non-recursive request
|
||||
if (!$recurse) {
|
||||
return $this->chownReal($path, $user);
|
||||
return $this->chownReal($path, $user);
|
||||
}
|
||||
|
||||
//Recursive chown
|
||||
return $this->chownRecurse($path, $user);
|
||||
return $this->chownRecurse($path, $user);
|
||||
}
|
||||
|
||||
/**
|
||||
* Change owner permission recursive
|
||||
* Change owner permission recursive
|
||||
*
|
||||
* @param string $path
|
||||
* @param string $user
|
||||
@@ -248,8 +297,7 @@ class Permission
|
||||
return false;
|
||||
}
|
||||
|
||||
$allFiles = scandir($path);
|
||||
$items = array_slice($allFiles, 2);
|
||||
$allFiles = $this->getFileManager()->getFileList($path);
|
||||
|
||||
foreach ($items as $item) {
|
||||
$this->chownRecurse($path. Utils\Util::getSeparator() .$item, $user);
|
||||
@@ -259,7 +307,7 @@ class Permission
|
||||
}
|
||||
|
||||
/**
|
||||
* Change group permission
|
||||
* Change group permission
|
||||
*
|
||||
* @param string $path
|
||||
* @param int | string $group
|
||||
@@ -269,7 +317,7 @@ class Permission
|
||||
*/
|
||||
public function chgrp($path, $group = null, $recurse = false)
|
||||
{
|
||||
if (!file_exists($path)) {
|
||||
if (!file_exists($path)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -279,15 +327,15 @@ class Permission
|
||||
|
||||
//Set chgrp for non-recursive request
|
||||
if (!$recurse) {
|
||||
return $this->chgrpReal($path, $group);
|
||||
return $this->chgrpReal($path, $group);
|
||||
}
|
||||
|
||||
//Recursive chown
|
||||
return $this->chgrpRecurse($path, $group);
|
||||
return $this->chgrpRecurse($path, $group);
|
||||
}
|
||||
|
||||
/**
|
||||
* Change group permission recursive
|
||||
* Change group permission recursive
|
||||
*
|
||||
* @param string $filename
|
||||
* @param int $fileOctal - ex. 0644
|
||||
@@ -301,8 +349,7 @@ class Permission
|
||||
return false;
|
||||
}
|
||||
|
||||
$allFiles = scandir($path);
|
||||
$items = array_slice($allFiles, 2);
|
||||
$allFiles = $this->getFileManager()->getFileList($path);
|
||||
|
||||
foreach ($items as $item) {
|
||||
$this->chgrpRecurse($path. Utils\Util::getSeparator() .$item, $group);
|
||||
@@ -313,7 +360,7 @@ class Permission
|
||||
|
||||
|
||||
/**
|
||||
* Change permissions recursive
|
||||
* Change permissions recursive
|
||||
*
|
||||
* @param string $filename
|
||||
* @param int $mode - ex. 0644
|
||||
@@ -323,7 +370,7 @@ class Permission
|
||||
protected function chmodReal($filename, $mode)
|
||||
{
|
||||
try {
|
||||
$result = chmod($filename, $mode);
|
||||
$result = chmod($filename, $mode);
|
||||
} catch (\Exception $e) {
|
||||
$result = false;
|
||||
}
|
||||
@@ -333,39 +380,39 @@ class Permission
|
||||
$this->chgrp($filename, $this->getDefaultGroup(true));
|
||||
|
||||
try {
|
||||
$result = chmod($filename, $mode);
|
||||
$result = chmod($filename, $mode);
|
||||
} catch (\Exception $e) {
|
||||
throw new Error($e->getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $result;
|
||||
return $result;
|
||||
}
|
||||
|
||||
protected function chownReal($path, $user)
|
||||
{
|
||||
try {
|
||||
$result = chown($path, $user);
|
||||
$result = chown($path, $user);
|
||||
} catch (\Exception $e) {
|
||||
throw new Error($e->getMessage());
|
||||
throw new Error($e->getMessage());
|
||||
}
|
||||
|
||||
return $result;
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
protected function chgrpReal($path, $group)
|
||||
{
|
||||
try {
|
||||
$result = chgrp($path, $group);
|
||||
$result = chgrp($path, $group);
|
||||
} catch (\Exception $e) {
|
||||
throw new Error($e->getMessage());
|
||||
throw new Error($e->getMessage());
|
||||
}
|
||||
|
||||
return $result;
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get default owner user
|
||||
* Get default owner user
|
||||
*
|
||||
* @return int - owner id
|
||||
*/
|
||||
@@ -374,19 +421,19 @@ class Permission
|
||||
$defaultPermissions = $this->getDefaultPermissions();
|
||||
|
||||
$owner = $defaultPermissions['user'];
|
||||
if (empty($owner) && $usePosix) {
|
||||
$owner = posix_getuid();
|
||||
}
|
||||
if (empty($owner) && $usePosix) {
|
||||
$owner = posix_getuid();
|
||||
}
|
||||
|
||||
if (empty($owner)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return $owner;
|
||||
return $owner;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get default group user
|
||||
* Get default group user
|
||||
*
|
||||
* @return int - group id
|
||||
*/
|
||||
@@ -395,15 +442,91 @@ class Permission
|
||||
$defaultPermissions = $this->getDefaultPermissions();
|
||||
|
||||
$group = $defaultPermissions['group'];
|
||||
if (empty($group) && $usePosix) {
|
||||
$group = posix_getegid();
|
||||
}
|
||||
if (empty($group) && $usePosix) {
|
||||
$group = posix_getegid();
|
||||
}
|
||||
|
||||
if (empty($group)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return $group;
|
||||
return $group;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set permission regarding defined in permissionMap
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function setMapPermission()
|
||||
{
|
||||
$this->permissionError = array();
|
||||
$this->permissionErrorRules = array();
|
||||
|
||||
$params = $this->getParams();
|
||||
|
||||
$result = true;
|
||||
foreach ($params['permissionMap'] as $type => $items) {
|
||||
|
||||
$permission = $this->permissionRules[$type];
|
||||
|
||||
foreach ($items as $item) {
|
||||
|
||||
if (file_exists($item)) {
|
||||
|
||||
try {
|
||||
$res = $this->chmod($item, $permission, true);
|
||||
} catch (\Exception $e) {
|
||||
$res = false;
|
||||
}
|
||||
|
||||
/** 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get last permission error
|
||||
*
|
||||
* @return array | string
|
||||
*/
|
||||
public function getLastError()
|
||||
{
|
||||
return $this->permissionError;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get last permission error rules
|
||||
*
|
||||
* @return array | string
|
||||
*/
|
||||
public function getLastErrorRules()
|
||||
{
|
||||
return $this->permissionErrorRules;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -28,6 +28,28 @@ return array (
|
||||
'user' => '',
|
||||
'group' => '',
|
||||
),
|
||||
|
||||
'permissionMap' => array(
|
||||
|
||||
/** 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',
|
||||
),
|
||||
),
|
||||
'cron' => array(
|
||||
'maxJobNumber' => 15, /** Max number of jobs per one execution */
|
||||
'jobPeriod' => 7800, /** Period for jobs, ex. if cron executed at 15:35, it will execute all pending jobs for times from 14:05 to 15:35 */
|
||||
@@ -58,6 +80,8 @@ return array (
|
||||
'isInstalled',
|
||||
'defaultPermissions',
|
||||
'systemUser',
|
||||
'permissionMap',
|
||||
'permissionRules',
|
||||
),
|
||||
'adminItems' =>
|
||||
array (
|
||||
|
||||
+20
-35
@@ -31,11 +31,9 @@ class Installer
|
||||
|
||||
protected $isAuth = false;
|
||||
|
||||
protected $writableList = array(
|
||||
'data',
|
||||
);
|
||||
protected $permissionMap;
|
||||
|
||||
protected $writableListError;
|
||||
protected $permissionError;
|
||||
|
||||
/**
|
||||
* Ajax Urls, pairs: url:directory (if bad permission)
|
||||
@@ -44,7 +42,6 @@ class Installer
|
||||
*/
|
||||
protected $ajaxUrls = array(
|
||||
'api/v1/Settings' => 'api',
|
||||
'api/v1' => 'api',
|
||||
'client/res/templates/login.tpl' => 'client/res/templates',
|
||||
);
|
||||
|
||||
@@ -74,7 +71,8 @@ class Installer
|
||||
$this->systemHelper = new SystemHelper();
|
||||
|
||||
$configPath = $this->getConfig()->getConfigPath();
|
||||
$this->writableList[] = $configPath;
|
||||
$this->permissionMap = $this->getConfig()->get('permissionMap');
|
||||
$this->permissionMap['writable'][] = $configPath;
|
||||
|
||||
if (!file_exists($configPath)) {
|
||||
$configData = $this->getConfig()->getDefaults();
|
||||
@@ -102,6 +100,11 @@ class Installer
|
||||
return $this->systemHelper;
|
||||
}
|
||||
|
||||
protected function getFileManager()
|
||||
{
|
||||
return $this->app->getContainer()->get('fileManager');
|
||||
}
|
||||
|
||||
|
||||
protected function auth()
|
||||
{
|
||||
@@ -120,12 +123,6 @@ class Installer
|
||||
return $this->app->isInstalled();
|
||||
}
|
||||
|
||||
|
||||
public function getLastWritableError()
|
||||
{
|
||||
return $this->writableListError;
|
||||
}
|
||||
|
||||
protected function getLanguage()
|
||||
{
|
||||
if (!isset($this->language)) {
|
||||
@@ -175,6 +172,10 @@ class Installer
|
||||
$data = array_merge($data, $initData);
|
||||
$result = $this->saveConfig($data);
|
||||
|
||||
/*if ($result) {
|
||||
$this->app = new \Espo\Core\Application();
|
||||
}*/
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
@@ -316,30 +317,14 @@ class Installer
|
||||
return false;
|
||||
}
|
||||
|
||||
public function isWritable()
|
||||
public function checkPermission()
|
||||
{
|
||||
$this->writableListError = array();
|
||||
return $this->getFileManager()->getPermissionUtils()->setMapPermission();
|
||||
}
|
||||
|
||||
$fileManager = $this->app->getContainer()->get('fileManager');
|
||||
|
||||
$result = true;
|
||||
foreach ($this->writableList as $item) {
|
||||
|
||||
if (!file_exists($item)) {
|
||||
$item = $fileManager->getDirName($item);
|
||||
}
|
||||
|
||||
if (file_exists($item) && !is_writable($item)) {
|
||||
|
||||
$fileManager->getPermissionUtils()->setDefaultPermissions($item);
|
||||
if (!is_writable($item)) {
|
||||
$result = false;
|
||||
$this->writableListError[] = $item;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $result;
|
||||
public function getLastPermissionError()
|
||||
{
|
||||
return $this->getFileManager()->getPermissionUtils()->getLastErrorRules();
|
||||
}
|
||||
|
||||
public function getAjaxUrls()
|
||||
@@ -350,7 +335,7 @@ class Installer
|
||||
public function fixAjaxPermission($url = null)
|
||||
{
|
||||
$permission = array(0644, 0755);
|
||||
$fileManager = $this->app->getContainer()->get('fileManager');
|
||||
$fileManager = $this->getFileManager();
|
||||
|
||||
$result = false;
|
||||
if (!isset($url)) {
|
||||
|
||||
@@ -37,6 +37,8 @@ class SystemHelper extends \Espo\Core\Utils\System
|
||||
|
||||
protected $writableDir = 'data';
|
||||
|
||||
protected $combineOperator = '&&';
|
||||
|
||||
|
||||
public function initWritable()
|
||||
{
|
||||
@@ -127,35 +129,52 @@ class SystemHelper extends \Espo\Core\Utils\System
|
||||
return $this->modRewriteUrl;
|
||||
}
|
||||
|
||||
public function getChmodCommand($path, $permissions = array('755'), $isSudo = false, $isFile = null)
|
||||
public function getChmodCommand($path, $permissions = array('755'), $isSudo = false, $isFile = null, $isCd = true)
|
||||
{
|
||||
$path = $this->getFullPath($path);
|
||||
//$path = $this->getFullPath($path);
|
||||
|
||||
$path = empty($path) ? '*' : $path;
|
||||
if (is_array($path)) {
|
||||
$path = implode(' ', $path);
|
||||
}
|
||||
|
||||
$sudoStr = $isSudo ? 'sudo ' : '';
|
||||
|
||||
$cd = $isCd ? $this->getCd(true) : '';
|
||||
|
||||
if (is_string($permissions)) {
|
||||
$permissions = (array) $permissions;
|
||||
}
|
||||
|
||||
if (!isset($isFile) && count($permissions) == 1) {
|
||||
return $sudoStr.'chmod -R '.$permissions[0].' '.$path;
|
||||
return $cd.$sudoStr.'chmod -R '.$permissions[0].' '.$path;
|
||||
}
|
||||
|
||||
$bufPerm = (count($permissions) == 1) ? array_fill(0, 2, $permissions[0]) : $permissions;
|
||||
|
||||
$commands = array();
|
||||
|
||||
if ($isCd) {
|
||||
$commands[] = $this->getCd();
|
||||
}
|
||||
|
||||
$commands[] = $sudoStr.'chmod '.$bufPerm[0].' $(find '.$path.' -type f)';
|
||||
$commands[] = $sudoStr.'chmod '.$bufPerm[1].' $(find '.$path.' -type d)';
|
||||
|
||||
if (count($permissions) >= 2) {
|
||||
return implode('; ', $commands);
|
||||
return implode(' ' . $this->combineOperator . ' ', $commands);
|
||||
}
|
||||
|
||||
return $isFile ? $commands[0] : $commands[1];
|
||||
}
|
||||
|
||||
public function getChownCommand($path, $isSudo = false)
|
||||
public function getChownCommand($path, $isSudo = false, $isCd = true)
|
||||
{
|
||||
$path = empty($path) ? '*' : $path;
|
||||
if (is_array($path)) {
|
||||
$path = implode(' ', $path);
|
||||
}
|
||||
|
||||
$owner = posix_getuid();
|
||||
$group = posix_getegid();
|
||||
|
||||
@@ -165,11 +184,25 @@ class SystemHelper extends \Espo\Core\Utils\System
|
||||
return null;
|
||||
}
|
||||
|
||||
return $sudoStr.'chown -R '.$owner.':'.$group.' '.$this->getFullPath($path);
|
||||
$cd = '';
|
||||
if ($isCd) {
|
||||
$cd = $this->getCd(true);
|
||||
}
|
||||
|
||||
//$path = $this->getFullPath($path;
|
||||
return $cd.$sudoStr.'chown -R '.$owner.':'.$group.' '.$path;
|
||||
}
|
||||
|
||||
public function getFullPath($path)
|
||||
{
|
||||
if (is_array($path)) {
|
||||
$pathList = array();
|
||||
foreach ($path as $pathItem) {
|
||||
$pathList[] = $this->getFullPath($pathItem);
|
||||
}
|
||||
return $pathList;
|
||||
}
|
||||
|
||||
if (!empty($path)) {
|
||||
$path = DIRECTORY_SEPARATOR . $path;
|
||||
}
|
||||
@@ -196,12 +229,23 @@ class SystemHelper extends \Espo\Core\Utils\System
|
||||
$commands = array();
|
||||
$commands[] = $this->getChmodCommand($chmodPath, $permissions, $isSudo, $isFile);
|
||||
|
||||
$chown = $this->getChownCommand($chownPath, $isSudo);
|
||||
$chown = $this->getChownCommand($chownPath, $isSudo, false);
|
||||
if (isset($chown)) {
|
||||
$commands[] = $chown;
|
||||
}
|
||||
|
||||
return implode('; ', $commands);
|
||||
return implode(' ' . $this->combineOperator . ' ', $commands);
|
||||
}
|
||||
|
||||
protected function getCd($isCombineOperator = false)
|
||||
{
|
||||
$cd = 'cd '.$this->getRootDir();
|
||||
|
||||
if ($isCombineOperator) {
|
||||
$cd .= ' '.$this->combineOperator.' ';
|
||||
}
|
||||
|
||||
return $cd;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -23,15 +23,24 @@
|
||||
ob_start();
|
||||
$result = array('success' => true, 'errorMsg' => '');
|
||||
|
||||
if (!$installer->isWritable()) {
|
||||
if (!$installer->checkPermission()) {
|
||||
$result['success'] = false;
|
||||
$urls = $installer->getLastWritableError();
|
||||
foreach ($urls as &$url) {
|
||||
$url = ' '.$url;
|
||||
}
|
||||
$result['errorMsg'] = $langs['messages']['Permission denied to files'].':<br>'.implode('<br>', $urls);
|
||||
$result['errorFixInstruction'] = $systemHelper->getPermissionCommands('', array('644', '755'));
|
||||
$error = $installer->getLastPermissionError();
|
||||
$urls = array_keys($error);
|
||||
$group = array();
|
||||
foreach($error as $folder => $permission) {
|
||||
$group[implode('-', $permission)][] = $folder;
|
||||
}
|
||||
$instruction = '';
|
||||
$instructionSU = '';
|
||||
foreach($group as $permission => $folders) {
|
||||
$instruction .= $systemHelper->getPermissionCommands(array($folders, ''), explode('-', $permission)) . ";<br>";
|
||||
$instructionSU .= " " . $systemHelper->getPermissionCommands(array($folders, ''), explode('-', $permission), true) . ";<br>";
|
||||
}
|
||||
$result['errorMsg'] = $langs['messages']['Permission denied to'] . ':<br><pre>/'.implode('<br>/', $urls).'</pre>';
|
||||
$result['errorFixInstruction'] = str_replace( '"{C}"' , $instruction, $langs['messages']['permissionInstruction']) . "<br>" .
|
||||
str_replace( '{CSU}' , $instructionSU, $langs['messages']['operationNotPermitted']);
|
||||
}
|
||||
|
||||
ob_clean();
|
||||
echo json_encode($result);
|
||||
echo json_encode($result);
|
||||
@@ -18,7 +18,7 @@
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with EspoCRM. If not, see http://www.gnu.org/licenses/.
|
||||
************************************************************************/
|
||||
************************************************************************/
|
||||
|
||||
$errors = array();
|
||||
if (!empty($_REQUEST['desc'])) {
|
||||
|
||||
@@ -33,10 +33,10 @@ if (!empty($res['errors'])) {
|
||||
if (!empty($_REQUEST['dbName']) && !empty($_REQUEST['hostName']) && !empty($_REQUEST['dbUserName'])) {
|
||||
$connect = false;
|
||||
|
||||
$dbName = $_REQUEST['dbName'];
|
||||
$hostName = $_REQUEST['hostName'];
|
||||
$dbUserName = $_REQUEST['dbUserName'];
|
||||
$dbUserPass = $_REQUEST['dbUserPass'];
|
||||
$dbName = trim($_REQUEST['dbName']);
|
||||
$hostName = trim($_REQUEST['hostName']);
|
||||
$dbUserName = trim($_REQUEST['dbUserName']);
|
||||
$dbUserPass = trim($_REQUEST['dbUserPass']);
|
||||
$dbDriver = (!empty($_REQUEST['dbDriver']))? $_REQUEST['dbDriver'] : 'pdo_mysql';
|
||||
|
||||
$res = $systemHelper->checkDbConnection($hostName, $dbUserName, $dbUserPass, $dbName, $dbDriver);
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with EspoCRM. If not, see http://www.gnu.org/licenses/.
|
||||
************************************************************************/
|
||||
************************************************************************/
|
||||
|
||||
$fields = array(
|
||||
'db-name' => array(),
|
||||
|
||||
@@ -75,7 +75,8 @@
|
||||
"Cannot create user": "Cannot create user",
|
||||
"Permission denied": "Permission denied",
|
||||
"permissionInstruction": "<br>Run this in Terminal<pre><b>\"{C}\"<\/b><\/pre>",
|
||||
"Permission denied to files": "Permission denied to file(s)",
|
||||
"operationNotPermitted" : "Operation not permitted? Try this: <br>{CSU}",
|
||||
"Permission denied to": "Permission denied",
|
||||
"Can not save settings": "Can not save settings",
|
||||
"Cannot save preferences": "Cannot save preferences",
|
||||
"Thousand Separator and Decimal Mark equal": "Thousand Separator and Decimal Mark cannot be equal",
|
||||
@@ -104,4 +105,4 @@
|
||||
"default": "API Error: EspoCRM API unavailable.<br> Possible problem: disabled Rewrite Module. Please check and enable Rewrite Module in your server (e.g. mod_rewrite in Apache) and .htaccess support."
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,2 @@
|
||||
<p class="credit small">© 2014 <a href="http://www.espocrm.com">EspoCRM</a></p>
|
||||
|
||||
@@ -15,12 +15,17 @@
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="col-md-offset-1 col-md-10">
|
||||
<div class="panel panel-default">
|
||||
{include file="header.tpl"}
|
||||
{include file="$tplName"}
|
||||
<body class='install-body'>
|
||||
<header id="header"></header>
|
||||
<div class="container content">
|
||||
<div class="col-md-offset-1 col-md-10">
|
||||
<div class="panel panel-default">
|
||||
{include file="header.tpl"}
|
||||
{include file="$tplName"}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<footer class="container">{include file="footer.tpl"}</footer>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
<div class="panel-body">
|
||||
<div id="msg-box" class="alert hide"></div>
|
||||
<div class="row">
|
||||
<div class=" col-md-13">
|
||||
<div class=" col-md-12">
|
||||
<div align="center">
|
||||
<div class="content-img">
|
||||
<img class="devices" src="img/devices.png" alt="EspoCRM">
|
||||
|
||||
@@ -35,4 +35,4 @@
|
||||
var installScript = new InstallScript({action: 'step1', langs: langs});
|
||||
})
|
||||
{/literal}
|
||||
</script>
|
||||
</script>
|
||||
|
||||
@@ -15,7 +15,9 @@ select[name="user-lang"] {
|
||||
text-align: left ;
|
||||
}
|
||||
|
||||
|
||||
.install-body {
|
||||
padding-top: 30px;
|
||||
}
|
||||
.btn-panel {
|
||||
margin-top: 20px;
|
||||
}
|
||||
|
||||
+1
-1
@@ -77,7 +77,7 @@ $ignore = array('desc', 'dbName', 'hostName', 'dbUserName', 'dbUserPass', 'dbDri
|
||||
if (!empty($_REQUEST)) {
|
||||
foreach ($_REQUEST as $key => $val) {
|
||||
if (!in_array($val, $ignore))
|
||||
$_SESSION['install'][$key] = $val;
|
||||
$_SESSION['install'][$key] = trim($val);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+16
-102
@@ -42,7 +42,7 @@ var InstallScript = function(opt) {
|
||||
if (typeof(opt.serverType) !== 'undefined') {
|
||||
this.serverType = opt.serverType;
|
||||
}
|
||||
|
||||
|
||||
if (typeof(opt.OS) !== 'undefined') {
|
||||
this.OS = opt.OS;
|
||||
}
|
||||
@@ -57,7 +57,7 @@ var InstallScript = function(opt) {
|
||||
'break': true,
|
||||
},
|
||||
{
|
||||
'action': 'checkWritable',
|
||||
'action': 'checkPermission',
|
||||
'break': true,
|
||||
},
|
||||
{
|
||||
@@ -72,10 +72,7 @@ var InstallScript = function(opt) {
|
||||
'action': 'createUser',
|
||||
'break': true,
|
||||
},
|
||||
{
|
||||
'action': 'checkAjaxPermission',
|
||||
'break': true,
|
||||
}
|
||||
|
||||
];
|
||||
this.checkIndex = 0;
|
||||
this.checkError = false;
|
||||
@@ -267,7 +264,7 @@ InstallScript.prototype.step5 = function() {
|
||||
})
|
||||
|
||||
})
|
||||
|
||||
|
||||
$('.field-smtpAuth').find('input[type="checkbox"]').change( function(e){
|
||||
if ($(this).is(':checked')) {
|
||||
$('.cell-smtpPassword').removeClass('hide');
|
||||
@@ -282,7 +279,7 @@ InstallScript.prototype.step5 = function() {
|
||||
});
|
||||
$('[name="smtpSecurity"]').change( function(e){
|
||||
if ($(this).val() == '') {
|
||||
$('[name="smtpPort"]').val('25');
|
||||
$('[name="smtpPort"]').val('25');
|
||||
}
|
||||
else {
|
||||
$('[name="smtpPort"]').val('465');
|
||||
@@ -416,7 +413,7 @@ InstallScript.prototype.checkSett = function(opt) {
|
||||
|
||||
InstallScript.prototype.validate = function() {
|
||||
this.hideMsg();
|
||||
|
||||
|
||||
var valid = true;
|
||||
var elem = null;
|
||||
var fieldRequired = [];
|
||||
@@ -450,14 +447,14 @@ InstallScript.prototype.validate = function() {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// decimal and group sep
|
||||
$('[name="thousandSeparator"]').parent().parent().removeClass('has-error');
|
||||
if (typeof(this.systemSettings.thousandSeparator) !== 'undefined'
|
||||
&& typeof(this.systemSettings.decimalMark) !== 'undefined'
|
||||
if (typeof(this.systemSettings.thousandSeparator) !== 'undefined'
|
||||
&& typeof(this.systemSettings.decimalMark) !== 'undefined'
|
||||
&& this.systemSettings.thousandSeparator == this.systemSettings.decimalMark
|
||||
&& valid) {
|
||||
|
||||
|
||||
$('[name="thousandSeparator"]').parent().parent().addClass('has-error');
|
||||
$('[name="decimalMark"]').parent().parent().addClass('has-error');
|
||||
msg = this.getLang('Thousand Separator and Decimal Mark equal', 'messages');
|
||||
@@ -552,15 +549,11 @@ InstallScript.prototype.checkAction = function(dataMain) {
|
||||
var currIndex = this.checkIndex;
|
||||
var checkAction = this.checkActions[currIndex].action;
|
||||
this.checkIndex++;
|
||||
|
||||
|
||||
if (checkAction == 'checkModRewrite') {
|
||||
this.checkModRewrite();
|
||||
return;
|
||||
}
|
||||
if (checkAction == 'checkAjaxPermission') {
|
||||
this.checkAjaxPermission();
|
||||
return;
|
||||
}
|
||||
if (checkAction == 'applySett') {
|
||||
data['user-name'] = this.userSett.name;
|
||||
data['user-pass'] = this.userSett.pass;
|
||||
@@ -604,25 +597,11 @@ InstallScript.prototype.checkAction = function(dataMain) {
|
||||
})
|
||||
}
|
||||
|
||||
InstallScript.prototype.checkAjaxPermission = function() {
|
||||
var self = this;
|
||||
|
||||
this.ajaxUrlFinished = 0;
|
||||
this.ajaxUrlPermRes = true;
|
||||
this.ajaxUrlPermMsgs = [];
|
||||
this.ajaxUrlPermInstructions = [];
|
||||
|
||||
var len = this.ajaxUrls.length;
|
||||
for (var count = 0; count < len; count++) {
|
||||
var url = this.ajaxUrls[count];
|
||||
this.checkAjaxPermUrl(url);
|
||||
}
|
||||
}
|
||||
|
||||
InstallScript.prototype.checkModRewrite = function() {
|
||||
var self = this;
|
||||
this.modRewriteUrl;
|
||||
|
||||
|
||||
var urlAjax = '..'+this.modRewriteUrl;;
|
||||
var realJqXHR = $.ajax({
|
||||
url: urlAjax,
|
||||
@@ -635,83 +614,17 @@ InstallScript.prototype.checkModRewrite = function() {
|
||||
if (status == '200' || status == '401') {
|
||||
var data = {'success': 1};
|
||||
}
|
||||
|
||||
|
||||
self.callbackModRewrite(data);
|
||||
|
||||
|
||||
})
|
||||
}
|
||||
|
||||
InstallScript.prototype.checkAjaxPermUrl = function(url) {
|
||||
var self = this;
|
||||
|
||||
var urlAjax = '../'+url;
|
||||
var realJqXHR = $.ajax({
|
||||
url: urlAjax,
|
||||
type: "GET",
|
||||
})
|
||||
.always(function(data, textStatus, jqXHR){
|
||||
var status = jqXHR.status || realJqXHR.status || 404;
|
||||
status += '';
|
||||
if (status == '200' || status == '401') {
|
||||
var data = {'success': 1};
|
||||
self.callbackAjaxPerm(data);
|
||||
}
|
||||
else {
|
||||
var data = {};
|
||||
data.action = 'fixAjaxPermission';
|
||||
data.url = url;
|
||||
$.ajax({
|
||||
url: "index.php",
|
||||
type: "POST",
|
||||
data: data,
|
||||
dataType: 'json',
|
||||
})
|
||||
.done(function(ajaxData){
|
||||
self.callbackAjaxPerm(ajaxData);
|
||||
})
|
||||
.fail(function(){
|
||||
|
||||
var ajaxData = {
|
||||
'success': false,
|
||||
'errorMsg': ['Ajax failed']+': '+url,
|
||||
}
|
||||
self.callbackAjaxPerm(ajaxData);
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
InstallScript.prototype.callbackAjaxPerm = function(data) {
|
||||
this.ajaxUrlFinished++;
|
||||
if (typeof(data.success) != 'undefined' && !data.success) {
|
||||
this.ajaxUrlPermRes = false;
|
||||
this.ajaxUrlPermMsgs.push(data.errorMsg);
|
||||
if (typeof(data.errorFixInstruction) != 'undefined') {
|
||||
this.ajaxUrlPermInstructions.push(data.errorFixInstruction);
|
||||
}
|
||||
}
|
||||
|
||||
if (this.ajaxUrlFinished == this.ajaxUrls.length) {
|
||||
// all urls was checked
|
||||
var ajaxData = {
|
||||
'success': this.ajaxUrlPermRes
|
||||
}
|
||||
if (!this.ajaxUrlPermRes) {
|
||||
var errorMsg = this.getLang('Permission denied', 'messages') + ' ( ' + this.ajaxUrlPermMsgs.join(', ') + ' ) .';
|
||||
if (this.ajaxUrlPermInstructions.length > 0) {
|
||||
errorMsg += '<br>' + this.getLang('permissionInstruction', 'messages').replace('"{C}"', this.ajaxUrlPermInstructions.join('<br>'));
|
||||
}
|
||||
ajaxData.errorMsg = errorMsg;
|
||||
}
|
||||
this.checkAction(ajaxData);
|
||||
}
|
||||
}
|
||||
|
||||
InstallScript.prototype.callbackModRewrite = function(data) {
|
||||
var ajaxData = {
|
||||
'success': true,
|
||||
}
|
||||
|
||||
|
||||
if (typeof(data.success) != 'undefined' && data.success) {
|
||||
this.checkAction(ajaxData);
|
||||
return;
|
||||
@@ -741,6 +654,7 @@ InstallScript.prototype.callbackChecking = function(data) {
|
||||
}
|
||||
else {
|
||||
var desc = (typeof(data.errorMsg))? data.errorMsg : '';
|
||||
desc += (typeof(data.errorFixInstruction) != 'undefined')? data.errorFixInstruction : '';
|
||||
if (this.reChecking) {
|
||||
this.showMsg({msg: desc, error: true});
|
||||
$("#re-check").removeAttr('disabled');
|
||||
|
||||
@@ -17,16 +17,9 @@ class ManagerTest extends \PHPUnit_Framework_TestCase
|
||||
|
||||
protected function setUp()
|
||||
{
|
||||
$this->object = new \Espo\Core\Utils\File\Manager(
|
||||
array(
|
||||
'defaultPermissions' => array (
|
||||
'dir' => '0775',
|
||||
'file' => '0664',
|
||||
'user' => '',
|
||||
'group' => '',
|
||||
),
|
||||
)
|
||||
);
|
||||
$this->objects['config'] = $this->getMockBuilder('\Espo\Core\Utils\Config')->disableOriginalConstructor()->getMock();
|
||||
|
||||
$this->object = new \Espo\Core\Utils\File\Manager();
|
||||
|
||||
$this->reflection = new ReflectionHelper($this->object);
|
||||
}
|
||||
|
||||
@@ -102,7 +102,7 @@ return array (
|
||||
8 => 'Prospect',
|
||||
),
|
||||
'isInstalled' => true,
|
||||
'cacheTimestamp' => 1401876283,
|
||||
'cacheTimestamp' => 1401978369,
|
||||
'testOption' => 'Another Wrong Value',
|
||||
'testOption2' => 'Test2',
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user