Skip to content

Commit 17f8b44

Browse files
committed
XmlStreamReader can't parse XML document with multi-line prolog #550
- Apply PR #550, not merged or would have caused the build to fail. - Implement fix
1 parent 555647f commit 17f8b44

3 files changed

Lines changed: 22 additions & 5 deletions

File tree

src/changes/changes.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,7 @@ The <action> type attribute can be add,update,fix,remove.
8888
<action dev="ggregory" type="fix" issue="IO-807" due-to="Elliotte Rusty Harold, Gary Gregory">Characterization test for broken symlinks when copying directories #547.</action>
8989
<action dev="ggregory" type="fix" due-to="Gary Gregory">ClosedInputStream.read(byte[], int, int) does not always return -1.</action>
9090
<action dev="ggregory" type="fix" due-to="Gary Gregory">ClosedOutputStream.write(byte[], int, int) does not always throw IOException.</action>
91+
<action dev="ggregory" type="fix" due-to="Sylwester Lachiewicz, Gary Gregory">XmlStreamReader can't parse XML document with multi-line prolog #550.</action>
9192
<!-- Add -->
9293
<action dev="ggregory" type="add" due-to="Gary Gregory">Add and use PathUtils.getFileName(Path, Function&lt;Path, R&gt;).</action>
9394
<action dev="ggregory" type="add" due-to="Gary Gregory">Add and use PathUtils.getFileNameString().</action>

src/main/java/org/apache/commons/io/input/XmlStreamReader.java

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -214,6 +214,16 @@ public Builder setLenient(final boolean lenient) {
214214
* <p>
215215
* See also the <a href="https://www.w3.org/TR/2008/REC-xml-20081126/#NT-EncName">XML specification</a>.
216216
* </p>
217+
* <p>
218+
* Note the documented pattern is:
219+
* </p>
220+
* <pre>
221+
* EncName ::= [A-Za-z] ([A-Za-z0-9._] | '-')*
222+
* </pre>
223+
* <p>
224+
* However this does not match all the aliases that are supported by Java.
225+
* For example, '437', 'ISO_8859-1:1987' and 'ebcdic-de-273+euro'.
226+
* </p>
217227
*/
218228
public static final Pattern ENCODING_PATTERN = Pattern.compile(
219229
// @formatter:off
@@ -223,10 +233,6 @@ public Builder setLenient(final boolean lenient) {
223233
+ "((?:\"[A-Za-z0-9][A-Za-z0-9._+:-]*\")" // double-quoted
224234
+ "|(?:'[A-Za-z0-9][A-Za-z0-9._+:-]*'))", // single-quoted
225235
Pattern.MULTILINE);
226-
// N.B. the documented pattern is
227-
// EncName ::= [A-Za-z] ([A-Za-z0-9._] | '-')*
228-
// However this does not match all the aliases that are supported by Java.
229-
// e.g. '437', 'ISO_8859-1:1987' and 'ebcdic-de-273+euro'
230236
// @formatter:on
231237

232238
private static final String RAW_EX_1 = "Illegal encoding, BOM [{0}] XML guess [{1}] XML prolog [{2}] encoding mismatch";
@@ -325,7 +331,7 @@ private static String getXmlProlog(final InputStream inputStream, final String g
325331
inputStream.reset();
326332
final BufferedReader bReader = new BufferedReader(new StringReader(xmlProlog.substring(0, firstGT + 1)));
327333
final StringBuilder prolog = new StringBuilder();
328-
IOConsumer.forEach(bReader.lines(), prolog::append);
334+
IOConsumer.forEach(bReader.lines(), l -> prolog.append(l).append(' '));
329335
final Matcher m = ENCODING_PATTERN.matcher(prolog);
330336
if (m.find()) {
331337
encoding = m.group(1).toUpperCase(Locale.ROOT);

src/test/java/org/apache/commons/io/input/XmlStreamReaderTest.java

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,8 @@ public class XmlStreamReaderTest {
6060
private static final String UTF_32LE = "UTF-32LE";
6161
private static final String UTF_32BE = "UTF-32BE";
6262
private static final String UTF_8 = StandardCharsets.UTF_8.name();
63+
64+
private static final String XML6 = "xml-prolog-encoding-new-line";
6365
private static final String XML5 = "xml-prolog-encoding-spaced-single-quotes";
6466
private static final String XML4 = "xml-prolog-encoding-single-quotes";
6567
private static final String XML3 = "xml-prolog-encoding-double-quotes";
@@ -102,6 +104,8 @@ public class XmlStreamReaderTest {
102104

103105
private static final MessageFormat XML_WITH_PROLOG = new MessageFormat(
104106
"<?xml version=\"1.0\"?>\n<root>{2}</root>");
107+
private static final MessageFormat XML_WITH_PROLOG_AND_ENCODING_NEW_LINES = new MessageFormat(
108+
"<?xml\nversion\n=\n\"1.0\"\nencoding\n=\n\"{1}\"\n?>\n<root>{2}</root>");
105109

106110
private static final MessageFormat XML_WITH_PROLOG_AND_ENCODING_DOUBLE_QUOTES = new MessageFormat(
107111
"<?xml version=\"1.0\" encoding=\"{1}\"?>\n<root>{2}</root>");
@@ -123,6 +127,7 @@ public class XmlStreamReaderTest {
123127
XMLs.put(XML3, XML_WITH_PROLOG_AND_ENCODING_DOUBLE_QUOTES);
124128
XMLs.put(XML4, XML_WITH_PROLOG_AND_ENCODING_SINGLE_QUOTES);
125129
XMLs.put(XML5, XML_WITH_PROLOG_AND_ENCODING_SPACED_SINGLE_QUOTES);
130+
XMLs.put(XML6, XML_WITH_PROLOG_AND_ENCODING_NEW_LINES);
126131
}
127132

128133
/**
@@ -624,5 +629,10 @@ protected void testRawNoBomValid(final String encoding) throws Exception {
624629
xmlReader = new XmlStreamReader(is);
625630
assertEquals(xmlReader.getEncoding(), encoding);
626631
xmlReader.close();
632+
633+
is = getXmlInputStream("no-bom", XML6, encoding, encoding);
634+
xmlReader = new XmlStreamReader(is);
635+
assertEquals(xmlReader.getEncoding(), encoding);
636+
xmlReader.close();
627637
}
628638
}

0 commit comments

Comments
 (0)