package net.i2p.time;
import java.io.File;
import java.io.InputStream;
import java.io.IOException;
import java.net.URL;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;
import java.util.TimeZone;
import java.util.jar.Attributes;
import java.util.jar.Manifest;
import net.i2p.I2PAppContext;
import net.i2p.util.SystemVersion;
/**
* Get the build date as set in i2p.jar,
* and reasonable min and max values for the current time,
* to be used as sanity checks.
*
* Idea taken from Chrome, which assumes any clock more than
* 2 days before or 1 year after the build date is bad.
*
* Not maintained as a public API, not for use by plugins or applications.
*
* @since 0.9.25 modded from FileDumpHelper
*/
public class BuildTime {
private static final long _buildTime;
private static final long _earliestTime;
private static final long _latestTime;
private static final long YEARS_25 = 25L*365*24*60*60*1000;
/** update this periodically */
private static final String EARLIEST = "2017-03-27 12:00:00 UTC";
// fallback if parse fails ticket #1976
// date -d 201x-xx-xx +%s
private static final long EARLIEST_LONG = 1490587200 * 1000L;
static {
// this is the standard format of build.timestamp as set in the top-level build.xml
SimpleDateFormat fmt = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss z", Locale.US);
TimeZone utc = TimeZone.getTimeZone("GMT");
fmt.setTimeZone(utc);
long min;
try {
Date date = fmt.parse(EARLIEST);
if (date == null)
min = EARLIEST_LONG;
else
min = date.getTime();
} catch (ParseException pe) {
System.out.println("BuildTime FAIL");
// Old Android, ticket #1976
//pe.printStackTrace();
//throw new RuntimeException("BuildTime FAIL", pe);
min = EARLIEST_LONG;
}
long max = min + YEARS_25;
long build = getBuildTime(fmt, "i2p.jar");
if (build > max) {
System.out.println("Warning: Strange build time, contact packager: " + new Date(build));
build = max;
} else if (build < min) {
if (build > 0)
System.out.println("Warning: Strange build time, contact packager: " + new Date(build));
build = min;
} else {
// build time looks reasonable
// allow 24h skew on build machine
min = build - 24*60*60*1000L;
}
_earliestTime = min;
_latestTime = max;
_buildTime = build;
}
/**
* Get the build date for i2p.jar.
*
* @return the earliest possible time if actual build date is unknown
*/
public static long getBuildTime() {
return _buildTime;
}
/**
* Get the earliest it could possibly be right now.
* Latest of the build time minus a day, or a hardcoded time.
*
* @return the time
*/
public static long getEarliestTime() {
return _earliestTime;
}
/**
* Get the latest it could possibly be right now.
* Hardcoded.
*
* @return the time
*/
public static long getLatestTime() {
return _latestTime;
}
private BuildTime() {}
/**
* Won't be available on Android or on any builds not using our build.xml.
*
* @return 0 if unknown
*/
private static long getBuildTime(SimpleDateFormat fmt, String jar) {
if (SystemVersion.isAndroid())
return 0;
File f = new File(I2PAppContext.getGlobalContext().getBaseDir(), "lib");
f = new File(f, jar);
Attributes atts = attributes(f);
if (atts == null)
return 0;
String s = atts.getValue("Build-Date");
if (s == null)
return 0;
try {
Date date = fmt.parse(s);
if (date != null) {
return date.getTime();
}
} catch (ParseException pe) {}
return 0;
}
private static Attributes attributes(File f) {
InputStream in = null;
try {
in = (new URL("jar:file:" + f.getAbsolutePath() + "!/META-INF/MANIFEST.MF")).openStream();
Manifest man = new Manifest(in);
return man.getMainAttributes();
} catch (IOException ioe) {
return null;
} finally {
if (in != null) try { in.close(); } catch (IOException e) {}
}
}
/****
public static void main(String[] args) {
long date = getEarliestTime();
System.out.println("Earliest date: " + new Date(date));
date = getBuildTime();
System.out.println("Build date: " + new Date(date));
date = System.currentTimeMillis();
System.out.println("System time: " + new Date(date));
date = I2PAppContext.getGlobalContext().clock().now();
System.out.println("I2P time: " + new Date(date));
date = getLatestTime();
System.out.println("Latest date: " + new Date(date));
}
****/
}