Package: SunV3Multipart
SunV3Multipart
name | instruction | branch | complexity | line | method | ||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
SunV3Multipart(DataSource) |
|
|
|
|
|
||||||||||||||||||||
getBodyPart(String) |
|
|
|
|
|
||||||||||||||||||||
parse() |
|
|
|
|
|
||||||||||||||||||||
setSubType(String) |
|
|
|
|
|
||||||||||||||||||||
updateHeaders() |
|
|
|
|
|
||||||||||||||||||||
writeTo(OutputStream) |
|
|
|
|
|
Coverage
1: /*
2: * Copyright (c) 1997, 2023 Oracle and/or its affiliates. All rights reserved.
3: *
4: * This program and the accompanying materials are made available under the
5: * terms of the Eclipse Public License v. 2.0, which is available at
6: * http://www.eclipse.org/legal/epl-2.0.
7: *
8: * This Source Code may also be made available under the following Secondary
9: * Licenses when the conditions for such availability set forth in the
10: * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
11: * version 2 with the GNU Classpath Exception, which is available at
12: * https://www.gnu.org/software/classpath/license.html.
13: *
14: * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
15: */
16:
17: package org.eclipse.angus.mail.mbox;
18:
19: import jakarta.mail.*;
20: import jakarta.mail.internet.*;
21: import jakarta.activation.*;
22:
23: import org.eclipse.angus.mail.util.LineInputStream;
24:
25: import java.io.*;
26: import java.nio.charset.StandardCharsets;
27:
28: /**
29: * The SunV3Multipart class is an implementation of the abstract Multipart
30: * class that uses SunV3 conventions for the multipart data. <p>
31: *
32: * @author Bill Shannon
33: */
34:
35: public class SunV3Multipart extends MimeMultipart {
36: private boolean parsing;
37:
38: /**
39: * Constructs a SunV3Multipart object and its bodyparts from the
40: * given DataSource. <p>
41: *
42: * @param        ds        DataSource, can be a MultipartDataSource
43: */
44: public SunV3Multipart(DataSource ds) throws MessagingException {
45:         super(ds);
46: }
47:
48: /**
49: * Set the subtype. Throws MethodNotSupportedException.
50: *
51: * @param        subtype                Subtype
52: */
53: public void setSubType(String subtype) throws MessagingException {
54:         throw new MethodNotSupportedException(
55:                 "can't change SunV3Multipart subtype");
56: }
57:
58: /**
59: * Get the BodyPart referred to by the given ContentID (CID).
60: * Throws MethodNotSupportException.
61: */
62: public synchronized BodyPart getBodyPart(String CID)
63:                         throws MessagingException {
64:         throw new MethodNotSupportedException(
65:                 "SunV3Multipart doesn't support Content-ID");
66: }
67:
68: /**
69: * Update headers. Throws MethodNotSupportException.
70: */
71: protected void updateHeaders() throws MessagingException {
72:         throw new MethodNotSupportedException("SunV3Multipart not writable");
73: }
74:
75: /**
76: * Iterates through all the parts and outputs each SunV3 part
77: * separated by a boundary.
78: */
79: public void writeTo(OutputStream os)
80:                                 throws IOException, MessagingException {
81:         throw new MethodNotSupportedException(
82:                 "SunV3Multipart writeTo not supported");
83: }
84:
85: private static final String boundary = "----------";
86:
87: /*
88: * Parse the contents of this multipart message and create the
89: * child body parts.
90: */
91: protected synchronized void parse() throws MessagingException {
92:         /*
93:          * If the data has already been parsed, or we're in the middle of
94:          * parsing it, there's nothing to do. The latter will occur when
95:          * we call addBodyPart, which will call parse again. We really
96:          * want to be able to call super.super.addBodyPart.
97:          */
98:•        if (parsed || parsing)
99:          return;
100:
101:         InputStream in = null;
102:
103:         try {
104:          in = ds.getInputStream();
105:•         if (!(in instanceof ByteArrayInputStream) &&
106:                 !(in instanceof BufferedInputStream))
107:                 in = new BufferedInputStream(in);
108:         } catch (IOException ex) {
109:          throw new MessagingException("No inputstream from datasource");
110:         } catch (RuntimeException ex) {
111:          throw new MessagingException("No inputstream from datasource");
112:         }
113:
114:         byte[] bndbytes = boundary.getBytes(StandardCharsets.ISO_8859_1);
115:         int bl = bndbytes.length;
116:
117:         String line;
118:         parsing = true;
119:         try {
120:          /*
121:          * Skip any kind of junk until we get to the first
122:          * boundary line.
123:          */
124:          LineInputStream lin = new LineInputStream(in);
125:•         while ((line = lin.readLine()) != null) {
126:•                if (line.trim().equals(boundary))
127:                  break;
128:          }
129:•         if (line == null)
130:                 throw new MessagingException("Missing start boundary");
131:
132:          /*
133:          * Read and process body parts until we see the
134:          * terminating boundary line (or EOF).
135:          */
136:          for (;;) {
137:                 /*
138:                  * Collect the headers for this body part.
139:                  */
140:                 InternetHeaders headers = new InternetHeaders(in);
141:
142:•                if (!in.markSupported())
143:                  throw new MessagingException("Stream doesn't support mark");
144:
145:                 ByteArrayOutputStream buf = new ByteArrayOutputStream();
146:                 int b;
147:
148:                 /*
149:                  * Read and save the content bytes in buf.
150:                  */
151:•                while ((b = in.read()) >= 0) {
152:•                 if (b == '\r' || b == '\n') {
153:                         /*
154:                          * Found the end of a line, check whether the
155:                          * next line is a boundary.
156:                          */
157:                         int i;
158:                         in.mark(bl + 4 + 1);        // "4" for possible "--\r\n"
159:•                        if (b == '\r' && in.read() != '\n') {
160:                          in.reset();
161:                          in.mark(bl + 4);
162:                         }
163:                         // read bytes, matching against the boundary
164:•                        for (i = 0; i < bl; i++)
165:•                         if (in.read() != bndbytes[i])
166:                                 break;
167:•                        if (i == bl) {
168:                          int b2 = in.read();
169:                          // check for end of line
170:•                         if (b2 == '\n')
171:                                 break;        // got it! break out of the while loop
172:•                         if (b2 == '\r') {
173:                                 in.mark(1);
174:•                                if (in.read() != '\n')
175:                                  in.reset();
176:                                 break;        // got it! break out of the while loop
177:                          }
178:                         }
179:                         // failed to match, reset and proceed normally
180:                         in.reset();
181:                  }
182:                  buf.write(b);
183:                 }
184:
185:                 /*
186:                  * Create a SunV3BodyPart to represent this body part.
187:                  */
188:                 SunV3BodyPart body =
189:                         new SunV3BodyPart(headers, buf.toByteArray());
190:                 addBodyPart(body);
191:•                if (b < 0)
192:                  break;
193:          }
194:         } catch (IOException e) {
195:          throw new MessagingException("IO Error");        // XXX
196:         } finally {
197:          parsing = false;
198:         }
199:
200:         parsed = true;
201: }
202: }