nokogiri 1.11.1-java → 1.11.2-java

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of nokogiri might be problematic. Click here for more details.

Files changed (142) hide show
  1. checksums.yaml +4 -4
  2. data/LICENSE-DEPENDENCIES.md +12 -12
  3. data/LICENSE.md +1 -1
  4. data/README.md +20 -15
  5. data/ext/java/nokogiri/EncodingHandler.java +78 -59
  6. data/ext/java/nokogiri/HtmlDocument.java +137 -114
  7. data/ext/java/nokogiri/HtmlElementDescription.java +104 -87
  8. data/ext/java/nokogiri/HtmlEntityLookup.java +31 -26
  9. data/ext/java/nokogiri/HtmlSaxParserContext.java +220 -192
  10. data/ext/java/nokogiri/HtmlSaxPushParser.java +164 -139
  11. data/ext/java/nokogiri/NokogiriService.java +597 -526
  12. data/ext/java/nokogiri/XmlAttr.java +120 -96
  13. data/ext/java/nokogiri/XmlAttributeDecl.java +97 -76
  14. data/ext/java/nokogiri/XmlCdata.java +35 -26
  15. data/ext/java/nokogiri/XmlComment.java +48 -37
  16. data/ext/java/nokogiri/XmlDocument.java +642 -540
  17. data/ext/java/nokogiri/XmlDocumentFragment.java +127 -107
  18. data/ext/java/nokogiri/XmlDtd.java +450 -384
  19. data/ext/java/nokogiri/XmlElement.java +25 -18
  20. data/ext/java/nokogiri/XmlElementContent.java +345 -286
  21. data/ext/java/nokogiri/XmlElementDecl.java +126 -95
  22. data/ext/java/nokogiri/XmlEntityDecl.java +121 -97
  23. data/ext/java/nokogiri/XmlEntityReference.java +51 -42
  24. data/ext/java/nokogiri/XmlNamespace.java +177 -145
  25. data/ext/java/nokogiri/XmlNode.java +1843 -1588
  26. data/ext/java/nokogiri/XmlNodeSet.java +361 -299
  27. data/ext/java/nokogiri/XmlProcessingInstruction.java +49 -39
  28. data/ext/java/nokogiri/XmlReader.java +513 -418
  29. data/ext/java/nokogiri/XmlRelaxng.java +91 -78
  30. data/ext/java/nokogiri/XmlSaxParserContext.java +330 -285
  31. data/ext/java/nokogiri/XmlSaxPushParser.java +229 -190
  32. data/ext/java/nokogiri/XmlSchema.java +328 -263
  33. data/ext/java/nokogiri/XmlSyntaxError.java +113 -83
  34. data/ext/java/nokogiri/XmlText.java +57 -46
  35. data/ext/java/nokogiri/XmlXpathContext.java +240 -206
  36. data/ext/java/nokogiri/XsltStylesheet.java +282 -239
  37. data/ext/java/nokogiri/internals/ClosedStreamException.java +5 -2
  38. data/ext/java/nokogiri/internals/HtmlDomParserContext.java +199 -168
  39. data/ext/java/nokogiri/internals/IgnoreSchemaErrorsErrorHandler.java +17 -10
  40. data/ext/java/nokogiri/internals/NokogiriBlockingQueueInputStream.java +43 -16
  41. data/ext/java/nokogiri/internals/NokogiriDomParser.java +65 -50
  42. data/ext/java/nokogiri/internals/NokogiriEntityResolver.java +107 -88
  43. data/ext/java/nokogiri/internals/NokogiriErrorHandler.java +25 -18
  44. data/ext/java/nokogiri/internals/NokogiriHandler.java +316 -254
  45. data/ext/java/nokogiri/internals/NokogiriHelpers.java +738 -622
  46. data/ext/java/nokogiri/internals/NokogiriNamespaceCache.java +186 -143
  47. data/ext/java/nokogiri/internals/NokogiriNamespaceContext.java +83 -68
  48. data/ext/java/nokogiri/internals/NokogiriNonStrictErrorHandler.java +66 -49
  49. data/ext/java/nokogiri/internals/NokogiriNonStrictErrorHandler4NekoHtml.java +86 -69
  50. data/ext/java/nokogiri/internals/NokogiriStrictErrorHandler.java +44 -29
  51. data/ext/java/nokogiri/internals/NokogiriXPathFunction.java +118 -101
  52. data/ext/java/nokogiri/internals/NokogiriXPathFunctionResolver.java +34 -24
  53. data/ext/java/nokogiri/internals/NokogiriXPathVariableResolver.java +25 -17
  54. data/ext/java/nokogiri/internals/NokogiriXsltErrorListener.java +57 -42
  55. data/ext/java/nokogiri/internals/ParserContext.java +206 -179
  56. data/ext/java/nokogiri/internals/ReaderNode.java +478 -371
  57. data/ext/java/nokogiri/internals/SaveContextVisitor.java +822 -707
  58. data/ext/java/nokogiri/internals/SchemaErrorHandler.java +28 -19
  59. data/ext/java/nokogiri/internals/XalanDTMManagerPatch.java +129 -123
  60. data/ext/java/nokogiri/internals/XmlDeclHandler.java +5 -4
  61. data/ext/java/nokogiri/internals/XmlDomParserContext.java +208 -177
  62. data/ext/java/nokogiri/internals/XmlSaxParser.java +24 -17
  63. data/ext/java/nokogiri/internals/c14n/AttrCompare.java +71 -68
  64. data/ext/java/nokogiri/internals/c14n/C14nHelper.java +137 -118
  65. data/ext/java/nokogiri/internals/c14n/CanonicalFilter.java +27 -21
  66. data/ext/java/nokogiri/internals/c14n/CanonicalizationException.java +74 -61
  67. data/ext/java/nokogiri/internals/c14n/Canonicalizer.java +230 -205
  68. data/ext/java/nokogiri/internals/c14n/Canonicalizer11.java +572 -547
  69. data/ext/java/nokogiri/internals/c14n/Canonicalizer11_OmitComments.java +17 -10
  70. data/ext/java/nokogiri/internals/c14n/Canonicalizer11_WithComments.java +17 -10
  71. data/ext/java/nokogiri/internals/c14n/Canonicalizer20010315.java +323 -302
  72. data/ext/java/nokogiri/internals/c14n/Canonicalizer20010315Excl.java +232 -219
  73. data/ext/java/nokogiri/internals/c14n/Canonicalizer20010315ExclOmitComments.java +22 -15
  74. data/ext/java/nokogiri/internals/c14n/Canonicalizer20010315ExclWithComments.java +23 -16
  75. data/ext/java/nokogiri/internals/c14n/Canonicalizer20010315OmitComments.java +23 -16
  76. data/ext/java/nokogiri/internals/c14n/Canonicalizer20010315WithComments.java +22 -15
  77. data/ext/java/nokogiri/internals/c14n/CanonicalizerBase.java +575 -545
  78. data/ext/java/nokogiri/internals/c14n/CanonicalizerPhysical.java +141 -120
  79. data/ext/java/nokogiri/internals/c14n/CanonicalizerSpi.java +39 -38
  80. data/ext/java/nokogiri/internals/c14n/Constants.java +13 -10
  81. data/ext/java/nokogiri/internals/c14n/ElementProxy.java +279 -247
  82. data/ext/java/nokogiri/internals/c14n/HelperNodeList.java +66 -53
  83. data/ext/java/nokogiri/internals/c14n/IgnoreAllErrorHandler.java +44 -37
  84. data/ext/java/nokogiri/internals/c14n/InclusiveNamespaces.java +135 -120
  85. data/ext/java/nokogiri/internals/c14n/InvalidCanonicalizerException.java +59 -48
  86. data/ext/java/nokogiri/internals/c14n/NameSpaceSymbTable.java +384 -334
  87. data/ext/java/nokogiri/internals/c14n/NodeFilter.java +25 -24
  88. data/ext/java/nokogiri/internals/c14n/UtfHelpper.java +151 -140
  89. data/ext/java/nokogiri/internals/c14n/XMLUtils.java +456 -423
  90. data/ext/java/nokogiri/internals/dom2dtm/DOM2DTM.java +1466 -1500
  91. data/ext/java/nokogiri/internals/dom2dtm/DOM2DTMdefaultNamespaceDeclarationNode.java +626 -570
  92. data/ext/nokogiri/depend +34 -474
  93. data/ext/nokogiri/extconf.rb +253 -183
  94. data/ext/nokogiri/html_document.c +10 -15
  95. data/ext/nokogiri/html_element_description.c +84 -71
  96. data/ext/nokogiri/html_entity_lookup.c +21 -16
  97. data/ext/nokogiri/html_sax_parser_context.c +66 -65
  98. data/ext/nokogiri/html_sax_push_parser.c +29 -27
  99. data/ext/nokogiri/libxml2_backwards_compat.c +121 -0
  100. data/ext/nokogiri/nokogiri.c +171 -63
  101. data/ext/nokogiri/test_global_handlers.c +3 -4
  102. data/ext/nokogiri/xml_attr.c +15 -15
  103. data/ext/nokogiri/xml_attribute_decl.c +18 -18
  104. data/ext/nokogiri/xml_cdata.c +13 -18
  105. data/ext/nokogiri/xml_comment.c +19 -26
  106. data/ext/nokogiri/xml_document.c +221 -164
  107. data/ext/nokogiri/xml_document_fragment.c +13 -15
  108. data/ext/nokogiri/xml_dtd.c +54 -48
  109. data/ext/nokogiri/xml_element_content.c +30 -27
  110. data/ext/nokogiri/xml_element_decl.c +22 -22
  111. data/ext/nokogiri/xml_encoding_handler.c +17 -11
  112. data/ext/nokogiri/xml_entity_decl.c +32 -30
  113. data/ext/nokogiri/xml_entity_reference.c +16 -18
  114. data/ext/nokogiri/xml_namespace.c +56 -49
  115. data/ext/nokogiri/xml_node.c +338 -286
  116. data/ext/nokogiri/xml_node_set.c +168 -156
  117. data/ext/nokogiri/xml_processing_instruction.c +17 -19
  118. data/ext/nokogiri/xml_reader.c +191 -157
  119. data/ext/nokogiri/xml_relax_ng.c +29 -23
  120. data/ext/nokogiri/xml_sax_parser.c +117 -112
  121. data/ext/nokogiri/xml_sax_parser_context.c +100 -85
  122. data/ext/nokogiri/xml_sax_push_parser.c +34 -27
  123. data/ext/nokogiri/xml_schema.c +48 -42
  124. data/ext/nokogiri/xml_syntax_error.c +21 -23
  125. data/ext/nokogiri/xml_text.c +13 -17
  126. data/ext/nokogiri/xml_xpath_context.c +134 -127
  127. data/ext/nokogiri/xslt_stylesheet.c +157 -157
  128. data/lib/nokogiri.rb +1 -22
  129. data/lib/nokogiri/css/parser.rb +1 -1
  130. data/lib/nokogiri/extension.rb +26 -0
  131. data/lib/nokogiri/html/document_fragment.rb +15 -15
  132. data/lib/nokogiri/nokogiri.jar +0 -0
  133. data/lib/nokogiri/version/constant.rb +1 -1
  134. data/lib/nokogiri/version/info.rb +31 -8
  135. data/lib/nokogiri/xml/document.rb +31 -11
  136. data/lib/nokogiri/xml/node.rb +38 -42
  137. data/lib/nokogiri/xml/reader.rb +2 -9
  138. data/lib/nokogiri/xml/xpath.rb +1 -3
  139. data/lib/nokogiri/xml/xpath/syntax_error.rb +1 -1
  140. metadata +7 -8
  141. data/ext/nokogiri/xml_io.c +0 -63
  142. data/ext/nokogiri/xml_libxml2_hacks.c +0 -112
@@ -23,29 +23,30 @@ import org.w3c.dom.Node;
23
23
  /**
24
24
  * An interface to tell to the c14n if a node is included or not in the output
25
25
  */
26
- public interface NodeFilter {
27
-
28
- /**
29
- * Tells if a node must be output in c14n.
30
- * @param n
31
- * @return 1 if the node should be output.
32
- * 0 if node must not be output,
33
- * -1 if the node and all it's child must not be output.
34
- *
35
- */
36
- int isNodeInclude(Node n);
37
-
38
- /**
39
- * Tells if a node must be output in a c14n.
40
- * The caller must assured that this method is always call
41
- * in document order. The implementations can use this
42
- * restriction to optimize the transformation.
43
- * @param n
44
- * @param level the relative level in the tree
45
- * @return 1 if the node should be output.
46
- * 0 if node must not be output,
47
- * -1 if the node and all it's child must not be output.
48
- */
49
- int isNodeIncludeDO(Node n, int level);
26
+ public interface NodeFilter
27
+ {
28
+
29
+ /**
30
+ * Tells if a node must be output in c14n.
31
+ * @param n
32
+ * @return 1 if the node should be output.
33
+ * 0 if node must not be output,
34
+ * -1 if the node and all it's child must not be output.
35
+ *
36
+ */
37
+ int isNodeInclude(Node n);
38
+
39
+ /**
40
+ * Tells if a node must be output in a c14n.
41
+ * The caller must assured that this method is always call
42
+ * in document order. The implementations can use this
43
+ * restriction to optimize the transformation.
44
+ * @param n
45
+ * @param level the relative level in the tree
46
+ * @return 1 if the node should be output.
47
+ * 0 if node must not be output,
48
+ * -1 if the node and all it's child must not be output.
49
+ */
50
+ int isNodeIncludeDO(Node n, int level);
50
51
 
51
52
  }
@@ -22,158 +22,169 @@ import java.io.IOException;
22
22
  import java.io.OutputStream;
23
23
  import java.util.Map;
24
24
 
25
- public final class UtfHelpper {
26
-
27
- private UtfHelpper() {
28
- // complete
25
+ public final class UtfHelpper
26
+ {
27
+
28
+ private
29
+ UtfHelpper()
30
+ {
31
+ // complete
32
+ }
33
+
34
+ public static void
35
+ writeByte(
36
+ final String str,
37
+ final OutputStream out,
38
+ Map<String, byte[]> cache
39
+ ) throws IOException
40
+ {
41
+ byte[] result = cache.get(str);
42
+ if (result == null) {
43
+ result = getStringInUtf8(str);
44
+ cache.put(str, result);
29
45
  }
30
46
 
31
- public static void writeByte(
32
- final String str,
33
- final OutputStream out,
34
- Map<String, byte[]> cache
35
- ) throws IOException {
36
- byte[] result = cache.get(str);
37
- if (result == null) {
38
- result = getStringInUtf8(str);
39
- cache.put(str, result);
40
- }
47
+ out.write(result);
48
+ }
41
49
 
42
- out.write(result);
50
+ public static void
51
+ writeCharToUtf8(final char c, final OutputStream out) throws IOException
52
+ {
53
+ if (c < 0x80) {
54
+ out.write(c);
55
+ return;
56
+ }
57
+ if ((c >= 0xD800 && c <= 0xDBFF) || (c >= 0xDC00 && c <= 0xDFFF)) {
58
+ //No Surrogates in sun java
59
+ out.write(0x3f);
60
+ return;
43
61
  }
62
+ int bias;
63
+ int write;
64
+ char ch;
65
+ if (c > 0x07FF) {
66
+ ch = (char)(c >>> 12);
67
+ write = 0xE0;
68
+ if (ch > 0) {
69
+ write |= (ch & 0x0F);
70
+ }
71
+ out.write(write);
72
+ write = 0x80;
73
+ bias = 0x3F;
74
+ } else {
75
+ write = 0xC0;
76
+ bias = 0x1F;
77
+ }
78
+ ch = (char)(c >>> 6);
79
+ if (ch > 0) {
80
+ write |= (ch & bias);
81
+ }
82
+ out.write(write);
83
+ out.write(0x80 | ((c) & 0x3F));
44
84
 
45
- public static void writeCharToUtf8(final char c, final OutputStream out) throws IOException {
46
- if (c < 0x80) {
47
- out.write(c);
48
- return;
49
- }
50
- if ((c >= 0xD800 && c <= 0xDBFF) || (c >= 0xDC00 && c <= 0xDFFF)) {
51
- //No Surrogates in sun java
52
- out.write(0x3f);
53
- return;
54
- }
55
- int bias;
56
- int write;
57
- char ch;
58
- if (c > 0x07FF) {
59
- ch = (char)(c>>>12);
60
- write = 0xE0;
61
- if (ch > 0) {
62
- write |= (ch & 0x0F);
63
- }
64
- out.write(write);
65
- write = 0x80;
66
- bias = 0x3F;
67
- } else {
68
- write = 0xC0;
69
- bias = 0x1F;
70
- }
71
- ch = (char)(c>>>6);
85
+ }
86
+
87
+ public static void
88
+ writeStringToUtf8(
89
+ final String str,
90
+ final OutputStream out
91
+ ) throws IOException
92
+ {
93
+ final int length = str.length();
94
+ int i = 0;
95
+ char c;
96
+ while (i < length) {
97
+ c = str.charAt(i++);
98
+ if (c < 0x80) {
99
+ out.write(c);
100
+ continue;
101
+ }
102
+ if ((c >= 0xD800 && c <= 0xDBFF) || (c >= 0xDC00 && c <= 0xDFFF)) {
103
+ //No Surrogates in sun java
104
+ out.write(0x3f);
105
+ continue;
106
+ }
107
+ char ch;
108
+ int bias;
109
+ int write;
110
+ if (c > 0x07FF) {
111
+ ch = (char)(c >>> 12);
112
+ write = 0xE0;
72
113
  if (ch > 0) {
73
- write |= (ch & bias);
74
- }
114
+ write |= (ch & 0x0F);
115
+ }
75
116
  out.write(write);
76
- out.write(0x80 | ((c) & 0x3F));
117
+ write = 0x80;
118
+ bias = 0x3F;
119
+ } else {
120
+ write = 0xC0;
121
+ bias = 0x1F;
122
+ }
123
+ ch = (char)(c >>> 6);
124
+ if (ch > 0) {
125
+ write |= (ch & bias);
126
+ }
127
+ out.write(write);
128
+ out.write(0x80 | ((c) & 0x3F));
77
129
 
78
130
  }
79
131
 
80
- public static void writeStringToUtf8(
81
- final String str,
82
- final OutputStream out
83
- ) throws IOException{
84
- final int length = str.length();
85
- int i = 0;
86
- char c;
87
- while (i < length) {
88
- c = str.charAt(i++);
89
- if (c < 0x80) {
90
- out.write(c);
91
- continue;
92
- }
93
- if ((c >= 0xD800 && c <= 0xDBFF) || (c >= 0xDC00 && c <= 0xDFFF)) {
94
- //No Surrogates in sun java
95
- out.write(0x3f);
96
- continue;
97
- }
98
- char ch;
99
- int bias;
100
- int write;
101
- if (c > 0x07FF) {
102
- ch = (char)(c>>>12);
103
- write = 0xE0;
104
- if (ch > 0) {
105
- write |= (ch & 0x0F);
106
- }
107
- out.write(write);
108
- write = 0x80;
109
- bias = 0x3F;
110
- } else {
111
- write = 0xC0;
112
- bias = 0x1F;
113
- }
114
- ch = (char)(c>>>6);
115
- if (ch > 0) {
116
- write |= (ch & bias);
117
- }
118
- out.write(write);
119
- out.write(0x80 | ((c) & 0x3F));
132
+ }
120
133
 
134
+ public static byte[]
135
+ getStringInUtf8(final String str)
136
+ {
137
+ final int length = str.length();
138
+ boolean expanded = false;
139
+ byte[] result = new byte[length];
140
+ int i = 0;
141
+ int out = 0;
142
+ char c;
143
+ while (i < length) {
144
+ c = str.charAt(i++);
145
+ if (c < 0x80) {
146
+ result[out++] = (byte)c;
147
+ continue;
148
+ }
149
+ if ((c >= 0xD800 && c <= 0xDBFF) || (c >= 0xDC00 && c <= 0xDFFF)) {
150
+ //No Surrogates in sun java
151
+ result[out++] = 0x3f;
152
+ continue;
153
+ }
154
+ if (!expanded) {
155
+ byte newResult[] = new byte[3 * length];
156
+ System.arraycopy(result, 0, newResult, 0, out);
157
+ result = newResult;
158
+ expanded = true;
159
+ }
160
+ char ch;
161
+ int bias;
162
+ byte write;
163
+ if (c > 0x07FF) {
164
+ ch = (char)(c >>> 12);
165
+ write = (byte)0xE0;
166
+ if (ch > 0) {
167
+ write |= (ch & 0x0F);
121
168
  }
122
-
169
+ result[out++] = write;
170
+ write = (byte)0x80;
171
+ bias = 0x3F;
172
+ } else {
173
+ write = (byte)0xC0;
174
+ bias = 0x1F;
175
+ }
176
+ ch = (char)(c >>> 6);
177
+ if (ch > 0) {
178
+ write |= (ch & bias);
179
+ }
180
+ result[out++] = write;
181
+ result[out++] = (byte)(0x80 | ((c) & 0x3F));
123
182
  }
124
-
125
- public static byte[] getStringInUtf8(final String str) {
126
- final int length = str.length();
127
- boolean expanded = false;
128
- byte[] result = new byte[length];
129
- int i = 0;
130
- int out = 0;
131
- char c;
132
- while (i < length) {
133
- c = str.charAt(i++);
134
- if (c < 0x80) {
135
- result[out++] = (byte)c;
136
- continue;
137
- }
138
- if ((c >= 0xD800 && c <= 0xDBFF) || (c >= 0xDC00 && c <= 0xDFFF)) {
139
- //No Surrogates in sun java
140
- result[out++] = 0x3f;
141
- continue;
142
- }
143
- if (!expanded) {
144
- byte newResult[] = new byte[3*length];
145
- System.arraycopy(result, 0, newResult, 0, out);
146
- result = newResult;
147
- expanded = true;
148
- }
149
- char ch;
150
- int bias;
151
- byte write;
152
- if (c > 0x07FF) {
153
- ch = (char)(c>>>12);
154
- write = (byte)0xE0;
155
- if (ch > 0) {
156
- write |= (ch & 0x0F);
157
- }
158
- result[out++] = write;
159
- write = (byte)0x80;
160
- bias = 0x3F;
161
- } else {
162
- write = (byte)0xC0;
163
- bias = 0x1F;
164
- }
165
- ch = (char)(c>>>6);
166
- if (ch > 0) {
167
- write |= (ch & bias);
168
- }
169
- result[out++] = write;
170
- result[out++] = (byte)(0x80 | ((c) & 0x3F));
171
- }
172
- if (expanded) {
173
- byte newResult[] = new byte[out];
174
- System.arraycopy(result, 0, newResult, 0, out);
175
- result = newResult;
176
- }
177
- return result;
183
+ if (expanded) {
184
+ byte newResult[] = new byte[out];
185
+ System.arraycopy(result, 0, newResult, 0, out);
186
+ result = newResult;
178
187
  }
188
+ return result;
189
+ }
179
190
  }
@@ -39,469 +39,502 @@ import org.w3c.dom.Text;
39
39
  *
40
40
  * @author Christian Geuer-Pollmann
41
41
  */
42
- public class XMLUtils {
43
-
44
- /**
45
- * Constructor XMLUtils
46
- *
47
- */
48
- private XMLUtils() {
49
- // we don't allow instantiation
42
+ public class XMLUtils
43
+ {
44
+
45
+ /**
46
+ * Constructor XMLUtils
47
+ *
48
+ */
49
+ private
50
+ XMLUtils()
51
+ {
52
+ // we don't allow instantiation
53
+ }
54
+
55
+ /**
56
+ * Method getFullTextChildrenFromElement
57
+ *
58
+ * @param element
59
+ * @return the string of children
60
+ */
61
+ public static String
62
+ getFullTextChildrenFromElement(Element element)
63
+ {
64
+ StringBuilder sb = new StringBuilder();
65
+
66
+ Node child = element.getFirstChild();
67
+ while (child != null) {
68
+ if (child.getNodeType() == Node.TEXT_NODE) {
69
+ sb.append(((Text)child).getData());
70
+ }
71
+ child = child.getNextSibling();
50
72
  }
51
73
 
52
- /**
53
- * Method getFullTextChildrenFromElement
54
- *
55
- * @param element
56
- * @return the string of children
57
- */
58
- public static String getFullTextChildrenFromElement(Element element) {
59
- StringBuilder sb = new StringBuilder();
60
-
61
- Node child = element.getFirstChild();
62
- while (child != null) {
63
- if (child.getNodeType() == Node.TEXT_NODE) {
64
- sb.append(((Text)child).getData());
65
- }
66
- child = child.getNextSibling();
67
- }
68
-
69
- return sb.toString();
74
+ return sb.toString();
75
+ }
76
+
77
+ /**
78
+ * This method returns the owner document of a particular node.
79
+ * This method is necessary because it <I>always</I> returns a
80
+ * {@link Document}. {@link Node#getOwnerDocument} returns <CODE>null</CODE>
81
+ * if the {@link Node} is a {@link Document}.
82
+ *
83
+ * @param node
84
+ * @return the owner document of the node
85
+ */
86
+ public static Document
87
+ getOwnerDocument(Node node)
88
+ {
89
+ if (node.getNodeType() == Node.DOCUMENT_NODE) {
90
+ return (Document) node;
70
91
  }
71
-
72
- /**
73
- * This method returns the owner document of a particular node.
74
- * This method is necessary because it <I>always</I> returns a
75
- * {@link Document}. {@link Node#getOwnerDocument} returns <CODE>null</CODE>
76
- * if the {@link Node} is a {@link Document}.
77
- *
78
- * @param node
79
- * @return the owner document of the node
80
- */
81
- public static Document getOwnerDocument(Node node) {
82
- if (node.getNodeType() == Node.DOCUMENT_NODE) {
83
- return (Document) node;
84
- }
85
- try {
86
- return node.getOwnerDocument();
87
- } catch (NullPointerException npe) {
88
- throw new NullPointerException(npe.getMessage());
89
- }
92
+ try {
93
+ return node.getOwnerDocument();
94
+ } catch (NullPointerException npe) {
95
+ throw new NullPointerException(npe.getMessage());
90
96
  }
91
-
92
- /**
93
- * This method returns the first non-null owner document of the Nodes in this Set.
94
- * This method is necessary because it <I>always</I> returns a
95
- * {@link Document}. {@link Node#getOwnerDocument} returns <CODE>null</CODE>
96
- * if the {@link Node} is a {@link Document}.
97
- *
98
- * @param xpathNodeSet
99
- * @return the owner document
100
- */
101
- public static Document getOwnerDocument(Set<Node> xpathNodeSet) {
102
- NullPointerException npe = null;
103
- for (Node node : xpathNodeSet) {
104
- int nodeType = node.getNodeType();
105
- if (nodeType == Node.DOCUMENT_NODE) {
106
- return (Document) node;
107
- }
108
- try {
109
- if (nodeType == Node.ATTRIBUTE_NODE) {
110
- return ((Attr)node).getOwnerElement().getOwnerDocument();
111
- }
112
- return node.getOwnerDocument();
113
- } catch (NullPointerException e) {
114
- npe = e;
115
- }
97
+ }
98
+
99
+ /**
100
+ * This method returns the first non-null owner document of the Nodes in this Set.
101
+ * This method is necessary because it <I>always</I> returns a
102
+ * {@link Document}. {@link Node#getOwnerDocument} returns <CODE>null</CODE>
103
+ * if the {@link Node} is a {@link Document}.
104
+ *
105
+ * @param xpathNodeSet
106
+ * @return the owner document
107
+ */
108
+ public static Document
109
+ getOwnerDocument(Set<Node> xpathNodeSet)
110
+ {
111
+ NullPointerException npe = null;
112
+ for (Node node : xpathNodeSet) {
113
+ int nodeType = node.getNodeType();
114
+ if (nodeType == Node.DOCUMENT_NODE) {
115
+ return (Document) node;
116
+ }
117
+ try {
118
+ if (nodeType == Node.ATTRIBUTE_NODE) {
119
+ return ((Attr)node).getOwnerElement().getOwnerDocument();
116
120
  }
117
-
118
- throw new NullPointerException(npe.getMessage());
121
+ return node.getOwnerDocument();
122
+ } catch (NullPointerException e) {
123
+ npe = e;
124
+ }
119
125
  }
120
126
 
121
- /**
122
- * Method convertNodelistToSet
123
- *
124
- * @param xpathNodeSet
125
- * @return the set with the nodelist
126
- */
127
- public static Set<Node> convertNodelistToSet(NodeList xpathNodeSet) {
128
- if (xpathNodeSet == null) {
129
- return new HashSet<Node>();
130
- }
127
+ throw new NullPointerException(npe.getMessage());
128
+ }
129
+
130
+ /**
131
+ * Method convertNodelistToSet
132
+ *
133
+ * @param xpathNodeSet
134
+ * @return the set with the nodelist
135
+ */
136
+ public static Set<Node>
137
+ convertNodelistToSet(NodeList xpathNodeSet)
138
+ {
139
+ if (xpathNodeSet == null) {
140
+ return new HashSet<Node>();
141
+ }
131
142
 
132
- int length = xpathNodeSet.getLength();
133
- Set<Node> set = new HashSet<Node>(length);
143
+ int length = xpathNodeSet.getLength();
144
+ Set<Node> set = new HashSet<Node>(length);
134
145
 
135
- for (int i = 0; i < length; i++) {
136
- set.add(xpathNodeSet.item(i));
137
- }
146
+ for (int i = 0; i < length; i++) {
147
+ set.add(xpathNodeSet.item(i));
148
+ }
138
149
 
139
- return set;
150
+ return set;
151
+ }
152
+
153
+ /**
154
+ * This method spreads all namespace attributes in a DOM document to their
155
+ * children. This is needed because the XML Signature XPath transform
156
+ * must evaluate the XPath against all nodes in the input, even against
157
+ * XPath namespace nodes. Through a bug in XalanJ2, the namespace nodes are
158
+ * not fully visible in the Xalan XPath model, so we have to do this by
159
+ * hand in DOM spaces so that the nodes become visible in XPath space.
160
+ *
161
+ * @param doc
162
+ * @see <A HREF="http://nagoya.apache.org/bugzilla/show_bug.cgi?id=2650">
163
+ * Namespace axis resolution is not XPath compliant </A>
164
+ */
165
+ public static void
166
+ circumventBug2650(Document doc)
167
+ {
168
+
169
+ Element documentElement = doc.getDocumentElement();
170
+
171
+ // if the document element has no xmlns definition, we add xmlns=""
172
+ Attr xmlnsAttr =
173
+ documentElement.getAttributeNodeNS(Constants.NamespaceSpecNS, "xmlns");
174
+
175
+ if (xmlnsAttr == null) {
176
+ documentElement.setAttributeNS(Constants.NamespaceSpecNS, "xmlns", "");
140
177
  }
141
178
 
142
- /**
143
- * This method spreads all namespace attributes in a DOM document to their
144
- * children. This is needed because the XML Signature XPath transform
145
- * must evaluate the XPath against all nodes in the input, even against
146
- * XPath namespace nodes. Through a bug in XalanJ2, the namespace nodes are
147
- * not fully visible in the Xalan XPath model, so we have to do this by
148
- * hand in DOM spaces so that the nodes become visible in XPath space.
149
- *
150
- * @param doc
151
- * @see <A HREF="http://nagoya.apache.org/bugzilla/show_bug.cgi?id=2650">
152
- * Namespace axis resolution is not XPath compliant </A>
153
- */
154
- public static void circumventBug2650(Document doc) {
155
-
156
- Element documentElement = doc.getDocumentElement();
157
-
158
- // if the document element has no xmlns definition, we add xmlns=""
159
- Attr xmlnsAttr =
160
- documentElement.getAttributeNodeNS(Constants.NamespaceSpecNS, "xmlns");
161
-
162
- if (xmlnsAttr == null) {
163
- documentElement.setAttributeNS(Constants.NamespaceSpecNS, "xmlns", "");
179
+ XMLUtils.circumventBug2650internal(doc);
180
+ }
181
+
182
+ /**
183
+ * This is the work horse for {@link #circumventBug2650}.
184
+ *
185
+ * @param node
186
+ * @see <A HREF="http://nagoya.apache.org/bugzilla/show_bug.cgi?id=2650">
187
+ * Namespace axis resolution is not XPath compliant </A>
188
+ */
189
+ @SuppressWarnings("fallthrough")
190
+ private static void
191
+ circumventBug2650internal(Node node)
192
+ {
193
+ Node parent = null;
194
+ Node sibling = null;
195
+ final String namespaceNs = Constants.NamespaceSpecNS;
196
+ do {
197
+ switch (node.getNodeType()) {
198
+ case Node.ELEMENT_NODE :
199
+ Element element = (Element) node;
200
+ if (!element.hasChildNodes()) {
201
+ break;
164
202
  }
203
+ if (element.hasAttributes()) {
204
+ NamedNodeMap attributes = element.getAttributes();
205
+ int attributesLength = attributes.getLength();
165
206
 
166
- XMLUtils.circumventBug2650internal(doc);
167
- }
207
+ for (Node child = element.getFirstChild(); child != null;
208
+ child = child.getNextSibling()) {
168
209
 
169
- /**
170
- * This is the work horse for {@link #circumventBug2650}.
171
- *
172
- * @param node
173
- * @see <A HREF="http://nagoya.apache.org/bugzilla/show_bug.cgi?id=2650">
174
- * Namespace axis resolution is not XPath compliant </A>
175
- */
176
- @SuppressWarnings("fallthrough")
177
- private static void circumventBug2650internal(Node node) {
178
- Node parent = null;
179
- Node sibling = null;
180
- final String namespaceNs = Constants.NamespaceSpecNS;
181
- do {
182
- switch (node.getNodeType()) {
183
- case Node.ELEMENT_NODE :
184
- Element element = (Element) node;
185
- if (!element.hasChildNodes()) {
186
- break;
187
- }
188
- if (element.hasAttributes()) {
189
- NamedNodeMap attributes = element.getAttributes();
190
- int attributesLength = attributes.getLength();
191
-
192
- for (Node child = element.getFirstChild(); child!=null;
193
- child = child.getNextSibling()) {
194
-
195
- if (child.getNodeType() != Node.ELEMENT_NODE) {
196
- continue;
197
- }
198
- Element childElement = (Element) child;
199
-
200
- for (int i = 0; i < attributesLength; i++) {
201
- Attr currentAttr = (Attr) attributes.item(i);
202
- if (!namespaceNs.equals(currentAttr.getNamespaceURI())) {
203
- continue;
204
- }
205
- if (childElement.hasAttributeNS(namespaceNs,
206
- currentAttr.getLocalName())) {
207
- continue;
208
- }
209
- childElement.setAttributeNS(namespaceNs,
210
- currentAttr.getName(),
211
- currentAttr.getNodeValue());
212
- }
213
- }
214
- }
215
- case Node.ENTITY_REFERENCE_NODE :
216
- case Node.DOCUMENT_NODE :
217
- parent = node;
218
- sibling = node.getFirstChild();
219
- break;
220
- }
221
- while ((sibling == null) && (parent != null)) {
222
- sibling = parent.getNextSibling();
223
- parent = parent.getParentNode();
210
+ if (child.getNodeType() != Node.ELEMENT_NODE) {
211
+ continue;
224
212
  }
225
- if (sibling == null) {
226
- return;
213
+ Element childElement = (Element) child;
214
+
215
+ for (int i = 0; i < attributesLength; i++) {
216
+ Attr currentAttr = (Attr) attributes.item(i);
217
+ if (!namespaceNs.equals(currentAttr.getNamespaceURI())) {
218
+ continue;
219
+ }
220
+ if (childElement.hasAttributeNS(namespaceNs,
221
+ currentAttr.getLocalName())) {
222
+ continue;
223
+ }
224
+ childElement.setAttributeNS(namespaceNs,
225
+ currentAttr.getName(),
226
+ currentAttr.getNodeValue());
227
227
  }
228
-
229
- node = sibling;
230
- sibling = node.getNextSibling();
231
- } while (true);
232
- }
233
-
234
- /**
235
- * @param sibling
236
- * @param uri
237
- * @param nodeName
238
- * @param number
239
- * @return nodes with the constrain
240
- */
241
- public static Text selectNodeText(Node sibling, String uri, String nodeName, int number) {
242
- Node n = selectNode(sibling,uri,nodeName,number);
243
- if (n == null) {
244
- return null;
245
- }
246
- n = n.getFirstChild();
247
- while (n != null && n.getNodeType() != Node.TEXT_NODE) {
248
- n = n.getNextSibling();
228
+ }
249
229
  }
250
- return (Text)n;
230
+ case Node.ENTITY_REFERENCE_NODE :
231
+ case Node.DOCUMENT_NODE :
232
+ parent = node;
233
+ sibling = node.getFirstChild();
234
+ break;
235
+ }
236
+ while ((sibling == null) && (parent != null)) {
237
+ sibling = parent.getNextSibling();
238
+ parent = parent.getParentNode();
239
+ }
240
+ if (sibling == null) {
241
+ return;
242
+ }
243
+
244
+ node = sibling;
245
+ sibling = node.getNextSibling();
246
+ } while (true);
247
+ }
248
+
249
+ /**
250
+ * @param sibling
251
+ * @param uri
252
+ * @param nodeName
253
+ * @param number
254
+ * @return nodes with the constrain
255
+ */
256
+ public static Text
257
+ selectNodeText(Node sibling, String uri, String nodeName, int number)
258
+ {
259
+ Node n = selectNode(sibling, uri, nodeName, number);
260
+ if (n == null) {
261
+ return null;
251
262
  }
252
-
253
- /**
254
- * @param sibling
255
- * @param uri
256
- * @param nodeName
257
- * @param number
258
- * @return nodes with the constrain
259
- */
260
- public static Element selectNode(Node sibling, String uri, String nodeName, int number) {
261
- while (sibling != null) {
262
- if (sibling.getNamespaceURI() != null && sibling.getNamespaceURI().equals(uri)
263
- && sibling.getLocalName().equals(nodeName)) {
264
- if (number == 0){
265
- return (Element)sibling;
266
- }
267
- number--;
268
- }
269
- sibling = sibling.getNextSibling();
270
- }
271
- return null;
263
+ n = n.getFirstChild();
264
+ while (n != null && n.getNodeType() != Node.TEXT_NODE) {
265
+ n = n.getNextSibling();
272
266
  }
273
-
274
- /**
275
- * @param sibling
276
- * @param uri
277
- * @param nodeName
278
- * @return nodes with the constraint
279
- */
280
- public static Element[] selectNodes(Node sibling, String uri, String nodeName) {
281
- List<Element> list = new ArrayList<Element>();
282
- while (sibling != null) {
283
- if (sibling.getNamespaceURI() != null && sibling.getNamespaceURI().equals(uri)
284
- && sibling.getLocalName().equals(nodeName)) {
285
- list.add((Element)sibling);
286
- }
287
- sibling = sibling.getNextSibling();
267
+ return (Text)n;
268
+ }
269
+
270
+ /**
271
+ * @param sibling
272
+ * @param uri
273
+ * @param nodeName
274
+ * @param number
275
+ * @return nodes with the constrain
276
+ */
277
+ public static Element
278
+ selectNode(Node sibling, String uri, String nodeName, int number)
279
+ {
280
+ while (sibling != null) {
281
+ if (sibling.getNamespaceURI() != null && sibling.getNamespaceURI().equals(uri)
282
+ && sibling.getLocalName().equals(nodeName)) {
283
+ if (number == 0) {
284
+ return (Element)sibling;
288
285
  }
289
- return list.toArray(new Element[list.size()]);
286
+ number--;
287
+ }
288
+ sibling = sibling.getNextSibling();
290
289
  }
291
-
292
- /**
293
- * @param signatureElement
294
- * @param inputSet
295
- * @return nodes with the constrain
296
- */
297
- public static Set<Node> excludeNodeFromSet(Node signatureElement, Set<Node> inputSet) {
298
- Set<Node> resultSet = new HashSet<Node>();
299
- Iterator<Node> iterator = inputSet.iterator();
300
-
301
- while (iterator.hasNext()) {
302
- Node inputNode = iterator.next();
303
-
304
- if (!XMLUtils.isDescendantOrSelf(signatureElement, inputNode)) {
305
- resultSet.add(inputNode);
306
- }
307
- }
308
- return resultSet;
290
+ return null;
291
+ }
292
+
293
+ /**
294
+ * @param sibling
295
+ * @param uri
296
+ * @param nodeName
297
+ * @return nodes with the constraint
298
+ */
299
+ public static Element[]
300
+ selectNodes(Node sibling, String uri, String nodeName)
301
+ {
302
+ List<Element> list = new ArrayList<Element>();
303
+ while (sibling != null) {
304
+ if (sibling.getNamespaceURI() != null && sibling.getNamespaceURI().equals(uri)
305
+ && sibling.getLocalName().equals(nodeName)) {
306
+ list.add((Element)sibling);
307
+ }
308
+ sibling = sibling.getNextSibling();
309
309
  }
310
-
311
- /**
312
- * Method getStrFromNode
313
- *
314
- * @param xpathnode
315
- * @return the string for the node.
316
- */
317
- public static String getStrFromNode(Node xpathnode) {
318
- if (xpathnode.getNodeType() == Node.TEXT_NODE) {
319
- // we iterate over all siblings of the context node because eventually,
320
- // the text is "polluted" with pi's or comments
321
- StringBuilder sb = new StringBuilder();
322
-
323
- for (Node currentSibling = xpathnode.getParentNode().getFirstChild();
324
- currentSibling != null;
325
- currentSibling = currentSibling.getNextSibling()) {
326
- if (currentSibling.getNodeType() == Node.TEXT_NODE) {
327
- sb.append(((Text) currentSibling).getData());
328
- }
329
- }
330
-
331
- return sb.toString();
332
- } else if (xpathnode.getNodeType() == Node.ATTRIBUTE_NODE) {
333
- return ((Attr) xpathnode).getNodeValue();
334
- } else if (xpathnode.getNodeType() == Node.PROCESSING_INSTRUCTION_NODE) {
335
- return ((ProcessingInstruction) xpathnode).getNodeValue();
336
- }
337
-
338
- return null;
310
+ return list.toArray(new Element[list.size()]);
311
+ }
312
+
313
+ /**
314
+ * @param signatureElement
315
+ * @param inputSet
316
+ * @return nodes with the constrain
317
+ */
318
+ public static Set<Node>
319
+ excludeNodeFromSet(Node signatureElement, Set<Node> inputSet)
320
+ {
321
+ Set<Node> resultSet = new HashSet<Node>();
322
+ Iterator<Node> iterator = inputSet.iterator();
323
+
324
+ while (iterator.hasNext()) {
325
+ Node inputNode = iterator.next();
326
+
327
+ if (!XMLUtils.isDescendantOrSelf(signatureElement, inputNode)) {
328
+ resultSet.add(inputNode);
329
+ }
339
330
  }
340
-
341
- /**
342
- * Returns true if the descendantOrSelf is on the descendant-or-self axis
343
- * of the context node.
344
- *
345
- * @param ctx
346
- * @param descendantOrSelf
347
- * @return true if the node is descendant
348
- */
349
- public static boolean isDescendantOrSelf(Node ctx, Node descendantOrSelf) {
350
- if (ctx == descendantOrSelf) {
351
- return true;
331
+ return resultSet;
332
+ }
333
+
334
+ /**
335
+ * Method getStrFromNode
336
+ *
337
+ * @param xpathnode
338
+ * @return the string for the node.
339
+ */
340
+ public static String
341
+ getStrFromNode(Node xpathnode)
342
+ {
343
+ if (xpathnode.getNodeType() == Node.TEXT_NODE) {
344
+ // we iterate over all siblings of the context node because eventually,
345
+ // the text is "polluted" with pi's or comments
346
+ StringBuilder sb = new StringBuilder();
347
+
348
+ for (Node currentSibling = xpathnode.getParentNode().getFirstChild();
349
+ currentSibling != null;
350
+ currentSibling = currentSibling.getNextSibling()) {
351
+ if (currentSibling.getNodeType() == Node.TEXT_NODE) {
352
+ sb.append(((Text) currentSibling).getData());
352
353
  }
354
+ }
353
355
 
354
- Node parent = descendantOrSelf;
355
-
356
- while (true) {
357
- if (parent == null) {
358
- return false;
359
- }
360
-
361
- if (parent == ctx) {
362
- return true;
363
- }
364
-
365
- if (parent.getNodeType() == Node.ATTRIBUTE_NODE) {
366
- parent = ((Attr) parent).getOwnerElement();
367
- } else {
368
- parent = parent.getParentNode();
369
- }
370
- }
356
+ return sb.toString();
357
+ } else if (xpathnode.getNodeType() == Node.ATTRIBUTE_NODE) {
358
+ return ((Attr) xpathnode).getNodeValue();
359
+ } else if (xpathnode.getNodeType() == Node.PROCESSING_INSTRUCTION_NODE) {
360
+ return ((ProcessingInstruction) xpathnode).getNodeValue();
371
361
  }
372
362
 
373
- /**
374
- * Returns the attribute value for the attribute with the specified name.
375
- * Returns null if there is no such attribute, or
376
- * the empty string if the attribute value is empty.
377
- *
378
- * <p>This works around a limitation of the DOM
379
- * <code>Element.getAttributeNode</code> method, which does not distinguish
380
- * between an unspecified attribute and an attribute with a value of
381
- * "" (it returns "" for both cases).
382
- *
383
- * @param elem the element containing the attribute
384
- * @param name the name of the attribute
385
- * @return the attribute value (may be null if unspecified)
386
- */
387
- public static String getAttributeValue(Element elem, String name) {
388
- Attr attr = elem.getAttributeNodeNS(null, name);
389
- return (attr == null) ? null : attr.getValue();
363
+ return null;
364
+ }
365
+
366
+ /**
367
+ * Returns true if the descendantOrSelf is on the descendant-or-self axis
368
+ * of the context node.
369
+ *
370
+ * @param ctx
371
+ * @param descendantOrSelf
372
+ * @return true if the node is descendant
373
+ */
374
+ public static boolean
375
+ isDescendantOrSelf(Node ctx, Node descendantOrSelf)
376
+ {
377
+ if (ctx == descendantOrSelf) {
378
+ return true;
390
379
  }
391
380
 
392
- /**
393
- * This method is a tree-search to help prevent against wrapping attacks. It checks that no
394
- * two Elements have ID Attributes that match the "value" argument, if this is the case then
395
- * "false" is returned. Note that a return value of "true" does not necessarily mean that
396
- * a matching Element has been found, just that no wrapping attack has been detected.
397
- */
398
- public static boolean protectAgainstWrappingAttack(Node startNode, String value) {
399
- Node startParent = startNode.getParentNode();
400
- Node processedNode;
401
- Element foundElement = null;
402
-
403
- String id = value.trim();
404
- if (id.charAt(0) == '#') {
405
- id = id.substring(1);
406
- }
381
+ Node parent = descendantOrSelf;
407
382
 
408
- while (startNode != null) {
409
- if (startNode.getNodeType() == Node.ELEMENT_NODE) {
410
- Element se = (Element) startNode;
411
-
412
- NamedNodeMap attributes = se.getAttributes();
413
- if (attributes != null) {
414
- for (int i = 0; i < attributes.getLength(); i++) {
415
- Attr attr = (Attr)attributes.item(i);
416
- if (attr.isId() && id.equals(attr.getValue())) {
417
- if (foundElement == null) {
418
- // Continue searching to find duplicates
419
- foundElement = attr.getOwnerElement();
420
- } else {
421
- //log.debug("Multiple elements with the same 'Id' attribute value!");
422
- return false;
423
- }
424
- }
425
- }
426
- }
427
- }
383
+ while (true) {
384
+ if (parent == null) {
385
+ return false;
386
+ }
428
387
 
429
- processedNode = startNode;
430
- startNode = startNode.getFirstChild();
388
+ if (parent == ctx) {
389
+ return true;
390
+ }
431
391
 
432
- // no child, this node is done.
433
- if (startNode == null) {
434
- // close node processing, get sibling
435
- startNode = processedNode.getNextSibling();
436
- }
392
+ if (parent.getNodeType() == Node.ATTRIBUTE_NODE) {
393
+ parent = ((Attr) parent).getOwnerElement();
394
+ } else {
395
+ parent = parent.getParentNode();
396
+ }
397
+ }
398
+ }
399
+
400
+ /**
401
+ * Returns the attribute value for the attribute with the specified name.
402
+ * Returns null if there is no such attribute, or
403
+ * the empty string if the attribute value is empty.
404
+ *
405
+ * <p>This works around a limitation of the DOM
406
+ * <code>Element.getAttributeNode</code> method, which does not distinguish
407
+ * between an unspecified attribute and an attribute with a value of
408
+ * "" (it returns "" for both cases).
409
+ *
410
+ * @param elem the element containing the attribute
411
+ * @param name the name of the attribute
412
+ * @return the attribute value (may be null if unspecified)
413
+ */
414
+ public static String
415
+ getAttributeValue(Element elem, String name)
416
+ {
417
+ Attr attr = elem.getAttributeNodeNS(null, name);
418
+ return (attr == null) ? null : attr.getValue();
419
+ }
420
+
421
+ /**
422
+ * This method is a tree-search to help prevent against wrapping attacks. It checks that no
423
+ * two Elements have ID Attributes that match the "value" argument, if this is the case then
424
+ * "false" is returned. Note that a return value of "true" does not necessarily mean that
425
+ * a matching Element has been found, just that no wrapping attack has been detected.
426
+ */
427
+ public static boolean
428
+ protectAgainstWrappingAttack(Node startNode, String value)
429
+ {
430
+ Node startParent = startNode.getParentNode();
431
+ Node processedNode;
432
+ Element foundElement = null;
433
+
434
+ String id = value.trim();
435
+ if (id.charAt(0) == '#') {
436
+ id = id.substring(1);
437
+ }
437
438
 
438
- // no more siblings, get parent, all children
439
- // of parent are processed.
440
- while (startNode == null) {
441
- processedNode = processedNode.getParentNode();
442
- if (processedNode == startParent) {
443
- return true;
444
- }
445
- // close parent node processing (processed node now)
446
- startNode = processedNode.getNextSibling();
439
+ while (startNode != null) {
440
+ if (startNode.getNodeType() == Node.ELEMENT_NODE) {
441
+ Element se = (Element) startNode;
442
+
443
+ NamedNodeMap attributes = se.getAttributes();
444
+ if (attributes != null) {
445
+ for (int i = 0; i < attributes.getLength(); i++) {
446
+ Attr attr = (Attr)attributes.item(i);
447
+ if (attr.isId() && id.equals(attr.getValue())) {
448
+ if (foundElement == null) {
449
+ // Continue searching to find duplicates
450
+ foundElement = attr.getOwnerElement();
451
+ } else {
452
+ //log.debug("Multiple elements with the same 'Id' attribute value!");
453
+ return false;
454
+ }
447
455
  }
456
+ }
448
457
  }
449
- return true;
450
- }
451
-
452
- /**
453
- * This method is a tree-search to help prevent against wrapping attacks. It checks that no other
454
- * Element than the given "knownElement" argument has an ID attribute that matches the "value"
455
- * argument, which is the ID value of "knownElement". If this is the case then "false" is returned.
456
- */
457
- public static boolean protectAgainstWrappingAttack(
458
- Node startNode, Element knownElement, String value
459
- ) {
460
- Node startParent = startNode.getParentNode();
461
- Node processedNode;
462
-
463
- String id = value.trim();
464
- if (id.charAt(0) == '#') {
465
- id = id.substring(1);
458
+ }
459
+
460
+ processedNode = startNode;
461
+ startNode = startNode.getFirstChild();
462
+
463
+ // no child, this node is done.
464
+ if (startNode == null) {
465
+ // close node processing, get sibling
466
+ startNode = processedNode.getNextSibling();
467
+ }
468
+
469
+ // no more siblings, get parent, all children
470
+ // of parent are processed.
471
+ while (startNode == null) {
472
+ processedNode = processedNode.getParentNode();
473
+ if (processedNode == startParent) {
474
+ return true;
466
475
  }
476
+ // close parent node processing (processed node now)
477
+ startNode = processedNode.getNextSibling();
478
+ }
479
+ }
480
+ return true;
481
+ }
482
+
483
+ /**
484
+ * This method is a tree-search to help prevent against wrapping attacks. It checks that no other
485
+ * Element than the given "knownElement" argument has an ID attribute that matches the "value"
486
+ * argument, which is the ID value of "knownElement". If this is the case then "false" is returned.
487
+ */
488
+ public static boolean
489
+ protectAgainstWrappingAttack(
490
+ Node startNode, Element knownElement, String value
491
+ )
492
+ {
493
+ Node startParent = startNode.getParentNode();
494
+ Node processedNode;
495
+
496
+ String id = value.trim();
497
+ if (id.charAt(0) == '#') {
498
+ id = id.substring(1);
499
+ }
467
500
 
468
- while (startNode != null) {
469
- if (startNode.getNodeType() == Node.ELEMENT_NODE) {
470
- Element se = (Element) startNode;
471
-
472
- NamedNodeMap attributes = se.getAttributes();
473
- if (attributes != null) {
474
- for (int i = 0; i < attributes.getLength(); i++) {
475
- Attr attr = (Attr)attributes.item(i);
476
- if (attr.isId() && id.equals(attr.getValue()) && se != knownElement) {
477
- //log.debug("Multiple elements with the same 'Id' attribute value!");
478
- return false;
479
- }
480
- }
481
- }
482
- }
483
-
484
- processedNode = startNode;
485
- startNode = startNode.getFirstChild();
486
-
487
- // no child, this node is done.
488
- if (startNode == null) {
489
- // close node processing, get sibling
490
- startNode = processedNode.getNextSibling();
491
- }
492
-
493
- // no more siblings, get parent, all children
494
- // of parent are processed.
495
- while (startNode == null) {
496
- processedNode = processedNode.getParentNode();
497
- if (processedNode == startParent) {
498
- return true;
499
- }
500
- // close parent node processing (processed node now)
501
- startNode = processedNode.getNextSibling();
501
+ while (startNode != null) {
502
+ if (startNode.getNodeType() == Node.ELEMENT_NODE) {
503
+ Element se = (Element) startNode;
504
+
505
+ NamedNodeMap attributes = se.getAttributes();
506
+ if (attributes != null) {
507
+ for (int i = 0; i < attributes.getLength(); i++) {
508
+ Attr attr = (Attr)attributes.item(i);
509
+ if (attr.isId() && id.equals(attr.getValue()) && se != knownElement) {
510
+ //log.debug("Multiple elements with the same 'Id' attribute value!");
511
+ return false;
502
512
  }
513
+ }
503
514
  }
504
- return true;
515
+ }
516
+
517
+ processedNode = startNode;
518
+ startNode = startNode.getFirstChild();
519
+
520
+ // no child, this node is done.
521
+ if (startNode == null) {
522
+ // close node processing, get sibling
523
+ startNode = processedNode.getNextSibling();
524
+ }
525
+
526
+ // no more siblings, get parent, all children
527
+ // of parent are processed.
528
+ while (startNode == null) {
529
+ processedNode = processedNode.getParentNode();
530
+ if (processedNode == startParent) {
531
+ return true;
532
+ }
533
+ // close parent node processing (processed node now)
534
+ startNode = processedNode.getNextSibling();
535
+ }
505
536
  }
537
+ return true;
538
+ }
506
539
 
507
540
  }