import java.io.*;
import java.net.*;
import java.text.*;
import java.util.*;

class WebServer extends Thread {
  Socket mySocket;
  int counter;

  WebServer(String root, Socket i, int c) {
    mySocket=i;
    counter=c;
    myRoot=root;
  }

  public void run() {
    String cmd=null;
    String ccmd=null;
    String request=new String();
    BufferedReader pIn;

    try {      
      pIn=new BufferedReader(
        new InputStreamReader(mySocket.getInputStream()));    
      bOut=new BufferedOutputStream(mySocket.getOutputStream());
      pOut=new PrintStream(mySocket.getOutputStream(),true);
    }
    catch(Exception e) {
      System.out.println("fatal:"+e);
      return;
    }
    boolean done=false;
    int len=0;
    char c;
    int cols;

    while(!done) {
      String str=null;
      try {
        str=pIn.readLine();
      }
      catch(Exception e) {
        System.out.println(e);
        done=true;
      }

      if(str!=null)
        len=str.length();

      if(str==null) {
        System.out.println(counter+":Done - aaaaaagh");
        done=true;
      }
      // received two returns in row, close connection
      else if(len==0) { 
        if(ccmd.equals("GET ")) 
          handleGet(cmd,request);

        done=true;
      }
      // received GET ....
      else if(len>3 && str.substring(0,3).equals("GET")) {
        ccmd=new String("GET ");
        str=str.substring(4,str.length());
        cmd=str.substring(0,str.indexOf(' '));
System.out.println(counter+":GET "+cmd);
      }
      // received POST ....
      else if(len>4 && str.substring(0,4).equals("POST")) {
        ccmd=new String("POST ");
        str=str.substring(5,str.length());
        cmd=str.substring(0,str.indexOf(' '));
 //       System.out.println(counter+":POST "+cmd);
      }
      else {
        request=request+str+"\r\n";
//          System.out.println(counter+":"+str+":"+str.length());
      }
    }
    try {
      mySocket.close();
System.out.println("closing:"+counter);
    }
    catch(Exception e) {
      System.out.println(e);
    }
  }


  private void handleGet(String cmd, String request) {
    // find file type
    int period=cmd.lastIndexOf('.');
    String type=null;

    if(period>-1)
      type=cmd.substring(period);
    else if(cmd.equals("/") || cmd.equals("\\")) {
        cmd=cmd+"index.html";
        type=".html";
    }

    //cmd=cmd.replace('/','\\');

    File file=new File(myRoot+cmd);
    if(file.isFile()) {
      if(type.equals(".bat") || type.equals(".cgi")) {
        getCGI(myRoot+cmd);
      }
      else
        getFile(file,type);
    }
    else if(file.isDirectory()) {
      showError("Directories are not supported");
    }
    else 
      showError(myRoot+cmd+" is not found on this system");
  }

  private void getFile(File file, String type) {
System.out.println(file);
    Date date=new Date(file.lastModified());
    Date theDate=new Date();

    pOut.println("HTTP/1.0 200 OK");
    pOut.println("Server: JDN");
//    pOut.println("Date: Friday, 24-Oct-97 00:08:52 GMT");
//    pOut.println("Last-modified: Friday, 24-Oct-97 00:08:52 GMT");
    pOut.println("Date: "+theDate.toString());
    pOut.println("Last-modified: "+date.toString());
    pOut.println("Content-length: "+file.length());

    if(type.equals(".html") || type.equals(".htm"))
      pOut.println("Content-type: text/html");
    else if(type.equals(".class"))
      pOut.println("Content-type: text/plain");
    else if(type.equals(".jpeg") || type.equals(".jpg"))
      pOut.println("Content-type: image/pjpeg");
    else
      pOut.println("Content-type: text/plain");

    pOut.println();

    FileInputStream aInStream;
//    BufferedReader uin=null;

    try {   
      aInStream=new FileInputStream(file);
//      uin=new BufferedReader(
//          new InputStreamReader(aInStream));
    }
    catch(Exception e) {
      System.out.println(e);
      return;
    }

    byte []buf=new byte[512];

    try {
      int len;   
      while((len=aInStream.read(buf))>0) {

        bOut.write(buf,0,len);
      }
      bOut.flush();
      aInStream.close();
    }
    catch(Exception e) {
      System.out.println(e);
      try {
        aInStream.close();
      }
      catch(Exception ex) {
        System.out.println(ex);
      }
      return;
    }
  }


  private void getCGI(String cmd) {
    Runtime r=Runtime.getRuntime();
    Process p=null;
    BufferedReader dIn;


    try {
      p=r.exec(cmd);
      dIn=new BufferedReader(
          new InputStreamReader(p.getInputStream()));
    }
    catch(Exception e) {
      System.out.println(e);
      showError(e.toString());
      return;
    } 

    try {
      int len,retries=0;
      char []buf=new char[512];

      while(dIn.ready() || retries++<3) {
//        if(len>0) {
          pOut.println(dIn.readLine());
//          retries=0;
//        }
//        else {
//          sleep(1000);
//          System.out.println("sleeping");
//        }


/*         System.out.println(pIn.readLine());
            int len;
pOut.println("read output 1");
            for(int i=0;i<10;i++) {
              while(pIn.available()>0) {
pOut.println("write output");
                len=pIn.read(buf);
                bOut.write(buf,0,len);
System.out.println("read output");
              }
              sleep(1000);
            }
            bOut.flush();
*/
      }  // while

      pOut.println("Done.");
      System.out.println("done with output");
    }  //try
    catch(Exception e) {
      System.out.println(e);
      return;
    } 
  }

  private void showError(String message) {
    Date theDate=new Date();
    int length=1;

//    pOut.println("HTTP/1.0 404 Not Found");
    pOut.println("HTTP/1.0 200 OK");
    pOut.println("Server: JDN");
//    pOut.println("Date: Friday, 24-Oct-97 00:08:52 GMT");
//    pOut.println("Last-modified: Friday, 24-Oct-97 00:08:52 GMT");
    pOut.println("Date: "+theDate.toString());
    pOut.println("Last-modified: "+theDate.toString());
    pOut.println("Content-length: "+message.length()+length);
    pOut.println("Content-type: text/html");
    pOut.println();

    pOut.println(message);
  }


/*
  private void handlePost(String cmd, String request, 
       DataInputStream in) {
    try {      // Prepare connection
      URL myURL=new URL(cmd);
      String myFile=myURL.getFile();      
      String myCmd="POST "+myFile+" HTTP/1.0";
      int myPort=getPort(myURL.getPort(),myURL.getProtocol());

      Socket so=new Socket(myURL.getHost(),myPort);
      PrintWriter spOut=new PrintWriter(so.getOutputStream(),true);
//      BufferedOutputStream sbOut=
//        new BufferedOutputStream(so.getOutputStream());
      DataInputStream sIn=new DataInputStream(so.getInputStream());

      // send request
      spOut.println(myCmd);
      spOut.println(request);
//      spOut.println();

      // read message to post
      spOut.println(in.readLine());

      // read return data
      byte []buf=new byte[512];
      int len;
      while((len=sIn.read(buf))>0) {
//printBin(buf,len);
        bOut.write(buf,0,len);
      }
      bOut.flush();
    }
    catch(Exception e) {
      System.out.println(e);
    }
  }
*/


/*
  public void printBin(byte [] b, int len) {
    for(int i=0;i<len;i++) {
//      System.out.print(b[i]+" ");
      System.out.print((char)b[i]);
    }
    System.out.println();
  }
*/


/*
  void copyToStream(DataInputStream in, BufferedOutputStream out) {
      byte []buf=new byte[512];
      int len;
      while((len=in.read(buf))>0) {
        out.write(buf,0,len);
      }
      out.flush();
  }
*/


/*
  private int getPort(int port,String protocol) {
    if(port<0) {
      if(protocol.equals("http"))
        port=80;
      if(protocol.equals("ftp"))
        port=21;
      else
        port=80;
    }
    return port;
  }
*/


  public static int sToI(String s) {
    try {
      return Integer.valueOf(s).intValue();
    }
    catch(Exception e) {
      return 0;
    }
  }

  private PrintStream pOut;
  private BufferedOutputStream bOut;
  private String myRoot;


  public static void main(String[] args) {
    int port=80;
    String root=".";

    boolean bad=false;

    if(args.length>0) {
      port=sToI(args[0]);

      if(port==0)
        bad=true;
    }

    if(args.length>1) {
      root=args[1];
      File f=new File(root);

      if(!f.isDirectory())
        bad=true;
    }

    if(bad) {
      System.out.println("syntax:  java WebServer [port=80] [rootpath=.]");
      return;
    }

    int i=1;
    try {
      ServerSocket s=new ServerSocket(port);
      while(true) {
        Socket aSocket=s.accept();
        System.out.println("starting "+i);
        new WebServer(root,aSocket,i).start();
        i++;
      }
    }
    catch (Exception e) {
      System.out.println(e);
    }
  }
}

