forked from I2P_Developers/i2p.i2p
propagate from branch 'i2p.i2p.zzz.test2' (head 8fa44268a1dd2b7baaf01806e6994281ab031870)
to branch 'i2p.i2p' (head 44afdaa15ce8a95c112c7d58a5908f401c1a0145)
This commit is contained in:
@ -3,8 +3,8 @@ package org.klomp.snark;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URL;
|
||||
import java.net.URI;
|
||||
import java.net.URISyntaxException;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
@ -590,10 +590,10 @@ public class I2PSnarkUtil {
|
||||
*/
|
||||
public boolean isKnownOpenTracker(String url) {
|
||||
try {
|
||||
URL u = new URL(url);
|
||||
URI u = new URI(url);
|
||||
String host = u.getHost();
|
||||
return host != null && SnarkManager.KNOWN_OPENTRACKERS.contains(host);
|
||||
} catch (MalformedURLException mue) {
|
||||
} catch (URISyntaxException use) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -62,7 +62,7 @@ public class Peer implements Comparable<Peer>
|
||||
|
||||
// Keeps state for in/out connections. Non-null when the handshake
|
||||
// was successful, the connection setup and runs
|
||||
PeerState state;
|
||||
volatile PeerState state;
|
||||
|
||||
/** shared across all peers on this torrent */
|
||||
MagnetState magnetState;
|
||||
|
@ -39,7 +39,7 @@ class PeerConnectionIn implements Runnable
|
||||
private static final int MAX_MSG_SIZE = Math.max(PeerState.PARTSIZE + 9,
|
||||
MagnetState.CHUNK_SIZE + 100); // 100 for the ext msg dictionary
|
||||
|
||||
private Thread thread;
|
||||
private volatile Thread thread;
|
||||
private volatile boolean quit;
|
||||
|
||||
long lastRcvd;
|
||||
@ -75,9 +75,12 @@ class PeerConnectionIn implements Runnable
|
||||
thread = Thread.currentThread();
|
||||
try
|
||||
{
|
||||
PeerState ps = peer.state;
|
||||
while (!quit && ps != null)
|
||||
while (!quit)
|
||||
{
|
||||
final PeerState ps = peer.state;
|
||||
if (ps == null)
|
||||
break;
|
||||
|
||||
// Common variables used for some messages.
|
||||
int piece;
|
||||
int begin;
|
||||
@ -91,9 +94,9 @@ class PeerConnectionIn implements Runnable
|
||||
|
||||
if (i == 0)
|
||||
{
|
||||
ps.keepAliveMessage();
|
||||
if (_log.shouldLog(Log.DEBUG))
|
||||
_log.debug("Received keepalive from " + peer);
|
||||
ps.keepAliveMessage();
|
||||
continue;
|
||||
}
|
||||
|
||||
@ -101,51 +104,51 @@ class PeerConnectionIn implements Runnable
|
||||
switch (b)
|
||||
{
|
||||
case Message.CHOKE:
|
||||
ps.chokeMessage(true);
|
||||
if (_log.shouldLog(Log.DEBUG))
|
||||
_log.debug("Received choke from " + peer);
|
||||
ps.chokeMessage(true);
|
||||
break;
|
||||
|
||||
case Message.UNCHOKE:
|
||||
ps.chokeMessage(false);
|
||||
if (_log.shouldLog(Log.DEBUG))
|
||||
_log.debug("Received unchoke from " + peer);
|
||||
ps.chokeMessage(false);
|
||||
break;
|
||||
|
||||
case Message.INTERESTED:
|
||||
ps.interestedMessage(true);
|
||||
if (_log.shouldLog(Log.DEBUG))
|
||||
_log.debug("Received interested from " + peer);
|
||||
ps.interestedMessage(true);
|
||||
break;
|
||||
|
||||
case Message.UNINTERESTED:
|
||||
ps.interestedMessage(false);
|
||||
if (_log.shouldLog(Log.DEBUG))
|
||||
_log.debug("Received not interested from " + peer);
|
||||
ps.interestedMessage(false);
|
||||
break;
|
||||
|
||||
case Message.HAVE:
|
||||
piece = din.readInt();
|
||||
ps.haveMessage(piece);
|
||||
if (_log.shouldLog(Log.DEBUG))
|
||||
_log.debug("Received havePiece(" + piece + ") from " + peer);
|
||||
ps.haveMessage(piece);
|
||||
break;
|
||||
|
||||
case Message.BITFIELD:
|
||||
byte[] bitmap = new byte[i-1];
|
||||
din.readFully(bitmap);
|
||||
ps.bitfieldMessage(bitmap);
|
||||
if (_log.shouldLog(Log.DEBUG))
|
||||
_log.debug("Received bitmap from " + peer + ": size=" + (i-1) /* + ": " + ps.bitfield */ );
|
||||
ps.bitfieldMessage(bitmap);
|
||||
break;
|
||||
|
||||
case Message.REQUEST:
|
||||
piece = din.readInt();
|
||||
begin = din.readInt();
|
||||
len = din.readInt();
|
||||
ps.requestMessage(piece, begin, len);
|
||||
if (_log.shouldLog(Log.DEBUG))
|
||||
_log.debug("Received request(" + piece + "," + begin + ") from " + peer);
|
||||
ps.requestMessage(piece, begin, len);
|
||||
break;
|
||||
|
||||
case Message.PIECE:
|
||||
@ -156,9 +159,9 @@ class PeerConnectionIn implements Runnable
|
||||
if (req != null)
|
||||
{
|
||||
req.read(din);
|
||||
ps.pieceMessage(req);
|
||||
if (_log.shouldLog(Log.DEBUG))
|
||||
_log.debug("Received data(" + piece + "," + begin + ") from " + peer);
|
||||
ps.pieceMessage(req);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -175,16 +178,16 @@ class PeerConnectionIn implements Runnable
|
||||
piece = din.readInt();
|
||||
begin = din.readInt();
|
||||
len = din.readInt();
|
||||
ps.cancelMessage(piece, begin, len);
|
||||
if (_log.shouldLog(Log.DEBUG))
|
||||
_log.debug("Received cancel(" + piece + "," + begin + ") from " + peer);
|
||||
ps.cancelMessage(piece, begin, len);
|
||||
break;
|
||||
|
||||
case Message.PORT:
|
||||
int port = din.readUnsignedShort();
|
||||
ps.portMessage(port);
|
||||
if (_log.shouldLog(Log.DEBUG))
|
||||
_log.debug("Received port message from " + peer);
|
||||
ps.portMessage(port);
|
||||
break;
|
||||
|
||||
case Message.EXTENSION:
|
||||
@ -247,11 +250,9 @@ class PeerConnectionIn implements Runnable
|
||||
if (_log.shouldLog(Log.INFO))
|
||||
_log.info("IOError talking with " + peer, ioe);
|
||||
}
|
||||
catch (Throwable t)
|
||||
catch (RuntimeException t)
|
||||
{
|
||||
_log.error("Error talking with " + peer, t);
|
||||
if (t instanceof OutOfMemoryError)
|
||||
throw (OutOfMemoryError)t;
|
||||
}
|
||||
finally
|
||||
{
|
||||
|
@ -911,6 +911,30 @@ public class Snark
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Bytes not received and set to skipped.
|
||||
* This is not the same as the total of all skipped files,
|
||||
* since pieces may span multiple files.
|
||||
*
|
||||
* @return exact value. or 0 if no storage yet.
|
||||
* @since 0.9.24
|
||||
*/
|
||||
public long getSkippedLength() {
|
||||
PeerCoordinator coord = coordinator;
|
||||
if (coord != null) {
|
||||
// fast way
|
||||
long r = getRemainingLength();
|
||||
if (r <= 0)
|
||||
return 0;
|
||||
long n = coord.getNeededLength();
|
||||
return r - n;
|
||||
} else if (storage != null) {
|
||||
// slow way
|
||||
return storage.getSkippedLength();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Does not account (i.e. includes) for skipped files.
|
||||
* @return number of pieces still needed (magnet mode or not), or -1 if unknown
|
||||
|
@ -189,7 +189,7 @@ public class SnarkManager implements CompleteListener {
|
||||
for (int i = 1; i < DEFAULT_TRACKERS.length; i += 2) {
|
||||
if (DEFAULT_TRACKERS[i-1].equals("TheBland") && !SigType.ECDSA_SHA256_P256.isAvailable())
|
||||
continue;
|
||||
String urls[] = DEFAULT_TRACKERS[i].split("=", 2);
|
||||
String urls[] = DataHelper.split(DEFAULT_TRACKERS[i], "=", 2);
|
||||
ann.add(urls[0]);
|
||||
}
|
||||
DEFAULT_TRACKER_ANNOUNCES = Collections.unmodifiableSet(ann);
|
||||
@ -1078,7 +1078,7 @@ public class SnarkManager implements CompleteListener {
|
||||
val = dflt;
|
||||
if (val == null)
|
||||
return Collections.emptyList();
|
||||
return Arrays.asList(val.split(","));
|
||||
return Arrays.asList(DataHelper.split(val, ","));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1611,7 +1611,7 @@ public class SnarkManager implements CompleteListener {
|
||||
return;
|
||||
int filecount = metainfo.getFiles().size();
|
||||
int[] rv = new int[filecount];
|
||||
String[] arr = pri.split(",");
|
||||
String[] arr = DataHelper.split(pri, ",");
|
||||
for (int i = 0; i < filecount && i < arr.length; i++) {
|
||||
if (arr[i].length() > 0) {
|
||||
try {
|
||||
@ -2051,7 +2051,7 @@ public class SnarkManager implements CompleteListener {
|
||||
synchronized (_snarks) {
|
||||
ok = monitorTorrents(dir);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
} catch (RuntimeException e) {
|
||||
_log.error("Error in the DirectoryMonitor", e);
|
||||
ok = false;
|
||||
}
|
||||
@ -2060,7 +2060,7 @@ public class SnarkManager implements CompleteListener {
|
||||
try {
|
||||
addMagnets();
|
||||
doMagnets = false;
|
||||
} catch (Exception e) {
|
||||
} catch (RuntimeException e) {
|
||||
_log.error("Error in the DirectoryMonitor", e);
|
||||
}
|
||||
if (!_snarks.isEmpty())
|
||||
@ -2266,7 +2266,7 @@ public class SnarkManager implements CompleteListener {
|
||||
// Snark.fatal() throws a RuntimeException
|
||||
// don't let one bad torrent kill the whole loop
|
||||
addTorrent(name, null, !shouldAutoStart());
|
||||
} catch (Exception e) {
|
||||
} catch (RuntimeException e) {
|
||||
addMessage(_t("Error: Could not add the torrent {0}", name) + ": " + e);
|
||||
_log.error("Unable to add the torrent " + name, e);
|
||||
rv = false;
|
||||
@ -2285,7 +2285,7 @@ public class SnarkManager implements CompleteListener {
|
||||
// Snark.fatal() throws a RuntimeException
|
||||
// don't let one bad torrent kill the whole loop
|
||||
stopTorrent(name, true);
|
||||
} catch (Exception e) {
|
||||
} catch (RuntimeException e) {
|
||||
// don't bother with message
|
||||
}
|
||||
}
|
||||
@ -2342,12 +2342,12 @@ public class SnarkManager implements CompleteListener {
|
||||
if ( (trackers == null) || (trackers.trim().length() <= 0) ) {
|
||||
setDefaultTrackerMap(true);
|
||||
} else {
|
||||
String[] toks = trackers.split(",");
|
||||
String[] toks = DataHelper.split(trackers, ",");
|
||||
for (int i = 0; i < toks.length; i += 2) {
|
||||
String name = toks[i].trim().replace(",", ",");
|
||||
String url = toks[i+1].trim().replace(",", ",");
|
||||
if ( (name.length() > 0) && (url.length() > 0) ) {
|
||||
String urls[] = url.split("=", 2);
|
||||
String urls[] = DataHelper.split(url, "=", 2);
|
||||
String url2 = urls.length > 1 ? urls[1] : "";
|
||||
_trackerMap.put(name, new Tracker(name, urls[0], url2));
|
||||
}
|
||||
@ -2367,7 +2367,7 @@ public class SnarkManager implements CompleteListener {
|
||||
String name = DEFAULT_TRACKERS[i];
|
||||
if (name.equals("TheBland") && !SigType.ECDSA_SHA256_P256.isAvailable())
|
||||
continue;
|
||||
String urls[] = DEFAULT_TRACKERS[i+1].split("=", 2);
|
||||
String urls[] = DataHelper.split(DEFAULT_TRACKERS[i+1], "=", 2);
|
||||
String url2 = urls.length > 1 ? urls[1] : null;
|
||||
_trackerMap.put(name, new Tracker(name, urls[0], url2));
|
||||
}
|
||||
@ -2467,7 +2467,7 @@ public class SnarkManager implements CompleteListener {
|
||||
public void run() {
|
||||
try {
|
||||
run2();
|
||||
} catch (Exception e) {
|
||||
} catch (RuntimeException e) {
|
||||
_log.error("Error starting", e);
|
||||
}
|
||||
}
|
||||
@ -2595,7 +2595,7 @@ public class SnarkManager implements CompleteListener {
|
||||
} else {
|
||||
addMessageNoEscape(_t("Finished recheck of torrent {0}, unchanged", link));
|
||||
}
|
||||
} catch (Exception e) {
|
||||
} catch (IOException e) {
|
||||
_log.error("Error rechecking " + snark.getBaseName(), e);
|
||||
addMessage(_t("Error checking the torrent {0}", snark.getBaseName()) + ": " + e);
|
||||
}
|
||||
|
@ -518,6 +518,31 @@ public class Storage implements Closeable
|
||||
return rv;
|
||||
}
|
||||
|
||||
/**
|
||||
* Call setPriority() for all changed files first,
|
||||
* then call this.
|
||||
* The length of all the pieces that are not yet downloaded,
|
||||
* and are set to skipped.
|
||||
* This is not the same as the total of all skipped files,
|
||||
* since pieces may span multiple files.
|
||||
*
|
||||
* @return 0 on error, if complete, or if only one file
|
||||
* @since 0.9.24
|
||||
*/
|
||||
public long getSkippedLength() {
|
||||
int[] pri = getPiecePriorities();
|
||||
if (pri == null)
|
||||
return 0;
|
||||
long rv = 0;
|
||||
final int end = pri.length - 1;
|
||||
for (int i = 0; i <= end; i++) {
|
||||
if (pri[i] <= -9 && !bitfield.get(i)) {
|
||||
rv += (i != end) ? piece_size : metainfo.getPieceLength(i);
|
||||
}
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
/**
|
||||
* The BitField that tells which pieces this storage contains.
|
||||
* Do not change this since this is the current state of the storage.
|
||||
@ -748,7 +773,7 @@ public class Storage implements Closeable
|
||||
}
|
||||
rv = repl;
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
} catch (RuntimeException ex) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
}
|
||||
@ -1483,7 +1508,7 @@ public class Storage implements Closeable
|
||||
break;
|
||||
} // switch
|
||||
} // while
|
||||
} catch (Exception e) {
|
||||
} catch (RuntimeException e) {
|
||||
e.printStackTrace();
|
||||
error = true;
|
||||
}
|
||||
|
@ -23,8 +23,8 @@ package org.klomp.snark;
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URL;
|
||||
import java.net.URI;
|
||||
import java.net.URISyntaxException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
@ -875,18 +875,20 @@ public class TrackerClient implements Runnable {
|
||||
}
|
||||
|
||||
/**
|
||||
* @param ann an announce URL
|
||||
* @param ann an announce URL, may be null, returns false if null
|
||||
* @return true for i2p hosts only
|
||||
* @since 0.7.12
|
||||
*/
|
||||
public static boolean isValidAnnounce(String ann) {
|
||||
URL url;
|
||||
if (ann == null)
|
||||
return false;
|
||||
URI url;
|
||||
try {
|
||||
url = new URL(ann);
|
||||
} catch (MalformedURLException mue) {
|
||||
return false;
|
||||
url = new URI(ann);
|
||||
} catch (URISyntaxException use) {
|
||||
return false;
|
||||
}
|
||||
return url.getProtocol().equals("http") &&
|
||||
return "http".equals(url.getScheme()) && url.getHost() != null &&
|
||||
(url.getHost().endsWith(".i2p") || url.getHost().equals("i2p"));
|
||||
}
|
||||
|
||||
@ -896,13 +898,13 @@ public class TrackerClient implements Runnable {
|
||||
* @since 0.9.5
|
||||
*/
|
||||
private static Hash getHostHash(String ann) {
|
||||
URL url;
|
||||
URI url;
|
||||
try {
|
||||
url = new URL(ann);
|
||||
} catch (MalformedURLException mue) {
|
||||
url = new URI(ann);
|
||||
} catch (URISyntaxException use) {
|
||||
return null;
|
||||
}
|
||||
if (!url.getProtocol().equals("http"))
|
||||
if (!"http".equals(url.getScheme()))
|
||||
return null;
|
||||
String host = url.getHost();
|
||||
if (host.endsWith(".i2p"))
|
||||
@ -912,7 +914,7 @@ public class TrackerClient implements Runnable {
|
||||
if (path == null || path.length() < 517 ||
|
||||
!path.startsWith("/"))
|
||||
return null;
|
||||
String[] parts = path.substring(1).split("[/\\?&;]", 2);
|
||||
String[] parts = DataHelper.split(path.substring(1), "[/\\?&;]", 2);
|
||||
return ConvertToHash.getHash(parts[0]);
|
||||
}
|
||||
return null;
|
||||
|
@ -102,7 +102,7 @@ class NodeInfo extends SimpleDataStructure {
|
||||
*/
|
||||
public NodeInfo(String s) throws DataFormatException {
|
||||
super();
|
||||
String[] parts = s.split(":", 4);
|
||||
String[] parts = DataHelper.split(s, ":", 4);
|
||||
if (parts.length != 4)
|
||||
throw new DataFormatException("Bad format");
|
||||
byte[] nid = Base64.decode(parts[0]);
|
||||
@ -225,7 +225,7 @@ class NodeInfo extends SimpleDataStructure {
|
||||
NodeInfo ni = (NodeInfo) o;
|
||||
// assume dest matches, ignore it
|
||||
return this.hash.equals(ni.hash) && nID.equals(ni.nID) && port == ni.port;
|
||||
} catch (Exception e) {
|
||||
} catch (RuntimeException e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -18,7 +18,6 @@ import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.TimeZone;
|
||||
import java.util.TreeMap;
|
||||
|
||||
import javax.servlet.ServletConfig;
|
||||
@ -2714,7 +2713,7 @@ public class I2PSnarkServlet extends BasicServlet {
|
||||
if (snark != null) {
|
||||
// first table - torrent info
|
||||
buf.append("<table class=\"snarkTorrentInfo\">\n");
|
||||
buf.append("<tr><th><b>")
|
||||
buf.append("<tr><th></th><th><b>")
|
||||
.append(_t("Torrent"))
|
||||
.append(":</b> ")
|
||||
.append(DataHelper.escapeHTML(snark.getBaseName()))
|
||||
@ -2724,7 +2723,7 @@ public class I2PSnarkServlet extends BasicServlet {
|
||||
String baseName = encodePath((new File(fullPath)).getName());
|
||||
buf.append("<tr><td>");
|
||||
toThemeImg(buf, "file");
|
||||
buf.append(" <b>")
|
||||
buf.append("</td><td><b>")
|
||||
.append(_t("Torrent file"))
|
||||
.append(":</b> <a href=\"").append(_contextPath).append('/').append(baseName).append("\">")
|
||||
.append(DataHelper.escapeHTML(fullPath))
|
||||
@ -2732,7 +2731,7 @@ public class I2PSnarkServlet extends BasicServlet {
|
||||
if (snark.getStorage() != null) {
|
||||
buf.append("<tr><td>");
|
||||
toThemeImg(buf, "file");
|
||||
buf.append(" <b>")
|
||||
buf.append("</td><td><b>")
|
||||
.append(_t("Data location"))
|
||||
.append(":</b> ")
|
||||
.append(DataHelper.escapeHTML(snark.getStorage().getBase().getPath()))
|
||||
@ -2741,7 +2740,7 @@ public class I2PSnarkServlet extends BasicServlet {
|
||||
String hex = I2PSnarkUtil.toHex(snark.getInfoHash());
|
||||
buf.append("<tr><td>");
|
||||
toThemeImg(buf, "details");
|
||||
buf.append(" <b>")
|
||||
buf.append("</td><td><b>")
|
||||
.append(_t("Info hash"))
|
||||
.append(":</b> ")
|
||||
.append(hex.toUpperCase(Locale.US))
|
||||
@ -2761,7 +2760,7 @@ public class I2PSnarkServlet extends BasicServlet {
|
||||
buf.append(trackerLink);
|
||||
else
|
||||
toThemeImg(buf, "details");
|
||||
buf.append(" <b>").append(_t("Primary Tracker")).append(":</b> ");
|
||||
buf.append("</td><td><b>").append(_t("Primary Tracker")).append(":</b> ");
|
||||
buf.append(getShortTrackerLink(announce, snark.getInfoHash()));
|
||||
buf.append("</td></tr>");
|
||||
}
|
||||
@ -2769,7 +2768,7 @@ public class I2PSnarkServlet extends BasicServlet {
|
||||
if (alist != null && !alist.isEmpty()) {
|
||||
buf.append("<tr><td>");
|
||||
toThemeImg(buf, "details");
|
||||
buf.append(" <b>")
|
||||
buf.append("</td><td valign=\"top\"><b>")
|
||||
.append(_t("Tracker List")).append(":</b> ");
|
||||
for (List<String> alist2 : alist) {
|
||||
buf.append('[');
|
||||
@ -2794,21 +2793,19 @@ public class I2PSnarkServlet extends BasicServlet {
|
||||
com = com.substring(0, 1024);
|
||||
buf.append("<tr><td>");
|
||||
toThemeImg(buf, "details");
|
||||
buf.append(" <b>")
|
||||
buf.append("</td><td><b>")
|
||||
.append(_t("Comment")).append(":</b> ")
|
||||
.append(DataHelper.stripHTML(com))
|
||||
.append("</td></tr>\n");
|
||||
}
|
||||
long dat = meta.getCreationDate();
|
||||
SimpleDateFormat fmt = new SimpleDateFormat("yyyy-MM-dd HH:mm");
|
||||
String systemTimeZone = _context.getProperty("i2p.systemTimeZone");
|
||||
if (systemTimeZone != null)
|
||||
fmt.setTimeZone(TimeZone.getTimeZone(systemTimeZone));
|
||||
fmt.setTimeZone(DataHelper.getSystemTimeZone(_context));
|
||||
if (dat > 0) {
|
||||
String date = fmt.format(new Date(dat));
|
||||
buf.append("<tr><td>");
|
||||
toThemeImg(buf, "details");
|
||||
buf.append(" <b>")
|
||||
buf.append("</td><td><b>")
|
||||
.append(_t("Created")).append(":</b> ")
|
||||
.append(date)
|
||||
.append("</td></tr>\n");
|
||||
@ -2819,7 +2816,7 @@ public class I2PSnarkServlet extends BasicServlet {
|
||||
cby = com.substring(0, 128);
|
||||
buf.append("<tr><td>");
|
||||
toThemeImg(buf, "details");
|
||||
buf.append(" <b>")
|
||||
buf.append("</td><td><b>")
|
||||
.append(_t("Created By")).append(":</b> ")
|
||||
.append(DataHelper.stripHTML(cby))
|
||||
.append("</td></tr>\n");
|
||||
@ -2829,7 +2826,7 @@ public class I2PSnarkServlet extends BasicServlet {
|
||||
String date = fmt.format(new Date(dates[0]));
|
||||
buf.append("<tr><td>");
|
||||
toThemeImg(buf, "details");
|
||||
buf.append(" <b>")
|
||||
buf.append("</td><td><b>")
|
||||
.append(_t("Added")).append(":</b> ")
|
||||
.append(date)
|
||||
.append("</td></tr>\n");
|
||||
@ -2838,7 +2835,7 @@ public class I2PSnarkServlet extends BasicServlet {
|
||||
String date = fmt.format(new Date(dates[1]));
|
||||
buf.append("<tr><td>");
|
||||
toThemeImg(buf, "details");
|
||||
buf.append(" <b>")
|
||||
buf.append("</td><td><b>")
|
||||
.append(_t("Completed")).append(":</b> ")
|
||||
.append(date)
|
||||
.append("</td></tr>\n");
|
||||
@ -2852,7 +2849,7 @@ public class I2PSnarkServlet extends BasicServlet {
|
||||
buf.append("&tr=").append(announce);
|
||||
buf.append("\">")
|
||||
.append(toImg("magnet", _t("Magnet link")))
|
||||
.append("</a> <b>Magnet:</b> <a href=\"")
|
||||
.append("</a></td><td><b>Magnet:</b> <a href=\"")
|
||||
.append(MagnetURI.MAGNET_FULL).append(hex);
|
||||
if (announce != null)
|
||||
buf.append("&tr=").append(announce);
|
||||
@ -2863,7 +2860,9 @@ public class I2PSnarkServlet extends BasicServlet {
|
||||
buf.append("</a>")
|
||||
.append("</td></tr>\n");
|
||||
} else {
|
||||
buf.append("<tr><td>")
|
||||
buf.append("<tr><td>");
|
||||
toThemeImg(buf, "details");
|
||||
buf.append("</td><td><b>")
|
||||
.append(_t("Private torrent"))
|
||||
.append("</td></tr>\n");
|
||||
}
|
||||
@ -2874,7 +2873,7 @@ public class I2PSnarkServlet extends BasicServlet {
|
||||
|
||||
buf.append("<tr><td>");
|
||||
toThemeImg(buf, "size");
|
||||
buf.append(" <b>")
|
||||
buf.append("</td><td><b>")
|
||||
.append(_t("Size"))
|
||||
.append(":</b> ")
|
||||
.append(formatSize(snark.getTotalLength()));
|
||||
@ -2917,6 +2916,15 @@ public class I2PSnarkServlet extends BasicServlet {
|
||||
.append(":</b> ")
|
||||
.append(formatSize(needed));
|
||||
}
|
||||
long skipped = snark.getSkippedLength();
|
||||
if (skipped > 0) {
|
||||
buf.append(" ");
|
||||
toThemeImg(buf, "head_rx");
|
||||
buf.append(" <b>")
|
||||
.append(_t("Skipped"))
|
||||
.append(":</b> ")
|
||||
.append(formatSize(skipped));
|
||||
}
|
||||
if (meta != null) {
|
||||
List<List<String>> files = meta.getFiles();
|
||||
int fileCount = files != null ? files.size() : 1;
|
||||
@ -2943,20 +2951,19 @@ public class I2PSnarkServlet extends BasicServlet {
|
||||
|
||||
// buttons
|
||||
if (showStopStart) {
|
||||
buf.append("<tr><td>");
|
||||
toThemeImg(buf, "file");
|
||||
buf.append("<tr><td></td><td>");
|
||||
if (snark.isChecking()) {
|
||||
buf.append(" <b>").append(_t("Checking")).append("… ")
|
||||
buf.append("<b>").append(_t("Checking")).append("… ")
|
||||
.append((new DecimalFormat("0.00%")).format(snark.getCheckingProgress()))
|
||||
.append(" <a href=\"").append(base).append("\">")
|
||||
.append(_t("Refresh page for results")).append("</a>");
|
||||
} else if (snark.isStarting()) {
|
||||
buf.append(" <b>").append(_t("Starting")).append("…</b>");
|
||||
buf.append("<b>").append(_t("Starting")).append("…</b>");
|
||||
} else if (snark.isAllocating()) {
|
||||
buf.append(" <b>").append(_t("Allocating")).append("…</b>");
|
||||
buf.append("<b>").append(_t("Allocating")).append("…</b>");
|
||||
} else {
|
||||
boolean isRunning = !snark.isStopped();
|
||||
buf.append(" <input type=\"submit\" value=\"");
|
||||
buf.append("<input type=\"submit\" value=\"");
|
||||
if (isRunning)
|
||||
buf.append(_t("Stop")).append("\" name=\"stop\" class=\"stoptorrent\">\n");
|
||||
else
|
||||
|
Reference in New Issue
Block a user