Skip to content

Commit d4c6741

Browse files
glenn.volckaertUbuntu
authored andcommitted
Add escaping of single quotes and basic support for .net style escaping
DEVSIX-6308
1 parent d5b0e93 commit d4c6741

File tree

2 files changed

+25
-79
lines changed

2 files changed

+25
-79
lines changed

commons/src/main/java/com/itextpdf/commons/utils/MessageFormatUtil.java

Lines changed: 20 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -61,82 +61,31 @@ private MessageFormatUtil() {
6161
* Indexed arguments can be referred with {index},
6262
* to escape curly braces you have to double them.
6363
*
64+
* <p>
65+
* Only basic escaping is allowed, single quotes in a set of curly braces are not supported and
66+
* multiple escaped braces in a row are also not supported
67+
*
68+
* <p>
69+
* Allowed {{{0}}}
70+
* Allowed '{0}'
71+
* Allowed '{{{0}}}'
72+
*
73+
* <p>
74+
* Not allowed {{'{0}'}}
75+
* Not allowed {{{{{0}}}}}
76+
*
6477
* @param pattern to format
6578
* @param arguments arguments
6679
*
6780
* @return The formatted string
6881
*/
6982
public static String format(String pattern, Object... arguments) {
70-
boolean mustClose = false;
71-
StringBuilder result = new StringBuilder(pattern.length());
72-
int i = 0;
73-
int n = pattern.length();
74-
while (i < n) {
75-
char current = pattern.charAt(i);
76-
switch (current) {
77-
case '{': {
78-
int curlyCount = 0;
79-
int j;
80-
for (j = i; j < n && pattern.charAt(j) == '{'; j++, curlyCount++)
81-
;
82-
i += curlyCount - 1;
83-
if (curlyCount > 1) {
84-
if (!mustClose) {
85-
result.append("'");
86-
}
87-
while (curlyCount >= 2) {
88-
result.append('{');
89-
curlyCount -= 2;
90-
}
91-
mustClose = true;
92-
}
93-
if (curlyCount == 1) {
94-
if (mustClose) {
95-
result.append('\'');
96-
}
97-
result.append('{');
98-
mustClose = false;
99-
}
100-
}
101-
break;
102-
case '}': {
103-
int curlyCount = 0;
104-
int j;
105-
for (j = i; j < n && pattern.charAt(j) == '}'; j++, curlyCount++)
106-
;
107-
i += curlyCount - 1;
108-
if (curlyCount % 2 == 1) {
109-
if (mustClose) {
110-
result.append('\'');
111-
}
112-
result.append('}');
113-
mustClose = false;
114-
}
115-
if (curlyCount > 1) {
116-
result.append("'");
117-
while (curlyCount >= 2) {
118-
result.append('}');
119-
curlyCount -= 2;
120-
}
121-
mustClose = true;
122-
}
123-
}
124-
break;
125-
case '\'':
126-
result.append("''");
127-
break;
128-
default:
129-
if (mustClose) {
130-
result.append('\'');
131-
mustClose = false;
132-
}
133-
result.append(current);
134-
}
135-
i++;
136-
}
137-
if (mustClose) {
138-
result.append('\'');
139-
}
140-
return new MessageFormat(result.toString(), Locale.ROOT).format(arguments);
83+
return new MessageFormat(
84+
pattern.replace("'", "''")
85+
.replace("{{{","'{'{" )
86+
.replace("}}}","}'}'" )
87+
.replace("{{","'{'" )
88+
.replace("}}","'}'" )
89+
,Locale.ROOT).format(arguments);
14190
}
14291
}

commons/src/test/java/com/itextpdf/commons/utils/MessageFormatUtilTest.java

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -45,33 +45,30 @@ public class MessageFormatUtilTest extends ExtendedITextTest {
4545
private String pattern;
4646
private Object[] arguments;
4747

48-
4948
public MessageFormatUtilTest(Object expectedResult, Object pattern, Object arguments, Object name) {
5049
this.expectedResult = (String)expectedResult;
5150
this.pattern = (String)pattern;
5251
this.arguments = (Object[]) arguments;
5352
}
5453

55-
5654
@Parameterized.Parameters(name = "{index}: {3} format: {1}; {0}")
5755
public static Iterable<Object[]> dataSource() {
5856
return Arrays.asList(new Object[][]{
5957
{"Plain message with params 1 test", "Plain message with params {0} {1}", new Object[] {1, "test"},"test with simple params"},
6058
{"Message with 'single quotes'", "Message with 'single quotes'", new Object[0],"test with single quotes"},
6159
{"Message with ''doubled single quotes''", "Message with ''doubled single quotes''", new Object[0],"test with doubled single quotes"},
6260
{"Message with {curly braces} and a parameter {I'm between curly braces too}", "Message with {{curly braces}} and a parameter {{{0}}}", new Object[]{"I'm between curly braces too"},"Test with curly braces"},
63-
{"Message with {{multiple curly braces}}", "Message with {{{{multiple curly braces}}}}", new Object[]{},"Test with multiple curly braces"},
64-
{"Message with {Value between brackets} and {{Value between double brackets}}", "Message with {{{0}}} and {{{{{1}}}}}", new Object[]{"Value between brackets", "Value between double brackets"},"Test with multiple curly braces"},
65-
{"Lets go wild 'value 1', {value 2}, '{value 3}', {'{value 4}'}", "Lets go wild '{0}', {{{1}}}, '{{{2}}}', {{'{{{3}}}'}}", new Object[]{"value 1", "value 2","value 3","value 4"},"Some of all"},
66-
{"{'{value}'}", "{{'{{{0}}}'}}", new Object[]{"value"},"Mix om multiple brackets and quotes 1"},
6761
{"'{value}'", "'{{{0}}}'", new Object[]{"value"},"Mix om multiple brackets and quotes 1"},
68-
{"a '{'{123}'}''' b", "a '{{'{{{0}}}'}}''' b", new Object[]{123},"Mix om multiple brackets and quotes 1"},
62+
{"'value'", "'{0}'", new Object[]{"value"},"Mix of brackets and quotes"},
63+
{"{'0'}", "{{'0'}}", new Object[0],"Mix of multiple brackets and quotes 2"},
64+
{"single opening brace {0 test" , "single opening brace {{0 test", new Object[0],"Test single opening brace"},
65+
{"single closing brace 0} test", "single closing brace 0}} test", new Object[0],"Test single closing brace"},
66+
{"single opening + closing brace { test }", "single opening + closing brace {{ {0} }}", new Object[]{"test"},"Test single opening and closing brace"},
6967
});
7068
}
7169

7270
@Test
7371
public void testFormatting() {
7472
Assert.assertEquals(expectedResult, MessageFormatUtil.format(pattern, arguments));
7573
}
76-
7774
}

0 commit comments

Comments
 (0)