package com.grendelscan.commons.html; // TODO UCdetector: Remove unused code: // /** // * Compares the DOM structure of two nodes (which could be // * documents also). Does not detect duplicate nodes. This // * can be used to find subtle changes between different // * requests. There are many possible uses. For example, // * finding the session ids in URLs that change between login // * requests. Finding different text results between queries // * can help with SQL Injection testing. // * // * // * @author David Byrne // */ // public class CompareDom // { // Node masterOriginalNode, masterCandidateNode; // // // Contains all of the nodes by node name, then by node // // hash to prevent dups // HashMap<String, HashMap<String, Node>> originalNodes, candidateNodes; // // /** // * When compairing multiple nodes to an original, use // * {@link setCandidateNode(Node candidateDocument) setCandidateNode} // * to compare each candidate node. This will save time // * because the original node will not need to be // * re-parsed. // * // * @param originalNode // * The node against which comparisons are // * made. // * @param candidateNode // * The node that will be compared against // * originalNode. // * // */ // public CompareDom(Node originalNode, Node candiateNode) // { // masterOriginalNode = originalNode; // masterCandidateNode = candiateNode; // originalNodes = splitDom(originalNode); // originalNodes = splitDom(masterCandidateNode); // } // // /** // * Returns a HashSet of nodes from the candidate node // * that appear similar to specified node. Currently, // * only the node and attributes are compared. Child // * nodes are not analyzed. // */ // public Set<Node> findSimilarInCandidate(Node node, int maxMatches) // { // return findSimilarInTarget(node, candidateNodes, maxMatches); // } // // /** // * Returns a HashSet of nodes from the original node // * that appear similar to specified node. Currently, // * only the node and attributes are compared. Child // * nodes are not analyzed. // * // * @param node // * The node to compare against in finding // * matches // * @param maxMatches // * Limits the returned values to the top // * "maxMatches" results. // */ // public Set<Node> findSimilarInOriginal(Node node, int maxMatches) // { // return findSimilarInTarget(node, originalNodes, maxMatches); // } // // public Node getCandidateNode() // { // return masterCandidateNode; // } // // public Node getOriginalNode() // { // return masterOriginalNode; // } // // /** // * Returns a HashSet of all nodes that are in the // * candidate node, but not the original node. // * // * Supports Node.DOCUMENT_TYPE_NODE, Node.ELEMENT_NODE, // * Node.TEXT_NODE, and Node.COMMENT_NODE // * // */ // public HashSet<Node> inCandidateNotOriginal() // { // return compare(originalNodes, candidateNodes); // } // // /** // * Returns a HashSet of nodes matching the specified // * node name that are in the candidate node, but not the // * original node. // * // * Supports Node.DOCUMENT_TYPE_NODE, Node.ELEMENT_NODE, // * Node.TEXT_NODE, Node.COMMENT_NODE, and any tag name // * // * @param nodeName // * The name of the node type to search for. // * For a complete list, see the w3c // * documentation for Node // */ // public HashSet<Node> inCandidateNotOriginal(String nodeName) // { // return compareNodeCategory(originalNodes, candidateNodes, nodeName); // } // // /** // * Returns a HashSet of all nodes that are in the // * original node, but not the candidate node. // * // */ // public HashSet<Node> inOriginalNotCandidate() // { // return compare(candidateNodes, originalNodes); // } // // /** // * Returns a HashSet of nodes matching the specified // * node name that are in the original node, but not the // * candidate node. // * // * Supports Node.DOCUMENT_TYPE_NODE, Node.ELEMENT_NODE, // * Node.TEXT_NODE, and Node.COMMENT_NODE // * // * @param nodeName // * The name of the node type to search for. // * For a complete list, see the w3c // * documentation for Node // * // */ // public HashSet<Node> inOriginalNotCandidate(String nodeName) // { // return compareNodeCategory(candidateNodes, originalNodes, nodeName); // } // // public void setCandidateNode(Node candidateNode) // { // masterCandidateNode = candidateNode; // } // // private void addNode(Node target, HashMap<String, HashMap<String, Node>> nodes) // { // String nodeName = target.getNodeName(); // String hash = HtmlNodeUtilities.getNodeHash(target, false); // HashMap<String, Node> nodeCategory; // // if (nodes.containsKey(nodeName)) // { // nodeCategory = nodes.get(nodeName); // if (!nodeCategory.containsKey(hash)) // { // nodeCategory.put(hash, target); // } // } // else // { // nodeCategory = new HashMap<String, Node>(); // nodeCategory.put(hash, target); // nodes.put(nodeName, nodeCategory); // } // } // // /** // * Returns a set of all nodes that are in targetB, but // * not in targetA // */ // private HashSet<Node> compare(HashMap<String, HashMap<String, Node>> targetA, HashMap<String, HashMap<String, Node>> targetB) // { // HashSet<Node> nodes = new HashSet<Node>(); // // for (String nodeName: targetB.keySet()) // { // nodes.addAll(compareNodeCategory(targetA, targetB, nodeName)); // } // return nodes; // } // // private HashSet<Node> compareNodeCategory(HashMap<String, HashMap<String, Node>> targetA, HashMap<String, HashMap<String, Node>> targetB, String nodeName) // { // HashSet<Node> nodes = new HashSet<Node>(); // HashMap<String, Node> nodeCategoryA, nodeCategoryB; // nodeCategoryB = targetB.get(nodeName); // if (targetA.containsKey(nodeName)) // { // nodeCategoryA = targetA.get(nodeName); // for (String node: nodeCategoryB.keySet()) // { // if (!nodeCategoryA.containsKey(node)) // { // nodes.add(nodeCategoryB.get(node)); // } // } // } // else // { // for (String node: nodeCategoryB.keySet()) // { // nodes.add(nodeCategoryB.get(node)); // } // } // return nodes; // } // // private Set<Node> findSimilarInTarget(Node originalNode, HashMap<String, HashMap<String, Node>> targetNodes, int maxMatches) // { // int lowestGoodScore = 0; // int nodeScore; // HashMap<Node, Integer> resultNodes = new HashMap<Node, Integer>(); // HashMap<String, Node> candidates = targetNodes.get(originalNode.getNodeName()); // // for (Node candidateNode: candidates.values()) // { // nodeScore = scoreNode(originalNode, candidateNode); // if (resultNodes.size() < maxMatches) // { // resultNodes.put(candidateNode, nodeScore); // } // else if (nodeScore > lowestGoodScore) // { // for (Node node: resultNodes.keySet()) // { // if (resultNodes.get(node) < nodeScore) // { // resultNodes.remove(node); // resultNodes.put(candidateNode, nodeScore); // lowestGoodScore = nodeScore; // break; // } // } // } // } // // return resultNodes.keySet(); // } // // private int[] scoreAttribute(Attr originalAttribute, Attr candidateAttribute) // { // int score[]; // // String name = originalAttribute.getName().toLowerCase(); // // if (name.equals("href") || name.equals("src")) // { // score = scoreUriAttribute(originalAttribute, candidateAttribute); // } // else if (name.startsWith("on")) // { // score = scoreEventAttribute(originalAttribute, candidateAttribute); // } // else // { // score = scoreSimpleAttribute(originalAttribute, candidateAttribute); // } // // return score; // } // // private int scoreElement(Node original, Node candidate) // { // int score = 0; // int maxScore = 0; // int returnedScore[] = new int[2]; // // NamedNodeMap originalAttributes = original.getAttributes(); // NamedNodeMap candidateAttributes = candidate.getAttributes(); // // for (int index = 0; index < originalAttributes.getLength(); index++) // { // // Three points for a matching attribute value, // // one point for a matching name only // maxScore += 4; // Attr originalAttribute = (Attr) originalAttributes.item(index); // Attr candidateAttribute = (Attr) candidateAttributes.getNamedItem(originalAttribute.getName()); // if (candidateAttribute != null) // { // returnedScore = scoreAttribute(originalAttribute, candidateAttribute); // score += returnedScore[0]; // maxScore += returnedScore[1]; // } // } // // return score; // } // // /** // * Same scoring technique as scoreSimpleAttribute, but // * with up to 10 points for a perfect match // */ // private int[] scoreEventAttribute(Attr originalAttribute, Attr candidateAttribute) // { // int finalScore[] = new int[2]; // // finalScore = scoreSimpleAttribute(originalAttribute, candidateAttribute); // finalScore[1] = 10; // // return finalScore; // } // // /** // * Currently, this will only compare the node and // * attributes. Child nodes are not analyzed. // */ // private int scoreNode(Node original, Node candidate) // { // int score = 0; // // switch (original.getNodeType()) // { // // case Node.ELEMENT_NODE: // { // score = scoreElement(original, candidate); // break; // } // } // return score; // } // // /** // * Up to 5 points for a perfect match // */ // private int[] scoreSimpleAttribute(Attr originalAttribute, Attr candidateAttribute) // { // int finalScore[] = new int[2]; // int score = 0; // int maxLength; // int levenshteinDistance; // String originalValue; // String candidateValue; // float scaleIncrement; // // if ((originalAttribute == null) || (candidateAttribute == null)) // { // score = 0; // } // else // { // originalValue = originalAttribute.getValue(); // candidateValue = candidateAttribute.getValue(); // // if (originalValue.equals(candidateValue)) // { // score = 5; // } // else if (originalValue.equalsIgnoreCase(candidateValue)) // { // score = 4; // } // else // { // if (originalValue.length() > candidateValue.length()) // { // maxLength = originalValue.length(); // } // else // { // maxLength = candidateValue.length(); // } // // score = StringUtils.scoreStringDifferenceIgnoreCase(originalValue, candidateValue, 4); // /* // levenshteinDistance = StringUtilities.getLevenshteinDistance(originalValue, candidateValue); // scaleIncrement = (maxLength - 1) / 6; // if (levenshteinDistance < scaleIncrement + 1) // { // score = 3; // } // else if (levenshteinDistance < 3 * scaleIncrement + 1) // { // score = 2; // } // else if (levenshteinDistance < 5 * scaleIncrement + 1) // { // score = 1; // } // else // { // score = 0; // } // */ // } // } // finalScore[0] = score; // finalScore[1] = 5; // // return finalScore; // } // // /** // * // * two points for protocol, five points for host name, // * two points for port, five points for path, 1 point // * for parameter name, 2 points for parameter value // * // * This won't work well for URIs that use the path for // * query parameters // * // * If one of the attributes isn't a URI, score it as a // * simple attribute // * // * Currently, this doesn't compare relative & absolute // * URIs well, even if they are pointing to the same // * server. It would require the URI of the node to do // * this right. Oh well. // * // */ // private int[] scoreUriAttribute(Attr originalAttribute, Attr candidateAttribute) // { // int finalScore[] = new int[2]; // int score = 0, maxScore = 0; // URI originalURI, candidateURI; // // try // { // originalURI = UriFactory.makeUri(originalAttribute.getValue(), false); // candidateURI = UriFactory.makeUri(candidateAttribute.getValue(), false); // } // catch (URISyntaxException e) // { // return scoreSimpleAttribute(originalAttribute, candidateAttribute); // } // // maxScore += 9; // // if (! originalURI.isAbsolute() && ! candidateURI.isAbsolute()) // { // score += 9; // } // // if (originalURI.isAbsolute() && candidateURI.isAbsolute()) // { // if (originalURI.getScheme().equals(candidateURI.getScheme())) // { // score += 2; // } // // if (originalURI.getPort() == candidateURI.getPort()) // { // score += 2; // } // // if (originalURI.getHost().equals(candidateURI.getHost())) // { // score += 5; // } // // if (originalURI.getPath().equals(candidateURI.getPath())) // { // score += 5; // } // // UriQuery originalQuery = new UriQuery(originalURI.getQuery()); // UriQuery candidateQuery = new UriQuery(candidateURI.getQuery()); // // for (String name: originalQuery.getParameters().keySet()) // { // maxScore += 3; // if (candidateQuery.containsParameter(name)) // { // score++; // if (originalQuery.getParameter(name).equals(candidateQuery.getParameter(name))) // { // score += 2; // } // } // } // } // // finalScore[0] = score; // finalScore[1] = maxScore; // // return finalScore; // } // // private HashMap<String, HashMap<String, Node>> splitDom(Node target) // { // HashMap<String, HashMap<String, Node>> nodes = new HashMap<String, HashMap<String, Node>>(8); // target.normalize(); // if (target instanceof Document) // { // HTMLDocumentImpl doc = (HTMLDocumentImpl) target; // doc.normalizeDocument(); // } // // splitNode(target, nodes); // // return nodes; // } // // private void splitNode(Node target, HashMap<String, HashMap<String, Node>> nodes) // { // if (target.hasChildNodes()) // { // NodeList children = target.getChildNodes(); // for (int index = 0; index < children.getLength(); index++) // { // splitNode(children.item(index), nodes); // } // } // switch (target.getNodeType()) // { // case Node.DOCUMENT_TYPE_NODE: // ; // case Node.ELEMENT_NODE: // ; // case Node.TEXT_NODE: // ; // case Node.COMMENT_NODE: // addNode(target, nodes); // } // } // }