1 19 20 21 28 29 package com.sslexplorer.core; 44 45 import java.io.ByteArrayOutputStream ; 46 import java.io.File ; 47 import java.io.FileInputStream ; 48 import java.io.FileNotFoundException ; 49 import java.io.FileOutputStream ; 50 import java.io.IOException ; 51 import java.io.InputStream ; 52 import java.io.OutputStream ; 53 import java.net.MalformedURLException ; 54 import java.net.URL ; 55 import java.util.ArrayList ; 56 import java.util.Iterator ; 57 import java.util.List ; 58 import java.util.Map ; 59 import java.util.StringTokenizer ; 60 import java.util.TreeMap ; 61 62 import org.apache.commons.logging.Log; 63 import org.apache.commons.logging.LogFactory; 64 import org.mortbay.util.MultiMap; 65 66 import com.sslexplorer.boot.RequestHandlerRequest; 67 import com.sslexplorer.boot.Util; 68 import com.sslexplorer.policyframework.LaunchSession; 69 70 93 public class RequestParameterMap extends MultiMap { 94 95 final static Log log = LogFactory.getLog(RequestParameterMap.class); 96 97 101 public final static String ISO_8859_1; 102 static { 103 String iso = System.getProperty("ISO_8859_1"); 104 if (iso != null) 105 ISO_8859_1 = iso; 106 else { 107 try { 108 new String (new byte[] { (byte) 20 }, "ISO-8859-1"); 109 iso = "ISO-8859-1"; 110 } catch (java.io.UnsupportedEncodingException e) { 111 iso = "ISO8859_1"; 112 } 113 ISO_8859_1 = iso; 114 } 115 } 116 117 private static final long serialVersionUID = -2005125971106236972L; 118 119 121 private LineInput input; 122 private String boundary; 123 private byte[] boundaryBytes; 124 private boolean finished; 125 private File multipartFile; 126 private long multipartLength; 127 private int ch; 128 private URL proxiedURLBase, proxiedURL; 129 private String launchId; 130 131 134 public RequestParameterMap() { 135 super(); 136 ch = -2; 137 } 138 139 145 public RequestParameterMap(RequestHandlerRequest request) throws IOException { 146 this(); 147 String contentType = request.getField("content-type"); 148 149 if (contentType != null && contentType.startsWith("multipart/form-data")) { 150 initMultipart(contentType, request.getInputStream()); 151 } 152 153 String requestPath = request.getPath(); 154 155 156 163 164 if(requestPath != null && requestPath.startsWith("/replacementProxyEngine/")) { 165 int idx = requestPath.indexOf('/', 1); 166 int idx2 = requestPath.indexOf('/', idx + 1); 167 launchId = requestPath.substring(idx + 1, idx2); 168 parseProxiedURL(requestPath.substring(idx2 + 1)); 169 } 170 171 Map params = request.getParameters(); 174 for (Iterator e = params.keySet().iterator(); e.hasNext();) { 175 String n = (String ) e.next(); 176 177 Object obj = params.get(n); 178 179 if(!checkForSSLXUrl(n, obj)) { 180 if (obj instanceof String []) { 181 put(n, ((String []) obj)[0]); 182 } else if (obj instanceof String ) { 183 put(n, obj.toString()); 184 } else 185 log.warn("Parameter value is an unexepected type " + obj.getClass().getName()); 186 } 187 } 188 189 } 190 191 198 public String getLaunchId() { 199 return launchId; 200 } 201 202 208 public boolean isFormData() { 209 return multipartFile != null; 210 } 211 212 220 public Object get(Object name) { 221 return getParameter(name); 222 } 223 224 235 public InputStream getFormData() throws IOException , FileNotFoundException { 236 if (multipartFile == null) { 237 throw new IOException ("This request was not of type multipart/form-data."); 238 } 239 return new FileMultipartInputStream(multipartFile); 240 } 241 242 249 public long getFormDataLength() throws IOException { 250 if (multipartFile == null) { 251 throw new IOException ("This request was not of type multipart/form-data."); 252 } 253 return multipartLength; 254 } 255 256 263 public URL getProxiedURL() { 264 return proxiedURL; 265 } 266 267 274 public URL getProxiedURLBase() { 275 return proxiedURLBase; 276 } 277 278 284 public String getParameter(Object name) { 285 List list = getValues(name); 286 if(list!=null && list.size() >= 1) { 287 return (String ) list.get(0); 288 } else 289 return null; 290 } 291 292 public List getParameterValues(Object name) { 293 return getValues(name); 294 } 295 296 301 public Iterator getParameterNames() { 302 return keySet().iterator(); 303 } 304 305 309 310 private void readBytes(InputStream in, OutputStream out, OutputStream recorded) throws IOException { 311 312 int c; 313 boolean cr = false; 314 boolean lf = false; 315 316 while (true) { 318 int b = 0; 319 while ((c = (ch != -2) ? ch : readWrite(in, recorded)) != -1) { 320 multipartLength++; 321 ch = -2; 322 323 if (c == 13 || c == 10) { 325 if (c == 13) { 326 ch = readWrite(in, recorded); 327 multipartLength++; 328 } 329 break; 330 } 331 332 if (b >= 0 && b < boundaryBytes.length && c == boundaryBytes[b]) 334 b++; 335 else { 336 if (cr && out != null) 338 out.write(13); 339 if (lf && out != null) 340 out.write(10); 341 cr = lf = false; 342 343 if (b > 0 && out != null) 344 out.write(boundaryBytes, 0, b); 345 b = -1; 346 347 if (out != null) 348 out.write(c); 349 } 350 } 351 352 if ((b > 0 && b < boundaryBytes.length - 2) || (b == boundaryBytes.length - 1)) { 354 if (cr && out != null) 355 out.write(13); 356 if (lf && out != null) 357 out.write(10); 358 cr = lf = false; 359 if (out != null) 360 out.write(boundaryBytes, 0, b); 361 b = -1; 362 } 363 364 if (b > 0 || c == -1) { 366 if (b == boundaryBytes.length) 367 finished = true; 368 if (ch == 10) 369 ch = -2; 370 break; 371 } 372 373 if (cr && out != null) 375 out.write(13); 376 if (lf && out != null) 377 out.write(10); 378 cr = (c == 13); 379 lf = (c == 10 || ch == 10); 380 if (ch == 10) 381 ch = -2; 382 } 383 } 384 385 private int readWrite(InputStream in, OutputStream out) throws IOException { 386 int i = in.read(); 387 if (i != -1 && out != null) { 388 out.write(i); 389 } 390 return i; 391 392 } 393 394 private boolean checkForSSLXUrl(String n, Object params) { 395 String val; 396 397 if (params instanceof String []) { 398 val = ((String []) params)[0]; 399 } else 400 val = (String ) params; 401 402 if (n.equals("sslex_url")) { 403 parseProxiedURL(val); 404 return true; 405 } else if (n.equals(LaunchSession.LONG_LAUNCH_ID)) { 406 launchId = val; 407 return true; 408 } 409 return false; 410 } 411 412 private void initMultipart(String contentType, InputStream in) throws IOException , FileNotFoundException { 413 multipartFile = File.createTempFile("mpr", ".tmp"); 414 FileOutputStream mpOut = new FileOutputStream (multipartFile); 415 416 try { 417 418 input = new LineInput(in); 419 boundary = "--" + Util.valueOfNameValuePair(contentType.substring(contentType.indexOf("boundary="))); 420 boundaryBytes = (boundary + "--").getBytes(ISO_8859_1); String line = input.readLine(); 424 if (!line.equals(boundary)) { 425 throw new IOException ("Missing initial multi part boundary"); 426 } 427 428 byte[] buf = (line + "\r\n").getBytes(); 429 multipartLength += buf.length; 430 mpOut.write(buf); 431 432 while (!finished) { 433 String contentDisposition = null; 434 435 Map <String , List <String >> parms = new TreeMap <String , List <String >>(); 436 while ((line = input.readLine()) != null) { 437 if (line.length() == 0) 438 break; 439 int idx = line.indexOf(':', 0); 440 if (idx > 0) { 441 String key = line.substring(0, idx).trim(); 442 String value = line.substring(idx + 1, line.length()).trim(); 443 444 List <String > cur = (List <String >) parms.get(key); 445 if (cur == null) { 446 cur = new ArrayList <String >(); 447 parms.put(key, cur); 448 } 449 cur.add(value); 450 451 if (key.equalsIgnoreCase("content-disposition")) 452 contentDisposition = value; 453 } 454 } 455 boolean form = false; 456 if (contentDisposition == null) { 457 throw new IOException ("Missing content-disposition"); 458 } 459 StringTokenizer tok = new StringTokenizer (contentDisposition, ";"); 460 String name = null; 461 String filename = null; 462 while (tok.hasMoreTokens()) { 463 String t = tok.nextToken().trim(); 464 String tl = t.toLowerCase(); 465 if (t.startsWith("form-data")) 466 form = true; 467 else if (tl.startsWith("name=")) 468 name = Util.valueOfNameValuePair(t); 469 else if (tl.startsWith("filename=")) 470 filename = Util.valueOfNameValuePair(t); 471 } 472 473 if (!form) { 475 log.warn("Non form-data part in multipart/form-data"); 476 continue; 477 } 478 479 if (name.equals("sslex_url")) { 480 ByteArrayOutputStream baos = new ByteArrayOutputStream (); 481 readBytes(input, baos, null); 482 parseProxiedURL(new String (baos.toString())); 483 } else { 484 for (Iterator i = parms.keySet().iterator(); i.hasNext();) { 485 String key = (String ) i.next(); 486 List list = (List ) parms.get(key); 487 for (Iterator j = list.iterator(); j.hasNext();) { 488 String val = (String ) j.next(); 489 buf = (key + ": " + val + "\r\n").getBytes(); 490 multipartLength += buf.length; 491 mpOut.write(buf); 492 } 493 } 494 buf = "\r\n".getBytes(); 495 multipartLength += buf.length; 496 mpOut.write(buf); 497 498 if (filename != null) { 499 readBytes(input, null, mpOut); 500 } else { 501 ByteArrayOutputStream baos = new ByteArrayOutputStream (); 502 readBytes(input, baos, mpOut); 503 put(Util.urlDecode(name), baos.toString()); 504 } 505 } 506 } 507 } finally { 508 Util.closeStream(mpOut); 509 } 510 511 } 512 513 public void parseProxiedURL(String location) { 514 try { 515 proxiedURL = new URL (location); 516 517 String query = proxiedURL.getQuery(); 519 if (query != null) { 520 proxiedURLBase = new URL (proxiedURL.getProtocol(), proxiedURL.getHost(), proxiedURL.getPort() < 1 ? -1 : proxiedURL.getPort() , proxiedURL.getFile()); 521 StringTokenizer t = new StringTokenizer (query, "&"); 522 while (t.hasMoreTokens()) { 523 String parm = t.nextToken(); 524 int pidx = parm.indexOf('='); 525 String name = pidx == -1 ? parm : parm.substring(0, pidx); 526 String value = pidx == -1 ? "" : parm.substring(pidx + 1); 527 put(name, value); 528 } 529 } else { 530 proxiedURLBase = proxiedURL; 531 } 532 } catch (MalformedURLException murle) { 533 log.error("Invalid proxied URL '" + location + "'"); 534 } 535 } 536 537 class FileMultipartInputStream extends FileInputStream { 538 539 private File file; 540 541 FileMultipartInputStream(File file) throws FileNotFoundException { 542 super(file); 543 this.file = file; 544 } 545 546 public void close() throws IOException { 547 super.close(); 548 file.delete(); 549 } 550 551 } 552 } 553 | Popular Tags |