From 4f05da7fed7e55d0744a91e4ac384d8f5df6e665 Mon Sep 17 00:00:00 2001 From: Rossen Stoyanchev Date: Mon, 3 Jun 2019 16:03:35 -0400 Subject: [PATCH 1/2] Support escape character in ContentDisposition Closes gh-23077 --- .../java/org/springframework/http/ContentDisposition.java | 6 ++++-- .../org/springframework/http/ContentDispositionTests.java | 8 ++++++++ 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/spring-web/src/main/java/org/springframework/http/ContentDisposition.java b/spring-web/src/main/java/org/springframework/http/ContentDisposition.java index df94d1617f1..b0b13aa205d 100644 --- a/spring-web/src/main/java/org/springframework/http/ContentDisposition.java +++ b/spring-web/src/main/java/org/springframework/http/ContentDisposition.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2018 the original author or authors. + * Copyright 2002-2019 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -331,6 +331,7 @@ public final class ContentDisposition { do { int nextIndex = index + 1; boolean quoted = false; + boolean escaped = false; while (nextIndex < headerValue.length()) { char ch = headerValue.charAt(nextIndex); if (ch == ';') { @@ -338,9 +339,10 @@ public final class ContentDisposition { break; } } - else if (ch == '"') { + else if (!escaped && ch == '"') { quoted = !quoted; } + escaped = (!escaped && ch == '\\'); nextIndex++; } String part = headerValue.substring(index + 1, nextIndex).trim(); diff --git a/spring-web/src/test/java/org/springframework/http/ContentDispositionTests.java b/spring-web/src/test/java/org/springframework/http/ContentDispositionTests.java index 788a9c69fed..fd0ec56572b 100644 --- a/spring-web/src/test/java/org/springframework/http/ContentDispositionTests.java +++ b/spring-web/src/test/java/org/springframework/http/ContentDispositionTests.java @@ -79,6 +79,14 @@ public class ContentDispositionTests { .filename("中文.txt", StandardCharsets.UTF_8).build(), disposition); } + @Test // gh-23077 + public void parseWithEscapedQuote() { + ContentDisposition disposition = ContentDisposition.parse( + "form-data; name=\"file\"; filename=\"\\\"The Twilight Zone\\\".txt\"; size=123"); + assertEquals(ContentDisposition.builder("form-data").name("file") + .filename("\\\"The Twilight Zone\\\".txt").size(123L).build(), disposition); + } + @Test(expected = IllegalArgumentException.class) public void parseEmpty() { ContentDisposition.parse(""); From d2ec876f572958f309231924cc364ff9d675b9e0 Mon Sep 17 00:00:00 2001 From: Rossen Stoyanchev Date: Mon, 3 Jun 2019 16:22:43 -0400 Subject: [PATCH 2/2] Consistently close connection after ERROR frame Closes gh-23039 --- .../web/socket/messaging/StompSubProtocolHandler.java | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/spring-websocket/src/main/java/org/springframework/web/socket/messaging/StompSubProtocolHandler.java b/spring-websocket/src/main/java/org/springframework/web/socket/messaging/StompSubProtocolHandler.java index cfdfbd76061..0c1be831015 100644 --- a/spring-websocket/src/main/java/org/springframework/web/socket/messaging/StompSubProtocolHandler.java +++ b/spring-websocket/src/main/java/org/springframework/web/socket/messaging/StompSubProtocolHandler.java @@ -329,12 +329,10 @@ public class StompSubProtocolHandler implements SubProtocolHandler, ApplicationE sendErrorMessage(session, ex); return; } - Message message = getErrorHandler().handleClientMessageProcessingError(clientMessage, ex); if (message == null) { return; } - StompHeaderAccessor accessor = MessageHeaderAccessor.getAccessor(message, StompHeaderAccessor.class); Assert.state(accessor != null, "No StompHeaderAccessor"); sendToClient(session, accessor, message.getPayload()); @@ -357,6 +355,14 @@ public class StompSubProtocolHandler implements SubProtocolHandler, ApplicationE // Could be part of normal workflow (e.g. browser tab closed) logger.debug("Failed to send STOMP ERROR to client", ex); } + finally { + try { + session.close(CloseStatus.PROTOCOL_ERROR); + } + catch (IOException ex) { + // Ignore + } + } } private boolean detectImmutableMessageInterceptor(MessageChannel channel) {