blob: e93ea7d390a4811b0c0b106f09aa905b2c504d60 [file] [log] [blame]
/****************************************************************
* Licensed to the Apache Software Foundation (ASF) under one *
* or more contributor license agreements. See the NOTICE file *
* distributed with this work for additional information *
* regarding copyright ownership. The ASF licenses this file *
* to you under the Apache License, Version 2.0 (the *
* "License"); you may not use this file except in compliance *
* with the License. You may obtain a copy of the License at *
* *
* http://www.apache.org/licenses/LICENSE-2.0 *
* *
* Unless required by applicable law or agreed to in writing, *
* software distributed under the License is distributed on an *
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY *
* KIND, either express or implied. See the License for the *
* specific language governing permissions and limitations *
* under the License. *
****************************************************************/
package org.apache.james.imapserver.netty;
import java.util.List;
import org.apache.james.imap.api.ImapConstants;
import org.apache.james.imap.api.process.ImapSession;
import org.apache.james.protocols.api.CommandDetectionSession;
import org.apache.james.protocols.netty.AllButStartTlsLineBasedChannelHandler;
import org.jboss.netty.buffer.ChannelBuffer;
import org.jboss.netty.channel.Channel;
import org.jboss.netty.channel.ChannelHandlerContext;
import org.jboss.netty.channel.ChannelPipeline;
import org.jboss.netty.channel.Channels;
import org.jboss.netty.channel.MessageEvent;
public class SwitchableLineBasedFrameDecoder extends AllButStartTlsLineBasedChannelHandler {
public static final String PATTERN = ImapConstants.STARTTLS_COMMAND.getName().toLowerCase();
private volatile boolean framingEnabled = true;
public SwitchableLineBasedFrameDecoder(ChannelPipeline pipeline, int maxFrameLength, boolean stripDelimiter) {
super(pipeline, maxFrameLength, stripDelimiter, PATTERN);
}
@Override
public synchronized void messageReceived(ChannelHandlerContext ctx, MessageEvent e) throws Exception {
if (this.framingEnabled) {
super.messageReceived(ctx, e);
} else {
ctx.sendUpstream(e);
}
}
public synchronized void enableFraming() {
this.framingEnabled = true;
}
public synchronized void disableFraming(ChannelHandlerContext ctx) {
this.framingEnabled = false;
if (this.cumulation != null && this.cumulation.readable()) {
final ChannelBuffer spareBytes = this.cumulation.readBytes(this.cumulation.readableBytes());
this.cumulation = null;
Channels.fireMessageReceived(ctx, spareBytes);
}
}
@Override
protected CommandDetectionSession retrieveSession(ChannelHandlerContext ctx, Channel channel) {
return (ImapSession) NettyConstants.attributes.get(ctx.getChannel());
}
@Override
protected boolean multiPartsAndOneStartTls(List<String> parts) {
return parts.stream()
.map(this::removeTag)
.anyMatch(line -> line.startsWith(PATTERN)) && parts.size() > 1;
}
@Override
protected boolean hasInvalidStartTlsPart(List<String> parts) {
return parts.stream()
.map(this::removeTag)
.anyMatch(line -> line.startsWith(PATTERN) && !line.endsWith(PATTERN));
}
@Override
protected boolean hasStartTLS(String trimedLowerCasedInput) {
return super.hasStartTLS(removeTag(trimedLowerCasedInput));
}
protected String removeTag(String input) {
String trimmedInput = input.trim();
int tagEnd = trimmedInput.indexOf(' ');
if (tagEnd < 0) {
return input;
}
return trimmedInput.substring(tagEnd + 1);
}
}