1052 lines
31 KiB
Java
1052 lines
31 KiB
Java
/*
|
|
* The contents of this file are subject to the Netscape Public
|
|
* License Version 1.1 (the "License"); you may not use this file
|
|
* except in compliance with the License. You may obtain a copy of
|
|
* the License at http://www.mozilla.org/NPL/
|
|
*
|
|
* Software distributed under the License is distributed on an "AS
|
|
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
|
* implied. See the License for the specific language governing
|
|
* rights and limitations under the License.
|
|
*
|
|
* The Original Code is the Netscape Messaging Access SDK Version 3.5 code,
|
|
* released on or about June 15, 1998. *
|
|
* The Initial Developer of the Original Code is Netscape Communications
|
|
* Corporation. Portions created by Netscape are
|
|
* Copyright (C) 1998 Netscape Communications Corporation. All
|
|
* Rights Reserved.
|
|
*
|
|
* Contributor(s): ______________________________________.
|
|
*/
|
|
|
|
/*
|
|
* Copyright (c) 1997 and 1998 Netscape Communications Corporation
|
|
* (http://home.netscape.com/misc/trademarks.html)
|
|
*/
|
|
|
|
|
|
package netscape.messaging.mime;
|
|
import java.io.*;
|
|
import java.lang.*;
|
|
import java.util.*;
|
|
import netscape.messaging.mime.MIMEParser;
|
|
|
|
/**
|
|
* The MIMEBasicPart class is a common class used for all Basic
|
|
* MIME BodyPart types:
|
|
* Text, Image, Audio, Video, and Application. It does not represent structured
|
|
* parts such as MIMEMessagePart and MIMEMultiPart.
|
|
* @author Prasad Yendluri
|
|
*/
|
|
public class MIMEBasicPart extends MIMEBodyPart implements Cloneable
|
|
{
|
|
|
|
/**
|
|
* Content (primary) type Text.
|
|
*/
|
|
public static final int TEXT = 0;
|
|
/**
|
|
* Content (primary) type Audio.
|
|
*/
|
|
public static final int AUDIO = 1;
|
|
/**
|
|
* Content (primary) type Image.
|
|
*/
|
|
public static final int IMAGE = 2;
|
|
/**
|
|
* Content (primary) type Video.
|
|
*/
|
|
public static final int VIDEO = 3;
|
|
/**
|
|
* Content (primary) type Application.
|
|
*/
|
|
public static final int APPLICATION = 4;
|
|
|
|
|
|
|
|
//===========================================================================
|
|
//
|
|
// Internal members not visible at the API
|
|
//
|
|
//===========================================================================
|
|
|
|
// Encodings
|
|
private static final int BASE64 = MIMEBodyPart.BASE64;
|
|
private static final int QP = MIMEBodyPart.QP;
|
|
private static final int BINARY = MIMEBodyPart.BINARY;
|
|
private static final int E7BIT = MIMEBodyPart.E7BIT;
|
|
private static final int E8BIT = MIMEBodyPart.E8BIT;
|
|
private static final int EIGNORE = 99;
|
|
public static final int UNINITIALIZED = -1;
|
|
private static final int MAXDATABUFSIZE = 1111111;
|
|
|
|
private static final String[] m_stringContentTypes = { "Text", "Audio", "Image",
|
|
"Video", "Application" };
|
|
private static final String[] m_stringEncoding = { "base64", "quoted-printable",
|
|
"binary", "7bit", "8bit" };
|
|
private static final String[] m_stringDisposition = { "Attachment", "Inline"};
|
|
|
|
private int m_contentType;
|
|
private String m_contentMD5;
|
|
private int m_contentTransferEncoding;
|
|
private int m_parsedPart;
|
|
|
|
// The key to the hashTable below is the name of the header field.
|
|
// To make sure we handle case differences in the header-name, we
|
|
// must convert the header name to lower-case always prior to the
|
|
// hash look-up. The entries added to the hash table are objects of
|
|
// class Header.
|
|
private Hashtable m_mimeHeadersTable;
|
|
|
|
// Buffer to hold body-data (not encoded). We always store un-encoded.
|
|
// Buffer stores data as parsed from input message or as given by the user
|
|
// when constructing this bodyPart.
|
|
private ByteBuffer m_databuf;
|
|
private byte m_readbuf[];
|
|
private InputStream m_dataStream;
|
|
|
|
private int m_nStartMessageDataIndex;
|
|
private int m_nEndMessageDataIndex;
|
|
private int m_nMessageDataLen;
|
|
private boolean m_bDecodedData;
|
|
protected boolean m_endData;
|
|
protected MIMEMultiPart m_parentContainer;
|
|
|
|
|
|
//===========================================================================
|
|
//
|
|
// CONSTRUCTORS
|
|
//
|
|
//===========================================================================
|
|
|
|
/**
|
|
* Constructs a MIMEBasicPart object with the given content-type.
|
|
* @param contentType Content type. Values:
|
|
* TEXT, AUDIO, IMAGE, VIDEO, APPLICATION.
|
|
* @see MIMEBasicPart#TEXT
|
|
* @see MIMEBasicPart#AUDIO
|
|
* @see MIMEBasicPart#IMAGE
|
|
* @see MIMEBasicPart#VIDEO
|
|
* @see MIMEBasicPart#APPLICATION
|
|
* @exception MIMEException If ContentType passed is invalid.
|
|
*/
|
|
public MIMEBasicPart (int contentType) throws MIMEException
|
|
{
|
|
switch (contentType)
|
|
{
|
|
case MIMEBasicPart.TEXT:
|
|
m_contentType = TEXT;
|
|
break;
|
|
case MIMEBasicPart.AUDIO:
|
|
m_contentType = AUDIO;
|
|
break;
|
|
case MIMEBasicPart.IMAGE:
|
|
m_contentType = IMAGE;
|
|
break;
|
|
case MIMEBasicPart.VIDEO:
|
|
m_contentType = VIDEO;
|
|
break;
|
|
case MIMEBasicPart.APPLICATION:
|
|
m_contentType = APPLICATION;
|
|
break;
|
|
default:
|
|
throw new MIMEException ("Invalid content-type: " + contentType);
|
|
}
|
|
|
|
m_parsedPart = 0;
|
|
m_contentDisposition = UNINITIALIZED;
|
|
m_contentTransferEncoding = UNINITIALIZED;
|
|
m_mimeHeadersTable = new Hashtable();
|
|
m_databuf = null;
|
|
m_readbuf = null;
|
|
m_dataStream = null;
|
|
|
|
m_nStartMessageDataIndex = UNINITIALIZED;
|
|
m_nEndMessageDataIndex = UNINITIALIZED;
|
|
m_nMessageDataLen = 0;
|
|
m_UserObject = null;
|
|
m_bDecodedData = false;
|
|
}
|
|
|
|
|
|
/**
|
|
* Default constructor.
|
|
* Constructs a MIMEBasicPart object with MIMEBasicPart#TEXT content-type.
|
|
*/
|
|
public MIMEBasicPart() throws MIMEException
|
|
{
|
|
this (MIMEBasicPart.TEXT);
|
|
}
|
|
|
|
|
|
//===========================================================================
|
|
//
|
|
// Methods overriden from MIMEBodyPart
|
|
//
|
|
//===========================================================================
|
|
|
|
/**
|
|
* Returns Content-Type of this MIME Part.
|
|
* @see MIMEBodyPart#getContentType
|
|
*/
|
|
public String getContentType ()
|
|
{
|
|
String ct = new String (m_stringContentTypes [m_contentType]);
|
|
return (ct);
|
|
}
|
|
|
|
|
|
//===========================================================================
|
|
//
|
|
// Methods Specific to this Class alone.
|
|
//
|
|
//===========================================================================
|
|
|
|
/**
|
|
* Returns Content-MD5 of this MIME Part or NULL if Content-MD5 is not present.
|
|
* @see #setContentMD5
|
|
*/
|
|
public String getContentMD5 ()
|
|
{
|
|
if (m_contentMD5 == null)
|
|
return (null);
|
|
|
|
return (m_contentMD5);
|
|
}
|
|
|
|
/**
|
|
* Sets Content-MD5 of this MIME Part.
|
|
* @param cid String to use as Content-ID.
|
|
* @see #getContentMD5
|
|
*/
|
|
public void setContentMD5 (String md5)
|
|
{
|
|
m_contentMD5 = md5;
|
|
}
|
|
|
|
/**
|
|
* Returns an InputStream to this Part's Data after decoding any
|
|
* transfer encoding.
|
|
* @exception IOException If an IO error occurs.
|
|
* @exception MIMEException If the BodyData is not present.
|
|
* or an error is detected during decoding.
|
|
* @see #setBodyData
|
|
*/
|
|
public InputStream getBodyData () throws IOException, MIMEException
|
|
{
|
|
if (m_databuf == null && m_dataStream == null)
|
|
{
|
|
throw new MIMEException ("getBodyData(): No BodyData present." );
|
|
}
|
|
|
|
if (m_databuf != null)
|
|
{
|
|
ByteArrayInputStream ins = new ByteArrayInputStream (m_databuf.getBytes());
|
|
return (ins);
|
|
}
|
|
|
|
if (m_dataStream.markSupported())
|
|
m_dataStream.reset();
|
|
|
|
return (m_dataStream);
|
|
}
|
|
|
|
/**
|
|
* Returns an ByteBuffer object, return null if no data
|
|
* carsonl, used by parser
|
|
*/
|
|
protected ByteBuffer getDataBuf() { return m_databuf; }
|
|
|
|
|
|
|
|
/**
|
|
* Sets BodyData of this MIME Part.
|
|
* @param is Stream to read input data from. This data must be un-encoded raw data.
|
|
* @exception MIMEException If already set (or) if is parameter is null.
|
|
* @exception IOException If an IO error occurs.
|
|
* @see #getDataBuf
|
|
*/
|
|
public void setBodyData (InputStream is) throws MIMEException, IOException
|
|
{
|
|
if (m_databuf != null && m_dataStream != null)
|
|
{
|
|
throw new MIMEException ("setBodyData(): BodyData already set." );
|
|
}
|
|
|
|
if (is == null)
|
|
{
|
|
throw new MIMEException ("setBodyData(): null inputStream");
|
|
}
|
|
|
|
setMessageDataLen( is.available() );
|
|
|
|
if (m_nMessageDataLen <= 0)
|
|
{
|
|
m_nMessageDataLen = 0;
|
|
throw new MIMEException ("setBodyData(): no data in inputStream");
|
|
}
|
|
|
|
if (m_nMessageDataLen > MAXDATABUFSIZE)
|
|
{
|
|
m_dataStream = is;
|
|
if (is.markSupported())
|
|
is.mark (2*m_nMessageDataLen);
|
|
}
|
|
else
|
|
{
|
|
ByteBuffer l_inbuf = new ByteBuffer (DATABUFSZ);
|
|
int l_read = is.read (l_inbuf.buffer, 0, DATABUFSZ);
|
|
|
|
if (l_read > 0)
|
|
{
|
|
m_databuf = new ByteBuffer(DATABUFSZ); // initial size
|
|
}
|
|
else
|
|
{
|
|
throw new MIMEException ("setBodyData(): InputStream Empty.");
|
|
}
|
|
|
|
while (l_read > 0)
|
|
{
|
|
l_inbuf.hi = l_read;
|
|
m_databuf.append (l_inbuf);
|
|
l_read = is.read (l_inbuf.buffer, 0, DATABUFSZ);
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Sets BodyData of this MIME Part.
|
|
* @param s Source string for input data. Must be un-encoded raw data.
|
|
* @exception MIMEException If already set or if is parameter is null.
|
|
*/
|
|
public void setBodyData (String s) throws MIMEException
|
|
{
|
|
if (m_databuf != null && m_dataStream != null)
|
|
{
|
|
throw new MIMEException ("setBodyData(): BodyData already set." );
|
|
}
|
|
|
|
if ( s != null )
|
|
{
|
|
m_databuf = new ByteBuffer( s.length() );
|
|
m_databuf.append( s.getBytes() );
|
|
setMessageDataLen( s.length() );
|
|
}
|
|
}
|
|
|
|
// non clone version
|
|
// carsonl. Not Exposed at API
|
|
protected void setBodyData( ByteBuffer s ) throws MIMEException
|
|
{
|
|
if (m_databuf != null && m_dataStream != null)
|
|
{
|
|
throw new MIMEException ("setBodyData(): BodyData already set." );
|
|
}
|
|
|
|
if ( s != null )
|
|
m_databuf = s;
|
|
}
|
|
|
|
/**
|
|
* Sets BodyData of this MIME Part.
|
|
* Saves a reference to the passed byte buffer.
|
|
* Does not copy the data.
|
|
* @param s un-encoded raw data.
|
|
* @exception MIMEException If already set or if s parameter is null.
|
|
*/
|
|
public void setBodyData( byte s[] ) throws MIMEException
|
|
{
|
|
if (m_databuf != null && m_dataStream != null)
|
|
{
|
|
throw new MIMEException ("setBodyData(): BodyData already set.");
|
|
}
|
|
|
|
if ( s != null )
|
|
{
|
|
m_databuf = new ByteBuffer( s );
|
|
setMessageDataLen( s.length );
|
|
}
|
|
}
|
|
|
|
|
|
/**
|
|
* Deletes BodyData of this MIME Part.
|
|
* If no BodyData is present, this method has no effect.
|
|
*/
|
|
public void deleteBodyData ()
|
|
{
|
|
m_databuf = null;
|
|
m_dataStream = null;
|
|
m_nMessageDataLen = 0;
|
|
}
|
|
|
|
/**
|
|
* Outputs a byte-stream for this part with its MIME part headers and encoded
|
|
* body data.
|
|
* @param fullfilename Filename including full path of where to write the byte-stream.
|
|
* @exception IOException If an IO error occurs.
|
|
* @exception MIMEException If any required fields in the bodyPart are not set-up.
|
|
*/
|
|
public void putByteStream (String fullfilename) throws IOException, MIMEException
|
|
{
|
|
FileOutputStream fos;
|
|
|
|
fos = new FileOutputStream (fullfilename);
|
|
|
|
putByteStream (fos);
|
|
}
|
|
|
|
/**
|
|
* Outputs a byte-stream for this part with its MIME part headers and encoded
|
|
* body data.
|
|
* @param os OutputStream to write to.
|
|
* @exception IOException If an IO error occurs.
|
|
* @exception MIMEException If any required fields in the bodyPart are not set-up.
|
|
*/
|
|
public void putByteStream (OutputStream os) throws IOException, MIMEException
|
|
{
|
|
if (m_databuf == null && m_dataStream == null)
|
|
{
|
|
throw new MIMEException ("MIMEBasicPart.putByteStream(). No bodyData!");
|
|
}
|
|
|
|
// Write out the headers first
|
|
StringBuffer l_hdrbuf = new StringBuffer (HDRBUFSZ);
|
|
byte[] l_bytebuf;
|
|
|
|
// Headers in member variables
|
|
|
|
// content-type
|
|
switch (m_contentType)
|
|
{
|
|
case TEXT:
|
|
l_hdrbuf.append ("Content-Type: text/");
|
|
|
|
if (m_contentSubType != null)
|
|
l_hdrbuf.append (m_contentSubType);
|
|
else
|
|
l_hdrbuf.append ("plain");
|
|
|
|
if (m_contentTypeParams != null && m_contentTypeParams.length() > 0 )
|
|
{
|
|
l_hdrbuf.append ("; ");
|
|
l_hdrbuf.append (m_contentTypeParams);
|
|
l_hdrbuf.append ("\r\n");
|
|
}
|
|
else
|
|
{
|
|
// l_hdrbuf.append ("; ");
|
|
// l_hdrbuf.append ("charset=us-ascii\r\n");
|
|
l_hdrbuf.append ("\r\n");
|
|
}
|
|
break;
|
|
case AUDIO:
|
|
l_hdrbuf.append ("Content-Type: audio/");
|
|
|
|
if (m_contentSubType != null)
|
|
l_hdrbuf.append (m_contentSubType);
|
|
else
|
|
throw new MIMEException ("putByteStream: No content-subtype." );
|
|
//l_hdrbuf.append ("basic");
|
|
|
|
if (m_contentTypeParams != null && m_contentTypeParams.length() > 0 )
|
|
{
|
|
l_hdrbuf.append ("; ");
|
|
l_hdrbuf.append (m_contentTypeParams);
|
|
l_hdrbuf.append ("\r\n");
|
|
}
|
|
else
|
|
l_hdrbuf.append ("\r\n");
|
|
break;
|
|
case IMAGE:
|
|
l_hdrbuf.append ("Content-Type: image/");
|
|
|
|
if (m_contentSubType != null)
|
|
l_hdrbuf.append (m_contentSubType);
|
|
else
|
|
throw new MIMEException ("putByteStream: No content-subtype.");
|
|
//l_hdrbuf.append ("jpeg");
|
|
|
|
if (m_contentTypeParams != null && m_contentTypeParams.length() > 0 )
|
|
{
|
|
l_hdrbuf.append ("; ");
|
|
l_hdrbuf.append (m_contentTypeParams);
|
|
l_hdrbuf.append ("\r\n");
|
|
}
|
|
else
|
|
l_hdrbuf.append ("\r\n");
|
|
break;
|
|
case VIDEO:
|
|
l_hdrbuf.append ("Content-Type: video/");
|
|
if (m_contentSubType != null)
|
|
l_hdrbuf.append (m_contentSubType);
|
|
else
|
|
throw new MIMEException ("putByteStream: No content-subtype.");
|
|
//l_hdrbuf.append ("mpeg");
|
|
|
|
if (m_contentTypeParams != null && m_contentTypeParams.length() > 0 )
|
|
{
|
|
l_hdrbuf.append ("; ");
|
|
l_hdrbuf.append (m_contentTypeParams);
|
|
l_hdrbuf.append ("\r\n");
|
|
}
|
|
else
|
|
l_hdrbuf.append ("\r\n");
|
|
break;
|
|
case APPLICATION:
|
|
l_hdrbuf.append ("Content-Type: application/");
|
|
if (m_contentSubType != null)
|
|
l_hdrbuf.append (m_contentSubType);
|
|
else
|
|
l_hdrbuf.append ("octet-stream");
|
|
|
|
if (m_contentTypeParams != null && m_contentTypeParams.length() > 0 )
|
|
{
|
|
l_hdrbuf.append ("; ");
|
|
l_hdrbuf.append (m_contentTypeParams);
|
|
l_hdrbuf.append ("\r\n");
|
|
}
|
|
else
|
|
l_hdrbuf.append ("\r\n");
|
|
break;
|
|
default:
|
|
throw new MIMEException ("Invalid content-type: " + m_contentType);
|
|
}
|
|
|
|
// write the header out to os
|
|
try
|
|
{
|
|
//l_bytebuf = l_hdrbuf.toString().getBytes("iso-8859-1");
|
|
l_bytebuf = MIMEHelper.unicodeToASCII (l_hdrbuf.toString());
|
|
os.write (l_bytebuf);
|
|
}
|
|
catch (Exception e)
|
|
{
|
|
throw new MIMEException ("Content-Type: " + e.getMessage());
|
|
}
|
|
|
|
// contentID
|
|
if (m_contentID != null)
|
|
{
|
|
l_hdrbuf.setLength (0);
|
|
l_hdrbuf.append ("Content-ID: " + m_contentID);
|
|
l_hdrbuf.append ("\r\n");
|
|
|
|
try
|
|
{
|
|
//l_bytebuf = l_hdrbuf.toString().getBytes("iso-8859-1");
|
|
l_bytebuf = MIMEHelper.unicodeToASCII (l_hdrbuf.toString());
|
|
os.write (l_bytebuf);
|
|
}
|
|
catch (Exception e)
|
|
{
|
|
throw new MIMEException ("Content-ID: " + e.getMessage());
|
|
}
|
|
}
|
|
|
|
// contentMD5
|
|
if (m_contentMD5 != null)
|
|
{
|
|
l_hdrbuf.setLength (0);
|
|
l_hdrbuf.append ("Content-MD5: " + m_contentMD5);
|
|
l_hdrbuf.append ("\r\n");
|
|
|
|
try
|
|
{
|
|
//l_bytebuf = l_hdrbuf.toString().getBytes("iso-8859-1");
|
|
l_bytebuf = MIMEHelper.unicodeToASCII (l_hdrbuf.toString());
|
|
os.write (l_bytebuf);
|
|
}
|
|
catch (Exception e)
|
|
{
|
|
throw new MIMEException ("Content-MD5: " + e.getMessage());
|
|
}
|
|
}
|
|
|
|
// contentDisposition
|
|
if (m_contentDisposition != UNINITIALIZED)
|
|
{
|
|
l_hdrbuf.setLength (0);
|
|
l_hdrbuf.append ("Content-Disposition: " +
|
|
m_stringDisposition [m_contentDisposition]);
|
|
|
|
if (m_contentDispParams != null)
|
|
{
|
|
l_hdrbuf.append ("; ");
|
|
l_hdrbuf.append (m_contentDispParams);
|
|
}
|
|
|
|
l_hdrbuf.append ("\r\n");
|
|
|
|
try
|
|
{
|
|
//l_bytebuf = l_hdrbuf.toString().getBytes("iso-8859-1");
|
|
l_bytebuf = MIMEHelper.unicodeToASCII (l_hdrbuf.toString());
|
|
os.write (l_bytebuf);
|
|
}
|
|
catch (Exception e)
|
|
{
|
|
throw new MIMEException ("Content-Disposition: " + e.getMessage());
|
|
}
|
|
}
|
|
|
|
// contentDescription
|
|
if (m_contentDescription != null)
|
|
{
|
|
l_hdrbuf.setLength (0);
|
|
l_hdrbuf.append ("Content-Description: " + m_contentDescription);
|
|
l_hdrbuf.append ("\r\n");
|
|
|
|
try
|
|
{
|
|
//l_bytebuf = l_hdrbuf.toString().getBytes("iso-8859-1");
|
|
l_bytebuf = MIMEHelper.unicodeToASCII (l_hdrbuf.toString());
|
|
os.write (l_bytebuf);
|
|
}
|
|
catch (Exception e)
|
|
{
|
|
throw new MIMEException ("Content-Description: " + e.getMessage());
|
|
}
|
|
}
|
|
|
|
// Content-transfer-encoding
|
|
// if (m_contentTransferEncoding == UNINITIALIZED)
|
|
// {
|
|
// if ((m_contentType == TEXT) && (m_contentTypeParams != null) && m_contentTypeParams.length() > 0)
|
|
// {
|
|
// String l_params = m_contentTypeParams.toLowerCase();
|
|
// int idx = l_params.indexOf ("charset=us-ascii");
|
|
// if (idx >= 0)
|
|
// m_contentTransferEncoding = E7BIT;
|
|
// else
|
|
// //m_contentTransferEncoding = BASE64;
|
|
// //m_contentTransferEncoding = E8BIT;
|
|
// m_contentTransferEncoding = EIGNORE;
|
|
//
|
|
// }
|
|
// else
|
|
// m_contentTransferEncoding = E7BIT;
|
|
// }
|
|
|
|
if (m_contentTransferEncoding != EIGNORE && m_contentTransferEncoding != UNINITIALIZED)
|
|
{
|
|
l_hdrbuf.setLength (0);
|
|
l_hdrbuf.append ("Content-Transfer-Encoding: " +
|
|
m_stringEncoding [m_contentTransferEncoding]);
|
|
l_hdrbuf.append ("\r\n");
|
|
|
|
try
|
|
{
|
|
// l_bytebuf = l_hdrbuf.toString().getBytes("iso-8859-1");
|
|
l_bytebuf = MIMEHelper.unicodeToASCII (l_hdrbuf.toString());
|
|
os.write (l_bytebuf);
|
|
}
|
|
catch (Exception e)
|
|
{
|
|
throw new MIMEException ("Content-Transfer-Encoding: " + e.getMessage());
|
|
}
|
|
}
|
|
|
|
// Do all the other headers
|
|
Header[] hdrs = getAllHeaders ();
|
|
if (hdrs != null)
|
|
for (int i = 0, len = hdrs.length; i < len; i++)
|
|
{
|
|
try
|
|
{
|
|
l_bytebuf = MIMEHelper.unicodeToASCII (hdrs[i].getLine());
|
|
os.write (l_bytebuf);
|
|
}
|
|
catch (Exception e)
|
|
{
|
|
throw new MIMEException (hdrs[i].getLine() + "> " + e.getMessage());
|
|
}
|
|
}
|
|
|
|
// blank-line after headers
|
|
//l_bytebuf = new String("\r\n").getBytes("iso-8859-1");
|
|
//os.write (LF);
|
|
os.write (CRLF);
|
|
|
|
int encoding = m_contentTransferEncoding;
|
|
|
|
if (encoding == UNINITIALIZED || encoding == EIGNORE)
|
|
encoding = E7BIT;
|
|
|
|
// Write out the bodydata encoding if needed.
|
|
switch (encoding) // we know it is not UNINITIALIZED
|
|
{
|
|
case BASE64:
|
|
if (m_dataStream == null)
|
|
{
|
|
ByteArrayInputStream isb =
|
|
new ByteArrayInputStream (m_databuf.getBytes());
|
|
MIMEHelper.encodeBase64 (isb, os);
|
|
}
|
|
else
|
|
{
|
|
if (m_dataStream.markSupported())
|
|
m_dataStream.reset();
|
|
MIMEHelper.encodeBase64 (m_dataStream, os);
|
|
}
|
|
break;
|
|
|
|
case QP:
|
|
if (m_dataStream == null)
|
|
{
|
|
ByteArrayInputStream isq =
|
|
new ByteArrayInputStream (m_databuf.getBytes());
|
|
MIMEHelper.encodeQP (isq, os);
|
|
}
|
|
else
|
|
{
|
|
if (m_dataStream.markSupported())
|
|
m_dataStream.reset();
|
|
MIMEHelper.encodeQP (m_dataStream, os);
|
|
}
|
|
break;
|
|
|
|
case BINARY:
|
|
case E7BIT:
|
|
case E8BIT:
|
|
case EIGNORE:
|
|
if (m_dataStream == null)
|
|
{
|
|
os.write (m_databuf.getBytes());
|
|
}
|
|
else
|
|
{
|
|
if (m_dataStream.markSupported())
|
|
m_dataStream.reset();
|
|
|
|
if (m_readbuf == null)
|
|
m_readbuf = new byte [DATABUFSZ];
|
|
|
|
int l_read = m_dataStream.read (m_readbuf, 0, DATABUFSZ);
|
|
|
|
while (l_read > 0)
|
|
{
|
|
os.write (m_readbuf, 0, l_read);
|
|
l_read = m_dataStream.read (m_readbuf, 0, DATABUFSZ);
|
|
}
|
|
}
|
|
break;
|
|
|
|
default:
|
|
throw new MIMEException ("Invalid Content Transfer Encoding : "
|
|
+ m_contentTransferEncoding);
|
|
} // switch
|
|
|
|
//os.write (CRLF);
|
|
|
|
} // putByteStream()
|
|
|
|
/**
|
|
* Returns the size of this Part's BodyData.
|
|
* @return Size of BodyData or -1 if this part does not have bodyData.
|
|
*/
|
|
public int getSize ()
|
|
{
|
|
if (m_databuf != null)
|
|
{
|
|
return (m_databuf.size());
|
|
}
|
|
else if (m_dataStream != null)
|
|
{
|
|
return (m_nMessageDataLen);
|
|
}
|
|
|
|
return (-1);
|
|
}
|
|
|
|
/**
|
|
* Sets Content-Transfer-Encoding of this MIME Part.
|
|
* @param encoding Value that represents the encoding.
|
|
* @see MIMEBodyPart#BASE64
|
|
* @see MIMEBodyPart#QP
|
|
* @see MIMEBodyPart#BINARY
|
|
* @see MIMEBodyPart#E7BIT
|
|
* @see MIMEBodyPart#E8BIT
|
|
* @exception MIMEException If encoding is invalid.
|
|
*/
|
|
public void setContentEncoding (int encoding) throws MIMEException
|
|
{
|
|
switch (encoding)
|
|
{
|
|
case BASE64:
|
|
case QP:
|
|
case BINARY:
|
|
case E7BIT:
|
|
case E8BIT:
|
|
m_contentTransferEncoding = encoding;
|
|
break;
|
|
default:
|
|
throw new MIMEException ("Invalid Content Transfer Encoding : " + encoding);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Returns value of Content-Transfer-Encoding of this MIME Part. -1 if none present.
|
|
* @see MIMEBodyPart#BASE64
|
|
* @see MIMEBodyPart#QP
|
|
* @see MIMEBodyPart#BINARY
|
|
* @see MIMEBodyPart#E7BIT
|
|
* @see MIMEBodyPart#E8BIT
|
|
*/
|
|
public int getContentEncoding ()
|
|
{
|
|
if (m_contentTransferEncoding == UNINITIALIZED || m_contentTransferEncoding == EIGNORE)
|
|
return (-1);
|
|
|
|
return (m_contentTransferEncoding);
|
|
}
|
|
|
|
/**
|
|
* Sets a header of this body-part given name and value.
|
|
* To be used to set any header that is not explicitly supported with a
|
|
* set method, such as X-headers. Multiple invocations on the same header
|
|
* replace the old value.
|
|
* @param name Name of the header field. Should not include ':'
|
|
* @param value Value of the header field to be added.
|
|
* @exception MIMEException If either of name or value is NULL.
|
|
*/
|
|
public void setHeader (String name, String value) throws MIMEException
|
|
{
|
|
if ((name == null) || (value == null))
|
|
throw new MIMEException ("Invalid NULL Header name or value");
|
|
|
|
if ( name.indexOf (':') > -1)
|
|
throw new MIMEException ("Invalid ':' in Header name");
|
|
|
|
// Check if the header is one of those they need to specify with other methods
|
|
String rslt = isOKtoset (name);
|
|
if (rslt != null)
|
|
throw new MIMEException ("Invalid setHeader(). Use method: " + rslt);
|
|
|
|
String l_hashKey = name.toLowerCase();
|
|
Header l_hdr = new Header (name, value);
|
|
m_mimeHeadersTable.put (l_hashKey, l_hdr);
|
|
}
|
|
|
|
/**
|
|
* Appends the value to an existing header. Creates new header if one does
|
|
* not exist already.
|
|
* @param name Name of the header field.
|
|
* @param value Value of the header field to be added.
|
|
* @exception MIMEException If either name or value are NULL
|
|
*/
|
|
public void addHeader (String name, String value) throws MIMEException
|
|
{
|
|
if ((name == null) || (value == null))
|
|
throw new MIMEException ("Invalid NULL Header name or value");
|
|
|
|
String l_hashKey = name.toLowerCase();
|
|
|
|
Header l_hdr = (Header) m_mimeHeadersTable.get (l_hashKey);
|
|
|
|
if (l_hdr == null)
|
|
setHeader (name, value);
|
|
else
|
|
{
|
|
StringBuffer l_oldvalue = new StringBuffer (l_hdr.getValue());
|
|
l_oldvalue.append (value);
|
|
Header l_newhdr = new Header (name, l_oldvalue.toString());
|
|
m_mimeHeadersTable.put (l_hashKey, l_newhdr);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Returns the value of the requested header.
|
|
* Returns NULL if the header is not present.
|
|
* @param name Name of the header field.
|
|
* @exception MIMEException If name passed is a NULL.
|
|
*/
|
|
public String getHeader (String name) throws MIMEException
|
|
{
|
|
if (name == null)
|
|
throw new MIMEException ("Invalid NULL Header name");
|
|
|
|
String l_hashKey = name.toLowerCase();
|
|
Header l_hdr = (Header) m_mimeHeadersTable.get (l_hashKey);
|
|
|
|
if (l_hdr != null)
|
|
return (l_hdr.getValue());
|
|
else
|
|
return (null);
|
|
}
|
|
|
|
/**
|
|
* Deletes the requested header from this Part.
|
|
* @param name Name of the header field.
|
|
* @exception MIMEException if name is NULL.
|
|
*/
|
|
public void deleteHeader (String name) throws MIMEException
|
|
{
|
|
if (name == null)
|
|
throw new MIMEException ("Invalid NULL Header name");
|
|
|
|
String l_hashKey = name.toLowerCase();
|
|
m_mimeHeadersTable.remove (l_hashKey);
|
|
}
|
|
|
|
/**
|
|
* Returns all the headers in this Part as an array of Header objects.
|
|
* @exception MIMEException If no headers exist.
|
|
*/
|
|
public Header[] getAllHeaders () throws MIMEException
|
|
{
|
|
int l_numElements = m_mimeHeadersTable.size();
|
|
int i = 0;
|
|
|
|
if (l_numElements <= 0)
|
|
return (null);
|
|
|
|
Header[] hdrs = new Header [l_numElements];
|
|
Enumeration he = m_mimeHeadersTable.elements();
|
|
|
|
while (he.hasMoreElements())
|
|
{
|
|
hdrs[i++] = (Header) he.nextElement();
|
|
}
|
|
|
|
return (hdrs);
|
|
}
|
|
|
|
/**
|
|
* Checks if it is OK to set the header with the setHeader().
|
|
* @return null if it is OK to set. Name of the method to use if it is NOT ok.
|
|
*/
|
|
private String isOKtoset (String name)
|
|
{
|
|
if (name.equalsIgnoreCase ("Content-Type"))
|
|
return ("setContentType()");
|
|
|
|
if (name.equalsIgnoreCase ("Content-ID"))
|
|
return ("setContentID()");
|
|
|
|
if (name.equalsIgnoreCase ("Content-MD5"))
|
|
return ("setContentMD5()");
|
|
|
|
if (name.equalsIgnoreCase ("Content-Disposition"))
|
|
return ("setContentDisposition()");
|
|
|
|
if (name.equalsIgnoreCase ("Content-Description"))
|
|
return ("setContentDescription()");
|
|
|
|
if (name.equalsIgnoreCase ("Content-Transfer-Encoding"))
|
|
return ("setContentEncoding()");
|
|
|
|
return (null);
|
|
|
|
} // end isOKtoset ()
|
|
|
|
private ByteBuffer getStreamData (InputStream is)
|
|
{
|
|
ByteBuffer l_retbuf, l_readbuf = new ByteBuffer (DATABUFSZ);
|
|
|
|
try
|
|
{
|
|
if (m_dataStream.markSupported())
|
|
m_dataStream.reset();
|
|
int l_read = is.read (l_readbuf.buffer, 0, DATABUFSZ);
|
|
|
|
if (l_read > 0)
|
|
{
|
|
l_retbuf = new ByteBuffer(DATABUFSZ); // initial size
|
|
}
|
|
else
|
|
return null;
|
|
|
|
while (l_read > 0)
|
|
{
|
|
l_readbuf.hi = l_read;
|
|
l_retbuf.append (l_readbuf);
|
|
l_read = is.read (l_readbuf.buffer, 0, DATABUFSZ);
|
|
}
|
|
|
|
if (m_dataStream.markSupported())
|
|
m_dataStream.reset();
|
|
return l_retbuf;
|
|
}
|
|
catch (IOException e)
|
|
{
|
|
return null;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Clones an instance of this MIMEBasicPart object.
|
|
* @exception CloneNotSupportedException If thrown by constituent components.
|
|
*/
|
|
public Object clone () throws CloneNotSupportedException
|
|
{
|
|
// Do the bit-wise copy first.
|
|
MIMEBasicPart l_theClone = (MIMEBasicPart) super.clone();
|
|
|
|
// Take care of all other "reference"s.
|
|
if (m_mimeHeadersTable != null)
|
|
l_theClone.m_mimeHeadersTable = (Hashtable) m_mimeHeadersTable.clone();
|
|
|
|
if (m_databuf != null)
|
|
l_theClone.m_databuf = (ByteBuffer) m_databuf.clone();
|
|
else if (m_dataStream != null)
|
|
{
|
|
l_theClone.m_databuf = getStreamData (m_dataStream);
|
|
l_theClone.m_dataStream = null;
|
|
}
|
|
if (m_contentSubType != null)
|
|
l_theClone.m_contentSubType = m_contentSubType;
|
|
if (m_contentTypeParams != null)
|
|
l_theClone.m_contentTypeParams = m_contentTypeParams;
|
|
|
|
if (m_contentID != null)
|
|
l_theClone.m_contentID = m_contentID;
|
|
|
|
if (m_contentMD5 != null)
|
|
l_theClone.m_contentMD5 = m_contentMD5;
|
|
|
|
if (m_contentDispParams != null)
|
|
l_theClone.m_contentDispParams = m_contentDispParams;
|
|
|
|
if (m_contentDescription != null)
|
|
l_theClone.m_contentDescription = m_contentDescription;
|
|
|
|
l_theClone.m_nStartMessageDataIndex = m_nStartMessageDataIndex;
|
|
l_theClone.m_nEndMessageDataIndex = m_nEndMessageDataIndex;
|
|
l_theClone.m_nMessageDataLen = m_nMessageDataLen;
|
|
l_theClone.m_UserObject = m_UserObject;
|
|
l_theClone.m_bDecodedData = m_bDecodedData;
|
|
|
|
return (l_theClone);
|
|
|
|
} // end clone()
|
|
|
|
|
|
protected int getStartMessageDataIndex() { return m_nStartMessageDataIndex; }
|
|
protected void setStartMessageDataIndex( int i ) { m_nStartMessageDataIndex = i; }
|
|
|
|
protected int getEndMessageDataIndex() { return m_nEndMessageDataIndex; }
|
|
protected void setEndMessageDataIndex( int i ) { m_nEndMessageDataIndex = i; }
|
|
|
|
public int getMessageDataLen() { return getSize(); }
|
|
|
|
protected void setMessageDataLen( int len ) { setSize( len ); }
|
|
|
|
protected void setContentType( int contentType ) { m_contentType = contentType; }
|
|
|
|
protected boolean getDecodedData() { return m_bDecodedData; }
|
|
protected void setDecodedData( boolean decodedData ) { m_bDecodedData = decodedData; }
|
|
|
|
protected void setSize( int len )
|
|
{
|
|
m_nMessageDataLen = len;
|
|
|
|
if (m_databuf != null)
|
|
m_databuf.setSize( len );
|
|
//else if (m_dataStream != null)
|
|
// m_nMessageDataLen = len;
|
|
}
|
|
|
|
} // end class MIMEBasicPart
|