Skip to content

Commit

Permalink
WW-4507 - clone Tomcat UDecoder and use it for in query string handling
Browse files Browse the repository at this point in the history
  • Loading branch information
rgielen committed Jan 14, 2016
1 parent c6750c1 commit 5421930
Show file tree
Hide file tree
Showing 14 changed files with 4,262 additions and 10 deletions.
Expand Up @@ -26,9 +26,9 @@
import com.opensymphony.xwork2.util.logging.Logger;
import com.opensymphony.xwork2.util.logging.LoggerFactory;
import org.apache.struts2.StrutsConstants;
import org.apache.struts2.util.URLDecoderUtil;

import javax.servlet.http.HttpServletRequest;
import java.net.URLDecoder;
import java.util.HashMap;
import java.util.StringTokenizer;

Expand Down Expand Up @@ -133,10 +133,10 @@ public ActionMapping getMapping(HttpServletRequest request, ConfigurationManager

while (st.hasMoreTokens()) {
if (isNameTok) {
paramName = URLDecoder.decode(st.nextToken(), "UTF-8");
paramName = URLDecoderUtil.decode(st.nextToken(), "UTF-8");
isNameTok = false;
} else {
paramValue = URLDecoder.decode(st.nextToken(), "UTF-8");
paramValue = URLDecoderUtil.decode(st.nextToken(), "UTF-8");

if ((paramName != null) && (paramName.length() > 0)) {
parameters.put(paramName, paramValue);
Expand Down
Expand Up @@ -25,9 +25,9 @@
import com.opensymphony.xwork2.util.logging.Logger;
import com.opensymphony.xwork2.util.logging.LoggerFactory;
import org.apache.struts2.RequestUtils;
import org.apache.struts2.util.URLDecoderUtil;

import javax.servlet.http.HttpServletRequest;
import java.net.URLDecoder;
import java.util.HashMap;
import java.util.Map;
import java.util.StringTokenizer;
Expand Down Expand Up @@ -67,10 +67,10 @@ public ActionMapping getMapping(HttpServletRequest request, ConfigurationManager

while (st.hasMoreTokens()) {
if (isNameTok) {
paramName = URLDecoder.decode(st.nextToken(), "UTF-8");
paramName = URLDecoderUtil.decode(st.nextToken(), "UTF-8");
isNameTok = false;
} else {
paramValue = URLDecoder.decode(st.nextToken(), "UTF-8");
paramValue = URLDecoderUtil.decode(st.nextToken(), "UTF-8");

if ((paramName != null) && (paramName.length() > 0)) {
parameters.put(paramName, paramValue);
Expand Down
22 changes: 22 additions & 0 deletions core/src/main/java/org/apache/struts2/util/URLDecoderUtil.java
@@ -0,0 +1,22 @@
package org.apache.struts2.util;

import org.apache.struts2.util.tomcat.buf.UDecoder;

/**
* URLDecoderUtil serves as a facade for a correct URL decoding implementation.
* As of Struts 2.3.25 it uses Tomcat URLDecoder functionality rather than the one found in java.io.
*/
public class URLDecoderUtil {

/**
* Decodes a <code>x-www-form-urlencoded</code> string.
* @param sequence the String to decode
* @param charset The name of a supported character encoding.
* @return the newly decoded <code>String</code>
* @exception IllegalArgumentException If the encoding is not valid
*/
public static String decode(String sequence, String charset) {
return UDecoder.URLDecode(sequence, charset);
}

}
255 changes: 255 additions & 0 deletions core/src/main/java/org/apache/struts2/util/tomcat/buf/Ascii.java
@@ -0,0 +1,255 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You 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.struts2.util.tomcat.buf;

/**
* This class implements some basic ASCII character handling functions.
*
* @author dac@eng.sun.com
* @author James Todd [gonzo@eng.sun.com]
*/
public final class Ascii {
/*
* Character translation tables.
*/

private static final byte[] toUpper = new byte[256];
private static final byte[] toLower = new byte[256];

/*
* Character type tables.
*/

private static final boolean[] isAlpha = new boolean[256];
private static final boolean[] isUpper = new boolean[256];
private static final boolean[] isLower = new boolean[256];
private static final boolean[] isWhite = new boolean[256];
private static final boolean[] isDigit = new boolean[256];

private static final long OVERFLOW_LIMIT = Long.MAX_VALUE / 10;

/*
* Initialize character translation and type tables.
*/
static {
for (int i = 0; i < 256; i++) {
toUpper[i] = (byte)i;
toLower[i] = (byte)i;
}

for (int lc = 'a'; lc <= 'z'; lc++) {
int uc = lc + 'A' - 'a';

toUpper[lc] = (byte)uc;
toLower[uc] = (byte)lc;
isAlpha[lc] = true;
isAlpha[uc] = true;
isLower[lc] = true;
isUpper[uc] = true;
}

isWhite[ ' '] = true;
isWhite['\t'] = true;
isWhite['\r'] = true;
isWhite['\n'] = true;
isWhite['\f'] = true;
isWhite['\b'] = true;

for (int d = '0'; d <= '9'; d++) {
isDigit[d] = true;
}
}

/**
* Returns the upper case equivalent of the specified ASCII character.
* @deprecated Unused. Will be removed in Tomcat 8.0.x onwards.
*/
@Deprecated
public static int toUpper(int c) {
return toUpper[c & 0xff] & 0xff;
}

/**
* Returns the lower case equivalent of the specified ASCII character.
*/

public static int toLower(int c) {
return toLower[c & 0xff] & 0xff;
}

/**
* Returns true if the specified ASCII character is upper or lower case.
* @deprecated Unused. Will be removed in Tomcat 8.0.x onwards.
*/
@Deprecated
public static boolean isAlpha(int c) {
return isAlpha[c & 0xff];
}

/**
* Returns true if the specified ASCII character is upper case.
* @deprecated Unused. Will be removed in Tomcat 8.0.x onwards.
*/
@Deprecated
public static boolean isUpper(int c) {
return isUpper[c & 0xff];
}

/**
* Returns true if the specified ASCII character is lower case.
* @deprecated Unused. Will be removed in Tomcat 8.0.x onwards.
*/
@Deprecated
public static boolean isLower(int c) {
return isLower[c & 0xff];
}

/**
* Returns true if the specified ASCII character is white space.
* @deprecated Unused. Will be removed in Tomcat 8.0.x onwards.
*/
@Deprecated
public static boolean isWhite(int c) {
return isWhite[c & 0xff];
}

/**
* Returns true if the specified ASCII character is a digit.
*/

public static boolean isDigit(int c) {
return isDigit[c & 0xff];
}

/**
* Parses an unsigned integer from the specified subarray of bytes.
* @param b the bytes to parse
* @param off the start offset of the bytes
* @param len the length of the bytes
* @exception NumberFormatException if the integer format was invalid
* @deprecated Unused. Will be removed in Tomcat 8.0.x onwards.
*/
@Deprecated
public static int parseInt(byte[] b, int off, int len)
throws NumberFormatException
{
int c;

if (b == null || len <= 0 || !isDigit(c = b[off++])) {
throw new NumberFormatException();
}

int n = c - '0';

while (--len > 0) {
if (!isDigit(c = b[off++])) {
throw new NumberFormatException();
}
n = n * 10 + c - '0';
}

return n;
}

/**
* @deprecated Unused. Will be removed in Tomcat 8.0.x onwards.
*/
@Deprecated
public static int parseInt(char[] b, int off, int len)
throws NumberFormatException
{
int c;

if (b == null || len <= 0 || !isDigit(c = b[off++])) {
throw new NumberFormatException();
}

int n = c - '0';

while (--len > 0) {
if (!isDigit(c = b[off++])) {
throw new NumberFormatException();
}
n = n * 10 + c - '0';
}

return n;
}

/**
* Parses an unsigned long from the specified subarray of bytes.
* @param b the bytes to parse
* @param off the start offset of the bytes
* @param len the length of the bytes
* @exception NumberFormatException if the long format was invalid
*/
public static long parseLong(byte[] b, int off, int len)
throws NumberFormatException
{
int c;

if (b == null || len <= 0 || !isDigit(c = b[off++])) {
throw new NumberFormatException();
}

long n = c - '0';
while (--len > 0) {
if (isDigit(c = b[off++]) &&
(n < OVERFLOW_LIMIT || (n == OVERFLOW_LIMIT && (c - '0') < 8))) {
n = n * 10 + c - '0';
} else {
throw new NumberFormatException();
}
}

return n;
}

/**
* @deprecated Unused. Will be removed in Tomcat 8.0.x onwards.
*/
@Deprecated
public static long parseLong(char[] b, int off, int len)
throws NumberFormatException
{
int c;

if (b == null || len <= 0 || !isDigit(c = b[off++])) {
throw new NumberFormatException();
}

long n = c - '0';
long m;

while (--len > 0) {
if (!isDigit(c = b[off++])) {
throw new NumberFormatException();
}
m = n * 10 + c - '0';

if (m < n) {
// Overflow
throw new NumberFormatException();
} else {
n = m;
}
}

return n;
}

}

0 comments on commit 5421930

Please sign in to comment.