diff --git a/cas-client-core/src/main/java/org/jasig/cas/client/util/XmlUtils.java b/cas-client-core/src/main/java/org/jasig/cas/client/util/XmlUtils.java index 064ccd0..62abfdf 100644 --- a/cas-client-core/src/main/java/org/jasig/cas/client/util/XmlUtils.java +++ b/cas-client-core/src/main/java/org/jasig/cas/client/util/XmlUtils.java @@ -21,6 +21,8 @@ package org.jasig.cas.client.util; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; +import org.w3c.dom.Document; +import org.w3c.dom.NodeList; import org.xml.sax.Attributes; import org.xml.sax.InputSource; import org.xml.sax.SAXException; @@ -28,6 +30,10 @@ import org.xml.sax.XMLReader; import org.xml.sax.helpers.DefaultHandler; import org.xml.sax.helpers.XMLReaderFactory; +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; +import javax.xml.parsers.ParserConfigurationException; +import java.io.IOException; import java.io.StringReader; import java.util.ArrayList; import java.util.List; @@ -171,4 +177,27 @@ public final class XmlUtils { return builder.toString(); } + + /** + * Retrieve the child nodes from xml string, for a specific element. + * + * @param xmlAsString the xml response + * @param tagName the element to look for + * @return the {@link org.w3c.dom.NodeList NodeList} containing the child nodes. + * @throws ParserConfigurationException + * @throws IOException + * @throws SAXException + */ + public static NodeList getNodeListForElements(final String xmlAsString, final String tagName) + throws ParserConfigurationException, + IOException, + SAXException { + + final DocumentBuilder documentBuilder = DocumentBuilderFactory.newInstance().newDocumentBuilder(); + final InputSource inStream = new InputSource(); + inStream.setCharacterStream(new StringReader(xmlAsString)); + final Document document = documentBuilder.parse(inStream); + + return document.getElementsByTagName(tagName).item(0).getChildNodes(); + } } diff --git a/cas-client-core/src/main/java/org/jasig/cas/client/validation/Cas20ServiceTicketValidator.java b/cas-client-core/src/main/java/org/jasig/cas/client/validation/Cas20ServiceTicketValidator.java index c007282..7255361 100644 --- a/cas-client-core/src/main/java/org/jasig/cas/client/validation/Cas20ServiceTicketValidator.java +++ b/cas-client-core/src/main/java/org/jasig/cas/client/validation/Cas20ServiceTicketValidator.java @@ -26,14 +26,10 @@ import org.jasig.cas.client.proxy.ProxyGrantingTicketStorage; import org.jasig.cas.client.proxy.ProxyRetriever; import org.jasig.cas.client.util.CommonUtils; import org.jasig.cas.client.util.XmlUtils; +import org.w3c.dom.NodeList; -import java.io.BufferedReader; -import java.io.IOException; -import java.io.StringReader; -import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; -import java.util.List; import java.util.Map; /** @@ -115,6 +111,11 @@ public class Cas20ServiceTicketValidator extends AbstractCasProtocolUrlBasedTick * <cas:attribute2>value</cas:attribute2> * </cas:attributes> *

+ * + * Attributes look like following also parsed correctly: + * <cas:attributes><cas:attribute1>value</cas:attribute1><cas:attribute2>value</cas:attribute2></cas:attributes> + *

+ * * This code is here merely for sample/demonstration purposes for those wishing to modify the CAS2 protocol. You'll * probably want a more robust implementation or to use SAML 1.1 * @@ -122,45 +123,29 @@ public class Cas20ServiceTicketValidator extends AbstractCasProtocolUrlBasedTick * @return the map of attributes. */ protected Map extractCustomAttributes(final String xml) { - final int pos1 = xml.indexOf(""); - final int pos2 = xml.indexOf(""); - - if (pos1 == -1) { + + if (!xml.contains("")) { return Collections.emptyMap(); } - - final String attributesText = xml.substring(pos1+16, pos2); - - final Map attributes = new HashMap(); - final BufferedReader br = new BufferedReader(new StringReader(attributesText)); - - String line; - final List attributeNames = new ArrayList(); - try { - while ((line = br.readLine()) != null) { - final String trimmedLine = line.trim(); - if (trimmedLine.length() > 0) { - final int leftPos = trimmedLine.indexOf(":"); - final int rightPos = trimmedLine.indexOf(">"); - attributeNames.add(trimmedLine.substring(leftPos+1, rightPos)); - } - } - br.close(); - } catch (final IOException e) { - //ignore - } - for (final String name : attributeNames) { - final List values = XmlUtils.getTextForElements(xml, name); + final Map attributes = new HashMap(); - if (values.size() == 1) { - attributes.put(name, values.get(0)); - } else { - attributes.put(name, values); + try { + NodeList nodeList = XmlUtils.getNodeListForElements(xml,"cas:attributes"); + for (int i = 0; i < nodeList.getLength(); i++) { + final String nodeName = nodeList.item(i).getNodeName(); + final int beginIndex = nodeName.indexOf(":") + 1; + final int endIndex = nodeList.item(i).getNodeName().length(); + + final String attributeName = nodeName.substring(beginIndex, endIndex); // remove the "cas:" prefix from node name + final Object attributeValue = nodeList.item(i).getTextContent(); + attributes.put(attributeName, attributeValue); } - } - - return attributes; + return attributes; + + } catch (Exception e) { + return Collections.emptyMap(); + } } /** diff --git a/cas-client-core/src/test/java/org/jasig/cas/client/validation/Cas20ServiceTicketValidatorTests.java b/cas-client-core/src/test/java/org/jasig/cas/client/validation/Cas20ServiceTicketValidatorTests.java index cf31da4..c250969 100644 --- a/cas-client-core/src/test/java/org/jasig/cas/client/validation/Cas20ServiceTicketValidatorTests.java +++ b/cas-client-core/src/test/java/org/jasig/cas/client/validation/Cas20ServiceTicketValidatorTests.java @@ -139,7 +139,7 @@ public final class Cas20ServiceTicketValidatorTests extends AbstractTicketValida + USERNAME + "" + PGTIOU - + "\ntest\nid\n"; + + "testid"; server.content = RESPONSE.getBytes(server.encoding); final Assertion assertion = this.ticketValidator.validate("test", "test");