diff --git a/apps/i2psnark/java/src/org/klomp/snark/Storage.java b/apps/i2psnark/java/src/org/klomp/snark/Storage.java index 63787fe053..3e341cc09d 100644 --- a/apps/i2psnark/java/src/org/klomp/snark/Storage.java +++ b/apps/i2psnark/java/src/org/klomp/snark/Storage.java @@ -286,6 +286,40 @@ public class Storage return needed == 0; } + /** + * @param file absolute path (non-directory) + * @return number of bytes remaining; -1 if unknown file + * @since 0.7.14 + */ + public long remaining(String file) { + long bytes = 0; + for (int i = 0; i < rafs.length; i++) { + File f = RAFfile[i]; + if (f != null && f.getAbsolutePath().equals(file)) { + if (complete()) + return 0; + int psz = metainfo.getPieceLength(0); + long start = bytes; + long end = start + lengths[i]; + int pc = (int) (bytes / psz); + long rv = 0; + if (!bitfield.get(pc)) + rv = psz - (bytes % psz); + for (int j = pc + 1; j * psz < end; j++) { + if (!bitfield.get(j)) { + if ((j+1)*psz < end) + rv += psz; + else + rv += end - (j * psz); + } + } + return rv; + } + bytes += lengths[i]; + } + return -1; + } + /** * The BitField that tells which pieces this storage contains. * Do not change this since this is the current state of the storage. diff --git a/apps/i2psnark/java/src/org/klomp/snark/web/I2PSnarkServlet.java b/apps/i2psnark/java/src/org/klomp/snark/web/I2PSnarkServlet.java index dd0db4337b..85c0e917c9 100644 --- a/apps/i2psnark/java/src/org/klomp/snark/web/I2PSnarkServlet.java +++ b/apps/i2psnark/java/src/org/klomp/snark/web/I2PSnarkServlet.java @@ -686,7 +686,7 @@ public class I2PSnarkServlet extends Default { out.write(statusString + "\n\t"); out.write(""); - if (remaining == 0) { + if (remaining == 0 || snark.meta.getFiles() != null) { out.write(""); } out.write(filename); - if (remaining == 0) + if (remaining == 0 || snark.meta.getFiles() != null) out.write(""); // temporarily hardcoded for postman* and anonymity, requires bytemonsoon patch for lookup by info_hash String announce = snark.meta.getAnnounce(); @@ -1205,9 +1205,23 @@ public class I2PSnarkServlet extends Default { String title = URI.decodePath(base); if (title.startsWith("/i2psnark/")) title = title.substring("/i2psnark/".length()); + + // Get the snark associated with this directory + Snark snark = null; + try { + String torrentName; + int slash = title.indexOf('/'); + if (slash > 0) + torrentName = title.substring(0, slash) + ".torrent"; + else + torrentName = title + ".torrent"; + File dataDir = _manager.getDataDir(); + String torrentAbsPath = (new File(dataDir, torrentName)).getCanonicalPath(); + snark = _manager.getTorrent(torrentAbsPath); + } catch (IOException ioe) {} if (title.endsWith("/")) title = title.substring(0, title.length() - 1); - title = _("Completed Torrent") + ": " + title; + title = _("Torrent") + ": " + title; buf.append(title); buf.append("").append(HEADER).append("\n
"); buf.append(title); @@ -1241,25 +1255,66 @@ public class I2PSnarkServlet extends Default { buf.append(""); + // Get completeness and status string + boolean complete = false; + String status = ""; + long length = item.length(); + if (item.isDirectory()) { + complete = true; + status = _("Directory"); + } else { + if (snark == null) { + status = "Snark not found?"; + } else { + try { + File f = item.getFile(); + if (f != null) { + long remaining = snark.storage.remaining(f.getCanonicalPath()); + if (remaining == 0) { + complete = true; + status = _("Complete"); + } else if (remaining < 0) { + complete = true; + status = _("File not found in torrent?"); + } else if (length <= 0) { + complete = true; + status = _("Complete"); + } else { + status = (100 - (100 * remaining / length)) + "% " + _("complete") + + " (" + DataHelper.formatSize(remaining) + " bytes remaining)"; + } + } else { + status = "Not a file?"; + } + } catch (IOException ioe) { + status = "Not a file? " + ioe; + } + } + } + String path=URI.addPaths(base,encoded); if (item.isDirectory() && !path.endsWith("/")) path=URI.addPaths(path,"/"); - // thumbnail ? - String plc = path.toLowerCase(); - if (plc.endsWith(".jpg") || plc.endsWith(".png") || plc.endsWith(".gif")) - buf.append("\"\" "); - buf.append(""); + if (complete) { + // thumbnail ? + String plc = path.toLowerCase(); + if (plc.endsWith(".jpg") || plc.endsWith(".png") || plc.endsWith(".gif")) { + buf.append("\"\" "); + } + buf.append(""); + } buf.append(ls[i]); + if (complete) + buf.append(""); buf.append(""); if (!item.isDirectory()) - buf.append(DataHelper.formatSize(item.length())).append(' ').append(_("Bytes")); + buf.append(DataHelper.formatSize(length)).append(' ').append(_("Bytes")); buf.append(""); //buf.append(dfmt.format(new Date(item.lastModified()))); - // TODO add real status - if (!item.isDirectory()) - buf.append(_("Complete")); + buf.append(status); buf.append("\n"); } buf.append("\n"); diff --git a/installer/resources/themes/console/snark.css b/installer/resources/themes/console/snark.css index eb10595d8c..70091b13f9 100644 --- a/installer/resources/themes/console/snark.css +++ b/installer/resources/themes/console/snark.css @@ -108,6 +108,15 @@ td { font-size: 8pt; } +.snarkFileName { + min-width: 25em; +} + +.thumb { + max-height: 64px; + max-width: 96px; +} + .snarkNewTorrent { font-size: 9pt; }