* i2psnark:

- Restore text (ticket #273)
      - Fix several HTML errors (ticket #273)
      - Fix HTML error causing info links to be unclickable in dillo (tiicket #273)
      - Fix alt text duplicated or looking bad in text browsers (ticket #273)
      - Fix Opera button errors (ticket #332)
      - Fix POST resubmission errors (ticket #334)
      - Catch FetchAndAdd copy error (ticket #352)
      - Set permissions on downloaded torrent files
      - Hide some columns when not running
      - Lots of spacing cleanups
      - Rename images so users don't end up with unused files
      - Remove ~15 unused images
      - Clean up theme selection speed-coding exercise
      - Indent fixes
This commit is contained in:
zzz
2010-12-11 13:57:14 +00:00
parent 89b3e3bcb4
commit 2ca8fc6e62
25 changed files with 352 additions and 286 deletions

View File

@ -179,7 +179,7 @@ public class SnarkManager implements Snark.CompleteListener {
if (!_config.containsKey(PROP_STARTUP_DELAY)) if (!_config.containsKey(PROP_STARTUP_DELAY))
_config.setProperty(PROP_STARTUP_DELAY, "" + DEFAULT_STARTUP_DELAY); _config.setProperty(PROP_STARTUP_DELAY, "" + DEFAULT_STARTUP_DELAY);
if (!_config.containsKey(PROP_THEME)) if (!_config.containsKey(PROP_THEME))
_config.setProperty(PROP_THEME, "" + DEFAULT_THEME); _config.setProperty(PROP_THEME, DEFAULT_THEME);
updateConfig(); updateConfig();
} }
/** /**
@ -198,11 +198,9 @@ public class SnarkManager implements Snark.CompleteListener {
public String[] getThemes() { public String[] getThemes() {
String[] themes = null; String[] themes = null;
// "docs/themes/snark/" // "docs/themes/snark/"
String fsc = new String(""+File.separatorChar); File dir = new File(_context.getBaseDir(), "docs/themes/snark");
String look = _context.getBaseDir() + fsc + "docs" + fsc +"themes" + fsc + "snark" + fsc;
FileFilter fileFilter = new FileFilter() { public boolean accept(File file) { return file.isDirectory(); } }; FileFilter fileFilter = new FileFilter() { public boolean accept(File file) { return file.isDirectory(); } };
// Walk the themes dir, collecting the theme names, and append them to the map // Walk the themes dir, collecting the theme names, and append them to the map
File dir = new File(look);
File[] dirnames = dir.listFiles(fileFilter); File[] dirnames = dir.listFiles(fileFilter);
if (dirnames != null) { if (dirnames != null) {
themes = new String[dirnames.length]; themes = new String[dirnames.length];
@ -271,7 +269,7 @@ public class SnarkManager implements Snark.CompleteListener {
public void updateConfig(String dataDir, boolean autoStart, String startDelay, String seedPct, String eepHost, public void updateConfig(String dataDir, boolean autoStart, String startDelay, String seedPct, String eepHost,
String eepPort, String i2cpHost, String i2cpPort, String i2cpOpts, String eepPort, String i2cpHost, String i2cpPort, String i2cpOpts,
String upLimit, String upBW, boolean useOpenTrackers, String openTrackers, String Theme) { String upLimit, String upBW, boolean useOpenTrackers, String openTrackers, String theme) {
boolean changed = false; boolean changed = false;
//if (eepHost != null) { //if (eepHost != null) {
// // unused, we use socket eepget // // unused, we use socket eepget
@ -434,10 +432,10 @@ public class SnarkManager implements Snark.CompleteListener {
changed = true; changed = true;
} }
} }
if (Theme != null) { if (theme != null) {
if(!Theme.equals(_config.getProperty(PROP_THEME))) { if(!theme.equals(_config.getProperty(PROP_THEME))) {
_config.setProperty(PROP_THEME, Theme +""); _config.setProperty(PROP_THEME, theme);
addMessage (Theme+(_(" theme locked and loaded."))); addMessage(_("{0} theme loaded, return to main i2psnark page to view.", theme));
changed = true; changed = true;
} }
} }
@ -935,8 +933,8 @@ public class SnarkManager implements Snark.CompleteListener {
// , "The freak's tracker", "http://mHKva9x24E5Ygfey2llR1KyQHv5f8hhMpDMwJDg1U-hABpJ2NrQJd6azirdfaR0OKt4jDlmP2o4Qx0H598~AteyD~RJU~xcWYdcOE0dmJ2e9Y8-HY51ie0B1yD9FtIV72ZI-V3TzFDcs6nkdX9b81DwrAwwFzx0EfNvK1GLVWl59Ow85muoRTBA1q8SsZImxdyZ-TApTVlMYIQbdI4iQRwU9OmmtefrCe~ZOf4UBS9-KvNIqUL0XeBSqm0OU1jq-D10Ykg6KfqvuPnBYT1BYHFDQJXW5DdPKwcaQE4MtAdSGmj1epDoaEBUa9btQlFsM2l9Cyn1hzxqNWXELmx8dRlomQLlV4b586dRzW~fLlOPIGC13ntPXogvYvHVyEyptXkv890jC7DZNHyxZd5cyrKC36r9huKvhQAmNABT2Y~pOGwVrb~RpPwT0tBuPZ3lHYhBFYmD8y~AOhhNHKMLzea1rfwTvovBMByDdFps54gMN1mX4MbCGT4w70vIopS9yAAAA.i2p/bytemonsoon/announce.php" // , "The freak's tracker", "http://mHKva9x24E5Ygfey2llR1KyQHv5f8hhMpDMwJDg1U-hABpJ2NrQJd6azirdfaR0OKt4jDlmP2o4Qx0H598~AteyD~RJU~xcWYdcOE0dmJ2e9Y8-HY51ie0B1yD9FtIV72ZI-V3TzFDcs6nkdX9b81DwrAwwFzx0EfNvK1GLVWl59Ow85muoRTBA1q8SsZImxdyZ-TApTVlMYIQbdI4iQRwU9OmmtefrCe~ZOf4UBS9-KvNIqUL0XeBSqm0OU1jq-D10Ykg6KfqvuPnBYT1BYHFDQJXW5DdPKwcaQE4MtAdSGmj1epDoaEBUa9btQlFsM2l9Cyn1hzxqNWXELmx8dRlomQLlV4b586dRzW~fLlOPIGC13ntPXogvYvHVyEyptXkv890jC7DZNHyxZd5cyrKC36r9huKvhQAmNABT2Y~pOGwVrb~RpPwT0tBuPZ3lHYhBFYmD8y~AOhhNHKMLzea1rfwTvovBMByDdFps54gMN1mX4MbCGT4w70vIopS9yAAAA.i2p/bytemonsoon/announce.php"
// , "mastertracker", "http://VzXD~stRKbL3MOmeTn1iaCQ0CFyTmuFHiKYyo0Rd~dFPZFCYH-22rT8JD7i-C2xzYFa4jT5U2aqHzHI-Jre4HL3Ri5hFtZrLk2ax3ji7Qfb6qPnuYkuiF2E2UDmKUOppI8d9Ye7tjdhQVCy0izn55tBaB-U7UWdcvSK2i85sauyw3G0Gfads1Rvy5-CAe2paqyYATcDmGjpUNLoxbfv9KH1KmwRTNH6k1v4PyWYYnhbT39WfKMbBjSxVQRdi19cyJrULSWhjxaQfJHeWx5Z8Ev4bSPByBeQBFl2~4vqy0S5RypINsRSa3MZdbiAAyn5tr5slWR6QdoqY3qBQgBJFZppy-3iWkFqqKgSxCPundF8gdDLC5ddizl~KYcYKl42y9SGFHIukH-TZs8~em0~iahzsqWVRks3zRG~tlBcX2U3M2~OJs~C33-NKhyfZT7-XFBREvb8Szmd~p66jDxrwOnKaku-G6DyoQipJqIz4VHmY9-y5T8RrUcJcM-5lVoMpAAAA.i2p/announce.php=http://tracker.mastertracker.i2p/" // , "mastertracker", "http://VzXD~stRKbL3MOmeTn1iaCQ0CFyTmuFHiKYyo0Rd~dFPZFCYH-22rT8JD7i-C2xzYFa4jT5U2aqHzHI-Jre4HL3Ri5hFtZrLk2ax3ji7Qfb6qPnuYkuiF2E2UDmKUOppI8d9Ye7tjdhQVCy0izn55tBaB-U7UWdcvSK2i85sauyw3G0Gfads1Rvy5-CAe2paqyYATcDmGjpUNLoxbfv9KH1KmwRTNH6k1v4PyWYYnhbT39WfKMbBjSxVQRdi19cyJrULSWhjxaQfJHeWx5Z8Ev4bSPByBeQBFl2~4vqy0S5RypINsRSa3MZdbiAAyn5tr5slWR6QdoqY3qBQgBJFZppy-3iWkFqqKgSxCPundF8gdDLC5ddizl~KYcYKl42y9SGFHIukH-TZs8~em0~iahzsqWVRks3zRG~tlBcX2U3M2~OJs~C33-NKhyfZT7-XFBREvb8Szmd~p66jDxrwOnKaku-G6DyoQipJqIz4VHmY9-y5T8RrUcJcM-5lVoMpAAAA.i2p/announce.php=http://tracker.mastertracker.i2p/"
// , "Galen", "http://5jpwQMI5FT303YwKa5Rd38PYSX04pbIKgTaKQsWbqoWjIfoancFdWCShXHLI5G5ofOb0Xu11vl2VEMyPsg1jUFYSVnu4-VfMe3y4TKTR6DTpetWrnmEK6m2UXh91J5DZJAKlgmO7UdsFlBkQfR2rY853-DfbJtQIFl91tbsmjcA5CGQi4VxMFyIkBzv-pCsuLQiZqOwWasTlnzey8GcDAPG1LDcvfflGV~6F5no9mnuisZPteZKlrv~~TDoXTj74QjByWc4EOYlwqK8sbU9aOvz~s31XzErbPTfwiawiaZ0RUI-IDrKgyvmj0neuFTWgjRGVTH8bz7cBZIc3viy6ioD-eMQOrXaQL0TCWZUelRwHRvgdPiQrxdYQs7ixkajeHzxi-Pq0EMm5Vbh3j3Q9kfUFW3JjFDA-MLB4g6XnjCbM5J1rC0oOBDCIEfhQkszru5cyLjHiZ5yeA0VThgu~c7xKHybv~OMXION7V8pBKOgET7ZgAkw1xgYe3Kkyq5syAAAA.i2p/tr/announce.php=http://galen.i2p/tr/" // , "Galen", "http://5jpwQMI5FT303YwKa5Rd38PYSX04pbIKgTaKQsWbqoWjIfoancFdWCShXHLI5G5ofOb0Xu11vl2VEMyPsg1jUFYSVnu4-VfMe3y4TKTR6DTpetWrnmEK6m2UXh91J5DZJAKlgmO7UdsFlBkQfR2rY853-DfbJtQIFl91tbsmjcA5CGQi4VxMFyIkBzv-pCsuLQiZqOwWasTlnzey8GcDAPG1LDcvfflGV~6F5no9mnuisZPteZKlrv~~TDoXTj74QjByWc4EOYlwqK8sbU9aOvz~s31XzErbPTfwiawiaZ0RUI-IDrKgyvmj0neuFTWgjRGVTH8bz7cBZIc3viy6ioD-eMQOrXaQL0TCWZUelRwHRvgdPiQrxdYQs7ixkajeHzxi-Pq0EMm5Vbh3j3Q9kfUFW3JjFDA-MLB4g6XnjCbM5J1rC0oOBDCIEfhQkszru5cyLjHiZ5yeA0VThgu~c7xKHybv~OMXION7V8pBKOgET7ZgAkw1xgYe3Kkyq5syAAAA.i2p/tr/announce.php=http://galen.i2p/tr/"
"POSTMAN", "http://tracker2.postman.i2p/announce.php=http://tracker2.postman.i2p/" "Postman", "http://tracker2.postman.i2p/announce.php=http://tracker2.postman.i2p/"
,"WELTERDE", "http://tracker.welterde.i2p/a=http://tracker.welterde.i2p/stats?mode=top5" ,"Welterde", "http://tracker.welterde.i2p/a=http://tracker.welterde.i2p/stats?mode=top5"
// , "CRSTRACK", "http://b4G9sCdtfvccMAXh~SaZrPqVQNyGQbhbYMbw6supq2XGzbjU4NcOmjFI0vxQ8w1L05twmkOvg5QERcX6Mi8NQrWnR0stLExu2LucUXg1aYjnggxIR8TIOGygZVIMV3STKH4UQXD--wz0BUrqaLxPhrm2Eh9Hwc8TdB6Na4ShQUq5Xm8D4elzNUVdpM~RtChEyJWuQvoGAHY3ppX-EJJLkiSr1t77neS4Lc-KofMVmgI9a2tSSpNAagBiNI6Ak9L1T0F9uxeDfEG9bBSQPNMOSUbAoEcNxtt7xOW~cNOAyMyGydwPMnrQ5kIYPY8Pd3XudEko970vE0D6gO19yoBMJpKx6Dh50DGgybLQ9CpRaynh2zPULTHxm8rneOGRcQo8D3mE7FQ92m54~SvfjXjD2TwAVGI~ae~n9HDxt8uxOecAAvjjJ3TD4XM63Q9TmB38RmGNzNLDBQMEmJFpqQU8YeuhnS54IVdUoVQFqui5SfDeLXlSkh4vYoMU66pvBfWbAAAA.i2p/tracker/announce.php=http://crstrack.i2p/tracker/" // , "CRSTRACK", "http://b4G9sCdtfvccMAXh~SaZrPqVQNyGQbhbYMbw6supq2XGzbjU4NcOmjFI0vxQ8w1L05twmkOvg5QERcX6Mi8NQrWnR0stLExu2LucUXg1aYjnggxIR8TIOGygZVIMV3STKH4UQXD--wz0BUrqaLxPhrm2Eh9Hwc8TdB6Na4ShQUq5Xm8D4elzNUVdpM~RtChEyJWuQvoGAHY3ppX-EJJLkiSr1t77neS4Lc-KofMVmgI9a2tSSpNAagBiNI6Ak9L1T0F9uxeDfEG9bBSQPNMOSUbAoEcNxtt7xOW~cNOAyMyGydwPMnrQ5kIYPY8Pd3XudEko970vE0D6gO19yoBMJpKx6Dh50DGgybLQ9CpRaynh2zPULTHxm8rneOGRcQo8D3mE7FQ92m54~SvfjXjD2TwAVGI~ae~n9HDxt8uxOecAAvjjJ3TD4XM63Q9TmB38RmGNzNLDBQMEmJFpqQU8YeuhnS54IVdUoVQFqui5SfDeLXlSkh4vYoMU66pvBfWbAAAA.i2p/tracker/announce.php=http://crstrack.i2p/tracker/"
}; };

View File

@ -31,6 +31,7 @@ import net.i2p.data.DataHelper;
import net.i2p.util.FileUtil; import net.i2p.util.FileUtil;
import net.i2p.util.I2PAppThread; import net.i2p.util.I2PAppThread;
import net.i2p.util.Log; import net.i2p.util.Log;
import net.i2p.util.SecureFileOutputStream;
import org.klomp.snark.MetaInfo; import org.klomp.snark.MetaInfo;
import org.klomp.snark.Peer; import org.klomp.snark.Peer;
@ -55,6 +56,8 @@ public class I2PSnarkServlet extends Default {
private SnarkManager _manager; private SnarkManager _manager;
private static long _nonce; private static long _nonce;
private Resource _resourceBase; private Resource _resourceBase;
private String _themePath;
private String _imgPath;
public static final String PROP_CONFIG_FILE = "i2psnark.configFile"; public static final String PROP_CONFIG_FILE = "i2psnark.configFile";
@ -124,11 +127,13 @@ public class I2PSnarkServlet extends Default {
resp.sendError(HttpResponse.__405_Method_Not_Allowed); resp.sendError(HttpResponse.__405_Method_Not_Allowed);
return; return;
} }
_themePath = "/themes/snark/" + _manager.getTheme() + '/';
_imgPath = _themePath + "images/";
// this is the part after /i2psnark // this is the part after /i2psnark
String path = req.getServletPath(); String path = req.getServletPath();
boolean isConfigure = "/configure".equals(path); boolean isConfigure = "/configure".equals(path);
// index.jsp doesn't work, it is grabbed by the war handler before here // index.jsp doesn't work, it is grabbed by the war handler before here
if (!(path == null || path.equals("/") || path.equals("/index.jsp") || path.equals("/index.html") || isConfigure)) { if (!(path == null || path.equals("/") || path.equals("/index.jsp") || path.equals("/index.html") || path.equals("/_post") || isConfigure)) {
if (path.endsWith("/")) { if (path.endsWith("/")) {
// bypass the horrid Resource.getListHTML() // bypass the horrid Resource.getListHTML()
String pathInfo = req.getPathInfo(); String pathInfo = req.getPathInfo();
@ -158,8 +163,12 @@ public class I2PSnarkServlet extends Default {
resp.setContentType("text/html; charset=UTF-8"); resp.setContentType("text/html; charset=UTF-8");
String nonce = req.getParameter("nonce"); String nonce = req.getParameter("nonce");
if ( (nonce != null) && (nonce.equals(String.valueOf(_nonce))) ) if (nonce != null) {
processRequest(req); if (nonce.equals(String.valueOf(_nonce)))
processRequest(req);
else // nonce is constant, shouldn't happen
_manager.addMessage("Please retry form submission (bad nonce)");
}
String peerParam = req.getParameter("p"); String peerParam = req.getParameter("p");
String peerString; String peerString;
@ -170,8 +179,8 @@ public class I2PSnarkServlet extends Default {
} }
PrintWriter out = resp.getWriter(); PrintWriter out = resp.getWriter();
out.write("<html>\n" + out.write(DOCTYPE + "<html>\n" +
"<head><link rel=\"shortcut icon\" href=\"/themes/snark/" + _manager.getTheme() + "/favicon.ico\">\n" + "<head><link rel=\"shortcut icon\" href=\"" + _themePath + "favicon.ico\">\n" +
"<title>"); "<title>");
out.write(_("I2PSnark - Anonymous BitTorrent Client")); out.write(_("I2PSnark - Anonymous BitTorrent Client"));
if ("2".equals(peerParam)) if ("2".equals(peerParam))
@ -180,22 +189,22 @@ public class I2PSnarkServlet extends Default {
// we want it to go to the base URI so we don't refresh with some funky action= value // we want it to go to the base URI so we don't refresh with some funky action= value
if (!isConfigure) if (!isConfigure)
out.write("<meta http-equiv=\"refresh\" content=\"60;" + req.getRequestURI() + peerString + "\">\n"); out.write("<meta http-equiv=\"refresh\" content=\"60;/i2psnark/" + peerString + "\">\n");
out.write(HEADER_A + _manager.getTheme() + HEADER_B); out.write(HEADER_A + _themePath + HEADER_B);
out.write("</head><body>"); out.write("</head><body>");
out.write("<center>"); out.write("<center>");
if (isConfigure) { if (isConfigure) {
out.write("<div class=\"snarknavbar\"><a href=\"/i2psnark/\" title=\""); out.write("<div class=\"snarknavbar\"><a href=\"/i2psnark/\" title=\"");
out.write(_("Torrents")); out.write(_("Torrents"));
out.write("\" class=\"snarkRefresh\">"); out.write("\" class=\"snarkRefresh\">");
out.write("<img border=\"0\" src=\"/themes/snark/" + _manager.getTheme() + "/images/arrow_refresh.png\"> "); out.write("<img alt=\"\" border=\"0\" src=\"" + _imgPath + "arrow_refresh.png\">&nbsp;&nbsp;");
out.write(_("I2PSnark")); out.write(_("I2PSnark"));
out.write("</a>"); out.write("</a>");
} else { } else {
out.write("<div class=\"snarknavbar\"><a href=\"" + req.getRequestURI() + peerString + "\" title=\""); out.write("<div class=\"snarknavbar\"><a href=\"/i2psnark/" + 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/" + _manager.getTheme() + "/images/arrow_refresh.png\"> "); out.write("<img alt=\"\" border=\"0\" src=\"" + _imgPath + "arrow_refresh.png\">&nbsp;&nbsp;");
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"));
@ -244,85 +253,103 @@ public class I2PSnarkServlet extends Default {
String uri = req.getRequestURI(); String uri = req.getRequestURI();
boolean isForm = _manager.util().connected() || !snarks.isEmpty(); boolean isForm = _manager.util().connected() || !snarks.isEmpty();
if (isForm) { if (isForm) {
out.write("<form action=\""); out.write("<form action=\"_post\" method=\"POST\">\n");
out.write(uri);
out.write("\" method=\"POST\">\n");
out.write("<input type=\"hidden\" name=\"nonce\" value=\"" + _nonce + "\" >\n"); out.write("<input type=\"hidden\" name=\"nonce\" value=\"" + _nonce + "\" >\n");
// don't lose peer setting // don't lose peer setting
if (peerParam != null) if (peerParam != null)
out.write("<input type=\"hidden\" name=\"p\" value=\"" + peerParam + "\" >\n"); out.write("<input type=\"hidden\" name=\"p\" value=\"" + peerParam + "\" >\n");
} }
out.write(TABLE_HEADER); out.write(TABLE_HEADER);
out.write("<img border=\"0\" src=\"/themes/snark/" + _manager.getTheme() + "/images/status.png\""); out.write("<img alt=\"\" border=\"0\" src=\"" + _imgPath + "status.png\" > ");
out.write(" title=\"");
out.write(_("Status")); out.write(_("Status"));
out.write("\"> ");
// out.write(_("Status"));
if (_manager.util().connected() && !snarks.isEmpty()) { if (_manager.util().connected() && !snarks.isEmpty()) {
out.write(" <a href=\""); out.write(" <a href=\"/i2psnark/");
out.write(req.getRequestURI());
if (peerParam != null) { if (peerParam != null) {
out.write("\">"); out.write("\">");
out.write("<img border=\"0\" src=\"/themes/snark/" + _manager.getTheme() + "/images/showpeers.png\" title=\""); out.write("<img border=\"0\" src=\"" + _imgPath + "hidepeers.png\" title=\"");
out.write(_("Hide All Attached Peers [connected/total in swarm]")); out.write(_("Hide Peers"));
out.write("\" alt=\""); out.write("\" alt=\"");
out.write(_("Hide Peers")); out.write(_("Hide Peers"));
out.write("\">"); out.write("\">");
} else { } else {
out.write("?p=1\">"); out.write("?p=1\">");
out.write("<img border=\"0\" src=\"/themes/snark/" + _manager.getTheme() + "/images/hidepeers.png\" title=\""); out.write("<img border=\"0\" src=\"" + _imgPath + "showpeers.png\" title=\"");
out.write(_("Show All Attached Peers [connected/total in swarm]")); out.write(_("Show Peers"));
out.write("\" alt=\""); out.write("\" alt=\"");
out.write(_("Show Peers")); out.write(_("Show Peers"));
out.write("\">"); out.write("\">");
} }
out.write("</a><br>\n"); out.write("</a><br>\n");
} }
out.write("</th>\n<th align=\"left\">"); out.write("</th>\n<th colspan=\"3\" align=\"left\">");
// out.write("<img border=\"0\" src=\"/themes/snark/" + _manager.getTheme() + "/images/torrent.png\"\">"); out.write("<img border=\"0\" src=\"" + _imgPath + "torrent.png\" alt=\"\">");
out.write("<img border=\"0\" src=\"/themes/snark/" + _manager.getTheme() + "/images/head_torrent.png\" title=\""); out.write(_("Torrent"));
out.write(_("Loaded Torrents")); out.write("</th>\n<th align=\"right\">");
out.write("\">"); if (_manager.util().connected() && !snarks.isEmpty()) {
// out.write(_("Torrent")); out.write("<img border=\"0\" src=\"" + _imgPath + "eta.png\" alt=\"\" title=\"");
out.write("</th>\n<th align=\"center\">"); out.write(_("Estimated time remaining"));
out.write("<img border=\"0\" src=\"/themes/snark/" + _manager.getTheme() + "/images/head_eta.png\" title=\""); out.write("\">");
out.write(_("Estimated Download Time")); out.write(_("ETA"));
out.write("\">"); // space here would look better but nbsp is too big and thinsp breaks }
// out.write(_("ETA")); out.write("</th>\n<th align=\"right\">");
out.write("</th>\n<th align=\"center\">"); out.write("<img border=\"0\" src=\"" + _imgPath + "head_rx.png\" alt=\"\" title=\"");
out.write("<img border=\"0\" src=\"/themes/snark/" + _manager.getTheme() + "/images/head_rx.png\" title=\"");
out.write(_("Downloaded")); out.write(_("Downloaded"));
out.write("\">"); out.write("\">");
// out.write(_("RX")); out.write(_("RX"));
out.write("</th>\n<th align=\"right\">");
if (_manager.util().connected() && !snarks.isEmpty()) {
out.write("<img border=\"0\" src=\"" + _imgPath + "head_tx.png\" alt=\"\" title=\"");
out.write(_("Uploaded"));
out.write("\">");
out.write(_("TX"));
}
out.write("</th>\n<th align=\"right\">");
if (_manager.util().connected() && !snarks.isEmpty()) {
out.write("<img border=\"0\" src=\"" + _imgPath + "head_rxspeed.png\" title=\"");
out.write(_("Down Rate"));
out.write("\" alt=\"");
out.write(_("RX"));
out.write(" \">");
out.write(_("Rate"));
}
out.write("</th>\n<th align=\"right\">");
if (_manager.util().connected() && !snarks.isEmpty()) {
out.write("<img border=\"0\" src=\"" + _imgPath + "head_txspeed.png\" title=\"");
out.write(_("Up Rate"));
out.write("\" alt=\"");
out.write(_("TX"));
out.write(" \">");
out.write(_("Rate"));
}
out.write("</th>\n<th align=\"center\">"); out.write("</th>\n<th align=\"center\">");
out.write("<img border=\"0\" src=\"/themes/snark/" + _manager.getTheme() + "/images/head_tx.png\" title=\"");
out.write(_("Uploaded")); // Opera and text-mode browsers: no &thinsp; and no input type=image values submitted
out.write("\">"); String ua = req.getHeader("User-Agent");
// out.write(_("TX")); boolean isDegraded = ua != null && (ua.startsWith("Opera") || ua.startsWith("Lynx") ||
out.write("</th>\n<th align=\"center\">"); ua.startsWith("ELinks") || ua.startsWith("Dillo"));
out.write("<img border=\"0\" src=\"/themes/snark/" + _manager.getTheme() + "/images/head_rxspeed.png\" title=\"");
out.write(_("Down Rate"));
out.write("\">");
// out.write(_("Rate"));
out.write("</th>\n<th align=\"center\">");
out.write("<img border=\"0\" src=\"/themes/snark/" + _manager.getTheme() + "/images/head_txspeed.png\" title=\"");
out.write(_("Up Rate"));
out.write("\">");
// out.write(_("Rate"));
out.write("</th>\n");
out.write("<th align=\"center\">");
if (_manager.util().connected()) { if (_manager.util().connected()) {
out.write("<input type=\"image\" name=\"action\" value=\"StopAll\" title=\""); if (isDegraded)
out.write("<a href=\"/i2psnark/?action=StopAll&amp;nonce=" + _nonce + "\"><img title=\"");
else
out.write("<input type=\"image\" name=\"action\" value=\"StopAll\" title=\"");
out.write(_("Stop all torrents and the I2P tunnel")); out.write(_("Stop all torrents and the I2P tunnel"));
out.write("\" src=\"/themes/snark/" + _manager.getTheme() + "/images/stop_all.png\" alt=\""); out.write("\" src=\"" + _imgPath + "stop_all.png\" alt=\"");
out.write(_("Stop All")); out.write(_("Stop All"));
out.write("\">"); out.write("\">");
if (isDegraded)
out.write("</a>");
} else if (!snarks.isEmpty()) { } else if (!snarks.isEmpty()) {
out.write("<input type=\"image\" name=\"action\" value=\"StartAll\" title=\""); if (isDegraded)
out.write("<a href=\"/i2psnark/?action=StartAll&amp;nonce=" + _nonce + "\"><img title=\"");
else
out.write("<input type=\"image\" name=\"action\" value=\"StartAll\" title=\"");
out.write(_("Start all torrents and the I2P tunnel")); out.write(_("Start all torrents and the I2P tunnel"));
out.write("\" src=\"/themes/snark/" + _manager.getTheme() + "/images/start_all.png\" alt=\""); out.write("\" src=\"" + _imgPath + "start_all.png\" alt=\"");
out.write(_("Start All")); out.write(_("Start All"));
out.write("\">"); out.write("\">");
if (isDegraded)
out.write("</a>");
} else { } else {
out.write("&nbsp;"); out.write("&nbsp;");
} }
@ -331,55 +358,35 @@ public class I2PSnarkServlet extends Default {
Snark snark = (Snark)snarks.get(i); Snark snark = (Snark)snarks.get(i);
boolean showDebug = "2".equals(peerParam); boolean showDebug = "2".equals(peerParam);
boolean showPeers = showDebug || "1".equals(peerParam) || Base64.encode(snark.meta.getInfoHash()).equals(peerParam); boolean showPeers = showDebug || "1".equals(peerParam) || Base64.encode(snark.meta.getInfoHash()).equals(peerParam);
displaySnark(out, snark, uri, i, stats, showPeers, showDebug); displaySnark(out, snark, uri, i, stats, showPeers, isDegraded, showDebug);
} }
if (snarks.isEmpty()) { if (snarks.isEmpty()) {
out.write("<tr class=\"snarkTorrentNoneLoaded\">" + out.write("<tr class=\"snarkTorrentNoneLoaded\">" +
"<td class=\"snarkTorrentNoneLoaded\"" + "<td class=\"snarkTorrentNoneLoaded\"" +
" colspan=\"8\"><i>"); " colspan=\"11\"><i>");
out.write(_("No torrents loaded.")); out.write(_("No torrents loaded."));
out.write("</i></td></tr>\n"); out.write("</i></td></tr>\n");
} else if (snarks.size() > 1) { } else if (snarks.size() > 1) {
out.write("<tfoot><tr>\n" + out.write("<tfoot><tr>\n" +
// " <th align=\"left\" colspan=\"2\">"); " <th align=\"left\" colspan=\"6\">");
" <th align=\"left\">");
// out.write(_("Totals"));
// out.write(" &raquo;&nbsp;");
out.write("<img border=\"0\" src=\"/themes/snark/" + _manager.getTheme() + "/images/status.png\"");
out.write(" title=\"");
out.write(_("Totals")); out.write(_("Totals"));
out.write("\">"); out.write(":&nbsp;");
out.write("&thinsp;"); out.write(ngettext("1 torrent", "{0} torrents", snarks.size()));
// out.write(ngettext("1 connected peer", "{0} connected peers", (int) stats[4])); out.write(", ");
out.write("<img border=\"0\" src=\"/themes/snark/" + _manager.getTheme() + "/images/head_peers.png\""); out.write(DataHelper.formatSize2(stats[5]) + "B, ");
out.write(" title=\"");
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("\">"); out.write("</th>\n");
out.write(ngettext("1", "{0}", (int) stats[4])); if (_manager.util().connected()) {
out.write("</th>"); out.write(" <th align=\"right\">" + formatSize(stats[0]) + "</th>\n" +
// out.write("&nbsp;&nbsp;");
// out.write(ngettext("1 torrent", "{0} torrents", snarks.size()));
out.write("<th><img border=\"0\" src=\"/themes/snark/" + _manager.getTheme() + "/images/head_snarks.png\"");
out.write(" title=\"");
out.write(ngettext("1 torrent loaded", "{0} torrents loaded", snarks.size()));
out.write("\">");
out.write(ngettext("1", "{0}", snarks.size()));
out.write("&nbsp;&nbsp;");
out.write("<img border=\"0\" src=\"/themes/snark/" + _manager.getTheme() + "/images/head_loaded.png\"");
out.write(" title=\"");
out.write(_("Total download size (pre-allocated): "));
out.write(DataHelper.formatSize2(stats[5]) + "B");
out.write("\">");
out.write(DataHelper.formatSize2(stats[5]) + "B");
out.write("</th>\n" +
" <th>&nbsp;</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" +
" <th align=\"right\">" + formatSize(stats[2]) + "ps</th>\n" + " <th align=\"right\">" + formatSize(stats[2]) + "ps</th>\n" +
" <th align=\"right\">" + formatSize(stats[3]) + "ps</th>\n" + " <th align=\"right\">" + formatSize(stats[3]) + "ps</th>\n" +
" <th>&nbsp;</th></tr>\n" + " <th></th>");
"</tfoot>\n"); } else {
out.write("<th colspan=\"5\"></th>");
}
out.write("</tr></tfoot>\n");
} }
out.write("</table>"); out.write("</table>");
@ -393,14 +400,18 @@ public class I2PSnarkServlet extends Default {
private void processRequest(HttpServletRequest req) { private void processRequest(HttpServletRequest req) {
String action = req.getParameter("action"); String action = req.getParameter("action");
if (action == null) { if (action == null) {
// noop _manager.addMessage("No action specified");
return; return;
} }
if (!"POST".equals(req.getMethod())) // sadly, Opera doesn't send value with input type=image, so we have to use GET there
return; //if (!"POST".equals(req.getMethod())) {
// _manager.addMessage("Action must be with POST");
// return;
//}
if ("Add".equals(action)) { if ("Add".equals(action)) {
String newFile = req.getParameter("newFile"); String newFile = req.getParameter("newFile");
String newURL = req.getParameter("newURL"); String newURL = req.getParameter("newURL");
/******
// NOTE - newFile currently disabled in HTML form - see below // NOTE - newFile currently disabled in HTML form - see below
File f = null; File f = null;
if ( (newFile != null) && (newFile.trim().length() > 0) ) if ( (newFile != null) && (newFile.trim().length() > 0) )
@ -409,6 +420,7 @@ public class I2PSnarkServlet extends Default {
_manager.addMessage(_("Torrent file {0} does not exist", newFile)); _manager.addMessage(_("Torrent file {0} does not exist", newFile));
} }
if ( (f != null) && (f.exists()) ) { if ( (f != null) && (f.exists()) ) {
// NOTE - All this is disabled - load from local file disabled
File local = new File(_manager.getDataDir(), f.getName()); File local = new File(_manager.getDataDir(), f.getName());
String canonical = null; String canonical = null;
try { try {
@ -431,7 +443,9 @@ public class I2PSnarkServlet extends Default {
} catch (IOException ioe) { } catch (IOException ioe) {
_log.warn("hrm: " + local, ioe); _log.warn("hrm: " + local, ioe);
} }
} else if (newURL != null) { } else
*****/
if (newURL != null) {
if (newURL.startsWith("http://")) { if (newURL.startsWith("http://")) {
_manager.addMessage(_("Fetching {0}", urlify(newURL))); _manager.addMessage(_("Fetching {0}", urlify(newURL)));
I2PAppThread fetch = new I2PAppThread(new FetchAndAdd(_manager, newURL), "Fetch and add"); I2PAppThread fetch = new I2PAppThread(new FetchAndAdd(_manager, newURL), "Fetch and add");
@ -616,6 +630,8 @@ public class I2PSnarkServlet extends Default {
if (snark.stopped) if (snark.stopped)
snark.startTorrent(); snark.startTorrent();
} }
} else {
_manager.addMessage("Unknown POST action: \"" + action + '\"');
} }
} }
@ -676,8 +692,9 @@ public class I2PSnarkServlet extends Default {
} }
private static final int MAX_DISPLAYED_FILENAME_LENGTH = 50; private static final int MAX_DISPLAYED_FILENAME_LENGTH = 50;
private static final int MAX_DISPLAYED_ERROR_LENGTH = 6; private static final int MAX_DISPLAYED_ERROR_LENGTH = 43;
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 isDegraded, boolean showDebug) throws IOException {
String filename = snark.torrent; String filename = snark.torrent;
File f = new File(filename); File f = new File(filename);
filename = f.getName(); // the torrent may be the canonical name, so lets just grab the local name filename = f.getName(); // the torrent may be the canonical name, so lets just grab the local name
@ -731,97 +748,69 @@ public class I2PSnarkServlet extends Default {
knownPeers = Math.max(curPeers, snark.coordinator.trackerSeenPeers); knownPeers = Math.max(curPeers, snark.coordinator.trackerSeenPeers);
} }
String statusString = _("Unknown"); String rowClass = (row % 2 == 0 ? "snarkTorrentEven" : "snarkTorrentOdd");
String statusString;
if (err != null) { if (err != null) {
if (isRunning && curPeers > 0 && !showPeers) if (isRunning && curPeers > 0 && !showPeers)
statusString = "<img border=\"0\" src=\"/themes/snark/" + _manager.getTheme() + "/images/trackererror.png\" title=\"" + _("Tracker Error") + statusString = "<img alt=\"\" border=\"0\" src=\"" + _imgPath + "trackererror.png\" title=\"" + err + "\"></td><td class=\"snarkTorrentStatus " + rowClass + "\">" + _("Tracker Error") +
"\"><a href=\"" + uri + "?p=" + Base64.encode(snark.meta.getInfoHash()) + "\">" + ": <a href=\"" + uri + "?p=" + Base64.encode(snark.meta.getInfoHash()) + "\">" +
' ' + curPeers + "&thinsp;/&thinsp;" + curPeers + thinsp(isDegraded) +
// ngettext("1 peer", "{0} peers", knownPeers) + "</a>"; ngettext("1 peer", "{0} peers", knownPeers) + "</a>";
ngettext("1", "{0}", knownPeers) + "</a>";
else if (isRunning) else if (isRunning)
statusString = "<img border=\"0\" src=\"/themes/snark/" + _manager.getTheme() + "/images/trackererror.png\" title=\"" + _("Tracker Error") + statusString = "<img alt=\"\" border=\"0\" src=\"" + _imgPath + "trackererror.png\" title=\"" + err + "\"></td><td class=\"snarkTorrentStatus " + rowClass + "\">" + _("Tracker Error") +
"\">" + ' ' + curPeers + "&thinsp;/&thinsp;" + ": " + curPeers + thinsp(isDegraded) +
// ngettext("1 peer", "{0} peers", knownPeers) + "</a>"; ngettext("1 peer", "{0} peers", knownPeers);
ngettext("1", "{0}", 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 = "<img border=\"0\" src=\"/themes/snark/" + _manager.getTheme() + "/images/trackererror.png\" title=\"" + _("Tracker Error") + statusString = "<img alt=\"\" border=\"0\" src=\"" + _imgPath + "trackererror.png\" title=\"" + err + "\"></td><td class=\"snarkTorrentStatus " + rowClass + "\">" + _("Tracker Error") +
"\"> " + err + "</a>"; "<br>" + err;
} }
} else if (remaining <= 0) { } else if (remaining <= 0) {
if (isRunning && curPeers > 0 && !showPeers) if (isRunning && curPeers > 0 && !showPeers)
statusString = "<img border=\"0\" src=\"/themes/snark/" + _manager.getTheme() + "/images/seeding.png\" title=\"" + _("Seeding") + "\">" + statusString = "<img alt=\"\" border=\"0\" src=\"" + _imgPath + "seeding.png\" ></td><td class=\"snarkTorrentStatus " + rowClass + "\">" + _("Seeding") +
"<a href=\"" + uri + "?p=" + Base64.encode(snark.meta.getInfoHash()) + "\">" + ": <a href=\"" + uri + "?p=" + Base64.encode(snark.meta.getInfoHash()) + "\">" +
' ' + curPeers + "&thinsp;/&thinsp;" + curPeers + thinsp(isDegraded) +
// ngettext("1 peer", "{0} peers", knownPeers) + "</a>"; ngettext("1 peer", "{0} peers", knownPeers) + "</a>";
ngettext("1", "{0}", knownPeers) + "</a>";
else if (isRunning) else if (isRunning)
statusString = "<img border=\"0\" src=\"/themes/snark/" + _manager.getTheme() + "/images/seeding.png\" title=\"" + _("Seeding") + "\">" + statusString = "<img alt=\"\" border=\"0\" src=\"" + _imgPath + "seeding.png\" ></td><td class=\"snarkTorrentStatus " + rowClass + "\">" + _("Seeding") +
' ' + curPeers + "&thinsp;/&thinsp;" + ": " + curPeers + thinsp(isDegraded) +
// ngettext("1 peer", "{0} peers", knownPeers) + "</a>"; ngettext("1 peer", "{0} peers", knownPeers);
ngettext("1", "{0}", knownPeers) + "</a>";
else else
statusString = "<img border=\"0\" src=\"/themes/snark/" + _manager.getTheme() + "/images/complete.png\" title=\"" + _("Complete") + "\"> " + _("Complete"); statusString = "<img alt=\"\" border=\"0\" src=\"" + _imgPath + "complete.png\" ></td><td class=\"snarkTorrentStatus " + rowClass + "\">" + _("Complete");
} else { } else {
if (isRunning && curPeers > 0 && downBps > 0 && !showPeers) if (isRunning && curPeers > 0 && downBps > 0 && !showPeers)
statusString = "<img border=\"0\" src=\"/themes/snark/" + _manager.getTheme() + "/images/downloading.png\" title=\"" + _("Downloading") + "\">" + statusString = "<img alt=\"\" border=\"0\" src=\"" + _imgPath + "downloading.png\" ></td><td class=\"snarkTorrentStatus " + rowClass + "\">" + _("OK") +
"<a href=\"" + uri + "?p=" + Base64.encode(snark.meta.getInfoHash()) + "\">" + ": <a href=\"" + uri + "?p=" + Base64.encode(snark.meta.getInfoHash()) + "\">" +
' ' + curPeers + "&thinsp;/&thinsp;" + curPeers + thinsp(isDegraded) +
// ngettext("1 peer", "{0} peers", knownPeers) + "</a>"; ngettext("1 peer", "{0} peers", knownPeers) + "</a>";
ngettext("1", "{0}", knownPeers) + "</a>";
else if (isRunning && curPeers > 0 && downBps > 0) else if (isRunning && curPeers > 0 && downBps > 0)
statusString = "<img border=\"0\" src=\"/themes/snark/" + _manager.getTheme() + "/images/downloading.png\" title=\"" + _("Downloading") + "\">" + statusString = "<img alt=\"\" border=\"0\" src=\"" + _imgPath + "downloading.png\" ></td><td class=\"snarkTorrentStatus " + rowClass + "\">" + _("OK") +
' ' + curPeers + "&thinsp;/&thinsp;" + ": " + curPeers + thinsp(isDegraded) +
ngettext("1", "{0}", knownPeers); ngettext("1 peer", "{0} peers", knownPeers);
// ngettext("1 peer", "{0} peers", knownPeers);
else if (isRunning && curPeers > 0 && !showPeers) else if (isRunning && curPeers > 0 && !showPeers)
statusString = "<img border=\"0\" src=\"/themes/snark/" + _manager.getTheme() + "/images/stalled.png\" title=\"" + _("Stalled") + "\">" + statusString = "<img alt=\"\" border=\"0\" src=\"" + _imgPath + "stalled.png\" ></td><td class=\"snarkTorrentStatus " + rowClass + "\">" + _("Stalled") +
"<a href=\"" + uri + "?p=" + Base64.encode(snark.meta.getInfoHash()) + "\">" + ": <a href=\"" + uri + "?p=" + Base64.encode(snark.meta.getInfoHash()) + "\">" +
' ' + curPeers + "&thinsp;/&thinsp;" + curPeers + thinsp(isDegraded) +
// ngettext("1 peer", "{0} peers", knownPeers) + "</a>"; ngettext("1 peer", "{0} peers", knownPeers) + "</a>";
ngettext("1", "{0}", knownPeers) + "</a>";
else if (isRunning && curPeers > 0) else if (isRunning && curPeers > 0)
statusString = "<img border=\"0\" src=\"/themes/snark/" + _manager.getTheme() + "/images/stalled.png\" title=\"" + _("Stalled") + "\">" + statusString = "<img alt=\"\" border=\"0\" src=\"" + _imgPath + "stalled.png\" ></td><td class=\"snarkTorrentStatus " + rowClass + "\">" + _("Stalled") +
' ' + curPeers + "&thinsp;/&thinsp;" + ": " + curPeers + thinsp(isDegraded) +
// ngettext("1 peer", "{0} peers", knownPeers); ngettext("1 peer", "{0} peers", knownPeers);
ngettext("1", "{0}", knownPeers); else if (isRunning && knownPeers > 0)
statusString = "<img alt=\"\" border=\"0\" src=\"" + _imgPath + "nopeers.png\" ></td><td class=\"snarkTorrentStatus " + rowClass + "\">" + _("No Peers") +
": 0&thinsp;/&thinsp;" + knownPeers ;
else if (isRunning) else if (isRunning)
statusString = "<img border=\"0\" src=\"/themes/snark/" + _manager.getTheme() + "/images/nopeers.png\" title=\"" + _("No Peers") + "\">" + statusString = "<img alt=\"\" border=\"0\" src=\"" + _imgPath + "nopeers.png\" ></td><td class=\"snarkTorrentStatus " + rowClass + "\">" + _("No Peers");
' ' + curPeers + "&thinsp;/&thinsp;" +
// ngettext("1 peer", "{0} peers", knownPeers);
ngettext("1", "{0}", knownPeers);
else else
statusString = "<img border=\"0\" src=\"/themes/snark/" + _manager.getTheme() + "/images/stopped.png\" title=\"" + _("Stopped") + "\"> " + _("Stopped"); statusString = "<img alt=\"\" border=\"0\" src=\"" + _imgPath + "stopped.png\" ></td><td class=\"snarkTorrentStatus " + rowClass + "\">" + _("Stopped");
} }
String rowClass = (row % 2 == 0 ? "snarkTorrentEven" : "snarkTorrentOdd");
out.write("<tr class=\"" + rowClass + "\">"); out.write("<tr class=\"" + rowClass + "\">");
out.write("<td align=\"center\" class=\"snarkTorrentStatus " + rowClass + "\">"); out.write("<td class=\"center " + rowClass + "\">");
out.write(statusString + "</td>\n\t"); out.write(statusString + "</td>\n\t");
out.write("<td align=\"left\" class=\"snarkTorrentName " + rowClass + "\">");
if (remaining == 0 || snark.meta.getFiles() != null) { out.write("<td class=\"" + rowClass + "\">");
out.write("<a href=\"" + snark.storage.getBaseName());
if (snark.meta.getFiles() != null)
out.write("/");
out.write("\" title=\"");
if (snark.meta.getFiles() != null)
out.write(_("View files"));
else
out.write(_("Open file"));
out.write("\">");
}
String icon;
if (snark.meta.getFiles() != null)
icon = "folder";
else
icon = toIcon(snark.meta.getName());
out.write(toImg(icon));
out.write(filename);
if (remaining == 0 || snark.meta.getFiles() != null)
out.write("</a>");
// temporarily hardcoded for postman* and anonymity, requires bytemonsoon patch for lookup by info_hash // temporarily hardcoded for postman* and anonymity, requires bytemonsoon patch for lookup by info_hash
String announce = snark.meta.getAnnounce(); String announce = snark.meta.getAnnounce();
if (announce.startsWith("http://YRgrgTLG") || announce.startsWith("http://8EoJZIKr") || if (announce.startsWith("http://YRgrgTLG") || announce.startsWith("http://8EoJZIKr") ||
@ -839,28 +828,62 @@ 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;<a href=\"" + baseURL + "details.php?dllist=1&filelist=1&info_hash="); out.write("<a href=\"" + baseURL + "details.php?dllist=1&amp;filelist=1&amp;info_hash=");
out.write(TrackerClient.urlencode(snark.meta.getInfoHash())); out.write(TrackerClient.urlencode(snark.meta.getInfoHash()));
out.write("\" title=\"" + name + ' ' + _("Tracker") + "\" target=\"_blank\">"); out.write("\" title=\"" + _("Details at {0} tracker", name) + "\" target=\"_blank\">");
out.write("<div class=\"infoz\"><img border=\"0\" src=\"/themes/snark/" + _manager.getTheme() + "/images/details.png\"></div>"); out.write("<img alt=\"" + _("Info") + "\" border=\"0\" src=\"" + _imgPath + "details.png\">");
out.write("</a>"); out.write("</a>");
break; break;
} }
} }
out.write("</td>\n\t");
out.write("<td align=\"center\" class=\"snarkTorrentETA " + rowClass + "\">"); out.write("</td>\n<td class=\"" + rowClass + "\">");
StringBuilder buf = null;
if (remaining == 0 || snark.meta.getFiles() != null) {
buf = new StringBuilder(128);
buf.append("<a href=\"").append(snark.storage.getBaseName());
if (snark.meta.getFiles() != null)
buf.append('/');
buf.append("\" title=\"");
if (snark.meta.getFiles() != null)
buf.append(_("View files"));
else
buf.append(_("Open file"));
buf.append("\">");
out.write(buf.toString());
}
String icon;
if (snark.meta.getFiles() != null)
icon = "folder";
else
icon = toIcon(snark.meta.getName());
if (remaining == 0 || snark.meta.getFiles() != null) {
out.write(toImg(icon, _("Open")));
out.write("</a>");
} else {
out.write(toImg(icon));
}
out.write("</td><td class=\"snarkTorrentName " + rowClass + "\">");
if (remaining == 0 || snark.meta.getFiles() != null)
out.write(buf.toString());
out.write(filename);
if (remaining == 0 || snark.meta.getFiles() != null)
out.write("</a>");
out.write("<td align=\"right\" class=\"snarkTorrentETA " + rowClass + "\">");
if(isRunning && remainingSeconds > 0) if(isRunning && remainingSeconds > 0)
out.write(DataHelper.formatDuration2(remainingSeconds*1000)); // (eta 6h) out.write(DataHelper.formatDuration2(remainingSeconds*1000)); // (eta 6h)
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; remove thin space so line does _not_ break. We don't want a break here. out.write(formatSize(total-remaining) + thinsp(isDegraded) + formatSize(total));
else else
out.write(formatSize(total)); // 3GB out.write(formatSize(total)); // 3GB
out.write("</td>\n\t"); out.write("</td>\n\t");
out.write("<td align=\"right\" class=\"snarkTorrentUploaded " + rowClass out.write("<td align=\"right\" class=\"snarkTorrentUploaded " + rowClass + "\">");
+ "\">" + formatSize(uploaded) + "</td>\n\t"); if(isRunning)
out.write(formatSize(uploaded));
out.write("</td>\n\t");
out.write("<td align=\"right\" class=\"snarkTorrentRateDown\">"); out.write("<td align=\"right\" class=\"snarkTorrentRateDown\">");
if(isRunning && remaining > 0) if(isRunning && remaining > 0)
out.write(formatSize(downBps) + "ps"); out.write(formatSize(downBps) + "ps");
@ -875,27 +898,34 @@ public class I2PSnarkServlet extends Default {
if (showPeers) if (showPeers)
parameters = parameters + "&p=1"; parameters = parameters + "&p=1";
if (isRunning) { if (isRunning) {
out.write("<input type=\"image\" name=\"action\" value=\"Stop_"); if (isDegraded)
out.write(b64); out.write("<a href=\"/i2psnark/?action=Stop_" + b64 + "&amp;nonce=" + _nonce + "\"><img title=\"");
out.write("\" title=\""); else
out.write("<input type=\"image\" name=\"action\" value=\"Stop_" + b64 + "\" title=\"");
out.write(_("Stop the torrent")); out.write(_("Stop the torrent"));
out.write("\" src=\"/themes/snark/" + _manager.getTheme() + "/images/stop.png\" alt=\""); out.write("\" src=\"" + _imgPath + "stop.png\" alt=\"");
out.write(_("Stop")); out.write(_("Stop"));
out.write("\">"); out.write("\">");
if (isDegraded)
out.write("</a>");
} else { } else {
if (isValid) { if (isValid) {
out.write("<input type=\"image\" name=\"action\" value=\"Start_"); if (isDegraded)
out.write(b64); out.write("<a href=\"/i2psnark/?action=Start_" + b64 + "&amp;nonce=" + _nonce + "\"><img title=\"");
out.write("\" title=\""); else
out.write("<input type=\"image\" name=\"action\" value=\"Start_" + b64 + "\" title=\"");
out.write(_("Start the torrent")); out.write(_("Start the torrent"));
out.write("\" src=\"/themes/snark/" + _manager.getTheme() + "/images/start.png\" alt=\""); out.write("\" src=\"" + _imgPath + "start.png\" alt=\"");
out.write(_("Start")); out.write(_("Start"));
out.write("\">"); out.write("\">");
if (isDegraded)
out.write("</a>");
} }
out.write("<input type=\"image\" name=\"action\" value=\"Remove_"); if (isDegraded)
out.write(b64); out.write("<a href=\"/i2psnark/?action=Remove_" + b64 + "&amp;nonce=" + _nonce + "\"><img title=\"");
out.write("\" title=\""); else
out.write("<input type=\"image\" name=\"action\" value=\"Remove_" + b64 + "\" title=\"");
out.write(_("Remove the torrent from the active list, deleting the .torrent file")); out.write(_("Remove the torrent from the active list, deleting the .torrent file"));
out.write("\" onclick=\"if (!confirm('"); out.write("\" onclick=\"if (!confirm('");
// Can't figure out how to escape double quotes inside the onclick string. // Can't figure out how to escape double quotes inside the onclick string.
@ -903,13 +933,16 @@ 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(" src=\"/themes/snark/" + _manager.getTheme() + "/images/remove.png\" alt=\""); out.write(" src=\"" + _imgPath + "remove.png\" alt=\"");
out.write(_("Remove")); out.write(_("Remove"));
out.write("\">"); out.write("\">");
if (isDegraded)
out.write("</a>");
out.write("<input type=\"image\" name=\"action\" value=\"Delete_"); if (isDegraded)
out.write(b64); out.write("<a href=\"/i2psnark/?action=Delete_" + b64 + "&amp;nonce=" + _nonce + "\"><img title=\"");
out.write("\" title=\""); else
out.write("<input type=\"image\" name=\"action\" value=\"Delete_" + b64 + "\" 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)"));
out.write("\" onclick=\"if (!confirm('"); out.write("\" onclick=\"if (!confirm('");
// Can't figure out how to escape double quotes inside the onclick string. // Can't figure out how to escape double quotes inside the onclick string.
@ -917,9 +950,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(" src=\"/themes/snark/" + _manager.getTheme() + "/images/delete.png\" alt=\""); out.write(" src=\"" + _imgPath + "delete.png\" alt=\"");
out.write(_("Delete")); out.write(_("Delete"));
out.write("\">"); out.write("\">");
if (isDegraded)
out.write("</a>");
} }
out.write("</td>\n</tr>\n"); out.write("</td>\n</tr>\n");
@ -930,10 +965,8 @@ public class I2PSnarkServlet extends Default {
for (Peer peer : peers) { for (Peer peer : peers) {
if (!peer.isConnected()) if (!peer.isConnected())
continue; continue;
out.write("<tr class=\"" + rowClass + "\">"); out.write("<tr class=\"" + rowClass + "\"><td></td>");
out.write("<td align=\"center\" class=\"snarkTorrentStatus " + rowClass + "\">"); out.write("<td colspan=\"4\" align=\"right\" class=\"" + rowClass + "\">");
out.write("</td>\n\t");
out.write("<td align=\"right\" class=\"snarkTorrentStatus " + rowClass + "\">");
String ch = peer.toString().substring(0, 4); String ch = peer.toString().substring(0, 4);
String client; String client;
if ("AwMD".equals(ch)) if ("AwMD".equals(ch))
@ -1006,11 +1039,18 @@ public class I2PSnarkServlet extends Default {
out.write("<td class=\"snarkTorrentStatus " + rowClass + "\">"); out.write("<td class=\"snarkTorrentStatus " + rowClass + "\">");
out.write("</td></tr>\n\t"); out.write("</td></tr>\n\t");
if (showDebug) if (showDebug)
out.write("<tr><td colspan=\"8\" align=\"right\" class=\"snarkTorrentStatus " + rowClass + "\">" + peer.getSocket() + "</td></tr>"); out.write("<tr><td></td><td colspan=\"10\" align=\"right\" class=\"" + rowClass + "\">" + peer.getSocket() + "</td></tr>");
} }
} }
} }
/** @since 0.8.2 */
private static String thinsp(boolean disable) {
if (disable)
return " / ";
return ("&thinsp;/&thinsp;");
}
/** /**
* Sort by completeness (seeds first), then by ID * Sort by completeness (seeds first), then by ID
* @since 0.8.1 * @since 0.8.1
@ -1034,9 +1074,9 @@ public class I2PSnarkServlet extends Default {
//String newFile = req.getParameter("newFile"); //String newFile = req.getParameter("newFile");
//if ( (newFile == null) || (newFile.trim().length() <= 0) ) newFile = ""; //if ( (newFile == null) || (newFile.trim().length() <= 0) ) newFile = "";
out.write("<span class=\"snarkNewTorrent\">\n"); out.write("<div class=\"snarkNewTorrent\">\n");
// *not* enctype="multipart/form-data", so that the input type=file sends the filename, not the file // *not* enctype="multipart/form-data", so that the input type=file sends the filename, not the file
out.write("<form action=\"" + uri + "\" method=\"POST\">\n"); out.write("<form action=\"_post\" method=\"POST\">\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=\"Add\" >\n"); out.write("<input type=\"hidden\" name=\"action\" value=\"Add\" >\n");
// don't lose peer setting // don't lose peer setting
@ -1044,7 +1084,7 @@ public class I2PSnarkServlet extends Default {
if (peerParam != null) if (peerParam != null)
out.write("<input type=\"hidden\" name=\"p\" value=\"" + peerParam + "\" >\n"); out.write("<input type=\"hidden\" name=\"p\" value=\"" + peerParam + "\" >\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/" + _manager.getTheme() + "/images/add.png\">"); out.write("<img alt=\"\" border=\"0\" src=\"" + _imgPath + "add.png\"> ");
out.write(_("Add Torrent")); out.write(_("Add Torrent"));
out.write("</span><hr>\n<table border=\"0\"><tr><td>"); out.write("</span><hr>\n<table border=\"0\"><tr><td>");
out.write(_("From URL")); out.write(_("From URL"));
@ -1062,7 +1102,7 @@ public class I2PSnarkServlet extends Default {
out.write("\n"); out.write("\n");
out.write(_("Removing a .torrent will cause it 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("</div></form></div>");
} }
private void writeSeedForm(PrintWriter out, HttpServletRequest req) throws IOException { private void writeSeedForm(PrintWriter out, HttpServletRequest req) throws IOException {
@ -1073,9 +1113,9 @@ public class I2PSnarkServlet extends Default {
else else
baseFile = DataHelper.stripHTML(baseFile); // XSS baseFile = DataHelper.stripHTML(baseFile); // XSS
out.write("<div class=\"newtorrentsection\"><span class=\"snarkNewTorrent\">\n"); out.write("<div class=\"newtorrentsection\"><div class=\"snarkNewTorrent\">\n");
// *not* enctype="multipart/form-data", so that the input type=file sends the filename, not the file // *not* enctype="multipart/form-data", so that the input type=file sends the filename, not the file
out.write("<form action=\"" + uri + "\" method=\"POST\">\n"); out.write("<form action=\"_post\" method=\"POST\">\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=\"Create\" >\n"); out.write("<input type=\"hidden\" name=\"action\" value=\"Create\" >\n");
// don't lose peer setting // don't lose peer setting
@ -1083,7 +1123,7 @@ public class I2PSnarkServlet extends Default {
if (peerParam != null) if (peerParam != null)
out.write("<input type=\"hidden\" name=\"p\" value=\"" + peerParam + "\" >\n"); out.write("<input type=\"hidden\" name=\"p\" value=\"" + peerParam + "\" >\n");
out.write("<span class=\"snarkConfigTitle\">"); out.write("<span class=\"snarkConfigTitle\">");
out.write("<img border=\"0\" src=\"/themes/snark/" + _manager.getTheme() + "/images/create.png\">"); out.write("<img alt=\"\" border=\"0\" src=\"" + _imgPath + "create.png\"> ");
out.write(_("Create Torrent")); out.write(_("Create Torrent"));
out.write("</span><hr>\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");
@ -1116,7 +1156,7 @@ public class I2PSnarkServlet extends Default {
out.write("<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></div></div>");
} }
private void writeConfigForm(PrintWriter out, HttpServletRequest req) throws IOException { private void writeConfigForm(PrintWriter out, HttpServletRequest req) throws IOException {
@ -1127,31 +1167,18 @@ public class I2PSnarkServlet extends Default {
String openTrackers = _manager.util().getOpenTrackerString(); String openTrackers = _manager.util().getOpenTrackerString();
//int seedPct = 0; //int seedPct = 0;
out.write("<form action=\"" + uri + "\" method=\"POST\">\n"); out.write("<form action=\"/i2psnark/configure\" method=\"POST\">\n");
out.write("<div class=\"configsectionpanel\"><span class=\"snarkConfig\">\n"); out.write("<div class=\"configsectionpanel\"><div 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/" + _manager.getTheme() + "/images/config.png\">"); out.write("<img alt=\"\" border=\"0\" src=\"" + _imgPath + "config.png\"> ");
out.write(_("Configuration")); out.write(_("Configuration"));
out.write("</span><hr>\n"); out.write("</span><hr>\n");
out.write("<table border=\"0\"><tr><td>"); out.write("<table border=\"0\"><tr><td>");
out.write(_("Theme"));
out.write(": <td><select name='theme'>");
String theme = _manager.getTheme();
String[] themes = _manager.getThemes();
for(int i = 0; i < themes.length; i++) {
if(themes[i].equals(theme))
out.write("\n<OPTION value='" + themes[i] + "' SELECTED>" + themes[i]);
else
out.write("\n<OPTION value='" + themes[i] + "'>" + themes[i]);
}
out.write("\n</select>\n<tr><td>");
out.write(_("Data directory")); out.write(_("Data directory"));
out.write(": <td><code>" + dataDir + "</code> ("); out.write(": <td><code>" + dataDir + "</code> <i>(");
out.write(_("Edit i2psnark.config and restart to change")); out.write(_("Edit i2psnark.config and restart to change"));
out.write(")</i><br>\n"); out.write(")</i><br>\n");
@ -1163,6 +1190,19 @@ public class I2PSnarkServlet extends Default {
out.write(_("If checked, automatically start torrents that are added")); out.write(_("If checked, automatically start torrents that are added"));
out.write("\" >"); out.write("\" >");
out.write("<tr><td>");
out.write(_("Theme"));
out.write(": <td><select name='theme'>");
String theme = _manager.getTheme();
String[] themes = _manager.getThemes();
for(int i = 0; i < themes.length; i++) {
if(themes[i].equals(theme))
out.write("\n<OPTION value=\"" + themes[i] + "\" SELECTED>" + themes[i]);
else
out.write("\n<OPTION value=\"" + themes[i] + "\">" + themes[i]);
}
out.write("</select>\n");
out.write("<tr><td>"); out.write("<tr><td>");
out.write(_("Startup delay")); out.write(_("Startup delay"));
out.write(": <td><input name=\"startupDelay\" size=\"3\" class=\"r\" value=\"" + _manager.util().getStartupDelay() + "\"> "); out.write(": <td><input name=\"startupDelay\" size=\"3\" class=\"r\" value=\"" + _manager.util().getStartupDelay() + "\"> ");
@ -1263,14 +1303,13 @@ public class I2PSnarkServlet extends Default {
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");
out.write("</table></span>\n"); out.write("</table></div></div></form>");
out.write("</form></div>");
} }
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/" + _manager.getTheme() + "/images/config.png\">"); out.write("<img alt=\"\" border=\"0\" src=\"" + _imgPath + "config.png\"> ");
out.write(_("Configuration")); out.write(_("Configuration"));
out.write("</a></span></span></div>\n"); out.write("</a></span></span></div>\n");
} }
@ -1346,15 +1385,16 @@ public class I2PSnarkServlet extends Default {
return buf.toString(); return buf.toString();
} }
private static final String HEADER_A = "<link href=\"/themes/snark/"; private static final String DOCTYPE = "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\">\n";
private static final String HEADER_B = "/snark.css\" rel=\"stylesheet\" type=\"text/css\" >"; private static final String HEADER_A = "<link href=\"";
private static final String HEADER_B = "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%\" >\n" +
"<thead>\n" + "<thead>\n" +
"<tr><th align=\"center\">"; "<tr><th colspan=\"2\">";
private static final String FOOTER = "</div></div></div></center></body></html>"; private static final String FOOTER = "</div></center></body></html>";
/** /**
* Modded heavily from the Jetty version in Resource.java, * Modded heavily from the Jetty version in Resource.java,
@ -1398,7 +1438,7 @@ public class I2PSnarkServlet extends Default {
Arrays.sort(ls, Collator.getInstance()); Arrays.sort(ls, Collator.getInstance());
StringBuilder buf=new StringBuilder(4096); StringBuilder buf=new StringBuilder(4096);
buf.append("<HTML><HEAD><TITLE>"); buf.append(DOCTYPE + "<HTML><HEAD><TITLE>");
String title = URI.decodePath(base); String title = URI.decodePath(base);
if (title.startsWith("/i2psnark/")) if (title.startsWith("/i2psnark/"))
title = title.substring("/i2psnark/".length()); title = title.substring("/i2psnark/".length());
@ -1419,36 +1459,32 @@ public class I2PSnarkServlet extends Default {
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_A).append(_manager.getTheme()).append(HEADER_B).append("<link rel=\"shortcut icon\" href=\"/themes/snark/" + _manager.getTheme() + "/favicon.ico\"></HEAD><BODY>\n<center><div class=\"snarknavbar\"> <a href=\"/i2psnark/\" title=\"Torrents\""); buf.append("</TITLE>").append(HEADER_A).append(_themePath).append(HEADER_B).append("<link rel=\"shortcut icon\" href=\"" + _themePath + "favicon.ico\">" +
buf.append(" class=\"snarkRefresh\"><img border=\"0\" src=\"/themes/snark/" + _manager.getTheme() + "/images/arrow_refresh.png\"> I2PSnark</a>").append("</div>"); "</HEAD><BODY>\n<center><div class=\"snarknavbar\"><a href=\"/i2psnark/\" title=\"Torrents\"");
buf.append(" class=\"snarkRefresh\"><img alt=\"\" border=\"0\" src=\"" + _imgPath + "arrow_refresh.png\">&nbsp;&nbsp;I2PSnark</a></div></center>\n");
if (parent) if (parent) // always true
buf.append("</div><div class=\"page\"><div class=\"mainsection\">"); buf.append("<div class=\"page\"><div class=\"mainsection\">");
boolean showPriority = snark != null && !snark.storage.complete(); boolean showPriority = snark != null && !snark.storage.complete();
if (showPriority) if (showPriority)
buf.append("<form action=\"").append(base).append("\" method=\"POST\">\n"); buf.append("<form action=\"").append(base).append("\" method=\"POST\">\n");
buf.append("<TABLE BORDER=0 class=\"snarkTorrents\" cellpadding=\"5px 10px\">" + buf.append("<TABLE BORDER=0 class=\"snarkTorrents\" >" +
"<thead><tr><th>") "<thead><tr><th>")
.append("<img border=\"0\" src=\"/themes/snark/" + _manager.getTheme() + "/images/file.png\" title=\"") .append("<img alt=\"\" border=\"0\" src=\"" + _imgPath + "file.png\" >&nbsp;")
.append(_("File")).append("\" alt=\"").append(_("File")).append("\">&nbsp;")
.append(title).append("</th><th align=\"right\">") .append(title).append("</th><th align=\"right\">")
.append("<img border=\"0\" src=\"/themes/snark/" + _manager.getTheme() + "/images/size.png\" title=\"") .append("<img alt=\"\" border=\"0\" src=\"" + _imgPath + "size.png\" >&nbsp;")
// .append(_("FileSize")).append("\" alt=\"").append(_("FileSize")).append("\">").append(_("Size")); .append(_("Size"));
.append(_("FileSize")).append("\" alt=\"").append(_("FileSize")).append("\">"); buf.append("</th><th class=\"headerstatus\">")
buf.append("</th><th class=\"headerstatus\">") .append("<img alt=\"\" border=\"0\" src=\"" + _imgPath + "status.png\" >&nbsp;")
.append("<img border=\"0\" src=\"/themes/snark/" + _manager.getTheme() + "/images/status.png\" title=\"") .append(_("Status")).append("</th>");
// .append(_("Download Status")).append("\">").append(_("Status")).append("</th>");
.append(_("Download Status")).append("\">").append("</th>");
if (showPriority) if (showPriority)
buf.append("<th class=\"headerpriority\">") buf.append("<th class=\"headerpriority\">")
.append("<img border=\"0\" src=\"/themes/snark/" + _manager.getTheme() + "/images/priority.png\" title=\"") .append("<img alt=\"\" border=\"0\" src=\"" + _imgPath + "priority.png\" >&nbsp;")
.append(_("Priority")).append("\">").append("</th>"); .append(_("Priority")).append("</th>");
// .append(_("Priority")).append("</th>"); buf.append("</tr></thead>\n");
// .append("</th>"); buf.append("<tr><td colspan=\"" + (showPriority ? '4' : '3') + "\" class=\"ParentDir\"><A HREF=\"");
buf.append("</tr></thead>\n"); buf.append(URI.addPaths(base,"../"));
buf.append("<tr><td colspan=\"4\" class=\"ParentDir\"><A HREF=\""); buf.append("\"><img alt=\"\" border=\"0\" src=\"" + _imgPath + "up.png\"> ")
buf.append(URI.addPaths(base,"../"));
buf.append("\"><img border=\"0\" src=\"/themes/snark/" + _manager.getTheme() + "/images/up.png\"> ")
.append(_("Up to higher level directory")).append("</A></td></tr>\n"); .append(_("Up to higher level directory")).append("</A></td></tr>\n");
@ -1474,12 +1510,12 @@ public class I2PSnarkServlet extends Default {
long length = item.length(); long length = item.length();
if (item.isDirectory()) { if (item.isDirectory()) {
complete = true; complete = true;
status = toImg("tick") + _("Directory"); status = toImg("tick") + ' ' + _("Directory");
} else { } else {
if (snark == null) { if (snark == null) {
// Assume complete, perhaps he removed a completed torrent but kept a bookmark // Assume complete, perhaps he removed a completed torrent but kept a bookmark
complete = true; complete = true;
status = toImg("cancel") + _("Torrent not found?"); status = toImg("cancel") + ' ' + _("Torrent not found?");
} else { } else {
try { try {
File f = item.getFile(); File f = item.getFile();
@ -1487,10 +1523,10 @@ public class I2PSnarkServlet extends Default {
long remaining = snark.storage.remaining(f.getCanonicalPath()); long remaining = snark.storage.remaining(f.getCanonicalPath());
if (remaining < 0) { if (remaining < 0) {
complete = true; complete = true;
status = toImg("cancel") + _("File not found in torrent?"); status = toImg("cancel") + ' ' + _("File not found in torrent?");
} else if (remaining == 0 || length <= 0) { } else if (remaining == 0 || length <= 0) {
complete = true; complete = true;
status = toImg("tick") + _("Complete"); status = toImg("tick") + ' ' + _("Complete");
} else { } else {
int priority = snark.storage.getPriority(f.getCanonicalPath()); int priority = snark.storage.getPriority(f.getCanonicalPath());
if (priority < 0) if (priority < 0)
@ -1499,7 +1535,7 @@ public class I2PSnarkServlet extends Default {
status = toImg("clock"); status = toImg("clock");
else else
status = toImg("clock_red"); status = toImg("clock_red");
status += status += " " +
(100 * (length - remaining) / length) + "% " + _("complete") + (100 * (length - remaining) / length) + "% " + _("complete") +
" (" + DataHelper.formatSize2(remaining) + _("bytes remaining") + ")"; " (" + DataHelper.formatSize2(remaining) + _("bytes remaining") + ")";
} }
@ -1526,13 +1562,13 @@ public class I2PSnarkServlet extends Default {
buf.append("<img alt=\"\" border=\"0\" class=\"thumb\" src=\"") buf.append("<img alt=\"\" border=\"0\" class=\"thumb\" src=\"")
.append(path).append("\"></a> "); .append(path).append("\"></a> ");
} else { } else {
buf.append(toImg(icon)); buf.append(toImg(icon, _("Open"))).append("</a> ");
} }
buf.append("<A HREF=\""); buf.append("<A HREF=\"");
buf.append(path); buf.append(path);
buf.append("\">"); buf.append("\">");
} else { } else {
buf.append(toImg(icon)); buf.append(toImg(icon)).append(' ');
} }
buf.append(ls[i]); buf.append(ls[i]);
if (complete) if (complete)
@ -1640,7 +1676,12 @@ public class I2PSnarkServlet extends Default {
/** @since 0.7.14 */ /** @since 0.7.14 */
private static String toImg(String icon) { private static String toImg(String icon) {
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.2 */
private static String toImg(String icon, String altText) {
return "<img alt=\"" + altText + "\" height=\"16\" width=\"16\" src=\"/i2psnark/_icons/" + icon + ".png\">";
} }
/** @since 0.8.1 */ /** @since 0.8.1 */
@ -1702,8 +1743,13 @@ private static class FetchAndAdd implements Runnable {
else else
_manager.addMessage(_("Torrent already in the queue: {0}", name)); _manager.addMessage(_("Torrent already in the queue: {0}", name));
} else { } else {
FileUtil.copy(file.getAbsolutePath(), canonical, true); boolean success = FileUtil.copy(file.getAbsolutePath(), canonical, false);
_manager.addTorrent(canonical); if (success) {
SecureFileOutputStream.setPerms(torrentFile);
_manager.addTorrent(canonical);
} else {
_manager.addMessage(_("Failed to copy torrent file to {0}", canonical));
}
} }
} catch (IOException ioe) { } catch (IOException ioe) {
_manager.addMessage(_("Torrent at {0} was not valid", urlify(_url)) + ": " + ioe.getMessage()); _manager.addMessage(_("Torrent at {0} was not valid", urlify(_url)) + ": " + ioe.getMessage());

View File

@ -1,3 +1,25 @@
2010-12-11 zzz
* Build: Fix 'ant distclean poupdate' again
* i2psnark:
- Restore text (ticket #273)
- Fix several HTML errors (ticket #273)
- Fix HTML error causing info links to be unclickable in dillo (tiicket #273)
- Fix alt text duplicated or looking bad in text browsers (ticket #273)
- Fix Opera button errors (ticket #332)
- Fix POST resubmission errors (ticket #334)
- Catch FetchAndAdd copy error (ticket #352)
- Set permissions on downloaded torrent files
- Hide some columns when not running
- Lots of spacing cleanups
- Rename images so users don't end up with unused files
- Remove ~15 unused images
- Clean up theme selection speed-coding exercise
- Indent fixes
* Log: Don't double-timestamp CRITS in wrapper.log
* News: XML fixes (ticket #350)
* Plugins: Better handling of signing keys (Ticket #351)
* TunnelPoolManager: Fix rare startup NPE (http://forum.i2p/viewtopic.php?t=5192)
2010-12-10 Mathiasdm 2010-12-10 Mathiasdm
* I2PTunnel: Fixed up security fix. * I2PTunnel: Fixed up security fix.
2010-12-07 Mathiasdm 2010-12-07 Mathiasdm

Binary file not shown.

Before

Width:  |  Height:  |  Size: 805 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 561 B

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 867 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1022 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 854 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 121 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 543 B

After

Width:  |  Height:  |  Size: 2.7 KiB

View File

@ -155,7 +155,6 @@ th {
border-bottom: 1px inset #101; border-bottom: 1px inset #101;
color: #ddd; color: #ddd;
whitespace: nowrap; whitespace: nowrap;
font-variant: small-caps !important;
letter-spacing: 0.05em; letter-spacing: 0.05em;
} }
@ -238,6 +237,10 @@ td:first-child {
font-size: 9.5pt; font-size: 9.5pt;
} }
.center {
text-align: center !important;
}
.snarkTorrentName { .snarkTorrentName {
text-shadow:1px 1px #550000; text-shadow:1px 1px #550000;
padding: 2px 0 0; padding: 2px 0 0;
@ -268,7 +271,6 @@ td:first-child {
} }
.snarkTorrentEven { .snarkTorrentEven {
background: #545;
font-size: 8pt; font-size: 8pt;
background: #202; background: #202;
} }
@ -323,7 +325,6 @@ td:first-child {
} }
.snarkTorrentOdd { .snarkTorrentOdd {
background: #656;
background: #351933; background: #351933;
font-size: 8pt; font-size: 8pt;
border: 0px inset #101 !important; border: 0px inset #101 !important;

Binary file not shown.

Before

Width:  |  Height:  |  Size: 561 B

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 877 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1014 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 833 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 343 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 182 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 175 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 543 B

After

Width:  |  Height:  |  Size: 2.8 KiB

View File

@ -139,7 +139,6 @@ tr {
} }
thead, tfoot { thead, tfoot {
text-shadow: 0px 1px 1px #707;
background: url("images/bling2.png") repeat-x scroll center center #867; background: url("images/bling2.png") repeat-x scroll center center #867;
font-weight: bold; font-weight: bold;
color: #503; color: #503;
@ -161,7 +160,6 @@ th {
border-top: 1px outset #604; border-top: 1px outset #604;
border-bottom: 1px inset #604; border-bottom: 1px inset #604;
whitespace: nowrap; whitespace: nowrap;
font-variant: small-caps !important;
letter-spacing: 0.05em; letter-spacing: 0.05em;
} }
@ -244,6 +242,10 @@ td:first-child {
font-size: 9.5pt; font-size: 9.5pt;
} }
.center {
text-align: center !important;
}
.snarkTorrentName { .snarkTorrentName {
/* text-shadow:1px 1px #540;*/ /* text-shadow:1px 1px #540;*/
padding: 3px 0 0; padding: 3px 0 0;
@ -270,7 +272,6 @@ td:first-child {
} }
.snarkTorrentEven { .snarkTorrentEven {
background: #fef;
font-size: 8pt; font-size: 8pt;
background: #feb; background: #feb;
} }
@ -328,7 +329,6 @@ td:first-child {
} }
.snarkTorrentOdd { .snarkTorrentOdd {
background: #656;
background: #fed; background: #fed;
font-size: 8pt; font-size: 8pt;
border: 0px inset #fff !important; border: 0px inset #fff !important;
@ -490,7 +490,6 @@ input {
input.r { input.r {
text-align: right; text-align: right;
background: /*url('/themes/snark/ubergine/images/graytile.png')*/;
} }
input[type=submit] { input[type=submit] {
@ -524,7 +523,7 @@ input[type=image] {
border-radius: 0px; border-radius: 0px;
border: medium none; border: medium none;
margin: 0 2px; margin: 0 2px;
opacity: 0.9 !important; opacity: 0.8 !important;
} }
input[type=image]:hover { input[type=image]:hover {
@ -561,7 +560,7 @@ select:hover, textarea:hover {
} }
textarea { textarea {
background: #fff; /*/*url('/themes/snark/ubergine/images/graytile.png')*/;*/ background: #fff; /*url('/themes/snark/ubergine/images/graytile.png');*/
color: #f60; color: #f60;
font-weight: bold; font-weight: bold;
padding: 1px 4px 0px; padding: 1px 4px 0px;

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 = 35; public final static long BUILD = 36;
/** for example "-test" */ /** for example "-test" */
public final static String EXTRA = "-rc"; public final static String EXTRA = "-rc";