public boolean equals(Object obj) {
    if (this == obj) {

      return true;
    }

    if (obj instanceof TorrentDownloaderImpl) {

      TorrentDownloaderImpl other = (TorrentDownloaderImpl) obj;

      if (other.getURL().equals(this.url.toString())) {

        File other_file = other.getFile();
        File this_file = file;

        if (other_file == this_file) {

          return (true);
        }

        if (other_file == null || this_file == null) {

          return (false);
        }

        return (other_file.getAbsolutePath().equals(this_file.getAbsolutePath()));

      } else {

        return false;
      }
    } else {
      return false;
    }
  }
  protected static long getTorrentDataSizeFromFileOrDirSupport(File file) {
    String name = file.getName();

    if (name.equals(".") || name.equals("..")) {

      return (0);
    }

    if (!file.exists()) {

      return (0);
    }

    if (file.isFile()) {

      return (file.length());

    } else {

      File[] dir_files = file.listFiles();

      long length = 0;

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

        length += getTorrentDataSizeFromFileOrDirSupport(dir_files[i]);
      }

      return (length);
    }
  }
  protected TOTorrentCreateImpl(
      File _torrent_base, URL _announce_url, boolean _add_other_hashes, long _piece_length)
      throws TOTorrentException {
    super(_torrent_base.getName(), _announce_url, _torrent_base.isFile());

    torrent_base = _torrent_base;
    piece_length = _piece_length;
    add_other_hashes = _add_other_hashes;
  }
    private void save() {
      File file = getCacheFile();

      file.getParentFile().mkdirs();

      System.out.println("Writing cache: " + file);

      FileUtil.writeResilientFile(file, contents);

      dirty = false;
    }
  private void loadExportedParameters() {
    synchronized (exported_parameters) {
      try {
        File parent_dir = new File(SystemProperties.getUserPath());

        File props = new File(parent_dir, "exported_params.properties");

        if (props.exists()) {

          LineNumberReader lnr =
              new LineNumberReader(new InputStreamReader(new FileInputStream(props), "UTF-8"));

          try {
            while (true) {

              String line = lnr.readLine();

              if (line == null) {

                break;
              }

              String[] bits = line.split("=");

              if (bits.length == 2) {

                String key = bits[0].trim();
                String value = bits[1].trim();

                if (key.length() > 0 && value.length() > 0) {

                  imported_parameters.put(key, value);
                }
              }
            }
          } finally {

            lnr.close();
          }
        }
      } catch (Throwable e) {

        e.printStackTrace();
      }
    }

    COConfigurationManager.setIntDefault("instance.port", Constants.INSTANCE_PORT);

    registerExportedParameter("instance.port", "instance.port");
  }
  public String getDirectoryParameter(String parameter) throws IOException {
    String dir = getStringParameter(parameter);

    if (dir.length() > 0) {
      File temp = new File(dir);
      if (!temp.exists()) {
        FileUtil.mkdirs(temp);
      }
      if (!temp.isDirectory()) {
        throw new IOException("Configuration error. This is not a directory: " + dir);
      }
    }

    return dir;
  }
    private Map<String, List<Long>> getContents() {
      if (contents == null) {

        File file = getCacheFile();

        if (file.exists()) {

          System.out.println("Reading cache: " + file);

          contents = FileUtil.readResilientFile(file);

        } else {

          contents = new HashMap<String, List<Long>>();
        }
      }

      return (contents);
    }
  protected TOTorrentCreateImpl(
      File _torrent_base,
      URL _announce_url,
      boolean _add_other_hashes,
      long _piece_min_size,
      long _piece_max_size,
      long _piece_num_lower,
      long _piece_num_upper)
      throws TOTorrentException {
    super(_torrent_base.getName(), _announce_url, _torrent_base.isFile());

    torrent_base = _torrent_base;
    add_other_hashes = _add_other_hashes;

    long total_size = calculateTotalFileSize(_torrent_base);

    piece_length =
        getComputedPieceSize(
            total_size, _piece_min_size, _piece_max_size, _piece_num_lower, _piece_num_upper);
  }
  protected long getTotalFileSizeSupport(File file) throws TOTorrentException {

    String name = file.getName();

    /////////////////////////////////////////

    /////////////////////////////////////

    if (name.equals(".") || name.equals("..")) {

      return (0);
    }

    if (!file.exists()) {

      throw (new TOTorrentException(
          "TOTorrentCreate: file '" + file.getName() + "' doesn't exist",
          TOTorrentException.RT_FILE_NOT_FOUND));
    }

    if (file.isFile()) {

      if (!ignoreFile(name)) {

        total_file_count++;

        return (file.length());

      } else {

        return (0);
      }
    } else {

      File[] dir_files = file.listFiles();

      if (dir_files == null) {

        throw (new TOTorrentException(
            "TOTorrentCreate: directory '"
                + file.getAbsolutePath()
                + "' returned error when listing files in it",
            TOTorrentException.RT_FILE_NOT_FOUND));
      }

      long length = 0;

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

        length += getTotalFileSizeSupport(dir_files[i]);
      }

      return (length);
    }
  }
  public long[] getTotalUsageInPeriod(Date start_date, Date end_date) {
    synchronized (this) {
      long[] result = new long[STAT_ENTRY_COUNT];

      long start_millis = start_date.getTime();
      long end_millis = end_date.getTime();

      long now = SystemTime.getCurrentTime();

      long now_day = (now / DAY_IN_MILLIS) * DAY_IN_MILLIS;

      if (end_millis > now) {

        end_millis = now;
      }

      long start_day = (start_millis / DAY_IN_MILLIS) * DAY_IN_MILLIS;
      long end_day = (end_millis / DAY_IN_MILLIS) * DAY_IN_MILLIS;

      if (start_day > end_day) {

        return (result);
      }

      long start_offset = start_millis - start_day;

      start_offset = start_offset / MIN_IN_MILLIS;

      boolean offset_cachable = start_offset % 60 == 0;

      System.out.println(
          "start="
              + debug_utc_format.format(start_date)
              + ", end="
              + debug_utc_format.format(end_date)
              + ", offset="
              + start_offset);

      MonthCache month_cache = null;

      for (long this_day = start_day; this_day <= end_day; this_day += DAY_IN_MILLIS) {

        String[] bits = utc_date_format.format(new Date(this_day)).split(",");

        String year_str = bits[0];
        String month_str = bits[1];
        String day_str = bits[2];

        int year = Integer.parseInt(year_str);
        int month = Integer.parseInt(month_str);
        int day = Integer.parseInt(day_str);

        if (month_cache == null || !month_cache.isForMonth(year_str, month_str)) {

          if (month_cache != null && month_cache.isDirty()) {

            month_cache.save();
          }

          month_cache = getMonthCache(year_str, month_str);
        }

        boolean can_cache =
            this_day != now_day
                && (this_day > start_day || (this_day == start_day && offset_cachable))
                && this_day < end_day;

        long cache_offset = this_day == start_day ? start_offset : 0;

        if (can_cache) {

          long[] cached_totals = month_cache.getTotals(day, cache_offset);

          if (cached_totals != null) {

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

              result[i] += cached_totals[i];
            }

            continue;
          }
        } else {

          if (this_day == now_day) {

            if (day_cache != null) {

              if (day_cache.isForDay(year_str, month_str, day_str)) {

                long[] cached_totals = day_cache.getTotals(cache_offset);

                if (cached_totals != null) {

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

                    result[i] += cached_totals[i];
                  }

                  continue;
                }

              } else {

                day_cache = null;
              }
            }
          }
        }

        String current_rel_file =
            bits[0] + File.separator + bits[1] + File.separator + bits[2] + ".dat";

        File stats_file = new File(stats_dir, current_rel_file);

        if (!stats_file.exists()) {

          if (can_cache) {

            month_cache.setTotals(day, cache_offset, new long[0]);
          }
        } else {

          LineNumberReader lnr = null;

          try {
            System.out.println("Reading " + stats_file);

            lnr = new LineNumberReader(new FileReader(stats_file));

            long file_start_time = 0;

            long[] file_totals = null;

            long[] file_result_totals = new long[STAT_ENTRY_COUNT];

            long[] session_start_stats = null;
            long session_start_time = 0;
            long session_time = 0;

            while (true) {

              String line = lnr.readLine();

              if (line == null) {

                break;
              }

              // System.out.println( line );

              String[] fields = line.split(",");

              if (fields.length < 6) {

                continue;
              }

              String first_field = fields[0];

              if (first_field.equals("s")) {

                session_start_time = Long.parseLong(fields[2]) * MIN_IN_MILLIS;

                if (file_totals == null) {

                  file_totals = new long[STAT_ENTRY_COUNT];

                  file_start_time = session_start_time;
                }

                session_time = session_start_time;

                session_start_stats = new long[STAT_ENTRY_COUNT];

                for (int i = 3; i < 9; i++) {

                  session_start_stats[i - 3] = Long.parseLong(fields[i]);
                }
              } else if (session_start_time > 0) {

                session_time += MIN_IN_MILLIS;

                int field_offset = 0;

                if (first_field.equals("e")) {

                  field_offset = 3;
                }

                long[] line_stats = new long[STAT_ENTRY_COUNT];

                for (int i = 0; i < 6; i++) {

                  line_stats[i] = Long.parseLong(fields[i + field_offset]);

                  file_totals[i] += line_stats[i];
                }

                if (session_time >= start_millis && session_time <= end_millis) {

                  for (int i = 0; i < 6; i++) {

                    result[i] += line_stats[i];

                    file_result_totals[i] += line_stats[i];
                  }
                }

                // System.out.println( getString( line_stats ));
              }
            }

            System.out.println(
                "File total: start="
                    + debug_utc_format.format(file_start_time)
                    + ", end="
                    + debug_utc_format.format(session_time)
                    + " - "
                    + getString(file_totals));

            if (can_cache) {

              month_cache.setTotals(day, cache_offset, file_result_totals);

              if (cache_offset != 0) {

                month_cache.setTotals(day, 0, file_totals);
              }
            } else {

              if (this_day == now_day) {

                if (day_cache == null) {

                  System.out.println("Creating day cache");

                  day_cache = new DayCache(year_str, month_str, day_str);
                }

                day_cache.setTotals(cache_offset, file_result_totals);

                if (cache_offset != 0) {

                  day_cache.setTotals(0, file_totals);
                }
              }
            }

          } catch (Throwable e) {

            Debug.out(e);

          } finally {

            if (lnr != null) {

              try {
                lnr.close();

              } catch (Throwable e) {
              }
            }
          }
        }
      }

      if (month_cache != null && month_cache.isDirty()) {

        month_cache.save();
      }

      System.out.println("    -> " + getString(result));

      return (result);
    }
  }
  private void write(int record_type, long[] line_stats) {
    synchronized (this) {
      try {
        final long now = SystemTime.getCurrentTime();

        final long now_mins = now / (1000 * 60);

        String[] bits = utc_date_format.format(new Date(now)).split(",");

        String year = bits[0];
        String month = bits[1];
        String day = bits[2];

        String current_rel_file = year + File.separator + month + File.separator + day + ".dat";

        String line;

        String stats_str = "";

        if (record_type == RT_SESSION_START) {

          // absolute values

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

            stats_str += "," + line_stats[i];

            line_stats_prev[i] = 0;
          }

          day_cache = null;

        } else {

          // relative values

          long[] diffs = new long[STAT_ENTRY_COUNT];

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

            long diff = line_stats[i] - line_stats_prev[i];

            session_total += diff;

            diffs[i] = diff;

            stats_str += "," + diff;

            line_stats_prev[i] = line_stats[i];

            stat_averages[i].update(diff);
          }

          if (day_cache != null) {

            if (day_cache.isForDay(year, month, day)) {

              day_cache.addRecord(now_mins, diffs);
            }
          }
        }

        if (record_type != RT_SESSION_STATS) {

          line =
              (record_type == RT_SESSION_START ? "s," : "e,")
                  + VERSION
                  + ","
                  + now_mins
                  + stats_str;

        } else {

          line = stats_str.substring(1);
        }

        if (writer == null || !writer_rel_file.equals(current_rel_file)) {

          // first open of a file or file switch

          if (writer != null) {

            // file switch

            if (record_type != RT_SESSION_START) {

              writer.println(line);
            }

            writer.close();

            if (writer.checkError()) {

              writer = null;

              throw (new IOException("Write faled"));
            }

            writer = null;
          }

          // no point in opening a new file just to record the session-end

          if (record_type != RT_SESSION_END) {

            File file = new File(stats_dir, current_rel_file);

            file.getParentFile().mkdirs();

            writer = new PrintWriter(new FileWriter(file, true));

            writer_rel_file = current_rel_file;

            if (record_type == RT_SESSION_START) {

              writer.println(line);

            } else {

              // first entry in a new file, files always start with a session-start so they
              // can be processed in isolation so reset the session data and start a new one

              st_p_sent += line_stats[0];
              st_d_sent += line_stats[1];
              st_p_received += line_stats[2];
              st_d_received += line_stats[3];
              st_dht_sent += line_stats[4];
              st_dht_received += line_stats[5];

              ss_p_sent += line_stats[0];
              ss_d_sent += line_stats[1];
              ss_p_received += line_stats[2];
              ss_d_received += line_stats[3];
              ss_dht_sent += line_stats[4];
              ss_dht_received += line_stats[5];

              stats_str = "";

              long[] st_stats =
                  new long[] {
                    st_p_sent, st_d_sent, st_p_received, st_d_received, st_dht_sent, st_dht_received
                  };

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

                stats_str += "," + st_stats[i];

                line_stats_prev[i] = 0;
              }

              line = "s," + VERSION + "," + now_mins + stats_str;

              writer.println(line);
            }
          }
        } else {

          writer.println(line);
        }

      } catch (Throwable e) {

        Debug.out("Failed to write long term stats", e);

      } finally {

        if (writer != null) {

          if (record_type == RT_SESSION_END) {

            writer.close();
          }

          if (writer.checkError()) {

            Debug.out("Failed to write long term stats");

            writer.close();

            writer = null;

          } else {

            if (record_type == RT_SESSION_END) {

              writer = null;
            }
          }
        }
      }
    }

    if (record_type != RT_SESSION_END) {

      final List<LongTermStatsListener> to_fire = new ArrayList<LongTermStatsListener>();

      for (Object[] entry : listeners) {

        long diff = session_total - (Long) entry[2];

        if (diff >= (Long) entry[1]) {

          entry[2] = session_total;

          to_fire.add((LongTermStatsListener) entry[0]);
        }
      }

      if (to_fire.size() > 0) {

        dispatcher.dispatch(
            new AERunnable() {
              @Override
              public void runSupport() {
                for (LongTermStatsListener l : to_fire) {

                  try {
                    l.updated(LongTermStatsImpl.this);

                  } catch (Throwable e) {

                    Debug.out(e);
                  }
                }
              }
            });
      }
    }
  }
  protected void processDir(TOTorrentFileHasher hasher, File dir, Vector encoded, String root)
      throws TOTorrentException {
    File[] dir_file_list = dir.listFiles();

    if (dir_file_list == null) {

      throw (new TOTorrentException(
          "TOTorrentCreate: directory '"
              + dir.getAbsolutePath()
              + "' returned error when listing files in it",
          TOTorrentException.RT_FILE_NOT_FOUND));
    }
    // sort contents so that multiple encodes of a dir always
    // generate same torrent

    List file_list = new ArrayList(Arrays.asList(dir_file_list));

    Collections.sort(file_list);

    long offset = 0;

    for (int i = 0; i < file_list.size(); i++) {

      File file = (File) file_list.get(i);

      String file_name = file.getName();

      if (!(file_name.equals(".") || file_name.equals(".."))) {

        if (file.isDirectory()) {

          if (root.length() > 0) {

            file_name = root + File.separator + file_name;
          }

          processDir(hasher, file, encoded, file_name);

        } else {

          if (!ignoreFile(file_name)) {

            if (root.length() > 0) {

              file_name = root + File.separator + file_name;
            }

            long length = hasher.add(file);

            TOTorrentFileImpl tf = new TOTorrentFileImpl(this, offset, length, file_name);

            offset += length;

            if (add_other_hashes) {

              byte[] ed2k_digest = hasher.getPerFileED2KDigest();
              byte[] sha1_digest = hasher.getPerFileSHA1Digest();

              // System.out.println( "file:ed2k = " + ByteFormatter.nicePrint( ed2k_digest, true ));
              // System.out.println( "file:sha1 = " + ByteFormatter.nicePrint( sha1_digest, true ));

              tf.setAdditionalProperty("sha1", sha1_digest);
              tf.setAdditionalProperty("ed2k", ed2k_digest);
            }

            encoded.addElement(tf);
          }
        }
      }
    }
  }
  public void runSupport() {

    try {
      new URL(url_str); // determine if this is already a proper URL
    } catch (Throwable t) { // it's not

      //  			//check if the string is just a base32/hex-encoded torrent infohash
      //
      //  		String magnet_uri = UrlUtils.normaliseMagnetURI( url_str );
      //
      //  		if ( magnet_uri != null ){
      //
      //  			url_str = magnet_uri;
      //  		}
    }

    try {
      url = AddressUtils.adjustURL(new URL(url_str));

      String protocol = url.getProtocol().toLowerCase();

      // hack here - the magnet download process requires an additional paramter to cause it to
      // stall on error so the error can be reported

      //    	if ( protocol.equals( "magnet" ) || protocol.equals( "dht" )){
      //
      //    		url = AddressUtils.adjustURL( new URL(url_str+"&pause_on_error=true"));
      //    	}

      for (int i = 0; i < 2; i++) {
        try {

          //	      if ( protocol.equals("https")){
          //
          //	      	// see ConfigurationChecker for SSL client defaults
          //
          //	      	HttpsURLConnection ssl_con = (HttpsURLConnection)url.openConnection();
          //
          //	      	// allow for certs that contain IP addresses rather than dns names
          //
          //	      	ssl_con.setHostnameVerifier(
          //	      			new HostnameVerifier()
          //	      			{
          //	      				public boolean
          //	      				verify(
          //	      					String		host,
          //							SSLSession	session )
          //	      				{
          //	      					return( true );
          //	      				}
          //	      			});
          //
          //	      	con = ssl_con;
          //
          //	      }else{
          //
          con = (HttpURLConnection) url.openConnection();

          //	      }

          con.setRequestProperty(
              "User-Agent", Constants.AZUREUS_NAME + " " + Constants.AZUREUS_VERSION);

          if (referrer != null && referrer.length() > 0) {

            con.setRequestProperty("Referer", referrer);
          }

          if (request_properties != null) {

            Iterator it = request_properties.entrySet().iterator();

            while (it.hasNext()) {

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

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

              // currently this code doesn't support gzip/deflate...

              if (!key.equalsIgnoreCase("Accept-Encoding")) {

                con.setRequestProperty(key, value);
              }
            }
          }

          this.con.connect();

          break;

          //      	}catch( SSLException e ){
          //
          //      		if ( i == 0 ){
          //
          //      			if ( SESecurityManager.installServerCertificates( url ) != null ){
          //
          //      				// certificate has been installed
          //
          //      				continue;	// retry with new certificate
          //      			}
          //      		}
          //
          //      		throw( e );
          //
        } catch (IOException e) {

          if (i == 0) {

            URL retry_url = UrlUtils.getIPV4Fallback(url);

            if (retry_url != null) {

              url = retry_url;

            } else {

              throw (e);
            }
          }
        }
      }

      int response = this.con.getResponseCode();
      if (!ignoreReponseCode) {
        if ((response != HttpURLConnection.HTTP_ACCEPTED)
            && (response != HttpURLConnection.HTTP_OK)) {
          this.error(response, Integer.toString(response) + ": " + this.con.getResponseMessage());
          return;
        }
      }

      /*
           Map headerFields = this.con.getHeaderFields();

           System.out.println("Header of download of " + url_str);
           for (Iterator iter = headerFields.keySet().iterator(); iter.hasNext();) {
      			String s = (String) iter.next();
      			System.out.println(s + ":" + headerFields.get(s));

      		}
      */
      filename = this.con.getHeaderField("Content-Disposition");
      if ((filename != null)
          && filename
              .toLowerCase()
              .matches(".*attachment.*")) // Some code to handle b0rked servers.
      while (filename.toLowerCase().charAt(0) != 'a') filename = filename.substring(1);
      if ((filename == null)
          || !filename.toLowerCase().startsWith("attachment")
          || (filename.indexOf('=') == -1)) {
        String tmp = this.url.getFile();
        if (tmp.length() == 0 || tmp.equals("/")) {
          filename = url.getHost();
        } else if (tmp.startsWith("?")) {

          // probably a magnet URI - use the hash
          // magnet:?xt=urn:sha1:VGC53ZWCUXUWVGX7LQPVZIYF4L6RXSU6

          String query = tmp.toUpperCase();

          int pos = query.indexOf("XT=URN:SHA1:");

          if (pos == -1) {

            pos = query.indexOf("XT=URN:BTIH:");
          }

          if (pos != -1) {

            pos += 12;

            int p2 = query.indexOf("&", pos);

            if (p2 == -1) {

              filename = query.substring(pos);

            } else {

              filename = query.substring(pos, p2);
            }
          } else {

            filename = "Torrent" + (long) (Math.random() * Long.MAX_VALUE);
          }

          filename += ".tmp";

        } else {
          if (tmp.lastIndexOf('/') != -1) tmp = tmp.substring(tmp.lastIndexOf('/') + 1);

          // remove any params in the url

          int param_pos = tmp.indexOf('?');

          if (param_pos != -1) {
            tmp = tmp.substring(0, param_pos);
          }

          filename = URLDecoder.decode(tmp, Constants.DEFAULT_ENCODING);
        }
      } else {
        filename = filename.substring(filename.indexOf('=') + 1);
        if (filename.startsWith("\"") && filename.endsWith("\""))
          filename = filename.substring(1, filename.lastIndexOf('\"'));

        filename = URLDecoder.decode(filename, Constants.DEFAULT_ENCODING);

        // not sure of this piece of logic here but I'm not changing it at the moment

        File temp = new File(filename);
        filename = temp.getName();
      }

      filename = FileUtil.convertOSSpecificChars(filename, false);

      //      directoryname =
      // COConfigurationManager.getDirectoryParameter("General_sDefaultTorrent_Directory");
      //      boolean useTorrentSave = COConfigurationManager.getBooleanParameter("Save Torrent
      // Files");
      directoryname = "D:\\Development\\testDownloads\\";
      boolean useTorrentSave = true;
      if (file_str != null) {
        // not completely sure about the whole logic in this block
        File temp = new File(file_str);

        // if we're not using a default torrent save dir
        if (!useTorrentSave || directoryname.length() == 0) {
          // if it's already a dir
          if (temp.isDirectory()) {
            // use it
            directoryname = temp.getCanonicalPath();
          }
          // it's a file
          else {
            // so use its parent dir
            directoryname = temp.getCanonicalFile().getParent();
          }
        }

        // if it's a file
        if (!temp.isDirectory()) {
          // set the file name
          filename = temp.getName();
        }
      }
      // what would happen here if directoryname == null and file_str == null??

      this.state = STATE_INIT;
      this.notifyListener();
    } catch (java.net.MalformedURLException e) {
      this.error(0, "Exception while parsing URL '" + url + "':" + e.getMessage());
    } catch (java.net.UnknownHostException e) {
      this.error(
          0,
          "Exception while initializing download of '"
              + url
              + "': Unknown Host '"
              + e.getMessage()
              + "'");
    } catch (java.io.IOException ioe) {
      this.error(0, "I/O Exception while initializing download of '" + url + "':" + ioe.toString());
    } catch (Throwable e) {
      this.error(0, "Exception while initializing download of '" + url + "':" + e.toString());
    }

    if (this.state == STATE_ERROR) {

      return;
    }

    try {
      final boolean status_reader_run[] = {true};

      this.state = STATE_START;

      notifyListener();

      this.state = STATE_DOWNLOADING;

      notifyListener();

      Thread status_reader =
          new AEThread("TorrentDownloader:statusreader") {
            public void runSupport() {
              boolean changed_status = false;

              while (true) {

                try {
                  Thread.sleep(100);

                  try {
                    this_mon.enter();

                    if (!status_reader_run[0]) {

                      break;
                    }
                  } finally {

                    this_mon.exit();
                  }

                  String s = con.getResponseMessage();

                  if (!s.equals(getStatus())) {

                    if (!s.toLowerCase().startsWith("error:")) {

                      if (s.toLowerCase().indexOf("alive") != -1) {

                        if (percentDone < 10) {

                          percentDone++;
                        }
                      }

                      int pos = s.indexOf('%');

                      if (pos != -1) {

                        int i;

                        for (i = pos - 1; i >= 0; i--) {

                          char c = s.charAt(i);

                          if (!Character.isDigit(c) && c != ' ') {

                            i++;

                            break;
                          }
                        }

                        try {
                          percentDone = Integer.parseInt(s.substring(i, pos).trim());

                        } catch (Throwable e) {

                        }
                      }

                      setStatus(s);

                    } else {

                      error(con.getResponseCode(), s.substring(6));
                    }

                    changed_status = true;
                  }

                } catch (Throwable e) {

                  break;
                }
              }

              if (changed_status) {

                setStatus("");
              }
            }
          };

      status_reader.setDaemon(true);

      status_reader.start();

      InputStream in;

      try {
        in = this.con.getInputStream();

      } catch (FileNotFoundException e) {
        if (ignoreReponseCode) {

          in = this.con.getErrorStream();
        } else {

          throw e;
        }

      } finally {

        try {
          this_mon.enter();

          status_reader_run[0] = false;

        } finally {

          this_mon.exit();
        }
      }

      // handle some servers that return gzip'd torrents even though we don't request it!

      String encoding = con.getHeaderField("content-encoding");

      if (encoding != null) {

        if (encoding.equalsIgnoreCase("gzip")) {

          in = new GZIPInputStream(in);

        } else if (encoding.equalsIgnoreCase("deflate")) {

          in = new InflaterInputStream(in);
        }
      }

      if (this.state != STATE_ERROR) {

        this.file = new File(this.directoryname, filename);

        boolean useTempFile = false;
        try {
          this.file.createNewFile();
          useTempFile = !this.file.exists();
        } catch (Throwable t) {
          useTempFile = true;
        }

        if (useTempFile) {
          this.file = File.createTempFile("AZU", ".torrent", new File(this.directoryname));
          this.file.createNewFile();
        }

        FileOutputStream fileout = new FileOutputStream(this.file, false);

        bufBytes = 0;

        int size = (int) UrlUtils.getContentLength(con);

        this.percentDone = -1;

        do {
          if (this.cancel) {
            break;
          }

          try {
            bufBytes = in.read(buf);

            this.readTotal += bufBytes;

            if (size != 0) {
              this.percentDone = (100 * this.readTotal) / size;
            }

            notifyListener();

          } catch (IOException e) {
          }

          if (bufBytes > 0) {
            fileout.write(buf, 0, bufBytes);
          }
        } while (bufBytes > 0);

        in.close();

        fileout.flush();

        fileout.close();

        if (this.cancel) {
          this.state = STATE_CANCELLED;
          if (deleteFileOnCancel) {
            this.cleanUpFile();
          }
        } else {
          if (this.readTotal <= 0) {
            this.error(0, "No data contained in '" + this.url.toString() + "'");
            return;
          }

          // if the file has come down with a not-so-useful name then we try to rename
          // it to something more useful

          try {
            if (!filename.toLowerCase().endsWith(".torrent")) {

              TOTorrent torrent = TorrentUtils.readFromFile(file, false);

              String name = TorrentUtils.getLocalisedName(torrent) + ".torrent";

              File new_file = new File(directoryname, name);

              if (file.renameTo(new_file)) {

                filename = name;

                file = new_file;
              }
            }
          } catch (Throwable e) {

            Debug.printStackTrace(e);
          }

          //	          TorrentUtils.setObtainedFrom( file, original_url );

          this.state = STATE_FINISHED;
        }
        this.notifyListener();
      }
    } catch (Exception e) {

      if (!cancel) {

        Debug.out("'" + this.directoryname + "' '" + filename + "'", e);
      }

      this.error(0, "Exception while downloading '" + this.url.toString() + "':" + e.getMessage());
    }
  }