You are viewing a plain text version of this content. The canonical link for it is here.
Posted to server-dev@james.apache.org by rd...@apache.org on 2007/09/08 16:35:07 UTC
svn commit: r573847 - in /james/mime4j/trunk/src:
main/java/org/apache/james/mime4j/MimeParseEventException.java
main/java/org/apache/james/mime4j/MimeTokenStream.java
test/java/org/apache/james/mime4j/StrictMimeTokenStreamTest.java
Author: rdonkin
Date: Sat Sep 8 07:35:06 2007
New Revision: 573847
URL: http://svn.apache.org/viewvc?rev=573847&view=rev
Log:
Add support for strict validation. Implemented by adding event monitor. Developed in https://issues.apache.org/jira/browse/MIME4J-23.
Added:
james/mime4j/trunk/src/main/java/org/apache/james/mime4j/MimeParseEventException.java
james/mime4j/trunk/src/test/java/org/apache/james/mime4j/StrictMimeTokenStreamTest.java
Modified:
james/mime4j/trunk/src/main/java/org/apache/james/mime4j/MimeTokenStream.java
Added: james/mime4j/trunk/src/main/java/org/apache/james/mime4j/MimeParseEventException.java
URL: http://svn.apache.org/viewvc/james/mime4j/trunk/src/main/java/org/apache/james/mime4j/MimeParseEventException.java?rev=573847&view=auto
==============================================================================
--- james/mime4j/trunk/src/main/java/org/apache/james/mime4j/MimeParseEventException.java (added)
+++ james/mime4j/trunk/src/main/java/org/apache/james/mime4j/MimeParseEventException.java Sat Sep 8 07:35:06 2007
@@ -0,0 +1,48 @@
+/****************************************************************
+ * 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.mime4j;
+
+/**
+ * Indicates that strict parsing has been enabled
+ * and an optional invality has been found in the input.
+ * {@link #getEvent()} indicates the type of invalidity.
+ */
+public class MimeParseEventException extends MimeException {
+
+ private static final long serialVersionUID = 4632991604246852302L;
+ private final MimeTokenStream.Event event;
+
+ /**
+ * Constructs an exception
+ * @param event <code>MimeTokenStream.Event</code>, not null
+ */
+ public MimeParseEventException(final MimeTokenStream.Event event) {
+ super(event.toString());
+ this.event = event;
+ }
+
+ /**
+ * Gets the causal parse event.
+ * @return <code>MimeTokenStream.Event</code>, not null
+ */
+ public MimeTokenStream.Event getEvent() {
+ return event;
+ }
+}
Modified: james/mime4j/trunk/src/main/java/org/apache/james/mime4j/MimeTokenStream.java
URL: http://svn.apache.org/viewvc/james/mime4j/trunk/src/main/java/org/apache/james/mime4j/MimeTokenStream.java?rev=573847&r1=573846&r2=573847&view=diff
==============================================================================
--- james/mime4j/trunk/src/main/java/org/apache/james/mime4j/MimeTokenStream.java (original)
+++ james/mime4j/trunk/src/main/java/org/apache/james/mime4j/MimeTokenStream.java Sat Sep 8 07:35:06 2007
@@ -168,6 +168,57 @@
fieldChars.set(i);
}
}
+
+ /**
+ * Creates a stream that strictly validates the input.
+ * @return <code>MimeTokenStream</code> which throws a
+ * <code>MimeException</code> whenever possible issues
+ * are dedicated in the input
+ */
+ public static final MimeTokenStream createStrictValidationStream() {
+ return new MimeTokenStream(true);
+ }
+
+ /**
+ * Enumerates events which can be monitored.
+ */
+ public final static class Event {
+
+ /** Indicates that a body part ended prematurely. */
+ public static final Event MIME_BODY_PREMATURE_END
+ = new Event("Body part ended prematurely. " +
+ "Boundary detected in header or EOF reached.");
+ /** Indicates that unexpected end of headers detected.*/
+ public static final Event HEADERS_PREMATURE_END
+ = new Event("Unexpected end of headers detected. " +
+ "Higher level boundary detected or EOF reached.");
+
+ private final String code;
+
+ private Event(final String code) {
+ super();
+ this.code = code;
+ }
+
+ public int hashCode() {
+ return code.hashCode();
+ }
+
+ public boolean equals(Object obj) {
+ if (this == obj)
+ return true;
+ if (obj == null)
+ return false;
+ if (getClass() != obj.getClass())
+ return false;
+ final Event other = (Event) obj;
+ return code.equals(other.code);
+ }
+
+ public String toString() {
+ return code;
+ }
+ }
abstract static class StateMachine {
int state;
@@ -208,15 +259,10 @@
state = parseField() ? T_FIELD : T_END_HEADER;
}
- private int setParseBodyPartState() throws IOException {
+ private int setParseBodyPartState() throws IOException, MimeException {
cursor.advanceToBoundary();
if (cursor.isEnded()) {
- if (log.isWarnEnabled()) {
- log.warn("Line " + cursor.getLineNumber()
- + ": Body part ended prematurely. "
- + "Higher level boundary detected or "
- + "EOF reached.");
- }
+ monitor(Event.MIME_BODY_PREMATURE_END);
} else {
if (cursor.moreMimeParts()) {
final String boundary = body.getBoundary();
@@ -296,7 +342,7 @@
return state;
}
- private void initHeaderParsing() throws IOException {
+ private void initHeaderParsing() throws IOException, MimeException {
body = newBodyDescriptor(parent);
startLineNumber = lineNumber = cursor.getLineNumber();
@@ -314,10 +360,8 @@
prev = curr == '\r' ? prev : curr;
}
- if (curr == -1 && log.isWarnEnabled()) {
- log.warn("Line " + cursor.getLineNumber()
- + ": Unexpected end of headers detected. "
- + "Boundary detected in header or EOF reached.");
+ if (curr == -1) {
+ monitor(Event.HEADERS_PREMATURE_END);
}
}
@@ -386,12 +430,27 @@
}
}
+ private final boolean strictParsing;
private int state = T_END_OF_STREAM;
private Cursor cursor;
private StateMachine currentStateMachine;
private final List entities = new ArrayList();
private boolean raw;
-
+
+ /**
+ * Constructs a standard (lax) stream.
+ * Optional validation events will be logged only.
+ * Use {@link #createStrictValidationStream()} to create
+ * a stream that strictly validates the input.
+ */
+ public MimeTokenStream() {
+ this(false);
+ }
+
+ private MimeTokenStream(final boolean strictParsing) {
+ this.strictParsing = strictParsing;
+ }
+
/** Instructs the {@code MimeTokenStream} to parse the given streams contents.
* If the {@code MimeTokenStream} has already been in use, resets the streams
* internal state.
@@ -436,7 +495,7 @@
public void setRaw(boolean raw) {
this.raw = raw;
}
-
+
/**
* Finishes the parsing and stops reading lines.
* NOTE: No more lines will be parsed but the parser
@@ -502,6 +561,70 @@
return ((Entity) currentStateMachine).fieldValue;
default:
throw new IllegalStateException("Expected state to be T_FIELD.");
+ }
+ }
+
+ /**
+ * Monitors the given event.
+ * Subclasses may override to perform actions upon events.
+ * Base implementation logs at warn.
+ * @param event <code>Event</code>, not null
+ * @throws MimeException subclasses may elect to throw this exception upon
+ * invalid content
+ * @throws IOException subclasses may elect to throw this exception
+ */
+ protected void monitor(Event event) throws MimeException, IOException {
+ if (strictParsing) {
+ throw new MimeParseEventException(event);
+ } else {
+ warn(event);
+ }
+ }
+
+ /**
+ * Creates an indicative message suitable for display
+ * based on the given event and the current state of the system.
+ * @param event <code>Event</code>, not null
+ * @return message suitable for use as a message in an exception
+ * or for logging
+ */
+ protected String message(Event event) {
+ String preamble = "";
+ try {
+ preamble = "Line " + cursor.getLineNumber() + ": ";
+ } catch (IOException e) {
+ log.debug("Cannot get event line number.", e);
+ }
+
+ final String message;
+ if (event == null) {
+ message = "Event is unexpectedly null.";
+ } else {
+ message = event.toString();
+ }
+ final String result = preamble + message;
+ return result;
+ }
+
+ /**
+ * Logs (at warn) an indicative message based on the given event
+ * and the current state of the system.
+ * @param event <code>Event</code>, not null
+ */
+ protected void warn(Event event) {
+ if (log.isWarnEnabled()) {
+ log.warn(message(event));
+ }
+ }
+
+ /**
+ * Logs (at debug) an indicative message based on the given event
+ * and the current state of the system.
+ * @param event <code>Event</code>, not null
+ */
+ protected void debug(Event event) {
+ if (log.isDebugEnabled()) {
+ log.debug(message(event));
}
}
Added: james/mime4j/trunk/src/test/java/org/apache/james/mime4j/StrictMimeTokenStreamTest.java
URL: http://svn.apache.org/viewvc/james/mime4j/trunk/src/test/java/org/apache/james/mime4j/StrictMimeTokenStreamTest.java?rev=573847&view=auto
==============================================================================
--- james/mime4j/trunk/src/test/java/org/apache/james/mime4j/StrictMimeTokenStreamTest.java (added)
+++ james/mime4j/trunk/src/test/java/org/apache/james/mime4j/StrictMimeTokenStreamTest.java Sat Sep 8 07:35:06 2007
@@ -0,0 +1,57 @@
+/****************************************************************
+ * 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.mime4j;
+
+import java.io.ByteArrayInputStream;
+
+import junit.framework.TestCase;
+
+public class StrictMimeTokenStreamTest extends TestCase {
+
+ private static final String HEADER_ONLY = "From: foo@abr.com\r\nSubject: A subject\r\n";
+ private static final String CORRECT_HEADERS = HEADER_ONLY + "\r\n";
+
+ public void testUnexpectedEndOfHeaders() throws Exception {
+
+ MimeTokenStream parser = MimeTokenStream.createStrictValidationStream();
+
+ parser.parse(new ByteArrayInputStream(HEADER_ONLY.getBytes()));
+
+ assertEquals("Headers start", MimeTokenStream.T_START_HEADER, parser.next());
+ try {
+ parser.next();
+ fail("Expected exception to be thrown");
+ } catch (MimeParseEventException e) {
+ assertEquals("Premature end of headers", MimeTokenStream.Event.HEADERS_PREMATURE_END, e.getEvent());
+ }
+ }
+
+ public void testCorrectEndOfHeaders() throws Exception {
+
+ MimeTokenStream parser = MimeTokenStream.createStrictValidationStream();
+
+ parser.parse(new ByteArrayInputStream(CORRECT_HEADERS.getBytes()));
+
+ assertEquals("Headers start", MimeTokenStream.T_START_HEADER, parser.next());
+ assertEquals("From header", MimeTokenStream.T_FIELD, parser.next());
+ assertEquals("Subject header", MimeTokenStream.T_FIELD, parser.next());
+ assertEquals("End message", MimeTokenStream.T_END_HEADER, parser.next());
+ }
+}
---------------------------------------------------------------------
To unsubscribe, e-mail: server-dev-unsubscribe@james.apache.org
For additional commands, e-mail: server-dev-help@james.apache.org
Re: svn commit: r573847 - in /james/mime4j/trunk/src: main/java/org/apache/james/mime4j/MimeParseEventException.java
main/java/org/apache/james/mime4j/MimeTokenStream.java test/java/org/apache/james/mime4j/StrictMimeTokenStreamTest.java
Posted by Stefano Bagnara <ap...@bago.org>.
rdonkin@apache.org ha scritto:
> Author: rdonkin
> Date: Sat Sep 8 07:35:06 2007
> New Revision: 573847
>
> URL: http://svn.apache.org/viewvc?rev=573847&view=rev
> Log:
> Add support for strict validation. Implemented by adding event monitor. Developed in https://issues.apache.org/jira/browse/MIME4J-23.
I suggest you to use the JIRA identifier (MIME4J-23) as a standalone
word, otherwise svn plugin for JIRA does not recognize the commit is
about that issue and does not show it in the issue log.
I found it very useful to see svn commits related to issues in JIRA.
Stefano
PS: welcome back! :-)
---------------------------------------------------------------------
To unsubscribe, e-mail: server-dev-unsubscribe@james.apache.org
For additional commands, e-mail: server-dev-help@james.apache.org