home *** CD-ROM | disk | FTP | other *** search
/ PC World 2001 April / PCWorld_2001-04_cd.bin / Software / TemaCD / smartcache / src / httpreq.java < prev    next >
Text File  |  2001-01-26  |  10KB  |  342 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.net.*;
  24. import java.text.*;
  25. import java.util.*;
  26.  
  27.  
  28. /* bugs */
  29. /* nepodporuje multi-line hlavicky. Pouziva to vubec nekdo? */
  30. /* turn off cache file je neefektivni (neodstranuje lf ze seznamu) */
  31.  
  32. public final class httpreq implements Runnable
  33. {
  34.  
  35. public static InetAddress allowed[];
  36.  
  37. public static final int REQUEST_GET=1;
  38. public static final int REQUEST_POST=2;
  39. public static final int REQUEST_HEAD=3;
  40. public static final int REQUEST_OPTIONS=4;
  41. public static final int REQUEST_PUT=5;
  42. public static final int REQUEST_DELETE=6;
  43. public static final int REQUEST_TRACE=7;
  44. public static final int REQUEST_CONNECT=8;
  45. public static final int REQUEST_MIN=REQUEST_GET;
  46. public static final int REQUEST_MAX=REQUEST_CONNECT;
  47. public static mgr mgr;
  48. public static String visible_hostname;
  49. public static String visible_link;
  50. public static int client_timeout;
  51.  
  52. public static DateFormat formatter= new SimpleDateFormat("dd/MMM/yyyy:HH:mm:ss", Locale.US);
  53. public static String timezone;
  54.  
  55. /* access.log */
  56. public static String logpatterns[];
  57. public static DataOutputStream logfilez[];
  58. public static String logfilenames[];
  59.  
  60.    private Socket socket = null;
  61.  
  62.     httpreq(Socket socket) {
  63.         this.socket=socket;
  64.     }
  65.         
  66. final public static String methodToString(int method)
  67. {
  68.  switch(method)
  69.  {
  70.  case REQUEST_GET:
  71.          return "GET";
  72.  case REQUEST_POST:
  73.          return "POST";
  74.  case REQUEST_HEAD:
  75.          return "HEAD";
  76.  case REQUEST_PUT:
  77.          return "PUT";
  78.  case REQUEST_OPTIONS:
  79.          return "OPTIONS";
  80.  case REQUEST_DELETE:
  81.          return "DELETE";
  82.  case REQUEST_CONNECT:
  83.          return "CONNECT";
  84.  case REQUEST_TRACE:
  85.          return "TRACE";
  86.  default:
  87.          return "UNKNOWN";
  88.  }
  89. }
  90.  
  91.  final public void run() {
  92.     boolean http10=true;
  93.     try { DataInputStream in=new DataInputStream (new BufferedInputStream(socket.getInputStream()));
  94.          DataOutputStream ou=new DataOutputStream(new BufferedOutputStream(socket.getOutputStream()));
  95.          
  96.     /* precteme radku GET / */
  97.     
  98.     socket.setSoTimeout(client_timeout);
  99.     
  100.     String req=in.readLine();
  101.     if(req==null) { socket.close();ou.close();return;}
  102.     String req2=null;
  103.     if(allowed!=null) {
  104.        InetAddress adr;
  105.        adr=socket.getInetAddress();
  106.        int j=allowed.length;
  107.        boolean Block=true;
  108.  
  109.        for(int i=0;i<j;i++) {
  110.           if (adr.equals(allowed[i])) Block=false;
  111.           }
  112.        if (Block) 
  113.           server_error(http10,403,"Cache access denied.",ou);
  114.        }
  115.     int req_method=0;
  116.     Vector headers=new Vector();
  117.    
  118.     if (req.indexOf(" HTTP/",0)==-1) http10=false;
  119.                                      
  120.     StringTokenizer st=new StringTokenizer(req);
  121.     try{
  122.     req2=st.nextToken();
  123.     
  124.     if(req2.equals("GET")) req_method=REQUEST_GET;
  125.     else
  126.     if(req2.equals("POST")) req_method=REQUEST_POST;
  127.     else
  128.     if(req2.equals("HEAD")) req_method=REQUEST_HEAD;
  129.     else
  130.     if(req2.equals("OPTIONS")) req_method=REQUEST_OPTIONS;
  131.     else
  132.     if(req2.equals("PUT")) req_method=REQUEST_PUT;
  133.     else
  134.     if(req2.equals("TRACE")) req_method=REQUEST_TRACE;
  135.     else
  136.     if(req2.equals("DELETE")) req_method=REQUEST_DELETE;
  137.     else
  138.     if(req2.equals("CONNECT")) req_method=REQUEST_CONNECT;
  139.     else
  140.      server_error(http10,501,"Method "+req2+" not implemented.",ou);
  141.     
  142.     req2=st.nextToken();
  143.     }
  144.     catch (NoSuchElementException e) { server_error(http10,400,"Incomplete request",ou);}
  145.         
  146.     /* HTTP 1.0+ - musime precist zbytek volovin az do prazdne radky */    
  147.     
  148.     if(http10)  while(true)
  149.                    { req=in.readLine();
  150.                      if(req==null) break;
  151.                      if(req.length()==0) break;
  152.                      headers.addElement(req);
  153.                     }
  154.                     
  155.      /* zaciname zpracovavat requesty */
  156.      request rq;
  157.      try{
  158.      if (http10) rq=new request(req_method,req2,headers,in,ou);
  159.        else
  160.         rq=new request(req_method,req2,null,in,ou);
  161.          
  162.      /* zalogovat do access.logu */
  163.      if(logpatterns!=null)
  164.       {
  165.        int j=logpatterns.length;
  166.        String urlcache=rq.getURL();
  167.        for(int i=0;i<j;i++)
  168.         {
  169.         String fragment;
  170.         fragment=mgr.simpleWildMatch(logpatterns[i], urlcache);
  171.         if(fragment==null) continue;
  172.         DataOutputStream outfile;
  173.         outfile=logfilez[i];
  174.           
  175.            if(outfile==null && logfilenames[i]!=null)
  176.            /* OPEN LOGFILE */
  177.             if(!open_logfile(logfilenames,logfilez,i)) break;
  178.              else
  179.               outfile=logfilez[i];
  180.             
  181.           /* ZAHAJUJEME LOGOVANI ! */  
  182.           InetAddress adr;
  183.           adr=socket.getInetAddress();
  184.           // DataOutputStream log;
  185.           StringBuffer sb=new StringBuffer(90);
  186.           
  187.           sb.append(adr.getHostAddress());
  188.           // log.writeBytes(adr.getHostAddress());
  189.           sb.append(" - - [");
  190.           sb.append(formatter.format(new Date()));
  191.           sb.append(timezone);
  192.       sb.append(methodToString(req_method));
  193.       sb.append(" ");
  194.           if(logpatterns[i]==null) sb.append(fragment+"\" 200 -\n");
  195.              else
  196.             sb.append("/"+fragment+"\" 200 -\n");
  197.           synchronized (outfile)
  198.           {
  199.         try
  200.         {
  201.               outfile.writeBytes(sb.toString());
  202.         }
  203.         catch (IOException errr) { logfilez[i]=null; }
  204.           }
  205.           
  206.           // log.flush();
  207.        } /* log for */
  208.       }/* log enabled? */
  209.      try
  210.       {
  211.         mgr.process_request(rq);
  212.       }
  213.       catch (EOFException DONE) {}
  214.       catch (IOException transfer_error)
  215.       { 
  216.          // System.out.println("[debug] I/O error when serving "+rq.getURL());
  217.          socket.setSoLinger(true,10*1000);
  218.      throw transfer_error;
  219.       }
  220.      } /* main loop try */
  221.      catch(MalformedURLException e2) { server_error(http10,400,"Invalid URL syntax",ou);}
  222.      }
  223.      catch (IOException main_transfer_error) {}
  224.      finally {
  225.               /* zkusime zavrit hlavni socket */
  226.               try {
  227.                 /*
  228.                 try
  229.             {
  230.                      socket.setSoTimeout(0);
  231.             }catch (IOException ignoreit) {}
  232.             */
  233.                     socket.close();
  234.           }
  235.           catch (IOException jejda) {}
  236.          };
  237.      return;
  238.     }
  239.  
  240. final public static void server_error(boolean http10,int errorrc,String msg,
  241.  DataOutputStream ou) throws IOException
  242.  {
  243.    StringBuffer sb=new StringBuffer(1024);
  244.    if(http10) { 
  245.                 sb.append("HTTP/1.0 ");
  246.         sb.append(errorrc);
  247.         sb.append(" ERROR\r\nContent-type: text/html\r\nLast-Modified: ");
  248.         String ted=request.printDate(new Date());
  249.         sb.append(ted);
  250.                 sb.append("\r\nDate: ");
  251.         sb.append(ted);
  252.         sb.append("\r\nExpires: ");
  253.         sb.append(request.printDate(new Date( new Date().getTime()+5*60*1000L )));
  254.         sb.append("\r\nServer: ");
  255.         sb.append(scache.VERSION);
  256.         sb.append("\r\nConnection: close\r\nProxy-Connection: close\r\n\r\n");
  257.               }
  258.    sb.append("<!DOCTYPE HTML PUBLIC \"-//IETF//DTD HTML 2.0//EN\">\r\n<HTML><HEAD><TITLE>Error</TITLE></HEAD>\n<BODY><h2>");
  259.    sb.append(errorrc);
  260.    sb.append(" ");
  261.    sb.append(msg);
  262.    sb.append("</h2>\r\n<hr noshade size=1>\r\nGenerated by ");
  263.    sb.append(visible_hostname);
  264.    sb.append(" (");
  265.    if(visible_link!=null) 
  266.     {
  267.       sb.append("<a href=\"");
  268.       sb.append(visible_link);
  269.       sb.append("\">");
  270.     }
  271.    sb.append(scache.VERSION);
  272.    if(visible_link!=null)
  273.    {
  274.      sb.append("</a>");
  275.    }
  276.    sb.append(")\r\n</BODY></HTML>\r\n");
  277.     
  278.    ou.writeBytes(sb.toString());
  279.    ou.close();
  280.    throw new EOFException("Request processing canceled");
  281. }
  282.  
  283. /* pokusi se otevrit protokolacni soubor */
  284.  
  285. public final static boolean 
  286.   open_logfile(String xlogfilenames[], DataOutputStream xlogfilez[], int i)
  287. {
  288.            /* OPEN LOGFILE */
  289.             {
  290.              try{
  291.                DataOutputStream dos;
  292.                dos=new DataOutputStream(new BufferedOutputStream(
  293.                new FileOutputStream(xlogfilenames[i],true),4096));
  294.                xlogfilez[i]=dos;
  295.              }
  296.              catch (IOException e1)
  297.               {
  298.                System.err.println("Problem creating logfile "+xlogfilenames[i]+" - turning it off");
  299.                xlogfilenames[i]=null;
  300.                return false;
  301.               }
  302.             } /* logfile open */
  303.   return true;
  304. }
  305.  
  306. public final static void flush(DataOutputStream xlogfilez[])
  307. {
  308.  
  309.  if(xlogfilez!=null)
  310.    for(int z=0;z<xlogfilez.length;z++)
  311.    {
  312.      if(xlogfilez[z]!=null)
  313.        try{
  314.         xlogfilez[z].flush();
  315.        }
  316.        catch(IOException e)
  317.        {}
  318.    }
  319. }
  320.  
  321.  
  322. public final static void close(DataOutputStream xlogfilez[])
  323. {
  324.  
  325.  if(xlogfilez!=null)
  326.    for(int z=0;z<xlogfilez.length;z++)
  327.    {
  328.      if(xlogfilez[z]!=null)
  329.        try{
  330.         xlogfilez[z].close();
  331.        }
  332.        catch(IOException e)
  333.        {}
  334.        finally
  335.        {
  336.         xlogfilez[z]=null;
  337.        }
  338.    }
  339. }
  340.  
  341. } /* class */
  342.