001: package com.ecyrd.jspwiki.url;
002:
003: import java.util.Properties;
004: import java.io.UnsupportedEncodingException;
005: import java.net.MalformedURLException;
006: import java.net.URL;
007: import java.net.URLDecoder;
008:
009: import javax.servlet.http.HttpServletRequest;
010:
011: import org.apache.commons.lang.StringUtils;
012:
013: import com.ecyrd.jspwiki.InternalWikiException;
014: import com.ecyrd.jspwiki.TextUtil;
015: import com.ecyrd.jspwiki.WikiContext;
016: import com.ecyrd.jspwiki.WikiEngine;
017:
018: public class DefaultURLConstructor implements URLConstructor {
019: protected WikiEngine m_engine;
020: private String m_viewURLPattern = "%uWiki.jsp?page=%n";
021:
022: /** Are URL styles relative or absolute? */
023: protected boolean m_useRelativeURLStyle = true;
024:
025: public void initialize(WikiEngine engine, Properties properties) {
026: m_engine = engine;
027:
028: m_useRelativeURLStyle = "relative".equals(properties
029: .getProperty(WikiEngine.PROP_REFSTYLE, "relative"));
030: }
031:
032: protected final String doReplacement(String baseptrn, String name,
033: boolean absolute) {
034: String baseurl = "";
035:
036: if (absolute || !m_useRelativeURLStyle)
037: baseurl = m_engine.getBaseURL();
038:
039: baseptrn = TextUtil.replaceString(baseptrn, "%u", baseurl);
040: baseptrn = TextUtil.replaceString(baseptrn, "%U", m_engine
041: .getBaseURL());
042: baseptrn = TextUtil.replaceString(baseptrn, "%n",
043: encodeURI(name));
044:
045: return baseptrn;
046: }
047:
048: /**
049: * URLEncoder returns pluses, when we want to have the percent
050: * encoding. See http://issues.apache.org/bugzilla/show_bug.cgi?id=39278
051: * for more info.
052: *
053: * We also convert any %2F's back to slashes to make nicer-looking URLs.
054: */
055: private final String encodeURI(String uri) {
056: uri = m_engine.encodeName(uri);
057:
058: uri = StringUtils.replace(uri, "+", "%20");
059: uri = StringUtils.replace(uri, "%2F", "/");
060:
061: return uri;
062: }
063:
064: /**
065: * Returns the pattern used for each URL style.
066: *
067: * @param context
068: * @param name
069: * @return A pattern for replacement.
070: */
071: public static String getURLPattern(String context, String name) {
072: if (context.equals(WikiContext.VIEW)) {
073: if (name == null)
074: return "%uWiki.jsp"; // FIXME
075: return "%uWiki.jsp?page=%n";
076: } else if (context.equals(WikiContext.EDIT)) {
077: return "%uEdit.jsp?page=%n";
078: } else if (context.equals(WikiContext.ATTACH)) {
079: return "%uattach/%n";
080: } else if (context.equals(WikiContext.INFO)) {
081: return "%uPageInfo.jsp?page=%n";
082: } else if (context.equals(WikiContext.DIFF)) {
083: return "%uDiff.jsp?page=%n";
084: } else if (context.equals(WikiContext.NONE)) {
085: return "%u%n";
086: } else if (context.equals(WikiContext.UPLOAD)) {
087: return "%uUpload.jsp?page=%n";
088: } else if (context.equals(WikiContext.COMMENT)) {
089: return "%uComment.jsp?page=%n";
090: } else if (context.equals(WikiContext.ERROR)) {
091: return "%uError.jsp";
092: }
093: throw new InternalWikiException(
094: "Requested unsupported context " + context);
095: }
096:
097: /**
098: * Constructs the actual URL based on the context.
099: */
100: private String makeURL(String context, String name, boolean absolute) {
101: if (context.equals(WikiContext.VIEW)) {
102: if (name == null)
103: return makeURL("%uWiki.jsp", "", absolute); // FIXME
104: }
105:
106: return doReplacement(getURLPattern(context, name), name,
107: absolute);
108: }
109:
110: /**
111: * Constructs the URL with a bunch of parameters.
112: * @param parameters If null or empty, no parameters are added.
113: */
114: public String makeURL(String context, String name,
115: boolean absolute, String parameters) {
116: if (parameters != null && parameters.length() > 0) {
117: if (context.equals(WikiContext.ATTACH)) {
118: parameters = "?" + parameters;
119: } else {
120: parameters = "&" + parameters;
121: }
122: } else {
123: parameters = "";
124: }
125: return makeURL(context, name, absolute) + parameters;
126: }
127:
128: /**
129: * Should parse the "page" parameter from the actual
130: * request.
131: */
132: public String parsePage(String context, HttpServletRequest request,
133: String encoding) throws UnsupportedEncodingException {
134: String pagereq = m_engine.safeGetParameter(request, "page");
135:
136: if (context.equals(WikiContext.ATTACH)) {
137: pagereq = parsePageFromURL(request, encoding);
138: }
139:
140: return pagereq;
141: }
142:
143: /**
144: * There's a bug in Tomcat until 5.5.16 at least: The "+" sign is not
145: * properly decoded by the servlet container, and therefore request.getPathInfo()
146: * will return faulty results for paths which contains + signs to signify spaces.
147: * <p>
148: * This method provides a workaround by simply parsing the getRequestURI(), which
149: * is returned from the servlet container undedecoded.
150: * <p>
151: * Please see <a href="http://issues.apache.org/bugzilla/show_bug.cgi?id=39278">Tomcat Bug 39278</a>
152: * for more information.
153: *
154: * @param request A HTTP servlet request
155: * @param encoding The used encoding
156: * @return a String, decoded by JSPWiki, specifying extra path information that comes
157: * after the servlet path but before the query string in the request URL;
158: * or null if the URL does not have any extra path information
159: * @throws UnsupportedEncodingException
160: */
161: private static String getPathInfo(HttpServletRequest request,
162: String encoding) throws UnsupportedEncodingException {
163: String c = request.getContextPath(); // Undecoded
164: String s = request.getServletPath(); // Decoded
165: String u = request.getRequestURI(); // Undecoded
166:
167: c = URLDecoder.decode(c, encoding);
168: u = URLDecoder.decode(u, encoding);
169:
170: String pi = u.substring(s.length() + c.length());
171:
172: if (pi.length() == 0)
173: pi = null;
174:
175: return pi;
176: }
177:
178: /**
179: * Takes the name of the page from the request URI.
180: * The initial slash is also removed. If there is no page,
181: * returns null.
182: */
183: public static String parsePageFromURL(HttpServletRequest request,
184: String encoding) throws UnsupportedEncodingException {
185: String name = request.getPathInfo();
186:
187: if (name == null || name.length() <= 1) {
188: return null;
189: } else if (name.charAt(0) == '/') {
190: name = name.substring(1);
191: }
192:
193: //
194: // This is required, because by default all URLs are handled
195: // as Latin1, even if they are really UTF-8.
196: //
197:
198: //name = TextUtil.urlDecode( name, encoding );
199:
200: return name;
201: }
202:
203: /**
204: * This method is not needed for the DefaultURLConstructor.
205: *
206: * @author jalkanen
207: *
208: * @since
209: */
210: public String getForwardPage(HttpServletRequest request) {
211: return request.getPathInfo();
212: }
213: }
|