31
31
public final class UDecoder {
33
private static org.apache.juli.logging.Log log=
34
org.apache.juli.logging.LogFactory.getLog(UDecoder.class );
36
33
protected static final boolean ALLOW_ENCODED_SLASH =
37
34
Boolean.valueOf(System.getProperty("org.apache.tomcat.util.buf.UDecoder.ALLOW_ENCODED_SLASH", "false")).booleanValue();
52
49
/** URLDecode, will modify the source.
54
51
public void convert( ByteChunk mb, boolean query )
57
int start=mb.getOffset();
58
byte buff[]=mb.getBytes();
54
int start=mb.getOffset();
55
byte buff[]=mb.getBytes();
61
int idx= ByteChunk.indexOf( buff, start, end, '%' );
58
int idx= ByteChunk.indexOf( buff, start, end, '%' );
64
61
idx2= ByteChunk.indexOf( buff, start, end, '+' );
65
if( idx<0 && idx2<0 ) {
62
if( idx<0 && idx2<0 ) {
69
// idx will be the smallest positive inxes ( first % or + )
70
if( idx2 >= 0 && idx2 < idx ) idx=idx2;
71
if( idx < 0 ) idx=idx2;
66
// idx will be the smallest positive inxes ( first % or + )
67
if( idx2 >= 0 && idx2 < idx ) idx=idx2;
68
if( idx < 0 ) idx=idx2;
73
70
boolean noSlash = !(ALLOW_ENCODED_SLASH || query);
75
for( int j=idx; j<end; j++, idx++ ) {
76
if( buff[ j ] == '+' && query) {
77
buff[idx]= (byte)' ' ;
78
} else if( buff[ j ] != '%' ) {
83
throw new CharConversionException("EOF");
87
if( !isHexDigit( b1 ) || ! isHexDigit(b2 ))
88
throw new CharConversionException( "isHexDigit");
91
int res=x2c( b1, b2 );
72
for( int j=idx; j<end; j++, idx++ ) {
73
if( buff[ j ] == '+' && query) {
74
buff[idx]= (byte)' ' ;
75
} else if( buff[ j ] != '%' ) {
80
throw new CharConversionException("EOF");
84
if( !isHexDigit( b1 ) || ! isHexDigit(b2 ))
85
throw new CharConversionException( "isHexDigit");
88
int res=x2c( b1, b2 );
92
89
if (noSlash && (res == '/')) {
93
90
throw new CharConversionException( "noSlash");
104
101
// -------------------- Additional methods --------------------
116
113
/** In-buffer processing - the buffer will be modified
118
115
public void convert( CharChunk mb, boolean query )
121
// log( "Converting a char chunk ");
122
int start=mb.getOffset();
123
char buff[]=mb.getBuffer();
124
int cend=mb.getEnd();
118
// log( "Converting a char chunk ");
119
int start=mb.getOffset();
120
char buff[]=mb.getBuffer();
121
int cend=mb.getEnd();
126
int idx= CharChunk.indexOf( buff, start, cend, '%' );
123
int idx= CharChunk.indexOf( buff, start, cend, '%' );
129
126
idx2= CharChunk.indexOf( buff, start, cend, '+' );
130
if( idx<0 && idx2<0 ) {
134
if( idx2 >= 0 && idx2 < idx ) idx=idx2;
135
if( idx < 0 ) idx=idx2;
127
if( idx<0 && idx2<0 ) {
131
if( idx2 >= 0 && idx2 < idx ) idx=idx2;
132
if( idx < 0 ) idx=idx2;
137
for( int j=idx; j<cend; j++, idx++ ) {
138
if( buff[ j ] == '+' && query ) {
140
} else if( buff[ j ] != '%' ) {
143
// read next 2 digits
146
throw new CharConversionException("EOF");
150
if( !isHexDigit( b1 ) || ! isHexDigit(b2 ))
151
throw new CharConversionException("isHexDigit");
154
int res=x2c( b1, b2 );
134
for( int j=idx; j<cend; j++, idx++ ) {
135
if( buff[ j ] == '+' && query ) {
137
} else if( buff[ j ] != '%' ) {
140
// read next 2 digits
143
throw new CharConversionException("EOF");
147
if( !isHexDigit( b1 ) || ! isHexDigit(b2 ))
148
throw new CharConversionException("isHexDigit");
151
int res=x2c( b1, b2 );
161
158
/** URLDecode, will modify the source
162
159
* Includes converting '+' to ' '.
164
161
public void convert(MessageBytes mb)
167
164
convert(mb, true);
170
167
/** URLDecode, will modify the source
172
169
public void convert(MessageBytes mb, boolean query)
176
switch (mb.getType()) {
177
case MessageBytes.T_STR:
178
String strValue=mb.toString();
179
if( strValue==null ) return;
180
mb.setString( convert( strValue, query ));
182
case MessageBytes.T_CHARS:
183
CharChunk charC=mb.getCharChunk();
184
convert( charC, query );
186
case MessageBytes.T_BYTES:
187
ByteChunk bytesC=mb.getByteChunk();
188
convert( bytesC, query );
173
switch (mb.getType()) {
174
case MessageBytes.T_STR:
175
String strValue=mb.toString();
176
if( strValue==null ) return;
177
mb.setString( convert( strValue, query ));
179
case MessageBytes.T_CHARS:
180
CharChunk charC=mb.getCharChunk();
181
convert( charC, query );
183
case MessageBytes.T_BYTES:
184
ByteChunk bytesC=mb.getByteChunk();
185
convert( bytesC, query );
193
190
// XXX Old code, needs to be replaced !!!!
200
197
public final String convert(String str, boolean query)
202
199
if (str == null) return null;
204
if( (!query || str.indexOf( '+' ) < 0) && str.indexOf( '%' ) < 0 )
201
if( (!query || str.indexOf( '+' ) < 0) && str.indexOf( '%' ) < 0 )
207
204
StringBuffer dec = new StringBuffer(); // decoded string output
209
206
int strLen = str.length();
240
237
} else if (metaChar == '%') {
241
// We throw the original exception - the super will deal with
244
dec.append((char)Integer.
245
parseInt(str.substring(strPos + 1, strPos + 3),16));
238
// We throw the original exception - the super will deal with
241
dec.append((char)Integer.
242
parseInt(str.substring(strPos + 1, strPos + 3),16));
255
252
private static boolean isHexDigit( int c ) {
256
return ( ( c>='0' && c<='9' ) ||
257
( c>='a' && c<='f' ) ||
258
( c>='A' && c<='F' ));
253
return ( ( c>='0' && c<='9' ) ||
254
( c>='a' && c<='f' ) ||
255
( c>='A' && c<='F' ));
261
258
private static int x2c( byte b1, byte b2 ) {
262
int digit= (b1>='A') ? ( (b1 & 0xDF)-'A') + 10 :
265
digit +=(b2>='A') ? ( (b2 & 0xDF)-'A') + 10 :
259
int digit= (b1>='A') ? ( (b1 & 0xDF)-'A') + 10 :
262
digit +=(b2>='A') ? ( (b2 & 0xDF)-'A') + 10 :
270
267
private static int x2c( char b1, char b2 ) {
271
int digit= (b1>='A') ? ( (b1 & 0xDF)-'A') + 10 :
274
digit +=(b2>='A') ? ( (b2 & 0xDF)-'A') + 10 :
279
private final static int debug=0;
280
private static void log( String s ) {
281
if (log.isDebugEnabled())
282
log.debug("URLDecoder: " + s );
268
int digit= (b1>='A') ? ( (b1 & 0xDF)-'A') + 10 :
271
digit +=(b2>='A') ? ( (b2 & 0xDF)-'A') + 10 :