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
@@ -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
  }