diff --git a/spring-messaging/src/main/java/org/springframework/messaging/simp/stomp/StompDecoder.java b/spring-messaging/src/main/java/org/springframework/messaging/simp/stomp/StompDecoder.java
index 2edd0202963..44a083414e1 100644
--- a/spring-messaging/src/main/java/org/springframework/messaging/simp/stomp/StompDecoder.java
+++ b/spring-messaging/src/main/java/org/springframework/messaging/simp/stomp/StompDecoder.java
@@ -54,7 +54,6 @@ public class StompDecoder {
private final Log logger = LogFactory.getLog(StompDecoder.class);
-
/**
* Decodes one or more STOMP frames from the given {@code ByteBuffer} into a
* list of {@link Message}s. If the input buffer contains any incplcontains partial STOMP frame content, or additional
@@ -201,11 +200,41 @@ public class StompDecoder {
}
}
- private String unescape(String input) {
- return input.replaceAll("\\\\n", "\n")
- .replaceAll("\\\\r", "\r")
- .replaceAll("\\\\c", ":")
- .replaceAll("\\\\\\\\", "\\\\");
+ /**
+ * See STOMP Spec 1.2:
+ * "Value Encoding".
+ */
+ private String unescape(String inString) {
+
+ StringBuilder sb = new StringBuilder();
+ int pos = 0; // position in the old string
+ int index = inString.indexOf("\\");
+
+ while (index >= 0) {
+ sb.append(inString.substring(pos, index));
+ Character c = inString.charAt(index + 1);
+ if (c == 'r') {
+ sb.append('\r');
+ }
+ else if (c == 'n') {
+ sb.append('\n');
+ }
+ else if (c == 'c') {
+ sb.append(':');
+ }
+ else if (c == '\\') {
+ sb.append('\\');
+ }
+ else {
+ // should never happen
+ throw new StompConversionException("Illegal escape sequence at index " + index + ": " + inString);
+ }
+ pos = index + 2;
+ index = inString.indexOf("\\", pos);
+ }
+
+ sb.append(inString.substring(pos));
+ return sb.toString();
}
private byte[] readPayload(ByteBuffer buffer, MultiValueMap headers) {
diff --git a/spring-messaging/src/main/java/org/springframework/messaging/simp/stomp/StompEncoder.java b/spring-messaging/src/main/java/org/springframework/messaging/simp/stomp/StompEncoder.java
index e7f94ddd9e9..0deb332361b 100644
--- a/spring-messaging/src/main/java/org/springframework/messaging/simp/stomp/StompEncoder.java
+++ b/spring-messaging/src/main/java/org/springframework/messaging/simp/stomp/StompEncoder.java
@@ -34,6 +34,7 @@ import org.springframework.messaging.simp.SimpMessageType;
* An encoder for STOMP frames.
*
* @author Andy Wilkinson
+ * @author Rossen Stoyanchev
* @since 4.0
*/
public final class StompEncoder {
@@ -95,42 +96,64 @@ public final class StompEncoder {
else if (logger.isDebugEnabled()) {
logger.debug("Encoded STOMP command=" + headers.getCommand() + " headers=" + stompHeaders);
}
+ boolean escapeHeaders = shouldEscapeHeaders(headers);
for (Entry> entry : stompHeaders.entrySet()) {
- byte[] key = getUtf8BytesEscapingIfNecessary(entry.getKey(), headers);
+ byte[] key = toUtf8Bytes(entry.getKey(), escapeHeaders);
for (String value : entry.getValue()) {
output.write(key);
output.write(COLON);
- output.write(getUtf8BytesEscapingIfNecessary(value, headers));
+ output.write(toUtf8Bytes(value, escapeHeaders));
output.write(LF);
}
}
if ((headers.getCommand() == StompCommand.SEND) || (headers.getCommand() == StompCommand.MESSAGE) ||
(headers.getCommand() == StompCommand.ERROR)) {
+ int contentLength = message.getPayload().length;
output.write("content-length:".getBytes(UTF8_CHARSET));
- output.write(Integer.toString(message.getPayload().length).getBytes(UTF8_CHARSET));
+ output.write(Integer.toString(contentLength).getBytes(UTF8_CHARSET));
output.write(LF);
}
}
- private void writeBody(Message message, DataOutputStream output) throws IOException {
- output.write(message.getPayload());
+ private boolean shouldEscapeHeaders(StompHeaderAccessor headers) {
+ return (headers.getCommand() != StompCommand.CONNECT && headers.getCommand() != StompCommand.CONNECTED);
}
- private byte[] getUtf8BytesEscapingIfNecessary(String input, StompHeaderAccessor headers) {
- if (headers.getCommand() != StompCommand.CONNECT && headers.getCommand() != StompCommand.CONNECTED) {
- return escape(input).getBytes(UTF8_CHARSET);
- }
- else {
- return input.getBytes(UTF8_CHARSET);
+ private byte[] toUtf8Bytes(String input, boolean escape) {
+ input = escape ? escape(input) : input;
+ return input.getBytes(UTF8_CHARSET);
+ }
+
+ /**
+ * See STOMP Spec 1.2:
+ * "Value Encoding".
+ */
+ private String escape(String inString) {
+ StringBuilder sb = new StringBuilder(inString.length());
+ for (int i = 0; i < inString.length(); i++) {
+ char c = inString.charAt(i);
+ if (c == '\\') {
+ sb.append("\\\\");
+ }
+ else if (c == ':') {
+ sb.append("\\c");
+ }
+ else if (c == '\n') {
+ sb.append("\\n");
+ }
+ else if (c == '\r') {
+ sb.append("\\r");
+ }
+ else {
+ sb.append(c);
+ }
}
+ return sb.toString();
}
- private String escape(String input) {
- return input.replaceAll("\\\\", "\\\\\\\\")
- .replaceAll(":", "\\\\c")
- .replaceAll("\n", "\\\\n")
- .replaceAll("\r", "\\\\r");
+ private void writeBody(Message message, DataOutputStream output) throws IOException {
+ output.write(message.getPayload());
}
}