1 /* 2 * reserved comment block 3 * DO NOT REMOVE OR ALTER! 4 */ 5 /** 6 * Licensed to the Apache Software Foundation (ASF) under one 7 * or more contributor license agreements. See the NOTICE file 8 * distributed with this work for additional information 9 * regarding copyright ownership. The ASF licenses this file 10 * to you under the Apache License, Version 2.0 (the 11 * "License"); you may not use this file except in compliance 12 * with the License. You may obtain a copy of the License at 13 * 14 * http://www.apache.org/licenses/LICENSE-2.0 15 * 16 * Unless required by applicable law or agreed to in writing, 17 * software distributed under the License is distributed on an 18 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 19 * KIND, either express or implied. See the License for the 20 * specific language governing permissions and limitations 21 * under the License. 22 */ 23 package com.sun.org.apache.xml.internal.security.transforms.implementations; 24 25 import java.io.OutputStream; 26 27 import javax.xml.transform.TransformerException; 28 29 import com.sun.org.apache.xml.internal.security.exceptions.XMLSecurityRuntimeException; 30 import com.sun.org.apache.xml.internal.security.signature.NodeFilter; 31 import com.sun.org.apache.xml.internal.security.signature.XMLSignatureInput; 32 import com.sun.org.apache.xml.internal.security.transforms.Transform; 33 import com.sun.org.apache.xml.internal.security.transforms.TransformSpi; 34 import com.sun.org.apache.xml.internal.security.transforms.TransformationException; 35 import com.sun.org.apache.xml.internal.security.transforms.Transforms; 36 import com.sun.org.apache.xml.internal.security.utils.Constants; 37 import com.sun.org.apache.xml.internal.security.utils.XMLUtils; 38 import com.sun.org.apache.xml.internal.security.utils.XPathAPI; 39 import com.sun.org.apache.xml.internal.security.utils.XPathFactory; 40 import org.w3c.dom.DOMException; 41 import org.w3c.dom.Element; 42 import org.w3c.dom.Node; 43 44 /** 45 * Class TransformXPath 46 * 47 * Implements the <CODE>http://www.w3.org/TR/1999/REC-xpath-19991116</CODE> 48 * transform. 49 * 50 * @author Christian Geuer-Pollmann 51 * @see <a href="http://www.w3.org/TR/1999/REC-xpath-19991116">XPath</a> 52 * 53 */ 54 public class TransformXPath extends TransformSpi { 55 56 /** Field implementedTransformURI */ 57 public static final String implementedTransformURI = Transforms.TRANSFORM_XPATH; 58 59 /** 60 * Method engineGetURI 61 * 62 * @inheritDoc 63 */ 64 protected String engineGetURI() { 65 return implementedTransformURI; 66 } 67 68 /** 69 * Method enginePerformTransform 70 * @inheritDoc 71 * @param input 72 * 73 * @throws TransformationException 74 */ 75 protected XMLSignatureInput enginePerformTransform( 76 XMLSignatureInput input, OutputStream os, Transform transformObject 77 ) throws TransformationException { 78 try { 79 /** 80 * If the actual input is an octet stream, then the application MUST 81 * convert the octet stream to an XPath node-set suitable for use by 82 * Canonical XML with Comments. (A subsequent application of the 83 * REQUIRED Canonical XML algorithm would strip away these comments.) 84 * 85 * ... 86 * 87 * The evaluation of this expression includes all of the document's nodes 88 * (including comments) in the node-set representing the octet stream. 89 */ 90 Element xpathElement = 91 XMLUtils.selectDsNode( 92 transformObject.getElement().getFirstChild(), Constants._TAG_XPATH, 0); 93 94 if (xpathElement == null) { 95 Object exArgs[] = { "ds:XPath", "Transform" }; 96 97 throw new TransformationException("xml.WrongContent", exArgs); 98 } 99 Node xpathnode = xpathElement.getChildNodes().item(0); 100 String str = XMLUtils.getStrFromNode(xpathnode); 101 input.setNeedsToBeExpanded(needsCircumvent(str)); 102 if (xpathnode == null) { 103 throw new DOMException( 104 DOMException.HIERARCHY_REQUEST_ERR, "Text must be in ds:Xpath" 105 ); 106 } 107 108 XPathFactory xpathFactory = XPathFactory.newInstance(); 109 XPathAPI xpathAPIInstance = xpathFactory.newXPathAPI(); 110 input.addNodeFilter(new XPathNodeFilter(xpathElement, xpathnode, str, xpathAPIInstance)); 111 input.setNodeSet(true); 112 return input; 113 } catch (DOMException ex) { 114 throw new TransformationException("empty", ex); 115 } 116 } 117 118 /** 119 * @param str 120 * @return true if needs to be circumvent for bug. 121 */ 122 private boolean needsCircumvent(String str) { 123 return (str.indexOf("namespace") != -1) || (str.indexOf("name()") != -1); 124 } 125 126 static class XPathNodeFilter implements NodeFilter { 127 128 XPathAPI xPathAPI; 129 Node xpathnode; 130 Element xpathElement; 131 String str; 132 133 XPathNodeFilter(Element xpathElement, Node xpathnode, String str, XPathAPI xPathAPI) { 134 this.xpathnode = xpathnode; 135 this.str = str; 136 this.xpathElement = xpathElement; 137 this.xPathAPI = xPathAPI; 138 } 139 140 /** 141 * @see com.sun.org.apache.xml.internal.security.signature.NodeFilter#isNodeInclude(org.w3c.dom.Node) 142 */ 143 public int isNodeInclude(Node currentNode) { 144 try { 145 boolean include = xPathAPI.evaluate(currentNode, xpathnode, str, xpathElement); 146 if (include) { 147 return 1; 148 } 149 return 0; 150 } catch (TransformerException e) { 151 Object[] eArgs = {currentNode}; 152 throw new XMLSecurityRuntimeException("signature.Transform.node", eArgs, e); 153 } catch (Exception e) { 154 Object[] eArgs = {currentNode, Short.valueOf(currentNode.getNodeType())}; 155 throw new XMLSecurityRuntimeException("signature.Transform.nodeAndType",eArgs, e); 156 } 157 } 158 159 public int isNodeIncludeDO(Node n, int level) { 160 return isNodeInclude(n); 161 } 162 163 } 164 }