costin 01/10/04 13:18:08 Modified: src/facade22/org/apache/tomcat/facade HttpServletRequestFacade.java src/share/org/apache/tomcat/util/buf UEncoder.java Log: getRequestURI returns an encoded request. Fix is slightly modified from what Bill Barker sent, I was thinking to do some optimizations ( avoid use of Writer, and do the encoding directly in the buffer), but given that this happens only when it's needed - it should be ok. Probably for 3.3.1 we can do this ( and the date formating which is another hotspot ). Note that we do not encode contextPath. This is against the spec, but I think we should leave it this way: - that's how it was in 3.1, 3.2, etc - 4.0 is also broken ( well, it returns 404 if I try any encoded char in the context path ) - it can raise a large number of bugs, if users expect the contextPath to be unique ( with encoding - there are many ways you can encode a string, without even considering charsets ). - it would be very hard to write an app that is consistent between 3.3 and 3.2 ( which most people use ). I don't know how other containers are doing this, but I suspect most will return the context path decoded - if you can find one that is not decoding the CP - we can reconsider this. Revision Changes Path 1.29 +51 -8 jakarta-tomcat/src/facade22/org/apache/tomcat/facade/HttpServletRequestFacade.java Index: HttpServletRequestFacade.java =================================================================== RCS file: /home/cvs/jakarta-tomcat/src/facade22/org/apache/tomcat/facade/HttpServletRequestFacade.java,v retrieving revision 1.28 retrieving revision 1.29 diff -u -r1.28 -r1.29 --- HttpServletRequestFacade.java 2001/09/22 00:53:47 1.28 +++ HttpServletRequestFacade.java 2001/10/04 20:18:08 1.29 @@ -63,6 +63,7 @@ import org.apache.tomcat.util.res.StringManager; import org.apache.tomcat.util.io.FileUtil; import org.apache.tomcat.util.buf.DateTool; +import org.apache.tomcat.util.buf.UEncoder; import org.apache.tomcat.util.http.*; import org.apache.tomcat.core.*; import org.apache.tomcat.facade.*; @@ -95,11 +96,8 @@ ServletInputStreamFacade isFacade=new ServletInputStreamFacade(); boolean isFacadeInitialized=false; BufferedReader reader; - DateFormat []dateFormats = { - new SimpleDateFormat(DateTool.RFC1123_PATTERN, Locale.US), - new SimpleDateFormat(DateTool.rfc1036Pattern, Locale.US), - new SimpleDateFormat(DateTool.asctimePattern, Locale.US) - }; + DateFormat []dateFormats; + UEncoder uencoder; private boolean usingStream = false; private boolean usingReader = false; @@ -111,6 +109,31 @@ HttpServletRequestFacade(Request request) { this.request = request; isFacade.setRequest( request ); + try { + // we may create facades more often than requests + Object o=request.getNote( "req.dateFormats" ); + if( o==null ) { + o=new DateFormat[] { + new SimpleDateFormat(DateTool.RFC1123_PATTERN, Locale.US), + new SimpleDateFormat(DateTool.rfc1036Pattern, Locale.US), + new SimpleDateFormat(DateTool.asctimePattern, Locale.US) + }; + request.setNote( "req.dateFormats", o ); + } + dateFormats=(DateFormat[])o; + o=request.getNote( "req.uencoder" ); + if( o==null ) { + uencoder=new UEncoder(); + uencoder.addSafeCharacter(';'); + uencoder.addSafeCharacter('/'); + request.setNote( "req.uencoder", uencoder ); + } else { + uencoder=(UEncoder)o; + } + } catch( TomcatException ex ) { + ex.printStackTrace(); + } + } /** Not public - is called only from FacadeManager on behalf of Request @@ -288,10 +311,12 @@ } public String getPathInfo() { + // DECODED return request.pathInfo().toString(); } public String getPathTranslated() { + // DECODED // Servlet 2.2 spec differs from what Apache and // all other web servers consider to be PATH_TRANSLATED. // It's important not to use CGI PATH_TRANSLATED - this @@ -309,7 +334,8 @@ } public String getQueryString() { - // unprocessed + // ENCODED. We don't decode the original query string, + // we we can return the same thing String qS=request.queryString().toString(); if( "".equals(qS) ) return null; @@ -379,11 +405,22 @@ } public String getRequestURI() { - if( request.unparsedURI().isNull() ) - return request.requestURI().toString(); + // ENCODED + if( request.unparsedURI().isNull() ) { + // unparsed URI is used as a cache. + // request.unparsedURI().duplicate( request.requestURI() ); + String decoded=request.requestURI().toString(); + // XXX - I'm not sure what encoding should we use - maybe output ?, + // since this will probably be used for the output + uencoder.setEncoding(request.getCharacterEncoding()); + String encoded= uencoder.encodeURL( decoded ); + + request.unparsedURI().setString( encoded ); + } return request.unparsedURI().toString(); } + /** Facade: we delegate to the right object ( the context ) */ public RequestDispatcher getRequestDispatcher(String path) { @@ -423,10 +460,16 @@ /** Delegate to Context */ public String getContextPath() { + // Should be ENCODED ( in 2.3 ). tomcat4.0 doesn't seem to do that + // ( it's in fact returning 404 on any encoded context paths ), and + // is very likely to result in user errors - if anyone expects it to + // be decoded, as it allways was in 3.x or if anyone will use it as + // a key. return request.getContext().getPath(); } public String getServletPath() { + // DECODED return request.servletPath().toString(); } 1.4 +18 -2 jakarta-tomcat/src/share/org/apache/tomcat/util/buf/UEncoder.java Index: UEncoder.java =================================================================== RCS file: /home/cvs/jakarta-tomcat/src/share/org/apache/tomcat/util/buf/UEncoder.java,v retrieving revision 1.3 retrieving revision 1.4 diff -u -r1.3 -r1.4 --- UEncoder.java 2001/07/19 05:49:02 1.3 +++ UEncoder.java 2001/10/04 20:18:08 1.4 @@ -158,8 +158,24 @@ buf.write(ch); } } - - + + /** + * Utility funtion to re-encode the URL. + * Still has problems with charset, since UEncoder mostly + * ignores it. + */ + public String encodeURL(String uri) { + String outUri=null; + try { + // XXX optimize - recycle, etc + CharArrayWriter out = new CharArrayWriter(); + urlEncode(out, uri); + outUri=out.toString(); + } catch (IOException iex) { + } + return outUri; + } + // -------------------- Internal implementation --------------------