Skip to content

Package: MSMessage$1FastByteArrayOutputStream

MSMessage$1FastByteArrayOutputStream

nameinstructionbranchcomplexitylinemethod
toByteArrayInputStream()
M: 9 C: 0
0%
M: 0 C: 0
100%
M: 1 C: 0
0%
M: 1 C: 0
0%
M: 1 C: 0
0%
{...}
M: 6 C: 0
0%
M: 0 C: 0
100%
M: 1 C: 0
0%
M: 1 C: 0
0%
M: 1 C: 0
0%

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 Distribution License v. 1.0, which is available at
6: * http://www.eclipse.org/org/documents/edl-v10.php.
7: *
8: * SPDX-License-Identifier: BSD-3-Clause
9: */
10:
11: package example.outlook;
12:
13: import jakarta.activation.DataHandler;
14: import jakarta.mail.MessagingException;
15: import jakarta.mail.Session;
16: import jakarta.mail.internet.MimeMessage;
17: import jakarta.mail.internet.MimePartDataSource;
18: import jakarta.mail.util.StreamProvider.EncoderTypes;
19:
20: import java.io.BufferedInputStream;
21: import java.io.ByteArrayInputStream;
22: import java.io.ByteArrayOutputStream;
23: import java.io.IOException;
24: import java.io.InputStream;
25:
26: /**
27: * This class models a UUEncoded Message sent from MS Outlook etc. <p>
28: *
29: * The message structure looks like this :=
30: * [text body] [uuencoded attachment]*
31: * <p>
32: * i.e., an optional text/plain main-body, followed by zero or more
33: * UUENCODE-ed attachments.
34: *
35: * @author John Mani
36: * @author Bill Shannon
37: * @see jakarta.mail.internet.MimeMessage
38: */
39: public class MSMessage extends MimeMessage {
40: private String type;
41:
42: /**
43: * Constructor that converts a MimeMessage object into a outlook.MSMessage.
44: *
45: * @throws MessagingException if the given MimeMessage
46: * is not a non-MIME MS message, or if an
47: * IOException occurs when accessing the given
48: * MimeMessage object
49: */
50: public MSMessage(Session session, MimeMessage msg)
51: throws MessagingException {
52: super(session);
53:
54: if (!isMSMessage(msg)) // sanity check
55: throw new MessagingException("Not an MS message");
56:
57: class FastByteArrayOutputStream extends ByteArrayOutputStream {
58: ByteArrayInputStream toByteArrayInputStream() {
59: return new ByteArrayInputStream(buf, 0, count);
60: }
61: }
62:
63: // extract the bytes of the given message
64: // ByteArrayOutputStream bos = new ByteArrayOutputStream();
65: FastByteArrayOutputStream bos = new FastByteArrayOutputStream();
66: try {
67: msg.writeTo(bos);
68: } catch (IOException ioex) {
69: throw new MessagingException("IOException", ioex);
70: } catch (Exception ex) {
71: throw new MessagingException("Exception", ex);
72: }
73: //parse(new ByteArrayInputStream(bos.toByteArray()));
74: parse(bos.toByteArrayInputStream());
75: }
76:
77: /**
78: * Constructor to create a outlook.MSMessage from the given InputStream.
79: */
80: public MSMessage(Session session, InputStream is)
81: throws MessagingException {
82: super(session); // setup headerstore etc
83: parse(is);
84: }
85:
86: // parse input stream
87: protected void parse(InputStream is) throws MessagingException {
88: // Create a buffered input stream for efficiency
89: if (!(is instanceof ByteArrayInputStream) &&
90: !(is instanceof BufferedInputStream))
91: is = new BufferedInputStream(is);
92:
93: // Load headerstore
94: headers.load(is);
95:
96: /*
97: * Load the content into a byte[].
98: * This byte[] is shared among the bodyparts.
99: */
100: try {
101: ByteArrayOutputStream bos = new ByteArrayOutputStream();
102: int b;
103: // XXX - room for performance improvement
104: while ((b = is.read()) != -1)
105: bos.write(b);
106: content = bos.toByteArray();
107: } catch (IOException ioex) {
108: throw new MessagingException("IOException", ioex);
109: }
110:
111: /*
112: * Check whether this is multipart.
113: */
114: boolean isMulti = false;
115: // check for presence of X-MS-Attachment header
116: String[] att = getHeader("X-MS-Attachment");
117: if (att != null && att.length > 0)
118: isMulti = true;
119: else {
120: /*
121: * Fall back to scanning the content.
122: * We scan the content until we find a sequence that looks
123: * like the start of a uuencoded block, i.e., "<newline>begin".
124: * If found, we claim that this is a multipart message.
125: */
126: for (int i = 0; i < content.length; i++) {
127: int b = content[i] & 0xff; // mask higher byte
128: if (b == '\r' || b == '\n') {
129: // start of a new line
130: if ((i + 5) < content.length) {
131: // can there be a "begin" now?
132: String s = toString(content, i + 1, i + 6);
133: if (s.equalsIgnoreCase("begin")) {
134: isMulti = true;
135: break;
136: }
137: }
138: }
139: }
140: }
141:
142: if (isMulti) {
143: type = "multipart/mixed";
144: dh = new DataHandler(new MSMultipartDataSource(this, content));
145: } else {
146: type = "text/plain"; // charset = ?
147: dh = new DataHandler(new MimePartDataSource(this));
148: }
149:
150: modified = false;
151: }
152:
153: /**
154: * Return content-type
155: */
156: public String getContentType() throws MessagingException {
157: return type;
158: }
159:
160: /**
161: * Return content-disposition
162: */
163: public String getDisposition() throws MessagingException {
164: return "inline";
165: }
166:
167: /**
168: * Return content-transfer-encoding
169: */
170: public String getEncoding() throws MessagingException {
171: return EncoderTypes.BIT7_ENCODER.getEncoder();
172: }
173:
174: /**
175: * Check whether the given MimeMessage object represents a
176: * non-MIME message sent by Outlook. Such a message will
177: * have no MIME-Version header, may have an X-Mailer header
178: * that includes the word "Microsoft", and will have at least
179: * one X-MS-Attachment header.
180: */
181: public static boolean isMSMessage(MimeMessage msg)
182: throws MessagingException {
183: // Check whether the MIME header is present
184: if (msg.getHeader("MIME-Version") != null)
185: // MIME-Version header present, should be a MIME message
186: return false;
187:
188: /*
189: * XXX - disabled X-Mailer check because many sample messages
190: * I saw didn't have an X-Mailer header at all.
191: */
192: if (false) {
193: // Check X-Mailer
194: String mailer = msg.getHeader("X-mailer", null);
195: if (mailer == null) // No X-mailer ?
196: return false; // Oh well !
197: if (!mailer.contains("Microsoft")) // Not MS stuff ?
198: return false;
199: }
200:
201: // Check X-MS-Attachment header
202: // XXX - not all such messages have this header
203: String[] att = msg.getHeader("X-MS-Attachment");
204: if (att == null || att.length == 0)
205: return false;
206:
207: return true;
208: }
209:
210: // convert given byte array of ASCII characters to string
211: static String toString(byte[] b, int start, int end) {
212: int size = end - start;
213: char[] theChars = new char[size];
214:
215: for (int i = 0, j = start; i < size; )
216: theChars[i++] = (char) b[j++];
217: return new String(theChars);
218: }
219: }