I'll take a look - please give me few days, I want to fix the security first.
It's much better, I think afterRead() is the right solution and will help in other
areas ( performance, etc).
Costin
Jun Inamori wrote:
> Hi Costin, Dmitry and Eugen
> Thank you for your reply.
>
> Based on the discussion about my proposal, I've just wrote some sort of
> RequestInterceptor.
> While I've not completed it yet, I send its source.
> I'll write some comment about it later.
>
> --
> Happy Java programming!
>
> Jun Inamori
> E-mail: j-office@osa.att.ne.jp
> URL: http://www.oop-reserch.com
>
> *** source ***
> *** for FixCharset ***
>
> package org.apache.tomcat.request;
>
> import org.apache.tomcat.core.*;
> import org.apache.tomcat.util.*;
> import java.io.*;
> import java.util.*;
> import javax.servlet.*;
> import javax.servlet.http.*;
>
> // Should we use this?
> //import sun.io.ByteToCharConverter;
>
> public class FixCharset extends BaseInterceptor
> implements RequestInterceptor {
>
> static private int result=0;
>
> /**
> * Web masters can override this by 'charSet' property.
> * Should be overriden by 'charset' attribute
> * of 'Content-Type' from WWW browser.
> * But at this time, we don't know such a browser.
> */
> static private String cs="US-ASCII";
>
> /**
> * Web masters can override this by 'charSet' property.
> * Should be overriden by 'charset' attribute
> * of 'Content-Type' from WWW browser.
> * But at this time, we don't know such a browser.
> */
> static private String enc=System.getProperty("file.encoding");
> // Or should we use this?
> // static private String
> enc=ByteToCharConverter.getDefault().getCharacterEncoding();
>
> /** an original request */
> static private Request req = null;
>
> /** parameter storage */
> static private Hashtable params = new Hashtable();
> /** file storage */
>
> /** the HTTP GET method signature */
> final static private String METHOD_GET = "GET";
> /** the HTTP POST method signature */
> final static private String METHOD_POST = "POST";
> /** the url-style form parameter encoding */
> final static private String ENCODING_URL =
> "application/x-www-form-urlencoded";
>
> public FixCharset() {
> }
>
> public void setCharset(String c_set){
> cs=c_set;
> enc=CharsetToJavaEnc.getJavaEncoding(cs);
> if(enc==null){
> enc=System.getProperty("file.encoding");
> // Or should we use this?
> //enc=ByteToCharConverter.getDefault().getCharacterEncoding();
> }
> }
>
> public String getCharset(){
> return cs;
> }
>
> public String getJavaEnc(){
> return enc;
> }
>
> /**
> * Called at first in ServletWrapper.handleRequest().
> * In case of POST or GET, parameters must be parsed
> * and decoded.
> * For POST, parameters should be read from InputStream.
> */
> public int afterRead( Request request, Response response ) {
> req=request;
> result=0;
> params.clear();
> /**
> * Override the initial value
> * (which is specified by webmaster)
> * by the one from WWW browser.
> */
> String c_set=req.getCharacterEncoding();
> if(c_set!=null){
> cs=c_set;
> String w_enc=CharsetToJavaEnc.getJavaEncoding(c_set);
> if(w_enc!=null){
> enc=w_enc;
> }
> }
> // Set the initial value to request
> else{
> req.setCharEncoding(cs);
> }
>
> if(!req.getMethod().toUpperCase().equals(METHOD_GET)&&!req.getMethod().toUpperCase().equals(METHOD_POST)){
> return 0;
> }
> else{
> try{
> processParameters(getByteArray());
> req.setParameters(params);
> }
> catch(Exception ex){}
> }
> return result;
> }
>
> /**
> * In case of POST, we have to read from InputStream.
> * Otherwise we can use req.getQueryString.
> */
> private byte[] getByteArray()
> throws Exception{
> byte[] buffer=null;
> if(req.getMethod().toUpperCase().equals(METHOD_POST)){
> try{
> ServletInputStream sis = req.getInputStream();
> if(sis!=null){
> int length=req.getContentLength();
> buffer=new byte[length];
> int offset=0;
> for(int readBytes=0; offset<length; offset+=readBytes){
> readBytes=sis.read(buffer,offset,length-offset );
> if(readBytes==-1){
> break;
> }
> }
> sis.close();
> }
> }
> catch(Exception ex){
> result=HttpServletResponse.SC_INTERNAL_SERVER_ERROR;
> throw ex;
> }
> }
> else{
> String s=req.getQueryString();
> if(s!=null && s.length() > 0 ){
> buffer=s.getBytes();
> }
> else{
> result=HttpServletResponse.SC_BAD_REQUEST;
> throw (new TomcatException("No query string!"));
> }
> }
> return buffer;
> }
>
> /**
> * Parameter processor core. Parses text values,
> * extracts and saves files.
> */
> private void processParameters(byte[] buffer)
> throws Exception{
>
> //extract parameters
> byte[] b2 = new byte[buffer.length + 1];
> int n = 0;
> for ( int i = 0; i < buffer.length; i++ ){
> char some=(char)buffer[i];
> switch ( some ){
> case '+':
> b2[n++] =(byte) ' ';
> break;
> case '%':
> char[] digit=new char[2];
> digit[0]=(char)buffer[++i];
> digit[1]=(char)buffer[++i];
> int i_v=Integer.parseInt((new String(digit)),16);
> b2[n++]=(byte)i_v;
> break;
> case '&':
> convertParameter( b2, n );
> n = 0;
> break;
> default:
> b2[n++] = buffer[i];
> break;
> }
> }
> convertParameter( b2, n );
> }
>
> /**
> * The parameter parser
> * @param bytes a byte array representing the parameter entry
> * @param n entry length (it's expected that the buffer is longer)
> */
> private void convertParameter( byte[] bytes, int n )
> throws Exception{
> int n2 = 0;
> // At first, we have to know the index of '='.
> // Without String.indexOf()!
> while ( bytes[n2++] != '=' && n2 < n );
>
> // Then devide given byte array into key and value.
> int del=(bytes[n2 - 1] == '=') ? n2 - 1 : n2;
> try{
> String key = new String(bytes, 0, del, enc);
> String value = "";
> if( n2 < n ){
> value=new String(bytes, n2, n - n2, enc);
> }
> putParameter( key, value );
> }
> catch(Exception ex){
> result=HttpServletResponse.SC_INTERNAL_SERVER_ERROR;
> throw ex;
> }
> }
>
> private void putParameter(String key, String value){
> String values[];
> if (params.containsKey(key)) {
> String oldValues[] = (String[])params.get(key);
> values = new String[oldValues.length + 1];
> for (int i = 0; i < oldValues.length; i++) {
> values[i] = oldValues[i];
> }
> values[oldValues.length] = value;
> } else {
> values = new String[1];
> values[0] = value;
> }
> params.put(key, values);
> }
>
> }
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: tomcat-dev-unsubscribe@jakarta.apache.org
> For additional commands, e-mail: tomcat-dev-help@jakarta.apache.org
|