001: /***
002: * jwma Java WebMail
003: * Copyright (c) 2000-2003 jwma team
004: *
005: * jwma is free software; you can distribute and use this source
006: * under the terms of the BSD-style license received along with
007: * the distribution.
008: ***/package dtw.webmail.util;
009:
010: import java.io.*;
011: import java.util.*;
012: import javax.servlet.*;
013: import javax.mail.*;
014: import javax.mail.internet.*;
015:
016: import org.apache.log4j.Logger;
017:
018: import dtw.webmail.model.JwmaMessagePartImpl;
019: import dtw.webmail.JwmaKernel;
020:
021: /**
022: * Class that encapsulates a MultipartRequest, internally
023: * handling it.
024: * <p>
025: * The protocol to access the parameters resembles the one
026: * of the <tt>ServletRequest</tt> class.
027: *
028: * @author Dieter Wimberger
029: * @version 0.9.7 07/02/2003
030: */
031: public class MultipartRequest {
032:
033: //logging
034: private static Logger log = Logger
035: .getLogger(MultipartRequest.class);
036:
037: //instance attributes
038: private int m_Limit;
039:
040: private ServletRequest m_Request;
041: private Hashtable m_Parameters;
042: private FormdataMultipart m_FormdataMultipart;
043:
044: /**
045: * Constructs a <tt>MultipartRequest</tt> instance, with an
046: * upload limit of 2048 kB.
047: *
048: * @return the newly constructed <tt>MultipartRequest</tt> instance.
049: */
050: public MultipartRequest(ServletRequest request) throws IOException {
051:
052: m_Limit = 2048 * 1024;
053:
054: m_Request = request;
055: processRequest();
056: }//constructor
057:
058: /**
059: * Constructs a <tt>MultipartRequest</tt> instance.
060: *
061: * @return the newly constructed <tt>MultipartRequest</tt> instance.
062: */
063: public MultipartRequest(ServletRequest request, int limit)
064: throws IOException {
065:
066: //Create with size from Kernel which comes in kb
067: //m_Limit = JwmaKernel.getReference()
068: // .getSettings().getMailTransportLimit() * 1024;
069: m_Limit = limit * 1024;
070:
071: m_Request = request;
072: processRequest();
073: }//constructor
074:
075: /**
076: * Returns the names of all the parameters as an Enumeration of
077: * strings.<br>
078: * It returns an empty Enumeration if there are no parameters.
079: *
080: * @return Enumeration of the names of all the parameters as strings.
081: */
082: public Enumeration getParameterNames() {
083: return m_Parameters.keys();
084: }//getParameterNames
085:
086: /**
087: * Returns the value of a given parameter as String, or null if
088: * the control was not successful or non existant.
089: * <i><b>Note:</b><br>
090: * Mimics servlet request, do not call for multi value
091: * parameters.</i>
092: *
093: * @param name of the parameter to be retrieved as <tt>String</tt>.
094: *
095: * @return the parameter's value as <tt>String</tt>.
096: */
097: public String getParameter(String name) {
098: if (m_Parameters.containsKey(name)) {
099: return ((String[]) m_Parameters.get(name))[0];
100: } else {
101: return null;
102: }
103: }//getParameter
104:
105: /**
106: * Returns all values of a given parameter as an array of strings.
107: *
108: * If this MultipartRequest does not contain any values for this
109: * parameter name, then this method returns null.
110: * Otherwise the array contains one <tt>String</tt> for each value
111: * of this parameter.
112: *
113: * @param name of the parameter to be retrieved as <tt>String</tt>.
114: *
115: * @return an array of strings,each representing a value of the
116: * parameter.
117: */
118: public String[] getParameterValues(String name) {
119: if (m_Parameters.containsKey(name)) {
120: return (String[]) m_Parameters.get(name);
121: } else {
122: return null;
123: }
124: }//getParameterValues
125:
126: /**
127: * Tests if this <tt>MultipartRequest</tt> has attachments.
128: *
129: * @return true if it has attachments, false otherwise.
130: */
131: public boolean hasAttachments() {
132: try {
133: return (m_FormdataMultipart.getCount() > 0);
134: } catch (MessagingException ex) {
135: return false;
136: }
137: }//hasAttachments
138:
139: /**
140: * Returns the attachments as <tt>MimeMultipart</tt>.
141: *
142: * @return the attachments contained within in a <tt>MimeMultipart</tt>
143: * instance.
144: */
145: public MimeMultipart getAttachments() {
146: return (MimeMultipart) m_FormdataMultipart;
147: }//getAttachments
148:
149: /**
150: * Parses the incoming multipart/form-data by reading it from the
151: * given request's input stream.
152: *
153: * <i><b>Note:</b>Does not handle multiparts contained in multiparts.</i>
154: *
155: * @throws IOException if uploaded content larger than allowed
156: * or parsing failed.
157: */
158: public void processRequest() throws IOException {
159:
160: //JwmaKernel.getReference().debugLog().write("Processing request data..");
161: //first check on content length
162: int length = m_Request.getContentLength();
163: //JwmaKernel.getReference().debugLog().write("Got Length..");
164:
165: if (length > m_Limit) {
166: throw new IOException("Posted data exceeds limit of "
167: + m_Limit + " bytes.");
168: }
169: //then check for the content type and contained boundary
170: String ctype = m_Request.getContentType();
171: //JwmaKernel.getReference().debugLog().write("Got content-type ("+ctype+")");
172:
173: if (ctype.indexOf("multipart/form-data") == -1) {
174: throw new IOException(
175: "Can only handle an incoming multipart/form-data stream:"
176: + ctype);
177: }
178:
179: //Quote unquoted boundaries
180: //Opera for example sends unquoted boundaries with non-safe characters
181: StringBuffer sbuf = new StringBuffer();
182: int idx = ctype.indexOf("boundary=");
183: sbuf.append(ctype.substring(0, idx));
184: sbuf.append("boundary=");
185: String boundary = ctype.substring(idx + 9, ctype.length());
186: if (boundary.charAt(0) == '"') {
187: sbuf.append(boundary);
188: } else {
189: sbuf.append("\"");
190: sbuf.append(boundary);
191: sbuf.append("\"");
192: }
193: ctype = sbuf.toString();
194:
195: //JwmaKernel.getReference().debugLog().write("Streaming in...");
196:
197: MultipartInputStream m_InputStream = new MultipartInputStream(
198: m_Request.getInputStream(), ctype, m_Limit);
199:
200: try {
201: m_FormdataMultipart = new FormdataMultipart(m_InputStream);
202: m_Parameters = m_FormdataMultipart.getParameters();
203:
204: } catch (MessagingException mex) {
205:
206: //JwmaKernel.getReference().debugLog().writeStackTrace(mex);
207: log.error("Failed to process multipart/form-data request.",
208: mex);
209: throw new IOException(mex.getMessage());
210: }
211: }//processRequest
212:
213: //constant definitions
214: /**
215: * Defines the size limit of the upload.
216: */
217: private static final int FORMDATA_LIMIT = 1024 * 1024; // 1 Meg
218:
219: }//class MultipartRequest
|