001/* 002 * This library is part of OpenCms - 003 * the Open Source Content Management System 004 * 005 * Copyright (c) Alkacon Software GmbH (http://www.alkacon.com) 006 * 007 * This library is free software; you can redistribute it and/or 008 * modify it under the terms of the GNU Lesser General Public 009 * License as published by the Free Software Foundation; either 010 * version 2.1 of the License, or (at your option) any later version. 011 * 012 * This library is distributed in the hope that it will be useful, 013 * but WITHOUT ANY WARRANTY; without even the implied warranty of 014 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 015 * Lesser General Public License for more details. 016 * 017 * For further information about Alkacon Software GmbH, please see the 018 * company website: http://www.alkacon.com 019 * 020 * For further information about OpenCms, please see the 021 * project website: http://www.opencms.org 022 * 023 * You should have received a copy of the GNU Lesser General Public 024 * License along with this library; if not, write to the Free Software 025 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 026 */ 027 028package org.opencms.util; 029 030import org.opencms.flex.CmsFlexRequest; 031import org.opencms.i18n.CmsEncoder; 032import org.opencms.json.JSONArray; 033import org.opencms.json.JSONException; 034import org.opencms.json.JSONObject; 035import org.opencms.jsp.CmsJspActionElement; 036import org.opencms.main.CmsLog; 037import org.opencms.main.OpenCms; 038 039import java.io.File; 040import java.io.IOException; 041import java.io.UnsupportedEncodingException; 042import java.util.ArrayList; 043import java.util.Enumeration; 044import java.util.HashMap; 045import java.util.Iterator; 046import java.util.List; 047import java.util.Map; 048import java.util.Map.Entry; 049 050import javax.servlet.ServletException; 051import javax.servlet.ServletRequest; 052import javax.servlet.http.Cookie; 053import javax.servlet.http.HttpServletRequest; 054import javax.servlet.http.HttpServletResponse; 055import javax.servlet.http.HttpSession; 056 057import org.apache.commons.fileupload.FileItem; 058import org.apache.commons.fileupload.FileUploadException; 059import org.apache.commons.fileupload.disk.DiskFileItemFactory; 060import org.apache.commons.fileupload.servlet.ServletFileUpload; 061import org.apache.commons.logging.Log; 062 063/** 064 * Provides utility functions for dealing with values a <code>{@link HttpServletRequest}</code>.<p> 065 * 066 * @since 6.0.0 067 */ 068public final class CmsRequestUtil { 069 070 /** Request attribute that contains the original error code. */ 071 public static final String ATTRIBUTE_ERRORCODE = "org.opencms.util.CmsErrorCode"; 072 073 /** HTTP Accept Header for the cms:device-tag. */ 074 public static final String HEADER_ACCEPT = "Accept"; 075 076 /** HTTP Accept-Charset Header for internal requests used during static export. */ 077 public static final String HEADER_ACCEPT_CHARSET = "Accept-Charset"; 078 079 /** HTTP Accept-Language Header for internal requests used during static export. */ 080 public static final String HEADER_ACCEPT_LANGUAGE = "Accept-Language"; 081 082 /** HTTP Header "Cache-Control". */ 083 public static final String HEADER_CACHE_CONTROL = "Cache-Control"; 084 085 /** HTTP Header "Connection". */ 086 public static final String HEADER_CONNECTION = "Connection"; 087 088 /** The "Content-Disposition" http header. */ 089 public static final String HEADER_CONTENT_DISPOSITION = "Content-Disposition"; 090 091 /** The "Content-Type" http header. */ 092 public static final String HEADER_CONTENT_TYPE = "Content-Type"; 093 094 /** HTTP Header "Expires". */ 095 public static final String HEADER_EXPIRES = "Expires"; 096 097 /** HTTP Header "If-Modified-Since". */ 098 public static final String HEADER_IF_MODIFIED_SINCE = "If-Modified-Since"; 099 100 /** The Header that stores the session id (used by OpenCms upload applet). */ 101 public static final String HEADER_JSESSIONID = "JSESSIONID"; 102 103 /** HTTP Header "Last-Modified". */ 104 public static final String HEADER_LAST_MODIFIED = "Last-Modified"; 105 106 /** HTTP Header "Location". */ 107 public static final String HEADER_LOCATION = "Location"; 108 109 /** HTTP Header for internal requests used during static export. */ 110 public static final String HEADER_OPENCMS_EXPORT = "OpenCms-Export"; 111 112 /** HTTP Header "Pragma". */ 113 public static final String HEADER_PRAGMA = "Pragma"; 114 115 /** HTTP Header "Server". */ 116 public static final String HEADER_SERVER = "Server"; 117 118 /** HTTP Header "user-agent". */ 119 public static final String HEADER_USER_AGENT = "user-agent"; 120 121 /** HTTP Header value "max-age=" (for "Cache-Control"). */ 122 public static final String HEADER_VALUE_MAX_AGE = "max-age="; 123 124 /** HTTP Header value "must-revalidate" (for "Cache-Control"). */ 125 public static final String HEADER_VALUE_MUST_REVALIDATE = "must-revalidate"; 126 127 /** HTTP Header value "no-cache" (for "Cache-Control"). */ 128 public static final String HEADER_VALUE_NO_CACHE = "no-cache"; 129 130 /** HTTP Header value "no-store" (for "Cache-Control"). */ 131 public static final String HEADER_VALUE_NO_STORE = "no-store"; 132 133 /** HTTP Header "WWW-Authenticate". */ 134 public static final String HEADER_WWW_AUTHENTICATE = "WWW-Authenticate"; 135 136 /** Identifier for x-forwarded-for (i.e. proxied) request headers. */ 137 public static final String HEADER_X_FORWARDED_FOR = "x-forwarded-for"; 138 139 /** Assignment char between parameter name and values. */ 140 public static final String PARAMETER_ASSIGNMENT = "="; 141 142 /** Delimiter char between parameters. */ 143 public static final String PARAMETER_DELIMITER = "&"; 144 145 /** Delimiter char between url and query. */ 146 public static final String URL_DELIMITER = "?"; 147 148 /** The prefix for &. */ 149 private static final String AMP = "amp;"; 150 151 /** The log object for this class. */ 152 private static final Log LOG = CmsLog.getLog(CmsRequestUtil.class); 153 154 /** 155 * Default constructor (empty), private because this class has only 156 * static methods.<p> 157 */ 158 private CmsRequestUtil() { 159 160 // empty 161 } 162 163 /** 164 * Appends a request parameter to the given URL.<p> 165 * 166 * This method takes care about the adding the parameter as an additional 167 * parameter (appending <code>¶m=value</code>) or as the first parameter 168 * (appending <code>?param=value</code>).<p> 169 * 170 * @param url the URL where to append the parameter to 171 * @param paramName the paramter name to append 172 * @param paramValue the parameter value to append 173 * 174 * @return the URL with the given parameter appended 175 */ 176 public static String appendParameter(String url, String paramName, String paramValue) { 177 178 if (CmsStringUtil.isEmpty(url)) { 179 return null; 180 } 181 int pos = url.indexOf(URL_DELIMITER); 182 StringBuffer result = new StringBuffer(256); 183 result.append(url); 184 if (pos >= 0) { 185 // url already has parameters 186 result.append(PARAMETER_DELIMITER); 187 } else { 188 // url does not have parameters 189 result.append(URL_DELIMITER); 190 } 191 result.append(paramName); 192 result.append(PARAMETER_ASSIGNMENT); 193 result.append(paramValue); 194 return result.toString(); 195 } 196 197 /** 198 * Appends a map of request parameters to the given URL.<p> 199 * 200 * The map can contains values of <code>String[]</code> or 201 * simple <code>String</code> values.<p> 202 * 203 * This method takes care about the adding the parameter as an additional 204 * parameter (appending <code>¶m=value</code>) or as the first parameter 205 * (appending <code>?param=value</code>).<p> 206 * 207 * @param url the URL where to append the parameter to 208 * @param params the parameters to append 209 * @param encode if <code>true</code>, the parameter values are encoded before they are appended 210 * 211 * @return the URL with the given parameter appended 212 */ 213 public static String appendParameters(String url, Map<String, String[]> params, boolean encode) { 214 215 if (CmsStringUtil.isEmpty(url)) { 216 return null; 217 } 218 if ((params == null) || params.isEmpty()) { 219 return url; 220 } 221 int pos = url.indexOf(URL_DELIMITER); 222 StringBuffer result = new StringBuffer(256); 223 result.append(url); 224 if (pos >= 0) { 225 // url already has parameters 226 result.append(PARAMETER_DELIMITER); 227 } else { 228 // url does not have parameters 229 result.append(URL_DELIMITER); 230 } 231 // ensure all values are of type String[] 232 Iterator<Map.Entry<String, String[]>> i = params.entrySet().iterator(); 233 while (i.hasNext()) { 234 Map.Entry<String, String[]> entry = i.next(); 235 String key = entry.getKey(); 236 Object value = entry.getValue(); 237 // generics where added later, so make sure that the value really is a String[] 238 String[] values = value instanceof String[] ? (String[])value : new String[] {value.toString()}; 239 for (int j = 0; j < values.length; j++) { 240 String strValue = values[j]; 241 if (encode) { 242 strValue = CmsEncoder.encode(strValue); 243 } 244 result.append(key); 245 result.append(PARAMETER_ASSIGNMENT); 246 result.append(strValue); 247 if ((j + 1) < values.length) { 248 result.append(PARAMETER_DELIMITER); 249 } 250 } 251 if (i.hasNext()) { 252 result.append(PARAMETER_DELIMITER); 253 } 254 } 255 return result.toString(); 256 } 257 258 /** 259 * Creates a valid request parameter map from the given map, 260 * most notably changing the values form <code>String</code> 261 * to <code>String[]</code> if required.<p> 262 * 263 * If the given parameter map is <code>null</code>, then <code>null</code> is returned.<p> 264 * 265 * @param params the map of parameters to create a parameter map from 266 * @return the created parameter map, all values will be instances of <code>String[]</code> 267 */ 268 public static Map<String, String[]> createParameterMap(Map<String, ?> params) { 269 270 if (params == null) { 271 return null; 272 } 273 Map<String, String[]> result = new HashMap<String, String[]>(); 274 Iterator<?> i = params.entrySet().iterator(); 275 while (i.hasNext()) { 276 @SuppressWarnings("unchecked") 277 Map.Entry<String, ?> entry = (Entry<String, ?>)i.next(); 278 String key = entry.getKey(); 279 Object values = entry.getValue(); 280 if (values instanceof String[]) { 281 result.put(key, (String[])values); 282 } else { 283 if (values != null) { 284 result.put(key, new String[] {values.toString()}); 285 } 286 } 287 } 288 return result; 289 } 290 291 /** 292 * Parses the parameters of the given request query part and creates a parameter map out of them.<p> 293 * 294 * Please note: This does not parse a full request URI/URL, only the query part that 295 * starts after the "?". For example, in the URI <code>/system/index.html?a=b&c=d</code>, 296 * the query part is <code>a=b&c=d</code>.<p> 297 * 298 * If the given String is empty, an empty map is returned.<p> 299 * 300 * @param query the query to parse 301 * @return the parameter map created from the query 302 */ 303 public static Map<String, String[]> createParameterMap(String query) { 304 305 return createParameterMap(query, false, null); 306 } 307 308 /** 309 * Parses the parameters of the given request query part, optionally decodes them, and creates a parameter map out of them.<p> 310 * 311 * Please note: This does not parse a full request URI/URL, only the query part that 312 * starts after the "?". For example, in the URI <code>/system/index.html?a=b&c=d</code>, 313 * the query part is <code>a=b&c=d</code>.<p> 314 * 315 * If the given String is empty, an empty map is returned.<p> 316 * 317 * @param query the query to parse 318 * @param decodeParameters a flag, indicating if the parameters should be decoded. 319 * @param encoding the character encoding used while decoding. If <code>null</code>, the default character encoding is used. 320 * @return the parameter map created from the query 321 */ 322 public static Map<String, String[]> createParameterMap(String query, boolean decodeParameters, String encoding) { 323 324 if (CmsStringUtil.isEmpty(query)) { 325 // empty query 326 return new HashMap<String, String[]>(); 327 } 328 if (query.charAt(0) == URL_DELIMITER.charAt(0)) { 329 // remove leading '?' if required 330 query = query.substring(1); 331 } 332 // cut along the different parameters 333 String[] params = CmsStringUtil.splitAsArray(query, PARAMETER_DELIMITER); 334 Map<String, String[]> parameters = new HashMap<String, String[]>(params.length); 335 for (int i = 0; i < params.length; i++) { 336 String key = null; 337 String value = null; 338 // get key and value, separated by a '=' 339 int pos = params[i].indexOf(PARAMETER_ASSIGNMENT); 340 if (pos > 0) { 341 key = params[i].substring(0, pos); 342 value = params[i].substring(pos + 1); 343 } else if (pos < 0) { 344 key = params[i]; 345 value = ""; 346 } 347 // adjust the key if it starts with "amp;" 348 // this happens when "&" is used instead of a simple "&" 349 if ((key != null) && (key.startsWith(AMP))) { 350 key = key.substring(AMP.length()); 351 } 352 // now make sure the values are of type String[] 353 if (key != null) { 354 if (decodeParameters) { 355 key = CmsEncoder.decode(key, encoding); 356 value = CmsEncoder.decode(value, encoding); 357 } 358 String[] values = parameters.get(key); 359 if (values == null) { 360 // this is the first value, create new array 361 values = new String[] {value}; 362 } else { 363 // append to the existing value array 364 String[] copy = new String[values.length + 1]; 365 System.arraycopy(values, 0, copy, 0, values.length); 366 copy[copy.length - 1] = value; 367 values = copy; 368 } 369 parameters.put(key, values); 370 } 371 } 372 return parameters; 373 } 374 375 /** 376 * Returns all parameters of the given request 377 * as a request parameter URL String, that is in the form <code>key1=value1&key2=value2</code> etc. 378 * 379 * The result will be encoded using the <code>{@link CmsEncoder#encode(String)}</code> function.<p> 380 * 381 * @param req the request to read the parameters from 382 * 383 * @return all initialized parameters of the given request as request parameter URL String 384 */ 385 public static String encodeParams(HttpServletRequest req) { 386 387 StringBuffer result = new StringBuffer(512); 388 Map<String, String[]> params = CmsCollectionsGenericWrapper.map(req.getParameterMap()); 389 Iterator<Map.Entry<String, String[]>> i = params.entrySet().iterator(); 390 while (i.hasNext()) { 391 Map.Entry<String, String[]> entry = i.next(); 392 String param = entry.getKey(); 393 String[] values = entry.getValue(); 394 for (int j = 0; j < values.length; j++) { 395 result.append(param); 396 result.append("="); 397 result.append(CmsEncoder.encode(values[j])); 398 if ((j + 1) < values.length) { 399 result.append("&"); 400 } 401 } 402 if (i.hasNext()) { 403 result.append("&"); 404 } 405 } 406 return CmsEncoder.encode(result.toString()); 407 } 408 409 /** 410 * Encodes the given URI, with all parameters from the given request appended.<p> 411 * 412 * The result will be encoded using the <code>{@link CmsEncoder#encode(String)}</code> function.<p> 413 * 414 * @param req the request where to read the parameters from 415 * @param uri the URI to encode 416 * @return the encoded URI, with all parameters from the given request appended 417 */ 418 public static String encodeParamsWithUri(String uri, HttpServletRequest req) { 419 420 String result; 421 String params = encodeParams(req); 422 if (CmsStringUtil.isNotEmpty(params)) { 423 result = CmsEncoder.encode(uri + "?") + params; 424 } else { 425 result = CmsEncoder.encode(uri); 426 } 427 return result; 428 } 429 430 /** 431 * Forwards the response to the given target, which may contain parameters appended like for example <code>?a=b&c=d</code>.<p> 432 * 433 * Please note: If possible, use <code>{@link #forwardRequest(String, Map, HttpServletRequest, HttpServletResponse)}</code> 434 * where the parameters are passed as a map, since the parsing of the parameters may introduce issues with encoding 435 * and is in general much less effective.<p> 436 * 437 * The parsing of parameters will likely fail for "large values" (e.g. full blown web forms with <textarea> 438 * elements etc. Use this method only if you know that the target will just contain up to 3 parameters which 439 * are relatively short and have no encoding or line break issues.<p> 440 * 441 * @param target the target to forward to (may contain parameters like <code>?a=b&c=d</code>) 442 * @param req the request to forward 443 * @param res the response to forward 444 * 445 * @throws IOException in case the forwarding fails 446 * @throws ServletException in case the forwarding fails 447 */ 448 public static void forwardRequest(String target, HttpServletRequest req, HttpServletResponse res) 449 throws IOException, ServletException { 450 451 // clear the current parameters 452 CmsUriSplitter uri = new CmsUriSplitter(target); 453 Map<String, String[]> params = createParameterMap(uri.getQuery()); 454 forwardRequest(uri.getPrefix(), params, req, res); 455 } 456 457 /** 458 * Forwards the response to the given target, with the provided parameter map.<p> 459 * 460 * The target URI must NOT have parameters appended like for example <code>?a=b&c=d</code>. 461 * The values in the provided map must be of type <code>String[]</code>. If required, use 462 * <code>{@link #createParameterMap(Map)}</code> before calling this method to make sure 463 * all values are actually of the required array type.<p> 464 * 465 * @param target the target to forward to (may NOT contain parameters like <code>?a=b&c=d</code>) 466 * @param params the parameter map (the values must be of type <code>String[]</code> 467 * @param req the request to forward 468 * @param res the response to forward 469 * 470 * @throws IOException in case the forwarding fails 471 * @throws ServletException in case the forwarding fails 472 */ 473 public static void forwardRequest( 474 String target, 475 Map<String, String[]> params, 476 HttpServletRequest req, 477 HttpServletResponse res) throws IOException, ServletException { 478 479 // cast the request back to a flex request so the parameter map can be accessed 480 CmsFlexRequest f_req = (CmsFlexRequest)req; 481 // set the parameters 482 f_req.setParameterMap(params); 483 // check for links "into" OpenCms, these may need the webapp name to be removed 484 String vfsPrefix = OpenCms.getStaticExportManager().getVfsPrefix(); 485 if (target.startsWith(vfsPrefix)) { 486 // remove VFS prefix (will also work for empty vfs prefix in ROOT webapp case with proxy rules) 487 target = target.substring(vfsPrefix.length()); 488 // append the servlet name 489 target = OpenCms.getSystemInfo().getServletPath() + target; 490 } 491 // forward the request 492 f_req.getRequestDispatcher(target).forward(f_req, res); 493 } 494 495 /** 496 * Returns a map with all request attributes.<p> 497 * 498 * @param req the request 499 * 500 * @return the attribute map 501 */ 502 public static Map<String, Object> getAtrributeMap(ServletRequest req) { 503 504 if (req instanceof CmsFlexRequest) { 505 return ((CmsFlexRequest)req).getAttributeMap(); 506 } 507 Map<String, Object> attrs = new HashMap<String, Object>(); 508 Enumeration<String> atrrEnum = CmsCollectionsGenericWrapper.enumeration(req.getAttributeNames()); 509 while (atrrEnum.hasMoreElements()) { 510 String key = atrrEnum.nextElement(); 511 Object value = req.getAttribute(key); 512 attrs.put(key, value); 513 } 514 return attrs; 515 } 516 517 /** 518 * Returns the value of the cookie with the given name.<p/> 519 * 520 * @param jsp the CmsJspActionElement to use 521 * @param name the name of the cookie 522 * 523 * @return the value of the cookie with the given name or null, if no cookie exists with the name 524 */ 525 public static String getCookieValue(CmsJspActionElement jsp, String name) { 526 527 Cookie[] cookies = jsp.getRequest().getCookies(); 528 return getCookieValue(cookies, name); 529 } 530 531 /** 532 * Gets the value of a specific cookie from an array of cookies.<p> 533 * 534 * @param cookies the cookie array 535 * @param name the name of the cookie we want 536 * 537 * @return the cookie value, or null if cookie with the given name wasn't found 538 */ 539 public static String getCookieValue(Cookie[] cookies, String name) { 540 541 for (int i = 0; (cookies != null) && (i < cookies.length); i++) { 542 if (name.equalsIgnoreCase(cookies[i].getName())) { 543 return cookies[i].getValue(); 544 } 545 } 546 return null; 547 } 548 549 /** 550 * Converts the given parameter map into an JSON object.<p> 551 * 552 * @param params the parameters map to convert 553 * 554 * @return the JSON representation of the given parameter map 555 */ 556 public static JSONObject getJsonParameterMap(Map<String, String[]> params) { 557 558 JSONObject result = new JSONObject(); 559 for (Map.Entry<String, String[]> entry : params.entrySet()) { 560 String paramKey = entry.getKey(); 561 JSONArray paramValue = new JSONArray(); 562 for (int i = 0, l = entry.getValue().length; i < l; i++) { 563 paramValue.put(entry.getValue()[i]); 564 } 565 try { 566 result.putOpt(paramKey, paramValue); 567 } catch (JSONException e) { 568 // should never happen 569 LOG.warn(e.getLocalizedMessage(), e); 570 } 571 } 572 return result; 573 } 574 575 /** 576 * Reads value from the request parameters, 577 * will return <code>null</code> if the value is not available or only white space.<p> 578 * 579 * The value of the request will also be decoded using <code>{@link CmsEncoder#decode(String)}</code> 580 * and also trimmed using <code>{@link String#trim()}</code>.<p> 581 * 582 * @param request the request to read the parameter from 583 * @param paramName the parameter name to read 584 * 585 * @return the request parameter value for the given parameter 586 */ 587 public static String getNotEmptyDecodedParameter(HttpServletRequest request, String paramName) { 588 589 String result = getNotEmptyParameter(request, paramName); 590 if (result != null) { 591 result = CmsEncoder.decode(result.trim()); 592 } 593 return result; 594 } 595 596 /** 597 * Reads value from the request parameters, 598 * will return <code>null</code> if the value is not available or only white space.<p> 599 * 600 * @param request the request to read the parameter from 601 * @param paramName the parameter name to read 602 * 603 * @return the request parameter value for the given parameter 604 */ 605 public static String getNotEmptyParameter(HttpServletRequest request, String paramName) { 606 607 String result = request.getParameter(paramName); 608 if (CmsStringUtil.isEmptyOrWhitespaceOnly(result)) { 609 result = null; 610 } 611 return result; 612 } 613 614 /** 615 * Converts the given JSON object into a valid parameter map.<p> 616 * 617 * @param params the JSON object to convert 618 * 619 * @return the parameter map from the given JSON object 620 */ 621 public static Map<String, String[]> getParameterMapFromJSON(JSONObject params) { 622 623 Map<String, String[]> result = new HashMap<String, String[]>(); 624 Iterator<String> itKeys = params.keys(); 625 while (itKeys.hasNext()) { 626 String key = itKeys.next(); 627 JSONArray paramValue = params.optJSONArray(key); 628 result.put(key, new String[paramValue.length()]); 629 for (int i = 0, l = paramValue.length(); i < l; i++) { 630 result.get(key)[i] = paramValue.optString(i); 631 } 632 } 633 return result; 634 } 635 636 /** 637 * Returns the link without parameters from a String that is formatted for a GET request.<p> 638 * 639 * @param url the URL to remove the parameters from 640 * @return the URL without any parameters 641 */ 642 public static String getRequestLink(String url) { 643 644 if (CmsStringUtil.isEmpty(url)) { 645 return null; 646 } 647 int pos = url.indexOf(URL_DELIMITER); 648 if (pos >= 0) { 649 return url.substring(0, pos); 650 } 651 return url; 652 653 } 654 655 /** 656 * Reads an object from the session of the given HTTP request.<p> 657 * 658 * A session will be initialized if the request does not currently have a session. 659 * As a result, the request will always have a session after this method has been called.<p> 660 * 661 * Will return <code>null</code> if no corresponding object is found in the session.<p> 662 * 663 * @param request the request to get the session from 664 * @param key the key of the object to read from the session 665 * @return the object received form the session, or <code>null</code> 666 */ 667 public static Object getSessionValue(HttpServletRequest request, String key) { 668 669 HttpSession session = request.getSession(true); 670 return session.getAttribute(key); 671 } 672 673 /** 674 * Parses a request of the form <code>multipart/form-data</code>. 675 * 676 * The result list will contain items of type <code>{@link FileItem}</code>. 677 * If the request is not of type <code>multipart/form-data</code>, then <code>null</code> is returned.<p> 678 * 679 * @param request the HTTP servlet request to parse 680 * 681 * @return the list of <code>{@link FileItem}</code> extracted from the multipart request, 682 * or <code>null</code> if the request was not of type <code>multipart/form-data</code> 683 */ 684 public static List<FileItem> readMultipartFileItems(HttpServletRequest request) { 685 686 if (!ServletFileUpload.isMultipartContent(request)) { 687 return null; 688 } 689 DiskFileItemFactory factory = new DiskFileItemFactory(); 690 // maximum size that will be stored in memory 691 factory.setSizeThreshold(4096); 692 // the location for saving data that is larger than getSizeThreshold() 693 factory.setRepository(new File(OpenCms.getSystemInfo().getPackagesRfsPath())); 694 ServletFileUpload fu = new ServletFileUpload(factory); 695 // set encoding to correctly handle special chars (e.g. in filenames) 696 fu.setHeaderEncoding(request.getCharacterEncoding()); 697 List<FileItem> result = new ArrayList<FileItem>(); 698 try { 699 List<FileItem> items = CmsCollectionsGenericWrapper.list(fu.parseRequest(request)); 700 if (items != null) { 701 result = items; 702 } 703 } catch (FileUploadException e) { 704 LOG.error(Messages.get().getBundle().key(Messages.LOG_PARSE_MULIPART_REQ_FAILED_0), e); 705 } 706 return result; 707 } 708 709 /** 710 * Creates a "standard" request parameter map from the values of a 711 * <code>multipart/form-data</code> request.<p> 712 * 713 * @param encoding the encoding to use when creating the values 714 * @param multiPartFileItems the list of parsed multi part file items 715 * 716 * @return a map containing all non-file request parameters 717 * 718 * @see #readMultipartFileItems(HttpServletRequest) 719 */ 720 public static Map<String, String[]> readParameterMapFromMultiPart( 721 String encoding, 722 List<FileItem> multiPartFileItems) { 723 724 Map<String, String[]> parameterMap = new HashMap<String, String[]>(); 725 Iterator<FileItem> i = multiPartFileItems.iterator(); 726 while (i.hasNext()) { 727 FileItem item = i.next(); 728 String name = item.getFieldName(); 729 String value = null; 730 if ((name != null) && (item.getName() == null)) { 731 // only put to map if current item is no file and not null 732 try { 733 value = item.getString(encoding); 734 } catch (UnsupportedEncodingException e) { 735 LOG.error(Messages.get().getBundle().key(Messages.LOG_ENC_MULTIPART_REQ_ERROR_0), e); 736 value = item.getString(); 737 } 738 if (parameterMap.containsKey(name)) { 739 740 // append value to parameter values array 741 String[] oldValues = parameterMap.get(name); 742 String[] newValues = new String[oldValues.length + 1]; 743 System.arraycopy(oldValues, 0, newValues, 0, oldValues.length); 744 newValues[oldValues.length] = value; 745 parameterMap.put(name, newValues); 746 747 } else { 748 parameterMap.put(name, new String[] {value}); 749 } 750 } 751 } 752 return parameterMap; 753 } 754 755 /** 756 * Redirects the response to the target link using a "301 - Moved Permanently" header.<p> 757 * 758 * This implementation will work only on JSP pages in OpenCms that use the default JSP loader implementation.<p> 759 * 760 * @param jsp the OpenCms JSP context 761 * @param target the target link 762 */ 763 public static void redirectPermanently(CmsJspActionElement jsp, String target) { 764 765 String newTarget = OpenCms.getLinkManager().substituteLink(jsp.getCmsObject(), target, null, true); 766 jsp.getRequest().setAttribute( 767 CmsRequestUtil.ATTRIBUTE_ERRORCODE, 768 new Integer(HttpServletResponse.SC_MOVED_PERMANENTLY)); 769 jsp.getResponse().setHeader(HEADER_CONNECTION, "close"); 770 try { 771 jsp.getResponse().sendRedirect(newTarget); 772 } catch (IOException e) { 773 LOG.error(Messages.get().getBundle().key(Messages.ERR_IOERROR_0), e); 774 // In case of an IOException, we send the redirect ourselves 775 jsp.getResponse().setHeader(HEADER_LOCATION, newTarget); 776 } 777 } 778 779 /** 780 * Redirects the response to the target link.<p> 781 * 782 * Use this method instead of {@link javax.servlet.http.HttpServletResponse#sendRedirect(java.lang.String)} 783 * to avoid relative links with secure sites (and issues with apache).<p> 784 * 785 * @param jsp the OpenCms JSP context 786 * @param target the target link 787 * 788 * @throws IOException if something goes wrong during redirection 789 */ 790 public static void redirectRequestSecure(CmsJspActionElement jsp, String target) throws IOException { 791 792 jsp.getResponse().sendRedirect(OpenCms.getLinkManager().substituteLink(jsp.getCmsObject(), target, null, true)); 793 } 794 795 /** 796 * Removes an object from the session of the given http request.<p> 797 * 798 * A session will be initialized if the request does not currently have a session. 799 * As a result, the request will always have a session after this method has been called.<p> 800 * 801 * @param request the request to get the session from 802 * @param key the key of the object to be removed from the session 803 */ 804 public static void removeSessionValue(HttpServletRequest request, String key) { 805 806 HttpSession session = request.getSession(true); 807 session.removeAttribute(key); 808 } 809 810 /** 811 * Sets the value of a specific cookie.<p> 812 * If no cookie exists with the value, a new cookie will be created. 813 * 814 * @param jsp the CmsJspActionElement to use 815 * @param name the name of the cookie 816 * @param value the value of the cookie 817 */ 818 public static void setCookieValue(CmsJspActionElement jsp, String name, String value) { 819 820 Cookie[] cookies = jsp.getRequest().getCookies(); 821 for (int i = 0; (cookies != null) && (i < cookies.length); i++) { 822 if (name.equalsIgnoreCase(cookies[i].getName())) { 823 cookies[i].setValue(value); 824 return; 825 } 826 } 827 Cookie cookie = new Cookie(name, value); 828 jsp.getResponse().addCookie(cookie); 829 } 830 831 /** 832 * Sets headers to the given response to prevent client side caching.<p> 833 * 834 * The following headers are set:<p> 835 * <code> 836 * Cache-Control: max-age=0<br> 837 * Cache-Control: must-revalidate<br> 838 * Pragma: no-cache 839 * </code> 840 * 841 * @param res the request where to set the no-cache headers 842 */ 843 public static void setNoCacheHeaders(HttpServletResponse res) { 844 845 res.setHeader(CmsRequestUtil.HEADER_CACHE_CONTROL, CmsRequestUtil.HEADER_VALUE_MAX_AGE + "0"); 846 res.addHeader(CmsRequestUtil.HEADER_CACHE_CONTROL, CmsRequestUtil.HEADER_VALUE_MUST_REVALIDATE); 847 res.addHeader(CmsRequestUtil.HEADER_CACHE_CONTROL, CmsRequestUtil.HEADER_VALUE_NO_CACHE); 848 res.addHeader(CmsRequestUtil.HEADER_CACHE_CONTROL, CmsRequestUtil.HEADER_VALUE_NO_STORE); 849 res.setHeader(CmsRequestUtil.HEADER_PRAGMA, CmsRequestUtil.HEADER_VALUE_NO_CACHE); 850 } 851 852 /** 853 * Adds an object to the session of the given HTTP request.<p> 854 * 855 * A session will be initialized if the request does not currently have a session. 856 * As a result, the request will always have a session after this method has been called.<p> 857 * 858 * @param request the request to get the session from 859 * @param key the key of the object to be stored in the session 860 * @param value the object to be stored in the session 861 */ 862 public static void setSessionValue(HttpServletRequest request, String key, Object value) { 863 864 HttpSession session = request.getSession(true); 865 session.setAttribute(key, value); 866 } 867}