forked from I2P_Developers/i2p.i2p
i2psnark: Add support for specifying data dir in add form (ticket #1028)
This commit is contained in:
@@ -1119,21 +1119,23 @@ public class SnarkManager implements CompleteListener {
|
|||||||
* Caller must verify this torrent is not already added.
|
* Caller must verify this torrent is not already added.
|
||||||
*
|
*
|
||||||
* @param filename the absolute path to save the metainfo to, generally ending in ".torrent"
|
* @param filename the absolute path to save the metainfo to, generally ending in ".torrent"
|
||||||
* @param baseFile may be null, if so look in rootDataDir
|
* @param baseFile may be null, if so look in dataDir
|
||||||
* @throws RuntimeException via Snark.fatal()
|
* @throws RuntimeException via Snark.fatal()
|
||||||
*/
|
*/
|
||||||
private void addTorrent(String filename) {
|
private void addTorrent(String filename, File baseFile, boolean dontAutoStart) {
|
||||||
addTorrent(filename, null, false);
|
addTorrent(filename, baseFile, dontAutoStart, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Caller must verify this torrent is not already added.
|
* Caller must verify this torrent is not already added.
|
||||||
*
|
*
|
||||||
* @param filename the absolute path to save the metainfo to, generally ending in ".torrent"
|
* @param filename the absolute path to save the metainfo to, generally ending in ".torrent"
|
||||||
* @param baseFile may be null, if so look in rootDataDir
|
* @param baseFile may be null, if so look in dataDir
|
||||||
|
* @param dataDir must exist, or null to default to snark data directory
|
||||||
* @throws RuntimeException via Snark.fatal()
|
* @throws RuntimeException via Snark.fatal()
|
||||||
|
* @since 0.9.17
|
||||||
*/
|
*/
|
||||||
private void addTorrent(String filename, File baseFile, boolean dontAutoStart) {
|
private void addTorrent(String filename, File baseFile, boolean dontAutoStart, File dataDir) {
|
||||||
if ((!dontAutoStart) && !_util.connected()) {
|
if ((!dontAutoStart) && !_util.connected()) {
|
||||||
addMessage(_("Connecting to I2P"));
|
addMessage(_("Connecting to I2P"));
|
||||||
boolean ok = _util.connect();
|
boolean ok = _util.connect();
|
||||||
@@ -1150,7 +1152,8 @@ public class SnarkManager implements CompleteListener {
|
|||||||
addMessage(_("Error: Could not add the torrent {0}", filename) + ": " + ioe);
|
addMessage(_("Error: Could not add the torrent {0}", filename) + ": " + ioe);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
File dataDir = getDataDir();
|
if (dataDir == null)
|
||||||
|
dataDir = getDataDir();
|
||||||
Snark torrent = null;
|
Snark torrent = null;
|
||||||
synchronized (_snarks) {
|
synchronized (_snarks) {
|
||||||
torrent = _snarks.get(filename);
|
torrent = _snarks.get(filename);
|
||||||
@@ -1266,7 +1269,25 @@ public class SnarkManager implements CompleteListener {
|
|||||||
*/
|
*/
|
||||||
public void addMagnet(String name, byte[] ih, String trackerURL, boolean updateStatus) {
|
public void addMagnet(String name, byte[] ih, String trackerURL, boolean updateStatus) {
|
||||||
// updateStatus is true from UI, false from config file bulk add
|
// updateStatus is true from UI, false from config file bulk add
|
||||||
addMagnet(name, ih, trackerURL, updateStatus, updateStatus, this);
|
addMagnet(name, ih, trackerURL, updateStatus, updateStatus, null, this);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add a torrent with the info hash alone (magnet / maggot)
|
||||||
|
*
|
||||||
|
* @param name hex or b32 name from the magnet link
|
||||||
|
* @param ih 20 byte info hash
|
||||||
|
* @param trackerURL may be null
|
||||||
|
* @param updateStatus should we add this magnet to the config file,
|
||||||
|
* to save it across restarts, in case we don't get
|
||||||
|
* the metadata before shutdown?
|
||||||
|
* @param dataDir must exist, or null to default to snark data directory
|
||||||
|
* @throws RuntimeException via Snark.fatal()
|
||||||
|
* @since 0.9.17
|
||||||
|
*/
|
||||||
|
public void addMagnet(String name, byte[] ih, String trackerURL, boolean updateStatus, File dataDir) {
|
||||||
|
// updateStatus is true from UI, false from config file bulk add
|
||||||
|
addMagnet(name, ih, trackerURL, updateStatus, updateStatus, dataDir, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -1279,16 +1300,18 @@ public class SnarkManager implements CompleteListener {
|
|||||||
* @param updateStatus should we add this magnet to the config file,
|
* @param updateStatus should we add this magnet to the config file,
|
||||||
* to save it across restarts, in case we don't get
|
* to save it across restarts, in case we don't get
|
||||||
* the metadata before shutdown?
|
* the metadata before shutdown?
|
||||||
|
* @param dataDir must exist, or null to default to snark data directory
|
||||||
* @param listener to intercept callbacks, should pass through to this
|
* @param listener to intercept callbacks, should pass through to this
|
||||||
* @return the new Snark or null on failure
|
* @return the new Snark or null on failure
|
||||||
* @throws RuntimeException via Snark.fatal()
|
* @throws RuntimeException via Snark.fatal()
|
||||||
* @since 0.9.4
|
* @since 0.9.4
|
||||||
*/
|
*/
|
||||||
public Snark addMagnet(String name, byte[] ih, String trackerURL, boolean updateStatus,
|
public Snark addMagnet(String name, byte[] ih, String trackerURL, boolean updateStatus,
|
||||||
boolean autoStart, CompleteListener listener) {
|
boolean autoStart, File dataDir, CompleteListener listener) {
|
||||||
|
String dirPath = dataDir != null ? dataDir.getAbsolutePath() : getDataDir().getPath();
|
||||||
Snark torrent = new Snark(_util, name, ih, trackerURL, listener,
|
Snark torrent = new Snark(_util, name, ih, trackerURL, listener,
|
||||||
_peerCoordinatorSet, _connectionAcceptor,
|
_peerCoordinatorSet, _connectionAcceptor,
|
||||||
false, getDataDir().getPath());
|
false, dirPath);
|
||||||
|
|
||||||
synchronized (_snarks) {
|
synchronized (_snarks) {
|
||||||
Snark snark = getTorrentByInfoHash(ih);
|
Snark snark = getTorrentByInfoHash(ih);
|
||||||
@@ -1407,10 +1430,11 @@ public class SnarkManager implements CompleteListener {
|
|||||||
* @param fromfile where the file is now, presumably in a temp directory somewhere
|
* @param fromfile where the file is now, presumably in a temp directory somewhere
|
||||||
* @param filename the absolute path to save the metainfo to, generally ending in ".torrent", which is also the name of the torrent
|
* @param filename the absolute path to save the metainfo to, generally ending in ".torrent", which is also the name of the torrent
|
||||||
* Must be a filesystem-safe name.
|
* Must be a filesystem-safe name.
|
||||||
|
* @param dataDir must exist, or null to default to snark data directory
|
||||||
* @throws RuntimeException via Snark.fatal()
|
* @throws RuntimeException via Snark.fatal()
|
||||||
* @since 0.8.4
|
* @since 0.8.4
|
||||||
*/
|
*/
|
||||||
public void copyAndAddTorrent(File fromfile, String filename) throws IOException {
|
public void copyAndAddTorrent(File fromfile, String filename, File dataDir) throws IOException {
|
||||||
// prevent interference by DirMonitor
|
// prevent interference by DirMonitor
|
||||||
synchronized (_snarks) {
|
synchronized (_snarks) {
|
||||||
boolean success = FileUtil.copy(fromfile.getAbsolutePath(), filename, false);
|
boolean success = FileUtil.copy(fromfile.getAbsolutePath(), filename, false);
|
||||||
@@ -1422,7 +1446,7 @@ public class SnarkManager implements CompleteListener {
|
|||||||
if (!areFilesPublic())
|
if (!areFilesPublic())
|
||||||
SecureFileOutputStream.setPerms(new File(filename));
|
SecureFileOutputStream.setPerms(new File(filename));
|
||||||
// hold the lock for a long time
|
// hold the lock for a long time
|
||||||
addTorrent(filename);
|
addTorrent(filename, null, false, dataDir);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -110,7 +110,7 @@ class UpdateRunner implements UpdateTask, CompleteListener {
|
|||||||
_umgr.notifyAttemptFailed(this, "No tracker, no DHT, no OT", null);
|
_umgr.notifyAttemptFailed(this, "No tracker, no DHT, no OT", null);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
_snark = _smgr.addMagnet(name, ih, trackerURL, true, true, this);
|
_snark = _smgr.addMagnet(name, ih, trackerURL, true, true, null, this);
|
||||||
if (_snark != null) {
|
if (_snark != null) {
|
||||||
updateStatus("<b>" + _smgr.util().getString("Updating from {0}", linkify(updateURL)) + "</b>");
|
updateStatus("<b>" + _smgr.util().getString("Updating from {0}", linkify(updateURL)) + "</b>");
|
||||||
new Timeout();
|
new Timeout();
|
||||||
|
@@ -50,6 +50,7 @@ public class FetchAndAdd extends Snark implements EepGet.StatusListener, Runnabl
|
|||||||
private final String _url;
|
private final String _url;
|
||||||
private final byte[] _fakeHash;
|
private final byte[] _fakeHash;
|
||||||
private final String _name;
|
private final String _name;
|
||||||
|
private final File _dataDir;
|
||||||
private volatile long _remaining = -1;
|
private volatile long _remaining = -1;
|
||||||
private volatile long _total = -1;
|
private volatile long _total = -1;
|
||||||
private volatile long _transferred;
|
private volatile long _transferred;
|
||||||
@@ -65,8 +66,10 @@ public class FetchAndAdd extends Snark implements EepGet.StatusListener, Runnabl
|
|||||||
/**
|
/**
|
||||||
* Caller should call _mgr.addDownloader(this), which
|
* Caller should call _mgr.addDownloader(this), which
|
||||||
* will start things off.
|
* will start things off.
|
||||||
|
*
|
||||||
|
* @param dataDir null to default to snark data directory
|
||||||
*/
|
*/
|
||||||
public FetchAndAdd(I2PAppContext ctx, SnarkManager mgr, String url) {
|
public FetchAndAdd(I2PAppContext ctx, SnarkManager mgr, String url, File dataDir) {
|
||||||
// magnet constructor
|
// magnet constructor
|
||||||
super(mgr.util(), "Torrent download",
|
super(mgr.util(), "Torrent download",
|
||||||
null, null, null, null, null, false, null);
|
null, null, null, null, null, false, null);
|
||||||
@@ -75,6 +78,7 @@ public class FetchAndAdd extends Snark implements EepGet.StatusListener, Runnabl
|
|||||||
_mgr = mgr;
|
_mgr = mgr;
|
||||||
_url = url;
|
_url = url;
|
||||||
_name = _("Download torrent file from {0}", url);
|
_name = _("Download torrent file from {0}", url);
|
||||||
|
_dataDir = dataDir;
|
||||||
byte[] fake = null;
|
byte[] fake = null;
|
||||||
try {
|
try {
|
||||||
fake = SHA1.getInstance().digest(url.getBytes("ISO-8859-1"));
|
fake = SHA1.getInstance().digest(url.getBytes("ISO-8859-1"));
|
||||||
@@ -176,7 +180,7 @@ public class FetchAndAdd extends Snark implements EepGet.StatusListener, Runnabl
|
|||||||
_mgr.addMessage(_("Torrent already in the queue: {0}", name));
|
_mgr.addMessage(_("Torrent already in the queue: {0}", name));
|
||||||
} else {
|
} else {
|
||||||
// This may take a LONG time to create the storage.
|
// This may take a LONG time to create the storage.
|
||||||
_mgr.copyAndAddTorrent(file, canonical);
|
_mgr.copyAndAddTorrent(file, canonical, _dataDir);
|
||||||
snark = _mgr.getTorrentByBaseName(originalName);
|
snark = _mgr.getTorrentByBaseName(originalName);
|
||||||
if (snark != null)
|
if (snark != null)
|
||||||
snark.startTorrent();
|
snark.startTorrent();
|
||||||
|
@@ -30,6 +30,7 @@ import net.i2p.data.Base64;
|
|||||||
import net.i2p.data.DataHelper;
|
import net.i2p.data.DataHelper;
|
||||||
import net.i2p.data.Hash;
|
import net.i2p.data.Hash;
|
||||||
import net.i2p.util.Log;
|
import net.i2p.util.Log;
|
||||||
|
import net.i2p.util.SecureFile;
|
||||||
|
|
||||||
import org.klomp.snark.I2PSnarkUtil;
|
import org.klomp.snark.I2PSnarkUtil;
|
||||||
import org.klomp.snark.MagnetURI;
|
import org.klomp.snark.MagnetURI;
|
||||||
@@ -933,13 +934,41 @@ public class I2PSnarkServlet extends BasicServlet {
|
|||||||
} else
|
} else
|
||||||
*****/
|
*****/
|
||||||
if (newURL != null) {
|
if (newURL != null) {
|
||||||
|
String newDir = req.getParameter("nofilter_newDir");
|
||||||
|
File dir = null;
|
||||||
|
if (newDir != null) {
|
||||||
|
newDir = newDir.trim();
|
||||||
|
if (newDir.length() > 0) {
|
||||||
|
dir = new SecureFile(newDir);
|
||||||
|
if (!dir.isAbsolute()) {
|
||||||
|
_manager.addMessage(_("Data directory must be an absolute path") + ": " + dir);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!dir.isDirectory() && !dir.mkdirs()) {
|
||||||
|
_manager.addMessage(_("Data directory cannot be created") + ": " + dir);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Collection<Snark> snarks = _manager.getTorrents();
|
||||||
|
for (Snark s : snarks) {
|
||||||
|
Storage storage = s.getStorage();
|
||||||
|
if (storage == null)
|
||||||
|
continue;
|
||||||
|
File sbase = storage.getBase();
|
||||||
|
if (isParentOf(sbase, dir)) {
|
||||||
|
_manager.addMessage(_("Cannot add torrent {0} inside another torrent: {1}",
|
||||||
|
dir.getAbsolutePath(), sbase));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
if (newURL.startsWith("http://")) {
|
if (newURL.startsWith("http://")) {
|
||||||
FetchAndAdd fetch = new FetchAndAdd(_context, _manager, newURL);
|
FetchAndAdd fetch = new FetchAndAdd(_context, _manager, newURL, dir);
|
||||||
_manager.addDownloader(fetch);
|
_manager.addDownloader(fetch);
|
||||||
} else if (newURL.startsWith(MagnetURI.MAGNET) || newURL.startsWith(MagnetURI.MAGGOT)) {
|
} else if (newURL.startsWith(MagnetURI.MAGNET) || newURL.startsWith(MagnetURI.MAGGOT)) {
|
||||||
addMagnet(newURL);
|
addMagnet(newURL, dir);
|
||||||
} else if (newURL.length() == 40 && newURL.replaceAll("[a-fA-F0-9]", "").length() == 0) {
|
} else if (newURL.length() == 40 && newURL.replaceAll("[a-fA-F0-9]", "").length() == 0) {
|
||||||
addMagnet(MagnetURI.MAGNET_FULL + newURL);
|
addMagnet(MagnetURI.MAGNET_FULL + newURL, dir);
|
||||||
} else {
|
} else {
|
||||||
_manager.addMessage(_("Invalid URL: Must start with \"http://\", \"{0}\", or \"{1}\"",
|
_manager.addMessage(_("Invalid URL: Must start with \"http://\", \"{0}\", or \"{1}\"",
|
||||||
MagnetURI.MAGNET, MagnetURI.MAGGOT));
|
MagnetURI.MAGNET, MagnetURI.MAGGOT));
|
||||||
@@ -2000,6 +2029,7 @@ public class I2PSnarkServlet extends BasicServlet {
|
|||||||
out.write(toThemeImg("add"));
|
out.write(toThemeImg("add"));
|
||||||
out.write(' ');
|
out.write(' ');
|
||||||
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"));
|
||||||
out.write(":<td><input type=\"text\" name=\"nofilter_newURL\" size=\"85\" value=\"" + newURL + "\" spellcheck=\"false\"");
|
out.write(":<td><input type=\"text\" name=\"nofilter_newURL\" size=\"85\" value=\"" + newURL + "\" spellcheck=\"false\"");
|
||||||
@@ -2010,9 +2040,17 @@ public class I2PSnarkServlet extends BasicServlet {
|
|||||||
//out.write("From file: <input type=\"file\" name=\"newFile\" size=\"50\" value=\"" + newFile + "\" /><br>");
|
//out.write("From file: <input type=\"file\" name=\"newFile\" size=\"50\" value=\"" + newFile + "\" /><br>");
|
||||||
out.write("<input type=\"submit\" class=\"add\" value=\"");
|
out.write("<input type=\"submit\" class=\"add\" value=\"");
|
||||||
out.write(_("Add torrent"));
|
out.write(_("Add torrent"));
|
||||||
out.write("\" name=\"foo\" ><br>\n");
|
out.write("\" name=\"foo\" ><br>\n" +
|
||||||
|
|
||||||
|
"<tr><td>");
|
||||||
|
out.write(_("Data dir"));
|
||||||
|
out.write(":<td><input type=\"text\" name=\"nofilter_newDir\" size=\"85\" value=\"\" spellcheck=\"false\"");
|
||||||
|
out.write(" title=\"");
|
||||||
|
out.write(_("Enter the directory to save the data in (default {0})", _manager.getDataDir().getAbsolutePath()));
|
||||||
|
out.write("\"></td></tr>\n");
|
||||||
|
|
||||||
out.write("<tr><td> <td><span class=\"snarkAddInfo\">");
|
out.write("<tr><td> <td><span class=\"snarkAddInfo\">");
|
||||||
out.write(_("You can also copy .torrent files to: {0}.", "<code>" + _manager.getDataDir().getAbsolutePath () + "</code>"));
|
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 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");
|
||||||
@@ -2372,15 +2410,16 @@ public class I2PSnarkServlet extends BasicServlet {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @param url in base32 or hex
|
* @param url in base32 or hex
|
||||||
|
* @param dataDir null to default to snark data directory
|
||||||
* @since 0.8.4
|
* @since 0.8.4
|
||||||
*/
|
*/
|
||||||
private void addMagnet(String url) {
|
private void addMagnet(String url, File dataDir) {
|
||||||
try {
|
try {
|
||||||
MagnetURI magnet = new MagnetURI(_manager.util(), url);
|
MagnetURI magnet = new MagnetURI(_manager.util(), url);
|
||||||
String name = magnet.getName();
|
String name = magnet.getName();
|
||||||
byte[] ih = magnet.getInfoHash();
|
byte[] ih = magnet.getInfoHash();
|
||||||
String trackerURL = magnet.getTrackerURL();
|
String trackerURL = magnet.getTrackerURL();
|
||||||
_manager.addMagnet(name, ih, trackerURL, true);
|
_manager.addMagnet(name, ih, trackerURL, true, dataDir);
|
||||||
} catch (IllegalArgumentException iae) {
|
} catch (IllegalArgumentException iae) {
|
||||||
_manager.addMessage(_("Invalid magnet URL {0}", url));
|
_manager.addMessage(_("Invalid magnet URL {0}", url));
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user