~ubuntu-branches/ubuntu/saucy/apache-mime4j/saucy

« back to all changes in this revision

Viewing changes to src/test/java/org/apache/james/mime4j/parser/MultipartTokensTest.java

  • Committer: Bazaar Package Importer
  • Author(s): David Paleino
  • Date: 2010-07-13 09:28:28 UTC
  • Revision ID: james.westby@ubuntu.com-20100713092828-g6wafdtidgmtx7su
Tags: upstream-0.6
ImportĀ upstreamĀ versionĀ 0.6

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/****************************************************************
 
2
 * Licensed to the Apache Software Foundation (ASF) under one   *
 
3
 * or more contributor license agreements.  See the NOTICE file *
 
4
 * distributed with this work for additional information        *
 
5
 * regarding copyright ownership.  The ASF licenses this file   *
 
6
 * to you under the Apache License, Version 2.0 (the            *
 
7
 * "License"); you may not use this file except in compliance   *
 
8
 * with the License.  You may obtain a copy of the License at   *
 
9
 *                                                              *
 
10
 *   http://www.apache.org/licenses/LICENSE-2.0                 *
 
11
 *                                                              *
 
12
 * Unless required by applicable law or agreed to in writing,   *
 
13
 * software distributed under the License is distributed on an  *
 
14
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY       *
 
15
 * KIND, either express or implied.  See the License for the    *
 
16
 * specific language governing permissions and limitations      *
 
17
 * under the License.                                           *
 
18
 ****************************************************************/
 
19
 
 
20
package org.apache.james.mime4j.parser;
 
21
 
 
22
import java.io.ByteArrayInputStream;
 
23
import java.io.IOException;
 
24
import java.nio.charset.Charset;
 
25
 
 
26
import junit.framework.TestCase;
 
27
 
 
28
import org.apache.commons.io.IOUtils;
 
29
import org.apache.james.mime4j.MimeException;
 
30
import org.apache.james.mime4j.util.CharsetUtil;
 
31
 
 
32
public class MultipartTokensTest extends TestCase {
 
33
 
 
34
    private static final Charset US_ASCII = CharsetUtil.US_ASCII;
 
35
    
 
36
    private static final String BODY = "A Preamble\r\n" +
 
37
                "--1729\r\n\r\n" +
 
38
                "Simple plain text\r\n" +
 
39
                "--1729\r\n" +
 
40
                "Content-Type: text/plain; charset=US-ASCII\r\n\r\n" +
 
41
                "Some more text\r\n" +
 
42
                "--1729--\r\n";
 
43
    public static final String MESSAGE = "To: Road Runner <runner@example.org>\r\n" +
 
44
            "From: Wile E. Cayote <wile@example.org>\r\n" +
 
45
            "Date: Tue, 12 Feb 2008 17:34:09 +0000 (GMT)\r\n" +
 
46
            "Subject: Mail\r\n" +
 
47
            "Content-Type: multipart/mixed;boundary=1729\r\n\r\n" +
 
48
            BODY;
 
49
    
 
50
    public static final String COMPLEX_MESSAGE = "To: Wile E. Cayote <wile@example.org>\r\n" +
 
51
    "From: Road Runner <runner@example.org>\r\n" +
 
52
    "Date: Tue, 19 Feb 2008 17:34:09 +0000 (GMT)\r\n" +
 
53
    "Subject: Mail\r\n" +
 
54
    "Content-Type: multipart/mixed;boundary=42\r\n\r\n" +
 
55
    "A little preamble\r\n" +
 
56
    "--42\r\n" +
 
57
    "Content-Type: text/plain; charset=US-ASCII\r\n\r\n" +
 
58
    "Rhubard!\r\n" +
 
59
    "--42\r\n" +
 
60
    "Content-Type: message/rfc822\r\n\r\n" +
 
61
    MESSAGE +
 
62
    "\r\n" +
 
63
    "--42\r\n" +
 
64
    "\r\n" +
 
65
    "Custard!" +
 
66
    "\r\n" +
 
67
    "--42--\r\n";
 
68
    
 
69
    public static final String COMPLEX_QP_MESSAGE = 
 
70
        "Content-Transfer-Encoding: quoted-printable\r\n" +
 
71
        "Content-Type: message/rfc822; charset=us-ascii\r\n" +
 
72
        "\r\n" +
 
73
        "Subject: The subject\r\n" +
 
74
        "Content-Type: multipart/alternative;\r\n" +
 
75
        "        boundary=3D=22----=3DNextPart=22\r\n" +
 
76
        "\r\n" +
 
77
        "This is a multi-part message in MIME format.\r\n" +
 
78
        "\r\n" +
 
79
        "------=3DNextPart\r\n" +
 
80
        "Content-Type: text/plain;\r\n" +
 
81
        "        charset=3D=22iso-8859-1=22\r\n" +
 
82
        "\r\n" +
 
83
        "Some text\r\n" +
 
84
        "\r\n" +
 
85
        "------=3DNextPart\r\n" +
 
86
        "Content-Type: text/html;\r\n" +
 
87
        "        charset=3D=22iso-8859-1=22\r\n" +
 
88
        "\r\n" +
 
89
        "<HTML><BODY>=3D Some HTML =3D</BODY></HTML>\r\n" +
 
90
        "------=3DNextPart--\r\n" +
 
91
        "\r\n" +
 
92
        "\r\n";
 
93
    
 
94
    MimeTokenStream parser;
 
95
    
 
96
    @Override
 
97
    protected void setUp() throws Exception {
 
98
        super.setUp();
 
99
        parser = new MimeTokenStream();
 
100
    }
 
101
 
 
102
    @Override
 
103
    protected void tearDown() throws Exception {
 
104
        super.tearDown();
 
105
    }
 
106
    
 
107
    public void testShouldParseSimpleMessage() throws Exception {
 
108
        parser.parse(new ByteArrayInputStream(US_ASCII.encode(MESSAGE).array()));
 
109
        checkState(MimeTokenStream.T_START_HEADER);
 
110
        checkState(MimeTokenStream.T_FIELD);
 
111
        checkState(MimeTokenStream.T_FIELD);
 
112
        checkState(MimeTokenStream.T_FIELD);
 
113
        checkState(MimeTokenStream.T_FIELD);
 
114
        checkState(MimeTokenStream.T_FIELD);
 
115
        checkState(MimeTokenStream.T_END_HEADER);
 
116
        checkState(MimeTokenStream.T_START_MULTIPART);
 
117
        checkState(MimeTokenStream.T_PREAMBLE);
 
118
        checkState(MimeTokenStream.T_START_BODYPART);
 
119
        checkState(MimeTokenStream.T_START_HEADER);
 
120
        checkState(MimeTokenStream.T_END_HEADER);
 
121
        checkState(MimeTokenStream.T_BODY);
 
122
        checkState(MimeTokenStream.T_END_BODYPART);
 
123
        checkState(MimeTokenStream.T_START_BODYPART);
 
124
        checkState(MimeTokenStream.T_START_HEADER);
 
125
        checkState(MimeTokenStream.T_FIELD);
 
126
        checkState(MimeTokenStream.T_END_HEADER);
 
127
        checkState(MimeTokenStream.T_BODY);
 
128
        checkState(MimeTokenStream.T_END_BODYPART);
 
129
        checkState(MimeTokenStream.T_EPILOGUE);
 
130
        checkState(MimeTokenStream.T_END_MULTIPART);
 
131
        checkState(MimeTokenStream.T_END_MESSAGE);
 
132
        checkState(MimeTokenStream.T_END_OF_STREAM);
 
133
    }
 
134
    
 
135
    public void testShouldParseMoreComplexMessage() throws Exception {
 
136
        String message = 
 
137
            "Content-Type: multipart/alternative; boundary=\"outer-boundary\"\r\n" +
 
138
            "\r\n" +
 
139
            "--outer-boundary\r\n" +
 
140
            "Content-Type: multipart/alternative; boundary=\"inner-boundary\"\r\n" +
 
141
            "\r\n" +
 
142
            "--inner-boundary\r\n" +
 
143
            "Content-Type: text/plain\r\n" +
 
144
            "\r\n" +
 
145
            "Some text\r\n" +
 
146
            "--inner-boundary--\r\n" +
 
147
            "\r\n" +
 
148
            "foo\r\n" +
 
149
            "--outer-boundary--\r\n";
 
150
        
 
151
        parser.parse(new ByteArrayInputStream(US_ASCII.encode(message).array()));
 
152
        checkState(MimeTokenStream.T_START_HEADER);
 
153
        checkState(MimeTokenStream.T_FIELD);
 
154
        checkState(MimeTokenStream.T_END_HEADER);
 
155
        checkState(MimeTokenStream.T_START_MULTIPART);
 
156
        checkState(MimeTokenStream.T_PREAMBLE);
 
157
        checkState(MimeTokenStream.T_START_BODYPART);
 
158
        checkState(MimeTokenStream.T_START_HEADER);
 
159
        checkState(MimeTokenStream.T_FIELD);
 
160
        checkState(MimeTokenStream.T_END_HEADER);
 
161
        checkState(MimeTokenStream.T_START_MULTIPART);
 
162
        checkState(MimeTokenStream.T_PREAMBLE);
 
163
        checkState(MimeTokenStream.T_START_BODYPART);
 
164
        checkState(MimeTokenStream.T_START_HEADER);
 
165
        checkState(MimeTokenStream.T_FIELD);
 
166
        checkState(MimeTokenStream.T_END_HEADER);
 
167
        checkState(MimeTokenStream.T_BODY);
 
168
        checkState(MimeTokenStream.T_END_BODYPART);
 
169
        checkState(MimeTokenStream.T_EPILOGUE);
 
170
        checkState(MimeTokenStream.T_END_MULTIPART);
 
171
        checkState(MimeTokenStream.T_END_BODYPART);
 
172
        checkState(MimeTokenStream.T_EPILOGUE);
 
173
        checkState(MimeTokenStream.T_END_MULTIPART);
 
174
        checkState(MimeTokenStream.T_END_MESSAGE);
 
175
        checkState(MimeTokenStream.T_END_OF_STREAM);
 
176
    }
 
177
    
 
178
    public void testShouldParseMessageWithEmbeddedMessage() throws Exception {
 
179
        parser.parse(new ByteArrayInputStream(US_ASCII.encode(COMPLEX_MESSAGE).array()));
 
180
        checkState(MimeTokenStream.T_START_HEADER);
 
181
            checkState(MimeTokenStream.T_FIELD);
 
182
            checkState(MimeTokenStream.T_FIELD);
 
183
            checkState(MimeTokenStream.T_FIELD);
 
184
            checkState(MimeTokenStream.T_FIELD);
 
185
            checkState(MimeTokenStream.T_FIELD);
 
186
        checkState(MimeTokenStream.T_END_HEADER);
 
187
        checkState(MimeTokenStream.T_START_MULTIPART);
 
188
            checkState(MimeTokenStream.T_PREAMBLE);
 
189
            checkState(MimeTokenStream.T_START_BODYPART);
 
190
                checkState(MimeTokenStream.T_START_HEADER);
 
191
                    checkState(MimeTokenStream.T_FIELD);
 
192
                checkState(MimeTokenStream.T_END_HEADER);
 
193
                checkState(MimeTokenStream.T_BODY);
 
194
            checkState(MimeTokenStream.T_END_BODYPART);
 
195
            checkState(MimeTokenStream.T_START_BODYPART);
 
196
                checkState(MimeTokenStream.T_START_HEADER);
 
197
                    checkState(MimeTokenStream.T_FIELD);
 
198
                checkState(MimeTokenStream.T_END_HEADER);
 
199
                checkState(MimeTokenStream.T_START_MESSAGE);
 
200
                    checkState(MimeTokenStream.T_START_HEADER);
 
201
                        checkState(MimeTokenStream.T_FIELD);
 
202
                        checkState(MimeTokenStream.T_FIELD);
 
203
                        checkState(MimeTokenStream.T_FIELD);
 
204
                        checkState(MimeTokenStream.T_FIELD);
 
205
                        checkState(MimeTokenStream.T_FIELD);
 
206
                    checkState(MimeTokenStream.T_END_HEADER);
 
207
                    checkState(MimeTokenStream.T_START_MULTIPART);
 
208
                        checkState(MimeTokenStream.T_PREAMBLE);
 
209
                        checkState(MimeTokenStream.T_START_BODYPART);
 
210
                            checkState(MimeTokenStream.T_START_HEADER);
 
211
                            checkState(MimeTokenStream.T_END_HEADER);   
 
212
                            checkState(MimeTokenStream.T_BODY);
 
213
                        checkState(MimeTokenStream.T_END_BODYPART);
 
214
                        checkState(MimeTokenStream.T_START_BODYPART);
 
215
                            checkState(MimeTokenStream.T_START_HEADER);
 
216
                                checkState(MimeTokenStream.T_FIELD);
 
217
                            checkState(MimeTokenStream.T_END_HEADER);
 
218
                            checkState(MimeTokenStream.T_BODY);
 
219
                        checkState(MimeTokenStream.T_END_BODYPART);
 
220
                        checkState(MimeTokenStream.T_EPILOGUE);
 
221
                    checkState(MimeTokenStream.T_END_MULTIPART);
 
222
                checkState(MimeTokenStream.T_END_MESSAGE);
 
223
            checkState(MimeTokenStream.T_END_BODYPART);
 
224
            checkState(MimeTokenStream.T_START_BODYPART);
 
225
                checkState(MimeTokenStream.T_START_HEADER);
 
226
                checkState(MimeTokenStream.T_END_HEADER);
 
227
                checkState(MimeTokenStream.T_BODY);
 
228
            checkState(MimeTokenStream.T_END_BODYPART);
 
229
            checkState(MimeTokenStream.T_EPILOGUE);
 
230
        checkState(MimeTokenStream.T_END_MULTIPART);
 
231
        checkState(MimeTokenStream.T_END_MESSAGE);
 
232
        checkState(MimeTokenStream.T_END_OF_STREAM);
 
233
    }
 
234
 
 
235
    public void testShouldParseMessagesWithEmbeddedQuotedPrintableEncodedMessage() throws Exception {
 
236
        parser.parse(new ByteArrayInputStream(US_ASCII.encode(COMPLEX_QP_MESSAGE).array()));
 
237
        checkState(MimeTokenStream.T_START_HEADER);
 
238
        checkState(MimeTokenStream.T_FIELD);
 
239
        checkState(MimeTokenStream.T_FIELD);
 
240
        checkState(MimeTokenStream.T_END_HEADER);
 
241
        checkState(MimeTokenStream.T_START_MESSAGE);
 
242
        checkState(MimeTokenStream.T_START_HEADER);
 
243
        checkState(MimeTokenStream.T_FIELD);
 
244
        checkState(MimeTokenStream.T_FIELD);
 
245
        checkState(MimeTokenStream.T_END_HEADER);
 
246
        checkState(MimeTokenStream.T_START_MULTIPART);
 
247
        checkState(MimeTokenStream.T_PREAMBLE);
 
248
        checkState(MimeTokenStream.T_START_BODYPART);
 
249
        checkState(MimeTokenStream.T_START_HEADER);
 
250
        checkState(MimeTokenStream.T_FIELD);
 
251
        checkState(MimeTokenStream.T_END_HEADER);
 
252
        checkState(MimeTokenStream.T_BODY);
 
253
        assertEquals("text/plain", parser.getBodyDescriptor().getMimeType());
 
254
        assertEquals("iso-8859-1", parser.getBodyDescriptor().getCharset());
 
255
        assertEquals("Some text\r\n", 
 
256
                IOUtils.toString(parser.getInputStream()));
 
257
        checkState(MimeTokenStream.T_END_BODYPART);
 
258
        checkState(MimeTokenStream.T_START_BODYPART);
 
259
        checkState(MimeTokenStream.T_START_HEADER);
 
260
        checkState(MimeTokenStream.T_FIELD);
 
261
        checkState(MimeTokenStream.T_END_HEADER);
 
262
        checkState(MimeTokenStream.T_BODY);
 
263
        assertEquals("text/html", parser.getBodyDescriptor().getMimeType());
 
264
        assertEquals("iso-8859-1", parser.getBodyDescriptor().getCharset());
 
265
        assertEquals("<HTML><BODY>= Some HTML =</BODY></HTML>", 
 
266
                IOUtils.toString(parser.getInputStream()));
 
267
        checkState(MimeTokenStream.T_END_BODYPART);
 
268
        checkState(MimeTokenStream.T_EPILOGUE);
 
269
        checkState(MimeTokenStream.T_END_MULTIPART);
 
270
        checkState(MimeTokenStream.T_END_MESSAGE);
 
271
        checkState(MimeTokenStream.T_END_MESSAGE);
 
272
        checkState(MimeTokenStream.T_END_OF_STREAM);
 
273
    }
 
274
    
 
275
    public void testMultipartMessageWithoutHeader() throws Exception {
 
276
        parser.parseHeadless(new ByteArrayInputStream(US_ASCII.encode(BODY).array()), 
 
277
                "multipart/mixed;boundary=1729");
 
278
        checkState(MimeTokenStream.T_END_HEADER);
 
279
        checkState(MimeTokenStream.T_START_MULTIPART);
 
280
        checkState(MimeTokenStream.T_PREAMBLE);
 
281
        checkState(MimeTokenStream.T_START_BODYPART);
 
282
        checkState(MimeTokenStream.T_START_HEADER);
 
283
        checkState(MimeTokenStream.T_END_HEADER);
 
284
        checkState(MimeTokenStream.T_BODY);
 
285
        checkState(MimeTokenStream.T_END_BODYPART);
 
286
        checkState(MimeTokenStream.T_START_BODYPART);
 
287
        checkState(MimeTokenStream.T_START_HEADER);
 
288
        checkState(MimeTokenStream.T_FIELD);
 
289
        checkState(MimeTokenStream.T_END_HEADER);
 
290
        checkState(MimeTokenStream.T_BODY);
 
291
        checkState(MimeTokenStream.T_END_BODYPART);
 
292
        checkState(MimeTokenStream.T_EPILOGUE);
 
293
        checkState(MimeTokenStream.T_END_MULTIPART);
 
294
        checkState(MimeTokenStream.T_END_MESSAGE);
 
295
        checkState(MimeTokenStream.T_END_OF_STREAM);
 
296
    }
 
297
    
 
298
    private void checkState(final int state) throws IOException, MimeException {
 
299
        assertEquals(MimeTokenStream.stateToString(state), MimeTokenStream.stateToString(parser.next()));
 
300
    }
 
301
}