Kaynağa Gözat

Fixed Trac#446: XSS vulnerabilities... to be tested !
Also fixed the display/download links on documents that were both doing exactly the same thing !

git-svn-id: http://svn.code.sf.net/p/itop/code/trunk@1443 a333f486-631f-4898-b8df-5754b55c2be0

dflaven 14 yıl önce
ebeveyn
işleme
253a2ee596

+ 27 - 6
application/ajaxwebpage.class.inc.php

@@ -50,6 +50,7 @@ class ajax_page extends WebPage
 		$this->m_sCurrentTabContainer = '';
         $this->m_sCurrentTab = '';
 		$this->m_aTabs = array();
+		$this->sContentDisposition = 'inline';
     }	
 
 	public function AddTabContainer($sTabContainer, $sPrefix = '')
@@ -92,11 +93,22 @@ class ajax_page extends WebPage
      */	  
     public function output()
     {
+    	if (!empty($this->sContentType))
+    	{
+			$this->add_header('Content-type: '.$this->sContentType);
+    	}
+    	else
+    	{
+			$this->add_header('Content-type: text/html');
+    	}
+    	if (!empty($this->sContentDisposition))
+    	{
+			$this->add_header('Content-Disposition: '.$this->sContentDisposition.'; filename="'.$this->sContentFileName.'"');
+    	}
         foreach($this->a_headers as $s_header)
         {
             header($s_header);
         }
-
 		if (count($this->m_aTabs) > 0)
 		{
 					$this->add_ready_script(
@@ -165,7 +177,15 @@ EOF
 	
         $s_captured_output = ob_get_contents();
         ob_end_clean();
-        echo $this->s_content;
+        if (($this->sContentType == 'text/html') &&  ($this->sContentDisposition == 'inline'))
+        {
+        	// inline content != attachment && html => filter all scripts for malicious XSS scripts
+        	echo self::FilterXSS($this->s_content);
+        }
+        else
+        {
+        	echo $this->s_content;
+        }
         //echo $this->s_deferred_content;
         if (count($this->a_scripts) > 0)
         {
@@ -187,7 +207,7 @@ EOF
         }
 		if (trim($s_captured_output) != "")
         {
-            echo $s_captured_output;
+        	echo self::FilterXSS($s_captured_output);
         }
     }
 
@@ -220,9 +240,6 @@ EOF
 	 */	 	 	
 	public function add_ready_script($sScript)
 	{
-		// Does nothing in ajax rendered content.. for now...
-		// Maybe we should add this as a simple <script> tag at the end of the output
-		// considering that at this time everything in the page is "ready"...
 		$this->m_sReadyScript .= $sScript;
 	}
 	
@@ -236,6 +253,10 @@ EOF
 		return 0;
 	}
 	
+	public static function FilterXSS($sHTML)
+	{
+		return str_ireplace(array('<script', '</script>'), array('<!-- <removed-script', '</removed-script> -->'), $sHTML);
+	}
 }
 
 ?>

+ 3 - 3
application/cmdbabstract.class.inc.php

@@ -1287,7 +1287,7 @@ EOF
 			//$oAppContext->Reset($sFilterCode); // Make sure the same parameter will not be passed twice
 			$sHtml .= '<span style="white-space: nowrap;padding:5px;display:inline-block;">';
 			$sFilterValue = '';
-			$sFilterValue = utils::ReadParam($sFilterCode, '');
+			$sFilterValue = utils::ReadParam($sFilterCode, '', false, 'raw_data');
 			$sFilterOpCode = null; // Use the default 'loose' OpCode
 			if (empty($sFilterValue))
 			{
@@ -1970,7 +1970,7 @@ EOF
 				$oDocument = $this->Get($sAttCode);
 				$sDisplayValue = $this->GetAsHTML($sAttCode);
 				$sDisplayValue .= "<br/>".Dict::Format('UI:OpenDocumentInNewWindow_', $oDocument->GetDisplayLink(get_class($this), $this->GetKey(), $sAttCode)).", \n";
-				$sDisplayValue .= "<br/>".Dict::Format('UI:DownloadDocument_', $oDocument->GetDisplayLink(get_class($this), $this->GetKey(), $sAttCode)).", \n";
+				$sDisplayValue .= "<br/>".Dict::Format('UI:DownloadDocument_', $oDocument->GetDownloadLink(get_class($this), $this->GetKey(), $sAttCode)).", \n";
 			}
 			else
 			{
@@ -2314,7 +2314,7 @@ EOF
 			}
 			else
 			{
-				$value = utils::ReadPostedParam("attr_{$sFormPrefix}{$sAttCode}", null);
+				$value = utils::ReadPostedParam("attr_{$sFormPrefix}{$sAttCode}", null, 'raw_data');
 			}
 			if (!is_null($value))
 			{

+ 4 - 8
application/displayblock.class.inc.php

@@ -232,8 +232,7 @@ class DisplayBlock
 			$sHtml .= "<div id=\"$sId\" class=\"display_block loading\">\n";
 			$sHtml .= $oPage->GetP("<img src=\"../images/indicator_arrows.gif\"> ".Dict::S('UI:Loading'));
 			$sHtml .= "</div>\n";
-			$sHtml .= '
-			<script language="javascript">
+			$oPage->add_script('
 			$.post("ajax.render.php?style='.$this->m_sStyle.'",
 			   { operation: "ajax", filter: "'.$sFilter.'", extra_params: "'.$sExtraParams.'" },
 			   function(data){
@@ -242,14 +241,11 @@ class DisplayBlock
 				 $("#'.$sId.'").removeClass("loading");
 				}
 			 );
-			 </script>';
+			 ');
 		}
 		if ($bAutoReload)
 		{
-			$sHtml .= '
-			<script language="javascript">
-			setInterval("ReloadBlock(\''.$sId.'\', \''.$this->m_sStyle.'\', \''.$sFilter.'\', \"'.$sExtraParams.'\")", '.$iReloadInterval.');
-			 </script>';
+			$oPage->add_script('setInterval("ReloadBlock(\''.$sId.'\', \''.$this->m_sStyle.'\', \''.$sFilter.'\', \"'.$sExtraParams.'\")", '.$iReloadInterval.');');
 		}
 		return $sHtml;
 	}
@@ -299,7 +295,7 @@ class DisplayBlock
 				}
 				foreach($aFilterCodes as $sFilterCode)
 				{
-					$sExternalFilterValue = utils::ReadParam($sFilterCode, '');
+					$sExternalFilterValue = utils::ReadParam($sFilterCode, '', false, 'raw_data');
 					$condition = null;
 					if (isset($aExtraParams[$sFilterCode]))
 					{

+ 9 - 9
application/itopwebpage.class.inc.php

@@ -733,16 +733,16 @@ EOF
 		echo '<div id="left-pane" class="ui-layout-west">';
 		echo '<!-- Beginning of the left pane -->';
 		echo '	<div id="header-logo">';
-		echo '	<div id="top-left"></div><div id="logo"><a href="http://www.combodo.com/itop"><img src="../images/itop-logo.png" title="'.$sVersionString.'" style="border:0; margin-top:16px; margin-right:40px;"/></a></div>';
+		echo '	<div id="top-left"></div><div id="logo"><a href="http://www.combodo.com/itop"><img src="../images/itop-logo.png" title="'.self::FilterXSS($sVersionString).'" style="border:0; margin-top:16px; margin-right:40px;"/></a></div>';
 		echo '	</div>';
 		echo '	<div class="header-menu">';
 		echo '		<div class="icon ui-state-default ui-corner-all"><span id="tPinMenu" class="ui-icon ui-icon-pin-w">pin</span></div>';
-		echo '		<div style="text-align:center;">'.$sForm.'</div>';
+		echo '		<div style="text-align:center;">'.self::FilterXSS($sForm).'</div>';
 		echo '	</div>';
 		echo '	<div id="menu" class="ui-layout-content">';
 		echo '		<div id="inner_menu">';
 		echo '			<div id="accordion">';
-		echo $this->m_sMenu;
+		echo self::FilterXSS($this->m_sMenu);
 		echo '			<!-- Beginning of the accordion menu -->';
 		echo '			<!-- End of the accordion menu-->';
 		echo '			</div>';
@@ -754,16 +754,16 @@ EOF
 
 		echo '<div class="ui-layout-center">';
 		echo '	<div id="top-bar" style="width:100%">';
-		echo $sApplicationBanner;
-		echo '		<div id="global-search"><form action="'.utils::GetAbsoluteUrlAppRoot().'pages/UI.php"><table><tr><td></td><td id="g-search-input"><input type="text" name="text" value="'.$sText.'"'.$sOnClick.'/></td>';
+		echo self::FilterXSS($sApplicationBanner);
+		echo '		<div id="global-search"><form action="'.utils::GetAbsoluteUrlAppRoot().'pages/UI.php"><table><tr><td></td><td id="g-search-input"><input type="text" name="text" value="'.self::FilterXSS($sText).'"'.$sOnClick.'/></td>';
 		echo '<td><input type="image" src="../images/searchBtn.png"/></a></td>';
 		echo '<td><a style="background:transparent;" href="'.$sOnlineHelpUrl.'" target="_blank"><img style="border:0;padding-left:20px;padding-right:10px;" title="'.Dict::S('UI:Help').'" src="../images/help.png"/></td>';
-		echo '<td style="padding-right:20px;padding-left:10px;">'.$sLogOffMenu.'</td><td><input type="hidden" name="operation" value="full_text"/></td></tr></table></form></div>';
+		echo '<td style="padding-right:20px;padding-left:10px;">'.self::FilterXSS($sLogOffMenu).'</td><td><input type="hidden" name="operation" value="full_text"/></td></tr></table></form></div>';
 		//echo '<td>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<input type="hidden" name="operation" value="full_text"/></td></tr></table></form></div>';
 		echo '	</div>';
 		echo '	<div class="ui-layout-content">';
 		echo '	<!-- Beginning of page content -->';
-		echo $this->s_content;
+		echo self::FilterXSS($this->s_content);
 		echo '	<!-- End of page content -->';
 		echo '	</div>';
 		echo '</div>';
@@ -771,9 +771,9 @@ EOF
         // Add the captured output
         if (trim($s_captured_output) != "")
         {
-            echo "<div id=\"rawOutput\" title=\"Debug Output\"><div style=\"height:500px; overflow-y:auto;\">$s_captured_output</div></div>\n";
+            echo "<div id=\"rawOutput\" title=\"Debug Output\"><div style=\"height:500px; overflow-y:auto;\">".self::FilterXSS($s_captured_output)."</div></div>\n";
         }
-		echo "<div id=\"at_the_end\">".$this->s_deferred_content."</div>";
+		echo "<div id=\"at_the_end\">".self::FilterXSS($this->s_deferred_content)."</div>";
 //		echo $this->s_deferred_content;
 		echo "<div style=\"display:none\" title=\"ex2\" id=\"ex2\">Please wait...</div>\n"; // jqModal Window
 		echo "<div style=\"display:none\" title=\"dialog\" id=\"ModalDlg\"></div>";

+ 10 - 10
application/loginwebpage.class.inc.php

@@ -110,8 +110,8 @@ EOF
 			case 'external':
 			case 'form':
 			default: // In case the settings get messed up...
-			$sAuthUser = utils::ReadParam('auth_user', '');
-			$sAuthPwd = utils::ReadParam('suggest_pwd', '');
+			$sAuthUser = utils::ReadParam('auth_user', '', true, 'raw_data');
+			$sAuthPwd = utils::ReadParam('suggest_pwd', '', true, 'raw_data');
 	
 			$sVersionShort = Dict::Format('UI:iTopVersion:Short', ITOP_VERSION);
 			$this->add("<div id=\"login-logo\"><a href=\"http://www.combodo.com/itop\"><img title=\"$sVersionShort\" src=\"../images/itop-logo-external.png\"></a></div>\n");
@@ -140,8 +140,8 @@ EOF
 
 	public function DisplayChangePwdForm($bFailedLogin = false)
 	{
-		$sAuthUser = utils::ReadParam('auth_user', '');
-		$sAuthPwd = utils::ReadParam('suggest_pwd', '');
+		$sAuthUser = utils::ReadParam('auth_user', '', false, 'raw_data');
+		$sAuthPwd = utils::ReadParam('suggest_pwd', '', false, 'raw_data');
 
 		$sVersionShort = Dict::Format('UI:iTopVersion:Short', ITOP_VERSION);
 		$sInconsistenPwdMsg = Dict::S('UI:Login:RetypePwdDoesNotMatch');
@@ -320,8 +320,8 @@ EOF
 					
 					case 'form':
 					// iTop standard mode: form based authentication
-					$sAuthUser = utils::ReadPostedParam('auth_user', '');
-					$sAuthPwd = utils::ReadPostedParam('auth_pwd', '');
+					$sAuthUser = utils::ReadPostedParam('auth_user', '', 'raw_data');
+					$sAuthPwd = utils::ReadPostedParam('auth_pwd', '', 'raw_data');
 					if ($sAuthUser != '')
 					{
 						$sLoginMode = 'form';
@@ -361,10 +361,10 @@ EOF
 
 					case 'url':
 					// Credentials passed directly in the url
-					$sAuthUser = utils::ReadParam('auth_user', '');
+					$sAuthUser = utils::ReadParam('auth_user', '', false, 'raw_data');
 					if ($sAuthUser != '')
 					{
-						$sAuthPwd = utils::ReadParam('auth_pwd', '');
+						$sAuthPwd = utils::ReadParam('auth_pwd', '', false, 'raw_data');
 						$sLoginMode = 'url';
 					}		
 					break;	
@@ -472,8 +472,8 @@ EOF
 		{
 			$sAuthUser = $_SESSION['auth_user'];
 			UserRights::Login($sAuthUser); // Set the user's language
-			$sOldPwd = utils::ReadPostedParam('old_pwd');
-			$sNewPwd = utils::ReadPostedParam('new_pwd');
+			$sOldPwd = utils::ReadPostedParam('old_pwd', 'raw_data');
+			$sNewPwd = utils::ReadPostedParam('new_pwd', 'raw_data');
 			if (UserRights::CanChangePassword() && ((!UserRights::CheckCredentials($sAuthUser, $sOldPwd)) || (!UserRights::ChangePassword($sOldPwd, $sNewPwd))))
 			{
 				$oPage = new LoginWebPage();

+ 1 - 1
application/portalwebpage.class.inc.php

@@ -593,7 +593,7 @@ EOF
 		foreach($aAttList as $sAttSpec)
 		{
 			$sFieldName = str_replace('->', PARAM_ARROW_SEP, $sAttSpec);
-			$value = utils::ReadPostedParam($sPrefix.$sFieldName, null);
+			$value = utils::ReadPostedParam($sPrefix.$sFieldName, null, 'raw_data');
 			if (!is_null($value) && strlen($value) > 0)
 			{
 				$oFilter->AddConditionAdvanced($sAttSpec, $value);

+ 1 - 1
application/ui.extkeywidget.class.inc.php

@@ -327,7 +327,7 @@ EOF
 		$aValues = $oValuesSet->GetValues(array('this' => $oObj), $sContains);
 		foreach($aValues as $sKey => $sFriendlyName)
 		{
-			$oP->add(trim($sFriendlyName)."|".$sKey."\n");
+			$oP->add(trim(htmlentities($sFriendlyName, ENT_COMPAT, 'UTF-8'))."|".$sKey."\n");
 		}
 	}
 	

+ 2 - 2
application/ui.passwordwidget.class.inc.php

@@ -52,8 +52,8 @@ class UIPasswordWidget
 	{
 		$sCode = $this->sAttCode.$this->sNameSuffix;
 		$iWidgetIndex = self::$iWidgetIndex;
-		$sPasswordValue = utils::ReadPostedParam("attr_{$sCode}[value]", '*****');
-		$sConfirmPasswordValue = utils::ReadPostedParam("attr_{$sCode}[confirm]", '*****');
+		$sPasswordValue = utils::ReadPostedParam("attr_{$sCode}[value]", '*****', 'raw_data');
+		$sConfirmPasswordValue = utils::ReadPostedParam("attr_{$sCode}[confirm]", '*****', 'raw_data');
 		$sChangedValue = (($sPasswordValue != '*****') || ($sConfirmPasswordValue != '*****')) ? 1 : 0;
 		$sHtmlValue = '';
 		$sHtmlValue = '<input type="password" maxlength="255" name="attr_'.$sCode.'[value]" id="'.$this->iId.'" value="'.htmlentities($sPasswordValue, ENT_QUOTES, 'UTF-8').'"/>&nbsp;<span class="form_validation" id="v_'.$this->iId.'"></span><br/>';

+ 1 - 3
application/uilinkswizard.class.inc.php

@@ -97,8 +97,7 @@ class UILinksWizard
 		$oP->add("<input type=\"hidden\" name=\"linking_attcode\" value=\"{$this->m_sLinkingAttCode}\">\n");
 		$oP->add("<h1>".Dict::Format('UI:ManageObjectsOf_Class_LinkedWith_Class_Instance', MetaModel::GetName($this->m_sLinkedClass), MetaModel::GetName(get_class($oTargetObj)), "<span class=\"hilite\">".$oTargetObj->GetHyperlink()."</span>")."</h1>\n");
 		$oP->add("</div>\n");
-		$oP->add("<script type=\"text/javascript\">\n");
-		$oP->add(
+		$oP->add_script(
 <<<EOF
 		function OnSelectChange()
 		{
@@ -257,7 +256,6 @@ class UILinksWizard
 		}
 EOF
 );
-		$oP->Add("</script>\n");
 		$oP->add_ready_script("InitForm();");
 		$oFilter = new DBObjectSearch($this->m_sClass);
 		$oFilter->AddCondition($this->m_sLinkageAttr, $this->m_iObjectId, '=');

+ 8 - 10
application/uiwizard.class.inc.php

@@ -112,8 +112,7 @@ class UIWizard
 		<input type=\"button\" value=\"".Dict::S('UI:Button:Next')."\" onClick=\"GoToStep($iStepIndex, 1+$iStepIndex)\" />
 		<input type=\"button\" value=\"".Dict::S('UI:Button:Finish')."\" $sDisabled onClick=\"GoToStep($iStepIndex, 1+$nbSteps)\" />
 		</div>\n");
-		$this->m_oPage->add("
-<script type=\"text/javascript\">
+		$this->m_oPage->add_script("
 function OnEnterStep{$iStepIndex}()
 {
 	oWizardHelper.ResetQuery();
@@ -123,7 +122,7 @@ $sJSHandlerCode
 
 	oWizardHelper.AjaxQueryServer();
 }
-</script>\n");
+");
 		$this->m_oPage->add("</div>\n\n");
 	}	
 
@@ -139,16 +138,15 @@ $sJSHandlerCode
 		$this->m_oPage->add("<input type=\"hidden\" name=\"operation\" value=\"wizard_apply_new\" />\n");
 		$this->m_oPage->add("<input type=\"hidden\" name=\"transaction_id\" value=\"".utils::GetNewTransactionId()."\" />\n");
 		$this->m_oPage->add("<input type=\"hidden\" id=\"wizard_json_obj\" name=\"json_obj\" value=\"\" />\n");
-		$this->m_oPage->add("<script type=\"text/javascript\">\n");
-		$this->m_oPage->add("function OnEnterStep$iStepIndex() {\n");
+		$sScript = "function OnEnterStep$iStepIndex() {\n";
 		foreach($aFieldsMap as $iInputId => $sAttCode)
 		{
-			$this->m_oPage->add("\toWizardHelper.UpdateCurrentValue('$sAttCode');\n");		
+			$sScript .= "\toWizardHelper.UpdateCurrentValue('$sAttCode');\n";		
 		}
-		$this->m_oPage->add("\toWizardHelper.Preview('object_preview');\n");		
-		$this->m_oPage->add("\t$('#wizard_json_obj').val(oWizardHelper.ToJSON());\n");		
-		$this->m_oPage->add("}\n");
-		$this->m_oPage->add("</script>\n");
+		$sScript .= "\toWizardHelper.Preview('object_preview');\n";		
+		$sScript .= "\t$('#wizard_json_obj').val(oWizardHelper.ToJSON());\n";		
+		$sScript .= "}\n";
+		$this->m_oPage->add_script($sScript);
 		$this->m_oPage->add("<div id=\"object_preview\">\n");
 		$this->m_oPage->add("</div>\n");
 		$this->m_oPage->add($oAppContext->GetForForm());		

+ 63 - 4
application/utils.inc.php

@@ -114,7 +114,7 @@ class utils
 	}
 
 
-	public static function ReadParam($sName, $defaultValue = "", $bAllowCLI = false)
+	public static function ReadParam($sName, $defaultValue = "", $bAllowCLI = false, $sSanitizationFilter = 'parameter')
 	{
 		global $argv;
 		$retValue = $defaultValue;
@@ -141,12 +141,71 @@ class utils
 				}
 			}
 		}
-		return $retValue;
+		return self::Sanitize($retValue, $defaultValue, $sSanitizationFilter);
 	}
 	
-	public static function ReadPostedParam($sName, $defaultValue = "")
+	public static function ReadPostedParam($sName, $defaultValue = '', $sSanitizationFilter = 'parameter')
 	{
-		return isset($_POST[$sName]) ? $_POST[$sName] : $defaultValue;
+		$retValue = isset($_POST[$sName]) ? $_POST[$sName] : $defaultValue;
+		return self::Sanitize($retValue, $defaultValue, $sSanitizationFilter);
+	}
+	
+	public static function Sanitize($value, $defaultValue, $sSanitizationFilter)
+	{
+		$retValue = self::Sanitize_Internal($value, $sSanitizationFilter);
+		if ($retValue === false)
+		{
+			$retValue = $defaultValue;
+		}
+		return $retValue;		
+	}
+	
+	protected static function Sanitize_Internal($value, $sSanitizationFilter)
+	{
+		switch($sSanitizationFilter)
+		{
+			case 'integer':
+			$retValue = filter_var($value, FILTER_SANITIZE_NUMBER_INT);
+			break;
+			
+			case 'class':
+			$retValue = $value;
+			if (!MetaModel::IsValidClass($value))
+			{
+				$retValue = false;
+			}
+			break;
+
+			case 'string':
+			$retValue = filter_var($value, FILTER_SANITIZE_SPECIAL_CHARS);
+			break;
+			
+			case 'parameter':
+			if (is_array($value))
+			{
+				$retValue = array();
+				foreach($value as $key => $val)
+				{
+					$retValue[$key] = self::Sanitize_Internal($val, $sSanitizationFilter); // recursively check arrays
+					if ($retValue[$key] === false)
+					{
+						$retValue = false;
+						break;
+					}
+				}
+			}
+			else
+			{
+				$retValue = filter_var($value, FILTER_VALIDATE_REGEXP, array("options"=>array("regexp"=>'/^[A-Za-z0-9_=-]*$/'))); // the '=' equal character is used in serialized filters
+			}
+			break;
+			
+			default:
+			case 'raw_data':
+			$retValue = $value;
+			// Do nothing
+		}
+		return $retValue;		
 	}
 	
 	/**

+ 39 - 6
application/webpage.class.inc.php

@@ -47,7 +47,10 @@ class WebPage
     protected $a_base;
     protected $iNextId;
     protected $iTransactionId;
-    
+	protected $sContentType;
+	protected $sContentDisposition;
+	protected $sContentFileName;
+	    
     public function __construct($s_title)
     {
         $this->s_title = $s_title;
@@ -61,6 +64,9 @@ class WebPage
         $this->a_base = array( 'href' => '', 'target' => '');
         $this->iNextId = 0;
         $this->iTransactionId = 0;
+        $this->sContentType = '';
+        $this->sContentDisposition = '';
+        $this->sContentFileName = '';
         ob_start(); // Start capturing the output
     }
 	
@@ -359,7 +365,7 @@ class WebPage
         echo "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Strict//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd\">\n";
         echo "<html>\n";
         echo "<head>\n";
-        echo "<meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\" />\n";
+		echo "<meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\" />\n";
         echo "<title>{$this->s_title}</title>\n";
         echo $this->get_base_tag();
         foreach($this->a_linked_scripts as $s_script)
@@ -409,12 +415,12 @@ class WebPage
         }
         echo "</head>\n";
         echo "<body>\n";
-        echo $this->s_content;
+        echo self::FilterXSS($this->s_content);
         if (trim($s_captured_output) != "")
         {
-            echo "<div class=\"raw_output\">$s_captured_output</div>\n";
+            echo "<div class=\"raw_output\">".self::FilterXSS($s_captured_output)."</div>\n";
         }
-        echo '<div id="at_the_end">'.$this->s_deferred_content.'</div>';
+        echo '<div id="at_the_end">'.self::FilterXSS($this->s_deferred_content).'</div>';
         echo "</body>\n";
         echo "</html>\n";
     }
@@ -459,7 +465,29 @@ class WebPage
 	{
 		return $this->iNextId++;
 	}
-	
+
+	/**
+	 * Set the content-type (mime type) for the page's content
+	 * @param $sContentType string
+	 * @return void
+	 */
+	public function SetContentType($sContentType)
+	{
+		$this->sContentType = $sContentType;
+	}
+		
+	/**
+	 * Set the content-disposition (mime type) for the page's content
+	 * @param $sDisposition string The disposition: 'inline' or 'attachment'
+	 * @param $sFileName string The original name of the file
+	 * @return void
+	 */
+	public function SetContentDisposition($sDisposition, $sFileName)
+	{
+		$this->sContentDisposition = $sDisposition;
+		$this->sContentFileName = $sFileName;
+	}
+		
 	/**
 	 * Set the transactionId of the current form
 	 * @param $iTransactionId integer
@@ -478,5 +506,10 @@ class WebPage
 	{
 		return $this->iTransactionId;
 	}
+	
+	public static function FilterXSS($sHTML)
+	{
+		return str_ireplace('<script', '&lt;script', $sHTML);
+	}
 }
 ?>

+ 0 - 27
modules/itop-welcome-itil/welcome_menu.html

@@ -84,33 +84,6 @@ a.summary:hover {
 	text-decoration: underline;
 }
 </style>
-<script>
-var sSerialized = '';
-function DumpPositions()
-{
-	sSerialized = $('.sortable').sortable('serialize', {key: 'menu'});
-	alert(sSerialized);
-}
-
-function RestorePositions()
-{	height: auto;
-    var arr = $('#main_menu .main_container').get();    
-    arr.reverse();
-
-	var sTemp = sSerialized.replace(/menu=/g, '');
-	alert(sTemp);
-	var aSerialized = sTemp.split('&');
-	console.log(aSerialized);
-    $.each(aSerialized, function(i,v) {
-      console.log(i+' => '+v);
-      var $menu = $('#menu_'+v);
-      if ($menu.length >  0) // Check that the menu exists
-      {
-      	$('#main_menu').append($menu);
-      }
-    });
-}
-</script>
 <div id="main_menu" class="sortable persistent">
 
 <div id="menu_1" class="main_container v-resizable">

+ 2 - 2
pages/UniversalSearch.php

@@ -49,8 +49,8 @@ $oP->add_linked_script("../js/jquery.blockUI.js");
 // Now render the content of the page
 $sBaseClass = utils::ReadParam('baseClass', 'Organization');
 $sClass = utils::ReadParam('class', $sBaseClass);
-$sOQLClause = utils::ReadParam('oql_clause', '');
-$sFilter = utils::ReadParam('filter', '');
+$sOQLClause = utils::ReadParam('oql_clause', '', false, 'raw_data');
+$sFilter = utils::ReadParam('filter', '', false, 'raw_data');
 $sOperation = utils::ReadParam('operation', '');
 
 // First part: select the class to search for

+ 8 - 6
pages/ajax.csvimport.php

@@ -224,13 +224,14 @@ try
 		case 'parser_preview':
 		$oPage = new ajax_page("");
 		$oPage->no_cache();
-		$sSeparator = utils::ReadParam('separator', ',');
+		$oPage->SetContentType('text/html');
+		$sSeparator = utils::ReadParam('separator', ',', false, 'raw_data');
 		if ($sSeparator == 'tab') $sSeparator = "\t";
-		$sTextQualifier = utils::ReadParam('qualifier', '"');
+		$sTextQualifier = utils::ReadParam('qualifier', '"', false, 'raw_data');
 		$iLinesToSkip = utils::ReadParam('nb_lines_skipped', 0);
 		$bFirstLineAsHeader = utils::ReadParam('header_line', true);
 		$sEncoding = utils::ReadParam('encoding', 'UTF-8');
-		$sData = stripslashes(utils::ReadParam('csvdata', true));
+		$sData = stripslashes(utils::ReadParam('csvdata', true, false, 'raw_data'));
 		$oCSVParser = new CSVParser($sData, $sSeparator, $sTextQualifier);
 		$aData = $oCSVParser->ToArray($iLinesToSkip);
 		$iTarget = count($aData);
@@ -284,11 +285,12 @@ try
 		case 'display_mapping_form':
 		$oPage = new ajax_page("");
 		$oPage->no_cache();
-		$sSeparator = utils::ReadParam('separator', ',');
-		$sTextQualifier = utils::ReadParam('qualifier', '"');
+		$oPage->SetContentType('text/html');
+		$sSeparator = utils::ReadParam('separator', ',', false, 'raw_data');
+		$sTextQualifier = utils::ReadParam('qualifier', '"', false, 'raw_data');
 		$iLinesToSkip = utils::ReadParam('nb_lines_skipped', 0);
 		$bFirstLineAsHeader = utils::ReadParam('header_line', false);
-		$sData = stripslashes(utils::ReadParam('csvdata', ''));
+		$sData = stripslashes(utils::ReadParam('csvdata', '', false, 'raw_data'));
 		$sClassName = utils::ReadParam('class_name', '');
 		$bAdvanced = utils::ReadParam('advanced', false);
 		$sEncoding = utils::ReadParam('encoding', 'UTF-8');

+ 34 - 24
pages/ajax.render.php

@@ -43,7 +43,7 @@ try
 	$oPage->no_cache();
 	
 	$operation = utils::ReadParam('operation', '');
-	$sFilter = stripslashes(utils::ReadParam('filter', ''));
+	$sFilter = stripslashes(utils::ReadParam('filter', '', false, 'raw_data'));
 	$sEncoding = utils::ReadParam('encoding', 'serialize');
 	$sClass = utils::ReadParam('class', 'MissingAjaxParam');
 	$sStyle = utils::ReadParam('style', 'list');
@@ -51,7 +51,8 @@ try
 	switch($operation)
 	{
 		case 'pagination':
-		$sExtraParams = stripslashes(utils::ReadParam('extra_param', ''));
+		$oPage->SetContentType('text/html');
+		$sExtraParams = stripslashes(utils::ReadParam('extra_param', '', false, 'raw_data'));
 		$aExtraParams = array();
 		if (!empty($sExtraParams))
 		{
@@ -169,6 +170,7 @@ try
 		
 		// ui.linkswidget
 		case 'searchObjectsToAdd':
+		$oPage->SetContentType('text/html');
 		$sRemoteClass = utils::ReadParam('sRemoteClass', '');
 		$sAttCode = utils::ReadParam('sAttCode', '');
 		$iInputId = utils::ReadParam('iInputId', '');
@@ -183,11 +185,12 @@ try
 		
 		// ui.extkeywidget
 		case 'searchObjectsToSelect':
+		$oPage->SetContentType('text/html');
 		$sTargetClass = utils::ReadParam('sTargetClass', '');
 		$iInputId = utils::ReadParam('iInputId', '');
 		$sRemoteClass = utils::ReadParam('sRemoteClass', '');
-		$sFilter = utils::ReadParam('sFilter');
-		$sJson = utils::ReadParam('json', '');
+		$sFilter = utils::ReadParam('sFilter', false, 'raw_data');
+		$sJson = utils::ReadParam('json', '', false, 'raw_data');
 		if (!empty($sJson))
 		{
 			$oWizardHelper = WizardHelper::FromJSON($sJson);
@@ -206,9 +209,9 @@ try
 		case 'ac_extkey':
 		$sTargetClass = utils::ReadParam('sTargetClass', '');
 		$iInputId = utils::ReadParam('iInputId', '');
-		$sFilter = utils::ReadParam('sFilter');
-		$sJson = utils::ReadParam('json', '');
-		$sContains = utils::ReadParam('q', '');
+		$sFilter = utils::ReadParam('sFilter', false, 'raw_data');
+		$sJson = utils::ReadParam('json', '', false, 'raw_data');
+		$sContains = utils::ReadParam('q', '', false, 'raw_data');
 		if (!empty($sJson))
 		{
 			$oWizardHelper = WizardHelper::FromJSON($sJson);
@@ -225,9 +228,10 @@ try
 	
 		// ui.extkeywidget
 		case 'objectSearchForm':
+		$oPage->SetContentType('text/html');
 		$sTargetClass = utils::ReadParam('sTargetClass', '');
 		$iInputId = utils::ReadParam('iInputId', '');
-		$sTitle = utils::ReadParam('sTitle');
+		$sTitle = utils::ReadParam('sTitle', false, 'raw_data');
 		$oWidget = new UIExtKeyWidget($sTargetClass, $iInputId);
 		$oWidget->GetSearchDialog($oPage, $sTitle);
 		break;
@@ -262,10 +266,11 @@ try
 		
 		// ui.extkeywidget
 		case 'displayHierarchy':
+		$oPage->SetContentType('text/html');
 		$sTargetClass = utils::ReadParam('sTargetClass', '');
 		$sInputId = utils::ReadParam('sInputId', '');
-		$sFilter = utils::ReadParam('sFilter');
-		$sJson = utils::ReadParam('json', '');
+		$sFilter = utils::ReadParam('sFilter', '', false, 'raw_data');
+		$sJson = utils::ReadParam('json', '', false, 'raw_data');
 		$currValue = utils::ReadParam('value', '');
 		if (!empty($sJson))
 		{
@@ -285,6 +290,7 @@ try
 		
 		// ui.linkswidget
 		case 'doAddObjects':
+		$oPage->SetContentType('text/html');
 		$sAttCode = utils::ReadParam('sAttCode', '');
 		$iInputId = utils::ReadParam('iInputId', '');
 		$sSuffix = utils::ReadParam('sSuffix', '');
@@ -303,14 +309,16 @@ try
 		break;
 			
 		case 'wizard_helper_preview':
-		$sJson = utils::ReadParam('json_obj', '');
+		$oPage->SetContentType('text/html');
+		$sJson = utils::ReadParam('json_obj', '', false, 'raw_data');
 		$oWizardHelper = WizardHelper::FromJSON($sJson);
 		$oObj = $oWizardHelper->GetTargetObject();
 		$oObj->DisplayBareProperties($oPage); 
 		break;
 		
 		case 'wizard_helper':
-		$sJson = utils::ReadParam('json_obj', '');
+		$oPage->SetContentType('application/json');
+		$sJson = utils::ReadParam('json_obj', '', false, 'raw_data');
 		$oWizardHelper = WizardHelper::FromJSON($sJson);
 		$oObj = $oWizardHelper->GetTargetObject(); 
 		$sClass = $oWizardHelper->GetTargetClass();
@@ -345,6 +353,7 @@ try
 			
 		// DisplayBlock
 		case 'ajax':
+		$oPage->SetContentType('text/html');
 		if ($sFilter != "")
 		{
 			$sExtraParams = stripslashes(utils::ReadParam('extra_params', ''));
@@ -373,11 +382,13 @@ try
 		break;
 		
 		case 'displayCSVHistory':
+		$oPage->SetContentType('text/html');
 		$bShowAll = (utils::ReadParam('showall', 'false') == 'true');
 		BulkChange::DisplayImportHistory($oPage, true, $bShowAll);
 		break;
 		
 		case 'details':
+		$oPage->SetContentType('text/html');
 		$key = utils::ReadParam('id', 0);
 		$oFilter = new DBObjectSearch($sClass);
 		$oFilter->AddCondition('id', $key, '=');
@@ -386,6 +397,7 @@ try
 		break;
 		
 		case 'pie_chart':
+		$oPage->SetContentType('application/json');
 		$sGroupBy = utils::ReadParam('group_by', '');
 		if ($sFilter != '')
 		{
@@ -408,6 +420,7 @@ try
 		break;
 		
 		case 'open_flash_chart':
+		$oPage->SetContentType('application/json');
 		$aParams = utils::ReadParam('params', array());
 		if ($sFilter != '')
 		{
@@ -423,6 +436,7 @@ try
 		break;
 	
 		case 'modal_details':
+		$oPage->SetContentType('text/html');
 		$key = utils::ReadParam('id', 0);
 		$oFilter = new DBObjectSearch($sClass);
 		$oFilter->AddCondition('id', $key, '=');
@@ -433,6 +447,7 @@ try
 		break;
 
 		case 'link':
+		$oPage->SetContentType('text/html');
 		$sClass = utils::ReadParam('sclass', 'logInfra');
 		$sAttCode = utils::ReadParam('attCode', 'name');
 		//$sOrg = utils::ReadParam('org_id', '');
@@ -449,15 +464,9 @@ try
 			$iCount++;
 		}
 		break;
-		
-		case 'create':
-			case 'create_menu':
-			$sClass = utils::ReadParam('class', '');
-			$sFilter = utils::ReadParam('filter', '');
-			menuNode::DisplayCreationForm($oPage, $sClass, $sFilter);
-		break;
 	
 		case 'combo_options':
+		$oPage->SetContentType('text/html');
 		$oFilter = CMDBSearchFilter::FromOQL($sFilter);
 		$oSet = new CMDBObjectSet($oFilter);
 		while( $oObj = $oSet->fetch())
@@ -480,11 +489,12 @@ try
 		$sField = utils::ReadParam('field', '');
 		if (!empty($sClass) && !empty($id) && !empty($sField))
 		{
-			DownloadDocument($oPage, $sClass, $id, $sField, 'attachement');
+			DownloadDocument($oPage, $sClass, $id, $sField, 'attachment');
 		}
 		break;
 		
 		case 'search_form':
+		$oPage->SetContentType('text/html');
 		$sClass = utils::ReadParam('className', '');
 		$sRootClass = utils::ReadParam('baseClass', '');
 		$currentId = utils::ReadParam('currentId', '');
@@ -497,7 +507,7 @@ try
 		
 		case 'set_pref':
 		$sCode = utils::ReadPostedParam('code', '');
-		$sValue = utils::ReadPostedParam('value', '');
+		$sValue = utils::ReadPostedParam('value', '', 'raw_data');
 		appUserPreferences::SetPref($sCode, $sValue);
 		break;
 	
@@ -542,7 +552,7 @@ catch (Exception $e)
  * @param string $sContentDisposition Either 'inline' or 'attachment'
  * @return none
  */   
-function DownloadDocument(WebPage $oPage, $sClass, $id, $sAttCode, $sContentDisposition = 'attachement')
+function DownloadDocument(WebPage $oPage, $sClass, $id, $sAttCode, $sContentDisposition = 'attachment')
 {
 	try
 	{
@@ -552,8 +562,8 @@ function DownloadDocument(WebPage $oPage, $sClass, $id, $sAttCode, $sContentDisp
 			$oDocument = $oObj->Get($sAttCode);
 			if (is_object($oDocument))
 			{
-				$oPage->add_header('Content-type: '.$oDocument->GetMimeType());
-				$oPage->add_header('Content-Disposition: '.$sContentDisposition.'; filename="'.$oDocument->GetFileName().'"');
+				$oPage->SetContentType($oDocument->GetMimeType());
+				$oPage->SetContentDisposition($sContentDisposition,$oDocument->GetFileName());
 				$oPage->add($oDocument->GetData());
 			}
 		}

+ 19 - 19
pages/csvimport.php

@@ -191,10 +191,10 @@ try
 	function ProcessCSVData(WebPage $oPage, $bSimulate = true)
 	{
 		$aResult = array();
-		$sCSVData = utils::ReadParam('csvdata', '');
+		$sCSVData = utils::ReadParam('csvdata', '', false, 'raw_data');
 		$sCSVDataTruncated = utils::ReadParam('csvdata_truncated', '');
-		$sSeparator = utils::ReadParam('separator', ',');
-		$sTextQualifier = utils::ReadParam('text_qualifier', '"');
+		$sSeparator = utils::ReadParam('separator', ',', false, 'raw_data');
+		$sTextQualifier = utils::ReadParam('text_qualifier', '"', false, 'raw_data');
 		$bHeaderLine = (utils::ReadParam('header_line', '0') == 1);
 		$iRealSkippedLines = $iSkippedLines = utils::ReadParam('nb_skipped_lines', '0');
 		$sClassName = utils::ReadParam('class_name', '');
@@ -203,7 +203,7 @@ try
 		$iCurrentStep = $bSimulate ? 4 : 5;
 		$bAdvanced = utils::ReadParam('advanced', 0);
 		$sEncoding = utils::ReadParam('encoding', 'UTF-8');
-		$sSynchroScope = utils::ReadParam('synchro_scope', '');
+		$sSynchroScope = utils::ReadParam('synchro_scope', '', false, 'raw_data');
 		if (!empty($sSynchroScope))
 		{
 			$oSearch = DBObjectSearch::FromOQL($sSynchroScope);
@@ -789,18 +789,18 @@ EOF
 	 */
 	function SelectMapping(WebPage $oPage)
 	{
-		$sCSVData = utils::ReadParam('csvdata', '');
-		$sCSVDataTruncated = utils::ReadParam('csvdata_truncated', '');;
-		$sSeparator = utils::ReadParam('separator', ',');
+		$sCSVData = utils::ReadParam('csvdata', '', false, 'raw_data');
+		$sCSVDataTruncated = utils::ReadParam('csvdata_truncated', '', false, 'raw_data');
+		$sSeparator = utils::ReadParam('separator', ',', false, 'raw_data');
 		if ($sSeparator == 'tab') $sSeparator = "\t";
 		if ($sSeparator == 'other')
 		{
-			$sSeparator = utils::ReadParam('other_separator', ',');
+			$sSeparator = utils::ReadParam('other_separator', ',', false, 'raw_data');
 		}
-		$sTextQualifier = utils::ReadParam('text_qualifier', '"');
+		$sTextQualifier = utils::ReadParam('text_qualifier', '"', false, 'raw_data');
 		if ($sTextQualifier == 'other')
 		{
-			$sTextQualifier = utils::ReadParam('other_qualifier', '"');
+			$sTextQualifier = utils::ReadParam('other_qualifier', '"', false, 'raw_data');
 		}
 		$bHeaderLine = (utils::ReadParam('header_line', '0') == 1);
 		$iSkippedLines = 0;
@@ -812,7 +812,7 @@ EOF
 		$bAdvanced = utils::ReadParam('advanced', 0);
 		$sEncoding = utils::ReadParam('encoding', 'UTF-8');
 	
-		$sSynchroScope = utils::ReadParam('synchro_scope', '');
+		$sSynchroScope = utils::ReadParam('synchro_scope', '', false, 'raw_data');
 		if (!empty($sSynchroScope))
 		{
 			$oSearch = DBObjectSearch::FromOQL($sSynchroScope);
@@ -1064,7 +1064,7 @@ EOF
 			break;
 			
 			default:
-			$sCSVData = utils::ReadPostedParam('csvdata', '');
+			$sCSVData = utils::ReadPostedParam('csvdata', '', 'raw_data');
 		}
 		$sEncoding = utils::ReadParam('encoding', 'UTF-8');
 	
@@ -1080,7 +1080,7 @@ EOF
 	
 		$aGuesses = GuessParameters($sUTF8Data); // Try to predict the parameters, based on the input data
 		
-		$sSeparator = utils::ReadParam('separator', '');
+		$sSeparator = utils::ReadParam('separator', '', false, 'raw_data');
 		if ($sSeparator == '') // May be set to an empty value by the previous page
 		{
 			$sSeparator = $aGuesses['separator'];	
@@ -1089,7 +1089,7 @@ EOF
 		$bBoxSkipLines = utils::ReadParam('box_skiplines', 0);
 		if ($sSeparator == 'tab') $sSeparator = "\t";
 		$sOtherSeparator = in_array($sSeparator, array(',', ';', "\t")) ? '' : $sSeparator;
-		$sTextQualifier = utils::ReadParam('text_qualifier', '');
+		$sTextQualifier = utils::ReadParam('text_qualifier', '', false, 'raw_data');
 		if ($sTextQualifier == '') // May be set to an empty value by the previous page
 		{
 			$sTextQualifier = $aGuesses['qualifier'];	
@@ -1127,7 +1127,7 @@ EOF
 			$sCSVDataTruncated = '';
 		}
 
-		$sSynchroScope = utils::ReadParam('synchro_scope', '');
+		$sSynchroScope = utils::ReadParam('synchro_scope', '', false, 'raw_data');
 		if (!empty($sSynchroScope))
 		{
 			$oSearch = DBObjectSearch::FromOQL($sSynchroScope);
@@ -1263,7 +1263,7 @@ EOF
 		$aPossibleEncodings = array_merge($aPossibleEncodings, $aExtraCharsets);
 		asort($aPossibleEncodings);
 	
-		$sSynchroScope = utils::ReadParam('synchro_scope', '');
+		$sSynchroScope = utils::ReadParam('synchro_scope', '', false, 'raw_data');
 		if (!empty($sSynchroScope))
 		{
 			$oSearch = DBObjectSearch::FromOQL($sSynchroScope);
@@ -1281,8 +1281,8 @@ EOF
 		$oPage->add("<div><p><h1>".Dict::S('UI:Title:BulkImport+')."</h1></p></div>\n");
 		$oPage->AddTabContainer('tabs1');	
 	
-		$sSeparator = utils::ReadParam('separator', '');
-		$sTextQualifier = utils::ReadParam('text_qualifier', '');
+		$sSeparator = utils::ReadParam('separator', '', false, 'raw_data');
+		$sTextQualifier = utils::ReadParam('text_qualifier', '', false, 'raw_data');
 		$bHeaderLine = utils::ReadParam('header_line', true);
 		$iSkippedLines = utils::ReadParam('nb_skipped_lines', '');
 		$sClassName = utils::ReadParam('class_name', '');
@@ -1322,7 +1322,7 @@ EOF
 		$sFileLoadHtml .= '</form></div>';
 		
 		$oPage->AddToTab('tabs1', Dict::S('UI:CSVImport:Tab:LoadFromFile'), $sFileLoadHtml);	
-		$sCSVData = utils::ReadParam('csvdata', '');
+		$sCSVData = utils::ReadParam('csvdata', '', false, 'raw_data');
 		$sPasteDataHtml = '<div><form enctype="multipart/form-data" method="post"><p>'.Dict::S('UI:CSVImport:PasteData').'</p>'.
 						  '<p><textarea cols="100" rows="30" name="csvdata">'.htmlentities($sCSVData, ENT_QUOTES, 'UTF-8').'</textarea></p>';
 		$sPasteDataHtml .= '<p>'.Dict::S('UI:CSVImport:Encoding').': ';

+ 1 - 1
pages/run_query.php

@@ -100,7 +100,7 @@ $oAppContext = new ApplicationContext();
 $oP = new iTopWebPage(Dict::S('UI:RunQuery:Title'));
 
 // Main program
-$sExpression = utils::ReadParam('expression', '');
+$sExpression = utils::ReadParam('expression', '', false, 'raw_data');
 $sEncoding = utils::ReadParam('encoding', 'oql');
 
 ShowExamples($oP, $sExpression);

+ 2 - 2
portal/index.php

@@ -834,7 +834,7 @@ function DoCloseRequest($oP, UserRequest $oRequest)
 		if ( ($iExpectCode & (OPT_ATT_MUSTCHANGE | OPT_ATT_MUSTPROMPT)) ||
 			 (($iExpectCode & OPT_ATT_MANDATORY) && ($oRequest->Get($sAttCode) == '')) ) 
 		{
-			$value = utils::ReadPostedParam('attr_'.$sAttCode, null);
+			$value = utils::ReadPostedParam('attr_'.$sAttCode, null, 'raw_data');
 			if (!is_null($value))
 			{
 				$oRequest->Set($sAttCode, $value);
@@ -956,7 +956,7 @@ function AddComment($oP, $id)
 		DisplayMainMenu($oP);
 		return;
 	}
-	$sComment = trim(utils::ReadPostedParam('attr_ticket_log'));
+	$sComment = trim(utils::ReadPostedParam('attr_ticket_log', '', 'raw_data'));
 	if (!empty($sComment))
 	{
 		$oRequest->Set('ticket_log', $sComment);

+ 7 - 8
setup/index.php

@@ -416,10 +416,9 @@ function CheckServerConnection(SetupWebPage $oP, $sDBServer, $sDBUser, $sDBPwd)
 function PopulateDataFilesList(SetupWebPage $oP, $aParamValues, $oConfig)
 {
 
-	$oP->add("<script type=\"text/javascript\">\n");
-	$oP->add("function PopulateDataFilesList()\n");
-	$oP->add("{\n");
-	$oP->add("if (aFilesToLoad.length > 0)  return;"); // Populate the list only once...
+	$sScript = "function PopulateDataFilesList()\n";
+	$sScript .= "{\n";
+	$sScript .= "if (aFilesToLoad.length > 0)  return;"; // Populate the list only once...
 
 	$aAvailableModules = AnalyzeInstallation($oConfig);
 
@@ -452,7 +451,7 @@ function PopulateDataFilesList(SetupWebPage $oP, $aParamValues, $oConfig)
 		// Under Windows, it is a must to escape backslashes (not an issue until a folder name starts with t or n, etc...)
 		$sFile = APPROOT.$sFile;
 		$sFile = str_replace('\\', '\\\\', $sFile);
-		$oP->add("aFilesToLoad[aFilesToLoad.length] = '$sFile';\n");
+		$sScript .= "aFilesToLoad[aFilesToLoad.length] = '$sFile';\n";
 	}
 
 	// Sample data - loaded IIF wished by the user
@@ -464,11 +463,11 @@ function PopulateDataFilesList(SetupWebPage $oP, $aParamValues, $oConfig)
 			// Under Windows, it is a must to escape backslashes (not an issue until a folder name starts with t or n, etc...)
 			$sFile = APPROOT.$sFile;
 			$sFile = str_replace('\\', '\\\\', $sFile);
-			$oP->add("aFilesToLoad[aFilesToLoad.length] = '$sFile';\n");
+			$sScript .= "aFilesToLoad[aFilesToLoad.length] = '$sFile';\n";
 		}
 	}
-	$oP->add("}\n");
-	$oP->add("</script>\n");
+	$sScript .= "}\n";
+	$oP->add_script($sScript);
 }
 
 /**

+ 4 - 4
setup/setuppage.class.inc.php

@@ -174,25 +174,25 @@ h3.clickable.open {
 	}
 	public function info($sText)
 	{
-		$this->add("<p class=\"info\">$sText</p>\n");
+		$this->add("<p class=\"info\">".htmlentities($sText, ENT_COMPAT, 'UTF-8')."</p>\n");
 		$this->log_info($sText);
 	}
 	
 	public function ok($sText)
 	{
-		$this->add("<p class=\"ok\">$sText</p>\n");
+		$this->add("<p class=\"ok\">".htmlentities($sText, ENT_COMPAT, 'UTF-8')."</p>\n");
 		$this->log_ok($sText);
 	}
 	
 	public function warning($sText)
 	{
-		$this->add("<p class=\"warning\">$sText</p>\n");
+		$this->add("<p class=\"warning\">".htmlentities($sText, ENT_COMPAT, 'UTF-8')."</p>\n");
 		$this->log_warning($sText);
 	}
 	
 	public function error($sText)
 	{
-		$this->add("<p class=\"error\">$sText</p>\n");
+		$this->add("<p class=\"error\">".htmlentities($sText, ENT_COMPAT, 'UTF-8')."</p>\n");
 		$this->log_error($sText);
 	}
 	

+ 1 - 1
synchro/replica.php

@@ -48,7 +48,7 @@ try
 		break;
 		
 		case 'oql':
-		$sOQL = utils::ReadParam('oql', null);
+		$sOQL = utils::ReadParam('oql', null, false, 'raw_data');
 		if ($sOQL == null)
 		{
 			throw new ApplicationException(Dict::Format('UI:Error:1ParametersMissing', 'oql'));

+ 1 - 1
synchro/synchro_import.php

@@ -273,7 +273,7 @@ else
 	require_once(APPROOT.'/application/loginwebpage.class.inc.php');
 	LoginWebPage::DoLogin(); // Check user rights and prompt if needed
 
-	$sCSVData = utils::ReadPostedParam('csvdata');
+	$sCSVData = utils::ReadPostedParam('csvdata', '', 'raw_data');
 }
 
 

+ 1 - 1
webservices/import.php

@@ -262,7 +262,7 @@ else
 	require_once(APPROOT.'/application/loginwebpage.class.inc.php');
 	LoginWebPage::DoLogin(); // Check user rights and prompt if needed
 
-	$sCSVData = utils::ReadPostedParam('csvdata');
+	$sCSVData = utils::ReadPostedParam('csvdata', '', 'raw_data');
 }