1 package org
.apache
.james
.mime4j
;
3 import java
.io
.IOException
;
4 import java
.io
.InputStream
;
6 import org
.apache
.james
.mime4j
.decoder
.Base64InputStream
;
7 import org
.apache
.james
.mime4j
.decoder
.QuotedPrintableInputStream
;
8 import org
.apache
.james
.mime4j
.util
.MimeUtil
;
10 public class MimeEntity
extends AbstractEntity
{
13 * Internal state, not exposed.
15 private static final int T_IN_BODYPART
= -2;
17 * Internal state, not exposed.
19 private static final int T_IN_MESSAGE
= -3;
21 private final InputBuffer inbuffer
;
22 private final InputStream rawStream
;
24 private int recursionMode
;
25 private MimeBoundaryInputStream mimeStream
;
26 private EOFSensitiveInputStream dataStream
;
27 private boolean skipHeader
;
30 RootInputStream rootStream
,
31 InputStream rawStream
,
33 BodyDescriptor parent
,
36 boolean maximalBodyDescriptor
,
37 boolean strictParsing
) {
38 super(rootStream
, parent
, startState
, endState
, maximalBodyDescriptor
, strictParsing
);
39 this.inbuffer
= inbuffer
;
40 this.rawStream
= rawStream
;
41 this.dataStream
= new EOFSensitiveInputStream(rawStream
);
42 this.skipHeader
= false;
46 RootInputStream rootStream
,
47 InputStream rawStream
,
49 BodyDescriptor parent
,
52 this(rootStream
, rawStream
, inbuffer
, parent
, startState
, endState
, false, false);
55 public int getRecursionMode() {
59 public void setRecursionMode(int recursionMode
) {
60 this.recursionMode
= recursionMode
;
63 public void skipHeader(String contentType
) {
64 if (state
!= EntityStates
.T_START_MESSAGE
) {
65 throw new IllegalStateException("Invalid state: " + stateToString(state
));
68 body
.addField("Content-Type", contentType
);
71 protected InputStream
getDataStream() {
75 public EntityStateMachine
advance() throws IOException
, MimeException
{
77 case EntityStates
.T_START_MESSAGE
:
79 state
= EntityStates
.T_END_HEADER
;
81 state
= EntityStates
.T_START_HEADER
;
84 case EntityStates
.T_START_BODYPART
:
85 state
= EntityStates
.T_START_HEADER
;
87 case EntityStates
.T_START_HEADER
:
89 state
= parseField() ? EntityStates
.T_FIELD
: EntityStates
.T_END_HEADER
;
91 case EntityStates
.T_FIELD
:
92 state
= parseField() ? EntityStates
.T_FIELD
: EntityStates
.T_END_HEADER
;
94 case EntityStates
.T_END_HEADER
:
95 String mimeType
= body
.getMimeType();
96 if (recursionMode
== RecursionMode
.M_FLAT
) {
97 state
= EntityStates
.T_BODY
;
98 } else if (MimeUtil
.isMultipart(mimeType
)) {
99 state
= EntityStates
.T_START_MULTIPART
;
101 } else if (recursionMode
!= RecursionMode
.M_NO_RECURSE
102 && MimeUtil
.isMessage(mimeType
)) {
103 state
= T_IN_MESSAGE
;
104 return nextMessage();
106 state
= EntityStates
.T_BODY
;
109 case EntityStates
.T_START_MULTIPART
:
110 if (dataStream
.isUsed()) {
112 state
= EntityStates
.T_END_MULTIPART
;
115 state
= EntityStates
.T_PREAMBLE
;
118 case EntityStates
.T_PREAMBLE
:
120 if (mimeStream
.isLastPart()) {
122 state
= EntityStates
.T_END_MULTIPART
;
125 state
= T_IN_BODYPART
;
126 return nextMimeEntity();
131 if (mimeStream
.eof() && !mimeStream
.isLastPart()) {
132 monitor(Event
.MIME_BODY_PREMATURE_END
);
134 if (!mimeStream
.isLastPart()) {
136 state
= T_IN_BODYPART
;
137 return nextMimeEntity();
141 state
= EntityStates
.T_EPILOGUE
;
143 case EntityStates
.T_EPILOGUE
:
144 state
= EntityStates
.T_END_MULTIPART
;
146 case EntityStates
.T_BODY
:
147 case EntityStates
.T_END_MULTIPART
:
152 if (state
== endState
) {
153 state
= EntityStates
.T_END_OF_STREAM
;
156 throw new IllegalStateException("Invalid state: " + stateToString(state
));
161 private void createMimeStream() throws IOException
{
162 mimeStream
= new MimeBoundaryInputStream(inbuffer
, body
.getBoundary());
163 dataStream
= new EOFSensitiveInputStream(mimeStream
);
166 private void clearMimeStream() {
168 dataStream
= new EOFSensitiveInputStream(rawStream
);
171 private void advanceToBoundary() throws IOException
{
172 if (!dataStream
.eof()) {
173 byte[] tmp
= new byte[2048];
174 while (dataStream
.read(tmp
)!= -1) {
179 private EntityStateMachine
nextMessage() {
180 String transferEncoding
= body
.getTransferEncoding();
181 InputStream instream
;
182 if (MimeUtil
.isBase64Encoding(transferEncoding
)) {
183 log
.debug("base64 encoded message/rfc822 detected");
184 instream
= new EOLConvertingInputStream(
185 new Base64InputStream(mimeStream
));
186 } else if (MimeUtil
.isQuotedPrintableEncoded(transferEncoding
)) {
187 log
.debug("quoted-printable encoded message/rfc822 detected");
188 instream
= new EOLConvertingInputStream(
189 new QuotedPrintableInputStream(mimeStream
));
191 instream
= dataStream
;
194 if (recursionMode
== RecursionMode
.M_RAW
) {
195 RawEntity message
= new RawEntity(instream
);
198 MimeEntity message
= new MimeEntity(
203 EntityStates
.T_START_MESSAGE
,
204 EntityStates
.T_END_MESSAGE
,
205 maximalBodyDescriptor
,
207 message
.setRecursionMode(recursionMode
);
212 private EntityStateMachine
nextMimeEntity() {
213 if (recursionMode
== RecursionMode
.M_RAW
) {
214 RawEntity message
= new RawEntity(mimeStream
);
217 MimeEntity mimeentity
= new MimeEntity(
222 EntityStates
.T_START_BODYPART
,
223 EntityStates
.T_END_BODYPART
,
224 maximalBodyDescriptor
,
226 mimeentity
.setRecursionMode(recursionMode
);
231 public InputStream
getContentStream() {
233 case EntityStates
.T_START_MULTIPART
:
234 case EntityStates
.T_PREAMBLE
:
235 case EntityStates
.T_EPILOGUE
:
236 case EntityStates
.T_BODY
:
237 return this.dataStream
;
239 throw new IllegalStateException("Invalid state: " + stateToString(state
));