/** * Reads and consumes a number of characters from the underlying reader, * filling the byte array provided. * * @param holder A byte array which will be filled with bytes read from the underlying reader. * @throws ProtocolException If a char can't be read into each array element. */ public void read(byte[] holder) throws ProtocolException { int readTotal = 0; try { while (readTotal < holder.length) { int count = input.read(holder, readTotal, holder.length - readTotal); if (count == -1) { throw new ProtocolException("Unexpected end of stream."); } readTotal += count; } // Unset the next char. nextSeen = false; nextChar = 0; } catch (IOException e) { throw new ProtocolException("Error reading from stream.", e); } }
/** * Consumes the next character in the request, checking that it matches the * expected one. This method should be used when the */ protected void consumeChar(ImapRequestLineReader request, char expected) throws ProtocolException { char consumed = request.consume(); if (consumed != expected) { throw new ProtocolException("Expected:'" + expected + "' found:'" + consumed + '\''); } }
private void addItem(String nextWord, StatusDataItems items) throws ProtocolException { if (nextWord.equals(MESSAGES)) { items.messages = true; } else if (nextWord.equals(RECENT)) { items.recent = true; } else if (nextWord.equals(UIDNEXT)) { items.uidNext = true; } else if (nextWord.equals(UIDVALIDITY)) { items.uidValidity = true; } else if (nextWord.equals(UNSEEN)) { items.unseen = true; } else { throw new ProtocolException("Unknown status item: '" + nextWord + '\''); } } }
/** * Reads an argument of type "nznumber" (a non-zero number) * (NOTE this isn't strictly as per the spec, since the spec disallows * numbers such as "0123" as nzNumbers (although it's ok as a "number". * I think the spec is a bit shonky.) */ public long nzNumber(ImapRequestLineReader request) throws ProtocolException { long number = number(request); if (number == 0) { throw new ProtocolException("Zero value not permitted."); } return number; }
/** * Sends a server command continuation request '+' back to the client, * requesting more data to be sent. */ public void commandContinuationRequest() throws ProtocolException { try { output.write('+'); output.write(' '); output.write('O'); output.write('K'); output.write('\r'); output.write('\n'); output.flush(); } catch (IOException e) { throw new ProtocolException("Unexpected exception in sending command continuation request.", e); } }
/** * Reads the next character in the current line. This method will continue to return * the same character until the {@link #consume()} method is called. * * @return The next character. * @throws ProtocolException If the end-of-stream is reached. */ public char nextChar() throws ProtocolException { if (!nextSeen) { try { final int read = input.read(); final char c = (char) read; buf.append(c); if(read == -1) { dumpLine(); throw new ProtocolException("End of stream"); } nextChar = c; nextSeen = true; } catch (IOException e) { throw new ProtocolException("Error reading from stream.", e); } } return nextChar; }
/** * Reads a "date-time" argument from the request. */ public Date dateTime(ImapRequestLineReader request) throws ProtocolException { char next = request.nextWordChar(); String dateString; // From https://tools.ietf.org/html/rfc3501 : // date-time = DQUOTE date-day-fixed "-" date-month "-" date-year // SP time SP zone DQUOTE // zone = ("+" / "-") 4DIGIT if (next == '"') { dateString = consumeQuoted(request); } else { throw new ProtocolException("DateTime values must be quoted."); } try { // You can use Z or zzzz return new SimpleDateFormat("dd-MMM-yyyy hh:mm:ss Z", Locale.US).parse(dateString); } catch (ParseException e) { throw new ProtocolException("Invalid date format <" + dateString + ">, should comply to dd-MMM-yyyy hh:mm:ss Z"); } }
/** * Reads a MimeMessage encoded as a string literal from the request. * TODO shouldn't need to read as a string and write out bytes * use FixedLengthInputStream instead. Hopefully it can then be dynamic. * * @param request The Imap APPEND request * @return A MimeMessage read off the request. */ public MimeMessage mimeMessage(ImapRequestLineReader request) throws ProtocolException { request.nextWordChar(); byte[] mail = consumeLiteralAsBytes(request); try { return GreenMailUtil.newMimeMessage(new ByteArrayInputStream(mail)); } catch (Exception e) { throw new ProtocolException("Can not create new mime message", e); } }
private char nextCharInLine(ImapRequestLineReader request) throws ProtocolException { char next = request.nextChar(); if (isCrOrLf(next)) { request.dumpLine(); throw new ProtocolException("Unexpected end of line (CR or LF)."); } return next; }
@Override protected void doProcess(ImapRequestLineReader request, ImapResponse response, ImapSession session) throws ProtocolException, FolderException { String commandName = parser.atom(request); ImapCommand command = commandFactory.getCommand(commandName); if (command == null || !(command instanceof UidEnabledCommand)) { throw new ProtocolException("Invalid UID command: '" + commandName + "'"); } ((UidEnabledCommand) command).doProcess(request, response, session, true); }
/** * Reads the next "word from the request, comprising all characters up to the next SPACE. * Characters are tested by the supplied CharacterValidator, and an exception is thrown * if invalid characters are encountered. */ protected String consumeWord(ImapRequestLineReader request, CharacterValidator validator) throws ProtocolException { StringBuilder atom = new StringBuilder(); char next = request.nextWordChar(); while (!isWhitespace(next)) { if (validator.isValid(next)) { atom.append(next); request.consume(); } else { throw new ProtocolException("Invalid character: '" + next + '\''); } next = request.nextChar(); } return atom.toString(); }
/** * Reads an argument of type "nstring" from the request. */ public String nstring(ImapRequestLineReader request) throws ProtocolException { char next = request.nextWordChar(); switch (next) { case '"': return consumeQuoted(request); case '{': return consumeLiteral(request); default: String value = atom(request); if ("NIL".equals(value)) { return null; } else { throw new ProtocolException("Invalid nstring value: valid values are '\"...\"', '{12} CRLF *CHAR8', and 'NIL'."); } } }
/** * Reads the next regular, non-space character in the current line. Spaces are skipped * over, but end-of-line characters will cause a {@link ProtocolException} to be thrown. * This method will continue to return * the same character until the {@link #consume()} method is called. * * @return The next non-space character. * @throws ProtocolException If the end-of-line or end-of-stream is reached. */ public char nextWordChar() throws ProtocolException { char next = nextChar(); while (next == ' ') { consume(); next = nextChar(); } if (next == '\r' || next == '\n') { throw new ProtocolException("Missing argument."); } return next; }
StoreDirective storeDirective(ImapRequestLineReader request) throws ProtocolException { int sign = 0; boolean silent = false; char next = request.nextWordChar(); if (next == '+') { sign = 1; request.consume(); } else if (next == '-') { sign = -1; request.consume(); } else { sign = 0; } String directive = consumeWord(request, new NoopCharValidator()); if ("FLAGS".equalsIgnoreCase(directive)) { silent = false; } else if ("FLAGS.SILENT".equalsIgnoreCase(directive)) { silent = true; } else { throw new ProtocolException("Invalid Store Directive: '" + directive + '\''); } return new StoreDirective(sign, silent); } }
/** * Reads a quoted string value from the request. */ protected String consumeQuoted(ImapRequestLineReader request) throws ProtocolException { // The 1st character must be '"' consumeChar(request, '"'); StringBuilder quoted = new StringBuilder(); char next = request.nextChar(); while (next != '"') { if (next == '\\') { request.consume(); next = request.nextChar(); if (!isQuotedSpecial(next)) { throw new ProtocolException("Invalid escaped character in quote: '" + next + '\''); } } quoted.append(next); request.consume(); next = request.nextChar(); } consumeChar(request, '"'); return quoted.toString(); }
fetch.add(new BodyFetchElement("RFC822.TEXT", "TEXT"), false); } else { throw new ProtocolException("Invalid fetch attribute: " + name); fetch.add(new BodyFetchElement("BODY[" + parameter + ']', parameter, partial), true); } else { throw new ProtocolException("Invalid fetch attribute: " + name + "[]");
/** * Moves the request line reader to end of the line, checking that no non-space * character are found. * * @throws ProtocolException If more non-space tokens are found in this line, * or the end-of-file is reached. */ public void eol() throws ProtocolException { char next = nextChar(); // Ignore trailing spaces. while (next == ' ') { consume(); next = nextChar(); } // handle DOS and unix end-of-lines if (next == '\r') { consume(); next = nextChar(); } // Check if we found extra characters. if (next != '\n') { throw new ProtocolException("Expected end-of-line, found more character(s): "+next); } dumpLine(); }