001: /* Copyright 2004 The JA-SIG Collaborative. All rights reserved.
002: * See license distributed with this file and
003: * available online at http://www.uportal.org/license.html
004: */
005:
006: package org.jasig.portal;
007:
008: import java.util.Enumeration;
009: import java.util.Hashtable;
010: import java.util.Iterator;
011: import java.util.Map;
012:
013: import javax.servlet.http.HttpServletRequest;
014: import javax.servlet.http.HttpServletRequestWrapper;
015:
016: import org.apache.commons.collections.iterators.IteratorEnumeration;
017: import org.jasig.portal.container.services.information.PortletStateManager;
018: import org.jasig.portal.properties.PropertiesManager;
019:
020: import com.oreilly.servlet.multipart.FilePart;
021: import com.oreilly.servlet.multipart.MultipartParser;
022: import com.oreilly.servlet.multipart.ParamPart;
023:
024: /**
025: * Wraps an http request object to prevent unverified requests from
026: * accessing any of the request parameters.
027: * @author Peter Kharchenko {@link <a href="mailto:pkharchenko@interactivebusiness.com"">pkharchenko@interactivebusiness.com"</a>}
028: * @version $Revision: 36815 $
029: */
030: public class RequestParamWrapper extends HttpServletRequestWrapper
031: implements IRequestParamWrapper {
032:
033: final protected Map parameters = new Hashtable();
034: protected boolean request_verified;
035: private static int sizeLimit = -1;
036:
037: public static final String UPLOAD_STATUS = "up_upload_status";
038:
039: /**
040: * Default value for the upload size limit.
041: * This value will be used when we are unable to load the corresponding property.
042: */
043: private static final int DEFAULT_SIZE_LIMIT = 3000000;
044:
045: /**
046: * Creates a new <code>RequestParamWrapper</code> instance.
047: *
048: * @param source an <code>HttpServletRequest</code> value that's being wrapped.
049: * @param request_verified a <code>boolean</code> flag that determines if the request params should be accessable.
050: */
051: public RequestParamWrapper(HttpServletRequest source,
052: boolean request_verified) {
053: super (source);
054: setFileUploadMaxSize();
055:
056: // leech all of the information from the source request
057: this .request_verified = request_verified;
058:
059: // only bother with parameter work if should be accessable
060: if (request_verified) {
061: //Determine if this is a request for a portlet
062: boolean isPortletRequest = source.getParameterMap()
063: .containsKey(PortletStateManager.ACTION);
064:
065: // parse request body
066: String contentType = source.getContentType();
067: if (contentType != null
068: && contentType.startsWith("multipart/form-data")
069: && !isPortletRequest) {
070: /*
071: UploadStatus is used to help with conversational state
072: that is lost when parameters are not parsed when the
073: sizeLimit is exceeded... this will help channels
074: determine the appropriate action when parameters
075: are lost.
076: */
077: UploadStatus uploadStatus = null;
078:
079: com.oreilly.servlet.multipart.Part attachmentPart;
080: try {
081: MultipartParser multi = new MultipartParser(source,
082: source.getContentLength(), true, true,
083: "UTF-8");
084: boolean noAttachments = source.getContentLength() > sizeLimit;
085:
086: while ((attachmentPart = multi.readNextPart()) != null) {
087: String partName = attachmentPart.getName();
088:
089: if (attachmentPart.isParam()) {
090: ParamPart parameterPart = (ParamPart) attachmentPart;
091: String paramValue = parameterPart
092: .getStringValue();
093: if (parameters.containsKey(partName)) {
094:
095: /* Assume they meant a multivalued tag, like a checkbox */
096: String[] oldValueArray = (String[]) parameters
097: .get(partName);
098: String[] valueArray = new String[oldValueArray.length + 1];
099: for (int i = 0; i < oldValueArray.length; i++) {
100: valueArray[i] = oldValueArray[i];
101: }
102: valueArray[oldValueArray.length] = paramValue;
103: parameters.put(partName, valueArray);
104: } else {
105: String[] valueArray = new String[1];
106: valueArray[0] = paramValue;
107: parameters.put(partName, valueArray);
108: }
109: } else if (attachmentPart.isFile()) {
110: FilePart filePart = (FilePart) attachmentPart;
111: String filename = filePart.getFileName();
112:
113: MultipartDataSource fileUpload = null;
114: // check if this file has exceeded the maximum allowed upload size
115: if (noAttachments) {
116: fileUpload = new MultipartDataSource(
117: filename,
118: "Exceeded file size allowed");
119: } else if (filename != null) {
120: fileUpload = new MultipartDataSource(
121: filePart);
122: }
123:
124: if (fileUpload != null) {
125:
126: if (parameters.containsKey(partName)) {
127: MultipartDataSource[] oldValueArray = (MultipartDataSource[]) parameters
128: .get(partName);
129: MultipartDataSource[] valueArray = new MultipartDataSource[oldValueArray.length + 1];
130: for (int i = 0; i < oldValueArray.length; i++) {
131: valueArray[i] = oldValueArray[i];
132: }
133: valueArray[oldValueArray.length] = fileUpload;
134: parameters
135: .put(partName, valueArray);
136: } else {
137: MultipartDataSource[] valueArray = new MultipartDataSource[1];
138: valueArray[0] = fileUpload;
139: parameters
140: .put(partName, valueArray);
141: }
142: uploadStatus = new UploadStatus(
143: UploadStatus.SUCCESS, sizeLimit);
144: }
145: }
146: }
147: } catch (Exception e) {
148: uploadStatus = new UploadStatus(
149: UploadStatus.FAILURE, sizeLimit);
150: //was: LogService.log(LogService.ERROR, e);
151: ExceptionHelper.genericTopHandler(Errors.bug, e);
152: }
153: UploadStatus[] statusArray = new UploadStatus[1];
154: statusArray[0] = uploadStatus;
155: parameters.put(UPLOAD_STATUS, statusArray);
156: }
157: }
158: }
159:
160: /**
161: * Overloaded method
162: * @param name the parameter name
163: * @return parameter
164: */
165: public String getParameter(String name) {
166: String[] value_array = this .getParameterValues(name);
167: if ((value_array != null) && (value_array.length > 0)) {
168: return value_array[0];
169: } else {
170: return null;
171: }
172: }
173:
174: /**
175: * Overloaded method
176: * @return parameter names
177: */
178: public Enumeration getParameterNames() {
179: final Iterator keyItr = this .getParameterMap().keySet()
180: .iterator();
181: return new IteratorEnumeration(keyItr);
182: }
183:
184: /**
185: * Return a String[] for this parameter
186: * @param name the parameter name
187: * @return String[] if parameter is not an Object[]
188: */
189: public String[] getParameterValues(String name) {
190: Object[] pars = (Object[]) this .getParameterMap().get(name);
191: if (pars != null && pars instanceof String[]) {
192: return (String[]) this .getParameterMap().get(name);
193: } else {
194: return null;
195: }
196: }
197:
198: /**
199: * Overloaded method
200: *
201: * @return a <code>Map</code> value
202: */
203: public Map getParameterMap() {
204: if (parameters.isEmpty()) {
205: return super .getParameterMap();
206: }
207:
208: Map mergedParams = new Hashtable(super .getParameterMap());
209: Iterator it = parameters.keySet().iterator();
210: while (it.hasNext()) {
211: String pName = (String) it.next();
212: mergedParams.put(pName, parameters.get(pName));
213: }
214: return mergedParams;
215: }
216:
217: /**
218: * Return the Object represented by this parameter name
219: * @param name the parameter name
220: * @return Object
221: */
222: public Object[] getObjectParameterValues(String name) {
223: return (Object[]) this .getParameterMap().get(name);
224: }
225:
226: private void setFileUploadMaxSize() {
227: // Obtain file upload max size
228: // This property was renamed in uPortal 2.3, so we'll check the old name if it is missing
229: if (sizeLimit < 0) {
230: try {
231: sizeLimit = PropertiesManager
232: .getPropertyAsInt("org.jasig.portal.RequestParamWrapper.file_upload_max_size");
233: } catch (Exception e) {
234: // if the old property name also isn't set, fall back on the default value.
235: sizeLimit = PropertiesManager
236: .getPropertyAsInt(
237: "org.jasig.portal.PortalSessionManager.File_upload_max_size",
238: DEFAULT_SIZE_LIMIT);
239: }
240: }
241: }
242:
243: }
|