1 package webman.stager; 2 3 import java.net.*; 4 import java.security.*; 5 import java.io.*; 6 import java.util.*; 7 import java.lang.reflect.*; 8 import javax.net.ssl.*; 9 import com.ringlord.archive.*; 11 import org.apache.log4j.*; 12 13 19 public class SiteReceiver extends Stager 20 { 21 22 private final static Category CAT = Category.getInstance(SiteReceiver.class); 23 24 25 public final String INTERNAL_VERSION = "1.49"; 26 27 28 public final static String DEFAULT_SITE_LISTING_NAME = "sitereceiver.doclist"; 29 30 public final static String DEFAULT_LOGFILE_NAME = "sitereceiver.log"; 31 32 public final static String DEFAULT_KEYSTORE_FILE = "testkeys.sitereceiver"; 33 34 public final static String DEFAULT_KEYSTORE_PASSWORD = "passphrase"; 35 36 public final static String DEFAULT_RECEIVER_PORT = "4242"; 37 38 public final static String DEFAULT_OPEN_SOCKET_TIMEOUT_SECONDS = "60"; 39 40 public final static int MAX_OPEN_TIMEOUT_SECONDS = 300; 41 42 private final static int MILLIS_PER_SECOND = 1000; 43 44 private final static int RECEIVE_SITE_BUFSIZE = 2048; 45 46 private final static int SLEEP_TIME = 1000; 47 48 private final static int MIN_PORT = 1024; 49 50 private final static int MAX_PORT = 65535; 51 52 private final static int ZIP_BUFSIZE = 16384; 53 55 56 private PropertySet properties; 57 58 private PropertySet queryStringProperties = null; 59 60 SSLSocket clientSocket = null; 61 62 private SSLServerSocket serverSocket = null; 63 64 private SSLServerSocketFactory serverSocketFactory = null; 65 66 private int zipSize; 67 68 private SiteDocumentsListing sendSiteListing = null; 69 70 private SiteDocumentsListing oldListing = null; 71 72 private SiteDocumentsListing newListing = null; 73 74 private Vector vLog = new Vector(); 75 76 private boolean vLogStarted = false; 77 78 private static boolean instanceRunning = false; 79 80 private int updatedFiles = 0; 81 82 private int updatedDirs = 0; 83 84 private String fuckJTest; 85 86 90 public static void main(String [] args) 91 { 92 if ( instanceRunning ) 93 { 94 System.exit(1); 95 } 96 else 97 { 98 instanceRunning = true; 99 new SiteReceiver(args); 100 } 101 } 102 103 107 private SiteReceiver(String [] args) 108 { 109 outStream = System.out; String propertyFile, remoteIP; 111 remoteIP = "127.0.0.1"; CAT.info("WebMan SiteReceiver starting at " + new java.util.Date ()); 114 try 115 { 116 remoteIP = args[0]; 118 propertyFile = args[1]; 119 if ( args.length > 2 ) { 121 CAT.debug("PARSING properties from urlString..."); 122 queryStringProperties = new PropertySet(parseQueryString(args[2])); 123 } 124 else 125 { 126 queryStringProperties = null; 127 } 128 CAT.debug("PARSING properties from file..."); 130 properties = readProperties(propertyFile); 131 } 132 catch (Exception e) 133 { 134 error("Error in configuration: ",e); 135 error("SiteReceiver stopped."); 136 printUsage(); 137 System.exit(-1); 138 } 139 140 logfile = openLog(properties.get("logFile"),properties.get("appendLog").equals("true")); 142 if ( logfile == null ) 143 { 144 error("Could not open logfile " + properties.get("logFile")); 145 error("SiteReceiver stopped."); 146 System.exit(-1); 147 } 148 logAndPrint("<h2>WebMan Stager: SiteReceiver</h2>"); 149 logAndPrint("<B>started at " + new java.util.Date () + "</B>"); 150 logAndPrint("Java version: " + System.getProperty("java.version") + ", Java vendor: " 151 + System.getProperty("java.vendor") + ", SiteReceiver-Version: " + INTERNAL_VERSION); 152 try 153 { 154 logAndPrint("Remote host: " + InetAddress.getByName(remoteIP)); 155 } 156 catch( Exception e) 157 { 158 logAndPrint("Remote host: " + remoteIP + " (unknown host)"); 159 } 160 if ( !transferAllowedFrom(remoteIP,properties.get("SenderIP")) ) 162 { 163 error("Request denied because IP " + remoteIP + " is not allowed"); 164 error("SiteReceiver stopped."); 165 System.exit(-1); 166 } 167 logAndPrint("ReceiverPort: " + properties.get("ReceiverPort")); 168 logAndPrint("TempDir: " + markAsFile(properties.get("tempDir"))); 169 if ( properties.get("appendLog").equals("true") ) 170 { 171 logAndPrint("Appending log to " + markAsFile(properties.get("logFile"))); 172 } 173 else 174 { 175 logAndPrint("Creating log in " + markAsFile(properties.get("logFile"))); 176 } 177 try 178 { 179 logAndPrint("Using site documents listing " + markAsFile(properties.get("siteDocumentsListing"))); 180 oldListing = new SiteDocumentsListing(properties.get("siteDocumentsListing")); 181 } 182 catch ( IOException e) 183 { 184 logAndPrint("Found no old listing at " + markAsFile(properties.get("siteDocumentsListing"))); 185 } 186 try 187 { 188 logAndPrint("ReceiverHost: " + (properties.get("ReceiverHost").equals("localhost") 189 ? InetAddress.getLocalHost() 190 : InetAddress.getByName(properties.get("ReceiverHost")))); 191 } 192 catch (java.net.UnknownHostException e) 193 { 194 error("Server IP is unknown",e); 195 } 196 if ( properties.get("Simulate").equals("true") ) 197 { 198 logAndPrint(" "); 199 logAndPrint("<B> --- Entering Simulation Mode: No files are changed (except logfile and temporary directory). --- </B>"); 200 logAndPrint(" "); 201 } 202 try 203 { 204 boolean success = true; 206 int openSocketTimeout = MILLIS_PER_SECOND * Integer.parseInt(properties.get("OpenSocketTimeoutSeconds")); 207 try 208 { 209 214 if ( !methodSucceed(initSSL(), "initializing ssl") 216 || !methodSucceed(prepareSSL(properties.get("keyStore"), properties.get("keyStorePassword"), 218 properties.get("keyPassword"),properties.get("trustStore"))) 219 || !methodSucceed(createTempDir(properties.get("tempDir")), "creating temp dir") 221 || !methodSucceed(createConnection(properties.get("ReceiverHost"), 223 Integer.parseInt(properties.get("ReceiverPort")),openSocketTimeout, 224 !properties.get("trustStore").equals(""))) 225 || !methodSucceed(receiveFileSize(), "receiving file size") 227 || !methodSucceed(receiveSite(properties.get("archiveName"))) 229 || !methodSucceed(receiveSiteInfo(), "receiving site info") 231 || !methodSucceed(extractSite(properties.get("tempDir"),properties.get("archiveName"), 233 properties.get("SkipErrors").equals("true"), 234 properties.get("Simulate").equals("true")) ) 235 ) 236 { 237 success = false; 238 } 239 } 240 catch (Exception e) 242 { 243 error("Unknown exception: ",e); 244 success = false; 245 } 246 if ( properties.get("AfterBurner") != null ) 248 { 249 String afterBurner = properties.get("AfterBurner"); 250 Vector params = properties.getPropertyGroup("AfterBurnerParameter"); 251 String [] strParams = new String [params.size()]; 253 String paramString = ""; 254 for ( int i=0; i<params.size(); i++ ) 255 { 256 strParams[i] = (String )params.elementAt(i); 257 paramString += strParams[i] + " "; 258 } 259 logAndPrint("<B>running AfterBurner</B>"); 260 boolean noJava = properties.get("AfterBurnerNoJava").equals("true"); 261 logAndPrint((noJava ? "" : "java ") + afterBurner + " " + "<I>" + paramString + "</I>"); 262 if ( !doAfterBurner(afterBurner,strParams,noJava) ) 263 { 264 success = false; 265 CAT.warn("AfterBurner failed"); 266 } 267 else 268 { 269 logAndPrint("<B>... done</B>"); 270 } 271 } 272 if ( clientSocket == null ) 274 { 275 logAndPrint("skipping log transmission (no socket available)"); 276 } 277 else if ( !methodSucceed(transmitLog(success),"transmitting log") ) 278 { 279 success = false; 280 } 281 if ( !success ) 282 { 283 Enumeration appenders = CAT.getRoot().getAllAppenders(); 285 Vector logNames = new Vector(); 286 Object appender; 287 while ( appenders.hasMoreElements() ) 288 { 289 appender = appenders.nextElement(); 290 if ( appender instanceof FileAppender ) 291 { 292 logNames.add( ((FileAppender)appender).getFile() ); 293 } 294 } 295 if ( logNames.size() > 0 ) 296 { 297 String hint = "Something went wrong. You should check the Log4J-Logfiles: "; 298 for ( int i=0; i<logNames.size(); i++ ) 299 { 300 hint += (String )logNames.elementAt(i); 301 if ( i<logNames.size()-1 ) 302 { 303 hint += ", "; 304 } 305 } 306 error(hint + "."); 307 } 308 logAndPrint("abort"); 309 System.exit(-1); 310 } 311 logAndPrint("WebMan SiteReceiver finished at " + new java.util.Date ()); 313 } 314 315 finally 316 { 317 try 318 { 319 clientSocket.close(); 320 serverSocket.close(); 321 closeLog(); 322 } 323 catch (Exception e) 324 { 325 fuckJTest = "wen interessiert's?"; 326 } 327 } 328 System.exit(0); 330 } 331 332 337 private Hashtable parseQueryString(String query) 338 { 339 Hashtable result = new Hashtable(); 340 String pair, key, value; 341 int delimiter; 342 343 StringTokenizer tokenizer = new StringTokenizer(query,"&"); 344 while ( tokenizer.hasMoreTokens() ) 345 { 346 pair = tokenizer.nextToken(); 347 delimiter = pair.indexOf('='); 348 if (delimiter > -1) 349 { 350 key = pair.substring(0,delimiter); 351 value = pair.substring(delimiter+1); 352 if (value.length() > 0) 353 { try 355 { 356 result.put(URLDecoder.decode(key),URLDecoder.decode(value)); 357 } 358 catch (Exception e) 359 { 360 fuckJTest="was immer hier auch schief gehen könnte."; 361 } 362 } 363 } 364 } 365 return result; 366 } 367 368 374 private PropertySet readProperties(String propertyFile) throws WrongConfigurationException 375 { 376 Properties p = new Properties(); 378 try 381 { 382 p.load(new FileInputStream(propertyFile)); 383 } 384 catch (Exception e) 385 { 386 throw new WrongConfigurationException("Could not read property file \"" + propertyFile + "\": " + e.toString()); 387 } 388 PropertySet source = new PropertySet(p); return parseProperties(source); 390 } 391 392 398 private PropertySet parseProperties(PropertySet source) throws WrongConfigurationException 399 { 400 PropertySet result = new PropertySet(); 401 try 402 { 403 String temp = null; File tempFile = null; 406 result.set("logDir",new File(getProperty(source,"logDir")).getCanonicalPath()); 407 CAT.debug("LogDir=" + result.get("logDir")); 408 tempFile = new File(result.get("logDir")); 409 if ( !tempFile.exists() ) 410 { 411 throw new WrongConfigurationException("LogDir " + tempFile.getPath() + " doesn't exist."); 412 } 413 else if ( !tempFile.canWrite() ) 414 { 415 throw new WrongConfigurationException("Cannot write to LogDir " + tempFile.getPath()); 416 } 417 418 if ( queryStringProperties != null && queryStringProperties.get("LogFile") != null ) 420 { 421 temp = queryStringProperties.get("LogFile"); 422 } 423 else 424 { 425 try 426 { 427 temp = getProperty(source,"LogFile"); 428 } 429 catch ( PropertyNotFoundException p ) 430 { 431 temp = DEFAULT_LOGFILE_NAME; 432 } 433 } 434 result.set("logFile",getAbsoluteName(result.get("logDir"),temp)); 435 CAT.debug("logFile=" + result.get("logFile")); 436 437 if ( queryStringProperties != null && queryStringProperties.get("siteDocumentsListing") != null ) 439 { 440 temp = queryStringProperties.get("siteDocumentsListing"); 441 } 442 else 443 { 444 try 445 { 446 temp = getProperty(source,"siteDocumentsListing"); 447 } 448 catch ( PropertyNotFoundException p ) 449 { 450 temp = DEFAULT_SITE_LISTING_NAME; 451 } 452 } 453 result.set("siteDocumentsListing",getAbsoluteName(result.get("logDir"),temp)); 454 CAT.debug("siteDocumentsListing=" + result.get("siteDocumentsListing")); 455 456 result.set("SkipErrors","false"); 458 if ( queryStringProperties != null && queryStringProperties.get("SkipErrors") != null ) 461 { 462 if ( queryStringProperties.get("SkipErrors").equals("yes") ) 463 { 464 result.set("SkipErrors","true"); 465 } 466 } 467 else 468 { 469 temp = source.get("SkipErrors"); 470 if ( temp != null && temp.toLowerCase().equals("yes") ) 471 { 472 result.set("SkipErrors","true"); 473 } 474 } 475 CAT.debug("SkipErrors=" + result.get("SkipErrors")); 476 477 result.set("Simulate","false"); 479 if ( queryStringProperties != null && queryStringProperties.get("Simulate") != null ) 482 { 483 if ( queryStringProperties.get("Simulate").equals("yes") ) 484 { 485 result.set("Simulate","true"); 486 } 487 } 488 else 489 { 490 temp = source.get("Simulate"); 491 if ( temp != null && temp.toLowerCase().equals("yes") ) 492 { 493 result.set("Simulate","true"); 494 } 495 } 496 CAT.debug("Simulate=" + result.get("Simulate")); 497 498 temp = new File(getProperty(source,"TempDir")).getCanonicalPath(); 500 tempFile = new File(temp); 501 if ( !tempFile.exists() ) 502 { 503 throw new WrongConfigurationException("TempDir " + temp + " doesn't exist."); 504 } 505 if ( !tempFile.isDirectory() || !tempFile.canRead() || !tempFile.canWrite() ) 506 { 507 throw new WrongConfigurationException("TempDir " + temp + " is not a readable/writeable directory."); 508 } 509 try 511 { tempFile = File.createTempFile("webman_received",".zip",new File(temp)); 513 tempFile.delete(); 514 result.set("archiveName",tempFile.getPath()); 515 CAT.debug("ArchiveName=" + result.get("archiveName")); 516 517 tempFile = File.createTempFile("webman_site","",new File(temp)); 518 tempFile.delete(); 519 520 temp = tempFile.getPath(); 522 if ( !temp.endsWith(File.separator) && !temp.endsWith("/") ) 523 { temp += File.separator; 525 } 526 result.set("tempDir",temp); 527 CAT.debug("TempDir=" + result.get("TempDir")); 528 } 529 catch (IOException e) 530 { 531 throw new WrongConfigurationException("Cannot create temporary files in TempDir " + temp + "."); 532 } 533 534 try 535 { 536 temp = getProperty(source, "AppendLog"); 537 if ( temp.toLowerCase().equals("yes") ) 538 { 539 result.set("appendLog","true"); 540 } 541 else 542 { 543 result.set("appendLog","false"); 544 } 545 } 546 catch (Exception e) 547 { 548 result.set("appendLog","false"); } 550 CAT.debug("AppendLog=" + result.get("AppendLog")); 551 552 try 553 { 554 result.set("keyStore",getProperty(source,"KeyStore")); 555 } 556 catch (PropertyNotFoundException p) 557 { 558 result.set("keyStore",DEFAULT_KEYSTORE_FILE); 559 } 560 CAT.debug("keyStore=" + result.get("keyStore")); 561 562 try 563 { 564 result.set("KeyStorePassword",getProperty(source,"KeyStorePassword")); 565 } 566 catch (PropertyNotFoundException p) 567 { 568 result.set("KeyStorePassword",DEFAULT_KEYSTORE_PASSWORD); 569 } 570 CAT.debug("KeyStorePassword=" + result.get("KeyStorePassword")); 571 572 try 573 { 574 result.set("KeyPassword",getProperty(source,"KeyPassword")); 575 } 576 catch (PropertyNotFoundException p) 577 { 578 result.set("KeyPassword",result.get("KeyStorePassword")); 579 } 580 CAT.debug("KeyPassword=" + result.get("KeyPassword")); 581 582 try 584 { 585 result.set("trustStore",getProperty(source,"TrustStore")); 586 } 587 catch (PropertyNotFoundException p) 588 { 589 result.set("trustStore",""); 590 } 591 CAT.debug("trustStore=" + result.get("trustStore")); 592 593 try 594 { 595 int port = Integer.parseInt(getProperty(source,"ReceiverPort")); if ( port < MIN_PORT || port > MAX_PORT ) 597 { 598 throw new NumberFormatException (); 599 } 600 result.set("ReceiverPort",String.valueOf(port)); 601 } 602 catch (NumberFormatException n) 603 { 604 throw new WrongConfigurationException("ReceiverPort must be within 1024...65535"); 605 } 606 catch (PropertyNotFoundException p) 607 { 608 result.set("ReceiverPort",DEFAULT_RECEIVER_PORT); 609 } 610 CAT.debug("ReceiverPort=" + result.get("ReceiverPort")); 611 612 result.set("SenderIP",getProperty(source, "SenderIP")); 613 CAT.debug("SenderIP=" + result.get("SenderIP")); 614 615 try 616 { temp = getProperty(source,"OpenSocketTimeoutSeconds"); 618 if ( temp != null && (Integer.parseInt(temp) < 1 || Integer.parseInt(temp) > MAX_OPEN_TIMEOUT_SECONDS) ) 620 { 621 throw new WrongConfigurationException("OpenSocketTimeoutSeconds must be within 1.." + MAX_OPEN_TIMEOUT_SECONDS); 622 } 623 } 624 catch ( PropertyNotFoundException p ) 625 { 626 temp = DEFAULT_OPEN_SOCKET_TIMEOUT_SECONDS; 627 } 628 result.set("OpenSocketTimeoutSeconds",temp); 629 CAT.debug("OpenSocketTimeoutSeconds=" + result.get("OpenSocketTimeoutSeconds")); 630 631 try 632 { 633 result.set("ReceiverHost",getProperty(source,"ReceiverHost")); 634 } 635 catch (Exception e) 636 { result.set("ReceiverHost","localhost"); 638 } 639 CAT.debug("ReceiverHost=" + result.get("ReceiverHost")); 640 641 if ( queryStringProperties != null && queryStringProperties.get("AfterBurner") != null ) 644 { 645 result.set("AfterBurner",queryStringProperties.get("AfterBurner")); 646 CAT.debug("AfterBurner=" + result.get("AfterBurner")); 647 temp = queryStringProperties.get("AfterBurnerNoJava"); 648 if ( temp != null && temp.equals("true") ) 649 { 650 result.set("AfterBurnerNoJava","true"); 651 } 652 else 653 { 654 result.set("AfterBurnerNoJava","false"); 655 } 656 CAT.debug("AfterBurnerNoJava=" + result.get("AfterBurnerNoJava")); 657 Vector params = queryStringProperties.getPropertyGroup("AfterBurnerParameter"); 658 for ( int i=0; i<params.size(); i++) 659 { 660 result.set("AfterBurnerParameter" + i,params.elementAt(i)); 661 } 662 } 663 } 664 catch (PropertyNotFoundException p) 665 { 666 throw new WrongConfigurationException(p); 667 } 668 catch (Exception e) { 670 if ( !(e instanceof WrongConfigurationException) ) 671 { CAT.error("Unknown Exception: " + e.getMessage(),e); throw new WrongConfigurationException(e.toString()); 674 } 675 else 676 { throw (WrongConfigurationException)e; 678 } 679 } 680 return result; 681 } 682 683 691 private String prepareSSL(String keyStore, String keyStorePassword, String keyPassword, String trustStore) 692 { 693 logAndPrint("<b>preparing ssl connection</b>"); 694 try 695 { 696 700 701 KeyStore ks = KeyStore.getInstance("JKS"); 702 703 com.sun.net.ssl.TrustManagerFactory tmf = null; 704 if ( !trustStore.equals("") ) 706 { 707 tmf = com.sun.net.ssl.TrustManagerFactory.getInstance("SunX509"); 708 ks.load(Stager.getResourceInputStream(this.getClass(),trustStore),null); 709 tmf.init(ks); 710 logAndPrint("using TrustStore " + markAsFile(trustStore) + " (for client authentication)"); 711 } 712 713 com.sun.net.ssl.SSLContext ssl = com.sun.net.ssl.SSLContext.getInstance("SSL"); 714 715 com.sun.net.ssl.KeyManagerFactory kmf = com.sun.net.ssl.KeyManagerFactory.getInstance("SunX509"); 716 ks.load(Stager.getResourceInputStream(this.getClass(),keyStore),keyStorePassword.toCharArray()); 717 logAndPrint("using KeyStore " + markAsFile(keyStore) + " (for server authentication)"); 718 719 kmf.init(ks, keyPassword.toCharArray()); 720 ssl.init(kmf.getKeyManagers(), (tmf==null ? null : tmf.getTrustManagers()), null); 721 serverSocketFactory = ssl.getServerSocketFactory(); 722 } 723 catch (Exception e) 724 { 725 return "unable to create ssl socket factory: " + e; 726 } 727 return null; 728 } 729 730 737 private String createConnection(String ipaddress, int receiverPort, int timeOut, boolean useClientAuth) 738 { 739 try 740 { 741 logAndPrint("<b>creating server socket</b>"); 742 serverSocket = (SSLServerSocket)serverSocketFactory.createServerSocket( 743 receiverPort, 1, ipaddress.equals("localhost") ? InetAddress.getLocalHost() 745 : InetAddress.getByName(ipaddress)); 746 if ( useClientAuth ) 750 { 751 logAndPrint("demanding SSL client authentication"); 752 serverSocket.setNeedClientAuth(useClientAuth); 753 } 754 CAT.debug("createConnection(): serverSocket created"); 755 } 756 catch (Exception e) 757 { 758 return "unable to create server socket: " + e; 759 } 760 logAndPrint("starting ClientConnector..."); 761 ClientConnector acceptor = new ClientConnector(this,serverSocket); 763 logAndPrint("opened server socket at " + new java.util.Date ()); 764 acceptor.start(); 765 long start_time = System.currentTimeMillis(); 766 try 767 { 768 while ( System.currentTimeMillis() - start_time < timeOut && clientSocket == null ) 769 { 770 Thread.sleep(SLEEP_TIME); 771 } 772 } 773 catch (Exception e) 774 { 775 return "server interrupted: " + e; 776 } 777 if ( clientSocket == null ) 778 { 779 try 780 { 781 serverSocket.close(); 782 logAndPrint("closed server socket at " + new java.util.Date ()); 783 } 784 catch (Exception e) 785 { 786 return "connection from client failed - time out, but cannot close server socket: " + e; 787 } 788 return "connection from client failed - time out"; 789 } 790 if ( !transferAllowedFrom(clientSocket.getInetAddress().getHostAddress(),properties.get("SenderIP"))) 792 { 793 try 794 { 795 printToSocket(clientSocket, "request denied"); 796 } 797 catch (Exception e) 798 { 799 CAT.warn("request denied because ip " + clientSocket.getInetAddress() + " not allowed"); 800 } 801 return "request denied"; 802 } 803 try 804 { 805 printToSocket(clientSocket, "ready"); 806 } 807 catch (Exception e) 808 { 809 return e.toString(); 810 } 811 try 812 { 813 clientSocket.setSoTimeout(0); 814 } 815 catch (Exception e) 816 { 817 return e.toString(); 818 } 819 logAndPrint("end of http output"); vLogStarted = true; 822 return null; 823 } 824 825 829 private String receiveFileSize() 830 { 831 String line; 833 try 834 { 835 line = readFromSocket(clientSocket); 836 } 837 catch (Exception e) 838 { 839 return "unable to read from socket: " + e.toString(); 840 } 841 if ( line == null ) 842 { 843 return "received null instead of zip-size"; 844 } 845 if ( !line.startsWith("zip.size=") ) 846 { 847 return "wrong format: " + markAsFile(line) + " - expected " + markAsFile("zip.size=[0-9]+"); 848 } 849 line = line.substring(9, line.length()); 850 try 851 { 852 zipSize = Integer.parseInt(line); 853 } 854 catch (Exception e) 855 { 856 return "wrong format: " + markAsFile(line) + e + " - expected " + markAsFile("zip.size=[0-9]+"); 857 } 858 return null; 859 } 860 861 866 private String createTempDir(String tempDir) 867 { 868 File tmp = new File(tempDir); 870 int fileCount = 0; 871 if ( tmp.exists() ) 872 { 873 if ( !tmp.isDirectory() ) 874 { 875 return("could not create temporary directory " + markAsFile(tempDir) + " - file of same name does exist"); 876 } 877 logAndPrint("Deleting files in temporary dir: " + tempDir); 878 String [] list = tmp.list(); 879 for ( int i = 0; i < list.length; i++ ) 880 { 881 fileCount += deleteFile(tempDir + File.separator + list[i]); 882 } 883 CAT.info(fileCount + " files/dirs deleted in temporary dir " + tempDir); 884 } 885 else if ( !tmp.mkdirs() ) 886 { 887 return "could not create temporary directory " + markAsFile(tempDir); 888 } 889 return null; 890 } 891 892 897 private String receiveSite(String archiveName) 898 { 899 logAndPrint("<b>receiving site</b>"); 900 try 901 { 902 FileOutputStream fout = new FileOutputStream(archiveName); 903 BufferedInputStream in = new BufferedInputStream(clientSocket.getInputStream()); 904 byte[] buf = new byte[RECEIVE_SITE_BUFSIZE]; 905 int to_read = zipSize; int read; 907 908 logAndPrint("start receiving site: " + (new Date()).toString() + " "); 909 logAndPrint("wait until " + zipSize + " bytes are received..."); 910 while ( to_read > 0 ) 911 { 912 if ( to_read < RECEIVE_SITE_BUFSIZE ) 913 { 914 read = in.read(buf, 0, to_read); 915 } 916 else 917 { 918 read = in.read(buf, 0, RECEIVE_SITE_BUFSIZE); 919 } 920 fout.write(buf, 0, read); 921 to_read -= read; 922 } 923 logAndPrint("finish receiving site: " + (new Date()).toString()); 924 fout.flush(); 925 fout.close(); 926 } 927 catch (Exception e) 928 { 929 return "unable to receive zip file: " + e; 930 } 931 return null; 932 } 933 934 938 private String receiveSiteInfo() 939 { 940 try 941 { 942 InputStream in = clientSocket.getInputStream(); 943 ObjectInputStream ois = new ObjectInputStream(in); 944 sendSiteListing = (SiteDocumentsListing)ois.readObject(); 945 } 946 catch (Exception e) 947 { 948 return "unable to receive site info: " + e.toString(); 949 } 950 return null; 951 } 952 953 961 private String extractSite(String tempDir, String archiveName, boolean skipErrors, boolean simulate) 962 { 963 try 964 { 965 logAndPrint("<b>updating site</b>"); 966 String fs = File.separator; 967 if ( new File(archiveName).length() == 0 ) 968 { 969 logAndPrint("Nothing to extract (empty or non existent zip file)."); 970 } 971 else try 972 { 973 Archive archive = new ArchiveFactory().open(archiveName); 974 if ( archive == null ) 975 { 976 return archiveName + " is not a recognized collection of files. Aborting zip-extraction."; 977 } 978 Enumeration names = archive.getNames(); 979 if ( names != null ) 980 { 981 StringBuffer tBuf = new StringBuffer (); 982 int fileCount = 0; 983 final byte[] buf = new byte[ZIP_BUFSIZE]; 984 while ( names.hasMoreElements() ) 987 { 988 String name = (String )names.nextElement(); 989 fileCount++; 990 System.out.print( tBuf.toString() ); 991 System.out.flush(); 992 File file = new File(tempDir + name); 994 File parent = file.getParentFile(); 995 if ( parent != null ) 996 { 997 parent.mkdirs(); } 999 CAT.debug("extractSite(): creating file " + tempDir + name); 1000 try 1001 { 1002 BufferedInputStream input = new BufferedInputStream(archive.getInputStream(name)); 1003 BufferedOutputStream output = new BufferedOutputStream(new FileOutputStream(file)); 1004 int total = 0; 1005 int inBuffer; 1006 while( (inBuffer = input.read(buf)) > -1 ) 1007 { 1008 output.write( buf, 0, inBuffer ); 1009 total += inBuffer; 1010 } 1011 input.close(); 1012 output.close(); } 1014 catch(IOException e) 1015 { 1016 CAT.error("extractSite(): error reading/writing file " + name + "from zip",e); 1017 } 1018 } 1019 logAndPrint(fileCount + " files extracted."); 1020 } 1021 } 1022 catch (Exception e) 1023 { 1024 CAT.error("extractSite(): error extracting zip " + archiveName,e); 1025 return "unable to extract zip file: " + e; 1026 } 1028 deleteFile(archiveName); 1029 CAT.debug("extractSite(): zip deleted."); 1030 1031 1033 newListing = new SiteDocumentsListing(); 1035 String [] dirs = sendSiteListing.getDirectories(); 1036 for ( int i = 0; i < dirs.length; i++ ) 1037 { 1038 String [] files = sendSiteListing.getDocumentNames(dirs[i]); 1039 for ( int k = 0; k < files.length; k++ ) 1040 { 1041 String target = sendSiteListing.getTargetDir(dirs[i], files[k]); 1042 newListing.addDocument(target, files[k], -1, -1, null); 1044 } 1045 } 1046 logAndPrint("<BR>updating documents...<BR>"); 1048 if ( skipErrors ) 1049 { 1050 logAndPrint("<BR>(skipping possible errors)<BR>"); 1051 } 1052 if ( !updateSite(tempDir, ".",skipErrors,simulate) ) 1053 { 1054 if ( !skipErrors ) 1055 { 1056 throw new Exception ("stopped updating documents at first error"); 1057 } 1058 else 1059 { 1060 error("Errors occured while updating documents. Since the option SkipErrors was set, " 1061 + "the SiteReceiver updated as much as possible and is trying to continue operation." 1062 + " Note that, however, the consistency of the site cannot be garanteed, " 1063 + "nor the correct behaviour of the following operations."); 1064 } 1065 } 1066 logAndPrint(""); 1067 logAndPrint("updated " + updatedFiles + " files in " + updatedDirs + " directories."); 1068 logAndPrint(""); 1069 if ( oldListing != null ) 1071 { 1072 logAndPrint("deleting files and directories that no longer belong to the site..."); 1073 int fileCounter, totalFiles = 0, totalDirs = 0; String canonicalDir; 1075 dirs = oldListing.getDirectories(); 1077 for ( int i = 0; i < dirs.length; i++ ) 1078 { 1079 fileCounter = 0; 1080 canonicalDir = dirs[i]; 1081 try 1082 { 1083 canonicalDir = new File(dirs[i]).getCanonicalPath(); 1084 } 1085 catch (Exception e) 1086 { 1087 CAT.debug("extractSite(): Couldn't form canonical path for " + dirs[i]); 1088 } 1089 String [] docs = oldListing.getNoMoreExistingDocuments(dirs[i], newListing); 1093 for ( int k=0; k<docs.length; k++ ) 1094 { 1095 if ( !simulate ) 1096 { 1097 if ( (new File(dirs[i] + fs + docs[k])).delete() ) 1098 { 1099 CAT.info("deleted " + canonicalDir + fs + docs[k]); 1100 fileCounter++; 1101 } 1102 } 1103 else 1104 { 1105 fileCounter++; } 1107 } 1108 if ( fileCounter > 0 ) 1109 { 1110 logAndPrint("deleted " + fileCounter + " document(s) in " + canonicalDir); 1111 totalDirs++; 1112 } 1113 totalFiles += fileCounter; 1114 } 1115 logAndPrint(""); 1116 logAndPrint("deleted " + totalFiles + " files in " + totalDirs + " directories."); 1117 logAndPrint(""); 1118 totalDirs = 0; 1119 dirs = oldListing.getNoMoreExistingDirectories(newListing); 1121 for ( int i=0; i<dirs.length; i++ ) 1122 { 1123 File dir = new File(dirs[i]); 1124 try 1125 { 1126 dir = dir.getCanonicalFile(); 1127 } 1128 catch (IOException e) 1129 { 1130 CAT.debug("extractSite(): Couldn't form canonical path for " + dir.getPath()); 1131 } 1132 if ( dir.exists() ) 1133 { 1134 if ( dir.list().length == 0 ) 1135 { 1136 if ( !simulate ) 1137 { 1138 if ( dir.delete() ) 1139 { 1140 totalDirs++; 1141 logAndPrint("deleted directory " + dir.getPath()); 1142 } 1143 } 1144 else 1145 { 1146 totalDirs++; 1147 logAndPrint("deleted directory " + dir.getPath()); 1148 } 1149 } 1150 else 1151 { 1152 logAndPrint("could not delete directory " + dir.getPath() + " because it was not empty."); 1153 } 1154 } 1155 } 1156 logAndPrint(""); 1157 logAndPrint("deleted " + totalDirs + " directories."); 1158 logAndPrint(""); 1159 } 1160 try 1162 { 1163 if ( !simulate ) 1164 { 1165 newListing.saveToFile(properties.get("siteDocumentsListing")); 1166 } 1167 logAndPrint("Saved new document list"); 1168 } 1169 catch (IOException e) 1170 { 1171 error("Unable to save new document list: ",e); 1172 } 1173 } 1174 catch (Exception e) 1175 { 1176 e.printStackTrace(new PrintWriter(logfile)); 1177 return e.toString(); 1178 } 1180 finally 1181 { 1182 logAndPrint("Deleting temporary dir " + tempDir); 1184 deleteFile(tempDir); 1185 } 1186 return null; 1190 } 1191 1192 1202 boolean updateSite(String tempDir, String subdir, boolean skipErrors, boolean simulate) throws Exception 1203 { 1204 boolean success = true; 1205 int fileCounter = 0; 1206 String target = null; 1207 String FS = File.separator; 1208 String [] list = (new File(tempDir + FS + subdir)).list(); 1209 try 1210 { 1211 for ( int i = 0; i < list.length; i++ ) 1212 { 1213 String filename = list[i]; 1214 File file = new File(tempDir + FS + subdir + FS + filename); 1215 try 1216 { 1217 file = file.getCanonicalFile(); 1218 } 1219 catch (IOException e) 1220 { 1221 CAT.debug("updateSite(): Couldn't form canonical path for " + file.getPath()); 1222 } 1223 CAT.debug("file " + file.getPath()); 1224 if ( file.isDirectory() ) 1226 { 1227 success = updateSite(tempDir, subdir + FS + filename, skipErrors, simulate); 1228 if ( !success && !skipErrors ) 1229 { 1230 return false; 1231 } 1232 } 1233 else 1234 { 1235 target = sendSiteListing.getTargetDir(subdir, filename); 1236 if ( target == null ) 1237 { 1238 error("found " + subdir + FS + filename + " in " + tempDir + ", but not in sent siteDocumentsListing!"); 1239 if ( skipErrors ) 1240 { 1241 success = false; 1242 continue; } 1244 else 1245 { 1246 return false; 1247 } 1248 1249 } 1250 File targetDir = new File(target); 1252 try 1253 { 1254 targetDir = targetDir.getCanonicalFile(); 1255 } 1256 catch (IOException e) 1257 { 1258 CAT.debug("updateSite(): Couldn't form canonical path for " + targetDir.getPath()); 1259 } 1260 target = targetDir.getPath(); CAT.debug(" ...target dir is " + target); 1262 if ( targetDir.exists() ) 1263 { 1264 if ( !targetDir.isDirectory() ) 1265 { 1266 error("failed to create directory " + markAsFile(target) + ": a file with that name exists"); 1267 error("failed to create document " + target + FS + filename); 1268 if ( skipErrors ) 1269 { 1270 error("Skipping further attempts to write to this \"directory\"."); 1271 return false; } 1273 else 1274 { 1275 return false; 1276 } 1277 } 1278 } 1279 else 1280 { 1281 try 1282 { 1283 if ( !targetDir.mkdirs() ) { 1285 error("failed to create directory " + markAsFile(target)); 1286 String dir = new String (target); 1288 boolean foundParentDir = false; 1289 int index = dir.length(); 1290 while ( (index = dir.lastIndexOf(FS, index - 1)) >= 0 && !foundParentDir ) 1291 { 1292 dir = dir.substring(0, index + 1); 1293 File fDir = new File(dir); 1294 if ( fDir.exists() ) 1295 { 1296 foundParentDir = true; 1297 error("nearest existing parent directory is: " + markAsFile(dir)); 1298 if ( fDir.canRead() ) 1299 { 1300 CAT.info("directory is readable"); 1301 } 1302 else 1303 { 1304 error("directory is not readable"); 1305 } 1306 if ( fDir.canWrite() ) 1307 { 1308 CAT.info("directory is writeable"); 1309 } 1310 else 1311 { 1312 error(markAsFile(dir) + " is not a writable directory. " 1313 + "Skipping further attempts to write to " + markAsFile(target) + "."); 1314 return false; } 1316 try 1319 { 1320 File temp = File.createTempFile("SRU",".tmp",fDir); 1321 temp.delete(); 1322 } 1323 catch (Exception dummy) 1324 { 1325 error(markAsFile(dir) + " is no accessible directory. " 1326 + "Skipping further attempts to write to " + markAsFile(target) + "."); 1327 return false; } 1329 } 1330 } 1331 if ( !foundParentDir ) 1332 { 1333 CAT.warn("found no parent directory"); 1334 } 1335 error("failed to create document " + markAsFile(target + FS + filename)); 1336 if ( skipErrors ) 1337 { 1338 success = false; 1339 continue; } 1341 else 1342 { 1343 return false; 1344 } 1345 } 1346 } 1347 catch (Exception e) 1348 { 1349 error("failed to create directory " + markAsFile(target),e); 1350 error("failed to create document " + markAsFile(target + FS + filename)); 1351 if ( skipErrors ) 1352 { 1353 if ( e.toString().toLowerCase().indexOf("no space") > -1 || 1354 ( e.toString().toLowerCase().indexOf("kein ") > -1 1355 && e.toString().toLowerCase().indexOf("platz ") > -1 ) 1356 ) 1357 { throw e; 1359 } 1360 else 1361 { 1362 success = false; 1363 continue; } 1365 } 1366 else 1367 { 1368 return false; 1369 } 1370 } 1371 } 1372 String source = tempDir + FS + subdir + FS + filename; 1374 try 1375 { 1376 source = new File(source).getCanonicalPath(); 1377 } 1378 catch (IOException e) 1379 { 1380 CAT.debug("updateSite(): Couldn't form canonical path for " + source); 1381 } 1382 String dest = target + FS + filename; 1383 try 1384 { 1385 dest = new File(dest).getCanonicalPath(); 1386 } 1387 catch (IOException e) 1388 { 1389 CAT.debug("updateSite(): Couldn't form canonical path for " + dest); 1390 } 1391 File fSource = new File(source); 1392 if ( !fSource.exists() ) 1393 { 1394 error("failed to create document " + markAsFile(dest) + ": source file " + markAsFile(source) + " does not exist."); 1395 if ( skipErrors ) 1396 { 1397 success = false; 1398 continue; } 1400 else 1401 { 1402 return false; 1403 } 1404 } 1405 try 1406 { 1407 if ( !simulate ) 1410 { 1411 SitePacker.copyFile(fSource,new File(dest)); 1412 } 1413 if ( simulate || fSource.delete() ) 1414 { 1415 CAT.info("moved document from " + source + " to " + target); 1416 } 1417 else 1418 { 1419 CAT.info("copied but could not delete document " + source); 1420 } 1421 fileCounter++; 1422 } 1423 catch (Exception e) 1424 { 1425 error("failed to copy document from " + source + " to " + markAsFile(dest),e); 1426 if ( skipErrors ) 1427 { 1428 if ( e.toString().indexOf("denied") > -1 || e.toString().indexOf("verweigert") > -1) 1429 { 1430 File dir = new File(dest).getParentFile(); 1433 if ( !dir.exists() || !dir.isDirectory() || !dir.canWrite() ) 1434 { 1435 error(markAsFile(dir.getName()) + " is not a writable directory. " 1436 + "Skipping further attempts to write to this directory."); 1437 return false; } 1439 else 1440 { try 1443 { 1444 File temp = File.createTempFile("SRU",".tmp",dir); 1445 temp.delete(); 1446 } 1447 catch (Exception dummy) 1448 { 1449 error(markAsFile(dir.getName()) + " is no accessible directory. " 1450 + "Skipping further attempts to write to this directory."); 1451 return false; } 1453 } 1454 } 1455 else if ( e.toString().toLowerCase().indexOf("no space") > -1 || 1456 ( e.toString().toLowerCase().indexOf("kein ") > -1 1457 && e.toString().toLowerCase().indexOf("platz ") > -1 ) 1458 ) 1459 { throw e; 1461 } 1462 success = false; 1463 continue; } 1465 else 1466 { 1467 return false; 1468 } 1469 } 1470 } 1471 } 1472 } 1473 catch (Exception e) 1474 { 1475 e.printStackTrace(new PrintWriter(logfile)); 1477 } 1478 finally 1479 { 1480 if ( target != null ) 1481 { 1482 logAndPrint("moved " + fileCounter + " file(s) to " + target); 1483 updatedFiles += fileCounter; 1484 updatedDirs++; 1485 } 1486 } 1487 return success; 1488 } 1489 1490 1496 private String transmitLog(boolean success) 1497 { 1498 PrintWriter out = null; 1499 int lineCount = 0; 1500 try 1501 { 1502 out = new PrintWriter(clientSocket.getOutputStream()); 1503 int size = vLog.size(); 1504 for ( int i = 0; i < size; i++ ) 1505 { 1506 out.println((String )vLog.get(i)); 1507 lineCount++; 1508 } 1509 if ( !success ) 1510 { 1511 out.println("abort"); 1512 } 1513 out.println("end"); 1514 out.flush(); 1515 } 1516 catch (Exception e) 1517 { 1518 return e.toString(); 1519 } 1520 finally 1521 { 1522 CAT.debug("transmitted " + lineCount + " log lines."); 1523 } 1524 return null; 1525 } 1526 1527 1528 1530 1536 private boolean transferAllowedFrom(String ip, String allowedIP) 1537 { 1538 CAT.debug("transferAllowedFrom(): ip=" + ip + " allowedIP=" + allowedIP); 1539 if ( allowedIP.indexOf("*") > -1 ) { int pos = allowedIP.indexOf("*") - 1; 1542 if ( pos == -1 || ip.substring(0,pos).equals(allowedIP.substring(0,pos)) ) 1543 { 1544 return true; 1545 } 1546 return false; 1547 } 1548 return (ip.indexOf(allowedIP) > -1 ); 1549 } 1550 1551 1554 private void printUsage() 1555 { 1556 outStream.println("usage: java SiteReceiver <remoteIP> <propertyFileName> [<url-encoded properties>]"); 1557 } 1558 1559 1564 private int deleteFile(String name) 1565 { 1566 File f = new File(name); 1567 int fileCount = 0; 1568 if ( f.exists() ) 1569 { 1570 if ( f.isDirectory() ) 1572 { 1573 String [] list = f.list(); 1574 for ( int i = 0; i < list.length; i++ ) 1575 { 1576 fileCount += deleteFile(name + File.separator + list[i]); 1577 } 1578 } 1579 if ( f.delete() ) 1581 { 1582 fileCount++; 1583 } 1584 } 1585 return fileCount; 1586 } 1587 1588 1593 static void CAT(Priority p, String s) 1594 { 1595 CAT.log(p,s); 1596 } 1597 1598 1602 protected void logAndPrint(String message) 1603 { 1604 if ( vLogStarted ) 1605 { 1606 logAndKeep(message); 1607 } 1608 else 1609 { 1610 print(message); 1611 log(message); 1612 } 1613 } 1614 1615 1619 private void print(String s) 1620 { 1621 int i = s.indexOf(NEWLINE); 1622 while ( i > -1 ) 1623 { 1624 outStream.println(s.substring(0,i) + "<BR>"); 1625 s = s.substring(i+1,s.length()); 1626 i = s.indexOf(NEWLINE); 1627 } 1628 if ( s.length() > 0 ) 1629 { 1630 outStream.println(s); 1631 } 1632 outStream.flush(); 1633 } 1634 1635 1639 private void logAndKeep(String message) 1640 { 1641 vLog.add(message); 1642 log(message); 1643 } 1644 1645 1652 private String getProperty(PropertySet source, String key) throws PropertyNotFoundException 1653 { 1654 String result = source.get(key); 1655 1656 if ( result == null || result.equals("") ) { 1658 throw new PropertyNotFoundException(key); 1659 } 1660 return result; 1661 } 1662 1663 1670 private boolean doAfterBurner(String afterBurner, String [] strArgs, boolean noJava) 1671 { 1672 try 1673 { 1674 String [] newArgs; 1675 int offset; 1676 if ( noJava ) 1678 { 1679 offset = 1; 1680 newArgs = new String [strArgs.length + offset]; 1681 newArgs[0] = afterBurner; 1682 } 1683 else 1684 { offset = 4; 1688 newArgs = new String [strArgs.length + 4]; 1689 newArgs[0] = System.getProperty("java.home") + File.separator + "bin" + File.separator + "java"; 1690 newArgs[1] = "-classpath"; 1691 newArgs[2] = System.getProperty("java.class.path"); 1692 newArgs[3] = afterBurner; 1693 } 1694 for ( int x=0; x<strArgs.length; x++ ) 1696 { 1697 newArgs[x+offset] = strArgs[x]; 1698 } 1699 Process proc = Runtime.getRuntime().exec(newArgs); 1701 BufferedReader inReader = new BufferedReader(new InputStreamReader(proc.getInputStream())); 1702 BufferedReader errReader = new BufferedReader(new InputStreamReader(proc.getErrorStream())); 1703 String line; 1704 while ((line = inReader.readLine()) != null) 1705 { 1706 logAndPrint(line); 1707 } 1708 String errors = ""; 1710 while ((line = errReader.readLine()) != null) 1711 { 1712 errors += line; 1713 } 1714 if ( !errors.equals("") ) 1715 { 1716 throw new Exception (errors); 1717 } 1718 return true; 1719 } 1720 catch (Throwable t) 1721 { 1722 error("Error during afterburning: ",t); 1723 return false; 1724 } 1725 } 1726 } 1727 1728 1729 1736class ClientConnector extends Thread 1737{ 1738 1739 private SSLServerSocket server; 1740 1741 private SiteReceiver siteReceiver; 1742 1743 1748 ClientConnector(SiteReceiver receiver, SSLServerSocket socket) 1749 { 1750 server = socket; 1751 siteReceiver = receiver; 1752 } 1753 1754 1757 public void run() 1758 { 1759 try 1760 { 1761 siteReceiver.clientSocket = (SSLSocket)server.accept(); 1762 SiteReceiver.CAT(Priority.DEBUG,"ClientConnector: connection accepted"); 1763 } 1764 catch (Exception e) 1765 { 1766 siteReceiver.error("Connection from client failed: ",e); 1767 siteReceiver.closeLog(); 1768 System.exit(1); 1769 } 1770 } 1771} | Popular Tags |