Пример #1
0
  /**
   * Close all IO connections that were opened during post()
   *
   * @param cs Client socket items to populate.
   */
  private static void cleanUp(ClientSocket cs) throws IOException {

    Debug.log(Debug.MSG_LIFECYCLE, "HTTPUtils: closing IO socket connections");

    if (cs.in != null) {
      try {
        cs.in.close();

        cs.in = null;
      } catch (Exception e) {
        Debug.log(Debug.ALL_WARNINGS, e.toString());
      }
    }

    if (cs.out != null) {
      try {
        cs.out.close();

        cs.out = null;
      } catch (Exception e) {
        Debug.log(Debug.ALL_WARNINGS, e.toString());
      }
    }

    if (cs.s != null) {
      try {
        cs.s.close();

        cs.s = null;
      } catch (Exception e) {
        Debug.log(Debug.ALL_WARNINGS, e.toString());
      }
    }
  }
Пример #2
0
  /**
   * POSTs the given content to the given URL.
   *
   * @param String the url to post to
   * @param content the body of the post
   * @param contentType the content-type of the request
   * @exception IOException if post fails
   */
  public static String post(String urlString, String contentType, String content)
      throws IOException {

    Debug.log(
        Debug.MSG_LIFECYCLE,
        "HTTPUtils: Trying to post " + content + " to web server at [ " + urlString + "]");

    StringBuffer responseBuffer = new StringBuffer();

    URL url = new URL(urlString);

    ClientSocket cs = new ClientSocket();

    HTTPUtils.Response resp = post(cs, url, new Hashtable(), contentType, content);

    while (true) {
      String line = resp.content.readLine();
      if (line == null) break;

      responseBuffer.append(line);
    }

    Debug.log(
        Debug.MSG_LIFECYCLE,
        "HTTPUtils: Obtained response from web server : " + responseBuffer.toString());

    cleanUp(cs);

    return responseBuffer.toString();
  }
  /**
   * Perform the actual version check by connecting to the version server.
   *
   * @param data_to_send version message
   * @return version reply
   * @throws Exception if the server check connection fails
   */
  private Map performVersionCheck(
      Map data_to_send, boolean use_az_message, boolean use_http, boolean v6) throws Exception {
    Exception error = null;
    Map reply = null;

    if (use_http) {

      try {
        reply = executeHTTP(data_to_send, v6);

        reply.put("protocol_used", "HTTP");

        error = null;
      } catch (IOException e) {
        error = e;
      } catch (Exception e) {
        Debug.printStackTrace(e);
        error = e;
      }
    }

    if (reply == null && use_az_message) {

      try {
        reply = executeAZMessage(data_to_send, v6);

        reply.put("protocol_used", "AZMSG");
      } catch (IOException e) {
        error = e;
      } catch (Exception e) {
        Debug.printStackTrace(e);
        error = e;
      }
    }
    if (error != null) {

      throw (error);
    }

    if (Logger.isEnabled())
      Logger.log(
          new LogEvent(
              LOGID,
              "VersionCheckClient server "
                  + "version check successful. Received "
                  + reply.size()
                  + " reply keys."));

    if (v6) {

      last_check_time_v6 = SystemTime.getCurrentTime();

    } else {

      last_check_time_v4 = SystemTime.getCurrentTime();
    }

    return reply;
  }
Пример #4
0
  public void actionPerformed(ActionEvent event) {
    if (Debug.isActive()) Debug.println("Action for Collapse Tree button");

    tree_view.collapseLevel();
    toolbar.getYaxisTreeCommitButton().doClick();

    // Set toolbar buttons to reflect status
    toolbar.resetYaxisTreeButtons();
  }
 protected void sendRequest(PrintWriter out, String[] msg) {
   for (int i = 0; i < msg.length; i++) {
     if (Debug.get(Debug.Communication)) {
       System.err.println(">>>" + msg[i]);
     }
     out.print(msg[i] + crlf);
   }
   if (Debug.get(Debug.Communication)) {
     System.err.println(">>>");
   }
   out.print(crlf);
   out.flush();
 }
Пример #6
0
 /** Opens this net scan. */
 public void open() throws DbException {
   try {
     if (socket == null) {
       Debug.println("NetScan accepting @ :" + port);
       socket = Utilities.accept(serverSocket);
       Debug.println("NetScan accepted, creating input stream...");
       in = new DataInputStream(socket.getInputStream());
       Debug.println("NetScan opened");
     }
   } catch (IOException ioe) {
     ioe.printStackTrace();
     closeConnection();
     throw new DbException(ioe);
   }
 }
Пример #7
0
  public void actionPerformed(ActionEvent event) {
    Window window;
    String msg;

    if (model.isZoomUndoStackEmpty()) {
      window = SwingUtilities.windowForComponent((JToolBar) toolbar);
      msg = "Zoom Undo Stack is empty";
      Dialogs.warn(window, msg);
    } else model.zoomUndo();

    // Set toolbar buttons to reflect status
    if (toolbar != null) toolbar.resetZoomButtons();

    if (Debug.isActive()) Debug.println("Action for Zoom Undo button.");
  }
Пример #8
0
  public SSLResult fingerprint() throws IOException, FingerprintError {

    SSLConfigCollector scc;

    scc = new SSLConfigCollector(host, port, si);
    scc.setCertValidator(cv);

    startDate = new Date();

    sslSupport = SSLResult.UNKNOWN;

    // If a delay is set, wait some time, except for
    // the first request
    if (!initial && (delay > 0)) {
      if (Debug.get(Debug.Delay)) {
        System.err.println("Delaying request.");
      }
      try {
        Thread.sleep(delay);
      } catch (InterruptedException e) {
        Thread.currentThread().interrupt();
      }
    }
    initial = false;

    try {
      scc.probe();
      sslSupport = SSLResult.SUPPORTED;
      sslSupportReason = null;
    } catch (NoSSLException e) {
      // This exception is thrown when the protocol support
      // for ssl is not available
      sslSupport = SSLResult.UNSUPPORTED;
      sslSupportReason = e.toString();
    } catch (FingerprintException e) {
      sslSupport = SSLResult.UNSUPPORTED;
      sslSupportReason = e.toString();
    } catch (IOException e) {
      sslSupport = SSLResult.UNKNOWN;
      sslSupportReason = e.toString();
    }
    endDate = new Date();

    protos = scc.getSupportedProtos();

    ProbeResult pres =
        new ProbeResult(
            host,
            port,
            startDate,
            endDate,
            sslSupport,
            sslSupportReason,
            scc.getServerCertificates(),
            scc.serverCertificateVerifies(),
            scc.serverCertNameMatch());

    pres.setProtosResult(protos);
    return pres;
  }
 public void setCredentials(String uid, String pass) {
   authID = uid;
   authPW = pass;
   if (Debug.get(Debug.SockInit)) {
     System.err.println("HttpProxySocketInitialiser: " + " uid " + authID + " pw " + authPW);
   }
 }
  public AuthenticatorWindow() {
    SESecurityManager.addPasswordListener(this);

    // System.out.println( "AuthenticatorWindow");

    Map cache = COConfigurationManager.getMapParameter(CONFIG_PARAM, new HashMap());

    try {
      Iterator it = cache.entrySet().iterator();

      while (it.hasNext()) {

        Map.Entry entry = (Map.Entry) it.next();

        String key = (String) entry.getKey();
        Map value = (Map) entry.getValue();

        String user = new String((byte[]) value.get("user"), "UTF-8");
        char[] pw = new String((byte[]) value.get("pw"), "UTF-8").toCharArray();

        auth_cache.put(key, new authCache(key, new PasswordAuthentication(user, pw), true));
      }

    } catch (Throwable e) {

      COConfigurationManager.setParameter(CONFIG_PARAM, new HashMap());

      Debug.printStackTrace(e);
    }
  }
  public static void main(String[] args) throws Exception {

    // parse arguments
    if (args.length != 3 || !args[1].equals("-config")) {
      usage();
    }

    // Determine type
    Type type = null;
    String software;
    if (args[0].equals("-w")) {
      type = Type.WELCOME;
      software = "TAISHI/WelcomeThreadServer";
    } else if (args[0].equals("-b")) {
      type = Type.BUSY;
      software = "TAISHI/BusyWaitServer";
    } else if (args[0].equals("-s")) {
      type = Type.SUSPENSION;
      software = "TAISHI/SuspensionServer";
    } else {
      software = "";
      usage();
    }

    // Reading configuration file
    String config_file = args[2];

    ReadConfig parse = new ReadConfig(config_file, software);
    HashMap<String, String> config_map = parse.getConfig();
    Debug.debug(config_map.toString());

    // check if config_map is valid
    // necessary to check the thread pool size is set
    if (config_map == null || !config_map.containsKey("ThreadPoolSize")) {
      throw new Exception("Incomplete configuration");
    }

    // create cache
    Debug.debug("Create cache with size: " + config_map.get("CacheSize"));
    ThreadSafeCache cache = new ThreadSafeCache(Integer.parseInt(config_map.get("CacheSize")));

    // create server
    ThreadPoolServer server = new ThreadPoolServer(type, config_map, cache);
    server.run();
  }
Пример #12
0
 private void closeConnection() {
   Debug.println("NetScan closing connection", 5);
   try {
     if (in != null) in.close();
     if (socket != null) socket.close();
     if (serverSocket != null) {
       serverSocket.close();
     }
   } catch (IOException ioe) {
     ioe.printStackTrace();
   }
 }
  public Set<String> getAutoInstallPluginIDs() {
    Set<String> result = new HashSet<String>();

    Map m = getMostRecentVersionCheckData();

    if (m != null) {

      byte[] x = (byte[]) m.get("autoinstall_pids");

      if (x != null) {

        String str = new String(x);

        String latest = COConfigurationManager.getStringParameter("vc.autoinstall_pids.latest", "");

        if (!str.equals(latest)) {

          byte[] sig = (byte[]) m.get("autoinstall_pids_sig");

          if (sig == null) {

            Debug.out("autoinstall plugins sig missing");

            return (result);
          }

          try {
            AEVerifier.verifyData(str, sig);

            COConfigurationManager.setParameter("vc.autoinstall_pids.latest", str);

          } catch (Throwable e) {

            return (result);
          }
        }

        String[] bits = str.split(",");

        for (String b : bits) {

          b = b.trim();

          if (b.length() > 0) {

            result.add(b);
          }
        }
      }
    }

    return (result);
  }
Пример #14
0
  protected String[] getAuthenticationDialog(final String realm, final String tracker) {
    final Display display = SWTThread.getInstance().getDisplay();

    if (display.isDisposed()) {

      return (null);
    }

    final AESemaphore sem = new AESemaphore("SWTAuth");

    final authDialog[] dialog = new authDialog[1];

    TOTorrent torrent = TorrentUtils.getTLSTorrent();

    final String torrent_name;

    if (torrent == null) {

      torrent_name = null;

    } else {

      torrent_name = TorrentUtils.getLocalisedName(torrent);
    }

    try {
      display.asyncExec(
          new AERunnable() {
            public void runSupport() {
              dialog[0] = new authDialog(sem, display, realm, tracker, torrent_name);
            }
          });
    } catch (Throwable e) {

      Debug.printStackTrace(e);

      return (null);
    }
    sem.reserve();

    String user = dialog[0].getUsername();
    String pw = dialog[0].getPassword();
    String persist = dialog[0].savePassword() ? "true" : "false";

    if (user == null) {

      return (null);
    }

    return (new String[] {user, pw == null ? "" : pw, persist});
  }
  public void addVersionCheckClientListener(
      boolean triggerStartListener, VersionCheckClientListener l) {
    synchronized (listeners) {
      listeners.add(l);

      if (triggerStartListener && startCheckRan) {
        try {
          l.versionCheckStarted(REASON_UPDATE_CHECK_START);
        } catch (Exception e) {
          Debug.out(e);
        }
      }
    }
  }
  protected void prepareAuthorisation(String authVal) throws FingerprintError {

    if (authVal == null) {
      throw new HttpProxyError("Authentication " + "challenge missing");
    }
    int idx = authVal.indexOf(' ');
    String scheme = authVal.substring(0, idx).toLowerCase();
    String param;
    if (authVal.length() > idx) {
      param = authVal.substring(idx + 1);
    } else {
      param = "";
    }
    if (!scheme.equals("basic")) {
      throw new HttpProxyError("Auth scheme '" + scheme + "' not supported");
    }
    if (Debug.get(Debug.SockInit)) {
      System.err.println("prepareAuthorisation: " + "using scheme " + scheme);
    }
    authenticator = "Basic " + Base64.encode(authID + ":" + authPW);
    if (Debug.get(Debug.SockInit)) {
      System.err.println("prepareAuthorisation: auth=" + authenticator);
    }
  }
  public boolean open(String addr, int port, String bindAddr) {
    try {
      ssdpMultiSock = new MulticastSocket(null);
      ssdpMultiSock.setReuseAddress(true);
      InetSocketAddress bindSockAddr = new InetSocketAddress(port);
      ssdpMultiSock.bind(bindSockAddr);
      ssdpMultiGroup = new InetSocketAddress(InetAddress.getByName(addr), port);
      ssdpMultiIf = NetworkInterface.getByInetAddress(InetAddress.getByName(bindAddr));
      ssdpMultiSock.joinGroup(ssdpMultiGroup, ssdpMultiIf);
    } catch (Exception e) {
      Debug.warning(e);
      return false;
    }

    return true;
  }
  /** Stop the server. */
  public void stop() {
    try {
      this_mon.enter();

      if (server_channel != null) {
        try {
          server_channel.close();
          server_channel = null;
        } catch (Throwable t) {
          Debug.out(t);
        }
      }
    } finally {

      this_mon.exit();
    }
  }
 public boolean send(String msg, String bindAddr, int bindPort) {
   try {
     MulticastSocket msock;
     if ((bindAddr) != null && (0 < bindPort)) {
       msock = new MulticastSocket(null);
       msock.bind(new InetSocketAddress(bindAddr, bindPort));
     } else msock = new MulticastSocket();
     DatagramPacket dgmPacket = new DatagramPacket(msg.getBytes(), msg.length(), ssdpMultiGroup);
     // Thnaks for Tho Beisch (11/09/04)
     msock.setTimeToLive(4);
     msock.send(dgmPacket);
     msock.close();
   } catch (Exception e) {
     Debug.warning(e);
     return false;
   }
   return true;
 }
 protected void accept_loop() {
   while (isRunning()) {
     try {
       SocketChannel client_channel = server_channel.accept();
       last_accept_time = SystemTime.getCurrentTime();
       client_channel.configureBlocking(false);
       listener.newConnectionAccepted(server_channel, client_channel);
     } catch (AsynchronousCloseException e) {
       /* is thrown when stop() is called */
     } catch (Throwable t) {
       Debug.out(t);
       try {
         Thread.sleep(500);
       } catch (Exception e) {
         e.printStackTrace();
       }
     }
   }
 }
  /** Start the server and begin accepting incoming connections. */
  public void start() {
    try {
      this_mon.enter();

      if (!isRunning()) {
        try {
          server_channel = ServerSocketChannel.open();

          server_channel.socket().setReuseAddress(true);
          if (receive_buffer_size > 0)
            server_channel.socket().setReceiveBufferSize(receive_buffer_size);

          server_channel.socket().bind(bind_address, 1024);

          if (Logger.isEnabled())
            Logger.log(new LogEvent(LOGID, "TCP incoming server socket " + bind_address));

          AEThread accept_thread =
              new AEThread("VServerSelector:port" + bind_address.getPort()) {
                public void runSupport() {
                  accept_loop();
                }
              };
          accept_thread.setDaemon(true);
          accept_thread.start();
        } catch (Throwable t) {
          Debug.out(t);
          Logger.log(
              new LogAlert(
                  LogAlert.UNREPEATABLE,
                  "ERROR, unable to bind TCP incoming server socket to " + bind_address.getPort(),
                  t));
        }

        last_accept_time = SystemTime.getCurrentTime(); // init to now
      }
    } finally {

      this_mon.exit();
    }
  }
  public ThreadPoolServer(Type type, HashMap<String, String> config_map, ThreadSafeCache cache)
      throws Exception {
    try {
      this.concurrent_type = type;
      this.config_map = config_map;
      this.cache = cache;

      // making welcome socket
      int port = Integer.parseInt(config_map.get("port"));
      welcomeSocket = new ServerSocket(port);

      this.thread_count = Integer.parseInt(config_map.get("ThreadPoolSize"));
      System.out.println(
          "Starting the server with thread pool size of "
              + thread_count
              + " and listening at: "
              + welcomeSocket);
    } catch (Exception e) {
      Debug.debug(e.getMessage());
      throw new Exception("ThreadPool Server initial construction failed.");
    }
  }
  protected void saveAuthCache() {
    try {
      this_mon.enter();

      HashMap map = new HashMap();

      Iterator it = auth_cache.values().iterator();

      while (it.hasNext()) {

        authCache value = (authCache) it.next();

        if (value.isPersistent()) {

          try {
            HashMap entry_map = new HashMap();

            entry_map.put("user", value.getAuth().getUserName().getBytes("UTF-8"));
            entry_map.put("pw", new String(value.getAuth().getPassword()).getBytes("UTF-8"));

            map.put(value.getKey(), entry_map);

          } catch (Throwable e) {

            Debug.printStackTrace(e);
          }
        }
      }

      COConfigurationManager.setParameter(CONFIG_PARAM, map);

    } finally {

      this_mon.exit();
    }
  }
 // Run using thread pool competing on welcome socket
 private void run_welcome(WServiceThread[] threads) throws InterruptedException {
   for (int i = 0; i < threads.length; i++) {
     threads[i].join();
   }
   Debug.debug("All threads finished. Exit");
 }
  public void runSupport() {
    byte[] input_buffer = new byte[request_dg.getLength()];

    System.arraycopy(request_dg.getData(), 0, input_buffer, 0, input_buffer.length);

    int packet_data_length = input_buffer.length;

    String auth_user = null;
    byte[] auth_user_bytes = null;
    byte[] auth_hash = null;

    if (server.isTrackerPasswordEnabled()) {

      // auth detail should be attached to the packet. Auth details are 16
      // bytes

      if (input_buffer.length < 17) {

        Logger.log(
            new LogEvent(
                LOGID,
                LogEvent.LT_WARNING,
                "TRTrackerServerProcessorUDP: " + "packet received but authorisation missing"));

        return;
      }

      packet_data_length -= 16;

      auth_user_bytes = new byte[8];

      auth_hash = new byte[8];

      System.arraycopy(input_buffer, packet_data_length, auth_user_bytes, 0, 8);

      int user_len = 0;

      while (user_len < 8 && auth_user_bytes[user_len] != 0) {

        user_len++;
      }

      auth_user = new String(auth_user_bytes, 0, user_len);

      System.arraycopy(input_buffer, packet_data_length + 8, auth_hash, 0, 8);
    }

    DataInputStream is =
        new DataInputStream(new ByteArrayInputStream(input_buffer, 0, packet_data_length));

    try {
      String client_ip_address = request_dg.getAddress().getHostAddress();

      PRUDPPacketRequest request = PRUDPPacketRequest.deserialiseRequest(null, is);

      Logger.log(
          new LogEvent(
              LOGID, "TRTrackerServerProcessorUDP: packet received: " + request.getString()));

      PRUDPPacket reply = null;
      TRTrackerServerTorrentImpl torrent = null;

      if (auth_user_bytes != null) {

        // user name is irrelevant as we only have one at the moment

        // <parg_home> so <new_packet> = <old_packet> + <user_padded_to_8_bytes> + <hash>
        // <parg_home> where <hash> = first 8 bytes of sha1(<old_packet> + <user_padded_to_8> +
        // sha1(pass))
        // <XTF> Yes

        byte[] sha1_pw = null;

        if (server.hasExternalAuthorisation()) {

          try {
            URL resource = new URL("udp://" + server.getHost() + ":" + server.getPort() + "/");

            sha1_pw = server.performExternalAuthorisation(resource, auth_user);

          } catch (MalformedURLException e) {

            Debug.printStackTrace(e);
          }

          if (sha1_pw == null) {

            Logger.log(
                new LogEvent(
                    LOGID,
                    LogEvent.LT_ERROR,
                    "TRTrackerServerProcessorUDP: auth fails for user '" + auth_user + "'"));

            reply = new PRUDPPacketReplyError(request.getTransactionId(), "Access Denied");
          }
        } else {

          sha1_pw = server.getPassword();
        }

        // if we haven't already failed then check the PW

        if (reply == null) {

          SHA1Hasher hasher = new SHA1Hasher();

          hasher.update(input_buffer, 0, packet_data_length);
          hasher.update(auth_user_bytes);
          hasher.update(sha1_pw);

          byte[] digest = hasher.getDigest();

          for (int i = 0; i < auth_hash.length; i++) {

            if (auth_hash[i] != digest[i]) {

              Logger.log(
                  new LogEvent(
                      LOGID,
                      LogEvent.LT_ERROR,
                      "TRTrackerServerProcessorUDP: auth fails for user '" + auth_user + "'"));

              reply = new PRUDPPacketReplyError(request.getTransactionId(), "Access Denied");

              break;
            }
          }
        }
      }

      int request_type = TRTrackerServerRequest.RT_UNKNOWN;

      if (reply == null) {

        if (server.isEnabled()) {

          try {
            int type = request.getAction();

            if (type == PRUDPPacketTracker.ACT_REQUEST_CONNECT) {

              reply = handleConnect(client_ip_address, request);

            } else if (type == PRUDPPacketTracker.ACT_REQUEST_ANNOUNCE) {

              Object[] x =
                  handleAnnounceAndScrape(
                      client_ip_address, request, TRTrackerServerRequest.RT_ANNOUNCE);

              if (x == null) {

                throw (new Exception("Connection ID mismatch"));
              }

              reply = (PRUDPPacket) x[0];
              torrent = (TRTrackerServerTorrentImpl) x[1];

              request_type = TRTrackerServerRequest.RT_ANNOUNCE;

            } else if (type == PRUDPPacketTracker.ACT_REQUEST_SCRAPE) {

              Object[] x =
                  handleAnnounceAndScrape(
                      client_ip_address, request, TRTrackerServerRequest.RT_SCRAPE);

              if (x == null) {

                throw (new Exception("Connection ID mismatch"));
              }

              reply = (PRUDPPacket) x[0];
              torrent = (TRTrackerServerTorrentImpl) x[1];

              request_type = TRTrackerServerRequest.RT_SCRAPE;

            } else {

              reply = new PRUDPPacketReplyError(request.getTransactionId(), "unsupported action");
            }
          } catch (Throwable e) {

            // e.printStackTrace();

            String error = e.getMessage();

            if (error == null) {

              error = e.toString();
            }

            reply = new PRUDPPacketReplyError(request.getTransactionId(), error);
          }
        } else {

          System.out.println("UDP Tracker: replying 'disabled' to " + client_ip_address);

          reply = new PRUDPPacketReplyError(request.getTransactionId(), "UDP Tracker disabled");
        }
      }

      if (reply != null) {

        InetAddress address = request_dg.getAddress();

        ByteArrayOutputStream baos = new ByteArrayOutputStream();

        DataOutputStream os = new DataOutputStream(baos);

        reply.serialise(os);

        byte[] output_buffer = baos.toByteArray();

        DatagramPacket reply_packet =
            new DatagramPacket(output_buffer, output_buffer.length, address, request_dg.getPort());

        socket.send(reply_packet);

        server.updateStats(request_type, torrent, input_buffer.length, output_buffer.length);
      }

    } catch (Throwable e) {

      Logger.log(new LogEvent(LOGID, "TRTrackerServerProcessorUDP: processing fails", e));
    } finally {

      try {
        is.close();

      } catch (Throwable e) {

      }
    }
  }
Пример #26
0
  /**
   * POST something to the given URL. The headers are put in as HTTP headers, the content length is
   * calculated and the content is sent as content. Duh.
   *
   * @param cs Client socket items.
   * @param url the url to post to
   * @param headers additional headers to send as HTTP headers
   * @param contentType type of the content
   * @param content the body of the post
   * @exception IOException if post fails
   */
  private static Response post(
      ClientSocket cs, URL url, Hashtable headers, String contentType, String content)
      throws IOException {

    // If the port is not specified in the URL, use the default http port.
    int port = url.getPort();
    if (port == -1) port = 80;

    cs.s = new Socket(url.getHost(), +port);
    cs.out = new PrintWriter(cs.s.getOutputStream());
    cs.in = new BufferedReader(new InputStreamReader(cs.s.getInputStream()));

    // Create the HTTP header
    cs.out.print(HTTP_POST + " " + url.getFile() + " HTTP/" + HTTP_VERSION + "\r\n");
    cs.out.print(HEADER_HOST + ": " + url.getHost() + ':' + port + "\r\n");
    cs.out.print(HEADER_CONTENT_TYPE + ": " + contentType + "\r\n");
    cs.out.print(HEADER_CONTENT_LENGTH + ": " + content.length() + "\r\n");

    for (Enumeration e = headers.keys(); e.hasMoreElements(); ) {
      Object key = e.nextElement();
      cs.out.print(key + ": " + headers.get(key) + "\r\n");
    }

    // According to HTTP1.1 need another CRLF after the header
    cs.out.print("\r\n");

    Debug.log(Debug.MSG_LIFECYCLE, "HTTPUtils: Writing content to the socket... " + content);

    cs.out.println(content);

    cs.out.flush();

    /* read the status line */
    int statusCode = 0;
    String statusString = null;
    StringTokenizer st = new StringTokenizer(cs.in.readLine());
    st.nextToken(); // ignore version part
    statusCode = Integer.parseInt(st.nextToken());

    StringBuffer sb = new StringBuffer();

    while (st.hasMoreTokens()) {
      sb.append(st.nextToken());
      if (st.hasMoreTokens()) sb.append(" ");
    }

    statusString = sb.toString();

    /* get the headers */
    Hashtable respHeaders = new Hashtable();
    int respContentLength = -1;
    String respContentType = null;
    String line = null;

    while ((line = cs.in.readLine()) != null) {

      if (line.length() == 0) break;

      int colonIndex = line.indexOf(':');
      String fieldName = line.substring(0, colonIndex);
      String fieldValue = line.substring(colonIndex + 1).trim();

      if (fieldName.equals(HEADER_CONTENT_LENGTH)) respContentLength = Integer.parseInt(fieldValue);
      else if (fieldName.equals(HEADER_CONTENT_TYPE)) respContentType = fieldValue;
      else respHeaders.put(fieldName, fieldValue);
    }

    Response response =
        new Response(
            statusCode, statusString, respHeaders, respContentLength, respContentType, cs.in);

    return response;
  }
  public Socket createSocket(String host, int port)
      throws IOException, FingerprintException, FingerprintError {

    Socket s = new Socket();
    s.connect(new InetSocketAddress(proxyHost, proxyPort), 1000 * timeout);

    PrintWriter out = new PrintWriter(s.getOutputStream());
    InputStreamReader isr = new InputStreamReader(s.getInputStream());
    BufferedReader in = new BufferedReader(isr);

    String[] connHdr = {
      "CONNECT " + host + ":" + port + " HTTP/1.1",
      "Host: " + host + ":" + port,
      "Proxy-Connection: close"
    };

    String[] connReq = null;

    if (authRequired) {
      connReq = new String[connHdr.length + 1];
      for (int i = 0; i < connHdr.length; i++) {
        connReq[i] = connHdr[i];
      }
      connReq[connHdr.length] = "Proxy-Authorization: " + authenticator;
    } else {
      connReq = new String[connHdr.length];
      for (int i = 0; i < connHdr.length; i++) {
        connReq[i] = connHdr[i];
      }
    }
    sendRequest(out, connReq);

    HttpResponseHeader hdr = new HttpResponseHeader(in);
    int status = hdr.getStatusCode();

    if (Debug.get(Debug.Communication)) {
      System.err.println("Got status " + status);
    }

    /* Now check the status code and act upon it */
    if ((status / 100) == 2) { // Code is 2xx
      return s;
    }

    if (((status / 100) == 4) && (status != 407)) {
      throw new HttpProxyError("Proxy request failed");
    }

    if ((status == 407) && authRequired) {
      /* We already sent authorisation info,
       * but the proxy did not accept it.
       * So we can only stop here, as
       * we do not have the right credentials
       * at hand.
       */
      throw new HttpProxyError("Cannot authenticate " + "to proxy, wrong " + "credentials?");
    }
    if (status == 407) {
      if (Debug.get(Debug.SockInit)) {
        System.err.println("Preparing proxy " + "authenticator for " + hdr.getProxyAuthInfo());
      }
      prepareAuthorisation(hdr.getProxyAuthInfo());
      authRequired = true;
      return createSocket(host, port);
    }
    return s;
  }
  public PasswordAuthentication getAuthentication(
      String realm, String protocol, String host, int port) {
    try {
      this_mon.enter();

      String tracker = protocol + "://" + host + ":" + port + "/";

      InetAddress bind_ip = NetworkAdmin.getSingleton().getSingleHomedServiceBindAddress();

      String self_addr;

      // System.out.println( "auth req for " + realm + " - " + tracker );

      if (bind_ip == null || bind_ip.isAnyLocalAddress()) {

        self_addr = "127.0.0.1";

      } else {

        self_addr = bind_ip.getHostAddress();
      }

      // when the tracker is connected to internally we don't want to prompt
      // for the password. Here we return a special user and the password hash
      // which is picked up in the tracker auth code - search for "<internal>"!

      // also include the tracker IP as well as for scrapes these can occur on
      // a raw torrent which hasn't been modified to point to localhost

      if (host.equals(self_addr)
          || host.equals(COConfigurationManager.getStringParameter("Tracker IP", ""))) {

        try {
          byte[] pw = COConfigurationManager.getByteParameter("Tracker Password", new byte[0]);

          String str_pw = new String(Base64.encode(pw));

          return (new PasswordAuthentication("<internal>", str_pw.toCharArray()));

        } catch (Throwable e) {

          Debug.printStackTrace(e);
        }
      }

      String auth_key = realm + ":" + tracker;

      authCache cache = (authCache) auth_cache.get(auth_key);

      if (cache != null) {

        PasswordAuthentication auth = cache.getAuth();

        if (auth != null) {

          return (auth);
        }
      }

      String[] res = getAuthenticationDialog(realm, tracker);

      if (res == null) {

        return (null);

      } else {

        PasswordAuthentication auth = new PasswordAuthentication(res[0], res[1].toCharArray());

        boolean save_pw = res[2].equals("true");

        boolean old_entry_existed =
            auth_cache.put(auth_key, new authCache(auth_key, auth, save_pw)) != null;

        if (save_pw || old_entry_existed) {

          saveAuthCache();
        }

        return (auth);
      }
    } finally {

      this_mon.exit();
    }
  }
  protected String[] getAuthenticationDialog(final String realm, final String location) {
    final Display display = SWTThread.getInstance().getDisplay();

    if (display.isDisposed()) {

      return (null);
    }

    final AESemaphore sem = new AESemaphore("SWTAuth");

    final authDialog[] dialog = new authDialog[1];

    TOTorrent torrent = TorrentUtils.getTLSTorrent();

    final boolean is_tracker;
    final String details;

    if (torrent == null) {

      is_tracker = false;

      details = TorrentUtils.getTLSDescription();

    } else {

      details = TorrentUtils.getLocalisedName(torrent);
      is_tracker = true;
    }

    try {
      if (display.getThread() == Thread.currentThread()) {

        dialog[0] = new authDialog(sem, display, realm, is_tracker, location, details);

        while (!(display.isDisposed() || sem.isReleasedForever())) {

          if (!display.readAndDispatch()) {

            display.sleep();
          }
        }

        if (display.isDisposed()) {

          return (null);
        }
      } else {

        display.asyncExec(
            new AERunnable() {
              public void runSupport() {
                dialog[0] = new authDialog(sem, display, realm, is_tracker, location, details);
              }
            });
      }
    } catch (Throwable e) {

      Debug.printStackTrace(e);

      return (null);
    }

    sem.reserve();

    String user = dialog[0].getUsername();
    String pw = dialog[0].getPassword();
    String persist = dialog[0].savePassword() ? "true" : "false";

    if (user == null) {

      return (null);
    }

    return (new String[] {user, pw == null ? "" : pw, persist});
  }
    protected authDialog(
        AESemaphore _sem,
        Display display,
        String realm,
        boolean is_tracker,
        String target,
        String details) {
      sem = _sem;

      if (display.isDisposed()) {

        sem.releaseForever();

        return;
      }

      final String ignore_key = "IgnoreAuth:" + realm + ":" + target + ":" + details;

      if (RememberedDecisionsManager.getRememberedDecision(ignore_key) == 1) {

        Debug.out(
            "Authentication for "
                + realm
                + "/"
                + target
                + "/"
                + details
                + " ignored as told not to ask again");

        sem.releaseForever();

        return;
      }

      shell = ShellFactory.createMainShell(SWT.DIALOG_TRIM | SWT.APPLICATION_MODAL);

      Utils.setShellIcon(shell);
      Messages.setLanguageText(shell, "authenticator.title");

      GridLayout layout = new GridLayout();
      layout.numColumns = 3;

      shell.setLayout(layout);

      GridData gridData;

      // realm

      Label realm_label = new Label(shell, SWT.NULL);
      Messages.setLanguageText(realm_label, "authenticator.realm");
      gridData = new GridData(GridData.FILL_BOTH);
      gridData.horizontalSpan = 1;
      realm_label.setLayoutData(gridData);

      Label realm_value = new Label(shell, SWT.NULL);
      realm_value.setText(realm.replaceAll("&", "&&"));
      gridData = new GridData(GridData.FILL_BOTH);
      gridData.horizontalSpan = 2;
      realm_value.setLayoutData(gridData);

      // target

      Label target_label = new Label(shell, SWT.NULL);
      Messages.setLanguageText(
          target_label, is_tracker ? "authenticator.tracker" : "authenticator.location");
      gridData = new GridData(GridData.FILL_BOTH);
      gridData.horizontalSpan = 1;
      target_label.setLayoutData(gridData);

      Label target_value = new Label(shell, SWT.NULL);
      target_value.setText(target.replaceAll("&", "&&"));
      gridData = new GridData(GridData.FILL_BOTH);
      gridData.horizontalSpan = 2;
      target_value.setLayoutData(gridData);

      if (details != null) {

        Label details_label = new Label(shell, SWT.NULL);
        Messages.setLanguageText(
            details_label, is_tracker ? "authenticator.torrent" : "authenticator.details");
        gridData = new GridData(GridData.FILL_BOTH);
        gridData.horizontalSpan = 1;
        details_label.setLayoutData(gridData);

        Label details_value = new Label(shell, SWT.NULL);
        details_value.setText(details.replaceAll("&", "&&"));
        gridData = new GridData(GridData.FILL_BOTH);
        gridData.horizontalSpan = 2;
        details_value.setLayoutData(gridData);
      }
      // user

      Label user_label = new Label(shell, SWT.NULL);
      Messages.setLanguageText(user_label, "authenticator.user");
      gridData = new GridData(GridData.FILL_BOTH);
      gridData.horizontalSpan = 1;
      user_label.setLayoutData(gridData);

      final Text user_value = new Text(shell, SWT.BORDER);
      user_value.setText("");
      gridData = new GridData(GridData.FILL_BOTH);
      gridData.horizontalSpan = 2;
      user_value.setLayoutData(gridData);

      user_value.addListener(
          SWT.Modify,
          new Listener() {
            public void handleEvent(Event event) {
              username = user_value.getText();
            }
          });

      // password

      Label password_label = new Label(shell, SWT.NULL);
      Messages.setLanguageText(password_label, "authenticator.password");
      gridData = new GridData(GridData.FILL_BOTH);
      gridData.horizontalSpan = 1;
      password_label.setLayoutData(gridData);

      final Text password_value = new Text(shell, SWT.BORDER);
      password_value.setEchoChar('*');
      password_value.setText("");
      gridData = new GridData(GridData.FILL_BOTH);
      gridData.horizontalSpan = 2;
      password_value.setLayoutData(gridData);

      password_value.addListener(
          SWT.Modify,
          new Listener() {
            public void handleEvent(Event event) {
              password = password_value.getText();
            }
          });

      // persist

      Label blank_label = new Label(shell, SWT.NULL);
      gridData = new GridData(GridData.FILL_BOTH);
      gridData.horizontalSpan = 1;
      blank_label.setLayoutData(gridData);

      final Button checkBox = new Button(shell, SWT.CHECK);
      checkBox.setText(MessageText.getString("authenticator.savepassword"));
      gridData = new GridData(GridData.FILL_BOTH);
      gridData.horizontalSpan = 1;
      checkBox.setLayoutData(gridData);
      checkBox.addListener(
          SWT.Selection,
          new Listener() {
            public void handleEvent(Event e) {
              persist = checkBox.getSelection();
            }
          });

      final Button dontAsk = new Button(shell, SWT.CHECK);
      dontAsk.setText(MessageText.getString("general.dont.ask.again"));
      gridData = new GridData(GridData.FILL_BOTH);
      gridData.horizontalSpan = 1;
      dontAsk.setLayoutData(gridData);
      dontAsk.addListener(
          SWT.Selection,
          new Listener() {
            public void handleEvent(Event e) {
              RememberedDecisionsManager.setRemembered(ignore_key, dontAsk.getSelection() ? 1 : 0);
            }
          });

      // line

      Label labelSeparator = new Label(shell, SWT.SEPARATOR | SWT.HORIZONTAL);
      gridData = new GridData(GridData.FILL_HORIZONTAL);
      gridData.horizontalSpan = 3;
      labelSeparator.setLayoutData(gridData);

      // buttons

      new Label(shell, SWT.NULL);

      Button bOk = new Button(shell, SWT.PUSH);
      Messages.setLanguageText(bOk, "Button.ok");
      gridData =
          new GridData(
              GridData.FILL_HORIZONTAL
                  | GridData.HORIZONTAL_ALIGN_END
                  | GridData.HORIZONTAL_ALIGN_FILL);
      gridData.grabExcessHorizontalSpace = true;
      gridData.widthHint = 70;
      bOk.setLayoutData(gridData);
      bOk.addListener(
          SWT.Selection,
          new Listener() {
            public void handleEvent(Event e) {
              close(true);
            }
          });

      Button bCancel = new Button(shell, SWT.PUSH);
      Messages.setLanguageText(bCancel, "Button.cancel");
      gridData = new GridData(GridData.HORIZONTAL_ALIGN_END);
      gridData.grabExcessHorizontalSpace = false;
      gridData.widthHint = 70;
      bCancel.setLayoutData(gridData);
      bCancel.addListener(
          SWT.Selection,
          new Listener() {
            public void handleEvent(Event e) {
              close(false);
            }
          });

      shell.setDefaultButton(bOk);

      shell.addListener(
          SWT.Traverse,
          new Listener() {
            public void handleEvent(Event e) {
              if (e.character == SWT.ESC) {
                close(false);
              }
            }
          });

      shell.pack();

      Utils.centreWindow(shell);

      shell.open();
    }