1 package org.sapia.soto.state.cocoon.util; 2 3 import org.apache.cocoon.environment.http.HttpRequest; 4 5 import org.apache.commons.fileupload.FileItem; 6 import org.apache.commons.fileupload.FileItemFactory; 7 import org.apache.commons.fileupload.FileUploadException; 8 import org.apache.commons.fileupload.MultipartStream; 9 10 import java.io.IOException ; 11 import java.io.InputStream ; 12 import java.io.OutputStream ; 13 14 import java.util.ArrayList ; 15 import java.util.HashMap ; 16 import java.util.List ; 17 import java.util.Map ; 18 19 20 51 public abstract class CocoonFileUploadBase { 52 54 57 public static final String CONTENT_TYPE = "Content-type"; 58 59 62 public static final String CONTENT_DISPOSITION = "Content-disposition"; 63 64 67 public static final String FORM_DATA = "form-data"; 68 69 72 public static final String ATTACHMENT = "attachment"; 73 74 77 public static final String MULTIPART = "multipart/"; 78 79 82 public static final String MULTIPART_FORM_DATA = "multipart/form-data"; 83 84 87 public static final String MULTIPART_MIXED = "multipart/mixed"; 88 89 93 public static final int MAX_HEADER_SIZE = 1024; 94 95 97 101 private long sizeMax = -1; 102 103 106 private String headerEncoding; 107 108 110 119 public static final boolean isMultipartContent(HttpRequest req) { 120 String contentType = req.getHeader(CONTENT_TYPE); 121 122 if (contentType == null) { 123 return false; 124 } 125 126 if (contentType.startsWith(MULTIPART)) { 127 return true; 128 } 129 130 return false; 131 } 132 133 135 140 public abstract FileItemFactory getFileItemFactory(); 141 142 147 public abstract void setFileItemFactory(FileItemFactory factory); 148 149 157 public long getSizeMax() { 158 return sizeMax; 159 } 160 161 169 public void setSizeMax(long sizeMax) { 170 this.sizeMax = sizeMax; 171 } 172 173 180 public String getHeaderEncoding() { 181 return headerEncoding; 182 } 183 184 191 public void setHeaderEncoding(String encoding) { 192 headerEncoding = encoding; 193 } 194 195 197 210 public List parseRequest(HttpRequest req) 211 throws FileUploadException { 212 if (null == req) { 213 throw new NullPointerException ("req parameter"); 214 } 215 216 ArrayList items = new ArrayList (); 217 String contentType = req.getHeader(CONTENT_TYPE); 218 219 if ((null == contentType) || (!contentType.startsWith(MULTIPART))) { 220 throw new InvalidContentTypeException("the request doesn't contain a " + 221 MULTIPART_FORM_DATA + " or " + MULTIPART_MIXED + 222 " stream, content type header is " + contentType); 223 } 224 225 int requestSize = req.getContentLength(); 226 227 if (requestSize == -1) { 228 throw new UnknownSizeException( 229 "the request was rejected because it's size is unknown"); 230 } 231 232 if ((sizeMax >= 0) && (requestSize > sizeMax)) { 233 throw new SizeLimitExceededException("the request was rejected because " + 234 "it's size exceeds allowed range"); 235 } 236 237 try { 238 int boundaryIndex = contentType.indexOf("boundary="); 239 240 if (boundaryIndex < 0) { 241 throw new FileUploadException("the request was rejected because " + 242 "no multipart boundary was found"); 243 } 244 245 byte[] boundary = contentType.substring(boundaryIndex + 9) 246 .getBytes(); 247 248 InputStream input = req.getInputStream(); 249 250 MultipartStream multi = new MultipartStream(input, boundary); 251 multi.setHeaderEncoding(headerEncoding); 252 253 boolean nextPart = multi.skipPreamble(); 254 255 while (nextPart) { 256 Map headers = parseHeaders(multi.readHeaders()); 257 String fieldName = getFieldName(headers); 258 259 if (fieldName != null) { 260 String subContentType = getHeader(headers, CONTENT_TYPE); 261 262 if ((subContentType != null) && 263 subContentType.startsWith(MULTIPART_MIXED)) { 264 byte[] subBoundary = subContentType.substring(subContentType.indexOf( 266 "boundary=") + 9).getBytes(); 267 multi.setBoundary(subBoundary); 268 269 boolean nextSubPart = multi.skipPreamble(); 270 271 while (nextSubPart) { 272 headers = parseHeaders(multi.readHeaders()); 273 274 if (getFileName(headers) != null) { 275 FileItem item = createItem(headers, false); 276 OutputStream os = item.getOutputStream(); 277 278 try { 279 multi.readBodyData(os); 280 } finally { 281 os.close(); 282 } 283 284 items.add(item); 285 } else { 286 multi.discardBodyData(); 289 } 290 291 nextSubPart = multi.readBoundary(); 292 } 293 294 multi.setBoundary(boundary); 295 } else { 296 FileItem item = createItem(headers, getFileName(headers) == null); 297 OutputStream os = item.getOutputStream(); 298 299 try { 300 multi.readBodyData(os); 301 } finally { 302 os.close(); 303 } 304 305 items.add(item); 306 } 307 } else { 308 multi.discardBodyData(); 310 } 311 312 nextPart = multi.readBoundary(); 313 } 314 } catch (IOException e) { 315 throw new FileUploadException("Processing of " + MULTIPART_FORM_DATA + 316 " request failed. " + e.getMessage()); 317 } 318 319 return items; 320 } 321 322 324 332 protected String getFileName(Map headers) { 333 String fileName = null; 334 String cd = getHeader(headers, CONTENT_DISPOSITION); 335 336 if (cd.startsWith(FORM_DATA) || cd.startsWith(ATTACHMENT)) { 337 int start = cd.indexOf("filename=\""); 338 int end = cd.indexOf('"', start + 10); 339 340 if ((start != -1) && (end != -1)) { 341 fileName = cd.substring(start + 10, end).trim(); 342 } 343 } 344 345 return fileName; 346 } 347 348 356 protected String getFieldName(Map headers) { 357 String fieldName = null; 358 String cd = getHeader(headers, CONTENT_DISPOSITION); 359 360 if ((cd != null) && cd.startsWith(FORM_DATA)) { 361 int start = cd.indexOf("name=\""); 362 int end = cd.indexOf('"', start + 6); 363 364 if ((start != -1) && (end != -1)) { 365 fieldName = cd.substring(start + 6, end); 366 } 367 } 368 369 return fieldName; 370 } 371 372 384 protected FileItem createItem(Map headers, 385 boolean isFormField) throws FileUploadException { 386 return getFileItemFactory().createItem(getFieldName(headers), 387 getHeader(headers, CONTENT_TYPE), isFormField, getFileName(headers)); 388 } 389 390 402 protected Map parseHeaders(String headerPart) { 403 Map headers = new HashMap (); 404 char[] buffer = new char[MAX_HEADER_SIZE]; 405 boolean done = false; 406 int j = 0; 407 int i; 408 String header; 409 String headerName; 410 String headerValue; 411 412 try { 413 while (!done) { 414 i = 0; 415 416 while ((i < 2) || (buffer[i - 2] != '\r') || (buffer[i - 1] != '\n')) { 419 buffer[i++] = headerPart.charAt(j++); 420 } 421 422 header = new String (buffer, 0, i - 2); 423 424 if (header.equals("")) { 425 done = true; 426 } else { 427 if (header.indexOf(':') == -1) { 428 continue; 430 } 431 432 headerName = header.substring(0, header.indexOf(':')).trim() 433 .toLowerCase(); 434 headerValue = header.substring(header.indexOf(':') + 1).trim(); 435 436 if (getHeader(headers, headerName) != null) { 437 headers.put(headerName, 440 getHeader(headers, headerName) + ',' + headerValue); 441 } else { 442 headers.put(headerName, headerValue); 443 } 444 } 445 } 446 } catch (IndexOutOfBoundsException e) { 447 } 450 451 return headers; 452 } 453 454 464 protected final String getHeader(Map headers, String name) { 465 return (String ) headers.get(name.toLowerCase()); 466 } 467 468 471 public static class InvalidContentTypeException extends FileUploadException { 472 476 public InvalidContentTypeException() { 477 super(); 478 } 479 480 486 public InvalidContentTypeException(String message) { 487 super(message); 488 } 489 } 490 491 494 public static class UnknownSizeException extends FileUploadException { 495 499 public UnknownSizeException() { 500 super(); 501 } 502 503 509 public UnknownSizeException(String message) { 510 super(message); 511 } 512 } 513 514 517 public static class SizeLimitExceededException extends FileUploadException { 518 522 public SizeLimitExceededException() { 523 super(); 524 } 525 526 532 public SizeLimitExceededException(String message) { 533 super(message); 534 } 535 } 536 } 537 | Popular Tags |