Skip to content

Commit f9e2f74

Browse files
committed
Merge branch '2.3.x' into 2.4.x
Conflicts: grails-encoder/src/main/groovy/org/codehaus/groovy/grails/web/util/StreamCharBuffer.java grails-test-suite-web/src/test/groovy/org/codehaus/groovy/grails/web/codecs/CodecSpec.groovy
2 parents c05fc17 + 47253e0 commit f9e2f74

File tree

6 files changed

+61
-8
lines changed

6 files changed

+61
-8
lines changed

grails-encoder/src/main/groovy/org/codehaus/groovy/grails/support/encoding/AbstractEncodedAppender.java

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@
2424
* @since 2.3
2525
*/
2626
public abstract class AbstractEncodedAppender implements EncodedAppender {
27+
private boolean ignoreEncodingState;
28+
2729
/**
2830
* Append a portion of a char array to the buffer and attach the
2931
* encodingState information to it
@@ -172,9 +174,9 @@ public void appendEncoded(Encoder encoder, EncodingState encodingState, CharSequ
172174
* @return true, if should encode
173175
*/
174176
protected boolean shouldEncode(Encoder encoderToApply, EncodingState encodingState) {
175-
return encoderToApply != null
177+
return ignoreEncodingState || (encoderToApply != null
176178
&& (encodingState == null || DefaultEncodingStateRegistry.shouldEncodeWith(encoderToApply,
177-
encodingState));
179+
encodingState)));
178180
}
179181

180182
/**
@@ -272,4 +274,12 @@ public void getChars(int srcBegin, int srcEnd, char[] dst, int dstBegin) {
272274
System.arraycopy(chars, start + srcBegin, dst, dstBegin, srcEnd - srcBegin);
273275
}
274276
}
277+
278+
public boolean isIgnoreEncodingState() {
279+
return ignoreEncodingState;
280+
}
281+
282+
public void setIgnoreEncodingState(boolean ignoreEncodingState) {
283+
this.ignoreEncodingState = ignoreEncodingState;
284+
}
275285
}

grails-encoder/src/main/groovy/org/codehaus/groovy/grails/support/encoding/EncodedAppender.java

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -125,4 +125,18 @@ void appendEncoded(Encoder encoder, EncodingState encodingState, CharSequence st
125125
void flush() throws IOException;
126126

127127
public void close() throws IOException;
128+
129+
130+
/**
131+
* When enabled, will encode all input regardless of it's current state
132+
* disables double-encoding prevention.
133+
*
134+
* @param ignoreEncodingState
135+
*/
136+
void setIgnoreEncodingState(boolean ignoreEncodingState);
137+
138+
/**
139+
* @return current state of ignoreEncodingState setting
140+
*/
141+
public boolean isIgnoreEncodingState();
128142
}

grails-encoder/src/main/groovy/org/codehaus/groovy/grails/web/util/CodecPrintWriter.java

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,13 @@
2626
public class CodecPrintWriter extends GrailsPrintWriter implements EncoderAware, EncodedAppenderFactory {
2727
private final Encoder encoder;
2828
private final StreamCharBuffer buffer;
29+
private boolean ignoreEncodingState;
2930

3031
public CodecPrintWriter(Writer out, Encoder encoder, EncodingStateRegistry encodingStateRegistry) {
32+
this(out, encoder, encodingStateRegistry, false);
33+
}
34+
35+
public CodecPrintWriter(Writer out, Encoder encoder, EncodingStateRegistry encodingStateRegistry, boolean ignoreEncodingState) {
3136
super(null);
3237
this.encoder = encoder;
3338
buffer=new StreamCharBuffer();
@@ -38,19 +43,21 @@ public CodecPrintWriter(Writer out, Encoder encoder, EncodingStateRegistry encod
3843
buffer.setWriteDirectlyToConnectedMinSize(0);
3944
buffer.setChunkMinSize(0);
4045
}
41-
setOut(buffer.getWriterForEncoder(encoder, encodingStateRegistry));
46+
setOut(buffer.getWriterForEncoder(encoder, encodingStateRegistry, ignoreEncodingState));
4247
}
4348

4449
public Encoder getEncoder() {
4550
return encoder;
4651
}
4752

4853
public EncodedAppender getEncodedAppender() {
49-
return ((EncodedAppenderFactory)buffer.getWriter()).getEncodedAppender();
54+
EncodedAppender encodedAppender = ((EncodedAppenderFactory)buffer.getWriter()).getEncodedAppender();
55+
encodedAppender.setIgnoreEncodingState(ignoreEncodingState);
56+
return encodedAppender;
5057
}
5158

5259
@Override
5360
public Writer getWriterForEncoder(Encoder encoder, EncodingStateRegistry encodingStateRegistry) {
54-
return buffer.getWriterForEncoder(encoder, encodingStateRegistry);
61+
return buffer.getWriterForEncoder(encoder, encodingStateRegistry, ignoreEncodingState);
5562
}
5663
}

grails-encoder/src/main/groovy/org/codehaus/groovy/grails/web/util/StreamCharBuffer.java

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2623,11 +2623,17 @@ public Writer getWriterForEncoder() {
26232623
public Writer getWriterForEncoder(Encoder encoder) {
26242624
EncodingStateRegistryLookup encodingStateRegistryLookup = EncodingStateRegistryLookupHolder.getEncodingStateRegistryLookup();
26252625
EncodingStateRegistry encodingStateRegistry = encodingStateRegistryLookup != null ? encodingStateRegistryLookup.lookup() : null;
2626-
return getWriterForEncoder(encoder, encodingStateRegistry);
2626+
return getWriterForEncoder(encoder, encodingStateRegistry, false);
26272627
}
26282628

26292629
public Writer getWriterForEncoder(Encoder encoder, EncodingStateRegistry encodingStateRegistry) {
2630-
return new EncodedAppenderWriter(writer.getEncodedAppender(), encoder, encodingStateRegistry);
2630+
return getWriterForEncoder(encoder, encodingStateRegistry, false);
2631+
}
2632+
2633+
public Writer getWriterForEncoder(Encoder encoder, EncodingStateRegistry encodingStateRegistry, boolean ignoreEncodingState) {
2634+
EncodedAppender encodedAppender = writer.getEncodedAppender();
2635+
encodedAppender.setIgnoreEncodingState(ignoreEncodingState);
2636+
return new EncodedAppenderWriter(encodedAppender, encoder, encodingStateRegistry);
26312637
}
26322638

26332639
public boolean isNotifyParentBuffersEnabled() {

grails-test-suite-web/src/test/groovy/org/codehaus/groovy/grails/web/codecs/CodecSpec.groovy

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,12 @@
11
package org.codehaus.groovy.grails.web.codecs
22

33
import grails.converters.XML
4+
import grails.converters.JSON
45
import grails.test.mixin.TestMixin
56
import grails.test.mixin.web.GroovyPageUnitTestMixin
7+
8+
import org.codehaus.groovy.grails.web.util.StreamCharBuffer
9+
610
import spock.lang.Issue
711
import spock.lang.Specification
812

@@ -93,6 +97,18 @@ class CodecSpec extends Specification {
9397
public boolean equals(Object obj) {
9498
throw new RuntimeException("equals shouldn't be called")
9599
}
100+
}
101+
102+
@Issue("GRAILS-11361")
103+
void "JSON converter should not use encoding state"() {
104+
given:
105+
def buffer=new StreamCharBuffer()
106+
buffer.writer.write('"Hello world"')
107+
def content=buffer.encodeAsRaw()
108+
when:
109+
def json = [content: content] as JSON
110+
then:
111+
json.toString() == '{"content":"\\"Hello world\\""}'
96112
}
97113

98114
void "output should be safe at the end"() {

grails-web-common/src/main/groovy/org/codehaus/groovy/grails/web/json/JSONObject.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1129,7 +1129,7 @@ static void writeQuoted(Writer writer, Object value) throws IOException {
11291129
javascriptEncoderStateless.encodeToWriter((CharSequence)value, writer);
11301130
}
11311131
else {
1132-
CodecPrintWriter codecWriter = new CodecPrintWriter(writer, javascriptEncoder, null);
1132+
CodecPrintWriter codecWriter = new CodecPrintWriter(writer, javascriptEncoder, null, true);
11331133
codecWriter.print(value);
11341134
codecWriter.flush();
11351135
}

0 commit comments

Comments
 (0)