/* * Copyright (c) 1997, 2018 Oracle and/or its affiliates. All rights reserved. * * This program and the accompanying materials are made available under the * terms of the Eclipse Public License v. 2.0, which is available at * http://www.eclipse.org/legal/epl-2.0. * * This Source Code may also be made available under the following Secondary * Licenses when the conditions for such availability set forth in the * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, * version 2 with the GNU Classpath Exception, which is available at * https://www.gnu.org/software/classpath/license.html. * * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 */ package com.sun.mail.mbox; import javax.mail.*; import javax.mail.internet.*; import javax.activation.*; import java.io.*; /** * This class represents a SunV3 BodyPart. * * @author Bill Shannon * @see javax.mail.Part * @see javax.mail.internet.MimePart * @see javax.mail.internet.MimeBodyPart */ public class SunV3BodyPart extends MimeBodyPart { /** * Constructs a SunV3BodyPart using the given header and * content bytes.

* * Used by providers. * * @param headers The header of this part * @param content bytes representing the body of this part. */ public SunV3BodyPart(InternetHeaders headers, byte[] content) throws MessagingException { super(headers, content); } /** * Return the size of the content of this BodyPart in bytes. * Return -1 if the size cannot be determined.

* * Note that this number may not be an exact measure of the * content size and may or may not account for any transfer * encoding of the content.

* * @return size in bytes */ public int getSize() throws MessagingException { String s = getHeader("X-Sun-Content-Length", null); try { return Integer.parseInt(s); } catch (NumberFormatException ex) { return -1; } } /** * Return the number of lines for the content of this Part. * Return -1 if this number cannot be determined.

* * Note that this number may not be an exact measure of the * content length and may or may not account for any transfer * encoding of the content. */ public int getLineCount() throws MessagingException { String s = getHeader("X-Sun-Content-Lines", null); try { return Integer.parseInt(s); } catch (NumberFormatException ex) { return -1; } } /* * This is just enough to get us going. * * For more complete transformation from V3 to MIME, refer to * sun_att.c from the Sun IMAP server code. */ static class MimeV3Map { String mime; String v3; MimeV3Map(String mime, String v3) { this.mime = mime; this.v3 = v3; } private static MimeV3Map[] mimeV3Table = new MimeV3Map[] { new MimeV3Map("text/plain", "text"), new MimeV3Map("text/plain", "default"), new MimeV3Map("multipart/x-sun-attachment", "X-sun-attachment"), new MimeV3Map("application/postscript", "postscript-file"), new MimeV3Map("image/gif", "gif-file") // audio-file // cshell-script }; // V3 Content-Type to MIME Content-Type static String toMime(String s) { for (int i = 0; i < mimeV3Table.length; i++) { if (mimeV3Table[i].v3.equalsIgnoreCase(s)) return mimeV3Table[i].mime; } return "application/x-" + s; } // MIME Content-Type to V3 Content-Type static String toV3(String s) { for (int i = 0; i < mimeV3Table.length; i++) { if (mimeV3Table[i].mime.equalsIgnoreCase(s)) return mimeV3Table[i].v3; } return s; } } /** * Returns the value of the RFC822 "Content-Type" header field. * This represents the content-type of the content of this * BodyPart. This value must not be null. If this field is * unavailable, "text/plain" should be returned.

* * This implementation uses getHeader(name) * to obtain the requisite header field. * * @return Content-Type of this BodyPart */ public String getContentType() throws MessagingException { String ct = getHeader("Content-Type", null); if (ct == null) ct = getHeader("X-Sun-Data-Type", null); if (ct == null) ct = "text/plain"; else if (ct.indexOf('/') < 0) ct = MimeV3Map.toMime(ct); return ct; } /** * Returns the value of the "Content-Transfer-Encoding" header * field. Returns null if the header is unavailable * or its value is absent.

* * This implementation uses getHeader(name) * to obtain the requisite header field. * * @see #headers */ public String getEncoding() throws MessagingException { String enc = super.getEncoding(); if (enc == null) enc = getHeader("X-Sun-Encoding-Info", null); return enc; } /** * Returns the "Content-Description" header field of this BodyPart. * This typically associates some descriptive information with * this part. Returns null if this field is unavailable or its * value is absent.

* * If the Content-Description field is encoded as per RFC 2047, * it is decoded and converted into Unicode. If the decoding or * conversion fails, the raw data is returned as-is

* * This implementation uses getHeader(name) * to obtain the requisite header field. * * @return content-description */ public String getDescription() throws MessagingException { String desc = super.getDescription(); if (desc == null) desc = getHeader("X-Sun-Data-Description", null); return desc; } /** * Set the "Content-Description" header field for this BodyPart. * If the description parameter is null, then any * existing "Content-Description" fields are removed.

* * If the description contains non US-ASCII characters, it will * be encoded using the platform's default charset. If the * description contains only US-ASCII characters, no encoding * is done and it is used as-is. * * @param description content-description * @exception IllegalWriteException if the underlying * implementation does not support modification * @exception IllegalStateException if this BodyPart is * obtained from a READ_ONLY folder. */ public void setDescription(String description) throws MessagingException { throw new MethodNotSupportedException("SunV3BodyPart not writable"); } /** * Set the "Content-Description" header field for this BodyPart. * If the description parameter is null, then any * existing "Content-Description" fields are removed.

* * If the description contains non US-ASCII characters, it will * be encoded using the specified charset. If the description * contains only US-ASCII characters, no encoding is done and * it is used as-is * * @param description Description * @param charset Charset for encoding * @exception IllegalWriteException if the underlying * implementation does not support modification * @exception IllegalStateException if this BodyPart is * obtained from a READ_ONLY folder. */ public void setDescription(String description, String charset) throws MessagingException { throw new MethodNotSupportedException("SunV3BodyPart not writable"); } /** * Get the filename associated with this BodyPart.

* * Returns the value of the "filename" parameter from the * "Content-Disposition" header field of this BodyPart. If its * not available, returns the value of the "name" parameter from * the "Content-Type" header field of this BodyPart. * Returns null if both are absent. * * @return filename */ public String getFileName() throws MessagingException { String name = super.getFileName(); if (name == null) name = getHeader("X-Sun-Data-Name", null); return name; } /** * Set the filename associated with this BodyPart, if possible.

* * Sets the "filename" parameter of the "Content-Disposition" * header field of this BodyPart. * * @exception IllegalWriteException if the underlying * implementation does not support modification * @exception IllegalStateException if this BodyPart is * obtained from a READ_ONLY folder. */ public void setFileName(String filename) throws MessagingException { throw new MethodNotSupportedException("SunV3BodyPart not writable"); } /** * This method provides the mechanism to set this BodyPart's content. * The given DataHandler object should wrap the actual content. * * @param dh The DataHandler for the content * @exception IllegalWriteException if the underlying * implementation does not support modification * @exception IllegalStateException if this BodyPart is * obtained from a READ_ONLY folder. */ public void setDataHandler(DataHandler dh) throws MessagingException { throw new MethodNotSupportedException("SunV3BodyPart not writable"); } /** * Output the BodyPart as a RFC822 format stream. * * @exception MessagingException * @exception IOException if an error occurs writing to the * stream or if an error is generated * by the javax.activation layer. * @see javax.activation.DataHandler#writeTo() */ public void writeTo(OutputStream os) throws IOException, MessagingException { throw new MethodNotSupportedException("SunV3BodyPart writeTo"); } /** * This is the method that has the 'smarts' to query the 'content' * and update the appropriate headers. Typical headers that get * set here are: Content-Type, Content-Encoding, boundary (for * multipart). Now, the tricky part here is when to actually * activate this method: * * - A Message being crafted by a mail-application will certainly * need to activate this method at some point to fill up its internal * headers. Typically this is triggered off by our writeTo() method. * * - A message read-in from a MessageStore will have obtained * all its headers from the store, and so does'nt need this. * However, if this message is editable and if any edits have * been made to either the content or message-structure, we might * need to resync our headers. Typically this is triggered off by * the Message.saveChanges() methods. */ protected void updateHeaders() throws MessagingException { throw new MethodNotSupportedException("SunV3BodyPart updateHeaders"); } }