/**
   * 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
  }