diff --git a/apps/kolab_guam/src/kolab_guam_session.erl b/apps/kolab_guam/src/kolab_guam_session.erl --- a/apps/kolab_guam/src/kolab_guam_session.erl +++ b/apps/kolab_guam/src/kolab_guam_session.erl @@ -143,6 +143,18 @@ end end end; +update_split_command_state(Data, #state{ command_split_reset_trigger = reset_for_next_client_command, current_command_split = CurrentCommandSplit }) -> + %If we have a currently active command (CurrentCommandSplit), then we reset only if we find a new command (and not just on any new line). + %This is relevant for multi-line commands such as APPEND, which follow up with a continuation which we want to avoid buffering. + case CurrentCommandSplit of + undefined -> undefined; + _ -> + case eimap_utils:split_command_into_components(Data) of + { <<>>, <<>>, <<>> } -> CurrentCommandSplit; + { _Tag, <<>>, <<>> } -> CurrentCommandSplit; + { _Tag, Command, _Data } -> undefined + end + end; update_split_command_state(_Data, _State) -> undefined. @@ -185,10 +197,7 @@ process_preprocessed_client_data(Socket, PreprocessData, #state{ command_split_reset_trigger = CurrentCommandSplitResetTrigger, current_command_split = CurrentCommandSplit } = State) -> - NewSplitCommand = case CurrentCommandSplitResetTrigger of - reset_for_next_client_command -> undefined; - _ -> CurrentCommandSplit - end, + NewSplitCommand = update_split_command_state(PreprocessData, State), % TODO Maybe we should prepend buffered data here instead. {Line, Remainder} = read_line(PreprocessData), diff --git a/apps/kolab_guam/test/kolab_guam_session_SUITE.erl b/apps/kolab_guam/test/kolab_guam_session_SUITE.erl --- a/apps/kolab_guam/test/kolab_guam_session_SUITE.erl +++ b/apps/kolab_guam/test/kolab_guam_session_SUITE.erl @@ -91,6 +91,29 @@ }} = kolab_guam_session:handle_info({tcp, Socket, <<"y1 ID (\"name\" \"Test\")\r\n">>}, State#state{ rules_deciding = ActiveRules }), + % Append + {noreply, #state{ + server_config = ServerConfig, + buffered_client_data = <<>>, + current_command_split = {<<"y1">>,<<"APPEND">>,<<"INBOX {7}">>}, + command_split_reset_trigger = reset_for_next_client_command + } = IntermediateState4} = kolab_guam_session:handle_info({tcp, Socket, <<"y1 APPEND INBOX {7}\r\n123">>}, State#state{ rules_deciding = ActiveRules }), + + {noreply, #state{ + server_config = ServerConfig, + buffered_client_data = <<>>, %This ensures we aren't buffering during the continuation + current_command_split = {<<"y1">>,<<"APPEND">>,<<"INBOX {7}">>}, + command_split_reset_trigger = reset_for_next_client_command + } = IntermediateState5} = kolab_guam_session:handle_info({tcp, Socket, <<"456">>}, IntermediateState4), + + {noreply, #state{ + server_config = ServerConfig, + buffered_client_data = <<>>, + current_command_split = {<<"y2">>,<<"ENABLE">>,<<"QRESYNC">>}, + command_split_reset_trigger = reset_for_next_client_command + }} = kolab_guam_session:handle_info({tcp, Socket, <<"7\r\ny2 ENABLE QRESYNC\r\n">>}, IntermediateState5), + + % Don't activate filtering {noreply, #state{ server_config = ServerConfig,