N°3007 - Warn the user that installing a patch on a non conform install is not recommended

This commit is contained in:
Eric
2020-06-04 10:38:58 +02:00
parent 8064a20718
commit 9d8a7bf561
6 changed files with 99 additions and 12 deletions

View File

@@ -73,7 +73,8 @@ Dict::Add('EN US', 'English', 'English', array(
'iTopUpdate:UI:CanCoreUpdate:ErrorFileNotExist' => 'Checking files failed (File not exist %1$s)',
'iTopUpdate:UI:CanCoreUpdate:Failed' => 'Checking files failed',
'iTopUpdate:UI:CanCoreUpdate:Yes' => 'Application can be updated',
'iTopUpdate:UI:CanCoreUpdate:No' => 'Application cannot be updated: %1$s',
'iTopUpdate:UI:CanCoreUpdate:No' => 'Application cannot be updated: %1$s',
'iTopUpdate:UI:CanCoreUpdate:Warning' => 'Warning: application update can fail: %1$s',
// Setup Messages
'iTopUpdate:UI:SetupMessage:Ready' => 'Ready to start',

View File

@@ -74,6 +74,7 @@ Dict::Add('FR FR', 'French', 'Français', array(
'iTopUpdate:UI:CanCoreUpdate:Failed' => 'Échec de la vérification des fichiers',
'iTopUpdate:UI:CanCoreUpdate:Yes' => 'L\'application peut être mise à jour',
'iTopUpdate:UI:CanCoreUpdate:No' => 'L\'application ne peut pas être mise à jour : %1$s',
'iTopUpdate:UI:CanCoreUpdate:Warning' => 'Attention : la mise à jour de l\'application peut échouer : %1$s',
// Setup Messages
'iTopUpdate:UI:SetupMessage:Ready' => 'Prêt pour l\\installation',

View File

@@ -28,7 +28,8 @@ class AjaxController extends Controller
try
{
$bCanUpdateCore = FilesInformation::CanUpdateCore($sMessage);
$sCanUpdateCore = FilesInformation::CanUpdateCore($sMessage);
$bCanUpdateCore = ($sCanUpdateCore == 'Yes');
$aParams['bStatus'] = $bCanUpdateCore;
if ($bCanUpdateCore)
{
@@ -36,7 +37,7 @@ class AjaxController extends Controller
}
else
{
$aParams['sMessage'] = Dict::Format('iTopUpdate:UI:CanCoreUpdate:No', $sMessage);
$aParams['sMessage'] = Dict::Format("iTopUpdate:UI:CanCoreUpdate:{$sCanUpdateCore}", $sMessage);
}
} catch (FileNotExistException $e)
{

View File

@@ -21,33 +21,71 @@ class FilesInformation
*
* @param string $sMessage
*
* @return bool true if core update is possible
* @return string 'Yes', 'No', 'Warning'
* @throws \Combodo\iTop\FilesInformation\Service\FileNotExistException
* @throws \Exception
*/
public static function CanUpdateCore(&$sMessage)
{
self::Init();
// Check than iTop can write everywhere
if (!self::CanWriteRecursive('', $sMessage))
$aFilesInfo = FilesIntegrity::GetInstalledFiles(APPROOT.'manifest.xml');
if ($aFilesInfo === false)
{
$sMessage = Dict::Format('FilesInformation:Error:MissingFile', 'manifest.xml');
return 'No';
}
// generate files and folders list
$aInstalledFiles = array();
foreach (array_keys($aFilesInfo) as $sFile)
{
$sLocalDirPath = utils::LocalPath(APPROOT.dirname($sFile));
if ($sLocalDirPath !== false)
{
if (!isset($aInstalledFiles[$sLocalDirPath]))
{
$aInstalledFiles[$sLocalDirPath] = true;
}
$aInstalledFiles[$sFile] = true;
}
}
if (!self::CanWriteRecursive('', $sMessage, $aInstalledFiles))
{
return false;
return 'No';
}
return true;
try
{
FilesIntegrity::CheckInstallationIntegrity();
}
catch (FileIntegrityException $e)
{
$sMessage = $e->getMessage();
return 'Warning';
}
return 'Yes';
}
/**
* @param string $sRootPath
* @param string $sMessage
* @param array $aInstalledFiles
*
* @return bool
* @throws \Combodo\iTop\FilesInformation\Service\FileNotExistException
*/
private static function CanWriteRecursive($sRootPath = '', &$sMessage = null)
private static function CanWriteRecursive($sRootPath = '', &$sMessage = null, $aInstalledFiles = array())
{
$aDirStats = FilesInformationUtils::Scan($sRootPath, false);
foreach ($aDirStats as $sFileName => $aFileStats)
{
// For name normalization
$sLocalPath = utils::LocalPath(APPROOT.$sRootPath.DIRECTORY_SEPARATOR.$sFileName);
if (($sLocalPath === false) || !isset($aInstalledFiles[$sLocalPath]))
{
continue;
}
if (!self::CanWriteToFile($aFileStats))
{
$sMessage = Dict::Format('FilesInformation:Error:CantWriteToFile', $sRootPath.DIRECTORY_SEPARATOR.$sFileName);
@@ -55,7 +93,7 @@ class FilesInformation
}
if (($sFileName != '.') && ($aFileStats['type'] == 'dir'))
{
if (!self::CanWriteRecursive($sRootPath.DIRECTORY_SEPARATOR.$sFileName, $sMessage))
if (!self::CanWriteRecursive($sRootPath.DIRECTORY_SEPARATOR.$sFileName, $sMessage, $aInstalledFiles))
{
return false;
}

View File

@@ -25,7 +25,7 @@ class FilesIntegrity
* @return array|false list of file info (path, size, md5)
* @throws \Exception
*/
private static function GetInstalledFiles($sManifest)
public static function GetInstalledFiles($sManifest)
{
$aFiles = array();
@@ -54,14 +54,19 @@ class FilesIntegrity
if ($oFileNode->hasChildNodes())
{
$aFileInfo = array();
$sFilePath = uniqid(); // just in case no path...
foreach ($oFileNode->childNodes as $oFileInfo)
{
if ($oFileInfo instanceof DOMElement)
{
$aFileInfo[$oFileInfo->tagName] = $oFileInfo->textContent;
if ($oFileInfo->tagName == 'path')
{
$sFilePath = $oFileInfo->textContent;
}
}
}
$aFiles[] = $aFileInfo;
$aFiles[$sFilePath] = $aFileInfo;
}
}
}
@@ -98,7 +103,6 @@ class FilesIntegrity
$sChecksum = md5($sContent);
if (($iSize != $aFileInfo['size']) || ($sChecksum != $aFileInfo['md5']))
{
throw new FileIntegrityException(Dict::Format('FilesInformation:Error:CorruptedFile', basename($sFile)));
}
}

View File

@@ -103,6 +103,48 @@ class UtilsTest extends \Combodo\iTop\Test\UnitTest\ItopTestCase
];
}
/**
* @dataProvider LocalPathProvider
*
* @param $sAbsolutePath
* @param $expected
*/
public function testLocalPath($sAbsolutePath, $expected)
{
$this->assertSame($expected, utils::LocalPath($sAbsolutePath));
}
public function LocalPathProvider()
{
return array(
'index.php' => array(
'sAbsolutePath' => APPROOT.'index.php',
'expected' => 'index.php',
),
'non existing' => array(
'sAbsolutePath' => APPROOT.'nonexisting/nonexisting',
'expected' => false,
),
'outside' => array(
'sAbsolutePath' => '/tmp',
'expected' => false,
),
'application/cmdbabstract.class.inc.php' => array(
'sAbsolutePath' => APPROOT.'application/cmdbabstract.class.inc.php',
'expected' => 'application/cmdbabstract.class.inc.php',
),
'dir' => array(
'sAbsolutePath' => APPROOT.'application/.',
'expected' => 'application',
),
'root' => array(
'sAbsolutePath' => APPROOT.'.',
'expected' => '',
),
);
}
/**
* @dataProvider appRootUrlProvider
* @covers utils::GetAppRootUrl