1 17 18 package org.apache.tomcat.util.http; 19 20 import java.io.IOException ; 21 import java.util.Enumeration ; 22 import java.util.Hashtable ; 23 24 import org.apache.tomcat.util.buf.ByteChunk; 25 import org.apache.tomcat.util.buf.CharChunk; 26 import org.apache.tomcat.util.buf.MessageBytes; 27 import org.apache.tomcat.util.buf.UDecoder; 28 import org.apache.tomcat.util.collections.MultiMap; 29 30 34 public final class Parameters extends MultiMap { 35 36 37 private static org.apache.commons.logging.Log log= 38 org.apache.commons.logging.LogFactory.getLog(Parameters.class ); 39 40 private Hashtable paramHashStringArray=new Hashtable (); 44 private boolean didQueryParameters=false; 45 private boolean didMerge=false; 46 47 MessageBytes queryMB; 48 MimeHeaders headers; 49 50 UDecoder urlDec; 51 MessageBytes decodedQuery=MessageBytes.newInstance(); 52 53 public static final int INITIAL_SIZE=4; 54 55 private Parameters child=null; 62 private Parameters parent=null; 63 private Parameters currentChild=null; 64 65 String encoding=null; 66 String queryStringEncoding=null; 67 68 71 public Parameters() { 72 super( INITIAL_SIZE ); 73 } 74 75 public void setQuery( MessageBytes queryMB ) { 76 this.queryMB=queryMB; 77 } 78 79 public void setHeaders( MimeHeaders headers ) { 80 this.headers=headers; 81 } 82 83 public void setEncoding( String s ) { 84 encoding=s; 85 if(debug>0) log( "Set encoding to " + s ); 86 } 87 88 public void setQueryStringEncoding( String s ) { 89 queryStringEncoding=s; 90 if(debug>0) log( "Set query string encoding to " + s ); 91 } 92 93 public void recycle() { 94 super.recycle(); 95 paramHashStringArray.clear(); 96 didQueryParameters=false; 97 currentChild=null; 98 didMerge=false; 99 encoding=null; 100 decodedQuery.recycle(); 101 } 102 103 105 public Parameters getCurrentSet() { 106 if( currentChild==null ) 107 return this; 108 return currentChild; 109 } 110 111 117 public void push() { 118 126 if( currentChild==null ) { 130 currentChild=new Parameters(); 131 currentChild.setURLDecoder( urlDec ); 132 currentChild.parent=this; 133 return; 134 } 135 if( currentChild.child==null ) { 136 currentChild.child=new Parameters(); 137 currentChild.setURLDecoder( urlDec ); 138 currentChild.child.parent=currentChild; 139 } 142 currentChild=currentChild.child; 144 currentChild.setEncoding( encoding ); 145 } 146 147 150 public void pop() { 151 if( currentChild==null ) { 152 throw new RuntimeException ( "Attempt to pop without a push" ); 153 } 154 currentChild.recycle(); 155 currentChild=currentChild.parent; 156 } 158 159 163 165 public void addParameterValues( String key, String [] newValues) { 166 if ( key==null ) return; 167 String values[]; 168 if (paramHashStringArray.containsKey(key)) { 169 String oldValues[] = (String [])paramHashStringArray.get(key); 170 values = new String [oldValues.length + newValues.length]; 171 for (int i = 0; i < oldValues.length; i++) { 172 values[i] = oldValues[i]; 173 } 174 for (int i = 0; i < newValues.length; i++) { 175 values[i+ oldValues.length] = newValues[i]; 176 } 177 } else { 178 values = newValues; 179 } 180 181 paramHashStringArray.put(key, values); 182 } 183 184 public String [] getParameterValues(String name) { 185 handleQueryParameters(); 186 if( currentChild!=null ) { 188 currentChild.merge(); 189 return (String [])currentChild.paramHashStringArray.get(name); 190 } 191 192 String values[]=(String [])paramHashStringArray.get(name); 194 return values; 195 } 196 197 public Enumeration getParameterNames() { 198 handleQueryParameters(); 199 if( currentChild!=null ) { 201 currentChild.merge(); 202 return currentChild.paramHashStringArray.keys(); 203 } 204 205 return paramHashStringArray.keys(); 207 } 208 209 211 private void merge() { 212 if( debug > 0 ) { 214 log("Before merging " + this + " " + parent + " " + didMerge ); 215 log( paramsAsString()); 216 } 217 handleQueryParameters(); 219 220 if( didMerge ) return; 222 223 if( parent==null ) return; 225 226 parent.merge(); 228 Hashtable parentProps=parent.paramHashStringArray; 229 merge2( paramHashStringArray , parentProps); 230 didMerge=true; 231 if(debug > 0 ) 232 log("After " + paramsAsString()); 233 } 234 235 236 public String getParameter(String name ) { 238 String [] values = getParameterValues(name); 239 if (values != null) { 240 if( values.length==0 ) return ""; 241 return values[0]; 242 } else { 243 return null; 244 } 245 } 246 249 public void handleQueryParameters() { 250 if( didQueryParameters ) return; 251 252 didQueryParameters=true; 253 254 if( queryMB==null || queryMB.isNull() ) 255 return; 256 257 if( debug > 0 ) 258 log( "Decoding query " + decodedQuery + " " + queryStringEncoding); 259 260 try { 261 decodedQuery.duplicate( queryMB ); 262 } catch (IOException e) { 263 e.printStackTrace(); 265 } 266 processParameters( decodedQuery, queryStringEncoding ); 267 } 268 269 271 276 private static void merge2(Hashtable one, Hashtable two ) { 277 Enumeration e = two.keys(); 278 279 while (e.hasMoreElements()) { 280 String name = (String ) e.nextElement(); 281 String [] oneValue = (String []) one.get(name); 282 String [] twoValue = (String []) two.get(name); 283 String [] combinedValue; 284 285 if (twoValue == null) { 286 continue; 287 } else { 288 if( oneValue==null ) { 289 combinedValue = new String [twoValue.length]; 290 System.arraycopy(twoValue, 0, combinedValue, 291 0, twoValue.length); 292 } else { 293 combinedValue = new String [oneValue.length + 294 twoValue.length]; 295 System.arraycopy(oneValue, 0, combinedValue, 0, 296 oneValue.length); 297 System.arraycopy(twoValue, 0, combinedValue, 298 oneValue.length, twoValue.length); 299 } 300 one.put(name, combinedValue); 301 } 302 } 303 } 304 305 private void addParam( String key, String value ) { 308 if( key==null ) return; 309 String values[]; 310 if (paramHashStringArray.containsKey(key)) { 311 String oldValues[] = (String [])paramHashStringArray. 312 get(key); 313 values = new String [oldValues.length + 1]; 314 for (int i = 0; i < oldValues.length; i++) { 315 values[i] = oldValues[i]; 316 } 317 values[oldValues.length] = value; 318 } else { 319 values = new String [1]; 320 values[0] = value; 321 } 322 323 324 paramHashStringArray.put(key, values); 325 } 326 327 public void setURLDecoder( UDecoder u ) { 328 urlDec=u; 329 } 330 331 333 336 ByteChunk tmpName=new ByteChunk(); 339 ByteChunk tmpValue=new ByteChunk(); 340 CharChunk tmpNameC=new CharChunk(1024); 341 CharChunk tmpValueC=new CharChunk(1024); 342 343 public void processParameters( byte bytes[], int start, int len ) { 344 processParameters(bytes, start, len, encoding); 345 } 346 347 public void processParameters( byte bytes[], int start, int len, 348 String enc ) { 349 int end=start+len; 350 int pos=start; 351 352 if( debug>0 ) 353 log( "Bytes: " + new String ( bytes, start, len )); 354 355 do { 356 boolean noEq=false; 357 int valStart=-1; 358 int valEnd=-1; 359 360 int nameStart=pos; 361 int nameEnd=ByteChunk.indexOf(bytes, nameStart, end, '=' ); 362 int nameEnd2=ByteChunk.indexOf(bytes, nameStart, end, '&' ); 364 if( (nameEnd2!=-1 ) && 365 ( nameEnd==-1 || nameEnd > nameEnd2) ) { 366 nameEnd=nameEnd2; 367 noEq=true; 368 valStart=nameEnd; 369 valEnd=nameEnd; 370 if( debug>0) log("no equal " + nameStart + " " + nameEnd + " " + new String (bytes, nameStart, nameEnd-nameStart) ); 371 } 372 if( nameEnd== -1 ) 373 nameEnd=end; 374 375 if( ! noEq ) { 376 valStart= (nameEnd < end) ? nameEnd+1 : end; 377 valEnd=ByteChunk.indexOf(bytes, valStart, end, '&'); 378 if( valEnd== -1 ) valEnd = (valStart < end) ? end : valStart; 379 } 380 381 pos=valEnd+1; 382 383 if( nameEnd<=nameStart ) { 384 continue; 385 } 388 tmpName.setBytes( bytes, nameStart, nameEnd-nameStart ); 389 tmpValue.setBytes( bytes, valStart, valEnd-valStart ); 390 391 try { 392 addParam( urlDecode(tmpName, enc), urlDecode(tmpValue, enc) ); 393 } catch (IOException e) { 394 } 396 397 tmpName.recycle(); 398 tmpValue.recycle(); 399 400 } while( pos<end ); 401 } 402 403 private String urlDecode(ByteChunk bc, String enc) 404 throws IOException { 405 if( urlDec==null ) { 406 urlDec=new UDecoder(); 407 } 408 urlDec.convert(bc); 409 String result = null; 410 if (enc != null) { 411 bc.setEncoding(enc); 412 result = bc.toString(); 413 } else { 414 CharChunk cc = tmpNameC; 415 cc.allocate(bc.getLength(), -1); 416 byte[] bbuf = bc.getBuffer(); 418 char[] cbuf = cc.getBuffer(); 419 int start = bc.getStart(); 420 for (int i = 0; i < bc.getLength(); i++) { 421 cbuf[i] = (char) (bbuf[i + start] & 0xff); 422 } 423 cc.setChars(cbuf, 0, bc.getLength()); 424 result = cc.toString(); 425 cc.recycle(); 426 } 427 return result; 428 } 429 430 public void processParameters( char chars[], int start, int len ) { 431 int end=start+len; 432 int pos=start; 433 434 if( debug>0 ) 435 log( "Chars: " + new String ( chars, start, len )); 436 do { 437 boolean noEq=false; 438 int nameStart=pos; 439 int valStart=-1; 440 int valEnd=-1; 441 442 int nameEnd=CharChunk.indexOf(chars, nameStart, end, '=' ); 443 int nameEnd2=CharChunk.indexOf(chars, nameStart, end, '&' ); 444 if( (nameEnd2!=-1 ) && 445 ( nameEnd==-1 || nameEnd > nameEnd2) ) { 446 nameEnd=nameEnd2; 447 noEq=true; 448 valStart=nameEnd; 449 valEnd=nameEnd; 450 if( debug>0) log("no equal " + nameStart + " " + nameEnd + " " + new String (chars, nameStart, nameEnd-nameStart) ); 451 } 452 if( nameEnd== -1 ) nameEnd=end; 453 454 if( ! noEq ) { 455 valStart= (nameEnd < end) ? nameEnd+1 : end; 456 valEnd=CharChunk.indexOf(chars, valStart, end, '&'); 457 if( valEnd== -1 ) valEnd = (valStart < end) ? end : valStart; 458 } 459 460 pos=valEnd+1; 461 462 if( nameEnd<=nameStart ) { 463 continue; 464 } 467 468 try { 469 tmpNameC.append( chars, nameStart, nameEnd-nameStart ); 470 tmpValueC.append( chars, valStart, valEnd-valStart ); 471 472 if( debug > 0 ) 473 log( tmpNameC + "= " + tmpValueC); 474 475 if( urlDec==null ) { 476 urlDec=new UDecoder(); 477 } 478 479 urlDec.convert( tmpNameC ); 480 urlDec.convert( tmpValueC ); 481 482 if( debug > 0 ) 483 log( tmpNameC + "= " + tmpValueC); 484 485 addParam( tmpNameC.toString(), tmpValueC.toString() ); 486 } catch( IOException ex ) { 487 ex.printStackTrace(); 488 } 489 490 tmpNameC.recycle(); 491 tmpValueC.recycle(); 492 493 } while( pos<end ); 494 } 495 496 public void processParameters( MessageBytes data ) { 497 processParameters(data, encoding); 498 } 499 500 public void processParameters( MessageBytes data, String encoding ) { 501 if( data==null || data.isNull() || data.getLength() <= 0 ) return; 502 503 if( data.getType() == MessageBytes.T_BYTES ) { 504 ByteChunk bc=data.getByteChunk(); 505 processParameters( bc.getBytes(), bc.getOffset(), 506 bc.getLength(), encoding); 507 } else { 508 if (data.getType()!= MessageBytes.T_CHARS ) 509 data.toChars(); 510 CharChunk cc=data.getCharChunk(); 511 processParameters( cc.getChars(), cc.getOffset(), 512 cc.getLength()); 513 } 514 } 515 516 518 public String paramsAsString() { 519 StringBuffer sb=new StringBuffer (); 520 Enumeration en= paramHashStringArray.keys(); 521 while( en.hasMoreElements() ) { 522 String k=(String )en.nextElement(); 523 sb.append( k ).append("="); 524 String v[]=(String [])paramHashStringArray.get( k ); 525 for( int i=0; i<v.length; i++ ) 526 sb.append( v[i] ).append(","); 527 sb.append("\n"); 528 } 529 return sb.toString(); 530 } 531 532 private static int debug=0; 533 private void log(String s ) { 534 if (log.isDebugEnabled()) 535 log.debug("Parameters: " + s ); 536 } 537 538 540 542 public void processParameters( String str ) { 543 int end=str.length(); 544 int pos=0; 545 if( debug > 0) 546 log("String: " + str ); 547 548 do { 549 boolean noEq=false; 550 int valStart=-1; 551 int valEnd=-1; 552 553 int nameStart=pos; 554 int nameEnd=str.indexOf('=', nameStart ); 555 int nameEnd2=str.indexOf('&', nameStart ); 556 if( nameEnd2== -1 ) nameEnd2=end; 557 if( (nameEnd2!=-1 ) && 558 ( nameEnd==-1 || nameEnd > nameEnd2) ) { 559 nameEnd=nameEnd2; 560 noEq=true; 561 valStart=nameEnd; 562 valEnd=nameEnd; 563 if( debug>0) log("no equal " + nameStart + " " + nameEnd + " " + str.substring(nameStart, nameEnd) ); 564 } 565 566 if( nameEnd== -1 ) nameEnd=end; 567 568 if( ! noEq ) { 569 valStart=nameEnd+1; 570 valEnd=str.indexOf('&', valStart); 571 if( valEnd== -1 ) valEnd = (valStart < end) ? end : valStart; 572 } 573 574 pos=valEnd+1; 575 576 if( nameEnd<=nameStart ) { 577 continue; 578 } 579 if( debug>0) 580 log( "XXX " + nameStart + " " + nameEnd + " " 581 + valStart + " " + valEnd ); 582 583 try { 584 tmpNameC.append(str, nameStart, nameEnd-nameStart ); 585 tmpValueC.append(str, valStart, valEnd-valStart ); 586 587 if( debug > 0 ) 588 log( tmpNameC + "= " + tmpValueC); 589 590 if( urlDec==null ) { 591 urlDec=new UDecoder(); 592 } 593 594 urlDec.convert( tmpNameC ); 595 urlDec.convert( tmpValueC ); 596 597 if( debug > 0 ) 598 log( tmpNameC + "= " + tmpValueC); 599 600 addParam( tmpNameC.toString(), tmpValueC.toString() ); 601 } catch( IOException ex ) { 602 ex.printStackTrace(); 603 } 604 605 tmpNameC.recycle(); 606 tmpValueC.recycle(); 607 608 } while( pos<end ); 609 } 610 611 612 } 613 | Popular Tags |