home *** CD-ROM | disk | FTP | other *** search
/ PC World 2001 April / PCWorld_2001-04_cd.bin / Software / TemaCD / smartcache / src / mgr.java < prev    next >
Encoding:
Java Source  |  2001-01-26  |  66.8 KB  |  1,829 lines

  1. /*
  2.  *  Smart Cache, http proxy cache server
  3.  *  Copyright (C) 1998, 1999 Radim Kolar 
  4.  *
  5.  *    Smart Cache is Open Source Software; you may redistribute it
  6.  *  and/or modify it under the terms of the GNU General Public
  7.  *  License as published by the Free Software Foundation; either
  8.  *  version 2, or (at your option) any later version.
  9.  *
  10.  *    This program distributed in the hope that it will be useful,
  11.  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  12.  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  13.  *  General Public License for more details.
  14.  *
  15.  *    A copy of the GNU General Public License is available as
  16.  *  /usr/doc/copyright/GPL in the Debian GNU/Linux distribution or on
  17.  *  the World Wide Web at http://www.gnu.org/copyleft/gpl.html. You
  18.  *  can also obtain it by writing to the Free Software Foundation,
  19.  *  Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  20.  */
  21.  
  22. import java.io.*;
  23. import java.util.*;
  24. import java.text.*;
  25. import java.util.zip.*;
  26. import java.net.*;
  27.  
  28. public final class mgr implements Runnable{
  29.  
  30. public static final String DEFAULTNAME=".welcome";
  31. /* cache manager */
  32. public static InetAddress parentproxy;
  33. public static String parentauth; /* auth header */
  34. public static int port; // parentproxyport
  35.  
  36. public static int ourport;
  37. private static InetAddress ouraddress;
  38.  
  39. private static final long SAVETIMER=1000L*60*3; /* 3 min. */
  40. public  static String cache_dir;
  41. private static String custom403;
  42. public static int swap_level1_dirs= 4;
  43. public static int swap_level2_dirs= 4;
  44. public  static String[] no_proxy;
  45. public  static String[] allow_cookies_to;
  46. public static boolean case_sensitive;
  47.  
  48. /* ad Busters */
  49. private  static AdBuster ad;
  50. private  static String AdID,AdAuth;
  51.  
  52. /* access rulez */
  53. private  static  boolean cacheonly;
  54. private  static  regexp[] fail;
  55. private  static  regexp[] nocache;
  56. private  static  regexp[] pass;
  57. private  static  int allowconnect[];
  58. private  static  boolean fail_trace;
  59.  
  60. /* time stamps */
  61. private  static  long pass_timestamp;
  62. private  static  long fail_timestamp;
  63. private  static  long cookie_timestamp;
  64.  
  65. private  static  String cookie_filename;
  66. private  static  String pass_filename;
  67. private  static  String fail_filename;
  68.  
  69. /* refresh strategy - multiple */
  70. private  static regexp[] refresh;
  71. private  static long minage[];
  72. private  static long maxage[];
  73. private  static long reloadage[];
  74. private  static float lastmodf[];
  75. private  static long expireage[];
  76. private  static long redirage[];
  77.  
  78. /* simple refresh p. */
  79. private  static long min_age;
  80. public   static long max_age;
  81. private  static long reload_age;
  82. private  static long expire_age;
  83. private  static long redir_age;
  84. private  static float lmfactor;
  85.  
  86. /* redirects */
  87. private  static String[] redirfrom;
  88. private  static String[] redirto;
  89.  
  90. private  static Hashtable dircache;
  91.  
  92. /* flags */
  93. private  static String shutdownflag,immediate_shutdownflag;
  94. public static boolean clear_flags_on_start=true;
  95. private static int flag_check_interval;
  96.  
  97. /* log for statistic */
  98. private static String stat_log;
  99.  
  100. mgr()
  101. {
  102.  dircache=new Hashtable(25);
  103.  /* init to some defaults */
  104.  /* static intit */
  105.  request.formatter.setTimeZone(TimeZone.getTimeZone("GMT")); 
  106.  httpreq.formatter.setTimeZone(TimeZone.getDefault());
  107.  /* compute timezone in apache log style format */
  108.  int ofs=TimeZone.getDefault().getRawOffset();
  109.  if(TimeZone.getDefault().inDaylightTime(new Date())) ofs+=60*60*1000;
  110.  httpreq.timezone=(ofs<0?" -":" +");
  111.  ofs=Math.abs(ofs);
  112.  httpreq.timezone=httpreq.timezone+
  113.             (ofs/(60*60*1000)<10 ? "0"+ofs/(60*60*1000): ""+ofs/(60*60*1000));
  114. ofs-=(ofs/(60*60*1000))*60*60*1000;
  115. ofs/=60*1000;
  116. httpreq.timezone=httpreq.timezone+(ofs<10? "0"+ofs : ""+ofs)+"] \"";
  117.  
  118.  /* defaults */
  119.  cacheonly=false;
  120.  cache_dir="store";
  121.  port=3128; /* default squid parent proxy port */
  122.  ourport=8080; /* well known webcache port     */
  123.  request.default_forward_for="127.0.0.1";
  124.  swap_level1_dirs= swap_level2_dirs=4;
  125.  lmfactor=0.2f;
  126.  min_age=15*60*1000L; /* 15 minut */
  127.  max_age=4*24*60*60*1000L; /* 4 dny */
  128.  expire_age=1000L*60*5; /* 5 minutes */
  129.  redir_age=15*1000L; /* 15 seconds */
  130.  request.qa_minlen=-1; /* quick abort disable */
  131.  request.qa_maxtime=3*60*60*1000L; /* max luxovaci cas 3 minuty */
  132.  httpreq.client_timeout=30*1000; /* 30 sec. read from cl. timeout */
  133.  request.read_timeout=5*60*1000; /* 5 min. read from net timeout  */
  134.  cacheobject.keep_deleted=false;
  135.  cacheobject.generate_lastmod=0;
  136.  cacheobject.hide_errors=false;
  137.  cacheobject.defaultname=DEFAULTNAME; // UGLY CERN standard
  138.  request.remove_pragma_no_cache=false;
  139.  request.referer_hack=0; 
  140.  request.fake_referer=null;
  141.  request.fake_user_agent=null;
  142.  request.append_via=true;
  143.  request.full_referer_log=true;
  144.  request.cache_protected=false; 
  145.  case_sensitive=false;
  146.  httpreq.visible_hostname="smart.cache.lan";
  147.  httpreq.visible_link=null;
  148.  cachedir.readonly=false;
  149.  clear_flags_on_start=true;
  150.  fail_trace=false;
  151.  stat_log=null;
  152.  flag_check_interval=45;
  153.  cacheobject.auto_compress=false;
  154.  cacheobject.auto_decompress=false;
  155.  
  156.  /* for safety */
  157.  cacheobject.end_dot=false;
  158.  cacheobject.escape_backslash=true;
  159. }
  160.  
  161. public final void check_filesystem()
  162. {
  163.  System.err.println("Checking filesystem ("+cache_dir+")");
  164.   
  165.  if(!cachedir.readonly)
  166.    cacheobject.end_dot=endDotFilesystem();
  167.  if(!new File(cache_dir).isDirectory())
  168.    {
  169.      System.out.println("[SMARTCACHE] Fatal Error: Directory "+cache_dir+" can not be created.");
  170.      return;
  171.    }
  172.    
  173.  if(cachedir.readonly)
  174.     System.err.println("   Using cache directory in READ-ONLY mode.");
  175.   else
  176.  {
  177.    System.err.println("   Host OS allows ending dot in filename: "+cacheobject.end_dot);
  178.    cacheobject.escape_backslash=!(filesystemCanUseBackslash());
  179.    System.err.println("   Host OS allows backslash in filename : "+!(cacheobject.escape_backslash));
  180.    garbage.realdirsize=filesystemHasRealDirsize();
  181.    System.err.println("   Host OS reports real directory size  : "+garbage.realdirsize);
  182.  
  183.  }
  184.  System.err.println("");
  185. }
  186.  
  187. public void go() throws IOException
  188. {
  189.  
  190.  scache daemon=new scache(ourport,ouraddress);
  191.  new Thread(this).start(); /* start background directory saver... */ 
  192.  
  193.  // TODO: REMOVE ALL ADBUSTERS CODE ??
  194.  scache.faststart=true; 
  195.   // NO BUSTERS AND LASTVERCHECK.  NO SERVER FOR HOSTING :(
  196.   // SOME1 WANTS TO HOST IT?
  197.   
  198.  if(scache.faststart==false)
  199.  {
  200.    System.err.println("Checking for latest Smart Cache version");
  201.    String lv=getLatestVersion();
  202.  if (lv==null) lv="(Error connecting to server)";
  203.  else if (!lv.equals(scache.CACHEVER)) lv+="\007 ... its time for update!";
  204.    else
  205.     lv+=" ... up to date";
  206.  System.err.println("   Latest version is "+lv);
  207.  }
  208.  initAdBusters();
  209.  
  210.  /* refresh pattern hack */
  211.  if(refresh!=null && !isInRegexpArray("*",refresh)) 
  212.  {
  213.   refresh=addRegexpToArray("*",refresh);
  214.                       
  215.   /* natahnout ! */
  216.   reloadage=incLongArraySize(reloadage);
  217.   minage=incLongArraySize(minage);
  218.   maxage=incLongArraySize(maxage);
  219.   lastmodf=incFloatArraySize(lastmodf);
  220.   expireage=incLongArraySize(expireage);
  221.   redirage=incLongArraySize(redirage);
  222.                     
  223.   /* nastavit hodnoty */
  224.   reloadage[reloadage.length-1]=reload_age;
  225.   minage[minage.length-1]=min_age;
  226.   maxage[maxage.length-1]=max_age;
  227.   lastmodf[lastmodf.length-1]=lmfactor;
  228.   expireage[expireage.length-1]=expire_age;
  229.   redirage[redirage.length-1]=redir_age;
  230.  }
  231.  
  232.  System.out.println(new Date()+" "+scache.VERSION+" ready."); 
  233.  // on port "+ourport+"/"+(ouraddress==null ? "*" : ouraddress.getHostAddress())+".");
  234.  
  235.  ouraddress=null; // GC IT!
  236.  httpreq.mgr=this;  
  237.  if(clear_flags_on_start)
  238.  {
  239.  checkFlag(shutdownflag); // delete pending shutdown flag on start
  240.  checkFlag(immediate_shutdownflag); // delete pending shutdown flag on start
  241.  }
  242.  daemon.httpdloop(); // enter main loop
  243. }
  244.  
  245. private final static boolean filesystemCanUseBackslash()
  246. {
  247.  if(cachedir.readonly) return false;
  248.  File test=new File(cache_dir,"test\\slash");
  249.  try{
  250.  new FileOutputStream(test).close();
  251.  }
  252.  catch (IOException e1) {
  253.                           return false;
  254.             }
  255.  
  256.  test.delete();
  257.  return true;
  258. }
  259. private final static boolean filesystemHasRealDirsize()
  260. {
  261.   try
  262.    {
  263.     if(new File(".").length()>0) return true;
  264.     else return false;
  265.   }
  266.   catch (Exception grrrrrrrrrrrrrrrr)
  267.     {
  268.       return false;
  269.     }
  270.    // return false; /* Uncomment to keep some stupid JAVAC compilers happy */
  271. }   
  272.  
  273. private final static String getLatestVersion()
  274. {
  275.  URL u=null;
  276.  try
  277.  {
  278.       u=new URL("http://adbusters.netmag.cz:8001/cachever");
  279.    // u=new URL("http://localhost:8001/cachever");
  280.  }
  281.  catch (MalformedURLException e)
  282.   { return null;}
  283.  String ver=null;
  284.  try
  285.  {
  286.    ver=new DataInputStream(u.openStream()).readLine();
  287.    return ver;
  288.  }
  289.  catch (IOException e)
  290.   { return null;}
  291.  
  292. }
  293.  
  294. private final void initAdBusters()
  295. {
  296.  if(AdID==null || AdAuth==null) return;
  297.  System.err.println("Initializing cache in AdBusters mode");
  298.  try
  299.  {
  300.    URL u;
  301.    if(scache.faststart==true)
  302.    u=new URL("http://127.0.0.1:8001/AdBuster?id="+AdID+"&auth="+AdAuth+"&e");  
  303.      else
  304.   u=new URL("http://adbusters.netmag.cz:8001/AdBuster?id="+AdID+"&auth="+AdAuth+"&e");
  305.   
  306. // u=new URL("http://localhost:8001/AdBuster?id="+AdID+"&auth="+AdAuth+"&e");
  307.   
  308.   ObjectInputStream ois=null; 
  309.   try{
  310.   ois =
  311.                     new ObjectInputStream(u.openStream());
  312.                     ad = (AdBuster)ois.readObject();
  313.                           
  314.                         }
  315.                         catch (Throwable e) {
  316.                                 System.err.println("   *ERR "+e);
  317.                         }
  318.                         finally
  319.                          {
  320.                              if(ois!=null) try{ois.close();}
  321.                                             catch(IOException e) {};
  322.                              ois=null;
  323.                          }
  324.  if(ad!=null) { System.err.println("   Refreshed rules list from server");
  325.                 mergeBusters(); 
  326.                 ad=null; 
  327.                 return;}
  328.  
  329.  
  330.  /* ze souboru */
  331.   try{
  332.   ois =
  333.                     new ObjectInputStream(new FileInputStream("AdBuster.ser"));
  334.                     ad = (AdBuster)ois.readObject();
  335.  
  336.                           
  337.                         }
  338.                         catch (Throwable e) {
  339.                                 System.err.println("  *ERR "+e);
  340.                         }
  341.                         finally
  342.                          {
  343.                              if(ois!=null) try{ois.close();}
  344.                                             catch(IOException e) {};
  345.                              ois=null;
  346.                          }
  347.                          
  348.  if(ad!=null) { System.err.println("   Rules list loaded from local backup copy");mergeBusters(); ad=null; return;}
  349.  }
  350.  catch (MalformedURLException e)
  351.   {}
  352. }
  353.  
  354. private final void mergeBusters()
  355. {
  356.  if(ad==null) return;
  357.  
  358.  /* save! */
  359.                          try {
  360.                                 BufferedOutputStream bos = new BufferedOutputStream
  361.                                     (new FileOutputStream("AdBuster.tmp"));
  362.                                 ObjectOutputStream oos =
  363.                                     new ObjectOutputStream(bos);
  364.                                 oos.writeObject(ad);
  365.                                 oos.close();                                
  366.                                 bos.close();
  367.                                 /* prejmenovat na .ser */
  368.                                 File f=new File("AdBuster.tmp");
  369.                                 File f2=new File("AdBuster.ser");
  370.                                 if(!f2.delete()) { System.err.println("   Delete old savefile failed.");}
  371.                                 if(false==f.renameTo(f2)) { System.err.println("   Rename to new savefile failed");}
  372.                         }
  373.                         catch (Throwable e) {
  374.                                 System.err.println("error when saving: "+e);
  375.                         }
  376.   for(int i=0;i<ad.allow.length;i++)
  377.    pass=addRegexpToArray(ad.allow[i],pass);
  378.  
  379.   for(int i=0;i<ad.fail.length;i++)
  380.    fail=addRegexpToArray(ad.fail[i],fail);
  381.       
  382.    
  383.   System.err.println("   Ad Busters mode init done.");
  384.   scache.VERSION=scache.CACHENAME+" "+scache.CACHEVER+" in Ad Busters mode";
  385.  
  386. }
  387. /*
  388. private final boolean caseSensitiveFilesystem()
  389. {
  390.  (new File(cache_dir)).mkdirs();
  391.  try{
  392.  new FileOutputStream(cache_dir+File.separator+"casecheck").close();
  393.  }
  394.  catch (IOException e1) {return false;}
  395.  boolean r=!new File(cache_dir+File.separator+"cAsEcHeCk").exists();
  396.  new File(cache_dir,"casecheck").delete();
  397.  return r;
  398. }
  399. */
  400. private final boolean endDotFilesystem()
  401. {
  402.  (new File(cache_dir)).mkdirs();
  403.  try{
  404.  new FileOutputStream(cache_dir+File.separator+"dot.").close();
  405.  }
  406.  catch (IOException e1) {
  407.                           cachedir.readonly=true;
  408.                           return false;
  409.             }
  410.  
  411.  File d=new File(cache_dir);
  412.  String names[];
  413.  names=d.list();
  414.  new File(cache_dir,"dot.").delete();
  415.  if(names==null) return false;
  416.   
  417.  for(int i=0;i<names.length;i++)
  418.   {
  419.    if(names[i].toLowerCase().equals("dot.")) return true;
  420.   }
  421.  
  422.  return false;
  423. }
  424.  
  425. public final void read_config(String cfgfile)
  426. {
  427.  try{
  428.  String line,token;
  429.  StringTokenizer st;
  430.  int lineno=0;
  431.  if(! new File(cfgfile).isAbsolute()) cfgfile=scache.cfgdir+File.separator+cfgfile;
  432.  
  433.  DataInputStream dis=new DataInputStream(new BufferedInputStream(new FileInputStream(cfgfile))); 
  434.  while ( (line = dis.readLine()) != null)
  435.  {
  436.       lineno++;
  437.       if(line.startsWith("#")) continue;
  438.       st=new StringTokenizer(line);
  439.       if(st.hasMoreTokens()==false) continue;
  440.       token=st.nextToken();
  441.       try
  442.       {
  443.           
  444.           if(token.equalsIgnoreCase("visible_link")) {httpreq.visible_link=st.nextToken();
  445.                                   continue;
  446.                             }
  447.           if(token.equalsIgnoreCase("stat_log"))   {stat_log=st.nextToken();
  448.                                   continue;
  449.                             }
  450.           if(token.equalsIgnoreCase("visible_hostname")) {httpreq.visible_hostname=st.nextToken();
  451.                                   continue;
  452.                                                     }
  453.           if(token.equalsIgnoreCase("default_forward_for")) {request.default_forward_for=st.nextToken();
  454.                                   continue;
  455.                                                     }
  456.                                                     
  457.           if(token.equalsIgnoreCase("adbustersid")) {AdID=st.nextToken();
  458.                                   continue;
  459.                                                     }
  460.                                                     
  461.           if(token.equalsIgnoreCase("adbustersauth")) {AdAuth=st.nextToken();
  462.                                   continue;
  463.                                                     }
  464.                                                     
  465.          if(token.equalsIgnoreCase("defaultname")) {cacheobject.defaultname=st.nextToken();
  466.                                   continue;
  467.                                                     }
  468.  
  469.          if(token.equalsIgnoreCase("allow_cookies_to")) 
  470.                                                     {
  471.                                                      while(st.hasMoreTokens())
  472.                                                      {
  473.                                                       String z;
  474.                                                       z=st.nextToken().toLowerCase();
  475.                                                       if(z.equals("all")) { allow_cookies_to=null;break;}
  476.                                                       allow_cookies_to=addStringToArray(z,allow_cookies_to);
  477.                                                      }
  478.                                    continue;
  479.                                                     }
  480.                                                                                                         
  481.  
  482.           if(token.equalsIgnoreCase("bindaddress")) {
  483.                                                     String ip=st.nextToken();
  484.                                                     if(ip.equals("*")) { ouraddress=null;continue;}
  485.                                                     try{
  486.                                                     ouraddress=InetAddress.getByName(ip);
  487.                                                     }
  488.                                                     catch (IOException e) { System.err.println("Can not resolve my BindAddress: "+ip);}
  489.                                   continue;
  490.                                                     }
  491.                                                                                                         
  492.                                                     
  493.           if(token.equalsIgnoreCase("shutdown_flag")) {shutdownflag=st.nextToken();
  494.                                   continue;
  495.                                                     }
  496.           if(token.equalsIgnoreCase("mime_types")) {repair.loadMimeTypes(st.nextToken());
  497.                                   continue;
  498.                                                     }
  499.  
  500.  
  501.           if(token.equalsIgnoreCase("immediate_shutdown_flag")) {immediate_shutdownflag=st.nextToken();
  502.                                   continue;
  503.                                                     }
  504.                                                     
  505.           if(token.equals("case_sensitive_matching")) {
  506.                                              char c=(char)Integer.valueOf(st.nextToken()).intValue();
  507.                                                            if(c!=0) case_sensitive=true; else case_sensitive=false;
  508.                                                            continue;
  509.                                                       }
  510.                               
  511.           if(token.equals("auto_compress")) {
  512.                                              char c=(char)Integer.valueOf(st.nextToken()).intValue();
  513.                                                            if(c!=0) cacheobject.auto_compress=true; else cacheobject.auto_compress=false;
  514.                                                            continue;
  515.                                                       }
  516.           if(token.equals("auto_decompress")) {
  517.                                              char c=(char)Integer.valueOf(st.nextToken()).intValue();
  518.                                                            if(c!=0) cacheobject.auto_decompress=true; else cacheobject.auto_decompress=false;
  519.                                                            continue;
  520.                                                       }
  521.           if(token.equals("allowconnect")) {
  522.                                                     while(st.hasMoreTokens())
  523.                             {
  524.                                              int c;
  525.                                c=Integer.valueOf(st.nextToken()).intValue();
  526.                                allowconnect=incIntegerArraySize(allowconnect);
  527.                                allowconnect[allowconnect.length-1]=c;
  528.                             }
  529.                                                            continue;
  530.                                                       }
  531.                                                     
  532.           if(token.equalsIgnoreCase("cacheroot")) {
  533.                                     cache_dir=st.nextToken();
  534.                       if(cache_dir.endsWith(File.separator)) 
  535.                          cache_dir=cache_dir.substring(0,cache_dir.length()-File.separator.length());
  536.                     if(cache_dir.length()==2 && cache_dir.charAt(1)==':') throw new IllegalArgumentException("Smart Cache will not use root directory '"+cache_dir+"' as data storage. Use some subdirectory instead.");
  537.                               continue;
  538.                                                   }
  539.                                                     
  540.           if(token.equalsIgnoreCase("port")) {ourport=Integer.valueOf(st.nextToken()).intValue();
  541.                                   continue;
  542.                                                     }
  543.  
  544.           if(token.equalsIgnoreCase("referer_hack")) {
  545.                                                      String rh=st.nextToken();
  546.                                                     try
  547.                                                       {
  548.                                        request.referer_hack=(char)Integer.valueOf(rh).intValue();
  549.                                                       }
  550.                                                     catch (NumberFormatException e)
  551.                                                      {
  552.                               System.out.println("[ERROR] Referer_hack do not longer accept non-numeric agument `"+rh+"`.\nUse fake_referer instead.");
  553.                                                      }
  554.                                   continue;
  555.                                                     }
  556.  
  557.           if(token.equalsIgnoreCase("fake_user_agent")) {request.fake_user_agent="User-Agent:"+st.nextToken("\n");
  558.                                        continue;
  559.                                                         }
  560.  
  561.           if(token.equalsIgnoreCase("fake_referer")) {request.fake_referer="Referer:"+st.nextToken("\n");  
  562.       request.referer_hack=98;
  563.                                     continue;
  564.                                                     }
  565.                                                     
  566.           if(token.equalsIgnoreCase("swap_level1_dirs")) {swap_level1_dirs=Integer.valueOf(st.nextToken()).intValue();
  567.                                   continue;
  568.                                                     }
  569.  
  570.           if(token.equalsIgnoreCase("swap_level2_dirs")) {swap_level2_dirs=Integer.valueOf(st.nextToken()).intValue();
  571.                                   continue;
  572.                                                     }
  573.           if(token.equalsIgnoreCase("http_proxy")) {
  574.                                                     if (st.countTokens()>2) 
  575.                                                         setproxy(st.nextToken(),Integer.valueOf(st.nextToken()).intValue(),st.nextToken());
  576.                                                      else 
  577.                                                         setproxy(st.nextToken(),Integer.valueOf(st.nextToken()).intValue(),null);
  578.                             
  579.                                    continue;
  580.                                                     }
  581.           if(token.equalsIgnoreCase("access_log")) {
  582.                                                     String mask=st.nextToken();
  583.                                                     if(mask.equals("*")) mask=null;
  584.           
  585.                                                     httpreq.logpatterns=addStringToArray(mask,httpreq.logpatterns);
  586.                                                     httpreq.logfilenames=addStringToArray(st.nextToken(),httpreq.logfilenames);
  587.                                                     
  588.                                   continue;
  589.                                                     }
  590.  
  591.           if(token.equalsIgnoreCase("agent_log")) {
  592.                                                     String mask=st.nextToken();
  593.                                                     if(mask.equals("*")) mask=null;
  594.           
  595.                                                     request.alogpatterns=addStringToArray(mask,request.alogpatterns);
  596.                                                     request.alogfilenames=addStringToArray(st.nextToken(),request.alogfilenames);
  597.                                                     
  598.                                   continue;
  599.                                                     }
  600.  
  601.           if(token.equalsIgnoreCase("referer_log")) {
  602.                                                     String mask=st.nextToken();
  603.                                                     if(mask.equals("*")) mask=null;
  604.           
  605.                                                     request.rlogpatterns=addStringToArray(mask,request.rlogpatterns);
  606.                                                     request.rlogfilenames=addStringToArray(st.nextToken(),request.rlogfilenames);
  607.                                                     
  608.                                   continue;
  609.                                                     }
  610.                                                                                                                                                             
  611.                                                     
  612.  
  613.           if(token.equalsIgnoreCase("no_proxy"))   {
  614.                                                     while(st.hasMoreTokens())
  615.                                                       no_proxy=addStringToArray(st.nextToken().toLowerCase(),no_proxy);
  616.                                   continue;
  617.                                                     }
  618.           if(token.equalsIgnoreCase("serialnumber")) {
  619.                                                     /* Look at my very secure registration keys checker */
  620.                                                     
  621.                                                     // if(st.nextToken().startsWith("HTTP")) registered=true;
  622.                                                     // else
  623.                                                     //System.out.println("\t\007WARNING: Invalid serial number entered!");
  624.                                                     // registered=true;
  625.                                   continue;
  626.                                                     }
  627.  
  628.           if(token.equalsIgnoreCase("fail")) {     while(st.hasMoreTokens())
  629.                                                       fail=addRegexpToArray(st.nextToken(),fail);
  630.                                   continue;
  631.                                                     }
  632.  
  633.           if(token.equalsIgnoreCase("fail_file")) {
  634.                                                     String fn=st.nextToken();
  635.                                                     fail=parseRegexpFile(fn,fail);
  636.                                                     fail_timestamp=new File(fn).lastModified();
  637.                                                     fail_filename=fn;
  638.                                   continue;
  639.                                                     }
  640.  
  641.           if(token.equalsIgnoreCase("allow_cookies_to_file")) {
  642.                                                     String fn=st.nextToken();
  643.                                                     allow_cookies_to=parseCookieFile(fn,allow_cookies_to);
  644.                                                     cookie_timestamp=new File(fn).lastModified();
  645.                                                     cookie_filename=fn;
  646.                                   continue;
  647.                                                     }
  648.                                                     
  649.           if(token.equalsIgnoreCase("pass_file")) {
  650.                                                     String fn=st.nextToken();
  651.                                                     pass=parseRegexpFile(fn,pass);
  652.                                                     pass_timestamp=new File(fn).lastModified();
  653.                                                     pass_filename=fn;
  654.                                   continue;
  655.                                                     }
  656.                                                                                                         
  657.           if(token.equalsIgnoreCase("nocaching")) { while(st.hasMoreTokens())
  658.                                                        nocache=addRegexpToArray(st.nextToken(),nocache);
  659.                                                     cacheonly=false;
  660.                                   continue;
  661.                                                     }
  662.  
  663.           if(token.equalsIgnoreCase("wafer")
  664.       || token.equalsIgnoreCase("fake_cookie")
  665.       ) {request.wafer="Cookie:"+st.nextToken("\n");
  666.                                        continue;
  667.                                               }
  668.  
  669.           if(token.equalsIgnoreCase("pass"))      {while(st.hasMoreTokens())
  670.                                                     pass=addRegexpToArray(st.nextToken(),pass);
  671.                                  continue;
  672.                                                    }
  673.                                                     
  674.           if(token.equalsIgnoreCase("cacheonly")) {while(st.hasMoreTokens())
  675.                                                      nocache=addRegexpToArray(st.nextToken(),nocache);
  676.                                                    cacheonly=true;
  677.                                  continue;
  678.                                                     }
  679.                                                                                                         
  680.                                                                                                         
  681.           if(token.equalsIgnoreCase("redirect")) { redirfrom=addStringToArray(st.nextToken(),redirfrom);
  682.                                                    redirto=addStringToArray(st.nextToken(),redirto);
  683.                                  continue;
  684.                                                    }
  685.  
  686.           if(token.equalsIgnoreCase("quick_abort")) { 
  687.                                                    request.qa_minlen=Integer.valueOf(st.nextToken()).intValue();          
  688.                                                    request.qa_percent=Float.valueOf(st.nextToken()).floatValue();                                                   
  689.                                                    request.qa_maxlen=Integer.valueOf(st.nextToken()).intValue();                                                             
  690.                                  continue;
  691.                                                    }
  692.  
  693.           if(token.equalsIgnoreCase("errordocument")) { 
  694.                                                    int code=Integer.valueOf(st.nextToken()).intValue();          
  695.                                                    if(code==403) custom403=st.nextToken();
  696.                                                     else if(code==400 || code==500) cacheobject.custom500=st.nextToken();
  697.                                                           else
  698.                                                             System.err.println("[CONFIG_ERROR] "+cfgfile+":"+lineno+" Error code "+code+" is not customizable.");
  699.                                  continue;
  700.                                                    }
  701.                                                                                                       
  702.  
  703.           if(token.equalsIgnoreCase("max_aborted_transfer_time")) { 
  704.                                                    request.qa_maxtime=Integer.valueOf(st.nextToken()).intValue()*1000L*60L;
  705.                                  continue;
  706.                                                    }
  707.  
  708.           if(token.equalsIgnoreCase("max_clients")) { 
  709.                                                    scache.MAXHTTPCLIENTS=Integer.valueOf(st.nextToken()).intValue();
  710.                                  continue;
  711.                                                    }
  712.  
  713.           if(token.equalsIgnoreCase("inputtimeout")) { 
  714.                                                    httpreq.client_timeout=Integer.valueOf(st.nextToken()).intValue()*1000;
  715.                                  continue;
  716.                                                    }
  717.           if(token.equalsIgnoreCase("proxyreadtimeout")) { 
  718.                                                    request.read_timeout=Integer.valueOf(st.nextToken()).intValue()*1000;
  719.                                  continue;
  720.                                                    }
  721.                                                    
  722.                                                    
  723.           if(token.equalsIgnoreCase("pragma_no_cache")) { 
  724.                                                    request.pnocache=(char)Integer.valueOf(st.nextToken()).intValue();
  725.                                  continue;
  726.                                                    }
  727.           if(token.equalsIgnoreCase("append_via"  )) { 
  728.                                                    int z=Integer.valueOf(st.nextToken()).intValue();
  729.                                                    if(z!=0) request.append_via=true; else
  730.                                                             request.append_via=false;
  731.                                  continue;
  732.                                                    }
  733.           if(token.equalsIgnoreCase("keep_deleted")) { 
  734.                                                    int z=Integer.valueOf(st.nextToken()).intValue();
  735.                                                    if(z!=0) cacheobject.keep_deleted=true; else
  736.                                                     cacheobject.keep_deleted=false;
  737.                                  continue;
  738.                                                    }
  739.  
  740.           if(token.equalsIgnoreCase("cache_password_protected")) { 
  741.                                                    int z=Integer.valueOf(st.nextToken()).intValue();
  742.                                                    if(z!=0) request.cache_protected=true; else
  743.                                                     request.cache_protected=false;
  744.                                  continue;
  745.                                                    }
  746.                                                    
  747.           if(token.equalsIgnoreCase("remove_pragma_no_cache")) { 
  748.                                                    int z=Integer.valueOf(st.nextToken()).intValue();
  749.                                                    if(z!=0) request.remove_pragma_no_cache=true; else
  750.                                                     request.remove_pragma_no_cache=false;
  751.                                  continue;
  752.                                                    }
  753.  
  754.           if(token.equalsIgnoreCase("fail_trace")) { 
  755.                                                    int z=Integer.valueOf(st.nextToken()).intValue();
  756.                                                    if(z!=0) fail_trace=true; else
  757.                                                     fail_trace=false;
  758.                                  continue;
  759.                                                    }
  760.           if(token.equalsIgnoreCase("clear_flags_on_start")) { 
  761.                                                    int z=Integer.valueOf(st.nextToken()).intValue();
  762.                                                    if(z!=0) clear_flags_on_start=true; else
  763.                                                     clear_flags_on_start=false;
  764.                                  continue;
  765.                                                    }
  766.           if(token.equalsIgnoreCase("flag_check_interval")) { 
  767.                                                    int z=Integer.valueOf(st.nextToken()).intValue();
  768.                                                    flag_check_interval=z;
  769.                                  continue;
  770.                                                    }
  771.          if(token.equalsIgnoreCase("reload_block_files")) {
  772.                             // ABSOLETE: now always enabled
  773.                                  continue;
  774.                                                    }
  775.                                                                                                       
  776.           if(token.equalsIgnoreCase("generate_lastmod")) { 
  777.                                                    int z=Integer.valueOf(st.nextToken()).intValue();
  778.                                                    cacheobject.generate_lastmod=z;
  779.                                  continue;
  780.                                                    }
  781.  
  782.           if(token.equalsIgnoreCase("hide_errors")) { 
  783.                                                    int z=Integer.valueOf(st.nextToken()).intValue();
  784.                                                    if(z!=0) cacheobject.hide_errors=true; else
  785.                                                     cacheobject.hide_errors=false;
  786.                                  continue;
  787.                                                    }
  788.  
  789.           if(token.equalsIgnoreCase("full_referer_log")) { 
  790.                                                    int z=Integer.valueOf(st.nextToken()).intValue();
  791.                                                    if(z!=0) request.full_referer_log=true; else
  792.                                                     request.full_referer_log=false;
  793.                                  continue;
  794.                                                    }
  795.                                                    
  796.           if(token.equalsIgnoreCase("allow")) {
  797.                            while(st.hasMoreElements())
  798.                            {
  799.                                                String adr;
  800.                            adr=st.nextToken();
  801.                                                if(adr.equals("*")) httpreq.allowed=null;
  802.                            else
  803.                                                httpreq.allowed=addInetAdrToArray(InetAddress.getByName(adr),httpreq.allowed);
  804.                            }
  805.                            continue;
  806.                           }
  807.           if(token.equalsIgnoreCase("default_refresh_pattern")) 
  808.                                                     {
  809.                                                     reload_age=(long)(Float.valueOf(st.nextToken()).floatValue()*1000L*60L);
  810.                                                     min_age=(long)(Float.valueOf(st.nextToken()).floatValue()*1000L*60L);
  811.                                                     lmfactor=Float.valueOf(st.nextToken()).floatValue();
  812.                                                     max_age=(long)(Float.valueOf(st.nextToken()).floatValue()*1000L*60L);
  813.                                                     if(reload_age>min_age) reload_age=min_age/2;
  814.                                                     if(max_age<=min_age) max_age=min_age+1000L*60L*60L*48L;
  815.                             if(st.countTokens()>0)
  816.                             {
  817.                                                       expire_age=(long)(Float.valueOf(st.nextToken()).floatValue()*1000L*60L);
  818.                                                       redir_age=(long)(Float.valueOf(st.nextToken()).floatValue()*1000L*60L);
  819.                             } else
  820.                             System.out.println("[WARNING] default_refresh_pattern can have additional arguments.");
  821.                             if(expire_age>max_age) expire_age=max_age;
  822.                             if(redir_age>min_age) redir_age=min_age;
  823.                                   continue;
  824.                                                     }
  825.           if(token.equalsIgnoreCase("refresh_pattern")) 
  826.                                                     {
  827.                                                     String url=st.nextToken();
  828.                                                     if(isInRegexpArray(url,refresh)) continue;
  829.                                                     long xreload_age=(long)Float.valueOf(st.nextToken()).floatValue()*1000L*60L;
  830.                                                     long xmin_age=(long)Float.valueOf(st.nextToken()).floatValue()*1000L*60L;
  831.                                                     float xlmfactor=Float.valueOf(st.nextToken()).floatValue();
  832.                                                     long xmax_age=(long)Float.valueOf(st.nextToken()).floatValue()*1000L*60L;
  833.                                                     if(xreload_age>xmin_age) xreload_age=xmin_age/4;
  834.                                                     if(xmax_age<=xmin_age) xmax_age=xmin_age+1000L*60L*60L*48L;
  835.                             long xexpire_age,xredir_age;
  836.                             if(st.countTokens()>0)
  837.                             {
  838.                                                       xexpire_age=(long)(Float.valueOf(st.nextToken()).floatValue()*1000L*60L);
  839.                                                       xredir_age=(long)(Float.valueOf(st.nextToken()).floatValue()*1000L*60L);
  840.                             } else
  841.                             { 
  842.                                System.out.println("[WARNING] refresh_pattern can have additional arguments.");
  843.                                xexpire_age=5*60*1000L;
  844.                                xredir_age=10*1000L;
  845.                             }
  846.                             
  847.                             if(xexpire_age>xmax_age) xexpire_age=xmax_age;
  848.                             if(xredir_age>xmin_age) xredir_age=xmin_age;
  849.                                                     /* pridat do pole */
  850.                                                     refresh=addRegexpToArray(url,refresh);
  851.                                                     /* natahnout ! */
  852.                                                     reloadage=incLongArraySize(reloadage);
  853.                                                     minage=incLongArraySize(minage);
  854.                                                     maxage=incLongArraySize(maxage);
  855.                                                     expireage=incLongArraySize(expireage);
  856.                                                     redirage=incLongArraySize(redirage);
  857.                                                     lastmodf=incFloatArraySize(lastmodf);
  858.                                                     
  859.                                                     /* nastavit hodnoty */
  860.                                                     reloadage[reloadage.length-1]=xreload_age;
  861.                                                     minage[minage.length-1]=xmin_age;
  862.                                                     maxage[maxage.length-1]=xmax_age;
  863.                                                     lastmodf[lastmodf.length-1]=xlmfactor;
  864.                                                     expireage[expireage.length-1]=xexpire_age;
  865.                                                     redirage[redirage.length-1]=xredir_age;
  866.                                   continue;
  867.                                                     }
  868.                                                     
  869.                                                                                                                                                             
  870.           System.out.println("[CONFIG_ERROR] Unknown keyword "+token+" in "+cfgfile+":"+lineno);  
  871.      }
  872.      catch (NoSuchElementException nse)
  873.            { System.out.println("[CONFIG_ERROR] "+cfgfile+":"+lineno+" Missing arguent(s).");
  874.              continue;}                                     
  875.      catch (NumberFormatException nse)
  876.            { System.out.println("[CONFIG_ERROR] "+cfgfile+":"+lineno+" Invalid Number Format.");
  877.              continue;}                                     
  878.              
  879.      
  880.  }/* while */
  881.  dis.close();
  882.    
  883.  }
  884.  catch(FileNotFoundException kiss)
  885.   { System.out.println("[WARNING] No config file ("+cfgfile+") found, using defaults.");}  
  886.  catch(IOException e) 
  887.   { System.out.println("I/O Error reading config file "+cfgfile);}
  888.  
  889.  // init access log filez 
  890.  if(httpreq.logpatterns!=null) httpreq.logfilez=new DataOutputStream[httpreq.logpatterns.length];
  891.  
  892.  // init agent log filez 
  893.  if(request.alogpatterns!=null) request.alogfilez=new DataOutputStream[request.alogpatterns.length];
  894.  
  895.  // init referer log filez 
  896.  if(request.rlogpatterns!=null) request.rlogfilez=new DataOutputStream[request.rlogpatterns.length];
  897.  
  898.  if(swap_level1_dirs<1) swap_level1_dirs=1;
  899.  if(swap_level2_dirs<1) swap_level2_dirs=1;
  900. }
  901.  
  902. public final void setproxy(String hostname,int port,String auth)
  903. {
  904.  if (auth!=null) parentauth="Proxy-authorization: Basic "+HTUU.encode_string(auth); else parentauth=null;
  905.  try{
  906.  parentproxy=InetAddress.getByName(hostname);
  907.  this.port=port;
  908. // System.out.println("My parent proxy is "+hostname+" port "+port);
  909.  }
  910.  catch (UnknownHostException e) 
  911.   {
  912.    System.err.println("[WARNING] Can not resolve parent proxy hostname: "+hostname+" - running without it.");
  913.    parentproxy=null;
  914.    no_proxy=null;
  915.    parentauth=null;
  916.    this.port=0;
  917.   }
  918. }
  919.  
  920. final public void process_request(request req) throws MalformedURLException, IOException
  921. {
  922.  boolean allowed;
  923.  allowed=false;
  924.  
  925.  String requested=req.getURL();
  926.  
  927.  /* HANDLE  REWRITE ! */
  928.  if(redirfrom!=null)
  929.   {
  930.    String fragment;
  931.    int j=redirfrom.length;
  932.    for(int i=0;i<j;i++)
  933.    {
  934.     fragment=simpleWildMatch(redirfrom[i], requested);
  935.     if(fragment==null) continue;
  936.     if(is_wild(redirto[i])) 
  937.      //req.make_headers(301,"text/html",redirto[i].substring(0,redirto[i].length()-1)+fragment,0,0,0);
  938.        req.rewriteURL(redirto[i].substring(0,redirto[i].length()-1)+fragment);
  939.      else
  940.        // req.make_headers(301,"text/html",redirto[i],0,0,0);
  941.        req.rewriteURL(redirto[i]);
  942.  
  943.     requested=req.getURL(); // reread URL
  944.     break;          
  945.    }
  946.   } /* redir handler end */
  947.  
  948.  
  949.  try
  950.  {
  951.  /* is URL in allowed list ? */
  952.  if(pass!=null)
  953.   {
  954.   
  955.    int j=pass.length;
  956.    for(int i=0;i<j;i++)
  957.     if(pass[i].matches(requested))
  958.      { allowed=true;break;}
  959.   }
  960.  }
  961.  catch (IndexOutOfBoundsException ignore) {}
  962.  
  963.  try
  964.  {
  965.  /* is URL blocked ? */ 
  966.  if(fail!=null && allowed==false)
  967.   {
  968.   
  969.    int j=fail.length;
  970.    for(int i=0;i<j;i++)
  971.    {
  972.     if(fail[i].matches(requested))
  973.      { 
  974.        cacheobject.c_block++; //STAT
  975.        if(fail_trace)
  976.        {
  977.          System.out.println("Blocked: " +requested+"\n\tby rule: \""+fail[i]+"\"");
  978.        }
  979.        if(custom403==null) req.send_error(403,"Forbidden by rule");
  980.          else
  981.             if(custom403.charAt(0)=='0') {
  982.             req.make_headers(200,"image/gif",null,null,43,886828316241L,0);
  983.         req.send_headers();
  984.         req.sendBytes(req.GIF);
  985.           }
  986.         else 
  987.             if(custom403.charAt(0)=='-') { 
  988.                                        req.send_error(204,"No Content");  
  989.                                        }
  990.             else if(custom403.charAt(0)=='!')
  991.               {
  992.                  req.make_headers(200,"text/html",null,null,0,new Date().getTime(),0);
  993.                  req.send_headers();
  994.                  req.sendString("<HTML></HTML>");
  995.               }                                       
  996.                   else
  997.                    { req.make_headers(301,null,null,custom403,0,new Date().getTime(),0);
  998.                      req.send_headers();
  999.                    }
  1000.                 
  1001.        req.close();
  1002.        return;
  1003.        }
  1004.    }
  1005.   
  1006.   }
  1007.   
  1008.  }
  1009.  catch (IndexOutOfBoundsException ignore) {}
  1010.   
  1011.   /* NO-CACHE HANDLER */
  1012.     
  1013.   if(nocache!=null)
  1014.    { // if(cacheonly) req.nocache();
  1015.    
  1016.      int j=nocache.length;
  1017.      int i;
  1018.      
  1019.      toploop:while(true)
  1020.      {
  1021.      for(i=0;i<j;i++)
  1022.        {
  1023.          if(nocache[i].matches(requested))
  1024.            {
  1025.             if(!cacheonly) req.nocache();
  1026.             break toploop;              
  1027.            }
  1028.        } /* for */
  1029.          if(cacheonly) req.nocache();    
  1030.          break;   
  1031.       } /* toploop */
  1032.    }
  1033.    
  1034.  String[] parsed;
  1035.  parsed=parseURL(requested,req.getProtocol());
  1036.  String host=parsed[0];
  1037.  
  1038.  try
  1039.  {
  1040.  /* C00KIES FILTER */
  1041.  if(allow_cookies_to!=null)
  1042.   {
  1043.    cookieloop:while(true)
  1044.    {
  1045.     for(int i=allow_cookies_to.length-1;i>=0;i--)
  1046.      if(host.endsWith(allow_cookies_to[i])) { break cookieloop;}
  1047.    
  1048.    req.removeCookies();
  1049.    break;
  1050.    }
  1051.   }
  1052.  }
  1053.  catch (IndexOutOfBoundsException ignore) {}
  1054.  
  1055.  /* USE PARENT PROXY SERVER ?? */
  1056.  boolean direct;
  1057.  if(parentproxy==null) direct=true;
  1058.   else
  1059.   {
  1060.      direct=false;
  1061.      if(no_proxy!=null) {
  1062.         int j=no_proxy.length;
  1063.         for(int i=0;i<j;i++) {
  1064.            if(host.endsWith(no_proxy[i])) {
  1065.               direct=true;
  1066.               break;
  1067.               }
  1068.            }
  1069.         } /* if No_proxy */
  1070.   }
  1071.  if(direct)
  1072.  {
  1073.  /* DIREKT REZIM - klidek */
  1074.  try{
  1075.    req.setTarget(InetAddress.getByName(host),parsed[1]==null? 80: Integer.valueOf(parsed[1]).intValue());
  1076.  }
  1077.  catch (UnknownHostException e) { req.setTarget(null,80); }
  1078.  catch (NumberFormatException e) { req.send_error(400,"Port is not a numeric constant: "+parsed[1]); }
  1079.  
  1080.  /* premenime request na normal */
  1081.  if(parsed[4]!=null) req.send_error(501,"Protocol "+parsed[4]+" is not directly supported, configure http_proxy.");
  1082.  req.setRequestTo(parsed[2]+parsed[3]);
  1083.  }
  1084.  else
  1085.  {
  1086.    req.setTarget(parentproxy,port);
  1087.    if (parentauth!=null) req.add_header(parentauth);
  1088.  }
  1089.  
  1090.  /* testneme na non HEAD/GET methods */
  1091.   switch(req.getMethod())
  1092.   {
  1093.    case httpreq.REQUEST_POST:
  1094.    case httpreq.REQUEST_PUT:  
  1095.                                req.addHost(host,parsed[1]);
  1096.                                req.direct_request(true);
  1097.                                return;
  1098.    case httpreq.REQUEST_TRACE: 
  1099.                                req.handle_trace();
  1100.                    return;
  1101.    case httpreq.REQUEST_OPTIONS:
  1102.                                req.addHost(host,parsed[1]);
  1103.                                req.handle_options();
  1104.                    return;
  1105.    case httpreq.REQUEST_DELETE: 
  1106.                                req.addHost(host,parsed[1]);
  1107.                                req.direct_request(false);
  1108.                                return;
  1109.   case httpreq.REQUEST_CONNECT:
  1110.                                 {
  1111.                  int port=80;
  1112.                                  if(parsed[1]!=null) 
  1113.                    try
  1114.                     { port=Integer.valueOf(parsed[1]).intValue();}
  1115.                                     catch (NumberFormatException e) { req.send_error(400,"Port is not a numeric constant:"+parsed[1]); }
  1116.  
  1117.                                  if(allowconnect==null) req.send_error(501,"CONNECCT method is disabled by configuration.");
  1118.                    /* Always go direct! */
  1119.                    try
  1120.                    {
  1121.                                     req.setTarget(InetAddress.getByName(host),port);}
  1122.                                    catch (UnknownHostException e) 
  1123.                                      { req.send_error(500,"CONNECT failed: "+host+" Host unknown.");}
  1124.                  for(int i=allowconnect.length-1;i>=0;i--)
  1125.                  {
  1126.                    if(allowconnect[i]==port)
  1127.                     {
  1128.                      req.handle_connect();
  1129.                      return;
  1130.                     }
  1131.                  }
  1132.                                  req.send_error(403,"Direct connecting to port "+parsed[1]+" is forbidden by rule.");
  1133.                 }
  1134.   }
  1135.  
  1136.  req.addHost(host,parsed[1]); /* pridat Host: hlavicku */
  1137.  
  1138.  /* konverze na local dir */
  1139.  String locdir=getLocalDir(host,parsed[1],parsed[2],parsed[4]);
  1140.  cachedir dir=null;
  1141.  try{
  1142.       dir=getDir(locdir);
  1143.     }
  1144.  catch(Exception e) { e.printStackTrace();
  1145.                       System.out.println("Hostname:"+host);
  1146.                       System.out.println("Port:"+parsed[1]);
  1147.                       System.out.println("Dir:"+parsed[2]);
  1148.                       req.close();
  1149.                       return;
  1150.                     }
  1151.  cacheobject cobj;
  1152.  cobj=dir.getObject(parsed[3]);
  1153.  
  1154.  /* HANDLE REFRESH PATTERNS MIN_AGE, PERCENT, MAX_AGE */
  1155.  if(refresh!=null)
  1156.   {
  1157.    int refreshcache=refresh.length;
  1158.    for(int i=0;i<refreshcache;i++)
  1159.     if(refresh[i].matches(requested))
  1160.      {
  1161.      cobj.make_request(req,reloadage[i],minage[i],maxage[i],lastmodf[i],expireage[i],redirage[i]);
  1162.      break;
  1163.      }
  1164.   
  1165.   }
  1166.   else
  1167.    cobj.make_request(req,reload_age,min_age,max_age, lmfactor,expire_age,redir_age);
  1168.  
  1169.  req.close();
  1170. }
  1171.  
  1172. final private synchronized cachedir getDir(String locdir)
  1173.  cachedir dir=(cachedir)dircache.get(locdir);
  1174.  if(dir!=null) return dir;
  1175.  
  1176.  dir=new cachedir(locdir); 
  1177.  dircache.put(locdir,dir);
  1178.  return dir;
  1179. }
  1180.  
  1181. final public void run()
  1182. {
  1183.  int ticks;
  1184.  if(immediate_shutdownflag==null || flag_check_interval<=0) 
  1185.        flag_check_interval=(int)(SAVETIMER/1000);
  1186.  /* normalize fci */
  1187.  ticks=(int)(SAVETIMER/1000/flag_check_interval);
  1188.  if(ticks==0) ticks=1;
  1189.  flag_check_interval=(int)(SAVETIMER/1000/ticks);
  1190.  long sleeptime=flag_check_interval*1000L;
  1191.  int i=0;
  1192.  // System.out.println("[debug] ticks="+ticks+" sleeptime="+sleeptime/1000);
  1193.  while(true)
  1194.  {
  1195.  
  1196.  try{
  1197.  Thread.sleep(sleeptime);
  1198.  }
  1199.  catch (InterruptedException e) 
  1200.  { 
  1201.    System.out.println("[Smart Cache] Background saver Interrupted, exiting.");
  1202.    save();save();break;
  1203.  }
  1204.  i++;
  1205.  if(i>=ticks) { save();i=0;}
  1206.  /* check 4 IMM shutdownflag */
  1207.   if(checkFlag(immediate_shutdownflag))
  1208.    {
  1209.     Enumeration e2=dircache.elements();
  1210.     while(e2.hasMoreElements())
  1211.     {
  1212.      cachedir d;
  1213.      d=(cachedir) e2.nextElement();
  1214.      d.save();
  1215.      d.cleandir(); /* if needed */ 
  1216.     }
  1217.     httpreq.flush(httpreq.logfilez);
  1218.     httpreq.flush(request.alogfilez);
  1219.     httpreq.flush(request.rlogfilez);
  1220.     System.out.println(new Date()+" Server stoped by Immediate shutdown flag.");System.exit(0);
  1221.    }
  1222.  
  1223.   // reloading block files
  1224.     if(pass_filename!=null)
  1225.      {
  1226.       if(new File(pass_filename).lastModified()!=pass_timestamp)
  1227.       {
  1228.        System.out.println(new Date()+" Reloading Pass_file "+pass_filename);
  1229.        pass=parseRegexpFile(pass_filename,null);
  1230.        pass_timestamp=new File(pass_filename).lastModified();
  1231.       }
  1232.      }
  1233.  
  1234.     if(fail_filename!=null)
  1235.      {
  1236.       if(new File(fail_filename).lastModified()!=fail_timestamp)
  1237.       {
  1238.        System.out.println(new Date()+" Reloading fail_file "+fail_filename);
  1239.        fail=parseRegexpFile(fail_filename,null);
  1240.        fail_timestamp=new File(fail_filename).lastModified();
  1241.       }
  1242.      }
  1243.         
  1244.     if(cookie_filename!=null)
  1245.      {
  1246.       if(new File(cookie_filename).lastModified()!=cookie_timestamp)
  1247.       {
  1248.        System.out.println(new Date()+" Reloading allow_cookies_to_file "+cookie_filename);
  1249.        allow_cookies_to=parseCookieFile(cookie_filename,null);
  1250.        cookie_timestamp=new File(cookie_filename).lastModified();
  1251.       }
  1252.      }
  1253.  }
  1254.  
  1255. }
  1256.  
  1257. /* Ulozi hashtabulku na disk */
  1258. final private void save()
  1259. {
  1260.  int saved=0;
  1261.  int cleaned=0;
  1262.  Enumeration e1=dircache.keys();
  1263.  Enumeration e2=dircache.elements();
  1264.  while(e1.hasMoreElements())
  1265.  {
  1266.   cachedir d;
  1267.   d=(cachedir) e2.nextElement();
  1268.   String key;
  1269.   key=(String) e1.nextElement();
  1270.   
  1271.   if(d.dirty==true) { d.save(); saved++;}
  1272.     else
  1273.                   { dircache.remove(key);
  1274.                     d.cleandir(); /* if needed */ 
  1275. //                  System.err.println("[DIRGC] "+key);
  1276.                     cleaned++;}
  1277.  
  1278.  }
  1279.  httpreq.flush(httpreq.logfilez);
  1280.  httpreq.flush(request.alogfilez);
  1281.  httpreq.flush(request.rlogfilez);
  1282.  
  1283.  /* STATs */
  1284.  DataOutputStream dos=null;
  1285.  if(stat_log!=null)
  1286.  try
  1287.  {
  1288.    dos=new DataOutputStream(new BufferedOutputStream(
  1289.    new FileOutputStream(stat_log,true),4096));
  1290.  }
  1291.    catch (IOException ee1)
  1292.    {
  1293.           System.err.println("Problem creating stat_log file "+stat_log+" - turning it off.");
  1294.           stat_log=null;
  1295.    }
  1296.  
  1297.  if(saved>0)
  1298.  {
  1299.    StringBuffer sb=new StringBuffer(100);
  1300.    sb.append(new Date().toString());
  1301.    sb.append(" - ");
  1302.    sb.append(
  1303.    (int)(
  1304.    100.0f*(cacheobject.c_hit+cacheobject.c_block)  /  
  1305.    ((float)cacheobject.c_hit+cacheobject.c_block
  1306.                 +cacheobject.c_miss+cacheobject.c_refresh)
  1307.         )   );
  1308.    sb.append("% REQS: ");
  1309.    sb.append(cacheobject.c_hit);
  1310.    sb.append(" Hit, ");
  1311.    sb.append(cacheobject.c_refresh);
  1312.    sb.append(" Refresh, ");
  1313.    sb.append(cacheobject.c_miss);
  1314.    sb.append(" Miss, ");
  1315.    sb.append(cacheobject.c_block);
  1316.    sb.append(" Block.");
  1317.    System.out.println(sb);
  1318.    if(dos!=null)
  1319.      try
  1320.       {
  1321.         dos.writeBytes(sb.toString());
  1322.         dos.writeBytes("\n");
  1323.       }
  1324.       catch (IOException ignore) {}
  1325.    
  1326.    // clear the stats
  1327.    cacheobject.c_hit=cacheobject.c_miss=cacheobject.c_refresh=cacheobject.c_block
  1328.    =0;
  1329.  }
  1330.  if(cacheobject.b_miss+cacheobject.b_hit>0)
  1331.  {
  1332.    StringBuffer sb=new StringBuffer(100);
  1333.    sb.append(new Date());
  1334.    sb.append(" - ");
  1335.    sb.append(
  1336.    (int)(
  1337.    100.0f*cacheobject.b_hit/((float)cacheobject.b_miss+cacheobject.b_hit)
  1338.    )         );
  1339.    sb.append("% BYTES: ");
  1340.    sb.append(cacheobject.b_miss);
  1341.    sb.append(" B in, ");
  1342.    sb.append(cacheobject.b_miss+cacheobject.b_hit);
  1343.    sb.append(" B out.");
  1344.    System.out.println(sb);
  1345.    if(dos!=null)
  1346.      try
  1347.       {
  1348.         dos.writeBytes(sb.toString());
  1349.         dos.writeBytes("\n");
  1350.       }
  1351.       catch (IOException ignore) {}
  1352.    
  1353.    // clear the stats
  1354.    cacheobject.b_hit=cacheobject.b_miss=0;
  1355.   }
  1356.   /* close stat_logfile */
  1357.   if(dos!=null)
  1358.    try
  1359.     { dos.close();}
  1360.    catch (IOException err)
  1361.     {
  1362.      stat_log=null;
  1363.     }
  1364.  
  1365.  if(saved>0 || cleaned> 0) 
  1366.   {
  1367.    System.out.println(new Date().toString()+" - DIRS: "+saved+" saved, "+cleaned+" garbage collected.");
  1368.   }
  1369.  if(saved==0)
  1370.   { 
  1371.    httpreq.close(httpreq.logfilez);
  1372.    httpreq.close(request.alogfilez);
  1373.    httpreq.close(request.rlogfilez);   
  1374.  
  1375.    if(checkFlag(shutdownflag)) 
  1376.          { System.out.println(new Date()+" Server stoped by shutdown flag.");System.exit(0);}
  1377.   }
  1378.   
  1379.   
  1380.      
  1381. } /* save end */
  1382.  
  1383. /*  prechrousta URL a vrati
  1384. 0 - hostname
  1385. 1 - port (if any) jinak null
  1386. 2 - directory
  1387. 3 - file including query string ("" if empty)
  1388. 4 - protocol (null if http)
  1389. */
  1390.  
  1391. final public static String[] parseURL(String url,String proto)
  1392. {
  1393.   String[] res=new String[5];
  1394.   res[3]=""; /* HashTable do not likes NULL */
  1395.   int i,j,seven;
  1396.   if(proto!=null)
  1397.   {
  1398.   /* protocol check */
  1399.   res[4]=proto;
  1400.   seven=proto.length()+3; /* '://' */
  1401.   
  1402.   if(seven==7)
  1403.    {
  1404.     char c;
  1405.     c=proto.charAt(0);
  1406.     if(c=='h' || c=='H') res[4]=null;
  1407.    }
  1408.   }else { res[4]=null;seven=0;}
  1409.   i=url.indexOf('/',seven);
  1410.   if(i==-1) { url+='/'; i=url.length()-1;}
  1411.   
  1412.   j=url.indexOf(':',seven);
  1413.   /* http://zero.dsd:434/ */
  1414.   if(j!=-1 && j<i)  /* mame tu portname */
  1415.                     {
  1416.                       res[0]=url.substring(seven,j).toLowerCase();
  1417.                       res[1]=url.substring(j+1,i);
  1418.                       if(res[1].equals("80")) res[1]=null;
  1419.                     }
  1420.            else
  1421.              {
  1422.               res[0]=url.substring(seven,i).toLowerCase();
  1423.              }
  1424.  
  1425.   /* parse adr */
  1426.   
  1427.   /* najdeme nejvice vlevo z moznych debilnich znaku */
  1428.   
  1429.    j=url.length()-1;
  1430.    byte v[];
  1431.    v=new byte[j+1];
  1432.    url.getBytes(i,j+1,v,i);
  1433.    // getChars(i,j,v,0);
  1434.    loop1:for(int zz=i;zz<=j;zz++)
  1435.     {
  1436.     switch(v[zz])
  1437.     {
  1438.     case 0x3b: // ;
  1439.     case 0x3a: // :
  1440.     case 0x3d: // =
  1441.     case 0x3f: // ?
  1442.               j=zz;break loop1;
  1443.     case 0x23: // #
  1444.      url=url.substring(0,zz);break loop1;
  1445.     }
  1446.     }
  1447.       
  1448.    
  1449.    j=url.lastIndexOf('/',j);
  1450.  
  1451.   String adr=url.substring(i,j+1); // adresar
  1452.   /* Normalize URL - remove /../ */
  1453.   /* NOTE: /./ should be also removed, but it do not hurt anything? */
  1454.   while( (i=adr.indexOf("/../")) >= 0 ) 
  1455.   {
  1456.    /* DEBUG: 
  1457.    */
  1458.    int l;
  1459.    if( (l=adr.lastIndexOf('/',i-1)) >=0 )
  1460.       adr= adr.substring(0,l)+ adr.substring(i+3);
  1461.    else
  1462.      adr=adr.substring(i+3);
  1463.   }
  1464.   res[2]=adr;
  1465.   if(j+1!=url.length()) res[3]=url.substring(j+1);
  1466.   return res;  
  1467. }
  1468.  
  1469. final public String getLocalDir(String host,String port,String urldir,String proto)
  1470. {
  1471. /***
  1472. Host - zero.vole.cz:3333
  1473. urldir = /ddfgfds/rerew/ - musi koncit s /
  1474. */
  1475.   StringBuffer result=new StringBuffer(80);
  1476.   result.append(cache_dir);
  1477.   int i;
  1478.   
  1479.   /* 1. spocitat hash z host stringu */
  1480.   CRC32 crc=new CRC32();
  1481.   
  1482.   // host=host.toLowerCase();  
  1483.   crc.update(host.getBytes());
  1484.                            
  1485.   /* mame hash - rozdelime ho na adresar */
  1486. //  System.out.println("value="+i);  
  1487.   /* zacneme budovat cestu */
  1488.       i=(int)(crc.getValue()/(0x100000000L/(swap_level1_dirs*swap_level2_dirs)));
  1489.       result.append(File.separator+(i/swap_level2_dirs)+File.separator+(i % swap_level2_dirs)+File.separator+host);
  1490.       
  1491.   /* pridame port */
  1492.   if(port!=null)
  1493.    {result.append('_');
  1494.     result.append(port);
  1495.    }
  1496.  
  1497.   /* add protocol */
  1498.   if(proto!=null) 
  1499.              {
  1500.               result.append('^');
  1501.               result.append(proto);
  1502.              }
  1503.   
  1504.   /* pridame adresar */
  1505.   if(File.separatorChar!='/') urldir=urldir.replace('/',File.separatorChar);
  1506.   
  1507.   /* *************************************************** */
  1508.   /* ALERT: Synchronize by hand with garbage.encodechars */
  1509.   /* *************************************************** */
  1510.   /* nahrazujeme nepratelske znaky */
  1511.   // urldir=urldir.replace(':','_');
  1512.   // zde to neni nutne, neb muze byt jen v portu
  1513.   
  1514.   //  urldir=urldir.replace('*','@');
  1515.   //  urldir=urldir.replace('?','#');  
  1516.   // urldir=urldir.replace('~','-');
  1517.   
  1518.   // these two are not needed. Browsers sends < >
  1519.   // urldir=urldir.replace('>','}');  
  1520.   // urldir=urldir.replace('<','{');
  1521.   urldir=urldir.replace('|','!');
  1522.   
  1523.   result.append(urldir);
  1524.   return result.toString();
  1525. }
  1526.  
  1527. /* U T I L I T Y */
  1528.  
  1529. final static String[] addStringToArray(String what,String[] array)
  1530. {
  1531.  //if(what==null) return array;
  1532.  if(array==null) { array=new String[1];array[0]=what;return array;}
  1533.  String[] tmp;
  1534.  int ar=array.length;
  1535.  tmp=new String[ar+1];
  1536.  System.arraycopy(array,0,tmp,0,ar);
  1537.  tmp[ar]=what;
  1538.  return tmp;
  1539. }
  1540.  
  1541. final static String[] reverseStringArray(String[] what)
  1542. {
  1543.  String res[];
  1544.  if(what==null) return null;
  1545.  res=new String[what.length];
  1546.  for(int i=0;i<what.length;i++)
  1547.   res[what.length-1-i]=what[i];
  1548.  
  1549.  return res;
  1550. }
  1551.  
  1552. final static regexp[] reverseRegexpArray(regexp[] what)
  1553. {
  1554.  regexp res[];
  1555.  if(what==null) return null;
  1556.  res=new regexp[what.length];
  1557.  for(int i=0;i<what.length;i++)
  1558.   res[what.length-1-i]=what[i];
  1559.  
  1560.  return res;
  1561. }
  1562.  
  1563. final static regexp[] addRegexpToArray(String what,regexp[] array)
  1564. {
  1565.  if(what==null) return array;
  1566.  if(array==null) { array=new regexp[1];array[0]=new regexp(what,true);return array;}
  1567.  /* test zda tam uz nejsme */
  1568.  for(int i=0;i<array.length;i++)
  1569.   if(array[i].matches(what)) { System.err.println("[INFO] Rule \""+what+"\" ignored, already matched by \""+array[i]+"\"");return array;}
  1570.   
  1571.  regexp[] tmp;
  1572.  tmp=new regexp[array.length+1];
  1573.  System.arraycopy(array,0,tmp,0,array.length);
  1574.  tmp[array.length]=new regexp(what,!case_sensitive);
  1575.  return tmp;
  1576. }
  1577.  
  1578. final static boolean isInRegexpArray(String what,regexp[] array)
  1579. {
  1580.  if(array==null) return false;
  1581.  for(int i=0;i<array.length;i++)
  1582.   if(array[i].matches(what)) { return true;}
  1583.  return false;
  1584. }
  1585.  
  1586.  
  1587. final public static int [] incIntegerArraySize(int[] array)
  1588. {
  1589.  if(array==null) { array=new int[1];return array;}
  1590.  int[] tmp;
  1591.  tmp=new int[array.length+1];
  1592.  System.arraycopy(array,0,tmp,0,array.length);
  1593.  return tmp;
  1594. }
  1595.  
  1596. final public static long[] incLongArraySize(long[] array)
  1597. {
  1598.  if(array==null) { array=new long[1];return array;}
  1599.  long[] tmp;
  1600.  tmp=new long[array.length+1];
  1601.  System.arraycopy(array,0,tmp,0,array.length);
  1602.  return tmp;
  1603. }
  1604.  
  1605. final public static float[] incFloatArraySize(float[] array)
  1606. {
  1607.  if(array==null) { array=new float[1];return array;}
  1608.  float[] tmp;
  1609.  tmp=new float[array.length+1];
  1610.  System.arraycopy(array,0,tmp,0,array.length);
  1611.  return tmp;
  1612. }
  1613.  
  1614.  
  1615. /* SIMPLE WILD CARD REGEXP */
  1616.  
  1617. /* hvezdicka muze byt jen na konci retezce */
  1618. /* TODO: predelat na regionmatches */
  1619.  
  1620. final public static String simpleWildMatch(String mask, String test)
  1621. {
  1622.  String lastmatch;
  1623.  if(mask==null) return test;
  1624.  int i=mask.indexOf('*',0);
  1625.  if(i==-1) {
  1626.             if(test.equals(mask)) return test;
  1627.              else
  1628.                return null;
  1629.            }
  1630.  int tl=test.length();
  1631.  int ml=mask.length();          
  1632.  if(i!=ml-1) throw new IllegalArgumentException("* is not at end of string "+mask);
  1633.  //if(test.startsWith(mask.substring(0,ml-1)))
  1634.  
  1635.  if(test.regionMatches(0,mask,0,ml-1))
  1636.  
  1637.   if (tl>=ml) return test.substring(ml-1);
  1638.           else
  1639.               return "";
  1640.   
  1641.  return null;
  1642. }
  1643.  
  1644. final public void garbage_collection()
  1645. {
  1646.  System.out.println(new Date()+" running garbage collection");
  1647.  garbage g=new garbage(cache_dir);
  1648.  g.garbage_collection();
  1649.  System.out.println(new Date()+" operation ended");
  1650. }
  1651.  
  1652. final public void rebalance()
  1653. {
  1654.  System.out.println(new Date()+" rebalancing directories to "+swap_level1_dirs+"/"+swap_level2_dirs+" levels.");
  1655.  garbage g=new garbage(cache_dir);
  1656.  g.rebalance();
  1657.  System.out.println(new Date()+" operation ended");
  1658. }
  1659.  
  1660. final public void cacheimport(String d)
  1661. {
  1662.  repair.quiet=true;
  1663.  repair.nosave=true;
  1664.  repair.force=false;
  1665.  System.out.println(new Date()+" importing from cache on "+d);
  1666.  garbage g=new garbage(cache_dir);
  1667.  g.cacheimport(d);
  1668.  System.out.println(new Date()+" operation ended");
  1669. }
  1670.  
  1671. final public void cacheexport(String d,int type,long diff)
  1672. {
  1673.  repair.quiet=true;
  1674.  repair.nosave=true;
  1675.  repair.force=false;
  1676.  System.out.println(new Date()+" exporting cache to "+d);
  1677.  garbage g=new garbage(cache_dir);
  1678.  g.export(d,type,diff);
  1679.  System.out.println(new Date()+" operation ended");
  1680. }
  1681.  
  1682. final public void dirimport(String d)
  1683. {
  1684.  repair.quiet=true;
  1685.  repair.nosave=true;
  1686.  repair.force=false;
  1687.  System.out.println(new Date()+" importing "+d);
  1688.  garbage g=new garbage(cache_dir);
  1689.  g.dirimport(d);
  1690.  System.out.println(new Date()+" operation ended");
  1691. }
  1692. final public void fake_garbage_collection()
  1693. {
  1694.  System.out.println(new Date()+" [FAKE] running garbage collection.");
  1695.  garbage g=new garbage(cache_dir);
  1696.  g.fake_garbage_collection();
  1697.  System.out.println(new Date()+" [FAKE] garbage collection ended.");
  1698. }
  1699.  
  1700. final public void kill_unref()
  1701. {
  1702.  System.out.println(new Date()+" killing unreferenced files.");
  1703.  garbage g=new garbage(cache_dir);
  1704.  g.cleanup();
  1705.  System.out.println(new Date()+" unreferenced files removed.");
  1706. }
  1707.  
  1708. final public void converto020()
  1709. {
  1710.  System.out.println(new Date()+" converting cache control files to version 0.20");
  1711.  garbage g=new garbage(cache_dir);
  1712.  g.converto020();
  1713.  System.out.println(new Date()+" operation ended\nDO *** NOT *** RUN THIS OPERATION AGAIN OR YOUR DATA IN CACHE WILL BE DESTROYED!");
  1714. }
  1715.  
  1716. final public void converto030()
  1717. {
  1718.  System.out.println(new Date()+" converting cache control files to version 0.30.");
  1719.  garbage g=new garbage(cache_dir);
  1720.  g.converto030();
  1721.  System.out.println(new Date()+" operation ended.");
  1722. }
  1723.  
  1724.  
  1725. final static private boolean is_wild(String r)
  1726. {
  1727.  if(r.indexOf('*',0)==-1) return false;
  1728.   else
  1729.    return true;
  1730. }
  1731.  
  1732. final static private boolean checkFlag(String f)
  1733. {
  1734.  if(f==null) return false;
  1735.  File fl=new File(f);
  1736.  if(fl.canRead()) 
  1737.     {fl.delete();return true;}
  1738.  return false;
  1739. }
  1740.  
  1741. final static regexp[] parseRegexpFile(String fname,regexp fail[])
  1742. {
  1743.  try
  1744.  {
  1745.  String line,token;
  1746.  StringTokenizer st;
  1747.  if(! new File(fname).isAbsolute()) fname=scache.cfgdir+File.separator+fname;
  1748.   
  1749.  DataInputStream dis=new DataInputStream(new BufferedInputStream(new FileInputStream(fname))); 
  1750.  while ( (line = dis.readLine()) != null)
  1751.  {
  1752.       if(line.startsWith("#")) continue;
  1753.       st=new StringTokenizer(line);
  1754.       if(st.hasMoreTokens()==false) continue;
  1755.       token=st.nextToken();
  1756.       if(token.equalsIgnoreCase("fail")||token.equalsIgnoreCase("pass"))
  1757.        {
  1758.         System.out.println(new Date()+" [WARNING] Stop using Fail/Pass keyword in fail/pass file.");
  1759.         if(st.hasMoreTokens()==false) continue;
  1760.         token=st.nextToken();
  1761.        }
  1762.        if(token.indexOf('*')==-1) token+="*";
  1763.  
  1764.        fail=addRegexpToArray(token,fail);
  1765.  }
  1766.  dis.close();
  1767.  
  1768.  }
  1769.  catch (IOException ioe)
  1770.   {
  1771.    System.out.println(new Date()+" I/O Error reading file "+fname);
  1772.   }
  1773.  return fail;
  1774. }
  1775.  
  1776. /* load block c00kie */
  1777.  
  1778. final static String[] parseCookieFile(String fname,String fail[])
  1779. {
  1780.  try
  1781.  {
  1782.  String line,token;
  1783.  StringTokenizer st;
  1784.  if(! new File(fname).isAbsolute()) fname=scache.cfgdir+File.separator+fname;
  1785.  
  1786.  DataInputStream dis=new DataInputStream(new BufferedInputStream(new FileInputStream(fname))); 
  1787.  while ( (line = dis.readLine()) != null)
  1788.  {
  1789.       if(line.startsWith("#")) continue;
  1790.       st=new StringTokenizer(line);
  1791.       while(st.hasMoreTokens())
  1792.       {
  1793.         token=st.nextToken().toLowerCase();
  1794.         
  1795.         if(token.indexOf('*')>-1) 
  1796.          {
  1797.           System.out.println(new Date()+" [ERROR] Wildcards records are not supported in cookie_file");
  1798.           continue;
  1799.          } 
  1800.         else
  1801.          if(token.equalsIgnoreCase("all")) { return null;}
  1802.         fail=addStringToArray(token,fail);
  1803.         
  1804.       }
  1805.  }
  1806.  dis.close();
  1807.  
  1808.  }
  1809.  catch (IOException ioe)
  1810.   {
  1811.    System.out.println(new Date()+" I/O Error reading file "+fname);
  1812.   }
  1813.  return fail;
  1814. }
  1815.  
  1816. final static InetAddress[] addInetAdrToArray(InetAddress what,InetAddress[] array)
  1817. {
  1818.    if(array==null) { array=new InetAddress[1];array[0]=what;return array;}
  1819.    InetAddress[] tmp;
  1820.    int ar=array.length;
  1821.    tmp=new InetAddress[ar+1];
  1822.    System.arraycopy(array,0,tmp,0,ar);
  1823.    tmp[ar]=what;
  1824.    return tmp;
  1825. }
  1826.  
  1827. } /* class */
  1828.