diff --git a/apps/i2psnark/java/src/org/klomp/snark/I2PSnarkUtil.java b/apps/i2psnark/java/src/org/klomp/snark/I2PSnarkUtil.java index 320b5005a..a00ad001e 100644 --- a/apps/i2psnark/java/src/org/klomp/snark/I2PSnarkUtil.java +++ b/apps/i2psnark/java/src/org/klomp/snark/I2PSnarkUtil.java @@ -3,6 +3,7 @@ package org.klomp.snark; import java.io.File; import java.io.IOException; import java.util.ArrayList; +import java.util.Collections; import java.util.HashMap; import java.util.Iterator; import java.util.List; @@ -64,7 +65,7 @@ public class I2PSnarkUtil { private int _startupDelay; private boolean _shouldUseOT; private boolean _areFilesPublic; - private String _openTrackerString; + private List _openTrackers; private DHT _dht; public static final int DEFAULT_STARTUP_DELAY = 3; @@ -88,6 +89,8 @@ public class I2PSnarkUtil { _maxConnections = MAX_CONNECTIONS; _startupDelay = DEFAULT_STARTUP_DELAY; _shouldUseOT = DEFAULT_USE_OPENTRACKERS; + // FIXME split if default has more than one + _openTrackers = Collections.singletonList(DEFAULT_OPENTRACKERS); // This is used for both announce replies and .torrent file downloads, // so it must be available even if not connected to I2CP. // so much for multiple instances @@ -453,34 +456,17 @@ public class I2PSnarkUtil { } /** @param ot non-null */ - public void setOpenTrackerString(String ot) { - _openTrackerString = ot; - } - - /** Comma delimited list of open trackers to use as backups - * non-null but possibly empty - */ - public String getOpenTrackerString() { - if (_openTrackerString == null) - return DEFAULT_OPENTRACKERS; - return _openTrackerString; + public void setOpenTrackers(List ot) { + _openTrackers = ot; } /** List of open trackers to use as backups - * Null if disabled + * @return non-null, possibly unmodifiable, empty if disabled */ public List getOpenTrackers() { if (!shouldUseOpenTrackers()) - return null; - List rv = new ArrayList(1); - String trackers = getOpenTrackerString(); - StringTokenizer tok = new StringTokenizer(trackers, ", "); - while (tok.hasMoreTokens()) - rv.add(tok.nextToken()); - - if (rv.isEmpty()) - return null; - return rv; + return Collections.EMPTY_LIST; + return _openTrackers; } public void setUseOpenTrackers(boolean yes) { diff --git a/apps/i2psnark/java/src/org/klomp/snark/SnarkManager.java b/apps/i2psnark/java/src/org/klomp/snark/SnarkManager.java index 7c1c421a8..0186d5d7d 100644 --- a/apps/i2psnark/java/src/org/klomp/snark/SnarkManager.java +++ b/apps/i2psnark/java/src/org/klomp/snark/SnarkManager.java @@ -8,6 +8,7 @@ import java.io.FilenameFilter; import java.io.IOException; import java.io.OutputStream; import java.util.ArrayList; +import java.util.Arrays; import java.util.Collection; import java.util.Collections; import java.util.Comparator; @@ -85,6 +86,7 @@ public class SnarkManager implements Snark.CompleteListener { public static final String DEFAULT_THEME = "ubergine"; private static final String PROP_USE_OPENTRACKERS = "i2psnark.useOpentrackers"; public static final String PROP_OPENTRACKERS = "i2psnark.opentrackers"; + public static final String PROP_PRIVATETRACKERS = "i2psnark.privatetrackers"; public static final int MIN_UP_BW = 2; public static final int DEFAULT_MAX_UP_BW = 10; @@ -343,7 +345,7 @@ public class SnarkManager implements Snark.CompleteListener { _util.setFilesPublic(areFilesPublic()); String ot = _config.getProperty(PROP_OPENTRACKERS); if (ot != null) - _util.setOpenTrackerString(ot); + _util.setOpenTrackers(getOpenTrackers()); String useOT = _config.getProperty(PROP_USE_OPENTRACKERS); boolean bOT = useOT == null || Boolean.valueOf(useOT).booleanValue(); _util.setUseOpenTrackers(bOT); @@ -563,20 +565,84 @@ public class SnarkManager implements Snark.CompleteListener { } } + /** + * Others should use the version in I2PSnarkUtil + * @return non-null, empty if disabled + * @since 0.9.1 + */ + private List getOpenTrackers() { + if (!_util.shouldUseOpenTrackers()) + return Collections.EMPTY_LIST; + return getListConfig(PROP_OPENTRACKERS, I2PSnarkUtil.DEFAULT_OPENTRACKERS); + } + + /** + * @return non-null, fixed size, may be empty or unmodifiable + * @since 0.9.1 + */ + public List getPrivateTrackers() { + return getListConfig(PROP_PRIVATETRACKERS, null); + } + /** * @param ot null to restore default * @since 0.9.1 */ - public void saveOpenTrackers(String ot) { - _util.setOpenTrackerString(ot); - if (ot != null) - _config.setProperty(PROP_OPENTRACKERS, ot); - else - _config.remove(PROP_OPENTRACKERS); + public void saveOpenTrackers(List ot) { + String val = setListConfig(PROP_OPENTRACKERS, ot); + if (ot == null) + ot = Collections.singletonList(I2PSnarkUtil.DEFAULT_OPENTRACKERS); + _util.setOpenTrackers(ot); addMessage(_("Open Tracker list changed - torrent restart required to take effect.")); saveConfig(); } + /** + * @param ot null ok, default is none + * @since 0.9.1 + */ + public void savePrivateTrackers(List pt) { + setListConfig(PROP_PRIVATETRACKERS, pt); + addMessage(_("Private tracker list changed - affects newly created torrents only.")); + saveConfig(); + } + + /** + * @param dflt default or null + * @return non-null, fixed size + * @since 0.9.1 + */ + private List getListConfig(String prop, String dflt) { + String val = _config.getProperty(prop); + if (val == null) + val = dflt; + if (val == null) + return Collections.EMPTY_LIST; + return Arrays.asList(val.split(",")); + } + + /** + * Sets the config, does NOT save it + * @param values may be null or empty + * @return the comma-separated config string, non-null + * @since 0.9.1 + */ + private String setListConfig(String prop, List values) { + if (values == null || values.isEmpty()) { + _config.remove(prop); + return ""; + } + StringBuilder buf = new StringBuilder(64); + for (String s : values) { + if (buf.length() > 0) + buf.append(','); + buf.append(s); + } + String rv = buf.toString(); + _config.setProperty(prop, rv); + return rv; + } + public void saveConfig() { try { synchronized (_configFile) { @@ -1449,7 +1515,7 @@ public class SnarkManager implements Snark.CompleteListener { String url = toks[i+1].trim().replace(",", ","); if ( (name.length() > 0) && (url.length() > 0) ) { String urls[] = url.split("=", 2); - String url2 = urls.length > 1 ? urls[1] : null; + String url2 = urls.length > 1 ? urls[1] : ""; _trackerMap.put(name, new Tracker(name, urls[0], url2)); } } 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 d6acf4853..cb0098525 100644 --- a/apps/i2psnark/java/src/org/klomp/snark/web/I2PSnarkServlet.java +++ b/apps/i2psnark/java/src/org/klomp/snark/web/I2PSnarkServlet.java @@ -721,7 +721,8 @@ public class I2PSnarkServlet extends DefaultServlet { try { // This may take a long time to check the storage, but since it already exists, // it shouldn't be THAT bad, so keep it in this thread. - Storage s = new Storage(_manager.util(), baseFile, announceURL, req.getParameter("private") != null, null); + boolean isPrivate = _manager.getPrivateTrackers().contains(announceURL); + Storage s = new Storage(_manager.util(), baseFile, announceURL, isPrivate, null); s.close(); // close the files... maybe need a way to pass this Storage to addTorrent rather than starting over MetaInfo info = s.getMetaInfo(); File torrentFile = new File(_manager.getDataDir(), s.getBaseName() + ".torrent"); @@ -729,7 +730,7 @@ public class I2PSnarkServlet extends DefaultServlet { // now add it, but don't automatically start it _manager.addTorrent(info, s.getBitField(), torrentFile.getAbsolutePath(), true); _manager.addMessage(_("Torrent created for \"{0}\"", baseFile.getName()) + ": " + torrentFile.getAbsolutePath()); - if (announceURL != null) + if (announceURL != null && !_manager.util().getOpenTrackers().contains(announceURL)) _manager.addMessage(_("Many I2P trackers require you to register new torrents before seeding - please do so before starting \"{0}\"", baseFile.getName())); } catch (IOException ioe) { _manager.addMessage(_("Error creating a torrent for \"{0}\"", baseFile.getAbsolutePath()) + ": " + ioe.getMessage()); @@ -771,11 +772,12 @@ public class I2PSnarkServlet extends DefaultServlet { /** @since 0.9 */ private void processTrackerForm(String action, HttpServletRequest req) { - if (action.equals(_("Delete selected")) || action.equals(_("Change open trackers"))) { + if (action.equals(_("Delete selected")) || action.equals(_("Save tracker configuration"))) { boolean changed = false; Map trackers = _manager.getTrackerMap(); List removed = new ArrayList(); List open = new ArrayList(); + List priv = new ArrayList(); Enumeration e = req.getParameterNames(); while (e.hasMoreElements()) { Object o = e.nextElement(); @@ -792,22 +794,30 @@ public class I2PSnarkServlet extends DefaultServlet { } } else if (k.startsWith("open_")) { open.add(k.substring(5)); + } else if (k.startsWith("private_")) { + priv.add(k.substring(8)); } } if (changed) { _manager.saveTrackerMap(); } + open.removeAll(removed); - StringBuilder openBuf = new StringBuilder(128); - for (String s : open) { - if (openBuf.length() > 0) - openBuf.append(','); - openBuf.append(s); - } - String newOpen = openBuf.toString(); - if (!newOpen.equals(_manager.util().getOpenTrackerString())) { - _manager.saveOpenTrackers(newOpen); - } + List oldOpen = new ArrayList(_manager.util().getOpenTrackers()); + Collections.sort(oldOpen); + Collections.sort(open); + if (!open.equals(oldOpen)) + _manager.saveOpenTrackers(open); + + priv.removeAll(removed); + // open trumps private + priv.removeAll(open); + List oldPriv = new ArrayList(_manager.getPrivateTrackers()); + Collections.sort(oldPriv); + Collections.sort(priv); + if (!priv.equals(oldPriv)) + _manager.savePrivateTrackers(priv); + } else if (action.equals(_("Add tracker"))) { String name = req.getParameter("tname"); String hurl = req.getParameter("thurl"); @@ -820,10 +830,15 @@ public class I2PSnarkServlet extends DefaultServlet { Map trackers = _manager.getTrackerMap(); trackers.put(name, new Tracker(name, aurl, hurl)); _manager.saveTrackerMap(); + // open trumps private if (req.getParameter("_add_open_") != null) { - String oldOpen = _manager.util().getOpenTrackerString(); - String newOpen = oldOpen.length() <= 0 ? aurl : oldOpen + ',' + aurl; + List newOpen = new ArrayList(_manager.util().getOpenTrackers()); + newOpen.add(aurl); _manager.saveOpenTrackers(newOpen); + } else if (req.getParameter("_add_private_") != null) { + List newPriv = new ArrayList(_manager.getPrivateTrackers()); + newPriv.add(aurl); + _manager.savePrivateTrackers(newPriv); } } else { _manager.addMessage(_("Enter valid tracker name and URLs")); @@ -1426,14 +1441,7 @@ public class I2PSnarkServlet extends DefaultServlet { out.write(" \n" + - ""); - out.write(_("Private?")); - out.write(" " + + "" + "\n" + ""); } @@ -1636,11 +1644,14 @@ public class I2PSnarkServlet extends DefaultServlet { .append("") .append(_("Website URL")) .append("") - .append(_("Open Tracker?")) + .append(_("Open")) + .append("") + .append(_("Private")) .append("") .append(_("Announce URL")) .append("\n"); List openTrackers = _manager.util().getOpenTrackers(); + List privateTrackers = _manager.getPrivateTrackers(); for (Tracker t : _manager.getSortedTrackers()) { String name = t.name; String homeURL = t.baseURL; @@ -1651,7 +1662,12 @@ public class I2PSnarkServlet extends DefaultServlet { .append("").append(urlify(homeURL, 35)) .append("" + + "" + "").append(urlify(announceURL, 35)) @@ -1662,11 +1678,12 @@ public class I2PSnarkServlet extends DefaultServlet { "" + "" + "" + + "" + "\n" + - "\n" + + "\n" + "\n" + "\n" + - "\n" + + "\n" + // "\n" + "\n" + "\n" + @@ -2067,9 +2084,13 @@ public class I2PSnarkServlet extends DefaultServlet { } String hex = I2PSnarkUtil.toHex(snark.getInfoHash()); - buf.append("
").append(toImg("magnet", _("Magnet link"))).append(" ") - .append(MAGNET_FULL).append(hex).append(""); + if (meta == null || !meta.isPrivate()) { + buf.append("
").append(toImg("magnet", _("Magnet link"))).append(" ") + .append(MAGNET_FULL).append(hex).append(""); + } else { + buf.append("
").append(_("Private torrent")); + } // We don't have the hash of the torrent file //buf.append("
").append(_("Maggot link")).append(": ") // .append(MAGGOT).append(hex).append(':').append(hex).append(""); diff --git a/history.txt b/history.txt index b274c8fc4..f0107f6f2 100644 --- a/history.txt +++ b/history.txt @@ -1,3 +1,10 @@ +2012-06-08 zzz + * i2psnark: + - Move private tracker config from create box to torrent config + - Refactor private and open tracker configuration + - Add private indication on details page + * netdb.jsp: Don't show our info on summary page + 2012-06-04 zzz * i2psnark: Take tracker out of opentracker list when removed diff --git a/router/java/src/net/i2p/router/RouterVersion.java b/router/java/src/net/i2p/router/RouterVersion.java index 7ca1a3ec2..5a58b19bc 100644 --- a/router/java/src/net/i2p/router/RouterVersion.java +++ b/router/java/src/net/i2p/router/RouterVersion.java @@ -18,7 +18,7 @@ public class RouterVersion { /** deprecated */ public final static String ID = "Monotone"; public final static String VERSION = CoreVersion.VERSION; - public final static long BUILD = 10; + public final static long BUILD = 11; /** for example "-test" */ public final static String EXTRA = "";