forked from I2P_Developers/i2p.i2p
Build:
- Include geoip in update files for next release - Add created-by string to release torrents i2psnark: - Store torrent added and completed times in config files, display on details page - Display dates on details page in local time zone - Add metainfo creation command line support for created-by string
This commit is contained in:
@ -74,10 +74,11 @@ public class MetaInfo
|
|||||||
* @param files null for single-file torrent
|
* @param files null for single-file torrent
|
||||||
* @param lengths null for single-file torrent
|
* @param lengths null for single-file torrent
|
||||||
* @param announce_list may be null
|
* @param announce_list may be null
|
||||||
|
* @param created_by may be null
|
||||||
*/
|
*/
|
||||||
MetaInfo(String announce, String name, String name_utf8, List<List<String>> files, List<Long> lengths,
|
MetaInfo(String announce, String name, String name_utf8, List<List<String>> files, List<Long> lengths,
|
||||||
int piece_length, byte[] piece_hashes, long length, boolean privateTorrent,
|
int piece_length, byte[] piece_hashes, long length, boolean privateTorrent,
|
||||||
List<List<String>> announce_list)
|
List<List<String>> announce_list, String created_by)
|
||||||
{
|
{
|
||||||
this.announce = announce;
|
this.announce = announce;
|
||||||
this.name = name;
|
this.name = name;
|
||||||
@ -91,7 +92,7 @@ public class MetaInfo
|
|||||||
this.privateTorrent = privateTorrent;
|
this.privateTorrent = privateTorrent;
|
||||||
this.announce_list = announce_list;
|
this.announce_list = announce_list;
|
||||||
this.comment = null;
|
this.comment = null;
|
||||||
this.created_by = null;
|
this.created_by = created_by;
|
||||||
this.creation_date = I2PAppContext.getGlobalContext().clock().now();
|
this.creation_date = I2PAppContext.getGlobalContext().clock().now();
|
||||||
|
|
||||||
// TODO if we add a parameter for other keys
|
// TODO if we add a parameter for other keys
|
||||||
|
@ -96,6 +96,8 @@ public class SnarkManager implements CompleteListener {
|
|||||||
private static final String PROP_META_PRIORITY = "priority";
|
private static final String PROP_META_PRIORITY = "priority";
|
||||||
private static final String PROP_META_PRESERVE_NAMES = "preserveFileNames";
|
private static final String PROP_META_PRESERVE_NAMES = "preserveFileNames";
|
||||||
private static final String PROP_META_UPLOADED = "uploaded";
|
private static final String PROP_META_UPLOADED = "uploaded";
|
||||||
|
private static final String PROP_META_ADDED = "added";
|
||||||
|
private static final String PROP_META_COMPLETED = "completed";
|
||||||
//private static final String PROP_META_BITFIELD_SUFFIX = ".bitfield";
|
//private static final String PROP_META_BITFIELD_SUFFIX = ".bitfield";
|
||||||
//private static final String PROP_META_PRIORITY_SUFFIX = ".priority";
|
//private static final String PROP_META_PRIORITY_SUFFIX = ".priority";
|
||||||
private static final String PROP_META_MAGNET_PREFIX = "i2psnark.magnet.";
|
private static final String PROP_META_MAGNET_PREFIX = "i2psnark.magnet.";
|
||||||
@ -1624,6 +1626,25 @@ public class SnarkManager implements CompleteListener {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get setting for a torrent from the config file.
|
||||||
|
* @return non-null, rv[0] is added time or 0; rv[1] is completed time or 0
|
||||||
|
* @since 0.9.23
|
||||||
|
*/
|
||||||
|
public long[] getSavedAddedAndCompleted(Snark snark) {
|
||||||
|
long[] rv = new long[2];
|
||||||
|
Properties config = getConfig(snark);
|
||||||
|
if (config != null) {
|
||||||
|
try {
|
||||||
|
rv[0] = Long.parseLong(config.getProperty(PROP_META_ADDED));
|
||||||
|
} catch (NumberFormatException nfe) {}
|
||||||
|
try {
|
||||||
|
rv[1] = Long.parseLong(config.getProperty(PROP_META_COMPLETED));
|
||||||
|
} catch (NumberFormatException nfe) {}
|
||||||
|
}
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Save the completion status of a torrent and other data in the config file
|
* Save the completion status of a torrent and other data in the config file
|
||||||
* for that torrent. Does nothing for magnets.
|
* for that torrent. Does nothing for magnets.
|
||||||
@ -1661,19 +1682,25 @@ public class SnarkManager implements CompleteListener {
|
|||||||
private void locked_saveTorrentStatus(MetaInfo metainfo, BitField bitfield, int[] priorities,
|
private void locked_saveTorrentStatus(MetaInfo metainfo, BitField bitfield, int[] priorities,
|
||||||
File base, boolean preserveNames, long uploaded, boolean stopped) {
|
File base, boolean preserveNames, long uploaded, boolean stopped) {
|
||||||
byte[] ih = metainfo.getInfoHash();
|
byte[] ih = metainfo.getInfoHash();
|
||||||
|
Properties config = getConfig(ih);
|
||||||
|
String now = Long.toString(System.currentTimeMillis());
|
||||||
|
config.setProperty(PROP_META_STAMP, now);
|
||||||
|
if (config.getProperty(PROP_META_ADDED) == null)
|
||||||
|
config.setProperty(PROP_META_ADDED, now);
|
||||||
String bfs;
|
String bfs;
|
||||||
if (bitfield.complete()) {
|
if (bitfield.complete()) {
|
||||||
bfs = ".";
|
bfs = ".";
|
||||||
|
if (config.getProperty(PROP_META_COMPLETED) == null)
|
||||||
|
config.setProperty(PROP_META_COMPLETED, now);
|
||||||
} else {
|
} else {
|
||||||
byte[] bf = bitfield.getFieldBytes();
|
byte[] bf = bitfield.getFieldBytes();
|
||||||
bfs = Base64.encode(bf);
|
bfs = Base64.encode(bf);
|
||||||
|
config.remove(PROP_META_COMPLETED);
|
||||||
}
|
}
|
||||||
boolean running = !stopped;
|
|
||||||
Properties config = getConfig(ih);
|
|
||||||
config.setProperty(PROP_META_STAMP, Long.toString(System.currentTimeMillis()));
|
|
||||||
config.setProperty(PROP_META_BITFIELD, bfs);
|
config.setProperty(PROP_META_BITFIELD, bfs);
|
||||||
config.setProperty(PROP_META_PRESERVE_NAMES, Boolean.toString(preserveNames));
|
config.setProperty(PROP_META_PRESERVE_NAMES, Boolean.toString(preserveNames));
|
||||||
config.setProperty(PROP_META_UPLOADED, Long.toString(uploaded));
|
config.setProperty(PROP_META_UPLOADED, Long.toString(uploaded));
|
||||||
|
boolean running = !stopped;
|
||||||
config.setProperty(PROP_META_RUNNING, Boolean.toString(running));
|
config.setProperty(PROP_META_RUNNING, Boolean.toString(running));
|
||||||
if (base != null)
|
if (base != null)
|
||||||
config.setProperty(PROP_META_BASE, base.getAbsolutePath());
|
config.setProperty(PROP_META_BASE, base.getAbsolutePath());
|
||||||
|
@ -39,6 +39,8 @@ import java.util.TreeSet;
|
|||||||
import java.util.concurrent.ConcurrentHashMap;
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
import java.util.concurrent.atomic.AtomicInteger;
|
import java.util.concurrent.atomic.AtomicInteger;
|
||||||
|
|
||||||
|
import gnu.getopt.Getopt;
|
||||||
|
|
||||||
import net.i2p.I2PAppContext;
|
import net.i2p.I2PAppContext;
|
||||||
import net.i2p.crypto.SHA1;
|
import net.i2p.crypto.SHA1;
|
||||||
import net.i2p.data.ByteArray;
|
import net.i2p.data.ByteArray;
|
||||||
@ -123,10 +125,12 @@ public class Storage implements Closeable
|
|||||||
*
|
*
|
||||||
* @param announce may be null
|
* @param announce may be null
|
||||||
* @param listener may be null
|
* @param listener may be null
|
||||||
|
* @param created_by may be null
|
||||||
* @throws IOException when creating and/or checking files fails.
|
* @throws IOException when creating and/or checking files fails.
|
||||||
*/
|
*/
|
||||||
public Storage(I2PSnarkUtil util, File baseFile, String announce,
|
public Storage(I2PSnarkUtil util, File baseFile, String announce,
|
||||||
List<List<String>> announce_list,
|
List<List<String>> announce_list,
|
||||||
|
String created_by,
|
||||||
boolean privateTorrent, StorageListener listener)
|
boolean privateTorrent, StorageListener listener)
|
||||||
throws IOException
|
throws IOException
|
||||||
{
|
{
|
||||||
@ -195,7 +199,7 @@ public class Storage implements Closeable
|
|||||||
byte[] piece_hashes = fast_digestCreate();
|
byte[] piece_hashes = fast_digestCreate();
|
||||||
metainfo = new MetaInfo(announce, baseFile.getName(), null, files,
|
metainfo = new MetaInfo(announce, baseFile.getName(), null, files,
|
||||||
lengthsList, piece_size, piece_hashes, total, privateTorrent,
|
lengthsList, piece_size, piece_hashes, total, privateTorrent,
|
||||||
announce_list);
|
announce_list, created_by);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1373,18 +1377,44 @@ public class Storage implements Closeable
|
|||||||
* @since 0.9.4
|
* @since 0.9.4
|
||||||
*/
|
*/
|
||||||
public static void main(String[] args) {
|
public static void main(String[] args) {
|
||||||
if (args.length < 1 || args.length > 2) {
|
boolean error = false;
|
||||||
System.err.println("Usage: Storage file-or-dir [announceURL]");
|
String created_by = null;
|
||||||
|
String announce = null;
|
||||||
|
Getopt g = new Getopt("Storage", args, "a:c:");
|
||||||
|
try {
|
||||||
|
int c;
|
||||||
|
while ((c = g.getopt()) != -1) {
|
||||||
|
switch (c) {
|
||||||
|
case 'a':
|
||||||
|
announce = g.getOptarg();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'c':
|
||||||
|
created_by = g.getOptarg();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case '?':
|
||||||
|
case ':':
|
||||||
|
default:
|
||||||
|
error = true;
|
||||||
|
break;
|
||||||
|
} // switch
|
||||||
|
} // while
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
error = true;
|
||||||
|
}
|
||||||
|
if (error || args.length - g.getOptind() != 1) {
|
||||||
|
System.err.println("Usage: Storage [-a announceURL] [-c created-by] file-or-dir");
|
||||||
System.exit(1);
|
System.exit(1);
|
||||||
}
|
}
|
||||||
File base = new File(args[0]);
|
File base = new File(args[g.getOptind()]);
|
||||||
String announce = args.length == 2 ? args[1] : null;
|
|
||||||
I2PAppContext ctx = I2PAppContext.getGlobalContext();
|
I2PAppContext ctx = I2PAppContext.getGlobalContext();
|
||||||
I2PSnarkUtil util = new I2PSnarkUtil(ctx);
|
I2PSnarkUtil util = new I2PSnarkUtil(ctx);
|
||||||
File file = null;
|
File file = null;
|
||||||
FileOutputStream out = null;
|
FileOutputStream out = null;
|
||||||
try {
|
try {
|
||||||
Storage storage = new Storage(util, base, announce, null, false, null);
|
Storage storage = new Storage(util, base, announce, null, created_by, false, null);
|
||||||
MetaInfo meta = storage.getMetaInfo();
|
MetaInfo meta = storage.getMetaInfo();
|
||||||
file = new File(storage.getBaseName() + ".torrent");
|
file = new File(storage.getBaseName() + ".torrent");
|
||||||
out = new FileOutputStream(file);
|
out = new FileOutputStream(file);
|
||||||
|
@ -18,6 +18,7 @@ import java.util.List;
|
|||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
import java.util.TimeZone;
|
||||||
import java.util.TreeMap;
|
import java.util.TreeMap;
|
||||||
|
|
||||||
import javax.servlet.ServletConfig;
|
import javax.servlet.ServletConfig;
|
||||||
@ -1230,7 +1231,7 @@ public class I2PSnarkServlet extends BasicServlet {
|
|||||||
// it shouldn't be THAT bad, so keep it in this thread.
|
// it shouldn't be THAT bad, so keep it in this thread.
|
||||||
// TODO thread it for big torrents, perhaps a la FetchAndAdd
|
// TODO thread it for big torrents, perhaps a la FetchAndAdd
|
||||||
boolean isPrivate = _manager.getPrivateTrackers().contains(announceURL);
|
boolean isPrivate = _manager.getPrivateTrackers().contains(announceURL);
|
||||||
Storage s = new Storage(_manager.util(), baseFile, announceURL, announceList, isPrivate, null);
|
Storage s = new Storage(_manager.util(), baseFile, announceURL, announceList, null, isPrivate, null);
|
||||||
s.close(); // close the files... maybe need a way to pass this Storage to addTorrent rather than starting over
|
s.close(); // close the files... maybe need a way to pass this Storage to addTorrent rather than starting over
|
||||||
MetaInfo info = s.getMetaInfo();
|
MetaInfo info = s.getMetaInfo();
|
||||||
File torrentFile = new File(_manager.getDataDir(), s.getBaseName() + ".torrent");
|
File torrentFile = new File(_manager.getDataDir(), s.getBaseName() + ".torrent");
|
||||||
@ -2763,13 +2764,17 @@ public class I2PSnarkServlet extends BasicServlet {
|
|||||||
.append("</td></tr>\n");
|
.append("</td></tr>\n");
|
||||||
}
|
}
|
||||||
long dat = meta.getCreationDate();
|
long dat = meta.getCreationDate();
|
||||||
|
SimpleDateFormat fmt = new SimpleDateFormat("yyyy-MM-dd HH:mm");
|
||||||
|
String systemTimeZone = _context.getProperty("i2p.systemTimeZone");
|
||||||
|
if (systemTimeZone != null)
|
||||||
|
fmt.setTimeZone(TimeZone.getTimeZone(systemTimeZone));
|
||||||
if (dat > 0) {
|
if (dat > 0) {
|
||||||
String date = (new SimpleDateFormat("yyyy-MM-dd HH:mm")).format(new Date(dat));
|
String date = fmt.format(new Date(dat));
|
||||||
buf.append("<tr><td>");
|
buf.append("<tr><td>");
|
||||||
toThemeImg(buf, "details");
|
toThemeImg(buf, "details");
|
||||||
buf.append(" <b>")
|
buf.append(" <b>")
|
||||||
.append(_("Created")).append(":</b> ")
|
.append(_("Created")).append(":</b> ")
|
||||||
.append(date).append(" UTC")
|
.append(date)
|
||||||
.append("</td></tr>\n");
|
.append("</td></tr>\n");
|
||||||
}
|
}
|
||||||
String cby = meta.getCreatedBy();
|
String cby = meta.getCreatedBy();
|
||||||
@ -2783,6 +2788,25 @@ public class I2PSnarkServlet extends BasicServlet {
|
|||||||
.append(DataHelper.stripHTML(cby))
|
.append(DataHelper.stripHTML(cby))
|
||||||
.append("</td></tr>\n");
|
.append("</td></tr>\n");
|
||||||
}
|
}
|
||||||
|
long[] dates = _manager.getSavedAddedAndCompleted(snark);
|
||||||
|
if (dates[0] > 0) {
|
||||||
|
String date = fmt.format(new Date(dates[0]));
|
||||||
|
buf.append("<tr><td>");
|
||||||
|
toThemeImg(buf, "details");
|
||||||
|
buf.append(" <b>")
|
||||||
|
.append(_("Added")).append(":</b> ")
|
||||||
|
.append(date)
|
||||||
|
.append("</td></tr>\n");
|
||||||
|
}
|
||||||
|
if (dates[1] > 0) {
|
||||||
|
String date = fmt.format(new Date(dates[1]));
|
||||||
|
buf.append("<tr><td>");
|
||||||
|
toThemeImg(buf, "details");
|
||||||
|
buf.append(" <b>")
|
||||||
|
.append(_("Completed")).append(":</b> ")
|
||||||
|
.append(date)
|
||||||
|
.append("</td></tr>\n");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (meta == null || !meta.isPrivate()) {
|
if (meta == null || !meta.isPrivate()) {
|
||||||
|
@ -100,8 +100,11 @@
|
|||||||
<pathelement location="build/i2p.jar" />
|
<pathelement location="build/i2p.jar" />
|
||||||
<pathelement location="build/i2psnark.jar" />
|
<pathelement location="build/i2psnark.jar" />
|
||||||
</classpath>
|
</classpath>
|
||||||
<arg value="@{file}" />
|
<arg value="-a" />
|
||||||
<arg value="http://tracker2.postman.i2p/announce.php" />
|
<arg value="http://tracker2.postman.i2p/announce.php" />
|
||||||
|
<arg value="-c" />
|
||||||
|
<arg value="${build.built-by}" />
|
||||||
|
<arg value="@{file}" />
|
||||||
</java>
|
</java>
|
||||||
</sequential>
|
</sequential>
|
||||||
</macrodef>
|
</macrodef>
|
||||||
@ -1763,9 +1766,11 @@
|
|||||||
since preppkg puts too much stuff in pkg-temp -->
|
since preppkg puts too much stuff in pkg-temp -->
|
||||||
<!--
|
<!--
|
||||||
<target name="release" depends="distclean, updaterWithJettyFixesAndJbigi , updater200WithJettyFixes, preppkg, installer, getReleaseNumber" >
|
<target name="release" depends="distclean, updaterWithJettyFixesAndJbigi , updater200WithJettyFixes, preppkg, installer, getReleaseNumber" >
|
||||||
<target name="release" depends="verifyReleaseBuildNumbers, -pre-release, distclean, testscripts, updaterWithJettyAndGeoIPRepack, updater200WithJettyAndGeoIP, delete-j6-update, installer-nowindows, delete-nonwindows, installer-windows">
|
|
||||||
-->
|
-->
|
||||||
|
<target name="release" depends="verifyReleaseBuildNumbers, -pre-release, distclean, testscripts, updaterWithJettyAndGeoIPRepack, updater200WithJettyAndGeoIP, delete-j6-update, installer-nowindows, delete-nonwindows, installer-windows">
|
||||||
|
<!--
|
||||||
<target name="release" depends="verifyReleaseBuildNumbers, -pre-release, distclean, testscripts, updaterWithJettyRepack, updater200WithJetty, delete-j6-update, installer-nowindows, delete-nonwindows, installer-windows">
|
<target name="release" depends="verifyReleaseBuildNumbers, -pre-release, distclean, testscripts, updaterWithJettyRepack, updater200WithJetty, delete-j6-update, installer-nowindows, delete-nonwindows, installer-windows">
|
||||||
|
-->
|
||||||
<echo message="New version number is ${release.number}" />
|
<echo message="New version number is ${release.number}" />
|
||||||
<copy file="i2pupdate.zip" tofile="i2pupdate_${release.number}.zip" />
|
<copy file="i2pupdate.zip" tofile="i2pupdate_${release.number}.zip" />
|
||||||
<copy file="i2pinstall_${full.version}.jar" tofile="i2pinstall_${release.number}.jar" />
|
<copy file="i2pinstall_${full.version}.jar" tofile="i2pinstall_${release.number}.jar" />
|
||||||
|
Reference in New Issue
Block a user