This commit is contained in:
Shinsuke Sugaya 2014-07-31 00:00:40 +09:00
parent 5875db6899
commit 6f85901356
2 changed files with 256 additions and 0 deletions

View file

@ -0,0 +1,163 @@
package jp.sf.fess.filter;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.codec.DecoderException;
import org.apache.commons.codec.net.URLCodec;
import org.codelibs.core.util.StringUtil;
import org.seasar.extension.filter.EncodingFilter;
public class FessEncodingFilter extends EncodingFilter {
public static String ENCODING_MAP = "encoding-map";
protected Map<String, String> encodingMap = new ConcurrentHashMap<>();
protected String encoding;
protected ServletContext servletContext;
protected URLCodec urlCodec = new URLCodec();
@Override
public void init(final FilterConfig config) throws ServletException {
super.init(config);
servletContext = config.getServletContext();
encoding = config.getInitParameter(ENCODING);
if (encoding == null) {
encoding = DEFAULT_ENCODING;
}
// ex. sjis:Shift_JIS,eucjp:EUC-JP
final String value = config.getInitParameter(ENCODING_MAP);
if (StringUtil.isNotBlank(value)) {
final String[] encodingPairs = value.split(",");
for (final String pair : encodingPairs) {
final String[] encInfos = pair.trim().split(":");
if (encInfos.length == 2) {
encodingMap.put("/" + encInfos[0] + "/", encInfos[1]);
}
}
}
}
@Override
public void doFilter(final ServletRequest request,
final ServletResponse response, final FilterChain chain)
throws IOException, ServletException {
final HttpServletRequest req = (HttpServletRequest) request;
final String servletPath = req.getServletPath();
for (final Map.Entry<String, String> entry : encodingMap.entrySet()) {
final String path = entry.getKey();
if (servletPath.startsWith(path)) {
req.setCharacterEncoding(entry.getValue());
final StringBuilder locationBuf = new StringBuilder(1000);
final String contextPath = servletContext.getContextPath();
locationBuf.append(StringUtil.isBlank(contextPath) ? "/"
: contextPath);
locationBuf.append(servletPath.substring(path.length()));
boolean append = false;
final Map<String, String[]> parameterMap = new HashMap<>();
parameterMap.putAll(req.getParameterMap());
parameterMap.putAll(getParameterMapFromQueryString(req,
entry.getValue()));
for (final Map.Entry<String, String[]> paramEntry : parameterMap
.entrySet()) {
final String[] values = paramEntry.getValue();
if (values == null) {
continue;
}
final String key = paramEntry.getKey();
for (final String value : values) {
if (append) {
locationBuf.append('&');
} else {
locationBuf.append('?');
append = true;
}
locationBuf.append(urlCodec.encode(key, encoding));
locationBuf.append('=');
locationBuf.append(urlCodec.encode(value, encoding));
}
}
final HttpServletResponse res = (HttpServletResponse) response;
res.sendRedirect(locationBuf.toString());
return;
}
}
super.doFilter(request, response, chain);
}
protected Map<String, String[]> getParameterMapFromQueryString(
final HttpServletRequest request, final String enc)
throws IOException {
final String queryString = request.getQueryString();
if (StringUtil.isNotBlank(queryString)) {
return parseQueryString(queryString, enc);
} else {
return Collections.emptyMap();
}
}
protected Map<String, String[]> parseQueryString(final String queryString,
final String enc) throws IOException {
final Map<String, List<String>> paramListMap = new HashMap<>();
final String[] pairs = queryString.split("&");
try {
for (final String pair : pairs) {
final int pos = pair.indexOf('=');
if (pos >= 0) {
final String key = urlCodec.decode(pair.substring(0, pos),
enc);
List<String> list = paramListMap.get(key);
if (list == null) {
list = new ArrayList<>();
paramListMap.put(key, list);
}
if (pos + 1 < pair.length()) {
list.add(urlCodec.decode(pair.substring(pos + 1), enc));
} else {
list.add(StringUtil.EMPTY);
}
} else {
final String key = urlCodec.decode(pair, enc);
List<String> list = paramListMap.get(key);
if (list == null) {
list = new ArrayList<>();
paramListMap.put(key, list);
}
list.add(StringUtil.EMPTY);
}
}
} catch (DecoderException e) {
throw new IOException(e);
}
final Map<String, String[]> paramMap = new HashMap<>(
paramListMap.size());
for (final Map.Entry<String, List<String>> entry : paramListMap
.entrySet()) {
final List<String> list = entry.getValue();
paramMap.put(entry.getKey(), list.toArray(new String[list.size()]));
}
return paramMap;
}
}

View file

@ -0,0 +1,93 @@
/*
* Copyright 2009-2014 the CodeLibs Project and the Others.
*
* 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 jp.sf.fess.filter;
import java.io.IOException;
import java.util.Map;
import org.seasar.extension.unit.S2TestCase;
public class FessEncodingFilterTest extends S2TestCase {
public void test_normal() throws IOException {
FessEncodingFilter filter = new FessEncodingFilter();
Map<String, String[]> paramMap;
paramMap = filter.parseQueryString("a=1", "UTF-8");
assertEquals(1, paramMap.size());
assertEquals("1", paramMap.get("a")[0]);
paramMap = filter.parseQueryString("a=1&b=2", "UTF-8");
assertEquals(2, paramMap.size());
assertEquals("1", paramMap.get("a")[0]);
assertEquals("2", paramMap.get("b")[0]);
paramMap = filter.parseQueryString("a=111&b=222&c=333", "UTF-8");
assertEquals(3, paramMap.size());
assertEquals("111", paramMap.get("a")[0]);
assertEquals("222", paramMap.get("b")[0]);
assertEquals("333", paramMap.get("c")[0]);
paramMap = filter.parseQueryString("a=1&b=2&c=3&a=2", "UTF-8");
assertEquals(3, paramMap.size());
assertEquals("1", paramMap.get("a")[0]);
assertEquals("2", paramMap.get("a")[1]);
assertEquals("2", paramMap.get("b")[0]);
assertEquals("3", paramMap.get("c")[0]);
}
public void test_missing() throws IOException {
FessEncodingFilter filter = new FessEncodingFilter();
Map<String, String[]> paramMap;
paramMap = filter.parseQueryString("a=", "UTF-8");
assertEquals(1, paramMap.size());
assertEquals("", paramMap.get("a")[0]);
paramMap = filter.parseQueryString("a", "UTF-8");
assertEquals(1, paramMap.size());
assertEquals("", paramMap.get("a")[0]);
paramMap = filter.parseQueryString("=1", "UTF-8");
assertEquals(1, paramMap.size());
assertEquals("1", paramMap.get("")[0]);
paramMap = filter.parseQueryString("=", "UTF-8");
assertEquals(1, paramMap.size());
assertEquals("", paramMap.get("")[0]);
}
public void test_decode() throws IOException {
FessEncodingFilter filter = new FessEncodingFilter();
Map<String, String[]> paramMap;
paramMap = filter.parseQueryString("a=%E3%83%86%E3%82%B9%E3%83%88",
"UTF-8");
assertEquals(1, paramMap.size());
assertEquals("テスト", paramMap.get("a")[0]);
paramMap = filter.parseQueryString("a=%A5%C6%A5%B9%A5%C8", "EUC-JP");
assertEquals(1, paramMap.size());
assertEquals("テスト", paramMap.get("a")[0]);
paramMap = filter.parseQueryString("a=%83e%83X%83g", "Shift_JIS");
assertEquals(1, paramMap.size());
assertEquals("テスト", paramMap.get("a")[0]);
}
}