Skip to content

Commit

Permalink
Fixed issue #16917: Error when navigating to global settings and usin…
Browse files Browse the repository at this point in the history
…g PHP8
  • Loading branch information
c-schmitz committed Feb 16, 2021
1 parent a3e53fa commit 5a72ccc
Show file tree
Hide file tree
Showing 9 changed files with 96 additions and 37 deletions.
8 changes: 6 additions & 2 deletions application/controllers/admin/export.php
Expand Up @@ -1322,14 +1322,18 @@ private function _addHeaders($filename, $content_type, $expires)

private function _xmlToJson($fileContents)
{
$bOldEntityLoaderState = libxml_disable_entity_loader(true); // @see: http://phpsecurity.readthedocs.io/en/latest/Injection-Attacks.html#xml-external-entity-injection
if (\PHP_VERSION_ID < 80000) {
$bOldEntityLoaderState = libxml_disable_entity_loader(true); // @see: http://phpsecurity.readthedocs.io/en/latest/Injection-Attacks.html#xml-external-entity-injection
}

$fileContents = str_replace(array("\n", "\r", "\t"), '', $fileContents);
$fileContents = trim(str_replace('"', "'", $fileContents));
$simpleXml = simplexml_load_string($fileContents, 'SimpleXMLElement', LIBXML_NOCDATA);
$json = json_encode($simpleXml);

libxml_disable_entity_loader($bOldEntityLoaderState); // Put back entity loader to its original state, to avoid contagion to other applications on the server
if (\PHP_VERSION_ID < 80000) {
libxml_disable_entity_loader($bOldEntityLoaderState); // Put back entity loader to its original state, to avoid contagion to other applications on the server
}
return $json;
}

Expand Down
8 changes: 6 additions & 2 deletions application/core/LSYii_Application.php
Expand Up @@ -461,7 +461,9 @@ public function getTwigCustomExtensionsConfig( $sUsertwigextensionrootdir, $aApp
}

// Then we read each manifest and add their functions to Twig Component
$bOldEntityLoaderState = libxml_disable_entity_loader(true); // @see: http://phpsecurity.readthedocs.io/en/latest/Injection-Attacks.html#xml-external-entity-injection
if (\PHP_VERSION_ID < 80000) {
$bOldEntityLoaderState = libxml_disable_entity_loader(true); // @see: http://phpsecurity.readthedocs.io/en/latest/Injection-Attacks.html#xml-external-entity-injection
}

foreach ($CustomTwigExtensionsManifestFiles as $ctemFile){
$sXMLConfigFile = file_get_contents( realpath ($ctemFile)); // @see: Now that entity loader is disabled, we can't use simplexml_load_file; so we must read the file with file_get_contents and convert it as a string
Expand Down Expand Up @@ -489,7 +491,9 @@ public function getTwigCustomExtensionsConfig( $sUsertwigextensionrootdir, $aApp
}
}

libxml_disable_entity_loader($bOldEntityLoaderState); // Put back entity loader to its original state, to avoid contagion to other applications on the server
if (\PHP_VERSION_ID < 80000) {
libxml_disable_entity_loader($bOldEntityLoaderState); // Put back entity loader to its original state, to avoid contagion to other applications on the server
}

return $aApplicationConfig;
}
Expand Down
8 changes: 6 additions & 2 deletions application/helpers/admin/import_helper.php
Expand Up @@ -20,7 +20,9 @@
function XMLImportGroup($sFullFilePath, $iNewSID)
{
$sBaseLanguage = Survey::model()->findByPk($iNewSID)->language;
$bOldEntityLoaderState = libxml_disable_entity_loader(true); // @see: http://phpsecurity.readthedocs.io/en/latest/Injection-Attacks.html#xml-external-entity-injection
if (\PHP_VERSION_ID < 80000) {
$bOldEntityLoaderState = libxml_disable_entity_loader(true); // @see: http://phpsecurity.readthedocs.io/en/latest/Injection-Attacks.html#xml-external-entity-injection
}

$sXMLdata = file_get_contents($sFullFilePath);
$xml = simplexml_load_string($sXMLdata, 'SimpleXMLElement', LIBXML_NONET);
Expand Down Expand Up @@ -333,7 +335,9 @@ function XMLImportGroup($sFullFilePath, $iNewSID)
$results['labelsets'] = 0;
$results['labels'] = 0;

libxml_disable_entity_loader($bOldEntityLoaderState); // Put back entity loader to its original state, to avoid contagion to other applications on the server
if (\PHP_VERSION_ID < 80000) {
libxml_disable_entity_loader($bOldEntityLoaderState); // Put back entity loader to its original state, to avoid contagion to other applications on the server
}
return $results;
}

Expand Down
2 changes: 1 addition & 1 deletion application/helpers/adodb/adodb-time.inc_helper.php
Expand Up @@ -722,7 +722,7 @@ function adodb_get_gmt_diff($y, $m, $d)
} else {
if (isset($TZ)) return $TZ;
$y = date('Y');
$TZ = @mktime(0, 0, 0, 12, 2, $y, 0) - @gmmktime(0, 0, 0, 12, 2, $y, 0);
$TZ = @mktime(0, 0, 0, 12, 2, $y) - @gmmktime(0, 0, 0, 12, 2, $y);
}

return $TZ;
Expand Down
9 changes: 6 additions & 3 deletions application/helpers/questionHelper.php
Expand Up @@ -1631,14 +1631,17 @@ public static function getQuestionAttributesSettings($sType)
*/
public static function getQuestionThemeAttributeValues($sQuestionThemeName = null, $question_template = null)
{
libxml_disable_entity_loader(false);

if (\PHP_VERSION_ID < 80000) {
libxml_disable_entity_loader(false);
}
$sCoreThemeXmlPath = Yii::app()->getConfig('corequestionthemerootdir').'/'.$sQuestionThemeName.'/survey/questions/answer/'.$question_template.'/config.xml';
$sUserThemeXmlPath = Yii::app()->getConfig("userquestionthemerootdir").'/'.$sQuestionThemeName.'/survey/questions/answer/'.$question_template.'/config.xml';

$xml_config = is_file($sCoreThemeXmlPath) ? simplexml_load_file($sCoreThemeXmlPath) : simplexml_load_file($sUserThemeXmlPath);
$custom_attributes = json_decode(json_encode((array)$xml_config->custom_attributes), TRUE);
libxml_disable_entity_loader(true);
if (\PHP_VERSION_ID < 80000) {
libxml_disable_entity_loader(true);
}

if(!empty($custom_attributes['attribute']['name'])) {
// Only one attribute set in config : need an array of attributes
Expand Down
38 changes: 27 additions & 11 deletions application/helpers/remotecontrol/remotecontrol_handle.php
Expand Up @@ -1111,12 +1111,16 @@ public function import_group($sSessionKey, $iSurveyID, $sImportData, $sImportDat
file_put_contents($sFullFilePath, base64_decode(chunk_split($sImportData)));

if (strtolower($sImportDataType) == 'lsg') {
$bOldEntityLoaderState = libxml_disable_entity_loader(true); // @see: http://phpsecurity.readthedocs.io/en/latest/Injection-Attacks.html#xml-external-entity-injection
if (\PHP_VERSION_ID < 80000) {
$bOldEntityLoaderState = libxml_disable_entity_loader(true); // @see: http://phpsecurity.readthedocs.io/en/latest/Injection-Attacks.html#xml-external-entity-injection
}
$sXMLdata = file_get_contents($sFullFilePath);
$xml = @simplexml_load_string($sXMLdata, 'SimpleXMLElement', LIBXML_NONET);
if (!$xml) {
unlink($sFullFilePath);
libxml_disable_entity_loader($bOldEntityLoaderState); // Put back entity loader to its original state, to avoid contagion to other applications on the server
if (\PHP_VERSION_ID < 80000) {
libxml_disable_entity_loader($bOldEntityLoaderState); // Put back entity loader to its original state, to avoid contagion to other applications on the server
}
return array('status' => 'Error: Invalid LimeSurvey group structure XML ');
}
$aImportResults = XMLImportGroup($sFullFilePath, $iSurveyID);
Expand All @@ -1128,7 +1132,9 @@ public function import_group($sSessionKey, $iSurveyID, $sImportData, $sImportDat
unlink($sFullFilePath);

if (isset($aImportResults['fatalerror'])) {
libxml_disable_entity_loader($bOldEntityLoaderState); // Put back entity loader to its original state, to avoid contagion to other applications on the server
if (\PHP_VERSION_ID < 80000) {
libxml_disable_entity_loader($bOldEntityLoaderState); // Put back entity loader to its original state, to avoid contagion to other applications on the server
}
return array('status' => 'Error: '.$aImportResults['fatalerror']);
} else {
$iNewgid = $aImportResults['newgid'];
Expand All @@ -1145,7 +1151,9 @@ public function import_group($sSessionKey, $iSurveyID, $sImportData, $sImportDat
} catch (Exception $e) {
// no need to throw exception
}
libxml_disable_entity_loader($bOldEntityLoaderState); // Put back entity loader to its original state, to avoid contagion to other applications on the server
if (\PHP_VERSION_ID < 80000) {
libxml_disable_entity_loader($bOldEntityLoaderState); // Put back entity loader to its original state, to avoid contagion to other applications on the server
}
return (int) $aImportResults['newgid'];
}
} else {
Expand Down Expand Up @@ -1418,25 +1426,32 @@ public function import_question($sSessionKey, $iSurveyID, $iGroupID, $sImportDat
file_put_contents($sFullFilePath, base64_decode(chunk_split($sImportData)));

if (strtolower($sImportDataType) == 'lsq') {
$bOldEntityLoaderState = libxml_disable_entity_loader(true); // @see: http://phpsecurity.readthedocs.io/en/latest/Injection-Attacks.html#xml-external-entity-injection

if (\PHP_VERSION_ID < 80000) {
$bOldEntityLoaderState = libxml_disable_entity_loader(true); // @see: http://phpsecurity.readthedocs.io/en/latest/Injection-Attacks.html#xml-external-entity-injection
}
$sXMLdata = file_get_contents($sFullFilePath);
$xml = @simplexml_load_string($sXMLdata, 'SimpleXMLElement', LIBXML_NONET);
if (!$xml) {
unlink($sFullFilePath);
libxml_disable_entity_loader($bOldEntityLoaderState); // Put back entity loader to its original state, to avoid contagion to other applications on the server
if (\PHP_VERSION_ID < 80000) {
libxml_disable_entity_loader($bOldEntityLoaderState); // Put back entity loader to its original state, to avoid contagion to other applications on the server
}
return array('status' => 'Error: Invalid LimeSurvey question structure XML ');
}
$aImportResults = XMLImportQuestion($sFullFilePath, $iSurveyID, $iGroupID);
} else {
libxml_disable_entity_loader($bOldEntityLoaderState); // Put back entity loader to its original state, to avoid contagion to other applications on the server
if (\PHP_VERSION_ID < 80000) {
libxml_disable_entity_loader($bOldEntityLoaderState); // Put back entity loader to its original state, to avoid contagion to other applications on the server
}
return array('status' => 'Really Invalid extension'); //just for symmetry!
}

unlink($sFullFilePath);

if (isset($aImportResults['fatalerror'])) {
libxml_disable_entity_loader($bOldEntityLoaderState); // Put back entity loader to its original state, to avoid contagion to other applications on the server
if (\PHP_VERSION_ID < 80000) {
libxml_disable_entity_loader($bOldEntityLoaderState); // Put back entity loader to its original state, to avoid contagion to other applications on the server
}
return array('status' => 'Error: '.$aImportResults['fatalerror']);
} else {
fixLanguageConsistency($iSurveyID);
Expand All @@ -1458,8 +1473,9 @@ public function import_question($sSessionKey, $iSurveyID, $iGroupID, $sImportDat
$oQuestion->setAttribute('mandatory', 'N');
}

libxml_disable_entity_loader($bOldEntityLoaderState); // Put back entity loader to its original state, to avoid contagion to other applications on the server

if (\PHP_VERSION_ID < 80000) {
libxml_disable_entity_loader($bOldEntityLoaderState); // Put back entity loader to its original state, to avoid contagion to other applications on the server
}

try {
$oQuestion->save();
Expand Down
16 changes: 12 additions & 4 deletions application/models/AdminTheme.php
Expand Up @@ -102,7 +102,9 @@ public function setAdminTheme()
//////////////////////
// Config file loading

$bOldEntityLoaderState = libxml_disable_entity_loader(true); // @see: http://phpsecurity.readthedocs.io/en/latest/Injection-Attacks.html#xml-external-entity-injection
if (\PHP_VERSION_ID < 80000) {
$bOldEntityLoaderState = libxml_disable_entity_loader(true); // @see: http://phpsecurity.readthedocs.io/en/latest/Injection-Attacks.html#xml-external-entity-injection
}
$sXMLConfigFile = file_get_contents(realpath($this->path.'/config.xml')); // Now that entity loader is disabled, we can't use simplexml_load_file; so we must read the file with file_get_contents and convert it as a string

// Simple Xml is buggy on PHP < 5.4. The [ array -> json_encode -> json_decode ] workaround seems to be the most used one.
Expand All @@ -115,7 +117,9 @@ public function setAdminTheme()
$this->defineConstants(); // Define the (still) necessary constants
$this->registerStylesAndScripts(); // Register all CSS and JS

libxml_disable_entity_loader($bOldEntityLoaderState); // Put back entity loader to its original state, to avoid contagion to other applications on the server
if (\PHP_VERSION_ID < 80000) {
libxml_disable_entity_loader($bOldEntityLoaderState); // Put back entity loader to its original state, to avoid contagion to other applications on the server
}

return $this;
}
Expand Down Expand Up @@ -307,7 +311,9 @@ public static function getOtherAssets()
*/
static private function getThemeList($sDir)
{
$bOldEntityLoaderState = libxml_disable_entity_loader(true); // @see: http://phpsecurity.readthedocs.io/en/latest/Injection-Attacks.html#xml-external-entity-injection
if (\PHP_VERSION_ID < 80000) {
$bOldEntityLoaderState = libxml_disable_entity_loader(true); // @see: http://phpsecurity.readthedocs.io/en/latest/Injection-Attacks.html#xml-external-entity-injection
}
$aListOfFiles = array();
$oAdminTheme = new AdminTheme;
if ($sDir && $pHandle = opendir($sDir)) {
Expand All @@ -330,7 +336,9 @@ static private function getThemeList($sDir)
}
closedir($pHandle);
}
libxml_disable_entity_loader($bOldEntityLoaderState);
if (\PHP_VERSION_ID < 80000) {
libxml_disable_entity_loader($bOldEntityLoaderState);
}
return $aListOfFiles;
}

Expand Down
40 changes: 30 additions & 10 deletions application/models/TemplateManifest.php
Expand Up @@ -41,12 +41,16 @@ class TemplateManifest extends TemplateConfiguration
*/
public function actualizeLastUpdate()
{
libxml_disable_entity_loader(false);
if (\PHP_VERSION_ID < 80000) {
libxml_disable_entity_loader(false);
}
$config = simplexml_load_file(realpath($this->xmlFile));
$config->metadata->last_update = date("Y-m-d H:i:s");
$config->asXML(realpath($this->xmlFile)); // Belt
touch($this->path); // & Suspenders ;-)
libxml_disable_entity_loader(true);
if (\PHP_VERSION_ID < 80000) {
libxml_disable_entity_loader(true);
}
}

/**
Expand Down Expand Up @@ -881,13 +885,17 @@ public static function changeDateInDOM($oNewManifest, $sDate = '')
*/
public static function rename($sOldName, $sNewName)
{
libxml_disable_entity_loader(false);
if (\PHP_VERSION_ID < 80000) {
libxml_disable_entity_loader(false);
}
$sConfigPath = Yii::app()->getConfig('userthemerootdir')."/".$sNewName;
$oNewManifest = self::getManifestDOM($sConfigPath);
self::changeNameInDOM($oNewManifest, $sNewName);
self::changeDateInDOM($oNewManifest);
$oNewManifest->save($sConfigPath."/config.xml");
libxml_disable_entity_loader(true);
if (\PHP_VERSION_ID < 80000) {
libxml_disable_entity_loader(true);
}
}

/**
Expand Down Expand Up @@ -983,7 +991,9 @@ public static function extendsConfig($sToExtends, $sNewName)
$sConfigPath = Yii::app()->getConfig('userthemerootdir')."/".$sNewName;

// First we get the XML file
$oldState = libxml_disable_entity_loader(false);
if (\PHP_VERSION_ID < 80000) {
$oldState = libxml_disable_entity_loader(false);
}
$oNewManifest = self::getManifestDOM($sConfigPath);

self::deleteEngineInDom($oNewManifest);
Expand All @@ -995,7 +1005,9 @@ public static function extendsConfig($sToExtends, $sNewName)

$oNewManifest->save($sConfigPath."/config.xml");

libxml_disable_entity_loader($oldState);
if (\PHP_VERSION_ID < 80000) {
libxml_disable_entity_loader($oldState);
}
}

/**
Expand All @@ -1006,7 +1018,9 @@ private function readManifest()
$this->xmlFile = $this->path.'config.xml';

if (file_exists(realpath($this->xmlFile))) {
$bOldEntityLoaderState = libxml_disable_entity_loader(true); // @see: http://phpsecurity.readthedocs.io/en/latest/Injection-Attacks.html#xml-external-entity-injection
if (\PHP_VERSION_ID < 80000) {
$bOldEntityLoaderState = libxml_disable_entity_loader(true); // @see: http://phpsecurity.readthedocs.io/en/latest/Injection-Attacks.html#xml-external-entity-injection
}
$sXMLConfigFile = file_get_contents(realpath($this->xmlFile)); // @see: Now that entity loader is disabled, we can't use simplexml_load_file; so we must read the file with file_get_contents and convert it as a string
$oDOMConfig = new DOMDocument;
$oDOMConfig->loadXML($sXMLConfigFile);
Expand All @@ -1020,7 +1034,9 @@ private function readManifest()
}

$this->config = $oXMLConfig; // Using PHP >= 5.4 then no need to decode encode + need attributes : then other function if needed :https://secure.php.net/manual/en/book.simplexml.php#108688 for example
libxml_disable_entity_loader($bOldEntityLoaderState); // Put back entity loader to its original state, to avoid contagion to other applications on the server
if (\PHP_VERSION_ID < 80000) {
libxml_disable_entity_loader($bOldEntityLoaderState); // Put back entity loader to its original state, to avoid contagion to other applications on the server
}
} else {
throw new Exception(" Error: Can't find a manifest for $this->sTemplateName in ' $this->path ' ");
}
Expand Down Expand Up @@ -1132,7 +1148,9 @@ public function getshowpopups(){
public function addFileReplacement($sFile, $sType)
{
// First we get the XML file
libxml_disable_entity_loader(false);
if (\PHP_VERSION_ID < 80000) {
libxml_disable_entity_loader(false);
}
$oNewManifest = new DOMDocument();
$oNewManifest->load($this->path."config.xml");

Expand All @@ -1159,7 +1177,9 @@ public function addFileReplacement($sFile, $sType)
$oAssetType->appendChild($oAssetElem);
$oConfig->insertBefore($oFiles, $oOptions);
$oNewManifest->save($this->path."config.xml");
libxml_disable_entity_loader(true);
if (\PHP_VERSION_ID < 80000) {
libxml_disable_entity_loader(true);
}
}

/**
Expand Down
4 changes: 2 additions & 2 deletions application/models/UpdateForm.php
Expand Up @@ -92,11 +92,11 @@ public function getUpdateInfo($crosscheck = "1")
/**
* The server will do some checks and will ask for the correct view to be diplayed.
*
* @param string $updateKey the update key
* @param string $updateKey the update key -
* @param string $destinationBuild
* @return string html
*/
public function getWelcomeMessage($updateKey = null, $destinationBuild)
public function getWelcomeMessage($updateKey, $destinationBuild)
{
// First, we destroy any previous cookie :
if (file_exists(realpath($this->path_cookie))) {
Expand Down

0 comments on commit 5a72ccc

Please sign in to comment.