Chris Pollett > Old Classes >
CS174

( Print View )

Grades: [Sec1]  [Sec2]

Submit: [Sec1]  [Sec2]

Course Info:
  [Texts & Links]
  [Topics]
  [Grading]
  [HW Info]
  [Exam Info]
  [Regrades]
  [Honesty]
  [Announcements]

HW Assignments:
  [Hw1]  [Hw2]  [Hw3]
  [Hw4]  [Hw5]

Practice Exams:
  [Mid1]  [Mid2]  [Final]

                            












HW5 Solutions Page

Return to homework page.

This solution was heavily modified from student DK's solution.
Good work DK!

<!-- test.html -->
<html>
  <head>
     <title>test.html</title>
  </head>
  <body>
    <p>test</p>
  </body>  
</html>

#!/usr/bin/perl 
#
# test.cgi
#
# This cgi-script can be used to output the CGI environment
# variables and also act as a counter of number of times it 
# has been accessed
#

$countFile = "counter.txt"; # file counter stored in
 
print <<HTML_BLOCK;
Content-type:text/html


 <html>
 <head>
   <title>Environment + Counter</title>
 </head>

 <body>
   <p><h3>Environment + Counter</h3></p>
   <table border="2">

HTML_BLOCK

foreach (sort keys %ENV) 
{
   print "    <tr><td> $_ </td><td> $ENV{$_}</td></tr> \n";
}

print "  </table> \n";


if(-e $countFile)
{
   open(FILE, $countFile) || die "Could not open count file\n";
   
   $count = <FILE>;

   close(FILE);
   $count++;
}
else
{
   $count = 1;
}

open(FILE, ">$countFile") || die "Could not write to count file";
print FILE "$count\n";
close(FILE);

print "  <p>You are visitor number: $count</p>";
print <<HTML_BLOCK;

<body>
</html>

HTML_BLOCK




/*
   MyServerProperties.txt
*/
port= 5000
host=localhost
public_html = /home/cpollett/Hw5/
cgi_bin = /home/cpollett/Hw5/

// MyWebServer.java -- a simplified web server that can do CGI
import java.io.*;
import java.util.*;
import java.net.*;
/**
    MyWebServer

    Java web server that serves text htmls and cgi pages

    It uses MyServerProperties.txt to read in a property data.
    The MyServerProperties file should be formatted in the 
    following way:

    for windows:

    port=80
    perl=w:/perl/bin/perl
    name=computer name
    publicHtml = w:/public_html/
    cgi_bin = w:/cgi-bin/

    for UNIX:

    port=80
    perl= /usr/bin/perl
    name=computer name
    publicHtml = /usr/wwwroot/
    cgi_bin = /usr/wwwroot/cgi-bin/

   @author DK (student) -- heavily modified by C. Pollett
   @version 1.0
*/
public class MyWebServer
{

   /**
      @return the port number
   */
   public static int getPort()
   {
      return port;
   }

   /**

      @return the public_html directory
   */
   public static String publicHtml()
   {
      return publicHtml;
   }

   /**
      @return the cgi_bin directory
   */
   public static String getCgiBin()
   {
      return cgi;
   }

   /**
      Creates a socket and then listens for users
   */
   public static void startWebServer()
   {
      try
      {

         //calls for the function to read in property file

         readConfig("MyServerProperties.txt");
         ServerSocket accept = new ServerSocket(port);

         System.out.println("Server ready to accept connections.");

         while(true) 
         {
            Socket s = accept.accept();

            //if someone there create a new thread

            ConnectionHandler handler = new ConnectionHandler(s);
            handler.start();
         }
      }
      catch (Exception e)
      {
         System.out.println(e.toString());
         System.exit(0);
      }
   }


   /**
      Reads in the Property file
      @param fileName -- the property file's name
   */
   public static void readConfig(String fileName)
   {
      System.out.println(
         "Attempting to read MyServerProperties.txt...");

      Properties properties = new Properties();

      try 
      {
         FileInputStream file = new FileInputStream(fileName);
         properties.load(file);
         file.close();
      }
      catch (IOException ie)
      {
         System.err.println("Error reading"+ 
            "MyServerProperties.txt configuration file ");
         System.err.println(ie.toString());
         System.exit(0);
      }

      port = Integer.parseInt(properties.getProperty("port"));
      publicHtml = properties.getProperty("public_html");

      cgi = properties.getProperty("cgi_bin");
      host= properties.getProperty("host");

      System.out.println("MyServerProperties.txt file read.");
   }

   public static void main(String[] args)
   {
      startWebServer();
   }

   public static String publicHtml ; //path to public_html
   public static String perl; //path to perl directory
   public static String cgi; //path to cgi-bin
   public static int port; //port number
   public static String host; //path to cgi-bin


}

/**
   ConnectionHandler class used to handle an
      individual request by a Thread
*/
class ConnectionHandler extends Thread
{

   /**
      Constructor -- sets the socket involved in this request

      @param s -- the socket
   */
   public ConnectionHandler(Socket s)
   {
      socket = s;
   }

   /**
      method that is executed by a thread to handle a single HTTP
      request
   */
   public void run()
   {
     try
     {
        String tmp;

        //input stream to get users requests
        BufferedReader socketInput = new BufferedReader(
           new InputStreamReader(socket.getInputStream()));
     
        //output stream to respond to users requests
        DataOutputStream socketOutput = 
           new DataOutputStream(socket.getOutputStream());

        //user Request  
        String userRequest = socketInput.readLine().toString();
        System.out.println("\nRequest:\n"+userRequest);

        tmp = socketInput.readLine().toString();
        System.out.println(tmp);
 
        String accept = tmp.substring(8);

        boolean flag=true;
        while(flag)
        {
           tmp=socketInput.readLine(); 
           System.out.println(tmp);
           if(tmp.equalsIgnoreCase("")) flag=false;
        }
        
        StringTokenizer token = new StringTokenizer(userRequest);
        String getRequest = token.nextToken();

        //FILENAME
        String fileName = token.nextToken();

        //HTTP protocol
        http = token.nextToken();

        //checks if the user input correct path

        if(!fileName.startsWith("/public_html")
           && !fileName.startsWith("/cgi-bin"))
        {
           printMessage("403", Err403, socketOutput);
        }
        // we only handle GET requests
        else if(getRequest.equals("GET"))
        {
           if(fileName.startsWith("/public_html"))
               sendHtml(http, fileName, socketOutput);
           
           else
              executeCgi (fileName, socketOutput, accept);
        }
        else
           printMessage("405", Err405, socketOutput);
        
       //all done socket closed
       socket.close();
     }
     catch(Exception e)
     {
       System.err.println(e.toString());
     } 
  }

  /**
     Sends page user requested

     @param http -- http protocol user uses
     @param fileName -- filename user wanted
     @param socketOutput -- DataOutputStream from socket
     @throws Exception - exception
  */
  public void sendHtml(String http, String fileName, 
     DataOutputStream socketOutput) throws Exception
  {
     String httpOutput="";
     String tmp;
   
     //if the file is html and exists display it, otherwise error

     if(fileName.endsWith(".html"))
     {
        BufferedReader in = new BufferedReader(
           new FileReader(MyWebServer.publicHtml() 
              + fileName.substring(12)));

        /* read the file line by line into a 
           string then send the string
        */

        while( (tmp = in.readLine())!= null)
           httpOutput+=tmp;

        printMessage("OK 200", httpOutput, socketOutput);

     }
     else
     {
        printMessage("415", Err415, socketOutput);
     }
   }

   /**
      executes a cgi script and displays the results

      @param fileName file name
      @param accept MIME serve accepts*
      @param socketOutput DataOutputStream
      @throws Exception exception
   */
   public void executeCgi(String fileName, 
      DataOutputStream socketOutput, String accept)
   {
      String  tmp, cgiOutput="";
      Runtime runTime = Runtime.getRuntime();
      String[] env = getEnvironment(fileName, accept);

      try
      {
 
         String cmd = MyWebServer.getCgiBin()
            + fileName.substring(9);

         Process p = runTime.exec(cmd, env);

         String processError="";

         //process input stream
         BufferedReader stdInput = 
            new BufferedReader(new InputStreamReader(
               p.getInputStream()));

         //process error stream
         BufferedReader stdError = 
            new BufferedReader(
               new InputStreamReader(p.getErrorStream()));

         //gets all the input stream, ie result of execution

         while ((tmp = stdInput.readLine()) != null)
            cgiOutput+=tmp+"\n";

         //gets all if any errors in the execution
         while ((tmp = stdError.readLine()) != null)
            processError+=tmp;

         if(processError.equalsIgnoreCase(""))
            printMessage("200 OK", cgiOutput, socketOutput, false);
         else
            printMessage("500", processError, socketOutput);
      }
      //catch for the top try
      catch (Exception e)
      {
         System.out.println(e.toString());
      }

  }

  /**
      Prints HTTP responses, outputs Content-type as text/html

      @param code response code      
      @param msg  response string
      @param socketOutput output
      @throws Exception exception
  */
  public void printMessage(String code, String msg, 
     DataOutputStream socketOutput) throws Exception
  {
     printMessage(code, msg, socketOutput, true);
  }

  /**
      Prints HTTP responses

      @param code response code      
      @param msg  response string
      @param socketOutput output
      @param outputType says whether we output the Content-type
         as text/html or not
      @throws Exception exception
  */
  public void printMessage(String code, String msg,  
     DataOutputStream socketOutput, boolean outputType) 
     throws Exception
  {
     socketOutput.writeBytes(http+" "+ code+"\n");
     System.out.println("\nResponse:\n"+http +" "+ code + "\n");

     socketOutput.writeBytes(
       "Server: My Server\n MIME - version: 1.0\n");

     System.out.println("Server: My Server\n MIME - version: 1.0\n");

     if(outputType)
     {
        socketOutput.writeBytes("Content-Type: text/html\n");
        System.out.println("Content-Type: text/html\n");

        socketOutput.writeBytes(
          "Content-length:"+ msg.length() + "\n\n");
        System.out.println(
          "Content-length:"+ msg.length() + "\n\n");

     }

     socketOutput.writeBytes(msg);
     System.out.println(msg);
     
     socketOutput.flush();
  }

   /**
      creates an array of cgi environment variables

      @param fileName - user requested filename
      @param accept -- connection type
      @return array on cgi environmental variables
   */
   public String[] getEnvironment(String fileName, String accept)
   {
      ArrayList env =  new ArrayList();
      String[] type = new String[1];
      String rname = socket.getInetAddress().toString();
      String hname =  socket.getLocalAddress().toString();

      int slash1 = rname.indexOf("/");
      int slash2 = hname.indexOf("/");
      int qmark = fileName.indexOf("?");
  
      if (qmark < 0 ) qmark = fileName.length();
   
      env.add("SERVER_SOFTWARE=Java Web server");
      env.add("SERVER_NAME=" + hname.substring(0, slash2));
      env.add("SERVER_PROTOCOL=" + http); 
      env.add("SERVER_PORT=" + MyWebServer.getPort());
      env.add("REQUEST_METHOD=GET"); 
         //request method is always get in this assignment
      env.add("SCRIPT_NAME=" + fileName.substring(0, qmark));
      if(qmark < fileName.length())
         env.add("QUERY_STRING=" + fileName.substring(qmark+1));
      else
         env.add("QUERY_STRING=");

      env.add("REMOTE_HOST=" + rname.substring(0, slash1)); 
         //host contains value from Host header
      env.add("REMOTE_ADDR=" +  rname.substring(slash1+1));
      env.add("HTTP_CONNECTION="  + accept.substring(3));

      return ( (String[]) env.toArray(type));
   }

   private Socket socket;
 
   //http protocol user requested, HTTP/1.0 or something else
   private String http = "";

   //HTTP error messages

   String Err403 = "<h2>ERROR 403 Forbidden </h2>";
   String Err404 = "<h2>ERROR 404 Page not found</h2>";

   String Err405 = "<h2>ERROR 405 Method not allowed </h2>";

   String Err410 = "<h2>ERROR 410 Page Permanently not available</h2>";

   String Err415 = "<h2>ERROR 415 Unsupported media type</h2>";

}