瀏覽代碼

More fixes for Trac#446: XSS vulnerabilities with vectors containing double quotes

git-svn-id: http://svn.code.sf.net/p/itop/code/trunk@1563 a333f486-631f-4898-b8df-5754b55c2be0
dflaven 13 年之前
父節點
當前提交
32a4ceba39

+ 1 - 1
addons/userrights/userrightsprofile.class.inc.php

@@ -265,7 +265,7 @@ class URP_Profiles extends UserRightsBaseClassGUI
 	
 	function DoShowGrantSumary($oPage)
 	{
-		if ($this->GetName() == "Administrator")
+		if ($this->GetRawName() == "Administrator")
 		{
 			// Looks dirty, but ok that's THE ONE
 			$oPage->p(Dict::S('UI:UserManagement:AdminProfile+'));

+ 1 - 1
addons/userrights/userrightsprojection.class.inc.php

@@ -97,7 +97,7 @@ class URP_Profiles extends UserRightsBaseClass
 	
 	function DoShowGrantSumary($oPage)
 	{
-		if ($this->GetName() == "Administrator")
+		if ($this->GetRawName() == "Administrator")
 		{
 			// Looks dirty, but ok that's THE ONE
 			$oPage->p(Dict::S('UI:UserManagement:AdminProfile+'));

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

@@ -163,7 +163,7 @@ class ApplicationContext
 		$sContext = "";
 		foreach($this->aValues as $sName => $sValue)
 		{
-			$sContext .= "<input type=\"hidden\" name=\"c[$sName]\" value=\"$sValue\" />\n";
+			$sContext .= "<input type=\"hidden\" name=\"c[$sName]\" value=\"".htmlentities($sValue)."\" />\n";
 		}
 		return $sContext;
 	}

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

@@ -581,7 +581,7 @@ abstract class cmdbAbstractObject extends CMDBObject implements iDisplay
 			$oTemplate = new DisplayTemplate($sTemplate);
 			// Note: to preserve backward compatibility with home-made templates, the placeholder '$pkey$' has been preserved
 			//       but the preferred method is to use '$id$'
-			$oTemplate->Render($oPage, array('class_name'=> MetaModel::GetName(get_class($this)),'class'=> get_class($this), 'pkey'=> $this->GetKey(), 'id'=> $this->GetKey(), 'name' => $this->Get('friendlyname')));
+			$oTemplate->Render($oPage, array('class_name'=> MetaModel::GetName(get_class($this)),'class'=> get_class($this), 'pkey'=> $this->GetKey(), 'id'=> $this->GetKey(), 'name' => $this->GetName()));
 		}
 		else
 		{
@@ -1473,14 +1473,14 @@ EOF
 				$aEventsList[] ='validate';
 				$aEventsList[] ='keyup';
 				$aEventsList[] ='change';
-				$sHTMLValue = "<input title=\"$sHelpText\" class=\"date-pick\" type=\"text\" size=\"12\" name=\"attr_{$sFieldPrefix}{$sAttCode}{$sNameSuffix}\" value=\"$value\" id=\"$iId\"/>&nbsp;{$sValidationField}";
+				$sHTMLValue = "<input title=\"$sHelpText\" class=\"date-pick\" type=\"text\" size=\"12\" name=\"attr_{$sFieldPrefix}{$sAttCode}{$sNameSuffix}\" value=\"".htmlentities($value)."\" id=\"$iId\"/>&nbsp;{$sValidationField}";
 				break;
 
 				case 'DateTime':
 				$aEventsList[] ='validate';
 				$aEventsList[] ='keyup';
 				$aEventsList[] ='change';
-				$sHTMLValue = "<input title=\"$sHelpText\" class=\"date-pick\" type=\"text\" size=\"20\" name=\"attr_{$sFieldPrefix}{$sAttCode}{$sNameSuffix}\" value=\"$value\" id=\"$iId\"/>&nbsp;{$sValidationField}";
+				$sHTMLValue = "<input title=\"$sHelpText\" class=\"date-pick\" type=\"text\" size=\"20\" name=\"attr_{$sFieldPrefix}{$sAttCode}{$sNameSuffix}\" value=\"".htmlentities($value)."\" id=\"$iId\"/>&nbsp;{$sValidationField}";
 				break;
 
 				case 'Duration':
@@ -1495,7 +1495,7 @@ EOF
 				$sHours = "<input title=\"$sHelpText\" type=\"text\" size=\"2\" name=\"attr_{$sFieldPrefix}{$sAttCode}[h]{$sNameSuffix}\" value=\"{$aVal['hours']}\" id=\"{$iId}_h\"/>";
 				$sMinutes = "<input title=\"$sHelpText\" type=\"text\" size=\"2\" name=\"attr_{$sFieldPrefix}{$sAttCode}[m]{$sNameSuffix}\" value=\"{$aVal['minutes']}\" id=\"{$iId}_m\"/>";
 				$sSeconds = "<input title=\"$sHelpText\" type=\"text\" size=\"2\" name=\"attr_{$sFieldPrefix}{$sAttCode}[s]{$sNameSuffix}\" value=\"{$aVal['seconds']}\" id=\"{$iId}_s\"/>";
-				$sHidden = "<input type=\"hidden\" id=\"{$iId}\" value=\"$value\"/>";
+				$sHidden = "<input type=\"hidden\" id=\"{$iId}\" value=\"".htmlentities($value)."\"/>";
 				$sHTMLValue = Dict::Format('UI:DurationForm_Days_Hours_Minutes_Seconds', $sDays, $sHours, $sMinutes, $sSeconds).$sHidden."&nbsp;".$sValidationField;
 				$oPage->add_ready_script("$('#{$iId}').bind('update', function(evt, sFormId) { return ToggleDurationField('$iId'); });");				
 				break;
@@ -1504,7 +1504,7 @@ EOF
 					$aEventsList[] ='validate';
 					$aEventsList[] ='keyup';
 					$aEventsList[] ='change';
-					$sHTMLValue = "<input title=\"$sHelpText\" type=\"password\" size=\"30\" name=\"attr_{$sFieldPrefix}{$sAttCode}{$sNameSuffix}\" value=\"$value\" id=\"$iId\"/>&nbsp;{$sValidationField}";
+					$sHTMLValue = "<input title=\"$sHelpText\" type=\"password\" size=\"30\" name=\"attr_{$sFieldPrefix}{$sAttCode}{$sNameSuffix}\" value=\"".htmlentities($value)."\" id=\"$iId\"/>&nbsp;{$sValidationField}";
 				break;
 				
 				case 'Text':
@@ -1528,7 +1528,7 @@ EOF
 					{
 						$sStyle = 'style="'.implode('; ', $aStyles).'"';
 					}
-					$sHTMLValue = "<table><tr><td><textarea class=\"resizable\" title=\"$sHelpText\" name=\"attr_{$sFieldPrefix}{$sAttCode}{$sNameSuffix}\" rows=\"8\" cols=\"40\" id=\"$iId\" $sStyle>$sEditValue</textarea></td><td>{$sValidationField}</td></tr></table>";
+					$sHTMLValue = "<table><tr><td><textarea class=\"resizable\" title=\"$sHelpText\" name=\"attr_{$sFieldPrefix}{$sAttCode}{$sNameSuffix}\" rows=\"8\" cols=\"40\" id=\"$iId\" $sStyle>".htmlentities($sEditValue)."</textarea></td><td>{$sValidationField}</td></tr></table>";
 				break;
 
 				case 'CaseLog':
@@ -1553,7 +1553,7 @@ EOF
 					$sPreviousLog = is_object($value) ? $value->GetAsHTML() : '';
 					$iEntriesCount = is_object($value) ? count($value->GetIndex()) : 0;
 					$sHidden = "<input type=\"hidden\" id=\"{$iId}_count\" value=\"$iEntriesCount\"/>"; // To know how many entries the case log already contains
-					$sHTMLValue = "<div class=\"caselog\" $sStyle><table style=\"width:100%;\"><tr><td>$sHeader<textarea style=\"border:0;width:100%\" title=\"$sHelpText\" name=\"attr_{$sFieldPrefix}{$sAttCode}{$sNameSuffix}\" rows=\"8\" cols=\"40\" id=\"$iId\">$sEditValue</textarea>$sPreviousLog</td><td>{$sValidationField}</td></tr></table>$sHidden</div>";
+					$sHTMLValue = "<div class=\"caselog\" $sStyle><table style=\"width:100%;\"><tr><td>$sHeader<textarea style=\"border:0;width:100%\" title=\"$sHelpText\" name=\"attr_{$sFieldPrefix}{$sAttCode}{$sNameSuffix}\" rows=\"8\" cols=\"40\" id=\"$iId\">".htmlentities($sEditValue)."</textarea>$sPreviousLog</td><td>{$sValidationField}</td></tr></table>$sHidden</div>";
 					$oPage->add_ready_script("$('#$iId').bind('keyup change validate', function(evt, sFormId) { return ValidateCaseLogField('$iId', $bMandatory, sFormId) } );"); // Custom validation function
 				break;
 
@@ -1580,7 +1580,7 @@ EOF
 					}
 					$iMaxFileSize = utils::ConvertToBytes(ini_get('upload_max_filesize'));
 					$sHTMLValue = "<input type=\"hidden\" name=\"MAX_FILE_SIZE\" value=\"$iMaxFileSize\" />\n";
-					$sHTMLValue .= "<input name=\"attr_{$sFieldPrefix}{$sAttCode}{$sNameSuffix}[filename]\" type=\"hidden\" id=\"$iId\" \" value=\"$sFileName\"/>\n";
+					$sHTMLValue .= "<input name=\"attr_{$sFieldPrefix}{$sAttCode}{$sNameSuffix}[filename]\" type=\"hidden\" id=\"$iId\" \" value=\"".htmlentities($sFileName)."\"/>\n";
 					$sHTMLValue .= "<span id=\"name_$iInputId\">$sFileName</span><br/>\n";
 					$sHTMLValue .= "<input title=\"$sHelpText\" name=\"attr_{$sFieldPrefix}{$sAttCode}{$sNameSuffix}[fcontents]\" type=\"file\" id=\"file_$iId\" onChange=\"UpdateFileName('$iId', this.value)\"/>&nbsp;{$sValidationField}\n";
 				break;
@@ -1654,7 +1654,7 @@ EOF
 					}
 					else
 					{
-						$sHTMLValue = "<input title=\"$sHelpText\" type=\"text\" size=\"30\" maxlength=\"$iFieldSize\" name=\"attr_{$sFieldPrefix}{$sAttCode}{$sNameSuffix}\" value=\"$value\" id=\"$iId\"/>&nbsp;{$sValidationField}";
+						$sHTMLValue = "<input title=\"$sHelpText\" type=\"text\" size=\"30\" maxlength=\"$iFieldSize\" name=\"attr_{$sFieldPrefix}{$sAttCode}{$sNameSuffix}\" value=\"".htmlentities($value)."\" id=\"$iId\"/>&nbsp;{$sValidationField}";
 						$aEventsList[] ='keyup';
 						$aEventsList[] ='change';
 					}

+ 2 - 2
application/displayblock.class.inc.php

@@ -1034,7 +1034,7 @@ class HistoryBlock extends DisplayBlock
 		$aValues = array();
 		foreach($aChanges as $aChange)
 		{
-			$aValues[] = array('date' => $aChange['date'], 'userinfo' => $aChange['userinfo'], 'log' => "<ul><li>".implode('</li><li>', $aChange['log'])."</li></ul>");
+			$aValues[] = array('date' => $aChange['date'], 'userinfo' => htmlentities($aChange['userinfo']), 'log' => "<ul><li>".implode('</li><li>', $aChange['log'])."</li></ul>");
 		}
 		$sHtml .= $oPage->GetTable($aAttribs, $aValues);
 		return $sHtml;
@@ -1135,7 +1135,7 @@ class MenuBlock extends DisplayBlock
 				$this->AddMenuSeparator($aActions);
 				// Static menus: Email this page & CSV Export
 				$sUrl = ApplicationContext::MakeObjectUrl($sClass, $id);
-				$aActions['UI:Menu:EMail'] = array ('label' => Dict::S('UI:Menu:EMail'), 'url' => "mailto:?subject=".$oObj->GetName()."&body=".urlencode($sUrl));
+				$aActions['UI:Menu:EMail'] = array ('label' => Dict::S('UI:Menu:EMail'), 'url' => "mailto:?subject=".urlencode($oObj->GetRawName())."&body=".urlencode($sUrl));
 				$aActions['UI:Menu:CSVExport'] = array ('label' => Dict::S('UI:Menu:CSVExport'), 'url' => "{$sRootUrl}pages/$sUIPage?operation=search&filter=$sFilter&format=csv{$sContext}");
 			}
 			$this->AddMenuSeparator($aActions);

+ 0 - 1
application/loginwebpage.class.inc.php

@@ -141,7 +141,6 @@ EOF
 	public function DisplayChangePwdForm($bFailedLogin = false)
 	{
 		$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');

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

@@ -288,7 +288,7 @@ EOF
 				{
 					$aRow = array();
 					
-					$aRow['key'] = '<a href="./index.php?operation=details&class='.get_class($oObj).'&id='.$oObj->GetKey().'">'.$oObj->Get('friendlyname').'</a>';
+					$aRow['key'] = '<a href="./index.php?operation=details&class='.get_class($oObj).'&id='.$oObj->GetKey().'">'.$oObj->GetName().'</a>';
 					$sHilightClass = $oObj->GetHilightClass();
 					if ($sHilightClass != '')
 					{

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

@@ -133,7 +133,7 @@ class UIExtKeyWidget
 				$aAllowedValues = array();
 				while($oObj = $oAllowedValues->Fetch())
 				{
-					$aAllowedValues[$oObj->GetKey()] = $oObj->Get('friendlyname');
+					$aAllowedValues[$oObj->GetKey()] = $oObj->GetName();
 				}				
 				$sHTMLValue = $oPage->GetRadioButtons($aAllowedValues, $value, $this->iId, "{$sAttrFieldPrefix}{$sFieldName}", $bMandatory, $bVertical, $sValidationField);
 				$aEventsList[] ='change';
@@ -159,7 +159,7 @@ class UIExtKeyWidget
 				while($oObj = $oAllowedValues->Fetch())
 				{
 					$key = $oObj->GetKey();
-					$display_value = $oObj->Get('friendlyname');
+					$display_value = $oObj->GetName();
 	
 					if (($oAllowedValues->Count() == 1) && ($bMandatory == 'true') )
 					{
@@ -326,11 +326,11 @@ EOF
 		{
 			throw new Exception('Implementation: null value for allowed values definition');
 		}
-		$oValuesSet = new ValueSetObjects($sFilter);
+		$oValuesSet = new ValueSetObjects($sFilter, 'friendlyname'); // Bypass GetName() to avoid the encoding by htmlentities
 		$aValues = $oValuesSet->GetValues(array('this' => $oObj), $sContains);
 		foreach($aValues as $sKey => $sFriendlyName)
 		{
-			$oP->add(trim($sFriendlyName)."|".$sKey."\n");
+			$oP->add(trim($sFriendlyName)."\t".$sKey."\n");
 		}
 	}
 	

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

@@ -85,7 +85,7 @@ class UILinksWizard
 		$sTargetClass = $oAttDef->GetTargetClass();
 		$oTargetObj = MetaModel::GetObject($sTargetClass, $this->m_iObjectId);
 
-		$oP->set_title("iTop - ".MetaModel::GetName($this->m_sLinkedClass)." objects linked with ".MetaModel::GetName(get_class($oTargetObj)).": ".$oTargetObj->GetName());
+		$oP->set_title("iTop - ".MetaModel::GetName($this->m_sLinkedClass)." objects linked with ".MetaModel::GetName(get_class($oTargetObj)).": ".$oTargetObj->GetRawName());
 		$oP->add("<div class=\"wizContainer\">\n");
 		$oP->add("<form method=\"post\">\n");
 		$oP->add("<div class=\"page_header\">\n");

+ 16 - 0
core/dbobject.class.php

@@ -622,8 +622,24 @@ abstract class DBObject
 		return MetaModel::GetClassIcon(get_class($this), $bImgTag);
 	}
 
+	/**
+	 * Gets the name of an object in a safe manner for displaying inside a web page
+	 * @return string
+	 */
 	public function GetName()
 	{
+		return htmlentities($this->GetRawName(), ENT_QUOTES, 'UTF-8');
+	}
+
+	/**
+	 * Gets the raw name of an object, this is not safe for displaying inside a web page
+	 * since the " < > characters are not escaped and the name may contain some XSS script
+	 * instructions.
+	 * Use this function only for internal computations or for an output to a non-HTML destination
+	 * @return string
+	 */
+	public function GetRawName()
+	{
 		return $this->Get('friendlyname');
 	}
 

+ 1 - 1
core/valuesetdef.class.inc.php

@@ -251,7 +251,7 @@ class ValueSetRelatedObjectsFromLinkSet extends ValueSetDefinition
 			}
 			// #@# or AddObjectArray($aObjects) ?
 			$oSetToCreate = DBObjectSet::FromArray($this->m_sTargetLinkClass, $aLinksToCreate);
-			$this->m_aValues[$oObject->GetKey()] = $oObject->GetAsHTML($oObject->GetName());
+			$this->m_aValues[$oObject->GetKey()] = $oObject->GetName();
 		}
 
 		return true;

+ 1 - 1
js/extkeywidget.js

@@ -354,7 +354,7 @@ function ExtKeyWidget(id, sTargetClass, sFilter, sTitle, bSelectMode, oWizHelper
 					if (me.bSelectMode)
 					{
 						// Add the newly created object to the drop-down list and select it
-						$('<option/>', { value : data.id }).text(data.name).appendTo('#'+me.id);
+						$('<option/>', { value : data.id }).html(data.name).appendTo('#'+me.id);
 						$('#'+me.id+' option[value="'+data.id+'"]').attr('selected', 'selected');
 						$('#'+me.id).focus();
 					}

+ 3 - 1
js/jquery.autocomplete.js

@@ -388,7 +388,7 @@ $.Autocompleter = function(input, options) {
 		for (var i=0; i < rows.length; i++) {
 			var row = $.trim(rows[i]);
 			if (row) {
-				row = row.split("|");
+				row = row.split("\t");
 				parsed[parsed.length] = {
 					data: row,
 					value: row[0],
@@ -668,6 +668,8 @@ $.Autocompleter.Select = function (options, input, select, config) {
 			var formatted = options.formatItem(data[i].data, i+1, max, data[i].value, term);
 			if ( formatted === false )
 				continue;
+			// Escape dangerous characters to prevent XSS vulnerabilities
+			formatted = formatted.replace('&', '&amp;').replace('"', '&quot;').replace('>', '&gt;').replace('<', '&lt;');
 			var li = $("<li/>").html( options.highlight(formatted, term) ).addClass(i%2 == 0 ? "ac_even" : "ac_odd").appendTo(list)[0];
 			$.data(li, "ac_data", data[i]);
 		}

+ 6 - 6
pages/UI.php

@@ -424,7 +424,7 @@ function DisplayDetails($oP, $sClass, $oObj, $id)
 	{
 		throw new SecurityException('User not allowed to view this object', array('class' => $sClass, 'id' => $id));
 	}
-	$oP->set_title(Dict::Format('UI:DetailsPageTitle', $oObj->GetName(), $sClassLabel));
+	$oP->set_title(Dict::Format('UI:DetailsPageTitle', $oObj->GetRawName(), $sClassLabel)); // Set title will take care of the encoding
 	$oObj->DisplayDetails($oP);
 }
 
@@ -780,7 +780,7 @@ try
 					throw new SecurityException('User not allowed to modify this object', array('class' => $sClass, 'id' => $id));
 				}
 				// Note: code duplicated to the case 'apply_modify' when a data integrity issue has been found
-				$oP->set_title(Dict::Format('UI:ModificationPageTitle_Object_Class', $oObj->GetName(), $sClassLabel));
+				$oP->set_title(Dict::Format('UI:ModificationPageTitle_Object_Class', $oObj->GetRawName(), $sClassLabel)); // Set title will take care of the encoding
 				$oP->add("<div class=\"page_header\">\n");
 				$oP->add("<h1>".$oObj->GetIcon()."&nbsp;".Dict::Format('UI:ModificationTitle_Class_Object', $sClassLabel, $oObj->GetName())."</h1>\n");
 				$oP->add("</div>\n");
@@ -1226,7 +1226,7 @@ EOF
 			}
 			elseif (!utils::IsTransactionValid($sTransactionId, false))
 			{
-				$oP->set_title(Dict::Format('UI:ModificationPageTitle_Object_Class', $oObj->GetName(), $sClassLabel));
+				$oP->set_title(Dict::Format('UI:ModificationPageTitle_Object_Class', $oObj->GetRawName(), $sClassLabel)); // Set title will take care of the encoding
 				$oP->p("<strong>".Dict::S('UI:Error:ObjectAlreadyUpdated')."</strong>\n");
 			}
 			else
@@ -1236,7 +1236,7 @@ EOF
 
 				if (!$oObj->IsModified())
 				{
-					$oP->set_title(Dict::Format('UI:ModificationPageTitle_Object_Class', $oObj->GetName(), $sClassLabel));
+					$oP->set_title(Dict::Format('UI:ModificationPageTitle_Object_Class', $oObj->GetRawName(), $sClassLabel)); // Set title will take care of the encoding
 					$oP->p(Dict::Format('UI:Class_Object_NotUpdated', MetaModel::GetName(get_class($oObj)), $oObj->GetName()));
 				}
 				else
@@ -1244,7 +1244,7 @@ EOF
 					list($bRes, $aIssues) = $oObj->CheckToWrite();
 					if ($bRes)
 					{
-						$oP->set_title(Dict::Format('UI:ModificationPageTitle_Object_Class', $oObj->GetName(), $sClassLabel));
+						$oP->set_title(Dict::Format('UI:ModificationPageTitle_Object_Class', $oObj->GetRawName(), $sClassLabel)); // Set title will take care of the encoding
 						$oP->add("<h1>".Dict::Format('UI:ModificationTitle_Class_Object', $sClassLabel, $oObj->GetName())."</h1>\n");
 
 						$oMyChange = MetaModel::NewObject("CMDBChange");
@@ -1262,7 +1262,7 @@ EOF
 						$bDisplayDetails = false;
 						// Found issues, explain and give the user a second chance
 						//
-						$oP->set_title(Dict::Format('UI:ModificationPageTitle_Object_Class', $oObj->GetName(), $sClassLabel));
+						$oP->set_title(Dict::Format('UI:ModificationPageTitle_Object_Class', $oObj->GetRawName(), $sClassLabel)); // Set title will take care of the encoding
 						$oP->add("<div class=\"page_header\">\n");
 						$oP->add("<h1>".$oObj->GetIcon()."&nbsp;".Dict::Format('UI:ModificationTitle_Class_Object', $sClassLabel, $oObj->GetName())."</h1>\n");
 						$oP->add("</div>\n");

+ 1 - 1
pages/audit.php

@@ -199,7 +199,7 @@ try
 			while($oAuditRule = $oRulesSet->fetch() )
 			{
 				$aRow = array();
-				$aRow['description'] = $oAuditRule->Get('name');
+				$aRow['description'] = $oAuditRule->GetName();
 				if ($iCount == 0)
 				{
 					// nothing to check, really !

+ 5 - 5
pages/xml.navigator.php

@@ -77,8 +77,8 @@ function GetRelatedObjectsAsXml(DBObject $oObj, $sRelationName, &$oLinks, &$oXml
 				$oLinkedNode = $oXmlDoc->CreateElement('node');
 				$oLinkedNode->SetAttribute('id', $oTargetObj->GetKey());
 				$oLinkedNode->SetAttribute('obj_class', get_class($oTargetObj));
-				$oLinkedNode->SetAttribute('obj_class_name', MetaModel::GetName(get_class($oTargetObj)));
-				$oLinkedNode->SetAttribute('name', $oTargetObj->GetName());
+				$oLinkedNode->SetAttribute('obj_class_name', htmlspecialchars(MetaModel::GetName(get_class($oTargetObj))));
+				$oLinkedNode->SetAttribute('name', htmlspecialchars($oTargetObj->GetRawName())); // htmlentities is too much for XML
 				$oLinkedNode->SetAttribute('icon', BuildIconPath($oTargetObj->GetIcon(false /* No IMG tag */)));
 				AddNodeDetails($oLinkedNode, $oTargetObj);
 				$oSubLinks = $oXmlDoc->CreateElement('links');
@@ -158,15 +158,15 @@ try
 			$oXmlNode = $oXmlDoc->CreateElement('node');
 			$oXmlNode->SetAttribute('id', $oObj->GetKey());
 			$oXmlNode->SetAttribute('obj_class', get_class($oObj));
-			$oXmlNode->SetAttribute('obj_class_name', MetaModel::GetName(get_class($oObj)));
-			$oXmlNode->SetAttribute('name', $oObj->GetName());
+			$oXmlNode->SetAttribute('obj_class_name', htmlspecialchars(MetaModel::GetName(get_class($oObj))));
+			$oXmlNode->SetAttribute('name',  htmlspecialchars($oObj->GetRawName()));
 			$oXmlNode->SetAttribute('icon', BuildIconPath($oObj->GetIcon(false /* No IMG tag */))); // Hard coded for the moment
 			AddNodeDetails($oXmlNode, $oObj);
 			
 			$oLinks = $oXmlDoc->CreateElement("links");
 		
 			$oXmlRoot->SetAttribute('position', 'left');
-			$oXmlRoot->SetAttribute('title', MetaModel::GetRelationDescription($sRelation).' '.$oObj->GetName());
+			$oXmlRoot->SetAttribute('title', MetaModel::GetRelationDescription($sRelation).' '. htmlspecialchars($oObj->GetRawName()));
 			GetRelatedObjectsAsXml($oObj, $sRelation, $oLinks, $oXmlDoc, $oXmlNode);
 			
 			$oXmlRoot->AppendChild($oXmlNode);

+ 1 - 1
webservices/webservices.class.inc.php

@@ -135,7 +135,7 @@ class WebServiceResult
 	{
 		$this->m_aResult[$sLabel] = array(
 			'id' => $oObject->GetKey(),
-			'name' => $oObject->GetName(),
+			'name' => $oObject->GetRawName(),
 			'url' => $oObject->GetHyperlink(),
 		);
 	}