nokogiri 1.11.1-java → 1.11.6-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 (143) hide show
  1. checksums.yaml +4 -4
  2. data/LICENSE-DEPENDENCIES.md +12 -12
  3. data/LICENSE.md +1 -1
  4. data/README.md +21 -16
  5. data/dependencies.yml +12 -12
  6. data/ext/java/nokogiri/EncodingHandler.java +76 -89
  7. data/ext/java/nokogiri/HtmlDocument.java +135 -144
  8. data/ext/java/nokogiri/HtmlElementDescription.java +102 -117
  9. data/ext/java/nokogiri/HtmlEntityLookup.java +33 -60
  10. data/ext/java/nokogiri/HtmlSaxParserContext.java +218 -222
  11. data/ext/java/nokogiri/HtmlSaxPushParser.java +162 -169
  12. data/ext/java/nokogiri/NokogiriService.java +595 -556
  13. data/ext/java/nokogiri/XmlAttr.java +118 -126
  14. data/ext/java/nokogiri/XmlAttributeDecl.java +95 -106
  15. data/ext/java/nokogiri/XmlCdata.java +35 -58
  16. data/ext/java/nokogiri/XmlComment.java +46 -67
  17. data/ext/java/nokogiri/XmlDocument.java +645 -572
  18. data/ext/java/nokogiri/XmlDocumentFragment.java +125 -137
  19. data/ext/java/nokogiri/XmlDtd.java +448 -414
  20. data/ext/java/nokogiri/XmlElement.java +23 -48
  21. data/ext/java/nokogiri/XmlElementContent.java +343 -316
  22. data/ext/java/nokogiri/XmlElementDecl.java +124 -125
  23. data/ext/java/nokogiri/XmlEntityDecl.java +119 -127
  24. data/ext/java/nokogiri/XmlEntityReference.java +49 -72
  25. data/ext/java/nokogiri/XmlNamespace.java +175 -175
  26. data/ext/java/nokogiri/XmlNode.java +1843 -1620
  27. data/ext/java/nokogiri/XmlNodeSet.java +361 -331
  28. data/ext/java/nokogiri/XmlProcessingInstruction.java +47 -69
  29. data/ext/java/nokogiri/XmlReader.java +513 -450
  30. data/ext/java/nokogiri/XmlRelaxng.java +85 -104
  31. data/ext/java/nokogiri/XmlSaxParserContext.java +328 -315
  32. data/ext/java/nokogiri/XmlSaxPushParser.java +227 -220
  33. data/ext/java/nokogiri/XmlSchema.java +328 -295
  34. data/ext/java/nokogiri/XmlSyntaxError.java +113 -115
  35. data/ext/java/nokogiri/XmlText.java +55 -76
  36. data/ext/java/nokogiri/XmlXpathContext.java +240 -238
  37. data/ext/java/nokogiri/XsltStylesheet.java +280 -269
  38. data/ext/java/nokogiri/internals/ClosedStreamException.java +5 -2
  39. data/ext/java/nokogiri/internals/HtmlDomParserContext.java +201 -202
  40. data/ext/java/nokogiri/internals/IgnoreSchemaErrorsErrorHandler.java +17 -10
  41. data/ext/java/nokogiri/internals/NokogiriBlockingQueueInputStream.java +43 -16
  42. data/ext/java/nokogiri/internals/NokogiriDomParser.java +63 -80
  43. data/ext/java/nokogiri/internals/NokogiriEntityResolver.java +107 -88
  44. data/ext/java/nokogiri/internals/NokogiriErrorHandler.java +27 -52
  45. data/ext/java/nokogiri/internals/NokogiriHandler.java +316 -286
  46. data/ext/java/nokogiri/internals/NokogiriHelpers.java +736 -652
  47. data/ext/java/nokogiri/internals/NokogiriNamespaceCache.java +184 -173
  48. data/ext/java/nokogiri/internals/NokogiriNamespaceContext.java +81 -98
  49. data/ext/java/nokogiri/internals/NokogiriNonStrictErrorHandler.java +64 -79
  50. data/ext/java/nokogiri/internals/NokogiriNonStrictErrorHandler4NekoHtml.java +84 -99
  51. data/ext/java/nokogiri/internals/NokogiriStrictErrorHandler.java +48 -65
  52. data/ext/java/nokogiri/internals/NokogiriXPathFunction.java +116 -131
  53. data/ext/java/nokogiri/internals/NokogiriXPathFunctionResolver.java +34 -56
  54. data/ext/java/nokogiri/internals/NokogiriXPathVariableResolver.java +23 -46
  55. data/ext/java/nokogiri/internals/NokogiriXsltErrorListener.java +55 -72
  56. data/ext/java/nokogiri/internals/ParserContext.java +206 -211
  57. data/ext/java/nokogiri/internals/ReaderNode.java +478 -403
  58. data/ext/java/nokogiri/internals/SaveContextVisitor.java +822 -739
  59. data/ext/java/nokogiri/internals/SchemaErrorHandler.java +31 -54
  60. data/ext/java/nokogiri/internals/XalanDTMManagerPatch.java +129 -123
  61. data/ext/java/nokogiri/internals/XmlDeclHandler.java +3 -34
  62. data/ext/java/nokogiri/internals/XmlDomParserContext.java +206 -207
  63. data/ext/java/nokogiri/internals/XmlSaxParser.java +22 -47
  64. data/ext/java/nokogiri/internals/c14n/AttrCompare.java +71 -68
  65. data/ext/java/nokogiri/internals/c14n/C14nHelper.java +137 -118
  66. data/ext/java/nokogiri/internals/c14n/CanonicalFilter.java +27 -21
  67. data/ext/java/nokogiri/internals/c14n/CanonicalizationException.java +74 -61
  68. data/ext/java/nokogiri/internals/c14n/Canonicalizer.java +230 -205
  69. data/ext/java/nokogiri/internals/c14n/Canonicalizer11.java +572 -547
  70. data/ext/java/nokogiri/internals/c14n/Canonicalizer11_OmitComments.java +17 -10
  71. data/ext/java/nokogiri/internals/c14n/Canonicalizer11_WithComments.java +17 -10
  72. data/ext/java/nokogiri/internals/c14n/Canonicalizer20010315.java +323 -302
  73. data/ext/java/nokogiri/internals/c14n/Canonicalizer20010315Excl.java +232 -219
  74. data/ext/java/nokogiri/internals/c14n/Canonicalizer20010315ExclOmitComments.java +22 -15
  75. data/ext/java/nokogiri/internals/c14n/Canonicalizer20010315ExclWithComments.java +23 -16
  76. data/ext/java/nokogiri/internals/c14n/Canonicalizer20010315OmitComments.java +23 -16
  77. data/ext/java/nokogiri/internals/c14n/Canonicalizer20010315WithComments.java +22 -15
  78. data/ext/java/nokogiri/internals/c14n/CanonicalizerBase.java +575 -545
  79. data/ext/java/nokogiri/internals/c14n/CanonicalizerPhysical.java +141 -120
  80. data/ext/java/nokogiri/internals/c14n/CanonicalizerSpi.java +39 -38
  81. data/ext/java/nokogiri/internals/c14n/Constants.java +13 -10
  82. data/ext/java/nokogiri/internals/c14n/ElementProxy.java +279 -247
  83. data/ext/java/nokogiri/internals/c14n/HelperNodeList.java +66 -53
  84. data/ext/java/nokogiri/internals/c14n/IgnoreAllErrorHandler.java +44 -37
  85. data/ext/java/nokogiri/internals/c14n/InclusiveNamespaces.java +135 -120
  86. data/ext/java/nokogiri/internals/c14n/InvalidCanonicalizerException.java +59 -48
  87. data/ext/java/nokogiri/internals/c14n/NameSpaceSymbTable.java +384 -334
  88. data/ext/java/nokogiri/internals/c14n/NodeFilter.java +25 -24
  89. data/ext/java/nokogiri/internals/c14n/UtfHelpper.java +151 -140
  90. data/ext/java/nokogiri/internals/c14n/XMLUtils.java +456 -423
  91. data/ext/java/nokogiri/internals/dom2dtm/DOM2DTM.java +1466 -1500
  92. data/ext/java/nokogiri/internals/dom2dtm/DOM2DTMdefaultNamespaceDeclarationNode.java +626 -574
  93. data/ext/nokogiri/depend +34 -474
  94. data/ext/nokogiri/extconf.rb +253 -183
  95. data/ext/nokogiri/html_document.c +10 -15
  96. data/ext/nokogiri/html_element_description.c +84 -71
  97. data/ext/nokogiri/html_entity_lookup.c +21 -16
  98. data/ext/nokogiri/html_sax_parser_context.c +66 -65
  99. data/ext/nokogiri/html_sax_push_parser.c +29 -27
  100. data/ext/nokogiri/libxml2_backwards_compat.c +121 -0
  101. data/ext/nokogiri/nokogiri.c +190 -63
  102. data/ext/nokogiri/test_global_handlers.c +3 -4
  103. data/ext/nokogiri/xml_attr.c +15 -15
  104. data/ext/nokogiri/xml_attribute_decl.c +18 -18
  105. data/ext/nokogiri/xml_cdata.c +13 -18
  106. data/ext/nokogiri/xml_comment.c +19 -26
  107. data/ext/nokogiri/xml_document.c +246 -188
  108. data/ext/nokogiri/xml_document_fragment.c +13 -15
  109. data/ext/nokogiri/xml_dtd.c +54 -48
  110. data/ext/nokogiri/xml_element_content.c +30 -27
  111. data/ext/nokogiri/xml_element_decl.c +22 -22
  112. data/ext/nokogiri/xml_encoding_handler.c +17 -11
  113. data/ext/nokogiri/xml_entity_decl.c +32 -30
  114. data/ext/nokogiri/xml_entity_reference.c +16 -18
  115. data/ext/nokogiri/xml_namespace.c +56 -49
  116. data/ext/nokogiri/xml_node.c +385 -326
  117. data/ext/nokogiri/xml_node_set.c +168 -156
  118. data/ext/nokogiri/xml_processing_instruction.c +17 -19
  119. data/ext/nokogiri/xml_reader.c +191 -157
  120. data/ext/nokogiri/xml_relax_ng.c +29 -23
  121. data/ext/nokogiri/xml_sax_parser.c +117 -112
  122. data/ext/nokogiri/xml_sax_parser_context.c +100 -85
  123. data/ext/nokogiri/xml_sax_push_parser.c +34 -27
  124. data/ext/nokogiri/xml_schema.c +48 -42
  125. data/ext/nokogiri/xml_syntax_error.c +21 -23
  126. data/ext/nokogiri/xml_text.c +13 -17
  127. data/ext/nokogiri/xml_xpath_context.c +134 -127
  128. data/ext/nokogiri/xslt_stylesheet.c +157 -157
  129. data/lib/nokogiri.rb +1 -22
  130. data/lib/nokogiri/css/parser.rb +1 -1
  131. data/lib/nokogiri/extension.rb +26 -0
  132. data/lib/nokogiri/html/document_fragment.rb +15 -15
  133. data/lib/nokogiri/nokogiri.jar +0 -0
  134. data/lib/nokogiri/version/constant.rb +1 -1
  135. data/lib/nokogiri/version/info.rb +32 -8
  136. data/lib/nokogiri/xml/document.rb +74 -28
  137. data/lib/nokogiri/xml/node.rb +39 -42
  138. data/lib/nokogiri/xml/reader.rb +2 -9
  139. data/lib/nokogiri/xml/xpath.rb +1 -3
  140. data/lib/nokogiri/xml/xpath/syntax_error.rb +1 -1
  141. metadata +7 -8
  142. data/ext/nokogiri/xml_io.c +0 -63
  143. data/ext/nokogiri/xml_libxml2_hacks.c +0 -112
@@ -43,597 +43,622 @@ import org.w3c.dom.Node;
43
43
  * @author Sean Mullan
44
44
  * @author Raul Benito
45
45
  */
46
- public abstract class Canonicalizer11 extends CanonicalizerBase {
47
-
48
- private static final String XMLNS_URI = Constants.NamespaceSpecNS;
49
- private static final String XML_LANG_URI = Constants.XML_LANG_SPACE_SpecNS;
50
- private final SortedSet<Attr> result = new TreeSet<Attr>(COMPARE);
51
-
52
- private boolean firstCall = true;
46
+ public abstract class Canonicalizer11 extends CanonicalizerBase
47
+ {
48
+
49
+ private static final String XMLNS_URI = Constants.NamespaceSpecNS;
50
+ private static final String XML_LANG_URI = Constants.XML_LANG_SPACE_SpecNS;
51
+ private final SortedSet<Attr> result = new TreeSet<Attr>(COMPARE);
52
+
53
+ private boolean firstCall = true;
54
+
55
+ private static class XmlAttrStack
56
+ {
57
+ static class XmlsStackElement
58
+ {
59
+ int level;
60
+ boolean rendered = false;
61
+ List<Attr> nodes = new ArrayList<Attr>();
62
+ }
53
63
 
54
- private static class XmlAttrStack {
55
- static class XmlsStackElement {
56
- int level;
57
- boolean rendered = false;
58
- List<Attr> nodes = new ArrayList<Attr>();
64
+ int currentLevel = 0;
65
+ int lastlevel = 0;
66
+ XmlsStackElement cur;
67
+ List<XmlsStackElement> levels = new ArrayList<XmlsStackElement>();
68
+
69
+ void
70
+ push(int level)
71
+ {
72
+ currentLevel = level;
73
+ if (currentLevel == -1) {
74
+ return;
75
+ }
76
+ cur = null;
77
+ while (lastlevel >= currentLevel) {
78
+ levels.remove(levels.size() - 1);
79
+ int newSize = levels.size();
80
+ if (newSize == 0) {
81
+ lastlevel = 0;
82
+ return;
59
83
  }
84
+ lastlevel = (levels.get(newSize - 1)).level;
85
+ }
86
+ }
60
87
 
61
- int currentLevel = 0;
62
- int lastlevel = 0;
63
- XmlsStackElement cur;
64
- List<XmlsStackElement> levels = new ArrayList<XmlsStackElement>();
88
+ void
89
+ addXmlnsAttr(Attr n)
90
+ {
91
+ if (cur == null) {
92
+ cur = new XmlsStackElement();
93
+ cur.level = currentLevel;
94
+ levels.add(cur);
95
+ lastlevel = currentLevel;
96
+ }
97
+ cur.nodes.add(n);
98
+ }
65
99
 
66
- void push(int level) {
67
- currentLevel = level;
68
- if (currentLevel == -1) {
69
- return;
70
- }
71
- cur = null;
72
- while (lastlevel >= currentLevel) {
73
- levels.remove(levels.size() - 1);
74
- int newSize = levels.size();
75
- if (newSize == 0) {
76
- lastlevel = 0;
77
- return;
78
- }
79
- lastlevel = (levels.get(newSize - 1)).level;
80
- }
100
+ void
101
+ getXmlnsAttr(Collection<Attr> col) throws CanonicalizationException
102
+ {
103
+ int size = levels.size() - 1;
104
+ if (cur == null) {
105
+ cur = new XmlsStackElement();
106
+ cur.level = currentLevel;
107
+ lastlevel = currentLevel;
108
+ levels.add(cur);
109
+ }
110
+ boolean parentRendered = false;
111
+ if (size == -1) {
112
+ parentRendered = true;
113
+ } else {
114
+ XmlsStackElement e = levels.get(size);
115
+ if (e.rendered && e.level + 1 == currentLevel) {
116
+ parentRendered = true;
81
117
  }
82
-
83
- void addXmlnsAttr(Attr n) {
84
- if (cur == null) {
85
- cur = new XmlsStackElement();
86
- cur.level = currentLevel;
87
- levels.add(cur);
88
- lastlevel = currentLevel;
89
- }
90
- cur.nodes.add(n);
118
+ }
119
+ if (parentRendered) {
120
+ col.addAll(cur.nodes);
121
+ cur.rendered = true;
122
+ return;
123
+ }
124
+
125
+ Map<String, Attr> loa = new HashMap<String, Attr>();
126
+ List<Attr> baseAttrs = new ArrayList<Attr>();
127
+ boolean successiveOmitted = true;
128
+ for (; size >= 0; size--) {
129
+ XmlsStackElement e = levels.get(size);
130
+ if (e.rendered) {
131
+ successiveOmitted = false;
91
132
  }
92
-
93
- void getXmlnsAttr(Collection<Attr> col) throws CanonicalizationException {
94
- int size = levels.size() - 1;
95
- if (cur == null) {
96
- cur = new XmlsStackElement();
97
- cur.level = currentLevel;
98
- lastlevel = currentLevel;
99
- levels.add(cur);
100
- }
101
- boolean parentRendered = false;
102
- if (size == -1) {
103
- parentRendered = true;
104
- } else {
105
- XmlsStackElement e = levels.get(size);
106
- if (e.rendered && e.level + 1 == currentLevel) {
107
- parentRendered = true;
108
- }
109
- }
110
- if (parentRendered) {
111
- col.addAll(cur.nodes);
112
- cur.rendered = true;
113
- return;
114
- }
115
-
116
- Map<String, Attr> loa = new HashMap<String, Attr>();
117
- List<Attr> baseAttrs = new ArrayList<Attr>();
118
- boolean successiveOmitted = true;
119
- for (; size >= 0; size--) {
120
- XmlsStackElement e = levels.get(size);
121
- if (e.rendered) {
122
- successiveOmitted = false;
123
- }
124
- Iterator<Attr> it = e.nodes.iterator();
125
- while (it.hasNext() && successiveOmitted) {
126
- Attr n = it.next();
127
- if (n.getLocalName().equals("base") && !e.rendered) {
128
- baseAttrs.add(n);
129
- } else if (!loa.containsKey(n.getName())) {
130
- loa.put(n.getName(), n);
131
- }
132
- }
133
- }
134
- if (!baseAttrs.isEmpty()) {
135
- Iterator<Attr> it = col.iterator();
136
- String base = null;
137
- Attr baseAttr = null;
138
- while (it.hasNext()) {
139
- Attr n = it.next();
140
- if (n.getLocalName().equals("base")) {
141
- base = n.getValue();
142
- baseAttr = n;
143
- break;
144
- }
145
- }
146
- it = baseAttrs.iterator();
147
- while (it.hasNext()) {
148
- Attr n = it.next();
149
- if (base == null) {
150
- base = n.getValue();
151
- baseAttr = n;
152
- } else {
153
- try {
154
- base = joinURI(n.getValue(), base);
155
- } catch (URISyntaxException e1) {
156
- throw new CanonicalizationException(e1);
157
- }
158
- }
159
- }
160
- if (base != null && base.length() != 0) {
161
- baseAttr.setValue(base);
162
- col.add(baseAttr);
163
- }
164
- }
165
-
166
- cur.rendered = true;
167
- col.addAll(loa.values());
133
+ Iterator<Attr> it = e.nodes.iterator();
134
+ while (it.hasNext() && successiveOmitted) {
135
+ Attr n = it.next();
136
+ if (n.getLocalName().equals("base") && !e.rendered) {
137
+ baseAttrs.add(n);
138
+ } else if (!loa.containsKey(n.getName())) {
139
+ loa.put(n.getName(), n);
140
+ }
168
141
  }
169
- }
170
-
171
- private final XmlAttrStack xmlattrStack = new XmlAttrStack();
172
-
173
- /**
174
- * Constructor Canonicalizer11
175
- *
176
- * @param includeComments
177
- */
178
- public Canonicalizer11(boolean includeComments) {
179
- super(includeComments);
180
- }
181
-
182
- /**
183
- * Always throws a CanonicalizationException because this is inclusive c14n.
184
- *
185
- * @param rootNode
186
- * @param inclusiveNamespaces
187
- * @return none it always fails
188
- * @throws CanonicalizationException
189
- */
190
- public byte[] engineCanonicalizeSubTree(
191
- Node rootNode, String inclusiveNamespaces, CanonicalFilter filter
192
- ) throws CanonicalizationException {
193
- throw new CanonicalizationException("c14n.Canonicalizer.UnsupportedOperation");
194
- }
195
-
196
- /**
197
- * Returns the Attr[]s to be output for the given element.
198
- * <br>
199
- * The code of this method is a copy of {@link #handleAttributes(Element,
200
- * NameSpaceSymbTable)},
201
- * whereas it takes into account that subtree-c14n is -- well --
202
- * subtree-based.
203
- * So if the element in question isRoot of c14n, it's parent is not in the
204
- * node set, as well as all other ancestors.
205
- *
206
- * @param element
207
- * @param ns
208
- * @return the Attr[]s to be output
209
- * @throws CanonicalizationException
210
- * @throws URISyntaxException
211
- */
212
- @Override
213
- protected Iterator<Attr> handleAttributesSubtree(Element element, NameSpaceSymbTable ns)
214
- throws CanonicalizationException {
215
- if (!element.hasAttributes() && !firstCall) {
216
- return null;
142
+ }
143
+ if (!baseAttrs.isEmpty()) {
144
+ Iterator<Attr> it = col.iterator();
145
+ String base = null;
146
+ Attr baseAttr = null;
147
+ while (it.hasNext()) {
148
+ Attr n = it.next();
149
+ if (n.getLocalName().equals("base")) {
150
+ base = n.getValue();
151
+ baseAttr = n;
152
+ break;
153
+ }
217
154
  }
218
- // result will contain the attrs which have to be output
219
- final SortedSet<Attr> result = this.result;
220
- result.clear();
221
-
222
- if (element.hasAttributes()) {
223
- NamedNodeMap attrs = element.getAttributes();
224
- int attrsLength = attrs.getLength();
225
-
226
- for (int i = 0; i < attrsLength; i++) {
227
- Attr attribute = (Attr) attrs.item(i);
228
- String NUri = attribute.getNamespaceURI();
229
- String NName = attribute.getLocalName();
230
- String NValue = attribute.getValue();
231
-
232
- if (!XMLNS_URI.equals(NUri)) {
233
- // It's not a namespace attr node. Add to the result and continue.
234
- result.add(attribute);
235
- } else if (!(XML.equals(NName) && XML_LANG_URI.equals(NValue))) {
236
- // The default mapping for xml must not be output.
237
- Node n = ns.addMappingAndRender(NName, NValue, attribute);
238
-
239
- if (n != null) {
240
- // Render the ns definition
241
- result.add((Attr)n);
242
- if (C14nHelper.namespaceIsRelative(attribute)) {
243
- Object exArgs[] = {element.getTagName(), NName, attribute.getNodeValue()};
244
- throw new CanonicalizationException(
245
- "c14n.Canonicalizer.RelativeNamespace", exArgs
246
- );
247
- }
248
- }
249
- }
155
+ it = baseAttrs.iterator();
156
+ while (it.hasNext()) {
157
+ Attr n = it.next();
158
+ if (base == null) {
159
+ base = n.getValue();
160
+ baseAttr = n;
161
+ } else {
162
+ try {
163
+ base = joinURI(n.getValue(), base);
164
+ } catch (URISyntaxException e1) {
165
+ throw new CanonicalizationException(e1);
250
166
  }
167
+ }
251
168
  }
252
-
253
- if (firstCall) {
254
- // It is the first node of the subtree
255
- // Obtain all the namespaces defined in the parents, and added to the output.
256
- ns.getUnrenderedNodes(result);
257
- // output the attributes in the xml namespace.
258
- xmlattrStack.getXmlnsAttr(result);
259
- firstCall = false;
169
+ if (base != null && base.length() != 0) {
170
+ baseAttr.setValue(base);
171
+ col.add(baseAttr);
260
172
  }
173
+ }
261
174
 
262
- return result.iterator();
175
+ cur.rendered = true;
176
+ col.addAll(loa.values());
263
177
  }
264
-
265
- /**
266
- * Returns the Attr[]s to be output for the given element.
267
- * <br>
268
- * IMPORTANT: This method expects to work on a modified DOM tree, i.e. a
269
- * DOM which has been prepared using
270
- * {@link nokogiri.internals.c14n.security.utils.XMLUtils#circumventBug2650(
271
- * org.w3c.dom.Document)}.
272
- *
273
- * @param element
274
- * @param ns
275
- * @return the Attr[]s to be output
276
- * @throws CanonicalizationException
277
- */
278
- @Override
279
- protected Iterator<Attr> handleAttributes(Element element, NameSpaceSymbTable ns)
280
- throws CanonicalizationException {
281
- // result will contain the attrs which have to be output
282
- xmlattrStack.push(ns.getLevel());
283
- boolean isRealVisible = isVisibleDO(element, ns.getLevel()) == 1;
284
- final SortedSet<Attr> result = this.result;
285
- result.clear();
286
-
287
- if (element.hasAttributes()) {
288
- NamedNodeMap attrs = element.getAttributes();
289
- int attrsLength = attrs.getLength();
290
-
291
- for (int i = 0; i < attrsLength; i++) {
292
- Attr attribute = (Attr) attrs.item(i);
293
- String NUri = attribute.getNamespaceURI();
294
- String NName = attribute.getLocalName();
295
- String NValue = attribute.getValue();
296
-
297
- if (!XMLNS_URI.equals(NUri)) {
298
- //A non namespace definition node.
299
- if (XML_LANG_URI.equals(NUri)) {
300
- if (NName.equals("id")) {
301
- if (isRealVisible) {
302
- // treat xml:id like any other attribute
303
- // (emit it, but don't inherit it)
304
- result.add(attribute);
305
- }
306
- } else {
307
- xmlattrStack.addXmlnsAttr(attribute);
308
- }
309
- } else if (isRealVisible) {
310
- //The node is visible add the attribute to the list of output attributes.
311
- result.add(attribute);
312
- }
313
- } else if (!XML.equals(NName) || !XML_LANG_URI.equals(NValue)) {
314
- /* except omit namespace node with local name xml, which defines
315
- * the xml prefix, if its string value is
316
- * http://www.w3.org/XML/1998/namespace.
317
- */
318
- // add the prefix binding to the ns symb table.
319
- if (isVisible(attribute)) {
320
- if (isRealVisible || !ns.removeMappingIfRender(NName)) {
321
- // The xpath select this node output it if needed.
322
- Node n = ns.addMappingAndRender(NName, NValue, attribute);
323
- if (n != null) {
324
- result.add((Attr)n);
325
- if (C14nHelper.namespaceIsRelative(attribute)) {
326
- Object exArgs[] = { element.getTagName(), NName, attribute.getNodeValue() };
327
- throw new CanonicalizationException(
328
- "c14n.Canonicalizer.RelativeNamespace", exArgs
329
- );
330
- }
331
- }
332
- }
333
- } else {
334
- if (isRealVisible && !XMLNS.equals(NName)) {
335
- ns.removeMapping(NName);
336
- } else {
337
- ns.addMapping(NName, NValue, attribute);
338
- }
339
- }
340
- }
341
- }
342
- }
343
-
344
- if (isRealVisible) {
345
- //The element is visible, handle the xmlns definition
346
- Attr xmlns = element.getAttributeNodeNS(XMLNS_URI, XMLNS);
347
- Node n = null;
348
- if (xmlns == null) {
349
- //No xmlns def just get the already defined.
350
- n = ns.getMapping(XMLNS);
351
- } else if (!isVisible(xmlns)) {
352
- //There is a definition but the xmlns is not selected by the xpath.
353
- //then xmlns=""
354
- n = ns.addMappingAndRender(XMLNS, "", nullNode);
355
- }
356
- //output the xmlns def if needed.
357
- if (n != null) {
358
- result.add((Attr)n);
178
+ }
179
+
180
+ private final XmlAttrStack xmlattrStack = new XmlAttrStack();
181
+
182
+ /**
183
+ * Constructor Canonicalizer11
184
+ *
185
+ * @param includeComments
186
+ */
187
+ public
188
+ Canonicalizer11(boolean includeComments)
189
+ {
190
+ super(includeComments);
191
+ }
192
+
193
+ /**
194
+ * Always throws a CanonicalizationException because this is inclusive c14n.
195
+ *
196
+ * @param rootNode
197
+ * @param inclusiveNamespaces
198
+ * @return none it always fails
199
+ * @throws CanonicalizationException
200
+ */
201
+ public byte[]
202
+ engineCanonicalizeSubTree(
203
+ Node rootNode, String inclusiveNamespaces, CanonicalFilter filter
204
+ ) throws CanonicalizationException
205
+ {
206
+ throw new CanonicalizationException("c14n.Canonicalizer.UnsupportedOperation");
207
+ }
208
+
209
+ /**
210
+ * Returns the Attr[]s to be output for the given element.
211
+ * <br>
212
+ * The code of this method is a copy of {@link #handleAttributes(Element,
213
+ * NameSpaceSymbTable)},
214
+ * whereas it takes into account that subtree-c14n is -- well --
215
+ * subtree-based.
216
+ * So if the element in question isRoot of c14n, it's parent is not in the
217
+ * node set, as well as all other ancestors.
218
+ *
219
+ * @param element
220
+ * @param ns
221
+ * @return the Attr[]s to be output
222
+ * @throws CanonicalizationException
223
+ * @throws URISyntaxException
224
+ */
225
+ @Override
226
+ protected Iterator<Attr>
227
+ handleAttributesSubtree(Element element, NameSpaceSymbTable ns)
228
+ throws CanonicalizationException
229
+ {
230
+ if (!element.hasAttributes() && !firstCall) {
231
+ return null;
232
+ }
233
+ // result will contain the attrs which have to be output
234
+ final SortedSet<Attr> result = this.result;
235
+ result.clear();
236
+
237
+ if (element.hasAttributes()) {
238
+ NamedNodeMap attrs = element.getAttributes();
239
+ int attrsLength = attrs.getLength();
240
+
241
+ for (int i = 0; i < attrsLength; i++) {
242
+ Attr attribute = (Attr) attrs.item(i);
243
+ String NUri = attribute.getNamespaceURI();
244
+ String NName = attribute.getLocalName();
245
+ String NValue = attribute.getValue();
246
+
247
+ if (!XMLNS_URI.equals(NUri)) {
248
+ // It's not a namespace attr node. Add to the result and continue.
249
+ result.add(attribute);
250
+ } else if (!(XML.equals(NName) && XML_LANG_URI.equals(NValue))) {
251
+ // The default mapping for xml must not be output.
252
+ Node n = ns.addMappingAndRender(NName, NValue, attribute);
253
+
254
+ if (n != null) {
255
+ // Render the ns definition
256
+ result.add((Attr)n);
257
+ if (C14nHelper.namespaceIsRelative(attribute)) {
258
+ Object exArgs[] = {element.getTagName(), NName, attribute.getNodeValue()};
259
+ throw new CanonicalizationException(
260
+ "c14n.Canonicalizer.RelativeNamespace", exArgs
261
+ );
359
262
  }
360
- //Float all xml:* attributes of the unselected parent elements to this one.
361
- xmlattrStack.getXmlnsAttr(result);
362
- ns.getUnrenderedNodes(result);
263
+ }
363
264
  }
265
+ }
266
+ }
364
267
 
365
- return result.iterator();
268
+ if (firstCall) {
269
+ // It is the first node of the subtree
270
+ // Obtain all the namespaces defined in the parents, and added to the output.
271
+ ns.getUnrenderedNodes(result);
272
+ // output the attributes in the xml namespace.
273
+ xmlattrStack.getXmlnsAttr(result);
274
+ firstCall = false;
366
275
  }
367
276
 
368
- @Override
369
- protected void handleParent(Element e, NameSpaceSymbTable ns) {
370
- if (!e.hasAttributes() && e.getNamespaceURI() == null) {
371
- return;
372
- }
373
- xmlattrStack.push(-1);
374
- NamedNodeMap attrs = e.getAttributes();
375
- int attrsLength = attrs.getLength();
376
- for (int i = 0; i < attrsLength; i++) {
377
- Attr attribute = (Attr) attrs.item(i);
378
- String NName = attribute.getLocalName();
379
- String NValue = attribute.getNodeValue();
380
-
381
- if (Constants.NamespaceSpecNS.equals(attribute.getNamespaceURI())) {
382
- if (!XML.equals(NName) || !Constants.XML_LANG_SPACE_SpecNS.equals(NValue)) {
383
- ns.addMapping(NName, NValue, attribute);
277
+ return result.iterator();
278
+ }
279
+
280
+ /**
281
+ * Returns the Attr[]s to be output for the given element.
282
+ * <br>
283
+ * IMPORTANT: This method expects to work on a modified DOM tree, i.e. a
284
+ * DOM which has been prepared using
285
+ * {@link nokogiri.internals.c14n.security.utils.XMLUtils#circumventBug2650(
286
+ * org.w3c.dom.Document)}.
287
+ *
288
+ * @param element
289
+ * @param ns
290
+ * @return the Attr[]s to be output
291
+ * @throws CanonicalizationException
292
+ */
293
+ @Override
294
+ protected Iterator<Attr>
295
+ handleAttributes(Element element, NameSpaceSymbTable ns)
296
+ throws CanonicalizationException
297
+ {
298
+ // result will contain the attrs which have to be output
299
+ xmlattrStack.push(ns.getLevel());
300
+ boolean isRealVisible = isVisibleDO(element, ns.getLevel()) == 1;
301
+ final SortedSet<Attr> result = this.result;
302
+ result.clear();
303
+
304
+ if (element.hasAttributes()) {
305
+ NamedNodeMap attrs = element.getAttributes();
306
+ int attrsLength = attrs.getLength();
307
+
308
+ for (int i = 0; i < attrsLength; i++) {
309
+ Attr attribute = (Attr) attrs.item(i);
310
+ String NUri = attribute.getNamespaceURI();
311
+ String NName = attribute.getLocalName();
312
+ String NValue = attribute.getValue();
313
+
314
+ if (!XMLNS_URI.equals(NUri)) {
315
+ //A non namespace definition node.
316
+ if (XML_LANG_URI.equals(NUri)) {
317
+ if (NName.equals("id")) {
318
+ if (isRealVisible) {
319
+ // treat xml:id like any other attribute
320
+ // (emit it, but don't inherit it)
321
+ result.add(attribute);
322
+ }
323
+ } else {
324
+ xmlattrStack.addXmlnsAttr(attribute);
325
+ }
326
+ } else if (isRealVisible) {
327
+ //The node is visible add the attribute to the list of output attributes.
328
+ result.add(attribute);
329
+ }
330
+ } else if (!XML.equals(NName) || !XML_LANG_URI.equals(NValue)) {
331
+ /* except omit namespace node with local name xml, which defines
332
+ * the xml prefix, if its string value is
333
+ * http://www.w3.org/XML/1998/namespace.
334
+ */
335
+ // add the prefix binding to the ns symb table.
336
+ if (isVisible(attribute)) {
337
+ if (isRealVisible || !ns.removeMappingIfRender(NName)) {
338
+ // The xpath select this node output it if needed.
339
+ Node n = ns.addMappingAndRender(NName, NValue, attribute);
340
+ if (n != null) {
341
+ result.add((Attr)n);
342
+ if (C14nHelper.namespaceIsRelative(attribute)) {
343
+ Object exArgs[] = { element.getTagName(), NName, attribute.getNodeValue() };
344
+ throw new CanonicalizationException(
345
+ "c14n.Canonicalizer.RelativeNamespace", exArgs
346
+ );
384
347
  }
385
- } else if (!"id".equals(NName) && XML_LANG_URI.equals(attribute.getNamespaceURI())) {
386
- xmlattrStack.addXmlnsAttr(attribute);
348
+ }
387
349
  }
388
- }
389
- if (e.getNamespaceURI() != null) {
390
- String NName = e.getPrefix();
391
- String NValue = e.getNamespaceURI();
392
- String Name;
393
- if (NName == null || NName.equals("")) {
394
- NName = "xmlns";
395
- Name = "xmlns";
350
+ } else {
351
+ if (isRealVisible && !XMLNS.equals(NName)) {
352
+ ns.removeMapping(NName);
396
353
  } else {
397
- Name = "xmlns:" + NName;
354
+ ns.addMapping(NName, NValue, attribute);
398
355
  }
399
- Attr n = e.getOwnerDocument().createAttributeNS("http://www.w3.org/2000/xmlns/", Name);
400
- n.setValue(NValue);
401
- ns.addMapping(NName, NValue, n);
356
+ }
402
357
  }
358
+ }
403
359
  }
404
360
 
405
- private static String joinURI(String baseURI, String relativeURI) throws URISyntaxException {
406
- String bscheme = null;
407
- String bauthority = null;
408
- String bpath = "";
409
- String bquery = null;
361
+ if (isRealVisible) {
362
+ //The element is visible, handle the xmlns definition
363
+ Attr xmlns = element.getAttributeNodeNS(XMLNS_URI, XMLNS);
364
+ Node n = null;
365
+ if (xmlns == null) {
366
+ //No xmlns def just get the already defined.
367
+ n = ns.getMapping(XMLNS);
368
+ } else if (!isVisible(xmlns)) {
369
+ //There is a definition but the xmlns is not selected by the xpath.
370
+ //then xmlns=""
371
+ n = ns.addMappingAndRender(XMLNS, "", nullNode);
372
+ }
373
+ //output the xmlns def if needed.
374
+ if (n != null) {
375
+ result.add((Attr)n);
376
+ }
377
+ //Float all xml:* attributes of the unselected parent elements to this one.
378
+ xmlattrStack.getXmlnsAttr(result);
379
+ ns.getUnrenderedNodes(result);
380
+ }
410
381
 
411
- // pre-parse the baseURI
412
- if (baseURI != null) {
413
- if (baseURI.endsWith("..")) {
414
- baseURI = baseURI + "/";
415
- }
416
- URI base = new URI(baseURI);
417
- bscheme = base.getScheme();
418
- bauthority = base.getAuthority();
419
- bpath = base.getPath();
420
- bquery = base.getQuery();
382
+ return result.iterator();
383
+ }
384
+
385
+ @Override
386
+ protected void
387
+ handleParent(Element e, NameSpaceSymbTable ns)
388
+ {
389
+ if (!e.hasAttributes() && e.getNamespaceURI() == null) {
390
+ return;
391
+ }
392
+ xmlattrStack.push(-1);
393
+ NamedNodeMap attrs = e.getAttributes();
394
+ int attrsLength = attrs.getLength();
395
+ for (int i = 0; i < attrsLength; i++) {
396
+ Attr attribute = (Attr) attrs.item(i);
397
+ String NName = attribute.getLocalName();
398
+ String NValue = attribute.getNodeValue();
399
+
400
+ if (Constants.NamespaceSpecNS.equals(attribute.getNamespaceURI())) {
401
+ if (!XML.equals(NName) || !Constants.XML_LANG_SPACE_SpecNS.equals(NValue)) {
402
+ ns.addMapping(NName, NValue, attribute);
421
403
  }
404
+ } else if (!"id".equals(NName) && XML_LANG_URI.equals(attribute.getNamespaceURI())) {
405
+ xmlattrStack.addXmlnsAttr(attribute);
406
+ }
407
+ }
408
+ if (e.getNamespaceURI() != null) {
409
+ String NName = e.getPrefix();
410
+ String NValue = e.getNamespaceURI();
411
+ String Name;
412
+ if (NName == null || NName.equals("")) {
413
+ NName = "xmlns";
414
+ Name = "xmlns";
415
+ } else {
416
+ Name = "xmlns:" + NName;
417
+ }
418
+ Attr n = e.getOwnerDocument().createAttributeNS("http://www.w3.org/2000/xmlns/", Name);
419
+ n.setValue(NValue);
420
+ ns.addMapping(NName, NValue, n);
421
+ }
422
+ }
423
+
424
+ private static String
425
+ joinURI(String baseURI, String relativeURI) throws URISyntaxException
426
+ {
427
+ String bscheme = null;
428
+ String bauthority = null;
429
+ String bpath = "";
430
+ String bquery = null;
431
+
432
+ // pre-parse the baseURI
433
+ if (baseURI != null) {
434
+ if (baseURI.endsWith("..")) {
435
+ baseURI = baseURI + "/";
436
+ }
437
+ URI base = new URI(baseURI);
438
+ bscheme = base.getScheme();
439
+ bauthority = base.getAuthority();
440
+ bpath = base.getPath();
441
+ bquery = base.getQuery();
442
+ }
422
443
 
423
- URI r = new URI(relativeURI);
424
- String rscheme = r.getScheme();
425
- String rauthority = r.getAuthority();
426
- String rpath = r.getPath();
427
- String rquery = r.getQuery();
444
+ URI r = new URI(relativeURI);
445
+ String rscheme = r.getScheme();
446
+ String rauthority = r.getAuthority();
447
+ String rpath = r.getPath();
448
+ String rquery = r.getQuery();
428
449
 
429
- String tscheme, tauthority, tpath, tquery;
430
- if (rscheme != null && rscheme.equals(bscheme)) {
431
- rscheme = null;
432
- }
433
- if (rscheme != null) {
434
- tscheme = rscheme;
435
- tauthority = rauthority;
436
- tpath = removeDotSegments(rpath);
450
+ String tscheme, tauthority, tpath, tquery;
451
+ if (rscheme != null && rscheme.equals(bscheme)) {
452
+ rscheme = null;
453
+ }
454
+ if (rscheme != null) {
455
+ tscheme = rscheme;
456
+ tauthority = rauthority;
457
+ tpath = removeDotSegments(rpath);
458
+ tquery = rquery;
459
+ } else {
460
+ if (rauthority != null) {
461
+ tauthority = rauthority;
462
+ tpath = removeDotSegments(rpath);
463
+ tquery = rquery;
464
+ } else {
465
+ if (rpath.length() == 0) {
466
+ tpath = bpath;
467
+ if (rquery != null) {
437
468
  tquery = rquery;
469
+ } else {
470
+ tquery = bquery;
471
+ }
438
472
  } else {
439
- if (rauthority != null) {
440
- tauthority = rauthority;
441
- tpath = removeDotSegments(rpath);
442
- tquery = rquery;
473
+ if (rpath.startsWith("/")) {
474
+ tpath = removeDotSegments(rpath);
475
+ } else {
476
+ if (bauthority != null && bpath.length() == 0) {
477
+ tpath = "/" + rpath;
443
478
  } else {
444
- if (rpath.length() == 0) {
445
- tpath = bpath;
446
- if (rquery != null) {
447
- tquery = rquery;
448
- } else {
449
- tquery = bquery;
450
- }
451
- } else {
452
- if (rpath.startsWith("/")) {
453
- tpath = removeDotSegments(rpath);
454
- } else {
455
- if (bauthority != null && bpath.length() == 0) {
456
- tpath = "/" + rpath;
457
- } else {
458
- int last = bpath.lastIndexOf('/');
459
- if (last == -1) {
460
- tpath = rpath;
461
- } else {
462
- tpath = bpath.substring(0, last+1) + rpath;
463
- }
464
- }
465
- tpath = removeDotSegments(tpath);
466
- }
467
- tquery = rquery;
468
- }
469
- tauthority = bauthority;
479
+ int last = bpath.lastIndexOf('/');
480
+ if (last == -1) {
481
+ tpath = rpath;
482
+ } else {
483
+ tpath = bpath.substring(0, last + 1) + rpath;
484
+ }
470
485
  }
471
- tscheme = bscheme;
486
+ tpath = removeDotSegments(tpath);
487
+ }
488
+ tquery = rquery;
472
489
  }
473
- return new URI(tscheme, tauthority, tpath, tquery, null).toString();
490
+ tauthority = bauthority;
491
+ }
492
+ tscheme = bscheme;
493
+ }
494
+ return new URI(tscheme, tauthority, tpath, tquery, null).toString();
495
+ }
496
+
497
+ private static String
498
+ removeDotSegments(String path)
499
+ {
500
+
501
+ // 1. The input buffer is initialized with the now-appended path
502
+ // components then replace occurrences of "//" in the input buffer
503
+ // with "/" until no more occurrences of "//" are in the input buffer.
504
+ String input = path;
505
+ while (input.indexOf("//") > -1) {
506
+ input = input.replaceAll("//", "/");
474
507
  }
475
508
 
476
- private static String removeDotSegments(String path) {
477
-
478
- // 1. The input buffer is initialized with the now-appended path
479
- // components then replace occurrences of "//" in the input buffer
480
- // with "/" until no more occurrences of "//" are in the input buffer.
481
- String input = path;
482
- while (input.indexOf("//") > -1) {
483
- input = input.replaceAll("//", "/");
484
- }
509
+ // Initialize the output buffer with the empty string.
510
+ StringBuilder output = new StringBuilder();
485
511
 
486
- // Initialize the output buffer with the empty string.
487
- StringBuilder output = new StringBuilder();
512
+ // If the input buffer starts with a root slash "/" then move this
513
+ // character to the output buffer.
514
+ if (input.charAt(0) == '/') {
515
+ output.append('/');
516
+ input = input.substring(1);
517
+ }
488
518
 
489
- // If the input buffer starts with a root slash "/" then move this
490
- // character to the output buffer.
491
- if (input.charAt(0) == '/') {
492
- output.append('/');
493
- input = input.substring(1);
519
+ printStep("1 ", output, input);
520
+
521
+ // While the input buffer is not empty, loop as follows
522
+ while (input.length() != 0) {
523
+ // 2A. If the input buffer begins with a prefix of "./",
524
+ // then remove that prefix from the input buffer
525
+ // else if the input buffer begins with a prefix of "../", then
526
+ // if also the output does not contain the root slash "/" only,
527
+ // then move this prefix to the end of the output buffer else
528
+ // remove that prefix
529
+ if (input.startsWith("./")) {
530
+ input = input.substring(2);
531
+ printStep("2A", output, input);
532
+ } else if (input.startsWith("../")) {
533
+ input = input.substring(3);
534
+ if (!output.toString().equals("/")) {
535
+ output.append("../");
494
536
  }
495
-
496
- printStep("1 ", output, input);
497
-
498
- // While the input buffer is not empty, loop as follows
499
- while (input.length() != 0) {
500
- // 2A. If the input buffer begins with a prefix of "./",
501
- // then remove that prefix from the input buffer
502
- // else if the input buffer begins with a prefix of "../", then
503
- // if also the output does not contain the root slash "/" only,
504
- // then move this prefix to the end of the output buffer else
505
- // remove that prefix
506
- if (input.startsWith("./")) {
507
- input = input.substring(2);
508
- printStep("2A", output, input);
509
- } else if (input.startsWith("../")) {
510
- input = input.substring(3);
511
- if (!output.toString().equals("/")) {
512
- output.append("../");
513
- }
514
- printStep("2A", output, input);
515
- // 2B. if the input buffer begins with a prefix of "/./" or "/.",
516
- // where "." is a complete path segment, then replace that prefix
517
- // with "/" in the input buffer; otherwise,
518
- } else if (input.startsWith("/./")) {
519
- input = input.substring(2);
520
- printStep("2B", output, input);
521
- } else if (input.equals("/.")) {
522
- // FIXME: what is complete path segment?
523
- input = input.replaceFirst("/.", "/");
524
- printStep("2B", output, input);
525
- // 2C. if the input buffer begins with a prefix of "/../" or "/..",
526
- // where ".." is a complete path segment, then replace that prefix
527
- // with "/" in the input buffer and if also the output buffer is
528
- // empty, last segment in the output buffer equals "../" or "..",
529
- // where ".." is a complete path segment, then append ".." or "/.."
530
- // for the latter case respectively to the output buffer else
531
- // remove the last segment and its preceding "/" (if any) from the
532
- // output buffer and if hereby the first character in the output
533
- // buffer was removed and it was not the root slash then delete a
534
- // leading slash from the input buffer; otherwise,
535
- } else if (input.startsWith("/../")) {
536
- input = input.substring(3);
537
- if (output.length() == 0) {
538
- output.append("/");
539
- } else if (output.toString().endsWith("../")) {
540
- output.append("..");
541
- } else if (output.toString().endsWith("..")) {
542
- output.append("/..");
543
- } else {
544
- int index = output.lastIndexOf("/");
545
- if (index == -1) {
546
- output = new StringBuilder();
547
- if (input.charAt(0) == '/') {
548
- input = input.substring(1);
549
- }
550
- } else {
551
- output = output.delete(index, output.length());
552
- }
553
- }
554
- printStep("2C", output, input);
555
- } else if (input.equals("/..")) {
556
- // FIXME: what is complete path segment?
557
- input = input.replaceFirst("/..", "/");
558
- if (output.length() == 0) {
559
- output.append("/");
560
- } else if (output.toString().endsWith("../")) {
561
- output.append("..");
562
- } else if (output.toString().endsWith("..")) {
563
- output.append("/..");
564
- } else {
565
- int index = output.lastIndexOf("/");
566
- if (index == -1) {
567
- output = new StringBuilder();
568
- if (input.charAt(0) == '/') {
569
- input = input.substring(1);
570
- }
571
- } else {
572
- output = output.delete(index, output.length());
573
- }
574
- }
575
- printStep("2C", output, input);
576
- // 2D. if the input buffer consists only of ".", then remove
577
- // that from the input buffer else if the input buffer consists
578
- // only of ".." and if the output buffer does not contain only
579
- // the root slash "/", then move the ".." to the output buffer
580
- // else delte it.; otherwise,
581
- } else if (input.equals(".")) {
582
- input = "";
583
- printStep("2D", output, input);
584
- } else if (input.equals("..")) {
585
- if (!output.toString().equals("/")) {
586
- output.append("..");
587
- }
588
- input = "";
589
- printStep("2D", output, input);
590
- // 2E. move the first path segment (if any) in the input buffer
591
- // to the end of the output buffer, including the initial "/"
592
- // character (if any) and any subsequent characters up to, but not
593
- // including, the next "/" character or the end of the input buffer.
594
- } else {
595
- int end;
596
- int begin = input.indexOf('/');
597
- if (begin == 0) {
598
- end = input.indexOf('/', 1);
599
- } else {
600
- end = begin;
601
- begin = 0;
602
- }
603
- String segment;
604
- if (end == -1) {
605
- segment = input.substring(begin);
606
- input = "";
607
- } else {
608
- segment = input.substring(begin, end);
609
- input = input.substring(end);
610
- }
611
- output.append(segment);
612
- printStep("2E", output, input);
537
+ printStep("2A", output, input);
538
+ // 2B. if the input buffer begins with a prefix of "/./" or "/.",
539
+ // where "." is a complete path segment, then replace that prefix
540
+ // with "/" in the input buffer; otherwise,
541
+ } else if (input.startsWith("/./")) {
542
+ input = input.substring(2);
543
+ printStep("2B", output, input);
544
+ } else if (input.equals("/.")) {
545
+ // FIXME: what is complete path segment?
546
+ input = input.replaceFirst("/.", "/");
547
+ printStep("2B", output, input);
548
+ // 2C. if the input buffer begins with a prefix of "/../" or "/..",
549
+ // where ".." is a complete path segment, then replace that prefix
550
+ // with "/" in the input buffer and if also the output buffer is
551
+ // empty, last segment in the output buffer equals "../" or "..",
552
+ // where ".." is a complete path segment, then append ".." or "/.."
553
+ // for the latter case respectively to the output buffer else
554
+ // remove the last segment and its preceding "/" (if any) from the
555
+ // output buffer and if hereby the first character in the output
556
+ // buffer was removed and it was not the root slash then delete a
557
+ // leading slash from the input buffer; otherwise,
558
+ } else if (input.startsWith("/../")) {
559
+ input = input.substring(3);
560
+ if (output.length() == 0) {
561
+ output.append("/");
562
+ } else if (output.toString().endsWith("../")) {
563
+ output.append("..");
564
+ } else if (output.toString().endsWith("..")) {
565
+ output.append("/..");
566
+ } else {
567
+ int index = output.lastIndexOf("/");
568
+ if (index == -1) {
569
+ output = new StringBuilder();
570
+ if (input.charAt(0) == '/') {
571
+ input = input.substring(1);
613
572
  }
573
+ } else {
574
+ output = output.delete(index, output.length());
575
+ }
614
576
  }
615
-
616
- // 3. Finally, if the only or last segment of the output buffer is
617
- // "..", where ".." is a complete path segment not followed by a slash
618
- // then append a slash "/". The output buffer is returned as the result
619
- // of remove_dot_segments
620
- if (output.toString().endsWith("..")) {
621
- output.append('/');
622
- printStep("3 ", output, input);
577
+ printStep("2C", output, input);
578
+ } else if (input.equals("/..")) {
579
+ // FIXME: what is complete path segment?
580
+ input = input.replaceFirst("/..", "/");
581
+ if (output.length() == 0) {
582
+ output.append("/");
583
+ } else if (output.toString().endsWith("../")) {
584
+ output.append("..");
585
+ } else if (output.toString().endsWith("..")) {
586
+ output.append("/..");
587
+ } else {
588
+ int index = output.lastIndexOf("/");
589
+ if (index == -1) {
590
+ output = new StringBuilder();
591
+ if (input.charAt(0) == '/') {
592
+ input = input.substring(1);
593
+ }
594
+ } else {
595
+ output = output.delete(index, output.length());
596
+ }
623
597
  }
624
-
625
- return output.toString();
598
+ printStep("2C", output, input);
599
+ // 2D. if the input buffer consists only of ".", then remove
600
+ // that from the input buffer else if the input buffer consists
601
+ // only of ".." and if the output buffer does not contain only
602
+ // the root slash "/", then move the ".." to the output buffer
603
+ // else delte it.; otherwise,
604
+ } else if (input.equals(".")) {
605
+ input = "";
606
+ printStep("2D", output, input);
607
+ } else if (input.equals("..")) {
608
+ if (!output.toString().equals("/")) {
609
+ output.append("..");
610
+ }
611
+ input = "";
612
+ printStep("2D", output, input);
613
+ // 2E. move the first path segment (if any) in the input buffer
614
+ // to the end of the output buffer, including the initial "/"
615
+ // character (if any) and any subsequent characters up to, but not
616
+ // including, the next "/" character or the end of the input buffer.
617
+ } else {
618
+ int end;
619
+ int begin = input.indexOf('/');
620
+ if (begin == 0) {
621
+ end = input.indexOf('/', 1);
622
+ } else {
623
+ end = begin;
624
+ begin = 0;
625
+ }
626
+ String segment;
627
+ if (end == -1) {
628
+ segment = input.substring(begin);
629
+ input = "";
630
+ } else {
631
+ segment = input.substring(begin, end);
632
+ input = input.substring(end);
633
+ }
634
+ output.append(segment);
635
+ printStep("2E", output, input);
636
+ }
626
637
  }
627
638
 
628
- private static void printStep(String step, StringBuilder output, String input) {
629
- //if (System.getProperty("nokogiri.c14.debug") == "on") { //
630
- // System.out.println(" " + step + ": " + output);
631
- // if (output.length() == 0) {
632
- // System.out.println("\t\t\t\t" + input);
633
- // } else {
634
- // System.out.println("\t\t\t" + input);
635
- // }
636
- //}
639
+ // 3. Finally, if the only or last segment of the output buffer is
640
+ // "..", where ".." is a complete path segment not followed by a slash
641
+ // then append a slash "/". The output buffer is returned as the result
642
+ // of remove_dot_segments
643
+ if (output.toString().endsWith("..")) {
644
+ output.append('/');
645
+ printStep("3 ", output, input);
637
646
  }
638
647
 
648
+ return output.toString();
649
+ }
650
+
651
+ private static void
652
+ printStep(String step, StringBuilder output, String input)
653
+ {
654
+ //if (System.getProperty("nokogiri.c14.debug") == "on") { //
655
+ // System.out.println(" " + step + ": " + output);
656
+ // if (output.length() == 0) {
657
+ // System.out.println("\t\t\t\t" + input);
658
+ // } else {
659
+ // System.out.println("\t\t\t" + input);
660
+ // }
661
+ //}
662
+ }
663
+
639
664
  }