1 7 package org.mmbase.applications.packaging.sharehandlers; 8 9 import java.io.BufferedInputStream ; 10 import java.io.BufferedOutputStream ; 11 import java.io.DataInputStream ; 12 import java.io.DataOutputStream ; 13 import java.io.File ; 14 import java.io.FileInputStream ; 15 import java.io.FileOutputStream ; 16 import java.io.IOException ; 17 import java.io.OutputStream ; 18 import java.io.RandomAccessFile ; 19 import java.util.Hashtable ; 20 import java.util.StringTokenizer ; 21 import java.util.Vector ; 22 23 import javax.servlet.ServletException ; 24 import javax.servlet.http.HttpServletRequest ; 25 import javax.servlet.http.HttpServletResponse ; 26 27 import org.mmbase.applications.packaging.BundleManager; 28 import org.mmbase.applications.packaging.InstallManager; 29 import org.mmbase.applications.packaging.PackageManager; 30 import org.mmbase.applications.packaging.ProviderManager; 31 import org.mmbase.applications.packaging.ShareManager; 32 import org.mmbase.applications.packaging.bundlehandlers.BundleContainer; 33 import org.mmbase.applications.packaging.bundlehandlers.BundleInterface; 34 import org.mmbase.applications.packaging.packagehandlers.PackageContainer; 35 import org.mmbase.applications.packaging.packagehandlers.PackageInterface; 36 import org.mmbase.module.core.MMBaseContext; 37 import org.mmbase.servlet.BridgeServlet; 38 import org.mmbase.util.logging.Logger; 39 import org.mmbase.util.logging.Logging; 40 41 44 public class ShareServlet extends BridgeServlet { 45 46 private static Logger log; 47 48 private static String packagepath = "/mmpm/download/package.mmp"; 49 50 private Hashtable postValues = new Hashtable (); 51 52 private boolean isRequestDecoded = false; 53 private long postid; 54 private HttpServletRequest req = null; 55 int maxLoop = 20000; 56 public static final int DEFAULT_MAX_REQUEST_SIZE = 4 * 1024 * 1024; public static final int DEFAULT_MAX_PARAMETER_SIZE = 4 * 1024 * 1024; public static final int DEFAULT_MAX_IN_MEMORY_PARAMETER_SIZE =4 * 1024 * 1024; 60 private int maxParameterSize = DEFAULT_MAX_PARAMETER_SIZE; 62 private int maxInMemoryParameterSize = DEFAULT_MAX_IN_MEMORY_PARAMETER_SIZE; 63 private String uploadDir = "/tmp/"; 64 private boolean isPostedToDisk = false; 65 66 67 70 71 public void init() throws ServletException { 72 super.init(); 73 log = Logging.getLoggerInstance(ShareServlet.class); 74 packagepath = getInitParameter("packagepath"); 75 } 76 77 78 87 public synchronized void doGet(HttpServletRequest req, HttpServletResponse res) throws ServletException , IOException { 88 res.setContentType("application/x-binary"); 90 91 String request = req.getRequestURI(); 92 if (request.equals(packagepath)) { 93 if (!InstallManager.isRunning()) { 94 InstallManager.init(); 95 } 96 String id = req.getParameter("id"); 97 String version = req.getParameter("version"); 98 99 102 PackageContainer p = (PackageContainer) PackageManager.getPackage(id); 104 if (p != null) { 105 PackageInterface rp = p.getPackageByScore(version); 106 BufferedInputStream in = rp.getJarStream(); 107 int buffersize = 10240; 108 byte[] buffer = new byte[buffersize]; 109 OutputStream out = null; 110 try { 111 out = new BufferedOutputStream (res.getOutputStream()); 112 int len; 113 while ((len = in.read(buffer, 0, buffersize)) != -1) { 114 out.write(buffer, 0, len); 115 } 116 out.flush(); 117 out.close(); 118 } catch (java.io.IOException e) { 119 log.error(Logging.stackTrace(e)); 120 } 121 } 122 123 BundleContainer b = (BundleContainer) BundleManager.getBundle(id); 124 if (b != null) { 125 BundleInterface rb = b.getBundleByScore(version); 126 BufferedInputStream in = rb.getJarStream(); 127 int buffersize = 10240; 128 byte[] buffer = new byte[buffersize]; 129 OutputStream out = null; 130 try { 131 out = new BufferedOutputStream (res.getOutputStream()); 132 int len; 133 while ((len = in.read(buffer, 0, buffersize)) != -1) { 134 out.write(buffer, 0, len); 135 } 136 out.flush(); 137 out.close(); 138 } catch (java.io.IOException e) { 139 log.error(Logging.stackTrace(e)); 140 } 141 } 142 } 143 } 144 145 public synchronized void doPost(HttpServletRequest req, HttpServletResponse res) throws ServletException , IOException { 146 this.req=req; 147 148 String filename = getPostParameter("filename"); 149 String account = getPostParameter("account"); 150 String password = getPostParameter("password"); 151 153 ShareUser user = ShareManager.getShareUser(account); 155 if ( user != null ) { 156 if ( user.getPassword().equals(password) ) { 157 byte[] bytes = getPostParameterBytes("handle"); 158 159 String path=MMBaseContext.getConfigPath()+File.separator+"packaging"+File.separator+"import"+File.separator; 160 161 File file = new File (path+filename); 162 try { 163 DataOutputStream f = new DataOutputStream (new FileOutputStream (file)); 164 f.write(bytes); 165 f.flush(); 166 f.close(); 167 } catch (Exception e) { 168 log.error(Logging.stackTrace(e)); 169 } 170 ProviderManager.resetSleepCounter(); 171 } else { 172 log.info("publish upload with wrong password '"+account+"'"); 173 } 174 } else { 175 log.info("publish upload with the user name '"+account+"', use not found"); 176 } 177 } 178 179 180 186 public String getPostParameter(String name) { 187 Object obj = null; 188 Vector v; 189 190 if (!isRequestDecoded) { 191 decodePost(req); 192 } 193 194 if ((obj = postValues.get(name)) != null) { 195 try { 196 if (obj instanceof String ) { 197 log.error("Use getPostParameterFile"); 198 } 199 } catch (Exception e) { 202 log.error("getPostParameter(" + name + "): " + e); 203 } 204 205 if (obj instanceof Vector ) { 206 v = (Vector )obj; 207 Object elem = v.elementAt(0); 208 if (elem instanceof String ) { 209 return (String )elem; 210 } else { 211 return new String ((byte[])v.elementAt(0)); 212 } 213 } else { 214 return new String ((byte[])obj); 215 } 216 } else { 217 return null; 218 } 219 } 220 221 222 private void decodePost(HttpServletRequest req) { 223 isRequestDecoded = true; 224 byte[] postbuffer = null; 225 226 if (req.getHeader("Content-length") != null || req.getHeader("Content-Length") != null) { 227 postbuffer = readContentLength(req); 228 String line = req.getHeader("Content-type"); 229 if (line == null) { 230 line = req.getHeader("Content-Type"); 231 } 232 233 if (line != null) { 234 if (line.indexOf("application/x-www-form-urlencoded") != -1) { 235 readPostUrlEncoded(postbuffer, postValues); 236 } else if (line.indexOf("multipart/form-data") != -1) { 237 if (!isPostedToDisk) { 238 readPostFormData(postbuffer, postValues, line); 239 } else { 240 readPostFormData( new File (uploadDir,"form_" + postid).getPath(), postValues, line); 241 } 242 } else { 243 log.error("decodePost(): found no 'post' tag in post."); 244 } 245 } else { 246 log.error("decodePost(): can't find Content-Type"); 247 } 248 } else { 249 log.error("decodePost(): found no 'content-length' tag in post."); 250 } 251 } 252 253 254 public byte[] readContentLength(HttpServletRequest req) { 255 int len, len2, len3; 256 byte buffer[] = null; 257 DataInputStream connect_in = null; 258 259 int i = 0; 260 261 try { 262 connect_in = new DataInputStream (req.getInputStream()); 263 } catch (Exception e) { 264 log.error("readContentLength(): can't open input stream"); 265 } 266 267 len = req.getContentLength(); 268 if (len < maxInMemoryParameterSize) { 270 log.debug("readContentLength(): writing to memory."); 271 try { 272 buffer = new byte[len]; 273 len2 = connect_in.read(buffer, 0, len); 274 while (len2 < len && i < maxLoop) { 275 log.debug("readContentLength(): found len2( " + len2 + ")"); 276 len3 = connect_in.read(buffer, len2, len - len2); 277 if (len3 == -1) { 278 log.debug("readContentLength(): WARNING: EOF while not Content Length"); 279 break; 280 } else { 281 len2 += len3; 282 } 283 i++; 284 } 285 if (i >= maxLoop) { 286 log.info("readContentLength(): (memory) broken out of loop after " + i + " times"); 287 } 288 } catch (Exception e) { 289 log.error("readContentLength(): Can't read post msg from client"); 290 log.error(Logging.stackTrace(e)); 291 buffer[len - 1] = -1; 292 295 } 296 } else if (len < maxParameterSize) { 297 log.debug("readContentLength(): writing to disk"); 298 try { 299 isPostedToDisk = true; 300 RandomAccessFile raf = new RandomAccessFile (new File (uploadDir,"form_" + postid), "rw"); 301 int bufferlength = 64000; 302 buffer = new byte[bufferlength]; 303 int index1 = 0, totallength = 0; 304 305 index1 = connect_in.read(buffer); 306 raf.write(buffer, 0, index1); 307 totallength += index1; 308 log.debug("readContentLength(): writing to disk: +"); 309 310 while (totallength < len && i < maxLoop) { 311 index1 = connect_in.read(buffer); 312 raf.write(buffer, 0, index1); 313 if (index1 == -1) { 314 log.error("readContentLength(): EOF while not Content Length"); 315 break; 316 } else { 317 totallength += index1; 318 } 319 i++; 320 } 321 if (i >= maxLoop) { 322 log.info("readContentLength(): (disk) broken out of loop after " + i + " times"); 323 } 324 log.info(" written(" + totallength + ")"); 325 raf.close(); 326 } catch (Exception e) { 327 log.error("readContentLength(): " + e); 328 } 329 } else { 330 log.error("readContentLength(): post too large: " + len + " size"); 331 } 332 return buffer; 333 } 334 335 336 private boolean readPostUrlEncoded(byte[] postbuffer, Hashtable post_header) { 337 String mimestr = ""; 338 int i = 0, idx; 339 char letter; 340 341 String buffer = new String (postbuffer); 342 buffer = buffer.replace('+', ' '); 343 StringTokenizer tok = new StringTokenizer (buffer, "&"); 344 int z = 0; 345 while (tok.hasMoreTokens() && i < maxLoop) { 346 mimestr = tok.nextToken(); 347 if ((idx = mimestr.indexOf('=')) != -1) { 348 while ((i = mimestr.indexOf('%', i)) != -1) { 349 try { 351 letter = (char)Integer.parseInt(mimestr.substring(i + 1, i + 3), 16); 352 mimestr = mimestr.substring(0, i) + letter + mimestr.substring(i + 3); 353 } catch (Exception e) {} 354 355 i++; 356 } 357 addpostinfo2(post_header, mimestr.substring(0, idx), mimestr.substring(idx + 1)); 358 } else { 359 addpostinfo2(post_header, mimestr, ""); 360 } 361 z++; 362 } 363 if (z >= maxLoop) { 364 log.info("readPostUrlEncoded: broken out of loop after " + z + " times"); 365 } 366 return true; 367 } 368 369 370 private final void addpostinfo2(Hashtable postinfo, String name, String values) { 371 Object obj; 372 Vector v = null; 373 374 byte[] value = new byte[values.length()]; 375 values.getBytes(0, values.length(), value, 0); 376 377 if (postinfo.containsKey(name)) { 378 obj = postinfo.get(name); 379 if (obj instanceof byte[]) { 380 v = new Vector (); 381 v.addElement(obj); v.addElement(value); postinfo.put(name, v); 384 } else if (obj instanceof Vector ) { 385 v = (Vector )obj; 386 v.addElement(value); 387 } else { 388 log.error("addpostinfo(" + name + "," + value + "): object " + v + " is not Vector or byte[]"); 389 } 390 } else { 391 postinfo.put(name, value); 392 } 393 } 394 395 396 public boolean readPostFormData(byte[] postbuffer, Hashtable post_header, String line) { 397 int i2, i3, i4, start2, end2; 398 String r; 399 String templine = "--" + line.substring(line.indexOf("boundary=") + 9); 400 byte[] marker = new byte[templine.length()]; 401 byte[] marker2 = new byte[4]; 402 byte[] marker3 = new byte[1]; 403 byte[] marker4 = new byte[1]; 404 byte[] dest; 405 marker2[0] = (byte)'\r'; 406 marker2[1] = (byte)'\n'; 407 marker2[2] = (byte)'\r'; 408 marker2[3] = (byte)'\n'; 409 marker3[0] = (byte)'='; 410 marker4[0] = (byte)'\"'; 411 templine.getBytes(0, templine.length(), marker, 0); 412 413 start2 = indexOf(postbuffer, marker, 0) + marker.length; 414 415 int z = 0; 416 do { 417 end2 = indexOf(postbuffer, marker, start2); 419 if (end2 < 0) { 420 log.error("readPostFormData(): postbuffer < 0 !!!! "); 421 break; 422 } 423 424 i2 = indexOf(postbuffer, marker2, start2); 426 427 437 String disposition = new String (postbuffer, start2 + 2, i2 - (start2 + 2)); 438 int separator = indexOf(postbuffer, new byte[] {(byte)'\r', (byte)'\n' }, start2 + 2); 439 440 int filesize = (end2 - i2 - 6); 441 if (filesize < 0) 442 filesize = 0; 448 if (separator > start2 + 2 && separator < i2) { 449 try { 450 String [] dispositionInfo = extractDispositionInfo(disposition.substring(0, separator - (start2 + 2))); 451 String mimetype = extractContentType(disposition.substring(separator - (start2 + 2) + 2)); 452 String fieldname = dispositionInfo[1]; 453 String filename = dispositionInfo[2]; 454 Vector v1 = new Vector (); 455 v1.addElement(mimetype.getBytes()); 456 addpostinfo(post_header, fieldname + "_type", v1); 457 Vector v2 = new Vector (); 458 v2.addElement(filename.getBytes()); 459 addpostinfo(post_header, fieldname + "_name", v2); 460 461 Vector v3 = new Vector (); 462 v3.addElement("" + filesize); 463 addpostinfo(post_header, fieldname + "_size", v3); 464 465 if (log.isDebugEnabled()) { 466 log.debug("mimetype = " + mimetype); 467 log.debug("filename = " + dispositionInfo[2]); 468 log.debug("filesize = " + filesize); 469 } 470 } catch (IOException e) { 471 log.error(e.getMessage()); 472 } 473 } 474 476 i3 = indexOf(postbuffer, marker3, start2 + 2) + 2; 477 i4 = indexOf(postbuffer, marker4, i3 + 2); 478 r = new String (postbuffer, i3, (i4 - i3)); dest = new byte[filesize]; 483 System.arraycopy(postbuffer, i2 + 4, dest, 0, filesize); 484 486 addpostinfo(post_header, r, dest); 487 start2 = end2 + marker.length; 488 z++; 489 } while (postbuffer[start2] != '-' && z < maxLoop); 490 if (z >= maxLoop) { 491 log.info("readPostFormData: broken out of loop after " + z + " times"); 492 } 493 return false; 494 } 495 496 497 private final void addpostinfo(Hashtable postinfo, String name, Object value) { 498 Object obj; 499 Vector v = null; 500 501 if (postinfo.containsKey(name)) { 502 obj = postinfo.get(name); 503 if (obj instanceof byte[]) { 504 v = new Vector (); 505 v.addElement(obj); v.addElement(value); postinfo.put(name, v); 508 } else if (obj instanceof Vector ) { 509 v = (Vector )obj; 510 v.addElement(value); 511 } else { 512 log.error("addpostinfo(" + name + "," + value + "): object " + v + " is not Vector or byte[]"); 513 } 514 } else { 515 postinfo.put(name, value); 516 } 517 } 518 519 520 private int indexOf(byte v1[], byte v2[], int fromIndex) { 521 522 int max = (v1.length - v2.length); 523 524 test : for (int i = ((fromIndex < 0) ? 0 : fromIndex); i <= max; i++) { 528 int n = v2.length; 529 int j = i; 530 int k = 0; 531 while (n-- != 0) { 532 if (v1[j++] != v2[k++]) { 533 continue test; 534 } 535 } 536 return i; 537 } 538 return -1; 539 } 540 541 542 private String [] extractDispositionInfo(String line) throws IOException { 543 String [] retval = new String [3]; 544 545 String origline = line; 548 line = origline.toLowerCase(); 549 550 int start = line.indexOf("content-disposition: "); 552 int end = line.indexOf(";"); 553 if (start == -1 || end == -1) { 554 throw new IOException ("Content disposition corrupt: " + origline); 555 } 556 String disposition = line.substring(start + 21, end); 557 if (!disposition.equals("form-data")) { 558 throw new IOException ("Invalid content disposition: " + disposition); 559 } 560 561 start = line.indexOf("name=\"", end); end = line.indexOf("\"", start + 7); if (start == -1 || end == -1) { 565 throw new IOException ("Content disposition corrupt: " + origline); 566 } 567 String name = origline.substring(start + 6, end); 568 569 String filename = null; 571 start = line.indexOf("filename=\"", end + 2); end = line.indexOf("\"", start + 10); if (start != -1 && end != -1) { filename = origline.substring(start + 10, end); 575 int slash = Math.max(filename.lastIndexOf('/'), filename.lastIndexOf('\\')); 577 if (slash > -1) { 578 filename = filename.substring(slash + 1); } 580 581 if (filename.equals("")) { 582 filename = "unknown"; } 584 585 } 586 587 retval[0] = disposition; 589 retval[1] = name; 590 retval[2] = filename; 591 return retval; 592 } 593 594 595 private String extractContentType(String line) throws IOException { 596 String contentType = null; 597 598 String origline = line; 600 line = origline.toLowerCase(); 601 602 if (line.startsWith("content-type")) { 604 int start = line.indexOf(" "); 605 if (start == -1) { 606 throw new IOException ("Content type corrupt: " + origline); 607 } 608 contentType = line.substring(start + 1); 609 } else if (line.length() != 0) { throw new IOException ("Malformed line after disposition: " + origline); 611 } 612 613 return contentType; 614 } 615 616 617 public boolean readPostFormData(String formFile, Hashtable post_header, String line) { 618 FileInputStream fis = null; 619 RandomAccessFile raf = null; 620 try { 621 fis = new FileInputStream (formFile); 622 } catch (Exception e) { 623 System.out.println("WorkerPostHandler -> File " + formFile + " not exist"); 624 } 625 int i, i2, i3, i4, start2, end2; 626 String r; 627 String templine = "--" + line.substring(line.indexOf("boundary=") + 9); 628 byte[] marker = new byte[templine.length()]; 629 byte[] marker2 = new byte[4]; 630 byte[] marker3 = new byte[1]; 631 byte[] marker4 = new byte[1]; 632 byte[] dest; 633 marker2[0] = (byte)'\r'; 634 marker2[1] = (byte)'\n'; 635 marker2[2] = (byte)'\r'; 636 marker2[3] = (byte)'\n'; 637 marker3[0] = (byte)'='; 638 marker4[0] = (byte)'\"'; 639 templine.getBytes(0, templine.length(), marker, 0); 640 log.info("readPostFormData(): begin"); 641 642 int offset = 0; 643 int len = 64000; 645 byte postbuffer[] = new byte[len]; 646 try { 647 len = fis.read(postbuffer); 649 650 start2 = indexOf(postbuffer, marker, 0) + marker.length; 652 i = 0; 653 do { 654 i3 = indexOf(postbuffer, marker3, start2 + 2) + 2; 656 i4 = indexOf(postbuffer, marker4, i3 + 2); 657 r = new String (postbuffer, i3, (i4 - i3)); 658 log.debug("readPostFormData(): postName=" + r); 659 660 end2 = indexOf(postbuffer, marker, start2); 662 i2 = indexOf(postbuffer, marker2, start2); 663 664 if (end2 == -1) { 665 log.info("readPostFormData(): writing to postValue: "); 666 File f = new File (uploadDir,"form_" + postid + "_" + r); 667 raf = new RandomAccessFile (f, "rw"); 668 addpostinfo(post_header, r, f.getPath()); 669 try { 670 raf.write(postbuffer, i2 + 4, len - (i2 + 4)); 671 } catch (Exception e) { 672 log.error("readPostFormData(): Cannot write into file(1)" + e); 673 } 674 offset = len - i2 + 4; 675 int j = 0; 676 do { 677 fis.read(postbuffer); 680 681 end2 = indexOf(postbuffer, marker, 0); 682 if (end2 == -1) { 683 raf.write(postbuffer); 684 } else { 685 raf.write(postbuffer, 0, end2 - 2); 686 } 687 offset += len; 688 j++; 689 } while (end2 == -1 && j < maxLoop); 690 if (j >= maxLoop) { 691 log.info("readPostFormData(): (inner) broken out of loop after " + j + " times"); 692 } 693 start2 = end2 + marker.length; 694 raf.close(); 695 } else { 696 dest = new byte[(end2 - i2) - 6]; 697 System.arraycopy(postbuffer, i2 + 4, dest, 0, (end2 - i2) - 6); 698 699 addpostinfo(post_header, r, dest); 700 start2 = end2 + marker.length; 701 } 702 i++; 703 } 704 while (postbuffer[start2] != '-' && i < maxLoop); 705 if (i >= maxLoop) { 706 log.info("readPostFormData(): (outer) broken out of loop after " + i + " times"); 707 } 708 } catch (Exception e) { 709 log.error("readPostFormData(): Reached end of file: " + e); 710 } 711 return false; 712 } 713 714 715 public byte[] getPostParameterBytes(String name) { 716 if (!isRequestDecoded) { 718 decodePost(req); 719 } 720 721 Object obj = postValues.get(name); 723 if (obj == null) { 724 return null; 725 } 726 727 if (obj instanceof String ) { 729 String msg = "Use getPostParameterFile"; 730 log.warn(msg); 731 } 732 if (obj instanceof Vector ) { 733 Vector v = (Vector )obj; 734 byte[] data = (byte[])v.elementAt(0); 735 return data; 736 } 737 byte[] data = (byte[])obj; 738 return data; 739 } 740 } 741 742 | Popular Tags |