1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.codelibs.fess.filter;
17
18 import java.io.IOException;
19 import java.util.ArrayList;
20 import java.util.Collections;
21 import java.util.HashMap;
22 import java.util.List;
23 import java.util.Map;
24 import java.util.concurrent.ConcurrentHashMap;
25
26 import javax.servlet.Filter;
27 import javax.servlet.FilterChain;
28 import javax.servlet.FilterConfig;
29 import javax.servlet.ServletContext;
30 import javax.servlet.ServletException;
31 import javax.servlet.ServletRequest;
32 import javax.servlet.ServletResponse;
33 import javax.servlet.http.HttpServletRequest;
34 import javax.servlet.http.HttpServletResponse;
35
36 import org.apache.commons.codec.DecoderException;
37 import org.apache.commons.codec.net.URLCodec;
38 import org.codelibs.core.lang.StringUtil;
39 import org.lastaflute.web.servlet.filter.LastaPrepareFilter;
40
41 public class EncodingFilter implements Filter {
42 public static final String ENCODING_MAP = "encodingRules";
43
44 protected Map<String, String> encodingMap = new ConcurrentHashMap<>();
45
46 protected String encoding;
47
48 protected ServletContext servletContext;
49
50 protected URLCodec urlCodec = new URLCodec();
51
52 @Override
53 public void init(final FilterConfig config) throws ServletException {
54 servletContext = config.getServletContext();
55
56 encoding = config.getInitParameter(LastaPrepareFilter.ENCODING_KEY);
57 if (encoding == null) {
58 encoding = LastaPrepareFilter.DEFAULT_ENCODING;
59 }
60
61
62 final String value = config.getInitParameter(ENCODING_MAP);
63 if (StringUtil.isNotBlank(value)) {
64 final String[] encodingPairs = value.split(",");
65 for (final String pair : encodingPairs) {
66 final String[] encInfos = pair.trim().split(":");
67 if (encInfos.length == 2) {
68 encodingMap.put("/" + encInfos[0] + "/", encInfos[1]);
69 }
70 }
71 }
72 }
73
74 @Override
75 public void doFilter(final ServletRequest request, final ServletResponse response, final FilterChain chain)
76 throws IOException, ServletException {
77 final HttpServletRequest req = (HttpServletRequest) request;
78 final String servletPath = req.getServletPath();
79 for (final Map.Entry<String, String> entry : encodingMap.entrySet()) {
80 final String path = entry.getKey();
81 if (servletPath.startsWith(path)) {
82 req.setCharacterEncoding(entry.getValue());
83 final StringBuilder locationBuf = new StringBuilder(1000);
84 final String contextPath = servletContext.getContextPath();
85 if (StringUtil.isNotBlank(contextPath) && !"/".equals(contextPath)) {
86 locationBuf.append(contextPath);
87 }
88 locationBuf.append('/');
89 locationBuf.append(servletPath.substring(path.length()));
90 boolean append = false;
91 final Map<String, String[]> parameterMap = new HashMap<>(req.getParameterMap());
92 parameterMap.putAll(getParameterMapFromQueryString(req, entry.getValue()));
93 for (final Map.Entry<String, String[]> paramEntry : parameterMap.entrySet()) {
94 final String[] values = paramEntry.getValue();
95 if (values == null) {
96 continue;
97 }
98 final String key = paramEntry.getKey();
99 for (final String value : values) {
100 if (append) {
101 locationBuf.append('&');
102 } else {
103 locationBuf.append('?');
104 append = true;
105 }
106 locationBuf.append(urlCodec.encode(key, encoding));
107 locationBuf.append('=');
108 locationBuf.append(urlCodec.encode(value, encoding));
109 }
110
111 }
112 final HttpServletResponse res = (HttpServletResponse) response;
113 res.sendRedirect(locationBuf.toString());
114 return;
115 }
116 }
117
118 chain.doFilter(request, response);
119 }
120
121 protected Map<String, String[]> getParameterMapFromQueryString(final HttpServletRequest request, final String enc) throws IOException {
122 final String queryString = request.getQueryString();
123 if (StringUtil.isNotBlank(queryString)) {
124 return parseQueryString(queryString, enc);
125 }
126 return Collections.emptyMap();
127 }
128
129 protected Map<String, String[]> parseQueryString(final String queryString, final String enc) throws IOException {
130 final Map<String, List<String>> paramListMap = new HashMap<>();
131 final String[] pairs = queryString.split("&");
132 try {
133 for (final String pair : pairs) {
134 final int pos = pair.indexOf('=');
135 if (pos >= 0) {
136 final String key = urlCodec.decode(pair.substring(0, pos), enc);
137 List<String> list = paramListMap.get(key);
138 if (list == null) {
139 list = new ArrayList<>();
140 paramListMap.put(key, list);
141 }
142 if (pos + 1 < pair.length()) {
143 list.add(urlCodec.decode(pair.substring(pos + 1), enc));
144 } else {
145 list.add(StringUtil.EMPTY);
146 }
147 } else {
148 final String key = urlCodec.decode(pair, enc);
149 List<String> list = paramListMap.get(key);
150 if (list == null) {
151 list = new ArrayList<>();
152 paramListMap.put(key, list);
153 }
154 list.add(StringUtil.EMPTY);
155 }
156 }
157 } catch (final DecoderException e) {
158 throw new IOException(e);
159 }
160
161 final Map<String, String[]> paramMap = new HashMap<>(paramListMap.size());
162 for (final Map.Entry<String, List<String>> entry : paramListMap.entrySet()) {
163 final List<String> list = entry.getValue();
164 paramMap.put(entry.getKey(), list.toArray(new String[list.size()]));
165 }
166 return paramMap;
167 }
168
169 @Override
170 public void destroy() {
171
172 }
173 }