From fa6f471be90feff31373b2e3f45dc3ddd1c15768 Mon Sep 17 00:00:00 2001 From: Taras Machyshyn Date: Thu, 5 Jun 2014 17:28:45 +0300 Subject: [PATCH] improved check permission in installation --- application/Espo/Core/Container.php | 4 +- application/Espo/Core/Utils/File/Manager.php | 21 +- .../Espo/Core/Utils/File/Permission.php | 261 +++++++++++++----- .../Espo/Core/defaults/systemConfig.php | 24 ++ install/core/Installer.php | 55 ++-- install/core/SystemHelper.php | 60 +++- ...{checkWritable.php => checkPermission.php} | 25 +- install/core/actions/errors.php | 2 +- install/core/actions/settingsTest.php | 8 +- install/core/actions/step2.php | 2 +- install/core/i18n/en_US/install.json | 5 +- install/core/tpl/footer.tpl | 2 + install/core/tpl/index.tpl | 15 +- install/core/tpl/main.tpl | 2 +- install/core/tpl/step1.tpl | 2 +- install/css/install.css | 4 +- install/index.php | 2 +- install/js/install.js | 118 ++------ tests/Espo/Core/Utils/File/ManagerTest.php | 13 +- tests/testData/Utils/Config/config.php | 2 +- 20 files changed, 369 insertions(+), 258 deletions(-) rename install/core/actions/{checkWritable.php => checkPermission.php} (53%) create mode 100644 install/core/tpl/footer.tpl diff --git a/application/Espo/Core/Container.php b/application/Espo/Core/Container.php index 9fe1d7499d..3fadccfbdd 100644 --- a/application/Espo/Core/Container.php +++ b/application/Espo/Core/Container.php @@ -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') ); } diff --git a/application/Espo/Core/Utils/File/Manager.php b/application/Espo/Core/Utils/File/Manager.php index 8fa325a152..7581bad3c9 100644 --- a/application/Espo/Core/Utils/File/Manager.php +++ b/application/Espo/Core/Utils/File/Manager.php @@ -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; } /** diff --git a/application/Espo/Core/Utils/File/Permission.php b/application/Espo/Core/Utils/File/Permission.php index ab9ad1ac58..ef641f8aaf 100644 --- a/application/Espo/Core/Utils/File/Permission.php +++ b/application/Espo/Core/Utils/File/Permission.php @@ -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; } diff --git a/application/Espo/Core/defaults/systemConfig.php b/application/Espo/Core/defaults/systemConfig.php index ba67044450..d9cd1db214 100644 --- a/application/Espo/Core/defaults/systemConfig.php +++ b/application/Espo/Core/defaults/systemConfig.php @@ -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 ( diff --git a/install/core/Installer.php b/install/core/Installer.php index 6346bfcdf8..d5e3ff027a 100644 --- a/install/core/Installer.php +++ b/install/core/Installer.php @@ -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)) { diff --git a/install/core/SystemHelper.php b/install/core/SystemHelper.php index 8cad89d9b9..128b551d1f 100644 --- a/install/core/SystemHelper.php +++ b/install/core/SystemHelper.php @@ -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; } } diff --git a/install/core/actions/checkWritable.php b/install/core/actions/checkPermission.php similarity index 53% rename from install/core/actions/checkWritable.php rename to install/core/actions/checkPermission.php index 8b0623da80..3c89e23d02 100644 --- a/install/core/actions/checkWritable.php +++ b/install/core/actions/checkPermission.php @@ -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'].':
'.implode('
', $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)) . ";
"; + $instructionSU .= "  " . $systemHelper->getPermissionCommands(array($folders, ''), explode('-', $permission), true) . ";
"; + } + $result['errorMsg'] = $langs['messages']['Permission denied to'] . ':
/'.implode('
/', $urls).'
'; + $result['errorFixInstruction'] = str_replace( '"{C}"' , $instruction, $langs['messages']['permissionInstruction']) . "
" . + str_replace( '{CSU}' , $instructionSU, $langs['messages']['operationNotPermitted']); } ob_clean(); -echo json_encode($result); \ No newline at end of file +echo json_encode($result); diff --git a/install/core/actions/errors.php b/install/core/actions/errors.php index d1b4f0c202..d6473a18f9 100644 --- a/install/core/actions/errors.php +++ b/install/core/actions/errors.php @@ -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'])) { diff --git a/install/core/actions/settingsTest.php b/install/core/actions/settingsTest.php index 4ca9682b33..860eae85c9 100644 --- a/install/core/actions/settingsTest.php +++ b/install/core/actions/settingsTest.php @@ -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); diff --git a/install/core/actions/step2.php b/install/core/actions/step2.php index a18100219a..5fed93852b 100644 --- a/install/core/actions/step2.php +++ b/install/core/actions/step2.php @@ -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(), diff --git a/install/core/i18n/en_US/install.json b/install/core/i18n/en_US/install.json index 3eb870e537..ef6e0e00f4 100644 --- a/install/core/i18n/en_US/install.json +++ b/install/core/i18n/en_US/install.json @@ -75,7 +75,8 @@ "Cannot create user": "Cannot create user", "Permission denied": "Permission denied", "permissionInstruction": "
Run this in Terminal
\"{C}\"<\/b><\/pre>",
-		"Permission denied to files": "Permission denied to file(s)",
+		"operationNotPermitted" : "Operation not permitted? Try this: 
{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.
Possible problem: disabled Rewrite Module. Please check and enable Rewrite Module in your server (e.g. mod_rewrite in Apache) and .htaccess support." } } -} \ No newline at end of file +} diff --git a/install/core/tpl/footer.tpl b/install/core/tpl/footer.tpl new file mode 100644 index 0000000000..e43b0e5262 --- /dev/null +++ b/install/core/tpl/footer.tpl @@ -0,0 +1,2 @@ +

© 2014 EspoCRM

+ diff --git a/install/core/tpl/index.tpl b/install/core/tpl/index.tpl index 84c7841113..7e671b05f2 100644 --- a/install/core/tpl/index.tpl +++ b/install/core/tpl/index.tpl @@ -15,12 +15,17 @@ } - -
-
- {include file="header.tpl"} - {include file="$tplName"} + + +
+
+
+ {include file="header.tpl"} + {include file="$tplName"} +
+
{include file="footer.tpl"}
+ diff --git a/install/core/tpl/main.tpl b/install/core/tpl/main.tpl index 031b479784..d455ffe7f6 100644 --- a/install/core/tpl/main.tpl +++ b/install/core/tpl/main.tpl @@ -5,7 +5,7 @@
-
+
EspoCRM diff --git a/install/core/tpl/step1.tpl b/install/core/tpl/step1.tpl index 03857430b6..f5727fce48 100644 --- a/install/core/tpl/step1.tpl +++ b/install/core/tpl/step1.tpl @@ -35,4 +35,4 @@ var installScript = new InstallScript({action: 'step1', langs: langs}); }) {/literal} - \ No newline at end of file + diff --git a/install/css/install.css b/install/css/install.css index ae081da528..195ba8ae86 100644 --- a/install/css/install.css +++ b/install/css/install.css @@ -15,7 +15,9 @@ select[name="user-lang"] { text-align: left ; } - +.install-body { + padding-top: 30px; +} .btn-panel { margin-top: 20px; } diff --git a/install/index.php b/install/index.php index abf8a8bab6..8ae8aa2eb8 100644 --- a/install/index.php +++ b/install/index.php @@ -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); } } diff --git a/install/js/install.js b/install/js/install.js index 1555462e34..d9055071fe 100644 --- a/install/js/install.js +++ b/install/js/install.js @@ -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 += '
' + this.getLang('permissionInstruction', 'messages').replace('"{C}"', this.ajaxUrlPermInstructions.join('
')); - } - 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'); diff --git a/tests/Espo/Core/Utils/File/ManagerTest.php b/tests/Espo/Core/Utils/File/ManagerTest.php index 0a7d5cab7b..4868c772e0 100644 --- a/tests/Espo/Core/Utils/File/ManagerTest.php +++ b/tests/Espo/Core/Utils/File/ManagerTest.php @@ -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); } diff --git a/tests/testData/Utils/Config/config.php b/tests/testData/Utils/Config/config.php index 7c1238f8f1..1cccd4af8a 100644 --- a/tests/testData/Utils/Config/config.php +++ b/tests/testData/Utils/Config/config.php @@ -102,7 +102,7 @@ return array ( 8 => 'Prospect', ), 'isInstalled' => true, - 'cacheTimestamp' => 1401876283, + 'cacheTimestamp' => 1401978369, 'testOption' => 'Another Wrong Value', 'testOption2' => 'Test2', );