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) throws IOException,
76 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<>();
92 parameterMap.putAll(req.getParameterMap());
93 parameterMap.putAll(getParameterMapFromQueryString(req, entry.getValue()));
94 for (final Map.Entry<String, String[]> paramEntry : parameterMap.entrySet()) {
95 final String[] values = paramEntry.getValue();
96 if (values == null) {
97 continue;
98 }
99 final String key = paramEntry.getKey();
100 for (final String value : values) {
101 if (append) {
102 locationBuf.append('&');
103 } else {
104 locationBuf.append('?');
105 append = true;
106 }
107 locationBuf.append(urlCodec.encode(key, encoding));
108 locationBuf.append('=');
109 locationBuf.append(urlCodec.encode(value, encoding));
110 }
111
112 }
113 final HttpServletResponse res = (HttpServletResponse) response;
114 res.sendRedirect(locationBuf.toString());
115 return;
116 }
117 }
118
119 chain.doFilter(request, response);
120 }
121
122 protected Map<String, String[]> getParameterMapFromQueryString(final HttpServletRequest request, final String enc) throws IOException {
123 final String queryString = request.getQueryString();
124 if (StringUtil.isNotBlank(queryString)) {
125 return parseQueryString(queryString, enc);
126 } else {
127 return Collections.emptyMap();
128 }
129 }
130
131 protected Map<String, String[]> parseQueryString(final String queryString, final String enc) throws IOException {
132 final Map<String, List<String>> paramListMap = new HashMap<>();
133 final String[] pairs = queryString.split("&");
134 try {
135 for (final String pair : pairs) {
136 final int pos = pair.indexOf('=');
137 if (pos >= 0) {
138 final String key = urlCodec.decode(pair.substring(0, pos), enc);
139 List<String> list = paramListMap.get(key);
140 if (list == null) {
141 list = new ArrayList<>();
142 paramListMap.put(key, list);
143 }
144 if (pos + 1 < pair.length()) {
145 list.add(urlCodec.decode(pair.substring(pos + 1), enc));
146 } else {
147 list.add(StringUtil.EMPTY);
148 }
149 } else {
150 final String key = urlCodec.decode(pair, enc);
151 List<String> list = paramListMap.get(key);
152 if (list == null) {
153 list = new ArrayList<>();
154 paramListMap.put(key, list);
155 }
156 list.add(StringUtil.EMPTY);
157 }
158 }
159 } catch (final DecoderException e) {
160 throw new IOException(e);
161 }
162
163 final Map<String, String[]> paramMap = new HashMap<>(paramListMap.size());
164 for (final Map.Entry<String, List<String>> entry : paramListMap.entrySet()) {
165 final List<String> list = entry.getValue();
166 paramMap.put(entry.getKey(), list.toArray(new String[list.size()]));
167 }
168 return paramMap;
169 }
170
171 @Override
172 public void destroy() {
173
174 }
175 }