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 org.apache.commons.codec.DecoderException;
27 import org.apache.commons.codec.net.URLCodec;
28 import org.codelibs.core.lang.StringUtil;
29 import org.lastaflute.web.servlet.filter.LastaPrepareFilter;
30
31 import jakarta.servlet.Filter;
32 import jakarta.servlet.FilterChain;
33 import jakarta.servlet.FilterConfig;
34 import jakarta.servlet.ServletContext;
35 import jakarta.servlet.ServletException;
36 import jakarta.servlet.ServletRequest;
37 import jakarta.servlet.ServletResponse;
38 import jakarta.servlet.http.HttpServletRequest;
39 import jakarta.servlet.http.HttpServletResponse;
40
41
42
43
44
45
46
47
48
49 public class EncodingFilter implements Filter {
50
51 public static final String ENCODING_MAP = "encodingRules";
52
53
54 protected Map<String, String> encodingMap = new ConcurrentHashMap<>();
55
56
57 protected String encoding;
58
59
60 protected ServletContext servletContext;
61
62
63 protected URLCodec urlCodec = new URLCodec();
64
65
66
67
68 public EncodingFilter() {
69
70 }
71
72
73
74
75
76
77
78
79 @Override
80 public void init(final FilterConfig config) throws ServletException {
81 servletContext = config.getServletContext();
82
83 encoding = config.getInitParameter(LastaPrepareFilter.ENCODING_KEY);
84 if (encoding == null) {
85 encoding = LastaPrepareFilter.DEFAULT_ENCODING;
86 }
87
88
89 final String value = config.getInitParameter(ENCODING_MAP);
90 if (StringUtil.isNotBlank(value)) {
91 final String[] encodingPairs = value.split(",");
92 for (final String pair : encodingPairs) {
93 final String[] encInfos = pair.trim().split(":");
94 if (encInfos.length == 2) {
95 encodingMap.put("/" + encInfos[0] + "/", encInfos[1]);
96 }
97 }
98 }
99 }
100
101
102
103
104
105
106
107
108
109
110
111
112 @Override
113 public void doFilter(final ServletRequest request, final ServletResponse response, final FilterChain chain)
114 throws IOException, ServletException {
115 final HttpServletRequest req = (HttpServletRequest) request;
116 final String servletPath = req.getServletPath();
117 for (final Map.Entry<String, String> entry : encodingMap.entrySet()) {
118 final String path = entry.getKey();
119 if (servletPath.startsWith(path)) {
120 req.setCharacterEncoding(entry.getValue());
121 final StringBuilder locationBuf = new StringBuilder(1000);
122 final String contextPath = servletContext.getContextPath();
123 if (StringUtil.isNotBlank(contextPath) && !"/".equals(contextPath)) {
124 locationBuf.append(contextPath);
125 }
126 locationBuf.append('/');
127 locationBuf.append(servletPath.substring(path.length()));
128 boolean append = false;
129 final Map<String, String[]> parameterMap = new HashMap<>(req.getParameterMap());
130 parameterMap.putAll(getParameterMapFromQueryString(req, entry.getValue()));
131 for (final Map.Entry<String, String[]> paramEntry : parameterMap.entrySet()) {
132 final String[] values = paramEntry.getValue();
133 if (values == null) {
134 continue;
135 }
136 final String key = paramEntry.getKey();
137 for (final String value : values) {
138 if (append) {
139 locationBuf.append('&');
140 } else {
141 locationBuf.append('?');
142 append = true;
143 }
144 locationBuf.append(urlCodec.encode(key, encoding));
145 locationBuf.append('=');
146 locationBuf.append(urlCodec.encode(value, encoding));
147 }
148
149 }
150 final HttpServletResponse res = (HttpServletResponse) response;
151 res.sendRedirect(locationBuf.toString());
152 return;
153 }
154 }
155
156 chain.doFilter(request, response);
157 }
158
159
160
161
162
163
164
165
166
167
168 protected Map<String, String[]> getParameterMapFromQueryString(final HttpServletRequest request, final String enc) throws IOException {
169 final String queryString = request.getQueryString();
170 if (StringUtil.isNotBlank(queryString)) {
171 return parseQueryString(queryString, enc);
172 }
173 return Collections.emptyMap();
174 }
175
176
177
178
179
180
181
182
183
184
185 protected Map<String, String[]> parseQueryString(final String queryString, final String enc) throws IOException {
186 final Map<String, List<String>> paramListMap = new HashMap<>();
187 final String[] pairs = queryString.split("&");
188 try {
189 for (final String pair : pairs) {
190 final int pos = pair.indexOf('=');
191 if (pos >= 0) {
192 final String key = urlCodec.decode(pair.substring(0, pos), enc);
193 List<String> list = paramListMap.get(key);
194 if (list == null) {
195 list = new ArrayList<>();
196 paramListMap.put(key, list);
197 }
198 if (pos + 1 < pair.length()) {
199 list.add(urlCodec.decode(pair.substring(pos + 1), enc));
200 } else {
201 list.add(StringUtil.EMPTY);
202 }
203 } else {
204 final String key = urlCodec.decode(pair, enc);
205 List<String> list = paramListMap.get(key);
206 if (list == null) {
207 list = new ArrayList<>();
208 paramListMap.put(key, list);
209 }
210 list.add(StringUtil.EMPTY);
211 }
212 }
213 } catch (final DecoderException e) {
214 throw new IOException(e);
215 }
216
217 final Map<String, String[]> paramMap = new HashMap<>(paramListMap.size());
218 for (final Map.Entry<String, List<String>> entry : paramListMap.entrySet()) {
219 final List<String> list = entry.getValue();
220 paramMap.put(entry.getKey(), list.toArray(new String[list.size()]));
221 }
222 return paramMap;
223 }
224
225
226
227
228
229 @Override
230 public void destroy() {
231
232 }
233 }