protected void loadConfig() {
    if (FileUtil.resilientConfigFileExists(CONFIG_FILE)) {

      Map map = FileUtil.readResilientConfigFile(CONFIG_FILE);

      List list = (List) map.get("networks");

      if (list != null) {

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

          Map cnet_map = (Map) list.get(i);

          try {

            ContentNetworkImpl cn = ContentNetworkImpl.importFromBEncodedMapStatic(this, cnet_map);

            if (cn.getID() != ContentNetwork.CONTENT_NETWORK_VUZE) {

              networks.add(cn);
            }
          } catch (Throwable e) {

            log("Failed to load " + cnet_map, e);
          }
        }
      }
    }
  }
Beispiel #2
0
  protected void createDirs(File target) throws FMFileManagerException {

    if (clone) {

      return;
    }

    deleteDirs();

    File parent = target.getParentFile();

    if (!parent.exists()) {

      List new_dirs = new ArrayList();

      File current = parent;

      while (current != null && !current.exists()) {

        new_dirs.add(current);

        current = current.getParentFile();
      }

      created_dirs_leaf = target;
      created_dirs = new ArrayList();

      if (FileUtil.mkdirs(parent)) {

        created_dirs = new_dirs;

        /*
        for (int i=created_dirs.size()-1;i>=0;i--){

        	System.out.println( "created " + created_dirs.get(i));
        }
        */
      } else {
        // had some reports of this exception being thrown when starting a torrent
        // double check in case there's some parallel creation being triggered somehow

        try {
          Thread.sleep(RandomUtils.nextInt(1000));

        } catch (Throwable e) {
        }

        FileUtil.mkdirs(parent);

        if (parent.isDirectory()) {

          created_dirs = new_dirs;

        } else {

          throw (new FMFileManagerException("Failed to create parent directory '" + parent + "'"));
        }
      }
    }
  }
Beispiel #3
0
  public static void createTestFiles() {
    try {
      System.out.println("Creating test files ... ");
      Random rand = new Random();
      String rootname = "f-";

      long[] sizes = {0, 1, 50000000};

      File testdir = new File(dirname);
      FileUtil.mkdirs(testdir);

      for (int i = 0; i < sizes.length; i++) {
        long size = sizes[i];
        File file = new File(testdir, rootname + String.valueOf(size));
        System.out.println(file.getName() + "...");
        FileChannel fc = new RandomAccessFile(file, "rw").getChannel();

        long position = 0;
        while (position < size) {
          long remaining = size - position;
          if (remaining > 1024000) remaining = 1024000;
          byte[] buffer = new byte[new Long(remaining).intValue()];
          rand.nextBytes(buffer);
          ByteBuffer bb = ByteBuffer.wrap(buffer);
          position += fc.write(bb);
        }

        fc.close();
      }
      System.out.println("DONE\n");
    } catch (Exception e) {
      Debug.printStackTrace(e);
    }
  }
    private void save() {
      File file = getCacheFile();

      file.getParentFile().mkdirs();

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

      FileUtil.writeResilientFile(file, contents);

      dirty = false;
    }
  public void load(String filename) {
    Map data = FileUtil.readResilientConfigFile(filename, false);

    // horrendous recursive loading going on here due to logger + config depedencies. If already
    // loaded
    // then use the existing data as it might have already been written to...

    if (propertiesMap == null) {

      ConcurrentHashMapWrapper<String, Object> c_map =
          new ConcurrentHashMapWrapper<String, Object>(data.size() + 256, 0.75f, 8);

      c_map.putAll(data);

      propertiesMap = c_map;
    }

    /*
     * Can't do this yet.  Sometimes, there's a default set to x, but the code
     * calls get..Parameter(..., y).  y != x.  When the user sets the the parameter
     * to x, we remove it from the list.  Later, the get..Parameter(.., y) returns
     * y because there is no entry.
     *
     * The solution is to not allow get..Parameter(.., y) when there's a default
     * value.  Another reason to not allow it is that having two defaults confuses
     * coders.
     *
      	// Remove entries that are default.  Saves memory, reduces
      	// file size when saved again
        ConfigurationDefaults def = ConfigurationDefaults.getInstance();
      	Iterator it = new TreeSet(propertiesMap.keySet()).iterator();

    		while (it.hasNext()) {
    			String key = (String)it.next();
    			Object defValue = def.getDefaultValueAsObject(key);
    			if (defValue == null)
    				continue;

    			if (defValue instanceof Long) {
    				int iDefValue = ((Long)defValue).intValue();
    				int iValue = getIntParameter(key, iDefValue);
    				if (iValue == iDefValue)
    					propertiesMap.remove(key);
    			}
    			if (defValue instanceof String) {
    				String sDefValue = defValue.toString();
    				String sValue = getStringParameter(key, sDefValue);
    				if (sValue.compareTo(sDefValue) == 0)
    					propertiesMap.remove(key);
    			}
    		}
    */
  }
  public LongTermStatsImpl(AzureusCore _core, GlobalManagerStats _gm_stats) {
    core = _core;
    gm_stats = _gm_stats;

    stats_dir = FileUtil.getUserFile("stats");

    COConfigurationManager.addParameterListener(
        "long.term.stats.enable",
        new ParameterListener() {
          public void parameterChanged(String name) {
            boolean enabled = COConfigurationManager.getBooleanParameter(name);

            synchronized (LongTermStatsImpl.this) {
              if (enabled) {

                if (!active) {

                  sessionStart();
                }
              } else {

                if (active) {

                  sessionEnd();
                }
              }
            }
          }
        });

    _core.addLifecycleListener(
        new AzureusCoreLifecycleAdapter() {
          public void componentCreated(AzureusCore core, AzureusCoreComponent component) {
            if (component instanceof GlobalManager) {

              synchronized (LongTermStatsImpl.this) {
                sessionStart();
              }
            }
          }

          public void stopped(AzureusCore core) {
            synchronized (LongTermStatsImpl.this) {
              closing = true;

              if (active) {

                sessionEnd();
              }
            }
          }
        });
  }
  protected void saveConfig() {
    Map map = new HashMap();

    List list = new ArrayList();

    map.put("networks", list);

    Iterator<ContentNetworkImpl> it = networks.iterator();

    while (it.hasNext()) {

      ContentNetworkImpl network = it.next();

      if (network.getID() == ContentNetwork.CONTENT_NETWORK_VUZE) {

        continue;
      }

      Map cnet_map = new HashMap();

      try {
        network.exportToBEncodedMap(cnet_map);

        list.add(cnet_map);

      } catch (Throwable e) {

        log("Failed to save " + network.getName(), e);
      }
    }

    if (list.size() == 0) {

      FileUtil.deleteResilientConfigFile(CONFIG_FILE);

    } else {

      FileUtil.writeResilientConfigFile(CONFIG_FILE, map);
    }
  }
  public void save(String filename) {
    if (propertiesMap == null) {

      // nothing to save, initialisation not complete

      return;
    }

    /**
     * Note - propertiesMap isn't synchronised! We'll clone the map now, because we need to modify
     * it. The BEncoding code will create a new map object (TreeMap) because it needs to be sorted,
     * so we might as well do it here too.
     */
    TreeMap<String, Object> properties_clone = propertiesMap.toTreeMap();

    // Remove any transient parameters.
    if (!this.transient_properties.isEmpty()) {
      properties_clone.keySet().removeAll(this.transient_properties);
    }

    FileUtil.writeResilientConfigFile(filename, properties_clone);

    List<COConfigurationListener> listeners_copy;

    synchronized (listenerz) {
      listeners_copy = new ArrayList<COConfigurationListener>(listenerz);
    }

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

      COConfigurationListener l = (COConfigurationListener) listeners_copy.get(i);

      if (l != null) {

        try {
          l.configurationSaved();

        } catch (Throwable e) {

          Debug.printStackTrace(e);
        }
      } else {

        Debug.out("COConfigurationListener is null");
      }
    }

    if (exported_parameters_dirty) {

      exportParameters();
    }
  }
Beispiel #9
0
  protected void saveDeviceFile() {
    device_files_dirty = false;

    try {
      loadDeviceFile();

      if (device_files == null || device_files.size() == 0) {

        FileUtil.deleteResilientFile(getDeviceFile());

      } else {
        Map map = new HashMap();

        map.put("files", device_files);

        FileUtil.writeResilientFile(getDeviceFile(), map);
      }
    } catch (Throwable e) {

      Debug.out("Failed to save device file", e);
    }
  }
  private String getFileContent() throws IOException {
    InputStreamReader reader = null;

    try {
      byte[] file_bytes = FileUtil.readFileAsByteArray(new File(plistFile));

      // handle UTF-8 encoded BOM EFBBBF

      if (file_bytes.length > 3
          && file_bytes[0] == (byte) 0xEF
          && file_bytes[1] == (byte) 0xBB
          && file_bytes[2] == (byte) 0xBF) {

        found_bom = true;

        reader =
            new InputStreamReader(new ByteArrayInputStream(file_bytes, 3, file_bytes.length - 3));

      } else {

        found_bom = false;

        reader = new InputStreamReader(new ByteArrayInputStream(file_bytes));
      }

      // max 32KB

      int length = 32 * 1024;

      char[] buffer = new char[length];

      int offset = 0;

      int len = 0;

      while ((len = reader.read(buffer, offset, length - offset)) > 0) {
        offset += len;
      }

      String result = new String(buffer, 0, offset);

      return result;

    } finally {
      if (reader != null) {
        reader.close();
      }
    }

    // return FileUtil.readFileAsString(new File(plistFile), 64*1024, "UTF-8" );
  }
Beispiel #11
0
  protected void loadDeviceFile() throws IOException {

    device_files_last_mod = SystemTime.getMonotonousTime();

    if (device_files_ref != null) {

      device_files = device_files_ref.get();
    }

    if (device_files == null) {

      Map map = FileUtil.readResilientFile(getDeviceFile());

      device_files = (Map<String, Map<String, ?>>) map.get("files");

      if (device_files == null) {

        device_files = new HashMap<String, Map<String, ?>>();
      }

      device_files_ref = new WeakReference<Map<String, Map<String, ?>>>(device_files);

      log("Loaded device file for " + getName() + ": files=" + device_files.size());
    }

    final int GC_TIME = 15000;

    new DelayedEvent(
        "Device:gc",
        GC_TIME,
        new AERunnable() {
          public void runSupport() {
            synchronized (DeviceImpl.this) {
              if (SystemTime.getMonotonousTime() - device_files_last_mod >= GC_TIME) {

                if (device_files_dirty) {

                  saveDeviceFile();
                }

                device_files = null;

              } else {

                new DelayedEvent("Device:gc2", GC_TIME, this);
              }
            }
          }
        });
  }
  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;
  }
Beispiel #13
0
  public File getWorkingDirectory(boolean persist) {
    String result = getPersistentStringProperty(PP_REND_WORK_DIR);

    if (result.length() == 0) {

      File f = manager.getDefaultWorkingDirectory(persist);

      if (persist) {

        f.mkdirs();
      }

      String name = FileUtil.convertOSSpecificChars(getName(), true);

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

        String test_name = name + (i == 0 ? "" : ("_" + i));

        File test_file = new File(f, test_name);

        if (!test_file.exists()) {

          f = test_file;

          break;
        }
      }

      result = f.getAbsolutePath();

      if (persist) {

        setPersistentStringProperty(PP_REND_WORK_DIR, result);
      }
    }

    File f_result = new File(result);

    if (!f_result.exists()) {

      if (persist) {

        f_result.mkdirs();
      }
    }

    return (f_result);
  }
    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);
    }
Beispiel #15
0
 private static File getApplicationFile(String filename) {
   return FileUtil.getApplicationFile(filename);
 }
Beispiel #16
0
  protected File getDeviceFile() throws IOException {

    File dir = getDevicesDir();

    return (new File(dir, FileUtil.convertOSSpecificChars(getID(), false) + ".dat"));
  }
  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());
    }
  }
  protected PluginInterfaceImpl(
      Plugin _plugin,
      PluginInitializer _initialiser,
      Object _initialiser_key,
      ClassLoader _class_loader,
      List<File> _verified_files,
      String _key,
      Properties _props,
      String _pluginDir,
      String _plugin_id,
      String _plugin_version)
      throws PluginException {
    // check we're being created by the core

    StackTraceElement[] stack = Thread.currentThread().getStackTrace();

    int pos = 0;

    while (!stack[pos].getClassName().equals(PluginInterfaceImpl.class.getName())) {

      pos++;
    }

    String caller_class = stack[pos + 1].getClassName();

    if (!(caller_class.equals("org.gudy.azureus2.pluginsimpl.local.PluginInitializer")
        || caller_class.equals("org.gudy.azureus2.pluginsimpl.local.PluginInterfaceImpl"))) {

      throw (new PluginException("Invalid caller"));
    }

    // check we haven't been subclassed

    String class_name = getClass().getCanonicalName();

    if (class_name == null
        || !class_name.equals("org.gudy.azureus2.pluginsimpl.local.PluginInterfaceImpl")) {

      throw (new PluginException("Subclassing not permitted"));
    }

    plugin = _plugin;
    initialiser = _initialiser;
    initialiser_key = _initialiser_key;
    class_loader = _class_loader;
    key = _key;
    pluginConfigKey = "Plugin." + _key;
    props = new propertyWrapper(_props);
    pluginDir = _pluginDir;
    config = new PluginConfigImpl(this, pluginConfigKey);
    given_plugin_id = _plugin_id;
    plugin_version = _plugin_version;
    ipc_interface = new IPCInterfaceImpl(initialiser, plugin);
    state = new PluginStateImpl(this, initialiser);

    boolean verified = false;
    boolean bad = false;

    if (_plugin_id.endsWith("_v")) {

      if (plugin.getClass() == FailedPlugin.class) {

        verified = true;

      } else {
        if (_verified_files != null) {

          File jar = FileUtil.getJarFileFromClass(plugin.getClass());

          if (jar != null) {

            for (File file : _verified_files) {

              if (file.equals(jar)) {

                verified = true;
              }
            }
          }
        }
      }

      if (!verified) {

        bad = true;
      }
    }

    PluginInitializer.setVerified(this, plugin, verified, bad);
  }
Beispiel #19
0
  public void moveFile(File new_unlinked_file) throws FMFileManagerException {

    try {
      this_mon.enter();

      TOTorrentFile tf = owner.getTorrentFile();

      String new_canonical_path;

      File new_linked_file = manager.getFileLink(tf.getTorrent(), tf.getIndex(), new_unlinked_file);

      try {

        try {

          new_canonical_path = new_linked_file.getCanonicalPath();

        } catch (IOException ioe) {

          String msg = ioe.getMessage();

          if (msg != null && msg.indexOf("There are no more files") != -1) {
            String abs_path = new_linked_file.getAbsolutePath();
            String error =
                "Caught 'There are no more files' exception during new_file.getCanonicalPath(). "
                    + "os=["
                    + Constants.OSName
                    + "], new_file.getPath()=["
                    + new_linked_file.getPath()
                    + "], new_file.getAbsolutePath()=["
                    + abs_path
                    + "]. ";
            // "new_canonical_path temporarily set to [" +abs_path+ "]";
            Debug.out(error, ioe);
          }
          throw ioe;
        }

      } catch (Throwable e) {

        throw (new FMFileManagerException("getCanonicalPath fails", e));
      }

      if (new_linked_file.exists()) {

        throw (new FMFileManagerException(
            "moveFile fails - file '" + new_canonical_path + "' already exists"));
      }

      boolean was_open = isOpen();

      close(); // full close, this will release any slots in the limited file case

      createDirs(new_linked_file);

      if (!linked_file.exists() || FileUtil.renameFile(linked_file, new_linked_file)) {

        linked_file = new_linked_file;
        canonical_path = new_canonical_path;

        reserveFile();

        if (was_open) {

          ensureOpen("moveFile target"); // ensure open will regain slots in limited file case
        }

      } else {

        try {
          reserveFile();

        } catch (FMFileManagerException e) {

          Debug.printStackTrace(e);
        }

        if (was_open) {

          try {
            ensureOpen("moveFile recovery");

          } catch (FMFileManagerException e) {

            Debug.printStackTrace(e);
          }
        }

        throw (new FMFileManagerException("moveFile fails"));
      }
    } finally {

      this_mon.exit();
    }
  }
Beispiel #20
0
  private void getWhatsNew(final int phase) {
    String helpFile = null;
    if (phase == 1) {
      helpFile = MessageText.getString("window.welcome.file");

      if (!helpFile.toLowerCase().startsWith(Constants.SF_WEB_SITE)) {
        getWhatsNew(2);
        return;
      }
    } else {
      helpFile = MessageText.getString("window.welcome.file");

      InputStream stream;
      stream = getClass().getResourceAsStream(helpFile);
      if (stream == null) {
        String helpFullPath = "/org/gudy/azureus2/internat/whatsnew/" + helpFile;
        stream = getClass().getResourceAsStream(helpFullPath);
      }
      if (stream == null) {
        stream = getClass().getResourceAsStream("/ChangeLog.txt");
      }
      if (stream == null) {
        sWhatsNew = "Welcome Window: Error loading resource: " + helpFile;
      } else {
        try {
          sWhatsNew = FileUtil.readInputStreamAsString(stream, 65535, "utf8");
          stream.close();
        } catch (IOException e) {
          Debug.out(e);
        }
      }
      setWhatsNew();
      return;
    }

    final String url = helpFile;

    new AEThread2("getWhatsNew", true) {

      public void run() {

        String s;
        ResourceDownloaderFactory rdf = ResourceDownloaderFactoryImpl.getSingleton();
        try {
          ResourceDownloader rd = rdf.create(new URL(url));
          InputStream is = rd.download();
          int length = is.available();
          byte data[] = new byte[length];
          is.read(data);
          is.close();
          s = new String(data);
        } catch (ResourceDownloaderException rde) {
          // We don't need a stack trace - it's arguable that we even need any
          // errors at all - the below line is better, but suppressed output might
          // be better.
          // Debug.outNoStack("Error downloading from " + url + ", " + rde, true);
          s = "";
        } catch (Exception e) {
          Debug.out(e);
          s = "";
        }
        sWhatsNew = s;

        if (sWhatsNew == null || sWhatsNew.length() == 0) {
          getWhatsNew(phase + 1);
          return;
        }

        Utils.execSWTThread(
            new AERunnable() {
              public void runSupport() {
                if (cWhatsNew != null && !cWhatsNew.isDisposed()) {
                  setWhatsNew();
                }
              }
            });
      }
    }.start();
  }
Beispiel #21
0
  public static Locale[] getLocales() {
    String bundleFolder = BUNDLE_NAME.replace('.', '/');
    final String prefix = BUNDLE_NAME.substring(BUNDLE_NAME.lastIndexOf('.') + 1);
    final String extension = ".properties";

    String urlString =
        MessageText.class
            .getClassLoader()
            .getResource(bundleFolder.concat(extension))
            .toExternalForm();
    // System.out.println("urlString: " + urlString);
    String[] bundles = null;

    if (urlString.startsWith("jar:file:")) {

      File jar = FileUtil.getJarFileFromURL(urlString);

      if (jar != null) {
        try {
          // System.out.println("jar: " + jar.getAbsolutePath());
          JarFile jarFile = new JarFile(jar);
          Enumeration entries = jarFile.entries();
          ArrayList list = new ArrayList(250);
          while (entries.hasMoreElements()) {
            JarEntry jarEntry = (JarEntry) entries.nextElement();
            if (jarEntry.getName().startsWith(bundleFolder)
                && jarEntry.getName().endsWith(extension)) {
              // System.out.println("jarEntry: " + jarEntry.getName());
              list.add(jarEntry.getName().substring(bundleFolder.length() - prefix.length()));
              // "MessagesBundle_de_DE.properties"
            }
          }
          bundles = (String[]) list.toArray(new String[list.size()]);
        } catch (Exception e) {
          Debug.printStackTrace(e);
        }
      }
    } else {
      File bundleDirectory = new File(URI.create(urlString)).getParentFile();
      //      System.out.println("bundleDirectory: " +
      // bundleDirectory.getAbsolutePath());

      bundles =
          bundleDirectory.list(
              new FilenameFilter() {
                public boolean accept(File dir, String name) {
                  return name.startsWith(prefix) && name.endsWith(extension);
                }
              });
    }

    HashSet bundleSet = new HashSet();

    // Add local first
    File localDir = new File(SystemProperties.getUserPath());
    String localBundles[] =
        localDir.list(
            new FilenameFilter() {
              public boolean accept(File dir, String name) {
                return name.startsWith(prefix) && name.endsWith(extension);
              }
            });

    // can be null if user path is borked

    if (localBundles != null) {

      bundleSet.addAll(Arrays.asList(localBundles));
    }

    // Add AppDir 2nd
    File appDir = new File(SystemProperties.getApplicationPath());
    String appBundles[] =
        appDir.list(
            new FilenameFilter() {
              public boolean accept(File dir, String name) {
                return name.startsWith(prefix) && name.endsWith(extension);
              }
            });

    // can be null if app path is borked

    if (appBundles != null) {

      bundleSet.addAll(Arrays.asList(appBundles));
    }
    // Any duplicates will be ignored
    bundleSet.addAll(Arrays.asList(bundles));

    List foundLocalesList = new ArrayList(bundleSet.size());

    foundLocalesList.add(LOCALE_ENGLISH);

    Iterator val = bundleSet.iterator();
    while (val.hasNext()) {
      String sBundle = (String) val.next();

      // System.out.println("ResourceBundle: " + bundles[i]);
      if (prefix.length() + 1 < sBundle.length() - extension.length()) {
        String locale =
            sBundle.substring(prefix.length() + 1, sBundle.length() - extension.length());
        // System.out.println("Locale: " + locale);
        String[] sLocalesSplit = locale.split("_", 3);
        if (sLocalesSplit.length > 0 && sLocalesSplit[0].length() == 2) {
          if (sLocalesSplit.length == 3) {
            foundLocalesList.add(new Locale(sLocalesSplit[0], sLocalesSplit[1], sLocalesSplit[2]));
          } else if (sLocalesSplit.length == 2 && sLocalesSplit[1].length() == 2) {
            foundLocalesList.add(new Locale(sLocalesSplit[0], sLocalesSplit[1]));
          } else {
            foundLocalesList.add(new Locale(sLocalesSplit[0]));
          }
        } else {
          if (sLocalesSplit.length == 3
              && sLocalesSplit[0].length() == 0
              && sLocalesSplit[2].length() > 0) {
            foundLocalesList.add(new Locale(sLocalesSplit[0], sLocalesSplit[1], sLocalesSplit[2]));
          }
        }
      }
    }

    Locale[] foundLocales = new Locale[foundLocalesList.size()];

    foundLocalesList.toArray(foundLocales);

    try {
      Arrays.sort(
          foundLocales,
          new Comparator() {
            public final int compare(Object a, Object b) {
              return ((Locale) a)
                  .getDisplayName((Locale) a)
                  .compareToIgnoreCase(((Locale) b).getDisplayName((Locale) b));
            }
          });
    } catch (Throwable e) {
      // user has a problem whereby a null-pointer exception occurs when sorting the
      // list - I've done some fixes to the locale list construction but am
      // putting this in here just in case
      Debug.printStackTrace(e);
    }
    return foundLocales;
  }
  protected boolean handleLocalTunnel(
      TrackerWebPageRequest request, TrackerWebPageResponse response) throws IOException {
    start();

    if (SRP_VERIFIER == null || !active) {

      throw (new IOException("Secure pairing is not enabled"));
    }

    boolean good_request = false;

    try {
      // remove /pairing/tunnel/

      String url = request.getURL().substring(16);

      int q_pos = url.indexOf('?');

      Map<String, String> args = new HashMap<String, String>();

      if (q_pos != -1) {

        String args_str = url.substring(q_pos + 1);

        String[] bits = args_str.split("&");

        for (String arg : bits) {

          String[] x = arg.split("=");

          if (x.length == 2) {

            args.put(x[0].toLowerCase(), x[1]);
          }
        }

        url = url.substring(0, q_pos);
      }

      if (url.startsWith("create")) {

        String ac = args.get("ac");
        String sid = args.get("sid");

        if (ac == null || sid == null) {

          throw (new IOException("Access code or service id missing"));
        }

        if (!ac.equals(manager.peekAccessCode())) {

          throw (new IOException("Invalid access code"));
        }

        PairedServiceImpl ps = manager.getService(sid);

        if (ps == null) {

          good_request = true;

          throw (new IOException("Service '" + sid + "' not registered"));
        }

        PairedServiceRequestHandler handler = ps.getHandler();

        if (handler == null) {

          good_request = true;

          throw (new IOException("Service '" + sid + "' has no handler registered"));
        }

        JSONObject json = new JSONObject();

        JSONObject result = new JSONObject();

        json.put("result", result);

        byte[] ss = new byte[] {SRP_SALT[0], SRP_SALT[1], SRP_SALT[2], SRP_SALT[3]};

        long tunnel_id = RandomUtils.nextSecureAbsoluteLong();

        String tunnel_name = Base32.encode(ss) + "_" + tunnel_id;

        synchronized (local_server_map) {
          long diff = SystemTime.getMonotonousTime() - last_local_server_create_time;

          if (diff < 5000) {

            try {
              long sleep = 5000 - diff;

              System.out.println("Sleeping for " + sleep + " before starting srp");

              Thread.sleep(sleep);

            } catch (Throwable e) {
            }
          }

          SRP6Server server = new SRP6Server();

          server.init(N_3072, G_3072, SRP_VERIFIER, new SHA256Digest(), RandomUtils.SECURE_RANDOM);

          BigInteger B = server.generateServerCredentials();

          local_server_map.put(tunnel_name, new Object[] {server, handler, null, null});

          last_local_server_create_time = SystemTime.getMonotonousTime();

          total_local_servers++;

          result.put("srp_salt", Base32.encode(SRP_SALT));

          result.put("srp_b", Base32.encode(B.toByteArray()));

          Map<String, String> headers = request.getHeaders();

          String host = headers.get("host");

          // remove port number

          int pos = host.lastIndexOf("]");

          if (pos != -1) {

            // ipv6 literal

            host = host.substring(0, pos + 1);

          } else {

            pos = host.indexOf(':');

            if (pos != -1) {

              host = host.substring(0, pos);
            }
          }

          String abs_url = request.getAbsoluteURL().toString();

          // unfortunately there is some nasty code that uses a configured tracker
          // address as the default host

          abs_url = UrlUtils.setHost(new URL(abs_url), host).toExternalForm();

          pos = abs_url.indexOf("/create");

          String tunnel_url = abs_url.substring(0, pos) + "/id/" + tunnel_name;

          result.put("url", tunnel_url);
        }

        response.getOutputStream().write(JSONUtils.encodeToJSON(json).getBytes("UTF-8"));

        response.setContentType("application/json; charset=UTF-8");

        response.setGZIP(true);

        good_request = true;

        return (true);

      } else if (url.startsWith("id/")) {

        String tunnel_name = url.substring(3);

        Object[] entry;

        synchronized (local_server_map) {
          entry = local_server_map.get(tunnel_name);

          if (entry == null) {

            good_request = true;

            throw (new IOException("Unknown tunnel id"));
          }
        }

        String srp_a = args.get("srp_a");
        String enc_data = args.get("enc_data");
        String enc_iv = args.get("enc_iv");

        if (srp_a != null && enc_data != null && enc_iv != null) {

          try {
            synchronized (local_server_map) {
              long diff = SystemTime.getMonotonousTime() - last_local_server_agree_time;

              if (diff < 5000) {

                try {
                  long sleep = 5000 - diff;

                  System.out.println("Sleeping for " + sleep + " before completing srp");

                  Thread.sleep(sleep);

                } catch (Throwable e) {
                }
              }
            }

            JSONObject json = new JSONObject();

            JSONObject result = new JSONObject();

            json.put("result", result);

            SRP6Server server = (SRP6Server) entry[0];

            BigInteger A = new BigInteger(Base32.decode(srp_a));

            BigInteger serverS = server.calculateSecret(A);

            byte[] shared_secret = serverS.toByteArray();

            Cipher decipher = Cipher.getInstance("AES/CBC/PKCS5Padding");

            byte[] key = new byte[16];

            System.arraycopy(shared_secret, 0, key, 0, 16);

            SecretKeySpec secret = new SecretKeySpec(key, "AES");

            decipher.init(Cipher.DECRYPT_MODE, secret, new IvParameterSpec(Base32.decode(enc_iv)));

            byte[] dec = decipher.doFinal(Base32.decode(enc_data));

            JSONObject dec_json = (JSONObject) JSONUtils.decodeJSON(new String(dec, "UTF-8"));

            String tunnel_url = (String) dec_json.get("url");

            if (!tunnel_url.contains(tunnel_name)) {

              throw (new IOException("Invalid tunnel url"));
            }

            String endpoint_url = (String) dec_json.get("endpoint");

            entry[2] = secret;
            entry[3] = endpoint_url;

            result.put("state", "activated");

            response.getOutputStream().write(JSONUtils.encodeToJSON(json).getBytes("UTF-8"));

            response.setContentType("application/json; charset=UTF-8");

            response.setGZIP(true);

            good_request = true;

            return (true);

          } catch (Throwable e) {

            throw (new IOException(Debug.getNestedExceptionMessage(e)));

          } finally {

            last_local_server_agree_time = SystemTime.getMonotonousTime();
          }
        } else if (args.containsKey("close")) {

          synchronized (local_server_map) {
            local_server_map.remove(tunnel_name);
          }

          good_request = true;

          return (true);

        } else {

          PairedServiceRequestHandler request_handler = (PairedServiceRequestHandler) entry[1];

          SecretKeySpec secret = (SecretKeySpec) entry[2];

          String endpoint_url = (String) entry[3];

          if (secret == null) {

            throw (new IOException("auth not completed"));
          }

          byte[] request_data = FileUtil.readInputStreamAsByteArray(request.getInputStream());

          try {
            byte[] decrypted;

            {
              byte[] IV = new byte[16];

              System.arraycopy(request_data, 0, IV, 0, IV.length);

              Cipher decipher = Cipher.getInstance("AES/CBC/PKCS5Padding");

              decipher.init(Cipher.DECRYPT_MODE, secret, new IvParameterSpec(IV));

              decrypted = decipher.doFinal(request_data, 16, request_data.length - 16);
            }

            byte[] reply_bytes =
                request_handler.handleRequest(
                    request.getClientAddress2().getAddress(), endpoint_url, decrypted);

            {
              Cipher encipher = Cipher.getInstance("AES/CBC/PKCS5Padding");

              encipher.init(Cipher.ENCRYPT_MODE, secret);

              AlgorithmParameters params = encipher.getParameters();

              byte[] IV = params.getParameterSpec(IvParameterSpec.class).getIV();

              byte[] enc = encipher.doFinal(reply_bytes);

              byte[] rep_bytes = new byte[IV.length + enc.length];

              System.arraycopy(IV, 0, rep_bytes, 0, IV.length);
              System.arraycopy(enc, 0, rep_bytes, IV.length, enc.length);

              response.getOutputStream().write(rep_bytes);

              response.setContentType("application/octet-stream");

              good_request = true;

              return (true);
            }
          } catch (Throwable e) {

            throw (new IOException(Debug.getNestedExceptionMessage(e)));
          }
        }
      }

      throw (new IOException("Unknown tunnel operation"));

    } finally {

      if (!good_request) {

        manager.recordRequest(
            "SRP", request.getClientAddress2().getAddress().getHostAddress(), false);
      }
    }
  }
  private void setFileContent(String fileContent) throws IOException {

    File file = new File(plistFile);

    File backup_file = new File(plistFile + ".bak");

    if (file.exists()) {

      if (!FileUtil.copyFile(file, backup_file)) {

        throw (new IOException("Failed to backup plist file prior to modification"));
      }
    }

    boolean ok = false;

    try {

      ByteArrayOutputStream baos = new ByteArrayOutputStream(fileContent.length() + 256);

      if (found_bom) {

        // preserve UTF-8 BOM if it was found

        baos.write(new byte[] {(byte) 0xEF, (byte) 0xBB, (byte) 0xBF});
      }

      OutputStreamWriter osw = new OutputStreamWriter(baos);

      osw.write(fileContent);

      osw.close();

      FileOutputStream out = null;

      try {

        out = new FileOutputStream(plistFile);

        out.write(baos.toByteArray());

      } finally {

        if (out != null) {

          out.close();

          ok = true;
        }
      }
    } finally {
      if (ok) {

        backup_file.delete();

      } else {

        if (backup_file.exists()) {

          File bork_file = new File(plistFile + ".bad");

          file.renameTo(bork_file);

          file.delete();

          backup_file.renameTo(file);
        }
      }
    }
  }
Beispiel #24
0
  public void _setWhatsNew() {

    if (sWhatsNew.indexOf("<html") >= 0 || sWhatsNew.indexOf("<HTML") >= 0) {
      BrowserWrapper browser = Utils.createSafeBrowser(cWhatsNew, SWT.NONE);
      if (browser != null) {
        browser.setText(sWhatsNew);
      } else {
        try {
          File tempFile = File.createTempFile("AZU", ".html");
          tempFile.deleteOnExit();
          FileUtil.writeBytesAsFile(tempFile.getAbsolutePath(), sWhatsNew.getBytes("utf8"));
          Utils.launch(tempFile.getAbsolutePath());
          shell.dispose();
          return;
        } catch (IOException e) {
        }
      }
    } else {

      StyledText helpPanel = new StyledText(cWhatsNew, SWT.VERTICAL | SWT.HORIZONTAL);

      helpPanel.setEditable(false);
      try {
        helpPanel.setRedraw(false);
        helpPanel.setWordWrap(false);
        helpPanel.setFont(monospace);

        black = ColorCache.getColor(display, 0, 0, 0);
        white = ColorCache.getColor(display, 255, 255, 255);
        light = ColorCache.getColor(display, 200, 200, 200);
        grey = ColorCache.getColor(display, 50, 50, 50);
        green = ColorCache.getColor(display, 30, 80, 30);
        blue = ColorCache.getColor(display, 20, 20, 80);
        int style;
        boolean setStyle;

        helpPanel.setForeground(grey);

        String[] lines = sWhatsNew.split("\\r?\\n");
        for (int i = 0; i < lines.length; i++) {
          String line = lines[i];

          setStyle = false;
          fg = grey;
          bg = white;
          style = SWT.NORMAL;

          char styleChar;
          String text;

          if (line.length() < 2) {
            styleChar = ' ';
            text = " " + lineSeparator;
          } else {
            styleChar = line.charAt(0);
            text = line.substring(1) + lineSeparator;
          }

          switch (styleChar) {
            case '*':
              text = "  * " + text;
              fg = green;
              setStyle = true;
              break;
            case '+':
              text = "     " + text;
              fg = black;
              bg = light;
              style = SWT.BOLD;
              setStyle = true;
              break;
            case '!':
              style = SWT.BOLD;
              setStyle = true;
              break;
            case '@':
              fg = blue;
              setStyle = true;
              break;
            case '$':
              bg = blue;
              fg = white;
              style = SWT.BOLD;
              setStyle = true;
              break;
            case ' ':
              text = "  " + text;
              break;

            default:
              text = styleChar + text;
          }

          helpPanel.append(text);

          if (setStyle) {
            int lineCount = helpPanel.getLineCount() - 1;
            int charCount = helpPanel.getCharCount();
            //          System.out.println("Got Linecount " + lineCount + ", Charcount " +
            // charCount);

            int lineOfs = helpPanel.getOffsetAtLine(lineCount - 1);
            int lineLen = charCount - lineOfs;
            //          System.out.println("Setting Style : " + lineOfs + ", " + lineLen);
            helpPanel.setStyleRange(new StyleRange(lineOfs, lineLen, fg, bg, style));
            helpPanel.setLineBackground(lineCount - 1, 1, bg);
          }
        }

        helpPanel.setRedraw(true);
      } catch (Exception e) {
        System.out.println("Unable to load help contents because:" + e);
        // e.printStackTrace();
      }
    }

    if (labelLoading != null && !labelLoading.isDisposed()) {
      labelLoading.dispose();
    }
    shell.layout(true, true);
  }
  protected void generateEvidence(IndentWriter writer) {
    writer.println(getPluginName());

    try {
      writer.indent();

      writer.println("id:" + getPluginID() + ",version:" + getPluginVersion());

      String user_dir = FileUtil.getUserFile("plugins").toString();
      String shared_dir = FileUtil.getApplicationFile("plugins").toString();

      String plugin_dir = getPluginDirectoryName();

      String type;
      boolean built_in = false;

      if (plugin_dir.startsWith(shared_dir)) {

        type = "shared";

      } else if (plugin_dir.startsWith(user_dir)) {

        type = "per-user";

      } else {

        built_in = true;

        type = "built-in";
      }

      PluginState ps = getPluginState();

      String info = getPluginconfig().getPluginStringParameter("plugin.info");

      writer.println(
          "type:"
              + type
              + ",enabled="
              + !ps.isDisabled()
              + ",load_at_start="
              + ps.isLoadedAtStartup()
              + ",operational="
              + ps.isOperational()
              + (info == null || info.length() == 0 ? "" : (",info=" + info)));

      if (ps.isOperational()) {

        Plugin plugin = getPlugin();

        if (plugin instanceof AEDiagnosticsEvidenceGenerator) {

          try {
            writer.indent();

            ((AEDiagnosticsEvidenceGenerator) plugin).generate(writer);

          } catch (Throwable e) {

            writer.println(
                "Failed to generate plugin-specific info: " + Debug.getNestedExceptionMessage(e));

          } finally {

            writer.exdent();
          }
        }
      } else {
        if (!built_in) {

          File dir = new File(plugin_dir);

          if (dir.exists()) {

            String[] files = dir.list();

            if (files != null) {

              String files_str = "";

              for (String f : files) {

                files_str += (files_str.length() == 0 ? "" : ", ") + f;
              }

              writer.println("    files: " + files_str);
            }
          }
        }
      }
    } finally {

      writer.exdent();
    }
  }
  public boolean addTorrentWithOptions(boolean force, final TorrentOpenOptions torrentOptions) {

    if (AzureusCoreFactory.isCoreRunning()) {
      GlobalManager gm = AzureusCoreFactory.getSingleton().getGlobalManager();
      // Check if torrent already exists in gm, and add if not
      DownloadManager existingDownload = gm.getDownloadManager(torrentOptions.getTorrent());

      if (existingDownload != null) {

        final String fExistingName = existingDownload.getDisplayName();
        final DownloadManager fExistingDownload = existingDownload;

        fExistingDownload.fireGlobalManagerEvent(GlobalManagerEvent.ET_REQUEST_ATTENTION);

        Utils.execSWTThread(
            new AERunnable() {
              public void runSupport() {
                boolean can_merge =
                    TorrentUtils.canMergeAnnounceURLs(
                        torrentOptions.getTorrent(), fExistingDownload.getTorrent());

                Shell mainShell = UIFunctionsManagerSWT.getUIFunctionsSWT().getMainShell();

                if ((Display.getDefault().getActiveShell() == null
                        || !mainShell.isVisible()
                        || mainShell.getMinimized())
                    && (!can_merge)) {

                  new MessageSlideShell(
                      Display.getCurrent(),
                      SWT.ICON_INFORMATION,
                      MSG_ALREADY_EXISTS,
                      null,
                      new String[] {
                        ":" + torrentOptions.sOriginatingLocation,
                        fExistingName,
                        MessageText.getString(MSG_ALREADY_EXISTS_NAME),
                      },
                      new Object[] {fExistingDownload},
                      -1);
                } else {

                  if (can_merge) {

                    String text =
                        MessageText.getString(
                            MSG_ALREADY_EXISTS + ".text",
                            new String[] {
                              ":" + torrentOptions.sOriginatingLocation,
                              fExistingName,
                              MessageText.getString(MSG_ALREADY_EXISTS_NAME),
                            });

                    text +=
                        "\n\n" + MessageText.getString("openTorrentWindow.mb.alreadyExists.merge");

                    MessageBoxShell mb =
                        new MessageBoxShell(
                            SWT.YES | SWT.NO,
                            MessageText.getString(MSG_ALREADY_EXISTS + ".title"),
                            text);

                    mb.open(
                        new UserPrompterResultListener() {
                          public void prompterClosed(int result) {
                            if (result == SWT.YES) {

                              TorrentUtils.mergeAnnounceURLs(
                                  torrentOptions.getTorrent(), fExistingDownload.getTorrent());
                            }
                          }
                        });
                  } else {
                    MessageBoxShell mb =
                        new MessageBoxShell(
                            SWT.OK,
                            MSG_ALREADY_EXISTS,
                            new String[] {
                              ":" + torrentOptions.sOriginatingLocation,
                              fExistingName,
                              MessageText.getString(MSG_ALREADY_EXISTS_NAME),
                            });
                    mb.open(null);
                  }
                }
              }
            });

        if (torrentOptions.bDeleteFileOnCancel) {
          File torrentFile = new File(torrentOptions.sFileName);
          torrentFile.delete();
        }
        return true;
      }
    }

    if (!force) {
      String showAgainMode =
          COConfigurationManager.getStringParameter(
              ConfigurationDefaults.CFG_TORRENTADD_OPENOPTIONS);
      if (showAgainMode != null
          && ((showAgainMode.equals(ConfigurationDefaults.CFG_TORRENTADD_OPENOPTIONS_NEVER))
              || (showAgainMode.equals(ConfigurationDefaults.CFG_TORRENTADD_OPENOPTIONS_MANY)
                  && torrentOptions.getFiles() != null
                  && torrentOptions.getFiles().length == 1))) {

        // we're about to silently add the download - ensure that it is going to be saved somewhere
        // vaguely sensible
        // as the current save location is simply taken from the 'default download' config which can
        // be blank (for example)

        boolean looks_good = false;

        String save_loc = torrentOptions.getParentDir().trim();

        if (save_loc.length() == 0) {

          // blank :(

        } else if (save_loc.startsWith(".")) {

          // relative to who knows where
        } else {

          File f = new File(save_loc);

          if (!f.exists()) {

            f.mkdirs();
          }

          if (f.isDirectory() && FileUtil.canWriteToDirectory(f)) {

            if (!f.equals(AETemporaryFileHandler.getTempDirectory())) {

              looks_good = true;
            }
          }
        }

        if (looks_good) {

          return TorrentOpener.addTorrent(torrentOptions);

        } else {

          torrentOptions.setParentDir("");

          MessageBoxShell mb =
              new MessageBoxShell(
                  SWT.OK | SWT.ICON_ERROR,
                  "OpenTorrentWindow.mb.invaliddefsave",
                  new String[] {save_loc});

          mb.open(
              new UserPrompterResultListener() {
                public void prompterClosed(int result) {
                  OpenTorrentOptionsWindow.addTorrent(torrentOptions);
                }
              });

          return (true);
        }
      }
    }

    OpenTorrentOptionsWindow.addTorrent(torrentOptions);

    return true;
  }