1 28 29 package com.opencms.core; 30 31 import org.opencms.main.CmsLog; 32 import org.opencms.main.OpenCms; 33 import org.opencms.util.CmsResourceTranslator; 34 35 import java.io.ByteArrayOutputStream ; 36 import java.io.IOException ; 37 import java.util.Enumeration ; 38 import java.util.Hashtable ; 39 import java.util.StringTokenizer ; 40 41 import javax.servlet.http.HttpServletRequest ; 42 import javax.servlet.http.HttpSession ; 43 44 import org.apache.commons.logging.Log; 45 46 72 public class CmsRequestHttpServlet implements I_CmsRequest { 73 74 77 static final String C_REQUEST_NOBOUNDARY = "Separation boundary was not specified"; 78 79 82 static final String C_REQUEST_NOMULTIPART = "Posted content type isn't multipart/form-data"; 83 84 87 static final String C_REQUEST_NOTNULL = "The Request cannot be null."; 88 89 92 static final String C_REQUEST_PROMATUREEND = "Corrupt form data: premature ending"; 93 94 97 static final String C_REQUEST_SIZENOTNEGATIVE = "The maxPostSize must be positive."; 98 99 100 private static final Log LOG = CmsLog.getLog(CmsRequestHttpServlet.class); 101 102 105 int m_filecounter; 106 107 110 private Hashtable m_files = new Hashtable (); 111 112 115 private Hashtable m_parameters = new Hashtable (); 116 117 120 private HttpServletRequest m_req; 121 122 123 private String m_requestedResource; 124 private String m_scheme=""; 125 private String m_serverName=""; 126 private int m_serverPort; 127 private String m_servletUrl=""; 128 129 132 private CmsResourceTranslator m_translator; 133 134 137 private int m_type = com.opencms.core.I_CmsConstants.C_REQUEST_HTTP; 138 139 143 private String m_webAppUrl=""; 144 145 152 public CmsRequestHttpServlet(HttpServletRequest req, CmsResourceTranslator translator) throws IOException { 153 m_req = req; 154 m_translator = translator; 155 156 try { 158 m_webAppUrl = m_req.getContextPath(); 159 } catch (NoSuchMethodError err) { 160 } 163 m_serverName = m_req.getServerName(); 164 m_scheme = m_req.getScheme(); 165 m_serverPort = m_req.getServerPort(); 166 m_servletUrl = m_webAppUrl + m_req.getServletPath(); 167 String type = req.getHeader("content-type"); 170 if ((type != null) && type.startsWith("multipart/form-data") && (req.getContentLength() > -1)) { 171 readRequest(); 172 } else { 173 String encoding = req.getCharacterEncoding(); 176 if (encoding == null) { 177 HttpSession httpSession = req.getSession(false); 179 I_CmsSession session = (httpSession != null) 180 ? new CmsSession(httpSession) : null; 181 if (session != null) { 182 encoding = (String )session.getValue( 183 com.opencms.core.I_CmsConstants.C_SESSION_CONTENT_ENCODING); 184 } 185 if (encoding == null) { 187 encoding = OpenCms.getSystemInfo().getDefaultEncoding(); 188 } 189 req.setCharacterEncoding(encoding); 190 } 191 if (LOG.isDebugEnabled()) { 192 LOG.debug("Request character encoding is: '" + req.getCharacterEncoding() + "'"); 193 } 194 } 195 } 196 197 205 public byte[] getFile(String name) { 206 return (byte[])m_files.get(name); 207 } 208 209 215 public Enumeration getFileNames() { 216 Enumeration names = m_files.keys(); 217 return names; 218 } 219 220 225 public HttpServletRequest getOriginalRequest() { 226 return m_req; 227 } 228 229 235 public int getOriginalRequestType() { 236 return m_type; 237 } 238 239 247 public String getParameter(String name) { 248 String parameter = null; 249 250 String type = m_req.getHeader("content-type"); 253 if ((type != null) && type.startsWith("multipart/form-data")) { 254 parameter = (String )m_parameters.get(name); 255 } else { 256 parameter = m_req.getParameter(name); 257 } 258 return parameter; 259 } 260 261 267 public Enumeration getParameterNames() { 268 String type = m_req.getHeader("content-type"); 269 if ((type != null) && type.startsWith("multipart/form-data")) { 270 271 return m_parameters.keys(); 273 } else { 274 275 return m_req.getParameterNames(); 277 } 278 } 279 280 286 public String [] getParameterValues(String key) { 287 return m_req.getParameterValues(key); 288 } 289 290 302 public String getRequestedResource() { 303 if (m_requestedResource != null) { 304 return m_requestedResource; 305 } 306 m_requestedResource = m_req.getPathInfo(); 307 if (m_requestedResource == null) { 308 m_requestedResource = "/"; 309 } 310 return m_requestedResource; 311 } 312 317 public String getScheme() { 318 return m_scheme; 319 } 320 321 326 public String getServerName() { 327 return m_serverName; 328 } 329 334 public int getServerPort() { 335 return m_serverPort; 336 } 337 338 344 public String getServletUrl() { 345 return m_servletUrl; 346 } 347 348 356 public String getWebAppUrl() { 357 return m_webAppUrl; 358 } 359 360 365 public void setOriginalRequest(HttpServletRequest request) { 366 m_req = request; 367 } 368 369 376 public void setRequestedResource(String resourceName) { 377 m_requestedResource = resourceName; 378 } 379 380 386 private String extractBoundary(String line) { 387 int index = line.indexOf("boundary="); 388 if (index == -1) { 389 return null; 390 } 391 392 String boundary = line.substring(index + 9); 394 395 boundary = "--" + boundary; 397 return boundary; 398 } 399 400 407 private String extractContentType(String line) throws IOException { 408 String contentType = null; 409 410 String origline = line; 412 line = origline.toLowerCase(); 413 414 if (line.startsWith("content-type")) { 416 int start = line.indexOf(" "); 417 if (start == -1) { 418 throw new IOException ("Content type corrupt: " + origline); 419 } 420 contentType = line.substring(start + 1); 421 } else { 422 if (line.length() != 0) { 423 throw new IOException ("Malformed line after disposition: " + origline); 425 } 426 } 427 return contentType; 428 } 429 430 439 private String [] extractDispositionInfo(String line) throws IOException { 440 441 String [] retval = new String [3]; 443 444 String origline = line; 447 line = origline.toLowerCase(); 448 449 int start = line.indexOf("content-disposition: "); 451 int end = line.indexOf(";"); 452 if (start == -1 || end == -1) { 453 throw new IOException ("Content disposition corrupt: " + origline); 454 } 455 String disposition = line.substring(start + 21, end); 456 if (!disposition.equals("form-data")) { 457 throw new IOException ("Invalid content disposition: " + disposition); 458 } 459 460 start = line.indexOf("name=\"", end); 463 464 end = line.indexOf("\"", start + 7); 466 if (start == -1 || end == -1) { 467 throw new IOException ("Content disposition corrupt: " + origline); 468 } 469 String name = origline.substring(start + 6, end); 470 471 String filename = null; 473 474 start = line.indexOf("filename=\"", end + 2); 476 477 end = line.indexOf("\"", start + 10); 479 480 if (start != -1 && end != -1) { 482 filename = origline.substring(start + 10, end); 483 484 int slash = Math.max(filename.lastIndexOf('/'), filename.lastIndexOf('\\')); 486 if (slash > -1) { 487 filename = filename.substring(slash + 1); } 489 if (filename.equals("")) { 490 filename = "unknown"; } 492 } 493 494 filename = m_translator.translateResource(filename); 496 497 retval[0] = disposition; 499 retval[1] = name; 500 retval[2] = filename; 501 return retval; 502 } 503 504 517 private byte[] readAndSaveFile(CmsMultipartInputStreamHandler in, String boundary) throws IOException { 518 ByteArrayOutputStream out = new ByteArrayOutputStream (8 * 1024); 519 byte[] boundaryBytes = boundary.getBytes(); 520 int[] lookaheadBuf = new int[boundary.length() + 3]; 521 int[] newLineBuf = { 522 -1, -1 523 }; 524 int matches = 0; 525 int matchingByte = new Byte (boundaryBytes[matches]).intValue(); 526 527 534 int read = in.read(); 535 while (read > -1) { 536 if (read == matchingByte) { 537 538 lookaheadBuf[matches] = read; 541 matches++; 542 if (matches == boundary.length()) { 543 544 read = in.read(); 547 if (newLineBuf[1] == read) { 548 549 out.write(newLineBuf[0]); 552 } else { 553 554 in.read(); 558 } 559 break; 560 } 561 matchingByte = new Byte (boundaryBytes[matches]).intValue(); 562 } else { 563 564 if (newLineBuf[0] != -1) { 567 out.write(newLineBuf[0]); 568 } 569 if (matches == 0) { 570 571 newLineBuf[0] = newLineBuf[1]; 573 } else { 574 575 if (newLineBuf[1] != -1) { 580 out.write(newLineBuf[1]); 581 } 582 for (int i = 0; i < matches; i++) { 583 out.write(lookaheadBuf[i]); 584 } 585 586 matches = 0; 588 matchingByte = new Byte (boundaryBytes[matches]).intValue(); 589 590 newLineBuf[0] = -1; 592 } 593 594 newLineBuf[1] = read; 597 } 598 read = in.read(); 599 } 600 out.flush(); 601 return out.toByteArray(); 602 } 603 604 619 private boolean readNextPart(CmsMultipartInputStreamHandler in, String boundary) throws IOException { 620 621 String line = in.readLine(); 624 if (line == null || line.equals("")) { 625 626 return true; 628 } 629 630 String [] dispInfo = extractDispositionInfo(line); 632 633 String name = dispInfo[1]; 635 String filename = dispInfo[2]; 636 637 line = in.readLine(); 640 if (line == null) { 641 642 return true; 644 } 645 646 String contentType = extractContentType(line); 648 if (contentType != null) { 649 650 line = in.readLine(); 652 if (line == null || line.length() > 0) { line = in.readLine(); 654 if (line == null || line.length() > 0) { throw new IOException ("Malformed line after content type: " + line); 656 } 657 } 658 659 } else { 660 661 contentType = "application/octet-stream"; 663 } 664 665 if (filename == null) { 667 668 String value = readParameter(in, boundary); 670 m_parameters.put(name, value); 671 } else { 672 m_filecounter++; 673 m_files.put(filename, readAndSaveFile(in, boundary)); 675 m_parameters.put(name, filename); 677 } 678 679 return false; 681 } 682 683 694 private String readParameter(CmsMultipartInputStreamHandler in, String boundary) throws IOException { 695 StringBuffer sbuf = new StringBuffer (); 696 String line; 697 while ((line = in.readLine()) != null) { 698 if (line.startsWith(boundary)) { 699 break; 700 } 701 702 sbuf.append(line + "\r\n"); 704 } 705 if (sbuf.length() == 0) { 706 707 return null; 709 } 710 711 sbuf.setLength(sbuf.length() - 2); 713 714 return sbuf.toString(); 716 } 717 718 726 private void readRequest() throws IOException { 727 728 String type = m_req.getContentType(); 730 if (type == null || !type.toLowerCase().startsWith("multipart/form-data")) { 731 throw new IOException (C_REQUEST_NOMULTIPART); 732 } 733 734 int length = m_req.getContentLength(); 735 736 String boundary = extractBoundary(type); 739 if (boundary == null) { 740 throw new IOException (C_REQUEST_NOBOUNDARY); 741 } 742 743 CmsMultipartInputStreamHandler in = new CmsMultipartInputStreamHandler(m_req.getInputStream(), length); 745 746 String line = in.readLine(); 748 if (line == null) { 749 throw new IOException (C_REQUEST_PROMATUREEND); 750 } 751 752 if (!line.startsWith(boundary)) { 754 throw new IOException (C_REQUEST_NOBOUNDARY); 755 } 756 757 boolean done = false; 759 while (!done) { 760 done = readNextPart(in, boundary); 761 } 762 763 String queryString = m_req.getQueryString(); 767 if (queryString != null) { 768 StringTokenizer st = new StringTokenizer (m_req.getQueryString(), "&"); 769 while (st.hasMoreTokens()) { 770 771 String currToken = st.nextToken(); 773 if (currToken != null && !"".equals(currToken)) { 774 775 int idx = currToken.indexOf("="); 777 if (idx > -1) { 778 String key = currToken.substring(0, idx); 779 String value = (idx < (currToken.length() - 1)) ? currToken.substring(idx + 1) : ""; 780 m_parameters.put(key, value); 781 } 782 } 783 } 784 } 785 } 786 } 787 | Popular Tags |