This is an automated email from the ASF dual-hosted git repository. chibenwa pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/james-mime4j.git
commit 005f0fe79767da149b346ee5784b7e8b107a2d96 Author: Benoit TELLIER <[email protected]> AuthorDate: Wed Nov 4 15:06:32 2026 +0100 [FIX] StructuredFieldParser: drop the backslash of a quoted pair followed by text in a quoted string The quoted pair is a MORE rule whose action removes the backslash from the token manager's image. STRING_CONTENT and FOLD had no action, so JavaCC built their image from the raw input, MORE prefix included: the backslash came back ("a\"b" read as a\"b, the lenient parser gives a"b), and a quoted pair just before a fold was dropped. Both tokens now take their image from the edited buffer, the fold keeping only the text before the line break. Fixes #106 --- .../mime4j/field/structured/StructuredFieldParser.jj | 10 +++++++--- .../james/mime4j/field/ContentLocationFieldTest.java | 19 +++++++++++++++++++ .../field/structured/StructuredFieldParserTest.java | 8 ++++++++ 3 files changed, 34 insertions(+), 3 deletions(-) diff --git a/dom/src/main/javacc/org/apache/james/mime4j/field/structured/StructuredFieldParser.jj b/dom/src/main/javacc/org/apache/james/mime4j/field/structured/StructuredFieldParser.jj index 6ba407de..dd4a0dc9 100644 --- a/dom/src/main/javacc/org/apache/james/mime4j/field/structured/StructuredFieldParser.jj +++ b/dom/src/main/javacc/org/apache/james/mime4j/field/structured/StructuredFieldParser.jj @@ -123,6 +123,7 @@ private String doParse() : | t = <FOLD> { + buffer.append(t.image); if (preserveFolding) buffer.append("\r\n"); } | @@ -207,9 +208,12 @@ SKIP : <INQUOTEDSTRING> TOKEN : { - < STRING_CONTENT : (~["\"", "\\", "\r"])+ > - // Preserve line break within quotes but not trailing white space -| < FOLD: "\r\n" ( [" ", "\t"] )* > + // a token after a quoted pair (MORE) takes its image from image, where the + // quoted pair action removed the backslash, not from the raw input + < STRING_CONTENT : (~["\"", "\\", "\r"])+ > { matchedToken.image = image.toString(); } + // Preserve line break within quotes but not trailing white space: + // the image keeps only the quoted pairs before the fold +| < FOLD: "\r\n" ( [" ", "\t"] )* > { matchedToken.image = image.substring(0, image.length() - lengthOfMatch); } | < QUOTEDSTRING: "\"" > { matchedToken.image = image.substring(0, image.length() - 1); } : DEFAULT } diff --git a/dom/src/test/java/org/apache/james/mime4j/field/ContentLocationFieldTest.java b/dom/src/test/java/org/apache/james/mime4j/field/ContentLocationFieldTest.java index f2b67879..85f18c7a 100644 --- a/dom/src/test/java/org/apache/james/mime4j/field/ContentLocationFieldTest.java +++ b/dom/src/test/java/org/apache/james/mime4j/field/ContentLocationFieldTest.java @@ -82,4 +82,23 @@ public class ContentLocationFieldTest extends TestCase { assertTrue(f.getLocation(), f.getLocation().endsWith("e")); assertNull(f.getParseException()); } + + public void testQuotedPairFollowedByTextInQuotedString() throws Exception { + ContentLocationField f = parse("Content-Location: \"a\\\"b\""); + assertNull(f.getParseException()); + assertEquals("a\"b", f.getLocation()); + + f = parse("Content-Location: \"http://example.com/a\\\\b.html\""); + assertNull(f.getParseException()); + assertEquals("http://example.com/a\\b.html", f.getLocation()); + } + + public void testQuotedPairInQuotedStringShouldAgreeWithTheLenientParser() throws Exception { + String[] values = {"\"a\\\"b\"", "\"http://example.com/a\\\\b.html\"", "\"ab\\\"\""}; + for (String value : values) { + ContentLocationField strict = parse("Content-Location: " + value); + ContentLocationField lenient = LenientContentLocationFieldTest.parse("Content-Location: " + value); + assertEquals(value, lenient.getLocation(), strict.getLocation()); + } + } } diff --git a/dom/src/test/java/org/apache/james/mime4j/field/structured/StructuredFieldParserTest.java b/dom/src/test/java/org/apache/james/mime4j/field/structured/StructuredFieldParserTest.java index cd8775dc..1bd807f4 100644 --- a/dom/src/test/java/org/apache/james/mime4j/field/structured/StructuredFieldParserTest.java +++ b/dom/src/test/java/org/apache/james/mime4j/field/structured/StructuredFieldParserTest.java @@ -63,6 +63,14 @@ public class StructuredFieldParserTest { Assert.assertEquals("Field Value", parse("Fi(This is a comment)eld (A (very (nested) )comment)Value")); } + @Test + public void testQuotedPairInQuotedString() throws Exception { + Assert.assertEquals("a\"b", parse("\"a\\\"b\"")); + Assert.assertEquals("a\\b", parse("\"a\\\\b\"")); + Assert.assertEquals("ab\"", parse("\"ab\\\"\"")); + Assert.assertEquals("a\"\r\nb", parse("\"a\\\"\r\n b\"")); + } + private String parse(String in) throws Exception { StructuredFieldParser parser = new StructuredFieldParser(new StringReader(in)); parser.setFoldingPreserved(true); --------------------------------------------------------------------- To unsubscribe, e-mail: [email protected] For additional commands, e-mail: [email protected]
