propagate from branch 'i2p.i2p.zzz.homepage' (head 27c8ea684056ce34ea81acdfd18571776ca63641)
to branch 'i2p.i2p' (head 83f37b19742045fa42ed71a0abd8e90d080c2c05)
@@ -56,6 +56,7 @@
|
|||||||
<manifest>
|
<manifest>
|
||||||
<attribute name="Main-Class" value="addressbook.Daemon"/>
|
<attribute name="Main-Class" value="addressbook.Daemon"/>
|
||||||
<attribute name="Implementation-Version" value="${full.version}" />
|
<attribute name="Implementation-Version" value="${full.version}" />
|
||||||
|
<attribute name="Built-By" value="${build.built-by}" />
|
||||||
<attribute name="Build-Date" value="${build.timestamp}" />
|
<attribute name="Build-Date" value="${build.timestamp}" />
|
||||||
<attribute name="Base-Revision" value="${workspace.version}" />
|
<attribute name="Base-Revision" value="${workspace.version}" />
|
||||||
<attribute name="Workspace-Changes" value="${workspace.changes}" />
|
<attribute name="Workspace-Changes" value="${workspace.changes}" />
|
||||||
@@ -75,6 +76,7 @@
|
|||||||
<war basedir="${dist}/tmp" webxml="web.xml" destfile="${dist}/${war}">
|
<war basedir="${dist}/tmp" webxml="web.xml" destfile="${dist}/${war}">
|
||||||
<manifest>
|
<manifest>
|
||||||
<attribute name="Implementation-Version" value="${full.version}" />
|
<attribute name="Implementation-Version" value="${full.version}" />
|
||||||
|
<attribute name="Built-By" value="${build.built-by}" />
|
||||||
<attribute name="Build-Date" value="${build.timestamp}" />
|
<attribute name="Build-Date" value="${build.timestamp}" />
|
||||||
<attribute name="Base-Revision" value="${workspace.version}" />
|
<attribute name="Base-Revision" value="${workspace.version}" />
|
||||||
<attribute name="Workspace-Changes" value="${workspace.changes.tr}" />
|
<attribute name="Workspace-Changes" value="${workspace.changes.tr}" />
|
||||||
|
Before Width: | Height: | Size: 464 B After Width: | Height: | Size: 464 B |
Before Width: | Height: | Size: 587 B After Width: | Height: | Size: 587 B |
Before Width: | Height: | Size: 673 B After Width: | Height: | Size: 673 B |
Before Width: | Height: | Size: 882 B After Width: | Height: | Size: 882 B |
Before Width: | Height: | Size: 889 B After Width: | Height: | Size: 889 B |
Before Width: | Height: | Size: 766 B After Width: | Height: | Size: 766 B |
Before Width: | Height: | Size: 653 B After Width: | Height: | Size: 653 B |
Before Width: | Height: | Size: 537 B After Width: | Height: | Size: 537 B |
Before Width: | Height: | Size: 578 B After Width: | Height: | Size: 578 B |
Before Width: | Height: | Size: 591 B After Width: | Height: | Size: 591 B |
Before Width: | Height: | Size: 385 B After Width: | Height: | Size: 385 B |
Before Width: | Height: | Size: 853 B After Width: | Height: | Size: 853 B |
Before Width: | Height: | Size: 635 B After Width: | Height: | Size: 635 B |
Before Width: | Height: | Size: 294 B After Width: | Height: | Size: 294 B |
Before Width: | Height: | Size: 591 B After Width: | Height: | Size: 591 B |
Before Width: | Height: | Size: 589 B After Width: | Height: | Size: 589 B |
Before Width: | Height: | Size: 591 B After Width: | Height: | Size: 591 B |
Before Width: | Height: | Size: 537 B After Width: | Height: | Size: 537 B |
@@ -61,6 +61,7 @@
|
|||||||
<attribute name="Main-Class" value="org.klomp.snark.Snark" />
|
<attribute name="Main-Class" value="org.klomp.snark.Snark" />
|
||||||
<attribute name="Class-Path" value="i2p.jar mstreaming.jar streaming.jar" />
|
<attribute name="Class-Path" value="i2p.jar mstreaming.jar streaming.jar" />
|
||||||
<attribute name="Implementation-Version" value="${full.version}" />
|
<attribute name="Implementation-Version" value="${full.version}" />
|
||||||
|
<attribute name="Built-By" value="${build.built-by}" />
|
||||||
<attribute name="Build-Date" value="${build.timestamp}" />
|
<attribute name="Build-Date" value="${build.timestamp}" />
|
||||||
<attribute name="Base-Revision" value="${workspace.version}" />
|
<attribute name="Base-Revision" value="${workspace.version}" />
|
||||||
<attribute name="Workspace-Changes" value="${workspace.changes.tr}" />
|
<attribute name="Workspace-Changes" value="${workspace.changes.tr}" />
|
||||||
@@ -95,11 +96,16 @@
|
|||||||
<target name="war" depends="jar, bundle, warUpToDate, listChangedFiles" unless="war.uptodate" >
|
<target name="war" depends="jar, bundle, warUpToDate, listChangedFiles" unless="war.uptodate" >
|
||||||
<!-- set if unset -->
|
<!-- set if unset -->
|
||||||
<property name="workspace.changes.tr" value="" />
|
<property name="workspace.changes.tr" value="" />
|
||||||
<war destfile="../i2psnark.war" webxml="../web.xml" basedir="../" includes="_icons/*" >
|
<copy todir="build/icons/.icons" >
|
||||||
|
<fileset dir="../icons/" />
|
||||||
|
</copy>
|
||||||
|
<war destfile="../i2psnark.war" webxml="../web.xml" >
|
||||||
<!-- include only the web stuff, as of 0.7.12 the router will add i2psnark.jar to the classpath for the war -->
|
<!-- include only the web stuff, as of 0.7.12 the router will add i2psnark.jar to the classpath for the war -->
|
||||||
<classes dir="./build/obj" includes="**/web/*.class" />
|
<classes dir="./build/obj" includes="**/web/*.class" />
|
||||||
|
<fileset dir="build/icons/" />
|
||||||
<manifest>
|
<manifest>
|
||||||
<attribute name="Implementation-Version" value="${full.version}" />
|
<attribute name="Implementation-Version" value="${full.version}" />
|
||||||
|
<attribute name="Built-By" value="${build.built-by}" />
|
||||||
<attribute name="Build-Date" value="${build.timestamp}" />
|
<attribute name="Build-Date" value="${build.timestamp}" />
|
||||||
<attribute name="Base-Revision" value="${workspace.version}" />
|
<attribute name="Base-Revision" value="${workspace.version}" />
|
||||||
<attribute name="Workspace-Changes" value="${workspace.changes.tr}" />
|
<attribute name="Workspace-Changes" value="${workspace.changes.tr}" />
|
||||||
@@ -109,7 +115,7 @@
|
|||||||
|
|
||||||
<target name="warUpToDate">
|
<target name="warUpToDate">
|
||||||
<uptodate property="war.uptodate" targetfile="../i2psnark.war" >
|
<uptodate property="war.uptodate" targetfile="../i2psnark.war" >
|
||||||
<srcfiles dir= "." includes="build/obj/org/klomp/snark/web/*.class ../_icons/* ../web.xml" />
|
<srcfiles dir= "." includes="build/obj/org/klomp/snark/web/*.class ../icons/* ../web.xml" />
|
||||||
</uptodate>
|
</uptodate>
|
||||||
</target>
|
</target>
|
||||||
|
|
||||||
|
@@ -39,15 +39,19 @@ abstract class ExtensionHandler {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @param metasize -1 if unknown
|
* @param metasize -1 if unknown
|
||||||
|
* @param pexAndMetadata advertise these capabilities
|
||||||
* @return bencoded outgoing handshake message
|
* @return bencoded outgoing handshake message
|
||||||
*/
|
*/
|
||||||
public static byte[] getHandshake(int metasize) {
|
public static byte[] getHandshake(int metasize, boolean pexAndMetadata) {
|
||||||
Map<String, Object> handshake = new HashMap();
|
Map<String, Object> handshake = new HashMap();
|
||||||
Map<String, Integer> m = new HashMap();
|
Map<String, Integer> m = new HashMap();
|
||||||
m.put(TYPE_METADATA, Integer.valueOf(ID_METADATA));
|
if (pexAndMetadata) {
|
||||||
m.put(TYPE_PEX, Integer.valueOf(ID_PEX));
|
m.put(TYPE_METADATA, Integer.valueOf(ID_METADATA));
|
||||||
if (metasize >= 0)
|
m.put(TYPE_PEX, Integer.valueOf(ID_PEX));
|
||||||
handshake.put("metadata_size", Integer.valueOf(metasize));
|
if (metasize >= 0)
|
||||||
|
handshake.put("metadata_size", Integer.valueOf(metasize));
|
||||||
|
}
|
||||||
|
// include the map even if empty so the far-end doesn't NPE
|
||||||
handshake.put("m", m);
|
handshake.put("m", m);
|
||||||
handshake.put("p", Integer.valueOf(6881));
|
handshake.put("p", Integer.valueOf(6881));
|
||||||
handshake.put("v", "I2PSnark");
|
handshake.put("v", "I2PSnark");
|
||||||
|
@@ -219,6 +219,10 @@ public class I2PSnarkUtil {
|
|||||||
// opts.setProperty("i2p.streaming.writeTimeout", "90000");
|
// opts.setProperty("i2p.streaming.writeTimeout", "90000");
|
||||||
//if (opts.getProperty("i2p.streaming.readTimeout") == null)
|
//if (opts.getProperty("i2p.streaming.readTimeout") == null)
|
||||||
// opts.setProperty("i2p.streaming.readTimeout", "120000");
|
// opts.setProperty("i2p.streaming.readTimeout", "120000");
|
||||||
|
if (opts.getProperty("i2p.streaming.maxConnsPerMinute") == null)
|
||||||
|
opts.setProperty("i2p.streaming.maxConnsPerMinute", "2");
|
||||||
|
if (opts.getProperty("i2p.streaming.maxTotalConnsPerMinute") == null)
|
||||||
|
opts.setProperty("i2p.streaming.maxTotalConnsPerMinute", "6");
|
||||||
_manager = I2PSocketManagerFactory.createManager(_i2cpHost, _i2cpPort, opts);
|
_manager = I2PSocketManagerFactory.createManager(_i2cpHost, _i2cpPort, opts);
|
||||||
}
|
}
|
||||||
// FIXME this only instantiates krpc once, left stuck with old manager
|
// FIXME this only instantiates krpc once, left stuck with old manager
|
||||||
|
@@ -61,6 +61,7 @@ public class MetaInfo
|
|||||||
private final int piece_length;
|
private final int piece_length;
|
||||||
private final byte[] piece_hashes;
|
private final byte[] piece_hashes;
|
||||||
private final long length;
|
private final long length;
|
||||||
|
private final boolean privateTorrent;
|
||||||
private Map<String, BEValue> infoMap;
|
private Map<String, BEValue> infoMap;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -71,7 +72,7 @@ public class MetaInfo
|
|||||||
* @param lengths null for single-file torrent
|
* @param lengths null for single-file torrent
|
||||||
*/
|
*/
|
||||||
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)
|
int piece_length, byte[] piece_hashes, long length, boolean privateTorrent)
|
||||||
{
|
{
|
||||||
this.announce = announce;
|
this.announce = announce;
|
||||||
this.name = name;
|
this.name = name;
|
||||||
@@ -82,6 +83,7 @@ public class MetaInfo
|
|||||||
this.piece_length = piece_length;
|
this.piece_length = piece_length;
|
||||||
this.piece_hashes = piece_hashes;
|
this.piece_hashes = piece_hashes;
|
||||||
this.length = length;
|
this.length = length;
|
||||||
|
this.privateTorrent = privateTorrent;
|
||||||
|
|
||||||
// TODO if we add a parameter for other keys
|
// TODO if we add a parameter for other keys
|
||||||
//if (other != null) {
|
//if (other != null) {
|
||||||
@@ -160,6 +162,10 @@ public class MetaInfo
|
|||||||
else
|
else
|
||||||
name_utf8 = null;
|
name_utf8 = null;
|
||||||
|
|
||||||
|
// BEP 27
|
||||||
|
val = info.get("private");
|
||||||
|
privateTorrent = val != null && val.getString().equals("1");
|
||||||
|
|
||||||
val = info.get("piece length");
|
val = info.get("piece length");
|
||||||
if (val == null)
|
if (val == null)
|
||||||
throw new InvalidBEncodingException("Missing piece length number");
|
throw new InvalidBEncodingException("Missing piece length number");
|
||||||
@@ -318,6 +324,14 @@ public class MetaInfo
|
|||||||
return name;
|
return name;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Is it a private torrent?
|
||||||
|
* @since 0.9
|
||||||
|
*/
|
||||||
|
public boolean isPrivate() {
|
||||||
|
return privateTorrent;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns a list of lists of file name hierarchies or null if it is
|
* Returns a list of lists of file name hierarchies or null if it is
|
||||||
* a single name. It has the same size as the list returned by
|
* a single name. It has the same size as the list returned by
|
||||||
@@ -439,7 +453,7 @@ public class MetaInfo
|
|||||||
{
|
{
|
||||||
return new MetaInfo(announce, name, name_utf8, files,
|
return new MetaInfo(announce, name, name_utf8, files,
|
||||||
lengths, piece_length,
|
lengths, piece_length,
|
||||||
piece_hashes, length);
|
piece_hashes, length, privateTorrent);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -475,6 +489,10 @@ public class MetaInfo
|
|||||||
info.put("name", name);
|
info.put("name", name);
|
||||||
if (name_utf8 != null)
|
if (name_utf8 != null)
|
||||||
info.put("name.utf-8", name_utf8);
|
info.put("name.utf-8", name_utf8);
|
||||||
|
// BEP 27
|
||||||
|
if (privateTorrent)
|
||||||
|
info.put("private", "1");
|
||||||
|
|
||||||
info.put("piece length", Integer.valueOf(piece_length));
|
info.put("piece length", Integer.valueOf(piece_length));
|
||||||
info.put("pieces", piece_hashes);
|
info.put("pieces", piece_hashes);
|
||||||
if (files == null)
|
if (files == null)
|
||||||
|
@@ -268,7 +268,8 @@ public class Peer implements Comparable
|
|||||||
if (_log.shouldLog(Log.DEBUG))
|
if (_log.shouldLog(Log.DEBUG))
|
||||||
_log.debug("Peer supports extensions, sending reply message");
|
_log.debug("Peer supports extensions, sending reply message");
|
||||||
int metasize = metainfo != null ? metainfo.getInfoBytes().length : -1;
|
int metasize = metainfo != null ? metainfo.getInfoBytes().length : -1;
|
||||||
out.sendExtension(0, ExtensionHandler.getHandshake(metasize));
|
boolean pexAndMetadata = metainfo == null || !metainfo.isPrivate();
|
||||||
|
out.sendExtension(0, ExtensionHandler.getHandshake(metasize, pexAndMetadata));
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((options & OPTION_I2P_DHT) != 0 && util.getDHT() != null) {
|
if ((options & OPTION_I2P_DHT) != 0 && util.getDHT() != null) {
|
||||||
|
@@ -1186,6 +1186,8 @@ public class PeerCoordinator implements PeerListener
|
|||||||
* @since 0.8.4
|
* @since 0.8.4
|
||||||
*/
|
*/
|
||||||
void sendPeers(Peer peer) {
|
void sendPeers(Peer peer) {
|
||||||
|
if (metainfo != null && metainfo.isPrivate())
|
||||||
|
return;
|
||||||
Map<String, BEValue> handshake = peer.getHandshakeMap();
|
Map<String, BEValue> handshake = peer.getHandshakeMap();
|
||||||
if (handshake == null)
|
if (handshake == null)
|
||||||
return;
|
return;
|
||||||
|
@@ -489,6 +489,13 @@ class PeerState implements DataLoader
|
|||||||
/** @since 0.8.2 */
|
/** @since 0.8.2 */
|
||||||
void extensionMessage(int id, byte[] bs)
|
void extensionMessage(int id, byte[] bs)
|
||||||
{
|
{
|
||||||
|
if (metainfo != null && metainfo.isPrivate() &&
|
||||||
|
(id == ExtensionHandler.ID_METADATA || id == ExtensionHandler.ID_PEX)) {
|
||||||
|
// shouldn't get this since we didn't advertise it but they could send it anyway
|
||||||
|
if (_log.shouldLog(Log.WARN))
|
||||||
|
_log.warn("Private torrent, ignoring ext msg " + id);
|
||||||
|
return;
|
||||||
|
}
|
||||||
ExtensionHandler.handleMessage(peer, listener, id, bs);
|
ExtensionHandler.handleMessage(peer, listener, id, bs);
|
||||||
// Peer coord will get metadata from MagnetState,
|
// Peer coord will get metadata from MagnetState,
|
||||||
// verify, and then call gotMetaInfo()
|
// verify, and then call gotMetaInfo()
|
||||||
|
@@ -8,6 +8,8 @@ import java.io.FilenameFilter;
|
|||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.OutputStream;
|
import java.io.OutputStream;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.Comparator;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
@@ -35,8 +37,6 @@ import net.i2p.util.SecureFileOutputStream;
|
|||||||
* Manage multiple snarks
|
* Manage multiple snarks
|
||||||
*/
|
*/
|
||||||
public class SnarkManager implements Snark.CompleteListener {
|
public class SnarkManager implements Snark.CompleteListener {
|
||||||
private static SnarkManager _instance = new SnarkManager();
|
|
||||||
public static SnarkManager instance() { return _instance; }
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Map of (canonical) filename of the .torrent file to Snark instance.
|
* Map of (canonical) filename of the .torrent file to Snark instance.
|
||||||
@@ -57,6 +57,7 @@ public class SnarkManager implements Snark.CompleteListener {
|
|||||||
private ConnectionAcceptor _connectionAcceptor;
|
private ConnectionAcceptor _connectionAcceptor;
|
||||||
private Thread _monitor;
|
private Thread _monitor;
|
||||||
private volatile boolean _running;
|
private volatile boolean _running;
|
||||||
|
private final Map<String, String> _trackerMap;
|
||||||
|
|
||||||
public static final String PROP_I2CP_HOST = "i2psnark.i2cpHost";
|
public static final String PROP_I2CP_HOST = "i2psnark.i2cpHost";
|
||||||
public static final String PROP_I2CP_PORT = "i2psnark.i2cpPort";
|
public static final String PROP_I2CP_PORT = "i2psnark.i2cpPort";
|
||||||
@@ -89,6 +90,34 @@ public class SnarkManager implements Snark.CompleteListener {
|
|||||||
public static final int DEFAULT_STARTUP_DELAY = 3;
|
public static final int DEFAULT_STARTUP_DELAY = 3;
|
||||||
public static final int DEFAULT_REFRESH_DELAY_SECS = 60;
|
public static final int DEFAULT_REFRESH_DELAY_SECS = 60;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* "name", "announceURL=websiteURL" pairs
|
||||||
|
* '=' in announceURL must be escaped as ,
|
||||||
|
*/
|
||||||
|
private static final String DEFAULT_TRACKERS[] = {
|
||||||
|
// "Postman", "http://YRgrgTLGnbTq2aZOZDJQ~o6Uk5k6TK-OZtx0St9pb0G-5EGYURZioxqYG8AQt~LgyyI~NCj6aYWpPO-150RcEvsfgXLR~CxkkZcVpgt6pns8SRc3Bi-QSAkXpJtloapRGcQfzTtwllokbdC-aMGpeDOjYLd8b5V9Im8wdCHYy7LRFxhEtGb~RL55DA8aYOgEXcTpr6RPPywbV~Qf3q5UK55el6Kex-6VCxreUnPEe4hmTAbqZNR7Fm0hpCiHKGoToRcygafpFqDw5frLXToYiqs9d4liyVB-BcOb0ihORbo0nS3CLmAwZGvdAP8BZ7cIYE3Z9IU9D1G8JCMxWarfKX1pix~6pIA-sp1gKlL1HhYhPMxwyxvuSqx34o3BqU7vdTYwWiLpGM~zU1~j9rHL7x60pVuYaXcFQDR4-QVy26b6Pt6BlAZoFmHhPcAuWfu-SFhjyZYsqzmEmHeYdAwa~HojSbofg0TMUgESRXMw6YThK1KXWeeJVeztGTz25sL8AAAA.i2p/announce.php=http://tracker.postman.i2p/"
|
||||||
|
// , "eBook", "http://E71FRom6PZNEqTN2Lr8P-sr23b7HJVC32KoGnVQjaX6zJiXwhJy2HsXob36Qmj81TYFZdewFZa9mSJ533UZgGyQkXo2ahctg82JKYZfDe5uDxAn1E9YPjxZCWJaFJh0S~UwSs~9AZ7UcauSJIoNtpxrtbmRNVFLqnkEDdLZi26TeucfOmiFmIWnVblLniWv3tG1boE9Abd-6j3FmYVrRucYuepAILYt6katmVNOk6sXmno1Eynrp~~MBuFq0Ko6~jsc2E2CRVYXDhGHEMdt-j6JUz5D7S2RIVzDRqQyAZLKJ7OdQDmI31przzmne1vOqqqLC~1xUumZVIvF~yOeJUGNjJ1Vx0J8i2BQIusn1pQJ6UCB~ZtZZLQtEb8EPVCfpeRi2ri1M5CyOuxN0V5ekmPHrYIBNevuTCRC26NP7ZS5VDgx1~NaC3A-CzJAE6f1QXi0wMI9aywNG5KGzOPifcsih8eyGyytvgLtrZtV7ykzYpPCS-rDfITncpn5hliPUAAAA.i2p/pub/bt/announce.php=http://de-ebook-archiv.i2p/pub/bt/"
|
||||||
|
// , "Gaytorrents", "http://uxPWHbK1OIj9HxquaXuhMiIvi21iK0~ZiG9d8G0840ZXIg0r6CbiV71xlsqmdnU6wm0T2LySriM0doW2gUigo-5BNkUquHwOjLROiETnB3ZR0Ml4IGa6QBPn1aAq2d9~g1r1nVjLE~pcFnXB~cNNS7kIhX1d6nLgYVZf0C2cZopEow2iWVUggGGnAA9mHjE86zLEnTvAyhbAMTqDQJhEuLa0ZYSORqzJDMkQt90MV4YMjX1ICY6RfUSFmxEqu0yWTrkHsTtRw48l~dz9wpIgc0a0T9C~eeWvmBFTqlJPtQZwntpNeH~jF7nlYzB58olgV2HHFYpVYD87DYNzTnmNWxCJ5AfDorm6AIUCV2qaE7tZtI1h6fbmGpGlPyW~Kw5GXrRfJwNvr6ajwAVi~bPVnrBwDZezHkfW4slOO8FACPR28EQvaTu9nwhAbqESxV2hCTq6vQSGjuxHeOuzBOEvRWkLKOHWTC09t2DbJ94FSqETmZopTB1ukEmaxRWbKSIaAAAA.i2p/announce.php=http://gaytorrents.i2p/"
|
||||||
|
// , "NickyB", "http://9On6d3cZ27JjwYCtyJJbowe054d5tFnfMjv4PHsYs-EQn4Y4mk2zRixatvuAyXz2MmRfXG-NAUfhKr0KCxRNZbvHmlckYfT-WBzwwpiMAl0wDFY~Pl8cqXuhfikSG5WrqdPfDNNIBuuznS0dqaczf~OyVaoEOpvuP3qV6wKqbSSLpjOwwAaQPHjlRtNIW8-EtUZp-I0LT45HSoowp~6b7zYmpIyoATvIP~sT0g0MTrczWhbVTUZnEkZeLhOR0Duw1-IRXI2KHPbA24wLO9LdpKKUXed05RTz0QklW5ROgR6TYv7aXFufX8kC0-DaKvQ5JKG~h8lcoHvm1RCzNqVE-2aiZnO2xH08H-iCWoLNJE-Td2kT-Tsc~3QdQcnEUcL5BF-VT~QYRld2--9r0gfGl-yDrJZrlrihHGr5J7ImahelNn9PpkVp6eIyABRmJHf2iicrk3CtjeG1j9OgTSwaNmEpUpn4aN7Kx0zNLdH7z6uTgCGD9Kmh1MFYrsoNlTp4AAAA.i2p/bittorrent/announce.php=http://nickyb.i2p/bittorrent/"
|
||||||
|
// , "Orion", "http://gKik1lMlRmuroXVGTZ~7v4Vez3L3ZSpddrGZBrxVriosCQf7iHu6CIk8t15BKsj~P0JJpxrofeuxtm7SCUAJEr0AIYSYw8XOmp35UfcRPQWyb1LsxUkMT4WqxAT3s1ClIICWlBu5An~q-Mm0VFlrYLIPBWlUFnfPR7jZ9uP5ZMSzTKSMYUWao3ejiykr~mtEmyls6g-ZbgKZawa9II4zjOy-hdxHgP-eXMDseFsrym4Gpxvy~3Fv9TuiSqhpgm~UeTo5YBfxn6~TahKtE~~sdCiSydqmKBhxAQ7uT9lda7xt96SS09OYMsIWxLeQUWhns-C~FjJPp1D~IuTrUpAFcVEGVL-BRMmdWbfOJEcWPZ~CBCQSO~VkuN1ebvIOr9JBerFMZSxZtFl8JwcrjCIBxeKPBmfh~xYh16BJm1BBBmN1fp2DKmZ2jBNkAmnUbjQOqWvUcehrykWk5lZbE7bjJMDFH48v3SXwRuDBiHZmSbsTY6zhGY~GkMQHNGxPMMSIAAAA.i2p/bt/announce.php=http://orion.i2p/bt/"
|
||||||
|
// , "anonymity", "http://8EoJZIKrWgGuDrxA3nRJs1jsPfiGwmFWL91hBrf0HA7oKhEvAna4Ocx47VLUR9retVEYBAyWFK-eZTPcvhnz9XffBEiJQQ~kFSCqb1fV6IfPiV3HySqi9U5Caf6~hC46fRd~vYnxmaBLICT3N160cxBETqH3v2rdxdJpvYt8q4nMk9LUeVXq7zqCTFLLG5ig1uKgNzBGe58iNcsvTEYlnbYcE930ABmrzj8G1qQSgSwJ6wx3tUQNl1z~4wSOUMan~raZQD60lRK70GISjoX0-D0Po9WmPveN3ES3g72TIET3zc3WPdK2~lgmKGIs8GgNLES1cXTolvbPhdZK1gxddRMbJl6Y6IPFyQ9o4-6Rt3Lp-RMRWZ2TG7j2OMcNSiOmATUhKEFBDfv-~SODDyopGBmfeLw16F4NnYednvn4qP10dyMHcUASU6Zag4mfc2-WivrOqeWhD16fVAh8MoDpIIT~0r9XmwdaVFyLcjbXObabJczxCAW3fodQUnvuSkwzAAAA.i2p/anonymityTracker/announce.php=http://anonymityweb.i2p/anonymityTracker/"
|
||||||
|
// , "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/"
|
||||||
|
// , "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/"
|
||||||
|
,"Welterde", "http://tracker.welterde.i2p/a=http://tracker.welterde.i2p/stats?mode=top5"
|
||||||
|
,"Diftracker", "http://n--XWjHjUPjnMNrSwXA2OYXpMIUL~u4FNXnrt2HtjK3y6j~4SOClyyeKzd0zRPlixxkCe2wfBIYye3bZsaqAD8bd0QMmowxbq91WpjsPfKMiphJbePKXtYAVARiy0cqyvh1d2LyDE-6wkvgaw45hknmS0U-Dg3YTJZbAQRU2SKXgIlAbWCv4R0kDFBLEVpReDiJef3rzAWHiW8yjmJuJilkYjMwlfRjw8xx1nl2s~yhlljk1pl13jGYb0nfawQnuOWeP-ASQWvAAyVgKvZRJE2O43S7iveu9piuv7plXWbt36ef7ndu2GNoNyPOBdpo9KUZ-NOXm4Kgh659YtEibL15dEPAOdxprY0sYUurVw8OIWqrpX7yn08nbi6qHVGqQwTpxH35vkL8qrCbm-ym7oQJQnNmSDrNTyWYRFSq5s5~7DAdFDzqRPW-pX~g0zEivWj5tzkhvG9rVFgFo0bpQX3X0PUAV9Xbyf8u~v8Zbr9K1pCPqBq9XEr4TqaLHw~bfAAAA.i2p/announce.php=http://diftracker.i2p/"
|
||||||
|
// , "CRSTRACK", "http://b4G9sCdtfvccMAXh~SaZrPqVQNyGQbhbYMbw6supq2XGzbjU4NcOmjFI0vxQ8w1L05twmkOvg5QERcX6Mi8NQrWnR0stLExu2LucUXg1aYjnggxIR8TIOGygZVIMV3STKH4UQXD--wz0BUrqaLxPhrm2Eh9Hwc8TdB6Na4ShQUq5Xm8D4elzNUVdpM~RtChEyJWuQvoGAHY3ppX-EJJLkiSr1t77neS4Lc-KofMVmgI9a2tSSpNAagBiNI6Ak9L1T0F9uxeDfEG9bBSQPNMOSUbAoEcNxtt7xOW~cNOAyMyGydwPMnrQ5kIYPY8Pd3XudEko970vE0D6gO19yoBMJpKx6Dh50DGgybLQ9CpRaynh2zPULTHxm8rneOGRcQo8D3mE7FQ92m54~SvfjXjD2TwAVGI~ae~n9HDxt8uxOecAAvjjJ3TD4XM63Q9TmB38RmGNzNLDBQMEmJFpqQU8YeuhnS54IVdUoVQFqui5SfDeLXlSkh4vYoMU66pvBfWbAAAA.i2p/tracker/announce.php=http://crstrack.i2p/tracker/"
|
||||||
|
// ,"Exotrack", "http://blbgywsjubw3d2zih2giokakhe3o2cko7jtte4risb3hohbcoyva.b32.i2p/announce.php=http://exotrack.i2p/"
|
||||||
|
};
|
||||||
|
|
||||||
|
/** comma delimited list of name=announceURL=baseURL for the trackers to be displayed */
|
||||||
|
public static final String PROP_TRACKERS = "i2psnark.trackers";
|
||||||
|
|
||||||
|
private static final SnarkManager _instance = new SnarkManager();
|
||||||
|
|
||||||
|
public static SnarkManager instance() { return _instance; }
|
||||||
|
|
||||||
private SnarkManager() {
|
private SnarkManager() {
|
||||||
_snarks = new ConcurrentHashMap();
|
_snarks = new ConcurrentHashMap();
|
||||||
_magnets = new ConcurrentHashSet();
|
_magnets = new ConcurrentHashSet();
|
||||||
@@ -100,6 +129,7 @@ public class SnarkManager implements Snark.CompleteListener {
|
|||||||
_configFile = new File(CONFIG_FILE);
|
_configFile = new File(CONFIG_FILE);
|
||||||
if (!_configFile.isAbsolute())
|
if (!_configFile.isAbsolute())
|
||||||
_configFile = new File(_context.getConfigDir(), CONFIG_FILE);
|
_configFile = new File(_context.getConfigDir(), CONFIG_FILE);
|
||||||
|
_trackerMap = Collections.synchronizedMap(new TreeMap(new IgnoreCaseComparator()));
|
||||||
loadConfig(null);
|
loadConfig(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -312,6 +342,7 @@ public class SnarkManager implements Snark.CompleteListener {
|
|||||||
boolean bOT = useOT == null || Boolean.valueOf(useOT).booleanValue();
|
boolean bOT = useOT == null || Boolean.valueOf(useOT).booleanValue();
|
||||||
_util.setUseOpenTrackers(bOT);
|
_util.setUseOpenTrackers(bOT);
|
||||||
getDataDir().mkdirs();
|
getDataDir().mkdirs();
|
||||||
|
initTrackerMap();
|
||||||
}
|
}
|
||||||
|
|
||||||
private int getInt(String prop, int defaultVal) {
|
private int getInt(String prop, int defaultVal) {
|
||||||
@@ -663,7 +694,9 @@ public class SnarkManager implements Snark.CompleteListener {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!TrackerClient.isValidAnnounce(info.getAnnounce())) {
|
if (!TrackerClient.isValidAnnounce(info.getAnnounce())) {
|
||||||
if (_util.shouldUseOpenTrackers() && _util.getOpenTrackers() != null) {
|
if (info.isPrivate()) {
|
||||||
|
addMessage(_("ERROR - No I2P trackers in private torrent \"{0}\"", info.getName()));
|
||||||
|
} else if (_util.shouldUseOpenTrackers() && _util.getOpenTrackers() != null) {
|
||||||
//addMessage(_("Warning - No I2P trackers in \"{0}\", will announce to I2P open trackers and DHT only.", info.getName()));
|
//addMessage(_("Warning - No I2P trackers in \"{0}\", will announce to I2P open trackers and DHT only.", info.getName()));
|
||||||
addMessage(_("Warning - No I2P trackers in \"{0}\", will announce to I2P open trackers only.", info.getName()));
|
addMessage(_("Warning - No I2P trackers in \"{0}\", will announce to I2P open trackers only.", info.getName()));
|
||||||
//} else if (_util.getDHT() != null) {
|
//} else if (_util.getDHT() != null) {
|
||||||
@@ -1356,57 +1389,59 @@ public class SnarkManager implements Snark.CompleteListener {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* "name", "announceURL=websiteURL" pairs
|
* Sorted map of name to announceURL=baseURL
|
||||||
|
* Modifiable, not a copy
|
||||||
*/
|
*/
|
||||||
private static final String DEFAULT_TRACKERS[] = {
|
|
||||||
// "Postman", "http://YRgrgTLGnbTq2aZOZDJQ~o6Uk5k6TK-OZtx0St9pb0G-5EGYURZioxqYG8AQt~LgyyI~NCj6aYWpPO-150RcEvsfgXLR~CxkkZcVpgt6pns8SRc3Bi-QSAkXpJtloapRGcQfzTtwllokbdC-aMGpeDOjYLd8b5V9Im8wdCHYy7LRFxhEtGb~RL55DA8aYOgEXcTpr6RPPywbV~Qf3q5UK55el6Kex-6VCxreUnPEe4hmTAbqZNR7Fm0hpCiHKGoToRcygafpFqDw5frLXToYiqs9d4liyVB-BcOb0ihORbo0nS3CLmAwZGvdAP8BZ7cIYE3Z9IU9D1G8JCMxWarfKX1pix~6pIA-sp1gKlL1HhYhPMxwyxvuSqx34o3BqU7vdTYwWiLpGM~zU1~j9rHL7x60pVuYaXcFQDR4-QVy26b6Pt6BlAZoFmHhPcAuWfu-SFhjyZYsqzmEmHeYdAwa~HojSbofg0TMUgESRXMw6YThK1KXWeeJVeztGTz25sL8AAAA.i2p/announce.php=http://tracker.postman.i2p/"
|
|
||||||
// , "eBook", "http://E71FRom6PZNEqTN2Lr8P-sr23b7HJVC32KoGnVQjaX6zJiXwhJy2HsXob36Qmj81TYFZdewFZa9mSJ533UZgGyQkXo2ahctg82JKYZfDe5uDxAn1E9YPjxZCWJaFJh0S~UwSs~9AZ7UcauSJIoNtpxrtbmRNVFLqnkEDdLZi26TeucfOmiFmIWnVblLniWv3tG1boE9Abd-6j3FmYVrRucYuepAILYt6katmVNOk6sXmno1Eynrp~~MBuFq0Ko6~jsc2E2CRVYXDhGHEMdt-j6JUz5D7S2RIVzDRqQyAZLKJ7OdQDmI31przzmne1vOqqqLC~1xUumZVIvF~yOeJUGNjJ1Vx0J8i2BQIusn1pQJ6UCB~ZtZZLQtEb8EPVCfpeRi2ri1M5CyOuxN0V5ekmPHrYIBNevuTCRC26NP7ZS5VDgx1~NaC3A-CzJAE6f1QXi0wMI9aywNG5KGzOPifcsih8eyGyytvgLtrZtV7ykzYpPCS-rDfITncpn5hliPUAAAA.i2p/pub/bt/announce.php=http://de-ebook-archiv.i2p/pub/bt/"
|
|
||||||
// , "Gaytorrents", "http://uxPWHbK1OIj9HxquaXuhMiIvi21iK0~ZiG9d8G0840ZXIg0r6CbiV71xlsqmdnU6wm0T2LySriM0doW2gUigo-5BNkUquHwOjLROiETnB3ZR0Ml4IGa6QBPn1aAq2d9~g1r1nVjLE~pcFnXB~cNNS7kIhX1d6nLgYVZf0C2cZopEow2iWVUggGGnAA9mHjE86zLEnTvAyhbAMTqDQJhEuLa0ZYSORqzJDMkQt90MV4YMjX1ICY6RfUSFmxEqu0yWTrkHsTtRw48l~dz9wpIgc0a0T9C~eeWvmBFTqlJPtQZwntpNeH~jF7nlYzB58olgV2HHFYpVYD87DYNzTnmNWxCJ5AfDorm6AIUCV2qaE7tZtI1h6fbmGpGlPyW~Kw5GXrRfJwNvr6ajwAVi~bPVnrBwDZezHkfW4slOO8FACPR28EQvaTu9nwhAbqESxV2hCTq6vQSGjuxHeOuzBOEvRWkLKOHWTC09t2DbJ94FSqETmZopTB1ukEmaxRWbKSIaAAAA.i2p/announce.php=http://gaytorrents.i2p/"
|
|
||||||
// , "NickyB", "http://9On6d3cZ27JjwYCtyJJbowe054d5tFnfMjv4PHsYs-EQn4Y4mk2zRixatvuAyXz2MmRfXG-NAUfhKr0KCxRNZbvHmlckYfT-WBzwwpiMAl0wDFY~Pl8cqXuhfikSG5WrqdPfDNNIBuuznS0dqaczf~OyVaoEOpvuP3qV6wKqbSSLpjOwwAaQPHjlRtNIW8-EtUZp-I0LT45HSoowp~6b7zYmpIyoATvIP~sT0g0MTrczWhbVTUZnEkZeLhOR0Duw1-IRXI2KHPbA24wLO9LdpKKUXed05RTz0QklW5ROgR6TYv7aXFufX8kC0-DaKvQ5JKG~h8lcoHvm1RCzNqVE-2aiZnO2xH08H-iCWoLNJE-Td2kT-Tsc~3QdQcnEUcL5BF-VT~QYRld2--9r0gfGl-yDrJZrlrihHGr5J7ImahelNn9PpkVp6eIyABRmJHf2iicrk3CtjeG1j9OgTSwaNmEpUpn4aN7Kx0zNLdH7z6uTgCGD9Kmh1MFYrsoNlTp4AAAA.i2p/bittorrent/announce.php=http://nickyb.i2p/bittorrent/"
|
|
||||||
// , "Orion", "http://gKik1lMlRmuroXVGTZ~7v4Vez3L3ZSpddrGZBrxVriosCQf7iHu6CIk8t15BKsj~P0JJpxrofeuxtm7SCUAJEr0AIYSYw8XOmp35UfcRPQWyb1LsxUkMT4WqxAT3s1ClIICWlBu5An~q-Mm0VFlrYLIPBWlUFnfPR7jZ9uP5ZMSzTKSMYUWao3ejiykr~mtEmyls6g-ZbgKZawa9II4zjOy-hdxHgP-eXMDseFsrym4Gpxvy~3Fv9TuiSqhpgm~UeTo5YBfxn6~TahKtE~~sdCiSydqmKBhxAQ7uT9lda7xt96SS09OYMsIWxLeQUWhns-C~FjJPp1D~IuTrUpAFcVEGVL-BRMmdWbfOJEcWPZ~CBCQSO~VkuN1ebvIOr9JBerFMZSxZtFl8JwcrjCIBxeKPBmfh~xYh16BJm1BBBmN1fp2DKmZ2jBNkAmnUbjQOqWvUcehrykWk5lZbE7bjJMDFH48v3SXwRuDBiHZmSbsTY6zhGY~GkMQHNGxPMMSIAAAA.i2p/bt/announce.php=http://orion.i2p/bt/"
|
|
||||||
// , "anonymity", "http://8EoJZIKrWgGuDrxA3nRJs1jsPfiGwmFWL91hBrf0HA7oKhEvAna4Ocx47VLUR9retVEYBAyWFK-eZTPcvhnz9XffBEiJQQ~kFSCqb1fV6IfPiV3HySqi9U5Caf6~hC46fRd~vYnxmaBLICT3N160cxBETqH3v2rdxdJpvYt8q4nMk9LUeVXq7zqCTFLLG5ig1uKgNzBGe58iNcsvTEYlnbYcE930ABmrzj8G1qQSgSwJ6wx3tUQNl1z~4wSOUMan~raZQD60lRK70GISjoX0-D0Po9WmPveN3ES3g72TIET3zc3WPdK2~lgmKGIs8GgNLES1cXTolvbPhdZK1gxddRMbJl6Y6IPFyQ9o4-6Rt3Lp-RMRWZ2TG7j2OMcNSiOmATUhKEFBDfv-~SODDyopGBmfeLw16F4NnYednvn4qP10dyMHcUASU6Zag4mfc2-WivrOqeWhD16fVAh8MoDpIIT~0r9XmwdaVFyLcjbXObabJczxCAW3fodQUnvuSkwzAAAA.i2p/anonymityTracker/announce.php=http://anonymityweb.i2p/anonymityTracker/"
|
|
||||||
// , "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/"
|
|
||||||
// , "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/"
|
|
||||||
,"Welterde", "http://tracker.welterde.i2p/a=http://tracker.welterde.i2p/stats?mode=top5"
|
|
||||||
,"Diftracker", "http://n--XWjHjUPjnMNrSwXA2OYXpMIUL~u4FNXnrt2HtjK3y6j~4SOClyyeKzd0zRPlixxkCe2wfBIYye3bZsaqAD8bd0QMmowxbq91WpjsPfKMiphJbePKXtYAVARiy0cqyvh1d2LyDE-6wkvgaw45hknmS0U-Dg3YTJZbAQRU2SKXgIlAbWCv4R0kDFBLEVpReDiJef3rzAWHiW8yjmJuJilkYjMwlfRjw8xx1nl2s~yhlljk1pl13jGYb0nfawQnuOWeP-ASQWvAAyVgKvZRJE2O43S7iveu9piuv7plXWbt36ef7ndu2GNoNyPOBdpo9KUZ-NOXm4Kgh659YtEibL15dEPAOdxprY0sYUurVw8OIWqrpX7yn08nbi6qHVGqQwTpxH35vkL8qrCbm-ym7oQJQnNmSDrNTyWYRFSq5s5~7DAdFDzqRPW-pX~g0zEivWj5tzkhvG9rVFgFo0bpQX3X0PUAV9Xbyf8u~v8Zbr9K1pCPqBq9XEr4TqaLHw~bfAAAA.i2p/announce.php=http://diftracker.i2p/"
|
|
||||||
// , "CRSTRACK", "http://b4G9sCdtfvccMAXh~SaZrPqVQNyGQbhbYMbw6supq2XGzbjU4NcOmjFI0vxQ8w1L05twmkOvg5QERcX6Mi8NQrWnR0stLExu2LucUXg1aYjnggxIR8TIOGygZVIMV3STKH4UQXD--wz0BUrqaLxPhrm2Eh9Hwc8TdB6Na4ShQUq5Xm8D4elzNUVdpM~RtChEyJWuQvoGAHY3ppX-EJJLkiSr1t77neS4Lc-KofMVmgI9a2tSSpNAagBiNI6Ak9L1T0F9uxeDfEG9bBSQPNMOSUbAoEcNxtt7xOW~cNOAyMyGydwPMnrQ5kIYPY8Pd3XudEko970vE0D6gO19yoBMJpKx6Dh50DGgybLQ9CpRaynh2zPULTHxm8rneOGRcQo8D3mE7FQ92m54~SvfjXjD2TwAVGI~ae~n9HDxt8uxOecAAvjjJ3TD4XM63Q9TmB38RmGNzNLDBQMEmJFpqQU8YeuhnS54IVdUoVQFqui5SfDeLXlSkh4vYoMU66pvBfWbAAAA.i2p/tracker/announce.php=http://crstrack.i2p/tracker/"
|
|
||||||
// ,"Exotrack", "http://blbgywsjubw3d2zih2giokakhe3o2cko7jtte4risb3hohbcoyva.b32.i2p/announce.php=http://exotrack.i2p/"
|
|
||||||
};
|
|
||||||
|
|
||||||
/** comma delimited list of name=announceURL=baseURL for the trackers to be displayed */
|
|
||||||
public static final String PROP_TRACKERS = "i2psnark.trackers";
|
|
||||||
private static Map<String, String> trackerMap = null;
|
|
||||||
/** sorted map of name to announceURL=baseURL */
|
|
||||||
public Map<String, String> getTrackers() {
|
public Map<String, String> getTrackers() {
|
||||||
if (trackerMap != null) // only do this once, can't be updated while running
|
return _trackerMap;
|
||||||
return trackerMap;
|
}
|
||||||
Map<String, String> rv = new TreeMap();
|
|
||||||
|
/** @since 0.9 */
|
||||||
|
private void initTrackerMap() {
|
||||||
String trackers = _config.getProperty(PROP_TRACKERS);
|
String trackers = _config.getProperty(PROP_TRACKERS);
|
||||||
if ( (trackers == null) || (trackers.trim().length() <= 0) )
|
if ( (trackers == null) || (trackers.trim().length() <= 0) )
|
||||||
trackers = _context.getProperty(PROP_TRACKERS);
|
trackers = _context.getProperty(PROP_TRACKERS);
|
||||||
|
_trackerMap.clear();
|
||||||
if ( (trackers == null) || (trackers.trim().length() <= 0) ) {
|
if ( (trackers == null) || (trackers.trim().length() <= 0) ) {
|
||||||
for (int i = 0; i < DEFAULT_TRACKERS.length; i += 2)
|
for (int i = 0; i < DEFAULT_TRACKERS.length; i += 2)
|
||||||
rv.put(DEFAULT_TRACKERS[i], DEFAULT_TRACKERS[i+1]);
|
_trackerMap.put(DEFAULT_TRACKERS[i], DEFAULT_TRACKERS[i+1]);
|
||||||
} else {
|
} else {
|
||||||
StringTokenizer tok = new StringTokenizer(trackers, ",");
|
String[] toks = trackers.split(",");
|
||||||
while (tok.hasMoreTokens()) {
|
for (int i = 0; i < toks.length; i += 2) {
|
||||||
String pair = tok.nextToken();
|
String name = toks[i].trim().replace(",", ",");
|
||||||
int split = pair.indexOf('=');
|
String url = toks[i+1].trim().replace(",", ",");
|
||||||
if (split <= 0)
|
|
||||||
continue;
|
|
||||||
String name = pair.substring(0, split).trim();
|
|
||||||
String url = pair.substring(split+1).trim();
|
|
||||||
if ( (name.length() > 0) && (url.length() > 0) )
|
if ( (name.length() > 0) && (url.length() > 0) )
|
||||||
rv.put(name, url);
|
_trackerMap.put(name, url);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
trackerMap = rv;
|
|
||||||
return trackerMap;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** @since 0.9 */
|
||||||
|
public void setDefaultTrackerMap() {
|
||||||
|
_trackerMap.clear();
|
||||||
|
for (int i = 0; i < DEFAULT_TRACKERS.length; i += 2) {
|
||||||
|
_trackerMap.put(DEFAULT_TRACKERS[i], DEFAULT_TRACKERS[i+1]);
|
||||||
|
}
|
||||||
|
if (_config.remove(PROP_TRACKERS) != null) {
|
||||||
|
saveConfig();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @since 0.9 */
|
||||||
|
public void saveTrackerMap() {
|
||||||
|
StringBuilder buf = new StringBuilder(2048);
|
||||||
|
boolean comma = false;
|
||||||
|
for (Map.Entry<String, String> e : _trackerMap.entrySet()) {
|
||||||
|
if (comma)
|
||||||
|
buf.append(',');
|
||||||
|
else
|
||||||
|
comma = true;
|
||||||
|
buf.append(e.getKey().replace(",", ",")).append(',').append(e.getValue().replace(",", ","));
|
||||||
|
}
|
||||||
|
_config.setProperty(PROP_TRACKERS, buf.toString());
|
||||||
|
saveConfig();
|
||||||
|
}
|
||||||
|
|
||||||
private static class TorrentFilenameFilter implements FilenameFilter {
|
private static class TorrentFilenameFilter implements FilenameFilter {
|
||||||
private static final TorrentFilenameFilter _filter = new TorrentFilenameFilter();
|
private static final TorrentFilenameFilter _filter = new TorrentFilenameFilter();
|
||||||
public static TorrentFilenameFilter instance() { return _filter; }
|
public static TorrentFilenameFilter instance() { return _filter; }
|
||||||
@@ -1426,4 +1461,14 @@ public class SnarkManager implements Snark.CompleteListener {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ignore case, current locale
|
||||||
|
* @since 0.9
|
||||||
|
*/
|
||||||
|
private static class IgnoreCaseComparator implements Comparator<String> {
|
||||||
|
public int compare(String l, String r) {
|
||||||
|
return l.toLowerCase().compareTo(r.toLowerCase());
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@@ -101,7 +101,8 @@ public class Storage
|
|||||||
* @param announce may be null
|
* @param announce may be null
|
||||||
* @param listener may be null
|
* @param listener may be null
|
||||||
*/
|
*/
|
||||||
public Storage(I2PSnarkUtil util, File baseFile, String announce, StorageListener listener)
|
public Storage(I2PSnarkUtil util, File baseFile, String announce,
|
||||||
|
boolean privateTorrent, StorageListener listener)
|
||||||
throws IOException
|
throws IOException
|
||||||
{
|
{
|
||||||
_util = util;
|
_util = util;
|
||||||
@@ -157,7 +158,7 @@ public class Storage
|
|||||||
|
|
||||||
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);
|
lengthsList, piece_size, piece_hashes, total, privateTorrent);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -156,7 +156,7 @@ public class TrackerClient extends I2PAppThread
|
|||||||
primary = "";
|
primary = "";
|
||||||
}
|
}
|
||||||
List tlist = _util.getOpenTrackers();
|
List tlist = _util.getOpenTrackers();
|
||||||
if (tlist != null) {
|
if (tlist != null && !meta.isPrivate()) {
|
||||||
for (int i = 0; i < tlist.size(); i++) {
|
for (int i = 0; i < tlist.size(); i++) {
|
||||||
String url = (String)tlist.get(i);
|
String url = (String)tlist.get(i);
|
||||||
if (!isValidAnnounce(url)) {
|
if (!isValidAnnounce(url)) {
|
||||||
@@ -348,7 +348,7 @@ public class TrackerClient extends I2PAppThread
|
|||||||
} // *** end of trackers loop here
|
} // *** end of trackers loop here
|
||||||
|
|
||||||
// Get peers from PEX
|
// Get peers from PEX
|
||||||
if (left > 0 && coordinator.needPeers() && !stop) {
|
if (left > 0 && coordinator.needPeers() && (!meta.isPrivate()) && !stop) {
|
||||||
Set<PeerID> pids = coordinator.getPEXPeers();
|
Set<PeerID> pids = coordinator.getPEXPeers();
|
||||||
if (!pids.isEmpty()) {
|
if (!pids.isEmpty()) {
|
||||||
_util.debug("Got " + pids.size() + " from PEX", Snark.INFO);
|
_util.debug("Got " + pids.size() + " from PEX", Snark.INFO);
|
||||||
@@ -370,7 +370,7 @@ public class TrackerClient extends I2PAppThread
|
|||||||
|
|
||||||
// Get peers from DHT
|
// Get peers from DHT
|
||||||
// FIXME this needs to be in its own thread
|
// FIXME this needs to be in its own thread
|
||||||
if (_util.getDHT() != null && !stop) {
|
if (_util.getDHT() != null && (!meta.isPrivate()) && !stop) {
|
||||||
int numwant;
|
int numwant;
|
||||||
if (left == 0 || event.equals(STOPPED_EVENT) || !coordinator.needPeers())
|
if (left == 0 || event.equals(STOPPED_EVENT) || !coordinator.needPeers())
|
||||||
numwant = 1;
|
numwant = 1;
|
||||||
@@ -444,22 +444,33 @@ public class TrackerClient extends I2PAppThread
|
|||||||
long downloaded, long left, String event)
|
long downloaded, long left, String event)
|
||||||
throws IOException
|
throws IOException
|
||||||
{
|
{
|
||||||
// What do we send for left in magnet mode? Can we omit it?
|
StringBuilder buf = new StringBuilder(512);
|
||||||
long tleft = left >= 0 ? left : 1;
|
buf.append(tr.announce);
|
||||||
String s = tr.announce
|
if (tr.announce.contains("?"))
|
||||||
+ "?info_hash=" + infoHash
|
buf.append('&');
|
||||||
+ "&peer_id=" + peerID
|
|
||||||
+ "&port=" + port
|
|
||||||
+ "&ip=" + _util.getOurIPString() + ".i2p"
|
|
||||||
+ "&uploaded=" + uploaded
|
|
||||||
+ "&downloaded=" + downloaded
|
|
||||||
+ "&left=" + tleft
|
|
||||||
+ "&compact=1" // NOTE: opentracker will return 400 for &compact alone
|
|
||||||
+ ((! event.equals(NO_EVENT)) ? ("&event=" + event) : "");
|
|
||||||
if (left == 0 || event.equals(STOPPED_EVENT) || !coordinator.needPeers())
|
|
||||||
s += "&numwant=0";
|
|
||||||
else
|
else
|
||||||
s += "&numwant=" + _util.getMaxConnections();
|
buf.append('?');
|
||||||
|
buf.append("info_hash=").append(infoHash)
|
||||||
|
.append("&peer_id=").append(peerID)
|
||||||
|
.append("&port=").append(port)
|
||||||
|
.append("&ip=" ).append(_util.getOurIPString()).append(".i2p")
|
||||||
|
.append("&uploaded=").append(uploaded)
|
||||||
|
.append("&downloaded=").append(downloaded)
|
||||||
|
.append("&left=");
|
||||||
|
// What do we send for left in magnet mode? Can we omit it?
|
||||||
|
if (left >= 0)
|
||||||
|
buf.append(left);
|
||||||
|
else
|
||||||
|
buf.append('1');
|
||||||
|
buf.append("&compact=1"); // NOTE: opentracker will return 400 for &compact alone
|
||||||
|
if (! event.equals(NO_EVENT))
|
||||||
|
buf.append("&event=").append(event);
|
||||||
|
buf.append("&numwant=");
|
||||||
|
if (left == 0 || event.equals(STOPPED_EVENT) || !coordinator.needPeers())
|
||||||
|
buf.append('0');
|
||||||
|
else
|
||||||
|
buf.append(_util.getMaxConnections());
|
||||||
|
String s = buf.toString();
|
||||||
_util.debug("Sending TrackerClient request: " + s, Snark.INFO);
|
_util.debug("Sending TrackerClient request: " + s, Snark.INFO);
|
||||||
|
|
||||||
tr.lastRequestTime = System.currentTimeMillis();
|
tr.lastRequestTime = System.currentTimeMillis();
|
||||||
|
@@ -102,7 +102,8 @@ public class I2PSnarkServlet extends Default {
|
|||||||
protected Resource getResource(String pathInContext) throws IOException
|
protected Resource getResource(String pathInContext) throws IOException
|
||||||
{
|
{
|
||||||
if (pathInContext == null || pathInContext.equals("/") || pathInContext.equals("/index.jsp") ||
|
if (pathInContext == null || pathInContext.equals("/") || pathInContext.equals("/index.jsp") ||
|
||||||
pathInContext.equals("/index.html") || pathInContext.startsWith("/_icons/"))
|
pathInContext.equals("/index.html") || pathInContext.startsWith("/.icons/") ||
|
||||||
|
pathInContext.startsWith("/.js/") || pathInContext.startsWith("/.ajax/"))
|
||||||
return super.getResource(pathInContext);
|
return super.getResource(pathInContext);
|
||||||
// files in the i2psnark/ directory
|
// files in the i2psnark/ directory
|
||||||
return _resourceBase.addPath(pathInContext);
|
return _resourceBase.addPath(pathInContext);
|
||||||
@@ -151,6 +152,19 @@ public class I2PSnarkServlet extends Default {
|
|||||||
_imgPath = _themePath + "images/";
|
_imgPath = _themePath + "images/";
|
||||||
// this is the part after /i2psnark
|
// this is the part after /i2psnark
|
||||||
String path = req.getServletPath();
|
String path = req.getServletPath();
|
||||||
|
|
||||||
|
// AJAX for mainsection
|
||||||
|
if ("/.ajax/xhr1.html".equals(path)) {
|
||||||
|
resp.setCharacterEncoding("UTF-8");
|
||||||
|
resp.setContentType("text/html; charset=UTF-8");
|
||||||
|
PrintWriter out = resp.getWriter();
|
||||||
|
//if (_log.shouldLog(Log.DEBUG))
|
||||||
|
// _manager.addMessage((_context.clock().now() / 1000) + " xhr1 p=" + req.getParameter("p"));
|
||||||
|
writeMessages(out);
|
||||||
|
writeTorrents(out, req);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
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") || path.equals("/_post") || isConfigure)) {
|
if (!(path == null || path.equals("/") || path.equals("/index.jsp") || path.equals("/index.html") || path.equals("/_post") || isConfigure)) {
|
||||||
@@ -192,7 +206,8 @@ public class I2PSnarkServlet extends Default {
|
|||||||
|
|
||||||
String peerParam = req.getParameter("p");
|
String peerParam = req.getParameter("p");
|
||||||
String peerString;
|
String peerString;
|
||||||
if (peerParam == null || !_manager.util().connected()) {
|
if (peerParam == null || (!_manager.util().connected()) ||
|
||||||
|
peerParam.replaceAll("[a-zA-Z0-9~=-]", "").length() > 0) { // XSS
|
||||||
peerString = "";
|
peerString = "";
|
||||||
} else {
|
} else {
|
||||||
peerString = "?p=" + peerParam;
|
peerString = "?p=" + peerParam;
|
||||||
@@ -208,13 +223,23 @@ public class I2PSnarkServlet extends Default {
|
|||||||
out.write("</title>\n");
|
out.write("</title>\n");
|
||||||
|
|
||||||
// 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
|
||||||
|
int delay = 0;
|
||||||
if (!isConfigure) {
|
if (!isConfigure) {
|
||||||
int delay = _manager.getRefreshDelaySeconds();
|
delay = _manager.getRefreshDelaySeconds();
|
||||||
if (delay > 0)
|
if (delay > 0) {
|
||||||
out.write("<meta http-equiv=\"refresh\" content=\"" + delay + ";/i2psnark/" + peerString + "\">\n");
|
//out.write("<meta http-equiv=\"refresh\" content=\"" + delay + ";/i2psnark/" + peerString + "\">\n");
|
||||||
|
out.write("<script src=\"/js/ajax.js\" type=\"text/javascript\"></script>\n" +
|
||||||
|
"<script type=\"text/javascript\">\n" +
|
||||||
|
"function requestAjax1() { ajax(\"/i2psnark/.ajax/xhr1.html" + peerString + "\", \"mainsection\", " + (delay*1000) + "); }\n" +
|
||||||
|
"function initAjax(delayMs) { setTimeout(requestAjax1, " + (delay*1000) +"); }\n" +
|
||||||
|
"</script>\n");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
out.write(HEADER_A + _themePath + HEADER_B);
|
out.write(HEADER_A + _themePath + HEADER_B + "</head>\n");
|
||||||
out.write("</head><body>");
|
if (isConfigure || delay <= 0)
|
||||||
|
out.write("<body>");
|
||||||
|
else
|
||||||
|
out.write("<body onload=\"initAjax()\">");
|
||||||
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=\"");
|
||||||
@@ -249,25 +274,36 @@ public class I2PSnarkServlet extends Default {
|
|||||||
String newURL = req.getParameter("newURL");
|
String newURL = req.getParameter("newURL");
|
||||||
if (newURL != null && newURL.trim().length() > 0 && req.getMethod().equals("GET"))
|
if (newURL != null && newURL.trim().length() > 0 && req.getMethod().equals("GET"))
|
||||||
_manager.addMessage(_("Click \"Add torrent\" button to fetch torrent"));
|
_manager.addMessage(_("Click \"Add torrent\" button to fetch torrent"));
|
||||||
out.write("<div class=\"page\"><div class=\"mainsection\"><div class=\"snarkMessages\"><table><tr><td align=\"left\"><pre>");
|
out.write("<div class=\"page\"><div id=\"mainsection\" class=\"mainsection\">");
|
||||||
|
|
||||||
|
writeMessages(out);
|
||||||
|
|
||||||
|
if (isConfigure) {
|
||||||
|
// end of mainsection div
|
||||||
|
out.write("<div class=\"logshim\"></div></div>\n");
|
||||||
|
writeConfigForm(out, req);
|
||||||
|
writeTrackerForm(out, req);
|
||||||
|
} else {
|
||||||
|
writeTorrents(out, req);
|
||||||
|
// end of mainsection div
|
||||||
|
out.write("</div><div id=\"lowersection\">\n");
|
||||||
|
writeAddForm(out, req);
|
||||||
|
writeSeedForm(out, req);
|
||||||
|
writeConfigLink(out);
|
||||||
|
// end of lowersection div
|
||||||
|
out.write("</div>\n");
|
||||||
|
}
|
||||||
|
out.write(FOOTER);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void writeMessages(PrintWriter out) throws IOException {
|
||||||
|
out.write("<div class=\"snarkMessages\"><table><tr><td align=\"left\"><pre>");
|
||||||
List msgs = _manager.getMessages();
|
List msgs = _manager.getMessages();
|
||||||
for (int i = msgs.size()-1; i >= 0; i--) {
|
for (int i = msgs.size()-1; i >= 0; i--) {
|
||||||
String msg = (String)msgs.get(i);
|
String msg = (String)msgs.get(i);
|
||||||
out.write(msg + "\n");
|
out.write(msg + "\n");
|
||||||
}
|
}
|
||||||
out.write("</pre></td></tr></table></div>");
|
out.write("</pre></td></tr></table></div>");
|
||||||
|
|
||||||
if (isConfigure) {
|
|
||||||
out.write("<div class=\"logshim\"></div></div>\n");
|
|
||||||
writeConfigForm(out, req);
|
|
||||||
} else {
|
|
||||||
writeTorrents(out, req);
|
|
||||||
out.write("</div>\n");
|
|
||||||
writeAddForm(out, req);
|
|
||||||
writeSeedForm(out, req);
|
|
||||||
writeConfigLink(out);
|
|
||||||
}
|
|
||||||
out.write(FOOTER);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void writeTorrents(PrintWriter out, HttpServletRequest req) throws IOException {
|
private void writeTorrents(PrintWriter out, HttpServletRequest req) throws IOException {
|
||||||
@@ -276,7 +312,6 @@ public class I2PSnarkServlet extends Default {
|
|||||||
String peerParam = req.getParameter("p");
|
String peerParam = req.getParameter("p");
|
||||||
|
|
||||||
List snarks = getSortedSnarks(req);
|
List snarks = getSortedSnarks(req);
|
||||||
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=\"_post\" method=\"POST\">\n");
|
out.write("<form action=\"_post\" method=\"POST\">\n");
|
||||||
@@ -390,6 +425,7 @@ public class I2PSnarkServlet extends Default {
|
|||||||
out.write(" ");
|
out.write(" ");
|
||||||
}
|
}
|
||||||
out.write("</th></tr></thead>\n");
|
out.write("</th></tr></thead>\n");
|
||||||
|
String uri = "/i2psnark/";
|
||||||
for (int i = 0; i < snarks.size(); i++) {
|
for (int i = 0; i < snarks.size(); i++) {
|
||||||
Snark snark = (Snark)snarks.get(i);
|
Snark snark = (Snark)snarks.get(i);
|
||||||
boolean showDebug = "2".equals(peerParam);
|
boolean showDebug = "2".equals(peerParam);
|
||||||
@@ -650,14 +686,19 @@ public class I2PSnarkServlet extends Default {
|
|||||||
_manager.updateConfig(dataDir, filesPublic, autoStart, refreshDel, startupDel,
|
_manager.updateConfig(dataDir, filesPublic, autoStart, refreshDel, startupDel,
|
||||||
seedPct, eepHost, eepPort, i2cpHost, i2cpPort, i2cpOpts,
|
seedPct, eepHost, eepPort, i2cpHost, i2cpPort, i2cpOpts,
|
||||||
upLimit, upBW, useOpenTrackers, openTrackers, theme);
|
upLimit, upBW, useOpenTrackers, openTrackers, theme);
|
||||||
|
} else if ("Save2".equals(action)) {
|
||||||
|
String taction = req.getParameter("taction");
|
||||||
|
if (taction != null)
|
||||||
|
processTrackerForm(taction, req);
|
||||||
} else if ("Create".equals(action)) {
|
} else if ("Create".equals(action)) {
|
||||||
String baseData = req.getParameter("baseFile");
|
String baseData = req.getParameter("baseFile");
|
||||||
if (baseData != null && baseData.trim().length() > 0) {
|
if (baseData != null && baseData.trim().length() > 0) {
|
||||||
File baseFile = new File(_manager.getDataDir(), baseData);
|
File baseFile = new File(_manager.getDataDir(), baseData);
|
||||||
String announceURL = req.getParameter("announceURL");
|
String announceURL = req.getParameter("announceURL");
|
||||||
String announceURLOther = req.getParameter("announceURLOther");
|
// make the user add a tracker on the config form now
|
||||||
if ( (announceURLOther != null) && (announceURLOther.trim().length() > "http://.i2p/announce".length()) )
|
//String announceURLOther = req.getParameter("announceURLOther");
|
||||||
announceURL = announceURLOther;
|
//if ( (announceURLOther != null) && (announceURLOther.trim().length() > "http://.i2p/announce".length()) )
|
||||||
|
// announceURL = announceURLOther;
|
||||||
|
|
||||||
if (announceURL == null || announceURL.length() <= 0)
|
if (announceURL == null || announceURL.length() <= 0)
|
||||||
_manager.addMessage(_("Error creating torrent - you must select a tracker"));
|
_manager.addMessage(_("Error creating torrent - you must select a tracker"));
|
||||||
@@ -668,7 +709,7 @@ public class I2PSnarkServlet extends Default {
|
|||||||
try {
|
try {
|
||||||
// This may take a long time to check the storage, but since it already exists,
|
// This may take a long time to check the storage, but since it already exists,
|
||||||
// it shouldn't be THAT bad, so keep it in this thread.
|
// it shouldn't be THAT bad, so keep it in this thread.
|
||||||
Storage s = new Storage(_manager.util(), baseFile, announceURL, null);
|
Storage s = new Storage(_manager.util(), baseFile, announceURL, req.getParameter("private") != null, 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");
|
||||||
@@ -713,6 +754,54 @@ public class I2PSnarkServlet extends Default {
|
|||||||
_manager.addMessage("Unknown POST action: \"" + action + '\"');
|
_manager.addMessage("Unknown POST action: \"" + action + '\"');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** @since 0.9 */
|
||||||
|
private void processTrackerForm(String action, HttpServletRequest req) {
|
||||||
|
if (action.equals(_("Delete selected"))) {
|
||||||
|
boolean changed = false;
|
||||||
|
Map<String, String> trackers = _manager.getTrackers();
|
||||||
|
Enumeration e = req.getParameterNames();
|
||||||
|
while (e.hasMoreElements()) {
|
||||||
|
Object o = e.nextElement();
|
||||||
|
if (!(o instanceof String))
|
||||||
|
continue;
|
||||||
|
String k = (String) o;
|
||||||
|
if (!k.startsWith("delete_"))
|
||||||
|
continue;
|
||||||
|
k = k.substring(7);
|
||||||
|
if (trackers.remove(k) != null) {
|
||||||
|
_manager.addMessage(_("Removed") + ": " + k);
|
||||||
|
changed = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (changed) {
|
||||||
|
_manager.saveTrackerMap();
|
||||||
|
}
|
||||||
|
} else if (action.equals(_("Add tracker"))) {
|
||||||
|
String name = req.getParameter("tname");
|
||||||
|
String hurl = req.getParameter("thurl");
|
||||||
|
String aurl = req.getParameter("taurl");
|
||||||
|
if (name != null && hurl != null && aurl != null) {
|
||||||
|
name = name.trim();
|
||||||
|
hurl = hurl.trim();
|
||||||
|
aurl = aurl.trim().replace("=", "=");
|
||||||
|
if (name.length() > 0 && hurl.startsWith("http://") && aurl.startsWith("http://")) {
|
||||||
|
Map<String, String> trackers = _manager.getTrackers();
|
||||||
|
trackers.put(name, aurl + '=' + hurl);
|
||||||
|
_manager.saveTrackerMap();
|
||||||
|
} else {
|
||||||
|
_manager.addMessage(_("Enter valid tracker name and URLs"));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
_manager.addMessage(_("Enter valid tracker name and URLs"));
|
||||||
|
}
|
||||||
|
} else if (action.equals(_("Restore defaults"))) {
|
||||||
|
_manager.setDefaultTrackerMap();
|
||||||
|
_manager.addMessage(_("Restored default trackers"));
|
||||||
|
} else {
|
||||||
|
_manager.addMessage("Unknown POST action: \"" + action + '\"');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private static final String iopts[] = {"inbound.length", "inbound.quantity",
|
private static final String iopts[] = {"inbound.length", "inbound.quantity",
|
||||||
"outbound.length", "outbound.quantity" };
|
"outbound.length", "outbound.quantity" };
|
||||||
@@ -1222,7 +1311,7 @@ public class I2PSnarkServlet extends Default {
|
|||||||
out.write("\"> \n");
|
out.write("\"> \n");
|
||||||
// not supporting from file at the moment, since the file name passed isn't always absolute (so it may not resolve)
|
// not supporting from file at the moment, since the file name passed isn't always absolute (so it may not resolve)
|
||||||
//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\" 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");
|
||||||
out.write("<tr><td> <td><span class=\"snarkAddInfo\">");
|
out.write("<tr><td> <td><span class=\"snarkAddInfo\">");
|
||||||
@@ -1269,31 +1358,40 @@ public class I2PSnarkServlet extends Default {
|
|||||||
//out.write(_("Open trackers and DHT only"));
|
//out.write(_("Open trackers and DHT only"));
|
||||||
out.write(_("Open trackers only"));
|
out.write(_("Open trackers only"));
|
||||||
out.write("</option>\n");
|
out.write("</option>\n");
|
||||||
Map trackers = _manager.getTrackers();
|
Map<String, String> trackers = _manager.getTrackers();
|
||||||
for (Iterator iter = trackers.entrySet().iterator(); iter.hasNext(); ) {
|
for (Map.Entry<String, String> entry : trackers.entrySet()) {
|
||||||
Map.Entry entry = (Map.Entry)iter.next();
|
String name = entry.getKey();
|
||||||
String name = (String)entry.getKey();
|
String announceURL = entry.getValue();
|
||||||
String announceURL = (String)entry.getValue();
|
|
||||||
int e = announceURL.indexOf('=');
|
int e = announceURL.indexOf('=');
|
||||||
if (e > 0)
|
if (e > 0)
|
||||||
announceURL = announceURL.substring(0, e);
|
announceURL = announceURL.substring(0, e).replace("=", "=");
|
||||||
if (announceURL.equals(_lastAnnounceURL))
|
if (announceURL.equals(_lastAnnounceURL))
|
||||||
announceURL += "\" selected=\"selected";
|
announceURL += "\" selected=\"selected";
|
||||||
out.write("\t<option value=\"" + announceURL + "\">" + name + "</option>\n");
|
out.write("\t<option value=\"" + announceURL + "\">" + name + "</option>\n");
|
||||||
}
|
}
|
||||||
out.write("</select>\n");
|
out.write("</select>\n");
|
||||||
out.write(_("or"));
|
// make the user add a tracker on the config form now
|
||||||
out.write(" <input type=\"text\" name=\"announceURLOther\" size=\"57\" value=\"http://\" " +
|
//out.write(_("or"));
|
||||||
"title=\"");
|
//out.write(" <input type=\"text\" name=\"announceURLOther\" size=\"57\" value=\"http://\" " +
|
||||||
out.write(_("Specify custom tracker announce URL"));
|
// "title=\"");
|
||||||
out.write("\" > " +
|
//out.write(_("Specify custom tracker announce URL"));
|
||||||
"<input type=\"submit\" value=\"");
|
//out.write("\" > " +
|
||||||
|
out.write(" <input type=\"submit\" class=\"create\" value=\"");
|
||||||
out.write(_("Create torrent"));
|
out.write(_("Create torrent"));
|
||||||
out.write("\" name=\"foo\" ></table>\n" +
|
out.write("\" name=\"foo\" >\n" +
|
||||||
|
"</td></tr><tr><td>");
|
||||||
|
out.write(_("Private?"));
|
||||||
|
out.write(" </td><td> <input type=\"checkbox\" class=\"optbox\" name=\"private\" value=\"true\" title=\"");
|
||||||
|
out.write(_("Use for private trackers"));
|
||||||
|
out.write("\"");
|
||||||
|
if (req.getParameter("private") != null)
|
||||||
|
out.write(" checked");
|
||||||
|
out.write("></td></tr>" +
|
||||||
|
"</table>\n" +
|
||||||
"</form></div></div>");
|
"</form></div></div>");
|
||||||
}
|
}
|
||||||
|
|
||||||
private static final int[] times = { 30, 60, 2*60, 5*60, 10*60, 30*60, -1 };
|
private static final int[] times = { 5, 15, 30, 60, 2*60, 5*60, 10*60, 30*60, -1 };
|
||||||
|
|
||||||
private void writeConfigForm(PrintWriter out, HttpServletRequest req) throws IOException {
|
private void writeConfigForm(PrintWriter out, HttpServletRequest req) throws IOException {
|
||||||
String dataDir = _manager.getDataDir().getAbsolutePath();
|
String dataDir = _manager.getDataDir().getAbsolutePath();
|
||||||
@@ -1356,7 +1454,7 @@ public class I2PSnarkServlet extends Default {
|
|||||||
out.write(Integer.toString(times[i]));
|
out.write(Integer.toString(times[i]));
|
||||||
out.write("\"");
|
out.write("\"");
|
||||||
if (times[i] == delay)
|
if (times[i] == delay)
|
||||||
out.write(" selected=\"true\"");
|
out.write(" selected=\"selected\"");
|
||||||
out.write(">");
|
out.write(">");
|
||||||
if (times[i] > 0)
|
if (times[i] > 0)
|
||||||
out.write(DataHelper.formatDuration2(times[i] * 1000));
|
out.write(DataHelper.formatDuration2(times[i] * 1000));
|
||||||
@@ -1379,15 +1477,15 @@ public class I2PSnarkServlet extends Default {
|
|||||||
/*
|
/*
|
||||||
out.write("Seed percentage: <select name=\"seedPct\" disabled=\"true\" >\n\t");
|
out.write("Seed percentage: <select name=\"seedPct\" disabled=\"true\" >\n\t");
|
||||||
if (seedPct <= 0)
|
if (seedPct <= 0)
|
||||||
out.write("<option value=\"0\" selected=\"true\">Unlimited</option>\n\t");
|
out.write("<option value=\"0\" selected=\"selected\">Unlimited</option>\n\t");
|
||||||
else
|
else
|
||||||
out.write("<option value=\"0\">Unlimited</option>\n\t");
|
out.write("<option value=\"0\">Unlimited</option>\n\t");
|
||||||
if (seedPct == 100)
|
if (seedPct == 100)
|
||||||
out.write("<option value=\"100\" selected=\"true\">100%</option>\n\t");
|
out.write("<option value=\"100\" selected=\"selected\">100%</option>\n\t");
|
||||||
else
|
else
|
||||||
out.write("<option value=\"100\">100%</option>\n\t");
|
out.write("<option value=\"100\">100%</option>\n\t");
|
||||||
if (seedPct == 150)
|
if (seedPct == 150)
|
||||||
out.write("<option value=\"150\" selected=\"true\">150%</option>\n\t");
|
out.write("<option value=\"150\" selected=\"selected\">150%</option>\n\t");
|
||||||
else
|
else
|
||||||
out.write("<option value=\"150\">150%</option>\n\t");
|
out.write("<option value=\"150\">150%</option>\n\t");
|
||||||
out.write("</select><br>\n");
|
out.write("</select><br>\n");
|
||||||
@@ -1473,6 +1571,57 @@ public class I2PSnarkServlet extends Default {
|
|||||||
"</table></div></div></form>");
|
"</table></div></div></form>");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** @since 0.9 */
|
||||||
|
private void writeTrackerForm(PrintWriter out, HttpServletRequest req) throws IOException {
|
||||||
|
StringBuilder buf = new StringBuilder(1024);
|
||||||
|
buf.append("<form action=\"/i2psnark/configure\" method=\"POST\">\n" +
|
||||||
|
"<div class=\"configsectionpanel\"><div class=\"snarkConfig\">\n" +
|
||||||
|
"<input type=\"hidden\" name=\"nonce\" value=\"" + _nonce + "\" >\n" +
|
||||||
|
"<input type=\"hidden\" name=\"action\" value=\"Save2\" >\n" +
|
||||||
|
"<span class=\"snarkConfigTitle\">" +
|
||||||
|
"<img alt=\"\" border=\"0\" src=\"" + _imgPath + "config.png\"> ");
|
||||||
|
buf.append(_("Trackers"));
|
||||||
|
buf.append("</span><hr>\n" +
|
||||||
|
"<table><tr><th>")
|
||||||
|
//.append(_("Remove"))
|
||||||
|
.append("</th><th>")
|
||||||
|
.append(_("Name"))
|
||||||
|
.append("</th><th>")
|
||||||
|
.append(_("Website URL"))
|
||||||
|
.append("</th><th>")
|
||||||
|
.append(_("Announce URL"))
|
||||||
|
.append("</th></tr>\n");
|
||||||
|
Map<String, String> trackers = _manager.getTrackers();
|
||||||
|
for (Map.Entry<String, String> entry : trackers.entrySet()) {
|
||||||
|
String name = entry.getKey();
|
||||||
|
String announceURL = entry.getValue();
|
||||||
|
int e = announceURL.indexOf('=');
|
||||||
|
if (e <= 0)
|
||||||
|
continue;
|
||||||
|
String homeURL = announceURL.substring(e + 1);
|
||||||
|
announceURL = announceURL.substring(0, e).replace("=", "=");
|
||||||
|
buf.append("<tr><td align=\"center\"><input type=\"checkbox\" class=\"optbox\" name=\"delete_")
|
||||||
|
.append(name).append("\">" +
|
||||||
|
"</td><td align=\"left\">").append(name)
|
||||||
|
.append("</td><td align=\"left\">").append(urlify(homeURL, 35))
|
||||||
|
.append("</td><td align=\"left\">").append(urlify(announceURL, 35))
|
||||||
|
.append("</td></tr>\n");
|
||||||
|
}
|
||||||
|
buf.append("<tr><td align=\"center\"><b>")
|
||||||
|
.append(_("Add")).append(":</b></td>" +
|
||||||
|
"<td align=\"left\"><input type=\"text\" size=\"16\" name=\"tname\"></td>" +
|
||||||
|
"<td align=\"left\"><input type=\"text\" size=\"40\" name=\"thurl\"></td>" +
|
||||||
|
"<td align=\"left\"><input type=\"text\" size=\"40\" name=\"taurl\"></td></tr>\n" +
|
||||||
|
"<tr><td colspan=\"2\"></td><td colspan=\"2\" align=\"left\">\n" +
|
||||||
|
"<input type=\"submit\" name=\"taction\" class=\"default\" value=\"").append(_("Add tracker")).append("\">\n" +
|
||||||
|
"<input type=\"submit\" name=\"taction\" class=\"delete\" value=\"").append(_("Delete selected")).append("\">\n" +
|
||||||
|
// "<input type=\"reset\" class=\"cancel\" value=\"").append(_("Cancel")).append("\">\n" +
|
||||||
|
"<input type=\"submit\" name=\"taction\" class=\"reload\" value=\"").append(_("Restore defaults")).append("\">\n" +
|
||||||
|
"<input type=\"submit\" name=\"taction\" class=\"add\" value=\"").append(_("Add tracker")).append("\">\n" +
|
||||||
|
"</td></tr></table></div></div></form>\n");
|
||||||
|
out.write(buf.toString());
|
||||||
|
}
|
||||||
|
|
||||||
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" +
|
||||||
"<span class=\"snarkConfigTitle\"><a href=\"configure\">" +
|
"<span class=\"snarkConfigTitle\"><a href=\"configure\">" +
|
||||||
@@ -1574,7 +1723,7 @@ public class I2PSnarkServlet extends Default {
|
|||||||
for (int i = min; i <= max; i++) {
|
for (int i = min; i <= max; i++) {
|
||||||
buf.append("<option value=\"").append(i).append("\" ");
|
buf.append("<option value=\"").append(i).append("\" ");
|
||||||
if (i == now)
|
if (i == now)
|
||||||
buf.append("selected=\"true\" ");
|
buf.append("selected=\"selected\" ");
|
||||||
// constants to prevent tagging
|
// constants to prevent tagging
|
||||||
buf.append(">").append(ngettext(DUMMY1 + name, DUMMY0 + name + 's', i));
|
buf.append(">").append(ngettext(DUMMY1 + name, DUMMY0 + name + 's', i));
|
||||||
buf.append("</option>\n");
|
buf.append("</option>\n");
|
||||||
@@ -1622,10 +1771,20 @@ public class I2PSnarkServlet extends Default {
|
|||||||
|
|
||||||
/** @since 0.7.14 */
|
/** @since 0.7.14 */
|
||||||
private static String urlify(String s) {
|
private static String urlify(String s) {
|
||||||
|
return urlify(s, 100);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @since 0.9 */
|
||||||
|
private static String urlify(String s, int max) {
|
||||||
StringBuilder buf = new StringBuilder(256);
|
StringBuilder buf = new StringBuilder(256);
|
||||||
// browsers seem to work without doing this but let's be strict
|
// browsers seem to work without doing this but let's be strict
|
||||||
String link = urlEncode(s);
|
String link = urlEncode(s);
|
||||||
buf.append("<a href=\"").append(link).append("\">").append(link).append("</a>");
|
String display;
|
||||||
|
if (s.length() <= max)
|
||||||
|
display = link;
|
||||||
|
else
|
||||||
|
display = urlEncode(s.substring(0, max)) + "…";
|
||||||
|
buf.append("<a href=\"").append(link).append("\">").append(display).append("</a>");
|
||||||
return buf.toString();
|
return buf.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1991,12 +2150,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 */
|
/** @since 0.8.2 */
|
||||||
private static String toImg(String icon, String altText) {
|
private static String toImg(String icon, String altText) {
|
||||||
return "<img alt=\"" + altText + "\" height=\"16\" width=\"16\" src=\"/i2psnark/_icons/" + icon + ".png\">";
|
return "<img alt=\"" + altText + "\" height=\"16\" width=\"16\" src=\"/i2psnark/.icons/" + icon + ".png\">";
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @since 0.8.1 */
|
/** @since 0.8.1 */
|
||||||
|
@@ -63,6 +63,7 @@
|
|||||||
<attribute name="Main-Class" value="net.i2p.i2ptunnel.I2PTunnel" />
|
<attribute name="Main-Class" value="net.i2p.i2ptunnel.I2PTunnel" />
|
||||||
<attribute name="Class-Path" value="i2p.jar mstreaming.jar" />
|
<attribute name="Class-Path" value="i2p.jar mstreaming.jar" />
|
||||||
<attribute name="Implementation-Version" value="${full.version}" />
|
<attribute name="Implementation-Version" value="${full.version}" />
|
||||||
|
<attribute name="Built-By" value="${build.built-by}" />
|
||||||
<attribute name="Build-Date" value="${build.timestamp}" />
|
<attribute name="Build-Date" value="${build.timestamp}" />
|
||||||
<attribute name="Base-Revision" value="${workspace.version}" />
|
<attribute name="Base-Revision" value="${workspace.version}" />
|
||||||
<attribute name="Workspace-Changes" value="${workspace.changes.j.tr}" />
|
<attribute name="Workspace-Changes" value="${workspace.changes.j.tr}" />
|
||||||
@@ -136,6 +137,7 @@
|
|||||||
basedir="../jsp/" excludes="web.xml, web-fragment.xml, web-out.xml, **/*.java, *.jsp">
|
basedir="../jsp/" excludes="web.xml, web-fragment.xml, web-out.xml, **/*.java, *.jsp">
|
||||||
<manifest>
|
<manifest>
|
||||||
<attribute name="Implementation-Version" value="${full.version}" />
|
<attribute name="Implementation-Version" value="${full.version}" />
|
||||||
|
<attribute name="Built-By" value="${build.built-by}" />
|
||||||
<attribute name="Build-Date" value="${build.timestamp}" />
|
<attribute name="Build-Date" value="${build.timestamp}" />
|
||||||
<attribute name="Base-Revision" value="${workspace.version}" />
|
<attribute name="Base-Revision" value="${workspace.version}" />
|
||||||
<attribute name="Workspace-Changes" value="${workspace.changes.w.tr}" />
|
<attribute name="Workspace-Changes" value="${workspace.changes.w.tr}" />
|
||||||
|
@@ -13,6 +13,8 @@ import java.io.InputStreamReader;
|
|||||||
import java.io.OutputStream;
|
import java.io.OutputStream;
|
||||||
import java.net.Socket;
|
import java.net.Socket;
|
||||||
import java.net.SocketException;
|
import java.net.SocketException;
|
||||||
|
import java.net.URI;
|
||||||
|
import java.net.URISyntaxException;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
@@ -36,8 +38,8 @@ import net.i2p.data.DataFormatException;
|
|||||||
import net.i2p.data.DataHelper;
|
import net.i2p.data.DataHelper;
|
||||||
import net.i2p.data.Destination;
|
import net.i2p.data.Destination;
|
||||||
import net.i2p.data.Hash;
|
import net.i2p.data.Hash;
|
||||||
|
import net.i2p.i2ptunnel.localServer.LocalHTTPServer;
|
||||||
import net.i2p.util.EventDispatcher;
|
import net.i2p.util.EventDispatcher;
|
||||||
import net.i2p.util.FileUtil;
|
|
||||||
import net.i2p.util.Log;
|
import net.i2p.util.Log;
|
||||||
import net.i2p.util.PortMapper;
|
import net.i2p.util.PortMapper;
|
||||||
import net.i2p.util.Translate;
|
import net.i2p.util.Translate;
|
||||||
@@ -61,6 +63,10 @@ import net.i2p.util.Translate;
|
|||||||
* in browsers or other user-visible applications, as relative links will not
|
* in browsers or other user-visible applications, as relative links will not
|
||||||
* resolve correctly, cookies won't work, etc.
|
* resolve correctly, cookies won't work, etc.
|
||||||
*
|
*
|
||||||
|
* Note that http://$b64key/... and http://$b64key.i2p/... are NOT supported, as
|
||||||
|
* a b64 key may contain '=' and '~', both of which are illegal host name characters.
|
||||||
|
* Rewrite as http://i2p/$b64key/...
|
||||||
|
*
|
||||||
* If the $site resolves with the I2P naming service, then it is directed towards
|
* If the $site resolves with the I2P naming service, then it is directed towards
|
||||||
* that eepsite, otherwise it is directed towards this client's outproxy (typically
|
* that eepsite, otherwise it is directed towards this client's outproxy (typically
|
||||||
* "squid.i2p"). Only HTTP is supported (no HTTPS, ftp, mailto, etc). Both GET
|
* "squid.i2p"). Only HTTP is supported (no HTTPS, ftp, mailto, etc). Both GET
|
||||||
@@ -102,7 +108,7 @@ public class I2PTunnelHTTPClient extends I2PTunnelHTTPClientBase implements Runn
|
|||||||
"That I2P Destination was not found. Perhaps you pasted in the "+
|
"That I2P Destination was not found. Perhaps you pasted in the "+
|
||||||
"wrong BASE64 I2P Destination or the link you are following is "+
|
"wrong BASE64 I2P Destination or the link you are following is "+
|
||||||
"bad. The host (or the WWW proxy, if you're using one) could also "+
|
"bad. The host (or the WWW proxy, if you're using one) could also "+
|
||||||
"be temporarily offline. You may want to <b>retry</b>. "+
|
"be temporarily offline. You may want to <b>retry</b>. "+
|
||||||
"Could not find the following Destination:<BR><BR><div>")
|
"Could not find the following Destination:<BR><BR><div>")
|
||||||
.getBytes();
|
.getBytes();
|
||||||
|
|
||||||
@@ -309,7 +315,8 @@ public class I2PTunnelHTTPClient extends I2PTunnelHTTPClientBase implements Runn
|
|||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static final String LOCAL_SERVER = "proxy.i2p";
|
private static final String HELPER_PARAM = "i2paddresshelper";
|
||||||
|
public static final String LOCAL_SERVER = "proxy.i2p";
|
||||||
private static final boolean DEFAULT_GZIP = true;
|
private static final boolean DEFAULT_GZIP = true;
|
||||||
/** all default to false */
|
/** all default to false */
|
||||||
public static final String PROP_REFERER = "i2ptunnel.httpclient.sendReferer";
|
public static final String PROP_REFERER = "i2ptunnel.httpclient.sendReferer";
|
||||||
@@ -321,11 +328,19 @@ public class I2PTunnelHTTPClient extends I2PTunnelHTTPClientBase implements Runn
|
|||||||
protected void clientConnectionRun(Socket s) {
|
protected void clientConnectionRun(Socket s) {
|
||||||
InputStream in = null;
|
InputStream in = null;
|
||||||
OutputStream out = null;
|
OutputStream out = null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The URL after fixup, always starting with http://
|
||||||
|
*/
|
||||||
String targetRequest = null;
|
String targetRequest = null;
|
||||||
|
|
||||||
boolean usingWWWProxy = false;
|
boolean usingWWWProxy = false;
|
||||||
boolean usingInternalServer = false;
|
boolean usingInternalServer = false;
|
||||||
|
String internalPath = null;
|
||||||
|
String internalRawQuery = null;
|
||||||
String currentProxy = null;
|
String currentProxy = null;
|
||||||
long requestId = ++__requestId;
|
long requestId = ++__requestId;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
out = s.getOutputStream();
|
out = s.getOutputStream();
|
||||||
InputReader reader = new InputReader(s.getInputStream());
|
InputReader reader = new InputReader(s.getInputStream());
|
||||||
@@ -351,79 +366,84 @@ public class I2PTunnelHTTPClient extends I2PTunnelHTTPClientBase implements Runn
|
|||||||
if (_log.shouldLog(Log.DEBUG))
|
if (_log.shouldLog(Log.DEBUG))
|
||||||
_log.debug(getPrefix(requestId) + "First line [" + line + "]");
|
_log.debug(getPrefix(requestId) + "First line [" + line + "]");
|
||||||
|
|
||||||
int pos = line.indexOf(" ");
|
String[] params = line.split(" ", 3);
|
||||||
if (pos == -1) break;
|
if (params.length != 3)
|
||||||
method = line.substring(0, pos);
|
break;
|
||||||
// TODO use Java URL class to make all this simpler and more robust
|
String request = params[1];
|
||||||
// That will also fix IPV6 [a:b:c]
|
|
||||||
String request = line.substring(pos + 1);
|
// various obscure fixups
|
||||||
if (request.startsWith("/") && getTunnel().getClientOptions().getProperty("i2ptunnel.noproxy") != null) {
|
if (request.startsWith("/") && getTunnel().getClientOptions().getProperty("i2ptunnel.noproxy") != null) {
|
||||||
// what is this for ???
|
// what is this for ???
|
||||||
request = "http://i2p" + request;
|
request = "http://i2p" + request;
|
||||||
} else if (request.startsWith("/eepproxy/")) {
|
} else if (request.startsWith("/eepproxy/")) {
|
||||||
// /eepproxy/foo.i2p/bar/baz.html HTTP/1.0
|
// Deprecated
|
||||||
|
// /eepproxy/foo.i2p/bar/baz.html
|
||||||
String subRequest = request.substring("/eepproxy/".length());
|
String subRequest = request.substring("/eepproxy/".length());
|
||||||
int protopos = subRequest.indexOf(" ");
|
if (subRequest.indexOf("/") == -1)
|
||||||
String uri = subRequest.substring(0, protopos);
|
subRequest += "/";
|
||||||
if (uri.indexOf("/") == -1) {
|
request = "http://" + subRequest;
|
||||||
uri = uri + "/";
|
/****
|
||||||
}
|
|
||||||
// "http://" + "foo.i2p/bar/baz.html" + " HTTP/1.0"
|
|
||||||
request = "http://" + uri + subRequest.substring(protopos);
|
|
||||||
} else if (request.toLowerCase(Locale.US).startsWith("http://i2p/")) {
|
} else if (request.toLowerCase(Locale.US).startsWith("http://i2p/")) {
|
||||||
// http://i2p/b64key/bar/baz.html HTTP/1.0
|
// http://i2p/b64key/bar/baz.html
|
||||||
|
// we can't do this now by setting the URI host to the b64key, as
|
||||||
|
// it probably contains '=' and '~' which are illegal,
|
||||||
|
// and a host may not include escaped octets
|
||||||
|
// This will get undone below.
|
||||||
String subRequest = request.substring("http://i2p/".length());
|
String subRequest = request.substring("http://i2p/".length());
|
||||||
int protopos = subRequest.indexOf(" ");
|
if (subRequest.indexOf("/") == -1)
|
||||||
String uri = subRequest.substring(0, protopos);
|
subRequest += "/";
|
||||||
if (uri.indexOf("/") == -1) {
|
"http://" + "b64key/bar/baz.html"
|
||||||
uri = uri + "/";
|
request = "http://" + subRequest;
|
||||||
}
|
} else if (request.toLowerCase(Locale.US).startsWith("http://")) {
|
||||||
// "http://" + "b64key/bar/baz.html" + " HTTP/1.0"
|
// Unsupported
|
||||||
request = "http://" + uri + subRequest.substring(protopos);
|
// http://$b64key/...
|
||||||
|
// This probably used to work, rewrite it so that
|
||||||
|
// we can create a URI without illegal characters
|
||||||
|
// This will get undone below.
|
||||||
|
String oldPath = request.substring(7);
|
||||||
|
int slash = oldPath.indexOf("/");
|
||||||
|
if (slash < 0)
|
||||||
|
slash = oldPath.length();
|
||||||
|
if (slash >= 516 && !oldPath.substring(0, slash).contains("."))
|
||||||
|
request = "http://i2p/" + oldPath;
|
||||||
|
****/
|
||||||
}
|
}
|
||||||
|
|
||||||
pos = request.indexOf("//");
|
// Now use the Java URI parser
|
||||||
if (pos == -1) {
|
// This will be the incoming URI but will then get modified
|
||||||
|
// to be the outgoing URI (with http:// if going to outproxy, otherwise without)
|
||||||
|
URI requestURI;
|
||||||
|
try {
|
||||||
|
requestURI = new URI(request);
|
||||||
|
if (requestURI.getRawUserInfo() != null || requestURI.getRawFragment() != null) {
|
||||||
|
// these should never be sent to the proxy in the request line
|
||||||
|
if (_log.shouldLog(Log.WARN))
|
||||||
|
_log.warn(getPrefix(requestId) + "Removing userinfo or fragment [" + request + "]");
|
||||||
|
requestURI = changeURI(requestURI, null, 0, null);
|
||||||
|
}
|
||||||
|
if (requestURI.getPath() == null || requestURI.getPath().length() <= 0) {
|
||||||
|
// Add a path
|
||||||
|
if (_log.shouldLog(Log.WARN))
|
||||||
|
_log.warn(getPrefix(requestId) + "Adding / path to [" + request + "]");
|
||||||
|
requestURI = changeURI(requestURI, null, 0, "/");
|
||||||
|
}
|
||||||
|
} catch (URISyntaxException use) {
|
||||||
|
if (_log.shouldLog(Log.WARN))
|
||||||
|
_log.warn(getPrefix(requestId) + "Bad request [" + request + "]", use);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
method = params[0];
|
||||||
|
String protocolVersion = params[2];
|
||||||
|
|
||||||
|
protocol = requestURI.getScheme();
|
||||||
|
host = requestURI.getHost();
|
||||||
|
if (protocol == null || host == null) {
|
||||||
|
_log.warn("Null protocol or host: " + request);
|
||||||
method = null;
|
method = null;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
protocol = request.substring(0, pos + 2);
|
|
||||||
request = request.substring(pos + 2);
|
|
||||||
|
|
||||||
// "foo.i2p/bar/baz HTTP/1.1", with any i2paddresshelper parameter removed
|
int port = requestURI.getPort();
|
||||||
targetRequest = request;
|
|
||||||
|
|
||||||
// pos is the start of the path
|
|
||||||
pos = request.indexOf("/");
|
|
||||||
if (pos == -1) {
|
|
||||||
//pos = request.length();
|
|
||||||
method = null;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
host = request.substring(0, pos);
|
|
||||||
|
|
||||||
// parse port
|
|
||||||
int posPort = host.indexOf(":");
|
|
||||||
int port = 80;
|
|
||||||
if(posPort != -1) {
|
|
||||||
String[] parts = host.split(":");
|
|
||||||
try {
|
|
||||||
host = parts[0];
|
|
||||||
} catch (ArrayIndexOutOfBoundsException ex) {
|
|
||||||
if (out != null) {
|
|
||||||
out.write(getErrorPage("denied", ERR_REQUEST_DENIED));
|
|
||||||
writeFooter(out);
|
|
||||||
}
|
|
||||||
s.close();
|
|
||||||
return;
|
|
||||||
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
port = Integer.parseInt(parts[1]);
|
|
||||||
} catch(Exception exc) {
|
|
||||||
// TODO: log this
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Go through the various types of host names, set
|
// Go through the various types of host names, set
|
||||||
// the host and destination variables accordingly,
|
// the host and destination variables accordingly,
|
||||||
@@ -433,115 +453,142 @@ public class I2PTunnelHTTPClient extends I2PTunnelHTTPClientBase implements Runn
|
|||||||
// in our addressbook (all naming is local),
|
// in our addressbook (all naming is local),
|
||||||
// and it is removed from the request line.
|
// and it is removed from the request line.
|
||||||
|
|
||||||
if (host.length() >= 516 && host.indexOf(".") < 0) {
|
String hostLowerCase = host.toLowerCase(Locale.US);
|
||||||
// http://b64key/bar/baz.html
|
if (hostLowerCase.equals(LOCAL_SERVER)) {
|
||||||
destination = host;
|
|
||||||
host = getHostName(destination);
|
|
||||||
line = method + ' ' + request.substring(pos);
|
|
||||||
} else if (host.toLowerCase(Locale.US).equals(LOCAL_SERVER)) {
|
|
||||||
// so we don't do any naming service lookups
|
// so we don't do any naming service lookups
|
||||||
destination = host;
|
destination = host;
|
||||||
usingInternalServer = true;
|
usingInternalServer = true;
|
||||||
} else if (host.toLowerCase(Locale.US).endsWith(".i2p")) {
|
internalPath = requestURI.getPath();
|
||||||
|
internalRawQuery = requestURI.getRawQuery();
|
||||||
|
} else if (hostLowerCase.equals("i2p")) {
|
||||||
|
// pull the b64 dest out of the first path element
|
||||||
|
String oldPath = requestURI.getPath().substring(1);
|
||||||
|
int slash = oldPath.indexOf("/");
|
||||||
|
if (slash < 0) {
|
||||||
|
slash = oldPath.length();
|
||||||
|
oldPath += "/";
|
||||||
|
}
|
||||||
|
String dest = oldPath.substring(0, slash);
|
||||||
|
if (slash >= 516 && !dest.contains(".")) {
|
||||||
|
// possible alternative:
|
||||||
|
// redirect to b32
|
||||||
|
destination = dest;
|
||||||
|
host = getHostName(destination);
|
||||||
|
targetRequest = requestURI.toASCIIString();
|
||||||
|
String newURI = oldPath.substring(slash);
|
||||||
|
String query = requestURI.getRawQuery();
|
||||||
|
if (query != null)
|
||||||
|
newURI += '?' + query;
|
||||||
|
try {
|
||||||
|
requestURI = new URI(newURI);
|
||||||
|
} catch (URISyntaxException use) {
|
||||||
|
// shouldnt happen
|
||||||
|
_log.warn(request, use);
|
||||||
|
method = null;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
_log.warn("Bad http://i2p/b64dest " + request);
|
||||||
|
host = null;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} else if (hostLowerCase.endsWith(".i2p")) {
|
||||||
// Destination gets the host name
|
// Destination gets the host name
|
||||||
destination = host;
|
destination = host;
|
||||||
// Host becomes the destination's "{b32}.b32.i2p" string, or "i2p" on lookup failure
|
// Host becomes the destination's "{b32}.b32.i2p" string, or "i2p" on lookup failure
|
||||||
host = getHostName(destination);
|
host = getHostName(destination);
|
||||||
|
|
||||||
int pos2;
|
if (requestURI.getPort() >= 0) {
|
||||||
if ((pos2 = request.indexOf("?")) != -1) {
|
// TODO support I2P ports someday
|
||||||
// Try to find an address helper in the fragments
|
//if (port >= 0)
|
||||||
// and split the request into it's component parts for rebuilding later
|
// host = host + ':' + port;
|
||||||
|
if (_log.shouldLog(Log.WARN))
|
||||||
|
_log.warn(getPrefix(requestId) + "Removing port from [" + request + "]");
|
||||||
|
try {
|
||||||
|
requestURI = changeURI(requestURI, null, -1, null);
|
||||||
|
} catch (URISyntaxException use) {
|
||||||
|
_log.warn(request, use);
|
||||||
|
method = null;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
String query = requestURI.getRawQuery();
|
||||||
|
if (query != null) {
|
||||||
boolean ahelperConflict = false;
|
boolean ahelperConflict = false;
|
||||||
|
|
||||||
String fragments = request.substring(pos2 + 1);
|
// Try to find an address helper in the query
|
||||||
String uriPath = request.substring(0, pos2);
|
String[] helperStrings = removeHelper(query);
|
||||||
pos2 = fragments.indexOf(" ");
|
if (helperStrings != null &&
|
||||||
String protocolVersion = fragments.substring(pos2 + 1);
|
!Boolean.valueOf(getTunnel().getClientOptions().getProperty(PROP_DISABLE_HELPER)).booleanValue()) {
|
||||||
String urlEncoding = "";
|
query = helperStrings[0];
|
||||||
fragments = fragments.substring(0, pos2);
|
if (query.equals(""))
|
||||||
String initialFragments = fragments;
|
query = null;
|
||||||
// FIXME split on ';' also
|
try {
|
||||||
fragments = fragments + "&";
|
requestURI = replaceQuery(requestURI, query);
|
||||||
String fragment;
|
} catch (URISyntaxException use) {
|
||||||
while(fragments.length() > 0) {
|
// shouldn't happen
|
||||||
pos2 = fragments.indexOf("&");
|
_log.warn(request, use);
|
||||||
fragment = fragments.substring(0, pos2);
|
method = null;
|
||||||
fragments = fragments.substring(pos2 + 1);
|
break;
|
||||||
|
}
|
||||||
|
ahelperKey = helperStrings[1];
|
||||||
|
// Key contains data, lets not ignore it
|
||||||
|
if (ahelperKey.length() > 0) {
|
||||||
|
if(ahelperKey.endsWith(".i2p")) {
|
||||||
|
// allow i2paddresshelper=<b32>.b32.i2p syntax.
|
||||||
|
/*
|
||||||
|
also i2paddresshelper=name.i2p for aliases
|
||||||
|
i.e. on your eepsite put
|
||||||
|
<a href="?i2paddresshelper=name.i2p">This is the name I want to be called.</a>
|
||||||
|
*/
|
||||||
|
Destination dest = _context.namingService().lookup(ahelperKey);
|
||||||
|
if(dest==null) {
|
||||||
|
if (_log.shouldLog(Log.WARN))
|
||||||
|
_log.warn(getPrefix(requestId) + "Could not find destination for "+ahelperKey);
|
||||||
|
byte[] header = getErrorPage("ahelper-notfound", ERR_AHELPER_NOTFOUND);
|
||||||
|
out.write(header);
|
||||||
|
out.write(("<p>" + _("This seems to be a bad destination:") + " " + ahelperKey + " " + _("i2paddresshelper cannot help you with a destination like that!") + "</p>").getBytes("UTF-8"));
|
||||||
|
writeFooter(out);
|
||||||
|
// XXX: should closeSocket(s) be in a finally block?
|
||||||
|
closeSocket(s);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
ahelperKey = dest.toBase64();
|
||||||
|
}
|
||||||
|
|
||||||
// Fragment looks like addresshelper key
|
ahelperPresent = true;
|
||||||
if (fragment.startsWith("i2paddresshelper=") &&
|
// ahelperKey will be validated later
|
||||||
!Boolean.valueOf(getTunnel().getClientOptions().getProperty(PROP_DISABLE_HELPER)).booleanValue()) {
|
if (host == null || "i2p".equals(host)) {
|
||||||
pos2 = fragment.indexOf("=");
|
// Host lookup failed - resolvable only with addresshelper
|
||||||
ahelperKey = fragment.substring(pos2 + 1);
|
// Store in local HashMap unless there is conflict
|
||||||
// Key contains data, lets not ignore it
|
String old = addressHelpers.putIfAbsent(destination.toLowerCase(Locale.US), ahelperKey);
|
||||||
if (ahelperKey != null) {
|
ahelperNew = old == null;
|
||||||
if(ahelperKey.endsWith(".i2p")) {
|
if ((!ahelperNew) && !old.equals(ahelperKey)) {
|
||||||
// allow i2paddresshelper=<b32>.b32.i2p syntax.
|
// Conflict: handle when URL reconstruction done
|
||||||
/*
|
ahelperConflict = true;
|
||||||
also i2paddresshelper=name.i2p for aliases
|
if (_log.shouldLog(Log.WARN))
|
||||||
i.e. on your eepsite put
|
_log.warn(getPrefix(requestId) + "Addresshelper key conflict for site [" + destination +
|
||||||
<a href="?i2paddresshelper=name.i2p">This is the name I want to be called.</a>
|
"], trusted key [" + old + "], specified key [" + ahelperKey + "].");
|
||||||
*/
|
}
|
||||||
Destination dest = _context.namingService().lookup(ahelperKey);
|
} else {
|
||||||
if(dest==null) {
|
// If the host is resolvable from database, verify addresshelper key
|
||||||
if (_log.shouldLog(Log.WARN))
|
// Silently bypass correct keys, otherwise alert
|
||||||
_log.warn(getPrefix(requestId) + "Could not find destination for "+ahelperKey);
|
Destination hostDest = _context.namingService().lookup(destination);
|
||||||
byte[] header = getErrorPage("ahelper-notfound", ERR_AHELPER_NOTFOUND);
|
if (hostDest != null) {
|
||||||
out.write(header);
|
String destB64 = hostDest.toBase64();
|
||||||
out.write(("<p>" + _("This seems to be a bad destination:") + " " + ahelperKey + " " + _("i2paddresshelper cannot help you with a destination like that!") + "</p>").getBytes("UTF-8"));
|
if (destB64 != null && !destB64.equals(ahelperKey)) {
|
||||||
writeFooter(out);
|
|
||||||
// XXX: should closeSocket(s) be in a finally block?
|
|
||||||
closeSocket(s);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
ahelperKey = dest.toBase64();
|
|
||||||
}
|
|
||||||
|
|
||||||
ahelperPresent = true;
|
|
||||||
// ahelperKey will be validated later
|
|
||||||
if (host == null || "i2p".equals(host)) {
|
|
||||||
// Host lookup failed - resolvable only with addresshelper
|
|
||||||
// Store in local HashMap unless there is conflict
|
|
||||||
String old = addressHelpers.putIfAbsent(destination.toLowerCase(Locale.US), ahelperKey);
|
|
||||||
ahelperNew = old == null;
|
|
||||||
if ((!ahelperNew) && !old.equals(ahelperKey)) {
|
|
||||||
// Conflict: handle when URL reconstruction done
|
// Conflict: handle when URL reconstruction done
|
||||||
ahelperConflict = true;
|
ahelperConflict = true;
|
||||||
if (_log.shouldLog(Log.WARN))
|
if (_log.shouldLog(Log.WARN))
|
||||||
_log.warn(getPrefix(requestId) + "Addresshelper key conflict for site [" + destination +
|
_log.warn(getPrefix(requestId) + "Addresshelper key conflict for site [" + destination +
|
||||||
"], trusted key [" + old + "], specified key [" + ahelperKey + "].");
|
"], trusted key [" + destB64 + "], specified key [" + ahelperKey + "].");
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// If the host is resolvable from database, verify addresshelper key
|
|
||||||
// Silently bypass correct keys, otherwise alert
|
|
||||||
Destination hostDest = _context.namingService().lookup(destination);
|
|
||||||
if (hostDest != null) {
|
|
||||||
String destB64 = hostDest.toBase64();
|
|
||||||
if (destB64 != null && !destB64.equals(ahelperKey)) {
|
|
||||||
// Conflict: handle when URL reconstruction done
|
|
||||||
ahelperConflict = true;
|
|
||||||
if (_log.shouldLog(Log.WARN))
|
|
||||||
_log.warn(getPrefix(requestId) + "Addresshelper key conflict for site [" + destination +
|
|
||||||
"], trusted key [" + destB64 + "], specified key [" + ahelperKey + "].");
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} // ahelperKey
|
|
||||||
} else {
|
|
||||||
// Other fragments, just pass along
|
|
||||||
// Append each fragment to urlEncoding
|
|
||||||
if ("".equals(urlEncoding)) {
|
|
||||||
urlEncoding = "?" + fragment;
|
|
||||||
} else {
|
|
||||||
urlEncoding = urlEncoding + "&" + fragment;
|
|
||||||
}
|
}
|
||||||
}
|
} // ahelperKey
|
||||||
}
|
} // helperstrings
|
||||||
// Reconstruct the request minus the i2paddresshelper GET var
|
|
||||||
request = uriPath + urlEncoding + " " + protocolVersion;
|
|
||||||
targetRequest = request;
|
|
||||||
|
|
||||||
// Did addresshelper key conflict?
|
// Did addresshelper key conflict?
|
||||||
if (ahelperConflict) {
|
if (ahelperConflict) {
|
||||||
@@ -553,9 +600,17 @@ public class I2PTunnelHTTPClient extends I2PTunnelHTTPClientBase implements Runn
|
|||||||
byte[] header = getErrorPage("dnfb", ERR_DESTINATION_UNKNOWN);
|
byte[] header = getErrorPage("dnfb", ERR_DESTINATION_UNKNOWN);
|
||||||
writeErrorMessage(header, out, targetRequest, false, destination, null);
|
writeErrorMessage(header, out, targetRequest, false, destination, null);
|
||||||
} else {
|
} else {
|
||||||
String trustedURL = protocol + uriPath + urlEncoding;
|
String trustedURL = requestURI.toASCIIString();
|
||||||
// Fixme - any path is lost
|
URI conflictURI;
|
||||||
String conflictURL = protocol + alias + '/' + urlEncoding;
|
try {
|
||||||
|
conflictURI = changeURI(requestURI, alias, 0, null);
|
||||||
|
} catch (URISyntaxException use) {
|
||||||
|
// shouldn't happen
|
||||||
|
_log.warn(request, use);
|
||||||
|
method = null;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
String conflictURL = conflictURI.toASCIIString();
|
||||||
byte[] header = getErrorPage("ahelper-conflict", ERR_AHELPER_CONFLICT);
|
byte[] header = getErrorPage("ahelper-conflict", ERR_AHELPER_CONFLICT);
|
||||||
out.write(header);
|
out.write(header);
|
||||||
out.write(_("To visit the destination in your host database, click <a href=\"{0}\">here</a>. To visit the conflicting addresshelper destination, click <a href=\"{1}\">here</a>.", trustedURL, conflictURL).getBytes("UTF-8"));
|
out.write(_("To visit the destination in your host database, click <a href=\"{0}\">here</a>. To visit the conflicting addresshelper destination, click <a href=\"{1}\">here</a>.", trustedURL, conflictURL).getBytes("UTF-8"));
|
||||||
@@ -572,11 +627,24 @@ public class I2PTunnelHTTPClient extends I2PTunnelHTTPClientBase implements Runn
|
|||||||
if (addressHelper != null)
|
if (addressHelper != null)
|
||||||
host = getHostName(addressHelper);
|
host = getHostName(addressHelper);
|
||||||
|
|
||||||
line = method + " " + request.substring(pos);
|
// now strip everything but path and query from URI
|
||||||
|
targetRequest = requestURI.toASCIIString();
|
||||||
|
String newURI = requestURI.getRawPath();
|
||||||
|
if (query != null)
|
||||||
|
newURI += '?' + query;
|
||||||
|
try {
|
||||||
|
requestURI = new URI(newURI);
|
||||||
|
} catch (URISyntaxException use) {
|
||||||
|
// shouldnt happen
|
||||||
|
_log.warn(request, use);
|
||||||
|
method = null;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
// end of (host endsWith(".i2p"))
|
// end of (host endsWith(".i2p"))
|
||||||
|
|
||||||
} else if (host.toLowerCase(Locale.US).equals("localhost") || host.equals("127.0.0.1") ||
|
} else if (hostLowerCase.equals("localhost") || host.equals("127.0.0.1") ||
|
||||||
host.startsWith("192.168.")) {
|
host.startsWith("192.168.") || host.equals("[::1]")) {
|
||||||
// if somebody is trying to get to 192.168.example.com, oh well
|
// if somebody is trying to get to 192.168.example.com, oh well
|
||||||
if (out != null) {
|
if (out != null) {
|
||||||
out.write(getErrorPage("localhost", ERR_LOCALHOST));
|
out.write(getErrorPage("localhost", ERR_LOCALHOST));
|
||||||
@@ -584,9 +652,9 @@ public class I2PTunnelHTTPClient extends I2PTunnelHTTPClientBase implements Runn
|
|||||||
}
|
}
|
||||||
s.close();
|
s.close();
|
||||||
return;
|
return;
|
||||||
} else if (host.indexOf(".") != -1) {
|
} else if (host.contains(".") || host.startsWith("[")) {
|
||||||
// rebuild host
|
if (port >= 0)
|
||||||
host = host + ":" + port;
|
host = host + ':' + port;
|
||||||
// The request must be forwarded to a WWW proxy
|
// The request must be forwarded to a WWW proxy
|
||||||
if (_log.shouldLog(Log.DEBUG))
|
if (_log.shouldLog(Log.DEBUG))
|
||||||
_log.debug("Before selecting outproxy for " + host);
|
_log.debug("Before selecting outproxy for " + host);
|
||||||
@@ -606,36 +674,23 @@ public class I2PTunnelHTTPClient extends I2PTunnelHTTPClientBase implements Runn
|
|||||||
}
|
}
|
||||||
destination = currentProxy;
|
destination = currentProxy;
|
||||||
usingWWWProxy = true;
|
usingWWWProxy = true;
|
||||||
|
targetRequest = requestURI.toASCIIString();
|
||||||
if (_log.shouldLog(Log.DEBUG))
|
if (_log.shouldLog(Log.DEBUG))
|
||||||
_log.debug(getPrefix(requestId) + "Host doesnt end with .i2p and it contains a period [" + host + "]: wwwProxy!");
|
_log.debug(getPrefix(requestId) + " [" + host + "]: wwwProxy!");
|
||||||
} else {
|
} else {
|
||||||
// what is left for here? a hostname with no dots, and != "i2p"
|
// what is left for here? a hostname with no dots, and != "i2p"
|
||||||
// and not a destination ???
|
// and not a destination ???
|
||||||
// Perhaps something in privatehosts.txt ...
|
// Perhaps something in privatehosts.txt ...
|
||||||
request = request.substring(pos + 1);
|
// Rather than look it up, just bail out.
|
||||||
pos = request.indexOf("/");
|
if (_log.shouldLog(Log.WARN))
|
||||||
if (pos < 0) {
|
_log.warn("NODOTS, NOI2P: " + request);
|
||||||
l.log("Invalid request url [" + request + "]");
|
|
||||||
if (out != null) {
|
|
||||||
out.write(getErrorPage("denied", ERR_REQUEST_DENIED));
|
|
||||||
writeFooter(out);
|
|
||||||
}
|
|
||||||
s.close();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
destination = request.substring(0, pos);
|
|
||||||
host = getHostName(destination);
|
|
||||||
line = method + " " + request.substring(pos);
|
|
||||||
} // end host name processing
|
|
||||||
|
|
||||||
if (port != 80 && !usingWWWProxy) {
|
|
||||||
if (out != null) {
|
if (out != null) {
|
||||||
out.write(getErrorPage("denied", ERR_REQUEST_DENIED));
|
out.write(getErrorPage("denied", ERR_REQUEST_DENIED));
|
||||||
writeFooter(out);
|
writeFooter(out);
|
||||||
}
|
}
|
||||||
s.close();
|
s.close();
|
||||||
return;
|
return;
|
||||||
}
|
} // end host name processing
|
||||||
|
|
||||||
boolean isValid = usingWWWProxy || usingInternalServer || isSupportedAddress(host, protocol);
|
boolean isValid = usingWWWProxy || usingInternalServer || isSupportedAddress(host, protocol);
|
||||||
if (!isValid) {
|
if (!isValid) {
|
||||||
@@ -645,18 +700,10 @@ public class I2PTunnelHTTPClient extends I2PTunnelHTTPClientBase implements Runn
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
// don't do this, it forces yet another hostname lookup,
|
line = method + ' ' + requestURI.toASCIIString() + ' ' + protocolVersion;
|
||||||
// and in all cases host was already set above
|
|
||||||
//if ((!usingWWWProxy) && (!usingInternalServer)) {
|
|
||||||
// String oldhost = host;
|
|
||||||
// host = getHostName(destination); // hide original host
|
|
||||||
// if (_log.shouldLog(Log.INFO))
|
|
||||||
// _log.info(getPrefix(requestId) + " oldhost " + oldhost + " newhost " + host + " dest " + destination);
|
|
||||||
//}
|
|
||||||
|
|
||||||
if (_log.shouldLog(Log.DEBUG)) {
|
if (_log.shouldLog(Log.DEBUG)) {
|
||||||
_log.debug(getPrefix(requestId) + "METHOD: \"" + method + "\"");
|
_log.debug(getPrefix(requestId) + "NEWREQ: \"" + line + "\"");
|
||||||
_log.debug(getPrefix(requestId) + "PROTOC: \"" + protocol + "\"");
|
|
||||||
_log.debug(getPrefix(requestId) + "HOST : \"" + host + "\"");
|
_log.debug(getPrefix(requestId) + "HOST : \"" + host + "\"");
|
||||||
_log.debug(getPrefix(requestId) + "DEST : \"" + destination + "\"");
|
_log.debug(getPrefix(requestId) + "DEST : \"" + destination + "\"");
|
||||||
}
|
}
|
||||||
@@ -763,7 +810,7 @@ public class I2PTunnelHTTPClient extends I2PTunnelHTTPClientBase implements Runn
|
|||||||
if (method == null || destination == null) {
|
if (method == null || destination == null) {
|
||||||
//l.log("No HTTP method found in the request.");
|
//l.log("No HTTP method found in the request.");
|
||||||
if (out != null) {
|
if (out != null) {
|
||||||
if (protocol != null && "http://".equals(protocol.toLowerCase(Locale.US)))
|
if (protocol != null && "http".equals(protocol.toLowerCase(Locale.US)))
|
||||||
out.write(getErrorPage("denied", ERR_REQUEST_DENIED));
|
out.write(getErrorPage("denied", ERR_REQUEST_DENIED));
|
||||||
else
|
else
|
||||||
out.write(getErrorPage("protocol", ERR_BAD_PROTOCOL));
|
out.write(getErrorPage("protocol", ERR_BAD_PROTOCOL));
|
||||||
@@ -794,11 +841,11 @@ public class I2PTunnelHTTPClient extends I2PTunnelHTTPClientBase implements Runn
|
|||||||
// Ignore all the headers
|
// Ignore all the headers
|
||||||
if (usingInternalServer) {
|
if (usingInternalServer) {
|
||||||
// disable the add form if address helper is disabled
|
// disable the add form if address helper is disabled
|
||||||
if (targetRequest.startsWith(LOCAL_SERVER + "/add?") &&
|
if (internalPath.equals("/add") &&
|
||||||
Boolean.valueOf(getTunnel().getClientOptions().getProperty(PROP_DISABLE_HELPER)).booleanValue()) {
|
Boolean.valueOf(getTunnel().getClientOptions().getProperty(PROP_DISABLE_HELPER)).booleanValue()) {
|
||||||
out.write(ERR_HELPER_DISABLED);
|
out.write(ERR_HELPER_DISABLED);
|
||||||
} else {
|
} else {
|
||||||
serveLocalFile(out, method, targetRequest, _proxyNonce);
|
LocalHTTPServer.serveLocalFile(out, method, internalPath, internalRawQuery, _proxyNonce);
|
||||||
}
|
}
|
||||||
s.close();
|
s.close();
|
||||||
return;
|
return;
|
||||||
@@ -812,9 +859,16 @@ public class I2PTunnelHTTPClient extends I2PTunnelHTTPClientBase implements Runn
|
|||||||
String addressHelper = addressHelpers.get(destination.toLowerCase(Locale.US));
|
String addressHelper = addressHelpers.get(destination.toLowerCase(Locale.US));
|
||||||
if (addressHelper != null) {
|
if (addressHelper != null) {
|
||||||
clientDest = _context.namingService().lookup(addressHelper);
|
clientDest = _context.namingService().lookup(addressHelper);
|
||||||
// remove bad entries
|
if (clientDest == null) {
|
||||||
if (clientDest == null)
|
// remove bad entries
|
||||||
addressHelpers.remove(destination.toLowerCase(Locale.US));
|
addressHelpers.remove(destination.toLowerCase(Locale.US));
|
||||||
|
if (_log.shouldLog(Log.WARN))
|
||||||
|
_log.warn(getPrefix(requestId) + "Could not find destination for " + addressHelper);
|
||||||
|
byte[] header = getErrorPage("ahelper-notfound", ERR_AHELPER_NOTFOUND);
|
||||||
|
writeErrorMessage(header, out, targetRequest, false, destination, null);
|
||||||
|
s.close();
|
||||||
|
return;
|
||||||
|
}
|
||||||
} else if ("i2p".equals(host)) {
|
} else if ("i2p".equals(host)) {
|
||||||
clientDest = null;
|
clientDest = null;
|
||||||
} else if (destination.length() == 60 && destination.toLowerCase(Locale.US).endsWith(".b32.i2p")) {
|
} else if (destination.length() == 60 && destination.toLowerCase(Locale.US).endsWith(".b32.i2p")) {
|
||||||
@@ -865,7 +919,7 @@ public class I2PTunnelHTTPClient extends I2PTunnelHTTPClientBase implements Runn
|
|||||||
if (ahelperNew && "GET".equals(method) &&
|
if (ahelperNew && "GET".equals(method) &&
|
||||||
(userAgent == null || !userAgent.startsWith("Wget")) &&
|
(userAgent == null || !userAgent.startsWith("Wget")) &&
|
||||||
!Boolean.valueOf(getTunnel().getClientOptions().getProperty(PROP_DISABLE_HELPER)).booleanValue()) {
|
!Boolean.valueOf(getTunnel().getClientOptions().getProperty(PROP_DISABLE_HELPER)).booleanValue()) {
|
||||||
writeHelperSaveForm(out, destination, ahelperKey, protocol + targetRequest);
|
writeHelperSaveForm(out, destination, ahelperKey, targetRequest);
|
||||||
s.close();
|
s.close();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -875,10 +929,7 @@ public class I2PTunnelHTTPClient extends I2PTunnelHTTPClientBase implements Runn
|
|||||||
// This also prevents the not-found error page from looking bad
|
// This also prevents the not-found error page from looking bad
|
||||||
// Syndie can't handle a redirect of a POST
|
// Syndie can't handle a redirect of a POST
|
||||||
if (ahelperPresent && !"POST".equals(method)) {
|
if (ahelperPresent && !"POST".equals(method)) {
|
||||||
String uri = protocol + targetRequest;
|
String uri = targetRequest;
|
||||||
int spc = uri.indexOf(" ");
|
|
||||||
if (spc >= 0)
|
|
||||||
uri = uri.substring(0, spc);
|
|
||||||
if (_log.shouldLog(Log.DEBUG))
|
if (_log.shouldLog(Log.DEBUG))
|
||||||
_log.debug("Auto redirecting to " + uri);
|
_log.debug("Auto redirecting to " + uri);
|
||||||
out.write(("HTTP/1.1 301 Address Helper Accepted\r\n"+
|
out.write(("HTTP/1.1 301 Address Helper Accepted\r\n"+
|
||||||
@@ -928,10 +979,6 @@ public class I2PTunnelHTTPClient extends I2PTunnelHTTPClientBase implements Runn
|
|||||||
private void writeHelperSaveForm(OutputStream out, String destination, String ahelperKey, String targetRequest) throws IOException {
|
private void writeHelperSaveForm(OutputStream out, String destination, String ahelperKey, String targetRequest) throws IOException {
|
||||||
if (out == null)
|
if (out == null)
|
||||||
return;
|
return;
|
||||||
// strip HTTP/1.1
|
|
||||||
int protopos = targetRequest.indexOf(" ");
|
|
||||||
if (protopos >= 0)
|
|
||||||
targetRequest = targetRequest.substring(0, protopos);
|
|
||||||
byte[] header = getErrorPage("ahelper-new", ERR_AHELPER_NEW);
|
byte[] header = getErrorPage("ahelper-new", ERR_AHELPER_NEW);
|
||||||
out.write(header);
|
out.write(header);
|
||||||
out.write(("<table><tr><td class=\"mediumtags\" align=\"right\">" + _("Host") + "</td><td class=\"mediumtags\">" + destination + "</td></tr>\n" +
|
out.write(("<table><tr><td class=\"mediumtags\" align=\"right\">" + _("Host") + "</td><td class=\"mediumtags\">" + destination + "</td></tr>\n" +
|
||||||
@@ -939,6 +986,7 @@ public class I2PTunnelHTTPClient extends I2PTunnelHTTPClientBase implements Runn
|
|||||||
"<textarea rows=\"1\" style=\"height: 4em; min-width: 0; min-height: 0;\" cols=\"70\" wrap=\"off\" readonly=\"readonly\" >" +
|
"<textarea rows=\"1\" style=\"height: 4em; min-width: 0; min-height: 0;\" cols=\"70\" wrap=\"off\" readonly=\"readonly\" >" +
|
||||||
ahelperKey + "</textarea></td></tr></table>\n" +
|
ahelperKey + "</textarea></td></tr></table>\n" +
|
||||||
"<hr><div class=\"formaction\">"+
|
"<hr><div class=\"formaction\">"+
|
||||||
|
// FIXME if there is a query remaining it is lost
|
||||||
"<form method=\"GET\" action=\"" + targetRequest + "\">" +
|
"<form method=\"GET\" action=\"" + targetRequest + "\">" +
|
||||||
"<button type=\"submit\" class=\"go\">" + _("Continue to {0} without saving", destination) + "</button>" +
|
"<button type=\"submit\" class=\"go\">" + _("Continue to {0} without saving", destination) + "</button>" +
|
||||||
"</form>\n<form method=\"GET\" action=\"http://" + LOCAL_SERVER + "/add\">" +
|
"</form>\n<form method=\"GET\" action=\"http://" + LOCAL_SERVER + "/add\">" +
|
||||||
@@ -1046,7 +1094,10 @@ public class I2PTunnelHTTPClient extends I2PTunnelHTTPClientBase implements Runn
|
|||||||
// we won't ever get here
|
// we won't ever get here
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void writeFooter(OutputStream out) throws IOException {
|
/**
|
||||||
|
* Public only for LocalHTTPServer, not for general use
|
||||||
|
*/
|
||||||
|
public static void writeFooter(OutputStream out) throws IOException {
|
||||||
// the css is hiding this div for now, but we'll keep it here anyway
|
// the css is hiding this div for now, but we'll keep it here anyway
|
||||||
out.write("<div class=\"proxyfooter\"><p><i>I2P HTTP Proxy Server<br>Generated on: ".getBytes());
|
out.write("<div class=\"proxyfooter\"><p><i>I2P HTTP Proxy Server<br>Generated on: ".getBytes());
|
||||||
out.write(new Date().toString().getBytes());
|
out.write(new Date().toString().getBytes());
|
||||||
@@ -1091,15 +1142,10 @@ public class I2PTunnelHTTPClient extends I2PTunnelHTTPClientBase implements Runn
|
|||||||
if (out != null) {
|
if (out != null) {
|
||||||
out.write(errMessage);
|
out.write(errMessage);
|
||||||
if (targetRequest != null) {
|
if (targetRequest != null) {
|
||||||
int protopos = targetRequest.indexOf(" ");
|
String uri = targetRequest;
|
||||||
String uri;
|
out.write("<a href=\"".getBytes());
|
||||||
if (protopos >= 0)
|
|
||||||
uri = targetRequest.substring(0, protopos);
|
|
||||||
else
|
|
||||||
uri = targetRequest;
|
|
||||||
out.write("<a href=\"http://".getBytes());
|
|
||||||
out.write(uri.getBytes());
|
out.write(uri.getBytes());
|
||||||
out.write("\">http://".getBytes());
|
out.write("\">".getBytes());
|
||||||
out.write(uri.getBytes());
|
out.write(uri.getBytes());
|
||||||
out.write("</a>".getBytes());
|
out.write("</a>".getBytes());
|
||||||
if (usingWWWProxy) {
|
if (usingWWWProxy) {
|
||||||
@@ -1193,23 +1239,9 @@ public class I2PTunnelHTTPClient extends I2PTunnelHTTPClientBase implements Runn
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
****/
|
****/
|
||||||
return protocol.toLowerCase(Locale.US).equals("http://");
|
return protocol.toLowerCase(Locale.US).equals("http");
|
||||||
}
|
}
|
||||||
|
|
||||||
private final static byte[] ERR_404 =
|
|
||||||
("HTTP/1.1 404 Not Found\r\n"+
|
|
||||||
"Content-Type: text/plain\r\n"+
|
|
||||||
"\r\n"+
|
|
||||||
"HTTP Proxy local file not found")
|
|
||||||
.getBytes();
|
|
||||||
|
|
||||||
private final static byte[] ERR_ADD =
|
|
||||||
("HTTP/1.1 409 Bad\r\n"+
|
|
||||||
"Content-Type: text/plain\r\n"+
|
|
||||||
"\r\n"+
|
|
||||||
"Add to addressbook failed - bad parameters")
|
|
||||||
.getBytes();
|
|
||||||
|
|
||||||
private final static byte[] ERR_HELPER_DISABLED =
|
private final static byte[] ERR_HELPER_DISABLED =
|
||||||
("HTTP/1.1 403 Disabled\r\n"+
|
("HTTP/1.1 403 Disabled\r\n"+
|
||||||
"Content-Type: text/plain\r\n"+
|
"Content-Type: text/plain\r\n"+
|
||||||
@@ -1218,185 +1250,127 @@ public class I2PTunnelHTTPClient extends I2PTunnelHTTPClientBase implements Runn
|
|||||||
.getBytes();
|
.getBytes();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Very simple web server.
|
* Change various parts of the URI.
|
||||||
|
* String parameters are all non-encoded.
|
||||||
*
|
*
|
||||||
* Serve local files in the docs/ directory, for CSS and images in
|
* Scheme always preserved.
|
||||||
* error pages, using the reserved address proxy.i2p
|
* Userinfo always cleared.
|
||||||
* (similar to p.p in privoxy).
|
* Host changed if non-null.
|
||||||
* This solves the problems with including links to the router console,
|
* Port changed if non-zero.
|
||||||
* as assuming the router console is at 127.0.0.1 leads to broken
|
* Path changed if non-null.
|
||||||
* links if it isn't.
|
* Query always preserved.
|
||||||
|
* Fragment always cleared.
|
||||||
*
|
*
|
||||||
* Ignore all request headers (If-Modified-Since, etc.)
|
* @since 0.9
|
||||||
*
|
|
||||||
* There is basic protection here -
|
|
||||||
* FileUtil.readFile() prevents traversal above the base directory -
|
|
||||||
* but inproxy/gateway ops would be wise to block proxy.i2p to prevent
|
|
||||||
* exposing the docs/ directory or perhaps other issues through
|
|
||||||
* uncaught vulnerabilities.
|
|
||||||
* Restrict to the /themes/ directory for now.
|
|
||||||
*
|
|
||||||
* @param targetRequest "proxy.i2p/themes/foo.png HTTP/1.1"
|
|
||||||
*/
|
*/
|
||||||
private static void serveLocalFile(OutputStream out, String method, String targetRequest, String proxyNonce) {
|
private static URI changeURI(URI uri, String host, int port, String path) throws URISyntaxException {
|
||||||
//System.err.println("targetRequest: \"" + targetRequest + "\"");
|
return new URI(uri.getScheme(),
|
||||||
// a home page message for the curious...
|
null,
|
||||||
if (targetRequest.startsWith(LOCAL_SERVER + "/ ")) {
|
host != null ? host : uri.getHost(),
|
||||||
try {
|
port != 0 ? port : uri.getPort(),
|
||||||
out.write(("HTTP/1.1 200 OK\r\nContent-Type: text/plain\r\nCache-Control: max-age=86400\r\n\r\nI2P HTTP proxy OK").getBytes());
|
path != null ? path : uri.getPath(),
|
||||||
out.flush();
|
// FIXME this breaks encoded =, &
|
||||||
} catch (IOException ioe) {}
|
uri.getQuery(),
|
||||||
return;
|
null);
|
||||||
}
|
|
||||||
if ((method.equals("GET") || method.equals("HEAD")) &&
|
|
||||||
targetRequest.startsWith(LOCAL_SERVER + "/themes/") &&
|
|
||||||
!targetRequest.contains("..")) {
|
|
||||||
int space = targetRequest.indexOf(' ');
|
|
||||||
String filename = null;
|
|
||||||
try {
|
|
||||||
filename = targetRequest.substring(LOCAL_SERVER.length() + 8, space); // "/themes/".length
|
|
||||||
} catch (IndexOutOfBoundsException ioobe) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
// theme hack
|
|
||||||
if (filename.startsWith("console/default/"))
|
|
||||||
filename = filename.replaceFirst("default", I2PAppContext.getGlobalContext().getProperty("routerconsole.theme", "light"));
|
|
||||||
File themesDir = new File(_errorDir, "themes");
|
|
||||||
File file = new File(themesDir, filename);
|
|
||||||
if (file.exists() && !file.isDirectory()) {
|
|
||||||
String type;
|
|
||||||
if (filename.endsWith(".css"))
|
|
||||||
type = "text/css";
|
|
||||||
else if (filename.endsWith(".ico"))
|
|
||||||
type = "image/x-icon";
|
|
||||||
else if (filename.endsWith(".png"))
|
|
||||||
type = "image/png";
|
|
||||||
else if (filename.endsWith(".jpg"))
|
|
||||||
type = "image/jpeg";
|
|
||||||
else type = "text/html";
|
|
||||||
try {
|
|
||||||
out.write("HTTP/1.1 200 OK\r\nContent-Type: ".getBytes());
|
|
||||||
out.write(type.getBytes());
|
|
||||||
out.write("\r\nCache-Control: max-age=86400\r\n\r\n".getBytes());
|
|
||||||
FileUtil.readFile(filename, themesDir.getAbsolutePath(), out);
|
|
||||||
} catch (IOException ioe) {}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add to addressbook (form submit)
|
|
||||||
// Parameters are url, host, dest, nonce, and master | router | private.
|
|
||||||
// Do the add and redirect.
|
|
||||||
if (targetRequest.startsWith(LOCAL_SERVER + "/add?")) {
|
|
||||||
int spc = targetRequest.indexOf(' ');
|
|
||||||
String query = targetRequest.substring(LOCAL_SERVER.length() + 5, spc); // "/add?".length()
|
|
||||||
Map<String, String> opts = new HashMap(8);
|
|
||||||
StringTokenizer tok = new StringTokenizer(query, "=&;");
|
|
||||||
while (tok.hasMoreTokens()) {
|
|
||||||
String k = tok.nextToken();
|
|
||||||
if (!tok.hasMoreTokens())
|
|
||||||
break;
|
|
||||||
String v = tok.nextToken();
|
|
||||||
opts.put(decode(k), decode(v));
|
|
||||||
}
|
|
||||||
|
|
||||||
String url = opts.get("url");
|
|
||||||
String host = opts.get("host");
|
|
||||||
String b64Dest = opts.get("dest");
|
|
||||||
String nonce = opts.get("nonce");
|
|
||||||
String book = "privatehosts.txt";
|
|
||||||
if (opts.get("master") != null)
|
|
||||||
book = "userhosts.txt";
|
|
||||||
else if (opts.get("router") != null)
|
|
||||||
book = "hosts.txt";
|
|
||||||
Destination dest = null;
|
|
||||||
if (b64Dest != null) {
|
|
||||||
try {
|
|
||||||
dest = new Destination(b64Dest);
|
|
||||||
} catch (DataFormatException dfe) {
|
|
||||||
System.err.println("Bad dest to save?" + b64Dest);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
//System.err.println("url : \"" + url + "\"");
|
|
||||||
//System.err.println("host : \"" + host + "\"");
|
|
||||||
//System.err.println("b64dest : \"" + b64Dest + "\"");
|
|
||||||
//System.err.println("book : \"" + book + "\"");
|
|
||||||
//System.err.println("nonce : \"" + nonce + "\"");
|
|
||||||
if (proxyNonce.equals(nonce) && url != null && host != null && dest != null) {
|
|
||||||
try {
|
|
||||||
NamingService ns = I2PAppContext.getGlobalContext().namingService();
|
|
||||||
Properties nsOptions = new Properties();
|
|
||||||
nsOptions.setProperty("list", book);
|
|
||||||
nsOptions.setProperty("s", _("Added via address helper"));
|
|
||||||
boolean success = ns.put(host, dest, nsOptions);
|
|
||||||
writeRedirectPage(out, success, host, book, url);
|
|
||||||
return;
|
|
||||||
} catch (IOException ioe) {}
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
out.write(ERR_ADD);
|
|
||||||
out.flush();
|
|
||||||
} catch (IOException ioe) {}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
out.write(ERR_404);
|
|
||||||
out.flush();
|
|
||||||
} catch (IOException ioe) {}
|
|
||||||
}
|
|
||||||
|
|
||||||
/** @since 0.8.7 */
|
|
||||||
private static void writeRedirectPage(OutputStream out, boolean success, String host, String book, String url) throws IOException {
|
|
||||||
out.write(("HTTP/1.1 200 OK\r\n"+
|
|
||||||
"Content-Type: text/html; charset=UTF-8\r\n"+
|
|
||||||
"\r\n"+
|
|
||||||
"<html><head>"+
|
|
||||||
"<title>" + _("Redirecting to {0}", host) + "</title>\n" +
|
|
||||||
"<link rel=\"shortcut icon\" href=\"http://proxy.i2p/themes/console/images/favicon.ico\" >\n" +
|
|
||||||
"<link href=\"http://proxy.i2p/themes/console/default/console.css\" rel=\"stylesheet\" type=\"text/css\" >\n" +
|
|
||||||
"<meta http-equiv=\"Refresh\" content=\"1; url=" + url + "\">\n" +
|
|
||||||
"</head><body>\n" +
|
|
||||||
"<div class=logo>\n" +
|
|
||||||
"<a href=\"http://127.0.0.1:7657/\" title=\"" + _("Router Console") + "\"><img src=\"http://proxy.i2p/themes/console/images/i2plogo.png\" alt=\"I2P Router Console\" border=\"0\"></a><hr>\n" +
|
|
||||||
"<a href=\"http://127.0.0.1:7657/config\">" + _("Configuration") + "</a> <a href=\"http://127.0.0.1:7657/help.jsp\">" + _("Help") + "</a> <a href=\"http://127.0.0.1:7657/susidns/index\">" + _("Addressbook") + "</a>\n" +
|
|
||||||
"</div>" +
|
|
||||||
"<div class=warning id=warning>\n" +
|
|
||||||
"<h3>" +
|
|
||||||
(success ?
|
|
||||||
_("Saved {0} to the {1} addressbook, redirecting now.", host, book) :
|
|
||||||
_("Failed to save {0} to the {1} addressbook, redirecting now.", host, book)) +
|
|
||||||
"</h3>\n<p><a href=\"" + url + "\">" +
|
|
||||||
_("Click here if you are not redirected automatically.") +
|
|
||||||
"</a></p></div>").getBytes("UTF-8"));
|
|
||||||
writeFooter(out);
|
|
||||||
out.flush();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Decode %xx encoding
|
* Replace query in the URI.
|
||||||
* @since 0.8.7
|
* Userinfo cleared if uri contained a query.
|
||||||
|
* Fragment cleared if uri contained a query.
|
||||||
|
*
|
||||||
|
* @param query an ENCODED query, removed if null
|
||||||
|
* @since 0.9
|
||||||
*/
|
*/
|
||||||
private static String decode(String s) {
|
private static URI replaceQuery(URI uri, String query) throws URISyntaxException {
|
||||||
if (!s.contains("%"))
|
URI rv = uri;
|
||||||
return s;
|
if (rv.getRawQuery() != null) {
|
||||||
StringBuilder buf = new StringBuilder(s.length());
|
rv = new URI(rv.getScheme(),
|
||||||
for (int i = 0; i < s.length(); i++) {
|
null,
|
||||||
char c = s.charAt(i);
|
uri.getHost(),
|
||||||
if (c != '%') {
|
uri.getPort(),
|
||||||
buf.append(c);
|
uri.getPath(),
|
||||||
} else {
|
null,
|
||||||
try {
|
null);
|
||||||
buf.append((char) Integer.parseInt(s.substring(++i, (++i) + 1), 16));
|
|
||||||
} catch (IndexOutOfBoundsException ioobe) {
|
|
||||||
break;
|
|
||||||
} catch (NumberFormatException nfe) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return buf.toString();
|
if (query != null) {
|
||||||
|
String newURI = rv.toASCIIString() + '?' + query;
|
||||||
|
rv = new URI(newURI);
|
||||||
|
}
|
||||||
|
return rv;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove the address helper from an encoded query.
|
||||||
|
*
|
||||||
|
* @param query an ENCODED query, removed if null
|
||||||
|
* @return rv[0] is ENCODED query with helper removed, non-null but possibly empty;
|
||||||
|
* rv[1] is DECODED helper value, non-null but possibly empty;
|
||||||
|
* rv null if no helper present
|
||||||
|
* @since 0.9
|
||||||
|
*/
|
||||||
|
private static String[] removeHelper(String query) {
|
||||||
|
int keystart = 0;
|
||||||
|
int valstart = -1;
|
||||||
|
String key = null;
|
||||||
|
for (int i = 0; i <= query.length(); i++) {
|
||||||
|
char c = i < query.length() ? query.charAt(i) : '&';
|
||||||
|
if (c == ';' || c == '&') {
|
||||||
|
// end of key or value
|
||||||
|
if (valstart < 0)
|
||||||
|
key = query.substring(keystart, i);
|
||||||
|
String decodedKey = LocalHTTPServer.decode(key);
|
||||||
|
if (decodedKey.equals(HELPER_PARAM)) {
|
||||||
|
String newQuery = keystart > 0 ? query.substring(0, keystart - 1) : "";
|
||||||
|
if (i < query.length() - 1) {
|
||||||
|
if (keystart > 0)
|
||||||
|
newQuery += query.substring(i);
|
||||||
|
else
|
||||||
|
newQuery += query.substring(i + 1);
|
||||||
|
}
|
||||||
|
String value = valstart >= 0 ? query.substring(valstart, i) : "";
|
||||||
|
String helperValue = LocalHTTPServer.decode(value);
|
||||||
|
return new String[] { newQuery, helperValue };
|
||||||
|
}
|
||||||
|
keystart = i + 1;
|
||||||
|
valstart = -1;
|
||||||
|
} else if (c == '=') {
|
||||||
|
// end of key
|
||||||
|
key = query.substring(keystart, i);
|
||||||
|
valstart = i + 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/****
|
||||||
|
private static String[] tests = {
|
||||||
|
"", "foo", "foo=bar", "&", "&=&", "===", "&&",
|
||||||
|
"i2paddresshelper=foo",
|
||||||
|
"i2paddresshelpe=foo",
|
||||||
|
"2paddresshelper=foo",
|
||||||
|
"i2paddresshelper=%66oo",
|
||||||
|
"%692paddresshelper=foo",
|
||||||
|
"i2paddresshelper=foo&a=b",
|
||||||
|
"a=b&i2paddresshelper=foo",
|
||||||
|
"a=b&i2paddresshelper&c=d",
|
||||||
|
"a=b&i2paddresshelper=foo&c=d",
|
||||||
|
"a=b;i2paddresshelper=foo;c=d",
|
||||||
|
"a=b&i2paddresshelper=foo&c"
|
||||||
|
};
|
||||||
|
|
||||||
|
public static void main(String[] args) {
|
||||||
|
for (int i = 0; i < tests.length; i++) {
|
||||||
|
String[] s = removeHelper(tests[i]);
|
||||||
|
if (s != null)
|
||||||
|
System.out.println("Test \"" + tests[i] + "\" q=\"" + s[0] + "\" h=\"" + s[1] + "\"");
|
||||||
|
else
|
||||||
|
System.out.println("Test \"" + tests[i] + "\" no match");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
****/
|
||||||
|
|
||||||
|
/** */
|
||||||
private static final String BUNDLE_NAME = "net.i2p.i2ptunnel.web.messages";
|
private static final String BUNDLE_NAME = "net.i2p.i2ptunnel.web.messages";
|
||||||
|
|
||||||
/** lang in routerconsole.lang property, else current locale */
|
/** lang in routerconsole.lang property, else current locale */
|
||||||
|
@@ -0,0 +1,247 @@
|
|||||||
|
/* I2PTunnel is GPL'ed (with the exception mentioned in I2PTunnel.java)
|
||||||
|
* (c) 2003 - 2004 mihi
|
||||||
|
*/
|
||||||
|
package net.i2p.i2ptunnel.localServer;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.OutputStream;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Properties;
|
||||||
|
import java.util.StringTokenizer;
|
||||||
|
|
||||||
|
import net.i2p.I2PAppContext;
|
||||||
|
import net.i2p.client.naming.NamingService;
|
||||||
|
import net.i2p.data.DataFormatException;
|
||||||
|
import net.i2p.data.Destination;
|
||||||
|
import net.i2p.i2ptunnel.I2PTunnelHTTPClient;
|
||||||
|
import net.i2p.util.FileUtil;
|
||||||
|
import net.i2p.util.Log;
|
||||||
|
import net.i2p.util.Translate;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Very simple web server.
|
||||||
|
*
|
||||||
|
* Serve local files in the docs/ directory, for CSS and images in
|
||||||
|
* error pages, using the reserved address proxy.i2p
|
||||||
|
* (similar to p.p in privoxy).
|
||||||
|
* This solves the problems with including links to the router console,
|
||||||
|
* as assuming the router console is at 127.0.0.1 leads to broken
|
||||||
|
* links if it isn't.
|
||||||
|
*
|
||||||
|
* @since 0.7.6, moved from I2PTunnelHTTPClient in 0.9
|
||||||
|
*/
|
||||||
|
public abstract class LocalHTTPServer {
|
||||||
|
|
||||||
|
private final static byte[] ERR_404 =
|
||||||
|
("HTTP/1.1 404 Not Found\r\n"+
|
||||||
|
"Content-Type: text/plain\r\n"+
|
||||||
|
"\r\n"+
|
||||||
|
"HTTP Proxy local file not found")
|
||||||
|
.getBytes();
|
||||||
|
|
||||||
|
private final static byte[] ERR_ADD =
|
||||||
|
("HTTP/1.1 409 Bad\r\n"+
|
||||||
|
"Content-Type: text/plain\r\n"+
|
||||||
|
"\r\n"+
|
||||||
|
"Add to addressbook failed - bad parameters")
|
||||||
|
.getBytes();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Very simple web server.
|
||||||
|
*
|
||||||
|
* Serve local files in the docs/ directory, for CSS and images in
|
||||||
|
* error pages, using the reserved address proxy.i2p
|
||||||
|
* (similar to p.p in privoxy).
|
||||||
|
* This solves the problems with including links to the router console,
|
||||||
|
* as assuming the router console is at 127.0.0.1 leads to broken
|
||||||
|
* links if it isn't.
|
||||||
|
*
|
||||||
|
* Ignore all request headers (If-Modified-Since, etc.)
|
||||||
|
*
|
||||||
|
* There is basic protection here -
|
||||||
|
* FileUtil.readFile() prevents traversal above the base directory -
|
||||||
|
* but inproxy/gateway ops would be wise to block proxy.i2p to prevent
|
||||||
|
* exposing the docs/ directory or perhaps other issues through
|
||||||
|
* uncaught vulnerabilities.
|
||||||
|
* Restrict to the /themes/ directory for now.
|
||||||
|
*
|
||||||
|
* @param targetRequest decoded path only, non-null
|
||||||
|
* @param query raw (encoded), may be null
|
||||||
|
*/
|
||||||
|
public static void serveLocalFile(OutputStream out, String method, String targetRequest, String query, String proxyNonce) {
|
||||||
|
//System.err.println("targetRequest: \"" + targetRequest + "\"");
|
||||||
|
// a home page message for the curious...
|
||||||
|
if (targetRequest.equals("/")) {
|
||||||
|
try {
|
||||||
|
out.write(("HTTP/1.1 200 OK\r\nContent-Type: text/plain\r\nCache-Control: max-age=86400\r\n\r\nI2P HTTP proxy OK").getBytes());
|
||||||
|
out.flush();
|
||||||
|
} catch (IOException ioe) {}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if ((method.equals("GET") || method.equals("HEAD")) &&
|
||||||
|
targetRequest.startsWith("/themes/") &&
|
||||||
|
!targetRequest.contains("..")) {
|
||||||
|
String filename = null;
|
||||||
|
try {
|
||||||
|
filename = targetRequest.substring(8); // "/themes/".length
|
||||||
|
} catch (IndexOutOfBoundsException ioobe) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// theme hack
|
||||||
|
if (filename.startsWith("console/default/"))
|
||||||
|
filename = filename.replaceFirst("default", I2PAppContext.getGlobalContext().getProperty("routerconsole.theme", "light"));
|
||||||
|
File themesDir = new File(I2PAppContext.getGlobalContext().getBaseDir(), "docs/themes");
|
||||||
|
File file = new File(themesDir, filename);
|
||||||
|
if (file.exists() && !file.isDirectory()) {
|
||||||
|
String type;
|
||||||
|
if (filename.endsWith(".css"))
|
||||||
|
type = "text/css";
|
||||||
|
else if (filename.endsWith(".ico"))
|
||||||
|
type = "image/x-icon";
|
||||||
|
else if (filename.endsWith(".png"))
|
||||||
|
type = "image/png";
|
||||||
|
else if (filename.endsWith(".jpg"))
|
||||||
|
type = "image/jpeg";
|
||||||
|
else type = "text/html";
|
||||||
|
try {
|
||||||
|
out.write("HTTP/1.1 200 OK\r\nContent-Type: ".getBytes());
|
||||||
|
out.write(type.getBytes());
|
||||||
|
out.write("\r\nCache-Control: max-age=86400\r\n\r\n".getBytes());
|
||||||
|
FileUtil.readFile(filename, themesDir.getAbsolutePath(), out);
|
||||||
|
} catch (IOException ioe) {}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add to addressbook (form submit)
|
||||||
|
// Parameters are url, host, dest, nonce, and master | router | private.
|
||||||
|
// Do the add and redirect.
|
||||||
|
if (targetRequest.equals("/add")) {
|
||||||
|
Map<String, String> opts = new HashMap(8);
|
||||||
|
// this only works if all keys are followed by =value
|
||||||
|
StringTokenizer tok = new StringTokenizer(query, "=&;");
|
||||||
|
while (tok.hasMoreTokens()) {
|
||||||
|
String k = tok.nextToken();
|
||||||
|
if (!tok.hasMoreTokens())
|
||||||
|
break;
|
||||||
|
String v = tok.nextToken();
|
||||||
|
opts.put(decode(k), decode(v));
|
||||||
|
}
|
||||||
|
|
||||||
|
String url = opts.get("url");
|
||||||
|
String host = opts.get("host");
|
||||||
|
String b64Dest = opts.get("dest");
|
||||||
|
String nonce = opts.get("nonce");
|
||||||
|
String book = "privatehosts.txt";
|
||||||
|
if (opts.get("master") != null)
|
||||||
|
book = "userhosts.txt";
|
||||||
|
else if (opts.get("router") != null)
|
||||||
|
book = "hosts.txt";
|
||||||
|
Destination dest = null;
|
||||||
|
if (b64Dest != null) {
|
||||||
|
try {
|
||||||
|
dest = new Destination(b64Dest);
|
||||||
|
} catch (DataFormatException dfe) {
|
||||||
|
System.err.println("Bad dest to save?" + b64Dest);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//System.err.println("url : \"" + url + "\"");
|
||||||
|
//System.err.println("host : \"" + host + "\"");
|
||||||
|
//System.err.println("b64dest : \"" + b64Dest + "\"");
|
||||||
|
//System.err.println("book : \"" + book + "\"");
|
||||||
|
//System.err.println("nonce : \"" + nonce + "\"");
|
||||||
|
if (proxyNonce.equals(nonce) && url != null && host != null && dest != null) {
|
||||||
|
try {
|
||||||
|
NamingService ns = I2PAppContext.getGlobalContext().namingService();
|
||||||
|
Properties nsOptions = new Properties();
|
||||||
|
nsOptions.setProperty("list", book);
|
||||||
|
nsOptions.setProperty("s", _("Added via address helper"));
|
||||||
|
boolean success = ns.put(host, dest, nsOptions);
|
||||||
|
writeRedirectPage(out, success, host, book, url);
|
||||||
|
return;
|
||||||
|
} catch (IOException ioe) {}
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
out.write(ERR_ADD);
|
||||||
|
out.flush();
|
||||||
|
} catch (IOException ioe) {}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
out.write(ERR_404);
|
||||||
|
out.flush();
|
||||||
|
} catch (IOException ioe) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @since 0.8.7 */
|
||||||
|
private static void writeRedirectPage(OutputStream out, boolean success, String host, String book, String url) throws IOException {
|
||||||
|
out.write(("HTTP/1.1 200 OK\r\n"+
|
||||||
|
"Content-Type: text/html; charset=UTF-8\r\n"+
|
||||||
|
"\r\n"+
|
||||||
|
"<html><head>"+
|
||||||
|
"<title>" + _("Redirecting to {0}", host) + "</title>\n" +
|
||||||
|
"<link rel=\"shortcut icon\" href=\"http://proxy.i2p/themes/console/images/favicon.ico\" >\n" +
|
||||||
|
"<link href=\"http://proxy.i2p/themes/console/default/console.css\" rel=\"stylesheet\" type=\"text/css\" >\n" +
|
||||||
|
"<meta http-equiv=\"Refresh\" content=\"1; url=" + url + "\">\n" +
|
||||||
|
"</head><body>\n" +
|
||||||
|
"<div class=logo>\n" +
|
||||||
|
"<a href=\"http://127.0.0.1:7657/\" title=\"" + _("Router Console") + "\"><img src=\"http://proxy.i2p/themes/console/images/i2plogo.png\" alt=\"I2P Router Console\" border=\"0\"></a><hr>\n" +
|
||||||
|
"<a href=\"http://127.0.0.1:7657/config\">" + _("Configuration") + "</a> <a href=\"http://127.0.0.1:7657/help.jsp\">" + _("Help") + "</a> <a href=\"http://127.0.0.1:7657/susidns/index\">" + _("Addressbook") + "</a>\n" +
|
||||||
|
"</div>" +
|
||||||
|
"<div class=warning id=warning>\n" +
|
||||||
|
"<h3>" +
|
||||||
|
(success ?
|
||||||
|
_("Saved {0} to the {1} addressbook, redirecting now.", host, book) :
|
||||||
|
_("Failed to save {0} to the {1} addressbook, redirecting now.", host, book)) +
|
||||||
|
"</h3>\n<p><a href=\"" + url + "\">" +
|
||||||
|
_("Click here if you are not redirected automatically.") +
|
||||||
|
"</a></p></div>").getBytes("UTF-8"));
|
||||||
|
I2PTunnelHTTPClient.writeFooter(out);
|
||||||
|
out.flush();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Decode %xx encoding
|
||||||
|
* @since 0.8.7
|
||||||
|
*/
|
||||||
|
public static String decode(String s) {
|
||||||
|
if (!s.contains("%"))
|
||||||
|
return s;
|
||||||
|
StringBuilder buf = new StringBuilder(s.length());
|
||||||
|
for (int i = 0; i < s.length(); i++) {
|
||||||
|
char c = s.charAt(i);
|
||||||
|
if (c != '%') {
|
||||||
|
buf.append(c);
|
||||||
|
} else {
|
||||||
|
try {
|
||||||
|
buf.append((char) Integer.parseInt(s.substring(++i, (++i) + 1), 16));
|
||||||
|
} catch (IndexOutOfBoundsException ioobe) {
|
||||||
|
break;
|
||||||
|
} catch (NumberFormatException nfe) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return buf.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static final String BUNDLE_NAME = "net.i2p.i2ptunnel.web.messages";
|
||||||
|
|
||||||
|
/** lang in routerconsole.lang property, else current locale */
|
||||||
|
protected static String _(String key) {
|
||||||
|
return Translate.getString(key, I2PAppContext.getGlobalContext(), BUNDLE_NAME);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** {0} */
|
||||||
|
protected static String _(String key, Object o) {
|
||||||
|
return Translate.getString(key, o, I2PAppContext.getGlobalContext(), BUNDLE_NAME);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** {0} and {1} */
|
||||||
|
protected static String _(String key, Object o, Object o2) {
|
||||||
|
return Translate.getString(key, o, o2, I2PAppContext.getGlobalContext(), BUNDLE_NAME);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@@ -1,6 +1,10 @@
|
|||||||
<%
|
<%
|
||||||
// NOTE: Do the header carefully so there is no whitespace before the <?xml... line
|
// NOTE: Do the header carefully so there is no whitespace before the <?xml... line
|
||||||
|
|
||||||
|
// http://www.crazysquirrel.com/computing/general/form-encoding.jspx
|
||||||
|
if (request.getCharacterEncoding() == null)
|
||||||
|
request.setCharacterEncoding("UTF-8");
|
||||||
|
|
||||||
%><%@page pageEncoding="UTF-8"
|
%><%@page pageEncoding="UTF-8"
|
||||||
%><%@page contentType="text/html" import="net.i2p.i2ptunnel.web.EditBean"
|
%><%@page contentType="text/html" import="net.i2p.i2ptunnel.web.EditBean"
|
||||||
%><?xml version="1.0" encoding="UTF-8"?>
|
%><?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
@@ -117,6 +117,7 @@
|
|||||||
<property name="workspace.changes.tr" value="" />
|
<property name="workspace.changes.tr" value="" />
|
||||||
<jar destfile="./jettylib/org.mortbay.jetty.jar" basedir="./build/obj" includes="**/*.class" update="true" >
|
<jar destfile="./jettylib/org.mortbay.jetty.jar" basedir="./build/obj" includes="**/*.class" update="true" >
|
||||||
<manifest>
|
<manifest>
|
||||||
|
<attribute name="Built-By" value="${build.built-by}" />
|
||||||
<attribute name="Build-Date" value="${build.timestamp}" />
|
<attribute name="Build-Date" value="${build.timestamp}" />
|
||||||
<attribute name="Base-Revision" value="${workspace.version}" />
|
<attribute name="Base-Revision" value="${workspace.version}" />
|
||||||
<attribute name="Workspace-Changes" value="${workspace.changes.tr}" />
|
<attribute name="Workspace-Changes" value="${workspace.changes.tr}" />
|
||||||
|
@@ -51,6 +51,7 @@
|
|||||||
<jar destfile="./build/mstreaming.jar" basedir="./build/obj" includes="**/*.class" >
|
<jar destfile="./build/mstreaming.jar" basedir="./build/obj" includes="**/*.class" >
|
||||||
<manifest>
|
<manifest>
|
||||||
<attribute name="Implementation-Version" value="${full.version}" />
|
<attribute name="Implementation-Version" value="${full.version}" />
|
||||||
|
<attribute name="Built-By" value="${build.built-by}" />
|
||||||
<attribute name="Build-Date" value="${build.timestamp}" />
|
<attribute name="Build-Date" value="${build.timestamp}" />
|
||||||
<attribute name="Base-Revision" value="${workspace.version}" />
|
<attribute name="Base-Revision" value="${workspace.version}" />
|
||||||
<attribute name="Workspace-Changes" value="${workspace.changes.tr}" />
|
<attribute name="Workspace-Changes" value="${workspace.changes.tr}" />
|
||||||
|
@@ -92,6 +92,7 @@
|
|||||||
<!-- DTG added in 0.8.4, not in the classpath for very old installs, before we changed wrapper.config to specify * -->
|
<!-- DTG added in 0.8.4, not in the classpath for very old installs, before we changed wrapper.config to specify * -->
|
||||||
<attribute name="Class-Path" value="i2p.jar router.jar jrobin.jar desktopgui.jar" />
|
<attribute name="Class-Path" value="i2p.jar router.jar jrobin.jar desktopgui.jar" />
|
||||||
<attribute name="Implementation-Version" value="${full.version}" />
|
<attribute name="Implementation-Version" value="${full.version}" />
|
||||||
|
<attribute name="Built-By" value="${build.built-by}" />
|
||||||
<attribute name="Build-Date" value="${build.timestamp}" />
|
<attribute name="Build-Date" value="${build.timestamp}" />
|
||||||
<attribute name="Base-Revision" value="${workspace.version}" />
|
<attribute name="Base-Revision" value="${workspace.version}" />
|
||||||
<attribute name="Workspace-Changes" value="${workspace.changes.j.tr}" />
|
<attribute name="Workspace-Changes" value="${workspace.changes.j.tr}" />
|
||||||
@@ -172,6 +173,7 @@
|
|||||||
basedir="../jsp/" excludes="web.xml, *.css, **/*.java, *.jsp, *.jsi, web-fragment.xml, web-out.xml">
|
basedir="../jsp/" excludes="web.xml, *.css, **/*.java, *.jsp, *.jsi, web-fragment.xml, web-out.xml">
|
||||||
<manifest>
|
<manifest>
|
||||||
<attribute name="Implementation-Version" value="${full.version}" />
|
<attribute name="Implementation-Version" value="${full.version}" />
|
||||||
|
<attribute name="Built-By" value="${build.built-by}" />
|
||||||
<attribute name="Build-Date" value="${build.timestamp}" />
|
<attribute name="Build-Date" value="${build.timestamp}" />
|
||||||
<attribute name="Base-Revision" value="${workspace.version}" />
|
<attribute name="Base-Revision" value="${workspace.version}" />
|
||||||
<attribute name="Workspace-Changes" value="${workspace.changes.w.tr}" />
|
<attribute name="Workspace-Changes" value="${workspace.changes.w.tr}" />
|
||||||
|
@@ -52,7 +52,7 @@ public class ConfigClientsHelper extends HelperBase {
|
|||||||
if ((mode == 0 && disabled) ||
|
if ((mode == 0 && disabled) ||
|
||||||
(mode == 1 && (!disabled) && (!ssl)) ||
|
(mode == 1 && (!disabled) && (!ssl)) ||
|
||||||
(mode == 2 && (!disabled) && ssl))
|
(mode == 2 && (!disabled) && ssl))
|
||||||
return "checked=\"true\"";
|
return "checked=\"checked\"";
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -60,7 +60,7 @@ public class ConfigClientsHelper extends HelperBase {
|
|||||||
public String getAuth() {
|
public String getAuth() {
|
||||||
boolean enabled = _context.getBooleanProperty(PROP_AUTH);
|
boolean enabled = _context.getBooleanProperty(PROP_AUTH);
|
||||||
if (enabled)
|
if (enabled)
|
||||||
return "checked=\"true\"";
|
return "checked=\"checked\"";
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -253,9 +253,9 @@ public class ConfigClientsHelper extends HelperBase {
|
|||||||
}
|
}
|
||||||
buf.append("</td><td align=\"center\" width=\"10%\"><input type=\"checkbox\" class=\"optbox\" name=\"").append(index).append(".enabled\" value=\"true\" ");
|
buf.append("</td><td align=\"center\" width=\"10%\"><input type=\"checkbox\" class=\"optbox\" name=\"").append(index).append(".enabled\" value=\"true\" ");
|
||||||
if (enabled) {
|
if (enabled) {
|
||||||
buf.append("checked=\"true\" ");
|
buf.append("checked=\"checked\" ");
|
||||||
if (ro)
|
if (ro)
|
||||||
buf.append("disabled=\"true\" ");
|
buf.append("disabled=\"disabled\" ");
|
||||||
}
|
}
|
||||||
buf.append("></td><td align=\"center\" width=\"15%\">");
|
buf.append("></td><td align=\"center\" width=\"15%\">");
|
||||||
// The icons were way too much, so there's an X in each button class,
|
// The icons were way too much, so there's an X in each button class,
|
||||||
|
@@ -80,7 +80,7 @@ public class ConfigLoggingHelper extends HelperBase {
|
|||||||
String l = levels[i];
|
String l = levels[i];
|
||||||
buf.append("<option value=\"").append(l).append('\"');
|
buf.append("<option value=\"").append(l).append('\"');
|
||||||
if (l.equals(cur))
|
if (l.equals(cur))
|
||||||
buf.append(" selected=\"true\"");
|
buf.append(" selected=\"selected\"");
|
||||||
buf.append('>').append(_(l)).append("</option>\n");
|
buf.append('>').append(_(l)).append("</option>\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -121,7 +121,7 @@ public class ConfigLoggingHelper extends HelperBase {
|
|||||||
|
|
||||||
StringBuilder buf = new StringBuilder(65536);
|
StringBuilder buf = new StringBuilder(65536);
|
||||||
buf.append("<select name=\"newlogclass\">\n" +
|
buf.append("<select name=\"newlogclass\">\n" +
|
||||||
"<option value=\"\" selected=\"true\">")
|
"<option value=\"\" selected=\"selected\">")
|
||||||
.append(_("Select a class to add"))
|
.append(_("Select a class to add"))
|
||||||
.append("</option>\n");
|
.append("</option>\n");
|
||||||
|
|
||||||
|
@@ -20,8 +20,8 @@ public class ConfigNetHelper extends HelperBase {
|
|||||||
public final static String PROP_I2NP_NTCP_PORT = "i2np.ntcp.port";
|
public final static String PROP_I2NP_NTCP_PORT = "i2np.ntcp.port";
|
||||||
public final static String PROP_I2NP_NTCP_AUTO_PORT = "i2np.ntcp.autoport";
|
public final static String PROP_I2NP_NTCP_AUTO_PORT = "i2np.ntcp.autoport";
|
||||||
public final static String PROP_I2NP_NTCP_AUTO_IP = "i2np.ntcp.autoip";
|
public final static String PROP_I2NP_NTCP_AUTO_IP = "i2np.ntcp.autoip";
|
||||||
private final static String CHECKED = " checked=\"true\" ";
|
private final static String CHECKED = " checked=\"checked\" ";
|
||||||
private final static String DISABLED = " disabled=\"true\" ";
|
private final static String DISABLED = " disabled=\"disabled\" ";
|
||||||
|
|
||||||
public String getUdphostname() {
|
public String getUdphostname() {
|
||||||
return _context.getProperty(UDPTransport.PROP_EXTERNAL_HOST, "");
|
return _context.getProperty(UDPTransport.PROP_EXTERNAL_HOST, "");
|
||||||
@@ -250,7 +250,7 @@ public class ConfigNetHelper extends HelperBase {
|
|||||||
}
|
}
|
||||||
buf.append("<option style=\"text-align: right;\" value=\"").append(val).append("\" ");
|
buf.append("<option style=\"text-align: right;\" value=\"").append(val).append("\" ");
|
||||||
if (pct == val) {
|
if (pct == val) {
|
||||||
buf.append("selected=\"true\" ");
|
buf.append("selected=\"selected\" ");
|
||||||
found = true;
|
found = true;
|
||||||
}
|
}
|
||||||
buf.append(">").append(val).append("%</option>\n");
|
buf.append(">").append(val).append("%</option>\n");
|
||||||
|
@@ -56,7 +56,7 @@ public class ConfigReseedHelper extends HelperBase {
|
|||||||
if ((mode == 0 && (!disabled) && (!required)) ||
|
if ((mode == 0 && (!disabled) && (!required)) ||
|
||||||
(mode == 1 && (!disabled) && required) ||
|
(mode == 1 && (!disabled) && required) ||
|
||||||
(mode == 2 && disabled))
|
(mode == 2 && disabled))
|
||||||
return "checked=\"true\"";
|
return "checked=\"checked\"";
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -82,7 +82,7 @@ public class ConfigReseedHelper extends HelperBase {
|
|||||||
private String checked(String prop) {
|
private String checked(String prop) {
|
||||||
boolean enabled = _context.getBooleanProperty(prop);
|
boolean enabled = _context.getBooleanProperty(prop);
|
||||||
if (enabled)
|
if (enabled)
|
||||||
return "checked=\"true\"";
|
return "checked=\"checked\"";
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -59,8 +59,16 @@ public class ConfigStatsHelper extends HelperBase {
|
|||||||
_filters.add(tok.nextToken().trim());
|
_filters.add(tok.nextToken().trim());
|
||||||
}
|
}
|
||||||
|
|
||||||
public ConfigStatsHelper() {}
|
/**
|
||||||
|
* Just hide for everybody unless already set.
|
||||||
|
* To enable set advanced config stat.logFilters=foo before starting...
|
||||||
|
* it has to be set at startup anyway for logging to be enabled at all
|
||||||
|
* @since 0.9
|
||||||
|
*/
|
||||||
|
public boolean shouldShowLog() {
|
||||||
|
return !_filters.isEmpty();
|
||||||
|
}
|
||||||
|
|
||||||
public String getFilename() { return _context.statManager().getStatFile(); }
|
public String getFilename() { return _context.statManager().getStatFile(); }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@@ -172,7 +172,7 @@ public class ConfigTunnelsHelper extends HelperBase {
|
|||||||
if (!props.isEmpty()) {
|
if (!props.isEmpty()) {
|
||||||
buf.append("<tr><td align=\"right\" class=\"mediumtags\">" + _("Inbound options") + ":</td>\n" +
|
buf.append("<tr><td align=\"right\" class=\"mediumtags\">" + _("Inbound options") + ":</td>\n" +
|
||||||
"<td colspan=\"2\" align=\"center\"><input name=\"").append(index);
|
"<td colspan=\"2\" align=\"center\"><input name=\"").append(index);
|
||||||
buf.append(".inboundOptions\" type=\"text\" size=\"32\" disabled=\"true\" " +
|
buf.append(".inboundOptions\" type=\"text\" size=\"32\" disabled=\"disabled\" " +
|
||||||
"value=\"");
|
"value=\"");
|
||||||
for (Iterator iter = props.keySet().iterator(); iter.hasNext(); ) {
|
for (Iterator iter = props.keySet().iterator(); iter.hasNext(); ) {
|
||||||
String prop = (String)iter.next();
|
String prop = (String)iter.next();
|
||||||
@@ -185,7 +185,7 @@ public class ConfigTunnelsHelper extends HelperBase {
|
|||||||
if (!props.isEmpty()) {
|
if (!props.isEmpty()) {
|
||||||
buf.append("<tr><td align=\"right\" class=\"mediumtags\">" + _("Outbound options") + ":</td>\n" +
|
buf.append("<tr><td align=\"right\" class=\"mediumtags\">" + _("Outbound options") + ":</td>\n" +
|
||||||
"<td colspan=\"2\" align=\"center\"><input name=\"").append(index);
|
"<td colspan=\"2\" align=\"center\"><input name=\"").append(index);
|
||||||
buf.append(".outboundOptions\" type=\"text\" size=\"32\" disabled=\"true\" " +
|
buf.append(".outboundOptions\" type=\"text\" size=\"32\" disabled=\"disabled\" " +
|
||||||
"value=\"");
|
"value=\"");
|
||||||
for (Iterator iter = props.keySet().iterator(); iter.hasNext(); ) {
|
for (Iterator iter = props.keySet().iterator(); iter.hasNext(); ) {
|
||||||
String prop = (String)iter.next();
|
String prop = (String)iter.next();
|
||||||
@@ -205,7 +205,7 @@ public class ConfigTunnelsHelper extends HelperBase {
|
|||||||
for (int i = min; i <= max; i++) {
|
for (int i = min; i <= max; i++) {
|
||||||
buf.append("<option value=\"").append(i).append("\" ");
|
buf.append("<option value=\"").append(i).append("\" ");
|
||||||
if (i == now)
|
if (i == now)
|
||||||
buf.append("selected=\"true\" ");
|
buf.append("selected=\"selected\" ");
|
||||||
buf.append(">").append(ngettext(DUMMY1 + name, DUMMY2 + name + 's', i));
|
buf.append(">").append(ngettext(DUMMY1 + name, DUMMY2 + name + 's', i));
|
||||||
buf.append("</option>\n");
|
buf.append("</option>\n");
|
||||||
}
|
}
|
||||||
|
@@ -14,7 +14,7 @@ public class ConfigUIHelper extends HelperBase {
|
|||||||
for (String theme : themes) {
|
for (String theme : themes) {
|
||||||
buf.append("<input type=\"radio\" class=\"optbox\" name=\"theme\" ");
|
buf.append("<input type=\"radio\" class=\"optbox\" name=\"theme\" ");
|
||||||
if (theme.equals(current))
|
if (theme.equals(current))
|
||||||
buf.append("checked=\"true\" ");
|
buf.append("checked=\"checked\" ");
|
||||||
buf.append("value=\"").append(theme).append("\">").append(_(theme)).append("<br>\n");
|
buf.append("value=\"").append(theme).append("\">").append(_(theme)).append("<br>\n");
|
||||||
}
|
}
|
||||||
return buf.toString();
|
return buf.toString();
|
||||||
@@ -73,7 +73,7 @@ public class ConfigUIHelper extends HelperBase {
|
|||||||
// we use "lang" so it is set automagically in CSSHelper
|
// we use "lang" so it is set automagically in CSSHelper
|
||||||
buf.append("<input type=\"radio\" class=\"optbox\" name=\"lang\" ");
|
buf.append("<input type=\"radio\" class=\"optbox\" name=\"lang\" ");
|
||||||
if (langs[i].equals(current))
|
if (langs[i].equals(current))
|
||||||
buf.append("checked=\"true\" ");
|
buf.append("checked=\"checked\" ");
|
||||||
buf.append("value=\"").append(langs[i]).append("\">")
|
buf.append("value=\"").append(langs[i]).append("\">")
|
||||||
.append("<img height=\"11\" width=\"16\" alt=\"\" src=\"/flags.jsp?c=").append(flags[i]).append("\"> ")
|
.append("<img height=\"11\" width=\"16\" alt=\"\" src=\"/flags.jsp?c=").append(flags[i]).append("\"> ")
|
||||||
.append(_(xlangs[i])).append("<br>\n");
|
.append(_(xlangs[i])).append("<br>\n");
|
||||||
|
@@ -75,7 +75,7 @@ public class ConfigUpdateHelper extends HelperBase {
|
|||||||
public String getUpdateThroughProxy() {
|
public String getUpdateThroughProxy() {
|
||||||
String proxy = _context.getProperty(ConfigUpdateHandler.PROP_SHOULD_PROXY, ConfigUpdateHandler.DEFAULT_SHOULD_PROXY);
|
String proxy = _context.getProperty(ConfigUpdateHandler.PROP_SHOULD_PROXY, ConfigUpdateHandler.DEFAULT_SHOULD_PROXY);
|
||||||
if (Boolean.valueOf(proxy).booleanValue())
|
if (Boolean.valueOf(proxy).booleanValue())
|
||||||
return "<input type=\"checkbox\" class=\"optbox\" value=\"true\" name=\"updateThroughProxy\" checked=\"true\" >";
|
return "<input type=\"checkbox\" class=\"optbox\" value=\"true\" name=\"updateThroughProxy\" checked=\"checked\" >";
|
||||||
else
|
else
|
||||||
return "<input type=\"checkbox\" class=\"optbox\" value=\"true\" name=\"updateThroughProxy\" >";
|
return "<input type=\"checkbox\" class=\"optbox\" value=\"true\" name=\"updateThroughProxy\" >";
|
||||||
}
|
}
|
||||||
@@ -83,7 +83,7 @@ public class ConfigUpdateHelper extends HelperBase {
|
|||||||
public String getUpdateUnsigned() {
|
public String getUpdateUnsigned() {
|
||||||
String foo = _context.getProperty(ConfigUpdateHandler.PROP_UPDATE_UNSIGNED);
|
String foo = _context.getProperty(ConfigUpdateHandler.PROP_UPDATE_UNSIGNED);
|
||||||
if (Boolean.valueOf(foo).booleanValue())
|
if (Boolean.valueOf(foo).booleanValue())
|
||||||
return "<input type=\"checkbox\" class=\"optbox\" value=\"true\" name=\"updateUnsigned\" checked=\"true\" >";
|
return "<input type=\"checkbox\" class=\"optbox\" value=\"true\" name=\"updateUnsigned\" checked=\"checked\" >";
|
||||||
else
|
else
|
||||||
return "<input type=\"checkbox\" class=\"optbox\" value=\"true\" name=\"updateUnsigned\" >";
|
return "<input type=\"checkbox\" class=\"optbox\" value=\"true\" name=\"updateUnsigned\" >";
|
||||||
}
|
}
|
||||||
@@ -106,7 +106,7 @@ public class ConfigUpdateHelper extends HelperBase {
|
|||||||
for (int i = 0; i < PERIODS.length; i++) {
|
for (int i = 0; i < PERIODS.length; i++) {
|
||||||
buf.append("<option value=\"").append(PERIODS[i]);
|
buf.append("<option value=\"").append(PERIODS[i]);
|
||||||
if (PERIODS[i] == ms)
|
if (PERIODS[i] == ms)
|
||||||
buf.append("\" selected=\"true");
|
buf.append("\" selected=\"selected");
|
||||||
|
|
||||||
if (PERIODS[i] == -1)
|
if (PERIODS[i] == -1)
|
||||||
buf.append("\">" + _("Never") + "</option>\n");
|
buf.append("\">" + _("Never") + "</option>\n");
|
||||||
@@ -128,22 +128,22 @@ public class ConfigUpdateHelper extends HelperBase {
|
|||||||
|
|
||||||
buf.append("<option value=\"notify\"");
|
buf.append("<option value=\"notify\"");
|
||||||
if ("notify".equals(policy) || _dontInstall)
|
if ("notify".equals(policy) || _dontInstall)
|
||||||
buf.append(" selected=\"true\"");
|
buf.append(" selected=\"selected\"");
|
||||||
buf.append('>').append(_("Notify only")).append("</option>");
|
buf.append('>').append(_("Notify only")).append("</option>");
|
||||||
|
|
||||||
buf.append("<option value=\"download\"");
|
buf.append("<option value=\"download\"");
|
||||||
if (_dontInstall)
|
if (_dontInstall)
|
||||||
buf.append(" disabled=\"true\"");
|
buf.append(" disabled=\"disabled\"");
|
||||||
else if ("download".equals(policy))
|
else if ("download".equals(policy))
|
||||||
buf.append(" selected=\"true\"");
|
buf.append(" selected=\"selected\"");
|
||||||
buf.append('>').append(_("Download and verify only")).append("</option>");
|
buf.append('>').append(_("Download and verify only")).append("</option>");
|
||||||
|
|
||||||
if (_context.hasWrapper()) {
|
if (_context.hasWrapper()) {
|
||||||
buf.append("<option value=\"install\"");
|
buf.append("<option value=\"install\"");
|
||||||
if (_dontInstall)
|
if (_dontInstall)
|
||||||
buf.append(" disabled=\"true\"");
|
buf.append(" disabled=\"disabled\"");
|
||||||
else if ("install".equals(policy))
|
else if ("install".equals(policy))
|
||||||
buf.append(" selected=\"true\"");
|
buf.append(" selected=\"selected\"");
|
||||||
buf.append('>').append(_("Download, verify, and restart")).append("</option>");
|
buf.append('>').append(_("Download, verify, and restart")).append("</option>");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -18,6 +18,7 @@ import java.util.jar.Manifest;
|
|||||||
|
|
||||||
import net.i2p.crypto.SHA256Generator;
|
import net.i2p.crypto.SHA256Generator;
|
||||||
import net.i2p.data.DataHelper;
|
import net.i2p.data.DataHelper;
|
||||||
|
import net.i2p.util.FileUtil;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Dump info on jars and wars
|
* Dump info on jars and wars
|
||||||
@@ -29,7 +30,7 @@ public class FileDumpHelper extends HelperBase {
|
|||||||
public String getFileSummary() {
|
public String getFileSummary() {
|
||||||
StringBuilder buf = new StringBuilder(16*1024);
|
StringBuilder buf = new StringBuilder(16*1024);
|
||||||
buf.append("<table><tr><th>File</th><th>Size</th><th>Date</th><th>SHA 256</th><th>Revision</th>" +
|
buf.append("<table><tr><th>File</th><th>Size</th><th>Date</th><th>SHA 256</th><th>Revision</th>" +
|
||||||
"<th>JDK</th><th>Built</th><th>Mods</th></tr>");
|
"<th>JDK</th><th>Built</th><th>By</th><th>Mods</th></tr>");
|
||||||
|
|
||||||
// jars added in wrapper.config
|
// jars added in wrapper.config
|
||||||
URLClassLoader urlClassLoader = (URLClassLoader) ClassLoader.getSystemClassLoader();
|
URLClassLoader urlClassLoader = (URLClassLoader) ClassLoader.getSystemClassLoader();
|
||||||
@@ -95,7 +96,9 @@ public class FileDumpHelper extends HelperBase {
|
|||||||
buf.append((new Date(mod)).toString());
|
buf.append((new Date(mod)).toString());
|
||||||
else
|
else
|
||||||
buf.append("<font color=\"red\">Not found</font>");
|
buf.append("<font color=\"red\">Not found</font>");
|
||||||
buf.append("</td><td>");
|
buf.append("</td><td align=\"center\">");
|
||||||
|
if (mod > 0 && !FileUtil.verifyZip(f))
|
||||||
|
buf.append("<font color=\"red\">CORRUPT</font><br>");
|
||||||
byte[] hash = sha256(f);
|
byte[] hash = sha256(f);
|
||||||
if (hash != null) {
|
if (hash != null) {
|
||||||
byte[] hh = new byte[16];
|
byte[] hh = new byte[16];
|
||||||
@@ -132,13 +135,17 @@ public class FileDumpHelper extends HelperBase {
|
|||||||
buf.append(s);
|
buf.append(s);
|
||||||
buf.append("</td><td>");
|
buf.append("</td><td>");
|
||||||
s = getAtt(att, "Build-Date");
|
s = getAtt(att, "Build-Date");
|
||||||
|
if (s != null)
|
||||||
|
buf.append(s);
|
||||||
|
buf.append("</td><td align=\"center\">");
|
||||||
|
s = getAtt(att, "Built-By");
|
||||||
if (s != null)
|
if (s != null)
|
||||||
buf.append(s);
|
buf.append(s);
|
||||||
buf.append("</td><td><font color=\"red\">");
|
buf.append("</td><td><font color=\"red\">");
|
||||||
s = getAtt(att, "Workspace-Changes");
|
s = getAtt(att, "Workspace-Changes");
|
||||||
if (s != null)
|
if (s != null)
|
||||||
buf.append(s.replace(",", "<br>"));
|
buf.append(s.replace(",", "<br>"));
|
||||||
buf.append("</font></td>");
|
buf.append("</font></td></tr>\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
private static byte[] sha256(File f) {
|
private static byte[] sha256(File f) {
|
||||||
|
@@ -20,6 +20,8 @@ public class GraphHelper extends FormHandler {
|
|||||||
private int _height;
|
private int _height;
|
||||||
private int _refreshDelaySeconds;
|
private int _refreshDelaySeconds;
|
||||||
private boolean _persistent;
|
private boolean _persistent;
|
||||||
|
private String _stat;
|
||||||
|
private int _end;
|
||||||
|
|
||||||
private static final String PROP_X = "routerconsole.graphX";
|
private static final String PROP_X = "routerconsole.graphX";
|
||||||
private static final String PROP_Y = "routerconsole.graphY";
|
private static final String PROP_Y = "routerconsole.graphY";
|
||||||
@@ -32,6 +34,10 @@ public class GraphHelper extends FormHandler {
|
|||||||
private static final int DEFAULT_PERIODS = 60;
|
private static final int DEFAULT_PERIODS = 60;
|
||||||
static final int MAX_X = 2048;
|
static final int MAX_X = 2048;
|
||||||
static final int MAX_Y = 1024;
|
static final int MAX_Y = 1024;
|
||||||
|
private static final int MIN_X = 200;
|
||||||
|
private static final int MIN_Y = 60;
|
||||||
|
private static final int MIN_C = 20;
|
||||||
|
private static final int MAX_C = SummaryListener.MAX_ROWS;
|
||||||
private static final int MIN_REFRESH = 15;
|
private static final int MIN_REFRESH = 15;
|
||||||
|
|
||||||
/** set the defaults after we have a context */
|
/** set the defaults after we have a context */
|
||||||
@@ -64,17 +70,45 @@ public class GraphHelper extends FormHandler {
|
|||||||
public void storeWriter(Writer out) { _out = out; }
|
public void storeWriter(Writer out) { _out = out; }
|
||||||
|
|
||||||
public void setPeriodCount(String str) {
|
public void setPeriodCount(String str) {
|
||||||
try { _periodCount = Integer.parseInt(str); } catch (NumberFormatException nfe) {}
|
setC(str);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setShowEvents(boolean b) { _showEvents = b; }
|
/** @since 0.9 */
|
||||||
|
public void setE(String str) {
|
||||||
|
try {
|
||||||
|
_end = Math.max(0, Integer.parseInt(str));
|
||||||
|
} catch (NumberFormatException nfe) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @since 0.9 shorter parameter */
|
||||||
|
public void setC(String str) {
|
||||||
|
try {
|
||||||
|
_periodCount = Math.max(MIN_C, Math.min(Integer.parseInt(str), MAX_C));
|
||||||
|
} catch (NumberFormatException nfe) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setShowEvents(String b) { _showEvents = !"false".equals(b); }
|
||||||
|
|
||||||
public void setHeight(String str) {
|
public void setHeight(String str) {
|
||||||
try { _height = Math.min(Integer.parseInt(str), MAX_Y); } catch (NumberFormatException nfe) {}
|
setH(str);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @since 0.9 shorter parameter */
|
||||||
|
public void setH(String str) {
|
||||||
|
try {
|
||||||
|
_height = Math.max(MIN_Y, Math.min(Integer.parseInt(str), MAX_Y));
|
||||||
|
} catch (NumberFormatException nfe) {}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setWidth(String str) {
|
public void setWidth(String str) {
|
||||||
try { _width = Math.min(Integer.parseInt(str), MAX_X); } catch (NumberFormatException nfe) {}
|
setW(str);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @since 0.9 shorter parameter */
|
||||||
|
public void setW(String str) {
|
||||||
|
try {
|
||||||
|
_width = Math.max(MIN_X, Math.min(Integer.parseInt(str), MAX_X));
|
||||||
|
} catch (NumberFormatException nfe) {}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setRefreshDelay(String str) {
|
public void setRefreshDelay(String str) {
|
||||||
@@ -89,6 +123,14 @@ public class GraphHelper extends FormHandler {
|
|||||||
|
|
||||||
/** @since 0.8.7 */
|
/** @since 0.8.7 */
|
||||||
public void setPersistent(String foo) { _persistent = true; }
|
public void setPersistent(String foo) { _persistent = true; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* For single stat page
|
||||||
|
* @since 0.9
|
||||||
|
*/
|
||||||
|
public void setStat(String stat) {
|
||||||
|
_stat = stat;
|
||||||
|
}
|
||||||
|
|
||||||
public String getImages() {
|
public String getImages() {
|
||||||
if (StatSummarizer.isDisabled())
|
if (StatSummarizer.isDisabled())
|
||||||
@@ -109,11 +151,11 @@ public class GraphHelper extends FormHandler {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (hasTx && hasRx && !_showEvents) {
|
if (hasTx && hasRx && !_showEvents) {
|
||||||
_out.write("<a href=\"viewstat.jsp?stat=bw.combined"
|
_out.write("<a href=\"viewstat?stat=bw.combined"
|
||||||
+ "&periodCount=" + (3 * _periodCount )
|
+ "&periodCount=" + (3 * _periodCount )
|
||||||
+ "&width=" + (3 * _width)
|
+ "&width=" + (3 * _width)
|
||||||
+ "&height=" + (3 * _height)
|
+ "&height=" + (3 * _height)
|
||||||
+ "\" target=\"_blank\">");
|
+ "\">");
|
||||||
String title = _("Combined bandwidth graph");
|
String title = _("Combined bandwidth graph");
|
||||||
_out.write("<img class=\"statimage\""
|
_out.write("<img class=\"statimage\""
|
||||||
+ " src=\"viewstat.jsp?stat=bw.combined"
|
+ " src=\"viewstat.jsp?stat=bw.combined"
|
||||||
@@ -128,14 +170,14 @@ public class GraphHelper extends FormHandler {
|
|||||||
Rate r = lsnr.getRate();
|
Rate r = lsnr.getRate();
|
||||||
// e.g. "statname for 60m"
|
// e.g. "statname for 60m"
|
||||||
String title = _("{0} for {1}", r.getRateStat().getName(), DataHelper.formatDuration2(_periodCount * r.getPeriod()));
|
String title = _("{0} for {1}", r.getRateStat().getName(), DataHelper.formatDuration2(_periodCount * r.getPeriod()));
|
||||||
_out.write("<a href=\"viewstat.jsp?stat="
|
_out.write("<a href=\"graph?stat="
|
||||||
+ r.getRateStat().getName()
|
+ r.getRateStat().getName()
|
||||||
+ "&showEvents=" + _showEvents
|
+ '.' + r.getPeriod()
|
||||||
+ "&period=" + r.getPeriod()
|
+ "&c=" + (3 * _periodCount)
|
||||||
+ "&periodCount=" + (3 * _periodCount)
|
+ "&w=" + (3 * _width)
|
||||||
+ "&width=" + (3 * _width)
|
+ "&h=" + (3 * _height)
|
||||||
+ "&height=" + (3 * _height)
|
+ (_showEvents ? "&showEvents=1" : "")
|
||||||
+ "\" target=\"_blank\">");
|
+ "\">");
|
||||||
_out.write("<img class=\"statimage\" border=\"0\""
|
_out.write("<img class=\"statimage\" border=\"0\""
|
||||||
+ " src=\"viewstat.jsp?stat="
|
+ " src=\"viewstat.jsp?stat="
|
||||||
+ r.getRateStat().getName()
|
+ r.getRateStat().getName()
|
||||||
@@ -156,6 +198,134 @@ public class GraphHelper extends FormHandler {
|
|||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* For single stat page
|
||||||
|
* @since 0.9
|
||||||
|
*/
|
||||||
|
public String getSingleStat() {
|
||||||
|
try {
|
||||||
|
if (StatSummarizer.isDisabled())
|
||||||
|
return "";
|
||||||
|
if (_stat == null) {
|
||||||
|
_out.write("No stat");
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
List<Rate> rates = StatSummarizer.instance().parseSpecs(_stat);
|
||||||
|
if (rates.size() != 1) {
|
||||||
|
_out.write("Graphs not enabled for " + _stat);
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
Rate r = rates.get(0);
|
||||||
|
_out.write("<h3>");
|
||||||
|
_out.write(_("{0} for {1}", r.getRateStat().getName(), DataHelper.formatDuration2(_periodCount * r.getPeriod())));
|
||||||
|
if (_end > 0)
|
||||||
|
_out.write(' ' + _("ending {0} ago", DataHelper.formatDuration2(_end * r.getPeriod())));
|
||||||
|
|
||||||
|
_out.write("</h3><p><img class=\"statimage\" border=\"0\""
|
||||||
|
+ " src=\"viewstat.jsp?stat="
|
||||||
|
+ r.getRateStat().getName()
|
||||||
|
+ "&showEvents=" + _showEvents
|
||||||
|
+ "&period=" + r.getPeriod()
|
||||||
|
+ "&periodCount=" + _periodCount
|
||||||
|
+ "&end=" + _end
|
||||||
|
+ "&width=" + _width
|
||||||
|
+ "&height=" + _height
|
||||||
|
+ "\"></p><p>\n");
|
||||||
|
|
||||||
|
if (_width < MAX_X && _height < MAX_Y) {
|
||||||
|
_out.write(link(_stat, _showEvents, _periodCount, _end, _width * 3 / 2, _height * 3 / 2));
|
||||||
|
_out.write(_("Larger"));
|
||||||
|
_out.write("</a> - ");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_width > MIN_X && _height > MIN_Y) {
|
||||||
|
_out.write(link(_stat, _showEvents, _periodCount, _end, _width * 2 / 3, _height * 2 / 3));
|
||||||
|
_out.write(_("Smaller"));
|
||||||
|
_out.write("</a> - ");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_height < MAX_Y) {
|
||||||
|
_out.write(link(_stat, _showEvents, _periodCount, _end, _width, _height * 3 / 2));
|
||||||
|
_out.write(_("Taller"));
|
||||||
|
_out.write("</a> - ");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_height > MIN_Y) {
|
||||||
|
_out.write(link(_stat, _showEvents, _periodCount, _end, _width, _height * 2 / 3));
|
||||||
|
_out.write(_("Shorter"));
|
||||||
|
_out.write("</a> - ");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_width < MAX_X) {
|
||||||
|
_out.write(link(_stat, _showEvents, _periodCount, _end, _width * 3 / 2, _height));
|
||||||
|
_out.write(_("Wider"));
|
||||||
|
_out.write("</a> - ");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_width > MIN_X) {
|
||||||
|
_out.write(link(_stat, _showEvents, _periodCount, _end, _width * 2 / 3, _height));
|
||||||
|
_out.write(_("Narrower"));
|
||||||
|
_out.write("</a>");
|
||||||
|
}
|
||||||
|
|
||||||
|
_out.write("<br>");
|
||||||
|
if (_periodCount < MAX_C) {
|
||||||
|
_out.write(link(_stat, _showEvents, _periodCount * 2, _end, _width, _height));
|
||||||
|
_out.write(_("Larger interval"));
|
||||||
|
_out.write("</a> - ");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_periodCount > MIN_C) {
|
||||||
|
_out.write(link(_stat, _showEvents, _periodCount / 2, _end, _width, _height));
|
||||||
|
_out.write(_("Smaller interval"));
|
||||||
|
_out.write("</a>");
|
||||||
|
}
|
||||||
|
|
||||||
|
_out.write("<br>");
|
||||||
|
if (_periodCount < MAX_C) {
|
||||||
|
_out.write(link(_stat, _showEvents, _periodCount, _end + _periodCount, _width, _height));
|
||||||
|
_out.write(_("Previous interval"));
|
||||||
|
_out.write("</a>");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_end > 0) {
|
||||||
|
int end = _end - _periodCount;
|
||||||
|
if (end <= 0)
|
||||||
|
end = 0;
|
||||||
|
if (_periodCount < MAX_C)
|
||||||
|
_out.write(" - ");
|
||||||
|
_out.write(link(_stat, _showEvents, _periodCount, end, _width, _height));
|
||||||
|
_out.write(_("Next interval"));
|
||||||
|
_out.write("</a> ");
|
||||||
|
}
|
||||||
|
|
||||||
|
_out.write("<br>");
|
||||||
|
_out.write(link(_stat, !_showEvents, _periodCount, _end, _width, _height));
|
||||||
|
_out.write(_showEvents ? _("Plot averages") : _("plot events"));
|
||||||
|
_out.write("</a>");
|
||||||
|
|
||||||
|
_out.write("</p><p><i>" + _("All times are UTC.") + "</i></p>\n");
|
||||||
|
} catch (IOException ioe) {
|
||||||
|
ioe.printStackTrace();
|
||||||
|
}
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @since 0.9 */
|
||||||
|
private static String link(String stat, boolean showEvents,
|
||||||
|
int periodCount, int end,
|
||||||
|
int width, int height) {
|
||||||
|
return
|
||||||
|
"<a href=\"graph?stat="
|
||||||
|
+ stat
|
||||||
|
+ "&c=" + periodCount
|
||||||
|
+ "&w=" + width
|
||||||
|
+ "&h=" + height
|
||||||
|
+ (end > 0 ? "&e=" + end : "")
|
||||||
|
+ (showEvents ? "&showEvents=1" : "")
|
||||||
|
+ "\">";
|
||||||
|
}
|
||||||
|
|
||||||
private static final int[] times = { 60, 2*60, 5*60, 10*60, 30*60, 60*60, -1 };
|
private static final int[] times = { 60, 2*60, 5*60, 10*60, 30*60, 60*60, -1 };
|
||||||
|
|
||||||
public String getForm() {
|
public String getForm() {
|
||||||
@@ -171,8 +341,8 @@ public class GraphHelper extends FormHandler {
|
|||||||
"<input type=\"hidden\" name=\"action\" value=\"foo\">\n" +
|
"<input type=\"hidden\" name=\"action\" value=\"foo\">\n" +
|
||||||
"<input type=\"hidden\" name=\"nonce\" value=\"" + nonce + "\" >\n");
|
"<input type=\"hidden\" name=\"nonce\" value=\"" + nonce + "\" >\n");
|
||||||
_out.write(_("Periods") + ": <input size=\"5\" style=\"text-align: right;\" type=\"text\" name=\"periodCount\" value=\"" + _periodCount + "\"><br>\n");
|
_out.write(_("Periods") + ": <input size=\"5\" style=\"text-align: right;\" type=\"text\" name=\"periodCount\" value=\"" + _periodCount + "\"><br>\n");
|
||||||
_out.write(_("Plot averages") + ": <input type=\"radio\" class=\"optbox\" name=\"showEvents\" value=\"false\" " + (_showEvents ? "" : "checked=\"true\" ") + "> ");
|
_out.write(_("Plot averages") + ": <input type=\"radio\" class=\"optbox\" name=\"showEvents\" value=\"false\" " + (_showEvents ? "" : "checked=\"checked\" ") + "> ");
|
||||||
_out.write(_("or")+ " " +_("plot events") + ": <input type=\"radio\" class=\"optbox\" name=\"showEvents\" value=\"true\" "+ (_showEvents ? "checked=\"true\" " : "") + "><br>\n");
|
_out.write(_("or")+ " " +_("plot events") + ": <input type=\"radio\" class=\"optbox\" name=\"showEvents\" value=\"true\" "+ (_showEvents ? "checked=\"checked\" " : "") + "><br>\n");
|
||||||
_out.write(_("Image sizes") + ": " + _("width") + ": <input size=\"4\" style=\"text-align: right;\" type=\"text\" name=\"width\" value=\"" + _width
|
_out.write(_("Image sizes") + ": " + _("width") + ": <input size=\"4\" style=\"text-align: right;\" type=\"text\" name=\"width\" value=\"" + _width
|
||||||
+ "\"> " + _("pixels") + ", " + _("height") + ": <input size=\"4\" style=\"text-align: right;\" type=\"text\" name=\"height\" value=\"" + _height
|
+ "\"> " + _("pixels") + ", " + _("height") + ": <input size=\"4\" style=\"text-align: right;\" type=\"text\" name=\"height\" value=\"" + _height
|
||||||
+ "\"> " + _("pixels") + "<br>\n");
|
+ "\"> " + _("pixels") + "<br>\n");
|
||||||
@@ -182,7 +352,7 @@ public class GraphHelper extends FormHandler {
|
|||||||
_out.write(Integer.toString(times[i]));
|
_out.write(Integer.toString(times[i]));
|
||||||
_out.write("\"");
|
_out.write("\"");
|
||||||
if (times[i] == _refreshDelaySeconds)
|
if (times[i] == _refreshDelaySeconds)
|
||||||
_out.write(" selected=\"true\"");
|
_out.write(" selected=\"selected\"");
|
||||||
_out.write(">");
|
_out.write(">");
|
||||||
if (times[i] > 0)
|
if (times[i] > 0)
|
||||||
_out.write(DataHelper.formatDuration2(times[i] * 1000));
|
_out.write(DataHelper.formatDuration2(times[i] * 1000));
|
||||||
@@ -195,7 +365,7 @@ public class GraphHelper extends FormHandler {
|
|||||||
" <input type=\"checkbox\" class=\"optbox\" value=\"true\" name=\"persistent\"");
|
" <input type=\"checkbox\" class=\"optbox\" value=\"true\" name=\"persistent\"");
|
||||||
boolean persistent = _context.getBooleanPropertyDefaultTrue(SummaryListener.PROP_PERSISTENT);
|
boolean persistent = _context.getBooleanPropertyDefaultTrue(SummaryListener.PROP_PERSISTENT);
|
||||||
if (persistent)
|
if (persistent)
|
||||||
_out.write(" checked=\"true\"");
|
_out.write(" checked=\"checked\"");
|
||||||
_out.write(">" +
|
_out.write(">" +
|
||||||
"<hr><div class=\"formaction\"><input type=\"submit\" class=\"acceot\" value=\"" + _("Save settings and redraw graphs") + "\"></div></form>");
|
"<hr><div class=\"formaction\"><input type=\"submit\" class=\"acceot\" value=\"" + _("Save settings and redraw graphs") + "\"></div></form>");
|
||||||
} catch (IOException ioe) {
|
} catch (IOException ioe) {
|
||||||
|
@@ -33,6 +33,7 @@ import net.i2p.data.RouterInfo;
|
|||||||
import net.i2p.router.RouterContext;
|
import net.i2p.router.RouterContext;
|
||||||
import net.i2p.router.TunnelPoolSettings;
|
import net.i2p.router.TunnelPoolSettings;
|
||||||
import net.i2p.router.networkdb.kademlia.HashDistance; // debug
|
import net.i2p.router.networkdb.kademlia.HashDistance; // debug
|
||||||
|
import net.i2p.router.networkdb.kademlia.FloodfillNetworkDatabaseFacade;
|
||||||
import net.i2p.util.HexDump; // debug
|
import net.i2p.util.HexDump; // debug
|
||||||
import net.i2p.util.ObjectCounter;
|
import net.i2p.util.ObjectCounter;
|
||||||
import net.i2p.util.OrderedProperties;
|
import net.i2p.util.OrderedProperties;
|
||||||
@@ -105,7 +106,10 @@ public class NetDbRenderer {
|
|||||||
StringBuilder buf = new StringBuilder(4*1024);
|
StringBuilder buf = new StringBuilder(4*1024);
|
||||||
buf.append("<h2>" + _("Network Database Contents") + "</h2>\n");
|
buf.append("<h2>" + _("Network Database Contents") + "</h2>\n");
|
||||||
buf.append("<a href=\"netdb\">" + _("View RouterInfo") + "</a>");
|
buf.append("<a href=\"netdb\">" + _("View RouterInfo") + "</a>");
|
||||||
buf.append("<h3>").append(_("LeaseSets")).append("</h3>\n");
|
buf.append("<h3>").append(_("LeaseSets"));
|
||||||
|
if (debug)
|
||||||
|
buf.append(" - Debug mode - Sorted by hash distance, closest first");
|
||||||
|
buf.append("</h3>\n");
|
||||||
Hash ourRKey;
|
Hash ourRKey;
|
||||||
Set<LeaseSet> leases;
|
Set<LeaseSet> leases;
|
||||||
DecimalFormat fmt;
|
DecimalFormat fmt;
|
||||||
@@ -120,15 +124,16 @@ public class NetDbRenderer {
|
|||||||
}
|
}
|
||||||
leases.addAll(_context.netDb().getLeases());
|
leases.addAll(_context.netDb().getLeases());
|
||||||
int medianCount = 0;
|
int medianCount = 0;
|
||||||
|
int rapCount = 0;
|
||||||
BigInteger median = null;
|
BigInteger median = null;
|
||||||
int c = 0;
|
int c = 0;
|
||||||
if (debug) {
|
if (debug) {
|
||||||
// Find the center of the RAP leasesets
|
// Find the center of the RAP leasesets
|
||||||
for (LeaseSet ls : leases) {
|
for (LeaseSet ls : leases) {
|
||||||
if (ls.getReceivedAsPublished())
|
if (ls.getReceivedAsPublished())
|
||||||
medianCount++;
|
rapCount++;
|
||||||
}
|
}
|
||||||
medianCount /= 2;
|
medianCount = rapCount / 2;
|
||||||
}
|
}
|
||||||
long now = _context.clock().now();
|
long now = _context.clock().now();
|
||||||
for (LeaseSet ls : leases) {
|
for (LeaseSet ls : leases) {
|
||||||
@@ -167,9 +172,10 @@ public class NetDbRenderer {
|
|||||||
if (c++ == medianCount)
|
if (c++ == medianCount)
|
||||||
median = dist;
|
median = dist;
|
||||||
}
|
}
|
||||||
buf.append(" Dist: <b>").append(fmt.format(biLog2(dist))).append("</b>");
|
buf.append(" Dist: <b>").append(fmt.format(biLog2(dist))).append("</b><br>");
|
||||||
buf.append(" RKey: ").append(ls.getRoutingKey().toBase64());
|
buf.append("Routing Key: ").append(ls.getRoutingKey().toBase64());
|
||||||
buf.append("<br>");
|
buf.append("<br>");
|
||||||
|
buf.append("Encryption Key: ").append(ls.getEncryptionKey().toBase64().substring(0, 20)).append("...<br>");
|
||||||
}
|
}
|
||||||
for (int i = 0; i < ls.getLeaseCount(); i++) {
|
for (int i = 0; i < ls.getLeaseCount(); i++) {
|
||||||
buf.append(_("Lease")).append(' ').append(i + 1).append(": " + _("Gateway") + ' ');
|
buf.append(_("Lease")).append(' ').append(i + 1).append(": " + _("Gateway") + ' ');
|
||||||
@@ -181,18 +187,23 @@ public class NetDbRenderer {
|
|||||||
buf.setLength(0);
|
buf.setLength(0);
|
||||||
}
|
}
|
||||||
if (debug) {
|
if (debug) {
|
||||||
buf.append("<p><b>Total Leasesets: " + leases.size());
|
FloodfillNetworkDatabaseFacade netdb = (FloodfillNetworkDatabaseFacade)_context.netDb();
|
||||||
buf.append("</b></p><p><b>Published (RAP) Leasesets: " + _context.netDb().getKnownLeaseSets());
|
buf.append("<p><b>Total Leasesets: ").append(leases.size());
|
||||||
|
buf.append("</b></p><p><b>Published (RAP) Leasesets: ").append(netdb.getKnownLeaseSets());
|
||||||
//buf.append("</b></p><p><b>Mod Data: " + HexDump.dump(_context.routingKeyGenerator().getModData()));
|
//buf.append("</b></p><p><b>Mod Data: " + HexDump.dump(_context.routingKeyGenerator().getModData()));
|
||||||
|
int ff = _context.peerManager().getPeersByCapability(FloodfillNetworkDatabaseFacade.CAPABILITY_FLOODFILL).size();
|
||||||
|
buf.append("</b></p><p><b>Known Floodfills: ").append(ff);
|
||||||
|
buf.append("</b></p><p><b>Currently Floodfill? ");
|
||||||
|
buf.append(netdb.floodfillEnabled() ? "yes" : "no");
|
||||||
buf.append("</b></p><p><b>Network data (only valid if floodfill):");
|
buf.append("</b></p><p><b>Network data (only valid if floodfill):");
|
||||||
//buf.append("</b></p><p><b>Center of Key Space (router hash): " + ourRKey.toBase64());
|
//buf.append("</b></p><p><b>Center of Key Space (router hash): " + ourRKey.toBase64());
|
||||||
if (median != null) {
|
if (median != null) {
|
||||||
double log2 = biLog2(median);
|
double log2 = biLog2(median);
|
||||||
buf.append("</b></p><p><b>Median distance (bits): " + fmt.format(log2));
|
buf.append("</b></p><p><b>Median distance (bits): ").append(fmt.format(log2));
|
||||||
// 3 for 8 floodfills... -1 for median
|
// 3 for 8 floodfills... -1 for median
|
||||||
int total = (int) Math.round(Math.pow(2, 3 + 256 - 1 - log2));
|
int total = (int) Math.round(Math.pow(2, 3 + 256 - 1 - log2));
|
||||||
buf.append("</b></p><p><b>Estimated total floodfills: " + total);
|
buf.append("</b></p><p><b>Estimated total floodfills: ").append(total);
|
||||||
buf.append("</b></p><p><b>Estimated network total leasesets: " + (total * leases.size() / 8));
|
buf.append("</b></p><p><b>Estimated total leasesets: ").append(total * rapCount / 8);
|
||||||
}
|
}
|
||||||
buf.append("</b></p>");
|
buf.append("</b></p>");
|
||||||
}
|
}
|
||||||
|
@@ -172,32 +172,37 @@ public class StatSummarizer implements Runnable {
|
|||||||
|
|
||||||
public boolean renderPng(Rate rate, OutputStream out) throws IOException {
|
public boolean renderPng(Rate rate, OutputStream out) throws IOException {
|
||||||
return renderPng(rate, out, GraphHelper.DEFAULT_X, GraphHelper.DEFAULT_Y,
|
return renderPng(rate, out, GraphHelper.DEFAULT_X, GraphHelper.DEFAULT_Y,
|
||||||
false, false, false, false, -1, true);
|
false, false, false, false, -1, 0, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This does the single data graphs.
|
* This does the single data graphs.
|
||||||
* For the two-data bandwidth graph see renderRatePng().
|
* For the two-data bandwidth graph see renderRatePng().
|
||||||
* Synchronized to conserve memory.
|
* Synchronized to conserve memory.
|
||||||
|
*
|
||||||
|
* @param end number of periods before now
|
||||||
* @return success
|
* @return success
|
||||||
*/
|
*/
|
||||||
public boolean renderPng(Rate rate, OutputStream out, int width, int height, boolean hideLegend,
|
public boolean renderPng(Rate rate, OutputStream out, int width, int height, boolean hideLegend,
|
||||||
boolean hideGrid, boolean hideTitle, boolean showEvents, int periodCount,
|
boolean hideGrid, boolean hideTitle, boolean showEvents, int periodCount,
|
||||||
boolean showCredit) throws IOException {
|
int end, boolean showCredit) throws IOException {
|
||||||
try {
|
try {
|
||||||
try {
|
try {
|
||||||
_sem.acquire();
|
_sem.acquire();
|
||||||
} catch (InterruptedException ie) {}
|
} catch (InterruptedException ie) {}
|
||||||
return locked_renderPng(rate, out, width, height, hideLegend, hideGrid, hideTitle, showEvents,
|
return locked_renderPng(rate, out, width, height, hideLegend, hideGrid, hideTitle, showEvents,
|
||||||
periodCount, showCredit);
|
periodCount, end, showCredit);
|
||||||
} finally {
|
} finally {
|
||||||
_sem.release();
|
_sem.release();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param end number of periods before now
|
||||||
|
*/
|
||||||
private boolean locked_renderPng(Rate rate, OutputStream out, int width, int height, boolean hideLegend,
|
private boolean locked_renderPng(Rate rate, OutputStream out, int width, int height, boolean hideLegend,
|
||||||
boolean hideGrid, boolean hideTitle, boolean showEvents, int periodCount,
|
boolean hideGrid, boolean hideTitle, boolean showEvents, int periodCount,
|
||||||
boolean showCredit) throws IOException {
|
int end, boolean showCredit) throws IOException {
|
||||||
if (width > GraphHelper.MAX_X)
|
if (width > GraphHelper.MAX_X)
|
||||||
width = GraphHelper.MAX_X;
|
width = GraphHelper.MAX_X;
|
||||||
else if (width <= 0)
|
else if (width <= 0)
|
||||||
@@ -206,9 +211,11 @@ public class StatSummarizer implements Runnable {
|
|||||||
height = GraphHelper.MAX_Y;
|
height = GraphHelper.MAX_Y;
|
||||||
else if (height <= 0)
|
else if (height <= 0)
|
||||||
height = GraphHelper.DEFAULT_Y;
|
height = GraphHelper.DEFAULT_Y;
|
||||||
|
if (end < 0)
|
||||||
|
end = 0;
|
||||||
for (SummaryListener lsnr : _listeners) {
|
for (SummaryListener lsnr : _listeners) {
|
||||||
if (lsnr.getRate().equals(rate)) {
|
if (lsnr.getRate().equals(rate)) {
|
||||||
lsnr.renderPng(out, width, height, hideLegend, hideGrid, hideTitle, showEvents, periodCount, showCredit);
|
lsnr.renderPng(out, width, height, hideLegend, hideGrid, hideTitle, showEvents, periodCount, end, showCredit);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -368,7 +375,7 @@ public class StatSummarizer implements Runnable {
|
|||||||
* @param specs statName.period,statName.period,statName.period
|
* @param specs statName.period,statName.period,statName.period
|
||||||
* @return list of Rate objects
|
* @return list of Rate objects
|
||||||
*/
|
*/
|
||||||
private List<Rate> parseSpecs(String specs) {
|
List<Rate> parseSpecs(String specs) {
|
||||||
StringTokenizer tok = new StringTokenizer(specs, ",");
|
StringTokenizer tok = new StringTokenizer(specs, ",");
|
||||||
List<Rate> rv = new ArrayList();
|
List<Rate> rv = new ArrayList();
|
||||||
while (tok.hasMoreTokens()) {
|
while (tok.hasMoreTokens()) {
|
||||||
|
@@ -55,7 +55,7 @@ class SummaryListener implements RateSummaryListener {
|
|||||||
|
|
||||||
static final int PERIODS = 60 * 24; // 1440
|
static final int PERIODS = 60 * 24; // 1440
|
||||||
private static final int MIN_ROWS = PERIODS;
|
private static final int MIN_ROWS = PERIODS;
|
||||||
private static final int MAX_ROWS = 91 * MIN_ROWS;
|
static final int MAX_ROWS = 91 * MIN_ROWS;
|
||||||
private static final long THREE_MONTHS = 91l * 24 * 60 * 60 * 1000;
|
private static final long THREE_MONTHS = 91l * 24 * 60 * 60 * 1000;
|
||||||
|
|
||||||
public SummaryListener(Rate r) {
|
public SummaryListener(Rate r) {
|
||||||
@@ -191,10 +191,15 @@ class SummaryListener implements RateSummaryListener {
|
|||||||
_db = null;
|
_db = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void renderPng(OutputStream out, int width, int height, boolean hideLegend, boolean hideGrid, boolean hideTitle, boolean showEvents, int periodCount, boolean showCredit) throws IOException {
|
/**
|
||||||
|
* @param end number of periods before now
|
||||||
|
*/
|
||||||
|
public void renderPng(OutputStream out, int width, int height, boolean hideLegend, boolean hideGrid,
|
||||||
|
boolean hideTitle, boolean showEvents, int periodCount,
|
||||||
|
int end, boolean showCredit) throws IOException {
|
||||||
if (_renderer == null || _db == null)
|
if (_renderer == null || _db == null)
|
||||||
throw new IOException("No RRD, check logs for previous errors");
|
throw new IOException("No RRD, check logs for previous errors");
|
||||||
_renderer.render(out, width, height, hideLegend, hideGrid, hideTitle, showEvents, periodCount, showCredit);
|
_renderer.render(out, width, height, hideLegend, hideGrid, hideTitle, showEvents, periodCount, end, showCredit);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void renderPng(OutputStream out) throws IOException {
|
public void renderPng(OutputStream out) throws IOException {
|
||||||
|
@@ -81,13 +81,21 @@ class SummaryRenderer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void render(OutputStream out) throws IOException { render(out, GraphHelper.DEFAULT_X, GraphHelper.DEFAULT_Y,
|
public void render(OutputStream out) throws IOException { render(out, GraphHelper.DEFAULT_X, GraphHelper.DEFAULT_Y,
|
||||||
false, false, false, false, -1, false); }
|
false, false, false, false, -1, 0, false); }
|
||||||
|
|
||||||
public void render(OutputStream out, int width, int height, boolean hideLegend, boolean hideGrid, boolean hideTitle, boolean showEvents, int periodCount, boolean showCredit) throws IOException {
|
/**
|
||||||
|
* @param endp number of periods before now
|
||||||
|
*/
|
||||||
|
public void render(OutputStream out, int width, int height, boolean hideLegend, boolean hideGrid,
|
||||||
|
boolean hideTitle, boolean showEvents, int periodCount,
|
||||||
|
int endp, boolean showCredit) throws IOException {
|
||||||
long end = _listener.now() - 75*1000;
|
long end = _listener.now() - 75*1000;
|
||||||
|
long period = _listener.getRate().getPeriod();
|
||||||
|
if (endp > 0)
|
||||||
|
end -= period * endp;
|
||||||
if (periodCount <= 0 || periodCount > _listener.getRows())
|
if (periodCount <= 0 || periodCount > _listener.getRows())
|
||||||
periodCount = _listener.getRows();
|
periodCount = _listener.getRows();
|
||||||
long start = end - _listener.getRate().getPeriod()*periodCount;
|
long start = end - (period * periodCount);
|
||||||
//long begin = System.currentTimeMillis();
|
//long begin = System.currentTimeMillis();
|
||||||
try {
|
try {
|
||||||
RrdGraphDef def = new RrdGraphDef();
|
RrdGraphDef def = new RrdGraphDef();
|
||||||
@@ -103,9 +111,9 @@ class SummaryRenderer {
|
|||||||
String p;
|
String p;
|
||||||
// we want the formatting and translation of formatDuration2(), except not zh, and not the
|
// we want the formatting and translation of formatDuration2(), except not zh, and not the
|
||||||
if (IS_WIN && "zh".equals(Messages.getLanguage(_context)))
|
if (IS_WIN && "zh".equals(Messages.getLanguage(_context)))
|
||||||
p = DataHelper.formatDuration(_listener.getRate().getPeriod());
|
p = DataHelper.formatDuration(period);
|
||||||
else
|
else
|
||||||
p = DataHelper.formatDuration2(_listener.getRate().getPeriod()).replace(" ", " ");
|
p = DataHelper.formatDuration2(period).replace(" ", " ");
|
||||||
if (showEvents)
|
if (showEvents)
|
||||||
title = name + ' ' + _("events in {0}", p);
|
title = name + ' ' + _("events in {0}", p);
|
||||||
else
|
else
|
||||||
|
@@ -134,6 +134,7 @@ public class TunnelRenderer {
|
|||||||
out.write("<div class=\"statusnotes\"><b>" + _("Inactive participating tunnels") + ": " + inactive + "</b></div>\n");
|
out.write("<div class=\"statusnotes\"><b>" + _("Inactive participating tunnels") + ": " + inactive + "</b></div>\n");
|
||||||
out.write("<div class=\"statusnotes\"><b>" + _("Lifetime bandwidth usage") + ": " + DataHelper.formatSize2(processed*1024) + "B</b></div>\n");
|
out.write("<div class=\"statusnotes\"><b>" + _("Lifetime bandwidth usage") + ": " + DataHelper.formatSize2(processed*1024) + "B</b></div>\n");
|
||||||
//renderPeers(out);
|
//renderPeers(out);
|
||||||
|
out.write("</div>");
|
||||||
}
|
}
|
||||||
|
|
||||||
private static class TunnelComparator implements Comparator<HopConfig> {
|
private static class TunnelComparator implements Comparator<HopConfig> {
|
||||||
@@ -222,7 +223,7 @@ public class TunnelRenderer {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (live <= 0)
|
if (live <= 0)
|
||||||
out.write("<div class=\"statusnotes\"><center><b>" + _("No tunnels; waiting for the grace period to end.") + "</center></b></div>\n");
|
out.write("<div class=\"statusnotes\"><center><b>" + _("No tunnels; waiting for the grace period to end.") + "</b></center></div>\n");
|
||||||
out.write("<div class=\"statusnotes\"><center><b>" + _("Lifetime bandwidth usage") + ": " +
|
out.write("<div class=\"statusnotes\"><center><b>" + _("Lifetime bandwidth usage") + ": " +
|
||||||
DataHelper.formatSize2(processedIn*1024) + "B " + _("in") + ", " +
|
DataHelper.formatSize2(processedIn*1024) + "B " + _("in") + ", " +
|
||||||
DataHelper.formatSize2(processedOut*1024) + "B " + _("out") + "</b></center></div>");
|
DataHelper.formatSize2(processedOut*1024) + "B " + _("out") + "</b></center></div>");
|
||||||
|
@@ -41,7 +41,7 @@
|
|||||||
<input type="radio" class="optbox" name="mode" value="2" <%=reseedHelper.modeChecked(2) %> >
|
<input type="radio" class="optbox" name="mode" value="2" <%=reseedHelper.modeChecked(2) %> >
|
||||||
<b><%=intl._("Use non-SSL only")%></b></td></tr>
|
<b><%=intl._("Use non-SSL only")%></b></td></tr>
|
||||||
<tr><td class="mediumtags" align="right"><b><%=intl._("Reseed URLs")%>:</b></td>
|
<tr><td class="mediumtags" align="right"><b><%=intl._("Reseed URLs")%>:</b></td>
|
||||||
<td><textarea name="reseedURL" wrap="off" spellcheck="false"><jsp:getProperty name="reseedHelper" property="reseedURL" /></textarea></td></tr>
|
<td><textarea wrap="off" name="reseedURL" cols="60" rows="7" spellcheck="false"><jsp:getProperty name="reseedHelper" property="reseedURL" /></textarea></td></tr>
|
||||||
|
|
||||||
<tr><td class="mediumtags" align="right"><b><%=intl._("Enable HTTP Proxy?")%></b></td>
|
<tr><td class="mediumtags" align="right"><b><%=intl._("Enable HTTP Proxy?")%></b></td>
|
||||||
<td><input type="checkbox" class="optbox" name="enable" value="true" <jsp:getProperty name="reseedHelper" property="enable" /> ></td></tr>
|
<td><input type="checkbox" class="optbox" name="enable" value="true" <jsp:getProperty name="reseedHelper" property="enable" /> ></td></tr>
|
||||||
|
@@ -76,10 +76,21 @@ function toggleAll(category)
|
|||||||
<h3><%=intl._("Configure I2P Stat Collection")%></h3>
|
<h3><%=intl._("Configure I2P Stat Collection")%></h3>
|
||||||
<p><%=intl._("Enable full stats?")%>
|
<p><%=intl._("Enable full stats?")%>
|
||||||
<input type="checkbox" class="optbox" name="isFull" value="true" <%
|
<input type="checkbox" class="optbox" name="isFull" value="true" <%
|
||||||
if (statshelper.getIsFull()) { %>checked="true" <% } %> >
|
if (statshelper.getIsFull()) { %>checked="checked" <% } %> >
|
||||||
(<%=intl._("change requires restart to take effect")%>)<br>
|
(<%=intl._("change requires restart to take effect")%>)<br>
|
||||||
<%=intl._("Stat file")%>: <input type="text" name="filename" value="<%=statshelper.getFilename()%>" ><br>
|
<%
|
||||||
<%=intl._("Filter")%>: (<a href="javascript:void(null);" onclick="toggleAll('*')"><%=intl._("toggle all")%></a>)<br></p>
|
|
||||||
|
// stats.log for devs only and grows without bounds, not recommended
|
||||||
|
boolean shouldShowLog = statshelper.shouldShowLog();
|
||||||
|
if (shouldShowLog) {
|
||||||
|
|
||||||
|
%><%=intl._("Stat file")%>: <input type="text" name="filename" value="<%=statshelper.getFilename()%>" ><br>
|
||||||
|
Warning - Log with care, stat file grows without limit.<br>
|
||||||
|
<%
|
||||||
|
|
||||||
|
} // shouldShowLog
|
||||||
|
|
||||||
|
%><%=intl._("Filter")%>: (<a href="javascript:void(null);" onclick="toggleAll('*')"><%=intl._("toggle all")%></a>)<br></p>
|
||||||
<div class="wideload">
|
<div class="wideload">
|
||||||
<table>
|
<table>
|
||||||
<% while (statshelper.hasMoreStats()) {
|
<% while (statshelper.hasMoreStats()) {
|
||||||
@@ -90,27 +101,51 @@ function toggleAll(category)
|
|||||||
(<a href="javascript:void(null);" onclick="toggleAll('<%=statshelper.getCurrentGroupName()%>')"><%=intl._("toggle all")%></a>)
|
(<a href="javascript:void(null);" onclick="toggleAll('<%=statshelper.getCurrentGroupName()%>')"><%=intl._("toggle all")%></a>)
|
||||||
</td></tr>
|
</td></tr>
|
||||||
<tr class="tablefooter">
|
<tr class="tablefooter">
|
||||||
<td align="center"><b><%=intl._("Log")%></b></td>
|
<%
|
||||||
<td align="center"><b><%=intl._("Graph")%></b></td>
|
|
||||||
|
if (shouldShowLog) {
|
||||||
|
|
||||||
|
%> <td align="center"><b><%=intl._("Log")%></b></td>
|
||||||
|
<%
|
||||||
|
|
||||||
|
} // shouldShowLog
|
||||||
|
|
||||||
|
%> <td align="center"><b><%=intl._("Graph")%></b></td>
|
||||||
<td></td></tr>
|
<td></td></tr>
|
||||||
<%
|
<%
|
||||||
} // end iterating over required groups for the current stat %>
|
} // end iterating over required groups for the current stat %>
|
||||||
<tr><td align="center">
|
<tr>
|
||||||
|
<%
|
||||||
|
|
||||||
|
if (shouldShowLog) {
|
||||||
|
|
||||||
|
%> <td align="center">
|
||||||
<a name="<%=statshelper.getCurrentStatName()%>"></a>
|
<a name="<%=statshelper.getCurrentStatName()%>"></a>
|
||||||
<input type="checkbox" class="optbox <%=statshelper.getCurrentGroupName()%>" name="statList" value="<%=statshelper.getCurrentStatName()%>" <%
|
<input type="checkbox" class="optbox <%=statshelper.getCurrentGroupName()%>" name="statList" value="<%=statshelper.getCurrentStatName()%>" <%
|
||||||
if (statshelper.getCurrentIsLogged()) { %>checked="true" <% } %> ></td>
|
if (statshelper.getCurrentIsLogged()) { %>checked="checked" <% } %> ></td>
|
||||||
<td align="center">
|
<%
|
||||||
|
|
||||||
|
} // shouldShowLog
|
||||||
|
|
||||||
|
%> <td align="center">
|
||||||
<% if (statshelper.getCurrentCanBeGraphed()) { %>
|
<% if (statshelper.getCurrentCanBeGraphed()) { %>
|
||||||
<input type="checkbox" class="optbox <%=statshelper.getCurrentGroupName()%>" name="graphList" value="<%=statshelper.getCurrentGraphName()%>" <%
|
<input type="checkbox" class="optbox <%=statshelper.getCurrentGroupName()%>" name="graphList" value="<%=statshelper.getCurrentGraphName()%>" <%
|
||||||
if (statshelper.getCurrentIsGraphed()) { %>checked="true" <% } %> ><% } %></td>
|
if (statshelper.getCurrentIsGraphed()) { %>checked="checked" <% } %> ><% } %></td>
|
||||||
<td align="left"><b><%=statshelper.getCurrentStatName()%>:</b><br>
|
<td align="left"><b><%=statshelper.getCurrentStatName()%>:</b><br>
|
||||||
<%=statshelper.getCurrentStatDescription()%></td></tr><%
|
<%=statshelper.getCurrentStatDescription()%></td></tr><%
|
||||||
} // end iterating over all stats %>
|
} // end iterating over all stats
|
||||||
<tr><td colspan="3"></td></tr>
|
|
||||||
|
if (shouldShowLog) {
|
||||||
|
|
||||||
|
%> <tr><td colspan="3"></td></tr>
|
||||||
<tr><td align="center"><input type="checkbox" class="optbox" name="explicitFilter" ></td>
|
<tr><td align="center"><input type="checkbox" class="optbox" name="explicitFilter" ></td>
|
||||||
<td colspan="2"><%=intl._("Advanced filter")%>:
|
<td colspan="2"><%=intl._("Advanced filter")%>:
|
||||||
<input type="text" name="explicitFilterValue" value="<%=statshelper.getExplicitFilter()%>" size="40" ></td></tr>
|
<input type="text" name="explicitFilterValue" value="<%=statshelper.getExplicitFilter()%>" size="40" ></td></tr>
|
||||||
<tr class="tablefooter"><td colspan="3" align="right">
|
<%
|
||||||
|
|
||||||
|
} // shouldShowLog
|
||||||
|
|
||||||
|
%> <tr class="tablefooter"><td colspan="3" align="right">
|
||||||
<input type="reset" class="cancel" value="<%=intl._("Cancel")%>" >
|
<input type="reset" class="cancel" value="<%=intl._("Cancel")%>" >
|
||||||
<input type="submit" name="shouldsave" class="accept" value="<%=intl._("Save changes")%>" >
|
<input type="submit" name="shouldsave" class="accept" value="<%=intl._("Save changes")%>" >
|
||||||
</td></tr>
|
</td></tr>
|
||||||
|
@@ -56,9 +56,9 @@
|
|||||||
<td><input type="text" size="10" name="proxyPort" value="<jsp:getProperty name="updatehelper" property="proxyPort" />" /></td></tr>
|
<td><input type="text" size="10" name="proxyPort" value="<jsp:getProperty name="updatehelper" property="proxyPort" />" /></td></tr>
|
||||||
<% if (updatehelper.canInstall()) { %>
|
<% if (updatehelper.canInstall()) { %>
|
||||||
<tr><td class= "mediumtags" align="right"><b><%=intl._("Update URLs")%>:</b></td>
|
<tr><td class= "mediumtags" align="right"><b><%=intl._("Update URLs")%>:</b></td>
|
||||||
<td><textarea name="updateURL" wrap="off" spellcheck="false"><jsp:getProperty name="updatehelper" property="updateURL" /></textarea></td>
|
<td><textarea cols="60" rows="6" name="updateURL" wrap="off" spellcheck="false"><jsp:getProperty name="updatehelper" property="updateURL" /></textarea></td>
|
||||||
</tr><tr><td class= "mediumtags" align="right"><b><%=intl._("Trusted keys")%>:</b></td>
|
</tr><tr><td class= "mediumtags" align="right"><b><%=intl._("Trusted keys")%>:</b></td>
|
||||||
<td><textarea name="trustedKeys" wrap="off" spellcheck="false"><jsp:getProperty name="updatehelper" property="trustedKeys" /></textarea></td>
|
<td><textarea cols="60" rows="6" name="trustedKeys" wrap="off" spellcheck="false"><jsp:getProperty name="updatehelper" property="trustedKeys" /></textarea></td>
|
||||||
</tr><tr><td class= "mediumtags" align="right"><b><%=intl._("Update with unsigned development builds?")%></b></td>
|
</tr><tr><td class= "mediumtags" align="right"><b><%=intl._("Update with unsigned development builds?")%></b></td>
|
||||||
<td><jsp:getProperty name="updatehelper" property="updateUnsigned" /></td>
|
<td><jsp:getProperty name="updatehelper" property="updateUnsigned" /></td>
|
||||||
</tr><tr><td class= "mediumtags" align="right"><b><%=intl._("Unsigned Build URL")%>:</b></td>
|
</tr><tr><td class= "mediumtags" align="right"><b><%=intl._("Unsigned Build URL")%>:</b></td>
|
||||||
|
22
apps/routerconsole/jsp/graph.jsp
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
<%@page contentType="text/html"%>
|
||||||
|
<%@page pageEncoding="UTF-8"%>
|
||||||
|
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
|
||||||
|
|
||||||
|
<html><head>
|
||||||
|
<%@include file="css.jsi" %>
|
||||||
|
<%=intl.title("graphs")%>
|
||||||
|
<jsp:useBean class="net.i2p.router.web.GraphHelper" id="graphHelper" scope="request" />
|
||||||
|
<jsp:setProperty name="graphHelper" property="contextId" value="<%=(String)session.getAttribute(\"i2p.contextId\")%>" />
|
||||||
|
<% /* GraphHelper sets the defaults in setContextId, so setting the properties must be after the context */ %>
|
||||||
|
<jsp:setProperty name="graphHelper" property="*" />
|
||||||
|
<%
|
||||||
|
graphHelper.storeWriter(out);
|
||||||
|
%>
|
||||||
|
</head><body>
|
||||||
|
<%@include file="summary.jsi" %>
|
||||||
|
<h1><%=intl._("I2P Performance Graphs")%></h1>
|
||||||
|
<div class="main" id="main">
|
||||||
|
<div class="graphspanel">
|
||||||
|
<div class="widepanel">
|
||||||
|
<jsp:getProperty name="graphHelper" property="singleStat" />
|
||||||
|
</div></div></div></body></html>
|
@@ -6,7 +6,6 @@
|
|||||||
<%@include file="css.jsi" %>
|
<%@include file="css.jsi" %>
|
||||||
<%=intl.title("graphs")%>
|
<%=intl.title("graphs")%>
|
||||||
<jsp:useBean class="net.i2p.router.web.GraphHelper" id="graphHelper" scope="request" />
|
<jsp:useBean class="net.i2p.router.web.GraphHelper" id="graphHelper" scope="request" />
|
||||||
<% graphHelper.storeMethod(request.getMethod()); %>
|
|
||||||
<jsp:setProperty name="graphHelper" property="contextId" value="<%=(String)session.getAttribute("i2p.contextId")%>" />
|
<jsp:setProperty name="graphHelper" property="contextId" value="<%=(String)session.getAttribute("i2p.contextId")%>" />
|
||||||
<% /* GraphHelper sets the defaults in setContextId, so setting the properties must be after the context */ %>
|
<% /* GraphHelper sets the defaults in setContextId, so setting the properties must be after the context */ %>
|
||||||
<jsp:setProperty name="graphHelper" property="*" />
|
<jsp:setProperty name="graphHelper" property="*" />
|
||||||
|
33
apps/routerconsole/jsp/js/ajax.js
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
function ajax(url, target, refresh) {
|
||||||
|
// native XMLHttpRequest object
|
||||||
|
if (window.XMLHttpRequest) {
|
||||||
|
req = new XMLHttpRequest();
|
||||||
|
req.onreadystatechange = function() {ajaxDone(url, target, refresh);};
|
||||||
|
req.open("GET", url, true);
|
||||||
|
req.send(null);
|
||||||
|
// IE/Windows ActiveX version
|
||||||
|
} else if (window.ActiveXObject) {
|
||||||
|
req = new ActiveXObject("Microsoft.XMLDOM");
|
||||||
|
if (req) {
|
||||||
|
req.onreadystatechange = function() {ajaxDone(target);};
|
||||||
|
req.open("GET", url, true);
|
||||||
|
req.send(null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function ajaxDone(url, target, refresh) {
|
||||||
|
// only if req is "loaded"
|
||||||
|
if (req.readyState == 4) {
|
||||||
|
// only if "OK"
|
||||||
|
if (req.status == 200) {
|
||||||
|
results = req.responseText;
|
||||||
|
document.getElementById(target).innerHTML = results;
|
||||||
|
document.getElementById("lowersection").style.display="block";
|
||||||
|
} else {
|
||||||
|
document.getElementById(target).innerHTML="<b>Router is down</b>";
|
||||||
|
document.getElementById("lowersection").style.display="none";
|
||||||
|
}
|
||||||
|
setTimeout(function() {ajax(url, target, refresh);}, refresh);
|
||||||
|
}
|
||||||
|
}
|
@@ -47,12 +47,15 @@ if ( !rendered && ((rs != null) || fakeBw) ) {
|
|||||||
int width = -1;
|
int width = -1;
|
||||||
int height = -1;
|
int height = -1;
|
||||||
int periodCount = -1;
|
int periodCount = -1;
|
||||||
|
int end = 0;
|
||||||
String str = request.getParameter("width");
|
String str = request.getParameter("width");
|
||||||
if (str != null) try { width = Integer.parseInt(str); } catch (NumberFormatException nfe) {}
|
if (str != null) try { width = Integer.parseInt(str); } catch (NumberFormatException nfe) {}
|
||||||
str = request.getParameter("height");
|
str = request.getParameter("height");
|
||||||
if (str != null) try { height = Integer.parseInt(str); } catch (NumberFormatException nfe) {}
|
if (str != null) try { height = Integer.parseInt(str); } catch (NumberFormatException nfe) {}
|
||||||
str = request.getParameter("periodCount");
|
str = request.getParameter("periodCount");
|
||||||
if (str != null) try { periodCount = Integer.parseInt(str); } catch (NumberFormatException nfe) {}
|
if (str != null) try { periodCount = Integer.parseInt(str); } catch (NumberFormatException nfe) {}
|
||||||
|
str = request.getParameter("end");
|
||||||
|
if (str != null) try { end = Integer.parseInt(str); } catch (NumberFormatException nfe) {}
|
||||||
boolean hideLegend = Boolean.valueOf(""+request.getParameter("hideLegend")).booleanValue();
|
boolean hideLegend = Boolean.valueOf(""+request.getParameter("hideLegend")).booleanValue();
|
||||||
boolean hideGrid = Boolean.valueOf(""+request.getParameter("hideGrid")).booleanValue();
|
boolean hideGrid = Boolean.valueOf(""+request.getParameter("hideGrid")).booleanValue();
|
||||||
boolean hideTitle = Boolean.valueOf(""+request.getParameter("hideTitle")).booleanValue();
|
boolean hideTitle = Boolean.valueOf(""+request.getParameter("hideTitle")).booleanValue();
|
||||||
@@ -63,7 +66,7 @@ if ( !rendered && ((rs != null) || fakeBw) ) {
|
|||||||
if (fakeBw)
|
if (fakeBw)
|
||||||
rendered = net.i2p.router.web.StatSummarizer.instance().renderRatePng(cout, width, height, hideLegend, hideGrid, hideTitle, showEvents, periodCount, showCredit);
|
rendered = net.i2p.router.web.StatSummarizer.instance().renderRatePng(cout, width, height, hideLegend, hideGrid, hideTitle, showEvents, periodCount, showCredit);
|
||||||
else
|
else
|
||||||
rendered = net.i2p.router.web.StatSummarizer.instance().renderPng(rate, cout, width, height, hideLegend, hideGrid, hideTitle, showEvents, periodCount, showCredit);
|
rendered = net.i2p.router.web.StatSummarizer.instance().renderPng(rate, cout, width, height, hideLegend, hideGrid, hideTitle, showEvents, periodCount, end, showCredit);
|
||||||
}
|
}
|
||||||
if (rendered)
|
if (rendered)
|
||||||
cout.close();
|
cout.close();
|
||||||
|
@@ -72,6 +72,7 @@
|
|||||||
<attribute name="Main-Class" value="net.i2p.sam.SAMBridge" />
|
<attribute name="Main-Class" value="net.i2p.sam.SAMBridge" />
|
||||||
<attribute name="Class-Path" value="i2p.jar mstreaming.jar streaming.jar" />
|
<attribute name="Class-Path" value="i2p.jar mstreaming.jar streaming.jar" />
|
||||||
<attribute name="Implementation-Version" value="${full.version}" />
|
<attribute name="Implementation-Version" value="${full.version}" />
|
||||||
|
<attribute name="Built-By" value="${build.built-by}" />
|
||||||
<attribute name="Build-Date" value="${build.timestamp}" />
|
<attribute name="Build-Date" value="${build.timestamp}" />
|
||||||
<attribute name="Base-Revision" value="${workspace.version}" />
|
<attribute name="Base-Revision" value="${workspace.version}" />
|
||||||
<attribute name="Workspace-Changes" value="${workspace.changes.tr}" />
|
<attribute name="Workspace-Changes" value="${workspace.changes.tr}" />
|
||||||
@@ -87,6 +88,7 @@
|
|||||||
<attribute name="Main-Class" value="net.i2p.sam.SAMBridge" />
|
<attribute name="Main-Class" value="net.i2p.sam.SAMBridge" />
|
||||||
<attribute name="Class-Path" value="i2p.jar mstreaming.jar streaming.jar" />
|
<attribute name="Class-Path" value="i2p.jar mstreaming.jar streaming.jar" />
|
||||||
<attribute name="Implementation-Version" value="${full.version}" />
|
<attribute name="Implementation-Version" value="${full.version}" />
|
||||||
|
<attribute name="Built-By" value="${build.built-by}" />
|
||||||
<attribute name="Build-Date" value="${build.timestamp}" />
|
<attribute name="Build-Date" value="${build.timestamp}" />
|
||||||
<attribute name="Base-Revision" value="${workspace.version}" />
|
<attribute name="Base-Revision" value="${workspace.version}" />
|
||||||
<attribute name="Workspace-Changes" value="${workspace.changes.tr}" />
|
<attribute name="Workspace-Changes" value="${workspace.changes.tr}" />
|
||||||
|
@@ -64,6 +64,7 @@
|
|||||||
<jar destfile="./build/streaming.jar" basedir="./build/obj" includes="**/*.class" >
|
<jar destfile="./build/streaming.jar" basedir="./build/obj" includes="**/*.class" >
|
||||||
<manifest>
|
<manifest>
|
||||||
<attribute name="Implementation-Version" value="${full.version}" />
|
<attribute name="Implementation-Version" value="${full.version}" />
|
||||||
|
<attribute name="Built-By" value="${build.built-by}" />
|
||||||
<attribute name="Build-Date" value="${build.timestamp}" />
|
<attribute name="Build-Date" value="${build.timestamp}" />
|
||||||
<attribute name="Base-Revision" value="${workspace.version}" />
|
<attribute name="Base-Revision" value="${workspace.version}" />
|
||||||
<attribute name="Workspace-Changes" value="${workspace.changes.tr}" />
|
<attribute name="Workspace-Changes" value="${workspace.changes.tr}" />
|
||||||
|
@@ -161,8 +161,7 @@ class ConnectionManager {
|
|||||||
// active++;
|
// active++;
|
||||||
//}
|
//}
|
||||||
if (locked_tooManyStreams()) {
|
if (locked_tooManyStreams()) {
|
||||||
if (_log.shouldLog(Log.WARN))
|
_log.logAlways(Log.WARN, "Refusing connection since we have exceeded our max of "
|
||||||
_log.warn("Refusing connection since we have exceeded our max of "
|
|
||||||
+ _maxConcurrentStreams + " connections");
|
+ _maxConcurrentStreams + " connections");
|
||||||
reject = true;
|
reject = true;
|
||||||
} else {
|
} else {
|
||||||
@@ -233,8 +232,7 @@ class ConnectionManager {
|
|||||||
while (true) {
|
while (true) {
|
||||||
long remaining = expiration - _context.clock().now();
|
long remaining = expiration - _context.clock().now();
|
||||||
if (remaining <= 0) {
|
if (remaining <= 0) {
|
||||||
if (_log.shouldLog(Log.WARN))
|
_log.logAlways(Log.WARN, "Refusing to connect since we have exceeded our max of "
|
||||||
_log.warn("Refusing to connect since we have exceeded our max of "
|
|
||||||
+ _maxConcurrentStreams + " connections");
|
+ _maxConcurrentStreams + " connections");
|
||||||
_numWaiting--;
|
_numWaiting--;
|
||||||
return null;
|
return null;
|
||||||
@@ -243,8 +241,7 @@ class ConnectionManager {
|
|||||||
if (locked_tooManyStreams()) {
|
if (locked_tooManyStreams()) {
|
||||||
// allow a full buffer of pending/waiting streams
|
// allow a full buffer of pending/waiting streams
|
||||||
if (_numWaiting > _maxConcurrentStreams) {
|
if (_numWaiting > _maxConcurrentStreams) {
|
||||||
if (_log.shouldLog(Log.WARN))
|
_log.logAlways(Log.WARN, "Refusing connection since we have exceeded our max of "
|
||||||
_log.warn("Refusing connection since we have exceeded our max of "
|
|
||||||
+ _maxConcurrentStreams + " and there are " + _numWaiting
|
+ _maxConcurrentStreams + " and there are " + _numWaiting
|
||||||
+ " waiting already");
|
+ " waiting already");
|
||||||
_numWaiting--;
|
_numWaiting--;
|
||||||
|
@@ -98,6 +98,7 @@
|
|||||||
</fileset>
|
</fileset>
|
||||||
<manifest>
|
<manifest>
|
||||||
<attribute name="Implementation-Version" value="${full.version}" />
|
<attribute name="Implementation-Version" value="${full.version}" />
|
||||||
|
<attribute name="Built-By" value="${build.built-by}" />
|
||||||
<attribute name="Build-Date" value="${build.timestamp}" />
|
<attribute name="Build-Date" value="${build.timestamp}" />
|
||||||
<attribute name="Base-Revision" value="${workspace.version}" />
|
<attribute name="Base-Revision" value="${workspace.version}" />
|
||||||
<attribute name="Workspace-Changes" value="${workspace.changes.tr}" />
|
<attribute name="Workspace-Changes" value="${workspace.changes.tr}" />
|
||||||
|
@@ -170,6 +170,15 @@ public class AddressBean
|
|||||||
return Base32.encode(hash) + ".b32.i2p";
|
return Base32.encode(hash) + ".b32.i2p";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** @since 0.9 */
|
||||||
|
public String getB64()
|
||||||
|
{
|
||||||
|
byte[] dest = Base64.decode(destination);
|
||||||
|
if (dest == null)
|
||||||
|
return "";
|
||||||
|
return I2PAppContext.getGlobalContext().sha().calculateHash(dest).toBase64();
|
||||||
|
}
|
||||||
|
|
||||||
/** @since 0.8.7 */
|
/** @since 0.8.7 */
|
||||||
public void setProperties(Properties p) {
|
public void setProperties(Properties p) {
|
||||||
props = p;
|
props = p;
|
||||||
|
@@ -42,7 +42,7 @@
|
|||||||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
|
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
|
||||||
<html>
|
<html>
|
||||||
<head>
|
<head>
|
||||||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
|
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
|
||||||
<title>${book.book} <%=intl._("address book")%> - susidns</title>
|
<title>${book.book} <%=intl._("address book")%> - susidns</title>
|
||||||
<link rel="stylesheet" type="text/css" href="css.css">
|
<link rel="stylesheet" type="text/css" href="css.css">
|
||||||
</head>
|
</head>
|
||||||
@@ -158,7 +158,7 @@ ${book.loadBookMessages}
|
|||||||
</td><td class="names">
|
</td><td class="names">
|
||||||
<span class="addrhlpr"><a href="details?h=${addr.name}" title="<%=intl._("More information on this entry")%>"><%=intl._("details")%></a></span>
|
<span class="addrhlpr"><a href="details?h=${addr.name}" title="<%=intl._("More information on this entry")%>"><%=intl._("details")%></a></span>
|
||||||
</td>
|
</td>
|
||||||
<td class="destinations"><textarea rows="1" style="height: 3em;" cols="40" wrap="off" readonly="readonly" name="dest_${addr.name}" >${addr.destination}</textarea></td>
|
<td class="destinations"><textarea rows="1" style="height:3em;" wrap="off" cols="40" readonly="readonly" name="dest_${addr.name}" >${addr.destination}</textarea></td>
|
||||||
</tr>
|
</tr>
|
||||||
</c:forEach>
|
</c:forEach>
|
||||||
</table>
|
</table>
|
||||||
@@ -190,7 +190,7 @@ ${book.loadBookMessages}
|
|||||||
<table><tr><td>
|
<table><tr><td>
|
||||||
<b><%=intl._("Host Name")%></b></td><td><input type="text" name="hostname" value="${book.hostname}" size="54">
|
<b><%=intl._("Host Name")%></b></td><td><input type="text" name="hostname" value="${book.hostname}" size="54">
|
||||||
</td></tr><tr><td>
|
</td></tr><tr><td>
|
||||||
<b><%=intl._("Destination")%></b></td><td><textarea name="destination" rows="1" style="height: 3em;" cols="70" wrap="off" spellcheck="false">${book.destination}</textarea>
|
<b><%=intl._("Destination")%></b></td><td><textarea name="destination" rows="1" style="height:3em" wrap="off" cols="70" spellcheck="false">${book.destination}</textarea>
|
||||||
</td></tr></table>
|
</td></tr></table>
|
||||||
<p class="buttons">
|
<p class="buttons">
|
||||||
<input class="cancel" type="reset" value="<%=intl._("Cancel")%>" >
|
<input class="cancel" type="reset" value="<%=intl._("Cancel")%>" >
|
||||||
|
@@ -38,7 +38,7 @@
|
|||||||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
|
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
|
||||||
<html>
|
<html>
|
||||||
<head>
|
<head>
|
||||||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
|
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
|
||||||
<title><%=intl._("configuration")%> - susidns</title>
|
<title><%=intl._("configuration")%> - susidns</title>
|
||||||
<link rel="stylesheet" type="text/css" href="css.css">
|
<link rel="stylesheet" type="text/css" href="css.css">
|
||||||
</head>
|
</head>
|
||||||
|
@@ -36,7 +36,7 @@
|
|||||||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
|
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
|
||||||
<html>
|
<html>
|
||||||
<head>
|
<head>
|
||||||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
|
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
|
||||||
<title>${book.book} <%=intl._("addressbook")%> - susidns</title>
|
<title>${book.book} <%=intl._("addressbook")%> - susidns</title>
|
||||||
<link rel="stylesheet" type="text/css" href="css.css">
|
<link rel="stylesheet" type="text/css" href="css.css">
|
||||||
</head>
|
</head>
|
||||||
@@ -94,6 +94,9 @@
|
|||||||
<td><%=intl._("Base 32 Address")%></td>
|
<td><%=intl._("Base 32 Address")%></td>
|
||||||
<td><a href="http://<%=b32%>/"><%=b32%></a></td>
|
<td><a href="http://<%=b32%>/"><%=b32%></a></td>
|
||||||
</tr><tr class="list${book.trClass}">
|
</tr><tr class="list${book.trClass}">
|
||||||
|
<td><%=intl._("Base 64 Hash")%></td>
|
||||||
|
<td><%=addr.getB64()%></td>
|
||||||
|
</tr><tr class="list${book.trClass}">
|
||||||
<td><%=intl._("Address Helper")%></td>
|
<td><%=intl._("Address Helper")%></td>
|
||||||
<td><a href="http://<%=addr.getName()%>/?i2paddresshelper=<%=addr.getDestination()%>"><%=intl._("link")%></a></td>
|
<td><a href="http://<%=addr.getName()%>/?i2paddresshelper=<%=addr.getDestination()%>"><%=intl._("link")%></a></td>
|
||||||
</tr><tr class="list${book.trClass}">
|
</tr><tr class="list${book.trClass}">
|
||||||
@@ -119,7 +122,7 @@
|
|||||||
<td><%=addr.getNotes()%></td>
|
<td><%=addr.getNotes()%></td>
|
||||||
</tr><tr class="list${book.trClass}">
|
</tr><tr class="list${book.trClass}">
|
||||||
<td><%=intl._("Destination")%></td>
|
<td><%=intl._("Destination")%></td>
|
||||||
<td class="destinations"><textarea rows="1" style="height: 3em;" cols="70" wrap="off" readonly="readonly" ><%=addr.getDestination()%></textarea></td>
|
<td class="destinations"><textarea rows="1" style="height:3em;" wrap="off" cols="70" readonly="readonly" ><%=addr.getDestination()%></textarea></td>
|
||||||
</tr></table>
|
</tr></table>
|
||||||
</div>
|
</div>
|
||||||
<div id="buttons">
|
<div id="buttons">
|
||||||
|
@@ -38,7 +38,7 @@
|
|||||||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
|
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
|
||||||
<html>
|
<html>
|
||||||
<head>
|
<head>
|
||||||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
|
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
|
||||||
<title><%=intl._("subscriptions")%> - susidns</title>
|
<title><%=intl._("subscriptions")%> - susidns</title>
|
||||||
<link rel="stylesheet" type="text/css" href="css.css">
|
<link rel="stylesheet" type="text/css" href="css.css">
|
||||||
</head>
|
</head>
|
||||||
|
@@ -46,6 +46,7 @@
|
|||||||
basedir="src/" excludes="WEB-INF/web.xml LICENSE src/**/*">
|
basedir="src/" excludes="WEB-INF/web.xml LICENSE src/**/*">
|
||||||
<manifest>
|
<manifest>
|
||||||
<attribute name="Implementation-Version" value="${full.version}" />
|
<attribute name="Implementation-Version" value="${full.version}" />
|
||||||
|
<attribute name="Built-By" value="${build.built-by}" />
|
||||||
<attribute name="Build-Date" value="${build.timestamp}" />
|
<attribute name="Build-Date" value="${build.timestamp}" />
|
||||||
<attribute name="Base-Revision" value="${workspace.version}" />
|
<attribute name="Base-Revision" value="${workspace.version}" />
|
||||||
<attribute name="Workspace-Changes" value="${workspace.changes.tr}" />
|
<attribute name="Workspace-Changes" value="${workspace.changes.tr}" />
|
||||||
|
@@ -45,6 +45,7 @@
|
|||||||
<attribute name="Main-Class" value="net.i2p.apps.systray.SysTray" />
|
<attribute name="Main-Class" value="net.i2p.apps.systray.SysTray" />
|
||||||
<attribute name="Class-Path" value="systray4j.jar" />
|
<attribute name="Class-Path" value="systray4j.jar" />
|
||||||
<attribute name="Implementation-Version" value="${full.version}" />
|
<attribute name="Implementation-Version" value="${full.version}" />
|
||||||
|
<attribute name="Built-By" value="${build.built-by}" />
|
||||||
<attribute name="Build-Date" value="${build.timestamp}" />
|
<attribute name="Build-Date" value="${build.timestamp}" />
|
||||||
<attribute name="Base-Revision" value="${workspace.version}" />
|
<attribute name="Base-Revision" value="${workspace.version}" />
|
||||||
<attribute name="Workspace-Changes" value="${workspace.changes.tr}" />
|
<attribute name="Workspace-Changes" value="${workspace.changes.tr}" />
|
||||||
|
@@ -16,3 +16,5 @@ wrapperdocs.url=http://wrapper.tanukisoftware.com/jdoc/
|
|||||||
# these are only for unit test javadocs
|
# these are only for unit test javadocs
|
||||||
i2pdocs.url=http://docs.i2p-projekt.de/javadoc/
|
i2pdocs.url=http://docs.i2p-projekt.de/javadoc/
|
||||||
junitdocs.url=http://junit.org/apidocs/
|
junitdocs.url=http://junit.org/apidocs/
|
||||||
|
# This will go in the jar manifests
|
||||||
|
build.built-by=unknown
|
||||||
|
90
build.xml
@@ -166,6 +166,7 @@
|
|||||||
<zipfileset src="apps/jrobin/jrobin-1.5.9.1.jar"
|
<zipfileset src="apps/jrobin/jrobin-1.5.9.1.jar"
|
||||||
excludes="org/jrobin/cmd/ org/jrobin/convertor/ org/jrobin/inspector/" />
|
excludes="org/jrobin/cmd/ org/jrobin/convertor/ org/jrobin/inspector/" />
|
||||||
<manifest>
|
<manifest>
|
||||||
|
<attribute name="Built-By" value="${build.built-by}" />
|
||||||
<attribute name="Build-Date" value="${build.timestamp}" />
|
<attribute name="Build-Date" value="${build.timestamp}" />
|
||||||
<attribute name="Base-Revision" value="${workspace.version}" />
|
<attribute name="Base-Revision" value="${workspace.version}" />
|
||||||
</manifest>
|
</manifest>
|
||||||
@@ -206,6 +207,7 @@
|
|||||||
<copy file="apps/jetty/jettylib/javax.servlet.jar" todir="build/" />
|
<copy file="apps/jetty/jettylib/javax.servlet.jar" todir="build/" />
|
||||||
</target>
|
</target>
|
||||||
|
|
||||||
|
<!-- this makes an empty build/launchi2p.jar and the build/i2p.exe for the no-wrapper windows startup, if possible -->
|
||||||
<target name="buildexe">
|
<target name="buildexe">
|
||||||
<condition property="noExe">
|
<condition property="noExe">
|
||||||
<os arch="x86_64" />
|
<os arch="x86_64" />
|
||||||
@@ -234,11 +236,13 @@
|
|||||||
classname="net.sf.launch4j.ant.Launch4jTask"
|
classname="net.sf.launch4j.ant.Launch4jTask"
|
||||||
classpath="${basedir}/installer/lib/launch4j/launch4j.jar:${basedir}/installer/lib/launch4j/lib/xstream.jar" />
|
classpath="${basedir}/installer/lib/launch4j/launch4j.jar:${basedir}/installer/lib/launch4j/lib/xstream.jar" />
|
||||||
|
|
||||||
|
<!-- this makes an empty build/launchi2p.jar and the build/i2p.exe for the no-wrapper windows startup -->
|
||||||
<target name="doBuildEXE" depends="buildProperties" unless="noExe">
|
<target name="doBuildEXE" depends="buildProperties" unless="noExe">
|
||||||
<jar destfile="./build/launchi2p.jar">
|
<jar destfile="./build/launchi2p.jar">
|
||||||
<manifest>
|
<manifest>
|
||||||
<attribute name="Main-Class" value="net.i2p.router.RouterLaunch" />
|
<attribute name="Main-Class" value="net.i2p.router.RouterLaunch" />
|
||||||
<attribute name="Class-Path" value="lib/i2p.jar lib/router.jar lib/jbigi.jar lib/BOB.jar lib/sam.jar lib/mstreaming.jar lib/streaming.jar lib/routerconsole.jar lib/i2ptunnel.jar lib/org.mortbay.jetty.jar lib/javax.servlet.jar lib/jasper-compiler.jar lib/jasper-runtime.jar lib/commons-logging.jar lib/commons-el.jar lib/wrapper.jar lib/systray.jar lib/systray4j.jar lib/desktopgui.jar" />
|
<attribute name="Class-Path" value="lib/i2p.jar lib/router.jar lib/jbigi.jar lib/BOB.jar lib/sam.jar lib/mstreaming.jar lib/streaming.jar lib/routerconsole.jar lib/i2ptunnel.jar lib/org.mortbay.jetty.jar lib/javax.servlet.jar lib/jasper-compiler.jar lib/jasper-runtime.jar lib/commons-logging.jar lib/commons-el.jar lib/wrapper.jar lib/systray.jar lib/systray4j.jar lib/desktopgui.jar" />
|
||||||
|
<attribute name="Built-By" value="${build.built-by}" />
|
||||||
<attribute name="Build-Date" value="${build.timestamp}" />
|
<attribute name="Build-Date" value="${build.timestamp}" />
|
||||||
<attribute name="Base-Revision" value="${workspace.version}" />
|
<attribute name="Base-Revision" value="${workspace.version}" />
|
||||||
</manifest>
|
</manifest>
|
||||||
@@ -289,6 +293,7 @@
|
|||||||
<jar destfile="build/jbigi.jar" whenmanifestonly="fail" >
|
<jar destfile="build/jbigi.jar" whenmanifestonly="fail" >
|
||||||
<fileset dir="installer/lib/jbigi" includes="*.so *.dll *.jnilib" />
|
<fileset dir="installer/lib/jbigi" includes="*.so *.dll *.jnilib" />
|
||||||
<manifest>
|
<manifest>
|
||||||
|
<attribute name="Built-By" value="${build.built-by}" />
|
||||||
<attribute name="Build-Date" value="${build.timestamp}" />
|
<attribute name="Build-Date" value="${build.timestamp}" />
|
||||||
<attribute name="Base-Revision" value="${workspace.version}" />
|
<attribute name="Base-Revision" value="${workspace.version}" />
|
||||||
<attribute name="Workspace-Changes" value="${workspace.changes.jbigi.tr}" />
|
<attribute name="Workspace-Changes" value="${workspace.changes.jbigi.tr}" />
|
||||||
@@ -302,6 +307,7 @@
|
|||||||
<jar destfile="build/jbigi.jar" whenmanifestonly="fail" >
|
<jar destfile="build/jbigi.jar" whenmanifestonly="fail" >
|
||||||
<fileset dir="installer/lib/jbigi" includes="*.so *.jnilib" />
|
<fileset dir="installer/lib/jbigi" includes="*.so *.jnilib" />
|
||||||
<manifest>
|
<manifest>
|
||||||
|
<attribute name="Built-By" value="${build.built-by}" />
|
||||||
<attribute name="Build-Date" value="${build.timestamp}" />
|
<attribute name="Build-Date" value="${build.timestamp}" />
|
||||||
<attribute name="Base-Revision" value="${workspace.version}" />
|
<attribute name="Base-Revision" value="${workspace.version}" />
|
||||||
<attribute name="Workspace-Changes" value="${workspace.changes.jbigi.tr}" />
|
<attribute name="Workspace-Changes" value="${workspace.changes.jbigi.tr}" />
|
||||||
@@ -316,6 +322,7 @@
|
|||||||
<jar destfile="build/jbigi.jar" whenmanifestonly="fail" >
|
<jar destfile="build/jbigi.jar" whenmanifestonly="fail" >
|
||||||
<fileset dir="installer/lib/jbigi" includes="*freebsd*.so" />
|
<fileset dir="installer/lib/jbigi" includes="*freebsd*.so" />
|
||||||
<manifest>
|
<manifest>
|
||||||
|
<attribute name="Built-By" value="${build.built-by}" />
|
||||||
<attribute name="Build-Date" value="${build.timestamp}" />
|
<attribute name="Build-Date" value="${build.timestamp}" />
|
||||||
<attribute name="Base-Revision" value="${workspace.version}" />
|
<attribute name="Base-Revision" value="${workspace.version}" />
|
||||||
<attribute name="Workspace-Changes" value="${workspace.changes.jbigi.tr}" />
|
<attribute name="Workspace-Changes" value="${workspace.changes.jbigi.tr}" />
|
||||||
@@ -329,6 +336,7 @@
|
|||||||
<jar destfile="build/jbigi.jar" whenmanifestonly="fail" >
|
<jar destfile="build/jbigi.jar" whenmanifestonly="fail" >
|
||||||
<fileset dir="installer/lib/jbigi" includes="*linux*.so" />
|
<fileset dir="installer/lib/jbigi" includes="*linux*.so" />
|
||||||
<manifest>
|
<manifest>
|
||||||
|
<attribute name="Built-By" value="${build.built-by}" />
|
||||||
<attribute name="Build-Date" value="${build.timestamp}" />
|
<attribute name="Build-Date" value="${build.timestamp}" />
|
||||||
<attribute name="Base-Revision" value="${workspace.version}" />
|
<attribute name="Base-Revision" value="${workspace.version}" />
|
||||||
<attribute name="Workspace-Changes" value="${workspace.changes.jbigi.tr}" />
|
<attribute name="Workspace-Changes" value="${workspace.changes.jbigi.tr}" />
|
||||||
@@ -342,6 +350,7 @@
|
|||||||
<jar destfile="build/jbigi.jar" whenmanifestonly="fail" >
|
<jar destfile="build/jbigi.jar" whenmanifestonly="fail" >
|
||||||
<fileset dir="installer/lib/jbigi" includes="*linux-arm*.so,*linux-ppc*.so" />
|
<fileset dir="installer/lib/jbigi" includes="*linux-arm*.so,*linux-ppc*.so" />
|
||||||
<manifest>
|
<manifest>
|
||||||
|
<attribute name="Built-By" value="${build.built-by}" />
|
||||||
<attribute name="Build-Date" value="${build.timestamp}" />
|
<attribute name="Build-Date" value="${build.timestamp}" />
|
||||||
<attribute name="Base-Revision" value="${workspace.version}" />
|
<attribute name="Base-Revision" value="${workspace.version}" />
|
||||||
<attribute name="Workspace-Changes" value="${workspace.changes.jbigi.tr}" />
|
<attribute name="Workspace-Changes" value="${workspace.changes.jbigi.tr}" />
|
||||||
@@ -355,6 +364,7 @@
|
|||||||
<jar destfile="build/jbigi.jar" whenmanifestonly="fail" >
|
<jar destfile="build/jbigi.jar" whenmanifestonly="fail" >
|
||||||
<fileset dir="installer/lib/jbigi" includes="*.jnilib" />
|
<fileset dir="installer/lib/jbigi" includes="*.jnilib" />
|
||||||
<manifest>
|
<manifest>
|
||||||
|
<attribute name="Built-By" value="${build.built-by}" />
|
||||||
<attribute name="Build-Date" value="${build.timestamp}" />
|
<attribute name="Build-Date" value="${build.timestamp}" />
|
||||||
<attribute name="Base-Revision" value="${workspace.version}" />
|
<attribute name="Base-Revision" value="${workspace.version}" />
|
||||||
<attribute name="Workspace-Changes" value="${workspace.changes.jbigi.tr}" />
|
<attribute name="Workspace-Changes" value="${workspace.changes.jbigi.tr}" />
|
||||||
@@ -368,6 +378,7 @@
|
|||||||
<jar destfile="build/jbigi.jar" whenmanifestonly="fail" >
|
<jar destfile="build/jbigi.jar" whenmanifestonly="fail" >
|
||||||
<fileset dir="installer/lib/jbigi" includes="*windows*.dll" />
|
<fileset dir="installer/lib/jbigi" includes="*windows*.dll" />
|
||||||
<manifest>
|
<manifest>
|
||||||
|
<attribute name="Built-By" value="${build.built-by}" />
|
||||||
<attribute name="Build-Date" value="${build.timestamp}" />
|
<attribute name="Build-Date" value="${build.timestamp}" />
|
||||||
<attribute name="Base-Revision" value="${workspace.version}" />
|
<attribute name="Base-Revision" value="${workspace.version}" />
|
||||||
<attribute name="Workspace-Changes" value="${workspace.changes.jbigi.tr}" />
|
<attribute name="Workspace-Changes" value="${workspace.changes.jbigi.tr}" />
|
||||||
@@ -544,6 +555,7 @@
|
|||||||
</target>
|
</target>
|
||||||
|
|
||||||
<target name="verifyReleaseBuildNumbers" depends="getReleaseNumber, getBuildNumber" >
|
<target name="verifyReleaseBuildNumbers" depends="getReleaseNumber, getBuildNumber" >
|
||||||
|
<echo message="SDK: ${java.vendor} ${java.version} (${java.runtime.name} ${java.runtime.version})" />
|
||||||
<fail message="Bad release number: ${release.number}" >
|
<fail message="Bad release number: ${release.number}" >
|
||||||
<condition>
|
<condition>
|
||||||
<or>
|
<or>
|
||||||
@@ -572,7 +584,6 @@
|
|||||||
<delete dir="./build" />
|
<delete dir="./build" />
|
||||||
<delete file="installer/lib/izpack/patches.jar" failonerror="false" quiet="true" />
|
<delete file="installer/lib/izpack/patches.jar" failonerror="false" quiet="true" />
|
||||||
<delete file="i2pinstall.exe" failonerror="false" quiet="true" />
|
<delete file="i2pinstall.exe" failonerror="false" quiet="true" />
|
||||||
<delete file="i2p.exe" failonerror="false" quiet="true" />
|
|
||||||
<delete file="syndie-standalone.zip" failonerror="false" quiet="true" />
|
<delete file="syndie-standalone.zip" failonerror="false" quiet="true" />
|
||||||
<delete>
|
<delete>
|
||||||
<fileset dir="." includes="i2pinstall*jar i2pinstall*bz2" />
|
<fileset dir="." includes="i2pinstall*jar i2pinstall*bz2" />
|
||||||
@@ -754,7 +765,7 @@
|
|||||||
</target>
|
</target>
|
||||||
|
|
||||||
<target name="preppkg-windows" depends="preppkg-base, buildexe">
|
<target name="preppkg-windows" depends="preppkg-base, buildexe">
|
||||||
<copy file="i2p.exe" todir="pkg-temp/" failonerror="false" />
|
<copy file="build/i2p.exe" todir="pkg-temp/" failonerror="false" />
|
||||||
<copy file="apps/systray/java/lib/systray4j.dll" todir="pkg-temp/lib" />
|
<copy file="apps/systray/java/lib/systray4j.dll" todir="pkg-temp/lib" />
|
||||||
<copy file="apps/systray/java/resources/iggy.ico" todir="pkg-temp/icons" />
|
<copy file="apps/systray/java/resources/iggy.ico" todir="pkg-temp/icons" />
|
||||||
<copy file="apps/systray/java/resources/iggy.xpm" todir="pkg-temp/icons" />
|
<copy file="apps/systray/java/resources/iggy.xpm" todir="pkg-temp/icons" />
|
||||||
@@ -1016,7 +1027,9 @@
|
|||||||
<copy file="build/i2psnark.jar" todir="pkg-temp/lib" />
|
<copy file="build/i2psnark.jar" todir="pkg-temp/lib" />
|
||||||
<!-- include systray changes in 0.7.5 -->
|
<!-- include systray changes in 0.7.5 -->
|
||||||
<copy file="build/systray.jar" todir="pkg-temp/lib/" />
|
<copy file="build/systray.jar" todir="pkg-temp/lib/" />
|
||||||
|
<!-- removed from updater in 0.9
|
||||||
<copy file="build/desktopgui.jar" todir="pkg-temp/lib/" />
|
<copy file="build/desktopgui.jar" todir="pkg-temp/lib/" />
|
||||||
|
-->
|
||||||
<copy file="build/susimail.war" todir="pkg-temp/webapps/" />
|
<copy file="build/susimail.war" todir="pkg-temp/webapps/" />
|
||||||
<copy file="build/susidns.war" todir="pkg-temp/webapps/" />
|
<copy file="build/susidns.war" todir="pkg-temp/webapps/" />
|
||||||
<!-- as of 0.7.12; someday, we can remove these from the updater -->
|
<!-- as of 0.7.12; someday, we can remove these from the updater -->
|
||||||
@@ -1116,6 +1129,7 @@
|
|||||||
<jar destfile="./pkg-temp/installer/copy.jar" basedir="./core/java/build/obj" includes="net/i2p/util/Copy.class net/i2p/util/FileUtil.class">
|
<jar destfile="./pkg-temp/installer/copy.jar" basedir="./core/java/build/obj" includes="net/i2p/util/Copy.class net/i2p/util/FileUtil.class">
|
||||||
<manifest>
|
<manifest>
|
||||||
<attribute name="Main-Class" value="net.i2p.util.Copy" />
|
<attribute name="Main-Class" value="net.i2p.util.Copy" />
|
||||||
|
<attribute name="Built-By" value="${build.built-by}" />
|
||||||
<attribute name="Build-Date" value="${build.timestamp}" />
|
<attribute name="Build-Date" value="${build.timestamp}" />
|
||||||
<attribute name="Base-Revision" value="${workspace.version}" />
|
<attribute name="Base-Revision" value="${workspace.version}" />
|
||||||
<attribute name="Workspace-Changes" value="${workspace.changes.util.tr}" />
|
<attribute name="Workspace-Changes" value="${workspace.changes.util.tr}" />
|
||||||
@@ -1124,6 +1138,7 @@
|
|||||||
<jar destfile="./pkg-temp/installer/delete.jar" basedir="./core/java/build/obj" includes="net/i2p/util/Delete.class net/i2p/util/FileUtil.class">
|
<jar destfile="./pkg-temp/installer/delete.jar" basedir="./core/java/build/obj" includes="net/i2p/util/Delete.class net/i2p/util/FileUtil.class">
|
||||||
<manifest>
|
<manifest>
|
||||||
<attribute name="Main-Class" value="net.i2p.util.Delete" />
|
<attribute name="Main-Class" value="net.i2p.util.Delete" />
|
||||||
|
<attribute name="Built-By" value="${build.built-by}" />
|
||||||
<attribute name="Build-Date" value="${build.timestamp}" />
|
<attribute name="Build-Date" value="${build.timestamp}" />
|
||||||
<attribute name="Base-Revision" value="${workspace.version}" />
|
<attribute name="Base-Revision" value="${workspace.version}" />
|
||||||
<attribute name="Workspace-Changes" value="${workspace.changes.util.tr}" />
|
<attribute name="Workspace-Changes" value="${workspace.changes.util.tr}" />
|
||||||
@@ -1132,6 +1147,7 @@
|
|||||||
<jar destfile="./pkg-temp/installer/exec.jar" basedir="./core/java/build/obj" includes="net/i2p/util/Exec.class">
|
<jar destfile="./pkg-temp/installer/exec.jar" basedir="./core/java/build/obj" includes="net/i2p/util/Exec.class">
|
||||||
<manifest>
|
<manifest>
|
||||||
<attribute name="Main-Class" value="net.i2p.util.Exec" />
|
<attribute name="Main-Class" value="net.i2p.util.Exec" />
|
||||||
|
<attribute name="Built-By" value="${build.built-by}" />
|
||||||
<attribute name="Build-Date" value="${build.timestamp}" />
|
<attribute name="Build-Date" value="${build.timestamp}" />
|
||||||
<attribute name="Base-Revision" value="${workspace.version}" />
|
<attribute name="Base-Revision" value="${workspace.version}" />
|
||||||
<attribute name="Workspace-Changes" value="${workspace.changes.util.tr}" />
|
<attribute name="Workspace-Changes" value="${workspace.changes.util.tr}" />
|
||||||
@@ -1169,43 +1185,31 @@
|
|||||||
<ant target="doInstallerEXE" />
|
<ant target="doInstallerEXE" />
|
||||||
</target>
|
</target>
|
||||||
|
|
||||||
|
<!-- this makes i2pinstall.exe from install.jar -->
|
||||||
<target name="doInstallerEXE" unless="noExe">
|
<target name="doInstallerEXE" unless="noExe">
|
||||||
<!-- now the installer exe -->
|
<!-- now the installer exe -->
|
||||||
<launch4j configFile="./installer/i2pinstaller.xml" />
|
<launch4j configFile="./installer/i2pinstaller.xml" />
|
||||||
<launch4j configFile="./installer/i2pstandalone.xml" />
|
|
||||||
<!-- thazzit -->
|
<!-- thazzit -->
|
||||||
</target>
|
</target>
|
||||||
|
|
||||||
<!-- Custom installers -->
|
<!-- Custom installers -->
|
||||||
<target name="installer-nowindows" depends="clean, preppkg-nowindows, getReleaseNumber, getBuildNumber, buildProperties, util-list-changes, izpack-patches" >
|
<target name="installer-nowindows" depends="clean, preppkg-nowindows, izpack-patches" >
|
||||||
<mkdir dir="pkg-temp/installer" />
|
<izpack input="${basedir}/installer/install.xml" output="${basedir}/i2pinstall_${full.version}.jar" installerType="standard" basedir="${basedir}" />
|
||||||
<!-- set if unset -->
|
|
||||||
<property name="workspace.changes.util.tr" value="" />
|
|
||||||
<izpack input="${basedir}/installer/install.xml" output="${basedir}/i2pinstall_${release.number}-${i2p.build.number}${build.extra}.jar" installerType="standard" basedir="${basedir}" />
|
|
||||||
</target>
|
</target>
|
||||||
|
|
||||||
|
|
||||||
<target name="installer-freebsd" depends="clean, preppkg-freebsd-only, getReleaseNumber, getBuildNumber, buildProperties, util-list-changes, izpack-patches" >
|
<target name="installer-freebsd" depends="clean, preppkg-freebsd-only, izpack-patches" >
|
||||||
<mkdir dir="pkg-temp/installer" />
|
<izpack input="${basedir}/installer/install.xml" output="${basedir}/i2pinstall_${full.version}_freebsd-only.jar" installerType="standard" basedir="${basedir}" />
|
||||||
<!-- set if unset -->
|
|
||||||
<property name="workspace.changes.util.tr" value="" />
|
|
||||||
<izpack input="${basedir}/installer/install.xml" output="${basedir}/i2pinstall_${release.number}-${i2p.build.number}${build.extra}_freebsd-only.jar" installerType="standard" basedir="${basedir}" />
|
|
||||||
</target>
|
</target>
|
||||||
|
|
||||||
<target name="installer-linux" depends="clean, preppkg-linux-only, getReleaseNumber, getBuildNumber, buildProperties, util-list-changes, izpack-patches" >
|
<target name="installer-linux" depends="clean, preppkg-linux-only, izpack-patches" >
|
||||||
<mkdir dir="pkg-temp/installer" />
|
<izpack input="${basedir}/installer/install.xml" output="${basedir}/i2pinstall_${full.version}_linux-only.jar" installerType="standard" basedir="${basedir}" />
|
||||||
<!-- set if unset -->
|
|
||||||
<property name="workspace.changes.util.tr" value="" />
|
|
||||||
<izpack input="${basedir}/installer/install.xml" output="${basedir}/i2pinstall_${release.number}-${i2p.build.number}${build.extra}_linux-only.jar" installerType="standard" basedir="${basedir}" />
|
|
||||||
</target>
|
</target>
|
||||||
|
|
||||||
|
|
||||||
<target name="installer-osx" depends="clean, checkForIzpack2App, preppkg-osx-only, getReleaseNumber, getBuildNumber, buildProperties, util-list-changes, izpack-patches">
|
<target name="installer-osx" depends="clean, checkForIzpack2App, preppkg-osx-only, izpack-patches">
|
||||||
<mkdir dir="pkg-temp/installer" />
|
|
||||||
<mkdir dir="pkg-temp/osx" />
|
<mkdir dir="pkg-temp/osx" />
|
||||||
<!-- set if unset -->
|
<izpack input="${basedir}/installer/install.xml" output="${basedir}/i2pinstall_${full.version}_osx-only.jar" installerType="standard" basedir="${basedir}" />
|
||||||
<property name="workspace.changes.util.tr" value="" />
|
|
||||||
<izpack input="${basedir}/installer/install.xml" output="${basedir}/i2pinstall_${release.number}-${i2p.build.number}${build.extra}_osx-only.jar" installerType="standard" basedir="${basedir}" />
|
|
||||||
<ant target="installer2app" />
|
<ant target="installer2app" />
|
||||||
<delete dir="pkg-temp/osx" />
|
<delete dir="pkg-temp/osx" />
|
||||||
</target>
|
</target>
|
||||||
@@ -1218,34 +1222,32 @@
|
|||||||
<mkdir dir="pkg-temp/osx" />
|
<mkdir dir="pkg-temp/osx" />
|
||||||
<exec executable="python" failonerror="true">
|
<exec executable="python" failonerror="true">
|
||||||
<arg value="${user.home}/IzPack/utils/wrappers/izpack2app/izpack2app.py" />
|
<arg value="${user.home}/IzPack/utils/wrappers/izpack2app/izpack2app.py" />
|
||||||
<arg value="${basedir}/i2pinstall_${release.number}-${i2p.build.number}${build.extra}_osx-only.jar" />
|
<arg value="${basedir}/i2pinstall_${full.version}_osx-only.jar" />
|
||||||
<arg value="${basedir}/pkg-temp/osx/i2p-${release.number}-${i2p.build.number}${build.extra}_osx-install.app" />
|
<arg value="${basedir}/pkg-temp/osx/i2p-${full.version}_osx-install.app" />
|
||||||
</exec>
|
</exec>
|
||||||
<exec executable="chmod" failonerror="true" osfamily="unix">
|
<exec executable="chmod" failonerror="true" osfamily="unix">
|
||||||
<arg value="755" />
|
<arg value="755" />
|
||||||
<arg value="${basedir}/pkg-temp/osx/i2p-${release.number}-${i2p.build.number}${build.extra}_osx-install.app/Contents/MacOS/JavaApplicationStub" />
|
<arg value="${basedir}/pkg-temp/osx/i2p-${full.version}_osx-install.app/Contents/MacOS/JavaApplicationStub" />
|
||||||
</exec>
|
</exec>
|
||||||
<exec executable="tar" osfamily="unix" failonerror="true">
|
<exec executable="tar" osfamily="unix" failonerror="true">
|
||||||
<arg value="--owner=root" />
|
<arg value="--owner=root" />
|
||||||
<arg value="--group=root" />
|
<arg value="--group=root" />
|
||||||
<arg value="-cjvf" />
|
<arg value="-cjvf" />
|
||||||
<arg value="${basedir}/i2pinstall_${release.number}-${i2p.build.number}${build.extra}_osx.tar.bz2" />
|
<arg value="${basedir}/i2pinstall_${full.version}_osx.tar.bz2" />
|
||||||
<arg value="-C" />
|
<arg value="-C" />
|
||||||
<arg value="${basedir}/pkg-temp/osx" />
|
<arg value="${basedir}/pkg-temp/osx" />
|
||||||
<arg value="i2p-${release.number}-${i2p.build.number}${build.extra}_osx-install.app" />
|
<arg value="i2p-${full.version}_osx-install.app" />
|
||||||
</exec>
|
</exec>
|
||||||
</target>
|
</target>
|
||||||
|
|
||||||
<!-- Yes, even though this makes an installer for Windows, we still need to depend on preppkg-unix (because the installer attempts to delete these files
|
<target name="installer-windows" depends="clean, preppkg-windows-only, util-list-changes, izpack-patches" >
|
||||||
and will fail if they don't exist. Thankfully these files are so very small there's not much harm in including them.
|
|
||||||
-->
|
|
||||||
<target name="installer-windows" depends="clean, doBuildEXE, preppkg-windows-only, preppkg-unix, getReleaseNumber, getBuildNumber, buildProperties, util-list-changes, izpack-patches" >
|
|
||||||
<mkdir dir="pkg-temp/installer" />
|
<mkdir dir="pkg-temp/installer" />
|
||||||
<!-- set if unset -->
|
<!-- set if unset -->
|
||||||
<property name="workspace.changes.util.tr" value="" />
|
<property name="workspace.changes.util.tr" value="" />
|
||||||
<jar destfile="./pkg-temp/installer/copy.jar" basedir="./core/java/build/obj" includes="net/i2p/util/Copy.class net/i2p/util/FileUtil.class">
|
<jar destfile="./pkg-temp/installer/copy.jar" basedir="./core/java/build/obj" includes="net/i2p/util/Copy.class net/i2p/util/FileUtil.class">
|
||||||
<manifest>
|
<manifest>
|
||||||
<attribute name="Main-Class" value="net.i2p.util.Copy" />
|
<attribute name="Main-Class" value="net.i2p.util.Copy" />
|
||||||
|
<attribute name="Built-By" value="${build.built-by}" />
|
||||||
<attribute name="Build-Date" value="${build.timestamp}" />
|
<attribute name="Build-Date" value="${build.timestamp}" />
|
||||||
<attribute name="Base-Revision" value="${workspace.version}" />
|
<attribute name="Base-Revision" value="${workspace.version}" />
|
||||||
<attribute name="Workspace-Changes" value="${workspace.changes.util.tr}" />
|
<attribute name="Workspace-Changes" value="${workspace.changes.util.tr}" />
|
||||||
@@ -1254,6 +1256,7 @@
|
|||||||
<jar destfile="./pkg-temp/installer/delete.jar" basedir="./core/java/build/obj" includes="net/i2p/util/Delete.class net/i2p/util/FileUtil.class">
|
<jar destfile="./pkg-temp/installer/delete.jar" basedir="./core/java/build/obj" includes="net/i2p/util/Delete.class net/i2p/util/FileUtil.class">
|
||||||
<manifest>
|
<manifest>
|
||||||
<attribute name="Main-Class" value="net.i2p.util.Delete" />
|
<attribute name="Main-Class" value="net.i2p.util.Delete" />
|
||||||
|
<attribute name="Built-By" value="${build.built-by}" />
|
||||||
<attribute name="Build-Date" value="${build.timestamp}" />
|
<attribute name="Build-Date" value="${build.timestamp}" />
|
||||||
<attribute name="Base-Revision" value="${workspace.version}" />
|
<attribute name="Base-Revision" value="${workspace.version}" />
|
||||||
<attribute name="Workspace-Changes" value="${workspace.changes.util.tr}" />
|
<attribute name="Workspace-Changes" value="${workspace.changes.util.tr}" />
|
||||||
@@ -1262,13 +1265,16 @@
|
|||||||
<jar destfile="./pkg-temp/installer/exec.jar" basedir="./core/java/build/obj" includes="net/i2p/util/Exec.class">
|
<jar destfile="./pkg-temp/installer/exec.jar" basedir="./core/java/build/obj" includes="net/i2p/util/Exec.class">
|
||||||
<manifest>
|
<manifest>
|
||||||
<attribute name="Main-Class" value="net.i2p.util.Exec" />
|
<attribute name="Main-Class" value="net.i2p.util.Exec" />
|
||||||
|
<attribute name="Built-By" value="${build.built-by}" />
|
||||||
<attribute name="Build-Date" value="${build.timestamp}" />
|
<attribute name="Build-Date" value="${build.timestamp}" />
|
||||||
<attribute name="Base-Revision" value="${workspace.version}" />
|
<attribute name="Base-Revision" value="${workspace.version}" />
|
||||||
<attribute name="Workspace-Changes" value="${workspace.changes.util.tr}" />
|
<attribute name="Workspace-Changes" value="${workspace.changes.util.tr}" />
|
||||||
</manifest>
|
</manifest>
|
||||||
</jar>
|
</jar>
|
||||||
<izpack input="${basedir}/installer/install.xml" output="${basedir}/i2pinstall_${release.number}-${i2p.build.number}${build.extra}_windows-only.jar" installerType="standard" basedir="${basedir}" />
|
<izpack input="${basedir}/installer/install.xml" output="${basedir}/install.jar" installerType="standard" basedir="${basedir}" />
|
||||||
<delete dir="pkg-temp/win" />
|
<ant target="installerexe" />
|
||||||
|
<delete file="${basedir}/install.jar" />
|
||||||
|
<move file="${basedir}/i2pinstall.exe" tofile="${basedir}/i2pinstall_${full.version}_windows-only.exe" />
|
||||||
</target>
|
</target>
|
||||||
|
|
||||||
<target name="installer-all" depends="installer-freebsd, installer-linux, installer-osx, installer-windows, installer" >
|
<target name="installer-all" depends="installer-freebsd, installer-linux, installer-osx, installer-windows, installer" >
|
||||||
@@ -1383,8 +1389,9 @@
|
|||||||
<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.exe" tofile="i2pinstall_${release.number}.exe" />
|
<copy file="i2pinstall.exe" tofile="i2pinstall_${release.number}.exe" />
|
||||||
<delete file="i2pupdate.sud" failonerror="false" />
|
<delete file="i2pupdate.sud" />
|
||||||
<delete file="i2pupdate.su2" failonerror="false" />
|
<delete file="i2pupdate.su2" />
|
||||||
|
<!-- make this a lot easier by putting release.privkey=/path/to/privkey in override.properties -->
|
||||||
<input message="Enter private signing key file:" addproperty="release.privkey" />
|
<input message="Enter private signing key file:" addproperty="release.privkey" />
|
||||||
<fail message="You must enter a path." >
|
<fail message="You must enter a path." >
|
||||||
<condition>
|
<condition>
|
||||||
@@ -1494,6 +1501,17 @@
|
|||||||
<arg value="-b" />
|
<arg value="-b" />
|
||||||
<arg value="i2pupdate_${release.number}.zip" />
|
<arg value="i2pupdate_${release.number}.zip" />
|
||||||
</exec>
|
</exec>
|
||||||
|
<exec executable="chmod" failonerror="true">
|
||||||
|
<arg value="444" />
|
||||||
|
<arg value="i2pinstall_${release.number}.exe" />
|
||||||
|
<arg value="i2psource_${release.number}.tar.bz2" />
|
||||||
|
<arg value="i2pupdate_${release.number}.zip" />
|
||||||
|
<arg value="i2pupdate.su2" />
|
||||||
|
<arg value="i2pupdate.sud" />
|
||||||
|
<arg value="i2pinstall_${release.number}.exe.sig" />
|
||||||
|
<arg value="i2psource_${release.number}.tar.bz2.sig" />
|
||||||
|
<arg value="i2pupdate_${release.number}.zip.sig" />
|
||||||
|
</exec>
|
||||||
<echo message="File sizes:" />
|
<echo message="File sizes:" />
|
||||||
<exec executable="ls" failonerror="true">
|
<exec executable="ls" failonerror="true">
|
||||||
<arg value="-l" />
|
<arg value="-l" />
|
||||||
|
@@ -59,6 +59,7 @@
|
|||||||
<jar destfile="./build/i2p.jar" basedir="./build/obj" includes="**/*.class" >
|
<jar destfile="./build/i2p.jar" basedir="./build/obj" includes="**/*.class" >
|
||||||
<manifest>
|
<manifest>
|
||||||
<attribute name="Implementation-Version" value="${full.version}" />
|
<attribute name="Implementation-Version" value="${full.version}" />
|
||||||
|
<attribute name="Built-By" value="${build.built-by}" />
|
||||||
<attribute name="Build-Date" value="${build.timestamp}" />
|
<attribute name="Build-Date" value="${build.timestamp}" />
|
||||||
<attribute name="Base-Revision" value="${workspace.version}" />
|
<attribute name="Base-Revision" value="${workspace.version}" />
|
||||||
<attribute name="Workspace-Changes" value="${workspace.changes.tr}" />
|
<attribute name="Workspace-Changes" value="${workspace.changes.tr}" />
|
||||||
|
@@ -34,7 +34,7 @@ import net.i2p.util.Log;
|
|||||||
* @author jrandom
|
* @author jrandom
|
||||||
*/
|
*/
|
||||||
class RequestLeaseSetMessageHandler extends HandlerImpl {
|
class RequestLeaseSetMessageHandler extends HandlerImpl {
|
||||||
private final Map _existingLeaseSets;
|
private final Map<Destination, LeaseInfo> _existingLeaseSets;
|
||||||
|
|
||||||
public RequestLeaseSetMessageHandler(I2PAppContext context) {
|
public RequestLeaseSetMessageHandler(I2PAppContext context) {
|
||||||
super(context, RequestLeaseSetMessage.MESSAGE_TYPE);
|
super(context, RequestLeaseSetMessage.MESSAGE_TYPE);
|
||||||
@@ -59,7 +59,7 @@ class RequestLeaseSetMessageHandler extends HandlerImpl {
|
|||||||
leaseSet.setDestination(session.getMyDestination());
|
leaseSet.setDestination(session.getMyDestination());
|
||||||
|
|
||||||
// reuse the old keys for the client
|
// reuse the old keys for the client
|
||||||
LeaseInfo li = (LeaseInfo) _existingLeaseSets.get(session.getMyDestination());
|
LeaseInfo li = _existingLeaseSets.get(session.getMyDestination());
|
||||||
if (li == null) {
|
if (li == null) {
|
||||||
li = new LeaseInfo(session.getMyDestination());
|
li = new LeaseInfo(session.getMyDestination());
|
||||||
_existingLeaseSets.put(session.getMyDestination(), li);
|
_existingLeaseSets.put(session.getMyDestination(), li);
|
||||||
@@ -98,11 +98,11 @@ class RequestLeaseSetMessageHandler extends HandlerImpl {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private static class LeaseInfo {
|
private static class LeaseInfo {
|
||||||
private PublicKey _pubKey;
|
private final PublicKey _pubKey;
|
||||||
private PrivateKey _privKey;
|
private final PrivateKey _privKey;
|
||||||
private SigningPublicKey _signingPubKey;
|
private final SigningPublicKey _signingPubKey;
|
||||||
private SigningPrivateKey _signingPrivKey;
|
private final SigningPrivateKey _signingPrivKey;
|
||||||
private Destination _dest;
|
private final Destination _dest;
|
||||||
|
|
||||||
public LeaseInfo(Destination dest) {
|
public LeaseInfo(Destination dest) {
|
||||||
_dest = dest;
|
_dest = dest;
|
||||||
|
@@ -92,6 +92,7 @@ public class BlockfileNamingService extends DummyNamingService {
|
|||||||
private final RAIFile _raf;
|
private final RAIFile _raf;
|
||||||
private final List<String> _lists;
|
private final List<String> _lists;
|
||||||
private final List<InvalidEntry> _invalid;
|
private final List<InvalidEntry> _invalid;
|
||||||
|
private final Map<String, String> _negativeCache;
|
||||||
private volatile boolean _isClosed;
|
private volatile boolean _isClosed;
|
||||||
private final boolean _readOnly;
|
private final boolean _readOnly;
|
||||||
private boolean _needsUpgrade;
|
private boolean _needsUpgrade;
|
||||||
@@ -118,6 +119,9 @@ public class BlockfileNamingService extends DummyNamingService {
|
|||||||
private static final String PROP_ADDED = "a";
|
private static final String PROP_ADDED = "a";
|
||||||
private static final String PROP_SOURCE = "s";
|
private static final String PROP_SOURCE = "s";
|
||||||
|
|
||||||
|
private static final String DUMMY = "";
|
||||||
|
private static final int NEGATIVE_CACHE_SIZE = 32;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Opens the database at hostsdb.blockfile or creates a new
|
* Opens the database at hostsdb.blockfile or creates a new
|
||||||
* one and imports entries from hosts.txt, userhosts.txt, and privatehosts.txt.
|
* one and imports entries from hosts.txt, userhosts.txt, and privatehosts.txt.
|
||||||
@@ -132,6 +136,7 @@ public class BlockfileNamingService extends DummyNamingService {
|
|||||||
super(context);
|
super(context);
|
||||||
_lists = new ArrayList();
|
_lists = new ArrayList();
|
||||||
_invalid = new ArrayList();
|
_invalid = new ArrayList();
|
||||||
|
_negativeCache = new LHM(NEGATIVE_CACHE_SIZE);
|
||||||
BlockFile bf = null;
|
BlockFile bf = null;
|
||||||
RAIFile raf = null;
|
RAIFile raf = null;
|
||||||
boolean readOnly = false;
|
boolean readOnly = false;
|
||||||
@@ -628,6 +633,10 @@ public class BlockfileNamingService extends DummyNamingService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
String key = hostname.toLowerCase(Locale.US);
|
String key = hostname.toLowerCase(Locale.US);
|
||||||
|
synchronized(_negativeCache) {
|
||||||
|
if (_negativeCache.get(key) != null)
|
||||||
|
return null;
|
||||||
|
}
|
||||||
synchronized(_bf) {
|
synchronized(_bf) {
|
||||||
if (_isClosed)
|
if (_isClosed)
|
||||||
return null;
|
return null;
|
||||||
@@ -650,8 +659,13 @@ public class BlockfileNamingService extends DummyNamingService {
|
|||||||
}
|
}
|
||||||
deleteInvalid();
|
deleteInvalid();
|
||||||
}
|
}
|
||||||
if (d != null)
|
if (d != null) {
|
||||||
putCache(hostname, d);
|
putCache(hostname, d);
|
||||||
|
} else {
|
||||||
|
synchronized(_negativeCache) {
|
||||||
|
_negativeCache.put(key, DUMMY);
|
||||||
|
}
|
||||||
|
}
|
||||||
return d;
|
return d;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -683,6 +697,9 @@ public class BlockfileNamingService extends DummyNamingService {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
String key = hostname.toLowerCase(Locale.US);
|
String key = hostname.toLowerCase(Locale.US);
|
||||||
|
synchronized(_negativeCache) {
|
||||||
|
_negativeCache.remove(key);
|
||||||
|
}
|
||||||
String listname = FALLBACK_LIST;
|
String listname = FALLBACK_LIST;
|
||||||
Properties props = new Properties();
|
Properties props = new Properties();
|
||||||
props.setProperty(PROP_ADDED, Long.toString(_context.clock().now()));
|
props.setProperty(PROP_ADDED, Long.toString(_context.clock().now()));
|
||||||
@@ -1031,6 +1048,9 @@ public class BlockfileNamingService extends DummyNamingService {
|
|||||||
}
|
}
|
||||||
_isClosed = true;
|
_isClosed = true;
|
||||||
}
|
}
|
||||||
|
synchronized(_negativeCache) {
|
||||||
|
_negativeCache.clear();
|
||||||
|
}
|
||||||
clearCache();
|
clearCache();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -116,7 +116,7 @@ class DummyNamingService extends NamingService {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static class LHM<K, V> extends LinkedHashMap<K, V> {
|
protected static class LHM<K, V> extends LinkedHashMap<K, V> {
|
||||||
private final int _max;
|
private final int _max;
|
||||||
|
|
||||||
public LHM(int max) {
|
public LHM(int max) {
|
||||||
|
@@ -625,7 +625,7 @@ public class TransientSessionKeyManager extends SessionKeyManager {
|
|||||||
OutboundSession sess = iter.next();
|
OutboundSession sess = iter.next();
|
||||||
Set<TagSet> sets = new TreeSet(new TagSetComparator());
|
Set<TagSet> sets = new TreeSet(new TagSetComparator());
|
||||||
sets.addAll(sess.getTagSets());
|
sets.addAll(sess.getTagSets());
|
||||||
buf.append("<tr><td><b>Target key:</b> ").append(sess.getTarget().toBase64().substring(0, 64)).append("<br>" +
|
buf.append("<tr><td><b>Target public key:</b> ").append(sess.getTarget().toBase64().substring(0, 20)).append("...<br>" +
|
||||||
"<b>Established:</b> ").append(DataHelper.formatDuration(now - sess.getEstablishedDate())).append(" ago<br>" +
|
"<b>Established:</b> ").append(DataHelper.formatDuration(now - sess.getEstablishedDate())).append(" ago<br>" +
|
||||||
"<b>Last Used:</b> ").append(DataHelper.formatDuration(now - sess.getLastUsedDate())).append(" ago<br>" +
|
"<b>Last Used:</b> ").append(DataHelper.formatDuration(now - sess.getLastUsedDate())).append(" ago<br>" +
|
||||||
"<b>Session key:</b> ").append(sess.getCurrentKey().toBase64()).append("</td>" +
|
"<b>Session key:</b> ").append(sess.getCurrentKey().toBase64()).append("</td>" +
|
||||||
|
@@ -29,7 +29,7 @@ import net.i2p.util.Log;
|
|||||||
*/
|
*/
|
||||||
public class Base32 {
|
public class Base32 {
|
||||||
|
|
||||||
private final static Log _log = new Log(Base32.class);
|
//private final static Log _log = new Log(Base32.class);
|
||||||
|
|
||||||
/** The 32 valid Base32 values. */
|
/** The 32 valid Base32 values. */
|
||||||
private final static char[] ALPHABET = {'a', 'b', 'c', 'd',
|
private final static char[] ALPHABET = {'a', 'b', 'c', 'd',
|
||||||
@@ -248,12 +248,12 @@ public class Base32 {
|
|||||||
outBuff[outBuffPosn] = next;
|
outBuff[outBuffPosn] = next;
|
||||||
usedbits -= 3;
|
usedbits -= 3;
|
||||||
} else if (next != 0) {
|
} else if (next != 0) {
|
||||||
_log.warn("Extra data at the end: " + next + "(decimal)");
|
//_log.warn("Extra data at the end: " + next + "(decimal)");
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
_log.warn("Bad Base32 input character at " + i + ": " + source[i] + "(decimal)");
|
//_log.warn("Bad Base32 input character at " + i + ": " + source[i] + "(decimal)");
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -41,7 +41,7 @@ import net.i2p.util.Log;
|
|||||||
*/
|
*/
|
||||||
public class Base64 {
|
public class Base64 {
|
||||||
|
|
||||||
private final static Log _log = new Log(Base64.class);
|
//private final static Log _log = new Log(Base64.class);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param source if null will return ""
|
* @param source if null will return ""
|
||||||
@@ -750,7 +750,7 @@ public class Base64 {
|
|||||||
|
|
||||||
} // end if: white space, equals sign or better
|
} // end if: white space, equals sign or better
|
||||||
else {
|
else {
|
||||||
_log.warn("Bad Base64 input character at " + i + ": " + source[i] + "(decimal)");
|
//_log.warn("Bad Base64 input character at " + i + ": " + source[i] + "(decimal)");
|
||||||
return null;
|
return null;
|
||||||
} // end else:
|
} // end else:
|
||||||
} // each input character
|
} // each input character
|
||||||
|
@@ -1299,10 +1299,20 @@ public class DataHelper {
|
|||||||
// rv.add(struct);
|
// rv.add(struct);
|
||||||
//}
|
//}
|
||||||
ArrayList<DataStructure> rv = new ArrayList(dataStructures);
|
ArrayList<DataStructure> rv = new ArrayList(dataStructures);
|
||||||
Collections.sort(rv, new DataStructureComparator());
|
sortStructureList(rv);
|
||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* See above.
|
||||||
|
* DEPRECATED - Only used by RouterInfo.
|
||||||
|
*
|
||||||
|
* @since 0.9
|
||||||
|
*/
|
||||||
|
static void sortStructureList(List<? extends DataStructure> dataStructures) {
|
||||||
|
Collections.sort(dataStructures, new DataStructureComparator());
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* See sortStructures() comments.
|
* See sortStructures() comments.
|
||||||
* @since 0.8.3
|
* @since 0.8.3
|
||||||
|
@@ -14,6 +14,7 @@ import java.io.ByteArrayOutputStream;
|
|||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
|
|
||||||
|
import net.i2p.I2PAppContext;
|
||||||
import net.i2p.crypto.SHA256Generator;
|
import net.i2p.crypto.SHA256Generator;
|
||||||
import net.i2p.util.Log;
|
import net.i2p.util.Log;
|
||||||
|
|
||||||
@@ -23,7 +24,6 @@ import net.i2p.util.Log;
|
|||||||
* @author jrandom
|
* @author jrandom
|
||||||
*/
|
*/
|
||||||
public abstract class DataStructureImpl implements DataStructure {
|
public abstract class DataStructureImpl implements DataStructure {
|
||||||
private final static Log _log = new Log(DataStructureImpl.class);
|
|
||||||
|
|
||||||
public String toBase64() {
|
public String toBase64() {
|
||||||
byte data[] = toByteArray();
|
byte data[] = toByteArray();
|
||||||
@@ -48,10 +48,12 @@ public abstract class DataStructureImpl implements DataStructure {
|
|||||||
writeBytes(baos);
|
writeBytes(baos);
|
||||||
return baos.toByteArray();
|
return baos.toByteArray();
|
||||||
} catch (IOException ioe) {
|
} catch (IOException ioe) {
|
||||||
_log.error("Error writing out the byte array", ioe);
|
Log log = I2PAppContext.getGlobalContext().logManager().getLog(getClass());
|
||||||
|
log.error("Error writing out the byte array", ioe);
|
||||||
return null;
|
return null;
|
||||||
} catch (DataFormatException dfe) {
|
} catch (DataFormatException dfe) {
|
||||||
_log.error("Error writing out the byte array", dfe);
|
Log log = I2PAppContext.getGlobalContext().logManager().getLog(getClass());
|
||||||
|
log.error("Error writing out the byte array", dfe);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -73,4 +75,4 @@ public abstract class DataStructureImpl implements DataStructure {
|
|||||||
protected int read(InputStream in, byte target[]) throws IOException {
|
protected int read(InputStream in, byte target[]) throws IOException {
|
||||||
return DataHelper.read(in, target);
|
return DataHelper.read(in, target);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -26,8 +26,8 @@ public class Lease extends DataStructureImpl {
|
|||||||
private Hash _gateway;
|
private Hash _gateway;
|
||||||
private TunnelId _tunnelId;
|
private TunnelId _tunnelId;
|
||||||
private Date _end;
|
private Date _end;
|
||||||
private int _numSuccess;
|
//private int _numSuccess;
|
||||||
private int _numFailure;
|
//private int _numFailure;
|
||||||
|
|
||||||
public Lease() {
|
public Lease() {
|
||||||
}
|
}
|
||||||
@@ -74,14 +74,18 @@ public class Lease extends DataStructureImpl {
|
|||||||
*
|
*
|
||||||
* @deprecated unused
|
* @deprecated unused
|
||||||
*/
|
*/
|
||||||
|
/****
|
||||||
public int getNumSuccess() {
|
public int getNumSuccess() {
|
||||||
return _numSuccess;
|
return _numSuccess;
|
||||||
}
|
}
|
||||||
|
****/
|
||||||
|
|
||||||
/** @deprecated unused */
|
/** @deprecated unused */
|
||||||
|
/****
|
||||||
public void setNumSuccess(int num) {
|
public void setNumSuccess(int num) {
|
||||||
_numSuccess = num;
|
_numSuccess = num;
|
||||||
}
|
}
|
||||||
|
****/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Transient attribute of the lease, used to note how many times messages sent
|
* Transient attribute of the lease, used to note how many times messages sent
|
||||||
@@ -89,14 +93,18 @@ public class Lease extends DataStructureImpl {
|
|||||||
*
|
*
|
||||||
* @deprecated unused
|
* @deprecated unused
|
||||||
*/
|
*/
|
||||||
|
/****
|
||||||
public int getNumFailure() {
|
public int getNumFailure() {
|
||||||
return _numFailure;
|
return _numFailure;
|
||||||
}
|
}
|
||||||
|
****/
|
||||||
|
|
||||||
/** @deprecated unused */
|
/** @deprecated unused */
|
||||||
|
/****
|
||||||
public void setNumFailure(int num) {
|
public void setNumFailure(int num) {
|
||||||
_numFailure = num;
|
_numFailure = num;
|
||||||
}
|
}
|
||||||
|
****/
|
||||||
|
|
||||||
/** has this lease already expired? */
|
/** has this lease already expired? */
|
||||||
public boolean isExpired() {
|
public boolean isExpired() {
|
||||||
|
@@ -56,7 +56,6 @@ import net.i2p.util.RandomSource;
|
|||||||
* @author jrandom
|
* @author jrandom
|
||||||
*/
|
*/
|
||||||
public class LeaseSet extends DatabaseEntry {
|
public class LeaseSet extends DatabaseEntry {
|
||||||
private final static Log _log = new Log(LeaseSet.class);
|
|
||||||
private Destination _destination;
|
private Destination _destination;
|
||||||
private PublicKey _encryptionKey;
|
private PublicKey _encryptionKey;
|
||||||
private SigningPublicKey _signingKey;
|
private SigningPublicKey _signingKey;
|
||||||
@@ -71,11 +70,26 @@ public class LeaseSet extends DatabaseEntry {
|
|||||||
private boolean _decrypted;
|
private boolean _decrypted;
|
||||||
private boolean _checked;
|
private boolean _checked;
|
||||||
|
|
||||||
/** This seems like plenty */
|
/**
|
||||||
public final static int MAX_LEASES = 6;
|
* Unlimited before 0.6.3;
|
||||||
|
* 6 as of 0.6.3;
|
||||||
|
* Increased in version 0.9.
|
||||||
|
*
|
||||||
|
* Leasesets larger than 6 should be used with caution,
|
||||||
|
* as each lease adds 44 bytes, and routers older than version 0.9
|
||||||
|
* will not be able to connect as they will throw an exception in
|
||||||
|
* readBytes(). Also, the churn will be quite rapid, leading to
|
||||||
|
* frequent netdb stores and transmission on existing connections.
|
||||||
|
*
|
||||||
|
* However we increase it now in case some hugely popular eepsite arrives.
|
||||||
|
* Strategies elsewhere in the router to efficiently handle
|
||||||
|
* large leasesets are TBD.
|
||||||
|
*/
|
||||||
|
public static final int MAX_LEASES = 16;
|
||||||
|
private static final int OLD_MAX_LEASES = 6;
|
||||||
|
|
||||||
public LeaseSet() {
|
public LeaseSet() {
|
||||||
_leases = new ArrayList(MAX_LEASES);
|
_leases = new ArrayList(OLD_MAX_LEASES);
|
||||||
_firstExpiration = Long.MAX_VALUE;
|
_firstExpiration = Long.MAX_VALUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -354,14 +368,16 @@ public class LeaseSet extends DatabaseEntry {
|
|||||||
* Must be called after all the leases are in place, but before sign().
|
* Must be called after all the leases are in place, but before sign().
|
||||||
*/
|
*/
|
||||||
public void encrypt(SessionKey key) {
|
public void encrypt(SessionKey key) {
|
||||||
if (_log.shouldLog(Log.WARN))
|
//if (_log.shouldLog(Log.WARN))
|
||||||
_log.warn("encrypting lease: " + _destination.calculateHash());
|
// _log.warn("encrypting lease: " + _destination.calculateHash());
|
||||||
try {
|
try {
|
||||||
encryp(key);
|
encryp(key);
|
||||||
} catch (DataFormatException dfe) {
|
} catch (DataFormatException dfe) {
|
||||||
_log.error("Error encrypting lease: " + _destination.calculateHash());
|
Log log = I2PAppContext.getGlobalContext().logManager().getLog(LeaseSet.class);
|
||||||
|
log.error("Error encrypting lease: " + _destination.calculateHash());
|
||||||
} catch (IOException ioe) {
|
} catch (IOException ioe) {
|
||||||
_log.error("Error encrypting lease: " + _destination.calculateHash());
|
Log log = I2PAppContext.getGlobalContext().logManager().getLog(LeaseSet.class);
|
||||||
|
log.error("Error encrypting lease: " + _destination.calculateHash());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -420,8 +436,8 @@ public class LeaseSet extends DatabaseEntry {
|
|||||||
* encrypted leaseset can be sent on to others (via writeBytes())
|
* encrypted leaseset can be sent on to others (via writeBytes())
|
||||||
*/
|
*/
|
||||||
private void decrypt(SessionKey key) throws DataFormatException, IOException {
|
private void decrypt(SessionKey key) throws DataFormatException, IOException {
|
||||||
if (_log.shouldLog(Log.WARN))
|
//if (_log.shouldLog(Log.WARN))
|
||||||
_log.warn("decrypting lease: " + _destination.calculateHash());
|
// _log.warn("decrypting lease: " + _destination.calculateHash());
|
||||||
int size = _leases.size();
|
int size = _leases.size();
|
||||||
if (size < 2)
|
if (size < 2)
|
||||||
throw new DataFormatException("Bad number of leases for decryption");
|
throw new DataFormatException("Bad number of leases for decryption");
|
||||||
@@ -468,9 +484,11 @@ public class LeaseSet extends DatabaseEntry {
|
|||||||
decrypt(key);
|
decrypt(key);
|
||||||
_decrypted = true;
|
_decrypted = true;
|
||||||
} catch (DataFormatException dfe) {
|
} catch (DataFormatException dfe) {
|
||||||
_log.error("Error decrypting lease: " + _destination.calculateHash() + dfe);
|
Log log = I2PAppContext.getGlobalContext().logManager().getLog(LeaseSet.class);
|
||||||
|
log.error("Error decrypting lease: " + _destination.calculateHash() + dfe);
|
||||||
} catch (IOException ioe) {
|
} catch (IOException ioe) {
|
||||||
_log.error("Error decrypting lease: " + _destination.calculateHash() + ioe);
|
Log log = I2PAppContext.getGlobalContext().logManager().getLog(LeaseSet.class);
|
||||||
|
log.error("Error decrypting lease: " + _destination.calculateHash() + ioe);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_checked = true;
|
_checked = true;
|
||||||
|
@@ -26,7 +26,7 @@ import net.i2p.util.Log;
|
|||||||
* @author jrandom
|
* @author jrandom
|
||||||
*/
|
*/
|
||||||
public class Payload extends DataStructureImpl {
|
public class Payload extends DataStructureImpl {
|
||||||
private final static Log _log = new Log(Payload.class);
|
//private final static Log _log = new Log(Payload.class);
|
||||||
private byte[] _encryptedData;
|
private byte[] _encryptedData;
|
||||||
private byte[] _unencryptedData;
|
private byte[] _unencryptedData;
|
||||||
|
|
||||||
@@ -82,16 +82,16 @@ public class Payload extends DataStructureImpl {
|
|||||||
_encryptedData = new byte[size];
|
_encryptedData = new byte[size];
|
||||||
int read = read(in, _encryptedData);
|
int read = read(in, _encryptedData);
|
||||||
if (read != size) throw new DataFormatException("Incorrect number of bytes read in the payload structure");
|
if (read != size) throw new DataFormatException("Incorrect number of bytes read in the payload structure");
|
||||||
if (_log.shouldLog(Log.DEBUG))
|
//if (_log.shouldLog(Log.DEBUG))
|
||||||
_log.debug("read payload: " + read + " bytes");
|
// _log.debug("read payload: " + read + " bytes");
|
||||||
}
|
}
|
||||||
|
|
||||||
public void writeBytes(OutputStream out) throws DataFormatException, IOException {
|
public void writeBytes(OutputStream out) throws DataFormatException, IOException {
|
||||||
if (_encryptedData == null) throw new DataFormatException("Not yet encrypted. Please set the encrypted data");
|
if (_encryptedData == null) throw new DataFormatException("Not yet encrypted. Please set the encrypted data");
|
||||||
DataHelper.writeLong(out, 4, _encryptedData.length);
|
DataHelper.writeLong(out, 4, _encryptedData.length);
|
||||||
out.write(_encryptedData);
|
out.write(_encryptedData);
|
||||||
if (_log.shouldLog(Log.DEBUG))
|
//if (_log.shouldLog(Log.DEBUG))
|
||||||
_log.debug("wrote payload: " + _encryptedData.length);
|
// _log.debug("wrote payload: " + _encryptedData.length);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@@ -13,6 +13,7 @@ import java.io.ByteArrayOutputStream;
|
|||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.io.OutputStream;
|
import java.io.OutputStream;
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
@@ -24,6 +25,7 @@ import java.util.Properties;
|
|||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.Vector;
|
import java.util.Vector;
|
||||||
|
|
||||||
|
import net.i2p.I2PAppContext;
|
||||||
import net.i2p.crypto.SHA256Generator;
|
import net.i2p.crypto.SHA256Generator;
|
||||||
import net.i2p.util.Clock;
|
import net.i2p.util.Clock;
|
||||||
import net.i2p.util.Log;
|
import net.i2p.util.Log;
|
||||||
@@ -43,10 +45,14 @@ import net.i2p.util.OrderedProperties;
|
|||||||
* @author jrandom
|
* @author jrandom
|
||||||
*/
|
*/
|
||||||
public class RouterInfo extends DatabaseEntry {
|
public class RouterInfo extends DatabaseEntry {
|
||||||
private final static Log _log = new Log(RouterInfo.class);
|
|
||||||
private RouterIdentity _identity;
|
private RouterIdentity _identity;
|
||||||
private volatile long _published;
|
private volatile long _published;
|
||||||
private final Set<RouterAddress> _addresses;
|
/**
|
||||||
|
* Addresses must be sorted by SHA256.
|
||||||
|
* When an RI is created, they are sorted in setAddresses().
|
||||||
|
* Save addresses in the order received so we need not resort.
|
||||||
|
*/
|
||||||
|
private final List<RouterAddress> _addresses;
|
||||||
/** may be null to save memory, no longer final */
|
/** may be null to save memory, no longer final */
|
||||||
private Set<Hash> _peers;
|
private Set<Hash> _peers;
|
||||||
private final Properties _options;
|
private final Properties _options;
|
||||||
@@ -71,7 +77,7 @@ public class RouterInfo extends DatabaseEntry {
|
|||||||
public static final String BW_CAPABILITY_CHARS = "KLMNO";
|
public static final String BW_CAPABILITY_CHARS = "KLMNO";
|
||||||
|
|
||||||
public RouterInfo() {
|
public RouterInfo() {
|
||||||
_addresses = new HashSet(2);
|
_addresses = new ArrayList(2);
|
||||||
_options = new OrderedProperties();
|
_options = new OrderedProperties();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -156,21 +162,33 @@ public class RouterInfo extends DatabaseEntry {
|
|||||||
*
|
*
|
||||||
* @return unmodifiable view, non-null
|
* @return unmodifiable view, non-null
|
||||||
*/
|
*/
|
||||||
public Set<RouterAddress> getAddresses() {
|
public Collection<RouterAddress> getAddresses() {
|
||||||
return Collections.unmodifiableSet(_addresses);
|
return Collections.unmodifiableCollection(_addresses);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Specify a set of RouterAddress structures at which this router
|
* Specify a set of RouterAddress structures at which this router
|
||||||
* can be contacted.
|
* can be contacted.
|
||||||
*
|
*
|
||||||
* @throws IllegalStateException if RouterInfo is already signed
|
* Warning - Sorts the addresses here. Do not modify any address
|
||||||
|
* after calling this, as the sort order is based on the
|
||||||
|
* hash of the entire address structure.
|
||||||
|
*
|
||||||
|
* @param addresses may be null
|
||||||
|
* @throws IllegalStateException if RouterInfo is already signed or addresses previously set
|
||||||
*/
|
*/
|
||||||
public void setAddresses(Set<RouterAddress> addresses) {
|
public void setAddresses(Collection<RouterAddress> addresses) {
|
||||||
if (_signature != null)
|
if (_signature != null || !_addresses.isEmpty())
|
||||||
throw new IllegalStateException();
|
throw new IllegalStateException();
|
||||||
_addresses.clear();
|
if (addresses != null) {
|
||||||
if (addresses != null) _addresses.addAll(addresses);
|
_addresses.addAll(addresses);
|
||||||
|
if (_addresses.size() > 1) {
|
||||||
|
// WARNING this sort algorithm cannot be changed, as it must be consistent
|
||||||
|
// network-wide. The signature is not checked at readin time, but only
|
||||||
|
// later, and the addresses are stored in a Set, not a List.
|
||||||
|
DataHelper.sortStructureList(_addresses);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -270,14 +288,7 @@ public class RouterInfo extends DatabaseEntry {
|
|||||||
DataHelper.writeLong(out, 1, 0);
|
DataHelper.writeLong(out, 1, 0);
|
||||||
} else {
|
} else {
|
||||||
DataHelper.writeLong(out, 1, sz);
|
DataHelper.writeLong(out, 1, sz);
|
||||||
Collection<RouterAddress> addresses = _addresses;
|
for (RouterAddress addr : _addresses) {
|
||||||
if (sz > 1) {
|
|
||||||
// WARNING this sort algorithm cannot be changed, as it must be consistent
|
|
||||||
// network-wide. The signature is not checked at readin time, but only
|
|
||||||
// later, and the addresses are stored in a Set, not a List.
|
|
||||||
addresses = (Collection<RouterAddress>) DataHelper.sortStructures(addresses);
|
|
||||||
}
|
|
||||||
for (RouterAddress addr : addresses) {
|
|
||||||
addr.writeBytes(out);
|
addr.writeBytes(out);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -458,16 +469,16 @@ public class RouterInfo extends DatabaseEntry {
|
|||||||
_validated = true;
|
_validated = true;
|
||||||
|
|
||||||
if (!_isValid) {
|
if (!_isValid) {
|
||||||
|
Log log = I2PAppContext.getGlobalContext().logManager().getLog(RouterInfo.class);
|
||||||
byte data[] = null;
|
byte data[] = null;
|
||||||
try {
|
try {
|
||||||
data = getBytes();
|
data = getBytes();
|
||||||
} catch (DataFormatException dfe) {
|
} catch (DataFormatException dfe) {
|
||||||
_log.error("Error validating", dfe);
|
log.error("Error validating", dfe);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (_log.shouldLog(Log.ERROR))
|
log.error("Invalid [" + SHA256Generator.getInstance().calculateHash(data).toBase64()
|
||||||
_log.error("Invalid [" + SHA256Generator.getInstance().calculateHash(data).toBase64()
|
+ (log.shouldLog(Log.WARN) ? ("]\n" + toString()) : ""),
|
||||||
+ (_log.shouldLog(Log.WARN) ? ("]\n" + toString()) : ""),
|
|
||||||
new Exception("Signature failed"));
|
new Exception("Signature failed"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -16,7 +16,7 @@ import net.i2p.I2PAppContext;
|
|||||||
/**
|
/**
|
||||||
* Wrapper class for whatever logging system I2P uses. This class should be
|
* Wrapper class for whatever logging system I2P uses. This class should be
|
||||||
* instantiated and kept as a variable for each class it is used by, ala:
|
* instantiated and kept as a variable for each class it is used by, ala:
|
||||||
* <code>private final static Log _log = new Log(MyClassName.class);</code>
|
* <code>private final Log _log = context.logManager().getLog(MyClassName.class);</code>
|
||||||
*
|
*
|
||||||
* If there is anything in here that doesn't make sense, turn off your computer
|
* If there is anything in here that doesn't make sense, turn off your computer
|
||||||
* and go fly a kite.
|
* and go fly a kite.
|
||||||
|
@@ -31,7 +31,6 @@ public class SimpleTimer2 {
|
|||||||
private static final int MIN_THREADS = 2;
|
private static final int MIN_THREADS = 2;
|
||||||
private static final int MAX_THREADS = 4;
|
private static final int MAX_THREADS = 4;
|
||||||
private final I2PAppContext _context;
|
private final I2PAppContext _context;
|
||||||
private static Log _log; // static so TimedEvent can use it
|
|
||||||
private final ScheduledThreadPoolExecutor _executor;
|
private final ScheduledThreadPoolExecutor _executor;
|
||||||
private final String _name;
|
private final String _name;
|
||||||
private int _count;
|
private int _count;
|
||||||
@@ -40,7 +39,6 @@ public class SimpleTimer2 {
|
|||||||
protected SimpleTimer2() { this("SimpleTimer2"); }
|
protected SimpleTimer2() { this("SimpleTimer2"); }
|
||||||
protected SimpleTimer2(String name) {
|
protected SimpleTimer2(String name) {
|
||||||
_context = I2PAppContext.getGlobalContext();
|
_context = I2PAppContext.getGlobalContext();
|
||||||
_log = _context.logManager().getLog(SimpleTimer2.class);
|
|
||||||
_name = name;
|
_name = name;
|
||||||
_count = 0;
|
_count = 0;
|
||||||
long maxMemory = Runtime.getRuntime().maxMemory();
|
long maxMemory = Runtime.getRuntime().maxMemory();
|
||||||
@@ -79,8 +77,10 @@ public class SimpleTimer2 {
|
|||||||
@Override
|
@Override
|
||||||
protected void afterExecute(Runnable r, Throwable t) {
|
protected void afterExecute(Runnable r, Throwable t) {
|
||||||
super.afterExecute(r, t);
|
super.afterExecute(r, t);
|
||||||
if (t != null) // shoudn't happen, caught in RunnableEvent.run()
|
if (t != null) { // shoudn't happen, caught in RunnableEvent.run()
|
||||||
_log.log(Log.CRIT, "wtf, event borked: " + r, t);
|
Log log = I2PAppContext.getGlobalContext().logManager().getLog(SimpleTimer2.class);
|
||||||
|
log.log(Log.CRIT, "wtf, event borked: " + r, t);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -126,6 +126,7 @@ public class SimpleTimer2 {
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public static abstract class TimedEvent implements Runnable {
|
public static abstract class TimedEvent implements Runnable {
|
||||||
|
private final Log _log;
|
||||||
private SimpleTimer2 _pool;
|
private SimpleTimer2 _pool;
|
||||||
private int _fuzz;
|
private int _fuzz;
|
||||||
protected static final int DEFAULT_FUZZ = 3;
|
protected static final int DEFAULT_FUZZ = 3;
|
||||||
@@ -136,7 +137,9 @@ public class SimpleTimer2 {
|
|||||||
public TimedEvent(SimpleTimer2 pool) {
|
public TimedEvent(SimpleTimer2 pool) {
|
||||||
_pool = pool;
|
_pool = pool;
|
||||||
_fuzz = DEFAULT_FUZZ;
|
_fuzz = DEFAULT_FUZZ;
|
||||||
|
_log = I2PAppContext.getGlobalContext().logManager().getLog(SimpleTimer2.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** automatically schedules, don't use this one if you have other things to do first */
|
/** automatically schedules, don't use this one if you have other things to do first */
|
||||||
public TimedEvent(SimpleTimer2 pool, long timeoutMs) {
|
public TimedEvent(SimpleTimer2 pool, long timeoutMs) {
|
||||||
this(pool);
|
this(pool);
|
||||||
|
33
history.txt
@@ -1,3 +1,36 @@
|
|||||||
|
2012-03-02 zzz
|
||||||
|
* BlockfileNamingService: Add negative cache
|
||||||
|
* Build: Add built-by to jars; check for corrupt jars on debug page
|
||||||
|
* configstats.jsp: Hide log settings unless already enabled
|
||||||
|
* DataStructures:
|
||||||
|
- Remove static logs
|
||||||
|
- Sort addresses in RouterInfo at initialization only;
|
||||||
|
change from Set to List to save space
|
||||||
|
- Remove unused counters in Lease to save space
|
||||||
|
- Increase max leases to 16
|
||||||
|
* Graphs:
|
||||||
|
- New single graph page with easy resizing
|
||||||
|
- Support graphing of previous intervals
|
||||||
|
* i2pinstall.exe: Add icon
|
||||||
|
* i2psnark:
|
||||||
|
- Add tracker configuration form
|
||||||
|
- Remove custom tracker option from create form
|
||||||
|
- Add private torrent option
|
||||||
|
- More icons in buttons
|
||||||
|
- Use js for refresh
|
||||||
|
* I2PTunnelHTTPClient:
|
||||||
|
- Refactoring to use Java URI parser to better handle
|
||||||
|
escapes, IPv6 addresses, ports
|
||||||
|
- Rewrite i2paddresshelper scanning/removal
|
||||||
|
- Refactor out local server code
|
||||||
|
- Nicer address helper error page
|
||||||
|
* NetDB:
|
||||||
|
- Reenable verify of RI stores, disabled in 0.7.9,
|
||||||
|
checkin comments claim reenabled in 0.7.10 but didn't happen.
|
||||||
|
- Synchronize StoreJob.sendNext() to avoid dups
|
||||||
|
* netdb.jsp: Fix debug leaseset count again
|
||||||
|
* susidns: Add b64 hash to details page
|
||||||
|
|
||||||
* 2012-02-27 0.8.13 released
|
* 2012-02-27 0.8.13 released
|
||||||
|
|
||||||
2012-02-22 kytv
|
2012-02-22 kytv
|
||||||
|
@@ -5,7 +5,7 @@
|
|||||||
<errTitle>I2P Installer</errTitle>
|
<errTitle>I2P Installer</errTitle>
|
||||||
<chdir>.</chdir>
|
<chdir>.</chdir>
|
||||||
<customProcName>false</customProcName>
|
<customProcName>false</customProcName>
|
||||||
<!--<icon>SimpleApp.ico</icon>-->
|
<icon>resources/console.ico</icon>
|
||||||
<jre>
|
<jre>
|
||||||
<minVersion>1.5.0</minVersion>
|
<minVersion>1.5.0</minVersion>
|
||||||
</jre>
|
</jre>
|
||||||
|
@@ -1,7 +1,7 @@
|
|||||||
<launch4jConfig>
|
<launch4jConfig>
|
||||||
<headerType>0</headerType>
|
<headerType>0</headerType>
|
||||||
<jar>../build/launchi2p.jar</jar>
|
<jar>../build/launchi2p.jar</jar>
|
||||||
<outfile>../i2p.exe</outfile>
|
<outfile>../build/i2p.exe</outfile>
|
||||||
<errTitle>I2P</errTitle>
|
<errTitle>I2P</errTitle>
|
||||||
<chdir>.</chdir>
|
<chdir>.</chdir>
|
||||||
<customProcName>false</customProcName>
|
<customProcName>false</customProcName>
|
||||||
|
23
installer/resources/proxy/ahelper-notfound-header.ht
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
HTTP/1.1 409 Bad Helper
|
||||||
|
Content-Type: text/html; charset=UTF-8
|
||||||
|
Cache-control: no-cache
|
||||||
|
Connection: close
|
||||||
|
Proxy-Connection: close
|
||||||
|
|
||||||
|
<html><head>
|
||||||
|
<title>I2P Warning: Bad Address Helper</title>
|
||||||
|
<link rel="shortcut icon" href="http://proxy.i2p/themes/console/images/favicon.ico" >
|
||||||
|
<link href="http://proxy.i2p/themes/console/default/console.css" rel="stylesheet" type="text/css" >
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div class=logo>
|
||||||
|
<a href="http://127.0.0.1:7657/index.jsp" title="Router Console"><img src="http://proxy.i2p/themes/console/images/i2plogo.png" alt="I2P Router Console" border="0"></a><hr>
|
||||||
|
<a href="http://127.0.0.1:7657/config.jsp">Configuration</a> <a href="http://127.0.0.1:7657/help.jsp">Help</a> <a href="http://127.0.0.1:7657/susidns/">Addressbook</a>
|
||||||
|
</div>
|
||||||
|
<div class=warning id=warning>
|
||||||
|
<h3>Warning: Bad Address Helper</h3>
|
||||||
|
<p>
|
||||||
|
The helper key you put for i2paddresshelper= is not resolvable.
|
||||||
|
It seems to be garbage data, or a mistyped b32. Check your URL
|
||||||
|
to try and fix the helper key to be a valid Base 32 hostname or Base 64 key.
|
||||||
|
</p>
|
@@ -470,7 +470,7 @@ input {
|
|||||||
border: 1px inset #000;
|
border: 1px inset #000;
|
||||||
background: #212 url('/themes/snark/ubergine/images/graytile.png');
|
background: #212 url('/themes/snark/ubergine/images/graytile.png');
|
||||||
color: #f60;
|
color: #f60;
|
||||||
margin: 2px 0;
|
margin: 2px 4px;
|
||||||
}
|
}
|
||||||
|
|
||||||
input.r {
|
input.r {
|
||||||
@@ -525,12 +525,50 @@ input[type=radio] {
|
|||||||
vertical-align: bottom;
|
vertical-align: bottom;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
input.default { width: 1px; height: 1px; visibility: hidden; }
|
||||||
|
|
||||||
input.accept {
|
input.accept {
|
||||||
background: #989 url('../../console/images/accept.png') no-repeat 2px center;
|
background: #989 url('../../console/images/accept.png') no-repeat 2px center;
|
||||||
padding: 2px 3px 2px 20px !important;
|
padding: 2px 3px 2px 20px !important;
|
||||||
min-height: 22px;
|
min-height: 22px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
input.add {
|
||||||
|
background: #989 url('../../console/images/add.png') no-repeat 2px center;
|
||||||
|
padding: 2px 3px 2px 20px !important;
|
||||||
|
min-height: 22px;
|
||||||
|
}
|
||||||
|
|
||||||
|
input.create {
|
||||||
|
background: #989 url('images/create.png') no-repeat 2px center;
|
||||||
|
padding: 2px 3px 2px 20px !important;
|
||||||
|
min-height: 22px;
|
||||||
|
}
|
||||||
|
|
||||||
|
input.cancel {
|
||||||
|
background: #989 url('../../console/images/cancel.png') no-repeat 2px center;
|
||||||
|
padding: 2px 3px 2px 20px !important;
|
||||||
|
min-height: 22px;
|
||||||
|
}
|
||||||
|
|
||||||
|
input.create {
|
||||||
|
background: #989 url('images/create.png') no-repeat 2px center;
|
||||||
|
padding: 2px 3px 2px 20px !important;
|
||||||
|
min-height: 22px;
|
||||||
|
}
|
||||||
|
|
||||||
|
input.delete {
|
||||||
|
background: #989 url('../../console/images/delete.png') no-repeat 2px center;
|
||||||
|
padding: 2px 3px 2px 20px !important;
|
||||||
|
min-height: 22px;
|
||||||
|
}
|
||||||
|
|
||||||
|
input.reload {
|
||||||
|
background: #989 url('../../console/images/arrow_refresh.png') no-repeat 2px center;
|
||||||
|
padding: 2px 3px 2px 20px !important;
|
||||||
|
min-height: 22px;
|
||||||
|
}
|
||||||
|
|
||||||
select {
|
select {
|
||||||
background: #333;
|
background: #333;
|
||||||
background: url('/themes/snark/ubergine/images/graytile.png') !important;
|
background: url('/themes/snark/ubergine/images/graytile.png') !important;
|
||||||
|
@@ -493,7 +493,7 @@ input {
|
|||||||
border: 1px inset #000;
|
border: 1px inset #000;
|
||||||
background: #fff /*url('/themes/snark/ubergine/images/graytile.png')*/;
|
background: #fff /*url('/themes/snark/ubergine/images/graytile.png')*/;
|
||||||
color: #000;
|
color: #000;
|
||||||
margin: 2px 0;
|
margin: 2px 4px;
|
||||||
}
|
}
|
||||||
|
|
||||||
input.r {
|
input.r {
|
||||||
@@ -549,12 +549,44 @@ input[type=radio] {
|
|||||||
vertical-align: bottom;
|
vertical-align: bottom;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
input.default { width: 1px; height: 1px; visibility: hidden; }
|
||||||
|
|
||||||
input.accept {
|
input.accept {
|
||||||
background: #f3efc7 url('../../console/images/accept.png') no-repeat 2px center;
|
background: #f3efc7 url('../../console/images/accept.png') no-repeat 2px center;
|
||||||
padding: 2px 3px 2px 20px !important;
|
padding: 2px 3px 2px 20px !important;
|
||||||
min-height: 22px;
|
min-height: 22px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
input.add {
|
||||||
|
background: #f3efc7 url('../../console/images/add.png') no-repeat 2px center;
|
||||||
|
padding: 2px 3px 2px 20px !important;
|
||||||
|
min-height: 22px;
|
||||||
|
}
|
||||||
|
|
||||||
|
input.cancel {
|
||||||
|
background: #f3efc7 url('../../console/images/cancel.png') no-repeat 2px center;
|
||||||
|
padding: 2px 3px 2px 20px !important;
|
||||||
|
min-height: 22px;
|
||||||
|
}
|
||||||
|
|
||||||
|
input.create {
|
||||||
|
background: #f3efc7 url('images/create.png') no-repeat 2px center;
|
||||||
|
padding: 2px 3px 2px 20px !important;
|
||||||
|
min-height: 22px;
|
||||||
|
}
|
||||||
|
|
||||||
|
input.delete {
|
||||||
|
background: #f3efc7 url('../../console/images/delete.png') no-repeat 2px center;
|
||||||
|
padding: 2px 3px 2px 20px !important;
|
||||||
|
min-height: 22px;
|
||||||
|
}
|
||||||
|
|
||||||
|
input.reload {
|
||||||
|
background: #f3efc7 url('../../console/images/arrow_refresh.png') no-repeat 2px center;
|
||||||
|
padding: 2px 3px 2px 20px !important;
|
||||||
|
min-height: 22px;
|
||||||
|
}
|
||||||
|
|
||||||
select {
|
select {
|
||||||
background: #fff;
|
background: #fff;
|
||||||
/* background: url('/themes/snark/ubergine/images/graytile.png') !important;*/
|
/* background: url('/themes/snark/ubergine/images/graytile.png') !important;*/
|
||||||
|
@@ -73,6 +73,7 @@
|
|||||||
<jar destfile="./build/router.jar" basedir="./build/obj" includes="**/*.class" >
|
<jar destfile="./build/router.jar" basedir="./build/obj" includes="**/*.class" >
|
||||||
<manifest>
|
<manifest>
|
||||||
<attribute name="Implementation-Version" value="${full.version}" />
|
<attribute name="Implementation-Version" value="${full.version}" />
|
||||||
|
<attribute name="Built-By" value="${build.built-by}" />
|
||||||
<attribute name="Build-Date" value="${build.timestamp}" />
|
<attribute name="Build-Date" value="${build.timestamp}" />
|
||||||
<attribute name="Base-Revision" value="${workspace.version}" />
|
<attribute name="Base-Revision" value="${workspace.version}" />
|
||||||
<attribute name="Workspace-Changes" value="${workspace.changes.tr}" />
|
<attribute name="Workspace-Changes" value="${workspace.changes.tr}" />
|
||||||
|
@@ -479,15 +479,9 @@ public class Blocklist {
|
|||||||
List<byte[]> rv = new ArrayList(1);
|
List<byte[]> rv = new ArrayList(1);
|
||||||
RouterInfo pinfo = _context.netDb().lookupRouterInfoLocally(peer);
|
RouterInfo pinfo = _context.netDb().lookupRouterInfoLocally(peer);
|
||||||
if (pinfo == null) return rv;
|
if (pinfo == null) return rv;
|
||||||
Set<RouterAddress> paddr = pinfo.getAddresses();
|
|
||||||
if (paddr == null || paddr.isEmpty())
|
|
||||||
return rv;
|
|
||||||
String oldphost = null;
|
String oldphost = null;
|
||||||
List<RouterAddress> pladdr = new ArrayList(paddr);
|
|
||||||
// for each peer address
|
// for each peer address
|
||||||
for (int j = 0; j < paddr.size(); j++) {
|
for (RouterAddress pa : pinfo.getAddresses()) {
|
||||||
RouterAddress pa = (RouterAddress) pladdr.get(j);
|
|
||||||
if (pa == null) continue;
|
|
||||||
String phost = pa.getOption("host");
|
String phost = pa.getOption("host");
|
||||||
if (phost == null) continue;
|
if (phost == null) continue;
|
||||||
if (oldphost != null && oldphost.equals(phost)) continue;
|
if (oldphost != null && oldphost.equals(phost)) continue;
|
||||||
@@ -787,7 +781,7 @@ public class Blocklist {
|
|||||||
Set<Integer> singles = new TreeSet();
|
Set<Integer> singles = new TreeSet();
|
||||||
singles.addAll(_singleIPBlocklist);
|
singles.addAll(_singleIPBlocklist);
|
||||||
if (!singles.isEmpty()) {
|
if (!singles.isEmpty()) {
|
||||||
out.write("<table><tr><th align=center colspan=2><b>");
|
out.write("<table><tr><th align=\"center\" colspan=\"2\"><b>");
|
||||||
out.write(_("IPs Banned Until Restart"));
|
out.write(_("IPs Banned Until Restart"));
|
||||||
out.write("</b></td></tr>");
|
out.write("</b></td></tr>");
|
||||||
// first 0 - 127
|
// first 0 - 127
|
||||||
@@ -795,27 +789,27 @@ public class Blocklist {
|
|||||||
int ip = ii.intValue();
|
int ip = ii.intValue();
|
||||||
if (ip < 0)
|
if (ip < 0)
|
||||||
continue;
|
continue;
|
||||||
out.write("<tr><td align=center width=50%>");
|
out.write("<tr><td align=\"center\" width=\"50%\">");
|
||||||
out.write(toStr(ip));
|
out.write(toStr(ip));
|
||||||
out.write("</td><td width=50%> </td></tr>\n");
|
out.write("</td><td width=\"50%\"> </td></tr>\n");
|
||||||
}
|
}
|
||||||
// then 128 - 255
|
// then 128 - 255
|
||||||
for (Integer ii : singles) {
|
for (Integer ii : singles) {
|
||||||
int ip = ii.intValue();
|
int ip = ii.intValue();
|
||||||
if (ip >= 0)
|
if (ip >= 0)
|
||||||
break;
|
break;
|
||||||
out.write("<tr><td align=center width=50%>");
|
out.write("<tr><td align=\"center\" width=\"50%\">");
|
||||||
out.write(toStr(ip));
|
out.write(toStr(ip));
|
||||||
out.write("</td><td width=50%> </td></tr>\n");
|
out.write("</td><td width=\"50%\"> </td></tr>\n");
|
||||||
}
|
}
|
||||||
out.write("</table>");
|
out.write("</table>");
|
||||||
}
|
}
|
||||||
if (_blocklistSize > 0) {
|
if (_blocklistSize > 0) {
|
||||||
out.write("<table><tr><th align=center colspan=2><b>");
|
out.write("<table><tr><th align=\"center\" colspan=\"2\"><b>");
|
||||||
out.write(_("IPs Permanently Banned"));
|
out.write(_("IPs Permanently Banned"));
|
||||||
out.write("</b></th></tr><tr><td align=center width=50%><b>");
|
out.write("</b></th></tr><tr><td align=\"center\" width=\"50%\"><b>");
|
||||||
out.write(_("From"));
|
out.write(_("From"));
|
||||||
out.write("</b></td><td align=center width=50%><b>");
|
out.write("</b></td><td align=\"center\" width=\"50%\"><b>");
|
||||||
out.write(_("To"));
|
out.write(_("To"));
|
||||||
out.write("</b></td></tr>");
|
out.write("</b></td></tr>");
|
||||||
int max = Math.min(_blocklistSize, MAX_DISPLAY);
|
int max = Math.min(_blocklistSize, MAX_DISPLAY);
|
||||||
@@ -825,7 +819,7 @@ public class Blocklist {
|
|||||||
int from = getFrom(_blocklist[i]);
|
int from = getFrom(_blocklist[i]);
|
||||||
if (from < 0)
|
if (from < 0)
|
||||||
continue;
|
continue;
|
||||||
out.write("<tr><td align=center width=50%>"); out.write(toStr(from)); out.write("</td><td align=center width=50%>");
|
out.write("<tr><td align=\"center\" width=\"50%\">"); out.write(toStr(from)); out.write("</td><td align=\"center\" width=\"50%\">");
|
||||||
int to = getTo(_blocklist[i]);
|
int to = getTo(_blocklist[i]);
|
||||||
if (to != from) {
|
if (to != from) {
|
||||||
out.write(toStr(to)); out.write("</td></tr>\n");
|
out.write(toStr(to)); out.write("</td></tr>\n");
|
||||||
@@ -838,7 +832,7 @@ public class Blocklist {
|
|||||||
int from = getFrom(_blocklist[i]);
|
int from = getFrom(_blocklist[i]);
|
||||||
if (from >= 0)
|
if (from >= 0)
|
||||||
break;
|
break;
|
||||||
out.write("<tr><td align=center width=50%>"); out.write(toStr(from)); out.write("</td><td align=center width=50%>");
|
out.write("<tr><td align=\"center\" width=\"50%\">"); out.write(toStr(from)); out.write("</td><td align=\"center\" width=\"50%\">");
|
||||||
int to = getTo(_blocklist[i]);
|
int to = getTo(_blocklist[i]);
|
||||||
if (to != from) {
|
if (to != from) {
|
||||||
out.write(toStr(to)); out.write("</td></tr>\n");
|
out.write(toStr(to)); out.write("</td></tr>\n");
|
||||||
|
@@ -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 = 0;
|
public final static long BUILD = 1;
|
||||||
|
|
||||||
/** for example "-test" */
|
/** for example "-test" */
|
||||||
public final static String EXTRA = "";
|
public final static String EXTRA = "";
|
||||||
|
@@ -85,7 +85,7 @@ public class StatisticsManager implements Service {
|
|||||||
if (_context.getBooleanPropertyDefaultTrue(PROP_PUBLISH_RANKINGS)) {
|
if (_context.getBooleanPropertyDefaultTrue(PROP_PUBLISH_RANKINGS)) {
|
||||||
long publishedUptime = _context.router().getUptime();
|
long publishedUptime = _context.router().getUptime();
|
||||||
// Don't publish these for first hour
|
// Don't publish these for first hour
|
||||||
if (publishedUptime > 62*60*1000)
|
if (publishedUptime > 62*60*1000 && CoreVersion.VERSION.equals("0.8.13"))
|
||||||
includeAverageThroughput(stats);
|
includeAverageThroughput(stats);
|
||||||
//includeRate("router.invalidMessageTime", stats, new long[] { 10*60*1000 });
|
//includeRate("router.invalidMessageTime", stats, new long[] { 10*60*1000 });
|
||||||
//includeRate("router.duplicateMessageId", stats, new long[] { 24*60*60*1000 });
|
//includeRate("router.duplicateMessageId", stats, new long[] { 24*60*60*1000 });
|
||||||
|
@@ -239,13 +239,13 @@ class ClientConnectionRunner {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Send a DisconnectMessage and log with level Log.CRIT.
|
* Send a DisconnectMessage and log with level Log.ERROR.
|
||||||
* This is always bad.
|
* This is always bad.
|
||||||
* See ClientMessageEventListener.handleCreateSession()
|
* See ClientMessageEventListener.handleCreateSession()
|
||||||
* for why we don't send a SessionStatusMessage when we do this.
|
* for why we don't send a SessionStatusMessage when we do this.
|
||||||
*/
|
*/
|
||||||
void disconnectClient(String reason) {
|
void disconnectClient(String reason) {
|
||||||
disconnectClient(reason, Log.CRIT);
|
disconnectClient(reason, Log.ERROR);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -254,9 +254,10 @@ class ClientConnectionRunner {
|
|||||||
*/
|
*/
|
||||||
void disconnectClient(String reason, int logLevel) {
|
void disconnectClient(String reason, int logLevel) {
|
||||||
if (_log.shouldLog(logLevel))
|
if (_log.shouldLog(logLevel))
|
||||||
_log.log(logLevel, "Disconnecting the client ("
|
_log.log(logLevel, "Disconnecting the client - "
|
||||||
+ _config
|
+ reason
|
||||||
+ ") : " + reason);
|
+ " config: "
|
||||||
|
+ _config);
|
||||||
DisconnectMessage msg = new DisconnectMessage();
|
DisconnectMessage msg = new DisconnectMessage();
|
||||||
msg.setReason(reason);
|
msg.setReason(reason);
|
||||||
try {
|
try {
|
||||||
|
@@ -36,7 +36,7 @@ import net.i2p.util.Log;
|
|||||||
* @author jrandom
|
* @author jrandom
|
||||||
*/
|
*/
|
||||||
public class ClientManagerFacadeImpl extends ClientManagerFacade implements InternalClientManager {
|
public class ClientManagerFacadeImpl extends ClientManagerFacade implements InternalClientManager {
|
||||||
private final static Log _log = new Log(ClientManagerFacadeImpl.class);
|
private final Log _log;
|
||||||
private ClientManager _manager;
|
private ClientManager _manager;
|
||||||
private RouterContext _context;
|
private RouterContext _context;
|
||||||
/** note that this is different than the property the client side uses, i2cp.tcp.port */
|
/** note that this is different than the property the client side uses, i2cp.tcp.port */
|
||||||
@@ -48,7 +48,8 @@ public class ClientManagerFacadeImpl extends ClientManagerFacade implements Inte
|
|||||||
|
|
||||||
public ClientManagerFacadeImpl(RouterContext context) {
|
public ClientManagerFacadeImpl(RouterContext context) {
|
||||||
_context = context;
|
_context = context;
|
||||||
_log.debug("Client manager facade created");
|
_log = _context.logManager().getLog(ClientManagerFacadeImpl.class);
|
||||||
|
//_log.debug("Client manager facade created");
|
||||||
}
|
}
|
||||||
|
|
||||||
public void startup() {
|
public void startup() {
|
||||||
|
@@ -27,13 +27,13 @@ import net.i2p.util.Log;
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
class RequestLeaseSetJob extends JobImpl {
|
class RequestLeaseSetJob extends JobImpl {
|
||||||
private Log _log;
|
private final Log _log;
|
||||||
private ClientConnectionRunner _runner;
|
private final ClientConnectionRunner _runner;
|
||||||
private LeaseSet _ls;
|
private final LeaseSet _ls;
|
||||||
private long _expiration;
|
private final long _expiration;
|
||||||
private Job _onCreate;
|
private final Job _onCreate;
|
||||||
private Job _onFail;
|
private final Job _onFail;
|
||||||
private LeaseRequestState _requestState;
|
private final LeaseRequestState _requestState;
|
||||||
|
|
||||||
public RequestLeaseSetJob(RouterContext ctx, ClientConnectionRunner runner, LeaseSet set, long expiration, Job onCreate, Job onFail, LeaseRequestState state) {
|
public RequestLeaseSetJob(RouterContext ctx, ClientConnectionRunner runner, LeaseSet set, long expiration, Job onCreate, Job onFail, LeaseRequestState state) {
|
||||||
super(ctx);
|
super(ctx);
|
||||||
@@ -92,8 +92,8 @@ class RequestLeaseSetJob extends JobImpl {
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
private class CheckLeaseRequestStatus extends JobImpl {
|
private class CheckLeaseRequestStatus extends JobImpl {
|
||||||
private LeaseRequestState _req;
|
private final LeaseRequestState _req;
|
||||||
private long _start;
|
private final long _start;
|
||||||
|
|
||||||
public CheckLeaseRequestStatus(RouterContext enclosingContext, LeaseRequestState state) {
|
public CheckLeaseRequestStatus(RouterContext enclosingContext, LeaseRequestState state) {
|
||||||
super(enclosingContext);
|
super(enclosingContext);
|
||||||
@@ -114,9 +114,9 @@ class RequestLeaseSetJob extends JobImpl {
|
|||||||
return;
|
return;
|
||||||
} else {
|
} else {
|
||||||
RequestLeaseSetJob.CheckLeaseRequestStatus.this.getContext().statManager().addRateData("client.requestLeaseSetTimeout", 1, 0);
|
RequestLeaseSetJob.CheckLeaseRequestStatus.this.getContext().statManager().addRateData("client.requestLeaseSetTimeout", 1, 0);
|
||||||
if (_log.shouldLog(Log.CRIT)) {
|
if (_log.shouldLog(Log.ERROR)) {
|
||||||
long waited = System.currentTimeMillis() - _start;
|
long waited = System.currentTimeMillis() - _start;
|
||||||
_log.log(Log.CRIT, "Failed to receive a leaseSet in the time allotted (" + waited + "): " + _req + " for "
|
_log.error("Failed to receive a leaseSet in the time allotted (" + waited + "): " + _req + " for "
|
||||||
+ _runner.getConfig().getDestination().calculateHash().toBase64());
|
+ _runner.getConfig().getDestination().calculateHash().toBase64());
|
||||||
}
|
}
|
||||||
_runner.disconnectClient("Took too long to request leaseSet");
|
_runner.disconnectClient("Took too long to request leaseSet");
|
||||||
|