diff --git a/hadoop-hdfs-project/hadoop-hdfs/CHANGES.txt b/hadoop-hdfs-project/hadoop-hdfs/CHANGES.txt index 0898deeeb34..95a6b1c380f 100644 --- a/hadoop-hdfs-project/hadoop-hdfs/CHANGES.txt +++ b/hadoop-hdfs-project/hadoop-hdfs/CHANGES.txt @@ -574,6 +574,9 @@ Release 2.0.3-alpha - Unreleased HDFS-3810. Implement format() for BKJM (Ivan Kelly via umamahesh) + HDFS-4162. Some malformed and unquoted HTML strings are returned from + datanode web ui. (Darek Dagit via suresh) + Release 2.0.2-alpha - 2012-09-07 INCOMPATIBLE CHANGES diff --git a/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/server/common/JspHelper.java b/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/server/common/JspHelper.java index a2e0f501bde..3d03447a6c6 100644 --- a/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/server/common/JspHelper.java +++ b/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/server/common/JspHelper.java @@ -408,15 +408,15 @@ public class JspHelper { if (!parts[i].equals("")) { tempPath.append(parts[i]); out.print("" + parts[i] + "" + Path.SEPARATOR); + out.print("\">" + HtmlQuoting.quoteHtmlChars(parts[i]) + "" + Path.SEPARATOR); tempPath.append(Path.SEPARATOR); } } if(parts.length > 0) { - out.print(parts[parts.length-1]); + out.print(HtmlQuoting.quoteHtmlChars(parts[parts.length-1])); } } catch (UnsupportedEncodingException ex) { @@ -431,16 +431,16 @@ public class JspHelper { String nnAddress) throws IOException { out.print("
"); out.print("Goto : "); - out.print(""); - out.print(""); + out.print(""); + out.print(""); out.print(""); + + "value=\"" + namenodeInfoPort + "\"/>"); if (UserGroupInformation.isSecurityEnabled()) { out.print(""); + + "\" type=\"hidden\" value=\"" + tokenString + "\"/>"); } out.print(""); + + "value=\"" + nnAddress + "\"/>"); out.print("
"); } diff --git a/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/server/datanode/DatanodeJspHelper.java b/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/server/datanode/DatanodeJspHelper.java index d19e54e1122..98dceceb5d3 100644 --- a/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/server/datanode/DatanodeJspHelper.java +++ b/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/server/datanode/DatanodeJspHelper.java @@ -43,6 +43,7 @@ import org.apache.hadoop.hdfs.protocol.LocatedBlock; import org.apache.hadoop.hdfs.security.token.block.BlockTokenIdentifier; import org.apache.hadoop.hdfs.security.token.block.BlockTokenSecretManager; import org.apache.hadoop.hdfs.server.common.JspHelper; +import org.apache.hadoop.http.HtmlQuoting; import org.apache.hadoop.http.HttpConfig; import org.apache.hadoop.net.NetUtils; import org.apache.hadoop.security.UserGroupInformation; @@ -119,7 +120,7 @@ public class DatanodeJspHelper { String target = dir; final HdfsFileStatus targetStatus = dfs.getFileInfo(target); if (targetStatus == null) { // not exists - out.print("

File or directory : " + target + " does not exist

"); + out.print("

File or directory : " + StringEscapeUtils.escapeHtml(target) + " does not exist

"); JspHelper.printGotoForm(out, namenodeInfoPort, tokenString, target, nnAddr); } else { @@ -203,7 +204,7 @@ public class DatanodeJspHelper { + JspHelper.getDelegationTokenUrlParam(tokenString) + JspHelper.getUrlParam(JspHelper.NAMENODE_ADDRESS, nnAddr); cols[0] = "" - + localFileName + ""; + + HtmlQuoting.quoteHtmlChars(localFileName) + ""; cols[5] = lsDateFormat.format(new Date((files[i] .getModificationTime()))); cols[6] = files[i].getPermission().toString(); diff --git a/hadoop-hdfs-project/hadoop-hdfs/src/test/java/org/apache/hadoop/hdfs/server/common/TestJspHelper.java b/hadoop-hdfs-project/hadoop-hdfs/src/test/java/org/apache/hadoop/hdfs/server/common/TestJspHelper.java index bad1fff3ef2..ab6ed12492e 100644 --- a/hadoop-hdfs-project/hadoop-hdfs/src/test/java/org/apache/hadoop/hdfs/server/common/TestJspHelper.java +++ b/hadoop-hdfs-project/hadoop-hdfs/src/test/java/org/apache/hadoop/hdfs/server/common/TestJspHelper.java @@ -19,13 +19,20 @@ package org.apache.hadoop.hdfs.server.common; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; +import static org.mockito.Mockito.doAnswer; import java.io.IOException; +import java.io.StringReader; import java.net.InetSocketAddress; import java.util.ArrayList; import javax.servlet.ServletContext; import javax.servlet.http.HttpServletRequest; +import javax.servlet.jsp.JspWriter; +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; +import javax.xml.parsers.ParserConfigurationException; + import org.apache.hadoop.conf.Configuration; import org.apache.hadoop.hdfs.DFSConfigKeys; @@ -46,10 +53,17 @@ import org.apache.hadoop.security.token.TokenIdentifier; import org.apache.hadoop.security.token.delegation.AbstractDelegationTokenSecretManager; import org.junit.Assert; import org.junit.Test; +import org.mockito.ArgumentCaptor; +import org.mockito.invocation.InvocationOnMock; +import org.mockito.stubbing.Answer; +import org.xml.sax.InputSource; +import org.xml.sax.SAXException; + public class TestJspHelper { private Configuration conf = new HdfsConfiguration(); + private String jspWriterOutput = ""; public static class DummySecretManager extends AbstractDelegationTokenSecretManager { @@ -368,7 +382,33 @@ public class TestJspHelper { ae.getMessage()); } } - + + @Test + public void testPrintGotoFormWritesValidXML() throws IOException, + ParserConfigurationException, SAXException { + JspWriter mockJspWriter = mock(JspWriter.class); + ArgumentCaptor arg = ArgumentCaptor.forClass(String.class); + doAnswer(new Answer() { + @Override + public Object answer(InvocationOnMock invok) { + Object[] args = invok.getArguments(); + jspWriterOutput += (String) args[0]; + return null; + } + }).when(mockJspWriter).print(arg.capture()); + + jspWriterOutput = ""; + + JspHelper.printGotoForm(mockJspWriter, 424242, "a token string", + "foobar/file", "0.0.0.0"); + + DocumentBuilder parser = + DocumentBuilderFactory.newInstance().newDocumentBuilder(); + InputSource is = new InputSource(); + is.setCharacterStream(new StringReader(jspWriterOutput)); + parser.parse(is); + } + private HttpServletRequest getMockRequest(String remoteUser, String user, String doAs) { HttpServletRequest request = mock(HttpServletRequest.class); when(request.getParameter(UserParam.NAME)).thenReturn(user);