diff --git a/apps/i2psnark/java/src/org/klomp/snark/SnarkManager.java b/apps/i2psnark/java/src/org/klomp/snark/SnarkManager.java index 51c9373b0..905c27cee 100644 --- a/apps/i2psnark/java/src/org/klomp/snark/SnarkManager.java +++ b/apps/i2psnark/java/src/org/klomp/snark/SnarkManager.java @@ -198,6 +198,7 @@ public class SnarkManager implements Snark.CompleteListener { String ot = _config.getProperty(I2PSnarkUtil.PROP_OPENTRACKERS); if (ot != null) _util.setOpenTrackerString(ot); + // FIXME set util use open trackers property somehow getDataDir().mkdirs(); } @@ -428,6 +429,14 @@ public class SnarkManager implements Snark.CompleteListener { fis.close(); fis = null; + if (!TrackerClient.isValidAnnounce(info.getAnnounce())) { + if (_util.shouldUseOpenTrackers() && _util.getOpenTrackers() != null) { + addMessage(_("Warning - Ignoring non-i2p tracker in \"{0}\", will announce to i2p open trackers only", info.getName())); + } else { + addMessage(_("Warning - Ignoring non-i2p tracker in \"{0}\", and open trackers are disabled, you must enable open trackers before starting the torrent!", info.getName())); + dontAutoStart = true; + } + } String rejectMessage = locked_validateTorrent(info); if (rejectMessage != null) { sfile.delete(); @@ -551,12 +560,10 @@ public class SnarkManager implements Snark.CompleteListener { saveConfig(); } + /** + * Warning - does not validate announce URL - use TrackerClient.isValidAnnounce() + */ private String locked_validateTorrent(MetaInfo info) throws IOException { - String announce = info.getAnnounce(); - // basic validation of url - if ((!announce.startsWith("http://")) || - (announce.indexOf(".i2p/") < 0)) // need to do better than this - return _("Non-i2p tracker in \"{0}\", deleting it from our list of trackers!", info.getName()); List files = info.getFiles(); if ( (files != null) && (files.size() > MAX_FILES_PER_TORRENT) ) { return _("Too many files in \"{0}\" ({1}), deleting it!", info.getName(), files.size()); diff --git a/apps/i2psnark/java/src/org/klomp/snark/TrackerClient.java b/apps/i2psnark/java/src/org/klomp/snark/TrackerClient.java index 309fd62b5..c6f22a63d 100644 --- a/apps/i2psnark/java/src/org/klomp/snark/TrackerClient.java +++ b/apps/i2psnark/java/src/org/klomp/snark/TrackerClient.java @@ -24,6 +24,8 @@ import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; +import java.net.MalformedURLException; +import java.net.URL; import java.util.ArrayList; import java.util.Collections; import java.util.Iterator; @@ -123,13 +125,19 @@ public class TrackerClient extends I2PAppThread // followed by the secondary open trackers // It's painful, but try to make sure if an open tracker is also // the primary tracker, that we don't add it twice. + // todo: check for b32 matches as well trackers = new ArrayList(2); - trackers.add(new Tracker(meta.getAnnounce(), true)); + String primary = meta.getAnnounce(); + if (isValidAnnounce(primary)) { + trackers.add(new Tracker(meta.getAnnounce(), true)); + } else { + _log.warn("Skipping invalid or non-i2p announce: " + primary); + } List tlist = _util.getOpenTrackers(); if (tlist != null) { for (int i = 0; i < tlist.size(); i++) { String url = (String)tlist.get(i); - if (!url.startsWith("http://")) { + if (!isValidAnnounce(url)) { _log.error("Bad announce URL: [" + url + "]"); continue; } @@ -138,22 +146,29 @@ public class TrackerClient extends I2PAppThread _log.error("Bad announce URL: [" + url + "]"); continue; } - if (meta.getAnnounce().startsWith(url.substring(0, slash))) + if (primary.startsWith(url.substring(0, slash))) continue; String dest = _util.lookup(url.substring(7, slash)); if (dest == null) { _log.error("Announce host unknown: [" + url + "]"); continue; } - if (meta.getAnnounce().startsWith("http://" + dest)) + if (primary.startsWith("http://" + dest)) continue; - if (meta.getAnnounce().startsWith("http://i2p/" + dest)) + if (primary.startsWith("http://i2p/" + dest)) continue; trackers.add(new Tracker(url, false)); _log.debug("Additional announce: [" + url + "] for infoHash: " + infoHash); } } + if (tlist.size() <= 0) { + // FIXME really need to get this message to the gui + stop = true; + _log.error("No valid trackers for infoHash: " + infoHash); + return; + } + long uploaded = coordinator.getUploaded(); long downloaded = coordinator.getDownloaded(); long left = coordinator.getLeft(); @@ -399,6 +414,22 @@ public class TrackerClient extends I2PAppThread return sb.toString(); } + /** + * @return true for i2p hosts only + * @since 0.7.12 + */ + static boolean isValidAnnounce(String ann) { + URL url; + try { + url = new URL(ann); + } catch (MalformedURLException mue) { + return false; + } + return url.getProtocol().equals("http") && + (url.getHost().endsWith(".i2p") || url.getHost().equals("i2p")) && + url.getPort() < 0; + } + private class Tracker { String announce; diff --git a/apps/i2psnark/java/src/org/klomp/snark/web/I2PSnarkServlet.java b/apps/i2psnark/java/src/org/klomp/snark/web/I2PSnarkServlet.java index f5e46d5d9..013d70a94 100644 --- a/apps/i2psnark/java/src/org/klomp/snark/web/I2PSnarkServlet.java +++ b/apps/i2psnark/java/src/org/klomp/snark/web/I2PSnarkServlet.java @@ -455,8 +455,11 @@ public class I2PSnarkServlet extends HttpServlet { int i = filename.lastIndexOf(".torrent"); if (i > 0) filename = filename.substring(0, i); - if (filename.length() > MAX_DISPLAYED_FILENAME_LENGTH) + String fullFilename = filename; + if (filename.length() > MAX_DISPLAYED_FILENAME_LENGTH) { + fullFilename = new String(filename); filename = filename.substring(0, MAX_DISPLAYED_FILENAME_LENGTH) + "…"; + } long total = snark.meta.getTotalLength(); // Early typecast, avoid possibly overflowing a temp integer long remaining = (long) snark.storage.needed() * (long) snark.meta.getPieceLength(0); @@ -627,13 +630,23 @@ public class I2PSnarkServlet extends HttpServlet { out.write(""); + out.write("\" onclick=\"if (!confirm('"); + // Can't figure out how to escape double quotes inside the onclick string. + // Single quotes in translate strings with parameters must be doubled. + // Then the remaining single quite must be escaped + out.write(_("Are you sure you want to delete the file \\''{0}.torrent\\'' (downloaded data will not be deleted) ?", fullFilename)); + out.write("')) { return false; }\">"); out.write(_("Remove")); out.write("
"); out.write(""); + out.write("\" onclick=\"if (!confirm('"); + // Can't figure out how to escape double quotes inside the onclick string. + // Single quotes in translate strings with parameters must be doubled. + // Then the remaining single quite must be escaped + out.write(_("Are you sure you want to delete the torrent \\''{0}\\'' and all downloaded data?", fullFilename)); + out.write("')) { return false; }\">"); out.write(_("Delete")); out.write(""); } diff --git a/apps/routerconsole/java/src/net/i2p/router/web/ConfigClientsHelper.java b/apps/routerconsole/java/src/net/i2p/router/web/ConfigClientsHelper.java index d66e37e23..bb19f3c47 100644 --- a/apps/routerconsole/java/src/net/i2p/router/web/ConfigClientsHelper.java +++ b/apps/routerconsole/java/src/net/i2p/router/web/ConfigClientsHelper.java @@ -42,11 +42,12 @@ public class ConfigClientsHelper extends HelperBase { ClientAppConfig ca = clients.get(cur); renderForm(buf, ""+cur, ca.clientName, false, !ca.disabled, "webConsole".equals(ca.clientName) || "Web console".equals(ca.clientName), - ca.className + ((ca.args != null) ? " " + ca.args : ""), (""+cur).equals(_edit), true, false, false); + ca.className + ((ca.args != null) ? " " + ca.args : ""), (""+cur).equals(_edit), + true, false, false, true); } if ("new".equals(_edit)) - renderForm(buf, "" + clients.size(), "", false, false, false, "", true, false, false, false); + renderForm(buf, "" + clients.size(), "", false, false, false, "", true, false, false, false, false); buf.append("\n"); return buf.toString(); } @@ -63,7 +64,8 @@ public class ConfigClientsHelper extends HelperBase { String app = name.substring(RouterConsoleRunner.PREFIX.length(), name.lastIndexOf(RouterConsoleRunner.ENABLED)); String val = props.getProperty(name); renderForm(buf, app, app, !"addressbook".equals(app), - "true".equals(val), RouterConsoleRunner.ROUTERCONSOLE.equals(app), app + ".war", false, false, false, false); + "true".equals(val), RouterConsoleRunner.ROUTERCONSOLE.equals(app), app + ".war", + false, false, false, false, false); } } buf.append("\n"); @@ -146,7 +148,7 @@ public class ConfigClientsHelper extends HelperBase { desc.append(""); renderForm(buf, app, app, false, "true".equals(val), false, desc.toString(), false, false, - updateURL != null, true); + updateURL != null, true, true); } } buf.append("\n"); @@ -156,7 +158,8 @@ public class ConfigClientsHelper extends HelperBase { /** ro trumps edit and showEditButton */ private void renderForm(StringBuilder buf, String index, String name, boolean urlify, boolean enabled, boolean ro, String desc, boolean edit, - boolean showEditButton, boolean showUpdateButton, boolean showStopButton) { + boolean showEditButton, boolean showUpdateButton, boolean showStopButton, + boolean showDeleteButton) { buf.append(""); if (urlify && enabled) { String link = "/"; @@ -190,8 +193,13 @@ public class ConfigClientsHelper extends HelperBase { buf.append(""); buf.append(""); } - if ((!edit) && !ro) - buf.append(""); + if (showDeleteButton && (!edit) && !ro) { + buf.append(""); + } buf.append(""); if (edit && !ro) { buf.append("