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