package mireka.pop.command; import java.io.IOException; import java.io.InputStream; import java.util.List; import mireka.pop.Command; import mireka.pop.CommandParser; import mireka.pop.CommandSyntaxException; import mireka.pop.IllegalSessionStateException; import mireka.pop.Pop3Exception; import mireka.pop.Session; import mireka.pop.SessionState; import org.subethamail.smtp.io.CRLFTerminatedReader.MaxLineLengthException; import org.subethamail.smtp.io.ExtraDotOutputStream; public class TopCommand implements Command { private final Session session; public TopCommand(Session session) { this.session = session; } @Override public void execute(CommandParser commandParser) throws IOException, Pop3Exception { if (session.getSessionState() != SessionState.TRANSACTION) throw new IllegalSessionStateException(); List<String> args = commandParser.parseArguments(); if (args.size() != 2) throw new CommandSyntaxException( "Two numeric arguments are expected"); int messageNumber; int lines; try { messageNumber = Integer.valueOf(args.get(0)); lines = Integer.valueOf(args.get(1)); } catch (NumberFormatException e) { throw new CommandSyntaxException( "Two numeric arguments are expected"); } if (lines < 0) throw new CommandSyntaxException( "Two numeric arguments are expected"); InputStream mailAsStream = session.getMaildrop().getMailAsStream(messageNumber); try { session.getThread().sendResponse("+OK"); ExtraDotOutputStream dotOutputStream = new ExtraDotOutputStream(session.getThread() .getOutputStream()); CrLfInputStream in = new CrLfInputStream(mailAsStream); byte[] buffer = new byte[1000]; int cRead; // read headers while (true) { cRead = in.readLineWithEol(buffer); if (cRead == -1) break; // no body dotOutputStream.write(buffer, 0, cRead); if (buffer[0] == '\r' || buffer[0] == '\n') break; } // read body int cLines = 0; while (cLines < lines) { try { cRead = in.readLineWithEol(buffer); } catch (MaxLineLengthException e) { // not a big problem, some body lines will be missing break; } if (cRead == -1) break; // end of mail dotOutputStream.write(buffer, 0, cRead); cLines++; } dotOutputStream.flush(); } finally { mailAsStream.close(); } session.getThread().sendResponse("."); } }