"SfR Fresh" - the SfR Freeware/Shareware Archive

Member "wormscan-1.6.1-src/net/websoup/wormscan/Program.java" of archive wormscan-1.6.1-src.tar.gz:


As a special service "SfR Fresh" has tried to format the requested source page into HTML format using source code syntax highlighting with prefixed line numbers. Alternatively you can here view or download the uninterpreted source code file. That can be also achieved for any archive member file by clicking within an archive contents listing on the first character of the file(path) respectively on the according byte size field.
    1 package net.websoup.wormscan;
    2 
    3 /*
    4 *    This file is part of WormScan.
    5 *
    6 *    WormScan is free software; you can redistribute it and/or
    7 *    modify it under the terms of the GNU General Public License
    8 *    as published by the Free Software Foundation; either version 2
    9 *    of the License, or (at your option) any later version.
   10 *
   11 *    This program is distributed in the hope that it will be useful,
   12 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
   13 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   14 *    GNU General Public License for more details.
   15 *
   16 *    You should have received a copy of the GNU General Public License
   17 *    along with this program; if not, write to the Free Software
   18 *    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
   19 */
   20 
   21 import java.io.*;
   22 import java.net.InetAddress;
   23 import java.text.SimpleDateFormat;
   24 import java.util.Locale;
   25 import java.util.Date;
   26 import java.util.Vector;
   27 import java.util.Map;
   28 import java.util.TreeMap;
   29 import java.util.Enumeration;
   30 import java.util.Collection;
   31 import java.util.Iterator;
   32 import java.util.Properties;
   33 import java.util.Stack;
   34 
   35 import org.apache.oro.text.perl.Perl5Util;
   36 import org.apache.oro.text.regex.Perl5Compiler;
   37 import org.apache.oro.text.regex.Perl5Matcher;
   38 import org.apache.oro.text.regex.Pattern;
   39 import org.apache.oro.text.regex.MatchResult;
   40 import org.apache.tools.bzip2.CBZip2InputStream;
   41 import org.apache.velocity.VelocityContext;
   42 import org.apache.velocity.Template;
   43 import org.apache.velocity.app.Velocity;
   44 
   45 import java.util.zip.GZIPInputStream;
   46 import java.util.zip.GZIPOutputStream;
   47 
   48 import net.websoup.wormscan.*;
   49 import net.websoup.utility.FilenameResolver;
   50 
   51 import org.jfree.chart.*;
   52 import org.jfree.chart.plot.*;
   53 import org.jfree.chart.ui.*;
   54 import org.jfree.data.*;
   55 import org.jfree.data.time.*;
   56 import org.jfree.ui.*;
   57 
   58 /**
   59  * Title:        WormScan
   60  * Description:  Extendable system to parse web server log files and output reports on attack attempts by various known internet worms.
   61  * Copyright:    Copyright (c) 2001-2004 Andriy Rozeluk <arozeluk@websoup.net>
   62  * @author Andriy Rozeluk
   63  * @version 1.6.1
   64  */
   65 
   66 public class Program extends Thread {
   67   private static int bufferSize = 32768;
   68 
   69   private static final int GZIP_BUFFER = 8192;
   70 
   71   /* how many parser threads to run */
   72   private static int NUM_PARSE_THREADS = 1;
   73 
   74   /* current line being processed by this thread */
   75   private String currentLine;
   76 
   77   /* identify this thread by a unique number */
   78   private int threadID;
   79 
   80   /* our logfile reader */
   81   private BufferedReader reader;
   82 
   83   /* the imported worms */
   84   private static Worm[] worms;
   85 
   86   /* store our list of attacks here */
   87   private static Vector attackStorage;
   88 
   89   /* what size to initialize our attackStorage to */
   90   private static int INITIAL_ATTACK_STORAGE_SIZE = 10000;
   91 
   92   /* store our list of hosts here */
   93   private static Map sourceStorage;
   94 
   95   /* what size to initialize our sourceStorage to */
   96   private static int INITIAL_SOURCE_STORAGE_SIZE = 4000;
   97 
   98   /* save DNS information in file cache [Y/N]*/
   99   private static boolean cacheDNS = true;
  100 
  101   /* all filenames of reports will start with this */
  102   private static String BASE_FILENAME = "wormreport";
  103 
  104   /* all filenames of reports will end with this */
  105   private static String BASE_EXTENSION = ".html";
  106 
  107   /* template to load for detailed report generation */
  108   private static String REPORT_TEMPLATE_NAME = "wormreport.vm";
  109 
  110   /* template to load for summary report generation */
  111   private static String SUMMARY_TEMPLATE_NAME = "wormsummary.vm";
  112 
  113   /* filename to store number of attacks in */
  114   private static String NUM_ATTACKS_FILE = null;
  115 
  116   /* filename to store DNS cache in */
  117   private static String DNS_CACHE_FILENAME = "dnscache";
  118 
  119   /* show only latest attack by host in generated reports */
  120   private static boolean SHOW_LATEST_ATTACK_ONLY = true;
  121 
  122   /* output GZIP-compressed version of reports while we're at it */
  123   private static boolean WRITE_GZIP = true;
  124 
  125   /* go ahead and check to see if log files are GZIP-compressed before parsing */
  126   private static boolean CHECK_GZIP = true;
  127 
  128   /* go ahead and check to see if log files are BZIP2-compressed before parsing */
  129   private static boolean CHECK_BZIP2 = true;
  130 
  131   /* go ahead and resolve hostnames */
  132   static boolean RESOLVE_DNS = true;
  133 
  134   /* how much information should we give the console? */
  135   static int OUTPUT_LEVEL = 3;
  136 
  137   /* how many sort threads to run simultaneously */
  138   private static int NUM_RUNNING_SORT_THREADS = 1;
  139 
  140   private static String CHART_BASE_FILENAME = "chart";
  141   private static int CHART_WIDTH = 640;
  142   private static int CHART_HEIGHT = 480;
  143   private static boolean CHARTS_PRODUCE = false;
  144 
  145   private Perl5Matcher matcher;
  146 
  147   /* how many resolver threads to run */
  148   private static int NUM_RESOLVER_THREADS = 1;
  149 
  150   private static Resolver[] resolverThreads;
  151 
  152   private static Perl5Compiler p5 = new Perl5Compiler();
  153   private static Pattern pattern;
  154   private static int patternHostIndex = 1;
  155   private static int patternDateIndex = 3;
  156   private static Locale LOG_LOCALE = Locale.US;
  157   private static String defaultDatePattern = "d/MMM/yyy:H:mm:ss";
  158   private static SimpleDateFormat patternDateFormat = new SimpleDateFormat(defaultDatePattern, LOG_LOCALE);
  159   private static int patternUriIndex = 6;
  160   private static boolean patternPrependFilenameToDate = false;
  161 
  162   /* get a bunch of threads ready to resolve hostnames. They'll wait */
  163   private static boolean resolveStarted = false;
  164 
  165   private static boolean enableReportByWorm = true;
  166   private static boolean enableReportByNumattacks = true;
  167   private static boolean enableReportByDate = true;
  168   private static boolean enableReportByIP = true;
  169   private static boolean enableReportByHostname = true;
  170 
  171   private String filename;
  172 
  173   static {
  174     //try it just in case JRE 1.4 is installed for charts
  175     System.setProperty("java.awt.headless", "true");
  176 
  177     try {
  178       pattern = p5.compile( "^(.*?)\\s+(.*?)\\[(.*?)\\](.*?)(GET|POST|HEAD|SEARCH)\\s+(.*?)\\s+(.*?)$" );
  179     }
  180     catch ( Exception e){
  181       System.err.println( "Exception thrown on init: " + e.getMessage() );
  182     }
  183   }
  184 
  185   /**
  186    * Compress a file with GZIP
  187    */
  188   private static void writeGZIP( String inputFilename, String outputFilename ) throws Exception {
  189     BufferedInputStream fis = new BufferedInputStream( new FileInputStream( inputFilename ) );
  190     BufferedOutputStream gos = new BufferedOutputStream( new GZIPOutputStream( new FileOutputStream( outputFilename ) ) );
  191     byte[] buffer = new byte[GZIP_BUFFER];
  192     for(;;){
  193       int numBytes = fis.read( buffer, 0, GZIP_BUFFER );
  194       if ( numBytes < 0 ) break;
  195       gos.write( buffer, 0, numBytes );
  196     }
  197     fis.close();
  198     gos.close();
  199   }
  200 
  201   /**
  202    * Some static initialization stuff. Read in our DNS cache and create some of our storage Vectors
  203    */
  204   private static void initialize(){
  205     attackStorage = new Vector( INITIAL_ATTACK_STORAGE_SIZE );
  206 
  207     if ( cacheDNS ){
  208       try {
  209         ObjectInputStream ois = new ObjectInputStream( new FileInputStream(DNS_CACHE_FILENAME) );
  210         sourceStorage = (TreeMap)(ois.readObject());
  211         ois.close();
  212         if ( OUTPUT_LEVEL > 2 ) System.out.println( "DNS Cache loaded" );
  213       }
  214       catch( Exception e ){
  215         sourceStorage = new TreeMap();
  216         if ( OUTPUT_LEVEL > 1 ) System.err.println("DNS Cache couldn't be loaded: " + e.getMessage());
  217       }
  218 
  219       try {
  220         //do some fixup processing of previously-stored objects
  221         Iterator i = sourceStorage.values().iterator();
  222         while( i.hasNext() ){
  223           AttackSource source = (AttackSource)(i.next());
  224           source.convertIP();
  225         }
  226       }
  227       catch( Exception e ){
  228         if ( OUTPUT_LEVEL > 1 ) System.err.println("Error performing fixup: " + e.getMessage());
  229         e.printStackTrace();
  230       }
  231     }
  232     else {
  233       sourceStorage = new TreeMap();
  234     }
  235   }
  236 
  237   /**
  238    * IP/Hostname should only be stored once. This method controls that.
  239    */
  240   private static AttackSource getAttackSource( String ip ){
  241     AttackSource as;
  242     //changes 3.26.2002 to not synchronize if only one thread
  243     //synchronization too expensive if not needed
  244     if ( NUM_PARSE_THREADS > 1 ){
  245       synchronized( sourceStorage ){
  246         as = (AttackSource)(sourceStorage.get(ip));
  247       }
  248 
  249       if ( as == null ){
  250         as = new AttackSource( ip );
  251         synchronized( sourceStorage ){
  252           sourceStorage.put( ip, as );
  253 
  254           Resolver.addSource( as );
  255           if ( !resolveStarted ){
  256             for ( int i = 0; i < NUM_RESOLVER_THREADS; i++ ) {
  257               resolverThreads[i] = new Resolver();
  258               resolverThreads[i].setPriority(Thread.MIN_PRIORITY);
  259               resolverThreads[i].start();
  260             }
  261             resolveStarted = true;
  262           }
  263         }
  264       }
  265     }
  266     else {
  267       as = (AttackSource)(sourceStorage.get(ip));
  268       if ( as == null ){
  269         as = new AttackSource( ip );
  270         sourceStorage.put( ip, as );
  271         Resolver.addSource( as );
  272         if ( !resolveStarted ){
  273           for ( int i = 0; i < NUM_RESOLVER_THREADS; i++ ) {
  274             resolverThreads[i] = new Resolver();
  275             resolverThreads[i].setPriority(Thread.MIN_PRIORITY);
  276             resolverThreads[i].start();
  277           }
  278           resolveStarted = true;
  279         }
  280       }
  281     }
  282 
  283     return as;
  284   }
  285 
  286   /**
  287    * Constructs a parse thread.
  288    */
  289   public Program( int id, BufferedReader bf, String filename ) {
  290     threadID = id;
  291     reader = bf;
  292     this.filename = filename;
  293     matcher = new Perl5Matcher();
  294   }
  295 
  296   /**
  297    * Begins a parse thread. This will loop until no more lines can be read from file
  298    */
  299   public void run(){
  300     /* read lines until there's nothing left to read */
  301     for(;;){
  302       try {
  303         currentLine = reader.readLine();
  304       }
  305       catch (Exception e){
  306         if ( OUTPUT_LEVEL > 1 ) System.err.println( "Warning: couldn't read a line: " + e.getMessage() );
  307         return;
  308       }
  309       if ( currentLine == null ) return;
  310 
  311         /* check each line against each worm. Do stuff if attack found. */
  312         if ( matcher.matches( currentLine, pattern ) ) {
  313           MatchResult lineMatch = matcher.getMatch();
  314           String uri = lineMatch.group( patternUriIndex );
  315           for( int i = 0; i < worms.length; i++ ){
  316             if ( matcher.contains( uri, worms[i].getPattern() ) ){
  317               String host = lineMatch.group( patternHostIndex );
  318               String tempdate = lineMatch.group( patternDateIndex );
  319 
  320               /* try to parse the date */
  321               Date date = null;
  322               try {
  323                 if ( patternPrependFilenameToDate ){
  324                   tempdate = filename + tempdate;
  325                 }
  326                 synchronized( patternDateFormat ){
  327                   date = patternDateFormat.parse( tempdate );
  328                 }
  329               }
  330               catch ( Exception e ){
  331                 if ( OUTPUT_LEVEL > 1 ) System.err.println("cannot interpret date in log file:" + e.getMessage());
  332               }
  333 
  334               /* increment attack counter for worm */
  335               worms[i].addAttack();
  336               AttackSource as = getAttackSource( host );
  337 
  338               /* increment attack counter for host */
  339               as.addAttack();
  340 
  341               Attack attack = new Attack( date, worms[i], as );
  342               if ( NUM_PARSE_THREADS > 1 ){
  343                 synchronized( attackStorage ){
  344                   attackStorage.add( attack );
  345                   /* check to see if this is the first or last attack by this host.
  346                    Update if necessary */
  347                   as.checkAttackDates( attack );
  348                 }
  349               }
  350               else {
  351                 attackStorage.add( attack );
  352                 as.checkAttackDates( attack );
  353               }
  354 
  355               if ( OUTPUT_LEVEL > 3 )
  356                 System.out.println( "Thread " + threadID + " found " + attack.getAttackingWorm().getShortName() + " attack" );
  357 
  358               /* no need to continue on this line - we've marked it as an attack already */
  359               break;
  360             }
  361           }
  362 
  363         currentLine = null;
  364       }
  365 /* screw the yield - it's taking up too much of our time to be polite
  366       try {
  367         this.yield();
  368       }
  369       catch ( Exception e ){
  370       }
  371 */
  372     }
  373   }
  374 
  375   /**
  376    * Return a BufferedReader which can read in the log file. Can also detect and handle GZIP/BZIP2 compression
  377    */
  378   private static BufferedReader getLogfileReader( String filename ) throws Exception{
  379     if ( CHECK_GZIP ){
  380       if ( OUTPUT_LEVEL > 2 ) System.out.println( "Detecting GZIP... in " + filename );
  381       byte[] test = new byte[2];
  382       FileInputStream fis = new FileInputStream( filename );
  383       int read = fis.read( test, 0, 2 );
  384       if ( read == 2 ){
  385         if ( test[0] == new Integer( 31 ).byteValue() && test[1] == new Integer( 139 ).byteValue() ){
  386           fis.close();
  387           fis = new FileInputStream( filename );
  388           GZIPInputStream gis = new GZIPInputStream( fis );
  389           InputStreamReader isr = new InputStreamReader( gis );
  390           if ( OUTPUT_LEVEL > 2 ) System.out.println( "Log file " + filename + " was compressed with GZIP. Decompression will take place automatically." );
  391           return new BufferedReader( isr, bufferSize );
  392         }
  393       }
  394       if ( OUTPUT_LEVEL > 2 ) System.out.println( "Log file was NOT compressed with GZIP" );
  395     }
  396     if ( CHECK_BZIP2 ){
  397       if ( OUTPUT_LEVEL > 2 ) System.out.println( "Detecting BZIP2... in " + filename );
  398       byte[] test = new byte[4];
  399       FileInputStream fis = new FileInputStream( filename );
  400       int read = fis.read( test, 0, 2 );
  401       if ( read == 2 ){
  402         if ( test[0] == 'B' && test[1] == 'Z' ){
  403           CBZip2InputStream bis = new CBZip2InputStream( fis );
  404           InputStreamReader isr = new InputStreamReader( bis );
  405           if ( OUTPUT_LEVEL > 2 ) System.out.println( "Log file " + filename + " was compressed with BZIP2. Decompression will take place automatically." );
  406           return new BufferedReader( isr, bufferSize );
  407         }
  408       }
  409       if ( OUTPUT_LEVEL > 2 ) System.out.println( "Log file was NOT compressed with BZIP2" );
  410     }
  411     FileReader fileInput = new FileReader( filename );
  412     return new BufferedReader( fileInput, bufferSize );
  413   }
  414 
  415   public static void main(String[] args) {
  416     /* the user entered this as our list of logfile(s) to parse */
  417     String LOGFILE = null;
  418 
  419     /* this mess reads in the properties file and sets values accordingly */
  420     Properties p = new Properties();
  421     try {
  422       p.load( new FileInputStream("wormscan.properties") );
  423       String temp = p.getProperty( "outputLevel" );
  424       if ( temp != null ){
  425         try {
  426           OUTPUT_LEVEL = Integer.parseInt( temp );
  427         }
  428         catch ( Exception e){
  429           if ( OUTPUT_LEVEL > 1 ) System.err.println( "Warning: outputLevel property was not an integer. Using default" );
  430         }
  431       }
  432       else {
  433         if ( OUTPUT_LEVEL > 1 ) System.err.println( "Warning: outputLevel property not specified. Using default" );
  434       }
  435       temp = p.getProperty("reportFilename");
  436       if ( temp != null ) BASE_FILENAME = temp;
  437       else {
  438         if ( OUTPUT_LEVEL > 1 ) System.err.println( "Warning: reportFilename property not specified. Using default" );
  439       }
  440       temp = p.getProperty("reportExtension");
  441       if ( temp != null ) BASE_EXTENSION = temp;
  442       else {
  443         if ( OUTPUT_LEVEL > 1 ) System.err.println( "Warning: reportExtension property not specified. Using default" );
  444       }
  445       temp = p.getProperty( "logFile" );
  446       if ( temp != null ) LOGFILE = temp;
  447       else {
  448         if ( OUTPUT_LEVEL > 0 ) System.err.println( "logFile property not specified in wormscan.properties - unable to proceed" );
  449         System.exit(1);
  450       }
  451       temp = p.getProperty( "numAttacksFile" );
  452       if ( temp != null ) NUM_ATTACKS_FILE = temp;
  453       else {
  454         if ( OUTPUT_LEVEL > 1 ) System.err.println( "Warning: numAttacksFile property not specified. File won't be written" );
  455       }
  456       temp = p.getProperty( "initialAttackStorageSize" );
  457       if ( temp != null ){
  458         try {
  459           INITIAL_ATTACK_STORAGE_SIZE = Integer.parseInt( temp );
  460         }
  461         catch ( Exception e){
  462           if ( OUTPUT_LEVEL > 1 ) System.err.println( "Warning: initialAttackStorageSize property was not an integer. Using default" );
  463         }
  464       }
  465       else {
  466         if ( OUTPUT_LEVEL > 1 ) System.err.println( "Warning: initialAttackStorageSize property not specified. Using default" );
  467       }
  468       temp = p.getProperty( "initialSourceStorageSize" );
  469       if ( temp != null ){
  470         try {
  471           INITIAL_SOURCE_STORAGE_SIZE = Integer.parseInt( temp );
  472         }
  473         catch ( Exception e){
  474           if ( OUTPUT_LEVEL > 1 ) System.err.println( "Warning: initialSourceStorageSize property was not an integer. Using default" );
  475         }
  476       }
  477       else {
  478         if ( OUTPUT_LEVEL > 1 ) System.err.println( "Warning: initialSourceStorageSize property not specified. Using default" );
  479       }
  480       temp = p.getProperty( "numParseThreads" );
  481       if ( temp != null ){
  482         try {
  483           NUM_PARSE_THREADS = Integer.parseInt( temp );
  484         }
  485         catch ( Exception e){
  486           if ( OUTPUT_LEVEL > 1 ) System.err.println( "Warning: numParseThreads property was not an integer. Using default" );
  487         }
  488       }
  489       else {
  490         if ( OUTPUT_LEVEL > 1 ) System.err.println( "Warning: numParseThreads property not specified. Using default" );
  491       }
  492       temp = p.getProperty( "numResolverThreads" );
  493       if ( temp != null ){
  494         try {
  495           NUM_RESOLVER_THREADS = Integer.parseInt( temp );
  496         }
  497         catch ( Exception e){
  498           if ( OUTPUT_LEVEL > 1 ) System.err.println( "Warning: numResolverThreads property was not an integer. Using default" );
  499         }
  500       }
  501       else {
  502         if ( OUTPUT_LEVEL > 1 ) System.err.println( "Warning: numResolverThreads property not specified. Using default" );
  503       }
  504       temp = p.getProperty( "maxResolverQueue" );
  505       if ( temp != null ){
  506         try {
  507           Resolver.MAX_WAITING = Integer.parseInt( temp );
  508         }
  509         catch ( Exception e){
  510           if ( OUTPUT_LEVEL > 1 ) System.err.println( "Warning: maxResolverQueue property was not an integer. Using default" );
  511         }
  512       }
  513       else {
  514         if ( OUTPUT_LEVEL > 1 ) System.err.println( "Warning: numResolverThreads property not specified. Using default" );
  515       }
  516       temp = p.getProperty( "numSortThreads" );
  517       if ( temp != null ){
  518         try {
  519           NUM_RUNNING_SORT_THREADS = Integer.parseInt( temp );
  520         }
  521         catch ( Exception e){
  522           if ( OUTPUT_LEVEL > 1 ) System.err.println( "Warning: numSortThreads property was not an integer. Using default" );
  523         }
  524       }
  525       else {
  526         if ( OUTPUT_LEVEL > 1 ) System.err.println( "Warning: numSortThreads property not specified. Using default" );
  527       }
  528       temp = p.getProperty( "cacheDNS" );
  529       if ( temp != null ){
  530         if ( temp.equals("1") ){
  531           cacheDNS = true;
  532           temp = p.getProperty( "cacheFilename" );
  533           if ( temp != null ){
  534            DNS_CACHE_FILENAME = temp;
  535           }
  536           else if ( OUTPUT_LEVEL > 1 ){
  537            System.err.println( "Warning: cacheFilename property not specified. Using default" );
  538           }
  539         }
  540         else if ( temp.equals("0") ){
  541          cacheDNS = false;
  542         }
  543         else if ( OUTPUT_LEVEL > 1 ){
  544          System.err.println( "Warning: cacheDNS property is not 1 or 0. Using default" );
  545         }
  546       }
  547       else {
  548         if ( OUTPUT_LEVEL > 1 ){
  549          System.err.println( "Warning: numResolverThreads property not specified. Using default" );
  550         }
  551       }
  552       temp = p.getProperty( "showLatestAttackOnly" );
  553       if ( temp != null ){
  554         if ( temp.equals("1") ){
  555          SHOW_LATEST_ATTACK_ONLY = true;
  556         }
  557         else if ( temp.equals("0") ){
  558          SHOW_LATEST_ATTACK_ONLY = false;
  559         }
  560         else if ( OUTPUT_LEVEL > 1 ){
  561          System.err.println( "Warning: showLatestAttackOnly property is not 1 or 0. Using default" );
  562         }
  563       }
  564       else {
  565         if ( OUTPUT_LEVEL > 1 ){
  566          System.err.println( "Warning: showLatestAttackOnly property not specified. Using default" );
  567         }
  568       }
  569       temp = p.getProperty( "resolveDNS" );
  570       if ( temp != null ){
  571         if ( temp.equals("1") ){
  572          RESOLVE_DNS = true;
  573         }
  574         else if ( temp.equals("0") ){
  575          RESOLVE_DNS = false;
  576         }
  577         else if ( OUTPUT_LEVEL > 1 ){
  578          System.err.println( "Warning: resolveDNS property is not 1 or 0. Using default" );
  579         }
  580       }
  581       else {
  582         if ( OUTPUT_LEVEL > 1 ){
  583          System.err.println( "Warning: resolveDNS property not specified. Using default" );
  584         }
  585       }
  586       temp = p.getProperty( "logCheckGZIP" );
  587       if ( temp != null ){
  588         if ( temp.equals("1") ){
  589          CHECK_GZIP = true;
  590         }
  591         else if ( temp.equals("0") ){
  592          CHECK_GZIP = false;
  593         }
  594         else if ( OUTPUT_LEVEL > 1 ){
  595          System.err.println( "Warning: logCheckGZIP property is not 1 or 0. Using default" );
  596         }
  597       }
  598       else {
  599         if ( OUTPUT_LEVEL > 1 ){
  600          System.err.println( "Warning: logCheckGZIP property not specified. Using default" );
  601         }
  602       }
  603       temp = p.getProperty( "logCheckBZIP2" );
  604       if ( temp != null ){
  605         if ( temp.equals("1") ){
  606          CHECK_BZIP2 = true;
  607         }
  608         else if ( temp.equals("0") ){
  609          CHECK_BZIP2 = false;
  610         }
  611         else if ( OUTPUT_LEVEL > 1 ){
  612          System.err.println( "Warning: logCheckBZIP2 property is not 1 or 0. Using default" );
  613         }
  614       }
  615       else {
  616         if ( OUTPUT_LEVEL > 1 ){
  617          System.err.println( "Warning: logCheckBZIP2 property not specified. Using default" );
  618         }
  619       }
  620       temp = p.getProperty( "writeGZIP" );
  621       if ( temp != null ){
  622         if ( temp.equals("1") ){
  623          WRITE_GZIP = true;
  624         }
  625         else if ( temp.equals("0") ){
  626          WRITE_GZIP = false;
  627         }
  628         else if ( OUTPUT_LEVEL > 1 ){
  629          System.err.println( "Warning: writeGZIP property is not 1 or 0. Using default" );
  630         }
  631       }
  632       else {
  633         if ( OUTPUT_LEVEL > 1 ){
  634          System.err.println( "Warning: writeGZIP property not specified. Using default" );
  635         }
  636       }
  637       temp = p.getProperty( "disableReportByWorm" );
  638       if ( temp != null && temp.equals("1") ){
  639         enableReportByWorm = false;
  640       }
  641       temp = p.getProperty( "disableReportByNumattacks" );
  642       if ( temp != null && temp.equals("1") ){
  643         enableReportByNumattacks = false;
  644       }
  645       temp = p.getProperty( "disableReportByDate" );
  646       if ( temp != null && temp.equals("1") ){
  647         enableReportByDate = false;
  648       }
  649       temp = p.getProperty( "disableReportByIP" );
  650       if ( temp != null && temp.equals("1") ){
  651         enableReportByIP = false;
  652       }
  653       temp = p.getProperty( "disableReportByHostname" );
  654       if ( temp != null && temp.equals("1") ){
  655         enableReportByHostname = false;
  656       }
  657       temp = p.getProperty( "produceCharts" );
  658       if ( temp != null ){
  659         if ( temp.equals("1") ) {
  660           CHARTS_PRODUCE = true;
  661           temp = p.getProperty( "chartFilename" );
  662           if ( temp != null && !temp.equals("") ){
  663             CHART_BASE_FILENAME = temp;
  664           }
  665           else if ( OUTPUT_LEVEL > 1 ){
  666             System.err.println( "Warning: chartFilename property not specified. Using default" );
  667           }
  668           temp = p.getProperty( "chartWidth" );
  669           if ( temp != null && !temp.equals("") ){
  670             try {
  671               int tempInt = Integer.parseInt( temp );
  672               if ( tempInt >= 50 ){
  673                 CHART_WIDTH = tempInt;
  674               }
  675               else if ( OUTPUT_LEVEL > 1 ){
  676                 System.err.println( "Warning: chartWidth property is too small. Using default" );
  677               }
  678             }
  679             catch ( Exception ex ){
  680               if ( OUTPUT_LEVEL > 1 ) System.err.println( "Warning: chartWidth property is not an integer. Using default" );
  681             }
  682           }
  683           else if ( OUTPUT_LEVEL > 1 ){
  684             System.err.println( "Warning: chartWidth property not specified. Using default" );
  685           }
  686           temp = p.getProperty( "chartHeight" );
  687           if ( temp != null && !temp.equals("") ){
  688             try {
  689               int tempInt = Integer.parseInt( temp );
  690               if ( tempInt >= 50 ){
  691                 CHART_HEIGHT = tempInt;
  692               }
  693               else if ( OUTPUT_LEVEL > 1 ){
  694                 System.err.println( "Warning: chartHeight property is too small. Using default" );
  695               }
  696             }
  697             catch ( Exception ex ){
  698               if ( OUTPUT_LEVEL > 1 ) System.err.println( "Warning: chartHeight property is not an integer. Using default" );
  699             }
  700           }
  701           else if ( OUTPUT_LEVEL > 1 ){
  702             System.err.println( "Warning: chartHeight property not specified. Using default" );
  703           }
  704         }
  705         else if ( temp.equals("0") ){
  706           CHARTS_PRODUCE = false;
  707         }
  708         else if ( OUTPUT_LEVEL > 1 ) {
  709           System.err.println( "Warning: produceCharts property is not 1 or 0. Using default" );
  710         }
  711       }
  712       else {
  713         if ( OUTPUT_LEVEL > 1 ) System.err.println( "Warning: produceCharts property not specified. Charts will not be created" );
  714       }
  715 
  716       String locLanguage = "en";
  717       String locCountry = "US";
  718       temp = p.getProperty( "serverLocaleLanguage" );
  719       if ( temp != null && !temp.equals("")){
  720         locLanguage = temp;
  721       }
  722       else {
  723         if ( OUTPUT_LEVEL > 1 ) System.err.println( "Warning: serverLocaleLanguage property not specified. Using default" );
  724       }
  725       temp = p.getProperty( "serverLocaleCountry" );
  726       if ( temp != null && !temp.equals("")){
  727         locCountry = temp;
  728       }
  729       else {
  730         if ( OUTPUT_LEVEL > 1 ) System.err.println( "Warning: serverLocaleCountry property not specified. Using default" );
  731       }
  732       if ( !locLanguage.equals("en") || !locCountry.equals("US") ){
  733         try {
  734           Locale tempLocale = new Locale( locLanguage, locCountry );
  735           LOG_LOCALE = tempLocale;
  736           patternDateFormat = new SimpleDateFormat(defaultDatePattern, LOG_LOCALE);
  737         }
  738         catch( Exception e ){
  739           System.err.println( "Warning: unable to create Locale for " + locLanguage + ", " + locCountry + ": " + e.getMessage() );
  740