1 package com.imcode.util; 2 3 import org.apache.commons.collections.MultiHashMap; 4 import org.apache.commons.collections.MultiMap; 5 import org.apache.commons.collections.iterators.IteratorEnumeration; 6 import org.apache.commons.fileupload.*; 7 import org.apache.commons.lang.UnhandledException; 8 import org.apache.oro.text.perl.Perl5Util; 9 10 import javax.servlet.http.HttpServletRequest; 11 import javax.servlet.http.HttpServletRequestWrapper; 12 import javax.activation.DataSource; 13 import java.io.*; 14 import java.util.*; 15 16 /*** 17 * Extends HttpServletRequest for RFC 1867 form based file upload support from Jakarta Commons-FileUpload 18 */ 19 public class MultipartHttpServletRequest extends HttpServletRequestWrapper { 20 static final String CHARSET_ISO_8859_1 = "ISO-8859-1"; 21 22 private MultiMap fileItemMap; 23 24 public MultipartHttpServletRequest( HttpServletRequest request ) throws IOException { 25 this(request,-1) ; 26 } 27 28 /*** 29 Constructor used to specify a size limit for uploads. 30 31 @param sizeLimit The maximum size for an upload, in bytes. 32 **/ 33 public MultipartHttpServletRequest( HttpServletRequest request, long sizeLimit ) throws IOException { 34 super( request ); 35 if ( FileUploadBase.isMultipartContent( request ) ) { 36 FileUpload fileUpload = new FileUpload( new DefaultFileItemFactory() ); 37 fileUpload.setSizeMax( sizeLimit ); 38 List fileItems ; 39 try { 40 fileItems = fileUpload.parseRequest( request ); 41 } catch ( FileUploadException e ) { 42 throw new IOException( e.getMessage() ); 43 } 44 fileItemMap = new MultiHashMap(); 45 for ( Iterator iterator = fileItems.iterator(); iterator.hasNext(); ) { 46 FileItem fileItem = new BaseNameFileItem( (FileItem)iterator.next() ); 47 fileItemMap.put( fileItem.getFieldName(), fileItem ); 48 } 49 } 50 } 51 52 public String getParameter( String key ) { 53 String[] parameterValues = getParameterValues( key ); 54 if ( null != parameterValues && parameterValues.length > 0 ) { 55 return parameterValues[0]; 56 } 57 return null; 58 } 59 60 public DataSourceFileItem getParameterFileItem( String key ) { 61 DataSourceFileItem[] parameterValues = getParameterFileItems( key ); 62 if ( null != parameterValues && parameterValues.length > 0 ) { 63 return parameterValues[0]; 64 } 65 return null; 66 } 67 68 public DataSourceFileItem[] getParameterFileItems( String key ) { 69 if ( null == fileItemMap ) { 70 return null; 71 } 72 final Collection parameterFileItems = (Collection)fileItemMap.get( key ); 73 if ( null == parameterFileItems ) { 74 return null; 75 } 76 return (DataSourceFileItem[])parameterFileItems.toArray( new DataSourceFileItem[parameterFileItems.size()] ); 77 } 78 79 public Map getParameterMap() { 80 Map map = super.getParameterMap() ; 81 if ( null != fileItemMap ) { 82 map = new HashMap( map ); 83 Set fileItemKeys = fileItemMap.keySet(); 84 for ( Iterator iterator = fileItemKeys.iterator(); iterator.hasNext(); ) { 85 String key = (String)iterator.next(); 86 map.put( key, getParameterValues( key ) ); 87 } 88 } 89 return map; 90 } 91 92 public Enumeration getParameterNames() { 93 Enumeration superParameterNames = super.getParameterNames(); 94 Set parameterNames = new HashSet(); 95 while ( superParameterNames.hasMoreElements() ) { 96 parameterNames.add( superParameterNames.nextElement() ); 97 } 98 if (null != fileItemMap) { 99 parameterNames.addAll( fileItemMap.keySet() ); 100 } 101 return new IteratorEnumeration( parameterNames.iterator() ); 102 } 103 104 public String[] getParameterValues( String key ) { 105 if ( null != fileItemMap ) { 106 List parameterValues = new ArrayList(); 107 Collection fileItems = (Collection)fileItemMap.get( key ); 108 if ( null == fileItems ) { 109 return null; 110 } 111 for ( Iterator iterator = fileItems.iterator(); iterator.hasNext(); ) { 112 FileItem fileItem = (FileItem)iterator.next(); 113 String contentType = fileItem.getContentType(); 114 parameterValues.add( getStringFromBytesWithContentType( fileItem.get(), contentType ) ); 115 } 116 return (String[])parameterValues.toArray( new String[parameterValues.size()] ); 117 } 118 return super.getParameterValues( key ); 119 } 120 121 static String getStringFromBytesWithContentType( byte[] bytes, String contentType ) { 122 try { 123 return new String( bytes, getCharsetFromContentType(contentType) ); 124 } catch ( UnsupportedEncodingException ignored ) { 125 } 126 try { 127 return new String( bytes, CHARSET_ISO_8859_1 ); 128 } catch ( UnsupportedEncodingException never ) { 129 throw new UnhandledException(never); 130 } 131 } 132 133 static String getCharsetFromContentType(String contentType) { 134 String charset = CHARSET_ISO_8859_1; 135 if ( null != contentType ) { 136 Perl5Util perl5Util = new Perl5Util(); 137 if ( perl5Util.match( "///bcharset=\"?(//S+?)\"?(?:$|;|//s)/", contentType ) ) { 138 charset = perl5Util.group( 1 ); 139 } 140 } 141 return charset ; 142 } 143 144 public interface DataSourceFileItem extends FileItem, DataSource { 145 146 } 147 148 private class BaseNameFileItem extends FileItemWrapper { 149 150 private BaseNameFileItem( FileItem fileItem ) { 151 super( fileItem ); 152 } 153 154 public String getName() { 155 String filename = fileItem.getName(); 156 if ( null != filename ) { 157 filename = filename.substring( filename.lastIndexOf( '/' ) + 1 ); 158 filename = filename.substring( filename.lastIndexOf( '//' ) + 1 ); 159 } 160 return filename; 161 } 162 } 163 164 private class FileItemWrapper implements DataSourceFileItem { 165 166 FileItem fileItem; 167 168 private FileItemWrapper( FileItem fileItem ) { 169 this.fileItem = fileItem; 170 } 171 172 public String getContentType() { 173 return fileItem.getContentType(); 174 } 175 176 public String getFieldName() { 177 return fileItem.getFieldName(); 178 } 179 180 public void setFieldName( String s ) { 181 fileItem.setFieldName( s ); 182 } 183 184 public InputStream getInputStream() throws IOException { 185 return fileItem.getInputStream(); 186 } 187 188 public String getName() { 189 return fileItem.getName(); 190 } 191 192 public OutputStream getOutputStream() throws IOException { 193 return fileItem.getOutputStream(); 194 } 195 196 public long getSize() { 197 return fileItem.getSize(); 198 } 199 200 public String getString() { 201 return fileItem.getString(); 202 } 203 204 public boolean isFormField() { 205 return fileItem.isFormField(); 206 } 207 208 public void setFormField( boolean b ) { 209 fileItem.setFormField( b ); 210 } 211 212 public boolean isInMemory() { 213 return fileItem.isInMemory(); 214 } 215 216 public byte[] get() { 217 return fileItem.get(); 218 } 219 220 public void delete() { 221 fileItem.delete(); 222 } 223 224 public String getString( String s ) throws UnsupportedEncodingException { 225 return fileItem.getString( s ); 226 } 227 228 public void write( File file ) throws Exception { 229 fileItem.write( file ); 230 } 231 } 232 233 }