forked from I2P_Developers/i2p.i2p
propagate from branch 'i2p.i2p.zzz.test2' (head f33dbe1499b84cf6192b1a7bd494eaf081a047c0)
to branch 'i2p.i2p' (head 4e5bd2836592b95e1eff01d8e83f2690da386ef8)
This commit is contained in:
@@ -238,8 +238,8 @@ Applications:
|
||||
Bundles systray4j-2.4.1:
|
||||
See licenses/LICENSE-LGPLv2.1.txt
|
||||
|
||||
Tomcat 6.0.35:
|
||||
Copyright 1999-2011 The Apache Software Foundation
|
||||
Tomcat 6.0.36:
|
||||
Copyright 1999-2012 The Apache Software Foundation
|
||||
See licenses/LICENSE-Apache2.0.txt
|
||||
See licenses/NOTICE-Tomcat.txt
|
||||
|
||||
|
||||
@@ -61,6 +61,7 @@ public class MetaInfo
|
||||
private final byte[] piece_hashes;
|
||||
private final long length;
|
||||
private final boolean privateTorrent;
|
||||
private final List<List<String>> announce_list;
|
||||
private Map<String, BEValue> infoMap;
|
||||
|
||||
/**
|
||||
@@ -69,9 +70,11 @@ public class MetaInfo
|
||||
* @param announce may be null
|
||||
* @param files null for single-file torrent
|
||||
* @param lengths null for single-file torrent
|
||||
* @param announce_list may be null
|
||||
*/
|
||||
MetaInfo(String announce, String name, String name_utf8, List<List<String>> files, List<Long> lengths,
|
||||
int piece_length, byte[] piece_hashes, long length, boolean privateTorrent)
|
||||
int piece_length, byte[] piece_hashes, long length, boolean privateTorrent,
|
||||
List<List<String>> announce_list)
|
||||
{
|
||||
this.announce = announce;
|
||||
this.name = name;
|
||||
@@ -83,6 +86,7 @@ public class MetaInfo
|
||||
this.piece_hashes = piece_hashes;
|
||||
this.length = length;
|
||||
this.privateTorrent = privateTorrent;
|
||||
this.announce_list = announce_list;
|
||||
|
||||
// TODO if we add a parameter for other keys
|
||||
//if (other != null) {
|
||||
@@ -141,6 +145,23 @@ public class MetaInfo
|
||||
this.announce = val.getString();
|
||||
}
|
||||
|
||||
// BEP 12
|
||||
val = m.get("announce-list");
|
||||
if (val == null) {
|
||||
this.announce_list = null;
|
||||
} else {
|
||||
this.announce_list = new ArrayList();
|
||||
List<BEValue> bl1 = val.getList();
|
||||
for (BEValue bev : bl1) {
|
||||
List<BEValue> bl2 = bev.getList();
|
||||
List<String> sl2 = new ArrayList();
|
||||
for (BEValue bev2 : bl2) {
|
||||
sl2.add(bev2.getString());
|
||||
}
|
||||
this.announce_list.add(sl2);
|
||||
}
|
||||
}
|
||||
|
||||
val = m.get("info");
|
||||
if (val == null)
|
||||
throw new InvalidBEncodingException("Missing info map");
|
||||
@@ -296,6 +317,15 @@ public class MetaInfo
|
||||
return announce;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a list of lists of urls.
|
||||
*
|
||||
* @since 0.9.5
|
||||
*/
|
||||
public List<List<String>> getAnnounceList() {
|
||||
return announce_list;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the original 20 byte SHA1 hash over the bencoded info map.
|
||||
*/
|
||||
@@ -470,12 +500,13 @@ public class MetaInfo
|
||||
/**
|
||||
* Creates a copy of this MetaInfo that shares everything except the
|
||||
* announce URL.
|
||||
* Drops any announce-list.
|
||||
*/
|
||||
public MetaInfo reannounce(String announce)
|
||||
{
|
||||
return new MetaInfo(announce, name, name_utf8, files,
|
||||
lengths, piece_length,
|
||||
piece_hashes, length, privateTorrent);
|
||||
piece_hashes, length, privateTorrent, null);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -486,6 +517,8 @@ public class MetaInfo
|
||||
Map m = new HashMap();
|
||||
if (announce != null)
|
||||
m.put("announce", announce);
|
||||
if (announce_list != null)
|
||||
m.put("announce-list", announce_list);
|
||||
Map info = createInfoMap();
|
||||
m.put("info", info);
|
||||
// don't save this locally, we should only do this once
|
||||
|
||||
@@ -886,7 +886,9 @@ public class SnarkManager implements CompleteListener {
|
||||
}
|
||||
}
|
||||
} catch (IOException ioe) {
|
||||
addMessage(_("Torrent in \"{0}\" is invalid", sfile.getName()) + ": " + ioe.getMessage());
|
||||
String err = _("Torrent in \"{0}\" is invalid", sfile.getName()) + ": " + ioe.getMessage();
|
||||
addMessage(err);
|
||||
_log.error(err, ioe);
|
||||
if (sfile.exists())
|
||||
sfile.delete();
|
||||
return;
|
||||
|
||||
@@ -122,6 +122,7 @@ public class Storage
|
||||
* @throws IOException when creating and/or checking files fails.
|
||||
*/
|
||||
public Storage(I2PSnarkUtil util, File baseFile, String announce,
|
||||
List<List<String>> announce_list,
|
||||
boolean privateTorrent, StorageListener listener)
|
||||
throws IOException
|
||||
{
|
||||
@@ -182,7 +183,8 @@ public class Storage
|
||||
// TODO thread this so we can return and show something on the UI
|
||||
byte[] piece_hashes = fast_digestCreate();
|
||||
metainfo = new MetaInfo(announce, baseFile.getName(), null, files,
|
||||
lengthsList, piece_size, piece_hashes, total, privateTorrent);
|
||||
lengthsList, piece_size, piece_hashes, total, privateTorrent,
|
||||
announce_list);
|
||||
|
||||
}
|
||||
|
||||
@@ -1225,7 +1227,7 @@ public class Storage
|
||||
File file = null;
|
||||
FileOutputStream out = null;
|
||||
try {
|
||||
Storage storage = new Storage(util, base, announce, false, null);
|
||||
Storage storage = new Storage(util, base, announce, null, false, null);
|
||||
MetaInfo meta = storage.getMetaInfo();
|
||||
file = new File(storage.getBaseName() + ".torrent");
|
||||
out = new FileOutputStream(file);
|
||||
|
||||
@@ -31,6 +31,7 @@ import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.Date;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
@@ -40,6 +41,7 @@ import java.util.Set;
|
||||
import net.i2p.I2PAppContext;
|
||||
import net.i2p.data.DataHelper;
|
||||
import net.i2p.data.Hash;
|
||||
import net.i2p.util.ConvertToHash;
|
||||
import net.i2p.util.I2PAppThread;
|
||||
import net.i2p.util.Log;
|
||||
import net.i2p.util.SimpleTimer2;
|
||||
@@ -109,8 +111,8 @@ public class TrackerClient implements Runnable {
|
||||
private boolean completed;
|
||||
private volatile boolean _fastUnannounce;
|
||||
private long lastDHTAnnounce;
|
||||
private final List<Tracker> trackers;
|
||||
private final List<Tracker> backupTrackers;
|
||||
private final List<TCTracker> trackers;
|
||||
private final List<TCTracker> backupTrackers;
|
||||
|
||||
/**
|
||||
* Call start() to start it.
|
||||
@@ -270,9 +272,12 @@ public class TrackerClient implements Runnable {
|
||||
primary = meta.getAnnounce();
|
||||
else if (additionalTrackerURL != null)
|
||||
primary = additionalTrackerURL;
|
||||
Set<Hash> trackerHashes = new HashSet(8);
|
||||
|
||||
// primary tracker
|
||||
if (primary != null) {
|
||||
if (isValidAnnounce(primary)) {
|
||||
trackers.add(new Tracker(primary, true));
|
||||
if (isNewValidTracker(trackerHashes, primary)) {
|
||||
trackers.add(new TCTracker(primary, true));
|
||||
if (_log.shouldLog(Log.DEBUG))
|
||||
_log.debug("Announce: [" + primary + "] infoHash: " + infoHash);
|
||||
} else {
|
||||
@@ -281,36 +286,35 @@ public class TrackerClient implements Runnable {
|
||||
}
|
||||
} else {
|
||||
_log.warn("No primary announce");
|
||||
primary = "";
|
||||
}
|
||||
|
||||
// announce list
|
||||
if (meta != null && !meta.isPrivate()) {
|
||||
List<List<String>> list = meta.getAnnounceList();
|
||||
if (list != null) {
|
||||
for (List<String> llist : list) {
|
||||
for (String url : llist) {
|
||||
if (!isNewValidTracker(trackerHashes, url))
|
||||
continue;
|
||||
trackers.add(new TCTracker(url, trackers.isEmpty()));
|
||||
if (_log.shouldLog(Log.DEBUG))
|
||||
_log.debug("Additional announce (list): [" + url + "] for infoHash: " + infoHash);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// configured open trackers
|
||||
if (meta == null || !meta.isPrivate()) {
|
||||
List<String> tlist = _util.getOpenTrackers();
|
||||
for (int i = 0; i < tlist.size(); i++) {
|
||||
String url = tlist.get(i);
|
||||
if (!isValidAnnounce(url)) {
|
||||
_log.error("Bad announce URL: [" + url + "]");
|
||||
String url = tlist.get(i);
|
||||
if (!isNewValidTracker(trackerHashes, url))
|
||||
continue;
|
||||
}
|
||||
int slash = url.indexOf('/', 7);
|
||||
if (slash <= 7) {
|
||||
_log.error("Bad announce URL: [" + url + "]");
|
||||
continue;
|
||||
}
|
||||
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.substring(7, slash) + "]");
|
||||
continue;
|
||||
}
|
||||
if (primary.startsWith("http://" + dest))
|
||||
continue;
|
||||
if (primary.startsWith("http://i2p/" + dest))
|
||||
continue;
|
||||
// opentrackers are primary if we don't have primary
|
||||
trackers.add(new Tracker(url, primary.equals("")));
|
||||
if (_log.shouldLog(Log.DEBUG))
|
||||
_log.debug("Additional announce: [" + url + "] for infoHash: " + infoHash);
|
||||
// opentrackers are primary if we don't have primary
|
||||
trackers.add(new TCTracker(url, trackers.isEmpty()));
|
||||
if (_log.shouldLog(Log.DEBUG))
|
||||
_log.debug("Additional announce: [" + url + "] for infoHash: " + infoHash);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -318,31 +322,40 @@ public class TrackerClient implements Runnable {
|
||||
if (trackers.isEmpty() && (meta == null || !meta.isPrivate())) {
|
||||
List<String> tlist = _util.getBackupTrackers();
|
||||
for (int i = 0; i < tlist.size(); i++) {
|
||||
String url = tlist.get(i);
|
||||
if (!isValidAnnounce(url)) {
|
||||
_log.error("Bad announce URL: [" + url + "]");
|
||||
String url = tlist.get(i);
|
||||
if (!isNewValidTracker(trackerHashes, url))
|
||||
continue;
|
||||
}
|
||||
int slash = url.indexOf('/', 7);
|
||||
if (slash <= 7) {
|
||||
_log.error("Bad announce URL: [" + url + "]");
|
||||
continue;
|
||||
}
|
||||
String dest = _util.lookup(url.substring(7, slash));
|
||||
if (dest == null) {
|
||||
_log.error("Announce host unknown: [" + url.substring(7, slash) + "]");
|
||||
continue;
|
||||
}
|
||||
backupTrackers.add(new Tracker(url, false));
|
||||
if (_log.shouldLog(Log.DEBUG))
|
||||
_log.debug("Backup announce: [" + url + "] for infoHash: " + infoHash);
|
||||
backupTrackers.add(new TCTracker(url, false));
|
||||
if (_log.shouldLog(Log.DEBUG))
|
||||
_log.debug("Backup announce: [" + url + "] for infoHash: " + infoHash);
|
||||
}
|
||||
if (backupTrackers.isEmpty()) {
|
||||
backupTrackers.add(new TCTracker(DEFAULT_BACKUP_TRACKER, false));
|
||||
}
|
||||
if (backupTrackers.isEmpty())
|
||||
backupTrackers.add(new Tracker(DEFAULT_BACKUP_TRACKER, false));
|
||||
}
|
||||
this.completed = coordinator.getLeft() == 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param existing the ones we already know about
|
||||
* @param ann an announce URL non-null
|
||||
* @return true if ann is valid and new; adds to existing if returns true
|
||||
* @since 0.9.5
|
||||
*/
|
||||
private boolean isNewValidTracker(Set<Hash> existing, String ann) {
|
||||
Hash h = getHostHash(ann);
|
||||
if (h == null) {
|
||||
_log.error("Bad announce URL: [" + ann + ']');
|
||||
return false;
|
||||
}
|
||||
boolean rv = existing.add(h);
|
||||
if (!rv) {
|
||||
if (_log.shouldLog(Log.INFO))
|
||||
_log.info("Dup announce URL: [" + ann + ']');
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
/**
|
||||
* Announce to all the trackers, get peers from PEX and DHT, then queue up a SimpleTimer2 event.
|
||||
* This will take several seconds to several minutes.
|
||||
@@ -425,7 +438,7 @@ public class TrackerClient implements Runnable {
|
||||
/**
|
||||
* @return max peers seen
|
||||
*/
|
||||
private int getPeersFromTrackers(List<Tracker> trckrs) {
|
||||
private int getPeersFromTrackers(List<TCTracker> trckrs) {
|
||||
long uploaded = coordinator.getUploaded();
|
||||
long downloaded = coordinator.getDownloaded();
|
||||
long left = coordinator.getLeft(); // -1 in magnet mode
|
||||
@@ -442,7 +455,7 @@ public class TrackerClient implements Runnable {
|
||||
|
||||
// *** loop once for each tracker
|
||||
int maxSeenPeers = 0;
|
||||
for (Tracker tr : trckrs) {
|
||||
for (TCTracker tr : trckrs) {
|
||||
if ((!stop) && (!tr.stop) &&
|
||||
(completed || coordinator.needOutboundPeers() || !tr.started) &&
|
||||
(event.equals(COMPLETED_EVENT) || System.currentTimeMillis() > tr.lastRequestTime + tr.interval))
|
||||
@@ -639,7 +652,7 @@ public class TrackerClient implements Runnable {
|
||||
if (dht != null)
|
||||
dht.unannounce(snark.getInfoHash());
|
||||
int i = 0;
|
||||
for (Tracker tr : trackers) {
|
||||
for (TCTracker tr : trackers) {
|
||||
if (_util.connected() &&
|
||||
tr.started && (!tr.stop) && tr.trackerProblems == null) {
|
||||
try {
|
||||
@@ -659,9 +672,9 @@ public class TrackerClient implements Runnable {
|
||||
* @since 0.9.1
|
||||
*/
|
||||
private class Unannouncer implements Runnable {
|
||||
private final Tracker tr;
|
||||
private final TCTracker tr;
|
||||
|
||||
public Unannouncer(Tracker tr) {
|
||||
public Unannouncer(TCTracker tr) {
|
||||
this.tr = tr;
|
||||
}
|
||||
|
||||
@@ -685,7 +698,7 @@ public class TrackerClient implements Runnable {
|
||||
}
|
||||
}
|
||||
|
||||
private TrackerInfo doRequest(Tracker tr, String infoHash,
|
||||
private TrackerInfo doRequest(TCTracker tr, String infoHash,
|
||||
String peerID, long uploaded,
|
||||
long downloaded, long left, String event)
|
||||
throws IOException
|
||||
@@ -775,6 +788,7 @@ public class TrackerClient implements Runnable {
|
||||
}
|
||||
|
||||
/**
|
||||
* @param ann an announce URL
|
||||
* @return true for i2p hosts only
|
||||
* @since 0.7.12
|
||||
*/
|
||||
@@ -790,10 +804,38 @@ public class TrackerClient implements Runnable {
|
||||
url.getPort() < 0;
|
||||
}
|
||||
|
||||
private static class Tracker
|
||||
/**
|
||||
* @param ann an announce URL non-null
|
||||
* @return a Hash for i2p hosts only, null otherwise
|
||||
* @since 0.9.5
|
||||
*/
|
||||
private static Hash getHostHash(String ann) {
|
||||
URL url;
|
||||
try {
|
||||
url = new URL(ann);
|
||||
} catch (MalformedURLException mue) {
|
||||
return null;
|
||||
}
|
||||
if (url.getPort() >= 0 || !url.getProtocol().equals("http"))
|
||||
return null;
|
||||
String host = url.getHost();
|
||||
if (host.endsWith(".i2p"))
|
||||
return ConvertToHash.getHash(host);
|
||||
if (host.equals("i2p")) {
|
||||
String path = url.getPath();
|
||||
if (path == null || path.length() < 517 ||
|
||||
!path.startsWith("/"))
|
||||
return null;
|
||||
String[] parts = path.substring(1).split("/?&;", 2);
|
||||
return ConvertToHash.getHash(parts[0]);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private static class TCTracker
|
||||
{
|
||||
String announce;
|
||||
boolean isPrimary;
|
||||
final String announce;
|
||||
final boolean isPrimary;
|
||||
long interval;
|
||||
long lastRequestTime;
|
||||
String trackerProblems;
|
||||
@@ -803,7 +845,7 @@ public class TrackerClient implements Runnable {
|
||||
int consecutiveFails;
|
||||
int seenPeers;
|
||||
|
||||
public Tracker(String a, boolean p)
|
||||
public TCTracker(String a, boolean p)
|
||||
{
|
||||
announce = a;
|
||||
isPrimary = p;
|
||||
|
||||
@@ -61,7 +61,7 @@ public class I2PSnarkServlet extends DefaultServlet {
|
||||
private Resource _resourceBase;
|
||||
private String _themePath;
|
||||
private String _imgPath;
|
||||
private String _lastAnnounceURL = "";
|
||||
private String _lastAnnounceURL;
|
||||
|
||||
public static final String PROP_CONFIG_FILE = "i2psnark.configFile";
|
||||
|
||||
@@ -730,18 +730,54 @@ public class I2PSnarkServlet extends DefaultServlet {
|
||||
//if ( (announceURLOther != null) && (announceURLOther.trim().length() > "http://.i2p/announce".length()) )
|
||||
// announceURL = announceURLOther;
|
||||
|
||||
if (announceURL == null || announceURL.length() <= 0)
|
||||
_manager.addMessage(_("Error creating torrent - you must select a tracker"));
|
||||
else if (baseFile.exists()) {
|
||||
_lastAnnounceURL = announceURL;
|
||||
if (baseFile.exists()) {
|
||||
if (announceURL.equals("none"))
|
||||
announceURL = null;
|
||||
_lastAnnounceURL = announceURL;
|
||||
List<String> backupURLs = new ArrayList();
|
||||
Enumeration e = req.getParameterNames();
|
||||
while (e.hasMoreElements()) {
|
||||
Object o = e.nextElement();
|
||||
if (!(o instanceof String))
|
||||
continue;
|
||||
String k = (String) o;
|
||||
if (k.startsWith("backup_")) {
|
||||
String url = k.substring(7);
|
||||
if (!url.equals(announceURL))
|
||||
backupURLs.add(url);
|
||||
}
|
||||
}
|
||||
List<List<String>> announceList = null;
|
||||
if (!backupURLs.isEmpty()) {
|
||||
// BEP 12 - Put primary first, then the others, each as the sole entry in their own list
|
||||
if (announceURL == null) {
|
||||
_manager.addMessage(_("Error - Cannot include alternate trackers without a primary tracker"));
|
||||
return;
|
||||
}
|
||||
backupURLs.add(0, announceURL);
|
||||
boolean hasPrivate = false;
|
||||
boolean hasPublic = false;
|
||||
for (String url : backupURLs) {
|
||||
if (_manager.getPrivateTrackers().contains(announceURL))
|
||||
hasPrivate = true;
|
||||
else
|
||||
hasPublic = true;
|
||||
}
|
||||
if (hasPrivate && hasPublic) {
|
||||
_manager.addMessage(_("Error - Cannot mix private and public trackers in a torrent"));
|
||||
return;
|
||||
}
|
||||
announceList = new ArrayList(backupURLs.size());
|
||||
for (String url : backupURLs) {
|
||||
announceList.add(Collections.singletonList(url));
|
||||
}
|
||||
}
|
||||
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.
|
||||
// TODO thread it for big torrents, perhaps a la FetchAndAdd
|
||||
boolean isPrivate = _manager.getPrivateTrackers().contains(announceURL);
|
||||
Storage s = new Storage(_manager.util(), baseFile, announceURL, isPrivate, null);
|
||||
Storage s = new Storage(_manager.util(), baseFile, announceURL, announceList, 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");
|
||||
@@ -1372,6 +1408,7 @@ public class I2PSnarkServlet extends DefaultServlet {
|
||||
}
|
||||
|
||||
/**
|
||||
* Start of anchor only, caller must add anchor text or img and close anchor
|
||||
* @return string or null
|
||||
* @since 0.8.4
|
||||
*/
|
||||
@@ -1399,6 +1436,7 @@ public class I2PSnarkServlet extends DefaultServlet {
|
||||
}
|
||||
|
||||
/**
|
||||
* Full anchor with img
|
||||
* @return string or null
|
||||
* @since 0.8.4
|
||||
*/
|
||||
@@ -1414,6 +1452,29 @@ public class I2PSnarkServlet extends DefaultServlet {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Full anchor with shortened URL as anchor text
|
||||
* @return string, non-null
|
||||
* @since 0.9.5
|
||||
*/
|
||||
private String getShortTrackerLink(String announce, byte[] infohash) {
|
||||
StringBuilder buf = new StringBuilder(128);
|
||||
String trackerLinkUrl = getTrackerLinkUrl(announce, infohash);
|
||||
if (trackerLinkUrl != null)
|
||||
buf.append(trackerLinkUrl);
|
||||
if (announce.startsWith("http://"))
|
||||
announce = announce.substring(7);
|
||||
int slsh = announce.indexOf('/');
|
||||
if (slsh > 0)
|
||||
announce = announce.substring(0, slsh);
|
||||
if (announce.length() > 67)
|
||||
announce = announce.substring(0, 40) + "…" + announce.substring(announce.length() - 8);
|
||||
buf.append(announce);
|
||||
if (trackerLinkUrl != null)
|
||||
buf.append("</a>");
|
||||
return buf.toString();
|
||||
}
|
||||
|
||||
private void writeAddForm(PrintWriter out, HttpServletRequest req) throws IOException {
|
||||
// display incoming parameter if a GET so links will work
|
||||
String newURL = req.getParameter("newURL");
|
||||
@@ -1482,23 +1543,32 @@ public class I2PSnarkServlet extends DefaultServlet {
|
||||
+ "\" title=\"");
|
||||
out.write(_("File or directory to seed (must be within the specified path)"));
|
||||
out.write("\" ><tr><td>\n");
|
||||
out.write(_("Tracker"));
|
||||
out.write(":<td><select name=\"announceURL\"><option value=\"\">");
|
||||
out.write(_("Select a tracker"));
|
||||
out.write("</option>\n");
|
||||
// todo remember this one with _lastAnnounceURL also
|
||||
out.write("<option value=\"none\">");
|
||||
//out.write(_("Open trackers and DHT only"));
|
||||
out.write(_("Open trackers only"));
|
||||
out.write("</option>\n");
|
||||
out.write(_("Trackers"));
|
||||
out.write(":<td><table style=\"width: 20%;\"><tr><td></td><td align=\"center\">");
|
||||
out.write(_("Primary"));
|
||||
out.write("</td><td align=\"center\">");
|
||||
out.write(_("Alternates"));
|
||||
out.write("</td></tr>\n");
|
||||
for (Tracker t : sortedTrackers) {
|
||||
String name = t.name;
|
||||
String announceURL = t.announceURL.replace("=", "=");
|
||||
out.write("<tr><td>");
|
||||
out.write(name);
|
||||
out.write("</td><td align=\"center\"><input type=\"radio\" name=\"announceURL\" value=\"");
|
||||
out.write(announceURL);
|
||||
out.write("\"");
|
||||
if (announceURL.equals(_lastAnnounceURL))
|
||||
announceURL += "\" selected=\"selected";
|
||||
out.write("\t<option value=\"" + announceURL + "\">" + name + "</option>\n");
|
||||
out.write(" checked");
|
||||
out.write("></td><td align=\"center\"><input type=\"checkbox\" name=\"backup_");
|
||||
out.write(announceURL);
|
||||
out.write("\" value=\"foo\"></td></tr>\n");
|
||||
}
|
||||
out.write("</select>\n");
|
||||
out.write("<tr><td>");
|
||||
out.write(_("none"));
|
||||
out.write("</td><td align=\"center\"><input type=\"radio\" name=\"announceURL\" value=\"none\"");
|
||||
if (_lastAnnounceURL == null)
|
||||
out.write(" checked");
|
||||
out.write("></td><td></td></tr></table>\n");
|
||||
// make the user add a tracker on the config form now
|
||||
//out.write(_("or"));
|
||||
//out.write(" <input type=\"text\" name=\"announceURLOther\" size=\"57\" value=\"http://\" " +
|
||||
@@ -1998,20 +2068,26 @@ public class I2PSnarkServlet extends DefaultServlet {
|
||||
String trackerLink = getTrackerLink(announce, snark.getInfoHash());
|
||||
if (trackerLink != null)
|
||||
buf.append(trackerLink).append(' ');
|
||||
buf.append("<b>").append(_("Tracker")).append(":</b> ");
|
||||
String trackerLinkUrl = getTrackerLinkUrl(announce, snark.getInfoHash());
|
||||
if (trackerLinkUrl != null)
|
||||
buf.append(trackerLinkUrl);
|
||||
if (announce.startsWith("http://"))
|
||||
announce = announce.substring(7);
|
||||
int slsh = announce.indexOf('/');
|
||||
if (slsh > 0)
|
||||
announce = announce.substring(0, slsh);
|
||||
if (announce.length() > 67)
|
||||
announce = announce.substring(0, 40) + "…" + announce.substring(announce.length() - 8);
|
||||
buf.append(announce);
|
||||
if (trackerLinkUrl != null)
|
||||
buf.append("</a>");
|
||||
buf.append("<b>").append(_("Primary Tracker")).append(":</b> ");
|
||||
buf.append(getShortTrackerLink(announce, snark.getInfoHash()));
|
||||
buf.append("</td></tr>");
|
||||
}
|
||||
List<List<String>> alist = meta.getAnnounceList();
|
||||
if (alist != null) {
|
||||
buf.append("<tr><td><b>");
|
||||
buf.append(_("Tracker List")).append(":</b> ");
|
||||
for (List<String> alist2 : alist) {
|
||||
buf.append('[');
|
||||
boolean more = false;
|
||||
for (String s : alist2) {
|
||||
if (more)
|
||||
buf.append(' ');
|
||||
else
|
||||
more = true;
|
||||
buf.append(getShortTrackerLink(s, snark.getInfoHash()));
|
||||
}
|
||||
buf.append("] ");
|
||||
}
|
||||
buf.append("</td></tr>");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -248,7 +248,7 @@
|
||||
<option value="2"<%=(tunnelQuantity == 2 ? " selected=\"selected\"" : "") %>><%=intl._("2 inbound, 2 outbound tunnels (standard bandwidth usage, standard reliability)")%></option>
|
||||
<option value="3"<%=(tunnelQuantity == 3 ? " selected=\"selected\"" : "") %>><%=intl._("3 inbound, 3 outbound tunnels (higher bandwidth usage, higher reliability)")%></option>
|
||||
<% if (tunnelQuantity > 3) {
|
||||
%> <option value="<%=tunnelQuantity%>" selected="selected"><%=tunnelQuantity%> <%=intl._("tunnels")%></option>
|
||||
%> <option value="<%=tunnelQuantity%>" selected="selected"><%=tunnelQuantity%> <%=intl._("tunnels")%></option>
|
||||
<% }
|
||||
%></select>
|
||||
</div>
|
||||
|
||||
@@ -264,8 +264,11 @@
|
||||
%><option value="1"<%=(tunnelQuantity == 1 ? " selected=\"selected\"" : "") %>><%=intl._("1 inbound, 1 outbound tunnel (low bandwidth usage, less reliability)")%></option>
|
||||
<option value="2"<%=(tunnelQuantity == 2 ? " selected=\"selected\"" : "") %>><%=intl._("2 inbound, 2 outbound tunnels (standard bandwidth usage, standard reliability)")%></option>
|
||||
<option value="3"<%=(tunnelQuantity == 3 ? " selected=\"selected\"" : "") %>><%=intl._("3 inbound, 3 outbound tunnels (higher bandwidth usage, higher reliability)")%></option>
|
||||
<% if (tunnelQuantity > 3) {
|
||||
%> <option value="<%=tunnelQuantity%>" selected="selected"><%=tunnelQuantity%> <%=intl._("tunnels")%></option>
|
||||
<option value="4"<%=(tunnelQuantity == 4 ? " selected=\"selected\"" : "") %>><%=intl._("4 in, 4 out (high traffic server)")%></option>
|
||||
<option value="5"<%=(tunnelQuantity == 5 ? " selected=\"selected\"" : "") %>><%=intl._("5 in, 5 out (high traffic server)")%></option>
|
||||
<option value="6"<%=(tunnelQuantity == 6 ? " selected=\"selected\"" : "") %>><%=intl._("6 in, 6 out (high traffic server)")%></option>
|
||||
<% if (tunnelQuantity > 6) {
|
||||
%> <option value="<%=tunnelQuantity%>" selected="selected"><%=tunnelQuantity%> <%=intl._("tunnels")%></option>
|
||||
<% }
|
||||
%></select>
|
||||
</div>
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
Apache Tomcat
|
||||
Copyright 1999-2011 The Apache Software Foundation
|
||||
Copyright 1999-2012 The Apache Software Foundation
|
||||
|
||||
This product includes software developed by
|
||||
The Apache Software Foundation (http://www.apache.org/).
|
||||
|
||||
@@ -2,7 +2,7 @@ This is Apache Tomcat 6.x, supporting Servlet 2.5 and JSP 2.1.
|
||||
The Glassfish JSP 2.1 bundled in Jetty 6 is way too old.
|
||||
|
||||
Retrieved from the file
|
||||
apache-tomcat-6.0.35-deployer.tar.gz
|
||||
apache-tomcat-6.0.36-deployer.tar.gz
|
||||
|
||||
minus the following files and directores:
|
||||
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Reference in New Issue
Block a user