Class that implements a Multipart that handles multipart/form-data content type : Email Header « Email « Java






Class that implements a Multipart that handles multipart/form-data content type

 
/***
 * jwma Java WebMail
 * Copyright (c) 2000-2003 jwma team
 *
 * jwma is free software; you can distribute and use this source
 * under the terms of the BSD-style license received along with
 * the distribution.
 ***/
package dtw.webmail.util;

import java.io.*;
import java.util.Hashtable;
import javax.mail.*;
import javax.mail.internet.*;
import javax.activation.*;

import org.apache.log4j.Logger;

//import dtw.webmail.JwmaKernel;

/**
 * Class that implements a Multipart that handles
 * the <tt>multipart/form-data</tt> content type.
 *
 * @author Dieter Wimberger
 * @version 0.9.7 07/02/2003
 */
public class FormdataMultipart extends MimeMultipart {

  //logging
  private static Logger log = Logger.getLogger(FormdataMultipart.class);

  //instance attributes
  private Hashtable m_Params = new Hashtable();
  private boolean m_Removed = false;

  /**
   * Constructs a <tt>FormdataMultipart</tt> instance.<br>
   * This implementation just calls the superclass constructor.
   *
   * @return the newly created <tt>FormdataMultipart</tt> instance.
   */
  public FormdataMultipart() {
    super();
  }//constructor

  /**
   * Constructs a <tt>FormdataMultipart</tt> instance.<br>
   * Automatically processes the body parts to extract parameters,
   * and attachments.
   *
   * @param DataSource to construct the Multipart from, will be a
   *        <tt>MultipartInputStream</tt>.
   *
   * @return the newly created <tt>FormdataMultipart</tt> instance.
   */
  public FormdataMultipart(DataSource ds)
      throws MessagingException, IOException {

    super(ds);
    processBodyParts();
    updateHeaders();
  }//constructor

  /**
   * Returns the extracted parameters (with the extrcted values)
   * as <tt>Hashtable</tt>.
   *
   * @return the extracted parameter data as <tt>Hashtable</tt>
   */
  public Hashtable getParameters() {
    return m_Params;
  }//getParameters

  /**
   * Processes the body parts of the form-data.
   * Extracts parameters and set values, and
   * leaves over the attachments.
   *
   * @throws IOException if i/o operations fail.
   * @throws MessagingException if parsing or part handling with
   *         Mail API classes fails.
   */
  private void processBodyParts()
      throws IOException, MessagingException {

    //if write out to log for debug reasons!
    //ByteArrayOutputStream bout=new ByteArrayOutputStream();
    //writeTo(bout);
    //JwmaKernel.getReference().debugLog().write(bout.toString());

    for (int i = 0; i < getCount(); i++) {
      MimeBodyPart mbp = (MimeBodyPart) getBodyPart(i);
      processBodyPart(mbp);
      if (m_Removed) {
        m_Removed = false;
        //decrease index i approbiately
        i--;
      }
    }


    setSubType("mixed");
    //JwmaKernel.getReference().debugLog().write(
    //  "Processed multipart/form-data. Attachment parts:"+getCount()
    //);
  }//processParts

  /**
   * Processes a body part of the form-data.
   * Extracts parameters and set values, and
   * leaves over the attachments.
   *
   * @param mbp the <tt>MimeBodyPart</tt> to be processed.
   *
   * @throws IOException if i/o operations fail.
   * @throws MessagingException if parsing or part handling with
   *         Mail API classes fails.
   */
  private void processBodyPart(MimeBodyPart mbp)
      throws MessagingException, IOException {

    //String contenttype=new String(mbp.getContentType());
    //JwmaKernel.getReference().debugLog().write("Processing "+contenttype);

    //check if a content-type is given
    String[] cts = mbp.getHeader("Content-Type");
    if (cts == null || cts.length == 0) {
      //this is a parameter, get it out and
      //remove the part.
      String controlname = extractName(
          (mbp.getHeader("Content-Disposition"))[0]);

      //JwmaKernel.getReference().debugLog().write("Processing control:"+controlname);
      //retrieve value observing encoding
      InputStream in = mbp.getInputStream();
      String[] encoding = mbp.getHeader("Content-Transfer-Encoding");
      if (encoding != null && encoding.length > 0) {
        in = MimeUtility.decode(in, encoding[0]);
      }

      String value = extractValue(in);
      if (value != null || !value.trim().equals("")) {
        addParameter(controlname, value);
      }
      //flag removal
      m_Removed = true;
      removeBodyPart(mbp);
    } else {
      String filename = extractFileName(
          (mbp.getHeader("Content-Disposition"))[0]);

      //normally without file the control should be not successful.
      //but neither netscape nor mircosoft iexploder care much.
      //the only feature is an empty filename.
      if (filename.equals("")) {
        //kick it out too
        m_Removed = true;
        removeBodyPart(mbp);
      } else {

        //JwmaKernel.getReference().debugLog().write("Incoming filename="+filename);

        //IExploder sends files with complete path.
        //jwma doesnt want this.
        int lastindex = filename.lastIndexOf("\\");
        if (lastindex != -1) {
          filename = filename.substring(lastindex + 1, filename.length());
        }

        //JwmaKernel.getReference().debugLog().write("Outgoing filename="+filename);

        //Observe a possible encoding
        InputStream in = mbp.getInputStream();
        String[] encoding = mbp.getHeader("Content-Transfer-Encoding");
        if (encoding != null && encoding.length > 0) {
          in = MimeUtility.decode(in, encoding[0]);
        }
        ByteArrayOutputStream bout = new ByteArrayOutputStream();
        OutputStream out = (OutputStream) bout;

        int i = 0;
        while ((i = in.read()) != -1) {
          //maybe more efficient in buffers, but well
          out.write(i);
        }
        out.flush();
        out.close();

        //create the datasource
        MimeBodyPartDataSource mbpds =
            new MimeBodyPartDataSource(
                //    contenttype,filename,bout.toByteArray()
                cts[0], filename, bout.toByteArray()
            );


        //Re-set the Content-Disposition header, in case
        //the file name was changed
        mbp.removeHeader("Content-Disposition");
        mbp.addHeader(
            "Content-Disposition", "attachment; filename=\"" +
            filename +
            "\""
        );

        //set a base64 transferencoding und the data handler
        mbp.addHeader("Content-Transfer-Encoding", "base64");
        mbp.setDataHandler(new DataHandler(mbpds));
      }
    }
  }//processBodyPart

  /**
   * Returns the name of a parameter by extracting it
   * from the content-disposition header line.
   *
   * @param disposition the content-disposition header line as
   *        <tt>String</tt>.
   *
   * @return the name of the parameter as <tt>String</tt>.
   *
   * @throws IOException if the header line is malformed.
   */
  private String extractName(String disposition)
      throws IOException {

    int end = 0;
    int start = -1;

    start = disposition.indexOf("name=\"");
    end = disposition.indexOf("\"", start + 7);   //offset is to skip name=\"
    if (start == -1 || end == -1) {
      throw new IOException("Mime header malformed.");
    }
    return disposition.substring(start + 6, end);
  }//extractName

  /**
   * Returns the filename of an attachment by extracting it
   * from the content-disposition header line.
   *
   * @param disposition the content-disposition header line as
   *        <tt>String</tt>.
   *
   * @return the filename of the attachment as <tt>String</tt>.
   *
   * @throws IOException if the header line is malformed.
   */
  private String extractFileName(String disposition)
      throws IOException {

    int end = 0;
    int start = -1;

    start = disposition.indexOf("filename=\"");
    end = disposition.indexOf("\"", start + 10);   //offset is to skip filename=\"
    if (start == -1 || end == -1) {
      throw new IOException("Mime header malformed.");
    }
    return disposition.substring(start + 10, end);
  }//extractFileName

  /**
   * Returns the value of a parameter by extracting it
   * from the <tt>InputStream</tt> that represents the content
   * of the (parameter) part.
   *
   * @param in <tt>InputStream</tt> that reads from the content
   *        of the (parameter) part.
   *
   * @return the value of the parameter as <tt>String</tt>.
   *
   * @throws IOException if reading from the stream fails.
   */
  private String extractValue(InputStream in)
      throws IOException {

    ByteArrayOutputStream out = new ByteArrayOutputStream();
    int i = 0;
    while ((i = in.read()) != -1) {
      out.write(i);
    }
    out.flush();
    out.close();
    in.close();

    //JwmaKernel.getReference().debugLog().write("Retrieved value="+out.toString());
    //apply a little bit of magic when returning
    return out.toString("iso-8859-1");
  }//extractValue

  /**
   * Adds a parameter and mapped value to the parameters collection.
   * If the parameter already exists, it adds another value to
   * an already existing parameter by extending the array of strings.
   *
   * @param name the name of the parameter as <tt>String</tt>.
   * @param value the value of the parameter as <tt>String</tt>.
   */
  private void addParameter(String name, String value) {
    String values[];

    //JwmaKernel.getReference().debugLog().write("Adding "+name+"="+value);

    if (m_Params.containsKey(name)) {
      String oldValues[] = (String[]) m_Params.get(name);
      values = new String[oldValues.length + 1];
      for (int i = 0; i < oldValues.length; i++) {
        values[i] = oldValues[i];
      }
      values[oldValues.length] = value;
    } else {
      values = new String[1];
      values[0] = value;
    }
    m_Params.put(name, values);
  }//addParameter

}//FormdataMultipart

   
  








Related examples in the same category

1.Get Email Header
2.Get Detail Header