merge of '01966a37ff4e50e48ab6eeb9d215baa8b75fc46d'

and '85cbdd70a9896ae9b2257bfe8f25f045b1cd0b2d'
This commit is contained in:
HungryHobo
2010-11-04 04:24:23 +00:00
3 changed files with 220 additions and 86 deletions

View File

@ -133,6 +133,7 @@ public class I2PSnarkServlet extends Default {
// bypass the horrid Resource.getListHTML() // bypass the horrid Resource.getListHTML()
String pathInfo = req.getPathInfo(); String pathInfo = req.getPathInfo();
String pathInContext = URI.addPaths(path, pathInfo); String pathInContext = URI.addPaths(path, pathInfo);
req.setCharacterEncoding("UTF-8");
resp.setCharacterEncoding("UTF-8"); resp.setCharacterEncoding("UTF-8");
resp.setContentType("text/html; charset=UTF-8"); resp.setContentType("text/html; charset=UTF-8");
Resource resource = getResource(pathInContext); Resource resource = getResource(pathInContext);
@ -140,7 +141,7 @@ public class I2PSnarkServlet extends Default {
resp.sendError(HttpResponse.__404_Not_Found); resp.sendError(HttpResponse.__404_Not_Found);
} else { } else {
String base = URI.addPaths(req.getRequestURI(), "/"); String base = URI.addPaths(req.getRequestURI(), "/");
String listing = getListHTML(resource, base, true); String listing = getListHTML(resource, base, true, method.equals("POST") ? req.getParameterMap() : null);
if (listing != null) if (listing != null)
resp.getWriter().write(listing); resp.getWriter().write(listing);
else // shouldn't happen else // shouldn't happen
@ -170,7 +171,7 @@ public class I2PSnarkServlet extends Default {
PrintWriter out = resp.getWriter(); PrintWriter out = resp.getWriter();
out.write("<html>\n" + out.write("<html>\n" +
"<head>\n" + "<head><link rel=\"shortcut icon\" href=\"/themes/snark/ubergine/favicon.ico\">\n" +
"<title>"); "<title>");
out.write(_("I2PSnark - Anonymous BitTorrent Client")); out.write(_("I2PSnark - Anonymous BitTorrent Client"));
out.write("</title>\n"); out.write("</title>\n");
@ -191,6 +192,7 @@ public class I2PSnarkServlet extends Default {
out.write("<div class=\"snarknavbar\"><a href=\"" + req.getRequestURI() + peerString + "\" title=\""); out.write("<div class=\"snarknavbar\"><a href=\"" + req.getRequestURI() + peerString + "\" title=\"");
out.write(_("Refresh page")); out.write(_("Refresh page"));
out.write("\" class=\"snarkRefresh\">"); out.write("\" class=\"snarkRefresh\">");
out.write("<img border=\"0\" src=\"/themes/snark/ubergine/images/arrow_refresh.png\"> ");
out.write(_("I2PSnark")); out.write(_("I2PSnark"));
out.write("</a> <a href=\"http://forum.i2p/viewforum.php?f=21\" class=\"snarkRefresh\" target=\"_blank\">"); out.write("</a> <a href=\"http://forum.i2p/viewforum.php?f=21\" class=\"snarkRefresh\" target=\"_blank\">");
out.write(_("Forum")); out.write(_("Forum"));
@ -218,7 +220,7 @@ public class I2PSnarkServlet extends Default {
out.write("</pre></td></tr></table></div>"); out.write("</pre></td></tr></table></div>");
if (isConfigure) { if (isConfigure) {
out.write("</div>\n"); out.write("<div class=\"logshim\"></div></div>\n");
writeConfigForm(out, req); writeConfigForm(out, req);
} else { } else {
writeTorrents(out, req); writeTorrents(out, req);
@ -238,47 +240,81 @@ public class I2PSnarkServlet extends Default {
List snarks = getSortedSnarks(req); List snarks = getSortedSnarks(req);
String uri = req.getRequestURI(); String uri = req.getRequestURI();
out.write(TABLE_HEADER); out.write(TABLE_HEADER);
out.write("<img border=\"0\" src=\"/themes/snark/ubergine/images/status.png\"");
out.write(" title=\"");
out.write(_("Status"));
out.write("\"> ");
out.write(_("Status")); out.write(_("Status"));
if (_manager.util().connected() && !snarks.isEmpty()) { if (_manager.util().connected() && !snarks.isEmpty()) {
out.write(" (<a href=\""); out.write(" <a href=\"");
out.write(req.getRequestURI()); out.write(req.getRequestURI());
if (peerParam != null) { if (peerParam != null) {
out.write("\">"); out.write("\">");
out.write("<img border=\"0\" src=\"/themes/snark/ubergine/images/showpeers.png\" title=\"");
out.write(_("Hide Peers")); out.write(_("Hide Peers"));
out.write("\" alt=\"");
out.write(_("Hide Peers"));
out.write("\">");
} else { } else {
out.write("?p=1\">"); out.write("?p=1\">");
out.write("<img border=\"0\" src=\"/themes/snark/ubergine/images/hidepeers.png\" title=\"");
out.write(_("Show Peers")); out.write(_("Show Peers"));
out.write("\" alt=\"");
out.write(_("Show Peers"));
out.write("\">");
} }
out.write("</a>)<br>\n"); out.write("</a><br>\n");
} }
out.write("</th>\n<th align=\"left\">"); out.write("</th>\n<th align=\"left\">");
out.write("<img border=\"0\" src=\"/themes/snark/ubergine/images/torrent.png\" title=\"");
out.write(_("Torrent"));
out.write("\">");
out.write(_("Torrent")); out.write(_("Torrent"));
out.write("</th>\n<th align=\"center\">"); out.write("</th>\n<th align=\"center\">");
out.write("<img border=\"0\" src=\"/themes/snark/ubergine/images/eta.png\" title=\"");
out.write(_("Estimated Download Time"));
out.write("\">");
out.write(_("ETA")); out.write(_("ETA"));
out.write("</th>\n<th align=\"right\">"); out.write("</th>\n<th align=\"center\">");
out.write("<img border=\"0\" src=\"/themes/console/images/inbound.png\" title=\"");
out.write(_("Downloaded")); out.write(_("Downloaded"));
out.write("</th>\n<th align=\"right\">"); out.write("\">");
out.write(_("RX"));
out.write("</th>\n<th align=\"center\">");
out.write("<img border=\"0\" src=\"/themes/console/images/outbound.png\" title=\"");
out.write(_("Uploaded")); out.write(_("Uploaded"));
out.write("</th>\n<th align=\"right\">"); out.write("\">");
out.write(_("TX"));
out.write("</th>\n<th align=\"center\">");
out.write("<img border=\"0\" src=\"/themes/console/images/inbound.png\" title=\"");
out.write(_("Down Rate")); out.write(_("Down Rate"));
out.write("</th>\n<th align=\"right\">"); out.write("\">Rate");
out.write("</th>\n<th align=\"center\">");
out.write("<img border=\"0\" src=\"/themes/console/images/outbound.png\" title=\"");
out.write(_("Up Rate")); out.write(_("Up Rate"));
out.write("\">");
out.write(_("Rate"));
out.write("</th>\n"); out.write("</th>\n");
out.write("<th align=\"center\">"); out.write("<th align=\"center\">");
if (_manager.util().connected()) { if (_manager.util().connected()) {
out.write("<a href=\"" + uri + "?action=StopAll&nonce=" + _nonce + out.write("<a href=\"" + uri + "?action=StopAll&nonce=" + _nonce +
"\" title=\""); "\" title=\"");
out.write(_("Stop all torrents and the I2P tunnel")); out.write(_("Stop all torrents and the I2P tunnel"));
out.write("\">"); out.write("\">");
out.write("<img src=\"/themes/snark/ubergine/images/stop_all.png\" title=\"");
out.write(_("Stop all torrents and the I2P tunnel"));
out.write("\" alt=\"");
out.write(_("Stop All")); out.write(_("Stop All"));
out.write("\">");
out.write("</a>"); out.write("</a>");
} else if (!snarks.isEmpty()) { } else if (!snarks.isEmpty()) {
out.write("<a href=\"" + uri + "?action=StartAll&nonce=" + _nonce + out.write("<a href=\"" + uri + "?action=StartAll&nonce=" + _nonce +
"\" title=\""); "\" title=\"");
out.write(_("Start all torrents and the I2P tunnel")); out.write(_("Start all torrents and the I2P tunnel"));
out.write("\">"); out.write("\">");
out.write(_("Start All")); out.write("<img src=\"/themes/snark/ubergine/images/start_all.png\" title=\"");
out.write(_("Start all torrents and the I2P tunnel"));
out.write("\" alt=\"Start All\">");
out.write("</a>"); out.write("</a>");
} else { } else {
out.write("&nbsp;"); out.write("&nbsp;");
@ -292,8 +328,8 @@ public class I2PSnarkServlet extends Default {
} }
if (snarks.isEmpty()) { if (snarks.isEmpty()) {
out.write("<tr class=\"snarkTorrentEven\">" + out.write("<tr class=\"snarkTorrentNoneLoaded\">" +
"<td class=\"snarkTorrentEven\" align=\"center\"" + "<td class=\"snarkTorrentNoneLoaded\"" +
" colspan=\"8\"><i>"); " colspan=\"8\"><i>");
out.write(_("No torrents loaded.")); out.write(_("No torrents loaded."));
out.write("</i></td></tr>\n"); out.write("</i></td></tr>\n");
@ -301,12 +337,12 @@ public class I2PSnarkServlet extends Default {
out.write("<tfoot><tr>\n" + out.write("<tfoot><tr>\n" +
" <th align=\"left\" colspan=\"2\">"); " <th align=\"left\" colspan=\"2\">");
out.write(_("Totals")); out.write(_("Totals"));
out.write(" ("); out.write(" &raquo;&nbsp;");
out.write(ngettext("1 torrent", "{0} torrents", snarks.size())); out.write(ngettext("1 torrent", "{0} torrents", snarks.size()));
out.write(", "); out.write(", ");
out.write(DataHelper.formatSize2(stats[5]) + "B, "); out.write(DataHelper.formatSize2(stats[5]) + "B, ");
out.write(ngettext("1 connected peer", "{0} connected peers", (int) stats[4])); out.write(ngettext("1 connected peer", "{0} connected peers", (int) stats[4]));
out.write(")</th>\n" + out.write("</th>\n" +
" <th>&nbsp;</th>\n" + " <th>&nbsp;</th>\n" +
" <th align=\"right\">" + formatSize(stats[0]) + "</th>\n" + " <th align=\"right\">" + formatSize(stats[0]) + "</th>\n" +
" <th align=\"right\">" + formatSize(stats[1]) + "</th>\n" + " <th align=\"right\">" + formatSize(stats[1]) + "</th>\n" +
@ -502,7 +538,7 @@ public class I2PSnarkServlet extends Default {
File torrentFile = new File(baseFile.getParent(), baseFile.getName() + ".torrent"); File torrentFile = new File(baseFile.getParent(), baseFile.getName() + ".torrent");
if (torrentFile.exists()) if (torrentFile.exists())
throw new IOException("Cannot overwrite an existing .torrent file: " + torrentFile.getPath()); throw new IOException("Cannot overwrite an existing .torrent file: " + torrentFile.getPath());
_manager.saveTorrentStatus(info, s.getBitField()); // so addTorrent won't recheck _manager.saveTorrentStatus(info, s.getBitField(), null); // so addTorrent won't recheck
// DirMonitor could grab this first, maybe hold _snarks lock? // DirMonitor could grab this first, maybe hold _snarks lock?
FileOutputStream out = new FileOutputStream(torrentFile); FileOutputStream out = new FileOutputStream(torrentFile);
out.write(info.getTorrentData()); out.write(info.getTorrentData());
@ -529,6 +565,8 @@ public class I2PSnarkServlet extends Default {
_manager.stopTorrent(snark.torrent, false); _manager.stopTorrent(snark.torrent, false);
} }
if (_manager.util().connected()) { if (_manager.util().connected()) {
// Give the stopped announces time to get out
try { Thread.sleep(2000); } catch (InterruptedException ie) {}
_manager.util().disconnect(); _manager.util().disconnect();
_manager.addMessage(_("I2P tunnel closed.")); _manager.addMessage(_("I2P tunnel closed."));
} }
@ -600,7 +638,7 @@ public class I2PSnarkServlet extends Default {
} }
private static final int MAX_DISPLAYED_FILENAME_LENGTH = 44; private static final int MAX_DISPLAYED_FILENAME_LENGTH = 44;
private static final int MAX_DISPLAYED_ERROR_LENGTH = 40; private static final int MAX_DISPLAYED_ERROR_LENGTH = 6;
private void displaySnark(PrintWriter out, Snark snark, String uri, int row, long stats[], boolean showPeers, boolean showDebug) throws IOException { private void displaySnark(PrintWriter out, Snark snark, String uri, int row, long stats[], boolean showPeers, boolean showDebug) throws IOException {
String filename = snark.torrent; String filename = snark.torrent;
File f = new File(filename); File f = new File(filename);
@ -658,50 +696,57 @@ public class I2PSnarkServlet extends Default {
String statusString = _("Unknown"); String statusString = _("Unknown");
if (err != null) { if (err != null) {
if (isRunning && curPeers > 0 && !showPeers) if (isRunning && curPeers > 0 && !showPeers)
statusString = "<a title=\"" + err + "\">" + _("TrackerErr") + "</a> (" + statusString = "<img border=\"0\" src=\"/themes/snark/ubergine/images/trackererror.png\" title=\"" + _("Tracker Error") +
"<a href=\"" + uri + "?p=" + Base64.encode(snark.meta.getInfoHash()) + "\">" + "\"><a href=\"" + uri + "?p=" + Base64.encode(snark.meta.getInfoHash()) + "\">" +
curPeers + '/' + ' ' + curPeers + "&thinsp;/&thinsp;" +
ngettext("1 peer", "{0} peers", knownPeers) + "</a>)"; ngettext("1 peer", "{0} peers", knownPeers) + "</a>";
else if (isRunning) else if (isRunning)
statusString = "<a title=\"" + err + "\">" + _("TrackerErr") + " (" + curPeers + '/' + statusString = "<img border=\"0\" src=\"/themes/snark/ubergine/images/trackererror.png\" title=\"" + _("Tracker Error") +
ngettext("1 peer", "{0} peers", knownPeers) + ')'; "\">" + ' ' + curPeers + "&thinsp;/&thinsp;" +
ngettext("1 peer", "{0} peers", knownPeers) + "</a>";
else { else {
if (err.length() > MAX_DISPLAYED_ERROR_LENGTH) if (err.length() > MAX_DISPLAYED_ERROR_LENGTH)
err = err.substring(0, MAX_DISPLAYED_ERROR_LENGTH) + "&hellip;"; err = err.substring(0, MAX_DISPLAYED_ERROR_LENGTH) + "&hellip;";
statusString = _("TrackerErr") + "<br>(" + err + ")"; statusString = "<img border=\"0\" src=\"/themes/snark/ubergine/images/trackererror.png\" title=\"" + _("Tracker Error") +
"\"> " + err + "</a>";
} }
} else if (remaining <= 0) { } else if (remaining <= 0) {
if (isRunning && curPeers > 0 && !showPeers) if (isRunning && curPeers > 0 && !showPeers)
statusString = _("Seeding") + " (" + statusString = "<img border=\"0\" src=\"/themes/snark/ubergine/images/seeding.png\" title=\"" + _("Seeding") + "\">" +
"<a href=\"" + uri + "?p=" + Base64.encode(snark.meta.getInfoHash()) + "\">" + "<a href=\"" + uri + "?p=" + Base64.encode(snark.meta.getInfoHash()) + "\">" +
curPeers + '/' + ' ' + curPeers + "&thinsp;/&thinsp;" +
ngettext("1 peer", "{0} peers", knownPeers) + "</a>)"; ngettext("1 peer", "{0} peers", knownPeers) + "</a>";
else if (isRunning) else if (isRunning)
statusString = _("Seeding") + " (" + curPeers + "/" + statusString = "<img border=\"0\" src=\"/themes/snark/ubergine/images/seeding.png\" title=\"" + _("Seeding") + "\">" +
ngettext("1 peer", "{0} peers", knownPeers) + ')'; ' ' + curPeers + "&thinsp;/&thinsp;" +
ngettext("1 peer", "{0} peers", knownPeers) + "</a>";
else else
statusString = _("Complete"); statusString = "<img border=\"0\" src=\"/themes/snark/ubergine/images/complete.png\" title=\"" + _("Complete") + "\"> " + _("Complete");
} else { } else {
if (isRunning && curPeers > 0 && downBps > 0 && !showPeers) if (isRunning && curPeers > 0 && downBps > 0 && !showPeers)
statusString = _("OK") + " (" + statusString = "<img border=\"0\" src=\"/themes/snark/ubergine/images/downloading.png\" title=\"" + _("Downloading") + "\">" +
"<a href=\"" + uri + "?p=" + Base64.encode(snark.meta.getInfoHash()) + "\">" + "<a href=\"" + uri + "?p=" + Base64.encode(snark.meta.getInfoHash()) + "\">" +
curPeers + "/" + ' ' + curPeers + "&thinsp;/&thinsp;" +
ngettext("1 peer", "{0} peers", knownPeers) + "</a>)"; ngettext("1 peer", "{0} peers", knownPeers) + "</a>";
else if (isRunning && curPeers > 0 && downBps > 0) else if (isRunning && curPeers > 0 && downBps > 0)
statusString = _("OK") + " (" + curPeers + "/" + statusString = "<img border=\"0\" src=\"/themes/snark/ubergine/images/downloading.png\" title=\"" + _("Downloading") + "\">" +
ngettext("1 peer", "{0} peers", knownPeers) + ')'; ' ' + curPeers + "&thinsp;/&thinsp;" +
ngettext("1 peer", "{0} peers", knownPeers);
else if (isRunning && curPeers > 0 && !showPeers) else if (isRunning && curPeers > 0 && !showPeers)
statusString = _("Stalled") + " (" + statusString = "<img border=\"0\" src=\"/themes/snark/ubergine/images/stalled.png\" title=\"" + _("Stalled") + "\">" +
"<a href=\"" + uri + "?p=" + Base64.encode(snark.meta.getInfoHash()) + "\">" + "<a href=\"" + uri + "?p=" + Base64.encode(snark.meta.getInfoHash()) + "\">" +
curPeers + '/' + ' ' + curPeers + "&thinsp;/&thinsp;" +
ngettext("1 peer", "{0} peers", knownPeers) + "</a>)"; ngettext("1 peer", "{0} peers", knownPeers) + "</a>";
else if (isRunning && curPeers > 0) else if (isRunning && curPeers > 0)
statusString = _("Stalled") + " (" + curPeers + '/' + statusString = "<img border=\"0\" src=\"/themes/snark/ubergine/images/stalled.png\" title=\"" + _("Stalled") + "\">" +
ngettext("1 peer", "{0} peers", knownPeers) + ')'; ' ' + curPeers + "&thinsp;/&thinsp;" +
ngettext("1 peer", "{0} peers", knownPeers);
else if (isRunning) else if (isRunning)
statusString = _("No Peers") + " (0/" + knownPeers + ')'; statusString = "<img border=\"0\" src=\"/themes/snark/ubergine/images/nopeers.png\" title=\"" + _("No Peers") + "\">" +
' ' + curPeers + "&thinsp;/&thinsp;" +
ngettext("1 peer", "{0} peers", knownPeers);
else else
statusString = _("Stopped"); statusString = "<img border=\"0\" src=\"/themes/snark/ubergine/images/stopped.png\" title=\"" + _("Stopped") + "\"> " + _("Stopped");
} }
String rowClass = (row % 2 == 0 ? "snarkTorrentEven" : "snarkTorrentOdd"); String rowClass = (row % 2 == 0 ? "snarkTorrentEven" : "snarkTorrentOdd");
@ -746,11 +791,11 @@ public class I2PSnarkServlet extends Default {
if (e < 0) if (e < 0)
continue; continue;
baseURL = baseURL.substring(e + 1); baseURL = baseURL.substring(e + 1);
out.write("&nbsp;&nbsp;&nbsp;[<a href=\"" + baseURL + "details.php?dllist=1&filelist=1&info_hash="); out.write("&nbsp;<a href=\"" + baseURL + "details.php?dllist=1&filelist=1&info_hash=");
out.write(TrackerClient.urlencode(snark.meta.getInfoHash())); out.write(TrackerClient.urlencode(snark.meta.getInfoHash()));
out.write("\" title=\"" + name + ' ' + _("Tracker") + "\">"); out.write("\" title=\"" + name + ' ' + _("Tracker") + "\" target=\"_blank\">");
out.write(_("Details")); out.write("<img border=\"0\" src=\"/themes/snark/ubergine/images/details.png\">");
out.write("</a>]"); out.write("</a>");
break; break;
} }
} }
@ -762,7 +807,7 @@ public class I2PSnarkServlet extends Default {
out.write("</td>\n\t"); out.write("</td>\n\t");
out.write("<td align=\"right\" class=\"snarkTorrentDownloaded " + rowClass + "\">"); out.write("<td align=\"right\" class=\"snarkTorrentDownloaded " + rowClass + "\">");
if (remaining > 0) if (remaining > 0)
out.write(formatSize(total-remaining) + " / " + formatSize(total)); // 18MB/3GB out.write(formatSize(total-remaining) + "&thinsp;/&thinsp;" + formatSize(total)); // 18MB/3GB; thin space so it will line break well
else else
out.write(formatSize(total)); // 3GB out.write(formatSize(total)); // 3GB
out.write("</td>\n\t"); out.write("</td>\n\t");
@ -785,7 +830,11 @@ public class I2PSnarkServlet extends Default {
+ "\" title=\""); + "\" title=\"");
out.write(_("Stop the torrent")); out.write(_("Stop the torrent"));
out.write("\">"); out.write("\">");
out.write("<img src=\"/themes/snark/ubergine/images/stop.png\" title=\"");
out.write(_("Stop the torrent"));
out.write("\" alt=\"");
out.write(_("Stop")); out.write(_("Stop"));
out.write("\">");
out.write("</a>"); out.write("</a>");
} else { } else {
if (isValid) { if (isValid) {
@ -793,8 +842,12 @@ public class I2PSnarkServlet extends Default {
+ "\" title=\""); + "\" title=\"");
out.write(_("Start the torrent")); out.write(_("Start the torrent"));
out.write("\">"); out.write("\">");
out.write("<img src=\"/themes/snark/ubergine/images/start.png\" title=\"");
out.write(_("Start the torrent"));
out.write("\" alt=\"");
out.write(_("Start")); out.write(_("Start"));
out.write("</a>\n"); out.write("\">");
out.write("</a>");
} }
out.write("<a href=\"" + uri + "?action=Remove" + parameters out.write("<a href=\"" + uri + "?action=Remove" + parameters
+ "\" title=\""); + "\" title=\"");
@ -805,8 +858,12 @@ public class I2PSnarkServlet extends Default {
// Then the remaining single quite must be escaped // 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(_("Are you sure you want to delete the file \\''{0}.torrent\\'' (downloaded data will not be deleted) ?", fullFilename));
out.write("')) { return false; }\">"); out.write("')) { return false; }\">");
out.write("<img src=\"/themes/snark/ubergine/images/remove.png\" title=\"");
out.write(_("Remove the torrent from the active list, deleting the .torrent file"));
out.write("\" alt=\"");
out.write(_("Remove")); out.write(_("Remove"));
out.write("</a><br>"); out.write("\">");
out.write("</a>");
out.write("<a href=\"" + uri + "?action=Delete" + parameters out.write("<a href=\"" + uri + "?action=Delete" + parameters
+ "\" title=\""); + "\" title=\"");
out.write(_("Delete the .torrent file and the associated data file(s)")); out.write(_("Delete the .torrent file and the associated data file(s)"));
@ -816,7 +873,11 @@ public class I2PSnarkServlet extends Default {
// Then the remaining single quite must be escaped // 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(_("Are you sure you want to delete the torrent \\''{0}\\'' and all downloaded data?", fullFilename));
out.write("')) { return false; }\">"); out.write("')) { return false; }\">");
out.write("<img src=\"/themes/snark/ubergine/images/delete.png\" title=\"");
out.write(_("Delete the .torrent file and the associated data file(s)"));
out.write("\" alt=\"");
out.write(_("Delete")); out.write(_("Delete"));
out.write("\">");
out.write("</a>"); out.write("</a>");
} }
out.write("</td>\n</tr>\n"); out.write("</td>\n</tr>\n");
@ -872,10 +933,10 @@ public class I2PSnarkServlet extends Default {
out.write("<td align=\"right\" class=\"snarkTorrentStatus " + rowClass + "\">"); out.write("<td align=\"right\" class=\"snarkTorrentStatus " + rowClass + "\">");
if (remaining > 0) { if (remaining > 0) {
if (peer.isInteresting() && !peer.isChoked()) { if (peer.isInteresting() && !peer.isChoked()) {
out.write("<font color=#008000>"); out.write("<font color=#00ff00>");
out.write(formatSize(peer.getDownloadRate()) + "ps</font>"); out.write(formatSize(peer.getDownloadRate()) + "ps</font>");
} else { } else {
out.write("<font color=#a00000><a title=\""); out.write("<font color=#ff0000><a title=\"");
if (!peer.isInteresting()) if (!peer.isInteresting())
out.write(_("Uninteresting (The peer has no pieces we need)")); out.write(_("Uninteresting (The peer has no pieces we need)"));
else else
@ -888,10 +949,10 @@ public class I2PSnarkServlet extends Default {
out.write("<td align=\"right\" class=\"snarkTorrentStatus " + rowClass + "\">"); out.write("<td align=\"right\" class=\"snarkTorrentStatus " + rowClass + "\">");
if (pct != 100.0) { if (pct != 100.0) {
if (peer.isInterested() && !peer.isChoking()) { if (peer.isInterested() && !peer.isChoking()) {
out.write("<font color=#008000>"); out.write("<font color=#00ff00>");
out.write(formatSize(peer.getUploadRate()) + "ps</font>"); out.write(formatSize(peer.getUploadRate()) + "ps</font>");
} else { } else {
out.write("<font color=#a00000><a title=\""); out.write("<font color=#ff0000><a title=\"");
if (!peer.isInterested()) if (!peer.isInterested())
out.write(_("Uninterested (We have no pieces the peer needs)")); out.write(_("Uninterested (We have no pieces the peer needs)"));
else else
@ -938,19 +999,20 @@ public class I2PSnarkServlet extends Default {
out.write("<input type=\"hidden\" name=\"nonce\" value=\"" + _nonce + "\" >\n"); out.write("<input type=\"hidden\" name=\"nonce\" value=\"" + _nonce + "\" >\n");
out.write("<input type=\"hidden\" name=\"action\" value=\"Add\" >\n"); out.write("<input type=\"hidden\" name=\"action\" value=\"Add\" >\n");
out.write("<div class=\"addtorrentsection\"><span class=\"snarkConfigTitle\">"); out.write("<div class=\"addtorrentsection\"><span class=\"snarkConfigTitle\">");
out.write("<img border=\"0\" src=\"/themes/snark/ubergine/images/add.png\">");
out.write(_("Add Torrent")); out.write(_("Add Torrent"));
out.write("</span><br>\n<table border=\"0\"><tr><td>"); out.write("</span><hr>\n<table border=\"0\"><tr><td>");
out.write(_("From URL")); out.write(_("From URL"));
out.write(":<td><input type=\"text\" name=\"newURL\" size=\"80\" value=\"" + newURL + "\" > \n"); out.write(":<td><input type=\"text\" name=\"newURL\" size=\"85\" value=\"" + newURL + "\" > \n");
// not supporting from file at the moment, since the file name passed isn't always absolute (so it may not resolve) // not supporting from file at the moment, since the file name passed isn't always absolute (so it may not resolve)
//out.write("From file: <input type=\"file\" name=\"newFile\" size=\"50\" value=\"" + newFile + "\" /><br>\n"); //out.write("From file: <input type=\"file\" name=\"newFile\" size=\"50\" value=\"" + newFile + "\" /><br>");
out.write("<tr><td>&nbsp;<td><input type=\"submit\" value=\""); out.write("<input type=\"submit\" value=\"");
out.write(_("Add torrent")); out.write(_("Add torrent"));
out.write("\" name=\"foo\" ><br>\n"); out.write("\" name=\"foo\" ><br>\n");
out.write("<tr><td>&nbsp;<td><span class=\"snarkAddInfo\">"); out.write("<tr><td>&nbsp;<td><span class=\"snarkAddInfo\">");
out.write(_("Alternately, you can copy .torrent files to the directory {0}.", _manager.getDataDir().getAbsolutePath())); out.write(_("You can also copy .torrent files to: {0}.", "<code>" + _manager.getDataDir().getAbsolutePath () + "</code>"));
out.write("\n"); out.write("\n");
out.write(_("Removing a .torrent file will cause the torrent to stop.")); out.write(_("Removing a .torrent will cause it to stop."));
out.write("<br></span></table>\n"); out.write("<br></span></table>\n");
out.write("</form>\n</span></div>"); out.write("</form>\n</span></div>");
} }
@ -969,12 +1031,13 @@ public class I2PSnarkServlet extends Default {
out.write("<input type=\"hidden\" name=\"nonce\" value=\"" + _nonce + "\" >\n"); out.write("<input type=\"hidden\" name=\"nonce\" value=\"" + _nonce + "\" >\n");
out.write("<input type=\"hidden\" name=\"action\" value=\"Create\" >\n"); out.write("<input type=\"hidden\" name=\"action\" value=\"Create\" >\n");
out.write("<span class=\"snarkConfigTitle\">"); out.write("<span class=\"snarkConfigTitle\">");
out.write("<img border=\"0\" src=\"/themes/snark/ubergine/images/create.png\">");
out.write(_("Create Torrent")); out.write(_("Create Torrent"));
out.write("</span><br>\n<table border=\"0\"><tr><td>"); out.write("</span><hr>\n<table border=\"0\"><tr><td>");
//out.write("From file: <input type=\"file\" name=\"newFile\" size=\"50\" value=\"" + newFile + "\" /><br>\n"); //out.write("From file: <input type=\"file\" name=\"newFile\" size=\"50\" value=\"" + newFile + "\" /><br>\n");
out.write(_("Data to seed")); out.write(_("Data to seed"));
out.write(":<td>" + _manager.getDataDir().getAbsolutePath() + File.separatorChar out.write(":<td><code>" + _manager.getDataDir().getAbsolutePath() + File.separatorChar
+ "<input type=\"text\" name=\"baseFile\" size=\"40\" value=\"" + baseFile + "</code><input type=\"text\" name=\"baseFile\" size=\"58\" value=\"" + baseFile
+ "\" title=\""); + "\" title=\"");
out.write(_("File or directory to seed (must be within the specified path)")); out.write(_("File or directory to seed (must be within the specified path)"));
out.write("\" ><tr><td>\n"); out.write("\" ><tr><td>\n");
@ -994,11 +1057,11 @@ public class I2PSnarkServlet extends Default {
} }
out.write("</select>\n"); out.write("</select>\n");
out.write(_("or")); out.write(_("or"));
out.write("<tr><td>&nbsp;<td><input type=\"text\" name=\"announceURLOther\" size=\"50\" value=\"http://\" " + out.write("&nbsp;<input type=\"text\" name=\"announceURLOther\" size=\"57\" value=\"http://\" " +
"title=\""); "title=\"");
out.write(_("Specify custom tracker announce URL")); out.write(_("Specify custom tracker announce URL"));
out.write("\" > "); out.write("\" > ");
out.write("<tr><td>&nbsp;<td><input type=\"submit\" value=\""); out.write("<input type=\"submit\" value=\"");
out.write(_("Create torrent")); out.write(_("Create torrent"));
out.write("\" name=\"foo\" ></table>\n"); out.write("\" name=\"foo\" ></table>\n");
out.write("</form>\n</span></div>"); out.write("</form>\n</span></div>");
@ -1013,12 +1076,13 @@ public class I2PSnarkServlet extends Default {
//int seedPct = 0; //int seedPct = 0;
out.write("<form action=\"" + uri + "\" method=\"POST\">\n"); out.write("<form action=\"" + uri + "\" method=\"POST\">\n");
out.write("<div class=\"configsection\"><span class=\"snarkConfig\">\n"); out.write("<div class=\"configsectionpanel\"><span class=\"snarkConfig\">\n");
out.write("<input type=\"hidden\" name=\"nonce\" value=\"" + _nonce + "\" >\n"); out.write("<input type=\"hidden\" name=\"nonce\" value=\"" + _nonce + "\" >\n");
out.write("<input type=\"hidden\" name=\"action\" value=\"Save\" >\n"); out.write("<input type=\"hidden\" name=\"action\" value=\"Save\" >\n");
out.write("<span class=\"snarkConfigTitle\">"); out.write("<span class=\"snarkConfigTitle\">");
out.write("<img border=\"0\" src=\"/themes/snark/ubergine/images/config.png\">");
out.write(_("Configuration")); out.write(_("Configuration"));
out.write("</span><br>\n"); out.write("</span><hr>\n");
out.write("<table border=\"0\"><tr><td>"); out.write("<table border=\"0\"><tr><td>");
out.write(_("Data directory")); out.write(_("Data directory"));
out.write(": <td><input type=\"text\" size=\"50\" name=\"dataDir\" value=\"" + dataDir + "\" "); out.write(": <td><input type=\"text\" size=\"50\" name=\"dataDir\" value=\"" + dataDir + "\" ");
@ -1133,7 +1197,6 @@ public class I2PSnarkServlet extends Default {
out.write(": <td><textarea name=\"i2cpOpts\" cols=\"60\" rows=\"1\" wrap=\"off\" >" out.write(": <td><textarea name=\"i2cpOpts\" cols=\"60\" rows=\"1\" wrap=\"off\" >"
+ opts.toString() + "</textarea><br>\n"); + opts.toString() + "</textarea><br>\n");
out.write("<tr><td>&nbsp;<td><input type=\"submit\" value=\""); out.write("<tr><td>&nbsp;<td><input type=\"submit\" value=\"");
out.write(_("Save configuration")); out.write(_("Save configuration"));
out.write("\" name=\"foo\" >\n"); out.write("\" name=\"foo\" >\n");
@ -1144,6 +1207,7 @@ public class I2PSnarkServlet extends Default {
private void writeConfigLink(PrintWriter out) throws IOException { private void writeConfigLink(PrintWriter out) throws IOException {
out.write("<div class=\"configsection\"><span class=\"snarkConfig\">\n"); out.write("<div class=\"configsection\"><span class=\"snarkConfig\">\n");
out.write("<span class=\"snarkConfigTitle\"><a href=\"configure\">"); out.write("<span class=\"snarkConfigTitle\"><a href=\"configure\">");
out.write("<img border=\"0\" src=\"/themes/snark/ubergine/images/config.png\">");
out.write(_("Configuration")); out.write(_("Configuration"));
out.write("</a></span></span></div>\n"); out.write("</a></span></span></div>\n");
} }
@ -1201,23 +1265,25 @@ public class I2PSnarkServlet extends Default {
// rounding makes us look faster :) // rounding makes us look faster :)
private static String formatSize(long bytes) { private static String formatSize(long bytes) {
if (bytes < 5*1024) if (bytes < 5*1024)
return bytes + " B"; return bytes + "&nbsp;B";
else if (bytes < 5*1024*1024) else if (bytes < 5*1024*1024)
return ((bytes + 512)/1024) + " KB"; return ((bytes + 512)/1024) + "&nbsp;KB";
else if (bytes < 10*1024*1024*1024l) else if (bytes < 10*1024*1024*1024l)
return ((bytes + 512*1024)/(1024*1024)) + " MB"; return ((bytes + 512*1024)/(1024*1024)) + "&nbsp;MB";
else else
return ((bytes + 512*1024*1024)/(1024*1024*1024)) + " GB"; return ((bytes + 512*1024*1024)/(1024*1024*1024)) + "&nbsp;GB";
} }
/** @since 0.7.14 */ /** @since 0.7.14 */
private static String urlify(String s) { private static String urlify(String s) {
StringBuilder buf = new StringBuilder(256); StringBuilder buf = new StringBuilder(256);
buf.append("<a href=\"").append(s).append("\">").append(s).append("</a>"); // browsers seem to work without doing this but let's be strict
String link = s.replace("&", "&amp;");
buf.append("<a href=\"").append(link).append("\">").append(link).append("</a>");
return buf.toString(); return buf.toString();
} }
private static final String HEADER = "<link href=\"/themes/console/snark.css\" rel=\"stylesheet\" type=\"text/css\" >"; private static final String HEADER = "<link href=\"/themes/snark/ubergine/snark.css\" rel=\"stylesheet\" type=\"text/css\" >";
private static final String TABLE_HEADER = "<table border=\"0\" class=\"snarkTorrents\" width=\"100%\" cellpadding=\"0 10px\">\n" + private static final String TABLE_HEADER = "<table border=\"0\" class=\"snarkTorrents\" width=\"100%\" cellpadding=\"0 10px\">\n" +
@ -1252,10 +1318,11 @@ public class I2PSnarkServlet extends Default {
* @param r The Resource * @param r The Resource
* @param base The base URL * @param base The base URL
* @param parent True if the parent directory should be included * @param parent True if the parent directory should be included
* @param postParams map of POST parameters or null if not a POST
* @return String of HTML * @return String of HTML
* @since 0.7.14 * @since 0.7.14
*/ */
private String getListHTML(Resource r, String base, boolean parent) private String getListHTML(Resource r, String base, boolean parent, Map postParams)
throws IOException throws IOException
{ {
if (!r.isDirectory()) if (!r.isDirectory())
@ -1280,12 +1347,16 @@ public class I2PSnarkServlet extends Default {
else else
torrentName = title; torrentName = title;
Snark snark = _manager.getTorrentByBaseName(torrentName); Snark snark = _manager.getTorrentByBaseName(torrentName);
if (snark != null && postParams != null)
savePriorities(snark, postParams);
if (title.endsWith("/")) if (title.endsWith("/"))
title = title.substring(0, title.length() - 1); title = title.substring(0, title.length() - 1);
title = _("Torrent") + ": " + title; title = _("Torrent") + ": " + title;
buf.append(title); buf.append(title);
buf.append("</TITLE>").append(HEADER).append("</HEAD><BODY>\n<div class=\"snarknavbar\">"); buf.append("</TITLE>").append(HEADER).append("<link rel=\"shortcut icon\" href=\"/themes/snark/ubergine/favicon.ico\"></HEAD><BODY>\n<center><div class=\"snarknavbar\"> <a href=\"/i2psnark/\" title=\"Torrents\"");
buf.append(title); buf.append(" class=\"snarkRefresh\">I2PSnark</a>").append("</div>");
if (parent) if (parent)
{ {
@ -1297,12 +1368,19 @@ public class I2PSnarkServlet extends Default {
.append(_("Up to higher level directory")).append("</A>\n"); .append(_("Up to higher level directory")).append("</A>\n");
} }
buf.append("</div><div class=\"page\"><div class=\"mainsection\">" + buf.append("</div><div class=\"page\"><div class=\"mainsection\">");
"<TABLE BORDER=0 class=\"snarkTorrents\" cellpadding=\"5px 10px\">" + boolean showPriority = snark != null && !snark.storage.complete();
"<thead><tr><th>").append(_("File")).append("</th><th>").append(_("Size")) if (showPriority)
.append("</th><th>").append(_("Status")).append("</th></tr></thead>"); buf.append("<form action=\"").append(base).append("\" method=\"POST\">\n");
buf.append("<TABLE BORDER=0 class=\"snarkTorrents\" cellpadding=\"5px 10px\">" +
"<thead><tr><th>").append("<img border=\"0\" src=\"/themes/snark/ubergine/images/file.png\" title=\"").append(_("File")).append("\" alt=\"").append(_("File")).append("\">&nbsp;").append(title).append("</th><th align=\"right\">").append("<img border=\"0\" src=\"/themes/snark/ubergine/images/size.png\" title=\"").append(_("FileSize")).append("\" alt=\"").append(_("FileSize")).append("\">").append(_("Size"));
buf.append("</th><th>").append("<img border=\"0\" src=\"/themes/snark/ubergine/images/status.png\" title=\"").append(_("Download Status")).append("\">").append(_("Status")).append("</th>");
if (showPriority)
buf.append("<th>").append(_("Priority")).append("</th>");
buf.append("</tr></thead>\n");
//DateFormat dfmt=DateFormat.getDateTimeInstance(DateFormat.MEDIUM, //DateFormat dfmt=DateFormat.getDateTimeInstance(DateFormat.MEDIUM,
// DateFormat.MEDIUM); // DateFormat.MEDIUM);
boolean showSaveButton = false;
for (int i=0 ; i< ls.length ; i++) for (int i=0 ; i< ls.length ; i++)
{ {
String encoded=URI.encodePath(ls[i]); String encoded=URI.encodePath(ls[i]);
@ -1340,7 +1418,8 @@ public class I2PSnarkServlet extends Default {
complete = true; complete = true;
status = toImg("tick") + _("Complete"); status = toImg("tick") + _("Complete");
} else { } else {
status = toImg("clock") + status =
(snark.storage.getPriority(f.getCanonicalPath()) < 0 ? toImg("cancel") : toImg("clock")) +
(100 * (length - remaining) / length) + "% " + _("complete") + (100 * (length - remaining) / length) + "% " + _("complete") +
" (" + DataHelper.formatSize2(remaining) + _("bytes remaining") + ")"; " (" + DataHelper.formatSize2(remaining) + _("bytes remaining") + ")";
} }
@ -1384,9 +1463,40 @@ public class I2PSnarkServlet extends Default {
buf.append("</TD><TD class=\"").append(rowClass).append(" snarkFileStatus\">"); buf.append("</TD><TD class=\"").append(rowClass).append(" snarkFileStatus\">");
//buf.append(dfmt.format(new Date(item.lastModified()))); //buf.append(dfmt.format(new Date(item.lastModified())));
buf.append(status); buf.append(status);
buf.append("</TD></TR>\n"); buf.append("</TD>");
if (showPriority) {
buf.append("<td>");
File f = item.getFile();
if ((!complete) && (!item.isDirectory()) && f != null) {
int pri = snark.storage.getPriority(f.getCanonicalPath());
buf.append("<input type=\"radio\" value=\"5\" name=\"pri.").append(f.getCanonicalPath()).append("\" ");
if (pri > 0)
buf.append("checked=\"true\"");
buf.append('>').append(_("High"));
buf.append("<input type=\"radio\" value=\"0\" name=\"pri.").append(f.getCanonicalPath()).append("\" ");
if (pri == 0)
buf.append("checked=\"true\"");
buf.append('>').append(_("Normal"));
buf.append("<input type=\"radio\" value=\"-9\" name=\"pri.").append(f.getCanonicalPath()).append("\" ");
if (pri < 0)
buf.append("checked=\"true\"");
buf.append('>').append(_("Do not download"));
showSaveButton = true;
}
buf.append("</td>");
}
buf.append("</TR>\n");
}
if (showSaveButton) {
buf.append("<thead><tr><th colspan=\"3\">&nbsp;</th><th align=\"center\"><input type=\"submit\" value=\"");
buf.append(_("Save priorities"));
buf.append("\" name=\"foo\" ></th></tr></thead>\n");
} }
buf.append("</TABLE>\n"); buf.append("</TABLE>\n");
if (showPriority)
buf.append("</form>");
buf.append("</div></div></BODY></HTML>\n"); buf.append("</div></div></BODY></HTML>\n");
return buf.toString(); return buf.toString();
@ -1431,7 +1541,8 @@ public class I2PSnarkServlet extends Default {
plc.endsWith(".ape")) plc.endsWith(".ape"))
icon = "music"; icon = "music";
else if (mime.startsWith("video/") || plc.endsWith(".mkv") || plc.endsWith(".m4v") || else if (mime.startsWith("video/") || plc.endsWith(".mkv") || plc.endsWith(".m4v") ||
plc.endsWith(".mp4") || plc.endsWith(".wmv") || plc.endsWith(".flv")) plc.endsWith(".mp4") || plc.endsWith(".wmv") || plc.endsWith(".flv") ||
plc.endsWith(".ogm"))
icon = "film"; icon = "film";
else if (mime.equals("application/zip") || mime.equals("application/x-gtar") || else if (mime.equals("application/zip") || mime.equals("application/x-gtar") ||
mime.equals("application/compress") || mime.equals("application/gzip") || mime.equals("application/compress") || mime.equals("application/gzip") ||
@ -1452,6 +1563,26 @@ public class I2PSnarkServlet extends Default {
return "<img alt=\"\" height=\"16\" width=\"16\" src=\"/i2psnark/_icons/" + icon + ".png\"> "; return "<img alt=\"\" height=\"16\" width=\"16\" src=\"/i2psnark/_icons/" + icon + ".png\"> ";
} }
/** @since 0.8.1 */
private void savePriorities(Snark snark, Map postParams) {
Set<Map.Entry> entries = postParams.entrySet();
for (Map.Entry entry : entries) {
String key = (String)entry.getKey();
if (key.startsWith("pri.")) {
try {
String file = key.substring(4);
String val = ((String[])entry.getValue())[0]; // jetty arrays
int pri = Integer.parseInt(val);
snark.storage.setPriority(file, pri);
//System.err.println("Priority now " + pri + " for " + file);
} catch (Throwable t) { t.printStackTrace(); }
}
}
if (snark.coordinator != null)
snark.coordinator.updatePiecePriorities();
_manager.saveTorrentStatus(snark.storage.getMetaInfo(), snark.storage.getBitField(), snark.storage.getFilePriorities());
}
/** inner class, don't bother reindenting */ /** inner class, don't bother reindenting */
private static class FetchAndAdd implements Runnable { private static class FetchAndAdd implements Runnable {

View File

@ -1,3 +1,6 @@
2010-11-03 zzz
* Merge and snark fixups
2010-11-01 zzz 2010-11-01 zzz
* ClientConnectionRunner: Add synch to fix race causing AIOOBE * ClientConnectionRunner: Add synch to fix race causing AIOOBE
(http://forum.i2p/viewtopic.php?t=5061) (http://forum.i2p/viewtopic.php?t=5061)

View File

@ -18,7 +18,7 @@ public class RouterVersion {
/** deprecated */ /** deprecated */
public final static String ID = "Monotone"; public final static String ID = "Monotone";
public final static String VERSION = CoreVersion.VERSION; public final static String VERSION = CoreVersion.VERSION;
public final static long BUILD = 8; public final static long BUILD = 10;
/** for example "-test" */ /** for example "-test" */
public final static String EXTRA = ""; public final static String EXTRA = "";