1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 package org.apache.struts2.views.util;
23
24 import java.io.UnsupportedEncodingException;
25 import java.net.URLDecoder;
26 import java.net.URLEncoder;
27 import java.util.ArrayList;
28 import java.util.Arrays;
29 import java.util.Iterator;
30 import java.util.LinkedHashMap;
31 import java.util.List;
32 import java.util.Map;
33
34 import javax.servlet.http.HttpServletRequest;
35 import javax.servlet.http.HttpServletResponse;
36
37 import org.apache.commons.logging.Log;
38 import org.apache.commons.logging.LogFactory;
39 import org.apache.struts2.ServletActionContext;
40 import org.apache.struts2.StrutsConstants;
41
42 import com.opensymphony.xwork2.inject.Inject;
43 import com.opensymphony.xwork2.util.TextParseUtil;
44 import com.opensymphony.xwork2.util.ValueStack;
45
46
47 /***
48 * UrlHelper
49 *
50 */
51 public class UrlHelper {
52 private static final Log LOG = LogFactory.getLog(UrlHelper.class);
53
54 /***
55 * Default HTTP port (80).
56 */
57 private static final int DEFAULT_HTTP_PORT = 80;
58
59 /***
60 * Default HTTPS port (443).
61 */
62 private static final int DEFAULT_HTTPS_PORT = 443;
63
64 private static final String AMP = "&";
65
66 private static int httpPort = DEFAULT_HTTP_PORT;
67 private static int httpsPort = DEFAULT_HTTPS_PORT;
68 private static String customEncoding;
69
70
71 @Inject(StrutsConstants.STRUTS_URL_HTTP_PORT)
72 public static void setHttpPort(String val) {
73 httpPort = Integer.parseInt(val);
74 }
75
76 @Inject(StrutsConstants.STRUTS_URL_HTTPS_PORT)
77 public static void setHttpsPort(String val) {
78 httpsPort = Integer.parseInt(val);
79 }
80
81 @Inject(StrutsConstants.STRUTS_I18N_ENCODING)
82 public static void setCustomEncoding(String val) {
83 customEncoding = val;
84 }
85
86 public static String buildUrl(String action, HttpServletRequest request, HttpServletResponse response, Map params) {
87 return buildUrl(action, request, response, params, null, true, true);
88 }
89
90 public static String buildUrl(String action, HttpServletRequest request, HttpServletResponse response, Map params, String scheme, boolean includeContext, boolean encodeResult) {
91 return buildUrl(action, request, response, params, scheme, includeContext, encodeResult, false);
92 }
93
94 public static String buildUrl(String action, HttpServletRequest request, HttpServletResponse response, Map params, String scheme, boolean includeContext, boolean encodeResult, boolean forceAddSchemeHostAndPort) {
95 return buildUrl(action, request, response, params, scheme, includeContext, encodeResult, forceAddSchemeHostAndPort, true);
96 }
97
98 public static String buildUrl(String action, HttpServletRequest request, HttpServletResponse response, Map params, String scheme, boolean includeContext, boolean encodeResult, boolean forceAddSchemeHostAndPort, boolean escapeAmp) {
99 StringBuffer link = new StringBuffer();
100
101 boolean changedScheme = false;
102
103
104
105 if (forceAddSchemeHostAndPort) {
106 String reqScheme = request.getScheme();
107 changedScheme = true;
108 link.append(scheme != null ? scheme : reqScheme);
109 link.append("://");
110 link.append(request.getServerName());
111
112 if (scheme != null) {
113
114 if (!scheme.equals(reqScheme)) {
115 if ((scheme.equals("http") && (httpPort != DEFAULT_HTTP_PORT)) || (scheme.equals("https") && httpsPort != DEFAULT_HTTPS_PORT)) {
116 link.append(":");
117 link.append(scheme.equals("http") ? httpPort : httpsPort);
118 }
119
120 } else {
121 int reqPort = request.getServerPort();
122
123 if ((scheme.equals("http") && (reqPort != DEFAULT_HTTP_PORT)) || (scheme.equals("https") && reqPort != DEFAULT_HTTPS_PORT)) {
124 link.append(":");
125 link.append(reqPort);
126 }
127 }
128 }
129 }
130 else if ((scheme != null) && !scheme.equals(request.getScheme())) {
131 changedScheme = true;
132 link.append(scheme);
133 link.append("://");
134 link.append(request.getServerName());
135
136 if ((scheme.equals("http") && (httpPort != DEFAULT_HTTP_PORT)) || (scheme.equals("https") && httpsPort != DEFAULT_HTTPS_PORT)) {
137 link.append(":");
138 link.append(scheme.equals("http") ? httpPort : httpsPort);
139 }
140 }
141
142 if (action != null) {
143
144
145 if (action.startsWith("/") && includeContext) {
146 String contextPath = request.getContextPath();
147 if (!contextPath.equals("/")) {
148 link.append(contextPath);
149 }
150 } else if (changedScheme) {
151
152
153
154 String uri = (String) request.getAttribute("javax.servlet.forward.request_uri");
155
156
157 if (uri == null) {
158 uri = request.getRequestURI();
159 }
160
161 link.append(uri.substring(0, uri.lastIndexOf('/') + 1));
162 }
163
164
165 link.append(action);
166 } else {
167
168 String requestURI = (String) request.getAttribute("struts.request_uri");
169
170
171
172 if (requestURI == null) {
173 requestURI = (String) request.getAttribute("javax.servlet.forward.request_uri");
174 }
175
176
177 if (requestURI == null) {
178 requestURI = request.getRequestURI();
179 }
180
181 link.append(requestURI);
182 }
183
184
185 if (escapeAmp) {
186 buildParametersString(params, link);
187 } else {
188 buildParametersString(params, link, "&");
189 }
190
191 String result = link.toString();
192
193 while (result.indexOf("<script>") > 0) {
194 result = result.replaceAll("<script>", "script");
195 }
196
197 try {
198 result = encodeResult ? response.encodeURL(result) : result;
199 } catch (Exception ex) {
200
201
202 result = link.toString();
203 }
204
205 return result;
206 }
207
208 public static void buildParametersString(Map params, StringBuffer link) {
209 buildParametersString(params, link, AMP);
210 }
211
212 public static void buildParametersString(Map params, StringBuffer link, String paramSeparator) {
213 if ((params != null) && (params.size() > 0)) {
214 if (link.toString().indexOf("?") == -1) {
215 link.append("?");
216 } else {
217 link.append(paramSeparator);
218 }
219
220
221 Iterator iter = params.entrySet().iterator();
222
223 String[] valueHolder = new String[1];
224
225 while (iter.hasNext()) {
226 Map.Entry entry = (Map.Entry) iter.next();
227 String name = (String) entry.getKey();
228 Object value = entry.getValue();
229
230 String[] values;
231
232 if (value instanceof String[]) {
233 values = (String[]) value;
234 } else {
235 valueHolder[0] = value.toString();
236 values = valueHolder;
237 }
238
239 for (int i = 0; i < values.length; i++) {
240 if (values[i] != null) {
241 link.append(name);
242 link.append('=');
243 link.append(translateAndEncode(values[i]));
244 }
245
246 if (i < (values.length - 1)) {
247 link.append(paramSeparator);
248 }
249 }
250
251 if (iter.hasNext()) {
252 link.append(paramSeparator);
253 }
254 }
255 }
256 }
257
258 /***
259 * Translates any script expressions using {@link com.opensymphony.xwork2.util.TextParseUtil#translateVariables} and
260 * encodes the URL using {@link java.net.URLEncoder#encode} with the encoding specified in the configuration.
261 *
262 * @param input
263 * @return the translated and encoded string
264 */
265 public static String translateAndEncode(String input) {
266 String translatedInput = translateVariable(input);
267 String encoding = getEncodingFromConfiguration();
268
269 try {
270 return URLEncoder.encode(translatedInput, encoding);
271 } catch (UnsupportedEncodingException e) {
272 LOG.warn("Could not encode URL parameter '" + input + "', returning value un-encoded");
273 return translatedInput;
274 }
275 }
276
277 public static String translateAndDecode(String input) {
278 String translatedInput = translateVariable(input);
279 String encoding = getEncodingFromConfiguration();
280
281 try {
282 return URLDecoder.decode(translatedInput, encoding);
283 } catch (UnsupportedEncodingException e) {
284 LOG.warn("Could not encode URL parameter '" + input + "', returning value un-encoded");
285 return translatedInput;
286 }
287 }
288
289 private static String translateVariable(String input) {
290 ValueStack valueStack = ServletActionContext.getContext().getValueStack();
291 String output = TextParseUtil.translateVariables(input, valueStack);
292 return output;
293 }
294
295 private static String getEncodingFromConfiguration() {
296 final String encoding;
297 if (customEncoding != null) {
298 encoding = customEncoding;
299 } else {
300 encoding = "UTF-8";
301 }
302 return encoding;
303 }
304
305 public static Map parseQueryString(String queryString) {
306 Map queryParams = new LinkedHashMap();
307 if (queryString != null) {
308 String[] params = queryString.split("&");
309 for (int a=0; a< params.length; a++) {
310 if (params[a].trim().length() > 0) {
311 String[] tmpParams = params[a].split("=");
312 String paramName = null;
313 String paramValue = "";
314 if (tmpParams.length > 0) {
315 paramName = tmpParams[0];
316 }
317 if (tmpParams.length > 1) {
318 paramValue = tmpParams[1];
319 }
320 if (paramName != null) {
321 String translatedParamValue = translateAndDecode(paramValue);
322
323 if(queryParams.containsKey(paramName)) {
324
325 Object currentParam = queryParams.get(paramName);
326 if(currentParam instanceof String) {
327 queryParams.put(paramName, new String[] {
328 (String) currentParam, translatedParamValue});
329 } else {
330 String currentParamValues[] = (String[]) currentParam;
331 List paramList = new ArrayList(Arrays
332 .asList(currentParamValues));
333 paramList.add(translatedParamValue);
334 String newParamValues[] = new String[paramList
335 .size()];
336 queryParams.put(paramName, paramList
337 .toArray(newParamValues));
338 }
339 } else {
340 queryParams.put(paramName, translatedParamValue);
341 }
342 }
343 }
344 }
345 }
346 return queryParams;
347 }
348 }