/**
   * Handler for the actual HTTP request
   *
   * @exception IOException
   */
  public int read(byte[] a) throws IOException {
    statuscode = connection.SC_OK;
    if (ssl) return super.read(a);
    boolean cookies_enabled = server.enableCookiesByDefault();
    String rq = "";
    header_length = 0;
    post_data_len = 0;
    content_len = 0;
    boolean start_line = true;
    buf = getLine(); // reads the first line

    while (lread > 2) {
      if (start_line) {
        start_line = false;
        int methodID = server.getHttpMethod(buf);
        switch (methodID) {
          case -1:
            statuscode = connection.SC_NOT_SUPPORTED;
            break;
          case 2:
            ssl = true;
          default:
            InetAddress host = parseRequest(buf, methodID);
            if (statuscode != connection.SC_OK) break; // error occured, go on with the next line

            if (!server.use_proxy && !ssl) {
              /* creates a new request without the hostname */
              buf = method + " " + url + " " + server.getHttpVersion() + "\r\n";
              lread = buf.length();
            }
            if ((server.use_proxy && connection.notConnected()) || !host.equals(remote_host)) {
              if (server.debug) server.writeLog("read_f: STATE_CONNECT_TO_NEW_HOST");
              statuscode = connection.SC_CONNECTING_TO_HOST;
              remote_host = host;
            }
            /*
             * ------------------------- url blocking (only "GET"
             * method) -------------------------
             */
            if (server.block_urls && methodID == 0 && statuscode != connection.SC_FILE_REQUEST) {
              if (server.debug) System.out.println("Searching match...");
              Jhttpp2URLMatch match = server.findMatch(this.remote_host_name + url);
              if (match != null) {
                if (server.debug) System.out.println("Match found!");
                cookies_enabled = match.getCookiesEnabled();
                if (match.getActionIndex() == -1) break;
                OnURLAction action =
                    (OnURLAction) server.getURLActions().elementAt(match.getActionIndex());
                if (action.onAccesssDeny()) {
                  statuscode = connection.SC_URL_BLOCKED;
                  if (action.onAccessDenyWithCustomText())
                    errordescription = action.getCustomErrorText();
                } else if (action.onAccessRedirect()) {
                  statuscode = connection.SC_MOVED_PERMANENTLY;
                  errordescription = action.newLocation();
                }
              } // end if match!=null)
            } // end if (server.block...
        } // end switch
      } // end if(startline)
      else {
        /*-----------------------------------------------
         * Content-Length parsing
         *-----------------------------------------------*/
        if (server.startsWith(buf.toUpperCase(), "CONTENT-LENGTH")) {
          String clen = buf.substring(16);
          if (clen.indexOf("\r") != -1) clen = clen.substring(0, clen.indexOf("\r"));
          else if (clen.indexOf("\n") != -1) clen = clen.substring(0, clen.indexOf("\n"));
          try {
            content_len = Integer.parseInt(clen);
          } catch (NumberFormatException e) {
            statuscode = connection.SC_CLIENT_ERROR;
          }
          if (server.debug) server.writeLog("read_f: content_len: " + content_len);
          if (!ssl) body = true; // Note: in HTTP/1.1 any method can have a
          // body, not only "POST"
        } else if (server.startsWith(buf, "Proxy-Connection:")) {
          if (!server.use_proxy) buf = null;
          else {
            buf = "Proxy-Connection: Keep-Alive\r\n";
            lread = buf.length();
          }
        }
        /*
         * else if (server.startsWith(buf,"Connection:")) { if
         * (!server.use_proxy) { buf="Connection: Keep-Alive\r\n"; //use
         * always keep-alive lread=buf.length(); } else buf=null; }
         */
        /*-----------------------------------------------
         * cookie crunch section
         *-----------------------------------------------*/
        else if (server.startsWith(buf, "Cookie:")) {
          if (!cookies_enabled) buf = null;
        }
        /*------------------------------------------------
         * Http-Header filtering section
         *------------------------------------------------*/
        else if (server.filter_http) {
          if (server.startsWith(buf, "Referer:")) { // removes
            // "Referer"
            buf = null;
          } else if (server.startsWith(buf, "User-Agent")) // changes
          // User-Agent
          {
            buf = "User-Agent: " + server.getUserAgent() + "\r\n";
            lread = buf.length();
          }
        }
      }
      if (buf != null) {
        rq += buf;
        if (server.debug) server.writeLog(buf);
        header_length += lread;
      }
      buf = getLine();
    }
    rq += buf; // adds last line (should be an empty line) to the header
    // String
    header_length += lread;

    if (header_length == 0) {
      if (server.debug)
        server.writeLog("header_length=0, setting status to SC_CONNECTION_CLOSED (buggy request)");
      statuscode = connection.SC_CONNECTION_CLOSED;
    }

    for (int i = 0; i < header_length; i++) a[i] = (byte) rq.charAt(i);

    if (body) { // read the body, if "Content-Length" given
      post_data_len = 0;
      while (post_data_len < content_len) {
        a[header_length + post_data_len] = (byte) read(); // writes data
        // into the
        // array
        post_data_len++;
      }
      header_length += content_len; // add the body-length to the
      // header-length
      body = false;
    }

    return (statuscode == connection.SC_OK) ? header_length : -1; // return
    // -1
    // with
    // an
    // error
  }
 /**
  * Parser for the first (!) line from the HTTP request<br>
  * Sets up the URL, method and remote hostname.
  *
  * @return an InetAddress for the hostname, null on errors with a statuscode!=SC_OK
  */
 public InetAddress parseRequest(String a, int method_index) {
   if (server.debug) server.writeLog(a);
   String f;
   int pos;
   url = "";
   if (ssl) {
     f = a.substring(8);
   } else {
     method = a.substring(0, a.indexOf(" ")); // first word in the line
     pos = a.indexOf(":"); // locate first :
     if (pos == -1) { // occours with "GET / HTTP/1.1"
       url = a.substring(a.indexOf(" ") + 1, a.lastIndexOf(" "));
       if (method_index == 0) { // method_index==0 --> GET
         if (url.indexOf(server.WEB_CONFIG_FILE) != -1) statuscode = connection.SC_CONFIG_RQ;
         else statuscode = connection.SC_FILE_REQUEST;
       } else {
         if (method_index == 1 && url.indexOf(server.WEB_CONFIG_FILE) != -1) { // allow
           // "POST"
           // for
           // admin
           // log
           // in
           statuscode = connection.SC_CONFIG_RQ;
         } else {
           statuscode = connection.SC_INTERNAL_SERVER_ERROR;
           errordescription =
               "This WWW proxy supports only the \"GET\" method while acting as webserver.";
         }
       }
       return null;
     }
     f = a.substring(pos + 3); // removes "http://"
   }
   pos = f.indexOf(" "); // locate space, should be the space before
   // "HTTP/1.1"
   if (pos == -1) { // buggy request
     statuscode = connection.SC_CLIENT_ERROR;
     errordescription = "Your browser sent an invalid request: \"" + a + "\"";
     return null;
   }
   f = f.substring(0, pos); // removes all after space
   // if the url contains a space... it's not our mistake...(url's must
   // never contain a space character)
   pos = f.indexOf("/"); // locate the first slash
   if (pos != -1) {
     url = f.substring(pos); // saves path without hostname
     f = f.substring(0, pos); // reduce string to the hostname
   } else url = "/"; // occurs with this request:
   // "GET http://localhost HTTP/1.1"
   pos = f.indexOf(":"); // check for the portnumber
   if (pos != -1) {
     String l_port = f.substring(pos + 1);
     l_port = l_port.indexOf(" ") != -1 ? l_port.substring(0, l_port.indexOf(" ")) : l_port;
     int i_port = 80;
     try {
       i_port = Integer.parseInt(l_port);
     } catch (NumberFormatException e_get_host) {
       server.writeLog("get_Host :" + e_get_host + " !!!!");
     }
     f = f.substring(0, pos);
     remote_port = i_port;
   } else remote_port = 80;
   remote_host_name = f;
   InetAddress address = null;
   if (server.log_access)
     server.logAccess(
         connection.getLocalSocket().getInetAddress().getHostAddress()
             + " "
             + method
             + " "
             + getFullURL());
   try {
     address = InetAddress.getByName(f);
     if (remote_port == server.port && address.equals(InetAddress.getLocalHost())) {
       if (url.indexOf(server.WEB_CONFIG_FILE) != -1 && (method_index == 0 || method_index == 1))
         statuscode = connection.SC_CONFIG_RQ;
       else if (method_index > 0) {
         statuscode = connection.SC_INTERNAL_SERVER_ERROR;
         errordescription =
             "This WWW proxy supports only the \"GET\" method while acting as webserver.";
       } else statuscode = connection.SC_FILE_REQUEST;
     }
   } catch (UnknownHostException e_u_host) {
     if (!server.use_proxy) statuscode = connection.SC_HOST_NOT_FOUND;
   }
   return address;
 }