| /* |
| * Copyright (c) 1997-2018 Oracle and/or its affiliates. All rights reserved. |
| * Copyright 2004 The Apache Software Foundation |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| package org.apache.naming; |
| |
| import java.nio.charset.Charset; |
| import java.nio.charset.UnsupportedCharsetException; |
| import org.glassfish.grizzly.utils.Charsets; |
| |
| /** |
| * Utility methods originally defined in org.apache.catalina.util.RequestUtil |
| * and moved here in order to become accessible to code in web-naming and |
| * war-util. |
| */ |
| |
| public final class Util { |
| |
| /** |
| * Normalize a relative URI path that may have relative values ("/./", |
| * "/../", and so on ) it it. <strong>WARNING</strong> - This method is |
| * useful only for normalizing application-generated paths. It does not |
| * try to perform security checks for malicious input. |
| * |
| * @param path Relative path to be normalized |
| * @param replaceBackSlash Should '\\' be replaced with '/' |
| */ |
| public static String normalize(String path, boolean replaceBackSlash) { |
| if (path == null) |
| return null; |
| |
| // Create a place for the normalized path |
| String normalized = path; |
| |
| if (replaceBackSlash && normalized.indexOf('\\') >= 0) |
| normalized = normalized.replace('\\', '/'); |
| |
| if (normalized.equals("/.")) |
| return "/"; |
| |
| // Add a leading "/" if necessary |
| if (!normalized.startsWith("/")) |
| normalized = "/" + normalized; |
| |
| // Resolve occurrences of "//" in the normalized path |
| while (true) { |
| int index = normalized.indexOf("//"); |
| if (index < 0) |
| break; |
| normalized = normalized.substring(0, index) + |
| normalized.substring(index + 1); |
| } |
| |
| // Resolve occurrences of "/./" in the normalized path |
| while (true) { |
| int index = normalized.indexOf("/./"); |
| if (index < 0) |
| break; |
| normalized = normalized.substring(0, index) + |
| normalized.substring(index + 2); |
| } |
| |
| // Resolve occurrences of "/../" in the normalized path |
| while (true) { |
| int index = normalized.indexOf("/../"); |
| if (index < 0) |
| break; |
| if (index == 0) |
| return (null); // Trying to go outside our context |
| int index2 = normalized.lastIndexOf('/', index - 1); |
| normalized = normalized.substring(0, index2) + |
| normalized.substring(index + 3); |
| } |
| |
| // Return the normalized path that we have completed |
| return (normalized); |
| } |
| |
| /** |
| * Decode and return the specified URL-encoded String. |
| * When the byte array is converted to a string, the system default |
| * character encoding is used... This may be different than some other |
| * servers. |
| * |
| * @param str The url-encoded string |
| * |
| * @exception IllegalArgumentException if a '%' character is not followed |
| * by a valid 2-digit hexadecimal number |
| */ |
| public static String urlDecode(String str) { |
| return urlDecode(str, null); |
| } |
| |
| /** |
| * Decode and return the specified URL-encoded String. |
| * |
| * @param str The url-encoded string |
| * @param enc The encoding to use; if null, the default encoding is used |
| * @exception IllegalArgumentException if a '%' character is not followed |
| * by a valid 2-digit hexadecimal number |
| */ |
| public static String urlDecode(String str, String enc) { |
| |
| if (str == null) |
| return (null); |
| |
| // use the specified encoding to extract bytes out of the |
| // given string so that the encoding is not lost. If an |
| // encoding is not specified, let it use platform default |
| byte[] bytes = null; |
| try { |
| if (enc == null) { |
| bytes = str.getBytes(Charset.defaultCharset()); |
| } else { |
| bytes = str.getBytes(Charsets.lookupCharset(enc)); |
| } |
| } catch (UnsupportedCharsetException uee) {} |
| |
| return urlDecode(bytes, enc); |
| |
| } |
| |
| /** |
| * Decode and return the specified URL-encoded byte array. |
| * |
| * @param bytes The url-encoded byte array |
| * @exception IllegalArgumentException if a '%' character is not followed |
| * by a valid 2-digit hexadecimal number |
| */ |
| public static String urlDecode(byte[] bytes) { |
| return urlDecode(bytes, null); |
| } |
| |
| /** |
| * Decode and return the specified URL-encoded byte array. |
| * |
| * @param bytes The url-encoded byte array |
| * @param enc The encoding to use; if null, the default encoding is used |
| * @exception IllegalArgumentException if a '%' character is not followed |
| * by a valid 2-digit hexadecimal number |
| */ |
| public static String urlDecode(byte[] bytes, String enc) { |
| |
| if (bytes == null) |
| return (null); |
| |
| int len = bytes.length; |
| int ix = 0; |
| int ox = 0; |
| while (ix < len) { |
| byte b = bytes[ix++]; // Get byte to test |
| if (b == '+') { |
| b = (byte)' '; |
| } else if (b == '%') { |
| b = (byte) ((convertHexDigit(bytes[ix++]) << 4) |
| + convertHexDigit(bytes[ix++])); |
| } |
| bytes[ox++] = b; |
| } |
| if (enc != null) { |
| try { |
| return new String(bytes, 0, ox, Charsets.lookupCharset(enc)); |
| } catch (Exception e) { |
| e.printStackTrace(); |
| } |
| } |
| return new String(bytes, 0, ox, Charset.defaultCharset()); |
| |
| } |
| |
| /** |
| * Convert a byte character value to hexidecimal digit value. |
| * |
| * @param b the character value byte |
| */ |
| public static byte convertHexDigit( byte b ) { |
| if ((b >= '0') && (b <= '9')) return (byte)(b - '0'); |
| if ((b >= 'a') && (b <= 'f')) return (byte)(b - 'a' + 10); |
| if ((b >= 'A') && (b <= 'F')) return (byte)(b - 'A' + 10); |
| return 0; |
| } |
| |
| } |